1
2
3
4
5
6
7
8#include <linux/slab.h>
9#include <linux/wait.h>
10#include <linux/interrupt.h>
11#include <linux/module.h>
12#include <linux/usb.h>
13
14#include <sound/core.h>
15#include <sound/control.h>
16
17#include "capture.h"
18#include "driver.h"
19#include "playback.h"
20
21
22
23
24#define POD_NAME_OFFSET 0
25#define POD_NAME_LENGTH 16
26
27
28
29
30#define POD_CONTROL_SIZE 0x80
31#define POD_BUFSIZE_DUMPREQ 7
32#define POD_STARTUP_DELAY 1000
33
34
35
36
37enum {
38 POD_STARTUP_VERSIONREQ,
39 POD_STARTUP_SETUP,
40 POD_STARTUP_DONE,
41};
42
43enum {
44 LINE6_BASSPODXT,
45 LINE6_BASSPODXTLIVE,
46 LINE6_BASSPODXTPRO,
47 LINE6_POCKETPOD,
48 LINE6_PODXT,
49 LINE6_PODXTLIVE_POD,
50 LINE6_PODXTPRO,
51};
52
53struct usb_line6_pod {
54
55 struct usb_line6 line6;
56
57
58 int monitor_level;
59
60
61 int startup_progress;
62
63
64 u32 serial_number;
65
66
67 int firmware_version;
68
69
70 int device_id;
71};
72
73#define line6_to_pod(x) container_of(x, struct usb_line6_pod, line6)
74
75#define POD_SYSEX_CODE 3
76
77
78
79enum {
80 POD_SYSEX_SAVE = 0x24,
81 POD_SYSEX_SYSTEM = 0x56,
82 POD_SYSEX_SYSTEMREQ = 0x57,
83
84 POD_SYSEX_STORE = 0x71,
85 POD_SYSEX_FINISH = 0x72,
86 POD_SYSEX_DUMPMEM = 0x73,
87 POD_SYSEX_DUMP = 0x74,
88 POD_SYSEX_DUMPREQ = 0x75
89
90
91
92};
93
94enum {
95 POD_MONITOR_LEVEL = 0x04,
96 POD_SYSTEM_INVALID = 0x10000
97};
98
99
100
101enum {
102 POD_DUMP_MEMORY = 2
103};
104
105enum {
106 POD_BUSY_READ,
107 POD_BUSY_WRITE,
108 POD_CHANNEL_DIRTY,
109 POD_SAVE_PRESSED,
110 POD_BUSY_MIDISEND
111};
112
113static const struct snd_ratden pod_ratden = {
114 .num_min = 78125,
115 .num_max = 78125,
116 .num_step = 1,
117 .den = 2
118};
119
120static struct line6_pcm_properties pod_pcm_properties = {
121 .playback_hw = {
122 .info = (SNDRV_PCM_INFO_MMAP |
123 SNDRV_PCM_INFO_INTERLEAVED |
124 SNDRV_PCM_INFO_BLOCK_TRANSFER |
125 SNDRV_PCM_INFO_MMAP_VALID |
126 SNDRV_PCM_INFO_PAUSE |
127 SNDRV_PCM_INFO_SYNC_START),
128 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
129 .rates = SNDRV_PCM_RATE_KNOT,
130 .rate_min = 39062,
131 .rate_max = 39063,
132 .channels_min = 2,
133 .channels_max = 2,
134 .buffer_bytes_max = 60000,
135 .period_bytes_min = 64,
136 .period_bytes_max = 8192,
137 .periods_min = 1,
138 .periods_max = 1024},
139 .capture_hw = {
140 .info = (SNDRV_PCM_INFO_MMAP |
141 SNDRV_PCM_INFO_INTERLEAVED |
142 SNDRV_PCM_INFO_BLOCK_TRANSFER |
143 SNDRV_PCM_INFO_MMAP_VALID |
144 SNDRV_PCM_INFO_SYNC_START),
145 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
146 .rates = SNDRV_PCM_RATE_KNOT,
147 .rate_min = 39062,
148 .rate_max = 39063,
149 .channels_min = 2,
150 .channels_max = 2,
151 .buffer_bytes_max = 60000,
152 .period_bytes_min = 64,
153 .period_bytes_max = 8192,
154 .periods_min = 1,
155 .periods_max = 1024},
156 .rates = {
157 .nrats = 1,
158 .rats = &pod_ratden},
159 .bytes_per_channel = 3
160};
161
162static const char pod_version_header[] = {
163 0xf2, 0x7e, 0x7f, 0x06, 0x02
164};
165
166static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
167 int size)
168{
169 return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code,
170 size);
171}
172
173
174
175
176static void line6_pod_process_message(struct usb_line6 *line6)
177{
178 struct usb_line6_pod *pod = line6_to_pod(line6);
179 const unsigned char *buf = pod->line6.buffer_message;
180
181 if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {
182 pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];
183 pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) |
184 (int) buf[10];
185 if (pod->startup_progress == POD_STARTUP_VERSIONREQ) {
186 pod->startup_progress = POD_STARTUP_SETUP;
187 schedule_delayed_work(&line6->startup_work, 0);
188 }
189 return;
190 }
191
192
193 if (buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE) &&
194 buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN)) {
195 return;
196 }
197 if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) != 0)
198 return;
199
200 if (buf[5] == POD_SYSEX_SYSTEM && buf[6] == POD_MONITOR_LEVEL) {
201 short value = ((int)buf[7] << 12) | ((int)buf[8] << 8) |
202 ((int)buf[9] << 4) | (int)buf[10];
203 pod->monitor_level = value;
204 }
205}
206
207
208
209
210static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
211 int code)
212{
213 char *sysex;
214 static const int size = 5;
215
216 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
217 if (!sysex)
218 return -ENOMEM;
219 sysex[SYSEX_DATA_OFS] = code;
220 sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
221 sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
222 sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
223 sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f;
224 line6_send_sysex_message(&pod->line6, sysex, size);
225 kfree(sysex);
226 return 0;
227}
228
229
230
231
232static ssize_t serial_number_show(struct device *dev,
233 struct device_attribute *attr, char *buf)
234{
235 struct snd_card *card = dev_to_snd_card(dev);
236 struct usb_line6_pod *pod = card->private_data;
237
238 return sprintf(buf, "%u\n", pod->serial_number);
239}
240
241
242
243
244static ssize_t firmware_version_show(struct device *dev,
245 struct device_attribute *attr, char *buf)
246{
247 struct snd_card *card = dev_to_snd_card(dev);
248 struct usb_line6_pod *pod = card->private_data;
249
250 return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
251 pod->firmware_version % 100);
252}
253
254
255
256
257static ssize_t device_id_show(struct device *dev,
258 struct device_attribute *attr, char *buf)
259{
260 struct snd_card *card = dev_to_snd_card(dev);
261 struct usb_line6_pod *pod = card->private_data;
262
263 return sprintf(buf, "%d\n", pod->device_id);
264}
265
266
267
268
269
270
271
272
273static void pod_startup(struct usb_line6 *line6)
274{
275 struct usb_line6_pod *pod = line6_to_pod(line6);
276
277 switch (pod->startup_progress) {
278 case POD_STARTUP_VERSIONREQ:
279
280 line6_version_request_async(line6);
281 break;
282 case POD_STARTUP_SETUP:
283
284 line6_read_serial_number(&pod->line6, &pod->serial_number);
285
286
287 if (snd_card_register(line6->card))
288 dev_err(line6->ifcdev, "Failed to register POD card.\n");
289 pod->startup_progress = POD_STARTUP_DONE;
290 break;
291 default:
292 break;
293 }
294}
295
296
297static DEVICE_ATTR_RO(device_id);
298static DEVICE_ATTR_RO(firmware_version);
299static DEVICE_ATTR_RO(serial_number);
300
301static struct attribute *pod_dev_attrs[] = {
302 &dev_attr_device_id.attr,
303 &dev_attr_firmware_version.attr,
304 &dev_attr_serial_number.attr,
305 NULL
306};
307
308static const struct attribute_group pod_dev_attr_group = {
309 .name = "pod",
310 .attrs = pod_dev_attrs,
311};
312
313
314static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
315 struct snd_ctl_elem_info *uinfo)
316{
317 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
318 uinfo->count = 1;
319 uinfo->value.integer.min = 0;
320 uinfo->value.integer.max = 65535;
321 return 0;
322}
323
324
325static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
326 struct snd_ctl_elem_value *ucontrol)
327{
328 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
329 struct usb_line6_pod *pod = line6_to_pod(line6pcm->line6);
330
331 ucontrol->value.integer.value[0] = pod->monitor_level;
332 return 0;
333}
334
335
336static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
337 struct snd_ctl_elem_value *ucontrol)
338{
339 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
340 struct usb_line6_pod *pod = line6_to_pod(line6pcm->line6);
341
342 if (ucontrol->value.integer.value[0] == pod->monitor_level)
343 return 0;
344
345 pod->monitor_level = ucontrol->value.integer.value[0];
346 pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
347 POD_MONITOR_LEVEL);
348 return 1;
349}
350
351
352static const struct snd_kcontrol_new pod_control_monitor = {
353 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
354 .name = "Monitor Playback Volume",
355 .index = 0,
356 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
357 .info = snd_pod_control_monitor_info,
358 .get = snd_pod_control_monitor_get,
359 .put = snd_pod_control_monitor_put
360};
361
362
363
364
365static int pod_init(struct usb_line6 *line6,
366 const struct usb_device_id *id)
367{
368 int err;
369 struct usb_line6_pod *pod = line6_to_pod(line6);
370
371 line6->process_message = line6_pod_process_message;
372 line6->startup = pod_startup;
373
374
375 err = snd_card_add_dev_attr(line6->card, &pod_dev_attr_group);
376 if (err < 0)
377 return err;
378
379
380 err = line6_init_pcm(line6, &pod_pcm_properties);
381 if (err < 0)
382 return err;
383
384
385 err = snd_ctl_add(line6->card,
386 snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
387 if (err < 0)
388 return err;
389
390
391
392
393
394
395
396 if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
397 pod->monitor_level = POD_SYSTEM_INVALID;
398
399
400 schedule_delayed_work(&line6->startup_work,
401 msecs_to_jiffies(POD_STARTUP_DELAY));
402 }
403
404 return 0;
405}
406
407#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
408#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
409
410
411static const struct usb_device_id pod_id_table[] = {
412 { LINE6_DEVICE(0x4250), .driver_info = LINE6_BASSPODXT },
413 { LINE6_DEVICE(0x4642), .driver_info = LINE6_BASSPODXTLIVE },
414 { LINE6_DEVICE(0x4252), .driver_info = LINE6_BASSPODXTPRO },
415 { LINE6_IF_NUM(0x5051, 1), .driver_info = LINE6_POCKETPOD },
416 { LINE6_DEVICE(0x5044), .driver_info = LINE6_PODXT },
417 { LINE6_IF_NUM(0x4650, 0), .driver_info = LINE6_PODXTLIVE_POD },
418 { LINE6_DEVICE(0x5050), .driver_info = LINE6_PODXTPRO },
419 {}
420};
421
422MODULE_DEVICE_TABLE(usb, pod_id_table);
423
424static const struct line6_properties pod_properties_table[] = {
425 [LINE6_BASSPODXT] = {
426 .id = "BassPODxt",
427 .name = "BassPODxt",
428 .capabilities = LINE6_CAP_CONTROL
429 | LINE6_CAP_CONTROL_MIDI
430 | LINE6_CAP_PCM
431 | LINE6_CAP_HWMON,
432 .altsetting = 5,
433 .ep_ctrl_r = 0x84,
434 .ep_ctrl_w = 0x03,
435 .ep_audio_r = 0x82,
436 .ep_audio_w = 0x01,
437 },
438 [LINE6_BASSPODXTLIVE] = {
439 .id = "BassPODxtLive",
440 .name = "BassPODxt Live",
441 .capabilities = LINE6_CAP_CONTROL
442 | LINE6_CAP_CONTROL_MIDI
443 | LINE6_CAP_PCM
444 | LINE6_CAP_HWMON,
445 .altsetting = 1,
446 .ep_ctrl_r = 0x84,
447 .ep_ctrl_w = 0x03,
448 .ep_audio_r = 0x82,
449 .ep_audio_w = 0x01,
450 },
451 [LINE6_BASSPODXTPRO] = {
452 .id = "BassPODxtPro",
453 .name = "BassPODxt Pro",
454 .capabilities = LINE6_CAP_CONTROL
455 | LINE6_CAP_CONTROL_MIDI
456 | LINE6_CAP_PCM
457 | LINE6_CAP_HWMON,
458 .altsetting = 5,
459 .ep_ctrl_r = 0x84,
460 .ep_ctrl_w = 0x03,
461 .ep_audio_r = 0x82,
462 .ep_audio_w = 0x01,
463 },
464 [LINE6_POCKETPOD] = {
465 .id = "PocketPOD",
466 .name = "Pocket POD",
467 .capabilities = LINE6_CAP_CONTROL
468 | LINE6_CAP_CONTROL_MIDI,
469 .altsetting = 0,
470 .ep_ctrl_r = 0x82,
471 .ep_ctrl_w = 0x02,
472
473 },
474 [LINE6_PODXT] = {
475 .id = "PODxt",
476 .name = "PODxt",
477 .capabilities = LINE6_CAP_CONTROL
478 | LINE6_CAP_CONTROL_MIDI
479 | LINE6_CAP_PCM
480 | LINE6_CAP_HWMON,
481 .altsetting = 5,
482 .ep_ctrl_r = 0x84,
483 .ep_ctrl_w = 0x03,
484 .ep_audio_r = 0x82,
485 .ep_audio_w = 0x01,
486 },
487 [LINE6_PODXTLIVE_POD] = {
488 .id = "PODxtLive",
489 .name = "PODxt Live",
490 .capabilities = LINE6_CAP_CONTROL
491 | LINE6_CAP_CONTROL_MIDI
492 | LINE6_CAP_PCM
493 | LINE6_CAP_HWMON,
494 .altsetting = 1,
495 .ep_ctrl_r = 0x84,
496 .ep_ctrl_w = 0x03,
497 .ep_audio_r = 0x82,
498 .ep_audio_w = 0x01,
499 },
500 [LINE6_PODXTPRO] = {
501 .id = "PODxtPro",
502 .name = "PODxt Pro",
503 .capabilities = LINE6_CAP_CONTROL
504 | LINE6_CAP_CONTROL_MIDI
505 | LINE6_CAP_PCM
506 | LINE6_CAP_HWMON,
507 .altsetting = 5,
508 .ep_ctrl_r = 0x84,
509 .ep_ctrl_w = 0x03,
510 .ep_audio_r = 0x82,
511 .ep_audio_w = 0x01,
512 },
513};
514
515
516
517
518static int pod_probe(struct usb_interface *interface,
519 const struct usb_device_id *id)
520{
521 return line6_probe(interface, id, "Line6-POD",
522 &pod_properties_table[id->driver_info],
523 pod_init, sizeof(struct usb_line6_pod));
524}
525
526static struct usb_driver pod_driver = {
527 .name = KBUILD_MODNAME,
528 .probe = pod_probe,
529 .disconnect = line6_disconnect,
530#ifdef CONFIG_PM
531 .suspend = line6_suspend,
532 .resume = line6_resume,
533 .reset_resume = line6_resume,
534#endif
535 .id_table = pod_id_table,
536};
537
538module_usb_driver(pod_driver);
539
540MODULE_DESCRIPTION("Line 6 POD USB driver");
541MODULE_LICENSE("GPL");
542