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