cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ttusb2.c (18994B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones
      3 * (e.g. Pinnacle 400e DVB-S USB2.0).
      4 *
      5 * The Pinnacle 400e uses the same protocol as the Technotrend USB1.1 boxes.
      6 *
      7 * TDA8263 + TDA10086
      8 *
      9 * I2C addresses:
     10 * 0x08 - LNBP21PD   - LNB power supply
     11 * 0x0e - TDA10086   - Demodulator
     12 * 0x50 - FX2 eeprom
     13 * 0x60 - TDA8263    - Tuner
     14 * 0x78 ???
     15 *
     16 * Copyright (c) 2002 Holger Waechtler <holger@convergence.de>
     17 * Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net>
     18 * Copyright (C) 2005-6 Patrick Boettcher <pb@linuxtv.org>
     19 *
     20 * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
     21 */
     22#define DVB_USB_LOG_PREFIX "ttusb2"
     23#include "dvb-usb.h"
     24
     25#include "ttusb2.h"
     26
     27#include "tda826x.h"
     28#include "tda10086.h"
     29#include "tda1002x.h"
     30#include "tda10048.h"
     31#include "tda827x.h"
     32#include "lnbp21.h"
     33/* CA */
     34#include <media/dvb_ca_en50221.h>
     35
     36/* debug */
     37static int dvb_usb_ttusb2_debug;
     38#define deb_info(args...)   dprintk(dvb_usb_ttusb2_debug,0x01,args)
     39module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644);
     40MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS);
     41static int dvb_usb_ttusb2_debug_ci;
     42module_param_named(debug_ci,dvb_usb_ttusb2_debug_ci, int, 0644);
     43MODULE_PARM_DESC(debug_ci, "set debugging ci." DVB_USB_DEBUG_STATUS);
     44
     45DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
     46
     47#define ci_dbg(format, arg...)                \
     48do {                                          \
     49	if (dvb_usb_ttusb2_debug_ci)                                    \
     50		printk(KERN_DEBUG DVB_USB_LOG_PREFIX \
     51			": %s " format "\n" , __func__, ## arg);       \
     52} while (0)
     53
     54enum {
     55	TT3650_CMD_CI_TEST = 0x40,
     56	TT3650_CMD_CI_RD_CTRL,
     57	TT3650_CMD_CI_WR_CTRL,
     58	TT3650_CMD_CI_RD_ATTR,
     59	TT3650_CMD_CI_WR_ATTR,
     60	TT3650_CMD_CI_RESET,
     61	TT3650_CMD_CI_SET_VIDEO_PORT
     62};
     63
     64struct ttusb2_state {
     65	struct dvb_ca_en50221 ca;
     66	struct mutex ca_mutex;
     67	u8 id;
     68	u16 last_rc_key;
     69};
     70
     71static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd,
     72		u8 *wbuf, int wlen, u8 *rbuf, int rlen)
     73{
     74	struct ttusb2_state *st = d->priv;
     75	u8 *s, *r = NULL;
     76	int ret = 0;
     77
     78	if (4 + rlen > 64)
     79		return -EIO;
     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 */
    120static 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
    130static 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
    143static 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
    165static 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
    181static 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
    201static 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
    216static 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
    240static 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
    245static 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
    250static 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
    292static 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]) {
    305		return DVB_CA_EN50221_POLL_CAM_PRESENT |
    306			DVB_CA_EN50221_POLL_CAM_READY;
    307	}
    308	return 0;
    309}
    310
    311static 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
    332static 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
    368static 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		if (3 + msg[i].len > sizeof(obuf)) {
    385			err("i2c wr len=%d too high", msg[i].len);
    386			break;
    387		}
    388		if (write_read) {
    389			if (3 + msg[i+1].len > sizeof(ibuf)) {
    390				err("i2c rd len=%d too high", msg[i+1].len);
    391				break;
    392			}
    393		} else if (read) {
    394			if (3 + msg[i].len > sizeof(ibuf)) {
    395				err("i2c rd len=%d too high", msg[i].len);
    396				break;
    397			}
    398		}
    399
    400		obuf[0] = (msg[i].addr << 1) | (write_read | read);
    401		if (read)
    402			obuf[1] = 0;
    403		else
    404			obuf[1] = msg[i].len;
    405
    406		/* read request */
    407		if (write_read)
    408			obuf[2] = msg[i+1].len;
    409		else if (read)
    410			obuf[2] = msg[i].len;
    411		else
    412			obuf[2] = 0;
    413
    414		memcpy(&obuf[3], msg[i].buf, msg[i].len);
    415
    416		if (ttusb2_msg(d, CMD_I2C_XFER, obuf, obuf[1]+3, ibuf, obuf[2] + 3) < 0) {
    417			err("i2c transfer failed.");
    418			break;
    419		}
    420
    421		if (write_read) {
    422			memcpy(msg[i+1].buf, &ibuf[3], msg[i+1].len);
    423			i++;
    424		} else if (read)
    425			memcpy(msg[i].buf, &ibuf[3], msg[i].len);
    426	}
    427
    428	mutex_unlock(&d->i2c_mutex);
    429	return i;
    430}
    431
    432static u32 ttusb2_i2c_func(struct i2c_adapter *adapter)
    433{
    434	return I2C_FUNC_I2C;
    435}
    436
    437static struct i2c_algorithm ttusb2_i2c_algo = {
    438	.master_xfer   = ttusb2_i2c_xfer,
    439	.functionality = ttusb2_i2c_func,
    440};
    441
    442/* command to poll IR receiver (copied from pctv452e.c) */
    443#define CMD_GET_IR_CODE     0x1b
    444
    445/* IR */
    446static int tt3650_rc_query(struct dvb_usb_device *d)
    447{
    448	int ret;
    449	u8 rx[9]; /* A CMD_GET_IR_CODE reply is 9 bytes long */
    450	struct ttusb2_state *st = d->priv;
    451	ret = ttusb2_msg(d, CMD_GET_IR_CODE, NULL, 0, rx, sizeof(rx));
    452	if (ret != 0)
    453		return ret;
    454
    455	if (rx[8] & 0x01) {
    456		/* got a "press" event */
    457		st->last_rc_key = RC_SCANCODE_RC5(rx[3], rx[2]);
    458		deb_info("%s: cmd=0x%02x sys=0x%02x\n", __func__, rx[2], rx[3]);
    459		rc_keydown(d->rc_dev, RC_PROTO_RC5, st->last_rc_key, rx[1]);
    460	} else if (st->last_rc_key) {
    461		rc_keyup(d->rc_dev);
    462		st->last_rc_key = 0;
    463	}
    464
    465	return 0;
    466}
    467
    468
    469/* Callbacks for DVB USB */
    470static int ttusb2_identify_state(struct usb_device *udev,
    471				 const struct dvb_usb_device_properties *props,
    472				 const struct dvb_usb_device_description **desc,
    473				 int *cold)
    474{
    475	*cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0;
    476	return 0;
    477}
    478
    479static int ttusb2_power_ctrl(struct dvb_usb_device *d, int onoff)
    480{
    481	u8 b = onoff;
    482	ttusb2_msg(d, CMD_POWER, &b, 0, NULL, 0);
    483	return ttusb2_msg(d, CMD_POWER, &b, 1, NULL, 0);
    484}
    485
    486
    487static struct tda10086_config tda10086_config = {
    488	.demod_address = 0x0e,
    489	.invert = 0,
    490	.diseqc_tone = 1,
    491	.xtal_freq = TDA10086_XTAL_16M,
    492};
    493
    494static struct tda10023_config tda10023_config = {
    495	.demod_address = 0x0c,
    496	.invert = 0,
    497	.xtal = 16000000,
    498	.pll_m = 11,
    499	.pll_p = 3,
    500	.pll_n = 1,
    501	.deltaf = 0xa511,
    502};
    503
    504static struct tda10048_config tda10048_config = {
    505	.demod_address    = 0x10 >> 1,
    506	.output_mode      = TDA10048_PARALLEL_OUTPUT,
    507	.inversion        = TDA10048_INVERSION_ON,
    508	.dtv6_if_freq_khz = TDA10048_IF_4000,
    509	.dtv7_if_freq_khz = TDA10048_IF_4500,
    510	.dtv8_if_freq_khz = TDA10048_IF_5000,
    511	.clk_freq_khz     = TDA10048_CLK_16000,
    512	.no_firmware      = 1,
    513	.set_pll          = true ,
    514	.pll_m            = 5,
    515	.pll_n            = 3,
    516	.pll_p            = 0,
    517};
    518
    519static struct tda827x_config tda827x_config = {
    520	.config = 0,
    521};
    522
    523static int ttusb2_frontend_tda10086_attach(struct dvb_usb_adapter *adap)
    524{
    525	if (usb_set_interface(adap->dev->udev,0,3) < 0)
    526		err("set interface to alts=3 failed");
    527
    528	if ((adap->fe_adap[0].fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) {
    529		deb_info("TDA10086 attach failed\n");
    530		return -ENODEV;
    531	}
    532
    533	return 0;
    534}
    535
    536static int ttusb2_ct3650_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
    537{
    538	struct dvb_usb_adapter *adap = fe->dvb->priv;
    539
    540	return adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, enable);
    541}
    542
    543static int ttusb2_frontend_tda10023_attach(struct dvb_usb_adapter *adap)
    544{
    545	if (usb_set_interface(adap->dev->udev, 0, 3) < 0)
    546		err("set interface to alts=3 failed");
    547
    548	if (adap->fe_adap[0].fe == NULL) {
    549		/* FE 0 DVB-C */
    550		adap->fe_adap[0].fe = dvb_attach(tda10023_attach,
    551			&tda10023_config, &adap->dev->i2c_adap, 0x48);
    552
    553		if (adap->fe_adap[0].fe == NULL) {
    554			deb_info("TDA10023 attach failed\n");
    555			return -ENODEV;
    556		}
    557		tt3650_ci_init(adap);
    558	} else {
    559		adap->fe_adap[1].fe = dvb_attach(tda10048_attach,
    560			&tda10048_config, &adap->dev->i2c_adap);
    561
    562		if (adap->fe_adap[1].fe == NULL) {
    563			deb_info("TDA10048 attach failed\n");
    564			return -ENODEV;
    565		}
    566
    567		/* tuner is behind TDA10023 I2C-gate */
    568		adap->fe_adap[1].fe->ops.i2c_gate_ctrl = ttusb2_ct3650_i2c_gate_ctrl;
    569
    570	}
    571
    572	return 0;
    573}
    574
    575static int ttusb2_tuner_tda827x_attach(struct dvb_usb_adapter *adap)
    576{
    577	struct dvb_frontend *fe;
    578
    579	/* MFE: select correct FE to attach tuner since that's called twice */
    580	if (adap->fe_adap[1].fe == NULL)
    581		fe = adap->fe_adap[0].fe;
    582	else
    583		fe = adap->fe_adap[1].fe;
    584
    585	/* attach tuner */
    586	if (dvb_attach(tda827x_attach, fe, 0x61, &adap->dev->i2c_adap, &tda827x_config) == NULL) {
    587		printk(KERN_ERR "%s: No tda827x found!\n", __func__);
    588		return -ENODEV;
    589	}
    590	return 0;
    591}
    592
    593static int ttusb2_tuner_tda826x_attach(struct dvb_usb_adapter *adap)
    594{
    595	if (dvb_attach(tda826x_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) {
    596		deb_info("TDA8263 attach failed\n");
    597		return -ENODEV;
    598	}
    599
    600	if (dvb_attach(lnbp21_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap, 0, 0) == NULL) {
    601		deb_info("LNBP21 attach failed\n");
    602		return -ENODEV;
    603	}
    604	return 0;
    605}
    606
    607/* DVB USB Driver stuff */
    608static struct dvb_usb_device_properties ttusb2_properties;
    609static struct dvb_usb_device_properties ttusb2_properties_s2400;
    610static struct dvb_usb_device_properties ttusb2_properties_ct3650;
    611
    612static void ttusb2_usb_disconnect(struct usb_interface *intf)
    613{
    614	struct dvb_usb_device *d = usb_get_intfdata(intf);
    615
    616	tt3650_ci_uninit(d);
    617	dvb_usb_device_exit(intf);
    618}
    619
    620static int ttusb2_probe(struct usb_interface *intf,
    621		const struct usb_device_id *id)
    622{
    623	if (0 == dvb_usb_device_init(intf, &ttusb2_properties,
    624				     THIS_MODULE, NULL, adapter_nr) ||
    625	    0 == dvb_usb_device_init(intf, &ttusb2_properties_s2400,
    626				     THIS_MODULE, NULL, adapter_nr) ||
    627	    0 == dvb_usb_device_init(intf, &ttusb2_properties_ct3650,
    628				     THIS_MODULE, NULL, adapter_nr))
    629		return 0;
    630	return -ENODEV;
    631}
    632
    633enum {
    634	PINNACLE_PCTV_400E,
    635	PINNACLE_PCTV_450E,
    636	TECHNOTREND_CONNECT_S2400,
    637	TECHNOTREND_CONNECT_CT3650,
    638	TECHNOTREND_CONNECT_S2400_8KEEPROM,
    639};
    640
    641static struct usb_device_id ttusb2_table[] = {
    642	DVB_USB_DEV(PINNACLE, PINNACLE_PCTV_400E),
    643	DVB_USB_DEV(PINNACLE, PINNACLE_PCTV_450E),
    644	DVB_USB_DEV(TECHNOTREND, TECHNOTREND_CONNECT_S2400),
    645	DVB_USB_DEV(TECHNOTREND, TECHNOTREND_CONNECT_CT3650),
    646	DVB_USB_DEV(TECHNOTREND, TECHNOTREND_CONNECT_S2400_8KEEPROM),
    647	{ }
    648};
    649
    650MODULE_DEVICE_TABLE (usb, ttusb2_table);
    651
    652static struct dvb_usb_device_properties ttusb2_properties = {
    653	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
    654
    655	.usb_ctrl = CYPRESS_FX2,
    656	.firmware = "dvb-usb-pctv-400e-01.fw",
    657
    658	.size_of_priv = sizeof(struct ttusb2_state),
    659
    660	.num_adapters = 1,
    661	.adapter = {
    662		{
    663		.num_frontends = 1,
    664		.fe = {{
    665			.streaming_ctrl   = NULL, // ttusb2_streaming_ctrl,
    666
    667			.frontend_attach  = ttusb2_frontend_tda10086_attach,
    668			.tuner_attach     = ttusb2_tuner_tda826x_attach,
    669
    670			/* parameter for the MPEG2-data transfer */
    671			.stream = {
    672				.type = USB_ISOC,
    673				.count = 5,
    674				.endpoint = 0x02,
    675				.u = {
    676					.isoc = {
    677						.framesperurb = 4,
    678						.framesize = 940,
    679						.interval = 1,
    680					}
    681				}
    682			}
    683		}},
    684		}
    685	},
    686
    687	.power_ctrl       = ttusb2_power_ctrl,
    688	.identify_state   = ttusb2_identify_state,
    689
    690	.i2c_algo         = &ttusb2_i2c_algo,
    691
    692	.generic_bulk_ctrl_endpoint = 0x01,
    693
    694	.num_device_descs = 2,
    695	.devices = {
    696		{   "Pinnacle 400e DVB-S USB2.0",
    697			{ &ttusb2_table[PINNACLE_PCTV_400E], NULL },
    698			{ NULL },
    699		},
    700		{   "Pinnacle 450e DVB-S USB2.0",
    701			{ &ttusb2_table[PINNACLE_PCTV_450E], NULL },
    702			{ NULL },
    703		},
    704	}
    705};
    706
    707static struct dvb_usb_device_properties ttusb2_properties_s2400 = {
    708	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
    709
    710	.usb_ctrl = CYPRESS_FX2,
    711	.firmware = "dvb-usb-tt-s2400-01.fw",
    712
    713	.size_of_priv = sizeof(struct ttusb2_state),
    714
    715	.num_adapters = 1,
    716	.adapter = {
    717		{
    718		.num_frontends = 1,
    719		.fe = {{
    720			.streaming_ctrl   = NULL,
    721
    722			.frontend_attach  = ttusb2_frontend_tda10086_attach,
    723			.tuner_attach     = ttusb2_tuner_tda826x_attach,
    724
    725			/* parameter for the MPEG2-data transfer */
    726			.stream = {
    727				.type = USB_ISOC,
    728				.count = 5,
    729				.endpoint = 0x02,
    730				.u = {
    731					.isoc = {
    732						.framesperurb = 4,
    733						.framesize = 940,
    734						.interval = 1,
    735					}
    736				}
    737			}
    738		}},
    739		}
    740	},
    741
    742	.power_ctrl       = ttusb2_power_ctrl,
    743	.identify_state   = ttusb2_identify_state,
    744
    745	.i2c_algo         = &ttusb2_i2c_algo,
    746
    747	.generic_bulk_ctrl_endpoint = 0x01,
    748
    749	.num_device_descs = 2,
    750	.devices = {
    751		{   "Technotrend TT-connect S-2400",
    752			{ &ttusb2_table[TECHNOTREND_CONNECT_S2400], NULL },
    753			{ NULL },
    754		},
    755		{   "Technotrend TT-connect S-2400 (8kB EEPROM)",
    756			{ &ttusb2_table[TECHNOTREND_CONNECT_S2400_8KEEPROM], NULL },
    757			{ NULL },
    758		},
    759	}
    760};
    761
    762static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
    763	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
    764
    765	.usb_ctrl = CYPRESS_FX2,
    766
    767	.size_of_priv = sizeof(struct ttusb2_state),
    768
    769	.rc.core = {
    770		.rc_interval      = 150, /* Less than IR_KEYPRESS_TIMEOUT */
    771		.rc_codes         = RC_MAP_TT_1500,
    772		.rc_query         = tt3650_rc_query,
    773		.allowed_protos   = RC_PROTO_BIT_RC5,
    774	},
    775
    776	.num_adapters = 1,
    777	.adapter = {
    778		{
    779		.num_frontends = 2,
    780		.fe = {{
    781			.streaming_ctrl   = NULL,
    782
    783			.frontend_attach  = ttusb2_frontend_tda10023_attach,
    784			.tuner_attach = ttusb2_tuner_tda827x_attach,
    785
    786			/* parameter for the MPEG2-data transfer */
    787			.stream = {
    788				.type = USB_ISOC,
    789				.count = 5,
    790				.endpoint = 0x02,
    791				.u = {
    792					.isoc = {
    793						.framesperurb = 4,
    794						.framesize = 940,
    795						.interval = 1,
    796					}
    797				}
    798			}
    799		}, {
    800			.streaming_ctrl   = NULL,
    801
    802			.frontend_attach  = ttusb2_frontend_tda10023_attach,
    803			.tuner_attach = ttusb2_tuner_tda827x_attach,
    804
    805			/* parameter for the MPEG2-data transfer */
    806			.stream = {
    807				.type = USB_ISOC,
    808				.count = 5,
    809				.endpoint = 0x02,
    810				.u = {
    811					.isoc = {
    812						.framesperurb = 4,
    813						.framesize = 940,
    814						.interval = 1,
    815					}
    816				}
    817			}
    818		}},
    819		},
    820	},
    821
    822	.power_ctrl       = ttusb2_power_ctrl,
    823	.identify_state   = ttusb2_identify_state,
    824
    825	.i2c_algo         = &ttusb2_i2c_algo,
    826
    827	.generic_bulk_ctrl_endpoint = 0x01,
    828
    829	.num_device_descs = 1,
    830	.devices = {
    831		{   "Technotrend TT-connect CT-3650",
    832			.warm_ids = { &ttusb2_table[TECHNOTREND_CONNECT_CT3650], NULL },
    833		},
    834	}
    835};
    836
    837static struct usb_driver ttusb2_driver = {
    838	.name		= "dvb_usb_ttusb2",
    839	.probe		= ttusb2_probe,
    840	.disconnect	= ttusb2_usb_disconnect,
    841	.id_table	= ttusb2_table,
    842};
    843
    844module_usb_driver(ttusb2_driver);
    845
    846MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
    847MODULE_DESCRIPTION("Driver for Pinnacle PCTV 400e DVB-S USB2.0");
    848MODULE_VERSION("1.0");
    849MODULE_LICENSE("GPL");