blob: fa5caa245d8522e72c5e886a7c85df9b9071061e [file] [log] [blame]
Markus Grabner705ecec2009-02-27 19:43:04 -08001/*
2 * Line6 Linux USB driver - 0.8.0
3 *
4 * Copyright (C) 2004-2009 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 "driver.h"
13
14#include "audio.h"
15#include "capture.h"
16#include "control.h"
17#include "playback.h"
18#include "pod.h"
19
20
21#define POD_SYSEX_CODE 3
22#define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
23
24
25enum {
26 POD_SYSEX_CLIP = 0x0f,
27 POD_SYSEX_SAVE = 0x24,
28 POD_SYSEX_SYSTEM = 0x56,
29 POD_SYSEX_SYSTEMREQ = 0x57,
30 /* POD_SYSEX_UPDATE = 0x6c, */ /* software update! */
31 POD_SYSEX_STORE = 0x71,
32 POD_SYSEX_FINISH = 0x72,
33 POD_SYSEX_DUMPMEM = 0x73,
34 POD_SYSEX_DUMP = 0x74,
35 POD_SYSEX_DUMPREQ = 0x75
36 /* POD_SYSEX_DUMPMEM2 = 0x76 */ /* dumps entire internal memory of PODxt Pro */
37};
38
39enum {
40 POD_monitor_level = 0x04,
41 POD_routing = 0x05,
42 POD_tuner_mute = 0x13,
43 POD_tuner_freq = 0x15,
44 POD_tuner_note = 0x16,
45 POD_tuner_pitch = 0x17,
46 POD_system_invalid = 0x7fff
47};
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
61
62static struct snd_ratden pod_ratden = {
63 .num_min = 78125,
64 .num_max = 78125,
65 .num_step = 1,
66 .den = 2
67};
68
69static struct line6_pcm_properties pod_pcm_properties = {
70 .snd_line6_playback_hw = {
71 .info = (SNDRV_PCM_INFO_MMAP |
72 SNDRV_PCM_INFO_INTERLEAVED |
73 SNDRV_PCM_INFO_BLOCK_TRANSFER |
74 SNDRV_PCM_INFO_MMAP_VALID |
75 SNDRV_PCM_INFO_PAUSE |
76 SNDRV_PCM_INFO_SYNC_START),
77 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
78 .rates = SNDRV_PCM_RATE_KNOT,
79 .rate_min = 39062,
80 .rate_max = 39063,
81 .channels_min = 2,
82 .channels_max = 2,
83 .buffer_bytes_max = 60000,
84 .period_bytes_min = LINE6_ISO_PACKET_SIZE_MAX * POD_BYTES_PER_FRAME, /* at least one URB must fit into one period */
85 .period_bytes_max = 8192,
86 .periods_min = 1,
87 .periods_max = 1024
88 },
89 .snd_line6_capture_hw = {
90 .info = (SNDRV_PCM_INFO_MMAP |
91 SNDRV_PCM_INFO_INTERLEAVED |
92 SNDRV_PCM_INFO_BLOCK_TRANSFER |
93 SNDRV_PCM_INFO_MMAP_VALID |
94 SNDRV_PCM_INFO_SYNC_START),
95 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
96 .rates = SNDRV_PCM_RATE_KNOT,
97 .rate_min = 39062,
98 .rate_max = 39063,
99 .channels_min = 2,
100 .channels_max = 2,
101 .buffer_bytes_max = 60000,
102 .period_bytes_min = LINE6_ISO_PACKET_SIZE_MAX * POD_BYTES_PER_FRAME, /* at least one URB must fit into one period */
103 .period_bytes_max = 8192,
104 .periods_min = 1,
105 .periods_max = 1024
106 },
107 .snd_line6_rates = {
108 .nrats = 1,
109 .rats = &pod_ratden
110 },
111 .bytes_per_frame = POD_BYTES_PER_FRAME
112};
113
114static const char pod_request_version[] = { 0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7 };
115static const char pod_request_channel[] = { 0xf0, 0x00, 0x01, 0x0c, 0x03, 0x75, 0xf7 };
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800116static const char pod_version_header[] = { 0xf2, 0x7e, 0x7f, 0x06, 0x02 };
Markus Grabner705ecec2009-02-27 19:43:04 -0800117
118
119/*
120 Mark all parameters as dirty and notify waiting processes.
121*/
122static void pod_mark_batch_all_dirty(struct usb_line6_pod *pod)
123{
124 int i;
125
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800126 for (i = POD_CONTROL_SIZE; i--;)
Markus Grabner705ecec2009-02-27 19:43:04 -0800127 set_bit(i, pod->param_dirty);
128}
129
130/*
131 Send an asynchronous request for the POD firmware version and device ID.
132*/
133static int pod_version_request_async(struct usb_line6_pod *pod)
134{
135 return line6_send_raw_message_async(&pod->line6, pod->buffer_versionreq, sizeof(pod_request_version));
136}
137
Markus Grabner705ecec2009-02-27 19:43:04 -0800138static void pod_create_files_work(struct work_struct *work)
139{
140 struct usb_line6_pod *pod = container_of(work, struct usb_line6_pod, create_files_work);
Markus Grabner705ecec2009-02-27 19:43:04 -0800141
142 pod_create_files(pod->firmware_version, pod->line6.properties->device_bit, pod->line6.ifcdev);
143}
144
145static void pod_startup_timeout(unsigned long arg)
146{
147 enum {
148 REQUEST_NONE,
149 REQUEST_DUMP,
150 REQUEST_VERSION
151 };
152
153 int request = REQUEST_NONE;
154 struct usb_line6_pod *pod = (struct usb_line6_pod *)arg;
155
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800156 if (pod->dumpreq.ok) {
157 if (!pod->versionreq_ok)
Markus Grabner705ecec2009-02-27 19:43:04 -0800158 request = REQUEST_VERSION;
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800159 } else {
160 if (pod->versionreq_ok)
Markus Grabner705ecec2009-02-27 19:43:04 -0800161 request = REQUEST_DUMP;
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800162 else if (pod->startup_count++ & 1)
Markus Grabner705ecec2009-02-27 19:43:04 -0800163 request = REQUEST_DUMP;
164 else
165 request = REQUEST_VERSION;
166 }
167
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800168 switch (request) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800169 case REQUEST_DUMP:
170 line6_dump_request_async(&pod->dumpreq, &pod->line6, 0);
171 break;
172
173 case REQUEST_VERSION:
174 pod_version_request_async(pod);
175 break;
176
177 default:
178 return;
179 }
180
181 line6_startup_delayed(&pod->dumpreq, 1, pod_startup_timeout, pod);
182}
183
184static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code, int size)
185{
186 return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code, size);
187}
188
189/*
190 Send channel dump data to the PODxt Pro.
191*/
192static void pod_dump(struct usb_line6_pod *pod, const unsigned char *data)
193{
194 int size = 1 + sizeof(pod->prog_data);
195 char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_DUMP, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800196 if (!sysex)
197 return;
198 /* Don't know what this is good for, but PODxt Pro transmits it, so we
199 * also do... */
200 sysex[SYSEX_DATA_OFS] = 5;
Markus Grabner705ecec2009-02-27 19:43:04 -0800201 memcpy(sysex + SYSEX_DATA_OFS + 1, data, sizeof(pod->prog_data));
202 line6_send_sysex_message(&pod->line6, sysex, size);
203 memcpy(&pod->prog_data, data, sizeof(pod->prog_data));
204 pod_mark_batch_all_dirty(pod);
205 kfree(sysex);
206}
207
208/*
209 Store parameter value in driver memory and mark it as dirty.
210*/
211static void pod_store_parameter(struct usb_line6_pod *pod, int param, int value)
212{
213 pod->prog_data.control[param] = value;
214 set_bit(param, pod->param_dirty);
215 pod->dirty = 1;
216}
217
218/*
219 Handle SAVE button
220*/
221static void pod_save_button_pressed(struct usb_line6_pod *pod, int type, int index)
222{
223 pod->dirty = 0;
224 set_bit(POD_SAVE_PRESSED, &pod->atomic_flags);
225}
226
227/*
228 Process a completely received message.
229*/
230void pod_process_message(struct usb_line6_pod *pod)
231{
232 const unsigned char *buf = pod->line6.buffer_message;
233
234 /* filter messages by type */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800235 switch (buf[0] & 0xf0) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800236 case LINE6_PARAM_CHANGE:
237 case LINE6_PROGRAM_CHANGE:
238 case LINE6_SYSEX_BEGIN:
239 break; /* handle these further down */
240
241 default:
242 return; /* ignore all others */
243 }
244
245 /* process all remaining messages */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800246 switch (buf[0]) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800247 case LINE6_PARAM_CHANGE | LINE6_CHANNEL_DEVICE:
248 pod_store_parameter(pod, buf[1], buf[2]);
249 /* intentionally no break here! */
250
251 case LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST:
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800252 if ((buf[1] == POD_amp_model_setup) ||
253 (buf[1] == POD_effect_setup))
254 /* these also affect other settings */
Markus Grabner705ecec2009-02-27 19:43:04 -0800255 line6_dump_request_async(&pod->dumpreq, &pod->line6, 0);
256
257 break;
258
259 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE:
260 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST:
261 pod->channel_num = buf[1];
262 pod->dirty = 0;
263 set_bit(POD_CHANNEL_DIRTY, &pod->atomic_flags);
264 line6_dump_request_async(&pod->dumpreq, &pod->line6, 0);
265 break;
266
267 case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE:
268 case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN:
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800269 if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) == 0) {
270 switch (buf[5]) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800271 case POD_SYSEX_DUMP:
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800272 if (pod->line6.message_length == sizeof(pod->prog_data) + 7) {
273 switch (pod->dumpreq.in_progress) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800274 case LINE6_DUMP_CURRENT:
275 memcpy(&pod->prog_data, buf + 7, sizeof(pod->prog_data));
276 pod_mark_batch_all_dirty(pod);
277 pod->dumpreq.ok = 1;
278 break;
279
280 case POD_DUMP_MEMORY:
281 memcpy(&pod->prog_data_buf, buf + 7, sizeof(pod->prog_data_buf));
282 break;
283
284 default:
285 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "unknown dump code %02X\n", pod->dumpreq.in_progress));
286 }
287
288 line6_dump_finished(&pod->dumpreq);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800289 } else
Markus Grabner705ecec2009-02-27 19:43:04 -0800290 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "wrong size of channel dump message (%d instead of %d)\n",
291 pod->line6.message_length, (int)sizeof(pod->prog_data) + 7));
292
293 break;
294
295 case POD_SYSEX_SYSTEM: {
296 short value = ((int)buf[7] << 12) | ((int)buf[8] << 8) | ((int)buf[9] << 4) | (int)buf[10];
297
298#define PROCESS_SYSTEM_PARAM(x) \
299 case POD_ ## x: \
300 pod->x.value = value; \
301 wake_up_interruptible(&pod->x.wait); \
302 break;
303
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800304 switch (buf[6]) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800305 PROCESS_SYSTEM_PARAM(monitor_level);
306 PROCESS_SYSTEM_PARAM(routing);
307 PROCESS_SYSTEM_PARAM(tuner_mute);
308 PROCESS_SYSTEM_PARAM(tuner_freq);
309 PROCESS_SYSTEM_PARAM(tuner_note);
310 PROCESS_SYSTEM_PARAM(tuner_pitch);
311
312#undef PROCESS_SYSTEM_PARAM
313
314 default:
315 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "unknown tuner/system response %02X\n", buf[6]));
316 }
317
318 break;
319 }
320
321 case POD_SYSEX_FINISH:
322 /* do we need to respond to this? */
323 break;
324
325 case POD_SYSEX_SAVE:
326 pod_save_button_pressed(pod, buf[6], buf[7]);
327 break;
328
329 case POD_SYSEX_CLIP:
330 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "audio clipped\n"));
331 pod->clipping.value = 1;
332 wake_up_interruptible(&pod->clipping.wait);
333 break;
334
335 case POD_SYSEX_STORE:
336 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "message %02X not yet implemented\n", buf[5]));
337 break;
338
339 default:
340 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "unknown sysex message %02X\n", buf[5]));
341 }
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800342 } else if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {
343 if (pod->versionreq_ok == 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800344 pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];
345 pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) | (int)buf[10];
346 pod->versionreq_ok = 1;
347
348 /* Now we know the firmware version, so we schedule a bottom half
349 handler to create the special files: */
Markus Grabner705ecec2009-02-27 19:43:04 -0800350 INIT_WORK(&pod->create_files_work, pod_create_files_work);
Markus Grabner705ecec2009-02-27 19:43:04 -0800351 queue_work(line6_workqueue, &pod->create_files_work);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800352 } else
Markus Grabner705ecec2009-02-27 19:43:04 -0800353 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "multiple firmware version message\n"));
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800354 } else
Markus Grabner705ecec2009-02-27 19:43:04 -0800355 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "unknown sysex header\n"));
356
357 break;
358
359 case LINE6_SYSEX_END:
360 break;
361
362 default:
363 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "POD: unknown message %02X\n", buf[0]));
364 }
365}
366
367/*
368 Detect some cases that require a channel dump after sending a command to the
369 device. Important notes:
370 *) The actual dump request can not be sent here since we are not allowed to
371 wait for the completion of the first message in this context, and sending
372 the dump request before completion of the previous message leaves the POD
373 in an undefined state. The dump request will be sent when the echoed
374 commands are received.
375 *) This method fails if a param change message is "chopped" after the first
376 byte.
377*/
378void pod_midi_postprocess(struct usb_line6_pod *pod, unsigned char *data, int length)
379{
380 int i;
381
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800382 if (!pod->midi_postprocess)
Markus Grabner705ecec2009-02-27 19:43:04 -0800383 return;
384
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800385 for (i = 0; i < length; ++i) {
386 if (data[i] == (LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST)) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800387 line6_invalidate_current(&pod->dumpreq);
388 break;
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800389 } else if ((data[i] == (LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST)) && (i < length - 1))
390 if ((data[i + 1] == POD_amp_model_setup) || (data[i + 1] == POD_effect_setup)) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800391 line6_invalidate_current(&pod->dumpreq);
392 break;
393 }
394 }
395}
396
397/*
398 Send channel number (i.e., switch to a different sound).
399*/
Greg Kroah-Hartmanb702ed252009-02-27 20:45:03 -0800400static void pod_send_channel(struct usb_line6_pod *pod, int value)
Markus Grabner705ecec2009-02-27 19:43:04 -0800401{
402 line6_invalidate_current(&pod->dumpreq);
403
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800404 if (line6_send_program(&pod->line6, value) == 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800405 pod->channel_num = value;
406 else
407 line6_dump_finished(&pod->dumpreq);
408}
409
410/*
411 Transmit PODxt Pro control parameter.
412*/
413void pod_transmit_parameter(struct usb_line6_pod *pod, int param, int value)
414{
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800415 if (line6_transmit_parameter(&pod->line6, param, value) == 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800416 pod_store_parameter(pod, param, value);
417
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800418 if ((param == POD_amp_model_setup) || (param == POD_effect_setup)) /* these also affect other settings */
Markus Grabner705ecec2009-02-27 19:43:04 -0800419 line6_invalidate_current(&pod->dumpreq);
420}
421
422/*
423 Resolve value to memory location.
424*/
425static void pod_resolve(const char *buf, short block0, short block1, unsigned char *location)
426{
427 int value = simple_strtoul(buf, NULL, 10);
428 short block = (value < 0x40) ? block0 : block1;
429 value &= 0x3f;
430 location[0] = block >> 7;
431 location[1] = value | (block & 0x7f);
432}
433
434/*
435 Send command to store channel/effects setup/amp setup to PODxt Pro.
436*/
437static ssize_t pod_send_store_command(struct device *dev, const char *buf, size_t count, short block0, short block1)
438{
439 struct usb_interface *interface = to_usb_interface(dev);
440 struct usb_line6_pod *pod = usb_get_intfdata(interface);
441
442 int size = 3 + sizeof(pod->prog_data_buf);
443 char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_STORE, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800444 if (!sysex)
445 return 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800446
447 sysex[SYSEX_DATA_OFS] = 5; /* see pod_dump() */
448 pod_resolve(buf, block0, block1, sysex + SYSEX_DATA_OFS + 1);
449 memcpy(sysex + SYSEX_DATA_OFS + 3, &pod->prog_data_buf, sizeof(pod->prog_data_buf));
450
451 line6_send_sysex_message(&pod->line6, sysex, size);
452 kfree(sysex);
453 /* needs some delay here on AMD64 platform */
454 return count;
455}
456
457/*
458 Send command to retrieve channel/effects setup/amp setup to PODxt Pro.
459*/
460static ssize_t pod_send_retrieve_command(struct device *dev, const char *buf, size_t count, short block0, short block1)
461{
462 struct usb_interface *interface = to_usb_interface(dev);
463 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Markus Grabner705ecec2009-02-27 19:43:04 -0800464 int size = 4;
465 char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_DUMPMEM, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800466
467 if (!sysex)
468 return 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800469
470 pod_resolve(buf, block0, block1, sysex + SYSEX_DATA_OFS);
471 sysex[SYSEX_DATA_OFS + 2] = 0;
472 sysex[SYSEX_DATA_OFS + 3] = 0;
473 line6_dump_started(&pod->dumpreq, POD_DUMP_MEMORY);
474
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800475 if (line6_send_sysex_message(&pod->line6, sysex, size) < size)
Markus Grabner705ecec2009-02-27 19:43:04 -0800476 line6_dump_finished(&pod->dumpreq);
477
478 kfree(sysex);
479 /* needs some delay here on AMD64 platform */
480 return count;
481}
482
483/*
484 Generic get name function.
485*/
486static ssize_t get_name_generic(struct usb_line6_pod *pod, const char *str, char *buf)
487{
488 int length = 0;
489 const char *p1;
490 char *p2;
491 char *last_non_space = buf;
492
493 int retval = line6_wait_dump(&pod->dumpreq, 0);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800494 if (retval < 0)
495 return retval;
Markus Grabner705ecec2009-02-27 19:43:04 -0800496
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800497 for (p1 = str, p2 = buf; *p1; ++p1, ++p2) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800498 *p2 = *p1;
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800499 if (*p2 != ' ')
500 last_non_space = p2;
501 if (++length == POD_NAME_LENGTH)
502 break;
Markus Grabner705ecec2009-02-27 19:43:04 -0800503 }
504
505 *(last_non_space + 1) = '\n';
506 return last_non_space - buf + 2;
507}
508
509/*
510 "read" request on "channel" special file.
511*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800512static ssize_t pod_get_channel(struct device *dev,
513 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800514{
515 struct usb_interface *interface = to_usb_interface(dev);
516 struct usb_line6_pod *pod = usb_get_intfdata(interface);
517 return sprintf(buf, "%d\n", pod->channel_num);
518}
519
520/*
521 "write" request on "channel" special file.
522*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800523static ssize_t pod_set_channel(struct device *dev,
524 struct device_attribute *attr,
525 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800526{
527 struct usb_interface *interface = to_usb_interface(dev);
528 struct usb_line6_pod *pod = usb_get_intfdata(interface);
529 int value = simple_strtoul(buf, NULL, 10);
530 pod_send_channel(pod, value);
531 return count;
532}
533
534/*
535 "read" request on "name" special file.
536*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800537static ssize_t pod_get_name(struct device *dev, struct device_attribute *attr,
538 char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800539{
540 struct usb_interface *interface = to_usb_interface(dev);
541 struct usb_line6_pod *pod = usb_get_intfdata(interface);
542 return get_name_generic(pod, pod->prog_data.header + POD_NAME_OFFSET, buf);
543}
544
545/*
546 "read" request on "name" special file.
547*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800548static ssize_t pod_get_name_buf(struct device *dev,
549 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800550{
551 struct usb_interface *interface = to_usb_interface(dev);
552 struct usb_line6_pod *pod = usb_get_intfdata(interface);
553 return get_name_generic(pod, pod->prog_data_buf.header + POD_NAME_OFFSET, buf);
554}
555
556/*
557 "read" request on "dump" special file.
558*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800559static ssize_t pod_get_dump(struct device *dev, struct device_attribute *attr,
560 char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800561{
562 struct usb_interface *interface = to_usb_interface(dev);
563 struct usb_line6_pod *pod = usb_get_intfdata(interface);
564 int retval = line6_wait_dump(&pod->dumpreq, 0);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800565 if (retval < 0)
566 return retval;
Markus Grabner705ecec2009-02-27 19:43:04 -0800567 memcpy(buf, &pod->prog_data, sizeof(pod->prog_data));
568 return sizeof(pod->prog_data);
569}
570
571/*
572 "write" request on "dump" special file.
573*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800574static ssize_t pod_set_dump(struct device *dev, struct device_attribute *attr,
575 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800576{
577 struct usb_interface *interface = to_usb_interface(dev);
578 struct usb_line6_pod *pod = usb_get_intfdata(interface);
579
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800580 if (count != sizeof(pod->prog_data)) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800581 dev_err(pod->line6.ifcdev,
582 "data block must be exactly %d bytes\n",
583 (int)sizeof(pod->prog_data));
584 return -EINVAL;
585 }
586
587 pod_dump(pod, buf);
588 return sizeof(pod->prog_data);
589}
590
591/*
592 Request system parameter.
593 @param tuner non-zero, if code refers to a tuner parameter
594*/
595static ssize_t pod_get_system_param(struct usb_line6_pod *pod, char *buf, int code, struct ValueWait *param, int tuner, int sign)
596{
597 char *sysex;
598 int value;
599 static const int size = 1;
600 int retval = 0;
601 DECLARE_WAITQUEUE(wait, current);
602
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800603 if (((pod->prog_data.control[POD_tuner] & 0x40) == 0) && tuner)
Markus Grabner705ecec2009-02-27 19:43:04 -0800604 return -ENODEV;
605
606 /* send value request to tuner: */
607 param->value = POD_system_invalid;
608 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEMREQ, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800609 if (!sysex)
610 return 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800611 sysex[SYSEX_DATA_OFS] = code;
612 line6_send_sysex_message(&pod->line6, sysex, size);
613 kfree(sysex);
614
615 /* wait for tuner to respond: */
616 add_wait_queue(&param->wait, &wait);
617 current->state = TASK_INTERRUPTIBLE;
618
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800619 while (param->value == POD_system_invalid) {
620 if (signal_pending(current)) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800621 retval = -ERESTARTSYS;
622 break;
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800623 } else
Markus Grabner705ecec2009-02-27 19:43:04 -0800624 schedule();
625 }
626
627 current->state = TASK_RUNNING;
628 remove_wait_queue(&param->wait, &wait);
629
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800630 if (retval < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800631 return retval;
632
633 value = sign ? (int)(signed short)param->value : (int)(unsigned short)param->value;
634 return sprintf(buf, "%d\n", value);
635}
636
637/*
638 Send system parameter.
639 @param tuner non-zero, if code refers to a tuner parameter
640*/
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800641static ssize_t pod_set_system_param(struct usb_line6_pod *pod, const char *buf,
642 int count, int code, unsigned short mask,
643 int tuner)
Markus Grabner705ecec2009-02-27 19:43:04 -0800644{
645 char *sysex;
646 static const int size = 5;
647 unsigned short value;
648
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800649 if (((pod->prog_data.control[POD_tuner] & 0x40) == 0) && tuner)
Markus Grabner705ecec2009-02-27 19:43:04 -0800650 return -EINVAL;
651
652 /* send value to tuner: */
653 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800654 if (!sysex)
655 return 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800656 value = simple_strtoul(buf, NULL, 10) & mask;
657 sysex[SYSEX_DATA_OFS] = code;
658 sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
659 sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
660 sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
661 sysex[SYSEX_DATA_OFS + 4] = (value ) & 0x0f;
662 line6_send_sysex_message(&pod->line6, sysex, size);
663 kfree(sysex);
664 return count;
665}
666
667/*
668 "read" request on "dump_buf" special file.
669*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800670static ssize_t pod_get_dump_buf(struct device *dev,
671 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800672{
673 struct usb_interface *interface = to_usb_interface(dev);
674 struct usb_line6_pod *pod = usb_get_intfdata(interface);
675 int retval = line6_wait_dump(&pod->dumpreq, 0);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800676 if (retval < 0)
677 return retval;
Markus Grabner705ecec2009-02-27 19:43:04 -0800678 memcpy(buf, &pod->prog_data_buf, sizeof(pod->prog_data_buf));
679 return sizeof(pod->prog_data_buf);
680}
681
682/*
683 "write" request on "dump_buf" special file.
684*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800685static ssize_t pod_set_dump_buf(struct device *dev,
686 struct device_attribute *attr,
687 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800688{
689 struct usb_interface *interface = to_usb_interface(dev);
690 struct usb_line6_pod *pod = usb_get_intfdata(interface);
691
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800692 if (count != sizeof(pod->prog_data)) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800693 dev_err(pod->line6.ifcdev,
694 "data block must be exactly %d bytes\n",
695 (int)sizeof(pod->prog_data));
696 return -EINVAL;
697 }
698
699 memcpy(&pod->prog_data_buf, buf, sizeof(pod->prog_data));
700 return sizeof(pod->prog_data);
701}
702
703/*
704 "write" request on "finish" special file.
705*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800706static ssize_t pod_set_finish(struct device *dev,
707 struct device_attribute *attr,
708 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800709{
710 struct usb_interface *interface = to_usb_interface(dev);
711 struct usb_line6_pod *pod = usb_get_intfdata(interface);
712 int size = 0;
713 char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_FINISH, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800714 if (!sysex)
715 return 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800716 line6_send_sysex_message(&pod->line6, sysex, size);
717 kfree(sysex);
718 return count;
719}
720
721/*
722 "write" request on "store_channel" special file.
723*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800724static ssize_t pod_set_store_channel(struct device *dev,
725 struct device_attribute *attr,
726 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800727{
728 return pod_send_store_command(dev, buf, count, 0x0000, 0x00c0);
729}
730
731/*
732 "write" request on "store_effects_setup" special file.
733*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800734static ssize_t pod_set_store_effects_setup(struct device *dev,
735 struct device_attribute *attr,
736 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800737{
738 return pod_send_store_command(dev, buf, count, 0x0080, 0x0080);
739}
740
741/*
742 "write" request on "store_amp_setup" special file.
743*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800744static ssize_t pod_set_store_amp_setup(struct device *dev,
745 struct device_attribute *attr,
746 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800747{
748 return pod_send_store_command(dev, buf, count, 0x0040, 0x0100);
749}
750
751/*
752 "write" request on "retrieve_channel" special file.
753*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800754static ssize_t pod_set_retrieve_channel(struct device *dev,
755 struct device_attribute *attr,
756 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800757{
758 return pod_send_retrieve_command(dev, buf, count, 0x0000, 0x00c0);
759}
760
761/*
762 "write" request on "retrieve_effects_setup" special file.
763*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800764static ssize_t pod_set_retrieve_effects_setup(struct device *dev,
765 struct device_attribute *attr,
766 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800767{
768 return pod_send_retrieve_command(dev, buf, count, 0x0080, 0x0080);
769}
770
771/*
772 "write" request on "retrieve_amp_setup" special file.
773*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800774static ssize_t pod_set_retrieve_amp_setup(struct device *dev,
775 struct device_attribute *attr,
776 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800777{
778 return pod_send_retrieve_command(dev, buf, count, 0x0040, 0x0100);
779}
780
781/*
782 "read" request on "dirty" special file.
783*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800784static ssize_t pod_get_dirty(struct device *dev, struct device_attribute *attr,
785 char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800786{
787 struct usb_interface *interface = to_usb_interface(dev);
788 struct usb_line6_pod *pod = usb_get_intfdata(interface);
789 buf[0] = pod->dirty ? '1' : '0';
790 buf[1] = '\n';
791 return 2;
792}
793
794/*
795 "read" request on "midi_postprocess" special file.
796*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800797static ssize_t pod_get_midi_postprocess(struct device *dev,
798 struct device_attribute *attr,
799 char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800800{
801 struct usb_interface *interface = to_usb_interface(dev);
802 struct usb_line6_pod *pod = usb_get_intfdata(interface);
803 return sprintf(buf, "%d\n", pod->midi_postprocess);
804}
805
806/*
807 "write" request on "midi_postprocess" special file.
808*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800809static ssize_t pod_set_midi_postprocess(struct device *dev,
810 struct device_attribute *attr,
811 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800812{
813 struct usb_interface *interface = to_usb_interface(dev);
814 struct usb_line6_pod *pod = usb_get_intfdata(interface);
815 int value = simple_strtoul(buf, NULL, 10);
816 pod->midi_postprocess = value ? 1 : 0;
817 return count;
818}
819
820/*
821 "read" request on "serial_number" special file.
822*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800823static ssize_t pod_get_serial_number(struct device *dev,
824 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800825{
826 struct usb_interface *interface = to_usb_interface(dev);
827 struct usb_line6_pod *pod = usb_get_intfdata(interface);
828 return sprintf(buf, "%d\n", pod->serial_number);
829}
830
831/*
832 "read" request on "firmware_version" special file.
833*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800834static ssize_t pod_get_firmware_version(struct device *dev,
835 struct device_attribute *attr,
836 char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800837{
838 struct usb_interface *interface = to_usb_interface(dev);
839 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800840 return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
841 pod->firmware_version % 100);
Markus Grabner705ecec2009-02-27 19:43:04 -0800842}
843
844/*
845 "read" request on "device_id" special file.
846*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800847static ssize_t pod_get_device_id(struct device *dev,
848 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800849{
850 struct usb_interface *interface = to_usb_interface(dev);
851 struct usb_line6_pod *pod = usb_get_intfdata(interface);
852 return sprintf(buf, "%d\n", pod->device_id);
853}
854
855/*
856 "read" request on "clip" special file.
857*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800858static ssize_t pod_wait_for_clip(struct device *dev,
859 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800860{
861 struct usb_interface *interface = to_usb_interface(dev);
862 struct usb_line6_pod *pod = usb_get_intfdata(interface);
863 int err = 0;
864 DECLARE_WAITQUEUE(wait, current);
865 pod->clipping.value = 0;
866 add_wait_queue(&pod->clipping.wait, &wait);
867 current->state = TASK_INTERRUPTIBLE;
868
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800869 while (pod->clipping.value == 0) {
870 if (signal_pending(current)) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800871 err = -ERESTARTSYS;
872 break;
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800873 } else
Markus Grabner705ecec2009-02-27 19:43:04 -0800874 schedule();
875 }
876
877 current->state = TASK_RUNNING;
878 remove_wait_queue(&pod->clipping.wait, &wait);
879 return err;
880}
881
882#define POD_GET_SYSTEM_PARAM(code, tuner, sign) \
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800883static ssize_t pod_get_ ## code(struct device *dev, \
884 struct device_attribute *attr, char *buf) \
Markus Grabner705ecec2009-02-27 19:43:04 -0800885{ \
886 struct usb_interface *interface = to_usb_interface(dev); \
887 struct usb_line6_pod *pod = usb_get_intfdata(interface); \
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800888 return pod_get_system_param(pod, buf, POD_ ## code, &pod->code, \
889 tuner, sign); \
Markus Grabner705ecec2009-02-27 19:43:04 -0800890}
891
892#define POD_GET_SET_SYSTEM_PARAM(code, mask, tuner, sign) \
893POD_GET_SYSTEM_PARAM(code, tuner, sign) \
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800894static ssize_t pod_set_ ## code(struct device *dev, \
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800895 struct device_attribute *attr, \
896 const char *buf, size_t count) \
Markus Grabner705ecec2009-02-27 19:43:04 -0800897{ \
898 struct usb_interface *interface = to_usb_interface(dev); \
899 struct usb_line6_pod *pod = usb_get_intfdata(interface); \
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800900 return pod_set_system_param(pod, buf, count, POD_ ## code, mask, \
901 tuner); \
Markus Grabner705ecec2009-02-27 19:43:04 -0800902}
903
904POD_GET_SET_SYSTEM_PARAM(monitor_level, 0xffff, 0, 0);
905POD_GET_SET_SYSTEM_PARAM(routing, 0x0003, 0, 0);
906POD_GET_SET_SYSTEM_PARAM(tuner_mute, 0x0001, 1, 0);
907POD_GET_SET_SYSTEM_PARAM(tuner_freq, 0xffff, 1, 0);
908POD_GET_SYSTEM_PARAM(tuner_note, 1, 1);
909POD_GET_SYSTEM_PARAM(tuner_pitch, 1, 1);
910
911#undef GET_SET_SYSTEM_PARAM
912#undef GET_SYSTEM_PARAM
913
914/* POD special files: */
915static DEVICE_ATTR(channel, S_IWUGO | S_IRUGO, pod_get_channel, pod_set_channel);
916static DEVICE_ATTR(clip, S_IRUGO, pod_wait_for_clip, line6_nop_write);
917static DEVICE_ATTR(device_id, S_IRUGO, pod_get_device_id, line6_nop_write);
918static DEVICE_ATTR(dirty, S_IRUGO, pod_get_dirty, line6_nop_write);
919static DEVICE_ATTR(dump, S_IWUGO | S_IRUGO, pod_get_dump, pod_set_dump);
920static DEVICE_ATTR(dump_buf, S_IWUGO | S_IRUGO, pod_get_dump_buf, pod_set_dump_buf);
921static DEVICE_ATTR(finish, S_IWUGO, line6_nop_read, pod_set_finish);
922static DEVICE_ATTR(firmware_version, S_IRUGO, pod_get_firmware_version, line6_nop_write);
923static DEVICE_ATTR(midi_postprocess, S_IWUGO | S_IRUGO, pod_get_midi_postprocess, pod_set_midi_postprocess);
924static DEVICE_ATTR(monitor_level, S_IWUGO | S_IRUGO, pod_get_monitor_level, pod_set_monitor_level);
925static DEVICE_ATTR(name, S_IRUGO, pod_get_name, line6_nop_write);
926static DEVICE_ATTR(name_buf, S_IRUGO, pod_get_name_buf, line6_nop_write);
927static DEVICE_ATTR(retrieve_amp_setup, S_IWUGO, line6_nop_read, pod_set_retrieve_amp_setup);
928static DEVICE_ATTR(retrieve_channel, S_IWUGO, line6_nop_read, pod_set_retrieve_channel);
929static DEVICE_ATTR(retrieve_effects_setup, S_IWUGO, line6_nop_read, pod_set_retrieve_effects_setup);
930static DEVICE_ATTR(routing, S_IWUGO | S_IRUGO, pod_get_routing, pod_set_routing);
931static DEVICE_ATTR(serial_number, S_IRUGO, pod_get_serial_number, line6_nop_write);
932static DEVICE_ATTR(store_amp_setup, S_IWUGO, line6_nop_read, pod_set_store_amp_setup);
933static DEVICE_ATTR(store_channel, S_IWUGO, line6_nop_read, pod_set_store_channel);
934static DEVICE_ATTR(store_effects_setup, S_IWUGO, line6_nop_read, pod_set_store_effects_setup);
935static DEVICE_ATTR(tuner_freq, S_IWUGO | S_IRUGO, pod_get_tuner_freq, pod_set_tuner_freq);
936static DEVICE_ATTR(tuner_mute, S_IWUGO | S_IRUGO, pod_get_tuner_mute, pod_set_tuner_mute);
937static DEVICE_ATTR(tuner_note, S_IRUGO, pod_get_tuner_note, line6_nop_write);
938static DEVICE_ATTR(tuner_pitch, S_IRUGO, pod_get_tuner_pitch, line6_nop_write);
939
940#if CREATE_RAW_FILE
941static DEVICE_ATTR(raw, S_IWUGO, line6_nop_read, line6_set_raw);
942#endif
943
944/*
945 POD destructor.
946*/
947static void pod_destruct(struct usb_interface *interface)
948{
949 struct usb_line6_pod *pod = usb_get_intfdata(interface);
950 struct usb_line6 *line6;
951
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800952 if (pod == NULL)
953 return;
Markus Grabner705ecec2009-02-27 19:43:04 -0800954 line6 = &pod->line6;
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800955 if (line6 == NULL)
956 return;
Markus Grabner705ecec2009-02-27 19:43:04 -0800957 line6_cleanup_audio(line6);
958
959 /* free dump request data: */
960 line6_dumpreq_destruct(&pod->dumpreq);
961
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800962 kfree(pod->buffer_versionreq);
Markus Grabner705ecec2009-02-27 19:43:04 -0800963}
964
965/*
966 Create sysfs entries.
967*/
Greg Kroah-Hartmanb702ed252009-02-27 20:45:03 -0800968static int pod_create_files2(struct device *dev)
Markus Grabner705ecec2009-02-27 19:43:04 -0800969{
970 int err;
971
972 CHECK_RETURN(device_create_file(dev, &dev_attr_channel));
973 CHECK_RETURN(device_create_file(dev, &dev_attr_clip));
974 CHECK_RETURN(device_create_file(dev, &dev_attr_device_id));
975 CHECK_RETURN(device_create_file(dev, &dev_attr_dirty));
976 CHECK_RETURN(device_create_file(dev, &dev_attr_dump));
977 CHECK_RETURN(device_create_file(dev, &dev_attr_dump_buf));
978 CHECK_RETURN(device_create_file(dev, &dev_attr_finish));
979 CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version));
980 CHECK_RETURN(device_create_file(dev, &dev_attr_midi_postprocess));
981 CHECK_RETURN(device_create_file(dev, &dev_attr_monitor_level));
982 CHECK_RETURN(device_create_file(dev, &dev_attr_name));
983 CHECK_RETURN(device_create_file(dev, &dev_attr_name_buf));
984 CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_amp_setup));
985 CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_channel));
986 CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_effects_setup));
987 CHECK_RETURN(device_create_file(dev, &dev_attr_routing));
988 CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number));
989 CHECK_RETURN(device_create_file(dev, &dev_attr_store_amp_setup));
990 CHECK_RETURN(device_create_file(dev, &dev_attr_store_channel));
991 CHECK_RETURN(device_create_file(dev, &dev_attr_store_effects_setup));
992 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_freq));
993 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_mute));
994 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_note));
995 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_pitch));
996
997#if CREATE_RAW_FILE
998 CHECK_RETURN(device_create_file(dev, &dev_attr_raw));
999#endif
1000
1001 return 0;
1002}
1003
1004/*
1005 Init POD device.
1006*/
1007int pod_init(struct usb_interface *interface, struct usb_line6_pod *pod)
1008{
1009 int err;
1010 struct usb_line6 *line6 = &pod->line6;
1011
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001012 if ((interface == NULL) || (pod == NULL))
1013 return -ENODEV;
Markus Grabner705ecec2009-02-27 19:43:04 -08001014
1015 pod->channel_num = 255;
1016
1017 /* initialize wait queues: */
1018 init_waitqueue_head(&pod->monitor_level.wait);
1019 init_waitqueue_head(&pod->routing.wait);
1020 init_waitqueue_head(&pod->tuner_mute.wait);
1021 init_waitqueue_head(&pod->tuner_freq.wait);
1022 init_waitqueue_head(&pod->tuner_note.wait);
1023 init_waitqueue_head(&pod->tuner_pitch.wait);
1024 init_waitqueue_head(&pod->clipping.wait);
1025
1026 memset(pod->param_dirty, 0xff, sizeof(pod->param_dirty));
1027
1028 /* initialize USB buffers: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001029 err = line6_dumpreq_init(&pod->dumpreq, pod_request_channel,
1030 sizeof(pod_request_channel));
1031 if (err < 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001032 dev_err(&interface->dev, "Out of memory\n");
1033 pod_destruct(interface);
1034 return -ENOMEM;
1035 }
1036
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001037 pod->buffer_versionreq = kmalloc(sizeof(pod_request_version),
1038 GFP_KERNEL);
Markus Grabner705ecec2009-02-27 19:43:04 -08001039
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001040 if (pod->buffer_versionreq == NULL) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001041 dev_err(&interface->dev, "Out of memory\n");
1042 pod_destruct(interface);
1043 return -ENOMEM;
1044 }
1045
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001046 memcpy(pod->buffer_versionreq, pod_request_version,
1047 sizeof(pod_request_version));
Markus Grabner705ecec2009-02-27 19:43:04 -08001048
1049 /* create sysfs entries: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001050 err = pod_create_files2(&interface->dev);
1051 if (err < 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001052 pod_destruct(interface);
1053 return err;
1054 }
1055
1056 /* initialize audio system: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001057 err = line6_init_audio(line6);
1058 if (err < 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001059 pod_destruct(interface);
1060 return err;
1061 }
1062
1063 /* initialize MIDI subsystem: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001064 err = line6_init_midi(line6);
1065 if (err < 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001066 pod_destruct(interface);
1067 return err;
1068 }
1069
1070 /* initialize PCM subsystem: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001071 err = line6_init_pcm(line6, &pod_pcm_properties);
1072 if (err < 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001073 pod_destruct(interface);
1074 return err;
1075 }
1076
1077 /* register audio system: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001078 err = line6_register_audio(line6);
1079 if (err < 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001080 pod_destruct(interface);
1081 return err;
1082 }
1083
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001084 if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001085 /* query some data: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001086 line6_startup_delayed(&pod->dumpreq, POD_STARTUP_DELAY,
1087 pod_startup_timeout, pod);
Markus Grabner705ecec2009-02-27 19:43:04 -08001088 line6_read_serial_number(&pod->line6, &pod->serial_number);
1089 }
1090
1091 return 0;
1092}
1093
1094/*
1095 POD device disconnected.
1096*/
1097void pod_disconnect(struct usb_interface *interface)
1098{
1099 struct usb_line6_pod *pod;
1100
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001101 if (interface == NULL)
1102 return;
Markus Grabner705ecec2009-02-27 19:43:04 -08001103 pod = usb_get_intfdata(interface);
1104
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001105 if (pod != NULL) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001106 struct snd_line6_pcm *line6pcm = pod->line6.line6pcm;
1107 struct device *dev = &interface->dev;
1108
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001109 if (line6pcm != NULL) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001110 unlink_wait_clear_audio_out_urbs(line6pcm);
1111 unlink_wait_clear_audio_in_urbs(line6pcm);
1112 }
1113
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001114 if (dev != NULL) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001115 /* remove sysfs entries: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001116 if (pod->versionreq_ok)
Markus Grabner705ecec2009-02-27 19:43:04 -08001117 pod_remove_files(pod->firmware_version, pod->line6.properties->device_bit, dev);
1118
1119 device_remove_file(dev, &dev_attr_channel);
1120 device_remove_file(dev, &dev_attr_clip);
1121 device_remove_file(dev, &dev_attr_device_id);
1122 device_remove_file(dev, &dev_attr_dirty);
1123 device_remove_file(dev, &dev_attr_dump);
1124 device_remove_file(dev, &dev_attr_dump_buf);
1125 device_remove_file(dev, &dev_attr_finish);
1126 device_remove_file(dev, &dev_attr_firmware_version);
1127 device_remove_file(dev, &dev_attr_midi_postprocess);
1128 device_remove_file(dev, &dev_attr_monitor_level);
1129 device_remove_file(dev, &dev_attr_name);
1130 device_remove_file(dev, &dev_attr_name_buf);
1131 device_remove_file(dev, &dev_attr_retrieve_amp_setup);
1132 device_remove_file(dev, &dev_attr_retrieve_channel);
1133 device_remove_file(dev, &dev_attr_retrieve_effects_setup);
1134 device_remove_file(dev, &dev_attr_routing);
1135 device_remove_file(dev, &dev_attr_serial_number);
1136 device_remove_file(dev, &dev_attr_store_amp_setup);
1137 device_remove_file(dev, &dev_attr_store_channel);
1138 device_remove_file(dev, &dev_attr_store_effects_setup);
1139 device_remove_file(dev, &dev_attr_tuner_freq);
1140 device_remove_file(dev, &dev_attr_tuner_mute);
1141 device_remove_file(dev, &dev_attr_tuner_note);
1142 device_remove_file(dev, &dev_attr_tuner_pitch);
1143
1144#if CREATE_RAW_FILE
1145 device_remove_file(dev, &dev_attr_raw);
1146#endif
1147 }
1148 }
1149
1150 pod_destruct(interface);
1151}