diff options
Diffstat (limited to 'drivers/hid/hid-roccat-koneplus.c')
-rw-r--r-- | drivers/hid/hid-roccat-koneplus.c | 135 |
1 files changed, 39 insertions, 96 deletions
diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c index c826c0d6c872..d1c3a02109a8 100644 --- a/drivers/hid/hid-roccat-koneplus.c +++ b/drivers/hid/hid-roccat-koneplus.c | |||
@@ -19,11 +19,11 @@ | |||
19 | #include <linux/device.h> | 19 | #include <linux/device.h> |
20 | #include <linux/input.h> | 20 | #include <linux/input.h> |
21 | #include <linux/hid.h> | 21 | #include <linux/hid.h> |
22 | #include <linux/usb.h> | ||
23 | #include <linux/module.h> | 22 | #include <linux/module.h> |
24 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
25 | #include "hid-ids.h" | 24 | #include "hid-ids.h" |
26 | #include "hid-roccat.h" | 25 | #include "hid-roccat.h" |
26 | #include "hid-roccat-common.h" | ||
27 | #include "hid-roccat-koneplus.h" | 27 | #include "hid-roccat-koneplus.h" |
28 | 28 | ||
29 | static uint profile_numbers[5] = {0, 1, 2, 3, 4}; | 29 | static uint profile_numbers[5] = {0, 1, 2, 3, 4}; |
@@ -39,110 +39,63 @@ static void koneplus_profile_activated(struct koneplus_device *koneplus, | |||
39 | static int koneplus_send_control(struct usb_device *usb_dev, uint value, | 39 | static int koneplus_send_control(struct usb_device *usb_dev, uint value, |
40 | enum koneplus_control_requests request) | 40 | enum koneplus_control_requests request) |
41 | { | 41 | { |
42 | int len; | 42 | struct koneplus_control control; |
43 | struct koneplus_control *control; | ||
44 | 43 | ||
45 | if ((request == KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS || | 44 | if ((request == KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS || |
46 | request == KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) && | 45 | request == KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) && |
47 | value > 4) | 46 | value > 4) |
48 | return -EINVAL; | 47 | return -EINVAL; |
49 | 48 | ||
50 | control = kmalloc(sizeof(struct koneplus_control), GFP_KERNEL); | 49 | control.command = KONEPLUS_COMMAND_CONTROL; |
51 | if (!control) | 50 | control.value = value; |
52 | return -ENOMEM; | 51 | control.request = request; |
53 | 52 | ||
54 | control->command = KONEPLUS_COMMAND_CONTROL; | 53 | return roccat_common_send(usb_dev, KONEPLUS_USB_COMMAND_CONTROL, |
55 | control->value = value; | 54 | &control, sizeof(struct koneplus_control)); |
56 | control->request = request; | ||
57 | |||
58 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), | ||
59 | USB_REQ_SET_CONFIGURATION, | ||
60 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | ||
61 | KONEPLUS_USB_COMMAND_CONTROL, 0, control, | ||
62 | sizeof(struct koneplus_control), | ||
63 | USB_CTRL_SET_TIMEOUT); | ||
64 | |||
65 | kfree(control); | ||
66 | |||
67 | if (len != sizeof(struct koneplus_control)) | ||
68 | return len; | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int koneplus_receive(struct usb_device *usb_dev, uint usb_command, | ||
74 | void *buf, uint size) { | ||
75 | int len; | ||
76 | |||
77 | len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | ||
78 | USB_REQ_CLEAR_FEATURE, | ||
79 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | ||
80 | usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT); | ||
81 | |||
82 | return (len != size) ? -EIO : 0; | ||
83 | } | 55 | } |
84 | 56 | ||
85 | static int koneplus_receive_control_status(struct usb_device *usb_dev) | 57 | static int koneplus_receive_control_status(struct usb_device *usb_dev) |
86 | { | 58 | { |
87 | int retval; | 59 | int retval; |
88 | struct koneplus_control *control; | 60 | struct koneplus_control control; |
89 | |||
90 | control = kmalloc(sizeof(struct koneplus_control), GFP_KERNEL); | ||
91 | if (!control) | ||
92 | return -ENOMEM; | ||
93 | 61 | ||
94 | do { | 62 | do { |
95 | retval = koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_CONTROL, | 63 | retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_CONTROL, |
96 | control, sizeof(struct koneplus_control)); | 64 | &control, sizeof(struct koneplus_control)); |
97 | 65 | ||
98 | /* check if we get a completely wrong answer */ | 66 | /* check if we get a completely wrong answer */ |
99 | if (retval) | 67 | if (retval) |
100 | goto out; | 68 | return retval; |
101 | 69 | ||
102 | if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_OK) { | 70 | if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_OK) |
103 | retval = 0; | 71 | return 0; |
104 | goto out; | ||
105 | } | ||
106 | 72 | ||
107 | /* indicates that hardware needs some more time to complete action */ | 73 | /* indicates that hardware needs some more time to complete action */ |
108 | if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_WAIT) { | 74 | if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_WAIT) { |
109 | msleep(500); /* windows driver uses 1000 */ | 75 | msleep(500); /* windows driver uses 1000 */ |
110 | continue; | 76 | continue; |
111 | } | 77 | } |
112 | 78 | ||
113 | /* seems to be critical - replug necessary */ | 79 | /* seems to be critical - replug necessary */ |
114 | if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD) { | 80 | if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD) |
115 | retval = -EINVAL; | 81 | return -EINVAL; |
116 | goto out; | ||
117 | } | ||
118 | 82 | ||
119 | hid_err(usb_dev, "koneplus_receive_control_status: " | 83 | hid_err(usb_dev, "koneplus_receive_control_status: " |
120 | "unknown response value 0x%x\n", control->value); | 84 | "unknown response value 0x%x\n", control.value); |
121 | retval = -EINVAL; | 85 | return -EINVAL; |
122 | goto out; | ||
123 | |||
124 | } while (1); | 86 | } while (1); |
125 | out: | ||
126 | kfree(control); | ||
127 | return retval; | ||
128 | } | 87 | } |
129 | 88 | ||
130 | static int koneplus_send(struct usb_device *usb_dev, uint command, | 89 | static int koneplus_send(struct usb_device *usb_dev, uint command, |
131 | void *buf, uint size) { | 90 | void const *buf, uint size) |
132 | int len; | 91 | { |
133 | 92 | int retval; | |
134 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), | ||
135 | USB_REQ_SET_CONFIGURATION, | ||
136 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | ||
137 | command, 0, buf, size, USB_CTRL_SET_TIMEOUT); | ||
138 | |||
139 | if (len != size) | ||
140 | return -EIO; | ||
141 | 93 | ||
142 | if (koneplus_receive_control_status(usb_dev)) | 94 | retval = roccat_common_send(usb_dev, command, buf, size); |
143 | return -EIO; | 95 | if (retval) |
96 | return retval; | ||
144 | 97 | ||
145 | return 0; | 98 | return koneplus_receive_control_status(usb_dev); |
146 | } | 99 | } |
147 | 100 | ||
148 | static int koneplus_select_profile(struct usb_device *usb_dev, uint number, | 101 | static int koneplus_select_profile(struct usb_device *usb_dev, uint number, |
@@ -167,7 +120,7 @@ static int koneplus_select_profile(struct usb_device *usb_dev, uint number, | |||
167 | static int koneplus_get_info(struct usb_device *usb_dev, | 120 | static int koneplus_get_info(struct usb_device *usb_dev, |
168 | struct koneplus_info *buf) | 121 | struct koneplus_info *buf) |
169 | { | 122 | { |
170 | return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_INFO, | 123 | return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_INFO, |
171 | buf, sizeof(struct koneplus_info)); | 124 | buf, sizeof(struct koneplus_info)); |
172 | } | 125 | } |
173 | 126 | ||
@@ -181,7 +134,7 @@ static int koneplus_get_profile_settings(struct usb_device *usb_dev, | |||
181 | if (retval) | 134 | if (retval) |
182 | return retval; | 135 | return retval; |
183 | 136 | ||
184 | return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS, | 137 | return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS, |
185 | buf, sizeof(struct koneplus_profile_settings)); | 138 | buf, sizeof(struct koneplus_profile_settings)); |
186 | } | 139 | } |
187 | 140 | ||
@@ -189,7 +142,7 @@ static int koneplus_set_profile_settings(struct usb_device *usb_dev, | |||
189 | struct koneplus_profile_settings const *settings) | 142 | struct koneplus_profile_settings const *settings) |
190 | { | 143 | { |
191 | return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS, | 144 | return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS, |
192 | (void *)settings, sizeof(struct koneplus_profile_settings)); | 145 | settings, sizeof(struct koneplus_profile_settings)); |
193 | } | 146 | } |
194 | 147 | ||
195 | static int koneplus_get_profile_buttons(struct usb_device *usb_dev, | 148 | static int koneplus_get_profile_buttons(struct usb_device *usb_dev, |
@@ -202,7 +155,7 @@ static int koneplus_get_profile_buttons(struct usb_device *usb_dev, | |||
202 | if (retval) | 155 | if (retval) |
203 | return retval; | 156 | return retval; |
204 | 157 | ||
205 | return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS, | 158 | return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS, |
206 | buf, sizeof(struct koneplus_profile_buttons)); | 159 | buf, sizeof(struct koneplus_profile_buttons)); |
207 | } | 160 | } |
208 | 161 | ||
@@ -210,29 +163,19 @@ static int koneplus_set_profile_buttons(struct usb_device *usb_dev, | |||
210 | struct koneplus_profile_buttons const *buttons) | 163 | struct koneplus_profile_buttons const *buttons) |
211 | { | 164 | { |
212 | return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS, | 165 | return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS, |
213 | (void *)buttons, sizeof(struct koneplus_profile_buttons)); | 166 | buttons, sizeof(struct koneplus_profile_buttons)); |
214 | } | 167 | } |
215 | 168 | ||
216 | /* retval is 0-4 on success, < 0 on error */ | 169 | /* retval is 0-4 on success, < 0 on error */ |
217 | static int koneplus_get_startup_profile(struct usb_device *usb_dev) | 170 | static int koneplus_get_startup_profile(struct usb_device *usb_dev) |
218 | { | 171 | { |
219 | struct koneplus_startup_profile *buf; | 172 | struct koneplus_startup_profile buf; |
220 | int retval; | 173 | int retval; |
221 | 174 | ||
222 | buf = kmalloc(sizeof(struct koneplus_startup_profile), GFP_KERNEL); | 175 | retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE, |
223 | if (buf == NULL) | 176 | &buf, sizeof(struct koneplus_startup_profile)); |
224 | return -ENOMEM; | ||
225 | |||
226 | retval = koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE, | ||
227 | buf, sizeof(struct koneplus_startup_profile)); | ||
228 | 177 | ||
229 | if (retval) | 178 | return retval ? retval : buf.startup_profile; |
230 | goto out; | ||
231 | |||
232 | retval = buf->startup_profile; | ||
233 | out: | ||
234 | kfree(buf); | ||
235 | return retval; | ||
236 | } | 179 | } |
237 | 180 | ||
238 | static int koneplus_set_startup_profile(struct usb_device *usb_dev, | 181 | static int koneplus_set_startup_profile(struct usb_device *usb_dev, |
@@ -245,7 +188,7 @@ static int koneplus_set_startup_profile(struct usb_device *usb_dev, | |||
245 | buf.startup_profile = startup_profile; | 188 | buf.startup_profile = startup_profile; |
246 | 189 | ||
247 | return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE, | 190 | return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE, |
248 | (char *)&buf, sizeof(struct koneplus_profile_buttons)); | 191 | &buf, sizeof(struct koneplus_profile_buttons)); |
249 | } | 192 | } |
250 | 193 | ||
251 | static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj, | 194 | static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj, |
@@ -265,7 +208,7 @@ static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj, | |||
265 | return -EINVAL; | 208 | return -EINVAL; |
266 | 209 | ||
267 | mutex_lock(&koneplus->koneplus_lock); | 210 | mutex_lock(&koneplus->koneplus_lock); |
268 | retval = koneplus_receive(usb_dev, command, buf, real_size); | 211 | retval = roccat_common_receive(usb_dev, command, buf, real_size); |
269 | mutex_unlock(&koneplus->koneplus_lock); | 212 | mutex_unlock(&koneplus->koneplus_lock); |
270 | 213 | ||
271 | if (retval) | 214 | if (retval) |
@@ -288,7 +231,7 @@ static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj, | |||
288 | return -EINVAL; | 231 | return -EINVAL; |
289 | 232 | ||
290 | mutex_lock(&koneplus->koneplus_lock); | 233 | mutex_lock(&koneplus->koneplus_lock); |
291 | retval = koneplus_send(usb_dev, command, (void *)buf, real_size); | 234 | retval = koneplus_send(usb_dev, command, buf, real_size); |
292 | mutex_unlock(&koneplus->koneplus_lock); | 235 | mutex_unlock(&koneplus->koneplus_lock); |
293 | 236 | ||
294 | if (retval) | 237 | if (retval) |
@@ -352,7 +295,7 @@ static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp, | |||
352 | count = sizeof(struct koneplus_profile_settings) - off; | 295 | count = sizeof(struct koneplus_profile_settings) - off; |
353 | 296 | ||
354 | mutex_lock(&koneplus->koneplus_lock); | 297 | mutex_lock(&koneplus->koneplus_lock); |
355 | memcpy(buf, ((void const *)&koneplus->profile_settings[*(uint *)(attr->private)]) + off, | 298 | memcpy(buf, ((char const *)&koneplus->profile_settings[*(uint *)(attr->private)]) + off, |
356 | count); | 299 | count); |
357 | mutex_unlock(&koneplus->koneplus_lock); | 300 | mutex_unlock(&koneplus->koneplus_lock); |
358 | 301 | ||
@@ -411,7 +354,7 @@ static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp, | |||
411 | count = sizeof(struct koneplus_profile_buttons) - off; | 354 | count = sizeof(struct koneplus_profile_buttons) - off; |
412 | 355 | ||
413 | mutex_lock(&koneplus->koneplus_lock); | 356 | mutex_lock(&koneplus->koneplus_lock); |
414 | memcpy(buf, ((void const *)&koneplus->profile_buttons[*(uint *)(attr->private)]) + off, | 357 | memcpy(buf, ((char const *)&koneplus->profile_buttons[*(uint *)(attr->private)]) + off, |
415 | count); | 358 | count); |
416 | mutex_unlock(&koneplus->koneplus_lock); | 359 | mutex_unlock(&koneplus->koneplus_lock); |
417 | 360 | ||