aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2014-03-14 10:27:36 -0400
committerJiri Kosina <jkosina@suse.cz>2014-03-14 10:27:36 -0400
commitc16527cdccaa5dbbda38c7886f9ac65129302e88 (patch)
treef6d6651b42512ff7551b35fd1a237e6b8fa7619e
parent3a75b24949a8d34d2014866006e30dc69dd567c8 (diff)
parent0438ee7080ac83a6a831c52bc4e8c29dc2306e95 (diff)
Merge branch 'for-3.15/hid-cp2112' into for-3.15/hid-core-ll-transport-cleanup
-rw-r--r--drivers/hid/Kconfig9
-rw-r--r--drivers/hid/Makefile1
-rw-r--r--drivers/hid/hid-core.c1
-rw-r--r--drivers/hid/hid-cp2112.c1068
-rw-r--r--drivers/hid/hid-ids.h1
5 files changed, 1080 insertions, 0 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index f7220011a00b..669cc19573ae 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -175,6 +175,15 @@ config HID_PRODIKEYS
175 multimedia keyboard, but will lack support for the musical keyboard 175 multimedia keyboard, but will lack support for the musical keyboard
176 and some additional multimedia keys. 176 and some additional multimedia keys.
177 177
178config 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
178config HID_CYPRESS 187config HID_CYPRESS
179 tristate "Cypress mouse and barcode readers" if EXPERT 188 tristate "Cypress mouse and barcode readers" if EXPERT
180 depends on HID 189 depends on HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 30e44318f87f..fc712dde02a4 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_HID_AUREAL) += hid-aureal.o
41obj-$(CONFIG_HID_BELKIN) += hid-belkin.o 41obj-$(CONFIG_HID_BELKIN) += hid-belkin.o
42obj-$(CONFIG_HID_CHERRY) += hid-cherry.o 42obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
43obj-$(CONFIG_HID_CHICONY) += hid-chicony.o 43obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
44obj-$(CONFIG_HID_CP2112) += hid-cp2112.o
44obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o 45obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
45obj-$(CONFIG_HID_DRAGONRISE) += hid-dr.o 46obj-$(CONFIG_HID_DRAGONRISE) += hid-dr.o
46obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o 47obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 0b57babe3f9f..ddb981db08bd 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1732,6 +1732,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
1732 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, 1732 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
1733 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) }, 1733 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
1734 { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, 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 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, 1736 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
1736 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, 1737 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) },
1737 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) }, 1738 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) },
diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
new file mode 100644
index 000000000000..1025982c7fd3
--- /dev/null
+++ b/drivers/hid/hid-cp2112.c
@@ -0,0 +1,1068 @@
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
35enum {
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
56enum {
57 STATUS0_IDLE = 0x00,
58 STATUS0_BUSY = 0x01,
59 STATUS0_COMPLETE = 0x02,
60 STATUS0_ERROR = 0x03,
61};
62
63enum {
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
72struct 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
83struct 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
96struct cp2112_read_req_report {
97 u8 report; /* CP2112_DATA_READ_REQUEST */
98 u8 slave_address;
99 __be16 length;
100} __packed;
101
102struct 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
110struct 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
117struct cp2112_force_read_report {
118 u8 report; /* CP2112_DATA_READ_FORCE_SEND */
119 __be16 length;
120} __packed;
121
122struct 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
130struct 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. */
141static 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. */
145static const int RESPONSE_TIMEOUT = 50;
146
147static const struct hid_device_id cp2112_devices[] = {
148 { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) },
149 { }
150};
151MODULE_DEVICE_TABLE(hid, cp2112_devices);
152
153struct 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
165static int gpio_push_pull = 0xFF;
166module_param(gpio_push_pull, int, S_IRUGO | S_IWUSR);
167MODULE_PARM_DESC(gpio_push_pull, "GPIO push-pull configuration bitmask");
168
169static 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
198static 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
216static 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
234static 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
266static 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
283static 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
298static 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
321static 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
344static 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
376static 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
389static 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
407static 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
423static 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;
581power_normal:
582 hid_hw_power(hdev, PM_HINT_NORMAL);
583 hid_dbg(hdev, "transfer finished: %d\n", ret);
584 return ret;
585}
586
587static 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
598static const struct i2c_algorithm smbus_algorithm = {
599 .smbus_xfer = cp2112_xfer,
600 .functionality = cp2112_functionality,
601};
602
603static 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
620static 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
639static void chmod_sysfs_attrs(struct hid_device *hdev);
640
641#define CP2112_CONFIG_ATTR(name, store, format, ...) \
642static 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} \
658static 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} \
668static DEVICE_ATTR_RW(name);
669
670CP2112_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
680CP2112_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
690CP2112_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
700CP2112_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
707CP2112_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
717struct cp2112_pstring_attribute {
718 struct device_attribute attr;
719 unsigned char report;
720};
721
722static 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
754static 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) \
789static struct cp2112_pstring_attribute dev_attr_##name = { \
790 .attr = __ATTR(name, (S_IWUSR | S_IRUGO), pstr_show, pstr_store), \
791 .report = _report, \
792};
793
794CP2112_PSTR_ATTR(manufacturer, CP2112_MANUFACTURER_STRING);
795CP2112_PSTR_ATTR(product, CP2112_PRODUCT_STRING);
796CP2112_PSTR_ATTR(serial, CP2112_SERIAL_STRING);
797
798#undef CP2112_PSTR_ATTR
799
800static 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 */
820static 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
843static 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
961err_gpiochip_remove:
962 if (gpiochip_remove(&dev->gc) < 0)
963 hid_err(hdev, "error removing gpio chip\n");
964err_free_i2c:
965 i2c_del_adapter(&dev->adap);
966err_free_dev:
967 kfree(dev);
968err_power_normal:
969 hid_hw_power(hdev, PM_HINT_NORMAL);
970err_hid_close:
971 hid_hw_close(hdev);
972err_hid_stop:
973 hid_hw_stop(hdev);
974 return ret;
975}
976
977static 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
996static 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
1056static 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
1064module_hid_driver(cp2112_driver);
1065MODULE_DESCRIPTION("Silicon Labs HID USB to SMBus master bridge");
1066MODULE_AUTHOR("David Barksdale <dbarksdale@uplogix.com>");
1067MODULE_LICENSE("GPL");
1068
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 92b40c09d917..239f29c1c85c 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -240,6 +240,7 @@
240 240
241#define USB_VENDOR_ID_CYGNAL 0x10c4 241#define USB_VENDOR_ID_CYGNAL 0x10c4
242#define USB_DEVICE_ID_CYGNAL_RADIO_SI470X 0x818a 242#define USB_DEVICE_ID_CYGNAL_RADIO_SI470X 0x818a
243#define USB_DEVICE_ID_CYGNAL_CP2112 0xea90
243 244
244#define USB_VENDOR_ID_CYPRESS 0x04b4 245#define USB_VENDOR_ID_CYPRESS 0x04b4
245#define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001 246#define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001