Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ttusb2.c
Go to the documentation of this file.
1 /* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones
2  * (e.g. Pinnacle 400e DVB-S USB2.0).
3  *
4  * The Pinnacle 400e uses the same protocol as the Technotrend USB1.1 boxes.
5  *
6  * TDA8263 + TDA10086
7  *
8  * I2C addresses:
9  * 0x08 - LNBP21PD - LNB power supply
10  * 0x0e - TDA10086 - Demodulator
11  * 0x50 - FX2 eeprom
12  * 0x60 - TDA8263 - Tuner
13  * 0x78 ???
14  *
15  * Copyright (c) 2002 Holger Waechtler <[email protected]>
16  * Copyright (c) 2003 Felix Domke <[email protected]>
17  * Copyright (C) 2005-6 Patrick Boettcher <[email protected]>
18  *
19  * This program is free software; you can redistribute it and/or modify it
20  * under the terms of the GNU General Public License as published by the Free
21  * Software Foundation, version 2.
22  *
23  * see Documentation/dvb/README.dvb-usb for more information
24  */
25 #define DVB_USB_LOG_PREFIX "ttusb2"
26 #include "dvb-usb.h"
27 
28 #include "ttusb2.h"
29 
30 #include "tda826x.h"
31 #include "tda10086.h"
32 #include "tda1002x.h"
33 #include "tda10048.h"
34 #include "tda827x.h"
35 #include "lnbp21.h"
36 /* CA */
37 #include "dvb_ca_en50221.h"
38 
39 /* debug */
40 static int dvb_usb_ttusb2_debug;
41 #define deb_info(args...) dprintk(dvb_usb_ttusb2_debug,0x01,args)
42 module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644);
43 MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS);
44 static int dvb_usb_ttusb2_debug_ci;
45 module_param_named(debug_ci,dvb_usb_ttusb2_debug_ci, int, 0644);
46 MODULE_PARM_DESC(debug_ci, "set debugging ci." DVB_USB_DEBUG_STATUS);
47 
49 
50 #define ci_dbg(format, arg...) \
51 do { \
52  if (dvb_usb_ttusb2_debug_ci) \
53  printk(KERN_DEBUG DVB_USB_LOG_PREFIX \
54  ": %s " format "\n" , __func__, ## arg); \
55 } while (0)
56 
57 enum {
65 };
66 
67 struct ttusb2_state {
69  struct mutex ca_mutex;
70  u8 id;
72 };
73 
74 static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd,
75  u8 *wbuf, int wlen, u8 *rbuf, int rlen)
76 {
77  struct ttusb2_state *st = d->priv;
78  u8 *s, *r = NULL;
79  int ret = 0;
80 
81  s = kzalloc(wlen+4, GFP_KERNEL);
82  if (!s)
83  return -ENOMEM;
84 
85  r = kzalloc(64, GFP_KERNEL);
86  if (!r) {
87  kfree(s);
88  return -ENOMEM;
89  }
90 
91  s[0] = 0xaa;
92  s[1] = ++st->id;
93  s[2] = cmd;
94  s[3] = wlen;
95  memcpy(&s[4],wbuf,wlen);
96 
97  ret = dvb_usb_generic_rw(d, s, wlen+4, r, 64, 0);
98 
99  if (ret != 0 ||
100  r[0] != 0x55 ||
101  r[1] != s[1] ||
102  r[2] != cmd ||
103  (rlen > 0 && r[3] != rlen)) {
104  warn("there might have been an error during control message transfer. (rlen = %d, was %d)",rlen,r[3]);
105  kfree(s);
106  kfree(r);
107  return -EIO;
108  }
109 
110  if (rlen > 0)
111  memcpy(rbuf, &r[4], rlen);
112 
113  kfree(s);
114  kfree(r);
115 
116  return 0;
117 }
118 
119 /* ci */
120 static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len)
121 {
122  int ret;
123  u8 rx[60];/* (64 -4) */
124  ret = ttusb2_msg(d, cmd, data, write_len, rx, read_len);
125  if (!ret)
126  memcpy(data, rx, read_len);
127  return ret;
128 }
129 
130 static int tt3650_ci_msg_locked(struct dvb_ca_en50221 *ca, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len)
131 {
132  struct dvb_usb_device *d = ca->data;
133  struct ttusb2_state *state = d->priv;
134  int ret;
135 
136  mutex_lock(&state->ca_mutex);
137  ret = tt3650_ci_msg(d, cmd, data, write_len, read_len);
138  mutex_unlock(&state->ca_mutex);
139 
140  return ret;
141 }
142 
143 static int tt3650_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
144 {
145  u8 buf[3];
146  int ret = 0;
147 
148  if (slot)
149  return -EINVAL;
150 
151  buf[0] = (address >> 8) & 0x0F;
152  buf[1] = address;
153 
154 
155  ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_ATTR, buf, 2, 3);
156 
157  ci_dbg("%04x -> %d 0x%02x", address, ret, buf[2]);
158 
159  if (ret < 0)
160  return ret;
161 
162  return buf[2];
163 }
164 
165 static int tt3650_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
166 {
167  u8 buf[3];
168 
169  ci_dbg("%d 0x%04x 0x%02x", slot, address, value);
170 
171  if (slot)
172  return -EINVAL;
173 
174  buf[0] = (address >> 8) & 0x0F;
175  buf[1] = address;
176  buf[2] = value;
177 
178  return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_ATTR, buf, 3, 3);
179 }
180 
181 static int tt3650_ci_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
182 {
183  u8 buf[2];
184  int ret;
185 
186  if (slot)
187  return -EINVAL;
188 
189  buf[0] = address & 3;
190 
191  ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_CTRL, buf, 1, 2);
192 
193  ci_dbg("0x%02x -> %d 0x%02x", address, ret, buf[1]);
194 
195  if (ret < 0)
196  return ret;
197 
198  return buf[1];
199 }
200 
201 static int tt3650_ci_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
202 {
203  u8 buf[2];
204 
205  ci_dbg("%d 0x%02x 0x%02x", slot, address, value);
206 
207  if (slot)
208  return -EINVAL;
209 
210  buf[0] = address;
211  buf[1] = value;
212 
213  return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_CTRL, buf, 2, 2);
214 }
215 
216 static int tt3650_ci_set_video_port(struct dvb_ca_en50221 *ca, int slot, int enable)
217 {
218  u8 buf[1];
219  int ret;
220 
221  ci_dbg("%d %d", slot, enable);
222 
223  if (slot)
224  return -EINVAL;
225 
226  buf[0] = enable;
227 
228  ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
229  if (ret < 0)
230  return ret;
231 
232  if (enable != buf[0]) {
233  err("CI not %sabled.", enable ? "en" : "dis");
234  return -EIO;
235  }
236 
237  return 0;
238 }
239 
240 static int tt3650_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
241 {
242  return tt3650_ci_set_video_port(ca, slot, 0);
243 }
244 
245 static int tt3650_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
246 {
247  return tt3650_ci_set_video_port(ca, slot, 1);
248 }
249 
250 static int tt3650_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
251 {
252  struct dvb_usb_device *d = ca->data;
253  struct ttusb2_state *state = d->priv;
254  u8 buf[1];
255  int ret;
256 
257  ci_dbg("%d", slot);
258 
259  if (slot)
260  return -EINVAL;
261 
262  buf[0] = 0;
263 
264  mutex_lock(&state->ca_mutex);
265 
266  ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
267  if (ret)
268  goto failed;
269 
270  msleep(500);
271 
272  buf[0] = 1;
273 
274  ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
275  if (ret)
276  goto failed;
277 
278  msleep(500);
279 
280  buf[0] = 0; /* FTA */
281 
282  ret = tt3650_ci_msg(d, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
283 
284  msleep(1100);
285 
286  failed:
287  mutex_unlock(&state->ca_mutex);
288 
289  return ret;
290 }
291 
292 static int tt3650_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
293 {
294  u8 buf[1];
295  int ret;
296 
297  if (slot)
298  return -EINVAL;
299 
300  ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_TEST, buf, 0, 1);
301  if (ret)
302  return ret;
303 
304  if (1 == buf[0]) {
307  }
308  return 0;
309 }
310 
311 static void tt3650_ci_uninit(struct dvb_usb_device *d)
312 {
313  struct ttusb2_state *state;
314 
315  ci_dbg("");
316 
317  if (NULL == d)
318  return;
319 
320  state = d->priv;
321  if (NULL == state)
322  return;
323 
324  if (NULL == state->ca.data)
325  return;
326 
327  dvb_ca_en50221_release(&state->ca);
328 
329  memset(&state->ca, 0, sizeof(state->ca));
330 }
331 
332 static int tt3650_ci_init(struct dvb_usb_adapter *a)
333 {
334  struct dvb_usb_device *d = a->dev;
335  struct ttusb2_state *state = d->priv;
336  int ret;
337 
338  ci_dbg("");
339 
340  mutex_init(&state->ca_mutex);
341 
342  state->ca.owner = THIS_MODULE;
343  state->ca.read_attribute_mem = tt3650_ci_read_attribute_mem;
344  state->ca.write_attribute_mem = tt3650_ci_write_attribute_mem;
345  state->ca.read_cam_control = tt3650_ci_read_cam_control;
346  state->ca.write_cam_control = tt3650_ci_write_cam_control;
347  state->ca.slot_reset = tt3650_ci_slot_reset;
348  state->ca.slot_shutdown = tt3650_ci_slot_shutdown;
349  state->ca.slot_ts_enable = tt3650_ci_slot_ts_enable;
350  state->ca.poll_slot_status = tt3650_ci_poll_slot_status;
351  state->ca.data = d;
352 
353  ret = dvb_ca_en50221_init(&a->dvb_adap,
354  &state->ca,
355  /* flags */ 0,
356  /* n_slots */ 1);
357  if (ret) {
358  err("Cannot initialize CI: Error %d.", ret);
359  memset(&state->ca, 0, sizeof(state->ca));
360  return ret;
361  }
362 
363  info("CI initialized.");
364 
365  return 0;
366 }
367 
368 static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
369 {
370  struct dvb_usb_device *d = i2c_get_adapdata(adap);
371  static u8 obuf[60], ibuf[60];
372  int i, write_read, read;
373 
374  if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
375  return -EAGAIN;
376 
377  if (num > 2)
378  warn("more than 2 i2c messages at a time is not handled yet. TODO.");
379 
380  for (i = 0; i < num; i++) {
381  write_read = i+1 < num && (msg[i+1].flags & I2C_M_RD);
382  read = msg[i].flags & I2C_M_RD;
383 
384  obuf[0] = (msg[i].addr << 1) | (write_read | read);
385  if (read)
386  obuf[1] = 0;
387  else
388  obuf[1] = msg[i].len;
389 
390  /* read request */
391  if (write_read)
392  obuf[2] = msg[i+1].len;
393  else if (read)
394  obuf[2] = msg[i].len;
395  else
396  obuf[2] = 0;
397 
398  memcpy(&obuf[3], msg[i].buf, msg[i].len);
399 
400  if (ttusb2_msg(d, CMD_I2C_XFER, obuf, obuf[1]+3, ibuf, obuf[2] + 3) < 0) {
401  err("i2c transfer failed.");
402  break;
403  }
404 
405  if (write_read) {
406  memcpy(msg[i+1].buf, &ibuf[3], msg[i+1].len);
407  i++;
408  } else if (read)
409  memcpy(msg[i].buf, &ibuf[3], msg[i].len);
410  }
411 
412  mutex_unlock(&d->i2c_mutex);
413  return i;
414 }
415 
416 static u32 ttusb2_i2c_func(struct i2c_adapter *adapter)
417 {
418  return I2C_FUNC_I2C;
419 }
420 
421 static struct i2c_algorithm ttusb2_i2c_algo = {
422  .master_xfer = ttusb2_i2c_xfer,
423  .functionality = ttusb2_i2c_func,
424 };
425 
426 /* command to poll IR receiver (copied from pctv452e.c) */
427 #define CMD_GET_IR_CODE 0x1b
428 
429 /* IR */
430 static int tt3650_rc_query(struct dvb_usb_device *d)
431 {
432  int ret;
433  u8 rx[9]; /* A CMD_GET_IR_CODE reply is 9 bytes long */
434  struct ttusb2_state *st = d->priv;
435  ret = ttusb2_msg(d, CMD_GET_IR_CODE, NULL, 0, rx, sizeof(rx));
436  if (ret != 0)
437  return ret;
438 
439  if (rx[8] & 0x01) {
440  /* got a "press" event */
441  st->last_rc_key = (rx[3] << 8) | rx[2];
442  deb_info("%s: cmd=0x%02x sys=0x%02x\n", __func__, rx[2], rx[3]);
443  rc_keydown(d->rc_dev, st->last_rc_key, rx[1]);
444  } else if (st->last_rc_key) {
445  rc_keyup(d->rc_dev);
446  st->last_rc_key = 0;
447  }
448 
449  return 0;
450 }
451 
452 
453 /* Callbacks for DVB USB */
454 static int ttusb2_identify_state (struct usb_device *udev, struct
456  int *cold)
457 {
458  *cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0;
459  return 0;
460 }
461 
462 static int ttusb2_power_ctrl(struct dvb_usb_device *d, int onoff)
463 {
464  u8 b = onoff;
465  ttusb2_msg(d, CMD_POWER, &b, 0, NULL, 0);
466  return ttusb2_msg(d, CMD_POWER, &b, 1, NULL, 0);
467 }
468 
469 
470 static struct tda10086_config tda10086_config = {
471  .demod_address = 0x0e,
472  .invert = 0,
473  .diseqc_tone = 1,
474  .xtal_freq = TDA10086_XTAL_16M,
475 };
476 
477 static struct tda10023_config tda10023_config = {
478  .demod_address = 0x0c,
479  .invert = 0,
480  .xtal = 16000000,
481  .pll_m = 11,
482  .pll_p = 3,
483  .pll_n = 1,
484  .deltaf = 0xa511,
485 };
486 
487 static struct tda10048_config tda10048_config = {
488  .demod_address = 0x10 >> 1,
489  .output_mode = TDA10048_PARALLEL_OUTPUT,
490  .inversion = TDA10048_INVERSION_ON,
491  .dtv6_if_freq_khz = TDA10048_IF_4000,
492  .dtv7_if_freq_khz = TDA10048_IF_4500,
493  .dtv8_if_freq_khz = TDA10048_IF_5000,
494  .clk_freq_khz = TDA10048_CLK_16000,
495  .no_firmware = 1,
496  .set_pll = true ,
497  .pll_m = 5,
498  .pll_n = 3,
499  .pll_p = 0,
500 };
501 
502 static struct tda827x_config tda827x_config = {
503  .config = 0,
504 };
505 
506 static int ttusb2_frontend_tda10086_attach(struct dvb_usb_adapter *adap)
507 {
508  if (usb_set_interface(adap->dev->udev,0,3) < 0)
509  err("set interface to alts=3 failed");
510 
511  if ((adap->fe_adap[0].fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) {
512  deb_info("TDA10086 attach failed\n");
513  return -ENODEV;
514  }
515 
516  return 0;
517 }
518 
519 static int ttusb2_ct3650_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
520 {
521  struct dvb_usb_adapter *adap = fe->dvb->priv;
522 
523  return adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, enable);
524 }
525 
526 static int ttusb2_frontend_tda10023_attach(struct dvb_usb_adapter *adap)
527 {
528  if (usb_set_interface(adap->dev->udev, 0, 3) < 0)
529  err("set interface to alts=3 failed");
530 
531  if (adap->fe_adap[0].fe == NULL) {
532  /* FE 0 DVB-C */
533  adap->fe_adap[0].fe = dvb_attach(tda10023_attach,
534  &tda10023_config, &adap->dev->i2c_adap, 0x48);
535 
536  if (adap->fe_adap[0].fe == NULL) {
537  deb_info("TDA10023 attach failed\n");
538  return -ENODEV;
539  }
540  tt3650_ci_init(adap);
541  } else {
542  adap->fe_adap[1].fe = dvb_attach(tda10048_attach,
543  &tda10048_config, &adap->dev->i2c_adap);
544 
545  if (adap->fe_adap[1].fe == NULL) {
546  deb_info("TDA10048 attach failed\n");
547  return -ENODEV;
548  }
549 
550  /* tuner is behind TDA10023 I2C-gate */
551  adap->fe_adap[1].fe->ops.i2c_gate_ctrl = ttusb2_ct3650_i2c_gate_ctrl;
552 
553  }
554 
555  return 0;
556 }
557 
558 static int ttusb2_tuner_tda827x_attach(struct dvb_usb_adapter *adap)
559 {
560  struct dvb_frontend *fe;
561 
562  /* MFE: select correct FE to attach tuner since that's called twice */
563  if (adap->fe_adap[1].fe == NULL)
564  fe = adap->fe_adap[0].fe;
565  else
566  fe = adap->fe_adap[1].fe;
567 
568  /* attach tuner */
569  if (dvb_attach(tda827x_attach, fe, 0x61, &adap->dev->i2c_adap, &tda827x_config) == NULL) {
570  printk(KERN_ERR "%s: No tda827x found!\n", __func__);
571  return -ENODEV;
572  }
573  return 0;
574 }
575 
576 static int ttusb2_tuner_tda826x_attach(struct dvb_usb_adapter *adap)
577 {
578  if (dvb_attach(tda826x_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) {
579  deb_info("TDA8263 attach failed\n");
580  return -ENODEV;
581  }
582 
583  if (dvb_attach(lnbp21_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap, 0, 0) == NULL) {
584  deb_info("LNBP21 attach failed\n");
585  return -ENODEV;
586  }
587  return 0;
588 }
589 
590 /* DVB USB Driver stuff */
591 static struct dvb_usb_device_properties ttusb2_properties;
592 static struct dvb_usb_device_properties ttusb2_properties_s2400;
593 static struct dvb_usb_device_properties ttusb2_properties_ct3650;
594 
595 static void ttusb2_usb_disconnect(struct usb_interface *intf)
596 {
597  struct dvb_usb_device *d = usb_get_intfdata(intf);
598 
599  tt3650_ci_uninit(d);
600  dvb_usb_device_exit(intf);
601 }
602 
603 static int ttusb2_probe(struct usb_interface *intf,
604  const struct usb_device_id *id)
605 {
606  if (0 == dvb_usb_device_init(intf, &ttusb2_properties,
607  THIS_MODULE, NULL, adapter_nr) ||
608  0 == dvb_usb_device_init(intf, &ttusb2_properties_s2400,
609  THIS_MODULE, NULL, adapter_nr) ||
610  0 == dvb_usb_device_init(intf, &ttusb2_properties_ct3650,
611  THIS_MODULE, NULL, adapter_nr))
612  return 0;
613  return -ENODEV;
614 }
615 
616 static struct usb_device_id ttusb2_table [] = {
617  { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) },
618  { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_450E) },
619  { USB_DEVICE(USB_VID_TECHNOTREND,
621  { USB_DEVICE(USB_VID_TECHNOTREND,
623  {} /* Terminating entry */
624 };
625 MODULE_DEVICE_TABLE (usb, ttusb2_table);
626 
627 static struct dvb_usb_device_properties ttusb2_properties = {
629 
630  .usb_ctrl = CYPRESS_FX2,
631  .firmware = "dvb-usb-pctv-400e-01.fw",
632 
633  .size_of_priv = sizeof(struct ttusb2_state),
634 
635  .num_adapters = 1,
636  .adapter = {
637  {
638  .num_frontends = 1,
639  .fe = {{
640  .streaming_ctrl = NULL, // ttusb2_streaming_ctrl,
641 
642  .frontend_attach = ttusb2_frontend_tda10086_attach,
643  .tuner_attach = ttusb2_tuner_tda826x_attach,
644 
645  /* parameter for the MPEG2-data transfer */
646  .stream = {
647  .type = USB_ISOC,
648  .count = 5,
649  .endpoint = 0x02,
650  .u = {
651  .isoc = {
652  .framesperurb = 4,
653  .framesize = 940,
654  .interval = 1,
655  }
656  }
657  }
658  }},
659  }
660  },
661 
662  .power_ctrl = ttusb2_power_ctrl,
663  .identify_state = ttusb2_identify_state,
664 
665  .i2c_algo = &ttusb2_i2c_algo,
666 
667  .generic_bulk_ctrl_endpoint = 0x01,
668 
669  .num_device_descs = 2,
670  .devices = {
671  { "Pinnacle 400e DVB-S USB2.0",
672  { &ttusb2_table[0], NULL },
673  { NULL },
674  },
675  { "Pinnacle 450e DVB-S USB2.0",
676  { &ttusb2_table[1], NULL },
677  { NULL },
678  },
679  }
680 };
681 
682 static struct dvb_usb_device_properties ttusb2_properties_s2400 = {
684 
685  .usb_ctrl = CYPRESS_FX2,
686  .firmware = "dvb-usb-tt-s2400-01.fw",
687 
688  .size_of_priv = sizeof(struct ttusb2_state),
689 
690  .num_adapters = 1,
691  .adapter = {
692  {
693  .num_frontends = 1,
694  .fe = {{
695  .streaming_ctrl = NULL,
696 
697  .frontend_attach = ttusb2_frontend_tda10086_attach,
698  .tuner_attach = ttusb2_tuner_tda826x_attach,
699 
700  /* parameter for the MPEG2-data transfer */
701  .stream = {
702  .type = USB_ISOC,
703  .count = 5,
704  .endpoint = 0x02,
705  .u = {
706  .isoc = {
707  .framesperurb = 4,
708  .framesize = 940,
709  .interval = 1,
710  }
711  }
712  }
713  }},
714  }
715  },
716 
717  .power_ctrl = ttusb2_power_ctrl,
718  .identify_state = ttusb2_identify_state,
719 
720  .i2c_algo = &ttusb2_i2c_algo,
721 
722  .generic_bulk_ctrl_endpoint = 0x01,
723 
724  .num_device_descs = 1,
725  .devices = {
726  { "Technotrend TT-connect S-2400",
727  { &ttusb2_table[2], NULL },
728  { NULL },
729  },
730  }
731 };
732 
733 static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
735 
736  .usb_ctrl = CYPRESS_FX2,
737 
738  .size_of_priv = sizeof(struct ttusb2_state),
739 
740  .rc.core = {
741  .rc_interval = 150, /* Less than IR_KEYPRESS_TIMEOUT */
742  .rc_codes = RC_MAP_TT_1500,
743  .rc_query = tt3650_rc_query,
744  .allowed_protos = RC_TYPE_UNKNOWN,
745  },
746 
747  .num_adapters = 1,
748  .adapter = {
749  {
750  .num_frontends = 2,
751  .fe = {{
752  .streaming_ctrl = NULL,
753 
754  .frontend_attach = ttusb2_frontend_tda10023_attach,
755  .tuner_attach = ttusb2_tuner_tda827x_attach,
756 
757  /* parameter for the MPEG2-data transfer */
758  .stream = {
759  .type = USB_ISOC,
760  .count = 5,
761  .endpoint = 0x02,
762  .u = {
763  .isoc = {
764  .framesperurb = 4,
765  .framesize = 940,
766  .interval = 1,
767  }
768  }
769  }
770  }, {
771  .streaming_ctrl = NULL,
772 
773  .frontend_attach = ttusb2_frontend_tda10023_attach,
774  .tuner_attach = ttusb2_tuner_tda827x_attach,
775 
776  /* parameter for the MPEG2-data transfer */
777  .stream = {
778  .type = USB_ISOC,
779  .count = 5,
780  .endpoint = 0x02,
781  .u = {
782  .isoc = {
783  .framesperurb = 4,
784  .framesize = 940,
785  .interval = 1,
786  }
787  }
788  }
789  }},
790  },
791  },
792 
793  .power_ctrl = ttusb2_power_ctrl,
794  .identify_state = ttusb2_identify_state,
795 
796  .i2c_algo = &ttusb2_i2c_algo,
797 
798  .generic_bulk_ctrl_endpoint = 0x01,
799 
800  .num_device_descs = 1,
801  .devices = {
802  { "Technotrend TT-connect CT-3650",
803  .warm_ids = { &ttusb2_table[3], NULL },
804  },
805  }
806 };
807 
808 static struct usb_driver ttusb2_driver = {
809  .name = "dvb_usb_ttusb2",
810  .probe = ttusb2_probe,
811  .disconnect = ttusb2_usb_disconnect,
812  .id_table = ttusb2_table,
813 };
814 
815 module_usb_driver(ttusb2_driver);
816 
817 MODULE_AUTHOR("Patrick Boettcher <[email protected]>");
818 MODULE_DESCRIPTION("Driver for Pinnacle PCTV 400e DVB-S USB2.0");
819 MODULE_VERSION("1.0");
820 MODULE_LICENSE("GPL");