diff options
Diffstat (limited to 'linux/drivers/media/dvb/dibusb/dvb-dibusb-pid.c')
-rw-r--r-- | linux/drivers/media/dvb/dibusb/dvb-dibusb-pid.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/linux/drivers/media/dvb/dibusb/dvb-dibusb-pid.c b/linux/drivers/media/dvb/dibusb/dvb-dibusb-pid.c new file mode 100644 index 000000000..91a39541d --- /dev/null +++ b/linux/drivers/media/dvb/dibusb/dvb-dibusb-pid.c @@ -0,0 +1,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; +} + |