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