Merge tag 'v4.9-rc1' into patchwork
authorMauro Carvalho Chehab <mchehab@s-opensource.com>
Mon, 17 Oct 2016 14:10:40 +0000 (12:10 -0200)
committerMauro Carvalho Chehab <mchehab@s-opensource.com>
Mon, 17 Oct 2016 14:10:40 +0000 (12:10 -0200)
Linux 4.9-rc1

* tag 'v4.9-rc1': (13774 commits)
  Linux 4.9-rc1
  score: traps: Add missing include file to fix build error
  fs/super.c: don't fool lockdep in freeze_super() and thaw_super() paths
  fs/super.c: fix race between freeze_super() and thaw_super()
  overlayfs: Fix setting IOP_XATTR flag
  iov_iter: kernel-doc import_iovec() and rw_copy_check_uvector()
  CIFS: Retrieve uid and gid from special sid if enabled
  CIFS: Add new mount option to set owner uid and gid from special sids in acl
  qedr: Add events support and register IB device
  qedr: Add GSI support
  qedr: Add LL2 RoCE interface
  qedr: Add support for data path
  qedr: Add support for memory registeration verbs
  qedr: Add support for QP verbs
  qedr: Add support for PD,PKEY and CQ verbs
  qedr: Add support for user context verbs
  qedr: Add support for RoCE HW init
  qedr: Add RoCE driver framework
  pkeys: Remove easily triggered WARN
  MIPS: Wire up new pkey_{mprotect,alloc,free} syscalls
  ...

25 files changed:
drivers/media/usb/b2c2/flexcop-usb.c
drivers/media/usb/b2c2/flexcop-usb.h
drivers/media/usb/cpia2/cpia2_usb.c
drivers/media/usb/dvb-usb/af9005.c
drivers/media/usb/dvb-usb/cinergyT2-core.c
drivers/media/usb/dvb-usb/cinergyT2-fe.c
drivers/media/usb/dvb-usb/cxusb.c
drivers/media/usb/dvb-usb/cxusb.h
drivers/media/usb/dvb-usb/dib0700_core.c
drivers/media/usb/dvb-usb/dib0700_devices.c
drivers/media/usb/dvb-usb/dibusb-common.c
drivers/media/usb/dvb-usb/dibusb.h
drivers/media/usb/dvb-usb/digitv.c
drivers/media/usb/dvb-usb/digitv.h
drivers/media/usb/dvb-usb/dtt200u-fe.c
drivers/media/usb/dvb-usb/dtt200u.c
drivers/media/usb/dvb-usb/dtv5100.c
drivers/media/usb/dvb-usb/dvb-usb.h
drivers/media/usb/dvb-usb/dw2102.c
drivers/media/usb/dvb-usb/gp8psk.c
drivers/media/usb/dvb-usb/nova-t-usb2.c
drivers/media/usb/dvb-usb/pctv452e.c
drivers/media/usb/dvb-usb/technisat-usb2.c
drivers/media/usb/s2255/s2255drv.c
drivers/media/usb/stkwebcam/stk-webcam.c

index d4bdba60b0f71436065e4884d5622cc34dffbfe6..52bc42da8a4ce4dde4848c3a2497c5b286b6ae8b 100644 (file)
@@ -73,23 +73,34 @@ static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI,
        u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR;
        u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) |
                (read ? 0x80 : 0);
+       int ret;
+
+       mutex_lock(&fc_usb->data_mutex);
+       if (!read)
+               memcpy(fc_usb->data, val, sizeof(*val));
 
