/*
 *
 *
 *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include "pvrusb2-ioread.h"
#include "pvrusb2-debug.h"
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <asm/uaccess.h>

#define BUFFER_COUNT 32
#define BUFFER_SIZE PAGE_ALIGN(0x4000)

struct pvr2_ioread {
	struct pvr2_stream *stream;
	char *buffer_storage[BUFFER_COUNT];
	char *sync_key_ptr;
	unsigned int sync_key_len;
	unsigned int sync_buf_offs;
	unsigned int sync_state;
	unsigned int sync_trashed_count;
	int enabled;         // Streaming is on
	int spigot_open;     // OK to pass data to client
	int stream_running;  // Passing data to client now

	/* State relevant to current buffer being read */
	struct pvr2_buffer *c_buf;
	char *c_data_ptr;
	unsigned int c_data_len;
	unsigned int c_data_offs;
	struct mutex mutex;
};

static int pvr2_ioread_init(struct pvr2_ioread *cp)
{
	unsigned int idx;

	cp->stream = NULL;
	mutex_init(&cp->mutex);

	for (idx = 0; idx < BUFFER_COUNT; idx++) {
		cp->buffer_storage[idx] = kmalloc(BUFFER_SIZE,GFP_KERNEL);
		if (!(cp->buffer_storage[idx])) break;
	}

	if (idx < BUFFER_COUNT) {
		// An allocation appears to have failed
		for (idx = 0; idx < BUFFER_COUNT; idx++) {
			if (!(cp->buffer_storage[idx])) continue;
			kfree(cp->buffer_storage[idx]);
		}
		return -ENOMEM;
	}
	return 0;
}

static void pvr2_ioread_done(struct pvr2_ioread *cp)
{
	unsigned int idx;

	pvr2_ioread_setup(cp,NULL);
	for (idx = 0; idx < BUFFER_COUNT; idx++) {
		if (!(cp->buffer_storage[idx])) continue;
		kfree(cp->buffer_storage[idx]);
	}
}

struct pvr2_ioread *pvr2_ioread_create(void)
{
	struct pvr2_ioread *cp;
	cp = kzalloc(sizeof(*cp),GFP_KERNEL);
	if (!cp) return NULL;
	pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_create id=%p",cp);
	if (pvr2_ioread_init(cp) < 0) {
		kfree(cp);
		return NULL;
	}
	return cp;
}

void pvr2_ioread_destroy(struct pvr2_ioread *cp)
{
	if (!cp) return;
	pvr2_ioread_done(cp);
	pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_destroy id=%p",cp);
	if (cp->sync_key_ptr) {
		kfree(cp->sync_key_ptr);
		cp->sync_key_ptr = NULL;
	}
	kfree(cp);
}

void pvr2_ioread_set_sync_key(struct pvr2_ioread *cp,
			      const char *sync_key_ptr,
			      unsigned int sync_key_len)
{
	if (!cp) return;

	if (!sync_key_ptr) sync_key_len = 0;
	if ((sync_key_len == cp->sync_key_len) &&
	    ((!sync_key_len) ||
	     (!memcmp(sync_key_ptr,cp->sync_key_ptr,sync_key_len)))) return;

	if (sync_key_len != cp->sync_key_len) {
		if (cp->sync_key_ptr) {
			kfree(cp->sync_key_ptr);
			cp->sync_key_ptr = NULL;
		}
		cp->sync_key_len = 0;
		if (sync_key_len) {
			cp->sync_key_ptr = kmalloc(sync_key_len,GFP_KERNEL);
			if (cp->sync_key_ptr) {
				cp->sync_key_len = sync_key_len;
			}
		}
	}
	if (!cp->sync_key_len) return;
	memcpy(cp->sync_key_ptr,sync_key_ptr,cp->sync_key_len);
}

