Commit d8d1721c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'media/v4.9-3' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media

Pull media fixes from Mauro Carvalho Chehab:
 "A series of fixup patches meant to fix the usage of DMA on stack, plus
  one warning fixup"

* tag 'media/v4.9-3' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (32 commits)
  [media] radio-bcm2048: don't ignore errors
  [media] pctv452e: fix semicolon.cocci warnings
  [media] flexcop-usb: don't use stack for DMA
  [media] stk-webcam: don't use stack for DMA
  [media] s2255drv: don't use stack for DMA
  [media] cpia2_usb: don't use stack for DMA
  [media] digitv: handle error code on RC query
  [media] dw2102: return error if su3000_power_ctrl() fails
  [media] nova-t-usb2: handle error code on RC query
  [media] technisat-usb2: use DMA buffers for I2C transfers
  [media] pctv452e: don't call BUG_ON() on non-fatal error
  [media] pctv452e: don't do DMA on stack
  [media] nova-t-usb2: don't do DMA on stack
  [media] gp8psk: don't go past the buffer size
  [media] gp8psk: don't do DMA on stack
  [media] dtv5100: don't do DMA on stack
  [media] dtt200u: handle USB control message errors
  [media] dtt200u: don't do DMA on stack
  [media] dtt200u-fe: handle errors on USB control messages
  [media] dtt200u-fe: don't do DMA on stack
  ...
