Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

hwmon: (corsair-cpro) Add firmware and bootloader information

Add support for reporting firmware and bootloader version using debugfs.
Update documentation accordingly.

Signed-off-by: Marius Zachmann <mail@mariuszachmann.de>
Link: https://lore.kernel.org/r/20240513194734.43040-2-mail@mariuszachmann.de
Signed-off-by: Guenter Roeck <linux@roeck-us.net>

authored by

Marius Zachmann and committed by
Guenter Roeck
5997eb60 1613e604

+96
+8
Documentation/hwmon/corsair-cpro.rst
··· 39 39 pwm[1-6] Sets the fan speed. Values from 0-255. Can only be read if pwm 40 40 was set directly. 41 41 ======================= ===================================================================== 42 + 43 + Debugfs entries 44 + --------------- 45 + 46 + ======================= =================== 47 + firmware_version Firmware version 48 + bootloader_version Bootloader version 49 + ======================= ===================
+88
drivers/hwmon/corsair-cpro.c
··· 10 10 11 11 #include <linux/bitops.h> 12 12 #include <linux/completion.h> 13 + #include <linux/debugfs.h> 13 14 #include <linux/hid.h> 14 15 #include <linux/hwmon.h> 15 16 #include <linux/kernel.h> 16 17 #include <linux/module.h> 17 18 #include <linux/mutex.h> 19 + #include <linux/seq_file.h> 18 20 #include <linux/slab.h> 19 21 #include <linux/spinlock.h> 20 22 #include <linux/types.h> ··· 30 28 #define LABEL_LENGTH 11 31 29 #define REQ_TIMEOUT 300 32 30 31 + #define CTL_GET_FW_VER 0x02 /* returns the firmware version in bytes 1-3 */ 32 + #define CTL_GET_BL_VER 0x06 /* returns the bootloader version in bytes 1-2 */ 33 33 #define CTL_GET_TMP_CNCT 0x10 /* 34 34 * returns in bytes 1-4 for each temp sensor: 35 35 * 0 not connected ··· 82 78 struct ccp_device { 83 79 struct hid_device *hdev; 84 80 struct device *hwmon_dev; 81 + struct dentry *debugfs; 85 82 /* For reinitializing the completion below */ 86 83 spinlock_t wait_input_report_lock; 87 84 struct completion wait_input_report; ··· 93 88 DECLARE_BITMAP(temp_cnct, NUM_TEMP_SENSORS); 94 89 DECLARE_BITMAP(fan_cnct, NUM_FANS); 95 90 char fan_label[6][LABEL_LENGTH]; 91 + u8 firmware_ver[3]; 92 + u8 bootloader_ver[2]; 96 93 }; 97 94 98 95 /* converts response error in buffer to errno */ ··· 503 496 return 0; 504 497 } 505 498 499 + /* read firmware version */ 500 + static int get_fw_version(struct ccp_device *ccp) 501 + { 502 + int ret; 503 + 504 + ret = send_usb_cmd(ccp, CTL_GET_FW_VER, 0, 0, 0); 505 + if (ret) { 506 + hid_notice(ccp->hdev, "Failed to read firmware version.\n"); 507 + return ret; 508 + } 509 + ccp->firmware_ver[0] = ccp->buffer[1]; 510 + ccp->firmware_ver[1] = ccp->buffer[2]; 511 + ccp->firmware_ver[2] = ccp->buffer[3]; 512 + 513 + return 0; 514 + } 515 + 516 + /* read bootloader version */ 517 + static int get_bl_version(struct ccp_device *ccp) 518 + { 519 + int ret; 520 + 521 + ret = send_usb_cmd(ccp, CTL_GET_BL_VER, 0, 0, 0); 522 + if (ret) { 523 + hid_notice(ccp->hdev, "Failed to read bootloader version.\n"); 524 + return ret; 525 + } 526 + ccp->bootloader_ver[0] = ccp->buffer[1]; 527 + ccp->bootloader_ver[1] = ccp->buffer[2]; 528 + 529 + return 0; 530 + } 531 + 532 + static int firmware_show(struct seq_file *seqf, void *unused) 533 + { 534 + struct ccp_device *ccp = seqf->private; 535 + 536 + seq_printf(seqf, "%d.%d.%d\n", 537 + ccp->firmware_ver[0], 538 + ccp->firmware_ver[1], 539 + ccp->firmware_ver[2]); 540 + 541 + return 0; 542 + } 543 + DEFINE_SHOW_ATTRIBUTE(firmware); 544 + 545 + static int bootloader_show(struct seq_file *seqf, void *unused) 546 + { 547 + struct ccp_device *ccp = seqf->private; 548 + 549 + seq_printf(seqf, "%d.%d\n", 550 + ccp->bootloader_ver[0], 551 + ccp->bootloader_ver[1]); 552 + 553 + return 0; 554 + } 555 + DEFINE_SHOW_ATTRIBUTE(bootloader); 556 + 557 + static void ccp_debugfs_init(struct ccp_device *ccp) 558 + { 559 + char name[32]; 560 + int ret; 561 + 562 + scnprintf(name, sizeof(name), "corsaircpro-%s", dev_name(&ccp->hdev->dev)); 563 + ccp->debugfs = debugfs_create_dir(name, NULL); 564 + 565 + ret = get_fw_version(ccp); 566 + if (!ret) 567 + debugfs_create_file("firmware_version", 0444, 568 + ccp->debugfs, ccp, &firmware_fops); 569 + 570 + ret = get_bl_version(ccp); 571 + if (!ret) 572 + debugfs_create_file("bootloader_version", 0444, 573 + ccp->debugfs, ccp, &bootloader_fops); 574 + } 575 + 506 576 static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id) 507 577 { 508 578 struct ccp_device *ccp; ··· 626 542 ret = get_fan_cnct(ccp); 627 543 if (ret) 628 544 goto out_hw_close; 545 + 546 + ccp_debugfs_init(ccp); 547 + 629 548 ccp->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, "corsaircpro", 630 549 ccp, &ccp_chip_info, NULL); 631 550 if (IS_ERR(ccp->hwmon_dev)) { ··· 649 562 { 650 563 struct ccp_device *ccp = hid_get_drvdata(hdev); 651 564 565 + debugfs_remove_recursive(ccp->debugfs); 652 566 hwmon_device_unregister(ccp->hwmon_dev); 653 567 hid_hw_close(hdev); 654 568 hid_hw_stop(hdev);