1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2786baecfSMauro Carvalho Chehab /* 3786baecfSMauro Carvalho Chehab * TTUSB DEC Driver 4786baecfSMauro Carvalho Chehab * 5786baecfSMauro Carvalho Chehab * Copyright (C) 2003-2004 Alex Woods <linux-dvb@giblets.org> 6786baecfSMauro Carvalho Chehab * IR support by Peter Beutner <p.beutner@gmx.net> 7786baecfSMauro Carvalho Chehab */ 8786baecfSMauro Carvalho Chehab 9786baecfSMauro Carvalho Chehab #include <linux/list.h> 10786baecfSMauro Carvalho Chehab #include <linux/module.h> 11786baecfSMauro Carvalho Chehab #include <linux/pci.h> 12786baecfSMauro Carvalho Chehab #include <linux/slab.h> 13786baecfSMauro Carvalho Chehab #include <linux/spinlock.h> 14786baecfSMauro Carvalho Chehab #include <linux/usb.h> 15786baecfSMauro Carvalho Chehab #include <linux/interrupt.h> 16786baecfSMauro Carvalho Chehab #include <linux/firmware.h> 17786baecfSMauro Carvalho Chehab #include <linux/crc32.h> 18786baecfSMauro Carvalho Chehab #include <linux/init.h> 19786baecfSMauro Carvalho Chehab #include <linux/input.h> 20786baecfSMauro Carvalho Chehab 21786baecfSMauro Carvalho Chehab #include <linux/mutex.h> 22786baecfSMauro Carvalho Chehab 23fada1935SMauro Carvalho Chehab #include <media/dmxdev.h> 24fada1935SMauro Carvalho Chehab #include <media/dvb_demux.h> 25fada1935SMauro Carvalho Chehab #include <media/dvb_frontend.h> 26fada1935SMauro Carvalho Chehab #include <media/dvb_net.h> 27786baecfSMauro Carvalho Chehab #include "ttusbdecfe.h" 28786baecfSMauro Carvalho Chehab 29786baecfSMauro Carvalho Chehab static int debug; 30786baecfSMauro Carvalho Chehab static int output_pva; 31786baecfSMauro Carvalho Chehab static int enable_rc; 32786baecfSMauro Carvalho Chehab 33786baecfSMauro Carvalho Chehab module_param(debug, int, 0644); 34786baecfSMauro Carvalho Chehab MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); 35786baecfSMauro Carvalho Chehab module_param(output_pva, int, 0444); 36786baecfSMauro Carvalho Chehab MODULE_PARM_DESC(output_pva, "Output PVA from dvr device (default:off)"); 37786baecfSMauro Carvalho Chehab module_param(enable_rc, int, 0644); 38786baecfSMauro Carvalho Chehab MODULE_PARM_DESC(enable_rc, "Turn on/off IR remote control(default: off)"); 39786baecfSMauro Carvalho Chehab 40786baecfSMauro Carvalho Chehab DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 41786baecfSMauro Carvalho Chehab 42786baecfSMauro Carvalho Chehab #define dprintk if (debug) printk 43786baecfSMauro Carvalho Chehab 44786baecfSMauro Carvalho Chehab #define DRIVER_NAME "TechnoTrend/Hauppauge DEC USB" 45786baecfSMauro Carvalho Chehab 46786baecfSMauro Carvalho Chehab #define COMMAND_PIPE 0x03 47786baecfSMauro Carvalho Chehab #define RESULT_PIPE 0x04 48786baecfSMauro Carvalho Chehab #define IN_PIPE 0x08 49786baecfSMauro Carvalho Chehab #define OUT_PIPE 0x07 50786baecfSMauro Carvalho Chehab #define IRQ_PIPE 0x0A 51786baecfSMauro Carvalho Chehab 52786baecfSMauro Carvalho Chehab #define COMMAND_PACKET_SIZE 0x3c 53786baecfSMauro Carvalho Chehab #define ARM_PACKET_SIZE 0x1000 54786baecfSMauro Carvalho Chehab #define IRQ_PACKET_SIZE 0x8 55786baecfSMauro Carvalho Chehab 56786baecfSMauro Carvalho Chehab #define ISO_BUF_COUNT 0x04 57786baecfSMauro Carvalho Chehab #define FRAMES_PER_ISO_BUF 0x04 58786baecfSMauro Carvalho Chehab #define ISO_FRAME_SIZE 0x0380 59786baecfSMauro Carvalho Chehab 60786baecfSMauro Carvalho Chehab #define MAX_PVA_LENGTH 6144 61786baecfSMauro Carvalho Chehab 62786baecfSMauro Carvalho Chehab enum ttusb_dec_model { 63786baecfSMauro Carvalho Chehab TTUSB_DEC2000T, 64786baecfSMauro Carvalho Chehab TTUSB_DEC2540T, 65786baecfSMauro Carvalho Chehab TTUSB_DEC3000S 66786baecfSMauro Carvalho Chehab }; 67786baecfSMauro Carvalho Chehab 68786baecfSMauro Carvalho Chehab enum ttusb_dec_packet_type { 69786baecfSMauro Carvalho Chehab TTUSB_DEC_PACKET_PVA, 70786baecfSMauro Carvalho Chehab TTUSB_DEC_PACKET_SECTION, 71786baecfSMauro Carvalho Chehab TTUSB_DEC_PACKET_EMPTY 72786baecfSMauro Carvalho Chehab }; 73786baecfSMauro Carvalho Chehab 74786baecfSMauro Carvalho Chehab enum ttusb_dec_interface { 75786baecfSMauro Carvalho Chehab TTUSB_DEC_INTERFACE_INITIAL, 76786baecfSMauro Carvalho Chehab TTUSB_DEC_INTERFACE_IN, 77786baecfSMauro Carvalho Chehab TTUSB_DEC_INTERFACE_OUT 78786baecfSMauro Carvalho Chehab }; 79786baecfSMauro Carvalho Chehab 80b676e731SMauro Carvalho Chehab typedef int (dvb_filter_pes2ts_cb_t) (void *, unsigned char *); 81b676e731SMauro Carvalho Chehab 82b676e731SMauro Carvalho Chehab struct dvb_filter_pes2ts { 83b676e731SMauro Carvalho Chehab unsigned char buf[188]; 84b676e731SMauro Carvalho Chehab unsigned char cc; 85b676e731SMauro Carvalho Chehab dvb_filter_pes2ts_cb_t *cb; 86b676e731SMauro Carvalho Chehab void *priv; 87b676e731SMauro Carvalho Chehab }; 88b676e731SMauro Carvalho Chehab 89786baecfSMauro Carvalho Chehab struct ttusb_dec { 90786baecfSMauro Carvalho Chehab enum ttusb_dec_model model; 91786baecfSMauro Carvalho Chehab char *model_name; 92786baecfSMauro Carvalho Chehab char *firmware_name; 93786baecfSMauro Carvalho Chehab int can_playback; 94786baecfSMauro Carvalho Chehab 95786baecfSMauro Carvalho Chehab /* DVB bits */ 96786baecfSMauro Carvalho Chehab struct dvb_adapter adapter; 97786baecfSMauro Carvalho Chehab struct dmxdev dmxdev; 98786baecfSMauro Carvalho Chehab struct dvb_demux demux; 99786baecfSMauro Carvalho Chehab struct dmx_frontend frontend; 100786baecfSMauro Carvalho Chehab struct dvb_net dvb_net; 101786baecfSMauro Carvalho Chehab struct dvb_frontend* fe; 102786baecfSMauro Carvalho Chehab 103786baecfSMauro Carvalho Chehab u16 pid[DMX_PES_OTHER]; 104786baecfSMauro Carvalho Chehab 105786baecfSMauro Carvalho Chehab /* USB bits */ 106786baecfSMauro Carvalho Chehab struct usb_device *udev; 107786baecfSMauro Carvalho Chehab u8 trans_count; 108786baecfSMauro Carvalho Chehab unsigned int command_pipe; 109786baecfSMauro Carvalho Chehab unsigned int result_pipe; 110786baecfSMauro Carvalho Chehab unsigned int in_pipe; 111786baecfSMauro Carvalho Chehab unsigned int out_pipe; 112786baecfSMauro Carvalho Chehab unsigned int irq_pipe; 113786baecfSMauro Carvalho Chehab enum ttusb_dec_interface interface; 114786baecfSMauro Carvalho Chehab struct mutex usb_mutex; 115786baecfSMauro Carvalho Chehab 116786baecfSMauro Carvalho Chehab void *irq_buffer; 117786baecfSMauro Carvalho Chehab struct urb *irq_urb; 118786baecfSMauro Carvalho Chehab dma_addr_t irq_dma_handle; 119786baecfSMauro Carvalho Chehab void *iso_buffer; 120786baecfSMauro Carvalho Chehab struct urb *iso_urb[ISO_BUF_COUNT]; 121786baecfSMauro Carvalho Chehab int iso_stream_count; 122786baecfSMauro Carvalho Chehab struct mutex iso_mutex; 123786baecfSMauro Carvalho Chehab 124786baecfSMauro Carvalho Chehab u8 packet[MAX_PVA_LENGTH + 4]; 125786baecfSMauro Carvalho Chehab enum ttusb_dec_packet_type packet_type; 126786baecfSMauro Carvalho Chehab int packet_state; 127786baecfSMauro Carvalho Chehab int packet_length; 128786baecfSMauro Carvalho Chehab int packet_payload_length; 129786baecfSMauro Carvalho Chehab u16 next_packet_id; 130786baecfSMauro Carvalho Chehab 131786baecfSMauro Carvalho Chehab int pva_stream_count; 132786baecfSMauro Carvalho Chehab int filter_stream_count; 133786baecfSMauro Carvalho Chehab 134786baecfSMauro Carvalho Chehab struct dvb_filter_pes2ts a_pes2ts; 135786baecfSMauro Carvalho Chehab struct dvb_filter_pes2ts v_pes2ts; 136786baecfSMauro Carvalho Chehab 137786baecfSMauro Carvalho Chehab u8 v_pes[16 + MAX_PVA_LENGTH]; 138786baecfSMauro Carvalho Chehab int v_pes_length; 139786baecfSMauro Carvalho Chehab int v_pes_postbytes; 140786baecfSMauro Carvalho Chehab 141786baecfSMauro Carvalho Chehab struct list_head urb_frame_list; 142786baecfSMauro Carvalho Chehab struct tasklet_struct urb_tasklet; 143786baecfSMauro Carvalho Chehab spinlock_t urb_frame_list_lock; 144786baecfSMauro Carvalho Chehab 145786baecfSMauro Carvalho Chehab struct dvb_demux_filter *audio_filter; 146786baecfSMauro Carvalho Chehab struct dvb_demux_filter *video_filter; 147786baecfSMauro Carvalho Chehab struct list_head filter_info_list; 148786baecfSMauro Carvalho Chehab spinlock_t filter_info_list_lock; 149786baecfSMauro Carvalho Chehab 150786baecfSMauro Carvalho Chehab struct input_dev *rc_input_dev; 151786baecfSMauro Carvalho Chehab char rc_phys[64]; 152786baecfSMauro Carvalho Chehab 153786baecfSMauro Carvalho Chehab int active; /* Loaded successfully */ 154786baecfSMauro Carvalho Chehab }; 155786baecfSMauro Carvalho Chehab 156786baecfSMauro Carvalho Chehab struct urb_frame { 157786baecfSMauro Carvalho Chehab u8 data[ISO_FRAME_SIZE]; 158786baecfSMauro Carvalho Chehab int length; 159786baecfSMauro Carvalho Chehab struct list_head urb_frame_list; 160786baecfSMauro Carvalho Chehab }; 161786baecfSMauro Carvalho Chehab 162786baecfSMauro Carvalho Chehab struct filter_info { 163786baecfSMauro Carvalho Chehab u8 stream_id; 164786baecfSMauro Carvalho Chehab struct dvb_demux_filter *filter; 165786baecfSMauro Carvalho Chehab struct list_head filter_info_list; 166786baecfSMauro Carvalho Chehab }; 167786baecfSMauro Carvalho Chehab 168786baecfSMauro Carvalho Chehab static u16 rc_keys[] = { 169786baecfSMauro Carvalho Chehab KEY_POWER, 170786baecfSMauro Carvalho Chehab KEY_MUTE, 171786baecfSMauro Carvalho Chehab KEY_1, 172786baecfSMauro Carvalho Chehab KEY_2, 173786baecfSMauro Carvalho Chehab KEY_3, 174786baecfSMauro Carvalho Chehab KEY_4, 175786baecfSMauro Carvalho Chehab KEY_5, 176786baecfSMauro Carvalho Chehab KEY_6, 177786baecfSMauro Carvalho Chehab KEY_7, 178786baecfSMauro Carvalho Chehab KEY_8, 179786baecfSMauro Carvalho Chehab KEY_9, 180786baecfSMauro Carvalho Chehab KEY_0, 181786baecfSMauro Carvalho Chehab KEY_CHANNELUP, 182786baecfSMauro Carvalho Chehab KEY_VOLUMEDOWN, 183786baecfSMauro Carvalho Chehab KEY_OK, 184786baecfSMauro Carvalho Chehab KEY_VOLUMEUP, 185786baecfSMauro Carvalho Chehab KEY_CHANNELDOWN, 186786baecfSMauro Carvalho Chehab KEY_PREVIOUS, 187786baecfSMauro Carvalho Chehab KEY_ESC, 188786baecfSMauro Carvalho Chehab KEY_RED, 189786baecfSMauro Carvalho Chehab KEY_GREEN, 190786baecfSMauro Carvalho Chehab KEY_YELLOW, 191786baecfSMauro Carvalho Chehab KEY_BLUE, 192786baecfSMauro Carvalho Chehab KEY_OPTION, 193786baecfSMauro Carvalho Chehab KEY_M, 194786baecfSMauro Carvalho Chehab KEY_RADIO 195786baecfSMauro Carvalho Chehab }; 196786baecfSMauro Carvalho Chehab 197b676e731SMauro Carvalho Chehab static void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, 198b676e731SMauro Carvalho Chehab unsigned short pid, 199b676e731SMauro Carvalho Chehab dvb_filter_pes2ts_cb_t *cb, void *priv) 200b676e731SMauro Carvalho Chehab { 201b676e731SMauro Carvalho Chehab unsigned char *buf=p2ts->buf; 202b676e731SMauro Carvalho Chehab 203b676e731SMauro Carvalho Chehab buf[0]=0x47; 204b676e731SMauro Carvalho Chehab buf[1]=(pid>>8); 205b676e731SMauro Carvalho Chehab buf[2]=pid&0xff; 206b676e731SMauro Carvalho Chehab p2ts->cc=0; 207b676e731SMauro Carvalho Chehab p2ts->cb=cb; 208b676e731SMauro Carvalho Chehab p2ts->priv=priv; 209b676e731SMauro Carvalho Chehab } 210b676e731SMauro Carvalho Chehab 211b676e731SMauro Carvalho Chehab static int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, 212b676e731SMauro Carvalho Chehab unsigned char *pes, int len, int payload_start) 213b676e731SMauro Carvalho Chehab { 214b676e731SMauro Carvalho Chehab unsigned char *buf=p2ts->buf; 215b676e731SMauro Carvalho Chehab int ret=0, rest; 216b676e731SMauro Carvalho Chehab 217b676e731SMauro Carvalho Chehab //len=6+((pes[4]<<8)|pes[5]); 218b676e731SMauro Carvalho Chehab 219b676e731SMauro Carvalho Chehab if (payload_start) 220b676e731SMauro Carvalho Chehab buf[1]|=0x40; 221b676e731SMauro Carvalho Chehab else 222b676e731SMauro Carvalho Chehab buf[1]&=~0x40; 223b676e731SMauro Carvalho Chehab while (len>=184) { 224b676e731SMauro Carvalho Chehab buf[3]=0x10|((p2ts->cc++)&0x0f); 225b676e731SMauro Carvalho Chehab memcpy(buf+4, pes, 184); 226b676e731SMauro Carvalho Chehab if ((ret=p2ts->cb(p2ts->priv, buf))) 227b676e731SMauro Carvalho Chehab return ret; 228b676e731SMauro Carvalho Chehab len-=184; pes+=184; 229b676e731SMauro Carvalho Chehab buf[1]&=~0x40; 230b676e731SMauro Carvalho Chehab } 231b676e731SMauro Carvalho Chehab if (!len) 232b676e731SMauro Carvalho Chehab return 0; 233b676e731SMauro Carvalho Chehab buf[3]=0x30|((p2ts->cc++)&0x0f); 234b676e731SMauro Carvalho Chehab rest=183-len; 235b676e731SMauro Carvalho Chehab if (rest) { 236b676e731SMauro Carvalho Chehab buf[5]=0x00; 237b676e731SMauro Carvalho Chehab if (rest-1) 238b676e731SMauro Carvalho Chehab memset(buf+6, 0xff, rest-1); 239b676e731SMauro Carvalho Chehab } 240b676e731SMauro Carvalho Chehab buf[4]=rest; 241b676e731SMauro Carvalho Chehab memcpy(buf+5+rest, pes, len); 242b676e731SMauro Carvalho Chehab return p2ts->cb(p2ts->priv, buf); 243b676e731SMauro Carvalho Chehab } 244b676e731SMauro Carvalho Chehab 245786baecfSMauro Carvalho Chehab static void ttusb_dec_set_model(struct ttusb_dec *dec, 246786baecfSMauro Carvalho Chehab enum ttusb_dec_model model); 247786baecfSMauro Carvalho Chehab 248786baecfSMauro Carvalho Chehab static void ttusb_dec_handle_irq( struct urb *urb) 249786baecfSMauro Carvalho Chehab { 250786baecfSMauro Carvalho Chehab struct ttusb_dec *dec = urb->context; 251786baecfSMauro Carvalho Chehab char *buffer = dec->irq_buffer; 252786baecfSMauro Carvalho Chehab int retval; 253786baecfSMauro Carvalho Chehab 254786baecfSMauro Carvalho Chehab switch(urb->status) { 255786baecfSMauro Carvalho Chehab case 0: /*success*/ 256786baecfSMauro Carvalho Chehab break; 257786baecfSMauro Carvalho Chehab case -ECONNRESET: 258786baecfSMauro Carvalho Chehab case -ENOENT: 259786baecfSMauro Carvalho Chehab case -ESHUTDOWN: 260786baecfSMauro Carvalho Chehab case -ETIME: 261786baecfSMauro Carvalho Chehab /* this urb is dead, cleanup */ 262786baecfSMauro Carvalho Chehab dprintk("%s:urb shutting down with status: %d\n", 263786baecfSMauro Carvalho Chehab __func__, urb->status); 264786baecfSMauro Carvalho Chehab return; 265786baecfSMauro Carvalho Chehab default: 266786baecfSMauro Carvalho Chehab dprintk("%s:nonzero status received: %d\n", 267786baecfSMauro Carvalho Chehab __func__,urb->status); 268786baecfSMauro Carvalho Chehab goto exit; 269786baecfSMauro Carvalho Chehab } 270786baecfSMauro Carvalho Chehab 271786baecfSMauro Carvalho Chehab if ((buffer[0] == 0x1) && (buffer[2] == 0x15)) { 2723cc26912SMauro Carvalho Chehab /* 2733cc26912SMauro Carvalho Chehab * IR - Event 2743cc26912SMauro Carvalho Chehab * 2753cc26912SMauro Carvalho Chehab * this is an fact a bit too simple implementation; 276786baecfSMauro Carvalho Chehab * the box also reports a keyrepeat signal 2773e4d8f48SMauro Carvalho Chehab * (with buffer[3] == 0x40) in an interval of ~100ms. 278786baecfSMauro Carvalho Chehab * But to handle this correctly we had to imlemenent some 279786baecfSMauro Carvalho Chehab * kind of timer which signals a 'key up' event if no 280786baecfSMauro Carvalho Chehab * keyrepeat signal is received for lets say 200ms. 281786baecfSMauro Carvalho Chehab * this should/could be added later ... 2823cc26912SMauro Carvalho Chehab * for now lets report each signal as a key down and up 2833cc26912SMauro Carvalho Chehab */ 2843cc26912SMauro Carvalho Chehab if (buffer[4] - 1 < ARRAY_SIZE(rc_keys)) { 285786baecfSMauro Carvalho Chehab dprintk("%s:rc signal:%d\n", __func__, buffer[4]); 286786baecfSMauro Carvalho Chehab input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1); 287786baecfSMauro Carvalho Chehab input_sync(dec->rc_input_dev); 288786baecfSMauro Carvalho Chehab input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0); 289786baecfSMauro Carvalho Chehab input_sync(dec->rc_input_dev); 290786baecfSMauro Carvalho Chehab } 2913cc26912SMauro Carvalho Chehab } 292786baecfSMauro Carvalho Chehab 2933cc26912SMauro Carvalho Chehab exit: 2943cc26912SMauro Carvalho Chehab retval = usb_submit_urb(urb, GFP_ATOMIC); 295786baecfSMauro Carvalho Chehab if (retval) 296786baecfSMauro Carvalho Chehab printk("%s - usb_commit_urb failed with result: %d\n", 297786baecfSMauro Carvalho Chehab __func__, retval); 298786baecfSMauro Carvalho Chehab } 299786baecfSMauro Carvalho Chehab 300786baecfSMauro Carvalho Chehab static u16 crc16(u16 crc, const u8 *buf, size_t len) 301786baecfSMauro Carvalho Chehab { 302786baecfSMauro Carvalho Chehab u16 tmp; 303786baecfSMauro Carvalho Chehab 304786baecfSMauro Carvalho Chehab while (len--) { 305786baecfSMauro Carvalho Chehab crc ^= *buf++; 306786baecfSMauro Carvalho Chehab crc ^= (u8)crc >> 4; 307786baecfSMauro Carvalho Chehab tmp = (u8)crc; 308786baecfSMauro Carvalho Chehab crc ^= (tmp ^ (tmp << 1)) << 4; 309786baecfSMauro Carvalho Chehab } 310786baecfSMauro Carvalho Chehab return crc; 311786baecfSMauro Carvalho Chehab } 312786baecfSMauro Carvalho Chehab 313786baecfSMauro Carvalho Chehab static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, 314786baecfSMauro Carvalho Chehab int param_length, const u8 params[], 315786baecfSMauro Carvalho Chehab int *result_length, u8 cmd_result[]) 316786baecfSMauro Carvalho Chehab { 31761fc8749SMauro Carvalho Chehab int result, actual_len; 318786baecfSMauro Carvalho Chehab u8 *b; 319786baecfSMauro Carvalho Chehab 320786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 321786baecfSMauro Carvalho Chehab 322*a10feaf8STomas Bortoli b = kzalloc(COMMAND_PACKET_SIZE + 4, GFP_KERNEL); 323786baecfSMauro Carvalho Chehab if (!b) 324786baecfSMauro Carvalho Chehab return -ENOMEM; 325786baecfSMauro Carvalho Chehab 326786baecfSMauro Carvalho Chehab if ((result = mutex_lock_interruptible(&dec->usb_mutex))) { 327786baecfSMauro Carvalho Chehab kfree(b); 328786baecfSMauro Carvalho Chehab printk("%s: Failed to lock usb mutex.\n", __func__); 329786baecfSMauro Carvalho Chehab return result; 330786baecfSMauro Carvalho Chehab } 331786baecfSMauro Carvalho Chehab 332786baecfSMauro Carvalho Chehab b[0] = 0xaa; 333786baecfSMauro Carvalho Chehab b[1] = ++dec->trans_count; 334786baecfSMauro Carvalho Chehab b[2] = command; 335786baecfSMauro Carvalho Chehab b[3] = param_length; 336786baecfSMauro Carvalho Chehab 337786baecfSMauro Carvalho Chehab if (params) 338786baecfSMauro Carvalho Chehab memcpy(&b[4], params, param_length); 339786baecfSMauro Carvalho Chehab 340786baecfSMauro Carvalho Chehab if (debug) { 34161fc8749SMauro Carvalho Chehab printk(KERN_DEBUG "%s: command: %*ph\n", 34261fc8749SMauro Carvalho Chehab __func__, param_length, b); 343786baecfSMauro Carvalho Chehab } 344786baecfSMauro Carvalho Chehab 345786baecfSMauro Carvalho Chehab result = usb_bulk_msg(dec->udev, dec->command_pipe, b, 346786baecfSMauro Carvalho Chehab COMMAND_PACKET_SIZE + 4, &actual_len, 1000); 347786baecfSMauro Carvalho Chehab 348786baecfSMauro Carvalho Chehab if (result) { 349786baecfSMauro Carvalho Chehab printk("%s: command bulk message failed: error %d\n", 350786baecfSMauro Carvalho Chehab __func__, result); 351786baecfSMauro Carvalho Chehab mutex_unlock(&dec->usb_mutex); 352786baecfSMauro Carvalho Chehab kfree(b); 353786baecfSMauro Carvalho Chehab return result; 354786baecfSMauro Carvalho Chehab } 355786baecfSMauro Carvalho Chehab 356786baecfSMauro Carvalho Chehab result = usb_bulk_msg(dec->udev, dec->result_pipe, b, 357786baecfSMauro Carvalho Chehab COMMAND_PACKET_SIZE + 4, &actual_len, 1000); 358786baecfSMauro Carvalho Chehab 359786baecfSMauro Carvalho Chehab if (result) { 360786baecfSMauro Carvalho Chehab printk("%s: result bulk message failed: error %d\n", 361786baecfSMauro Carvalho Chehab __func__, result); 362786baecfSMauro Carvalho Chehab mutex_unlock(&dec->usb_mutex); 363786baecfSMauro Carvalho Chehab kfree(b); 364786baecfSMauro Carvalho Chehab return result; 365786baecfSMauro Carvalho Chehab } else { 366786baecfSMauro Carvalho Chehab if (debug) { 36761fc8749SMauro Carvalho Chehab printk(KERN_DEBUG "%s: result: %*ph\n", 36861fc8749SMauro Carvalho Chehab __func__, actual_len, b); 369786baecfSMauro Carvalho Chehab } 370786baecfSMauro Carvalho Chehab 371786baecfSMauro Carvalho Chehab if (result_length) 372786baecfSMauro Carvalho Chehab *result_length = b[3]; 373786baecfSMauro Carvalho Chehab if (cmd_result && b[3] > 0) 374786baecfSMauro Carvalho Chehab memcpy(cmd_result, &b[4], b[3]); 375786baecfSMauro Carvalho Chehab 376786baecfSMauro Carvalho Chehab mutex_unlock(&dec->usb_mutex); 377786baecfSMauro Carvalho Chehab 378786baecfSMauro Carvalho Chehab kfree(b); 379786baecfSMauro Carvalho Chehab return 0; 380786baecfSMauro Carvalho Chehab } 381786baecfSMauro Carvalho Chehab } 382786baecfSMauro Carvalho Chehab 383786baecfSMauro Carvalho Chehab static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode, 384786baecfSMauro Carvalho Chehab unsigned int *model, unsigned int *version) 385786baecfSMauro Carvalho Chehab { 386786baecfSMauro Carvalho Chehab u8 c[COMMAND_PACKET_SIZE]; 387786baecfSMauro Carvalho Chehab int c_length; 388786baecfSMauro Carvalho Chehab int result; 389786baecfSMauro Carvalho Chehab __be32 tmp; 390786baecfSMauro Carvalho Chehab 391786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 392786baecfSMauro Carvalho Chehab 393786baecfSMauro Carvalho Chehab result = ttusb_dec_send_command(dec, 0x08, 0, NULL, &c_length, c); 394786baecfSMauro Carvalho Chehab if (result) 395786baecfSMauro Carvalho Chehab return result; 396786baecfSMauro Carvalho Chehab 397786baecfSMauro Carvalho Chehab if (c_length >= 0x0c) { 398786baecfSMauro Carvalho Chehab if (mode != NULL) { 399786baecfSMauro Carvalho Chehab memcpy(&tmp, c, 4); 400786baecfSMauro Carvalho Chehab *mode = ntohl(tmp); 401786baecfSMauro Carvalho Chehab } 402786baecfSMauro Carvalho Chehab if (model != NULL) { 403786baecfSMauro Carvalho Chehab memcpy(&tmp, &c[4], 4); 404786baecfSMauro Carvalho Chehab *model = ntohl(tmp); 405786baecfSMauro Carvalho Chehab } 406786baecfSMauro Carvalho Chehab if (version != NULL) { 407786baecfSMauro Carvalho Chehab memcpy(&tmp, &c[8], 4); 408786baecfSMauro Carvalho Chehab *version = ntohl(tmp); 409786baecfSMauro Carvalho Chehab } 410786baecfSMauro Carvalho Chehab return 0; 411786baecfSMauro Carvalho Chehab } else { 412cf732b5fSAlexey Khoroshilov return -ENOENT; 413786baecfSMauro Carvalho Chehab } 414786baecfSMauro Carvalho Chehab } 415786baecfSMauro Carvalho Chehab 416786baecfSMauro Carvalho Chehab static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data) 417786baecfSMauro Carvalho Chehab { 418786baecfSMauro Carvalho Chehab struct ttusb_dec *dec = priv; 419786baecfSMauro Carvalho Chehab 420786baecfSMauro Carvalho Chehab dec->audio_filter->feed->cb.ts(data, 188, NULL, 0, 421fdbeb962SMauro Carvalho Chehab &dec->audio_filter->feed->feed.ts, NULL); 422786baecfSMauro Carvalho Chehab 423786baecfSMauro Carvalho Chehab return 0; 424786baecfSMauro Carvalho Chehab } 425786baecfSMauro Carvalho Chehab 426786baecfSMauro Carvalho Chehab static int ttusb_dec_video_pes2ts_cb(void *priv, unsigned char *data) 427786baecfSMauro Carvalho Chehab { 428786baecfSMauro Carvalho Chehab struct ttusb_dec *dec = priv; 429786baecfSMauro Carvalho Chehab 430786baecfSMauro Carvalho Chehab dec->video_filter->feed->cb.ts(data, 188, NULL, 0, 431fdbeb962SMauro Carvalho Chehab &dec->video_filter->feed->feed.ts, NULL); 432786baecfSMauro Carvalho Chehab 433786baecfSMauro Carvalho Chehab return 0; 434786baecfSMauro Carvalho Chehab } 435786baecfSMauro Carvalho Chehab 436786baecfSMauro Carvalho Chehab static void ttusb_dec_set_pids(struct ttusb_dec *dec) 437786baecfSMauro Carvalho Chehab { 438786baecfSMauro Carvalho Chehab u8 b[] = { 0x00, 0x00, 0x00, 0x00, 439786baecfSMauro Carvalho Chehab 0x00, 0x00, 0xff, 0xff, 440786baecfSMauro Carvalho Chehab 0xff, 0xff, 0xff, 0xff }; 441786baecfSMauro Carvalho Chehab 442786baecfSMauro Carvalho Chehab __be16 pcr = htons(dec->pid[DMX_PES_PCR]); 443786baecfSMauro Carvalho Chehab __be16 audio = htons(dec->pid[DMX_PES_AUDIO]); 444786baecfSMauro Carvalho Chehab __be16 video = htons(dec->pid[DMX_PES_VIDEO]); 445786baecfSMauro Carvalho Chehab 446786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 447786baecfSMauro Carvalho Chehab 448786baecfSMauro Carvalho Chehab memcpy(&b[0], &pcr, 2); 449786baecfSMauro Carvalho Chehab memcpy(&b[2], &audio, 2); 450786baecfSMauro Carvalho Chehab memcpy(&b[4], &video, 2); 451786baecfSMauro Carvalho Chehab 452786baecfSMauro Carvalho Chehab ttusb_dec_send_command(dec, 0x50, sizeof(b), b, NULL, NULL); 453786baecfSMauro Carvalho Chehab 454786baecfSMauro Carvalho Chehab dvb_filter_pes2ts_init(&dec->a_pes2ts, dec->pid[DMX_PES_AUDIO], 455786baecfSMauro Carvalho Chehab ttusb_dec_audio_pes2ts_cb, dec); 456786baecfSMauro Carvalho Chehab dvb_filter_pes2ts_init(&dec->v_pes2ts, dec->pid[DMX_PES_VIDEO], 457786baecfSMauro Carvalho Chehab ttusb_dec_video_pes2ts_cb, dec); 458786baecfSMauro Carvalho Chehab dec->v_pes_length = 0; 459786baecfSMauro Carvalho Chehab dec->v_pes_postbytes = 0; 460786baecfSMauro Carvalho Chehab } 461786baecfSMauro Carvalho Chehab 462786baecfSMauro Carvalho Chehab static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length) 463786baecfSMauro Carvalho Chehab { 464786baecfSMauro Carvalho Chehab if (length < 8) { 465786baecfSMauro Carvalho Chehab printk("%s: packet too short - discarding\n", __func__); 466786baecfSMauro Carvalho Chehab return; 467786baecfSMauro Carvalho Chehab } 468786baecfSMauro Carvalho Chehab 469786baecfSMauro Carvalho Chehab if (length > 8 + MAX_PVA_LENGTH) { 470786baecfSMauro Carvalho Chehab printk("%s: packet too long - discarding\n", __func__); 471786baecfSMauro Carvalho Chehab return; 472786baecfSMauro Carvalho Chehab } 473786baecfSMauro Carvalho Chehab 474786baecfSMauro Carvalho Chehab switch (pva[2]) { 475786baecfSMauro Carvalho Chehab 476786baecfSMauro Carvalho Chehab case 0x01: { /* VideoStream */ 477786baecfSMauro Carvalho Chehab int prebytes = pva[5] & 0x03; 478786baecfSMauro Carvalho Chehab int postbytes = (pva[5] & 0x0c) >> 2; 479786baecfSMauro Carvalho Chehab __be16 v_pes_payload_length; 480786baecfSMauro Carvalho Chehab 481786baecfSMauro Carvalho Chehab if (output_pva) { 482786baecfSMauro Carvalho Chehab dec->video_filter->feed->cb.ts(pva, length, NULL, 0, 483fdbeb962SMauro Carvalho Chehab &dec->video_filter->feed->feed.ts, NULL); 484786baecfSMauro Carvalho Chehab return; 485786baecfSMauro Carvalho Chehab } 486786baecfSMauro Carvalho Chehab 487786baecfSMauro Carvalho Chehab if (dec->v_pes_postbytes > 0 && 488786baecfSMauro Carvalho Chehab dec->v_pes_postbytes == prebytes) { 489786baecfSMauro Carvalho Chehab memcpy(&dec->v_pes[dec->v_pes_length], 490786baecfSMauro Carvalho Chehab &pva[12], prebytes); 491786baecfSMauro Carvalho Chehab 492786baecfSMauro Carvalho Chehab dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes, 493786baecfSMauro Carvalho Chehab dec->v_pes_length + prebytes, 1); 494786baecfSMauro Carvalho Chehab } 495786baecfSMauro Carvalho Chehab 496786baecfSMauro Carvalho Chehab if (pva[5] & 0x10) { 497786baecfSMauro Carvalho Chehab dec->v_pes[7] = 0x80; 498786baecfSMauro Carvalho Chehab dec->v_pes[8] = 0x05; 499786baecfSMauro Carvalho Chehab 500786baecfSMauro Carvalho Chehab dec->v_pes[9] = 0x21 | ((pva[8] & 0xc0) >> 5); 501786baecfSMauro Carvalho Chehab dec->v_pes[10] = ((pva[8] & 0x3f) << 2) | 502786baecfSMauro Carvalho Chehab ((pva[9] & 0xc0) >> 6); 503786baecfSMauro Carvalho Chehab dec->v_pes[11] = 0x01 | 504786baecfSMauro Carvalho Chehab ((pva[9] & 0x3f) << 2) | 505786baecfSMauro Carvalho Chehab ((pva[10] & 0x80) >> 6); 506786baecfSMauro Carvalho Chehab dec->v_pes[12] = ((pva[10] & 0x7f) << 1) | 507786baecfSMauro Carvalho Chehab ((pva[11] & 0xc0) >> 7); 508786baecfSMauro Carvalho Chehab dec->v_pes[13] = 0x01 | ((pva[11] & 0x7f) << 1); 509786baecfSMauro Carvalho Chehab 510786baecfSMauro Carvalho Chehab memcpy(&dec->v_pes[14], &pva[12 + prebytes], 511786baecfSMauro Carvalho Chehab length - 12 - prebytes); 512786baecfSMauro Carvalho Chehab dec->v_pes_length = 14 + length - 12 - prebytes; 513786baecfSMauro Carvalho Chehab } else { 514786baecfSMauro Carvalho Chehab dec->v_pes[7] = 0x00; 515786baecfSMauro Carvalho Chehab dec->v_pes[8] = 0x00; 516786baecfSMauro Carvalho Chehab 517786baecfSMauro Carvalho Chehab memcpy(&dec->v_pes[9], &pva[8], length - 8); 518786baecfSMauro Carvalho Chehab dec->v_pes_length = 9 + length - 8; 519786baecfSMauro Carvalho Chehab } 520786baecfSMauro Carvalho Chehab 521786baecfSMauro Carvalho Chehab dec->v_pes_postbytes = postbytes; 522786baecfSMauro Carvalho Chehab 523786baecfSMauro Carvalho Chehab if (dec->v_pes[9 + dec->v_pes[8]] == 0x00 && 524786baecfSMauro Carvalho Chehab dec->v_pes[10 + dec->v_pes[8]] == 0x00 && 525786baecfSMauro Carvalho Chehab dec->v_pes[11 + dec->v_pes[8]] == 0x01) 526786baecfSMauro Carvalho Chehab dec->v_pes[6] = 0x84; 527786baecfSMauro Carvalho Chehab else 528786baecfSMauro Carvalho Chehab dec->v_pes[6] = 0x80; 529786baecfSMauro Carvalho Chehab 530786baecfSMauro Carvalho Chehab v_pes_payload_length = htons(dec->v_pes_length - 6 + 531786baecfSMauro Carvalho Chehab postbytes); 532786baecfSMauro Carvalho Chehab memcpy(&dec->v_pes[4], &v_pes_payload_length, 2); 533786baecfSMauro Carvalho Chehab 534786baecfSMauro Carvalho Chehab if (postbytes == 0) 535786baecfSMauro Carvalho Chehab dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes, 536786baecfSMauro Carvalho Chehab dec->v_pes_length, 1); 537786baecfSMauro Carvalho Chehab 538786baecfSMauro Carvalho Chehab break; 539786baecfSMauro Carvalho Chehab } 540786baecfSMauro Carvalho Chehab 541786baecfSMauro Carvalho Chehab case 0x02: /* MainAudioStream */ 542786baecfSMauro Carvalho Chehab if (output_pva) { 543786baecfSMauro Carvalho Chehab dec->audio_filter->feed->cb.ts(pva, length, NULL, 0, 544fdbeb962SMauro Carvalho Chehab &dec->audio_filter->feed->feed.ts, NULL); 545786baecfSMauro Carvalho Chehab return; 546786baecfSMauro Carvalho Chehab } 547786baecfSMauro Carvalho Chehab 548786baecfSMauro Carvalho Chehab dvb_filter_pes2ts(&dec->a_pes2ts, &pva[8], length - 8, 549786baecfSMauro Carvalho Chehab pva[5] & 0x10); 550786baecfSMauro Carvalho Chehab break; 551786baecfSMauro Carvalho Chehab 552786baecfSMauro Carvalho Chehab default: 553786baecfSMauro Carvalho Chehab printk("%s: unknown PVA type: %02x.\n", __func__, 554786baecfSMauro Carvalho Chehab pva[2]); 555786baecfSMauro Carvalho Chehab break; 556786baecfSMauro Carvalho Chehab } 557786baecfSMauro Carvalho Chehab } 558786baecfSMauro Carvalho Chehab 559786baecfSMauro Carvalho Chehab static void ttusb_dec_process_filter(struct ttusb_dec *dec, u8 *packet, 560786baecfSMauro Carvalho Chehab int length) 561786baecfSMauro Carvalho Chehab { 562786baecfSMauro Carvalho Chehab struct list_head *item; 563786baecfSMauro Carvalho Chehab struct filter_info *finfo; 564786baecfSMauro Carvalho Chehab struct dvb_demux_filter *filter = NULL; 565786baecfSMauro Carvalho Chehab unsigned long flags; 566786baecfSMauro Carvalho Chehab u8 sid; 567786baecfSMauro Carvalho Chehab 568786baecfSMauro Carvalho Chehab sid = packet[1]; 569786baecfSMauro Carvalho Chehab spin_lock_irqsave(&dec->filter_info_list_lock, flags); 570786baecfSMauro Carvalho Chehab for (item = dec->filter_info_list.next; item != &dec->filter_info_list; 571786baecfSMauro Carvalho Chehab item = item->next) { 572786baecfSMauro Carvalho Chehab finfo = list_entry(item, struct filter_info, filter_info_list); 573786baecfSMauro Carvalho Chehab if (finfo->stream_id == sid) { 574786baecfSMauro Carvalho Chehab filter = finfo->filter; 575786baecfSMauro Carvalho Chehab break; 576786baecfSMauro Carvalho Chehab } 577786baecfSMauro Carvalho Chehab } 578786baecfSMauro Carvalho Chehab spin_unlock_irqrestore(&dec->filter_info_list_lock, flags); 579786baecfSMauro Carvalho Chehab 580786baecfSMauro Carvalho Chehab if (filter) 581786baecfSMauro Carvalho Chehab filter->feed->cb.sec(&packet[2], length - 2, NULL, 0, 582fdbeb962SMauro Carvalho Chehab &filter->filter, NULL); 583786baecfSMauro Carvalho Chehab } 584786baecfSMauro Carvalho Chehab 585786baecfSMauro Carvalho Chehab static void ttusb_dec_process_packet(struct ttusb_dec *dec) 586786baecfSMauro Carvalho Chehab { 587786baecfSMauro Carvalho Chehab int i; 588786baecfSMauro Carvalho Chehab u16 csum = 0; 589786baecfSMauro Carvalho Chehab u16 packet_id; 590786baecfSMauro Carvalho Chehab 591786baecfSMauro Carvalho Chehab if (dec->packet_length % 2) { 592786baecfSMauro Carvalho Chehab printk("%s: odd sized packet - discarding\n", __func__); 593786baecfSMauro Carvalho Chehab return; 594786baecfSMauro Carvalho Chehab } 595786baecfSMauro Carvalho Chehab 596786baecfSMauro Carvalho Chehab for (i = 0; i < dec->packet_length; i += 2) 597786baecfSMauro Carvalho Chehab csum ^= ((dec->packet[i] << 8) + dec->packet[i + 1]); 598786baecfSMauro Carvalho Chehab 599786baecfSMauro Carvalho Chehab if (csum) { 600786baecfSMauro Carvalho Chehab printk("%s: checksum failed - discarding\n", __func__); 601786baecfSMauro Carvalho Chehab return; 602786baecfSMauro Carvalho Chehab } 603786baecfSMauro Carvalho Chehab 604786baecfSMauro Carvalho Chehab packet_id = dec->packet[dec->packet_length - 4] << 8; 605786baecfSMauro Carvalho Chehab packet_id += dec->packet[dec->packet_length - 3]; 606786baecfSMauro Carvalho Chehab 607786baecfSMauro Carvalho Chehab if ((packet_id != dec->next_packet_id) && dec->next_packet_id) { 608786baecfSMauro Carvalho Chehab printk("%s: warning: lost packets between %u and %u\n", 609786baecfSMauro Carvalho Chehab __func__, dec->next_packet_id - 1, packet_id); 610786baecfSMauro Carvalho Chehab } 611786baecfSMauro Carvalho Chehab 612786baecfSMauro Carvalho Chehab if (packet_id == 0xffff) 613786baecfSMauro Carvalho Chehab dec->next_packet_id = 0x8000; 614786baecfSMauro Carvalho Chehab else 615786baecfSMauro Carvalho Chehab dec->next_packet_id = packet_id + 1; 616786baecfSMauro Carvalho Chehab 617786baecfSMauro Carvalho Chehab switch (dec->packet_type) { 618786baecfSMauro Carvalho Chehab case TTUSB_DEC_PACKET_PVA: 619786baecfSMauro Carvalho Chehab if (dec->pva_stream_count) 620786baecfSMauro Carvalho Chehab ttusb_dec_process_pva(dec, dec->packet, 621786baecfSMauro Carvalho Chehab dec->packet_payload_length); 622786baecfSMauro Carvalho Chehab break; 623786baecfSMauro Carvalho Chehab 624786baecfSMauro Carvalho Chehab case TTUSB_DEC_PACKET_SECTION: 625786baecfSMauro Carvalho Chehab if (dec->filter_stream_count) 626786baecfSMauro Carvalho Chehab ttusb_dec_process_filter(dec, dec->packet, 627786baecfSMauro Carvalho Chehab dec->packet_payload_length); 628786baecfSMauro Carvalho Chehab break; 629786baecfSMauro Carvalho Chehab 630786baecfSMauro Carvalho Chehab case TTUSB_DEC_PACKET_EMPTY: 631786baecfSMauro Carvalho Chehab break; 632786baecfSMauro Carvalho Chehab } 633786baecfSMauro Carvalho Chehab } 634786baecfSMauro Carvalho Chehab 635786baecfSMauro Carvalho Chehab static void swap_bytes(u8 *b, int length) 636786baecfSMauro Carvalho Chehab { 637786baecfSMauro Carvalho Chehab length -= length % 2; 63841cc14baSFabian Frederick for (; length; b += 2, length -= 2) 63941cc14baSFabian Frederick swap(*b, *(b + 1)); 640786baecfSMauro Carvalho Chehab } 641786baecfSMauro Carvalho Chehab 642786baecfSMauro Carvalho Chehab static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b, 643786baecfSMauro Carvalho Chehab int length) 644786baecfSMauro Carvalho Chehab { 645786baecfSMauro Carvalho Chehab swap_bytes(b, length); 646786baecfSMauro Carvalho Chehab 647786baecfSMauro Carvalho Chehab while (length) { 648786baecfSMauro Carvalho Chehab switch (dec->packet_state) { 649786baecfSMauro Carvalho Chehab 650786baecfSMauro Carvalho Chehab case 0: 651786baecfSMauro Carvalho Chehab case 1: 652786baecfSMauro Carvalho Chehab case 2: 653786baecfSMauro Carvalho Chehab if (*b++ == 0xaa) 654786baecfSMauro Carvalho Chehab dec->packet_state++; 655786baecfSMauro Carvalho Chehab else 656786baecfSMauro Carvalho Chehab dec->packet_state = 0; 657786baecfSMauro Carvalho Chehab 658786baecfSMauro Carvalho Chehab length--; 659786baecfSMauro Carvalho Chehab break; 660786baecfSMauro Carvalho Chehab 661786baecfSMauro Carvalho Chehab case 3: 662786baecfSMauro Carvalho Chehab if (*b == 0x00) { 663786baecfSMauro Carvalho Chehab dec->packet_state++; 664786baecfSMauro Carvalho Chehab dec->packet_length = 0; 665786baecfSMauro Carvalho Chehab } else if (*b != 0xaa) { 666786baecfSMauro Carvalho Chehab dec->packet_state = 0; 667786baecfSMauro Carvalho Chehab } 668786baecfSMauro Carvalho Chehab 669786baecfSMauro Carvalho Chehab b++; 670786baecfSMauro Carvalho Chehab length--; 671786baecfSMauro Carvalho Chehab break; 672786baecfSMauro Carvalho Chehab 673786baecfSMauro Carvalho Chehab case 4: 674786baecfSMauro Carvalho Chehab dec->packet[dec->packet_length++] = *b++; 675786baecfSMauro Carvalho Chehab 676786baecfSMauro Carvalho Chehab if (dec->packet_length == 2) { 677786baecfSMauro Carvalho Chehab if (dec->packet[0] == 'A' && 678786baecfSMauro Carvalho Chehab dec->packet[1] == 'V') { 679786baecfSMauro Carvalho Chehab dec->packet_type = 680786baecfSMauro Carvalho Chehab TTUSB_DEC_PACKET_PVA; 681786baecfSMauro Carvalho Chehab dec->packet_state++; 682786baecfSMauro Carvalho Chehab } else if (dec->packet[0] == 'S') { 683786baecfSMauro Carvalho Chehab dec->packet_type = 684786baecfSMauro Carvalho Chehab TTUSB_DEC_PACKET_SECTION; 685786baecfSMauro Carvalho Chehab dec->packet_state++; 686786baecfSMauro Carvalho Chehab } else if (dec->packet[0] == 0x00) { 687786baecfSMauro Carvalho Chehab dec->packet_type = 688786baecfSMauro Carvalho Chehab TTUSB_DEC_PACKET_EMPTY; 689786baecfSMauro Carvalho Chehab dec->packet_payload_length = 2; 690786baecfSMauro Carvalho Chehab dec->packet_state = 7; 691786baecfSMauro Carvalho Chehab } else { 692bf769a4eSMauro Carvalho Chehab printk("%s: unknown packet type: %02x%02x\n", 693bf769a4eSMauro Carvalho Chehab __func__, 694786baecfSMauro Carvalho Chehab dec->packet[0], dec->packet[1]); 695786baecfSMauro Carvalho Chehab dec->packet_state = 0; 696786baecfSMauro Carvalho Chehab } 697786baecfSMauro Carvalho Chehab } 698786baecfSMauro Carvalho Chehab 699786baecfSMauro Carvalho Chehab length--; 700786baecfSMauro Carvalho Chehab break; 701786baecfSMauro Carvalho Chehab 702786baecfSMauro Carvalho Chehab case 5: 703786baecfSMauro Carvalho Chehab dec->packet[dec->packet_length++] = *b++; 704786baecfSMauro Carvalho Chehab 705786baecfSMauro Carvalho Chehab if (dec->packet_type == TTUSB_DEC_PACKET_PVA && 706786baecfSMauro Carvalho Chehab dec->packet_length == 8) { 707786baecfSMauro Carvalho Chehab dec->packet_state++; 708786baecfSMauro Carvalho Chehab dec->packet_payload_length = 8 + 709786baecfSMauro Carvalho Chehab (dec->packet[6] << 8) + 710786baecfSMauro Carvalho Chehab dec->packet[7]; 711786baecfSMauro Carvalho Chehab } else if (dec->packet_type == 712786baecfSMauro Carvalho Chehab TTUSB_DEC_PACKET_SECTION && 713786baecfSMauro Carvalho Chehab dec->packet_length == 5) { 714786baecfSMauro Carvalho Chehab dec->packet_state++; 715786baecfSMauro Carvalho Chehab dec->packet_payload_length = 5 + 716786baecfSMauro Carvalho Chehab ((dec->packet[3] & 0x0f) << 8) + 717786baecfSMauro Carvalho Chehab dec->packet[4]; 718786baecfSMauro Carvalho Chehab } 719786baecfSMauro Carvalho Chehab 720786baecfSMauro Carvalho Chehab length--; 721786baecfSMauro Carvalho Chehab break; 722786baecfSMauro Carvalho Chehab 723786baecfSMauro Carvalho Chehab case 6: { 724786baecfSMauro Carvalho Chehab int remainder = dec->packet_payload_length - 725786baecfSMauro Carvalho Chehab dec->packet_length; 726786baecfSMauro Carvalho Chehab 727786baecfSMauro Carvalho Chehab if (length >= remainder) { 728786baecfSMauro Carvalho Chehab memcpy(dec->packet + dec->packet_length, 729786baecfSMauro Carvalho Chehab b, remainder); 730786baecfSMauro Carvalho Chehab dec->packet_length += remainder; 731786baecfSMauro Carvalho Chehab b += remainder; 732786baecfSMauro Carvalho Chehab length -= remainder; 733786baecfSMauro Carvalho Chehab dec->packet_state++; 734786baecfSMauro Carvalho Chehab } else { 735786baecfSMauro Carvalho Chehab memcpy(&dec->packet[dec->packet_length], 736786baecfSMauro Carvalho Chehab b, length); 737786baecfSMauro Carvalho Chehab dec->packet_length += length; 738786baecfSMauro Carvalho Chehab length = 0; 739786baecfSMauro Carvalho Chehab } 740786baecfSMauro Carvalho Chehab 741786baecfSMauro Carvalho Chehab break; 742786baecfSMauro Carvalho Chehab } 743786baecfSMauro Carvalho Chehab 744786baecfSMauro Carvalho Chehab case 7: { 745786baecfSMauro Carvalho Chehab int tail = 4; 746786baecfSMauro Carvalho Chehab 747786baecfSMauro Carvalho Chehab dec->packet[dec->packet_length++] = *b++; 748786baecfSMauro Carvalho Chehab 749786baecfSMauro Carvalho Chehab if (dec->packet_type == TTUSB_DEC_PACKET_SECTION && 750786baecfSMauro Carvalho Chehab dec->packet_payload_length % 2) 751786baecfSMauro Carvalho Chehab tail++; 752786baecfSMauro Carvalho Chehab 753786baecfSMauro Carvalho Chehab if (dec->packet_length == 754786baecfSMauro Carvalho Chehab dec->packet_payload_length + tail) { 755786baecfSMauro Carvalho Chehab ttusb_dec_process_packet(dec); 756786baecfSMauro Carvalho Chehab dec->packet_state = 0; 757786baecfSMauro Carvalho Chehab } 758786baecfSMauro Carvalho Chehab 759786baecfSMauro Carvalho Chehab length--; 760786baecfSMauro Carvalho Chehab break; 761786baecfSMauro Carvalho Chehab } 762786baecfSMauro Carvalho Chehab 763786baecfSMauro Carvalho Chehab default: 764786baecfSMauro Carvalho Chehab printk("%s: illegal packet state encountered.\n", 765786baecfSMauro Carvalho Chehab __func__); 766786baecfSMauro Carvalho Chehab dec->packet_state = 0; 767786baecfSMauro Carvalho Chehab } 768786baecfSMauro Carvalho Chehab } 769786baecfSMauro Carvalho Chehab } 770786baecfSMauro Carvalho Chehab 771786baecfSMauro Carvalho Chehab static void ttusb_dec_process_urb_frame_list(unsigned long data) 772786baecfSMauro Carvalho Chehab { 773786baecfSMauro Carvalho Chehab struct ttusb_dec *dec = (struct ttusb_dec *)data; 774786baecfSMauro Carvalho Chehab struct list_head *item; 775786baecfSMauro Carvalho Chehab struct urb_frame *frame; 776786baecfSMauro Carvalho Chehab unsigned long flags; 777786baecfSMauro Carvalho Chehab 778786baecfSMauro Carvalho Chehab while (1) { 779786baecfSMauro Carvalho Chehab spin_lock_irqsave(&dec->urb_frame_list_lock, flags); 780786baecfSMauro Carvalho Chehab if ((item = dec->urb_frame_list.next) != &dec->urb_frame_list) { 781786baecfSMauro Carvalho Chehab frame = list_entry(item, struct urb_frame, 782786baecfSMauro Carvalho Chehab urb_frame_list); 783786baecfSMauro Carvalho Chehab list_del(&frame->urb_frame_list); 784786baecfSMauro Carvalho Chehab } else { 785786baecfSMauro Carvalho Chehab spin_unlock_irqrestore(&dec->urb_frame_list_lock, 786786baecfSMauro Carvalho Chehab flags); 787786baecfSMauro Carvalho Chehab return; 788786baecfSMauro Carvalho Chehab } 789786baecfSMauro Carvalho Chehab spin_unlock_irqrestore(&dec->urb_frame_list_lock, flags); 790786baecfSMauro Carvalho Chehab 791786baecfSMauro Carvalho Chehab ttusb_dec_process_urb_frame(dec, frame->data, frame->length); 792786baecfSMauro Carvalho Chehab kfree(frame); 793786baecfSMauro Carvalho Chehab } 794786baecfSMauro Carvalho Chehab } 795786baecfSMauro Carvalho Chehab 796786baecfSMauro Carvalho Chehab static void ttusb_dec_process_urb(struct urb *urb) 797786baecfSMauro Carvalho Chehab { 798786baecfSMauro Carvalho Chehab struct ttusb_dec *dec = urb->context; 799786baecfSMauro Carvalho Chehab 800786baecfSMauro Carvalho Chehab if (!urb->status) { 801786baecfSMauro Carvalho Chehab int i; 802786baecfSMauro Carvalho Chehab 803786baecfSMauro Carvalho Chehab for (i = 0; i < FRAMES_PER_ISO_BUF; i++) { 804786baecfSMauro Carvalho Chehab struct usb_iso_packet_descriptor *d; 805786baecfSMauro Carvalho Chehab u8 *b; 806786baecfSMauro Carvalho Chehab int length; 807786baecfSMauro Carvalho Chehab struct urb_frame *frame; 808786baecfSMauro Carvalho Chehab 809786baecfSMauro Carvalho Chehab d = &urb->iso_frame_desc[i]; 810786baecfSMauro Carvalho Chehab b = urb->transfer_buffer + d->offset; 811786baecfSMauro Carvalho Chehab length = d->actual_length; 812786baecfSMauro Carvalho Chehab 813786baecfSMauro Carvalho Chehab if ((frame = kmalloc(sizeof(struct urb_frame), 814786baecfSMauro Carvalho Chehab GFP_ATOMIC))) { 815786baecfSMauro Carvalho Chehab unsigned long flags; 816786baecfSMauro Carvalho Chehab 817786baecfSMauro Carvalho Chehab memcpy(frame->data, b, length); 818786baecfSMauro Carvalho Chehab frame->length = length; 819786baecfSMauro Carvalho Chehab 820786baecfSMauro Carvalho Chehab spin_lock_irqsave(&dec->urb_frame_list_lock, 821786baecfSMauro Carvalho Chehab flags); 822786baecfSMauro Carvalho Chehab list_add_tail(&frame->urb_frame_list, 823786baecfSMauro Carvalho Chehab &dec->urb_frame_list); 824786baecfSMauro Carvalho Chehab spin_unlock_irqrestore(&dec->urb_frame_list_lock, 825786baecfSMauro Carvalho Chehab flags); 826786baecfSMauro Carvalho Chehab 827786baecfSMauro Carvalho Chehab tasklet_schedule(&dec->urb_tasklet); 828786baecfSMauro Carvalho Chehab } 829786baecfSMauro Carvalho Chehab } 830786baecfSMauro Carvalho Chehab } else { 831786baecfSMauro Carvalho Chehab /* -ENOENT is expected when unlinking urbs */ 832786baecfSMauro Carvalho Chehab if (urb->status != -ENOENT) 833786baecfSMauro Carvalho Chehab dprintk("%s: urb error: %d\n", __func__, 834786baecfSMauro Carvalho Chehab urb->status); 835786baecfSMauro Carvalho Chehab } 836786baecfSMauro Carvalho Chehab 837786baecfSMauro Carvalho Chehab if (dec->iso_stream_count) 838786baecfSMauro Carvalho Chehab usb_submit_urb(urb, GFP_ATOMIC); 839786baecfSMauro Carvalho Chehab } 840786baecfSMauro Carvalho Chehab 841786baecfSMauro Carvalho Chehab static void ttusb_dec_setup_urbs(struct ttusb_dec *dec) 842786baecfSMauro Carvalho Chehab { 843786baecfSMauro Carvalho Chehab int i, j, buffer_offset = 0; 844786baecfSMauro Carvalho Chehab 845786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 846786baecfSMauro Carvalho Chehab 847786baecfSMauro Carvalho Chehab for (i = 0; i < ISO_BUF_COUNT; i++) { 848786baecfSMauro Carvalho Chehab int frame_offset = 0; 849786baecfSMauro Carvalho Chehab struct urb *urb = dec->iso_urb[i]; 850786baecfSMauro Carvalho Chehab 851786baecfSMauro Carvalho Chehab urb->dev = dec->udev; 852786baecfSMauro Carvalho Chehab urb->context = dec; 853786baecfSMauro Carvalho Chehab urb->complete = ttusb_dec_process_urb; 854786baecfSMauro Carvalho Chehab urb->pipe = dec->in_pipe; 855786baecfSMauro Carvalho Chehab urb->transfer_flags = URB_ISO_ASAP; 856786baecfSMauro Carvalho Chehab urb->interval = 1; 857786baecfSMauro Carvalho Chehab urb->number_of_packets = FRAMES_PER_ISO_BUF; 858786baecfSMauro Carvalho Chehab urb->transfer_buffer_length = ISO_FRAME_SIZE * 859786baecfSMauro Carvalho Chehab FRAMES_PER_ISO_BUF; 860786baecfSMauro Carvalho Chehab urb->transfer_buffer = dec->iso_buffer + buffer_offset; 861786baecfSMauro Carvalho Chehab buffer_offset += ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF; 862786baecfSMauro Carvalho Chehab 863786baecfSMauro Carvalho Chehab for (j = 0; j < FRAMES_PER_ISO_BUF; j++) { 864786baecfSMauro Carvalho Chehab urb->iso_frame_desc[j].offset = frame_offset; 865786baecfSMauro Carvalho Chehab urb->iso_frame_desc[j].length = ISO_FRAME_SIZE; 866786baecfSMauro Carvalho Chehab frame_offset += ISO_FRAME_SIZE; 867786baecfSMauro Carvalho Chehab } 868786baecfSMauro Carvalho Chehab } 869786baecfSMauro Carvalho Chehab } 870786baecfSMauro Carvalho Chehab 871786baecfSMauro Carvalho Chehab static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec) 872786baecfSMauro Carvalho Chehab { 873786baecfSMauro Carvalho Chehab int i; 874786baecfSMauro Carvalho Chehab 875786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 876786baecfSMauro Carvalho Chehab 877786baecfSMauro Carvalho Chehab if (mutex_lock_interruptible(&dec->iso_mutex)) 878786baecfSMauro Carvalho Chehab return; 879786baecfSMauro Carvalho Chehab 880786baecfSMauro Carvalho Chehab dec->iso_stream_count--; 881786baecfSMauro Carvalho Chehab 882786baecfSMauro Carvalho Chehab if (!dec->iso_stream_count) { 883786baecfSMauro Carvalho Chehab for (i = 0; i < ISO_BUF_COUNT; i++) 884786baecfSMauro Carvalho Chehab usb_kill_urb(dec->iso_urb[i]); 885786baecfSMauro Carvalho Chehab } 886786baecfSMauro Carvalho Chehab 887786baecfSMauro Carvalho Chehab mutex_unlock(&dec->iso_mutex); 888786baecfSMauro Carvalho Chehab } 889786baecfSMauro Carvalho Chehab 890786baecfSMauro Carvalho Chehab /* Setting the interface of the DEC tends to take down the USB communications 891786baecfSMauro Carvalho Chehab * for a short period, so it's important not to call this function just before 892786baecfSMauro Carvalho Chehab * trying to talk to it. 893786baecfSMauro Carvalho Chehab */ 894786baecfSMauro Carvalho Chehab static int ttusb_dec_set_interface(struct ttusb_dec *dec, 895786baecfSMauro Carvalho Chehab enum ttusb_dec_interface interface) 896786baecfSMauro Carvalho Chehab { 897786baecfSMauro Carvalho Chehab int result = 0; 898786baecfSMauro Carvalho Chehab u8 b[] = { 0x05 }; 899786baecfSMauro Carvalho Chehab 900786baecfSMauro Carvalho Chehab if (interface != dec->interface) { 901786baecfSMauro Carvalho Chehab switch (interface) { 902786baecfSMauro Carvalho Chehab case TTUSB_DEC_INTERFACE_INITIAL: 903786baecfSMauro Carvalho Chehab result = usb_set_interface(dec->udev, 0, 0); 904786baecfSMauro Carvalho Chehab break; 905786baecfSMauro Carvalho Chehab case TTUSB_DEC_INTERFACE_IN: 906786baecfSMauro Carvalho Chehab result = ttusb_dec_send_command(dec, 0x80, sizeof(b), 907786baecfSMauro Carvalho Chehab b, NULL, NULL); 908786baecfSMauro Carvalho Chehab if (result) 909786baecfSMauro Carvalho Chehab return result; 910786baecfSMauro Carvalho Chehab result = usb_set_interface(dec->udev, 0, 8); 911786baecfSMauro Carvalho Chehab break; 912786baecfSMauro Carvalho Chehab case TTUSB_DEC_INTERFACE_OUT: 913786baecfSMauro Carvalho Chehab result = usb_set_interface(dec->udev, 0, 1); 914786baecfSMauro Carvalho Chehab break; 915786baecfSMauro Carvalho Chehab } 916786baecfSMauro Carvalho Chehab 917786baecfSMauro Carvalho Chehab if (result) 918786baecfSMauro Carvalho Chehab return result; 919786baecfSMauro Carvalho Chehab 920786baecfSMauro Carvalho Chehab dec->interface = interface; 921786baecfSMauro Carvalho Chehab } 922786baecfSMauro Carvalho Chehab 923786baecfSMauro Carvalho Chehab return 0; 924786baecfSMauro Carvalho Chehab } 925786baecfSMauro Carvalho Chehab 926786baecfSMauro Carvalho Chehab static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec) 927786baecfSMauro Carvalho Chehab { 928786baecfSMauro Carvalho Chehab int i, result; 929786baecfSMauro Carvalho Chehab 930786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 931786baecfSMauro Carvalho Chehab 932786baecfSMauro Carvalho Chehab if (mutex_lock_interruptible(&dec->iso_mutex)) 933786baecfSMauro Carvalho Chehab return -EAGAIN; 934786baecfSMauro Carvalho Chehab 935786baecfSMauro Carvalho Chehab if (!dec->iso_stream_count) { 936786baecfSMauro Carvalho Chehab ttusb_dec_setup_urbs(dec); 937786baecfSMauro Carvalho Chehab 938786baecfSMauro Carvalho Chehab dec->packet_state = 0; 939786baecfSMauro Carvalho Chehab dec->v_pes_postbytes = 0; 940786baecfSMauro Carvalho Chehab dec->next_packet_id = 0; 941786baecfSMauro Carvalho Chehab 942786baecfSMauro Carvalho Chehab for (i = 0; i < ISO_BUF_COUNT; i++) { 943786baecfSMauro Carvalho Chehab if ((result = usb_submit_urb(dec->iso_urb[i], 944786baecfSMauro Carvalho Chehab GFP_ATOMIC))) { 945bf769a4eSMauro Carvalho Chehab printk("%s: failed urb submission %d: error %d\n", 946bf769a4eSMauro Carvalho Chehab __func__, i, result); 947786baecfSMauro Carvalho Chehab 948786baecfSMauro Carvalho Chehab while (i) { 949786baecfSMauro Carvalho Chehab usb_kill_urb(dec->iso_urb[i - 1]); 950786baecfSMauro Carvalho Chehab i--; 951786baecfSMauro Carvalho Chehab } 952786baecfSMauro Carvalho Chehab 953786baecfSMauro Carvalho Chehab mutex_unlock(&dec->iso_mutex); 954786baecfSMauro Carvalho Chehab return result; 955786baecfSMauro Carvalho Chehab } 956786baecfSMauro Carvalho Chehab } 957786baecfSMauro Carvalho Chehab } 958786baecfSMauro Carvalho Chehab 959786baecfSMauro Carvalho Chehab dec->iso_stream_count++; 960786baecfSMauro Carvalho Chehab 961786baecfSMauro Carvalho Chehab mutex_unlock(&dec->iso_mutex); 962786baecfSMauro Carvalho Chehab 963786baecfSMauro Carvalho Chehab return 0; 964786baecfSMauro Carvalho Chehab } 965786baecfSMauro Carvalho Chehab 966786baecfSMauro Carvalho Chehab static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed) 967786baecfSMauro Carvalho Chehab { 968786baecfSMauro Carvalho Chehab struct dvb_demux *dvbdmx = dvbdmxfeed->demux; 969786baecfSMauro Carvalho Chehab struct ttusb_dec *dec = dvbdmx->priv; 970786baecfSMauro Carvalho Chehab u8 b0[] = { 0x05 }; 971786baecfSMauro Carvalho Chehab int result = 0; 972786baecfSMauro Carvalho Chehab 973786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 974786baecfSMauro Carvalho Chehab 975786baecfSMauro Carvalho Chehab dprintk(" ts_type:"); 976786baecfSMauro Carvalho Chehab 977786baecfSMauro Carvalho Chehab if (dvbdmxfeed->ts_type & TS_DECODER) 978786baecfSMauro Carvalho Chehab dprintk(" TS_DECODER"); 979786baecfSMauro Carvalho Chehab 980786baecfSMauro Carvalho Chehab if (dvbdmxfeed->ts_type & TS_PACKET) 981786baecfSMauro Carvalho Chehab dprintk(" TS_PACKET"); 982786baecfSMauro Carvalho Chehab 983786baecfSMauro Carvalho Chehab if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY) 984786baecfSMauro Carvalho Chehab dprintk(" TS_PAYLOAD_ONLY"); 985786baecfSMauro Carvalho Chehab 986786baecfSMauro Carvalho Chehab dprintk("\n"); 987786baecfSMauro Carvalho Chehab 988786baecfSMauro Carvalho Chehab switch (dvbdmxfeed->pes_type) { 989786baecfSMauro Carvalho Chehab 990fde04ab9SMauro Carvalho Chehab case DMX_PES_VIDEO: 991fde04ab9SMauro Carvalho Chehab dprintk(" pes_type: DMX_PES_VIDEO\n"); 992786baecfSMauro Carvalho Chehab dec->pid[DMX_PES_PCR] = dvbdmxfeed->pid; 993786baecfSMauro Carvalho Chehab dec->pid[DMX_PES_VIDEO] = dvbdmxfeed->pid; 994786baecfSMauro Carvalho Chehab dec->video_filter = dvbdmxfeed->filter; 995786baecfSMauro Carvalho Chehab ttusb_dec_set_pids(dec); 996786baecfSMauro Carvalho Chehab break; 997786baecfSMauro Carvalho Chehab 998fde04ab9SMauro Carvalho Chehab case DMX_PES_AUDIO: 999fde04ab9SMauro Carvalho Chehab dprintk(" pes_type: DMX_PES_AUDIO\n"); 1000786baecfSMauro Carvalho Chehab dec->pid[DMX_PES_AUDIO] = dvbdmxfeed->pid; 1001786baecfSMauro Carvalho Chehab dec->audio_filter = dvbdmxfeed->filter; 1002786baecfSMauro Carvalho Chehab ttusb_dec_set_pids(dec); 1003786baecfSMauro Carvalho Chehab break; 1004786baecfSMauro Carvalho Chehab 1005fde04ab9SMauro Carvalho Chehab case DMX_PES_TELETEXT: 1006786baecfSMauro Carvalho Chehab dec->pid[DMX_PES_TELETEXT] = dvbdmxfeed->pid; 1007fde04ab9SMauro Carvalho Chehab dprintk(" pes_type: DMX_PES_TELETEXT(not supported)\n"); 1008786baecfSMauro Carvalho Chehab return -ENOSYS; 1009786baecfSMauro Carvalho Chehab 1010fde04ab9SMauro Carvalho Chehab case DMX_PES_PCR: 1011fde04ab9SMauro Carvalho Chehab dprintk(" pes_type: DMX_PES_PCR\n"); 1012786baecfSMauro Carvalho Chehab dec->pid[DMX_PES_PCR] = dvbdmxfeed->pid; 1013786baecfSMauro Carvalho Chehab ttusb_dec_set_pids(dec); 1014786baecfSMauro Carvalho Chehab break; 1015786baecfSMauro Carvalho Chehab 1016fde04ab9SMauro Carvalho Chehab case DMX_PES_OTHER: 1017fde04ab9SMauro Carvalho Chehab dprintk(" pes_type: DMX_PES_OTHER(not supported)\n"); 1018786baecfSMauro Carvalho Chehab return -ENOSYS; 1019786baecfSMauro Carvalho Chehab 1020786baecfSMauro Carvalho Chehab default: 1021786baecfSMauro Carvalho Chehab dprintk(" pes_type: unknown (%d)\n", dvbdmxfeed->pes_type); 1022786baecfSMauro Carvalho Chehab return -EINVAL; 1023786baecfSMauro Carvalho Chehab 1024786baecfSMauro Carvalho Chehab } 1025786baecfSMauro Carvalho Chehab 1026786baecfSMauro Carvalho Chehab result = ttusb_dec_send_command(dec, 0x80, sizeof(b0), b0, NULL, NULL); 1027786baecfSMauro Carvalho Chehab if (result) 1028786baecfSMauro Carvalho Chehab return result; 1029786baecfSMauro Carvalho Chehab 1030786baecfSMauro Carvalho Chehab dec->pva_stream_count++; 1031786baecfSMauro Carvalho Chehab return ttusb_dec_start_iso_xfer(dec); 1032786baecfSMauro Carvalho Chehab } 1033786baecfSMauro Carvalho Chehab 1034786baecfSMauro Carvalho Chehab static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed) 1035786baecfSMauro Carvalho Chehab { 1036786baecfSMauro Carvalho Chehab struct ttusb_dec *dec = dvbdmxfeed->demux->priv; 1037786baecfSMauro Carvalho Chehab u8 b0[] = { 0x00, 0x00, 0x00, 0x01, 1038786baecfSMauro Carvalho Chehab 0x00, 0x00, 0x00, 0x00, 1039786baecfSMauro Carvalho Chehab 0x00, 0x00, 0x00, 0x00, 1040786baecfSMauro Carvalho Chehab 0x00, 0x00, 0x00, 0x00, 1041786baecfSMauro Carvalho Chehab 0x00, 0xff, 0x00, 0x00, 1042786baecfSMauro Carvalho Chehab 0x00, 0x00, 0x00, 0x00, 1043786baecfSMauro Carvalho Chehab 0x00, 0x00, 0x00, 0x00, 1044786baecfSMauro Carvalho Chehab 0x00 }; 1045786baecfSMauro Carvalho Chehab __be16 pid; 1046786baecfSMauro Carvalho Chehab u8 c[COMMAND_PACKET_SIZE]; 1047786baecfSMauro Carvalho Chehab int c_length; 1048786baecfSMauro Carvalho Chehab int result; 1049786baecfSMauro Carvalho Chehab struct filter_info *finfo; 1050786baecfSMauro Carvalho Chehab unsigned long flags; 1051786baecfSMauro Carvalho Chehab u8 x = 1; 1052786baecfSMauro Carvalho Chehab 1053786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 1054786baecfSMauro Carvalho Chehab 1055786baecfSMauro Carvalho Chehab pid = htons(dvbdmxfeed->pid); 1056786baecfSMauro Carvalho Chehab memcpy(&b0[0], &pid, 2); 1057786baecfSMauro Carvalho Chehab memcpy(&b0[4], &x, 1); 1058786baecfSMauro Carvalho Chehab memcpy(&b0[5], &dvbdmxfeed->filter->filter.filter_value[0], 1); 1059786baecfSMauro Carvalho Chehab 1060786baecfSMauro Carvalho Chehab result = ttusb_dec_send_command(dec, 0x60, sizeof(b0), b0, 1061786baecfSMauro Carvalho Chehab &c_length, c); 1062786baecfSMauro Carvalho Chehab 1063786baecfSMauro Carvalho Chehab if (!result) { 1064786baecfSMauro Carvalho Chehab if (c_length == 2) { 1065786baecfSMauro Carvalho Chehab if (!(finfo = kmalloc(sizeof(struct filter_info), 1066786baecfSMauro Carvalho Chehab GFP_ATOMIC))) 1067786baecfSMauro Carvalho Chehab return -ENOMEM; 1068786baecfSMauro Carvalho Chehab 1069786baecfSMauro Carvalho Chehab finfo->stream_id = c[1]; 1070786baecfSMauro Carvalho Chehab finfo->filter = dvbdmxfeed->filter; 1071786baecfSMauro Carvalho Chehab 1072786baecfSMauro Carvalho Chehab spin_lock_irqsave(&dec->filter_info_list_lock, flags); 1073786baecfSMauro Carvalho Chehab list_add_tail(&finfo->filter_info_list, 1074786baecfSMauro Carvalho Chehab &dec->filter_info_list); 1075786baecfSMauro Carvalho Chehab spin_unlock_irqrestore(&dec->filter_info_list_lock, 1076786baecfSMauro Carvalho Chehab flags); 1077786baecfSMauro Carvalho Chehab 1078786baecfSMauro Carvalho Chehab dvbdmxfeed->priv = finfo; 1079786baecfSMauro Carvalho Chehab 1080786baecfSMauro Carvalho Chehab dec->filter_stream_count++; 1081786baecfSMauro Carvalho Chehab return ttusb_dec_start_iso_xfer(dec); 1082786baecfSMauro Carvalho Chehab } 1083786baecfSMauro Carvalho Chehab 1084786baecfSMauro Carvalho Chehab return -EAGAIN; 1085786baecfSMauro Carvalho Chehab } else 1086786baecfSMauro Carvalho Chehab return result; 1087786baecfSMauro Carvalho Chehab } 1088786baecfSMauro Carvalho Chehab 1089786baecfSMauro Carvalho Chehab static int ttusb_dec_start_feed(struct dvb_demux_feed *dvbdmxfeed) 1090786baecfSMauro Carvalho Chehab { 1091786baecfSMauro Carvalho Chehab struct dvb_demux *dvbdmx = dvbdmxfeed->demux; 1092786baecfSMauro Carvalho Chehab 1093786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 1094786baecfSMauro Carvalho Chehab 1095786baecfSMauro Carvalho Chehab if (!dvbdmx->dmx.frontend) 1096786baecfSMauro Carvalho Chehab return -EINVAL; 1097786baecfSMauro Carvalho Chehab 1098786baecfSMauro Carvalho Chehab dprintk(" pid: 0x%04X\n", dvbdmxfeed->pid); 1099786baecfSMauro Carvalho Chehab 1100786baecfSMauro Carvalho Chehab switch (dvbdmxfeed->type) { 1101786baecfSMauro Carvalho Chehab 1102786baecfSMauro Carvalho Chehab case DMX_TYPE_TS: 1103786baecfSMauro Carvalho Chehab return ttusb_dec_start_ts_feed(dvbdmxfeed); 1104786baecfSMauro Carvalho Chehab break; 1105786baecfSMauro Carvalho Chehab 1106786baecfSMauro Carvalho Chehab case DMX_TYPE_SEC: 1107786baecfSMauro Carvalho Chehab return ttusb_dec_start_sec_feed(dvbdmxfeed); 1108786baecfSMauro Carvalho Chehab break; 1109786baecfSMauro Carvalho Chehab 1110786baecfSMauro Carvalho Chehab default: 1111786baecfSMauro Carvalho Chehab dprintk(" type: unknown (%d)\n", dvbdmxfeed->type); 1112786baecfSMauro Carvalho Chehab return -EINVAL; 1113786baecfSMauro Carvalho Chehab 1114786baecfSMauro Carvalho Chehab } 1115786baecfSMauro Carvalho Chehab } 1116786baecfSMauro Carvalho Chehab 1117786baecfSMauro Carvalho Chehab static int ttusb_dec_stop_ts_feed(struct dvb_demux_feed *dvbdmxfeed) 1118786baecfSMauro Carvalho Chehab { 1119786baecfSMauro Carvalho Chehab struct ttusb_dec *dec = dvbdmxfeed->demux->priv; 1120786baecfSMauro Carvalho Chehab u8 b0[] = { 0x00 }; 1121786baecfSMauro Carvalho Chehab 1122786baecfSMauro Carvalho Chehab ttusb_dec_send_command(dec, 0x81, sizeof(b0), b0, NULL, NULL); 1123786baecfSMauro Carvalho Chehab 1124786baecfSMauro Carvalho Chehab dec->pva_stream_count--; 1125786baecfSMauro Carvalho Chehab 1126786baecfSMauro Carvalho Chehab ttusb_dec_stop_iso_xfer(dec); 1127786baecfSMauro Carvalho Chehab 1128786baecfSMauro Carvalho Chehab return 0; 1129786baecfSMauro Carvalho Chehab } 1130786baecfSMauro Carvalho Chehab 1131786baecfSMauro Carvalho Chehab static int ttusb_dec_stop_sec_feed(struct dvb_demux_feed *dvbdmxfeed) 1132786baecfSMauro Carvalho Chehab { 1133786baecfSMauro Carvalho Chehab struct ttusb_dec *dec = dvbdmxfeed->demux->priv; 1134786baecfSMauro Carvalho Chehab u8 b0[] = { 0x00, 0x00 }; 1135786baecfSMauro Carvalho Chehab struct filter_info *finfo = (struct filter_info *)dvbdmxfeed->priv; 1136786baecfSMauro Carvalho Chehab unsigned long flags; 1137786baecfSMauro Carvalho Chehab 1138786baecfSMauro Carvalho Chehab b0[1] = finfo->stream_id; 1139786baecfSMauro Carvalho Chehab spin_lock_irqsave(&dec->filter_info_list_lock, flags); 1140786baecfSMauro Carvalho Chehab list_del(&finfo->filter_info_list); 1141786baecfSMauro Carvalho Chehab spin_unlock_irqrestore(&dec->filter_info_list_lock, flags); 1142786baecfSMauro Carvalho Chehab kfree(finfo); 1143786baecfSMauro Carvalho Chehab ttusb_dec_send_command(dec, 0x62, sizeof(b0), b0, NULL, NULL); 1144786baecfSMauro Carvalho Chehab 1145786baecfSMauro Carvalho Chehab dec->filter_stream_count--; 1146786baecfSMauro Carvalho Chehab 1147786baecfSMauro Carvalho Chehab ttusb_dec_stop_iso_xfer(dec); 1148786baecfSMauro Carvalho Chehab 1149786baecfSMauro Carvalho Chehab return 0; 1150786baecfSMauro Carvalho Chehab } 1151786baecfSMauro Carvalho Chehab 1152786baecfSMauro Carvalho Chehab static int ttusb_dec_stop_feed(struct dvb_demux_feed *dvbdmxfeed) 1153786baecfSMauro Carvalho Chehab { 1154786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 1155786baecfSMauro Carvalho Chehab 1156786baecfSMauro Carvalho Chehab switch (dvbdmxfeed->type) { 1157786baecfSMauro Carvalho Chehab case DMX_TYPE_TS: 1158786baecfSMauro Carvalho Chehab return ttusb_dec_stop_ts_feed(dvbdmxfeed); 1159786baecfSMauro Carvalho Chehab break; 1160786baecfSMauro Carvalho Chehab 1161786baecfSMauro Carvalho Chehab case DMX_TYPE_SEC: 1162786baecfSMauro Carvalho Chehab return ttusb_dec_stop_sec_feed(dvbdmxfeed); 1163786baecfSMauro Carvalho Chehab break; 1164786baecfSMauro Carvalho Chehab } 1165786baecfSMauro Carvalho Chehab 1166786baecfSMauro Carvalho Chehab return 0; 1167786baecfSMauro Carvalho Chehab } 1168786baecfSMauro Carvalho Chehab 1169786baecfSMauro Carvalho Chehab static void ttusb_dec_free_iso_urbs(struct ttusb_dec *dec) 1170786baecfSMauro Carvalho Chehab { 1171786baecfSMauro Carvalho Chehab int i; 1172786baecfSMauro Carvalho Chehab 1173786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 1174786baecfSMauro Carvalho Chehab 1175786baecfSMauro Carvalho Chehab for (i = 0; i < ISO_BUF_COUNT; i++) 1176786baecfSMauro Carvalho Chehab usb_free_urb(dec->iso_urb[i]); 11778d669f93SChristoph Hellwig kfree(dec->iso_buffer); 1178786baecfSMauro Carvalho Chehab } 1179786baecfSMauro Carvalho Chehab 1180786baecfSMauro Carvalho Chehab static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec) 1181786baecfSMauro Carvalho Chehab { 1182786baecfSMauro Carvalho Chehab int i; 1183786baecfSMauro Carvalho Chehab 1184786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 1185786baecfSMauro Carvalho Chehab 11868d669f93SChristoph Hellwig dec->iso_buffer = kcalloc(FRAMES_PER_ISO_BUF * ISO_BUF_COUNT, 11878d669f93SChristoph Hellwig ISO_FRAME_SIZE, GFP_KERNEL); 11888d669f93SChristoph Hellwig if (!dec->iso_buffer) 1189786baecfSMauro Carvalho Chehab return -ENOMEM; 1190786baecfSMauro Carvalho Chehab 1191786baecfSMauro Carvalho Chehab for (i = 0; i < ISO_BUF_COUNT; i++) { 1192786baecfSMauro Carvalho Chehab struct urb *urb; 1193786baecfSMauro Carvalho Chehab 1194786baecfSMauro Carvalho Chehab if (!(urb = usb_alloc_urb(FRAMES_PER_ISO_BUF, GFP_ATOMIC))) { 1195786baecfSMauro Carvalho Chehab ttusb_dec_free_iso_urbs(dec); 1196786baecfSMauro Carvalho Chehab return -ENOMEM; 1197786baecfSMauro Carvalho Chehab } 1198786baecfSMauro Carvalho Chehab 1199786baecfSMauro Carvalho Chehab dec->iso_urb[i] = urb; 1200786baecfSMauro Carvalho Chehab } 1201786baecfSMauro Carvalho Chehab 1202786baecfSMauro Carvalho Chehab ttusb_dec_setup_urbs(dec); 1203786baecfSMauro Carvalho Chehab 1204786baecfSMauro Carvalho Chehab return 0; 1205786baecfSMauro Carvalho Chehab } 1206786baecfSMauro Carvalho Chehab 1207786baecfSMauro Carvalho Chehab static void ttusb_dec_init_tasklet(struct ttusb_dec *dec) 1208786baecfSMauro Carvalho Chehab { 1209786baecfSMauro Carvalho Chehab spin_lock_init(&dec->urb_frame_list_lock); 1210786baecfSMauro Carvalho Chehab INIT_LIST_HEAD(&dec->urb_frame_list); 1211786baecfSMauro Carvalho Chehab tasklet_init(&dec->urb_tasklet, ttusb_dec_process_urb_frame_list, 1212786baecfSMauro Carvalho Chehab (unsigned long)dec); 1213786baecfSMauro Carvalho Chehab } 1214786baecfSMauro Carvalho Chehab 1215786baecfSMauro Carvalho Chehab static int ttusb_init_rc( struct ttusb_dec *dec) 1216786baecfSMauro Carvalho Chehab { 1217786baecfSMauro Carvalho Chehab struct input_dev *input_dev; 1218786baecfSMauro Carvalho Chehab u8 b[] = { 0x00, 0x01 }; 1219786baecfSMauro Carvalho Chehab int i; 1220786baecfSMauro Carvalho Chehab int err; 1221786baecfSMauro Carvalho Chehab 1222786baecfSMauro Carvalho Chehab usb_make_path(dec->udev, dec->rc_phys, sizeof(dec->rc_phys)); 1223786baecfSMauro Carvalho Chehab strlcat(dec->rc_phys, "/input0", sizeof(dec->rc_phys)); 1224786baecfSMauro Carvalho Chehab 1225786baecfSMauro Carvalho Chehab input_dev = input_allocate_device(); 1226786baecfSMauro Carvalho Chehab if (!input_dev) 1227786baecfSMauro Carvalho Chehab return -ENOMEM; 1228786baecfSMauro Carvalho Chehab 1229786baecfSMauro Carvalho Chehab input_dev->name = "ttusb_dec remote control"; 1230786baecfSMauro Carvalho Chehab input_dev->phys = dec->rc_phys; 1231786baecfSMauro Carvalho Chehab input_dev->evbit[0] = BIT_MASK(EV_KEY); 1232786baecfSMauro Carvalho Chehab input_dev->keycodesize = sizeof(u16); 1233786baecfSMauro Carvalho Chehab input_dev->keycodemax = 0x1a; 1234786baecfSMauro Carvalho Chehab input_dev->keycode = rc_keys; 1235786baecfSMauro Carvalho Chehab 1236786baecfSMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(rc_keys); i++) 1237786baecfSMauro Carvalho Chehab set_bit(rc_keys[i], input_dev->keybit); 1238786baecfSMauro Carvalho Chehab 1239786baecfSMauro Carvalho Chehab err = input_register_device(input_dev); 1240786baecfSMauro Carvalho Chehab if (err) { 1241786baecfSMauro Carvalho Chehab input_free_device(input_dev); 1242786baecfSMauro Carvalho Chehab return err; 1243786baecfSMauro Carvalho Chehab } 1244786baecfSMauro Carvalho Chehab 1245786baecfSMauro Carvalho Chehab dec->rc_input_dev = input_dev; 1246786baecfSMauro Carvalho Chehab if (usb_submit_urb(dec->irq_urb, GFP_KERNEL)) 1247786baecfSMauro Carvalho Chehab printk("%s: usb_submit_urb failed\n",__func__); 1248786baecfSMauro Carvalho Chehab /* enable irq pipe */ 1249786baecfSMauro Carvalho Chehab ttusb_dec_send_command(dec,0xb0,sizeof(b),b,NULL,NULL); 1250786baecfSMauro Carvalho Chehab 1251786baecfSMauro Carvalho Chehab return 0; 1252786baecfSMauro Carvalho Chehab } 1253786baecfSMauro Carvalho Chehab 1254786baecfSMauro Carvalho Chehab static void ttusb_dec_init_v_pes(struct ttusb_dec *dec) 1255786baecfSMauro Carvalho Chehab { 1256786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 1257786baecfSMauro Carvalho Chehab 1258786baecfSMauro Carvalho Chehab dec->v_pes[0] = 0x00; 1259786baecfSMauro Carvalho Chehab dec->v_pes[1] = 0x00; 1260786baecfSMauro Carvalho Chehab dec->v_pes[2] = 0x01; 1261786baecfSMauro Carvalho Chehab dec->v_pes[3] = 0xe0; 1262786baecfSMauro Carvalho Chehab } 1263786baecfSMauro Carvalho Chehab 1264786baecfSMauro Carvalho Chehab static int ttusb_dec_init_usb(struct ttusb_dec *dec) 1265786baecfSMauro Carvalho Chehab { 1266cf732b5fSAlexey Khoroshilov int result; 1267cf732b5fSAlexey Khoroshilov 1268786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 1269786baecfSMauro Carvalho Chehab 1270786baecfSMauro Carvalho Chehab mutex_init(&dec->usb_mutex); 1271786baecfSMauro Carvalho Chehab mutex_init(&dec->iso_mutex); 1272786baecfSMauro Carvalho Chehab 1273786baecfSMauro Carvalho Chehab dec->command_pipe = usb_sndbulkpipe(dec->udev, COMMAND_PIPE); 1274786baecfSMauro Carvalho Chehab dec->result_pipe = usb_rcvbulkpipe(dec->udev, RESULT_PIPE); 1275786baecfSMauro Carvalho Chehab dec->in_pipe = usb_rcvisocpipe(dec->udev, IN_PIPE); 1276786baecfSMauro Carvalho Chehab dec->out_pipe = usb_sndisocpipe(dec->udev, OUT_PIPE); 1277786baecfSMauro Carvalho Chehab dec->irq_pipe = usb_rcvintpipe(dec->udev, IRQ_PIPE); 1278786baecfSMauro Carvalho Chehab 1279786baecfSMauro Carvalho Chehab if(enable_rc) { 1280786baecfSMauro Carvalho Chehab dec->irq_urb = usb_alloc_urb(0, GFP_KERNEL); 1281786baecfSMauro Carvalho Chehab if(!dec->irq_urb) { 1282786baecfSMauro Carvalho Chehab return -ENOMEM; 1283786baecfSMauro Carvalho Chehab } 1284786baecfSMauro Carvalho Chehab dec->irq_buffer = usb_alloc_coherent(dec->udev,IRQ_PACKET_SIZE, 1285cf732b5fSAlexey Khoroshilov GFP_KERNEL, &dec->irq_dma_handle); 1286786baecfSMauro Carvalho Chehab if(!dec->irq_buffer) { 1287786baecfSMauro Carvalho Chehab usb_free_urb(dec->irq_urb); 1288786baecfSMauro Carvalho Chehab return -ENOMEM; 1289786baecfSMauro Carvalho Chehab } 1290786baecfSMauro Carvalho Chehab usb_fill_int_urb(dec->irq_urb, dec->udev,dec->irq_pipe, 1291786baecfSMauro Carvalho Chehab dec->irq_buffer, IRQ_PACKET_SIZE, 1292786baecfSMauro Carvalho Chehab ttusb_dec_handle_irq, dec, 1); 1293786baecfSMauro Carvalho Chehab dec->irq_urb->transfer_dma = dec->irq_dma_handle; 1294786baecfSMauro Carvalho Chehab dec->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 1295786baecfSMauro Carvalho Chehab } 1296786baecfSMauro Carvalho Chehab 1297cf732b5fSAlexey Khoroshilov result = ttusb_dec_alloc_iso_urbs(dec); 1298cf732b5fSAlexey Khoroshilov if (result) { 1299cf732b5fSAlexey Khoroshilov usb_free_urb(dec->irq_urb); 1300cf732b5fSAlexey Khoroshilov usb_free_coherent(dec->udev, IRQ_PACKET_SIZE, 1301cf732b5fSAlexey Khoroshilov dec->irq_buffer, dec->irq_dma_handle); 1302cf732b5fSAlexey Khoroshilov } 1303cf732b5fSAlexey Khoroshilov return result; 1304786baecfSMauro Carvalho Chehab } 1305786baecfSMauro Carvalho Chehab 1306786baecfSMauro Carvalho Chehab static int ttusb_dec_boot_dsp(struct ttusb_dec *dec) 1307786baecfSMauro Carvalho Chehab { 1308786baecfSMauro Carvalho Chehab int i, j, actual_len, result, size, trans_count; 1309786baecfSMauro Carvalho Chehab u8 b0[] = { 0x00, 0x00, 0x00, 0x00, 1310786baecfSMauro Carvalho Chehab 0x00, 0x00, 0x00, 0x00, 1311786baecfSMauro Carvalho Chehab 0x61, 0x00 }; 1312786baecfSMauro Carvalho Chehab u8 b1[] = { 0x61 }; 1313786baecfSMauro Carvalho Chehab u8 *b; 1314786baecfSMauro Carvalho Chehab char idstring[21]; 1315786baecfSMauro Carvalho Chehab const u8 *firmware = NULL; 1316786baecfSMauro Carvalho Chehab size_t firmware_size = 0; 1317786baecfSMauro Carvalho Chehab u16 firmware_csum = 0; 1318786baecfSMauro Carvalho Chehab __be16 firmware_csum_ns; 1319786baecfSMauro Carvalho Chehab __be32 firmware_size_nl; 1320786baecfSMauro Carvalho Chehab u32 crc32_csum, crc32_check; 1321786baecfSMauro Carvalho Chehab __be32 tmp; 1322786baecfSMauro Carvalho Chehab const struct firmware *fw_entry = NULL; 1323786baecfSMauro Carvalho Chehab 1324786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 1325786baecfSMauro Carvalho Chehab 1326cf732b5fSAlexey Khoroshilov result = request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev); 1327cf732b5fSAlexey Khoroshilov if (result) { 1328786baecfSMauro Carvalho Chehab printk(KERN_ERR "%s: Firmware (%s) unavailable.\n", 1329786baecfSMauro Carvalho Chehab __func__, dec->firmware_name); 1330cf732b5fSAlexey Khoroshilov return result; 1331786baecfSMauro Carvalho Chehab } 1332786baecfSMauro Carvalho Chehab 1333786baecfSMauro Carvalho Chehab firmware = fw_entry->data; 1334786baecfSMauro Carvalho Chehab firmware_size = fw_entry->size; 1335786baecfSMauro Carvalho Chehab 1336786baecfSMauro Carvalho Chehab if (firmware_size < 60) { 1337786baecfSMauro Carvalho Chehab printk("%s: firmware size too small for DSP code (%zu < 60).\n", 1338786baecfSMauro Carvalho Chehab __func__, firmware_size); 1339786baecfSMauro Carvalho Chehab release_firmware(fw_entry); 1340cf732b5fSAlexey Khoroshilov return -ENOENT; 1341786baecfSMauro Carvalho Chehab } 1342786baecfSMauro Carvalho Chehab 1343786baecfSMauro Carvalho Chehab /* a 32 bit checksum over the first 56 bytes of the DSP Code is stored 1344786baecfSMauro Carvalho Chehab at offset 56 of file, so use it to check if the firmware file is 1345786baecfSMauro Carvalho Chehab valid. */ 1346786baecfSMauro Carvalho Chehab crc32_csum = crc32(~0L, firmware, 56) ^ ~0L; 1347786baecfSMauro Carvalho Chehab memcpy(&tmp, &firmware[56], 4); 1348786baecfSMauro Carvalho Chehab crc32_check = ntohl(tmp); 1349786baecfSMauro Carvalho Chehab if (crc32_csum != crc32_check) { 1350bf769a4eSMauro Carvalho Chehab printk("%s: crc32 check of DSP code failed (calculated 0x%08x != 0x%08x in file), file invalid.\n", 1351786baecfSMauro Carvalho Chehab __func__, crc32_csum, crc32_check); 1352786baecfSMauro Carvalho Chehab release_firmware(fw_entry); 1353cf732b5fSAlexey Khoroshilov return -ENOENT; 1354786baecfSMauro Carvalho Chehab } 1355786baecfSMauro Carvalho Chehab memcpy(idstring, &firmware[36], 20); 1356786baecfSMauro Carvalho Chehab idstring[20] = '\0'; 1357786baecfSMauro Carvalho Chehab printk(KERN_INFO "ttusb_dec: found DSP code \"%s\".\n", idstring); 1358786baecfSMauro Carvalho Chehab 1359786baecfSMauro Carvalho Chehab firmware_size_nl = htonl(firmware_size); 1360786baecfSMauro Carvalho Chehab memcpy(b0, &firmware_size_nl, 4); 1361786baecfSMauro Carvalho Chehab firmware_csum = crc16(~0, firmware, firmware_size) ^ ~0; 1362786baecfSMauro Carvalho Chehab firmware_csum_ns = htons(firmware_csum); 1363786baecfSMauro Carvalho Chehab memcpy(&b0[6], &firmware_csum_ns, 2); 1364786baecfSMauro Carvalho Chehab 1365786baecfSMauro Carvalho Chehab result = ttusb_dec_send_command(dec, 0x41, sizeof(b0), b0, NULL, NULL); 1366786baecfSMauro Carvalho Chehab 1367786baecfSMauro Carvalho Chehab if (result) { 1368786baecfSMauro Carvalho Chehab release_firmware(fw_entry); 1369786baecfSMauro Carvalho Chehab return result; 1370786baecfSMauro Carvalho Chehab } 1371786baecfSMauro Carvalho Chehab 1372786baecfSMauro Carvalho Chehab trans_count = 0; 1373786baecfSMauro Carvalho Chehab j = 0; 1374786baecfSMauro Carvalho Chehab 1375786baecfSMauro Carvalho Chehab b = kmalloc(ARM_PACKET_SIZE, GFP_KERNEL); 1376786baecfSMauro Carvalho Chehab if (b == NULL) { 1377786baecfSMauro Carvalho Chehab release_firmware(fw_entry); 1378786baecfSMauro Carvalho Chehab return -ENOMEM; 1379786baecfSMauro Carvalho Chehab } 1380786baecfSMauro Carvalho Chehab 1381786baecfSMauro Carvalho Chehab for (i = 0; i < firmware_size; i += COMMAND_PACKET_SIZE) { 1382786baecfSMauro Carvalho Chehab size = firmware_size - i; 1383786baecfSMauro Carvalho Chehab if (size > COMMAND_PACKET_SIZE) 1384786baecfSMauro Carvalho Chehab size = COMMAND_PACKET_SIZE; 1385786baecfSMauro Carvalho Chehab 1386786baecfSMauro Carvalho Chehab b[j + 0] = 0xaa; 1387786baecfSMauro Carvalho Chehab b[j + 1] = trans_count++; 1388786baecfSMauro Carvalho Chehab b[j + 2] = 0xf0; 1389786baecfSMauro Carvalho Chehab b[j + 3] = size; 1390786baecfSMauro Carvalho Chehab memcpy(&b[j + 4], &firmware[i], size); 1391786baecfSMauro Carvalho Chehab 1392786baecfSMauro Carvalho Chehab j += COMMAND_PACKET_SIZE + 4; 1393786baecfSMauro Carvalho Chehab 1394786baecfSMauro Carvalho Chehab if (j >= ARM_PACKET_SIZE) { 1395786baecfSMauro Carvalho Chehab result = usb_bulk_msg(dec->udev, dec->command_pipe, b, 1396786baecfSMauro Carvalho Chehab ARM_PACKET_SIZE, &actual_len, 1397786baecfSMauro Carvalho Chehab 100); 1398786baecfSMauro Carvalho Chehab j = 0; 1399786baecfSMauro Carvalho Chehab } else if (size < COMMAND_PACKET_SIZE) { 1400786baecfSMauro Carvalho Chehab result = usb_bulk_msg(dec->udev, dec->command_pipe, b, 1401786baecfSMauro Carvalho Chehab j - COMMAND_PACKET_SIZE + size, 1402786baecfSMauro Carvalho Chehab &actual_len, 100); 1403786baecfSMauro Carvalho Chehab } 1404786baecfSMauro Carvalho Chehab } 1405786baecfSMauro Carvalho Chehab 1406786baecfSMauro Carvalho Chehab result = ttusb_dec_send_command(dec, 0x43, sizeof(b1), b1, NULL, NULL); 1407786baecfSMauro Carvalho Chehab 1408786baecfSMauro Carvalho Chehab release_firmware(fw_entry); 1409786baecfSMauro Carvalho Chehab kfree(b); 1410786baecfSMauro Carvalho Chehab 1411786baecfSMauro Carvalho Chehab return result; 1412786baecfSMauro Carvalho Chehab } 1413786baecfSMauro Carvalho Chehab 1414786baecfSMauro Carvalho Chehab static int ttusb_dec_init_stb(struct ttusb_dec *dec) 1415786baecfSMauro Carvalho Chehab { 1416786baecfSMauro Carvalho Chehab int result; 1417786baecfSMauro Carvalho Chehab unsigned int mode = 0, model = 0, version = 0; 1418786baecfSMauro Carvalho Chehab 1419786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 1420786baecfSMauro Carvalho Chehab 1421786baecfSMauro Carvalho Chehab result = ttusb_dec_get_stb_state(dec, &mode, &model, &version); 1422cf732b5fSAlexey Khoroshilov if (result) 1423cf732b5fSAlexey Khoroshilov return result; 1424786baecfSMauro Carvalho Chehab 1425786baecfSMauro Carvalho Chehab if (!mode) { 1426786baecfSMauro Carvalho Chehab if (version == 0xABCDEFAB) 1427bf769a4eSMauro Carvalho Chehab printk(KERN_INFO "ttusb_dec: no version info in Firmware\n"); 1428786baecfSMauro Carvalho Chehab else 1429bf769a4eSMauro Carvalho Chehab printk(KERN_INFO "ttusb_dec: Firmware %x.%02x%c%c\n", 1430786baecfSMauro Carvalho Chehab version >> 24, (version >> 16) & 0xff, 1431786baecfSMauro Carvalho Chehab (version >> 8) & 0xff, version & 0xff); 1432786baecfSMauro Carvalho Chehab 1433786baecfSMauro Carvalho Chehab result = ttusb_dec_boot_dsp(dec); 1434786baecfSMauro Carvalho Chehab if (result) 1435786baecfSMauro Carvalho Chehab return result; 1436786baecfSMauro Carvalho Chehab } else { 1437786baecfSMauro Carvalho Chehab /* We can't trust the USB IDs that some firmwares 1438786baecfSMauro Carvalho Chehab give the box */ 1439786baecfSMauro Carvalho Chehab switch (model) { 1440786baecfSMauro Carvalho Chehab case 0x00070001: 1441786baecfSMauro Carvalho Chehab case 0x00070008: 1442786baecfSMauro Carvalho Chehab case 0x0007000c: 1443786baecfSMauro Carvalho Chehab ttusb_dec_set_model(dec, TTUSB_DEC3000S); 1444786baecfSMauro Carvalho Chehab break; 1445786baecfSMauro Carvalho Chehab case 0x00070009: 1446786baecfSMauro Carvalho Chehab case 0x00070013: 1447786baecfSMauro Carvalho Chehab ttusb_dec_set_model(dec, TTUSB_DEC2000T); 1448786baecfSMauro Carvalho Chehab break; 1449786baecfSMauro Carvalho Chehab case 0x00070011: 1450786baecfSMauro Carvalho Chehab ttusb_dec_set_model(dec, TTUSB_DEC2540T); 1451786baecfSMauro Carvalho Chehab break; 1452786baecfSMauro Carvalho Chehab default: 1453bf769a4eSMauro Carvalho Chehab printk(KERN_ERR "%s: unknown model returned by firmware (%08x) - please report\n", 1454786baecfSMauro Carvalho Chehab __func__, model); 1455cf732b5fSAlexey Khoroshilov return -ENOENT; 1456786baecfSMauro Carvalho Chehab } 1457786baecfSMauro Carvalho Chehab if (version >= 0x01770000) 1458786baecfSMauro Carvalho Chehab dec->can_playback = 1; 1459cf732b5fSAlexey Khoroshilov } 1460786baecfSMauro Carvalho Chehab return 0; 1461786baecfSMauro Carvalho Chehab } 1462786baecfSMauro Carvalho Chehab 1463786baecfSMauro Carvalho Chehab static int ttusb_dec_init_dvb(struct ttusb_dec *dec) 1464786baecfSMauro Carvalho Chehab { 1465786baecfSMauro Carvalho Chehab int result; 1466786baecfSMauro Carvalho Chehab 1467786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 1468786baecfSMauro Carvalho Chehab 1469786baecfSMauro Carvalho Chehab if ((result = dvb_register_adapter(&dec->adapter, 1470786baecfSMauro Carvalho Chehab dec->model_name, THIS_MODULE, 1471786baecfSMauro Carvalho Chehab &dec->udev->dev, 1472786baecfSMauro Carvalho Chehab adapter_nr)) < 0) { 1473786baecfSMauro Carvalho Chehab printk("%s: dvb_register_adapter failed: error %d\n", 1474786baecfSMauro Carvalho Chehab __func__, result); 1475786baecfSMauro Carvalho Chehab 1476786baecfSMauro Carvalho Chehab return result; 1477786baecfSMauro Carvalho Chehab } 1478786baecfSMauro Carvalho Chehab 1479786baecfSMauro Carvalho Chehab dec->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING; 1480786baecfSMauro Carvalho Chehab 1481786baecfSMauro Carvalho Chehab dec->demux.priv = (void *)dec; 1482786baecfSMauro Carvalho Chehab dec->demux.filternum = 31; 1483786baecfSMauro Carvalho Chehab dec->demux.feednum = 31; 1484786baecfSMauro Carvalho Chehab dec->demux.start_feed = ttusb_dec_start_feed; 1485786baecfSMauro Carvalho Chehab dec->demux.stop_feed = ttusb_dec_stop_feed; 1486786baecfSMauro Carvalho Chehab dec->demux.write_to_decoder = NULL; 1487786baecfSMauro Carvalho Chehab 1488786baecfSMauro Carvalho Chehab if ((result = dvb_dmx_init(&dec->demux)) < 0) { 1489786baecfSMauro Carvalho Chehab printk("%s: dvb_dmx_init failed: error %d\n", __func__, 1490786baecfSMauro Carvalho Chehab result); 1491786baecfSMauro Carvalho Chehab 1492786baecfSMauro Carvalho Chehab dvb_unregister_adapter(&dec->adapter); 1493786baecfSMauro Carvalho Chehab 1494786baecfSMauro Carvalho Chehab return result; 1495786baecfSMauro Carvalho Chehab } 1496786baecfSMauro Carvalho Chehab 1497786baecfSMauro Carvalho Chehab dec->dmxdev.filternum = 32; 1498786baecfSMauro Carvalho Chehab dec->dmxdev.demux = &dec->demux.dmx; 1499786baecfSMauro Carvalho Chehab dec->dmxdev.capabilities = 0; 1500786baecfSMauro Carvalho Chehab 1501786baecfSMauro Carvalho Chehab if ((result = dvb_dmxdev_init(&dec->dmxdev, &dec->adapter)) < 0) { 1502786baecfSMauro Carvalho Chehab printk("%s: dvb_dmxdev_init failed: error %d\n", 1503786baecfSMauro Carvalho Chehab __func__, result); 1504786baecfSMauro Carvalho Chehab 1505786baecfSMauro Carvalho Chehab dvb_dmx_release(&dec->demux); 1506786baecfSMauro Carvalho Chehab dvb_unregister_adapter(&dec->adapter); 1507786baecfSMauro Carvalho Chehab 1508786baecfSMauro Carvalho Chehab return result; 1509786baecfSMauro Carvalho Chehab } 1510786baecfSMauro Carvalho Chehab 1511786baecfSMauro Carvalho Chehab dec->frontend.source = DMX_FRONTEND_0; 1512786baecfSMauro Carvalho Chehab 1513786baecfSMauro Carvalho Chehab if ((result = dec->demux.dmx.add_frontend(&dec->demux.dmx, 1514786baecfSMauro Carvalho Chehab &dec->frontend)) < 0) { 1515786baecfSMauro Carvalho Chehab printk("%s: dvb_dmx_init failed: error %d\n", __func__, 1516786baecfSMauro Carvalho Chehab result); 1517786baecfSMauro Carvalho Chehab 1518786baecfSMauro Carvalho Chehab dvb_dmxdev_release(&dec->dmxdev); 1519786baecfSMauro Carvalho Chehab dvb_dmx_release(&dec->demux); 1520786baecfSMauro Carvalho Chehab dvb_unregister_adapter(&dec->adapter); 1521786baecfSMauro Carvalho Chehab 1522786baecfSMauro Carvalho Chehab return result; 1523786baecfSMauro Carvalho Chehab } 1524786baecfSMauro Carvalho Chehab 1525786baecfSMauro Carvalho Chehab if ((result = dec->demux.dmx.connect_frontend(&dec->demux.dmx, 1526786baecfSMauro Carvalho Chehab &dec->frontend)) < 0) { 1527786baecfSMauro Carvalho Chehab printk("%s: dvb_dmx_init failed: error %d\n", __func__, 1528786baecfSMauro Carvalho Chehab result); 1529786baecfSMauro Carvalho Chehab 1530786baecfSMauro Carvalho Chehab dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend); 1531786baecfSMauro Carvalho Chehab dvb_dmxdev_release(&dec->dmxdev); 1532786baecfSMauro Carvalho Chehab dvb_dmx_release(&dec->demux); 1533786baecfSMauro Carvalho Chehab dvb_unregister_adapter(&dec->adapter); 1534786baecfSMauro Carvalho Chehab 1535786baecfSMauro Carvalho Chehab return result; 1536786baecfSMauro Carvalho Chehab } 1537786baecfSMauro Carvalho Chehab 1538786baecfSMauro Carvalho Chehab dvb_net_init(&dec->adapter, &dec->dvb_net, &dec->demux.dmx); 1539786baecfSMauro Carvalho Chehab 1540786baecfSMauro Carvalho Chehab return 0; 1541786baecfSMauro Carvalho Chehab } 1542786baecfSMauro Carvalho Chehab 1543786baecfSMauro Carvalho Chehab static void ttusb_dec_exit_dvb(struct ttusb_dec *dec) 1544786baecfSMauro Carvalho Chehab { 1545786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 1546786baecfSMauro Carvalho Chehab 1547786baecfSMauro Carvalho Chehab dvb_net_release(&dec->dvb_net); 1548786baecfSMauro Carvalho Chehab dec->demux.dmx.close(&dec->demux.dmx); 1549786baecfSMauro Carvalho Chehab dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend); 1550786baecfSMauro Carvalho Chehab dvb_dmxdev_release(&dec->dmxdev); 1551786baecfSMauro Carvalho Chehab dvb_dmx_release(&dec->demux); 1552786baecfSMauro Carvalho Chehab if (dec->fe) { 1553786baecfSMauro Carvalho Chehab dvb_unregister_frontend(dec->fe); 1554786baecfSMauro Carvalho Chehab if (dec->fe->ops.release) 1555786baecfSMauro Carvalho Chehab dec->fe->ops.release(dec->fe); 1556786baecfSMauro Carvalho Chehab } 1557786baecfSMauro Carvalho Chehab dvb_unregister_adapter(&dec->adapter); 1558786baecfSMauro Carvalho Chehab } 1559786baecfSMauro Carvalho Chehab 1560786baecfSMauro Carvalho Chehab static void ttusb_dec_exit_rc(struct ttusb_dec *dec) 1561786baecfSMauro Carvalho Chehab { 1562786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 1563786baecfSMauro Carvalho Chehab 1564786baecfSMauro Carvalho Chehab if (dec->rc_input_dev) { 1565786baecfSMauro Carvalho Chehab input_unregister_device(dec->rc_input_dev); 1566786baecfSMauro Carvalho Chehab dec->rc_input_dev = NULL; 1567786baecfSMauro Carvalho Chehab } 1568786baecfSMauro Carvalho Chehab } 1569786baecfSMauro Carvalho Chehab 1570786baecfSMauro Carvalho Chehab 1571786baecfSMauro Carvalho Chehab static void ttusb_dec_exit_usb(struct ttusb_dec *dec) 1572786baecfSMauro Carvalho Chehab { 1573786baecfSMauro Carvalho Chehab int i; 1574786baecfSMauro Carvalho Chehab 1575786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 1576786baecfSMauro Carvalho Chehab 1577cf732b5fSAlexey Khoroshilov if (enable_rc) { 1578cf732b5fSAlexey Khoroshilov /* we have to check whether the irq URB is already submitted. 1579cf732b5fSAlexey Khoroshilov * As the irq is submitted after the interface is changed, 1580cf732b5fSAlexey Khoroshilov * this is the best method i figured out. 1581cf732b5fSAlexey Khoroshilov * Any others?*/ 1582cf732b5fSAlexey Khoroshilov if (dec->interface == TTUSB_DEC_INTERFACE_IN) 1583cf732b5fSAlexey Khoroshilov usb_kill_urb(dec->irq_urb); 1584cf732b5fSAlexey Khoroshilov 1585cf732b5fSAlexey Khoroshilov usb_free_urb(dec->irq_urb); 1586cf732b5fSAlexey Khoroshilov 1587cf732b5fSAlexey Khoroshilov usb_free_coherent(dec->udev, IRQ_PACKET_SIZE, 1588cf732b5fSAlexey Khoroshilov dec->irq_buffer, dec->irq_dma_handle); 1589cf732b5fSAlexey Khoroshilov } 1590cf732b5fSAlexey Khoroshilov 1591786baecfSMauro Carvalho Chehab dec->iso_stream_count = 0; 1592786baecfSMauro Carvalho Chehab 1593786baecfSMauro Carvalho Chehab for (i = 0; i < ISO_BUF_COUNT; i++) 1594786baecfSMauro Carvalho Chehab usb_kill_urb(dec->iso_urb[i]); 1595786baecfSMauro Carvalho Chehab 1596786baecfSMauro Carvalho Chehab ttusb_dec_free_iso_urbs(dec); 1597786baecfSMauro Carvalho Chehab } 1598786baecfSMauro Carvalho Chehab 1599786baecfSMauro Carvalho Chehab static void ttusb_dec_exit_tasklet(struct ttusb_dec *dec) 1600786baecfSMauro Carvalho Chehab { 1601786baecfSMauro Carvalho Chehab struct list_head *item; 1602786baecfSMauro Carvalho Chehab struct urb_frame *frame; 1603786baecfSMauro Carvalho Chehab 1604786baecfSMauro Carvalho Chehab tasklet_kill(&dec->urb_tasklet); 1605786baecfSMauro Carvalho Chehab 1606786baecfSMauro Carvalho Chehab while ((item = dec->urb_frame_list.next) != &dec->urb_frame_list) { 1607786baecfSMauro Carvalho Chehab frame = list_entry(item, struct urb_frame, urb_frame_list); 1608786baecfSMauro Carvalho Chehab list_del(&frame->urb_frame_list); 1609786baecfSMauro Carvalho Chehab kfree(frame); 1610786baecfSMauro Carvalho Chehab } 1611786baecfSMauro Carvalho Chehab } 1612786baecfSMauro Carvalho Chehab 1613786baecfSMauro Carvalho Chehab static void ttusb_dec_init_filters(struct ttusb_dec *dec) 1614786baecfSMauro Carvalho Chehab { 1615786baecfSMauro Carvalho Chehab INIT_LIST_HEAD(&dec->filter_info_list); 1616786baecfSMauro Carvalho Chehab spin_lock_init(&dec->filter_info_list_lock); 1617786baecfSMauro Carvalho Chehab } 1618786baecfSMauro Carvalho Chehab 1619786baecfSMauro Carvalho Chehab static void ttusb_dec_exit_filters(struct ttusb_dec *dec) 1620786baecfSMauro Carvalho Chehab { 1621786baecfSMauro Carvalho Chehab struct list_head *item; 1622786baecfSMauro Carvalho Chehab struct filter_info *finfo; 1623786baecfSMauro Carvalho Chehab 1624786baecfSMauro Carvalho Chehab while ((item = dec->filter_info_list.next) != &dec->filter_info_list) { 1625786baecfSMauro Carvalho Chehab finfo = list_entry(item, struct filter_info, filter_info_list); 1626786baecfSMauro Carvalho Chehab list_del(&finfo->filter_info_list); 1627786baecfSMauro Carvalho Chehab kfree(finfo); 1628786baecfSMauro Carvalho Chehab } 1629786baecfSMauro Carvalho Chehab } 1630786baecfSMauro Carvalho Chehab 1631786baecfSMauro Carvalho Chehab static int fe_send_command(struct dvb_frontend* fe, const u8 command, 1632786baecfSMauro Carvalho Chehab int param_length, const u8 params[], 1633786baecfSMauro Carvalho Chehab int *result_length, u8 cmd_result[]) 1634786baecfSMauro Carvalho Chehab { 1635786baecfSMauro Carvalho Chehab struct ttusb_dec* dec = fe->dvb->priv; 1636786baecfSMauro Carvalho Chehab return ttusb_dec_send_command(dec, command, param_length, params, result_length, cmd_result); 1637786baecfSMauro Carvalho Chehab } 1638786baecfSMauro Carvalho Chehab 16399bca6266SJulia Lawall static const struct ttusbdecfe_config fe_config = { 1640786baecfSMauro Carvalho Chehab .send_command = fe_send_command 1641786baecfSMauro Carvalho Chehab }; 1642786baecfSMauro Carvalho Chehab 1643786baecfSMauro Carvalho Chehab static int ttusb_dec_probe(struct usb_interface *intf, 1644786baecfSMauro Carvalho Chehab const struct usb_device_id *id) 1645786baecfSMauro Carvalho Chehab { 1646786baecfSMauro Carvalho Chehab struct usb_device *udev; 1647786baecfSMauro Carvalho Chehab struct ttusb_dec *dec; 1648cf732b5fSAlexey Khoroshilov int result; 1649786baecfSMauro Carvalho Chehab 1650786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 1651786baecfSMauro Carvalho Chehab 1652786baecfSMauro Carvalho Chehab udev = interface_to_usbdev(intf); 1653786baecfSMauro Carvalho Chehab 1654786baecfSMauro Carvalho Chehab if (!(dec = kzalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) { 1655786baecfSMauro Carvalho Chehab printk("%s: couldn't allocate memory.\n", __func__); 1656786baecfSMauro Carvalho Chehab return -ENOMEM; 1657786baecfSMauro Carvalho Chehab } 1658786baecfSMauro Carvalho Chehab 1659786baecfSMauro Carvalho Chehab usb_set_intfdata(intf, (void *)dec); 1660786baecfSMauro Carvalho Chehab 1661786baecfSMauro Carvalho Chehab switch (id->idProduct) { 1662786baecfSMauro Carvalho Chehab case 0x1006: 1663786baecfSMauro Carvalho Chehab ttusb_dec_set_model(dec, TTUSB_DEC3000S); 1664786baecfSMauro Carvalho Chehab break; 1665786baecfSMauro Carvalho Chehab 1666786baecfSMauro Carvalho Chehab case 0x1008: 1667786baecfSMauro Carvalho Chehab ttusb_dec_set_model(dec, TTUSB_DEC2000T); 1668786baecfSMauro Carvalho Chehab break; 1669786baecfSMauro Carvalho Chehab 1670786baecfSMauro Carvalho Chehab case 0x1009: 1671786baecfSMauro Carvalho Chehab ttusb_dec_set_model(dec, TTUSB_DEC2540T); 1672786baecfSMauro Carvalho Chehab break; 1673786baecfSMauro Carvalho Chehab } 1674786baecfSMauro Carvalho Chehab 1675786baecfSMauro Carvalho Chehab dec->udev = udev; 1676786baecfSMauro Carvalho Chehab 1677cf732b5fSAlexey Khoroshilov result = ttusb_dec_init_usb(dec); 1678cf732b5fSAlexey Khoroshilov if (result) 1679cf732b5fSAlexey Khoroshilov goto err_usb; 1680cf732b5fSAlexey Khoroshilov result = ttusb_dec_init_stb(dec); 1681cf732b5fSAlexey Khoroshilov if (result) 1682cf732b5fSAlexey Khoroshilov goto err_stb; 1683cf732b5fSAlexey Khoroshilov result = ttusb_dec_init_dvb(dec); 1684cf732b5fSAlexey Khoroshilov if (result) 1685cf732b5fSAlexey Khoroshilov goto err_stb; 1686786baecfSMauro Carvalho Chehab 1687786baecfSMauro Carvalho Chehab dec->adapter.priv = dec; 1688786baecfSMauro Carvalho Chehab switch (id->idProduct) { 1689786baecfSMauro Carvalho Chehab case 0x1006: 1690786baecfSMauro Carvalho Chehab dec->fe = ttusbdecfe_dvbs_attach(&fe_config); 1691786baecfSMauro Carvalho Chehab break; 1692786baecfSMauro Carvalho Chehab 1693786baecfSMauro Carvalho Chehab case 0x1008: 1694786baecfSMauro Carvalho Chehab case 0x1009: 1695786baecfSMauro Carvalho Chehab dec->fe = ttusbdecfe_dvbt_attach(&fe_config); 1696786baecfSMauro Carvalho Chehab break; 1697786baecfSMauro Carvalho Chehab } 1698786baecfSMauro Carvalho Chehab 1699786baecfSMauro Carvalho Chehab if (dec->fe == NULL) { 1700786baecfSMauro Carvalho Chehab printk("dvb-ttusb-dec: A frontend driver was not found for device [%04x:%04x]\n", 1701786baecfSMauro Carvalho Chehab le16_to_cpu(dec->udev->descriptor.idVendor), 1702786baecfSMauro Carvalho Chehab le16_to_cpu(dec->udev->descriptor.idProduct)); 1703786baecfSMauro Carvalho Chehab } else { 1704786baecfSMauro Carvalho Chehab if (dvb_register_frontend(&dec->adapter, dec->fe)) { 1705786baecfSMauro Carvalho Chehab printk("budget-ci: Frontend registration failed!\n"); 1706786baecfSMauro Carvalho Chehab if (dec->fe->ops.release) 1707786baecfSMauro Carvalho Chehab dec->fe->ops.release(dec->fe); 1708786baecfSMauro Carvalho Chehab dec->fe = NULL; 1709786baecfSMauro Carvalho Chehab } 1710786baecfSMauro Carvalho Chehab } 1711786baecfSMauro Carvalho Chehab 1712786baecfSMauro Carvalho Chehab ttusb_dec_init_v_pes(dec); 1713786baecfSMauro Carvalho Chehab ttusb_dec_init_filters(dec); 1714786baecfSMauro Carvalho Chehab ttusb_dec_init_tasklet(dec); 1715786baecfSMauro Carvalho Chehab 1716786baecfSMauro Carvalho Chehab dec->active = 1; 1717786baecfSMauro Carvalho Chehab 1718786baecfSMauro Carvalho Chehab ttusb_dec_set_interface(dec, TTUSB_DEC_INTERFACE_IN); 1719786baecfSMauro Carvalho Chehab 1720786baecfSMauro Carvalho Chehab if (enable_rc) 1721786baecfSMauro Carvalho Chehab ttusb_init_rc(dec); 1722786baecfSMauro Carvalho Chehab 1723786baecfSMauro Carvalho Chehab return 0; 1724cf732b5fSAlexey Khoroshilov err_stb: 1725cf732b5fSAlexey Khoroshilov ttusb_dec_exit_usb(dec); 1726cf732b5fSAlexey Khoroshilov err_usb: 1727cf732b5fSAlexey Khoroshilov kfree(dec); 1728cf732b5fSAlexey Khoroshilov return result; 1729786baecfSMauro Carvalho Chehab } 1730786baecfSMauro Carvalho Chehab 1731786baecfSMauro Carvalho Chehab static void ttusb_dec_disconnect(struct usb_interface *intf) 1732786baecfSMauro Carvalho Chehab { 1733786baecfSMauro Carvalho Chehab struct ttusb_dec *dec = usb_get_intfdata(intf); 1734786baecfSMauro Carvalho Chehab 1735786baecfSMauro Carvalho Chehab usb_set_intfdata(intf, NULL); 1736786baecfSMauro Carvalho Chehab 1737786baecfSMauro Carvalho Chehab dprintk("%s\n", __func__); 1738786baecfSMauro Carvalho Chehab 1739786baecfSMauro Carvalho Chehab if (dec->active) { 1740786baecfSMauro Carvalho Chehab ttusb_dec_exit_tasklet(dec); 1741786baecfSMauro Carvalho Chehab ttusb_dec_exit_filters(dec); 1742786baecfSMauro Carvalho Chehab if(enable_rc) 1743786baecfSMauro Carvalho Chehab ttusb_dec_exit_rc(dec); 1744786baecfSMauro Carvalho Chehab ttusb_dec_exit_usb(dec); 1745786baecfSMauro Carvalho Chehab ttusb_dec_exit_dvb(dec); 1746786baecfSMauro Carvalho Chehab } 1747786baecfSMauro Carvalho Chehab 1748786baecfSMauro Carvalho Chehab kfree(dec); 1749786baecfSMauro Carvalho Chehab } 1750786baecfSMauro Carvalho Chehab 1751786baecfSMauro Carvalho Chehab static void ttusb_dec_set_model(struct ttusb_dec *dec, 1752786baecfSMauro Carvalho Chehab enum ttusb_dec_model model) 1753786baecfSMauro Carvalho Chehab { 1754786baecfSMauro Carvalho Chehab dec->model = model; 1755786baecfSMauro Carvalho Chehab 1756786baecfSMauro Carvalho Chehab switch (model) { 1757786baecfSMauro Carvalho Chehab case TTUSB_DEC2000T: 1758786baecfSMauro Carvalho Chehab dec->model_name = "DEC2000-t"; 1759786baecfSMauro Carvalho Chehab dec->firmware_name = "dvb-ttusb-dec-2000t.fw"; 1760786baecfSMauro Carvalho Chehab break; 1761786baecfSMauro Carvalho Chehab 1762786baecfSMauro Carvalho Chehab case TTUSB_DEC2540T: 1763786baecfSMauro Carvalho Chehab dec->model_name = "DEC2540-t"; 1764786baecfSMauro Carvalho Chehab dec->firmware_name = "dvb-ttusb-dec-2540t.fw"; 1765786baecfSMauro Carvalho Chehab break; 1766786baecfSMauro Carvalho Chehab 1767786baecfSMauro Carvalho Chehab case TTUSB_DEC3000S: 1768786baecfSMauro Carvalho Chehab dec->model_name = "DEC3000-s"; 1769786baecfSMauro Carvalho Chehab dec->firmware_name = "dvb-ttusb-dec-3000s.fw"; 1770786baecfSMauro Carvalho Chehab break; 1771786baecfSMauro Carvalho Chehab } 1772786baecfSMauro Carvalho Chehab } 1773786baecfSMauro Carvalho Chehab 17747fb2e072SArvind Yadav static const struct usb_device_id ttusb_dec_table[] = { 1775786baecfSMauro Carvalho Chehab {USB_DEVICE(0x0b48, 0x1006)}, /* DEC3000-s */ 1776786baecfSMauro Carvalho Chehab /*{USB_DEVICE(0x0b48, 0x1007)}, Unconfirmed */ 1777786baecfSMauro Carvalho Chehab {USB_DEVICE(0x0b48, 0x1008)}, /* DEC2000-t */ 1778786baecfSMauro Carvalho Chehab {USB_DEVICE(0x0b48, 0x1009)}, /* DEC2540-t */ 1779786baecfSMauro Carvalho Chehab {} 1780786baecfSMauro Carvalho Chehab }; 1781786baecfSMauro Carvalho Chehab 1782786baecfSMauro Carvalho Chehab static struct usb_driver ttusb_dec_driver = { 1783786baecfSMauro Carvalho Chehab .name = "ttusb-dec", 1784786baecfSMauro Carvalho Chehab .probe = ttusb_dec_probe, 1785786baecfSMauro Carvalho Chehab .disconnect = ttusb_dec_disconnect, 1786786baecfSMauro Carvalho Chehab .id_table = ttusb_dec_table, 1787786baecfSMauro Carvalho Chehab }; 1788786baecfSMauro Carvalho Chehab 1789786baecfSMauro Carvalho Chehab module_usb_driver(ttusb_dec_driver); 1790786baecfSMauro Carvalho Chehab 1791786baecfSMauro Carvalho Chehab MODULE_AUTHOR("Alex Woods <linux-dvb@giblets.org>"); 1792786baecfSMauro Carvalho Chehab MODULE_DESCRIPTION(DRIVER_NAME); 1793786baecfSMauro Carvalho Chehab MODULE_LICENSE("GPL"); 1794786baecfSMauro Carvalho Chehab MODULE_DEVICE_TABLE(usb, ttusb_dec_table); 1795