⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dvb-ttusb-budget.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
}static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len){	int maxwork = 1024;	while (len) {		if (!(maxwork--)) {			printk("%s: too much work\n", __FUNCTION__);			break;		}		switch (ttusb->mux_state) {		case 0:		case 1:		case 2:			len--;			if (*data++ == 0xAA)				++ttusb->mux_state;			else {				ttusb->mux_state = 0;#if DEBUG > 3				if (ttusb->insync)					printk("%02x ", data[-1]);#else				if (ttusb->insync) {					printk("%s: lost sync.\n",					       __FUNCTION__);					ttusb->insync = 0;				}#endif			}			break;		case 3:			ttusb->insync = 1;			len--;			ttusb->mux_npacks = *data++;			++ttusb->mux_state;			ttusb->muxpack_ptr = 0;			/* maximum bytes, until we know the length */			ttusb->muxpack_len = 2;			break;		case 4:			{				int avail;				avail = len;				if (avail >				    (ttusb->muxpack_len -				     ttusb->muxpack_ptr))					avail =					    ttusb->muxpack_len -					    ttusb->muxpack_ptr;				memcpy(ttusb->muxpack + ttusb->muxpack_ptr,				       data, avail);				ttusb->muxpack_ptr += avail;				if (ttusb->muxpack_ptr > 264)					BUG();				data += avail;				len -= avail;				/* determine length */				if (ttusb->muxpack_ptr == 2) {					if (ttusb->muxpack[0] & 0x80) {						ttusb->muxpack_len =						    ttusb->muxpack[1] + 2;						if (ttusb->						    muxpack[0] & 0x20)							ttusb->							    muxpack_len++;						if ((!!						     (ttusb->						      muxpack[0] & 0x20)) ^						    !!(ttusb->						       muxpack[1] & 1))							ttusb->							    muxpack_len++;						ttusb->muxpack_len += 4;					} else if (ttusb->muxpack[0] ==						   0x47)						ttusb->muxpack_len =						    188 + 4;					else if (ttusb->muxpack[0] == 0x00)						ttusb->muxpack_len =						    ttusb->muxpack[1] + 2 +						    4;					else {						dprintk						    ("%s: invalid state: first byte is %x\n",						     __FUNCTION__,						     ttusb->muxpack[0]);						ttusb->mux_state = 0;					}				}			/**			 * if length is valid and we reached the end:			 * goto next muxpack			 */				if ((ttusb->muxpack_ptr >= 2) &&				    (ttusb->muxpack_ptr ==				     ttusb->muxpack_len)) {					ttusb_process_muxpack(ttusb,							      ttusb->							      muxpack,							      ttusb->							      muxpack_ptr);					ttusb->muxpack_ptr = 0;					/* maximum bytes, until we know the length */					ttusb->muxpack_len = 2;				/**				 * no muxpacks left?				 * return to search-sync state				 */					if (!ttusb->mux_npacks--) {						ttusb->mux_state = 0;						break;					}				}				break;			}		default:			BUG();			break;		}	}}static void ttusb_iso_irq(struct urb *urb, struct pt_regs *ptregs){	struct ttusb *ttusb = urb->context;	if (!ttusb->iso_streaming)		return;#if 0	printk("%s: status %d, errcount == %d, length == %i\n",	       __FUNCTION__,	       urb->status, urb->error_count, urb->actual_length);#endif	if (!urb->status) {		int i;		for (i = 0; i < urb->number_of_packets; ++i) {			struct usb_iso_packet_descriptor *d;			u8 *data;			int len;			numpkt++;			if ((jiffies - lastj) >= HZ) {#if DEBUG > 2				printk				    ("frames/s: %d (ts: %d, stuff %d, sec: %d, invalid: %d, all: %d)\n",				     numpkt * HZ / (jiffies - lastj),				     numts, numstuff, numsec, numinvalid,				     numts + numstuff + numsec +				     numinvalid);#endif				numts = numstuff = numsec = numinvalid = 0;				lastj = jiffies;				numpkt = 0;			}			d = &urb->iso_frame_desc[i];			data = urb->transfer_buffer + d->offset;			len = d->actual_length;			d->actual_length = 0;			d->status = 0;			ttusb_process_frame(ttusb, data, len);		}	}	usb_submit_urb(urb, GFP_KERNEL);}static void ttusb_free_iso_urbs(struct ttusb *ttusb){	int i;	for (i = 0; i < ISO_BUF_COUNT; i++)		if (ttusb->iso_urb[i])			usb_free_urb(ttusb->iso_urb[i]);	pci_free_consistent(NULL,			    ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF *			    ISO_BUF_COUNT, ttusb->iso_buffer,			    ttusb->iso_dma_handle);}static int ttusb_alloc_iso_urbs(struct ttusb *ttusb){	int i;	ttusb->iso_buffer = pci_alloc_consistent(NULL,						 ISO_FRAME_SIZE *						 FRAMES_PER_ISO_BUF *						 ISO_BUF_COUNT,						 &ttusb->iso_dma_handle);	memset(ttusb->iso_buffer, 0,	       ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * ISO_BUF_COUNT);	for (i = 0; i < ISO_BUF_COUNT; i++) {		struct urb *urb;		if (!		    (urb =		     usb_alloc_urb(FRAMES_PER_ISO_BUF, GFP_KERNEL))) {			ttusb_free_iso_urbs(ttusb);			return -ENOMEM;		}		ttusb->iso_urb[i] = urb;	}	return 0;}static void ttusb_stop_iso_xfer(struct ttusb *ttusb){	int i;	for (i = 0; i < ISO_BUF_COUNT; i++)		usb_unlink_urb(ttusb->iso_urb[i]);	ttusb->iso_streaming = 0;}static int ttusb_start_iso_xfer(struct ttusb *ttusb){	int i, j, err, buffer_offset = 0;	if (ttusb->iso_streaming) {		printk("%s: iso xfer already running!\n", __FUNCTION__);		return 0;	}	ttusb->cc = -1;	ttusb->insync = 0;	ttusb->mux_state = 0;	for (i = 0; i < ISO_BUF_COUNT; i++) {		int frame_offset = 0;		struct urb *urb = ttusb->iso_urb[i];		urb->dev = ttusb->dev;		urb->context = ttusb;		urb->complete = ttusb_iso_irq;		urb->pipe = ttusb->isoc_in_pipe;		urb->transfer_flags = URB_ISO_ASAP;		urb->interval = 1;		urb->number_of_packets = FRAMES_PER_ISO_BUF;		urb->transfer_buffer_length =		    ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF;		urb->transfer_buffer = ttusb->iso_buffer + buffer_offset;		buffer_offset += ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF;		for (j = 0; j < FRAMES_PER_ISO_BUF; j++) {			urb->iso_frame_desc[j].offset = frame_offset;			urb->iso_frame_desc[j].length = ISO_FRAME_SIZE;			frame_offset += ISO_FRAME_SIZE;		}	}	for (i = 0; i < ISO_BUF_COUNT; i++) {		if ((err = usb_submit_urb(ttusb->iso_urb[i], GFP_KERNEL))) {			ttusb_stop_iso_xfer(ttusb);			printk			    ("%s: failed urb submission (%i: err = %i)!\n",			     __FUNCTION__, i, err);			return err;		}	}	ttusb->iso_streaming = 1;	return 0;}#ifdef TTUSB_HWSECTIONSstatic void ttusb_handle_ts_data(struct ttusb_channel *channel, const u8 * data,			  int len){	struct dvb_demux_feed *dvbdmxfeed = channel->dvbdmxfeed;	dvbdmxfeed->cb.ts(data, len, 0, 0, &dvbdmxfeed->feed.ts, 0);}static void ttusb_handle_sec_data(struct ttusb_channel *channel, const u8 * data,			   int len){//      struct dvb_demux_feed *dvbdmxfeed = channel->dvbdmxfeed;#error TODO: handle ugly stuff//      dvbdmxfeed->cb.sec(data, len, 0, 0, &dvbdmxfeed->feed.sec, 0);}#endifstatic struct ttusb_channel *ttusb_channel_allocate(struct ttusb *ttusb){	int i;	if (down_interruptible(&ttusb->sem))		return NULL;	/* lock! */	for (i = 0; i < TTUSB_MAXCHANNEL; ++i) {		if (!ttusb->channel[i].active) {			ttusb->channel[i].active = 1;			up(&ttusb->sem);			return ttusb->channel + i;		}	}	up(&ttusb->sem);	return NULL;}static int ttusb_start_feed(struct dvb_demux_feed *dvbdmxfeed){	struct ttusb *ttusb = (struct ttusb *) dvbdmxfeed->demux;	struct ttusb_channel *channel;	dprintk("ttusb_start_feed\n");	switch (dvbdmxfeed->type) {	case DMX_TYPE_TS:		break;	case DMX_TYPE_SEC:		break;	default:		return -EINVAL;	}	if (dvbdmxfeed->type == DMX_TYPE_TS) {		switch (dvbdmxfeed->pes_type) {		case DMX_TS_PES_VIDEO:		case DMX_TS_PES_AUDIO:		case DMX_TS_PES_TELETEXT:		case DMX_TS_PES_PCR:		case DMX_TS_PES_OTHER:			channel = ttusb_channel_allocate(ttusb);			break;		default:			return -EINVAL;		}	} else {		channel = ttusb_channel_allocate(ttusb);	}	if (!channel)		return -EBUSY;	dvbdmxfeed->priv = channel;	channel->dvbdmxfeed = dvbdmxfeed;	channel->pid = dvbdmxfeed->pid;#ifdef TTUSB_HWSECTIONS	if (dvbdmxfeed->type == DMX_TYPE_TS) {		channel->type = 1;	} else if (dvbdmxfeed->type == DMX_TYPE_SEC) {		channel->type = 2;#error TODO: allocate filters	}#else	channel->type = 1;#endif	ttusb_set_channel(ttusb, channel->id, channel->type, channel->pid);	if (0 == ttusb->running_feed_count++)		ttusb_start_iso_xfer(ttusb);	return 0;}static int ttusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed){	struct ttusb_channel *channel =	    (struct ttusb_channel *) dvbdmxfeed->priv;	struct ttusb *ttusb = (struct ttusb *) dvbdmxfeed->demux;	ttusb_del_channel(channel->ttusb, channel->id);	if (--ttusb->running_feed_count == 0)		ttusb_stop_iso_xfer(ttusb);	channel->active = 0;	return 0;}static int ttusb_setup_interfaces(struct ttusb *ttusb){	usb_set_interface(ttusb->dev, 1, 1);	ttusb->bulk_out_pipe = usb_sndbulkpipe(ttusb->dev, 1);	ttusb->bulk_in_pipe = usb_rcvbulkpipe(ttusb->dev, 1);	ttusb->isoc_in_pipe = usb_rcvisocpipe(ttusb->dev, 2);	return 0;}#if 0static u8 stc_firmware[8192];static int stc_open(struct inode *inode, struct file *file){	struct ttusb *ttusb = file->private_data;	int addr;	for (addr = 0; addr < 8192; addr += 16) {		u8 snd_buf[2] = { addr >> 8, addr & 0xFF };		ttusb_i2c_msg(ttusb, 0x50, snd_buf, 2, stc_firmware + addr,			      16);	}	return 0;}static ssize_t stc_read(struct file *file, char *buf, size_t count,		 loff_t * offset){	int tc = count;	if ((tc + *offset) > 8192)		tc = 8192 - *offset;	if (tc < 0)		return 0;	if (copy_to_user(buf, stc_firmware + *offset, tc))		return -EFAULT;	*offset += tc;	return tc;}static int stc_release(struct inode *inode, struct file *file){	return 0;}static struct file_operations stc_fops = {	.owner = THIS_MODULE,	.read = stc_read,	.open = stc_open,	.release = stc_release,};#endifstatic int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *id){	struct usb_device *udev;	struct ttusb *ttusb;	int result, channel;	dprintk("%s: TTUSB DVB connected\n", __FUNCTION__);	udev = interface_to_usbdev(intf);	/* Device has already been reset; its configuration was chosen.	 * If this fault happens, use a hotplug script to choose the	 * right configuration (write bConfigurationValue in sysfs).	 */	if (udev->actconfig->desc.bConfigurationValue != 1) {		dev_err(&intf->dev, "device config is #%d, need #1\n",			udev->actconfig->desc.bConfigurationValue);		return -ENODEV;	}        if (intf->altsetting->desc.bInterfaceNumber != 1) return -ENODEV;	if (!(ttusb = kmalloc(sizeof(struct ttusb), GFP_KERNEL)))		return -ENOMEM;	memset(ttusb, 0, sizeof(struct ttusb));	for (channel = 0; channel < TTUSB_MAXCHANNEL; ++channel) {		ttusb->channel[channel].id = channel;		ttusb->channel[channel].ttusb = ttusb;	}	ttusb->dev = udev;	ttusb->c = 0;	ttusb->mux_state = 0;	sema_init(&ttusb->sem, 0);	sema_init(&ttusb->semusb, 1);	ttusb_setup_interfaces(ttusb);	ttusb_alloc_iso_urbs(ttusb);	if (ttusb_init_controller(ttusb))		printk("ttusb_init_controller: error\n");	up(&ttusb->sem);	dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE);	dvb_register_i2c_bus(ttusb_i2c_xfer, ttusb, ttusb->adapter, 0);	dvb_add_frontend_ioctls(ttusb->adapter, ttusb_lnb_ioctl, NULL,				ttusb);	memset(&ttusb->dvb_demux, 0, sizeof(ttusb->dvb_demux));	ttusb->dvb_demux.dmx.capabilities =	    DMX_TS_FILTERING | DMX_SECTION_FILTERING;	ttusb->dvb_demux.priv = NULL;#ifdef TTUSB_HWSECTIONS	ttusb->dvb_demux.filternum = TTUSB_MAXFILTER;#else	ttusb->dvb_demux.filternum = 32;#endif	ttusb->dvb_demux.feednum = TTUSB_MAXCHANNEL;	ttusb->dvb_demux.start_feed = ttusb_start_feed;	ttusb->dvb_demux.stop_feed = ttusb_stop_feed;	ttusb->dvb_demux.write_to_decoder = NULL;	if ((result = dvb_dmx_init(&ttusb->dvb_demux)) < 0) {		printk("ttusb_dvb: dvb_dmx_init failed (errno = %d)\n",		       result);		goto err;	}//FIXME dmxdev (nur WAS?)	ttusb->dmxdev.filternum = ttusb->dvb_demux.filternum;	ttusb->dmxdev.demux = &ttusb->dvb_demux.dmx;	ttusb->dmxdev.capabilities = 0;	if ((result = dvb_dmxdev_init(&ttusb->dmxdev, ttusb->adapter)) < 0) {		printk("ttusb_dvb: dvb_dmxdev_init failed (errno = %d)\n",		       result);		dvb_dmx_release(&ttusb->dvb_demux);		goto err;	}	if (dvb_net_init	    (ttusb->adapter, &ttusb->dvbnet, &ttusb->dvb_demux.dmx)) {		printk("ttusb_dvb: dvb_net_init failed!\n");	}      err:#if 0	ttusb->stc_devfs_handle =	    devfs_register(ttusb->adapter->devfs_handle, TTUSB_BUDGET_NAME,			   DEVFS_FL_DEFAULT, 0, 192,			   S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP			   | S_IROTH | S_IWOTH, &stc_fops, ttusb);#endif	usb_set_intfdata(intf, (void *) ttusb);	return 0;}static void ttusb_disconnect(struct usb_interface *intf){	struct ttusb *ttusb = usb_get_intfdata(intf);	usb_set_intfdata(intf, NULL);	ttusb->disconnecting = 1;	ttusb_stop_iso_xfer(ttusb);	ttusb->dvb_demux.dmx.close(&ttusb->dvb_demux.dmx);	dvb_net_release(&ttusb->dvbnet);	dvb_dmxdev_release(&ttusb->dmxdev);	dvb_dmx_release(&ttusb->dvb_demux);	dvb_unregister_i2c_bus(ttusb_i2c_xfer, ttusb->adapter, 0);	dvb_unregister_adapter(ttusb->adapter);	ttusb_free_iso_urbs(ttusb);	kfree(ttusb);	dprintk("%s: TTUSB DVB disconnected\n", __FUNCTION__);}static struct usb_device_id ttusb_table[] = {	{USB_DEVICE(0xb48, 0x1003)},	{USB_DEVICE(0xb48, 0x1004)},	/* to be confirmed ????  */	{USB_DEVICE(0xb48, 0x1005)},	{}};MODULE_DEVICE_TABLE(usb, ttusb_table);static struct usb_driver ttusb_driver = {      .name 		= "Technotrend/Hauppauge USB-Nova",      .probe 		= ttusb_probe,      .disconnect 	= ttusb_disconnect,      .id_table 	= ttusb_table,};static int __init ttusb_init(void){	int err;	if ((err = usb_register(&ttusb_driver)) < 0) {		printk("%s: usb_register failed! Error number %d",		       __FILE__, err);		return err;	}	return 0;}static void __exit ttusb_exit(void){	usb_deregister(&ttusb_driver);}module_init(ttusb_init);module_exit(ttusb_exit);MODULE_PARM(debug, "i");MODULE_PARM_DESC(debug, "Debug or not");MODULE_AUTHOR("Holger Waechtler <holger@convergence.de>");MODULE_DESCRIPTION("TTUSB DVB Driver");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -