1 /* DVB USB framework compliant Linux driver for the
2 * TBS QBOX
3 *
4 * Copyright (C) 2008 Bob Liu (Bob@Turbosight.com)
5 * Igor M. Liplianin (liplianin@me.by)
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, version 2.
10 *
11 * see Documentation/dvb/README.dvb-usb for more information
12 */
13
14 /*
15 * History:
16 *
17 * July 2009 Konstantin Dimitrov <kosio.dimitrov@gmail.com>
18 * remove QBOX2-DS3000 support
19 * add QBOXS2-CX24116 support
20 */
21
22 #include <linux/version.h>
23 #include "tbs-qboxs2.h"
24 #include "cx24116.h"
25
26
27 #ifndef USB_PID_TBSQBOX_1
28 #define USB_PID_TBSQBOX_1 0x5928
29 #endif
30
31 #define TBSQBOX_READ_MSG 0
32 #define TBSQBOX_WRITE_MSG 1
33
34 /* on my own*/
35 #define TBSQBOX_VOLTAGE_CTRL (0x1800)
36 #define TBSQBOX_RC_QUERY (0x1a00)
37
38 struct tbsqboxs2_state {
39 u32 last_key_pressed;
40 };
41 struct tbsqboxs2_rc_keys {
42 u32 keycode;
43 u32 event;
44 };
45
46 /* debug */
47 static int dvb_usb_tbsqboxs2_debug;
48 module_param_named(debug, dvb_usb_tbsqboxs2_debug, int, 0644);
49 MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))." DVB_USB_DEBUG_STATUS);
50
51 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
52
tbsqboxs2_op_rw(struct usb_device * dev,u8 request,u16 value,u16 index,u8 * data,u16 len,int flags)53 static int tbsqboxs2_op_rw(struct usb_device *dev, u8 request, u16 value,
54 u16 index, u8 * data, u16 len, int flags)
55 {
56 int ret;
57 u8 u8buf[len];
58
59 unsigned int pipe = (flags == TBSQBOX_READ_MSG) ?
60 usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
61 u8 request_type = (flags == TBSQBOX_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
62
63 if (flags == TBSQBOX_WRITE_MSG)
64 memcpy(u8buf, data, len);
65 ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
66 value, index, u8buf, len, 2000);
67
68 if (flags == TBSQBOX_READ_MSG)
69 memcpy(data, u8buf, len);
70 return ret;
71 }
72
73 /* I2C */
tbsqboxs2_i2c_transfer(struct i2c_adapter * adap,struct i2c_msg msg[],int num)74 static int tbsqboxs2_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
75 int num)
76 {
77 struct dvb_usb_device *d = i2c_get_adapdata(adap);
78 int i = 0, len;
79 u8 ibuf[1], obuf[3];
80 u8 buf6[20];
81
82 if (!d)
83 return -ENODEV;
84 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
85 return -EAGAIN;
86
87 switch (num) {
88 case 2: {
89 /* read */
90 obuf[0] = msg[0].len;
91 obuf[1] = msg[0].addr<<1;
92 obuf[2] = msg[0].buf[0];
93
94 tbsqboxs2_op_rw(d->udev, 0x90, 0, 0,
95 obuf, 3, TBSQBOX_WRITE_MSG);
96 msleep(5);
97 tbsqboxs2_op_rw(d->udev, 0x91, 0, 0,
98 ibuf, 1, TBSQBOX_READ_MSG);
99 memcpy(msg[1].buf, ibuf, msg[1].len);
100 break;
101 }
102 case 1:
103 switch (msg[0].addr) {
104 case 0x55: {
105 if (msg[0].buf[0] == 0xf7) {
106 /* firmware */
107 /* Write in small blocks */
108 u8 iobuf[19];
109 iobuf[0] = 0x12;
110 iobuf[1] = 0xaa;
111 iobuf[2] = 0xf7;
112 len = msg[0].len - 1;
113 i = 1;
114 do {
115 memcpy(iobuf + 3, msg[0].buf + i, (len > 16 ? 16 : len));
116 tbsqboxs2_op_rw(d->udev, 0x80, 0, 0,
117 iobuf, (len > 16 ? 16 : len) + 3, TBSQBOX_WRITE_MSG);
118 i += 16;
119 len -= 16;
120 } while (len > 0);
121 } else {
122 /* write to register */
123 buf6[0] = msg[0].len+1;//lenth
124 buf6[1] = msg[0].addr<<1;//demod addr
125 for(i=0;i<msg[0].len;i++) {
126 buf6[2+i] = msg[0].buf[i];//register
127 }
128 tbsqboxs2_op_rw(d->udev, 0x80, 0, 0,
129 buf6, msg[0].len+2, TBSQBOX_WRITE_MSG);
130 //msleep(3);
131 }
132 break;
133 }
134 case 0x60: {
135 /* write to register */
136 buf6[0] = msg[0].len+1;//lenth
137 buf6[1] = msg[0].addr<<1;//demod addr
138 for(i=0;i<msg[0].len;i++) {
139 buf6[2+i] = msg[0].buf[i];//register
140 }
141 tbsqboxs2_op_rw(d->udev, 0x80, 0, 0,
142 buf6, msg[0].len+2, TBSQBOX_WRITE_MSG);
143 msleep(3);
144
145 break;
146 }
147 case (TBSQBOX_RC_QUERY): {
148 tbsqboxs2_op_rw(d->udev, 0xb8, 0, 0,
149 buf6, 4, TBSQBOX_READ_MSG);
150 msg[0].buf[0] = buf6[2];
151 msg[0].buf[1] = buf6[3];
152 msleep(3);
153 //info("TBSQBOX_RC_QUERY %x %x %x %x\n",buf6[0],buf6[1],buf6[2],buf6[3]);
154 break;
155 }
156 case (TBSQBOX_VOLTAGE_CTRL): {
157 buf6[0] = 3;
158 buf6[1] = msg[0].buf[0];
159 tbsqboxs2_op_rw(d->udev, 0x8a, 0, 0,
160 buf6, 2, TBSQBOX_WRITE_MSG);
161
162 break;
163 }
164 }
165
166 break;
167 }
168
169 mutex_unlock(&d->i2c_mutex);
170 return num;
171 }
172
tbsqboxs2_i2c_func(struct i2c_adapter * adapter)173 static u32 tbsqboxs2_i2c_func(struct i2c_adapter *adapter)
174 {
175 return I2C_FUNC_I2C;
176 }
177
178
179
180 static struct i2c_algorithm tbsqboxs2_i2c_algo = {
181 .master_xfer = tbsqboxs2_i2c_transfer,
182 .functionality = tbsqboxs2_i2c_func,
183 };
184
185 static const struct cx24116_config qbox2_cx24116_config = {
186 .demod_address = 0x55,
187 .mpg_clk_pos_pol = 0x01,
188 };
189
tbsqboxs2_read_mac_address(struct dvb_usb_device * d,u8 mac[6])190 static int tbsqboxs2_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
191 {
192 int i,ret;
193 u8 ibuf[3] = {0, 0,0};
194 u8 eeprom[256], eepromline[16];
195
196 for (i = 0; i < 256; i++) {
197 ibuf[0]=1;//lenth
198 ibuf[1]=0xa0;//eeprom addr
199 ibuf[2]=i;//register
200 ret = tbsqboxs2_op_rw(d->udev, 0x90, 0, 0,
201 ibuf, 3, TBSQBOX_WRITE_MSG);
202 ret = tbsqboxs2_op_rw(d->udev, 0x91, 0, 0,
203 ibuf, 1, TBSQBOX_READ_MSG);
204 if (ret < 0) {
205 err("read eeprom failed");
206 return -1;
207 } else {
208 eepromline[i%16] = ibuf[0];
209 eeprom[i] = ibuf[0];
210 }
211
212 if ((i % 16) == 15) {
213 deb_xfer("%02x: ", i - 15);
214 debug_dump(eepromline, 16, deb_xfer);
215 }
216 }
217 memcpy(mac, eeprom + 16, 6);
218 return 0;
219 };
220
tbsqboxs2_set_voltage(struct dvb_frontend * fe,enum fe_sec_voltage voltage)221 static int tbsqboxs2_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage)
222 {
223 static u8 command_13v[1] = {0x00};
224 static u8 command_18v[1] = {0x01};
225 struct i2c_msg msg[] = {
226 {.addr = TBSQBOX_VOLTAGE_CTRL, .flags = 0,
227 .buf = command_13v, .len = 1},
228 };
229
230 struct dvb_usb_adapter *udev_adap =
231 (struct dvb_usb_adapter *)(fe->dvb->priv);
232 if (voltage == SEC_VOLTAGE_18)
233 msg[0].buf = command_18v;
234 info("tbsqboxs2_set_voltage %d",voltage);
235 i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1);
236 return 0;
237 }
238
239 static struct dvb_usb_device_properties tbsqboxs2_properties;
240
tbsqboxs2_frontend_attach(struct dvb_usb_adapter * d)241 static int tbsqboxs2_frontend_attach(struct dvb_usb_adapter *d)
242 {
243 u8 buf[20];
244
245 if ((d->fe_adap[0].fe = dvb_attach(cx24116_attach, &qbox2_cx24116_config,
246 &d->dev->i2c_adap)) != NULL) {
247 d->fe_adap[0].fe->ops.set_voltage = tbsqboxs2_set_voltage;
248 printk("QBOXS2: CX24116 attached.\n");
249
250 buf[0] = 7;
251 buf[1] = 1;
252 tbsqboxs2_op_rw(d->dev->udev, 0x8a, 0, 0,
253 buf, 2, TBSQBOX_WRITE_MSG);
254
255 return 0;
256 }
257
258 return -EIO;
259 }
260
261
262
263 static struct rc_map_table tbsqboxs2_rc_keys[] = {
264 { 0xff84, KEY_POWER2}, /* power */
265 { 0xff94, KEY_MUTE}, /* mute */
266 { 0xff87, KEY_1},
267 { 0xff86, KEY_2},
268 { 0xff85, KEY_3},
269 { 0xff8b, KEY_4},
270 { 0xff8a, KEY_5},
271 { 0xff89, KEY_6},
272 { 0xff8f, KEY_7},
273 { 0xff8e, KEY_8},
274 { 0xff8d, KEY_9},
275 { 0xff92, KEY_0},
276 { 0xff96, KEY_CHANNELUP}, /* ch+ */
277 { 0xff91, KEY_CHANNELDOWN}, /* ch- */
278 { 0xff93, KEY_VOLUMEUP}, /* vol+ */
279 { 0xff8c, KEY_VOLUMEDOWN}, /* vol- */
280 { 0xff83, KEY_RECORD}, /* rec */
281 { 0xff98, KEY_PAUSE}, /* pause, yellow */
282 { 0xff99, KEY_OK}, /* ok */
283 { 0xff9a, KEY_CAMERA}, /* snapshot */
284 { 0xff81, KEY_UP},
285 { 0xff90, KEY_LEFT},
286 { 0xff82, KEY_RIGHT},
287 { 0xff88, KEY_DOWN},
288 { 0xff95, KEY_FAVORITES}, /* blue */
289 { 0xff97, KEY_SUBTITLE}, /* green */
290 { 0xff9d, KEY_ZOOM},
291 { 0xff9f, KEY_EXIT},
292 { 0xff9e, KEY_MENU},
293 { 0xff9c, KEY_EPG},
294 { 0xff80, KEY_PREVIOUS}, /* red */
295 { 0xff9b, KEY_MODE},
296 { 0xffdd, KEY_TV },
297 { 0xffde, KEY_PLAY },
298 { 0xffdc, KEY_STOP },
299 { 0xffdb, KEY_REWIND },
300 { 0xffda, KEY_FASTFORWARD },
301 { 0xffd9, KEY_PREVIOUS }, /* replay */
302 { 0xffd8, KEY_NEXT }, /* skip */
303 { 0xffd1, KEY_NUMERIC_STAR },
304 { 0xffd2, KEY_NUMERIC_POUND },
305 { 0xffd4, KEY_DELETE }, /* clear */
306 };
307
308
309
tbsqboxs2_rc_query(struct dvb_usb_device * d,u32 * event,int * state)310 static int tbsqboxs2_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
311 {
312 struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
313 int keymap_size = d->props.rc.legacy.rc_map_size;
314
315 struct tbsqboxs2_state *st = d->priv;
316 u8 key[2];
317 struct i2c_msg msg[] = {
318 {.addr = TBSQBOX_RC_QUERY, .flags = I2C_M_RD, .buf = key,
319 .len = 2},
320 };
321 int i;
322
323 *state = REMOTE_NO_KEY_PRESSED;
324 if (tbsqboxs2_i2c_transfer(&d->i2c_adap, msg, 1) == 1) {
325 //info("key: %x %x\n",msg[0].buf[0],msg[0].buf[1]);
326 for (i = 0; i < keymap_size; i++) {
327 if (rc5_data(&keymap[i]) == msg[0].buf[1]) {
328 *state = REMOTE_KEY_PRESSED;
329 *event = keymap[i].keycode;
330 st->last_key_pressed =
331 keymap[i].keycode;
332 break;
333 }
334 st->last_key_pressed = 0;
335 }
336 }
337
338 return 0;
339 }
340
341 static struct usb_device_id tbsqboxs2_table[] = {
342 {USB_DEVICE(0x734c, 0x5928)},
343 {USB_DEVICE(USB_VID_CYPRESS, USB_PID_TBSQBOX_1)},
344 { }
345 };
346
347 MODULE_DEVICE_TABLE(usb, tbsqboxs2_table);
348
tbsqboxs2_load_firmware(struct usb_device * dev,const struct firmware * frmwr)349 static int tbsqboxs2_load_firmware(struct usb_device *dev,
350 const struct firmware *frmwr)
351 {
352 u8 *b, *p;
353 int ret = 0, i;
354 u8 reset;
355 const struct firmware *fw;
356 const char *filename = "dvb-usb-tbsqbox-id5928.fw";
357 switch (dev->descriptor.idProduct) {
358 case 0x5928:
359 ret = request_firmware(&fw, filename, &dev->dev);
360 if (ret != 0) {
361 err("did not find the firmware file. (%s) "
362 "Please see linux/Documentation/dvb/ for more details "
363 "on firmware-problems.", filename);
364 return ret;
365 }
366 break;
367 default:
368 fw = frmwr;
369 break;
370 }
371 info("start downloading TBSQBOX firmware");
372 p = kmalloc(fw->size, GFP_KERNEL);
373 reset = 1;
374 /*stop the CPU*/
375 tbsqboxs2_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBSQBOX_WRITE_MSG);
376 tbsqboxs2_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBSQBOX_WRITE_MSG);
377
378 if (p != NULL) {
379 memcpy(p, fw->data, fw->size);
380 for (i = 0; i < fw->size; i += 0x40) {
381 b = (u8 *) p + i;
382 if (tbsqboxs2_op_rw(dev, 0xa0, i, 0, b , 0x40,
383 TBSQBOX_WRITE_MSG) != 0x40) {
384 err("error while transferring firmware");
385 ret = -EINVAL;
386 break;
387 }
388 }
389 /* restart the CPU */
390 reset = 0;
391 if (ret || tbsqboxs2_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
392 TBSQBOX_WRITE_MSG) != 1) {
393 err("could not restart the USB controller CPU.");
394 ret = -EINVAL;
395 }
396 if (ret || tbsqboxs2_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
397 TBSQBOX_WRITE_MSG) != 1) {
398 err("could not restart the USB controller CPU.");
399 ret = -EINVAL;
400 }
401
402 msleep(100);
403 kfree(p);
404 }
405 return ret;
406 }
407
408 static struct dvb_usb_device_properties tbsqboxs2_properties = {
409 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
410 .usb_ctrl = DEVICE_SPECIFIC,
411 .firmware = "dvb-usb-tbsqbox-id5928.fw",
412 .size_of_priv = sizeof(struct tbsqboxs2_state),
413 .no_reconnect = 1,
414 .i2c_algo = &tbsqboxs2_i2c_algo,
415 .read_mac_address = tbsqboxs2_read_mac_address,
416 .num_adapters = 1,
417
418 .generic_bulk_ctrl_endpoint = 0x81,
419 /* parameter for the MPEG2-data transfer */
420 .download_firmware = tbsqboxs2_load_firmware,
421
422 .adapter = {
423 {
424 .num_frontends = 1,
425 .fe = {{
426 .frontend_attach = tbsqboxs2_frontend_attach,
427
428 .stream = {
429 .type = USB_BULK,
430 .count = 8,
431 .endpoint = 0x82,
432 .u = {
433 .bulk = {
434 .buffersize = 4096,
435 }
436 }
437 },
438 }},
439 .size_of_priv = 0,
440 },
441 },
442
443 .num_device_descs = 1,
444 .devices = {
445 {"TBS QBOXS2 DVBS2 USB2.0",
446 {&tbsqboxs2_table[0], NULL},
447 {NULL},
448 },
449 },
450
451 .rc.legacy = {
452 .rc_map_table = tbsqboxs2_rc_keys,
453 .rc_map_size = ARRAY_SIZE(tbsqboxs2_rc_keys),
454 .rc_interval = 150,
455 .rc_query = tbsqboxs2_rc_query,
456 },
457 };
458
tbsqboxs2_probe(struct usb_interface * intf,const struct usb_device_id * id)459 static int tbsqboxs2_probe(struct usb_interface *intf,
460 const struct usb_device_id *id)
461 {
462 if (0 == dvb_usb_device_init(intf, &tbsqboxs2_properties,
463 THIS_MODULE, NULL, adapter_nr)) {
464 return 0;
465 }
466 return -ENODEV;
467 }
468
469 static struct usb_driver tbsqboxs2_driver = {
470 .name = "tbsqboxs2",
471 .probe = tbsqboxs2_probe,
472 .disconnect = dvb_usb_device_exit,
473 .id_table = tbsqboxs2_table,
474 };
475
tbsqboxs2_module_init(void)476 static int __init tbsqboxs2_module_init(void)
477 {
478 int ret = usb_register(&tbsqboxs2_driver);
479 if (ret)
480 err("usb_register failed. Error number %d", ret);
481
482 return ret;
483 }
484
tbsqboxs2_module_exit(void)485 static void __exit tbsqboxs2_module_exit(void)
486 {
487 usb_deregister(&tbsqboxs2_driver);
488 }
489
490 module_init(tbsqboxs2_module_init);
491 module_exit(tbsqboxs2_module_exit);
492
493 MODULE_AUTHOR("Bob Liu <Bob@turbosight.com>");
494 MODULE_DESCRIPTION("Driver for TBS QBOXS2-CX24116");
495 MODULE_VERSION("0.2");
496 MODULE_LICENSE("GPL");
497