From 3caece4ff394938f7544b994d35e784e2ce617cb Mon Sep 17 00:00:00 2001 From: John Ogness Date: Fri, 15 Feb 2019 11:10:09 +0106 Subject: [PATCH 6/7] hello: add led toggling via leds subsystem Signed-off-by: John Ogness --- hello.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/hello.c b/hello.c index c42c75f..f9809f3 100644 --- a/hello.c +++ b/hello.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "hello.h" struct hello_dev { @@ -14,6 +15,10 @@ struct hello_dev { struct cdev cdev; unsigned int minor; void __iomem *mem; + + struct led_classdev led_heartbeat; + struct led_classdev led_net; + struct led_classdev led_disk; }; #define HELLO_MAX_DEVICES 10 @@ -125,6 +130,67 @@ static const struct file_operations hello_fops = { .unlocked_ioctl = hello_ioctl, }; +static void set_brightness(struct hello_dev *hello, int offset, + enum led_brightness b) +{ + if (b) + writeb(0xff, hello->mem + offset); + else + writeb(0, hello->mem + offset); +} + +static enum led_brightness get_brightness(struct hello_dev *hello, int offset) +{ + if (readb(hello->mem + offset)) + return 1; + return 0; +} + +static void hello_led_heartbeat_set(struct led_classdev *ldev, + enum led_brightness b) +{ + struct hello_dev *hello = container_of(ldev, struct hello_dev, + led_heartbeat); + set_brightness(hello, 0, b); +} + +static enum led_brightness hello_led_heartbeat_get(struct led_classdev *ldev) +{ + struct hello_dev *hello = container_of(ldev, struct hello_dev, + led_heartbeat); + return get_brightness(hello, 0); +} + +static void hello_led_net_set(struct led_classdev *ldev, + enum led_brightness b) +{ + struct hello_dev *hello = container_of(ldev, struct hello_dev, + led_net); + set_brightness(hello, 1, b); +} + +static enum led_brightness hello_led_net_get(struct led_classdev *ldev) +{ + struct hello_dev *hello = container_of(ldev, struct hello_dev, + led_net); + return get_brightness(hello, 1); +} + +static void hello_led_disk_set(struct led_classdev *ldev, + enum led_brightness b) +{ + struct hello_dev *hello = container_of(ldev, struct hello_dev, + led_disk); + set_brightness(hello, 2, b); +} + +static enum led_brightness hello_led_disk_get(struct led_classdev *ldev) +{ + struct hello_dev *hello = container_of(ldev, struct hello_dev, + led_disk); + return get_brightness(hello, 2); +} + static int hello_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct hello_dev *hello; @@ -193,6 +259,27 @@ static int hello_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_cdev; } + hello->led_heartbeat.name = "heartbeat"; + hello->led_heartbeat.brightness = get_brightness(hello, 0); + hello->led_heartbeat.max_brightness = 1; + hello->led_heartbeat.brightness_set = hello_led_heartbeat_set; + hello->led_heartbeat.brightness_get = hello_led_heartbeat_get; + led_classdev_register(&pdev->dev, &hello->led_heartbeat); + + hello->led_net.name = "net"; + hello->led_net.brightness = get_brightness(hello, 2); + hello->led_net.max_brightness = 1; + hello->led_net.brightness_set = hello_led_net_set; + hello->led_net.brightness_get = hello_led_net_get; + led_classdev_register(&pdev->dev, &hello->led_net); + + hello->led_disk.name = "disk"; + hello->led_disk.brightness = get_brightness(hello, 2); + hello->led_disk.max_brightness = 1; + hello->led_disk.brightness_set = hello_led_disk_set; + hello->led_disk.brightness_get = hello_led_disk_get; + led_classdev_register(&pdev->dev, &hello->led_disk); + dev_info(&pdev->dev, "HELLO! I am hello device %d!\n", hello->minor); return 0; @@ -214,6 +301,9 @@ static void hello_remove(struct pci_dev *pdev) { struct hello_dev *hello = pci_get_drvdata(pdev); + led_classdev_unregister(&hello->led_disk); + led_classdev_unregister(&hello->led_net); + led_classdev_unregister(&hello->led_heartbeat); device_destroy(hello_class, MKDEV(MAJOR(hello_devt), hello->minor)); cdev_del(&hello->cdev); pci_iounmap(pdev, hello->mem); -- 2.11.0