brintos

brintos / linux-shallow public Read only

0
0
Text · 18.5 KiB · 373ffa7 Raw
850 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones3 * (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 + TDA100868 *9 * I2C addresses:10 * 0x08 - LNBP21PD   - LNB power supply11 * 0x0e - TDA10086   - Demodulator12 * 0x50 - FX2 eeprom13 * 0x60 - TDA8263    - Tuner14 * 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 information21 */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_PORT62};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		else404			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		else412			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     0x1b444 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	else583		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");850