summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb/dibusb/dvb-dibusb-pid.c
blob: 91a39541d52424286c0154d219717f0de3a34963 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/*
 * dvb-dibusb-pid.c is part of the driver for mobile USB Budget DVB-T devices 
 * based on reference design made by DiBcom (http://www.dibcom.fr/)
 *
 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
 *
 * see dvb-dibusb-core.c for more copyright details.
 *
 * This file contains functions for initializing and handling the internal
 * pid-list. This pid-list mirrors the information currently stored in the
 * devices pid-list.
 */
#include "dvb-dibusb.h"

int dibusb_pid_list_init(struct usb_dibusb *dib)
{
	int i;
	dib->pid_list = kmalloc(sizeof(struct dibusb_pid) * dib->dibdev->dev_cl->demod->pid_filter_count,GFP_KERNEL);
	if (dib->pid_list == NULL)
		return -ENOMEM;

	deb_xfer("initializing %d pids for the pid_list.\n",dib->dibdev->dev_cl->demod->pid_filter_count);
	
	dib->pid_list_lock = SPIN_LOCK_UNLOCKED;
	memset(dib->pid_list,0,dib->dibdev->dev_cl->demod->pid_filter_count*(sizeof(struct dibusb_pid)));
	for (i=0; i < dib->dibdev->dev_cl->demod->pid_filter_count; i++) {
		dib->pid_list[i].index = i;
		dib->pid_list[i].pid = 0;
		dib->pid_list[i].active = 0;
	}

	dib->init_state |= DIBUSB_STATE_PIDLIST;
	return 0;
}

void dibusb_pid_list_exit(struct usb_dibusb *dib)
{
	if (dib->init_state & DIBUSB_STATE_PIDLIST)
		kfree(dib->pid_list);
	dib->init_state &= ~DIBUSB_STATE_PIDLIST;
}

/* fetch a pid from pid_list and set it on or off */
int dibusb_ctrl_pid(struct usb_dibusb *dib, struct dvb_demux_feed *dvbdmxfeed , int onoff)
{
	int i,ret = -1;
	unsigned long flags;
	u16 pid = dvbdmxfeed->pid;

	if (onoff) {
		spin_lock_irqsave(&dib->pid_list_lock,flags);
		for (i=0; i < dib->dibdev->dev_cl->demod->pid_filter_count; i++)
			if (!dib->pid_list[i].active) {
				dib->pid_list[i].pid = pid;
				dib->pid_list[i].active = 1;
				ret = i;
				break;
			}
		dvbdmxfeed->priv = &dib->pid_list[ret];
		spin_unlock_irqrestore(&dib->pid_list_lock,flags);
		
		if (dib->xfer_ops.pid_ctrl != NULL) 
			dib->xfer_ops.pid_ctrl(dib->fe,dib->pid_list[ret].index,dib->pid_list[ret].pid,1);
	} else {
		struct dibusb_pid *dpid = dvbdmxfeed->priv;
		
		if (dib->xfer_ops.pid_ctrl != NULL) 
			dib->xfer_ops.pid_ctrl(dib->fe,dpid->index,0,0);
		
		dpid->pid = 0;
		dpid->active = 0;
		ret = dpid->index;
	}
	
	/* a free pid from the list */
	deb_info("setting pid: %5d %04x at index %d '%s'\n",pid,pid,ret,onoff ? "on" : "off");

	return ret;
}