blob: 4983f2b51cf2df1e7cb5f9df5b539de4eecb7158 [file] [log] [blame]
Markus Grabner705ecec2009-02-27 19:43:04 -08001/*
2 * Line6 Linux USB driver - 0.8.0
3 *
4 * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, version 2.
9 *
10 */
11
12#include "driver.h"
13
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090014#include <linux/slab.h>
15
Markus Grabner705ecec2009-02-27 19:43:04 -080016#include "audio.h"
17#include "capture.h"
18#include "control.h"
19#include "playback.h"
20#include "pod.h"
21
22
23#define POD_SYSEX_CODE 3
24#define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
25
26
27enum {
28 POD_SYSEX_CLIP = 0x0f,
29 POD_SYSEX_SAVE = 0x24,
30 POD_SYSEX_SYSTEM = 0x56,
31 POD_SYSEX_SYSTEMREQ = 0x57,
32 /* POD_SYSEX_UPDATE = 0x6c, */ /* software update! */
33 POD_SYSEX_STORE = 0x71,
34 POD_SYSEX_FINISH = 0x72,
35 POD_SYSEX_DUMPMEM = 0x73,
36 POD_SYSEX_DUMP = 0x74,
37 POD_SYSEX_DUMPREQ = 0x75
38 /* POD_SYSEX_DUMPMEM2 = 0x76 */ /* dumps entire internal memory of PODxt Pro */
39};
40
41enum {
42 POD_monitor_level = 0x04,
43 POD_routing = 0x05,
44 POD_tuner_mute = 0x13,
45 POD_tuner_freq = 0x15,
46 POD_tuner_note = 0x16,
47 POD_tuner_pitch = 0x17,
48 POD_system_invalid = 0x7fff
49};
50
51enum {
52 POD_DUMP_MEMORY = 2
53};
54
55enum {
56 POD_BUSY_READ,
57 POD_BUSY_WRITE,
58 POD_CHANNEL_DIRTY,
59 POD_SAVE_PRESSED,
60 POD_BUSY_MIDISEND
61};
62
63
64static struct snd_ratden pod_ratden = {
65 .num_min = 78125,
66 .num_max = 78125,
67 .num_step = 1,
68 .den = 2
69};
70
71static struct line6_pcm_properties pod_pcm_properties = {
72 .snd_line6_playback_hw = {
73 .info = (SNDRV_PCM_INFO_MMAP |
74 SNDRV_PCM_INFO_INTERLEAVED |
75 SNDRV_PCM_INFO_BLOCK_TRANSFER |
76 SNDRV_PCM_INFO_MMAP_VALID |
77 SNDRV_PCM_INFO_PAUSE |
78 SNDRV_PCM_INFO_SYNC_START),
79 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
80 .rates = SNDRV_PCM_RATE_KNOT,
81 .rate_min = 39062,
82 .rate_max = 39063,
83 .channels_min = 2,
84 .channels_max = 2,
85 .buffer_bytes_max = 60000,
86 .period_bytes_min = LINE6_ISO_PACKET_SIZE_MAX * POD_BYTES_PER_FRAME, /* at least one URB must fit into one period */
87 .period_bytes_max = 8192,
88 .periods_min = 1,
89 .periods_max = 1024
90 },
91 .snd_line6_capture_hw = {
92 .info = (SNDRV_PCM_INFO_MMAP |
93 SNDRV_PCM_INFO_INTERLEAVED |
94 SNDRV_PCM_INFO_BLOCK_TRANSFER |
95 SNDRV_PCM_INFO_MMAP_VALID |
96 SNDRV_PCM_INFO_SYNC_START),
97 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
98 .rates = SNDRV_PCM_RATE_KNOT,
99 .rate_min = 39062,
100 .rate_max = 39063,
101 .channels_min = 2,
102 .channels_max = 2,
103 .buffer_bytes_max = 60000,
104 .period_bytes_min = LINE6_ISO_PACKET_SIZE_MAX * POD_BYTES_PER_FRAME, /* at least one URB must fit into one period */
105 .period_bytes_max = 8192,
106 .periods_min = 1,
107 .periods_max = 1024
108 },
109 .snd_line6_rates = {
110 .nrats = 1,
111 .rats = &pod_ratden
112 },
113 .bytes_per_frame = POD_BYTES_PER_FRAME
114};
115
116static const char pod_request_version[] = { 0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7 };
117static const char pod_request_channel[] = { 0xf0, 0x00, 0x01, 0x0c, 0x03, 0x75, 0xf7 };
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800118static const char pod_version_header[] = { 0xf2, 0x7e, 0x7f, 0x06, 0x02 };
Markus Grabner705ecec2009-02-27 19:43:04 -0800119
120
121/*
122 Mark all parameters as dirty and notify waiting processes.
123*/
124static void pod_mark_batch_all_dirty(struct usb_line6_pod *pod)
125{
126 int i;
127
Frederik Deweerdte1769b32009-09-14 08:51:38 +0000128 for (i = 0; i < POD_CONTROL_SIZE; i++)
Markus Grabner705ecec2009-02-27 19:43:04 -0800129 set_bit(i, pod->param_dirty);
130}
131
132/*
133 Send an asynchronous request for the POD firmware version and device ID.
134*/
135static int pod_version_request_async(struct usb_line6_pod *pod)
136{
137 return line6_send_raw_message_async(&pod->line6, pod->buffer_versionreq, sizeof(pod_request_version));
138}
139
Markus Grabner705ecec2009-02-27 19:43:04 -0800140static void pod_create_files_work(struct work_struct *work)
141{
142 struct usb_line6_pod *pod = container_of(work, struct usb_line6_pod, create_files_work);
Markus Grabner705ecec2009-02-27 19:43:04 -0800143
144 pod_create_files(pod->firmware_version, pod->line6.properties->device_bit, pod->line6.ifcdev);
145}
146
147static void pod_startup_timeout(unsigned long arg)
148{
149 enum {
150 REQUEST_NONE,
151 REQUEST_DUMP,
152 REQUEST_VERSION
153 };
154
155 int request = REQUEST_NONE;
156 struct usb_line6_pod *pod = (struct usb_line6_pod *)arg;
157
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800158 if (pod->dumpreq.ok) {
159 if (!pod->versionreq_ok)
Markus Grabner705ecec2009-02-27 19:43:04 -0800160 request = REQUEST_VERSION;
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800161 } else {
162 if (pod->versionreq_ok)
Markus Grabner705ecec2009-02-27 19:43:04 -0800163 request = REQUEST_DUMP;
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800164 else if (pod->startup_count++ & 1)
Markus Grabner705ecec2009-02-27 19:43:04 -0800165 request = REQUEST_DUMP;
166 else
167 request = REQUEST_VERSION;
168 }
169
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800170 switch (request) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800171 case REQUEST_DUMP:
172 line6_dump_request_async(&pod->dumpreq, &pod->line6, 0);
173 break;
174
175 case REQUEST_VERSION:
176 pod_version_request_async(pod);
177 break;
178
179 default:
180 return;
181 }
182
183 line6_startup_delayed(&pod->dumpreq, 1, pod_startup_timeout, pod);
184}
185
186static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code, int size)
187{
188 return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code, size);
189}
190
191/*
192 Send channel dump data to the PODxt Pro.
193*/
194static void pod_dump(struct usb_line6_pod *pod, const unsigned char *data)
195{
196 int size = 1 + sizeof(pod->prog_data);
197 char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_DUMP, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800198 if (!sysex)
199 return;
200 /* Don't know what this is good for, but PODxt Pro transmits it, so we
201 * also do... */
202 sysex[SYSEX_DATA_OFS] = 5;
Markus Grabner705ecec2009-02-27 19:43:04 -0800203 memcpy(sysex + SYSEX_DATA_OFS + 1, data, sizeof(pod->prog_data));
204 line6_send_sysex_message(&pod->line6, sysex, size);
205 memcpy(&pod->prog_data, data, sizeof(pod->prog_data));
206 pod_mark_batch_all_dirty(pod);
207 kfree(sysex);
208}
209
210/*
211 Store parameter value in driver memory and mark it as dirty.
212*/
213static void pod_store_parameter(struct usb_line6_pod *pod, int param, int value)
214{
215 pod->prog_data.control[param] = value;
216 set_bit(param, pod->param_dirty);
217 pod->dirty = 1;
218}
219
220/*
221 Handle SAVE button
222*/
223static void pod_save_button_pressed(struct usb_line6_pod *pod, int type, int index)
224{
225 pod->dirty = 0;
226 set_bit(POD_SAVE_PRESSED, &pod->atomic_flags);
227}
228
229/*
230 Process a completely received message.
231*/
232void pod_process_message(struct usb_line6_pod *pod)
233{
234 const unsigned char *buf = pod->line6.buffer_message;
235
236 /* filter messages by type */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800237 switch (buf[0] & 0xf0) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800238 case LINE6_PARAM_CHANGE:
239 case LINE6_PROGRAM_CHANGE:
240 case LINE6_SYSEX_BEGIN:
241 break; /* handle these further down */
242
243 default:
244 return; /* ignore all others */
245 }
246
247 /* process all remaining messages */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800248 switch (buf[0]) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800249 case LINE6_PARAM_CHANGE | LINE6_CHANNEL_DEVICE:
250 pod_store_parameter(pod, buf[1], buf[2]);
251 /* intentionally no break here! */
252
253 case LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST:
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800254 if ((buf[1] == POD_amp_model_setup) ||
255 (buf[1] == POD_effect_setup))
256 /* these also affect other settings */
Markus Grabner705ecec2009-02-27 19:43:04 -0800257 line6_dump_request_async(&pod->dumpreq, &pod->line6, 0);
258
259 break;
260
261 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE:
262 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST:
263 pod->channel_num = buf[1];
264 pod->dirty = 0;
265 set_bit(POD_CHANNEL_DIRTY, &pod->atomic_flags);
266 line6_dump_request_async(&pod->dumpreq, &pod->line6, 0);
267 break;
268
269 case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE:
270 case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN:
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800271 if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) == 0) {
272 switch (buf[5]) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800273 case POD_SYSEX_DUMP:
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800274 if (pod->line6.message_length == sizeof(pod->prog_data) + 7) {
275 switch (pod->dumpreq.in_progress) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800276 case LINE6_DUMP_CURRENT:
277 memcpy(&pod->prog_data, buf + 7, sizeof(pod->prog_data));
278 pod_mark_batch_all_dirty(pod);
279 pod->dumpreq.ok = 1;
280 break;
281
282 case POD_DUMP_MEMORY:
283 memcpy(&pod->prog_data_buf, buf + 7, sizeof(pod->prog_data_buf));
284 break;
285
286 default:
287 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "unknown dump code %02X\n", pod->dumpreq.in_progress));
288 }
289
290 line6_dump_finished(&pod->dumpreq);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800291 } else
Markus Grabner705ecec2009-02-27 19:43:04 -0800292 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "wrong size of channel dump message (%d instead of %d)\n",
293 pod->line6.message_length, (int)sizeof(pod->prog_data) + 7));
294
295 break;
296
297 case POD_SYSEX_SYSTEM: {
298 short value = ((int)buf[7] << 12) | ((int)buf[8] << 8) | ((int)buf[9] << 4) | (int)buf[10];
299
300#define PROCESS_SYSTEM_PARAM(x) \
301 case POD_ ## x: \
302 pod->x.value = value; \
303 wake_up_interruptible(&pod->x.wait); \
304 break;
305
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800306 switch (buf[6]) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800307 PROCESS_SYSTEM_PARAM(monitor_level);
308 PROCESS_SYSTEM_PARAM(routing);
309 PROCESS_SYSTEM_PARAM(tuner_mute);
310 PROCESS_SYSTEM_PARAM(tuner_freq);
311 PROCESS_SYSTEM_PARAM(tuner_note);
312 PROCESS_SYSTEM_PARAM(tuner_pitch);
313
314#undef PROCESS_SYSTEM_PARAM
315
316 default:
317 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "unknown tuner/system response %02X\n", buf[6]));
318 }
319
320 break;
321 }
322
323 case POD_SYSEX_FINISH:
324 /* do we need to respond to this? */
325 break;
326
327 case POD_SYSEX_SAVE:
328 pod_save_button_pressed(pod, buf[6], buf[7]);
329 break;
330
331 case POD_SYSEX_CLIP:
332 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "audio clipped\n"));
333 pod->clipping.value = 1;
334 wake_up_interruptible(&pod->clipping.wait);
335 break;
336
337 case POD_SYSEX_STORE:
338 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "message %02X not yet implemented\n", buf[5]));
339 break;
340
341 default:
342 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "unknown sysex message %02X\n", buf[5]));
343 }
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800344 } else if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {
345 if (pod->versionreq_ok == 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800346 pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];
347 pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) | (int)buf[10];
348 pod->versionreq_ok = 1;
349
350 /* Now we know the firmware version, so we schedule a bottom half
351 handler to create the special files: */
Markus Grabner705ecec2009-02-27 19:43:04 -0800352 INIT_WORK(&pod->create_files_work, pod_create_files_work);
Markus Grabner705ecec2009-02-27 19:43:04 -0800353 queue_work(line6_workqueue, &pod->create_files_work);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800354 } else
Markus Grabner705ecec2009-02-27 19:43:04 -0800355 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "multiple firmware version message\n"));
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800356 } else
Markus Grabner705ecec2009-02-27 19:43:04 -0800357 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "unknown sysex header\n"));
358
359 break;
360
361 case LINE6_SYSEX_END:
362 break;
363
364 default:
365 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "POD: unknown message %02X\n", buf[0]));
366 }
367}
368
369/*
370 Detect some cases that require a channel dump after sending a command to the
371 device. Important notes:
372 *) The actual dump request can not be sent here since we are not allowed to
373 wait for the completion of the first message in this context, and sending
374 the dump request before completion of the previous message leaves the POD
375 in an undefined state. The dump request will be sent when the echoed
376 commands are received.
377 *) This method fails if a param change message is "chopped" after the first
378 byte.
379*/
380void pod_midi_postprocess(struct usb_line6_pod *pod, unsigned char *data, int length)
381{
382 int i;
383
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800384 if (!pod->midi_postprocess)
Markus Grabner705ecec2009-02-27 19:43:04 -0800385 return;
386
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800387 for (i = 0; i < length; ++i) {
388 if (data[i] == (LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST)) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800389 line6_invalidate_current(&pod->dumpreq);
390 break;
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800391 } else if ((data[i] == (LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST)) && (i < length - 1))
392 if ((data[i + 1] == POD_amp_model_setup) || (data[i + 1] == POD_effect_setup)) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800393 line6_invalidate_current(&pod->dumpreq);
394 break;
395 }
396 }
397}
398
399/*
400 Send channel number (i.e., switch to a different sound).
401*/
Greg Kroah-Hartmanb702ed252009-02-27 20:45:03 -0800402static void pod_send_channel(struct usb_line6_pod *pod, int value)
Markus Grabner705ecec2009-02-27 19:43:04 -0800403{
404 line6_invalidate_current(&pod->dumpreq);
405
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800406 if (line6_send_program(&pod->line6, value) == 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800407 pod->channel_num = value;
408 else
409 line6_dump_finished(&pod->dumpreq);
410}
411
412/*
413 Transmit PODxt Pro control parameter.
414*/
415void pod_transmit_parameter(struct usb_line6_pod *pod, int param, int value)
416{
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800417 if (line6_transmit_parameter(&pod->line6, param, value) == 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800418 pod_store_parameter(pod, param, value);
419
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800420 if ((param == POD_amp_model_setup) || (param == POD_effect_setup)) /* these also affect other settings */
Markus Grabner705ecec2009-02-27 19:43:04 -0800421 line6_invalidate_current(&pod->dumpreq);
422}
423
424/*
425 Resolve value to memory location.
426*/
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600427static int pod_resolve(const char *buf, short block0, short block1, unsigned char *location)
Markus Grabner705ecec2009-02-27 19:43:04 -0800428{
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600429 unsigned long value;
430 short block;
431 int ret;
432
433 ret = strict_strtoul(buf, 10, &value);
434 if (ret)
435 return ret;
436
437 block = (value < 0x40) ? block0 : block1;
Markus Grabner705ecec2009-02-27 19:43:04 -0800438 value &= 0x3f;
439 location[0] = block >> 7;
440 location[1] = value | (block & 0x7f);
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600441 return 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800442}
443
444/*
445 Send command to store channel/effects setup/amp setup to PODxt Pro.
446*/
447static ssize_t pod_send_store_command(struct device *dev, const char *buf, size_t count, short block0, short block1)
448{
449 struct usb_interface *interface = to_usb_interface(dev);
450 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600451 int ret;
Markus Grabner705ecec2009-02-27 19:43:04 -0800452 int size = 3 + sizeof(pod->prog_data_buf);
453 char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_STORE, size);
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600454
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800455 if (!sysex)
456 return 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800457
458 sysex[SYSEX_DATA_OFS] = 5; /* see pod_dump() */
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600459 ret = pod_resolve(buf, block0, block1, sysex + SYSEX_DATA_OFS + 1);
460 if (ret) {
461 kfree(sysex);
462 return ret;
463 }
464
Markus Grabner705ecec2009-02-27 19:43:04 -0800465 memcpy(sysex + SYSEX_DATA_OFS + 3, &pod->prog_data_buf, sizeof(pod->prog_data_buf));
466
467 line6_send_sysex_message(&pod->line6, sysex, size);
468 kfree(sysex);
469 /* needs some delay here on AMD64 platform */
470 return count;
471}
472
473/*
474 Send command to retrieve channel/effects setup/amp setup to PODxt Pro.
475*/
476static ssize_t pod_send_retrieve_command(struct device *dev, const char *buf, size_t count, short block0, short block1)
477{
478 struct usb_interface *interface = to_usb_interface(dev);
479 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600480 int ret;
Markus Grabner705ecec2009-02-27 19:43:04 -0800481 int size = 4;
482 char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_DUMPMEM, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800483
484 if (!sysex)
485 return 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800486
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600487 ret = pod_resolve(buf, block0, block1, sysex + SYSEX_DATA_OFS);
488 if (ret) {
489 kfree(sysex);
490 return ret;
491 }
Markus Grabner705ecec2009-02-27 19:43:04 -0800492 sysex[SYSEX_DATA_OFS + 2] = 0;
493 sysex[SYSEX_DATA_OFS + 3] = 0;
494 line6_dump_started(&pod->dumpreq, POD_DUMP_MEMORY);
495
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800496 if (line6_send_sysex_message(&pod->line6, sysex, size) < size)
Markus Grabner705ecec2009-02-27 19:43:04 -0800497 line6_dump_finished(&pod->dumpreq);
498
499 kfree(sysex);
500 /* needs some delay here on AMD64 platform */
501 return count;
502}
503
504/*
505 Generic get name function.
506*/
507static ssize_t get_name_generic(struct usb_line6_pod *pod, const char *str, char *buf)
508{
509 int length = 0;
510 const char *p1;
511 char *p2;
512 char *last_non_space = buf;
513
514 int retval = line6_wait_dump(&pod->dumpreq, 0);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800515 if (retval < 0)
516 return retval;
Markus Grabner705ecec2009-02-27 19:43:04 -0800517
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800518 for (p1 = str, p2 = buf; *p1; ++p1, ++p2) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800519 *p2 = *p1;
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800520 if (*p2 != ' ')
521 last_non_space = p2;
522 if (++length == POD_NAME_LENGTH)
523 break;
Markus Grabner705ecec2009-02-27 19:43:04 -0800524 }
525
526 *(last_non_space + 1) = '\n';
527 return last_non_space - buf + 2;
528}
529
530/*
531 "read" request on "channel" special file.
532*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800533static ssize_t pod_get_channel(struct device *dev,
534 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800535{
536 struct usb_interface *interface = to_usb_interface(dev);
537 struct usb_line6_pod *pod = usb_get_intfdata(interface);
538 return sprintf(buf, "%d\n", pod->channel_num);
539}
540
541/*
542 "write" request on "channel" special file.
543*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800544static ssize_t pod_set_channel(struct device *dev,
545 struct device_attribute *attr,
546 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800547{
548 struct usb_interface *interface = to_usb_interface(dev);
549 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600550 unsigned long value;
551 int ret;
552
553 ret = strict_strtoul(buf, 10, &value);
554 if (ret)
555 return ret;
556
Markus Grabner705ecec2009-02-27 19:43:04 -0800557 pod_send_channel(pod, value);
558 return count;
559}
560
561/*
562 "read" request on "name" special file.
563*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800564static ssize_t pod_get_name(struct device *dev, struct device_attribute *attr,
565 char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800566{
567 struct usb_interface *interface = to_usb_interface(dev);
568 struct usb_line6_pod *pod = usb_get_intfdata(interface);
569 return get_name_generic(pod, pod->prog_data.header + POD_NAME_OFFSET, buf);
570}
571
572/*
573 "read" request on "name" special file.
574*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800575static ssize_t pod_get_name_buf(struct device *dev,
576 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800577{
578 struct usb_interface *interface = to_usb_interface(dev);
579 struct usb_line6_pod *pod = usb_get_intfdata(interface);
580 return get_name_generic(pod, pod->prog_data_buf.header + POD_NAME_OFFSET, buf);
581}
582
583/*
584 "read" request on "dump" special file.
585*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800586static ssize_t pod_get_dump(struct device *dev, struct device_attribute *attr,
587 char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800588{
589 struct usb_interface *interface = to_usb_interface(dev);
590 struct usb_line6_pod *pod = usb_get_intfdata(interface);
591 int retval = line6_wait_dump(&pod->dumpreq, 0);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800592 if (retval < 0)
593 return retval;
Markus Grabner705ecec2009-02-27 19:43:04 -0800594 memcpy(buf, &pod->prog_data, sizeof(pod->prog_data));
595 return sizeof(pod->prog_data);
596}
597
598/*
599 "write" request on "dump" special file.
600*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800601static ssize_t pod_set_dump(struct device *dev, struct device_attribute *attr,
602 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800603{
604 struct usb_interface *interface = to_usb_interface(dev);
605 struct usb_line6_pod *pod = usb_get_intfdata(interface);
606
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800607 if (count != sizeof(pod->prog_data)) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800608 dev_err(pod->line6.ifcdev,
Randy Dunlap034f5852009-11-12 15:46:01 -0800609 "data block must be exactly %zu bytes\n",
Frederik Deweerdte1769b32009-09-14 08:51:38 +0000610 sizeof(pod->prog_data));
Markus Grabner705ecec2009-02-27 19:43:04 -0800611 return -EINVAL;
612 }
613
614 pod_dump(pod, buf);
615 return sizeof(pod->prog_data);
616}
617
618/*
619 Request system parameter.
620 @param tuner non-zero, if code refers to a tuner parameter
621*/
622static ssize_t pod_get_system_param(struct usb_line6_pod *pod, char *buf, int code, struct ValueWait *param, int tuner, int sign)
623{
624 char *sysex;
625 int value;
626 static const int size = 1;
627 int retval = 0;
628 DECLARE_WAITQUEUE(wait, current);
629
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800630 if (((pod->prog_data.control[POD_tuner] & 0x40) == 0) && tuner)
Markus Grabner705ecec2009-02-27 19:43:04 -0800631 return -ENODEV;
632
633 /* send value request to tuner: */
634 param->value = POD_system_invalid;
635 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEMREQ, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800636 if (!sysex)
637 return 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800638 sysex[SYSEX_DATA_OFS] = code;
639 line6_send_sysex_message(&pod->line6, sysex, size);
640 kfree(sysex);
641
642 /* wait for tuner to respond: */
643 add_wait_queue(&param->wait, &wait);
644 current->state = TASK_INTERRUPTIBLE;
645
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800646 while (param->value == POD_system_invalid) {
647 if (signal_pending(current)) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800648 retval = -ERESTARTSYS;
649 break;
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800650 } else
Markus Grabner705ecec2009-02-27 19:43:04 -0800651 schedule();
652 }
653
654 current->state = TASK_RUNNING;
655 remove_wait_queue(&param->wait, &wait);
656
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800657 if (retval < 0)
Markus Grabner705ecec2009-02-27 19:43:04 -0800658 return retval;
659
660 value = sign ? (int)(signed short)param->value : (int)(unsigned short)param->value;
661 return sprintf(buf, "%d\n", value);
662}
663
664/*
665 Send system parameter.
666 @param tuner non-zero, if code refers to a tuner parameter
667*/
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800668static ssize_t pod_set_system_param(struct usb_line6_pod *pod, const char *buf,
669 int count, int code, unsigned short mask,
670 int tuner)
Markus Grabner705ecec2009-02-27 19:43:04 -0800671{
672 char *sysex;
673 static const int size = 5;
674 unsigned short value;
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600675 unsigned long result;
676 int ret;
Markus Grabner705ecec2009-02-27 19:43:04 -0800677
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800678 if (((pod->prog_data.control[POD_tuner] & 0x40) == 0) && tuner)
Markus Grabner705ecec2009-02-27 19:43:04 -0800679 return -EINVAL;
680
681 /* send value to tuner: */
682 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800683 if (!sysex)
684 return 0;
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600685
686 ret = strict_strtoul(buf, 10, &result);
687 if (ret)
688 return ret;
689
690 value = result & mask;
Markus Grabner705ecec2009-02-27 19:43:04 -0800691 sysex[SYSEX_DATA_OFS] = code;
692 sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
693 sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
694 sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
695 sysex[SYSEX_DATA_OFS + 4] = (value ) & 0x0f;
696 line6_send_sysex_message(&pod->line6, sysex, size);
697 kfree(sysex);
698 return count;
699}
700
701/*
702 "read" request on "dump_buf" special file.
703*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800704static ssize_t pod_get_dump_buf(struct device *dev,
705 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800706{
707 struct usb_interface *interface = to_usb_interface(dev);
708 struct usb_line6_pod *pod = usb_get_intfdata(interface);
709 int retval = line6_wait_dump(&pod->dumpreq, 0);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800710 if (retval < 0)
711 return retval;
Markus Grabner705ecec2009-02-27 19:43:04 -0800712 memcpy(buf, &pod->prog_data_buf, sizeof(pod->prog_data_buf));
713 return sizeof(pod->prog_data_buf);
714}
715
716/*
717 "write" request on "dump_buf" special file.
718*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800719static ssize_t pod_set_dump_buf(struct device *dev,
720 struct device_attribute *attr,
721 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800722{
723 struct usb_interface *interface = to_usb_interface(dev);
724 struct usb_line6_pod *pod = usb_get_intfdata(interface);
725
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800726 if (count != sizeof(pod->prog_data)) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800727 dev_err(pod->line6.ifcdev,
Randy Dunlap034f5852009-11-12 15:46:01 -0800728 "data block must be exactly %zu bytes\n",
Frederik Deweerdte1769b32009-09-14 08:51:38 +0000729 sizeof(pod->prog_data));
Markus Grabner705ecec2009-02-27 19:43:04 -0800730 return -EINVAL;
731 }
732
733 memcpy(&pod->prog_data_buf, buf, sizeof(pod->prog_data));
734 return sizeof(pod->prog_data);
735}
736
737/*
738 "write" request on "finish" special file.
739*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800740static ssize_t pod_set_finish(struct device *dev,
741 struct device_attribute *attr,
742 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800743{
744 struct usb_interface *interface = to_usb_interface(dev);
745 struct usb_line6_pod *pod = usb_get_intfdata(interface);
746 int size = 0;
747 char *sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_FINISH, size);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800748 if (!sysex)
749 return 0;
Markus Grabner705ecec2009-02-27 19:43:04 -0800750 line6_send_sysex_message(&pod->line6, sysex, size);
751 kfree(sysex);
752 return count;
753}
754
755/*
756 "write" request on "store_channel" special file.
757*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800758static ssize_t pod_set_store_channel(struct device *dev,
759 struct device_attribute *attr,
760 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800761{
762 return pod_send_store_command(dev, buf, count, 0x0000, 0x00c0);
763}
764
765/*
766 "write" request on "store_effects_setup" special file.
767*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800768static ssize_t pod_set_store_effects_setup(struct device *dev,
769 struct device_attribute *attr,
770 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800771{
772 return pod_send_store_command(dev, buf, count, 0x0080, 0x0080);
773}
774
775/*
776 "write" request on "store_amp_setup" special file.
777*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800778static ssize_t pod_set_store_amp_setup(struct device *dev,
779 struct device_attribute *attr,
780 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800781{
782 return pod_send_store_command(dev, buf, count, 0x0040, 0x0100);
783}
784
785/*
786 "write" request on "retrieve_channel" special file.
787*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800788static ssize_t pod_set_retrieve_channel(struct device *dev,
789 struct device_attribute *attr,
790 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800791{
792 return pod_send_retrieve_command(dev, buf, count, 0x0000, 0x00c0);
793}
794
795/*
796 "write" request on "retrieve_effects_setup" special file.
797*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800798static ssize_t pod_set_retrieve_effects_setup(struct device *dev,
799 struct device_attribute *attr,
800 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800801{
802 return pod_send_retrieve_command(dev, buf, count, 0x0080, 0x0080);
803}
804
805/*
806 "write" request on "retrieve_amp_setup" special file.
807*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800808static ssize_t pod_set_retrieve_amp_setup(struct device *dev,
809 struct device_attribute *attr,
810 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800811{
812 return pod_send_retrieve_command(dev, buf, count, 0x0040, 0x0100);
813}
814
815/*
816 "read" request on "dirty" special file.
817*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800818static ssize_t pod_get_dirty(struct device *dev, struct device_attribute *attr,
819 char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800820{
821 struct usb_interface *interface = to_usb_interface(dev);
822 struct usb_line6_pod *pod = usb_get_intfdata(interface);
823 buf[0] = pod->dirty ? '1' : '0';
824 buf[1] = '\n';
825 return 2;
826}
827
828/*
829 "read" request on "midi_postprocess" special file.
830*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800831static ssize_t pod_get_midi_postprocess(struct device *dev,
832 struct device_attribute *attr,
833 char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800834{
835 struct usb_interface *interface = to_usb_interface(dev);
836 struct usb_line6_pod *pod = usb_get_intfdata(interface);
837 return sprintf(buf, "%d\n", pod->midi_postprocess);
838}
839
840/*
841 "write" request on "midi_postprocess" special file.
842*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800843static ssize_t pod_set_midi_postprocess(struct device *dev,
844 struct device_attribute *attr,
845 const char *buf, size_t count)
Markus Grabner705ecec2009-02-27 19:43:04 -0800846{
847 struct usb_interface *interface = to_usb_interface(dev);
848 struct usb_line6_pod *pod = usb_get_intfdata(interface);
Shawn Bohrer7e4d5c12009-11-15 22:18:01 -0600849 unsigned long value;
850 int ret;
851
852 ret = strict_strtoul(buf, 10, &value);
853 if (ret)
854 return ret;
855
Markus Grabner705ecec2009-02-27 19:43:04 -0800856 pod->midi_postprocess = value ? 1 : 0;
857 return count;
858}
859
860/*
861 "read" request on "serial_number" special file.
862*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800863static ssize_t pod_get_serial_number(struct device *dev,
864 struct device_attribute *attr, 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->serial_number);
869}
870
871/*
872 "read" request on "firmware_version" special file.
873*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800874static ssize_t pod_get_firmware_version(struct device *dev,
875 struct device_attribute *attr,
876 char *buf)
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);
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800880 return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
881 pod->firmware_version % 100);
Markus Grabner705ecec2009-02-27 19:43:04 -0800882}
883
884/*
885 "read" request on "device_id" special file.
886*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800887static ssize_t pod_get_device_id(struct device *dev,
888 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800889{
890 struct usb_interface *interface = to_usb_interface(dev);
891 struct usb_line6_pod *pod = usb_get_intfdata(interface);
892 return sprintf(buf, "%d\n", pod->device_id);
893}
894
895/*
896 "read" request on "clip" special file.
897*/
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800898static ssize_t pod_wait_for_clip(struct device *dev,
899 struct device_attribute *attr, char *buf)
Markus Grabner705ecec2009-02-27 19:43:04 -0800900{
901 struct usb_interface *interface = to_usb_interface(dev);
902 struct usb_line6_pod *pod = usb_get_intfdata(interface);
903 int err = 0;
904 DECLARE_WAITQUEUE(wait, current);
905 pod->clipping.value = 0;
906 add_wait_queue(&pod->clipping.wait, &wait);
907 current->state = TASK_INTERRUPTIBLE;
908
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800909 while (pod->clipping.value == 0) {
910 if (signal_pending(current)) {
Markus Grabner705ecec2009-02-27 19:43:04 -0800911 err = -ERESTARTSYS;
912 break;
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800913 } else
Markus Grabner705ecec2009-02-27 19:43:04 -0800914 schedule();
915 }
916
917 current->state = TASK_RUNNING;
918 remove_wait_queue(&pod->clipping.wait, &wait);
919 return err;
920}
921
922#define POD_GET_SYSTEM_PARAM(code, tuner, sign) \
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800923static ssize_t pod_get_ ## code(struct device *dev, \
924 struct device_attribute *attr, char *buf) \
Markus Grabner705ecec2009-02-27 19:43:04 -0800925{ \
926 struct usb_interface *interface = to_usb_interface(dev); \
927 struct usb_line6_pod *pod = usb_get_intfdata(interface); \
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800928 return pod_get_system_param(pod, buf, POD_ ## code, &pod->code, \
929 tuner, sign); \
Markus Grabner705ecec2009-02-27 19:43:04 -0800930}
931
932#define POD_GET_SET_SYSTEM_PARAM(code, mask, tuner, sign) \
933POD_GET_SYSTEM_PARAM(code, tuner, sign) \
Greg Kroah-Hartman77491e52009-02-27 20:25:43 -0800934static ssize_t pod_set_ ## code(struct device *dev, \
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800935 struct device_attribute *attr, \
936 const char *buf, size_t count) \
Markus Grabner705ecec2009-02-27 19:43:04 -0800937{ \
938 struct usb_interface *interface = to_usb_interface(dev); \
939 struct usb_line6_pod *pod = usb_get_intfdata(interface); \
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800940 return pod_set_system_param(pod, buf, count, POD_ ## code, mask, \
941 tuner); \
Markus Grabner705ecec2009-02-27 19:43:04 -0800942}
943
944POD_GET_SET_SYSTEM_PARAM(monitor_level, 0xffff, 0, 0);
945POD_GET_SET_SYSTEM_PARAM(routing, 0x0003, 0, 0);
946POD_GET_SET_SYSTEM_PARAM(tuner_mute, 0x0001, 1, 0);
947POD_GET_SET_SYSTEM_PARAM(tuner_freq, 0xffff, 1, 0);
948POD_GET_SYSTEM_PARAM(tuner_note, 1, 1);
949POD_GET_SYSTEM_PARAM(tuner_pitch, 1, 1);
950
951#undef GET_SET_SYSTEM_PARAM
952#undef GET_SYSTEM_PARAM
953
954/* POD special files: */
955static DEVICE_ATTR(channel, S_IWUGO | S_IRUGO, pod_get_channel, pod_set_channel);
956static DEVICE_ATTR(clip, S_IRUGO, pod_wait_for_clip, line6_nop_write);
957static DEVICE_ATTR(device_id, S_IRUGO, pod_get_device_id, line6_nop_write);
958static DEVICE_ATTR(dirty, S_IRUGO, pod_get_dirty, line6_nop_write);
959static DEVICE_ATTR(dump, S_IWUGO | S_IRUGO, pod_get_dump, pod_set_dump);
960static DEVICE_ATTR(dump_buf, S_IWUGO | S_IRUGO, pod_get_dump_buf, pod_set_dump_buf);
961static DEVICE_ATTR(finish, S_IWUGO, line6_nop_read, pod_set_finish);
962static DEVICE_ATTR(firmware_version, S_IRUGO, pod_get_firmware_version, line6_nop_write);
963static DEVICE_ATTR(midi_postprocess, S_IWUGO | S_IRUGO, pod_get_midi_postprocess, pod_set_midi_postprocess);
964static DEVICE_ATTR(monitor_level, S_IWUGO | S_IRUGO, pod_get_monitor_level, pod_set_monitor_level);
965static DEVICE_ATTR(name, S_IRUGO, pod_get_name, line6_nop_write);
966static DEVICE_ATTR(name_buf, S_IRUGO, pod_get_name_buf, line6_nop_write);
967static DEVICE_ATTR(retrieve_amp_setup, S_IWUGO, line6_nop_read, pod_set_retrieve_amp_setup);
968static DEVICE_ATTR(retrieve_channel, S_IWUGO, line6_nop_read, pod_set_retrieve_channel);
969static DEVICE_ATTR(retrieve_effects_setup, S_IWUGO, line6_nop_read, pod_set_retrieve_effects_setup);
970static DEVICE_ATTR(routing, S_IWUGO | S_IRUGO, pod_get_routing, pod_set_routing);
971static DEVICE_ATTR(serial_number, S_IRUGO, pod_get_serial_number, line6_nop_write);
972static DEVICE_ATTR(store_amp_setup, S_IWUGO, line6_nop_read, pod_set_store_amp_setup);
973static DEVICE_ATTR(store_channel, S_IWUGO, line6_nop_read, pod_set_store_channel);
974static DEVICE_ATTR(store_effects_setup, S_IWUGO, line6_nop_read, pod_set_store_effects_setup);
975static DEVICE_ATTR(tuner_freq, S_IWUGO | S_IRUGO, pod_get_tuner_freq, pod_set_tuner_freq);
976static DEVICE_ATTR(tuner_mute, S_IWUGO | S_IRUGO, pod_get_tuner_mute, pod_set_tuner_mute);
977static DEVICE_ATTR(tuner_note, S_IRUGO, pod_get_tuner_note, line6_nop_write);
978static DEVICE_ATTR(tuner_pitch, S_IRUGO, pod_get_tuner_pitch, line6_nop_write);
979
980#if CREATE_RAW_FILE
981static DEVICE_ATTR(raw, S_IWUGO, line6_nop_read, line6_set_raw);
982#endif
983
984/*
985 POD destructor.
986*/
987static void pod_destruct(struct usb_interface *interface)
988{
989 struct usb_line6_pod *pod = usb_get_intfdata(interface);
990 struct usb_line6 *line6;
991
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800992 if (pod == NULL)
993 return;
Markus Grabner705ecec2009-02-27 19:43:04 -0800994 line6 = &pod->line6;
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -0800995 if (line6 == NULL)
996 return;
Markus Grabner705ecec2009-02-27 19:43:04 -0800997 line6_cleanup_audio(line6);
998
999 /* free dump request data: */
1000 line6_dumpreq_destruct(&pod->dumpreq);
1001
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001002 kfree(pod->buffer_versionreq);
Markus Grabner705ecec2009-02-27 19:43:04 -08001003}
1004
1005/*
1006 Create sysfs entries.
1007*/
Greg Kroah-Hartmanb702ed252009-02-27 20:45:03 -08001008static int pod_create_files2(struct device *dev)
Markus Grabner705ecec2009-02-27 19:43:04 -08001009{
1010 int err;
1011
1012 CHECK_RETURN(device_create_file(dev, &dev_attr_channel));
1013 CHECK_RETURN(device_create_file(dev, &dev_attr_clip));
1014 CHECK_RETURN(device_create_file(dev, &dev_attr_device_id));
1015 CHECK_RETURN(device_create_file(dev, &dev_attr_dirty));
1016 CHECK_RETURN(device_create_file(dev, &dev_attr_dump));
1017 CHECK_RETURN(device_create_file(dev, &dev_attr_dump_buf));
1018 CHECK_RETURN(device_create_file(dev, &dev_attr_finish));
1019 CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version));
1020 CHECK_RETURN(device_create_file(dev, &dev_attr_midi_postprocess));
1021 CHECK_RETURN(device_create_file(dev, &dev_attr_monitor_level));
1022 CHECK_RETURN(device_create_file(dev, &dev_attr_name));
1023 CHECK_RETURN(device_create_file(dev, &dev_attr_name_buf));
1024 CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_amp_setup));
1025 CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_channel));
1026 CHECK_RETURN(device_create_file(dev, &dev_attr_retrieve_effects_setup));
1027 CHECK_RETURN(device_create_file(dev, &dev_attr_routing));
1028 CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number));
1029 CHECK_RETURN(device_create_file(dev, &dev_attr_store_amp_setup));
1030 CHECK_RETURN(device_create_file(dev, &dev_attr_store_channel));
1031 CHECK_RETURN(device_create_file(dev, &dev_attr_store_effects_setup));
1032 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_freq));
1033 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_mute));
1034 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_note));
1035 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_pitch));
1036
1037#if CREATE_RAW_FILE
1038 CHECK_RETURN(device_create_file(dev, &dev_attr_raw));
1039#endif
1040
1041 return 0;
1042}
1043
1044/*
1045 Init POD device.
1046*/
1047int pod_init(struct usb_interface *interface, struct usb_line6_pod *pod)
1048{
1049 int err;
1050 struct usb_line6 *line6 = &pod->line6;
1051
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001052 if ((interface == NULL) || (pod == NULL))
1053 return -ENODEV;
Markus Grabner705ecec2009-02-27 19:43:04 -08001054
1055 pod->channel_num = 255;
1056
1057 /* initialize wait queues: */
1058 init_waitqueue_head(&pod->monitor_level.wait);
1059 init_waitqueue_head(&pod->routing.wait);
1060 init_waitqueue_head(&pod->tuner_mute.wait);
1061 init_waitqueue_head(&pod->tuner_freq.wait);
1062 init_waitqueue_head(&pod->tuner_note.wait);
1063 init_waitqueue_head(&pod->tuner_pitch.wait);
1064 init_waitqueue_head(&pod->clipping.wait);
1065
1066 memset(pod->param_dirty, 0xff, sizeof(pod->param_dirty));
1067
1068 /* initialize USB buffers: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001069 err = line6_dumpreq_init(&pod->dumpreq, pod_request_channel,
1070 sizeof(pod_request_channel));
1071 if (err < 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001072 dev_err(&interface->dev, "Out of memory\n");
1073 pod_destruct(interface);
1074 return -ENOMEM;
1075 }
1076
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001077 pod->buffer_versionreq = kmalloc(sizeof(pod_request_version),
1078 GFP_KERNEL);
Markus Grabner705ecec2009-02-27 19:43:04 -08001079
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001080 if (pod->buffer_versionreq == NULL) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001081 dev_err(&interface->dev, "Out of memory\n");
1082 pod_destruct(interface);
1083 return -ENOMEM;
1084 }
1085
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001086 memcpy(pod->buffer_versionreq, pod_request_version,
1087 sizeof(pod_request_version));
Markus Grabner705ecec2009-02-27 19:43:04 -08001088
1089 /* create sysfs entries: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001090 err = pod_create_files2(&interface->dev);
1091 if (err < 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001092 pod_destruct(interface);
1093 return err;
1094 }
1095
1096 /* initialize audio system: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001097 err = line6_init_audio(line6);
1098 if (err < 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001099 pod_destruct(interface);
1100 return err;
1101 }
1102
1103 /* initialize MIDI subsystem: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001104 err = line6_init_midi(line6);
1105 if (err < 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001106 pod_destruct(interface);
1107 return err;
1108 }
1109
1110 /* initialize PCM subsystem: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001111 err = line6_init_pcm(line6, &pod_pcm_properties);
1112 if (err < 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001113 pod_destruct(interface);
1114 return err;
1115 }
1116
1117 /* register audio system: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001118 err = line6_register_audio(line6);
1119 if (err < 0) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001120 pod_destruct(interface);
1121 return err;
1122 }
1123
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001124 if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001125 /* query some data: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001126 line6_startup_delayed(&pod->dumpreq, POD_STARTUP_DELAY,
1127 pod_startup_timeout, pod);
Markus Grabner705ecec2009-02-27 19:43:04 -08001128 line6_read_serial_number(&pod->line6, &pod->serial_number);
1129 }
1130
1131 return 0;
1132}
1133
1134/*
1135 POD device disconnected.
1136*/
1137void pod_disconnect(struct usb_interface *interface)
1138{
1139 struct usb_line6_pod *pod;
1140
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001141 if (interface == NULL)
1142 return;
Markus Grabner705ecec2009-02-27 19:43:04 -08001143 pod = usb_get_intfdata(interface);
1144
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001145 if (pod != NULL) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001146 struct snd_line6_pcm *line6pcm = pod->line6.line6pcm;
1147 struct device *dev = &interface->dev;
1148
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001149 if (line6pcm != NULL) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001150 unlink_wait_clear_audio_out_urbs(line6pcm);
1151 unlink_wait_clear_audio_in_urbs(line6pcm);
1152 }
1153
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001154 if (dev != NULL) {
Markus Grabner705ecec2009-02-27 19:43:04 -08001155 /* remove sysfs entries: */
Greg Kroah-Hartman0fdef362009-02-27 22:41:29 -08001156 if (pod->versionreq_ok)
Markus Grabner705ecec2009-02-27 19:43:04 -08001157 pod_remove_files(pod->firmware_version, pod->line6.properties->device_bit, dev);
1158
1159 device_remove_file(dev, &dev_attr_channel);
1160 device_remove_file(dev, &dev_attr_clip);
1161 device_remove_file(dev, &dev_attr_device_id);
1162 device_remove_file(dev, &dev_attr_dirty);
1163 device_remove_file(dev, &dev_attr_dump);
1164 device_remove_file(dev, &dev_attr_dump_buf);
1165 device_remove_file(dev, &dev_attr_finish);
1166 device_remove_file(dev, &dev_attr_firmware_version);
1167 device_remove_file(dev, &dev_attr_midi_postprocess);
1168 device_remove_file(dev, &dev_attr_monitor_level);
1169 device_remove_file(dev, &dev_attr_name);
1170 device_remove_file(dev, &dev_attr_name_buf);
1171 device_remove_file(dev, &dev_attr_retrieve_amp_setup);
1172 device_remove_file(dev, &dev_attr_retrieve_channel);
1173 device_remove_file(dev, &dev_attr_retrieve_effects_setup);
1174 device_remove_file(dev, &dev_attr_routing);
1175 device_remove_file(dev, &dev_attr_serial_number);
1176 device_remove_file(dev, &dev_attr_store_amp_setup);
1177 device_remove_file(dev, &dev_attr_store_channel);
1178 device_remove_file(dev, &dev_attr_store_effects_setup);
1179 device_remove_file(dev, &dev_attr_tuner_freq);
1180 device_remove_file(dev, &dev_attr_tuner_mute);
1181 device_remove_file(dev, &dev_attr_tuner_note);
1182 device_remove_file(dev, &dev_attr_tuner_pitch);
1183
1184#if CREATE_RAW_FILE
1185 device_remove_file(dev, &dev_attr_raw);
1186#endif
1187 }
1188 }
1189
1190 pod_destruct(interface);
1191}