/*
 *  $Id$
 *
 *  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-context.h"
#include "pvrusb2-io.h"
#include "pvrusb2-ioread.h"
#include "pvrusb2-hdw.h"
#include "pvrusb2-debug.h"
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <asm/semaphore.h>


static void pvr2_context_destroy(struct pvr2_context *mp)
{
	if (mp->hdw) pvr2_hdw_destroy(mp->hdw);
	pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr_main id=%p",mp);
	flush_workqueue(mp->workqueue);
	destroy_workqueue(mp->workqueue);
	kfree(mp);
}


static void pvr2_context_trigger_poll(struct pvr2_context *mp)
{
	queue_work(mp->workqueue,&mp->workpoll);
}


static void pvr2_context_poll(struct pvr2_context *mp)
{
	pvr2_context_enter(mp); do {
		pvr2_hdw_poll(mp->hdw);
	} while (0); pvr2_context_exit(mp);
}


static void pvr2_context_setup(struct pvr2_context *mp)
{
	pvr2_context_enter(mp); do {
		if (!pvr2_hdw_dev_ok(mp->hdw)) break;
		pvr2_hdw_setup(mp->hdw);
		pvr2_hdw_setup_poll_trigger(
			mp->hdw,
			(void (*)(void *))pvr2_context_trigger_poll,
			mp);
		if (!pvr2_hdw_dev_ok(mp->hdw)) break;
		if (!pvr2_hdw_init_ok(mp->hdw)) break;
		mp->video_stream.stream = pvr2_hdw_get_video_stream(mp->hdw);
		if (mp->setup_func) {
			mp->setup_func(mp);
		}
	} while (0); pvr2_context_exit(mp);
}


struct pvr2_context *pvr2_context_create(
	struct usb_interface *intf,
	const struct usb_device_id *devid,
	void (*setup_func)(struct pvr2_context *))
{
	struct pvr2_context *mp = NULL;
	mp = kmalloc(sizeof(*mp),GFP_KERNEL);
	if (!mp) goto done;
	memset(mp,0,sizeof(*mp));
	pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_main id=%p",mp);
	mp->setup_func = setup_func;
	mutex_init(&mp->mutex);
	mp->hdw = pvr2_hdw_create(intf,devid);
	if (!mp->hdw) {
		pvr2_context_destroy(mp);
		mp = NULL;
		goto done;
	}

	mp->workqueue = create_singlethread_workqueue("pvrusb2");
	INIT_WORK(&mp->workinit,(void (*)(void*))pvr2_context_setup,mp);
	INIT_WORK(&mp->workpoll,(void (*)(void*))pvr2_context_poll,mp);
	queue_work(mp->workqueue,&mp->workinit);
 done:
	return mp;
}


void pvr2_context_enter(struct pvr2_context *mp)
{
	mutex_lock(&mp->mutex);
	pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_enter(id=%p)",mp);
}


void pvr2_context_exit(struct pvr2_context *mp)
{
	int destroy_flag = 0;
	if (!(mp->mc_first || !mp->disconnect_flag)) {
		destroy_flag = !0;
	}
	pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_exit(id=%p) outside",mp);
	mutex_unlock(&mp->mutex);
	if (destroy_flag) pvr2_context_destroy(mp);
}


static void pvr2_context_run_checks(struct pvr2_context *mp)
{
	struct pvr2_channel *ch1,*ch2;
	for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
		ch2 = ch1->mc_next;
		if (ch1->check_func) {
			ch1->check_func(ch1);
		}
	}
}


void pvr2_context_disconnect(struct pvr2_context *mp)
{
	pvr2_context_enter(mp); do {
		pvr2_hdw_disconnect(mp->hdw);
		mp->disconnect_flag = !0;
		pvr2_context_run_checks(mp);
	} while (0); pvr2_context_exit(mp);
}


void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
{
	cp->hdw = mp->hdw;
	cp->mc_head = mp;
	cp->mc_next = NULL;
	cp->mc_prev = mp->mc_last;
	if (mp->mc_last) {
		mp->mc_last->mc_next = cp;
	} else {
		mp->mc_first = cp;
	}
	mp->mc_last = cp;
}


static void pvr2_channel_disclaim_stream(struct pvr2_channel *cp)
{
	if (!cp->stream) return;
	pvr2_stream_kill(cp->stream->stream);
	cp->stream->user = NULL;
	cp->stream = NULL;
}


void pvr2_channel_done(struct pvr2_channel *cp)
{
	struct pvr2_context *mp = cp->mc_head;
	pvr2_channel_disclaim_stream(cp);
	if (cp->mc_next) {
		cp->mc_next->mc_prev = cp->mc_prev;
	} else {
		mp->mc_last = cp->mc_prev;
	}
	if (cp->mc_prev) {
		cp->mc_prev->mc_next = cp->mc_next;
	} else {
		mp->mc_first = cp->mc_next;
	}
	cp->hdw = NULL;
}


int pvr2_channel_claim_stream(struct pvr2_channel *cp,
			      struct pvr2_context_stream *sp)
{
	int code = 0;
	pvr2_context_enter(cp->mc_head); do {
		if (sp == cp->stream) break;
		if (sp->user) {
			code = -EBUSY;
			break;
		}
		pvr2_channel_disclaim_stream(cp);
		if (!sp) break;
		sp->user = cp;
		cp->stream = sp;
	} while (0); pvr2_context_exit(cp->mc_head);
	return code;
}


// This is the marker for the real beginning of a legitimate mpeg2 stream.
static char stream_sync_key[] = {
	0x00, 0x00, 0x01, 0xba,
};

struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
	struct pvr2_context_stream *sp)
{
	struct pvr2_ioread *cp;
	cp = pvr2_ioread_create();
	if (!cp) return NULL;
	pvr2_ioread_setup(cp,sp->stream);
	pvr2_ioread_set_sync_key(cp,stream_sync_key,sizeof(stream_sync_key));
	return cp;
}


/*
  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: ***
  */
