Lines Matching +full:channel +full:- +full:1
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * corsair-cpro.c - Linux driver for Corsair Commander Pro
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 */
36 * returns in bytes 1-4 for each temp sensor:
38 * 1 connected
41 * send: byte 1 is channel, rest zero
42 * rcv: returns temp for channel in centi-degree celsius
43 * in bytes 1 and 2
47 * send: byte 1 is rail number: 0 = 12v, 1 = 5v, 2 = 3.3v
48 * rcv: returns millivolt in bytes 1,2
52 * returns in bytes 1-6 for each fan:
54 * 1 3pin
58 * send: byte 1 is channel, rest zero
59 * rcv: returns rpm in bytes 1,2
62 * send: byte 1 is channel, rest zero
63 * rcv: returns pwm in byte 1 if it was set
69 * send: byte 1 is fan number
70 * send: byte 2 is percentage from 0 - 100
74 * send: byte 1 is fan number
75 * send: byte 2-3 is target
76 * device accepts all values from 0x00 - 0xFFFF
103 switch (ccp->buffer[0]) { in ccp_get_errno()
107 return -EOPNOTSUPP; in ccp_get_errno()
109 return -EINVAL; in ccp_get_errno()
112 return -ENODATA; in ccp_get_errno()
114 hid_dbg(ccp->hdev, "unknown device response error: %d", ccp->buffer[0]); in ccp_get_errno()
115 return -EIO; in ccp_get_errno()
119 /* send command, check for error in response, response in ccp->buffer */
125 memset(ccp->cmd_buffer, 0x00, OUT_BUFFER_SIZE); in send_usb_cmd()
126 ccp->cmd_buffer[0] = command; in send_usb_cmd()
127 ccp->cmd_buffer[1] = byte1; in send_usb_cmd()
128 ccp->cmd_buffer[2] = byte2; in send_usb_cmd()
129 ccp->cmd_buffer[3] = byte3; in send_usb_cmd()
134 * the raw event parsing and marked the ccp->wait_input_report in send_usb_cmd()
137 spin_lock_bh(&ccp->wait_input_report_lock); in send_usb_cmd()
138 reinit_completion(&ccp->wait_input_report); in send_usb_cmd()
139 spin_unlock_bh(&ccp->wait_input_report_lock); in send_usb_cmd()
141 ret = hid_hw_output_report(ccp->hdev, ccp->cmd_buffer, OUT_BUFFER_SIZE); in send_usb_cmd()
145 t = wait_for_completion_timeout(&ccp->wait_input_report, msecs_to_jiffies(REQ_TIMEOUT)); in send_usb_cmd()
147 return -ETIMEDOUT; in send_usb_cmd()
157 spin_lock(&ccp->wait_input_report_lock); in ccp_raw_event()
158 if (!completion_done(&ccp->wait_input_report)) { in ccp_raw_event()
159 memcpy(ccp->buffer, data, min(IN_BUFFER_SIZE, size)); in ccp_raw_event()
160 complete_all(&ccp->wait_input_report); in ccp_raw_event()
162 spin_unlock(&ccp->wait_input_report_lock); in ccp_raw_event()
167 /* requests and returns single data values depending on channel */
168 static int get_data(struct ccp_device *ccp, int command, int channel, bool two_byte_data) in get_data() argument
172 mutex_lock(&ccp->mutex); in get_data()
174 ret = send_usb_cmd(ccp, command, channel, 0, 0); in get_data()
178 ret = ccp->buffer[1]; in get_data()
180 ret = (ret << 8) + ccp->buffer[2]; in get_data()
183 mutex_unlock(&ccp->mutex); in get_data()
187 static int set_pwm(struct ccp_device *ccp, int channel, long val) in set_pwm() argument
192 return -EINVAL; in set_pwm()
194 /* The Corsair Commander Pro uses values from 0-100 */ in set_pwm()
197 mutex_lock(&ccp->mutex); in set_pwm()
199 ret = send_usb_cmd(ccp, CTL_SET_FAN_FPWM, channel, val, 0); in set_pwm()
201 ccp->target[channel] = -ENODATA; in set_pwm()
203 mutex_unlock(&ccp->mutex); in set_pwm()
207 static int set_target(struct ccp_device *ccp, int channel, long val) in set_target() argument
212 ccp->target[channel] = val; in set_target()
214 mutex_lock(&ccp->mutex); in set_target()
215 ret = send_usb_cmd(ccp, CTL_SET_FAN_TARGET, channel, val >> 8, val); in set_target()
217 mutex_unlock(&ccp->mutex); in set_target()
222 u32 attr, int channel, const char **str) in ccp_read_string() argument
230 *str = ccp->fan_label[channel]; in ccp_read_string()
240 return -EOPNOTSUPP; in ccp_read_string()
244 u32 attr, int channel, long *val) in ccp_read() argument
253 ret = get_data(ccp, CTL_GET_TMP, channel, true); in ccp_read()
265 ret = get_data(ccp, CTL_GET_FAN_RPM, channel, true); in ccp_read()
273 if (ccp->target[channel] < 0) in ccp_read()
274 return -ENODATA; in ccp_read()
275 *val = ccp->target[channel]; in ccp_read()
284 ret = get_data(ccp, CTL_GET_FAN_PWM, channel, false); in ccp_read()
296 ret = get_data(ccp, CTL_GET_VOLT, channel, true); in ccp_read()
309 return -EOPNOTSUPP; in ccp_read()
313 u32 attr, int channel, long val) in ccp_write() argument
321 return set_pwm(ccp, channel, val); in ccp_write()
329 return set_target(ccp, channel, val); in ccp_write()
338 return -EOPNOTSUPP; in ccp_write()
342 u32 attr, int channel) in ccp_is_visible() argument
348 if (!test_bit(channel, ccp->temp_cnct)) in ccp_is_visible()
361 if (!test_bit(channel, ccp->fan_cnct)) in ccp_is_visible()
376 if (!test_bit(channel, ccp->fan_cnct)) in ccp_is_visible()
449 int channel; in get_fan_cnct() local
457 for (channel = 0; channel < NUM_FANS; channel++) { in get_fan_cnct()
458 mode = ccp->buffer[channel + 1]; in get_fan_cnct()
462 set_bit(channel, ccp->fan_cnct); in get_fan_cnct()
463 ccp->target[channel] = -ENODATA; in get_fan_cnct()
466 case 1: in get_fan_cnct()
467 scnprintf(ccp->fan_label[channel], LABEL_LENGTH, in get_fan_cnct()
468 "fan%d 3pin", channel + 1); in get_fan_cnct()
471 scnprintf(ccp->fan_label[channel], LABEL_LENGTH, in get_fan_cnct()
472 "fan%d 4pin", channel + 1); in get_fan_cnct()
475 scnprintf(ccp->fan_label[channel], LABEL_LENGTH, in get_fan_cnct()
476 "fan%d other", channel + 1); in get_fan_cnct()
487 int channel; in get_temp_cnct() local
495 for (channel = 0; channel < NUM_TEMP_SENSORS; channel++) { in get_temp_cnct()
496 mode = ccp->buffer[channel + 1]; in get_temp_cnct()
500 set_bit(channel, ccp->temp_cnct); in get_temp_cnct()
513 hid_notice(ccp->hdev, "Failed to read firmware version.\n"); in get_fw_version()
516 ccp->firmware_ver[0] = ccp->buffer[1]; in get_fw_version()
517 ccp->firmware_ver[1] = ccp->buffer[2]; in get_fw_version()
518 ccp->firmware_ver[2] = ccp->buffer[3]; in get_fw_version()
530 hid_notice(ccp->hdev, "Failed to read bootloader version.\n"); in get_bl_version()
533 ccp->bootloader_ver[0] = ccp->buffer[1]; in get_bl_version()
534 ccp->bootloader_ver[1] = ccp->buffer[2]; in get_bl_version()
541 struct ccp_device *ccp = seqf->private; in firmware_show()
544 ccp->firmware_ver[0], in firmware_show()
545 ccp->firmware_ver[1], in firmware_show()
546 ccp->firmware_ver[2]); in firmware_show()
554 struct ccp_device *ccp = seqf->private; in bootloader_show()
557 ccp->bootloader_ver[0], in bootloader_show()
558 ccp->bootloader_ver[1]); in bootloader_show()
569 scnprintf(name, sizeof(name), "corsaircpro-%s", dev_name(&ccp->hdev->dev)); in ccp_debugfs_init()
570 ccp->debugfs = debugfs_create_dir(name, NULL); in ccp_debugfs_init()
575 ccp->debugfs, ccp, &firmware_fops); in ccp_debugfs_init()
580 ccp->debugfs, ccp, &bootloader_fops); in ccp_debugfs_init()
588 ccp = devm_kzalloc(&hdev->dev, sizeof(*ccp), GFP_KERNEL); in ccp_probe()
590 return -ENOMEM; in ccp_probe()
592 ccp->cmd_buffer = devm_kmalloc(&hdev->dev, OUT_BUFFER_SIZE, GFP_KERNEL); in ccp_probe()
593 if (!ccp->cmd_buffer) in ccp_probe()
594 return -ENOMEM; in ccp_probe()
596 ccp->buffer = devm_kmalloc(&hdev->dev, IN_BUFFER_SIZE, GFP_KERNEL); in ccp_probe()
597 if (!ccp->buffer) in ccp_probe()
598 return -ENOMEM; in ccp_probe()
612 ccp->hdev = hdev; in ccp_probe()
615 mutex_init(&ccp->mutex); in ccp_probe()
616 spin_lock_init(&ccp->wait_input_report_lock); in ccp_probe()
617 init_completion(&ccp->wait_input_report); in ccp_probe()
632 ccp->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, "corsaircpro", in ccp_probe()
634 if (IS_ERR(ccp->hwmon_dev)) { in ccp_probe()
635 ret = PTR_ERR(ccp->hwmon_dev); in ccp_probe()
652 debugfs_remove_recursive(ccp->debugfs); in ccp_remove()
653 hwmon_device_unregister(ccp->hwmon_dev); in ccp_remove()
665 .name = "corsair-cpro",
687 * When compiling this driver as built-in, hwmon initcalls will get called before the