Commit 73d5c5c8 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

[media] pctv452e: don't do DMA on stack

The USB control messages require DMA to work. We cannot pass
a stack-allocated buffer, as it is not warranted that the
stack would be into a DMA enabled area.
Reviewed-by: default avatarPatrick Boettcher <patrick.boettcher@posteo.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent c3a66e9f
...@@ -97,13 +97,14 @@ struct pctv452e_state { ...@@ -97,13 +97,14 @@ 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;
...@@ -112,33 +113,36 @@ static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, ...@@ -112,33 +113,36 @@ static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data,
BUG_ON(write_len > 64 - 4); BUG_ON(write_len > 64 - 4);
BUG_ON(read_len > 64 - 4); BUG_ON(read_len > 64 - 4);
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 +409,53 @@ static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr, ...@@ -405,52 +409,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 +504,7 @@ static u32 pctv452e_i2c_func(struct i2c_adapter *adapter) ...@@ -499,8 +504,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 +515,11 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i) ...@@ -511,6 +515,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 +527,75 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i) ...@@ -518,65 +527,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])
......
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