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