diff options
Diffstat (limited to 'drivers/media/usb/b2c2/flexcop-usb.c')
| -rw-r--r-- | drivers/media/usb/b2c2/flexcop-usb.c | 105 |
1 files changed, 68 insertions, 37 deletions
diff --git a/drivers/media/usb/b2c2/flexcop-usb.c b/drivers/media/usb/b2c2/flexcop-usb.c index d4bdba60b0f7..52bc42da8a4c 100644 --- a/drivers/media/usb/b2c2/flexcop-usb.c +++ b/drivers/media/usb/b2c2/flexcop-usb.c | |||
| @@ -73,23 +73,34 @@ static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI, | |||
| 73 | u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR; | 73 | u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR; |
| 74 | u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) | | 74 | u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) | |
| 75 | (read ? 0x80 : 0); | 75 | (read ? 0x80 : 0); |
| 76 | int ret; | ||
| 77 | |||
| 78 | mutex_lock(&fc_usb->data_mutex); | ||
| 79 | if (!read) | ||
| 80 | memcpy(fc_usb->data, val, sizeof(*val)); | ||
| 76 | 81 | ||
| 77 | int len = usb_control_msg(fc_usb->udev, | 82 | ret = usb_control_msg(fc_usb->udev, |
| 78 | read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT, | 83 | read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT, |
| 79 | request, | 84 | request, |
| 80 | request_type, /* 0xc0 read or 0x40 write */ | 85 | request_type, /* 0xc0 read or 0x40 write */ |
| 81 | wAddress, | 86 | wAddress, |
| 82 | 0, | 87 | 0, |
| 83 | val, | 88 | fc_usb->data, |
| 84 | sizeof(u32), | 89 | sizeof(u32), |
| 85 | B2C2_WAIT_FOR_OPERATION_RDW * HZ); | 90 | B2C2_WAIT_FOR_OPERATION_RDW * HZ); |
| 86 | 91 | ||
| 87 | if (len != sizeof(u32)) { | 92 | if (ret != sizeof(u32)) { |
| 88 | err("error while %s dword from %d (%d).", read ? "reading" : | 93 | err("error while %s dword from %d (%d).", read ? "reading" : |
| 89 | "writing", wAddress, wRegOffsPCI); | 94 | "writing", wAddress, wRegOffsPCI); |
| 90 | return -EIO; | 95 | if (ret >= 0) |
| 96 | ret = -EIO; | ||
| 91 | } | 97 | } |
| 92 | return 0; | 98 | |
| 99 | if (read && ret >= 0) | ||
| 100 | memcpy(val, fc_usb->data, sizeof(*val)); | ||
| 101 | mutex_unlock(&fc_usb->data_mutex); | ||
| 102 | |||
| 103 | return ret; | ||
| 93 | } | 104 | } |
| 94 | /* | 105 | /* |
| 95 | * DKT 010817 - add support for V8 memory read/write and flash update | 106 | * DKT 010817 - add support for V8 memory read/write and flash update |
| @@ -100,9 +111,14 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb, | |||
| 100 | { | 111 | { |
| 101 | u8 request_type = USB_TYPE_VENDOR; | 112 | u8 request_type = USB_TYPE_VENDOR; |
| 102 | u16 wIndex; | 113 | u16 wIndex; |
| 103 | int nWaitTime, pipe, len; | 114 | int nWaitTime, pipe, ret; |
| 104 | wIndex = page << 8; | 115 | wIndex = page << 8; |
| 105 | 116 | ||
| 117 | if (buflen > sizeof(fc_usb->data)) { | ||
| 118 | err("Buffer size bigger than max URB control message\n"); | ||
| 119 | return -EIO; | ||
| 120 | } | ||
| 121 | |||
| 106 | switch (req) { | 122 | switch (req) { |
| 107 | case B2C2_USB_READ_V8_MEM: | 123 | case B2C2_USB_READ_V8_MEM: |
| 108 | nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ; | 124 | nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ; |
| @@ -127,17 +143,32 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb, | |||
| 127 | deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n", request_type, req, | 143 | deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n", request_type, req, |
| 128 | wAddress, wIndex, buflen); | 144 | wAddress, wIndex, buflen); |
| 129 | 145 | ||
| 130 | len = usb_control_msg(fc_usb->udev, pipe, | 146 | mutex_lock(&fc_usb->data_mutex); |
| 147 | |||
| 148 | if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) | ||
| 149 | memcpy(fc_usb->data, pbBuffer, buflen); | ||
| 150 | |||
| 151 | ret = usb_control_msg(fc_usb->udev, pipe, | ||
| 131 | req, | 152 | req, |
| 132 | request_type, | 153 | request_type, |
| 133 | wAddress, | 154 | wAddress, |
| 134 | wIndex, | 155 | wIndex, |
| 135 | pbBuffer, | 156 | fc_usb->data, |
| 136 | buflen, | 157 | buflen, |
| 137 | nWaitTime * HZ); | 158 | nWaitTime * HZ); |
| 159 | if (ret != buflen) | ||
| 160 | ret = -EIO; | ||
| 161 | |||
| 162 | if (ret >= 0) { | ||
| 163 | ret = 0; | ||
| 164 | if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) | ||
| 165 | memcpy(pbBuffer, fc_usb->data, buflen); | ||
| 166 | } | ||
| 138 | 167 | ||
| 139 | debug_dump(pbBuffer, len, deb_v8); | 168 | mutex_unlock(&fc_usb->data_mutex); |
| 140 | return len == buflen ? 0 : -EIO; | 169 | |
| 170 | debug_dump(pbBuffer, ret, deb_v8); | ||
| 171 | return ret; | ||
| 141 | } | 172 | } |
| 142 | 173 | ||
| 143 | #define bytes_left_to_read_on_page(paddr,buflen) \ | 174 | #define bytes_left_to_read_on_page(paddr,buflen) \ |
| @@ -196,29 +227,6 @@ static int flexcop_usb_get_mac_addr(struct flexcop_device *fc, int extended) | |||
| 196 | fc->dvb_adapter.proposed_mac, 6); | 227 | fc->dvb_adapter.proposed_mac, 6); |
| 197 | } | 228 | } |
| 198 | 229 | ||
| 199 | #if 0 | ||
| 200 | static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set, | ||
| 201 | flexcop_usb_utility_function_t func, u8 extra, u16 wIndex, | ||
| 202 | u16 buflen, u8 *pvBuffer) | ||
| 203 | { | ||
| 204 | u16 wValue; | ||
| 205 | u8 request_type = (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR; | ||
| 206 | int nWaitTime = 2, | ||
| 207 | pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN, len; | ||
| 208 | wValue = (func << 8) | extra; | ||
| 209 | |||
| 210 | len = usb_control_msg(fc_usb->udev,pipe, | ||
| 211 | B2C2_USB_UTILITY, | ||
| 212 | request_type, | ||
| 213 | wValue, | ||
| 214 | wIndex, | ||
| 215 | pvBuffer, | ||
| 216 | buflen, | ||
| 217 | nWaitTime * HZ); | ||
| 218 | return len == buflen ? 0 : -EIO; | ||
| 219 | } | ||
| 220 | #endif | ||
| 221 | |||
| 222 | /* usb i2c stuff */ | 230 | /* usb i2c stuff */ |
| 223 | static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c, | 231 | static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c, |
| 224 | flexcop_usb_request_t req, flexcop_usb_i2c_function_t func, | 232 | flexcop_usb_request_t req, flexcop_usb_i2c_function_t func, |
| @@ -226,9 +234,14 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c, | |||
| 226 | { | 234 | { |
| 227 | struct flexcop_usb *fc_usb = i2c->fc->bus_specific; | 235 | struct flexcop_usb *fc_usb = i2c->fc->bus_specific; |
| 228 | u16 wValue, wIndex; | 236 | u16 wValue, wIndex; |
| 229 | int nWaitTime,pipe,len; | 237 | int nWaitTime, pipe, ret; |
| 230 | u8 request_type = USB_TYPE_VENDOR; | 238 | u8 request_type = USB_TYPE_VENDOR; |
| 231 | 239 | ||
| 240 | if (buflen > sizeof(fc_usb->data)) { | ||
| 241 | err("Buffer size bigger than max URB control message\n"); | ||
| 242 | return -EIO; | ||
| 243 | } | ||
| 244 | |||
| 232 | switch (func) { | 245 | switch (func) { |
| 233 | case USB_FUNC_I2C_WRITE: | 246 | case USB_FUNC_I2C_WRITE: |
| 234 | case USB_FUNC_I2C_MULTIWRITE: | 247 | case USB_FUNC_I2C_MULTIWRITE: |
| @@ -257,15 +270,32 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c, | |||
| 257 | wValue & 0xff, wValue >> 8, | 270 | wValue & 0xff, wValue >> 8, |
| 258 | wIndex & 0xff, wIndex >> 8); | 271 | wIndex & 0xff, wIndex >> 8); |
| 259 | 272 | ||
| 260 | len = usb_control_msg(fc_usb->udev,pipe, | 273 | mutex_lock(&fc_usb->data_mutex); |
| 274 | |||
| 275 | if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) | ||
| 276 | memcpy(fc_usb->data, buf, buflen); | ||
| 277 | |||
| 278 | ret = usb_control_msg(fc_usb->udev, pipe, | ||
| 261 | req, | 279 | req, |
| 262 | request_type, | 280 | request_type, |
| 263 | wValue, | 281 | wValue, |
| 264 | wIndex, | 282 | wIndex, |
| 265 | buf, | 283 | fc_usb->data, |
| 266 | buflen, | 284 | buflen, |
| 267 | nWaitTime * HZ); | 285 | nWaitTime * HZ); |
| 268 | return len == buflen ? 0 : -EREMOTEIO; | 286 | |
| 287 | if (ret != buflen) | ||
| 288 | ret = -EIO; | ||
| 289 | |||
| 290 | if (ret >= 0) { | ||
| 291 | ret = 0; | ||
| 292 | if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) | ||
| 293 | memcpy(buf, fc_usb->data, buflen); | ||
| 294 | } | ||
| 295 | |||
| 296 | mutex_unlock(&fc_usb->data_mutex); | ||
| 297 | |||
| 298 | return 0; | ||
| 269 | } | 299 | } |
| 270 | 300 | ||
| 271 | /* actual bus specific access functions, | 301 | /* actual bus specific access functions, |
| @@ -516,6 +546,7 @@ static int flexcop_usb_probe(struct usb_interface *intf, | |||
| 516 | /* general flexcop init */ | 546 | /* general flexcop init */ |
| 517 | fc_usb = fc->bus_specific; | 547 | fc_usb = fc->bus_specific; |
| 518 | fc_usb->fc_dev = fc; | 548 | fc_usb->fc_dev = fc; |
| 549 | mutex_init(&fc_usb->data_mutex); | ||
| 519 | 550 | ||
| 520 | fc->read_ibi_reg = flexcop_usb_read_ibi_reg; | 551 | fc->read_ibi_reg = flexcop_usb_read_ibi_reg; |
| 521 | fc->write_ibi_reg = flexcop_usb_write_ibi_reg; | 552 | fc->write_ibi_reg = flexcop_usb_write_ibi_reg; |