static void pvr2_ioread_stop(struct pvr2_ioread *cp)
{
	if (!(cp->enabled)) return;
	pvr2_trace(PVR2_TRACE_START_STOP,
		   "/*---TRACE_READ---*/ pvr2_ioread_stop id=%p",cp);
	pvr2_stream_kill(cp->stream);
	cp->c_buf = NULL;
	cp->c_data_ptr = NULL;
	cp->c_data_len = 0;
	cp->c_data_offs = 0;
	cp->enabled = 0;
	cp->stream_running = 0;
	cp->spigot_open = 0;
	if (cp->sync_state) {
		pvr2_trace(PVR2_TRACE_DATA_FLOW,
			   "/*---TRACE_READ---*/ sync_state <== 0");
		cp->sync_state = 0;
	}
}

static int pvr2_ioread_start(struct pvr2_ioread *cp)
{
	int stat;
	struct pvr2_buffer *bp;
	if (cp->enabled) return 0;
	if (!(cp->stream)) return 0;
	pvr2_trace(PVR2_TRACE_START_STOP,
		   "/*---TRACE_READ---*/ pvr2_ioread_start id=%p",cp);
	while ((bp = pvr2_stream_get_idle_buffer(cp->stream)) != NULL) {
		stat = pvr2_buffer_queue(bp);
		if (stat < 0) {
			pvr2_trace(PVR2_TRACE_DATA_FLOW,
				   "/*---TRACE_READ---*/"
				   " pvr2_ioread_start id=%p"
				   " error=%d",
				   cp,stat);
			pvr2_ioread_stop(cp);
			return stat;
		}
	}
	cp->enabled = !0;
	cp->c_buf = NULL;
	cp->c_data_ptr = NULL;
	cp->c_data_len = 0;
	cp->c_data_offs = 0;
	cp->stream_running = 0;
	if (cp->sync_key_len) {
		pvr2_trace(PVR2_TRACE_DATA_FLOW,
			   "/*---TRACE_READ---*/ sync_state <== 1");
		cp->sync_state = 1;
		cp->sync_trashed_count = 0;
		cp->sync_buf_offs = 0;
	}
	cp->spigot_open = 0;
	return 0;
}

struct pvr2_stream *pvr2_ioread_get_stream(struct pvr2_ioread *cp)
{
	return cp->stream;
}

int pvr2_ioread_setup(struct pvr2_ioread *cp,struct pvr2_stream *sp)
{
	int ret;
	unsigned int idx;
	struct pvr2_buffer *bp;

	mutex_lock(&cp->mutex); do {
		if (cp->stream) {
			pvr2_trace(PVR2_TRACE_START_STOP,
				   "/*---TRACE_READ---*/"
				   " pvr2_ioread_setup (tear-down) id=%p",cp);
			pvr2_ioread_stop(cp);
			pvr2_stream_kill(cp->stream);
			if (pvr2_stream_get_buffer_count(cp->stream)) {
				pvr2_stream_set_buffer_count(cp->stream,0);
			}
			cp->stream = NULL;
		}
		if (sp) {
			pvr2_trace(PVR2_TRACE_START_STOP,
				   "/*---TRACE_READ---*/"
				   " pvr2_ioread_setup (setup) id=%p",cp);
			pvr2_stream_kill(sp);
			ret = pvr2_stream_set_buffer_count(sp,BUFFER_COUNT);
			if (ret < 0) return ret;
			for (idx = 0; idx < BUFFER_COUNT; idx++) {
				bp = pvr2_stream_get_buffer(sp,idx);
				pvr2_buffer_set_buffer(bp,
						       cp->buffer_storage[idx],
						       BUFFER_SIZE);
			}
			cp->stream = sp;
		}
	} while (0); mutex_unlock(&cp->mutex);

	return 0;
}

int pvr2_ioread_set_enabled(struct pvr2_ioread *cp,int fl)
{
	int ret = 0;
	if ((!fl) == (!(cp->enabled))) return ret;

	mutex_lock(&cp->mutex); do {
		if (fl) {
			ret = pvr2_ioread_start(cp);
		} else {
			pvr2_ioread_stop(cp);
		}
	} while (0); mutex_unlock(&cp->mutex);
	return ret;
}

