📄 ttusb_dec.c
字号:
b[j + 0] = 0xaa; b[j + 1] = trans_count++; b[j + 2] = 0xf0; 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)) < 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; case FE_RESET: dprintk("%s: FE_RESET\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_RESET: dprintk("%s: FE_RESET\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); }}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)static void *ttusb_dec_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id){ struct ttusb_dec *dec; dprintk("%s\n", __FUNCTION__); if (ifnum != 0) return NULL; if (!(dec = kmalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) { printk("%s: couldn't allocate memory.\n", __FUNCTION__); return NULL; }#elsestatic 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);#endif 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);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) return (void *)dec;#else return 0;#endif}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)static void ttusb_dec_disconnect(struct usb_device *udev, void *data){ struct ttusb_dec *dec = data;#elsestatic void ttusb_dec_disconnect(struct usb_interface *intf){ struct ttusb_dec *dec = usb_get_intfdata(intf); usb_set_intfdata(intf, NULL);#endif 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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -