Re: [PATCH] leds: Introduce userspace LED triggers driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Please don't apply this patch. I realised that the Documentation/leds/index.rst needs to add the new uledtriggers.rst.

I will make a patch v2 in due course. But I'd like to wait for any other feedback first.



---- On Thu, 06 Mar 2025 22:46:39 +1100 Craig McQueen  wrote ---

 > This driver creates a userspace LED triggers driver similar to 
 > uleds and uinput. 
 >  
 > New LED triggers s are created by opening /dev/uledtriggers and writing 
 > a uledtriggers_user_dev struct. A new LED trigger is registered with the 
 > name given in the struct. 
 >  
 > After the initial setup, writing an int value will set the trigger's 
 > brightness, equivalent to calling led_trigger_event(). 
 >  
 > Alternatively, there are ioctls for setup, changing trigger brightness, 
 > or doing blinking. 
 >  
 > Closing the file handle to /dev/uledtriggers will remove the LED 
 > trigger. 
 > --- 
 >  Documentation/leds/uledtriggers.rst |  36 +++ 
 >  drivers/leds/Kconfig                |   9 + 
 >  drivers/leds/Makefile               |   1 + 
 >  drivers/leds/uledtriggers.c         | 384 ++++++++++++++++++++++++++++ 
 >  include/uapi/linux/uledtriggers.h   | 123 +++++++++ 
 >  5 files changed, 553 insertions(+) 
 >  create mode 100644 Documentation/leds/uledtriggers.rst 
 >  create mode 100644 drivers/leds/uledtriggers.c 
 >  create mode 100644 include/uapi/linux/uledtriggers.h 
 >  
 > diff --git a/Documentation/leds/uledtriggers.rst b/Documentation/leds/uledtriggers.rst 
 > new file mode 100644 
 > index 000000000000..6ec5cbf8f13e 
 > --- /dev/null 
 > +++ b/Documentation/leds/uledtriggers.rst 
 > @@ -0,0 +1,36 @@ 
 > +====================== 
 > +Userspace LED Triggers 
 > +====================== 
 > + 
 > +The uledtriggers driver supports userspace LED triggers. This can be useful 
 > +to create a more flexible architecture for applications to control LEDs. 
 > + 
 > + 
 > +Usage 
 > +===== 
 > + 
 > +When the driver is loaded, a character device is created at /dev/uledtriggers. 
 > +To create a new LED trigger, open /dev/uledtriggers and write a 
 > +uledtriggers_user_dev structure to it (found in kernel public header file 
 > +linux/uledtriggers.h):: 
 > + 
 > +    #define LED_TRIGGER_MAX_NAME_SIZE 50 
 > + 
 > +    struct uledtriggers_user_dev { 
 > +    char name[LED_TRIGGER_MAX_NAME_SIZE]; 
 > +    }; 
 > + 
 > +A new LED trigger will be created with the name given. The name can consist of 
 > +alphanumeric, hyphen and underscore characters. 
 > + 
 > +After the initial setup, writing an int value will set the trigger's 
 > +brightness, equivalent to calling led_trigger_event(). 
 > + 
 > +Alternatively, there are ioctls (defined in the public header file) for setup, 
 > +changing trigger brightness, or doing blinking. 
 > + 
 > +The LED trigger will be removed when the open file handle to /dev/uledtriggers 
 > +is closed. 
 > + 
 > +Multiple LED triggers are created by opening additional file handles to 
 > +/dev/uledtriggers. 
 > diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig 
 > index 2b27d043921c..7cd2fbcb1aa5 100644 
 > --- a/drivers/leds/Kconfig 
 > +++ b/drivers/leds/Kconfig 
 > @@ -921,6 +921,15 @@ config LEDS_USER 
 >        support in kernel. To compile this driver as a module, choose 'm' here: 
 >        the module will be called uleds. 
 >  
 > +config LED_TRIGGERS_USER 
 > +    tristate "Userspace LED triggers support" 
 > +    depends on LEDS_CLASS 
 > +    select LEDS_TRIGGERS 
 > +    help 
 > +      This option enables support for userspace LED triggers. Say 'y' to enable 
 > +      this support in kernel. To compile this driver as a module, choose 'm' 
 > +      here: the module will be called uledtriggers. 
 > + 
 >  config LEDS_NIC78BX 
 >      tristate "LED support for NI PXI NIC78bx devices" 
 >      depends on LEDS_CLASS 
 > diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile 
 > index 6ad52e219ec6..c71569a59b15 100644 
 > --- a/drivers/leds/Makefile 
 > +++ b/drivers/leds/Makefile 
 > @@ -108,6 +108,7 @@ obj-$(CONFIG_LEDS_SPI_BYTE)        += leds-spi-byte.o 
 >  
 >  # LED Userspace Drivers 
 >  obj-$(CONFIG_LEDS_USER)            += uleds.o 
 > +obj-$(CONFIG_LED_TRIGGERS_USER)            += uledtriggers.o 
 >  
 >  # Flash and Torch LED Drivers 
 >  obj-$(CONFIG_LEDS_CLASS_FLASH)        += flash/ 
 > diff --git a/drivers/leds/uledtriggers.c b/drivers/leds/uledtriggers.c 
 > new file mode 100644 
 > index 000000000000..4fdb8cf4c82d 
 > --- /dev/null 
 > +++ b/drivers/leds/uledtriggers.c 
 > @@ -0,0 +1,384 @@ 
 > +// SPDX-License-Identifier: GPL-2.0-or-later 
 > +/* 
 > + * Userspace LED triggers driver 
 > + * 
 > + * Copyright (C) 2025 Craig McQueen craig@xxxxxxxxxx> 
 > + */ 
 > +#include  
 > +#include  
 > +#include  
 > +#include  
 > +#include  
 > +#include  
 > + 
 > +#include  
 > + 
 > +#define ULEDTRIGGERS_NAME    "uledtriggers" 
 > + 
 > +enum uledtriggers_state { 
 > +    ULEDTRIGGERS_STATE_UNKNOWN, 
 > +    ULEDTRIGGERS_STATE_REGISTERED, 
 > +}; 
 > + 
 > +enum uledtriggers_trig_state { 
 > +    TRIG_STATE_EVENT, 
 > +    TRIG_STATE_BLINK, 
 > +}; 
 > + 
 > +struct uledtriggers_device { 
 > +    struct uledtriggers_user_dev    user_dev; 
 > +    struct led_trigger    led_trigger; 
 > +    struct mutex        mutex; 
 > +    enum uledtriggers_state    state; 
 > +    enum uledtriggers_trig_state    trig_state; 
 > +    int            brightness; 
 > +    unsigned long        trig_delay_on; 
 > +    unsigned long        trig_delay_off; 
 > +}; 
 > + 
 > +static struct miscdevice uledtriggers_misc; 
 > + 
 > +static int set_led_trigger(struct uledtriggers_device *udev) 
 > +{ 
 > +    int retval = 0; 
 > +    enum uledtriggers_trig_state trig_state; 
 > + 
 > +    retval = mutex_lock_interruptible(&udev->mutex); 
 > +    if (retval) 
 > +        return retval; 
 > + 
 > +    trig_state = udev->trig_state; 
 > +    switch (trig_state) { 
 > +    default: 
 > +    case TRIG_STATE_EVENT: 
 > +        led_trigger_event(&udev->led_trigger, udev->brightness); 
 > +        break; 
 > +    case TRIG_STATE_BLINK: 
 > +        led_trigger_blink(&udev->led_trigger, udev->trig_delay_on, udev->trig_delay_off); 
 > +        break; 
 > +    } 
 > +    mutex_unlock(&udev->mutex); 
 > + 
 > +    return retval; 
 > +} 
 > + 
 > +/* 
 > + * When an LED is connected to the trigger, this 'activate' function runs and 
 > + * sets the initial state of the LED. 
 > + */ 
 > +static int uledtriggers_trig_activate(struct led_classdev *led_cdev) 
 > +{ 
 > +    struct led_trigger        *trig; 
 > +    struct uledtriggers_device    *udev; 
 > + 
 > +    trig = led_cdev->trigger; 
 > +    udev = container_of(trig, struct uledtriggers_device, led_trigger); 
 > +    return set_led_trigger(udev); 
 > +} 
 > + 
 > +static int uledtriggers_open(struct inode *inode, struct file *file) 
 > +{ 
 > +    struct uledtriggers_device *udev; 
 > + 
 > +    udev = kzalloc(sizeof(*udev), GFP_KERNEL); 
 > +    if (!udev) 
 > +        return -ENOMEM; 
 > + 
 > +    mutex_init(&udev->mutex); 
 > +    udev->state = ULEDTRIGGERS_STATE_UNKNOWN; 
 > + 
 > +    file->private_data = udev; 
 > +    stream_open(inode, file); 
 > + 
 > +    return 0; 
 > +} 
 > + 
 > +/* 
 > + * Name validation: Allow only alphanumeric, hyphen or underscore. 
 > + */ 
 > +static bool is_trigger_name_valid(const char * name) 
 > +{ 
 > +    size_t i; 
 > + 
 > +    if (name[0] == '\0') 
 > +        return false; 
 > + 
 > +    for (i = 0; i < TRIG_NAME_MAX; i++) { 
 > +        if (name[i] == '\0') 
 > +            break; 
 > +        if (!isalnum(name[i]) && name[i] != '-' && name[i] != '_') 
 > +            return false; 
 > +    } 
 > +    /* Length check. */ 
 > +    return (i < TRIG_NAME_MAX); 
 > +} 
 > + 
 > +static int dev_setup(struct uledtriggers_device *udev, const char __user *buffer) 
 > +{ 
 > +    const char *name; 
 > +    int retval; 
 > + 
 > +    retval = mutex_lock_interruptible(&udev->mutex); 
 > +    if (retval) 
 > +        return retval; 
 > + 
 > +    if (udev->state == ULEDTRIGGERS_STATE_REGISTERED) { 
 > +        retval = -EBUSY; 
 > +        goto out; 
 > +    } 
 > + 
 > +    if (copy_from_user(&udev->user_dev, buffer, 
 > +               sizeof(struct uledtriggers_user_dev))) { 
 > +        retval = -EFAULT; 
 > +        goto out; 
 > +    } 
 > + 
 > +    name = udev->user_dev.name; 
 > +    if (!is_trigger_name_valid(name)) { 
 > +        retval = -EINVAL; 
 > +        goto out; 
 > +    } 
 > + 
 > +    udev->led_trigger.name = udev->user_dev.name; 
 > +    udev->led_trigger.activate = uledtriggers_trig_activate; 
 > +    retval = led_trigger_register(&udev->led_trigger); 
 > +    if (retval < 0) { 
 > +        udev->led_trigger.name = NULL; 
 > +        goto out; 
 > +    } 
 > + 
 > +    udev->state = ULEDTRIGGERS_STATE_REGISTERED; 
 > + 
 > +out: 
 > +    mutex_unlock(&udev->mutex); 
 > + 
 > +    return retval; 
 > +} 
 > + 
 > +static int write_brightness(struct uledtriggers_device *udev, const char __user *buffer) 
 > +{ 
 > +    int retval; 
 > +    int brightness; 
 > + 
 > +    retval = mutex_lock_interruptible(&udev->mutex); 
 > +    if (retval) 
 > +        return retval; 
 > + 
 > +    if (udev->state != ULEDTRIGGERS_STATE_REGISTERED) { 
 > +        retval = -EBUSY; 
 > +        goto out; 
 > +    } 
 > + 
 > +    if (copy_from_user(&brightness, buffer, 
 > +               sizeof(brightness))) { 
 > +        retval = -EFAULT; 
 > +        goto out; 
 > +    } 
 > + 
 > +    udev->trig_delay_on = 0u; 
 > +    udev->trig_delay_off = 0u; 
 > +    udev->brightness = brightness; 
 > +    udev->trig_state = TRIG_STATE_EVENT; 
 > +    led_trigger_event(&udev->led_trigger, brightness); 
 > + 
 > +out: 
 > +    mutex_unlock(&udev->mutex); 
 > + 
 > +    return retval; 
 > +} 
 > + 
 > +static ssize_t uledtriggers_write(struct file *file, const char __user *buffer, 
 > +    size_t count, loff_t *ppos) 
 > +{ 
 > +    struct uledtriggers_device *udev = file->private_data; 
 > +    int retval; 
 > + 
 > +    if (count == 0) 
 > +        return 0; 
 > + 
 > +    switch (udev->state) { 
 > +    case ULEDTRIGGERS_STATE_UNKNOWN: 
 > +        if (count != sizeof(struct uledtriggers_user_dev)) { 
 > +            return -EINVAL; 
 > +        } 
 > +        retval = dev_setup(udev, buffer); 
 > +        if (retval < 0) 
 > +            return retval; 
 > +        return count; 
 > +    case ULEDTRIGGERS_STATE_REGISTERED: 
 > +        if (count != sizeof(int)) { 
 > +            return -EINVAL; 
 > +        } 
 > +        retval = write_brightness(udev, buffer); 
 > +        if (retval < 0) 
 > +            return retval; 
 > +        return count; 
 > +    default: 
 > +        return -EBADFD; 
 > +    } 
 > +} 
 > + 
 > +static long uledtriggers_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 
 > +{ 
 > +    struct uledtriggers_device *udev = file->private_data; 
 > +    struct uledtriggers_blink blink; 
 > +    struct uledtriggers_blink_oneshot blink_oneshot; 
 > +    int brightness; 
 > +    int retval = 0; 
 > + 
 > +    /* 
 > +     * the direction is a bitmask, and VERIFY_WRITE catches R/W 
 > +     * transfers. `Direction' is user-oriented, while 
 > +     * access_ok is kernel-oriented, so the concept of "read" and 
 > +     * "write" is reversed 
 > +     */ 
 > +    retval = 0; 
 > +    if (_IOC_DIR(cmd) & _IOC_READ) 
 > +        retval = !access_ok((void __user *)arg, _IOC_SIZE(cmd)); 
 > +    else if (_IOC_DIR(cmd) & _IOC_WRITE) 
 > +        retval = !access_ok((void __user *)arg, _IOC_SIZE(cmd)); 
 > +    if (retval) 
 > +        return -EFAULT; 
 > + 
 > +    switch (cmd) { 
 > +    case ULEDTRIGGERS_IOC_DEV_SETUP: 
 > +        retval = dev_setup(udev, (const char __user *)arg); 
 > +        break; 
 > + 
 > +    case ULEDTRIGGERS_IOC_OFF: 
 > +        retval = mutex_lock_interruptible(&udev->mutex); 
 > +        if (retval) 
 > +            return retval; 
 > +        if (udev->state != ULEDTRIGGERS_STATE_REGISTERED) { 
 > +            mutex_unlock(&udev->mutex); 
 > +            return -EINVAL; 
 > +        } 
 > +        udev->trig_delay_on = 0u; 
 > +        udev->trig_delay_off = 0u; 
 > +        udev->brightness = 0; 
 > +        udev->trig_state = TRIG_STATE_EVENT; 
 > +        led_trigger_event(&udev->led_trigger, LED_OFF); 
 > +        mutex_unlock(&udev->mutex); 
 > +        break; 
 > + 
 > +    case ULEDTRIGGERS_IOC_ON: 
 > +        retval = mutex_lock_interruptible(&udev->mutex); 
 > +        if (retval) 
 > +            return retval; 
 > +        if (udev->state != ULEDTRIGGERS_STATE_REGISTERED) { 
 > +            mutex_unlock(&udev->mutex); 
 > +            return -EINVAL; 
 > +        } 
 > +        udev->trig_delay_on = 0u; 
 > +        udev->trig_delay_off = 0u; 
 > +        udev->brightness = LED_FULL; 
 > +        udev->trig_state = TRIG_STATE_EVENT; 
 > +        led_trigger_event(&udev->led_trigger, LED_FULL); 
 > +        mutex_unlock(&udev->mutex); 
 > +        break; 
 > + 
 > +    case ULEDTRIGGERS_IOC_EVENT: 
 > +        retval = copy_from_user(&brightness, 
 > +            (int __user *)arg, 
 > +            sizeof(brightness)); 
 > +        if (retval) 
 > +            return retval; 
 > +        retval = mutex_lock_interruptible(&udev->mutex); 
 > +        if (retval) 
 > +            return retval; 
 > +        if (udev->state != ULEDTRIGGERS_STATE_REGISTERED) { 
 > +            mutex_unlock(&udev->mutex); 
 > +            return -EINVAL; 
 > +        } 
 > +        udev->trig_delay_on = 0u; 
 > +        udev->trig_delay_off = 0u; 
 > +        udev->brightness = brightness; 
 > +        udev->trig_state = TRIG_STATE_EVENT; 
 > +        led_trigger_event(&udev->led_trigger, brightness); 
 > +        mutex_unlock(&udev->mutex); 
 > +        break; 
 > + 
 > +    case ULEDTRIGGERS_IOC_BLINK: 
 > +        retval = copy_from_user(&blink, 
 > +            (struct uledtriggers_blink __user *)arg, 
 > +            sizeof(blink)); 
 > +        if (retval) 
 > +            return retval; 
 > +        retval = mutex_lock_interruptible(&udev->mutex); 
 > +        if (retval) 
 > +            return retval; 
 > +        if (udev->state != ULEDTRIGGERS_STATE_REGISTERED) { 
 > +            mutex_unlock(&udev->mutex); 
 > +            return -EINVAL; 
 > +        } 
 > +        udev->trig_delay_on = blink.delay_on; 
 > +        udev->trig_delay_off = blink.delay_off; 
 > +        udev->brightness = LED_FULL; 
 > +        udev->trig_state = TRIG_STATE_BLINK; 
 > +        led_trigger_blink(&udev->led_trigger, blink.delay_on, blink.delay_off); 
 > +        mutex_unlock(&udev->mutex); 
 > +        break; 
 > + 
 > +    case ULEDTRIGGERS_IOC_BLINK_ONESHOT: 
 > +        retval = copy_from_user(&blink_oneshot, 
 > +            (struct uledtriggers_blink_oneshot __user *)arg, 
 > +            sizeof(blink_oneshot)); 
 > +        if (retval) 
 > +            return retval; 
 > +        if (blink_oneshot.__unused) 
 > +            return -EINVAL; 
 > +        retval = mutex_lock_interruptible(&udev->mutex); 
 > +        if (retval) 
 > +            return retval; 
 > +        if (udev->state != ULEDTRIGGERS_STATE_REGISTERED) { 
 > +            mutex_unlock(&udev->mutex); 
 > +            return -EINVAL; 
 > +        } 
 > +        udev->trig_delay_on = 0u; 
 > +        udev->trig_delay_off = 0u; 
 > +        udev->brightness = blink_oneshot.invert ? LED_FULL : LED_OFF; 
 > +        udev->trig_state = TRIG_STATE_EVENT; 
 > +        led_trigger_blink_oneshot(&udev->led_trigger, blink_oneshot.delay_on, blink_oneshot.delay_off, blink_oneshot.invert); 
 > +        mutex_unlock(&udev->mutex); 
 > +        break; 
 > + 
 > +    default: 
 > +        retval = -ENOIOCTLCMD; 
 > +        break; 
 > +    } 
 > + 
 > +    return retval; 
 > +} 
 > + 
 > +static int uledtriggers_release(struct inode *inode, struct file *file) 
 > +{ 
 > +    struct uledtriggers_device *udev = file->private_data; 
 > + 
 > +    if (udev->state == ULEDTRIGGERS_STATE_REGISTERED) { 
 > +        udev->state = ULEDTRIGGERS_STATE_UNKNOWN; 
 > +        led_trigger_unregister(&udev->led_trigger); 
 > +    } 
 > +    kfree(udev); 
 > + 
 > +    return 0; 
 > +} 
 > + 
 > +static const struct file_operations uledtriggers_fops = { 
 > +    .owner        = THIS_MODULE, 
 > +    .open        = uledtriggers_open, 
 > +    .release    = uledtriggers_release, 
 > +    .write        = uledtriggers_write, 
 > +    .unlocked_ioctl    = uledtriggers_ioctl, 
 > +}; 
 > + 
 > +static struct miscdevice uledtriggers_misc = { 
 > +    .fops        = &uledtriggers_fops, 
 > +    .minor        = MISC_DYNAMIC_MINOR, 
 > +    .name        = ULEDTRIGGERS_NAME, 
 > +}; 
 > + 
 > +module_misc_device(uledtriggers_misc); 
 > + 
 > +MODULE_AUTHOR("Craig McQueen craig@xxxxxxxxxx>"); 
 > +MODULE_DESCRIPTION("Userspace LED triggers driver"); 
 > +MODULE_LICENSE("GPL"); 
 > diff --git a/include/uapi/linux/uledtriggers.h b/include/uapi/linux/uledtriggers.h 
 > new file mode 100644 
 > index 000000000000..251fa0a31861 
 > --- /dev/null 
 > +++ b/include/uapi/linux/uledtriggers.h 
 > @@ -0,0 +1,123 @@ 
 > +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ 
 > +/* 
 > + * Userspace LED triggers driver support 
 > + * 
 > + * This program is free software; you can redistribute it and/or modify 
 > + * it under the terms of the GNU General Public License as published by 
 > + * the Free Software Foundation; either version 2 of the License, or 
 > + * (at your option) any later version. 
 > + * 
 > + * This program is distributed in the hope that it will be useful, 
 > + * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 > + * GNU General Public License for more details. 
 > + */ 
 > +#ifndef _UAPI__ULEDTRIGGERS_H_ 
 > +#define _UAPI__ULEDTRIGGERS_H_ 
 > + 
 > +/* See TRIG_NAME_MAX in linux/leds.h */ 
 > +#define LED_TRIGGER_MAX_NAME_SIZE    50 
 > + 
 > +/* 
 > + * Struct for initial write to setup, or ioctl ULEDTREGGERS_IOC_DEV_SETUP. 
 > + */ 
 > +struct uledtriggers_user_dev { 
 > +    char name[LED_TRIGGER_MAX_NAME_SIZE]; 
 > +}; 
 > + 
 > +/* 
 > + * Brightness levels for writes of int values, or for use with ULEDTRIGGERS_IOC_EVENT. 
 > + * These correspond to Linux kernel internal enum led_brightness in linux/leds.h. 
 > + */ 
 > +enum uledtriggers_brightness { 
 > +    ULEDTRIGGERS_OFF        = 0, 
 > +    ULEDTRIGGERS_ON            = 1, 
 > +    ULEDTRIGGERS_HALF        = 127, 
 > +    ULEDTRIGGERS_FULL        = 255, 
 > +}; 
 > + 
 > +/* 
 > + * Struct for ioctl ULEDTRIGGERS_IOC_BLINK. 
 > + */ 
 > +struct uledtriggers_blink { 
 > +    unsigned long delay_on; 
 > +    unsigned long delay_off; 
 > +}; 
 > + 
 > +/* 
 > + * Struct for ioctl ULEDTRIGGERS_IOC_BLINK_ONESHOT. 
 > + * Note padding at the end due to alignment (for 64-bit kernels). Ensure it's set to 0. 
 > + */ 
 > +struct uledtriggers_blink_oneshot { 
 > +    unsigned long delay_on; 
 > +    unsigned long delay_off; 
 > +    int invert; 
 > +    int __unused; 
 > +}; 
 > + 
 > + 
 > +/* ioctl commands */ 
 > + 
 > +#define ULEDTRIGGERS_IOC_MAGIC            't' 
 > + 
 > +/* 
 > + * Initial setup. 
 > + * E.g.: 
 > + *    int retval; 
 > + *    struct uledtriggers_user_dev dev_setup = { "transmogrifier" }; 
 > + *    retval = ioctl(fd, ULEDTRIGGERS_IOC_DEV_SETUP, &dev_setup); 
 > + */ 
 > +#define ULEDTRIGGERS_IOC_DEV_SETUP    _IOW(ULEDTRIGGERS_IOC_MAGIC, 0x01, struct uledtriggers_user_dev) 
 > + 
 > +/* 
 > + * Turn the trigger off. 
 > + * E.g.: 
 > + *    int retval; 
 > + *    retval = ioctl(fd, ULEDTRIGGERS_IOC_OFF); 
 > + */ 
 > +#define ULEDTRIGGERS_IOC_OFF        _IO(ULEDTRIGGERS_IOC_MAGIC, 0x10) 
 > + 
 > +/* 
 > + * Turn the trigger on. 
 > + * E.g.: 
 > + *    int retval; 
 > + *    retval = ioctl(fd, ULEDTRIGGERS_IOC_ON); 
 > + */ 
 > +#define ULEDTRIGGERS_IOC_ON        _IO(ULEDTRIGGERS_IOC_MAGIC, 0x11) 
 > + 
 > +/* 
 > + * Set the LED trigger to a specified brightness. 
 > + * Refer to enum uledtriggers_brightness. 
 > + * E.g.: 
 > + *    int retval; 
 > + *    int brightness = ULEDTRIGGERS_FULL; 
 > + *    retval = ioctl(fd, ULEDTRIGGERS_IOC_EVENT, &brightness); 
 > + */ 
 > +#define ULEDTRIGGERS_IOC_EVENT        _IOW(ULEDTRIGGERS_IOC_MAGIC, 0x12, int) 
 > + 
 > +/* 
 > + * Set the LED trigger to blink continuously. 
 > + * E.g.: 
 > + *    int retval; 
 > + *    struct uledtriggers_blink blink; 
 > + *      blink.delay_on = 100; 
 > + *      blink.delay_off = 400; 
 > + *    retval = ioctl(fd, ULEDTRIGGERS_IOC_BLINK, &blink); 
 > + */ 
 > +#define ULEDTRIGGERS_IOC_BLINK        _IOW(ULEDTRIGGERS_IOC_MAGIC, 0x20, struct uledtriggers_blink) 
 > + 
 > +/* 
 > + * Set the LED trigger to blink once. 
 > + * E.g.: 
 > + *    int retval; 
 > + *    struct uledtriggers_blink_oneshot blink_oneshot; 
 > + *      blink_oneshot.delay_on = 100; 
 > + *      blink_oneshot.delay_off = 400; 
 > + *      blink_oneshot.invert = false; 
 > + *      blink_oneshot.__unused = 0; 
 > + *    retval = ioctl(fd, ULEDTRIGGERS_IOC_BLINK_ONESHOT, &blink_oneshot); 
 > + */ 
 > +#define ULEDTRIGGERS_IOC_BLINK_ONESHOT    _IOW(ULEDTRIGGERS_IOC_MAGIC, 0x21, struct uledtriggers_blink_oneshot) 
 > + 
 > + 
 > +#endif /* _UAPI__ULEDTRIGGERS_H_ */ 
 > -- 
 > 2.48.1 
 >  
 >  
 > 






[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux