aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-cp2112.c
diff options
context:
space:
mode:
authorDavid Barksdale <dbarksdale@uplogix.com>2014-02-04 13:42:48 -0500
committerJiri Kosina <jkosina@suse.cz>2014-02-17 17:33:17 -0500
commite932d817866770d456815c9a84b7ed94f0589d80 (patch)
tree0c210184edf96177cea0dfbcd0ad7c841be0586e /drivers/hid/hid-cp2112.c
parent4988abf1749241bc80600a6b3283d03898d2717c (diff)
HID: add hid-cp2112 driver
This patch adds support for the Silicon Labs CP2112 "Single-Chip HID USB to SMBus Master Bridge." This is a HID device driver which registers as an i2c adapter and gpiochip to expose these functions of the CP2112. The customizable USB descriptor fields are exposed as sysfs attributes. The SMBus byte-read, byte-data-read/write, and word-data-read transfer modes have been tested by talking to an i2c sensor. The GPIO functions and USB descriptor field programming have also been tested. Signed-off-by: David Barksdale <dbarksdale@uplogix.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-cp2112.c')
-rw-r--r--drivers/hid/hid-cp2112.c1066
1 files changed, 1066 insertions, 0 deletions
diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
new file mode 100644
index 000000000000..ca0f356a2384
--- /dev/null
+++ b/drivers/hid/hid-cp2112.c
@@ -0,0 +1,1066 @@
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 = hdev->hid_get_raw_report(hdev, CP2112_GPIO_CONFIG, buf,
178 sizeof(buf), HID_FEATURE_REPORT);
179 if (ret != sizeof(buf)) {
180 hid_err(hdev, "error requesting GPIO config: %d\n", ret);
181 return ret;
182 }
183
184 buf[1] &= ~(1 << offset);
185 buf[2] = gpio_push_pull;
186
187 ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf),
188 HID_FEATURE_REPORT);
189 if (ret < 0) {
190 hid_err(hdev, "error setting GPIO config: %d\n", ret);
191 return ret;
192 }
193
194 return 0;
195}
196
197static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
198{
199 struct cp2112_device *dev = container_of(chip, struct cp2112_device,
200 gc);
201 struct hid_device *hdev = dev->hdev;
202 u8 buf[3];
203 int ret;
204
205 buf[0] = CP2112_GPIO_SET;
206 buf[1] = value ? 0xff : 0;
207 buf[2] = 1 << offset;
208
209 ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf),
210 HID_FEATURE_REPORT);
211 if (ret < 0)
212 hid_err(hdev, "error setting GPIO values: %d\n", ret);
213}
214
215static int cp2112_gpio_get(struct gpio_chip *chip, unsigned offset)
216{
217 struct cp2112_device *dev = container_of(chip, struct cp2112_device,
218 gc);
219 struct hid_device *hdev = dev->hdev;
220 u8 buf[2];
221 int ret;
222
223 ret = hdev->hid_get_raw_report(hdev, CP2112_GPIO_GET, buf, sizeof(buf),
224 HID_FEATURE_REPORT);
225 if (ret != sizeof(buf)) {
226 hid_err(hdev, "error requesting GPIO values: %d\n", ret);
227 return ret;
228 }
229
230 return (buf[1] >> offset) & 1;
231}
232
233static int cp2112_gpio_direction_output(struct gpio_chip *chip,
234 unsigned offset, int value)
235{
236 struct cp2112_device *dev = container_of(chip, struct cp2112_device,
237 gc);
238 struct hid_device *hdev = dev->hdev;
239 u8 buf[5];
240 int ret;
241
242 cp2112_gpio_set(chip, offset, value);
243
244 ret = hdev->hid_get_raw_report(hdev, CP2112_GPIO_CONFIG, buf,
245 sizeof(buf), HID_FEATURE_REPORT);
246 if (ret != sizeof(buf)) {
247 hid_err(hdev, "error requesting GPIO config: %d\n", ret);
248 return ret;
249 }
250
251 buf[1] |= 1 << offset;
252 buf[2] = gpio_push_pull;
253
254 ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf),
255 HID_FEATURE_REPORT);
256 if (ret < 0) {
257 hid_err(hdev, "error setting GPIO config: %d\n", ret);
258 return ret;
259 }
260
261 return 0;
262}
263
264static int cp2112_hid_get(struct hid_device *hdev, unsigned char report_number,
265 u8 *data, size_t count, unsigned char report_type)
266{
267 u8 *buf;
268 int ret;
269
270 buf = kmalloc(count, GFP_KERNEL);
271 if (!buf)
272 return -ENOMEM;
273
274 ret = hdev->hid_get_raw_report(hdev, report_number, buf, count,
275 report_type);
276 memcpy(data, buf, count);
277 kfree(buf);
278 return ret;
279}
280
281static int cp2112_hid_output(struct hid_device *hdev, u8 *data, size_t count,
282 unsigned char report_type)
283{
284 u8 *buf;
285 int ret;
286
287 buf = kmemdup(data, count, GFP_KERNEL);
288 if (!buf)
289 return -ENOMEM;
290
291 ret = hdev->hid_output_raw_report(hdev, buf, count, report_type);
292 kfree(buf);
293 return ret;
294}
295
296static int cp2112_wait(struct cp2112_device *dev, atomic_t *avail)
297{
298 int ret = 0;
299
300 /* We have sent either a CP2112_TRANSFER_STATUS_REQUEST or a
301 * CP2112_DATA_READ_FORCE_SEND and we are waiting for the response to
302 * come in cp2112_raw_event or timeout. There will only be one of these
303 * in flight at any one time. The timeout is extremely large and is a
304 * last resort if the CP2112 has died. If we do timeout we don't expect
305 * to receive the response which would cause data races, it's not like
306 * we can do anything about it anyway.
307 */
308 ret = wait_event_interruptible_timeout(dev->wait,
309 atomic_read(avail), msecs_to_jiffies(RESPONSE_TIMEOUT));
310 if (-ERESTARTSYS == ret)
311 return ret;
312 if (!ret)
313 return -ETIMEDOUT;
314
315 atomic_set(avail, 0);
316 return 0;
317}
318
319static int cp2112_xfer_status(struct cp2112_device *dev)
320{
321 struct hid_device *hdev = dev->hdev;
322 u8 buf[2];
323 int ret;
324
325 buf[0] = CP2112_TRANSFER_STATUS_REQUEST;
326 buf[1] = 0x01;
327 atomic_set(&dev->xfer_avail, 0);
328
329 ret = cp2112_hid_output(hdev, buf, 2, HID_OUTPUT_REPORT);
330 if (ret < 0) {
331 hid_warn(hdev, "Error requesting status: %d\n", ret);
332 return ret;
333 }
334
335 ret = cp2112_wait(dev, &dev->xfer_avail);
336 if (ret)
337 return ret;
338
339 return dev->xfer_status;
340}
341
342static int cp2112_read(struct cp2112_device *dev, u8 *data, size_t size)
343{
344 struct hid_device *hdev = dev->hdev;
345 struct cp2112_force_read_report report;
346 int ret;
347
348 report.report = CP2112_DATA_READ_FORCE_SEND;
349 report.length = cpu_to_be16(size);
350
351 atomic_set(&dev->read_avail, 0);
352
353 ret = cp2112_hid_output(hdev, &report.report, sizeof(report),
354 HID_OUTPUT_REPORT);
355 if (ret < 0) {
356 hid_warn(hdev, "Error requesting data: %d\n", ret);
357 return ret;
358 }
359
360 ret = cp2112_wait(dev, &dev->read_avail);
361 if (ret)
362 return ret;
363
364 hid_dbg(hdev, "read %d of %d bytes requested\n",
365 dev->read_length, size);
366
367 if (size > dev->read_length)
368 size = dev->read_length;
369
370 memcpy(data, dev->read_data, size);
371 return dev->read_length;
372}
373
374static int cp2112_read_req(void *buf, u8 slave_address, u16 length)
375{
376 struct cp2112_read_req_report *report = buf;
377
378 if (length < 1 || length > 512)
379 return -EINVAL;
380
381 report->report = CP2112_DATA_READ_REQUEST;
382 report->slave_address = slave_address << 1;
383 report->length = cpu_to_be16(length);
384 return sizeof(*report);
385}
386
387static int cp2112_write_read_req(void *buf, u8 slave_address, u16 length,
388 u8 command, u8 *data, u8 data_length)
389{
390 struct cp2112_write_read_req_report *report = buf;
391
392 if (length < 1 || length > 512
393 || data_length > sizeof(report->target_address) - 1)
394 return -EINVAL;
395
396 report->report = CP2112_DATA_WRITE_READ_REQUEST;
397 report->slave_address = slave_address << 1;
398 report->length = cpu_to_be16(length);
399 report->target_address_length = data_length + 1;
400 report->target_address[0] = command;
401 memcpy(&report->target_address[1], data, data_length);
402 return data_length + 6;
403}
404
405static int cp2112_write_req(void *buf, u8 slave_address, u8 command, u8 *data,
406 u8 data_length)
407{
408 struct cp2112_write_req_report *report = buf;
409
410 if (data_length > sizeof(report->data) - 1)
411 return -EINVAL;
412
413 report->report = CP2112_DATA_WRITE_REQUEST;
414 report->slave_address = slave_address << 1;
415 report->length = data_length + 1;
416 report->data[0] = command;
417 memcpy(&report->data[1], data, data_length);
418 return data_length + 4;
419}
420
421static int cp2112_xfer(struct i2c_adapter *adap, u16 addr,
422 unsigned short flags, char read_write, u8 command,
423 int size, union i2c_smbus_data *data)
424{
425 struct cp2112_device *dev = (struct cp2112_device *)adap->algo_data;
426 struct hid_device *hdev = dev->hdev;
427 u8 buf[64];
428 __be16 word;
429 size_t count;
430 size_t read_length = 0;
431 unsigned int retries;
432 int ret;
433
434 hid_dbg(hdev, "%s addr 0x%x flags 0x%x cmd 0x%x size %d\n",
435 read_write == I2C_SMBUS_WRITE ? "write" : "read",
436 addr, flags, command, size);
437
438 switch (size) {
439 case I2C_SMBUS_BYTE:
440 read_length = 1;
441
442 if (I2C_SMBUS_READ == read_write)
443 count = cp2112_read_req(buf, addr, read_length);
444 else
445 count = cp2112_write_req(buf, addr, data->byte, NULL,
446 0);
447 break;
448 case I2C_SMBUS_BYTE_DATA:
449 read_length = 1;
450
451 if (I2C_SMBUS_READ == read_write)
452 count = cp2112_write_read_req(buf, addr, read_length,
453 command, NULL, 0);
454 else
455 count = cp2112_write_req(buf, addr, command,
456 &data->byte, 1);
457 break;
458 case I2C_SMBUS_WORD_DATA:
459 read_length = 2;
460 word = cpu_to_be16(data->word);
461
462 if (I2C_SMBUS_READ == read_write)
463 count = cp2112_write_read_req(buf, addr, read_length,
464 command, NULL, 0);
465 else
466 count = cp2112_write_req(buf, addr, command,
467 (u8 *)&word, 2);
468 break;
469 case I2C_SMBUS_PROC_CALL:
470 size = I2C_SMBUS_WORD_DATA;
471 read_write = I2C_SMBUS_READ;
472 read_length = 2;
473 word = cpu_to_be16(data->word);
474
475 count = cp2112_write_read_req(buf, addr, read_length, command,
476 (u8 *)&word, 2);
477 break;
478 case I2C_SMBUS_I2C_BLOCK_DATA:
479 size = I2C_SMBUS_BLOCK_DATA;
480 /* fallthrough */
481 case I2C_SMBUS_BLOCK_DATA:
482 if (I2C_SMBUS_READ == read_write) {
483 count = cp2112_write_read_req(buf, addr,
484 I2C_SMBUS_BLOCK_MAX,
485 command, NULL, 0);
486 } else {
487 count = cp2112_write_req(buf, addr, command,
488 data->block,
489 data->block[0] + 1);
490 }
491 break;
492 case I2C_SMBUS_BLOCK_PROC_CALL:
493 size = I2C_SMBUS_BLOCK_DATA;
494 read_write = I2C_SMBUS_READ;
495
496 count = cp2112_write_read_req(buf, addr, I2C_SMBUS_BLOCK_MAX,
497 command, data->block,
498 data->block[0] + 1);
499 break;
500 default:
501 hid_warn(hdev, "Unsupported transaction %d\n", size);
502 return -EOPNOTSUPP;
503 }
504
505 if (count < 0)
506 return count;
507
508 ret = hid_hw_power(hdev, PM_HINT_FULLON);
509 if (ret < 0) {
510 hid_err(hdev, "power management error: %d\n", ret);
511 return ret;
512 }
513
514 ret = cp2112_hid_output(hdev, buf, count, HID_OUTPUT_REPORT);
515 if (ret < 0) {
516 hid_warn(hdev, "Error starting transaction: %d\n", ret);
517 goto power_normal;
518 }
519
520 for (retries = 0; retries < XFER_STATUS_RETRIES; ++retries) {
521 ret = cp2112_xfer_status(dev);
522 if (-EBUSY == ret)
523 continue;
524 if (ret < 0)
525 goto power_normal;
526 break;
527 }
528
529 if (XFER_STATUS_RETRIES <= retries) {
530 hid_warn(hdev, "Transfer timed out, cancelling.\n");
531 buf[0] = CP2112_CANCEL_TRANSFER;
532 buf[1] = 0x01;
533
534 ret = cp2112_hid_output(hdev, buf, 2, HID_OUTPUT_REPORT);
535 if (ret < 0)
536 hid_warn(hdev, "Error cancelling transaction: %d\n",
537 ret);
538
539 ret = -ETIMEDOUT;
540 goto power_normal;
541 }
542
543 if (I2C_SMBUS_WRITE == read_write) {
544 ret = 0;
545 goto power_normal;
546 }
547
548 if (I2C_SMBUS_BLOCK_DATA == size)
549 read_length = ret;
550
551 ret = cp2112_read(dev, buf, read_length);
552 if (ret < 0)
553 goto power_normal;
554 if (ret != read_length) {
555 hid_warn(hdev, "short read: %d < %d\n", ret, read_length);
556 ret = -EIO;
557 goto power_normal;
558 }
559
560 switch (size) {
561 case I2C_SMBUS_BYTE:
562 case I2C_SMBUS_BYTE_DATA:
563 data->byte = buf[0];
564 break;
565 case I2C_SMBUS_WORD_DATA:
566 data->word = be16_to_cpup((__be16 *)buf);
567 break;
568 case I2C_SMBUS_BLOCK_DATA:
569 if (read_length > I2C_SMBUS_BLOCK_MAX) {
570 ret = -EPROTO;
571 goto power_normal;
572 }
573
574 memcpy(data->block, buf, read_length);
575 break;
576 }
577
578 ret = 0;
579power_normal:
580 hid_hw_power(hdev, PM_HINT_NORMAL);
581 hid_dbg(hdev, "transfer finished: %d\n", ret);
582 return ret;
583}
584
585static u32 cp2112_functionality(struct i2c_adapter *adap)
586{
587 return I2C_FUNC_SMBUS_BYTE |
588 I2C_FUNC_SMBUS_BYTE_DATA |
589 I2C_FUNC_SMBUS_WORD_DATA |
590 I2C_FUNC_SMBUS_BLOCK_DATA |
591 I2C_FUNC_SMBUS_I2C_BLOCK |
592 I2C_FUNC_SMBUS_PROC_CALL |
593 I2C_FUNC_SMBUS_BLOCK_PROC_CALL;
594}
595
596static const struct i2c_algorithm smbus_algorithm = {
597 .smbus_xfer = cp2112_xfer,
598 .functionality = cp2112_functionality,
599};
600
601static int cp2112_get_usb_config(struct hid_device *hdev,
602 struct cp2112_usb_config_report *cfg)
603{
604 int ret;
605
606 ret = cp2112_hid_get(hdev, CP2112_USB_CONFIG, (u8 *)cfg, sizeof(*cfg),
607 HID_FEATURE_REPORT);
608 if (ret != sizeof(*cfg)) {
609 hid_err(hdev, "error reading usb config: %d\n", ret);
610 if (ret < 0)
611 return ret;
612 return -EIO;
613 }
614
615 return 0;
616}
617
618static int cp2112_set_usb_config(struct hid_device *hdev,
619 struct cp2112_usb_config_report *cfg)
620{
621 int ret;
622
623 BUG_ON(cfg->report != CP2112_USB_CONFIG);
624
625 ret = cp2112_hid_output(hdev, (u8 *)cfg, sizeof(*cfg),
626 HID_FEATURE_REPORT);
627 if (ret != sizeof(*cfg)) {
628 hid_err(hdev, "error writing usb config: %d\n", ret);
629 if (ret < 0)
630 return ret;
631 return -EIO;
632 }
633
634 return 0;
635}
636
637static void chmod_sysfs_attrs(struct hid_device *hdev);
638
639#define CP2112_CONFIG_ATTR(name, store, format, ...) \
640static ssize_t name##_store(struct device *kdev, \
641 struct device_attribute *attr, const char *buf, \
642 size_t count) \
643{ \
644 struct hid_device *hdev = container_of(kdev, struct hid_device, dev); \
645 struct cp2112_usb_config_report cfg; \
646 int ret = cp2112_get_usb_config(hdev, &cfg); \
647 if (ret) \
648 return ret; \
649 store; \
650 ret = cp2112_set_usb_config(hdev, &cfg); \
651 if (ret) \
652 return ret; \
653 chmod_sysfs_attrs(hdev); \
654 return count; \
655} \
656static ssize_t name##_show(struct device *kdev, \
657 struct device_attribute *attr, char *buf) \
658{ \
659 struct hid_device *hdev = container_of(kdev, struct hid_device, dev); \
660 struct cp2112_usb_config_report cfg; \
661 int ret = cp2112_get_usb_config(hdev, &cfg); \
662 if (ret) \
663 return ret; \
664 return scnprintf(buf, PAGE_SIZE, format, ##__VA_ARGS__); \
665} \
666DEVICE_ATTR_RW(name);
667
668CP2112_CONFIG_ATTR(vendor_id, ({
669 u16 vid;
670
671 if (sscanf(buf, "%hi", &vid) != 1)
672 return -EINVAL;
673
674 cfg.vid = cpu_to_le16(vid);
675 cfg.mask = 0x01;
676}), "0x%04x\n", le16_to_cpu(cfg.vid));
677
678CP2112_CONFIG_ATTR(product_id, ({
679 u16 pid;
680
681 if (sscanf(buf, "%hi", &pid) != 1)
682 return -EINVAL;
683
684 cfg.pid = cpu_to_le16(pid);
685 cfg.mask = 0x02;
686}), "0x%04x\n", le16_to_cpu(cfg.pid));
687
688CP2112_CONFIG_ATTR(max_power, ({
689 int mA;
690
691 if (sscanf(buf, "%i", &mA) != 1)
692 return -EINVAL;
693
694 cfg.max_power = (mA + 1) / 2;
695 cfg.mask = 0x04;
696}), "%u mA\n", cfg.max_power * 2);
697
698CP2112_CONFIG_ATTR(power_mode, ({
699 if (sscanf(buf, "%hhi", &cfg.power_mode) != 1)
700 return -EINVAL;
701
702 cfg.mask = 0x08;
703}), "%u\n", cfg.power_mode);
704
705CP2112_CONFIG_ATTR(release_version, ({
706 if (sscanf(buf, "%hhi.%hhi", &cfg.release_major, &cfg.release_minor)
707 != 2)
708 return -EINVAL;
709
710 cfg.mask = 0x10;
711}), "%u.%u\n", cfg.release_major, cfg.release_minor);
712
713#undef CP2112_CONFIG_ATTR
714
715struct cp2112_pstring_attribute {
716 struct device_attribute attr;
717 unsigned char report;
718};
719
720static ssize_t pstr_store(struct device *kdev,
721 struct device_attribute *kattr, const char *buf,
722 size_t count)
723{
724 struct hid_device *hdev = container_of(kdev, struct hid_device, dev);
725 struct cp2112_pstring_attribute *attr =
726 container_of(kattr, struct cp2112_pstring_attribute, attr);
727 struct cp2112_string_report report;
728 int ret;
729
730 memset(&report, 0, sizeof(report));
731
732 ret = utf8s_to_utf16s(buf, count, UTF16_LITTLE_ENDIAN,
733 report.string, ARRAY_SIZE(report.string));
734 report.report = attr->report;
735 report.length = ret * sizeof(report.string[0]) + 2;
736 report.type = USB_DT_STRING;
737
738 ret = cp2112_hid_output(hdev, &report.report, report.length + 1,
739 HID_FEATURE_REPORT);
740 if (ret != report.length + 1) {
741 hid_err(hdev, "error writing %s string: %d\n", kattr->attr.name,
742 ret);
743 if (ret < 0)
744 return ret;
745 return -EIO;
746 }
747
748 chmod_sysfs_attrs(hdev);
749 return count;
750}
751
752static ssize_t pstr_show(struct device *kdev,
753 struct device_attribute *kattr, char *buf)
754{
755 struct hid_device *hdev = container_of(kdev, struct hid_device, dev);
756 struct cp2112_pstring_attribute *attr =
757 container_of(kattr, struct cp2112_pstring_attribute, attr);
758 struct cp2112_string_report report;
759 u8 length;
760 int ret;
761
762 ret = cp2112_hid_get(hdev, attr->report, &report.report,
763 sizeof(report) - 1, HID_FEATURE_REPORT);
764 if (ret < 3) {
765 hid_err(hdev, "error reading %s string: %d\n", kattr->attr.name,
766 ret);
767 if (ret < 0)
768 return ret;
769 return -EIO;
770 }
771
772 if (report.length < 2) {
773 hid_err(hdev, "invalid %s string length: %d\n",
774 kattr->attr.name, report.length);
775 return -EIO;
776 }
777
778 length = report.length > ret - 1 ? ret - 1 : report.length;
779 length = (length - 2) / sizeof(report.string[0]);
780 ret = utf16s_to_utf8s(report.string, length, UTF16_LITTLE_ENDIAN, buf,
781 PAGE_SIZE - 1);
782 buf[ret++] = '\n';
783 return ret;
784}
785
786#define CP2112_PSTR_ATTR(name, _report) \
787struct cp2112_pstring_attribute dev_attr_##name = { \
788 .attr = __ATTR(name, (S_IWUSR | S_IRUGO), pstr_show, pstr_store), \
789 .report = _report, \
790};
791
792CP2112_PSTR_ATTR(manufacturer, CP2112_MANUFACTURER_STRING);
793CP2112_PSTR_ATTR(product, CP2112_PRODUCT_STRING);
794CP2112_PSTR_ATTR(serial, CP2112_SERIAL_STRING);
795
796#undef CP2112_PSTR_ATTR
797
798static const struct attribute_group cp2112_attr_group = {
799 .attrs = (struct attribute *[]){
800 &dev_attr_vendor_id.attr,
801 &dev_attr_product_id.attr,
802 &dev_attr_max_power.attr,
803 &dev_attr_power_mode.attr,
804 &dev_attr_release_version.attr,
805 &dev_attr_manufacturer.attr.attr,
806 &dev_attr_product.attr.attr,
807 &dev_attr_serial.attr.attr,
808 NULL
809 }
810};
811
812/* Chmoding our sysfs attributes is simply a way to expose which fields in the
813 * PROM have already been programmed. We do not depend on this preventing
814 * writing to these attributes since the CP2112 will simply ignore writes to
815 * already-programmed fields. This is why there is no sense in fixing this
816 * racy behaviour.
817 */
818static void chmod_sysfs_attrs(struct hid_device *hdev)
819{
820 struct attribute **attr;
821 u8 buf[2];
822 int ret;
823
824 ret = cp2112_hid_get(hdev, CP2112_LOCK_BYTE, buf, sizeof(buf),
825 HID_FEATURE_REPORT);
826 if (ret != sizeof(buf)) {
827 hid_err(hdev, "error reading lock byte: %d\n", ret);
828 return;
829 }
830
831 for (attr = cp2112_attr_group.attrs; *attr; ++attr) {
832 umode_t mode = (buf[1] & 1) ? S_IWUSR | S_IRUGO : S_IRUGO;
833 ret = sysfs_chmod_file(&hdev->dev.kobj, *attr, mode);
834 if (ret < 0)
835 hid_err(hdev, "error chmoding sysfs file %s\n",
836 (*attr)->name);
837 buf[1] >>= 1;
838 }
839}
840
841static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
842{
843 struct cp2112_device *dev;
844 u8 buf[3];
845 struct cp2112_smbus_config_report config;
846 int ret;
847
848 ret = hid_parse(hdev);
849 if (ret) {
850 hid_err(hdev, "parse failed\n");
851 return ret;
852 }
853
854 ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
855 if (ret) {
856 hid_err(hdev, "hw start failed\n");
857 return ret;
858 }
859
860 ret = hid_hw_open(hdev);
861 if (ret) {
862 hid_err(hdev, "hw open failed\n");
863 goto err_hid_stop;
864 }
865
866 ret = hid_hw_power(hdev, PM_HINT_FULLON);
867 if (ret < 0) {
868 hid_err(hdev, "power management error: %d\n", ret);
869 goto err_hid_close;
870 }
871
872 ret = cp2112_hid_get(hdev, CP2112_GET_VERSION_INFO, buf, sizeof(buf),
873 HID_FEATURE_REPORT);
874 if (ret != sizeof(buf)) {
875 hid_err(hdev, "error requesting version\n");
876 if (ret >= 0)
877 ret = -EIO;
878 goto err_power_normal;
879 }
880
881 hid_info(hdev, "Part Number: 0x%02X Device Version: 0x%02X\n",
882 buf[1], buf[2]);
883
884 ret = cp2112_hid_get(hdev, CP2112_SMBUS_CONFIG, (u8 *)&config,
885 sizeof(config), HID_FEATURE_REPORT);
886 if (ret != sizeof(config)) {
887 hid_err(hdev, "error requesting SMBus config\n");
888 if (ret >= 0)
889 ret = -EIO;
890 goto err_power_normal;
891 }
892
893 config.retry_time = cpu_to_be16(1);
894
895 ret = cp2112_hid_output(hdev, (u8 *)&config, sizeof(config),
896 HID_FEATURE_REPORT);
897 if (ret != sizeof(config)) {
898 hid_err(hdev, "error setting SMBus config\n");
899 if (ret >= 0)
900 ret = -EIO;
901 goto err_power_normal;
902 }
903
904 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
905 if (!dev) {
906 ret = -ENOMEM;
907 goto err_power_normal;
908 }
909
910 hid_set_drvdata(hdev, (void *)dev);
911 dev->hdev = hdev;
912 dev->adap.owner = THIS_MODULE;
913 dev->adap.class = I2C_CLASS_HWMON;
914 dev->adap.algo = &smbus_algorithm;
915 dev->adap.algo_data = dev;
916 dev->adap.dev.parent = &hdev->dev;
917 snprintf(dev->adap.name, sizeof(dev->adap.name),
918 "CP2112 SMBus Bridge on hiddev%d", hdev->minor);
919 init_waitqueue_head(&dev->wait);
920
921 hid_device_io_start(hdev);
922 ret = i2c_add_adapter(&dev->adap);
923 hid_device_io_stop(hdev);
924
925 if (ret) {
926 hid_err(hdev, "error registering i2c adapter\n");
927 goto err_free_dev;
928 }
929
930 hid_dbg(hdev, "adapter registered\n");
931
932 dev->gc.label = "cp2112_gpio";
933 dev->gc.direction_input = cp2112_gpio_direction_input;
934 dev->gc.direction_output = cp2112_gpio_direction_output;
935 dev->gc.set = cp2112_gpio_set;
936 dev->gc.get = cp2112_gpio_get;
937 dev->gc.base = -1;
938 dev->gc.ngpio = 8;
939 dev->gc.can_sleep = 1;
940 dev->gc.dev = &hdev->dev;
941
942 ret = gpiochip_add(&dev->gc);
943 if (ret < 0) {
944 hid_err(hdev, "error registering gpio chip\n");
945 goto err_free_i2c;
946 }
947
948 ret = sysfs_create_group(&hdev->dev.kobj, &cp2112_attr_group);
949 if (ret < 0) {
950 hid_err(hdev, "error creating sysfs attrs\n");
951 goto err_gpiochip_remove;
952 }
953
954 chmod_sysfs_attrs(hdev);
955 hid_hw_power(hdev, PM_HINT_NORMAL);
956
957 return ret;
958
959err_gpiochip_remove:
960 if (gpiochip_remove(&dev->gc) < 0)
961 hid_err(hdev, "error removing gpio chip\n");
962err_free_i2c:
963 i2c_del_adapter(&dev->adap);
964err_free_dev:
965 kfree(dev);
966err_power_normal:
967 hid_hw_power(hdev, PM_HINT_NORMAL);
968err_hid_close:
969 hid_hw_close(hdev);
970err_hid_stop:
971 hid_hw_stop(hdev);
972 return ret;
973}
974
975static void cp2112_remove(struct hid_device *hdev)
976{
977 struct cp2112_device *dev = hid_get_drvdata(hdev);
978
979 sysfs_remove_group(&hdev->dev.kobj, &cp2112_attr_group);
980 if (gpiochip_remove(&dev->gc))
981 hid_err(hdev, "unable to remove gpio chip\n");
982 i2c_del_adapter(&dev->adap);
983 /* i2c_del_adapter has finished removing all i2c devices from our
984 * adapter. Well behaved devices should no longer call our cp2112_xfer
985 * and should have waited for any pending calls to finish. It has also
986 * waited for device_unregister(&adap->dev) to complete. Therefore we
987 * can safely free our struct cp2112_device.
988 */
989 hid_hw_close(hdev);
990 hid_hw_stop(hdev);
991 kfree(dev);
992}
993
994static int cp2112_raw_event(struct hid_device *hdev, struct hid_report *report,
995 u8 *data, int size)
996{
997 struct cp2112_device *dev = hid_get_drvdata(hdev);
998 struct cp2112_xfer_status_report *xfer = (void *)data;
999
1000 switch (data[0]) {
1001 case CP2112_TRANSFER_STATUS_RESPONSE:
1002 hid_dbg(hdev, "xfer status: %02x %02x %04x %04x\n",
1003 xfer->status0, xfer->status1,
1004 be16_to_cpu(xfer->retries), be16_to_cpu(xfer->length));
1005
1006 switch (xfer->status0) {
1007 case STATUS0_IDLE:
1008 dev->xfer_status = -EAGAIN;
1009 break;
1010 case STATUS0_BUSY:
1011 dev->xfer_status = -EBUSY;
1012 break;
1013 case STATUS0_COMPLETE:
1014 dev->xfer_status = be16_to_cpu(xfer->length);
1015 break;
1016 case STATUS0_ERROR:
1017 switch (xfer->status1) {
1018 case STATUS1_TIMEOUT_NACK:
1019 case STATUS1_TIMEOUT_BUS:
1020 dev->xfer_status = -ETIMEDOUT;
1021 break;
1022 default:
1023 dev->xfer_status = -EIO;
1024 break;
1025 }
1026 break;
1027 default:
1028 dev->xfer_status = -EINVAL;
1029 break;
1030 }
1031
1032 atomic_set(&dev->xfer_avail, 1);
1033 break;
1034 case CP2112_DATA_READ_RESPONSE:
1035 hid_dbg(hdev, "read response: %02x %02x\n", data[1], data[2]);
1036
1037 dev->read_length = data[2];
1038 if (dev->read_length > sizeof(dev->read_data))
1039 dev->read_length = sizeof(dev->read_data);
1040
1041 memcpy(dev->read_data, &data[3], dev->read_length);
1042 atomic_set(&dev->read_avail, 1);
1043 break;
1044 default:
1045 hid_err(hdev, "unknown report\n");
1046
1047 return 0;
1048 }
1049
1050 wake_up_interruptible(&dev->wait);
1051 return 1;
1052}
1053
1054static struct hid_driver cp2112_driver = {
1055 .name = "cp2112",
1056 .id_table = cp2112_devices,
1057 .probe = cp2112_probe,
1058 .remove = cp2112_remove,
1059 .raw_event = cp2112_raw_event,
1060};
1061
1062module_hid_driver(cp2112_driver);
1063MODULE_DESCRIPTION("Silicon Labs HID USB to SMBus master bridge");
1064MODULE_AUTHOR("David Barksdale <dbarksdale@uplogix.com>");
1065MODULE_LICENSE("GPL");
1066