root/drivers/hid/hid-gt683r.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gt683r_brightness_set
  2. mode_show
  3. mode_store
  4. gt683r_led_snd_msg
  5. gt683r_leds_set
  6. gt683r_mode_set
  7. gt683r_led_work
  8. gt683r_led_probe
  9. gt683r_led_remove

   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         &gt683r_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");

/* [<][>][^][v][top][bottom][index][help] */