diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/media/dvb/ttusb-dec |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/media/dvb/ttusb-dec')
-rw-r--r-- | drivers/media/dvb/ttusb-dec/Kconfig | 21 | ||||
-rw-r--r-- | drivers/media/dvb/ttusb-dec/Makefile | 3 | ||||
-rw-r--r-- | drivers/media/dvb/ttusb-dec/ttusb_dec.c | 1744 | ||||
-rw-r--r-- | drivers/media/dvb/ttusb-dec/ttusbdecfe.c | 255 | ||||
-rw-r--r-- | drivers/media/dvb/ttusb-dec/ttusbdecfe.h | 38 |
5 files changed, 2061 insertions, 0 deletions
diff --git a/drivers/media/dvb/ttusb-dec/Kconfig b/drivers/media/dvb/ttusb-dec/Kconfig new file mode 100644 index 000000000000..c334526af66f --- /dev/null +++ b/drivers/media/dvb/ttusb-dec/Kconfig | |||
@@ -0,0 +1,21 @@ | |||
1 | config DVB_TTUSB_DEC | ||
2 | tristate "Technotrend/Hauppauge USB DEC devices" | ||
3 | depends on DVB_CORE && USB | ||
4 | select FW_LOADER | ||
5 | select CRC32 | ||
6 | help | ||
7 | Support for external USB adapters designed by Technotrend and | ||
8 | produced by Hauppauge, shipped under the brand name 'DEC2000-t' | ||
9 | and 'DEC3000-s'. | ||
10 | |||
11 | Even if these devices have a MPEG decoder built in, they transmit | ||
12 | only compressed MPEG data over the USB bus, so you need | ||
13 | an external software decoder to watch TV on your computer. | ||
14 | |||
15 | This driver needs external firmware. Please use the commands | ||
16 | "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2000t", | ||
17 | "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2540t", | ||
18 | "<kerneldir>/Documentation/dvb/get_dvb_firmware dec3000s", | ||
19 | download/extract them, and then copy them to /usr/lib/hotplug/firmware. | ||
20 | |||
21 | Say Y if you own such a device and want to use it. | ||
diff --git a/drivers/media/dvb/ttusb-dec/Makefile b/drivers/media/dvb/ttusb-dec/Makefile new file mode 100644 index 000000000000..b41bf1f06a9f --- /dev/null +++ b/drivers/media/dvb/ttusb-dec/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | obj-$(CONFIG_DVB_TTUSB_DEC) += ttusb_dec.o ttusbdecfe.o | ||
2 | |||
3 | EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ | ||
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c new file mode 100644 index 000000000000..64e771bd8907 --- /dev/null +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c | |||
@@ -0,0 +1,1744 @@ | |||
1 | /* | ||
2 | * TTUSB DEC Driver | ||
3 | * | ||
4 | * Copyright (C) 2003-2004 Alex Woods <linux-dvb@giblets.org> | ||
5 | * IR support by Peter Beutner <p.beutner@gmx.net> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <asm/semaphore.h> | ||
24 | #include <linux/list.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/moduleparam.h> | ||
27 | #include <linux/pci.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/spinlock.h> | ||
30 | #include <linux/usb.h> | ||
31 | #include <linux/version.h> | ||
32 | #include <linux/interrupt.h> | ||
33 | #include <linux/firmware.h> | ||
34 | #include <linux/crc32.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <linux/input.h> | ||
37 | |||
38 | #include "dmxdev.h" | ||
39 | #include "dvb_demux.h" | ||
40 | #include "dvb_filter.h" | ||
41 | #include "dvb_frontend.h" | ||
42 | #include "dvb_net.h" | ||
43 | #include "ttusbdecfe.h" | ||
44 | |||
45 | static int debug; | ||
46 | static int output_pva; | ||
47 | static int enable_rc; | ||
48 | |||
49 | module_param(debug, int, 0644); | ||
50 | MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); | ||
51 | module_param(output_pva, int, 0444); | ||
52 | MODULE_PARM_DESC(output_pva, "Output PVA from dvr device (default:off)"); | ||
53 | module_param(enable_rc, int, 0644); | ||
54 | MODULE_PARM_DESC(enable_rc, "Turn on/off IR remote control(default: off)"); | ||
55 | |||
56 | #define dprintk if (debug) printk | ||
57 | |||
58 | #define DRIVER_NAME "TechnoTrend/Hauppauge DEC USB" | ||
59 | |||
60 | #define COMMAND_PIPE 0x03 | ||
61 | #define RESULT_PIPE 0x04 | ||
62 | #define IN_PIPE 0x08 | ||
63 | #define OUT_PIPE 0x07 | ||
64 | #define IRQ_PIPE 0x0A | ||
65 | |||
66 | #define COMMAND_PACKET_SIZE 0x3c | ||
67 | #define ARM_PACKET_SIZE 0x1000 | ||
68 | #define IRQ_PACKET_SIZE 0x8 | ||
69 | |||
70 | #define ISO_BUF_COUNT 0x04 | ||
71 | #define FRAMES_PER_ISO_BUF 0x04 | ||
72 | #define ISO_FRAME_SIZE 0x0380 | ||
73 | |||
74 | #define MAX_PVA_LENGTH 6144 | ||
75 | |||
76 | enum ttusb_dec_model { | ||
77 | TTUSB_DEC2000T, | ||
78 | TTUSB_DEC2540T, | ||
79 | TTUSB_DEC3000S | ||
80 | }; | ||
81 | |||
82 | enum ttusb_dec_packet_type { | ||
83 | TTUSB_DEC_PACKET_PVA, | ||
84 | TTUSB_DEC_PACKET_SECTION, | ||
85 | TTUSB_DEC_PACKET_EMPTY | ||
86 | }; | ||
87 | |||
88 | enum ttusb_dec_interface { | ||
89 | TTUSB_DEC_INTERFACE_INITIAL, | ||
90 | TTUSB_DEC_INTERFACE_IN, | ||
91 | TTUSB_DEC_INTERFACE_OUT | ||
92 | }; | ||
93 | |||
94 | struct ttusb_dec { | ||
95 | enum ttusb_dec_model model; | ||
96 | char *model_name; | ||
97 | char *firmware_name; | ||
98 | int can_playback; | ||
99 | |||
100 | /* DVB bits */ | ||
101 | struct dvb_adapter *adapter; | ||
102 | struct dmxdev dmxdev; | ||
103 | struct dvb_demux demux; | ||
104 | struct dmx_frontend frontend; | ||
105 | struct dvb_net dvb_net; | ||
106 | struct dvb_frontend* fe; | ||
107 | |||
108 | u16 pid[DMX_PES_OTHER]; | ||
109 | |||
110 | /* USB bits */ | ||
111 | struct usb_device *udev; | ||
112 | u8 trans_count; | ||
113 | unsigned int command_pipe; | ||
114 | unsigned int result_pipe; | ||
115 | unsigned int in_pipe; | ||
116 | unsigned int out_pipe; | ||
117 | unsigned int irq_pipe; | ||
118 | enum ttusb_dec_interface interface; | ||
119 | struct semaphore usb_sem; | ||
120 | |||
121 | void *irq_buffer; | ||
122 | struct urb *irq_urb; | ||
123 | dma_addr_t irq_dma_handle; | ||
124 | void *iso_buffer; | ||
125 | dma_addr_t iso_dma_handle; | ||
126 | struct urb *iso_urb[ISO_BUF_COUNT]; | ||
127 | int iso_stream_count; | ||
128 | struct semaphore iso_sem; | ||
129 | |||
130 | u8 packet[MAX_PVA_LENGTH + 4]; | ||
131 | enum ttusb_dec_packet_type packet_type; | ||
132 | int packet_state; | ||
133 | int packet_length; | ||
134 | int packet_payload_length; | ||
135 | u16 next_packet_id; | ||
136 | |||
137 | int pva_stream_count; | ||
138 | int filter_stream_count; | ||
139 | |||
140 | struct dvb_filter_pes2ts a_pes2ts; | ||
141 | struct dvb_filter_pes2ts v_pes2ts; | ||
142 | |||
143 | u8 v_pes[16 + MAX_PVA_LENGTH]; | ||
144 | int v_pes_length; | ||
145 | int v_pes_postbytes; | ||
146 | |||
147 | struct list_head urb_frame_list; | ||
148 | struct tasklet_struct urb_tasklet; | ||
149 | spinlock_t urb_frame_list_lock; | ||
150 | |||
151 | struct dvb_demux_filter *audio_filter; | ||
152 | struct dvb_demux_filter *video_filter; | ||
153 | struct list_head filter_info_list; | ||
154 | spinlock_t filter_info_list_lock; | ||
155 | |||
156 | struct input_dev rc_input_dev; | ||
157 | |||
158 | int active; /* Loaded successfully */ | ||
159 | }; | ||
160 | |||
161 | struct urb_frame { | ||
162 | u8 data[ISO_FRAME_SIZE]; | ||
163 | int length; | ||
164 | struct list_head urb_frame_list; | ||
165 | }; | ||
166 | |||
167 | struct filter_info { | ||
168 | u8 stream_id; | ||
169 | struct dvb_demux_filter *filter; | ||
170 | struct list_head filter_info_list; | ||
171 | }; | ||
172 | |||
173 | static u16 rc_keys[] = { | ||
174 | KEY_POWER, | ||
175 | KEY_MUTE, | ||
176 | KEY_1, | ||
177 | KEY_2, | ||
178 | KEY_3, | ||
179 | KEY_4, | ||
180 | KEY_5, | ||
181 | KEY_6, | ||
182 | KEY_7, | ||
183 | KEY_8, | ||
184 | KEY_9, | ||
185 | KEY_0, | ||
186 | KEY_CHANNELUP, | ||
187 | KEY_VOLUMEDOWN, | ||
188 | KEY_OK, | ||
189 | KEY_VOLUMEUP, | ||
190 | KEY_CHANNELDOWN, | ||
191 | KEY_PREVIOUS, | ||
192 | KEY_ESC, | ||
193 | KEY_RED, | ||
194 | KEY_GREEN, | ||
195 | KEY_YELLOW, | ||
196 | KEY_BLUE, | ||
197 | KEY_OPTION, | ||
198 | KEY_M, | ||
199 | KEY_RADIO | ||
200 | }; | ||
201 | |||
202 | static void ttusb_dec_set_model(struct ttusb_dec *dec, | ||
203 | enum ttusb_dec_model model); | ||
204 | |||
205 | static void ttusb_dec_handle_irq( struct urb *urb, struct pt_regs *regs) | ||
206 | { | ||
207 | struct ttusb_dec * dec = urb->context; | ||
208 | char *buffer = dec->irq_buffer; | ||
209 | int retval; | ||
210 | |||
211 | switch(urb->status) { | ||
212 | case 0: /*success*/ | ||
213 | break; | ||
214 | case -ECONNRESET: | ||
215 | case -ENOENT: | ||
216 | case -ESHUTDOWN: | ||
217 | case -ETIMEDOUT: | ||
218 | /* this urb is dead, cleanup */ | ||
219 | dprintk("%s:urb shutting down with status: %d\n", | ||
220 | __FUNCTION__, urb->status); | ||
221 | return; | ||
222 | default: | ||
223 | dprintk("%s:nonzero status received: %d\n", | ||
224 | __FUNCTION__,urb->status); | ||
225 | goto exit; | ||
226 | } | ||
227 | |||
228 | if( (buffer[0] == 0x1) && (buffer[2] == 0x15) ) { | ||
229 | /* IR - Event */ | ||
230 | /* this is an fact a bit too simple implementation; | ||
231 | * the box also reports a keyrepeat signal | ||
232 | * (with buffer[3] == 0x40) in an intervall of ~100ms. | ||
233 | * But to handle this correctly we had to imlemenent some | ||
234 | * kind of timer which signals a 'key up' event if no | ||
235 | * keyrepeat signal is recieved for lets say 200ms. | ||
236 | * this should/could be added later ... | ||
237 | * for now lets report each signal as a key down and up*/ | ||
238 | dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]); | ||
239 | input_report_key(&dec->rc_input_dev,rc_keys[buffer[4]-1],1); | ||
240 | input_report_key(&dec->rc_input_dev,rc_keys[buffer[4]-1],0); | ||
241 | input_sync(&dec->rc_input_dev); | ||
242 | } | ||
243 | |||
244 | exit: retval = usb_submit_urb(urb, GFP_ATOMIC); | ||
245 | if(retval) | ||
246 | printk("%s - usb_commit_urb failed with result: %d\n", | ||
247 | __FUNCTION__, retval); | ||
248 | } | ||
249 | |||
250 | static u16 crc16(u16 crc, const u8 *buf, size_t len) | ||
251 | { | ||
252 | u16 tmp; | ||
253 | |||
254 | while (len--) { | ||
255 | crc ^= *buf++; | ||
256 | crc ^= (u8)crc >> 4; | ||
257 | tmp = (u8)crc; | ||
258 | crc ^= (tmp ^ (tmp << 1)) << 4; | ||
259 | } | ||
260 | return crc; | ||
261 | } | ||
262 | |||
263 | static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, | ||
264 | int param_length, const u8 params[], | ||
265 | int *result_length, u8 cmd_result[]) | ||
266 | { | ||
267 | int result, actual_len, i; | ||
268 | u8 *b; | ||
269 | |||
270 | dprintk("%s\n", __FUNCTION__); | ||
271 | |||
272 | b = kmalloc(COMMAND_PACKET_SIZE + 4, GFP_KERNEL); | ||
273 | if (!b) | ||
274 | return -ENOMEM; | ||
275 | |||
276 | if ((result = down_interruptible(&dec->usb_sem))) { | ||
277 | kfree(b); | ||
278 | printk("%s: Failed to down usb semaphore.\n", __FUNCTION__); | ||
279 | return result; | ||
280 | } | ||
281 | |||
282 | b[0] = 0xaa; | ||
283 | b[1] = ++dec->trans_count; | ||
284 | b[2] = command; | ||
285 | b[3] = param_length; | ||
286 | |||
287 | if (params) | ||
288 | memcpy(&b[4], params, param_length); | ||
289 | |||
290 | if (debug) { | ||
291 | printk("%s: command: ", __FUNCTION__); | ||
292 | for (i = 0; i < param_length + 4; i++) | ||
293 | printk("0x%02X ", b[i]); | ||
294 | printk("\n"); | ||
295 | } | ||
296 | |||
297 | result = usb_bulk_msg(dec->udev, dec->command_pipe, b, | ||
298 | COMMAND_PACKET_SIZE + 4, &actual_len, 1000); | ||
299 | |||
300 | if (result) { | ||
301 | printk("%s: command bulk message failed: error %d\n", | ||
302 | __FUNCTION__, result); | ||
303 | up(&dec->usb_sem); | ||
304 | kfree(b); | ||
305 | return result; | ||
306 | } | ||
307 | |||
308 | result = usb_bulk_msg(dec->udev, dec->result_pipe, b, | ||
309 | COMMAND_PACKET_SIZE + 4, &actual_len, 1000); | ||
310 | |||
311 | if (result) { | ||
312 | printk("%s: result bulk message failed: error %d\n", | ||
313 | __FUNCTION__, result); | ||
314 | up(&dec->usb_sem); | ||
315 | kfree(b); | ||
316 | return result; | ||
317 | } else { | ||
318 | if (debug) { | ||
319 | printk("%s: result: ", __FUNCTION__); | ||
320 | for (i = 0; i < actual_len; i++) | ||
321 | printk("0x%02X ", b[i]); | ||
322 | printk("\n"); | ||
323 | } | ||
324 | |||
325 | if (result_length) | ||
326 | *result_length = b[3]; | ||
327 | if (cmd_result && b[3] > 0) | ||
328 | memcpy(cmd_result, &b[4], b[3]); | ||
329 | |||
330 | up(&dec->usb_sem); | ||
331 | |||
332 | kfree(b); | ||
333 | return 0; | ||
334 | } | ||
335 | } | ||
336 | |||
337 | static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode, | ||
338 | unsigned int *model, unsigned int *version) | ||
339 | { | ||
340 | u8 c[COMMAND_PACKET_SIZE]; | ||
341 | int c_length; | ||
342 | int result; | ||
343 | unsigned int tmp; | ||
344 | |||
345 | dprintk("%s\n", __FUNCTION__); | ||
346 | |||
347 | result = ttusb_dec_send_command(dec, 0x08, 0, NULL, &c_length, c); | ||
348 | if (result) | ||
349 | return result; | ||
350 | |||
351 | if (c_length >= 0x0c) { | ||
352 | if (mode != NULL) { | ||
353 | memcpy(&tmp, c, 4); | ||
354 | *mode = ntohl(tmp); | ||
355 | } | ||
356 | if (model != NULL) { | ||
357 | memcpy(&tmp, &c[4], 4); | ||
358 | *model = ntohl(tmp); | ||
359 | } | ||
360 | if (version != NULL) { | ||
361 | memcpy(&tmp, &c[8], 4); | ||
362 | *version = ntohl(tmp); | ||
363 | } | ||
364 | return 0; | ||
365 | } else { | ||
366 | return -1; | ||
367 | } | ||
368 | } | ||
369 | |||
370 | static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data) | ||
371 | { | ||
372 | struct ttusb_dec *dec = (struct ttusb_dec *)priv; | ||
373 | |||
374 | dec->audio_filter->feed->cb.ts(data, 188, NULL, 0, | ||
375 | &dec->audio_filter->feed->feed.ts, | ||
376 | DMX_OK); | ||
377 | |||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | static int ttusb_dec_video_pes2ts_cb(void *priv, unsigned char *data) | ||
382 | { | ||
383 | struct ttusb_dec *dec = (struct ttusb_dec *)priv; | ||
384 | |||
385 | dec->video_filter->feed->cb.ts(data, 188, NULL, 0, | ||
386 | &dec->video_filter->feed->feed.ts, | ||
387 | DMX_OK); | ||
388 | |||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | static void ttusb_dec_set_pids(struct ttusb_dec *dec) | ||
393 | { | ||
394 | u8 b[] = { 0x00, 0x00, 0x00, 0x00, | ||
395 | 0x00, 0x00, 0xff, 0xff, | ||
396 | 0xff, 0xff, 0xff, 0xff }; | ||
397 | |||
398 | u16 pcr = htons(dec->pid[DMX_PES_PCR]); | ||
399 | u16 audio = htons(dec->pid[DMX_PES_AUDIO]); | ||
400 | u16 video = htons(dec->pid[DMX_PES_VIDEO]); | ||
401 | |||
402 | dprintk("%s\n", __FUNCTION__); | ||
403 | |||
404 | memcpy(&b[0], &pcr, 2); | ||
405 | memcpy(&b[2], &audio, 2); | ||
406 | memcpy(&b[4], &video, 2); | ||
407 | |||
408 | ttusb_dec_send_command(dec, 0x50, sizeof(b), b, NULL, NULL); | ||
409 | |||
410 | dvb_filter_pes2ts_init(&dec->a_pes2ts, dec->pid[DMX_PES_AUDIO], | ||
411 | ttusb_dec_audio_pes2ts_cb, dec); | ||
412 | dvb_filter_pes2ts_init(&dec->v_pes2ts, dec->pid[DMX_PES_VIDEO], | ||
413 | ttusb_dec_video_pes2ts_cb, dec); | ||
414 | dec->v_pes_length = 0; | ||
415 | dec->v_pes_postbytes = 0; | ||
416 | } | ||
417 | |||
418 | static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length) | ||
419 | { | ||
420 | if (length < 8) { | ||
421 | printk("%s: packet too short - discarding\n", __FUNCTION__); | ||
422 | return; | ||
423 | } | ||
424 | |||
425 | if (length > 8 + MAX_PVA_LENGTH) { | ||
426 | printk("%s: packet too long - discarding\n", __FUNCTION__); | ||
427 | return; | ||
428 | } | ||
429 | |||
430 | switch (pva[2]) { | ||
431 | |||
432 | case 0x01: { /* VideoStream */ | ||
433 | int prebytes = pva[5] & 0x03; | ||
434 | int postbytes = (pva[5] & 0x0c) >> 2; | ||
435 | u16 v_pes_payload_length; | ||
436 | |||
437 | if (output_pva) { | ||
438 | dec->video_filter->feed->cb.ts(pva, length, NULL, 0, | ||
439 | &dec->video_filter->feed->feed.ts, DMX_OK); | ||
440 | return; | ||
441 | } | ||
442 | |||
443 | if (dec->v_pes_postbytes > 0 && | ||
444 | dec->v_pes_postbytes == prebytes) { | ||
445 | memcpy(&dec->v_pes[dec->v_pes_length], | ||
446 | &pva[12], prebytes); | ||
447 | |||
448 | dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes, | ||
449 | dec->v_pes_length + prebytes, 1); | ||
450 | } | ||
451 | |||
452 | if (pva[5] & 0x10) { | ||
453 | dec->v_pes[7] = 0x80; | ||
454 | dec->v_pes[8] = 0x05; | ||
455 | |||
456 | dec->v_pes[9] = 0x21 | ((pva[8] & 0xc0) >> 5); | ||
457 | dec->v_pes[10] = ((pva[8] & 0x3f) << 2) | | ||
458 | ((pva[9] & 0xc0) >> 6); | ||
459 | dec->v_pes[11] = 0x01 | | ||
460 | ((pva[9] & 0x3f) << 2) | | ||
461 | ((pva[10] & 0x80) >> 6); | ||
462 | dec->v_pes[12] = ((pva[10] & 0x7f) << 1) | | ||
463 | ((pva[11] & 0xc0) >> 7); | ||
464 | dec->v_pes[13] = 0x01 | ((pva[11] & 0x7f) << 1); | ||
465 | |||
466 | memcpy(&dec->v_pes[14], &pva[12 + prebytes], | ||
467 | length - 12 - prebytes); | ||
468 | dec->v_pes_length = 14 + length - 12 - prebytes; | ||
469 | } else { | ||
470 | dec->v_pes[7] = 0x00; | ||
471 | dec->v_pes[8] = 0x00; | ||
472 | |||
473 | memcpy(&dec->v_pes[9], &pva[8], length - 8); | ||
474 | dec->v_pes_length = 9 + length - 8; | ||
475 | } | ||
476 | |||
477 | dec->v_pes_postbytes = postbytes; | ||
478 | |||
479 | if (dec->v_pes[9 + dec->v_pes[8]] == 0x00 && | ||
480 | dec->v_pes[10 + dec->v_pes[8]] == 0x00 && | ||
481 | dec->v_pes[11 + dec->v_pes[8]] == 0x01) | ||
482 | dec->v_pes[6] = 0x84; | ||
483 | else | ||
484 | dec->v_pes[6] = 0x80; | ||
485 | |||
486 | v_pes_payload_length = htons(dec->v_pes_length - 6 + | ||
487 | postbytes); | ||
488 | memcpy(&dec->v_pes[4], &v_pes_payload_length, 2); | ||
489 | |||
490 | if (postbytes == 0) | ||
491 | dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes, | ||
492 | dec->v_pes_length, 1); | ||
493 | |||
494 | break; | ||
495 | } | ||
496 | |||
497 | case 0x02: /* MainAudioStream */ | ||
498 | if (output_pva) { | ||
499 | dec->audio_filter->feed->cb.ts(pva, length, NULL, 0, | ||
500 | &dec->audio_filter->feed->feed.ts, DMX_OK); | ||
501 | return; | ||
502 | } | ||
503 | |||
504 | dvb_filter_pes2ts(&dec->a_pes2ts, &pva[8], length - 8, | ||
505 | pva[5] & 0x10); | ||
506 | break; | ||
507 | |||
508 | default: | ||
509 | printk("%s: unknown PVA type: %02x.\n", __FUNCTION__, | ||
510 | pva[2]); | ||
511 | break; | ||
512 | } | ||
513 | } | ||
514 | |||
515 | static void ttusb_dec_process_filter(struct ttusb_dec *dec, u8 *packet, | ||
516 | int length) | ||
517 | { | ||
518 | struct list_head *item; | ||
519 | struct filter_info *finfo; | ||
520 | struct dvb_demux_filter *filter = NULL; | ||
521 | unsigned long flags; | ||
522 | u8 sid; | ||
523 | |||
524 | sid = packet[1]; | ||
525 | spin_lock_irqsave(&dec->filter_info_list_lock, flags); | ||
526 | for (item = dec->filter_info_list.next; item != &dec->filter_info_list; | ||
527 | item = item->next) { | ||
528 | finfo = list_entry(item, struct filter_info, filter_info_list); | ||
529 | if (finfo->stream_id == sid) { | ||
530 | filter = finfo->filter; | ||
531 | break; | ||
532 | } | ||
533 | } | ||
534 | spin_unlock_irqrestore(&dec->filter_info_list_lock, flags); | ||
535 | |||
536 | if (filter) | ||
537 | filter->feed->cb.sec(&packet[2], length - 2, NULL, 0, | ||
538 | &filter->filter, DMX_OK); | ||
539 | } | ||
540 | |||
541 | static void ttusb_dec_process_packet(struct ttusb_dec *dec) | ||
542 | { | ||
543 | int i; | ||
544 | u16 csum = 0; | ||
545 | u16 packet_id; | ||
546 | |||
547 | if (dec->packet_length % 2) { | ||
548 | printk("%s: odd sized packet - discarding\n", __FUNCTION__); | ||
549 | return; | ||
550 | } | ||
551 | |||
552 | for (i = 0; i < dec->packet_length; i += 2) | ||
553 | csum ^= ((dec->packet[i] << 8) + dec->packet[i + 1]); | ||
554 | |||
555 | if (csum) { | ||
556 | printk("%s: checksum failed - discarding\n", __FUNCTION__); | ||
557 | return; | ||
558 | } | ||
559 | |||
560 | packet_id = dec->packet[dec->packet_length - 4] << 8; | ||
561 | packet_id += dec->packet[dec->packet_length - 3]; | ||
562 | |||
563 | if ((packet_id != dec->next_packet_id) && dec->next_packet_id) { | ||
564 | printk("%s: warning: lost packets between %u and %u\n", | ||
565 | __FUNCTION__, dec->next_packet_id - 1, packet_id); | ||
566 | } | ||
567 | |||
568 | if (packet_id == 0xffff) | ||
569 | dec->next_packet_id = 0x8000; | ||
570 | else | ||
571 | dec->next_packet_id = packet_id + 1; | ||
572 | |||
573 | switch (dec->packet_type) { | ||
574 | case TTUSB_DEC_PACKET_PVA: | ||
575 | if (dec->pva_stream_count) | ||
576 | ttusb_dec_process_pva(dec, dec->packet, | ||
577 | dec->packet_payload_length); | ||
578 | break; | ||
579 | |||
580 | case TTUSB_DEC_PACKET_SECTION: | ||
581 | if (dec->filter_stream_count) | ||
582 | ttusb_dec_process_filter(dec, dec->packet, | ||
583 | dec->packet_payload_length); | ||
584 | break; | ||
585 | |||
586 | case TTUSB_DEC_PACKET_EMPTY: | ||
587 | break; | ||
588 | } | ||
589 | } | ||
590 | |||
591 | static void swap_bytes(u8 *b, int length) | ||
592 | { | ||
593 | u8 c; | ||
594 | |||
595 | length -= length % 2; | ||
596 | for (; length; b += 2, length -= 2) { | ||
597 | c = *b; | ||
598 | *b = *(b + 1); | ||
599 | *(b + 1) = c; | ||
600 | } | ||
601 | } | ||
602 | |||
603 | static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b, | ||
604 | int length) | ||
605 | { | ||
606 | swap_bytes(b, length); | ||
607 | |||
608 | while (length) { | ||
609 | switch (dec->packet_state) { | ||
610 | |||
611 | case 0: | ||
612 | case 1: | ||
613 | case 2: | ||
614 | if (*b++ == 0xaa) | ||
615 | dec->packet_state++; | ||
616 | else | ||
617 | dec->packet_state = 0; | ||
618 | |||
619 | length--; | ||
620 | break; | ||
621 | |||
622 | case 3: | ||
623 | if (*b == 0x00) { | ||
624 | dec->packet_state++; | ||
625 | dec->packet_length = 0; | ||
626 | } else if (*b != 0xaa) { | ||
627 | dec->packet_state = 0; | ||
628 | } | ||
629 | |||
630 | b++; | ||
631 | length--; | ||
632 | break; | ||
633 | |||
634 | case 4: | ||
635 | dec->packet[dec->packet_length++] = *b++; | ||
636 | |||
637 | if (dec->packet_length == 2) { | ||
638 | if (dec->packet[0] == 'A' && | ||
639 | dec->packet[1] == 'V') { | ||
640 | dec->packet_type = | ||
641 | TTUSB_DEC_PACKET_PVA; | ||
642 | dec->packet_state++; | ||
643 | } else if (dec->packet[0] == 'S') { | ||
644 | dec->packet_type = | ||
645 | TTUSB_DEC_PACKET_SECTION; | ||
646 | dec->packet_state++; | ||
647 | } else if (dec->packet[0] == 0x00) { | ||
648 | dec->packet_type = | ||
649 | TTUSB_DEC_PACKET_EMPTY; | ||
650 | dec->packet_payload_length = 2; | ||
651 | dec->packet_state = 7; | ||
652 | } else { | ||
653 | printk("%s: unknown packet type: " | ||
654 | "%02x%02x\n", __FUNCTION__, | ||
655 | dec->packet[0], dec->packet[1]); | ||
656 | dec->packet_state = 0; | ||
657 | } | ||
658 | } | ||
659 | |||
660 | length--; | ||
661 | break; | ||
662 | |||
663 | case 5: | ||
664 | dec->packet[dec->packet_length++] = *b++; | ||
665 | |||
666 | if (dec->packet_type == TTUSB_DEC_PACKET_PVA && | ||
667 | dec->packet_length == 8) { | ||
668 | dec->packet_state++; | ||
669 | dec->packet_payload_length = 8 + | ||
670 | (dec->packet[6] << 8) + | ||
671 | dec->packet[7]; | ||
672 | } else if (dec->packet_type == | ||
673 | TTUSB_DEC_PACKET_SECTION && | ||
674 | dec->packet_length == 5) { | ||
675 | dec->packet_state++; | ||
676 | dec->packet_payload_length = 5 + | ||
677 | ((dec->packet[3] & 0x0f) << 8) + | ||
678 | dec->packet[4]; | ||
679 | } | ||
680 | |||
681 | length--; | ||
682 | break; | ||
683 | |||
684 | case 6: { | ||
685 | int remainder = dec->packet_payload_length - | ||
686 | dec->packet_length; | ||
687 | |||
688 | if (length >= remainder) { | ||
689 | memcpy(dec->packet + dec->packet_length, | ||
690 | b, remainder); | ||
691 | dec->packet_length += remainder; | ||
692 | b += remainder; | ||
693 | length -= remainder; | ||
694 | dec->packet_state++; | ||
695 | } else { | ||
696 | memcpy(&dec->packet[dec->packet_length], | ||
697 | b, length); | ||
698 | dec->packet_length += length; | ||
699 | length = 0; | ||
700 | } | ||
701 | |||
702 | break; | ||
703 | } | ||
704 | |||
705 | case 7: { | ||
706 | int tail = 4; | ||
707 | |||
708 | dec->packet[dec->packet_length++] = *b++; | ||
709 | |||
710 | if (dec->packet_type == TTUSB_DEC_PACKET_SECTION && | ||
711 | dec->packet_payload_length % 2) | ||
712 | tail++; | ||
713 | |||
714 | if (dec->packet_length == | ||
715 | dec->packet_payload_length + tail) { | ||
716 | ttusb_dec_process_packet(dec); | ||
717 | dec->packet_state = 0; | ||
718 | } | ||
719 | |||
720 | length--; | ||
721 | break; | ||
722 | } | ||
723 | |||
724 | default: | ||
725 | printk("%s: illegal packet state encountered.\n", | ||
726 | __FUNCTION__); | ||
727 | dec->packet_state = 0; | ||
728 | } | ||
729 | } | ||
730 | } | ||
731 | |||
732 | static void ttusb_dec_process_urb_frame_list(unsigned long data) | ||
733 | { | ||
734 | struct ttusb_dec *dec = (struct ttusb_dec *)data; | ||
735 | struct list_head *item; | ||
736 | struct urb_frame *frame; | ||
737 | unsigned long flags; | ||
738 | |||
739 | while (1) { | ||
740 | spin_lock_irqsave(&dec->urb_frame_list_lock, flags); | ||
741 | if ((item = dec->urb_frame_list.next) != &dec->urb_frame_list) { | ||
742 | frame = list_entry(item, struct urb_frame, | ||
743 | urb_frame_list); | ||
744 | list_del(&frame->urb_frame_list); | ||
745 | } else { | ||
746 | spin_unlock_irqrestore(&dec->urb_frame_list_lock, | ||
747 | flags); | ||
748 | return; | ||
749 | } | ||
750 | spin_unlock_irqrestore(&dec->urb_frame_list_lock, flags); | ||
751 | |||
752 | ttusb_dec_process_urb_frame(dec, frame->data, frame->length); | ||
753 | kfree(frame); | ||
754 | } | ||
755 | } | ||
756 | |||
757 | static void ttusb_dec_process_urb(struct urb *urb, struct pt_regs *ptregs) | ||
758 | { | ||
759 | struct ttusb_dec *dec = urb->context; | ||
760 | |||
761 | if (!urb->status) { | ||
762 | int i; | ||
763 | |||
764 | for (i = 0; i < FRAMES_PER_ISO_BUF; i++) { | ||
765 | struct usb_iso_packet_descriptor *d; | ||
766 | u8 *b; | ||
767 | int length; | ||
768 | struct urb_frame *frame; | ||
769 | |||
770 | d = &urb->iso_frame_desc[i]; | ||
771 | b = urb->transfer_buffer + d->offset; | ||
772 | length = d->actual_length; | ||
773 | |||
774 | if ((frame = kmalloc(sizeof(struct urb_frame), | ||
775 | GFP_ATOMIC))) { | ||
776 | unsigned long flags; | ||
777 | |||
778 | memcpy(frame->data, b, length); | ||
779 | frame->length = length; | ||
780 | |||
781 | spin_lock_irqsave(&dec->urb_frame_list_lock, | ||
782 | flags); | ||
783 | list_add_tail(&frame->urb_frame_list, | ||
784 | &dec->urb_frame_list); | ||
785 | spin_unlock_irqrestore(&dec->urb_frame_list_lock, | ||
786 | flags); | ||
787 | |||
788 | tasklet_schedule(&dec->urb_tasklet); | ||
789 | } | ||
790 | } | ||
791 | } else { | ||
792 | /* -ENOENT is expected when unlinking urbs */ | ||
793 | if (urb->status != -ENOENT) | ||
794 | dprintk("%s: urb error: %d\n", __FUNCTION__, | ||
795 | urb->status); | ||
796 | } | ||
797 | |||
798 | if (dec->iso_stream_count) | ||
799 | usb_submit_urb(urb, GFP_ATOMIC); | ||
800 | } | ||
801 | |||
802 | static void ttusb_dec_setup_urbs(struct ttusb_dec *dec) | ||
803 | { | ||
804 | int i, j, buffer_offset = 0; | ||
805 | |||
806 | dprintk("%s\n", __FUNCTION__); | ||
807 | |||
808 | for (i = 0; i < ISO_BUF_COUNT; i++) { | ||
809 | int frame_offset = 0; | ||
810 | struct urb *urb = dec->iso_urb[i]; | ||
811 | |||
812 | urb->dev = dec->udev; | ||
813 | urb->context = dec; | ||
814 | urb->complete = ttusb_dec_process_urb; | ||
815 | urb->pipe = dec->in_pipe; | ||
816 | urb->transfer_flags = URB_ISO_ASAP; | ||
817 | urb->interval = 1; | ||
818 | urb->number_of_packets = FRAMES_PER_ISO_BUF; | ||
819 | urb->transfer_buffer_length = ISO_FRAME_SIZE * | ||
820 | FRAMES_PER_ISO_BUF; | ||
821 | urb->transfer_buffer = dec->iso_buffer + buffer_offset; | ||
822 | buffer_offset += ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF; | ||
823 | |||
824 | for (j = 0; j < FRAMES_PER_ISO_BUF; j++) { | ||
825 | urb->iso_frame_desc[j].offset = frame_offset; | ||
826 | urb->iso_frame_desc[j].length = ISO_FRAME_SIZE; | ||
827 | frame_offset += ISO_FRAME_SIZE; | ||
828 | } | ||
829 | } | ||
830 | } | ||
831 | |||
832 | static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec) | ||
833 | { | ||
834 | int i; | ||
835 | |||
836 | dprintk("%s\n", __FUNCTION__); | ||
837 | |||
838 | if (down_interruptible(&dec->iso_sem)) | ||
839 | return; | ||
840 | |||
841 | dec->iso_stream_count--; | ||
842 | |||
843 | if (!dec->iso_stream_count) { | ||
844 | for (i = 0; i < ISO_BUF_COUNT; i++) | ||
845 | usb_kill_urb(dec->iso_urb[i]); | ||
846 | } | ||
847 | |||
848 | up(&dec->iso_sem); | ||
849 | } | ||
850 | |||
851 | /* Setting the interface of the DEC tends to take down the USB communications | ||
852 | * for a short period, so it's important not to call this function just before | ||
853 | * trying to talk to it. | ||
854 | */ | ||
855 | static int ttusb_dec_set_interface(struct ttusb_dec *dec, | ||
856 | enum ttusb_dec_interface interface) | ||
857 | { | ||
858 | int result = 0; | ||
859 | u8 b[] = { 0x05 }; | ||
860 | |||
861 | if (interface != dec->interface) { | ||
862 | switch (interface) { | ||
863 | case TTUSB_DEC_INTERFACE_INITIAL: | ||
864 | result = usb_set_interface(dec->udev, 0, 0); | ||
865 | break; | ||
866 | case TTUSB_DEC_INTERFACE_IN: | ||
867 | result = ttusb_dec_send_command(dec, 0x80, sizeof(b), | ||
868 | b, NULL, NULL); | ||
869 | if (result) | ||
870 | return result; | ||
871 | result = usb_set_interface(dec->udev, 0, 8); | ||
872 | break; | ||
873 | case TTUSB_DEC_INTERFACE_OUT: | ||
874 | result = usb_set_interface(dec->udev, 0, 1); | ||
875 | break; | ||
876 | } | ||
877 | |||
878 | if (result) | ||
879 | return result; | ||
880 | |||
881 | dec->interface = interface; | ||
882 | } | ||
883 | |||
884 | return 0; | ||
885 | } | ||
886 | |||
887 | static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec) | ||
888 | { | ||
889 | int i, result; | ||
890 | |||
891 | dprintk("%s\n", __FUNCTION__); | ||
892 | |||
893 | if (down_interruptible(&dec->iso_sem)) | ||
894 | return -EAGAIN; | ||
895 | |||
896 | if (!dec->iso_stream_count) { | ||
897 | ttusb_dec_setup_urbs(dec); | ||
898 | |||
899 | dec->packet_state = 0; | ||
900 | dec->v_pes_postbytes = 0; | ||
901 | dec->next_packet_id = 0; | ||
902 | |||
903 | for (i = 0; i < ISO_BUF_COUNT; i++) { | ||
904 | if ((result = usb_submit_urb(dec->iso_urb[i], | ||
905 | GFP_ATOMIC))) { | ||
906 | printk("%s: failed urb submission %d: " | ||
907 | "error %d\n", __FUNCTION__, i, result); | ||
908 | |||
909 | while (i) { | ||
910 | usb_kill_urb(dec->iso_urb[i - 1]); | ||
911 | i--; | ||
912 | } | ||
913 | |||
914 | up(&dec->iso_sem); | ||
915 | return result; | ||
916 | } | ||
917 | } | ||
918 | } | ||
919 | |||
920 | dec->iso_stream_count++; | ||
921 | |||
922 | up(&dec->iso_sem); | ||
923 | |||
924 | return 0; | ||
925 | } | ||
926 | |||
927 | static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
928 | { | ||
929 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | ||
930 | struct ttusb_dec *dec = dvbdmx->priv; | ||
931 | u8 b0[] = { 0x05 }; | ||
932 | int result = 0; | ||
933 | |||
934 | dprintk("%s\n", __FUNCTION__); | ||
935 | |||
936 | dprintk(" ts_type:"); | ||
937 | |||
938 | if (dvbdmxfeed->ts_type & TS_DECODER) | ||
939 | dprintk(" TS_DECODER"); | ||
940 | |||
941 | if (dvbdmxfeed->ts_type & TS_PACKET) | ||
942 | dprintk(" TS_PACKET"); | ||
943 | |||
944 | if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY) | ||
945 | dprintk(" TS_PAYLOAD_ONLY"); | ||
946 | |||
947 | dprintk("\n"); | ||
948 | |||
949 | switch (dvbdmxfeed->pes_type) { | ||
950 | |||
951 | case DMX_TS_PES_VIDEO: | ||
952 | dprintk(" pes_type: DMX_TS_PES_VIDEO\n"); | ||
953 | dec->pid[DMX_PES_PCR] = dvbdmxfeed->pid; | ||
954 | dec->pid[DMX_PES_VIDEO] = dvbdmxfeed->pid; | ||
955 | dec->video_filter = dvbdmxfeed->filter; | ||
956 | ttusb_dec_set_pids(dec); | ||
957 | break; | ||
958 | |||
959 | case DMX_TS_PES_AUDIO: | ||
960 | dprintk(" pes_type: DMX_TS_PES_AUDIO\n"); | ||
961 | dec->pid[DMX_PES_AUDIO] = dvbdmxfeed->pid; | ||
962 | dec->audio_filter = dvbdmxfeed->filter; | ||
963 | ttusb_dec_set_pids(dec); | ||
964 | break; | ||
965 | |||
966 | case DMX_TS_PES_TELETEXT: | ||
967 | dec->pid[DMX_PES_TELETEXT] = dvbdmxfeed->pid; | ||
968 | dprintk(" pes_type: DMX_TS_PES_TELETEXT\n"); | ||
969 | break; | ||
970 | |||
971 | case DMX_TS_PES_PCR: | ||
972 | dprintk(" pes_type: DMX_TS_PES_PCR\n"); | ||
973 | dec->pid[DMX_PES_PCR] = dvbdmxfeed->pid; | ||
974 | ttusb_dec_set_pids(dec); | ||
975 | break; | ||
976 | |||
977 | case DMX_TS_PES_OTHER: | ||
978 | dprintk(" pes_type: DMX_TS_PES_OTHER\n"); | ||
979 | break; | ||
980 | |||
981 | default: | ||
982 | dprintk(" pes_type: unknown (%d)\n", dvbdmxfeed->pes_type); | ||
983 | return -EINVAL; | ||
984 | |||
985 | } | ||
986 | |||
987 | result = ttusb_dec_send_command(dec, 0x80, sizeof(b0), b0, NULL, NULL); | ||
988 | if (result) | ||
989 | return result; | ||
990 | |||
991 | dec->pva_stream_count++; | ||
992 | return ttusb_dec_start_iso_xfer(dec); | ||
993 | } | ||
994 | |||
995 | static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
996 | { | ||
997 | struct ttusb_dec *dec = dvbdmxfeed->demux->priv; | ||
998 | u8 b0[] = { 0x00, 0x00, 0x00, 0x01, | ||
999 | 0x00, 0x00, 0x00, 0x00, | ||
1000 | 0x00, 0x00, 0x00, 0x00, | ||
1001 | 0x00, 0x00, 0x00, 0x00, | ||
1002 | 0x00, 0xff, 0x00, 0x00, | ||
1003 | 0x00, 0x00, 0x00, 0x00, | ||
1004 | 0x00, 0x00, 0x00, 0x00, | ||
1005 | 0x00 }; | ||
1006 | u16 pid; | ||
1007 | u8 c[COMMAND_PACKET_SIZE]; | ||
1008 | int c_length; | ||
1009 | int result; | ||
1010 | struct filter_info *finfo; | ||
1011 | unsigned long flags; | ||
1012 | u8 x = 1; | ||
1013 | |||
1014 | dprintk("%s\n", __FUNCTION__); | ||
1015 | |||
1016 | pid = htons(dvbdmxfeed->pid); | ||
1017 | memcpy(&b0[0], &pid, 2); | ||
1018 | memcpy(&b0[4], &x, 1); | ||
1019 | memcpy(&b0[5], &dvbdmxfeed->filter->filter.filter_value[0], 1); | ||
1020 | |||
1021 | result = ttusb_dec_send_command(dec, 0x60, sizeof(b0), b0, | ||
1022 | &c_length, c); | ||
1023 | |||
1024 | if (!result) { | ||
1025 | if (c_length == 2) { | ||
1026 | if (!(finfo = kmalloc(sizeof(struct filter_info), | ||
1027 | GFP_ATOMIC))) | ||
1028 | return -ENOMEM; | ||
1029 | |||
1030 | finfo->stream_id = c[1]; | ||
1031 | finfo->filter = dvbdmxfeed->filter; | ||
1032 | |||
1033 | spin_lock_irqsave(&dec->filter_info_list_lock, flags); | ||
1034 | list_add_tail(&finfo->filter_info_list, | ||
1035 | &dec->filter_info_list); | ||
1036 | spin_unlock_irqrestore(&dec->filter_info_list_lock, | ||
1037 | flags); | ||
1038 | |||
1039 | dvbdmxfeed->priv = finfo; | ||
1040 | |||
1041 | dec->filter_stream_count++; | ||
1042 | return ttusb_dec_start_iso_xfer(dec); | ||
1043 | } | ||
1044 | |||
1045 | return -EAGAIN; | ||
1046 | } else | ||
1047 | return result; | ||
1048 | } | ||
1049 | |||
1050 | static int ttusb_dec_start_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
1051 | { | ||
1052 | struct dvb_demux *dvbdmx = dvbdmxfeed->demux; | ||
1053 | |||
1054 | dprintk("%s\n", __FUNCTION__); | ||
1055 | |||
1056 | if (!dvbdmx->dmx.frontend) | ||
1057 | return -EINVAL; | ||
1058 | |||
1059 | dprintk(" pid: 0x%04X\n", dvbdmxfeed->pid); | ||
1060 | |||
1061 | switch (dvbdmxfeed->type) { | ||
1062 | |||
1063 | case DMX_TYPE_TS: | ||
1064 | return ttusb_dec_start_ts_feed(dvbdmxfeed); | ||
1065 | break; | ||
1066 | |||
1067 | case DMX_TYPE_SEC: | ||
1068 | return ttusb_dec_start_sec_feed(dvbdmxfeed); | ||
1069 | break; | ||
1070 | |||
1071 | default: | ||
1072 | dprintk(" type: unknown (%d)\n", dvbdmxfeed->type); | ||
1073 | return -EINVAL; | ||
1074 | |||
1075 | } | ||
1076 | } | ||
1077 | |||
1078 | static int ttusb_dec_stop_ts_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
1079 | { | ||
1080 | struct ttusb_dec *dec = dvbdmxfeed->demux->priv; | ||
1081 | u8 b0[] = { 0x00 }; | ||
1082 | |||
1083 | ttusb_dec_send_command(dec, 0x81, sizeof(b0), b0, NULL, NULL); | ||
1084 | |||
1085 | dec->pva_stream_count--; | ||
1086 | |||
1087 | ttusb_dec_stop_iso_xfer(dec); | ||
1088 | |||
1089 | return 0; | ||
1090 | } | ||
1091 | |||
1092 | static int ttusb_dec_stop_sec_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
1093 | { | ||
1094 | struct ttusb_dec *dec = dvbdmxfeed->demux->priv; | ||
1095 | u8 b0[] = { 0x00, 0x00 }; | ||
1096 | struct filter_info *finfo = (struct filter_info *)dvbdmxfeed->priv; | ||
1097 | unsigned long flags; | ||
1098 | |||
1099 | b0[1] = finfo->stream_id; | ||
1100 | spin_lock_irqsave(&dec->filter_info_list_lock, flags); | ||
1101 | list_del(&finfo->filter_info_list); | ||
1102 | spin_unlock_irqrestore(&dec->filter_info_list_lock, flags); | ||
1103 | kfree(finfo); | ||
1104 | ttusb_dec_send_command(dec, 0x62, sizeof(b0), b0, NULL, NULL); | ||
1105 | |||
1106 | dec->filter_stream_count--; | ||
1107 | |||
1108 | ttusb_dec_stop_iso_xfer(dec); | ||
1109 | |||
1110 | return 0; | ||
1111 | } | ||
1112 | |||
1113 | static int ttusb_dec_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
1114 | { | ||
1115 | dprintk("%s\n", __FUNCTION__); | ||
1116 | |||
1117 | switch (dvbdmxfeed->type) { | ||
1118 | case DMX_TYPE_TS: | ||
1119 | return ttusb_dec_stop_ts_feed(dvbdmxfeed); | ||
1120 | break; | ||
1121 | |||
1122 | case DMX_TYPE_SEC: | ||
1123 | return ttusb_dec_stop_sec_feed(dvbdmxfeed); | ||
1124 | break; | ||
1125 | } | ||
1126 | |||
1127 | return 0; | ||
1128 | } | ||
1129 | |||
1130 | static void ttusb_dec_free_iso_urbs(struct ttusb_dec *dec) | ||
1131 | { | ||
1132 | int i; | ||
1133 | |||
1134 | dprintk("%s\n", __FUNCTION__); | ||
1135 | |||
1136 | for (i = 0; i < ISO_BUF_COUNT; i++) | ||
1137 | if (dec->iso_urb[i]) | ||
1138 | usb_free_urb(dec->iso_urb[i]); | ||
1139 | |||
1140 | pci_free_consistent(NULL, | ||
1141 | ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * | ||
1142 | ISO_BUF_COUNT), | ||
1143 | dec->iso_buffer, dec->iso_dma_handle); | ||
1144 | } | ||
1145 | |||
1146 | static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec) | ||
1147 | { | ||
1148 | int i; | ||
1149 | |||
1150 | dprintk("%s\n", __FUNCTION__); | ||
1151 | |||
1152 | dec->iso_buffer = pci_alloc_consistent(NULL, | ||
1153 | ISO_FRAME_SIZE * | ||
1154 | (FRAMES_PER_ISO_BUF * | ||
1155 | ISO_BUF_COUNT), | ||
1156 | &dec->iso_dma_handle); | ||
1157 | |||
1158 | memset(dec->iso_buffer, 0, | ||
1159 | ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT)); | ||
1160 | |||
1161 | for (i = 0; i < ISO_BUF_COUNT; i++) { | ||
1162 | struct urb *urb; | ||
1163 | |||
1164 | if (!(urb = usb_alloc_urb(FRAMES_PER_ISO_BUF, GFP_ATOMIC))) { | ||
1165 | ttusb_dec_free_iso_urbs(dec); | ||
1166 | return -ENOMEM; | ||
1167 | } | ||
1168 | |||
1169 | dec->iso_urb[i] = urb; | ||
1170 | } | ||
1171 | |||
1172 | ttusb_dec_setup_urbs(dec); | ||
1173 | |||
1174 | return 0; | ||
1175 | } | ||
1176 | |||
1177 | static void ttusb_dec_init_tasklet(struct ttusb_dec *dec) | ||
1178 | { | ||
1179 | spin_lock_init(&dec->urb_frame_list_lock); | ||
1180 | INIT_LIST_HEAD(&dec->urb_frame_list); | ||
1181 | tasklet_init(&dec->urb_tasklet, ttusb_dec_process_urb_frame_list, | ||
1182 | (unsigned long)dec); | ||
1183 | } | ||
1184 | |||
1185 | static void ttusb_init_rc( struct ttusb_dec *dec) | ||
1186 | { | ||
1187 | u8 b[] = { 0x00, 0x01 }; | ||
1188 | int i; | ||
1189 | |||
1190 | init_input_dev(&dec->rc_input_dev); | ||
1191 | |||
1192 | dec->rc_input_dev.name = "ttusb_dec remote control"; | ||
1193 | dec->rc_input_dev.evbit[0] = BIT(EV_KEY); | ||
1194 | dec->rc_input_dev.keycodesize = sizeof(u16); | ||
1195 | dec->rc_input_dev.keycodemax = 0x1a; | ||
1196 | dec->rc_input_dev.keycode = rc_keys; | ||
1197 | |||
1198 | for (i = 0; i < sizeof(rc_keys)/sizeof(rc_keys[0]); i++) | ||
1199 | set_bit(rc_keys[i], dec->rc_input_dev.keybit); | ||
1200 | |||
1201 | input_register_device(&dec->rc_input_dev); | ||
1202 | |||
1203 | if(usb_submit_urb(dec->irq_urb,GFP_KERNEL)) { | ||
1204 | printk("%s: usb_submit_urb failed\n",__FUNCTION__); | ||
1205 | } | ||
1206 | /* enable irq pipe */ | ||
1207 | ttusb_dec_send_command(dec,0xb0,sizeof(b),b,NULL,NULL); | ||
1208 | } | ||
1209 | |||
1210 | static void ttusb_dec_init_v_pes(struct ttusb_dec *dec) | ||
1211 | { | ||
1212 | dprintk("%s\n", __FUNCTION__); | ||
1213 | |||
1214 | dec->v_pes[0] = 0x00; | ||
1215 | dec->v_pes[1] = 0x00; | ||
1216 | dec->v_pes[2] = 0x01; | ||
1217 | dec->v_pes[3] = 0xe0; | ||
1218 | } | ||
1219 | |||
1220 | static int ttusb_dec_init_usb(struct ttusb_dec *dec) | ||
1221 | { | ||
1222 | dprintk("%s\n", __FUNCTION__); | ||
1223 | |||
1224 | sema_init(&dec->usb_sem, 1); | ||
1225 | sema_init(&dec->iso_sem, 1); | ||
1226 | |||
1227 | dec->command_pipe = usb_sndbulkpipe(dec->udev, COMMAND_PIPE); | ||
1228 | dec->result_pipe = usb_rcvbulkpipe(dec->udev, RESULT_PIPE); | ||
1229 | dec->in_pipe = usb_rcvisocpipe(dec->udev, IN_PIPE); | ||
1230 | dec->out_pipe = usb_sndisocpipe(dec->udev, OUT_PIPE); | ||
1231 | dec->irq_pipe = usb_rcvintpipe(dec->udev, IRQ_PIPE); | ||
1232 | |||
1233 | if(enable_rc) { | ||
1234 | dec->irq_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
1235 | if(!dec->irq_urb) { | ||
1236 | return -ENOMEM; | ||
1237 | } | ||
1238 | dec->irq_buffer = usb_buffer_alloc(dec->udev,IRQ_PACKET_SIZE, | ||
1239 | SLAB_ATOMIC, &dec->irq_dma_handle); | ||
1240 | if(!dec->irq_buffer) { | ||
1241 | return -ENOMEM; | ||
1242 | } | ||
1243 | usb_fill_int_urb(dec->irq_urb, dec->udev,dec->irq_pipe, | ||
1244 | dec->irq_buffer, IRQ_PACKET_SIZE, | ||
1245 | ttusb_dec_handle_irq, dec, 1); | ||
1246 | dec->irq_urb->transfer_dma = dec->irq_dma_handle; | ||
1247 | dec->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
1248 | } | ||
1249 | |||
1250 | return ttusb_dec_alloc_iso_urbs(dec); | ||
1251 | } | ||
1252 | |||
1253 | static int ttusb_dec_boot_dsp(struct ttusb_dec *dec) | ||
1254 | { | ||
1255 | int i, j, actual_len, result, size, trans_count; | ||
1256 | u8 b0[] = { 0x00, 0x00, 0x00, 0x00, | ||
1257 | 0x00, 0x00, 0x00, 0x00, | ||
1258 | 0x61, 0x00 }; | ||
1259 | u8 b1[] = { 0x61 }; | ||
1260 | u8 *b; | ||
1261 | char idstring[21]; | ||
1262 | u8 *firmware = NULL; | ||
1263 | size_t firmware_size = 0; | ||
1264 | u16 firmware_csum = 0; | ||
1265 | u16 firmware_csum_ns; | ||
1266 | u32 firmware_size_nl; | ||
1267 | u32 crc32_csum, crc32_check, tmp; | ||
1268 | const struct firmware *fw_entry = NULL; | ||
1269 | |||
1270 | dprintk("%s\n", __FUNCTION__); | ||
1271 | |||
1272 | if (request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev)) { | ||
1273 | printk(KERN_ERR "%s: Firmware (%s) unavailable.\n", | ||
1274 | __FUNCTION__, dec->firmware_name); | ||
1275 | return 1; | ||
1276 | } | ||
1277 | |||
1278 | firmware = fw_entry->data; | ||
1279 | firmware_size = fw_entry->size; | ||
1280 | |||
1281 | if (firmware_size < 60) { | ||
1282 | printk("%s: firmware size too small for DSP code (%zu < 60).\n", | ||
1283 | __FUNCTION__, firmware_size); | ||
1284 | return -1; | ||
1285 | } | ||
1286 | |||
1287 | /* a 32 bit checksum over the first 56 bytes of the DSP Code is stored | ||
1288 | at offset 56 of file, so use it to check if the firmware file is | ||
1289 | valid. */ | ||
1290 | crc32_csum = crc32(~0L, firmware, 56) ^ ~0L; | ||
1291 | memcpy(&tmp, &firmware[56], 4); | ||
1292 | crc32_check = htonl(tmp); | ||
1293 | if (crc32_csum != crc32_check) { | ||
1294 | printk("%s: crc32 check of DSP code failed (calculated " | ||
1295 | "0x%08x != 0x%08x in file), file invalid.\n", | ||
1296 | __FUNCTION__, crc32_csum, crc32_check); | ||
1297 | return -1; | ||
1298 | } | ||
1299 | memcpy(idstring, &firmware[36], 20); | ||
1300 | idstring[20] = '\0'; | ||
1301 | printk(KERN_INFO "ttusb_dec: found DSP code \"%s\".\n", idstring); | ||
1302 | |||
1303 | firmware_size_nl = htonl(firmware_size); | ||
1304 | memcpy(b0, &firmware_size_nl, 4); | ||
1305 | firmware_csum = crc16(~0, firmware, firmware_size) ^ ~0; | ||
1306 | firmware_csum_ns = htons(firmware_csum); | ||
1307 | memcpy(&b0[6], &firmware_csum_ns, 2); | ||
1308 | |||
1309 | result = ttusb_dec_send_command(dec, 0x41, sizeof(b0), b0, NULL, NULL); | ||
1310 | |||
1311 | if (result) | ||
1312 | return result; | ||
1313 | |||
1314 | trans_count = 0; | ||
1315 | j = 0; | ||
1316 | |||
1317 | b = kmalloc(ARM_PACKET_SIZE, GFP_KERNEL); | ||
1318 | if (b == NULL) | ||
1319 | return -ENOMEM; | ||
1320 | |||
1321 | for (i = 0; i < firmware_size; i += COMMAND_PACKET_SIZE) { | ||
1322 | size = firmware_size - i; | ||
1323 | if (size > COMMAND_PACKET_SIZE) | ||
1324 | size = COMMAND_PACKET_SIZE; | ||
1325 | |||
1326 | b[j + 0] = 0xaa; | ||
1327 | b[j + 1] = trans_count++; | ||
1328 | b[j + 2] = 0xf0; | ||
1329 | b[j + 3] = size; | ||
1330 | memcpy(&b[j + 4], &firmware[i], size); | ||
1331 | |||
1332 | j += COMMAND_PACKET_SIZE + 4; | ||
1333 | |||
1334 | if (j >= ARM_PACKET_SIZE) { | ||
1335 | result = usb_bulk_msg(dec->udev, dec->command_pipe, b, | ||
1336 | ARM_PACKET_SIZE, &actual_len, | ||
1337 | 100); | ||
1338 | j = 0; | ||
1339 | } else if (size < COMMAND_PACKET_SIZE) { | ||
1340 | result = usb_bulk_msg(dec->udev, dec->command_pipe, b, | ||
1341 | j - COMMAND_PACKET_SIZE + size, | ||
1342 | &actual_len, 100); | ||
1343 | } | ||
1344 | } | ||
1345 | |||
1346 | result = ttusb_dec_send_command(dec, 0x43, sizeof(b1), b1, NULL, NULL); | ||
1347 | |||
1348 | kfree(b); | ||
1349 | |||
1350 | return result; | ||
1351 | } | ||
1352 | |||
1353 | static int ttusb_dec_init_stb(struct ttusb_dec *dec) | ||
1354 | { | ||
1355 | int result; | ||
1356 | unsigned int mode, model, version; | ||
1357 | |||
1358 | dprintk("%s\n", __FUNCTION__); | ||
1359 | |||
1360 | result = ttusb_dec_get_stb_state(dec, &mode, &model, &version); | ||
1361 | |||
1362 | if (!result) { | ||
1363 | if (!mode) { | ||
1364 | if (version == 0xABCDEFAB) | ||
1365 | printk(KERN_INFO "ttusb_dec: no version " | ||
1366 | "info in Firmware\n"); | ||
1367 | else | ||
1368 | printk(KERN_INFO "ttusb_dec: Firmware " | ||
1369 | "%x.%02x%c%c\n", | ||
1370 | version >> 24, (version >> 16) & 0xff, | ||
1371 | (version >> 8) & 0xff, version & 0xff); | ||
1372 | |||
1373 | result = ttusb_dec_boot_dsp(dec); | ||
1374 | if (result) | ||
1375 | return result; | ||
1376 | else | ||
1377 | return 1; | ||
1378 | } else { | ||
1379 | /* We can't trust the USB IDs that some firmwares | ||
1380 | give the box */ | ||
1381 | switch (model) { | ||
1382 | case 0x00070008: | ||
1383 | case 0x0007000c: | ||
1384 | ttusb_dec_set_model(dec, TTUSB_DEC3000S); | ||
1385 | break; | ||
1386 | case 0x00070009: | ||
1387 | case 0x00070013: | ||
1388 | ttusb_dec_set_model(dec, TTUSB_DEC2000T); | ||
1389 | break; | ||
1390 | case 0x00070011: | ||
1391 | ttusb_dec_set_model(dec, TTUSB_DEC2540T); | ||
1392 | break; | ||
1393 | default: | ||
1394 | printk(KERN_ERR "%s: unknown model returned " | ||
1395 | "by firmware (%08x) - please report\n", | ||
1396 | __FUNCTION__, model); | ||
1397 | return -1; | ||
1398 | break; | ||
1399 | } | ||
1400 | |||
1401 | if (version >= 0x01770000) | ||
1402 | dec->can_playback = 1; | ||
1403 | |||
1404 | return 0; | ||
1405 | } | ||
1406 | } | ||
1407 | else | ||
1408 | return result; | ||
1409 | } | ||
1410 | |||
1411 | static int ttusb_dec_init_dvb(struct ttusb_dec *dec) | ||
1412 | { | ||
1413 | int result; | ||
1414 | |||
1415 | dprintk("%s\n", __FUNCTION__); | ||
1416 | |||
1417 | if ((result = dvb_register_adapter(&dec->adapter, | ||
1418 | dec->model_name, THIS_MODULE)) < 0) { | ||
1419 | printk("%s: dvb_register_adapter failed: error %d\n", | ||
1420 | __FUNCTION__, result); | ||
1421 | |||
1422 | return result; | ||
1423 | } | ||
1424 | |||
1425 | dec->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING; | ||
1426 | |||
1427 | dec->demux.priv = (void *)dec; | ||
1428 | dec->demux.filternum = 31; | ||
1429 | dec->demux.feednum = 31; | ||
1430 | dec->demux.start_feed = ttusb_dec_start_feed; | ||
1431 | dec->demux.stop_feed = ttusb_dec_stop_feed; | ||
1432 | dec->demux.write_to_decoder = NULL; | ||
1433 | |||
1434 | if ((result = dvb_dmx_init(&dec->demux)) < 0) { | ||
1435 | printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__, | ||
1436 | result); | ||
1437 | |||
1438 | dvb_unregister_adapter(dec->adapter); | ||
1439 | |||
1440 | return result; | ||
1441 | } | ||
1442 | |||
1443 | dec->dmxdev.filternum = 32; | ||
1444 | dec->dmxdev.demux = &dec->demux.dmx; | ||
1445 | dec->dmxdev.capabilities = 0; | ||
1446 | |||
1447 | if ((result = dvb_dmxdev_init(&dec->dmxdev, dec->adapter)) < 0) { | ||
1448 | printk("%s: dvb_dmxdev_init failed: error %d\n", | ||
1449 | __FUNCTION__, result); | ||
1450 | |||
1451 | dvb_dmx_release(&dec->demux); | ||
1452 | dvb_unregister_adapter(dec->adapter); | ||
1453 | |||
1454 | return result; | ||
1455 | } | ||
1456 | |||
1457 | dec->frontend.source = DMX_FRONTEND_0; | ||
1458 | |||
1459 | if ((result = dec->demux.dmx.add_frontend(&dec->demux.dmx, | ||
1460 | &dec->frontend)) < 0) { | ||
1461 | printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__, | ||
1462 | result); | ||
1463 | |||
1464 | dvb_dmxdev_release(&dec->dmxdev); | ||
1465 | dvb_dmx_release(&dec->demux); | ||
1466 | dvb_unregister_adapter(dec->adapter); | ||
1467 | |||
1468 | return result; | ||
1469 | } | ||
1470 | |||
1471 | if ((result = dec->demux.dmx.connect_frontend(&dec->demux.dmx, | ||
1472 | &dec->frontend)) < 0) { | ||
1473 | printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__, | ||
1474 | result); | ||
1475 | |||
1476 | dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend); | ||
1477 | dvb_dmxdev_release(&dec->dmxdev); | ||
1478 | dvb_dmx_release(&dec->demux); | ||
1479 | dvb_unregister_adapter(dec->adapter); | ||
1480 | |||
1481 | return result; | ||
1482 | } | ||
1483 | |||
1484 | dvb_net_init(dec->adapter, &dec->dvb_net, &dec->demux.dmx); | ||
1485 | |||
1486 | return 0; | ||
1487 | } | ||
1488 | |||
1489 | static void ttusb_dec_exit_dvb(struct ttusb_dec *dec) | ||
1490 | { | ||
1491 | dprintk("%s\n", __FUNCTION__); | ||
1492 | |||
1493 | dvb_net_release(&dec->dvb_net); | ||
1494 | dec->demux.dmx.close(&dec->demux.dmx); | ||
1495 | dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend); | ||
1496 | dvb_dmxdev_release(&dec->dmxdev); | ||
1497 | dvb_dmx_release(&dec->demux); | ||
1498 | if (dec->fe) dvb_unregister_frontend(dec->fe); | ||
1499 | dvb_unregister_adapter(dec->adapter); | ||
1500 | } | ||
1501 | |||
1502 | static void ttusb_dec_exit_rc(struct ttusb_dec *dec) | ||
1503 | { | ||
1504 | |||
1505 | dprintk("%s\n", __FUNCTION__); | ||
1506 | /* we have to check whether the irq URB is already submitted. | ||
1507 | * As the irq is submitted after the interface is changed, | ||
1508 | * this is the best method i figured out. | ||
1509 | * Any others?*/ | ||
1510 | if(dec->interface == TTUSB_DEC_INTERFACE_IN) | ||
1511 | usb_kill_urb(dec->irq_urb); | ||
1512 | |||
1513 | usb_free_urb(dec->irq_urb); | ||
1514 | |||
1515 | usb_buffer_free(dec->udev,IRQ_PACKET_SIZE, | ||
1516 | dec->irq_buffer, dec->irq_dma_handle); | ||
1517 | |||
1518 | input_unregister_device(&dec->rc_input_dev); | ||
1519 | } | ||
1520 | |||
1521 | |||
1522 | static void ttusb_dec_exit_usb(struct ttusb_dec *dec) | ||
1523 | { | ||
1524 | int i; | ||
1525 | |||
1526 | dprintk("%s\n", __FUNCTION__); | ||
1527 | |||
1528 | dec->iso_stream_count = 0; | ||
1529 | |||
1530 | for (i = 0; i < ISO_BUF_COUNT; i++) | ||
1531 | usb_kill_urb(dec->iso_urb[i]); | ||
1532 | |||
1533 | ttusb_dec_free_iso_urbs(dec); | ||
1534 | } | ||
1535 | |||
1536 | static void ttusb_dec_exit_tasklet(struct ttusb_dec *dec) | ||
1537 | { | ||
1538 | struct list_head *item; | ||
1539 | struct urb_frame *frame; | ||
1540 | |||
1541 | tasklet_kill(&dec->urb_tasklet); | ||
1542 | |||
1543 | while ((item = dec->urb_frame_list.next) != &dec->urb_frame_list) { | ||
1544 | frame = list_entry(item, struct urb_frame, urb_frame_list); | ||
1545 | list_del(&frame->urb_frame_list); | ||
1546 | kfree(frame); | ||
1547 | } | ||
1548 | } | ||
1549 | |||
1550 | static void ttusb_dec_init_filters(struct ttusb_dec *dec) | ||
1551 | { | ||
1552 | INIT_LIST_HEAD(&dec->filter_info_list); | ||
1553 | spin_lock_init(&dec->filter_info_list_lock); | ||
1554 | } | ||
1555 | |||
1556 | static void ttusb_dec_exit_filters(struct ttusb_dec *dec) | ||
1557 | { | ||
1558 | struct list_head *item; | ||
1559 | struct filter_info *finfo; | ||
1560 | |||
1561 | while ((item = dec->filter_info_list.next) != &dec->filter_info_list) { | ||
1562 | finfo = list_entry(item, struct filter_info, filter_info_list); | ||
1563 | list_del(&finfo->filter_info_list); | ||
1564 | kfree(finfo); | ||
1565 | } | ||
1566 | } | ||
1567 | |||
1568 | int fe_send_command(struct dvb_frontend* fe, const u8 command, | ||
1569 | int param_length, const u8 params[], | ||
1570 | int *result_length, u8 cmd_result[]) | ||
1571 | { | ||
1572 | struct ttusb_dec* dec = (struct ttusb_dec*) fe->dvb->priv; | ||
1573 | return ttusb_dec_send_command(dec, command, param_length, params, result_length, cmd_result); | ||
1574 | } | ||
1575 | |||
1576 | struct ttusbdecfe_config fe_config = { | ||
1577 | .send_command = fe_send_command | ||
1578 | }; | ||
1579 | |||
1580 | static int ttusb_dec_probe(struct usb_interface *intf, | ||
1581 | const struct usb_device_id *id) | ||
1582 | { | ||
1583 | struct usb_device *udev; | ||
1584 | struct ttusb_dec *dec; | ||
1585 | |||
1586 | dprintk("%s\n", __FUNCTION__); | ||
1587 | |||
1588 | udev = interface_to_usbdev(intf); | ||
1589 | |||
1590 | if (!(dec = kmalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) { | ||
1591 | printk("%s: couldn't allocate memory.\n", __FUNCTION__); | ||
1592 | return -ENOMEM; | ||
1593 | } | ||
1594 | |||
1595 | usb_set_intfdata(intf, (void *)dec); | ||
1596 | |||
1597 | memset(dec, 0, sizeof(struct ttusb_dec)); | ||
1598 | |||
1599 | switch (le16_to_cpu(id->idProduct)) { | ||
1600 | case 0x1006: | ||
1601 | ttusb_dec_set_model(dec, TTUSB_DEC3000S); | ||
1602 | break; | ||
1603 | |||
1604 | case 0x1008: | ||
1605 | ttusb_dec_set_model(dec, TTUSB_DEC2000T); | ||
1606 | break; | ||
1607 | |||
1608 | case 0x1009: | ||
1609 | ttusb_dec_set_model(dec, TTUSB_DEC2540T); | ||
1610 | break; | ||
1611 | } | ||
1612 | |||
1613 | dec->udev = udev; | ||
1614 | |||
1615 | if (ttusb_dec_init_usb(dec)) | ||
1616 | return 0; | ||
1617 | if (ttusb_dec_init_stb(dec)) { | ||
1618 | ttusb_dec_exit_usb(dec); | ||
1619 | return 0; | ||
1620 | } | ||
1621 | ttusb_dec_init_dvb(dec); | ||
1622 | |||
1623 | dec->adapter->priv = dec; | ||
1624 | switch (le16_to_cpu(id->idProduct)) { | ||
1625 | case 0x1006: | ||
1626 | dec->fe = ttusbdecfe_dvbs_attach(&fe_config); | ||
1627 | break; | ||
1628 | |||
1629 | case 0x1008: | ||
1630 | case 0x1009: | ||
1631 | dec->fe = ttusbdecfe_dvbt_attach(&fe_config); | ||
1632 | break; | ||
1633 | } | ||
1634 | |||
1635 | if (dec->fe == NULL) { | ||
1636 | printk("dvb-ttusb-dec: A frontend driver was not found for device %04x/%04x\n", | ||
1637 | le16_to_cpu(dec->udev->descriptor.idVendor), | ||
1638 | le16_to_cpu(dec->udev->descriptor.idProduct)); | ||
1639 | } else { | ||
1640 | if (dvb_register_frontend(dec->adapter, dec->fe)) { | ||
1641 | printk("budget-ci: Frontend registration failed!\n"); | ||
1642 | if (dec->fe->ops->release) | ||
1643 | dec->fe->ops->release(dec->fe); | ||
1644 | dec->fe = NULL; | ||
1645 | } | ||
1646 | } | ||
1647 | |||
1648 | ttusb_dec_init_v_pes(dec); | ||
1649 | ttusb_dec_init_filters(dec); | ||
1650 | ttusb_dec_init_tasklet(dec); | ||
1651 | |||
1652 | dec->active = 1; | ||
1653 | |||
1654 | ttusb_dec_set_interface(dec, TTUSB_DEC_INTERFACE_IN); | ||
1655 | |||
1656 | if(enable_rc) | ||
1657 | ttusb_init_rc(dec); | ||
1658 | |||
1659 | return 0; | ||
1660 | } | ||
1661 | |||
1662 | static void ttusb_dec_disconnect(struct usb_interface *intf) | ||
1663 | { | ||
1664 | struct ttusb_dec *dec = usb_get_intfdata(intf); | ||
1665 | |||
1666 | usb_set_intfdata(intf, NULL); | ||
1667 | |||
1668 | dprintk("%s\n", __FUNCTION__); | ||
1669 | |||
1670 | if (dec->active) { | ||
1671 | ttusb_dec_exit_tasklet(dec); | ||
1672 | ttusb_dec_exit_filters(dec); | ||
1673 | if(enable_rc) | ||
1674 | ttusb_dec_exit_rc(dec); | ||
1675 | ttusb_dec_exit_usb(dec); | ||
1676 | ttusb_dec_exit_dvb(dec); | ||
1677 | } | ||
1678 | |||
1679 | kfree(dec); | ||
1680 | } | ||
1681 | |||
1682 | static void ttusb_dec_set_model(struct ttusb_dec *dec, | ||
1683 | enum ttusb_dec_model model) | ||
1684 | { | ||
1685 | dec->model = model; | ||
1686 | |||
1687 | switch (model) { | ||
1688 | case TTUSB_DEC2000T: | ||
1689 | dec->model_name = "DEC2000-t"; | ||
1690 | dec->firmware_name = "dvb-ttusb-dec-2000t.fw"; | ||
1691 | break; | ||
1692 | |||
1693 | case TTUSB_DEC2540T: | ||
1694 | dec->model_name = "DEC2540-t"; | ||
1695 | dec->firmware_name = "dvb-ttusb-dec-2540t.fw"; | ||
1696 | break; | ||
1697 | |||
1698 | case TTUSB_DEC3000S: | ||
1699 | dec->model_name = "DEC3000-s"; | ||
1700 | dec->firmware_name = "dvb-ttusb-dec-3000s.fw"; | ||
1701 | break; | ||
1702 | } | ||
1703 | } | ||
1704 | |||
1705 | static struct usb_device_id ttusb_dec_table[] = { | ||
1706 | {USB_DEVICE(0x0b48, 0x1006)}, /* DEC3000-s */ | ||
1707 | /*{USB_DEVICE(0x0b48, 0x1007)}, Unconfirmed */ | ||
1708 | {USB_DEVICE(0x0b48, 0x1008)}, /* DEC2000-t */ | ||
1709 | {USB_DEVICE(0x0b48, 0x1009)}, /* DEC2540-t */ | ||
1710 | {} | ||
1711 | }; | ||
1712 | |||
1713 | static struct usb_driver ttusb_dec_driver = { | ||
1714 | .name = "ttusb-dec", | ||
1715 | .probe = ttusb_dec_probe, | ||
1716 | .disconnect = ttusb_dec_disconnect, | ||
1717 | .id_table = ttusb_dec_table, | ||
1718 | }; | ||
1719 | |||
1720 | static int __init ttusb_dec_init(void) | ||
1721 | { | ||
1722 | int result; | ||
1723 | |||
1724 | if ((result = usb_register(&ttusb_dec_driver)) < 0) { | ||
1725 | printk("%s: initialisation failed: error %d.\n", __FUNCTION__, | ||
1726 | result); | ||
1727 | return result; | ||
1728 | } | ||
1729 | |||
1730 | return 0; | ||
1731 | } | ||
1732 | |||
1733 | static void __exit ttusb_dec_exit(void) | ||
1734 | { | ||
1735 | usb_deregister(&ttusb_dec_driver); | ||
1736 | } | ||
1737 | |||
1738 | module_init(ttusb_dec_init); | ||
1739 | module_exit(ttusb_dec_exit); | ||
1740 | |||
1741 | MODULE_AUTHOR("Alex Woods <linux-dvb@giblets.org>"); | ||
1742 | MODULE_DESCRIPTION(DRIVER_NAME); | ||
1743 | MODULE_LICENSE("GPL"); | ||
1744 | MODULE_DEVICE_TABLE(usb, ttusb_dec_table); | ||
diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c new file mode 100644 index 000000000000..1699cc9f6bb0 --- /dev/null +++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c | |||
@@ -0,0 +1,255 @@ | |||
1 | /* | ||
2 | * TTUSB DEC Frontend Driver | ||
3 | * | ||
4 | * Copyright (C) 2003-2004 Alex Woods <linux-dvb@giblets.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include "dvb_frontend.h" | ||
23 | #include "ttusbdecfe.h" | ||
24 | |||
25 | |||
26 | #define LOF_HI 10600000 | ||
27 | #define LOF_LO 9750000 | ||
28 | |||
29 | struct ttusbdecfe_state { | ||
30 | |||
31 | struct dvb_frontend_ops ops; | ||
32 | |||
33 | /* configuration settings */ | ||
34 | const struct ttusbdecfe_config* config; | ||
35 | |||
36 | struct dvb_frontend frontend; | ||
37 | |||
38 | u8 hi_band; | ||
39 | u8 voltage; | ||
40 | }; | ||
41 | |||
42 | |||
43 | static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status) | ||
44 | { | ||
45 | *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | | ||
46 | FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK; | ||
47 | |||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) | ||
52 | { | ||
53 | struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv; | ||
54 | u8 b[] = { 0x00, 0x00, 0x00, 0x03, | ||
55 | 0x00, 0x00, 0x00, 0x00, | ||
56 | 0x00, 0x00, 0x00, 0x01, | ||
57 | 0x00, 0x00, 0x00, 0xff, | ||
58 | 0x00, 0x00, 0x00, 0xff }; | ||
59 | |||
60 | u32 freq = htonl(p->frequency / 1000); | ||
61 | memcpy(&b[4], &freq, sizeof (u32)); | ||
62 | state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL); | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) | ||
68 | { | ||
69 | struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv; | ||
70 | |||
71 | u8 b[] = { 0x00, 0x00, 0x00, 0x01, | ||
72 | 0x00, 0x00, 0x00, 0x00, | ||
73 | 0x00, 0x00, 0x00, 0x01, | ||
74 | 0x00, 0x00, 0x00, 0x00, | ||
75 | 0x00, 0x00, 0x00, 0x00, | ||
76 | 0x00, 0x00, 0x00, 0x00, | ||
77 | 0x00, 0x00, 0x00, 0x00, | ||
78 | 0x00, 0x00, 0x00, 0x00, | ||
79 | 0x00, 0x00, 0x00, 0x00, | ||
80 | 0x00, 0x00, 0x00, 0x00 }; | ||
81 | u32 freq; | ||
82 | u32 sym_rate; | ||
83 | u32 band; | ||
84 | u32 lnb_voltage; | ||
85 | |||
86 | freq = htonl(p->frequency + | ||
87 | (state->hi_band ? LOF_HI : LOF_LO)); | ||
88 | memcpy(&b[4], &freq, sizeof(u32)); | ||
89 | sym_rate = htonl(p->u.qam.symbol_rate); | ||
90 | memcpy(&b[12], &sym_rate, sizeof(u32)); | ||
91 | band = htonl(state->hi_band ? LOF_HI : LOF_LO); | ||
92 | memcpy(&b[24], &band, sizeof(u32)); | ||
93 | lnb_voltage = htonl(state->voltage); | ||
94 | memcpy(&b[28], &lnb_voltage, sizeof(u32)); | ||
95 | |||
96 | state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL); | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static int ttusbdecfe_dvbs_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd) | ||
102 | { | ||
103 | struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv; | ||
104 | u8 b[] = { 0x00, 0xff, 0x00, 0x00, | ||
105 | 0x00, 0x00, 0x00, 0x00, | ||
106 | 0x00, 0x00 }; | ||
107 | |||
108 | memcpy(&b[4], cmd->msg, cmd->msg_len); | ||
109 | |||
110 | state->config->send_command(fe, 0x72, | ||
111 | sizeof(b) - (6 - cmd->msg_len), b, | ||
112 | NULL, NULL); | ||
113 | |||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | |||
118 | static int ttusbdecfe_dvbs_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) | ||
119 | { | ||
120 | struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv; | ||
121 | |||
122 | state->hi_band = (SEC_TONE_ON == tone); | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | |||
128 | static int ttusbdecfe_dvbs_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage) | ||
129 | { | ||
130 | struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv; | ||
131 | |||
132 | switch (voltage) { | ||
133 | case SEC_VOLTAGE_13: | ||
134 | state->voltage = 13; | ||
135 | break; | ||
136 | case SEC_VOLTAGE_18: | ||
137 | state->voltage = 18; | ||
138 | break; | ||
139 | default: | ||
140 | return -EINVAL; | ||
141 | } | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | static void ttusbdecfe_release(struct dvb_frontend* fe) | ||
147 | { | ||
148 | struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv; | ||
149 | kfree(state); | ||
150 | } | ||
151 | |||
152 | static struct dvb_frontend_ops ttusbdecfe_dvbt_ops; | ||
153 | |||
154 | struct dvb_frontend* ttusbdecfe_dvbt_attach(const struct ttusbdecfe_config* config) | ||
155 | { | ||
156 | struct ttusbdecfe_state* state = NULL; | ||
157 | |||
158 | /* allocate memory for the internal state */ | ||
159 | state = (struct ttusbdecfe_state*) kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL); | ||
160 | if (state == NULL) goto error; | ||
161 | |||
162 | /* setup the state */ | ||
163 | state->config = config; | ||
164 | memcpy(&state->ops, &ttusbdecfe_dvbt_ops, sizeof(struct dvb_frontend_ops)); | ||
165 | |||
166 | /* create dvb_frontend */ | ||
167 | state->frontend.ops = &state->ops; | ||
168 | state->frontend.demodulator_priv = state; | ||
169 | return &state->frontend; | ||
170 | |||
171 | error: | ||
172 | kfree(state); | ||
173 | return NULL; | ||
174 | } | ||
175 | |||
176 | static struct dvb_frontend_ops ttusbdecfe_dvbs_ops; | ||
177 | |||
178 | struct dvb_frontend* ttusbdecfe_dvbs_attach(const struct ttusbdecfe_config* config) | ||
179 | { | ||
180 | struct ttusbdecfe_state* state = NULL; | ||
181 | |||
182 | /* allocate memory for the internal state */ | ||
183 | state = (struct ttusbdecfe_state*) kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL); | ||
184 | if (state == NULL) goto error; | ||
185 | |||
186 | /* setup the state */ | ||
187 | state->config = config; | ||
188 | state->voltage = 0; | ||
189 | state->hi_band = 0; | ||
190 | memcpy(&state->ops, &ttusbdecfe_dvbs_ops, sizeof(struct dvb_frontend_ops)); | ||
191 | |||
192 | /* create dvb_frontend */ | ||
193 | state->frontend.ops = &state->ops; | ||
194 | state->frontend.demodulator_priv = state; | ||
195 | return &state->frontend; | ||
196 | |||
197 | error: | ||
198 | kfree(state); | ||
199 | return NULL; | ||
200 | } | ||
201 | |||
202 | static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = { | ||
203 | |||
204 | .info = { | ||
205 | .name = "TechnoTrend/Hauppauge DEC2000-t Frontend", | ||
206 | .type = FE_OFDM, | ||
207 | .frequency_min = 51000000, | ||
208 | .frequency_max = 858000000, | ||
209 | .frequency_stepsize = 62500, | ||
210 | .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
211 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
212 | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | | ||
213 | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | | ||
214 | FE_CAN_HIERARCHY_AUTO, | ||
215 | }, | ||
216 | |||
217 | .release = ttusbdecfe_release, | ||
218 | |||
219 | .set_frontend = ttusbdecfe_dvbt_set_frontend, | ||
220 | |||
221 | .read_status = ttusbdecfe_read_status, | ||
222 | }; | ||
223 | |||
224 | static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = { | ||
225 | |||
226 | .info = { | ||
227 | .name = "TechnoTrend/Hauppauge DEC3000-s Frontend", | ||
228 | .type = FE_QPSK, | ||
229 | .frequency_min = 950000, | ||
230 | .frequency_max = 2150000, | ||
231 | .frequency_stepsize = 125, | ||
232 | .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
233 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
234 | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | | ||
235 | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | | ||
236 | FE_CAN_HIERARCHY_AUTO, | ||
237 | }, | ||
238 | |||
239 | .release = ttusbdecfe_release, | ||
240 | |||
241 | .set_frontend = ttusbdecfe_dvbs_set_frontend, | ||
242 | |||
243 | .read_status = ttusbdecfe_read_status, | ||
244 | |||
245 | .diseqc_send_master_cmd = ttusbdecfe_dvbs_diseqc_send_master_cmd, | ||
246 | .set_voltage = ttusbdecfe_dvbs_set_voltage, | ||
247 | .set_tone = ttusbdecfe_dvbs_set_tone, | ||
248 | }; | ||
249 | |||
250 | MODULE_DESCRIPTION("TTUSB DEC DVB-T/S Demodulator driver"); | ||
251 | MODULE_AUTHOR("Alex Woods/Andrew de Quincey"); | ||
252 | MODULE_LICENSE("GPL"); | ||
253 | |||
254 | EXPORT_SYMBOL(ttusbdecfe_dvbt_attach); | ||
255 | EXPORT_SYMBOL(ttusbdecfe_dvbs_attach); | ||
diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.h b/drivers/media/dvb/ttusb-dec/ttusbdecfe.h new file mode 100644 index 000000000000..15ccc3d1a20e --- /dev/null +++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * TTUSB DEC Driver | ||
3 | * | ||
4 | * Copyright (C) 2003-2004 Alex Woods <linux-dvb@giblets.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef TTUSBDECFE_H | ||
23 | #define TTUSBDECFE_H | ||
24 | |||
25 | #include <linux/dvb/frontend.h> | ||
26 | |||
27 | struct ttusbdecfe_config | ||
28 | { | ||
29 | int (*send_command)(struct dvb_frontend* fe, const u8 command, | ||
30 | int param_length, const u8 params[], | ||
31 | int *result_length, u8 cmd_result[]); | ||
32 | }; | ||
33 | |||
34 | extern struct dvb_frontend* ttusbdecfe_dvbs_attach(const struct ttusbdecfe_config* config); | ||
35 | |||
36 | extern struct dvb_frontend* ttusbdecfe_dvbt_attach(const struct ttusbdecfe_config* config); | ||
37 | |||
38 | #endif // TTUSBDECFE_H | ||