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

📄 dvb-ttusb-budget.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 3 页
字号:
	u8 b[] = { 0xaa, ++ttusb->c, 0x19, 1, freq };	int err, actual_len;	err = ttusb_cmd(ttusb, b, sizeof(b), 0);	if (err) {		dprintk("%s: usb_bulk_msg() failed, return value %i!\n",			__FUNCTION__, err);	}}#endif/*****************************************************************************/#ifdef TTUSB_HWSECTIONSstatic void ttusb_handle_ts_data(struct ttusb_channel *channel,				 const u8 * data, int len);static void ttusb_handle_sec_data(struct ttusb_channel *channel,				  const u8 * data, int len);#endifstatic int numpkt = 0, numts, numstuff, numsec, numinvalid;static unsigned long lastj;static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,			   int len){	u16 csum = 0, cc;	int i;	for (i = 0; i < len; i += 2)		csum ^= le16_to_cpup((u16 *) (muxpack + i));	if (csum) {		printk("%s: muxpack with incorrect checksum, ignoring\n",		       __FUNCTION__);		numinvalid++;		return;	}	cc = (muxpack[len - 4] << 8) | muxpack[len - 3];	cc &= 0x7FFF;	if ((cc != ttusb->cc) && (ttusb->cc != -1))		printk("%s: cc discontinuity (%d frames missing)\n",		       __FUNCTION__, (cc - ttusb->cc) & 0x7FFF);	ttusb->cc = (cc + 1) & 0x7FFF;	if (muxpack[0] & 0x80) {#ifdef TTUSB_HWSECTIONS		/* section data */		int pusi = muxpack[0] & 0x40;		int channel = muxpack[0] & 0x1F;		int payload = muxpack[1];		const u8 *data = muxpack + 2;		/* check offset flag */		if (muxpack[0] & 0x20)			data++;		ttusb_handle_sec_data(ttusb->channel + channel, data,				      payload);		data += payload;		if ((!!(ttusb->muxpack[0] & 0x20)) ^		    !!(ttusb->muxpack[1] & 1))			data++;#warning TODO: pusi		printk("cc: %04x\n", (data[0] << 8) | data[1]);#endif		numsec++;	} else if (muxpack[0] == 0x47) {#ifdef TTUSB_HWSECTIONS		/* we have TS data here! */		int pid = ((muxpack[1] & 0x0F) << 8) | muxpack[2];		int channel;		for (channel = 0; channel < TTUSB_MAXCHANNEL; ++channel)			if (ttusb->channel[channel].active			    && (pid == ttusb->channel[channel].pid))				ttusb_handle_ts_data(ttusb->channel +						     channel, muxpack,						     188);#endif		numts++;		dvb_dmx_swfilter_packets(&ttusb->dvb_demux, muxpack, 1);	} else if (muxpack[0] != 0) {		numinvalid++;		printk("illegal muxpack type %02x\n", muxpack[0]);	} else		numstuff++;}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 (time_after_eq(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_ATOMIC);}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_ATOMIC))) {			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_kill_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_ATOMIC))) {			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 dvb_demux_feed *dvbdmxfeed, const u8 * data,			  int len){	dvbdmxfeed->cb.ts(data, len, 0, 0, &dvbdmxfeed->feed.ts, 0);}static void ttusb_handle_sec_data(struct dvb_demux_feed *dvbdmxfeed, 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 int ttusb_start_feed(struct dvb_demux_feed *dvbdmxfeed){	struct ttusb *ttusb = (struct ttusb *) dvbdmxfeed->demux;	int feed_type = 1;	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:			break;		default:			return -EINVAL;		}	}#ifdef TTUSB_HWSECTIONS#error TODO: allocate filters	if (dvbdmxfeed->type == DMX_TYPE_TS) {		feed_type = 1;	} else if (dvbdmxfeed->type == DMX_TYPE_SEC) {		feed_type = 2;	}#endif	ttusb_set_channel(ttusb, dvbdmxfeed->index, feed_type, dvbdmxfeed->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 *ttusb = (struct ttusb *) dvbdmxfeed->demux;	ttusb_del_channel(ttusb, dvbdmxfeed->index);	if (--ttusb->running_feed_count == 0)		ttusb_stop_iso_xfer(ttusb);	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 u32 functionality(struct i2c_adapter *adapter){	return I2C_FUNC_I2C;}static int alps_tdmb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params){	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;	u8 data[4];	struct i2c_msg msg = {.addr=0x61, .flags=0, .buf=data, .len=sizeof(data) };	u32 div;	div = (params->frequency + 36166667) / 166667;	data[0] = (div >> 8) & 0x7f;	data[1] = div & 0xff;	data[2] = ((div >> 10) & 0x60) | 0x85;	data[3] = params->frequency < 592000000 ? 0x40 : 0x80;	if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1) return -EIO;	return 0;}static struct cx22700_config alps_tdmb7_config = {	.demod_address = 0x43,	.pll_set = alps_tdmb7_pll_set,};static int philips_tdm1316l_pll_init(struct dvb_frontend* fe){	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;	static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };	static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };	struct i2c_msg tuner_msg = { .addr=0x60, .flags=0, .buf=td1316_init, .len=sizeof(td1316_init) };	// setup PLL configuration	if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) return -EIO;	msleep(1);	// disable the mc44BC374c (do not check for errors)	tuner_msg.addr = 0x65;	tuner_msg.buf = disable_mc44BC374c;	tuner_msg.len = sizeof(disable_mc44BC374c);	if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) {		i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1);	}	return 0;}static int philips_tdm1316l_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params){	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;	u8 tuner_buf[4];	struct i2c_msg tuner_msg = {.addr=0x60, .flags=0, .buf=tuner_buf, .len=sizeof(tuner_buf) };

⌨️ 快捷键说明

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