1/* DVB USB compliant linux driver for mobile DVB-T USB devices based on 2 * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-B) 3 * 4 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) 5 * 6 * based on GPL code from DiBcom, which has 7 * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the Free 11 * Software Foundation, version 2. 12 * 13 * see Documentation/dvb/README.dvb-usb for more information 14 */ 15#include "dibusb.h" 16 17static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_adapter *adap) 18{ 19 struct dib3000_config demod_cfg; 20 struct dibusb_state *st = adap->priv; 21 22 demod_cfg.demod_address = 0x8; 23 24 if ((adap->fe = dib3000mb_attach(&demod_cfg,&adap->dev->i2c_adap,&st->ops)) == NULL) 25 return -ENODEV; 26 27 adap->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c; 28 adap->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c; 29 30 adap->tuner_pass_ctrl = st->ops.tuner_pass_ctrl; 31 32 return 0; 33} 34 35static int dibusb_thomson_tuner_attach(struct dvb_usb_adapter *adap) 36{ 37 adap->pll_addr = 0x61; 38 adap->pll_desc = &dvb_pll_tua6010xs; 39 return 0; 40} 41 42/* Some of the Artec 1.1 device aren't equipped with the default tuner 43 * (Thomson Cable), but with a Panasonic ENV77H11D5. This function figures 44 * this out. */ 45static int dibusb_tuner_probe_and_attach(struct dvb_usb_adapter *adap) 46{ 47 u8 b[2] = { 0,0 }, b2[1]; 48 int ret = 0; 49 struct i2c_msg msg[2] = { 50 { .flags = 0, .buf = b, .len = 2 }, 51 { .flags = I2C_M_RD, .buf = b2, .len = 1 }, 52 }; 53 54 /* the Panasonic sits on I2C addrass 0x60, the Thomson on 0x61 */ 55 msg[0].addr = msg[1].addr = 0x60; 56 57 if (adap->tuner_pass_ctrl) 58 adap->tuner_pass_ctrl(adap->fe,1,msg[0].addr); 59 60 if (i2c_transfer(&adap->dev->i2c_adap, msg, 2) != 2) { 61 err("tuner i2c write failed."); 62 ret = -EREMOTEIO; 63 } 64 65 if (adap->tuner_pass_ctrl) 66 adap->tuner_pass_ctrl(adap->fe,0,msg[0].addr); 67 68 if (b2[0] == 0xfe) { 69 info("This device has the Thomson Cable onboard. Which is default."); 70 dibusb_thomson_tuner_attach(adap); 71 } else { 72 u8 bpll[4] = { 0x0b, 0xf5, 0x85, 0xab }; 73 info("This device has the Panasonic ENV77H11D5 onboard."); 74 adap->pll_addr = 0x60; 75 memcpy(adap->pll_init,bpll,4); 76 adap->pll_desc = &dvb_pll_tda665x; 77 } 78 79 return ret; 80} 81 82/* USB Driver stuff */ 83static struct dvb_usb_device_properties dibusb1_1_properties; 84static struct dvb_usb_device_properties dibusb1_1_an2235_properties; 85static struct dvb_usb_device_properties dibusb2_0b_properties; 86static struct dvb_usb_device_properties artec_t1_usb2_properties; 87 88static int dibusb_probe(struct usb_interface *intf, 89 const struct usb_device_id *id) 90{ 91 if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE,NULL) == 0 || 92 dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE,NULL) == 0 || 93 dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE,NULL) == 0 || 94 dvb_usb_device_init(intf,&artec_t1_usb2_properties,THIS_MODULE,NULL) == 0) 95 return 0; 96 97 return -EINVAL; 98} 99 100/* do not change the order of the ID table */ 101static struct usb_device_id dibusb_dib3000mb_table [] = { 102/* 00 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_COLD) }, 103/* 01 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_WARM) }, 104/* 02 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_COLD) }, 105/* 03 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_WARM) }, 106/* 04 */ { USB_DEVICE(USB_VID_COMPRO_UNK, USB_PID_COMPRO_DVBU2000_UNK_COLD) }, 107/* 05 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_COLD) }, 108/* 06 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_WARM) }, 109/* 07 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) }, 110/* 08 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) }, 111/* 09 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_COLD) }, 112/* 10 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_WARM) }, 113/* 11 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_COLD) }, 114/* 12 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_WARM) }, 115/* 13 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_COLD) }, 116/* 14 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_WARM) }, 117/* 15 */ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7041_COLD) }, 118/* 16 */ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7041_WARM) }, 119/* 17 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_COLD) }, 120/* 18 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_WARM) }, 121/* 19 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) }, 122/* 20 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) }, 123/* 21 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) }, 124/* 22 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) }, 125/* 23 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_COLD) }, 126 127/* device ID with default DIBUSB2_0-firmware and with the hacked firmware */ 128/* 24 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_WARM) }, 129/* 25 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_COLD) }, 130/* 26 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_WARM) }, 131 132/* 27 */ { USB_DEVICE(USB_VID_KWORLD, USB_PID_KWORLD_VSTREAM_COLD) }, 133 134/* 28 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) }, 135/* 29 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_WARM) }, 136 137 138#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY 139/* 30 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) }, 140#endif 141 142 { } /* Terminating entry */ 143}; 144MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table); 145 146static struct dvb_usb_device_properties dibusb1_1_properties = { 147 .caps = DVB_USB_IS_AN_I2C_ADAPTER, 148 149 .usb_ctrl = CYPRESS_AN2135, 150 151 .firmware = "dvb-usb-dibusb-5.0.0.11.fw", 152 153 .num_adapters = 1, 154 .adapter = { 155 { 156 .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, 157 .pid_filter_count = 16, 158 159 .streaming_ctrl = dibusb_streaming_ctrl, 160 .pid_filter = dibusb_pid_filter, 161 .pid_filter_ctrl = dibusb_pid_filter_ctrl, 162 .frontend_attach = dibusb_dib3000mb_frontend_attach, 163 .tuner_attach = dibusb_tuner_probe_and_attach, 164 165 /* parameter for the MPEG2-data transfer */ 166 .stream = { 167 .type = USB_BULK, 168 .count = 7, 169 .endpoint = 0x02, 170 .u = { 171 .bulk = { 172 .buffersize = 4096, 173 } 174 } 175 }, 176 .size_of_priv = sizeof(struct dibusb_state), 177 } 178 }, 179 180 .power_ctrl = dibusb_power_ctrl, 181 182 .rc_interval = DEFAULT_RC_INTERVAL, 183 .rc_key_map = dibusb_rc_keys, 184 .rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ 185 .rc_query = dibusb_rc_query, 186 187 .i2c_algo = &dibusb_i2c_algo, 188 189 .generic_bulk_ctrl_endpoint = 0x01, 190 191 .num_device_descs = 9, 192 .devices = { 193 { "AVerMedia AverTV DVBT USB1.1", 194 { &dibusb_dib3000mb_table[0], NULL }, 195 { &dibusb_dib3000mb_table[1], NULL }, 196 }, 197 { "Compro Videomate DVB-U2000 - DVB-T USB1.1 (please confirm to linux-dvb)", 198 { &dibusb_dib3000mb_table[2], &dibusb_dib3000mb_table[4], NULL}, 199 { &dibusb_dib3000mb_table[3], NULL }, 200 }, 201 { "DiBcom USB1.1 DVB-T reference design (MOD3000)", 202 { &dibusb_dib3000mb_table[5], NULL }, 203 { &dibusb_dib3000mb_table[6], NULL }, 204 }, 205 { "KWorld V-Stream XPERT DTV - DVB-T USB1.1", 206 { &dibusb_dib3000mb_table[7], NULL }, 207 { &dibusb_dib3000mb_table[8], NULL }, 208 }, 209 { "Grandtec USB1.1 DVB-T", 210 { &dibusb_dib3000mb_table[9], &dibusb_dib3000mb_table[11], NULL }, 211 { &dibusb_dib3000mb_table[10], &dibusb_dib3000mb_table[12], NULL }, 212 }, 213 { "Unkown USB1.1 DVB-T device ???? please report the name to the author", 214 { &dibusb_dib3000mb_table[13], NULL }, 215 { &dibusb_dib3000mb_table[14], NULL }, 216 }, 217 { "TwinhanDTV USB-Ter USB1.1 / Magic Box I / HAMA USB1.1 DVB-T device", 218 { &dibusb_dib3000mb_table[15], &dibusb_dib3000mb_table[17], NULL}, 219 { &dibusb_dib3000mb_table[16], &dibusb_dib3000mb_table[18], NULL}, 220 }, 221 { "Artec T1 USB1.1 TVBOX with AN2135", 222 { &dibusb_dib3000mb_table[19], NULL }, 223 { &dibusb_dib3000mb_table[20], NULL }, 224 }, 225 { "VideoWalker DVB-T USB", 226 { &dibusb_dib3000mb_table[25], NULL }, 227 { &dibusb_dib3000mb_table[26], NULL }, 228 }, 229 } 230}; 231 232static struct dvb_usb_device_properties dibusb1_1_an2235_properties = { 233 .caps = DVB_USB_IS_AN_I2C_ADAPTER, 234 .usb_ctrl = CYPRESS_AN2235, 235 236 .firmware = "dvb-usb-dibusb-an2235-01.fw", 237 238 .num_adapters = 1, 239 .adapter = { 240 { 241 .caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER, 242 .pid_filter_count = 16, 243 244 .streaming_ctrl = dibusb_streaming_ctrl, 245 .pid_filter = dibusb_pid_filter, 246 .pid_filter_ctrl = dibusb_pid_filter_ctrl, 247 .frontend_attach = dibusb_dib3000mb_frontend_attach, 248 .tuner_attach = dibusb_tuner_probe_and_attach, 249 250 /* parameter for the MPEG2-data transfer */ 251 .stream = { 252 .type = USB_BULK, 253 .count = 7, 254 .endpoint = 0x02, 255 .u = { 256 .bulk = { 257 .buffersize = 4096, 258 } 259 } 260 }, 261 .size_of_priv = sizeof(struct dibusb_state), 262 }, 263 }, 264 .power_ctrl = dibusb_power_ctrl, 265 266 .rc_interval = DEFAULT_RC_INTERVAL, 267 .rc_key_map = dibusb_rc_keys, 268 .rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ 269 .rc_query = dibusb_rc_query, 270 271 .i2c_algo = &dibusb_i2c_algo, 272 273 .generic_bulk_ctrl_endpoint = 0x01, 274 275#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY 276 .num_device_descs = 2, 277#else 278 .num_device_descs = 1, 279#endif 280 .devices = { 281 { "Artec T1 USB1.1 TVBOX with AN2235", 282 { &dibusb_dib3000mb_table[21], NULL }, 283 { &dibusb_dib3000mb_table[22], NULL }, 284 }, 285#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY 286 { "Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)", 287 { &dibusb_dib3000mb_table[30], NULL }, 288 { NULL }, 289 }, 290 { NULL }, 291#endif 292 } 293}; 294 295static struct dvb_usb_device_properties dibusb2_0b_properties = { 296 .caps = DVB_USB_IS_AN_I2C_ADAPTER, 297 298 .usb_ctrl = CYPRESS_FX2, 299 300 .firmware = "dvb-usb-adstech-usb2-02.fw", 301 302 .num_adapters = 1, 303 .adapter = { 304 { 305 .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, 306 .pid_filter_count = 16, 307 308 .streaming_ctrl = dibusb2_0_streaming_ctrl, 309 .pid_filter = dibusb_pid_filter, 310 .pid_filter_ctrl = dibusb_pid_filter_ctrl, 311 .frontend_attach = dibusb_dib3000mb_frontend_attach, 312 .tuner_attach = dibusb_thomson_tuner_attach, 313 314 /* parameter for the MPEG2-data transfer */ 315 .stream = { 316 .type = USB_BULK, 317 .count = 7, 318 .endpoint = 0x06, 319 .u = { 320 .bulk = { 321 .buffersize = 4096, 322 } 323 } 324 }, 325 .size_of_priv = sizeof(struct dibusb_state), 326 } 327 }, 328 .power_ctrl = dibusb2_0_power_ctrl, 329 330 .rc_interval = DEFAULT_RC_INTERVAL, 331 .rc_key_map = dibusb_rc_keys, 332 .rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ 333 .rc_query = dibusb_rc_query, 334 335 .i2c_algo = &dibusb_i2c_algo, 336 337 .generic_bulk_ctrl_endpoint = 0x01, 338 339 .num_device_descs = 2, 340 .devices = { 341 { "KWorld/ADSTech Instant DVB-T USB2.0", 342 { &dibusb_dib3000mb_table[23], NULL }, 343 { &dibusb_dib3000mb_table[24], NULL }, 344 }, 345 { "KWorld Xpert DVB-T USB2.0", 346 { &dibusb_dib3000mb_table[27], NULL }, 347 { NULL } 348 }, 349 { NULL }, 350 } 351}; 352 353static struct dvb_usb_device_properties artec_t1_usb2_properties = { 354 .caps = DVB_USB_IS_AN_I2C_ADAPTER, 355 356 .usb_ctrl = CYPRESS_FX2, 357 358 .firmware = "dvb-usb-dibusb-6.0.0.8.fw", 359 360 .num_adapters = 1, 361 .adapter = { 362 { 363 .caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, 364 .pid_filter_count = 16, 365 366 .streaming_ctrl = dibusb2_0_streaming_ctrl, 367 .pid_filter = dibusb_pid_filter, 368 .pid_filter_ctrl = dibusb_pid_filter_ctrl, 369 .frontend_attach = dibusb_dib3000mb_frontend_attach, 370 .tuner_attach = dibusb_tuner_probe_and_attach, 371 /* parameter for the MPEG2-data transfer */ 372 .stream = { 373 .type = USB_BULK, 374 .count = 7, 375 .endpoint = 0x06, 376 .u = { 377 .bulk = { 378 .buffersize = 4096, 379 } 380 } 381 }, 382 .size_of_priv = sizeof(struct dibusb_state), 383 } 384 }, 385 .power_ctrl = dibusb2_0_power_ctrl, 386 387 .rc_interval = DEFAULT_RC_INTERVAL, 388 .rc_key_map = dibusb_rc_keys, 389 .rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ 390 .rc_query = dibusb_rc_query, 391 392 .i2c_algo = &dibusb_i2c_algo, 393 394 .generic_bulk_ctrl_endpoint = 0x01, 395 396 .num_device_descs = 1, 397 .devices = { 398 { "Artec T1 USB2.0", 399 { &dibusb_dib3000mb_table[28], NULL }, 400 { &dibusb_dib3000mb_table[29], NULL }, 401 }, 402 { NULL }, 403 } 404}; 405 406static struct usb_driver dibusb_driver = { 407 .name = "dvb_usb_dibusb_mb", 408 .probe = dibusb_probe, 409 .disconnect = dvb_usb_device_exit, 410 .id_table = dibusb_dib3000mb_table, 411}; 412 413/* module stuff */ 414static int __init dibusb_module_init(void) 415{ 416 int result; 417 if ((result = usb_register(&dibusb_driver))) { 418 err("usb_register failed. Error number %d",result); 419 return result; 420 } 421 422 return 0; 423} 424 425static void __exit dibusb_module_exit(void) 426{ 427 /* deregister this driver from the USB subsystem */ 428 usb_deregister(&dibusb_driver); 429} 430 431module_init (dibusb_module_init); 432module_exit (dibusb_module_exit); 433 434MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); 435MODULE_DESCRIPTION("Driver for DiBcom USB DVB-T devices (DiB3000M-B based)"); 436MODULE_VERSION("1.0"); 437MODULE_LICENSE("GPL"); 438