-       int len = usb_control_msg(fc_usb->udev,
+       ret = usb_control_msg(fc_usb->udev,
                        read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT,
                        request,
                        request_type, /* 0xc0 read or 0x40 write */
                        wAddress,
                        0,
-                       val,
+                       fc_usb->data,
                        sizeof(u32),
                        B2C2_WAIT_FOR_OPERATION_RDW * HZ);
 
-       if (len != sizeof(u32)) {
+       if (ret != sizeof(u32)) {
                err("error while %s dword from %d (%d).", read ? "reading" :
                                "writing", wAddress, wRegOffsPCI);
-               return -EIO;
+               if (ret >= 0)
+                       ret = -EIO;
        }
-       return 0;
+
+       if (read && ret >= 0)
+               memcpy(val, fc_usb->data, sizeof(*val));
+       mutex_unlock(&fc_usb->data_mutex);
+
+       return ret;
 }
 /*
  * DKT 010817 - add support for V8 memory read/write and flash update
@@ -100,9 +111,14 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,
 {
        u8 request_type = USB_TYPE_VENDOR;
        u16 wIndex;
-       int nWaitTime, pipe, len;
+       int nWaitTime, pipe, ret;
        wIndex = page << 8;
 
+       if (buflen > sizeof(fc_usb->data)) {
+               err("Buffer size bigger than max URB control message\n");
+               return -EIO;
+       }
+
        switch (req) {
        case B2C2_USB_READ_V8_MEM:
                nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ;
@@ -127,17 +143,32 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,
        deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n", request_type, req,
                        wAddress, wIndex, buflen);
 
-       len = usb_control_msg(fc_usb->udev, pipe,
+       mutex_lock(&fc_usb->data_mutex);
+
+       if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
+               memcpy(fc_usb->data, pbBuffer, buflen);
+
+       ret = usb_control_msg(fc_usb->udev, pipe,
                        req,
                        request_type,
                        wAddress,
                        wIndex,
-                       pbBuffer,
+                       fc_usb->data,
                        buflen,
                        nWaitTime * HZ);
+       if (ret != buflen)
+               ret = -EIO;
+
+       if (ret >= 0) {
+               ret = 0;
+               if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
+                       memcpy(pbBuffer, fc_usb->data, buflen);
+       }
 
-       debug_dump(pbBuffer, len, deb_v8);
-       return len == buflen ? 0 : -EIO;
+       mutex_unlock(&fc_usb->data_mutex);
+
+       debug_dump(pbBuffer, ret, deb_v8);
+       return ret;
 }
 
 #define bytes_left_to_read_on_page(paddr,buflen) \
@@ -196,29 +227,6 @@ static int flexcop_usb_get_mac_addr(struct flexcop_device *fc, int extended)
                fc->dvb_adapter.proposed_mac, 6);
 }
 
-#if 0
-static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set,
-               flexcop_usb_utility_function_t func, u8 extra, u16 wIndex,
-               u16 buflen, u8 *pvBuffer)
-{
-       u16 wValue;
-       u8 request_type = (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR;
-       int nWaitTime = 2,
-           pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN, len;
-       wValue = (func << 8) | extra;
-
-       len = usb_control_msg(fc_usb->udev,pipe,
-                       B2C2_USB_UTILITY,
-                       request_type,
-                       wValue,
-                       wIndex,
-                       pvBuffer,
-                       buflen,
-                       nWaitTime * HZ);
-       return len == buflen ? 0 : -EIO;
-}
-#endif
-
 /* usb i2c stuff */
 static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
                flexcop_usb_request_t req, flexcop_usb_i2c_function_t func,
@@ -226,9 +234,14 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
 {
        struct flexcop_usb *fc_usb = i2c->fc->bus_specific;
        u16 wValue, wIndex;
-       int nWaitTime,pipe,len;
+       int nWaitTime, pipe, ret;
        u8 request_type = USB_TYPE_VENDOR;
 
+       if (buflen > sizeof(fc_usb->data)) {
+               err("Buffer size bigger than max URB control message\n");
+               return -EIO;
+       }
+
        switch (func) {
        case USB_FUNC_I2C_WRITE:
        case USB_FUNC_I2C_MULTIWRITE:
@@ -257,15 +270,32 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
                        wValue & 0xff, wValue >> 8,
                        wIndex & 0xff, wIndex >> 8);
 
-       len = usb_control_msg(fc_usb->udev,pipe,
+       mutex_lock(&fc_usb->data_mutex);
+
+       if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
+               memcpy(fc_usb->data, buf, buflen);
+
+       ret = usb_control_msg(fc_usb->udev, pipe,
                        req,
                        request_type,
                        wValue,
                        wIndex,
-                       buf,
+                       fc_usb->data,
                        buflen,
                        nWaitTime * HZ);
-       return len == buflen ? 0 : -EREMOTEIO;
+
+       if (ret != buflen)
+               ret = -EIO;
+
+       if (ret >= 0) {
+               ret = 0;
+               if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
+                       memcpy(buf, fc_usb->data, buflen);
+       }
+
+       mutex_unlock(&fc_usb->data_mutex);
+
+       return 0;
 }
 
 /* actual bus specific access functions,
@@ -516,6 +546,7 @@ static int flexcop_usb_probe(struct usb_interface *intf,
        /* general flexcop init */
        fc_usb = fc->bus_specific;
        fc_usb->fc_dev = fc;
+       mutex_init(&fc_usb->data_mutex);
 
        fc->read_ibi_reg  = flexcop_usb_read_ibi_reg;
        fc->write_ibi_reg = flexcop_usb_write_ibi_reg;
index 92529a9c4475b71ca5381670ceb16d5ccfcd079c..25ad43166e78c759226c603e66fa6e6b81a361f8 100644 (file)
@@ -29,6 +29,10 @@ struct flexcop_usb {
 
        u8 tmp_buffer[1023+190];
        int tmp_buffer_length;
+
+       /* for URB control messages */
+       u8 data[80];
+       struct mutex data_mutex;
 };
 
 #if 0
index 13620cdf05996fd3d549a5668043db0b12b1d381..e9100a23583104d3f6fcdcb4f0dfa9535877704a 100644 (file)
@@ -545,18 +545,30 @@ static void free_sbufs(struct camera_data *cam)
 static int write_packet(struct usb_device *udev,
                        u8 request, u8 * registers, u16 start, size_t size)
 {
+       unsigned char *buf;
+       int ret;
+
        if (!registers || size <= 0)
                return -EINVAL;
 
-       return usb_control_msg(udev,
+       buf = kmalloc(size, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       memcpy(buf, registers, size);
+
+       ret = usb_control_msg(udev,
                               usb_sndctrlpipe(udev, 0),
                               request,
                               USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                               start,   /* value */
                               0,       /* index */
-                              registers,       /* buffer */
+                              buf,     /* buffer */
                               size,
                               HZ);
+
+       kfree(buf);
+       return ret;
 }
 
 /****************************************************************************
@@ -567,18 +579,32 @@ static int write_packet(struct usb_device *udev,
 static int read_packet(struct usb_device *udev,
                       u8 request, u8 * registers, u16 start, size_t size)
 {
+       unsigned char *buf;
+       int ret;
+
        if (!registers || size <= 0)
                return -EINVAL;
 
-       return usb_control_msg(udev,
+       buf = kmalloc(size, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       ret = usb_control_msg(udev,
                               usb_rcvctrlpipe(udev, 0),
                               request,
                               USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE,
                               start,   /* value */
                               0,       /* index */
-                              registers,       /* buffer */
+                              buf,     /* buffer */
                               size,
                               HZ);
+
+       if (ret >= 0)
+               memcpy(registers, buf, size);
+
+       kfree(buf);
+
+       return ret;
 }
 
 /******************************************************************************
index efa782ed6e2d833630f7984646a7ddd2a6a90bdb..b257780fb380a7592b46f84a393209dc66f2edac 100644 (file)
@@ -52,17 +52,16 @@ u8 regmask[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
 struct af9005_device_state {
        u8 sequence;
        int led_state;
+       unsigned char data[256];
+       struct mutex data_mutex;
 };
 
 static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
                              int readwrite, int type, u8 * values, int len)
 {
        struct af9005_device_state *st = d->priv;
-       u8 obuf[16] = { 0 };
-       u8 ibuf[17] = { 0 };
-       u8 command;
-       int i;
-       int ret;
+       u8 command, seq;
+       int i, ret;
 
        if (len < 1) {
                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,
                return -EINVAL;
        }
 
-       obuf[0] = 14;           /* rest of buffer length low */
-       obuf[1] = 0;            /* rest of buffer length high */
+       mutex_lock(&st->data_mutex);
+       st->data[0] = 14;               /* rest of buffer length low */
+       st->data[1] = 0;                /* rest of buffer length high */
 
-       obuf[2] = AF9005_REGISTER_RW;   /* register operation */
-       obuf[3] = 12;           /* rest of buffer length */
+       st->data[2] = AF9005_REGISTER_RW;       /* register operation */
+       st->data[3] = 12;               /* rest of buffer length */
 
-       obuf[4] = st->sequence++;       /* sequence number */
+       st->data[4] = seq = st->sequence++;     /* sequence number */
 
-       obuf[5] = (u8) (reg >> 8);      /* register address */
-       obuf[6] = (u8) (reg & 0xff);
+       st->data[5] = (u8) (reg >> 8);  /* register address */
+       st->data[6] = (u8) (reg & 0xff);
 
        if (type == AF9005_OFDM_REG) {
                command = AF9005_CMD_OFDM_REG;
@@ -96,51 +96,52 @@ static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
        command |= readwrite;
        if (readwrite == AF9005_CMD_WRITE)
                for (i = 0; i < len; i++)
-                       obuf[8 + i] = values[i];
+                       st->data[8 + i] = values[i];
        else if (type == AF9005_TUNER_REG)
                /* read command for tuner, the first byte contains the i2c address */
-               obuf[8] = values[0];
-       obuf[7] = command;
+               st->data[8] = values[0];
+       st->data[7] = command;
 
-       ret = dvb_usb_generic_rw(d, obuf, 16, ibuf, 17, 0);
+       ret = dvb_usb_generic_rw(d, st->data, 16, st->data, 17, 0);
        if (ret)
-               return ret;
+               goto ret;
 
        /* sanity check */
-       if (ibuf[2] != AF9005_REGISTER_RW_ACK) {
+       if (st->data[2] != AF9005_REGISTER_RW_ACK) {
                err("generic read/write, wrong reply code.");
-               return -EIO;
+               ret = -EIO;
+               goto ret;
        }
-       if (ibuf[3] != 0x0d) {
+       if (st->data[3] != 0x0d) {
                err("generic read/write, wrong length in reply.");
-               return -EIO;
+               ret = -EIO;
+               goto ret;
        }
-       if (ibuf[4] != obuf[4]) {
+       if (st->data[4] != seq) {
                err("generic read/write, wrong sequence in reply.");
-               return -EIO;
+               ret = -EIO;
+               goto ret;
        }
        /*
-          Windows driver doesn't check these fields, in fact sometimes
-          the register in the reply is different that what has been sent
-
-          if (ibuf[5] != obuf[5] || ibuf[6] != obuf[6]) {
-          err("generic read/write, wrong register in reply.");
-          return -EIO;
-          }
-          if (ibuf[7] != command) {
-          err("generic read/write wrong command in reply.");
-          return -EIO;
-          }
+        * In thesis, both input and output buffers should have
+        * identical values for st->data[5] to st->data[8].
+        * However, windows driver doesn't check these fields, in fact
+        * sometimes the register in the reply is different that what
+        * has been sent
         */
-       if (ibuf[16] != 0x01) {
+       if (st->data[16] != 0x01) {
                err("generic read/write wrong status code in reply.");
-               return -EIO;
+               ret = -EIO;
+               goto ret;
        }
+
        if (readwrite == AF9005_CMD_READ)
                for (i = 0; i < len; i++)
-                       values[i] = ibuf[8 + i];
+                       values[i] = st->data[8 + i];
 
-       return 0;
+ret:
+       mutex_unlock(&st->data_mutex);
+       return ret;
 
 }
 
@@ -464,8 +465,7 @@ int af9005_send_command(struct dvb_usb_device *d, u8 command, u8 * wbuf,
        struct af9005_device_state *st = d->priv;
 
        int ret, i, packet_len;
-       u8 buf[64];
-       u8 ibuf[64];
+       u8 seq;
 
        if (wlen < 0) {
                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,
                return -EINVAL;
        }
        packet_len = wlen + 5;
-       buf[0] = (u8) (packet_len & 0xff);
-       buf[1] = (u8) ((packet_len & 0xff00) >> 8);
-
-       buf[2] = 0x26;          /* packet type */
-       buf[3] = wlen + 3;
-       buf[4] = st->sequence++;
-       buf[5] = command;
-       buf[6] = wlen;
+
+       mutex_lock(&st->data_mutex);
+
+       st->data[0] = (u8) (packet_len & 0xff);
+       st->data[1] = (u8) ((packet_len & 0xff00) >> 8);
+
+       st->data[2] = 0x26;             /* packet type */
+       st->data[3] = wlen + 3;
+       st->data[4] = seq = st->sequence++;
+       st->data[5] = command;
+       st->data[6] = wlen;
        for (i = 0; i < wlen; i++)
-               buf[7 + i] = wbuf[i];
-       ret = dvb_usb_generic_rw(d, buf, wlen + 7, ibuf, rlen + 7, 0);
-       if (ret)
-               return ret;
-       if (ibuf[2] != 0x27) {
+               st->data[7 + i] = wbuf[i];
+       ret = dvb_usb_generic_rw(d, st->data, wlen + 7, st->data, rlen + 7, 0);
+       if (st->data[2] != 0x27) {
                err("send command, wrong reply code.");
-               return -EIO;
-       }
-       if (ibuf[4] != buf[4]) {
+               ret = -EIO;
+       } else if (st->data[4] != seq) {
                err("send command, wrong sequence in reply.");
-               return -EIO;
-       }
-       if (ibuf[5] != 0x01) {
+               ret = -EIO;
+       } else if (st->data[5] != 0x01) {
                err("send command, wrong status code in reply.");
-               return -EIO;
-       }
-       if (ibuf[6] != rlen) {
+               ret = -EIO;
+       } else if (st->data[6] != rlen) {
                err("send command, invalid data length in reply.");
-               return -EIO;
+               ret = -EIO;
        }
-       for (i = 0; i < rlen; i++)
-               rbuf[i] = ibuf[i + 7];
-       return 0;
+       if (!ret) {
+               for (i = 0; i < rlen; i++)
+                       rbuf[i] = st->data[i + 7];
+       }
+
+       mutex_unlock(&st->data_mutex);
+       return ret;
 }
 
 int af9005_read_eeprom(struct dvb_usb_device *d, u8 address, u8 * values,
                       int len)
 {
        struct af9005_device_state *st = d->priv;
-       u8 obuf[16], ibuf[14];
+       u8 seq;
        int ret, i;
 
-       memset(obuf, 0, sizeof(obuf));
-       memset(ibuf, 0, sizeof(ibuf));
+       mutex_lock(&st->data_mutex);
 
-       obuf[0] = 14;           /* length of rest of packet low */
-       obuf[1] = 0;            /* length of rest of packer high */
+       memset(st->data, 0, sizeof(st->data));
 
-       obuf[2] = 0x2a;         /* read/write eeprom */
+       st->data[0] = 14;               /* length of rest of packet low */
+       st->data[1] = 0;                /* length of rest of packer high */
 
-       obuf[3] = 12;           /* size */
+       st->data[2] = 0x2a;             /* read/write eeprom */
 
-       obuf[4] = st->sequence++;
+       st->data[3] = 12;               /* size */
 
-       obuf[5] = 0;            /* read */
+       st->data[4] = seq = st->sequence++;
 
-       obuf[6] = len;
-       obuf[7] = address;
-       ret = dvb_usb_generic_rw(d, obuf, 16, ibuf, 14, 0);
-       if (ret)
-               return ret;
-       if (ibuf[2] != 0x2b) {
+       st->data[5] = 0;                /* read */
+
+       st->data[6] = len;
+       st->data[7] = address;
+       ret = dvb_usb_generic_rw(d, st->data, 16, st->data, 14, 0);
+       if (st->data[2] != 0x2b) {
                err("Read eeprom, invalid reply code");
-               return -EIO;
-       }
-       if (ibuf[3] != 10) {
+               ret = -EIO;
+       } else if (st->data[3] != 10) {
                err("Read eeprom, invalid reply length");
-               return -EIO;
-       }
-       if (ibuf[4] != obuf[4]) {
+               ret = -EIO;
+       } else if (st->data[4] != seq) {
                err("Read eeprom, wrong sequence in reply ");
-               return -EIO;
-       }
-       if (ibuf[5] != 1) {
+               ret = -EIO;
+       } else if (st->data[5] != 1) {
                err("Read eeprom, wrong status in reply ");
-               return -EIO;
+               ret = -EIO;
        }
-       for (i = 0; i < len; i++) {
-               values[i] = ibuf[6 + i];
+
+       if (!ret) {
+               for (i = 0; i < len; i++)
+                       values[i] = st->data[6 + i];
        }
-       return 0;
+       mutex_unlock(&st->data_mutex);
+
+       return ret;
 }
 
-static int af9005_boot_packet(struct usb_device *udev, int type, u8 * reply)
+static int af9005_boot_packet(struct usb_device *udev, int type, u8 *reply,
+                             u8 *buf, int size)
 {
-       u8 buf[FW_BULKOUT_SIZE + 2];
        u16 checksum;
        int act_len, i, ret;
-       memset(buf, 0, sizeof(buf));
+
+       memset(buf, 0, size);
        buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff);
        buf[1] = (u8) ((FW_BULKOUT_SIZE >> 8) & 0xff);
        switch (type) {
@@ -720,15 +723,21 @@ static int af9005_download_firmware(struct usb_device *udev, const struct firmwa
 {
        int i, packets, ret, act_len;
 
-       u8 buf[FW_BULKOUT_SIZE + 2];
+       u8 *buf;
        u8 reply;
 
-       ret = af9005_boot_packet(udev, FW_CONFIG, &reply);
+       buf = kmalloc(FW_BULKOUT_SIZE + 2, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       ret = af9005_boot_packet(udev, FW_CONFIG, &reply, buf,
+                                FW_BULKOUT_SIZE + 2);
        if (ret)
-               return ret;
+               goto err;
        if (reply != 0x01) {
                err("before downloading firmware, FW_CONFIG expected 0x01, received 0x%x", reply);
-               return -EIO;
+               ret = -EIO;
+               goto err;
        }
        packets = fw->size / FW_BULKOUT_SIZE;
        buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff);
@@ -743,28 +752,35 @@ static int af9005_download_firmware(struct usb_device *udev, const struct firmwa
                                   buf, FW_BULKOUT_SIZE + 2, &act_len, 1000);
                if (ret) {
                        err("firmware download failed at packet %d with code %d", i, ret);
-                       return ret;
+                       goto err;
                }
        }
-       ret = af9005_boot_packet(udev, FW_CONFIRM, &reply);
+       ret = af9005_boot_packet(udev, FW_CONFIRM, &reply,
+                                buf, FW_BULKOUT_SIZE + 2);
        if (ret)
-               return ret;
+               goto err;
        if (reply != (u8) (packets & 0xff)) {
                err("after downloading firmware, FW_CONFIRM expected 0x%x, received 0x%x", packets & 0xff, reply);
-               return -EIO;
+               ret = -EIO;
+               goto err;
        }
-       ret = af9005_boot_packet(udev, FW_BOOT, &reply);
+       ret = af9005_boot_packet(udev, FW_BOOT, &reply, buf,
+                                FW_BULKOUT_SIZE + 2);
        if (ret)
-               return ret;
-       ret = af9005_boot_packet(udev, FW_CONFIG, &reply);
+               goto err;
+       ret = af9005_boot_packet(udev, FW_CONFIG, &reply, buf,
+                                FW_BULKOUT_SIZE + 2);
        if (ret)
-               return ret;
+               goto err;
        if (reply != 0x02) {
                err("after downloading firmware, FW_CONFIG expected 0x02, received 0x%x", reply);
-               return -EIO;
+               ret = -EIO;
+               goto err;
        }
 
-       return 0;
+err:
+       kfree(buf);
+       return ret;
 
 }
 
@@ -823,53 +839,59 @@ static int af9005_rc_query(struct dvb_usb_device *d, u32 * event, int *state)
 {
        struct af9005_device_state *st = d->priv;
        int ret, len;
-
-       u8 obuf[5];
-       u8 ibuf[256];
+       u8 seq;
 
        *state = REMOTE_NO_KEY_PRESSED;
        if (rc_decode == NULL) {
                /* it shouldn't never come here */
                return 0;
        }
+
+       mutex_lock(&st->data_mutex);
+
        /* deb_info("rc_query\n"); */
-       obuf[0] = 3;            /* rest of packet length low */
-       obuf[1] = 0;            /* rest of packet lentgh high */
-       obuf[2] = 0x40;         /* read remote */
-       obuf[3] = 1;            /* rest of packet length */
-       obuf[4] = st->sequence++;       /* sequence number */
-       ret = dvb_usb_generic_rw(d, obuf, 5, ibuf, 256, 0);
+       st->data[0] = 3;                /* rest of packet length low */
+       st->data[1] = 0;                /* rest of packet lentgh high */
+       st->data[2] = 0x40;             /* read remote */
+       st->data[3] = 1;                /* rest of packet length */
+       st->data[4] = seq = st->sequence++;     /* sequence number */
+       ret = dvb_usb_generic_rw(d, st->data, 5, st->data, 256, 0);
        if (ret) {
                err("rc query failed");
-               return ret;
+               goto ret;
        }
-       if (ibuf[2] != 0x41) {
+       if (st->data[2] != 0x41) {
                err("rc query bad header.");
-               return -EIO;
-       }
-       if (ibuf[4] != obuf[4]) {
+               ret = -EIO;
+               goto ret;
+       } else if (st->data[4] != seq) {
                err("rc query bad sequence.");
-               return -EIO;
+               ret = -EIO;
+               goto ret;
        }
-       len = ibuf[5];
+       len = st->data[5];
        if (len > 246) {
                err("rc query invalid length");
-               return -EIO;
+               ret = -EIO;
+               goto ret;
        }
        if (len > 0) {
                deb_rc("rc data (%d) ", len);
-               debug_dump((ibuf + 6), len, deb_rc);
-               ret = rc_decode(d, &ibuf[6], len, event, state);
+               debug_dump((st->data + 6), len, deb_rc);
+               ret = rc_decode(d, &st->data[6], len, event, state);
                if (ret) {
                        err("rc_decode failed");
-                       return ret;
+                       goto ret;
                } else {
                        deb_rc("rc_decode state %x event %x\n", *state, *event);
                        if (*state == REMOTE_KEY_REPEAT)
                                *event = d->last_event;
                }
        }
-       return 0;
+
+ret:
+       mutex_unlock(&st->data_mutex);
+       return ret;
 }
 
 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,
                                 int *cold)
 {
        int ret;
-       u8 reply;
-       ret = af9005_boot_packet(udev, FW_CONFIG, &reply);
+       u8 reply, *buf;
+
+       buf = kmalloc(FW_BULKOUT_SIZE + 2, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       ret = af9005_boot_packet(udev, FW_CONFIG, &reply,
+                                buf, FW_BULKOUT_SIZE + 2);
        if (ret)
-               return ret;
+               goto err;
        deb_info("result of FW_CONFIG in identify state %d\n", reply);
        if (reply == 0x01)
                *cold = 1;
@@ -965,7 +993,10 @@ static int af9005_identify_state(struct usb_device *udev,
        else
                return -EIO;
        deb_info("Identify state cold = %d\n", *cold);
-       return 0;
+
+err:
+       kfree(buf);
+       return ret;
 }
 
 static struct dvb_usb_device_properties af9005_properties;
@@ -973,8 +1004,20 @@ static struct dvb_usb_device_properties af9005_properties;
 static int af9005_usb_probe(struct usb_interface *intf,
                            const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf, &af9005_properties,
-                                  THIS_MODULE, NULL, adapter_nr);
+       struct dvb_usb_device *d;
+       struct af9005_device_state *st;
+       int ret;
+
+       ret = dvb_usb_device_init(intf, &af9005_properties,
+                                 THIS_MODULE, &d, adapter_nr);
+
+       if (ret < 0)
+               return ret;
+
+       st = d->priv;
+       mutex_init(&st->data_mutex);
+
+       return 0;
 }
 
 enum af9005_usb_table_entry {
index 9fd1527494ebd65ab200c38f13a20e28330034a1..8ac825413d5ac09a17f33f9a6537e0cd69e4564c 100644 (file)
@@ -41,6 +41,8 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 struct cinergyt2_state {
        u8 rc_counter;
+       unsigned char data[64];
+       struct mutex data_mutex;
 };
 
 /* We are missing a release hook with usb_device data */
@@ -50,38 +52,57 @@ static struct dvb_usb_device_properties cinergyt2_properties;
 
 static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable)
 {
-       char buf[] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 };
-       char result[64];
-       return dvb_usb_generic_rw(adap->dev, buf, sizeof(buf), result,
-                               sizeof(result), 0);
+       struct dvb_usb_device *d = adap->dev;
+       struct cinergyt2_state *st = d->priv;
+       int ret;
+
+       mutex_lock(&st->data_mutex);
+       st->data[0] = CINERGYT2_EP1_CONTROL_STREAM_TRANSFER;
+       st->data[1] = enable ? 1 : 0;
+
+       ret = dvb_usb_generic_rw(d, st->data, 2, st->data, 64, 0);
+       mutex_unlock(&st->data_mutex);
+
+       return ret;
 }
 
 static int cinergyt2_power_ctrl(struct dvb_usb_device *d, int enable)
 {
-       char buf[] = { CINERGYT2_EP1_SLEEP_MODE, enable ? 0 : 1 };
-       char state[3];
-       return dvb_usb_generic_rw(d, buf, sizeof(buf), state, sizeof(state), 0);
+       struct cinergyt2_state *st = d->priv;
+       int ret;
+
+       mutex_lock(&st->data_mutex);
+       st->data[0] = CINERGYT2_EP1_SLEEP_MODE;
+       st->data[1] = enable ? 0 : 1;
+
+       ret = dvb_usb_generic_rw(d, st->data, 2, st->data, 3, 0);
+       mutex_unlock(&st->data_mutex);
+
+       return ret;
 }
 
 static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap)
 {
-       char query[] = { CINERGYT2_EP1_GET_FIRMWARE_VERSION };
-       char state[3];
+       struct dvb_usb_device *d = adap->dev;
+       struct cinergyt2_state *st = d->priv;
        int ret;
 
        adap->fe_adap[0].fe = cinergyt2_fe_attach(adap->dev);
 
-       ret = dvb_usb_generic_rw(adap->dev, query, sizeof(query), state,
-                               sizeof(state), 0);
+       mutex_lock(&st->data_mutex);
+       st->data[0] = CINERGYT2_EP1_GET_FIRMWARE_VERSION;
+
+       ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 3, 0);
        if (ret < 0) {
                deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep "
                        "state info\n");
        }
+       mutex_unlock(&st->data_mutex);
 
        /* Copy this pointer as we are gonna need it in the release phase */
        cinergyt2_usb_device = adap->dev;
 
-       return 0;
+       return ret;
 }
 
 static struct rc_map_table rc_map_cinergyt2_table[] = {
@@ -141,13 +162,18 @@ static int repeatable_keys[] = {
 static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
        struct cinergyt2_state *st = d->priv;
-       u8 key[5] = {0, 0, 0, 0, 0}, cmd = CINERGYT2_EP1_GET_RC_EVENTS;
-       int i;
+       int i, ret;
 
        *state = REMOTE_NO_KEY_PRESSED;
 
-       dvb_usb_generic_rw(d, &cmd, 1, key, sizeof(key), 0);
-       if (key[4] == 0xff) {
+       mutex_lock(&st->data_mutex);
+       st->data[0] = CINERGYT2_EP1_GET_RC_EVENTS;
+
+       ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 5, 0);
+       if (ret < 0)
+               goto ret;
+
+       if (st->data[4] == 0xff) {
                /* key repeat */
                st->rc_counter++;
                if (st->rc_counter > RC_REPEAT_DELAY) {
@@ -157,31 +183,45 @@ static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
                                        *event = d->last_event;
                                        deb_rc("repeat key, event %x\n",
                                                   *event);
-                                       return 0;
+                                       goto ret;
                                }
                        }
                        deb_rc("repeated key (non repeatable)\n");
                }
-               return 0;
+               goto ret;
        }
 
        /* hack to pass checksum on the custom field */
-       key[2] = ~key[1];
-       dvb_usb_nec_rc_key_to_event(d, key, event, state);
-       if (key[0] != 0) {
+       st->data[2] = ~st->data[1];
+       dvb_usb_nec_rc_key_to_event(d, st->data, event, state);
+       if (st->data[0] != 0) {
                if (*event != d->last_event)
                        st->rc_counter = 0;
 
-               deb_rc("key: %*ph\n", 5, key);
+               deb_rc("key: %*ph\n", 5, st->data);
        }
-       return 0;
+
+ret:
+       mutex_unlock(&st->data_mutex);
+       return ret;
 }
 
 static int cinergyt2_usb_probe(struct usb_interface *intf,
                                const struct usb_device_id *id)
 {
-       return dvb_usb_device_init(intf, &cinergyt2_properties,
-                                       THIS_MODULE, NULL, adapter_nr);
+       struct dvb_usb_device *d;
+       struct cinergyt2_state *st;
+       int ret;
+
+       ret = dvb_usb_device_init(intf, &cinergyt2_properties,
+                                 THIS_MODULE, &d, adapter_nr);
+       if (ret < 0)
+               return ret;
+
+       st = d->priv;
+       mutex_init(&st->data_mutex);
+
+       return 0;
 }
 
 
index b3ec743a7a2e6816eafa6d8f20a128eaabead3c4..2d29b4174dba0e94977aa988e6a309704898af6d 100644 (file)
@@ -139,32 +139,42 @@ static uint16_t compute_tps(struct dtv_frontend_properties *op)
 struct cinergyt2_fe_state {
        struct dvb_frontend fe;
        struct dvb_usb_device *d;
+
+       unsigned char data[64];
+       struct mutex data_mutex;
+
+       struct dvbt_get_status_msg status;
 };
 
 static int cinergyt2_fe_read_status(struct dvb_frontend *fe,
                                    enum fe_status *status)
 {
        struct cinergyt2_fe_state *state = fe->demodulator_priv;
-       struct dvbt_get_status_msg result;
-       u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
        int ret;
 
-       ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&result,
-                       sizeof(result), 0);
+       mutex_lock(&state->data_mutex);
+       state->data[0] = CINERGYT2_EP1_GET_TUNER_STATUS;
+
+       ret = dvb_usb_generic_rw(state->d, state->data, 1,
+                                state->data, sizeof(state->status), 0);
+       if (!ret)
+               memcpy(&state->status, state->data, sizeof(state->status));
+       mutex_unlock(&state->data_mutex);
+
        if (ret < 0)
                return ret;
 
        *status = 0;
 
-       if (0xffff - le16_to_cpu(result.gain) > 30)
+       if (0xffff - le16_to_cpu(state->status.gain) > 30)
                *status |= FE_HAS_SIGNAL;
-       if (result.lock_bits & (1 << 6))
+       if (state->status.lock_bits & (1 << 6))
                *status |= FE_HAS_LOCK;
-       if (result.lock_bits & (1 << 5))
+       if (state->status.lock_bits & (1 << 5))
                *status |= FE_HAS_SYNC;
-       if (result.lock_bits & (1 << 4))
+       if (state->status.lock_bits & (1 << 4))
                *status |= FE_HAS_CARRIER;
-       if (result.lock_bits & (1 << 1))
+       if (state->status.lock_bits & (1 << 1))
                *status |= FE_HAS_VITERBI;
 
        if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) !=
@@ -177,34 +187,16 @@ static int cinergyt2_fe_read_status(struct dvb_frontend *fe,
 static int cinergyt2_fe_read_ber(struct dvb_frontend *fe, u32 *ber)
 {
        struct cinergyt2_fe_state *state = fe->demodulator_priv;
-       struct dvbt_get_status_msg status;
-       char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
-       int ret;
-
-       ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status,
-                               sizeof(status), 0);
-       if (ret < 0)
-               return ret;
 
-       *ber = le32_to_cpu(status.viterbi_error_rate);
+       *ber = le32_to_cpu(state->status.viterbi_error_rate);
        return 0;
 }
 
 static int cinergyt2_fe_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
 {
        struct cinergyt2_fe_state *state = fe->demodulator_priv;
-       struct dvbt_get_status_msg status;
-       u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
-       int ret;
 
-       ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&status,
-                               sizeof(status), 0);
-       if (ret < 0) {
-               err("cinergyt2_fe_read_unc_blocks() Failed! (Error=%d)\n",
-                       ret);
-               return ret;
-       }
-       *unc = le32_to_cpu(status.uncorrected_block_count);
+       *unc = le32_to_cpu(state->status.uncorrected_block_count);
        return 0;
 }
 
@@ -212,35 +204,16 @@ static int cinergyt2_fe_read_signal_strength(struct dvb_frontend *fe,
                                                u16 *strength)
 {
        struct cinergyt2_fe_state *state = fe->demodulator_priv;
-       struct dvbt_get_status_msg status;
-       char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
-       int ret;
 
-       ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status,
-                               sizeof(status), 0);
-       if (ret < 0) {
-               err("cinergyt2_fe_read_signal_strength() Failed!"
-                       " (Error=%d)\n", ret);
-               return ret;
-       }
-       *strength = (0xffff - le16_to_cpu(status.gain));
+       *strength = (0xffff - le16_to_cpu(state->status.gain));
        return 0;
 }
 
 static int cinergyt2_fe_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
        struct cinergyt2_fe_state *state = fe->demodulator_priv;
-       struct dvbt_get_status_msg status;
-       char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
-       int ret;
 
-       ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status,
-                               sizeof(status), 0);
-       if (ret < 0) {
-               err("cinergyt2_fe_read_snr() Failed! (Error=%d)\n", ret);
-               return ret;
-       }
-       *snr = (status.snr << 8) | status.snr;
+       *snr = (state->status.snr << 8) | state->status.snr;
        return 0;
 }
 
@@ -266,34 +239,36 @@ static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe)
 {
        struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
        struct cinergyt2_fe_state *state = fe->demodulator_priv;
-       struct dvbt_set_parameters_msg param;
-       char result[2];
+       struct dvbt_set_parameters_msg *param;
        int err;
 
-       param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
-       param.tps = cpu_to_le16(compute_tps(fep));
-       param.freq = cpu_to_le32(fep->frequency / 1000);
-       param.flags = 0;
+       mutex_lock(&state->data_mutex);
+
+       param = (void *)state->data;
+       param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
+       param->tps = cpu_to_le16(compute_tps(fep));
+       param->freq = cpu_to_le32(fep->frequency / 1000);
+       param->flags = 0;
 
        switch (fep->bandwidth_hz) {
        default:
        case 8000000:
-               param.bandwidth = 8;
+               param->bandwidth = 8;
                break;
        case 7000000:
-               param.bandwidth = 7;
+               param->bandwidth = 7;
                break;
        case 6000000:
-               param.bandwidth = 6;
+               param->bandwidth = 6;
                break;
        }
 
-       err = dvb_usb_generic_rw(state->d,
-                       (char *)&param, sizeof(param),
-                       result, sizeof(result), 0);
+       err = dvb_usb_generic_rw(state->d, state->data, sizeof(*param),
+                                state->data, 2, 0);
        if (err < 0)
                err("cinergyt2_fe_set_frontend() Failed! err=%d\n", err);
 
+       mutex_unlock(&state->data_mutex);
        return (err < 0) ? err : 0;
 }
 
@@ -315,6 +290,7 @@ struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d)
        s->d = d;
        memcpy(&s->fe.ops, &cinergyt2_fe_ops, sizeof(struct dvb_frontend_ops));
        s->fe.demodulator_priv = s;
