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