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>
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.
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
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.
22 * http://www.silabs.com/Support%20Documents/TechnicalDocs/CP2112.pdf
23 * Programming Interface Specification:
24 * http://www.silabs.com/Support%20Documents/TechnicalDocs/AN495.pdf
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>
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,
59 STATUS0_COMPLETE
= 0x02,
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,
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 */
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 */
93 u8 mask
; /* What fields to program */
96 struct cp2112_read_req_report
{
97 u8 report
; /* CP2112_DATA_READ_REQUEST */
102 struct cp2112_write_read_req_report
{
103 u8 report
; /* CP2112_DATA_WRITE_READ_REQUEST */
106 u8 target_address_length
;
107 u8 target_address
[16];
110 struct cp2112_write_req_report
{
111 u8 report
; /* CP2112_DATA_WRITE_REQUEST */
117 struct cp2112_force_read_report
{
118 u8 report
; /* CP2112_DATA_READ_FORCE_SEND */
122 struct cp2112_xfer_status_report
{
123 u8 report
; /* CP2112_TRANSFER_STATUS_RESPONSE */
124 u8 status0
; /* STATUS0_* */
125 u8 status1
; /* STATUS1_* */
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 */
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;
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;
147 static const struct hid_device_id cp2112_devices
[] = {
148 { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL
, USB_DEVICE_ID_CYGNAL_CP2112
) },
151 MODULE_DEVICE_TABLE(hid
, cp2112_devices
);
153 struct cp2112_device
{
154 struct i2c_adapter adap
;
155 struct hid_device
*hdev
;
156 wait_queue_head_t wait
;
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");
169 static int cp2112_gpio_direction_input(struct gpio_chip
*chip
, unsigned offset
)
171 struct cp2112_device
*dev
= container_of(chip
, struct cp2112_device
,
173 struct hid_device
*hdev
= dev
->hdev
;
177 ret
= hid_hw_raw_request(hdev
, CP2112_GPIO_CONFIG
, buf
,
178 sizeof(buf
), HID_FEATURE_REPORT
,
180 if (ret
!= sizeof(buf
)) {
181 hid_err(hdev
, "error requesting GPIO config: %d\n", ret
);
185 buf
[1] &= ~(1 << offset
);
186 buf
[2] = gpio_push_pull
;
188 ret
= hid_hw_raw_request(hdev
, CP2112_GPIO_CONFIG
, buf
, sizeof(buf
),
189 HID_FEATURE_REPORT
, HID_REQ_SET_REPORT
);
191 hid_err(hdev
, "error setting GPIO config: %d\n", ret
);
198 static void cp2112_gpio_set(struct gpio_chip
*chip
, unsigned offset
, int value
)
200 struct cp2112_device
*dev
= container_of(chip
, struct cp2112_device
,
202 struct hid_device
*hdev
= dev
->hdev
;
206 buf
[0] = CP2112_GPIO_SET
;
207 buf
[1] = value
? 0xff : 0;
208 buf
[2] = 1 << offset
;
210 ret
= hid_hw_raw_request(hdev
, CP2112_GPIO_SET
, buf
, sizeof(buf
),
211 HID_FEATURE_REPORT
, HID_REQ_SET_REPORT
);
213 hid_err(hdev
, "error setting GPIO values: %d\n", ret
);
216 static int cp2112_gpio_get(struct gpio_chip
*chip
, unsigned offset
)
218 struct cp2112_device
*dev
= container_of(chip
, struct cp2112_device
,
220 struct hid_device
*hdev
= dev
->hdev
;
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
);
231 return (buf
[1] >> offset
) & 1;
234 static int cp2112_gpio_direction_output(struct gpio_chip
*chip
,
235 unsigned offset
, int value
)
237 struct cp2112_device
*dev
= container_of(chip
, struct cp2112_device
,
239 struct hid_device
*hdev
= dev
->hdev
;
243 ret
= hid_hw_raw_request(hdev
, CP2112_GPIO_CONFIG
, buf
,
244 sizeof(buf
), HID_FEATURE_REPORT
,
246 if (ret
!= sizeof(buf
)) {
247 hid_err(hdev
, "error requesting GPIO config: %d\n", ret
);
251 buf
[1] |= 1 << offset
;
252 buf
[2] = gpio_push_pull
;
254 ret
= hid_hw_raw_request(hdev
, CP2112_GPIO_CONFIG
, buf
, sizeof(buf
),
255 HID_FEATURE_REPORT
, HID_REQ_SET_REPORT
);
257 hid_err(hdev
, "error setting GPIO config: %d\n", ret
);
262 * Set gpio value when output direction is already set,
263 * as specified in AN495, Rev. 0.2, cpt. 4.4
265 cp2112_gpio_set(chip
, offset
, value
);
270 static int cp2112_hid_get(struct hid_device
*hdev
, unsigned char report_number
,
271 u8
*data
, size_t count
, unsigned char report_type
)
276 buf
= kmalloc(count
, GFP_KERNEL
);
280 ret
= hid_hw_raw_request(hdev
, report_number
, buf
, count
,
281 report_type
, HID_REQ_GET_REPORT
);
282 memcpy(data
, buf
, count
);
287 static int cp2112_hid_output(struct hid_device
*hdev
, u8
*data
, size_t count
,
288 unsigned char report_type
)
293 buf
= kmemdup(data
, count
, GFP_KERNEL
);
297 if (report_type
== HID_OUTPUT_REPORT
)
298 ret
= hid_hw_output_report(hdev
, buf
, count
);
300 ret
= hid_hw_raw_request(hdev
, buf
[0], buf
, count
, report_type
,
307 static int cp2112_wait(struct cp2112_device
*dev
, atomic_t
*avail
)
311 /* We have sent either a CP2112_TRANSFER_STATUS_REQUEST or a
312 * CP2112_DATA_READ_FORCE_SEND and we are waiting for the response to
313 * come in cp2112_raw_event or timeout. There will only be one of these
314 * in flight at any one time. The timeout is extremely large and is a
315 * last resort if the CP2112 has died. If we do timeout we don't expect
316 * to receive the response which would cause data races, it's not like
317 * we can do anything about it anyway.
319 ret
= wait_event_interruptible_timeout(dev
->wait
,
320 atomic_read(avail
), msecs_to_jiffies(RESPONSE_TIMEOUT
));
321 if (-ERESTARTSYS
== ret
)
326 atomic_set(avail
, 0);
330 static int cp2112_xfer_status(struct cp2112_device
*dev
)
332 struct hid_device
*hdev
= dev
->hdev
;
336 buf
[0] = CP2112_TRANSFER_STATUS_REQUEST
;
338 atomic_set(&dev
->xfer_avail
, 0);
340 ret
= cp2112_hid_output(hdev
, buf
, 2, HID_OUTPUT_REPORT
);
342 hid_warn(hdev
, "Error requesting status: %d\n", ret
);
346 ret
= cp2112_wait(dev
, &dev
->xfer_avail
);
350 return dev
->xfer_status
;
353 static int cp2112_read(struct cp2112_device
*dev
, u8
*data
, size_t size
)
355 struct hid_device
*hdev
= dev
->hdev
;
356 struct cp2112_force_read_report report
;
359 if (size
> sizeof(dev
->read_data
))
360 size
= sizeof(dev
->read_data
);
361 report
.report
= CP2112_DATA_READ_FORCE_SEND
;
362 report
.length
= cpu_to_be16(size
);
364 atomic_set(&dev
->read_avail
, 0);
366 ret
= cp2112_hid_output(hdev
, &report
.report
, sizeof(report
),
369 hid_warn(hdev
, "Error requesting data: %d\n", ret
);
373 ret
= cp2112_wait(dev
, &dev
->read_avail
);
377 hid_dbg(hdev
, "read %d of %zd bytes requested\n",
378 dev
->read_length
, size
);
380 if (size
> dev
->read_length
)
381 size
= dev
->read_length
;
383 memcpy(data
, dev
->read_data
, size
);
384 return dev
->read_length
;
387 static int cp2112_read_req(void *buf
, u8 slave_address
, u16 length
)
389 struct cp2112_read_req_report
*report
= buf
;
391 if (length
< 1 || length
> 512)
394 report
->report
= CP2112_DATA_READ_REQUEST
;
395 report
->slave_address
= slave_address
<< 1;
396 report
->length
= cpu_to_be16(length
);
397 return sizeof(*report
);
400 static int cp2112_write_read_req(void *buf
, u8 slave_address
, u16 length
,
401 u8 command
, u8
*data
, u8 data_length
)
403 struct cp2112_write_read_req_report
*report
= buf
;
405 if (length
< 1 || length
> 512
406 || data_length
> sizeof(report
->target_address
) - 1)
409 report
->report
= CP2112_DATA_WRITE_READ_REQUEST
;
410 report
->slave_address
= slave_address
<< 1;
411 report
->length
= cpu_to_be16(length
);
412 report
->target_address_length
= data_length
+ 1;
413 report
->target_address
[0] = command
;
414 memcpy(&report
->target_address
[1], data
, data_length
);
415 return data_length
+ 6;
418 static int cp2112_write_req(void *buf
, u8 slave_address
, u8 command
, u8
*data
,
421 struct cp2112_write_req_report
*report
= buf
;
423 if (data_length
> sizeof(report
->data
) - 1)
426 report
->report
= CP2112_DATA_WRITE_REQUEST
;
427 report
->slave_address
= slave_address
<< 1;
428 report
->length
= data_length
+ 1;
429 report
->data
[0] = command
;
430 memcpy(&report
->data
[1], data
, data_length
);
431 return data_length
+ 4;
434 static int cp2112_i2c_write_req(void *buf
, u8 slave_address
, u8
*data
,
437 struct cp2112_write_req_report
*report
= buf
;
439 if (data_length
> sizeof(report
->data
))
442 report
->report
= CP2112_DATA_WRITE_REQUEST
;
443 report
->slave_address
= slave_address
<< 1;
444 report
->length
= data_length
;
445 memcpy(report
->data
, data
, data_length
);
446 return data_length
+ 3;
449 static int cp2112_i2c_xfer(struct i2c_adapter
*adap
, struct i2c_msg
*msgs
,
452 struct cp2112_device
*dev
= (struct cp2112_device
*)adap
->algo_data
;
453 struct hid_device
*hdev
= dev
->hdev
;
456 unsigned int retries
;
459 hid_dbg(hdev
, "I2C %d messages\n", num
);
463 "Multi-message I2C transactions not supported\n");
467 if (msgs
->flags
& I2C_M_RD
)
468 count
= cp2112_read_req(buf
, msgs
->addr
, msgs
->len
);
470 count
= cp2112_i2c_write_req(buf
, msgs
->addr
, msgs
->buf
,
476 ret
= hid_hw_power(hdev
, PM_HINT_FULLON
);
478 hid_err(hdev
, "power management error: %d\n", ret
);
482 ret
= cp2112_hid_output(hdev
, buf
, count
, HID_OUTPUT_REPORT
);
484 hid_warn(hdev
, "Error starting transaction: %d\n", ret
);
488 for (retries
= 0; retries
< XFER_STATUS_RETRIES
; ++retries
) {
489 ret
= cp2112_xfer_status(dev
);
497 if (XFER_STATUS_RETRIES
<= retries
) {
498 hid_warn(hdev
, "Transfer timed out, cancelling.\n");
499 buf
[0] = CP2112_CANCEL_TRANSFER
;
502 ret
= cp2112_hid_output(hdev
, buf
, 2, HID_OUTPUT_REPORT
);
504 hid_warn(hdev
, "Error cancelling transaction: %d\n",
511 if (!(msgs
->flags
& I2C_M_RD
))
514 ret
= cp2112_read(dev
, msgs
->buf
, msgs
->len
);
517 if (ret
!= msgs
->len
) {
518 hid_warn(hdev
, "short read: %d < %d\n", ret
, msgs
->len
);
524 /* return the number of transferred messages */
528 hid_hw_power(hdev
, PM_HINT_NORMAL
);
529 hid_dbg(hdev
, "I2C transfer finished: %d\n", ret
);
533 static int cp2112_xfer(struct i2c_adapter
*adap
, u16 addr
,
534 unsigned short flags
, char read_write
, u8 command
,
535 int size
, union i2c_smbus_data
*data
)
537 struct cp2112_device
*dev
= (struct cp2112_device
*)adap
->algo_data
;
538 struct hid_device
*hdev
= dev
->hdev
;
542 size_t read_length
= 0;
543 unsigned int retries
;
546 hid_dbg(hdev
, "%s addr 0x%x flags 0x%x cmd 0x%x size %d\n",
547 read_write
== I2C_SMBUS_WRITE
? "write" : "read",
548 addr
, flags
, command
, size
);
554 if (I2C_SMBUS_READ
== read_write
)
555 count
= cp2112_read_req(buf
, addr
, read_length
);
557 count
= cp2112_write_req(buf
, addr
, command
, NULL
,
560 case I2C_SMBUS_BYTE_DATA
:
563 if (I2C_SMBUS_READ
== read_write
)
564 count
= cp2112_write_read_req(buf
, addr
, read_length
,
567 count
= cp2112_write_req(buf
, addr
, command
,
570 case I2C_SMBUS_WORD_DATA
:
572 word
= cpu_to_le16(data
->word
);
574 if (I2C_SMBUS_READ
== read_write
)
575 count
= cp2112_write_read_req(buf
, addr
, read_length
,
578 count
= cp2112_write_req(buf
, addr
, command
,
581 case I2C_SMBUS_PROC_CALL
:
582 size
= I2C_SMBUS_WORD_DATA
;
583 read_write
= I2C_SMBUS_READ
;
585 word
= cpu_to_le16(data
->word
);
587 count
= cp2112_write_read_req(buf
, addr
, read_length
, command
,
590 case I2C_SMBUS_I2C_BLOCK_DATA
:
591 size
= I2C_SMBUS_BLOCK_DATA
;
593 case I2C_SMBUS_BLOCK_DATA
:
594 if (I2C_SMBUS_READ
== read_write
) {
595 count
= cp2112_write_read_req(buf
, addr
,
599 count
= cp2112_write_req(buf
, addr
, command
,
604 case I2C_SMBUS_BLOCK_PROC_CALL
:
605 size
= I2C_SMBUS_BLOCK_DATA
;
606 read_write
= I2C_SMBUS_READ
;
608 count
= cp2112_write_read_req(buf
, addr
, I2C_SMBUS_BLOCK_MAX
,
609 command
, data
->block
,
613 hid_warn(hdev
, "Unsupported transaction %d\n", size
);
620 ret
= hid_hw_power(hdev
, PM_HINT_FULLON
);
622 hid_err(hdev
, "power management error: %d\n", ret
);
626 ret
= cp2112_hid_output(hdev
, buf
, count
, HID_OUTPUT_REPORT
);
628 hid_warn(hdev
, "Error starting transaction: %d\n", ret
);
632 for (retries
= 0; retries
< XFER_STATUS_RETRIES
; ++retries
) {
633 ret
= cp2112_xfer_status(dev
);
641 if (XFER_STATUS_RETRIES
<= retries
) {
642 hid_warn(hdev
, "Transfer timed out, cancelling.\n");
643 buf
[0] = CP2112_CANCEL_TRANSFER
;
646 ret
= cp2112_hid_output(hdev
, buf
, 2, HID_OUTPUT_REPORT
);
648 hid_warn(hdev
, "Error cancelling transaction: %d\n",
655 if (I2C_SMBUS_WRITE
== read_write
) {
660 if (I2C_SMBUS_BLOCK_DATA
== size
)
663 ret
= cp2112_read(dev
, buf
, read_length
);
666 if (ret
!= read_length
) {
667 hid_warn(hdev
, "short read: %d < %zd\n", ret
, read_length
);
674 case I2C_SMBUS_BYTE_DATA
:
677 case I2C_SMBUS_WORD_DATA
:
678 data
->word
= le16_to_cpup((__le16
*)buf
);
680 case I2C_SMBUS_BLOCK_DATA
:
681 if (read_length
> I2C_SMBUS_BLOCK_MAX
) {
686 memcpy(data
->block
, buf
, read_length
);
692 hid_hw_power(hdev
, PM_HINT_NORMAL
);
693 hid_dbg(hdev
, "transfer finished: %d\n", ret
);
697 static u32
cp2112_functionality(struct i2c_adapter
*adap
)
699 return I2C_FUNC_I2C
|
700 I2C_FUNC_SMBUS_BYTE
|
701 I2C_FUNC_SMBUS_BYTE_DATA
|
702 I2C_FUNC_SMBUS_WORD_DATA
|
703 I2C_FUNC_SMBUS_BLOCK_DATA
|
704 I2C_FUNC_SMBUS_I2C_BLOCK
|
705 I2C_FUNC_SMBUS_PROC_CALL
|
706 I2C_FUNC_SMBUS_BLOCK_PROC_CALL
;
709 static const struct i2c_algorithm smbus_algorithm
= {
710 .master_xfer
= cp2112_i2c_xfer
,
711 .smbus_xfer
= cp2112_xfer
,
712 .functionality
= cp2112_functionality
,
715 static int cp2112_get_usb_config(struct hid_device
*hdev
,
716 struct cp2112_usb_config_report
*cfg
)
720 ret
= cp2112_hid_get(hdev
, CP2112_USB_CONFIG
, (u8
*)cfg
, sizeof(*cfg
),
722 if (ret
!= sizeof(*cfg
)) {
723 hid_err(hdev
, "error reading usb config: %d\n", ret
);
732 static int cp2112_set_usb_config(struct hid_device
*hdev
,
733 struct cp2112_usb_config_report
*cfg
)
737 BUG_ON(cfg
->report
!= CP2112_USB_CONFIG
);
739 ret
= cp2112_hid_output(hdev
, (u8
*)cfg
, sizeof(*cfg
),
741 if (ret
!= sizeof(*cfg
)) {
742 hid_err(hdev
, "error writing usb config: %d\n", ret
);
751 static void chmod_sysfs_attrs(struct hid_device
*hdev
);
753 #define CP2112_CONFIG_ATTR(name, store, format, ...) \
754 static ssize_t name##_store(struct device *kdev, \
755 struct device_attribute *attr, const char *buf, \
758 struct hid_device *hdev = container_of(kdev, struct hid_device, dev); \
759 struct cp2112_usb_config_report cfg; \
760 int ret = cp2112_get_usb_config(hdev, &cfg); \
764 ret = cp2112_set_usb_config(hdev, &cfg); \
767 chmod_sysfs_attrs(hdev); \
770 static ssize_t name##_show(struct device *kdev, \
771 struct device_attribute *attr, char *buf) \
773 struct hid_device *hdev = container_of(kdev, struct hid_device, dev); \
774 struct cp2112_usb_config_report cfg; \
775 int ret = cp2112_get_usb_config(hdev, &cfg); \
778 return scnprintf(buf, PAGE_SIZE, format, ##__VA_ARGS__); \
780 static DEVICE_ATTR_RW(name);
782 CP2112_CONFIG_ATTR(vendor_id
, ({
785 if (sscanf(buf
, "%hi", &vid
) != 1)
788 cfg
.vid
= cpu_to_le16(vid
);
790 }), "0x%04x\n", le16_to_cpu(cfg
.vid
));
792 CP2112_CONFIG_ATTR(product_id
, ({
795 if (sscanf(buf
, "%hi", &pid
) != 1)
798 cfg
.pid
= cpu_to_le16(pid
);
800 }), "0x%04x\n", le16_to_cpu(cfg
.pid
));
802 CP2112_CONFIG_ATTR(max_power
, ({
805 if (sscanf(buf
, "%i", &mA
) != 1)
808 cfg
.max_power
= (mA
+ 1) / 2;
810 }), "%u mA\n", cfg
.max_power
* 2);
812 CP2112_CONFIG_ATTR(power_mode
, ({
813 if (sscanf(buf
, "%hhi", &cfg
.power_mode
) != 1)
817 }), "%u\n", cfg
.power_mode
);
819 CP2112_CONFIG_ATTR(release_version
, ({
820 if (sscanf(buf
, "%hhi.%hhi", &cfg
.release_major
, &cfg
.release_minor
)
825 }), "%u.%u\n", cfg
.release_major
, cfg
.release_minor
);
827 #undef CP2112_CONFIG_ATTR
829 struct cp2112_pstring_attribute
{
830 struct device_attribute attr
;
831 unsigned char report
;
834 static ssize_t
pstr_store(struct device
*kdev
,
835 struct device_attribute
*kattr
, const char *buf
,
838 struct hid_device
*hdev
= container_of(kdev
, struct hid_device
, dev
);
839 struct cp2112_pstring_attribute
*attr
=
840 container_of(kattr
, struct cp2112_pstring_attribute
, attr
);
841 struct cp2112_string_report report
;
844 memset(&report
, 0, sizeof(report
));
846 ret
= utf8s_to_utf16s(buf
, count
, UTF16_LITTLE_ENDIAN
,
847 report
.string
, ARRAY_SIZE(report
.string
));
848 report
.report
= attr
->report
;
849 report
.length
= ret
* sizeof(report
.string
[0]) + 2;
850 report
.type
= USB_DT_STRING
;
852 ret
= cp2112_hid_output(hdev
, &report
.report
, report
.length
+ 1,
854 if (ret
!= report
.length
+ 1) {
855 hid_err(hdev
, "error writing %s string: %d\n", kattr
->attr
.name
,
862 chmod_sysfs_attrs(hdev
);
866 static ssize_t
pstr_show(struct device
*kdev
,
867 struct device_attribute
*kattr
, char *buf
)
869 struct hid_device
*hdev
= container_of(kdev
, struct hid_device
, dev
);
870 struct cp2112_pstring_attribute
*attr
=
871 container_of(kattr
, struct cp2112_pstring_attribute
, attr
);
872 struct cp2112_string_report report
;
876 ret
= cp2112_hid_get(hdev
, attr
->report
, &report
.report
,
877 sizeof(report
) - 1, HID_FEATURE_REPORT
);
879 hid_err(hdev
, "error reading %s string: %d\n", kattr
->attr
.name
,
886 if (report
.length
< 2) {
887 hid_err(hdev
, "invalid %s string length: %d\n",
888 kattr
->attr
.name
, report
.length
);
892 length
= report
.length
> ret
- 1 ? ret
- 1 : report
.length
;
893 length
= (length
- 2) / sizeof(report
.string
[0]);
894 ret
= utf16s_to_utf8s(report
.string
, length
, UTF16_LITTLE_ENDIAN
, buf
,
900 #define CP2112_PSTR_ATTR(name, _report) \
901 static struct cp2112_pstring_attribute dev_attr_##name = { \
902 .attr = __ATTR(name, (S_IWUSR | S_IRUGO), pstr_show, pstr_store), \
906 CP2112_PSTR_ATTR(manufacturer
, CP2112_MANUFACTURER_STRING
);
907 CP2112_PSTR_ATTR(product
, CP2112_PRODUCT_STRING
);
908 CP2112_PSTR_ATTR(serial
, CP2112_SERIAL_STRING
);
910 #undef CP2112_PSTR_ATTR
912 static const struct attribute_group cp2112_attr_group
= {
913 .attrs
= (struct attribute
*[]){
914 &dev_attr_vendor_id
.attr
,
915 &dev_attr_product_id
.attr
,
916 &dev_attr_max_power
.attr
,
917 &dev_attr_power_mode
.attr
,
918 &dev_attr_release_version
.attr
,
919 &dev_attr_manufacturer
.attr
.attr
,
920 &dev_attr_product
.attr
.attr
,
921 &dev_attr_serial
.attr
.attr
,
926 /* Chmoding our sysfs attributes is simply a way to expose which fields in the
927 * PROM have already been programmed. We do not depend on this preventing
928 * writing to these attributes since the CP2112 will simply ignore writes to
929 * already-programmed fields. This is why there is no sense in fixing this
932 static void chmod_sysfs_attrs(struct hid_device
*hdev
)
934 struct attribute
**attr
;
938 ret
= cp2112_hid_get(hdev
, CP2112_LOCK_BYTE
, buf
, sizeof(buf
),
940 if (ret
!= sizeof(buf
)) {
941 hid_err(hdev
, "error reading lock byte: %d\n", ret
);
945 for (attr
= cp2112_attr_group
.attrs
; *attr
; ++attr
) {
946 umode_t mode
= (buf
[1] & 1) ? S_IWUSR
| S_IRUGO
: S_IRUGO
;
947 ret
= sysfs_chmod_file(&hdev
->dev
.kobj
, *attr
, mode
);
949 hid_err(hdev
, "error chmoding sysfs file %s\n",
955 static int cp2112_probe(struct hid_device
*hdev
, const struct hid_device_id
*id
)
957 struct cp2112_device
*dev
;
959 struct cp2112_smbus_config_report config
;
962 ret
= hid_parse(hdev
);
964 hid_err(hdev
, "parse failed\n");
968 ret
= hid_hw_start(hdev
, HID_CONNECT_HIDRAW
);
970 hid_err(hdev
, "hw start failed\n");
974 ret
= hid_hw_open(hdev
);
976 hid_err(hdev
, "hw open failed\n");
980 ret
= hid_hw_power(hdev
, PM_HINT_FULLON
);
982 hid_err(hdev
, "power management error: %d\n", ret
);
986 ret
= cp2112_hid_get(hdev
, CP2112_GET_VERSION_INFO
, buf
, sizeof(buf
),
988 if (ret
!= sizeof(buf
)) {
989 hid_err(hdev
, "error requesting version\n");
992 goto err_power_normal
;
995 hid_info(hdev
, "Part Number: 0x%02X Device Version: 0x%02X\n",
998 ret
= cp2112_hid_get(hdev
, CP2112_SMBUS_CONFIG
, (u8
*)&config
,
999 sizeof(config
), HID_FEATURE_REPORT
);
1000 if (ret
!= sizeof(config
)) {
1001 hid_err(hdev
, "error requesting SMBus config\n");
1004 goto err_power_normal
;
1007 config
.retry_time
= cpu_to_be16(1);
1009 ret
= cp2112_hid_output(hdev
, (u8
*)&config
, sizeof(config
),
1010 HID_FEATURE_REPORT
);
1011 if (ret
!= sizeof(config
)) {
1012 hid_err(hdev
, "error setting SMBus config\n");
1015 goto err_power_normal
;
1018 dev
= kzalloc(sizeof(*dev
), GFP_KERNEL
);
1021 goto err_power_normal
;
1024 hid_set_drvdata(hdev
, (void *)dev
);
1026 dev
->adap
.owner
= THIS_MODULE
;
1027 dev
->adap
.class = I2C_CLASS_HWMON
;
1028 dev
->adap
.algo
= &smbus_algorithm
;
1029 dev
->adap
.algo_data
= dev
;
1030 dev
->adap
.dev
.parent
= &hdev
->dev
;
1031 snprintf(dev
->adap
.name
, sizeof(dev
->adap
.name
),
1032 "CP2112 SMBus Bridge on hiddev%d", hdev
->minor
);
1033 init_waitqueue_head(&dev
->wait
);
1035 hid_device_io_start(hdev
);
1036 ret
= i2c_add_adapter(&dev
->adap
);
1037 hid_device_io_stop(hdev
);
1040 hid_err(hdev
, "error registering i2c adapter\n");
1044 hid_dbg(hdev
, "adapter registered\n");
1046 dev
->gc
.label
= "cp2112_gpio";
1047 dev
->gc
.direction_input
= cp2112_gpio_direction_input
;
1048 dev
->gc
.direction_output
= cp2112_gpio_direction_output
;
1049 dev
->gc
.set
= cp2112_gpio_set
;
1050 dev
->gc
.get
= cp2112_gpio_get
;
1053 dev
->gc
.can_sleep
= 1;
1054 dev
->gc
.dev
= &hdev
->dev
;
1056 ret
= gpiochip_add(&dev
->gc
);
1058 hid_err(hdev
, "error registering gpio chip\n");
1062 ret
= sysfs_create_group(&hdev
->dev
.kobj
, &cp2112_attr_group
);
1064 hid_err(hdev
, "error creating sysfs attrs\n");
1065 goto err_gpiochip_remove
;
1068 chmod_sysfs_attrs(hdev
);
1069 hid_hw_power(hdev
, PM_HINT_NORMAL
);
1073 err_gpiochip_remove
:
1074 gpiochip_remove(&dev
->gc
);
1076 i2c_del_adapter(&dev
->adap
);
1080 hid_hw_power(hdev
, PM_HINT_NORMAL
);
1088 static void cp2112_remove(struct hid_device
*hdev
)
1090 struct cp2112_device
*dev
= hid_get_drvdata(hdev
);
1092 sysfs_remove_group(&hdev
->dev
.kobj
, &cp2112_attr_group
);
1093 gpiochip_remove(&dev
->gc
);
1094 i2c_del_adapter(&dev
->adap
);
1095 /* i2c_del_adapter has finished removing all i2c devices from our
1096 * adapter. Well behaved devices should no longer call our cp2112_xfer
1097 * and should have waited for any pending calls to finish. It has also
1098 * waited for device_unregister(&adap->dev) to complete. Therefore we
1099 * can safely free our struct cp2112_device.
1106 static int cp2112_raw_event(struct hid_device
*hdev
, struct hid_report
*report
,
1109 struct cp2112_device
*dev
= hid_get_drvdata(hdev
);
1110 struct cp2112_xfer_status_report
*xfer
= (void *)data
;
1113 case CP2112_TRANSFER_STATUS_RESPONSE
:
1114 hid_dbg(hdev
, "xfer status: %02x %02x %04x %04x\n",
1115 xfer
->status0
, xfer
->status1
,
1116 be16_to_cpu(xfer
->retries
), be16_to_cpu(xfer
->length
));
1118 switch (xfer
->status0
) {
1120 dev
->xfer_status
= -EAGAIN
;
1123 dev
->xfer_status
= -EBUSY
;
1125 case STATUS0_COMPLETE
:
1126 dev
->xfer_status
= be16_to_cpu(xfer
->length
);
1129 switch (xfer
->status1
) {
1130 case STATUS1_TIMEOUT_NACK
:
1131 case STATUS1_TIMEOUT_BUS
:
1132 dev
->xfer_status
= -ETIMEDOUT
;
1135 dev
->xfer_status
= -EIO
;
1140 dev
->xfer_status
= -EINVAL
;
1144 atomic_set(&dev
->xfer_avail
, 1);
1146 case CP2112_DATA_READ_RESPONSE
:
1147 hid_dbg(hdev
, "read response: %02x %02x\n", data
[1], data
[2]);
1149 dev
->read_length
= data
[2];
1150 if (dev
->read_length
> sizeof(dev
->read_data
))
1151 dev
->read_length
= sizeof(dev
->read_data
);
1153 memcpy(dev
->read_data
, &data
[3], dev
->read_length
);
1154 atomic_set(&dev
->read_avail
, 1);
1157 hid_err(hdev
, "unknown report\n");
1162 wake_up_interruptible(&dev
->wait
);
1166 static struct hid_driver cp2112_driver
= {
1168 .id_table
= cp2112_devices
,
1169 .probe
= cp2112_probe
,
1170 .remove
= cp2112_remove
,
1171 .raw_event
= cp2112_raw_event
,
1174 module_hid_driver(cp2112_driver
);
1175 MODULE_DESCRIPTION("Silicon Labs HID USB to SMBus master bridge");
1176 MODULE_AUTHOR("David Barksdale <dbarksdale@uplogix.com>");
1177 MODULE_LICENSE("GPL");