~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to drivers/hid/hid-roccat-arvo.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno
  • Date: 2011-06-07 12:14:05 UTC
  • mfrom: (43.1.9 sid)
  • Revision ID: james.westby@ubuntu.com-20110607121405-i3h1rd7nrnd2b73h
Tags: 2.6.39-2
[ Ben Hutchings ]
* [x86] Enable BACKLIGHT_APPLE, replacing BACKLIGHT_MBP_NVIDIA
  (Closes: #627492)
* cgroups: Disable memory resource controller by default. Allow it
  to be enabled using kernel parameter 'cgroup_enable=memory'.
* rt2800usb: Enable support for more USB devices including
  Linksys WUSB600N (Closes: #596626) (this change was accidentally
  omitted from 2.6.39-1)
* [x86] Remove Celeron from list of processors supporting PAE. Most
  'Celeron M' models do not.
* Update debconf template translations:
  - Swedish (Martin Bagge) (Closes: #628932)
  - French (David Prévot) (Closes: #628191)
* aufs: Update for 2.6.39 (Closes: #627837)
* Add stable 2.6.39.1, including:
  - ext4: dont set PageUptodate in ext4_end_bio()
  - pata_cmd64x: fix boot crash on parisc (Closes: #622997, #622745)
  - ext3: Fix fs corruption when make_indexed_dir() fails
  - netfilter: nf_ct_sip: validate Content-Length in TCP SIP messages
  - sctp: fix race between sctp_bind_addr_free() and
    sctp_bind_addr_conflict()
  - sctp: fix memory leak of the ASCONF queue when free asoc
  - md/bitmap: fix saving of events_cleared and other state
  - cdc_acm: Fix oops when Droids MuIn LCD is connected
  - cx88: Fix conversion from BKL to fine-grained locks (Closes: #619827)
  - keys: Set cred->user_ns in key_replace_session_keyring (CVE-2011-2184)
  - tmpfs: fix race between truncate and writepage
  - nfs41: Correct offset for LAYOUTCOMMIT
  - xen/mmu: fix a race window causing leave_mm BUG()
  - ext4: fix possible use-after-free in ext4_remove_li_request()
  For the complete list of changes, see:
   http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.39.1
* Bump ABI to 2
* netfilter: Enable IP_SET, IP_SET_BITMAP_IP, IP_SET_BITMAP_IPMAC,
  IP_SET_BITMAP_PORT, IP_SET_HASH_IP, IP_SET_HASH_IPPORT,
  IP_SET_HASH_IPPORTIP, IP_SET_HASH_IPPORTNET, IP_SET_HASH_NET,
  IP_SET_HASH_NETPORT, IP_SET_LIST_SET, NETFILTER_XT_SET as modules
  (Closes: #629401)

[ Aurelien Jarno ]
* [mipsel/loongson-2f] Disable_SCSI_LPFC to workaround GCC ICE.

Show diffs side-by-side

added added

removed removed

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