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