hwmon: (aquacomputer_d5next) Add structure for fan layout
[linux-block.git] / drivers / hwmon / aquacomputer_d5next.c
CommitLineData
0e35f63f
AS
1// SPDX-License-Identifier: GPL-2.0+
2/*
cdbe34da 3 * hwmon driver for Aquacomputer devices (D5 Next, Farbwerk, Farbwerk 360, Octo,
aed80bb9 4 * Quadro, High Flow Next)
0e35f63f 5 *
2fd3eec1
AS
6 * Aquacomputer devices send HID reports (with ID 0x01) every second to report
7 * sensor values.
0e35f63f
AS
8 *
9 * Copyright 2021 Aleksa Savic <savicaleksa83@gmail.com>
229b159c 10 * Copyright 2022 Jack Doan <me@jackdoan.com>
0e35f63f
AS
11 */
12
752b9279 13#include <linux/crc16.h>
0e35f63f
AS
14#include <linux/debugfs.h>
15#include <linux/hid.h>
16#include <linux/hwmon.h>
17#include <linux/jiffies.h>
18#include <linux/module.h>
752b9279 19#include <linux/mutex.h>
0e35f63f 20#include <linux/seq_file.h>
2fd3eec1 21#include <asm/unaligned.h>
0e35f63f 22
2fd3eec1 23#define USB_VENDOR_ID_AQUACOMPUTER 0x0c70
229b159c 24#define USB_PRODUCT_ID_FARBWERK 0xf00a
cdbe34da 25#define USB_PRODUCT_ID_QUADRO 0xf00d
2fd3eec1
AS
26#define USB_PRODUCT_ID_D5NEXT 0xf00e
27#define USB_PRODUCT_ID_FARBWERK360 0xf010
752b9279 28#define USB_PRODUCT_ID_OCTO 0xf011
aed80bb9 29#define USB_PRODUCT_ID_HIGHFLOWNEXT 0xf012
0e35f63f 30
aed80bb9 31enum kinds { d5next, farbwerk, farbwerk360, octo, quadro, highflownext };
0e35f63f 32
2fd3eec1
AS
33static const char *const aqc_device_names[] = {
34 [d5next] = "d5next",
229b159c 35 [farbwerk] = "farbwerk",
752b9279 36 [farbwerk360] = "farbwerk360",
cdbe34da 37 [octo] = "octo",
aed80bb9
AS
38 [quadro] = "quadro",
39 [highflownext] = "highflownext"
2fd3eec1 40};
0e35f63f 41
2fd3eec1
AS
42#define DRIVER_NAME "aquacomputer_d5next"
43
44#define STATUS_REPORT_ID 0x01
45#define STATUS_UPDATE_INTERVAL (2 * HZ) /* In seconds */
46#define SERIAL_FIRST_PART 3
47#define SERIAL_SECOND_PART 5
48#define FIRMWARE_VERSION 13
49
752b9279
AS
50#define CTRL_REPORT_ID 0x03
51
52/* The HID report that the official software always sends
53 * after writing values, currently same for all devices
54 */
55#define SECONDARY_CTRL_REPORT_ID 0x02
56#define SECONDARY_CTRL_REPORT_SIZE 0x0B
57
58static u8 secondary_ctrl_report[] = {
59 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x34, 0xC6
60};
61
d5d896b8 62/* Sensor sizes and offsets for all Aquacomputer devices */
8bcb02bd 63#define AQC_SENSOR_SIZE 0x02
654c9735
AS
64#define AQC_TEMP_SENSOR_DISCONNECTED 0x7FFF
65#define AQC_FAN_PERCENT_OFFSET 0x00
66#define AQC_FAN_VOLTAGE_OFFSET 0x02
67#define AQC_FAN_CURRENT_OFFSET 0x04
68#define AQC_FAN_POWER_OFFSET 0x06
69#define AQC_FAN_SPEED_OFFSET 0x08
0e35f63f 70
d5d896b8 71/* Specs of the D5 Next pump */
654c9735
AS
72#define D5NEXT_NUM_FANS 2
73#define D5NEXT_NUM_SENSORS 1
e2769f5e 74#define D5NEXT_NUM_VIRTUAL_SENSORS 8
d5d896b8
AS
75#define D5NEXT_CTRL_REPORT_SIZE 0x329
76
77/* Sensor report offsets for the D5 Next pump */
78#define D5NEXT_POWER_CYCLES 0x18
79#define D5NEXT_COOLANT_TEMP 0x57
654c9735
AS
80#define D5NEXT_PUMP_OFFSET 0x6c
81#define D5NEXT_FAN_OFFSET 0x5f
82#define D5NEXT_5V_VOLTAGE 0x39
f4caa262 83#define D5NEXT_12V_VOLTAGE 0x37
d5d896b8 84#define D5NEXT_VIRTUAL_SENSORS_START 0x3f
654c9735 85static u8 d5next_sensor_fan_offsets[] = { D5NEXT_PUMP_OFFSET, D5NEXT_FAN_OFFSET };
0e35f63f 86
d5d896b8
AS
87/* Control report offsets for the D5 Next pump */
88#define D5NEXT_TEMP_CTRL_OFFSET 0x2D /* Temperature sensor offsets location */
89static u16 d5next_ctrl_fan_offsets[] = { 0x97, 0x42 }; /* Pump and fan speed (from 0-100%) */
09e89309 90
d5d896b8 91/* Spec and sensor report offset for the Farbwerk RGB controller */
229b159c
JD
92#define FARBWERK_NUM_SENSORS 4
93#define FARBWERK_SENSOR_START 0x2f
229b159c 94
d5d896b8 95/* Specs of the Farbwerk 360 RGB controller */
e2769f5e 96#define FARBWERK360_NUM_SENSORS 4
e2769f5e 97#define FARBWERK360_NUM_VIRTUAL_SENSORS 16
662d20b3 98#define FARBWERK360_CTRL_REPORT_SIZE 0x682
d5d896b8
AS
99
100/* Sensor report offsets for the Farbwerk 360 */
101#define FARBWERK360_SENSOR_START 0x32
102#define FARBWERK360_VIRTUAL_SENSORS_START 0x3a
103
104/* Control report offsets for the Farbwerk 360 */
662d20b3 105#define FARBWERK360_TEMP_CTRL_OFFSET 0x8
0e35f63f 106
d5d896b8 107/* Specs of the Octo fan controller */
752b9279 108#define OCTO_NUM_FANS 8
752b9279 109#define OCTO_NUM_SENSORS 4
e2769f5e 110#define OCTO_NUM_VIRTUAL_SENSORS 16
654c9735 111#define OCTO_CTRL_REPORT_SIZE 0x65F
d5d896b8
AS
112
113/* Sensor report offsets for the Octo */
114#define OCTO_POWER_CYCLES 0x18
115#define OCTO_SENSOR_START 0x3D
116#define OCTO_VIRTUAL_SENSORS_START 0x45
654c9735 117static u8 octo_sensor_fan_offsets[] = { 0x7D, 0x8A, 0x97, 0xA4, 0xB1, 0xBE, 0xCB, 0xD8 };
752b9279 118
d5d896b8
AS
119/* Control report offsets for the Octo */
120#define OCTO_TEMP_CTRL_OFFSET 0xA
121/* Fan speed offsets (0-100%) */
752b9279
AS
122static u16 octo_ctrl_fan_offsets[] = { 0x5B, 0xB0, 0x105, 0x15A, 0x1AF, 0x204, 0x259, 0x2AE };
123
d5d896b8 124/* Specs of Quadro fan controller */
cdbe34da
AS
125#define QUADRO_NUM_FANS 4
126#define QUADRO_NUM_SENSORS 4
e2769f5e 127#define QUADRO_NUM_VIRTUAL_SENSORS 16
a2ba7ee2 128#define QUADRO_NUM_FLOW_SENSORS 1
cdbe34da 129#define QUADRO_CTRL_REPORT_SIZE 0x3c1
d5d896b8
AS
130
131/* Sensor report offsets for the Quadro */
132#define QUADRO_POWER_CYCLES 0x18
133#define QUADRO_SENSOR_START 0x34
134#define QUADRO_VIRTUAL_SENSORS_START 0x3c
cdbe34da
AS
135#define QUADRO_FLOW_SENSOR_OFFSET 0x6e
136static u8 quadro_sensor_fan_offsets[] = { 0x70, 0x7D, 0x8A, 0x97 };
137
d5d896b8
AS
138/* Control report offsets for the Quadro */
139#define QUADRO_TEMP_CTRL_OFFSET 0xA
6ff838f2 140#define QUADRO_FLOW_PULSES_CTRL_OFFSET 0x6
d5d896b8 141static u16 quadro_ctrl_fan_offsets[] = { 0x37, 0x8c, 0xe1, 0x136 }; /* Fan speed offsets (0-100%) */
cdbe34da 142
d5d896b8 143/* Specs of High Flow Next flow sensor */
aed80bb9 144#define HIGHFLOWNEXT_NUM_SENSORS 2
a2ba7ee2 145#define HIGHFLOWNEXT_NUM_FLOW_SENSORS 1
d5d896b8
AS
146
147/* Sensor report offsets for the High Flow Next */
aed80bb9
AS
148#define HIGHFLOWNEXT_SENSOR_START 85
149#define HIGHFLOWNEXT_FLOW 81
150#define HIGHFLOWNEXT_WATER_QUALITY 89
151#define HIGHFLOWNEXT_POWER 91
152#define HIGHFLOWNEXT_CONDUCTIVITY 95
153#define HIGHFLOWNEXT_5V_VOLTAGE 97
154#define HIGHFLOWNEXT_5V_VOLTAGE_USB 99
155
2fd3eec1 156/* Labels for D5 Next */
752b9279
AS
157static const char *const label_d5next_temp[] = {
158 "Coolant temp"
159};
0e35f63f 160
2fd3eec1
AS
161static const char *const label_d5next_speeds[] = {
162 "Pump speed",
163 "Fan speed"
164};
0e35f63f 165
2fd3eec1
AS
166static const char *const label_d5next_power[] = {
167 "Pump power",
168 "Fan power"
0e35f63f
AS
169};
170
2fd3eec1
AS
171static const char *const label_d5next_voltages[] = {
172 "Pump voltage",
173 "Fan voltage",
f4caa262
AS
174 "+5V voltage",
175 "+12V voltage"
0e35f63f
AS
176};
177
2fd3eec1
AS
178static const char *const label_d5next_current[] = {
179 "Pump current",
180 "Fan current"
0e35f63f
AS
181};
182
cdbe34da 183/* Labels for Farbwerk, Farbwerk 360 and Octo and Quadro temperature sensors */
2fd3eec1
AS
184static const char *const label_temp_sensors[] = {
185 "Sensor 1",
186 "Sensor 2",
187 "Sensor 3",
188 "Sensor 4"
0e35f63f
AS
189};
190
e2769f5e
AS
191static const char *const label_virtual_temp_sensors[] = {
192 "Virtual sensor 1",
193 "Virtual sensor 2",
194 "Virtual sensor 3",
195 "Virtual sensor 4",
196 "Virtual sensor 5",
197 "Virtual sensor 6",
198 "Virtual sensor 7",
199 "Virtual sensor 8",
200 "Virtual sensor 9",
201 "Virtual sensor 10",
202 "Virtual sensor 11",
203 "Virtual sensor 12",
204 "Virtual sensor 13",
205 "Virtual sensor 14",
206 "Virtual sensor 15",
207 "Virtual sensor 16",
208};
209
cdbe34da 210/* Labels for Octo and Quadro (except speed) */
752b9279
AS
211static const char *const label_fan_speed[] = {
212 "Fan 1 speed",
213 "Fan 2 speed",
214 "Fan 3 speed",
215 "Fan 4 speed",
216 "Fan 5 speed",
217 "Fan 6 speed",
218 "Fan 7 speed",
219 "Fan 8 speed"
220};
221
222static const char *const label_fan_power[] = {
223 "Fan 1 power",
224 "Fan 2 power",
225 "Fan 3 power",
226 "Fan 4 power",
227 "Fan 5 power",
228 "Fan 6 power",
229 "Fan 7 power",
230 "Fan 8 power"
231};
232
233static const char *const label_fan_voltage[] = {
234 "Fan 1 voltage",
235 "Fan 2 voltage",
236 "Fan 3 voltage",
237 "Fan 4 voltage",
238 "Fan 5 voltage",
239 "Fan 6 voltage",
240 "Fan 7 voltage",
241 "Fan 8 voltage"
242};
243
244static const char *const label_fan_current[] = {
245 "Fan 1 current",
246 "Fan 2 current",
247 "Fan 3 current",
248 "Fan 4 current",
249 "Fan 5 current",
250 "Fan 6 current",
251 "Fan 7 current",
252 "Fan 8 current"
253};
254
cdbe34da
AS
255/* Labels for Quadro fan speeds */
256static const char *const label_quadro_speeds[] = {
257 "Fan 1 speed",
258 "Fan 2 speed",
259 "Fan 3 speed",
260 "Fan 4 speed",
261 "Flow speed [dL/h]"
262};
263
aed80bb9
AS
264/* Labels for High Flow Next */
265static const char *const label_highflownext_temp_sensors[] = {
266 "Coolant temp",
267 "External sensor"
268};
269
270static const char *const label_highflownext_fan_speed[] = {
271 "Flow [dL/h]",
272 "Water quality [%]",
273 "Conductivity [nS/cm]",
274};
275
276static const char *const label_highflownext_power[] = {
277 "Dissipated power",
278};
279
280static const char *const label_highflownext_voltage[] = {
281 "+5V voltage",
282 "+5V USB voltage"
283};
284
249c7521
LA
285struct aqc_fan_structure_offsets {
286 u8 voltage;
287 u8 curr;
288 u8 power;
289 u8 speed;
290};
291
292/* Fan structure offsets for all devices except Aquaero */
293static struct aqc_fan_structure_offsets aqc_general_fan_structure = {
294 .voltage = AQC_FAN_VOLTAGE_OFFSET,
295 .curr = AQC_FAN_CURRENT_OFFSET,
296 .power = AQC_FAN_POWER_OFFSET,
297 .speed = AQC_FAN_SPEED_OFFSET
298};
299
2fd3eec1 300struct aqc_data {
0e35f63f
AS
301 struct hid_device *hdev;
302 struct device *hwmon_dev;
303 struct dentry *debugfs;
752b9279 304 struct mutex mutex; /* Used for locking access when reading and writing PWM values */
2fd3eec1
AS
305 enum kinds kind;
306 const char *name;
307
752b9279
AS
308 int buffer_size;
309 u8 *buffer;
310 int checksum_start;
311 int checksum_length;
312 int checksum_offset;
313
654c9735
AS
314 int num_fans;
315 u8 *fan_sensor_offsets;
316 u16 *fan_ctrl_offsets;
317 int num_temp_sensors;
318 int temp_sensor_start_offset;
e2769f5e
AS
319 int num_virtual_temp_sensors;
320 int virtual_temp_sensor_start_offset;
662d20b3 321 u16 temp_ctrl_offset;
654c9735 322 u16 power_cycle_count_offset;
a2ba7ee2
LA
323 int num_flow_sensors;
324 u8 flow_sensors_start_offset;
6ff838f2 325 u8 flow_pulses_ctrl_offset;
249c7521 326 struct aqc_fan_structure_offsets *fan_structure;
654c9735 327
2fd3eec1
AS
328 /* General info, same across all devices */
329 u32 serial_number[2];
330 u16 firmware_version;
331
654c9735 332 /* How many times the device was powered on, if available */
2fd3eec1
AS
333 u32 power_cycles;
334
335 /* Sensor values */
e2769f5e 336 s32 temp_input[20]; /* Max 4 physical and 16 virtual */
752b9279
AS
337 u16 speed_input[8];
338 u32 power_input[8];
339 u16 voltage_input[8];
340 u16 current_input[8];
341
342 /* Label values */
343 const char *const *temp_label;
e2769f5e 344 const char *const *virtual_temp_label;
752b9279
AS
345 const char *const *speed_label;
346 const char *const *power_label;
347 const char *const *voltage_label;
348 const char *const *current_label;
2fd3eec1 349
0e35f63f
AS
350 unsigned long updated;
351};
352
752b9279
AS
353/* Converts from centi-percent */
354static int aqc_percent_to_pwm(u16 val)
355{
356 return DIV_ROUND_CLOSEST(val * 255, 100 * 100);
357}
358
359/* Converts to centi-percent */
360static int aqc_pwm_to_percent(long val)
361{
362 if (val < 0 || val > 255)
363 return -EINVAL;
364
365 return DIV_ROUND_CLOSEST(val * 100 * 100, 255);
366}
367
368/* Expects the mutex to be locked */
369static int aqc_get_ctrl_data(struct aqc_data *priv)
370{
371 int ret;
372
373 memset(priv->buffer, 0x00, priv->buffer_size);
374 ret = hid_hw_raw_request(priv->hdev, CTRL_REPORT_ID, priv->buffer, priv->buffer_size,
375 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
376 if (ret < 0)
377 ret = -ENODATA;
378
379 return ret;
380}
381
382/* Expects the mutex to be locked */
383static int aqc_send_ctrl_data(struct aqc_data *priv)
384{
385 int ret;
386 u16 checksum;
387
388 /* Init and xorout value for CRC-16/USB is 0xffff */
389 checksum = crc16(0xffff, priv->buffer + priv->checksum_start, priv->checksum_length);
390 checksum ^= 0xffff;
391
392 /* Place the new checksum at the end of the report */
393 put_unaligned_be16(checksum, priv->buffer + priv->checksum_offset);
394
395 /* Send the patched up report back to the device */
396 ret = hid_hw_raw_request(priv->hdev, CTRL_REPORT_ID, priv->buffer, priv->buffer_size,
397 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
398 if (ret < 0)
399 return ret;
400
401 /* The official software sends this report after every change, so do it here as well */
402 ret = hid_hw_raw_request(priv->hdev, SECONDARY_CTRL_REPORT_ID, secondary_ctrl_report,
403 SECONDARY_CTRL_REPORT_SIZE, HID_FEATURE_REPORT,
404 HID_REQ_SET_REPORT);
405 return ret;
406}
407
662d20b3
AS
408/* Refreshes the control buffer and stores value at offset in val */
409static int aqc_get_ctrl_val(struct aqc_data *priv, int offset, long *val)
752b9279
AS
410{
411 int ret;
412
413 mutex_lock(&priv->mutex);
414
415 ret = aqc_get_ctrl_data(priv);
416 if (ret < 0)
417 goto unlock_and_return;
418
662d20b3 419 *val = (s16)get_unaligned_be16(priv->buffer + offset);
752b9279
AS
420
421unlock_and_return:
422 mutex_unlock(&priv->mutex);
423 return ret;
424}
425
426static int aqc_set_ctrl_val(struct aqc_data *priv, int offset, long val)
427{
428 int ret;
429
430 mutex_lock(&priv->mutex);
431
432 ret = aqc_get_ctrl_data(priv);
433 if (ret < 0)
434 goto unlock_and_return;
435
662d20b3 436 put_unaligned_be16((s16)val, priv->buffer + offset);
752b9279
AS
437
438 ret = aqc_send_ctrl_data(priv);
439
440unlock_and_return:
441 mutex_unlock(&priv->mutex);
442 return ret;
443}
444
445static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, int channel)
0e35f63f 446{
2fd3eec1
AS
447 const struct aqc_data *priv = data;
448
449 switch (type) {
450 case hwmon_temp:
662d20b3
AS
451 if (channel < priv->num_temp_sensors) {
452 switch (attr) {
453 case hwmon_temp_label:
454 case hwmon_temp_input:
455 return 0444;
456 case hwmon_temp_offset:
457 if (priv->temp_ctrl_offset != 0)
458 return 0644;
459 break;
460 default:
461 break;
462 }
463 }
464
e2769f5e 465 if (channel < priv->num_temp_sensors + priv->num_virtual_temp_sensors)
662d20b3
AS
466 switch (attr) {
467 case hwmon_temp_label:
468 case hwmon_temp_input:
469 return 0444;
470 default:
471 break;
472 }
2fd3eec1 473 break;
752b9279 474 case hwmon_pwm:
654c9735 475 if (priv->fan_ctrl_offsets && channel < priv->num_fans) {
752b9279
AS
476 switch (attr) {
477 case hwmon_pwm_input:
478 return 0644;
479 default:
480 break;
481 }
752b9279
AS
482 }
483 break;
2fd3eec1 484 case hwmon_fan:
6ff838f2
AS
485 switch (attr) {
486 case hwmon_fan_input:
487 case hwmon_fan_label:
488 switch (priv->kind) {
489 case highflownext:
490 /* Special case to support flow sensor, water quality
491 * and conductivity
492 */
493 if (channel < 3)
494 return 0444;
495 break;
496 case quadro:
a2ba7ee2
LA
497 /* Special case to support flow sensors */
498 if (channel < priv->num_fans + priv->num_flow_sensors)
6ff838f2
AS
499 return 0444;
500 break;
501 default:
502 if (channel < priv->num_fans)
503 return 0444;
504 break;
505 }
aed80bb9 506 break;
6ff838f2
AS
507 case hwmon_fan_pulses:
508 /* Special case for Quadro flow sensor */
509 if (priv->kind == quadro && channel == priv->num_fans)
510 return 0644;
cdbe34da
AS
511 break;
512 default:
cdbe34da
AS
513 break;
514 }
515 break;
2fd3eec1 516 case hwmon_power:
aed80bb9
AS
517 switch (priv->kind) {
518 case highflownext:
519 /* Special case to support one power sensor */
520 if (channel == 0)
521 return 0444;
522 break;
523 default:
524 if (channel < priv->num_fans)
525 return 0444;
526 break;
527 }
528 break;
2fd3eec1 529 case hwmon_curr:
654c9735 530 if (channel < priv->num_fans)
752b9279 531 return 0444;
752b9279
AS
532 break;
533 case hwmon_in:
534 switch (priv->kind) {
535 case d5next:
f4caa262
AS
536 /* Special case to support +5V and +12V voltage sensors */
537 if (channel < priv->num_fans + 2)
752b9279
AS
538 return 0444;
539 break;
aed80bb9
AS
540 case highflownext:
541 /* Special case to support two voltage sensors */
542 if (channel < 2)
543 return 0444;
544 break;
2fd3eec1 545 default:
654c9735
AS
546 if (channel < priv->num_fans)
547 return 0444;
2fd3eec1
AS
548 break;
549 }
550 break;
551 default:
552 break;
553 }
554
555 return 0;
0e35f63f
AS
556}
557
2fd3eec1
AS
558static int aqc_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
559 int channel, long *val)
0e35f63f 560{
752b9279 561 int ret;
2fd3eec1 562 struct aqc_data *priv = dev_get_drvdata(dev);
0e35f63f 563
2fd3eec1 564 if (time_after(jiffies, priv->updated + STATUS_UPDATE_INTERVAL))
0e35f63f
AS
565 return -ENODATA;
566
567 switch (type) {
568 case hwmon_temp:
662d20b3
AS
569 switch (attr) {
570 case hwmon_temp_input:
571 if (priv->temp_input[channel] == -ENODATA)
572 return -ENODATA;
573
574 *val = priv->temp_input[channel];
575 break;
576 case hwmon_temp_offset:
577 ret =
578 aqc_get_ctrl_val(priv, priv->temp_ctrl_offset +
8bcb02bd 579 channel * AQC_SENSOR_SIZE, val);
662d20b3
AS
580 if (ret < 0)
581 return ret;
2fd3eec1 582
662d20b3
AS
583 *val *= 10;
584 break;
585 default:
586 break;
587 }
0e35f63f
AS
588 break;
589 case hwmon_fan:
6ff838f2
AS
590 switch (attr) {
591 case hwmon_fan_input:
592 *val = priv->speed_input[channel];
593 break;
594 case hwmon_fan_pulses:
595 ret = aqc_get_ctrl_val(priv, priv->flow_pulses_ctrl_offset, val);
596 if (ret < 0)
597 return ret;
598 break;
599 default:
600 break;
601 }
0e35f63f
AS
602 break;
603 case hwmon_power:
604 *val = priv->power_input[channel];
605 break;
752b9279 606 case hwmon_pwm:
654c9735 607 if (priv->fan_ctrl_offsets) {
662d20b3 608 ret = aqc_get_ctrl_val(priv, priv->fan_ctrl_offsets[channel], val);
752b9279
AS
609 if (ret < 0)
610 return ret;
611
612 *val = aqc_percent_to_pwm(ret);
752b9279
AS
613 }
614 break;
0e35f63f
AS
615 case hwmon_in:
616 *val = priv->voltage_input[channel];
617 break;
618 case hwmon_curr:
619 *val = priv->current_input[channel];
620 break;
621 default:
622 return -EOPNOTSUPP;
623 }
624
625 return 0;
626}
627
2fd3eec1
AS
628static int aqc_read_string(struct device *dev, enum hwmon_sensor_types type, u32 attr,
629 int channel, const char **str)
0e35f63f 630{
2fd3eec1
AS
631 struct aqc_data *priv = dev_get_drvdata(dev);
632
0e35f63f
AS
633 switch (type) {
634 case hwmon_temp:
e2769f5e
AS
635 if (channel < priv->num_temp_sensors)
636 *str = priv->temp_label[channel];
637 else
638 *str = priv->virtual_temp_label[channel - priv->num_temp_sensors];
0e35f63f
AS
639 break;
640 case hwmon_fan:
752b9279 641 *str = priv->speed_label[channel];
0e35f63f
AS
642 break;
643 case hwmon_power:
752b9279 644 *str = priv->power_label[channel];
0e35f63f
AS
645 break;
646 case hwmon_in:
752b9279 647 *str = priv->voltage_label[channel];
0e35f63f
AS
648 break;
649 case hwmon_curr:
752b9279
AS
650 *str = priv->current_label[channel];
651 break;
652 default:
653 return -EOPNOTSUPP;
654 }
655
656 return 0;
657}
658
659static int aqc_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel,
660 long val)
661{
662 int ret, pwm_value;
663 struct aqc_data *priv = dev_get_drvdata(dev);
664
665 switch (type) {
662d20b3
AS
666 case hwmon_temp:
667 switch (attr) {
668 case hwmon_temp_offset:
669 /* Limit temp offset to +/- 15K as in the official software */
670 val = clamp_val(val, -15000, 15000) / 10;
671 ret =
672 aqc_set_ctrl_val(priv, priv->temp_ctrl_offset +
8bcb02bd 673 channel * AQC_SENSOR_SIZE, val);
662d20b3
AS
674 if (ret < 0)
675 return ret;
676 break;
677 default:
678 return -EOPNOTSUPP;
679 }
680 break;
6ff838f2
AS
681 case hwmon_fan:
682 switch (attr) {
683 case hwmon_fan_pulses:
684 val = clamp_val(val, 10, 1000);
685 ret = aqc_set_ctrl_val(priv, priv->flow_pulses_ctrl_offset, val);
686 if (ret < 0)
687 return ret;
688 break;
689 default:
690 break;
691 }
692 break;
752b9279
AS
693 case hwmon_pwm:
694 switch (attr) {
695 case hwmon_pwm_input:
654c9735 696 if (priv->fan_ctrl_offsets) {
752b9279
AS
697 pwm_value = aqc_pwm_to_percent(val);
698 if (pwm_value < 0)
699 return pwm_value;
700
654c9735 701 ret = aqc_set_ctrl_val(priv, priv->fan_ctrl_offsets[channel],
752b9279
AS
702 pwm_value);
703 if (ret < 0)
704 return ret;
752b9279 705 }
2fd3eec1
AS
706 break;
707 default:
708 break;
709 }
0e35f63f
AS
710 break;
711 default:
712 return -EOPNOTSUPP;
713 }
714
715 return 0;
716}
717
2fd3eec1
AS
718static const struct hwmon_ops aqc_hwmon_ops = {
719 .is_visible = aqc_is_visible,
720 .read = aqc_read,
721 .read_string = aqc_read_string,
752b9279 722 .write = aqc_write
0e35f63f
AS
723};
724
2fd3eec1
AS
725static const struct hwmon_channel_info *aqc_info[] = {
726 HWMON_CHANNEL_INFO(temp,
662d20b3
AS
727 HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET,
728 HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET,
729 HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET,
730 HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET,
e2769f5e
AS
731 HWMON_T_INPUT | HWMON_T_LABEL,
732 HWMON_T_INPUT | HWMON_T_LABEL,
733 HWMON_T_INPUT | HWMON_T_LABEL,
734 HWMON_T_INPUT | HWMON_T_LABEL,
735 HWMON_T_INPUT | HWMON_T_LABEL,
736 HWMON_T_INPUT | HWMON_T_LABEL,
737 HWMON_T_INPUT | HWMON_T_LABEL,
738 HWMON_T_INPUT | HWMON_T_LABEL,
739 HWMON_T_INPUT | HWMON_T_LABEL,
740 HWMON_T_INPUT | HWMON_T_LABEL,
741 HWMON_T_INPUT | HWMON_T_LABEL,
742 HWMON_T_INPUT | HWMON_T_LABEL,
2fd3eec1
AS
743 HWMON_T_INPUT | HWMON_T_LABEL,
744 HWMON_T_INPUT | HWMON_T_LABEL,
745 HWMON_T_INPUT | HWMON_T_LABEL,
746 HWMON_T_INPUT | HWMON_T_LABEL),
747 HWMON_CHANNEL_INFO(fan,
752b9279
AS
748 HWMON_F_INPUT | HWMON_F_LABEL,
749 HWMON_F_INPUT | HWMON_F_LABEL,
750 HWMON_F_INPUT | HWMON_F_LABEL,
751 HWMON_F_INPUT | HWMON_F_LABEL,
6ff838f2 752 HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_PULSES,
752b9279 753 HWMON_F_INPUT | HWMON_F_LABEL,
2fd3eec1
AS
754 HWMON_F_INPUT | HWMON_F_LABEL,
755 HWMON_F_INPUT | HWMON_F_LABEL),
756 HWMON_CHANNEL_INFO(power,
752b9279
AS
757 HWMON_P_INPUT | HWMON_P_LABEL,
758 HWMON_P_INPUT | HWMON_P_LABEL,
759 HWMON_P_INPUT | HWMON_P_LABEL,
760 HWMON_P_INPUT | HWMON_P_LABEL,
761 HWMON_P_INPUT | HWMON_P_LABEL,
762 HWMON_P_INPUT | HWMON_P_LABEL,
2fd3eec1
AS
763 HWMON_P_INPUT | HWMON_P_LABEL,
764 HWMON_P_INPUT | HWMON_P_LABEL),
752b9279
AS
765 HWMON_CHANNEL_INFO(pwm,
766 HWMON_PWM_INPUT,
767 HWMON_PWM_INPUT,
768 HWMON_PWM_INPUT,
769 HWMON_PWM_INPUT,
770 HWMON_PWM_INPUT,
771 HWMON_PWM_INPUT,
772 HWMON_PWM_INPUT,
773 HWMON_PWM_INPUT),
2fd3eec1 774 HWMON_CHANNEL_INFO(in,
752b9279
AS
775 HWMON_I_INPUT | HWMON_I_LABEL,
776 HWMON_I_INPUT | HWMON_I_LABEL,
777 HWMON_I_INPUT | HWMON_I_LABEL,
778 HWMON_I_INPUT | HWMON_I_LABEL,
779 HWMON_I_INPUT | HWMON_I_LABEL,
2fd3eec1
AS
780 HWMON_I_INPUT | HWMON_I_LABEL,
781 HWMON_I_INPUT | HWMON_I_LABEL,
0e35f63f 782 HWMON_I_INPUT | HWMON_I_LABEL),
2fd3eec1 783 HWMON_CHANNEL_INFO(curr,
752b9279
AS
784 HWMON_C_INPUT | HWMON_C_LABEL,
785 HWMON_C_INPUT | HWMON_C_LABEL,
786 HWMON_C_INPUT | HWMON_C_LABEL,
787 HWMON_C_INPUT | HWMON_C_LABEL,
788 HWMON_C_INPUT | HWMON_C_LABEL,
789 HWMON_C_INPUT | HWMON_C_LABEL,
2fd3eec1
AS
790 HWMON_C_INPUT | HWMON_C_LABEL,
791 HWMON_C_INPUT | HWMON_C_LABEL),
0e35f63f
AS
792 NULL
793};
794
2fd3eec1
AS
795static const struct hwmon_chip_info aqc_chip_info = {
796 .ops = &aqc_hwmon_ops,
797 .info = aqc_info,
0e35f63f
AS
798};
799
229b159c 800static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *data, int size)
0e35f63f 801{
e2769f5e 802 int i, j, sensor_value;
2fd3eec1 803 struct aqc_data *priv;
0e35f63f 804
2fd3eec1 805 if (report->id != STATUS_REPORT_ID)
0e35f63f
AS
806 return 0;
807
808 priv = hid_get_drvdata(hdev);
809
810 /* Info provided with every report */
2fd3eec1
AS
811 priv->serial_number[0] = get_unaligned_be16(data + SERIAL_FIRST_PART);
812 priv->serial_number[1] = get_unaligned_be16(data + SERIAL_SECOND_PART);
813 priv->firmware_version = get_unaligned_be16(data + FIRMWARE_VERSION);
0e35f63f 814
e2769f5e 815 /* Physical temperature sensor readings */
654c9735
AS
816 for (i = 0; i < priv->num_temp_sensors; i++) {
817 sensor_value = get_unaligned_be16(data +
818 priv->temp_sensor_start_offset +
8bcb02bd 819 i * AQC_SENSOR_SIZE);
654c9735
AS
820 if (sensor_value == AQC_TEMP_SENSOR_DISCONNECTED)
821 priv->temp_input[i] = -ENODATA;
822 else
823 priv->temp_input[i] = sensor_value * 10;
824 }
0e35f63f 825
e2769f5e
AS
826 /* Virtual temperature sensor readings */
827 for (j = 0; j < priv->num_virtual_temp_sensors; j++) {
828 sensor_value = get_unaligned_be16(data +
829 priv->virtual_temp_sensor_start_offset +
8bcb02bd 830 j * AQC_SENSOR_SIZE);
e2769f5e
AS
831 if (sensor_value == AQC_TEMP_SENSOR_DISCONNECTED)
832 priv->temp_input[i] = -ENODATA;
833 else
834 priv->temp_input[i] = sensor_value * 10;
835 i++;
836 }
837
654c9735
AS
838 /* Fan speed and related readings */
839 for (i = 0; i < priv->num_fans; i++) {
840 priv->speed_input[i] =
249c7521
LA
841 get_unaligned_be16(data + priv->fan_sensor_offsets[i] +
842 priv->fan_structure->speed);
654c9735
AS
843 priv->power_input[i] =
844 get_unaligned_be16(data + priv->fan_sensor_offsets[i] +
249c7521 845 priv->fan_structure->power) * 10000;
654c9735
AS
846 priv->voltage_input[i] =
847 get_unaligned_be16(data + priv->fan_sensor_offsets[i] +
249c7521 848 priv->fan_structure->voltage) * 10;
654c9735 849 priv->current_input[i] =
249c7521
LA
850 get_unaligned_be16(data + priv->fan_sensor_offsets[i] +
851 priv->fan_structure->curr);
654c9735 852 }
0e35f63f 853
a2ba7ee2
LA
854 /* Flow sensor readings */
855 for (j = 0; j < priv->num_flow_sensors; j++) {
856 priv->speed_input[i] = get_unaligned_be16(data + priv->flow_sensors_start_offset +
857 j * AQC_SENSOR_SIZE);
858 i++;
859 }
860
654c9735
AS
861 if (priv->power_cycle_count_offset != 0)
862 priv->power_cycles = get_unaligned_be32(data + priv->power_cycle_count_offset);
0e35f63f 863
654c9735
AS
864 /* Special-case sensor readings */
865 switch (priv->kind) {
866 case d5next:
2fd3eec1 867 priv->voltage_input[2] = get_unaligned_be16(data + D5NEXT_5V_VOLTAGE) * 10;
f4caa262 868 priv->voltage_input[3] = get_unaligned_be16(data + D5NEXT_12V_VOLTAGE) * 10;
752b9279 869 break;
aed80bb9
AS
870 case highflownext:
871 /* If external temp sensor is not connected, its power reading is also N/A */
872 if (priv->temp_input[1] == -ENODATA)
873 priv->power_input[0] = -ENODATA;
874 else
875 priv->power_input[0] =
876 get_unaligned_be16(data + HIGHFLOWNEXT_POWER) * 1000000;
877
878 priv->voltage_input[0] = get_unaligned_be16(data + HIGHFLOWNEXT_5V_VOLTAGE) * 10;
879 priv->voltage_input[1] =
880 get_unaligned_be16(data + HIGHFLOWNEXT_5V_VOLTAGE_USB) * 10;
881
aed80bb9
AS
882 priv->speed_input[1] = get_unaligned_be16(data + HIGHFLOWNEXT_WATER_QUALITY);
883 priv->speed_input[2] = get_unaligned_be16(data + HIGHFLOWNEXT_CONDUCTIVITY);
884 break;
2fd3eec1
AS
885 default:
886 break;
887 }
0e35f63f
AS
888
889 priv->updated = jiffies;
890
891 return 0;
892}
893
894#ifdef CONFIG_DEBUG_FS
895
896static int serial_number_show(struct seq_file *seqf, void *unused)
897{
2fd3eec1 898 struct aqc_data *priv = seqf->private;
0e35f63f
AS
899
900 seq_printf(seqf, "%05u-%05u\n", priv->serial_number[0], priv->serial_number[1]);
901
902 return 0;
903}
904DEFINE_SHOW_ATTRIBUTE(serial_number);
905
906static int firmware_version_show(struct seq_file *seqf, void *unused)
907{
2fd3eec1 908 struct aqc_data *priv = seqf->private;
0e35f63f
AS
909
910 seq_printf(seqf, "%u\n", priv->firmware_version);
911
912 return 0;
913}
914DEFINE_SHOW_ATTRIBUTE(firmware_version);
915
916static int power_cycles_show(struct seq_file *seqf, void *unused)
917{
2fd3eec1 918 struct aqc_data *priv = seqf->private;
0e35f63f
AS
919
920 seq_printf(seqf, "%u\n", priv->power_cycles);
921
922 return 0;
923}
924DEFINE_SHOW_ATTRIBUTE(power_cycles);
925
2fd3eec1 926static void aqc_debugfs_init(struct aqc_data *priv)
0e35f63f 927{
2fd3eec1 928 char name[64];
0e35f63f 929
2fd3eec1
AS
930 scnprintf(name, sizeof(name), "%s_%s-%s", "aquacomputer", priv->name,
931 dev_name(&priv->hdev->dev));
0e35f63f
AS
932
933 priv->debugfs = debugfs_create_dir(name, NULL);
934 debugfs_create_file("serial_number", 0444, priv->debugfs, priv, &serial_number_fops);
935 debugfs_create_file("firmware_version", 0444, priv->debugfs, priv, &firmware_version_fops);
2fd3eec1 936
654c9735 937 if (priv->power_cycle_count_offset != 0)
2fd3eec1 938 debugfs_create_file("power_cycles", 0444, priv->debugfs, priv, &power_cycles_fops);
0e35f63f
AS
939}
940
941#else
942
2fd3eec1 943static void aqc_debugfs_init(struct aqc_data *priv)
0e35f63f
AS
944{
945}
946
947#endif
948
2fd3eec1 949static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
0e35f63f 950{
2fd3eec1 951 struct aqc_data *priv;
0e35f63f
AS
952 int ret;
953
954 priv = devm_kzalloc(&hdev->dev, sizeof(*priv), GFP_KERNEL);
955 if (!priv)
956 return -ENOMEM;
957
958 priv->hdev = hdev;
959 hid_set_drvdata(hdev, priv);
960
2fd3eec1 961 priv->updated = jiffies - STATUS_UPDATE_INTERVAL;
0e35f63f
AS
962
963 ret = hid_parse(hdev);
964 if (ret)
965 return ret;
966
967 ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
968 if (ret)
969 return ret;
970
971 ret = hid_hw_open(hdev);
972 if (ret)
973 goto fail_and_stop;
974
2fd3eec1
AS
975 switch (hdev->product) {
976 case USB_PRODUCT_ID_D5NEXT:
977 priv->kind = d5next;
752b9279 978
654c9735
AS
979 priv->num_fans = D5NEXT_NUM_FANS;
980 priv->fan_sensor_offsets = d5next_sensor_fan_offsets;
09e89309 981 priv->fan_ctrl_offsets = d5next_ctrl_fan_offsets;
d5d896b8 982
654c9735
AS
983 priv->num_temp_sensors = D5NEXT_NUM_SENSORS;
984 priv->temp_sensor_start_offset = D5NEXT_COOLANT_TEMP;
e2769f5e
AS
985 priv->num_virtual_temp_sensors = D5NEXT_NUM_VIRTUAL_SENSORS;
986 priv->virtual_temp_sensor_start_offset = D5NEXT_VIRTUAL_SENSORS_START;
662d20b3 987 priv->temp_ctrl_offset = D5NEXT_TEMP_CTRL_OFFSET;
654c9735 988
d5d896b8
AS
989 priv->buffer_size = D5NEXT_CTRL_REPORT_SIZE;
990
991 priv->power_cycle_count_offset = D5NEXT_POWER_CYCLES;
992
752b9279 993 priv->temp_label = label_d5next_temp;
e2769f5e 994 priv->virtual_temp_label = label_virtual_temp_sensors;
752b9279
AS
995 priv->speed_label = label_d5next_speeds;
996 priv->power_label = label_d5next_power;
997 priv->voltage_label = label_d5next_voltages;
998 priv->current_label = label_d5next_current;
2fd3eec1 999 break;
229b159c
JD
1000 case USB_PRODUCT_ID_FARBWERK:
1001 priv->kind = farbwerk;
1002
654c9735 1003 priv->num_fans = 0;
d5d896b8 1004
654c9735
AS
1005 priv->num_temp_sensors = FARBWERK_NUM_SENSORS;
1006 priv->temp_sensor_start_offset = FARBWERK_SENSOR_START;
d5d896b8 1007
229b159c
JD
1008 priv->temp_label = label_temp_sensors;
1009 break;
2fd3eec1
AS
1010 case USB_PRODUCT_ID_FARBWERK360:
1011 priv->kind = farbwerk360;
752b9279 1012
654c9735 1013 priv->num_fans = 0;
d5d896b8 1014
654c9735
AS
1015 priv->num_temp_sensors = FARBWERK360_NUM_SENSORS;
1016 priv->temp_sensor_start_offset = FARBWERK360_SENSOR_START;
e2769f5e
AS
1017 priv->num_virtual_temp_sensors = FARBWERK360_NUM_VIRTUAL_SENSORS;
1018 priv->virtual_temp_sensor_start_offset = FARBWERK360_VIRTUAL_SENSORS_START;
662d20b3 1019 priv->temp_ctrl_offset = FARBWERK360_TEMP_CTRL_OFFSET;
d5d896b8
AS
1020
1021 priv->buffer_size = FARBWERK360_CTRL_REPORT_SIZE;
1022
752b9279 1023 priv->temp_label = label_temp_sensors;
e2769f5e 1024 priv->virtual_temp_label = label_virtual_temp_sensors;
752b9279
AS
1025 break;
1026 case USB_PRODUCT_ID_OCTO:
1027 priv->kind = octo;
654c9735
AS
1028
1029 priv->num_fans = OCTO_NUM_FANS;
1030 priv->fan_sensor_offsets = octo_sensor_fan_offsets;
1031 priv->fan_ctrl_offsets = octo_ctrl_fan_offsets;
d5d896b8 1032
654c9735
AS
1033 priv->num_temp_sensors = OCTO_NUM_SENSORS;
1034 priv->temp_sensor_start_offset = OCTO_SENSOR_START;
e2769f5e
AS
1035 priv->num_virtual_temp_sensors = OCTO_NUM_VIRTUAL_SENSORS;
1036 priv->virtual_temp_sensor_start_offset = OCTO_VIRTUAL_SENSORS_START;
662d20b3 1037 priv->temp_ctrl_offset = OCTO_TEMP_CTRL_OFFSET;
752b9279 1038
d5d896b8
AS
1039 priv->buffer_size = OCTO_CTRL_REPORT_SIZE;
1040
1041 priv->power_cycle_count_offset = OCTO_POWER_CYCLES;
1042
752b9279 1043 priv->temp_label = label_temp_sensors;
e2769f5e 1044 priv->virtual_temp_label = label_virtual_temp_sensors;
752b9279
AS
1045 priv->speed_label = label_fan_speed;
1046 priv->power_label = label_fan_power;
1047 priv->voltage_label = label_fan_voltage;
1048 priv->current_label = label_fan_current;
2fd3eec1 1049 break;
cdbe34da
AS
1050 case USB_PRODUCT_ID_QUADRO:
1051 priv->kind = quadro;
1052
1053 priv->num_fans = QUADRO_NUM_FANS;
1054 priv->fan_sensor_offsets = quadro_sensor_fan_offsets;
1055 priv->fan_ctrl_offsets = quadro_ctrl_fan_offsets;
d5d896b8 1056
cdbe34da
AS
1057 priv->num_temp_sensors = QUADRO_NUM_SENSORS;
1058 priv->temp_sensor_start_offset = QUADRO_SENSOR_START;
e2769f5e
AS
1059 priv->num_virtual_temp_sensors = QUADRO_NUM_VIRTUAL_SENSORS;
1060 priv->virtual_temp_sensor_start_offset = QUADRO_VIRTUAL_SENSORS_START;
a2ba7ee2
LA
1061 priv->num_flow_sensors = QUADRO_NUM_FLOW_SENSORS;
1062 priv->flow_sensors_start_offset = QUADRO_FLOW_SENSOR_OFFSET;
1063
d5d896b8
AS
1064 priv->temp_ctrl_offset = QUADRO_TEMP_CTRL_OFFSET;
1065
cdbe34da 1066 priv->buffer_size = QUADRO_CTRL_REPORT_SIZE;
d5d896b8 1067
6ff838f2 1068 priv->flow_pulses_ctrl_offset = QUADRO_FLOW_PULSES_CTRL_OFFSET;
d5d896b8 1069 priv->power_cycle_count_offset = QUADRO_POWER_CYCLES;
cdbe34da
AS
1070
1071 priv->temp_label = label_temp_sensors;
e2769f5e 1072 priv->virtual_temp_label = label_virtual_temp_sensors;
cdbe34da
AS
1073 priv->speed_label = label_quadro_speeds;
1074 priv->power_label = label_fan_power;
1075 priv->voltage_label = label_fan_voltage;
1076 priv->current_label = label_fan_current;
1077 break;
aed80bb9
AS
1078 case USB_PRODUCT_ID_HIGHFLOWNEXT:
1079 priv->kind = highflownext;
1080
1081 priv->num_fans = 0;
d5d896b8 1082
aed80bb9
AS
1083 priv->num_temp_sensors = HIGHFLOWNEXT_NUM_SENSORS;
1084 priv->temp_sensor_start_offset = HIGHFLOWNEXT_SENSOR_START;
a2ba7ee2
LA
1085 priv->num_flow_sensors = HIGHFLOWNEXT_NUM_FLOW_SENSORS;
1086 priv->flow_sensors_start_offset = HIGHFLOWNEXT_FLOW;
d5d896b8 1087
aed80bb9
AS
1088 priv->power_cycle_count_offset = QUADRO_POWER_CYCLES;
1089
1090 priv->temp_label = label_highflownext_temp_sensors;
1091 priv->speed_label = label_highflownext_fan_speed;
1092 priv->power_label = label_highflownext_power;
1093 priv->voltage_label = label_highflownext_voltage;
1094 break;
2fd3eec1
AS
1095 default:
1096 break;
1097 }
1098
249c7521
LA
1099 priv->fan_structure = &aqc_general_fan_structure;
1100
654c9735
AS
1101 if (priv->buffer_size != 0) {
1102 priv->checksum_start = 0x01;
1103 priv->checksum_length = priv->buffer_size - 3;
1104 priv->checksum_offset = priv->buffer_size - 2;
1105 }
1106
2fd3eec1
AS
1107 priv->name = aqc_device_names[priv->kind];
1108
752b9279 1109 priv->buffer = devm_kzalloc(&hdev->dev, priv->buffer_size, GFP_KERNEL);
8877ecb0
CJ
1110 if (!priv->buffer) {
1111 ret = -ENOMEM;
1112 goto fail_and_close;
1113 }
752b9279
AS
1114
1115 mutex_init(&priv->mutex);
1116
2fd3eec1
AS
1117 priv->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, priv->name, priv,
1118 &aqc_chip_info, NULL);
0e35f63f
AS
1119
1120 if (IS_ERR(priv->hwmon_dev)) {
1121 ret = PTR_ERR(priv->hwmon_dev);
1122 goto fail_and_close;
1123 }
1124
2fd3eec1 1125 aqc_debugfs_init(priv);
0e35f63f
AS
1126
1127 return 0;
1128
1129fail_and_close:
1130 hid_hw_close(hdev);
1131fail_and_stop:
1132 hid_hw_stop(hdev);
1133 return ret;
1134}
1135
2fd3eec1 1136static void aqc_remove(struct hid_device *hdev)
0e35f63f 1137{
2fd3eec1 1138 struct aqc_data *priv = hid_get_drvdata(hdev);
0e35f63f
AS
1139
1140 debugfs_remove_recursive(priv->debugfs);
1141 hwmon_device_unregister(priv->hwmon_dev);
1142
1143 hid_hw_close(hdev);
1144 hid_hw_stop(hdev);
1145}
1146
2fd3eec1
AS
1147static const struct hid_device_id aqc_table[] = {
1148 { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_D5NEXT) },
229b159c 1149 { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_FARBWERK) },
2fd3eec1 1150 { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_FARBWERK360) },
752b9279 1151 { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_OCTO) },
cdbe34da 1152 { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_QUADRO) },
aed80bb9 1153 { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_HIGHFLOWNEXT) },
2fd3eec1 1154 { }
0e35f63f
AS
1155};
1156
2fd3eec1 1157MODULE_DEVICE_TABLE(hid, aqc_table);
0e35f63f 1158
2fd3eec1 1159static struct hid_driver aqc_driver = {
0e35f63f 1160 .name = DRIVER_NAME,
2fd3eec1
AS
1161 .id_table = aqc_table,
1162 .probe = aqc_probe,
1163 .remove = aqc_remove,
1164 .raw_event = aqc_raw_event,
0e35f63f
AS
1165};
1166
2fd3eec1 1167static int __init aqc_init(void)
0e35f63f 1168{
2fd3eec1 1169 return hid_register_driver(&aqc_driver);
0e35f63f
AS
1170}
1171
2fd3eec1 1172static void __exit aqc_exit(void)
0e35f63f 1173{
2fd3eec1 1174 hid_unregister_driver(&aqc_driver);
0e35f63f
AS
1175}
1176
1177/* Request to initialize after the HID bus to ensure it's not being loaded before */
2fd3eec1
AS
1178late_initcall(aqc_init);
1179module_exit(aqc_exit);
0e35f63f
AS
1180
1181MODULE_LICENSE("GPL");
1182MODULE_AUTHOR("Aleksa Savic <savicaleksa83@gmail.com>");
229b159c 1183MODULE_AUTHOR("Jack Doan <me@jackdoan.com>");
2fd3eec1 1184MODULE_DESCRIPTION("Hwmon driver for Aquacomputer devices");