blob: e6a1c79cd8519e3a431980a0e1622fcc1c19087f [file] [log] [blame]
Markus Grabner705ecec2009-02-27 19:43:04 -08001/*
Markus Grabnere1a164d2010-08-23 01:08:25 +02002 * Line6 Linux USB driver - 0.9.1beta
Markus Grabner705ecec2009-02-27 19:43:04 -08003 *
Markus Grabner1027f4762010-08-12 01:35:30 +02004 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
Markus Grabner705ecec2009-02-27 19:43:04 -08005 *
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
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090012#include <linux/slab.h>
Markus Grabner1027f4762010-08-12 01:35:30 +020013#include <linux/wait.h>
14#include <sound/control.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090015
Markus Grabner705ecec2009-02-27 19:43:04 -080016#include "audio.h"
17#include "capture.h"
18#include "control.h"
Markus Grabner1027f4762010-08-12 01:35:30 +020019#include "driver.h"
Markus Grabner705ecec2009-02-27 19:43:04 -080020#include "playback.h"
21#include "pod.h"
22
Markus Grabner705ecec2009-02-27 19:43:04 -080023#define POD_SYSEX_CODE 3
Markus Grabnere1a164d2010-08-23 01:08:25 +020024#define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
Markus Grabner705ecec2009-02-27 19:43:04 -080025
Markus Grabnere1a164d2010-08-23 01:08:25 +020026/* *INDENT-OFF* */
Markus Grabner705ecec2009-02-27 19:43:04 -080027
28enum {
29 POD_SYSEX_CLIP = 0x0f,
30 POD_SYSEX_SAVE = 0x24,
31 POD_SYSEX_SYSTEM = 0x56,
32 POD_SYSEX_SYSTEMREQ = 0x57,
33 /* POD_SYSEX_UPDATE = 0x6c, */ /* software update! */
34 POD_SYSEX_STORE = 0x71,
35 POD_SYSEX_FINISH = 0x72,
36 POD_SYSEX_DUMPMEM = 0x73,
37 POD_SYSEX_DUMP = 0x74,
38 POD_SYSEX_DUMPREQ = 0x75
39 /* POD_SYSEX_DUMPMEM2 = 0x76 */ /* dumps entire internal memory of PODxt Pro */
40};
41
42enum {
43 POD_monitor_level = 0x04,
44 POD_routing = 0x05,
45 POD_tuner_mute = 0x13,
46 POD_tuner_freq = 0x15,
47 POD_tuner_note = 0x16,
48 POD_tuner_pitch = 0x17,
Markus Grabner1027f4762010-08-12 01:35:30 +020049 POD_system_invalid = 0x10000
Markus Grabner705ecec2009-02-27 19:43:04 -080050};
51
Markus Grabnere1a164d2010-08-23 01:08:25 +020052/* *INDENT-ON* */
53
Markus Grabner705ecec2009-02-27 19:43:04 -080054enum {
55 POD_DUMP_MEMORY = 2
56};
57
58enum {
59 POD_BUSY_READ,
60 POD_BUSY_WRITE,
61 POD_CHANNEL_DIRTY,
62 POD_SAVE_PRESSED,
63 POD_BUSY_MIDISEND
64};
65
Markus Grabner705ecec2009-02-27 19:43:04 -080066static struct snd_ratden pod_ratden = {
67 .num_min = 78125,
68 .num_max = 78125,
69 .num_step = 1,
70 .den = 2
71};
72
73static struct line6_pcm_properties pod_pcm_properties = {
Markus Grabner1027f4762010-08-12 01:35:30 +020074 .snd_line6_playback_hw = {
Markus Grabnere1a164d2010-08-23 01:08:25 +020075 .info = (SNDRV_PCM_INFO_MMAP |
76 SNDRV_PCM_INFO_INTERLEAVED |
77 SNDRV_PCM_INFO_BLOCK_TRANSFER |
78 SNDRV_PCM_INFO_MMAP_VALID |
79 SNDRV_PCM_INFO_PAUSE |
Markus Grabner1027f4762010-08-12 01:35:30 +020080#ifdef CONFIG_PM
Markus Grabnere1a164d2010-08-23 01:08:25 +020081 SNDRV_PCM_INFO_RESUME |
Markus Grabner1027f4762010-08-12 01:35:30 +020082#endif
Markus Grabnere1a164d2010-08-23 01:08:25 +020083 SNDRV_PCM_INFO_SYNC_START),
84 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
85 .rates = SNDRV_PCM_RATE_KNOT,
86 .rate_min = 39062,
87 .rate_max = 39063,
88 .channels_min = 2,
89 .channels_max = 2,
90 .buffer_bytes_max = 60000,
91 .period_bytes_min = 64,
92 .period_bytes_max = 8192,
93 .periods_min = 1,
94 .periods_max = 1024},
Markus Grabner1027f4762010-08-12 01:35:30 +020095 .snd_line6_capture_hw = {
Markus Grabnere1a164d2010-08-23 01:08:25 +020096 .info = (SNDRV_PCM_INFO_MMAP |
97 SNDRV_PCM_INFO_INTERLEAVED |
98 SNDRV_PCM_INFO_BLOCK_TRANSFER |
99 SNDRV_PCM_INFO_MMAP_VALID |
Markus Grabner1027f4762010-08-12 01:35:30 +0200100#ifdef CONFIG_PM
Markus Grabnere1a164d2010-08-23 01:08:25 +0200101 SNDRV_PCM_INFO_RESUME |
Markus Grabner1027f4762010-08-12 01:35:30 +0200102#endif
Markus Grabnere1a164d2010-08-23 01:08:25 +0200103 SNDRV_PCM_INFO_SYNC_START),
104 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
105 .rates = SNDRV_PCM_RATE_KNOT,
106 .rate_min = 39062,
107 .rate_max = 39063,
108 .channels_min = 2,
109 .channels_max = 2,
110 .buffer_bytes_max = 60000,
111 .period_bytes_min = 64,
112 .period_bytes_max = 8192,
113 .periods_min = 1,
114 .periods_max = 1024},
Markus Grabner705ecec2009-02-27 19:43:04 -0800115 .snd_line6_rates = {
Markus Grabnere1a164d2010-08-23 01:08:25 +0200116 .nrats = 1,
117 .rats = &pod_ratden},
Markus Grabner705ecec2009-02-27 19:43:04 -0800118 .bytes_per_frame = POD_BYTES_PER_FRAME
119};
120
Markus Grabner1027f4762010-08-12 01:35:30 +0200121static const char pod_request_channel[] = {
122 0xf0, 0x00, 0x01, 0x0c, 0x03, 0x75, 0xf7
123};
124
Markus Grabnere1a164d2010-08-23 01:08:25 +0200125static const char pod_version_header[] = {
Markus Grabner1027f4762010-08-12 01:35:30 +0200126 0xf2, 0x7e, 0x7f, 0x06, 0x02
127};
128
Markus Grabner1027f4762010-08-12 01:35:30 +0200129/* forward declarations: */
130static void pod_startup2(unsigned long data);
131static void pod_startup3(struct usb_line6_pod *pod);
132static void pod_startup4(struct usb_line6_pod *pod);
Markus Grabner705ecec2009-02-27 19:43:04 -0800133
Markus Grabner705ecec2009-02-27 19:43:04 -0800134/*
135 Mark all parameters as dirty and notify waiting processes.
136*/
137static void pod_mark_batch_all_dirty(struct usb_line6_pod *pod)
138{
139 int i;
140
Frederik Deweerdte1769b32009-09-14 08:51:38 +0000141 for (i = 0; i < POD_CONTROL_SIZE; i++)
Markus Grabner705ecec2009-02-27 19:43:04 -0800142 set_bit(i, pod->param_dirty);
143}
144
Markus Grabnere1a164d2010-08-23 01:08:25 +0200145static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
146 int size)
Markus Grabner705ecec2009-02-27 19:43:04 -0800147{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200148 return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code,
149 size);
Markus Grabner705ecec2009-02-27 19:43:04 -0800150}
151
152/*
153 Send channel dump data to the PODxt Pro.
154*/
155static void pod_dump(struct usb_line6_pod *pod, const unsigned char *data)
156{
157 int size = 1 + sizeof(pod->prog_data);
158 char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_DUMP, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800159 if (!sysex)
160 return;
161 /* Don't know what this is good for, but PODxt Pro transmits it, so we
162 * also do... */
163 sysex[SYSEX_DATA_OFS] = 5;
Markus Grabner705ecec2009-02-27 19:43:04 -0800164 memcpy(sysex + SYSEX_DATA_OFS + 1, data, sizeof(pod->prog_data));
165 line6_send_sysex_message(&pod->line6, sysex, size);
166 memcpy(&pod->prog_data, data, sizeof(pod->prog_data));
167 pod_mark_batch_all_dirty(pod);
168 kfree(sysex);
169}
170
171/*
172 Store parameter value in driver memory and mark it as dirty.
173*/
174static void pod_store_parameter(struct usb_line6_pod *pod, int param, int value)
175{
176 pod->prog_data.control[param] = value;
177 set_bit(param, pod->param_dirty);
178 pod->dirty = 1;
179}
180
181/*
Markus Grabner1027f4762010-08-12 01:35:30 +0200182 Handle SAVE button.
Markus Grabner705ecec2009-02-27 19:43:04 -0800183*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200184static void pod_save_button_pressed(struct usb_line6_pod *pod, int type,
185 int index)
Markus Grabner705ecec2009-02-27 19:43:04 -0800186{
187 pod->dirty = 0;
188 set_bit(POD_SAVE_PRESSED, &pod->atomic_flags);
189}
190
191/*
192 Process a completely received message.
193*/
Markus Grabner1027f4762010-08-12 01:35:30 +0200194void line6_pod_process_message(struct usb_line6_pod *pod)
Markus Grabner705ecec2009-02-27 19:43:04 -0800195{
196 const unsigned char *buf = pod->line6.buffer_message;
197
198 /* filter messages by type */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800199 switch (buf[0] & 0xf0) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800200 case LINE6_PARAM_CHANGE:
201 case LINE6_PROGRAM_CHANGE:
202 case LINE6_SYSEX_BEGIN:
Markus Grabnere1a164d2010-08-23 01:08:25 +0200203 break; /* handle these further down */
Markus Grabner705ecec2009-02-27 19:43:04 -0800204
205 default:
Markus Grabnere1a164d2010-08-23 01:08:25 +0200206 return; /* ignore all others */
Markus Grabner705ecec2009-02-27 19:43:04 -0800207 }
208
209 /* process all remaining messages */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800210 switch (buf[0]) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800211 case LINE6_PARAM_CHANGE | LINE6_CHANNEL_DEVICE:
212 pod_store_parameter(pod, buf[1], buf[2]);
213 /* intentionally no break here! */
214
215 case LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST:
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800216 if ((buf[1] == POD_amp_model_setup) ||
217 (buf[1] == POD_effect_setup))
218 /* these also affect other settings */
Markus Grabnere1a164d2010-08-23 01:08:25 +0200219 line6_dump_request_async(&pod->dumpreq, &pod->line6, 0,
220 LINE6_DUMP_CURRENT);
Markus Grabner705ecec2009-02-27 19:43:04 -0800221
222 break;
223
224 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE:
225 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST:
226 pod->channel_num = buf[1];
227 pod->dirty = 0;
228 set_bit(POD_CHANNEL_DIRTY, &pod->atomic_flags);
Markus Grabnere1a164d2010-08-23 01:08:25 +0200229 line6_dump_request_async(&pod->dumpreq, &pod->line6, 0,
230 LINE6_DUMP_CURRENT);
Markus Grabner705ecec2009-02-27 19:43:04 -0800231 break;
232
233 case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE:
234 case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN:
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800235 if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) == 0) {
236 switch (buf[5]) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800237 case POD_SYSEX_DUMP:
Markus Grabnere1a164d2010-08-23 01:08:25 +0200238 if (pod->line6.message_length ==
239 sizeof(pod->prog_data) + 7) {
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800240 switch (pod->dumpreq.in_progress) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800241 case LINE6_DUMP_CURRENT:
Markus Grabnere1a164d2010-08-23 01:08:25 +0200242 memcpy(&pod->prog_data, buf + 7,
243 sizeof(pod->prog_data));
Markus Grabner705ecec2009-02-27 19:43:04 -0800244 pod_mark_batch_all_dirty(pod);
Markus Grabner705ecec2009-02-27 19:43:04 -0800245 break;
246
247 case POD_DUMP_MEMORY:
Markus Grabnere1a164d2010-08-23 01:08:25 +0200248 memcpy(&pod->prog_data_buf,
249 buf + 7,
250 sizeof
251 (pod->prog_data_buf));
Markus Grabner705ecec2009-02-27 19:43:04 -0800252 break;
253
254 default:
Markus Grabnere1a164d2010-08-23 01:08:25 +0200255 DEBUG_MESSAGES(dev_err
256 (pod->
257 line6.ifcdev,
258 "unknown dump code %02X\n",
259 pod->
260 dumpreq.in_progress));
Markus Grabner705ecec2009-02-27 19:43:04 -0800261 }
262
263 line6_dump_finished(&pod->dumpreq);
Markus Grabner1027f4762010-08-12 01:35:30 +0200264 pod_startup3(pod);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800265 } else
Markus Grabnere1a164d2010-08-23 01:08:25 +0200266 DEBUG_MESSAGES(dev_err
267 (pod->line6.ifcdev,
268 "wrong size of channel dump message (%d instead of %d)\n",
269 pod->
270 line6.message_length,
271 (int)
272 sizeof(pod->prog_data) +
273 7));
Markus Grabner705ecec2009-02-27 19:43:04 -0800274
275 break;
276
Markus Grabnere1a164d2010-08-23 01:08:25 +0200277 case POD_SYSEX_SYSTEM:{
278 short value =
279 ((int)buf[7] << 12) | ((int)buf[8]
280 << 8) |
281 ((int)buf[9] << 4) | (int)buf[10];
Markus Grabner705ecec2009-02-27 19:43:04 -0800282
283#define PROCESS_SYSTEM_PARAM(x) \
284 case POD_ ## x: \
285 pod->x.value = value; \
Markus Grabner1027f4762010-08-12 01:35:30 +0200286 wake_up(&pod->x.wait); \
Markus Grabner705ecec2009-02-27 19:43:04 -0800287 break;
288
Markus Grabnere1a164d2010-08-23 01:08:25 +0200289 switch (buf[6]) {
290 PROCESS_SYSTEM_PARAM
291 (monitor_level);
292 PROCESS_SYSTEM_PARAM(routing);
293 PROCESS_SYSTEM_PARAM
294 (tuner_mute);
295 PROCESS_SYSTEM_PARAM
296 (tuner_freq);
297 PROCESS_SYSTEM_PARAM
298 (tuner_note);
299 PROCESS_SYSTEM_PARAM
300 (tuner_pitch);
Markus Grabner705ecec2009-02-27 19:43:04 -0800301
302#undef PROCESS_SYSTEM_PARAM
303
Markus Grabnere1a164d2010-08-23 01:08:25 +0200304 default:
305 DEBUG_MESSAGES(dev_err
306 (pod->
307 line6.ifcdev,
308 "unknown tuner/system response %02X\n",
309 buf[6]));
310 }
Markus Grabner705ecec2009-02-27 19:43:04 -0800311
Markus Grabnere1a164d2010-08-23 01:08:25 +0200312 break;
313 }
Markus Grabner705ecec2009-02-27 19:43:04 -0800314
315 case POD_SYSEX_FINISH:
316 /* do we need to respond to this? */
317 break;
318
319 case POD_SYSEX_SAVE:
320 pod_save_button_pressed(pod, buf[6], buf[7]);
321 break;
322
323 case POD_SYSEX_CLIP:
Markus Grabnere1a164d2010-08-23 01:08:25 +0200324 DEBUG_MESSAGES(dev_err
325 (pod->line6.ifcdev,
326 "audio clipped\n"));
Markus Grabner705ecec2009-02-27 19:43:04 -0800327 pod->clipping.value = 1;
Markus Grabner1027f4762010-08-12 01:35:30 +0200328 wake_up(&pod->clipping.wait);
Markus Grabner705ecec2009-02-27 19:43:04 -0800329 break;
330
331 case POD_SYSEX_STORE:
Markus Grabnere1a164d2010-08-23 01:08:25 +0200332 DEBUG_MESSAGES(dev_err
333 (pod->line6.ifcdev,
334 "message %02X not yet implemented\n",
335 buf[5]));
Markus Grabner705ecec2009-02-27 19:43:04 -0800336 break;
337
338 default:
Markus Grabnere1a164d2010-08-23 01:08:25 +0200339 DEBUG_MESSAGES(dev_err
340 (pod->line6.ifcdev,
341 "unknown sysex message %02X\n",
342 buf[5]));
Markus Grabner705ecec2009-02-27 19:43:04 -0800343 }
Markus Grabnere1a164d2010-08-23 01:08:25 +0200344 } else
345 if (memcmp
346 (buf, pod_version_header,
347 sizeof(pod_version_header)) == 0) {
348 pod->firmware_version =
349 buf[13] * 100 + buf[14] * 10 + buf[15];
350 pod->device_id =
351 ((int)buf[8] << 16) | ((int)buf[9] << 8) | (int)
352 buf[10];
Markus Grabner1027f4762010-08-12 01:35:30 +0200353 pod_startup4(pod);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800354 } else
Markus Grabnere1a164d2010-08-23 01:08:25 +0200355 DEBUG_MESSAGES(dev_err
356 (pod->line6.ifcdev,
357 "unknown sysex header\n"));
Markus Grabner705ecec2009-02-27 19:43:04 -0800358
359 break;
360
361 case LINE6_SYSEX_END:
362 break;
363
364 default:
Markus Grabnere1a164d2010-08-23 01:08:25 +0200365 DEBUG_MESSAGES(dev_err
366 (pod->line6.ifcdev,
367 "POD: unknown message %02X\n", buf[0]));
Markus Grabner705ecec2009-02-27 19:43:04 -0800368 }
369}
370
371/*
372 Detect some cases that require a channel dump after sending a command to the
373 device. Important notes:
374 *) The actual dump request can not be sent here since we are not allowed to
375 wait for the completion of the first message in this context, and sending
376 the dump request before completion of the previous message leaves the POD
377 in an undefined state. The dump request will be sent when the echoed
378 commands are received.
379 *) This method fails if a param change message is "chopped" after the first
380 byte.
381*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200382void line6_pod_midi_postprocess(struct usb_line6_pod *pod, unsigned char *data,
383 int length)
Markus Grabner705ecec2009-02-27 19:43:04 -0800384{
385 int i;
386
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800387 if (!pod->midi_postprocess)
Markus Grabner705ecec2009-02-27 19:43:04 -0800388 return;
389
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800390 for (i = 0; i < length; ++i) {
391 if (data[i] == (LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST)) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800392 line6_invalidate_current(&pod->dumpreq);
393 break;
Markus Grabnere1a164d2010-08-23 01:08:25 +0200394 } else
395 if ((data[i] == (LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST))
396 && (i < length - 1))
397 if ((data[i + 1] == POD_amp_model_setup)
398 || (data[i + 1] == POD_effect_setup)) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800399 line6_invalidate_current(&pod->dumpreq);
400 break;
401 }
402 }
403}
404
405/*
406 Send channel number (i.e., switch to a different sound).
407*/
Greg Kroah-Hartmanb702ed252009-02-27 20:45:03 -0800408static void pod_send_channel(struct usb_line6_pod *pod, int value)
Markus Grabner705ecec2009-02-27 19:43:04 -0800409{
410 line6_invalidate_current(&pod->dumpreq);
411
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800412 if (line6_send_program(&pod->line6, value) == 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800413 pod->channel_num = value;
414 else
415 line6_dump_finished(&pod->dumpreq);
416}
417
418/*
419 Transmit PODxt Pro control parameter.
420*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200421void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param,
422 int value)
Markus Grabner705ecec2009-02-27 19:43:04 -0800423{
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800424 if (line6_transmit_parameter(&pod->line6, param, value) == 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800425 pod_store_parameter(pod, param, value);
426
Markus Grabnere1a164d2010-08-23 01:08:25 +0200427 if ((param == POD_amp_model_setup) || (param == POD_effect_setup)) /* these also affect other settings */
Markus Grabner705ecec2009-02-27 19:43:04 -0800428 line6_invalidate_current(&pod->dumpreq);
429}
430
431/*
432 Resolve value to memory location.
433*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200434static int pod_resolve(const char *buf, short block0, short block1,
435 unsigned char *location)
Markus Grabner705ecec2009-02-27 19:43:04 -0800436{
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600437 unsigned long value;
438 short block;
439 int ret;
440
441 ret = strict_strtoul(buf, 10, &value);
442 if (ret)
443 return ret;
444
445 block = (value < 0x40) ? block0 : block1;
Markus Grabner705ecec2009-02-27 19:43:04 -0800446 value &= 0x3f;
447 location[0] = block >> 7;
448 location[1] = value | (block & 0x7f);
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600449 return 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800450}
451
452/*
453 Send command to store channel/effects setup/amp setup to PODxt Pro.
454*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200455static ssize_t pod_send_store_command(struct device *dev, const char *buf,
456 size_t count, short block0, short block1)
Markus Grabner705ecec2009-02-27 19:43:04 -0800457{
458 struct usb_interface *interface = to_usb_interface(dev);
459 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600460 int ret;
Markus Grabner705ecec2009-02-27 19:43:04 -0800461 int size = 3 + sizeof(pod->prog_data_buf);
462 char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_STORE, size);
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600463
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800464 if (!sysex)
465 return 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800466
Markus Grabnere1a164d2010-08-23 01:08:25 +0200467 sysex[SYSEX_DATA_OFS] = 5; /* see pod_dump() */
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600468 ret = pod_resolve(buf, block0, block1, sysex + SYSEX_DATA_OFS + 1);
469 if (ret) {
470 kfree(sysex);
471 return ret;
472 }
473
Markus Grabnere1a164d2010-08-23 01:08:25 +0200474 memcpy(sysex + SYSEX_DATA_OFS + 3, &pod->prog_data_buf,
475 sizeof(pod->prog_data_buf));
Markus Grabner705ecec2009-02-27 19:43:04 -0800476
477 line6_send_sysex_message(&pod->line6, sysex, size);
478 kfree(sysex);
479 /* needs some delay here on AMD64 platform */
480 return count;
481}
482
483/*
484 Send command to retrieve channel/effects setup/amp setup to PODxt Pro.
485*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200486static ssize_t pod_send_retrieve_command(struct device *dev, const char *buf,
487 size_t count, short block0,
488 short block1)
Markus Grabner705ecec2009-02-27 19:43:04 -0800489{
490 struct usb_interface *interface = to_usb_interface(dev);
491 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600492 int ret;
Markus Grabner705ecec2009-02-27 19:43:04 -0800493 int size = 4;
494 char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_DUMPMEM, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800495
496 if (!sysex)
497 return 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800498
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600499 ret = pod_resolve(buf, block0, block1, sysex + SYSEX_DATA_OFS);
500 if (ret) {
501 kfree(sysex);
502 return ret;
503 }
Markus Grabner705ecec2009-02-27 19:43:04 -0800504 sysex[SYSEX_DATA_OFS + 2] = 0;
505 sysex[SYSEX_DATA_OFS + 3] = 0;
506 line6_dump_started(&pod->dumpreq, POD_DUMP_MEMORY);
507
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800508 if (line6_send_sysex_message(&pod->line6, sysex, size) < size)
Markus Grabner705ecec2009-02-27 19:43:04 -0800509 line6_dump_finished(&pod->dumpreq);
510
511 kfree(sysex);
512 /* needs some delay here on AMD64 platform */
513 return count;
514}
515
516/*
517 Generic get name function.
518*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200519static ssize_t get_name_generic(struct usb_line6_pod *pod, const char *str,
520 char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800521{
522 int length = 0;
523 const char *p1;
524 char *p2;
525 char *last_non_space = buf;
526
Markus Grabner1027f4762010-08-12 01:35:30 +0200527 int retval = line6_dump_wait_interruptible(&pod->dumpreq);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800528 if (retval < 0)
529 return retval;
Markus Grabner705ecec2009-02-27 19:43:04 -0800530
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800531 for (p1 = str, p2 = buf; *p1; ++p1, ++p2) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800532 *p2 = *p1;
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800533 if (*p2 != ' ')
534 last_non_space = p2;
535 if (++length == POD_NAME_LENGTH)
536 break;
Markus Grabner705ecec2009-02-27 19:43:04 -0800537 }
538
539 *(last_non_space + 1) = '\n';
540 return last_non_space - buf + 2;
541}
542
543/*
544 "read" request on "channel" special file.
545*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800546static ssize_t pod_get_channel(struct device *dev,
547 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800548{
549 struct usb_interface *interface = to_usb_interface(dev);
550 struct usb_line6_pod *pod = usb_get_intfdata(interface);
551 return sprintf(buf, "%d\n", pod->channel_num);
552}
553
554/*
555 "write" request on "channel" special file.
556*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800557static ssize_t pod_set_channel(struct device *dev,
558 struct device_attribute *attr,
559 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800560{
561 struct usb_interface *interface = to_usb_interface(dev);
562 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600563 unsigned long value;
564 int ret;
565
566 ret = strict_strtoul(buf, 10, &value);
567 if (ret)
568 return ret;
569
Markus Grabner705ecec2009-02-27 19:43:04 -0800570 pod_send_channel(pod, value);
571 return count;
572}
573
574/*
575 "read" request on "name" special file.
576*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800577static ssize_t pod_get_name(struct device *dev, struct device_attribute *attr,
578 char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800579{
580 struct usb_interface *interface = to_usb_interface(dev);
581 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Markus Grabnere1a164d2010-08-23 01:08:25 +0200582 return get_name_generic(pod, pod->prog_data.header + POD_NAME_OFFSET,
583 buf);
Markus Grabner705ecec2009-02-27 19:43:04 -0800584}
585
586/*
587 "read" request on "name" special file.
588*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800589static ssize_t pod_get_name_buf(struct device *dev,
590 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800591{
592 struct usb_interface *interface = to_usb_interface(dev);
593 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Markus Grabnere1a164d2010-08-23 01:08:25 +0200594 return get_name_generic(pod,
595 pod->prog_data_buf.header + POD_NAME_OFFSET,
596 buf);
Markus Grabner705ecec2009-02-27 19:43:04 -0800597}
598
599/*
600 "read" request on "dump" special file.
601*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800602static ssize_t pod_get_dump(struct device *dev, struct device_attribute *attr,
603 char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800604{
605 struct usb_interface *interface = to_usb_interface(dev);
606 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Markus Grabner1027f4762010-08-12 01:35:30 +0200607 int retval = line6_dump_wait_interruptible(&pod->dumpreq);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800608 if (retval < 0)
609 return retval;
Markus Grabner705ecec2009-02-27 19:43:04 -0800610 memcpy(buf, &pod->prog_data, sizeof(pod->prog_data));
611 return sizeof(pod->prog_data);
612}
613
614/*
615 "write" request on "dump" special file.
616*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800617static ssize_t pod_set_dump(struct device *dev, struct device_attribute *attr,
618 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800619{
620 struct usb_interface *interface = to_usb_interface(dev);
621 struct usb_line6_pod *pod = usb_get_intfdata(interface);
622
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800623 if (count != sizeof(pod->prog_data)) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800624 dev_err(pod->line6.ifcdev,
Markus Grabnere1a164d2010-08-23 01:08:25 +0200625 "data block must be exactly %d bytes\n",
626 (int)sizeof(pod->prog_data));
Markus Grabner705ecec2009-02-27 19:43:04 -0800627 return -EINVAL;
628 }
629
630 pod_dump(pod, buf);
631 return sizeof(pod->prog_data);
632}
633
634/*
Markus Grabner1027f4762010-08-12 01:35:30 +0200635 Identify system parameters related to the tuner.
636*/
637static bool pod_is_tuner(int code)
638{
639 return
Markus Grabnere1a164d2010-08-23 01:08:25 +0200640 (code == POD_tuner_mute) ||
641 (code == POD_tuner_freq) ||
642 (code == POD_tuner_note) || (code == POD_tuner_pitch);
Markus Grabner1027f4762010-08-12 01:35:30 +0200643}
644
645/*
646 Get system parameter (as integer).
Markus Grabner705ecec2009-02-27 19:43:04 -0800647 @param tuner non-zero, if code refers to a tuner parameter
648*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200649static int pod_get_system_param_int(struct usb_line6_pod *pod, int *value,
650 int code, struct ValueWait *param, int sign)
Markus Grabner705ecec2009-02-27 19:43:04 -0800651{
652 char *sysex;
Markus Grabner705ecec2009-02-27 19:43:04 -0800653 static const int size = 1;
654 int retval = 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800655
Markus Grabnere1a164d2010-08-23 01:08:25 +0200656 if (((pod->prog_data.control[POD_tuner] & 0x40) == 0)
657 && pod_is_tuner(code))
Markus Grabner705ecec2009-02-27 19:43:04 -0800658 return -ENODEV;
659
Markus Grabner1027f4762010-08-12 01:35:30 +0200660 /* send value request to device: */
Markus Grabner705ecec2009-02-27 19:43:04 -0800661 param->value = POD_system_invalid;
662 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEMREQ, size);
Markus Grabner1027f4762010-08-12 01:35:30 +0200663
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800664 if (!sysex)
Markus Grabner1027f4762010-08-12 01:35:30 +0200665 return -ENOMEM;
666
Markus Grabner705ecec2009-02-27 19:43:04 -0800667 sysex[SYSEX_DATA_OFS] = code;
668 line6_send_sysex_message(&pod->line6, sysex, size);
669 kfree(sysex);
670
Markus Grabner1027f4762010-08-12 01:35:30 +0200671 /* wait for device to respond: */
Markus Grabnere1a164d2010-08-23 01:08:25 +0200672 retval =
673 wait_event_interruptible(param->wait,
674 param->value != POD_system_invalid);
Markus Grabner705ecec2009-02-27 19:43:04 -0800675
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800676 if (retval < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800677 return retval;
678
Markus Grabnere1a164d2010-08-23 01:08:25 +0200679 *value = sign ? (int)(signed short)param->value : (int)(unsigned short)
680 param->value;
Markus Grabner1027f4762010-08-12 01:35:30 +0200681
Markus Grabnere1a164d2010-08-23 01:08:25 +0200682 if (*value == POD_system_invalid)
683 *value = 0; /* don't report uninitialized values */
Markus Grabner1027f4762010-08-12 01:35:30 +0200684
685 return 0;
686}
687
688/*
689 Get system parameter (as string).
690 @param tuner non-zero, if code refers to a tuner parameter
691*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200692static ssize_t pod_get_system_param_string(struct usb_line6_pod *pod, char *buf,
693 int code, struct ValueWait *param,
694 int sign)
Markus Grabner1027f4762010-08-12 01:35:30 +0200695{
696 int retval, value = 0;
697 retval = pod_get_system_param_int(pod, &value, code, param, sign);
698
Markus Grabnere1a164d2010-08-23 01:08:25 +0200699 if (retval < 0)
Markus Grabner1027f4762010-08-12 01:35:30 +0200700 return retval;
701
Markus Grabner705ecec2009-02-27 19:43:04 -0800702 return sprintf(buf, "%d\n", value);
703}
704
705/*
Markus Grabner1027f4762010-08-12 01:35:30 +0200706 Send system parameter (from integer).
Markus Grabner705ecec2009-02-27 19:43:04 -0800707 @param tuner non-zero, if code refers to a tuner parameter
708*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200709static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
710 int code)
Markus Grabner705ecec2009-02-27 19:43:04 -0800711{
712 char *sysex;
713 static const int size = 5;
Markus Grabner705ecec2009-02-27 19:43:04 -0800714
Markus Grabnere1a164d2010-08-23 01:08:25 +0200715 if (((pod->prog_data.control[POD_tuner] & 0x40) == 0)
716 && pod_is_tuner(code))
Markus Grabner705ecec2009-02-27 19:43:04 -0800717 return -EINVAL;
718
719 /* send value to tuner: */
720 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800721 if (!sysex)
Markus Grabner1027f4762010-08-12 01:35:30 +0200722 return -ENOMEM;
Markus Grabner705ecec2009-02-27 19:43:04 -0800723 sysex[SYSEX_DATA_OFS] = code;
724 sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
Markus Grabnere1a164d2010-08-23 01:08:25 +0200725 sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
726 sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
727 sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f;
Markus Grabner705ecec2009-02-27 19:43:04 -0800728 line6_send_sysex_message(&pod->line6, sysex, size);
729 kfree(sysex);
Markus Grabner1027f4762010-08-12 01:35:30 +0200730 return 0;
731}
732
733/*
734 Send system parameter (from string).
735 @param tuner non-zero, if code refers to a tuner parameter
736*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200737static ssize_t pod_set_system_param_string(struct usb_line6_pod *pod,
738 const char *buf, int count, int code,
739 unsigned short mask)
Markus Grabner1027f4762010-08-12 01:35:30 +0200740{
741 int retval;
742 unsigned short value = simple_strtoul(buf, NULL, 10) & mask;
743 retval = pod_set_system_param_int(pod, value, code);
744 return (retval < 0) ? retval : count;
Markus Grabner705ecec2009-02-27 19:43:04 -0800745}
746
747/*
748 "read" request on "dump_buf" special file.
749*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800750static ssize_t pod_get_dump_buf(struct device *dev,
751 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800752{
753 struct usb_interface *interface = to_usb_interface(dev);
754 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Markus Grabner1027f4762010-08-12 01:35:30 +0200755 int retval = line6_dump_wait_interruptible(&pod->dumpreq);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800756 if (retval < 0)
757 return retval;
Markus Grabner705ecec2009-02-27 19:43:04 -0800758 memcpy(buf, &pod->prog_data_buf, sizeof(pod->prog_data_buf));
759 return sizeof(pod->prog_data_buf);
760}
761
762/*
763 "write" request on "dump_buf" special file.
764*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800765static ssize_t pod_set_dump_buf(struct device *dev,
766 struct device_attribute *attr,
767 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800768{
769 struct usb_interface *interface = to_usb_interface(dev);
770 struct usb_line6_pod *pod = usb_get_intfdata(interface);
771
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800772 if (count != sizeof(pod->prog_data)) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800773 dev_err(pod->line6.ifcdev,
Markus Grabner1027f4762010-08-12 01:35:30 +0200774 "data block must be exactly %d bytes\n",
775 (int)sizeof(pod->prog_data));
Markus Grabner705ecec2009-02-27 19:43:04 -0800776 return -EINVAL;
777 }
778
779 memcpy(&pod->prog_data_buf, buf, sizeof(pod->prog_data));
780 return sizeof(pod->prog_data);
781}
782
783/*
784 "write" request on "finish" special file.
785*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800786static ssize_t pod_set_finish(struct device *dev,
787 struct device_attribute *attr,
788 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800789{
790 struct usb_interface *interface = to_usb_interface(dev);
791 struct usb_line6_pod *pod = usb_get_intfdata(interface);
792 int size = 0;
793 char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_FINISH, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800794 if (!sysex)
795 return 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800796 line6_send_sysex_message(&pod->line6, sysex, size);
797 kfree(sysex);
798 return count;
799}
800
801/*
802 "write" request on "store_channel" special file.
803*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800804static ssize_t pod_set_store_channel(struct device *dev,
805 struct device_attribute *attr,
806 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800807{
808 return pod_send_store_command(dev, buf, count, 0x0000, 0x00c0);
809}
810
811/*
812 "write" request on "store_effects_setup" special file.
813*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800814static ssize_t pod_set_store_effects_setup(struct device *dev,
815 struct device_attribute *attr,
816 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800817{
818 return pod_send_store_command(dev, buf, count, 0x0080, 0x0080);
819}
820
821/*
822 "write" request on "store_amp_setup" special file.
823*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800824static ssize_t pod_set_store_amp_setup(struct device *dev,
825 struct device_attribute *attr,
826 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800827{
828 return pod_send_store_command(dev, buf, count, 0x0040, 0x0100);
829}
830
831/*
832 "write" request on "retrieve_channel" special file.
833*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800834static ssize_t pod_set_retrieve_channel(struct device *dev,
835 struct device_attribute *attr,
836 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800837{
838 return pod_send_retrieve_command(dev, buf, count, 0x0000, 0x00c0);
839}
840
841/*
842 "write" request on "retrieve_effects_setup" special file.
843*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800844static ssize_t pod_set_retrieve_effects_setup(struct device *dev,
845 struct device_attribute *attr,
846 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800847{
848 return pod_send_retrieve_command(dev, buf, count, 0x0080, 0x0080);
849}
850
851/*
852 "write" request on "retrieve_amp_setup" special file.
853*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800854static ssize_t pod_set_retrieve_amp_setup(struct device *dev,
855 struct device_attribute *attr,
856 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800857{
858 return pod_send_retrieve_command(dev, buf, count, 0x0040, 0x0100);
859}
860
861/*
862 "read" request on "dirty" special file.
863*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800864static ssize_t pod_get_dirty(struct device *dev, struct device_attribute *attr,
865 char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800866{
867 struct usb_interface *interface = to_usb_interface(dev);
868 struct usb_line6_pod *pod = usb_get_intfdata(interface);
869 buf[0] = pod->dirty ? '1' : '0';
870 buf[1] = '\n';
871 return 2;
872}
873
874/*
875 "read" request on "midi_postprocess" special file.
876*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800877static ssize_t pod_get_midi_postprocess(struct device *dev,
878 struct device_attribute *attr,
879 char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800880{
881 struct usb_interface *interface = to_usb_interface(dev);
882 struct usb_line6_pod *pod = usb_get_intfdata(interface);
883 return sprintf(buf, "%d\n", pod->midi_postprocess);
884}
885
886/*
887 "write" request on "midi_postprocess" special file.
888*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800889static ssize_t pod_set_midi_postprocess(struct device *dev,
890 struct device_attribute *attr,
891 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800892{
893 struct usb_interface *interface = to_usb_interface(dev);
894 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600895 unsigned long value;
896 int ret;
897
898 ret = strict_strtoul(buf, 10, &value);
899 if (ret)
900 return ret;
901
Markus Grabner705ecec2009-02-27 19:43:04 -0800902 pod->midi_postprocess = value ? 1 : 0;
903 return count;
904}
905
906/*
907 "read" request on "serial_number" special file.
908*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800909static ssize_t pod_get_serial_number(struct device *dev,
910 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800911{
912 struct usb_interface *interface = to_usb_interface(dev);
913 struct usb_line6_pod *pod = usb_get_intfdata(interface);
914 return sprintf(buf, "%d\n", pod->serial_number);
915}
916
917/*
918 "read" request on "firmware_version" special file.
919*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800920static ssize_t pod_get_firmware_version(struct device *dev,
921 struct device_attribute *attr,
922 char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800923{
924 struct usb_interface *interface = to_usb_interface(dev);
925 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800926 return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
927 pod->firmware_version % 100);
Markus Grabner705ecec2009-02-27 19:43:04 -0800928}
929
930/*
931 "read" request on "device_id" special file.
932*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800933static ssize_t pod_get_device_id(struct device *dev,
934 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800935{
936 struct usb_interface *interface = to_usb_interface(dev);
937 struct usb_line6_pod *pod = usb_get_intfdata(interface);
938 return sprintf(buf, "%d\n", pod->device_id);
939}
940
941/*
942 "read" request on "clip" special file.
943*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800944static ssize_t pod_wait_for_clip(struct device *dev,
945 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800946{
947 struct usb_interface *interface = to_usb_interface(dev);
948 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Markus Grabnere1a164d2010-08-23 01:08:25 +0200949 return wait_event_interruptible(pod->clipping.wait,
950 pod->clipping.value != 0);
Markus Grabner705ecec2009-02-27 19:43:04 -0800951}
952
Markus Grabner1027f4762010-08-12 01:35:30 +0200953/*
954 POD startup procedure.
955 This is a sequence of functions with special requirements (e.g., must
956 not run immediately after initialization, must not run in interrupt
957 context). After the last one has finished, the device is ready to use.
958*/
959
960static void pod_startup1(struct usb_line6_pod *pod)
961{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200962 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
Markus Grabner1027f4762010-08-12 01:35:30 +0200963
964 /* delay startup procedure: */
Markus Grabnere1a164d2010-08-23 01:08:25 +0200965 line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
966 (unsigned long)pod);
Markus Grabner1027f4762010-08-12 01:35:30 +0200967}
968
969static void pod_startup2(unsigned long data)
970{
971 struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
Markus Grabnere1a164d2010-08-23 01:08:25 +0200972
973 /* schedule another startup procedure until startup is complete: */
974 if (pod->startup_progress >= POD_STARTUP_LAST)
975 return;
976
977 pod->startup_progress = POD_STARTUP_DUMPREQ;
978 line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
979 (unsigned long)pod);
Markus Grabner1027f4762010-08-12 01:35:30 +0200980
981 /* current channel dump: */
Markus Grabnere1a164d2010-08-23 01:08:25 +0200982 line6_dump_request_async(&pod->dumpreq, &pod->line6, 0,
983 LINE6_DUMP_CURRENT);
Markus Grabner1027f4762010-08-12 01:35:30 +0200984}
985
986static void pod_startup3(struct usb_line6_pod *pod)
987{
988 struct usb_line6 *line6 = &pod->line6;
Markus Grabnere1a164d2010-08-23 01:08:25 +0200989 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
Markus Grabner1027f4762010-08-12 01:35:30 +0200990
991 /* request firmware version: */
992 line6_version_request_async(line6);
993}
994
995static void pod_startup4(struct usb_line6_pod *pod)
996{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200997 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
Markus Grabner1027f4762010-08-12 01:35:30 +0200998
999 /* schedule work for global work queue: */
1000 schedule_work(&pod->startup_work);
1001}
1002
1003static void pod_startup5(struct work_struct *work)
1004{
Markus Grabnere1a164d2010-08-23 01:08:25 +02001005 struct usb_line6_pod *pod =
1006 container_of(work, struct usb_line6_pod, startup_work);
Markus Grabner1027f4762010-08-12 01:35:30 +02001007 struct usb_line6 *line6 = &pod->line6;
1008
Markus Grabnere1a164d2010-08-23 01:08:25 +02001009 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
Markus Grabner1027f4762010-08-12 01:35:30 +02001010
1011 /* serial number: */
1012 line6_read_serial_number(&pod->line6, &pod->serial_number);
1013
1014 /* ALSA audio interface: */
1015 line6_register_audio(line6);
1016
1017 /* device files: */
Markus Grabnere1a164d2010-08-23 01:08:25 +02001018 line6_pod_create_files(pod->firmware_version,
1019 line6->properties->device_bit, line6->ifcdev);
Markus Grabner1027f4762010-08-12 01:35:30 +02001020}
1021
1022#define POD_GET_SYSTEM_PARAM(code, sign) \
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -08001023static ssize_t pod_get_ ## code(struct device *dev, \
1024 struct device_attribute *attr, char *buf) \
Markus Grabner705ecec2009-02-27 19:43:04 -08001025{ \
1026 struct usb_interface *interface = to_usb_interface(dev); \
1027 struct usb_line6_pod *pod = usb_get_intfdata(interface); \
Markus Grabner1027f4762010-08-12 01:35:30 +02001028 return pod_get_system_param_string(pod, buf, POD_ ## code, \
1029 &pod->code, sign); \
Markus Grabner705ecec2009-02-27 19:43:04 -08001030}
1031
Markus Grabner1027f4762010-08-12 01:35:30 +02001032#define POD_GET_SET_SYSTEM_PARAM(code, mask, sign) \
1033POD_GET_SYSTEM_PARAM(code, sign) \
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -08001034static ssize_t pod_set_ ## code(struct device *dev, \
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001035 struct device_attribute *attr, \
1036 const char *buf, size_t count) \
Markus Grabner705ecec2009-02-27 19:43:04 -08001037{ \
1038 struct usb_interface *interface = to_usb_interface(dev); \
1039 struct usb_line6_pod *pod = usb_get_intfdata(interface); \
Markus Grabner1027f4762010-08-12 01:35:30 +02001040 return pod_set_system_param_string(pod, buf, count, POD_ ## code, mask); \
Markus Grabner705ecec2009-02-27 19:43:04 -08001041}
1042
Markus Grabner1027f4762010-08-12 01:35:30 +02001043POD_GET_SET_SYSTEM_PARAM(monitor_level, 0xffff, 0);
1044POD_GET_SET_SYSTEM_PARAM(routing, 0x0003, 0);
1045POD_GET_SET_SYSTEM_PARAM(tuner_mute, 0x0001, 0);
1046POD_GET_SET_SYSTEM_PARAM(tuner_freq, 0xffff, 0);
1047POD_GET_SYSTEM_PARAM(tuner_note, 1);
1048POD_GET_SYSTEM_PARAM(tuner_pitch, 1);
Markus Grabner705ecec2009-02-27 19:43:04 -08001049
1050#undef GET_SET_SYSTEM_PARAM
1051#undef GET_SYSTEM_PARAM
1052
1053/* POD special files: */
Markus Grabnere1a164d2010-08-23 01:08:25 +02001054static DEVICE_ATTR(channel, S_IWUGO | S_IRUGO, pod_get_channel,
1055 pod_set_channel);
Markus Grabner705ecec2009-02-27 19:43:04 -08001056static DEVICE_ATTR(clip, S_IRUGO, pod_wait_for_clip, line6_nop_write);
1057static DEVICE_ATTR(device_id, S_IRUGO, pod_get_device_id, line6_nop_write);
1058static DEVICE_ATTR(dirty, S_IRUGO, pod_get_dirty, line6_nop_write);
1059static DEVICE_ATTR(dump, S_IWUGO | S_IRUGO, pod_get_dump, pod_set_dump);
Markus Grabnere1a164d2010-08-23 01:08:25 +02001060static DEVICE_ATTR(dump_buf, S_IWUGO | S_IRUGO, pod_get_dump_buf,
1061 pod_set_dump_buf);
Markus Grabner705ecec2009-02-27 19:43:04 -08001062static DEVICE_ATTR(finish, S_IWUGO, line6_nop_read, pod_set_finish);
Markus Grabnere1a164d2010-08-23 01:08:25 +02001063static DEVICE_ATTR(firmware_version, S_IRUGO, pod_get_firmware_version,
1064 line6_nop_write);
1065static DEVICE_ATTR(midi_postprocess, S_IWUGO | S_IRUGO,
1066 pod_get_midi_postprocess, pod_set_midi_postprocess);
1067static DEVICE_ATTR(monitor_level, S_IWUGO | S_IRUGO, pod_get_monitor_level,
1068 pod_set_monitor_level);
Markus Grabner705ecec2009-02-27 19:43:04 -08001069static DEVICE_ATTR(name, S_IRUGO, pod_get_name, line6_nop_write);
1070static DEVICE_ATTR(name_buf, S_IRUGO, pod_get_name_buf, line6_nop_write);
Markus Grabnere1a164d2010-08-23 01:08:25 +02001071static DEVICE_ATTR(retrieve_amp_setup, S_IWUGO, line6_nop_read,
1072 pod_set_retrieve_amp_setup);
1073static DEVICE_ATTR(retrieve_channel, S_IWUGO, line6_nop_read,
1074 pod_set_retrieve_channel);
1075static DEVICE_ATTR(retrieve_effects_setup, S_IWUGO, line6_nop_read,
1076 pod_set_retrieve_effects_setup);
1077static DEVICE_ATTR(routing, S_IWUGO | S_IRUGO, pod_get_routing,
1078 pod_set_routing);
1079static DEVICE_ATTR(serial_number, S_IRUGO, pod_get_serial_number,
1080 line6_nop_write);
1081static DEVICE_ATTR(store_amp_setup, S_IWUGO, line6_nop_read,
1082 pod_set_store_amp_setup);
1083static DEVICE_ATTR(store_channel, S_IWUGO, line6_nop_read,
1084 pod_set_store_channel);
1085static DEVICE_ATTR(store_effects_setup, S_IWUGO, line6_nop_read,
1086 pod_set_store_effects_setup);
1087static DEVICE_ATTR(tuner_freq, S_IWUGO | S_IRUGO, pod_get_tuner_freq,
1088 pod_set_tuner_freq);
1089static DEVICE_ATTR(tuner_mute, S_IWUGO | S_IRUGO, pod_get_tuner_mute,
1090 pod_set_tuner_mute);
Markus Grabner705ecec2009-02-27 19:43:04 -08001091static DEVICE_ATTR(tuner_note, S_IRUGO, pod_get_tuner_note, line6_nop_write);
1092static DEVICE_ATTR(tuner_pitch, S_IRUGO, pod_get_tuner_pitch, line6_nop_write);
1093
Markus Grabner1027f4762010-08-12 01:35:30 +02001094#ifdef CONFIG_LINE6_USB_RAW
Markus Grabner705ecec2009-02-27 19:43:04 -08001095static DEVICE_ATTR(raw, S_IWUGO, line6_nop_read, line6_set_raw);
1096#endif
1097
Markus Grabner1027f4762010-08-12 01:35:30 +02001098/* control info callback */
1099static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
1100 struct snd_ctl_elem_info *uinfo)
1101{
1102 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1103 uinfo->count = 1;
1104 uinfo->value.integer.min = 0;
1105 uinfo->value.integer.max = 65535;
1106 return 0;
1107}
1108
1109/* control get callback */
1110static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
1111 struct snd_ctl_elem_value *ucontrol)
1112{
1113 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
1114 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
1115 ucontrol->value.integer.value[0] = pod->monitor_level.value;
1116 return 0;
1117}
1118
1119/* control put callback */
1120static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
1121 struct snd_ctl_elem_value *ucontrol)
1122{
1123 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
1124 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
1125
Markus Grabnere1a164d2010-08-23 01:08:25 +02001126 if (ucontrol->value.integer.value[0] == pod->monitor_level.value)
Markus Grabner1027f4762010-08-12 01:35:30 +02001127 return 0;
1128
1129 pod->monitor_level.value = ucontrol->value.integer.value[0];
Markus Grabnere1a164d2010-08-23 01:08:25 +02001130 pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
1131 POD_monitor_level);
Markus Grabner1027f4762010-08-12 01:35:30 +02001132 return 1;
1133}
1134
1135/* control definition */
1136static struct snd_kcontrol_new pod_control_monitor = {
1137 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1138 .name = "Monitor Playback Volume",
1139 .index = 0,
1140 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1141 .info = snd_pod_control_monitor_info,
1142 .get = snd_pod_control_monitor_get,
1143 .put = snd_pod_control_monitor_put
1144};
1145
Markus Grabner705ecec2009-02-27 19:43:04 -08001146/*
1147 POD destructor.
1148*/
1149static void pod_destruct(struct usb_interface *interface)
1150{
1151 struct usb_line6_pod *pod = usb_get_intfdata(interface);
1152 struct usb_line6 *line6;
1153
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001154 if (pod == NULL)
1155 return;
Markus Grabner705ecec2009-02-27 19:43:04 -08001156 line6 = &pod->line6;
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001157 if (line6 == NULL)
1158 return;
Markus Grabner705ecec2009-02-27 19:43:04 -08001159 line6_cleanup_audio(line6);
1160
Markus Grabnere1a164d2010-08-23 01:08:25 +02001161 del_timer(&pod->startup_timer);
1162 cancel_work_sync(&pod->startup_work);
1163
Markus Grabner705ecec2009-02-27 19:43:04 -08001164 /* free dump request data: */
1165 line6_dumpreq_destruct(&pod->dumpreq);
Markus Grabner705ecec2009-02-27 19:43:04 -08001166}
1167
1168/*
1169 Create sysfs entries.
1170*/
Greg Kroah-Hartmanb702ed252009-02-27 20:45:03 -08001171static int pod_create_files2(struct device *dev)
Markus Grabner705ecec2009-02-27 19:43:04 -08001172{
1173 int err;
1174
1175 CHECK_RETURN(device_create_file(dev, &dev_attr_channel));
1176 CHECK_RETURN(device_create_file(dev, &dev_attr_clip));
1177 CHECK_RETURN(device_create_file(dev, &dev_attr_device_id));
1178 CHECK_RETURN(device_create_file(dev, &dev_attr_dirty));
1179 CHECK_RETURN(device_create_file(dev, &dev_attr_dump));
1180 CHECK_RETURN(device_create_file(dev, &dev_attr_dump_buf));
1181 CHECK_RETURN(device_create_file(dev, &dev_attr_finish));
1182 CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version));
1183 CHECK_RETURN(device_create_file(dev, &dev_attr_midi_postprocess));
1184 CHECK_RETURN(device_create_file(dev, &dev_attr_monitor_level));
1185 CHECK_RETURN(device_create_file(dev, &dev_attr_name));
1186 CHECK_RETURN(device_create_file(dev, &dev_attr_name_buf));
1187 CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_amp_setup));
1188 CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_channel));
1189 CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_effects_setup));
1190 CHECK_RETURN(device_create_file(dev, &dev_attr_routing));
1191 CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number));
1192 CHECK_RETURN(device_create_file(dev, &dev_attr_store_amp_setup));
1193 CHECK_RETURN(device_create_file(dev, &dev_attr_store_channel));
1194 CHECK_RETURN(device_create_file(dev, &dev_attr_store_effects_setup));
1195 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_freq));
1196 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_mute));
1197 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_note));
1198 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_pitch));
1199
Markus Grabner1027f4762010-08-12 01:35:30 +02001200#ifdef CONFIG_LINE6_USB_RAW
Markus Grabner705ecec2009-02-27 19:43:04 -08001201 CHECK_RETURN(device_create_file(dev, &dev_attr_raw));
1202#endif
1203
1204 return 0;
1205}
1206
1207/*
Markus Grabner1027f4762010-08-12 01:35:30 +02001208 Try to init POD device.
Markus Grabner705ecec2009-02-27 19:43:04 -08001209*/
Markus Grabnere1a164d2010-08-23 01:08:25 +02001210static int pod_try_init(struct usb_interface *interface,
1211 struct usb_line6_pod *pod)
Markus Grabner705ecec2009-02-27 19:43:04 -08001212{
1213 int err;
1214 struct usb_line6 *line6 = &pod->line6;
1215
Markus Grabnere1a164d2010-08-23 01:08:25 +02001216 init_timer(&pod->startup_timer);
1217 INIT_WORK(&pod->startup_work, pod_startup5);
1218
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001219 if ((interface == NULL) || (pod == NULL))
1220 return -ENODEV;
Markus Grabner705ecec2009-02-27 19:43:04 -08001221
1222 pod->channel_num = 255;
1223
1224 /* initialize wait queues: */
1225 init_waitqueue_head(&pod->monitor_level.wait);
1226 init_waitqueue_head(&pod->routing.wait);
1227 init_waitqueue_head(&pod->tuner_mute.wait);
1228 init_waitqueue_head(&pod->tuner_freq.wait);
1229 init_waitqueue_head(&pod->tuner_note.wait);
1230 init_waitqueue_head(&pod->tuner_pitch.wait);
1231 init_waitqueue_head(&pod->clipping.wait);
1232
1233 memset(pod->param_dirty, 0xff, sizeof(pod->param_dirty));
1234
1235 /* initialize USB buffers: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001236 err = line6_dumpreq_init(&pod->dumpreq, pod_request_channel,
1237 sizeof(pod_request_channel));
1238 if (err < 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001239 dev_err(&interface->dev, "Out of memory\n");
Markus Grabner705ecec2009-02-27 19:43:04 -08001240 return -ENOMEM;
1241 }
1242
Markus Grabner705ecec2009-02-27 19:43:04 -08001243 /* create sysfs entries: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001244 err = pod_create_files2(&interface->dev);
1245 if (err < 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001246 return err;
1247 }
1248
1249 /* initialize audio system: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001250 err = line6_init_audio(line6);
1251 if (err < 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001252 return err;
1253 }
1254
1255 /* initialize MIDI subsystem: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001256 err = line6_init_midi(line6);
1257 if (err < 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001258 return err;
1259 }
1260
1261 /* initialize PCM subsystem: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001262 err = line6_init_pcm(line6, &pod_pcm_properties);
1263 if (err < 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001264 return err;
1265 }
1266
Markus Grabner1027f4762010-08-12 01:35:30 +02001267 /* register monitor control: */
Markus Grabnere1a164d2010-08-23 01:08:25 +02001268 err =
1269 snd_ctl_add(line6->card,
1270 snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001271 if (err < 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001272 return err;
1273 }
1274
Markus Grabner1027f4762010-08-12 01:35:30 +02001275 /*
Markus Grabnere1a164d2010-08-23 01:08:25 +02001276 When the sound card is registered at this point, the PODxt Live
1277 displays "Invalid Code Error 07", so we do it later in the event
1278 handler.
1279 */
Markus Grabner1027f4762010-08-12 01:35:30 +02001280
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001281 if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) {
Markus Grabner1027f4762010-08-12 01:35:30 +02001282 pod->monitor_level.value = POD_system_invalid;
1283
1284 /* initiate startup procedure: */
1285 pod_startup1(pod);
Markus Grabner705ecec2009-02-27 19:43:04 -08001286 }
1287
1288 return 0;
1289}
1290
1291/*
Markus Grabner1027f4762010-08-12 01:35:30 +02001292 Init POD device (and clean up in case of failure).
1293*/
1294int line6_pod_init(struct usb_interface *interface, struct usb_line6_pod *pod)
1295{
1296 int err = pod_try_init(interface, pod);
1297
1298 if (err < 0) {
1299 pod_destruct(interface);
1300 }
1301
1302 return err;
1303}
1304
1305/*
Markus Grabner705ecec2009-02-27 19:43:04 -08001306 POD device disconnected.
1307*/
Markus Grabner1027f4762010-08-12 01:35:30 +02001308void line6_pod_disconnect(struct usb_interface *interface)
Markus Grabner705ecec2009-02-27 19:43:04 -08001309{
1310 struct usb_line6_pod *pod;
1311
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001312 if (interface == NULL)
1313 return;
Markus Grabner705ecec2009-02-27 19:43:04 -08001314 pod = usb_get_intfdata(interface);
1315
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001316 if (pod != NULL) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001317 struct snd_line6_pcm *line6pcm = pod->line6.line6pcm;
1318 struct device *dev = &interface->dev;
1319
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001320 if (line6pcm != NULL) {
Markus Grabner1027f4762010-08-12 01:35:30 +02001321 line6_pcm_disconnect(line6pcm);
Markus Grabner705ecec2009-02-27 19:43:04 -08001322 }
1323
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001324 if (dev != NULL) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001325 /* remove sysfs entries: */
Markus Grabnere1a164d2010-08-23 01:08:25 +02001326 line6_pod_remove_files(pod->firmware_version,
1327 pod->line6.
1328 properties->device_bit, dev);
Markus Grabner705ecec2009-02-27 19:43:04 -08001329
1330 device_remove_file(dev, &dev_attr_channel);
1331 device_remove_file(dev, &dev_attr_clip);
1332 device_remove_file(dev, &dev_attr_device_id);
1333 device_remove_file(dev, &dev_attr_dirty);
1334 device_remove_file(dev, &dev_attr_dump);
1335 device_remove_file(dev, &dev_attr_dump_buf);
1336 device_remove_file(dev, &dev_attr_finish);
1337 device_remove_file(dev, &dev_attr_firmware_version);
1338 device_remove_file(dev, &dev_attr_midi_postprocess);
1339 device_remove_file(dev, &dev_attr_monitor_level);
1340 device_remove_file(dev, &dev_attr_name);
1341 device_remove_file(dev, &dev_attr_name_buf);
1342 device_remove_file(dev, &dev_attr_retrieve_amp_setup);
1343 device_remove_file(dev, &dev_attr_retrieve_channel);
Markus Grabnere1a164d2010-08-23 01:08:25 +02001344 device_remove_file(dev,
1345 &dev_attr_retrieve_effects_setup);
Markus Grabner705ecec2009-02-27 19:43:04 -08001346 device_remove_file(dev, &dev_attr_routing);
1347 device_remove_file(dev, &dev_attr_serial_number);
1348 device_remove_file(dev, &dev_attr_store_amp_setup);
1349 device_remove_file(dev, &dev_attr_store_channel);
1350 device_remove_file(dev, &dev_attr_store_effects_setup);
1351 device_remove_file(dev, &dev_attr_tuner_freq);
1352 device_remove_file(dev, &dev_attr_tuner_mute);
1353 device_remove_file(dev, &dev_attr_tuner_note);
1354 device_remove_file(dev, &dev_attr_tuner_pitch);
1355
Markus Grabner1027f4762010-08-12 01:35:30 +02001356#ifdef CONFIG_LINE6_USB_RAW
Markus Grabner705ecec2009-02-27 19:43:04 -08001357 device_remove_file(dev, &dev_attr_raw);
1358#endif
1359 }
1360 }
1361
1362 pod_destruct(interface);
1363}