Loading...
Note: File does not exist in v6.9.4.
1/*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
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 <linux/slab.h>
13#include <linux/wait.h>
14#include <sound/control.h>
15
16#include "audio.h"
17#include "capture.h"
18#include "driver.h"
19#include "playback.h"
20#include "pod.h"
21
22#define POD_SYSEX_CODE 3
23#define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
24
25/* *INDENT-OFF* */
26
27enum {
28 POD_SYSEX_SAVE = 0x24,
29 POD_SYSEX_SYSTEM = 0x56,
30 POD_SYSEX_SYSTEMREQ = 0x57,
31 /* POD_SYSEX_UPDATE = 0x6c, */ /* software update! */
32 POD_SYSEX_STORE = 0x71,
33 POD_SYSEX_FINISH = 0x72,
34 POD_SYSEX_DUMPMEM = 0x73,
35 POD_SYSEX_DUMP = 0x74,
36 POD_SYSEX_DUMPREQ = 0x75
37
38 /* dumps entire internal memory of PODxt Pro */
39 /* POD_SYSEX_DUMPMEM2 = 0x76 */
40};
41
42enum {
43 POD_MONITOR_LEVEL = 0x04,
44 POD_SYSTEM_INVALID = 0x10000
45};
46
47/* *INDENT-ON* */
48
49enum {
50 POD_DUMP_MEMORY = 2
51};
52
53enum {
54 POD_BUSY_READ,
55 POD_BUSY_WRITE,
56 POD_CHANNEL_DIRTY,
57 POD_SAVE_PRESSED,
58 POD_BUSY_MIDISEND
59};
60
61static struct snd_ratden pod_ratden = {
62 .num_min = 78125,
63 .num_max = 78125,
64 .num_step = 1,
65 .den = 2
66};
67
68static struct line6_pcm_properties pod_pcm_properties = {
69 .snd_line6_playback_hw = {
70 .info = (SNDRV_PCM_INFO_MMAP |
71 SNDRV_PCM_INFO_INTERLEAVED |
72 SNDRV_PCM_INFO_BLOCK_TRANSFER |
73 SNDRV_PCM_INFO_MMAP_VALID |
74 SNDRV_PCM_INFO_PAUSE |
75#ifdef CONFIG_PM
76 SNDRV_PCM_INFO_RESUME |
77#endif
78 SNDRV_PCM_INFO_SYNC_START),
79 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
80 .rates = SNDRV_PCM_RATE_KNOT,
81 .rate_min = 39062,
82 .rate_max = 39063,
83 .channels_min = 2,
84 .channels_max = 2,
85 .buffer_bytes_max = 60000,
86 .period_bytes_min = 64,
87 .period_bytes_max = 8192,
88 .periods_min = 1,
89 .periods_max = 1024},
90 .snd_line6_capture_hw = {
91 .info = (SNDRV_PCM_INFO_MMAP |
92 SNDRV_PCM_INFO_INTERLEAVED |
93 SNDRV_PCM_INFO_BLOCK_TRANSFER |
94 SNDRV_PCM_INFO_MMAP_VALID |
95#ifdef CONFIG_PM
96 SNDRV_PCM_INFO_RESUME |
97#endif
98 SNDRV_PCM_INFO_SYNC_START),
99 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
100 .rates = SNDRV_PCM_RATE_KNOT,
101 .rate_min = 39062,
102 .rate_max = 39063,
103 .channels_min = 2,
104 .channels_max = 2,
105 .buffer_bytes_max = 60000,
106 .period_bytes_min = 64,
107 .period_bytes_max = 8192,
108 .periods_min = 1,
109 .periods_max = 1024},
110 .snd_line6_rates = {
111 .nrats = 1,
112 .rats = &pod_ratden},
113 .bytes_per_frame = POD_BYTES_PER_FRAME
114};
115
116static const char pod_version_header[] = {
117 0xf2, 0x7e, 0x7f, 0x06, 0x02
118};
119
120/* forward declarations: */
121static void pod_startup2(unsigned long data);
122static void pod_startup3(struct usb_line6_pod *pod);
123
124static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
125 int size)
126{
127 return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code,
128 size);
129}
130
131/*
132 Process a completely received message.
133*/
134void line6_pod_process_message(struct usb_line6_pod *pod)
135{
136 const unsigned char *buf = pod->line6.buffer_message;
137
138 if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {
139 pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];
140 pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) |
141 (int) buf[10];
142 pod_startup3(pod);
143 return;
144 }
145
146 /* Only look for sysex messages from this device */
147 if (buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE) &&
148 buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN)) {
149 return;
150 }
151 if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) != 0)
152 return;
153
154 if (buf[5] == POD_SYSEX_SYSTEM && buf[6] == POD_MONITOR_LEVEL) {
155 short value = ((int)buf[7] << 12) | ((int)buf[8] << 8) |
156 ((int)buf[9] << 4) | (int)buf[10];
157 pod->monitor_level = value;
158 }
159}
160
161/*
162 Transmit PODxt Pro control parameter.
163*/
164void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param,
165 u8 value)
166{
167 line6_transmit_parameter(&pod->line6, param, value);
168}
169
170/*
171 Send system parameter (from integer).
172*/
173static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
174 int code)
175{
176 char *sysex;
177 static const int size = 5;
178
179 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
180 if (!sysex)
181 return -ENOMEM;
182 sysex[SYSEX_DATA_OFS] = code;
183 sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
184 sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
185 sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
186 sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f;
187 line6_send_sysex_message(&pod->line6, sysex, size);
188 kfree(sysex);
189 return 0;
190}
191
192/*
193 "read" request on "serial_number" special file.
194*/
195static ssize_t serial_number_show(struct device *dev,
196 struct device_attribute *attr, char *buf)
197{
198 struct usb_interface *interface = to_usb_interface(dev);
199 struct usb_line6_pod *pod = usb_get_intfdata(interface);
200 return sprintf(buf, "%d\n", pod->serial_number);
201}
202
203/*
204 "read" request on "firmware_version" special file.
205*/
206static ssize_t firmware_version_show(struct device *dev,
207 struct device_attribute *attr, char *buf)
208{
209 struct usb_interface *interface = to_usb_interface(dev);
210 struct usb_line6_pod *pod = usb_get_intfdata(interface);
211 return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
212 pod->firmware_version % 100);
213}
214
215/*
216 "read" request on "device_id" special file.
217*/
218static ssize_t device_id_show(struct device *dev,
219 struct device_attribute *attr, char *buf)
220{
221 struct usb_interface *interface = to_usb_interface(dev);
222 struct usb_line6_pod *pod = usb_get_intfdata(interface);
223 return sprintf(buf, "%d\n", pod->device_id);
224}
225
226/*
227 POD startup procedure.
228 This is a sequence of functions with special requirements (e.g., must
229 not run immediately after initialization, must not run in interrupt
230 context). After the last one has finished, the device is ready to use.
231*/
232
233static void pod_startup1(struct usb_line6_pod *pod)
234{
235 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
236
237 /* delay startup procedure: */
238 line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
239 (unsigned long)pod);
240}
241
242static void pod_startup2(unsigned long data)
243{
244 struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
245 struct usb_line6 *line6 = &pod->line6;
246 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
247
248 /* request firmware version: */
249 line6_version_request_async(line6);
250}
251
252static void pod_startup3(struct usb_line6_pod *pod)
253{
254 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
255
256 /* schedule work for global work queue: */
257 schedule_work(&pod->startup_work);
258}
259
260static void pod_startup4(struct work_struct *work)
261{
262 struct usb_line6_pod *pod =
263 container_of(work, struct usb_line6_pod, startup_work);
264 struct usb_line6 *line6 = &pod->line6;
265
266 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
267
268 /* serial number: */
269 line6_read_serial_number(&pod->line6, &pod->serial_number);
270
271 /* ALSA audio interface: */
272 line6_register_audio(line6);
273}
274
275/* POD special files: */
276static DEVICE_ATTR_RO(device_id);
277static DEVICE_ATTR_RO(firmware_version);
278static DEVICE_ATTR_RO(serial_number);
279
280/* control info callback */
281static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
282 struct snd_ctl_elem_info *uinfo)
283{
284 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
285 uinfo->count = 1;
286 uinfo->value.integer.min = 0;
287 uinfo->value.integer.max = 65535;
288 return 0;
289}
290
291/* control get callback */
292static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
293 struct snd_ctl_elem_value *ucontrol)
294{
295 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
296 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
297 ucontrol->value.integer.value[0] = pod->monitor_level;
298 return 0;
299}
300
301/* control put callback */
302static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
303 struct snd_ctl_elem_value *ucontrol)
304{
305 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
306 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
307
308 if (ucontrol->value.integer.value[0] == pod->monitor_level)
309 return 0;
310
311 pod->monitor_level = ucontrol->value.integer.value[0];
312 pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
313 POD_MONITOR_LEVEL);
314 return 1;
315}
316
317/* control definition */
318static struct snd_kcontrol_new pod_control_monitor = {
319 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
320 .name = "Monitor Playback Volume",
321 .index = 0,
322 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
323 .info = snd_pod_control_monitor_info,
324 .get = snd_pod_control_monitor_get,
325 .put = snd_pod_control_monitor_put
326};
327
328/*
329 POD destructor.
330*/
331static void pod_destruct(struct usb_interface *interface)
332{
333 struct usb_line6_pod *pod = usb_get_intfdata(interface);
334
335 if (pod == NULL)
336 return;
337 line6_cleanup_audio(&pod->line6);
338
339 del_timer(&pod->startup_timer);
340 cancel_work_sync(&pod->startup_work);
341}
342
343/*
344 Create sysfs entries.
345*/
346static int pod_create_files2(struct device *dev)
347{
348 int err;
349
350 CHECK_RETURN(device_create_file(dev, &dev_attr_device_id));
351 CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version));
352 CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number));
353 return 0;
354}
355
356/*
357 Try to init POD device.
358*/
359static int pod_try_init(struct usb_interface *interface,
360 struct usb_line6_pod *pod)
361{
362 int err;
363 struct usb_line6 *line6 = &pod->line6;
364
365 init_timer(&pod->startup_timer);
366 INIT_WORK(&pod->startup_work, pod_startup4);
367
368 if ((interface == NULL) || (pod == NULL))
369 return -ENODEV;
370
371 /* create sysfs entries: */
372 err = pod_create_files2(&interface->dev);
373 if (err < 0)
374 return err;
375
376 /* initialize audio system: */
377 err = line6_init_audio(line6);
378 if (err < 0)
379 return err;
380
381 /* initialize MIDI subsystem: */
382 err = line6_init_midi(line6);
383 if (err < 0)
384 return err;
385
386 /* initialize PCM subsystem: */
387 err = line6_init_pcm(line6, &pod_pcm_properties);
388 if (err < 0)
389 return err;
390
391 /* register monitor control: */
392 err = snd_ctl_add(line6->card,
393 snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
394 if (err < 0)
395 return err;
396
397 /*
398 When the sound card is registered at this point, the PODxt Live
399 displays "Invalid Code Error 07", so we do it later in the event
400 handler.
401 */
402
403 if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) {
404 pod->monitor_level = POD_SYSTEM_INVALID;
405
406 /* initiate startup procedure: */
407 pod_startup1(pod);
408 }
409
410 return 0;
411}
412
413/*
414 Init POD device (and clean up in case of failure).
415*/
416int line6_pod_init(struct usb_interface *interface, struct usb_line6_pod *pod)
417{
418 int err = pod_try_init(interface, pod);
419
420 if (err < 0)
421 pod_destruct(interface);
422
423 return err;
424}
425
426/*
427 POD device disconnected.
428*/
429void line6_pod_disconnect(struct usb_interface *interface)
430{
431 struct usb_line6_pod *pod;
432
433 if (interface == NULL)
434 return;
435 pod = usb_get_intfdata(interface);
436
437 if (pod != NULL) {
438 struct snd_line6_pcm *line6pcm = pod->line6.line6pcm;
439 struct device *dev = &interface->dev;
440
441 if (line6pcm != NULL)
442 line6_pcm_disconnect(line6pcm);
443
444 if (dev != NULL) {
445 /* remove sysfs entries: */
446 device_remove_file(dev, &dev_attr_device_id);
447 device_remove_file(dev, &dev_attr_firmware_version);
448 device_remove_file(dev, &dev_attr_serial_number);
449 }
450 }
451
452 pod_destruct(interface);
453}