• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
gt683r_brightness_set(struct led_classdev * led_cdev,enum led_brightness brightness)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 
mode_show(struct device * dev,struct device_attribute * attr,char * buf)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 
mode_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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 
gt683r_led_snd_msg(struct gt683r_led * led,u8 * msg)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 
gt683r_leds_set(struct gt683r_led * led,u8 leds)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 
gt683r_mode_set(struct gt683r_led * led,u8 mode)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 
gt683r_led_work(struct work_struct * work)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 
gt683r_led_probe(struct hid_device * hdev,const struct hid_device_id * id)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 
gt683r_led_remove(struct hid_device * hdev)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");
310