+       mutex_init(&s->data_mutex);
        return &s->fe;
 }
 
index 907ac01ae2979a56657e6ddc32fafecfbb9c9042..39772812269dc81845d85954d1c52f2f3cc429e0 100644 (file)
@@ -45,9 +45,6 @@
 #include "si2168.h"
 #include "si2157.h"
 
-/* Max transfer size done by I2C transfer functions */
-#define MAX_XFER_SIZE  80
-
 /* debug */
 static int dvb_usb_cxusb_debug;
 module_param_named(debug, dvb_usb_cxusb_debug, int, 0644);
@@ -61,23 +58,27 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 static int cxusb_ctrl_msg(struct dvb_usb_device *d,
                          u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
 {
-       int wo = (rbuf == NULL || rlen == 0); /* write-only */
-       u8 sndbuf[MAX_XFER_SIZE];
+       struct cxusb_state *st = d->priv;
+       int ret, wo;
 
-       if (1 + wlen > sizeof(sndbuf)) {
-               warn("i2c wr: len=%d is too big!\n",
-                    wlen);
+       if (1 + wlen > MAX_XFER_SIZE) {
+               warn("i2c wr: len=%d is too big!\n", wlen);
                return -EOPNOTSUPP;
        }
 
-       memset(sndbuf, 0, 1+wlen);
+       wo = (rbuf == NULL || rlen == 0); /* write-only */
 
-       sndbuf[0] = cmd;
-       memcpy(&sndbuf[1], wbuf, wlen);
+       mutex_lock(&st->data_mutex);
+       st->data[0] = cmd;
+       memcpy(&st->data[1], wbuf, wlen);
        if (wo)
-               return dvb_usb_generic_write(d, sndbuf, 1+wlen);
+               ret = dvb_usb_generic_write(d, st->data, 1 + wlen);
        else
-               return dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0);
+               ret = dvb_usb_generic_rw(d, st->data, 1 + wlen,
+                                        rbuf, rlen, 0);
+
+       mutex_unlock(&st->data_mutex);
+       return ret;
 }
 
 /* GPIO */
@@ -1460,36 +1461,43 @@ static struct dvb_usb_device_properties cxusb_mygica_t230_properties;
 static int cxusb_probe(struct usb_interface *intf,
                       const struct usb_device_id *id)
 {
+       struct dvb_usb_device *d;
+       struct cxusb_state *st;
+
        if (0 == dvb_usb_device_init(intf, &cxusb_medion_properties,
-                                    THIS_MODULE, NULL, adapter_nr) ||
+                                    THIS_MODULE, &d, adapter_nr) ||
            0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgh064f_properties,
-                                    THIS_MODULE, NULL, adapter_nr) ||
+                                    THIS_MODULE, &d, adapter_nr) ||
            0 == dvb_usb_device_init(intf, &cxusb_bluebird_dee1601_properties,
-                                    THIS_MODULE, NULL, adapter_nr) ||
+                                    THIS_MODULE, &d, adapter_nr) ||
            0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgz201_properties,
-                                    THIS_MODULE, NULL, adapter_nr) ||
+                                    THIS_MODULE, &d, adapter_nr) ||
            0 == dvb_usb_device_init(intf, &cxusb_bluebird_dtt7579_properties,
-                                    THIS_MODULE, NULL, adapter_nr) ||
+                                    THIS_MODULE, &d, adapter_nr) ||
            0 == dvb_usb_device_init(intf, &cxusb_bluebird_dualdig4_properties,
-                                    THIS_MODULE, NULL, adapter_nr) ||
+                                    THIS_MODULE, &d, adapter_nr) ||
            0 == dvb_usb_device_init(intf, &cxusb_bluebird_nano2_properties,
-                                    THIS_MODULE, NULL, adapter_nr) ||
+                                    THIS_MODULE, &d, adapter_nr) ||
            0 == dvb_usb_device_init(intf,
                                &cxusb_bluebird_nano2_needsfirmware_properties,
-                                    THIS_MODULE, NULL, adapter_nr) ||
+                                    THIS_MODULE, &d, adapter_nr) ||
            0 == dvb_usb_device_init(intf, &cxusb_aver_a868r_properties,
-                                    THIS_MODULE, NULL, adapter_nr) ||
+                                    THIS_MODULE, &d, adapter_nr) ||
            0 == dvb_usb_device_init(intf,
                                     &cxusb_bluebird_dualdig4_rev2_properties,
-                                    THIS_MODULE, NULL, adapter_nr) ||
+                                    THIS_MODULE, &d, adapter_nr) ||
            0 == dvb_usb_device_init(intf, &cxusb_d680_dmb_properties,
-                                    THIS_MODULE, NULL, adapter_nr) ||
+                                    THIS_MODULE, &d, adapter_nr) ||
            0 == dvb_usb_device_init(intf, &cxusb_mygica_d689_properties,
-                                    THIS_MODULE, NULL, adapter_nr) ||
+                                    THIS_MODULE, &d, adapter_nr) ||
            0 == dvb_usb_device_init(intf, &cxusb_mygica_t230_properties,
-                                    THIS_MODULE, NULL, adapter_nr) ||
-           0)
+                                    THIS_MODULE, &d, adapter_nr) ||
+           0) {
+               st = d->priv;
+               mutex_init(&st->data_mutex);
+
                return 0;
+       }
 
        return -EINVAL;
 }
index 527ff7905e1590961b64b8edd3b62b859a9f903a..9f3ee0e47d5c63be2be07af579be384d65b3a80c 100644 (file)
 #define CMD_ANALOG        0x50
 #define CMD_DIGITAL       0x51
 
+/* Max transfer size done by I2C transfer functions */
+#define MAX_XFER_SIZE  80
+
 struct cxusb_state {
        u8 gpio_write_state[3];
        struct i2c_client *i2c_client_demod;
        struct i2c_client *i2c_client_tuner;
+
+       unsigned char data[MAX_XFER_SIZE];
+       struct mutex data_mutex;
 };
 
 #endif
index f3196658fb700706e12b61fd8b0951d25c2f1152..92d5408684ac1cdc33f65f578b5ee2ce525968b0 100644 (file)
@@ -213,7 +213,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
                                                 usb_rcvctrlpipe(d->udev, 0),
                                                 REQUEST_NEW_I2C_READ,
                                                 USB_TYPE_VENDOR | USB_DIR_IN,
-                                                value, index, msg[i].buf,
+                                                value, index, st->buf,
                                                 msg[i].len,
                                                 USB_CTRL_GET_TIMEOUT);
                        if (result < 0) {
@@ -221,6 +221,14 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
                                break;
                        }
 
+                       if (msg[i].len > sizeof(st->buf)) {
+                               deb_info("buffer too small to fit %d bytes\n",
+                                        msg[i].len);
+                               return -EIO;
+                       }
+
+                       memcpy(msg[i].buf, st->buf, msg[i].len);
+
                        deb_data("<<< ");
                        debug_dump(msg[i].buf, msg[i].len, deb_data);
 
@@ -238,6 +246,13 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
                        /* I2C ctrl + FE bus; */
                        st->buf[3] = ((gen_mode << 6) & 0xC0) |
                                 ((bus_mode << 4) & 0x30);
+
+                       if (msg[i].len > sizeof(st->buf) - 4) {
+                               deb_info("i2c message to big: %d\n",
+                                        msg[i].len);
+                               return -EIO;
+                       }
+
                        /* The Actual i2c payload */
                        memcpy(&st->buf[4], msg[i].buf, msg[i].len);
 
@@ -283,6 +298,11 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
                /* fill in the address */
                st->buf[1] = msg[i].addr << 1;
                /* fill the buffer */
+               if (msg[i].len > sizeof(st->buf) - 2) {
+                       deb_info("i2c xfer to big: %d\n",
+                               msg[i].len);
+                       return -EIO;
+               }
                memcpy(&st->buf[2], msg[i].buf, msg[i].len);
 
                /* write/read request */
@@ -292,13 +312,20 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
 
                        /* special thing in the current firmware: when length is zero the read-failed */
                        len = dib0700_ctrl_rd(d, st->buf, msg[i].len + 2,
-                                       msg[i+1].buf, msg[i+1].len);
+                                             st->buf, msg[i + 1].len);
                        if (len <= 0) {
                                deb_info("I2C read failed on address 0x%02x\n",
                                                msg[i].addr);
                                break;
                        }
 
