summaryrefslogtreecommitdiff
path: root/schulung_tools/drivers/modules/hellodriver/patches-leds/0005-hello-add-led-toggling-via-leds-subsystem.patch
blob: 32f37ce0dbaa0c124f60db3a2d420ff89a45c06b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
From 3caece4ff394938f7544b994d35e784e2ce617cb Mon Sep 17 00:00:00 2001
From: John Ogness <john.ogness@linutronix.de>
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 <john.ogness@linutronix.de>
---
 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 <linux/device.h>
 #include <linux/pci.h>
 #include <linux/cdev.h>
+#include <linux/leds.h>
 #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