]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/staging/line6/variax.c
staging: line6: sync with upstream
[mv-sheeva.git] / drivers / staging / line6 / variax.c
1 /*
2  * Line6 Linux USB driver - 0.9.0
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
14 #include "audio.h"
15 #include "control.h"
16 #include "driver.h"
17 #include "variax.h"
18
19
20 #define VARIAX_SYSEX_CODE 7
21 #define VARIAX_SYSEX_PARAM 0x3b
22 #define VARIAX_SYSEX_ACTIVATE 0x2a
23 #define VARIAX_MODEL_HEADER_LENGTH 7
24 #define VARIAX_MODEL_MESSAGE_LENGTH 199
25 #define VARIAX_OFFSET_ACTIVATE 7
26
27
28 /*
29         This message is sent by the device during initialization and identifies
30         the connected guitar model.
31 */
32 static const char variax_init_model[] = {
33         0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x69, 0x02,
34         0x00
35 };
36
37 /*
38         This message is sent by the device during initialization and identifies
39         the connected guitar version.
40 */
41 static const char variax_init_version[] = {
42         0xf0, 0x7e, 0x7f, 0x06, 0x02, 0x00, 0x01, 0x0c,
43         0x07, 0x00, 0x00, 0x00
44 };
45
46 /*
47         This message is the last one sent by the device during initialization.
48 */
49 static const char variax_init_done[] = {
50         0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6b
51 };
52
53 static const char variax_activate[] = {
54         0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x2a, 0x01,
55         0xf7
56 };
57
58 static const char variax_request_bank[] = {
59         0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6d, 0xf7
60 };
61
62 static const char variax_request_model1[] = {
63         0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x3c, 0x00,
64         0x02, 0x00, 0x00, 0x00, 0x00, 0x03, 0x05, 0x03,
65         0x00, 0x00, 0x00, 0xf7
66 };
67
68 static const char variax_request_model2[] = {
69         0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x3c, 0x00,
70         0x02, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x03,
71         0x00, 0x00, 0x00, 0xf7
72 };
73
74
75 /* forward declarations: */
76 static int variax_create_files2(struct device *dev);
77 static void variax_startup2(unsigned long data);
78 static void variax_startup4(unsigned long data);
79 static void variax_startup5(unsigned long data);
80
81
82 /*
83         Decode data transmitted by workbench.
84 */
85 static void variax_decode(const unsigned char *raw_data, unsigned char *data,
86                           int raw_size)
87 {
88         for (; raw_size > 0; raw_size -= 6) {
89                 data[2] = raw_data[0] | (raw_data[1] << 4);
90                 data[1] = raw_data[2] | (raw_data[3] << 4);
91                 data[0] = raw_data[4] | (raw_data[5] << 4);
92                 raw_data += 6;
93                 data += 3;
94         }
95 }
96
97 static void variax_activate_async(struct usb_line6_variax *variax, int a)
98 {
99         variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a;
100         line6_send_raw_message_async(&variax->line6, variax->buffer_activate,
101                                      sizeof(variax_activate));
102 }
103
104 /*
105         Variax startup procedure.
106         This is a sequence of functions with special requirements (e.g., must
107         not run immediately after initialization, must not run in interrupt
108         context). After the last one has finished, the device is ready to use.
109 */
110
111 static void variax_startup1(struct usb_line6_variax *variax)
112 {
113         CHECK_STARTUP_PROGRESS(variax->startup_progress, 1);
114
115         /* delay startup procedure: */
116         line6_start_timer(&variax->startup_timer, VARIAX_STARTUP_DELAY1, variax_startup2, (unsigned long)variax);
117 }
118
119 static void variax_startup2(unsigned long data)
120 {
121         struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
122         struct usb_line6 *line6 = &variax->line6;
123         CHECK_STARTUP_PROGRESS(variax->startup_progress, 2);
124
125         /* request firmware version: */
126         line6_version_request_async(line6);
127 }
128
129 static void variax_startup3(struct usb_line6_variax *variax)
130 {
131         CHECK_STARTUP_PROGRESS(variax->startup_progress, 3);
132
133         /* delay startup procedure: */
134         line6_start_timer(&variax->startup_timer, VARIAX_STARTUP_DELAY3, variax_startup4, (unsigned long)variax);
135 }
136
137 static void variax_startup4(unsigned long data)
138 {
139         struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
140         CHECK_STARTUP_PROGRESS(variax->startup_progress, 4);
141
142         /* activate device: */
143         variax_activate_async(variax, 1);
144         line6_start_timer(&variax->startup_timer, VARIAX_STARTUP_DELAY4, variax_startup5, (unsigned long)variax);
145 }
146
147 static void variax_startup5(unsigned long data)
148 {
149         struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
150         CHECK_STARTUP_PROGRESS(variax->startup_progress, 5);
151
152         /* current model dump: */
153         line6_dump_request_async(&variax->dumpreq, &variax->line6, 0, VARIAX_DUMP_PASS1);
154         /* passes 2 and 3 are performed implicitly before entering variax_startup6 */
155 }
156
157 static void variax_startup6(struct usb_line6_variax *variax)
158 {
159         CHECK_STARTUP_PROGRESS(variax->startup_progress, 6);
160
161         /* schedule work for global work queue: */
162         schedule_work(&variax->startup_work);
163 }
164
165 static void variax_startup7(struct work_struct *work)
166 {
167         struct usb_line6_variax *variax = container_of(work, struct usb_line6_variax, startup_work);
168         struct usb_line6 *line6 = &variax->line6;
169
170         CHECK_STARTUP_PROGRESS(variax->startup_progress, 7);
171
172         /* ALSA audio interface: */
173         line6_register_audio(&variax->line6);
174
175         /* device files: */
176         line6_variax_create_files(0, 0, line6->ifcdev);
177         variax_create_files2(line6->ifcdev);
178 }
179
180 /*
181         Process a completely received message.
182 */
183 void line6_variax_process_message(struct usb_line6_variax *variax)
184 {
185         const unsigned char *buf = variax->line6.buffer_message;
186
187         switch (buf[0]) {
188         case LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST:
189                 switch (buf[1]) {
190                 case VARIAXMIDI_volume:
191                         variax->volume = buf[2];
192                         break;
193
194                 case VARIAXMIDI_tone:
195                         variax->tone = buf[2];
196                 }
197
198                 break;
199
200         case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE:
201         case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST:
202                 variax->model = buf[1];
203                 line6_dump_request_async(&variax->dumpreq, &variax->line6, 0, VARIAX_DUMP_PASS1);
204                 break;
205
206         case LINE6_RESET:
207                 dev_info(variax->line6.ifcdev, "VARIAX reset\n");
208                 break;
209
210         case LINE6_SYSEX_BEGIN:
211                 if (memcmp(buf + 1, variax_request_model1 + 1,
212                            VARIAX_MODEL_HEADER_LENGTH - 1) == 0) {
213                         if (variax->line6.message_length ==
214                             VARIAX_MODEL_MESSAGE_LENGTH) {
215                                 switch (variax->dumpreq.in_progress) {
216                                 case VARIAX_DUMP_PASS1:
217                                         variax_decode(buf + VARIAX_MODEL_HEADER_LENGTH, (unsigned char *)&variax->model_data,
218                                                                                                 (sizeof(variax->model_data.name) + sizeof(variax->model_data.control) / 2) * 2);
219                                         line6_dump_request_async(&variax->dumpreq, &variax->line6, 1, VARIAX_DUMP_PASS2);
220                                         break;
221
222                                 case VARIAX_DUMP_PASS2:
223                                         /* model name is transmitted twice, so skip it here: */
224                                         variax_decode(buf + VARIAX_MODEL_HEADER_LENGTH,
225                                                       (unsigned char *)&variax->model_data.control + sizeof(variax->model_data.control) / 2,
226                                                       sizeof(variax->model_data.control) / 2 * 2);
227                                         line6_dump_request_async(&variax->dumpreq, &variax->line6, 2, VARIAX_DUMP_PASS3);
228                                 }
229                         } else {
230                                 DEBUG_MESSAGES(dev_err(variax->line6.ifcdev, "illegal length %d of model data\n", variax->line6.message_length));
231                                 line6_dump_finished(&variax->dumpreq);
232                         }
233                 } else if (memcmp(buf + 1, variax_request_bank + 1,
234                                   sizeof(variax_request_bank) - 2) == 0) {
235                         memcpy(variax->bank,
236                                buf + sizeof(variax_request_bank) - 1,
237                                sizeof(variax->bank));
238                         line6_dump_finished(&variax->dumpreq);
239                         variax_startup6(variax);
240                 } else if (memcmp(buf + 1, variax_init_model + 1,
241                                   sizeof(variax_init_model) - 1) == 0) {
242                         memcpy(variax->guitar,
243                                buf + sizeof(variax_init_model),
244                                sizeof(variax->guitar));
245                 } else if (memcmp(buf + 1, variax_init_version + 1,
246                                   sizeof(variax_init_version) - 1) == 0) {
247                         variax_startup3(variax);
248                 } else if (memcmp(buf + 1, variax_init_done + 1,
249                                   sizeof(variax_init_done) - 1) == 0) {
250                         /* notify of complete initialization: */
251                         variax_startup4((unsigned long)variax);
252                 }
253
254                 break;
255
256         case LINE6_SYSEX_END:
257                 break;
258
259         default:
260                 DEBUG_MESSAGES(dev_err(variax->line6.ifcdev, "Variax: unknown message %02X\n", buf[0]));
261         }
262 }
263
264 /*
265         "read" request on "volume" special file.
266 */
267 static ssize_t variax_get_volume(struct device *dev,
268                                  struct device_attribute *attr, char *buf)
269 {
270         struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev));
271         return sprintf(buf, "%d\n", variax->volume);
272 }
273
274 /*
275         "write" request on "volume" special file.
276 */
277 static ssize_t variax_set_volume(struct device *dev,
278                                  struct device_attribute *attr,
279                                  const char *buf, size_t count)
280 {
281         struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev));
282         unsigned long value;
283         int ret;
284
285         ret = strict_strtoul(buf, 10, &value);
286         if (ret)
287                 return ret;
288
289         if (line6_transmit_parameter(&variax->line6, VARIAXMIDI_volume,
290                                      value) == 0)
291                 variax->volume = value;
292
293         return count;
294 }
295
296 /*
297         "read" request on "model" special file.
298 */
299 static ssize_t variax_get_model(struct device *dev,
300                                 struct device_attribute *attr, char *buf)
301 {
302         struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev));
303         return sprintf(buf, "%d\n", variax->model);
304 }
305
306 /*
307         "write" request on "model" special file.
308 */
309 static ssize_t variax_set_model(struct device *dev,
310                                 struct device_attribute *attr,
311                                 const char *buf, size_t count)
312 {
313         struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev));
314         unsigned long value;
315         int ret;
316
317         ret = strict_strtoul(buf, 10, &value);
318         if (ret)
319                 return ret;
320
321         if (line6_send_program(&variax->line6, value) == 0)
322                 variax->model = value;
323
324         return count;
325 }
326
327 /*
328         "read" request on "active" special file.
329 */
330 static ssize_t variax_get_active(struct device *dev,
331                                  struct device_attribute *attr, char *buf)
332 {
333         struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev));
334         return sprintf(buf, "%d\n", variax->buffer_activate[VARIAX_OFFSET_ACTIVATE]);
335 }
336
337 /*
338         "write" request on "active" special file.
339 */
340 static ssize_t variax_set_active(struct device *dev,
341                                  struct device_attribute *attr,
342                                  const char *buf, size_t count)
343 {
344         struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev));
345         unsigned long value;
346         int ret;
347
348         ret = strict_strtoul(buf, 10, &value);
349         if (ret)
350                 return ret;
351
352         variax_activate_async(variax, value ? 1 : 0);
353         return count;
354 }
355
356 /*
357         "read" request on "tone" special file.
358 */
359 static ssize_t variax_get_tone(struct device *dev,
360                                struct device_attribute *attr, char *buf)
361 {
362         struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev));
363         return sprintf(buf, "%d\n", variax->tone);
364 }
365
366 /*
367         "write" request on "tone" special file.
368 */
369 static ssize_t variax_set_tone(struct device *dev,
370                                struct device_attribute *attr,
371                                const char *buf, size_t count)
372 {
373         struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev));
374         unsigned long value;
375         int ret;
376
377         ret = strict_strtoul(buf, 10, &value);
378         if (ret)
379                 return ret;
380
381         if (line6_transmit_parameter(&variax->line6, VARIAXMIDI_tone,
382                                      value) == 0)
383                 variax->tone = value;
384
385         return count;
386 }
387
388 static ssize_t get_string(char *buf, const char *data, int length)
389 {
390         int i;
391         memcpy(buf, data, length);
392
393         for (i = length; i--;) {
394                 char c = buf[i];
395
396                 if ((c != 0) && (c != ' '))
397                         break;
398         }
399
400         buf[i + 1] = '\n';
401         return i + 2;
402 }
403
404 /*
405         "read" request on "name" special file.
406 */
407 static ssize_t variax_get_name(struct device *dev,
408                                struct device_attribute *attr, char *buf)
409 {
410         struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev));
411         line6_dump_wait_interruptible(&variax->dumpreq);
412         return get_string(buf, variax->model_data.name,
413                           sizeof(variax->model_data.name));
414 }
415
416 /*
417         "read" request on "bank" special file.
418 */
419 static ssize_t variax_get_bank(struct device *dev,
420                                struct device_attribute *attr, char *buf)
421 {
422         struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev));
423         line6_dump_wait_interruptible(&variax->dumpreq);
424         return get_string(buf, variax->bank, sizeof(variax->bank));
425 }
426
427 /*
428         "read" request on "dump" special file.
429 */
430 static ssize_t variax_get_dump(struct device *dev,
431                                struct device_attribute *attr, char *buf)
432 {
433         struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev));
434         int retval;
435         retval = line6_dump_wait_interruptible(&variax->dumpreq);
436         if (retval < 0)
437                 return retval;
438         memcpy(buf, &variax->model_data.control,
439                sizeof(variax->model_data.control));
440         return sizeof(variax->model_data.control);
441 }
442
443 /*
444         "read" request on "guitar" special file.
445 */
446 static ssize_t variax_get_guitar(struct device *dev,
447                                  struct device_attribute *attr, char *buf)
448 {
449         struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev));
450         return sprintf(buf, "%s\n", variax->guitar);
451 }
452
453 #ifdef CONFIG_LINE6_USB_RAW
454
455 static char *variax_alloc_sysex_buffer(struct usb_line6_variax *variax, int code, int size)
456 {
457         return line6_alloc_sysex_buffer(&variax->line6, VARIAX_SYSEX_CODE, code, size);
458 }
459
460 /*
461         "write" request on "raw" special file.
462 */
463 static ssize_t variax_set_raw2(struct device *dev,
464                                struct device_attribute *attr,
465                                const char *buf, size_t count)
466 {
467         struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev));
468         int size;
469         int i;
470         char *sysex;
471
472         count -= count % 3;
473         size = count * 2;
474         sysex = variax_alloc_sysex_buffer(variax, VARIAX_SYSEX_PARAM, size);
475
476         if (!sysex)
477                 return 0;
478
479         for (i = 0; i < count; i += 3) {
480                 const unsigned char *p1 = buf + i;
481                 char *p2 = sysex + SYSEX_DATA_OFS + i * 2;
482                 p2[0] = p1[2] & 0x0f;
483                 p2[1] = p1[2] >> 4;
484                 p2[2] = p1[1] & 0x0f;
485                 p2[3] = p1[1] >> 4;
486                 p2[4] = p1[0] & 0x0f;
487                 p2[5] = p1[0] >> 4;
488         }
489
490         line6_send_sysex_message(&variax->line6, sysex, size);
491         kfree(sysex);
492         return count;
493 }
494
495 #endif
496
497 /* Variax workbench special files: */
498 static DEVICE_ATTR(model, S_IWUGO | S_IRUGO, variax_get_model, variax_set_model);
499 static DEVICE_ATTR(volume, S_IWUGO | S_IRUGO, variax_get_volume, variax_set_volume);
500 static DEVICE_ATTR(tone, S_IWUGO | S_IRUGO, variax_get_tone, variax_set_tone);
501 static DEVICE_ATTR(name, S_IRUGO, variax_get_name, line6_nop_write);
502 static DEVICE_ATTR(bank, S_IRUGO, variax_get_bank, line6_nop_write);
503 static DEVICE_ATTR(dump, S_IRUGO, variax_get_dump, line6_nop_write);
504 static DEVICE_ATTR(active, S_IWUGO | S_IRUGO, variax_get_active, variax_set_active);
505 static DEVICE_ATTR(guitar, S_IRUGO, variax_get_guitar, line6_nop_write);
506
507 #ifdef CONFIG_LINE6_USB_RAW
508 static DEVICE_ATTR(raw, S_IWUGO, line6_nop_read, line6_set_raw);
509 static DEVICE_ATTR(raw2, S_IWUGO, line6_nop_read, variax_set_raw2);
510 #endif
511
512
513 /*
514         Variax destructor.
515 */
516 static void variax_destruct(struct usb_interface *interface)
517 {
518         struct usb_line6_variax *variax = usb_get_intfdata(interface);
519         struct usb_line6 *line6;
520
521         if (variax == NULL)
522                 return;
523         line6 = &variax->line6;
524         if (line6 == NULL)
525                 return;
526         line6_cleanup_audio(line6);
527
528         /* free dump request data: */
529         line6_dumpreq_destructbuf(&variax->dumpreq, 2);
530         line6_dumpreq_destructbuf(&variax->dumpreq, 1);
531         line6_dumpreq_destruct(&variax->dumpreq);
532
533         kfree(variax->buffer_activate);
534 }
535
536 /*
537         Create sysfs entries.
538 */
539 static int variax_create_files2(struct device *dev)
540 {
541         int err;
542         CHECK_RETURN(device_create_file(dev, &dev_attr_model));
543         CHECK_RETURN(device_create_file(dev, &dev_attr_volume));
544         CHECK_RETURN(device_create_file(dev, &dev_attr_tone));
545         CHECK_RETURN(device_create_file(dev, &dev_attr_name));
546         CHECK_RETURN(device_create_file(dev, &dev_attr_bank));
547         CHECK_RETURN(device_create_file(dev, &dev_attr_dump));
548         CHECK_RETURN(device_create_file(dev, &dev_attr_active));
549         CHECK_RETURN(device_create_file(dev, &dev_attr_guitar));
550 #ifdef CONFIG_LINE6_USB_RAW
551         CHECK_RETURN(device_create_file(dev, &dev_attr_raw));
552         CHECK_RETURN(device_create_file(dev, &dev_attr_raw2));
553 #endif
554         return 0;
555 }
556
557 /*
558          Try to init workbench device.
559 */
560 static int variax_try_init(struct usb_interface *interface,
561                            struct usb_line6_variax *variax)
562 {
563         int err;
564
565         if ((interface == NULL) || (variax == NULL))
566                 return -ENODEV;
567
568         init_timer(&variax->startup_timer);
569         INIT_WORK(&variax->startup_work, variax_startup7);
570
571         /* initialize USB buffers: */
572         err = line6_dumpreq_init(&variax->dumpreq, variax_request_model1,
573                                  sizeof(variax_request_model1));
574
575         if (err < 0) {
576                 dev_err(&interface->dev, "Out of memory\n");
577                 return err;
578         }
579
580         err = line6_dumpreq_initbuf(&variax->dumpreq, variax_request_model2,
581                                     sizeof(variax_request_model2), 1);
582
583         if (err < 0) {
584                 dev_err(&interface->dev, "Out of memory\n");
585                 return err;
586         }
587
588         err = line6_dumpreq_initbuf(&variax->dumpreq, variax_request_bank,
589                                     sizeof(variax_request_bank), 2);
590
591         if (err < 0) {
592                 dev_err(&interface->dev, "Out of memory\n");
593                 return err;
594         }
595
596         variax->buffer_activate = kmemdup(variax_activate,
597                                           sizeof(variax_activate), GFP_KERNEL);
598
599         if (variax->buffer_activate == NULL) {
600                 dev_err(&interface->dev, "Out of memory\n");
601                 return -ENOMEM;
602         }
603
604         /* initialize audio system: */
605         err = line6_init_audio(&variax->line6);
606         if (err < 0) {
607                 return err;
608         }
609
610         /* initialize MIDI subsystem: */
611         err = line6_init_midi(&variax->line6);
612         if (err < 0) {
613                 return err;
614         }
615
616         /* initiate startup procedure: */
617         variax_startup1(variax);
618         return 0;
619 }
620
621 /*
622          Init workbench device (and clean up in case of failure).
623 */
624 int line6_variax_init(struct usb_interface *interface,
625                       struct usb_line6_variax *variax)
626 {
627         int err = variax_try_init(interface, variax);
628
629         if (err < 0) {
630                 variax_destruct(interface);
631         }
632
633         return err;
634 }
635
636 /*
637         Workbench device disconnected.
638 */
639 void line6_variax_disconnect(struct usb_interface *interface)
640 {
641         struct device *dev;
642
643         if (interface == NULL)
644                 return;
645         dev = &interface->dev;
646
647         if (dev != NULL) {
648                 /* remove sysfs entries: */
649                 line6_variax_remove_files(0, 0, dev);
650                 device_remove_file(dev, &dev_attr_model);
651                 device_remove_file(dev, &dev_attr_volume);
652                 device_remove_file(dev, &dev_attr_tone);
653                 device_remove_file(dev, &dev_attr_name);
654                 device_remove_file(dev, &dev_attr_bank);
655                 device_remove_file(dev, &dev_attr_dump);
656                 device_remove_file(dev, &dev_attr_active);
657                 device_remove_file(dev, &dev_attr_guitar);
658 #ifdef CONFIG_LINE6_USB_RAW
659                 device_remove_file(dev, &dev_attr_raw);
660                 device_remove_file(dev, &dev_attr_raw2);
661 #endif
662         }
663
664         variax_destruct(interface);
665 }