+                       if (msg[i + 1].len > sizeof(st->buf)) {
+                               deb_info("i2c xfer buffer to small for %d\n",
+                                       msg[i].len);
+                               return -EIO;
+                       }
+                       memcpy(msg[i + 1].buf, st->buf, msg[i + 1].len);
+
                        msg[i+1].len = len;
 
                        i++;
index 0857b56e652cf96515d34b890ff65693c5936507..ef1b8ee75c577f00c61b07b80859ef063722d907 100644 (file)
@@ -508,8 +508,6 @@ static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap)
 
 #define DEFAULT_RC_INTERVAL 50
 
-static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
-
 /*
  * This function is used only when firmware is < 1.20 version. Newer
  * firmwares use bulk mode, with functions implemented at dib0700_core,
@@ -517,7 +515,6 @@ static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
  */
 static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)
 {
-       u8 key[4];
        enum rc_type protocol;
        u32 scancode;
        u8 toggle;
@@ -532,39 +529,43 @@ static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)
                return 0;
        }
 
-       i = dib0700_ctrl_rd(d, rc_request, 2, key, 4);
+       st->buf[0] = REQUEST_POLL_RC;
+       st->buf[1] = 0;
+
+       i = dib0700_ctrl_rd(d, st->buf, 2, st->buf, 4);
        if (i <= 0) {
                err("RC Query Failed");
-               return -1;
+               return -EIO;
        }
 
        /* losing half of KEY_0 events from Philipps rc5 remotes.. */
-       if (key[0] == 0 && key[1] == 0 && key[2] == 0 && key[3] == 0)
+       if (st->buf[0] == 0 && st->buf[1] == 0
+           && st->buf[2] == 0 && st->buf[3] == 0)
                return 0;
 