parents 41e6410e 1aeb5b61
...@@ -73,23 +73,34 @@ static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI, ...@@ -73,23 +73,34 @@ static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI,
u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR; u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR;
u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) | u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) |
(read ? 0x80 : 0); (read ? 0x80 : 0);
int ret;
mutex_lock(&fc_usb->data_mutex);
if (!read)
memcpy(fc_usb->data, val, sizeof(*val));
int len = usb_control_msg(fc_usb->udev, ret = usb_control_msg(fc_usb->udev,
read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT, read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT,
request, request,
request_type, /* 0xc0 read or 0x40 write */ request_type, /* 0xc0 read or 0x40 write */
wAddress, wAddress,
0, 0,
val, fc_usb->data,
sizeof(u32), sizeof(u32),
B2C2_WAIT_FOR_OPERATION_RDW * HZ); B2C2_WAIT_FOR_OPERATION_RDW * HZ);
if (len != sizeof(u32)) { if (ret != sizeof(u32)) {
err("error while %s dword from %d (%d).", read ? "reading" : err("error while %s dword from %d (%d).", read ? "reading" :
"writing", wAddress, wRegOffsPCI); "writing", wAddress, wRegOffsPCI);
return -EIO; if (ret >= 0)
ret = -EIO;
} }
return 0;
if (read && ret >= 0)
memcpy(val, fc_usb->data, sizeof(*val));
mutex_unlock(&fc_usb->data_mutex);
return ret;
} }
/* /*
* DKT 010817 - add support for V8 memory read/write and flash update * DKT 010817 - add support for V8 memory read/write and flash update
...@@ -100,9 +111,14 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb, ...@@ -100,9 +111,14 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,
{ {
u8 request_type = USB_TYPE_VENDOR; u8 request_type = USB_TYPE_VENDOR;
u16 wIndex; u16 wIndex;
int nWaitTime, pipe, len; int nWaitTime, pipe, ret;
wIndex = page << 8; wIndex = page << 8;
if (buflen > sizeof(fc_usb->data)) {
err("Buffer size bigger than max URB control message\n");
return -EIO;
}
switch (req) { switch (req) {
case B2C2_USB_READ_V8_MEM: case B2C2_USB_READ_V8_MEM:
nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ; nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ;
...@@ -127,17 +143,32 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb, ...@@ -127,17 +143,32 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,
deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n", request_type, req, deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n", request_type, req,
wAddress, wIndex, buflen); wAddress, wIndex, buflen);
len = usb_control_msg(fc_usb->udev, pipe, mutex_lock(&fc_usb->data_mutex);
if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
memcpy(fc_usb->data, pbBuffer, buflen);
ret = usb_control_msg(fc_usb->udev, pipe,
req, req,
request_type, request_type,
wAddress, wAddress,
wIndex, wIndex,
pbBuffer, fc_usb->data,
buflen, buflen,
nWaitTime * HZ); nWaitTime * HZ);
if (ret != buflen)
ret = -EIO;
if (ret >= 0) {
ret = 0;
if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
memcpy(pbBuffer, fc_usb->data, buflen);
}
debug_dump(pbBuffer, len, deb_v8); mutex_unlock(&fc_usb->data_mutex);
return len == buflen ? 0 : -EIO;
debug_dump(pbBuffer, ret, deb_v8);
return ret;
} }
#define bytes_left_to_read_on_page(paddr,buflen) \ #define bytes_left_to_read_on_page(paddr,buflen) \
...@@ -196,29 +227,6 @@ static int flexcop_usb_get_mac_addr(struct flexcop_device *fc, int extended) ...@@ -196,29 +227,6 @@ static int flexcop_usb_get_mac_addr(struct flexcop_device *fc, int extended)
fc->dvb_adapter.proposed_mac, 6); fc->dvb_adapter.proposed_mac, 6);
} }
#if 0
static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set,
flexcop_usb_utility_function_t func, u8 extra, u16 wIndex,
u16 buflen, u8 *pvBuffer)
{
u16 wValue;
u8 request_type = (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR;
int nWaitTime = 2,
pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN, len;
wValue = (func << 8) | extra;
len = usb_control_msg(fc_usb->udev,pipe,
B2C2_USB_UTILITY,
request_type,
wValue,
wIndex,
pvBuffer,
buflen,
nWaitTime * HZ);
return len == buflen ? 0 : -EIO;
}
#endif
/* usb i2c stuff */ /* usb i2c stuff */
static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c, static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
flexcop_usb_request_t req, flexcop_usb_i2c_function_t func, flexcop_usb_request_t req, flexcop_usb_i2c_function_t func,
...@@ -226,9 +234,14 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c, ...@@ -226,9 +234,14 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
{ {
struct flexcop_usb *fc_usb = i2c->fc->bus_specific; struct flexcop_usb *fc_usb = i2c->fc->bus_specific;
u16 wValue, wIndex; u16 wValue, wIndex;
int nWaitTime,pipe,len; int nWaitTime, pipe, ret;
u8 request_type = USB_TYPE_VENDOR; u8 request_type = USB_TYPE_VENDOR;
if (buflen > sizeof(fc_usb->data)) {
err("Buffer size bigger than max URB control message\n");
return -EIO;
}
switch (func) { switch (func) {
case USB_FUNC_I2C_WRITE: case USB_FUNC_I2C_WRITE:
case USB_FUNC_I2C_MULTIWRITE: case USB_FUNC_I2C_MULTIWRITE:
...@@ -257,15 +270,32 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c, ...@@ -257,15 +270,32 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
wValue & 0xff, wValue >> 8, wValue & 0xff, wValue >> 8,
wIndex & 0xff, wIndex >> 8); wIndex & 0xff, wIndex >> 8);
len = usb_control_msg(fc_usb->udev,pipe, mutex_lock(&fc_usb->data_mutex);
if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
memcpy(fc_usb->data, buf, buflen);
ret = usb_control_msg(fc_usb->udev, pipe,
req, req,
request_type, request_type,
wValue, wValue,
wIndex, wIndex,
buf, fc_usb->data,
buflen, buflen,
nWaitTime * HZ); nWaitTime * HZ);
return len == buflen ? 0 : -EREMOTEIO;
if (ret != buflen)
ret = -EIO;
if (ret >= 0) {
ret = 0;
if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
memcpy(buf, fc_usb->data, buflen);
}
mutex_unlock(&fc_usb->data_mutex);
return 0;
} }
/* actual bus specific access functions, /* actual bus specific access functions,
...@@ -516,6 +546,7 @@ static int flexcop_usb_probe(struct usb_interface *intf, ...@@ -516,6 +546,7 @@ static int flexcop_usb_probe(struct usb_interface *intf,
/* general flexcop init */ /* general flexcop init */
fc_usb = fc->bus_specific; fc_usb = fc->bus_specific;
fc_usb->fc_dev = fc; fc_usb->fc_dev = fc;
mutex_init(&fc_usb->data_mutex);
fc->read_ibi_reg = flexcop_usb_read_ibi_reg; fc->read_ibi_reg = flexcop_usb_read_ibi_reg;
fc->write_ibi_reg = flexcop_usb_write_ibi_reg; fc->write_ibi_reg = flexcop_usb_write_ibi_reg;
......
...@@ -29,6 +29,10 @@ struct flexcop_usb { ...@@ -29,6 +29,10 @@ struct flexcop_usb {
u8 tmp_buffer[1023+190]; u8 tmp_buffer[1023+190];
int tmp_buffer_length; int tmp_buffer_length;
/* for URB control messages */
u8 data[80];
struct mutex data_mutex;
}; };
#if 0 #if 0
......
...@@ -545,18 +545,30 @@ static void free_sbufs(struct camera_data *cam) ...@@ -545,18 +545,30 @@ static void free_sbufs(struct camera_data *cam)
static int write_packet(struct usb_device *udev, static int write_packet(struct usb_device *udev,
u8 request, u8 * registers, u16 start, size_t size) u8 request, u8 * registers, u16 start, size_t size)
{ {
unsigned char *buf;
int ret;
if (!registers || size <= 0) if (!registers || size <= 0)
return -EINVAL; return -EINVAL;
return usb_control_msg(udev, buf = kmalloc(size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
memcpy(buf, registers, size);
ret = usb_control_msg(udev,
usb_sndctrlpipe(udev, 0), usb_sndctrlpipe(udev, 0),
request, request,
USB_TYPE_VENDOR | USB_RECIP_DEVICE, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
start, /* value */ start, /* value */
0, /* index */ 0, /* index */
registers, /* buffer */ buf, /* buffer */
size, size,
HZ); HZ);
kfree(buf);
return ret;
} }
/**************************************************************************** /****************************************************************************
...@@ -567,18 +579,32 @@ static int write_packet(struct usb_device *udev, ...@@ -567,18 +579,32 @@ static int write_packet(struct usb_device *udev,
static int read_packet(struct usb_device *udev, static int read_packet(struct usb_device *udev,
u8 request, u8 * registers, u16 start, size_t size) u8 request, u8 * registers, u16 start, size_t size)
{ {
unsigned char *buf;
int ret;
if (!registers || size <= 0) if (!registers || size <= 0)
return -EINVAL; return -EINVAL;
return usb_control_msg(udev, buf = kmalloc(size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
ret = usb_control_msg(udev,
usb_rcvctrlpipe(udev, 0), usb_rcvctrlpipe(udev, 0),
request, request,
USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE, USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE,
start, /* value */ start, /* value */
0, /* index */ 0, /* index */
registers, /* buffer */ buf, /* buffer */
size, size,
HZ); HZ);
if (ret >= 0)
memcpy(registers, buf, size);
kfree(buf);
return ret;
} }
/****************************************************************************** /******************************************************************************
......
This diff is collapsed.
...@@ -41,6 +41,8 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ...@@ -41,6 +41,8 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
struct cinergyt2_state { struct cinergyt2_state {
u8 rc_counter; u8 rc_counter;
unsigned char data[64];
struct mutex data_mutex;
}; };
/* We are missing a release hook with usb_device data */ /* We are missing a release hook with usb_device data */
...@@ -50,38 +52,57 @@ static struct dvb_usb_device_properties cinergyt2_properties; ...@@ -50,38 +52,57 @@ static struct dvb_usb_device_properties cinergyt2_properties;
static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable) static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable)
{ {
char buf[] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 }; struct dvb_usb_device *d = adap->dev;
char result[64]; struct cinergyt2_state *st = d->priv;
return dvb_usb_generic_rw(adap->dev, buf, sizeof(buf), result, int ret;
sizeof(result), 0);
mutex_lock(&st->data_mutex);
st->data[0] = CINERGYT2_EP1_CONTROL_STREAM_TRANSFER;
st->data[1] = enable ? 1 : 0;
ret = dvb_usb_generic_rw(d, st->data, 2, st->data, 64, 0);
mutex_unlock(&st->data_mutex);
return ret;
} }
static int cinergyt2_power_ctrl(struct dvb_usb_device *d, int enable) static int cinergyt2_power_ctrl(struct dvb_usb_device *d, int enable)
{ {
char buf[] = { CINERGYT2_EP1_SLEEP_MODE, enable ? 0 : 1 }; struct cinergyt2_state *st = d->priv;
char state[3]; int ret;
return dvb_usb_generic_rw(d, buf, sizeof(buf), state, sizeof(state), 0);
mutex_lock(&st->data_mutex);
st->data[0] = CINERGYT2_EP1_SLEEP_MODE;
st->data[1] = enable ? 0 : 1;
ret = dvb_usb_generic_rw(d, st->data, 2, st->data, 3, 0);
mutex_unlock(&st->data_mutex);
return ret;
} }
static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap) static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap)
{ {
char query[] = { CINERGYT2_EP1_GET_FIRMWARE_VERSION }; struct dvb_usb_device *d = adap->dev;
char state[3]; struct cinergyt2_state *st = d->priv;
int ret; int ret;
adap->fe_adap[0].fe = cinergyt2_fe_attach(adap->dev); adap->fe_adap[0].fe = cinergyt2_fe_attach(adap->dev);
ret = dvb_usb_generic_rw(adap->dev, query, sizeof(query), state, mutex_lock(&st->data_mutex);
sizeof(state), 0); st->data[0] = CINERGYT2_EP1_GET_FIRMWARE_VERSION;
ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 3, 0);
if (ret < 0) { if (ret < 0) {
deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep " deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep "
"state info\n"); "state info\n");
} }
mutex_unlock(&st->data_mutex);
/* Copy this pointer as we are gonna need it in the release phase */ /* Copy this pointer as we are gonna need it in the release phase */
cinergyt2_usb_device = adap->dev; cinergyt2_usb_device = adap->dev;
return 0; return ret;
} }
static struct rc_map_table rc_map_cinergyt2_table[] = { static struct rc_map_table rc_map_cinergyt2_table[] = {
...@@ -141,13 +162,18 @@ static int repeatable_keys[] = { ...@@ -141,13 +162,18 @@ static int repeatable_keys[] = {
static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state) static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
{ {
struct cinergyt2_state *st = d->priv; struct cinergyt2_state *st = d->priv;
u8 key[5] = {0, 0, 0, 0, 0}, cmd = CINERGYT2_EP1_GET_RC_EVENTS; int i, ret;
int i;
*state = REMOTE_NO_KEY_PRESSED; *state = REMOTE_NO_KEY_PRESSED;
dvb_usb_generic_rw(d, &cmd, 1, key, sizeof(key), 0); mutex_lock(&st->data_mutex);
if (key[4] == 0xff) { st->data[0] = CINERGYT2_EP1_GET_RC_EVENTS;
ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 5, 0);
if (ret < 0)
goto ret;
if (st->data[4] == 0xff) {
/* key repeat */ /* key repeat */
st->rc_counter++; st->rc_counter++;
if (st->rc_counter > RC_REPEAT_DELAY) { if (st->rc_counter > RC_REPEAT_DELAY) {
...@@ -157,31 +183,45 @@ static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state) ...@@ -157,31 +183,45 @@ static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
*event = d->last_event; *event = d->last_event;
deb_rc("repeat key, event %x\n", deb_rc("repeat key, event %x\n",
*event); *event);
return 0; goto ret;
} }
} }
deb_rc("repeated key (non repeatable)\n"); deb_rc("repeated key (non repeatable)\n");
} }
return 0; goto ret;
} }
/* hack to pass checksum on the custom field */ /* hack to pass checksum on the custom field */
key[2] = ~key[1]; st->data[2] = ~st->data[1];
dvb_usb_nec_rc_key_to_event(d, key, event, state); dvb_usb_nec_rc_key_to_event(d, st->data, event, state);
if (key[0] != 0) { if (st->data[0] != 0) {
if (*event != d->last_event) if (*event != d->last_event)
st->rc_counter = 0; st->rc_counter = 0;
deb_rc("key: %*ph\n", 5, key); deb_rc("key: %*ph\n", 5, st->data);
} }
return 0;
ret:
mutex_unlock(&st->data_mutex);
return ret;
} }
static int cinergyt2_usb_probe(struct usb_interface *intf, static int cinergyt2_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
return dvb_usb_device_init(intf, &cinergyt2_properties, struct dvb_usb_device *d;
THIS_MODULE, NULL, adapter_nr); struct cinergyt2_state *st;
int ret;
ret = dvb_usb_device_init(intf, &cinergyt2_properties,
THIS_MODULE, &d, adapter_nr);
if (ret < 0)
return ret;
st = d->priv;
mutex_init(&st->data_mutex);
return 0;
} }
......
...@@ -139,32 +139,42 @@ static uint16_t compute_tps(struct dtv_frontend_properties *op) ...@@ -139,32 +139,42 @@ static uint16_t compute_tps(struct dtv_frontend_properties *op)
struct cinergyt2_fe_state { struct cinergyt2_fe_state {
struct dvb_frontend fe; struct dvb_frontend fe;
struct dvb_usb_device *d; struct dvb_usb_device *d;
unsigned char data[64];
struct mutex data_mutex;
struct dvbt_get_status_msg status;
}; };
static int cinergyt2_fe_read_status(struct dvb_frontend *fe, static int cinergyt2_fe_read_status(struct dvb_frontend *fe,
enum fe_status *status) enum fe_status *status)
{ {
struct cinergyt2_fe_state *state = fe->demodulator_priv; struct cinergyt2_fe_state *state = fe->demodulator_priv;
struct dvbt_get_status_msg result;
u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
int ret; int ret;
ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&result, mutex_lock(&state->data_mutex);
sizeof(result), 0); state->data[0] = CINERGYT2_EP1_GET_TUNER_STATUS;
ret = dvb_usb_generic_rw(state->d, state->data, 1,
state->data, sizeof(state->status), 0);
if (!ret)
memcpy(&state->status, state->data, sizeof(state->status));
mutex_unlock(&state->data_mutex);
if (ret < 0) if (ret < 0)
return ret; return ret;
*status = 0; *status = 0;
if (0xffff - le16_to_cpu(result.gain) > 30) if (0xffff - le16_to_cpu(state->status.gain) > 30)
*status |= FE_HAS_SIGNAL; *status |= FE_HAS_SIGNAL;
if (result.lock_bits & (1 << 6)) if (state->status.lock_bits & (1 << 6))
*status |= FE_HAS_LOCK; *status |= FE_HAS_LOCK;
if (result.lock_bits & (1 << 5)) if (state->status.lock_bits & (1 << 5))
*status |= FE_HAS_SYNC; *status |= FE_HAS_SYNC;
if (result.lock_bits & (1 << 4)) if (state->status.lock_bits & (1 << 4))
*status |= FE_HAS_CARRIER; *status |= FE_HAS_CARRIER;
if (result.lock_bits & (1 << 1)) if (state->status.lock_bits & (1 << 1))
*status |= FE_HAS_VITERBI; *status |= FE_HAS_VITERBI;
if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) != if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) !=
...@@ -177,34 +187,16 @@ static int cinergyt2_fe_read_status(struct dvb_frontend *fe, ...@@ -177,34 +187,16 @@ static int cinergyt2_fe_read_status(struct dvb_frontend *fe,
static int cinergyt2_fe_read_ber(struct dvb_frontend *fe, u32 *ber) static int cinergyt2_fe_read_ber(struct dvb_frontend *fe, u32 *ber)
{ {
struct cinergyt2_fe_state *state = fe->demodulator_priv; struct cinergyt2_fe_state *state = fe->demodulator_priv;
struct dvbt_get_status_msg status;
char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
int ret;
ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status,
sizeof(status), 0);
if (ret < 0)
return ret;
*ber = le32_to_cpu(status.viterbi_error_rate); *ber = le32_to_cpu(state->status.viterbi_error_rate);
return 0; return 0;
} }
static int cinergyt2_fe_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) static int cinergyt2_fe_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
{ {
struct cinergyt2_fe_state *state = fe->demodulator_priv; struct cinergyt2_fe_state *state = fe->demodulator_priv;
struct dvbt_get_status_msg status;
u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
int ret;
ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&status, *unc = le32_to_cpu(state->status.uncorrected_block_count);
sizeof(status), 0);
if (ret < 0) {
err("cinergyt2_fe_read_unc_blocks() Failed! (Error=%d)\n",
ret);
return ret;
}
*unc = le32_to_cpu(status.uncorrected_block_count);
return 0; return 0;
} }
...@@ -212,35 +204,16 @@ static int cinergyt2_fe_read_signal_strength(struct dvb_frontend *fe, ...@@ -212,35 +204,16 @@ static int cinergyt2_fe_read_signal_strength(struct dvb_frontend *fe,
u16 *strength) u16 *strength)
{ {
struct cinergyt2_fe_state *state = fe->demodulator_priv; struct cinergyt2_fe_state *state = fe->demodulator_priv;
struct dvbt_get_status_msg status;
char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
int ret;
ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, *strength = (0xffff - le16_to_cpu(state->status.gain));
sizeof(status), 0);
if (ret < 0) {
err("cinergyt2_fe_read_signal_strength() Failed!"
" (Error=%d)\n", ret);
return ret;
}
*strength = (0xffff - le16_to_cpu(status.gain));
return 0; return 0;
} }
static int cinergyt2_fe_read_snr(struct dvb_frontend *fe, u16 *snr) static int cinergyt2_fe_read_snr(struct dvb_frontend *fe, u16 *snr)
{ {
struct cinergyt2_fe_state *state = fe->demodulator_priv; struct cinergyt2_fe_state *state = fe->demodulator_priv;
struct dvbt_get_status_msg status;
char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
int ret;
ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, *snr = (state->status.snr << 8) | state->status.snr;
sizeof(status), 0);
if (ret < 0) {
err("cinergyt2_fe_read_snr() Failed! (Error=%d)\n", ret);
return ret;
}
*snr = (status.snr << 8) | status.snr;
return 0; return 0;
} }
...@@ -266,34 +239,36 @@ static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe) ...@@ -266,34 +239,36 @@ static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe)
{ {
struct dtv_frontend_properties *fep = &fe->dtv_property_cache; struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct cinergyt2_fe_state *state = fe->demodulator_priv; struct cinergyt2_fe_state *state = fe->demodulator_priv;
struct dvbt_set_parameters_msg param; struct dvbt_set_parameters_msg *param;
char result[2];
int err; int err;
param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; mutex_lock(&state->data_mutex);
param.tps = cpu_to_le16(compute_tps(fep));
param.freq = cpu_to_le32(fep->frequency / 1000); param = (void *)state->data;
param.flags = 0; param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
param->tps = cpu_to_le16(compute_tps(fep));
param->freq = cpu_to_le32(fep->frequency / 1000);
param->flags = 0;
switch (fep->bandwidth_hz) { switch (fep->bandwidth_hz) {
default: default:
case 8000000: case 8000000:
param.bandwidth = 8; param->bandwidth = 8;
break; break;
case 7000000: case 7000000:
param.bandwidth = 7; param->bandwidth = 7;
break; break;
case 6000000: case 6000000:
param.bandwidth = 6; param->bandwidth = 6;
break; break;
} }
err = dvb_usb_generic_rw(state->d, err = dvb_usb_generic_rw(state->d, state->data, sizeof(*param),
(char *)&param, sizeof(param), state->data, 2, 0);
result, sizeof(result), 0);
if (err < 0) if (err < 0)
err("cinergyt2_fe_set_frontend() Failed! err=%d\n", err); err("cinergyt2_fe_set_frontend() Failed! err=%d\n", err);
mutex_unlock(&state->data_mutex);
return (err < 0) ? err : 0; return (err < 0) ? err : 0;
} }
...@@ -315,6 +290,7 @@ struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d) ...@@ -315,6 +290,7 @@ struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d)
s->d = d; s->d = d;
memcpy(&s->fe.ops, &cinergyt2_fe_ops, sizeof(struct dvb_frontend_ops)); memcpy(&s->fe.ops, &cinergyt2_fe_ops, sizeof(struct dvb_frontend_ops));
s->fe.demodulator_priv = s; s->fe.demodulator_priv = s;
mutex_init(&s->data_mutex);
return &s->fe; return &s->fe;
} }
......
...@@ -45,9 +45,6 @@ ...@@ -45,9 +45,6 @@
#include "si2168.h" #include "si2168.h"
#include "si2157.h" #include "si2157.h"
/* Max transfer size done by I2C transfer functions */
#define MAX_XFER_SIZE 80
/* debug */ /* debug */
static int dvb_usb_cxusb_debug; static int dvb_usb_cxusb_debug;
module_param_named(debug, dvb_usb_cxusb_debug, int, 0644); module_param_named(debug, dvb_usb_cxusb_debug, int, 0644);
...@@ -61,23 +58,27 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ...@@ -61,23 +58,27 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static int cxusb_ctrl_msg(struct dvb_usb_device *d, static int cxusb_ctrl_msg(struct dvb_usb_device *d,
u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
{ {
int wo = (rbuf == NULL || rlen == 0); /* write-only */ struct cxusb_state *st = d->priv;
u8 sndbuf[MAX_XFER_SIZE]; int ret, wo;
if (1 + wlen > sizeof(sndbuf)) { if (1 + wlen > MAX_XFER_SIZE) {
warn("i2c wr: len=%d is too big!\n", warn("i2c wr: len=%d is too big!\n", wlen);
wlen);
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
memset(sndbuf, 0, 1+wlen); wo = (rbuf == NULL || rlen == 0); /* write-only */
sndbuf[0] = cmd; mutex_lock(&st->data_mutex);
memcpy(&sndbuf[1], wbuf, wlen); st->data[0] = cmd;
memcpy(&st->data[1], wbuf, wlen);
if (wo) if (wo)
return dvb_usb_generic_write(d, sndbuf, 1+wlen); ret = dvb_usb_generic_write(d, st->data, 1 + wlen);
else else
return dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0); ret = dvb_usb_generic_rw(d, st->data, 1 + wlen,
rbuf, rlen, 0);
mutex_unlock(&st->data_mutex);
return ret;
} }
/* GPIO */ /* GPIO */
...@@ -1460,36 +1461,43 @@ static struct dvb_usb_device_properties cxusb_mygica_t230_properties; ...@@ -1460,36 +1461,43 @@ static struct dvb_usb_device_properties cxusb_mygica_t230_properties;
static int cxusb_probe(struct usb_interface *intf, static int cxusb_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
struct dvb_usb_device *d;
struct cxusb_state *st;
if (0 == dvb_usb_device_init(intf, &cxusb_medion_properties, if (0 == dvb_usb_device_init(intf, &cxusb_medion_properties,
THIS_MODULE, NULL, adapter_nr) || THIS_MODULE, &d, adapter_nr) ||
0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgh064f_properties, 0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgh064f_properties,
THIS_MODULE, NULL, adapter_nr) || THIS_MODULE, &d, adapter_nr) ||
0 == dvb_usb_device_init(intf, &cxusb_bluebird_dee1601_properties, 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dee1601_properties,
THIS_MODULE, NULL, adapter_nr) || THIS_MODULE, &d, adapter_nr) ||
0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgz201_properties, 0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgz201_properties,
THIS_MODULE, NULL, adapter_nr) || THIS_MODULE, &d, adapter_nr) ||
0 == dvb_usb_device_init(intf, &cxusb_bluebird_dtt7579_properties, 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dtt7579_properties,
THIS_MODULE, NULL, adapter_nr) || THIS_MODULE, &d, adapter_nr) ||
0 == dvb_usb_device_init(intf, &cxusb_bluebird_dualdig4_properties, 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dualdig4_properties,
THIS_MODULE, NULL, adapter_nr) || THIS_MODULE, &d, adapter_nr) ||
0 == dvb_usb_device_init(intf, &cxusb_bluebird_nano2_properties, 0 == dvb_usb_device_init(intf, &cxusb_bluebird_nano2_properties,
THIS_MODULE, NULL, adapter_nr) || THIS_MODULE, &d, adapter_nr) ||
0 == dvb_usb_device_init(intf, 0 == dvb_usb_device_init(intf,
&cxusb_bluebird_nano2_needsfirmware_properties, &cxusb_bluebird_nano2_needsfirmware_properties,
THIS_MODULE, NULL, adapter_nr) || THIS_MODULE, &d, adapter_nr) ||
0 == dvb_usb_device_init(intf, &cxusb_aver_a868r_properties, 0 == dvb_usb_device_init(intf, &cxusb_aver_a868r_properties,
THIS_MODULE, NULL, adapter_nr) || THIS_MODULE, &d, adapter_nr) ||
0 == dvb_usb_device_init(intf, 0 == dvb_usb_device_init(intf,
&cxusb_bluebird_dualdig4_rev2_properties, &cxusb_bluebird_dualdig4_rev2_properties,
THIS_MODULE, NULL, adapter_nr) || THIS_MODULE, &d, adapter_nr) ||
0 == dvb_usb_device_init(intf, &cxusb_d680_dmb_properties, 0 == dvb_usb_device_init(intf, &cxusb_d680_dmb_properties,
THIS_MODULE, NULL, adapter_nr) || THIS_MODULE, &d, adapter_nr) ||
0 == dvb_usb_device_init(intf, &cxusb_mygica_d689_properties, 0 == dvb_usb_device_init(intf, &cxusb_mygica_d689_properties,
THIS_MODULE, NULL, adapter_nr) || THIS_MODULE, &d, adapter_nr) ||
0 == dvb_usb_device_init(intf, &cxusb_mygica_t230_properties, 0 == dvb_usb_device_init(intf, &cxusb_mygica_t230_properties,
THIS_MODULE, NULL, adapter_nr) || THIS_MODULE, &d, adapter_nr) ||
0) 0) {
st = d->priv;
mutex_init(&st->data_mutex);
return 0; return 0;
}
return -EINVAL; return -EINVAL;
} }
......
...@@ -28,10 +28,16 @@ ...@@ -28,10 +28,16 @@
#define CMD_ANALOG 0x50 #define CMD_ANALOG 0x50
#define CMD_DIGITAL 0x51 #define CMD_DIGITAL 0x51
/* Max transfer size done by I2C transfer functions */
#define MAX_XFER_SIZE 80
struct cxusb_state { struct cxusb_state {
u8 gpio_write_state[3]; u8 gpio_write_state[3];
struct i2c_client *i2c_client_demod; struct i2c_client *i2c_client_demod;
struct i2c_client *i2c_client_tuner; struct i2c_client *i2c_client_tuner;
unsigned char data[MAX_XFER_SIZE];
struct mutex data_mutex;
}; };
#endif #endif
...@@ -213,7 +213,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, ...@@ -213,7 +213,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
usb_rcvctrlpipe(d->udev, 0), usb_rcvctrlpipe(d->udev, 0),
REQUEST_NEW_I2C_READ, REQUEST_NEW_I2C_READ,
USB_TYPE_VENDOR | USB_DIR_IN, USB_TYPE_VENDOR | USB_DIR_IN,
value, index, msg[i].buf, value, index, st->buf,
msg[i].len, msg[i].len,
USB_CTRL_GET_TIMEOUT); USB_CTRL_GET_TIMEOUT);
if (result < 0) { if (result < 0) {
...@@ -221,6 +221,14 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, ...@@ -221,6 +221,14 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
break; break;
} }
if (msg[i].len > sizeof(st->buf)) {
deb_info("buffer too small to fit %d bytes\n",
msg[i].len);
return -EIO;
}
memcpy(msg[i].buf, st->buf, msg[i].len);
deb_data("<<< "); deb_data("<<< ");
debug_dump(msg[i].buf, msg[i].len, deb_data); debug_dump(msg[i].buf, msg[i].len, deb_data);
...@@ -238,6 +246,13 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, ...@@ -238,6 +246,13 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
/* I2C ctrl + FE bus; */ /* I2C ctrl + FE bus; */
st->buf[3] = ((gen_mode << 6) & 0xC0) | st->buf[3] = ((gen_mode << 6) & 0xC0) |
((bus_mode << 4) & 0x30); ((bus_mode << 4) & 0x30);
if (msg[i].len > sizeof(st->buf) - 4) {
deb_info("i2c message to big: %d\n",
msg[i].len);
return -EIO;
}
/* The Actual i2c payload */ /* The Actual i2c payload */
memcpy(&st->buf[4], msg[i].buf, msg[i].len); memcpy(&st->buf[4], msg[i].buf, msg[i].len);
...@@ -283,6 +298,11 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, ...@@ -283,6 +298,11 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
/* fill in the address */ /* fill in the address */
st->buf[1] = msg[i].addr << 1; st->buf[1] = msg[i].addr << 1;
/* fill the buffer */ /* fill the buffer */
if (msg[i].len > sizeof(st->buf) - 2) {
deb_info("i2c xfer to big: %d\n",
msg[i].len);
return -EIO;
}
memcpy(&st->buf[2], msg[i].buf, msg[i].len); memcpy(&st->buf[2], msg[i].buf, msg[i].len);
/* write/read request */ /* write/read request */
...@@ -292,13 +312,20 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, ...@@ -292,13 +312,20 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
/* special thing in the current firmware: when length is zero the read-failed */ /* special thing in the current firmware: when length is zero the read-failed */
len = dib0700_ctrl_rd(d, st->buf, msg[i].len + 2, len = dib0700_ctrl_rd(d, st->buf, msg[i].len + 2,
msg[i+1].buf, msg[i+1].len); st->buf, msg[i + 1].len);
if (len <= 0) { if (len <= 0) {
deb_info("I2C read failed on address 0x%02x\n", deb_info("I2C read failed on address 0x%02x\n",
msg[i].addr); msg[i].addr);
break; break;
} }
if (msg[i + 1].len > sizeof(st->buf)) {
deb_info("i2c xfer buffer to small for %d\n",
msg[i].len);
return -EIO;
}
memcpy(msg[i + 1].buf, st->buf, msg[i + 1].len);
msg[i+1].len = len; msg[i+1].len = len;
i++; i++;
......
...@@ -508,8 +508,6 @@ static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap) ...@@ -508,8 +508,6 @@ static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap)
#define DEFAULT_RC_INTERVAL 50 #define DEFAULT_RC_INTERVAL 50
static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
/* /*
* This function is used only when firmware is < 1.20 version. Newer * This function is used only when firmware is < 1.20 version. Newer
* firmwares use bulk mode, with functions implemented at dib0700_core, * firmwares use bulk mode, with functions implemented at dib0700_core,
...@@ -517,7 +515,6 @@ static u8 rc_request[] = { REQUEST_POLL_RC, 0 }; ...@@ -517,7 +515,6 @@ static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
*/ */
static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d) static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)
{ {
u8 key[4];
enum rc_type protocol; enum rc_type protocol;
u32 scancode; u32 scancode;
u8 toggle; u8 toggle;
...@@ -532,39 +529,43 @@ static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d) ...@@ -532,39 +529,43 @@ static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)
return 0; return 0;
} }
i = dib0700_ctrl_rd(d, rc_request, 2, key, 4); st->buf[0] = REQUEST_POLL_RC;
st->buf[1] = 0;
i = dib0700_ctrl_rd(d, st->buf, 2, st->buf, 4);
if (i <= 0) { if (i <= 0) {
err("RC Query Failed"); err("RC Query Failed");
return -1; return -EIO;
} }
/* losing half of KEY_0 events from Philipps rc5 remotes.. */ /* losing half of KEY_0 events from Philipps rc5 remotes.. */
if (key[0] == 0 && key[1] == 0 && key[2] == 0 && key[3] == 0) if (st->buf[0] == 0 && st->buf[1] == 0
&& st->buf[2] == 0 && st->buf[3] == 0)
return 0; return 0;
/* info("%d: %2X %2X %2X %2X",dvb_usb_dib0700_ir_proto,(int)key[3-2],(int)key[3-3],(int)key[3-1],(int)key[3]); */ /* info("%d: %2X %2X %2X %2X",dvb_usb_dib0700_ir_proto,(int)st->buf[3 - 2],(int)st->buf[3 - 3],(int)st->buf[3 - 1],(int)st->buf[3]); */
dib0700_rc_setup(d, NULL); /* reset ir sensor data to prevent false events */ dib0700_rc_setup(d, NULL); /* reset ir sensor data to prevent false events */
switch (d->props.rc.core.protocol) { switch (d->props.rc.core.protocol) {
case RC_BIT_NEC: case RC_BIT_NEC:
/* NEC protocol sends repeat code as 0 0 0 FF */ /* NEC protocol sends repeat code as 0 0 0 FF */
if ((key[3-2] == 0x00) && (key[3-3] == 0x00) && if ((st->buf[3 - 2] == 0x00) && (st->buf[3 - 3] == 0x00) &&
(key[3] == 0xff)) { (st->buf[3] == 0xff)) {
rc_repeat(d->rc_dev); rc_repeat(d->rc_dev);
return 0; return 0;
} }
protocol = RC_TYPE_NEC; protocol = RC_TYPE_NEC;
scancode = RC_SCANCODE_NEC(key[3-2], key[3-3]); scancode = RC_SCANCODE_NEC(st->buf[3 - 2], st->buf[3 - 3]);
toggle = 0; toggle = 0;
break; break;
default: default:
/* RC-5 protocol changes toggle bit on new keypress */ /* RC-5 protocol changes toggle bit on new keypress */
protocol = RC_TYPE_RC5; protocol = RC_TYPE_RC5;
scancode = RC_SCANCODE_RC5(key[3-2], key[3-3]); scancode = RC_SCANCODE_RC5(st->buf[3 - 2], st->buf[3 - 3]);
toggle = key[3-1]; toggle = st->buf[3 - 1];
break; break;
} }
......
...@@ -62,72 +62,117 @@ EXPORT_SYMBOL(dibusb_pid_filter_ctrl); ...@@ -62,72 +62,117 @@ EXPORT_SYMBOL(dibusb_pid_filter_ctrl);
int dibusb_power_ctrl(struct dvb_usb_device *d, int onoff) int dibusb_power_ctrl(struct dvb_usb_device *d, int onoff)
{ {
u8 b[3]; u8 *b;
int ret; int ret;
b = kmalloc(3, GFP_KERNEL);
if (!b)
return -ENOMEM;
b[0] = DIBUSB_REQ_SET_IOCTL; b[0] = DIBUSB_REQ_SET_IOCTL;
b[1] = DIBUSB_IOCTL_CMD_POWER_MODE; b[1] = DIBUSB_IOCTL_CMD_POWER_MODE;
b[2] = onoff ? DIBUSB_IOCTL_POWER_WAKEUP : DIBUSB_IOCTL_POWER_SLEEP; b[2] = onoff ? DIBUSB_IOCTL_POWER_WAKEUP : DIBUSB_IOCTL_POWER_SLEEP;
ret = dvb_usb_generic_write(d,b,3);
ret = dvb_usb_generic_write(d, b, 3);
kfree(b);
msleep(10); msleep(10);
return ret; return ret;
} }
EXPORT_SYMBOL(dibusb_power_ctrl); EXPORT_SYMBOL(dibusb_power_ctrl);
int dibusb2_0_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) int dibusb2_0_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
{ {
u8 b[3] = { 0 };
int ret; int ret;
u8 *b;
b = kmalloc(3, GFP_KERNEL);
if (!b)
return -ENOMEM;
if ((ret = dibusb_streaming_ctrl(adap,onoff)) < 0) if ((ret = dibusb_streaming_ctrl(adap,onoff)) < 0)
return ret; goto ret;
if (onoff) { if (onoff) {
b[0] = DIBUSB_REQ_SET_STREAMING_MODE; b[0] = DIBUSB_REQ_SET_STREAMING_MODE;
b[1] = 0x00; b[1] = 0x00;
if ((ret = dvb_usb_generic_write(adap->dev,b,2)) < 0) ret = dvb_usb_generic_write(adap->dev, b, 2);
return ret; if (ret < 0)
goto ret;
} }
b[0] = DIBUSB_REQ_SET_IOCTL; b[0] = DIBUSB_REQ_SET_IOCTL;
b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM; b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM;
return dvb_usb_generic_write(adap->dev,b,3); ret = dvb_usb_generic_write(adap->dev, b, 3);
ret:
kfree(b);
return ret;
} }
EXPORT_SYMBOL(dibusb2_0_streaming_ctrl); EXPORT_SYMBOL(dibusb2_0_streaming_ctrl);
int dibusb2_0_power_ctrl(struct dvb_usb_device *d, int onoff) int dibusb2_0_power_ctrl(struct dvb_usb_device *d, int onoff)
{ {
if (onoff) { u8 *b;
u8 b[3] = { DIBUSB_REQ_SET_IOCTL, DIBUSB_IOCTL_CMD_POWER_MODE, DIBUSB_IOCTL_POWER_WAKEUP }; int ret;
return dvb_usb_generic_write(d,b,3);
} else if (!onoff)
return 0; return 0;
b = kmalloc(3, GFP_KERNEL);
if (!b)
return -ENOMEM;
b[0] = DIBUSB_REQ_SET_IOCTL;
b[1] = DIBUSB_IOCTL_CMD_POWER_MODE;
b[2] = DIBUSB_IOCTL_POWER_WAKEUP;
ret = dvb_usb_generic_write(d, b, 3);
kfree(b);
return ret;
} }
EXPORT_SYMBOL(dibusb2_0_power_ctrl); EXPORT_SYMBOL(dibusb2_0_power_ctrl);
static int dibusb_i2c_msg(struct dvb_usb_device *d, u8 addr, static int dibusb_i2c_msg(struct dvb_usb_device *d, u8 addr,
u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
{ {
u8 sndbuf[MAX_XFER_SIZE]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */ u8 *sndbuf;
int ret, wo, len;
/* write only ? */ /* write only ? */
int wo = (rbuf == NULL || rlen == 0), wo = (rbuf == NULL || rlen == 0);
len = 2 + wlen + (wo ? 0 : 2);
len = 2 + wlen + (wo ? 0 : 2);
sndbuf = kmalloc(MAX_XFER_SIZE, GFP_KERNEL);
if (!sndbuf)
return -ENOMEM;
if (4 + wlen > sizeof(sndbuf)) { if (4 + wlen > MAX_XFER_SIZE) {
warn("i2c wr: len=%d is too big!\n", wlen); warn("i2c wr: len=%d is too big!\n", wlen);
return -EOPNOTSUPP; ret = -EOPNOTSUPP;
goto ret;
} }
sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ; sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ;
sndbuf[1] = (addr << 1) | (wo ? 0 : 1); sndbuf[1] = (addr << 1) | (wo ? 0 : 1);
memcpy(&sndbuf[2],wbuf,wlen); memcpy(&sndbuf[2], wbuf, wlen);
if (!wo) { if (!wo) {
sndbuf[wlen+2] = (rlen >> 8) & 0xff; sndbuf[wlen + 2] = (rlen >> 8) & 0xff;
sndbuf[wlen+3] = rlen & 0xff; sndbuf[wlen + 3] = rlen & 0xff;
} }
return dvb_usb_generic_rw(d,sndbuf,len,rbuf,rlen,0); ret = dvb_usb_generic_rw(d, sndbuf, len, rbuf, rlen, 0);
ret:
kfree(sndbuf);
return ret;
} }
/* /*
...@@ -319,11 +364,27 @@ EXPORT_SYMBOL(rc_map_dibusb_table); ...@@ -319,11 +364,27 @@ EXPORT_SYMBOL(rc_map_dibusb_table);
int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
{ {
u8 key[5],cmd = DIBUSB_REQ_POLL_REMOTE; u8 *buf;
dvb_usb_generic_rw(d,&cmd,1,key,5,0); int ret;
dvb_usb_nec_rc_key_to_event(d,key,event,state);
if (key[0] != 0) buf = kmalloc(5, GFP_KERNEL);
deb_info("key: %*ph\n", 5, key); if (!buf)
return 0; return -ENOMEM;
buf[0] = DIBUSB_REQ_POLL_REMOTE;
ret = dvb_usb_generic_rw(d, buf, 1, buf, 5, 0);
if (ret < 0)
goto ret;
dvb_usb_nec_rc_key_to_event(d, buf, event, state);
if (buf[0] != 0)
deb_info("key: %*ph\n", 5, buf);
kfree(buf);
ret:
return ret;
} }
EXPORT_SYMBOL(dibusb_rc_query); EXPORT_SYMBOL(dibusb_rc_query);
...@@ -96,6 +96,9 @@ ...@@ -96,6 +96,9 @@
#define DIBUSB_IOCTL_CMD_ENABLE_STREAM 0x01 #define DIBUSB_IOCTL_CMD_ENABLE_STREAM 0x01
#define DIBUSB_IOCTL_CMD_DISABLE_STREAM 0x02 #define DIBUSB_IOCTL_CMD_DISABLE_STREAM 0x02
/* Max transfer size done by I2C transfer functions */
#define MAX_XFER_SIZE 64
struct dibusb_state { struct dibusb_state {
struct dib_fe_xfer_ops ops; struct dib_fe_xfer_ops ops;
int mt2060_present; int mt2060_present;
......
...@@ -28,22 +28,26 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ...@@ -28,22 +28,26 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static int digitv_ctrl_msg(struct dvb_usb_device *d, static int digitv_ctrl_msg(struct dvb_usb_device *d,
u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen) u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
{ {
int wo = (rbuf == NULL || rlen == 0); /* write-only */ struct digitv_state *st = d->priv;
u8 sndbuf[7],rcvbuf[7]; int ret, wo;
memset(sndbuf,0,7); memset(rcvbuf,0,7);
sndbuf[0] = cmd; wo = (rbuf == NULL || rlen == 0); /* write-only */
sndbuf[1] = vv;
sndbuf[2] = wo ? wlen : rlen; memset(st->sndbuf, 0, 7);
memset(st->rcvbuf, 0, 7);
st->sndbuf[0] = cmd;
st->sndbuf[1] = vv;
st->sndbuf[2] = wo ? wlen : rlen;
if (wo) { if (wo) {
memcpy(&sndbuf[3],wbuf,wlen); memcpy(&st->sndbuf[3], wbuf, wlen);
dvb_usb_generic_write(d,sndbuf,7); ret = dvb_usb_generic_write(d, st->sndbuf, 7);
} else { } else {
dvb_usb_generic_rw(d,sndbuf,7,rcvbuf,7,10); ret = dvb_usb_generic_rw(d, st->sndbuf, 7, st->rcvbuf, 7, 10);
memcpy(rbuf,&rcvbuf[3],rlen); memcpy(rbuf, &st->rcvbuf[3], rlen);
} }
return 0; return ret;
} }
/* I2C */ /* I2C */
......
...@@ -5,7 +5,10 @@ ...@@ -5,7 +5,10 @@
#include "dvb-usb.h" #include "dvb-usb.h"
struct digitv_state { struct digitv_state {
int is_nxt6000; int is_nxt6000;
unsigned char sndbuf[7];
unsigned char rcvbuf[7];
}; };
/* protocol (from usblogging and the SDK: /* protocol (from usblogging and the SDK:
......
...@@ -18,17 +18,28 @@ struct dtt200u_fe_state { ...@@ -18,17 +18,28 @@ struct dtt200u_fe_state {
struct dtv_frontend_properties fep; struct dtv_frontend_properties fep;
struct dvb_frontend frontend; struct dvb_frontend frontend;
unsigned char data[80];
struct mutex data_mutex;
}; };
static int dtt200u_fe_read_status(struct dvb_frontend *fe, static int dtt200u_fe_read_status(struct dvb_frontend *fe,
enum fe_status *stat) enum fe_status *stat)
{ {
struct dtt200u_fe_state *state = fe->demodulator_priv; struct dtt200u_fe_state *state = fe->demodulator_priv;
u8 st = GET_TUNE_STATUS, b[3]; int ret;
mutex_lock(&state->data_mutex);
state->data[0] = GET_TUNE_STATUS;
dvb_usb_generic_rw(state->d,&st,1,b,3,0); ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 3, 0);
if (ret < 0) {
*stat = 0;
mutex_unlock(&state->data_mutex);
return ret;
}
switch (b[0]) { switch (state->data[0]) {
case 0x01: case 0x01:
*stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | *stat = FE_HAS_SIGNAL | FE_HAS_CARRIER |
FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
...@@ -41,51 +52,86 @@ static int dtt200u_fe_read_status(struct dvb_frontend *fe, ...@@ -41,51 +52,86 @@ static int dtt200u_fe_read_status(struct dvb_frontend *fe,
*stat = 0; *stat = 0;
break; break;
} }
mutex_unlock(&state->data_mutex);
return 0; return 0;
} }
static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber) static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
{ {
struct dtt200u_fe_state *state = fe->demodulator_priv; struct dtt200u_fe_state *state = fe->demodulator_priv;
u8 bw = GET_VIT_ERR_CNT,b[3]; int ret;
dvb_usb_generic_rw(state->d,&bw,1,b,3,0);
*ber = (b[0] << 16) | (b[1] << 8) | b[2]; mutex_lock(&state->data_mutex);
return 0; state->data[0] = GET_VIT_ERR_CNT;
ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 3, 0);
if (ret >= 0)
*ber = (state->data[0] << 16) | (state->data[1] << 8) | state->data[2];
mutex_unlock(&state->data_mutex);
return ret;
} }
static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
{ {
struct dtt200u_fe_state *state = fe->demodulator_priv; struct dtt200u_fe_state *state = fe->demodulator_priv;
u8 bw = GET_RS_UNCOR_BLK_CNT,b[2]; int ret;
dvb_usb_generic_rw(state->d,&bw,1,b,2,0); mutex_lock(&state->data_mutex);
*unc = (b[0] << 8) | b[1]; state->data[0] = GET_RS_UNCOR_BLK_CNT;
return 0;
ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 2, 0);
if (ret >= 0)
*unc = (state->data[0] << 8) | state->data[1];
mutex_unlock(&state->data_mutex);
return ret;
} }
static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength) static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
{ {
struct dtt200u_fe_state *state = fe->demodulator_priv; struct dtt200u_fe_state *state = fe->demodulator_priv;
u8 bw = GET_AGC, b; int ret;
dvb_usb_generic_rw(state->d,&bw,1,&b,1,0);
*strength = (b << 8) | b; mutex_lock(&state->data_mutex);
return 0; state->data[0] = GET_AGC;
ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 1, 0);
if (ret >= 0)
*strength = (state->data[0] << 8) | state->data[0];
mutex_unlock(&state->data_mutex);
return ret;
} }
static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr) static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
{ {
struct dtt200u_fe_state *state = fe->demodulator_priv; struct dtt200u_fe_state *state = fe->demodulator_priv;
u8 bw = GET_SNR,br; int ret;
dvb_usb_generic_rw(state->d,&bw,1,&br,1,0);
*snr = ~((br << 8) | br); mutex_lock(&state->data_mutex);
return 0; state->data[0] = GET_SNR;
ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 1, 0);
if (ret >= 0)
*snr = ~((state->data[0] << 8) | state->data[0]);
mutex_unlock(&state->data_mutex);
return ret;
} }
static int dtt200u_fe_init(struct dvb_frontend* fe) static int dtt200u_fe_init(struct dvb_frontend* fe)
{ {
struct dtt200u_fe_state *state = fe->demodulator_priv; struct dtt200u_fe_state *state = fe->demodulator_priv;
u8 b = SET_INIT; int ret;
return dvb_usb_generic_write(state->d,&b,1);
mutex_lock(&state->data_mutex);
state->data[0] = SET_INIT;
ret = dvb_usb_generic_write(state->d, state->data, 1);
mutex_unlock(&state->data_mutex);
return ret;
} }
static int dtt200u_fe_sleep(struct dvb_frontend* fe) static int dtt200u_fe_sleep(struct dvb_frontend* fe)
...@@ -105,39 +151,40 @@ static int dtt200u_fe_set_frontend(struct dvb_frontend *fe) ...@@ -105,39 +151,40 @@ static int dtt200u_fe_set_frontend(struct dvb_frontend *fe)
{ {
struct dtv_frontend_properties *fep = &fe->dtv_property_cache; struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct dtt200u_fe_state *state = fe->demodulator_priv; struct dtt200u_fe_state *state = fe->demodulator_priv;
int i; int ret;
enum fe_status st;
u16 freq = fep->frequency / 250000; u16 freq = fep->frequency / 250000;
u8 bwbuf[2] = { SET_BANDWIDTH, 0 },freqbuf[3] = { SET_RF_FREQ, 0, 0 };
mutex_lock(&state->data_mutex);
state->data[0] = SET_BANDWIDTH;
switch (fep->bandwidth_hz) { switch (fep->bandwidth_hz) {
case 8000000: case 8000000:
bwbuf[1] = 8; state->data[1] = 8;
break; break;
case 7000000: case 7000000:
bwbuf[1] = 7; state->data[1] = 7;
break; break;
case 6000000: case 6000000:
bwbuf[1] = 6; state->data[1] = 6;
break; break;
default: default:
return -EINVAL; ret = -EINVAL;
goto ret;
} }
dvb_usb_generic_write(state->d,bwbuf,2); ret = dvb_usb_generic_write(state->d, state->data, 2);
if (ret < 0)
goto ret;
freqbuf[1] = freq & 0xff; state->data[0] = SET_RF_FREQ;
freqbuf[2] = (freq >> 8) & 0xff; state->data[1] = freq & 0xff;
dvb_usb_generic_write(state->d,freqbuf,3); state->data[2] = (freq >> 8) & 0xff;
ret = dvb_usb_generic_write(state->d, state->data, 3);
if (ret < 0)
goto ret;
for (i = 0; i < 30; i++) { ret:
msleep(20); mutex_unlock(&state->data_mutex);
dtt200u_fe_read_status(fe, &st); return ret;
if (st & FE_TIMEDOUT)
continue;
}
return 0;
} }
static int dtt200u_fe_get_frontend(struct dvb_frontend* fe, static int dtt200u_fe_get_frontend(struct dvb_frontend* fe,
...@@ -169,6 +216,7 @@ struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d) ...@@ -169,6 +216,7 @@ struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d)
deb_info("attaching frontend dtt200u\n"); deb_info("attaching frontend dtt200u\n");
state->d = d; state->d = d;
mutex_init(&state->data_mutex);
memcpy(&state->frontend.ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops)); memcpy(&state->frontend.ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state; state->frontend.demodulator_priv = state;
......
...@@ -20,75 +20,114 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB ...@@ -20,75 +20,114 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
struct dtt200u_state {
unsigned char data[80];
struct mutex data_mutex;
};
static int dtt200u_power_ctrl(struct dvb_usb_device *d, int onoff) static int dtt200u_power_ctrl(struct dvb_usb_device *d, int onoff)
{ {
u8 b = SET_INIT; struct dtt200u_state *st = d->priv;
int ret = 0;
mutex_lock(&st->data_mutex);
st->data[0] = SET_INIT;
if (onoff) if (onoff)
dvb_usb_generic_write(d,&b,2); ret = dvb_usb_generic_write(d, st->data, 2);
return 0; mutex_unlock(&st->data_mutex);
return ret;
} }
static int dtt200u_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) static int dtt200u_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
{ {
u8 b_streaming[2] = { SET_STREAMING, onoff }; struct dtt200u_state *st = adap->dev->priv;
u8 b_rst_pid = RESET_PID_FILTER; int ret;
dvb_usb_generic_write(adap->dev, b_streaming, 2); mutex_lock(&st->data_mutex);
st->data[0] = SET_STREAMING;
st->data[1] = onoff;
if (onoff == 0) ret = dvb_usb_generic_write(adap->dev, st->data, 2);
dvb_usb_generic_write(adap->dev, &b_rst_pid, 1); if (ret < 0)
return 0; goto ret;
if (onoff)
goto ret;
st->data[0] = RESET_PID_FILTER;
ret = dvb_usb_generic_write(adap->dev, st->data, 1);
ret:
mutex_unlock(&st->data_mutex);
return ret;
} }
static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff)
{ {
u8 b_pid[4]; struct dtt200u_state *st = adap->dev->priv;
int ret;
pid = onoff ? pid : 0; pid = onoff ? pid : 0;
b_pid[0] = SET_PID_FILTER; mutex_lock(&st->data_mutex);
b_pid[1] = index; st->data[0] = SET_PID_FILTER;
b_pid[2] = pid & 0xff; st->data[1] = index;
b_pid[3] = (pid >> 8) & 0x1f; st->data[2] = pid & 0xff;
st->data[3] = (pid >> 8) & 0x1f;
return dvb_usb_generic_write(adap->dev, b_pid, 4); ret = dvb_usb_generic_write(adap->dev, st->data, 4);
mutex_unlock(&st->data_mutex);
return ret;
} }
static int dtt200u_rc_query(struct dvb_usb_device *d) static int dtt200u_rc_query(struct dvb_usb_device *d)
{ {
u8 key[5],cmd = GET_RC_CODE; struct dtt200u_state *st = d->priv;
u32 scancode; u32 scancode;
int ret;
mutex_lock(&st->data_mutex);
st->data[0] = GET_RC_CODE;
ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 5, 0);
if (ret < 0)
goto ret;
dvb_usb_generic_rw(d,&cmd,1,key,5,0); if (st->data[0] == 1) {
if (key[0] == 1) {
enum rc_type proto = RC_TYPE_NEC; enum rc_type proto = RC_TYPE_NEC;
scancode = key[1]; scancode = st->data[1];
if ((u8) ~key[1] != key[2]) { if ((u8) ~st->data[1] != st->data[2]) {
/* Extended NEC */ /* Extended NEC */
scancode = scancode << 8; scancode = scancode << 8;
scancode |= key[2]; scancode |= st->data[2];
proto = RC_TYPE_NECX; proto = RC_TYPE_NECX;
} }
scancode = scancode << 8; scancode = scancode << 8;
scancode |= key[3]; scancode |= st->data[3];
/* Check command checksum is ok */ /* Check command checksum is ok */
if ((u8) ~key[3] == key[4]) if ((u8) ~st->data[3] == st->data[4])
rc_keydown(d->rc_dev, proto, scancode, 0); rc_keydown(d->rc_dev, proto, scancode, 0);
else else
rc_keyup(d->rc_dev); rc_keyup(d->rc_dev);
} else if (key[0] == 2) { } else if (st->data[0] == 2) {
rc_repeat(d->rc_dev); rc_repeat(d->rc_dev);
} else { } else {
rc_keyup(d->rc_dev); rc_keyup(d->rc_dev);
} }
if (key[0] != 0) if (st->data[0] != 0)
deb_info("key: %*ph\n", 5, key); deb_info("st->data: %*ph\n", 5, st->data);
return 0; ret:
mutex_unlock(&st->data_mutex);
return ret;
} }
static int dtt200u_frontend_attach(struct dvb_usb_adapter *adap) static int dtt200u_frontend_attach(struct dvb_usb_adapter *adap)
...@@ -106,17 +145,24 @@ static struct dvb_usb_device_properties wt220u_miglia_properties; ...@@ -106,17 +145,24 @@ static struct dvb_usb_device_properties wt220u_miglia_properties;
static int dtt200u_usb_probe(struct usb_interface *intf, static int dtt200u_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
struct dvb_usb_device *d;
struct dtt200u_state *st;
if (0 == dvb_usb_device_init(intf, &dtt200u_properties, if (0 == dvb_usb_device_init(intf, &dtt200u_properties,
THIS_MODULE, NULL, adapter_nr) || THIS_MODULE, &d, adapter_nr) ||
0 == dvb_usb_device_init(intf, &wt220u_properties, 0 == dvb_usb_device_init(intf, &wt220u_properties,
THIS_MODULE, NULL, adapter_nr) || THIS_MODULE, &d, adapter_nr) ||
0 == dvb_usb_device_init(intf, &wt220u_fc_properties, 0 == dvb_usb_device_init(intf, &wt220u_fc_properties,
THIS_MODULE, NULL, adapter_nr) || THIS_MODULE, &d, adapter_nr) ||
0 == dvb_usb_device_init(intf, &wt220u_zl0353_properties, 0 == dvb_usb_device_init(intf, &wt220u_zl0353_properties,
THIS_MODULE, NULL, adapter_nr) || THIS_MODULE, &d, adapter_nr) ||
0 == dvb_usb_device_init(intf, &wt220u_miglia_properties, 0 == dvb_usb_device_init(intf, &wt220u_miglia_properties,
THIS_MODULE, NULL, adapter_nr)) THIS_MODULE, &d, adapter_nr)) {
st = d->priv;
mutex_init(&st->data_mutex);
return 0; return 0;
}
return -ENODEV; return -ENODEV;
} }
...@@ -140,6 +186,8 @@ static struct dvb_usb_device_properties dtt200u_properties = { ...@@ -140,6 +186,8 @@ static struct dvb_usb_device_properties dtt200u_properties = {
.usb_ctrl = CYPRESS_FX2, .usb_ctrl = CYPRESS_FX2,
.firmware = "dvb-usb-dtt200u-01.fw", .firmware = "dvb-usb-dtt200u-01.fw",
.size_of_priv = sizeof(struct dtt200u_state),
.num_adapters = 1, .num_adapters = 1,
.adapter = { .adapter = {
{ {
...@@ -190,6 +238,8 @@ static struct dvb_usb_device_properties wt220u_properties = { ...@@ -190,6 +238,8 @@ static struct dvb_usb_device_properties wt220u_properties = {
.usb_ctrl = CYPRESS_FX2, .usb_ctrl = CYPRESS_FX2,
.firmware = "dvb-usb-wt220u-02.fw", .firmware = "dvb-usb-wt220u-02.fw",
.size_of_priv = sizeof(struct dtt200u_state),
.num_adapters = 1, .num_adapters = 1,
.adapter = { .adapter = {
{ {
...@@ -240,6 +290,8 @@ static struct dvb_usb_device_properties wt220u_fc_properties = { ...@@ -240,6 +290,8 @@ static struct dvb_usb_device_properties wt220u_fc_properties = {
.usb_ctrl = CYPRESS_FX2, .usb_ctrl = CYPRESS_FX2,
.firmware = "dvb-usb-wt220u-fc03.fw", .firmware = "dvb-usb-wt220u-fc03.fw",
.size_of_priv = sizeof(struct dtt200u_state),
.num_adapters = 1, .num_adapters = 1,
.adapter = { .adapter = {
{ {
...@@ -290,6 +342,8 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = { ...@@ -290,6 +342,8 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = {
.usb_ctrl = CYPRESS_FX2, .usb_ctrl = CYPRESS_FX2,
.firmware = "dvb-usb-wt220u-zl0353-01.fw", .firmware = "dvb-usb-wt220u-zl0353-01.fw",
.size_of_priv = sizeof(struct dtt200u_state),
.num_adapters = 1, .num_adapters = 1,
.adapter = { .adapter = {
{ {
...@@ -340,6 +394,8 @@ static struct dvb_usb_device_properties wt220u_miglia_properties = { ...@@ -340,6 +394,8 @@ static struct dvb_usb_device_properties wt220u_miglia_properties = {
.usb_ctrl = CYPRESS_FX2, .usb_ctrl = CYPRESS_FX2,
.firmware = "dvb-usb-wt220u-miglia-01.fw", .firmware = "dvb-usb-wt220u-miglia-01.fw",
.size_of_priv = sizeof(struct dtt200u_state),
.num_adapters = 1, .num_adapters = 1,
.generic_bulk_ctrl_endpoint = 0x01, .generic_bulk_ctrl_endpoint = 0x01,
......
...@@ -31,9 +31,14 @@ module_param_named(debug, dvb_usb_dtv5100_debug, int, 0644); ...@@ -31,9 +31,14 @@ module_param_named(debug, dvb_usb_dtv5100_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
struct dtv5100_state {
unsigned char data[80];
};
static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr, static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr,
u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
{ {
struct dtv5100_state *st = d->priv;
u8 request; u8 request;
u8 type; u8 type;
u16 value; u16 value;
...@@ -60,9 +65,10 @@ static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr, ...@@ -60,9 +65,10 @@ static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr,
} }
index = (addr << 8) + wbuf[0]; index = (addr << 8) + wbuf[0];
memcpy(st->data, rbuf, rlen);
msleep(1); /* avoid I2C errors */ msleep(1); /* avoid I2C errors */
return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), request, return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), request,
type, value, index, rbuf, rlen, type, value, index, st->data, rlen,
DTV5100_USB_TIMEOUT); DTV5100_USB_TIMEOUT);
} }
...@@ -176,7 +182,7 @@ static struct dvb_usb_device_properties dtv5100_properties = { ...@@ -176,7 +182,7 @@ static struct dvb_usb_device_properties dtv5100_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER, .caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC, .usb_ctrl = DEVICE_SPECIFIC,
.size_of_priv = 0, .size_of_priv = sizeof(struct dtv5100_state),
.num_adapters = 1, .num_adapters = 1,
.adapter = {{ .adapter = {{
......
...@@ -852,7 +852,7 @@ static int su3000_power_ctrl(struct dvb_usb_device *d, int i) ...@@ -852,7 +852,7 @@ static int su3000_power_ctrl(struct dvb_usb_device *d, int i)
if (i && !state->initialized) { if (i && !state->initialized) {
state->initialized = 1; state->initialized = 1;
/* reset board */ /* reset board */
dvb_usb_generic_rw(d, obuf, 2, NULL, 0, 0); return dvb_usb_generic_rw(d, obuf, 2, NULL, 0, 0);
} }
return 0; return 0;
......
...@@ -24,6 +24,10 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DV ...@@ -24,6 +24,10 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DV
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
struct gp8psk_state {
unsigned char data[80];
};
static int gp8psk_get_fw_version(struct dvb_usb_device *d, u8 *fw_vers) static int gp8psk_get_fw_version(struct dvb_usb_device *d, u8 *fw_vers)
{ {
return (gp8psk_usb_in_op(d, GET_FW_VERS, 0, 0, fw_vers, 6)); return (gp8psk_usb_in_op(d, GET_FW_VERS, 0, 0, fw_vers, 6));
...@@ -53,17 +57,22 @@ static void gp8psk_info(struct dvb_usb_device *d) ...@@ -53,17 +57,22 @@ static void gp8psk_info(struct dvb_usb_device *d)
int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
{ {
struct gp8psk_state *st = d->priv;
int ret = 0,try = 0; int ret = 0,try = 0;
if (blen > sizeof(st->data))
return -EIO;
if ((ret = mutex_lock_interruptible(&d->usb_mutex))) if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
return ret; return ret;
while (ret >= 0 && ret != blen && try < 3) { while (ret >= 0 && ret != blen && try < 3) {
memcpy(st->data, b, blen);
ret = usb_control_msg(d->udev, ret = usb_control_msg(d->udev,
usb_rcvctrlpipe(d->udev,0), usb_rcvctrlpipe(d->udev,0),
req, req,
USB_TYPE_VENDOR | USB_DIR_IN, USB_TYPE_VENDOR | USB_DIR_IN,
value,index,b,blen, value, index, st->data, blen,
2000); 2000);
deb_info("reading number %d (ret: %d)\n",try,ret); deb_info("reading number %d (ret: %d)\n",try,ret);
try++; try++;
...@@ -86,19 +95,24 @@ int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 ...@@ -86,19 +95,24 @@ int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8
int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
u16 index, u8 *b, int blen) u16 index, u8 *b, int blen)
{ {
struct gp8psk_state *st = d->priv;
int ret; int ret;
deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index); deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
debug_dump(b,blen,deb_xfer); debug_dump(b,blen,deb_xfer);
if (blen > sizeof(st->data))
return -EIO;
if ((ret = mutex_lock_interruptible(&d->usb_mutex))) if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
return ret; return ret;
memcpy(st->data, b, blen);
if (usb_control_msg(d->udev, if (usb_control_msg(d->udev,
usb_sndctrlpipe(d->udev,0), usb_sndctrlpipe(d->udev,0),
req, req,
USB_TYPE_VENDOR | USB_DIR_OUT, USB_TYPE_VENDOR | USB_DIR_OUT,
value,index,b,blen, value, index, st->data, blen,
2000) != blen) { 2000) != blen) {
warn("usb out operation failed."); warn("usb out operation failed.");
ret = -EIO; ret = -EIO;
...@@ -143,6 +157,11 @@ static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d) ...@@ -143,6 +157,11 @@ static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d)
err("failed to load bcm4500 firmware."); err("failed to load bcm4500 firmware.");
goto out_free; goto out_free;
} }
if (buflen > 64) {
err("firmare chunk size bigger than 64 bytes.");
goto out_free;
}
memcpy(buf, ptr, buflen); memcpy(buf, ptr, buflen);
if (dvb_usb_generic_write(d, buf, buflen)) { if (dvb_usb_generic_write(d, buf, buflen)) {
err("failed to load bcm4500 firmware."); err("failed to load bcm4500 firmware.");
...@@ -265,6 +284,8 @@ static struct dvb_usb_device_properties gp8psk_properties = { ...@@ -265,6 +284,8 @@ static struct dvb_usb_device_properties gp8psk_properties = {
.usb_ctrl = CYPRESS_FX2, .usb_ctrl = CYPRESS_FX2,
.firmware = "dvb-usb-gp8psk-01.fw", .firmware = "dvb-usb-gp8psk-01.fw",
.size_of_priv = sizeof(struct gp8psk_state),
.num_adapters = 1, .num_adapters = 1,
.adapter = { .adapter = {
{ {
......
...@@ -74,22 +74,31 @@ static struct rc_map_table rc_map_haupp_table[] = { ...@@ -74,22 +74,31 @@ static struct rc_map_table rc_map_haupp_table[] = {
*/ */
static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state) static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
{ {
u8 key[5],cmd[2] = { DIBUSB_REQ_POLL_REMOTE, 0x35 }, data,toggle,custom; u8 *buf, data, toggle, custom;
u16 raw; u16 raw;
int i; int i, ret;
struct dibusb_device_state *st = d->priv; struct dibusb_device_state *st = d->priv;
dvb_usb_generic_rw(d,cmd,2,key,5,0); buf = kmalloc(5, GFP_KERNEL);
if (!buf)
return -ENOMEM;
buf[0] = DIBUSB_REQ_POLL_REMOTE;
buf[1] = 0x35;
ret = dvb_usb_generic_rw(d, buf, 2, buf, 5, 0);
if (ret < 0)
goto ret;
*state = REMOTE_NO_KEY_PRESSED; *state = REMOTE_NO_KEY_PRESSED;
switch (key[0]) { switch (buf[0]) {
case DIBUSB_RC_HAUPPAUGE_KEY_PRESSED: case DIBUSB_RC_HAUPPAUGE_KEY_PRESSED:
raw = ((key[1] << 8) | key[2]) >> 3; raw = ((buf[1] << 8) | buf[2]) >> 3;
toggle = !!(raw & 0x800); toggle = !!(raw & 0x800);
data = raw & 0x3f; data = raw & 0x3f;
custom = (raw >> 6) & 0x1f; custom = (raw >> 6) & 0x1f;
deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to c: %02x d: %02x toggle: %d\n",key[1],key[2],key[3],custom,data,toggle); deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to c: %02x d: %02x toggle: %d\n",
buf[1], buf[2], buf[3], custom, data, toggle);
for (i = 0; i < ARRAY_SIZE(rc_map_haupp_table); i++) { for (i = 0; i < ARRAY_SIZE(rc_map_haupp_table); i++) {
if (rc5_data(&rc_map_haupp_table[i]) == data && if (rc5_data(&rc_map_haupp_table[i]) == data &&
...@@ -117,7 +126,9 @@ static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state) ...@@ -117,7 +126,9 @@ static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
break; break;
} }
return 0; ret:
kfree(buf);
return ret;
} }
static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6]) static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6])
......
...@@ -97,48 +97,53 @@ struct pctv452e_state { ...@@ -97,48 +97,53 @@ struct pctv452e_state {
u8 c; /* transaction counter, wraps around... */ u8 c; /* transaction counter, wraps around... */
u8 initialized; /* set to 1 if 0x15 has been sent */ u8 initialized; /* set to 1 if 0x15 has been sent */
u16 last_rc_key; u16 last_rc_key;
unsigned char data[80];
}; };
static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data,
unsigned int write_len, unsigned int read_len) unsigned int write_len, unsigned int read_len)
{ {
struct pctv452e_state *state = (struct pctv452e_state *)d->priv; struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
u8 buf[64];
u8 id; u8 id;
unsigned int rlen; unsigned int rlen;
int ret; int ret;
BUG_ON(NULL == data && 0 != (write_len | read_len)); if (!data || (write_len > 64 - 4) || (read_len > 64 - 4)) {
BUG_ON(write_len > 64 - 4); err("%s: transfer data invalid", __func__);
BUG_ON(read_len > 64 - 4); return -EIO;
}
mutex_lock(&state->ca_mutex);
id = state->c++; id = state->c++;
buf[0] = SYNC_BYTE_OUT; state->data[0] = SYNC_BYTE_OUT;
buf[1] = id; state->data[1] = id;
buf[2] = cmd; state->data[2] = cmd;
buf[3] = write_len; state->data[3] = write_len;
memcpy(buf + 4, data, write_len); memcpy(state->data + 4, data, write_len);
rlen = (read_len > 0) ? 64 : 0; rlen = (read_len > 0) ? 64 : 0;
ret = dvb_usb_generic_rw(d, buf, 4 + write_len, ret = dvb_usb_generic_rw(d, state->data, 4 + write_len,
buf, rlen, /* delay_ms */ 0); state->data, rlen, /* delay_ms */ 0);
if (0 != ret) if (0 != ret)
goto failed; goto failed;
ret = -EIO; ret = -EIO;
if (SYNC_BYTE_IN != buf[0] || id != buf[1]) if (SYNC_BYTE_IN != state->data[0] || id != state->data[1])
goto failed; goto failed;
memcpy(data, buf + 4, read_len); memcpy(data, state->data + 4, read_len);
mutex_unlock(&state->ca_mutex);
return 0; return 0;
failed: failed:
err("CI error %d; %02X %02X %02X -> %*ph.", err("CI error %d; %02X %02X %02X -> %*ph.",
ret, SYNC_BYTE_OUT, id, cmd, 3, buf); ret, SYNC_BYTE_OUT, id, cmd, 3, state->data);
mutex_unlock(&state->ca_mutex);
return ret; return ret;
} }
...@@ -405,52 +410,53 @@ static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr, ...@@ -405,52 +410,53 @@ static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr,
u8 *rcv_buf, u8 rcv_len) u8 *rcv_buf, u8 rcv_len)
{ {
struct pctv452e_state *state = (struct pctv452e_state *)d->priv; struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
u8 buf[64];
u8 id; u8 id;
int ret; int ret;
mutex_lock(&state->ca_mutex);
id = state->c++; id = state->c++;
ret = -EINVAL; ret = -EINVAL;
if (snd_len > 64 - 7 || rcv_len > 64 - 7) if (snd_len > 64 - 7 || rcv_len > 64 - 7)
goto failed; goto failed;
buf[0] = SYNC_BYTE_OUT; state->data[0] = SYNC_BYTE_OUT;
buf[1] = id; state->data[1] = id;
buf[2] = PCTV_CMD_I2C; state->data[2] = PCTV_CMD_I2C;
buf[3] = snd_len + 3; state->data[3] = snd_len + 3;
buf[4] = addr << 1; state->data[4] = addr << 1;
buf[5] = snd_len; state->data[5] = snd_len;
buf[6] = rcv_len; state->data[6] = rcv_len;
memcpy(buf + 7, snd_buf, snd_len); memcpy(state->data + 7, snd_buf, snd_len);
ret = dvb_usb_generic_rw(d, buf, 7 + snd_len, ret = dvb_usb_generic_rw(d, state->data, 7 + snd_len,
buf, /* rcv_len */ 64, state->data, /* rcv_len */ 64,
/* delay_ms */ 0); /* delay_ms */ 0);
if (ret < 0) if (ret < 0)
goto failed; goto failed;
/* TT USB protocol error. */ /* TT USB protocol error. */
ret = -EIO; ret = -EIO;
if (SYNC_BYTE_IN != buf[0] || id != buf[1]) if (SYNC_BYTE_IN != state->data[0] || id != state->data[1])
goto failed; goto failed;
/* I2C device didn't respond as expected. */ /* I2C device didn't respond as expected. */
ret = -EREMOTEIO; ret = -EREMOTEIO;
if (buf[5] < snd_len || buf[6] < rcv_len) if (state->data[5] < snd_len || state->data[6] < rcv_len)
goto failed; goto failed;
memcpy(rcv_buf, buf + 7, rcv_len); memcpy(rcv_buf, state->data + 7, rcv_len);
mutex_unlock(&state->ca_mutex);
return rcv_len; return rcv_len;
failed: failed:
err("I2C error %d; %02X %02X %02X %02X %02X -> " err("I2C error %d; %02X %02X %02X %02X %02X -> %*ph",
"%02X %02X %02X %02X %02X.",
ret, SYNC_BYTE_OUT, id, addr << 1, snd_len, rcv_len, ret, SYNC_BYTE_OUT, id, addr << 1, snd_len, rcv_len,
buf[0], buf[1], buf[4], buf[5], buf[6]); 7, state->data);
mutex_unlock(&state->ca_mutex);
return ret; return ret;
} }
...@@ -499,8 +505,7 @@ static u32 pctv452e_i2c_func(struct i2c_adapter *adapter) ...@@ -499,8 +505,7 @@ static u32 pctv452e_i2c_func(struct i2c_adapter *adapter)
static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i) static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
{ {
struct pctv452e_state *state = (struct pctv452e_state *)d->priv; struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
u8 b0[] = { 0xaa, 0, PCTV_CMD_RESET, 1, 0 }; u8 *rx;
u8 rx[PCTV_ANSWER_LEN];
int ret; int ret;
info("%s: %d\n", __func__, i); info("%s: %d\n", __func__, i);
...@@ -511,6 +516,11 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i) ...@@ -511,6 +516,11 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
if (state->initialized) if (state->initialized)
return 0; return 0;
rx = kmalloc(PCTV_ANSWER_LEN, GFP_KERNEL);
if (!rx)
return -ENOMEM;
mutex_lock(&state->ca_mutex);
/* hmm where shoud this should go? */ /* hmm where shoud this should go? */
ret = usb_set_interface(d->udev, 0, ISOC_INTERFACE_ALTERNATIVE); ret = usb_set_interface(d->udev, 0, ISOC_INTERFACE_ALTERNATIVE);
if (ret != 0) if (ret != 0)
...@@ -518,65 +528,75 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i) ...@@ -518,65 +528,75 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
__func__, ret); __func__, ret);
/* this is a one-time initialization, dont know where to put */ /* this is a one-time initialization, dont know where to put */
b0[1] = state->c++; state->data[0] = 0xaa;
state->data[1] = state->c++;
state->data[2] = PCTV_CMD_RESET;
state->data[3] = 1;
state->data[4] = 0;
/* reset board */ /* reset board */
ret = dvb_usb_generic_rw(d, b0, sizeof(b0), rx, PCTV_ANSWER_LEN, 0); ret = dvb_usb_generic_rw(d, state->data, 5, rx, PCTV_ANSWER_LEN, 0);
if (ret) if (ret)
return ret; goto ret;
b0[1] = state->c++; state->data[1] = state->c++;
b0[4] = 1; state->data[4] = 1;
/* reset board (again?) */ /* reset board (again?) */
ret = dvb_usb_generic_rw(d, b0, sizeof(b0), rx, PCTV_ANSWER_LEN, 0); ret = dvb_usb_generic_rw(d, state->data, 5, rx, PCTV_ANSWER_LEN, 0);
if (ret) if (ret)
return ret; goto ret;
state->initialized = 1; state->initialized = 1;
return 0; ret:
mutex_unlock(&state->ca_mutex);
kfree(rx);
return ret;
} }
static int pctv452e_rc_query(struct dvb_usb_device *d) static int pctv452e_rc_query(struct dvb_usb_device *d)
{ {
struct pctv452e_state *state = (struct pctv452e_state *)d->priv; struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
u8 b[CMD_BUFFER_SIZE];
u8 rx[PCTV_ANSWER_LEN];
int ret, i; int ret, i;
u8 id = state->c++; u8 id;
mutex_lock(&state->ca_mutex);
id = state->c++;
/* prepare command header */ /* prepare command header */
b[0] = SYNC_BYTE_OUT; state->data[0] = SYNC_BYTE_OUT;
b[1] = id; state->data[1] = id;
b[2] = PCTV_CMD_IR; state->data[2] = PCTV_CMD_IR;
b[3] = 0; state->data[3] = 0;
/* send ir request */ /* send ir request */
ret = dvb_usb_generic_rw(d, b, 4, rx, PCTV_ANSWER_LEN, 0); ret = dvb_usb_generic_rw(d, state->data, 4,
state->data, PCTV_ANSWER_LEN, 0);
if (ret != 0) if (ret != 0)
return ret; goto ret;
if (debug > 3) { if (debug > 3) {
info("%s: read: %2d: %*ph: ", __func__, ret, 3, rx); info("%s: read: %2d: %*ph: ", __func__, ret, 3, state->data);
for (i = 0; (i < rx[3]) && ((i+3) < PCTV_ANSWER_LEN); i++) for (i = 0; (i < state->data[3]) && ((i + 3) < PCTV_ANSWER_LEN); i++)
info(" %02x", rx[i+3]); info(" %02x", state->data[i + 3]);
info("\n"); info("\n");
} }
if ((rx[3] == 9) && (rx[12] & 0x01)) { if ((state->data[3] == 9) && (state->data[12] & 0x01)) {
/* got a "press" event */ /* got a "press" event */
state->last_rc_key = RC_SCANCODE_RC5(rx[7], rx[6]); state->last_rc_key = RC_SCANCODE_RC5(state->data[7], state->data[6]);
if (debug > 2) if (debug > 2)
info("%s: cmd=0x%02x sys=0x%02x\n", info("%s: cmd=0x%02x sys=0x%02x\n",
__func__, rx[6], rx[7]); __func__, state->data[6], state->data[7]);
rc_keydown(d->rc_dev, RC_TYPE_RC5, state->last_rc_key, 0); rc_keydown(d->rc_dev, RC_TYPE_RC5, state->last_rc_key, 0);
} else if (state->last_rc_key) { } else if (state->last_rc_key) {
rc_keyup(d->rc_dev); rc_keyup(d->rc_dev);
state->last_rc_key = 0; state->last_rc_key = 0;
} }
ret:
return 0; mutex_unlock(&state->ca_mutex);
return ret;
} }
static int pctv452e_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) static int pctv452e_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
......
...@@ -89,9 +89,13 @@ struct technisat_usb2_state { ...@@ -89,9 +89,13 @@ struct technisat_usb2_state {
static int technisat_usb2_i2c_access(struct usb_device *udev, static int technisat_usb2_i2c_access(struct usb_device *udev,
u8 device_addr, u8 *tx, u8 txlen, u8 *rx, u8 rxlen) u8 device_addr, u8 *tx, u8 txlen, u8 *rx, u8 rxlen)
{ {
u8 b[64]; u8 *b;
int ret, actual_length; int ret, actual_length;
b = kmalloc(64, GFP_KERNEL);
if (!b)
return -ENOMEM;
deb_i2c("i2c-access: %02x, tx: ", device_addr); deb_i2c("i2c-access: %02x, tx: ", device_addr);
debug_dump(tx, txlen, deb_i2c); debug_dump(tx, txlen, deb_i2c);
deb_i2c(" "); deb_i2c(" ");
...@@ -123,7 +127,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev, ...@@ -123,7 +127,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev,
if (ret < 0) { if (ret < 0) {
err("i2c-error: out failed %02x = %d", device_addr, ret); err("i2c-error: out failed %02x = %d", device_addr, ret);
return -ENODEV; goto err;
} }
ret = usb_bulk_msg(udev, ret = usb_bulk_msg(udev,
...@@ -131,7 +135,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev, ...@@ -131,7 +135,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev,
b, 64, &actual_length, 1000); b, 64, &actual_length, 1000);
if (ret < 0) { if (ret < 0) {
err("i2c-error: in failed %02x = %d", device_addr, ret); err("i2c-error: in failed %02x = %d", device_addr, ret);
return -ENODEV; goto err;
} }
if (b[0] != I2C_STATUS_OK) { if (b[0] != I2C_STATUS_OK) {
...@@ -140,7 +144,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev, ...@@ -140,7 +144,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev,
if (!(b[0] == I2C_STATUS_NAK && if (!(b[0] == I2C_STATUS_NAK &&
device_addr == 0x60 device_addr == 0x60
/* && device_is_technisat_usb2 */)) /* && device_is_technisat_usb2 */))
return -ENODEV; goto err;
} }
deb_i2c("status: %d, ", b[0]); deb_i2c("status: %d, ", b[0]);
...@@ -154,7 +158,9 @@ static int technisat_usb2_i2c_access(struct usb_device *udev, ...@@ -154,7 +158,9 @@ static int technisat_usb2_i2c_access(struct usb_device *udev,
deb_i2c("\n"); deb_i2c("\n");
return 0; err:
kfree(b);
return ret;
} }
static int technisat_usb2_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, static int technisat_usb2_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
......
...@@ -1901,19 +1901,30 @@ static long s2255_vendor_req(struct s2255_dev *dev, unsigned char Request, ...@@ -1901,19 +1901,30 @@ static long s2255_vendor_req(struct s2255_dev *dev, unsigned char Request,
s32 TransferBufferLength, int bOut) s32 TransferBufferLength, int bOut)
{ {
int r; int r;
unsigned char *buf;
buf = kmalloc(TransferBufferLength, GFP_KERNEL);
if (!buf)
return -ENOMEM;
if (!bOut) { if (!bOut) {
r = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), r = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
Request, Request,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_TYPE_VENDOR | USB_RECIP_DEVICE |
USB_DIR_IN, USB_DIR_IN,
Value, Index, TransferBuffer, Value, Index, buf,
TransferBufferLength, HZ * 5); TransferBufferLength, HZ * 5);
if (r >= 0)
memcpy(TransferBuffer, buf, TransferBufferLength);
} else { } else {
memcpy(buf, TransferBuffer, TransferBufferLength);
r = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), r = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
Request, USB_TYPE_VENDOR | USB_RECIP_DEVICE, Request, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Value, Index, TransferBuffer, Value, Index, buf,
TransferBufferLength, HZ * 5); TransferBufferLength, HZ * 5);
} }
kfree(buf);
return r; return r;
} }
......
...@@ -147,20 +147,26 @@ int stk_camera_write_reg(struct stk_camera *dev, u16 index, u8 value) ...@@ -147,20 +147,26 @@ int stk_camera_write_reg(struct stk_camera *dev, u16 index, u8 value)
int stk_camera_read_reg(struct stk_camera *dev, u16 index, int *value) int stk_camera_read_reg(struct stk_camera *dev, u16 index, int *value)
{ {
struct usb_device *udev = dev->udev; struct usb_device *udev = dev->udev;
unsigned char *buf;
int ret; int ret;
buf = kmalloc(sizeof(u8), GFP_KERNEL);
if (!buf)
return -ENOMEM;
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
0x00, 0x00,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0x00, 0x00,
index, index,
(u8 *) value, buf,
sizeof(u8), sizeof(u8),
500); 500);
if (ret < 0) if (ret >= 0)
return ret; memcpy(value, buf, sizeof(u8));
else
return 0; kfree(buf);
return ret;
} }
static int stk_start_stream(struct stk_camera *dev) static int stk_start_stream(struct stk_camera *dev)
......
...@@ -482,6 +482,8 @@ static int bcm2048_set_rds_no_lock(struct bcm2048_device *bdev, u8 rds_on) ...@@ -482,6 +482,8 @@ static int bcm2048_set_rds_no_lock(struct bcm2048_device *bdev, u8 rds_on)
flags); flags);
memset(&bdev->rds_info, 0, sizeof(bdev->rds_info)); memset(&bdev->rds_info, 0, sizeof(bdev->rds_info));
} }
if (err)
return err;
return bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM, return bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM,
bdev->cache_fm_rds_system); bdev->cache_fm_rds_system);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment