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