diff options
author | Alex Woods <devnull@localhost> | 2003-12-27 18:57:50 +0000 |
---|---|---|
committer | Alex Woods <devnull@localhost> | 2003-12-27 18:57:50 +0000 |
commit | e325e80abac96407e8bf501f0c77e10ed80bb090 (patch) | |
tree | e69c01dfd4ab3797991ea6e9f8ba495559447501 /linux/drivers | |
parent | d1000cc47d222fd0ceddc2a15faf3cbfe3a2b979 (diff) | |
download | mediapointer-dvb-s2-e325e80abac96407e8bf501f0c77e10ed80bb090.tar.gz mediapointer-dvb-s2-e325e80abac96407e8bf501f0c77e10ed80bb090.tar.bz2 |
Rudimentary section filter support (enough for scan).
Alter hotplug firmware naming to fit in with dvb standard.
Diffstat (limited to 'linux/drivers')
-rw-r--r-- | linux/drivers/media/dvb/ttusb-dec/Kconfig | 11 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c | 805 |
2 files changed, 514 insertions, 302 deletions
diff --git a/linux/drivers/media/dvb/ttusb-dec/Kconfig b/linux/drivers/media/dvb/ttusb-dec/Kconfig index 6e56764f6..0251c4f27 100644 --- a/linux/drivers/media/dvb/ttusb-dec/Kconfig +++ b/linux/drivers/media/dvb/ttusb-dec/Kconfig @@ -12,15 +12,6 @@ config DVB_TTUSB_DEC The DEC devices require firmware in order to boot into a mode in which they are slaves to the PC. See - linux/Documentation/dvb/FIRMWARE for details. - - The firmware can be obtained and put into the default - locations as follows: - - wget http://hauppauge.lightpath.net/de/dec215a.exe - unzip -j dec215a.exe Software/Oem/STB/App/Boot/STB_PC_T.bin - mv STB_PC_T.bin /usr/lib/hotplug/firmware/dec2000t.bin - unzip -j dec215a.exe Software/Oem/STB/App/Boot/STB_PC_S.bin - mv STB_PC_S.bin /usr/lib/hotplug/firmware/dec3000s.bin + linux/Documentation/dvb/ttusb-dec.txt for details. Say Y if you own such a device and want to use it. diff --git a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c index 081914c83..2fcd2887b 100644 --- a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -61,13 +61,18 @@ static int debug = 0; #define LOF_HI 10600000 #define LOF_LO 9750000 -enum ttusb_model { +enum ttusb_dec_model { TTUSB_DEC2000T, TTUSB_DEC3000S }; +enum ttusb_dec_packet_type { + PACKET_AV_PES, + PACKET_SECTION +}; + struct ttusb_dec { - enum ttusb_model model; + enum ttusb_dec_model model; char *model_name; char *firmware_name; @@ -99,10 +104,14 @@ struct ttusb_dec { int iso_stream_count; struct semaphore iso_sem; - u8 av_pes[MAX_AV_PES_LENGTH + 4]; - int av_pes_state; - int av_pes_length; - int av_pes_payload_length; + u8 packet[MAX_AV_PES_LENGTH + 4]; + enum ttusb_dec_packet_type packet_type; + int packet_state; + int packet_length; + int packet_payload_length; + + int av_pes_stream_count; + int filter_stream_count; struct dvb_filter_pes2ts a_pes2ts; struct dvb_filter_pes2ts v_pes2ts; @@ -115,6 +124,9 @@ struct ttusb_dec { struct tasklet_struct urb_tasklet; spinlock_t urb_frame_list_lock; + struct list_head filter_info_list; + spinlock_t filter_info_list_lock; + int active; /* Loaded successfully */ }; @@ -124,6 +136,12 @@ struct urb_frame { struct list_head urb_frame_list; }; +struct filter_info { + u8 stream_id; + struct dvb_demux_filter *filter; + struct list_head filter_info_list; +}; + static struct dvb_frontend_info dec2000t_frontend_info = { .name = "TechnoTrend/Hauppauge DEC2000-t Frontend", .type = FE_OFDM, @@ -180,8 +198,8 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, printk("\n"); } - result = usb_bulk_msg(dec->udev, dec->command_pipe, b, sizeof(b), - &actual_len, HZ); + result = usb_bulk_msg(dec->udev, dec->command_pipe, b, + sizeof(b), &actual_len, HZ); if (result) { printk("%s: command bulk message failed: error %d\n", @@ -190,8 +208,8 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, return result; } - result = usb_bulk_msg(dec->udev, dec->result_pipe, c, sizeof(c), - &actual_len, HZ); + result = usb_bulk_msg(dec->udev, dec->result_pipe, c, + sizeof(c), &actual_len, HZ); if (result) { printk("%s: result bulk message failed: error %d\n", @@ -228,8 +246,9 @@ static int ttusb_dec_av_pes2ts_cb(void *priv, unsigned char *data) static void ttusb_dec_set_pids(struct ttusb_dec *dec) { - u8 b[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff }; + u8 b[] = { 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff }; u16 pcr = htons(dec->pid[DMX_PES_PCR]); u16 audio = htons(dec->pid[DMX_PES_AUDIO]); @@ -254,103 +273,79 @@ static void ttusb_dec_set_pids(struct ttusb_dec *dec) static void ttusb_dec_process_av_pes(struct ttusb_dec *dec, u8 *av_pes, int length) { - int i; - u16 csum = 0; - u8 c; - - if (length < 16) { - printk("%s: packet too short.\n", __FUNCTION__); - return; - } - - for (i = 0; i < length; i += 2) { - csum ^= le16_to_cpup((u16 *)(av_pes + i)); - c = av_pes[i]; - av_pes[i] = av_pes[i + 1]; - av_pes[i + 1] = c; - } - - if (csum) { - printk("%s: checksum failed.\n", __FUNCTION__); + if (length < 8) { + printk("%s: packet too short - discarding\n", __FUNCTION__); return; } - if (length > 8 + MAX_AV_PES_LENGTH + 4) { - printk("%s: packet too long.\n", __FUNCTION__); - return; - } - - if (!(av_pes[0] == 'A' && av_pes[1] == 'V')) { - printk("%s: invalid AV_PES packet.\n", __FUNCTION__); + if (length > 8 + MAX_AV_PES_LENGTH) { + printk("%s: packet too long - discarding\n", __FUNCTION__); return; } switch (av_pes[2]) { case 0x01: { /* VideoStream */ - int prebytes = av_pes[5] & 0x03; - int postbytes = (av_pes[5] & 0x0c) >> 2; - u16 v_pes_payload_length; - - if (dec->v_pes_postbytes > 0 && - dec->v_pes_postbytes == prebytes) { - memcpy(&dec->v_pes[dec->v_pes_length], - &av_pes[12], prebytes); - - dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes, - dec->v_pes_length + prebytes, - 1); - } + int prebytes = av_pes[5] & 0x03; + int postbytes = (av_pes[5] & 0x0c) >> 2; + u16 v_pes_payload_length; - if (av_pes[5] & 0x10) { - dec->v_pes[7] = 0x80; - dec->v_pes[8] = 0x05; - - dec->v_pes[9] = 0x21 | - ((av_pes[8] & 0xc0) >> 5); - dec->v_pes[10] = ((av_pes[8] & 0x3f) << 2) | - ((av_pes[9] & 0xc0) >> 6); - dec->v_pes[11] = 0x01 | - ((av_pes[9] & 0x3f) << 2) | - ((av_pes[10] & 0x80) >> 6); - dec->v_pes[12] = ((av_pes[10] & 0x7f) << 1) | - ((av_pes[11] & 0xc0) >> 7); - dec->v_pes[13] = 0x01 | - ((av_pes[11] & 0x7f) << 1); - - memcpy(&dec->v_pes[14], &av_pes[12 + prebytes], - length - 16 - prebytes); - dec->v_pes_length = 14 + length - 16 - prebytes; - } else { - dec->v_pes[7] = 0x00; - dec->v_pes[8] = 0x00; + if (dec->v_pes_postbytes > 0 && + dec->v_pes_postbytes == prebytes) { + memcpy(&dec->v_pes[dec->v_pes_length], + &av_pes[12], prebytes); - memcpy(&dec->v_pes[9], &av_pes[8], length - 12); - dec->v_pes_length = 9 + length - 12; - } + dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes, + dec->v_pes_length + prebytes, 1); + } - dec->v_pes_postbytes = postbytes; + if (av_pes[5] & 0x10) { + dec->v_pes[7] = 0x80; + dec->v_pes[8] = 0x05; + + dec->v_pes[9] = 0x21 | ((av_pes[8] & 0xc0) >> 5); + dec->v_pes[10] = ((av_pes[8] & 0x3f) << 2) | + ((av_pes[9] & 0xc0) >> 6); + dec->v_pes[11] = 0x01 | + ((av_pes[9] & 0x3f) << 2) | + ((av_pes[10] & 0x80) >> 6); + dec->v_pes[12] = ((av_pes[10] & 0x7f) << 1) | + ((av_pes[11] & 0xc0) >> 7); + dec->v_pes[13] = 0x01 | ((av_pes[11] & 0x7f) << 1); + + memcpy(&dec->v_pes[14], &av_pes[12 + prebytes], + length - 12 - prebytes); + dec->v_pes_length = 14 + length - 12 - prebytes; + } else { + dec->v_pes[7] = 0x00; + dec->v_pes[8] = 0x00; - if (dec->v_pes[9 + dec->v_pes[8]] == 0x00 && - dec->v_pes[10 + dec->v_pes[8]] == 0x00 && - dec->v_pes[11 + dec->v_pes[8]] == 0x01) - dec->v_pes[6] = 0x84; - else - dec->v_pes[6] = 0x80; + memcpy(&dec->v_pes[9], &av_pes[8], length - 8); + dec->v_pes_length = 9 + length - 8; + } - v_pes_payload_length = htons(dec->v_pes_length - 6 + - postbytes); - memcpy(&dec->v_pes[4], &v_pes_payload_length, 2); + dec->v_pes_postbytes = postbytes; - if (postbytes == 0) - dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes, - dec->v_pes_length, 1); + if (dec->v_pes[9 + dec->v_pes[8]] == 0x00 && + dec->v_pes[10 + dec->v_pes[8]] == 0x00 && + dec->v_pes[11 + dec->v_pes[8]] == 0x01) + dec->v_pes[6] = 0x84; + else + dec->v_pes[6] = 0x80; - break; - } + v_pes_payload_length = htons(dec->v_pes_length - 6 + + postbytes); + memcpy(&dec->v_pes[4], &v_pes_payload_length, 2); + + if (postbytes == 0) + dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes, + dec->v_pes_length, 1); + + break; + } case 0x02: /* MainAudioStream */ - dvb_filter_pes2ts(&dec->a_pes2ts, &av_pes[8], length - 12, + dvb_filter_pes2ts(&dec->a_pes2ts, &av_pes[8], length - 8, av_pes[5] & 0x10); break; @@ -358,93 +353,194 @@ static void ttusb_dec_process_av_pes(struct ttusb_dec *dec, u8 *av_pes, printk("%s: unknown AV_PES type: %02x.\n", __FUNCTION__, av_pes[2]); break; + } +} + +static void ttusb_dec_process_filter(struct ttusb_dec *dec, u8 *packet, + int length) +{ + struct list_head *item; + struct filter_info *finfo; + struct dvb_demux_filter *filter = NULL; + unsigned long flags; + u8 sid; + + sid = packet[1]; + spin_lock_irqsave(&dec->filter_info_list_lock, flags); + for (item = dec->filter_info_list.next; item != &dec->filter_info_list; + item = item->next) { + finfo = list_entry(item, struct filter_info, filter_info_list); + if (finfo->stream_id == sid) { + filter = finfo->filter; + break; + } + } + spin_unlock_irqrestore(&dec->filter_info_list_lock, flags); + + if (filter) + filter->feed->cb.sec(&packet[2], length - 2, NULL, 0, + &filter->filter, DMX_OK); +} + +static void ttusb_dec_process_packet(struct ttusb_dec *dec) +{ + int i; + u16 csum = 0; + + if (dec->packet_length % 2) { + printk("%s: odd sized packet - discarding\n", __FUNCTION__); + return; + } + + for (i = 0; i < dec->packet_length; i += 2) + csum ^= ((dec->packet[i] << 8) + dec->packet[i + 1]); + + if (csum) { + printk("%s: checksum failed - discarding\n", __FUNCTION__); + return; + } + + switch (dec->packet_type) { + case PACKET_AV_PES: + if (dec->av_pes_stream_count) + ttusb_dec_process_av_pes(dec, dec->packet, + dec->packet_payload_length); + break; + + case PACKET_SECTION: + if (dec->filter_stream_count) + ttusb_dec_process_filter(dec, dec->packet, + dec->packet_payload_length); + break; + } +} + +static void swap_bytes(u8 *b, int length) +{ + u8 c; + length -= length % 2; + for (; length; b += 2, length -= 2) { + c = *b; + *b = *(b + 1); + *(b + 1) = c; } } static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b, int length) { + swap_bytes(b, length); + while (length) { - switch (dec->av_pes_state) { + switch (dec->packet_state) { case 0: case 1: - case 3: - if (*b++ == 0xaa) { - dec->av_pes_state++; - if (dec->av_pes_state == 4) - dec->av_pes_length = 0; - } else { - dec->av_pes_state = 0; - } + case 2: + if (*b++ == 0xaa) + dec->packet_state++; + else + dec->packet_state = 0; length--; break; - case 2: + case 3: if (*b++ == 0x00) { - dec->av_pes_state++; + dec->packet_state++; + dec->packet_length = 0; } else { - dec->av_pes_state = 0; + dec->packet_state = 0; } length--; break; case 4: - dec->av_pes[dec->av_pes_length++] = *b++; - - if (dec->av_pes_length == 8) { - dec->av_pes_state++; - dec->av_pes_payload_length = le16_to_cpup( - (u16 *)(dec->av_pes + 6)); + dec->packet[dec->packet_length++] = *b++; + + if (dec->packet_length == 3) { + if (dec->packet[0] == 'A' && + dec->packet[1] == 'V') { + dec->packet_type = PACKET_AV_PES; + dec->packet_state++; + } else if (dec->packet[0] == 'S') { + dec->packet_type = PACKET_SECTION; + dec->packet_state++; + } else { + dec->packet_state = 0; + } } length--; break; - case 5: { - int remainder = dec->av_pes_payload_length + - 8 - dec->av_pes_length; - - if (length >= remainder) { - memcpy(dec->av_pes + dec->av_pes_length, - b, remainder); - dec->av_pes_length += remainder; - b += remainder; - length -= remainder; - dec->av_pes_state++; - } else { - memcpy(&dec->av_pes[dec->av_pes_length], - b, length); - dec->av_pes_length += length; - length = 0; - } + case 5: + dec->packet[dec->packet_length++] = *b++; + + if (dec->packet_type == PACKET_AV_PES && + dec->packet_length == 8) { + dec->packet_state++; + dec->packet_payload_length = 8 + + (dec->packet[6] << 8) + + dec->packet[7]; + } else if (dec->packet_type == PACKET_SECTION && + dec->packet_length == 5) { + dec->packet_state++; + dec->packet_payload_length = 5 + + ((dec->packet[3] & 0x0f) << 8) + + dec->packet[4]; + } + + length--; + break; - break; + case 6: { + int remainder = dec->packet_payload_length - + dec->packet_length; + + if (length >= remainder) { + memcpy(dec->packet + dec->packet_length, + b, remainder); + dec->packet_length += remainder; + b += remainder; + length -= remainder; + dec->packet_state++; + } else { + memcpy(&dec->packet[dec->packet_length], + b, length); + dec->packet_length += length; + length = 0; } - case 6: - dec->av_pes[dec->av_pes_length++] = *b++; + break; + } + + case 7: { + int tail = 4; - if (dec->av_pes_length == - 8 + dec->av_pes_payload_length + 4) { - ttusb_dec_process_av_pes(dec, dec->av_pes, - dec->av_pes_length); - dec->av_pes_state = 0; + dec->packet[dec->packet_length++] = *b++; + + if (dec->packet_type == PACKET_SECTION && + dec->packet_payload_length % 2) + tail++; + + if (dec->packet_length == + dec->packet_payload_length + tail) { + ttusb_dec_process_packet(dec); + dec->packet_state = 0; } length--; break; + } default: printk("%s: illegal packet state encountered.\n", __FUNCTION__); - dec->av_pes_state = 0; - + dec->packet_state = 0; } - } } @@ -574,12 +670,8 @@ static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec) dec->iso_stream_count--; if (!dec->iso_stream_count) { - u8 b0[] = { 0x00 }; - for (i = 0; i < ISO_BUF_COUNT; i++) usb_unlink_urb(dec->iso_urb[i]); - - ttusb_dec_send_command(dec, 0x81, sizeof(b0), b0, NULL, NULL); } up(&dec->iso_sem); @@ -607,10 +699,6 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec) return -EAGAIN; if (!dec->iso_stream_count) { - u8 b0[] = { 0x05 }; - - ttusb_dec_send_command(dec, 0x80, sizeof(b0), b0, NULL, NULL); - ttusb_dec_setup_urbs(dec); for (i = 0; i < ISO_BUF_COUNT; i++) { @@ -633,7 +721,7 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec) } } - dec->av_pes_state = 0; + dec->packet_state = 0; dec->v_pes_postbytes = 0; } @@ -648,34 +736,14 @@ static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec) return 0; } -static int ttusb_dec_start_feed(struct dvb_demux_feed *dvbdmxfeed) +static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed) { struct dvb_demux *dvbdmx = dvbdmxfeed->demux; struct ttusb_dec *dec = dvbdmx->priv; + u8 b0[] = { 0x05 }; dprintk("%s\n", __FUNCTION__); - if (!dvbdmx->dmx.frontend) - return -EINVAL; - - dprintk(" pid: 0x%04X\n", dvbdmxfeed->pid); - - switch (dvbdmxfeed->type) { - - case DMX_TYPE_TS: - dprintk(" type: DMX_TYPE_TS\n"); - break; - - case DMX_TYPE_SEC: - dprintk(" type: DMX_TYPE_SEC\n"); - break; - - default: - dprintk(" type: unknown (%d)\n", dvbdmxfeed->type); - return -EINVAL; - - } - dprintk(" ts_type:"); if (dvbdmxfeed->ts_type & TS_DECODER) @@ -725,22 +793,151 @@ static int ttusb_dec_start_feed(struct dvb_demux_feed *dvbdmxfeed) } + ttusb_dec_send_command(dec, 0x80, sizeof(b0), b0, NULL, NULL); + + dec->av_pes_stream_count++; ttusb_dec_start_iso_xfer(dec); return 0; } -static int ttusb_dec_stop_feed(struct dvb_demux_feed *dvbdmxfeed) +static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed) { struct ttusb_dec *dec = dvbdmxfeed->demux->priv; + u8 b0[] = { 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00 }; + u16 pid; + u8 c[COMMAND_PACKET_SIZE]; + int c_length; + int result; + struct filter_info *finfo; + unsigned long flags; + u8 x = 1; dprintk("%s\n", __FUNCTION__); + pid = htons(dvbdmxfeed->pid); + memcpy(&b0[0], &pid, 2); + memcpy(&b0[4], &x, 1); + memcpy(&b0[5], &dvbdmxfeed->filter->filter.filter_value[0], 1); + + result = ttusb_dec_send_command(dec, 0x60, sizeof(b0), b0, + &c_length, c); + + if (!result) { + if (c_length == 2) { + if (!(finfo = kmalloc(sizeof(struct filter_info), + GFP_ATOMIC))) + return -ENOMEM; + + finfo->stream_id = c[1]; + finfo->filter = dvbdmxfeed->filter; + + spin_lock_irqsave(&dec->filter_info_list_lock, flags); + list_add_tail(&finfo->filter_info_list, + &dec->filter_info_list); + spin_unlock_irqrestore(&dec->filter_info_list_lock, + flags); + + dvbdmxfeed->priv = finfo; + + dec->filter_stream_count++; + ttusb_dec_start_iso_xfer(dec); + + return 0; + } + + return -EAGAIN; + } else + return result; +} + +static int ttusb_dec_start_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; + + dprintk("%s\n", __FUNCTION__); + + if (!dvbdmx->dmx.frontend) + return -EINVAL; + + dprintk(" pid: 0x%04X\n", dvbdmxfeed->pid); + + switch (dvbdmxfeed->type) { + + case DMX_TYPE_TS: + return ttusb_dec_start_ts_feed(dvbdmxfeed); + break; + + case DMX_TYPE_SEC: + return ttusb_dec_start_sec_feed(dvbdmxfeed); + break; + + default: + dprintk(" type: unknown (%d)\n", dvbdmxfeed->type); + return -EINVAL; + + } +} + +static int ttusb_dec_stop_ts_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + struct ttusb_dec *dec = dvbdmxfeed->demux->priv; + u8 b0[] = { 0x00 }; + + ttusb_dec_send_command(dec, 0x81, sizeof(b0), b0, NULL, NULL); + + dec->av_pes_stream_count--; + ttusb_dec_stop_iso_xfer(dec); return 0; } +static int ttusb_dec_stop_sec_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + struct ttusb_dec *dec = dvbdmxfeed->demux->priv; + u8 b0[] = { 0x00, 0x00 }; + struct filter_info *finfo = (struct filter_info *)dvbdmxfeed->priv; + unsigned long flags; + + b0[1] = finfo->stream_id; + spin_lock_irqsave(&dec->filter_info_list_lock, flags); + list_del(&finfo->filter_info_list); + spin_unlock_irqrestore(&dec->filter_info_list_lock, flags); + kfree(finfo); + ttusb_dec_send_command(dec, 0x62, sizeof(b0), b0, NULL, NULL); + + dec->filter_stream_count--; + + ttusb_dec_stop_iso_xfer(dec); + + return 0; +} + +static int ttusb_dec_stop_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + dprintk("%s\n", __FUNCTION__); + + switch (dvbdmxfeed->type) { + case DMX_TYPE_TS: + return ttusb_dec_stop_ts_feed(dvbdmxfeed); + break; + + case DMX_TYPE_SEC: + return ttusb_dec_stop_sec_feed(dvbdmxfeed); + break; + } + + return 0; +} + static void ttusb_dec_free_iso_urbs(struct ttusb_dec *dec) { int i; @@ -839,8 +1036,9 @@ static void ttusb_dec_init_usb(struct ttusb_dec *dec) static int ttusb_dec_boot_dsp(struct ttusb_dec *dec) { int i, j, actual_len, result, size, trans_count; - u8 b0[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00 }; + u8 b0[] = { 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 }; u8 b1[] = { 0x61 }; u8 b[ARM_PACKET_SIZE]; u8 *firmware = NULL; @@ -865,21 +1063,21 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec) firmware_size = fw_entry->size; #endif switch (dec->model) { - case TTUSB_DEC2000T: + case TTUSB_DEC2000T: #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - firmware = &dsp_dec2000t[0]; - firmware_size = sizeof(dsp_dec2000t); + firmware = &dsp_dec2000t[0]; + firmware_size = sizeof(dsp_dec2000t); #endif - firmware_csum = 0x1bc86100; - break; + firmware_csum = 0x1bc86100; + break; - case TTUSB_DEC3000S: + case TTUSB_DEC3000S: #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - firmware = &dsp_dec3000s[0]; - firmware_size = sizeof(dsp_dec3000s); + firmware = &dsp_dec3000s[0]; + firmware_size = sizeof(dsp_dec3000s); #endif - firmware_csum = 0x00000000; - break; + firmware_csum = 0x00000000; + break; } firmware_size_nl = htonl(firmware_size); @@ -1070,7 +1268,6 @@ static int ttusb_dec_2000t_frontend_ioctl(struct dvb_frontend *fe, unsigned int dprintk("%s\n", __FUNCTION__); switch (cmd) { - case FE_GET_INFO: dprintk("%s: FE_GET_INFO\n", __FUNCTION__); memcpy(arg, dec->frontend_info, @@ -1078,27 +1275,27 @@ static int ttusb_dec_2000t_frontend_ioctl(struct dvb_frontend *fe, unsigned int break; case FE_READ_STATUS: { - fe_status_t *status = (fe_status_t *)arg; - dprintk("%s: FE_READ_STATUS\n", __FUNCTION__); - *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | - FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK; - break; - } + fe_status_t *status = (fe_status_t *)arg; + dprintk("%s: FE_READ_STATUS\n", __FUNCTION__); + *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | + FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK; + break; + } case FE_READ_BER: { - u32 *ber = (u32 *)arg; - dprintk("%s: FE_READ_BER\n", __FUNCTION__); - *ber = 0; - return -ENOSYS; - break; - } + u32 *ber = (u32 *)arg; + dprintk("%s: FE_READ_BER\n", __FUNCTION__); + *ber = 0; + return -ENOSYS; + break; + } case FE_READ_SIGNAL_STRENGTH: { - dprintk("%s: FE_READ_SIGNAL_STRENGTH\n", __FUNCTION__); - *(s32 *)arg = 0xFF; - return -ENOSYS; - break; - } + dprintk("%s: FE_READ_SIGNAL_STRENGTH\n", __FUNCTION__); + *(s32 *)arg = 0xFF; + return -ENOSYS; + break; + } case FE_READ_SNR: dprintk("%s: FE_READ_SNR\n", __FUNCTION__); @@ -1113,26 +1310,28 @@ static int ttusb_dec_2000t_frontend_ioctl(struct dvb_frontend *fe, unsigned int break; case FE_SET_FRONTEND: { - struct dvb_frontend_parameters *p = - (struct dvb_frontend_parameters *)arg; - u8 b[] = { 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0xff, 0x00, 0x00, 0x00, 0xff }; - u32 freq; - - dprintk("%s: FE_SET_FRONTEND\n", __FUNCTION__); + struct dvb_frontend_parameters *p = + (struct dvb_frontend_parameters *)arg; + u8 b[] = { 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff }; + u32 freq; + + dprintk("%s: FE_SET_FRONTEND\n", __FUNCTION__); + + dprintk(" frequency->%d\n", p->frequency); + dprintk(" symbol_rate->%d\n", + p->u.qam.symbol_rate); + dprintk(" inversion->%d\n", p->inversion); + + freq = htonl(p->frequency / 1000); + memcpy(&b[4], &freq, sizeof (u32)); + ttusb_dec_send_command(dec, 0x71, sizeof(b), b, NULL, NULL); - dprintk(" frequency->%d\n", p->frequency); - dprintk(" symbol_rate->%d\n", - p->u.qam.symbol_rate); - dprintk(" inversion->%d\n", p->inversion); - - freq = htonl(p->frequency / 1000); - memcpy(&b[4], &freq, sizeof (u32)); - ttusb_dec_send_command(dec, 0x71, sizeof(b), b, NULL, NULL); - - break; - } + break; + } case FE_GET_FRONTEND: dprintk("%s: FE_GET_FRONTEND\n", __FUNCTION__); @@ -1154,14 +1353,13 @@ static int ttusb_dec_2000t_frontend_ioctl(struct dvb_frontend *fe, unsigned int default: dprintk("%s: unknown IOCTL (0x%X)\n", __FUNCTION__, cmd); return -EINVAL; - } return 0; } -static int ttusb_dec_3000s_frontend_ioctl(struct dvb_frontend *fe, unsigned int cmd, - void *arg) +static int ttusb_dec_3000s_frontend_ioctl(struct dvb_frontend *fe, + unsigned int cmd, void *arg) { struct ttusb_dec *dec = fe->data; @@ -1176,27 +1374,27 @@ static int ttusb_dec_3000s_frontend_ioctl(struct dvb_frontend *fe, unsigned int break; case FE_READ_STATUS: { - fe_status_t *status = (fe_status_t *)arg; - dprintk("%s: FE_READ_STATUS\n", __FUNCTION__); - *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | - FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK; - break; - } + fe_status_t *status = (fe_status_t *)arg; + dprintk("%s: FE_READ_STATUS\n", __FUNCTION__); + *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | + FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK; + break; + } case FE_READ_BER: { - u32 *ber = (u32 *)arg; - dprintk("%s: FE_READ_BER\n", __FUNCTION__); - *ber = 0; - return -ENOSYS; - break; - } + u32 *ber = (u32 *)arg; + dprintk("%s: FE_READ_BER\n", __FUNCTION__); + *ber = 0; + return -ENOSYS; + break; + } case FE_READ_SIGNAL_STRENGTH: { - dprintk("%s: FE_READ_SIGNAL_STRENGTH\n", __FUNCTION__); - *(s32 *)arg = 0xFF; - return -ENOSYS; - break; - } + dprintk("%s: FE_READ_SIGNAL_STRENGTH\n", __FUNCTION__); + *(s32 *)arg = 0xFF; + return -ENOSYS; + break; + } case FE_READ_SNR: dprintk("%s: FE_READ_SNR\n", __FUNCTION__); @@ -1211,37 +1409,41 @@ static int ttusb_dec_3000s_frontend_ioctl(struct dvb_frontend *fe, unsigned int break; case FE_SET_FRONTEND: { - struct dvb_frontend_parameters *p = - (struct dvb_frontend_parameters *)arg; - u8 b[] = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00 }; - u32 freq; - u32 sym_rate; - u32 band; - - - dprintk("%s: FE_SET_FRONTEND\n", __FUNCTION__); - - dprintk(" frequency->%d\n", p->frequency); - dprintk(" symbol_rate->%d\n", - p->u.qam.symbol_rate); - dprintk(" inversion->%d\n", p->inversion); - - freq = htonl(p->frequency * 1000 + (dec->hi_band ? LOF_HI : LOF_LO)); - memcpy(&b[4], &freq, sizeof(u32)); - sym_rate = htonl(p->u.qam.symbol_rate); - memcpy(&b[12], &sym_rate, sizeof(u32)); - band = htonl(dec->hi_band ? LOF_HI : LOF_LO); - memcpy(&b[24], &band, sizeof(u32)); - - ttusb_dec_send_command(dec, 0x71, sizeof(b), b, NULL, NULL); + struct dvb_frontend_parameters *p = + (struct dvb_frontend_parameters *)arg; + u8 b[] = { 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0d, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; + u32 freq; + u32 sym_rate; + u32 band; + + dprintk("%s: FE_SET_FRONTEND\n", __FUNCTION__); + + dprintk(" frequency->%d\n", p->frequency); + dprintk(" symbol_rate->%d\n", + p->u.qam.symbol_rate); + dprintk(" inversion->%d\n", p->inversion); + + freq = htonl(p->frequency * 1000 + + (dec->hi_band ? LOF_HI : LOF_LO)); + memcpy(&b[4], &freq, sizeof(u32)); + sym_rate = htonl(p->u.qam.symbol_rate); + memcpy(&b[12], &sym_rate, sizeof(u32)); + band = htonl(dec->hi_band ? LOF_HI : LOF_LO); + memcpy(&b[24], &band, sizeof(u32)); + + ttusb_dec_send_command(dec, 0x71, sizeof(b), b, NULL, NULL); - break; - } + break; + } case FE_GET_FRONTEND: dprintk("%s: FE_GET_FRONTEND\n", __FUNCTION__); @@ -1269,11 +1471,11 @@ static int ttusb_dec_3000s_frontend_ioctl(struct dvb_frontend *fe, unsigned int break; case FE_SET_TONE: { - fe_sec_tone_mode_t tone = (fe_sec_tone_mode_t)arg; - dprintk("%s: FE_SET_TONE\n", __FUNCTION__); - dec->hi_band = (SEC_TONE_ON == tone); - break; - } + fe_sec_tone_mode_t tone = (fe_sec_tone_mode_t)arg; + dprintk("%s: FE_SET_TONE\n", __FUNCTION__); + dec->hi_band = (SEC_TONE_ON == tone); + break; + } case FE_SET_VOLTAGE: dprintk("%s: FE_SET_VOLTAGE\n", __FUNCTION__); @@ -1282,7 +1484,6 @@ static int ttusb_dec_3000s_frontend_ioctl(struct dvb_frontend *fe, unsigned int default: dprintk("%s: unknown IOCTL (0x%X)\n", __FUNCTION__, cmd); return -EINVAL; - } return 0; @@ -1293,15 +1494,15 @@ static void ttusb_dec_init_frontend(struct ttusb_dec *dec) dec->i2c_bus.adapter = dec->adapter; switch (dec->model) { - case TTUSB_DEC2000T: - dec->frontend_info = &dec2000t_frontend_info; - dec->frontend_ioctl = ttusb_dec_2000t_frontend_ioctl; - break; + case TTUSB_DEC2000T: + dec->frontend_info = &dec2000t_frontend_info; + dec->frontend_ioctl = ttusb_dec_2000t_frontend_ioctl; + break; - case TTUSB_DEC3000S: - dec->frontend_info = &dec3000s_frontend_info; - dec->frontend_ioctl = ttusb_dec_3000s_frontend_ioctl; - break; + case TTUSB_DEC3000S: + dec->frontend_info = &dec3000s_frontend_info; + dec->frontend_ioctl = ttusb_dec_3000s_frontend_ioctl; + break; } dvb_register_frontend(dec->frontend_ioctl, &dec->i2c_bus, (void *)dec, @@ -1313,6 +1514,24 @@ static void ttusb_dec_exit_frontend(struct ttusb_dec *dec) dvb_unregister_frontend(dec->frontend_ioctl, &dec->i2c_bus); } +static void ttusb_dec_init_filters(struct ttusb_dec *dec) +{ + INIT_LIST_HEAD(&dec->filter_info_list); + dec->filter_info_list_lock = SPIN_LOCK_UNLOCKED; +} + +static void ttusb_dec_exit_filters(struct ttusb_dec *dec) +{ + struct list_head *item; + struct filter_info *finfo; + + while ((item = dec->filter_info_list.next) != &dec->filter_info_list) { + finfo = list_entry(item, struct filter_info, filter_info_list); + list_del(&finfo->filter_info_list); + kfree(finfo); + } +} + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) static void *ttusb_dec_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id) @@ -1350,17 +1569,17 @@ static int ttusb_dec_probe(struct usb_interface *intf, memset(dec, 0, sizeof(struct ttusb_dec)); switch (id->idProduct) { - case 0x1006: - dec->model = TTUSB_DEC3000S; - dec->model_name = "DEC3000-s"; - dec->firmware_name = "dec3000s.bin"; - break; + case 0x1006: + dec->model = TTUSB_DEC3000S; + dec->model_name = "DEC3000-s"; + dec->firmware_name = "dvb-ttusb-dec-3000s-2.15a.fw"; + break; - case 0x1008: - dec->model = TTUSB_DEC2000T; - dec->model_name = "DEC2000-t"; - dec->firmware_name = "dec2000t.bin"; - break; + case 0x1008: + dec->model = TTUSB_DEC2000T; + dec->model_name = "DEC2000-t"; + dec->firmware_name = "dvb-ttusb-dec-2000t-2.15a.fw"; + break; } dec->udev = udev; @@ -1373,6 +1592,7 @@ static int ttusb_dec_probe(struct usb_interface *intf, ttusb_dec_init_dvb(dec); ttusb_dec_init_frontend(dec); ttusb_dec_init_v_pes(dec); + ttusb_dec_init_filters(dec); ttusb_dec_init_tasklet(dec); dec->active = 1; @@ -1402,6 +1622,7 @@ static void ttusb_dec_disconnect(struct usb_interface *intf) if (dec->active) { ttusb_dec_exit_tasklet(dec); + ttusb_dec_exit_filters(dec); ttusb_dec_exit_usb(dec); ttusb_dec_exit_frontend(dec); ttusb_dec_exit_dvb(dec); |