ttusb_dec.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 1,847 行 · 第 1/3 页

C
1,847
字号
		b[j + 3] = size;		memcpy(&b[j + 4], &firmware[i], size);		j += COMMAND_PACKET_SIZE + 4;		if (j >= ARM_PACKET_SIZE) {			result = usb_bulk_msg(dec->udev, dec->command_pipe, b,					      ARM_PACKET_SIZE, &actual_len,					      HZ / 10);			j = 0;		} else if (size < COMMAND_PACKET_SIZE) {			result = usb_bulk_msg(dec->udev, dec->command_pipe, b,					      j - COMMAND_PACKET_SIZE + size,					      &actual_len, HZ / 10);		}	}	result = ttusb_dec_send_command(dec, 0x43, sizeof(b1), b1, NULL, NULL);	kfree(b);	return result;}static int ttusb_dec_init_stb(struct ttusb_dec *dec){	int result;	unsigned int mode, model, version;	dprintk("%s\n", __FUNCTION__);	result = ttusb_dec_get_stb_state(dec, &mode, &model, &version);	if (!result) {		if (!mode) {			if (version == 0xABCDEFAB)				printk(KERN_INFO "ttusb_dec: no version "				       "info in Firmware\n");			else				printk(KERN_INFO "ttusb_dec: Firmware "				       "%x.%02x%c%c\n",				       version >> 24, (version >> 16) & 0xff,				       (version >> 8) & 0xff, version & 0xff);			result = ttusb_dec_boot_dsp(dec);			if (result)				return result;		else				return 1;		} else {			/* We can't trust the USB IDs that some firmwares			   give the box */			switch (model) {			case 0x00070008:			case 0x0007000c:				ttusb_dec_set_model(dec, TTUSB_DEC3000S);				break;			case 0x00070009:				ttusb_dec_set_model(dec, TTUSB_DEC2000T);				break;			case 0x00070011:				ttusb_dec_set_model(dec, TTUSB_DEC2540T);				break;			default:				printk(KERN_ERR "%s: unknown model returned "				       "by firmware (%08x) - please report\n",				       __FUNCTION__, model);				return -1;				break;			}			if (version >= 0x01770000)				dec->can_playback = 1;			return 0;	}	}	else		return result;}static int ttusb_dec_init_dvb(struct ttusb_dec *dec){	int result;	dprintk("%s\n", __FUNCTION__);	if ((result = dvb_register_adapter(&dec->adapter,					   dec->model_name, THIS_MODULE)) < 0) {		printk("%s: dvb_register_adapter failed: error %d\n",		       __FUNCTION__, result);		return result;	}	dec->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;	dec->demux.priv = (void *)dec;	dec->demux.filternum = 31;	dec->demux.feednum = 31;	dec->demux.start_feed = ttusb_dec_start_feed;	dec->demux.stop_feed = ttusb_dec_stop_feed;	dec->demux.write_to_decoder = NULL;	if ((result = dvb_dmx_init(&dec->demux)) < 0) {		printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,		       result);		dvb_unregister_adapter(dec->adapter);		return result;	}	dec->dmxdev.filternum = 32;	dec->dmxdev.demux = &dec->demux.dmx;	dec->dmxdev.capabilities = 0;	if ((result = dvb_dmxdev_init(&dec->dmxdev, dec->adapter)) < 0) {		printk("%s: dvb_dmxdev_init failed: error %d\n",		       __FUNCTION__, result);		dvb_dmx_release(&dec->demux);		dvb_unregister_adapter(dec->adapter);		return result;	}	dec->frontend.source = DMX_FRONTEND_0;	if ((result = dec->demux.dmx.add_frontend(&dec->demux.dmx,						  &dec->frontend)) < 0) {		printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,		       result);		dvb_dmxdev_release(&dec->dmxdev);		dvb_dmx_release(&dec->demux);		dvb_unregister_adapter(dec->adapter);		return result;	}	if ((result = dec->demux.dmx.connect_frontend(&dec->demux.dmx,						      &dec->frontend)) < 0) {		printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,		       result);		dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);		dvb_dmxdev_release(&dec->dmxdev);		dvb_dmx_release(&dec->demux);		dvb_unregister_adapter(dec->adapter);		return result;	}	dvb_net_init(dec->adapter, &dec->dvb_net, &dec->demux.dmx);	return 0;}static void ttusb_dec_exit_dvb(struct ttusb_dec *dec){	dprintk("%s\n", __FUNCTION__);	dvb_net_release(&dec->dvb_net);	dec->demux.dmx.close(&dec->demux.dmx);	dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);	dvb_dmxdev_release(&dec->dmxdev);	dvb_dmx_release(&dec->demux);	dvb_unregister_adapter(dec->adapter);}static void ttusb_dec_exit_usb(struct ttusb_dec *dec){	int i;	dprintk("%s\n", __FUNCTION__);	dec->iso_stream_count = 0;	for (i = 0; i < ISO_BUF_COUNT; i++)		usb_unlink_urb(dec->iso_urb[i]);	ttusb_dec_free_iso_urbs(dec);}static void ttusb_dec_exit_tasklet(struct ttusb_dec *dec){	struct list_head *item;	struct urb_frame *frame;	tasklet_kill(&dec->urb_tasklet);	while ((item = dec->urb_frame_list.next) != &dec->urb_frame_list) {		frame = list_entry(item, struct urb_frame, urb_frame_list);		list_del(&frame->urb_frame_list);		kfree(frame);	}}static int ttusb_dec_2000t_frontend_ioctl(struct dvb_frontend *fe, unsigned int cmd,				  void *arg){	struct ttusb_dec *dec = fe->data;	dprintk("%s\n", __FUNCTION__);	switch (cmd) {	case FE_GET_INFO:		dprintk("%s: FE_GET_INFO\n", __FUNCTION__);		memcpy(arg, dec->frontend_info,		       sizeof (struct dvb_frontend_info));		break;	case FE_READ_STATUS: {			fe_status_t *status = (fe_status_t *)arg;			dprintk("%s: FE_READ_STATUS\n", __FUNCTION__);			*status = FE_HAS_SIGNAL | FE_HAS_VITERBI |				  FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;			break;		}	case FE_READ_BER: {			u32 *ber = (u32 *)arg;			dprintk("%s: FE_READ_BER\n", __FUNCTION__);			*ber = 0;			return -ENOSYS;			break;		}	case FE_READ_SIGNAL_STRENGTH: {			dprintk("%s: FE_READ_SIGNAL_STRENGTH\n", __FUNCTION__);			*(s32 *)arg = 0xFF;			return -ENOSYS;			break;		}	case FE_READ_SNR:		dprintk("%s: FE_READ_SNR\n", __FUNCTION__);		*(s32 *)arg = 0;		return -ENOSYS;		break;	case FE_READ_UNCORRECTED_BLOCKS:		dprintk("%s: FE_READ_UNCORRECTED_BLOCKS\n", __FUNCTION__);		*(u32 *)arg = 0;		return -ENOSYS;		break;	case FE_SET_FRONTEND: {			struct dvb_frontend_parameters *p =				(struct dvb_frontend_parameters *)arg;		u8 b[] = { 0x00, 0x00, 0x00, 0x03,			   0x00, 0x00, 0x00, 0x00,			   0x00, 0x00, 0x00, 0x01,			   0x00, 0x00, 0x00, 0xff,			   0x00, 0x00, 0x00, 0xff };			u32 freq;			dprintk("%s: FE_SET_FRONTEND\n", __FUNCTION__);			dprintk("            frequency->%d\n", p->frequency);			dprintk("            symbol_rate->%d\n",				p->u.qam.symbol_rate);			dprintk("            inversion->%d\n", p->inversion);			freq = htonl(p->frequency / 1000);			memcpy(&b[4], &freq, sizeof (u32));			ttusb_dec_send_command(dec, 0x71, sizeof(b), b, NULL, NULL);			break;		}	case FE_GET_FRONTEND:		dprintk("%s: FE_GET_FRONTEND\n", __FUNCTION__);		break;	case FE_SLEEP:		dprintk("%s: FE_SLEEP\n", __FUNCTION__);		return -ENOSYS;		break;	case FE_INIT:		dprintk("%s: FE_INIT\n", __FUNCTION__);		break;	default:		dprintk("%s: unknown IOCTL (0x%X)\n", __FUNCTION__, cmd);		return -EINVAL;	}	return 0;}static int ttusb_dec_3000s_frontend_ioctl(struct dvb_frontend *fe,					  unsigned int cmd, void *arg){	struct ttusb_dec *dec = fe->data;	dprintk("%s\n", __FUNCTION__);	switch (cmd) {	case FE_GET_INFO:		dprintk("%s: FE_GET_INFO\n", __FUNCTION__);		memcpy(arg, dec->frontend_info,		       sizeof (struct dvb_frontend_info));		break;	case FE_READ_STATUS: {			fe_status_t *status = (fe_status_t *)arg;			dprintk("%s: FE_READ_STATUS\n", __FUNCTION__);			*status = FE_HAS_SIGNAL | FE_HAS_VITERBI |				  FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;			break;		}	case FE_READ_BER: {			u32 *ber = (u32 *)arg;			dprintk("%s: FE_READ_BER\n", __FUNCTION__);			*ber = 0;			return -ENOSYS;			break;		}	case FE_READ_SIGNAL_STRENGTH: {			dprintk("%s: FE_READ_SIGNAL_STRENGTH\n", __FUNCTION__);			*(s32 *)arg = 0xFF;			return -ENOSYS;			break;		}	case FE_READ_SNR:		dprintk("%s: FE_READ_SNR\n", __FUNCTION__);		*(s32 *)arg = 0;		return -ENOSYS;		break;	case FE_READ_UNCORRECTED_BLOCKS:		dprintk("%s: FE_READ_UNCORRECTED_BLOCKS\n", __FUNCTION__);		*(u32 *)arg = 0;		return -ENOSYS;		break;	case FE_SET_FRONTEND: {			struct dvb_frontend_parameters *p =				(struct dvb_frontend_parameters *)arg;		u8 b[] = { 0x00, 0x00, 0x00, 0x01,			   0x00, 0x00, 0x00, 0x00,			   0x00, 0x00, 0x00, 0x01,			   0x00, 0x00, 0x00, 0x00,			   0x00, 0x00, 0x00, 0x00,			   0x00, 0x00, 0x00, 0x00,			   0x00, 0x00, 0x00, 0x00,			   0x00, 0x00, 0x00, 0x00,			   0x00, 0x00, 0x00, 0x00,			   0x00, 0x00, 0x00, 0x00 };			u32 freq;			u32 sym_rate;			u32 band;		u32 lnb_voltage;			dprintk("%s: FE_SET_FRONTEND\n", __FUNCTION__);			dprintk("            frequency->%d\n", p->frequency);			dprintk("            symbol_rate->%d\n",				p->u.qam.symbol_rate);			dprintk("            inversion->%d\n", p->inversion);		freq = htonl(p->frequency * 1000 +		       (dec->hi_band ? LOF_HI : LOF_LO));			memcpy(&b[4], &freq, sizeof(u32));			sym_rate = htonl(p->u.qam.symbol_rate);			memcpy(&b[12], &sym_rate, sizeof(u32));			band = htonl(dec->hi_band ? LOF_HI : LOF_LO);			memcpy(&b[24], &band, sizeof(u32));		lnb_voltage = htonl(dec->voltage);		memcpy(&b[28], &lnb_voltage, sizeof(u32));			ttusb_dec_send_command(dec, 0x71, sizeof(b), b, NULL, NULL);			break;		}	case FE_GET_FRONTEND:		dprintk("%s: FE_GET_FRONTEND\n", __FUNCTION__);		break;	case FE_SLEEP:		dprintk("%s: FE_SLEEP\n", __FUNCTION__);		return -ENOSYS;		break;	case FE_INIT:		dprintk("%s: FE_INIT\n", __FUNCTION__);		break;	case FE_DISEQC_SEND_MASTER_CMD:		dprintk("%s: FE_DISEQC_SEND_MASTER_CMD\n", __FUNCTION__);		break;	case FE_DISEQC_SEND_BURST:		dprintk("%s: FE_DISEQC_SEND_BURST\n", __FUNCTION__);		break;	case FE_SET_TONE: {			fe_sec_tone_mode_t tone = (fe_sec_tone_mode_t)arg;			dprintk("%s: FE_SET_TONE\n", __FUNCTION__);			dec->hi_band = (SEC_TONE_ON == tone);			break;		}	case FE_SET_VOLTAGE:		dprintk("%s: FE_SET_VOLTAGE\n", __FUNCTION__);		switch ((fe_sec_voltage_t) arg) {		case SEC_VOLTAGE_13:			dec->voltage = 13;			break;		case SEC_VOLTAGE_18:			dec->voltage = 18;			break;		default:			return -EINVAL;			break;		}		break;	default:		dprintk("%s: unknown IOCTL (0x%X)\n", __FUNCTION__, cmd);		return -EINVAL;	}	return 0;}static void ttusb_dec_init_frontend(struct ttusb_dec *dec){	dec->i2c_bus.adapter = dec->adapter;	dvb_register_frontend(dec->frontend_ioctl, &dec->i2c_bus, (void *)dec,			      dec->frontend_info);}static void ttusb_dec_exit_frontend(struct ttusb_dec *dec){	dvb_unregister_frontend(dec->frontend_ioctl, &dec->i2c_bus);}static void ttusb_dec_init_filters(struct ttusb_dec *dec){	INIT_LIST_HEAD(&dec->filter_info_list);	dec->filter_info_list_lock = SPIN_LOCK_UNLOCKED;}static void ttusb_dec_exit_filters(struct ttusb_dec *dec){	struct list_head *item;	struct filter_info *finfo;	while ((item = dec->filter_info_list.next) != &dec->filter_info_list) {		finfo = list_entry(item, struct filter_info, filter_info_list);		list_del(&finfo->filter_info_list);		kfree(finfo);	}}static int ttusb_dec_probe(struct usb_interface *intf,			   const struct usb_device_id *id){	struct usb_device *udev;	struct ttusb_dec *dec;	dprintk("%s\n", __FUNCTION__);	udev = interface_to_usbdev(intf);	if (!(dec = kmalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) {		printk("%s: couldn't allocate memory.\n", __FUNCTION__);		return -ENOMEM;	}	usb_set_intfdata(intf, (void *)dec);	memset(dec, 0, sizeof(struct ttusb_dec));	switch (id->idProduct) {		case 0x1006:		ttusb_dec_set_model(dec, TTUSB_DEC3000S);			break;		case 0x1008:		ttusb_dec_set_model(dec, TTUSB_DEC2000T);		break;	case 0x1009:		ttusb_dec_set_model(dec, TTUSB_DEC2540T);			break;	}	dec->udev = udev;	ttusb_dec_init_usb(dec);	if (ttusb_dec_init_stb(dec)) {		ttusb_dec_exit_usb(dec);		return 0;	}	ttusb_dec_init_dvb(dec);	ttusb_dec_init_frontend(dec);	ttusb_dec_init_v_pes(dec);	ttusb_dec_init_filters(dec);	ttusb_dec_init_tasklet(dec);	dec->active = 1;	ttusb_dec_set_interface(dec, TTUSB_DEC_INTERFACE_IN);	return 0;}static void ttusb_dec_disconnect(struct usb_interface *intf){	struct ttusb_dec *dec = usb_get_intfdata(intf);	usb_set_intfdata(intf, NULL);	dprintk("%s\n", __FUNCTION__);	if (dec->active) {	ttusb_dec_exit_tasklet(dec);		ttusb_dec_exit_filters(dec);	ttusb_dec_exit_usb(dec);		ttusb_dec_exit_frontend(dec);	ttusb_dec_exit_dvb(dec);	}	kfree(dec);}static void ttusb_dec_set_model(struct ttusb_dec *dec,				enum ttusb_dec_model model){	dec->model = model;	switch (model) {	case TTUSB_DEC2000T:		dec->model_name = "DEC2000-t";		dec->firmware_name = "dvb-ttusb-dec-2000t.fw";		dec->frontend_info = &dec2000t_frontend_info;		dec->frontend_ioctl = ttusb_dec_2000t_frontend_ioctl;		break;	case TTUSB_DEC2540T:		dec->model_name = "DEC2540-t";		dec->firmware_name = "dvb-ttusb-dec-2540t.fw";		dec->frontend_info = &dec2000t_frontend_info;		dec->frontend_ioctl = ttusb_dec_2000t_frontend_ioctl;		break;	case TTUSB_DEC3000S:		dec->model_name = "DEC3000-s";		dec->firmware_name = "dvb-ttusb-dec-3000s.fw";		dec->frontend_info = &dec3000s_frontend_info;		dec->frontend_ioctl = ttusb_dec_3000s_frontend_ioctl;		break;	}}static struct usb_device_id ttusb_dec_table[] = {	{USB_DEVICE(0x0b48, 0x1006)},	/* DEC3000-s */	/*{USB_DEVICE(0x0b48, 0x1007)},	   Unconfirmed */	{USB_DEVICE(0x0b48, 0x1008)},	/* DEC2000-t */	{USB_DEVICE(0x0b48, 0x1009)},	/* DEC2540-t */	{}};static struct usb_driver ttusb_dec_driver = {	.name		= "ttusb-dec",      .probe		= ttusb_dec_probe,      .disconnect	= ttusb_dec_disconnect,      .id_table		= ttusb_dec_table,};static int __init ttusb_dec_init(void){	int result;	if ((result = usb_register(&ttusb_dec_driver)) < 0) {		printk("%s: initialisation failed: error %d.\n", __FUNCTION__,		       result);		return result;	}	return 0;}static void __exit ttusb_dec_exit(void){	usb_deregister(&ttusb_dec_driver);}module_init(ttusb_dec_init);module_exit(ttusb_dec_exit);MODULE_AUTHOR("Alex Woods <linux-dvb@giblets.org>");MODULE_DESCRIPTION(DRIVER_NAME);MODULE_LICENSE("GPL");MODULE_DEVICE_TABLE(usb, ttusb_dec_table);MODULE_PARM(debug, "i");MODULE_PARM_DESC(debug, "Debug level");MODULE_PARM(output_pva, "i");MODULE_PARM_DESC(output_pva, "Output PVA from dvr device");

⌨️ 快捷键说明

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