diff options
Diffstat (limited to 'drivers/media/usb/dvb-usb/technisat-usb2.c')
| -rw-r--r-- | drivers/media/usb/dvb-usb/technisat-usb2.c | 153 |
1 files changed, 87 insertions, 66 deletions
diff --git a/drivers/media/usb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c index 40832a1aef6c..1e43aab2bc27 100644 --- a/drivers/media/usb/dvb-usb/technisat-usb2.c +++ b/drivers/media/usb/dvb-usb/technisat-usb2.c @@ -14,10 +14,6 @@ * License, or (at your option) any later version. * * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * * THIS PROGRAM IS PROVIDED "AS IS" AND BOTH THE COPYRIGHT HOLDER AND * TECHNISAT DIGITAL UK LTD DISCLAIM ALL WARRANTIES WITH REGARD TO * THIS PROGRAM INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY OR @@ -50,8 +46,7 @@ MODULE_PARM_DESC(debug, static int disable_led_control; module_param(disable_led_control, int, 0444); MODULE_PARM_DESC(disable_led_control, - "disable LED control of the device " - "(default: 0 - LED control is active)."); + "disable LED control of the device (default: 0 - LED control is active)."); /* device private data */ struct technisat_usb2_state { @@ -60,6 +55,8 @@ struct technisat_usb2_state { u8 power_state; u16 last_scan_code; + + u8 buf[64]; }; /* debug print helpers */ @@ -87,9 +84,13 @@ struct technisat_usb2_state { static int technisat_usb2_i2c_access(struct usb_device *udev, u8 device_addr, u8 *tx, u8 txlen, u8 *rx, u8 rxlen) { - u8 b[64]; + u8 *b; int ret, actual_length; + b = kmalloc(64, GFP_KERNEL); + if (!b) + return -ENOMEM; + deb_i2c("i2c-access: %02x, tx: ", device_addr); debug_dump(tx, txlen, deb_i2c); deb_i2c(" "); @@ -102,7 +103,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev, if (rxlen > 62) { err("i2c RX buffer can't exceed 62 bytes (dev 0x%02x)", device_addr); - txlen = 62; + rxlen = 62; } b[0] = I2C_SPEED_100KHZ_BIT; @@ -121,7 +122,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev, if (ret < 0) { err("i2c-error: out failed %02x = %d", device_addr, ret); - return -ENODEV; + goto err; } ret = usb_bulk_msg(udev, @@ -129,7 +130,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev, b, 64, &actual_length, 1000); if (ret < 0) { err("i2c-error: in failed %02x = %d", device_addr, ret); - return -ENODEV; + goto err; } if (b[0] != I2C_STATUS_OK) { @@ -138,7 +139,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev, if (!(b[0] == I2C_STATUS_NAK && device_addr == 0x60 /* && device_is_technisat_usb2 */)) - return -ENODEV; + goto err; } deb_i2c("status: %d, ", b[0]); @@ -152,7 +153,9 @@ static int technisat_usb2_i2c_access(struct usb_device *udev, deb_i2c("\n"); - return 0; +err: + kfree(b); + return ret; } static int technisat_usb2_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, @@ -196,7 +199,7 @@ static u32 technisat_usb2_i2c_func(struct i2c_adapter *adapter) return I2C_FUNC_I2C; } -static struct i2c_algorithm technisat_usb2_i2c_algo = { +static const struct i2c_algorithm technisat_usb2_i2c_algo = { .master_xfer = technisat_usb2_i2c_xfer, .functionality = technisat_usb2_i2c_func, }; @@ -214,29 +217,29 @@ static void technisat_usb2_frontend_reset(struct usb_device *udev) /* LED control */ enum technisat_usb2_led_state { - LED_OFF, - LED_BLINK, - LED_ON, - LED_UNDEFINED + TECH_LED_OFF, + TECH_LED_BLINK, + TECH_LED_ON, + TECH_LED_UNDEFINED }; -static int technisat_usb2_set_led(struct dvb_usb_device *d, int red, enum technisat_usb2_led_state state) +static int technisat_usb2_set_led(struct dvb_usb_device *d, int red, + enum technisat_usb2_led_state st) { + struct technisat_usb2_state *state = d->priv; + u8 *led = state->buf; int ret; - u8 led[8] = { - red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST, - 0 - }; + led[0] = red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST; - if (disable_led_control && state != LED_OFF) + if (disable_led_control && st != TECH_LED_OFF) return 0; - switch (state) { - case LED_ON: + switch (st) { + case TECH_LED_ON: led[1] = 0x82; break; - case LED_BLINK: + case TECH_LED_BLINK: led[1] = 0x82; if (red) { led[2] = 0x02; @@ -251,7 +254,7 @@ static int technisat_usb2_set_led(struct dvb_usb_device *d, int red, enum techni break; default: - case LED_OFF: + case TECH_LED_OFF: led[1] = 0x80; break; } @@ -263,7 +266,7 @@ static int technisat_usb2_set_led(struct dvb_usb_device *d, int red, enum techni red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST, USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, - led, sizeof(led), 500); + led, 8, 500); mutex_unlock(&d->i2c_mutex); return ret; @@ -271,8 +274,11 @@ static int technisat_usb2_set_led(struct dvb_usb_device *d, int red, enum techni static int technisat_usb2_set_led_timer(struct dvb_usb_device *d, u8 red, u8 green) { + struct technisat_usb2_state *state = d->priv; + u8 *b = state->buf; int ret; - u8 b = 0; + + b[0] = 0; if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; @@ -281,7 +287,7 @@ static int technisat_usb2_set_led_timer(struct dvb_usb_device *d, u8 red, u8 gre SET_LED_TIMER_DIVIDER_VENDOR_REQUEST, USB_TYPE_VENDOR | USB_DIR_OUT, (red << 8) | green, 0, - &b, 1, 500); + b, 1, 500); mutex_unlock(&d->i2c_mutex); @@ -310,11 +316,11 @@ static void technisat_usb2_green_led_control(struct work_struct *work) goto schedule; if (ber > 1000) - technisat_usb2_set_led(state->dev, 0, LED_BLINK); + technisat_usb2_set_led(state->dev, 0, TECH_LED_BLINK); else - technisat_usb2_set_led(state->dev, 0, LED_ON); + technisat_usb2_set_led(state->dev, 0, TECH_LED_ON); } else - technisat_usb2_set_led(state->dev, 0, LED_OFF); + technisat_usb2_set_led(state->dev, 0, TECH_LED_OFF); } schedule: @@ -324,11 +330,15 @@ schedule: /* method to find out whether the firmware has to be downloaded or not */ static int technisat_usb2_identify_state(struct usb_device *udev, - struct dvb_usb_device_properties *props, - struct dvb_usb_device_description **desc, int *cold) + const struct dvb_usb_device_properties *props, + const struct dvb_usb_device_description **desc, int *cold) { int ret; - u8 version[3]; + u8 *version; + + version = kmalloc(3, GFP_KERNEL); + if (!version) + return -ENOMEM; /* first select the interface */ if (usb_set_interface(udev, 0, 1) != 0) @@ -342,7 +352,7 @@ static int technisat_usb2_identify_state(struct usb_device *udev, GET_VERSION_INFO_VENDOR_REQUEST, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, - version, sizeof(version), 500); + version, 3, 500); if (ret < 0) *cold = 1; @@ -351,6 +361,8 @@ static int technisat_usb2_identify_state(struct usb_device *udev, *cold = 0; } + kfree(version); + return 0; } @@ -365,9 +377,9 @@ static int technisat_usb2_power_ctrl(struct dvb_usb_device *d, int level) return 0; /* green led is turned off in any case - will be turned on when tuning */ - technisat_usb2_set_led(d, 0, LED_OFF); + technisat_usb2_set_led(d, 0, TECH_LED_OFF); /* red led is turned on all the time */ - technisat_usb2_set_led(d, 1, LED_ON); + technisat_usb2_set_led(d, 1, TECH_LED_ON); return 0; } @@ -449,9 +461,11 @@ static int technisat_usb2_read_mac_address(struct dvb_usb_device *d, return 0; } +static struct stv090x_config technisat_usb2_stv090x_config; + /* frontend attach */ static int technisat_usb2_set_voltage(struct dvb_frontend *fe, - fe_sec_voltage_t voltage) + enum fe_sec_voltage voltage) { int i; u8 gpio[3] = { 0 }; /* 0 = 2, 1 = 3, 2 = 4 */ @@ -472,7 +486,8 @@ static int technisat_usb2_set_voltage(struct dvb_frontend *fe, } for (i = 0; i < 3; i++) - if (stv090x_set_gpio(fe, i+2, 0, gpio[i], 0) != 0) + if (technisat_usb2_stv090x_config.set_gpio(fe, i+2, 0, + gpio[i], 0) != 0) return -EREMOTEIO; return 0; } @@ -509,7 +524,7 @@ static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a) &a->dev->i2c_adap, STV090x_DEMODULATOR_0); if (a->fe_adap[0].fe) { - struct stv6110x_devctl *ctl; + const struct stv6110x_devctl *ctl; ctl = dvb_attach(stv6110x_attach, a->fe_adap[0].fe, @@ -551,8 +566,9 @@ static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a) a->fe_adap[0].fe->ops.set_voltage = technisat_usb2_set_voltage; /* if everything was successful assign a nice name to the frontend */ - strlcpy(a->fe_adap[0].fe->ops.info.name, a->dev->desc->name, - sizeof(a->fe_adap[0].fe->ops.info.name)); + strscpy(a->fe_adap[0].fe->ops.info.name, + a->dev->desc->name, + sizeof(a->fe_adap[0].fe->ops.info.name)); } else { dvb_frontend_detach(a->fe_adap[0].fe); a->fe_adap[0].fe = NULL; @@ -591,9 +607,10 @@ static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a) static int technisat_usb2_get_ir(struct dvb_usb_device *d) { - u8 buf[62], *b; - int ret; + struct technisat_usb2_state *state = d->priv; struct ir_raw_event ev; + u8 *buf = state->buf; + int i, ret; buf[0] = GET_IR_DATA_VENDOR_REQUEST; buf[1] = 0x08; @@ -617,7 +634,7 @@ static int technisat_usb2_get_ir(struct dvb_usb_device *d) GET_IR_DATA_VENDOR_REQUEST, USB_TYPE_VENDOR | USB_DIR_IN, 0x8080, 0, - buf, sizeof(buf), 500); + buf, 62, 500); unlock: mutex_unlock(&d->i2c_mutex); @@ -629,26 +646,25 @@ unlock: return 0; /* no key pressed */ /* decoding */ - b = buf+1; #if 0 deb_rc("RC: %d ", ret); - debug_dump(b, ret, deb_rc); + debug_dump(buf + 1, ret, deb_rc); #endif ev.pulse = 0; - while (1) { - ev.pulse = !ev.pulse; - ev.duration = (*b * FIRMWARE_CLOCK_DIVISOR * FIRMWARE_CLOCK_TICK) / 1000; - ir_raw_event_store(d->rc_dev, &ev); - - b++; - if (*b == 0xff) { + for (i = 1; i < ARRAY_SIZE(state->buf); i++) { + if (buf[i] == 0xff) { ev.pulse = 0; - ev.duration = 888888*2; + ev.duration = 889 * 2; ir_raw_event_store(d->rc_dev, &ev); break; } + + ev.pulse = !ev.pulse; + ev.duration = (buf[i] * FIRMWARE_CLOCK_DIVISOR * + FIRMWARE_CLOCK_TICK) / (1000 * 1000); + ir_raw_event_store(d->rc_dev, &ev); } ir_raw_event_handle(d->rc_dev); @@ -667,16 +683,21 @@ static int technisat_usb2_rc_query(struct dvb_usb_device *d) return 0; if (!disable_led_control) - technisat_usb2_set_led(d, 1, LED_BLINK); + technisat_usb2_set_led(d, 1, TECH_LED_BLINK); return 0; } /* DVB-USB and USB stuff follows */ -static struct usb_device_id technisat_usb2_id_table[] = { - { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_DVB_S2) }, - { 0 } /* Terminating entry */ +enum { + TECHNISAT_USB2_DVB_S2, }; + +static const struct usb_device_id technisat_usb2_id_table[] = { + DVB_USB_DEV(TECHNISAT, TECHNISAT_USB2_DVB_S2), + { } +}; + MODULE_DEVICE_TABLE(usb, technisat_usb2_id_table); /* device description */ @@ -704,13 +725,13 @@ static struct dvb_usb_device_properties technisat_usb2_devices = { .stream = { .type = USB_ISOC, - .count = 8, + .count = 4, .endpoint = 0x2, .u = { .isoc = { .framesperurb = 32, .framesize = 2048, - .interval = 3, + .interval = 1, } } }, @@ -722,7 +743,7 @@ static struct dvb_usb_device_properties technisat_usb2_devices = { .num_device_descs = 1, .devices = { { "Technisat SkyStar USB HD (DVB-S/S2)", - { &technisat_usb2_id_table[0], NULL }, + { &technisat_usb2_id_table[TECHNISAT_USB2_DVB_S2], NULL }, { NULL }, }, }, @@ -732,7 +753,7 @@ static struct dvb_usb_device_properties technisat_usb2_devices = { .rc_codes = RC_MAP_TECHNISAT_USB2, .module_name = "technisat-usb2", .rc_query = technisat_usb2_rc_query, - .allowed_protos = RC_BIT_ALL, + .allowed_protos = RC_PROTO_BIT_ALL_IR_DECODER, .driver_type = RC_DRIVER_IR_RAW, } }; @@ -765,7 +786,7 @@ static void technisat_usb2_disconnect(struct usb_interface *intf) { struct dvb_usb_device *dev = usb_get_intfdata(intf); - /* work and stuff was only created when the device is is hot-state */ + /* work and stuff was only created when the device is hot-state */ if (dev != NULL) { struct technisat_usb2_state *state = dev->priv; if (state != NULL) |
