1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * hwmon driver for Aquacomputer devices (D5 Next, Farbwerk, Farbwerk 360, Octo, |
4 | * Quadro, High Flow Next, Aquaero, Aquastream Ultimate, Leakshield, |
5 | * High Flow USB/MPS Flow family) |
6 | * |
7 | * Aquacomputer devices send HID reports (with ID 0x01) every second to report |
8 | * sensor values, except for devices that communicate through the |
9 | * legacy way (currently, Poweradjust 3 and High Flow USB/MPS Flow family). |
10 | * |
11 | * Copyright 2021 Aleksa Savic <savicaleksa83@gmail.com> |
12 | * Copyright 2022 Jack Doan <me@jackdoan.com> |
13 | */ |
14 | |
15 | #include <linux/crc16.h> |
16 | #include <linux/debugfs.h> |
17 | #include <linux/delay.h> |
18 | #include <linux/hid.h> |
19 | #include <linux/hwmon.h> |
20 | #include <linux/jiffies.h> |
21 | #include <linux/ktime.h> |
22 | #include <linux/module.h> |
23 | #include <linux/mutex.h> |
24 | #include <linux/seq_file.h> |
25 | #include <asm/unaligned.h> |
26 | |
27 | #define USB_VENDOR_ID_AQUACOMPUTER 0x0c70 |
28 | #define USB_PRODUCT_ID_AQUAERO 0xf001 |
29 | #define USB_PRODUCT_ID_FARBWERK 0xf00a |
30 | #define USB_PRODUCT_ID_QUADRO 0xf00d |
31 | #define USB_PRODUCT_ID_D5NEXT 0xf00e |
32 | #define USB_PRODUCT_ID_FARBWERK360 0xf010 |
33 | #define USB_PRODUCT_ID_OCTO 0xf011 |
34 | #define USB_PRODUCT_ID_HIGHFLOWNEXT 0xf012 |
35 | #define USB_PRODUCT_ID_LEAKSHIELD 0xf014 |
36 | #define USB_PRODUCT_ID_AQUASTREAMXT 0xf0b6 |
37 | #define USB_PRODUCT_ID_AQUASTREAMULT 0xf00b |
38 | #define USB_PRODUCT_ID_POWERADJUST3 0xf0bd |
39 | #define USB_PRODUCT_ID_HIGHFLOW 0xf003 |
40 | |
41 | enum kinds { |
42 | d5next, farbwerk, farbwerk360, octo, quadro, |
43 | highflownext, aquaero, poweradjust3, aquastreamult, |
44 | aquastreamxt, leakshield, highflow |
45 | }; |
46 | |
47 | static const char *const aqc_device_names[] = { |
48 | [d5next] = "d5next" , |
49 | [farbwerk] = "farbwerk" , |
50 | [farbwerk360] = "farbwerk360" , |
51 | [octo] = "octo" , |
52 | [quadro] = "quadro" , |
53 | [highflownext] = "highflownext" , |
54 | [leakshield] = "leakshield" , |
55 | [aquastreamxt] = "aquastreamxt" , |
56 | [aquaero] = "aquaero" , |
57 | [aquastreamult] = "aquastreamultimate" , |
58 | [poweradjust3] = "poweradjust3" , |
59 | [highflow] = "highflow" /* Covers MPS Flow devices */ |
60 | }; |
61 | |
62 | #define DRIVER_NAME "aquacomputer_d5next" |
63 | |
64 | #define STATUS_REPORT_ID 0x01 |
65 | #define STATUS_UPDATE_INTERVAL (2 * HZ) /* In seconds */ |
66 | #define SERIAL_PART_OFFSET 2 |
67 | |
68 | #define CTRL_REPORT_ID 0x03 |
69 | #define AQUAERO_CTRL_REPORT_ID 0x0b |
70 | |
71 | #define CTRL_REPORT_DELAY 200 /* ms */ |
72 | |
73 | /* The HID report that the official software always sends |
74 | * after writing values, currently same for all devices |
75 | */ |
76 | #define SECONDARY_CTRL_REPORT_ID 0x02 |
77 | #define SECONDARY_CTRL_REPORT_SIZE 0x0B |
78 | |
79 | static u8 secondary_ctrl_report[] = { |
80 | 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x34, 0xC6 |
81 | }; |
82 | |
83 | /* Secondary HID report values for Aquaero */ |
84 | #define AQUAERO_SECONDARY_CTRL_REPORT_ID 0x06 |
85 | #define AQUAERO_SECONDARY_CTRL_REPORT_SIZE 0x07 |
86 | |
87 | static u8 aquaero_secondary_ctrl_report[] = { |
88 | 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 |
89 | }; |
90 | |
91 | /* Report IDs for legacy devices */ |
92 | #define AQUASTREAMXT_STATUS_REPORT_ID 0x04 |
93 | |
94 | #define POWERADJUST3_STATUS_REPORT_ID 0x03 |
95 | |
96 | #define HIGHFLOW_STATUS_REPORT_ID 0x02 |
97 | |
98 | /* Data types for reading and writing control reports */ |
99 | #define AQC_8 0 |
100 | #define AQC_BE16 1 |
101 | |
102 | /* Info, sensor sizes and offsets for most Aquacomputer devices */ |
103 | #define AQC_SERIAL_START 0x3 |
104 | #define AQC_FIRMWARE_VERSION 0xD |
105 | |
106 | #define AQC_SENSOR_SIZE 0x02 |
107 | #define AQC_SENSOR_NA 0x7FFF |
108 | #define AQC_FAN_PERCENT_OFFSET 0x00 |
109 | #define AQC_FAN_VOLTAGE_OFFSET 0x02 |
110 | #define AQC_FAN_CURRENT_OFFSET 0x04 |
111 | #define AQC_FAN_POWER_OFFSET 0x06 |
112 | #define AQC_FAN_SPEED_OFFSET 0x08 |
113 | |
114 | /* Specs of the Aquaero fan controllers */ |
115 | #define AQUAERO_SERIAL_START 0x07 |
116 | #define AQUAERO_FIRMWARE_VERSION 0x0B |
117 | #define AQUAERO_NUM_FANS 4 |
118 | #define AQUAERO_NUM_SENSORS 8 |
119 | #define AQUAERO_NUM_VIRTUAL_SENSORS 8 |
120 | #define AQUAERO_NUM_CALC_VIRTUAL_SENSORS 4 |
121 | #define AQUAERO_NUM_FLOW_SENSORS 2 |
122 | #define AQUAERO_CTRL_REPORT_SIZE 0xa93 |
123 | #define AQUAERO_CTRL_PRESET_ID 0x5c |
124 | #define AQUAERO_CTRL_PRESET_SIZE 0x02 |
125 | #define AQUAERO_CTRL_PRESET_START 0x55c |
126 | |
127 | /* Sensor report offsets for Aquaero fan controllers */ |
128 | #define AQUAERO_SENSOR_START 0x65 |
129 | #define AQUAERO_VIRTUAL_SENSOR_START 0x85 |
130 | #define AQUAERO_CALC_VIRTUAL_SENSOR_START 0x95 |
131 | #define AQUAERO_FLOW_SENSORS_START 0xF9 |
132 | #define AQUAERO_FAN_VOLTAGE_OFFSET 0x04 |
133 | #define AQUAERO_FAN_CURRENT_OFFSET 0x06 |
134 | #define AQUAERO_FAN_POWER_OFFSET 0x08 |
135 | #define AQUAERO_FAN_SPEED_OFFSET 0x00 |
136 | static u16 aquaero_sensor_fan_offsets[] = { 0x167, 0x173, 0x17f, 0x18B }; |
137 | |
138 | /* Control report offsets for the Aquaero fan controllers */ |
139 | #define AQUAERO_TEMP_CTRL_OFFSET 0xdb |
140 | #define AQUAERO_FAN_CTRL_MIN_PWR_OFFSET 0x04 |
141 | #define AQUAERO_FAN_CTRL_MAX_PWR_OFFSET 0x06 |
142 | #define AQUAERO_FAN_CTRL_SRC_OFFSET 0x10 |
143 | static u16 aquaero_ctrl_fan_offsets[] = { 0x20c, 0x220, 0x234, 0x248 }; |
144 | |
145 | /* Specs of the D5 Next pump */ |
146 | #define D5NEXT_NUM_FANS 2 |
147 | #define D5NEXT_NUM_SENSORS 1 |
148 | #define D5NEXT_NUM_VIRTUAL_SENSORS 8 |
149 | #define D5NEXT_CTRL_REPORT_SIZE 0x329 |
150 | |
151 | /* Sensor report offsets for the D5 Next pump */ |
152 | #define D5NEXT_POWER_CYCLES 0x18 |
153 | #define D5NEXT_COOLANT_TEMP 0x57 |
154 | #define D5NEXT_PUMP_OFFSET 0x6c |
155 | #define D5NEXT_FAN_OFFSET 0x5f |
156 | #define D5NEXT_5V_VOLTAGE 0x39 |
157 | #define D5NEXT_12V_VOLTAGE 0x37 |
158 | #define D5NEXT_VIRTUAL_SENSORS_START 0x3f |
159 | static u16 d5next_sensor_fan_offsets[] = { D5NEXT_PUMP_OFFSET, D5NEXT_FAN_OFFSET }; |
160 | |
161 | /* Control report offsets for the D5 Next pump */ |
162 | #define D5NEXT_TEMP_CTRL_OFFSET 0x2D /* Temperature sensor offsets location */ |
163 | static u16 d5next_ctrl_fan_offsets[] = { 0x97, 0x42 }; /* Pump and fan speed (from 0-100%) */ |
164 | |
165 | /* Specs of the Aquastream Ultimate pump */ |
166 | /* Pump does not follow the standard structure, so only consider the fan */ |
167 | #define AQUASTREAMULT_NUM_FANS 1 |
168 | #define AQUASTREAMULT_NUM_SENSORS 2 |
169 | |
170 | /* Sensor report offsets for the Aquastream Ultimate pump */ |
171 | #define AQUASTREAMULT_SENSOR_START 0x2D |
172 | #define AQUASTREAMULT_PUMP_OFFSET 0x51 |
173 | #define AQUASTREAMULT_PUMP_VOLTAGE 0x3D |
174 | #define AQUASTREAMULT_PUMP_CURRENT 0x53 |
175 | #define AQUASTREAMULT_PUMP_POWER 0x55 |
176 | #define AQUASTREAMULT_FAN_OFFSET 0x41 |
177 | #define AQUASTREAMULT_PRESSURE_OFFSET 0x57 |
178 | #define AQUASTREAMULT_FLOW_SENSOR_OFFSET 0x37 |
179 | #define AQUASTREAMULT_FAN_VOLTAGE_OFFSET 0x02 |
180 | #define AQUASTREAMULT_FAN_CURRENT_OFFSET 0x00 |
181 | #define AQUASTREAMULT_FAN_POWER_OFFSET 0x04 |
182 | #define AQUASTREAMULT_FAN_SPEED_OFFSET 0x06 |
183 | static u16 aquastreamult_sensor_fan_offsets[] = { AQUASTREAMULT_FAN_OFFSET }; |
184 | |
185 | /* Spec and sensor report offset for the Farbwerk RGB controller */ |
186 | #define FARBWERK_NUM_SENSORS 4 |
187 | #define FARBWERK_SENSOR_START 0x2f |
188 | |
189 | /* Specs of the Farbwerk 360 RGB controller */ |
190 | #define FARBWERK360_NUM_SENSORS 4 |
191 | #define FARBWERK360_NUM_VIRTUAL_SENSORS 16 |
192 | #define FARBWERK360_CTRL_REPORT_SIZE 0x682 |
193 | |
194 | /* Sensor report offsets for the Farbwerk 360 */ |
195 | #define FARBWERK360_SENSOR_START 0x32 |
196 | #define FARBWERK360_VIRTUAL_SENSORS_START 0x3a |
197 | |
198 | /* Control report offsets for the Farbwerk 360 */ |
199 | #define FARBWERK360_TEMP_CTRL_OFFSET 0x8 |
200 | |
201 | /* Specs of the Octo fan controller */ |
202 | #define OCTO_NUM_FANS 8 |
203 | #define OCTO_NUM_SENSORS 4 |
204 | #define OCTO_NUM_VIRTUAL_SENSORS 16 |
205 | #define OCTO_CTRL_REPORT_SIZE 0x65F |
206 | |
207 | /* Sensor report offsets for the Octo */ |
208 | #define OCTO_POWER_CYCLES 0x18 |
209 | #define OCTO_SENSOR_START 0x3D |
210 | #define OCTO_VIRTUAL_SENSORS_START 0x45 |
211 | static u16 octo_sensor_fan_offsets[] = { 0x7D, 0x8A, 0x97, 0xA4, 0xB1, 0xBE, 0xCB, 0xD8 }; |
212 | |
213 | /* Control report offsets for the Octo */ |
214 | #define OCTO_TEMP_CTRL_OFFSET 0xA |
215 | /* Fan speed offsets (0-100%) */ |
216 | static u16 octo_ctrl_fan_offsets[] = { 0x5B, 0xB0, 0x105, 0x15A, 0x1AF, 0x204, 0x259, 0x2AE }; |
217 | |
218 | /* Specs of Quadro fan controller */ |
219 | #define QUADRO_NUM_FANS 4 |
220 | #define QUADRO_NUM_SENSORS 4 |
221 | #define QUADRO_NUM_VIRTUAL_SENSORS 16 |
222 | #define QUADRO_NUM_FLOW_SENSORS 1 |
223 | #define QUADRO_CTRL_REPORT_SIZE 0x3c1 |
224 | |
225 | /* Sensor report offsets for the Quadro */ |
226 | #define QUADRO_POWER_CYCLES 0x18 |
227 | #define QUADRO_SENSOR_START 0x34 |
228 | #define QUADRO_VIRTUAL_SENSORS_START 0x3c |
229 | #define QUADRO_FLOW_SENSOR_OFFSET 0x6e |
230 | static u16 quadro_sensor_fan_offsets[] = { 0x70, 0x7D, 0x8A, 0x97 }; |
231 | |
232 | /* Control report offsets for the Quadro */ |
233 | #define QUADRO_TEMP_CTRL_OFFSET 0xA |
234 | #define QUADRO_FLOW_PULSES_CTRL_OFFSET 0x6 |
235 | static u16 quadro_ctrl_fan_offsets[] = { 0x37, 0x8c, 0xe1, 0x136 }; /* Fan speed offsets (0-100%) */ |
236 | |
237 | /* Specs of High Flow Next flow sensor */ |
238 | #define HIGHFLOWNEXT_NUM_SENSORS 2 |
239 | #define HIGHFLOWNEXT_NUM_FLOW_SENSORS 1 |
240 | |
241 | /* Sensor report offsets for the High Flow Next */ |
242 | #define HIGHFLOWNEXT_SENSOR_START 85 |
243 | #define HIGHFLOWNEXT_FLOW 81 |
244 | #define HIGHFLOWNEXT_WATER_QUALITY 89 |
245 | #define HIGHFLOWNEXT_POWER 91 |
246 | #define HIGHFLOWNEXT_CONDUCTIVITY 95 |
247 | #define HIGHFLOWNEXT_5V_VOLTAGE 97 |
248 | #define HIGHFLOWNEXT_5V_VOLTAGE_USB 99 |
249 | |
250 | /* Specs of the Leakshield */ |
251 | #define LEAKSHIELD_NUM_SENSORS 2 |
252 | |
253 | /* Sensor report offsets for Leakshield */ |
254 | #define LEAKSHIELD_PRESSURE_ADJUSTED 285 |
255 | #define LEAKSHIELD_TEMPERATURE_1 265 |
256 | #define LEAKSHIELD_TEMPERATURE_2 287 |
257 | #define LEAKSHIELD_PRESSURE_MIN 291 |
258 | #define LEAKSHIELD_PRESSURE_TARGET 293 |
259 | #define LEAKSHIELD_PRESSURE_MAX 295 |
260 | #define LEAKSHIELD_PUMP_RPM_IN 101 |
261 | #define LEAKSHIELD_FLOW_IN 111 |
262 | #define LEAKSHIELD_RESERVOIR_VOLUME 313 |
263 | #define LEAKSHIELD_RESERVOIR_FILLED 311 |
264 | |
265 | /* Specs of the Aquastream XT pump */ |
266 | #define AQUASTREAMXT_SERIAL_START 0x3a |
267 | #define AQUASTREAMXT_FIRMWARE_VERSION 0x32 |
268 | #define AQUASTREAMXT_NUM_FANS 2 |
269 | #define AQUASTREAMXT_NUM_SENSORS 3 |
270 | #define AQUASTREAMXT_FAN_STOPPED 0x4 |
271 | #define AQUASTREAMXT_PUMP_CONVERSION_CONST 45000000 |
272 | #define AQUASTREAMXT_FAN_CONVERSION_CONST 5646000 |
273 | #define AQUASTREAMXT_SENSOR_REPORT_SIZE 0x42 |
274 | |
275 | /* Sensor report offsets and info for Aquastream XT */ |
276 | #define AQUASTREAMXT_SENSOR_START 0xd |
277 | #define AQUASTREAMXT_FAN_VOLTAGE_OFFSET 0x7 |
278 | #define AQUASTREAMXT_FAN_STATUS_OFFSET 0x1d |
279 | #define AQUASTREAMXT_PUMP_VOLTAGE_OFFSET 0x9 |
280 | #define AQUASTREAMXT_PUMP_CURR_OFFSET 0xb |
281 | static u16 aquastreamxt_sensor_fan_offsets[] = { 0x13, 0x1b }; |
282 | |
283 | /* Specs of the Poweradjust 3 */ |
284 | #define POWERADJUST3_NUM_SENSORS 1 |
285 | #define POWERADJUST3_SENSOR_REPORT_SIZE 0x32 |
286 | |
287 | /* Sensor report offsets for the Poweradjust 3 */ |
288 | #define POWERADJUST3_SENSOR_START 0x03 |
289 | |
290 | /* Specs of the High Flow USB */ |
291 | #define HIGHFLOW_NUM_SENSORS 2 |
292 | #define HIGHFLOW_NUM_FLOW_SENSORS 1 |
293 | #define HIGHFLOW_SENSOR_REPORT_SIZE 0x76 |
294 | |
295 | /* Sensor report offsets for the High Flow USB */ |
296 | #define HIGHFLOW_FIRMWARE_VERSION 0x3 |
297 | #define HIGHFLOW_SERIAL_START 0x9 |
298 | #define HIGHFLOW_FLOW_SENSOR_OFFSET 0x23 |
299 | #define HIGHFLOW_SENSOR_START 0x2b |
300 | |
301 | /* Labels for D5 Next */ |
302 | static const char *const label_d5next_temp[] = { |
303 | "Coolant temp" |
304 | }; |
305 | |
306 | static const char *const label_d5next_speeds[] = { |
307 | "Pump speed" , |
308 | "Fan speed" |
309 | }; |
310 | |
311 | static const char *const label_d5next_power[] = { |
312 | "Pump power" , |
313 | "Fan power" |
314 | }; |
315 | |
316 | static const char *const label_d5next_voltages[] = { |
317 | "Pump voltage" , |
318 | "Fan voltage" , |
319 | "+5V voltage" , |
320 | "+12V voltage" |
321 | }; |
322 | |
323 | static const char *const label_d5next_current[] = { |
324 | "Pump current" , |
325 | "Fan current" |
326 | }; |
327 | |
328 | /* Labels for Aquaero, Farbwerk, Farbwerk 360 and Octo and Quadro temperature sensors */ |
329 | static const char *const label_temp_sensors[] = { |
330 | "Sensor 1" , |
331 | "Sensor 2" , |
332 | "Sensor 3" , |
333 | "Sensor 4" , |
334 | "Sensor 5" , |
335 | "Sensor 6" , |
336 | "Sensor 7" , |
337 | "Sensor 8" |
338 | }; |
339 | |
340 | static const char *const label_virtual_temp_sensors[] = { |
341 | "Virtual sensor 1" , |
342 | "Virtual sensor 2" , |
343 | "Virtual sensor 3" , |
344 | "Virtual sensor 4" , |
345 | "Virtual sensor 5" , |
346 | "Virtual sensor 6" , |
347 | "Virtual sensor 7" , |
348 | "Virtual sensor 8" , |
349 | "Virtual sensor 9" , |
350 | "Virtual sensor 10" , |
351 | "Virtual sensor 11" , |
352 | "Virtual sensor 12" , |
353 | "Virtual sensor 13" , |
354 | "Virtual sensor 14" , |
355 | "Virtual sensor 15" , |
356 | "Virtual sensor 16" , |
357 | }; |
358 | |
359 | static const char *const label_aquaero_calc_temp_sensors[] = { |
360 | "Calc. virtual sensor 1" , |
361 | "Calc. virtual sensor 2" , |
362 | "Calc. virtual sensor 3" , |
363 | "Calc. virtual sensor 4" |
364 | }; |
365 | |
366 | /* Labels for Octo and Quadro (except speed) */ |
367 | static const char *const label_fan_speed[] = { |
368 | "Fan 1 speed" , |
369 | "Fan 2 speed" , |
370 | "Fan 3 speed" , |
371 | "Fan 4 speed" , |
372 | "Fan 5 speed" , |
373 | "Fan 6 speed" , |
374 | "Fan 7 speed" , |
375 | "Fan 8 speed" |
376 | }; |
377 | |
378 | static const char *const label_fan_power[] = { |
379 | "Fan 1 power" , |
380 | "Fan 2 power" , |
381 | "Fan 3 power" , |
382 | "Fan 4 power" , |
383 | "Fan 5 power" , |
384 | "Fan 6 power" , |
385 | "Fan 7 power" , |
386 | "Fan 8 power" |
387 | }; |
388 | |
389 | static const char *const label_fan_voltage[] = { |
390 | "Fan 1 voltage" , |
391 | "Fan 2 voltage" , |
392 | "Fan 3 voltage" , |
393 | "Fan 4 voltage" , |
394 | "Fan 5 voltage" , |
395 | "Fan 6 voltage" , |
396 | "Fan 7 voltage" , |
397 | "Fan 8 voltage" |
398 | }; |
399 | |
400 | static const char *const label_fan_current[] = { |
401 | "Fan 1 current" , |
402 | "Fan 2 current" , |
403 | "Fan 3 current" , |
404 | "Fan 4 current" , |
405 | "Fan 5 current" , |
406 | "Fan 6 current" , |
407 | "Fan 7 current" , |
408 | "Fan 8 current" |
409 | }; |
410 | |
411 | /* Labels for Quadro fan speeds */ |
412 | static const char *const label_quadro_speeds[] = { |
413 | "Fan 1 speed" , |
414 | "Fan 2 speed" , |
415 | "Fan 3 speed" , |
416 | "Fan 4 speed" , |
417 | "Flow speed [dL/h]" |
418 | }; |
419 | |
420 | /* Labels for Aquaero fan speeds */ |
421 | static const char *const label_aquaero_speeds[] = { |
422 | "Fan 1 speed" , |
423 | "Fan 2 speed" , |
424 | "Fan 3 speed" , |
425 | "Fan 4 speed" , |
426 | "Flow sensor 1 [dL/h]" , |
427 | "Flow sensor 2 [dL/h]" |
428 | }; |
429 | |
430 | /* Labels for High Flow Next */ |
431 | static const char *const label_highflownext_temp_sensors[] = { |
432 | "Coolant temp" , |
433 | "External sensor" |
434 | }; |
435 | |
436 | static const char *const label_highflownext_fan_speed[] = { |
437 | "Flow [dL/h]" , |
438 | "Water quality [%]" , |
439 | "Conductivity [nS/cm]" , |
440 | }; |
441 | |
442 | static const char *const label_highflownext_power[] = { |
443 | "Dissipated power" , |
444 | }; |
445 | |
446 | static const char *const label_highflownext_voltage[] = { |
447 | "+5V voltage" , |
448 | "+5V USB voltage" |
449 | }; |
450 | |
451 | /* Labels for Leakshield */ |
452 | static const char *const label_leakshield_temp_sensors[] = { |
453 | "Temperature 1" , |
454 | "Temperature 2" |
455 | }; |
456 | |
457 | static const char *const label_leakshield_fan_speed[] = { |
458 | "Pressure [ubar]" , |
459 | "User-Provided Pump Speed" , |
460 | "User-Provided Flow [dL/h]" , |
461 | "Reservoir Volume [ml]" , |
462 | "Reservoir Filled [ml]" , |
463 | }; |
464 | |
465 | /* Labels for Aquastream XT */ |
466 | static const char *const label_aquastreamxt_temp_sensors[] = { |
467 | "Fan IC temp" , |
468 | "External sensor" , |
469 | "Coolant temp" |
470 | }; |
471 | |
472 | /* Labels for Aquastream Ultimate */ |
473 | static const char *const label_aquastreamult_temp[] = { |
474 | "Coolant temp" , |
475 | "External temp" |
476 | }; |
477 | |
478 | static const char *const label_aquastreamult_speeds[] = { |
479 | "Fan speed" , |
480 | "Pump speed" , |
481 | "Pressure [mbar]" , |
482 | "Flow speed [dL/h]" |
483 | }; |
484 | |
485 | static const char *const label_aquastreamult_power[] = { |
486 | "Fan power" , |
487 | "Pump power" |
488 | }; |
489 | |
490 | static const char *const label_aquastreamult_voltages[] = { |
491 | "Fan voltage" , |
492 | "Pump voltage" |
493 | }; |
494 | |
495 | static const char *const label_aquastreamult_current[] = { |
496 | "Fan current" , |
497 | "Pump current" |
498 | }; |
499 | |
500 | /* Labels for Poweradjust 3 */ |
501 | static const char *const label_poweradjust3_temp_sensors[] = { |
502 | "External sensor" |
503 | }; |
504 | |
505 | /* Labels for Highflow */ |
506 | static const char *const label_highflow_temp[] = { |
507 | "External temp" , |
508 | "Internal temp" |
509 | }; |
510 | |
511 | static const char *const label_highflow_speeds[] = { |
512 | "Flow speed [dL/h]" |
513 | }; |
514 | |
515 | struct aqc_fan_structure_offsets { |
516 | u8 voltage; |
517 | u8 curr; |
518 | u8 power; |
519 | u8 speed; |
520 | }; |
521 | |
522 | /* Fan structure offsets for Aquaero */ |
523 | static struct aqc_fan_structure_offsets aqc_aquaero_fan_structure = { |
524 | .voltage = AQUAERO_FAN_VOLTAGE_OFFSET, |
525 | .curr = AQUAERO_FAN_CURRENT_OFFSET, |
526 | .power = AQUAERO_FAN_POWER_OFFSET, |
527 | .speed = AQUAERO_FAN_SPEED_OFFSET |
528 | }; |
529 | |
530 | /* Fan structure offsets for Aquastream Ultimate */ |
531 | static struct aqc_fan_structure_offsets aqc_aquastreamult_fan_structure = { |
532 | .voltage = AQUASTREAMULT_FAN_VOLTAGE_OFFSET, |
533 | .curr = AQUASTREAMULT_FAN_CURRENT_OFFSET, |
534 | .power = AQUASTREAMULT_FAN_POWER_OFFSET, |
535 | .speed = AQUASTREAMULT_FAN_SPEED_OFFSET |
536 | }; |
537 | |
538 | /* Fan structure offsets for all devices except those above */ |
539 | static struct aqc_fan_structure_offsets aqc_general_fan_structure = { |
540 | .voltage = AQC_FAN_VOLTAGE_OFFSET, |
541 | .curr = AQC_FAN_CURRENT_OFFSET, |
542 | .power = AQC_FAN_POWER_OFFSET, |
543 | .speed = AQC_FAN_SPEED_OFFSET |
544 | }; |
545 | |
546 | struct aqc_data { |
547 | struct hid_device *hdev; |
548 | struct device *hwmon_dev; |
549 | struct dentry *debugfs; |
550 | struct mutex mutex; /* Used for locking access when reading and writing PWM values */ |
551 | enum kinds kind; |
552 | const char *name; |
553 | |
554 | int status_report_id; /* Used for legacy devices, report is stored in buffer */ |
555 | int ctrl_report_id; |
556 | int secondary_ctrl_report_id; |
557 | int secondary_ctrl_report_size; |
558 | u8 *secondary_ctrl_report; |
559 | |
560 | ktime_t last_ctrl_report_op; |
561 | int ctrl_report_delay; /* Delay between two ctrl report operations, in ms */ |
562 | |
563 | int buffer_size; |
564 | u8 *buffer; |
565 | int checksum_start; |
566 | int checksum_length; |
567 | int checksum_offset; |
568 | |
569 | int num_fans; |
570 | u16 *fan_sensor_offsets; |
571 | u16 *fan_ctrl_offsets; |
572 | int num_temp_sensors; |
573 | int temp_sensor_start_offset; |
574 | int num_virtual_temp_sensors; |
575 | int virtual_temp_sensor_start_offset; |
576 | int num_calc_virt_temp_sensors; |
577 | int calc_virt_temp_sensor_start_offset; |
578 | u16 temp_ctrl_offset; |
579 | u16 power_cycle_count_offset; |
580 | int num_flow_sensors; |
581 | u8 flow_sensors_start_offset; |
582 | u8 flow_pulses_ctrl_offset; |
583 | struct aqc_fan_structure_offsets *fan_structure; |
584 | |
585 | /* General info, same across all devices */ |
586 | u8 serial_number_start_offset; |
587 | u32 serial_number[2]; |
588 | u8 firmware_version_offset; |
589 | u16 firmware_version; |
590 | |
591 | /* How many times the device was powered on, if available */ |
592 | u32 power_cycles; |
593 | |
594 | /* Sensor values */ |
595 | s32 temp_input[20]; /* Max 4 physical and 16 virtual or 8 physical and 12 virtual */ |
596 | s32 speed_input[8]; |
597 | u32 speed_input_min[1]; |
598 | u32 speed_input_target[1]; |
599 | u32 speed_input_max[1]; |
600 | u32 power_input[8]; |
601 | u16 voltage_input[8]; |
602 | u16 current_input[8]; |
603 | |
604 | /* Label values */ |
605 | const char *const *temp_label; |
606 | const char *const *virtual_temp_label; |
607 | const char *const *calc_virt_temp_label; /* For Aquaero */ |
608 | const char *const *speed_label; |
609 | const char *const *power_label; |
610 | const char *const *voltage_label; |
611 | const char *const *current_label; |
612 | |
613 | unsigned long updated; |
614 | }; |
615 | |
616 | /* Converts from centi-percent */ |
617 | static int aqc_percent_to_pwm(u16 val) |
618 | { |
619 | return DIV_ROUND_CLOSEST(val * 255, 100 * 100); |
620 | } |
621 | |
622 | /* Converts to centi-percent */ |
623 | static int aqc_pwm_to_percent(long val) |
624 | { |
625 | if (val < 0 || val > 255) |
626 | return -EINVAL; |
627 | |
628 | return DIV_ROUND_CLOSEST(val * 100 * 100, 255); |
629 | } |
630 | |
631 | /* Converts raw value for Aquastream XT pump speed to RPM */ |
632 | static int aqc_aquastreamxt_convert_pump_rpm(u16 val) |
633 | { |
634 | if (val > 0) |
635 | return DIV_ROUND_CLOSEST(AQUASTREAMXT_PUMP_CONVERSION_CONST, val); |
636 | return 0; |
637 | } |
638 | |
639 | /* Converts raw value for Aquastream XT fan speed to RPM */ |
640 | static int aqc_aquastreamxt_convert_fan_rpm(u16 val) |
641 | { |
642 | if (val > 0) |
643 | return DIV_ROUND_CLOSEST(AQUASTREAMXT_FAN_CONVERSION_CONST, val); |
644 | return 0; |
645 | } |
646 | |
647 | static void aqc_delay_ctrl_report(struct aqc_data *priv) |
648 | { |
649 | /* |
650 | * If previous read or write is too close to this one, delay the current operation |
651 | * to give the device enough time to process the previous one. |
652 | */ |
653 | if (priv->ctrl_report_delay) { |
654 | s64 delta = ktime_ms_delta(later: ktime_get(), earlier: priv->last_ctrl_report_op); |
655 | |
656 | if (delta < priv->ctrl_report_delay) |
657 | msleep(msecs: priv->ctrl_report_delay - delta); |
658 | } |
659 | } |
660 | |
661 | /* Expects the mutex to be locked */ |
662 | static int aqc_get_ctrl_data(struct aqc_data *priv) |
663 | { |
664 | int ret; |
665 | |
666 | aqc_delay_ctrl_report(priv); |
667 | |
668 | memset(priv->buffer, 0x00, priv->buffer_size); |
669 | ret = hid_hw_raw_request(hdev: priv->hdev, reportnum: priv->ctrl_report_id, buf: priv->buffer, len: priv->buffer_size, |
670 | rtype: HID_FEATURE_REPORT, reqtype: HID_REQ_GET_REPORT); |
671 | if (ret < 0) |
672 | ret = -ENODATA; |
673 | |
674 | priv->last_ctrl_report_op = ktime_get(); |
675 | |
676 | return ret; |
677 | } |
678 | |
679 | /* Expects the mutex to be locked */ |
680 | static int aqc_send_ctrl_data(struct aqc_data *priv) |
681 | { |
682 | int ret; |
683 | u16 checksum; |
684 | |
685 | aqc_delay_ctrl_report(priv); |
686 | |
687 | /* Checksum is not needed for Aquaero */ |
688 | if (priv->kind != aquaero) { |
689 | /* Init and xorout value for CRC-16/USB is 0xffff */ |
690 | checksum = crc16(crc: 0xffff, buffer: priv->buffer + priv->checksum_start, |
691 | len: priv->checksum_length); |
692 | checksum ^= 0xffff; |
693 | |
694 | /* Place the new checksum at the end of the report */ |
695 | put_unaligned_be16(val: checksum, p: priv->buffer + priv->checksum_offset); |
696 | } |
697 | |
698 | /* Send the patched up report back to the device */ |
699 | ret = hid_hw_raw_request(hdev: priv->hdev, reportnum: priv->ctrl_report_id, buf: priv->buffer, len: priv->buffer_size, |
700 | rtype: HID_FEATURE_REPORT, reqtype: HID_REQ_SET_REPORT); |
701 | if (ret < 0) |
702 | goto record_access_and_ret; |
703 | |
704 | /* The official software sends this report after every change, so do it here as well */ |
705 | ret = hid_hw_raw_request(hdev: priv->hdev, reportnum: priv->secondary_ctrl_report_id, |
706 | buf: priv->secondary_ctrl_report, len: priv->secondary_ctrl_report_size, |
707 | rtype: HID_FEATURE_REPORT, reqtype: HID_REQ_SET_REPORT); |
708 | |
709 | record_access_and_ret: |
710 | priv->last_ctrl_report_op = ktime_get(); |
711 | |
712 | return ret; |
713 | } |
714 | |
715 | /* Refreshes the control buffer and stores value at offset in val */ |
716 | static int aqc_get_ctrl_val(struct aqc_data *priv, int offset, long *val, int type) |
717 | { |
718 | int ret; |
719 | |
720 | mutex_lock(&priv->mutex); |
721 | |
722 | ret = aqc_get_ctrl_data(priv); |
723 | if (ret < 0) |
724 | goto unlock_and_return; |
725 | |
726 | switch (type) { |
727 | case AQC_BE16: |
728 | *val = (s16)get_unaligned_be16(p: priv->buffer + offset); |
729 | break; |
730 | case AQC_8: |
731 | *val = priv->buffer[offset]; |
732 | break; |
733 | default: |
734 | ret = -EINVAL; |
735 | } |
736 | |
737 | unlock_and_return: |
738 | mutex_unlock(lock: &priv->mutex); |
739 | return ret; |
740 | } |
741 | |
742 | static int aqc_set_ctrl_vals(struct aqc_data *priv, int *offsets, long *vals, int *types, int len) |
743 | { |
744 | int ret, i; |
745 | |
746 | mutex_lock(&priv->mutex); |
747 | |
748 | ret = aqc_get_ctrl_data(priv); |
749 | if (ret < 0) |
750 | goto unlock_and_return; |
751 | |
752 | for (i = 0; i < len; i++) { |
753 | switch (types[i]) { |
754 | case AQC_BE16: |
755 | put_unaligned_be16(val: (s16)vals[i], p: priv->buffer + offsets[i]); |
756 | break; |
757 | case AQC_8: |
758 | priv->buffer[offsets[i]] = (u8)vals[i]; |
759 | break; |
760 | default: |
761 | ret = -EINVAL; |
762 | } |
763 | } |
764 | |
765 | if (ret < 0) |
766 | goto unlock_and_return; |
767 | |
768 | ret = aqc_send_ctrl_data(priv); |
769 | |
770 | unlock_and_return: |
771 | mutex_unlock(lock: &priv->mutex); |
772 | return ret; |
773 | } |
774 | |
775 | static int aqc_set_ctrl_val(struct aqc_data *priv, int offset, long val, int type) |
776 | { |
777 | return aqc_set_ctrl_vals(priv, offsets: &offset, vals: &val, types: &type, len: 1); |
778 | } |
779 | |
780 | static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, int channel) |
781 | { |
782 | const struct aqc_data *priv = data; |
783 | |
784 | switch (type) { |
785 | case hwmon_temp: |
786 | if (channel < priv->num_temp_sensors) { |
787 | switch (attr) { |
788 | case hwmon_temp_label: |
789 | case hwmon_temp_input: |
790 | return 0444; |
791 | case hwmon_temp_offset: |
792 | if (priv->temp_ctrl_offset != 0) |
793 | return 0644; |
794 | break; |
795 | default: |
796 | break; |
797 | } |
798 | } |
799 | |
800 | if (channel < |
801 | priv->num_temp_sensors + priv->num_virtual_temp_sensors + |
802 | priv->num_calc_virt_temp_sensors) |
803 | switch (attr) { |
804 | case hwmon_temp_label: |
805 | case hwmon_temp_input: |
806 | return 0444; |
807 | default: |
808 | break; |
809 | } |
810 | break; |
811 | case hwmon_pwm: |
812 | if (priv->fan_ctrl_offsets && channel < priv->num_fans) { |
813 | switch (attr) { |
814 | case hwmon_pwm_input: |
815 | return 0644; |
816 | default: |
817 | break; |
818 | } |
819 | } |
820 | break; |
821 | case hwmon_fan: |
822 | switch (attr) { |
823 | case hwmon_fan_input: |
824 | case hwmon_fan_label: |
825 | switch (priv->kind) { |
826 | case aquastreamult: |
827 | /* |
828 | * Special case to support pump RPM, fan RPM, |
829 | * pressure and flow sensor |
830 | */ |
831 | if (channel < 4) |
832 | return 0444; |
833 | break; |
834 | case highflownext: |
835 | /* Special case to support flow sensor, water quality |
836 | * and conductivity |
837 | */ |
838 | if (channel < 3) |
839 | return 0444; |
840 | break; |
841 | case leakshield: |
842 | /* Special case for Leakshield sensors */ |
843 | if (channel < 5) |
844 | return 0444; |
845 | break; |
846 | case aquaero: |
847 | case quadro: |
848 | case highflow: |
849 | /* Special case to support flow sensors */ |
850 | if (channel < priv->num_fans + priv->num_flow_sensors) |
851 | return 0444; |
852 | break; |
853 | default: |
854 | if (channel < priv->num_fans) |
855 | return 0444; |
856 | break; |
857 | } |
858 | break; |
859 | case hwmon_fan_pulses: |
860 | /* Special case for Quadro flow sensor */ |
861 | if (priv->kind == quadro && channel == priv->num_fans) |
862 | return 0644; |
863 | break; |
864 | case hwmon_fan_min: |
865 | case hwmon_fan_max: |
866 | case hwmon_fan_target: |
867 | /* Special case for Leakshield pressure sensor */ |
868 | if (priv->kind == leakshield && channel == 0) |
869 | return 0444; |
870 | break; |
871 | default: |
872 | break; |
873 | } |
874 | break; |
875 | case hwmon_power: |
876 | switch (priv->kind) { |
877 | case aquastreamult: |
878 | /* Special case to support pump and fan power */ |
879 | if (channel < 2) |
880 | return 0444; |
881 | break; |
882 | case highflownext: |
883 | /* Special case to support one power sensor */ |
884 | if (channel == 0) |
885 | return 0444; |
886 | break; |
887 | case aquastreamxt: |
888 | break; |
889 | default: |
890 | if (channel < priv->num_fans) |
891 | return 0444; |
892 | break; |
893 | } |
894 | break; |
895 | case hwmon_curr: |
896 | switch (priv->kind) { |
897 | case aquastreamult: |
898 | /* Special case to support pump and fan current */ |
899 | if (channel < 2) |
900 | return 0444; |
901 | break; |
902 | case aquastreamxt: |
903 | /* Special case to support pump current */ |
904 | if (channel == 0) |
905 | return 0444; |
906 | break; |
907 | default: |
908 | if (channel < priv->num_fans) |
909 | return 0444; |
910 | break; |
911 | } |
912 | break; |
913 | case hwmon_in: |
914 | switch (priv->kind) { |
915 | case d5next: |
916 | /* Special case to support +5V and +12V voltage sensors */ |
917 | if (channel < priv->num_fans + 2) |
918 | return 0444; |
919 | break; |
920 | case aquastreamult: |
921 | case highflownext: |
922 | /* Special case to support two voltage sensors */ |
923 | if (channel < 2) |
924 | return 0444; |
925 | break; |
926 | default: |
927 | if (channel < priv->num_fans) |
928 | return 0444; |
929 | break; |
930 | } |
931 | break; |
932 | default: |
933 | break; |
934 | } |
935 | |
936 | return 0; |
937 | } |
938 | |
939 | /* Read device sensors by manually requesting the sensor report (legacy way) */ |
940 | static int aqc_legacy_read(struct aqc_data *priv) |
941 | { |
942 | int ret, i, sensor_value; |
943 | |
944 | mutex_lock(&priv->mutex); |
945 | |
946 | memset(priv->buffer, 0x00, priv->buffer_size); |
947 | ret = hid_hw_raw_request(hdev: priv->hdev, reportnum: priv->status_report_id, buf: priv->buffer, |
948 | len: priv->buffer_size, rtype: HID_FEATURE_REPORT, reqtype: HID_REQ_GET_REPORT); |
949 | if (ret < 0) |
950 | goto unlock_and_return; |
951 | |
952 | /* Temperature sensor readings */ |
953 | for (i = 0; i < priv->num_temp_sensors; i++) { |
954 | sensor_value = get_unaligned_le16(p: priv->buffer + priv->temp_sensor_start_offset + |
955 | i * AQC_SENSOR_SIZE); |
956 | if (sensor_value == AQC_SENSOR_NA) |
957 | priv->temp_input[i] = -ENODATA; |
958 | else |
959 | priv->temp_input[i] = sensor_value * 10; |
960 | } |
961 | |
962 | /* Special-case sensor readings */ |
963 | switch (priv->kind) { |
964 | case aquastreamxt: |
965 | /* Info provided with every report */ |
966 | priv->serial_number[0] = get_unaligned_le16(p: priv->buffer + |
967 | priv->serial_number_start_offset); |
968 | priv->firmware_version = |
969 | get_unaligned_le16(p: priv->buffer + priv->firmware_version_offset); |
970 | |
971 | /* Read pump speed in RPM */ |
972 | sensor_value = get_unaligned_le16(p: priv->buffer + priv->fan_sensor_offsets[0]); |
973 | priv->speed_input[0] = aqc_aquastreamxt_convert_pump_rpm(val: sensor_value); |
974 | |
975 | /* Read fan speed in RPM, if available */ |
976 | sensor_value = get_unaligned_le16(p: priv->buffer + AQUASTREAMXT_FAN_STATUS_OFFSET); |
977 | if (sensor_value == AQUASTREAMXT_FAN_STOPPED) { |
978 | priv->speed_input[1] = 0; |
979 | } else { |
980 | sensor_value = |
981 | get_unaligned_le16(p: priv->buffer + priv->fan_sensor_offsets[1]); |
982 | priv->speed_input[1] = aqc_aquastreamxt_convert_fan_rpm(val: sensor_value); |
983 | } |
984 | |
985 | /* Calculation derived from linear regression */ |
986 | sensor_value = get_unaligned_le16(p: priv->buffer + AQUASTREAMXT_PUMP_CURR_OFFSET); |
987 | priv->current_input[0] = DIV_ROUND_CLOSEST(sensor_value * 176, 100) - 52; |
988 | |
989 | sensor_value = get_unaligned_le16(p: priv->buffer + AQUASTREAMXT_PUMP_VOLTAGE_OFFSET); |
990 | priv->voltage_input[0] = DIV_ROUND_CLOSEST(sensor_value * 1000, 61); |
991 | |
992 | sensor_value = get_unaligned_le16(p: priv->buffer + AQUASTREAMXT_FAN_VOLTAGE_OFFSET); |
993 | priv->voltage_input[1] = DIV_ROUND_CLOSEST(sensor_value * 1000, 63); |
994 | break; |
995 | case highflow: |
996 | /* Info provided with every report */ |
997 | priv->serial_number[0] = get_unaligned_le16(p: priv->buffer + |
998 | priv->serial_number_start_offset); |
999 | priv->firmware_version = |
1000 | get_unaligned_le16(p: priv->buffer + priv->firmware_version_offset); |
1001 | |
1002 | /* Read flow speed */ |
1003 | priv->speed_input[0] = get_unaligned_le16(p: priv->buffer + |
1004 | priv->flow_sensors_start_offset); |
1005 | break; |
1006 | default: |
1007 | break; |
1008 | } |
1009 | |
1010 | priv->updated = jiffies; |
1011 | |
1012 | unlock_and_return: |
1013 | mutex_unlock(lock: &priv->mutex); |
1014 | return ret; |
1015 | } |
1016 | |
1017 | static int aqc_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, |
1018 | int channel, long *val) |
1019 | { |
1020 | int ret; |
1021 | struct aqc_data *priv = dev_get_drvdata(dev); |
1022 | |
1023 | if (time_after(jiffies, priv->updated + STATUS_UPDATE_INTERVAL)) { |
1024 | if (priv->status_report_id != 0) { |
1025 | /* Legacy devices require manual reads */ |
1026 | ret = aqc_legacy_read(priv); |
1027 | if (ret < 0) |
1028 | return -ENODATA; |
1029 | } else { |
1030 | return -ENODATA; |
1031 | } |
1032 | } |
1033 | |
1034 | switch (type) { |
1035 | case hwmon_temp: |
1036 | switch (attr) { |
1037 | case hwmon_temp_input: |
1038 | if (priv->temp_input[channel] == -ENODATA) |
1039 | return -ENODATA; |
1040 | |
1041 | *val = priv->temp_input[channel]; |
1042 | break; |
1043 | case hwmon_temp_offset: |
1044 | ret = |
1045 | aqc_get_ctrl_val(priv, offset: priv->temp_ctrl_offset + |
1046 | channel * AQC_SENSOR_SIZE, val, AQC_BE16); |
1047 | if (ret < 0) |
1048 | return ret; |
1049 | |
1050 | *val *= 10; |
1051 | break; |
1052 | default: |
1053 | break; |
1054 | } |
1055 | break; |
1056 | case hwmon_fan: |
1057 | switch (attr) { |
1058 | case hwmon_fan_input: |
1059 | if (priv->speed_input[channel] == -ENODATA) |
1060 | return -ENODATA; |
1061 | |
1062 | *val = priv->speed_input[channel]; |
1063 | break; |
1064 | case hwmon_fan_min: |
1065 | *val = priv->speed_input_min[channel]; |
1066 | break; |
1067 | case hwmon_fan_max: |
1068 | *val = priv->speed_input_max[channel]; |
1069 | break; |
1070 | case hwmon_fan_target: |
1071 | *val = priv->speed_input_target[channel]; |
1072 | break; |
1073 | case hwmon_fan_pulses: |
1074 | ret = aqc_get_ctrl_val(priv, offset: priv->flow_pulses_ctrl_offset, |
1075 | val, AQC_BE16); |
1076 | if (ret < 0) |
1077 | return ret; |
1078 | break; |
1079 | default: |
1080 | break; |
1081 | } |
1082 | break; |
1083 | case hwmon_power: |
1084 | *val = priv->power_input[channel]; |
1085 | break; |
1086 | case hwmon_pwm: |
1087 | switch (priv->kind) { |
1088 | case aquaero: |
1089 | ret = aqc_get_ctrl_val(priv, |
1090 | AQUAERO_CTRL_PRESET_START + channel * AQUAERO_CTRL_PRESET_SIZE, |
1091 | val, AQC_BE16); |
1092 | if (ret < 0) |
1093 | return ret; |
1094 | *val = aqc_percent_to_pwm(val: *val); |
1095 | break; |
1096 | default: |
1097 | ret = aqc_get_ctrl_val(priv, offset: priv->fan_ctrl_offsets[channel], |
1098 | val, AQC_BE16); |
1099 | if (ret < 0) |
1100 | return ret; |
1101 | |
1102 | *val = aqc_percent_to_pwm(val: *val); |
1103 | break; |
1104 | } |
1105 | break; |
1106 | case hwmon_in: |
1107 | *val = priv->voltage_input[channel]; |
1108 | break; |
1109 | case hwmon_curr: |
1110 | *val = priv->current_input[channel]; |
1111 | break; |
1112 | default: |
1113 | return -EOPNOTSUPP; |
1114 | } |
1115 | |
1116 | return 0; |
1117 | } |
1118 | |
1119 | static int aqc_read_string(struct device *dev, enum hwmon_sensor_types type, u32 attr, |
1120 | int channel, const char **str) |
1121 | { |
1122 | struct aqc_data *priv = dev_get_drvdata(dev); |
1123 | |
1124 | /* Number of sensors that are not calculated */ |
1125 | int num_non_calc_sensors = priv->num_temp_sensors + priv->num_virtual_temp_sensors; |
1126 | |
1127 | switch (type) { |
1128 | case hwmon_temp: |
1129 | if (channel < priv->num_temp_sensors) { |
1130 | *str = priv->temp_label[channel]; |
1131 | } else { |
1132 | if (priv->kind == aquaero && channel >= num_non_calc_sensors) |
1133 | *str = |
1134 | priv->calc_virt_temp_label[channel - num_non_calc_sensors]; |
1135 | else |
1136 | *str = priv->virtual_temp_label[channel - priv->num_temp_sensors]; |
1137 | } |
1138 | break; |
1139 | case hwmon_fan: |
1140 | *str = priv->speed_label[channel]; |
1141 | break; |
1142 | case hwmon_power: |
1143 | *str = priv->power_label[channel]; |
1144 | break; |
1145 | case hwmon_in: |
1146 | *str = priv->voltage_label[channel]; |
1147 | break; |
1148 | case hwmon_curr: |
1149 | *str = priv->current_label[channel]; |
1150 | break; |
1151 | default: |
1152 | return -EOPNOTSUPP; |
1153 | } |
1154 | |
1155 | return 0; |
1156 | } |
1157 | |
1158 | static int aqc_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, |
1159 | long val) |
1160 | { |
1161 | int ret, pwm_value; |
1162 | /* Arrays for setting multiple values at once in the control report */ |
1163 | int ctrl_values_offsets[4]; |
1164 | long ctrl_values[4]; |
1165 | int ctrl_values_types[4]; |
1166 | struct aqc_data *priv = dev_get_drvdata(dev); |
1167 | |
1168 | switch (type) { |
1169 | case hwmon_temp: |
1170 | switch (attr) { |
1171 | case hwmon_temp_offset: |
1172 | /* Limit temp offset to +/- 15K as in the official software */ |
1173 | val = clamp_val(val, -15000, 15000) / 10; |
1174 | ret = |
1175 | aqc_set_ctrl_val(priv, offset: priv->temp_ctrl_offset + |
1176 | channel * AQC_SENSOR_SIZE, val, AQC_BE16); |
1177 | if (ret < 0) |
1178 | return ret; |
1179 | break; |
1180 | default: |
1181 | return -EOPNOTSUPP; |
1182 | } |
1183 | break; |
1184 | case hwmon_fan: |
1185 | switch (attr) { |
1186 | case hwmon_fan_pulses: |
1187 | val = clamp_val(val, 10, 1000); |
1188 | ret = aqc_set_ctrl_val(priv, offset: priv->flow_pulses_ctrl_offset, |
1189 | val, AQC_BE16); |
1190 | if (ret < 0) |
1191 | return ret; |
1192 | break; |
1193 | default: |
1194 | break; |
1195 | } |
1196 | break; |
1197 | case hwmon_pwm: |
1198 | switch (attr) { |
1199 | case hwmon_pwm_input: |
1200 | pwm_value = aqc_pwm_to_percent(val); |
1201 | if (pwm_value < 0) |
1202 | return pwm_value; |
1203 | |
1204 | switch (priv->kind) { |
1205 | case aquaero: |
1206 | /* Write pwm value to preset corresponding to the channel */ |
1207 | ctrl_values_offsets[0] = AQUAERO_CTRL_PRESET_START + |
1208 | channel * AQUAERO_CTRL_PRESET_SIZE; |
1209 | ctrl_values[0] = pwm_value; |
1210 | ctrl_values_types[0] = AQC_BE16; |
1211 | |
1212 | /* Write preset number in fan control source */ |
1213 | ctrl_values_offsets[1] = priv->fan_ctrl_offsets[channel] + |
1214 | AQUAERO_FAN_CTRL_SRC_OFFSET; |
1215 | ctrl_values[1] = AQUAERO_CTRL_PRESET_ID + channel; |
1216 | ctrl_values_types[1] = AQC_BE16; |
1217 | |
1218 | /* Set minimum power to 0 to allow the fan to turn off */ |
1219 | ctrl_values_offsets[2] = priv->fan_ctrl_offsets[channel] + |
1220 | AQUAERO_FAN_CTRL_MIN_PWR_OFFSET; |
1221 | ctrl_values[2] = 0; |
1222 | ctrl_values_types[2] = AQC_BE16; |
1223 | |
1224 | /* Set maximum power to 255 to allow the fan to reach max speed */ |
1225 | ctrl_values_offsets[3] = priv->fan_ctrl_offsets[channel] + |
1226 | AQUAERO_FAN_CTRL_MAX_PWR_OFFSET; |
1227 | ctrl_values[3] = aqc_pwm_to_percent(val: 255); |
1228 | ctrl_values_types[3] = AQC_BE16; |
1229 | |
1230 | ret = aqc_set_ctrl_vals(priv, offsets: ctrl_values_offsets, vals: ctrl_values, |
1231 | types: ctrl_values_types, len: 4); |
1232 | if (ret < 0) |
1233 | return ret; |
1234 | break; |
1235 | default: |
1236 | ret = aqc_set_ctrl_val(priv, offset: priv->fan_ctrl_offsets[channel], |
1237 | val: pwm_value, AQC_BE16); |
1238 | if (ret < 0) |
1239 | return ret; |
1240 | break; |
1241 | } |
1242 | break; |
1243 | default: |
1244 | break; |
1245 | } |
1246 | break; |
1247 | default: |
1248 | return -EOPNOTSUPP; |
1249 | } |
1250 | |
1251 | return 0; |
1252 | } |
1253 | |
1254 | static const struct hwmon_ops aqc_hwmon_ops = { |
1255 | .is_visible = aqc_is_visible, |
1256 | .read = aqc_read, |
1257 | .read_string = aqc_read_string, |
1258 | .write = aqc_write |
1259 | }; |
1260 | |
1261 | static const struct hwmon_channel_info * const aqc_info[] = { |
1262 | HWMON_CHANNEL_INFO(temp, |
1263 | HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET, |
1264 | HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET, |
1265 | HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET, |
1266 | HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET, |
1267 | HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET, |
1268 | HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET, |
1269 | HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET, |
1270 | HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET, |
1271 | HWMON_T_INPUT | HWMON_T_LABEL, |
1272 | HWMON_T_INPUT | HWMON_T_LABEL, |
1273 | HWMON_T_INPUT | HWMON_T_LABEL, |
1274 | HWMON_T_INPUT | HWMON_T_LABEL, |
1275 | HWMON_T_INPUT | HWMON_T_LABEL, |
1276 | HWMON_T_INPUT | HWMON_T_LABEL, |
1277 | HWMON_T_INPUT | HWMON_T_LABEL, |
1278 | HWMON_T_INPUT | HWMON_T_LABEL, |
1279 | HWMON_T_INPUT | HWMON_T_LABEL, |
1280 | HWMON_T_INPUT | HWMON_T_LABEL, |
1281 | HWMON_T_INPUT | HWMON_T_LABEL, |
1282 | HWMON_T_INPUT | HWMON_T_LABEL), |
1283 | HWMON_CHANNEL_INFO(fan, |
1284 | HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX | |
1285 | HWMON_F_TARGET, |
1286 | HWMON_F_INPUT | HWMON_F_LABEL, |
1287 | HWMON_F_INPUT | HWMON_F_LABEL, |
1288 | HWMON_F_INPUT | HWMON_F_LABEL, |
1289 | HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_PULSES, |
1290 | HWMON_F_INPUT | HWMON_F_LABEL, |
1291 | HWMON_F_INPUT | HWMON_F_LABEL, |
1292 | HWMON_F_INPUT | HWMON_F_LABEL), |
1293 | HWMON_CHANNEL_INFO(power, |
1294 | HWMON_P_INPUT | HWMON_P_LABEL, |
1295 | HWMON_P_INPUT | HWMON_P_LABEL, |
1296 | HWMON_P_INPUT | HWMON_P_LABEL, |
1297 | HWMON_P_INPUT | HWMON_P_LABEL, |
1298 | HWMON_P_INPUT | HWMON_P_LABEL, |
1299 | HWMON_P_INPUT | HWMON_P_LABEL, |
1300 | HWMON_P_INPUT | HWMON_P_LABEL, |
1301 | HWMON_P_INPUT | HWMON_P_LABEL), |
1302 | HWMON_CHANNEL_INFO(pwm, |
1303 | HWMON_PWM_INPUT, |
1304 | HWMON_PWM_INPUT, |
1305 | HWMON_PWM_INPUT, |
1306 | HWMON_PWM_INPUT, |
1307 | HWMON_PWM_INPUT, |
1308 | HWMON_PWM_INPUT, |
1309 | HWMON_PWM_INPUT, |
1310 | HWMON_PWM_INPUT), |
1311 | HWMON_CHANNEL_INFO(in, |
1312 | HWMON_I_INPUT | HWMON_I_LABEL, |
1313 | HWMON_I_INPUT | HWMON_I_LABEL, |
1314 | HWMON_I_INPUT | HWMON_I_LABEL, |
1315 | HWMON_I_INPUT | HWMON_I_LABEL, |
1316 | HWMON_I_INPUT | HWMON_I_LABEL, |
1317 | HWMON_I_INPUT | HWMON_I_LABEL, |
1318 | HWMON_I_INPUT | HWMON_I_LABEL, |
1319 | HWMON_I_INPUT | HWMON_I_LABEL), |
1320 | HWMON_CHANNEL_INFO(curr, |
1321 | HWMON_C_INPUT | HWMON_C_LABEL, |
1322 | HWMON_C_INPUT | HWMON_C_LABEL, |
1323 | HWMON_C_INPUT | HWMON_C_LABEL, |
1324 | HWMON_C_INPUT | HWMON_C_LABEL, |
1325 | HWMON_C_INPUT | HWMON_C_LABEL, |
1326 | HWMON_C_INPUT | HWMON_C_LABEL, |
1327 | HWMON_C_INPUT | HWMON_C_LABEL, |
1328 | HWMON_C_INPUT | HWMON_C_LABEL), |
1329 | NULL |
1330 | }; |
1331 | |
1332 | static const struct hwmon_chip_info aqc_chip_info = { |
1333 | .ops = &aqc_hwmon_ops, |
1334 | .info = aqc_info, |
1335 | }; |
1336 | |
1337 | static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *data, int size) |
1338 | { |
1339 | int i, j, sensor_value; |
1340 | struct aqc_data *priv; |
1341 | |
1342 | if (report->id != STATUS_REPORT_ID) |
1343 | return 0; |
1344 | |
1345 | priv = hid_get_drvdata(hdev); |
1346 | |
1347 | /* Info provided with every report */ |
1348 | priv->serial_number[0] = get_unaligned_be16(p: data + priv->serial_number_start_offset); |
1349 | priv->serial_number[1] = get_unaligned_be16(p: data + priv->serial_number_start_offset + |
1350 | SERIAL_PART_OFFSET); |
1351 | priv->firmware_version = get_unaligned_be16(p: data + priv->firmware_version_offset); |
1352 | |
1353 | /* Physical temperature sensor readings */ |
1354 | for (i = 0; i < priv->num_temp_sensors; i++) { |
1355 | sensor_value = get_unaligned_be16(p: data + |
1356 | priv->temp_sensor_start_offset + |
1357 | i * AQC_SENSOR_SIZE); |
1358 | if (sensor_value == AQC_SENSOR_NA) |
1359 | priv->temp_input[i] = -ENODATA; |
1360 | else |
1361 | priv->temp_input[i] = sensor_value * 10; |
1362 | } |
1363 | |
1364 | /* Virtual temperature sensor readings */ |
1365 | for (j = 0; j < priv->num_virtual_temp_sensors; j++) { |
1366 | sensor_value = get_unaligned_be16(p: data + |
1367 | priv->virtual_temp_sensor_start_offset + |
1368 | j * AQC_SENSOR_SIZE); |
1369 | if (sensor_value == AQC_SENSOR_NA) |
1370 | priv->temp_input[i] = -ENODATA; |
1371 | else |
1372 | priv->temp_input[i] = sensor_value * 10; |
1373 | i++; |
1374 | } |
1375 | |
1376 | /* Fan speed and related readings */ |
1377 | for (i = 0; i < priv->num_fans; i++) { |
1378 | priv->speed_input[i] = |
1379 | get_unaligned_be16(p: data + priv->fan_sensor_offsets[i] + |
1380 | priv->fan_structure->speed); |
1381 | priv->power_input[i] = |
1382 | get_unaligned_be16(p: data + priv->fan_sensor_offsets[i] + |
1383 | priv->fan_structure->power) * 10000; |
1384 | priv->voltage_input[i] = |
1385 | get_unaligned_be16(p: data + priv->fan_sensor_offsets[i] + |
1386 | priv->fan_structure->voltage) * 10; |
1387 | priv->current_input[i] = |
1388 | get_unaligned_be16(p: data + priv->fan_sensor_offsets[i] + |
1389 | priv->fan_structure->curr); |
1390 | } |
1391 | |
1392 | /* Flow sensor readings */ |
1393 | for (j = 0; j < priv->num_flow_sensors; j++) { |
1394 | priv->speed_input[i] = get_unaligned_be16(p: data + priv->flow_sensors_start_offset + |
1395 | j * AQC_SENSOR_SIZE); |
1396 | i++; |
1397 | } |
1398 | |
1399 | if (priv->power_cycle_count_offset != 0) |
1400 | priv->power_cycles = get_unaligned_be32(p: data + priv->power_cycle_count_offset); |
1401 | |
1402 | /* Special-case sensor readings */ |
1403 | switch (priv->kind) { |
1404 | case aquaero: |
1405 | /* Read calculated virtual temp sensors */ |
1406 | i = priv->num_temp_sensors + priv->num_virtual_temp_sensors; |
1407 | for (j = 0; j < priv->num_calc_virt_temp_sensors; j++) { |
1408 | sensor_value = get_unaligned_be16(p: data + |
1409 | priv->calc_virt_temp_sensor_start_offset + |
1410 | j * AQC_SENSOR_SIZE); |
1411 | if (sensor_value == AQC_SENSOR_NA) |
1412 | priv->temp_input[i] = -ENODATA; |
1413 | else |
1414 | priv->temp_input[i] = sensor_value * 10; |
1415 | i++; |
1416 | } |
1417 | break; |
1418 | case aquastreamult: |
1419 | priv->speed_input[1] = get_unaligned_be16(p: data + AQUASTREAMULT_PUMP_OFFSET); |
1420 | priv->speed_input[2] = get_unaligned_be16(p: data + AQUASTREAMULT_PRESSURE_OFFSET); |
1421 | priv->speed_input[3] = get_unaligned_be16(p: data + AQUASTREAMULT_FLOW_SENSOR_OFFSET); |
1422 | |
1423 | priv->power_input[1] = get_unaligned_be16(p: data + AQUASTREAMULT_PUMP_POWER) * 10000; |
1424 | |
1425 | priv->voltage_input[1] = get_unaligned_be16(p: data + AQUASTREAMULT_PUMP_VOLTAGE) * 10; |
1426 | |
1427 | priv->current_input[1] = get_unaligned_be16(p: data + AQUASTREAMULT_PUMP_CURRENT); |
1428 | break; |
1429 | case d5next: |
1430 | priv->voltage_input[2] = get_unaligned_be16(p: data + D5NEXT_5V_VOLTAGE) * 10; |
1431 | priv->voltage_input[3] = get_unaligned_be16(p: data + D5NEXT_12V_VOLTAGE) * 10; |
1432 | break; |
1433 | case highflownext: |
1434 | /* If external temp sensor is not connected, its power reading is also N/A */ |
1435 | if (priv->temp_input[1] == -ENODATA) |
1436 | priv->power_input[0] = -ENODATA; |
1437 | else |
1438 | priv->power_input[0] = |
1439 | get_unaligned_be16(p: data + HIGHFLOWNEXT_POWER) * 1000000; |
1440 | |
1441 | priv->voltage_input[0] = get_unaligned_be16(p: data + HIGHFLOWNEXT_5V_VOLTAGE) * 10; |
1442 | priv->voltage_input[1] = |
1443 | get_unaligned_be16(p: data + HIGHFLOWNEXT_5V_VOLTAGE_USB) * 10; |
1444 | |
1445 | priv->speed_input[1] = get_unaligned_be16(p: data + HIGHFLOWNEXT_WATER_QUALITY); |
1446 | priv->speed_input[2] = get_unaligned_be16(p: data + HIGHFLOWNEXT_CONDUCTIVITY); |
1447 | break; |
1448 | case leakshield: |
1449 | priv->speed_input[0] = |
1450 | ((s16)get_unaligned_be16(p: data + LEAKSHIELD_PRESSURE_ADJUSTED)) * 100; |
1451 | priv->speed_input_min[0] = get_unaligned_be16(p: data + LEAKSHIELD_PRESSURE_MIN) * 100; |
1452 | priv->speed_input_target[0] = |
1453 | get_unaligned_be16(p: data + LEAKSHIELD_PRESSURE_TARGET) * 100; |
1454 | priv->speed_input_max[0] = get_unaligned_be16(p: data + LEAKSHIELD_PRESSURE_MAX) * 100; |
1455 | |
1456 | priv->speed_input[1] = get_unaligned_be16(p: data + LEAKSHIELD_PUMP_RPM_IN); |
1457 | if (priv->speed_input[1] == AQC_SENSOR_NA) |
1458 | priv->speed_input[1] = -ENODATA; |
1459 | |
1460 | priv->speed_input[2] = get_unaligned_be16(p: data + LEAKSHIELD_FLOW_IN); |
1461 | if (priv->speed_input[2] == AQC_SENSOR_NA) |
1462 | priv->speed_input[2] = -ENODATA; |
1463 | |
1464 | priv->speed_input[3] = get_unaligned_be16(p: data + LEAKSHIELD_RESERVOIR_VOLUME); |
1465 | priv->speed_input[4] = get_unaligned_be16(p: data + LEAKSHIELD_RESERVOIR_FILLED); |
1466 | |
1467 | /* Second temp sensor is not positioned after the first one, read it here */ |
1468 | priv->temp_input[1] = get_unaligned_be16(p: data + LEAKSHIELD_TEMPERATURE_2) * 10; |
1469 | break; |
1470 | default: |
1471 | break; |
1472 | } |
1473 | |
1474 | priv->updated = jiffies; |
1475 | |
1476 | return 0; |
1477 | } |
1478 | |
1479 | static int serial_number_show(struct seq_file *seqf, void *unused) |
1480 | { |
1481 | struct aqc_data *priv = seqf->private; |
1482 | |
1483 | seq_printf(m: seqf, fmt: "%05u-%05u\n" , priv->serial_number[0], priv->serial_number[1]); |
1484 | |
1485 | return 0; |
1486 | } |
1487 | DEFINE_SHOW_ATTRIBUTE(serial_number); |
1488 | |
1489 | static int firmware_version_show(struct seq_file *seqf, void *unused) |
1490 | { |
1491 | struct aqc_data *priv = seqf->private; |
1492 | |
1493 | seq_printf(m: seqf, fmt: "%u\n" , priv->firmware_version); |
1494 | |
1495 | return 0; |
1496 | } |
1497 | DEFINE_SHOW_ATTRIBUTE(firmware_version); |
1498 | |
1499 | static int power_cycles_show(struct seq_file *seqf, void *unused) |
1500 | { |
1501 | struct aqc_data *priv = seqf->private; |
1502 | |
1503 | seq_printf(m: seqf, fmt: "%u\n" , priv->power_cycles); |
1504 | |
1505 | return 0; |
1506 | } |
1507 | DEFINE_SHOW_ATTRIBUTE(power_cycles); |
1508 | |
1509 | static void aqc_debugfs_init(struct aqc_data *priv) |
1510 | { |
1511 | char name[64]; |
1512 | |
1513 | scnprintf(buf: name, size: sizeof(name), fmt: "%s_%s-%s" , "aquacomputer" , priv->name, |
1514 | dev_name(dev: &priv->hdev->dev)); |
1515 | |
1516 | priv->debugfs = debugfs_create_dir(name, NULL); |
1517 | |
1518 | if (priv->serial_number_start_offset != 0) |
1519 | debugfs_create_file(name: "serial_number" , mode: 0444, parent: priv->debugfs, data: priv, |
1520 | fops: &serial_number_fops); |
1521 | if (priv->firmware_version_offset != 0) |
1522 | debugfs_create_file(name: "firmware_version" , mode: 0444, parent: priv->debugfs, data: priv, |
1523 | fops: &firmware_version_fops); |
1524 | if (priv->power_cycle_count_offset != 0) |
1525 | debugfs_create_file(name: "power_cycles" , mode: 0444, parent: priv->debugfs, data: priv, fops: &power_cycles_fops); |
1526 | } |
1527 | |
1528 | static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id) |
1529 | { |
1530 | struct aqc_data *priv; |
1531 | int ret; |
1532 | |
1533 | priv = devm_kzalloc(dev: &hdev->dev, size: sizeof(*priv), GFP_KERNEL); |
1534 | if (!priv) |
1535 | return -ENOMEM; |
1536 | |
1537 | priv->hdev = hdev; |
1538 | hid_set_drvdata(hdev, data: priv); |
1539 | |
1540 | priv->updated = jiffies - STATUS_UPDATE_INTERVAL; |
1541 | |
1542 | ret = hid_parse(hdev); |
1543 | if (ret) |
1544 | return ret; |
1545 | |
1546 | ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW); |
1547 | if (ret) |
1548 | return ret; |
1549 | |
1550 | ret = hid_hw_open(hdev); |
1551 | if (ret) |
1552 | goto fail_and_stop; |
1553 | |
1554 | switch (hdev->product) { |
1555 | case USB_PRODUCT_ID_AQUAERO: |
1556 | /* |
1557 | * Aquaero presents itself as three HID devices under the same product ID: |
1558 | * "aquaero keyboard/mouse", "aquaero System Control" and "aquaero Device", |
1559 | * which is the one we want to communicate with. Unlike most other Aquacomputer |
1560 | * devices, Aquaero does not return meaningful data when explicitly requested |
1561 | * using GET_FEATURE_REPORT. |
1562 | * |
1563 | * The difference between "aquaero Device" and the other two is in the collections |
1564 | * they present. The two other devices have the type of the second element in |
1565 | * their respective collections set to 1, while the real device has it set to 0. |
1566 | */ |
1567 | if (hdev->collection[1].type != 0) { |
1568 | ret = -ENODEV; |
1569 | goto fail_and_close; |
1570 | } |
1571 | |
1572 | priv->kind = aquaero; |
1573 | |
1574 | priv->num_fans = AQUAERO_NUM_FANS; |
1575 | priv->fan_sensor_offsets = aquaero_sensor_fan_offsets; |
1576 | priv->fan_ctrl_offsets = aquaero_ctrl_fan_offsets; |
1577 | |
1578 | priv->num_temp_sensors = AQUAERO_NUM_SENSORS; |
1579 | priv->temp_sensor_start_offset = AQUAERO_SENSOR_START; |
1580 | priv->num_virtual_temp_sensors = AQUAERO_NUM_VIRTUAL_SENSORS; |
1581 | priv->virtual_temp_sensor_start_offset = AQUAERO_VIRTUAL_SENSOR_START; |
1582 | priv->num_calc_virt_temp_sensors = AQUAERO_NUM_CALC_VIRTUAL_SENSORS; |
1583 | priv->calc_virt_temp_sensor_start_offset = AQUAERO_CALC_VIRTUAL_SENSOR_START; |
1584 | priv->num_flow_sensors = AQUAERO_NUM_FLOW_SENSORS; |
1585 | priv->flow_sensors_start_offset = AQUAERO_FLOW_SENSORS_START; |
1586 | |
1587 | priv->buffer_size = AQUAERO_CTRL_REPORT_SIZE; |
1588 | priv->temp_ctrl_offset = AQUAERO_TEMP_CTRL_OFFSET; |
1589 | priv->ctrl_report_delay = CTRL_REPORT_DELAY; |
1590 | |
1591 | priv->temp_label = label_temp_sensors; |
1592 | priv->virtual_temp_label = label_virtual_temp_sensors; |
1593 | priv->calc_virt_temp_label = label_aquaero_calc_temp_sensors; |
1594 | priv->speed_label = label_aquaero_speeds; |
1595 | priv->power_label = label_fan_power; |
1596 | priv->voltage_label = label_fan_voltage; |
1597 | priv->current_label = label_fan_current; |
1598 | break; |
1599 | case USB_PRODUCT_ID_D5NEXT: |
1600 | priv->kind = d5next; |
1601 | |
1602 | priv->num_fans = D5NEXT_NUM_FANS; |
1603 | priv->fan_sensor_offsets = d5next_sensor_fan_offsets; |
1604 | priv->fan_ctrl_offsets = d5next_ctrl_fan_offsets; |
1605 | |
1606 | priv->num_temp_sensors = D5NEXT_NUM_SENSORS; |
1607 | priv->temp_sensor_start_offset = D5NEXT_COOLANT_TEMP; |
1608 | priv->num_virtual_temp_sensors = D5NEXT_NUM_VIRTUAL_SENSORS; |
1609 | priv->virtual_temp_sensor_start_offset = D5NEXT_VIRTUAL_SENSORS_START; |
1610 | priv->temp_ctrl_offset = D5NEXT_TEMP_CTRL_OFFSET; |
1611 | |
1612 | priv->buffer_size = D5NEXT_CTRL_REPORT_SIZE; |
1613 | priv->ctrl_report_delay = CTRL_REPORT_DELAY; |
1614 | |
1615 | priv->power_cycle_count_offset = D5NEXT_POWER_CYCLES; |
1616 | |
1617 | priv->temp_label = label_d5next_temp; |
1618 | priv->virtual_temp_label = label_virtual_temp_sensors; |
1619 | priv->speed_label = label_d5next_speeds; |
1620 | priv->power_label = label_d5next_power; |
1621 | priv->voltage_label = label_d5next_voltages; |
1622 | priv->current_label = label_d5next_current; |
1623 | break; |
1624 | case USB_PRODUCT_ID_FARBWERK: |
1625 | priv->kind = farbwerk; |
1626 | |
1627 | priv->num_fans = 0; |
1628 | |
1629 | priv->num_temp_sensors = FARBWERK_NUM_SENSORS; |
1630 | priv->temp_sensor_start_offset = FARBWERK_SENSOR_START; |
1631 | |
1632 | priv->temp_label = label_temp_sensors; |
1633 | break; |
1634 | case USB_PRODUCT_ID_FARBWERK360: |
1635 | priv->kind = farbwerk360; |
1636 | |
1637 | priv->num_fans = 0; |
1638 | |
1639 | priv->num_temp_sensors = FARBWERK360_NUM_SENSORS; |
1640 | priv->temp_sensor_start_offset = FARBWERK360_SENSOR_START; |
1641 | priv->num_virtual_temp_sensors = FARBWERK360_NUM_VIRTUAL_SENSORS; |
1642 | priv->virtual_temp_sensor_start_offset = FARBWERK360_VIRTUAL_SENSORS_START; |
1643 | priv->temp_ctrl_offset = FARBWERK360_TEMP_CTRL_OFFSET; |
1644 | |
1645 | priv->buffer_size = FARBWERK360_CTRL_REPORT_SIZE; |
1646 | |
1647 | priv->temp_label = label_temp_sensors; |
1648 | priv->virtual_temp_label = label_virtual_temp_sensors; |
1649 | break; |
1650 | case USB_PRODUCT_ID_OCTO: |
1651 | priv->kind = octo; |
1652 | |
1653 | priv->num_fans = OCTO_NUM_FANS; |
1654 | priv->fan_sensor_offsets = octo_sensor_fan_offsets; |
1655 | priv->fan_ctrl_offsets = octo_ctrl_fan_offsets; |
1656 | |
1657 | priv->num_temp_sensors = OCTO_NUM_SENSORS; |
1658 | priv->temp_sensor_start_offset = OCTO_SENSOR_START; |
1659 | priv->num_virtual_temp_sensors = OCTO_NUM_VIRTUAL_SENSORS; |
1660 | priv->virtual_temp_sensor_start_offset = OCTO_VIRTUAL_SENSORS_START; |
1661 | priv->temp_ctrl_offset = OCTO_TEMP_CTRL_OFFSET; |
1662 | |
1663 | priv->buffer_size = OCTO_CTRL_REPORT_SIZE; |
1664 | priv->ctrl_report_delay = CTRL_REPORT_DELAY; |
1665 | |
1666 | priv->power_cycle_count_offset = OCTO_POWER_CYCLES; |
1667 | |
1668 | priv->temp_label = label_temp_sensors; |
1669 | priv->virtual_temp_label = label_virtual_temp_sensors; |
1670 | priv->speed_label = label_fan_speed; |
1671 | priv->power_label = label_fan_power; |
1672 | priv->voltage_label = label_fan_voltage; |
1673 | priv->current_label = label_fan_current; |
1674 | break; |
1675 | case USB_PRODUCT_ID_QUADRO: |
1676 | priv->kind = quadro; |
1677 | |
1678 | priv->num_fans = QUADRO_NUM_FANS; |
1679 | priv->fan_sensor_offsets = quadro_sensor_fan_offsets; |
1680 | priv->fan_ctrl_offsets = quadro_ctrl_fan_offsets; |
1681 | |
1682 | priv->num_temp_sensors = QUADRO_NUM_SENSORS; |
1683 | priv->temp_sensor_start_offset = QUADRO_SENSOR_START; |
1684 | priv->num_virtual_temp_sensors = QUADRO_NUM_VIRTUAL_SENSORS; |
1685 | priv->virtual_temp_sensor_start_offset = QUADRO_VIRTUAL_SENSORS_START; |
1686 | priv->num_flow_sensors = QUADRO_NUM_FLOW_SENSORS; |
1687 | priv->flow_sensors_start_offset = QUADRO_FLOW_SENSOR_OFFSET; |
1688 | |
1689 | priv->temp_ctrl_offset = QUADRO_TEMP_CTRL_OFFSET; |
1690 | |
1691 | priv->buffer_size = QUADRO_CTRL_REPORT_SIZE; |
1692 | priv->ctrl_report_delay = CTRL_REPORT_DELAY; |
1693 | |
1694 | priv->flow_pulses_ctrl_offset = QUADRO_FLOW_PULSES_CTRL_OFFSET; |
1695 | priv->power_cycle_count_offset = QUADRO_POWER_CYCLES; |
1696 | |
1697 | priv->temp_label = label_temp_sensors; |
1698 | priv->virtual_temp_label = label_virtual_temp_sensors; |
1699 | priv->speed_label = label_quadro_speeds; |
1700 | priv->power_label = label_fan_power; |
1701 | priv->voltage_label = label_fan_voltage; |
1702 | priv->current_label = label_fan_current; |
1703 | break; |
1704 | case USB_PRODUCT_ID_HIGHFLOWNEXT: |
1705 | priv->kind = highflownext; |
1706 | |
1707 | priv->num_fans = 0; |
1708 | |
1709 | priv->num_temp_sensors = HIGHFLOWNEXT_NUM_SENSORS; |
1710 | priv->temp_sensor_start_offset = HIGHFLOWNEXT_SENSOR_START; |
1711 | priv->num_flow_sensors = HIGHFLOWNEXT_NUM_FLOW_SENSORS; |
1712 | priv->flow_sensors_start_offset = HIGHFLOWNEXT_FLOW; |
1713 | |
1714 | priv->power_cycle_count_offset = QUADRO_POWER_CYCLES; |
1715 | |
1716 | priv->temp_label = label_highflownext_temp_sensors; |
1717 | priv->speed_label = label_highflownext_fan_speed; |
1718 | priv->power_label = label_highflownext_power; |
1719 | priv->voltage_label = label_highflownext_voltage; |
1720 | break; |
1721 | case USB_PRODUCT_ID_LEAKSHIELD: |
1722 | /* |
1723 | * Choose the right Leakshield device, because |
1724 | * the other one acts as a keyboard |
1725 | */ |
1726 | if (hdev->type != 2) { |
1727 | ret = -ENODEV; |
1728 | goto fail_and_close; |
1729 | } |
1730 | |
1731 | priv->kind = leakshield; |
1732 | |
1733 | priv->num_fans = 0; |
1734 | priv->num_temp_sensors = LEAKSHIELD_NUM_SENSORS; |
1735 | priv->temp_sensor_start_offset = LEAKSHIELD_TEMPERATURE_1; |
1736 | |
1737 | priv->temp_label = label_leakshield_temp_sensors; |
1738 | priv->speed_label = label_leakshield_fan_speed; |
1739 | break; |
1740 | case USB_PRODUCT_ID_AQUASTREAMXT: |
1741 | priv->kind = aquastreamxt; |
1742 | |
1743 | priv->num_fans = AQUASTREAMXT_NUM_FANS; |
1744 | priv->fan_sensor_offsets = aquastreamxt_sensor_fan_offsets; |
1745 | |
1746 | priv->num_temp_sensors = AQUASTREAMXT_NUM_SENSORS; |
1747 | priv->temp_sensor_start_offset = AQUASTREAMXT_SENSOR_START; |
1748 | priv->buffer_size = AQUASTREAMXT_SENSOR_REPORT_SIZE; |
1749 | |
1750 | priv->temp_label = label_aquastreamxt_temp_sensors; |
1751 | priv->speed_label = label_d5next_speeds; |
1752 | priv->voltage_label = label_d5next_voltages; |
1753 | priv->current_label = label_d5next_current; |
1754 | break; |
1755 | case USB_PRODUCT_ID_AQUASTREAMULT: |
1756 | priv->kind = aquastreamult; |
1757 | |
1758 | priv->num_fans = AQUASTREAMULT_NUM_FANS; |
1759 | priv->fan_sensor_offsets = aquastreamult_sensor_fan_offsets; |
1760 | |
1761 | priv->num_temp_sensors = AQUASTREAMULT_NUM_SENSORS; |
1762 | priv->temp_sensor_start_offset = AQUASTREAMULT_SENSOR_START; |
1763 | |
1764 | priv->temp_label = label_aquastreamult_temp; |
1765 | priv->speed_label = label_aquastreamult_speeds; |
1766 | priv->power_label = label_aquastreamult_power; |
1767 | priv->voltage_label = label_aquastreamult_voltages; |
1768 | priv->current_label = label_aquastreamult_current; |
1769 | break; |
1770 | case USB_PRODUCT_ID_POWERADJUST3: |
1771 | priv->kind = poweradjust3; |
1772 | |
1773 | priv->num_fans = 0; |
1774 | |
1775 | priv->num_temp_sensors = POWERADJUST3_NUM_SENSORS; |
1776 | priv->temp_sensor_start_offset = POWERADJUST3_SENSOR_START; |
1777 | priv->buffer_size = POWERADJUST3_SENSOR_REPORT_SIZE; |
1778 | |
1779 | priv->temp_label = label_poweradjust3_temp_sensors; |
1780 | break; |
1781 | case USB_PRODUCT_ID_HIGHFLOW: |
1782 | priv->kind = highflow; |
1783 | |
1784 | priv->num_fans = 0; |
1785 | |
1786 | priv->num_temp_sensors = HIGHFLOW_NUM_SENSORS; |
1787 | priv->temp_sensor_start_offset = HIGHFLOW_SENSOR_START; |
1788 | priv->num_flow_sensors = HIGHFLOW_NUM_FLOW_SENSORS; |
1789 | priv->flow_sensors_start_offset = HIGHFLOW_FLOW_SENSOR_OFFSET; |
1790 | priv->buffer_size = HIGHFLOW_SENSOR_REPORT_SIZE; |
1791 | |
1792 | priv->temp_label = label_highflow_temp; |
1793 | priv->speed_label = label_highflow_speeds; |
1794 | break; |
1795 | default: |
1796 | break; |
1797 | } |
1798 | |
1799 | switch (priv->kind) { |
1800 | case aquaero: |
1801 | priv->serial_number_start_offset = AQUAERO_SERIAL_START; |
1802 | priv->firmware_version_offset = AQUAERO_FIRMWARE_VERSION; |
1803 | |
1804 | priv->fan_structure = &aqc_aquaero_fan_structure; |
1805 | |
1806 | priv->ctrl_report_id = AQUAERO_CTRL_REPORT_ID; |
1807 | priv->secondary_ctrl_report_id = AQUAERO_SECONDARY_CTRL_REPORT_ID; |
1808 | priv->secondary_ctrl_report_size = AQUAERO_SECONDARY_CTRL_REPORT_SIZE; |
1809 | priv->secondary_ctrl_report = aquaero_secondary_ctrl_report; |
1810 | break; |
1811 | case poweradjust3: |
1812 | priv->status_report_id = POWERADJUST3_STATUS_REPORT_ID; |
1813 | break; |
1814 | case aquastreamxt: |
1815 | priv->serial_number_start_offset = AQUASTREAMXT_SERIAL_START; |
1816 | priv->firmware_version_offset = AQUASTREAMXT_FIRMWARE_VERSION; |
1817 | |
1818 | priv->status_report_id = AQUASTREAMXT_STATUS_REPORT_ID; |
1819 | break; |
1820 | case highflow: |
1821 | priv->serial_number_start_offset = HIGHFLOW_SERIAL_START; |
1822 | priv->firmware_version_offset = HIGHFLOW_FIRMWARE_VERSION; |
1823 | |
1824 | priv->status_report_id = HIGHFLOW_STATUS_REPORT_ID; |
1825 | break; |
1826 | default: |
1827 | priv->serial_number_start_offset = AQC_SERIAL_START; |
1828 | priv->firmware_version_offset = AQC_FIRMWARE_VERSION; |
1829 | |
1830 | priv->ctrl_report_id = CTRL_REPORT_ID; |
1831 | priv->secondary_ctrl_report_id = SECONDARY_CTRL_REPORT_ID; |
1832 | priv->secondary_ctrl_report_size = SECONDARY_CTRL_REPORT_SIZE; |
1833 | priv->secondary_ctrl_report = secondary_ctrl_report; |
1834 | |
1835 | if (priv->kind == aquastreamult) |
1836 | priv->fan_structure = &aqc_aquastreamult_fan_structure; |
1837 | else |
1838 | priv->fan_structure = &aqc_general_fan_structure; |
1839 | break; |
1840 | } |
1841 | |
1842 | if (priv->buffer_size != 0) { |
1843 | priv->checksum_start = 0x01; |
1844 | priv->checksum_length = priv->buffer_size - 3; |
1845 | priv->checksum_offset = priv->buffer_size - 2; |
1846 | } |
1847 | |
1848 | priv->name = aqc_device_names[priv->kind]; |
1849 | |
1850 | priv->buffer = devm_kzalloc(dev: &hdev->dev, size: priv->buffer_size, GFP_KERNEL); |
1851 | if (!priv->buffer) { |
1852 | ret = -ENOMEM; |
1853 | goto fail_and_close; |
1854 | } |
1855 | |
1856 | mutex_init(&priv->mutex); |
1857 | |
1858 | priv->hwmon_dev = hwmon_device_register_with_info(dev: &hdev->dev, name: priv->name, drvdata: priv, |
1859 | info: &aqc_chip_info, NULL); |
1860 | |
1861 | if (IS_ERR(ptr: priv->hwmon_dev)) { |
1862 | ret = PTR_ERR(ptr: priv->hwmon_dev); |
1863 | goto fail_and_close; |
1864 | } |
1865 | |
1866 | aqc_debugfs_init(priv); |
1867 | |
1868 | return 0; |
1869 | |
1870 | fail_and_close: |
1871 | hid_hw_close(hdev); |
1872 | fail_and_stop: |
1873 | hid_hw_stop(hdev); |
1874 | return ret; |
1875 | } |
1876 | |
1877 | static void aqc_remove(struct hid_device *hdev) |
1878 | { |
1879 | struct aqc_data *priv = hid_get_drvdata(hdev); |
1880 | |
1881 | debugfs_remove_recursive(dentry: priv->debugfs); |
1882 | hwmon_device_unregister(dev: priv->hwmon_dev); |
1883 | |
1884 | hid_hw_close(hdev); |
1885 | hid_hw_stop(hdev); |
1886 | } |
1887 | |
1888 | static const struct hid_device_id aqc_table[] = { |
1889 | { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_AQUAERO) }, |
1890 | { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_D5NEXT) }, |
1891 | { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_FARBWERK) }, |
1892 | { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_FARBWERK360) }, |
1893 | { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_OCTO) }, |
1894 | { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_QUADRO) }, |
1895 | { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_HIGHFLOWNEXT) }, |
1896 | { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_LEAKSHIELD) }, |
1897 | { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_AQUASTREAMXT) }, |
1898 | { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_AQUASTREAMULT) }, |
1899 | { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_POWERADJUST3) }, |
1900 | { HID_USB_DEVICE(USB_VENDOR_ID_AQUACOMPUTER, USB_PRODUCT_ID_HIGHFLOW) }, |
1901 | { } |
1902 | }; |
1903 | |
1904 | MODULE_DEVICE_TABLE(hid, aqc_table); |
1905 | |
1906 | static struct hid_driver aqc_driver = { |
1907 | .name = DRIVER_NAME, |
1908 | .id_table = aqc_table, |
1909 | .probe = aqc_probe, |
1910 | .remove = aqc_remove, |
1911 | .raw_event = aqc_raw_event, |
1912 | }; |
1913 | |
1914 | static int __init aqc_init(void) |
1915 | { |
1916 | return hid_register_driver(&aqc_driver); |
1917 | } |
1918 | |
1919 | static void __exit aqc_exit(void) |
1920 | { |
1921 | hid_unregister_driver(&aqc_driver); |
1922 | } |
1923 | |
1924 | /* Request to initialize after the HID bus to ensure it's not being loaded before */ |
1925 | late_initcall(aqc_init); |
1926 | module_exit(aqc_exit); |
1927 | |
1928 | MODULE_LICENSE("GPL" ); |
1929 | MODULE_AUTHOR("Aleksa Savic <savicaleksa83@gmail.com>" ); |
1930 | MODULE_AUTHOR("Jack Doan <me@jackdoan.com>" ); |
1931 | MODULE_DESCRIPTION("Hwmon driver for Aquacomputer devices" ); |
1932 | |