static int pvr2_ioread_get_buffer(struct pvr2_ioread *cp)
{
	int stat;

	while (cp->c_data_len <= cp->c_data_offs) {
		if (cp->c_buf) {
			// Flush out current buffer first.
			stat = pvr2_buffer_queue(cp->c_buf);
			if (stat < 0) {
				// Streaming error...
				pvr2_trace(PVR2_TRACE_DATA_FLOW,
					   "/*---TRACE_READ---*/"
					   " pvr2_ioread_read id=%p"
					   " queue_error=%d",
					   cp,stat);
				pvr2_ioread_stop(cp);
				return 0;
			}
			cp->c_buf = NULL;
			cp->c_data_ptr = NULL;
			cp->c_data_len = 0;
			cp->c_data_offs = 0;
		}
		// Now get a freshly filled buffer.
		cp->c_buf = pvr2_stream_get_ready_buffer(cp->stream);
		if (!cp->c_buf) break; // Nothing ready; done.
		cp->c_data_len = pvr2_buffer_get_count(cp->c_buf);
		if (!cp->c_data_len) {
			// Nothing transferred.  Was there an error?
			stat = pvr2_buffer_get_status(cp->c_buf);
			if (stat < 0) {
				// Streaming error...
				pvr2_trace(PVR2_TRACE_DATA_FLOW,
					   "/*---TRACE_READ---*/"
					   " pvr2_ioread_read id=%p"
					   " buffer_error=%d",
					   cp,stat);
				pvr2_ioread_stop(cp);
				// Give up.
				return 0;
			}
			// Start over...
			continue;
		}
		cp->c_data_offs = 0;
		cp->c_data_ptr = cp->buffer_storage[
			pvr2_buffer_get_id(cp->c_buf)];
	}
	return !0;
}

static void pvr2_ioread_filter(struct pvr2_ioread *cp)
{
	unsigned int idx;
	if (!cp->enabled) return;
	if (cp->sync_state != 1) return;

	// Search the stream for our synchronization key.  This is made
	// complicated by the fact that in order to be honest with
	// ourselves here we must search across buffer boundaries...
	mutex_lock(&cp->mutex); while (1) {
		// Ensure we have a buffer
		if (!pvr2_ioread_get_buffer(cp)) break;
		if (!cp->c_data_len) break;

		// Now walk the buffer contents until we match the key or
		// run out of buffer data.
		for (idx = cp->c_data_offs; idx < cp->c_data_len; idx++) {
			if (cp->sync_buf_offs >= cp->sync_key_len) break;
			if (cp->c_data_ptr[idx] ==
			    cp->sync_key_ptr[cp->sync_buf_offs]) {
				// Found the next key byte
				(cp->sync_buf_offs)++;
			} else {
				// Whoops, mismatched.  Start key over...
				cp->sync_buf_offs = 0;
			}
		}

		// Consume what we've walked through
		cp->c_data_offs += idx;
		cp->sync_trashed_count += idx;

		// If we've found the key, then update state and get out.
		if (cp->sync_buf_offs >= cp->sync_key_len) {
			cp->sync_trashed_count -= cp->sync_key_len;
			pvr2_trace(PVR2_TRACE_DATA_FLOW,
				   "/*---TRACE_READ---*/"
				   " sync_state <== 2 (skipped %u bytes)",
				   cp->sync_trashed_count);
			cp->sync_state = 2;
			cp->sync_buf_offs = 0;
			break;
		}

		if (cp->c_data_offs < cp->c_data_len) {
			// Sanity check - should NEVER get here
			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
				   "ERROR: pvr2_ioread filter sync problem"
				   " len=%u offs=%u",
				   cp->c_data_len,cp->c_data_offs);
			// Get out so we don't get stuck in an infinite
			// loop.
			break;
		}

		continue; // (for clarity)
	} mutex_unlock(&cp->mutex);
}

