staging: line6: avoid CamelCase POD_* enums in pod.c
[deliverable/linux.git] / drivers / staging / line6 / pod.c
1 /*
2 * Line6 Linux USB driver - 0.9.1beta
3 *
4 * Copyright (C) 2004-2010 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 <linux/slab.h>
13 #include <linux/wait.h>
14 #include <sound/control.h>
15
16 #include "audio.h"
17 #include "capture.h"
18 #include "driver.h"
19 #include "playback.h"
20 #include "pod.h"
21
22 #define POD_SYSEX_CODE 3
23 #define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
24
25 /* *INDENT-OFF* */
26
27 enum {
28 POD_SYSEX_SAVE = 0x24,
29 POD_SYSEX_SYSTEM = 0x56,
30 POD_SYSEX_SYSTEMREQ = 0x57,
31 /* POD_SYSEX_UPDATE = 0x6c, */ /* software update! */
32 POD_SYSEX_STORE = 0x71,
33 POD_SYSEX_FINISH = 0x72,
34 POD_SYSEX_DUMPMEM = 0x73,
35 POD_SYSEX_DUMP = 0x74,
36 POD_SYSEX_DUMPREQ = 0x75
37
38 /* dumps entire internal memory of PODxt Pro */
39 /* POD_SYSEX_DUMPMEM2 = 0x76 */
40 };
41
42 enum {
43 POD_MONITOR_LEVEL = 0x04,
44 POD_SYSTEM_INVALID = 0x10000
45 };
46
47 /* *INDENT-ON* */
48
49 enum {
50 POD_DUMP_MEMORY = 2
51 };
52
53 enum {
54 POD_BUSY_READ,
55 POD_BUSY_WRITE,
56 POD_CHANNEL_DIRTY,
57 POD_SAVE_PRESSED,
58 POD_BUSY_MIDISEND
59 };
60
61 static struct snd_ratden pod_ratden = {
62 .num_min = 78125,
63 .num_max = 78125,
64 .num_step = 1,
65 .den = 2
66 };
67
68 static struct line6_pcm_properties pod_pcm_properties = {
69 .snd_line6_playback_hw = {
70 .info = (SNDRV_PCM_INFO_MMAP |
71 SNDRV_PCM_INFO_INTERLEAVED |
72 SNDRV_PCM_INFO_BLOCK_TRANSFER |
73 SNDRV_PCM_INFO_MMAP_VALID |
74 SNDRV_PCM_INFO_PAUSE |
75 #ifdef CONFIG_PM
76 SNDRV_PCM_INFO_RESUME |
77 #endif
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 = 64,
87 .period_bytes_max = 8192,
88 .periods_min = 1,
89 .periods_max = 1024},
90 .snd_line6_capture_hw = {
91 .info = (SNDRV_PCM_INFO_MMAP |
92 SNDRV_PCM_INFO_INTERLEAVED |
93 SNDRV_PCM_INFO_BLOCK_TRANSFER |
94 SNDRV_PCM_INFO_MMAP_VALID |
95 #ifdef CONFIG_PM
96 SNDRV_PCM_INFO_RESUME |
97 #endif
98 SNDRV_PCM_INFO_SYNC_START),
99 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
100 .rates = SNDRV_PCM_RATE_KNOT,
101 .rate_min = 39062,
102 .rate_max = 39063,
103 .channels_min = 2,
104 .channels_max = 2,
105 .buffer_bytes_max = 60000,
106 .period_bytes_min = 64,
107 .period_bytes_max = 8192,
108 .periods_min = 1,
109 .periods_max = 1024},
110 .snd_line6_rates = {
111 .nrats = 1,
112 .rats = &pod_ratden},
113 .bytes_per_frame = POD_BYTES_PER_FRAME
114 };
115
116 static const char pod_version_header[] = {
117 0xf2, 0x7e, 0x7f, 0x06, 0x02
118 };
119
120 /* forward declarations: */
121 static void pod_startup2(unsigned long data);
122 static void pod_startup3(struct usb_line6_pod *pod);
123
124 static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
125 int size)
126 {
127 return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code,
128 size);
129 }
130
131 /*
132 Process a completely received message.
133 */
134 void line6_pod_process_message(struct usb_line6_pod *pod)
135 {
136 const unsigned char *buf = pod->line6.buffer_message;
137
138 /* filter messages by type */
139 switch (buf[0] & 0xf0) {
140 case LINE6_PARAM_CHANGE:
141 case LINE6_PROGRAM_CHANGE:
142 case LINE6_SYSEX_BEGIN:
143 break; /* handle these further down */
144
145 default:
146 return; /* ignore all others */
147 }
148
149 /* process all remaining messages */
150 switch (buf[0]) {
151 case LINE6_PARAM_CHANGE | LINE6_CHANNEL_DEVICE:
152 case LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST:
153 break;
154
155 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE:
156 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST:
157 break;
158
159 case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE:
160 case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN:
161 if (memcmp(buf + 1, line6_midi_id,
162 sizeof(line6_midi_id)) == 0) {
163 switch (buf[5]) {
164 case POD_SYSEX_DUMP:
165 break;
166
167 case POD_SYSEX_SYSTEM:{
168 short value =
169 ((int)buf[7] << 12) | ((int)buf[8]
170 << 8) |
171 ((int)buf[9] << 4) | (int)buf[10];
172
173 if (buf[6] == POD_MONITOR_LEVEL)
174 pod->monitor_level = value;
175 break;
176 }
177
178 case POD_SYSEX_FINISH:
179 /* do we need to respond to this? */
180 break;
181
182 case POD_SYSEX_SAVE:
183 break;
184
185 case POD_SYSEX_STORE:
186 dev_dbg(pod->line6.ifcdev,
187 "message %02X not yet implemented\n",
188 buf[5]);
189 break;
190
191 default:
192 dev_dbg(pod->line6.ifcdev,
193 "unknown sysex message %02X\n",
194 buf[5]);
195 }
196 } else
197 if (memcmp
198 (buf, pod_version_header,
199 sizeof(pod_version_header)) == 0) {
200 pod->firmware_version =
201 buf[13] * 100 + buf[14] * 10 + buf[15];
202 pod->device_id =
203 ((int)buf[8] << 16) | ((int)buf[9] << 8) | (int)
204 buf[10];
205 pod_startup3(pod);
206 } else
207 dev_dbg(pod->line6.ifcdev, "unknown sysex header\n");
208
209 break;
210
211 case LINE6_SYSEX_END:
212 break;
213
214 default:
215 dev_dbg(pod->line6.ifcdev, "POD: unknown message %02X\n",
216 buf[0]);
217 }
218 }
219
220 /*
221 Transmit PODxt Pro control parameter.
222 */
223 void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param,
224 u8 value)
225 {
226 line6_transmit_parameter(&pod->line6, param, value);
227 }
228
229 /*
230 Send system parameter (from integer).
231 */
232 static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
233 int code)
234 {
235 char *sysex;
236 static const int size = 5;
237
238 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
239 if (!sysex)
240 return -ENOMEM;
241 sysex[SYSEX_DATA_OFS] = code;
242 sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
243 sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
244 sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
245 sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f;
246 line6_send_sysex_message(&pod->line6, sysex, size);
247 kfree(sysex);
248 return 0;
249 }
250
251 /*
252 "read" request on "serial_number" special file.
253 */
254 static ssize_t pod_get_serial_number(struct device *dev,
255 struct device_attribute *attr, char *buf)
256 {
257 struct usb_interface *interface = to_usb_interface(dev);
258 struct usb_line6_pod *pod = usb_get_intfdata(interface);
259 return sprintf(buf, "%d\n", pod->serial_number);
260 }
261
262 /*
263 "read" request on "firmware_version" special file.
264 */
265 static ssize_t pod_get_firmware_version(struct device *dev,
266 struct device_attribute *attr,
267 char *buf)
268 {
269 struct usb_interface *interface = to_usb_interface(dev);
270 struct usb_line6_pod *pod = usb_get_intfdata(interface);
271 return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
272 pod->firmware_version % 100);
273 }
274
275 /*
276 "read" request on "device_id" special file.
277 */
278 static ssize_t pod_get_device_id(struct device *dev,
279 struct device_attribute *attr, char *buf)
280 {
281 struct usb_interface *interface = to_usb_interface(dev);
282 struct usb_line6_pod *pod = usb_get_intfdata(interface);
283 return sprintf(buf, "%d\n", pod->device_id);
284 }
285
286 /*
287 POD startup procedure.
288 This is a sequence of functions with special requirements (e.g., must
289 not run immediately after initialization, must not run in interrupt
290 context). After the last one has finished, the device is ready to use.
291 */
292
293 static void pod_startup1(struct usb_line6_pod *pod)
294 {
295 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
296
297 /* delay startup procedure: */
298 line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
299 (unsigned long)pod);
300 }
301
302 static void pod_startup2(unsigned long data)
303 {
304 struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
305 struct usb_line6 *line6 = &pod->line6;
306 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
307
308 /* request firmware version: */
309 line6_version_request_async(line6);
310 }
311
312 static void pod_startup3(struct usb_line6_pod *pod)
313 {
314 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
315
316 /* schedule work for global work queue: */
317 schedule_work(&pod->startup_work);
318 }
319
320 static void pod_startup4(struct work_struct *work)
321 {
322 struct usb_line6_pod *pod =
323 container_of(work, struct usb_line6_pod, startup_work);
324 struct usb_line6 *line6 = &pod->line6;
325
326 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
327
328 /* serial number: */
329 line6_read_serial_number(&pod->line6, &pod->serial_number);
330
331 /* ALSA audio interface: */
332 line6_register_audio(line6);
333 }
334
335 /* POD special files: */
336 static DEVICE_ATTR(device_id, S_IRUGO, pod_get_device_id, line6_nop_write);
337 static DEVICE_ATTR(firmware_version, S_IRUGO, pod_get_firmware_version,
338 line6_nop_write);
339 static DEVICE_ATTR(serial_number, S_IRUGO, pod_get_serial_number,
340 line6_nop_write);
341
342 /* control info callback */
343 static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
344 struct snd_ctl_elem_info *uinfo)
345 {
346 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
347 uinfo->count = 1;
348 uinfo->value.integer.min = 0;
349 uinfo->value.integer.max = 65535;
350 return 0;
351 }
352
353 /* control get callback */
354 static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
355 struct snd_ctl_elem_value *ucontrol)
356 {
357 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
358 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
359 ucontrol->value.integer.value[0] = pod->monitor_level;
360 return 0;
361 }
362
363 /* control put callback */
364 static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
365 struct snd_ctl_elem_value *ucontrol)
366 {
367 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
368 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
369
370 if (ucontrol->value.integer.value[0] == pod->monitor_level)
371 return 0;
372
373 pod->monitor_level = ucontrol->value.integer.value[0];
374 pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
375 POD_MONITOR_LEVEL);
376 return 1;
377 }
378
379 /* control definition */
380 static struct snd_kcontrol_new pod_control_monitor = {
381 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
382 .name = "Monitor Playback Volume",
383 .index = 0,
384 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
385 .info = snd_pod_control_monitor_info,
386 .get = snd_pod_control_monitor_get,
387 .put = snd_pod_control_monitor_put
388 };
389
390 /*
391 POD destructor.
392 */
393 static void pod_destruct(struct usb_interface *interface)
394 {
395 struct usb_line6_pod *pod = usb_get_intfdata(interface);
396
397 if (pod == NULL)
398 return;
399 line6_cleanup_audio(&pod->line6);
400
401 del_timer(&pod->startup_timer);
402 cancel_work_sync(&pod->startup_work);
403 }
404
405 /*
406 Create sysfs entries.
407 */
408 static int pod_create_files2(struct device *dev)
409 {
410 int err;
411
412 CHECK_RETURN(device_create_file(dev, &dev_attr_device_id));
413 CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version));
414 CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number));
415 return 0;
416 }
417
418 /*
419 Try to init POD device.
420 */
421 static int pod_try_init(struct usb_interface *interface,
422 struct usb_line6_pod *pod)
423 {
424 int err;
425 struct usb_line6 *line6 = &pod->line6;
426
427 init_timer(&pod->startup_timer);
428 INIT_WORK(&pod->startup_work, pod_startup4);
429
430 if ((interface == NULL) || (pod == NULL))
431 return -ENODEV;
432
433 /* create sysfs entries: */
434 err = pod_create_files2(&interface->dev);
435 if (err < 0)
436 return err;
437
438 /* initialize audio system: */
439 err = line6_init_audio(line6);
440 if (err < 0)
441 return err;
442
443 /* initialize MIDI subsystem: */
444 err = line6_init_midi(line6);
445 if (err < 0)
446 return err;
447
448 /* initialize PCM subsystem: */
449 err = line6_init_pcm(line6, &pod_pcm_properties);
450 if (err < 0)
451 return err;
452
453 /* register monitor control: */
454 err = snd_ctl_add(line6->card,
455 snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
456 if (err < 0)
457 return err;
458
459 /*
460 When the sound card is registered at this point, the PODxt Live
461 displays "Invalid Code Error 07", so we do it later in the event
462 handler.
463 */
464
465 if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) {
466 pod->monitor_level = POD_SYSTEM_INVALID;
467
468 /* initiate startup procedure: */
469 pod_startup1(pod);
470 }
471
472 return 0;
473 }
474
475 /*
476 Init POD device (and clean up in case of failure).
477 */
478 int line6_pod_init(struct usb_interface *interface, struct usb_line6_pod *pod)
479 {
480 int err = pod_try_init(interface, pod);
481
482 if (err < 0)
483 pod_destruct(interface);
484
485 return err;
486 }
487
488 /*
489 POD device disconnected.
490 */
491 void line6_pod_disconnect(struct usb_interface *interface)
492 {
493 struct usb_line6_pod *pod;
494
495 if (interface == NULL)
496 return;
497 pod = usb_get_intfdata(interface);
498
499 if (pod != NULL) {
500 struct snd_line6_pcm *line6pcm = pod->line6.line6pcm;
501 struct device *dev = &interface->dev;
502
503 if (line6pcm != NULL)
504 line6_pcm_disconnect(line6pcm);
505
506 if (dev != NULL) {
507 /* remove sysfs entries: */
508 device_remove_file(dev, &dev_attr_device_id);
509 device_remove_file(dev, &dev_attr_firmware_version);
510 device_remove_file(dev, &dev_attr_serial_number);
511 }
512 }
513
514 pod_destruct(interface);
515 }
This page took 0.066103 seconds and 5 git commands to generate.