xref: /linux/drivers/hwmon/asus_rog_ryujin.c (revision 546b928da0427b0d6c663cbb992bd7bfa9ac7971)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * hwmon driver for Asus ROG Ryujin AIO coolers.
4  *
5  * Copyright 2024 Aleksa Savic <savicaleksa83@gmail.com>
6  */
7 
8 #include <linux/debugfs.h>
9 #include <linux/hid.h>
10 #include <linux/hwmon.h>
11 #include <linux/jiffies.h>
12 #include <linux/module.h>
13 #include <linux/spinlock.h>
14 #include <linux/unaligned.h>
15 
16 #define DRIVER_NAME	"asus_rog_ryujin"
17 
18 #define USB_VENDOR_ID_ASUS_ROG		0x0b05
19 #define USB_PRODUCT_ID_RYUJIN_AIO	0x1988	/* ASUS ROG RYUJIN II 360 */
20 #define USB_PRODUCT_ID_RYUJIN_III_EXTREME	0x1bcb
21 #define USB_PRODUCT_ID_RYUJIN_III_EVA		0x1ade
22 #define USB_PRODUCT_ID_RYUJIN_III_WHITE		0x1ada
23 
24 struct rog_ryujin_device_info {
25 	u8 temp_offset;
26 	u8 pump_speed_offset;
27 	u8 fan_speed_offset;
28 	u8 duty_channel;
29 	bool has_controller;
30 };
31 
32 static const struct rog_ryujin_device_info rog_ryujin_ii_360_info = {
33 	.temp_offset = 3,
34 	.pump_speed_offset = 5,
35 	.fan_speed_offset = 7,
36 	.duty_channel = 0,
37 	.has_controller = true,
38 };
39 
40 static const struct rog_ryujin_device_info rog_ryujin_iii_info = {
41 	.temp_offset = 5,
42 	.pump_speed_offset = 7,
43 	.fan_speed_offset = 10,
44 	.duty_channel = 1,
45 	.has_controller = false,
46 };
47 
48 #define STATUS_VALIDITY		1500	/* ms */
49 #define MAX_REPORT_LENGTH	65
50 
51 /* Cooler duty report offsets */
52 #define RYUJIN_PUMP_DUTY		4
53 #define RYUJIN_INTERNAL_FAN_DUTY	5
54 
55 /* Controller status (speeds) report offsets */
56 #define RYUJIN_CONTROLLER_SPEED_1	5
57 #define RYUJIN_CONTROLLER_SPEED_2	7
58 #define RYUJIN_CONTROLLER_SPEED_3	9
59 #define RYUJIN_CONTROLLER_SPEED_4	3
60 
61 /* Controller duty report offsets */
62 #define RYUJIN_CONTROLLER_DUTY		4
63 
64 /* Control commands and their inner offsets */
65 #define RYUJIN_CMD_PREFIX	0xEC
66 
67 static const u8 get_cooler_status_cmd[] = { RYUJIN_CMD_PREFIX, 0x99 };
68 static const u8 get_cooler_duty_cmd[] = { RYUJIN_CMD_PREFIX, 0x9A };
69 static const u8 get_controller_speed_cmd[] = { RYUJIN_CMD_PREFIX, 0xA0 };
70 static const u8 get_controller_duty_cmd[] = { RYUJIN_CMD_PREFIX, 0xA1 };
71 
72 #define RYUJIN_SET_COOLER_PUMP_DUTY_OFFSET	3
73 #define RYUJIN_SET_COOLER_FAN_DUTY_OFFSET	4
74 static const u8 set_cooler_duty_cmd[] = { RYUJIN_CMD_PREFIX, 0x1A, 0x00, 0x00, 0x00 };
75 
76 #define RYUJIN_SET_CONTROLLER_FAN_DUTY_OFFSET	4
77 static const u8 set_controller_duty_cmd[] = { RYUJIN_CMD_PREFIX, 0x21, 0x00, 0x00, 0x00 };
78 
79 /* Command lengths */
80 #define GET_CMD_LENGTH	2	/* Same length for all get commands */
81 #define SET_CMD_LENGTH	5	/* Same length for all set commands */
82 
83 /* Command response headers */
84 #define RYUJIN_GET_COOLER_STATUS_CMD_RESPONSE		0x19
85 #define RYUJIN_GET_COOLER_DUTY_CMD_RESPONSE		0x1A
86 #define RYUJIN_GET_CONTROLLER_SPEED_CMD_RESPONSE	0x20
87 #define RYUJIN_GET_CONTROLLER_DUTY_CMD_RESPONSE		0x21
88 
89 static const char *const rog_ryujin_temp_label[] = {
90 	"Coolant temp"
91 };
92 
93 static const char *const rog_ryujin_speed_label[] = {
94 	"Pump speed",
95 	"Internal fan speed",
96 	"Controller fan 1 speed",
97 	"Controller fan 2 speed",
98 	"Controller fan 3 speed",
99 	"Controller fan 4 speed",
100 };
101 
102 struct rog_ryujin_data {
103 	struct hid_device *hdev;
104 	struct device *hwmon_dev;
105 	const struct rog_ryujin_device_info *info;
106 	/* For reinitializing the completions below */
107 	spinlock_t status_report_request_lock;
108 	struct completion cooler_status_received;
109 	struct completion controller_status_received;
110 	struct completion cooler_duty_received;
111 	struct completion controller_duty_received;
112 	struct completion cooler_duty_set;
113 	struct completion controller_duty_set;
114 
115 	/* Sensor data */
116 	s32 temp_input[1];
117 	u16 speed_input[6];	/* Pump, internal fan and four controller fan speeds in RPM */
118 	u8 duty_input[3];	/* Pump, internal fan and controller fan duty in PWM */
119 
120 	u8 *buffer;
121 	unsigned long updated;	/* jiffies */
122 };
123 
rog_ryujin_percent_to_pwm(u16 val)124 static int rog_ryujin_percent_to_pwm(u16 val)
125 {
126 	return DIV_ROUND_CLOSEST(val * 255, 100);
127 }
128 
rog_ryujin_pwm_to_percent(long val)129 static int rog_ryujin_pwm_to_percent(long val)
130 {
131 	return DIV_ROUND_CLOSEST(val * 100, 255);
132 }
133 
rog_ryujin_is_visible(const void * data,enum hwmon_sensor_types type,u32 attr,int channel)134 static umode_t rog_ryujin_is_visible(const void *data,
135 				     enum hwmon_sensor_types type, u32 attr, int channel)
136 {
137 	const struct rog_ryujin_data *priv = data;
138 
139 	switch (type) {
140 	case hwmon_temp:
141 		switch (attr) {
142 		case hwmon_temp_label:
143 		case hwmon_temp_input:
144 			return 0444;
145 		default:
146 			break;
147 		}
148 		break;
149 	case hwmon_fan:
150 		if (channel >= 2 && !priv->info->has_controller)
151 			return 0;
152 		switch (attr) {
153 		case hwmon_fan_label:
154 		case hwmon_fan_input:
155 			return 0444;
156 		default:
157 			break;
158 		}
159 		break;
160 	case hwmon_pwm:
161 		if (channel >= 2 && !priv->info->has_controller)
162 			return 0;
163 		switch (attr) {
164 		case hwmon_pwm_input:
165 			return 0644;
166 		default:
167 			break;
168 		}
169 		break;
170 	default:
171 		break;
172 	}
173 
174 	return 0;
175 }
176 
177 /* Writes the command to the device with the rest of the report filled with zeroes */
rog_ryujin_write_expanded(struct rog_ryujin_data * priv,const u8 * cmd,int cmd_length)178 static int rog_ryujin_write_expanded(struct rog_ryujin_data *priv, const u8 *cmd, int cmd_length)
179 {
180 	memcpy_and_pad(priv->buffer, MAX_REPORT_LENGTH, cmd, cmd_length, 0x00);
181 	return hid_hw_output_report(priv->hdev, priv->buffer, MAX_REPORT_LENGTH);
182 }
183 
rog_ryujin_execute_cmd(struct rog_ryujin_data * priv,const u8 * cmd,int cmd_length,struct completion * status_completion)184 static int rog_ryujin_execute_cmd(struct rog_ryujin_data *priv, const u8 *cmd, int cmd_length,
185 				  struct completion *status_completion)
186 {
187 	unsigned long flags;
188 	int ret;
189 
190 	/*
191 	 * Disable raw event parsing for a moment to safely reinitialize the
192 	 * completion. Reinit is done because hidraw could have triggered
193 	 * the raw event parsing and marked the passed in completion as done.
194 	 */
195 	spin_lock_irqsave(&priv->status_report_request_lock, flags);
196 	reinit_completion(status_completion);
197 	spin_unlock_irqrestore(&priv->status_report_request_lock, flags);
198 
199 	/* Send command for getting data */
200 	ret = rog_ryujin_write_expanded(priv, cmd, cmd_length);
201 	if (ret < 0)
202 		return ret;
203 
204 	ret = wait_for_completion_interruptible_timeout(status_completion,
205 							msecs_to_jiffies(STATUS_VALIDITY));
206 	if (ret == 0)
207 		return -ETIMEDOUT;
208 	else if (ret < 0)
209 		return ret;
210 
211 	return 0;
212 }
213 
rog_ryujin_get_status(struct rog_ryujin_data * priv)214 static int rog_ryujin_get_status(struct rog_ryujin_data *priv)
215 {
216 	int ret;
217 
218 	if (!time_after(jiffies, priv->updated + msecs_to_jiffies(STATUS_VALIDITY))) {
219 		/* Data is up to date */
220 		return 0;
221 	}
222 
223 	/* Retrieve cooler status */
224 	ret =
225 	    rog_ryujin_execute_cmd(priv, get_cooler_status_cmd, GET_CMD_LENGTH,
226 				   &priv->cooler_status_received);
227 	if (ret < 0)
228 		return ret;
229 
230 	if (priv->info->has_controller) {
231 		/* Retrieve controller status (speeds) */
232 		ret = rog_ryujin_execute_cmd(priv, get_controller_speed_cmd,
233 					     GET_CMD_LENGTH,
234 					     &priv->controller_status_received);
235 		if (ret < 0)
236 			return ret;
237 	}
238 
239 	/* Retrieve cooler duty */
240 	ret =
241 	    rog_ryujin_execute_cmd(priv, get_cooler_duty_cmd, GET_CMD_LENGTH,
242 				   &priv->cooler_duty_received);
243 	if (ret < 0)
244 		return ret;
245 
246 	if (priv->info->has_controller) {
247 		/* Retrieve controller duty */
248 		ret = rog_ryujin_execute_cmd(priv, get_controller_duty_cmd,
249 					     GET_CMD_LENGTH,
250 					     &priv->controller_duty_received);
251 		if (ret < 0)
252 			return ret;
253 	}
254 
255 	priv->updated = jiffies;
256 	return 0;
257 }
258 
rog_ryujin_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * val)259 static int rog_ryujin_read(struct device *dev, enum hwmon_sensor_types type,
260 			   u32 attr, int channel, long *val)
261 {
262 	struct rog_ryujin_data *priv = dev_get_drvdata(dev);
263 	int ret = rog_ryujin_get_status(priv);
264 
265 	if (ret < 0)
266 		return ret;
267 
268 	switch (type) {
269 	case hwmon_temp:
270 		*val = priv->temp_input[channel];
271 		break;
272 	case hwmon_fan:
273 		*val = priv->speed_input[channel];
274 		break;
275 	case hwmon_pwm:
276 		switch (attr) {
277 		case hwmon_pwm_input:
278 			*val = priv->duty_input[channel];
279 			break;
280 		default:
281 			return -EOPNOTSUPP;
282 		}
283 		break;
284 	default:
285 		return -EOPNOTSUPP;	/* unreachable */
286 	}
287 
288 	return 0;
289 }
290 
rog_ryujin_read_string(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,const char ** str)291 static int rog_ryujin_read_string(struct device *dev, enum hwmon_sensor_types type,
292 				  u32 attr, int channel, const char **str)
293 {
294 	switch (type) {
295 	case hwmon_temp:
296 		*str = rog_ryujin_temp_label[channel];
297 		break;
298 	case hwmon_fan:
299 		*str = rog_ryujin_speed_label[channel];
300 		break;
301 	default:
302 		return -EOPNOTSUPP;	/* unreachable */
303 	}
304 
305 	return 0;
306 }
307 
rog_ryujin_write_fixed_duty(struct rog_ryujin_data * priv,int channel,int val)308 static int rog_ryujin_write_fixed_duty(struct rog_ryujin_data *priv, int channel, int val)
309 {
310 	u8 set_cmd[SET_CMD_LENGTH];
311 	int ret;
312 
313 	if (channel < 2) {
314 		/*
315 		 * Retrieve cooler duty since both pump and internal fan are set
316 		 * together, then write back with one of them modified.
317 		 */
318 		ret =
319 		    rog_ryujin_execute_cmd(priv, get_cooler_duty_cmd, GET_CMD_LENGTH,
320 					   &priv->cooler_duty_received);
321 		if (ret < 0)
322 			return ret;
323 
324 		memcpy(set_cmd, set_cooler_duty_cmd, SET_CMD_LENGTH);
325 		set_cmd[2] = priv->info->duty_channel;
326 
327 		/* Cooler duties are set as 0-100% */
328 		val = rog_ryujin_pwm_to_percent(val);
329 
330 		if (channel == 0) {
331 			/* Cooler pump duty */
332 			set_cmd[RYUJIN_SET_COOLER_PUMP_DUTY_OFFSET] = val;
333 			set_cmd[RYUJIN_SET_COOLER_FAN_DUTY_OFFSET] =
334 			    rog_ryujin_pwm_to_percent(priv->duty_input[1]);
335 		} else if (channel == 1) {
336 			/* Cooler internal fan duty */
337 			set_cmd[RYUJIN_SET_COOLER_PUMP_DUTY_OFFSET] =
338 			    rog_ryujin_pwm_to_percent(priv->duty_input[0]);
339 			set_cmd[RYUJIN_SET_COOLER_FAN_DUTY_OFFSET] = val;
340 		}
341 
342 		return rog_ryujin_execute_cmd(priv, set_cmd, SET_CMD_LENGTH, &priv->cooler_duty_set);
343 	} else {
344 		/*
345 		 * Controller fan duty (channel == 2). No need to retrieve current
346 		 * duty, so just send the command.
347 		 */
348 		memcpy(set_cmd, set_controller_duty_cmd, SET_CMD_LENGTH);
349 		set_cmd[RYUJIN_SET_CONTROLLER_FAN_DUTY_OFFSET] = val;
350 
351 		ret =
352 		    rog_ryujin_execute_cmd(priv, set_cmd, SET_CMD_LENGTH,
353 					   &priv->controller_duty_set);
354 		if (ret < 0)
355 			return ret;
356 	}
357 
358 	/* Lock onto this value until next refresh cycle */
359 	priv->duty_input[channel] = val;
360 
361 	return 0;
362 }
363 
rog_ryujin_write(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long val)364 static int rog_ryujin_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel,
365 			    long val)
366 {
367 	struct rog_ryujin_data *priv = dev_get_drvdata(dev);
368 	int ret;
369 
370 	switch (type) {
371 	case hwmon_pwm:
372 		switch (attr) {
373 		case hwmon_pwm_input:
374 			if (val < 0 || val > 255)
375 				return -EINVAL;
376 
377 			ret = rog_ryujin_write_fixed_duty(priv, channel, val);
378 			if (ret < 0)
379 				return ret;
380 			break;
381 		default:
382 			return -EOPNOTSUPP;
383 		}
384 		break;
385 	default:
386 		return -EOPNOTSUPP;
387 	}
388 
389 	return 0;
390 }
391 
392 static const struct hwmon_ops rog_ryujin_hwmon_ops = {
393 	.is_visible = rog_ryujin_is_visible,
394 	.read = rog_ryujin_read,
395 	.read_string = rog_ryujin_read_string,
396 	.write = rog_ryujin_write
397 };
398 
399 static const struct hwmon_channel_info *rog_ryujin_info[] = {
400 	HWMON_CHANNEL_INFO(temp,
401 			   HWMON_T_INPUT | HWMON_T_LABEL),
402 	HWMON_CHANNEL_INFO(fan,
403 			   HWMON_F_INPUT | HWMON_F_LABEL,
404 			   HWMON_F_INPUT | HWMON_F_LABEL,
405 			   HWMON_F_INPUT | HWMON_F_LABEL,
406 			   HWMON_F_INPUT | HWMON_F_LABEL,
407 			   HWMON_F_INPUT | HWMON_F_LABEL,
408 			   HWMON_F_INPUT | HWMON_F_LABEL),
409 	HWMON_CHANNEL_INFO(pwm,
410 			   HWMON_PWM_INPUT,
411 			   HWMON_PWM_INPUT,
412 			   HWMON_PWM_INPUT),
413 	NULL
414 };
415 
416 static const struct hwmon_chip_info rog_ryujin_chip_info = {
417 	.ops = &rog_ryujin_hwmon_ops,
418 	.info = rog_ryujin_info,
419 };
420 
rog_ryujin_raw_event(struct hid_device * hdev,struct hid_report * report,u8 * data,int size)421 static int rog_ryujin_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *data,
422 				int size)
423 {
424 	struct rog_ryujin_data *priv = hid_get_drvdata(hdev);
425 	unsigned long flags;
426 
427 	if (size < 2 || data[0] != RYUJIN_CMD_PREFIX)
428 		return 0;
429 
430 	spin_lock_irqsave(&priv->status_report_request_lock, flags);
431 
432 	if (data[1] == RYUJIN_GET_COOLER_STATUS_CMD_RESPONSE) {
433 		if (size <= priv->info->temp_offset + 1 ||
434 		    size <= priv->info->pump_speed_offset + 1 ||
435 		    size <= priv->info->fan_speed_offset + 1)
436 			goto unlock;
437 
438 		/* Received coolant temp and speeds of pump and internal fan */
439 		priv->temp_input[0] = data[priv->info->temp_offset] * 1000 +
440 			data[priv->info->temp_offset + 1] * 100;
441 		priv->speed_input[0] =
442 			get_unaligned_le16(data + priv->info->pump_speed_offset);
443 		priv->speed_input[1] =
444 			get_unaligned_le16(data + priv->info->fan_speed_offset);
445 
446 		if (!completion_done(&priv->cooler_status_received))
447 			complete_all(&priv->cooler_status_received);
448 	} else if (data[1] == RYUJIN_GET_CONTROLLER_SPEED_CMD_RESPONSE) {
449 		if (size <= RYUJIN_CONTROLLER_SPEED_3 + 1)
450 			goto unlock;
451 
452 		/* Received speeds of four fans attached to the controller */
453 		priv->speed_input[2] = get_unaligned_le16(data + RYUJIN_CONTROLLER_SPEED_1);
454 		priv->speed_input[3] = get_unaligned_le16(data + RYUJIN_CONTROLLER_SPEED_2);
455 		priv->speed_input[4] = get_unaligned_le16(data + RYUJIN_CONTROLLER_SPEED_3);
456 		priv->speed_input[5] = get_unaligned_le16(data + RYUJIN_CONTROLLER_SPEED_4);
457 
458 		if (!completion_done(&priv->controller_status_received))
459 			complete_all(&priv->controller_status_received);
460 	} else if (data[1] == RYUJIN_GET_COOLER_DUTY_CMD_RESPONSE) {
461 		if (size <= RYUJIN_INTERNAL_FAN_DUTY)
462 			goto unlock;
463 
464 		/* Received report for pump and internal fan duties (in %) */
465 		if (data[RYUJIN_PUMP_DUTY] == 0 && data[RYUJIN_INTERNAL_FAN_DUTY] == 0) {
466 			/*
467 			 * We received a report with zeroes for duty in both places.
468 			 * The device returns this as a confirmation that setting values
469 			 * is successful. If we initiated a write, mark it as complete.
470 			 */
471 			if (!completion_done(&priv->cooler_duty_set))
472 				complete_all(&priv->cooler_duty_set);
473 			else if (!completion_done(&priv->cooler_duty_received))
474 				/*
475 				 * We didn't initiate a write, but received both zeroes.
476 				 * This means that either both duties are actually zero,
477 				 * or that we received a success report caused by userspace.
478 				 * We're expecting a report, so parse it.
479 				 */
480 				goto read_cooler_duty;
481 			goto unlock;
482 		}
483 read_cooler_duty:
484 		priv->duty_input[0] = rog_ryujin_percent_to_pwm(data[RYUJIN_PUMP_DUTY]);
485 		priv->duty_input[1] = rog_ryujin_percent_to_pwm(data[RYUJIN_INTERNAL_FAN_DUTY]);
486 
487 		if (!completion_done(&priv->cooler_duty_received))
488 			complete_all(&priv->cooler_duty_received);
489 	} else if (data[1] == RYUJIN_GET_CONTROLLER_DUTY_CMD_RESPONSE) {
490 		if (size <= RYUJIN_CONTROLLER_DUTY)
491 			goto unlock;
492 
493 		/* Received report for controller duty for fans (in PWM) */
494 		if (data[RYUJIN_CONTROLLER_DUTY] == 0) {
495 			/*
496 			 * We received a report with a zero for duty. The device returns this as
497 			 * a confirmation that setting the controller duty value was successful.
498 			 * If we initiated a write, mark it as complete.
499 			 */
500 			if (!completion_done(&priv->controller_duty_set))
501 				complete_all(&priv->controller_duty_set);
502 			else if (!completion_done(&priv->controller_duty_received))
503 				/*
504 				 * We didn't initiate a write, but received a zero for duty.
505 				 * This means that either the duty is actually zero, or that
506 				 * we received a success report caused by userspace.
507 				 * We're expecting a report, so parse it.
508 				 */
509 				goto read_controller_duty;
510 			goto unlock;
511 		}
512 read_controller_duty:
513 		priv->duty_input[2] = data[RYUJIN_CONTROLLER_DUTY];
514 
515 		if (!completion_done(&priv->controller_duty_received))
516 			complete_all(&priv->controller_duty_received);
517 	}
518 
519 unlock:
520 	spin_unlock_irqrestore(&priv->status_report_request_lock, flags);
521 	return 0;
522 }
523 
rog_ryujin_probe(struct hid_device * hdev,const struct hid_device_id * id)524 static int rog_ryujin_probe(struct hid_device *hdev, const struct hid_device_id *id)
525 {
526 	struct rog_ryujin_data *priv;
527 	int ret;
528 
529 	if (!id->driver_data)
530 		return -EINVAL;
531 
532 	priv = devm_kzalloc(&hdev->dev, sizeof(*priv), GFP_KERNEL);
533 	if (!priv)
534 		return -ENOMEM;
535 
536 	priv->hdev = hdev;
537 	priv->info = (const struct rog_ryujin_device_info *)id->driver_data;
538 	hid_set_drvdata(hdev, priv);
539 
540 	/*
541 	 * Initialize priv->updated to STATUS_VALIDITY seconds in the past, making
542 	 * the initial empty data invalid for rog_ryujin_read() without the need for
543 	 * a special case there.
544 	 */
545 	priv->updated = jiffies - msecs_to_jiffies(STATUS_VALIDITY);
546 
547 	ret = hid_parse(hdev);
548 	if (ret) {
549 		hid_err(hdev, "hid parse failed with %d\n", ret);
550 		return ret;
551 	}
552 
553 	/* Enable hidraw so existing user-space tools can continue to work */
554 	ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
555 	if (ret) {
556 		hid_err(hdev, "hid hw start failed with %d\n", ret);
557 		return ret;
558 	}
559 
560 	ret = hid_hw_open(hdev);
561 	if (ret) {
562 		hid_err(hdev, "hid hw open failed with %d\n", ret);
563 		goto fail_and_stop;
564 	}
565 
566 	priv->buffer = devm_kzalloc(&hdev->dev, MAX_REPORT_LENGTH, GFP_KERNEL);
567 	if (!priv->buffer) {
568 		ret = -ENOMEM;
569 		goto fail_and_close;
570 	}
571 
572 	spin_lock_init(&priv->status_report_request_lock);
573 	init_completion(&priv->cooler_status_received);
574 	init_completion(&priv->controller_status_received);
575 	init_completion(&priv->cooler_duty_received);
576 	init_completion(&priv->controller_duty_received);
577 	init_completion(&priv->cooler_duty_set);
578 	init_completion(&priv->controller_duty_set);
579 
580 	priv->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, "rog_ryujin",
581 							  priv, &rog_ryujin_chip_info, NULL);
582 	if (IS_ERR(priv->hwmon_dev)) {
583 		ret = PTR_ERR(priv->hwmon_dev);
584 		hid_err(hdev, "hwmon registration failed with %d\n", ret);
585 		goto fail_and_close;
586 	}
587 
588 	return 0;
589 
590 fail_and_close:
591 	hid_hw_close(hdev);
592 fail_and_stop:
593 	hid_hw_stop(hdev);
594 	return ret;
595 }
596 
rog_ryujin_remove(struct hid_device * hdev)597 static void rog_ryujin_remove(struct hid_device *hdev)
598 {
599 	struct rog_ryujin_data *priv = hid_get_drvdata(hdev);
600 
601 	hwmon_device_unregister(priv->hwmon_dev);
602 
603 	hid_hw_close(hdev);
604 	hid_hw_stop(hdev);
605 }
606 
607 static const struct hid_device_id rog_ryujin_table[] = {
608 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS_ROG, USB_PRODUCT_ID_RYUJIN_AIO),
609 	  .driver_data = (kernel_ulong_t)&rog_ryujin_ii_360_info },
610 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS_ROG, USB_PRODUCT_ID_RYUJIN_III_EXTREME),
611 	  .driver_data = (kernel_ulong_t)&rog_ryujin_iii_info },
612 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS_ROG, USB_PRODUCT_ID_RYUJIN_III_EVA),
613 	  .driver_data = (kernel_ulong_t)&rog_ryujin_iii_info },
614 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUS_ROG, USB_PRODUCT_ID_RYUJIN_III_WHITE),
615 	  .driver_data = (kernel_ulong_t)&rog_ryujin_iii_info },
616 	{ }
617 };
618 
619 MODULE_DEVICE_TABLE(hid, rog_ryujin_table);
620 
621 static struct hid_driver rog_ryujin_driver = {
622 	.name = "rog_ryujin",
623 	.id_table = rog_ryujin_table,
624 	.probe = rog_ryujin_probe,
625 	.remove = rog_ryujin_remove,
626 	.raw_event = rog_ryujin_raw_event,
627 };
628 
rog_ryujin_init(void)629 static int __init rog_ryujin_init(void)
630 {
631 	return hid_register_driver(&rog_ryujin_driver);
632 }
633 
rog_ryujin_exit(void)634 static void __exit rog_ryujin_exit(void)
635 {
636 	hid_unregister_driver(&rog_ryujin_driver);
637 }
638 
639 /* When compiled into the kernel, initialize after the HID bus */
640 late_initcall(rog_ryujin_init);
641 module_exit(rog_ryujin_exit);
642 
643 MODULE_LICENSE("GPL");
644 MODULE_AUTHOR("Aleksa Savic <savicaleksa83@gmail.com>");
645 MODULE_DESCRIPTION("Hwmon driver for Asus ROG Ryujin AIO coolers");
646