This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / drivers / media / dvb / dibusb / dvb-dibusb-pid.c
1 /*
2  * dvb-dibusb-pid.c is part of the driver for mobile USB Budget DVB-T devices 
3  * based on reference design made by DiBcom (http://www.dibcom.fr/)
4  *
5  * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
6  *
7  * see dvb-dibusb-core.c for more copyright details.
8  *
9  * This file contains functions for initializing and handling the internal
10  * pid-list. This pid-list mirrors the information currently stored in the
11  * devices pid-list.
12  */
13 #include "dvb-dibusb.h"
14
15 int dibusb_pid_list_init(struct usb_dibusb *dib)
16 {
17         int i;
18         dib->pid_list = kmalloc(sizeof(struct dibusb_pid) * dib->dibdev->dev_cl->demod->pid_filter_count,GFP_KERNEL);
19         if (dib->pid_list == NULL)
20                 return -ENOMEM;
21
22         deb_xfer("initializing %d pids for the pid_list.\n",dib->dibdev->dev_cl->demod->pid_filter_count);
23         
24         dib->pid_list_lock = SPIN_LOCK_UNLOCKED;
25         memset(dib->pid_list,0,dib->dibdev->dev_cl->demod->pid_filter_count*(sizeof(struct dibusb_pid)));
26         for (i=0; i < dib->dibdev->dev_cl->demod->pid_filter_count; i++) {
27                 dib->pid_list[i].index = i;
28                 dib->pid_list[i].pid = 0;
29                 dib->pid_list[i].active = 0;
30         }
31
32         dib->init_state |= DIBUSB_STATE_PIDLIST;
33         return 0;
34 }
35
36 void dibusb_pid_list_exit(struct usb_dibusb *dib)
37 {
38         if (dib->init_state & DIBUSB_STATE_PIDLIST)
39                 kfree(dib->pid_list);
40         dib->init_state &= ~DIBUSB_STATE_PIDLIST;
41 }
42
43 /* fetch a pid from pid_list and set it on or off */
44 int dibusb_ctrl_pid(struct usb_dibusb *dib, struct dvb_demux_feed *dvbdmxfeed , int onoff)
45 {
46         int i,ret = -1;
47         unsigned long flags;
48         u16 pid = dvbdmxfeed->pid;
49
50         if (onoff) {
51                 spin_lock_irqsave(&dib->pid_list_lock,flags);
52                 for (i=0; i < dib->dibdev->dev_cl->demod->pid_filter_count; i++)
53                         if (!dib->pid_list[i].active) {
54                                 dib->pid_list[i].pid = pid;
55                                 dib->pid_list[i].active = 1;
56                                 ret = i;
57                                 break;
58                         }
59                 dvbdmxfeed->priv = &dib->pid_list[ret];
60                 spin_unlock_irqrestore(&dib->pid_list_lock,flags);
61                 
62                 if (dib->xfer_ops.pid_ctrl != NULL) 
63                         dib->xfer_ops.pid_ctrl(dib->fe,dib->pid_list[ret].index,dib->pid_list[ret].pid,1);
64         } else {
65                 struct dibusb_pid *dpid = dvbdmxfeed->priv;
66                 
67                 if (dib->xfer_ops.pid_ctrl != NULL) 
68                         dib->xfer_ops.pid_ctrl(dib->fe,dpid->index,0,0);
69                 
70                 dpid->pid = 0;
71                 dpid->active = 0;
72                 ret = dpid->index;
73         }
74         
75         /* a free pid from the list */
76         deb_info("setting pid: %5d %04x at index %d '%s'\n",pid,pid,ret,onoff ? "on" : "off");
77
78         return ret;
79 }
80