|
@@ -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;
|