Version:  2.0.40 2.2.26 2.4.37 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7

Linux/drivers/media/usb/dvb-usb/technisat-usb2.c

  1 /*
  2  * Linux driver for Technisat DVB-S/S2 USB 2.0 device
  3  *
  4  * Copyright (C) 2010 Patrick Boettcher,
  5  *                    Kernel Labs Inc. PO Box 745, St James, NY 11780
  6  *
  7  * Development was sponsored by Technisat Digital UK Limited, whose
  8  * registered office is Witan Gate House 500 - 600 Witan Gate West,
  9  * Milton Keynes, MK9 1SH
 10  *
 11  * This program is free software; you can redistribute it and/or
 12  * modify it under the terms of the GNU General Public License as
 13  * published by the Free Software Foundation; either version 2 of the
 14  * License, or (at your option) any later version.
 15  *
 16  *
 17  * You should have received a copy of the GNU General Public License
 18  * along with this program; if not, write to the Free Software
 19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20  *
 21  * THIS PROGRAM IS PROVIDED "AS IS" AND BOTH THE COPYRIGHT HOLDER AND
 22  * TECHNISAT DIGITAL UK LTD DISCLAIM ALL WARRANTIES WITH REGARD TO
 23  * THIS PROGRAM INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY OR
 24  * FITNESS FOR A PARTICULAR PURPOSE.  NEITHER THE COPYRIGHT HOLDER
 25  * NOR TECHNISAT DIGITAL UK LIMITED SHALL BE LIABLE FOR ANY SPECIAL,
 26  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
 27  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 28  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 29  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS PROGRAM. See the
 30  * GNU General Public License for more details.
 31  */
 32 
 33 #define DVB_USB_LOG_PREFIX "technisat-usb2"
 34 #include "dvb-usb.h"
 35 
 36 #include "stv6110x.h"
 37 #include "stv090x.h"
 38 
 39 /* module parameters */
 40 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 41 
 42 static int debug;
 43 module_param(debug, int, 0644);
 44 MODULE_PARM_DESC(debug,
 45                 "set debugging level (bit-mask: 1=info,2=eeprom,4=i2c,8=rc)." \
 46                 DVB_USB_DEBUG_STATUS);
 47 
 48 /* disables all LED control command and
 49  * also does not start the signal polling thread */
 50 static int disable_led_control;
 51 module_param(disable_led_control, int, 0444);
 52 MODULE_PARM_DESC(disable_led_control,
 53                 "disable LED control of the device "
 54                 "(default: 0 - LED control is active).");
 55 
 56 /* device private data */
 57 struct technisat_usb2_state {
 58         struct dvb_usb_device *dev;
 59         struct delayed_work green_led_work;
 60         u8 power_state;
 61 
 62         u16 last_scan_code;
 63 
 64         u8 buf[64];
 65 };
 66 
 67 /* debug print helpers */
 68 #define deb_info(args...)    dprintk(debug, 0x01, args)
 69 #define deb_eeprom(args...)  dprintk(debug, 0x02, args)
 70 #define deb_i2c(args...)     dprintk(debug, 0x04, args)
 71 #define deb_rc(args...)      dprintk(debug, 0x08, args)
 72 
 73 /* vendor requests */
 74 #define SET_IFCLK_TO_EXTERNAL_TSCLK_VENDOR_REQUEST 0xB3
 75 #define SET_FRONT_END_RESET_VENDOR_REQUEST         0xB4
 76 #define GET_VERSION_INFO_VENDOR_REQUEST            0xB5
 77 #define SET_GREEN_LED_VENDOR_REQUEST               0xB6
 78 #define SET_RED_LED_VENDOR_REQUEST                 0xB7
 79 #define GET_IR_DATA_VENDOR_REQUEST                 0xB8
 80 #define SET_LED_TIMER_DIVIDER_VENDOR_REQUEST       0xB9
 81 #define SET_USB_REENUMERATION                      0xBA
 82 
 83 /* i2c-access methods */
 84 #define I2C_SPEED_100KHZ_BIT 0x40
 85 
 86 #define I2C_STATUS_NAK 7
 87 #define I2C_STATUS_OK 8
 88 
 89 static int technisat_usb2_i2c_access(struct usb_device *udev,
 90                 u8 device_addr, u8 *tx, u8 txlen, u8 *rx, u8 rxlen)
 91 {
 92         u8 b[64];
 93         int ret, actual_length;
 94 
 95         deb_i2c("i2c-access: %02x, tx: ", device_addr);
 96         debug_dump(tx, txlen, deb_i2c);
 97         deb_i2c(" ");
 98 
 99         if (txlen > 62) {
100                 err("i2c TX buffer can't exceed 62 bytes (dev 0x%02x)",
101                                 device_addr);
102                 txlen = 62;
103         }
104         if (rxlen > 62) {
105                 err("i2c RX buffer can't exceed 62 bytes (dev 0x%02x)",
106                                 device_addr);
107                 rxlen = 62;
108         }
109 
110         b[0] = I2C_SPEED_100KHZ_BIT;
111         b[1] = device_addr << 1;
112 
113         if (rx != NULL) {
114                 b[0] |= rxlen;
115                 b[1] |= 1;
116         }
117 
118         memcpy(&b[2], tx, txlen);
119         ret = usb_bulk_msg(udev,
120                         usb_sndbulkpipe(udev, 0x01),
121                         b, 2 + txlen,
122                         NULL, 1000);
123 
124         if (ret < 0) {
125                 err("i2c-error: out failed %02x = %d", device_addr, ret);
126                 return -ENODEV;
127         }
128 
129         ret = usb_bulk_msg(udev,
130                         usb_rcvbulkpipe(udev, 0x01),
131                         b, 64, &actual_length, 1000);
132         if (ret < 0) {
133                 err("i2c-error: in failed %02x = %d", device_addr, ret);
134                 return -ENODEV;
135         }
136 
137         if (b[0] != I2C_STATUS_OK) {
138                 err("i2c-error: %02x = %d", device_addr, b[0]);
139                 /* handle tuner-i2c-nak */
140                 if (!(b[0] == I2C_STATUS_NAK &&
141                                 device_addr == 0x60
142                                 /* && device_is_technisat_usb2 */))
143                         return -ENODEV;
144         }
145 
146         deb_i2c("status: %d, ", b[0]);
147 
148         if (rx != NULL) {
149                 memcpy(rx, &b[2], rxlen);
150 
151                 deb_i2c("rx (%d): ", rxlen);
152                 debug_dump(rx, rxlen, deb_i2c);
153         }
154 
155         deb_i2c("\n");
156 
157         return 0;
158 }
159 
160 static int technisat_usb2_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
161                                 int num)
162 {
163         int ret = 0, i;
164         struct dvb_usb_device *d = i2c_get_adapdata(adap);
165 
166         /* Ensure nobody else hits the i2c bus while we're sending our
167            sequence of messages, (such as the remote control thread) */
168         if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
169                 return -EAGAIN;
170 
171         for (i = 0; i < num; i++) {
172                 if (i+1 < num && msg[i+1].flags & I2C_M_RD) {
173                         ret = technisat_usb2_i2c_access(d->udev, msg[i+1].addr,
174                                                 msg[i].buf, msg[i].len,
175                                                 msg[i+1].buf, msg[i+1].len);
176                         if (ret != 0)
177                                 break;
178                         i++;
179                 } else {
180                         ret = technisat_usb2_i2c_access(d->udev, msg[i].addr,
181                                                 msg[i].buf, msg[i].len,
182                                                 NULL, 0);
183                         if (ret != 0)
184                                 break;
185                 }
186         }
187 
188         if (ret == 0)
189                 ret = i;
190 
191         mutex_unlock(&d->i2c_mutex);
192 
193         return ret;
194 }
195 
196 static u32 technisat_usb2_i2c_func(struct i2c_adapter *adapter)
197 {
198         return I2C_FUNC_I2C;
199 }
200 
201 static struct i2c_algorithm technisat_usb2_i2c_algo = {
202         .master_xfer   = technisat_usb2_i2c_xfer,
203         .functionality = technisat_usb2_i2c_func,
204 };
205 
206 #if 0
207 static void technisat_usb2_frontend_reset(struct usb_device *udev)
208 {
209         usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
210                         SET_FRONT_END_RESET_VENDOR_REQUEST,
211                         USB_TYPE_VENDOR | USB_DIR_OUT,
212                         10, 0,
213                         NULL, 0, 500);
214 }
215 #endif
216 
217 /* LED control */
218 enum technisat_usb2_led_state {
219         TECH_LED_OFF,
220         TECH_LED_BLINK,
221         TECH_LED_ON,
222         TECH_LED_UNDEFINED
223 };
224 
225 static int technisat_usb2_set_led(struct dvb_usb_device *d, int red,
226                                   enum technisat_usb2_led_state st)
227 {
228         struct technisat_usb2_state *state = d->priv;
229         u8 *led = state->buf;
230         int ret;
231 
232         led[0] = red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST;
233 
234         if (disable_led_control && st != TECH_LED_OFF)
235                 return 0;
236 
237         switch (st) {
238         case TECH_LED_ON:
239                 led[1] = 0x82;
240                 break;
241         case TECH_LED_BLINK:
242                 led[1] = 0x82;
243                 if (red) {
244                         led[2] = 0x02;
245                         led[3] = 10;
246                         led[4] = 10;
247                 } else {
248                         led[2] = 0xff;
249                         led[3] = 50;
250                         led[4] = 50;
251                 }
252                 led[5] = 1;
253                 break;
254 
255         default:
256         case TECH_LED_OFF:
257                 led[1] = 0x80;
258                 break;
259         }
260 
261         if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
262                 return -EAGAIN;
263 
264         ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
265                 red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST,
266                 USB_TYPE_VENDOR | USB_DIR_OUT,
267                 0, 0,
268                 led, 8, 500);
269 
270         mutex_unlock(&d->i2c_mutex);
271         return ret;
272 }
273 
274 static int technisat_usb2_set_led_timer(struct dvb_usb_device *d, u8 red, u8 green)
275 {
276         struct technisat_usb2_state *state = d->priv;
277         u8 *b = state->buf;
278         int ret;
279 
280         b[0] = 0;
281 
282         if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
283                 return -EAGAIN;
284 
285         ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
286                 SET_LED_TIMER_DIVIDER_VENDOR_REQUEST,
287                 USB_TYPE_VENDOR | USB_DIR_OUT,
288                 (red << 8) | green, 0,
289                 b, 1, 500);
290 
291         mutex_unlock(&d->i2c_mutex);
292 
293         return ret;
294 }
295 
296 static void technisat_usb2_green_led_control(struct work_struct *work)
297 {
298         struct technisat_usb2_state *state =
299                 container_of(work, struct technisat_usb2_state, green_led_work.work);
300         struct dvb_frontend *fe = state->dev->adapter[0].fe_adap[0].fe;
301 
302         if (state->power_state == 0)
303                 goto schedule;
304 
305         if (fe != NULL) {
306                 enum fe_status status;
307 
308                 if (fe->ops.read_status(fe, &status) != 0)
309                         goto schedule;
310 
311                 if (status & FE_HAS_LOCK) {
312                         u32 ber;
313 
314                         if (fe->ops.read_ber(fe, &ber) != 0)
315                                 goto schedule;
316 
317                         if (ber > 1000)
318                                 technisat_usb2_set_led(state->dev, 0, TECH_LED_BLINK);
319                         else
320                                 technisat_usb2_set_led(state->dev, 0, TECH_LED_ON);
321                 } else
322                         technisat_usb2_set_led(state->dev, 0, TECH_LED_OFF);
323         }
324 
325 schedule:
326         schedule_delayed_work(&state->green_led_work,
327                         msecs_to_jiffies(500));
328 }
329 
330 /* method to find out whether the firmware has to be downloaded or not */
331 static int technisat_usb2_identify_state(struct usb_device *udev,
332                 struct dvb_usb_device_properties *props,
333                 struct dvb_usb_device_description **desc, int *cold)
334 {
335         int ret;
336         u8 *version;
337 
338         version = kmalloc(3, GFP_KERNEL);
339         if (!version)
340                 return -ENOMEM;
341 
342         /* first select the interface */
343         if (usb_set_interface(udev, 0, 1) != 0)
344                 err("could not set alternate setting to 0");
345         else
346                 info("set alternate setting");
347 
348         *cold = 0; /* by default do not download a firmware - just in case something is wrong */
349 
350         ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
351                 GET_VERSION_INFO_VENDOR_REQUEST,
352                 USB_TYPE_VENDOR | USB_DIR_IN,
353                 0, 0,
354                 version, 3, 500);
355 
356         if (ret < 0)
357                 *cold = 1;
358         else {
359                 info("firmware version: %d.%d", version[1], version[2]);
360                 *cold = 0;
361         }
362 
363         kfree(version);
364 
365         return 0;
366 }
367 
368 /* power control */
369 static int technisat_usb2_power_ctrl(struct dvb_usb_device *d, int level)
370 {
371         struct technisat_usb2_state *state = d->priv;
372 
373         state->power_state = level;
374 
375         if (disable_led_control)
376                 return 0;
377 
378         /* green led is turned off in any case - will be turned on when tuning */
379         technisat_usb2_set_led(d, 0, TECH_LED_OFF);
380         /* red led is turned on all the time */
381         technisat_usb2_set_led(d, 1, TECH_LED_ON);
382         return 0;
383 }
384 
385 /* mac address reading - from the eeprom */
386 #if 0
387 static void technisat_usb2_eeprom_dump(struct dvb_usb_device *d)
388 {
389         u8 reg;
390         u8 b[16];
391         int i, j;
392 
393         /* full EEPROM dump */
394         for (j = 0; j < 256 * 4; j += 16) {
395                 reg = j;
396                 if (technisat_usb2_i2c_access(d->udev, 0x50 + j / 256, &reg, 1, b, 16) != 0)
397                         break;
398 
399                 deb_eeprom("EEPROM: %01x%02x: ", j / 256, reg);
400                 for (i = 0; i < 16; i++)
401                         deb_eeprom("%02x ", b[i]);
402                 deb_eeprom("\n");
403         }
404 }
405 #endif
406 
407 static u8 technisat_usb2_calc_lrc(const u8 *b, u16 length)
408 {
409         u8 lrc = 0;
410         while (--length)
411                 lrc ^= *b++;
412         return lrc;
413 }
414 
415 static int technisat_usb2_eeprom_lrc_read(struct dvb_usb_device *d,
416         u16 offset, u8 *b, u16 length, u8 tries)
417 {
418         u8 bo = offset & 0xff;
419         struct i2c_msg msg[] = {
420                 {
421                         .addr = 0x50 | ((offset >> 8) & 0x3),
422                         .buf = &bo,
423                         .len = 1
424                 }, {
425                         .addr = 0x50 | ((offset >> 8) & 0x3),
426                         .flags  = I2C_M_RD,
427                         .buf = b,
428                         .len = length
429                 }
430         };
431 
432         while (tries--) {
433                 int status;
434 
435                 if (i2c_transfer(&d->i2c_adap, msg, 2) != 2)
436                         break;
437 
438                 status =
439                         technisat_usb2_calc_lrc(b, length - 1) == b[length - 1];
440 
441                 if (status)
442                         return 0;
443         }
444 
445         return -EREMOTEIO;
446 }
447 
448 #define EEPROM_MAC_START 0x3f8
449 #define EEPROM_MAC_TOTAL 8
450 static int technisat_usb2_read_mac_address(struct dvb_usb_device *d,
451                 u8 mac[])
452 {
453         u8 buf[EEPROM_MAC_TOTAL];
454 
455         if (technisat_usb2_eeprom_lrc_read(d, EEPROM_MAC_START,
456                                 buf, EEPROM_MAC_TOTAL, 4) != 0)
457                 return -ENODEV;
458 
459         memcpy(mac, buf, 6);
460         return 0;
461 }
462 
463 static struct stv090x_config technisat_usb2_stv090x_config;
464 
465 /* frontend attach */
466 static int technisat_usb2_set_voltage(struct dvb_frontend *fe,
467                                       enum fe_sec_voltage voltage)
468 {
469         int i;
470         u8 gpio[3] = { 0 }; /* 0 = 2, 1 = 3, 2 = 4 */
471 
472         gpio[2] = 1; /* high - voltage ? */
473 
474         switch (voltage) {
475         case SEC_VOLTAGE_13:
476                 gpio[0] = 1;
477                 break;
478         case SEC_VOLTAGE_18:
479                 gpio[0] = 1;
480                 gpio[1] = 1;
481                 break;
482         default:
483         case SEC_VOLTAGE_OFF:
484                 break;
485         }
486 
487         for (i = 0; i < 3; i++)
488                 if (technisat_usb2_stv090x_config.set_gpio(fe, i+2, 0,
489                                                            gpio[i], 0) != 0)
490                         return -EREMOTEIO;
491         return 0;
492 }
493 
494 static struct stv090x_config technisat_usb2_stv090x_config = {
495         .device         = STV0903,
496         .demod_mode     = STV090x_SINGLE,
497         .clk_mode       = STV090x_CLK_EXT,
498 
499         .xtal           = 8000000,
500         .address        = 0x68,
501 
502         .ts1_mode       = STV090x_TSMODE_DVBCI,
503         .ts1_clk        = 13400000,
504         .ts1_tei        = 1,
505 
506         .repeater_level = STV090x_RPTLEVEL_64,
507 
508         .tuner_bbgain   = 6,
509 };
510 
511 static struct stv6110x_config technisat_usb2_stv6110x_config = {
512         .addr           = 0x60,
513         .refclk         = 16000000,
514         .clk_div        = 2,
515 };
516 
517 static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a)
518 {
519         struct usb_device *udev = a->dev->udev;
520         int ret;
521 
522         a->fe_adap[0].fe = dvb_attach(stv090x_attach, &technisat_usb2_stv090x_config,
523                         &a->dev->i2c_adap, STV090x_DEMODULATOR_0);
524 
525         if (a->fe_adap[0].fe) {
526                 const struct stv6110x_devctl *ctl;
527 
528                 ctl = dvb_attach(stv6110x_attach,
529                                 a->fe_adap[0].fe,
530                                 &technisat_usb2_stv6110x_config,
531                                 &a->dev->i2c_adap);
532 
533                 if (ctl) {
534                         technisat_usb2_stv090x_config.tuner_init          = ctl->tuner_init;
535                         technisat_usb2_stv090x_config.tuner_sleep         = ctl->tuner_sleep;
536                         technisat_usb2_stv090x_config.tuner_set_mode      = ctl->tuner_set_mode;
537                         technisat_usb2_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency;
538                         technisat_usb2_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency;
539                         technisat_usb2_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth;
540                         technisat_usb2_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth;
541                         technisat_usb2_stv090x_config.tuner_set_bbgain    = ctl->tuner_set_bbgain;
542                         technisat_usb2_stv090x_config.tuner_get_bbgain    = ctl->tuner_get_bbgain;
543                         technisat_usb2_stv090x_config.tuner_set_refclk    = ctl->tuner_set_refclk;
544                         technisat_usb2_stv090x_config.tuner_get_status    = ctl->tuner_get_status;
545 
546                         /* call the init function once to initialize
547                            tuner's clock output divider and demod's
548                            master clock */
549                         if (a->fe_adap[0].fe->ops.init)
550                                 a->fe_adap[0].fe->ops.init(a->fe_adap[0].fe);
551 
552                         if (mutex_lock_interruptible(&a->dev->i2c_mutex) < 0)
553                                 return -EAGAIN;
554 
555                         ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
556                                         SET_IFCLK_TO_EXTERNAL_TSCLK_VENDOR_REQUEST,
557                                         USB_TYPE_VENDOR | USB_DIR_OUT,
558                                         0, 0,
559                                         NULL, 0, 500);
560                         mutex_unlock(&a->dev->i2c_mutex);
561 
562                         if (ret != 0)
563                                 err("could not set IF_CLK to external");
564 
565                         a->fe_adap[0].fe->ops.set_voltage = technisat_usb2_set_voltage;
566 
567                         /* if everything was successful assign a nice name to the frontend */
568                         strlcpy(a->fe_adap[0].fe->ops.info.name, a->dev->desc->name,
569                                         sizeof(a->fe_adap[0].fe->ops.info.name));
570                 } else {
571                         dvb_frontend_detach(a->fe_adap[0].fe);
572                         a->fe_adap[0].fe = NULL;
573                 }
574         }
575 
576         technisat_usb2_set_led_timer(a->dev, 1, 1);
577 
578         return a->fe_adap[0].fe == NULL ? -ENODEV : 0;
579 }
580 
581 /* Remote control */
582 
583 /* the device is giving providing raw IR-signals to the host mapping
584  * it only to one remote control is just the default implementation
585  */
586 #define NOMINAL_IR_BIT_TRANSITION_TIME_US 889
587 #define NOMINAL_IR_BIT_TIME_US (2 * NOMINAL_IR_BIT_TRANSITION_TIME_US)
588 
589 #define FIRMWARE_CLOCK_TICK 83333
590 #define FIRMWARE_CLOCK_DIVISOR 256
591 
592 #define IR_PERCENT_TOLERANCE 15
593 
594 #define NOMINAL_IR_BIT_TRANSITION_TICKS ((NOMINAL_IR_BIT_TRANSITION_TIME_US * 1000 * 1000) / FIRMWARE_CLOCK_TICK)
595 #define NOMINAL_IR_BIT_TRANSITION_TICK_COUNT (NOMINAL_IR_BIT_TRANSITION_TICKS / FIRMWARE_CLOCK_DIVISOR)
596 
597 #define NOMINAL_IR_BIT_TIME_TICKS ((NOMINAL_IR_BIT_TIME_US * 1000 * 1000) / FIRMWARE_CLOCK_TICK)
598 #define NOMINAL_IR_BIT_TIME_TICK_COUNT (NOMINAL_IR_BIT_TIME_TICKS / FIRMWARE_CLOCK_DIVISOR)
599 
600 #define MINIMUM_IR_BIT_TRANSITION_TICK_COUNT (NOMINAL_IR_BIT_TRANSITION_TICK_COUNT - ((NOMINAL_IR_BIT_TRANSITION_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100))
601 #define MAXIMUM_IR_BIT_TRANSITION_TICK_COUNT (NOMINAL_IR_BIT_TRANSITION_TICK_COUNT + ((NOMINAL_IR_BIT_TRANSITION_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100))
602 
603 #define MINIMUM_IR_BIT_TIME_TICK_COUNT (NOMINAL_IR_BIT_TIME_TICK_COUNT - ((NOMINAL_IR_BIT_TIME_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100))
604 #define MAXIMUM_IR_BIT_TIME_TICK_COUNT (NOMINAL_IR_BIT_TIME_TICK_COUNT + ((NOMINAL_IR_BIT_TIME_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100))
605 
606 static int technisat_usb2_get_ir(struct dvb_usb_device *d)
607 {
608         struct technisat_usb2_state *state = d->priv;
609         u8 *buf = state->buf;
610         u8 *b;
611         int ret;
612         struct ir_raw_event ev;
613 
614         buf[0] = GET_IR_DATA_VENDOR_REQUEST;
615         buf[1] = 0x08;
616         buf[2] = 0x8f;
617         buf[3] = MINIMUM_IR_BIT_TRANSITION_TICK_COUNT;
618         buf[4] = MAXIMUM_IR_BIT_TIME_TICK_COUNT;
619 
620         if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
621                 return -EAGAIN;
622         ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
623                         GET_IR_DATA_VENDOR_REQUEST,
624                         USB_TYPE_VENDOR | USB_DIR_OUT,
625                         0, 0,
626                         buf, 5, 500);
627         if (ret < 0)
628                 goto unlock;
629 
630         buf[1] = 0;
631         buf[2] = 0;
632         ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
633                         GET_IR_DATA_VENDOR_REQUEST,
634                         USB_TYPE_VENDOR | USB_DIR_IN,
635                         0x8080, 0,
636                         buf, 62, 500);
637 
638 unlock:
639         mutex_unlock(&d->i2c_mutex);
640 
641         if (ret < 0)
642                 return ret;
643 
644         if (ret == 1)
645                 return 0; /* no key pressed */
646 
647         /* decoding */
648         b = buf+1;
649 
650 #if 0
651         deb_rc("RC: %d ", ret);
652         debug_dump(b, ret, deb_rc);
653 #endif
654 
655         ev.pulse = 0;
656         while (1) {
657                 ev.pulse = !ev.pulse;
658                 ev.duration = (*b * FIRMWARE_CLOCK_DIVISOR * FIRMWARE_CLOCK_TICK) / 1000;
659                 ir_raw_event_store(d->rc_dev, &ev);
660 
661                 b++;
662                 if (*b == 0xff) {
663                         ev.pulse = 0;
664                         ev.duration = 888888*2;
665                         ir_raw_event_store(d->rc_dev, &ev);
666                         break;
667                 }
668         }
669 
670         ir_raw_event_handle(d->rc_dev);
671 
672         return 1;
673 }
674 
675 static int technisat_usb2_rc_query(struct dvb_usb_device *d)
676 {
677         int ret = technisat_usb2_get_ir(d);
678 
679         if (ret < 0)
680                 return ret;
681 
682         if (ret == 0)
683                 return 0;
684 
685         if (!disable_led_control)
686                 technisat_usb2_set_led(d, 1, TECH_LED_BLINK);
687 
688         return 0;
689 }
690 
691 /* DVB-USB and USB stuff follows */
692 static struct usb_device_id technisat_usb2_id_table[] = {
693         { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_DVB_S2) },
694         { 0 }           /* Terminating entry */
695 };
696 MODULE_DEVICE_TABLE(usb, technisat_usb2_id_table);
697 
698 /* device description */
699 static struct dvb_usb_device_properties technisat_usb2_devices = {
700         .caps              = DVB_USB_IS_AN_I2C_ADAPTER,
701 
702         .usb_ctrl          = CYPRESS_FX2,
703 
704         .identify_state    = technisat_usb2_identify_state,
705         .firmware          = "dvb-usb-SkyStar_USB_HD_FW_v17_63.HEX.fw",
706 
707         .size_of_priv      = sizeof(struct technisat_usb2_state),
708 
709         .i2c_algo          = &technisat_usb2_i2c_algo,
710 
711         .power_ctrl        = technisat_usb2_power_ctrl,
712         .read_mac_address  = technisat_usb2_read_mac_address,
713 
714         .num_adapters = 1,
715         .adapter = {
716                 {
717                 .num_frontends = 1,
718                 .fe = {{
719                         .frontend_attach  = technisat_usb2_frontend_attach,
720 
721                         .stream = {
722                                 .type = USB_ISOC,
723                                 .count = 4,
724                                 .endpoint = 0x2,
725                                 .u = {
726                                         .isoc = {
727                                                 .framesperurb = 32,
728                                                 .framesize = 2048,
729                                                 .interval = 1,
730                                         }
731                                 }
732                         },
733                 }},
734                         .size_of_priv = 0,
735                 },
736         },
737 
738         .num_device_descs = 1,
739         .devices = {
740                 {   "Technisat SkyStar USB HD (DVB-S/S2)",
741                         { &technisat_usb2_id_table[0], NULL },
742                         { NULL },
743                 },
744         },
745 
746         .rc.core = {
747                 .rc_interval = 100,
748                 .rc_codes    = RC_MAP_TECHNISAT_USB2,
749                 .module_name = "technisat-usb2",
750                 .rc_query    = technisat_usb2_rc_query,
751                 .allowed_protos = RC_BIT_ALL,
752                 .driver_type    = RC_DRIVER_IR_RAW,
753         }
754 };
755 
756 static int technisat_usb2_probe(struct usb_interface *intf,
757                 const struct usb_device_id *id)
758 {
759         struct dvb_usb_device *dev;
760 
761         if (dvb_usb_device_init(intf, &technisat_usb2_devices, THIS_MODULE,
762                                 &dev, adapter_nr) != 0)
763                 return -ENODEV;
764 
765         if (dev) {
766                 struct technisat_usb2_state *state = dev->priv;
767                 state->dev = dev;
768 
769                 if (!disable_led_control) {
770                         INIT_DELAYED_WORK(&state->green_led_work,
771                                         technisat_usb2_green_led_control);
772                         schedule_delayed_work(&state->green_led_work,
773                                         msecs_to_jiffies(500));
774                 }
775         }
776 
777         return 0;
778 }
779 
780 static void technisat_usb2_disconnect(struct usb_interface *intf)
781 {
782         struct dvb_usb_device *dev = usb_get_intfdata(intf);
783 
784         /* work and stuff was only created when the device is is hot-state */
785         if (dev != NULL) {
786                 struct technisat_usb2_state *state = dev->priv;
787                 if (state != NULL)
788                         cancel_delayed_work_sync(&state->green_led_work);
789         }
790 
791         dvb_usb_device_exit(intf);
792 }
793 
794 static struct usb_driver technisat_usb2_driver = {
795         .name       = "dvb_usb_technisat_usb2",
796         .probe      = technisat_usb2_probe,
797         .disconnect = technisat_usb2_disconnect,
798         .id_table   = technisat_usb2_id_table,
799 };
800 
801 module_usb_driver(technisat_usb2_driver);
802 
803 MODULE_AUTHOR("Patrick Boettcher <pboettcher@kernellabs.com>");
804 MODULE_DESCRIPTION("Driver for Technisat DVB-S/S2 USB 2.0 device");
805 MODULE_VERSION("1.0");
806 MODULE_LICENSE("GPL");
807 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us