blob: 4a86f7a1585a41bd323f0af6cb2595c320d8a400 [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:
Stefan Hajnoczie00d33c2012-11-11 13:52:24 +0100255 dev_dbg(pod->line6.ifcdev,
256 "unknown dump code %02X\n",
257 pod->dumpreq.in_progress);
Markus Grabner705ecec2009-02-27 19:43:04 -0800258 }
259
260 line6_dump_finished(&pod->dumpreq);
Markus Grabner1027f4762010-08-12 01:35:30 +0200261 pod_startup3(pod);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800262 } else
Stefan Hajnoczie00d33c2012-11-11 13:52:24 +0100263 dev_dbg(pod->line6.ifcdev,
264 "wrong size of channel dump message (%d instead of %d)\n",
265 pod->line6.message_length,
266 (int)sizeof(pod->prog_data) +
267 7);
Markus Grabner705ecec2009-02-27 19:43:04 -0800268
269 break;
270
Markus Grabnere1a164d2010-08-23 01:08:25 +0200271 case POD_SYSEX_SYSTEM:{
272 short value =
273 ((int)buf[7] << 12) | ((int)buf[8]
274 << 8) |
275 ((int)buf[9] << 4) | (int)buf[10];
Markus Grabner705ecec2009-02-27 19:43:04 -0800276
277#define PROCESS_SYSTEM_PARAM(x) \
278 case POD_ ## x: \
279 pod->x.value = value; \
Markus Grabner1027f4762010-08-12 01:35:30 +0200280 wake_up(&pod->x.wait); \
Markus Grabner705ecec2009-02-27 19:43:04 -0800281 break;
282
Markus Grabnere1a164d2010-08-23 01:08:25 +0200283 switch (buf[6]) {
284 PROCESS_SYSTEM_PARAM
285 (monitor_level);
286 PROCESS_SYSTEM_PARAM(routing);
287 PROCESS_SYSTEM_PARAM
288 (tuner_mute);
289 PROCESS_SYSTEM_PARAM
290 (tuner_freq);
291 PROCESS_SYSTEM_PARAM
292 (tuner_note);
293 PROCESS_SYSTEM_PARAM
294 (tuner_pitch);
Markus Grabner705ecec2009-02-27 19:43:04 -0800295
296#undef PROCESS_SYSTEM_PARAM
297
Markus Grabnere1a164d2010-08-23 01:08:25 +0200298 default:
Stefan Hajnoczie00d33c2012-11-11 13:52:24 +0100299 dev_dbg(pod->line6.ifcdev,
300 "unknown tuner/system response %02X\n",
301 buf[6]);
Markus Grabnere1a164d2010-08-23 01:08:25 +0200302 }
Markus Grabner705ecec2009-02-27 19:43:04 -0800303
Markus Grabnere1a164d2010-08-23 01:08:25 +0200304 break;
305 }
Markus Grabner705ecec2009-02-27 19:43:04 -0800306
307 case POD_SYSEX_FINISH:
308 /* do we need to respond to this? */
309 break;
310
311 case POD_SYSEX_SAVE:
312 pod_save_button_pressed(pod, buf[6], buf[7]);
313 break;
314
315 case POD_SYSEX_CLIP:
Stefan Hajnoczie00d33c2012-11-11 13:52:24 +0100316 dev_dbg(pod->line6.ifcdev, "audio clipped\n");
Markus Grabner705ecec2009-02-27 19:43:04 -0800317 pod->clipping.value = 1;
Markus Grabner1027f4762010-08-12 01:35:30 +0200318 wake_up(&pod->clipping.wait);
Markus Grabner705ecec2009-02-27 19:43:04 -0800319 break;
320
321 case POD_SYSEX_STORE:
Stefan Hajnoczie00d33c2012-11-11 13:52:24 +0100322 dev_dbg(pod->line6.ifcdev,
323 "message %02X not yet implemented\n",
324 buf[5]);
Markus Grabner705ecec2009-02-27 19:43:04 -0800325 break;
326
327 default:
Stefan Hajnoczie00d33c2012-11-11 13:52:24 +0100328 dev_dbg(pod->line6.ifcdev,
329 "unknown sysex message %02X\n",
330 buf[5]);
Markus Grabner705ecec2009-02-27 19:43:04 -0800331 }
Markus Grabnere1a164d2010-08-23 01:08:25 +0200332 } else
333 if (memcmp
334 (buf, pod_version_header,
335 sizeof(pod_version_header)) == 0) {
336 pod->firmware_version =
337 buf[13] * 100 + buf[14] * 10 + buf[15];
338 pod->device_id =
339 ((int)buf[8] << 16) | ((int)buf[9] << 8) | (int)
340 buf[10];
Markus Grabner1027f4762010-08-12 01:35:30 +0200341 pod_startup4(pod);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800342 } else
Stefan Hajnoczie00d33c2012-11-11 13:52:24 +0100343 dev_dbg(pod->line6.ifcdev, "unknown sysex header\n");
Markus Grabner705ecec2009-02-27 19:43:04 -0800344
345 break;
346
347 case LINE6_SYSEX_END:
348 break;
349
350 default:
Stefan Hajnoczie00d33c2012-11-11 13:52:24 +0100351 dev_dbg(pod->line6.ifcdev, "POD: unknown message %02X\n",
352 buf[0]);
Markus Grabner705ecec2009-02-27 19:43:04 -0800353 }
354}
355
356/*
357 Detect some cases that require a channel dump after sending a command to the
358 device. Important notes:
359 *) The actual dump request can not be sent here since we are not allowed to
360 wait for the completion of the first message in this context, and sending
361 the dump request before completion of the previous message leaves the POD
362 in an undefined state. The dump request will be sent when the echoed
363 commands are received.
364 *) This method fails if a param change message is "chopped" after the first
365 byte.
366*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200367void line6_pod_midi_postprocess(struct usb_line6_pod *pod, unsigned char *data,
368 int length)
Markus Grabner705ecec2009-02-27 19:43:04 -0800369{
370 int i;
371
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800372 if (!pod->midi_postprocess)
Markus Grabner705ecec2009-02-27 19:43:04 -0800373 return;
374
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800375 for (i = 0; i < length; ++i) {
376 if (data[i] == (LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST)) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800377 line6_invalidate_current(&pod->dumpreq);
378 break;
Markus Grabnere1a164d2010-08-23 01:08:25 +0200379 } else
380 if ((data[i] == (LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST))
381 && (i < length - 1))
382 if ((data[i + 1] == POD_amp_model_setup)
383 || (data[i + 1] == POD_effect_setup)) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800384 line6_invalidate_current(&pod->dumpreq);
385 break;
386 }
387 }
388}
389
390/*
391 Send channel number (i.e., switch to a different sound).
392*/
Johannes Thumshirn8d6b7f72012-06-27 21:25:59 +0200393static void pod_send_channel(struct usb_line6_pod *pod, u8 value)
Markus Grabner705ecec2009-02-27 19:43:04 -0800394{
395 line6_invalidate_current(&pod->dumpreq);
396
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800397 if (line6_send_program(&pod->line6, value) == 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800398 pod->channel_num = value;
399 else
400 line6_dump_finished(&pod->dumpreq);
401}
402
403/*
404 Transmit PODxt Pro control parameter.
405*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200406void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param,
Johannes Thumshirn5b9bd2a2012-06-27 21:25:57 +0200407 u8 value)
Markus Grabner705ecec2009-02-27 19:43:04 -0800408{
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800409 if (line6_transmit_parameter(&pod->line6, param, value) == 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800410 pod_store_parameter(pod, param, value);
411
Markus Grabnere1a164d2010-08-23 01:08:25 +0200412 if ((param == POD_amp_model_setup) || (param == POD_effect_setup)) /* these also affect other settings */
Markus Grabner705ecec2009-02-27 19:43:04 -0800413 line6_invalidate_current(&pod->dumpreq);
414}
415
416/*
417 Resolve value to memory location.
418*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200419static int pod_resolve(const char *buf, short block0, short block1,
420 unsigned char *location)
Markus Grabner705ecec2009-02-27 19:43:04 -0800421{
Johannes Thumshirn1d0e8342012-06-27 21:26:01 +0200422 u8 value;
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600423 short block;
424 int ret;
425
Johannes Thumshirn1d0e8342012-06-27 21:26:01 +0200426 ret = kstrtou8(buf, 10, &value);
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600427 if (ret)
428 return ret;
429
430 block = (value < 0x40) ? block0 : block1;
Markus Grabner705ecec2009-02-27 19:43:04 -0800431 value &= 0x3f;
432 location[0] = block >> 7;
433 location[1] = value | (block & 0x7f);
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600434 return 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800435}
436
437/*
438 Send command to store channel/effects setup/amp setup to PODxt Pro.
439*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200440static ssize_t pod_send_store_command(struct device *dev, const char *buf,
441 size_t count, short block0, short block1)
Markus Grabner705ecec2009-02-27 19:43:04 -0800442{
443 struct usb_interface *interface = to_usb_interface(dev);
444 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600445 int ret;
Markus Grabner705ecec2009-02-27 19:43:04 -0800446 int size = 3 + sizeof(pod->prog_data_buf);
447 char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_STORE, size);
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600448
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800449 if (!sysex)
450 return 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800451
Markus Grabnere1a164d2010-08-23 01:08:25 +0200452 sysex[SYSEX_DATA_OFS] = 5; /* see pod_dump() */
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600453 ret = pod_resolve(buf, block0, block1, sysex + SYSEX_DATA_OFS + 1);
454 if (ret) {
455 kfree(sysex);
456 return ret;
457 }
458
Markus Grabnere1a164d2010-08-23 01:08:25 +0200459 memcpy(sysex + SYSEX_DATA_OFS + 3, &pod->prog_data_buf,
460 sizeof(pod->prog_data_buf));
Markus Grabner705ecec2009-02-27 19:43:04 -0800461
462 line6_send_sysex_message(&pod->line6, sysex, size);
463 kfree(sysex);
464 /* needs some delay here on AMD64 platform */
465 return count;
466}
467
468/*
469 Send command to retrieve channel/effects setup/amp setup to PODxt Pro.
470*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200471static ssize_t pod_send_retrieve_command(struct device *dev, const char *buf,
472 size_t count, short block0,
473 short block1)
Markus Grabner705ecec2009-02-27 19:43:04 -0800474{
475 struct usb_interface *interface = to_usb_interface(dev);
476 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600477 int ret;
Markus Grabner705ecec2009-02-27 19:43:04 -0800478 int size = 4;
479 char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_DUMPMEM, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800480
481 if (!sysex)
482 return 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800483
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600484 ret = pod_resolve(buf, block0, block1, sysex + SYSEX_DATA_OFS);
485 if (ret) {
486 kfree(sysex);
487 return ret;
488 }
Markus Grabner705ecec2009-02-27 19:43:04 -0800489 sysex[SYSEX_DATA_OFS + 2] = 0;
490 sysex[SYSEX_DATA_OFS + 3] = 0;
491 line6_dump_started(&pod->dumpreq, POD_DUMP_MEMORY);
492
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800493 if (line6_send_sysex_message(&pod->line6, sysex, size) < size)
Markus Grabner705ecec2009-02-27 19:43:04 -0800494 line6_dump_finished(&pod->dumpreq);
495
496 kfree(sysex);
497 /* needs some delay here on AMD64 platform */
498 return count;
499}
500
501/*
502 Generic get name function.
503*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200504static ssize_t get_name_generic(struct usb_line6_pod *pod, const char *str,
505 char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800506{
507 int length = 0;
508 const char *p1;
509 char *p2;
510 char *last_non_space = buf;
511
Markus Grabner1027f4762010-08-12 01:35:30 +0200512 int retval = line6_dump_wait_interruptible(&pod->dumpreq);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800513 if (retval < 0)
514 return retval;
Markus Grabner705ecec2009-02-27 19:43:04 -0800515
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800516 for (p1 = str, p2 = buf; *p1; ++p1, ++p2) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800517 *p2 = *p1;
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800518 if (*p2 != ' ')
519 last_non_space = p2;
520 if (++length == POD_NAME_LENGTH)
521 break;
Markus Grabner705ecec2009-02-27 19:43:04 -0800522 }
523
524 *(last_non_space + 1) = '\n';
525 return last_non_space - buf + 2;
526}
527
528/*
529 "read" request on "channel" special file.
530*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800531static ssize_t pod_get_channel(struct device *dev,
532 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800533{
534 struct usb_interface *interface = to_usb_interface(dev);
535 struct usb_line6_pod *pod = usb_get_intfdata(interface);
536 return sprintf(buf, "%d\n", pod->channel_num);
537}
538
539/*
540 "write" request on "channel" special file.
541*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800542static ssize_t pod_set_channel(struct device *dev,
543 struct device_attribute *attr,
544 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800545{
546 struct usb_interface *interface = to_usb_interface(dev);
547 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Johannes Thumshirna4fb7d52012-06-27 21:26:02 +0200548 u8 value;
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600549 int ret;
550
Johannes Thumshirna4fb7d52012-06-27 21:26:02 +0200551 ret = kstrtou8(buf, 10, &value);
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600552 if (ret)
553 return ret;
554
Markus Grabner705ecec2009-02-27 19:43:04 -0800555 pod_send_channel(pod, value);
556 return count;
557}
558
559/*
560 "read" request on "name" special file.
561*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800562static ssize_t pod_get_name(struct device *dev, struct device_attribute *attr,
563 char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800564{
565 struct usb_interface *interface = to_usb_interface(dev);
566 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Markus Grabnere1a164d2010-08-23 01:08:25 +0200567 return get_name_generic(pod, pod->prog_data.header + POD_NAME_OFFSET,
568 buf);
Markus Grabner705ecec2009-02-27 19:43:04 -0800569}
570
571/*
572 "read" request on "name" special file.
573*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800574static ssize_t pod_get_name_buf(struct device *dev,
575 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800576{
577 struct usb_interface *interface = to_usb_interface(dev);
578 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Markus Grabnere1a164d2010-08-23 01:08:25 +0200579 return get_name_generic(pod,
580 pod->prog_data_buf.header + POD_NAME_OFFSET,
581 buf);
Markus Grabner705ecec2009-02-27 19:43:04 -0800582}
583
584/*
585 "read" request on "dump" special file.
586*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800587static ssize_t pod_get_dump(struct device *dev, struct device_attribute *attr,
588 char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800589{
590 struct usb_interface *interface = to_usb_interface(dev);
591 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Markus Grabner1027f4762010-08-12 01:35:30 +0200592 int retval = line6_dump_wait_interruptible(&pod->dumpreq);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800593 if (retval < 0)
594 return retval;
Markus Grabner705ecec2009-02-27 19:43:04 -0800595 memcpy(buf, &pod->prog_data, sizeof(pod->prog_data));
596 return sizeof(pod->prog_data);
597}
598
599/*
600 "write" request on "dump" special file.
601*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800602static ssize_t pod_set_dump(struct device *dev, struct device_attribute *attr,
603 const char *buf, size_t count)
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);
607
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800608 if (count != sizeof(pod->prog_data)) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800609 dev_err(pod->line6.ifcdev,
Markus Grabnere1a164d2010-08-23 01:08:25 +0200610 "data block must be exactly %d bytes\n",
611 (int)sizeof(pod->prog_data));
Markus Grabner705ecec2009-02-27 19:43:04 -0800612 return -EINVAL;
613 }
614
615 pod_dump(pod, buf);
616 return sizeof(pod->prog_data);
617}
618
619/*
Markus Grabner1027f4762010-08-12 01:35:30 +0200620 Identify system parameters related to the tuner.
621*/
622static bool pod_is_tuner(int code)
623{
624 return
Markus Grabnere1a164d2010-08-23 01:08:25 +0200625 (code == POD_tuner_mute) ||
626 (code == POD_tuner_freq) ||
627 (code == POD_tuner_note) || (code == POD_tuner_pitch);
Markus Grabner1027f4762010-08-12 01:35:30 +0200628}
629
630/*
631 Get system parameter (as integer).
Markus Grabner705ecec2009-02-27 19:43:04 -0800632 @param tuner non-zero, if code refers to a tuner parameter
633*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200634static int pod_get_system_param_int(struct usb_line6_pod *pod, int *value,
635 int code, struct ValueWait *param, int sign)
Markus Grabner705ecec2009-02-27 19:43:04 -0800636{
637 char *sysex;
Markus Grabner705ecec2009-02-27 19:43:04 -0800638 static const int size = 1;
639 int retval = 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800640
Markus Grabnere1a164d2010-08-23 01:08:25 +0200641 if (((pod->prog_data.control[POD_tuner] & 0x40) == 0)
642 && pod_is_tuner(code))
Markus Grabner705ecec2009-02-27 19:43:04 -0800643 return -ENODEV;
644
Markus Grabner1027f4762010-08-12 01:35:30 +0200645 /* send value request to device: */
Markus Grabner705ecec2009-02-27 19:43:04 -0800646 param->value = POD_system_invalid;
647 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEMREQ, size);
Markus Grabner1027f4762010-08-12 01:35:30 +0200648
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800649 if (!sysex)
Markus Grabner1027f4762010-08-12 01:35:30 +0200650 return -ENOMEM;
651
Markus Grabner705ecec2009-02-27 19:43:04 -0800652 sysex[SYSEX_DATA_OFS] = code;
653 line6_send_sysex_message(&pod->line6, sysex, size);
654 kfree(sysex);
655
Markus Grabner1027f4762010-08-12 01:35:30 +0200656 /* wait for device to respond: */
Markus Grabnere1a164d2010-08-23 01:08:25 +0200657 retval =
658 wait_event_interruptible(param->wait,
659 param->value != POD_system_invalid);
Markus Grabner705ecec2009-02-27 19:43:04 -0800660
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800661 if (retval < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800662 return retval;
663
Markus Grabnere1a164d2010-08-23 01:08:25 +0200664 *value = sign ? (int)(signed short)param->value : (int)(unsigned short)
665 param->value;
Markus Grabner1027f4762010-08-12 01:35:30 +0200666
Markus Grabnere1a164d2010-08-23 01:08:25 +0200667 if (*value == POD_system_invalid)
668 *value = 0; /* don't report uninitialized values */
Markus Grabner1027f4762010-08-12 01:35:30 +0200669
670 return 0;
671}
672
673/*
674 Get system parameter (as string).
675 @param tuner non-zero, if code refers to a tuner parameter
676*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200677static ssize_t pod_get_system_param_string(struct usb_line6_pod *pod, char *buf,
678 int code, struct ValueWait *param,
679 int sign)
Markus Grabner1027f4762010-08-12 01:35:30 +0200680{
681 int retval, value = 0;
682 retval = pod_get_system_param_int(pod, &value, code, param, sign);
683
Markus Grabnere1a164d2010-08-23 01:08:25 +0200684 if (retval < 0)
Markus Grabner1027f4762010-08-12 01:35:30 +0200685 return retval;
686
Markus Grabner705ecec2009-02-27 19:43:04 -0800687 return sprintf(buf, "%d\n", value);
688}
689
690/*
Markus Grabner1027f4762010-08-12 01:35:30 +0200691 Send system parameter (from integer).
Markus Grabner705ecec2009-02-27 19:43:04 -0800692 @param tuner non-zero, if code refers to a tuner parameter
693*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200694static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
695 int code)
Markus Grabner705ecec2009-02-27 19:43:04 -0800696{
697 char *sysex;
698 static const int size = 5;
Markus Grabner705ecec2009-02-27 19:43:04 -0800699
Markus Grabnere1a164d2010-08-23 01:08:25 +0200700 if (((pod->prog_data.control[POD_tuner] & 0x40) == 0)
701 && pod_is_tuner(code))
Markus Grabner705ecec2009-02-27 19:43:04 -0800702 return -EINVAL;
703
704 /* send value to tuner: */
705 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800706 if (!sysex)
Markus Grabner1027f4762010-08-12 01:35:30 +0200707 return -ENOMEM;
Markus Grabner705ecec2009-02-27 19:43:04 -0800708 sysex[SYSEX_DATA_OFS] = code;
709 sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
Markus Grabnere1a164d2010-08-23 01:08:25 +0200710 sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
711 sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
712 sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f;
Markus Grabner705ecec2009-02-27 19:43:04 -0800713 line6_send_sysex_message(&pod->line6, sysex, size);
714 kfree(sysex);
Markus Grabner1027f4762010-08-12 01:35:30 +0200715 return 0;
716}
717
718/*
719 Send system parameter (from string).
720 @param tuner non-zero, if code refers to a tuner parameter
721*/
Markus Grabnere1a164d2010-08-23 01:08:25 +0200722static ssize_t pod_set_system_param_string(struct usb_line6_pod *pod,
723 const char *buf, int count, int code,
724 unsigned short mask)
Markus Grabner1027f4762010-08-12 01:35:30 +0200725{
726 int retval;
727 unsigned short value = simple_strtoul(buf, NULL, 10) & mask;
728 retval = pod_set_system_param_int(pod, value, code);
729 return (retval < 0) ? retval : count;
Markus Grabner705ecec2009-02-27 19:43:04 -0800730}
731
732/*
733 "read" request on "dump_buf" special file.
734*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800735static ssize_t pod_get_dump_buf(struct device *dev,
736 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800737{
738 struct usb_interface *interface = to_usb_interface(dev);
739 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Markus Grabner1027f4762010-08-12 01:35:30 +0200740 int retval = line6_dump_wait_interruptible(&pod->dumpreq);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800741 if (retval < 0)
742 return retval;
Markus Grabner705ecec2009-02-27 19:43:04 -0800743 memcpy(buf, &pod->prog_data_buf, sizeof(pod->prog_data_buf));
744 return sizeof(pod->prog_data_buf);
745}
746
747/*
748 "write" request on "dump_buf" special file.
749*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800750static ssize_t pod_set_dump_buf(struct device *dev,
751 struct device_attribute *attr,
752 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800753{
754 struct usb_interface *interface = to_usb_interface(dev);
755 struct usb_line6_pod *pod = usb_get_intfdata(interface);
756
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800757 if (count != sizeof(pod->prog_data)) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800758 dev_err(pod->line6.ifcdev,
Markus Grabner1027f4762010-08-12 01:35:30 +0200759 "data block must be exactly %d bytes\n",
760 (int)sizeof(pod->prog_data));
Markus Grabner705ecec2009-02-27 19:43:04 -0800761 return -EINVAL;
762 }
763
764 memcpy(&pod->prog_data_buf, buf, sizeof(pod->prog_data));
765 return sizeof(pod->prog_data);
766}
767
768/*
769 "write" request on "finish" special file.
770*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800771static ssize_t pod_set_finish(struct device *dev,
772 struct device_attribute *attr,
773 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800774{
775 struct usb_interface *interface = to_usb_interface(dev);
776 struct usb_line6_pod *pod = usb_get_intfdata(interface);
777 int size = 0;
778 char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_FINISH, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800779 if (!sysex)
780 return 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800781 line6_send_sysex_message(&pod->line6, sysex, size);
782 kfree(sysex);
783 return count;
784}
785
786/*
787 "write" request on "store_channel" special file.
788*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800789static ssize_t pod_set_store_channel(struct device *dev,
790 struct device_attribute *attr,
791 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800792{
793 return pod_send_store_command(dev, buf, count, 0x0000, 0x00c0);
794}
795
796/*
797 "write" request on "store_effects_setup" special file.
798*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800799static ssize_t pod_set_store_effects_setup(struct device *dev,
800 struct device_attribute *attr,
801 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800802{
803 return pod_send_store_command(dev, buf, count, 0x0080, 0x0080);
804}
805
806/*
807 "write" request on "store_amp_setup" special file.
808*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800809static ssize_t pod_set_store_amp_setup(struct device *dev,
810 struct device_attribute *attr,
811 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800812{
813 return pod_send_store_command(dev, buf, count, 0x0040, 0x0100);
814}
815
816/*
817 "write" request on "retrieve_channel" special file.
818*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800819static ssize_t pod_set_retrieve_channel(struct device *dev,
820 struct device_attribute *attr,
821 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800822{
823 return pod_send_retrieve_command(dev, buf, count, 0x0000, 0x00c0);
824}
825
826/*
827 "write" request on "retrieve_effects_setup" special file.
828*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800829static ssize_t pod_set_retrieve_effects_setup(struct device *dev,
830 struct device_attribute *attr,
831 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800832{
833 return pod_send_retrieve_command(dev, buf, count, 0x0080, 0x0080);
834}
835
836/*
837 "write" request on "retrieve_amp_setup" special file.
838*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800839static ssize_t pod_set_retrieve_amp_setup(struct device *dev,
840 struct device_attribute *attr,
841 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800842{
843 return pod_send_retrieve_command(dev, buf, count, 0x0040, 0x0100);
844}
845
846/*
847 "read" request on "dirty" special file.
848*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800849static ssize_t pod_get_dirty(struct device *dev, struct device_attribute *attr,
850 char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800851{
852 struct usb_interface *interface = to_usb_interface(dev);
853 struct usb_line6_pod *pod = usb_get_intfdata(interface);
854 buf[0] = pod->dirty ? '1' : '0';
855 buf[1] = '\n';
856 return 2;
857}
858
859/*
860 "read" request on "midi_postprocess" special file.
861*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800862static ssize_t pod_get_midi_postprocess(struct device *dev,
863 struct device_attribute *attr,
864 char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800865{
866 struct usb_interface *interface = to_usb_interface(dev);
867 struct usb_line6_pod *pod = usb_get_intfdata(interface);
868 return sprintf(buf, "%d\n", pod->midi_postprocess);
869}
870
871/*
872 "write" request on "midi_postprocess" special file.
873*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800874static ssize_t pod_set_midi_postprocess(struct device *dev,
875 struct device_attribute *attr,
876 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800877{
878 struct usb_interface *interface = to_usb_interface(dev);
879 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Johannes Thumshirn06501782012-06-27 21:26:03 +0200880 u8 value;
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600881 int ret;
882
Johannes Thumshirn06501782012-06-27 21:26:03 +0200883 ret = kstrtou8(buf, 10, &value);
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600884 if (ret)
885 return ret;
886
Markus Grabner705ecec2009-02-27 19:43:04 -0800887 pod->midi_postprocess = value ? 1 : 0;
888 return count;
889}
890
891/*
892 "read" request on "serial_number" special file.
893*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800894static ssize_t pod_get_serial_number(struct device *dev,
895 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800896{
897 struct usb_interface *interface = to_usb_interface(dev);
898 struct usb_line6_pod *pod = usb_get_intfdata(interface);
899 return sprintf(buf, "%d\n", pod->serial_number);
900}
901
902/*
903 "read" request on "firmware_version" special file.
904*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800905static ssize_t pod_get_firmware_version(struct device *dev,
906 struct device_attribute *attr,
907 char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800908{
909 struct usb_interface *interface = to_usb_interface(dev);
910 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800911 return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
912 pod->firmware_version % 100);
Markus Grabner705ecec2009-02-27 19:43:04 -0800913}
914
915/*
916 "read" request on "device_id" special file.
917*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800918static ssize_t pod_get_device_id(struct device *dev,
919 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800920{
921 struct usb_interface *interface = to_usb_interface(dev);
922 struct usb_line6_pod *pod = usb_get_intfdata(interface);
923 return sprintf(buf, "%d\n", pod->device_id);
924}
925
926/*
927 "read" request on "clip" special file.
928*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800929static ssize_t pod_wait_for_clip(struct device *dev,
930 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800931{
932 struct usb_interface *interface = to_usb_interface(dev);
933 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Markus Grabnere1a164d2010-08-23 01:08:25 +0200934 return wait_event_interruptible(pod->clipping.wait,
935 pod->clipping.value != 0);
Markus Grabner705ecec2009-02-27 19:43:04 -0800936}
937
Markus Grabner1027f4762010-08-12 01:35:30 +0200938/*
939 POD startup procedure.
940 This is a sequence of functions with special requirements (e.g., must
941 not run immediately after initialization, must not run in interrupt
942 context). After the last one has finished, the device is ready to use.
943*/
944
945static void pod_startup1(struct usb_line6_pod *pod)
946{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200947 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
Markus Grabner1027f4762010-08-12 01:35:30 +0200948
949 /* delay startup procedure: */
Markus Grabnere1a164d2010-08-23 01:08:25 +0200950 line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
951 (unsigned long)pod);
Markus Grabner1027f4762010-08-12 01:35:30 +0200952}
953
954static void pod_startup2(unsigned long data)
955{
956 struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
Markus Grabnere1a164d2010-08-23 01:08:25 +0200957
958 /* schedule another startup procedure until startup is complete: */
959 if (pod->startup_progress >= POD_STARTUP_LAST)
960 return;
961
962 pod->startup_progress = POD_STARTUP_DUMPREQ;
963 line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
964 (unsigned long)pod);
Markus Grabner1027f4762010-08-12 01:35:30 +0200965
966 /* current channel dump: */
Markus Grabnere1a164d2010-08-23 01:08:25 +0200967 line6_dump_request_async(&pod->dumpreq, &pod->line6, 0,
968 LINE6_DUMP_CURRENT);
Markus Grabner1027f4762010-08-12 01:35:30 +0200969}
970
971static void pod_startup3(struct usb_line6_pod *pod)
972{
973 struct usb_line6 *line6 = &pod->line6;
Markus Grabnere1a164d2010-08-23 01:08:25 +0200974 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
Markus Grabner1027f4762010-08-12 01:35:30 +0200975
976 /* request firmware version: */
977 line6_version_request_async(line6);
978}
979
980static void pod_startup4(struct usb_line6_pod *pod)
981{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200982 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
Markus Grabner1027f4762010-08-12 01:35:30 +0200983
984 /* schedule work for global work queue: */
985 schedule_work(&pod->startup_work);
986}
987
988static void pod_startup5(struct work_struct *work)
989{
Markus Grabnere1a164d2010-08-23 01:08:25 +0200990 struct usb_line6_pod *pod =
991 container_of(work, struct usb_line6_pod, startup_work);
Markus Grabner1027f4762010-08-12 01:35:30 +0200992 struct usb_line6 *line6 = &pod->line6;
993
Markus Grabnere1a164d2010-08-23 01:08:25 +0200994 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
Markus Grabner1027f4762010-08-12 01:35:30 +0200995
996 /* serial number: */
997 line6_read_serial_number(&pod->line6, &pod->serial_number);
998
999 /* ALSA audio interface: */
1000 line6_register_audio(line6);
1001
1002 /* device files: */
Markus Grabnere1a164d2010-08-23 01:08:25 +02001003 line6_pod_create_files(pod->firmware_version,
1004 line6->properties->device_bit, line6->ifcdev);
Markus Grabner1027f4762010-08-12 01:35:30 +02001005}
1006
1007#define POD_GET_SYSTEM_PARAM(code, sign) \
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -08001008static ssize_t pod_get_ ## code(struct device *dev, \
1009 struct device_attribute *attr, char *buf) \
Markus Grabner705ecec2009-02-27 19:43:04 -08001010{ \
1011 struct usb_interface *interface = to_usb_interface(dev); \
1012 struct usb_line6_pod *pod = usb_get_intfdata(interface); \
Markus Grabner1027f4762010-08-12 01:35:30 +02001013 return pod_get_system_param_string(pod, buf, POD_ ## code, \
1014 &pod->code, sign); \
Markus Grabner705ecec2009-02-27 19:43:04 -08001015}
1016
Markus Grabner1027f4762010-08-12 01:35:30 +02001017#define POD_GET_SET_SYSTEM_PARAM(code, mask, sign) \
1018POD_GET_SYSTEM_PARAM(code, sign) \
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -08001019static ssize_t pod_set_ ## code(struct device *dev, \
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001020 struct device_attribute *attr, \
1021 const char *buf, size_t count) \
Markus Grabner705ecec2009-02-27 19:43:04 -08001022{ \
1023 struct usb_interface *interface = to_usb_interface(dev); \
1024 struct usb_line6_pod *pod = usb_get_intfdata(interface); \
Markus Grabner1027f4762010-08-12 01:35:30 +02001025 return pod_set_system_param_string(pod, buf, count, POD_ ## code, mask); \
Markus Grabner705ecec2009-02-27 19:43:04 -08001026}
1027
Markus Grabner1027f4762010-08-12 01:35:30 +02001028POD_GET_SET_SYSTEM_PARAM(monitor_level, 0xffff, 0);
1029POD_GET_SET_SYSTEM_PARAM(routing, 0x0003, 0);
1030POD_GET_SET_SYSTEM_PARAM(tuner_mute, 0x0001, 0);
1031POD_GET_SET_SYSTEM_PARAM(tuner_freq, 0xffff, 0);
1032POD_GET_SYSTEM_PARAM(tuner_note, 1);
1033POD_GET_SYSTEM_PARAM(tuner_pitch, 1);
Markus Grabner705ecec2009-02-27 19:43:04 -08001034
1035#undef GET_SET_SYSTEM_PARAM
1036#undef GET_SYSTEM_PARAM
1037
1038/* POD special files: */
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001039static DEVICE_ATTR(channel, S_IWUSR | S_IRUGO, pod_get_channel,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001040 pod_set_channel);
Markus Grabner705ecec2009-02-27 19:43:04 -08001041static DEVICE_ATTR(clip, S_IRUGO, pod_wait_for_clip, line6_nop_write);
1042static DEVICE_ATTR(device_id, S_IRUGO, pod_get_device_id, line6_nop_write);
1043static DEVICE_ATTR(dirty, S_IRUGO, pod_get_dirty, line6_nop_write);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001044static DEVICE_ATTR(dump, S_IWUSR | S_IRUGO, pod_get_dump, pod_set_dump);
1045static DEVICE_ATTR(dump_buf, S_IWUSR | S_IRUGO, pod_get_dump_buf,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001046 pod_set_dump_buf);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001047static DEVICE_ATTR(finish, S_IWUSR, line6_nop_read, pod_set_finish);
Markus Grabnere1a164d2010-08-23 01:08:25 +02001048static DEVICE_ATTR(firmware_version, S_IRUGO, pod_get_firmware_version,
1049 line6_nop_write);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001050static DEVICE_ATTR(midi_postprocess, S_IWUSR | S_IRUGO,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001051 pod_get_midi_postprocess, pod_set_midi_postprocess);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001052static DEVICE_ATTR(monitor_level, S_IWUSR | S_IRUGO, pod_get_monitor_level,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001053 pod_set_monitor_level);
Markus Grabner705ecec2009-02-27 19:43:04 -08001054static DEVICE_ATTR(name, S_IRUGO, pod_get_name, line6_nop_write);
1055static DEVICE_ATTR(name_buf, S_IRUGO, pod_get_name_buf, line6_nop_write);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001056static DEVICE_ATTR(retrieve_amp_setup, S_IWUSR, line6_nop_read,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001057 pod_set_retrieve_amp_setup);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001058static DEVICE_ATTR(retrieve_channel, S_IWUSR, line6_nop_read,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001059 pod_set_retrieve_channel);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001060static DEVICE_ATTR(retrieve_effects_setup, S_IWUSR, line6_nop_read,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001061 pod_set_retrieve_effects_setup);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001062static DEVICE_ATTR(routing, S_IWUSR | S_IRUGO, pod_get_routing,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001063 pod_set_routing);
1064static DEVICE_ATTR(serial_number, S_IRUGO, pod_get_serial_number,
1065 line6_nop_write);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001066static DEVICE_ATTR(store_amp_setup, S_IWUSR, line6_nop_read,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001067 pod_set_store_amp_setup);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001068static DEVICE_ATTR(store_channel, S_IWUSR, line6_nop_read,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001069 pod_set_store_channel);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001070static DEVICE_ATTR(store_effects_setup, S_IWUSR, line6_nop_read,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001071 pod_set_store_effects_setup);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001072static DEVICE_ATTR(tuner_freq, S_IWUSR | S_IRUGO, pod_get_tuner_freq,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001073 pod_set_tuner_freq);
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001074static DEVICE_ATTR(tuner_mute, S_IWUSR | S_IRUGO, pod_get_tuner_mute,
Markus Grabnere1a164d2010-08-23 01:08:25 +02001075 pod_set_tuner_mute);
Markus Grabner705ecec2009-02-27 19:43:04 -08001076static DEVICE_ATTR(tuner_note, S_IRUGO, pod_get_tuner_note, line6_nop_write);
1077static DEVICE_ATTR(tuner_pitch, S_IRUGO, pod_get_tuner_pitch, line6_nop_write);
1078
Markus Grabner1027f4762010-08-12 01:35:30 +02001079#ifdef CONFIG_LINE6_USB_RAW
Greg Kroah-Hartmana3a972a2010-11-18 11:21:04 -08001080static DEVICE_ATTR(raw, S_IWUSR, line6_nop_read, line6_set_raw);
Markus Grabner705ecec2009-02-27 19:43:04 -08001081#endif
1082
Markus Grabner1027f4762010-08-12 01:35:30 +02001083/* control info callback */
1084static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
1085 struct snd_ctl_elem_info *uinfo)
1086{
1087 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1088 uinfo->count = 1;
1089 uinfo->value.integer.min = 0;
1090 uinfo->value.integer.max = 65535;
1091 return 0;
1092}
1093
1094/* control get callback */
1095static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
1096 struct snd_ctl_elem_value *ucontrol)
1097{
1098 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
1099 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
1100 ucontrol->value.integer.value[0] = pod->monitor_level.value;
1101 return 0;
1102}
1103
1104/* control put callback */
1105static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
1106 struct snd_ctl_elem_value *ucontrol)
1107{
1108 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
1109 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
1110
Markus Grabnere1a164d2010-08-23 01:08:25 +02001111 if (ucontrol->value.integer.value[0] == pod->monitor_level.value)
Markus Grabner1027f4762010-08-12 01:35:30 +02001112 return 0;
1113
1114 pod->monitor_level.value = ucontrol->value.integer.value[0];
Markus Grabnere1a164d2010-08-23 01:08:25 +02001115 pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
1116 POD_monitor_level);
Markus Grabner1027f4762010-08-12 01:35:30 +02001117 return 1;
1118}
1119
1120/* control definition */
1121static struct snd_kcontrol_new pod_control_monitor = {
1122 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1123 .name = "Monitor Playback Volume",
1124 .index = 0,
1125 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1126 .info = snd_pod_control_monitor_info,
1127 .get = snd_pod_control_monitor_get,
1128 .put = snd_pod_control_monitor_put
1129};
1130
Markus Grabner705ecec2009-02-27 19:43:04 -08001131/*
1132 POD destructor.
1133*/
1134static void pod_destruct(struct usb_interface *interface)
1135{
1136 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Markus Grabner705ecec2009-02-27 19:43:04 -08001137
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001138 if (pod == NULL)
1139 return;
Stefan Hajnoczi188e6642011-12-10 02:12:30 +01001140 line6_cleanup_audio(&pod->line6);
Markus Grabner705ecec2009-02-27 19:43:04 -08001141
Markus Grabnere1a164d2010-08-23 01:08:25 +02001142 del_timer(&pod->startup_timer);
1143 cancel_work_sync(&pod->startup_work);
1144
Markus Grabner705ecec2009-02-27 19:43:04 -08001145 /* free dump request data: */
1146 line6_dumpreq_destruct(&pod->dumpreq);
Markus Grabner705ecec2009-02-27 19:43:04 -08001147}
1148
1149/*
1150 Create sysfs entries.
1151*/
Greg Kroah-Hartmanb702ed252009-02-27 20:45:03 -08001152static int pod_create_files2(struct device *dev)
Markus Grabner705ecec2009-02-27 19:43:04 -08001153{
1154 int err;
1155
1156 CHECK_RETURN(device_create_file(dev, &dev_attr_channel));
1157 CHECK_RETURN(device_create_file(dev, &dev_attr_clip));
1158 CHECK_RETURN(device_create_file(dev, &dev_attr_device_id));
1159 CHECK_RETURN(device_create_file(dev, &dev_attr_dirty));
1160 CHECK_RETURN(device_create_file(dev, &dev_attr_dump));
1161 CHECK_RETURN(device_create_file(dev, &dev_attr_dump_buf));
1162 CHECK_RETURN(device_create_file(dev, &dev_attr_finish));
1163 CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version));
1164 CHECK_RETURN(device_create_file(dev, &dev_attr_midi_postprocess));
1165 CHECK_RETURN(device_create_file(dev, &dev_attr_monitor_level));
1166 CHECK_RETURN(device_create_file(dev, &dev_attr_name));
1167 CHECK_RETURN(device_create_file(dev, &dev_attr_name_buf));
1168 CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_amp_setup));
1169 CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_channel));
1170 CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_effects_setup));
1171 CHECK_RETURN(device_create_file(dev, &dev_attr_routing));
1172 CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number));
1173 CHECK_RETURN(device_create_file(dev, &dev_attr_store_amp_setup));
1174 CHECK_RETURN(device_create_file(dev, &dev_attr_store_channel));
1175 CHECK_RETURN(device_create_file(dev, &dev_attr_store_effects_setup));
1176 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_freq));
1177 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_mute));
1178 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_note));
1179 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_pitch));
1180
Markus Grabner1027f4762010-08-12 01:35:30 +02001181#ifdef CONFIG_LINE6_USB_RAW
Markus Grabner705ecec2009-02-27 19:43:04 -08001182 CHECK_RETURN(device_create_file(dev, &dev_attr_raw));
1183#endif
1184
1185 return 0;
1186}
1187
1188/*
Markus Grabner1027f4762010-08-12 01:35:30 +02001189 Try to init POD device.
Markus Grabner705ecec2009-02-27 19:43:04 -08001190*/
Markus Grabnere1a164d2010-08-23 01:08:25 +02001191static int pod_try_init(struct usb_interface *interface,
1192 struct usb_line6_pod *pod)
Markus Grabner705ecec2009-02-27 19:43:04 -08001193{
1194 int err;
1195 struct usb_line6 *line6 = &pod->line6;
1196
Markus Grabnere1a164d2010-08-23 01:08:25 +02001197 init_timer(&pod->startup_timer);
1198 INIT_WORK(&pod->startup_work, pod_startup5);
1199
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001200 if ((interface == NULL) || (pod == NULL))
1201 return -ENODEV;
Markus Grabner705ecec2009-02-27 19:43:04 -08001202
1203 pod->channel_num = 255;
1204
1205 /* initialize wait queues: */
1206 init_waitqueue_head(&pod->monitor_level.wait);
1207 init_waitqueue_head(&pod->routing.wait);
1208 init_waitqueue_head(&pod->tuner_mute.wait);
1209 init_waitqueue_head(&pod->tuner_freq.wait);
1210 init_waitqueue_head(&pod->tuner_note.wait);
1211 init_waitqueue_head(&pod->tuner_pitch.wait);
1212 init_waitqueue_head(&pod->clipping.wait);
1213
1214 memset(pod->param_dirty, 0xff, sizeof(pod->param_dirty));
1215
1216 /* initialize USB buffers: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001217 err = line6_dumpreq_init(&pod->dumpreq, pod_request_channel,
1218 sizeof(pod_request_channel));
1219 if (err < 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001220 dev_err(&interface->dev, "Out of memory\n");
Markus Grabner705ecec2009-02-27 19:43:04 -08001221 return -ENOMEM;
1222 }
1223
Markus Grabner705ecec2009-02-27 19:43:04 -08001224 /* create sysfs entries: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001225 err = pod_create_files2(&interface->dev);
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -07001226 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -08001227 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -08001228
1229 /* initialize audio system: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001230 err = line6_init_audio(line6);
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -07001231 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -08001232 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -08001233
1234 /* initialize MIDI subsystem: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001235 err = line6_init_midi(line6);
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -07001236 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -08001237 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -08001238
1239 /* initialize PCM subsystem: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001240 err = line6_init_pcm(line6, &pod_pcm_properties);
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
Markus Grabner1027f4762010-08-12 01:35:30 +02001244 /* register monitor control: */
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -07001245 err = snd_ctl_add(line6->card,
1246 snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
1247 if (err < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -08001248 return err;
Markus Grabner705ecec2009-02-27 19:43:04 -08001249
Markus Grabner1027f4762010-08-12 01:35:30 +02001250 /*
Markus Grabnere1a164d2010-08-23 01:08:25 +02001251 When the sound card is registered at this point, the PODxt Live
1252 displays "Invalid Code Error 07", so we do it later in the event
1253 handler.
1254 */
Markus Grabner1027f4762010-08-12 01:35:30 +02001255
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001256 if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) {
Markus Grabner1027f4762010-08-12 01:35:30 +02001257 pod->monitor_level.value = POD_system_invalid;
1258
1259 /* initiate startup procedure: */
1260 pod_startup1(pod);
Markus Grabner705ecec2009-02-27 19:43:04 -08001261 }
1262
1263 return 0;
1264}
1265
1266/*
Markus Grabner1027f4762010-08-12 01:35:30 +02001267 Init POD device (and clean up in case of failure).
1268*/
1269int line6_pod_init(struct usb_interface *interface, struct usb_line6_pod *pod)
1270{
1271 int err = pod_try_init(interface, pod);
1272
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -07001273 if (err < 0)
Markus Grabner1027f4762010-08-12 01:35:30 +02001274 pod_destruct(interface);
Markus Grabner1027f4762010-08-12 01:35:30 +02001275
1276 return err;
1277}
1278
1279/*
Markus Grabner705ecec2009-02-27 19:43:04 -08001280 POD device disconnected.
1281*/
Markus Grabner1027f4762010-08-12 01:35:30 +02001282void line6_pod_disconnect(struct usb_interface *interface)
Markus Grabner705ecec2009-02-27 19:43:04 -08001283{
1284 struct usb_line6_pod *pod;
1285
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001286 if (interface == NULL)
1287 return;
Markus Grabner705ecec2009-02-27 19:43:04 -08001288 pod = usb_get_intfdata(interface);
1289
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001290 if (pod != NULL) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001291 struct snd_line6_pcm *line6pcm = pod->line6.line6pcm;
1292 struct device *dev = &interface->dev;
1293
Greg Kroah-Hartman027360c2010-09-21 16:58:00 -07001294 if (line6pcm != NULL)
Markus Grabner1027f4762010-08-12 01:35:30 +02001295 line6_pcm_disconnect(line6pcm);
Markus Grabner705ecec2009-02-27 19:43:04 -08001296
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001297 if (dev != NULL) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001298 /* remove sysfs entries: */
Markus Grabnere1a164d2010-08-23 01:08:25 +02001299 line6_pod_remove_files(pod->firmware_version,
1300 pod->line6.
1301 properties->device_bit, dev);
Markus Grabner705ecec2009-02-27 19:43:04 -08001302
1303 device_remove_file(dev, &dev_attr_channel);
1304 device_remove_file(dev, &dev_attr_clip);
1305 device_remove_file(dev, &dev_attr_device_id);
1306 device_remove_file(dev, &dev_attr_dirty);
1307 device_remove_file(dev, &dev_attr_dump);
1308 device_remove_file(dev, &dev_attr_dump_buf);
1309 device_remove_file(dev, &dev_attr_finish);
1310 device_remove_file(dev, &dev_attr_firmware_version);
1311 device_remove_file(dev, &dev_attr_midi_postprocess);
1312 device_remove_file(dev, &dev_attr_monitor_level);
1313 device_remove_file(dev, &dev_attr_name);
1314 device_remove_file(dev, &dev_attr_name_buf);
1315 device_remove_file(dev, &dev_attr_retrieve_amp_setup);
1316 device_remove_file(dev, &dev_attr_retrieve_channel);
Markus Grabnere1a164d2010-08-23 01:08:25 +02001317 device_remove_file(dev,
1318 &dev_attr_retrieve_effects_setup);
Markus Grabner705ecec2009-02-27 19:43:04 -08001319 device_remove_file(dev, &dev_attr_routing);
1320 device_remove_file(dev, &dev_attr_serial_number);
1321 device_remove_file(dev, &dev_attr_store_amp_setup);
1322 device_remove_file(dev, &dev_attr_store_channel);
1323 device_remove_file(dev, &dev_attr_store_effects_setup);
1324 device_remove_file(dev, &dev_attr_tuner_freq);
1325 device_remove_file(dev, &dev_attr_tuner_mute);
1326 device_remove_file(dev, &dev_attr_tuner_note);
1327 device_remove_file(dev, &dev_attr_tuner_pitch);
1328
Markus Grabner1027f4762010-08-12 01:35:30 +02001329#ifdef CONFIG_LINE6_USB_RAW
Markus Grabner705ecec2009-02-27 19:43:04 -08001330 device_remove_file(dev, &dev_attr_raw);
1331#endif
1332 }
1333 }
1334
1335 pod_destruct(interface);
1336}