Lines Matching +full:1 +full:- +full:channel
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
104 switch (ccp->buffer[0]) { in ccp_get_errno()
108 return -EOPNOTSUPP; in ccp_get_errno()
110 return -EINVAL; in ccp_get_errno()
113 return -ENODATA; in ccp_get_errno()
115 hid_dbg(ccp->hdev, "unknown device response error: %d", ccp->buffer[0]); in ccp_get_errno()
116 return -EIO; in ccp_get_errno()
120 /* send command, check for error in response, response in ccp->buffer */
126 memset(ccp->cmd_buffer, 0x00, OUT_BUFFER_SIZE); in send_usb_cmd()
127 ccp->cmd_buffer[0] = command; in send_usb_cmd()
128 ccp->cmd_buffer[1] = byte1; in send_usb_cmd()
129 ccp->cmd_buffer[2] = byte2; in send_usb_cmd()
130 ccp->cmd_buffer[3] = byte3; in send_usb_cmd()
135 * the raw event parsing and marked the ccp->wait_input_report in send_usb_cmd()
138 spin_lock_bh(&ccp->wait_input_report_lock); in send_usb_cmd()
139 reinit_completion(&ccp->wait_input_report); in send_usb_cmd()
140 spin_unlock_bh(&ccp->wait_input_report_lock); in send_usb_cmd()
142 ret = hid_hw_output_report(ccp->hdev, ccp->cmd_buffer, OUT_BUFFER_SIZE); in send_usb_cmd()
146 t = wait_for_completion_timeout(&ccp->wait_input_report, msecs_to_jiffies(REQ_TIMEOUT)); in send_usb_cmd()
148 return -ETIMEDOUT; in send_usb_cmd()
150 if (ccp->buffer_recv_size != IN_BUFFER_SIZE) in send_usb_cmd()
151 return -EPROTO; in send_usb_cmd()
161 spin_lock(&ccp->wait_input_report_lock); in ccp_raw_event()
162 if (!completion_done(&ccp->wait_input_report)) { in ccp_raw_event()
163 memcpy(ccp->buffer, data, min(IN_BUFFER_SIZE, size)); in ccp_raw_event()
164 ccp->buffer_recv_size = size; in ccp_raw_event()
165 complete_all(&ccp->wait_input_report); in ccp_raw_event()
167 spin_unlock(&ccp->wait_input_report_lock); in ccp_raw_event()
172 /* requests and returns single data values depending on channel */
173 static int get_data(struct ccp_device *ccp, int command, int channel, bool two_byte_data) in get_data() argument
177 mutex_lock(&ccp->mutex); in get_data()
179 ret = send_usb_cmd(ccp, command, channel, 0, 0); in get_data()
183 ret = ccp->buffer[1]; in get_data()
185 ret = (ret << 8) + ccp->buffer[2]; in get_data()
188 mutex_unlock(&ccp->mutex); in get_data()
192 static int set_pwm(struct ccp_device *ccp, int channel, long val) in set_pwm() argument
197 return -EINVAL; in set_pwm()
199 /* The Corsair Commander Pro uses values from 0-100 */ in set_pwm()
202 mutex_lock(&ccp->mutex); in set_pwm()
204 ret = send_usb_cmd(ccp, CTL_SET_FAN_FPWM, channel, val, 0); in set_pwm()
206 ccp->target[channel] = -ENODATA; in set_pwm()
208 mutex_unlock(&ccp->mutex); in set_pwm()
212 static int set_target(struct ccp_device *ccp, int channel, long val) in set_target() argument
217 ccp->target[channel] = val; in set_target()
219 mutex_lock(&ccp->mutex); in set_target()
220 ret = send_usb_cmd(ccp, CTL_SET_FAN_TARGET, channel, val >> 8, val); in set_target()
222 mutex_unlock(&ccp->mutex); in set_target()
227 u32 attr, int channel, const char **str) in ccp_read_string() argument
235 *str = ccp->fan_label[channel]; in ccp_read_string()
245 return -EOPNOTSUPP; in ccp_read_string()
249 u32 attr, int channel, long *val) in ccp_read() argument
258 ret = get_data(ccp, CTL_GET_TMP, channel, true); in ccp_read()
270 ret = get_data(ccp, CTL_GET_FAN_RPM, channel, true); in ccp_read()
278 if (ccp->target[channel] < 0) in ccp_read()
279 return -ENODATA; in ccp_read()
280 *val = ccp->target[channel]; in ccp_read()
289 ret = get_data(ccp, CTL_GET_FAN_PWM, channel, false); in ccp_read()
301 ret = get_data(ccp, CTL_GET_VOLT, channel, true); in ccp_read()
314 return -EOPNOTSUPP; in ccp_read()
318 u32 attr, int channel, long val) in ccp_write() argument
326 return set_pwm(ccp, channel, val); in ccp_write()
334 return set_target(ccp, channel, val); in ccp_write()
343 return -EOPNOTSUPP; in ccp_write()
347 u32 attr, int channel) in ccp_is_visible() argument
353 if (!test_bit(channel, ccp->temp_cnct)) in ccp_is_visible()
366 if (!test_bit(channel, ccp->fan_cnct)) in ccp_is_visible()
381 if (!test_bit(channel, ccp->fan_cnct)) in ccp_is_visible()
454 int channel; in get_fan_cnct() local
462 for (channel = 0; channel < NUM_FANS; channel++) { in get_fan_cnct()
463 mode = ccp->buffer[channel + 1]; in get_fan_cnct()
467 set_bit(channel, ccp->fan_cnct); in get_fan_cnct()
468 ccp->target[channel] = -ENODATA; in get_fan_cnct()
471 case 1: in get_fan_cnct()
472 scnprintf(ccp->fan_label[channel], LABEL_LENGTH, in get_fan_cnct()
473 "fan%d 3pin", channel + 1); in get_fan_cnct()
476 scnprintf(ccp->fan_label[channel], LABEL_LENGTH, in get_fan_cnct()
477 "fan%d 4pin", channel + 1); in get_fan_cnct()
480 scnprintf(ccp->fan_label[channel], LABEL_LENGTH, in get_fan_cnct()
481 "fan%d other", channel + 1); in get_fan_cnct()
492 int channel; in get_temp_cnct() local
500 for (channel = 0; channel < NUM_TEMP_SENSORS; channel++) { in get_temp_cnct()
501 mode = ccp->buffer[channel + 1]; in get_temp_cnct()
505 set_bit(channel, ccp->temp_cnct); in get_temp_cnct()
518 hid_notice(ccp->hdev, "Failed to read firmware version.\n"); in get_fw_version()
521 ccp->firmware_ver[0] = ccp->buffer[1]; in get_fw_version()
522 ccp->firmware_ver[1] = ccp->buffer[2]; in get_fw_version()
523 ccp->firmware_ver[2] = ccp->buffer[3]; in get_fw_version()
535 hid_notice(ccp->hdev, "Failed to read bootloader version.\n"); in get_bl_version()
538 ccp->bootloader_ver[0] = ccp->buffer[1]; in get_bl_version()
539 ccp->bootloader_ver[1] = ccp->buffer[2]; in get_bl_version()
546 struct ccp_device *ccp = seqf->private; in firmware_show()
549 ccp->firmware_ver[0], in firmware_show()
550 ccp->firmware_ver[1], in firmware_show()
551 ccp->firmware_ver[2]); in firmware_show()
559 struct ccp_device *ccp = seqf->private; in bootloader_show()
562 ccp->bootloader_ver[0], in bootloader_show()
563 ccp->bootloader_ver[1]); in bootloader_show()
574 scnprintf(name, sizeof(name), "corsaircpro-%s", dev_name(&ccp->hdev->dev)); in ccp_debugfs_init()
575 ccp->debugfs = debugfs_create_dir(name, NULL); in ccp_debugfs_init()
580 ccp->debugfs, ccp, &firmware_fops); in ccp_debugfs_init()
585 ccp->debugfs, ccp, &bootloader_fops); in ccp_debugfs_init()
593 ccp = devm_kzalloc(&hdev->dev, sizeof(*ccp), GFP_KERNEL); in ccp_probe()
595 return -ENOMEM; in ccp_probe()
597 ccp->cmd_buffer = devm_kmalloc(&hdev->dev, OUT_BUFFER_SIZE, GFP_KERNEL); in ccp_probe()
598 if (!ccp->cmd_buffer) in ccp_probe()
599 return -ENOMEM; in ccp_probe()
601 ccp->buffer = devm_kmalloc(&hdev->dev, IN_BUFFER_SIZE, GFP_KERNEL); in ccp_probe()
602 if (!ccp->buffer) in ccp_probe()
603 return -ENOMEM; in ccp_probe()
617 ccp->hdev = hdev; in ccp_probe()
620 mutex_init(&ccp->mutex); in ccp_probe()
621 spin_lock_init(&ccp->wait_input_report_lock); in ccp_probe()
622 init_completion(&ccp->wait_input_report); in ccp_probe()
637 ccp->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, "corsaircpro", in ccp_probe()
639 if (IS_ERR(ccp->hwmon_dev)) { in ccp_probe()
640 ret = PTR_ERR(ccp->hwmon_dev); in ccp_probe()
657 debugfs_remove_recursive(ccp->debugfs); in ccp_remove()
658 hwmon_device_unregister(ccp->hwmon_dev); in ccp_remove()
670 .name = "corsair-cpro",
692 * When compiling this driver as built-in, hwmon initcalls will get called before the