-       /* info("%d: %2X %2X %2X %2X",dvb_usb_dib0700_ir_proto,(int)key[3-2],(int)key[3-3],(int)key[3-1],(int)key[3]);  */
+       /* info("%d: %2X %2X %2X %2X",dvb_usb_dib0700_ir_proto,(int)st->buf[3 - 2],(int)st->buf[3 - 3],(int)st->buf[3 - 1],(int)st->buf[3]);  */
 
        dib0700_rc_setup(d, NULL); /* reset ir sensor data to prevent false events */
 
        switch (d->props.rc.core.protocol) {
        case RC_BIT_NEC:
                /* NEC protocol sends repeat code as 0 0 0 FF */
-               if ((key[3-2] == 0x00) && (key[3-3] == 0x00) &&
-                   (key[3] == 0xff)) {
+               if ((st->buf[3 - 2] == 0x00) && (st->buf[3 - 3] == 0x00) &&
+                   (st->buf[3] == 0xff)) {
                        rc_repeat(d->rc_dev);
                        return 0;
                }
 
                protocol = RC_TYPE_NEC;
-               scancode = RC_SCANCODE_NEC(key[3-2], key[3-3]);
+               scancode = RC_SCANCODE_NEC(st->buf[3 - 2], st->buf[3 - 3]);
                toggle = 0;
                break;
 
        default:
                /* RC-5 protocol changes toggle bit on new keypress */
                protocol = RC_TYPE_RC5;
-               scancode = RC_SCANCODE_RC5(key[3-2], key[3-3]);
-               toggle = key[3-1];
+               scancode = RC_SCANCODE_RC5(st->buf[3 - 2], st->buf[3 - 3]);
+               toggle = st->buf[3 - 1];
                break;
        }
 
index 18ed3bfbb5e2a95f5127b41d0e1f15cce01b1f07..de3ee2547479428cd1c14347db5332ea1090c60d 100644 (file)
@@ -62,72 +62,117 @@ EXPORT_SYMBOL(dibusb_pid_filter_ctrl);
 
 int dibusb_power_ctrl(struct dvb_usb_device *d, int onoff)
 {
-       u8 b[3];
+       u8 *b;
        int ret;
+
+       b = kmalloc(3, GFP_KERNEL);
+       if (!b)
+               return -ENOMEM;
+
        b[0] = DIBUSB_REQ_SET_IOCTL;
        b[1] = DIBUSB_IOCTL_CMD_POWER_MODE;
        b[2] = onoff ? DIBUSB_IOCTL_POWER_WAKEUP : DIBUSB_IOCTL_POWER_SLEEP;
-       ret = dvb_usb_generic_write(d,b,3);
+
+       ret = dvb_usb_generic_write(d, b, 3);
+
+       kfree(b);
+
        msleep(10);
+
        return ret;
 }
 EXPORT_SYMBOL(dibusb_power_ctrl);
 
 int dibusb2_0_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 {
-       u8 b[3] = { 0 };
        int ret;
+       u8 *b;
+
+       b = kmalloc(3, GFP_KERNEL);
+       if (!b)
+               return -ENOMEM;
 
        if ((ret = dibusb_streaming_ctrl(adap,onoff)) < 0)
-               return ret;
+               goto ret;
 
        if (onoff) {
                b[0] = DIBUSB_REQ_SET_STREAMING_MODE;
                b[1] = 0x00;
-               if ((ret = dvb_usb_generic_write(adap->dev,b,2)) < 0)
-                       return ret;
+               ret = dvb_usb_generic_write(adap->dev, b, 2);
+               if (ret  < 0)
+                       goto ret;
        }
 
        b[0] = DIBUSB_REQ_SET_IOCTL;
        b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM;
-       return dvb_usb_generic_write(adap->dev,b,3);
+       ret = dvb_usb_generic_write(adap->dev, b, 3);
+
+ret:
+       kfree(b);
+       return ret;
 }
 EXPORT_SYMBOL(dibusb2_0_streaming_ctrl);
 
 int dibusb2_0_power_ctrl(struct dvb_usb_device *d, int onoff)
 {
-       if (onoff) {
-               u8 b[3] = { DIBUSB_REQ_SET_IOCTL, DIBUSB_IOCTL_CMD_POWER_MODE, DIBUSB_IOCTL_POWER_WAKEUP };
-               return dvb_usb_generic_write(d,b,3);
-       } else
+       u8 *b;
+       int ret;
+
+       if (!onoff)
                return 0;
+
+       b = kmalloc(3, GFP_KERNEL);
+       if (!b)
+               return -ENOMEM;
+
+       b[0] = DIBUSB_REQ_SET_IOCTL;
+       b[1] = DIBUSB_IOCTL_CMD_POWER_MODE;
+       b[2] = DIBUSB_IOCTL_POWER_WAKEUP;
+
+       ret = dvb_usb_generic_write(d, b, 3);
+
+       kfree(b);
+
+       return ret;
 }
 EXPORT_SYMBOL(dibusb2_0_power_ctrl);
 
 static int dibusb_i2c_msg(struct dvb_usb_device *d, u8 addr,
                          u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
 {
-       u8 sndbuf[MAX_XFER_SIZE]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */
+       u8 *sndbuf;
+       int ret, wo, len;
+
        /* write only ? */
-       int wo = (rbuf == NULL || rlen == 0),
-               len = 2 + wlen + (wo ? 0 : 2);
+       wo = (rbuf == NULL || rlen == 0);
+
+       len = 2 + wlen + (wo ? 0 : 2);
+
+       sndbuf = kmalloc(MAX_XFER_SIZE, GFP_KERNEL);
+       if (!sndbuf)
+               return -ENOMEM;
 
-       if (4 + wlen > sizeof(sndbuf)) {
+       if (4 + wlen > MAX_XFER_SIZE) {
                warn("i2c wr: len=%d is too big!\n", wlen);
-               return -EOPNOTSUPP;
+               ret = -EOPNOTSUPP;
+               goto ret;
        }
 
        sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ;
        sndbuf[1] = (addr << 1) | (wo ? 0 : 1);
 
-       memcpy(&sndbuf[2],wbuf,wlen);
+       memcpy(&sndbuf[2], wbuf, wlen);
 
        if (!wo) {
-               sndbuf[wlen+2] = (rlen >> 8) & 0xff;
-               sndbuf[wlen+3] = rlen & 0xff;
+               sndbuf[wlen + 2] = (rlen >> 8) & 0xff;
+               sndbuf[wlen + 3] = rlen & 0xff;
        }
 
-       return dvb_usb_generic_rw(d,sndbuf,len,rbuf,rlen,0);
+       ret = dvb_usb_generic_rw(d, sndbuf, len, rbuf, rlen, 0);
+
+ret:
+       kfree(sndbuf);
+       return ret;
 }
 
 /*
@@ -319,11 +364,27 @@ EXPORT_SYMBOL(rc_map_dibusb_table);
 
 int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
-       u8 key[5],cmd = DIBUSB_REQ_POLL_REMOTE;
-       dvb_usb_generic_rw(d,&cmd,1,key,5,0);
-       dvb_usb_nec_rc_key_to_event(d,key,event,state);
-       if (key[0] != 0)
-               deb_info("key: %*ph\n", 5, key);
-       return 0;
+       u8 *buf;
+       int ret;
+
+       buf = kmalloc(5, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       buf[0] = DIBUSB_REQ_POLL_REMOTE;
+
+       ret = dvb_usb_generic_rw(d, buf, 1, buf, 5, 0);
+       if (ret < 0)
+               goto ret;
+
+       dvb_usb_nec_rc_key_to_event(d, buf, event, state);
+
+       if (buf[0] != 0)
+               deb_info("key: %*ph\n", 5, buf);
+
+       kfree(buf);
+
+ret:
+       return ret;
 }
 EXPORT_SYMBOL(dibusb_rc_query);
index 3f82163d8ab89061410bdff4b68bea2e1d153c27..697be2a17adef131b68a2f34a2401b2108174b68 100644 (file)
@@ -96,6 +96,9 @@
 #define DIBUSB_IOCTL_CMD_ENABLE_STREAM 0x01
 #define DIBUSB_IOCTL_CMD_DISABLE_STREAM        0x02
 
+/* Max transfer size done by I2C transfer functions */
+#define MAX_XFER_SIZE  64
+
 struct dibusb_state {
        struct dib_fe_xfer_ops ops;
        int mt2060_present;
index 63134335c99406ca7df3d284cd3ba95d4154cae3..4284f6984dc1ffe14698b6fcdc42aad8cf69bf32 100644 (file)
@@ -28,22 +28,26 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 static int digitv_ctrl_msg(struct dvb_usb_device *d,
                u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
 {
-       int wo = (rbuf == NULL || rlen == 0); /* write-only */
-       u8 sndbuf[7],rcvbuf[7];
-       memset(sndbuf,0,7); memset(rcvbuf,0,7);
+       struct digitv_state *st = d->priv;
+       int ret, wo;
 
-       sndbuf[0] = cmd;
-       sndbuf[1] = vv;
-       sndbuf[2] = wo ? wlen : rlen;
+       wo = (rbuf == NULL || rlen == 0); /* write-only */
+
+       memset(st->sndbuf, 0, 7);
+       memset(st->rcvbuf, 0, 7);
+
+       st->sndbuf[0] = cmd;
+       st->sndbuf[1] = vv;
+       st->sndbuf[2] = wo ? wlen : rlen;
 
        if (wo) {
-               memcpy(&sndbuf[3],wbuf,wlen);
-               dvb_usb_generic_write(d,sndbuf,7);
+               memcpy(&st->sndbuf[3], wbuf, wlen);
+               ret = dvb_usb_generic_write(d, st->sndbuf, 7);
        } else {
-               dvb_usb_generic_rw(d,sndbuf,7,rcvbuf,7,10);
-               memcpy(rbuf,&rcvbuf[3],rlen);
+               ret = dvb_usb_generic_rw(d, st->sndbuf, 7, st->rcvbuf, 7, 10);
+               memcpy(rbuf, &st->rcvbuf[3], rlen);
        }
-       return 0;
+       return ret;
 }
 
 /* I2C */
index 908c09f4966b89b8923569b35a5a2cbc3b8a6727..581e09c25491bfe54a683fbfd094a890c0351c4a 100644 (file)
@@ -5,7 +5,10 @@
 #include "dvb-usb.h"
 
 struct digitv_state {
-    int is_nxt6000;
+       int is_nxt6000;
+
+       unsigned char sndbuf[7];
+       unsigned char rcvbuf[7];
 };
 
 /* protocol (from usblogging and the SDK:
index c09332bd99cb7c5e41699e2a9d435c3072432277..f5c042baa254e0cf3be54eb759918161f82202b1 100644 (file)
@@ -18,17 +18,28 @@ struct dtt200u_fe_state {
 
        struct dtv_frontend_properties fep;
        struct dvb_frontend frontend;
+
+       unsigned char data[80];
+       struct mutex data_mutex;
 };
 
 static int dtt200u_fe_read_status(struct dvb_frontend *fe,
                                  enum fe_status *stat)
 {
        struct dtt200u_fe_state *state = fe->demodulator_priv;
-       u8 st = GET_TUNE_STATUS, b[3];
+       int ret;
+
+       mutex_lock(&state->data_mutex);
+       state->data[0] = GET_TUNE_STATUS;
 
-       dvb_usb_generic_rw(state->d,&st,1,b,3,0);
+       ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 3, 0);
+       if (ret < 0) {
+               *stat = 0;
+               mutex_unlock(&state->data_mutex);
+               return ret;
+       }
 
-       switch (b[0]) {
+       switch (state->data[0]) {
                case 0x01:
                        *stat = FE_HAS_SIGNAL | FE_HAS_CARRIER |
                                FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
@@ -41,51 +52,86 @@ static int dtt200u_fe_read_status(struct dvb_frontend *fe,
                        *stat = 0;
                        break;
        }
+       mutex_unlock(&state->data_mutex);
        return 0;
 }
 
 static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
 {
        struct dtt200u_fe_state *state = fe->demodulator_priv;
-       u8 bw = GET_VIT_ERR_CNT,b[3];
-       dvb_usb_generic_rw(state->d,&bw,1,b,3,0);
-       *ber = (b[0] << 16) | (b[1] << 8) | b[2];
-       return 0;
+       int ret;
+
+       mutex_lock(&state->data_mutex);
+       state->data[0] = GET_VIT_ERR_CNT;
+
+       ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 3, 0);
+       if (ret >= 0)
+               *ber = (state->data[0] << 16) | (state->data[1] << 8) | state->data[2];
+
+       mutex_unlock(&state->data_mutex);
+       return ret;
 }
 
 static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
 {
        struct dtt200u_fe_state *state = fe->demodulator_priv;
-       u8 bw = GET_RS_UNCOR_BLK_CNT,b[2];
+       int ret;
 
-       dvb_usb_generic_rw(state->d,&bw,1,b,2,0);
-       *unc = (b[0] << 8) | b[1];
-       return 0;
+       mutex_lock(&state->data_mutex);
+       state->data[0] = GET_RS_UNCOR_BLK_CNT;
+
+       ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 2, 0);
+       if (ret >= 0)
+               *unc = (state->data[0] << 8) | state->data[1];
+
+       mutex_unlock(&state->data_mutex);
+       return ret;
 }
 
 static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
 {
        struct dtt200u_fe_state *state = fe->demodulator_priv;
-       u8 bw = GET_AGC, b;
-       dvb_usb_generic_rw(state->d,&bw,1,&b,1,0);
-       *strength = (b << 8) | b;
-       return 0;
+       int ret;
+
+       mutex_lock(&state->data_mutex);
+       state->data[0] = GET_AGC;
+
+       ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 1, 0);
+       if (ret >= 0)
+               *strength = (state->data[0] << 8) | state->data[0];
+
+       mutex_unlock(&state->data_mutex);
+       return ret;
 }
 
 static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
 {
        struct dtt200u_fe_state *state = fe->demodulator_priv;
-       u8 bw = GET_SNR,br;
-       dvb_usb_generic_rw(state->d,&bw,1,&br,1,0);
-       *snr = ~((br << 8) | br);
-       return 0;
+       int ret;
+
+       mutex_lock(&state->data_mutex);
+       state->data[0] = GET_SNR;
+
+       ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 1, 0);
+       if (ret >= 0)
+               *snr = ~((state->data[0] << 8) | state->data[0]);
+
+       mutex_unlock(&state->data_mutex);
+       return ret;
 }
 
 static int dtt200u_fe_init(struct dvb_frontend* fe)
 {
        struct dtt200u_fe_state *state = fe->demodulator_priv;
-       u8 b = SET_INIT;
-       return dvb_usb_generic_write(state->d,&b,1);
+       int ret;
+
+       mutex_lock(&state->data_mutex);
+       state->data[0] = SET_INIT;
+
+       ret = dvb_usb_generic_write(state->d, state->data, 1);
+       mutex_unlock(&state->data_mutex);
+
+       return ret;
 }
 
 static int dtt200u_fe_sleep(struct dvb_frontend* fe)
@@ -105,39 +151,40 @@ static int dtt200u_fe_set_frontend(struct dvb_frontend *fe)
 {
        struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
        struct dtt200u_fe_state *state = fe->demodulator_priv;
-       int i;
-       enum fe_status st;
+       int ret;
        u16 freq = fep->frequency / 250000;
-       u8 bwbuf[2] = { SET_BANDWIDTH, 0 },freqbuf[3] = { SET_RF_FREQ, 0, 0 };
 
+       mutex_lock(&state->data_mutex);
+       state->data[0] = SET_BANDWIDTH;
        switch (fep->bandwidth_hz) {
        case 8000000:
-               bwbuf[1] = 8;
+               state->data[1] = 8;
                break;
        case 7000000:
-               bwbuf[1] = 7;
+               state->data[1] = 7;
                break;
        case 6000000:
-               bwbuf[1] = 6;
+               state->data[1] = 6;
                break;
        default:
-               return -EINVAL;
+               ret = -EINVAL;
+               goto ret;
        }
 
-       dvb_usb_generic_write(state->d,bwbuf,2);
+       ret = dvb_usb_generic_write(state->d, state->data, 2);
+       if (ret < 0)
+               goto ret;
 
-       freqbuf[1] = freq & 0xff;
-       freqbuf[2] = (freq >> 8) & 0xff;
-       dvb_usb_generic_write(state->d,freqbuf,3);
+       state->data[0] = SET_RF_FREQ;
+       state->data[1] = freq & 0xff;
+       state->data[2] = (freq >> 8) & 0xff;
+       ret = dvb_usb_generic_write(state->d, state->data, 3);
+       if (ret < 0)
+               goto ret;
 
-       for (i = 0; i < 30; i++) {
-               msleep(20);
-               dtt200u_fe_read_status(fe, &st);
-               if (st & FE_TIMEDOUT)
-                       continue;
-       }
-
-       return 0;
+ret:
+       mutex_unlock(&state->data_mutex);
+       return ret;
 }
 
 static int dtt200u_fe_get_frontend(struct dvb_frontend* fe,
@@ -169,6 +216,7 @@ struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d)
        deb_info("attaching frontend dtt200u\n");
 
        state->d = d;
+       mutex_init(&state->data_mutex);
 
        memcpy(&state->frontend.ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
index d2a01b50af0daf7ce7ab7d17686b845574c291a1..f88572c7ae7cbd6aa10e4e9fc430a584fc6a63b0 100644 (file)
@@ -20,75 +20,114 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
+struct dtt200u_state {
+       unsigned char data[80];
+       struct mutex data_mutex;
+};
+
 static int dtt200u_power_ctrl(struct dvb_usb_device *d, int onoff)
 {
-       u8 b = SET_INIT;
+       struct dtt200u_state *st = d->priv;
+       int ret = 0;
+
+       mutex_lock(&st->data_mutex);
+
+       st->data[0] = SET_INIT;
 
        if (onoff)
-               dvb_usb_generic_write(d,&b,2);
+               ret = dvb_usb_generic_write(d, st->data, 2);
 
-       return 0;
+       mutex_unlock(&st->data_mutex);
+       return ret;
 }
 
 static int dtt200u_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 {
-       u8 b_streaming[2] = { SET_STREAMING, onoff };
-       u8 b_rst_pid = RESET_PID_FILTER;
+       struct dtt200u_state *st = adap->dev->priv;
+       int ret;
 
-       dvb_usb_generic_write(adap->dev, b_streaming, 2);
+       mutex_lock(&st->data_mutex);
+       st->data[0] = SET_STREAMING;
+       st->data[1] = onoff;
 
-       if (onoff == 0)
-               dvb_usb_generic_write(adap->dev, &b_rst_pid, 1);
-       return 0;
+       ret = dvb_usb_generic_write(adap->dev, st->data, 2);
+       if (ret < 0)
+               goto ret;
+
+       if (onoff)
+               goto ret;
+
+       st->data[0] = RESET_PID_FILTER;
+       ret = dvb_usb_generic_write(adap->dev, st->data, 1);
+
+ret:
+       mutex_unlock(&st->data_mutex);
+
+       return ret;
 }
 
 static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff)
 {
-       u8 b_pid[4];
+       struct dtt200u_state *st = adap->dev->priv;
+       int ret;
+
        pid = onoff ? pid : 0;
 
-       b_pid[0] = SET_PID_FILTER;
-       b_pid[1] = index;
-       b_pid[2] = pid & 0xff;
-       b_pid[3] = (pid >> 8) & 0x1f;
+       mutex_lock(&st->data_mutex);
+       st->data[0] = SET_PID_FILTER;
+       st->data[1] = index;
+       st->data[2] = pid & 0xff;
+       st->data[3] = (pid >> 8) & 0x1f;
 
-       return dvb_usb_generic_write(adap->dev, b_pid, 4);
+       ret = dvb_usb_generic_write(adap->dev, st->data, 4);
+       mutex_unlock(&st->data_mutex);
+
+       return ret;
 }
 
 static int dtt200u_rc_query(struct dvb_usb_device *d)
 {
-       u8 key[5],cmd = GET_RC_CODE;
+       struct dtt200u_state *st = d->priv;
        u32 scancode;
+       int ret;
+
+       mutex_lock(&st->data_mutex);
+       st->data[0] = GET_RC_CODE;
+
+       ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 5, 0);
+       if (ret < 0)
+               goto ret;
 
-       dvb_usb_generic_rw(d,&cmd,1,key,5,0);
-       if (key[0] == 1) {
+       if (st->data[0] == 1) {
                enum rc_type proto = RC_TYPE_NEC;
 
-               scancode = key[1];
-               if ((u8) ~key[1] != key[2]) {
+               scancode = st->data[1];
+               if ((u8) ~st->data[1] != st->data[2]) {
                        /* Extended NEC */
                        scancode = scancode << 8;
-                       scancode |= key[2];
+                       scancode |= st->data[2];
                        proto = RC_TYPE_NECX;
                }
                scancode = scancode << 8;
-               scancode |= key[3];
+               scancode |= st->data[3];
 
                /* Check command checksum is ok */
-               if ((u8) ~key[3] == key[4])
+               if ((u8) ~st->data[3] == st->data[4])
                        rc_keydown(d->rc_dev, proto, scancode, 0);
                else
                        rc_keyup(d->rc_dev);
-       } else if (key[0] == 2) {
+       } else if (st->data[0] == 2) {
                rc_repeat(d->rc_dev);
        } else {
                rc_keyup(d->rc_dev);
        }
 
-       if (key[0] != 0)
-               deb_info("key: %*ph\n", 5, key);
+       if (st->data[0] != 0)
+               deb_info("st->data: %*ph\n", 5, st->data);
 
-       return 0;
+ret:
+       mutex_unlock(&st->data_mutex);
+       return ret;
 }
 
 static int dtt200u_frontend_attach(struct dvb_usb_adapter *adap)
@@ -106,17 +145,24 @@ static struct dvb_usb_device_properties wt220u_miglia_properties;
 static int dtt200u_usb_probe(struct usb_interface *intf,
                const struct usb_device_id *id)
 {
+       struct dvb_usb_device *d;
+       struct dtt200u_state *st;
+
        if (0 == dvb_usb_device_init(intf, &dtt200u_properties,
-                                    THIS_MODULE, NULL, adapter_nr) ||
+                                    THIS_MODULE, &d, adapter_nr) ||
            0 == dvb_usb_device_init(intf, &wt220u_properties,
-                                    THIS_MODULE, NULL, adapter_nr) ||
+                                    THIS_MODULE, &d, adapter_nr) ||
            0 == dvb_usb_device_init(intf, &wt220u_fc_properties,
-                                    THIS_MODULE, NULL, adapter_nr) ||
+                                    THIS_MODULE, &d, adapter_nr) ||
            0 == dvb_usb_device_init(intf, &wt220u_zl0353_properties,
-                                    THIS_MODULE, NULL, adapter_nr) ||
+                                    THIS_MODULE, &d, adapter_nr) ||
            0 == dvb_usb_device_init(intf, &wt220u_miglia_properties,
-                                    THIS_MODULE, NULL, adapter_nr))
+                                    THIS_MODULE, &d, adapter_nr)) {
+               st = d->priv;
+               mutex_init(&st->data_mutex);
+
                return 0;
+       }
 
        return -ENODEV;
 }
