root/drivers/hid/hid-picolcd_leds.c

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

DEFINITIONS

This source file includes following definitions.
  1. picolcd_leds_set
  2. picolcd_led_set_brightness
  3. picolcd_led_get_brightness
  4. picolcd_init_leds
  5. picolcd_exit_leds

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /***************************************************************************
   3  *   Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org>  *
   4  *                                                                         *
   5  *   Based on Logitech G13 driver (v0.4)                                   *
   6  *     Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu>   *
   7  *                                                                         *
   8  ***************************************************************************/
   9 
  10 #include <linux/hid.h>
  11 #include <linux/hid-debug.h>
  12 #include <linux/input.h>
  13 #include "hid-ids.h"
  14 
  15 #include <linux/fb.h>
  16 #include <linux/vmalloc.h>
  17 #include <linux/backlight.h>
  18 #include <linux/lcd.h>
  19 
  20 #include <linux/leds.h>
  21 
  22 #include <linux/seq_file.h>
  23 #include <linux/debugfs.h>
  24 
  25 #include <linux/completion.h>
  26 #include <linux/uaccess.h>
  27 #include <linux/module.h>
  28 
  29 #include "hid-picolcd.h"
  30 
  31 
  32 void picolcd_leds_set(struct picolcd_data *data)
  33 {
  34         struct hid_report *report;
  35         unsigned long flags;
  36 
  37         if (!data->led[0])
  38                 return;
  39         report = picolcd_out_report(REPORT_LED_STATE, data->hdev);
  40         if (!report || report->maxfield != 1 || report->field[0]->report_count != 1)
  41                 return;
  42 
  43         spin_lock_irqsave(&data->lock, flags);
  44         hid_set_field(report->field[0], 0, data->led_state);
  45         if (!(data->status & PICOLCD_FAILED))
  46                 hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
  47         spin_unlock_irqrestore(&data->lock, flags);
  48 }
  49 
  50 static void picolcd_led_set_brightness(struct led_classdev *led_cdev,
  51                         enum led_brightness value)
  52 {
  53         struct device *dev;
  54         struct hid_device *hdev;
  55         struct picolcd_data *data;
  56         int i, state = 0;
  57 
  58         dev  = led_cdev->dev->parent;
  59         hdev = to_hid_device(dev);
  60         data = hid_get_drvdata(hdev);
  61         if (!data)
  62                 return;
  63         for (i = 0; i < 8; i++) {
  64                 if (led_cdev != data->led[i])
  65                         continue;
  66                 state = (data->led_state >> i) & 1;
  67                 if (value == LED_OFF && state) {
  68                         data->led_state &= ~(1 << i);
  69                         picolcd_leds_set(data);
  70                 } else if (value != LED_OFF && !state) {
  71                         data->led_state |= 1 << i;
  72                         picolcd_leds_set(data);
  73                 }
  74                 break;
  75         }
  76 }
  77 
  78 static enum led_brightness picolcd_led_get_brightness(struct led_classdev *led_cdev)
  79 {
  80         struct device *dev;
  81         struct hid_device *hdev;
  82         struct picolcd_data *data;
  83         int i, value = 0;
  84 
  85         dev  = led_cdev->dev->parent;
  86         hdev = to_hid_device(dev);
  87         data = hid_get_drvdata(hdev);
  88         for (i = 0; i < 8; i++)
  89                 if (led_cdev == data->led[i]) {
  90                         value = (data->led_state >> i) & 1;
  91                         break;
  92                 }
  93         return value ? LED_FULL : LED_OFF;
  94 }
  95 
  96 int picolcd_init_leds(struct picolcd_data *data, struct hid_report *report)
  97 {
  98         struct device *dev = &data->hdev->dev;
  99         struct led_classdev *led;
 100         size_t name_sz = strlen(dev_name(dev)) + 8;
 101         char *name;
 102         int i, ret = 0;
 103 
 104         if (!report)
 105                 return -ENODEV;
 106         if (report->maxfield != 1 || report->field[0]->report_count != 1 ||
 107                         report->field[0]->report_size != 8) {
 108                 dev_err(dev, "unsupported LED_STATE report");
 109                 return -EINVAL;
 110         }
 111 
 112         for (i = 0; i < 8; i++) {
 113                 led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL);
 114                 if (!led) {
 115                         dev_err(dev, "can't allocate memory for LED %d\n", i);
 116                         ret = -ENOMEM;
 117                         goto err;
 118                 }
 119                 name = (void *)(&led[1]);
 120                 snprintf(name, name_sz, "%s::GPO%d", dev_name(dev), i);
 121                 led->name = name;
 122                 led->brightness = 0;
 123                 led->max_brightness = 1;
 124                 led->brightness_get = picolcd_led_get_brightness;
 125                 led->brightness_set = picolcd_led_set_brightness;
 126 
 127                 data->led[i] = led;
 128                 ret = led_classdev_register(dev, data->led[i]);
 129                 if (ret) {
 130                         data->led[i] = NULL;
 131                         kfree(led);
 132                         dev_err(dev, "can't register LED %d\n", i);
 133                         goto err;
 134                 }
 135         }
 136         return 0;
 137 err:
 138         for (i = 0; i < 8; i++)
 139                 if (data->led[i]) {
 140                         led = data->led[i];
 141                         data->led[i] = NULL;
 142                         led_classdev_unregister(led);
 143                         kfree(led);
 144                 }
 145         return ret;
 146 }
 147 
 148 void picolcd_exit_leds(struct picolcd_data *data)
 149 {
 150         struct led_classdev *led;
 151         int i;
 152 
 153         for (i = 0; i < 8; i++) {
 154                 led = data->led[i];
 155                 data->led[i] = NULL;
 156                 if (!led)
 157                         continue;
 158                 led_classdev_unregister(led);
 159                 kfree(led);
 160         }
 161 }
 162 
 163 

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