diff options
Diffstat (limited to 'drivers/hid/hid-roccat-pyra.c')
-rw-r--r-- | drivers/hid/hid-roccat-pyra.c | 968 |
1 files changed, 968 insertions, 0 deletions
diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c new file mode 100644 index 000000000000..9bf23047892a --- /dev/null +++ b/drivers/hid/hid-roccat-pyra.c | |||
@@ -0,0 +1,968 @@ | |||
1 | /* | ||
2 | * Roccat Pyra driver for Linux | ||
3 | * | ||
4 | * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net> | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
11 | * any later version. | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * Roccat Pyra is a mobile gamer mouse which comes in wired and wireless | ||
16 | * variant. Wireless variant is not tested. | ||
17 | * Userland tools can be found at http://sourceforge.net/projects/roccat | ||
18 | */ | ||
19 | |||
20 | #include <linux/device.h> | ||
21 | #include <linux/input.h> | ||
22 | #include <linux/hid.h> | ||
23 | #include <linux/usb.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include "hid-ids.h" | ||
27 | #include "hid-roccat.h" | ||
28 | #include "hid-roccat-pyra.h" | ||
29 | |||
30 | static void profile_activated(struct pyra_device *pyra, | ||
31 | unsigned int new_profile) | ||
32 | { | ||
33 | pyra->actual_profile = new_profile; | ||
34 | pyra->actual_cpi = pyra->profile_settings[pyra->actual_profile].y_cpi; | ||
35 | } | ||
36 | |||
37 | static int pyra_send_control(struct usb_device *usb_dev, int value, | ||
38 | enum pyra_control_requests request) | ||
39 | { | ||
40 | int len; | ||
41 | struct pyra_control control; | ||
42 | |||
43 | if ((request == PYRA_CONTROL_REQUEST_PROFILE_SETTINGS || | ||
44 | request == PYRA_CONTROL_REQUEST_PROFILE_BUTTONS) && | ||
45 | (value < 0 || value > 4)) | ||
46 | return -EINVAL; | ||
47 | |||
48 | control.command = PYRA_COMMAND_CONTROL; | ||
49 | control.value = value; | ||
50 | control.request = request; | ||
51 | |||
52 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), | ||
53 | USB_REQ_SET_CONFIGURATION, | ||
54 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | ||
55 | PYRA_USB_COMMAND_CONTROL, 0, (char *)&control, | ||
56 | sizeof(struct pyra_control), | ||
57 | USB_CTRL_SET_TIMEOUT); | ||
58 | |||
59 | if (len != sizeof(struct pyra_control)) | ||
60 | return len; | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static int pyra_receive_control_status(struct usb_device *usb_dev) | ||
66 | { | ||
67 | int len; | ||
68 | struct pyra_control control; | ||
69 | |||
70 | do { | ||
71 | msleep(10); | ||
72 | |||
73 | len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | ||
74 | USB_REQ_CLEAR_FEATURE, | ||
75 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | | ||
76 | USB_DIR_IN, | ||
77 | PYRA_USB_COMMAND_CONTROL, 0, (char *)&control, | ||
78 | sizeof(struct pyra_control), | ||
79 | USB_CTRL_SET_TIMEOUT); | ||
80 | |||
81 | /* requested too early, try again */ | ||
82 | } while (len == -EPROTO); | ||
83 | |||
84 | if (len == sizeof(struct pyra_control) && | ||
85 | control.command == PYRA_COMMAND_CONTROL && | ||
86 | control.request == PYRA_CONTROL_REQUEST_STATUS && | ||
87 | control.value == 1) | ||
88 | return 0; | ||
89 | else { | ||
90 | dev_err(&usb_dev->dev, "receive control status: " | ||
91 | "unknown response 0x%x 0x%x\n", | ||
92 | control.request, control.value); | ||
93 | return -EINVAL; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | static int pyra_get_profile_settings(struct usb_device *usb_dev, | ||
98 | struct pyra_profile_settings *buf, int number) | ||
99 | { | ||
100 | int retval; | ||
101 | |||
102 | retval = pyra_send_control(usb_dev, number, | ||
103 | PYRA_CONTROL_REQUEST_PROFILE_SETTINGS); | ||
104 | |||
105 | if (retval) | ||
106 | return retval; | ||
107 | |||
108 | retval = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | ||
109 | USB_REQ_CLEAR_FEATURE, | ||
110 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | ||
111 | PYRA_USB_COMMAND_PROFILE_SETTINGS, 0, (char *)buf, | ||
112 | sizeof(struct pyra_profile_settings), | ||
113 | USB_CTRL_SET_TIMEOUT); | ||
114 | |||
115 | if (retval != sizeof(struct pyra_profile_settings)) | ||
116 | return retval; | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | static int pyra_get_profile_buttons(struct usb_device *usb_dev, | ||
122 | struct pyra_profile_buttons *buf, int number) | ||
123 | { | ||
124 | int retval; | ||
125 | |||
126 | retval = pyra_send_control(usb_dev, number, | ||
127 | PYRA_CONTROL_REQUEST_PROFILE_BUTTONS); | ||
128 | |||
129 | if (retval) | ||
130 | return retval; | ||
131 | |||
132 | retval = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | ||
133 | USB_REQ_CLEAR_FEATURE, | ||
134 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | ||
135 | PYRA_USB_COMMAND_PROFILE_BUTTONS, 0, (char *)buf, | ||
136 | sizeof(struct pyra_profile_buttons), | ||
137 | USB_CTRL_SET_TIMEOUT); | ||
138 | |||
139 | if (retval != sizeof(struct pyra_profile_buttons)) | ||
140 | return retval; | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static int pyra_get_settings(struct usb_device *usb_dev, | ||
146 | struct pyra_settings *buf) | ||
147 | { | ||
148 | int len; | ||
149 | len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | ||
150 | USB_REQ_CLEAR_FEATURE, | ||
151 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | ||
152 | PYRA_USB_COMMAND_SETTINGS, 0, buf, | ||
153 | sizeof(struct pyra_settings), USB_CTRL_SET_TIMEOUT); | ||
154 | if (len != sizeof(struct pyra_settings)) | ||
155 | return -EIO; | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static int pyra_get_info(struct usb_device *usb_dev, struct pyra_info *buf) | ||
160 | { | ||
161 | int len; | ||
162 | len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | ||
163 | USB_REQ_CLEAR_FEATURE, | ||
164 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | ||
165 | PYRA_USB_COMMAND_INFO, 0, buf, | ||
166 | sizeof(struct pyra_info), USB_CTRL_SET_TIMEOUT); | ||
167 | if (len != sizeof(struct pyra_info)) | ||
168 | return -EIO; | ||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static int pyra_set_profile_settings(struct usb_device *usb_dev, | ||
173 | struct pyra_profile_settings const *settings) | ||
174 | { | ||
175 | int len; | ||
176 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), | ||
177 | USB_REQ_SET_CONFIGURATION, | ||
178 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | ||
179 | PYRA_USB_COMMAND_PROFILE_SETTINGS, 0, (char *)settings, | ||
180 | sizeof(struct pyra_profile_settings), | ||
181 | USB_CTRL_SET_TIMEOUT); | ||
182 | if (len != sizeof(struct pyra_profile_settings)) | ||
183 | return -EIO; | ||
184 | if (pyra_receive_control_status(usb_dev)) | ||
185 | return -EIO; | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | static int pyra_set_profile_buttons(struct usb_device *usb_dev, | ||
190 | struct pyra_profile_buttons const *buttons) | ||
191 | { | ||
192 | int len; | ||
193 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), | ||
194 | USB_REQ_SET_CONFIGURATION, | ||
195 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | ||
196 | PYRA_USB_COMMAND_PROFILE_BUTTONS, 0, (char *)buttons, | ||
197 | sizeof(struct pyra_profile_buttons), | ||
198 | USB_CTRL_SET_TIMEOUT); | ||
199 | if (len != sizeof(struct pyra_profile_buttons)) | ||
200 | return -EIO; | ||
201 | if (pyra_receive_control_status(usb_dev)) | ||
202 | return -EIO; | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static int pyra_set_settings(struct usb_device *usb_dev, | ||
207 | struct pyra_settings const *settings) | ||
208 | { | ||
209 | int len; | ||
210 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), | ||
211 | USB_REQ_SET_CONFIGURATION, | ||
212 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | ||
213 | PYRA_USB_COMMAND_SETTINGS, 0, (char *)settings, | ||
214 | sizeof(struct pyra_settings), USB_CTRL_SET_TIMEOUT); | ||
215 | if (len != sizeof(struct pyra_settings)) | ||
216 | return -EIO; | ||
217 | if (pyra_receive_control_status(usb_dev)) | ||
218 | return -EIO; | ||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp, | ||
223 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
224 | loff_t off, size_t count, int number) | ||
225 | { | ||
226 | struct device *dev = container_of(kobj, struct device, kobj); | ||
227 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
228 | |||
229 | if (off >= sizeof(struct pyra_profile_settings)) | ||
230 | return 0; | ||
231 | |||
232 | if (off + count > sizeof(struct pyra_profile_settings)) | ||
233 | count = sizeof(struct pyra_profile_settings) - off; | ||
234 | |||
235 | mutex_lock(&pyra->pyra_lock); | ||
236 | memcpy(buf, ((char const *)&pyra->profile_settings[number]) + off, | ||
237 | count); | ||
238 | mutex_unlock(&pyra->pyra_lock); | ||
239 | |||
240 | return count; | ||
241 | } | ||
242 | |||
243 | static ssize_t pyra_sysfs_read_profile1_settings(struct file *fp, | ||
244 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
245 | loff_t off, size_t count) | ||
246 | { | ||
247 | return pyra_sysfs_read_profilex_settings(fp, kobj, | ||
248 | attr, buf, off, count, 0); | ||
249 | } | ||
250 | |||
251 | static ssize_t pyra_sysfs_read_profile2_settings(struct file *fp, | ||
252 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
253 | loff_t off, size_t count) | ||
254 | { | ||
255 | return pyra_sysfs_read_profilex_settings(fp, kobj, | ||
256 | attr, buf, off, count, 1); | ||
257 | } | ||
258 | |||
259 | static ssize_t pyra_sysfs_read_profile3_settings(struct file *fp, | ||
260 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
261 | loff_t off, size_t count) | ||
262 | { | ||
263 | return pyra_sysfs_read_profilex_settings(fp, kobj, | ||
264 | attr, buf, off, count, 2); | ||
265 | } | ||
266 | |||
267 | static ssize_t pyra_sysfs_read_profile4_settings(struct file *fp, | ||
268 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
269 | loff_t off, size_t count) | ||
270 | { | ||
271 | return pyra_sysfs_read_profilex_settings(fp, kobj, | ||
272 | attr, buf, off, count, 3); | ||
273 | } | ||
274 | |||
275 | static ssize_t pyra_sysfs_read_profile5_settings(struct file *fp, | ||
276 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
277 | loff_t off, size_t count) | ||
278 | { | ||
279 | return pyra_sysfs_read_profilex_settings(fp, kobj, | ||
280 | attr, buf, off, count, 4); | ||
281 | } | ||
282 | |||
283 | static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp, | ||
284 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
285 | loff_t off, size_t count, int number) | ||
286 | { | ||
287 | struct device *dev = container_of(kobj, struct device, kobj); | ||
288 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
289 | |||
290 | if (off >= sizeof(struct pyra_profile_buttons)) | ||
291 | return 0; | ||
292 | |||
293 | if (off + count > sizeof(struct pyra_profile_buttons)) | ||
294 | count = sizeof(struct pyra_profile_buttons) - off; | ||
295 | |||
296 | mutex_lock(&pyra->pyra_lock); | ||
297 | memcpy(buf, ((char const *)&pyra->profile_buttons[number]) + off, | ||
298 | count); | ||
299 | mutex_unlock(&pyra->pyra_lock); | ||
300 | |||
301 | return count; | ||
302 | } | ||
303 | |||
304 | static ssize_t pyra_sysfs_read_profile1_buttons(struct file *fp, | ||
305 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
306 | loff_t off, size_t count) | ||
307 | { | ||
308 | return pyra_sysfs_read_profilex_buttons(fp, kobj, | ||
309 | attr, buf, off, count, 0); | ||
310 | } | ||
311 | |||
312 | static ssize_t pyra_sysfs_read_profile2_buttons(struct file *fp, | ||
313 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
314 | loff_t off, size_t count) | ||
315 | { | ||
316 | return pyra_sysfs_read_profilex_buttons(fp, kobj, | ||
317 | attr, buf, off, count, 1); | ||
318 | } | ||
319 | |||
320 | static ssize_t pyra_sysfs_read_profile3_buttons(struct file *fp, | ||
321 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
322 | loff_t off, size_t count) | ||
323 | { | ||
324 | return pyra_sysfs_read_profilex_buttons(fp, kobj, | ||
325 | attr, buf, off, count, 2); | ||
326 | } | ||
327 | |||
328 | static ssize_t pyra_sysfs_read_profile4_buttons(struct file *fp, | ||
329 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
330 | loff_t off, size_t count) | ||
331 | { | ||
332 | return pyra_sysfs_read_profilex_buttons(fp, kobj, | ||
333 | attr, buf, off, count, 3); | ||
334 | } | ||
335 | |||
336 | static ssize_t pyra_sysfs_read_profile5_buttons(struct file *fp, | ||
337 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
338 | loff_t off, size_t count) | ||
339 | { | ||
340 | return pyra_sysfs_read_profilex_buttons(fp, kobj, | ||
341 | attr, buf, off, count, 4); | ||
342 | } | ||
343 | |||
344 | static ssize_t pyra_sysfs_write_profile_settings(struct file *fp, | ||
345 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
346 | loff_t off, size_t count) | ||
347 | { | ||
348 | struct device *dev = container_of(kobj, struct device, kobj); | ||
349 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
350 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
351 | int retval = 0; | ||
352 | int difference; | ||
353 | int profile_number; | ||
354 | struct pyra_profile_settings *profile_settings; | ||
355 | |||
356 | if (off != 0 || count != sizeof(struct pyra_profile_settings)) | ||
357 | return -EINVAL; | ||
358 | |||
359 | profile_number = ((struct pyra_profile_settings const *)buf)->number; | ||
360 | profile_settings = &pyra->profile_settings[profile_number]; | ||
361 | |||
362 | mutex_lock(&pyra->pyra_lock); | ||
363 | difference = memcmp(buf, profile_settings, | ||
364 | sizeof(struct pyra_profile_settings)); | ||
365 | if (difference) { | ||
366 | retval = pyra_set_profile_settings(usb_dev, | ||
367 | (struct pyra_profile_settings const *)buf); | ||
368 | if (!retval) | ||
369 | memcpy(profile_settings, buf, | ||
370 | sizeof(struct pyra_profile_settings)); | ||
371 | } | ||
372 | mutex_unlock(&pyra->pyra_lock); | ||
373 | |||
374 | if (retval) | ||
375 | return retval; | ||
376 | |||
377 | return sizeof(struct pyra_profile_settings); | ||
378 | } | ||
379 | |||
380 | static ssize_t pyra_sysfs_write_profile_buttons(struct file *fp, | ||
381 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
382 | loff_t off, size_t count) | ||
383 | { | ||
384 | struct device *dev = container_of(kobj, struct device, kobj); | ||
385 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
386 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
387 | int retval = 0; | ||
388 | int difference; | ||
389 | int profile_number; | ||
390 | struct pyra_profile_buttons *profile_buttons; | ||
391 | |||
392 | if (off != 0 || count != sizeof(struct pyra_profile_buttons)) | ||
393 | return -EINVAL; | ||
394 | |||
395 | profile_number = ((struct pyra_profile_buttons const *)buf)->number; | ||
396 | profile_buttons = &pyra->profile_buttons[profile_number]; | ||
397 | |||
398 | mutex_lock(&pyra->pyra_lock); | ||
399 | difference = memcmp(buf, profile_buttons, | ||
400 | sizeof(struct pyra_profile_buttons)); | ||
401 | if (difference) { | ||
402 | retval = pyra_set_profile_buttons(usb_dev, | ||
403 | (struct pyra_profile_buttons const *)buf); | ||
404 | if (!retval) | ||
405 | memcpy(profile_buttons, buf, | ||
406 | sizeof(struct pyra_profile_buttons)); | ||
407 | } | ||
408 | mutex_unlock(&pyra->pyra_lock); | ||
409 | |||
410 | if (retval) | ||
411 | return retval; | ||
412 | |||
413 | return sizeof(struct pyra_profile_buttons); | ||
414 | } | ||
415 | |||
416 | static ssize_t pyra_sysfs_read_settings(struct file *fp, | ||
417 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
418 | loff_t off, size_t count) | ||
419 | { | ||
420 | struct device *dev = container_of(kobj, struct device, kobj); | ||
421 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
422 | |||
423 | if (off >= sizeof(struct pyra_settings)) | ||
424 | return 0; | ||
425 | |||
426 | if (off + count > sizeof(struct pyra_settings)) | ||
427 | count = sizeof(struct pyra_settings) - off; | ||
428 | |||
429 | mutex_lock(&pyra->pyra_lock); | ||
430 | memcpy(buf, ((char const *)&pyra->settings) + off, count); | ||
431 | mutex_unlock(&pyra->pyra_lock); | ||
432 | |||
433 | return count; | ||
434 | } | ||
435 | |||
436 | static ssize_t pyra_sysfs_write_settings(struct file *fp, | ||
437 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
438 | loff_t off, size_t count) | ||
439 | { | ||
440 | struct device *dev = container_of(kobj, struct device, kobj); | ||
441 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
442 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
443 | int retval = 0; | ||
444 | int difference; | ||
445 | |||
446 | if (off != 0 || count != sizeof(struct pyra_settings)) | ||
447 | return -EINVAL; | ||
448 | |||
449 | mutex_lock(&pyra->pyra_lock); | ||
450 | difference = memcmp(buf, &pyra->settings, sizeof(struct pyra_settings)); | ||
451 | if (difference) { | ||
452 | retval = pyra_set_settings(usb_dev, | ||
453 | (struct pyra_settings const *)buf); | ||
454 | if (!retval) | ||
455 | memcpy(&pyra->settings, buf, | ||
456 | sizeof(struct pyra_settings)); | ||
457 | } | ||
458 | mutex_unlock(&pyra->pyra_lock); | ||
459 | |||
460 | if (retval) | ||
461 | return retval; | ||
462 | |||
463 | profile_activated(pyra, pyra->settings.startup_profile); | ||
464 | |||
465 | return sizeof(struct pyra_settings); | ||
466 | } | ||
467 | |||
468 | |||
469 | static ssize_t pyra_sysfs_show_actual_cpi(struct device *dev, | ||
470 | struct device_attribute *attr, char *buf) | ||
471 | { | ||
472 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
473 | return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_cpi); | ||
474 | } | ||
475 | |||
476 | static ssize_t pyra_sysfs_show_actual_profile(struct device *dev, | ||
477 | struct device_attribute *attr, char *buf) | ||
478 | { | ||
479 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
480 | return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_profile); | ||
481 | } | ||
482 | |||
483 | static ssize_t pyra_sysfs_show_firmware_version(struct device *dev, | ||
484 | struct device_attribute *attr, char *buf) | ||
485 | { | ||
486 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
487 | return snprintf(buf, PAGE_SIZE, "%d\n", pyra->firmware_version); | ||
488 | } | ||
489 | |||
490 | static ssize_t pyra_sysfs_show_startup_profile(struct device *dev, | ||
491 | struct device_attribute *attr, char *buf) | ||
492 | { | ||
493 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
494 | return snprintf(buf, PAGE_SIZE, "%d\n", pyra->settings.startup_profile); | ||
495 | } | ||
496 | |||
497 | static DEVICE_ATTR(actual_cpi, 0440, pyra_sysfs_show_actual_cpi, NULL); | ||
498 | |||
499 | static DEVICE_ATTR(actual_profile, 0440, pyra_sysfs_show_actual_profile, NULL); | ||
500 | |||
501 | static DEVICE_ATTR(firmware_version, 0440, | ||
502 | pyra_sysfs_show_firmware_version, NULL); | ||
503 | |||
504 | static DEVICE_ATTR(startup_profile, 0440, | ||
505 | pyra_sysfs_show_startup_profile, NULL); | ||
506 | |||
507 | static struct attribute *pyra_attributes[] = { | ||
508 | &dev_attr_actual_cpi.attr, | ||
509 | &dev_attr_actual_profile.attr, | ||
510 | &dev_attr_firmware_version.attr, | ||
511 | &dev_attr_startup_profile.attr, | ||
512 | NULL | ||
513 | }; | ||
514 | |||
515 | static struct attribute_group pyra_attribute_group = { | ||
516 | .attrs = pyra_attributes | ||
517 | }; | ||
518 | |||
519 | static struct bin_attribute pyra_profile_settings_attr = { | ||
520 | .attr = { .name = "profile_settings", .mode = 0220 }, | ||
521 | .size = sizeof(struct pyra_profile_settings), | ||
522 | .write = pyra_sysfs_write_profile_settings | ||
523 | }; | ||
524 | |||
525 | static struct bin_attribute pyra_profile1_settings_attr = { | ||
526 | .attr = { .name = "profile1_settings", .mode = 0440 }, | ||
527 | .size = sizeof(struct pyra_profile_settings), | ||
528 | .read = pyra_sysfs_read_profile1_settings | ||
529 | }; | ||
530 | |||
531 | static struct bin_attribute pyra_profile2_settings_attr = { | ||
532 | .attr = { .name = "profile2_settings", .mode = 0440 }, | ||
533 | .size = sizeof(struct pyra_profile_settings), | ||
534 | .read = pyra_sysfs_read_profile2_settings | ||
535 | }; | ||
536 | |||
537 | static struct bin_attribute pyra_profile3_settings_attr = { | ||
538 | .attr = { .name = "profile3_settings", .mode = 0440 }, | ||
539 | .size = sizeof(struct pyra_profile_settings), | ||
540 | .read = pyra_sysfs_read_profile3_settings | ||
541 | }; | ||
542 | |||
543 | static struct bin_attribute pyra_profile4_settings_attr = { | ||
544 | .attr = { .name = "profile4_settings", .mode = 0440 }, | ||
545 | .size = sizeof(struct pyra_profile_settings), | ||
546 | .read = pyra_sysfs_read_profile4_settings | ||
547 | }; | ||
548 | |||
549 | static struct bin_attribute pyra_profile5_settings_attr = { | ||
550 | .attr = { .name = "profile5_settings", .mode = 0440 }, | ||
551 | .size = sizeof(struct pyra_profile_settings), | ||
552 | .read = pyra_sysfs_read_profile5_settings | ||
553 | }; | ||
554 | |||
555 | static struct bin_attribute pyra_profile_buttons_attr = { | ||
556 | .attr = { .name = "profile_buttons", .mode = 0220 }, | ||
557 | .size = sizeof(struct pyra_profile_buttons), | ||
558 | .write = pyra_sysfs_write_profile_buttons | ||
559 | }; | ||
560 | |||
561 | static struct bin_attribute pyra_profile1_buttons_attr = { | ||
562 | .attr = { .name = "profile1_buttons", .mode = 0440 }, | ||
563 | .size = sizeof(struct pyra_profile_buttons), | ||
564 | .read = pyra_sysfs_read_profile1_buttons | ||
565 | }; | ||
566 | |||
567 | static struct bin_attribute pyra_profile2_buttons_attr = { | ||
568 | .attr = { .name = "profile2_buttons", .mode = 0440 }, | ||
569 | .size = sizeof(struct pyra_profile_buttons), | ||
570 | .read = pyra_sysfs_read_profile2_buttons | ||
571 | }; | ||
572 | |||
573 | static struct bin_attribute pyra_profile3_buttons_attr = { | ||
574 | .attr = { .name = "profile3_buttons", .mode = 0440 }, | ||
575 | .size = sizeof(struct pyra_profile_buttons), | ||
576 | .read = pyra_sysfs_read_profile3_buttons | ||
577 | }; | ||
578 | |||
579 | static struct bin_attribute pyra_profile4_buttons_attr = { | ||
580 | .attr = { .name = "profile4_buttons", .mode = 0440 }, | ||
581 | .size = sizeof(struct pyra_profile_buttons), | ||
582 | .read = pyra_sysfs_read_profile4_buttons | ||
583 | }; | ||
584 | |||
585 | static struct bin_attribute pyra_profile5_buttons_attr = { | ||
586 | .attr = { .name = "profile5_buttons", .mode = 0440 }, | ||
587 | .size = sizeof(struct pyra_profile_buttons), | ||
588 | .read = pyra_sysfs_read_profile5_buttons | ||
589 | }; | ||
590 | |||
591 | static struct bin_attribute pyra_settings_attr = { | ||
592 | .attr = { .name = "settings", .mode = 0660 }, | ||
593 | .size = sizeof(struct pyra_settings), | ||
594 | .read = pyra_sysfs_read_settings, | ||
595 | .write = pyra_sysfs_write_settings | ||
596 | }; | ||
597 | |||
598 | static int pyra_create_sysfs_attributes(struct usb_interface *intf) | ||
599 | { | ||
600 | int retval; | ||
601 | |||
602 | retval = sysfs_create_group(&intf->dev.kobj, &pyra_attribute_group); | ||
603 | if (retval) | ||
604 | goto exit_1; | ||
605 | |||
606 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
607 | &pyra_profile_settings_attr); | ||
608 | if (retval) | ||
609 | goto exit_2; | ||
610 | |||
611 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
612 | &pyra_profile1_settings_attr); | ||
613 | if (retval) | ||
614 | goto exit_3; | ||
615 | |||
616 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
617 | &pyra_profile2_settings_attr); | ||
618 | if (retval) | ||
619 | goto exit_4; | ||
620 | |||
621 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
622 | &pyra_profile3_settings_attr); | ||
623 | if (retval) | ||
624 | goto exit_5; | ||
625 | |||
626 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
627 | &pyra_profile4_settings_attr); | ||
628 | if (retval) | ||
629 | goto exit_6; | ||
630 | |||
631 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
632 | &pyra_profile5_settings_attr); | ||
633 | if (retval) | ||
634 | goto exit_7; | ||
635 | |||
636 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
637 | &pyra_profile_buttons_attr); | ||
638 | if (retval) | ||
639 | goto exit_8; | ||
640 | |||
641 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
642 | &pyra_profile1_buttons_attr); | ||
643 | if (retval) | ||
644 | goto exit_9; | ||
645 | |||
646 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
647 | &pyra_profile2_buttons_attr); | ||
648 | if (retval) | ||
649 | goto exit_10; | ||
650 | |||
651 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
652 | &pyra_profile3_buttons_attr); | ||
653 | if (retval) | ||
654 | goto exit_11; | ||
655 | |||
656 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
657 | &pyra_profile4_buttons_attr); | ||
658 | if (retval) | ||
659 | goto exit_12; | ||
660 | |||
661 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
662 | &pyra_profile5_buttons_attr); | ||
663 | if (retval) | ||
664 | goto exit_13; | ||
665 | |||
666 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
667 | &pyra_settings_attr); | ||
668 | if (retval) | ||
669 | goto exit_14; | ||
670 | |||
671 | return 0; | ||
672 | |||
673 | exit_14: | ||
674 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_buttons_attr); | ||
675 | exit_13: | ||
676 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_buttons_attr); | ||
677 | exit_12: | ||
678 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_buttons_attr); | ||
679 | exit_11: | ||
680 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_buttons_attr); | ||
681 | exit_10: | ||
682 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_buttons_attr); | ||
683 | exit_9: | ||
684 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_buttons_attr); | ||
685 | exit_8: | ||
686 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_settings_attr); | ||
687 | exit_7: | ||
688 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_settings_attr); | ||
689 | exit_6: | ||
690 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_settings_attr); | ||
691 | exit_5: | ||
692 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_settings_attr); | ||
693 | exit_4: | ||
694 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_settings_attr); | ||
695 | exit_3: | ||
696 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_settings_attr); | ||
697 | exit_2: | ||
698 | sysfs_remove_group(&intf->dev.kobj, &pyra_attribute_group); | ||
699 | exit_1: | ||
700 | return retval; | ||
701 | } | ||
702 | |||
703 | static void pyra_remove_sysfs_attributes(struct usb_interface *intf) | ||
704 | { | ||
705 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_settings_attr); | ||
706 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_buttons_attr); | ||
707 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_buttons_attr); | ||
708 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_buttons_attr); | ||
709 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_buttons_attr); | ||
710 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_buttons_attr); | ||
711 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_buttons_attr); | ||
712 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_settings_attr); | ||
713 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_settings_attr); | ||
714 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_settings_attr); | ||
715 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_settings_attr); | ||
716 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_settings_attr); | ||
717 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_settings_attr); | ||
718 | sysfs_remove_group(&intf->dev.kobj, &pyra_attribute_group); | ||
719 | } | ||
720 | |||
721 | static int pyra_init_pyra_device_struct(struct usb_device *usb_dev, | ||
722 | struct pyra_device *pyra) | ||
723 | { | ||
724 | struct pyra_info *info; | ||
725 | int retval, i; | ||
726 | |||
727 | mutex_init(&pyra->pyra_lock); | ||
728 | |||
729 | info = kmalloc(sizeof(struct pyra_info), GFP_KERNEL); | ||
730 | if (!info) | ||
731 | return -ENOMEM; | ||
732 | retval = pyra_get_info(usb_dev, info); | ||
733 | if (retval) { | ||
734 | kfree(info); | ||
735 | return retval; | ||
736 | } | ||
737 | pyra->firmware_version = info->firmware_version; | ||
738 | kfree(info); | ||
739 | |||
740 | retval = pyra_get_settings(usb_dev, &pyra->settings); | ||
741 | if (retval) | ||
742 | return retval; | ||
743 | |||
744 | for (i = 0; i < 5; ++i) { | ||
745 | retval = pyra_get_profile_settings(usb_dev, | ||
746 | &pyra->profile_settings[i], i); | ||
747 | if (retval) | ||
748 | return retval; | ||
749 | |||
750 | retval = pyra_get_profile_buttons(usb_dev, | ||
751 | &pyra->profile_buttons[i], i); | ||
752 | if (retval) | ||
753 | return retval; | ||
754 | } | ||
755 | |||
756 | profile_activated(pyra, pyra->settings.startup_profile); | ||
757 | |||
758 | return 0; | ||
759 | } | ||
760 | |||
761 | static int pyra_init_specials(struct hid_device *hdev) | ||
762 | { | ||
763 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
764 | struct usb_device *usb_dev = interface_to_usbdev(intf); | ||
765 | struct pyra_device *pyra; | ||
766 | int retval; | ||
767 | |||
768 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
769 | == USB_INTERFACE_PROTOCOL_MOUSE) { | ||
770 | |||
771 | pyra = kzalloc(sizeof(*pyra), GFP_KERNEL); | ||
772 | if (!pyra) { | ||
773 | dev_err(&hdev->dev, "can't alloc device descriptor\n"); | ||
774 | return -ENOMEM; | ||
775 | } | ||
776 | hid_set_drvdata(hdev, pyra); | ||
777 | |||
778 | retval = pyra_init_pyra_device_struct(usb_dev, pyra); | ||
779 | if (retval) { | ||
780 | dev_err(&hdev->dev, | ||
781 | "couldn't init struct pyra_device\n"); | ||
782 | goto exit_free; | ||
783 | } | ||
784 | |||
785 | retval = roccat_connect(hdev); | ||
786 | if (retval < 0) { | ||
787 | dev_err(&hdev->dev, "couldn't init char dev\n"); | ||
788 | } else { | ||
789 | pyra->chrdev_minor = retval; | ||
790 | pyra->roccat_claimed = 1; | ||
791 | } | ||
792 | |||
793 | retval = pyra_create_sysfs_attributes(intf); | ||
794 | if (retval) { | ||
795 | dev_err(&hdev->dev, "cannot create sysfs files\n"); | ||
796 | goto exit_free; | ||
797 | } | ||
798 | } else { | ||
799 | hid_set_drvdata(hdev, NULL); | ||
800 | } | ||
801 | |||
802 | return 0; | ||
803 | exit_free: | ||
804 | kfree(pyra); | ||
805 | return retval; | ||
806 | } | ||
807 | |||
808 | static void pyra_remove_specials(struct hid_device *hdev) | ||
809 | { | ||
810 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
811 | struct pyra_device *pyra; | ||
812 | |||
813 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
814 | == USB_INTERFACE_PROTOCOL_MOUSE) { | ||
815 | pyra_remove_sysfs_attributes(intf); | ||
816 | pyra = hid_get_drvdata(hdev); | ||
817 | if (pyra->roccat_claimed) | ||
818 | roccat_disconnect(pyra->chrdev_minor); | ||
819 | kfree(hid_get_drvdata(hdev)); | ||
820 | } | ||
821 | } | ||
822 | |||
823 | static int pyra_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
824 | { | ||
825 | int retval; | ||
826 | |||
827 | retval = hid_parse(hdev); | ||
828 | if (retval) { | ||
829 | dev_err(&hdev->dev, "parse failed\n"); | ||
830 | goto exit; | ||
831 | } | ||
832 | |||
833 | retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
834 | if (retval) { | ||
835 | dev_err(&hdev->dev, "hw start failed\n"); | ||
836 | goto exit; | ||
837 | } | ||
838 | |||
839 | retval = pyra_init_specials(hdev); | ||
840 | if (retval) { | ||
841 | dev_err(&hdev->dev, "couldn't install mouse\n"); | ||
842 | goto exit_stop; | ||
843 | } | ||
844 | return 0; | ||
845 | |||
846 | exit_stop: | ||
847 | hid_hw_stop(hdev); | ||
848 | exit: | ||
849 | return retval; | ||
850 | } | ||
851 | |||
852 | static void pyra_remove(struct hid_device *hdev) | ||
853 | { | ||
854 | pyra_remove_specials(hdev); | ||
855 | hid_hw_stop(hdev); | ||
856 | } | ||
857 | |||
858 | static void pyra_keep_values_up_to_date(struct pyra_device *pyra, | ||
859 | u8 const *data) | ||
860 | { | ||
861 | struct pyra_mouse_event_button const *button_event; | ||
862 | |||
863 | switch (data[0]) { | ||
864 | case PYRA_MOUSE_REPORT_NUMBER_BUTTON: | ||
865 | button_event = (struct pyra_mouse_event_button const *)data; | ||
866 | switch (button_event->type) { | ||
867 | case PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2: | ||
868 | profile_activated(pyra, button_event->data1 - 1); | ||
869 | break; | ||
870 | case PYRA_MOUSE_EVENT_BUTTON_TYPE_CPI: | ||
871 | pyra->actual_cpi = button_event->data1; | ||
872 | break; | ||
873 | } | ||
874 | break; | ||
875 | } | ||
876 | } | ||
877 | |||
878 | static void pyra_report_to_chrdev(struct pyra_device const *pyra, | ||
879 | u8 const *data) | ||
880 | { | ||
881 | struct pyra_roccat_report roccat_report; | ||
882 | struct pyra_mouse_event_button const *button_event; | ||
883 | |||
884 | if (data[0] != PYRA_MOUSE_REPORT_NUMBER_BUTTON) | ||
885 | return; | ||
886 | |||
887 | button_event = (struct pyra_mouse_event_button const *)data; | ||
888 | |||
889 | switch (button_event->type) { | ||
890 | case PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2: | ||
891 | case PYRA_MOUSE_EVENT_BUTTON_TYPE_CPI: | ||
892 | roccat_report.type = button_event->type; | ||
893 | roccat_report.value = button_event->data1; | ||
894 | roccat_report.key = 0; | ||
895 | roccat_report_event(pyra->chrdev_minor, | ||
896 | (uint8_t const *)&roccat_report, | ||
897 | sizeof(struct pyra_roccat_report)); | ||
898 | break; | ||
899 | case PYRA_MOUSE_EVENT_BUTTON_TYPE_MACRO: | ||
900 | case PYRA_MOUSE_EVENT_BUTTON_TYPE_SHORTCUT: | ||
901 | case PYRA_MOUSE_EVENT_BUTTON_TYPE_QUICKLAUNCH: | ||
902 | if (button_event->data2 == PYRA_MOUSE_EVENT_BUTTON_PRESS) { | ||
903 | roccat_report.type = button_event->type; | ||
904 | roccat_report.key = button_event->data1; | ||
905 | /* | ||
906 | * pyra reports profile numbers with range 1-5. | ||
907 | * Keeping this behaviour. | ||
908 | */ | ||
909 | roccat_report.value = pyra->actual_profile + 1; | ||
910 | roccat_report_event(pyra->chrdev_minor, | ||
911 | (uint8_t const *)&roccat_report, | ||
912 | sizeof(struct pyra_roccat_report)); | ||
913 | } | ||
914 | break; | ||
915 | } | ||
916 | } | ||
917 | |||
918 | static int pyra_raw_event(struct hid_device *hdev, struct hid_report *report, | ||
919 | u8 *data, int size) | ||
920 | { | ||
921 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
922 | struct pyra_device *pyra = hid_get_drvdata(hdev); | ||
923 | |||
924 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
925 | != USB_INTERFACE_PROTOCOL_MOUSE) | ||
926 | return 0; | ||
927 | |||
928 | pyra_keep_values_up_to_date(pyra, data); | ||
929 | |||
930 | if (pyra->roccat_claimed) | ||
931 | pyra_report_to_chrdev(pyra, data); | ||
932 | |||
933 | return 0; | ||
934 | } | ||
935 | |||
936 | static const struct hid_device_id pyra_devices[] = { | ||
937 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, | ||
938 | USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, | ||
939 | /* TODO add USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS after testing */ | ||
940 | { } | ||
941 | }; | ||
942 | |||
943 | MODULE_DEVICE_TABLE(hid, pyra_devices); | ||
944 | |||
945 | static struct hid_driver pyra_driver = { | ||
946 | .name = "pyra", | ||
947 | .id_table = pyra_devices, | ||
948 | .probe = pyra_probe, | ||
949 | .remove = pyra_remove, | ||
950 | .raw_event = pyra_raw_event | ||
951 | }; | ||
952 | |||
953 | static int __init pyra_init(void) | ||
954 | { | ||
955 | return hid_register_driver(&pyra_driver); | ||
956 | } | ||
957 | |||
958 | static void __exit pyra_exit(void) | ||
959 | { | ||
960 | hid_unregister_driver(&pyra_driver); | ||
961 | } | ||
962 | |||
963 | module_init(pyra_init); | ||
964 | module_exit(pyra_exit); | ||
965 | |||
966 | MODULE_AUTHOR("Stefan Achatz"); | ||
967 | MODULE_DESCRIPTION("USB Roccat Pyra driver"); | ||
968 | MODULE_LICENSE("GPL v2"); | ||