@@ -140,6 +186,8 @@ static struct dvb_usb_device_properties dtt200u_properties = {
        .usb_ctrl = CYPRESS_FX2,
        .firmware = "dvb-usb-dtt200u-01.fw",
 
+       .size_of_priv     = sizeof(struct dtt200u_state),
+
        .num_adapters = 1,
        .adapter = {
                {
@@ -190,6 +238,8 @@ static struct dvb_usb_device_properties wt220u_properties = {
        .usb_ctrl = CYPRESS_FX2,
        .firmware = "dvb-usb-wt220u-02.fw",
 
+       .size_of_priv     = sizeof(struct dtt200u_state),
+
        .num_adapters = 1,
        .adapter = {
                {
@@ -240,6 +290,8 @@ static struct dvb_usb_device_properties wt220u_fc_properties = {
        .usb_ctrl = CYPRESS_FX2,
        .firmware = "dvb-usb-wt220u-fc03.fw",
 
+       .size_of_priv     = sizeof(struct dtt200u_state),
+
        .num_adapters = 1,
        .adapter = {
                {
@@ -290,6 +342,8 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = {
        .usb_ctrl = CYPRESS_FX2,
        .firmware = "dvb-usb-wt220u-zl0353-01.fw",
 
+       .size_of_priv     = sizeof(struct dtt200u_state),
+
        .num_adapters = 1,
        .adapter = {
                {
@@ -340,6 +394,8 @@ static struct dvb_usb_device_properties wt220u_miglia_properties = {
        .usb_ctrl = CYPRESS_FX2,
        .firmware = "dvb-usb-wt220u-miglia-01.fw",
 
+       .size_of_priv     = sizeof(struct dtt200u_state),
+
        .num_adapters = 1,
        .generic_bulk_ctrl_endpoint = 0x01,
 
index 3d11df41cac0300c00a5d635412b233d232d338f..c60fb54f445f582357ca949b3e4f6775e0822e12 100644 (file)
@@ -31,9 +31,14 @@ module_param_named(debug, dvb_usb_dtv5100_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
+struct dtv5100_state {
+       unsigned char data[80];
+};
+
 static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr,
                           u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
 {
+       struct dtv5100_state *st = d->priv;
        u8 request;
        u8 type;
        u16 value;
@@ -60,9 +65,10 @@ static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr,
        }
        index = (addr << 8) + wbuf[0];
 
+       memcpy(st->data, rbuf, rlen);
        msleep(1); /* avoid I2C errors */
        return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), request,
-                              type, value, index, rbuf, rlen,
+                              type, value, index, st->data, rlen,
                               DTV5100_USB_TIMEOUT);
 }
 
@@ -176,7 +182,7 @@ static struct dvb_usb_device_properties dtv5100_properties = {
        .caps = DVB_USB_IS_AN_I2C_ADAPTER,
        .usb_ctrl = DEVICE_SPECIFIC,
 
-       .size_of_priv = 0,
+       .size_of_priv = sizeof(struct dtv5100_state),
 
        .num_adapters = 1,
        .adapter = {{
index 639c4678c65b96c82293f7546919768401f43dbd..1448c3d27ea2959b811d36ec3bcede0415275f99 100644 (file)
@@ -462,8 +462,10 @@ extern int dvb_usb_device_init(struct usb_interface *,
 extern void dvb_usb_device_exit(struct usb_interface *);
 
 /* the generic read/write method for device control */
-extern int dvb_usb_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16,int);
-extern int dvb_usb_generic_write(struct dvb_usb_device *, u8 *, u16);
+extern int __must_check
+dvb_usb_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16, int);
+extern int __must_check
+dvb_usb_generic_write(struct dvb_usb_device *, u8 *, u16);
 
 /* commonly used remote control parsing */
 extern int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *, u8[], u32 *, int *);
index 5fb0c650926e3561684981013cc004a17975a290..2c720cb2fb00f0ddecd0eb82c6daf0f3a6731094 100644 (file)
@@ -852,7 +852,7 @@ static int su3000_power_ctrl(struct dvb_usb_device *d, int i)
        if (i && !state->initialized) {
                state->initialized = 1;
                /* reset board */
-               dvb_usb_generic_rw(d, obuf, 2, NULL, 0, 0);
+               return dvb_usb_generic_rw(d, obuf, 2, NULL, 0, 0);
        }
 
        return 0;
index 5d0384dd45b5ed1ed2e638acdddf9fe86ea2e628..adfd764914517bdbbbff823ee31e5d08ebcac7fb 100644 (file)
@@ -24,6 +24,10 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DV
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
+struct gp8psk_state {
+       unsigned char data[80];
+};
+
 static int gp8psk_get_fw_version(struct dvb_usb_device *d, u8 *fw_vers)
 {
        return (gp8psk_usb_in_op(d, GET_FW_VERS, 0, 0, fw_vers, 6));
@@ -53,17 +57,22 @@ static void gp8psk_info(struct dvb_usb_device *d)
 
 int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
 {
+       struct gp8psk_state *st = d->priv;
        int ret = 0,try = 0;
 
+       if (blen > sizeof(st->data))
+               return -EIO;
+
        if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
                return ret;
 
        while (ret >= 0 && ret != blen && try < 3) {
+               memcpy(st->data, b, blen);
                ret = usb_control_msg(d->udev,
                        usb_rcvctrlpipe(d->udev,0),
                        req,
                        USB_TYPE_VENDOR | USB_DIR_IN,
-                       value,index,b,blen,
+                       value, index, st->data, blen,
                        2000);
                deb_info("reading number %d (ret: %d)\n",try,ret);
                try++;
@@ -86,19 +95,24 @@ int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8
 int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
                             u16 index, u8 *b, int blen)
 {
+       struct gp8psk_state *st = d->priv;
        int ret;
 
        deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
        debug_dump(b,blen,deb_xfer);
 
+       if (blen > sizeof(st->data))
+               return -EIO;
+
        if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
                return ret;
 
+       memcpy(st->data, b, blen);
        if (usb_control_msg(d->udev,
                        usb_sndctrlpipe(d->udev,0),
                        req,
                        USB_TYPE_VENDOR | USB_DIR_OUT,
-                       value,index,b,blen,
+                       value, index, st->data, blen,
                        2000) != blen) {
                warn("usb out operation failed.");
                ret = -EIO;
@@ -143,6 +157,11 @@ static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d)
                        err("failed to load bcm4500 firmware.");
                        goto out_free;
                }
+               if (buflen > 64) {
+                       err("firmare chunk size bigger than 64 bytes.");
+                       goto out_free;
+               }
+
                memcpy(buf, ptr, buflen);
                if (dvb_usb_generic_write(d, buf, buflen)) {
                        err("failed to load bcm4500 firmware.");
@@ -265,6 +284,8 @@ static struct dvb_usb_device_properties gp8psk_properties = {
        .usb_ctrl = CYPRESS_FX2,
        .firmware = "dvb-usb-gp8psk-01.fw",
 
+       .size_of_priv = sizeof(struct gp8psk_state),
+
        .num_adapters = 1,
        .adapter = {
                {
index fc7569e2728d2201e14897cddd41c9a9504a9716..1babd334191069d30419e2c07fc25fd04e0931d4 100644 (file)
@@ -74,22 +74,31 @@ static struct rc_map_table rc_map_haupp_table[] = {
  */
 static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
-       u8 key[5],cmd[2] = { DIBUSB_REQ_POLL_REMOTE, 0x35 }, data,toggle,custom;
+       u8 *buf, data, toggle, custom;
        u16 raw;
-       int i;
+       int i, ret;
        struct dibusb_device_state *st = d->priv;
 
-       dvb_usb_generic_rw(d,cmd,2,key,5,0);
+       buf = kmalloc(5, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       buf[0] = DIBUSB_REQ_POLL_REMOTE;
+       buf[1] = 0x35;
+       ret = dvb_usb_generic_rw(d, buf, 2, buf, 5, 0);
+       if (ret < 0)
+               goto ret;
 
        *state = REMOTE_NO_KEY_PRESSED;
-       switch (key[0]) {
+       switch (buf[0]) {
                case DIBUSB_RC_HAUPPAUGE_KEY_PRESSED:
-                       raw = ((key[1] << 8) | key[2]) >> 3;
+                       raw = ((buf[1] << 8) | buf[2]) >> 3;
                        toggle = !!(raw & 0x800);
                        data = raw & 0x3f;
                        custom = (raw >> 6) & 0x1f;
 
-                       deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to c: %02x d: %02x toggle: %d\n",key[1],key[2],key[3],custom,data,toggle);
+                       deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to c: %02x d: %02x toggle: %d\n",
+                              buf[1], buf[2], buf[3], custom, data, toggle);
 
                        for (i = 0; i < ARRAY_SIZE(rc_map_haupp_table); i++) {
                                if (rc5_data(&rc_map_haupp_table[i]) == data &&
@@ -117,7 +126,9 @@ static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
                        break;
        }
 
-       return 0;
+ret:
+       kfree(buf);
+       return ret;
 }
 
 static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6])
index c05de1b088a4e3abf0e6de4309b43df6305d4678..07fa08be9e994a3f7d5952251b73f871fe4ecdca 100644 (file)
@@ -97,48 +97,53 @@ struct pctv452e_state {
        u8 c;      /* transaction counter, wraps around...  */
        u8 initialized; /* set to 1 if 0x15 has been sent */
        u16 last_rc_key;
+
+       unsigned char data[80];
 };
 
 static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data,
                         unsigned int write_len, unsigned int read_len)
 {
        struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
-       u8 buf[64];
        u8 id;
        unsigned int rlen;
        int ret;
 
-       BUG_ON(NULL == data && 0 != (write_len | read_len));
-       BUG_ON(write_len > 64 - 4);
-       BUG_ON(read_len > 64 - 4);
+       if (!data || (write_len > 64 - 4) || (read_len > 64 - 4)) {
+               err("%s: transfer data invalid", __func__);
+               return -EIO;
+       }
 
+       mutex_lock(&state->ca_mutex);
        id = state->c++;
 
-       buf[0] = SYNC_BYTE_OUT;
-       buf[1] = id;
-       buf[2] = cmd;
-       buf[3] = write_len;
+       state->data[0] = SYNC_BYTE_OUT;
+       state->data[1] = id;
+       state->data[2] = cmd;
+       state->data[3] = write_len;
 
-       memcpy(buf + 4, data, write_len);
+       memcpy(state->data + 4, data, write_len);
 
        rlen = (read_len > 0) ? 64 : 0;
-       ret = dvb_usb_generic_rw(d, buf, 4 + write_len,
-                                 buf, rlen, /* delay_ms */ 0);
+       ret = dvb_usb_generic_rw(d, state->data, 4 + write_len,
+                                 state->data, rlen, /* delay_ms */ 0);
        if (0 != ret)
                goto failed;
 
        ret = -EIO;
-       if (SYNC_BYTE_IN != buf[0] || id != buf[1])
+       if (SYNC_BYTE_IN != state->data[0] || id != state->data[1])
                goto failed;
 
-       memcpy(data, buf + 4, read_len);
+       memcpy(data, state->data + 4, read_len);
 
+       mutex_unlock(&state->ca_mutex);
        return 0;
 
 failed:
        err("CI error %d; %02X %02X %02X -> %*ph.",
-            ret, SYNC_BYTE_OUT, id, cmd, 3, buf);
+            ret, SYNC_BYTE_OUT, id, cmd, 3, state->data);
 
+       mutex_unlock(&state->ca_mutex);
        return ret;
 }
 
@@ -405,52 +410,53 @@ static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr,
                                u8 *rcv_buf, u8 rcv_len)
 {
        struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
-       u8 buf[64];
        u8 id;
        int ret;
 
+       mutex_lock(&state->ca_mutex);
        id = state->c++;
 
        ret = -EINVAL;
        if (snd_len > 64 - 7 || rcv_len > 64 - 7)
                goto failed;
 
-       buf[0] = SYNC_BYTE_OUT;
-       buf[1] = id;
-       buf[2] = PCTV_CMD_I2C;
-       buf[3] = snd_len + 3;
-       buf[4] = addr << 1;
-       buf[5] = snd_len;
-       buf[6] = rcv_len;
+       state->data[0] = SYNC_BYTE_OUT;
+       state->data[1] = id;
+       state->data[2] = PCTV_CMD_I2C;
+       state->data[3] = snd_len + 3;
+       state->data[4] = addr << 1;
+       state->data[5] = snd_len;
+       state->data[6] = rcv_len;
 
-       memcpy(buf + 7, snd_buf, snd_len);
+       memcpy(state->data + 7, snd_buf, snd_len);
 
-       ret = dvb_usb_generic_rw(d, buf, 7 + snd_len,
-                                 buf, /* rcv_len */ 64,
+       ret = dvb_usb_generic_rw(d, state->data, 7 + snd_len,
+                                 state->data, /* rcv_len */ 64,
                                  /* delay_ms */ 0);
        if (ret < 0)
                goto failed;
 
        /* TT USB protocol error. */
        ret = -EIO;
-       if (SYNC_BYTE_IN != buf[0] || id != buf[1])
+       if (SYNC_BYTE_IN != state->data[0] || id != state->data[1])
                goto failed;
 
        /* I2C device didn't respond as expected. */
        ret = -EREMOTEIO;
-       if (buf[5] < snd_len || buf[6] < rcv_len)
+       if (state->data[5] < snd_len || state->data[6] < rcv_len)
                goto failed;
 
-       memcpy(rcv_buf, buf + 7, rcv_len);
+       memcpy(rcv_buf, state->data + 7, rcv_len);
+       mutex_unlock(&state->ca_mutex);
 
        return rcv_len;
 
 failed:
-       err("I2C error %d; %02X %02X  %02X %02X %02X -> "
-            "%02X %02X  %02X %02X %02X.",
+       err("I2C error %d; %02X %02X  %02X %02X %02X -> %*ph",
             ret, SYNC_BYTE_OUT, id, addr << 1, snd_len, rcv_len,
-            buf[0], buf[1], buf[4], buf[5], buf[6]);
+            7, state->data);
 
+       mutex_unlock(&state->ca_mutex);
        return ret;
 }
 
@@ -499,8 +505,7 @@ static u32 pctv452e_i2c_func(struct i2c_adapter *adapter)
 static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
 {
        struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
-       u8 b0[] = { 0xaa, 0, PCTV_CMD_RESET, 1, 0 };
-       u8 rx[PCTV_ANSWER_LEN];
+       u8 *rx;
        int ret;
 
        info("%s: %d\n", __func__, i);
@@ -511,6 +516,11 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
        if (state->initialized)
                return 0;
 
+       rx = kmalloc(PCTV_ANSWER_LEN, GFP_KERNEL);
+       if (!rx)
+               return -ENOMEM;
+
+       mutex_lock(&state->ca_mutex);
        /* hmm where shoud this should go? */
        ret = usb_set_interface(d->udev, 0, ISOC_INTERFACE_ALTERNATIVE);
        if (ret != 0)
@@ -518,65 +528,75 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
                        __func__, ret);
 
        /* this is a one-time initialization, dont know where to put */
-       b0[1] = state->c++;
+       state->data[0] = 0xaa;
+       state->data[1] = state->c++;
+       state->data[2] = PCTV_CMD_RESET;
+       state->data[3] = 1;
+       state->data[4] = 0;
        /* reset board */
-       ret = dvb_usb_generic_rw(d, b0, sizeof(b0), rx, PCTV_ANSWER_LEN, 0);
+       ret = dvb_usb_generic_rw(d, state->data, 5, rx, PCTV_ANSWER_LEN, 0);
        if (ret)
-               return ret;
+               goto ret;
 
-       b0[1] = state->c++;
-       b0[4] = 1;
+       state->data[1] = state->c++;
+       state->data[4] = 1;
        /* reset board (again?) */
-       ret = dvb_usb_generic_rw(d, b0, sizeof(b0), rx, PCTV_ANSWER_LEN, 0);
+       ret = dvb_usb_generic_rw(d, state->data, 5, rx, PCTV_ANSWER_LEN, 0);
        if (ret)
-               return ret;
+               goto ret;
 
        state->initialized = 1;
 
-       return 0;
+ret:
+       mutex_unlock(&state->ca_mutex);
+       kfree(rx);
+       return ret;
 }
 
 static int pctv452e_rc_query(struct dvb_usb_device *d)
 {
        struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
-       u8 b[CMD_BUFFER_SIZE];
-       u8 rx[PCTV_ANSWER_LEN];
        int ret, i;
-       u8 id = state->c++;
+       u8 id;
+
+       mutex_lock(&state->ca_mutex);
+       id = state->c++;
 
        /* prepare command header  */
-       b[0] = SYNC_BYTE_OUT;
-       b[1] = id;
-       b[2] = PCTV_CMD_IR;
-       b[3] = 0;
+       state->data[0] = SYNC_BYTE_OUT;
+       state->data[1] = id;
+       state->data[2] = PCTV_CMD_IR;
+       state->data[3] = 0;
 
        /* send ir request */
-       ret = dvb_usb_generic_rw(d, b, 4, rx, PCTV_ANSWER_LEN, 0);
+       ret = dvb_usb_generic_rw(d, state->data, 4,
+                                state->data, PCTV_ANSWER_LEN, 0);
        if (ret != 0)
-               return ret;
+               goto ret;
 
        if (debug > 3) {
-               info("%s: read: %2d: %*ph: ", __func__, ret, 3, rx);
-               for (i = 0; (i < rx[3]) && ((i+3) < PCTV_ANSWER_LEN); i++)
-                       info(" %02x", rx[i+3]);
+               info("%s: read: %2d: %*ph: ", __func__, ret, 3, state->data);
+               for (i = 0; (i < state->data[3]) && ((i + 3) < PCTV_ANSWER_LEN); i++)
+                       info(" %02x", state->data[i + 3]);
 
                info("\n");
        }
 
-       if ((rx[3] == 9) &&  (rx[12] & 0x01)) {
+       if ((state->data[3] == 9) &&  (state->data[12] & 0x01)) {
                /* got a "press" event */
-               state->last_rc_key = RC_SCANCODE_RC5(rx[7], rx[6]);
+               state->last_rc_key = RC_SCANCODE_RC5(state->data[7], state->data[6]);
                if (debug > 2)
                        info("%s: cmd=0x%02x sys=0x%02x\n",
-                               __func__, rx[6], rx[7]);
+                               __func__, state->data[6], state->data[7]);
 
                rc_keydown(d->rc_dev, RC_TYPE_RC5, state->last_rc_key, 0);
        } else if (state->last_rc_key) {
                rc_keyup(d->rc_dev);
                state->last_rc_key = 0;
        }
-
-       return 0;
+ret:
+       mutex_unlock(&state->ca_mutex);
+       return ret;
 }
 
 static int pctv452e_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
index d9f3262bf0712642b6d15edd216a26ee48c7ecf9..4706628a3ed5ea5345e30a9dc59cad7fb385286d 100644 (file)
@@ -89,9 +89,13 @@ struct technisat_usb2_state {
 static int technisat_usb2_i2c_access(struct usb_device *udev,
                u8 device_addr, u8 *tx, u8 txlen, u8 *rx, u8 rxlen)
 {
-       u8 b[64];
+       u8 *b;
        int ret, actual_length;
 
+       b = kmalloc(64, GFP_KERNEL);
+       if (!b)
+               return -ENOMEM;
+
        deb_i2c("i2c-access: %02x, tx: ", device_addr);
        debug_dump(tx, txlen, deb_i2c);
        deb_i2c(" ");
@@ -123,7 +127,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev,
 
        if (ret < 0) {
                err("i2c-error: out failed %02x = %d", device_addr, ret);
-               return -ENODEV;
+               goto err;
        }
 
        ret = usb_bulk_msg(udev,
@@ -131,7 +135,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev,
                        b, 64, &actual_length, 1000);
        if (ret < 0) {
                err("i2c-error: in failed %02x = %d", device_addr, ret);
-               return -ENODEV;
+               goto err;
        }
 
        if (b[0] != I2C_STATUS_OK) {
@@ -140,7 +144,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev,
                if (!(b[0] == I2C_STATUS_NAK &&
                                device_addr == 0x60
                                /* && device_is_technisat_usb2 */))
-                       return -ENODEV;
+                       goto err;
        }
 
        deb_i2c("status: %d, ", b[0]);
@@ -154,7 +158,9 @@ static int technisat_usb2_i2c_access(struct usb_device *udev,
 
        deb_i2c("\n");
 
-       return 0;
+err:
+       kfree(b);
+       return ret;
 }
 
 static int technisat_usb2_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
index c3a0e87066ebbbd78cda420a48f7dc76ab511107..f7bb78c1873c915d9db9574ea024cc77a355c413 100644 (file)
@@ -1901,19 +1901,30 @@ static long s2255_vendor_req(struct s2255_dev *dev, unsigned char Request,
                             s32 TransferBufferLength, int bOut)
 {
        int r;
+       unsigned char *buf;
+
+       buf = kmalloc(TransferBufferLength, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
        if (!bOut) {
                r = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
                                    Request,
                                    USB_TYPE_VENDOR | USB_RECIP_DEVICE |
                                    USB_DIR_IN,
-                                   Value, Index, TransferBuffer,
+                                   Value, Index, buf,
                                    TransferBufferLength, HZ * 5);
+
+               if (r >= 0)
+                       memcpy(TransferBuffer, buf, TransferBufferLength);
        } else {
+               memcpy(buf, TransferBuffer, TransferBufferLength);
                r = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
                                    Request, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                                   Value, Index, TransferBuffer,
+                                   Value, Index, buf,
                                    TransferBufferLength, HZ * 5);
        }
+       kfree(buf);
        return r;
 }
 
index db200c9d796d3683d23b9279db73d6eb625420da..22a9aae16291b31adb5eeae0af4cd14c747c0ec5 100644 (file)
@@ -147,20 +147,26 @@ int stk_camera_write_reg(struct stk_camera *dev, u16 index, u8 value)
 int stk_camera_read_reg(struct stk_camera *dev, u16 index, int *value)
 {
        struct usb_device *udev = dev->udev;
+       unsigned char *buf;
        int ret;
 
+       buf = kmalloc(sizeof(u8), GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
        ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
                        0x00,
                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                        0x00,
                        index,
-                       (u8 *) value,
+                       buf,
                        sizeof(u8),
                        500);
-       if (ret < 0)
-               return ret;
-       else
-               return 0;
+       if (ret >= 0)
+               memcpy(value, buf, sizeof(u8));
+
+       kfree(buf);
+       return ret;
 }
 
 static int stk_start_stream(struct stk_camera *dev)