diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-11-05 14:15:09 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-11-05 14:15:09 -0400 |
| commit | d8d1721cfb3162abbda078d67a928792d6552b84 (patch) | |
| tree | 3ad51af0fcc08d60414fa832b546aee91115d180 | |
| parent | 41e6410ec3037cee1751d8f7d152a9ebec1fc1fc (diff) | |
| parent | 1aeb5b615cd10db7324d4e4d167c4916dfeca311 (diff) | |
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
...
25 files changed, 919 insertions, 499 deletions
diff --git a/drivers/media/usb/b2c2/flexcop-usb.c b/drivers/media/usb/b2c2/flexcop-usb.c index d4bdba60b0f7..52bc42da8a4c 100644 --- a/drivers/media/usb/b2c2/flexcop-usb.c +++ b/drivers/media/usb/b2c2/flexcop-usb.c | |||
| @@ -73,23 +73,34 @@ static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI, | |||
| 73 | u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR; | 73 | u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR; |
| 74 | u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) | | 74 | u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) | |
| 75 | (read ? 0x80 : 0); | 75 | (read ? 0x80 : 0); |
| 76 | int ret; | ||
| 77 | |||
| 78 | mutex_lock(&fc_usb->data_mutex); | ||
| 79 | if (!read) | ||
| 80 | memcpy(fc_usb->data, val, sizeof(*val)); | ||
| 76 | 81 | ||
| 77 | int len = usb_control_msg(fc_usb->udev, | 82 | ret = usb_control_msg(fc_usb->udev, |
| 78 | read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT, | 83 | read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT, |
| 79 | request, | 84 | request, |
| 80 | request_type, /* 0xc0 read or 0x40 write */ | 85 | request_type, /* 0xc0 read or 0x40 write */ |
| 81 | wAddress, | 86 | wAddress, |
| 82 | 0, | 87 | 0, |
| 83 | val, | 88 | fc_usb->data, |
| 84 | sizeof(u32), | 89 | sizeof(u32), |
| 85 | B2C2_WAIT_FOR_OPERATION_RDW * HZ); | 90 | B2C2_WAIT_FOR_OPERATION_RDW * HZ); |
| 86 | 91 | ||
| 87 | if (len != sizeof(u32)) { | 92 | if (ret != sizeof(u32)) { |
| 88 | err("error while %s dword from %d (%d).", read ? "reading" : | 93 | err("error while %s dword from %d (%d).", read ? "reading" : |
| 89 | "writing", wAddress, wRegOffsPCI); | 94 | "writing", wAddress, wRegOffsPCI); |
| 90 | return -EIO; | 95 | if (ret >= 0) |
| 96 | ret = -EIO; | ||
| 91 | } | 97 | } |
| 92 | return 0; | 98 | |
| 99 | if (read && ret >= 0) | ||
| 100 | memcpy(val, fc_usb->data, sizeof(*val)); | ||
| 101 | mutex_unlock(&fc_usb->data_mutex); | ||
| 102 | |||
| 103 | return ret; | ||
| 93 | } | 104 | } |
| 94 | /* | 105 | /* |
| 95 | * DKT 010817 - add support for V8 memory read/write and flash update | 106 | * 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 | { | 111 | { |
| 101 | u8 request_type = USB_TYPE_VENDOR; | 112 | u8 request_type = USB_TYPE_VENDOR; |
| 102 | u16 wIndex; | 113 | u16 wIndex; |
| 103 | int nWaitTime, pipe, len; | 114 | int nWaitTime, pipe, ret; |
| 104 | wIndex = page << 8; | 115 | wIndex = page << 8; |
| 105 | 116 | ||
| 117 | if (buflen > sizeof(fc_usb->data)) { | ||
| 118 | err("Buffer size bigger than max URB control message\n"); | ||
| 119 | return -EIO; | ||
| 120 | } | ||
| 121 | |||
| 106 | switch (req) { | 122 | switch (req) { |
| 107 | case B2C2_USB_READ_V8_MEM: | 123 | case B2C2_USB_READ_V8_MEM: |
| 108 | nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ; | 124 | nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ; |
| @@ -127,17 +143,32 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb, | |||
| 127 | deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n", request_type, req, | 143 | deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n", request_type, req, |
| 128 | wAddress, wIndex, buflen); | 144 | wAddress, wIndex, buflen); |
| 129 | 145 | ||
| 130 | len = usb_control_msg(fc_usb->udev, pipe, | 146 | mutex_lock(&fc_usb->data_mutex); |
| 147 | |||
| 148 | if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) | ||
| 149 | memcpy(fc_usb->data, pbBuffer, buflen); | ||
| 150 | |||
| 151 | ret = usb_control_msg(fc_usb->udev, pipe, | ||
| 131 | req, | 152 | req, |
| 132 | request_type, | 153 | request_type, |
| 133 | wAddress, | 154 | wAddress, |
| 134 | wIndex, | 155 | wIndex, |
| 135 | pbBuffer, | 156 | fc_usb->data, |
| 136 | buflen, | 157 | buflen, |
| 137 | nWaitTime * HZ); | 158 | nWaitTime * HZ); |
| 159 | if (ret != buflen) | ||
| 160 | ret = -EIO; | ||
| 161 | |||
| 162 | if (ret >= 0) { | ||
| 163 | ret = 0; | ||
| 164 | if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) | ||
| 165 | memcpy(pbBuffer, fc_usb->data, buflen); | ||
| 166 | } | ||
| 138 | 167 | ||
| 139 | debug_dump(pbBuffer, len, deb_v8); | 168 | mutex_unlock(&fc_usb->data_mutex); |
| 140 | return len == buflen ? 0 : -EIO; | 169 | |
| 170 | debug_dump(pbBuffer, ret, deb_v8); | ||
| 171 | return ret; | ||
| 141 | } | 172 | } |
| 142 | 173 | ||
| 143 | #define bytes_left_to_read_on_page(paddr,buflen) \ | 174 | #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 | fc->dvb_adapter.proposed_mac, 6); | 227 | fc->dvb_adapter.proposed_mac, 6); |
| 197 | } | 228 | } |
| 198 | 229 | ||
| 199 | #if 0 | ||
| 200 | static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set, | ||
| 201 | flexcop_usb_utility_function_t func, u8 extra, u16 wIndex, | ||
| 202 | u16 buflen, u8 *pvBuffer) | ||
| 203 | { | ||
| 204 | u16 wValue; | ||
| 205 | u8 request_type = (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR; | ||
| 206 | int nWaitTime = 2, | ||
| 207 | pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN, len; | ||
| 208 | wValue = (func << 8) | extra; | ||
| 209 | |||
| 210 | len = usb_control_msg(fc_usb->udev,pipe, | ||
| 211 | B2C2_USB_UTILITY, | ||
| 212 | request_type, | ||
| 213 | wValue, | ||
| 214 | wIndex, | ||
| 215 | pvBuffer, | ||
| 216 | buflen, | ||
| 217 | nWaitTime * HZ); | ||
| 218 | return len == buflen ? 0 : -EIO; | ||
| 219 | } | ||
| 220 | #endif | ||
| 221 | |||
| 222 | /* usb i2c stuff */ | 230 | /* usb i2c stuff */ |
| 223 | static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c, | 231 | static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c, |
| 224 | flexcop_usb_request_t req, flexcop_usb_i2c_function_t func, | 232 | 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 | { | 234 | { |
| 227 | struct flexcop_usb *fc_usb = i2c->fc->bus_specific; | 235 | struct flexcop_usb *fc_usb = i2c->fc->bus_specific; |
| 228 | u16 wValue, wIndex; | 236 | u16 wValue, wIndex; |
| 229 | int nWaitTime,pipe,len; | 237 | int nWaitTime, pipe, ret; |
| 230 | u8 request_type = USB_TYPE_VENDOR; | 238 | u8 request_type = USB_TYPE_VENDOR; |
| 231 | 239 | ||
| 240 | if (buflen > sizeof(fc_usb->data)) { | ||
| 241 | err("Buffer size bigger than max URB control message\n"); | ||
| 242 | return -EIO; | ||
| 243 | } | ||
| 244 | |||
| 232 | switch (func) { | 245 | switch (func) { |
| 233 | case USB_FUNC_I2C_WRITE: | 246 | case USB_FUNC_I2C_WRITE: |
| 234 | case USB_FUNC_I2C_MULTIWRITE: | 247 | case USB_FUNC_I2C_MULTIWRITE: |
| @@ -257,15 +270,32 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c, | |||
| 257 | wValue & 0xff, wValue >> 8, | 270 | wValue & 0xff, wValue >> 8, |
| 258 | wIndex & 0xff, wIndex >> 8); | 271 | wIndex & 0xff, wIndex >> 8); |
| 259 | 272 | ||
| 260 | len = usb_control_msg(fc_usb->udev,pipe, | 273 | mutex_lock(&fc_usb->data_mutex); |
| 274 | |||
| 275 | if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) | ||
| 276 | memcpy(fc_usb->data, buf, buflen); | ||
| 277 | |||
| 278 | ret = usb_control_msg(fc_usb->udev, pipe, | ||
| 261 | req, | 279 | req, |
| 262 | request_type, | 280 | request_type, |
| 263 | wValue, | 281 | wValue, |
| 264 | wIndex, | 282 | wIndex, |
| 265 | buf, | 283 | fc_usb->data, |
| 266 | buflen, | 284 | buflen, |
| 267 | nWaitTime * HZ); | 285 | nWaitTime * HZ); |
| 268 | return len == buflen ? 0 : -EREMOTEIO; | 286 | |
| 287 | if (ret != buflen) | ||
| 288 | ret = -EIO; | ||
| 289 | |||
| 290 | if (ret >= 0) { | ||
| 291 | ret = 0; | ||
| 292 | if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) | ||
| 293 | memcpy(buf, fc_usb->data, buflen); | ||
| 294 | } | ||
| 295 | |||
| 296 | mutex_unlock(&fc_usb->data_mutex); | ||
| 297 | |||
| 298 | return 0; | ||
| 269 | } | 299 | } |
| 270 | 300 | ||
| 271 | /* actual bus specific access functions, | 301 | /* actual bus specific access functions, |
| @@ -516,6 +546,7 @@ static int flexcop_usb_probe(struct usb_interface *intf, | |||
| 516 | /* general flexcop init */ | 546 | /* general flexcop init */ |
| 517 | fc_usb = fc->bus_specific; | 547 | fc_usb = fc->bus_specific; |
| 518 | fc_usb->fc_dev = fc; | 548 | fc_usb->fc_dev = fc; |
| 549 | mutex_init(&fc_usb->data_mutex); | ||
| 519 | 550 | ||
| 520 | fc->read_ibi_reg = flexcop_usb_read_ibi_reg; | 551 | fc->read_ibi_reg = flexcop_usb_read_ibi_reg; |
| 521 | fc->write_ibi_reg = flexcop_usb_write_ibi_reg; | 552 | fc->write_ibi_reg = flexcop_usb_write_ibi_reg; |
diff --git a/drivers/media/usb/b2c2/flexcop-usb.h b/drivers/media/usb/b2c2/flexcop-usb.h index 92529a9c4475..25ad43166e78 100644 --- a/drivers/media/usb/b2c2/flexcop-usb.h +++ b/drivers/media/usb/b2c2/flexcop-usb.h | |||
| @@ -29,6 +29,10 @@ struct flexcop_usb { | |||
| 29 | 29 | ||
| 30 | u8 tmp_buffer[1023+190]; | 30 | u8 tmp_buffer[1023+190]; |
| 31 | int tmp_buffer_length; | 31 | int tmp_buffer_length; |
| 32 | |||
| 33 | /* for URB control messages */ | ||
| 34 | u8 data[80]; | ||
| 35 | struct mutex data_mutex; | ||
| 32 | }; | 36 | }; |
| 33 | 37 | ||
| 34 | #if 0 | 38 | #if 0 |
diff --git a/drivers/media/usb/cpia2/cpia2_usb.c b/drivers/media/usb/cpia2/cpia2_usb.c index 13620cdf0599..e9100a235831 100644 --- a/drivers/media/usb/cpia2/cpia2_usb.c +++ b/drivers/media/usb/cpia2/cpia2_usb.c | |||
| @@ -545,18 +545,30 @@ static void free_sbufs(struct camera_data *cam) | |||
| 545 | static int write_packet(struct usb_device *udev, | 545 | static int write_packet(struct usb_device *udev, |
| 546 | u8 request, u8 * registers, u16 start, size_t size) | 546 | u8 request, u8 * registers, u16 start, size_t size) |
| 547 | { | 547 | { |
| 548 | unsigned char *buf; | ||
| 549 | int ret; | ||
| 550 | |||
| 548 | if (!registers || size <= 0) | 551 | if (!registers || size <= 0) |
| 549 | return -EINVAL; | 552 | return -EINVAL; |
| 550 | 553 | ||
| 551 | return usb_control_msg(udev, | 554 | buf = kmalloc(size, GFP_KERNEL); |
| 555 | if (!buf) | ||
| 556 | return -ENOMEM; | ||
| 557 | |||
| 558 | memcpy(buf, registers, size); | ||
| 559 | |||
| 560 | ret = usb_control_msg(udev, | ||
| 552 | usb_sndctrlpipe(udev, 0), | 561 | usb_sndctrlpipe(udev, 0), |
| 553 | request, | 562 | request, |
| 554 | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 563 | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 555 | start, /* value */ | 564 | start, /* value */ |
| 556 | 0, /* index */ | 565 | 0, /* index */ |
| 557 | registers, /* buffer */ | 566 | buf, /* buffer */ |
| 558 | size, | 567 | size, |
| 559 | HZ); | 568 | HZ); |
| 569 | |||
| 570 | kfree(buf); | ||
| 571 | return ret; | ||
| 560 | } | 572 | } |
| 561 | 573 | ||
| 562 | /**************************************************************************** | 574 | /**************************************************************************** |
| @@ -567,18 +579,32 @@ static int write_packet(struct usb_device *udev, | |||
| 567 | static int read_packet(struct usb_device *udev, | 579 | static int read_packet(struct usb_device *udev, |
| 568 | u8 request, u8 * registers, u16 start, size_t size) | 580 | u8 request, u8 * registers, u16 start, size_t size) |
| 569 | { | 581 | { |
| 582 | unsigned char *buf; | ||
| 583 | int ret; | ||
| 584 | |||
| 570 | if (!registers || size <= 0) | 585 | if (!registers || size <= 0) |
| 571 | return -EINVAL; | 586 | return -EINVAL; |
| 572 | 587 | ||
| 573 | return usb_control_msg(udev, | 588 | buf = kmalloc(size, GFP_KERNEL); |
| 589 | if (!buf) | ||
| 590 | return -ENOMEM; | ||
| 591 | |||
| 592 | ret = usb_control_msg(udev, | ||
| 574 | usb_rcvctrlpipe(udev, 0), | 593 | usb_rcvctrlpipe(udev, 0), |
| 575 | request, | 594 | request, |
| 576 | USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE, | 595 | USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE, |
| 577 | start, /* value */ | 596 | start, /* value */ |
| 578 | 0, /* index */ | 597 | 0, /* index */ |
| 579 | registers, /* buffer */ | 598 | buf, /* buffer */ |
| 580 | size, | 599 | size, |
| 581 | HZ); | 600 | HZ); |
| 601 | |||
| 602 | if (ret >= 0) | ||
| 603 | memcpy(registers, buf, size); | ||
| 604 | |||
| 605 | kfree(buf); | ||
| 606 | |||
| 607 | return ret; | ||
| 582 | } | 608 | } |
| 583 | 609 | ||
| 584 | /****************************************************************************** | 610 | /****************************************************************************** |
diff --git a/drivers/media/usb/dvb-usb/af9005.c b/drivers/media/usb/dvb-usb/af9005.c index efa782ed6e2d..b257780fb380 100644 --- a/drivers/media/usb/dvb-usb/af9005.c +++ b/drivers/media/usb/dvb-usb/af9005.c | |||
| @@ -52,17 +52,16 @@ u8 regmask[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; | |||
| 52 | struct af9005_device_state { | 52 | struct af9005_device_state { |
| 53 | u8 sequence; | 53 | u8 sequence; |
| 54 | int led_state; | 54 | int led_state; |
| 55 | unsigned char data[256]; | ||
| 56 | struct mutex data_mutex; | ||
| 55 | }; | 57 | }; |
| 56 | 58 | ||
| 57 | static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg, | 59 | static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg, |
| 58 | int readwrite, int type, u8 * values, int len) | 60 | int readwrite, int type, u8 * values, int len) |
| 59 | { | 61 | { |
| 60 | struct af9005_device_state *st = d->priv; | 62 | struct af9005_device_state *st = d->priv; |
| 61 | u8 obuf[16] = { 0 }; | 63 | u8 command, seq; |
| 62 | u8 ibuf[17] = { 0 }; | 64 | int i, ret; |
| 63 | u8 command; | ||
| 64 | int i; | ||
| 65 | int ret; | ||
| 66 | 65 | ||
| 67 | if (len < 1) { | 66 | if (len < 1) { |
| 68 | err("generic read/write, less than 1 byte. Makes no sense."); | 67 | err("generic read/write, less than 1 byte. Makes no sense."); |
| @@ -73,16 +72,17 @@ static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg, | |||
| 73 | return -EINVAL; | 72 | return -EINVAL; |
| 74 | } | 73 | } |
| 75 | 74 | ||
| 76 | obuf[0] = 14; /* rest of buffer length low */ | 75 | mutex_lock(&st->data_mutex); |
| 77 | obuf[1] = 0; /* rest of buffer length high */ | 76 | st->data[0] = 14; /* rest of buffer length low */ |
| 77 | st->data[1] = 0; /* rest of buffer length high */ | ||
| 78 | 78 | ||
| 79 | obuf[2] = AF9005_REGISTER_RW; /* register operation */ | 79 | st->data[2] = AF9005_REGISTER_RW; /* register operation */ |
| 80 | obuf[3] = 12; /* rest of buffer length */ | 80 | st->data[3] = 12; /* rest of buffer length */ |
| 81 | 81 | ||
| 82 | obuf[4] = st->sequence++; /* sequence number */ | 82 | st->data[4] = seq = st->sequence++; /* sequence number */ |
| 83 | 83 | ||
| 84 | obuf[5] = (u8) (reg >> 8); /* register address */ | 84 | st->data[5] = (u8) (reg >> 8); /* register address */ |
| 85 | obuf[6] = (u8) (reg & 0xff); | 85 | st->data[6] = (u8) (reg & 0xff); |
| 86 | 86 | ||
| 87 | if (type == AF9005_OFDM_REG) { | 87 | if (type == AF9005_OFDM_REG) { |
| 88 | command = AF9005_CMD_OFDM_REG; | 88 | command = AF9005_CMD_OFDM_REG; |
| @@ -96,51 +96,52 @@ static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg, | |||
| 96 | command |= readwrite; | 96 | command |= readwrite; |
| 97 | if (readwrite == AF9005_CMD_WRITE) | 97 | if (readwrite == AF9005_CMD_WRITE) |
| 98 | for (i = 0; i < len; i++) | 98 | for (i = 0; i < len; i++) |
| 99 | obuf[8 + i] = values[i]; | 99 | st->data[8 + i] = values[i]; |
| 100 | else if (type == AF9005_TUNER_REG) | 100 | else if (type == AF9005_TUNER_REG) |
| 101 | /* read command for tuner, the first byte contains the i2c address */ | 101 | /* read command for tuner, the first byte contains the i2c address */ |
| 102 | obuf[8] = values[0]; | 102 | st->data[8] = values[0]; |
| 103 | obuf[7] = command; | 103 | st->data[7] = command; |
| 104 | 104 | ||
| 105 | ret = dvb_usb_generic_rw(d, obuf, 16, ibuf, 17, 0); | 105 | ret = dvb_usb_generic_rw(d, st->data, 16, st->data, 17, 0); |
| 106 | if (ret) | 106 | if (ret) |
| 107 | return ret; | 107 | goto ret; |
| 108 | 108 | ||
| 109 | /* sanity check */ | 109 | /* sanity check */ |
| 110 | if (ibuf[2] != AF9005_REGISTER_RW_ACK) { | 110 | if (st->data[2] != AF9005_REGISTER_RW_ACK) { |
| 111 | err("generic read/write, wrong reply code."); | 111 | err("generic read/write, wrong reply code."); |
| 112 | return -EIO; | 112 | ret = -EIO; |
| 113 | goto ret; | ||
| 113 | } | 114 | } |
| 114 | if (ibuf[3] != 0x0d) { | 115 | if (st->data[3] != 0x0d) { |
| 115 | err("generic read/write, wrong length in reply."); | 116 | err("generic read/write, wrong length in reply."); |
| 116 | return -EIO; | 117 | ret = -EIO; |
| 118 | goto ret; | ||
| 117 | } | 119 | } |
| 118 | if (ibuf[4] != obuf[4]) { | 120 | if (st->data[4] != seq) { |
| 119 | err("generic read/write, wrong sequence in reply."); | 121 | err("generic read/write, wrong sequence in reply."); |
| 120 | return -EIO; | 122 | ret = -EIO; |
| 123 | goto ret; | ||
| 121 | } | 124 | } |
| 122 | /* | 125 | /* |
| 123 | Windows driver doesn't check these fields, in fact sometimes | 126 | * In thesis, both input and output buffers should have |
| 124 | the register in the reply is different that what has been sent | 127 | * identical values for st->data[5] to st->data[8]. |
| 125 | 128 | * However, windows driver doesn't check these fields, in fact | |
| 126 | if (ibuf[5] != obuf[5] || ibuf[6] != obuf[6]) { | 129 | * sometimes the register in the reply is different that what |
| 127 | err("generic read/write, wrong register in reply."); | 130 | * has been sent |
| 128 | return -EIO; | ||
| 129 | } | ||
| 130 | if (ibuf[7] != command) { | ||
| 131 | err("generic read/write wrong command in reply."); | ||
| 132 | return -EIO; | ||
| 133 | } | ||
| 134 | */ | 131 | */ |
| 135 | if (ibuf[16] != 0x01) { | 132 | if (st->data[16] != 0x01) { |
| 136 | err("generic read/write wrong status code in reply."); | 133 | err("generic read/write wrong status code in reply."); |
| 137 | return -EIO; | 134 | ret = -EIO; |
| 135 | goto ret; | ||
| 138 | } | 136 | } |
| 137 | |||
| 139 | if (readwrite == AF9005_CMD_READ) | 138 | if (readwrite == AF9005_CMD_READ) |
| 140 | for (i = 0; i < len; i++) | 139 | for (i = 0; i < len; i++) |
| 141 | values[i] = ibuf[8 + i]; | 140 | values[i] = st->data[8 + i]; |
| 142 | 141 | ||
| 143 | return 0; | 142 | ret: |
| 143 | mutex_unlock(&st->data_mutex); | ||
| 144 | return ret; | ||
| 144 | 145 | ||
| 145 | } | 146 | } |
| 146 | 147 | ||
| @@ -464,8 +465,7 @@ int af9005_send_command(struct dvb_usb_device *d, u8 command, u8 * wbuf, | |||
| 464 | struct af9005_device_state *st = d->priv; | 465 | struct af9005_device_state *st = d->priv; |
| 465 | 466 | ||
| 466 | int ret, i, packet_len; | 467 | int ret, i, packet_len; |
| 467 | u8 buf[64]; | 468 | u8 seq; |
| 468 | u8 ibuf[64]; | ||
| 469 | 469 | ||
| 470 | if (wlen < 0) { | 470 | if (wlen < 0) { |
| 471 | err("send command, wlen less than 0 bytes. Makes no sense."); | 471 | err("send command, wlen less than 0 bytes. Makes no sense."); |
| @@ -480,94 +480,97 @@ int af9005_send_command(struct dvb_usb_device *d, u8 command, u8 * wbuf, | |||
| 480 | return -EINVAL; | 480 | return -EINVAL; |
| 481 | } | 481 | } |
| 482 | packet_len = wlen + 5; | 482 | packet_len = wlen + 5; |
| 483 | buf[0] = (u8) (packet_len & 0xff); | 483 | |
| 484 | buf[1] = (u8) ((packet_len & 0xff00) >> 8); | 484 | mutex_lock(&st->data_mutex); |
| 485 | 485 | ||
| 486 | buf[2] = 0x26; /* packet type */ | 486 | st->data[0] = (u8) (packet_len & 0xff); |
| 487 | buf[3] = wlen + 3; | 487 | st->data[1] = (u8) ((packet_len & 0xff00) >> 8); |
| 488 | buf[4] = st->sequence++; | 488 | |
| 489 | buf[5] = command; | 489 | st->data[2] = 0x26; /* packet type */ |
| 490 | buf[6] = wlen; | 490 | st->data[3] = wlen + 3; |
| 491 | st->data[4] = seq = st->sequence++; | ||
| 492 | st->data[5] = command; | ||
| 493 | st->data[6] = wlen; | ||
| 491 | for (i = 0; i < wlen; i++) | 494 | for (i = 0; i < wlen; i++) |
| 492 | buf[7 + i] = wbuf[i]; | 495 | st->data[7 + i] = wbuf[i]; |
| 493 | ret = dvb_usb_generic_rw(d, buf, wlen + 7, ibuf, rlen + 7, 0); | 496 | ret = dvb_usb_generic_rw(d, st->data, wlen + 7, st->data, rlen + 7, 0); |
| 494 | if (ret) | 497 | if (st->data[2] != 0x27) { |
| 495 | return ret; | ||
| 496 | if (ibuf[2] != 0x27) { | ||
| 497 | err("send command, wrong reply code."); | 498 | err("send command, wrong reply code."); |
| 498 | return -EIO; | 499 | ret = -EIO; |
| 499 | } | 500 | } else if (st->data[4] != seq) { |
| 500 | if (ibuf[4] != buf[4]) { | ||
| 501 | err("send command, wrong sequence in reply."); | 501 | err("send command, wrong sequence in reply."); |
| 502 | return -EIO; | 502 | ret = -EIO; |
| 503 | } | 503 | } else if (st->data[5] != 0x01) { |
| 504 | if (ibuf[5] != 0x01) { | ||
| 505 | err("send command, wrong status code in reply."); | 504 | err("send command, wrong status code in reply."); |
| 506 | return -EIO; | 505 | ret = -EIO; |
| 507 | } | 506 | } else if (st->data[6] != rlen) { |
| 508 | if (ibuf[6] != rlen) { | ||
| 509 | err("send command, invalid data length in reply."); | 507 | err("send command, invalid data length in reply."); |
| 510 | return -EIO; | 508 | ret = -EIO; |
| 511 | } | 509 | } |
| 512 | for (i = 0; i < rlen; i++) | 510 | if (!ret) { |
| 513 | rbuf[i] = ibuf[i + 7]; | 511 | for (i = 0; i < rlen; i++) |
| 514 | return 0; | 512 | rbuf[i] = st->data[i + 7]; |
| 513 | } | ||
| 514 | |||
| 515 | mutex_unlock(&st->data_mutex); | ||
| 516 | return ret; | ||
| 515 | } | 517 | } |
| 516 | 518 | ||
| 517 | int af9005_read_eeprom(struct dvb_usb_device *d, u8 address, u8 * values, | 519 | int af9005_read_eeprom(struct dvb_usb_device *d, u8 address, u8 * values, |
| 518 | int len) | 520 | int len) |
| 519 | { | 521 | { |
| 520 | struct af9005_device_state *st = d->priv; | 522 | struct af9005_device_state *st = d->priv; |
| 521 | u8 obuf[16], ibuf[14]; | 523 | u8 seq; |
| 522 | int ret, i; | 524 | int ret, i; |
| 523 | 525 | ||
| 524 | memset(obuf, 0, sizeof(obuf)); | 526 | mutex_lock(&st->data_mutex); |
| 525 | memset(ibuf, 0, sizeof(ibuf)); | ||
| 526 | 527 | ||
| 527 | obuf[0] = 14; /* length of rest of packet low */ | 528 | memset(st->data, 0, sizeof(st->data)); |
| 528 | obuf[1] = 0; /* length of rest of packer high */ | ||
| 529 | 529 | ||
| 530 | obuf[2] = 0x2a; /* read/write eeprom */ | 530 | st->data[0] = 14; /* length of rest of packet low */ |
| 531 | st->data[1] = 0; /* length of rest of packer high */ | ||
| 531 | 532 | ||
| 532 | obuf[3] = 12; /* size */ | 533 | st->data[2] = 0x2a; /* read/write eeprom */ |
| 533 | 534 | ||
| 534 | obuf[4] = st->sequence++; | 535 | st->data[3] = 12; /* size */ |
| 535 | 536 | ||
| 536 | obuf[5] = 0; /* read */ | 537 | st->data[4] = seq = st->sequence++; |
| 537 | 538 | ||
| 538 | obuf[6] = len; | 539 | st->data[5] = 0; /* read */ |
| 539 | obuf[7] = address; | 540 | |
| 540 | ret = dvb_usb_generic_rw(d, obuf, 16, ibuf, 14, 0); | 541 | st->data[6] = len; |
| 541 | if (ret) | 542 | st->data[7] = address; |
| 542 | return ret; | 543 | ret = dvb_usb_generic_rw(d, st->data, 16, st->data, 14, 0); |
| 543 | if (ibuf[2] != 0x2b) { | 544 | if (st->data[2] != 0x2b) { |
| 544 | err("Read eeprom, invalid reply code"); | 545 | err("Read eeprom, invalid reply code"); |
| 545 | return -EIO; | 546 | ret = -EIO; |
| 546 | } | 547 | } else if (st->data[3] != 10) { |
| 547 | if (ibuf[3] != 10) { | ||
| 548 | err("Read eeprom, invalid reply length"); | 548 | err("Read eeprom, invalid reply length"); |
| 549 | return -EIO; | 549 | ret = -EIO; |
| 550 | } | 550 | } else if (st->data[4] != seq) { |
| 551 | if (ibuf[4] != obuf[4]) { | ||
| 552 | err("Read eeprom, wrong sequence in reply "); | 551 | err("Read eeprom, wrong sequence in reply "); |
| 553 | return -EIO; | 552 | ret = -EIO; |
| 554 | } | 553 | } else if (st->data[5] != 1) { |
| 555 | if (ibuf[5] != 1) { | ||
| 556 | err("Read eeprom, wrong status in reply "); | 554 | err("Read eeprom, wrong status in reply "); |
| 557 | return -EIO; | 555 | ret = -EIO; |
| 558 | } | 556 | } |
| 559 | for (i = 0; i < len; i++) { | 557 | |
| 560 | values[i] = ibuf[6 + i]; | 558 | if (!ret) { |
| 559 | for (i = 0; i < len; i++) | ||
| 560 | values[i] = st->data[6 + i]; | ||
| 561 | } | 561 | } |
| 562 | return 0; | 562 | mutex_unlock(&st->data_mutex); |
| 563 | |||
| 564 | return ret; | ||
| 563 | } | 565 | } |
| 564 | 566 | ||
| 565 | static int af9005_boot_packet(struct usb_device *udev, int type, u8 * reply) | 567 | static int af9005_boot_packet(struct usb_device *udev, int type, u8 *reply, |
| 568 | u8 *buf, int size) | ||
| 566 | { | 569 | { |
| 567 | u8 buf[FW_BULKOUT_SIZE + 2]; | ||
| 568 | u16 checksum; | 570 | u16 checksum; |
| 569 | int act_len, i, ret; | 571 | int act_len, i, ret; |
| 570 | memset(buf, 0, sizeof(buf)); | 572 | |
| 573 | memset(buf, 0, size); | ||
| 571 | buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff); | 574 | buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff); |
| 572 | buf[1] = (u8) ((FW_BULKOUT_SIZE >> 8) & 0xff); | 575 | buf[1] = (u8) ((FW_BULKOUT_SIZE >> 8) & 0xff); |
| 573 | switch (type) { | 576 | switch (type) { |
| @@ -720,15 +723,21 @@ static int af9005_download_firmware(struct usb_device *udev, const struct firmwa | |||
| 720 | { | 723 | { |
| 721 | int i, packets, ret, act_len; | 724 | int i, packets, ret, act_len; |
| 722 | 725 | ||
| 723 | u8 buf[FW_BULKOUT_SIZE + 2]; | 726 | u8 *buf; |
| 724 | u8 reply; | 727 | u8 reply; |
| 725 | 728 | ||
| 726 | ret = af9005_boot_packet(udev, FW_CONFIG, &reply); | 729 | buf = kmalloc(FW_BULKOUT_SIZE + 2, GFP_KERNEL); |
| 730 | if (!buf) | ||
| 731 | return -ENOMEM; | ||
| 732 | |||
| 733 | ret = af9005_boot_packet(udev, FW_CONFIG, &reply, buf, | ||
| 734 | FW_BULKOUT_SIZE + 2); | ||
| 727 | if (ret) | 735 | if (ret) |
| 728 | return ret; | 736 | goto err; |
| 729 | if (reply != 0x01) { | 737 | if (reply != 0x01) { |
| 730 | err("before downloading firmware, FW_CONFIG expected 0x01, received 0x%x", reply); | 738 | err("before downloading firmware, FW_CONFIG expected 0x01, received 0x%x", reply); |
| 731 | return -EIO; | 739 | ret = -EIO; |
| 740 | goto err; | ||
| 732 | } | 741 | } |
| 733 | packets = fw->size / FW_BULKOUT_SIZE; | 742 | packets = fw->size / FW_BULKOUT_SIZE; |
| 734 | buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff); | 743 | buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff); |
| @@ -743,28 +752,35 @@ static int af9005_download_firmware(struct usb_device *udev, const struct firmwa | |||
| 743 | buf, FW_BULKOUT_SIZE + 2, &act_len, 1000); | 752 | buf, FW_BULKOUT_SIZE + 2, &act_len, 1000); |
| 744 | if (ret) { | 753 | if (ret) { |
| 745 | err("firmware download failed at packet %d with code %d", i, ret); | 754 | err("firmware download failed at packet %d with code %d", i, ret); |
| 746 | return ret; | 755 | goto err; |
| 747 | } | 756 | } |
| 748 | } | 757 | } |
| 749 | ret = af9005_boot_packet(udev, FW_CONFIRM, &reply); | 758 | ret = af9005_boot_packet(udev, FW_CONFIRM, &reply, |
| 759 | buf, FW_BULKOUT_SIZE + 2); | ||
| 750 | if (ret) | 760 | if (ret) |
| 751 | return ret; | 761 | goto err; |
| 752 | if (reply != (u8) (packets & 0xff)) { | 762 | if (reply != (u8) (packets & 0xff)) { |
| 753 | err("after downloading firmware, FW_CONFIRM expected 0x%x, received 0x%x", packets & 0xff, reply); | 763 | err("after downloading firmware, FW_CONFIRM expected 0x%x, received 0x%x", packets & 0xff, reply); |
| 754 | return -EIO; | 764 | ret = -EIO; |
| 765 | goto err; | ||
| 755 | } | 766 | } |
| 756 | ret = af9005_boot_packet(udev, FW_BOOT, &reply); | 767 | ret = af9005_boot_packet(udev, FW_BOOT, &reply, buf, |
| 768 | FW_BULKOUT_SIZE + 2); | ||
| 757 | if (ret) | 769 | if (ret) |
| 758 | return ret; | 770 | goto err; |
| 759 | ret = af9005_boot_packet(udev, FW_CONFIG, &reply); | 771 | ret = af9005_boot_packet(udev, FW_CONFIG, &reply, buf, |
| 772 | FW_BULKOUT_SIZE + 2); | ||
| 760 | if (ret) | 773 | if (ret) |
| 761 | return ret; | 774 | goto err; |
| 762 | if (reply != 0x02) { | 775 | if (reply != 0x02) { |
| 763 | err("after downloading firmware, FW_CONFIG expected 0x02, received 0x%x", reply); | 776 | err("after downloading firmware, FW_CONFIG expected 0x02, received 0x%x", reply); |
| 764 | return -EIO; | 777 | ret = -EIO; |
| 778 | goto err; | ||
| 765 | } | 779 | } |
| 766 | 780 | ||
| 767 | return 0; | 781 | err: |
| 782 | kfree(buf); | ||
| 783 | return ret; | ||
| 768 | 784 | ||
| 769 | } | 785 | } |
| 770 | 786 | ||
| @@ -823,53 +839,59 @@ static int af9005_rc_query(struct dvb_usb_device *d, u32 * event, int *state) | |||
| 823 | { | 839 | { |
| 824 | struct af9005_device_state *st = d->priv; | 840 | struct af9005_device_state *st = d->priv; |
| 825 | int ret, len; | 841 | int ret, len; |
| 826 | 842 | u8 seq; | |
| 827 | u8 obuf[5]; | ||
| 828 | u8 ibuf[256]; | ||
| 829 | 843 | ||
| 830 | *state = REMOTE_NO_KEY_PRESSED; | 844 | *state = REMOTE_NO_KEY_PRESSED; |
| 831 | if (rc_decode == NULL) { | 845 | if (rc_decode == NULL) { |
| 832 | /* it shouldn't never come here */ | 846 | /* it shouldn't never come here */ |
| 833 | return 0; | 847 | return 0; |
| 834 | } | 848 | } |
| 849 | |||
| 850 | mutex_lock(&st->data_mutex); | ||
| 851 | |||
| 835 | /* deb_info("rc_query\n"); */ | 852 | /* deb_info("rc_query\n"); */ |
| 836 | obuf[0] = 3; /* rest of packet length low */ | 853 | st->data[0] = 3; /* rest of packet length low */ |
| 837 | obuf[1] = 0; /* rest of packet lentgh high */ | 854 | st->data[1] = 0; /* rest of packet lentgh high */ |
| 838 | obuf[2] = 0x40; /* read remote */ | 855 | st->data[2] = 0x40; /* read remote */ |
| 839 | obuf[3] = 1; /* rest of packet length */ | 856 | st->data[3] = 1; /* rest of packet length */ |
| 840 | obuf[4] = st->sequence++; /* sequence number */ | 857 | st->data[4] = seq = st->sequence++; /* sequence number */ |
| 841 | ret = dvb_usb_generic_rw(d, obuf, 5, ibuf, 256, 0); | 858 | ret = dvb_usb_generic_rw(d, st->data, 5, st->data, 256, 0); |
| 842 | if (ret) { | 859 | if (ret) { |
| 843 | err("rc query failed"); | 860 | err("rc query failed"); |
| 844 | return ret; | 861 | goto ret; |
| 845 | } | 862 | } |
| 846 | if (ibuf[2] != 0x41) { | 863 | if (st->data[2] != 0x41) { |
| 847 | err("rc query bad header."); | 864 | err("rc query bad header."); |
| 848 | return -EIO; | 865 | ret = -EIO; |
| 849 | } | 866 | goto ret; |
| 850 | if (ibuf[4] != obuf[4]) { | 867 | } else if (st->data[4] != seq) { |
| 851 | err("rc query bad sequence."); | 868 | err("rc query bad sequence."); |
| 852 | return -EIO; | 869 | ret = -EIO; |
| 870 | goto ret; | ||
| 853 | } | 871 | } |
| 854 | len = ibuf[5]; | 872 | len = st->data[5]; |
| 855 | if (len > 246) { | 873 | if (len > 246) { |
| 856 | err("rc query invalid length"); | 874 | err("rc query invalid length"); |
| 857 | return -EIO; | 875 | ret = -EIO; |
| 876 | goto ret; | ||
| 858 | } | 877 | } |
| 859 | if (len > 0) { | 878 | if (len > 0) { |
| 860 | deb_rc("rc data (%d) ", len); | 879 | deb_rc("rc data (%d) ", len); |
| 861 | debug_dump((ibuf + 6), len, deb_rc); | 880 | debug_dump((st->data + 6), len, deb_rc); |
| 862 | ret = rc_decode(d, &ibuf[6], len, event, state); | 881 | ret = rc_decode(d, &st->data[6], len, event, state); |
| 863 | if (ret) { | 882 | if (ret) { |
| 864 | err("rc_decode failed"); | 883 | err("rc_decode failed"); |
| 865 | return ret; | 884 | goto ret; |
| 866 | } else { | 885 | } else { |
| 867 | deb_rc("rc_decode state %x event %x\n", *state, *event); | 886 | deb_rc("rc_decode state %x event %x\n", *state, *event); |
| 868 | if (*state == REMOTE_KEY_REPEAT) | 887 | if (*state == REMOTE_KEY_REPEAT) |
| 869 | *event = d->last_event; | 888 | *event = d->last_event; |
| 870 | } | 889 | } |
| 871 | } | 890 | } |
| 872 | return 0; | 891 | |
| 892 | ret: | ||
| 893 | mutex_unlock(&st->data_mutex); | ||
| 894 | return ret; | ||
| 873 | } | 895 | } |
| 874 | 896 | ||
| 875 | static int af9005_power_ctrl(struct dvb_usb_device *d, int onoff) | 897 | static int af9005_power_ctrl(struct dvb_usb_device *d, int onoff) |
| @@ -953,10 +975,16 @@ static int af9005_identify_state(struct usb_device *udev, | |||
| 953 | int *cold) | 975 | int *cold) |
| 954 | { | 976 | { |
| 955 | int ret; | 977 | int ret; |
| 956 | u8 reply; | 978 | u8 reply, *buf; |
| 957 | ret = af9005_boot_packet(udev, FW_CONFIG, &reply); | 979 | |
| 980 | buf = kmalloc(FW_BULKOUT_SIZE + 2, GFP_KERNEL); | ||
| 981 | if (!buf) | ||
| 982 | return -ENOMEM; | ||
| 983 | |||
| 984 | ret = af9005_boot_packet(udev, FW_CONFIG, &reply, | ||
| 985 | buf, FW_BULKOUT_SIZE + 2); | ||
| 958 | if (ret) | 986 | if (ret) |
| 959 | return ret; | 987 | goto err; |
| 960 | deb_info("result of FW_CONFIG in identify state %d\n", reply); | 988 | deb_info("result of FW_CONFIG in identify state %d\n", reply); |
| 961 | if (reply == 0x01) | 989 | if (reply == 0x01) |
| 962 | *cold = 1; | 990 | *cold = 1; |
| @@ -965,7 +993,10 @@ static int af9005_identify_state(struct usb_device *udev, | |||
| 965 | else | 993 | else |
| 966 | return -EIO; | 994 | return -EIO; |
| 967 | deb_info("Identify state cold = %d\n", *cold); | 995 | deb_info("Identify state cold = %d\n", *cold); |
| 968 | return 0; | 996 | |
| 997 | err: | ||
| 998 | kfree(buf); | ||
| 999 | return ret; | ||
| 969 | } | 1000 | } |
| 970 | 1001 | ||
| 971 | static struct dvb_usb_device_properties af9005_properties; | 1002 | static struct dvb_usb_device_properties af9005_properties; |
| @@ -973,8 +1004,20 @@ static struct dvb_usb_device_properties af9005_properties; | |||
| 973 | static int af9005_usb_probe(struct usb_interface *intf, | 1004 | static int af9005_usb_probe(struct usb_interface *intf, |
| 974 | const struct usb_device_id *id) | 1005 | const struct usb_device_id *id) |
| 975 | { | 1006 | { |
| 976 | return dvb_usb_device_init(intf, &af9005_properties, | 1007 | struct dvb_usb_device *d; |
| 977 | THIS_MODULE, NULL, adapter_nr); | 1008 | struct af9005_device_state *st; |
| 1009 | int ret; | ||
| 1010 | |||
| 1011 | ret = dvb_usb_device_init(intf, &af9005_properties, | ||
| 1012 | THIS_MODULE, &d, adapter_nr); | ||
| 1013 | |||
| 1014 | if (ret < 0) | ||
| 1015 | return ret; | ||
| 1016 | |||
| 1017 | st = d->priv; | ||
| 1018 | mutex_init(&st->data_mutex); | ||
| 1019 | |||
| 1020 | return 0; | ||
| 978 | } | 1021 | } |
| 979 | 1022 | ||
| 980 | enum af9005_usb_table_entry { | 1023 | enum af9005_usb_table_entry { |
diff --git a/drivers/media/usb/dvb-usb/cinergyT2-core.c b/drivers/media/usb/dvb-usb/cinergyT2-core.c index 9fd1527494eb..8ac825413d5a 100644 --- a/drivers/media/usb/dvb-usb/cinergyT2-core.c +++ b/drivers/media/usb/dvb-usb/cinergyT2-core.c | |||
| @@ -41,6 +41,8 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | |||
| 41 | 41 | ||
| 42 | struct cinergyt2_state { | 42 | struct cinergyt2_state { |
| 43 | u8 rc_counter; | 43 | u8 rc_counter; |
| 44 | unsigned char data[64]; | ||
| 45 | struct mutex data_mutex; | ||
| 44 | }; | 46 | }; |
| 45 | 47 | ||
| 46 | /* We are missing a release hook with usb_device data */ | 48 | /* We are missing a release hook with usb_device data */ |
| @@ -50,38 +52,57 @@ static struct dvb_usb_device_properties cinergyt2_properties; | |||
| 50 | 52 | ||
| 51 | static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable) | 53 | static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable) |
| 52 | { | 54 | { |
| 53 | char buf[] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 }; | 55 | struct dvb_usb_device *d = adap->dev; |
| 54 | char result[64]; | 56 | struct cinergyt2_state *st = d->priv; |
| 55 | return dvb_usb_generic_rw(adap->dev, buf, sizeof(buf), result, | 57 | int ret; |
| 56 | sizeof(result), 0); | 58 | |
| 59 | mutex_lock(&st->data_mutex); | ||
| 60 | st->data[0] = CINERGYT2_EP1_CONTROL_STREAM_TRANSFER; | ||
| 61 | st->data[1] = enable ? 1 : 0; | ||
| 62 | |||
| 63 | ret = dvb_usb_generic_rw(d, st->data, 2, st->data, 64, 0); | ||
| 64 | mutex_unlock(&st->data_mutex); | ||
| 65 | |||
| 66 | return ret; | ||
| 57 | } | 67 | } |
| 58 | 68 | ||
| 59 | static int cinergyt2_power_ctrl(struct dvb_usb_device *d, int enable) | 69 | static int cinergyt2_power_ctrl(struct dvb_usb_device *d, int enable) |
| 60 | { | 70 | { |
| 61 | char buf[] = { CINERGYT2_EP1_SLEEP_MODE, enable ? 0 : 1 }; | 71 | struct cinergyt2_state *st = d->priv; |
| 62 | char state[3]; | 72 | int ret; |
| 63 | return dvb_usb_generic_rw(d, buf, sizeof(buf), state, sizeof(state), 0); | 73 | |
| 74 | mutex_lock(&st->data_mutex); | ||
| 75 | st->data[0] = CINERGYT2_EP1_SLEEP_MODE; | ||
| 76 | st->data[1] = enable ? 0 : 1; | ||
| 77 | |||
| 78 | ret = dvb_usb_generic_rw(d, st->data, 2, st->data, 3, 0); | ||
| 79 | mutex_unlock(&st->data_mutex); | ||
| 80 | |||
| 81 | return ret; | ||
| 64 | } | 82 | } |
| 65 | 83 | ||
| 66 | static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap) | 84 | static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap) |
| 67 | { | 85 | { |
| 68 | char query[] = { CINERGYT2_EP1_GET_FIRMWARE_VERSION }; | 86 | struct dvb_usb_device *d = adap->dev; |
| 69 | char state[3]; | 87 | struct cinergyt2_state *st = d->priv; |
| 70 | int ret; | 88 | int ret; |
| 71 | 89 | ||
| 72 | adap->fe_adap[0].fe = cinergyt2_fe_attach(adap->dev); | 90 | adap->fe_adap[0].fe = cinergyt2_fe_attach(adap->dev); |
| 73 | 91 | ||
| 74 | ret = dvb_usb_generic_rw(adap->dev, query, sizeof(query), state, | 92 | mutex_lock(&st->data_mutex); |
| 75 | sizeof(state), 0); | 93 | st->data[0] = CINERGYT2_EP1_GET_FIRMWARE_VERSION; |
| 94 | |||
| 95 | ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 3, 0); | ||
| 76 | if (ret < 0) { | 96 | if (ret < 0) { |
| 77 | deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep " | 97 | deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep " |
| 78 | "state info\n"); | 98 | "state info\n"); |
| 79 | } | 99 | } |
| 100 | mutex_unlock(&st->data_mutex); | ||
| 80 | 101 | ||
| 81 | /* Copy this pointer as we are gonna need it in the release phase */ | 102 | /* Copy this pointer as we are gonna need it in the release phase */ |
| 82 | cinergyt2_usb_device = adap->dev; | 103 | cinergyt2_usb_device = adap->dev; |
| 83 | 104 | ||
| 84 | return 0; | 105 | return ret; |
| 85 | } | 106 | } |
| 86 | 107 | ||
| 87 | static struct rc_map_table rc_map_cinergyt2_table[] = { | 108 | static struct rc_map_table rc_map_cinergyt2_table[] = { |
| @@ -141,13 +162,18 @@ static int repeatable_keys[] = { | |||
| 141 | static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | 162 | static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state) |
| 142 | { | 163 | { |
| 143 | struct cinergyt2_state *st = d->priv; | 164 | struct cinergyt2_state *st = d->priv; |
| 144 | u8 key[5] = {0, 0, 0, 0, 0}, cmd = CINERGYT2_EP1_GET_RC_EVENTS; | 165 | int i, ret; |
| 145 | int i; | ||
| 146 | 166 | ||
| 147 | *state = REMOTE_NO_KEY_PRESSED; | 167 | *state = REMOTE_NO_KEY_PRESSED; |
| 148 | 168 | ||
| 149 | dvb_usb_generic_rw(d, &cmd, 1, key, sizeof(key), 0); | 169 | mutex_lock(&st->data_mutex); |
| 150 | if (key[4] == 0xff) { | 170 | st->data[0] = CINERGYT2_EP1_GET_RC_EVENTS; |
| 171 | |||
| 172 | ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 5, 0); | ||
| 173 | if (ret < 0) | ||
| 174 | goto ret; | ||
| 175 | |||
| 176 | if (st->data[4] == 0xff) { | ||
| 151 | /* key repeat */ | 177 | /* key repeat */ |
| 152 | st->rc_counter++; | 178 | st->rc_counter++; |
| 153 | if (st->rc_counter > RC_REPEAT_DELAY) { | 179 | 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 | *event = d->last_event; | 183 | *event = d->last_event; |
| 158 | deb_rc("repeat key, event %x\n", | 184 | deb_rc("repeat key, event %x\n", |
| 159 | *event); | 185 | *event); |
| 160 | return 0; | 186 | goto ret; |
| 161 | } | 187 | } |
| 162 | } | 188 | } |
| 163 | deb_rc("repeated key (non repeatable)\n"); | 189 | deb_rc("repeated key (non repeatable)\n"); |
| 164 | } | 190 | } |
| 165 | return 0; | 191 | goto ret; |
| 166 | } | 192 | } |
| 167 | 193 | ||
| 168 | /* hack to pass checksum on the custom field */ | 194 | /* hack to pass checksum on the custom field */ |
| 169 | key[2] = ~key[1]; | 195 | st->data[2] = ~st->data[1]; |
| 170 | dvb_usb_nec_rc_key_to_event(d, key, event, state); | 196 | dvb_usb_nec_rc_key_to_event(d, st->data, event, state); |
| 171 | if (key[0] != 0) { | 197 | if (st->data[0] != 0) { |
| 172 | if (*event != d->last_event) | 198 | if (*event != d->last_event) |
| 173 | st->rc_counter = 0; | 199 | st->rc_counter = 0; |
| 174 | 200 | ||
| 175 | deb_rc("key: %*ph\n", 5, key); | 201 | deb_rc("key: %*ph\n", 5, st->data); |
| 176 | } | 202 | } |
| 177 | return 0; | 203 | |
| 204 | ret: | ||
| 205 | mutex_unlock(&st->data_mutex); | ||
| 206 | return ret; | ||
| 178 | } | 207 | } |
| 179 | 208 | ||
| 180 | static int cinergyt2_usb_probe(struct usb_interface *intf, | 209 | static int cinergyt2_usb_probe(struct usb_interface *intf, |
| 181 | const struct usb_device_id *id) | 210 | const struct usb_device_id *id) |
| 182 | { | 211 | { |
| 183 | return dvb_usb_device_init(intf, &cinergyt2_properties, | 212 | struct dvb_usb_device *d; |
| 184 | THIS_MODULE, NULL, adapter_nr); | 213 | struct cinergyt2_state *st; |
| 214 | int ret; | ||
| 215 | |||
| 216 | ret = dvb_usb_device_init(intf, &cinergyt2_properties, | ||
| 217 | THIS_MODULE, &d, adapter_nr); | ||
| 218 | if (ret < 0) | ||
| 219 | return ret; | ||
| 220 | |||
| 221 | st = d->priv; | ||
| 222 | mutex_init(&st->data_mutex); | ||
| 223 | |||
| 224 | return 0; | ||
| 185 | } | 225 | } |
| 186 | 226 | ||
| 187 | 227 | ||
diff --git a/drivers/media/usb/dvb-usb/cinergyT2-fe.c b/drivers/media/usb/dvb-usb/cinergyT2-fe.c index b3ec743a7a2e..2d29b4174dba 100644 --- a/drivers/media/usb/dvb-usb/cinergyT2-fe.c +++ b/drivers/media/usb/dvb-usb/cinergyT2-fe.c | |||
| @@ -139,32 +139,42 @@ static uint16_t compute_tps(struct dtv_frontend_properties *op) | |||
| 139 | struct cinergyt2_fe_state { | 139 | struct cinergyt2_fe_state { |
| 140 | struct dvb_frontend fe; | 140 | struct dvb_frontend fe; |
| 141 | struct dvb_usb_device *d; | 141 | struct dvb_usb_device *d; |
| 142 | |||
| 143 | unsigned char data[64]; | ||
| 144 | struct mutex data_mutex; | ||
| 145 | |||
| 146 | struct dvbt_get_status_msg status; | ||
| 142 | }; | 147 | }; |
| 143 | 148 | ||
| 144 | static int cinergyt2_fe_read_status(struct dvb_frontend *fe, | 149 | static int cinergyt2_fe_read_status(struct dvb_frontend *fe, |
| 145 | enum fe_status *status) | 150 | enum fe_status *status) |
| 146 | { | 151 | { |
| 147 | struct cinergyt2_fe_state *state = fe->demodulator_priv; | 152 | struct cinergyt2_fe_state *state = fe->demodulator_priv; |
| 148 | struct dvbt_get_status_msg result; | ||
| 149 | u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; | ||
| 150 | int ret; | 153 | int ret; |
| 151 | 154 | ||
| 152 | ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&result, | 155 | mutex_lock(&state->data_mutex); |
| 153 | sizeof(result), 0); | 156 | state->data[0] = CINERGYT2_EP1_GET_TUNER_STATUS; |
| 157 | |||
| 158 | ret = dvb_usb_generic_rw(state->d, state->data, 1, | ||
| 159 | state->data, sizeof(state->status), 0); | ||
| 160 | if (!ret) | ||
| 161 | memcpy(&state->status, state->data, sizeof(state->status)); | ||
| 162 | mutex_unlock(&state->data_mutex); | ||
| 163 | |||
| 154 | if (ret < 0) | 164 | if (ret < 0) |
| 155 | return ret; | 165 | return ret; |
| 156 | 166 | ||
| 157 | *status = 0; | 167 | *status = 0; |
| 158 | 168 | ||
| 159 | if (0xffff - le16_to_cpu(result.gain) > 30) | 169 | if (0xffff - le16_to_cpu(state->status.gain) > 30) |
| 160 | *status |= FE_HAS_SIGNAL; | 170 | *status |= FE_HAS_SIGNAL; |
| 161 | if (result.lock_bits & (1 << 6)) | 171 | if (state->status.lock_bits & (1 << 6)) |
| 162 | *status |= FE_HAS_LOCK; | 172 | *status |= FE_HAS_LOCK; |
| 163 | if (result.lock_bits & (1 << 5)) | 173 | if (state->status.lock_bits & (1 << 5)) |
| 164 | *status |= FE_HAS_SYNC; | 174 | *status |= FE_HAS_SYNC; |
| 165 | if (result.lock_bits & (1 << 4)) | 175 | if (state->status.lock_bits & (1 << 4)) |
| 166 | *status |= FE_HAS_CARRIER; | 176 | *status |= FE_HAS_CARRIER; |
| 167 | if (result.lock_bits & (1 << 1)) | 177 | if (state->status.lock_bits & (1 << 1)) |
| 168 | *status |= FE_HAS_VITERBI; | 178 | *status |= FE_HAS_VITERBI; |
| 169 | 179 | ||
| 170 | if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) != | 180 | 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 | static int cinergyt2_fe_read_ber(struct dvb_frontend *fe, u32 *ber) | 187 | static int cinergyt2_fe_read_ber(struct dvb_frontend *fe, u32 *ber) |
| 178 | { | 188 | { |
| 179 | struct cinergyt2_fe_state *state = fe->demodulator_priv; | 189 | struct cinergyt2_fe_state *state = fe->demodulator_priv; |
| 180 | struct dvbt_get_status_msg status; | ||
| 181 | char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; | ||
| 182 | int ret; | ||
| 183 | |||
| 184 | ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, | ||
| 185 | sizeof(status), 0); | ||
| 186 | if (ret < 0) | ||
| 187 | return ret; | ||
| 188 | 190 | ||
| 189 | *ber = le32_to_cpu(status.viterbi_error_rate); | 191 | *ber = le32_to_cpu(state->status.viterbi_error_rate); |
| 190 | return 0; | 192 | return 0; |
| 191 | } | 193 | } |
| 192 | 194 | ||
| 193 | static int cinergyt2_fe_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) | 195 | static int cinergyt2_fe_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) |
| 194 | { | 196 | { |
| 195 | struct cinergyt2_fe_state *state = fe->demodulator_priv; | 197 | struct cinergyt2_fe_state *state = fe->demodulator_priv; |
| 196 | struct dvbt_get_status_msg status; | ||
| 197 | u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; | ||
| 198 | int ret; | ||
| 199 | 198 | ||
| 200 | ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&status, | 199 | *unc = le32_to_cpu(state->status.uncorrected_block_count); |
| 201 | sizeof(status), 0); | ||
| 202 | if (ret < 0) { | ||
| 203 | err("cinergyt2_fe_read_unc_blocks() Failed! (Error=%d)\n", | ||
| 204 | ret); | ||
| 205 | return ret; | ||
| 206 | } | ||
| 207 | *unc = le32_to_cpu(status.uncorrected_block_count); | ||
| 208 | return 0; | 200 | return 0; |
| 209 | } | 201 | } |
| 210 | 202 | ||
| @@ -212,35 +204,16 @@ static int cinergyt2_fe_read_signal_strength(struct dvb_frontend *fe, | |||
| 212 | u16 *strength) | 204 | u16 *strength) |
| 213 | { | 205 | { |
| 214 | struct cinergyt2_fe_state *state = fe->demodulator_priv; | 206 | struct cinergyt2_fe_state *state = fe->demodulator_priv; |
| 215 | struct dvbt_get_status_msg status; | ||
| 216 | char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; | ||
| 217 | int ret; | ||
| 218 | 207 | ||
| 219 | ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, | 208 | *strength = (0xffff - le16_to_cpu(state->status.gain)); |
| 220 | sizeof(status), 0); | ||
| 221 | if (ret < 0) { | ||
| 222 | err("cinergyt2_fe_read_signal_strength() Failed!" | ||
| 223 | " (Error=%d)\n", ret); | ||
| 224 | return ret; | ||
| 225 | } | ||
| 226 | *strength = (0xffff - le16_to_cpu(status.gain)); | ||
| 227 | return 0; | 209 | return 0; |
| 228 | } | 210 | } |
| 229 | 211 | ||
| 230 | static int cinergyt2_fe_read_snr(struct dvb_frontend *fe, u16 *snr) | 212 | static int cinergyt2_fe_read_snr(struct dvb_frontend *fe, u16 *snr) |
| 231 | { | 213 | { |
| 232 | struct cinergyt2_fe_state *state = fe->demodulator_priv; | 214 | struct cinergyt2_fe_state *state = fe->demodulator_priv; |
| 233 | struct dvbt_get_status_msg status; | ||
| 234 | char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; | ||
| 235 | int ret; | ||
| 236 | 215 | ||
| 237 | ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, | 216 | *snr = (state->status.snr << 8) | state->status.snr; |
| 238 | sizeof(status), 0); | ||
| 239 | if (ret < 0) { | ||
| 240 | err("cinergyt2_fe_read_snr() Failed! (Error=%d)\n", ret); | ||
| 241 | return ret; | ||
| 242 | } | ||
| 243 | *snr = (status.snr << 8) | status.snr; | ||
| 244 | return 0; | 217 | return 0; |
| 245 | } | 218 | } |
| 246 | 219 | ||
| @@ -266,34 +239,36 @@ static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe) | |||
| 266 | { | 239 | { |
| 267 | struct dtv_frontend_properties *fep = &fe->dtv_property_cache; | 240 | struct dtv_frontend_properties *fep = &fe->dtv_property_cache; |
| 268 | struct cinergyt2_fe_state *state = fe->demodulator_priv; | 241 | struct cinergyt2_fe_state *state = fe->demodulator_priv; |
| 269 | struct dvbt_set_parameters_msg param; | 242 | struct dvbt_set_parameters_msg *param; |
| 270 | char result[2]; | ||
| 271 | int err; | 243 | int err; |
| 272 | 244 | ||
| 273 | param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; | 245 | mutex_lock(&state->data_mutex); |
| 274 | param.tps = cpu_to_le16(compute_tps(fep)); | 246 | |
| 275 | param.freq = cpu_to_le32(fep->frequency / 1000); | 247 | param = (void *)state->data; |
| 276 | param.flags = 0; | 248 | param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; |
| 249 | param->tps = cpu_to_le16(compute_tps(fep)); | ||
| 250 | param->freq = cpu_to_le32(fep->frequency / 1000); | ||
| 251 | param->flags = 0; | ||
| 277 | 252 | ||
| 278 | switch (fep->bandwidth_hz) { | 253 | switch (fep->bandwidth_hz) { |
| 279 | default: | 254 | default: |
| 280 | case 8000000: | 255 | case 8000000: |
| 281 | param.bandwidth = 8; | 256 | param->bandwidth = 8; |
| 282 | break; | 257 | break; |
| 283 | case 7000000: | 258 | case 7000000: |
| 284 | param.bandwidth = 7; | 259 | param->bandwidth = 7; |
| 285 | break; | 260 | break; |
| 286 | case 6000000: | 261 | case 6000000: |
| 287 | param.bandwidth = 6; | 262 | param->bandwidth = 6; |
| 288 | break; | 263 | break; |
| 289 | } | 264 | } |
| 290 | 265 | ||
| 291 | err = dvb_usb_generic_rw(state->d, | 266 | err = dvb_usb_generic_rw(state->d, state->data, sizeof(*param), |
| 292 | (char *)¶m, sizeof(param), | 267 | state->data, 2, 0); |
| 293 | result, sizeof(result), 0); | ||
| 294 | if (err < 0) | 268 | if (err < 0) |
| 295 | err("cinergyt2_fe_set_frontend() Failed! err=%d\n", err); | 269 | err("cinergyt2_fe_set_frontend() Failed! err=%d\n", err); |
| 296 | 270 | ||
| 271 | mutex_unlock(&state->data_mutex); | ||
| 297 | return (err < 0) ? err : 0; | 272 | return (err < 0) ? err : 0; |
| 298 | } | 273 | } |
| 299 | 274 | ||
| @@ -315,6 +290,7 @@ struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d) | |||
| 315 | s->d = d; | 290 | s->d = d; |
| 316 | memcpy(&s->fe.ops, &cinergyt2_fe_ops, sizeof(struct dvb_frontend_ops)); | 291 | memcpy(&s->fe.ops, &cinergyt2_fe_ops, sizeof(struct dvb_frontend_ops)); |
| 317 | s->fe.demodulator_priv = s; | 292 | s->fe.demodulator_priv = s; |
| 293 | mutex_init(&s->data_mutex); | ||
| 318 | return &s->fe; | 294 | return &s->fe; |
| 319 | } | 295 | } |
| 320 | 296 | ||
diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c index 907ac01ae297..39772812269d 100644 --- a/drivers/media/usb/dvb-usb/cxusb.c +++ b/drivers/media/usb/dvb-usb/cxusb.c | |||
| @@ -45,9 +45,6 @@ | |||
| 45 | #include "si2168.h" | 45 | #include "si2168.h" |
| 46 | #include "si2157.h" | 46 | #include "si2157.h" |
| 47 | 47 | ||
| 48 | /* Max transfer size done by I2C transfer functions */ | ||
| 49 | #define MAX_XFER_SIZE 80 | ||
| 50 | |||
| 51 | /* debug */ | 48 | /* debug */ |
| 52 | static int dvb_usb_cxusb_debug; | 49 | static int dvb_usb_cxusb_debug; |
| 53 | module_param_named(debug, dvb_usb_cxusb_debug, int, 0644); | 50 | module_param_named(debug, dvb_usb_cxusb_debug, int, 0644); |
| @@ -61,23 +58,27 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | |||
| 61 | static int cxusb_ctrl_msg(struct dvb_usb_device *d, | 58 | static int cxusb_ctrl_msg(struct dvb_usb_device *d, |
| 62 | u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) | 59 | u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) |
| 63 | { | 60 | { |
| 64 | int wo = (rbuf == NULL || rlen == 0); /* write-only */ | 61 | struct cxusb_state *st = d->priv; |
| 65 | u8 sndbuf[MAX_XFER_SIZE]; | 62 | int ret, wo; |
| 66 | 63 | ||
| 67 | if (1 + wlen > sizeof(sndbuf)) { | 64 | if (1 + wlen > MAX_XFER_SIZE) { |
| 68 | warn("i2c wr: len=%d is too big!\n", | 65 | warn("i2c wr: len=%d is too big!\n", wlen); |
| 69 | wlen); | ||
| 70 | return -EOPNOTSUPP; | 66 | return -EOPNOTSUPP; |
| 71 | } | 67 | } |
| 72 | 68 | ||
| 73 | memset(sndbuf, 0, 1+wlen); | 69 | wo = (rbuf == NULL || rlen == 0); /* write-only */ |
| 74 | 70 | ||
| 75 | sndbuf[0] = cmd; | 71 | mutex_lock(&st->data_mutex); |
| 76 | memcpy(&sndbuf[1], wbuf, wlen); | 72 | st->data[0] = cmd; |
| 73 | memcpy(&st->data[1], wbuf, wlen); | ||
| 77 | if (wo) | 74 | if (wo) |
| 78 | return dvb_usb_generic_write(d, sndbuf, 1+wlen); | 75 | ret = dvb_usb_generic_write(d, st->data, 1 + wlen); |
| 79 | else | 76 | else |
| 80 | return dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0); | 77 | ret = dvb_usb_generic_rw(d, st->data, 1 + wlen, |
| 78 | rbuf, rlen, 0); | ||
| 79 | |||
| 80 | mutex_unlock(&st->data_mutex); | ||
| 81 | return ret; | ||
| 81 | } | 82 | } |
| 82 | 83 | ||
| 83 | /* GPIO */ | 84 | /* GPIO */ |
| @@ -1460,36 +1461,43 @@ static struct dvb_usb_device_properties cxusb_mygica_t230_properties; | |||
| 1460 | static int cxusb_probe(struct usb_interface *intf, | 1461 | static int cxusb_probe(struct usb_interface *intf, |
| 1461 | const struct usb_device_id *id) | 1462 | const struct usb_device_id *id) |
| 1462 | { | 1463 | { |
| 1464 | struct dvb_usb_device *d; | ||
| 1465 | struct cxusb_state *st; | ||
| 1466 | |||
| 1463 | if (0 == dvb_usb_device_init(intf, &cxusb_medion_properties, | 1467 | if (0 == dvb_usb_device_init(intf, &cxusb_medion_properties, |
| 1464 | THIS_MODULE, NULL, adapter_nr) || | 1468 | THIS_MODULE, &d, adapter_nr) || |
| 1465 | 0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgh064f_properties, | 1469 | 0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgh064f_properties, |
| 1466 | THIS_MODULE, NULL, adapter_nr) || | 1470 | THIS_MODULE, &d, adapter_nr) || |
| 1467 | 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dee1601_properties, | 1471 | 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dee1601_properties, |
| 1468 | THIS_MODULE, NULL, adapter_nr) || | 1472 | THIS_MODULE, &d, adapter_nr) || |
| 1469 | 0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgz201_properties, | 1473 | 0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgz201_properties, |
| 1470 | THIS_MODULE, NULL, adapter_nr) || | 1474 | THIS_MODULE, &d, adapter_nr) || |
| 1471 | 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dtt7579_properties, | 1475 | 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dtt7579_properties, |
| 1472 | THIS_MODULE, NULL, adapter_nr) || | 1476 | THIS_MODULE, &d, adapter_nr) || |
| 1473 | 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dualdig4_properties, | 1477 | 0 == dvb_usb_device_init(intf, &cxusb_bluebird_dualdig4_properties, |
| 1474 | THIS_MODULE, NULL, adapter_nr) || | 1478 | THIS_MODULE, &d, adapter_nr) || |
| 1475 | 0 == dvb_usb_device_init(intf, &cxusb_bluebird_nano2_properties, | 1479 | 0 == dvb_usb_device_init(intf, &cxusb_bluebird_nano2_properties, |
| 1476 | THIS_MODULE, NULL, adapter_nr) || | 1480 | THIS_MODULE, &d, adapter_nr) || |
| 1477 | 0 == dvb_usb_device_init(intf, | 1481 | 0 == dvb_usb_device_init(intf, |
| 1478 | &cxusb_bluebird_nano2_needsfirmware_properties, | 1482 | &cxusb_bluebird_nano2_needsfirmware_properties, |
| 1479 | THIS_MODULE, NULL, adapter_nr) || | 1483 | THIS_MODULE, &d, adapter_nr) || |
| 1480 | 0 == dvb_usb_device_init(intf, &cxusb_aver_a868r_properties, | 1484 | 0 == dvb_usb_device_init(intf, &cxusb_aver_a868r_properties, |
| 1481 | THIS_MODULE, NULL, adapter_nr) || | 1485 | THIS_MODULE, &d, adapter_nr) || |
| 1482 | 0 == dvb_usb_device_init(intf, | 1486 | 0 == dvb_usb_device_init(intf, |
| 1483 | &cxusb_bluebird_dualdig4_rev2_properties, | 1487 | &cxusb_bluebird_dualdig4_rev2_properties, |
| 1484 | THIS_MODULE, NULL, adapter_nr) || | 1488 | THIS_MODULE, &d, adapter_nr) || |
| 1485 | 0 == dvb_usb_device_init(intf, &cxusb_d680_dmb_properties, | 1489 | 0 == dvb_usb_device_init(intf, &cxusb_d680_dmb_properties, |
| 1486 | THIS_MODULE, NULL, adapter_nr) || | 1490 | THIS_MODULE, &d, adapter_nr) || |
| 1487 | 0 == dvb_usb_device_init(intf, &cxusb_mygica_d689_properties, | 1491 | 0 == dvb_usb_device_init(intf, &cxusb_mygica_d689_properties, |
| 1488 | THIS_MODULE, NULL, adapter_nr) || | 1492 | THIS_MODULE, &d, adapter_nr) || |
| 1489 | 0 == dvb_usb_device_init(intf, &cxusb_mygica_t230_properties, | 1493 | 0 == dvb_usb_device_init(intf, &cxusb_mygica_t230_properties, |
| 1490 | THIS_MODULE, NULL, adapter_nr) || | 1494 | THIS_MODULE, &d, adapter_nr) || |
| 1491 | 0) | 1495 | 0) { |
| 1496 | st = d->priv; | ||
| 1497 | mutex_init(&st->data_mutex); | ||
| 1498 | |||
| 1492 | return 0; | 1499 | return 0; |
| 1500 | } | ||
| 1493 | 1501 | ||
| 1494 | return -EINVAL; | 1502 | return -EINVAL; |
| 1495 | } | 1503 | } |
diff --git a/drivers/media/usb/dvb-usb/cxusb.h b/drivers/media/usb/dvb-usb/cxusb.h index 527ff7905e15..9f3ee0e47d5c 100644 --- a/drivers/media/usb/dvb-usb/cxusb.h +++ b/drivers/media/usb/dvb-usb/cxusb.h | |||
| @@ -28,10 +28,16 @@ | |||
| 28 | #define CMD_ANALOG 0x50 | 28 | #define CMD_ANALOG 0x50 |
| 29 | #define CMD_DIGITAL 0x51 | 29 | #define CMD_DIGITAL 0x51 |
| 30 | 30 | ||
| 31 | /* Max transfer size done by I2C transfer functions */ | ||
| 32 | #define MAX_XFER_SIZE 80 | ||
| 33 | |||
| 31 | struct cxusb_state { | 34 | struct cxusb_state { |
| 32 | u8 gpio_write_state[3]; | 35 | u8 gpio_write_state[3]; |
| 33 | struct i2c_client *i2c_client_demod; | 36 | struct i2c_client *i2c_client_demod; |
| 34 | struct i2c_client *i2c_client_tuner; | 37 | struct i2c_client *i2c_client_tuner; |
| 38 | |||
| 39 | unsigned char data[MAX_XFER_SIZE]; | ||
| 40 | struct mutex data_mutex; | ||
| 35 | }; | 41 | }; |
| 36 | 42 | ||
| 37 | #endif | 43 | #endif |
diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c index f3196658fb70..92d5408684ac 100644 --- a/drivers/media/usb/dvb-usb/dib0700_core.c +++ b/drivers/media/usb/dvb-usb/dib0700_core.c | |||
| @@ -213,7 +213,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, | |||
| 213 | usb_rcvctrlpipe(d->udev, 0), | 213 | usb_rcvctrlpipe(d->udev, 0), |
| 214 | REQUEST_NEW_I2C_READ, | 214 | REQUEST_NEW_I2C_READ, |
| 215 | USB_TYPE_VENDOR | USB_DIR_IN, | 215 | USB_TYPE_VENDOR | USB_DIR_IN, |
| 216 | value, index, msg[i].buf, | 216 | value, index, st->buf, |
| 217 | msg[i].len, | 217 | msg[i].len, |
| 218 | USB_CTRL_GET_TIMEOUT); | 218 | USB_CTRL_GET_TIMEOUT); |
| 219 | if (result < 0) { | 219 | if (result < 0) { |
| @@ -221,6 +221,14 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, | |||
| 221 | break; | 221 | break; |
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | if (msg[i].len > sizeof(st->buf)) { | ||
| 225 | deb_info("buffer too small to fit %d bytes\n", | ||
| 226 | msg[i].len); | ||
| 227 | return -EIO; | ||
| 228 | } | ||
| 229 | |||
| 230 | memcpy(msg[i].buf, st->buf, msg[i].len); | ||
| 231 | |||
| 224 | deb_data("<<< "); | 232 | deb_data("<<< "); |
| 225 | debug_dump(msg[i].buf, msg[i].len, deb_data); | 233 | debug_dump(msg[i].buf, msg[i].len, deb_data); |
| 226 | 234 | ||
| @@ -238,6 +246,13 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, | |||
| 238 | /* I2C ctrl + FE bus; */ | 246 | /* I2C ctrl + FE bus; */ |
| 239 | st->buf[3] = ((gen_mode << 6) & 0xC0) | | 247 | st->buf[3] = ((gen_mode << 6) & 0xC0) | |
| 240 | ((bus_mode << 4) & 0x30); | 248 | ((bus_mode << 4) & 0x30); |
| 249 | |||
| 250 | if (msg[i].len > sizeof(st->buf) - 4) { | ||
| 251 | deb_info("i2c message to big: %d\n", | ||
| 252 | msg[i].len); | ||
| 253 | return -EIO; | ||
| 254 | } | ||
| 255 | |||
| 241 | /* The Actual i2c payload */ | 256 | /* The Actual i2c payload */ |
| 242 | memcpy(&st->buf[4], msg[i].buf, msg[i].len); | 257 | memcpy(&st->buf[4], msg[i].buf, msg[i].len); |
| 243 | 258 | ||
| @@ -283,6 +298,11 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, | |||
| 283 | /* fill in the address */ | 298 | /* fill in the address */ |
| 284 | st->buf[1] = msg[i].addr << 1; | 299 | st->buf[1] = msg[i].addr << 1; |
| 285 | /* fill the buffer */ | 300 | /* fill the buffer */ |
| 301 | if (msg[i].len > sizeof(st->buf) - 2) { | ||
| 302 | deb_info("i2c xfer to big: %d\n", | ||
| 303 | msg[i].len); | ||
| 304 | return -EIO; | ||
| 305 | } | ||
| 286 | memcpy(&st->buf[2], msg[i].buf, msg[i].len); | 306 | memcpy(&st->buf[2], msg[i].buf, msg[i].len); |
| 287 | 307 | ||
| 288 | /* write/read request */ | 308 | /* write/read request */ |
| @@ -292,13 +312,20 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, | |||
| 292 | 312 | ||
| 293 | /* special thing in the current firmware: when length is zero the read-failed */ | 313 | /* special thing in the current firmware: when length is zero the read-failed */ |
| 294 | len = dib0700_ctrl_rd(d, st->buf, msg[i].len + 2, | 314 | len = dib0700_ctrl_rd(d, st->buf, msg[i].len + 2, |
| 295 | msg[i+1].buf, msg[i+1].len); | 315 | st->buf, msg[i + 1].len); |
| 296 | if (len <= 0) { | 316 | if (len <= 0) { |
| 297 | deb_info("I2C read failed on address 0x%02x\n", | 317 | deb_info("I2C read failed on address 0x%02x\n", |
| 298 | msg[i].addr); | 318 | msg[i].addr); |
| 299 | break; | 319 | break; |
| 300 | } | 320 | } |
| 301 | 321 | ||
| 322 | if (msg[i + 1].len > sizeof(st->buf)) { | ||
| 323 | deb_info("i2c xfer buffer to small for %d\n", | ||
| 324 | msg[i].len); | ||
| 325 | return -EIO; | ||
| 326 | } | ||
| 327 | memcpy(msg[i + 1].buf, st->buf, msg[i + 1].len); | ||
| 328 | |||
| 302 | msg[i+1].len = len; | 329 | msg[i+1].len = len; |
| 303 | 330 | ||
| 304 | i++; | 331 | i++; |
diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c index 0857b56e652c..ef1b8ee75c57 100644 --- a/drivers/media/usb/dvb-usb/dib0700_devices.c +++ b/drivers/media/usb/dvb-usb/dib0700_devices.c | |||
| @@ -508,8 +508,6 @@ static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap) | |||
| 508 | 508 | ||
| 509 | #define DEFAULT_RC_INTERVAL 50 | 509 | #define DEFAULT_RC_INTERVAL 50 |
| 510 | 510 | ||
| 511 | static u8 rc_request[] = { REQUEST_POLL_RC, 0 }; | ||
| 512 | |||
| 513 | /* | 511 | /* |
| 514 | * This function is used only when firmware is < 1.20 version. Newer | 512 | * This function is used only when firmware is < 1.20 version. Newer |
| 515 | * firmwares use bulk mode, with functions implemented at dib0700_core, | 513 | * firmwares use bulk mode, with functions implemented at dib0700_core, |
| @@ -517,7 +515,6 @@ static u8 rc_request[] = { REQUEST_POLL_RC, 0 }; | |||
| 517 | */ | 515 | */ |
| 518 | static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d) | 516 | static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d) |
| 519 | { | 517 | { |
| 520 | u8 key[4]; | ||
| 521 | enum rc_type protocol; | 518 | enum rc_type protocol; |
| 522 | u32 scancode; | 519 | u32 scancode; |
| 523 | u8 toggle; | 520 | u8 toggle; |
| @@ -532,39 +529,43 @@ static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d) | |||
| 532 | return 0; | 529 | return 0; |
| 533 | } | 530 | } |
| 534 | 531 | ||
| 535 | i = dib0700_ctrl_rd(d, rc_request, 2, key, 4); | 532 | st->buf[0] = REQUEST_POLL_RC; |
| 533 | st->buf[1] = 0; | ||
| 534 | |||
| 535 | i = dib0700_ctrl_rd(d, st->buf, 2, st->buf, 4); | ||
| 536 | if (i <= 0) { | 536 | if (i <= 0) { |
| 537 | err("RC Query Failed"); | 537 | err("RC Query Failed"); |
| 538 | return -1; | 538 | return -EIO; |
| 539 | } | 539 | } |
| 540 | 540 | ||
| 541 | /* losing half of KEY_0 events from Philipps rc5 remotes.. */ | 541 | /* losing half of KEY_0 events from Philipps rc5 remotes.. */ |
| 542 | if (key[0] == 0 && key[1] == 0 && key[2] == 0 && key[3] == 0) | 542 | if (st->buf[0] == 0 && st->buf[1] == 0 |
| 543 | && st->buf[2] == 0 && st->buf[3] == 0) | ||
| 543 | return 0; | 544 | return 0; |
| 544 | 545 | ||
| 545 | /* 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]); */ | 546 | /* 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]); */ |
| 546 | 547 | ||
| 547 | dib0700_rc_setup(d, NULL); /* reset ir sensor data to prevent false events */ | 548 | dib0700_rc_setup(d, NULL); /* reset ir sensor data to prevent false events */ |
| 548 | 549 | ||
| 549 | switch (d->props.rc.core.protocol) { | 550 | switch (d->props.rc.core.protocol) { |
| 550 | case RC_BIT_NEC: | 551 | case RC_BIT_NEC: |
| 551 | /* NEC protocol sends repeat code as 0 0 0 FF */ | 552 | /* NEC protocol sends repeat code as 0 0 0 FF */ |
| 552 | if ((key[3-2] == 0x00) && (key[3-3] == 0x00) && | 553 | if ((st->buf[3 - 2] == 0x00) && (st->buf[3 - 3] == 0x00) && |
| 553 | (key[3] == 0xff)) { | 554 | (st->buf[3] == 0xff)) { |
| 554 | rc_repeat(d->rc_dev); | 555 | rc_repeat(d->rc_dev); |
| 555 | return 0; | 556 | return 0; |
| 556 | } | 557 | } |
| 557 | 558 | ||
| 558 | protocol = RC_TYPE_NEC; | 559 | protocol = RC_TYPE_NEC; |
| 559 | scancode = RC_SCANCODE_NEC(key[3-2], key[3-3]); | 560 | scancode = RC_SCANCODE_NEC(st->buf[3 - 2], st->buf[3 - 3]); |
| 560 | toggle = 0; | 561 | toggle = 0; |
| 561 | break; | 562 | break; |
| 562 | 563 | ||
| 563 | default: | 564 | default: |
| 564 | /* RC-5 protocol changes toggle bit on new keypress */ | 565 | /* RC-5 protocol changes toggle bit on new keypress */ |
| 565 | protocol = RC_TYPE_RC5; | 566 | protocol = RC_TYPE_RC5; |
| 566 | scancode = RC_SCANCODE_RC5(key[3-2], key[3-3]); | 567 | scancode = RC_SCANCODE_RC5(st->buf[3 - 2], st->buf[3 - 3]); |
| 567 | toggle = key[3-1]; | 568 | toggle = st->buf[3 - 1]; |
| 568 | break; | 569 | break; |
| 569 | } | 570 | } |
| 570 | 571 | ||
diff --git a/drivers/media/usb/dvb-usb/dibusb-common.c b/drivers/media/usb/dvb-usb/dibusb-common.c index 18ed3bfbb5e2..de3ee2547479 100644 --- a/drivers/media/usb/dvb-usb/dibusb-common.c +++ b/drivers/media/usb/dvb-usb/dibusb-common.c | |||
| @@ -62,72 +62,117 @@ EXPORT_SYMBOL(dibusb_pid_filter_ctrl); | |||
| 62 | 62 | ||
| 63 | int dibusb_power_ctrl(struct dvb_usb_device *d, int onoff) | 63 | int dibusb_power_ctrl(struct dvb_usb_device *d, int onoff) |
| 64 | { | 64 | { |
| 65 | u8 b[3]; | 65 | u8 *b; |
| 66 | int ret; | 66 | int ret; |
| 67 | |||
| 68 | b = kmalloc(3, GFP_KERNEL); | ||
| 69 | if (!b) | ||
| 70 | return -ENOMEM; | ||
| 71 | |||
| 67 | b[0] = DIBUSB_REQ_SET_IOCTL; | 72 | b[0] = DIBUSB_REQ_SET_IOCTL; |
| 68 | b[1] = DIBUSB_IOCTL_CMD_POWER_MODE; | 73 | b[1] = DIBUSB_IOCTL_CMD_POWER_MODE; |
| 69 | b[2] = onoff ? DIBUSB_IOCTL_POWER_WAKEUP : DIBUSB_IOCTL_POWER_SLEEP; | 74 | b[2] = onoff ? DIBUSB_IOCTL_POWER_WAKEUP : DIBUSB_IOCTL_POWER_SLEEP; |
| 70 | ret = dvb_usb_generic_write(d,b,3); | 75 | |
| 76 | ret = dvb_usb_generic_write(d, b, 3); | ||
| 77 | |||
| 78 | kfree(b); | ||
| 79 | |||
| 71 | msleep(10); | 80 | msleep(10); |
| 81 | |||
| 72 | return ret; | 82 | return ret; |
| 73 | } | 83 | } |
| 74 | EXPORT_SYMBOL(dibusb_power_ctrl); | 84 | EXPORT_SYMBOL(dibusb_power_ctrl); |
| 75 | 85 | ||
| 76 | int dibusb2_0_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | 86 | int dibusb2_0_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) |
| 77 | { | 87 | { |
| 78 | u8 b[3] = { 0 }; | ||
| 79 | int ret; | 88 | int ret; |
| 89 | u8 *b; | ||
| 90 | |||
| 91 | b = kmalloc(3, GFP_KERNEL); | ||
| 92 | if (!b) | ||
| 93 | return -ENOMEM; | ||
| 80 | 94 | ||
| 81 | if ((ret = dibusb_streaming_ctrl(adap,onoff)) < 0) | 95 | if ((ret = dibusb_streaming_ctrl(adap,onoff)) < 0) |
| 82 | return ret; | 96 | goto ret; |
| 83 | 97 | ||
| 84 | if (onoff) { | 98 | if (onoff) { |
| 85 | b[0] = DIBUSB_REQ_SET_STREAMING_MODE; | 99 | b[0] = DIBUSB_REQ_SET_STREAMING_MODE; |
| 86 | b[1] = 0x00; | 100 | b[1] = 0x00; |
| 87 | if ((ret = dvb_usb_generic_write(adap->dev,b,2)) < 0) | 101 | ret = dvb_usb_generic_write(adap->dev, b, 2); |
| 88 | return ret; | 102 | if (ret < 0) |
| 103 | goto ret; | ||
| 89 | } | 104 | } |
| 90 | 105 | ||
| 91 | b[0] = DIBUSB_REQ_SET_IOCTL; | 106 | b[0] = DIBUSB_REQ_SET_IOCTL; |
| 92 | b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM; | 107 | b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM; |
| 93 | return dvb_usb_generic_write(adap->dev,b,3); | 108 | ret = dvb_usb_generic_write(adap->dev, b, 3); |
| 109 | |||
| 110 | ret: | ||
| 111 | kfree(b); | ||
| 112 | return ret; | ||
| 94 | } | 113 | } |
| 95 | EXPORT_SYMBOL(dibusb2_0_streaming_ctrl); | 114 | EXPORT_SYMBOL(dibusb2_0_streaming_ctrl); |
| 96 | 115 | ||
| 97 | int dibusb2_0_power_ctrl(struct dvb_usb_device *d, int onoff) | 116 | int dibusb2_0_power_ctrl(struct dvb_usb_device *d, int onoff) |
| 98 | { | 117 | { |
| 99 | if (onoff) { | 118 | u8 *b; |
| 100 | u8 b[3] = { DIBUSB_REQ_SET_IOCTL, DIBUSB_IOCTL_CMD_POWER_MODE, DIBUSB_IOCTL_POWER_WAKEUP }; | 119 | int ret; |
| 101 | return dvb_usb_generic_write(d,b,3); | 120 | |
| 102 | } else | 121 | if (!onoff) |
| 103 | return 0; | 122 | return 0; |
| 123 | |||
| 124 | b = kmalloc(3, GFP_KERNEL); | ||
| 125 | if (!b) | ||
| 126 | return -ENOMEM; | ||
| 127 | |||
| 128 | b[0] = DIBUSB_REQ_SET_IOCTL; | ||
| 129 | b[1] = DIBUSB_IOCTL_CMD_POWER_MODE; | ||
| 130 | b[2] = DIBUSB_IOCTL_POWER_WAKEUP; | ||
| 131 | |||
| 132 | ret = dvb_usb_generic_write(d, b, 3); | ||
| 133 | |||
| 134 | kfree(b); | ||
| 135 | |||
| 136 | return ret; | ||
| 104 | } | 137 | } |
| 105 | EXPORT_SYMBOL(dibusb2_0_power_ctrl); | 138 | EXPORT_SYMBOL(dibusb2_0_power_ctrl); |
| 106 | 139 | ||
| 107 | static int dibusb_i2c_msg(struct dvb_usb_device *d, u8 addr, | 140 | static int dibusb_i2c_msg(struct dvb_usb_device *d, u8 addr, |
| 108 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) | 141 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) |
| 109 | { | 142 | { |
| 110 | u8 sndbuf[MAX_XFER_SIZE]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */ | 143 | u8 *sndbuf; |
| 144 | int ret, wo, len; | ||
| 145 | |||
| 111 | /* write only ? */ | 146 | /* write only ? */ |
| 112 | int wo = (rbuf == NULL || rlen == 0), | 147 | wo = (rbuf == NULL || rlen == 0); |
| 113 | len = 2 + wlen + (wo ? 0 : 2); | 148 | |
| 149 | len = 2 + wlen + (wo ? 0 : 2); | ||
| 150 | |||
| 151 | sndbuf = kmalloc(MAX_XFER_SIZE, GFP_KERNEL); | ||
| 152 | if (!sndbuf) | ||
| 153 | return -ENOMEM; | ||
| 114 | 154 | ||
| 115 | if (4 + wlen > sizeof(sndbuf)) { | 155 | if (4 + wlen > MAX_XFER_SIZE) { |
| 116 | warn("i2c wr: len=%d is too big!\n", wlen); | 156 | warn("i2c wr: len=%d is too big!\n", wlen); |
| 117 | return -EOPNOTSUPP; | 157 | ret = -EOPNOTSUPP; |
| 158 | goto ret; | ||
| 118 | } | 159 | } |
| 119 | 160 | ||
| 120 | sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ; | 161 | sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ; |
| 121 | sndbuf[1] = (addr << 1) | (wo ? 0 : 1); | 162 | sndbuf[1] = (addr << 1) | (wo ? 0 : 1); |
| 122 | 163 | ||
| 123 | memcpy(&sndbuf[2],wbuf,wlen); | 164 | memcpy(&sndbuf[2], wbuf, wlen); |
| 124 | 165 | ||
| 125 | if (!wo) { | 166 | if (!wo) { |
| 126 | sndbuf[wlen+2] = (rlen >> 8) & 0xff; | 167 | sndbuf[wlen + 2] = (rlen >> 8) & 0xff; |
| 127 | sndbuf[wlen+3] = rlen & 0xff; | 168 | sndbuf[wlen + 3] = rlen & 0xff; |
| 128 | } | 169 | } |
| 129 | 170 | ||
| 130 | return dvb_usb_generic_rw(d,sndbuf,len,rbuf,rlen,0); | 171 | ret = dvb_usb_generic_rw(d, sndbuf, len, rbuf, rlen, 0); |
| 172 | |||
| 173 | ret: | ||
| 174 | kfree(sndbuf); | ||
| 175 | return ret; | ||
| 131 | } | 176 | } |
| 132 | 177 | ||
| 133 | /* | 178 | /* |
| @@ -319,11 +364,27 @@ EXPORT_SYMBOL(rc_map_dibusb_table); | |||
| 319 | 364 | ||
| 320 | int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | 365 | int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) |
| 321 | { | 366 | { |
| 322 | u8 key[5],cmd = DIBUSB_REQ_POLL_REMOTE; | 367 | u8 *buf; |
| 323 | dvb_usb_generic_rw(d,&cmd,1,key,5,0); | 368 | int ret; |
| 324 | dvb_usb_nec_rc_key_to_event(d,key,event,state); | 369 | |
| 325 | if (key[0] != 0) | 370 | buf = kmalloc(5, GFP_KERNEL); |
| 326 | deb_info("key: %*ph\n", 5, key); | 371 | if (!buf) |
| 327 | return 0; | 372 | return -ENOMEM; |
| 373 | |||
| 374 | buf[0] = DIBUSB_REQ_POLL_REMOTE; | ||
| 375 | |||
| 376 | ret = dvb_usb_generic_rw(d, buf, 1, buf, 5, 0); | ||
| 377 | if (ret < 0) | ||
| 378 | goto ret; | ||
| 379 | |||
| 380 | dvb_usb_nec_rc_key_to_event(d, buf, event, state); | ||
| 381 | |||
| 382 | if (buf[0] != 0) | ||
| 383 | deb_info("key: %*ph\n", 5, buf); | ||
| 384 | |||
| 385 | kfree(buf); | ||
| 386 | |||
| 387 | ret: | ||
| 388 | return ret; | ||
| 328 | } | 389 | } |
| 329 | EXPORT_SYMBOL(dibusb_rc_query); | 390 | EXPORT_SYMBOL(dibusb_rc_query); |
diff --git a/drivers/media/usb/dvb-usb/dibusb.h b/drivers/media/usb/dvb-usb/dibusb.h index 3f82163d8ab8..697be2a17ade 100644 --- a/drivers/media/usb/dvb-usb/dibusb.h +++ b/drivers/media/usb/dvb-usb/dibusb.h | |||
| @@ -96,6 +96,9 @@ | |||
| 96 | #define DIBUSB_IOCTL_CMD_ENABLE_STREAM 0x01 | 96 | #define DIBUSB_IOCTL_CMD_ENABLE_STREAM 0x01 |
| 97 | #define DIBUSB_IOCTL_CMD_DISABLE_STREAM 0x02 | 97 | #define DIBUSB_IOCTL_CMD_DISABLE_STREAM 0x02 |
| 98 | 98 | ||
| 99 | /* Max transfer size done by I2C transfer functions */ | ||
| 100 | #define MAX_XFER_SIZE 64 | ||
| 101 | |||
| 99 | struct dibusb_state { | 102 | struct dibusb_state { |
| 100 | struct dib_fe_xfer_ops ops; | 103 | struct dib_fe_xfer_ops ops; |
| 101 | int mt2060_present; | 104 | int mt2060_present; |
diff --git a/drivers/media/usb/dvb-usb/digitv.c b/drivers/media/usb/dvb-usb/digitv.c index 63134335c994..4284f6984dc1 100644 --- a/drivers/media/usb/dvb-usb/digitv.c +++ b/drivers/media/usb/dvb-usb/digitv.c | |||
| @@ -28,22 +28,26 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | |||
| 28 | static int digitv_ctrl_msg(struct dvb_usb_device *d, | 28 | static int digitv_ctrl_msg(struct dvb_usb_device *d, |
| 29 | u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen) | 29 | u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen) |
| 30 | { | 30 | { |
| 31 | int wo = (rbuf == NULL || rlen == 0); /* write-only */ | 31 | struct digitv_state *st = d->priv; |
| 32 | u8 sndbuf[7],rcvbuf[7]; | 32 | int ret, wo; |
| 33 | memset(sndbuf,0,7); memset(rcvbuf,0,7); | ||
| 34 | 33 | ||
| 35 | sndbuf[0] = cmd; | 34 | wo = (rbuf == NULL || rlen == 0); /* write-only */ |
| 36 | sndbuf[1] = vv; | 35 | |
| 37 | sndbuf[2] = wo ? wlen : rlen; | 36 | memset(st->sndbuf, 0, 7); |
| 37 | memset(st->rcvbuf, 0, 7); | ||
| 38 | |||
| 39 | st->sndbuf[0] = cmd; | ||
| 40 | st->sndbuf[1] = vv; | ||
| 41 | st->sndbuf[2] = wo ? wlen : rlen; | ||
| 38 | 42 | ||
| 39 | if (wo) { | 43 | if (wo) { |
| 40 | memcpy(&sndbuf[3],wbuf,wlen); | 44 | memcpy(&st->sndbuf[3], wbuf, wlen); |
| 41 | dvb_usb_generic_write(d,sndbuf,7); | 45 | ret = dvb_usb_generic_write(d, st->sndbuf, 7); |
| 42 | } else { | 46 | } else { |
| 43 | dvb_usb_generic_rw(d,sndbuf,7,rcvbuf,7,10); | 47 | ret = dvb_usb_generic_rw(d, st->sndbuf, 7, st->rcvbuf, 7, 10); |
| 44 | memcpy(rbuf,&rcvbuf[3],rlen); | 48 | memcpy(rbuf, &st->rcvbuf[3], rlen); |
| 45 | } | 49 | } |
| 46 | return 0; | 50 | return ret; |
| 47 | } | 51 | } |
| 48 | 52 | ||
| 49 | /* I2C */ | 53 | /* I2C */ |
diff --git a/drivers/media/usb/dvb-usb/digitv.h b/drivers/media/usb/dvb-usb/digitv.h index 908c09f4966b..581e09c25491 100644 --- a/drivers/media/usb/dvb-usb/digitv.h +++ b/drivers/media/usb/dvb-usb/digitv.h | |||
| @@ -5,7 +5,10 @@ | |||
| 5 | #include "dvb-usb.h" | 5 | #include "dvb-usb.h" |
| 6 | 6 | ||
| 7 | struct digitv_state { | 7 | struct digitv_state { |
| 8 | int is_nxt6000; | 8 | int is_nxt6000; |
| 9 | |||
| 10 | unsigned char sndbuf[7]; | ||
| 11 | unsigned char rcvbuf[7]; | ||
| 9 | }; | 12 | }; |
| 10 | 13 | ||
| 11 | /* protocol (from usblogging and the SDK: | 14 | /* protocol (from usblogging and the SDK: |
diff --git a/drivers/media/usb/dvb-usb/dtt200u-fe.c b/drivers/media/usb/dvb-usb/dtt200u-fe.c index c09332bd99cb..f5c042baa254 100644 --- a/drivers/media/usb/dvb-usb/dtt200u-fe.c +++ b/drivers/media/usb/dvb-usb/dtt200u-fe.c | |||
| @@ -18,17 +18,28 @@ struct dtt200u_fe_state { | |||
| 18 | 18 | ||
| 19 | struct dtv_frontend_properties fep; | 19 | struct dtv_frontend_properties fep; |
| 20 | struct dvb_frontend frontend; | 20 | struct dvb_frontend frontend; |
| 21 | |||
| 22 | unsigned char data[80]; | ||
| 23 | struct mutex data_mutex; | ||
| 21 | }; | 24 | }; |
| 22 | 25 | ||
| 23 | static int dtt200u_fe_read_status(struct dvb_frontend *fe, | 26 | static int dtt200u_fe_read_status(struct dvb_frontend *fe, |
| 24 | enum fe_status *stat) | 27 | enum fe_status *stat) |
| 25 | { | 28 | { |
| 26 | struct dtt200u_fe_state *state = fe->demodulator_priv; | 29 | struct dtt200u_fe_state *state = fe->demodulator_priv; |
| 27 | u8 st = GET_TUNE_STATUS, b[3]; | 30 | int ret; |
| 31 | |||
| 32 | mutex_lock(&state->data_mutex); | ||
| 33 | state->data[0] = GET_TUNE_STATUS; | ||
| 28 | 34 | ||
| 29 | dvb_usb_generic_rw(state->d,&st,1,b,3,0); | 35 | ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 3, 0); |
| 36 | if (ret < 0) { | ||
| 37 | *stat = 0; | ||
| 38 | mutex_unlock(&state->data_mutex); | ||
| 39 | return ret; | ||
| 40 | } | ||
| 30 | 41 | ||
| 31 | switch (b[0]) { | 42 | switch (state->data[0]) { |
| 32 | case 0x01: | 43 | case 0x01: |
| 33 | *stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | | 44 | *stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | |
| 34 | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; | 45 | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; |
| @@ -41,51 +52,86 @@ static int dtt200u_fe_read_status(struct dvb_frontend *fe, | |||
| 41 | *stat = 0; | 52 | *stat = 0; |
| 42 | break; | 53 | break; |
| 43 | } | 54 | } |
| 55 | mutex_unlock(&state->data_mutex); | ||
| 44 | return 0; | 56 | return 0; |
| 45 | } | 57 | } |
| 46 | 58 | ||
| 47 | static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber) | 59 | static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber) |
| 48 | { | 60 | { |
| 49 | struct dtt200u_fe_state *state = fe->demodulator_priv; | 61 | struct dtt200u_fe_state *state = fe->demodulator_priv; |
| 50 | u8 bw = GET_VIT_ERR_CNT,b[3]; | 62 | int ret; |
| 51 | dvb_usb_generic_rw(state->d,&bw,1,b,3,0); | 63 | |
| 52 | *ber = (b[0] << 16) | (b[1] << 8) | b[2]; | 64 | mutex_lock(&state->data_mutex); |
| 53 | return 0; | 65 | state->data[0] = GET_VIT_ERR_CNT; |
| 66 | |||
| 67 | ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 3, 0); | ||
| 68 | if (ret >= 0) | ||
| 69 | *ber = (state->data[0] << 16) | (state->data[1] << 8) | state->data[2]; | ||
| 70 | |||
| 71 | mutex_unlock(&state->data_mutex); | ||
| 72 | return ret; | ||
| 54 | } | 73 | } |
| 55 | 74 | ||
| 56 | static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) | 75 | static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) |
| 57 | { | 76 | { |
| 58 | struct dtt200u_fe_state *state = fe->demodulator_priv; | 77 | struct dtt200u_fe_state *state = fe->demodulator_priv; |
| 59 | u8 bw = GET_RS_UNCOR_BLK_CNT,b[2]; | 78 | int ret; |
| 60 | 79 | ||
| 61 | dvb_usb_generic_rw(state->d,&bw,1,b,2,0); | 80 | mutex_lock(&state->data_mutex); |
| 62 | *unc = (b[0] << 8) | b[1]; | 81 | state->data[0] = GET_RS_UNCOR_BLK_CNT; |
| 63 | return 0; | 82 | |
| 83 | ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 2, 0); | ||
| 84 | if (ret >= 0) | ||
| 85 | *unc = (state->data[0] << 8) | state->data[1]; | ||
| 86 | |||
| 87 | mutex_unlock(&state->data_mutex); | ||
| 88 | return ret; | ||
| 64 | } | 89 | } |
| 65 | 90 | ||
| 66 | static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength) | 91 | static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength) |
| 67 | { | 92 | { |
| 68 | struct dtt200u_fe_state *state = fe->demodulator_priv; | 93 | struct dtt200u_fe_state *state = fe->demodulator_priv; |
| 69 | u8 bw = GET_AGC, b; | 94 | int ret; |
| 70 | dvb_usb_generic_rw(state->d,&bw,1,&b,1,0); | 95 | |
| 71 | *strength = (b << 8) | b; | 96 | mutex_lock(&state->data_mutex); |
| 72 | return 0; | 97 | state->data[0] = GET_AGC; |
| 98 | |||
| 99 | ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 1, 0); | ||
| 100 | if (ret >= 0) | ||
| 101 | *strength = (state->data[0] << 8) | state->data[0]; | ||
| 102 | |||
| 103 | mutex_unlock(&state->data_mutex); | ||
| 104 | return ret; | ||
| 73 | } | 105 | } |
| 74 | 106 | ||
| 75 | static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr) | 107 | static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr) |
| 76 | { | 108 | { |
| 77 | struct dtt200u_fe_state *state = fe->demodulator_priv; | 109 | struct dtt200u_fe_state *state = fe->demodulator_priv; |
| 78 | u8 bw = GET_SNR,br; | 110 | int ret; |
| 79 | dvb_usb_generic_rw(state->d,&bw,1,&br,1,0); | 111 | |
| 80 | *snr = ~((br << 8) | br); | 112 | mutex_lock(&state->data_mutex); |
| 81 | return 0; | 113 | state->data[0] = GET_SNR; |
| 114 | |||
| 115 | ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 1, 0); | ||
| 116 | if (ret >= 0) | ||
| 117 | *snr = ~((state->data[0] << 8) | state->data[0]); | ||
| 118 | |||
| 119 | mutex_unlock(&state->data_mutex); | ||
| 120 | return ret; | ||
| 82 | } | 121 | } |
| 83 | 122 | ||
| 84 | static int dtt200u_fe_init(struct dvb_frontend* fe) | 123 | static int dtt200u_fe_init(struct dvb_frontend* fe) |
| 85 | { | 124 | { |
| 86 | struct dtt200u_fe_state *state = fe->demodulator_priv; | 125 | struct dtt200u_fe_state *state = fe->demodulator_priv; |
| 87 | u8 b = SET_INIT; | 126 | int ret; |
| 88 | return dvb_usb_generic_write(state->d,&b,1); | 127 | |
| 128 | mutex_lock(&state->data_mutex); | ||
| 129 | state->data[0] = SET_INIT; | ||
| 130 | |||
| 131 | ret = dvb_usb_generic_write(state->d, state->data, 1); | ||
| 132 | mutex_unlock(&state->data_mutex); | ||
| 133 | |||
| 134 | return ret; | ||
| 89 | } | 135 | } |
| 90 | 136 | ||
| 91 | static int dtt200u_fe_sleep(struct dvb_frontend* fe) | 137 | static int dtt200u_fe_sleep(struct dvb_frontend* fe) |
| @@ -105,39 +151,40 @@ static int dtt200u_fe_set_frontend(struct dvb_frontend *fe) | |||
| 105 | { | 151 | { |
| 106 | struct dtv_frontend_properties *fep = &fe->dtv_property_cache; | 152 | struct dtv_frontend_properties *fep = &fe->dtv_property_cache; |
| 107 | struct dtt200u_fe_state *state = fe->demodulator_priv; | 153 | struct dtt200u_fe_state *state = fe->demodulator_priv; |
| 108 | int i; | 154 | int ret; |
| 109 | enum fe_status st; | ||
| 110 | u16 freq = fep->frequency / 250000; | 155 | u16 freq = fep->frequency / 250000; |
| 111 | u8 bwbuf[2] = { SET_BANDWIDTH, 0 },freqbuf[3] = { SET_RF_FREQ, 0, 0 }; | ||
| 112 | 156 | ||
| 157 | mutex_lock(&state->data_mutex); | ||
| 158 | state->data[0] = SET_BANDWIDTH; | ||
| 113 | switch (fep->bandwidth_hz) { | 159 | switch (fep->bandwidth_hz) { |
| 114 | case 8000000: | 160 | case 8000000: |
| 115 | bwbuf[1] = 8; | 161 | state->data[1] = 8; |
| 116 | break; | 162 | break; |
| 117 | case 7000000: | 163 | case 7000000: |
| 118 | bwbuf[1] = 7; | 164 | state->data[1] = 7; |
| 119 | break; | 165 | break; |
| 120 | case 6000000: | 166 | case 6000000: |
| 121 | bwbuf[1] = 6; | 167 | state->data[1] = 6; |
| 122 | break; | 168 | break; |
| 123 | default: | 169 | default: |
| 124 | return -EINVAL; | 170 | ret = -EINVAL; |
| 171 | goto ret; | ||
| 125 | } | 172 | } |
| 126 | 173 | ||
| 127 | dvb_usb_generic_write(state->d,bwbuf,2); | 174 | ret = dvb_usb_generic_write(state->d, state->data, 2); |
| 175 | if (ret < 0) | ||
| 176 | goto ret; | ||
| 128 | 177 | ||
| 129 | freqbuf[1] = freq & 0xff; | 178 | state->data[0] = SET_RF_FREQ; |
| 130 | freqbuf[2] = (freq >> 8) & 0xff; | 179 | state->data[1] = freq & 0xff; |
| 131 | dvb_usb_generic_write(state->d,freqbuf,3); | 180 | state->data[2] = (freq >> 8) & 0xff; |
| 181 | ret = dvb_usb_generic_write(state->d, state->data, 3); | ||
| 182 | if (ret < 0) | ||
| 183 | goto ret; | ||
| 132 | 184 | ||
| 133 | for (i = 0; i < 30; i++) { | 185 | ret: |
| 134 | msleep(20); | 186 | mutex_unlock(&state->data_mutex); |
| 135 | dtt200u_fe_read_status(fe, &st); | 187 | return ret; |
| 136 | if (st & FE_TIMEDOUT) | ||
| 137 | continue; | ||
| 138 | } | ||
| 139 | |||
| 140 | return 0; | ||
| 141 | } | 188 | } |
| 142 | 189 | ||
| 143 | static int dtt200u_fe_get_frontend(struct dvb_frontend* fe, | 190 | 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 | deb_info("attaching frontend dtt200u\n"); | 216 | deb_info("attaching frontend dtt200u\n"); |
| 170 | 217 | ||
| 171 | state->d = d; | 218 | state->d = d; |
| 219 | mutex_init(&state->data_mutex); | ||
| 172 | 220 | ||
| 173 | memcpy(&state->frontend.ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops)); | 221 | memcpy(&state->frontend.ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops)); |
| 174 | state->frontend.demodulator_priv = state; | 222 | state->frontend.demodulator_priv = state; |
diff --git a/drivers/media/usb/dvb-usb/dtt200u.c b/drivers/media/usb/dvb-usb/dtt200u.c index d2a01b50af0d..f88572c7ae7c 100644 --- a/drivers/media/usb/dvb-usb/dtt200u.c +++ b/drivers/media/usb/dvb-usb/dtt200u.c | |||
| @@ -20,75 +20,114 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB | |||
| 20 | 20 | ||
| 21 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 21 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
| 22 | 22 | ||
| 23 | struct dtt200u_state { | ||
| 24 | unsigned char data[80]; | ||
| 25 | struct mutex data_mutex; | ||
| 26 | }; | ||
| 27 | |||
| 23 | static int dtt200u_power_ctrl(struct dvb_usb_device *d, int onoff) | 28 | static int dtt200u_power_ctrl(struct dvb_usb_device *d, int onoff) |
| 24 | { | 29 | { |
| 25 | u8 b = SET_INIT; | 30 | struct dtt200u_state *st = d->priv; |
| 31 | int ret = 0; | ||
| 32 | |||
| 33 | mutex_lock(&st->data_mutex); | ||
| 34 | |||
| 35 | st->data[0] = SET_INIT; | ||
| 26 | 36 | ||
| 27 | if (onoff) | 37 | if (onoff) |
| 28 | dvb_usb_generic_write(d,&b,2); | 38 | ret = dvb_usb_generic_write(d, st->data, 2); |
| 29 | 39 | ||
| 30 | return 0; | 40 | mutex_unlock(&st->data_mutex); |
| 41 | return ret; | ||
| 31 | } | 42 | } |
| 32 | 43 | ||
| 33 | static int dtt200u_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | 44 | static int dtt200u_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) |
| 34 | { | 45 | { |
| 35 | u8 b_streaming[2] = { SET_STREAMING, onoff }; | 46 | struct dtt200u_state *st = adap->dev->priv; |
| 36 | u8 b_rst_pid = RESET_PID_FILTER; | 47 | int ret; |
| 37 | 48 | ||
| 38 | dvb_usb_generic_write(adap->dev, b_streaming, 2); | 49 | mutex_lock(&st->data_mutex); |
| 50 | st->data[0] = SET_STREAMING; | ||
| 51 | st->data[1] = onoff; | ||
| 39 | 52 | ||
| 40 | if (onoff == 0) | 53 | ret = dvb_usb_generic_write(adap->dev, st->data, 2); |
| 41 | dvb_usb_generic_write(adap->dev, &b_rst_pid, 1); | 54 | if (ret < 0) |
| 42 | return 0; | 55 | goto ret; |
| 56 | |||
| 57 | if (onoff) | ||
| 58 | goto ret; | ||
| 59 | |||
| 60 | st->data[0] = RESET_PID_FILTER; | ||
| 61 | ret = dvb_usb_generic_write(adap->dev, st->data, 1); | ||
| 62 | |||
| 63 | ret: | ||
| 64 | mutex_unlock(&st->data_mutex); | ||
| 65 | |||
| 66 | return ret; | ||
| 43 | } | 67 | } |
| 44 | 68 | ||
| 45 | static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) | 69 | static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff) |
| 46 | { | 70 | { |
| 47 | u8 b_pid[4]; | 71 | struct dtt200u_state *st = adap->dev->priv; |
| 72 | int ret; | ||
| 73 | |||
| 48 | pid = onoff ? pid : 0; | 74 | pid = onoff ? pid : 0; |
| 49 | 75 | ||
| 50 | b_pid[0] = SET_PID_FILTER; | 76 | mutex_lock(&st->data_mutex); |
| 51 | b_pid[1] = index; | 77 | st->data[0] = SET_PID_FILTER; |
| 52 | b_pid[2] = pid & 0xff; | 78 | st->data[1] = index; |
| 53 | b_pid[3] = (pid >> 8) & 0x1f; | 79 | st->data[2] = pid & 0xff; |
| 80 | st->data[3] = (pid >> 8) & 0x1f; | ||
| 54 | 81 | ||
| 55 | return dvb_usb_generic_write(adap->dev, b_pid, 4); | 82 | ret = dvb_usb_generic_write(adap->dev, st->data, 4); |
| 83 | mutex_unlock(&st->data_mutex); | ||
| 84 | |||
| 85 | return ret; | ||
| 56 | } | 86 | } |
| 57 | 87 | ||
| 58 | static int dtt200u_rc_query(struct dvb_usb_device *d) | 88 | static int dtt200u_rc_query(struct dvb_usb_device *d) |
| 59 | { | 89 | { |
| 60 | u8 key[5],cmd = GET_RC_CODE; | 90 | struct dtt200u_state *st = d->priv; |
| 61 | u32 scancode; | 91 | u32 scancode; |
| 92 | int ret; | ||
| 93 | |||
| 94 | mutex_lock(&st->data_mutex); | ||
| 95 | st->data[0] = GET_RC_CODE; | ||
| 96 | |||
| 97 | ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 5, 0); | ||
| 98 | if (ret < 0) | ||
| 99 | goto ret; | ||
| 62 | 100 | ||
| 63 | dvb_usb_generic_rw(d,&cmd,1,key,5,0); | 101 | if (st->data[0] == 1) { |
| 64 | if (key[0] == 1) { | ||
| 65 | enum rc_type proto = RC_TYPE_NEC; | 102 | enum rc_type proto = RC_TYPE_NEC; |
| 66 | 103 | ||
| 67 | scancode = key[1]; | 104 | scancode = st->data[1]; |
| 68 | if ((u8) ~key[1] != key[2]) { | 105 | if ((u8) ~st->data[1] != st->data[2]) { |
| 69 | /* Extended NEC */ | 106 | /* Extended NEC */ |
| 70 | scancode = scancode << 8; | 107 | scancode = scancode << 8; |
| 71 | scancode |= key[2]; | 108 | scancode |= st->data[2]; |
| 72 | proto = RC_TYPE_NECX; | 109 | proto = RC_TYPE_NECX; |
| 73 | } | 110 | } |
| 74 | scancode = scancode << 8; | 111 | scancode = scancode << 8; |
| 75 | scancode |= key[3]; | 112 | scancode |= st->data[3]; |
| 76 | 113 | ||
| 77 | /* Check command checksum is ok */ | 114 | /* Check command checksum is ok */ |
| 78 | if ((u8) ~key[3] == key[4]) | 115 | if ((u8) ~st->data[3] == st->data[4]) |
| 79 | rc_keydown(d->rc_dev, proto, scancode, 0); | 116 | rc_keydown(d->rc_dev, proto, scancode, 0); |
| 80 | else | 117 | else |
| 81 | rc_keyup(d->rc_dev); | 118 | rc_keyup(d->rc_dev); |
| 82 | } else if (key[0] == 2) { | 119 | } else if (st->data[0] == 2) { |
| 83 | rc_repeat(d->rc_dev); | 120 | rc_repeat(d->rc_dev); |
| 84 | } else { | 121 | } else { |
| 85 | rc_keyup(d->rc_dev); | 122 | rc_keyup(d->rc_dev); |
| 86 | } | 123 | } |
| 87 | 124 | ||
| 88 | if (key[0] != 0) | 125 | if (st->data[0] != 0) |
| 89 | deb_info("key: %*ph\n", 5, key); | 126 | deb_info("st->data: %*ph\n", 5, st->data); |
| 90 | 127 | ||
| 91 | return 0; | 128 | ret: |
| 129 | mutex_unlock(&st->data_mutex); | ||
| 130 | return ret; | ||
| 92 | } | 131 | } |
| 93 | 132 | ||
| 94 | static int dtt200u_frontend_attach(struct dvb_usb_adapter *adap) | 133 | static int dtt200u_frontend_attach(struct dvb_usb_adapter *adap) |
| @@ -106,17 +145,24 @@ static struct dvb_usb_device_properties wt220u_miglia_properties; | |||
| 106 | static int dtt200u_usb_probe(struct usb_interface *intf, | 145 | static int dtt200u_usb_probe(struct usb_interface *intf, |
| 107 | const struct usb_device_id *id) | 146 | const struct usb_device_id *id) |
| 108 | { | 147 | { |
| 148 | struct dvb_usb_device *d; | ||
| 149 | struct dtt200u_state *st; | ||
| 150 | |||
| 109 | if (0 == dvb_usb_device_init(intf, &dtt200u_properties, | 151 | if (0 == dvb_usb_device_init(intf, &dtt200u_properties, |
| 110 | THIS_MODULE, NULL, adapter_nr) || | 152 | THIS_MODULE, &d, adapter_nr) || |
| 111 | 0 == dvb_usb_device_init(intf, &wt220u_properties, | 153 | 0 == dvb_usb_device_init(intf, &wt220u_properties, |
| 112 | THIS_MODULE, NULL, adapter_nr) || | 154 | THIS_MODULE, &d, adapter_nr) || |
| 113 | 0 == dvb_usb_device_init(intf, &wt220u_fc_properties, | 155 | 0 == dvb_usb_device_init(intf, &wt220u_fc_properties, |
| 114 | THIS_MODULE, NULL, adapter_nr) || | 156 | THIS_MODULE, &d, adapter_nr) || |
| 115 | 0 == dvb_usb_device_init(intf, &wt220u_zl0353_properties, | 157 | 0 == dvb_usb_device_init(intf, &wt220u_zl0353_properties, |
| 116 | THIS_MODULE, NULL, adapter_nr) || | 158 | THIS_MODULE, &d, adapter_nr) || |
| 117 | 0 == dvb_usb_device_init(intf, &wt220u_miglia_properties, | 159 | 0 == dvb_usb_device_init(intf, &wt220u_miglia_properties, |
| 118 | THIS_MODULE, NULL, adapter_nr)) | 160 | THIS_MODULE, &d, adapter_nr)) { |
| 161 | st = d->priv; | ||
| 162 | mutex_init(&st->data_mutex); | ||
| 163 | |||
| 119 | return 0; | 164 | return 0; |
| 165 | } | ||
| 120 | 166 | ||
| 121 | return -ENODEV; | 167 | return -ENODEV; |
| 122 | } | 168 | } |
| @@ -140,6 +186,8 @@ static struct dvb_usb_device_properties dtt200u_properties = { | |||
| 140 | .usb_ctrl = CYPRESS_FX2, | 186 | .usb_ctrl = CYPRESS_FX2, |
| 141 | .firmware = "dvb-usb-dtt200u-01.fw", | 187 | .firmware = "dvb-usb-dtt200u-01.fw", |
| 142 | 188 | ||
| 189 | .size_of_priv = sizeof(struct dtt200u_state), | ||
| 190 | |||
| 143 | .num_adapters = 1, | 191 | .num_adapters = 1, |
| 144 | .adapter = { | 192 | .adapter = { |
| 145 | { | 193 | { |
| @@ -190,6 +238,8 @@ static struct dvb_usb_device_properties wt220u_properties = { | |||
| 190 | .usb_ctrl = CYPRESS_FX2, | 238 | .usb_ctrl = CYPRESS_FX2, |
| 191 | .firmware = "dvb-usb-wt220u-02.fw", | 239 | .firmware = "dvb-usb-wt220u-02.fw", |
| 192 | 240 | ||
| 241 | .size_of_priv = sizeof(struct dtt200u_state), | ||
| 242 | |||
| 193 | .num_adapters = 1, | 243 | .num_adapters = 1, |
| 194 | .adapter = { | 244 | .adapter = { |
| 195 | { | 245 | { |
| @@ -240,6 +290,8 @@ static struct dvb_usb_device_properties wt220u_fc_properties = { | |||
| 240 | .usb_ctrl = CYPRESS_FX2, | 290 | .usb_ctrl = CYPRESS_FX2, |
| 241 | .firmware = "dvb-usb-wt220u-fc03.fw", | 291 | .firmware = "dvb-usb-wt220u-fc03.fw", |
| 242 | 292 | ||
| 293 | .size_of_priv = sizeof(struct dtt200u_state), | ||
| 294 | |||
| 243 | .num_adapters = 1, | 295 | .num_adapters = 1, |
| 244 | .adapter = { | 296 | .adapter = { |
| 245 | { | 297 | { |
| @@ -290,6 +342,8 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = { | |||
| 290 | .usb_ctrl = CYPRESS_FX2, | 342 | .usb_ctrl = CYPRESS_FX2, |
| 291 | .firmware = "dvb-usb-wt220u-zl0353-01.fw", | 343 | .firmware = "dvb-usb-wt220u-zl0353-01.fw", |
| 292 | 344 | ||
| 345 | .size_of_priv = sizeof(struct dtt200u_state), | ||
| 346 | |||
| 293 | .num_adapters = 1, | 347 | .num_adapters = 1, |
| 294 | .adapter = { | 348 | .adapter = { |
| 295 | { | 349 | { |
| @@ -340,6 +394,8 @@ static struct dvb_usb_device_properties wt220u_miglia_properties = { | |||
| 340 | .usb_ctrl = CYPRESS_FX2, | 394 | .usb_ctrl = CYPRESS_FX2, |
| 341 | .firmware = "dvb-usb-wt220u-miglia-01.fw", | 395 | .firmware = "dvb-usb-wt220u-miglia-01.fw", |
| 342 | 396 | ||
| 397 | .size_of_priv = sizeof(struct dtt200u_state), | ||
| 398 | |||
| 343 | .num_adapters = 1, | 399 | .num_adapters = 1, |
| 344 | .generic_bulk_ctrl_endpoint = 0x01, | 400 | .generic_bulk_ctrl_endpoint = 0x01, |
| 345 | 401 | ||
diff --git a/drivers/media/usb/dvb-usb/dtv5100.c b/drivers/media/usb/dvb-usb/dtv5100.c index 3d11df41cac0..c60fb54f445f 100644 --- a/drivers/media/usb/dvb-usb/dtv5100.c +++ b/drivers/media/usb/dvb-usb/dtv5100.c | |||
| @@ -31,9 +31,14 @@ module_param_named(debug, dvb_usb_dtv5100_debug, int, 0644); | |||
| 31 | MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); | 31 | MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); |
| 32 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 32 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
| 33 | 33 | ||
| 34 | struct dtv5100_state { | ||
| 35 | unsigned char data[80]; | ||
| 36 | }; | ||
| 37 | |||
| 34 | static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr, | 38 | static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr, |
| 35 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) | 39 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) |
| 36 | { | 40 | { |
| 41 | struct dtv5100_state *st = d->priv; | ||
| 37 | u8 request; | 42 | u8 request; |
| 38 | u8 type; | 43 | u8 type; |
| 39 | u16 value; | 44 | u16 value; |
| @@ -60,9 +65,10 @@ static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr, | |||
| 60 | } | 65 | } |
| 61 | index = (addr << 8) + wbuf[0]; | 66 | index = (addr << 8) + wbuf[0]; |
| 62 | 67 | ||
| 68 | memcpy(st->data, rbuf, rlen); | ||
| 63 | msleep(1); /* avoid I2C errors */ | 69 | msleep(1); /* avoid I2C errors */ |
| 64 | return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), request, | 70 | return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), request, |
| 65 | type, value, index, rbuf, rlen, | 71 | type, value, index, st->data, rlen, |
| 66 | DTV5100_USB_TIMEOUT); | 72 | DTV5100_USB_TIMEOUT); |
| 67 | } | 73 | } |
| 68 | 74 | ||
| @@ -176,7 +182,7 @@ static struct dvb_usb_device_properties dtv5100_properties = { | |||
| 176 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | 182 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, |
| 177 | .usb_ctrl = DEVICE_SPECIFIC, | 183 | .usb_ctrl = DEVICE_SPECIFIC, |
| 178 | 184 | ||
| 179 | .size_of_priv = 0, | 185 | .size_of_priv = sizeof(struct dtv5100_state), |
| 180 | 186 | ||
| 181 | .num_adapters = 1, | 187 | .num_adapters = 1, |
| 182 | .adapter = {{ | 188 | .adapter = {{ |
diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 5fb0c650926e..2c720cb2fb00 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c | |||
| @@ -852,7 +852,7 @@ static int su3000_power_ctrl(struct dvb_usb_device *d, int i) | |||
| 852 | if (i && !state->initialized) { | 852 | if (i && !state->initialized) { |
| 853 | state->initialized = 1; | 853 | state->initialized = 1; |
| 854 | /* reset board */ | 854 | /* reset board */ |
| 855 | dvb_usb_generic_rw(d, obuf, 2, NULL, 0, 0); | 855 | return dvb_usb_generic_rw(d, obuf, 2, NULL, 0, 0); |
| 856 | } | 856 | } |
| 857 | 857 | ||
| 858 | return 0; | 858 | return 0; |
diff --git a/drivers/media/usb/dvb-usb/gp8psk.c b/drivers/media/usb/dvb-usb/gp8psk.c index 5d0384dd45b5..adfd76491451 100644 --- a/drivers/media/usb/dvb-usb/gp8psk.c +++ b/drivers/media/usb/dvb-usb/gp8psk.c | |||
| @@ -24,6 +24,10 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DV | |||
| 24 | 24 | ||
| 25 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 25 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
| 26 | 26 | ||
| 27 | struct gp8psk_state { | ||
| 28 | unsigned char data[80]; | ||
| 29 | }; | ||
| 30 | |||
| 27 | static int gp8psk_get_fw_version(struct dvb_usb_device *d, u8 *fw_vers) | 31 | static int gp8psk_get_fw_version(struct dvb_usb_device *d, u8 *fw_vers) |
| 28 | { | 32 | { |
| 29 | return (gp8psk_usb_in_op(d, GET_FW_VERS, 0, 0, fw_vers, 6)); | 33 | 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 | 57 | ||
| 54 | int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) | 58 | int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) |
| 55 | { | 59 | { |
| 60 | struct gp8psk_state *st = d->priv; | ||
| 56 | int ret = 0,try = 0; | 61 | int ret = 0,try = 0; |
| 57 | 62 | ||
| 63 | if (blen > sizeof(st->data)) | ||
| 64 | return -EIO; | ||
| 65 | |||
| 58 | if ((ret = mutex_lock_interruptible(&d->usb_mutex))) | 66 | if ((ret = mutex_lock_interruptible(&d->usb_mutex))) |
| 59 | return ret; | 67 | return ret; |
| 60 | 68 | ||
| 61 | while (ret >= 0 && ret != blen && try < 3) { | 69 | while (ret >= 0 && ret != blen && try < 3) { |
| 70 | memcpy(st->data, b, blen); | ||
| 62 | ret = usb_control_msg(d->udev, | 71 | ret = usb_control_msg(d->udev, |
| 63 | usb_rcvctrlpipe(d->udev,0), | 72 | usb_rcvctrlpipe(d->udev,0), |
| 64 | req, | 73 | req, |
| 65 | USB_TYPE_VENDOR | USB_DIR_IN, | 74 | USB_TYPE_VENDOR | USB_DIR_IN, |
| 66 | value,index,b,blen, | 75 | value, index, st->data, blen, |
| 67 | 2000); | 76 | 2000); |
| 68 | deb_info("reading number %d (ret: %d)\n",try,ret); | 77 | deb_info("reading number %d (ret: %d)\n",try,ret); |
| 69 | try++; | 78 | try++; |
| @@ -86,19 +95,24 @@ int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 | |||
| 86 | int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, | 95 | int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, |
| 87 | u16 index, u8 *b, int blen) | 96 | u16 index, u8 *b, int blen) |
| 88 | { | 97 | { |
| 98 | struct gp8psk_state *st = d->priv; | ||
| 89 | int ret; | 99 | int ret; |
| 90 | 100 | ||
| 91 | deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index); | 101 | deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index); |
| 92 | debug_dump(b,blen,deb_xfer); | 102 | debug_dump(b,blen,deb_xfer); |
| 93 | 103 | ||
| 104 | if (blen > sizeof(st->data)) | ||
| 105 | return -EIO; | ||
| 106 | |||
| 94 | if ((ret = mutex_lock_interruptible(&d->usb_mutex))) | 107 | if ((ret = mutex_lock_interruptible(&d->usb_mutex))) |
| 95 | return ret; | 108 | return ret; |
| 96 | 109 | ||
| 110 | memcpy(st->data, b, blen); | ||
| 97 | if (usb_control_msg(d->udev, | 111 | if (usb_control_msg(d->udev, |
| 98 | usb_sndctrlpipe(d->udev,0), | 112 | usb_sndctrlpipe(d->udev,0), |
| 99 | req, | 113 | req, |
| 100 | USB_TYPE_VENDOR | USB_DIR_OUT, | 114 | USB_TYPE_VENDOR | USB_DIR_OUT, |
| 101 | value,index,b,blen, | 115 | value, index, st->data, blen, |
| 102 | 2000) != blen) { | 116 | 2000) != blen) { |
| 103 | warn("usb out operation failed."); | 117 | warn("usb out operation failed."); |
| 104 | ret = -EIO; | 118 | ret = -EIO; |
| @@ -143,6 +157,11 @@ static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d) | |||
| 143 | err("failed to load bcm4500 firmware."); | 157 | err("failed to load bcm4500 firmware."); |
| 144 | goto out_free; | 158 | goto out_free; |
| 145 | } | 159 | } |
| 160 | if (buflen > 64) { | ||
| 161 | err("firmare chunk size bigger than 64 bytes."); | ||
| 162 | goto out_free; | ||
| 163 | } | ||
| 164 | |||
| 146 | memcpy(buf, ptr, buflen); | 165 | memcpy(buf, ptr, buflen); |
| 147 | if (dvb_usb_generic_write(d, buf, buflen)) { | 166 | if (dvb_usb_generic_write(d, buf, buflen)) { |
| 148 | err("failed to load bcm4500 firmware."); | 167 | err("failed to load bcm4500 firmware."); |
| @@ -265,6 +284,8 @@ static struct dvb_usb_device_properties gp8psk_properties = { | |||
| 265 | .usb_ctrl = CYPRESS_FX2, | 284 | .usb_ctrl = CYPRESS_FX2, |
| 266 | .firmware = "dvb-usb-gp8psk-01.fw", | 285 | .firmware = "dvb-usb-gp8psk-01.fw", |
| 267 | 286 | ||
| 287 | .size_of_priv = sizeof(struct gp8psk_state), | ||
| 288 | |||
| 268 | .num_adapters = 1, | 289 | .num_adapters = 1, |
| 269 | .adapter = { | 290 | .adapter = { |
| 270 | { | 291 | { |
diff --git a/drivers/media/usb/dvb-usb/nova-t-usb2.c b/drivers/media/usb/dvb-usb/nova-t-usb2.c index fc7569e2728d..1babd3341910 100644 --- a/drivers/media/usb/dvb-usb/nova-t-usb2.c +++ b/drivers/media/usb/dvb-usb/nova-t-usb2.c | |||
| @@ -74,22 +74,31 @@ static struct rc_map_table rc_map_haupp_table[] = { | |||
| 74 | */ | 74 | */ |
| 75 | static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | 75 | static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state) |
| 76 | { | 76 | { |
| 77 | u8 key[5],cmd[2] = { DIBUSB_REQ_POLL_REMOTE, 0x35 }, data,toggle,custom; | 77 | u8 *buf, data, toggle, custom; |
| 78 | u16 raw; | 78 | u16 raw; |
| 79 | int i; | 79 | int i, ret; |
| 80 | struct dibusb_device_state *st = d->priv; | 80 | struct dibusb_device_state *st = d->priv; |
| 81 | 81 | ||
| 82 | dvb_usb_generic_rw(d,cmd,2,key,5,0); | 82 | buf = kmalloc(5, GFP_KERNEL); |
| 83 | if (!buf) | ||
| 84 | return -ENOMEM; | ||
| 85 | |||
| 86 | buf[0] = DIBUSB_REQ_POLL_REMOTE; | ||
| 87 | buf[1] = 0x35; | ||
| 88 | ret = dvb_usb_generic_rw(d, buf, 2, buf, 5, 0); | ||
| 89 | if (ret < 0) | ||
| 90 | goto ret; | ||
| 83 | 91 | ||
| 84 | *state = REMOTE_NO_KEY_PRESSED; | 92 | *state = REMOTE_NO_KEY_PRESSED; |
| 85 | switch (key[0]) { | 93 | switch (buf[0]) { |
| 86 | case DIBUSB_RC_HAUPPAUGE_KEY_PRESSED: | 94 | case DIBUSB_RC_HAUPPAUGE_KEY_PRESSED: |
| 87 | raw = ((key[1] << 8) | key[2]) >> 3; | 95 | raw = ((buf[1] << 8) | buf[2]) >> 3; |
| 88 | toggle = !!(raw & 0x800); | 96 | toggle = !!(raw & 0x800); |
| 89 | data = raw & 0x3f; | 97 | data = raw & 0x3f; |
| 90 | custom = (raw >> 6) & 0x1f; | 98 | custom = (raw >> 6) & 0x1f; |
| 91 | 99 | ||
| 92 | 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); | 100 | deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to c: %02x d: %02x toggle: %d\n", |
| 101 | buf[1], buf[2], buf[3], custom, data, toggle); | ||
| 93 | 102 | ||
| 94 | for (i = 0; i < ARRAY_SIZE(rc_map_haupp_table); i++) { | 103 | for (i = 0; i < ARRAY_SIZE(rc_map_haupp_table); i++) { |
| 95 | if (rc5_data(&rc_map_haupp_table[i]) == data && | 104 | 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 | break; | 126 | break; |
| 118 | } | 127 | } |
| 119 | 128 | ||
| 120 | return 0; | 129 | ret: |
| 130 | kfree(buf); | ||
| 131 | return ret; | ||
| 121 | } | 132 | } |
| 122 | 133 | ||
| 123 | static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6]) | 134 | static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6]) |
diff --git a/drivers/media/usb/dvb-usb/pctv452e.c b/drivers/media/usb/dvb-usb/pctv452e.c index c05de1b088a4..07fa08be9e99 100644 --- a/drivers/media/usb/dvb-usb/pctv452e.c +++ b/drivers/media/usb/dvb-usb/pctv452e.c | |||
| @@ -97,48 +97,53 @@ struct pctv452e_state { | |||
| 97 | u8 c; /* transaction counter, wraps around... */ | 97 | u8 c; /* transaction counter, wraps around... */ |
| 98 | u8 initialized; /* set to 1 if 0x15 has been sent */ | 98 | u8 initialized; /* set to 1 if 0x15 has been sent */ |
| 99 | u16 last_rc_key; | 99 | u16 last_rc_key; |
| 100 | |||
| 101 | unsigned char data[80]; | ||
| 100 | }; | 102 | }; |
| 101 | 103 | ||
| 102 | static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, | 104 | static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, |
| 103 | unsigned int write_len, unsigned int read_len) | 105 | unsigned int write_len, unsigned int read_len) |
| 104 | { | 106 | { |
| 105 | struct pctv452e_state *state = (struct pctv452e_state *)d->priv; | 107 | struct pctv452e_state *state = (struct pctv452e_state *)d->priv; |
| 106 | u8 buf[64]; | ||
| 107 | u8 id; | 108 | u8 id; |
| 108 | unsigned int rlen; | 109 | unsigned int rlen; |
| 109 | int ret; | 110 | int ret; |
| 110 | 111 | ||
| 111 | BUG_ON(NULL == data && 0 != (write_len | read_len)); | 112 | if (!data || (write_len > 64 - 4) || (read_len > 64 - 4)) { |
| 112 | BUG_ON(write_len > 64 - 4); | 113 | err("%s: transfer data invalid", __func__); |
| 113 | BUG_ON(read_len > 64 - 4); | 114 | return -EIO; |
| 115 | } | ||
| 114 | 116 | ||
| 117 | mutex_lock(&state->ca_mutex); | ||
| 115 | id = state->c++; | 118 | id = state->c++; |
| 116 | 119 | ||
| 117 | buf[0] = SYNC_BYTE_OUT; | 120 | state->data[0] = SYNC_BYTE_OUT; |
| 118 | buf[1] = id; | 121 | state->data[1] = id; |
| 119 | buf[2] = cmd; | 122 | state->data[2] = cmd; |
| 120 | buf[3] = write_len; | 123 | state->data[3] = write_len; |
| 121 | 124 | ||
| 122 | memcpy(buf + 4, data, write_len); | 125 | memcpy(state->data + 4, data, write_len); |
| 123 | 126 | ||
| 124 | rlen = (read_len > 0) ? 64 : 0; | 127 | rlen = (read_len > 0) ? 64 : 0; |
| 125 | ret = dvb_usb_generic_rw(d, buf, 4 + write_len, | 128 | ret = dvb_usb_generic_rw(d, state->data, 4 + write_len, |
| 126 | buf, rlen, /* delay_ms */ 0); | 129 | state->data, rlen, /* delay_ms */ 0); |
| 127 | if (0 != ret) | 130 | if (0 != ret) |
| 128 | goto failed; | 131 | goto failed; |
| 129 | 132 | ||
| 130 | ret = -EIO; | 133 | ret = -EIO; |
| 131 | if (SYNC_BYTE_IN != buf[0] || id != buf[1]) | 134 | if (SYNC_BYTE_IN != state->data[0] || id != state->data[1]) |
| 132 | goto failed; | 135 | goto failed; |
| 133 | 136 | ||
| 134 | memcpy(data, buf + 4, read_len); | 137 | memcpy(data, state->data + 4, read_len); |
| 135 | 138 | ||
| 139 | mutex_unlock(&state->ca_mutex); | ||
| 136 | return 0; | 140 | return 0; |
| 137 | 141 | ||
| 138 | failed: | 142 | failed: |
| 139 | err("CI error %d; %02X %02X %02X -> %*ph.", | 143 | err("CI error %d; %02X %02X %02X -> %*ph.", |
| 140 | ret, SYNC_BYTE_OUT, id, cmd, 3, buf); | 144 | ret, SYNC_BYTE_OUT, id, cmd, 3, state->data); |
| 141 | 145 | ||
| 146 | mutex_unlock(&state->ca_mutex); | ||
| 142 | return ret; | 147 | return ret; |
| 143 | } | 148 | } |
| 144 | 149 | ||
| @@ -405,52 +410,53 @@ static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr, | |||
| 405 | u8 *rcv_buf, u8 rcv_len) | 410 | u8 *rcv_buf, u8 rcv_len) |
| 406 | { | 411 | { |
| 407 | struct pctv452e_state *state = (struct pctv452e_state *)d->priv; | 412 | struct pctv452e_state *state = (struct pctv452e_state *)d->priv; |
| 408 | u8 buf[64]; | ||
| 409 | u8 id; | 413 | u8 id; |
| 410 | int ret; | 414 | int ret; |
| 411 | 415 | ||
| 416 | mutex_lock(&state->ca_mutex); | ||
| 412 | id = state->c++; | 417 | id = state->c++; |
| 413 | 418 | ||
| 414 | ret = -EINVAL; | 419 | ret = -EINVAL; |
| 415 | if (snd_len > 64 - 7 || rcv_len > 64 - 7) | 420 | if (snd_len > 64 - 7 || rcv_len > 64 - 7) |
| 416 | goto failed; | 421 | goto failed; |
| 417 | 422 | ||
| 418 | buf[0] = SYNC_BYTE_OUT; | 423 | state->data[0] = SYNC_BYTE_OUT; |
| 419 | buf[1] = id; | 424 | state->data[1] = id; |
| 420 | buf[2] = PCTV_CMD_I2C; | 425 | state->data[2] = PCTV_CMD_I2C; |
| 421 | buf[3] = snd_len + 3; | 426 | state->data[3] = snd_len + 3; |
| 422 | buf[4] = addr << 1; | 427 | state->data[4] = addr << 1; |
| 423 | buf[5] = snd_len; | 428 | state->data[5] = snd_len; |
| 424 | buf[6] = rcv_len; | 429 | state->data[6] = rcv_len; |
| 425 | 430 | ||
| 426 | memcpy(buf + 7, snd_buf, snd_len); | 431 | memcpy(state->data + 7, snd_buf, snd_len); |
| 427 | 432 | ||
| 428 | ret = dvb_usb_generic_rw(d, buf, 7 + snd_len, | 433 | ret = dvb_usb_generic_rw(d, state->data, 7 + snd_len, |
| 429 | buf, /* rcv_len */ 64, | 434 | state->data, /* rcv_len */ 64, |
| 430 | /* delay_ms */ 0); | 435 | /* delay_ms */ 0); |
| 431 | if (ret < 0) | 436 | if (ret < 0) |
| 432 | goto failed; | 437 | goto failed; |
| 433 | 438 | ||
| 434 | /* TT USB protocol error. */ | 439 | /* TT USB protocol error. */ |
| 435 | ret = -EIO; | 440 | ret = -EIO; |
| 436 | if (SYNC_BYTE_IN != buf[0] || id != buf[1]) | 441 | if (SYNC_BYTE_IN != state->data[0] || id != state->data[1]) |
| 437 | goto failed; | 442 | goto failed; |
| 438 | 443 | ||
| 439 | /* I2C device didn't respond as expected. */ | 444 | /* I2C device didn't respond as expected. */ |
| 440 | ret = -EREMOTEIO; | 445 | ret = -EREMOTEIO; |
| 441 | if (buf[5] < snd_len || buf[6] < rcv_len) | 446 | if (state->data[5] < snd_len || state->data[6] < rcv_len) |
| 442 | goto failed; | 447 | goto failed; |
| 443 | 448 | ||
| 444 | memcpy(rcv_buf, buf + 7, rcv_len); | 449 | memcpy(rcv_buf, state->data + 7, rcv_len); |
| 450 | mutex_unlock(&state->ca_mutex); | ||
| 445 | 451 | ||
| 446 | return rcv_len; | 452 | return rcv_len; |
| 447 | 453 | ||
| 448 | failed: | 454 | failed: |
| 449 | err("I2C error %d; %02X %02X %02X %02X %02X -> " | 455 | err("I2C error %d; %02X %02X %02X %02X %02X -> %*ph", |
| 450 | "%02X %02X %02X %02X %02X.", | ||
| 451 | ret, SYNC_BYTE_OUT, id, addr << 1, snd_len, rcv_len, | 456 | ret, SYNC_BYTE_OUT, id, addr << 1, snd_len, rcv_len, |
| 452 | buf[0], buf[1], buf[4], buf[5], buf[6]); | 457 | 7, state->data); |
| 453 | 458 | ||
| 459 | mutex_unlock(&state->ca_mutex); | ||
| 454 | return ret; | 460 | return ret; |
| 455 | } | 461 | } |
| 456 | 462 | ||
| @@ -499,8 +505,7 @@ static u32 pctv452e_i2c_func(struct i2c_adapter *adapter) | |||
| 499 | static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i) | 505 | static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i) |
| 500 | { | 506 | { |
| 501 | struct pctv452e_state *state = (struct pctv452e_state *)d->priv; | 507 | struct pctv452e_state *state = (struct pctv452e_state *)d->priv; |
| 502 | u8 b0[] = { 0xaa, 0, PCTV_CMD_RESET, 1, 0 }; | 508 | u8 *rx; |
| 503 | u8 rx[PCTV_ANSWER_LEN]; | ||
| 504 | int ret; | 509 | int ret; |
| 505 | 510 | ||
| 506 | info("%s: %d\n", __func__, i); | 511 | info("%s: %d\n", __func__, i); |
| @@ -511,6 +516,11 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i) | |||
| 511 | if (state->initialized) | 516 | if (state->initialized) |
| 512 | return 0; | 517 | return 0; |
| 513 | 518 | ||
| 519 | rx = kmalloc(PCTV_ANSWER_LEN, GFP_KERNEL); | ||
| 520 | if (!rx) | ||
| 521 | return -ENOMEM; | ||
| 522 | |||
| 523 | mutex_lock(&state->ca_mutex); | ||
| 514 | /* hmm where shoud this should go? */ | 524 | /* hmm where shoud this should go? */ |
| 515 | ret = usb_set_interface(d->udev, 0, ISOC_INTERFACE_ALTERNATIVE); | 525 | ret = usb_set_interface(d->udev, 0, ISOC_INTERFACE_ALTERNATIVE); |
| 516 | if (ret != 0) | 526 | if (ret != 0) |
| @@ -518,65 +528,75 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i) | |||
| 518 | __func__, ret); | 528 | __func__, ret); |
| 519 | 529 | ||
| 520 | /* this is a one-time initialization, dont know where to put */ | 530 | /* this is a one-time initialization, dont know where to put */ |
| 521 | b0[1] = state->c++; | 531 | state->data[0] = 0xaa; |
| 532 | state->data[1] = state->c++; | ||
| 533 | state->data[2] = PCTV_CMD_RESET; | ||
| 534 | state->data[3] = 1; | ||
| 535 | state->data[4] = 0; | ||
| 522 | /* reset board */ | 536 | /* reset board */ |
| 523 | ret = dvb_usb_generic_rw(d, b0, sizeof(b0), rx, PCTV_ANSWER_LEN, 0); | 537 | ret = dvb_usb_generic_rw(d, state->data, 5, rx, PCTV_ANSWER_LEN, 0); |
| 524 | if (ret) | 538 | if (ret) |
| 525 | return ret; | 539 | goto ret; |
| 526 | 540 | ||
| 527 | b0[1] = state->c++; | 541 | state->data[1] = state->c++; |
| 528 | b0[4] = 1; | 542 | state->data[4] = 1; |
| 529 | /* reset board (again?) */ | 543 | /* reset board (again?) */ |
| 530 | ret = dvb_usb_generic_rw(d, b0, sizeof(b0), rx, PCTV_ANSWER_LEN, 0); | 544 | ret = dvb_usb_generic_rw(d, state->data, 5, rx, PCTV_ANSWER_LEN, 0); |
| 531 | if (ret) | 545 | if (ret) |
| 532 | return ret; | 546 | goto ret; |
| 533 | 547 | ||
| 534 | state->initialized = 1; | 548 | state->initialized = 1; |
| 535 | 549 | ||
| 536 | return 0; | 550 | ret: |
| 551 | mutex_unlock(&state->ca_mutex); | ||
| 552 | kfree(rx); | ||
| 553 | return ret; | ||
| 537 | } | 554 | } |
| 538 | 555 | ||
| 539 | static int pctv452e_rc_query(struct dvb_usb_device *d) | 556 | static int pctv452e_rc_query(struct dvb_usb_device *d) |
| 540 | { | 557 | { |
| 541 | struct pctv452e_state *state = (struct pctv452e_state *)d->priv; | 558 | struct pctv452e_state *state = (struct pctv452e_state *)d->priv; |
| 542 | u8 b[CMD_BUFFER_SIZE]; | ||
| 543 | u8 rx[PCTV_ANSWER_LEN]; | ||
| 544 | int ret, i; | 559 | int ret, i; |
| 545 | u8 id = state->c++; | 560 | u8 id; |
| 561 | |||
| 562 | mutex_lock(&state->ca_mutex); | ||
| 563 | id = state->c++; | ||
| 546 | 564 | ||
| 547 | /* prepare command header */ | 565 | /* prepare command header */ |
| 548 | b[0] = SYNC_BYTE_OUT; | 566 | state->data[0] = SYNC_BYTE_OUT; |
| 549 | b[1] = id; | 567 | state->data[1] = id; |
| 550 | b[2] = PCTV_CMD_IR; | 568 | state->data[2] = PCTV_CMD_IR; |
| 551 | b[3] = 0; | 569 | state->data[3] = 0; |
| 552 | 570 | ||
| 553 | /* send ir request */ | 571 | /* send ir request */ |
| 554 | ret = dvb_usb_generic_rw(d, b, 4, rx, PCTV_ANSWER_LEN, 0); | 572 | ret = dvb_usb_generic_rw(d, state->data, 4, |
| 573 | state->data, PCTV_ANSWER_LEN, 0); | ||
| 555 | if (ret != 0) | 574 | if (ret != 0) |
| 556 | return ret; | 575 | goto ret; |
| 557 | 576 | ||
| 558 | if (debug > 3) { | 577 | if (debug > 3) { |
| 559 | info("%s: read: %2d: %*ph: ", __func__, ret, 3, rx); | 578 | info("%s: read: %2d: %*ph: ", __func__, ret, 3, state->data); |
| 560 | for (i = 0; (i < rx[3]) && ((i+3) < PCTV_ANSWER_LEN); i++) | 579 | for (i = 0; (i < state->data[3]) && ((i + 3) < PCTV_ANSWER_LEN); i++) |
| 561 | info(" %02x", rx[i+3]); | 580 | info(" %02x", state->data[i + 3]); |
| 562 | 581 | ||
| 563 | info("\n"); | 582 | info("\n"); |
| 564 | } | 583 | } |
| 565 | 584 | ||
| 566 | if ((rx[3] == 9) && (rx[12] & 0x01)) { | 585 | if ((state->data[3] == 9) && (state->data[12] & 0x01)) { |
| 567 | /* got a "press" event */ | 586 | /* got a "press" event */ |
| 568 | state->last_rc_key = RC_SCANCODE_RC5(rx[7], rx[6]); | 587 | state->last_rc_key = RC_SCANCODE_RC5(state->data[7], state->data[6]); |
| 569 | if (debug > 2) | 588 | if (debug > 2) |
| 570 | info("%s: cmd=0x%02x sys=0x%02x\n", | 589 | info("%s: cmd=0x%02x sys=0x%02x\n", |
| 571 | __func__, rx[6], rx[7]); | 590 | __func__, state->data[6], state->data[7]); |
| 572 | 591 | ||
| 573 | rc_keydown(d->rc_dev, RC_TYPE_RC5, state->last_rc_key, 0); | 592 | rc_keydown(d->rc_dev, RC_TYPE_RC5, state->last_rc_key, 0); |
| 574 | } else if (state->last_rc_key) { | 593 | } else if (state->last_rc_key) { |
| 575 | rc_keyup(d->rc_dev); | 594 | rc_keyup(d->rc_dev); |
| 576 | state->last_rc_key = 0; | 595 | state->last_rc_key = 0; |
| 577 | } | 596 | } |
| 578 | 597 | ret: | |
| 579 | return 0; | 598 | mutex_unlock(&state->ca_mutex); |
| 599 | return ret; | ||
| 580 | } | 600 | } |
| 581 | 601 | ||
| 582 | static int pctv452e_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) | 602 | static int pctv452e_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) |
diff --git a/drivers/media/usb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c index d9f3262bf071..4706628a3ed5 100644 --- a/drivers/media/usb/dvb-usb/technisat-usb2.c +++ b/drivers/media/usb/dvb-usb/technisat-usb2.c | |||
| @@ -89,9 +89,13 @@ struct technisat_usb2_state { | |||
| 89 | static int technisat_usb2_i2c_access(struct usb_device *udev, | 89 | static int technisat_usb2_i2c_access(struct usb_device *udev, |
| 90 | u8 device_addr, u8 *tx, u8 txlen, u8 *rx, u8 rxlen) | 90 | u8 device_addr, u8 *tx, u8 txlen, u8 *rx, u8 rxlen) |
| 91 | { | 91 | { |
| 92 | u8 b[64]; | 92 | u8 *b; |
| 93 | int ret, actual_length; | 93 | int ret, actual_length; |
| 94 | 94 | ||
| 95 | b = kmalloc(64, GFP_KERNEL); | ||
| 96 | if (!b) | ||
| 97 | return -ENOMEM; | ||
| 98 | |||
| 95 | deb_i2c("i2c-access: %02x, tx: ", device_addr); | 99 | deb_i2c("i2c-access: %02x, tx: ", device_addr); |
| 96 | debug_dump(tx, txlen, deb_i2c); | 100 | debug_dump(tx, txlen, deb_i2c); |
| 97 | deb_i2c(" "); | 101 | deb_i2c(" "); |
| @@ -123,7 +127,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev, | |||
| 123 | 127 | ||
| 124 | if (ret < 0) { | 128 | if (ret < 0) { |
| 125 | err("i2c-error: out failed %02x = %d", device_addr, ret); | 129 | err("i2c-error: out failed %02x = %d", device_addr, ret); |
| 126 | return -ENODEV; | 130 | goto err; |
| 127 | } | 131 | } |
| 128 | 132 | ||
| 129 | ret = usb_bulk_msg(udev, | 133 | ret = usb_bulk_msg(udev, |
| @@ -131,7 +135,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev, | |||
| 131 | b, 64, &actual_length, 1000); | 135 | b, 64, &actual_length, 1000); |
| 132 | if (ret < 0) { | 136 | if (ret < 0) { |
| 133 | err("i2c-error: in failed %02x = %d", device_addr, ret); | 137 | err("i2c-error: in failed %02x = %d", device_addr, ret); |
| 134 | return -ENODEV; | 138 | goto err; |
| 135 | } | 139 | } |
| 136 | 140 | ||
| 137 | if (b[0] != I2C_STATUS_OK) { | 141 | if (b[0] != I2C_STATUS_OK) { |
| @@ -140,7 +144,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev, | |||
| 140 | if (!(b[0] == I2C_STATUS_NAK && | 144 | if (!(b[0] == I2C_STATUS_NAK && |
| 141 | device_addr == 0x60 | 145 | device_addr == 0x60 |
| 142 | /* && device_is_technisat_usb2 */)) | 146 | /* && device_is_technisat_usb2 */)) |
| 143 | return -ENODEV; | 147 | goto err; |
| 144 | } | 148 | } |
| 145 | 149 | ||
| 146 | deb_i2c("status: %d, ", b[0]); | 150 | deb_i2c("status: %d, ", b[0]); |
| @@ -154,7 +158,9 @@ static int technisat_usb2_i2c_access(struct usb_device *udev, | |||
| 154 | 158 | ||
| 155 | deb_i2c("\n"); | 159 | deb_i2c("\n"); |
| 156 | 160 | ||
| 157 | return 0; | 161 | err: |
| 162 | kfree(b); | ||
| 163 | return ret; | ||
| 158 | } | 164 | } |
| 159 | 165 | ||
| 160 | static int technisat_usb2_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, | 166 | static int technisat_usb2_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, |
diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c index c3a0e87066eb..f7bb78c1873c 100644 --- a/drivers/media/usb/s2255/s2255drv.c +++ b/drivers/media/usb/s2255/s2255drv.c | |||
| @@ -1901,19 +1901,30 @@ static long s2255_vendor_req(struct s2255_dev *dev, unsigned char Request, | |||
| 1901 | s32 TransferBufferLength, int bOut) | 1901 | s32 TransferBufferLength, int bOut) |
| 1902 | { | 1902 | { |
| 1903 | int r; | 1903 | int r; |
| 1904 | unsigned char *buf; | ||
| 1905 | |||
| 1906 | buf = kmalloc(TransferBufferLength, GFP_KERNEL); | ||
| 1907 | if (!buf) | ||
| 1908 | return -ENOMEM; | ||
| 1909 | |||
| 1904 | if (!bOut) { | 1910 | if (!bOut) { |
| 1905 | r = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), | 1911 | r = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), |
| 1906 | Request, | 1912 | Request, |
| 1907 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | | 1913 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | |
| 1908 | USB_DIR_IN, | 1914 | USB_DIR_IN, |
| 1909 | Value, Index, TransferBuffer, | 1915 | Value, Index, buf, |
| 1910 | TransferBufferLength, HZ * 5); | 1916 | TransferBufferLength, HZ * 5); |
| 1917 | |||
| 1918 | if (r >= 0) | ||
| 1919 | memcpy(TransferBuffer, buf, TransferBufferLength); | ||
| 1911 | } else { | 1920 | } else { |
| 1921 | memcpy(buf, TransferBuffer, TransferBufferLength); | ||
| 1912 | r = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), | 1922 | r = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), |
| 1913 | Request, USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 1923 | Request, USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 1914 | Value, Index, TransferBuffer, | 1924 | Value, Index, buf, |
| 1915 | TransferBufferLength, HZ * 5); | 1925 | TransferBufferLength, HZ * 5); |
| 1916 | } | 1926 | } |
| 1927 | kfree(buf); | ||
| 1917 | return r; | 1928 | return r; |
| 1918 | } | 1929 | } |
| 1919 | 1930 | ||
diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c index db200c9d796d..22a9aae16291 100644 --- a/drivers/media/usb/stkwebcam/stk-webcam.c +++ b/drivers/media/usb/stkwebcam/stk-webcam.c | |||
| @@ -147,20 +147,26 @@ int stk_camera_write_reg(struct stk_camera *dev, u16 index, u8 value) | |||
| 147 | int stk_camera_read_reg(struct stk_camera *dev, u16 index, int *value) | 147 | int stk_camera_read_reg(struct stk_camera *dev, u16 index, int *value) |
| 148 | { | 148 | { |
| 149 | struct usb_device *udev = dev->udev; | 149 | struct usb_device *udev = dev->udev; |
| 150 | unsigned char *buf; | ||
| 150 | int ret; | 151 | int ret; |
| 151 | 152 | ||
| 153 | buf = kmalloc(sizeof(u8), GFP_KERNEL); | ||
| 154 | if (!buf) | ||
| 155 | return -ENOMEM; | ||
| 156 | |||
| 152 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | 157 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), |
| 153 | 0x00, | 158 | 0x00, |
| 154 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 159 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 155 | 0x00, | 160 | 0x00, |
| 156 | index, | 161 | index, |
| 157 | (u8 *) value, | 162 | buf, |
| 158 | sizeof(u8), | 163 | sizeof(u8), |
| 159 | 500); | 164 | 500); |
| 160 | if (ret < 0) | 165 | if (ret >= 0) |
| 161 | return ret; | 166 | memcpy(value, buf, sizeof(u8)); |
| 162 | else | 167 | |
| 163 | return 0; | 168 | kfree(buf); |
| 169 | return ret; | ||
| 164 | } | 170 | } |
| 165 | 171 | ||
| 166 | static int stk_start_stream(struct stk_camera *dev) | 172 | static int stk_start_stream(struct stk_camera *dev) |
diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c index ea15cc638097..4d9bd02ede47 100644 --- a/drivers/staging/media/bcm2048/radio-bcm2048.c +++ b/drivers/staging/media/bcm2048/radio-bcm2048.c | |||
| @@ -482,6 +482,8 @@ static int bcm2048_set_rds_no_lock(struct bcm2048_device *bdev, u8 rds_on) | |||
| 482 | flags); | 482 | flags); |
| 483 | memset(&bdev->rds_info, 0, sizeof(bdev->rds_info)); | 483 | memset(&bdev->rds_info, 0, sizeof(bdev->rds_info)); |
| 484 | } | 484 | } |
| 485 | if (err) | ||
| 486 | return err; | ||
| 485 | 487 | ||
| 486 | return bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM, | 488 | return bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM, |
| 487 | bdev->cache_fm_rds_system); | 489 | bdev->cache_fm_rds_system); |
