]>
Commit | Line | Data |
---|---|---|
b7f54910 PB |
1 | /* Linux driver for devices based on the DiBcom DiB0700 USB bridge |
2 | * | |
3 | * This program is free software; you can redistribute it and/or modify it | |
4 | * under the terms of the GNU General Public License as published by the Free | |
5 | * Software Foundation, version 2. | |
6 | * | |
7 | * Copyright (C) 2005-6 DiBcom, SA | |
8 | */ | |
9 | #include "dib0700.h" | |
10 | ||
11 | /* debug */ | |
12 | int dvb_usb_dib0700_debug; | |
13 | module_param_named(debug,dvb_usb_dib0700_debug, int, 0644); | |
14 | MODULE_PARM_DESC(debug, "set debugging level (1=info,2=fw,4=fwdata,8=data (or-able))." DVB_USB_DEBUG_STATUS); | |
15 | ||
acc5c9ee OG |
16 | static int nb_packet_buffer_size = 21; |
17 | module_param(nb_packet_buffer_size, int, 0644); | |
18 | MODULE_PARM_DESC(nb_packet_buffer_size, | |
f319ed91 | 19 | "Set the dib0700 driver data buffer size. This parameter corresponds to the number of TS packets. The actual size of the data buffer corresponds to this parameter multiplied by 188 (default: 21)"); |
acc5c9ee | 20 | |
78e92006 JG |
21 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
22 | ||
99afb989 DH |
23 | |
24 | int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, | |
25 | u32 *romversion, u32 *ramversion, u32 *fwtype) | |
26 | { | |
ffa5899c OG |
27 | struct dib0700_state *st = d->priv; |
28 | int ret; | |
29 | ||
bff469f4 | 30 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { |
680417bb | 31 | err("could not acquire lock"); |
26a11eb1 | 32 | return -EINTR; |
bff469f4 OG |
33 | } |
34 | ||
ffa5899c | 35 | ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), |
99afb989 DH |
36 | REQUEST_GET_VERSION, |
37 | USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, | |
ffa5899c | 38 | st->buf, 16, USB_CTRL_GET_TIMEOUT); |
acc5c9ee | 39 | if (hwversion != NULL) |
ffa5899c OG |
40 | *hwversion = (st->buf[0] << 24) | (st->buf[1] << 16) | |
41 | (st->buf[2] << 8) | st->buf[3]; | |
acc5c9ee | 42 | if (romversion != NULL) |
ffa5899c OG |
43 | *romversion = (st->buf[4] << 24) | (st->buf[5] << 16) | |
44 | (st->buf[6] << 8) | st->buf[7]; | |
acc5c9ee | 45 | if (ramversion != NULL) |
ffa5899c OG |
46 | *ramversion = (st->buf[8] << 24) | (st->buf[9] << 16) | |
47 | (st->buf[10] << 8) | st->buf[11]; | |
acc5c9ee | 48 | if (fwtype != NULL) |
ffa5899c OG |
49 | *fwtype = (st->buf[12] << 24) | (st->buf[13] << 16) | |
50 | (st->buf[14] << 8) | st->buf[15]; | |
bff469f4 | 51 | mutex_unlock(&d->usb_mutex); |
99afb989 DH |
52 | return ret; |
53 | } | |
54 | ||
b7f54910 PB |
55 | /* expecting rx buffer: request data[0] data[1] ... data[2] */ |
56 | static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen) | |
57 | { | |
58 | int status; | |
59 | ||
60 | deb_data(">>> "); | |
230b27cd | 61 | debug_dump(tx, txlen, deb_data); |
b7f54910 PB |
62 | |
63 | status = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev,0), | |
64 | tx[0], USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, tx, txlen, | |
65 | USB_CTRL_GET_TIMEOUT); | |
66 | ||
67 | if (status != txlen) | |
6958effe | 68 | deb_data("ep 0 write error (status = %d, len: %d)\n",status,txlen); |
b7f54910 PB |
69 | |
70 | return status < 0 ? status : 0; | |
71 | } | |
72 | ||
73 | /* expecting tx buffer: request data[0] ... data[n] (n <= 4) */ | |
54d75eba | 74 | int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen) |
b7f54910 PB |
75 | { |
76 | u16 index, value; | |
77 | int status; | |
78 | ||
79 | if (txlen < 2) { | |
80 | err("tx buffer length is smaller than 2. Makes no sense."); | |
81 | return -EINVAL; | |
82 | } | |
83 | if (txlen > 4) { | |
84 | err("tx buffer length is larger than 4. Not supported."); | |
85 | return -EINVAL; | |
86 | } | |
87 | ||
88 | deb_data(">>> "); | |
89 | debug_dump(tx,txlen,deb_data); | |
90 | ||
91 | value = ((txlen - 2) << 8) | tx[1]; | |
92 | index = 0; | |
93 | if (txlen > 2) | |
94 | index |= (tx[2] << 8); | |
95 | if (txlen > 3) | |
96 | index |= tx[3]; | |
97 | ||
b7f54910 PB |
98 | status = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev,0), tx[0], |
99 | USB_TYPE_VENDOR | USB_DIR_IN, value, index, rx, rxlen, | |
100 | USB_CTRL_GET_TIMEOUT); | |
101 | ||
102 | if (status < 0) | |
6958effe | 103 | deb_info("ep 0 read error (status = %d)\n",status); |
b7f54910 PB |
104 | |
105 | deb_data("<<< "); | |
230b27cd | 106 | debug_dump(rx, rxlen, deb_data); |
b7f54910 PB |
107 | |
108 | return status; /* length in case of success */ | |
109 | } | |
110 | ||
111 | int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val) | |
112 | { | |
ffa5899c | 113 | struct dib0700_state *st = d->priv; |
bff469f4 OG |
114 | int ret; |
115 | ||
116 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { | |
680417bb | 117 | err("could not acquire lock"); |
26a11eb1 | 118 | return -EINTR; |
bff469f4 | 119 | } |
ffa5899c OG |
120 | |
121 | st->buf[0] = REQUEST_SET_GPIO; | |
122 | st->buf[1] = gpio; | |
123 | st->buf[2] = ((gpio_dir & 0x01) << 7) | ((gpio_val & 0x01) << 6); | |
124 | ||
125 | ret = dib0700_ctrl_wr(d, st->buf, 3); | |
126 | ||
bff469f4 | 127 | mutex_unlock(&d->usb_mutex); |
ffa5899c | 128 | return ret; |
b7f54910 PB |
129 | } |
130 | ||
acc5c9ee OG |
131 | static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) |
132 | { | |
230b27cd | 133 | struct dib0700_state *st = d->priv; |
230b27cd DM |
134 | int ret; |
135 | ||
136 | if (st->fw_version >= 0x10201) { | |
bff469f4 | 137 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { |
680417bb | 138 | err("could not acquire lock"); |
26a11eb1 | 139 | return -EINTR; |
bff469f4 OG |
140 | } |
141 | ||
ffa5899c OG |
142 | st->buf[0] = REQUEST_SET_USB_XFER_LEN; |
143 | st->buf[1] = (nb_ts_packets >> 8) & 0xff; | |
144 | st->buf[2] = nb_ts_packets & 0xff; | |
230b27cd DM |
145 | |
146 | deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets); | |
147 | ||
ffa5899c | 148 | ret = dib0700_ctrl_wr(d, st->buf, 3); |
bff469f4 | 149 | mutex_unlock(&d->usb_mutex); |
230b27cd DM |
150 | } else { |
151 | deb_info("this firmware does not allow to change the USB xfer len\n"); | |
152 | ret = -EIO; | |
153 | } | |
154 | ||
155 | return ret; | |
acc5c9ee OG |
156 | } |
157 | ||
b7f54910 | 158 | /* |
bdc203e1 | 159 | * I2C master xfer function (supported in 1.20 firmware) |
b7f54910 | 160 | */ |
bdc203e1 DH |
161 | static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, |
162 | int num) | |
163 | { | |
164 | /* The new i2c firmware messages are more reliable and in particular | |
165 | properly support i2c read calls not preceded by a write */ | |
166 | ||
167 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | |
ffa5899c | 168 | struct dib0700_state *st = d->priv; |
bdc203e1 DH |
169 | uint8_t bus_mode = 1; /* 0=eeprom bus, 1=frontend bus */ |
170 | uint8_t gen_mode = 0; /* 0=master i2c, 1=gpio i2c */ | |
171 | uint8_t en_start = 0; | |
172 | uint8_t en_stop = 0; | |
bdc203e1 DH |
173 | int result, i; |
174 | ||
175 | /* Ensure nobody else hits the i2c bus while we're sending our | |
176 | sequence of messages, (such as the remote control thread) */ | |
177 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | |
26a11eb1 | 178 | return -EINTR; |
bdc203e1 DH |
179 | |
180 | for (i = 0; i < num; i++) { | |
181 | if (i == 0) { | |
182 | /* First message in the transaction */ | |
183 | en_start = 1; | |
184 | } else if (!(msg[i].flags & I2C_M_NOSTART)) { | |
185 | /* Device supports repeated-start */ | |
186 | en_start = 1; | |
187 | } else { | |
188 | /* Not the first packet and device doesn't support | |
189 | repeated start */ | |
190 | en_start = 0; | |
191 | } | |
192 | if (i == (num - 1)) { | |
193 | /* Last message in the transaction */ | |
194 | en_stop = 1; | |
195 | } | |
196 | ||
197 | if (msg[i].flags & I2C_M_RD) { | |
198 | /* Read request */ | |
199 | u16 index, value; | |
200 | uint8_t i2c_dest; | |
201 | ||
202 | i2c_dest = (msg[i].addr << 1); | |
203 | value = ((en_start << 7) | (en_stop << 6) | | |
204 | (msg[i].len & 0x3F)) << 8 | i2c_dest; | |
205 | /* I2C ctrl + FE bus; */ | |
230b27cd DM |
206 | index = ((gen_mode << 6) & 0xC0) | |
207 | ((bus_mode << 4) & 0x30); | |
bdc203e1 DH |
208 | |
209 | result = usb_control_msg(d->udev, | |
210 | usb_rcvctrlpipe(d->udev, 0), | |
211 | REQUEST_NEW_I2C_READ, | |
212 | USB_TYPE_VENDOR | USB_DIR_IN, | |
fa1ecd8d | 213 | value, index, st->buf, |
bdc203e1 DH |
214 | msg[i].len, |
215 | USB_CTRL_GET_TIMEOUT); | |
216 | if (result < 0) { | |
be9bae10 | 217 | deb_info("i2c read error (status = %d)\n", result); |
bdc203e1 DH |
218 | break; |
219 | } | |
d2514991 | 220 | |
fa1ecd8d MCC |
221 | if (msg[i].len > sizeof(st->buf)) { |
222 | deb_info("buffer too small to fit %d bytes\n", | |
223 | msg[i].len); | |
224 | return -EIO; | |
225 | } | |
226 | ||
227 | memcpy(msg[i].buf, st->buf, msg[i].len); | |
228 | ||
d2514991 MK |
229 | deb_data("<<< "); |
230 | debug_dump(msg[i].buf, msg[i].len, deb_data); | |
231 | ||
bdc203e1 DH |
232 | } else { |
233 | /* Write request */ | |
bff469f4 | 234 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { |
680417bb | 235 | err("could not acquire lock"); |
26a11eb1 SN |
236 | mutex_unlock(&d->i2c_mutex); |
237 | return -EINTR; | |
bff469f4 | 238 | } |
ffa5899c OG |
239 | st->buf[0] = REQUEST_NEW_I2C_WRITE; |
240 | st->buf[1] = msg[i].addr << 1; | |
241 | st->buf[2] = (en_start << 7) | (en_stop << 6) | | |
bdc203e1 DH |
242 | (msg[i].len & 0x3F); |
243 | /* I2C ctrl + FE bus; */ | |
ffa5899c | 244 | st->buf[3] = ((gen_mode << 6) & 0xC0) | |
230b27cd | 245 | ((bus_mode << 4) & 0x30); |
fa1ecd8d MCC |
246 | |
247 | if (msg[i].len > sizeof(st->buf) - 4) { | |
248 | deb_info("i2c message to big: %d\n", | |
249 | msg[i].len); | |
250 | return -EIO; | |
251 | } | |
252 | ||
bdc203e1 | 253 | /* The Actual i2c payload */ |
ffa5899c | 254 | memcpy(&st->buf[4], msg[i].buf, msg[i].len); |
bdc203e1 | 255 | |
d2514991 | 256 | deb_data(">>> "); |
ffa5899c | 257 | debug_dump(st->buf, msg[i].len + 4, deb_data); |
d2514991 | 258 | |
bdc203e1 DH |
259 | result = usb_control_msg(d->udev, |
260 | usb_sndctrlpipe(d->udev, 0), | |
261 | REQUEST_NEW_I2C_WRITE, | |
262 | USB_TYPE_VENDOR | USB_DIR_OUT, | |
ffa5899c | 263 | 0, 0, st->buf, msg[i].len + 4, |
bdc203e1 | 264 | USB_CTRL_GET_TIMEOUT); |
bff469f4 | 265 | mutex_unlock(&d->usb_mutex); |
bdc203e1 | 266 | if (result < 0) { |
be9bae10 | 267 | deb_info("i2c write error (status = %d)\n", result); |
bdc203e1 DH |
268 | break; |
269 | } | |
270 | } | |
271 | } | |
272 | mutex_unlock(&d->i2c_mutex); | |
273 | return i; | |
274 | } | |
275 | ||
276 | /* | |
277 | * I2C master xfer function (pre-1.20 firmware) | |
278 | */ | |
279 | static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, | |
280 | struct i2c_msg *msg, int num) | |
b7f54910 PB |
281 | { |
282 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | |
ffa5899c | 283 | struct dib0700_state *st = d->priv; |
b7f54910 | 284 | int i,len; |
b7f54910 PB |
285 | |
286 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | |
26a11eb1 | 287 | return -EINTR; |
bff469f4 | 288 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { |
680417bb | 289 | err("could not acquire lock"); |
26a11eb1 SN |
290 | mutex_unlock(&d->i2c_mutex); |
291 | return -EINTR; | |
bff469f4 | 292 | } |
b7f54910 PB |
293 | |
294 | for (i = 0; i < num; i++) { | |
295 | /* fill in the address */ | |
ffa5899c | 296 | st->buf[1] = msg[i].addr << 1; |
b7f54910 | 297 | /* fill the buffer */ |
fa1ecd8d MCC |
298 | if (msg[i].len > sizeof(st->buf) - 2) { |
299 | deb_info("i2c xfer to big: %d\n", | |
300 | msg[i].len); | |
301 | return -EIO; | |
302 | } | |
ffa5899c | 303 | memcpy(&st->buf[2], msg[i].buf, msg[i].len); |
b7f54910 PB |
304 | |
305 | /* write/read request */ | |
306 | if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { | |
ffa5899c OG |
307 | st->buf[0] = REQUEST_I2C_READ; |
308 | st->buf[1] |= 1; | |
b7f54910 PB |
309 | |
310 | /* special thing in the current firmware: when length is zero the read-failed */ | |
ffa5899c | 311 | len = dib0700_ctrl_rd(d, st->buf, msg[i].len + 2, |
bd1f976c | 312 | st->buf, msg[i + 1].len); |
ffa5899c | 313 | if (len <= 0) { |
8db12cdf | 314 | deb_info("I2C read failed on address 0x%02x\n", |
ffa5899c | 315 | msg[i].addr); |
b7f54910 | 316 | break; |
303cbeaa | 317 | } |
b7f54910 | 318 | |
fa1ecd8d MCC |
319 | if (msg[i + 1].len > sizeof(st->buf)) { |
320 | deb_info("i2c xfer buffer to small for %d\n", | |
321 | msg[i].len); | |
322 | return -EIO; | |
323 | } | |
bd1f976c MCC |
324 | memcpy(msg[i + 1].buf, st->buf, msg[i + 1].len); |
325 | ||
b7f54910 PB |
326 | msg[i+1].len = len; |
327 | ||
328 | i++; | |
329 | } else { | |
ffa5899c OG |
330 | st->buf[0] = REQUEST_I2C_WRITE; |
331 | if (dib0700_ctrl_wr(d, st->buf, msg[i].len + 2) < 0) | |
b7f54910 PB |
332 | break; |
333 | } | |
334 | } | |
bff469f4 | 335 | mutex_unlock(&d->usb_mutex); |
b7f54910 | 336 | mutex_unlock(&d->i2c_mutex); |
ffa5899c | 337 | |
b7f54910 PB |
338 | return i; |
339 | } | |
340 | ||
bdc203e1 DH |
341 | static int dib0700_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, |
342 | int num) | |
343 | { | |
344 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | |
345 | struct dib0700_state *st = d->priv; | |
346 | ||
347 | if (st->fw_use_new_i2c_api == 1) { | |
348 | /* User running at least fw 1.20 */ | |
349 | return dib0700_i2c_xfer_new(adap, msg, num); | |
350 | } else { | |
351 | /* Use legacy calls */ | |
352 | return dib0700_i2c_xfer_legacy(adap, msg, num); | |
353 | } | |
354 | } | |
355 | ||
b7f54910 PB |
356 | static u32 dib0700_i2c_func(struct i2c_adapter *adapter) |
357 | { | |
358 | return I2C_FUNC_I2C; | |
359 | } | |
360 | ||
361 | struct i2c_algorithm dib0700_i2c_algo = { | |
362 | .master_xfer = dib0700_i2c_xfer, | |
363 | .functionality = dib0700_i2c_func, | |
364 | }; | |
365 | ||
6958effe PB |
366 | int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props, |
367 | struct dvb_usb_device_description **desc, int *cold) | |
368 | { | |
ffa5899c OG |
369 | s16 ret; |
370 | u8 *b; | |
371 | ||
372 | b = kmalloc(16, GFP_KERNEL); | |
373 | if (!b) | |
374 | return -ENOMEM; | |
375 | ||
376 | ||
377 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | |
a75763ff PB |
378 | REQUEST_GET_VERSION, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, b, 16, USB_CTRL_GET_TIMEOUT); |
379 | ||
380 | deb_info("FW GET_VERSION length: %d\n",ret); | |
381 | ||
382 | *cold = ret <= 0; | |
6958effe | 383 | deb_info("cold: %d\n", *cold); |
ffa5899c OG |
384 | |
385 | kfree(b); | |
6958effe PB |
386 | return 0; |
387 | } | |
388 | ||
a75763ff PB |
389 | static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, |
390 | u8 pll_src, u8 pll_range, u8 clock_gpio3, u16 pll_prediv, | |
391 | u16 pll_loopdiv, u16 free_div, u16 dsuScaler) | |
392 | { | |
ffa5899c | 393 | struct dib0700_state *st = d->priv; |
bff469f4 OG |
394 | int ret; |
395 | ||
396 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { | |
680417bb | 397 | err("could not acquire lock"); |
26a11eb1 | 398 | return -EINTR; |
bff469f4 | 399 | } |
ffa5899c OG |
400 | |
401 | st->buf[0] = REQUEST_SET_CLOCK; | |
402 | st->buf[1] = (en_pll << 7) | (pll_src << 6) | | |
403 | (pll_range << 5) | (clock_gpio3 << 4); | |
404 | st->buf[2] = (pll_prediv >> 8) & 0xff; /* MSB */ | |
405 | st->buf[3] = pll_prediv & 0xff; /* LSB */ | |
406 | st->buf[4] = (pll_loopdiv >> 8) & 0xff; /* MSB */ | |
407 | st->buf[5] = pll_loopdiv & 0xff; /* LSB */ | |
408 | st->buf[6] = (free_div >> 8) & 0xff; /* MSB */ | |
409 | st->buf[7] = free_div & 0xff; /* LSB */ | |
410 | st->buf[8] = (dsuScaler >> 8) & 0xff; /* MSB */ | |
411 | st->buf[9] = dsuScaler & 0xff; /* LSB */ | |
412 | ||
413 | ret = dib0700_ctrl_wr(d, st->buf, 10); | |
bff469f4 | 414 | mutex_unlock(&d->usb_mutex); |
ffa5899c OG |
415 | |
416 | return ret; | |
a75763ff PB |
417 | } |
418 | ||
7757ddda OG |
419 | int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) |
420 | { | |
ffa5899c | 421 | struct dib0700_state *st = d->priv; |
7757ddda | 422 | u16 divider; |
bff469f4 | 423 | int ret; |
7757ddda OG |
424 | |
425 | if (scl_kHz == 0) | |
426 | return -EINVAL; | |
427 | ||
bff469f4 | 428 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { |
680417bb | 429 | err("could not acquire lock"); |
26a11eb1 | 430 | return -EINTR; |
bff469f4 OG |
431 | } |
432 | ||
ffa5899c | 433 | st->buf[0] = REQUEST_SET_I2C_PARAM; |
7757ddda | 434 | divider = (u16) (30000 / scl_kHz); |
ffa5899c OG |
435 | st->buf[1] = 0; |
436 | st->buf[2] = (u8) (divider >> 8); | |
437 | st->buf[3] = (u8) (divider & 0xff); | |
7757ddda | 438 | divider = (u16) (72000 / scl_kHz); |
ffa5899c OG |
439 | st->buf[4] = (u8) (divider >> 8); |
440 | st->buf[5] = (u8) (divider & 0xff); | |
7757ddda | 441 | divider = (u16) (72000 / scl_kHz); /* clock: 72MHz */ |
ffa5899c OG |
442 | st->buf[6] = (u8) (divider >> 8); |
443 | st->buf[7] = (u8) (divider & 0xff); | |
7757ddda | 444 | |
b4d6046e | 445 | deb_info("setting I2C speed: %04x %04x %04x (%d kHz).", |
ffa5899c OG |
446 | (st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) | |
447 | st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz); | |
bff469f4 OG |
448 | |
449 | ret = dib0700_ctrl_wr(d, st->buf, 8); | |
450 | mutex_unlock(&d->usb_mutex); | |
451 | ||
452 | return ret; | |
7757ddda OG |
453 | } |
454 | ||
455 | ||
a75763ff PB |
456 | int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3) |
457 | { | |
458 | switch (clk_MHz) { | |
459 | case 72: dib0700_set_clock(d, 1, 0, 1, clock_out_gp3, 2, 24, 0, 0x4c); break; | |
460 | default: return -EINVAL; | |
461 | } | |
462 | return 0; | |
463 | } | |
464 | ||
b7f54910 PB |
465 | static int dib0700_jumpram(struct usb_device *udev, u32 address) |
466 | { | |
ffa5899c OG |
467 | int ret = 0, actlen; |
468 | u8 *buf; | |
469 | ||
470 | buf = kmalloc(8, GFP_KERNEL); | |
471 | if (!buf) | |
472 | return -ENOMEM; | |
473 | buf[0] = REQUEST_JUMPRAM; | |
474 | buf[1] = 0; | |
475 | buf[2] = 0; | |
476 | buf[3] = 0; | |
477 | buf[4] = (address >> 24) & 0xff; | |
478 | buf[5] = (address >> 16) & 0xff; | |
479 | buf[6] = (address >> 8) & 0xff; | |
480 | buf[7] = address & 0xff; | |
b7f54910 PB |
481 | |
482 | if ((ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x01),buf,8,&actlen,1000)) < 0) { | |
483 | deb_fw("jumpram to 0x%x failed\n",address); | |
ffa5899c | 484 | goto out; |
b7f54910 PB |
485 | } |
486 | if (actlen != 8) { | |
487 | deb_fw("jumpram to 0x%x failed\n",address); | |
ffa5899c OG |
488 | ret = -EIO; |
489 | goto out; | |
b7f54910 | 490 | } |
ffa5899c OG |
491 | out: |
492 | kfree(buf); | |
493 | return ret; | |
b7f54910 PB |
494 | } |
495 | ||
496 | int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw) | |
497 | { | |
498 | struct hexline hx; | |
acc5c9ee | 499 | int pos = 0, ret, act_len, i, adap_num; |
ffa5899c | 500 | u8 *buf; |
acc5c9ee | 501 | u32 fw_version; |
b7f54910 | 502 | |
ffa5899c OG |
503 | buf = kmalloc(260, GFP_KERNEL); |
504 | if (!buf) | |
505 | return -ENOMEM; | |
b7f54910 PB |
506 | |
507 | while ((ret = dvb_usb_get_hexline(fw, &hx, &pos)) > 0) { | |
230b27cd DM |
508 | deb_fwdata("writing to address 0x%08x (buffer: 0x%02x %02x)\n", |
509 | hx.addr, hx.len, hx.chk); | |
b7f54910 PB |
510 | |
511 | buf[0] = hx.len; | |
5bc63607 PB |
512 | buf[1] = (hx.addr >> 8) & 0xff; |
513 | buf[2] = hx.addr & 0xff; | |
b7f54910 PB |
514 | buf[3] = hx.type; |
515 | memcpy(&buf[4],hx.data,hx.len); | |
516 | buf[4+hx.len] = hx.chk; | |
517 | ||
518 | ret = usb_bulk_msg(udev, | |
519 | usb_sndbulkpipe(udev, 0x01), | |
520 | buf, | |
521 | hx.len + 5, | |
522 | &act_len, | |
523 | 1000); | |
524 | ||
525 | if (ret < 0) { | |
526 | err("firmware download failed at %d with %d",pos,ret); | |
ffa5899c | 527 | goto out; |
b7f54910 PB |
528 | } |
529 | } | |
530 | ||
531 | if (ret == 0) { | |
532 | /* start the firmware */ | |
6958effe | 533 | if ((ret = dib0700_jumpram(udev, 0x70000000)) == 0) { |
b7f54910 | 534 | info("firmware started successfully."); |
a75763ff | 535 | msleep(500); |
6958effe | 536 | } |
b7f54910 PB |
537 | } else |
538 | ret = -EIO; | |
539 | ||
acc5c9ee OG |
540 | /* the number of ts packet has to be at least 1 */ |
541 | if (nb_packet_buffer_size < 1) | |
542 | nb_packet_buffer_size = 1; | |
543 | ||
bad7de74 | 544 | /* get the firmware version */ |
acc5c9ee OG |
545 | usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), |
546 | REQUEST_GET_VERSION, | |
547 | USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, | |
ffa5899c OG |
548 | buf, 16, USB_CTRL_GET_TIMEOUT); |
549 | fw_version = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11]; | |
acc5c9ee OG |
550 | |
551 | /* set the buffer size - DVB-USB is allocating URB buffers | |
552 | * only after the firwmare download was successful */ | |
553 | for (i = 0; i < dib0700_device_count; i++) { | |
554 | for (adap_num = 0; adap_num < dib0700_devices[i].num_adapters; | |
555 | adap_num++) { | |
230b27cd | 556 | if (fw_version >= 0x10201) { |
77eed219 | 557 | dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = 188*nb_packet_buffer_size; |
230b27cd | 558 | } else { |
acc5c9ee OG |
559 | /* for fw version older than 1.20.1, |
560 | * the buffersize has to be n times 512 */ | |
77eed219 MK |
561 | dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = ((188*nb_packet_buffer_size+188/2)/512)*512; |
562 | if (dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize < 512) | |
563 | dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = 512; | |
acc5c9ee OG |
564 | } |
565 | } | |
566 | } | |
ffa5899c OG |
567 | out: |
568 | kfree(buf); | |
b7f54910 PB |
569 | return ret; |
570 | } | |
571 | ||
572 | int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | |
573 | { | |
574 | struct dib0700_state *st = adap->dev->priv; | |
acc5c9ee OG |
575 | int ret; |
576 | ||
577 | if ((onoff != 0) && (st->fw_version >= 0x10201)) { | |
578 | /* for firmware later than 1.20.1, | |
579 | * the USB xfer length can be set */ | |
580 | ret = dib0700_set_usb_xfer_len(adap->dev, | |
581 | st->nb_packet_buffer_size); | |
582 | if (ret < 0) { | |
583 | deb_info("can not set the USB xfer len\n"); | |
584 | return ret; | |
585 | } | |
586 | } | |
b7f54910 | 587 | |
a96fbe04 | 588 | mutex_lock(&adap->dev->usb_mutex); |
bff469f4 | 589 | |
ffa5899c OG |
590 | st->buf[0] = REQUEST_ENABLE_VIDEO; |
591 | /* this bit gives a kind of command, | |
592 | * rather than enabling something or not */ | |
593 | st->buf[1] = (onoff << 4) | 0x00; | |
cb22cb52 DH |
594 | |
595 | if (st->disable_streaming_master_mode == 1) | |
ffa5899c | 596 | st->buf[2] = 0x00; |
cb22cb52 | 597 | else |
ffa5899c | 598 | st->buf[2] = 0x01 << 4; /* Master mode */ |
cb22cb52 | 599 | |
ffa5899c | 600 | st->buf[3] = 0x00; |
b7f54910 PB |
601 | |
602 | deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id); | |
603 | ||
7757ddda | 604 | st->channel_state &= ~0x3; |
77eed219 MK |
605 | if ((adap->fe_adap[0].stream.props.endpoint != 2) |
606 | && (adap->fe_adap[0].stream.props.endpoint != 3)) { | |
607 | deb_info("the endpoint number (%i) is not correct, use the adapter id instead", adap->fe_adap[0].stream.props.endpoint); | |
7757ddda OG |
608 | if (onoff) |
609 | st->channel_state |= 1 << (adap->id); | |
610 | else | |
f85ed0ce | 611 | st->channel_state |= 1 << ~(adap->id); |
b4d6046e | 612 | } else { |
7757ddda | 613 | if (onoff) |
77eed219 | 614 | st->channel_state |= 1 << (adap->fe_adap[0].stream.props.endpoint-2); |
7757ddda | 615 | else |
77eed219 | 616 | st->channel_state |= 1 << (3-adap->fe_adap[0].stream.props.endpoint); |
7757ddda | 617 | } |
b7f54910 | 618 | |
ffa5899c | 619 | st->buf[2] |= st->channel_state; |
b7f54910 | 620 | |
ffa5899c | 621 | deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]); |
b7f54910 | 622 | |
bff469f4 OG |
623 | ret = dib0700_ctrl_wr(adap->dev, st->buf, 4); |
624 | mutex_unlock(&adap->dev->usb_mutex); | |
625 | ||
626 | return ret; | |
b7f54910 PB |
627 | } |
628 | ||
c003ab1b | 629 | int dib0700_change_protocol(struct rc_dev *rc, u64 *rc_type) |
0ffd1ab3 | 630 | { |
d8b4b582 | 631 | struct dvb_usb_device *d = rc->priv; |
0ffd1ab3 | 632 | struct dib0700_state *st = d->priv; |
0ffd1ab3 MCC |
633 | int new_proto, ret; |
634 | ||
bff469f4 | 635 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { |
680417bb | 636 | err("could not acquire lock"); |
26a11eb1 | 637 | return -EINTR; |
bff469f4 OG |
638 | } |
639 | ||
ffa5899c OG |
640 | st->buf[0] = REQUEST_SET_RC; |
641 | st->buf[1] = 0; | |
642 | st->buf[2] = 0; | |
643 | ||
0ffd1ab3 | 644 | /* Set the IR mode */ |
c003ab1b | 645 | if (*rc_type & RC_BIT_RC5) { |
0ffd1ab3 | 646 | new_proto = 1; |
c003ab1b DH |
647 | *rc_type = RC_BIT_RC5; |
648 | } else if (*rc_type & RC_BIT_NEC) { | |
0ffd1ab3 | 649 | new_proto = 0; |
c003ab1b DH |
650 | *rc_type = RC_BIT_NEC; |
651 | } else if (*rc_type & RC_BIT_RC6_MCE) { | |
bff469f4 OG |
652 | if (st->fw_version < 0x10200) { |
653 | ret = -EINVAL; | |
654 | goto out; | |
655 | } | |
0ffd1ab3 | 656 | new_proto = 2; |
c003ab1b | 657 | *rc_type = RC_BIT_RC6_MCE; |
bff469f4 OG |
658 | } else { |
659 | ret = -EINVAL; | |
660 | goto out; | |
661 | } | |
0ffd1ab3 | 662 | |
ffa5899c | 663 | st->buf[1] = new_proto; |
0ffd1ab3 | 664 | |
ffa5899c | 665 | ret = dib0700_ctrl_wr(d, st->buf, 3); |
0ffd1ab3 MCC |
666 | if (ret < 0) { |
667 | err("ir protocol setup failed"); | |
bff469f4 | 668 | goto out; |
0ffd1ab3 MCC |
669 | } |
670 | ||
c003ab1b | 671 | d->props.rc.core.protocol = *rc_type; |
0ffd1ab3 | 672 | |
bff469f4 OG |
673 | out: |
674 | mutex_unlock(&d->usb_mutex); | |
0ffd1ab3 MCC |
675 | return ret; |
676 | } | |
677 | ||
6a207100 DH |
678 | /* This is the structure of the RC response packet starting in firmware 1.20 */ |
679 | struct dib0700_rc_response { | |
680 | u8 report_id; | |
681 | u8 data_state; | |
4d298b85 DH |
682 | union { |
683 | struct { | |
684 | u8 system; | |
685 | u8 not_system; | |
686 | u8 data; | |
687 | u8 not_data; | |
688 | } nec; | |
689 | struct { | |
690 | u8 not_used; | |
691 | u8 system; | |
692 | u8 data; | |
693 | u8 not_data; | |
694 | } rc5; | |
695 | }; | |
6a207100 DH |
696 | }; |
697 | #define RC_MSG_SIZE_V1_20 6 | |
698 | ||
699 | static void dib0700_rc_urb_completion(struct urb *purb) | |
700 | { | |
701 | struct dvb_usb_device *d = purb->context; | |
d3c501d1 | 702 | struct dib0700_rc_response *poll_reply; |
120703f9 | 703 | enum rc_type protocol; |
ba13e98f | 704 | u32 keycode; |
72b39310 | 705 | u8 toggle; |
6a207100 DH |
706 | |
707 | deb_info("%s()\n", __func__); | |
d8b4b582 | 708 | if (d->rc_dev == NULL) { |
6a207100 | 709 | /* This will occur if disable_rc_polling=1 */ |
d3db22e1 | 710 | kfree(purb->transfer_buffer); |
6a207100 DH |
711 | usb_free_urb(purb); |
712 | return; | |
713 | } | |
714 | ||
d3c501d1 | 715 | poll_reply = purb->transfer_buffer; |
6a207100 DH |
716 | |
717 | if (purb->status < 0) { | |
718 | deb_info("discontinuing polling\n"); | |
d3db22e1 | 719 | kfree(purb->transfer_buffer); |
6a207100 DH |
720 | usb_free_urb(purb); |
721 | return; | |
722 | } | |
723 | ||
724 | if (purb->actual_length != RC_MSG_SIZE_V1_20) { | |
725 | deb_info("malformed rc msg size=%d\n", purb->actual_length); | |
726 | goto resubmit; | |
727 | } | |
728 | ||
d3c501d1 MCC |
729 | deb_data("IR ID = %02X state = %02X System = %02X %02X Cmd = %02X %02X (len %d)\n", |
730 | poll_reply->report_id, poll_reply->data_state, | |
4d298b85 DH |
731 | poll_reply->nec.system, poll_reply->nec.not_system, |
732 | poll_reply->nec.data, poll_reply->nec.not_data, | |
d3c501d1 | 733 | purb->actual_length); |
6a207100 | 734 | |
0ffd1ab3 | 735 | switch (d->props.rc.core.protocol) { |
c003ab1b | 736 | case RC_BIT_NEC: |
72b39310 | 737 | toggle = 0; |
6a207100 DH |
738 | |
739 | /* NEC protocol sends repeat code as 0 0 0 FF */ | |
4d298b85 DH |
740 | if (poll_reply->nec.system == 0x00 && |
741 | poll_reply->nec.not_system == 0x00 && | |
742 | poll_reply->nec.data == 0x00 && | |
743 | poll_reply->nec.not_data == 0xff) { | |
d3c501d1 | 744 | poll_reply->data_state = 2; |
ba13e98f SY |
745 | rc_repeat(d->rc_dev); |
746 | goto resubmit; | |
6a207100 | 747 | } |
72b39310 | 748 | |
4d298b85 | 749 | if ((poll_reply->nec.data ^ poll_reply->nec.not_data) != 0xff) { |
af3a4a9b | 750 | deb_data("NEC32 protocol\n"); |
4d298b85 DH |
751 | keycode = RC_SCANCODE_NEC32(poll_reply->nec.system << 24 | |
752 | poll_reply->nec.not_system << 16 | | |
753 | poll_reply->nec.data << 8 | | |
754 | poll_reply->nec.not_data); | |
2ceeca04 | 755 | protocol = RC_TYPE_NEC32; |
4d298b85 | 756 | } else if ((poll_reply->nec.system ^ poll_reply->nec.not_system) != 0xff) { |
d3c501d1 | 757 | deb_data("NEC extended protocol\n"); |
4d298b85 DH |
758 | keycode = RC_SCANCODE_NECX(poll_reply->nec.system << 8 | |
759 | poll_reply->nec.not_system, | |
760 | poll_reply->nec.data); | |
120703f9 | 761 | |
2ceeca04 | 762 | protocol = RC_TYPE_NECX; |
d3c501d1 MCC |
763 | } else { |
764 | deb_data("NEC normal protocol\n"); | |
4d298b85 DH |
765 | keycode = RC_SCANCODE_NEC(poll_reply->nec.system, |
766 | poll_reply->nec.data); | |
2ceeca04 | 767 | protocol = RC_TYPE_NEC; |
d3c501d1 MCC |
768 | } |
769 | ||
6a207100 DH |
770 | break; |
771 | default: | |
d3c501d1 | 772 | deb_data("RC5 protocol\n"); |
120703f9 | 773 | protocol = RC_TYPE_RC5; |
d3c501d1 | 774 | toggle = poll_reply->report_id; |
4d298b85 DH |
775 | keycode = RC_SCANCODE_RC5(poll_reply->rc5.system, poll_reply->rc5.data); |
776 | ||
777 | if ((poll_reply->rc5.data ^ poll_reply->rc5.not_data) != 0xff) { | |
778 | /* Key failed integrity check */ | |
779 | err("key failed integrity check: %02x %02x %02x %02x", | |
780 | poll_reply->rc5.not_used, poll_reply->rc5.system, | |
781 | poll_reply->rc5.data, poll_reply->rc5.not_data); | |
782 | goto resubmit; | |
783 | } | |
72b39310 | 784 | |
6a207100 DH |
785 | break; |
786 | } | |
787 | ||
120703f9 | 788 | rc_keydown(d->rc_dev, protocol, keycode, toggle); |
6a207100 DH |
789 | |
790 | resubmit: | |
791 | /* Clean the buffer before we requeue */ | |
792 | memset(purb->transfer_buffer, 0, RC_MSG_SIZE_V1_20); | |
793 | ||
794 | /* Requeue URB */ | |
795 | usb_submit_urb(purb, GFP_ATOMIC); | |
796 | } | |
797 | ||
c4018fa2 | 798 | int dib0700_rc_setup(struct dvb_usb_device *d, struct usb_interface *intf) |
89f4267d | 799 | { |
6a207100 | 800 | struct dib0700_state *st = d->priv; |
6a207100 | 801 | struct urb *purb; |
c4018fa2 MCC |
802 | const struct usb_endpoint_descriptor *e; |
803 | int ret, rc_ep = 1; | |
804 | unsigned int pipe = 0; | |
6a207100 | 805 | |
0ffd1ab3 | 806 | /* Poll-based. Don't initialize bulk mode */ |
c4018fa2 | 807 | if (st->fw_version < 0x10200 || !intf) |
6a207100 DH |
808 | return 0; |
809 | ||
810 | /* Starting in firmware 1.20, the RC info is provided on a bulk pipe */ | |
c4018fa2 | 811 | |
d5823511 JH |
812 | if (intf->altsetting[0].desc.bNumEndpoints < rc_ep + 1) |
813 | return -ENODEV; | |
814 | ||
6a207100 | 815 | purb = usb_alloc_urb(0, GFP_KERNEL); |
abbde78f | 816 | if (purb == NULL) |
8871c85d | 817 | return -ENOMEM; |
6a207100 DH |
818 | |
819 | purb->transfer_buffer = kzalloc(RC_MSG_SIZE_V1_20, GFP_KERNEL); | |
820 | if (purb->transfer_buffer == NULL) { | |
24ed693d | 821 | err("rc kzalloc failed"); |
6a207100 | 822 | usb_free_urb(purb); |
8871c85d | 823 | return -ENOMEM; |
6a207100 DH |
824 | } |
825 | ||
826 | purb->status = -EINPROGRESS; | |
c4018fa2 MCC |
827 | |
828 | /* | |
829 | * Some devices like the Hauppauge NovaTD model 52009 use an interrupt | |
830 | * endpoint, while others use a bulk one. | |
831 | */ | |
832 | e = &intf->altsetting[0].endpoint[rc_ep].desc; | |
833 | if (usb_endpoint_dir_in(e)) { | |
834 | if (usb_endpoint_xfer_bulk(e)) { | |
835 | pipe = usb_rcvbulkpipe(d->udev, rc_ep); | |
836 | usb_fill_bulk_urb(purb, d->udev, pipe, | |
837 | purb->transfer_buffer, | |
838 | RC_MSG_SIZE_V1_20, | |
839 | dib0700_rc_urb_completion, d); | |
840 | ||
841 | } else if (usb_endpoint_xfer_int(e)) { | |
842 | pipe = usb_rcvintpipe(d->udev, rc_ep); | |
843 | usb_fill_int_urb(purb, d->udev, pipe, | |
844 | purb->transfer_buffer, | |
845 | RC_MSG_SIZE_V1_20, | |
846 | dib0700_rc_urb_completion, d, 1); | |
847 | } | |
848 | } | |
849 | ||
850 | if (!pipe) { | |
851 | err("There's no endpoint for remote controller"); | |
852 | kfree(purb->transfer_buffer); | |
853 | usb_free_urb(purb); | |
854 | return 0; | |
855 | } | |
6a207100 DH |
856 | |
857 | ret = usb_submit_urb(purb, GFP_ATOMIC); | |
d3db22e1 | 858 | if (ret) { |
24ed693d | 859 | err("rc submit urb failed"); |
d3db22e1 JD |
860 | kfree(purb->transfer_buffer); |
861 | usb_free_urb(purb); | |
862 | } | |
6a207100 | 863 | |
8871c85d | 864 | return ret; |
89f4267d JG |
865 | } |
866 | ||
b7f54910 PB |
867 | static int dib0700_probe(struct usb_interface *intf, |
868 | const struct usb_device_id *id) | |
869 | { | |
870 | int i; | |
89f4267d | 871 | struct dvb_usb_device *dev; |
b7f54910 PB |
872 | |
873 | for (i = 0; i < dib0700_device_count; i++) | |
78e92006 | 874 | if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, |
acc5c9ee OG |
875 | &dev, adapter_nr) == 0) { |
876 | struct dib0700_state *st = dev->priv; | |
877 | u32 hwversion, romversion, fw_version, fwtype; | |
878 | ||
879 | dib0700_get_version(dev, &hwversion, &romversion, | |
880 | &fw_version, &fwtype); | |
881 | ||
882 | deb_info("Firmware version: %x, %d, 0x%x, %d\n", | |
883 | hwversion, romversion, fw_version, fwtype); | |
884 | ||
885 | st->fw_version = fw_version; | |
886 | st->nb_packet_buffer_size = (u32)nb_packet_buffer_size; | |
887 | ||
72b39310 MCC |
888 | /* Disable polling mode on newer firmwares */ |
889 | if (st->fw_version >= 0x10200) | |
890 | dev->props.rc.core.bulk_mode = true; | |
891 | else | |
892 | dev->props.rc.core.bulk_mode = false; | |
893 | ||
c4018fa2 | 894 | dib0700_rc_setup(dev, intf); |
acc5c9ee | 895 | |
b7f54910 | 896 | return 0; |
89f4267d | 897 | } |
b7f54910 PB |
898 | |
899 | return -ENODEV; | |
900 | } | |
901 | ||
902 | static struct usb_driver dib0700_driver = { | |
903 | .name = "dvb_usb_dib0700", | |
904 | .probe = dib0700_probe, | |
905 | .disconnect = dvb_usb_device_exit, | |
906 | .id_table = dib0700_usb_id_table, | |
907 | }; | |
908 | ||
ecb3b2b3 | 909 | module_usb_driver(dib0700_driver); |
b7f54910 | 910 | |
68dc8bc5 | 911 | MODULE_FIRMWARE("dvb-usb-dib0700-1.20.fw"); |
99e44da7 | 912 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>"); |
b7f54910 PB |
913 | MODULE_DESCRIPTION("Driver for devices based on DiBcom DiB0700 - USB bridge"); |
914 | MODULE_VERSION("1.0"); | |
915 | MODULE_LICENSE("GPL"); |