blob: 8667aaf51459ff9b43c2b205540f7a3f693f5bf1 [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,
Johannes Thumshirn5b9bd2a2012-06-27 21:25:57 +0200422 u8 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: */
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001054static DEVICE_ATTR(channel, S_IWUSR | S_IRUGO, pod_get_channel,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001055 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);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001059static DEVICE_ATTR(dump, S_IWUSR | S_IRUGO, pod_get_dump, pod_set_dump);
1060static DEVICE_ATTR(dump_buf, S_IWUSR | S_IRUGO, pod_get_dump_buf,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001061 pod_set_dump_buf);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001062static DEVICE_ATTR(finish, S_IWUSR, 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);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001065static DEVICE_ATTR(midi_postprocess, S_IWUSR | S_IRUGO,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001066 pod_get_midi_postprocess, pod_set_midi_postprocess);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001067static DEVICE_ATTR(monitor_level, S_IWUSR | S_IRUGO, pod_get_monitor_level,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001068 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);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001071static DEVICE_ATTR(retrieve_amp_setup, S_IWUSR, line6_nop_read,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001072 pod_set_retrieve_amp_setup);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001073static DEVICE_ATTR(retrieve_channel, S_IWUSR, line6_nop_read,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001074 pod_set_retrieve_channel);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001075static DEVICE_ATTR(retrieve_effects_setup, S_IWUSR, line6_nop_read,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001076 pod_set_retrieve_effects_setup);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001077static DEVICE_ATTR(routing, S_IWUSR | S_IRUGO, pod_get_routing,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001078 pod_set_routing);
1079static DEVICE_ATTR(serial_number, S_IRUGO, pod_get_serial_number,
1080 line6_nop_write);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001081static DEVICE_ATTR(store_amp_setup, S_IWUSR, line6_nop_read,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001082 pod_set_store_amp_setup);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001083static DEVICE_ATTR(store_channel, S_IWUSR, line6_nop_read,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001084 pod_set_store_channel);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001085static DEVICE_ATTR(store_effects_setup, S_IWUSR, line6_nop_read,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001086 pod_set_store_effects_setup);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001087static DEVICE_ATTR(tuner_freq, S_IWUSR | S_IRUGO, pod_get_tuner_freq,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001088 pod_set_tuner_freq);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001089static DEVICE_ATTR(tuner_mute, S_IWUSR | S_IRUGO, pod_get_tuner_mute,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001090 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
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001095static DEVICE_ATTR(raw, S_IWUSR, line6_nop_read, line6_set_raw);
Markus Grabner705ecec2009-02-27 19:43:04 -08001096#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);
Markus Grabner705ecec2009-02-27 19:43:04 -08001152
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001153 if (pod == NULL)
1154 return;
Stefan Hajnoczi188e6642011-12-10 02:12:30 +01001155 line6_cleanup_audio(&pod->line6);
Markus Grabner705ecec2009-02-27 19:43:04 -08001156
Markus Grabnere1a164d2010-08-23 01:08:25 +02001157 del_timer(&pod->startup_timer);
1158 cancel_work_sync(&pod->startup_work);
1159
Markus Grabner705ecec2009-02-27 19:43:04 -08001160 /* free dump request data: */
1161 line6_dumpreq_destruct(&pod->dumpreq);
Markus Grabner705ecec2009-02-27 19:43:04 -08001162}
1163
1164/*
1165 Create sysfs entries.
1166*/
Greg Kroah-Hartmanb702ed252009-02-27 20:45:03 -08001167static int pod_create_files2(struct device *dev)
Markus Grabner705ecec2009-02-27 19:43:04 -08001168{
1169 int err;
1170
1171 CHECK_RETURN(device_create_file(dev, &dev_attr_channel));
1172 CHECK_RETURN(device_create_file(dev, &dev_attr_clip));
1173 CHECK_RETURN(device_create_file(dev, &dev_attr_device_id));
1174 CHECK_RETURN(device_create_file(dev, &dev_attr_dirty));
1175 CHECK_RETURN(device_create_file(dev, &dev_attr_dump));
1176 CHECK_RETURN(device_create_file(dev, &dev_attr_dump_buf));
1177 CHECK_RETURN(device_create_file(dev, &dev_attr_finish));
1178 CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version));
1179 CHECK_RETURN(device_create_file(dev, &dev_attr_midi_postprocess));
1180 CHECK_RETURN(device_create_file(dev, &dev_attr_monitor_level));
1181 CHECK_RETURN(device_create_file(dev, &dev_attr_name));
1182 CHECK_RETURN(device_create_file(dev, &dev_attr_name_buf));
1183 CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_amp_setup));
1184 CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_channel));
1185 CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_effects_setup));
1186 CHECK_RETURN(device_create_file(dev, &dev_attr_routing));
1187 CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number));
1188 CHECK_RETURN(device_create_file(dev, &dev_attr_store_amp_setup));
1189 CHECK_RETURN(device_create_file(dev, &dev_attr_store_channel));
1190 CHECK_RETURN(device_create_file(dev, &dev_attr_store_effects_setup));
1191 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_freq));
1192 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_mute));
1193 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_note));
1194 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_pitch));
1195
Markus Grabner1027f4762010-08-12 01:35:30 +02001196#ifdef CONFIG_LINE6_USB_RAW
Markus Grabner705ecec2009-02-27 19:43:04 -08001197 CHECK_RETURN(device_create_file(dev, &dev_attr_raw));
1198#endif
1199
1200 return 0;
1201}
1202
1203/*
Markus Grabner1027f4762010-08-12 01:35:30 +02001204 Try to init POD device.
Markus Grabner705ecec2009-02-27 19:43:04 -08001205*/
Markus Grabnere1a164d2010-08-23 01:08:25 +02001206static int pod_try_init(struct usb_interface *interface,
1207 struct usb_line6_pod *pod)
Markus Grabner705ecec2009-02-27 19:43:04 -08001208{
1209 int err;
1210 struct usb_line6 *line6 = &pod->line6;
1211
Markus Grabnere1a164d2010-08-23 01:08:25 +02001212 init_timer(&pod->startup_timer);
1213 INIT_WORK(&pod->startup_work, pod_startup5);
1214
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001215 if ((interface == NULL) || (pod == NULL))
1216 return -ENODEV;
Markus Grabner705ecec2009-02-27 19:43:04 -08001217
1218 pod->channel_num = 255;
1219
1220 /* initialize wait queues: */
1221 init_waitqueue_head(&pod->monitor_level.wait);
1222 init_waitqueue_head(&pod->routing.wait);
1223 init_waitqueue_head(&pod->tuner_mute.wait);
1224 init_waitqueue_head(&pod->tuner_freq.wait);
1225 init_waitqueue_head(&pod->tuner_note.wait);
1226 init_waitqueue_head(&pod->tuner_pitch.wait);
1227 init_waitqueue_head(&pod->clipping.wait);
1228
1229 memset(pod->param_dirty, 0xff, sizeof(pod->param_dirty));
1230
1231 /* initialize USB buffers: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001232 err = line6_dumpreq_init(&pod->dumpreq, pod_request_channel,
1233 sizeof(pod_request_channel));
1234 if (err < 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001235 dev_err(&interface->dev, "Out of memory\n");
Markus Grabner705ecec2009-02-27 19:43:04 -08001236 return -ENOMEM;
1237 }
1238
Markus Grabner705ecec2009-02-27 19:43:04 -08001239 /* create sysfs entries: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001240 err = pod_create_files2(&interface->dev);
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -07001241 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -08001242 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -08001243
1244 /* initialize audio system: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001245 err = line6_init_audio(line6);
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -07001246 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -08001247 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -08001248
1249 /* initialize MIDI subsystem: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001250 err = line6_init_midi(line6);
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -07001251 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -08001252 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -08001253
1254 /* initialize PCM subsystem: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001255 err = line6_init_pcm(line6, &pod_pcm_properties);
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -07001256 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -08001257 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -08001258
Markus Grabner1027f4762010-08-12 01:35:30 +02001259 /* register monitor control: */
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -07001260 err = snd_ctl_add(line6->card,
1261 snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
1262 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -08001263 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -08001264
Markus Grabner1027f4762010-08-12 01:35:30 +02001265 /*
Markus Grabnere1a164d2010-08-23 01:08:25 +02001266 When the sound card is registered at this point, the PODxt Live
1267 displays "Invalid Code Error 07", so we do it later in the event
1268 handler.
1269 */
Markus Grabner1027f4762010-08-12 01:35:30 +02001270
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001271 if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) {
Markus Grabner1027f4762010-08-12 01:35:30 +02001272 pod->monitor_level.value = POD_system_invalid;
1273
1274 /* initiate startup procedure: */
1275 pod_startup1(pod);
Markus Grabner705ecec2009-02-27 19:43:04 -08001276 }
1277
1278 return 0;
1279}
1280
1281/*
Markus Grabner1027f4762010-08-12 01:35:30 +02001282 Init POD device (and clean up in case of failure).
1283*/
1284int line6_pod_init(struct usb_interface *interface, struct usb_line6_pod *pod)
1285{
1286 int err = pod_try_init(interface, pod);
1287
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -07001288 if (err < 0)
Markus Grabner1027f4762010-08-12 01:35:30 +02001289 pod_destruct(interface);
Markus Grabner1027f4762010-08-12 01:35:30 +02001290
1291 return err;
1292}
1293
1294/*
Markus Grabner705ecec2009-02-27 19:43:04 -08001295 POD device disconnected.
1296*/
Markus Grabner1027f4762010-08-12 01:35:30 +02001297void line6_pod_disconnect(struct usb_interface *interface)
Markus Grabner705ecec2009-02-27 19:43:04 -08001298{
1299 struct usb_line6_pod *pod;
1300
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001301 if (interface == NULL)
1302 return;
Markus Grabner705ecec2009-02-27 19:43:04 -08001303 pod = usb_get_intfdata(interface);
1304
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001305 if (pod != NULL) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001306 struct snd_line6_pcm *line6pcm = pod->line6.line6pcm;
1307 struct device *dev = &interface->dev;
1308
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -07001309 if (line6pcm != NULL)
Markus Grabner1027f4762010-08-12 01:35:30 +02001310 line6_pcm_disconnect(line6pcm);
Markus Grabner705ecec2009-02-27 19:43:04 -08001311
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001312 if (dev != NULL) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001313 /* remove sysfs entries: */
Markus Grabnere1a164d2010-08-23 01:08:25 +02001314 line6_pod_remove_files(pod->firmware_version,
1315 pod->line6.
1316 properties->device_bit, dev);
Markus Grabner705ecec2009-02-27 19:43:04 -08001317
1318 device_remove_file(dev, &dev_attr_channel);
1319 device_remove_file(dev, &dev_attr_clip);
1320 device_remove_file(dev, &dev_attr_device_id);
1321 device_remove_file(dev, &dev_attr_dirty);
1322 device_remove_file(dev, &dev_attr_dump);
1323 device_remove_file(dev, &dev_attr_dump_buf);
1324 device_remove_file(dev, &dev_attr_finish);
1325 device_remove_file(dev, &dev_attr_firmware_version);
1326 device_remove_file(dev, &dev_attr_midi_postprocess);
1327 device_remove_file(dev, &dev_attr_monitor_level);
1328 device_remove_file(dev, &dev_attr_name);
1329 device_remove_file(dev, &dev_attr_name_buf);
1330 device_remove_file(dev, &dev_attr_retrieve_amp_setup);
1331 device_remove_file(dev, &dev_attr_retrieve_channel);
Markus Grabnere1a164d2010-08-23 01:08:25 +02001332 device_remove_file(dev,
1333 &dev_attr_retrieve_effects_setup);
Markus Grabner705ecec2009-02-27 19:43:04 -08001334 device_remove_file(dev, &dev_attr_routing);
1335 device_remove_file(dev, &dev_attr_serial_number);
1336 device_remove_file(dev, &dev_attr_store_amp_setup);
1337 device_remove_file(dev, &dev_attr_store_channel);
1338 device_remove_file(dev, &dev_attr_store_effects_setup);
1339 device_remove_file(dev, &dev_attr_tuner_freq);
1340 device_remove_file(dev, &dev_attr_tuner_mute);
1341 device_remove_file(dev, &dev_attr_tuner_note);
1342 device_remove_file(dev, &dev_attr_tuner_pitch);
1343
Markus Grabner1027f4762010-08-12 01:35:30 +02001344#ifdef CONFIG_LINE6_USB_RAW
Markus Grabner705ecec2009-02-27 19:43:04 -08001345 device_remove_file(dev, &dev_attr_raw);
1346#endif
1347 }
1348 }
1349
1350 pod_destruct(interface);
1351}