1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * corsair-cpro.c - Linux driver for Corsair Commander Pro
4 * Copyright (C) 2020 Marius Zachmann <mail@mariuszachmann.de>
5 *
6 * This driver uses hid reports to communicate with the device to allow hidraw userspace drivers
7 * still being used. The device does not use report ids. When using hidraw and this driver
8 * simultaniously, reports could be switched.
9 */
10
11 #include <linux/bitops.h>
12 #include <linux/completion.h>
13 #include <linux/debugfs.h>
14 #include <linux/hid.h>
15 #include <linux/hwmon.h>
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/mutex.h>
19 #include <linux/seq_file.h>
20 #include <linux/slab.h>
21 #include <linux/spinlock.h>
22 #include <linux/types.h>
23
24 #define USB_VENDOR_ID_CORSAIR 0x1b1c
25 #define USB_PRODUCT_ID_CORSAIR_COMMANDERPRO 0x0c10
26 #define USB_PRODUCT_ID_CORSAIR_1000D 0x1d00
27
28 #define OUT_BUFFER_SIZE 63
29 #define IN_BUFFER_SIZE 16
30 #define LABEL_LENGTH 11
31 #define REQ_TIMEOUT 300
32
33 #define CTL_GET_FW_VER 0x02 /* returns the firmware version in bytes 1-3 */
34 #define CTL_GET_BL_VER 0x06 /* returns the bootloader version in bytes 1-2 */
35 #define CTL_GET_TMP_CNCT 0x10 /*
36 * returns in bytes 1-4 for each temp sensor:
37 * 0 not connected
38 * 1 connected
39 */
40 #define CTL_GET_TMP 0x11 /*
41 * send: byte 1 is channel, rest zero
42 * rcv: returns temp for channel in centi-degree celsius
43 * in bytes 1 and 2
44 * returns 0x11 in byte 0 if no sensor is connected
45 */
46 #define CTL_GET_VOLT 0x12 /*
47 * send: byte 1 is rail number: 0 = 12v, 1 = 5v, 2 = 3.3v
48 * rcv: returns millivolt in bytes 1,2
49 * returns error 0x10 if request is invalid
50 */
51 #define CTL_GET_FAN_CNCT 0x20 /*
52 * returns in bytes 1-6 for each fan:
53 * 0 not connected
54 * 1 3pin
55 * 2 4pin
56 */
57 #define CTL_GET_FAN_RPM 0x21 /*
58 * send: byte 1 is channel, rest zero
59 * rcv: returns rpm in bytes 1,2
60 */
61 #define CTL_GET_FAN_PWM 0x22 /*
62 * send: byte 1 is channel, rest zero
63 * rcv: returns pwm in byte 1 if it was set
64 * returns error 0x12 if fan is controlled via
65 * fan_target or fan curve
66 */
67 #define CTL_SET_FAN_FPWM 0x23 /*
68 * set fixed pwm
69 * send: byte 1 is fan number
70 * send: byte 2 is percentage from 0 - 100
71 */
72 #define CTL_SET_FAN_TARGET 0x24 /*
73 * set target rpm
74 * send: byte 1 is fan number
75 * send: byte 2-3 is target
76 * device accepts all values from 0x00 - 0xFFFF
77 */
78
79 #define NUM_FANS 6
80 #define NUM_TEMP_SENSORS 4
81
82 struct ccp_device {
83 struct hid_device *hdev;
84 struct device *hwmon_dev;
85 struct dentry *debugfs;
86 /* For reinitializing the completion below */
87 spinlock_t wait_input_report_lock;
88 struct completion wait_input_report;
89 struct mutex mutex; /* whenever buffer is used, lock before send_usb_cmd */
90 u8 *cmd_buffer;
91 u8 *buffer;
92 int buffer_recv_size; /* number of received bytes in buffer */
93 int target[6];
94 DECLARE_BITMAP(temp_cnct, NUM_TEMP_SENSORS);
95 DECLARE_BITMAP(fan_cnct, NUM_FANS);
96 char fan_label[6][LABEL_LENGTH];
97 u8 firmware_ver[3];
98 u8 bootloader_ver[2];
99 };
100
101 /* converts response error in buffer to errno */
ccp_get_errno(struct ccp_device * ccp)102 static int ccp_get_errno(struct ccp_device *ccp)
103 {
104 switch (ccp->buffer[0]) {
105 case 0x00: /* success */
106 return 0;
107 case 0x01: /* called invalid command */
108 return -EOPNOTSUPP;
109 case 0x10: /* called GET_VOLT / GET_TMP with invalid arguments */
110 return -EINVAL;
111 case 0x11: /* requested temps of disconnected sensors */
112 case 0x12: /* requested pwm of not pwm controlled channels */
113 return -ENODATA;
114 default:
115 hid_dbg(ccp->hdev, "unknown device response error: %d", ccp->buffer[0]);
116 return -EIO;
117 }
118 }
119
120 /* send command, check for error in response, response in ccp->buffer */
send_usb_cmd(struct ccp_device * ccp,u8 command,u8 byte1,u8 byte2,u8 byte3)121 static int send_usb_cmd(struct ccp_device *ccp, u8 command, u8 byte1, u8 byte2, u8 byte3)
122 {
123 unsigned long t;
124 int ret;
125
126 memset(ccp->cmd_buffer, 0x00, OUT_BUFFER_SIZE);
127 ccp->cmd_buffer[0] = command;
128 ccp->cmd_buffer[1] = byte1;
129 ccp->cmd_buffer[2] = byte2;
130 ccp->cmd_buffer[3] = byte3;
131
132 /*
133 * Disable raw event parsing for a moment to safely reinitialize the
134 * completion. Reinit is done because hidraw could have triggered
135 * the raw event parsing and marked the ccp->wait_input_report
136 * completion as done.
137 */
138 spin_lock_bh(&ccp->wait_input_report_lock);
139 reinit_completion(&ccp->wait_input_report);
140 spin_unlock_bh(&ccp->wait_input_report_lock);
141
142 ret = hid_hw_output_report(ccp->hdev, ccp->cmd_buffer, OUT_BUFFER_SIZE);
143 if (ret < 0)
144 return ret;
145
146 t = wait_for_completion_timeout(&ccp->wait_input_report, msecs_to_jiffies(REQ_TIMEOUT));
147 if (!t)
148 return -ETIMEDOUT;
149
150 if (ccp->buffer_recv_size != IN_BUFFER_SIZE)
151 return -EPROTO;
152
153 return ccp_get_errno(ccp);
154 }
155
ccp_raw_event(struct hid_device * hdev,struct hid_report * report,u8 * data,int size)156 static int ccp_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *data, int size)
157 {
158 struct ccp_device *ccp = hid_get_drvdata(hdev);
159
160 /* only copy buffer when requested */
161 spin_lock(&ccp->wait_input_report_lock);
162 if (!completion_done(&ccp->wait_input_report)) {
163 memcpy(ccp->buffer, data, min(IN_BUFFER_SIZE, size));
164 ccp->buffer_recv_size = size;
165 complete_all(&ccp->wait_input_report);
166 }
167 spin_unlock(&ccp->wait_input_report_lock);
168
169 return 0;
170 }
171
172 /* requests and returns single data values depending on channel */
get_data(struct ccp_device * ccp,int command,int channel,bool two_byte_data)173 static int get_data(struct ccp_device *ccp, int command, int channel, bool two_byte_data)
174 {
175 int ret;
176
177 mutex_lock(&ccp->mutex);
178
179 ret = send_usb_cmd(ccp, command, channel, 0, 0);
180 if (ret)
181 goto out_unlock;
182
183 ret = ccp->buffer[1];
184 if (two_byte_data)
185 ret = (ret << 8) + ccp->buffer[2];
186
187 out_unlock:
188 mutex_unlock(&ccp->mutex);
189 return ret;
190 }
191
set_pwm(struct ccp_device * ccp,int channel,long val)192 static int set_pwm(struct ccp_device *ccp, int channel, long val)
193 {
194 int ret;
195
196 if (val < 0 || val > 255)
197 return -EINVAL;
198
199 /* The Corsair Commander Pro uses values from 0-100 */
200 val = DIV_ROUND_CLOSEST(val * 100, 255);
201
202 mutex_lock(&ccp->mutex);
203
204 ret = send_usb_cmd(ccp, CTL_SET_FAN_FPWM, channel, val, 0);
205 if (!ret)
206 ccp->target[channel] = -ENODATA;
207
208 mutex_unlock(&ccp->mutex);
209 return ret;
210 }
211
set_target(struct ccp_device * ccp,int channel,long val)212 static int set_target(struct ccp_device *ccp, int channel, long val)
213 {
214 int ret;
215
216 val = clamp_val(val, 0, 0xFFFF);
217 ccp->target[channel] = val;
218
219 mutex_lock(&ccp->mutex);
220 ret = send_usb_cmd(ccp, CTL_SET_FAN_TARGET, channel, val >> 8, val);
221
222 mutex_unlock(&ccp->mutex);
223 return ret;
224 }
225
ccp_read_string(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,const char ** str)226 static int ccp_read_string(struct device *dev, enum hwmon_sensor_types type,
227 u32 attr, int channel, const char **str)
228 {
229 struct ccp_device *ccp = dev_get_drvdata(dev);
230
231 switch (type) {
232 case hwmon_fan:
233 switch (attr) {
234 case hwmon_fan_label:
235 *str = ccp->fan_label[channel];
236 return 0;
237 default:
238 break;
239 }
240 break;
241 default:
242 break;
243 }
244
245 return -EOPNOTSUPP;
246 }
247
ccp_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * val)248 static int ccp_read(struct device *dev, enum hwmon_sensor_types type,
249 u32 attr, int channel, long *val)
250 {
251 struct ccp_device *ccp = dev_get_drvdata(dev);
252 int ret;
253
254 switch (type) {
255 case hwmon_temp:
256 switch (attr) {
257 case hwmon_temp_input:
258 ret = get_data(ccp, CTL_GET_TMP, channel, true);
259 if (ret < 0)
260 return ret;
261 *val = ret * 10;
262 return 0;
263 default:
264 break;
265 }
266 break;
267 case hwmon_fan:
268 switch (attr) {
269 case hwmon_fan_input:
270 ret = get_data(ccp, CTL_GET_FAN_RPM, channel, true);
271 if (ret < 0)
272 return ret;
273 *val = ret;
274 return 0;
275 case hwmon_fan_target:
276 /* how to read target values from the device is unknown */
277 /* driver returns last set value or 0 */
278 if (ccp->target[channel] < 0)
279 return -ENODATA;
280 *val = ccp->target[channel];
281 return 0;
282 default:
283 break;
284 }
285 break;
286 case hwmon_pwm:
287 switch (attr) {
288 case hwmon_pwm_input:
289 ret = get_data(ccp, CTL_GET_FAN_PWM, channel, false);
290 if (ret < 0)
291 return ret;
292 *val = DIV_ROUND_CLOSEST(ret * 255, 100);
293 return 0;
294 default:
295 break;
296 }
297 break;
298 case hwmon_in:
299 switch (attr) {
300 case hwmon_in_input:
301 ret = get_data(ccp, CTL_GET_VOLT, channel, true);
302 if (ret < 0)
303 return ret;
304 *val = ret;
305 return 0;
306 default:
307 break;
308 }
309 break;
310 default:
311 break;
312 }
313
314 return -EOPNOTSUPP;
315 };
316
ccp_write(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long val)317 static int ccp_write(struct device *dev, enum hwmon_sensor_types type,
318 u32 attr, int channel, long val)
319 {
320 struct ccp_device *ccp = dev_get_drvdata(dev);
321
322 switch (type) {
323 case hwmon_pwm:
324 switch (attr) {
325 case hwmon_pwm_input:
326 return set_pwm(ccp, channel, val);
327 default:
328 break;
329 }
330 break;
331 case hwmon_fan:
332 switch (attr) {
333 case hwmon_fan_target:
334 return set_target(ccp, channel, val);
335 default:
336 break;
337 }
338 break;
339 default:
340 break;
341 }
342
343 return -EOPNOTSUPP;
344 };
345
ccp_is_visible(const void * data,enum hwmon_sensor_types type,u32 attr,int channel)346 static umode_t ccp_is_visible(const void *data, enum hwmon_sensor_types type,
347 u32 attr, int channel)
348 {
349 const struct ccp_device *ccp = data;
350
351 switch (type) {
352 case hwmon_temp:
353 if (!test_bit(channel, ccp->temp_cnct))
354 break;
355
356 switch (attr) {
357 case hwmon_temp_input:
358 return 0444;
359 case hwmon_temp_label:
360 return 0444;
361 default:
362 break;
363 }
364 break;
365 case hwmon_fan:
366 if (!test_bit(channel, ccp->fan_cnct))
367 break;
368
369 switch (attr) {
370 case hwmon_fan_input:
371 return 0444;
372 case hwmon_fan_label:
373 return 0444;
374 case hwmon_fan_target:
375 return 0644;
376 default:
377 break;
378 }
379 break;
380 case hwmon_pwm:
381 if (!test_bit(channel, ccp->fan_cnct))
382 break;
383
384 switch (attr) {
385 case hwmon_pwm_input:
386 return 0644;
387 default:
388 break;
389 }
390 break;
391 case hwmon_in:
392 switch (attr) {
393 case hwmon_in_input:
394 return 0444;
395 default:
396 break;
397 }
398 break;
399 default:
400 break;
401 }
402
403 return 0;
404 };
405
406 static const struct hwmon_ops ccp_hwmon_ops = {
407 .is_visible = ccp_is_visible,
408 .read = ccp_read,
409 .read_string = ccp_read_string,
410 .write = ccp_write,
411 };
412
413 static const struct hwmon_channel_info * const ccp_info[] = {
414 HWMON_CHANNEL_INFO(chip,
415 HWMON_C_REGISTER_TZ),
416 HWMON_CHANNEL_INFO(temp,
417 HWMON_T_INPUT,
418 HWMON_T_INPUT,
419 HWMON_T_INPUT,
420 HWMON_T_INPUT
421 ),
422 HWMON_CHANNEL_INFO(fan,
423 HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET,
424 HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET,
425 HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET,
426 HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET,
427 HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET,
428 HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_TARGET
429 ),
430 HWMON_CHANNEL_INFO(pwm,
431 HWMON_PWM_INPUT,
432 HWMON_PWM_INPUT,
433 HWMON_PWM_INPUT,
434 HWMON_PWM_INPUT,
435 HWMON_PWM_INPUT,
436 HWMON_PWM_INPUT
437 ),
438 HWMON_CHANNEL_INFO(in,
439 HWMON_I_INPUT,
440 HWMON_I_INPUT,
441 HWMON_I_INPUT
442 ),
443 NULL
444 };
445
446 static const struct hwmon_chip_info ccp_chip_info = {
447 .ops = &ccp_hwmon_ops,
448 .info = ccp_info,
449 };
450
451 /* read fan connection status and set labels */
get_fan_cnct(struct ccp_device * ccp)452 static int get_fan_cnct(struct ccp_device *ccp)
453 {
454 int channel;
455 int mode;
456 int ret;
457
458 ret = send_usb_cmd(ccp, CTL_GET_FAN_CNCT, 0, 0, 0);
459 if (ret)
460 return ret;
461
462 for (channel = 0; channel < NUM_FANS; channel++) {
463 mode = ccp->buffer[channel + 1];
464 if (mode == 0)
465 continue;
466
467 set_bit(channel, ccp->fan_cnct);
468 ccp->target[channel] = -ENODATA;
469
470 switch (mode) {
471 case 1:
472 scnprintf(ccp->fan_label[channel], LABEL_LENGTH,
473 "fan%d 3pin", channel + 1);
474 break;
475 case 2:
476 scnprintf(ccp->fan_label[channel], LABEL_LENGTH,
477 "fan%d 4pin", channel + 1);
478 break;
479 default:
480 scnprintf(ccp->fan_label[channel], LABEL_LENGTH,
481 "fan%d other", channel + 1);
482 break;
483 }
484 }
485
486 return 0;
487 }
488
489 /* read temp sensor connection status */
get_temp_cnct(struct ccp_device * ccp)490 static int get_temp_cnct(struct ccp_device *ccp)
491 {
492 int channel;
493 int mode;
494 int ret;
495
496 ret = send_usb_cmd(ccp, CTL_GET_TMP_CNCT, 0, 0, 0);
497 if (ret)
498 return ret;
499
500 for (channel = 0; channel < NUM_TEMP_SENSORS; channel++) {
501 mode = ccp->buffer[channel + 1];
502 if (mode == 0)
503 continue;
504
505 set_bit(channel, ccp->temp_cnct);
506 }
507
508 return 0;
509 }
510
511 /* read firmware version */
get_fw_version(struct ccp_device * ccp)512 static int get_fw_version(struct ccp_device *ccp)
513 {
514 int ret;
515
516 ret = send_usb_cmd(ccp, CTL_GET_FW_VER, 0, 0, 0);
517 if (ret) {
518 hid_notice(ccp->hdev, "Failed to read firmware version.\n");
519 return ret;
520 }
521 ccp->firmware_ver[0] = ccp->buffer[1];
522 ccp->firmware_ver[1] = ccp->buffer[2];
523 ccp->firmware_ver[2] = ccp->buffer[3];
524
525 return 0;
526 }
527
528 /* read bootloader version */
get_bl_version(struct ccp_device * ccp)529 static int get_bl_version(struct ccp_device *ccp)
530 {
531 int ret;
532
533 ret = send_usb_cmd(ccp, CTL_GET_BL_VER, 0, 0, 0);
534 if (ret) {
535 hid_notice(ccp->hdev, "Failed to read bootloader version.\n");
536 return ret;
537 }
538 ccp->bootloader_ver[0] = ccp->buffer[1];
539 ccp->bootloader_ver[1] = ccp->buffer[2];
540
541 return 0;
542 }
543
firmware_show(struct seq_file * seqf,void * unused)544 static int firmware_show(struct seq_file *seqf, void *unused)
545 {
546 struct ccp_device *ccp = seqf->private;
547
548 seq_printf(seqf, "%d.%d.%d\n",
549 ccp->firmware_ver[0],
550 ccp->firmware_ver[1],
551 ccp->firmware_ver[2]);
552
553 return 0;
554 }
555 DEFINE_SHOW_ATTRIBUTE(firmware);
556
bootloader_show(struct seq_file * seqf,void * unused)557 static int bootloader_show(struct seq_file *seqf, void *unused)
558 {
559 struct ccp_device *ccp = seqf->private;
560
561 seq_printf(seqf, "%d.%d\n",
562 ccp->bootloader_ver[0],
563 ccp->bootloader_ver[1]);
564
565 return 0;
566 }
567 DEFINE_SHOW_ATTRIBUTE(bootloader);
568
ccp_debugfs_init(struct ccp_device * ccp)569 static void ccp_debugfs_init(struct ccp_device *ccp)
570 {
571 char name[32];
572 int ret;
573
574 scnprintf(name, sizeof(name), "corsaircpro-%s", dev_name(&ccp->hdev->dev));
575 ccp->debugfs = debugfs_create_dir(name, NULL);
576
577 ret = get_fw_version(ccp);
578 if (!ret)
579 debugfs_create_file("firmware_version", 0444,
580 ccp->debugfs, ccp, &firmware_fops);
581
582 ret = get_bl_version(ccp);
583 if (!ret)
584 debugfs_create_file("bootloader_version", 0444,
585 ccp->debugfs, ccp, &bootloader_fops);
586 }
587
ccp_probe(struct hid_device * hdev,const struct hid_device_id * id)588 static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id)
589 {
590 struct ccp_device *ccp;
591 int ret;
592
593 ccp = devm_kzalloc(&hdev->dev, sizeof(*ccp), GFP_KERNEL);
594 if (!ccp)
595 return -ENOMEM;
596
597 ccp->cmd_buffer = devm_kmalloc(&hdev->dev, OUT_BUFFER_SIZE, GFP_KERNEL);
598 if (!ccp->cmd_buffer)
599 return -ENOMEM;
600
601 ccp->buffer = devm_kmalloc(&hdev->dev, IN_BUFFER_SIZE, GFP_KERNEL);
602 if (!ccp->buffer)
603 return -ENOMEM;
604
605 ret = hid_parse(hdev);
606 if (ret)
607 return ret;
608
609 ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
610 if (ret)
611 return ret;
612
613 ret = hid_hw_open(hdev);
614 if (ret)
615 goto out_hw_stop;
616
617 ccp->hdev = hdev;
618 hid_set_drvdata(hdev, ccp);
619
620 mutex_init(&ccp->mutex);
621 spin_lock_init(&ccp->wait_input_report_lock);
622 init_completion(&ccp->wait_input_report);
623
624 hid_device_io_start(hdev);
625
626 /* temp and fan connection status only updates when device is powered on */
627 ret = get_temp_cnct(ccp);
628 if (ret)
629 goto out_hw_close;
630
631 ret = get_fan_cnct(ccp);
632 if (ret)
633 goto out_hw_close;
634
635 ccp_debugfs_init(ccp);
636
637 ccp->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, "corsaircpro",
638 ccp, &ccp_chip_info, NULL);
639 if (IS_ERR(ccp->hwmon_dev)) {
640 ret = PTR_ERR(ccp->hwmon_dev);
641 goto out_hw_close;
642 }
643
644 return 0;
645
646 out_hw_close:
647 hid_hw_close(hdev);
648 out_hw_stop:
649 hid_hw_stop(hdev);
650 return ret;
651 }
652
ccp_remove(struct hid_device * hdev)653 static void ccp_remove(struct hid_device *hdev)
654 {
655 struct ccp_device *ccp = hid_get_drvdata(hdev);
656
657 debugfs_remove_recursive(ccp->debugfs);
658 hwmon_device_unregister(ccp->hwmon_dev);
659 hid_hw_close(hdev);
660 hid_hw_stop(hdev);
661 }
662
663 static const struct hid_device_id ccp_devices[] = {
664 { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_PRODUCT_ID_CORSAIR_COMMANDERPRO) },
665 { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_PRODUCT_ID_CORSAIR_1000D) },
666 { }
667 };
668
669 static struct hid_driver ccp_driver = {
670 .name = "corsair-cpro",
671 .id_table = ccp_devices,
672 .probe = ccp_probe,
673 .remove = ccp_remove,
674 .raw_event = ccp_raw_event,
675 };
676
677 MODULE_DEVICE_TABLE(hid, ccp_devices);
678 MODULE_DESCRIPTION("Corsair Commander Pro controller driver");
679 MODULE_LICENSE("GPL");
680
ccp_init(void)681 static int __init ccp_init(void)
682 {
683 return hid_register_driver(&ccp_driver);
684 }
685
ccp_exit(void)686 static void __exit ccp_exit(void)
687 {
688 hid_unregister_driver(&ccp_driver);
689 }
690
691 /*
692 * When compiling this driver as built-in, hwmon initcalls will get called before the
693 * hid driver and this driver would fail to register. late_initcall solves this.
694 */
695 late_initcall(ccp_init);
696 module_exit(ccp_exit);
697