Merge tag 'md-fixes-20230914' of https://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / drivers / hid / hid-roccat-arvo.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Roccat Arvo driver for Linux
4  *
5  * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net>
6  */
7
8 /*
9  */
10
11 /*
12  * Roccat Arvo is a gamer keyboard with 5 macro keys that can be configured in
13  * 5 profiles.
14  */
15
16 #include <linux/device.h>
17 #include <linux/input.h>
18 #include <linux/hid.h>
19 #include <linux/module.h>
20 #include <linux/slab.h>
21 #include <linux/hid-roccat.h>
22 #include "hid-ids.h"
23 #include "hid-roccat-common.h"
24 #include "hid-roccat-arvo.h"
25
26 static ssize_t arvo_sysfs_show_mode_key(struct device *dev,
27                 struct device_attribute *attr, char *buf)
28 {
29         struct arvo_device *arvo =
30                         hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
31         struct usb_device *usb_dev =
32                         interface_to_usbdev(to_usb_interface(dev->parent->parent));
33         struct arvo_mode_key temp_buf;
34         int retval;
35
36         mutex_lock(&arvo->arvo_lock);
37         retval = roccat_common2_receive(usb_dev, ARVO_COMMAND_MODE_KEY,
38                         &temp_buf, sizeof(struct arvo_mode_key));
39         mutex_unlock(&arvo->arvo_lock);
40         if (retval)
41                 return retval;
42
43         return sysfs_emit(buf, "%d\n", temp_buf.state);
44 }
45
46 static ssize_t arvo_sysfs_set_mode_key(struct device *dev,
47                 struct device_attribute *attr, char const *buf, size_t size)
48 {
49         struct arvo_device *arvo =
50                         hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
51         struct usb_device *usb_dev =
52                         interface_to_usbdev(to_usb_interface(dev->parent->parent));
53         struct arvo_mode_key temp_buf;
54         unsigned long state;
55         int retval;
56
57         retval = kstrtoul(buf, 10, &state);
58         if (retval)
59                 return retval;
60
61         temp_buf.command = ARVO_COMMAND_MODE_KEY;
62         temp_buf.state = state;
63
64         mutex_lock(&arvo->arvo_lock);
65         retval = roccat_common2_send(usb_dev, ARVO_COMMAND_MODE_KEY,
66                         &temp_buf, sizeof(struct arvo_mode_key));
67         mutex_unlock(&arvo->arvo_lock);
68         if (retval)
69                 return retval;
70
71         return size;
72 }
73 static DEVICE_ATTR(mode_key, 0660,
74                    arvo_sysfs_show_mode_key, arvo_sysfs_set_mode_key);
75
76 static ssize_t arvo_sysfs_show_key_mask(struct device *dev,
77                 struct device_attribute *attr, char *buf)
78 {
79         struct arvo_device *arvo =
80                         hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
81         struct usb_device *usb_dev =
82                         interface_to_usbdev(to_usb_interface(dev->parent->parent));
83         struct arvo_key_mask temp_buf;
84         int retval;
85
86         mutex_lock(&arvo->arvo_lock);
87         retval = roccat_common2_receive(usb_dev, ARVO_COMMAND_KEY_MASK,
88                         &temp_buf, sizeof(struct arvo_key_mask));
89         mutex_unlock(&arvo->arvo_lock);
90         if (retval)
91                 return retval;
92
93         return sysfs_emit(buf, "%d\n", temp_buf.key_mask);
94 }
95
96 static ssize_t arvo_sysfs_set_key_mask(struct device *dev,
97                 struct device_attribute *attr, char const *buf, size_t size)
98 {
99         struct arvo_device *arvo =
100                         hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
101         struct usb_device *usb_dev =
102                         interface_to_usbdev(to_usb_interface(dev->parent->parent));
103         struct arvo_key_mask temp_buf;
104         unsigned long key_mask;
105         int retval;
106
107         retval = kstrtoul(buf, 10, &key_mask);
108         if (retval)
109                 return retval;
110
111         temp_buf.command = ARVO_COMMAND_KEY_MASK;
112         temp_buf.key_mask = key_mask;
113
114         mutex_lock(&arvo->arvo_lock);
115         retval = roccat_common2_send(usb_dev, ARVO_COMMAND_KEY_MASK,
116                         &temp_buf, sizeof(struct arvo_key_mask));
117         mutex_unlock(&arvo->arvo_lock);
118         if (retval)
119                 return retval;
120
121         return size;
122 }
123 static DEVICE_ATTR(key_mask, 0660,
124                    arvo_sysfs_show_key_mask, arvo_sysfs_set_key_mask);
125
126 /* retval is 1-5 on success, < 0 on error */
127 static int arvo_get_actual_profile(struct usb_device *usb_dev)
128 {
129         struct arvo_actual_profile temp_buf;
130         int retval;
131
132         retval = roccat_common2_receive(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE,
133                         &temp_buf, sizeof(struct arvo_actual_profile));
134
135         if (retval)
136                 return retval;
137
138         return temp_buf.actual_profile;
139 }
140
141 static ssize_t arvo_sysfs_show_actual_profile(struct device *dev,
142                 struct device_attribute *attr, char *buf)
143 {
144         struct arvo_device *arvo =
145                         hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
146
147         return sysfs_emit(buf, "%d\n", arvo->actual_profile);
148 }
149
150 static ssize_t arvo_sysfs_set_actual_profile(struct device *dev,
151                 struct device_attribute *attr, char const *buf, size_t size)
152 {
153         struct arvo_device *arvo =
154                         hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
155         struct usb_device *usb_dev =
156                         interface_to_usbdev(to_usb_interface(dev->parent->parent));
157         struct arvo_actual_profile temp_buf;
158         unsigned long profile;
159         int retval;
160
161         retval = kstrtoul(buf, 10, &profile);
162         if (retval)
163                 return retval;
164
165         if (profile < 1 || profile > 5)
166                 return -EINVAL;
167
168         temp_buf.command = ARVO_COMMAND_ACTUAL_PROFILE;
169         temp_buf.actual_profile = profile;
170
171         mutex_lock(&arvo->arvo_lock);
172         retval = roccat_common2_send(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE,
173                         &temp_buf, sizeof(struct arvo_actual_profile));
174         if (!retval) {
175                 arvo->actual_profile = profile;
176                 retval = size;
177         }
178         mutex_unlock(&arvo->arvo_lock);
179         return retval;
180 }
181 static DEVICE_ATTR(actual_profile, 0660,
182                    arvo_sysfs_show_actual_profile,
183                    arvo_sysfs_set_actual_profile);
184
185 static ssize_t arvo_sysfs_write(struct file *fp,
186                 struct kobject *kobj, void const *buf,
187                 loff_t off, size_t count, size_t real_size, uint command)
188 {
189         struct device *dev = kobj_to_dev(kobj)->parent->parent;
190         struct arvo_device *arvo = hid_get_drvdata(dev_get_drvdata(dev));
191         struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
192         int retval;
193
194         if (off != 0 || count != real_size)
195                 return -EINVAL;
196
197         mutex_lock(&arvo->arvo_lock);
198         retval = roccat_common2_send(usb_dev, command, buf, real_size);
199         mutex_unlock(&arvo->arvo_lock);
200
201         return (retval ? retval : real_size);
202 }
203
204 static ssize_t arvo_sysfs_read(struct file *fp,
205                 struct kobject *kobj, void *buf, loff_t off,
206                 size_t count, size_t real_size, uint command)
207 {
208         struct device *dev = kobj_to_dev(kobj)->parent->parent;
209         struct arvo_device *arvo = hid_get_drvdata(dev_get_drvdata(dev));
210         struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
211         int retval;
212
213         if (off >= real_size)
214                 return 0;
215
216         if (off != 0 || count != real_size)
217                 return -EINVAL;
218
219         mutex_lock(&arvo->arvo_lock);
220         retval = roccat_common2_receive(usb_dev, command, buf, real_size);
221         mutex_unlock(&arvo->arvo_lock);
222
223         return (retval ? retval : real_size);
224 }
225
226 static ssize_t arvo_sysfs_write_button(struct file *fp,
227                 struct kobject *kobj, struct bin_attribute *attr, char *buf,
228                 loff_t off, size_t count)
229 {
230         return arvo_sysfs_write(fp, kobj, buf, off, count,
231                         sizeof(struct arvo_button), ARVO_COMMAND_BUTTON);
232 }
233 static BIN_ATTR(button, 0220, NULL, arvo_sysfs_write_button,
234                 sizeof(struct arvo_button));
235
236 static ssize_t arvo_sysfs_read_info(struct file *fp,
237                 struct kobject *kobj, struct bin_attribute *attr, char *buf,
238                 loff_t off, size_t count)
239 {
240         return arvo_sysfs_read(fp, kobj, buf, off, count,
241                         sizeof(struct arvo_info), ARVO_COMMAND_INFO);
242 }
243 static BIN_ATTR(info, 0440, arvo_sysfs_read_info, NULL,
244                 sizeof(struct arvo_info));
245
246 static struct attribute *arvo_attrs[] = {
247         &dev_attr_mode_key.attr,
248         &dev_attr_key_mask.attr,
249         &dev_attr_actual_profile.attr,
250         NULL,
251 };
252
253 static struct bin_attribute *arvo_bin_attributes[] = {
254         &bin_attr_button,
255         &bin_attr_info,
256         NULL,
257 };
258
259 static const struct attribute_group arvo_group = {
260         .attrs = arvo_attrs,
261         .bin_attrs = arvo_bin_attributes,
262 };
263
264 static const struct attribute_group *arvo_groups[] = {
265         &arvo_group,
266         NULL,
267 };
268
269 static const struct class arvo_class = {
270         .name = "arvo",
271         .dev_groups = arvo_groups,
272 };
273
274 static int arvo_init_arvo_device_struct(struct usb_device *usb_dev,
275                 struct arvo_device *arvo)
276 {
277         int retval;
278
279         mutex_init(&arvo->arvo_lock);
280
281         retval = arvo_get_actual_profile(usb_dev);
282         if (retval < 0)
283                 return retval;
284         arvo->actual_profile = retval;
285
286         return 0;
287 }
288
289 static int arvo_init_specials(struct hid_device *hdev)
290 {
291         struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
292         struct usb_device *usb_dev = interface_to_usbdev(intf);
293         struct arvo_device *arvo;
294         int retval;
295
296         if (intf->cur_altsetting->desc.bInterfaceProtocol
297                         == USB_INTERFACE_PROTOCOL_KEYBOARD) {
298                 hid_set_drvdata(hdev, NULL);
299                 return 0;
300         }
301
302         arvo = kzalloc(sizeof(*arvo), GFP_KERNEL);
303         if (!arvo) {
304                 hid_err(hdev, "can't alloc device descriptor\n");
305                 return -ENOMEM;
306         }
307         hid_set_drvdata(hdev, arvo);
308
309         retval = arvo_init_arvo_device_struct(usb_dev, arvo);
310         if (retval) {
311                 hid_err(hdev, "couldn't init struct arvo_device\n");
312                 goto exit_free;
313         }
314
315         retval = roccat_connect(&arvo_class, hdev,
316                         sizeof(struct arvo_roccat_report));
317         if (retval < 0) {
318                 hid_err(hdev, "couldn't init char dev\n");
319         } else {
320                 arvo->chrdev_minor = retval;
321                 arvo->roccat_claimed = 1;
322         }
323
324         return 0;
325 exit_free:
326         kfree(arvo);
327         return retval;
328 }
329
330 static void arvo_remove_specials(struct hid_device *hdev)
331 {
332         struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
333         struct arvo_device *arvo;
334
335         if (intf->cur_altsetting->desc.bInterfaceProtocol
336                         == USB_INTERFACE_PROTOCOL_KEYBOARD)
337                 return;
338
339         arvo = hid_get_drvdata(hdev);
340         if (arvo->roccat_claimed)
341                 roccat_disconnect(arvo->chrdev_minor);
342         kfree(arvo);
343 }
344
345 static int arvo_probe(struct hid_device *hdev,
346                 const struct hid_device_id *id)
347 {
348         int retval;
349
350         if (!hid_is_usb(hdev))
351                 return -EINVAL;
352
353         retval = hid_parse(hdev);
354         if (retval) {
355                 hid_err(hdev, "parse failed\n");
356                 goto exit;
357         }
358
359         retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
360         if (retval) {
361                 hid_err(hdev, "hw start failed\n");
362                 goto exit;
363         }
364
365         retval = arvo_init_specials(hdev);
366         if (retval) {
367                 hid_err(hdev, "couldn't install keyboard\n");
368                 goto exit_stop;
369         }
370
371         return 0;
372
373 exit_stop:
374         hid_hw_stop(hdev);
375 exit:
376         return retval;
377 }
378
379 static void arvo_remove(struct hid_device *hdev)
380 {
381         arvo_remove_specials(hdev);
382         hid_hw_stop(hdev);
383 }
384
385 static void arvo_report_to_chrdev(struct arvo_device const *arvo,
386                 u8 const *data)
387 {
388         struct arvo_special_report const *special_report;
389         struct arvo_roccat_report roccat_report;
390
391         special_report = (struct arvo_special_report const *)data;
392
393         roccat_report.profile = arvo->actual_profile;
394         roccat_report.button = special_report->event &
395                         ARVO_SPECIAL_REPORT_EVENT_MASK_BUTTON;
396         if ((special_report->event & ARVO_SPECIAL_REPORT_EVENT_MASK_ACTION) ==
397                         ARVO_SPECIAL_REPORT_EVENT_ACTION_PRESS)
398                 roccat_report.action = ARVO_ROCCAT_REPORT_ACTION_PRESS;
399         else
400                 roccat_report.action = ARVO_ROCCAT_REPORT_ACTION_RELEASE;
401
402         roccat_report_event(arvo->chrdev_minor,
403                         (uint8_t const *)&roccat_report);
404 }
405
406 static int arvo_raw_event(struct hid_device *hdev,
407                 struct hid_report *report, u8 *data, int size)
408 {
409         struct arvo_device *arvo = hid_get_drvdata(hdev);
410
411         if (size != 3)
412                 return 0;
413
414         if (arvo && arvo->roccat_claimed)
415                 arvo_report_to_chrdev(arvo, data);
416
417         return 0;
418 }
419
420 static const struct hid_device_id arvo_devices[] = {
421         { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
422         { }
423 };
424
425 MODULE_DEVICE_TABLE(hid, arvo_devices);
426
427 static struct hid_driver arvo_driver = {
428         .name = "arvo",
429         .id_table = arvo_devices,
430         .probe = arvo_probe,
431         .remove = arvo_remove,
432         .raw_event = arvo_raw_event
433 };
434
435 static int __init arvo_init(void)
436 {
437         int retval;
438
439         retval = class_register(&arvo_class);
440         if (retval)
441                 return retval;
442
443         retval = hid_register_driver(&arvo_driver);
444         if (retval)
445                 class_unregister(&arvo_class);
446         return retval;
447 }
448
449 static void __exit arvo_exit(void)
450 {
451         hid_unregister_driver(&arvo_driver);
452         class_unregister(&arvo_class);
453 }
454
455 module_init(arvo_init);
456 module_exit(arvo_exit);
457
458 MODULE_AUTHOR("Stefan Achatz");
459 MODULE_DESCRIPTION("USB Roccat Arvo driver");
460 MODULE_LICENSE("GPL v2");