Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for-3.15/hid-cp2112' into for-3.15/hid-core-ll-transport-cleanup

+1080
+9
drivers/hid/Kconfig
··· 175 175 multimedia keyboard, but will lack support for the musical keyboard 176 176 and some additional multimedia keys. 177 177 178 + config HID_CP2112 179 + tristate "Silicon Labs CP2112 HID USB-to-SMBus Bridge support" 180 + depends on USB_HID && I2C && GPIOLIB 181 + ---help--- 182 + Support for Silicon Labs CP2112 HID USB to SMBus Master Bridge. 183 + This is a HID device driver which registers as an i2c adapter 184 + and gpiochip to expose these functions of the CP2112. The 185 + customizable USB descriptor fields are exposed as sysfs attributes. 186 + 178 187 config HID_CYPRESS 179 188 tristate "Cypress mouse and barcode readers" if EXPERT 180 189 depends on HID
+1
drivers/hid/Makefile
··· 41 41 obj-$(CONFIG_HID_BELKIN) += hid-belkin.o 42 42 obj-$(CONFIG_HID_CHERRY) += hid-cherry.o 43 43 obj-$(CONFIG_HID_CHICONY) += hid-chicony.o 44 + obj-$(CONFIG_HID_CP2112) += hid-cp2112.o 44 45 obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o 45 46 obj-$(CONFIG_HID_DRAGONRISE) += hid-dr.o 46 47 obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o
+1
drivers/hid/hid-core.c
··· 1732 1732 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, 1733 1733 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) }, 1734 1734 { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, 1735 + { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) }, 1735 1736 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, 1736 1737 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, 1737 1738 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) },
+1068
drivers/hid/hid-cp2112.c
··· 1 + /* 2 + * hid-cp2112.c - Silicon Labs HID USB to SMBus master bridge 3 + * Copyright (c) 2013,2014 Uplogix, Inc. 4 + * David Barksdale <dbarksdale@uplogix.com> 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + */ 15 + 16 + /* 17 + * The Silicon Labs CP2112 chip is a USB HID device which provides an 18 + * SMBus controller for talking to slave devices and 8 GPIO pins. The 19 + * host communicates with the CP2112 via raw HID reports. 20 + * 21 + * Data Sheet: 22 + * http://www.silabs.com/Support%20Documents/TechnicalDocs/CP2112.pdf 23 + * Programming Interface Specification: 24 + * http://www.silabs.com/Support%20Documents/TechnicalDocs/AN495.pdf 25 + */ 26 + 27 + #include <linux/gpio.h> 28 + #include <linux/hid.h> 29 + #include <linux/i2c.h> 30 + #include <linux/module.h> 31 + #include <linux/nls.h> 32 + #include <linux/usb/ch9.h> 33 + #include "hid-ids.h" 34 + 35 + enum { 36 + CP2112_GPIO_CONFIG = 0x02, 37 + CP2112_GPIO_GET = 0x03, 38 + CP2112_GPIO_SET = 0x04, 39 + CP2112_GET_VERSION_INFO = 0x05, 40 + CP2112_SMBUS_CONFIG = 0x06, 41 + CP2112_DATA_READ_REQUEST = 0x10, 42 + CP2112_DATA_WRITE_READ_REQUEST = 0x11, 43 + CP2112_DATA_READ_FORCE_SEND = 0x12, 44 + CP2112_DATA_READ_RESPONSE = 0x13, 45 + CP2112_DATA_WRITE_REQUEST = 0x14, 46 + CP2112_TRANSFER_STATUS_REQUEST = 0x15, 47 + CP2112_TRANSFER_STATUS_RESPONSE = 0x16, 48 + CP2112_CANCEL_TRANSFER = 0x17, 49 + CP2112_LOCK_BYTE = 0x20, 50 + CP2112_USB_CONFIG = 0x21, 51 + CP2112_MANUFACTURER_STRING = 0x22, 52 + CP2112_PRODUCT_STRING = 0x23, 53 + CP2112_SERIAL_STRING = 0x24, 54 + }; 55 + 56 + enum { 57 + STATUS0_IDLE = 0x00, 58 + STATUS0_BUSY = 0x01, 59 + STATUS0_COMPLETE = 0x02, 60 + STATUS0_ERROR = 0x03, 61 + }; 62 + 63 + enum { 64 + STATUS1_TIMEOUT_NACK = 0x00, 65 + STATUS1_TIMEOUT_BUS = 0x01, 66 + STATUS1_ARBITRATION_LOST = 0x02, 67 + STATUS1_READ_INCOMPLETE = 0x03, 68 + STATUS1_WRITE_INCOMPLETE = 0x04, 69 + STATUS1_SUCCESS = 0x05, 70 + }; 71 + 72 + struct cp2112_smbus_config_report { 73 + u8 report; /* CP2112_SMBUS_CONFIG */ 74 + __be32 clock_speed; /* Hz */ 75 + u8 device_address; /* Stored in the upper 7 bits */ 76 + u8 auto_send_read; /* 1 = enabled, 0 = disabled */ 77 + __be16 write_timeout; /* ms, 0 = no timeout */ 78 + __be16 read_timeout; /* ms, 0 = no timeout */ 79 + u8 scl_low_timeout; /* 1 = enabled, 0 = disabled */ 80 + __be16 retry_time; /* # of retries, 0 = no limit */ 81 + } __packed; 82 + 83 + struct cp2112_usb_config_report { 84 + u8 report; /* CP2112_USB_CONFIG */ 85 + __le16 vid; /* Vendor ID */ 86 + __le16 pid; /* Product ID */ 87 + u8 max_power; /* Power requested in 2mA units */ 88 + u8 power_mode; /* 0x00 = bus powered 89 + 0x01 = self powered & regulator off 90 + 0x02 = self powered & regulator on */ 91 + u8 release_major; 92 + u8 release_minor; 93 + u8 mask; /* What fields to program */ 94 + } __packed; 95 + 96 + struct cp2112_read_req_report { 97 + u8 report; /* CP2112_DATA_READ_REQUEST */ 98 + u8 slave_address; 99 + __be16 length; 100 + } __packed; 101 + 102 + struct cp2112_write_read_req_report { 103 + u8 report; /* CP2112_DATA_WRITE_READ_REQUEST */ 104 + u8 slave_address; 105 + __be16 length; 106 + u8 target_address_length; 107 + u8 target_address[16]; 108 + } __packed; 109 + 110 + struct cp2112_write_req_report { 111 + u8 report; /* CP2112_DATA_WRITE_REQUEST */ 112 + u8 slave_address; 113 + u8 length; 114 + u8 data[61]; 115 + } __packed; 116 + 117 + struct cp2112_force_read_report { 118 + u8 report; /* CP2112_DATA_READ_FORCE_SEND */ 119 + __be16 length; 120 + } __packed; 121 + 122 + struct cp2112_xfer_status_report { 123 + u8 report; /* CP2112_TRANSFER_STATUS_RESPONSE */ 124 + u8 status0; /* STATUS0_* */ 125 + u8 status1; /* STATUS1_* */ 126 + __be16 retries; 127 + __be16 length; 128 + } __packed; 129 + 130 + struct cp2112_string_report { 131 + u8 dummy; /* force .string to be aligned */ 132 + u8 report; /* CP2112_*_STRING */ 133 + u8 length; /* length in bytes of everyting after .report */ 134 + u8 type; /* USB_DT_STRING */ 135 + wchar_t string[30]; /* UTF16_LITTLE_ENDIAN string */ 136 + } __packed; 137 + 138 + /* Number of times to request transfer status before giving up waiting for a 139 + transfer to complete. This may need to be changed if SMBUS clock, retries, 140 + or read/write/scl_low timeout settings are changed. */ 141 + static const int XFER_STATUS_RETRIES = 10; 142 + 143 + /* Time in ms to wait for a CP2112_DATA_READ_RESPONSE or 144 + CP2112_TRANSFER_STATUS_RESPONSE. */ 145 + static const int RESPONSE_TIMEOUT = 50; 146 + 147 + static const struct hid_device_id cp2112_devices[] = { 148 + { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) }, 149 + { } 150 + }; 151 + MODULE_DEVICE_TABLE(hid, cp2112_devices); 152 + 153 + struct cp2112_device { 154 + struct i2c_adapter adap; 155 + struct hid_device *hdev; 156 + wait_queue_head_t wait; 157 + u8 read_data[61]; 158 + u8 read_length; 159 + int xfer_status; 160 + atomic_t read_avail; 161 + atomic_t xfer_avail; 162 + struct gpio_chip gc; 163 + }; 164 + 165 + static int gpio_push_pull = 0xFF; 166 + module_param(gpio_push_pull, int, S_IRUGO | S_IWUSR); 167 + MODULE_PARM_DESC(gpio_push_pull, "GPIO push-pull configuration bitmask"); 168 + 169 + static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 170 + { 171 + struct cp2112_device *dev = container_of(chip, struct cp2112_device, 172 + gc); 173 + struct hid_device *hdev = dev->hdev; 174 + u8 buf[5]; 175 + int ret; 176 + 177 + ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf, 178 + sizeof(buf), HID_FEATURE_REPORT, 179 + HID_REQ_GET_REPORT); 180 + if (ret != sizeof(buf)) { 181 + hid_err(hdev, "error requesting GPIO config: %d\n", ret); 182 + return ret; 183 + } 184 + 185 + buf[1] &= ~(1 << offset); 186 + buf[2] = gpio_push_pull; 187 + 188 + ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), 189 + HID_FEATURE_REPORT); 190 + if (ret < 0) { 191 + hid_err(hdev, "error setting GPIO config: %d\n", ret); 192 + return ret; 193 + } 194 + 195 + return 0; 196 + } 197 + 198 + static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 199 + { 200 + struct cp2112_device *dev = container_of(chip, struct cp2112_device, 201 + gc); 202 + struct hid_device *hdev = dev->hdev; 203 + u8 buf[3]; 204 + int ret; 205 + 206 + buf[0] = CP2112_GPIO_SET; 207 + buf[1] = value ? 0xff : 0; 208 + buf[2] = 1 << offset; 209 + 210 + ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), 211 + HID_FEATURE_REPORT); 212 + if (ret < 0) 213 + hid_err(hdev, "error setting GPIO values: %d\n", ret); 214 + } 215 + 216 + static int cp2112_gpio_get(struct gpio_chip *chip, unsigned offset) 217 + { 218 + struct cp2112_device *dev = container_of(chip, struct cp2112_device, 219 + gc); 220 + struct hid_device *hdev = dev->hdev; 221 + u8 buf[2]; 222 + int ret; 223 + 224 + ret = hid_hw_raw_request(hdev, CP2112_GPIO_GET, buf, sizeof(buf), 225 + HID_FEATURE_REPORT, HID_REQ_GET_REPORT); 226 + if (ret != sizeof(buf)) { 227 + hid_err(hdev, "error requesting GPIO values: %d\n", ret); 228 + return ret; 229 + } 230 + 231 + return (buf[1] >> offset) & 1; 232 + } 233 + 234 + static int cp2112_gpio_direction_output(struct gpio_chip *chip, 235 + unsigned offset, int value) 236 + { 237 + struct cp2112_device *dev = container_of(chip, struct cp2112_device, 238 + gc); 239 + struct hid_device *hdev = dev->hdev; 240 + u8 buf[5]; 241 + int ret; 242 + 243 + cp2112_gpio_set(chip, offset, value); 244 + 245 + ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf, 246 + sizeof(buf), HID_FEATURE_REPORT, 247 + HID_REQ_GET_REPORT); 248 + if (ret != sizeof(buf)) { 249 + hid_err(hdev, "error requesting GPIO config: %d\n", ret); 250 + return ret; 251 + } 252 + 253 + buf[1] |= 1 << offset; 254 + buf[2] = gpio_push_pull; 255 + 256 + ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), 257 + HID_FEATURE_REPORT); 258 + if (ret < 0) { 259 + hid_err(hdev, "error setting GPIO config: %d\n", ret); 260 + return ret; 261 + } 262 + 263 + return 0; 264 + } 265 + 266 + static int cp2112_hid_get(struct hid_device *hdev, unsigned char report_number, 267 + u8 *data, size_t count, unsigned char report_type) 268 + { 269 + u8 *buf; 270 + int ret; 271 + 272 + buf = kmalloc(count, GFP_KERNEL); 273 + if (!buf) 274 + return -ENOMEM; 275 + 276 + ret = hid_hw_raw_request(hdev, report_number, buf, count, 277 + report_type, HID_REQ_GET_REPORT); 278 + memcpy(data, buf, count); 279 + kfree(buf); 280 + return ret; 281 + } 282 + 283 + static int cp2112_hid_output(struct hid_device *hdev, u8 *data, size_t count, 284 + unsigned char report_type) 285 + { 286 + u8 *buf; 287 + int ret; 288 + 289 + buf = kmemdup(data, count, GFP_KERNEL); 290 + if (!buf) 291 + return -ENOMEM; 292 + 293 + ret = hdev->hid_output_raw_report(hdev, buf, count, report_type); 294 + kfree(buf); 295 + return ret; 296 + } 297 + 298 + static int cp2112_wait(struct cp2112_device *dev, atomic_t *avail) 299 + { 300 + int ret = 0; 301 + 302 + /* We have sent either a CP2112_TRANSFER_STATUS_REQUEST or a 303 + * CP2112_DATA_READ_FORCE_SEND and we are waiting for the response to 304 + * come in cp2112_raw_event or timeout. There will only be one of these 305 + * in flight at any one time. The timeout is extremely large and is a 306 + * last resort if the CP2112 has died. If we do timeout we don't expect 307 + * to receive the response which would cause data races, it's not like 308 + * we can do anything about it anyway. 309 + */ 310 + ret = wait_event_interruptible_timeout(dev->wait, 311 + atomic_read(avail), msecs_to_jiffies(RESPONSE_TIMEOUT)); 312 + if (-ERESTARTSYS == ret) 313 + return ret; 314 + if (!ret) 315 + return -ETIMEDOUT; 316 + 317 + atomic_set(avail, 0); 318 + return 0; 319 + } 320 + 321 + static int cp2112_xfer_status(struct cp2112_device *dev) 322 + { 323 + struct hid_device *hdev = dev->hdev; 324 + u8 buf[2]; 325 + int ret; 326 + 327 + buf[0] = CP2112_TRANSFER_STATUS_REQUEST; 328 + buf[1] = 0x01; 329 + atomic_set(&dev->xfer_avail, 0); 330 + 331 + ret = cp2112_hid_output(hdev, buf, 2, HID_OUTPUT_REPORT); 332 + if (ret < 0) { 333 + hid_warn(hdev, "Error requesting status: %d\n", ret); 334 + return ret; 335 + } 336 + 337 + ret = cp2112_wait(dev, &dev->xfer_avail); 338 + if (ret) 339 + return ret; 340 + 341 + return dev->xfer_status; 342 + } 343 + 344 + static int cp2112_read(struct cp2112_device *dev, u8 *data, size_t size) 345 + { 346 + struct hid_device *hdev = dev->hdev; 347 + struct cp2112_force_read_report report; 348 + int ret; 349 + 350 + report.report = CP2112_DATA_READ_FORCE_SEND; 351 + report.length = cpu_to_be16(size); 352 + 353 + atomic_set(&dev->read_avail, 0); 354 + 355 + ret = cp2112_hid_output(hdev, &report.report, sizeof(report), 356 + HID_OUTPUT_REPORT); 357 + if (ret < 0) { 358 + hid_warn(hdev, "Error requesting data: %d\n", ret); 359 + return ret; 360 + } 361 + 362 + ret = cp2112_wait(dev, &dev->read_avail); 363 + if (ret) 364 + return ret; 365 + 366 + hid_dbg(hdev, "read %d of %zd bytes requested\n", 367 + dev->read_length, size); 368 + 369 + if (size > dev->read_length) 370 + size = dev->read_length; 371 + 372 + memcpy(data, dev->read_data, size); 373 + return dev->read_length; 374 + } 375 + 376 + static int cp2112_read_req(void *buf, u8 slave_address, u16 length) 377 + { 378 + struct cp2112_read_req_report *report = buf; 379 + 380 + if (length < 1 || length > 512) 381 + return -EINVAL; 382 + 383 + report->report = CP2112_DATA_READ_REQUEST; 384 + report->slave_address = slave_address << 1; 385 + report->length = cpu_to_be16(length); 386 + return sizeof(*report); 387 + } 388 + 389 + static int cp2112_write_read_req(void *buf, u8 slave_address, u16 length, 390 + u8 command, u8 *data, u8 data_length) 391 + { 392 + struct cp2112_write_read_req_report *report = buf; 393 + 394 + if (length < 1 || length > 512 395 + || data_length > sizeof(report->target_address) - 1) 396 + return -EINVAL; 397 + 398 + report->report = CP2112_DATA_WRITE_READ_REQUEST; 399 + report->slave_address = slave_address << 1; 400 + report->length = cpu_to_be16(length); 401 + report->target_address_length = data_length + 1; 402 + report->target_address[0] = command; 403 + memcpy(&report->target_address[1], data, data_length); 404 + return data_length + 6; 405 + } 406 + 407 + static int cp2112_write_req(void *buf, u8 slave_address, u8 command, u8 *data, 408 + u8 data_length) 409 + { 410 + struct cp2112_write_req_report *report = buf; 411 + 412 + if (data_length > sizeof(report->data) - 1) 413 + return -EINVAL; 414 + 415 + report->report = CP2112_DATA_WRITE_REQUEST; 416 + report->slave_address = slave_address << 1; 417 + report->length = data_length + 1; 418 + report->data[0] = command; 419 + memcpy(&report->data[1], data, data_length); 420 + return data_length + 4; 421 + } 422 + 423 + static int cp2112_xfer(struct i2c_adapter *adap, u16 addr, 424 + unsigned short flags, char read_write, u8 command, 425 + int size, union i2c_smbus_data *data) 426 + { 427 + struct cp2112_device *dev = (struct cp2112_device *)adap->algo_data; 428 + struct hid_device *hdev = dev->hdev; 429 + u8 buf[64]; 430 + __be16 word; 431 + ssize_t count; 432 + size_t read_length = 0; 433 + unsigned int retries; 434 + int ret; 435 + 436 + hid_dbg(hdev, "%s addr 0x%x flags 0x%x cmd 0x%x size %d\n", 437 + read_write == I2C_SMBUS_WRITE ? "write" : "read", 438 + addr, flags, command, size); 439 + 440 + switch (size) { 441 + case I2C_SMBUS_BYTE: 442 + read_length = 1; 443 + 444 + if (I2C_SMBUS_READ == read_write) 445 + count = cp2112_read_req(buf, addr, read_length); 446 + else 447 + count = cp2112_write_req(buf, addr, data->byte, NULL, 448 + 0); 449 + break; 450 + case I2C_SMBUS_BYTE_DATA: 451 + read_length = 1; 452 + 453 + if (I2C_SMBUS_READ == read_write) 454 + count = cp2112_write_read_req(buf, addr, read_length, 455 + command, NULL, 0); 456 + else 457 + count = cp2112_write_req(buf, addr, command, 458 + &data->byte, 1); 459 + break; 460 + case I2C_SMBUS_WORD_DATA: 461 + read_length = 2; 462 + word = cpu_to_be16(data->word); 463 + 464 + if (I2C_SMBUS_READ == read_write) 465 + count = cp2112_write_read_req(buf, addr, read_length, 466 + command, NULL, 0); 467 + else 468 + count = cp2112_write_req(buf, addr, command, 469 + (u8 *)&word, 2); 470 + break; 471 + case I2C_SMBUS_PROC_CALL: 472 + size = I2C_SMBUS_WORD_DATA; 473 + read_write = I2C_SMBUS_READ; 474 + read_length = 2; 475 + word = cpu_to_be16(data->word); 476 + 477 + count = cp2112_write_read_req(buf, addr, read_length, command, 478 + (u8 *)&word, 2); 479 + break; 480 + case I2C_SMBUS_I2C_BLOCK_DATA: 481 + size = I2C_SMBUS_BLOCK_DATA; 482 + /* fallthrough */ 483 + case I2C_SMBUS_BLOCK_DATA: 484 + if (I2C_SMBUS_READ == read_write) { 485 + count = cp2112_write_read_req(buf, addr, 486 + I2C_SMBUS_BLOCK_MAX, 487 + command, NULL, 0); 488 + } else { 489 + count = cp2112_write_req(buf, addr, command, 490 + data->block, 491 + data->block[0] + 1); 492 + } 493 + break; 494 + case I2C_SMBUS_BLOCK_PROC_CALL: 495 + size = I2C_SMBUS_BLOCK_DATA; 496 + read_write = I2C_SMBUS_READ; 497 + 498 + count = cp2112_write_read_req(buf, addr, I2C_SMBUS_BLOCK_MAX, 499 + command, data->block, 500 + data->block[0] + 1); 501 + break; 502 + default: 503 + hid_warn(hdev, "Unsupported transaction %d\n", size); 504 + return -EOPNOTSUPP; 505 + } 506 + 507 + if (count < 0) 508 + return count; 509 + 510 + ret = hid_hw_power(hdev, PM_HINT_FULLON); 511 + if (ret < 0) { 512 + hid_err(hdev, "power management error: %d\n", ret); 513 + return ret; 514 + } 515 + 516 + ret = cp2112_hid_output(hdev, buf, count, HID_OUTPUT_REPORT); 517 + if (ret < 0) { 518 + hid_warn(hdev, "Error starting transaction: %d\n", ret); 519 + goto power_normal; 520 + } 521 + 522 + for (retries = 0; retries < XFER_STATUS_RETRIES; ++retries) { 523 + ret = cp2112_xfer_status(dev); 524 + if (-EBUSY == ret) 525 + continue; 526 + if (ret < 0) 527 + goto power_normal; 528 + break; 529 + } 530 + 531 + if (XFER_STATUS_RETRIES <= retries) { 532 + hid_warn(hdev, "Transfer timed out, cancelling.\n"); 533 + buf[0] = CP2112_CANCEL_TRANSFER; 534 + buf[1] = 0x01; 535 + 536 + ret = cp2112_hid_output(hdev, buf, 2, HID_OUTPUT_REPORT); 537 + if (ret < 0) 538 + hid_warn(hdev, "Error cancelling transaction: %d\n", 539 + ret); 540 + 541 + ret = -ETIMEDOUT; 542 + goto power_normal; 543 + } 544 + 545 + if (I2C_SMBUS_WRITE == read_write) { 546 + ret = 0; 547 + goto power_normal; 548 + } 549 + 550 + if (I2C_SMBUS_BLOCK_DATA == size) 551 + read_length = ret; 552 + 553 + ret = cp2112_read(dev, buf, read_length); 554 + if (ret < 0) 555 + goto power_normal; 556 + if (ret != read_length) { 557 + hid_warn(hdev, "short read: %d < %zd\n", ret, read_length); 558 + ret = -EIO; 559 + goto power_normal; 560 + } 561 + 562 + switch (size) { 563 + case I2C_SMBUS_BYTE: 564 + case I2C_SMBUS_BYTE_DATA: 565 + data->byte = buf[0]; 566 + break; 567 + case I2C_SMBUS_WORD_DATA: 568 + data->word = be16_to_cpup((__be16 *)buf); 569 + break; 570 + case I2C_SMBUS_BLOCK_DATA: 571 + if (read_length > I2C_SMBUS_BLOCK_MAX) { 572 + ret = -EPROTO; 573 + goto power_normal; 574 + } 575 + 576 + memcpy(data->block, buf, read_length); 577 + break; 578 + } 579 + 580 + ret = 0; 581 + power_normal: 582 + hid_hw_power(hdev, PM_HINT_NORMAL); 583 + hid_dbg(hdev, "transfer finished: %d\n", ret); 584 + return ret; 585 + } 586 + 587 + static u32 cp2112_functionality(struct i2c_adapter *adap) 588 + { 589 + return I2C_FUNC_SMBUS_BYTE | 590 + I2C_FUNC_SMBUS_BYTE_DATA | 591 + I2C_FUNC_SMBUS_WORD_DATA | 592 + I2C_FUNC_SMBUS_BLOCK_DATA | 593 + I2C_FUNC_SMBUS_I2C_BLOCK | 594 + I2C_FUNC_SMBUS_PROC_CALL | 595 + I2C_FUNC_SMBUS_BLOCK_PROC_CALL; 596 + } 597 + 598 + static const struct i2c_algorithm smbus_algorithm = { 599 + .smbus_xfer = cp2112_xfer, 600 + .functionality = cp2112_functionality, 601 + }; 602 + 603 + static int cp2112_get_usb_config(struct hid_device *hdev, 604 + struct cp2112_usb_config_report *cfg) 605 + { 606 + int ret; 607 + 608 + ret = cp2112_hid_get(hdev, CP2112_USB_CONFIG, (u8 *)cfg, sizeof(*cfg), 609 + HID_FEATURE_REPORT); 610 + if (ret != sizeof(*cfg)) { 611 + hid_err(hdev, "error reading usb config: %d\n", ret); 612 + if (ret < 0) 613 + return ret; 614 + return -EIO; 615 + } 616 + 617 + return 0; 618 + } 619 + 620 + static int cp2112_set_usb_config(struct hid_device *hdev, 621 + struct cp2112_usb_config_report *cfg) 622 + { 623 + int ret; 624 + 625 + BUG_ON(cfg->report != CP2112_USB_CONFIG); 626 + 627 + ret = cp2112_hid_output(hdev, (u8 *)cfg, sizeof(*cfg), 628 + HID_FEATURE_REPORT); 629 + if (ret != sizeof(*cfg)) { 630 + hid_err(hdev, "error writing usb config: %d\n", ret); 631 + if (ret < 0) 632 + return ret; 633 + return -EIO; 634 + } 635 + 636 + return 0; 637 + } 638 + 639 + static void chmod_sysfs_attrs(struct hid_device *hdev); 640 + 641 + #define CP2112_CONFIG_ATTR(name, store, format, ...) \ 642 + static ssize_t name##_store(struct device *kdev, \ 643 + struct device_attribute *attr, const char *buf, \ 644 + size_t count) \ 645 + { \ 646 + struct hid_device *hdev = container_of(kdev, struct hid_device, dev); \ 647 + struct cp2112_usb_config_report cfg; \ 648 + int ret = cp2112_get_usb_config(hdev, &cfg); \ 649 + if (ret) \ 650 + return ret; \ 651 + store; \ 652 + ret = cp2112_set_usb_config(hdev, &cfg); \ 653 + if (ret) \ 654 + return ret; \ 655 + chmod_sysfs_attrs(hdev); \ 656 + return count; \ 657 + } \ 658 + static ssize_t name##_show(struct device *kdev, \ 659 + struct device_attribute *attr, char *buf) \ 660 + { \ 661 + struct hid_device *hdev = container_of(kdev, struct hid_device, dev); \ 662 + struct cp2112_usb_config_report cfg; \ 663 + int ret = cp2112_get_usb_config(hdev, &cfg); \ 664 + if (ret) \ 665 + return ret; \ 666 + return scnprintf(buf, PAGE_SIZE, format, ##__VA_ARGS__); \ 667 + } \ 668 + static DEVICE_ATTR_RW(name); 669 + 670 + CP2112_CONFIG_ATTR(vendor_id, ({ 671 + u16 vid; 672 + 673 + if (sscanf(buf, "%hi", &vid) != 1) 674 + return -EINVAL; 675 + 676 + cfg.vid = cpu_to_le16(vid); 677 + cfg.mask = 0x01; 678 + }), "0x%04x\n", le16_to_cpu(cfg.vid)); 679 + 680 + CP2112_CONFIG_ATTR(product_id, ({ 681 + u16 pid; 682 + 683 + if (sscanf(buf, "%hi", &pid) != 1) 684 + return -EINVAL; 685 + 686 + cfg.pid = cpu_to_le16(pid); 687 + cfg.mask = 0x02; 688 + }), "0x%04x\n", le16_to_cpu(cfg.pid)); 689 + 690 + CP2112_CONFIG_ATTR(max_power, ({ 691 + int mA; 692 + 693 + if (sscanf(buf, "%i", &mA) != 1) 694 + return -EINVAL; 695 + 696 + cfg.max_power = (mA + 1) / 2; 697 + cfg.mask = 0x04; 698 + }), "%u mA\n", cfg.max_power * 2); 699 + 700 + CP2112_CONFIG_ATTR(power_mode, ({ 701 + if (sscanf(buf, "%hhi", &cfg.power_mode) != 1) 702 + return -EINVAL; 703 + 704 + cfg.mask = 0x08; 705 + }), "%u\n", cfg.power_mode); 706 + 707 + CP2112_CONFIG_ATTR(release_version, ({ 708 + if (sscanf(buf, "%hhi.%hhi", &cfg.release_major, &cfg.release_minor) 709 + != 2) 710 + return -EINVAL; 711 + 712 + cfg.mask = 0x10; 713 + }), "%u.%u\n", cfg.release_major, cfg.release_minor); 714 + 715 + #undef CP2112_CONFIG_ATTR 716 + 717 + struct cp2112_pstring_attribute { 718 + struct device_attribute attr; 719 + unsigned char report; 720 + }; 721 + 722 + static ssize_t pstr_store(struct device *kdev, 723 + struct device_attribute *kattr, const char *buf, 724 + size_t count) 725 + { 726 + struct hid_device *hdev = container_of(kdev, struct hid_device, dev); 727 + struct cp2112_pstring_attribute *attr = 728 + container_of(kattr, struct cp2112_pstring_attribute, attr); 729 + struct cp2112_string_report report; 730 + int ret; 731 + 732 + memset(&report, 0, sizeof(report)); 733 + 734 + ret = utf8s_to_utf16s(buf, count, UTF16_LITTLE_ENDIAN, 735 + report.string, ARRAY_SIZE(report.string)); 736 + report.report = attr->report; 737 + report.length = ret * sizeof(report.string[0]) + 2; 738 + report.type = USB_DT_STRING; 739 + 740 + ret = cp2112_hid_output(hdev, &report.report, report.length + 1, 741 + HID_FEATURE_REPORT); 742 + if (ret != report.length + 1) { 743 + hid_err(hdev, "error writing %s string: %d\n", kattr->attr.name, 744 + ret); 745 + if (ret < 0) 746 + return ret; 747 + return -EIO; 748 + } 749 + 750 + chmod_sysfs_attrs(hdev); 751 + return count; 752 + } 753 + 754 + static ssize_t pstr_show(struct device *kdev, 755 + struct device_attribute *kattr, char *buf) 756 + { 757 + struct hid_device *hdev = container_of(kdev, struct hid_device, dev); 758 + struct cp2112_pstring_attribute *attr = 759 + container_of(kattr, struct cp2112_pstring_attribute, attr); 760 + struct cp2112_string_report report; 761 + u8 length; 762 + int ret; 763 + 764 + ret = cp2112_hid_get(hdev, attr->report, &report.report, 765 + sizeof(report) - 1, HID_FEATURE_REPORT); 766 + if (ret < 3) { 767 + hid_err(hdev, "error reading %s string: %d\n", kattr->attr.name, 768 + ret); 769 + if (ret < 0) 770 + return ret; 771 + return -EIO; 772 + } 773 + 774 + if (report.length < 2) { 775 + hid_err(hdev, "invalid %s string length: %d\n", 776 + kattr->attr.name, report.length); 777 + return -EIO; 778 + } 779 + 780 + length = report.length > ret - 1 ? ret - 1 : report.length; 781 + length = (length - 2) / sizeof(report.string[0]); 782 + ret = utf16s_to_utf8s(report.string, length, UTF16_LITTLE_ENDIAN, buf, 783 + PAGE_SIZE - 1); 784 + buf[ret++] = '\n'; 785 + return ret; 786 + } 787 + 788 + #define CP2112_PSTR_ATTR(name, _report) \ 789 + static struct cp2112_pstring_attribute dev_attr_##name = { \ 790 + .attr = __ATTR(name, (S_IWUSR | S_IRUGO), pstr_show, pstr_store), \ 791 + .report = _report, \ 792 + }; 793 + 794 + CP2112_PSTR_ATTR(manufacturer, CP2112_MANUFACTURER_STRING); 795 + CP2112_PSTR_ATTR(product, CP2112_PRODUCT_STRING); 796 + CP2112_PSTR_ATTR(serial, CP2112_SERIAL_STRING); 797 + 798 + #undef CP2112_PSTR_ATTR 799 + 800 + static const struct attribute_group cp2112_attr_group = { 801 + .attrs = (struct attribute *[]){ 802 + &dev_attr_vendor_id.attr, 803 + &dev_attr_product_id.attr, 804 + &dev_attr_max_power.attr, 805 + &dev_attr_power_mode.attr, 806 + &dev_attr_release_version.attr, 807 + &dev_attr_manufacturer.attr.attr, 808 + &dev_attr_product.attr.attr, 809 + &dev_attr_serial.attr.attr, 810 + NULL 811 + } 812 + }; 813 + 814 + /* Chmoding our sysfs attributes is simply a way to expose which fields in the 815 + * PROM have already been programmed. We do not depend on this preventing 816 + * writing to these attributes since the CP2112 will simply ignore writes to 817 + * already-programmed fields. This is why there is no sense in fixing this 818 + * racy behaviour. 819 + */ 820 + static void chmod_sysfs_attrs(struct hid_device *hdev) 821 + { 822 + struct attribute **attr; 823 + u8 buf[2]; 824 + int ret; 825 + 826 + ret = cp2112_hid_get(hdev, CP2112_LOCK_BYTE, buf, sizeof(buf), 827 + HID_FEATURE_REPORT); 828 + if (ret != sizeof(buf)) { 829 + hid_err(hdev, "error reading lock byte: %d\n", ret); 830 + return; 831 + } 832 + 833 + for (attr = cp2112_attr_group.attrs; *attr; ++attr) { 834 + umode_t mode = (buf[1] & 1) ? S_IWUSR | S_IRUGO : S_IRUGO; 835 + ret = sysfs_chmod_file(&hdev->dev.kobj, *attr, mode); 836 + if (ret < 0) 837 + hid_err(hdev, "error chmoding sysfs file %s\n", 838 + (*attr)->name); 839 + buf[1] >>= 1; 840 + } 841 + } 842 + 843 + static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id) 844 + { 845 + struct cp2112_device *dev; 846 + u8 buf[3]; 847 + struct cp2112_smbus_config_report config; 848 + int ret; 849 + 850 + ret = hid_parse(hdev); 851 + if (ret) { 852 + hid_err(hdev, "parse failed\n"); 853 + return ret; 854 + } 855 + 856 + ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW); 857 + if (ret) { 858 + hid_err(hdev, "hw start failed\n"); 859 + return ret; 860 + } 861 + 862 + ret = hid_hw_open(hdev); 863 + if (ret) { 864 + hid_err(hdev, "hw open failed\n"); 865 + goto err_hid_stop; 866 + } 867 + 868 + ret = hid_hw_power(hdev, PM_HINT_FULLON); 869 + if (ret < 0) { 870 + hid_err(hdev, "power management error: %d\n", ret); 871 + goto err_hid_close; 872 + } 873 + 874 + ret = cp2112_hid_get(hdev, CP2112_GET_VERSION_INFO, buf, sizeof(buf), 875 + HID_FEATURE_REPORT); 876 + if (ret != sizeof(buf)) { 877 + hid_err(hdev, "error requesting version\n"); 878 + if (ret >= 0) 879 + ret = -EIO; 880 + goto err_power_normal; 881 + } 882 + 883 + hid_info(hdev, "Part Number: 0x%02X Device Version: 0x%02X\n", 884 + buf[1], buf[2]); 885 + 886 + ret = cp2112_hid_get(hdev, CP2112_SMBUS_CONFIG, (u8 *)&config, 887 + sizeof(config), HID_FEATURE_REPORT); 888 + if (ret != sizeof(config)) { 889 + hid_err(hdev, "error requesting SMBus config\n"); 890 + if (ret >= 0) 891 + ret = -EIO; 892 + goto err_power_normal; 893 + } 894 + 895 + config.retry_time = cpu_to_be16(1); 896 + 897 + ret = cp2112_hid_output(hdev, (u8 *)&config, sizeof(config), 898 + HID_FEATURE_REPORT); 899 + if (ret != sizeof(config)) { 900 + hid_err(hdev, "error setting SMBus config\n"); 901 + if (ret >= 0) 902 + ret = -EIO; 903 + goto err_power_normal; 904 + } 905 + 906 + dev = kzalloc(sizeof(*dev), GFP_KERNEL); 907 + if (!dev) { 908 + ret = -ENOMEM; 909 + goto err_power_normal; 910 + } 911 + 912 + hid_set_drvdata(hdev, (void *)dev); 913 + dev->hdev = hdev; 914 + dev->adap.owner = THIS_MODULE; 915 + dev->adap.class = I2C_CLASS_HWMON; 916 + dev->adap.algo = &smbus_algorithm; 917 + dev->adap.algo_data = dev; 918 + dev->adap.dev.parent = &hdev->dev; 919 + snprintf(dev->adap.name, sizeof(dev->adap.name), 920 + "CP2112 SMBus Bridge on hiddev%d", hdev->minor); 921 + init_waitqueue_head(&dev->wait); 922 + 923 + hid_device_io_start(hdev); 924 + ret = i2c_add_adapter(&dev->adap); 925 + hid_device_io_stop(hdev); 926 + 927 + if (ret) { 928 + hid_err(hdev, "error registering i2c adapter\n"); 929 + goto err_free_dev; 930 + } 931 + 932 + hid_dbg(hdev, "adapter registered\n"); 933 + 934 + dev->gc.label = "cp2112_gpio"; 935 + dev->gc.direction_input = cp2112_gpio_direction_input; 936 + dev->gc.direction_output = cp2112_gpio_direction_output; 937 + dev->gc.set = cp2112_gpio_set; 938 + dev->gc.get = cp2112_gpio_get; 939 + dev->gc.base = -1; 940 + dev->gc.ngpio = 8; 941 + dev->gc.can_sleep = 1; 942 + dev->gc.dev = &hdev->dev; 943 + 944 + ret = gpiochip_add(&dev->gc); 945 + if (ret < 0) { 946 + hid_err(hdev, "error registering gpio chip\n"); 947 + goto err_free_i2c; 948 + } 949 + 950 + ret = sysfs_create_group(&hdev->dev.kobj, &cp2112_attr_group); 951 + if (ret < 0) { 952 + hid_err(hdev, "error creating sysfs attrs\n"); 953 + goto err_gpiochip_remove; 954 + } 955 + 956 + chmod_sysfs_attrs(hdev); 957 + hid_hw_power(hdev, PM_HINT_NORMAL); 958 + 959 + return ret; 960 + 961 + err_gpiochip_remove: 962 + if (gpiochip_remove(&dev->gc) < 0) 963 + hid_err(hdev, "error removing gpio chip\n"); 964 + err_free_i2c: 965 + i2c_del_adapter(&dev->adap); 966 + err_free_dev: 967 + kfree(dev); 968 + err_power_normal: 969 + hid_hw_power(hdev, PM_HINT_NORMAL); 970 + err_hid_close: 971 + hid_hw_close(hdev); 972 + err_hid_stop: 973 + hid_hw_stop(hdev); 974 + return ret; 975 + } 976 + 977 + static void cp2112_remove(struct hid_device *hdev) 978 + { 979 + struct cp2112_device *dev = hid_get_drvdata(hdev); 980 + 981 + sysfs_remove_group(&hdev->dev.kobj, &cp2112_attr_group); 982 + if (gpiochip_remove(&dev->gc)) 983 + hid_err(hdev, "unable to remove gpio chip\n"); 984 + i2c_del_adapter(&dev->adap); 985 + /* i2c_del_adapter has finished removing all i2c devices from our 986 + * adapter. Well behaved devices should no longer call our cp2112_xfer 987 + * and should have waited for any pending calls to finish. It has also 988 + * waited for device_unregister(&adap->dev) to complete. Therefore we 989 + * can safely free our struct cp2112_device. 990 + */ 991 + hid_hw_close(hdev); 992 + hid_hw_stop(hdev); 993 + kfree(dev); 994 + } 995 + 996 + static int cp2112_raw_event(struct hid_device *hdev, struct hid_report *report, 997 + u8 *data, int size) 998 + { 999 + struct cp2112_device *dev = hid_get_drvdata(hdev); 1000 + struct cp2112_xfer_status_report *xfer = (void *)data; 1001 + 1002 + switch (data[0]) { 1003 + case CP2112_TRANSFER_STATUS_RESPONSE: 1004 + hid_dbg(hdev, "xfer status: %02x %02x %04x %04x\n", 1005 + xfer->status0, xfer->status1, 1006 + be16_to_cpu(xfer->retries), be16_to_cpu(xfer->length)); 1007 + 1008 + switch (xfer->status0) { 1009 + case STATUS0_IDLE: 1010 + dev->xfer_status = -EAGAIN; 1011 + break; 1012 + case STATUS0_BUSY: 1013 + dev->xfer_status = -EBUSY; 1014 + break; 1015 + case STATUS0_COMPLETE: 1016 + dev->xfer_status = be16_to_cpu(xfer->length); 1017 + break; 1018 + case STATUS0_ERROR: 1019 + switch (xfer->status1) { 1020 + case STATUS1_TIMEOUT_NACK: 1021 + case STATUS1_TIMEOUT_BUS: 1022 + dev->xfer_status = -ETIMEDOUT; 1023 + break; 1024 + default: 1025 + dev->xfer_status = -EIO; 1026 + break; 1027 + } 1028 + break; 1029 + default: 1030 + dev->xfer_status = -EINVAL; 1031 + break; 1032 + } 1033 + 1034 + atomic_set(&dev->xfer_avail, 1); 1035 + break; 1036 + case CP2112_DATA_READ_RESPONSE: 1037 + hid_dbg(hdev, "read response: %02x %02x\n", data[1], data[2]); 1038 + 1039 + dev->read_length = data[2]; 1040 + if (dev->read_length > sizeof(dev->read_data)) 1041 + dev->read_length = sizeof(dev->read_data); 1042 + 1043 + memcpy(dev->read_data, &data[3], dev->read_length); 1044 + atomic_set(&dev->read_avail, 1); 1045 + break; 1046 + default: 1047 + hid_err(hdev, "unknown report\n"); 1048 + 1049 + return 0; 1050 + } 1051 + 1052 + wake_up_interruptible(&dev->wait); 1053 + return 1; 1054 + } 1055 + 1056 + static struct hid_driver cp2112_driver = { 1057 + .name = "cp2112", 1058 + .id_table = cp2112_devices, 1059 + .probe = cp2112_probe, 1060 + .remove = cp2112_remove, 1061 + .raw_event = cp2112_raw_event, 1062 + }; 1063 + 1064 + module_hid_driver(cp2112_driver); 1065 + MODULE_DESCRIPTION("Silicon Labs HID USB to SMBus master bridge"); 1066 + MODULE_AUTHOR("David Barksdale <dbarksdale@uplogix.com>"); 1067 + MODULE_LICENSE("GPL"); 1068 +
+1
drivers/hid/hid-ids.h
··· 240 240 241 241 #define USB_VENDOR_ID_CYGNAL 0x10c4 242 242 #define USB_DEVICE_ID_CYGNAL_RADIO_SI470X 0x818a 243 + #define USB_DEVICE_ID_CYGNAL_CP2112 0xea90 243 244 244 245 #define USB_VENDOR_ID_CYPRESS 0x04b4 245 246 #define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001