diff options
Diffstat (limited to 'drivers/media/usb/dvb-usb/pctv452e.c')
| -rw-r--r-- | drivers/media/usb/dvb-usb/pctv452e.c | 188 |
1 files changed, 119 insertions, 69 deletions
diff --git a/drivers/media/usb/dvb-usb/pctv452e.c b/drivers/media/usb/dvb-usb/pctv452e.c index 449a99605a87..bc7a224d829e 100644 --- a/drivers/media/usb/dvb-usb/pctv452e.c +++ b/drivers/media/usb/dvb-usb/pctv452e.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * PCTV 452e DVB driver * @@ -5,11 +6,6 @@ * * TT connect S2-3650-CI Common Interface support, MAC readout * Copyright (C) 2008 Michael H. Schimek <mschimek@gmx.at> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. */ /* dvb usb framework */ @@ -24,11 +20,14 @@ #include "stb6100.h" #include "stb6100_cfg.h" /* FE Power */ +#include "isl6423.h" #include "lnbp22.h" -#include "dvb_ca_en50221.h" +#include <media/dvb_ca_en50221.h> #include "ttpci-eeprom.h" +#include <linux/etherdevice.h> + static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); @@ -87,6 +86,13 @@ static struct stb0899_postproc pctv45e_postproc[] = { { 0, 0 } }; +static struct isl6423_config pctv452e_isl6423_config = { + .current_max = SEC_CURRENT_515m, + .curlim = SEC_CURRENT_LIM_ON, + .mod_extern = 1, + .addr = 0x08, +}; + /* * stores all private variables for communication with the PCTV452e DVB-S2 */ @@ -102,15 +108,20 @@ struct pctv452e_state { static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len) { - struct pctv452e_state *state = (struct pctv452e_state *)d->priv; - u8 buf[64]; + struct pctv452e_state *state = d->priv; + u8 *buf; u8 id; unsigned int rlen; int ret; - BUG_ON(NULL == data && 0 != (write_len | read_len)); - BUG_ON(write_len > 64 - 4); - BUG_ON(read_len > 64 - 4); + if (!data || (write_len > 64 - 4) || (read_len > 64 - 4)) { + err("%s: transfer data invalid", __func__); + return -EIO; + } + + buf = kmalloc(64, GFP_KERNEL); + if (!buf) + return -ENOMEM; id = state->c++; @@ -133,12 +144,14 @@ static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, memcpy(data, buf + 4, read_len); + kfree(buf); return 0; failed: err("CI error %d; %02X %02X %02X -> %*ph.", ret, SYNC_BYTE_OUT, id, cmd, 3, buf); + kfree(buf); return ret; } @@ -146,8 +159,8 @@ static int tt3650_ci_msg_locked(struct dvb_ca_en50221 *ca, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct pctv452e_state *state = (struct pctv452e_state *)d->priv; + struct dvb_usb_device *d = ca->data; + struct pctv452e_state *state = d->priv; int ret; mutex_lock(&state->ca_mutex); @@ -279,8 +292,8 @@ static int tt3650_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) static int tt3650_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot) { - struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data; - struct pctv452e_state *state = (struct pctv452e_state *)d->priv; + struct dvb_usb_device *d = ca->data; + struct pctv452e_state *state = d->priv; u8 buf[1]; int ret; @@ -348,7 +361,7 @@ static void tt3650_ci_uninit(struct dvb_usb_device *d) if (NULL == d) return; - state = (struct pctv452e_state *)d->priv; + state = d->priv; if (NULL == state) return; @@ -366,7 +379,7 @@ static void tt3650_ci_uninit(struct dvb_usb_device *d) static int tt3650_ci_init(struct dvb_usb_adapter *a) { struct dvb_usb_device *d = a->dev; - struct pctv452e_state *state = (struct pctv452e_state *)d->priv; + struct pctv452e_state *state = d->priv; int ret; ci_dbg("%s", __func__); @@ -404,16 +417,19 @@ static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr, const u8 *snd_buf, u8 snd_len, u8 *rcv_buf, u8 rcv_len) { - struct pctv452e_state *state = (struct pctv452e_state *)d->priv; - u8 buf[64]; + struct pctv452e_state *state = d->priv; + u8 *buf; u8 id; int ret; - id = state->c++; - - ret = -EINVAL; if (snd_len > 64 - 7 || rcv_len > 64 - 7) - goto failed; + return -EINVAL; + + buf = kmalloc(64, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + id = state->c++; buf[0] = SYNC_BYTE_OUT; buf[1] = id; @@ -443,14 +459,15 @@ static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr, memcpy(rcv_buf, buf + 7, rcv_len); + kfree(buf); return rcv_len; failed: - err("I2C error %d; %02X %02X %02X %02X %02X -> " - "%02X %02X %02X %02X %02X.", + err("I2C error %d; %02X %02X %02X %02X %02X -> %*ph", ret, SYNC_BYTE_OUT, id, addr << 1, snd_len, rcv_len, - buf[0], buf[1], buf[4], buf[5], buf[6]); + 7, buf); + kfree(buf); return ret; } @@ -498,9 +515,8 @@ static u32 pctv452e_i2c_func(struct i2c_adapter *adapter) static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i) { - struct pctv452e_state *state = (struct pctv452e_state *)d->priv; - u8 b0[] = { 0xaa, 0, PCTV_CMD_RESET, 1, 0 }; - u8 rx[PCTV_ANSWER_LEN]; + struct pctv452e_state *state = d->priv; + u8 *b0, *rx; int ret; info("%s: %d\n", __func__, i); @@ -511,38 +527,57 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i) if (state->initialized) return 0; - /* hmm where shoud this should go? */ + b0 = kmalloc(5 + PCTV_ANSWER_LEN, GFP_KERNEL); + if (!b0) + return -ENOMEM; + + rx = b0 + 5; + + /* hmm where should this should go? */ ret = usb_set_interface(d->udev, 0, ISOC_INTERFACE_ALTERNATIVE); if (ret != 0) info("%s: Warning set interface returned: %d\n", __func__, ret); - /* this is a one-time initialization, dont know where to put */ + /* this is a one-time initialization, don't know where to put */ + b0[0] = 0xaa; b0[1] = state->c++; + b0[2] = PCTV_CMD_RESET; + b0[3] = 1; + b0[4] = 0; /* reset board */ - ret = dvb_usb_generic_rw(d, b0, sizeof(b0), rx, PCTV_ANSWER_LEN, 0); + ret = dvb_usb_generic_rw(d, b0, 5, rx, PCTV_ANSWER_LEN, 0); if (ret) - return ret; + goto ret; b0[1] = state->c++; b0[4] = 1; /* reset board (again?) */ - ret = dvb_usb_generic_rw(d, b0, sizeof(b0), rx, PCTV_ANSWER_LEN, 0); + ret = dvb_usb_generic_rw(d, b0, 5, rx, PCTV_ANSWER_LEN, 0); if (ret) - return ret; + goto ret; state->initialized = 1; - return 0; +ret: + kfree(b0); + return ret; } static int pctv452e_rc_query(struct dvb_usb_device *d) { - struct pctv452e_state *state = (struct pctv452e_state *)d->priv; - u8 b[CMD_BUFFER_SIZE]; - u8 rx[PCTV_ANSWER_LEN]; + struct pctv452e_state *state = d->priv; + u8 *b, *rx; int ret, i; - u8 id = state->c++; + u8 id; + + b = kmalloc(CMD_BUFFER_SIZE + PCTV_ANSWER_LEN, GFP_KERNEL); + if (!b) + return -ENOMEM; + + rx = b + CMD_BUFFER_SIZE; + + id = state->c++; /* prepare command header */ b[0] = SYNC_BYTE_OUT; @@ -553,7 +588,7 @@ static int pctv452e_rc_query(struct dvb_usb_device *d) /* send ir request */ ret = dvb_usb_generic_rw(d, b, 4, rx, PCTV_ANSWER_LEN, 0); if (ret != 0) - return ret; + goto ret; if (debug > 3) { info("%s: read: %2d: %*ph: ", __func__, ret, 3, rx); @@ -565,18 +600,19 @@ static int pctv452e_rc_query(struct dvb_usb_device *d) if ((rx[3] == 9) && (rx[12] & 0x01)) { /* got a "press" event */ - state->last_rc_key = (rx[7] << 8) | rx[6]; + state->last_rc_key = RC_SCANCODE_RC5(rx[7], rx[6]); if (debug > 2) info("%s: cmd=0x%02x sys=0x%02x\n", __func__, rx[6], rx[7]); - rc_keydown(d->rc_dev, state->last_rc_key, 0); + rc_keydown(d->rc_dev, RC_PROTO_RC5, state->last_rc_key, 0); } else if (state->last_rc_key) { rc_keyup(d->rc_dev); state->last_rc_key = 0; } - - return 0; +ret: + kfree(b); + return ret; } static int pctv452e_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) @@ -611,7 +647,7 @@ static int pctv452e_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) return 0; failed: - memset(mac, 0, 6); + eth_zero_addr(mac); return ret; } @@ -869,28 +905,36 @@ static struct stb6100_config stb6100_config = { }; -static struct i2c_algorithm pctv452e_i2c_algo = { +static const struct i2c_algorithm pctv452e_i2c_algo = { .master_xfer = pctv452e_i2c_xfer, .functionality = pctv452e_i2c_func }; static int pctv452e_frontend_attach(struct dvb_usb_adapter *a) { - struct usb_device_id *id; + const struct usb_device_id *id; a->fe_adap[0].fe = dvb_attach(stb0899_attach, &stb0899_config, &a->dev->i2c_adap); if (!a->fe_adap[0].fe) return -ENODEV; - if ((dvb_attach(lnbp22_attach, a->fe_adap[0].fe, - &a->dev->i2c_adap)) == 0) - err("Cannot attach lnbp22\n"); id = a->dev->desc->warm_ids[0]; - if (USB_VID_TECHNOTREND == id->idVendor - && USB_PID_TECHNOTREND_CONNECT_S2_3650_CI == id->idProduct) + if (id->idVendor == USB_VID_TECHNOTREND && + id->idProduct == USB_PID_TECHNOTREND_CONNECT_S2_3650_CI) { + if (dvb_attach(lnbp22_attach, + a->fe_adap[0].fe, + &a->dev->i2c_adap) == NULL) { + err("Cannot attach lnbp22\n"); + } /* Error ignored. */ tt3650_ci_init(a); + } else if (dvb_attach(isl6423_attach, + a->fe_adap[0].fe, + &a->dev->i2c_adap, + &pctv452e_isl6423_config) == NULL) { + err("Cannot attach isl6423\n"); + } return 0; } @@ -900,7 +944,7 @@ static int pctv452e_tuner_attach(struct dvb_usb_adapter *a) if (!a->fe_adap[0].fe) return -ENODEV; if (dvb_attach(stb6100_attach, a->fe_adap[0].fe, &stb6100_config, - &a->dev->i2c_adap) == 0) { + &a->dev->i2c_adap) == NULL) { err("%s failed\n", __func__); return -ENODEV; } @@ -908,13 +952,19 @@ static int pctv452e_tuner_attach(struct dvb_usb_adapter *a) return 0; } -static struct usb_device_id pctv452e_usb_table[] = { - {USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_452E)}, - {USB_DEVICE(USB_VID_TECHNOTREND, USB_PID_TECHNOTREND_CONNECT_S2_3600)}, - {USB_DEVICE(USB_VID_TECHNOTREND, - USB_PID_TECHNOTREND_CONNECT_S2_3650_CI)}, - {} +enum { + PINNACLE_PCTV_452E, + TECHNOTREND_CONNECT_S2_3600, + TECHNOTREND_CONNECT_S2_3650_CI, }; + +static const struct usb_device_id pctv452e_usb_table[] = { + DVB_USB_DEV(PINNACLE, PINNACLE_PCTV_452E), + DVB_USB_DEV(TECHNOTREND, TECHNOTREND_CONNECT_S2_3600), + DVB_USB_DEV(TECHNOTREND, TECHNOTREND_CONNECT_S2_3650_CI), + { } +}; + MODULE_DEVICE_TABLE(usb, pctv452e_usb_table); static struct dvb_usb_device_properties pctv452e_properties = { @@ -927,7 +977,7 @@ static struct dvb_usb_device_properties pctv452e_properties = { .rc.core = { .rc_codes = RC_MAP_DIB0700_RC5_TABLE, - .allowed_protos = RC_BIT_UNKNOWN, + .allowed_protos = RC_PROTO_BIT_RC5, .rc_query = pctv452e_rc_query, .rc_interval = 100, }, @@ -963,9 +1013,9 @@ static struct dvb_usb_device_properties pctv452e_properties = { .devices = { { .name = "PCTV HDTV USB", .cold_ids = { NULL, NULL }, /* this is a warm only device */ - .warm_ids = { &pctv452e_usb_table[0], NULL } + .warm_ids = { &pctv452e_usb_table[PINNACLE_PCTV_452E], NULL } }, - { 0 }, + { NULL }, } }; @@ -980,7 +1030,7 @@ static struct dvb_usb_device_properties tt_connect_s2_3600_properties = { .rc.core = { .rc_codes = RC_MAP_TT_1500, - .allowed_protos = RC_BIT_UNKNOWN, + .allowed_protos = RC_PROTO_BIT_RC5, .rc_query = pctv452e_rc_query, .rc_interval = 100, }, @@ -995,11 +1045,11 @@ static struct dvb_usb_device_properties tt_connect_s2_3600_properties = { /* parameter for the MPEG2-data transfer */ .stream = { .type = USB_ISOC, - .count = 7, + .count = 4, .endpoint = 0x02, .u = { .isoc = { - .framesperurb = 4, + .framesperurb = 64, .framesize = 940, .interval = 1 } @@ -1017,13 +1067,13 @@ static struct dvb_usb_device_properties tt_connect_s2_3600_properties = { .devices = { { .name = "Technotrend TT Connect S2-3600", .cold_ids = { NULL, NULL }, /* this is a warm only device */ - .warm_ids = { &pctv452e_usb_table[1], NULL } + .warm_ids = { &pctv452e_usb_table[TECHNOTREND_CONNECT_S2_3600], NULL } }, { .name = "Technotrend TT Connect S2-3650-CI", .cold_ids = { NULL, NULL }, - .warm_ids = { &pctv452e_usb_table[2], NULL } + .warm_ids = { &pctv452e_usb_table[TECHNOTREND_CONNECT_S2_3650_CI], NULL } }, - { 0 }, + { NULL }, } }; |
