blob: 73199de2e37fedb582c6a560f4277cda7c8de640 [file] [log] [blame]
Stefan Achatz14bf62c2010-03-18 16:19:43 +01001/*
2 * Roccat Kone 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 Kone is a gamer mouse which consists of a mouse part and a keyboard
16 * part. The keyboard part enables the mouse to execute stored macros with mixed
17 * key- and button-events.
18 *
19 * TODO implement on-the-fly polling-rate change
20 * The windows driver has the ability to change the polling rate of the
21 * device on the press of a mousebutton.
22 * Is it possible to remove and reinstall the urb in raw-event- or any
23 * other handler, or to defer this action to be executed somewhere else?
24 *
Stefan Achatz14bf62c2010-03-18 16:19:43 +010025 * TODO is it possible to overwrite group for sysfs attributes via udev?
26 */
27
28#include <linux/device.h>
29#include <linux/input.h>
30#include <linux/hid.h>
31#include <linux/usb.h>
32#include <linux/module.h>
Tejun Heoed28f042010-03-30 02:52:41 +090033#include <linux/slab.h>
Stefan Achatz14bf62c2010-03-18 16:19:43 +010034#include "hid-ids.h"
Stefan Achatz206f5f22010-05-19 18:55:16 +020035#include "hid-roccat.h"
Stefan Achatz14bf62c2010-03-18 16:19:43 +010036#include "hid-roccat-kone.h"
37
38static void kone_set_settings_checksum(struct kone_settings *settings)
39{
40 uint16_t checksum = 0;
41 unsigned char *address = (unsigned char *)settings;
42 int i;
43
44 for (i = 0; i < sizeof(struct kone_settings) - 2; ++i, ++address)
45 checksum += *address;
46 settings->checksum = cpu_to_le16(checksum);
47}
48
49/*
50 * Checks success after writing data to mouse
51 * On success returns 0
52 * On failure returns errno
53 */
54static int kone_check_write(struct usb_device *usb_dev)
55{
56 int len;
57 unsigned char *data;
58
59 data = kmalloc(1, GFP_KERNEL);
60 if (!data)
61 return -ENOMEM;
62
63 do {
64 /*
65 * Mouse needs 50 msecs until it says ok, but there are
66 * 30 more msecs needed for next write to work.
67 */
68 msleep(80);
69
70 len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
71 USB_REQ_CLEAR_FEATURE,
72 USB_TYPE_CLASS | USB_RECIP_INTERFACE |
73 USB_DIR_IN,
74 kone_command_confirm_write, 0, data, 1,
75 USB_CTRL_SET_TIMEOUT);
76
77 if (len != 1) {
78 kfree(data);
79 return -EIO;
80 }
81
82 /*
83 * value of 3 seems to mean something like
84 * "not finished yet, but it looks good"
85 * So check again after a moment.
86 */
87 } while (*data == 3);
88
89 if (*data == 1) { /* everything alright */
90 kfree(data);
91 return 0;
92 } else { /* unknown answer */
Joe Perches4291ee32010-12-09 19:29:03 -080093 hid_err(usb_dev, "got retval %d when checking write\n", *data);
Stefan Achatz14bf62c2010-03-18 16:19:43 +010094 kfree(data);
95 return -EIO;
96 }
97}
98
99/*
100 * Reads settings from mouse and stores it in @buf
101 * @buf has to be alloced with GFP_KERNEL
102 * On success returns 0
103 * On failure returns errno
104 */
105static int kone_get_settings(struct usb_device *usb_dev,
106 struct kone_settings *buf)
107{
108 int len;
109
110 len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
111 USB_REQ_CLEAR_FEATURE,
112 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
113 kone_command_settings, 0, buf,
114 sizeof(struct kone_settings), USB_CTRL_SET_TIMEOUT);
115
116 if (len != sizeof(struct kone_settings))
117 return -EIO;
118
119 return 0;
120}
121
122/*
123 * Writes settings from @buf to mouse
124 * On success returns 0
125 * On failure returns errno
126 */
127static int kone_set_settings(struct usb_device *usb_dev,
128 struct kone_settings const *settings)
129{
130 int len;
131
132 len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
133 USB_REQ_SET_CONFIGURATION,
134 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
135 kone_command_settings, 0, (char *)settings,
136 sizeof(struct kone_settings),
137 USB_CTRL_SET_TIMEOUT);
138
139 if (len != sizeof(struct kone_settings))
140 return -EIO;
141
142 if (kone_check_write(usb_dev))
143 return -EIO;
144
145 return 0;
146}
147
148/*
149 * Reads profile data from mouse and stores it in @buf
150 * @number: profile number to read
151 * On success returns 0
152 * On failure returns errno
153 */
154static int kone_get_profile(struct usb_device *usb_dev,
155 struct kone_profile *buf, int number)
156{
157 int len;
158
159 if (number < 1 || number > 5)
160 return -EINVAL;
161
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 kone_command_profile, number, buf,
166 sizeof(struct kone_profile), USB_CTRL_SET_TIMEOUT);
167
168 if (len != sizeof(struct kone_profile))
169 return -EIO;
170
171 return 0;
172}
173
174/*
175 * Writes profile data to mouse.
176 * @number: profile number to write
177 * On success returns 0
178 * On failure returns errno
179 */
180static int kone_set_profile(struct usb_device *usb_dev,
181 struct kone_profile const *profile, int number)
182{
183 int len;
184
185 if (number < 1 || number > 5)
186 return -EINVAL;
187
188 len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
189 USB_REQ_SET_CONFIGURATION,
190 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
191 kone_command_profile, number, (char *)profile,
192 sizeof(struct kone_profile),
193 USB_CTRL_SET_TIMEOUT);
194
195 if (len != sizeof(struct kone_profile))
196 return len;
197
198 if (kone_check_write(usb_dev))
199 return -EIO;
200
201 return 0;
202}
203
204/*
205 * Reads value of "fast-clip-weight" and stores it in @result
206 * On success returns 0
207 * On failure returns errno
208 */
209static int kone_get_weight(struct usb_device *usb_dev, int *result)
210{
211 int len;
212 uint8_t *data;
213
214 data = kmalloc(1, GFP_KERNEL);
215 if (!data)
216 return -ENOMEM;
217
218 len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
219 USB_REQ_CLEAR_FEATURE,
220 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
221 kone_command_weight, 0, data, 1, USB_CTRL_SET_TIMEOUT);
222
223 if (len != 1) {
224 kfree(data);
225 return -EIO;
226 }
227 *result = (int)*data;
228 kfree(data);
229 return 0;
230}
231
232/*
233 * Reads firmware_version of mouse and stores it in @result
234 * On success returns 0
235 * On failure returns errno
236 */
237static int kone_get_firmware_version(struct usb_device *usb_dev, int *result)
238{
239 int len;
240 unsigned char *data;
241
242 data = kmalloc(2, GFP_KERNEL);
243 if (!data)
244 return -ENOMEM;
245
246 len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
247 USB_REQ_CLEAR_FEATURE,
248 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
249 kone_command_firmware_version, 0, data, 2,
250 USB_CTRL_SET_TIMEOUT);
251
252 if (len != 2) {
253 kfree(data);
254 return -EIO;
255 }
256 *result = le16_to_cpu(*data);
257 kfree(data);
258 return 0;
259}
260
Stephen Rothwell5f277622010-05-21 16:15:32 +1000261static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj,
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100262 struct bin_attribute *attr, char *buf,
263 loff_t off, size_t count) {
264 struct device *dev = container_of(kobj, struct device, kobj);
265 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
266
267 if (off >= sizeof(struct kone_settings))
268 return 0;
269
270 if (off + count > sizeof(struct kone_settings))
271 count = sizeof(struct kone_settings) - off;
272
273 mutex_lock(&kone->kone_lock);
Stefan Achatzcab6b162010-06-20 19:19:06 +0200274 memcpy(buf, ((char const *)&kone->settings) + off, count);
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100275 mutex_unlock(&kone->kone_lock);
276
277 return count;
278}
279
280/*
281 * Writing settings automatically activates startup_profile.
282 * This function keeps values in kone_device up to date and assumes that in
283 * case of error the old data is still valid
284 */
Stephen Rothwell5f277622010-05-21 16:15:32 +1000285static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj,
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100286 struct bin_attribute *attr, char *buf,
287 loff_t off, size_t count) {
288 struct device *dev = container_of(kobj, struct device, kobj);
289 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
290 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
291 int retval = 0, difference;
292
293 /* I need to get my data in one piece */
294 if (off != 0 || count != sizeof(struct kone_settings))
295 return -EINVAL;
296
297 mutex_lock(&kone->kone_lock);
298 difference = memcmp(buf, &kone->settings, sizeof(struct kone_settings));
299 if (difference) {
300 retval = kone_set_settings(usb_dev,
301 (struct kone_settings const *)buf);
302 if (!retval)
303 memcpy(&kone->settings, buf,
304 sizeof(struct kone_settings));
305 }
306 mutex_unlock(&kone->kone_lock);
307
308 if (retval)
309 return retval;
310
311 /*
312 * If we get here, treat settings as okay and update actual values
313 * according to startup_profile
314 */
315 kone->actual_profile = kone->settings.startup_profile;
316 kone->actual_dpi = kone->profiles[kone->actual_profile - 1].startup_dpi;
317
318 return sizeof(struct kone_settings);
319}
320
321static ssize_t kone_sysfs_read_profilex(struct kobject *kobj,
322 struct bin_attribute *attr, char *buf,
323 loff_t off, size_t count, int number) {
324 struct device *dev = container_of(kobj, struct device, kobj);
325 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
326
327 if (off >= sizeof(struct kone_profile))
328 return 0;
329
330 if (off + count > sizeof(struct kone_profile))
331 count = sizeof(struct kone_profile) - off;
332
333 mutex_lock(&kone->kone_lock);
Stefan Achatzcab6b162010-06-20 19:19:06 +0200334 memcpy(buf, ((char const *)&kone->profiles[number - 1]) + off, count);
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100335 mutex_unlock(&kone->kone_lock);
336
337 return count;
338}
339
Stephen Rothwell5f277622010-05-21 16:15:32 +1000340static ssize_t kone_sysfs_read_profile1(struct file *fp, struct kobject *kobj,
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100341 struct bin_attribute *attr, char *buf,
342 loff_t off, size_t count) {
343 return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 1);
344}
345
Stephen Rothwell5f277622010-05-21 16:15:32 +1000346static ssize_t kone_sysfs_read_profile2(struct file *fp, struct kobject *kobj,
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100347 struct bin_attribute *attr, char *buf,
348 loff_t off, size_t count) {
349 return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 2);
350}
351
Stephen Rothwell5f277622010-05-21 16:15:32 +1000352static ssize_t kone_sysfs_read_profile3(struct file *fp, struct kobject *kobj,
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100353 struct bin_attribute *attr, char *buf,
354 loff_t off, size_t count) {
355 return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 3);
356}
357
Stephen Rothwell5f277622010-05-21 16:15:32 +1000358static ssize_t kone_sysfs_read_profile4(struct file *fp, struct kobject *kobj,
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100359 struct bin_attribute *attr, char *buf,
360 loff_t off, size_t count) {
361 return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 4);
362}
363
Stephen Rothwell5f277622010-05-21 16:15:32 +1000364static ssize_t kone_sysfs_read_profile5(struct file *fp, struct kobject *kobj,
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100365 struct bin_attribute *attr, char *buf,
366 loff_t off, size_t count) {
367 return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 5);
368}
369
370/* Writes data only if different to stored data */
371static ssize_t kone_sysfs_write_profilex(struct kobject *kobj,
372 struct bin_attribute *attr, char *buf,
373 loff_t off, size_t count, int number) {
374 struct device *dev = container_of(kobj, struct device, kobj);
375 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
376 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
377 struct kone_profile *profile;
378 int retval = 0, difference;
379
380 /* I need to get my data in one piece */
381 if (off != 0 || count != sizeof(struct kone_profile))
382 return -EINVAL;
383
384 profile = &kone->profiles[number - 1];
385
386 mutex_lock(&kone->kone_lock);
387 difference = memcmp(buf, profile, sizeof(struct kone_profile));
388 if (difference) {
389 retval = kone_set_profile(usb_dev,
390 (struct kone_profile const *)buf, number);
391 if (!retval)
392 memcpy(profile, buf, sizeof(struct kone_profile));
393 }
394 mutex_unlock(&kone->kone_lock);
395
396 if (retval)
397 return retval;
398
399 return sizeof(struct kone_profile);
400}
401
Stephen Rothwell5f277622010-05-21 16:15:32 +1000402static ssize_t kone_sysfs_write_profile1(struct file *fp, struct kobject *kobj,
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100403 struct bin_attribute *attr, char *buf,
404 loff_t off, size_t count) {
405 return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 1);
406}
407
Stephen Rothwell5f277622010-05-21 16:15:32 +1000408static ssize_t kone_sysfs_write_profile2(struct file *fp, struct kobject *kobj,
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100409 struct bin_attribute *attr, char *buf,
410 loff_t off, size_t count) {
411 return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 2);
412}
413
Stephen Rothwell5f277622010-05-21 16:15:32 +1000414static ssize_t kone_sysfs_write_profile3(struct file *fp, struct kobject *kobj,
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100415 struct bin_attribute *attr, char *buf,
416 loff_t off, size_t count) {
417 return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 3);
418}
419
Stephen Rothwell5f277622010-05-21 16:15:32 +1000420static ssize_t kone_sysfs_write_profile4(struct file *fp, struct kobject *kobj,
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100421 struct bin_attribute *attr, char *buf,
422 loff_t off, size_t count) {
423 return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 4);
424}
425
Stephen Rothwell5f277622010-05-21 16:15:32 +1000426static ssize_t kone_sysfs_write_profile5(struct file *fp, struct kobject *kobj,
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100427 struct bin_attribute *attr, char *buf,
428 loff_t off, size_t count) {
429 return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 5);
430}
431
432static ssize_t kone_sysfs_show_actual_profile(struct device *dev,
433 struct device_attribute *attr, char *buf)
434{
435 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
436 return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_profile);
437}
438
439static ssize_t kone_sysfs_show_actual_dpi(struct device *dev,
440 struct device_attribute *attr, char *buf)
441{
442 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
443 return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_dpi);
444}
445
446/* weight is read each time, since we don't get informed when it's changed */
447static ssize_t kone_sysfs_show_weight(struct device *dev,
448 struct device_attribute *attr, char *buf)
449{
450 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
451 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
452 int weight = 0;
453 int retval;
454
455 mutex_lock(&kone->kone_lock);
456 retval = kone_get_weight(usb_dev, &weight);
457 mutex_unlock(&kone->kone_lock);
458
459 if (retval)
460 return retval;
461 return snprintf(buf, PAGE_SIZE, "%d\n", weight);
462}
463
464static ssize_t kone_sysfs_show_firmware_version(struct device *dev,
465 struct device_attribute *attr, char *buf)
466{
467 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
468 return snprintf(buf, PAGE_SIZE, "%d\n", kone->firmware_version);
469}
470
471static ssize_t kone_sysfs_show_tcu(struct device *dev,
472 struct device_attribute *attr, char *buf)
473{
474 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
475 return snprintf(buf, PAGE_SIZE, "%d\n", kone->settings.tcu);
476}
477
478static int kone_tcu_command(struct usb_device *usb_dev, int number)
479{
480 int len;
481 char *value;
482
483 value = kmalloc(1, GFP_KERNEL);
484 if (!value)
485 return -ENOMEM;
486
487 *value = number;
488
489 len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
490 USB_REQ_SET_CONFIGURATION,
491 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
492 kone_command_calibrate, 0, value, 1,
493 USB_CTRL_SET_TIMEOUT);
494
495 kfree(value);
496 return ((len != 1) ? -EIO : 0);
497}
498
499/*
500 * Calibrating the tcu is the only action that changes settings data inside the
501 * mouse, so this data needs to be reread
502 */
503static ssize_t kone_sysfs_set_tcu(struct device *dev,
504 struct device_attribute *attr, char const *buf, size_t size)
505{
506 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
507 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
508 int retval;
509 unsigned long state;
510
511 retval = strict_strtoul(buf, 10, &state);
512 if (retval)
513 return retval;
514
515 if (state != 0 && state != 1)
516 return -EINVAL;
517
518 mutex_lock(&kone->kone_lock);
519
520 if (state == 1) { /* state activate */
521 retval = kone_tcu_command(usb_dev, 1);
522 if (retval)
523 goto exit_unlock;
524 retval = kone_tcu_command(usb_dev, 2);
525 if (retval)
526 goto exit_unlock;
527 ssleep(5); /* tcu needs this time for calibration */
528 retval = kone_tcu_command(usb_dev, 3);
529 if (retval)
530 goto exit_unlock;
531 retval = kone_tcu_command(usb_dev, 0);
532 if (retval)
533 goto exit_unlock;
534 retval = kone_tcu_command(usb_dev, 4);
535 if (retval)
536 goto exit_unlock;
537 /*
538 * Kone needs this time to settle things.
539 * Reading settings too early will result in invalid data.
540 * Roccat's driver waits 1 sec, maybe this time could be
541 * shortened.
542 */
543 ssleep(1);
544 }
545
546 /* calibration changes values in settings, so reread */
547 retval = kone_get_settings(usb_dev, &kone->settings);
548 if (retval)
549 goto exit_no_settings;
550
551 /* only write settings back if activation state is different */
552 if (kone->settings.tcu != state) {
553 kone->settings.tcu = state;
554 kone_set_settings_checksum(&kone->settings);
555
556 retval = kone_set_settings(usb_dev, &kone->settings);
557 if (retval) {
Joe Perches4291ee32010-12-09 19:29:03 -0800558 hid_err(usb_dev, "couldn't set tcu state\n");
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100559 /*
560 * try to reread valid settings into buffer overwriting
561 * first error code
562 */
563 retval = kone_get_settings(usb_dev, &kone->settings);
564 if (retval)
565 goto exit_no_settings;
566 goto exit_unlock;
567 }
568 }
569
570 retval = size;
571exit_no_settings:
Joe Perches4291ee32010-12-09 19:29:03 -0800572 hid_err(usb_dev, "couldn't read settings\n");
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100573exit_unlock:
574 mutex_unlock(&kone->kone_lock);
575 return retval;
576}
577
578static ssize_t kone_sysfs_show_startup_profile(struct device *dev,
579 struct device_attribute *attr, char *buf)
580{
581 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
582 return snprintf(buf, PAGE_SIZE, "%d\n", kone->settings.startup_profile);
583}
584
585static ssize_t kone_sysfs_set_startup_profile(struct device *dev,
586 struct device_attribute *attr, char const *buf, size_t size)
587{
588 struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
589 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
590 int retval;
591 unsigned long new_startup_profile;
592
593 retval = strict_strtoul(buf, 10, &new_startup_profile);
594 if (retval)
595 return retval;
596
597 if (new_startup_profile < 1 || new_startup_profile > 5)
598 return -EINVAL;
599
600 mutex_lock(&kone->kone_lock);
601
602 kone->settings.startup_profile = new_startup_profile;
603 kone_set_settings_checksum(&kone->settings);
604
605 retval = kone_set_settings(usb_dev, &kone->settings);
606
607 mutex_unlock(&kone->kone_lock);
608
609 if (retval)
610 return retval;
611
612 /* changing the startup profile immediately activates this profile */
613 kone->actual_profile = new_startup_profile;
614 kone->actual_dpi = kone->profiles[kone->actual_profile - 1].startup_dpi;
615
616 return size;
617}
618
619/*
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100620 * Read actual dpi settings.
621 * Returns raw value for further processing. Refer to enum kone_polling_rates to
622 * get real value.
623 */
624static DEVICE_ATTR(actual_dpi, 0440, kone_sysfs_show_actual_dpi, NULL);
625
626static DEVICE_ATTR(actual_profile, 0440, kone_sysfs_show_actual_profile, NULL);
627
628/*
629 * The mouse can be equipped with one of four supplied weights from 5 to 20
630 * grams which are recognized and its value can be read out.
631 * This returns the raw value reported by the mouse for easy evaluation by
632 * software. Refer to enum kone_weights to get corresponding real weight.
633 */
634static DEVICE_ATTR(weight, 0440, kone_sysfs_show_weight, NULL);
635
636/*
637 * Prints firmware version stored in mouse as integer.
638 * The raw value reported by the mouse is returned for easy evaluation, to get
639 * the real version number the decimal point has to be shifted 2 positions to
640 * the left. E.g. a value of 138 means 1.38.
641 */
642static DEVICE_ATTR(firmware_version, 0440,
643 kone_sysfs_show_firmware_version, NULL);
644
645/*
646 * Prints state of Tracking Control Unit as number where 0 = off and 1 = on
647 * Writing 0 deactivates tcu and writing 1 calibrates and activates the tcu
648 */
649static DEVICE_ATTR(tcu, 0660, kone_sysfs_show_tcu, kone_sysfs_set_tcu);
650
651/* Prints and takes the number of the profile the mouse starts with */
652static DEVICE_ATTR(startup_profile, 0660,
653 kone_sysfs_show_startup_profile,
654 kone_sysfs_set_startup_profile);
655
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100656static struct attribute *kone_attributes[] = {
657 &dev_attr_actual_dpi.attr,
658 &dev_attr_actual_profile.attr,
659 &dev_attr_weight.attr,
660 &dev_attr_firmware_version.attr,
661 &dev_attr_tcu.attr,
662 &dev_attr_startup_profile.attr,
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100663 NULL
664};
665
666static struct attribute_group kone_attribute_group = {
667 .attrs = kone_attributes
668};
669
670static struct bin_attribute kone_settings_attr = {
671 .attr = { .name = "settings", .mode = 0660 },
672 .size = sizeof(struct kone_settings),
673 .read = kone_sysfs_read_settings,
674 .write = kone_sysfs_write_settings
675};
676
677static struct bin_attribute kone_profile1_attr = {
678 .attr = { .name = "profile1", .mode = 0660 },
679 .size = sizeof(struct kone_profile),
680 .read = kone_sysfs_read_profile1,
681 .write = kone_sysfs_write_profile1
682};
683
684static struct bin_attribute kone_profile2_attr = {
685 .attr = { .name = "profile2", .mode = 0660 },
686 .size = sizeof(struct kone_profile),
687 .read = kone_sysfs_read_profile2,
688 .write = kone_sysfs_write_profile2
689};
690
691static struct bin_attribute kone_profile3_attr = {
692 .attr = { .name = "profile3", .mode = 0660 },
693 .size = sizeof(struct kone_profile),
694 .read = kone_sysfs_read_profile3,
695 .write = kone_sysfs_write_profile3
696};
697
698static struct bin_attribute kone_profile4_attr = {
699 .attr = { .name = "profile4", .mode = 0660 },
700 .size = sizeof(struct kone_profile),
701 .read = kone_sysfs_read_profile4,
702 .write = kone_sysfs_write_profile4
703};
704
705static struct bin_attribute kone_profile5_attr = {
706 .attr = { .name = "profile5", .mode = 0660 },
707 .size = sizeof(struct kone_profile),
708 .read = kone_sysfs_read_profile5,
709 .write = kone_sysfs_write_profile5
710};
711
712static int kone_create_sysfs_attributes(struct usb_interface *intf)
713{
714 int retval;
715
716 retval = sysfs_create_group(&intf->dev.kobj, &kone_attribute_group);
717 if (retval)
718 goto exit_1;
719
720 retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_settings_attr);
721 if (retval)
722 goto exit_2;
723
724 retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile1_attr);
725 if (retval)
726 goto exit_3;
727
728 retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile2_attr);
729 if (retval)
730 goto exit_4;
731
732 retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile3_attr);
733 if (retval)
734 goto exit_5;
735
736 retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile4_attr);
737 if (retval)
738 goto exit_6;
739
740 retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile5_attr);
741 if (retval)
742 goto exit_7;
743
744 return 0;
745
746exit_7:
747 sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile4_attr);
748exit_6:
749 sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile3_attr);
750exit_5:
751 sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile2_attr);
752exit_4:
753 sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile1_attr);
754exit_3:
755 sysfs_remove_bin_file(&intf->dev.kobj, &kone_settings_attr);
756exit_2:
757 sysfs_remove_group(&intf->dev.kobj, &kone_attribute_group);
758exit_1:
759 return retval;
760}
761
762static void kone_remove_sysfs_attributes(struct usb_interface *intf)
763{
764 sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile5_attr);
765 sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile4_attr);
766 sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile3_attr);
767 sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile2_attr);
768 sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile1_attr);
769 sysfs_remove_bin_file(&intf->dev.kobj, &kone_settings_attr);
770 sysfs_remove_group(&intf->dev.kobj, &kone_attribute_group);
771}
772
773static int kone_init_kone_device_struct(struct usb_device *usb_dev,
774 struct kone_device *kone)
775{
776 uint i;
777 int retval;
778
779 mutex_init(&kone->kone_lock);
780
781 for (i = 0; i < 5; ++i) {
782 retval = kone_get_profile(usb_dev, &kone->profiles[i], i + 1);
783 if (retval)
784 return retval;
785 }
786
787 retval = kone_get_settings(usb_dev, &kone->settings);
788 if (retval)
789 return retval;
790
791 retval = kone_get_firmware_version(usb_dev, &kone->firmware_version);
792 if (retval)
793 return retval;
794
795 kone->actual_profile = kone->settings.startup_profile;
796 kone->actual_dpi = kone->profiles[kone->actual_profile].startup_dpi;
797
798 return 0;
799}
800
801/*
802 * Since IGNORE_MOUSE quirk moved to hid-apple, there is no way to bind only to
803 * mousepart if usb_hid is compiled into the kernel and kone is compiled as
804 * module.
805 * Secial behaviour is bound only to mousepart since only mouseevents contain
806 * additional notifications.
807 */
808static int kone_init_specials(struct hid_device *hdev)
809{
810 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
811 struct usb_device *usb_dev = interface_to_usbdev(intf);
812 struct kone_device *kone;
813 int retval;
814
815 if (intf->cur_altsetting->desc.bInterfaceProtocol
816 == USB_INTERFACE_PROTOCOL_MOUSE) {
817
818 kone = kzalloc(sizeof(*kone), GFP_KERNEL);
819 if (!kone) {
Joe Perches4291ee32010-12-09 19:29:03 -0800820 hid_err(hdev, "can't alloc device descriptor\n");
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100821 return -ENOMEM;
822 }
823 hid_set_drvdata(hdev, kone);
824
825 retval = kone_init_kone_device_struct(usb_dev, kone);
826 if (retval) {
Joe Perches4291ee32010-12-09 19:29:03 -0800827 hid_err(hdev, "couldn't init struct kone_device\n");
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100828 goto exit_free;
829 }
Stefan Achatz206f5f22010-05-19 18:55:16 +0200830
831 retval = roccat_connect(hdev);
832 if (retval < 0) {
Joe Perches4291ee32010-12-09 19:29:03 -0800833 hid_err(hdev, "couldn't init char dev\n");
Stefan Achatz206f5f22010-05-19 18:55:16 +0200834 /* be tolerant about not getting chrdev */
835 } else {
836 kone->roccat_claimed = 1;
837 kone->chrdev_minor = retval;
838 }
839
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100840 retval = kone_create_sysfs_attributes(intf);
841 if (retval) {
Joe Perches4291ee32010-12-09 19:29:03 -0800842 hid_err(hdev, "cannot create sysfs files\n");
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100843 goto exit_free;
844 }
845 } else {
846 hid_set_drvdata(hdev, NULL);
847 }
848
849 return 0;
850exit_free:
851 kfree(kone);
852 return retval;
853}
854
855
856static void kone_remove_specials(struct hid_device *hdev)
857{
858 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
Stefan Achatz206f5f22010-05-19 18:55:16 +0200859 struct kone_device *kone;
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100860
861 if (intf->cur_altsetting->desc.bInterfaceProtocol
862 == USB_INTERFACE_PROTOCOL_MOUSE) {
863 kone_remove_sysfs_attributes(intf);
Stefan Achatz206f5f22010-05-19 18:55:16 +0200864 kone = hid_get_drvdata(hdev);
865 if (kone->roccat_claimed)
866 roccat_disconnect(kone->chrdev_minor);
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100867 kfree(hid_get_drvdata(hdev));
868 }
869}
870
871static int kone_probe(struct hid_device *hdev, const struct hid_device_id *id)
872{
873 int retval;
874
875 retval = hid_parse(hdev);
876 if (retval) {
Joe Perches4291ee32010-12-09 19:29:03 -0800877 hid_err(hdev, "parse failed\n");
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100878 goto exit;
879 }
880
881 retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
882 if (retval) {
Joe Perches4291ee32010-12-09 19:29:03 -0800883 hid_err(hdev, "hw start failed\n");
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100884 goto exit;
885 }
886
887 retval = kone_init_specials(hdev);
888 if (retval) {
Joe Perches4291ee32010-12-09 19:29:03 -0800889 hid_err(hdev, "couldn't install mouse\n");
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100890 goto exit_stop;
891 }
892
893 return 0;
894
895exit_stop:
896 hid_hw_stop(hdev);
897exit:
898 return retval;
899}
900
901static void kone_remove(struct hid_device *hdev)
902{
903 kone_remove_specials(hdev);
904 hid_hw_stop(hdev);
905}
906
Stefan Achatz48e70802010-05-18 18:31:04 +0200907/* handle special events and keep actual profile and dpi values up to date */
908static void kone_keep_values_up_to_date(struct kone_device *kone,
909 struct kone_mouse_event const *event)
910{
911 switch (event->event) {
912 case kone_mouse_event_switch_profile:
913 case kone_mouse_event_osd_profile:
914 kone->actual_profile = event->value;
915 kone->actual_dpi = kone->profiles[kone->actual_profile - 1].
916 startup_dpi;
917 break;
918 case kone_mouse_event_switch_dpi:
919 case kone_mouse_event_osd_dpi:
920 kone->actual_dpi = event->value;
921 break;
922 }
923}
924
Stefan Achatz206f5f22010-05-19 18:55:16 +0200925static void kone_report_to_chrdev(struct kone_device const *kone,
926 struct kone_mouse_event const *event)
927{
928 struct kone_roccat_report roccat_report;
929
930 switch (event->event) {
931 case kone_mouse_event_switch_profile:
932 case kone_mouse_event_switch_dpi:
933 case kone_mouse_event_osd_profile:
934 case kone_mouse_event_osd_dpi:
935 roccat_report.event = event->event;
936 roccat_report.value = event->value;
937 roccat_report.key = 0;
938 roccat_report_event(kone->chrdev_minor,
939 (uint8_t *)&roccat_report,
940 sizeof(struct kone_roccat_report));
941 break;
942 case kone_mouse_event_call_overlong_macro:
943 if (event->value == kone_keystroke_action_press) {
944 roccat_report.event = kone_mouse_event_call_overlong_macro;
945 roccat_report.value = kone->actual_profile;
946 roccat_report.key = event->macro_key;
947 roccat_report_event(kone->chrdev_minor,
948 (uint8_t *)&roccat_report,
949 sizeof(struct kone_roccat_report));
950 }
951 break;
952 }
953
954}
955
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100956/*
957 * Is called for keyboard- and mousepart.
958 * Only mousepart gets informations about special events in its extended event
959 * structure.
960 */
961static int kone_raw_event(struct hid_device *hdev, struct hid_report *report,
962 u8 *data, int size)
963{
964 struct kone_device *kone = hid_get_drvdata(hdev);
965 struct kone_mouse_event *event = (struct kone_mouse_event *)data;
966
967 /* keyboard events are always processed by default handler */
968 if (size != sizeof(struct kone_mouse_event))
969 return 0;
970
971 /*
Stefan Achatz73b35772010-05-19 13:53:22 +0200972 * Firmware 1.38 introduced new behaviour for tilt and special buttons.
973 * Pressed button is reported in each movement event.
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100974 * Workaround sends only one event per press.
975 */
Stefan Achatz73b35772010-05-19 13:53:22 +0200976 if (memcmp(&kone->last_mouse_event.tilt, &event->tilt, 5))
977 memcpy(&kone->last_mouse_event, event,
978 sizeof(struct kone_mouse_event));
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100979 else
Stefan Achatz73b35772010-05-19 13:53:22 +0200980 memset(&event->tilt, 0, 5);
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100981
Stefan Achatz48e70802010-05-18 18:31:04 +0200982 kone_keep_values_up_to_date(kone, event);
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100983
Stefan Achatz206f5f22010-05-19 18:55:16 +0200984 if (kone->roccat_claimed)
985 kone_report_to_chrdev(kone, event);
986
Stefan Achatz48e70802010-05-18 18:31:04 +0200987 return 0; /* always do further processing */
Stefan Achatz14bf62c2010-03-18 16:19:43 +0100988}
989
990static const struct hid_device_id kone_devices[] = {
991 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) },
992 { }
993};
994
995MODULE_DEVICE_TABLE(hid, kone_devices);
996
997static struct hid_driver kone_driver = {
998 .name = "kone",
999 .id_table = kone_devices,
1000 .probe = kone_probe,
1001 .remove = kone_remove,
1002 .raw_event = kone_raw_event
1003};
1004
Stefan Achatz00237bc2010-05-08 17:20:38 +02001005static int __init kone_init(void)
Stefan Achatz14bf62c2010-03-18 16:19:43 +01001006{
1007 return hid_register_driver(&kone_driver);
1008}
1009
Stefan Achatz00237bc2010-05-08 17:20:38 +02001010static void __exit kone_exit(void)
Stefan Achatz14bf62c2010-03-18 16:19:43 +01001011{
1012 hid_unregister_driver(&kone_driver);
1013}
1014
1015module_init(kone_init);
1016module_exit(kone_exit);
1017
Stefan Achatz1f749d82010-05-12 17:43:34 +02001018MODULE_AUTHOR("Stefan Achatz");
1019MODULE_DESCRIPTION("USB Roccat Kone driver");
1020MODULE_LICENSE("GPL v2");