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,
u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR;
u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) |
(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,
request,
request_type, /* 0xc0 read or 0x40 write */
wAddress,
0,
val,
fc_usb->data,
sizeof(u32),
B2C2_WAIT_FOR_OPERATION_RDW * HZ);
if (len != sizeof(u32)) {
if (ret != sizeof(u32)) {
err("error while %s dword from %d (%d).", read ? "reading" :
"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
......@@ -100,9 +111,14 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,
{
u8 request_type = USB_TYPE_VENDOR;
u16 wIndex;
int nWaitTime, pipe, len;
int nWaitTime, pipe, ret;
wIndex = page << 8;
if (buflen > sizeof(fc_usb->data)) {
err("Buffer size bigger than max URB control message\n");
return -EIO;
}
switch (req) {
case B2C2_USB_READ_V8_MEM:
nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ;
......@@ -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,
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,
request_type,
wAddress,
wIndex,
pbBuffer,
fc_usb->data,
buflen,
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);
return len == buflen ? 0 : -EIO;
mutex_unlock(&fc_usb->data_mutex);
debug_dump(pbBuffer, ret, deb_v8);
return ret;
}
#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)
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 */
static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
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,
{
struct flexcop_usb *fc_usb = i2c->fc->bus_specific;
u16 wValue, wIndex;
int nWaitTime,pipe,len;
int nWaitTime, pipe, ret;
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) {
case USB_FUNC_I2C_WRITE:
case USB_FUNC_I2C_MULTIWRITE:
......@@ -257,15 +270,32 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
wValue & 0xff, wValue >> 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,
request_type,
wValue,
wIndex,
buf,
fc_usb->data,
buflen,
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,
......@@ -516,6 +546,7 @@ static int flexcop_usb_probe(struct usb_interface *intf,
/* general flexcop init */
fc_usb = fc->bus_specific;
fc_usb->fc_dev = fc;
mutex_init(&fc_usb->data_mutex);
fc->read_ibi_reg = flexcop_usb_read_ibi_reg;
fc->write_ibi_reg = flexcop_usb_write_ibi_reg;
......
......@@ -29,6 +29,10 @@ struct flexcop_usb {
u8 tmp_buffer[1023+190];
int tmp_buffer_length;
/* for URB control messages */
u8 data[80];
struct mutex data_mutex;
};
#if 0
......
......@@ -545,18 +545,30 @@ static void free_sbufs(struct camera_data *cam)
static int write_packet(struct usb_device *udev,
u8 request, u8 * registers, u16 start, size_t size)
{
unsigned char *buf;
int ret;
if (!registers || size <= 0)
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),
request,
USB_TYPE_VENDOR | USB_RECIP_DEVICE,
start, /* value */
0, /* index */
registers, /* buffer */
buf, /* buffer */
size,
HZ);
kfree(buf);
return ret;
}
/****************************************************************************
......@@ -567,18 +579,32 @@ static int write_packet(struct usb_device *udev,
static int read_packet(struct usb_device *udev,
u8 request, u8 * registers, u16 start, size_t size)
{
unsigned char *buf;
int ret;
if (!registers || size <= 0)
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),
request,
USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE,
start, /* value */
0, /* index */
registers, /* buffer */
buf, /* buffer */
size,
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);
struct cinergyt2_state {
u8 rc_counter;
unsigned char data[64];
struct mutex data_mutex;
};
/* We are missing a release hook with usb_device data */
......@@ -50,38 +52,57 @@ static struct dvb_usb_device_properties cinergyt2_properties;
static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable)
{
char buf[] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 };
char result[64];
return dvb_usb_generic_rw(adap->dev, buf, sizeof(buf), result,
sizeof(result), 0);
struct dvb_usb_device *d = adap->dev;
struct cinergyt2_state *st = d->priv;
int ret;
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)
{
char buf[] = { CINERGYT2_EP1_SLEEP_MODE, enable ? 0 : 1 };
char state[3];
return dvb_usb_generic_rw(d, buf, sizeof(buf), state, sizeof(state), 0);
struct cinergyt2_state *st = d->priv;
int ret;
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)
{
char query[] = { CINERGYT2_EP1_GET_FIRMWARE_VERSION };
char state[3];
struct dvb_usb_device *d = adap->dev;
struct cinergyt2_state *st = d->priv;
int ret;
adap->fe_adap[0].fe = cinergyt2_fe_attach(adap->dev);
ret = dvb_usb_generic_rw(adap->dev, query, sizeof(query), state,
sizeof(state), 0);
mutex_lock(&st->data_mutex);
st->data[0] = CINERGYT2_EP1_GET_FIRMWARE_VERSION;
ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 3, 0);
if (ret < 0) {
deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep "
"state info\n");
}
mutex_unlock(&st->data_mutex);
/* Copy this pointer as we are gonna need it in the release phase */
cinergyt2_usb_device = adap->dev;
return 0;
return ret;
}
static struct rc_map_table rc_map_cinergyt2_table[] = {
......@@ -141,13 +162,18 @@ static int repeatable_keys[] = {
static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
{
struct cinergyt2_state *st = d->priv;
u8 key[5] = {0, 0, 0, 0, 0}, cmd = CINERGYT2_EP1_GET_RC_EVENTS;
int i;
int i, ret;
*state = REMOTE_NO_KEY_PRESSED;
dvb_usb_generic_rw(d, &cmd, 1, key, sizeof(key), 0);
if (key[4] == 0xff) {
mutex_lock(&st->data_mutex);
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 */
st->rc_counter++;
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)
*event = d->last_event;
deb_rc("repeat key, event %x\n",
*event);
return 0;
goto ret;
}
}
deb_rc("repeated key (non repeatable)\n");
}
return 0;
goto ret;
}
/* hack to pass checksum on the custom field */
key[2] = ~key[1];
dvb_usb_nec_rc_key_to_event(d, key, event, state);
if (key[0] != 0) {
st->data[2] = ~st->data[1];
dvb_usb_nec_rc_key_to_event(d, st->data, event, state);
if (st->data[0] != 0) {
if (*event != d->last_event)
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,
const struct usb_device_id *id)
{
return dvb_usb_device_init(intf, &cinergyt2_properties,
THIS_MODULE, NULL, adapter_nr);
struct dvb_usb_device *d;
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)
struct cinergyt2_fe_state {
struct dvb_frontend fe;
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,
enum fe_status *status)
{
struct cinergyt2_fe_state *state = fe->demodulator_priv;
struct dvbt_get_status_msg result;
u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
int ret;
ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&result,
sizeof(result), 0);
mutex_lock(&state->data_mutex);
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)
return ret;
*status = 0;
if (0xffff - le16_to_cpu(result.gain) > 30)
if (0xffff - le16_to_cpu(state->status.gain) > 30)
*status |= FE_HAS_SIGNAL;
if (result.lock_bits & (1 << 6))
if (state->status.lock_bits & (1 << 6))
*status |= FE_HAS_LOCK;
if (result.lock_bits & (1 << 5))
if (state->status.lock_bits & (1 << 5))
*status |= FE_HAS_SYNC;
if (result.lock_bits & (1 << 4))
if (state->status.lock_bits & (1 << 4))
*status |= FE_HAS_CARRIER;
if (result.lock_bits & (1 << 1))
if (state->status.lock_bits & (1 << 1))
*status |= FE_HAS_VITERBI;
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,
static int cinergyt2_fe_read_ber(struct dvb_frontend *fe, u32 *ber)
{
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;
}
static int cinergyt2_fe_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
{
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,
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);
*unc = le32_to_cpu(state->status.uncorrected_block_count);
return 0;
}
......@@ -212,35 +204,16 @@ static int cinergyt2_fe_read_signal_strength(struct dvb_frontend *fe,
u16 *strength)
{
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) {
err("cinergyt2_fe_read_signal_strength() Failed!"
" (Error=%d)\n", ret);
return ret;
}
*strength = (0xffff - le16_to_cpu(status.gain));
*strength = (0xffff - le16_to_cpu(state->status.gain));
return 0;
}
static int cinergyt2_fe_read_snr(struct dvb_frontend *fe, u16 *snr)
{
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) {
err("cinergyt2_fe_read_snr() Failed! (Error=%d)\n", ret);
return ret;
}
*snr = (status.snr << 8) | status.snr;
*snr = (state->status.snr << 8) | state->status.snr;
return 0;
}
......@@ -266,34 +239,36 @@ static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct cinergyt2_fe_state *state = fe->demodulator_priv;
struct dvbt_set_parameters_msg param;
char result[2];
struct dvbt_set_parameters_msg *param;
int err;
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;
mutex_lock(&state->data_mutex);
param = (void *)state->data;
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) {
default:
case 8000000:
param.bandwidth = 8;
param->bandwidth = 8;
break;
case 7000000:
param.bandwidth = 7;
param->bandwidth = 7;
break;
case 6000000:
param.bandwidth = 6;
param->bandwidth = 6;
break;
}
err = dvb_usb_generic_rw(state->d,
(char *)&param, sizeof(param),
result, sizeof(result), 0);
err = dvb_usb_generic_rw(state->d, state->data, sizeof(*param),
state->data, 2, 0);
if (err < 0)
err("cinergyt2_fe_set_frontend() Failed! err=%d\n", err);
mutex_unlock(&state->data_mutex);
return (err < 0) ? err : 0;
}
......@@ -315,6 +290,7 @@ struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d)
s->d = d;
memcpy(&s->fe.ops, &cinergyt2_fe_ops, sizeof(struct dvb_frontend_ops));
s->fe.demodulator_priv = s;
mutex_init(&s->data_mutex);
return &s->fe;
}
......
......@@ -45,9 +45,6 @@
#include "si2168.h"
#include "si2157.h"
/* Max transfer size done by I2C transfer functions */
#define MAX_XFER_SIZE 80
/* debug */
static int dvb_usb_cxusb_debug;
module_param_named(debug, dvb_usb_cxusb_debug, int, 0644);
......@@ -61,23 +58,27 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static int cxusb_ctrl_msg(struct dvb_usb_device *d,
u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
{
int wo = (rbuf == NULL || rlen == 0); /* write-only */
u8 sndbuf[MAX_XFER_SIZE];
struct cxusb_state *st = d->priv;
int ret, wo;
if (1 + wlen > sizeof(sndbuf)) {
warn("i2c wr: len=%d is too big!\n",
wlen);
if (1 + wlen > MAX_XFER_SIZE) {
warn("i2c wr: len=%d is too big!\n", wlen);
return -EOPNOTSUPP;
}
memset(sndbuf, 0, 1+wlen);
wo = (rbuf == NULL || rlen == 0); /* write-only */
sndbuf[0] = cmd;
memcpy(&sndbuf[1], wbuf, wlen);
mutex_lock(&st->data_mutex);
st->data[0] = cmd;
memcpy(&st->data[1], wbuf, wlen);
if (wo)
return dvb_usb_generic_write(d, sndbuf, 1+wlen);
ret = dvb_usb_generic_write(d, st->data, 1 + wlen);
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 */
......@@ -1460,36 +1461,43 @@ static struct dvb_usb_device_properties cxusb_mygica_t230_properties;
static int cxusb_probe(struct usb_interface *intf,
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,
THIS_MODULE, NULL, adapter_nr) ||
THIS_MODULE, &d, adapter_nr) ||
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,
THIS_MODULE, NULL, adapter_nr) ||
THIS_MODULE, &d, adapter_nr) ||
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,
THIS_MODULE, NULL, adapter_nr) ||
THIS_MODULE, &d, adapter_nr) ||
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,
THIS_MODULE, NULL, adapter_nr) ||
THIS_MODULE, &d, adapter_nr) ||
0 == dvb_usb_device_init(intf,
&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,
THIS_MODULE, NULL, adapter_nr) ||
THIS_MODULE, &d, adapter_nr) ||
0 == dvb_usb_device_init(intf,
&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,
THIS_MODULE, NULL, adapter_nr) ||
THIS_MODULE, &d, adapter_nr) ||
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,
THIS_MODULE, NULL, adapter_nr) ||
0)
THIS_MODULE, &d, adapter_nr) ||
0) {
st = d->priv;
mutex_init(&st->data_mutex);
return 0;
}
return -EINVAL;
}
......
......@@ -28,10 +28,16 @@
#define CMD_ANALOG 0x50
#define CMD_DIGITAL 0x51
/* Max transfer size done by I2C transfer functions */
#define MAX_XFER_SIZE 80
struct cxusb_state {
u8 gpio_write_state[3];
struct i2c_client *i2c_client_demod;
struct i2c_client *i2c_client_tuner;
unsigned char data[MAX_XFER_SIZE];
struct mutex data_mutex;
};
#endif
......@@ -213,7 +213,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
usb_rcvctrlpipe(d->udev, 0),
REQUEST_NEW_I2C_READ,
USB_TYPE_VENDOR | USB_DIR_IN,
value, index, msg[i].buf,
value, index, st->buf,
msg[i].len,
USB_CTRL_GET_TIMEOUT);
if (result < 0) {
......@@ -221,6 +221,14 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
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("<<< ");
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,
/* I2C ctrl + FE bus; */
st->buf[3] = ((gen_mode << 6) & 0xC0) |
((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 */
memcpy(&st->buf[4], msg[i].buf, msg[i].len);
......@@ -283,6 +298,11 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
/* fill in the address */
st->buf[1] = msg[i].addr << 1;
/* 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);
/* write/read request */
......@@ -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 */
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) {
deb_info("I2C read failed on address 0x%02x\n",
msg[i].addr);
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;
i++;
......
......@@ -508,8 +508,6 @@ static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap)
#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
* firmwares use bulk mode, with functions implemented at dib0700_core,
......@@ -517,7 +515,6 @@ static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
*/
static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)
{
u8 key[4];
enum rc_type protocol;
u32 scancode;
u8 toggle;
......@@ -532,39 +529,43 @@ static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)
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) {
err("RC Query Failed");
return -1;
return -EIO;
}
/* 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;
/* 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 */
switch (d->props.rc.core.protocol) {
case RC_BIT_NEC:
/* NEC protocol sends repeat code as 0 0 0 FF */
if ((key[3-2] == 0x00) && (key[3-3] == 0x00) &&
(key[3] == 0xff)) {
if ((st->buf[3 - 2] == 0x00) && (st->buf[3 - 3] == 0x00) &&
(st->buf[3] == 0xff)) {
rc_repeat(d->rc_dev);
return 0;
}
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;
break;
default:
/* RC-5 protocol changes toggle bit on new keypress */
protocol = RC_TYPE_RC5;
scancode = RC_SCANCODE_RC5(key[3-2], key[3-3]);
toggle = key[3-1];
scancode = RC_SCANCODE_RC5(st->buf[3 - 2], st->buf[3 - 3]);
toggle = st->buf[3 - 1];
break;
}
......
......@@ -62,72 +62,117 @@ EXPORT_SYMBOL(dibusb_pid_filter_ctrl);
int dibusb_power_ctrl(struct dvb_usb_device *d, int onoff)
{
u8 b[3];
u8 *b;
int ret;
b = kmalloc(3, GFP_KERNEL);
if (!b)
return -ENOMEM;
b[0] = DIBUSB_REQ_SET_IOCTL;
b[1] = DIBUSB_IOCTL_CMD_POWER_MODE;
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);
return ret;
}
EXPORT_SYMBOL(dibusb_power_ctrl);
int dibusb2_0_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
{
u8 b[3] = { 0 };
int ret;
u8 *b;
b = kmalloc(3, GFP_KERNEL);
if (!b)
return -ENOMEM;
if ((ret = dibusb_streaming_ctrl(adap,onoff)) < 0)
return ret;
goto ret;
if (onoff) {
b[0] = DIBUSB_REQ_SET_STREAMING_MODE;
b[1] = 0x00;
if ((ret = dvb_usb_generic_write(adap->dev,b,2)) < 0)
return ret;
ret = dvb_usb_generic_write(adap->dev, b, 2);
if (ret < 0)
goto ret;
}
b[0] = DIBUSB_REQ_SET_IOCTL;
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);
int dibusb2_0_power_ctrl(struct dvb_usb_device *d, int onoff)
{
if (onoff) {
u8 b[3] = { DIBUSB_REQ_SET_IOCTL, DIBUSB_IOCTL_CMD_POWER_MODE, DIBUSB_IOCTL_POWER_WAKEUP };
return dvb_usb_generic_write(d,b,3);
} else
u8 *b;
int ret;
if (!onoff)
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);
static int dibusb_i2c_msg(struct dvb_usb_device *d, u8 addr,
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 ? */
int wo = (rbuf == NULL || rlen == 0),
wo = (rbuf == NULL || rlen == 0);
len = 2 + wlen + (wo ? 0 : 2);
if (4 + wlen > sizeof(sndbuf)) {
sndbuf = kmalloc(MAX_XFER_SIZE, GFP_KERNEL);
if (!sndbuf)
return -ENOMEM;
if (4 + wlen > MAX_XFER_SIZE) {
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[1] = (addr << 1) | (wo ? 0 : 1);
memcpy(&sndbuf[2],wbuf,wlen);
memcpy(&sndbuf[2], wbuf, wlen);
if (!wo) {
sndbuf[wlen+2] = (rlen >> 8) & 0xff;
sndbuf[wlen+3] = rlen & 0xff;
sndbuf[wlen + 2] = (rlen >> 8) & 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);
int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
{
u8 key[5],cmd = DIBUSB_REQ_POLL_REMOTE;
dvb_usb_generic_rw(d,&cmd,1,key,5,0);
dvb_usb_nec_rc_key_to_event(d,key,event,state);
if (key[0] != 0)
deb_info("key: %*ph\n", 5, key);
return 0;
u8 *buf;
int ret;
buf = kmalloc(5, GFP_KERNEL);
if (!buf)
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);
......@@ -96,6 +96,9 @@
#define DIBUSB_IOCTL_CMD_ENABLE_STREAM 0x01
#define DIBUSB_IOCTL_CMD_DISABLE_STREAM 0x02
/* Max transfer size done by I2C transfer functions */
#define MAX_XFER_SIZE 64
struct dibusb_state {
struct dib_fe_xfer_ops ops;
int mt2060_present;
......
......@@ -28,22 +28,26 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static int digitv_ctrl_msg(struct dvb_usb_device *d,
u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
{
int wo = (rbuf == NULL || rlen == 0); /* write-only */
u8 sndbuf[7],rcvbuf[7];
memset(sndbuf,0,7); memset(rcvbuf,0,7);
struct digitv_state *st = d->priv;
int ret, wo;
sndbuf[0] = cmd;
sndbuf[1] = vv;
sndbuf[2] = wo ? wlen : rlen;
wo = (rbuf == NULL || rlen == 0); /* write-only */
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) {
memcpy(&sndbuf[3],wbuf,wlen);
dvb_usb_generic_write(d,sndbuf,7);
memcpy(&st->sndbuf[3], wbuf, wlen);
ret = dvb_usb_generic_write(d, st->sndbuf, 7);
} else {
dvb_usb_generic_rw(d,sndbuf,7,rcvbuf,7,10);
memcpy(rbuf,&rcvbuf[3],rlen);
ret = dvb_usb_generic_rw(d, st->sndbuf, 7, st->rcvbuf, 7, 10);
memcpy(rbuf, &st->rcvbuf[3], rlen);
}
return 0;
return ret;
}
/* I2C */
......
......@@ -6,6 +6,9 @@
struct digitv_state {
int is_nxt6000;
unsigned char sndbuf[7];
unsigned char rcvbuf[7];
};
/* protocol (from usblogging and the SDK:
......
......@@ -18,17 +18,28 @@ struct dtt200u_fe_state {
struct dtv_frontend_properties fep;
struct dvb_frontend frontend;
unsigned char data[80];
struct mutex data_mutex;
};
static int dtt200u_fe_read_status(struct dvb_frontend *fe,
enum fe_status *stat)
{
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:
*stat = FE_HAS_SIGNAL | FE_HAS_CARRIER |
FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
......@@ -41,51 +52,86 @@ static int dtt200u_fe_read_status(struct dvb_frontend *fe,
*stat = 0;
break;
}
mutex_unlock(&state->data_mutex);
return 0;
}
static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
{
struct dtt200u_fe_state *state = fe->demodulator_priv;
u8 bw = GET_VIT_ERR_CNT,b[3];
dvb_usb_generic_rw(state->d,&bw,1,b,3,0);
*ber = (b[0] << 16) | (b[1] << 8) | b[2];
return 0;
int ret;
mutex_lock(&state->data_mutex);
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)
{
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);
*unc = (b[0] << 8) | b[1];
return 0;
mutex_lock(&state->data_mutex);
state->data[0] = GET_RS_UNCOR_BLK_CNT;
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)
{
struct dtt200u_fe_state *state = fe->demodulator_priv;
u8 bw = GET_AGC, b;
dvb_usb_generic_rw(state->d,&bw,1,&b,1,0);
*strength = (b << 8) | b;
return 0;
int ret;
mutex_lock(&state->data_mutex);
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)
{
struct dtt200u_fe_state *state = fe->demodulator_priv;
u8 bw = GET_SNR,br;
dvb_usb_generic_rw(state->d,&bw,1,&br,1,0);
*snr = ~((br << 8) | br);
return 0;
int ret;
mutex_lock(&state->data_mutex);
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)
{
struct dtt200u_fe_state *state = fe->demodulator_priv;
u8 b = SET_INIT;
return dvb_usb_generic_write(state->d,&b,1);
int ret;
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)
......@@ -105,39 +151,40 @@ static int dtt200u_fe_set_frontend(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
struct dtt200u_fe_state *state = fe->demodulator_priv;
int i;
enum fe_status st;
int ret;
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) {
case 8000000:
bwbuf[1] = 8;
state->data[1] = 8;
break;
case 7000000:
bwbuf[1] = 7;
state->data[1] = 7;
break;
case 6000000:
bwbuf[1] = 6;
state->data[1] = 6;
break;
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;
freqbuf[2] = (freq >> 8) & 0xff;
dvb_usb_generic_write(state->d,freqbuf,3);
state->data[0] = SET_RF_FREQ;
state->data[1] = freq & 0xff;
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++) {
msleep(20);
dtt200u_fe_read_status(fe, &st);
if (st & FE_TIMEDOUT)
continue;
}
return 0;
ret:
mutex_unlock(&state->data_mutex);
return ret;
}
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)
deb_info("attaching frontend dtt200u\n");
state->d = d;
mutex_init(&state->data_mutex);
memcpy(&state->frontend.ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
......
......@@ -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);
struct dtt200u_state {
unsigned char data[80];
struct mutex data_mutex;
};
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)
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)
{
u8 b_streaming[2] = { SET_STREAMING, onoff };
u8 b_rst_pid = RESET_PID_FILTER;
struct dtt200u_state *st = adap->dev->priv;
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)
dvb_usb_generic_write(adap->dev, &b_rst_pid, 1);
return 0;
ret = dvb_usb_generic_write(adap->dev, st->data, 2);
if (ret < 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)
{
u8 b_pid[4];
struct dtt200u_state *st = adap->dev->priv;
int ret;
pid = onoff ? pid : 0;
b_pid[0] = SET_PID_FILTER;
b_pid[1] = index;
b_pid[2] = pid & 0xff;
b_pid[3] = (pid >> 8) & 0x1f;
mutex_lock(&st->data_mutex);
st->data[0] = SET_PID_FILTER;
st->data[1] = index;
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)
{
u8 key[5],cmd = GET_RC_CODE;
struct dtt200u_state *st = d->priv;
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 (key[0] == 1) {
if (st->data[0] == 1) {
enum rc_type proto = RC_TYPE_NEC;
scancode = key[1];
if ((u8) ~key[1] != key[2]) {
scancode = st->data[1];
if ((u8) ~st->data[1] != st->data[2]) {
/* Extended NEC */
scancode = scancode << 8;
scancode |= key[2];
scancode |= st->data[2];
proto = RC_TYPE_NECX;
}
scancode = scancode << 8;
scancode |= key[3];
scancode |= st->data[3];
/* 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);
else
rc_keyup(d->rc_dev);
} else if (key[0] == 2) {
} else if (st->data[0] == 2) {
rc_repeat(d->rc_dev);
} else {
rc_keyup(d->rc_dev);
}
if (key[0] != 0)
deb_info("key: %*ph\n", 5, key);
if (st->data[0] != 0)
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)
......@@ -106,17 +145,24 @@ static struct dvb_usb_device_properties wt220u_miglia_properties;
static int dtt200u_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct dvb_usb_device *d;
struct dtt200u_state *st;
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,
THIS_MODULE, NULL, adapter_nr) ||
THIS_MODULE, &d, adapter_nr) ||
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,
THIS_MODULE, NULL, adapter_nr) ||
THIS_MODULE, &d, adapter_nr) ||
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 -ENODEV;
}
......@@ -140,6 +186,8 @@ static struct dvb_usb_device_properties dtt200u_properties = {
.usb_ctrl = CYPRESS_FX2,
.firmware = "dvb-usb-dtt200u-01.fw",
.size_of_priv = sizeof(struct dtt200u_state),
.num_adapters = 1,
.adapter = {
{
......@@ -190,6 +238,8 @@ static struct dvb_usb_device_properties wt220u_properties = {
.usb_ctrl = CYPRESS_FX2,
.firmware = "dvb-usb-wt220u-02.fw",
.size_of_priv = sizeof(struct dtt200u_state),
.num_adapters = 1,
.adapter = {
{
......@@ -240,6 +290,8 @@ static struct dvb_usb_device_properties wt220u_fc_properties = {
.usb_ctrl = CYPRESS_FX2,
.firmware = "dvb-usb-wt220u-fc03.fw",
.size_of_priv = sizeof(struct dtt200u_state),
.num_adapters = 1,
.adapter = {
{
......@@ -290,6 +342,8 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = {
.usb_ctrl = CYPRESS_FX2,
.firmware = "dvb-usb-wt220u-zl0353-01.fw",
.size_of_priv = sizeof(struct dtt200u_state),
.num_adapters = 1,
.adapter = {
{
......@@ -340,6 +394,8 @@ static struct dvb_usb_device_properties wt220u_miglia_properties = {
.usb_ctrl = CYPRESS_FX2,
.firmware = "dvb-usb-wt220u-miglia-01.fw",
.size_of_priv = sizeof(struct dtt200u_state),
.num_adapters = 1,
.generic_bulk_ctrl_endpoint = 0x01,
......
......@@ -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);
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,
u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
{
struct dtv5100_state *st = d->priv;
u8 request;
u8 type;
u16 value;
......@@ -60,9 +65,10 @@ static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr,
}
index = (addr << 8) + wbuf[0];
memcpy(st->data, rbuf, rlen);
msleep(1); /* avoid I2C errors */
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);
}
......@@ -176,7 +182,7 @@ static struct dvb_usb_device_properties dtv5100_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.size_of_priv = 0,
.size_of_priv = sizeof(struct dtv5100_state),
.num_adapters = 1,
.adapter = {{
......
......@@ -852,7 +852,7 @@ static int su3000_power_ctrl(struct dvb_usb_device *d, int i)
if (i && !state->initialized) {
state->initialized = 1;
/* 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;
......
......@@ -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);
struct gp8psk_state {
unsigned char data[80];
};
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));
......@@ -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)
{
struct gp8psk_state *st = d->priv;
int ret = 0,try = 0;
if (blen > sizeof(st->data))
return -EIO;
if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
return ret;
while (ret >= 0 && ret != blen && try < 3) {
memcpy(st->data, b, blen);
ret = usb_control_msg(d->udev,
usb_rcvctrlpipe(d->udev,0),
req,
USB_TYPE_VENDOR | USB_DIR_IN,
value,index,b,blen,
value, index, st->data, blen,
2000);
deb_info("reading number %d (ret: %d)\n",try,ret);
try++;
......@@ -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,
u16 index, u8 *b, int blen)
{
struct gp8psk_state *st = d->priv;
int ret;
deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
debug_dump(b,blen,deb_xfer);
if (blen > sizeof(st->data))
return -EIO;
if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
return ret;
memcpy(st->data, b, blen);
if (usb_control_msg(d->udev,
usb_sndctrlpipe(d->udev,0),
req,
USB_TYPE_VENDOR | USB_DIR_OUT,
value,index,b,blen,
value, index, st->data, blen,
2000) != blen) {
warn("usb out operation failed.");
ret = -EIO;
......@@ -143,6 +157,11 @@ static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d)
err("failed to load bcm4500 firmware.");
goto out_free;
}
if (buflen > 64) {
err("firmare chunk size bigger than 64 bytes.");
goto out_free;
}
memcpy(buf, ptr, buflen);
if (dvb_usb_generic_write(d, buf, buflen)) {
err("failed to load bcm4500 firmware.");
......@@ -265,6 +284,8 @@ static struct dvb_usb_device_properties gp8psk_properties = {
.usb_ctrl = CYPRESS_FX2,
.firmware = "dvb-usb-gp8psk-01.fw",
.size_of_priv = sizeof(struct gp8psk_state),
.num_adapters = 1,
.adapter = {
{
......
......@@ -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)
{
u8 key[5],cmd[2] = { DIBUSB_REQ_POLL_REMOTE, 0x35 }, data,toggle,custom;
u8 *buf, data, toggle, custom;
u16 raw;
int i;
int i, ret;
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;
switch (key[0]) {
switch (buf[0]) {
case DIBUSB_RC_HAUPPAUGE_KEY_PRESSED:
raw = ((key[1] << 8) | key[2]) >> 3;
raw = ((buf[1] << 8) | buf[2]) >> 3;
toggle = !!(raw & 0x800);
data = raw & 0x3f;
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++) {
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)
break;
}
return 0;
ret:
kfree(buf);
return ret;
}
static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6])
......
......@@ -97,48 +97,53 @@ struct pctv452e_state {
u8 c; /* transaction counter, wraps around... */
u8 initialized; /* set to 1 if 0x15 has been sent */
u16 last_rc_key;
unsigned char data[80];
};
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];
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;
}
mutex_lock(&state->ca_mutex);
id = state->c++;
buf[0] = SYNC_BYTE_OUT;
buf[1] = id;
buf[2] = cmd;
buf[3] = write_len;
state->data[0] = SYNC_BYTE_OUT;
state->data[1] = id;
state->data[2] = cmd;
state->data[3] = write_len;
memcpy(buf + 4, data, write_len);
memcpy(state->data + 4, data, write_len);
rlen = (read_len > 0) ? 64 : 0;
ret = dvb_usb_generic_rw(d, buf, 4 + write_len,
buf, rlen, /* delay_ms */ 0);
ret = dvb_usb_generic_rw(d, state->data, 4 + write_len,
state->data, rlen, /* delay_ms */ 0);
if (0 != ret)
goto failed;
ret = -EIO;
if (SYNC_BYTE_IN != buf[0] || id != buf[1])
if (SYNC_BYTE_IN != state->data[0] || id != state->data[1])
goto failed;
memcpy(data, buf + 4, read_len);
memcpy(data, state->data + 4, read_len);
mutex_unlock(&state->ca_mutex);
return 0;
failed:
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;
}
......@@ -405,52 +410,53 @@ static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr,
u8 *rcv_buf, u8 rcv_len)
{
struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
u8 buf[64];
u8 id;
int ret;
mutex_lock(&state->ca_mutex);
id = state->c++;
ret = -EINVAL;
if (snd_len > 64 - 7 || rcv_len > 64 - 7)
goto failed;
buf[0] = SYNC_BYTE_OUT;
buf[1] = id;
buf[2] = PCTV_CMD_I2C;
buf[3] = snd_len + 3;
buf[4] = addr << 1;
buf[5] = snd_len;
buf[6] = rcv_len;
state->data[0] = SYNC_BYTE_OUT;
state->data[1] = id;
state->data[2] = PCTV_CMD_I2C;
state->data[3] = snd_len + 3;
state->data[4] = addr << 1;
state->data[5] = snd_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,
buf, /* rcv_len */ 64,
ret = dvb_usb_generic_rw(d, state->data, 7 + snd_len,
state->data, /* rcv_len */ 64,
/* delay_ms */ 0);
if (ret < 0)
goto failed;
/* TT USB protocol error. */
ret = -EIO;
if (SYNC_BYTE_IN != buf[0] || id != buf[1])
if (SYNC_BYTE_IN != state->data[0] || id != state->data[1])
goto failed;
/* I2C device didn't respond as expected. */
ret = -EREMOTEIO;
if (buf[5] < snd_len || buf[6] < rcv_len)
if (state->data[5] < snd_len || state->data[6] < rcv_len)
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;
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, state->data);
mutex_unlock(&state->ca_mutex);
return ret;
}
......@@ -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)
{
struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
u8 b0[] = { 0xaa, 0, PCTV_CMD_RESET, 1, 0 };
u8 rx[PCTV_ANSWER_LEN];
u8 *rx;
int ret;
info("%s: %d\n", __func__, i);
......@@ -511,6 +516,11 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
if (state->initialized)
return 0;
rx = kmalloc(PCTV_ANSWER_LEN, GFP_KERNEL);
if (!rx)
return -ENOMEM;
mutex_lock(&state->ca_mutex);
/* hmm where shoud this should go? */
ret = usb_set_interface(d->udev, 0, ISOC_INTERFACE_ALTERNATIVE);
if (ret != 0)
......@@ -518,65 +528,75 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
__func__, ret);
/* 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 */
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)
return ret;
goto ret;
b0[1] = state->c++;
b0[4] = 1;
state->data[1] = state->c++;
state->data[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, state->data, 5, rx, PCTV_ANSWER_LEN, 0);
if (ret)
return ret;
goto ret;
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)
{
struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
u8 b[CMD_BUFFER_SIZE];
u8 rx[PCTV_ANSWER_LEN];
int ret, i;
u8 id = state->c++;
u8 id;
mutex_lock(&state->ca_mutex);
id = state->c++;
/* prepare command header */
b[0] = SYNC_BYTE_OUT;
b[1] = id;
b[2] = PCTV_CMD_IR;
b[3] = 0;
state->data[0] = SYNC_BYTE_OUT;
state->data[1] = id;
state->data[2] = PCTV_CMD_IR;
state->data[3] = 0;
/* 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)
return ret;
goto ret;
if (debug > 3) {
info("%s: read: %2d: %*ph: ", __func__, ret, 3, rx);
for (i = 0; (i < rx[3]) && ((i+3) < PCTV_ANSWER_LEN); i++)
info(" %02x", rx[i+3]);
info("%s: read: %2d: %*ph: ", __func__, ret, 3, state->data);
for (i = 0; (i < state->data[3]) && ((i + 3) < PCTV_ANSWER_LEN); i++)
info(" %02x", state->data[i + 3]);
info("\n");
}
if ((rx[3] == 9) && (rx[12] & 0x01)) {
if ((state->data[3] == 9) && (state->data[12] & 0x01)) {
/* 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)
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);
} else if (state->last_rc_key) {
rc_keyup(d->rc_dev);
state->last_rc_key = 0;
}
return 0;
ret:
mutex_unlock(&state->ca_mutex);
return ret;
}
static int pctv452e_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
......
......@@ -89,9 +89,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(" ");
......@@ -123,7 +127,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,
......@@ -131,7 +135,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) {
......@@ -140,7 +144,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]);
......@@ -154,7 +158,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,
......
......@@ -1901,19 +1901,30 @@ static long s2255_vendor_req(struct s2255_dev *dev, unsigned char Request,
s32 TransferBufferLength, int bOut)
{
int r;
unsigned char *buf;
buf = kmalloc(TransferBufferLength, GFP_KERNEL);
if (!buf)
return -ENOMEM;
if (!bOut) {
r = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
Request,
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
USB_DIR_IN,
Value, Index, TransferBuffer,
Value, Index, buf,
TransferBufferLength, HZ * 5);
if (r >= 0)
memcpy(TransferBuffer, buf, TransferBufferLength);
} else {
memcpy(buf, TransferBuffer, TransferBufferLength);
r = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
Request, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Value, Index, TransferBuffer,
Value, Index, buf,
TransferBufferLength, HZ * 5);
}
kfree(buf);
return r;
}
......
......@@ -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)
{
struct usb_device *udev = dev->udev;
unsigned char *buf;
int ret;
buf = kmalloc(sizeof(u8), GFP_KERNEL);
if (!buf)
return -ENOMEM;
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
0x00,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0x00,
index,
(u8 *) value,
buf,
sizeof(u8),
500);
if (ret < 0)
if (ret >= 0)
memcpy(value, buf, sizeof(u8));
kfree(buf);
return ret;
else
return 0;
}
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)
flags);
memset(&bdev->rds_info, 0, sizeof(bdev->rds_info));
}
if (err)
return err;
return bcm2048_send_command(bdev, BCM2048_I2C_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