1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * hwmon driver for Gigabyte AORUS Waterforce AIO CPU coolers: X240, X280 and X360. 4 * 5 * Copyright 2023 Aleksa Savic <savicaleksa83@gmail.com> 6 */ 7 8 #include <linux/debugfs.h> 9 #include <linux/hid.h> 10 #include <linux/hwmon.h> 11 #include <linux/jiffies.h> 12 #include <linux/module.h> 13 #include <linux/spinlock.h> 14 #include <linux/unaligned.h> 15 16 #define DRIVER_NAME "gigabyte_waterforce" 17 18 #define USB_VENDOR_ID_GIGABYTE 0x1044 19 #define USB_PRODUCT_ID_WATERFORCE 0x7a4d /* Gigabyte AORUS WATERFORCE X240, X280 and X360 */ 20 21 #define STATUS_VALIDITY (2 * 1000) /* ms */ 22 #define MAX_REPORT_LENGTH 6144 23 24 #define WATERFORCE_TEMP_SENSOR 0xD 25 #define WATERFORCE_FAN_SPEED 0x02 26 #define WATERFORCE_PUMP_SPEED 0x05 27 #define WATERFORCE_FAN_DUTY 0x08 28 #define WATERFORCE_PUMP_DUTY 0x09 29 30 /* Control commands, inner offsets and lengths */ 31 static const u8 get_status_cmd[] = { 0x99, 0xDA }; 32 33 #define FIRMWARE_VER_START_OFFSET_1 2 34 #define FIRMWARE_VER_START_OFFSET_2 3 35 static const u8 get_firmware_ver_cmd[] = { 0x99, 0xD6 }; 36 37 /* Command lengths */ 38 #define GET_STATUS_CMD_LENGTH 2 39 #define GET_FIRMWARE_VER_CMD_LENGTH 2 40 41 static const char *const waterforce_temp_label[] = { 42 "Coolant temp" 43 }; 44 45 static const char *const waterforce_speed_label[] = { 46 "Fan speed", 47 "Pump speed" 48 }; 49 50 struct waterforce_data { 51 struct hid_device *hdev; 52 struct device *hwmon_dev; 53 struct dentry *debugfs; 54 /* For locking access to buffer */ 55 struct mutex buffer_lock; 56 /* For queueing multiple readers */ 57 struct mutex status_report_request_mutex; 58 /* For reinitializing the completion below */ 59 spinlock_t status_report_request_lock; 60 struct completion status_report_received; 61 struct completion fw_version_processed; 62 63 /* Sensor data */ 64 s32 temp_input[1]; 65 u16 speed_input[2]; /* Fan and pump speed in RPM */ 66 u8 duty_input[2]; /* Fan and pump duty in 0-100% */ 67 68 u8 *buffer; 69 int firmware_version; 70 unsigned long updated; /* jiffies */ 71 }; 72 73 static umode_t waterforce_is_visible(const void *data, 74 enum hwmon_sensor_types type, u32 attr, int channel) 75 { 76 switch (type) { 77 case hwmon_temp: 78 switch (attr) { 79 case hwmon_temp_label: 80 case hwmon_temp_input: 81 return 0444; 82 default: 83 break; 84 } 85 break; 86 case hwmon_fan: 87 switch (attr) { 88 case hwmon_fan_label: 89 case hwmon_fan_input: 90 return 0444; 91 default: 92 break; 93 } 94 break; 95 case hwmon_pwm: 96 switch (attr) { 97 case hwmon_pwm_input: 98 return 0444; 99 default: 100 break; 101 } 102 break; 103 default: 104 break; 105 } 106 107 return 0; 108 } 109 110 /* Writes the command to the device with the rest of the report filled with zeroes */ 111 static int waterforce_write_expanded(struct waterforce_data *priv, const u8 *cmd, int cmd_length) 112 { 113 int ret; 114 115 mutex_lock(&priv->buffer_lock); 116 117 memcpy_and_pad(priv->buffer, MAX_REPORT_LENGTH, cmd, cmd_length, 0x00); 118 ret = hid_hw_output_report(priv->hdev, priv->buffer, MAX_REPORT_LENGTH); 119 120 mutex_unlock(&priv->buffer_lock); 121 return ret; 122 } 123 124 static int waterforce_get_status(struct waterforce_data *priv) 125 { 126 int ret = mutex_lock_interruptible(&priv->status_report_request_mutex); 127 128 if (ret < 0) 129 return ret; 130 131 if (!time_after(jiffies, priv->updated + msecs_to_jiffies(STATUS_VALIDITY))) { 132 /* Data is up to date */ 133 goto unlock_and_return; 134 } 135 136 /* 137 * Disable raw event parsing for a moment to safely reinitialize the 138 * completion. Reinit is done because hidraw could have triggered 139 * the raw event parsing and marked the priv->status_report_received 140 * completion as done. 141 */ 142 spin_lock_bh(&priv->status_report_request_lock); 143 reinit_completion(&priv->status_report_received); 144 spin_unlock_bh(&priv->status_report_request_lock); 145 146 /* Send command for getting status */ 147 ret = waterforce_write_expanded(priv, get_status_cmd, GET_STATUS_CMD_LENGTH); 148 if (ret < 0) 149 goto unlock_and_return; 150 151 ret = wait_for_completion_interruptible_timeout(&priv->status_report_received, 152 msecs_to_jiffies(STATUS_VALIDITY)); 153 if (ret == 0) 154 ret = -ETIMEDOUT; 155 156 unlock_and_return: 157 mutex_unlock(&priv->status_report_request_mutex); 158 if (ret < 0) 159 return ret; 160 161 return 0; 162 } 163 164 static int waterforce_read(struct device *dev, enum hwmon_sensor_types type, 165 u32 attr, int channel, long *val) 166 { 167 struct waterforce_data *priv = dev_get_drvdata(dev); 168 int ret = waterforce_get_status(priv); 169 170 if (ret < 0) 171 return ret; 172 173 switch (type) { 174 case hwmon_temp: 175 *val = priv->temp_input[channel]; 176 break; 177 case hwmon_fan: 178 *val = priv->speed_input[channel]; 179 break; 180 case hwmon_pwm: 181 switch (attr) { 182 case hwmon_pwm_input: 183 *val = DIV_ROUND_CLOSEST(priv->duty_input[channel] * 255, 100); 184 break; 185 default: 186 return -EOPNOTSUPP; 187 } 188 break; 189 default: 190 return -EOPNOTSUPP; /* unreachable */ 191 } 192 193 return 0; 194 } 195 196 static int waterforce_read_string(struct device *dev, enum hwmon_sensor_types type, 197 u32 attr, int channel, const char **str) 198 { 199 switch (type) { 200 case hwmon_temp: 201 *str = waterforce_temp_label[channel]; 202 break; 203 case hwmon_fan: 204 *str = waterforce_speed_label[channel]; 205 break; 206 default: 207 return -EOPNOTSUPP; /* unreachable */ 208 } 209 210 return 0; 211 } 212 213 static int waterforce_get_fw_ver(struct hid_device *hdev) 214 { 215 struct waterforce_data *priv = hid_get_drvdata(hdev); 216 int ret; 217 218 ret = waterforce_write_expanded(priv, get_firmware_ver_cmd, GET_FIRMWARE_VER_CMD_LENGTH); 219 if (ret < 0) 220 return ret; 221 222 ret = wait_for_completion_interruptible_timeout(&priv->fw_version_processed, 223 msecs_to_jiffies(STATUS_VALIDITY)); 224 if (ret == 0) 225 return -ETIMEDOUT; 226 else if (ret < 0) 227 return ret; 228 229 return 0; 230 } 231 232 static const struct hwmon_ops waterforce_hwmon_ops = { 233 .is_visible = waterforce_is_visible, 234 .read = waterforce_read, 235 .read_string = waterforce_read_string 236 }; 237 238 static const struct hwmon_channel_info *waterforce_info[] = { 239 HWMON_CHANNEL_INFO(temp, 240 HWMON_T_INPUT | HWMON_T_LABEL), 241 HWMON_CHANNEL_INFO(fan, 242 HWMON_F_INPUT | HWMON_F_LABEL, 243 HWMON_F_INPUT | HWMON_F_LABEL), 244 HWMON_CHANNEL_INFO(pwm, 245 HWMON_PWM_INPUT, 246 HWMON_PWM_INPUT), 247 NULL 248 }; 249 250 static const struct hwmon_chip_info waterforce_chip_info = { 251 .ops = &waterforce_hwmon_ops, 252 .info = waterforce_info, 253 }; 254 255 static int waterforce_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *data, 256 int size) 257 { 258 struct waterforce_data *priv = hid_get_drvdata(hdev); 259 260 if (data[0] == get_firmware_ver_cmd[0] && data[1] == get_firmware_ver_cmd[1]) { 261 /* Received a firmware version report */ 262 priv->firmware_version = 263 data[FIRMWARE_VER_START_OFFSET_1] * 10 + data[FIRMWARE_VER_START_OFFSET_2]; 264 265 if (!completion_done(&priv->fw_version_processed)) 266 complete_all(&priv->fw_version_processed); 267 return 0; 268 } 269 270 if (data[0] != get_status_cmd[0] || data[1] != get_status_cmd[1]) 271 return 0; 272 273 priv->temp_input[0] = data[WATERFORCE_TEMP_SENSOR] * 1000; 274 priv->speed_input[0] = get_unaligned_le16(data + WATERFORCE_FAN_SPEED); 275 priv->speed_input[1] = get_unaligned_le16(data + WATERFORCE_PUMP_SPEED); 276 priv->duty_input[0] = data[WATERFORCE_FAN_DUTY]; 277 priv->duty_input[1] = data[WATERFORCE_PUMP_DUTY]; 278 279 spin_lock(&priv->status_report_request_lock); 280 if (!completion_done(&priv->status_report_received)) 281 complete_all(&priv->status_report_received); 282 spin_unlock(&priv->status_report_request_lock); 283 284 priv->updated = jiffies; 285 286 return 0; 287 } 288 289 static int firmware_version_show(struct seq_file *seqf, void *unused) 290 { 291 struct waterforce_data *priv = seqf->private; 292 293 seq_printf(seqf, "%u\n", priv->firmware_version); 294 295 return 0; 296 } 297 DEFINE_SHOW_ATTRIBUTE(firmware_version); 298 299 static void waterforce_debugfs_init(struct waterforce_data *priv) 300 { 301 char name[64]; 302 303 if (!priv->firmware_version) 304 return; /* There's nothing to show in debugfs */ 305 306 scnprintf(name, sizeof(name), "%s-%s", DRIVER_NAME, dev_name(&priv->hdev->dev)); 307 308 priv->debugfs = debugfs_create_dir(name, NULL); 309 debugfs_create_file("firmware_version", 0444, priv->debugfs, priv, &firmware_version_fops); 310 } 311 312 static int waterforce_probe(struct hid_device *hdev, const struct hid_device_id *id) 313 { 314 struct waterforce_data *priv; 315 int ret; 316 317 priv = devm_kzalloc(&hdev->dev, sizeof(*priv), GFP_KERNEL); 318 if (!priv) 319 return -ENOMEM; 320 321 priv->hdev = hdev; 322 hid_set_drvdata(hdev, priv); 323 324 /* 325 * Initialize priv->updated to STATUS_VALIDITY seconds in the past, making 326 * the initial empty data invalid for waterforce_read() without the need for 327 * a special case there. 328 */ 329 priv->updated = jiffies - msecs_to_jiffies(STATUS_VALIDITY); 330 331 ret = hid_parse(hdev); 332 if (ret) { 333 hid_err(hdev, "hid parse failed with %d\n", ret); 334 return ret; 335 } 336 337 /* 338 * Enable hidraw so existing user-space tools can continue to work. 339 */ 340 ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW); 341 if (ret) { 342 hid_err(hdev, "hid hw start failed with %d\n", ret); 343 return ret; 344 } 345 346 ret = hid_hw_open(hdev); 347 if (ret) { 348 hid_err(hdev, "hid hw open failed with %d\n", ret); 349 goto fail_and_stop; 350 } 351 352 priv->buffer = devm_kzalloc(&hdev->dev, MAX_REPORT_LENGTH, GFP_KERNEL); 353 if (!priv->buffer) { 354 ret = -ENOMEM; 355 goto fail_and_close; 356 } 357 358 mutex_init(&priv->status_report_request_mutex); 359 mutex_init(&priv->buffer_lock); 360 spin_lock_init(&priv->status_report_request_lock); 361 init_completion(&priv->status_report_received); 362 init_completion(&priv->fw_version_processed); 363 364 hid_device_io_start(hdev); 365 ret = waterforce_get_fw_ver(hdev); 366 if (ret < 0) 367 hid_warn(hdev, "fw version request failed with %d\n", ret); 368 369 priv->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, "waterforce", 370 priv, &waterforce_chip_info, NULL); 371 if (IS_ERR(priv->hwmon_dev)) { 372 ret = PTR_ERR(priv->hwmon_dev); 373 hid_err(hdev, "hwmon registration failed with %d\n", ret); 374 goto fail_and_close; 375 } 376 377 waterforce_debugfs_init(priv); 378 379 return 0; 380 381 fail_and_close: 382 hid_hw_close(hdev); 383 fail_and_stop: 384 hid_hw_stop(hdev); 385 return ret; 386 } 387 388 static void waterforce_remove(struct hid_device *hdev) 389 { 390 struct waterforce_data *priv = hid_get_drvdata(hdev); 391 392 debugfs_remove_recursive(priv->debugfs); 393 hwmon_device_unregister(priv->hwmon_dev); 394 395 hid_hw_close(hdev); 396 hid_hw_stop(hdev); 397 } 398 399 static const struct hid_device_id waterforce_table[] = { 400 { HID_USB_DEVICE(USB_VENDOR_ID_GIGABYTE, USB_PRODUCT_ID_WATERFORCE) }, 401 { } 402 }; 403 404 MODULE_DEVICE_TABLE(hid, waterforce_table); 405 406 static struct hid_driver waterforce_driver = { 407 .name = "waterforce", 408 .id_table = waterforce_table, 409 .probe = waterforce_probe, 410 .remove = waterforce_remove, 411 .raw_event = waterforce_raw_event, 412 }; 413 414 static int __init waterforce_init(void) 415 { 416 return hid_register_driver(&waterforce_driver); 417 } 418 419 static void __exit waterforce_exit(void) 420 { 421 hid_unregister_driver(&waterforce_driver); 422 } 423 424 /* When compiled into the kernel, initialize after the HID bus */ 425 late_initcall(waterforce_init); 426 module_exit(waterforce_exit); 427 428 MODULE_LICENSE("GPL"); 429 MODULE_AUTHOR("Aleksa Savic <savicaleksa83@gmail.com>"); 430 MODULE_DESCRIPTION("Hwmon driver for Gigabyte AORUS Waterforce AIO coolers"); 431