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