int pvr2_ioread_avail(struct pvr2_ioread *cp)
{
	int ret;
	if (!(cp->enabled)) {
		// Stream is not enabled; so this is an I/O error
		return -EIO;
	}

	if (cp->sync_state == 1) {
		pvr2_ioread_filter(cp);
		if (cp->sync_state == 1) return -EAGAIN;
	}

	ret = 0;
	if (cp->stream_running) {
		if (!pvr2_stream_get_ready_count(cp->stream)) {
			// No data available at all right now.
			ret = -EAGAIN;
		}
	} else {
		if (pvr2_stream_get_ready_count(cp->stream) < BUFFER_COUNT/2) {
			// Haven't buffered up enough yet; try again later
			ret = -EAGAIN;
		}
	}

	if ((!(cp->spigot_open)) != (!(ret == 0))) {
		cp->spigot_open = (ret == 0);
		pvr2_trace(PVR2_TRACE_DATA_FLOW,
			   "/*---TRACE_READ---*/ data is %s",
			   cp->spigot_open ? "available" : "pending");
	}

	return ret;
}

int pvr2_ioread_read(struct pvr2_ioread *cp,void __user *buf,unsigned int cnt)
{
	unsigned int copied_cnt;
	unsigned int bcnt;
	const char *src;
	int stat;
	int ret = 0;
	unsigned int req_cnt = cnt;

	if (!cnt) {
		pvr2_trace(PVR2_TRACE_TRAP,
			   "/*---TRACE_READ---*/ pvr2_ioread_read id=%p"
			   " ZERO Request? Returning zero.",cp);
		return 0;
	}

	stat = pvr2_ioread_avail(cp);
	if (stat < 0) return stat;

	cp->stream_running = !0;

	mutex_lock(&cp->mutex); do {

		// Suck data out of the buffers and copy to the user
		copied_cnt = 0;
		if (!buf) cnt = 0;
		while (1) {
			if (!pvr2_ioread_get_buffer(cp)) {
				ret = -EIO;
				break;
			}

			if (!cnt) break;

			if (cp->sync_state == 2) {
				// We're repeating the sync key data into
				// the stream.
				src = cp->sync_key_ptr + cp->sync_buf_offs;
				bcnt = cp->sync_key_len - cp->sync_buf_offs;
			} else {
				// Normal buffer copy
				src = cp->c_data_ptr + cp->c_data_offs;
				bcnt = cp->c_data_len - cp->c_data_offs;
			}

			if (!bcnt) break;

			// Don't run past user's buffer
			if (bcnt > cnt) bcnt = cnt;

			if (copy_to_user(buf,src,bcnt)) {
				// User supplied a bad pointer?
				// Give up - this *will* cause data
				// to be lost.
				ret = -EFAULT;
				break;
			}
			cnt -= bcnt;
			buf += bcnt;
			copied_cnt += bcnt;

			if (cp->sync_state == 2) {
				// Update offset inside sync key that we're
				// repeating back out.
				cp->sync_buf_offs += bcnt;
				if (cp->sync_buf_offs >= cp->sync_key_len) {
					// Consumed entire key; switch mode
					// to normal.
					pvr2_trace(PVR2_TRACE_DATA_FLOW,
						   "/*---TRACE_READ---*/"
						   " sync_state <== 0");
					cp->sync_state = 0;
				}
			} else {
				// Update buffer offset.
				cp->c_data_offs += bcnt;
			}
		}

	} while (0); mutex_unlock(&cp->mutex);

	if (!ret) {
		if (copied_cnt) {
			// If anything was copied, return that count
			ret = copied_cnt;
		} else {
			// Nothing copied; suggest to caller that another
			// attempt should be tried again later
			ret = -EAGAIN;
		}
	}

	pvr2_trace(PVR2_TRACE_DATA_FLOW,
		   "/*---TRACE_READ---*/ pvr2_ioread_read"
		   " id=%p request=%d result=%d",
		   cp,req_cnt,ret);
	return ret;
}


/*
  Stuff for Emacs to see, in order to encourage consistent editing style:
  *** Local Variables: ***
  *** mode: c ***
  *** fill-column: 75 ***
  *** tab-width: 8 ***
  *** c-basic-offset: 8 ***
  *** End: ***
  */
