staging: line6: drop variax volume sysfs attr
[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_tone:
204                         variax->tone = buf[2];
205                 }
206
207                 break;
208
209         case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE:
210         case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST:
211                 line6_dump_request_async(&variax->dumpreq, &variax->line6, 0,
212                                          VARIAX_DUMP_PASS1);
213                 break;
214
215         case LINE6_RESET:
216                 dev_info(variax->line6.ifcdev, "VARIAX reset\n");
217                 break;
218
219         case LINE6_SYSEX_BEGIN:
220                 if (memcmp(buf + 1, variax_request_model1 + 1,
221                            VARIAX_MODEL_HEADER_LENGTH - 1) == 0) {
222                         if (variax->line6.message_length ==
223                             VARIAX_MODEL_MESSAGE_LENGTH) {
224                                 switch (variax->dumpreq.in_progress) {
225                                 case VARIAX_DUMP_PASS1:
226                                         variax_decode(buf +
227                                                       VARIAX_MODEL_HEADER_LENGTH,
228                                                       (unsigned char *)
229                                                       &variax->model_data,
230                                                       (sizeof
231                                                        (variax->model_data.
232                                                         name) +
233                                                        sizeof(variax->
234                                                               model_data.
235                                                               control)
236                                                        / 2) * 2);
237                                         line6_dump_request_async
238                                             (&variax->dumpreq, &variax->line6,
239                                              1, VARIAX_DUMP_PASS2);
240                                         break;
241
242                                 case VARIAX_DUMP_PASS2:
243                                         /* model name is transmitted twice, so skip it here: */
244                                         variax_decode(buf +
245                                                       VARIAX_MODEL_HEADER_LENGTH,
246                                                       (unsigned char *)
247                                                       &variax->
248                                                       model_data.control +
249                                                       sizeof(variax->model_data.
250                                                              control)
251                                                       / 2,
252                                                       sizeof(variax->model_data.
253                                                              control)
254                                                       / 2 * 2);
255                                         line6_dump_request_async
256                                             (&variax->dumpreq, &variax->line6,
257                                              2, VARIAX_DUMP_PASS3);
258                                 }
259                         } else {
260                                 dev_dbg(variax->line6.ifcdev,
261                                         "illegal length %d of model data\n",
262                                         variax->line6.message_length);
263                                 line6_dump_finished(&variax->dumpreq);
264                         }
265                 } else if (memcmp(buf + 1, variax_request_bank + 1,
266                                   sizeof(variax_request_bank) - 2) == 0) {
267                         memcpy(variax->bank,
268                                buf + sizeof(variax_request_bank) - 1,
269                                sizeof(variax->bank));
270                         line6_dump_finished(&variax->dumpreq);
271                         variax_startup6(variax);
272                 } else if (memcmp(buf + 1, variax_init_model + 1,
273                                   sizeof(variax_init_model) - 1) == 0) {
274                         memcpy(variax->guitar,
275                                buf + sizeof(variax_init_model),
276                                sizeof(variax->guitar));
277                 } else if (memcmp(buf + 1, variax_init_version + 1,
278                                   sizeof(variax_init_version) - 1) == 0) {
279                         variax_startup3(variax);
280                 } else if (memcmp(buf + 1, variax_init_done + 1,
281                                   sizeof(variax_init_done) - 1) == 0) {
282                         /* notify of complete initialization: */
283                         variax_startup4((unsigned long)variax);
284                 }
285
286                 break;
287
288         case LINE6_SYSEX_END:
289                 break;
290
291         default:
292                 dev_dbg(variax->line6.ifcdev,
293                         "Variax: unknown message %02X\n", buf[0]);
294         }
295 }
296
297 /*
298         "read" request on "active" special file.
299 */
300 static ssize_t variax_get_active(struct device *dev,
301                                  struct device_attribute *attr, char *buf)
302 {
303         struct usb_line6_variax *variax =
304             usb_get_intfdata(to_usb_interface(dev));
305         return sprintf(buf, "%d\n",
306                        variax->buffer_activate[VARIAX_OFFSET_ACTIVATE]);
307 }
308
309 /*
310         "write" request on "active" special file.
311 */
312 static ssize_t variax_set_active(struct device *dev,
313                                  struct device_attribute *attr,
314                                  const char *buf, size_t count)
315 {
316         struct usb_line6_variax *variax =
317             usb_get_intfdata(to_usb_interface(dev));
318         u8 value;
319         int ret;
320
321         ret = kstrtou8(buf, 10, &value);
322         if (ret)
323                 return ret;
324
325         variax_activate_async(variax, value ? 1 : 0);
326         return count;
327 }
328
329 /*
330         "read" request on "tone" special file.
331 */
332 static ssize_t variax_get_tone(struct device *dev,
333                                struct device_attribute *attr, char *buf)
334 {
335         struct usb_line6_variax *variax =
336             usb_get_intfdata(to_usb_interface(dev));
337         return sprintf(buf, "%d\n", variax->tone);
338 }
339
340 /*
341         "write" request on "tone" special file.
342 */
343 static ssize_t variax_set_tone(struct device *dev,
344                                struct device_attribute *attr,
345                                const char *buf, size_t count)
346 {
347         struct usb_line6_variax *variax =
348             usb_get_intfdata(to_usb_interface(dev));
349         u8 value;
350         int ret;
351
352         ret = kstrtou8(buf, 10, &value);
353         if (ret)
354                 return ret;
355
356         if (line6_transmit_parameter(&variax->line6, VARIAXMIDI_tone,
357                                      value) == 0)
358                 variax->tone = value;
359
360         return count;
361 }
362
363 static ssize_t get_string(char *buf, const char *data, int length)
364 {
365         int i;
366         memcpy(buf, data, length);
367
368         for (i = length; i--;) {
369                 char c = buf[i];
370
371                 if ((c != 0) && (c != ' '))
372                         break;
373         }
374
375         buf[i + 1] = '\n';
376         return i + 2;
377 }
378
379 /*
380         "read" request on "name" special file.
381 */
382 static ssize_t variax_get_name(struct device *dev,
383                                struct device_attribute *attr, char *buf)
384 {
385         struct usb_line6_variax *variax =
386             usb_get_intfdata(to_usb_interface(dev));
387         line6_dump_wait_interruptible(&variax->dumpreq);
388         return get_string(buf, variax->model_data.name,
389                           sizeof(variax->model_data.name));
390 }
391
392 /*
393         "read" request on "bank" special file.
394 */
395 static ssize_t variax_get_bank(struct device *dev,
396                                struct device_attribute *attr, char *buf)
397 {
398         struct usb_line6_variax *variax =
399             usb_get_intfdata(to_usb_interface(dev));
400         line6_dump_wait_interruptible(&variax->dumpreq);
401         return get_string(buf, variax->bank, sizeof(variax->bank));
402 }
403
404 /*
405         "read" request on "dump" special file.
406 */
407 static ssize_t variax_get_dump(struct device *dev,
408                                struct device_attribute *attr, char *buf)
409 {
410         struct usb_line6_variax *variax =
411             usb_get_intfdata(to_usb_interface(dev));
412         int retval;
413         retval = line6_dump_wait_interruptible(&variax->dumpreq);
414         if (retval < 0)
415                 return retval;
416         memcpy(buf, &variax->model_data.control,
417                sizeof(variax->model_data.control));
418         return sizeof(variax->model_data.control);
419 }
420
421 /*
422         "read" request on "guitar" special file.
423 */
424 static ssize_t variax_get_guitar(struct device *dev,
425                                  struct device_attribute *attr, char *buf)
426 {
427         struct usb_line6_variax *variax =
428             usb_get_intfdata(to_usb_interface(dev));
429         return sprintf(buf, "%s\n", variax->guitar);
430 }
431
432 #ifdef CONFIG_LINE6_USB_RAW
433
434 static char *variax_alloc_sysex_buffer(struct usb_line6_variax *variax,
435                                        int code, int size)
436 {
437         return line6_alloc_sysex_buffer(&variax->line6, VARIAX_SYSEX_CODE, code,
438                                         size);
439 }
440
441 /*
442         "write" request on "raw" special file.
443 */
444 static ssize_t variax_set_raw2(struct device *dev,
445                                struct device_attribute *attr,
446                                const char *buf, size_t count)
447 {
448         struct usb_line6_variax *variax =
449             usb_get_intfdata(to_usb_interface(dev));
450         int size;
451         int i;
452         char *sysex;
453
454         count -= count % 3;
455         size = count * 2;
456         sysex = variax_alloc_sysex_buffer(variax, VARIAX_SYSEX_PARAM, size);
457
458         if (!sysex)
459                 return 0;
460
461         for (i = 0; i < count; i += 3) {
462                 const unsigned char *p1 = buf + i;
463                 char *p2 = sysex + SYSEX_DATA_OFS + i * 2;
464                 p2[0] = p1[2] & 0x0f;
465                 p2[1] = p1[2] >> 4;
466                 p2[2] = p1[1] & 0x0f;
467                 p2[3] = p1[1] >> 4;
468                 p2[4] = p1[0] & 0x0f;
469                 p2[5] = p1[0] >> 4;
470         }
471
472         line6_send_sysex_message(&variax->line6, sysex, size);
473         kfree(sysex);
474         return count;
475 }
476
477 #endif
478
479 /* Variax workbench special files: */
480 static DEVICE_ATTR(tone, S_IWUSR | S_IRUGO, variax_get_tone, variax_set_tone);
481 static DEVICE_ATTR(name, S_IRUGO, variax_get_name, line6_nop_write);
482 static DEVICE_ATTR(bank, S_IRUGO, variax_get_bank, line6_nop_write);
483 static DEVICE_ATTR(dump, S_IRUGO, variax_get_dump, line6_nop_write);
484 static DEVICE_ATTR(active, S_IWUSR | S_IRUGO, variax_get_active,
485                    variax_set_active);
486 static DEVICE_ATTR(guitar, S_IRUGO, variax_get_guitar, line6_nop_write);
487
488 #ifdef CONFIG_LINE6_USB_RAW
489 static DEVICE_ATTR(raw, S_IWUSR, line6_nop_read, line6_set_raw);
490 static DEVICE_ATTR(raw2, S_IWUSR, line6_nop_read, variax_set_raw2);
491 #endif
492
493 /*
494         Variax destructor.
495 */
496 static void variax_destruct(struct usb_interface *interface)
497 {
498         struct usb_line6_variax *variax = usb_get_intfdata(interface);
499
500         if (variax == NULL)
501                 return;
502         line6_cleanup_audio(&variax->line6);
503
504         del_timer(&variax->startup_timer1);
505         del_timer(&variax->startup_timer2);
506         cancel_work_sync(&variax->startup_work);
507
508         /* free dump request data: */
509         line6_dumpreq_destructbuf(&variax->dumpreq, 2);
510         line6_dumpreq_destructbuf(&variax->dumpreq, 1);
511         line6_dumpreq_destruct(&variax->dumpreq);
512
513         kfree(variax->buffer_activate);
514 }
515
516 /*
517         Create sysfs entries.
518 */
519 static int variax_create_files2(struct device *dev)
520 {
521         int err;
522         CHECK_RETURN(device_create_file(dev, &dev_attr_tone));
523         CHECK_RETURN(device_create_file(dev, &dev_attr_name));
524         CHECK_RETURN(device_create_file(dev, &dev_attr_bank));
525         CHECK_RETURN(device_create_file(dev, &dev_attr_dump));
526         CHECK_RETURN(device_create_file(dev, &dev_attr_active));
527         CHECK_RETURN(device_create_file(dev, &dev_attr_guitar));
528 #ifdef CONFIG_LINE6_USB_RAW
529         CHECK_RETURN(device_create_file(dev, &dev_attr_raw));
530         CHECK_RETURN(device_create_file(dev, &dev_attr_raw2));
531 #endif
532         return 0;
533 }
534
535 /*
536          Try to init workbench device.
537 */
538 static int variax_try_init(struct usb_interface *interface,
539                            struct usb_line6_variax *variax)
540 {
541         int err;
542
543         init_timer(&variax->startup_timer1);
544         init_timer(&variax->startup_timer2);
545         INIT_WORK(&variax->startup_work, variax_startup7);
546
547         if ((interface == NULL) || (variax == NULL))
548                 return -ENODEV;
549
550         /* initialize USB buffers: */
551         err = line6_dumpreq_init(&variax->dumpreq, variax_request_model1,
552                                  sizeof(variax_request_model1));
553
554         if (err < 0) {
555                 dev_err(&interface->dev, "Out of memory\n");
556                 return err;
557         }
558
559         err = line6_dumpreq_initbuf(&variax->dumpreq, variax_request_model2,
560                                     sizeof(variax_request_model2), 1);
561
562         if (err < 0) {
563                 dev_err(&interface->dev, "Out of memory\n");
564                 return err;
565         }
566
567         err = line6_dumpreq_initbuf(&variax->dumpreq, variax_request_bank,
568                                     sizeof(variax_request_bank), 2);
569
570         if (err < 0) {
571                 dev_err(&interface->dev, "Out of memory\n");
572                 return err;
573         }
574
575         variax->buffer_activate = kmemdup(variax_activate,
576                                           sizeof(variax_activate), GFP_KERNEL);
577
578         if (variax->buffer_activate == NULL) {
579                 dev_err(&interface->dev, "Out of memory\n");
580                 return -ENOMEM;
581         }
582
583         /* initialize audio system: */
584         err = line6_init_audio(&variax->line6);
585         if (err < 0)
586                 return err;
587
588         /* initialize MIDI subsystem: */
589         err = line6_init_midi(&variax->line6);
590         if (err < 0)
591                 return err;
592
593         /* initiate startup procedure: */
594         variax_startup1(variax);
595         return 0;
596 }
597
598 /*
599          Init workbench device (and clean up in case of failure).
600 */
601 int line6_variax_init(struct usb_interface *interface,
602                       struct usb_line6_variax *variax)
603 {
604         int err = variax_try_init(interface, variax);
605
606         if (err < 0)
607                 variax_destruct(interface);
608
609         return err;
610 }
611
612 /*
613         Workbench device disconnected.
614 */
615 void line6_variax_disconnect(struct usb_interface *interface)
616 {
617         struct device *dev;
618
619         if (interface == NULL)
620                 return;
621         dev = &interface->dev;
622
623         if (dev != NULL) {
624                 /* remove sysfs entries: */
625                 line6_variax_remove_files(0, 0, dev);
626                 device_remove_file(dev, &dev_attr_tone);
627                 device_remove_file(dev, &dev_attr_name);
628                 device_remove_file(dev, &dev_attr_bank);
629                 device_remove_file(dev, &dev_attr_dump);
630                 device_remove_file(dev, &dev_attr_active);
631                 device_remove_file(dev, &dev_attr_guitar);
632 #ifdef CONFIG_LINE6_USB_RAW
633                 device_remove_file(dev, &dev_attr_raw);
634                 device_remove_file(dev, &dev_attr_raw2);
635 #endif
636         }
637
638         variax_destruct(interface);
639 }