Commit | Line | Data |
---|---|---|
705ececd | 1 | /* |
e1a164d7 | 2 | * Line6 Linux USB driver - 0.9.1beta |
705ececd | 3 | * |
1027f476 | 4 | * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) |
705ececd MG |
5 | * |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License as | |
8 | * published by the Free Software Foundation, version 2. | |
9 | * | |
10 | */ | |
11 | ||
705ececd MG |
12 | #include <linux/kernel.h> |
13 | #include <linux/module.h> | |
5a0e3ad6 | 14 | #include <linux/slab.h> |
705ececd MG |
15 | #include <linux/usb.h> |
16 | ||
17 | #include "audio.h" | |
18 | #include "capture.h" | |
19 | #include "control.h" | |
1027f476 | 20 | #include "driver.h" |
705ececd MG |
21 | #include "midi.h" |
22 | #include "playback.h" | |
23 | #include "pod.h" | |
16dc1040 | 24 | #include "podhd.h" |
705ececd MG |
25 | #include "revision.h" |
26 | #include "toneport.h" | |
27 | #include "usbdefs.h" | |
28 | #include "variax.h" | |
29 | ||
705ececd MG |
30 | #define DRIVER_AUTHOR "Markus Grabner <grabner@icg.tugraz.at>" |
31 | #define DRIVER_DESC "Line6 USB Driver" | |
e1a164d7 | 32 | #define DRIVER_VERSION "0.9.1beta" DRIVER_REVISION |
705ececd MG |
33 | |
34 | /* table of devices that work with this driver */ | |
a457732b | 35 | static const struct usb_device_id line6_id_table[] = { |
e1a164d7 MG |
36 | {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXT)}, |
37 | {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXTLIVE)}, | |
38 | {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXTPRO)}, | |
39 | {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_GUITARPORT)}, | |
40 | {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_POCKETPOD)}, | |
4c6fb5fc MG |
41 | {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODHD300)}, |
42 | {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODHD500)}, | |
e1a164d7 MG |
43 | {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODSTUDIO_GX)}, |
44 | {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODSTUDIO_UX1)}, | |
45 | {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODSTUDIO_UX2)}, | |
46 | {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODX3)}, | |
47 | {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODX3LIVE)}, | |
48 | {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODXT)}, | |
49 | {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODXTLIVE)}, | |
50 | {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODXTPRO)}, | |
51 | {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_TONEPORT_GX)}, | |
52 | {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_TONEPORT_UX1)}, | |
53 | {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_TONEPORT_UX2)}, | |
54 | {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_VARIAX)}, | |
55 | {}, | |
705ececd | 56 | }; |
e1a164d7 | 57 | |
36445bc1 | 58 | MODULE_DEVICE_TABLE(usb, line6_id_table); |
705ececd | 59 | |
e1a164d7 | 60 | /* *INDENT-OFF* */ |
705ececd | 61 | static struct line6_properties line6_properties_table[] = { |
4c6fb5fc MG |
62 | { LINE6_BIT_BASSPODXT, "BassPODxt", "BassPODxt", LINE6_BIT_CONTROL_PCM_HWMON }, |
63 | { LINE6_BIT_BASSPODXTLIVE, "BassPODxtLive", "BassPODxt Live", LINE6_BIT_CONTROL_PCM_HWMON }, | |
64 | { LINE6_BIT_BASSPODXTPRO, "BassPODxtPro", "BassPODxt Pro", LINE6_BIT_CONTROL_PCM_HWMON }, | |
65 | { LINE6_BIT_GUITARPORT, "GuitarPort", "GuitarPort", LINE6_BIT_PCM }, | |
66 | { LINE6_BIT_POCKETPOD, "PocketPOD", "Pocket POD", LINE6_BIT_CONTROL }, | |
67 | { LINE6_BIT_PODHD300, "PODHD300", "POD HD300", LINE6_BIT_CONTROL_PCM_HWMON }, | |
68 | { LINE6_BIT_PODHD500, "PODHD500", "POD HD500", LINE6_BIT_CONTROL_PCM_HWMON }, | |
69 | { LINE6_BIT_PODSTUDIO_GX, "PODStudioGX", "POD Studio GX", LINE6_BIT_PCM }, | |
70 | { LINE6_BIT_PODSTUDIO_UX1, "PODStudioUX1", "POD Studio UX1", LINE6_BIT_PCM }, | |
71 | { LINE6_BIT_PODSTUDIO_UX2, "PODStudioUX2", "POD Studio UX2", LINE6_BIT_PCM }, | |
72 | { LINE6_BIT_PODX3, "PODX3", "POD X3", LINE6_BIT_PCM }, | |
73 | { LINE6_BIT_PODX3LIVE, "PODX3Live", "POD X3 Live", LINE6_BIT_PCM }, | |
74 | { LINE6_BIT_PODXT, "PODxt", "PODxt", LINE6_BIT_CONTROL_PCM_HWMON }, | |
75 | { LINE6_BIT_PODXTLIVE, "PODxtLive", "PODxt Live", LINE6_BIT_CONTROL_PCM_HWMON }, | |
76 | { LINE6_BIT_PODXTPRO, "PODxtPro", "PODxt Pro", LINE6_BIT_CONTROL_PCM_HWMON }, | |
77 | { LINE6_BIT_TONEPORT_GX, "TonePortGX", "TonePort GX", LINE6_BIT_PCM }, | |
78 | { LINE6_BIT_TONEPORT_UX1, "TonePortUX1", "TonePort UX1", LINE6_BIT_PCM }, | |
79 | { LINE6_BIT_TONEPORT_UX2, "TonePortUX2", "TonePort UX2", LINE6_BIT_PCM }, | |
80 | { LINE6_BIT_VARIAX, "Variax", "Variax Workbench", LINE6_BIT_CONTROL }, | |
705ececd | 81 | }; |
e1a164d7 | 82 | /* *INDENT-ON* */ |
705ececd MG |
83 | |
84 | /* | |
85 | This is Line6's MIDI manufacturer ID. | |
86 | */ | |
1027f476 MG |
87 | const unsigned char line6_midi_id[] = { |
88 | 0x00, 0x01, 0x0c | |
89 | }; | |
90 | ||
91 | /* | |
92 | Code to request version of POD, Variax interface | |
93 | (and maybe other devices). | |
94 | */ | |
c46b8a65 | 95 | static const char line6_request_version[] = { |
1027f476 MG |
96 | 0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7 |
97 | }; | |
98 | ||
705ececd | 99 | struct usb_line6 *line6_devices[LINE6_MAX_DEVICES]; |
705ececd | 100 | |
705ececd MG |
101 | /** |
102 | Class for asynchronous messages. | |
103 | */ | |
36445bc1 | 104 | struct message { |
705ececd MG |
105 | struct usb_line6 *line6; |
106 | const char *buffer; | |
107 | int size; | |
108 | int done; | |
109 | }; | |
110 | ||
705ececd MG |
111 | /* |
112 | Forward declarations. | |
113 | */ | |
0c7ab158 | 114 | static void line6_data_received(struct urb *urb); |
36445bc1 GKH |
115 | static int line6_send_raw_message_async_part(struct message *msg, |
116 | struct urb *urb); | |
705ececd | 117 | |
705ececd MG |
118 | /* |
119 | Start to listen on endpoint. | |
120 | */ | |
121 | static int line6_start_listen(struct usb_line6 *line6) | |
122 | { | |
1027f476 | 123 | int err; |
36445bc1 GKH |
124 | usb_fill_int_urb(line6->urb_listen, line6->usbdev, |
125 | usb_rcvintpipe(line6->usbdev, line6->ep_control_read), | |
126 | line6->buffer_listen, LINE6_BUFSIZE_LISTEN, | |
127 | line6_data_received, line6, line6->interval); | |
705ececd | 128 | line6->urb_listen->actual_length = 0; |
e1a164d7 | 129 | err = usb_submit_urb(line6->urb_listen, GFP_ATOMIC); |
1027f476 MG |
130 | return err; |
131 | } | |
132 | ||
133 | /* | |
134 | Stop listening on endpoint. | |
135 | */ | |
136 | static void line6_stop_listen(struct usb_line6 *line6) | |
137 | { | |
138 | usb_kill_urb(line6->urb_listen); | |
705ececd MG |
139 | } |
140 | ||
1027f476 | 141 | #ifdef CONFIG_LINE6_USB_DUMP_ANY |
705ececd MG |
142 | /* |
143 | Write hexdump to syslog. | |
144 | */ | |
36445bc1 GKH |
145 | void line6_write_hexdump(struct usb_line6 *line6, char dir, |
146 | const unsigned char *buffer, int size) | |
705ececd MG |
147 | { |
148 | static const int BYTES_PER_LINE = 8; | |
149 | char hexdump[100]; | |
150 | char asc[BYTES_PER_LINE + 1]; | |
151 | int i, j; | |
152 | ||
36445bc1 | 153 | for (i = 0; i < size; i += BYTES_PER_LINE) { |
705ececd MG |
154 | int hexdumpsize = sizeof(hexdump); |
155 | char *p = hexdump; | |
156 | int n = min(size - i, BYTES_PER_LINE); | |
157 | asc[n] = 0; | |
158 | ||
36445bc1 | 159 | for (j = 0; j < BYTES_PER_LINE; ++j) { |
705ececd MG |
160 | int bytes; |
161 | ||
36445bc1 | 162 | if (j < n) { |
705ececd MG |
163 | unsigned char val = buffer[i + j]; |
164 | bytes = snprintf(p, hexdumpsize, " %02X", val); | |
e1a164d7 MG |
165 | asc[j] = ((val >= 0x20) |
166 | && (val < 0x7f)) ? val : '.'; | |
36445bc1 | 167 | } else |
705ececd MG |
168 | bytes = snprintf(p, hexdumpsize, " "); |
169 | ||
36445bc1 | 170 | if (bytes > hexdumpsize) |
e1a164d7 | 171 | break; /* buffer overflow */ |
705ececd MG |
172 | |
173 | p += bytes; | |
174 | hexdumpsize -= bytes; | |
175 | } | |
176 | ||
177 | dev_info(line6->ifcdev, "%c%04X:%s %s\n", dir, i, hexdump, asc); | |
178 | } | |
179 | } | |
180 | #endif | |
181 | ||
1027f476 | 182 | #ifdef CONFIG_LINE6_USB_DUMP_CTRL |
705ececd MG |
183 | /* |
184 | Dump URB data to syslog. | |
185 | */ | |
186 | static void line6_dump_urb(struct urb *urb) | |
187 | { | |
188 | struct usb_line6 *line6 = (struct usb_line6 *)urb->context; | |
189 | ||
36445bc1 | 190 | if (urb->status < 0) |
705ececd MG |
191 | return; |
192 | ||
36445bc1 GKH |
193 | line6_write_hexdump(line6, 'R', (unsigned char *)urb->transfer_buffer, |
194 | urb->actual_length); | |
705ececd MG |
195 | } |
196 | #endif | |
197 | ||
198 | /* | |
1027f476 | 199 | Send raw message in pieces of wMaxPacketSize bytes. |
705ececd | 200 | */ |
36445bc1 GKH |
201 | int line6_send_raw_message(struct usb_line6 *line6, const char *buffer, |
202 | int size) | |
705ececd MG |
203 | { |
204 | int i, done = 0; | |
205 | ||
1027f476 | 206 | #ifdef CONFIG_LINE6_USB_DUMP_CTRL |
705ececd MG |
207 | line6_write_hexdump(line6, 'S', buffer, size); |
208 | #endif | |
209 | ||
1027f476 MG |
210 | for (i = 0; i < size; i += line6->max_packet_size) { |
211 | int partial; | |
705ececd MG |
212 | const char *frag_buf = buffer + i; |
213 | int frag_size = min(line6->max_packet_size, size - i); | |
36445bc1 GKH |
214 | int retval; |
215 | ||
216 | retval = usb_interrupt_msg(line6->usbdev, | |
217 | usb_sndintpipe(line6->usbdev, | |
218 | line6->ep_control_write), | |
219 | (char *)frag_buf, frag_size, | |
1027f476 | 220 | &partial, LINE6_TIMEOUT * HZ); |
705ececd | 221 | |
36445bc1 GKH |
222 | if (retval) { |
223 | dev_err(line6->ifcdev, | |
224 | "usb_interrupt_msg failed (%d)\n", retval); | |
705ececd MG |
225 | break; |
226 | } | |
227 | ||
1027f476 | 228 | done += frag_size; |
705ececd MG |
229 | } |
230 | ||
231 | return done; | |
232 | } | |
233 | ||
234 | /* | |
235 | Notification of completion of asynchronous request transmission. | |
236 | */ | |
0c7ab158 | 237 | static void line6_async_request_sent(struct urb *urb) |
705ececd MG |
238 | { |
239 | struct message *msg = (struct message *)urb->context; | |
240 | ||
36445bc1 | 241 | if (msg->done >= msg->size) { |
705ececd MG |
242 | usb_free_urb(urb); |
243 | kfree(msg); | |
36445bc1 | 244 | } else |
705ececd MG |
245 | line6_send_raw_message_async_part(msg, urb); |
246 | } | |
247 | ||
248 | /* | |
249 | Asynchronously send part of a raw message. | |
250 | */ | |
36445bc1 GKH |
251 | static int line6_send_raw_message_async_part(struct message *msg, |
252 | struct urb *urb) | |
705ececd MG |
253 | { |
254 | int retval; | |
255 | struct usb_line6 *line6 = msg->line6; | |
256 | int done = msg->done; | |
257 | int bytes = min(msg->size - done, line6->max_packet_size); | |
258 | ||
36445bc1 GKH |
259 | usb_fill_int_urb(urb, line6->usbdev, |
260 | usb_sndintpipe(line6->usbdev, line6->ep_control_write), | |
261 | (char *)msg->buffer + done, bytes, | |
262 | line6_async_request_sent, msg, line6->interval); | |
705ececd | 263 | |
1027f476 | 264 | #ifdef CONFIG_LINE6_USB_DUMP_CTRL |
705ececd MG |
265 | line6_write_hexdump(line6, 'S', (char *)msg->buffer + done, bytes); |
266 | #endif | |
267 | ||
268 | msg->done += bytes; | |
269 | retval = usb_submit_urb(urb, GFP_ATOMIC); | |
270 | ||
36445bc1 GKH |
271 | if (retval < 0) { |
272 | dev_err(line6->ifcdev, "%s: usb_submit_urb failed (%d)\n", | |
273 | __func__, retval); | |
705ececd MG |
274 | usb_free_urb(urb); |
275 | kfree(msg); | |
276 | return -EINVAL; | |
277 | } | |
278 | ||
279 | return 0; | |
280 | } | |
281 | ||
1027f476 MG |
282 | /* |
283 | Setup and start timer. | |
284 | */ | |
285 | void line6_start_timer(struct timer_list *timer, unsigned int msecs, | |
e1a164d7 | 286 | void (*function) (unsigned long), unsigned long data) |
1027f476 MG |
287 | { |
288 | setup_timer(timer, function, data); | |
289 | timer->expires = jiffies + msecs * HZ / 1000; | |
290 | add_timer(timer); | |
291 | } | |
292 | ||
705ececd MG |
293 | /* |
294 | Asynchronously send raw message. | |
295 | */ | |
36445bc1 GKH |
296 | int line6_send_raw_message_async(struct usb_line6 *line6, const char *buffer, |
297 | int size) | |
705ececd MG |
298 | { |
299 | struct message *msg; | |
300 | struct urb *urb; | |
301 | ||
302 | /* create message: */ | |
303 | msg = kmalloc(sizeof(struct message), GFP_ATOMIC); | |
304 | ||
36445bc1 | 305 | if (msg == NULL) { |
705ececd MG |
306 | dev_err(line6->ifcdev, "Out of memory\n"); |
307 | return -ENOMEM; | |
308 | } | |
309 | ||
310 | /* create URB: */ | |
311 | urb = usb_alloc_urb(0, GFP_ATOMIC); | |
312 | ||
36445bc1 | 313 | if (urb == NULL) { |
705ececd MG |
314 | kfree(msg); |
315 | dev_err(line6->ifcdev, "Out of memory\n"); | |
316 | return -ENOMEM; | |
317 | } | |
318 | ||
319 | /* set message data: */ | |
320 | msg->line6 = line6; | |
321 | msg->buffer = buffer; | |
322 | msg->size = size; | |
323 | msg->done = 0; | |
324 | ||
325 | /* start sending: */ | |
326 | return line6_send_raw_message_async_part(msg, urb); | |
327 | } | |
328 | ||
1027f476 MG |
329 | /* |
330 | Send asynchronous device version request. | |
331 | */ | |
332 | int line6_version_request_async(struct usb_line6 *line6) | |
333 | { | |
c46b8a65 GKH |
334 | char *buffer; |
335 | int retval; | |
336 | ||
337 | buffer = kmalloc(sizeof(line6_request_version), GFP_ATOMIC); | |
338 | if (buffer == NULL) { | |
339 | dev_err(line6->ifcdev, "Out of memory"); | |
340 | return -ENOMEM; | |
341 | } | |
342 | ||
343 | memcpy(buffer, line6_request_version, sizeof(line6_request_version)); | |
344 | ||
345 | retval = line6_send_raw_message_async(line6, buffer, | |
346 | sizeof(line6_request_version)); | |
347 | kfree(buffer); | |
348 | return retval; | |
1027f476 MG |
349 | } |
350 | ||
705ececd MG |
351 | /* |
352 | Send sysex message in pieces of wMaxPacketSize bytes. | |
353 | */ | |
36445bc1 GKH |
354 | int line6_send_sysex_message(struct usb_line6 *line6, const char *buffer, |
355 | int size) | |
705ececd | 356 | { |
e1a164d7 MG |
357 | return line6_send_raw_message(line6, buffer, |
358 | size + SYSEX_EXTRA_SIZE) - | |
359 | SYSEX_EXTRA_SIZE; | |
705ececd MG |
360 | } |
361 | ||
1027f476 MG |
362 | /* |
363 | Send sysex message in pieces of wMaxPacketSize bytes. | |
364 | */ | |
365 | int line6_send_sysex_message_async(struct usb_line6 *line6, const char *buffer, | |
366 | int size) | |
367 | { | |
e1a164d7 MG |
368 | return line6_send_raw_message_async(line6, buffer, |
369 | size + SYSEX_EXTRA_SIZE) - | |
370 | SYSEX_EXTRA_SIZE; | |
1027f476 MG |
371 | } |
372 | ||
705ececd MG |
373 | /* |
374 | Allocate buffer for sysex message and prepare header. | |
375 | @param code sysex message code | |
376 | @param size number of bytes between code and sysex end | |
377 | */ | |
36445bc1 GKH |
378 | char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1, int code2, |
379 | int size) | |
705ececd | 380 | { |
1027f476 | 381 | char *buffer = kmalloc(size + SYSEX_EXTRA_SIZE, GFP_ATOMIC); |
705ececd | 382 | |
36445bc1 | 383 | if (!buffer) { |
705ececd | 384 | dev_err(line6->ifcdev, "out of memory\n"); |
536165d8 | 385 | return NULL; |
705ececd MG |
386 | } |
387 | ||
388 | buffer[0] = LINE6_SYSEX_BEGIN; | |
389 | memcpy(buffer + 1, line6_midi_id, sizeof(line6_midi_id)); | |
390 | buffer[sizeof(line6_midi_id) + 1] = code1; | |
391 | buffer[sizeof(line6_midi_id) + 2] = code2; | |
392 | buffer[sizeof(line6_midi_id) + 3 + size] = LINE6_SYSEX_END; | |
393 | return buffer; | |
394 | } | |
395 | ||
396 | /* | |
397 | Notification of data received from the Line6 device. | |
398 | */ | |
0c7ab158 | 399 | static void line6_data_received(struct urb *urb) |
705ececd MG |
400 | { |
401 | struct usb_line6 *line6 = (struct usb_line6 *)urb->context; | |
402 | struct MidiBuffer *mb = &line6->line6midi->midibuf_in; | |
403 | int done; | |
404 | ||
36445bc1 | 405 | if (urb->status == -ESHUTDOWN) |
705ececd MG |
406 | return; |
407 | ||
1027f476 | 408 | #ifdef CONFIG_LINE6_USB_DUMP_CTRL |
705ececd MG |
409 | line6_dump_urb(urb); |
410 | #endif | |
411 | ||
e1a164d7 MG |
412 | done = |
413 | line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length); | |
705ececd | 414 | |
36445bc1 | 415 | if (done < urb->actual_length) { |
1027f476 | 416 | line6_midibuf_ignore(mb, done); |
e1a164d7 MG |
417 | DEBUG_MESSAGES(dev_err |
418 | (line6->ifcdev, | |
419 | "%d %d buffer overflow - message skipped\n", | |
420 | done, urb->actual_length)); | |
705ececd MG |
421 | } |
422 | ||
36445bc1 | 423 | for (;;) { |
e1a164d7 MG |
424 | done = |
425 | line6_midibuf_read(mb, line6->buffer_message, | |
426 | LINE6_MESSAGE_MAXLEN); | |
705ececd | 427 | |
36445bc1 | 428 | if (done == 0) |
705ececd MG |
429 | break; |
430 | ||
431 | /* MIDI input filter */ | |
e1a164d7 MG |
432 | if (line6_midibuf_skip_message |
433 | (mb, line6->line6midi->midi_mask_receive)) | |
705ececd MG |
434 | continue; |
435 | ||
436 | line6->message_length = done; | |
1027f476 | 437 | #ifdef CONFIG_LINE6_USB_DUMP_MIDI |
705ececd MG |
438 | line6_write_hexdump(line6, 'r', line6->buffer_message, done); |
439 | #endif | |
440 | line6_midi_receive(line6, line6->buffer_message, done); | |
441 | ||
36445bc1 | 442 | switch (line6->usbdev->descriptor.idProduct) { |
705ececd MG |
443 | case LINE6_DEVID_BASSPODXT: |
444 | case LINE6_DEVID_BASSPODXTLIVE: | |
445 | case LINE6_DEVID_BASSPODXTPRO: | |
446 | case LINE6_DEVID_PODXT: | |
447 | case LINE6_DEVID_PODXTPRO: | |
448 | case LINE6_DEVID_POCKETPOD: | |
e1a164d7 MG |
449 | line6_pod_process_message((struct usb_line6_pod *) |
450 | line6); | |
705ececd MG |
451 | break; |
452 | ||
16dc1040 | 453 | case LINE6_DEVID_PODHD300: |
4c6fb5fc | 454 | case LINE6_DEVID_PODHD500: |
16dc1040 SH |
455 | break; /* let userspace handle MIDI */ |
456 | ||
705ececd | 457 | case LINE6_DEVID_PODXTLIVE: |
36445bc1 | 458 | switch (line6->interface_number) { |
705ececd | 459 | case PODXTLIVE_INTERFACE_POD: |
e1a164d7 MG |
460 | line6_pod_process_message((struct usb_line6_pod |
461 | *)line6); | |
705ececd MG |
462 | break; |
463 | ||
464 | case PODXTLIVE_INTERFACE_VARIAX: | |
e1a164d7 MG |
465 | line6_variax_process_message((struct |
466 | usb_line6_variax | |
467 | *)line6); | |
705ececd MG |
468 | break; |
469 | ||
470 | default: | |
e1a164d7 MG |
471 | dev_err(line6->ifcdev, |
472 | "PODxt Live interface %d not supported\n", | |
473 | line6->interface_number); | |
705ececd MG |
474 | } |
475 | break; | |
476 | ||
477 | case LINE6_DEVID_VARIAX: | |
e1a164d7 MG |
478 | line6_variax_process_message((struct usb_line6_variax *) |
479 | line6); | |
705ececd MG |
480 | break; |
481 | ||
482 | default: | |
483 | MISSING_CASE; | |
484 | } | |
485 | } | |
486 | ||
487 | line6_start_listen(line6); | |
488 | } | |
489 | ||
490 | /* | |
491 | Send channel number (i.e., switch to a different sound). | |
492 | */ | |
317e188b | 493 | int line6_send_program(struct usb_line6 *line6, u8 value) |
705ececd | 494 | { |
1027f476 | 495 | int retval; |
705ececd | 496 | unsigned char *buffer; |
1027f476 MG |
497 | int partial; |
498 | ||
499 | buffer = kmalloc(2, GFP_KERNEL); | |
705ececd | 500 | |
36445bc1 | 501 | if (!buffer) { |
705ececd MG |
502 | dev_err(line6->ifcdev, "out of memory\n"); |
503 | return -ENOMEM; | |
504 | } | |
505 | ||
506 | buffer[0] = LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST; | |
507 | buffer[1] = value; | |
508 | ||
1027f476 MG |
509 | #ifdef CONFIG_LINE6_USB_DUMP_CTRL |
510 | line6_write_hexdump(line6, 'S', buffer, 2); | |
511 | #endif | |
512 | ||
513 | retval = usb_interrupt_msg(line6->usbdev, | |
514 | usb_sndintpipe(line6->usbdev, | |
515 | line6->ep_control_write), | |
516 | buffer, 2, &partial, LINE6_TIMEOUT * HZ); | |
517 | ||
518 | if (retval) | |
e1a164d7 MG |
519 | dev_err(line6->ifcdev, "usb_interrupt_msg failed (%d)\n", |
520 | retval); | |
1027f476 MG |
521 | |
522 | kfree(buffer); | |
523 | return retval; | |
705ececd MG |
524 | } |
525 | ||
526 | /* | |
527 | Transmit Line6 control parameter. | |
528 | */ | |
2471c093 | 529 | int line6_transmit_parameter(struct usb_line6 *line6, int param, u8 value) |
705ececd | 530 | { |
1027f476 | 531 | int retval; |
705ececd | 532 | unsigned char *buffer; |
1027f476 MG |
533 | int partial; |
534 | ||
535 | buffer = kmalloc(3, GFP_KERNEL); | |
705ececd | 536 | |
36445bc1 | 537 | if (!buffer) { |
705ececd MG |
538 | dev_err(line6->ifcdev, "out of memory\n"); |
539 | return -ENOMEM; | |
540 | } | |
541 | ||
542 | buffer[0] = LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST; | |
543 | buffer[1] = param; | |
544 | buffer[2] = value; | |
545 | ||
1027f476 MG |
546 | #ifdef CONFIG_LINE6_USB_DUMP_CTRL |
547 | line6_write_hexdump(line6, 'S', buffer, 3); | |
548 | #endif | |
549 | ||
550 | retval = usb_interrupt_msg(line6->usbdev, | |
e1a164d7 MG |
551 | usb_sndintpipe(line6->usbdev, |
552 | line6->ep_control_write), | |
1027f476 MG |
553 | buffer, 3, &partial, LINE6_TIMEOUT * HZ); |
554 | ||
555 | if (retval) | |
e1a164d7 MG |
556 | dev_err(line6->ifcdev, "usb_interrupt_msg failed (%d)\n", |
557 | retval); | |
1027f476 MG |
558 | |
559 | kfree(buffer); | |
560 | return retval; | |
705ececd MG |
561 | } |
562 | ||
563 | /* | |
564 | Read data from device. | |
565 | */ | |
e1a164d7 MG |
566 | int line6_read_data(struct usb_line6 *line6, int address, void *data, |
567 | size_t datalen) | |
705ececd MG |
568 | { |
569 | struct usb_device *usbdev = line6->usbdev; | |
570 | int ret; | |
571 | unsigned char len; | |
572 | ||
573 | /* query the serial number: */ | |
574 | ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, | |
1027f476 MG |
575 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, |
576 | (datalen << 8) | 0x21, address, | |
577 | NULL, 0, LINE6_TIMEOUT * HZ); | |
705ececd | 578 | |
36445bc1 | 579 | if (ret < 0) { |
705ececd MG |
580 | dev_err(line6->ifcdev, "read request failed (error %d)\n", ret); |
581 | return ret; | |
582 | } | |
583 | ||
584 | /* Wait for data length. We'll get a couple of 0xff until length arrives. */ | |
585 | do { | |
586 | ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67, | |
36445bc1 GKH |
587 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | |
588 | USB_DIR_IN, | |
589 | 0x0012, 0x0000, &len, 1, | |
590 | LINE6_TIMEOUT * HZ); | |
591 | if (ret < 0) { | |
592 | dev_err(line6->ifcdev, | |
593 | "receive length failed (error %d)\n", ret); | |
705ececd MG |
594 | return ret; |
595 | } | |
d722a510 | 596 | } while (len == 0xff); |
36445bc1 GKH |
597 | |
598 | if (len != datalen) { | |
599 | /* should be equal or something went wrong */ | |
600 | dev_err(line6->ifcdev, | |
601 | "length mismatch (expected %d, got %d)\n", | |
602 | (int)datalen, (int)len); | |
705ececd MG |
603 | return -EINVAL; |
604 | } | |
605 | ||
606 | /* receive the result: */ | |
607 | ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67, | |
36445bc1 GKH |
608 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, |
609 | 0x0013, 0x0000, data, datalen, | |
610 | LINE6_TIMEOUT * HZ); | |
705ececd | 611 | |
36445bc1 | 612 | if (ret < 0) { |
705ececd MG |
613 | dev_err(line6->ifcdev, "read failed (error %d)\n", ret); |
614 | return ret; | |
615 | } | |
616 | ||
617 | return 0; | |
618 | } | |
619 | ||
620 | /* | |
621 | Write data to device. | |
622 | */ | |
36445bc1 GKH |
623 | int line6_write_data(struct usb_line6 *line6, int address, void *data, |
624 | size_t datalen) | |
705ececd MG |
625 | { |
626 | struct usb_device *usbdev = line6->usbdev; | |
627 | int ret; | |
628 | unsigned char status; | |
629 | ||
36445bc1 GKH |
630 | ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, |
631 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | |
632 | 0x0022, address, data, datalen, | |
633 | LINE6_TIMEOUT * HZ); | |
705ececd | 634 | |
36445bc1 GKH |
635 | if (ret < 0) { |
636 | dev_err(line6->ifcdev, | |
637 | "write request failed (error %d)\n", ret); | |
705ececd MG |
638 | return ret; |
639 | } | |
640 | ||
641 | do { | |
36445bc1 GKH |
642 | ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), |
643 | 0x67, | |
644 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | | |
645 | USB_DIR_IN, | |
646 | 0x0012, 0x0000, | |
647 | &status, 1, LINE6_TIMEOUT * HZ); | |
648 | ||
649 | if (ret < 0) { | |
650 | dev_err(line6->ifcdev, | |
651 | "receiving status failed (error %d)\n", ret); | |
705ececd MG |
652 | return ret; |
653 | } | |
027360c5 | 654 | } while (status == 0xff); |
705ececd | 655 | |
36445bc1 | 656 | if (status != 0) { |
705ececd MG |
657 | dev_err(line6->ifcdev, "write failed (error %d)\n", ret); |
658 | return -EINVAL; | |
659 | } | |
660 | ||
661 | return 0; | |
662 | } | |
663 | ||
664 | /* | |
665 | Read Line6 device serial number. | |
666 | (POD, TonePort, GuitarPort) | |
667 | */ | |
668 | int line6_read_serial_number(struct usb_line6 *line6, int *serial_number) | |
669 | { | |
e1a164d7 MG |
670 | return line6_read_data(line6, 0x80d0, serial_number, |
671 | sizeof(*serial_number)); | |
705ececd MG |
672 | } |
673 | ||
674 | /* | |
675 | No operation (i.e., unsupported). | |
676 | */ | |
77491e52 GKH |
677 | ssize_t line6_nop_read(struct device *dev, struct device_attribute *attr, |
678 | char *buf) | |
705ececd MG |
679 | { |
680 | return 0; | |
681 | } | |
682 | ||
683 | /* | |
684 | No operation (i.e., unsupported). | |
685 | */ | |
027360c5 | 686 | ssize_t line6_nop_write(struct device *dev, struct device_attribute *attr, |
77491e52 | 687 | const char *buf, size_t count) |
705ececd MG |
688 | { |
689 | return count; | |
690 | } | |
691 | ||
692 | /* | |
693 | "write" request on "raw" special file. | |
694 | */ | |
1027f476 | 695 | #ifdef CONFIG_LINE6_USB_RAW |
027360c5 | 696 | ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr, |
77491e52 | 697 | const char *buf, size_t count) |
705ececd MG |
698 | { |
699 | struct usb_interface *interface = to_usb_interface(dev); | |
700 | struct usb_line6 *line6 = usb_get_intfdata(interface); | |
701 | line6_send_raw_message(line6, buf, count); | |
702 | return count; | |
703 | } | |
704 | #endif | |
705 | ||
706 | /* | |
707 | Generic destructor. | |
708 | */ | |
709 | static void line6_destruct(struct usb_interface *interface) | |
710 | { | |
711 | struct usb_line6 *line6; | |
36445bc1 GKH |
712 | |
713 | if (interface == NULL) | |
714 | return; | |
705ececd | 715 | line6 = usb_get_intfdata(interface); |
36445bc1 GKH |
716 | if (line6 == NULL) |
717 | return; | |
705ececd MG |
718 | |
719 | /* free buffer memory first: */ | |
36445bc1 GKH |
720 | kfree(line6->buffer_message); |
721 | kfree(line6->buffer_listen); | |
705ececd MG |
722 | |
723 | /* then free URBs: */ | |
36445bc1 | 724 | usb_free_urb(line6->urb_listen); |
705ececd MG |
725 | |
726 | /* make sure the device isn't destructed twice: */ | |
727 | usb_set_intfdata(interface, NULL); | |
728 | ||
729 | /* free interface data: */ | |
730 | kfree(line6); | |
731 | } | |
732 | ||
705ececd MG |
733 | /* |
734 | Probe USB device. | |
735 | */ | |
e1a164d7 MG |
736 | static int line6_probe(struct usb_interface *interface, |
737 | const struct usb_device_id *id) | |
705ececd MG |
738 | { |
739 | int devtype; | |
4bd8b4de DC |
740 | struct usb_device *usbdev; |
741 | struct usb_line6 *line6; | |
705ececd MG |
742 | const struct line6_properties *properties; |
743 | int devnum; | |
744 | int interface_number, alternate = 0; | |
745 | int product; | |
746 | int size = 0; | |
747 | int ep_read = 0, ep_write = 0; | |
748 | int ret; | |
749 | ||
36445bc1 GKH |
750 | if (interface == NULL) |
751 | return -ENODEV; | |
705ececd | 752 | usbdev = interface_to_usbdev(interface); |
36445bc1 GKH |
753 | if (usbdev == NULL) |
754 | return -ENODEV; | |
705ececd | 755 | |
705ececd | 756 | /* we don't handle multiple configurations */ |
ab366c1a KV |
757 | if (usbdev->descriptor.bNumConfigurations != 1) { |
758 | ret = -ENODEV; | |
759 | goto err_put; | |
760 | } | |
705ececd MG |
761 | |
762 | /* check vendor and product id */ | |
d722a510 | 763 | for (devtype = ARRAY_SIZE(line6_id_table) - 1; devtype--;) { |
1e18c0d5 GKH |
764 | u16 idVendor = le16_to_cpu(usbdev->descriptor.idVendor); |
765 | u16 idProduct = le16_to_cpu(usbdev->descriptor.idProduct); | |
d722a510 | 766 | |
1027f476 MG |
767 | if (idVendor == line6_id_table[devtype].idVendor && |
768 | idProduct == line6_id_table[devtype].idProduct) | |
705ececd | 769 | break; |
d722a510 | 770 | } |
705ececd | 771 | |
ab366c1a KV |
772 | if (devtype < 0) { |
773 | ret = -ENODEV; | |
774 | goto err_put; | |
775 | } | |
705ececd MG |
776 | |
777 | /* find free slot in device table: */ | |
36445bc1 GKH |
778 | for (devnum = 0; devnum < LINE6_MAX_DEVICES; ++devnum) |
779 | if (line6_devices[devnum] == NULL) | |
705ececd MG |
780 | break; |
781 | ||
ab366c1a KV |
782 | if (devnum == LINE6_MAX_DEVICES) { |
783 | ret = -ENODEV; | |
784 | goto err_put; | |
785 | } | |
705ececd MG |
786 | |
787 | /* initialize device info: */ | |
788 | properties = &line6_properties_table[devtype]; | |
789 | dev_info(&interface->dev, "Line6 %s found\n", properties->name); | |
790 | product = le16_to_cpu(usbdev->descriptor.idProduct); | |
791 | ||
792 | /* query interface number */ | |
793 | interface_number = interface->cur_altsetting->desc.bInterfaceNumber; | |
794 | ||
36445bc1 | 795 | switch (product) { |
705ececd | 796 | case LINE6_DEVID_BASSPODXTLIVE: |
705ececd MG |
797 | case LINE6_DEVID_PODXTLIVE: |
798 | case LINE6_DEVID_VARIAX: | |
799 | alternate = 1; | |
800 | break; | |
801 | ||
1027f476 MG |
802 | case LINE6_DEVID_POCKETPOD: |
803 | switch (interface_number) { | |
804 | case 0: | |
e1a164d7 | 805 | return 0; /* this interface has no endpoints */ |
1027f476 MG |
806 | case 1: |
807 | alternate = 0; | |
808 | break; | |
809 | default: | |
810 | MISSING_CASE; | |
811 | } | |
812 | break; | |
813 | ||
4c6fb5fc | 814 | case LINE6_DEVID_PODHD500: |
705ececd MG |
815 | case LINE6_DEVID_PODX3: |
816 | case LINE6_DEVID_PODX3LIVE: | |
36445bc1 GKH |
817 | switch (interface_number) { |
818 | case 0: | |
819 | alternate = 1; | |
820 | break; | |
821 | case 1: | |
822 | alternate = 0; | |
823 | break; | |
824 | default: | |
825 | MISSING_CASE; | |
705ececd MG |
826 | } |
827 | break; | |
828 | ||
829 | case LINE6_DEVID_BASSPODXT: | |
830 | case LINE6_DEVID_BASSPODXTPRO: | |
831 | case LINE6_DEVID_PODXT: | |
832 | case LINE6_DEVID_PODXTPRO: | |
16dc1040 | 833 | case LINE6_DEVID_PODHD300: |
705ececd MG |
834 | alternate = 5; |
835 | break; | |
836 | ||
705ececd | 837 | case LINE6_DEVID_GUITARPORT: |
1027f476 MG |
838 | case LINE6_DEVID_PODSTUDIO_GX: |
839 | case LINE6_DEVID_PODSTUDIO_UX1: | |
840 | case LINE6_DEVID_TONEPORT_GX: | |
841 | case LINE6_DEVID_TONEPORT_UX1: | |
e1a164d7 | 842 | alternate = 2; /* 1..4 seem to be ok */ |
705ececd MG |
843 | break; |
844 | ||
705ececd | 845 | case LINE6_DEVID_TONEPORT_UX2: |
1027f476 | 846 | case LINE6_DEVID_PODSTUDIO_UX2: |
36445bc1 GKH |
847 | switch (interface_number) { |
848 | case 0: | |
849 | /* defaults to 44.1kHz, 16-bit */ | |
850 | alternate = 2; | |
851 | break; | |
852 | case 1: | |
1027f476 | 853 | /* don't know yet what this is ... |
e1a164d7 MG |
854 | alternate = 1; |
855 | break; | |
856 | */ | |
1027f476 | 857 | return -ENODEV; |
36445bc1 GKH |
858 | default: |
859 | MISSING_CASE; | |
705ececd MG |
860 | } |
861 | break; | |
862 | ||
863 | default: | |
864 | MISSING_CASE; | |
ab366c1a KV |
865 | ret = -ENODEV; |
866 | goto err_put; | |
705ececd MG |
867 | } |
868 | ||
36445bc1 GKH |
869 | ret = usb_set_interface(usbdev, interface_number, alternate); |
870 | if (ret < 0) { | |
705ececd | 871 | dev_err(&interface->dev, "set_interface failed\n"); |
ab366c1a | 872 | goto err_put; |
705ececd MG |
873 | } |
874 | ||
875 | /* initialize device data based on product id: */ | |
36445bc1 | 876 | switch (product) { |
705ececd MG |
877 | case LINE6_DEVID_BASSPODXT: |
878 | case LINE6_DEVID_BASSPODXTLIVE: | |
879 | case LINE6_DEVID_BASSPODXTPRO: | |
705ececd MG |
880 | case LINE6_DEVID_PODXT: |
881 | case LINE6_DEVID_PODXTPRO: | |
882 | size = sizeof(struct usb_line6_pod); | |
e1a164d7 | 883 | ep_read = 0x84; |
705ececd MG |
884 | ep_write = 0x03; |
885 | break; | |
886 | ||
16dc1040 SH |
887 | case LINE6_DEVID_PODHD300: |
888 | size = sizeof(struct usb_line6_podhd); | |
889 | ep_read = 0x84; | |
890 | ep_write = 0x03; | |
891 | break; | |
892 | ||
4c6fb5fc MG |
893 | case LINE6_DEVID_PODHD500: |
894 | size = sizeof(struct usb_line6_podhd); | |
895 | ep_read = 0x81; | |
896 | ep_write = 0x01; | |
897 | break; | |
898 | ||
1027f476 MG |
899 | case LINE6_DEVID_POCKETPOD: |
900 | size = sizeof(struct usb_line6_pod); | |
e1a164d7 | 901 | ep_read = 0x82; |
1027f476 MG |
902 | ep_write = 0x02; |
903 | break; | |
904 | ||
705ececd MG |
905 | case LINE6_DEVID_PODX3: |
906 | case LINE6_DEVID_PODX3LIVE: | |
907 | /* currently unused! */ | |
908 | size = sizeof(struct usb_line6_pod); | |
e1a164d7 | 909 | ep_read = 0x81; |
705ececd MG |
910 | ep_write = 0x01; |
911 | break; | |
912 | ||
1027f476 MG |
913 | case LINE6_DEVID_PODSTUDIO_GX: |
914 | case LINE6_DEVID_PODSTUDIO_UX1: | |
915 | case LINE6_DEVID_PODSTUDIO_UX2: | |
705ececd MG |
916 | case LINE6_DEVID_TONEPORT_GX: |
917 | case LINE6_DEVID_TONEPORT_UX1: | |
918 | case LINE6_DEVID_TONEPORT_UX2: | |
919 | case LINE6_DEVID_GUITARPORT: | |
920 | size = sizeof(struct usb_line6_toneport); | |
921 | /* these don't have a control channel */ | |
922 | break; | |
923 | ||
924 | case LINE6_DEVID_PODXTLIVE: | |
36445bc1 | 925 | switch (interface_number) { |
705ececd MG |
926 | case PODXTLIVE_INTERFACE_POD: |
927 | size = sizeof(struct usb_line6_pod); | |
e1a164d7 | 928 | ep_read = 0x84; |
705ececd MG |
929 | ep_write = 0x03; |
930 | break; | |
931 | ||
932 | case PODXTLIVE_INTERFACE_VARIAX: | |
933 | size = sizeof(struct usb_line6_variax); | |
e1a164d7 | 934 | ep_read = 0x86; |
705ececd MG |
935 | ep_write = 0x05; |
936 | break; | |
937 | ||
938 | default: | |
ab366c1a KV |
939 | ret = -ENODEV; |
940 | goto err_put; | |
705ececd MG |
941 | } |
942 | break; | |
943 | ||
944 | case LINE6_DEVID_VARIAX: | |
945 | size = sizeof(struct usb_line6_variax); | |
e1a164d7 | 946 | ep_read = 0x82; |
705ececd MG |
947 | ep_write = 0x01; |
948 | break; | |
949 | ||
950 | default: | |
951 | MISSING_CASE; | |
ab366c1a KV |
952 | ret = -ENODEV; |
953 | goto err_put; | |
705ececd MG |
954 | } |
955 | ||
36445bc1 | 956 | if (size == 0) { |
4bd8b4de | 957 | dev_err(&interface->dev, |
e1a164d7 | 958 | "driver bug: interface data size not set\n"); |
ab366c1a KV |
959 | ret = -ENODEV; |
960 | goto err_put; | |
705ececd MG |
961 | } |
962 | ||
963 | line6 = kzalloc(size, GFP_KERNEL); | |
964 | ||
36445bc1 | 965 | if (line6 == NULL) { |
705ececd | 966 | dev_err(&interface->dev, "Out of memory\n"); |
ab366c1a KV |
967 | ret = -ENODEV; |
968 | goto err_put; | |
705ececd MG |
969 | } |
970 | ||
971 | /* store basic data: */ | |
972 | line6->interface_number = interface_number; | |
973 | line6->properties = properties; | |
974 | line6->usbdev = usbdev; | |
975 | line6->ifcdev = &interface->dev; | |
976 | line6->ep_control_read = ep_read; | |
977 | line6->ep_control_write = ep_write; | |
978 | line6->product = product; | |
979 | ||
980 | /* get data from endpoint descriptor (see usb_maxpacket): */ | |
981 | { | |
982 | struct usb_host_endpoint *ep; | |
e1a164d7 MG |
983 | unsigned epnum = |
984 | usb_pipeendpoint(usb_rcvintpipe(usbdev, ep_read)); | |
705ececd MG |
985 | ep = usbdev->ep_in[epnum]; |
986 | ||
36445bc1 | 987 | if (ep != NULL) { |
705ececd | 988 | line6->interval = ep->desc.bInterval; |
e1a164d7 MG |
989 | line6->max_packet_size = |
990 | le16_to_cpu(ep->desc.wMaxPacketSize); | |
36445bc1 | 991 | } else { |
705ececd MG |
992 | line6->interval = LINE6_FALLBACK_INTERVAL; |
993 | line6->max_packet_size = LINE6_FALLBACK_MAXPACKETSIZE; | |
e1a164d7 MG |
994 | dev_err(line6->ifcdev, |
995 | "endpoint not available, using fallback values"); | |
705ececd MG |
996 | } |
997 | } | |
998 | ||
999 | usb_set_intfdata(interface, line6); | |
1000 | ||
36445bc1 | 1001 | if (properties->capabilities & LINE6_BIT_CONTROL) { |
705ececd | 1002 | /* initialize USB buffers: */ |
e1a164d7 MG |
1003 | line6->buffer_listen = |
1004 | kmalloc(LINE6_BUFSIZE_LISTEN, GFP_KERNEL); | |
705ececd | 1005 | |
36445bc1 | 1006 | if (line6->buffer_listen == NULL) { |
705ececd | 1007 | dev_err(&interface->dev, "Out of memory\n"); |
ab366c1a KV |
1008 | ret = -ENOMEM; |
1009 | goto err_destruct; | |
705ececd MG |
1010 | } |
1011 | ||
e1a164d7 MG |
1012 | line6->buffer_message = |
1013 | kmalloc(LINE6_MESSAGE_MAXLEN, GFP_KERNEL); | |
705ececd | 1014 | |
36445bc1 | 1015 | if (line6->buffer_message == NULL) { |
705ececd | 1016 | dev_err(&interface->dev, "Out of memory\n"); |
ab366c1a KV |
1017 | ret = -ENOMEM; |
1018 | goto err_destruct; | |
705ececd MG |
1019 | } |
1020 | ||
1021 | line6->urb_listen = usb_alloc_urb(0, GFP_KERNEL); | |
1022 | ||
36445bc1 | 1023 | if (line6->urb_listen == NULL) { |
705ececd MG |
1024 | dev_err(&interface->dev, "Out of memory\n"); |
1025 | line6_destruct(interface); | |
ab366c1a KV |
1026 | ret = -ENOMEM; |
1027 | goto err_destruct; | |
705ececd MG |
1028 | } |
1029 | ||
36445bc1 GKH |
1030 | ret = line6_start_listen(line6); |
1031 | if (ret < 0) { | |
1032 | dev_err(&interface->dev, "%s: usb_submit_urb failed\n", | |
1033 | __func__); | |
ab366c1a | 1034 | goto err_destruct; |
705ececd MG |
1035 | } |
1036 | } | |
1037 | ||
1038 | /* initialize device data based on product id: */ | |
36445bc1 | 1039 | switch (product) { |
705ececd MG |
1040 | case LINE6_DEVID_BASSPODXT: |
1041 | case LINE6_DEVID_BASSPODXTLIVE: | |
1042 | case LINE6_DEVID_BASSPODXTPRO: | |
1043 | case LINE6_DEVID_POCKETPOD: | |
1044 | case LINE6_DEVID_PODX3: | |
1045 | case LINE6_DEVID_PODX3LIVE: | |
1046 | case LINE6_DEVID_PODXT: | |
1047 | case LINE6_DEVID_PODXTPRO: | |
1027f476 | 1048 | ret = line6_pod_init(interface, (struct usb_line6_pod *)line6); |
705ececd MG |
1049 | break; |
1050 | ||
16dc1040 | 1051 | case LINE6_DEVID_PODHD300: |
4c6fb5fc | 1052 | case LINE6_DEVID_PODHD500: |
16dc1040 SH |
1053 | ret = line6_podhd_init(interface, |
1054 | (struct usb_line6_podhd *)line6); | |
1055 | break; | |
1056 | ||
705ececd | 1057 | case LINE6_DEVID_PODXTLIVE: |
36445bc1 | 1058 | switch (interface_number) { |
705ececd | 1059 | case PODXTLIVE_INTERFACE_POD: |
e1a164d7 MG |
1060 | ret = |
1061 | line6_pod_init(interface, | |
1062 | (struct usb_line6_pod *)line6); | |
705ececd MG |
1063 | break; |
1064 | ||
1065 | case PODXTLIVE_INTERFACE_VARIAX: | |
e1a164d7 MG |
1066 | ret = |
1067 | line6_variax_init(interface, | |
1068 | (struct usb_line6_variax *)line6); | |
705ececd MG |
1069 | break; |
1070 | ||
1071 | default: | |
36445bc1 GKH |
1072 | dev_err(&interface->dev, |
1073 | "PODxt Live interface %d not supported\n", | |
1074 | interface_number); | |
705ececd MG |
1075 | ret = -ENODEV; |
1076 | } | |
1077 | ||
1078 | break; | |
1079 | ||
1080 | case LINE6_DEVID_VARIAX: | |
e1a164d7 MG |
1081 | ret = |
1082 | line6_variax_init(interface, | |
1083 | (struct usb_line6_variax *)line6); | |
705ececd MG |
1084 | break; |
1085 | ||
1027f476 MG |
1086 | case LINE6_DEVID_PODSTUDIO_GX: |
1087 | case LINE6_DEVID_PODSTUDIO_UX1: | |
1088 | case LINE6_DEVID_PODSTUDIO_UX2: | |
705ececd MG |
1089 | case LINE6_DEVID_TONEPORT_GX: |
1090 | case LINE6_DEVID_TONEPORT_UX1: | |
1091 | case LINE6_DEVID_TONEPORT_UX2: | |
1092 | case LINE6_DEVID_GUITARPORT: | |
e1a164d7 MG |
1093 | ret = |
1094 | line6_toneport_init(interface, | |
1095 | (struct usb_line6_toneport *)line6); | |
705ececd MG |
1096 | break; |
1097 | ||
1098 | default: | |
1099 | MISSING_CASE; | |
1100 | ret = -ENODEV; | |
1101 | } | |
1102 | ||
ab366c1a KV |
1103 | if (ret < 0) |
1104 | goto err_destruct; | |
705ececd | 1105 | |
36445bc1 GKH |
1106 | ret = sysfs_create_link(&interface->dev.kobj, &usbdev->dev.kobj, |
1107 | "usb_device"); | |
ab366c1a KV |
1108 | if (ret < 0) |
1109 | goto err_destruct; | |
705ececd | 1110 | |
1027f476 MG |
1111 | /* creation of additional special files should go here */ |
1112 | ||
36445bc1 GKH |
1113 | dev_info(&interface->dev, "Line6 %s now attached\n", |
1114 | line6->properties->name); | |
705ececd | 1115 | line6_devices[devnum] = line6; |
1027f476 | 1116 | |
e1a164d7 | 1117 | switch (product) { |
1027f476 MG |
1118 | case LINE6_DEVID_PODX3: |
1119 | case LINE6_DEVID_PODX3LIVE: | |
e1a164d7 MG |
1120 | dev_info(&interface->dev, |
1121 | "NOTE: the Line6 %s is detected, but not yet supported\n", | |
1027f476 MG |
1122 | line6->properties->name); |
1123 | } | |
1124 | ||
1125 | /* increment reference counters: */ | |
1126 | usb_get_intf(interface); | |
1127 | usb_get_dev(usbdev); | |
1128 | ||
ab366c1a KV |
1129 | return 0; |
1130 | ||
1131 | err_destruct: | |
1132 | line6_destruct(interface); | |
1133 | err_put: | |
705ececd MG |
1134 | return ret; |
1135 | } | |
1136 | ||
1137 | /* | |
1138 | Line6 device disconnected. | |
1139 | */ | |
1140 | static void line6_disconnect(struct usb_interface *interface) | |
1141 | { | |
1142 | struct usb_line6 *line6; | |
1143 | struct usb_device *usbdev; | |
1144 | int interface_number, i; | |
1145 | ||
36445bc1 GKH |
1146 | if (interface == NULL) |
1147 | return; | |
705ececd | 1148 | usbdev = interface_to_usbdev(interface); |
36445bc1 GKH |
1149 | if (usbdev == NULL) |
1150 | return; | |
705ececd | 1151 | |
1027f476 MG |
1152 | /* removal of additional special files should go here */ |
1153 | ||
705ececd MG |
1154 | sysfs_remove_link(&interface->dev.kobj, "usb_device"); |
1155 | ||
1156 | interface_number = interface->cur_altsetting->desc.bInterfaceNumber; | |
1157 | line6 = usb_get_intfdata(interface); | |
1158 | ||
36445bc1 GKH |
1159 | if (line6 != NULL) { |
1160 | if (line6->urb_listen != NULL) | |
1027f476 | 1161 | line6_stop_listen(line6); |
705ececd | 1162 | |
36445bc1 GKH |
1163 | if (usbdev != line6->usbdev) |
1164 | dev_err(line6->ifcdev, | |
1165 | "driver bug: inconsistent usb device\n"); | |
705ececd | 1166 | |
36445bc1 | 1167 | switch (line6->usbdev->descriptor.idProduct) { |
705ececd MG |
1168 | case LINE6_DEVID_BASSPODXT: |
1169 | case LINE6_DEVID_BASSPODXTLIVE: | |
1170 | case LINE6_DEVID_BASSPODXTPRO: | |
1171 | case LINE6_DEVID_POCKETPOD: | |
1172 | case LINE6_DEVID_PODX3: | |
1173 | case LINE6_DEVID_PODX3LIVE: | |
1174 | case LINE6_DEVID_PODXT: | |
1175 | case LINE6_DEVID_PODXTPRO: | |
1027f476 | 1176 | line6_pod_disconnect(interface); |
705ececd MG |
1177 | break; |
1178 | ||
16dc1040 | 1179 | case LINE6_DEVID_PODHD300: |
4c6fb5fc | 1180 | case LINE6_DEVID_PODHD500: |
16dc1040 SH |
1181 | line6_podhd_disconnect(interface); |
1182 | break; | |
1183 | ||
705ececd | 1184 | case LINE6_DEVID_PODXTLIVE: |
36445bc1 | 1185 | switch (interface_number) { |
705ececd | 1186 | case PODXTLIVE_INTERFACE_POD: |
1027f476 | 1187 | line6_pod_disconnect(interface); |
705ececd MG |
1188 | break; |
1189 | ||
1190 | case PODXTLIVE_INTERFACE_VARIAX: | |
1027f476 | 1191 | line6_variax_disconnect(interface); |
705ececd MG |
1192 | break; |
1193 | } | |
1194 | ||
1195 | break; | |
1196 | ||
1197 | case LINE6_DEVID_VARIAX: | |
1027f476 | 1198 | line6_variax_disconnect(interface); |
705ececd MG |
1199 | break; |
1200 | ||
1027f476 MG |
1201 | case LINE6_DEVID_PODSTUDIO_GX: |
1202 | case LINE6_DEVID_PODSTUDIO_UX1: | |
1203 | case LINE6_DEVID_PODSTUDIO_UX2: | |
705ececd MG |
1204 | case LINE6_DEVID_TONEPORT_GX: |
1205 | case LINE6_DEVID_TONEPORT_UX1: | |
1206 | case LINE6_DEVID_TONEPORT_UX2: | |
1207 | case LINE6_DEVID_GUITARPORT: | |
1027f476 | 1208 | line6_toneport_disconnect(interface); |
705ececd MG |
1209 | break; |
1210 | ||
1211 | default: | |
1212 | MISSING_CASE; | |
1213 | } | |
1214 | ||
e1a164d7 MG |
1215 | dev_info(&interface->dev, "Line6 %s now disconnected\n", |
1216 | line6->properties->name); | |
705ececd | 1217 | |
1027f476 | 1218 | for (i = LINE6_MAX_DEVICES; i--;) |
36445bc1 | 1219 | if (line6_devices[i] == line6) |
536165d8 | 1220 | line6_devices[i] = NULL; |
705ececd MG |
1221 | } |
1222 | ||
1223 | line6_destruct(interface); | |
1224 | ||
1225 | /* decrement reference counters: */ | |
1226 | usb_put_intf(interface); | |
1227 | usb_put_dev(usbdev); | |
1027f476 MG |
1228 | } |
1229 | ||
1230 | #ifdef CONFIG_PM | |
1231 | ||
1232 | /* | |
1233 | Suspend Line6 device. | |
1234 | */ | |
1235 | static int line6_suspend(struct usb_interface *interface, pm_message_t message) | |
1236 | { | |
1237 | struct usb_line6 *line6 = usb_get_intfdata(interface); | |
1238 | struct snd_line6_pcm *line6pcm = line6->line6pcm; | |
1239 | ||
1240 | snd_power_change_state(line6->card, SNDRV_CTL_POWER_D3hot); | |
1241 | ||
1242 | if (line6->properties->capabilities & LINE6_BIT_CONTROL) | |
1243 | line6_stop_listen(line6); | |
1244 | ||
1245 | if (line6pcm != NULL) { | |
1246 | snd_pcm_suspend_all(line6pcm->pcm); | |
1247 | line6_pcm_disconnect(line6pcm); | |
1248 | line6pcm->flags = 0; | |
1249 | } | |
1250 | ||
1251 | return 0; | |
1252 | } | |
1253 | ||
1254 | /* | |
1255 | Resume Line6 device. | |
1256 | */ | |
1257 | static int line6_resume(struct usb_interface *interface) | |
1258 | { | |
1259 | struct usb_line6 *line6 = usb_get_intfdata(interface); | |
1260 | ||
1261 | if (line6->properties->capabilities & LINE6_BIT_CONTROL) | |
1262 | line6_start_listen(line6); | |
1263 | ||
1264 | snd_power_change_state(line6->card, SNDRV_CTL_POWER_D0); | |
1265 | return 0; | |
1266 | } | |
1267 | ||
1268 | /* | |
1269 | Resume Line6 device after reset. | |
1270 | */ | |
1271 | static int line6_reset_resume(struct usb_interface *interface) | |
1272 | { | |
1273 | struct usb_line6 *line6 = usb_get_intfdata(interface); | |
705ececd | 1274 | |
1027f476 MG |
1275 | switch (line6->usbdev->descriptor.idProduct) { |
1276 | case LINE6_DEVID_PODSTUDIO_GX: | |
1277 | case LINE6_DEVID_PODSTUDIO_UX1: | |
1278 | case LINE6_DEVID_PODSTUDIO_UX2: | |
1279 | case LINE6_DEVID_TONEPORT_GX: | |
1280 | case LINE6_DEVID_TONEPORT_UX1: | |
1281 | case LINE6_DEVID_TONEPORT_UX2: | |
1282 | case LINE6_DEVID_GUITARPORT: | |
1283 | line6_toneport_reset_resume((struct usb_line6_toneport *)line6); | |
1284 | } | |
1285 | ||
1286 | return line6_resume(interface); | |
705ececd MG |
1287 | } |
1288 | ||
e1a164d7 | 1289 | #endif /* CONFIG_PM */ |
1027f476 | 1290 | |
705ececd | 1291 | static struct usb_driver line6_driver = { |
705ececd MG |
1292 | .name = DRIVER_NAME, |
1293 | .probe = line6_probe, | |
1294 | .disconnect = line6_disconnect, | |
1027f476 MG |
1295 | #ifdef CONFIG_PM |
1296 | .suspend = line6_suspend, | |
1297 | .resume = line6_resume, | |
1298 | .reset_resume = line6_reset_resume, | |
1299 | #endif | |
705ececd MG |
1300 | .id_table = line6_id_table, |
1301 | }; | |
1302 | ||
4a631364 | 1303 | module_usb_driver(line6_driver); |
705ececd MG |
1304 | |
1305 | MODULE_AUTHOR(DRIVER_AUTHOR); | |
1306 | MODULE_DESCRIPTION(DRIVER_DESC); | |
1307 | MODULE_LICENSE("GPL"); | |
1308 | MODULE_VERSION(DRIVER_VERSION); |