1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * MSI GT683R led driver 4 * 5 * Copyright (c) 2014 Janne Kanniainen <janne.kanniainen@gmail.com> 6 */ 7 8 #include <linux/device.h> 9 #include <linux/hid.h> 10 #include <linux/kernel.h> 11 #include <linux/leds.h> 12 #include <linux/module.h> 13 14 #include "hid-ids.h" 15 16 #define GT683R_BUFFER_SIZE 8 17 18 /* 19 * GT683R_LED_OFF: all LEDs are off 20 * GT683R_LED_AUDIO: LEDs brightness depends on sound level 21 * GT683R_LED_BREATHING: LEDs brightness varies at human breathing rate 22 * GT683R_LED_NORMAL: LEDs are fully on when enabled 23 */ 24 enum gt683r_led_mode { 25 GT683R_LED_OFF = 0, 26 GT683R_LED_AUDIO = 2, 27 GT683R_LED_BREATHING = 3, 28 GT683R_LED_NORMAL = 5 29 }; 30 31 enum gt683r_panels { 32 GT683R_LED_BACK = 0, 33 GT683R_LED_SIDE = 1, 34 GT683R_LED_FRONT = 2, 35 GT683R_LED_COUNT, 36 }; 37 38 static const char * const gt683r_panel_names[] = { 39 "back", 40 "side", 41 "front", 42 }; 43 44 struct gt683r_led { 45 struct hid_device *hdev; 46 struct led_classdev led_devs[GT683R_LED_COUNT]; 47 struct mutex lock; 48 struct work_struct work; 49 enum led_brightness brightnesses[GT683R_LED_COUNT]; 50 enum gt683r_led_mode mode; 51 }; 52 53 static const struct hid_device_id gt683r_led_id[] = { 54 { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) }, 55 { } 56 }; 57 58 static void gt683r_brightness_set(struct led_classdev *led_cdev, 59 enum led_brightness brightness) 60 { 61 int i; 62 struct device *dev = led_cdev->dev->parent; 63 struct hid_device *hdev = to_hid_device(dev); 64 struct gt683r_led *led = hid_get_drvdata(hdev); 65 66 for (i = 0; i < GT683R_LED_COUNT; i++) { 67 if (led_cdev == &led->led_devs[i]) 68 break; 69 } 70 71 if (i < GT683R_LED_COUNT) { 72 led->brightnesses[i] = brightness; 73 schedule_work(&led->work); 74 } 75 } 76 77 static ssize_t mode_show(struct device *dev, 78 struct device_attribute *attr, 79 char *buf) 80 { 81 u8 sysfs_mode; 82 struct hid_device *hdev = to_hid_device(dev->parent); 83 struct gt683r_led *led = hid_get_drvdata(hdev); 84 85 if (led->mode == GT683R_LED_NORMAL) 86 sysfs_mode = 0; 87 else if (led->mode == GT683R_LED_AUDIO) 88 sysfs_mode = 1; 89 else 90 sysfs_mode = 2; 91 92 return scnprintf(buf, PAGE_SIZE, "%u\n", sysfs_mode); 93 } 94 95 static ssize_t mode_store(struct device *dev, 96 struct device_attribute *attr, 97 const char *buf, size_t count) 98 { 99 u8 sysfs_mode; 100 struct hid_device *hdev = to_hid_device(dev->parent); 101 struct gt683r_led *led = hid_get_drvdata(hdev); 102 103 104 if (kstrtou8(buf, 10, &sysfs_mode) || sysfs_mode > 2) 105 return -EINVAL; 106 107 mutex_lock(&led->lock); 108 109 if (sysfs_mode == 0) 110 led->mode = GT683R_LED_NORMAL; 111 else if (sysfs_mode == 1) 112 led->mode = GT683R_LED_AUDIO; 113 else 114 led->mode = GT683R_LED_BREATHING; 115 116 mutex_unlock(&led->lock); 117 schedule_work(&led->work); 118 119 return count; 120 } 121 122 static int gt683r_led_snd_msg(struct gt683r_led *led, u8 *msg) 123 { 124 int ret; 125 126 ret = hid_hw_raw_request(led->hdev, msg[0], msg, GT683R_BUFFER_SIZE, 127 HID_FEATURE_REPORT, HID_REQ_SET_REPORT); 128 if (ret != GT683R_BUFFER_SIZE) { 129 hid_err(led->hdev, 130 "failed to send set report request: %i\n", ret); 131 if (ret < 0) 132 return ret; 133 return -EIO; 134 } 135 136 return 0; 137 } 138 139 static int gt683r_leds_set(struct gt683r_led *led, u8 leds) 140 { 141 int ret; 142 u8 *buffer; 143 144 buffer = kzalloc(GT683R_BUFFER_SIZE, GFP_KERNEL); 145 if (!buffer) 146 return -ENOMEM; 147 148 buffer[0] = 0x01; 149 buffer[1] = 0x02; 150 buffer[2] = 0x30; 151 buffer[3] = leds; 152 ret = gt683r_led_snd_msg(led, buffer); 153 154 kfree(buffer); 155 return ret; 156 } 157 158 static int gt683r_mode_set(struct gt683r_led *led, u8 mode) 159 { 160 int ret; 161 u8 *buffer; 162 163 buffer = kzalloc(GT683R_BUFFER_SIZE, GFP_KERNEL); 164 if (!buffer) 165 return -ENOMEM; 166 167 buffer[0] = 0x01; 168 buffer[1] = 0x02; 169 buffer[2] = 0x20; 170 buffer[3] = mode; 171 buffer[4] = 0x01; 172 ret = gt683r_led_snd_msg(led, buffer); 173 174 kfree(buffer); 175 return ret; 176 } 177 178 static void gt683r_led_work(struct work_struct *work) 179 { 180 int i; 181 u8 leds = 0; 182 u8 mode; 183 struct gt683r_led *led = container_of(work, struct gt683r_led, work); 184 185 mutex_lock(&led->lock); 186 187 for (i = 0; i < GT683R_LED_COUNT; i++) { 188 if (led->brightnesses[i]) 189 leds |= BIT(i); 190 } 191 192 if (gt683r_leds_set(led, leds)) 193 goto fail; 194 195 if (leds) 196 mode = led->mode; 197 else 198 mode = GT683R_LED_OFF; 199 200 gt683r_mode_set(led, mode); 201 fail: 202 mutex_unlock(&led->lock); 203 } 204 205 static DEVICE_ATTR_RW(mode); 206 207 static struct attribute *gt683r_led_attrs[] = { 208 &dev_attr_mode.attr, 209 NULL 210 }; 211 212 static const struct attribute_group gt683r_led_group = { 213 .name = "gt683r", 214 .attrs = gt683r_led_attrs, 215 }; 216 217 static const struct attribute_group *gt683r_led_groups[] = { 218 >683r_led_group, 219 NULL 220 }; 221 222 static int gt683r_led_probe(struct hid_device *hdev, 223 const struct hid_device_id *id) 224 { 225 int i; 226 int ret; 227 int name_sz; 228 char *name; 229 struct gt683r_led *led; 230 231 led = devm_kzalloc(&hdev->dev, sizeof(*led), GFP_KERNEL); 232 if (!led) 233 return -ENOMEM; 234 235 mutex_init(&led->lock); 236 INIT_WORK(&led->work, gt683r_led_work); 237 238 led->mode = GT683R_LED_NORMAL; 239 led->hdev = hdev; 240 hid_set_drvdata(hdev, led); 241 242 ret = hid_parse(hdev); 243 if (ret) { 244 hid_err(hdev, "hid parsing failed\n"); 245 return ret; 246 } 247 248 ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW); 249 if (ret) { 250 hid_err(hdev, "hw start failed\n"); 251 return ret; 252 } 253 254 for (i = 0; i < GT683R_LED_COUNT; i++) { 255 name_sz = strlen(dev_name(&hdev->dev)) + 256 strlen(gt683r_panel_names[i]) + 3; 257 258 name = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL); 259 if (!name) { 260 ret = -ENOMEM; 261 goto fail; 262 } 263 264 snprintf(name, name_sz, "%s::%s", 265 dev_name(&hdev->dev), gt683r_panel_names[i]); 266 led->led_devs[i].name = name; 267 led->led_devs[i].max_brightness = 1; 268 led->led_devs[i].brightness_set = gt683r_brightness_set; 269 led->led_devs[i].groups = gt683r_led_groups; 270 271 ret = led_classdev_register(&hdev->dev, &led->led_devs[i]); 272 if (ret) { 273 hid_err(hdev, "could not register led device\n"); 274 goto fail; 275 } 276 } 277 278 return 0; 279 280 fail: 281 for (i = i - 1; i >= 0; i--) 282 led_classdev_unregister(&led->led_devs[i]); 283 hid_hw_stop(hdev); 284 return ret; 285 } 286 287 static void gt683r_led_remove(struct hid_device *hdev) 288 { 289 int i; 290 struct gt683r_led *led = hid_get_drvdata(hdev); 291 292 for (i = 0; i < GT683R_LED_COUNT; i++) 293 led_classdev_unregister(&led->led_devs[i]); 294 flush_work(&led->work); 295 hid_hw_stop(hdev); 296 } 297 298 static struct hid_driver gt683r_led_driver = { 299 .probe = gt683r_led_probe, 300 .remove = gt683r_led_remove, 301 .name = "gt683r_led", 302 .id_table = gt683r_led_id, 303 }; 304 305 module_hid_driver(gt683r_led_driver); 306 307 MODULE_AUTHOR("Janne Kanniainen"); 308 MODULE_DESCRIPTION("MSI GT683R led driver"); 309 MODULE_LICENSE("GPL"); 310