1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (c) 2006,2007 Daniel Mack, Tim Ruetz |
4 | */ |
5 | |
6 | #include <linux/device.h> |
7 | #include <linux/gfp.h> |
8 | #include <linux/init.h> |
9 | #include <linux/usb.h> |
10 | #include <linux/usb/input.h> |
11 | #include <sound/core.h> |
12 | #include <sound/pcm.h> |
13 | |
14 | #include "device.h" |
15 | #include "input.h" |
16 | |
17 | static const unsigned short keycode_ak1[] = { KEY_C, KEY_B, KEY_A }; |
18 | static const unsigned short keycode_rk2[] = { KEY_1, KEY_2, KEY_3, KEY_4, |
19 | KEY_5, KEY_6, KEY_7 }; |
20 | static const unsigned short keycode_rk3[] = { KEY_1, KEY_2, KEY_3, KEY_4, |
21 | KEY_5, KEY_6, KEY_7, KEY_8, KEY_9 }; |
22 | |
23 | static const unsigned short keycode_kore[] = { |
24 | KEY_FN_F1, /* "menu" */ |
25 | KEY_FN_F7, /* "lcd backlight */ |
26 | KEY_FN_F2, /* "control" */ |
27 | KEY_FN_F3, /* "enter" */ |
28 | KEY_FN_F4, /* "view" */ |
29 | KEY_FN_F5, /* "esc" */ |
30 | KEY_FN_F6, /* "sound" */ |
31 | KEY_FN_F8, /* array spacer, never triggered. */ |
32 | KEY_RIGHT, |
33 | KEY_DOWN, |
34 | KEY_UP, |
35 | KEY_LEFT, |
36 | KEY_SOUND, /* "listen" */ |
37 | KEY_RECORD, |
38 | KEY_PLAYPAUSE, |
39 | KEY_STOP, |
40 | BTN_4, /* 8 softkeys */ |
41 | BTN_3, |
42 | BTN_2, |
43 | BTN_1, |
44 | BTN_8, |
45 | BTN_7, |
46 | BTN_6, |
47 | BTN_5, |
48 | KEY_BRL_DOT4, /* touch sensitive knobs */ |
49 | KEY_BRL_DOT3, |
50 | KEY_BRL_DOT2, |
51 | KEY_BRL_DOT1, |
52 | KEY_BRL_DOT8, |
53 | KEY_BRL_DOT7, |
54 | KEY_BRL_DOT6, |
55 | KEY_BRL_DOT5 |
56 | }; |
57 | |
58 | #define MASCHINE_BUTTONS (42) |
59 | #define MASCHINE_BUTTON(X) ((X) + BTN_MISC) |
60 | #define MASCHINE_PADS (16) |
61 | #define MASCHINE_PAD(X) ((X) + ABS_PRESSURE) |
62 | |
63 | static const unsigned short keycode_maschine[] = { |
64 | MASCHINE_BUTTON(40), /* mute */ |
65 | MASCHINE_BUTTON(39), /* solo */ |
66 | MASCHINE_BUTTON(38), /* select */ |
67 | MASCHINE_BUTTON(37), /* duplicate */ |
68 | MASCHINE_BUTTON(36), /* navigate */ |
69 | MASCHINE_BUTTON(35), /* pad mode */ |
70 | MASCHINE_BUTTON(34), /* pattern */ |
71 | MASCHINE_BUTTON(33), /* scene */ |
72 | KEY_RESERVED, /* spacer */ |
73 | |
74 | MASCHINE_BUTTON(30), /* rec */ |
75 | MASCHINE_BUTTON(31), /* erase */ |
76 | MASCHINE_BUTTON(32), /* shift */ |
77 | MASCHINE_BUTTON(28), /* grid */ |
78 | MASCHINE_BUTTON(27), /* > */ |
79 | MASCHINE_BUTTON(26), /* < */ |
80 | MASCHINE_BUTTON(25), /* restart */ |
81 | |
82 | MASCHINE_BUTTON(21), /* E */ |
83 | MASCHINE_BUTTON(22), /* F */ |
84 | MASCHINE_BUTTON(23), /* G */ |
85 | MASCHINE_BUTTON(24), /* H */ |
86 | MASCHINE_BUTTON(20), /* D */ |
87 | MASCHINE_BUTTON(19), /* C */ |
88 | MASCHINE_BUTTON(18), /* B */ |
89 | MASCHINE_BUTTON(17), /* A */ |
90 | |
91 | MASCHINE_BUTTON(0), /* control */ |
92 | MASCHINE_BUTTON(2), /* browse */ |
93 | MASCHINE_BUTTON(4), /* < */ |
94 | MASCHINE_BUTTON(6), /* snap */ |
95 | MASCHINE_BUTTON(7), /* autowrite */ |
96 | MASCHINE_BUTTON(5), /* > */ |
97 | MASCHINE_BUTTON(3), /* sampling */ |
98 | MASCHINE_BUTTON(1), /* step */ |
99 | |
100 | MASCHINE_BUTTON(15), /* 8 softkeys */ |
101 | MASCHINE_BUTTON(14), |
102 | MASCHINE_BUTTON(13), |
103 | MASCHINE_BUTTON(12), |
104 | MASCHINE_BUTTON(11), |
105 | MASCHINE_BUTTON(10), |
106 | MASCHINE_BUTTON(9), |
107 | MASCHINE_BUTTON(8), |
108 | |
109 | MASCHINE_BUTTON(16), /* note repeat */ |
110 | MASCHINE_BUTTON(29) /* play */ |
111 | }; |
112 | |
113 | #define KONTROLX1_INPUTS (40) |
114 | #define KONTROLS4_BUTTONS (12 * 8) |
115 | #define KONTROLS4_AXIS (46) |
116 | |
117 | #define KONTROLS4_BUTTON(X) ((X) + BTN_MISC) |
118 | #define KONTROLS4_ABS(X) ((X) + ABS_HAT0X) |
119 | |
120 | #define DEG90 (range / 2) |
121 | #define DEG180 (range) |
122 | #define DEG270 (DEG90 + DEG180) |
123 | #define DEG360 (DEG180 * 2) |
124 | #define HIGH_PEAK (268) |
125 | #define LOW_PEAK (-7) |
126 | |
127 | /* some of these devices have endless rotation potentiometers |
128 | * built in which use two tapers, 90 degrees phase shifted. |
129 | * this algorithm decodes them to one single value, ranging |
130 | * from 0 to 999 */ |
131 | static unsigned int decode_erp(unsigned char a, unsigned char b) |
132 | { |
133 | int weight_a, weight_b; |
134 | int pos_a, pos_b; |
135 | int ret; |
136 | int range = HIGH_PEAK - LOW_PEAK; |
137 | int mid_value = (HIGH_PEAK + LOW_PEAK) / 2; |
138 | |
139 | weight_b = abs(mid_value - a) - (range / 2 - 100) / 2; |
140 | |
141 | if (weight_b < 0) |
142 | weight_b = 0; |
143 | |
144 | if (weight_b > 100) |
145 | weight_b = 100; |
146 | |
147 | weight_a = 100 - weight_b; |
148 | |
149 | if (a < mid_value) { |
150 | /* 0..90 and 270..360 degrees */ |
151 | pos_b = b - LOW_PEAK + DEG270; |
152 | if (pos_b >= DEG360) |
153 | pos_b -= DEG360; |
154 | } else |
155 | /* 90..270 degrees */ |
156 | pos_b = HIGH_PEAK - b + DEG90; |
157 | |
158 | |
159 | if (b > mid_value) |
160 | /* 0..180 degrees */ |
161 | pos_a = a - LOW_PEAK; |
162 | else |
163 | /* 180..360 degrees */ |
164 | pos_a = HIGH_PEAK - a + DEG180; |
165 | |
166 | /* interpolate both slider values, depending on weight factors */ |
167 | /* 0..99 x DEG360 */ |
168 | ret = pos_a * weight_a + pos_b * weight_b; |
169 | |
170 | /* normalize to 0..999 */ |
171 | ret *= 10; |
172 | ret /= DEG360; |
173 | |
174 | if (ret < 0) |
175 | ret += 1000; |
176 | |
177 | if (ret >= 1000) |
178 | ret -= 1000; |
179 | |
180 | return ret; |
181 | } |
182 | |
183 | #undef DEG90 |
184 | #undef DEG180 |
185 | #undef DEG270 |
186 | #undef DEG360 |
187 | #undef HIGH_PEAK |
188 | #undef LOW_PEAK |
189 | |
190 | static inline void snd_caiaq_input_report_abs(struct snd_usb_caiaqdev *cdev, |
191 | int axis, const unsigned char *buf, |
192 | int offset) |
193 | { |
194 | input_report_abs(dev: cdev->input_dev, code: axis, |
195 | value: (buf[offset * 2] << 8) | buf[offset * 2 + 1]); |
196 | } |
197 | |
198 | static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *cdev, |
199 | const unsigned char *buf, |
200 | unsigned int len) |
201 | { |
202 | struct input_dev *input_dev = cdev->input_dev; |
203 | |
204 | switch (cdev->chip.usb_id) { |
205 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): |
206 | snd_caiaq_input_report_abs(cdev, ABS_X, buf, offset: 2); |
207 | snd_caiaq_input_report_abs(cdev, ABS_Y, buf, offset: 0); |
208 | snd_caiaq_input_report_abs(cdev, ABS_Z, buf, offset: 1); |
209 | break; |
210 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): |
211 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): |
212 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): |
213 | snd_caiaq_input_report_abs(cdev, ABS_X, buf, offset: 0); |
214 | snd_caiaq_input_report_abs(cdev, ABS_Y, buf, offset: 1); |
215 | snd_caiaq_input_report_abs(cdev, ABS_Z, buf, offset: 2); |
216 | break; |
217 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): |
218 | snd_caiaq_input_report_abs(cdev, ABS_HAT0X, buf, offset: 4); |
219 | snd_caiaq_input_report_abs(cdev, ABS_HAT0Y, buf, offset: 2); |
220 | snd_caiaq_input_report_abs(cdev, ABS_HAT1X, buf, offset: 6); |
221 | snd_caiaq_input_report_abs(cdev, ABS_HAT1Y, buf, offset: 1); |
222 | snd_caiaq_input_report_abs(cdev, ABS_HAT2X, buf, offset: 7); |
223 | snd_caiaq_input_report_abs(cdev, ABS_HAT2Y, buf, offset: 0); |
224 | snd_caiaq_input_report_abs(cdev, ABS_HAT3X, buf, offset: 5); |
225 | snd_caiaq_input_report_abs(cdev, ABS_HAT3Y, buf, offset: 3); |
226 | break; |
227 | } |
228 | |
229 | input_sync(dev: input_dev); |
230 | } |
231 | |
232 | static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *cdev, |
233 | const char *buf, unsigned int len) |
234 | { |
235 | struct input_dev *input_dev = cdev->input_dev; |
236 | int i; |
237 | |
238 | switch (cdev->chip.usb_id) { |
239 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): |
240 | i = decode_erp(a: buf[0], b: buf[1]); |
241 | input_report_abs(dev: input_dev, ABS_X, value: i); |
242 | input_sync(dev: input_dev); |
243 | break; |
244 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): |
245 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): |
246 | i = decode_erp(a: buf[7], b: buf[5]); |
247 | input_report_abs(dev: input_dev, ABS_HAT0X, value: i); |
248 | i = decode_erp(a: buf[12], b: buf[14]); |
249 | input_report_abs(dev: input_dev, ABS_HAT0Y, value: i); |
250 | i = decode_erp(a: buf[15], b: buf[13]); |
251 | input_report_abs(dev: input_dev, ABS_HAT1X, value: i); |
252 | i = decode_erp(a: buf[0], b: buf[2]); |
253 | input_report_abs(dev: input_dev, ABS_HAT1Y, value: i); |
254 | i = decode_erp(a: buf[3], b: buf[1]); |
255 | input_report_abs(dev: input_dev, ABS_HAT2X, value: i); |
256 | i = decode_erp(a: buf[8], b: buf[10]); |
257 | input_report_abs(dev: input_dev, ABS_HAT2Y, value: i); |
258 | i = decode_erp(a: buf[11], b: buf[9]); |
259 | input_report_abs(dev: input_dev, ABS_HAT3X, value: i); |
260 | i = decode_erp(a: buf[4], b: buf[6]); |
261 | input_report_abs(dev: input_dev, ABS_HAT3Y, value: i); |
262 | input_sync(dev: input_dev); |
263 | break; |
264 | |
265 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER): |
266 | /* 4 under the left screen */ |
267 | input_report_abs(dev: input_dev, ABS_HAT0X, value: decode_erp(a: buf[21], b: buf[20])); |
268 | input_report_abs(dev: input_dev, ABS_HAT0Y, value: decode_erp(a: buf[15], b: buf[14])); |
269 | input_report_abs(dev: input_dev, ABS_HAT1X, value: decode_erp(a: buf[9], b: buf[8])); |
270 | input_report_abs(dev: input_dev, ABS_HAT1Y, value: decode_erp(a: buf[3], b: buf[2])); |
271 | |
272 | /* 4 under the right screen */ |
273 | input_report_abs(dev: input_dev, ABS_HAT2X, value: decode_erp(a: buf[19], b: buf[18])); |
274 | input_report_abs(dev: input_dev, ABS_HAT2Y, value: decode_erp(a: buf[13], b: buf[12])); |
275 | input_report_abs(dev: input_dev, ABS_HAT3X, value: decode_erp(a: buf[7], b: buf[6])); |
276 | input_report_abs(dev: input_dev, ABS_HAT3Y, value: decode_erp(a: buf[1], b: buf[0])); |
277 | |
278 | /* volume */ |
279 | input_report_abs(dev: input_dev, ABS_RX, value: decode_erp(a: buf[17], b: buf[16])); |
280 | /* tempo */ |
281 | input_report_abs(dev: input_dev, ABS_RY, value: decode_erp(a: buf[11], b: buf[10])); |
282 | /* swing */ |
283 | input_report_abs(dev: input_dev, ABS_RZ, value: decode_erp(a: buf[5], b: buf[4])); |
284 | |
285 | input_sync(dev: input_dev); |
286 | break; |
287 | } |
288 | } |
289 | |
290 | static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *cdev, |
291 | unsigned char *buf, unsigned int len) |
292 | { |
293 | struct input_dev *input_dev = cdev->input_dev; |
294 | unsigned short *keycode = input_dev->keycode; |
295 | int i; |
296 | |
297 | if (!keycode) |
298 | return; |
299 | |
300 | if (input_dev->id.product == USB_PID_RIGKONTROL2) |
301 | for (i = 0; i < len; i++) |
302 | buf[i] = ~buf[i]; |
303 | |
304 | for (i = 0; i < input_dev->keycodemax && i < len * 8; i++) |
305 | input_report_key(dev: input_dev, code: keycode[i], |
306 | value: buf[i / 8] & (1 << (i % 8))); |
307 | |
308 | switch (cdev->chip.usb_id) { |
309 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): |
310 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): |
311 | input_report_abs(dev: cdev->input_dev, ABS_MISC, value: 255 - buf[4]); |
312 | break; |
313 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): |
314 | /* rotary encoders */ |
315 | input_report_abs(dev: cdev->input_dev, ABS_X, value: buf[5] & 0xf); |
316 | input_report_abs(dev: cdev->input_dev, ABS_Y, value: buf[5] >> 4); |
317 | input_report_abs(dev: cdev->input_dev, ABS_Z, value: buf[6] & 0xf); |
318 | input_report_abs(dev: cdev->input_dev, ABS_MISC, value: buf[6] >> 4); |
319 | break; |
320 | } |
321 | |
322 | input_sync(dev: input_dev); |
323 | } |
324 | |
325 | #define TKS4_MSGBLOCK_SIZE 16 |
326 | |
327 | static void snd_usb_caiaq_tks4_dispatch(struct snd_usb_caiaqdev *cdev, |
328 | const unsigned char *buf, |
329 | unsigned int len) |
330 | { |
331 | struct device *dev = caiaqdev_to_dev(cdev); |
332 | |
333 | while (len) { |
334 | unsigned int i, block_id = (buf[0] << 8) | buf[1]; |
335 | |
336 | switch (block_id) { |
337 | case 0: |
338 | /* buttons */ |
339 | for (i = 0; i < KONTROLS4_BUTTONS; i++) |
340 | input_report_key(dev: cdev->input_dev, KONTROLS4_BUTTON(i), |
341 | value: (buf[4 + (i / 8)] >> (i % 8)) & 1); |
342 | break; |
343 | |
344 | case 1: |
345 | /* left wheel */ |
346 | input_report_abs(dev: cdev->input_dev, KONTROLS4_ABS(36), value: buf[9] | ((buf[8] & 0x3) << 8)); |
347 | /* right wheel */ |
348 | input_report_abs(dev: cdev->input_dev, KONTROLS4_ABS(37), value: buf[13] | ((buf[12] & 0x3) << 8)); |
349 | |
350 | /* rotary encoders */ |
351 | input_report_abs(dev: cdev->input_dev, KONTROLS4_ABS(38), value: buf[3] & 0xf); |
352 | input_report_abs(dev: cdev->input_dev, KONTROLS4_ABS(39), value: buf[4] >> 4); |
353 | input_report_abs(dev: cdev->input_dev, KONTROLS4_ABS(40), value: buf[4] & 0xf); |
354 | input_report_abs(dev: cdev->input_dev, KONTROLS4_ABS(41), value: buf[5] >> 4); |
355 | input_report_abs(dev: cdev->input_dev, KONTROLS4_ABS(42), value: buf[5] & 0xf); |
356 | input_report_abs(dev: cdev->input_dev, KONTROLS4_ABS(43), value: buf[6] >> 4); |
357 | input_report_abs(dev: cdev->input_dev, KONTROLS4_ABS(44), value: buf[6] & 0xf); |
358 | input_report_abs(dev: cdev->input_dev, KONTROLS4_ABS(45), value: buf[7] >> 4); |
359 | input_report_abs(dev: cdev->input_dev, KONTROLS4_ABS(46), value: buf[7] & 0xf); |
360 | |
361 | break; |
362 | case 2: |
363 | /* Volume Fader Channel D */ |
364 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(0), buf, offset: 1); |
365 | /* Volume Fader Channel B */ |
366 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(1), buf, offset: 2); |
367 | /* Volume Fader Channel A */ |
368 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(2), buf, offset: 3); |
369 | /* Volume Fader Channel C */ |
370 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(3), buf, offset: 4); |
371 | /* Loop Volume */ |
372 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(4), buf, offset: 6); |
373 | /* Crossfader */ |
374 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(7), buf, offset: 7); |
375 | |
376 | break; |
377 | |
378 | case 3: |
379 | /* Tempo Fader R */ |
380 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(6), buf, offset: 3); |
381 | /* Tempo Fader L */ |
382 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(5), buf, offset: 4); |
383 | /* Mic Volume */ |
384 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(8), buf, offset: 6); |
385 | /* Cue Mix */ |
386 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(9), buf, offset: 7); |
387 | |
388 | break; |
389 | |
390 | case 4: |
391 | /* Wheel distance sensor L */ |
392 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(10), buf, offset: 1); |
393 | /* Wheel distance sensor R */ |
394 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(11), buf, offset: 2); |
395 | /* Channel D EQ - Filter */ |
396 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(12), buf, offset: 3); |
397 | /* Channel D EQ - Low */ |
398 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(13), buf, offset: 4); |
399 | /* Channel D EQ - Mid */ |
400 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(14), buf, offset: 5); |
401 | /* Channel D EQ - Hi */ |
402 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(15), buf, offset: 6); |
403 | /* FX2 - dry/wet */ |
404 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(16), buf, offset: 7); |
405 | |
406 | break; |
407 | |
408 | case 5: |
409 | /* FX2 - 1 */ |
410 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(17), buf, offset: 1); |
411 | /* FX2 - 2 */ |
412 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(18), buf, offset: 2); |
413 | /* FX2 - 3 */ |
414 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(19), buf, offset: 3); |
415 | /* Channel B EQ - Filter */ |
416 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(20), buf, offset: 4); |
417 | /* Channel B EQ - Low */ |
418 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(21), buf, offset: 5); |
419 | /* Channel B EQ - Mid */ |
420 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(22), buf, offset: 6); |
421 | /* Channel B EQ - Hi */ |
422 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(23), buf, offset: 7); |
423 | |
424 | break; |
425 | |
426 | case 6: |
427 | /* Channel A EQ - Filter */ |
428 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(24), buf, offset: 1); |
429 | /* Channel A EQ - Low */ |
430 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(25), buf, offset: 2); |
431 | /* Channel A EQ - Mid */ |
432 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(26), buf, offset: 3); |
433 | /* Channel A EQ - Hi */ |
434 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(27), buf, offset: 4); |
435 | /* Channel C EQ - Filter */ |
436 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(28), buf, offset: 5); |
437 | /* Channel C EQ - Low */ |
438 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(29), buf, offset: 6); |
439 | /* Channel C EQ - Mid */ |
440 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(30), buf, offset: 7); |
441 | |
442 | break; |
443 | |
444 | case 7: |
445 | /* Channel C EQ - Hi */ |
446 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(31), buf, offset: 1); |
447 | /* FX1 - wet/dry */ |
448 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(32), buf, offset: 2); |
449 | /* FX1 - 1 */ |
450 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(33), buf, offset: 3); |
451 | /* FX1 - 2 */ |
452 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(34), buf, offset: 4); |
453 | /* FX1 - 3 */ |
454 | snd_caiaq_input_report_abs(cdev, KONTROLS4_ABS(35), buf, offset: 5); |
455 | |
456 | break; |
457 | |
458 | default: |
459 | dev_dbg(dev, "%s(): bogus block (id %d)\n" , |
460 | __func__, block_id); |
461 | return; |
462 | } |
463 | |
464 | len -= TKS4_MSGBLOCK_SIZE; |
465 | buf += TKS4_MSGBLOCK_SIZE; |
466 | } |
467 | |
468 | input_sync(dev: cdev->input_dev); |
469 | } |
470 | |
471 | #define MASCHINE_MSGBLOCK_SIZE 2 |
472 | |
473 | static void snd_usb_caiaq_maschine_dispatch(struct snd_usb_caiaqdev *cdev, |
474 | const unsigned char *buf, |
475 | unsigned int len) |
476 | { |
477 | unsigned int i, pad_id; |
478 | __le16 *pressure = (__le16 *) buf; |
479 | |
480 | for (i = 0; i < MASCHINE_PADS; i++) { |
481 | pad_id = le16_to_cpu(*pressure) >> 12; |
482 | input_report_abs(dev: cdev->input_dev, MASCHINE_PAD(pad_id), |
483 | le16_to_cpu(*pressure) & 0xfff); |
484 | pressure++; |
485 | } |
486 | |
487 | input_sync(dev: cdev->input_dev); |
488 | } |
489 | |
490 | static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb) |
491 | { |
492 | struct snd_usb_caiaqdev *cdev = urb->context; |
493 | unsigned char *buf = urb->transfer_buffer; |
494 | struct device *dev = &urb->dev->dev; |
495 | int ret; |
496 | |
497 | if (urb->status || !cdev || urb != cdev->ep4_in_urb) |
498 | return; |
499 | |
500 | switch (cdev->chip.usb_id) { |
501 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): |
502 | if (urb->actual_length < 24) |
503 | goto requeue; |
504 | |
505 | if (buf[0] & 0x3) |
506 | snd_caiaq_input_read_io(cdev, buf: buf + 1, len: 7); |
507 | |
508 | if (buf[0] & 0x4) |
509 | snd_caiaq_input_read_analog(cdev, buf: buf + 8, len: 16); |
510 | |
511 | break; |
512 | |
513 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4): |
514 | snd_usb_caiaq_tks4_dispatch(cdev, buf, len: urb->actual_length); |
515 | break; |
516 | |
517 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER): |
518 | if (urb->actual_length < (MASCHINE_PADS * MASCHINE_MSGBLOCK_SIZE)) |
519 | goto requeue; |
520 | |
521 | snd_usb_caiaq_maschine_dispatch(cdev, buf, len: urb->actual_length); |
522 | break; |
523 | } |
524 | |
525 | requeue: |
526 | cdev->ep4_in_urb->actual_length = 0; |
527 | ret = usb_submit_urb(urb: cdev->ep4_in_urb, GFP_ATOMIC); |
528 | if (ret < 0) |
529 | dev_err(dev, "unable to submit urb. OOM!?\n" ); |
530 | } |
531 | |
532 | static int snd_usb_caiaq_input_open(struct input_dev *idev) |
533 | { |
534 | struct snd_usb_caiaqdev *cdev = input_get_drvdata(dev: idev); |
535 | |
536 | if (!cdev) |
537 | return -EINVAL; |
538 | |
539 | switch (cdev->chip.usb_id) { |
540 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): |
541 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4): |
542 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER): |
543 | if (usb_submit_urb(urb: cdev->ep4_in_urb, GFP_KERNEL) != 0) |
544 | return -EIO; |
545 | break; |
546 | } |
547 | |
548 | return 0; |
549 | } |
550 | |
551 | static void snd_usb_caiaq_input_close(struct input_dev *idev) |
552 | { |
553 | struct snd_usb_caiaqdev *cdev = input_get_drvdata(dev: idev); |
554 | |
555 | if (!cdev) |
556 | return; |
557 | |
558 | switch (cdev->chip.usb_id) { |
559 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): |
560 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4): |
561 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER): |
562 | usb_kill_urb(urb: cdev->ep4_in_urb); |
563 | break; |
564 | } |
565 | } |
566 | |
567 | void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *cdev, |
568 | char *buf, |
569 | unsigned int len) |
570 | { |
571 | if (!cdev->input_dev || len < 1) |
572 | return; |
573 | |
574 | switch (buf[0]) { |
575 | case EP1_CMD_READ_ANALOG: |
576 | snd_caiaq_input_read_analog(cdev, buf: buf + 1, len: len - 1); |
577 | break; |
578 | case EP1_CMD_READ_ERP: |
579 | snd_caiaq_input_read_erp(cdev, buf: buf + 1, len: len - 1); |
580 | break; |
581 | case EP1_CMD_READ_IO: |
582 | snd_caiaq_input_read_io(cdev, buf: buf + 1, len: len - 1); |
583 | break; |
584 | } |
585 | } |
586 | |
587 | int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *cdev) |
588 | { |
589 | struct usb_device *usb_dev = cdev->chip.dev; |
590 | struct input_dev *input; |
591 | int i, ret = 0; |
592 | |
593 | input = input_allocate_device(); |
594 | if (!input) |
595 | return -ENOMEM; |
596 | |
597 | usb_make_path(dev: usb_dev, buf: cdev->phys, size: sizeof(cdev->phys)); |
598 | strlcat(p: cdev->phys, q: "/input0" , avail: sizeof(cdev->phys)); |
599 | |
600 | input->name = cdev->product_name; |
601 | input->phys = cdev->phys; |
602 | usb_to_input_id(dev: usb_dev, id: &input->id); |
603 | input->dev.parent = &usb_dev->dev; |
604 | |
605 | input_set_drvdata(dev: input, data: cdev); |
606 | |
607 | switch (cdev->chip.usb_id) { |
608 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): |
609 | input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
610 | input->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) | |
611 | BIT_MASK(ABS_Z); |
612 | BUILD_BUG_ON(sizeof(cdev->keycode) < sizeof(keycode_rk2)); |
613 | memcpy(cdev->keycode, keycode_rk2, sizeof(keycode_rk2)); |
614 | input->keycodemax = ARRAY_SIZE(keycode_rk2); |
615 | input_set_abs_params(dev: input, ABS_X, min: 0, max: 4096, fuzz: 0, flat: 10); |
616 | input_set_abs_params(dev: input, ABS_Y, min: 0, max: 4096, fuzz: 0, flat: 10); |
617 | input_set_abs_params(dev: input, ABS_Z, min: 0, max: 4096, fuzz: 0, flat: 10); |
618 | snd_usb_caiaq_set_auto_msg(cdev, digital: 1, analog: 10, erp: 0); |
619 | break; |
620 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): |
621 | input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
622 | input->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) | |
623 | BIT_MASK(ABS_Z); |
624 | BUILD_BUG_ON(sizeof(cdev->keycode) < sizeof(keycode_rk3)); |
625 | memcpy(cdev->keycode, keycode_rk3, sizeof(keycode_rk3)); |
626 | input->keycodemax = ARRAY_SIZE(keycode_rk3); |
627 | input_set_abs_params(dev: input, ABS_X, min: 0, max: 1024, fuzz: 0, flat: 10); |
628 | input_set_abs_params(dev: input, ABS_Y, min: 0, max: 1024, fuzz: 0, flat: 10); |
629 | input_set_abs_params(dev: input, ABS_Z, min: 0, max: 1024, fuzz: 0, flat: 10); |
630 | snd_usb_caiaq_set_auto_msg(cdev, digital: 1, analog: 10, erp: 0); |
631 | break; |
632 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): |
633 | input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
634 | input->absbit[0] = BIT_MASK(ABS_X); |
635 | BUILD_BUG_ON(sizeof(cdev->keycode) < sizeof(keycode_ak1)); |
636 | memcpy(cdev->keycode, keycode_ak1, sizeof(keycode_ak1)); |
637 | input->keycodemax = ARRAY_SIZE(keycode_ak1); |
638 | input_set_abs_params(dev: input, ABS_X, min: 0, max: 999, fuzz: 0, flat: 10); |
639 | snd_usb_caiaq_set_auto_msg(cdev, digital: 1, analog: 0, erp: 5); |
640 | break; |
641 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): |
642 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): |
643 | input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
644 | input->absbit[0] = BIT_MASK(ABS_HAT0X) | BIT_MASK(ABS_HAT0Y) | |
645 | BIT_MASK(ABS_HAT1X) | BIT_MASK(ABS_HAT1Y) | |
646 | BIT_MASK(ABS_HAT2X) | BIT_MASK(ABS_HAT2Y) | |
647 | BIT_MASK(ABS_HAT3X) | BIT_MASK(ABS_HAT3Y) | |
648 | BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) | |
649 | BIT_MASK(ABS_Z); |
650 | input->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC); |
651 | BUILD_BUG_ON(sizeof(cdev->keycode) < sizeof(keycode_kore)); |
652 | memcpy(cdev->keycode, keycode_kore, sizeof(keycode_kore)); |
653 | input->keycodemax = ARRAY_SIZE(keycode_kore); |
654 | input_set_abs_params(dev: input, ABS_HAT0X, min: 0, max: 999, fuzz: 0, flat: 10); |
655 | input_set_abs_params(dev: input, ABS_HAT0Y, min: 0, max: 999, fuzz: 0, flat: 10); |
656 | input_set_abs_params(dev: input, ABS_HAT1X, min: 0, max: 999, fuzz: 0, flat: 10); |
657 | input_set_abs_params(dev: input, ABS_HAT1Y, min: 0, max: 999, fuzz: 0, flat: 10); |
658 | input_set_abs_params(dev: input, ABS_HAT2X, min: 0, max: 999, fuzz: 0, flat: 10); |
659 | input_set_abs_params(dev: input, ABS_HAT2Y, min: 0, max: 999, fuzz: 0, flat: 10); |
660 | input_set_abs_params(dev: input, ABS_HAT3X, min: 0, max: 999, fuzz: 0, flat: 10); |
661 | input_set_abs_params(dev: input, ABS_HAT3Y, min: 0, max: 999, fuzz: 0, flat: 10); |
662 | input_set_abs_params(dev: input, ABS_X, min: 0, max: 4096, fuzz: 0, flat: 10); |
663 | input_set_abs_params(dev: input, ABS_Y, min: 0, max: 4096, fuzz: 0, flat: 10); |
664 | input_set_abs_params(dev: input, ABS_Z, min: 0, max: 4096, fuzz: 0, flat: 10); |
665 | input_set_abs_params(dev: input, ABS_MISC, min: 0, max: 255, fuzz: 0, flat: 1); |
666 | snd_usb_caiaq_set_auto_msg(cdev, digital: 1, analog: 10, erp: 5); |
667 | break; |
668 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): |
669 | input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
670 | input->absbit[0] = BIT_MASK(ABS_HAT0X) | BIT_MASK(ABS_HAT0Y) | |
671 | BIT_MASK(ABS_HAT1X) | BIT_MASK(ABS_HAT1Y) | |
672 | BIT_MASK(ABS_HAT2X) | BIT_MASK(ABS_HAT2Y) | |
673 | BIT_MASK(ABS_HAT3X) | BIT_MASK(ABS_HAT3Y) | |
674 | BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) | |
675 | BIT_MASK(ABS_Z); |
676 | input->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC); |
677 | BUILD_BUG_ON(sizeof(cdev->keycode) < KONTROLX1_INPUTS); |
678 | for (i = 0; i < KONTROLX1_INPUTS; i++) |
679 | cdev->keycode[i] = BTN_MISC + i; |
680 | input->keycodemax = KONTROLX1_INPUTS; |
681 | |
682 | /* analog potentiometers */ |
683 | input_set_abs_params(dev: input, ABS_HAT0X, min: 0, max: 4096, fuzz: 0, flat: 10); |
684 | input_set_abs_params(dev: input, ABS_HAT0Y, min: 0, max: 4096, fuzz: 0, flat: 10); |
685 | input_set_abs_params(dev: input, ABS_HAT1X, min: 0, max: 4096, fuzz: 0, flat: 10); |
686 | input_set_abs_params(dev: input, ABS_HAT1Y, min: 0, max: 4096, fuzz: 0, flat: 10); |
687 | input_set_abs_params(dev: input, ABS_HAT2X, min: 0, max: 4096, fuzz: 0, flat: 10); |
688 | input_set_abs_params(dev: input, ABS_HAT2Y, min: 0, max: 4096, fuzz: 0, flat: 10); |
689 | input_set_abs_params(dev: input, ABS_HAT3X, min: 0, max: 4096, fuzz: 0, flat: 10); |
690 | input_set_abs_params(dev: input, ABS_HAT3Y, min: 0, max: 4096, fuzz: 0, flat: 10); |
691 | |
692 | /* rotary encoders */ |
693 | input_set_abs_params(dev: input, ABS_X, min: 0, max: 0xf, fuzz: 0, flat: 1); |
694 | input_set_abs_params(dev: input, ABS_Y, min: 0, max: 0xf, fuzz: 0, flat: 1); |
695 | input_set_abs_params(dev: input, ABS_Z, min: 0, max: 0xf, fuzz: 0, flat: 1); |
696 | input_set_abs_params(dev: input, ABS_MISC, min: 0, max: 0xf, fuzz: 0, flat: 1); |
697 | |
698 | cdev->ep4_in_urb = usb_alloc_urb(iso_packets: 0, GFP_KERNEL); |
699 | if (!cdev->ep4_in_urb) { |
700 | ret = -ENOMEM; |
701 | goto exit_free_idev; |
702 | } |
703 | |
704 | usb_fill_bulk_urb(urb: cdev->ep4_in_urb, dev: usb_dev, |
705 | usb_rcvbulkpipe(usb_dev, 0x4), |
706 | transfer_buffer: cdev->ep4_in_buf, EP4_BUFSIZE, |
707 | complete_fn: snd_usb_caiaq_ep4_reply_dispatch, context: cdev); |
708 | ret = usb_urb_ep_type_check(urb: cdev->ep4_in_urb); |
709 | if (ret < 0) |
710 | goto exit_free_idev; |
711 | |
712 | snd_usb_caiaq_set_auto_msg(cdev, digital: 1, analog: 10, erp: 5); |
713 | |
714 | break; |
715 | |
716 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4): |
717 | input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
718 | BUILD_BUG_ON(sizeof(cdev->keycode) < KONTROLS4_BUTTONS); |
719 | for (i = 0; i < KONTROLS4_BUTTONS; i++) |
720 | cdev->keycode[i] = KONTROLS4_BUTTON(i); |
721 | input->keycodemax = KONTROLS4_BUTTONS; |
722 | |
723 | for (i = 0; i < KONTROLS4_AXIS; i++) { |
724 | int axis = KONTROLS4_ABS(i); |
725 | input->absbit[BIT_WORD(axis)] |= BIT_MASK(axis); |
726 | } |
727 | |
728 | /* 36 analog potentiometers and faders */ |
729 | for (i = 0; i < 36; i++) |
730 | input_set_abs_params(dev: input, KONTROLS4_ABS(i), min: 0, max: 0xfff, fuzz: 0, flat: 10); |
731 | |
732 | /* 2 encoder wheels */ |
733 | input_set_abs_params(dev: input, KONTROLS4_ABS(36), min: 0, max: 0x3ff, fuzz: 0, flat: 1); |
734 | input_set_abs_params(dev: input, KONTROLS4_ABS(37), min: 0, max: 0x3ff, fuzz: 0, flat: 1); |
735 | |
736 | /* 9 rotary encoders */ |
737 | for (i = 0; i < 9; i++) |
738 | input_set_abs_params(dev: input, KONTROLS4_ABS(38+i), min: 0, max: 0xf, fuzz: 0, flat: 1); |
739 | |
740 | cdev->ep4_in_urb = usb_alloc_urb(iso_packets: 0, GFP_KERNEL); |
741 | if (!cdev->ep4_in_urb) { |
742 | ret = -ENOMEM; |
743 | goto exit_free_idev; |
744 | } |
745 | |
746 | usb_fill_bulk_urb(urb: cdev->ep4_in_urb, dev: usb_dev, |
747 | usb_rcvbulkpipe(usb_dev, 0x4), |
748 | transfer_buffer: cdev->ep4_in_buf, EP4_BUFSIZE, |
749 | complete_fn: snd_usb_caiaq_ep4_reply_dispatch, context: cdev); |
750 | ret = usb_urb_ep_type_check(urb: cdev->ep4_in_urb); |
751 | if (ret < 0) |
752 | goto exit_free_idev; |
753 | |
754 | snd_usb_caiaq_set_auto_msg(cdev, digital: 1, analog: 10, erp: 5); |
755 | |
756 | break; |
757 | |
758 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER): |
759 | input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
760 | input->absbit[0] = BIT_MASK(ABS_HAT0X) | BIT_MASK(ABS_HAT0Y) | |
761 | BIT_MASK(ABS_HAT1X) | BIT_MASK(ABS_HAT1Y) | |
762 | BIT_MASK(ABS_HAT2X) | BIT_MASK(ABS_HAT2Y) | |
763 | BIT_MASK(ABS_HAT3X) | BIT_MASK(ABS_HAT3Y) | |
764 | BIT_MASK(ABS_RX) | BIT_MASK(ABS_RY) | |
765 | BIT_MASK(ABS_RZ); |
766 | |
767 | BUILD_BUG_ON(sizeof(cdev->keycode) < sizeof(keycode_maschine)); |
768 | memcpy(cdev->keycode, keycode_maschine, sizeof(keycode_maschine)); |
769 | input->keycodemax = ARRAY_SIZE(keycode_maschine); |
770 | |
771 | for (i = 0; i < MASCHINE_PADS; i++) { |
772 | input->absbit[0] |= MASCHINE_PAD(i); |
773 | input_set_abs_params(dev: input, MASCHINE_PAD(i), min: 0, max: 0xfff, fuzz: 5, flat: 10); |
774 | } |
775 | |
776 | input_set_abs_params(dev: input, ABS_HAT0X, min: 0, max: 999, fuzz: 0, flat: 10); |
777 | input_set_abs_params(dev: input, ABS_HAT0Y, min: 0, max: 999, fuzz: 0, flat: 10); |
778 | input_set_abs_params(dev: input, ABS_HAT1X, min: 0, max: 999, fuzz: 0, flat: 10); |
779 | input_set_abs_params(dev: input, ABS_HAT1Y, min: 0, max: 999, fuzz: 0, flat: 10); |
780 | input_set_abs_params(dev: input, ABS_HAT2X, min: 0, max: 999, fuzz: 0, flat: 10); |
781 | input_set_abs_params(dev: input, ABS_HAT2Y, min: 0, max: 999, fuzz: 0, flat: 10); |
782 | input_set_abs_params(dev: input, ABS_HAT3X, min: 0, max: 999, fuzz: 0, flat: 10); |
783 | input_set_abs_params(dev: input, ABS_HAT3Y, min: 0, max: 999, fuzz: 0, flat: 10); |
784 | input_set_abs_params(dev: input, ABS_RX, min: 0, max: 999, fuzz: 0, flat: 10); |
785 | input_set_abs_params(dev: input, ABS_RY, min: 0, max: 999, fuzz: 0, flat: 10); |
786 | input_set_abs_params(dev: input, ABS_RZ, min: 0, max: 999, fuzz: 0, flat: 10); |
787 | |
788 | cdev->ep4_in_urb = usb_alloc_urb(iso_packets: 0, GFP_KERNEL); |
789 | if (!cdev->ep4_in_urb) { |
790 | ret = -ENOMEM; |
791 | goto exit_free_idev; |
792 | } |
793 | |
794 | usb_fill_bulk_urb(urb: cdev->ep4_in_urb, dev: usb_dev, |
795 | usb_rcvbulkpipe(usb_dev, 0x4), |
796 | transfer_buffer: cdev->ep4_in_buf, EP4_BUFSIZE, |
797 | complete_fn: snd_usb_caiaq_ep4_reply_dispatch, context: cdev); |
798 | ret = usb_urb_ep_type_check(urb: cdev->ep4_in_urb); |
799 | if (ret < 0) |
800 | goto exit_free_idev; |
801 | |
802 | snd_usb_caiaq_set_auto_msg(cdev, digital: 1, analog: 10, erp: 5); |
803 | break; |
804 | |
805 | default: |
806 | /* no input methods supported on this device */ |
807 | ret = -EINVAL; |
808 | goto exit_free_idev; |
809 | } |
810 | |
811 | input->open = snd_usb_caiaq_input_open; |
812 | input->close = snd_usb_caiaq_input_close; |
813 | input->keycode = cdev->keycode; |
814 | input->keycodesize = sizeof(unsigned short); |
815 | for (i = 0; i < input->keycodemax; i++) |
816 | __set_bit(cdev->keycode[i], input->keybit); |
817 | |
818 | cdev->input_dev = input; |
819 | |
820 | ret = input_register_device(input); |
821 | if (ret < 0) |
822 | goto exit_free_idev; |
823 | |
824 | return 0; |
825 | |
826 | exit_free_idev: |
827 | input_free_device(dev: input); |
828 | cdev->input_dev = NULL; |
829 | return ret; |
830 | } |
831 | |
832 | void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *cdev) |
833 | { |
834 | if (!cdev || !cdev->input_dev) |
835 | return; |
836 | |
837 | usb_kill_urb(urb: cdev->ep4_in_urb); |
838 | usb_free_urb(urb: cdev->ep4_in_urb); |
839 | cdev->ep4_in_urb = NULL; |
840 | |
841 | input_unregister_device(cdev->input_dev); |
842 | cdev->input_dev = NULL; |
843 | } |
844 | |