1 // SPDX-License-Identifier: GPL-2.0+
3 * hwmon driver for NZXT Kraken X53/X63/X73, Z53/Z63/Z73 and 2023/2023 Elite all in one coolers.
4 * X53 and Z53 in code refer to all models in their respective series (shortened for brevity).
5 * 2023 models use the Z53 code paths.
7 * Copyright 2021 Jonas Malaco <jonas@protocubo.io>
8 * Copyright 2022 Aleksa Savic <savicaleksa83@gmail.com>
11 #include <linux/debugfs.h>
12 #include <linux/hid.h>
13 #include <linux/hwmon.h>
14 #include <linux/hwmon-sysfs.h>
15 #include <linux/jiffies.h>
16 #include <linux/module.h>
17 #include <linux/mutex.h>
18 #include <linux/spinlock.h>
19 #include <linux/wait.h>
20 #include <linux/unaligned.h>
22 #define USB_VENDOR_ID_NZXT 0x1e71
23 #define USB_PRODUCT_ID_X53 0x2007
24 #define USB_PRODUCT_ID_X53_SECOND 0x2014
25 #define USB_PRODUCT_ID_Z53 0x3008
26 #define USB_PRODUCT_ID_KRAKEN2023 0x300E
27 #define USB_PRODUCT_ID_KRAKEN2023_ELITE 0x300C
29 enum kinds
{ X53
, Z53
, KRAKEN2023
} __packed
;
30 enum pwm_enable
{ off
, manual
, curve
} __packed
;
32 #define DRIVER_NAME "nzxt_kraken3"
33 #define STATUS_REPORT_ID 0x75
34 #define FIRMWARE_REPORT_ID 0x11
35 #define STATUS_VALIDITY 2000 /* In ms, equivalent to period of four status reports */
36 #define CUSTOM_CURVE_POINTS 40 /* For temps from 20C to 59C (critical temp) */
37 #define PUMP_DUTY_MIN 20 /* In percent */
39 /* Sensor report offsets for Kraken X53 and Z53 */
40 #define TEMP_SENSOR_START_OFFSET 15
41 #define TEMP_SENSOR_END_OFFSET 16
42 #define PUMP_SPEED_OFFSET 17
43 #define PUMP_DUTY_OFFSET 19
45 /* Firmware version report offset for Kraken X53 and Z53 */
46 #define FIRMWARE_VERSION_OFFSET 17
48 /* Sensor report offsets for Kraken Z53 */
49 #define Z53_FAN_SPEED_OFFSET 23
50 #define Z53_FAN_DUTY_OFFSET 25
52 /* Report offsets for control commands for Kraken X53 and Z53 */
53 #define SET_DUTY_ID_OFFSET 1
55 /* Control commands and their lengths for Kraken X53 and Z53 */
57 /* Last byte sets the report interval at 0.5s */
58 static const u8 set_interval_cmd
[] = { 0x70, 0x02, 0x01, 0xB8, 1 };
59 static const u8 finish_init_cmd
[] = { 0x70, 0x01 };
60 static const u8 __maybe_unused get_fw_version_cmd
[] = { 0x10, 0x01 };
61 static const u8 set_pump_duty_cmd_header
[] = { 0x72, 0x00, 0x00, 0x00 };
62 static const u8 z53_get_status_cmd
[] = { 0x74, 0x01 };
64 #define SET_INTERVAL_CMD_LENGTH 5
65 #define FINISH_INIT_CMD_LENGTH 2
66 #define GET_FW_VERSION_CMD_LENGTH 2
67 #define MAX_REPORT_LENGTH 64
68 #define MIN_REPORT_LENGTH 20
69 #define SET_CURVE_DUTY_CMD_HEADER_LENGTH 4
70 /* 4 byte header and 40 duty offsets */
71 #define SET_CURVE_DUTY_CMD_LENGTH (4 + 40)
72 #define Z53_GET_STATUS_CMD_LENGTH 2
74 static const char *const kraken3_temp_label
[] = {
78 static const char *const kraken3_fan_label
[] = {
83 struct kraken3_channel_info
{
86 /* Both values are PWM */
88 u16 fixed_duty
; /* Manually set fixed duty */
90 u8 pwm_points
[CUSTOM_CURVE_POINTS
];
94 struct hid_device
*hdev
;
95 struct device
*hwmon_dev
;
96 struct dentry
*debugfs
;
97 struct mutex buffer_lock
; /* For locking access to buffer */
98 struct mutex z53_status_request_lock
;
99 struct completion fw_version_processed
;
101 * For X53 devices, tracks whether an initial (one) sensor report was received to
102 * make fancontrol not bail outright. For Z53 devices, whether a status report
103 * was processed after requesting one.
105 struct completion status_report_processed
;
106 /* For locking the above completion */
107 spinlock_t status_completion_lock
;
110 struct kraken3_channel_info channel_info
[2]; /* Pump and fan */
111 bool is_device_faulty
;
118 u8 firmware_version
[3];
120 unsigned long updated
; /* jiffies */
123 static umode_t
kraken3_is_visible(const void *data
, enum hwmon_sensor_types type
, u32 attr
,
126 const struct kraken3_data
*priv
= data
;
134 switch (priv
->kind
) {
152 case hwmon_pwm_enable
:
153 case hwmon_pwm_input
:
154 switch (priv
->kind
) {
182 * Writes the command to the device with the rest of the report (up to 64 bytes) filled
185 static int kraken3_write_expanded(struct kraken3_data
*priv
, const u8
*cmd
, int cmd_length
)
189 mutex_lock(&priv
->buffer_lock
);
191 memcpy_and_pad(priv
->buffer
, MAX_REPORT_LENGTH
, cmd
, cmd_length
, 0x00);
192 ret
= hid_hw_output_report(priv
->hdev
, priv
->buffer
, MAX_REPORT_LENGTH
);
194 mutex_unlock(&priv
->buffer_lock
);
198 static int kraken3_percent_to_pwm(long val
)
200 return DIV_ROUND_CLOSEST(val
* 255, 100);
203 static int kraken3_pwm_to_percent(long val
, int channel
)
207 if (val
< 0 || val
> 255)
210 percent_value
= DIV_ROUND_CLOSEST(val
* 100, 255);
212 /* Bring up pump duty to min value if needed */
213 if (channel
== 0 && percent_value
< PUMP_DUTY_MIN
)
214 percent_value
= PUMP_DUTY_MIN
;
216 return percent_value
;
219 static int kraken3_read_x53(struct kraken3_data
*priv
)
223 if (completion_done(&priv
->status_report_processed
))
225 * We're here because data is stale. This means that sensor reports haven't
226 * been received for some time in kraken3_raw_event(). On X-series sensor data
227 * can't be manually requested, so return an error.
232 * Data needs to be read, but a sensor report wasn't yet received. It's usually
233 * fancontrol that requests data this early and it exits if it reads an error code.
234 * So, wait for the first report to be parsed (but up to STATUS_VALIDITY).
235 * This does not concern the Z series devices, because they send a sensor report
236 * only when requested.
238 ret
= wait_for_completion_interruptible_timeout(&priv
->status_report_processed
,
239 msecs_to_jiffies(STATUS_VALIDITY
));
245 /* The first sensor report was parsed on time and reading can continue */
249 /* Covers Z53 and KRAKEN2023 device kinds */
250 static int kraken3_read_z53(struct kraken3_data
*priv
)
252 int ret
= mutex_lock_interruptible(&priv
->z53_status_request_lock
);
257 if (!time_after(jiffies
, priv
->updated
+ msecs_to_jiffies(STATUS_VALIDITY
))) {
258 /* Data is up to date */
259 goto unlock_and_return
;
263 * Disable interrupts for a moment to safely reinit the completion,
264 * as hidraw calls could have allowed one or more readers to complete.
266 spin_lock_bh(&priv
->status_completion_lock
);
267 reinit_completion(&priv
->status_report_processed
);
268 spin_unlock_bh(&priv
->status_completion_lock
);
270 /* Send command for getting status */
271 ret
= kraken3_write_expanded(priv
, z53_get_status_cmd
, Z53_GET_STATUS_CMD_LENGTH
);
273 goto unlock_and_return
;
275 /* Wait for completion from kraken3_raw_event() */
276 ret
= wait_for_completion_interruptible_timeout(&priv
->status_report_processed
,
277 msecs_to_jiffies(STATUS_VALIDITY
));
282 mutex_unlock(&priv
->z53_status_request_lock
);
289 static int kraken3_read(struct device
*dev
, enum hwmon_sensor_types type
, u32 attr
, int channel
,
292 struct kraken3_data
*priv
= dev_get_drvdata(dev
);
295 if (time_after(jiffies
, priv
->updated
+ msecs_to_jiffies(STATUS_VALIDITY
))) {
296 if (priv
->kind
== X53
)
297 ret
= kraken3_read_x53(priv
);
299 ret
= kraken3_read_z53(priv
);
304 if (priv
->is_device_faulty
)
310 *val
= priv
->temp_input
[channel
];
313 *val
= priv
->fan_input
[channel
];
317 case hwmon_pwm_enable
:
318 *val
= priv
->channel_info
[channel
].mode
;
320 case hwmon_pwm_input
:
321 *val
= priv
->channel_info
[channel
].reported_duty
;
334 static int kraken3_read_string(struct device
*dev
, enum hwmon_sensor_types type
, u32 attr
,
335 int channel
, const char **str
)
339 *str
= kraken3_temp_label
[channel
];
342 *str
= kraken3_fan_label
[channel
];
351 /* Writes custom curve to device */
352 static int kraken3_write_curve(struct kraken3_data
*priv
, u8
*curve_array
, int channel
)
354 u8 fixed_duty_cmd
[SET_CURVE_DUTY_CMD_LENGTH
];
357 /* Copy command header */
358 memcpy(fixed_duty_cmd
, set_pump_duty_cmd_header
, SET_CURVE_DUTY_CMD_HEADER_LENGTH
);
360 /* Set the correct ID for writing pump/fan duty (0x01 or 0x02, respectively) */
361 fixed_duty_cmd
[SET_DUTY_ID_OFFSET
] = channel
+ 1;
363 if (priv
->kind
== KRAKEN2023
) {
364 /* These require 1s in the next one or two slots after SET_DUTY_ID_OFFSET */
365 fixed_duty_cmd
[SET_DUTY_ID_OFFSET
+ 1] = 1;
366 if (channel
== 1) /* Fan */
367 fixed_duty_cmd
[SET_DUTY_ID_OFFSET
+ 2] = 1;
370 /* Copy curve to command */
371 memcpy(fixed_duty_cmd
+ SET_CURVE_DUTY_CMD_HEADER_LENGTH
, curve_array
, CUSTOM_CURVE_POINTS
);
373 ret
= kraken3_write_expanded(priv
, fixed_duty_cmd
, SET_CURVE_DUTY_CMD_LENGTH
);
377 static int kraken3_write_fixed_duty(struct kraken3_data
*priv
, long val
, int channel
)
379 u8 fixed_curve_points
[CUSTOM_CURVE_POINTS
];
380 int ret
, percent_val
, i
;
382 percent_val
= kraken3_pwm_to_percent(val
, channel
);
387 * The devices can only control the duty through a curve.
388 * Since we're setting a fixed duty here, fill the whole curve
389 * (ranging from 20C to 59C) with the same duty, except for
390 * the last point, the critical temperature, where it's maxed
394 /* Fill the custom curve with the fixed value we're setting */
395 for (i
= 0; i
< CUSTOM_CURVE_POINTS
- 1; i
++)
396 fixed_curve_points
[i
] = percent_val
;
398 /* Force duty to 100% at critical temp */
399 fixed_curve_points
[CUSTOM_CURVE_POINTS
- 1] = 100;
401 /* Write the fixed duty curve to the device */
402 ret
= kraken3_write_curve(priv
, fixed_curve_points
, channel
);
406 static int kraken3_write(struct device
*dev
, enum hwmon_sensor_types type
, u32 attr
, int channel
,
409 struct kraken3_data
*priv
= dev_get_drvdata(dev
);
415 case hwmon_pwm_input
:
416 /* Remember the last set fixed duty for channel */
417 priv
->channel_info
[channel
].fixed_duty
= val
;
419 if (priv
->channel_info
[channel
].mode
== manual
) {
420 ret
= kraken3_write_fixed_duty(priv
, val
, channel
);
425 * Lock onto this value and report it until next interrupt status
426 * report is received, so userspace tools can continue to work.
428 priv
->channel_info
[channel
].reported_duty
= val
;
431 case hwmon_pwm_enable
:
432 if (val
< 0 || val
> 2)
437 /* Set channel to 100%, direct duty value */
438 ret
= kraken3_write_fixed_duty(priv
, 255, channel
);
442 /* We don't control anything anymore */
443 priv
->channel_info
[channel
].mode
= off
;
446 /* Apply the last known direct duty value */
448 kraken3_write_fixed_duty(priv
,
449 priv
->channel_info
[channel
].fixed_duty
,
454 priv
->channel_info
[channel
].mode
= manual
;
457 /* Apply the curve and note as enabled */
459 kraken3_write_curve(priv
,
460 priv
->channel_info
[channel
].pwm_points
,
465 priv
->channel_info
[channel
].mode
= curve
;
482 static ssize_t
kraken3_fan_curve_pwm_store(struct device
*dev
, struct device_attribute
*attr
,
483 const char *buf
, size_t count
)
485 struct sensor_device_attribute_2
*dev_attr
= to_sensor_dev_attr_2(attr
);
486 struct kraken3_data
*priv
= dev_get_drvdata(dev
);
490 if (kstrtol(buf
, 10, &val
) < 0)
493 val
= kraken3_pwm_to_percent(val
, dev_attr
->nr
);
497 priv
->channel_info
[dev_attr
->nr
].pwm_points
[dev_attr
->index
] = val
;
499 if (priv
->channel_info
[dev_attr
->nr
].mode
== curve
) {
500 /* Apply the curve */
502 kraken3_write_curve(priv
,
503 priv
->channel_info
[dev_attr
->nr
].pwm_points
, dev_attr
->nr
);
511 static umode_t
kraken3_curve_props_are_visible(struct kobject
*kobj
, struct attribute
*attr
,
514 struct device
*dev
= kobj_to_dev(kobj
);
515 struct kraken3_data
*priv
= dev_get_drvdata(dev
);
517 /* X53 does not have a fan */
518 if (index
>= CUSTOM_CURVE_POINTS
&& priv
->kind
== X53
)
524 /* Custom pump curve from 20C to 59C (critical temp) */
525 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point1_pwm
, kraken3_fan_curve_pwm
, 0, 0);
526 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point2_pwm
, kraken3_fan_curve_pwm
, 0, 1);
527 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point3_pwm
, kraken3_fan_curve_pwm
, 0, 2);
528 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point4_pwm
, kraken3_fan_curve_pwm
, 0, 3);
529 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point5_pwm
, kraken3_fan_curve_pwm
, 0, 4);
530 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point6_pwm
, kraken3_fan_curve_pwm
, 0, 5);
531 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point7_pwm
, kraken3_fan_curve_pwm
, 0, 6);
532 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point8_pwm
, kraken3_fan_curve_pwm
, 0, 7);
533 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point9_pwm
, kraken3_fan_curve_pwm
, 0, 8);
534 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point10_pwm
, kraken3_fan_curve_pwm
, 0, 9);
535 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point11_pwm
, kraken3_fan_curve_pwm
, 0, 10);
536 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point12_pwm
, kraken3_fan_curve_pwm
, 0, 11);
537 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point13_pwm
, kraken3_fan_curve_pwm
, 0, 12);
538 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point14_pwm
, kraken3_fan_curve_pwm
, 0, 13);
539 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point15_pwm
, kraken3_fan_curve_pwm
, 0, 14);
540 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point16_pwm
, kraken3_fan_curve_pwm
, 0, 15);
541 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point17_pwm
, kraken3_fan_curve_pwm
, 0, 16);
542 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point18_pwm
, kraken3_fan_curve_pwm
, 0, 17);
543 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point19_pwm
, kraken3_fan_curve_pwm
, 0, 18);
544 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point20_pwm
, kraken3_fan_curve_pwm
, 0, 19);
545 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point21_pwm
, kraken3_fan_curve_pwm
, 0, 20);
546 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point22_pwm
, kraken3_fan_curve_pwm
, 0, 21);
547 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point23_pwm
, kraken3_fan_curve_pwm
, 0, 22);
548 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point24_pwm
, kraken3_fan_curve_pwm
, 0, 23);
549 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point25_pwm
, kraken3_fan_curve_pwm
, 0, 24);
550 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point26_pwm
, kraken3_fan_curve_pwm
, 0, 25);
551 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point27_pwm
, kraken3_fan_curve_pwm
, 0, 26);
552 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point28_pwm
, kraken3_fan_curve_pwm
, 0, 27);
553 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point29_pwm
, kraken3_fan_curve_pwm
, 0, 28);
554 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point30_pwm
, kraken3_fan_curve_pwm
, 0, 29);
555 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point31_pwm
, kraken3_fan_curve_pwm
, 0, 30);
556 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point32_pwm
, kraken3_fan_curve_pwm
, 0, 31);
557 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point33_pwm
, kraken3_fan_curve_pwm
, 0, 32);
558 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point34_pwm
, kraken3_fan_curve_pwm
, 0, 33);
559 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point35_pwm
, kraken3_fan_curve_pwm
, 0, 34);
560 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point36_pwm
, kraken3_fan_curve_pwm
, 0, 35);
561 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point37_pwm
, kraken3_fan_curve_pwm
, 0, 36);
562 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point38_pwm
, kraken3_fan_curve_pwm
, 0, 37);
563 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point39_pwm
, kraken3_fan_curve_pwm
, 0, 38);
564 static SENSOR_DEVICE_ATTR_2_WO(temp1_auto_point40_pwm
, kraken3_fan_curve_pwm
, 0, 39);
566 /* Custom fan curve from 20C to 59C (critical temp) */
567 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point1_pwm
, kraken3_fan_curve_pwm
, 1, 0);
568 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point2_pwm
, kraken3_fan_curve_pwm
, 1, 1);
569 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point3_pwm
, kraken3_fan_curve_pwm
, 1, 2);
570 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point4_pwm
, kraken3_fan_curve_pwm
, 1, 3);
571 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point5_pwm
, kraken3_fan_curve_pwm
, 1, 4);
572 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point6_pwm
, kraken3_fan_curve_pwm
, 1, 5);
573 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point7_pwm
, kraken3_fan_curve_pwm
, 1, 6);
574 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point8_pwm
, kraken3_fan_curve_pwm
, 1, 7);
575 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point9_pwm
, kraken3_fan_curve_pwm
, 1, 8);
576 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point10_pwm
, kraken3_fan_curve_pwm
, 1, 9);
577 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point11_pwm
, kraken3_fan_curve_pwm
, 1, 10);
578 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point12_pwm
, kraken3_fan_curve_pwm
, 1, 11);
579 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point13_pwm
, kraken3_fan_curve_pwm
, 1, 12);
580 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point14_pwm
, kraken3_fan_curve_pwm
, 1, 13);
581 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point15_pwm
, kraken3_fan_curve_pwm
, 1, 14);
582 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point16_pwm
, kraken3_fan_curve_pwm
, 1, 15);
583 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point17_pwm
, kraken3_fan_curve_pwm
, 1, 16);
584 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point18_pwm
, kraken3_fan_curve_pwm
, 1, 17);
585 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point19_pwm
, kraken3_fan_curve_pwm
, 1, 18);
586 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point20_pwm
, kraken3_fan_curve_pwm
, 1, 19);
587 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point21_pwm
, kraken3_fan_curve_pwm
, 1, 20);
588 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point22_pwm
, kraken3_fan_curve_pwm
, 1, 21);
589 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point23_pwm
, kraken3_fan_curve_pwm
, 1, 22);
590 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point24_pwm
, kraken3_fan_curve_pwm
, 1, 23);
591 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point25_pwm
, kraken3_fan_curve_pwm
, 1, 24);
592 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point26_pwm
, kraken3_fan_curve_pwm
, 1, 25);
593 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point27_pwm
, kraken3_fan_curve_pwm
, 1, 26);
594 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point28_pwm
, kraken3_fan_curve_pwm
, 1, 27);
595 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point29_pwm
, kraken3_fan_curve_pwm
, 1, 28);
596 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point30_pwm
, kraken3_fan_curve_pwm
, 1, 29);
597 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point31_pwm
, kraken3_fan_curve_pwm
, 1, 30);
598 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point32_pwm
, kraken3_fan_curve_pwm
, 1, 31);
599 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point33_pwm
, kraken3_fan_curve_pwm
, 1, 32);
600 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point34_pwm
, kraken3_fan_curve_pwm
, 1, 33);
601 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point35_pwm
, kraken3_fan_curve_pwm
, 1, 34);
602 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point36_pwm
, kraken3_fan_curve_pwm
, 1, 35);
603 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point37_pwm
, kraken3_fan_curve_pwm
, 1, 36);
604 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point38_pwm
, kraken3_fan_curve_pwm
, 1, 37);
605 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point39_pwm
, kraken3_fan_curve_pwm
, 1, 38);
606 static SENSOR_DEVICE_ATTR_2_WO(temp2_auto_point40_pwm
, kraken3_fan_curve_pwm
, 1, 39);
608 static struct attribute
*kraken3_curve_attrs
[] = {
609 /* Pump control curve */
610 &sensor_dev_attr_temp1_auto_point1_pwm
.dev_attr
.attr
,
611 &sensor_dev_attr_temp1_auto_point2_pwm
.dev_attr
.attr
,
612 &sensor_dev_attr_temp1_auto_point3_pwm
.dev_attr
.attr
,
613 &sensor_dev_attr_temp1_auto_point4_pwm
.dev_attr
.attr
,
614 &sensor_dev_attr_temp1_auto_point5_pwm
.dev_attr
.attr
,
615 &sensor_dev_attr_temp1_auto_point6_pwm
.dev_attr
.attr
,
616 &sensor_dev_attr_temp1_auto_point7_pwm
.dev_attr
.attr
,
617 &sensor_dev_attr_temp1_auto_point8_pwm
.dev_attr
.attr
,
618 &sensor_dev_attr_temp1_auto_point9_pwm
.dev_attr
.attr
,
619 &sensor_dev_attr_temp1_auto_point10_pwm
.dev_attr
.attr
,
620 &sensor_dev_attr_temp1_auto_point11_pwm
.dev_attr
.attr
,
621 &sensor_dev_attr_temp1_auto_point12_pwm
.dev_attr
.attr
,
622 &sensor_dev_attr_temp1_auto_point13_pwm
.dev_attr
.attr
,
623 &sensor_dev_attr_temp1_auto_point14_pwm
.dev_attr
.attr
,
624 &sensor_dev_attr_temp1_auto_point15_pwm
.dev_attr
.attr
,
625 &sensor_dev_attr_temp1_auto_point16_pwm
.dev_attr
.attr
,
626 &sensor_dev_attr_temp1_auto_point17_pwm
.dev_attr
.attr
,
627 &sensor_dev_attr_temp1_auto_point18_pwm
.dev_attr
.attr
,
628 &sensor_dev_attr_temp1_auto_point19_pwm
.dev_attr
.attr
,
629 &sensor_dev_attr_temp1_auto_point20_pwm
.dev_attr
.attr
,
630 &sensor_dev_attr_temp1_auto_point21_pwm
.dev_attr
.attr
,
631 &sensor_dev_attr_temp1_auto_point22_pwm
.dev_attr
.attr
,
632 &sensor_dev_attr_temp1_auto_point23_pwm
.dev_attr
.attr
,
633 &sensor_dev_attr_temp1_auto_point24_pwm
.dev_attr
.attr
,
634 &sensor_dev_attr_temp1_auto_point25_pwm
.dev_attr
.attr
,
635 &sensor_dev_attr_temp1_auto_point26_pwm
.dev_attr
.attr
,
636 &sensor_dev_attr_temp1_auto_point27_pwm
.dev_attr
.attr
,
637 &sensor_dev_attr_temp1_auto_point28_pwm
.dev_attr
.attr
,
638 &sensor_dev_attr_temp1_auto_point29_pwm
.dev_attr
.attr
,
639 &sensor_dev_attr_temp1_auto_point30_pwm
.dev_attr
.attr
,
640 &sensor_dev_attr_temp1_auto_point31_pwm
.dev_attr
.attr
,
641 &sensor_dev_attr_temp1_auto_point32_pwm
.dev_attr
.attr
,
642 &sensor_dev_attr_temp1_auto_point33_pwm
.dev_attr
.attr
,
643 &sensor_dev_attr_temp1_auto_point34_pwm
.dev_attr
.attr
,
644 &sensor_dev_attr_temp1_auto_point35_pwm
.dev_attr
.attr
,
645 &sensor_dev_attr_temp1_auto_point36_pwm
.dev_attr
.attr
,
646 &sensor_dev_attr_temp1_auto_point37_pwm
.dev_attr
.attr
,
647 &sensor_dev_attr_temp1_auto_point38_pwm
.dev_attr
.attr
,
648 &sensor_dev_attr_temp1_auto_point39_pwm
.dev_attr
.attr
,
649 &sensor_dev_attr_temp1_auto_point40_pwm
.dev_attr
.attr
,
650 /* Fan control curve (Z53 only) */
651 &sensor_dev_attr_temp2_auto_point1_pwm
.dev_attr
.attr
,
652 &sensor_dev_attr_temp2_auto_point2_pwm
.dev_attr
.attr
,
653 &sensor_dev_attr_temp2_auto_point3_pwm
.dev_attr
.attr
,
654 &sensor_dev_attr_temp2_auto_point4_pwm
.dev_attr
.attr
,
655 &sensor_dev_attr_temp2_auto_point5_pwm
.dev_attr
.attr
,
656 &sensor_dev_attr_temp2_auto_point6_pwm
.dev_attr
.attr
,
657 &sensor_dev_attr_temp2_auto_point7_pwm
.dev_attr
.attr
,
658 &sensor_dev_attr_temp2_auto_point8_pwm
.dev_attr
.attr
,
659 &sensor_dev_attr_temp2_auto_point9_pwm
.dev_attr
.attr
,
660 &sensor_dev_attr_temp2_auto_point10_pwm
.dev_attr
.attr
,
661 &sensor_dev_attr_temp2_auto_point11_pwm
.dev_attr
.attr
,
662 &sensor_dev_attr_temp2_auto_point12_pwm
.dev_attr
.attr
,
663 &sensor_dev_attr_temp2_auto_point13_pwm
.dev_attr
.attr
,
664 &sensor_dev_attr_temp2_auto_point14_pwm
.dev_attr
.attr
,
665 &sensor_dev_attr_temp2_auto_point15_pwm
.dev_attr
.attr
,
666 &sensor_dev_attr_temp2_auto_point16_pwm
.dev_attr
.attr
,
667 &sensor_dev_attr_temp2_auto_point17_pwm
.dev_attr
.attr
,
668 &sensor_dev_attr_temp2_auto_point18_pwm
.dev_attr
.attr
,
669 &sensor_dev_attr_temp2_auto_point19_pwm
.dev_attr
.attr
,
670 &sensor_dev_attr_temp2_auto_point20_pwm
.dev_attr
.attr
,
671 &sensor_dev_attr_temp2_auto_point21_pwm
.dev_attr
.attr
,
672 &sensor_dev_attr_temp2_auto_point22_pwm
.dev_attr
.attr
,
673 &sensor_dev_attr_temp2_auto_point23_pwm
.dev_attr
.attr
,
674 &sensor_dev_attr_temp2_auto_point24_pwm
.dev_attr
.attr
,
675 &sensor_dev_attr_temp2_auto_point25_pwm
.dev_attr
.attr
,
676 &sensor_dev_attr_temp2_auto_point26_pwm
.dev_attr
.attr
,
677 &sensor_dev_attr_temp2_auto_point27_pwm
.dev_attr
.attr
,
678 &sensor_dev_attr_temp2_auto_point28_pwm
.dev_attr
.attr
,
679 &sensor_dev_attr_temp2_auto_point29_pwm
.dev_attr
.attr
,
680 &sensor_dev_attr_temp2_auto_point30_pwm
.dev_attr
.attr
,
681 &sensor_dev_attr_temp2_auto_point31_pwm
.dev_attr
.attr
,
682 &sensor_dev_attr_temp2_auto_point32_pwm
.dev_attr
.attr
,
683 &sensor_dev_attr_temp2_auto_point33_pwm
.dev_attr
.attr
,
684 &sensor_dev_attr_temp2_auto_point34_pwm
.dev_attr
.attr
,
685 &sensor_dev_attr_temp2_auto_point35_pwm
.dev_attr
.attr
,
686 &sensor_dev_attr_temp2_auto_point36_pwm
.dev_attr
.attr
,
687 &sensor_dev_attr_temp2_auto_point37_pwm
.dev_attr
.attr
,
688 &sensor_dev_attr_temp2_auto_point38_pwm
.dev_attr
.attr
,
689 &sensor_dev_attr_temp2_auto_point39_pwm
.dev_attr
.attr
,
690 &sensor_dev_attr_temp2_auto_point40_pwm
.dev_attr
.attr
,
694 static const struct attribute_group kraken3_curves_group
= {
695 .attrs
= kraken3_curve_attrs
,
696 .is_visible
= kraken3_curve_props_are_visible
699 static const struct attribute_group
*kraken3_groups
[] = {
700 &kraken3_curves_group
,
704 static const struct hwmon_ops kraken3_hwmon_ops
= {
705 .is_visible
= kraken3_is_visible
,
706 .read
= kraken3_read
,
707 .read_string
= kraken3_read_string
,
708 .write
= kraken3_write
711 static const struct hwmon_channel_info
*kraken3_info
[] = {
712 HWMON_CHANNEL_INFO(temp
,
713 HWMON_T_INPUT
| HWMON_T_LABEL
),
714 HWMON_CHANNEL_INFO(fan
,
715 HWMON_F_INPUT
| HWMON_F_LABEL
,
716 HWMON_F_INPUT
| HWMON_F_LABEL
,
717 HWMON_F_INPUT
| HWMON_F_LABEL
,
718 HWMON_F_INPUT
| HWMON_F_LABEL
),
719 HWMON_CHANNEL_INFO(pwm
,
720 HWMON_PWM_INPUT
| HWMON_PWM_ENABLE
,
721 HWMON_PWM_INPUT
| HWMON_PWM_ENABLE
),
725 static const struct hwmon_chip_info kraken3_chip_info
= {
726 .ops
= &kraken3_hwmon_ops
,
727 .info
= kraken3_info
,
730 static int kraken3_raw_event(struct hid_device
*hdev
, struct hid_report
*report
, u8
*data
, int size
)
732 struct kraken3_data
*priv
= hid_get_drvdata(hdev
);
735 if (size
< MIN_REPORT_LENGTH
)
738 if (report
->id
== FIRMWARE_REPORT_ID
) {
739 /* Read firmware version */
740 for (i
= 0; i
< 3; i
++)
741 priv
->firmware_version
[i
] = data
[FIRMWARE_VERSION_OFFSET
+ i
];
743 if (!completion_done(&priv
->fw_version_processed
))
744 complete_all(&priv
->fw_version_processed
);
749 if (report
->id
!= STATUS_REPORT_ID
)
752 if (data
[TEMP_SENSOR_START_OFFSET
] == 0xff && data
[TEMP_SENSOR_END_OFFSET
] == 0xff) {
754 "firmware or device is possibly damaged (is SATA power connected?), not parsing reports\n");
757 * Mark first X-series device report as received,
758 * as well as all for Z-series, if faulty.
760 spin_lock(&priv
->status_completion_lock
);
761 if (priv
->kind
!= X53
|| !completion_done(&priv
->status_report_processed
)) {
762 priv
->is_device_faulty
= true;
763 complete_all(&priv
->status_report_processed
);
765 spin_unlock(&priv
->status_completion_lock
);
770 /* Received normal data */
771 priv
->is_device_faulty
= false;
773 /* Temperature and fan sensor readings */
774 priv
->temp_input
[0] =
775 data
[TEMP_SENSOR_START_OFFSET
] * 1000 + data
[TEMP_SENSOR_END_OFFSET
] * 100;
777 priv
->fan_input
[0] = get_unaligned_le16(data
+ PUMP_SPEED_OFFSET
);
778 priv
->channel_info
[0].reported_duty
= kraken3_percent_to_pwm(data
[PUMP_DUTY_OFFSET
]);
780 spin_lock(&priv
->status_completion_lock
);
781 if (priv
->kind
== X53
&& !completion_done(&priv
->status_report_processed
)) {
782 /* Mark first X-series device report as received */
783 complete_all(&priv
->status_report_processed
);
784 } else if (priv
->kind
== Z53
|| priv
->kind
== KRAKEN2023
) {
785 /* Additional readings for Z53 and KRAKEN2023 */
786 priv
->fan_input
[1] = get_unaligned_le16(data
+ Z53_FAN_SPEED_OFFSET
);
787 priv
->channel_info
[1].reported_duty
=
788 kraken3_percent_to_pwm(data
[Z53_FAN_DUTY_OFFSET
]);
790 if (!completion_done(&priv
->status_report_processed
))
791 complete_all(&priv
->status_report_processed
);
793 spin_unlock(&priv
->status_completion_lock
);
795 priv
->updated
= jiffies
;
800 static int kraken3_init_device(struct hid_device
*hdev
)
802 struct kraken3_data
*priv
= hid_get_drvdata(hdev
);
805 /* Set the polling interval */
806 ret
= kraken3_write_expanded(priv
, set_interval_cmd
, SET_INTERVAL_CMD_LENGTH
);
810 /* Finalize the init process */
811 ret
= kraken3_write_expanded(priv
, finish_init_cmd
, FINISH_INIT_CMD_LENGTH
);
818 static int kraken3_get_fw_ver(struct hid_device
*hdev
)
820 struct kraken3_data
*priv
= hid_get_drvdata(hdev
);
823 ret
= kraken3_write_expanded(priv
, get_fw_version_cmd
, GET_FW_VERSION_CMD_LENGTH
);
827 ret
= wait_for_completion_interruptible_timeout(&priv
->fw_version_processed
,
828 msecs_to_jiffies(STATUS_VALIDITY
));
837 static int __maybe_unused
kraken3_reset_resume(struct hid_device
*hdev
)
841 ret
= kraken3_init_device(hdev
);
843 hid_err(hdev
, "req init (reset_resume) failed with %d\n", ret
);
848 static int firmware_version_show(struct seq_file
*seqf
, void *unused
)
850 struct kraken3_data
*priv
= seqf
->private;
852 seq_printf(seqf
, "%u.%u.%u\n", priv
->firmware_version
[0], priv
->firmware_version
[1],
853 priv
->firmware_version
[2]);
857 DEFINE_SHOW_ATTRIBUTE(firmware_version
);
859 static void kraken3_debugfs_init(struct kraken3_data
*priv
, const char *device_name
)
863 if (!priv
->firmware_version
[0])
864 return; /* Nothing to display in debugfs */
866 scnprintf(name
, sizeof(name
), "%s_%s-%s", DRIVER_NAME
, device_name
,
867 dev_name(&priv
->hdev
->dev
));
869 priv
->debugfs
= debugfs_create_dir(name
, NULL
);
870 debugfs_create_file("firmware_version", 0444, priv
->debugfs
, priv
, &firmware_version_fops
);
873 static int kraken3_probe(struct hid_device
*hdev
, const struct hid_device_id
*id
)
875 struct kraken3_data
*priv
;
876 const char *device_name
;
879 priv
= devm_kzalloc(&hdev
->dev
, sizeof(*priv
), GFP_KERNEL
);
884 hid_set_drvdata(hdev
, priv
);
887 * Initialize ->updated to STATUS_VALIDITY seconds in the past, making
888 * the initial empty data invalid for kraken3_read without the need for
889 * a special case there.
891 priv
->updated
= jiffies
- msecs_to_jiffies(STATUS_VALIDITY
);
893 ret
= hid_parse(hdev
);
895 hid_err(hdev
, "hid parse failed with %d\n", ret
);
899 /* Enable hidraw so existing user-space tools can continue to work */
900 ret
= hid_hw_start(hdev
, HID_CONNECT_HIDRAW
);
902 hid_err(hdev
, "hid hw start failed with %d\n", ret
);
906 ret
= hid_hw_open(hdev
);
908 hid_err(hdev
, "hid hw open failed with %d\n", ret
);
912 switch (hdev
->product
) {
913 case USB_PRODUCT_ID_X53
:
914 case USB_PRODUCT_ID_X53_SECOND
:
918 case USB_PRODUCT_ID_Z53
:
922 case USB_PRODUCT_ID_KRAKEN2023
:
923 priv
->kind
= KRAKEN2023
;
924 device_name
= "kraken2023";
926 case USB_PRODUCT_ID_KRAKEN2023_ELITE
:
927 priv
->kind
= KRAKEN2023
;
928 device_name
= "kraken2023elite";
935 priv
->buffer
= devm_kzalloc(&hdev
->dev
, MAX_REPORT_LENGTH
, GFP_KERNEL
);
941 mutex_init(&priv
->buffer_lock
);
942 mutex_init(&priv
->z53_status_request_lock
);
943 init_completion(&priv
->fw_version_processed
);
944 init_completion(&priv
->status_report_processed
);
945 spin_lock_init(&priv
->status_completion_lock
);
947 hid_device_io_start(hdev
);
948 ret
= kraken3_init_device(hdev
);
950 hid_err(hdev
, "device init failed with %d\n", ret
);
954 ret
= kraken3_get_fw_ver(hdev
);
956 hid_warn(hdev
, "fw version request failed with %d\n", ret
);
958 priv
->hwmon_dev
= hwmon_device_register_with_info(&hdev
->dev
, device_name
, priv
,
959 &kraken3_chip_info
, kraken3_groups
);
960 if (IS_ERR(priv
->hwmon_dev
)) {
961 ret
= PTR_ERR(priv
->hwmon_dev
);
962 hid_err(hdev
, "hwmon registration failed with %d\n", ret
);
966 kraken3_debugfs_init(priv
, device_name
);
977 static void kraken3_remove(struct hid_device
*hdev
)
979 struct kraken3_data
*priv
= hid_get_drvdata(hdev
);
981 debugfs_remove_recursive(priv
->debugfs
);
982 hwmon_device_unregister(priv
->hwmon_dev
);
988 static const struct hid_device_id kraken3_table
[] = {
989 /* NZXT Kraken X53/X63/X73 have two possible product IDs */
990 { HID_USB_DEVICE(USB_VENDOR_ID_NZXT
, USB_PRODUCT_ID_X53
) },
991 { HID_USB_DEVICE(USB_VENDOR_ID_NZXT
, USB_PRODUCT_ID_X53_SECOND
) },
992 { HID_USB_DEVICE(USB_VENDOR_ID_NZXT
, USB_PRODUCT_ID_Z53
) },
993 { HID_USB_DEVICE(USB_VENDOR_ID_NZXT
, USB_PRODUCT_ID_KRAKEN2023
) },
994 { HID_USB_DEVICE(USB_VENDOR_ID_NZXT
, USB_PRODUCT_ID_KRAKEN2023_ELITE
) },
998 MODULE_DEVICE_TABLE(hid
, kraken3_table
);
1000 static struct hid_driver kraken3_driver
= {
1001 .name
= DRIVER_NAME
,
1002 .id_table
= kraken3_table
,
1003 .probe
= kraken3_probe
,
1004 .remove
= kraken3_remove
,
1005 .raw_event
= kraken3_raw_event
,
1007 .reset_resume
= kraken3_reset_resume
,
1011 static int __init
kraken3_init(void)
1013 return hid_register_driver(&kraken3_driver
);
1016 static void __exit
kraken3_exit(void)
1018 hid_unregister_driver(&kraken3_driver
);
1021 /* When compiled into the kernel, initialize after the HID bus */
1022 late_initcall(kraken3_init
);
1023 module_exit(kraken3_exit
);
1025 MODULE_LICENSE("GPL");
1026 MODULE_AUTHOR("Jonas Malaco <jonas@protocubo.io>");
1027 MODULE_AUTHOR("Aleksa Savic <savicaleksa83@gmail.com>");
1028 MODULE_DESCRIPTION("Hwmon driver for NZXT Kraken X53/X63/X73, Z53/Z63/Z73 coolers");