Merge remote-tracking branch 'cleancache/linux-next'
[linux-2.6/next.git] / drivers / staging / line6 / variax.c
blob81241cdf1be97ec60888550c128f3827f23713a2
1 /*
2 * Line6 Linux USB driver - 0.9.1beta
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
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.
12 #include <linux/slab.h>
14 #include "audio.h"
15 #include "control.h"
16 #include "driver.h"
17 #include "variax.h"
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
27 This message is sent by the device during initialization and identifies
28 the connected guitar model.
30 static const char variax_init_model[] = {
31 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x69, 0x02,
32 0x00
36 This message is sent by the device during initialization and identifies
37 the connected guitar version.
39 static const char variax_init_version[] = {
40 0xf0, 0x7e, 0x7f, 0x06, 0x02, 0x00, 0x01, 0x0c,
41 0x07, 0x00, 0x00, 0x00
45 This message is the last one sent by the device during initialization.
47 static const char variax_init_done[] = {
48 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6b
51 static const char variax_activate[] = {
52 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x2a, 0x01,
53 0xf7
56 static const char variax_request_bank[] = {
57 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6d, 0xf7
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
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
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);
79 Decode data transmitted by workbench.
81 static void variax_decode(const unsigned char *raw_data, unsigned char *data,
82 int raw_size)
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;
93 static void variax_activate_async(struct usb_line6_variax *variax, int a)
95 variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a;
96 line6_send_raw_message_async(&variax->line6, variax->buffer_activate,
97 sizeof(variax_activate));
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.
107 static void variax_startup1(struct usb_line6_variax *variax)
109 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_INIT);
111 /* delay startup procedure: */
112 line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
113 variax_startup2, (unsigned long)variax);
116 static void variax_startup2(unsigned long data)
118 struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
119 struct usb_line6 *line6 = &variax->line6;
121 /* schedule another startup procedure until startup is complete: */
122 if (variax->startup_progress >= VARIAX_STARTUP_LAST)
123 return;
125 variax->startup_progress = VARIAX_STARTUP_VERSIONREQ;
126 line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
127 variax_startup2, (unsigned long)variax);
129 /* request firmware version: */
130 line6_version_request_async(line6);
133 static void variax_startup3(struct usb_line6_variax *variax)
135 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_WAIT);
137 /* delay startup procedure: */
138 line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY3,
139 variax_startup4, (unsigned long)variax);
142 static void variax_startup4(unsigned long data)
144 struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
145 CHECK_STARTUP_PROGRESS(variax->startup_progress,
146 VARIAX_STARTUP_ACTIVATE);
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);
154 static void variax_startup5(unsigned long data)
156 struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
157 CHECK_STARTUP_PROGRESS(variax->startup_progress,
158 VARIAX_STARTUP_DUMPREQ);
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 variax_startup6 */
166 static void variax_startup6(struct usb_line6_variax *variax)
168 CHECK_STARTUP_PROGRESS(variax->startup_progress,
169 VARIAX_STARTUP_WORKQUEUE);
171 /* schedule work for global work queue: */
172 schedule_work(&variax->startup_work);
175 static void variax_startup7(struct work_struct *work)
177 struct usb_line6_variax *variax =
178 container_of(work, struct usb_line6_variax, startup_work);
179 struct usb_line6 *line6 = &variax->line6;
181 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_SETUP);
183 /* ALSA audio interface: */
184 line6_register_audio(&variax->line6);
186 /* device files: */
187 line6_variax_create_files(0, 0, line6->ifcdev);
188 variax_create_files2(line6->ifcdev);
192 Process a completely received message.
194 void line6_variax_process_message(struct usb_line6_variax *variax)
196 const unsigned char *buf = variax->line6.buffer_message;
198 switch (buf[0]) {
199 case LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST:
200 switch (buf[1]) {
201 case VARIAXMIDI_volume:
202 variax->volume = buf[2];
203 break;
205 case VARIAXMIDI_tone:
206 variax->tone = buf[2];
209 break;
211 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE:
212 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST:
213 variax->model = buf[1];
214 line6_dump_request_async(&variax->dumpreq, &variax->line6, 0,
215 VARIAX_DUMP_PASS1);
216 break;
218 case LINE6_RESET:
219 dev_info(variax->line6.ifcdev, "VARIAX reset\n");
220 break;
222 case LINE6_SYSEX_BEGIN:
223 if (memcmp(buf + 1, variax_request_model1 + 1,
224 VARIAX_MODEL_HEADER_LENGTH - 1) == 0) {
225 if (variax->line6.message_length ==
226 VARIAX_MODEL_MESSAGE_LENGTH) {
227 switch (variax->dumpreq.in_progress) {
228 case VARIAX_DUMP_PASS1:
229 variax_decode(buf +
230 VARIAX_MODEL_HEADER_LENGTH,
231 (unsigned char *)
232 &variax->model_data,
233 (sizeof
234 (variax->model_data.
235 name) +
236 sizeof(variax->
237 model_data.
238 control)
239 / 2) * 2);
240 line6_dump_request_async
241 (&variax->dumpreq, &variax->line6,
242 1, VARIAX_DUMP_PASS2);
243 break;
245 case VARIAX_DUMP_PASS2:
246 /* model name is transmitted twice, so skip it here: */
247 variax_decode(buf +
248 VARIAX_MODEL_HEADER_LENGTH,
249 (unsigned char *)
250 &variax->
251 model_data.control +
252 sizeof(variax->model_data.
253 control)
254 / 2,
255 sizeof(variax->model_data.
256 control)
257 / 2 * 2);
258 line6_dump_request_async
259 (&variax->dumpreq, &variax->line6,
260 2, VARIAX_DUMP_PASS3);
262 } else {
263 DEBUG_MESSAGES(dev_err
264 (variax->line6.ifcdev,
265 "illegal length %d of model data\n",
266 variax->line6.message_length));
267 line6_dump_finished(&variax->dumpreq);
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);
290 break;
292 case LINE6_SYSEX_END:
293 break;
295 default:
296 DEBUG_MESSAGES(dev_err
297 (variax->line6.ifcdev,
298 "Variax: unknown message %02X\n", buf[0]));
303 "read" request on "volume" special file.
305 static ssize_t variax_get_volume(struct device *dev,
306 struct device_attribute *attr, char *buf)
308 struct usb_line6_variax *variax =
309 usb_get_intfdata(to_usb_interface(dev));
310 return sprintf(buf, "%d\n", variax->volume);
314 "write" request on "volume" special file.
316 static ssize_t variax_set_volume(struct device *dev,
317 struct device_attribute *attr,
318 const char *buf, size_t count)
320 struct usb_line6_variax *variax =
321 usb_get_intfdata(to_usb_interface(dev));
322 unsigned long value;
323 int ret;
325 ret = strict_strtoul(buf, 10, &value);
326 if (ret)
327 return ret;
329 if (line6_transmit_parameter(&variax->line6, VARIAXMIDI_volume,
330 value) == 0)
331 variax->volume = value;
333 return count;
337 "read" request on "model" special file.
339 static ssize_t variax_get_model(struct device *dev,
340 struct device_attribute *attr, char *buf)
342 struct usb_line6_variax *variax =
343 usb_get_intfdata(to_usb_interface(dev));
344 return sprintf(buf, "%d\n", variax->model);
348 "write" request on "model" special file.
350 static ssize_t variax_set_model(struct device *dev,
351 struct device_attribute *attr,
352 const char *buf, size_t count)
354 struct usb_line6_variax *variax =
355 usb_get_intfdata(to_usb_interface(dev));
356 unsigned long value;
357 int ret;
359 ret = strict_strtoul(buf, 10, &value);
360 if (ret)
361 return ret;
363 if (line6_send_program(&variax->line6, value) == 0)
364 variax->model = value;
366 return count;
370 "read" request on "active" special file.
372 static ssize_t variax_get_active(struct device *dev,
373 struct device_attribute *attr, char *buf)
375 struct usb_line6_variax *variax =
376 usb_get_intfdata(to_usb_interface(dev));
377 return sprintf(buf, "%d\n",
378 variax->buffer_activate[VARIAX_OFFSET_ACTIVATE]);
382 "write" request on "active" special file.
384 static ssize_t variax_set_active(struct device *dev,
385 struct device_attribute *attr,
386 const char *buf, size_t count)
388 struct usb_line6_variax *variax =
389 usb_get_intfdata(to_usb_interface(dev));
390 unsigned long value;
391 int ret;
393 ret = strict_strtoul(buf, 10, &value);
394 if (ret)
395 return ret;
397 variax_activate_async(variax, value ? 1 : 0);
398 return count;
402 "read" request on "tone" special file.
404 static ssize_t variax_get_tone(struct device *dev,
405 struct device_attribute *attr, char *buf)
407 struct usb_line6_variax *variax =
408 usb_get_intfdata(to_usb_interface(dev));
409 return sprintf(buf, "%d\n", variax->tone);
413 "write" request on "tone" special file.
415 static ssize_t variax_set_tone(struct device *dev,
416 struct device_attribute *attr,
417 const char *buf, size_t count)
419 struct usb_line6_variax *variax =
420 usb_get_intfdata(to_usb_interface(dev));
421 unsigned long value;
422 int ret;
424 ret = strict_strtoul(buf, 10, &value);
425 if (ret)
426 return ret;
428 if (line6_transmit_parameter(&variax->line6, VARIAXMIDI_tone,
429 value) == 0)
430 variax->tone = value;
432 return count;
435 static ssize_t get_string(char *buf, const char *data, int length)
437 int i;
438 memcpy(buf, data, length);
440 for (i = length; i--;) {
441 char c = buf[i];
443 if ((c != 0) && (c != ' '))
444 break;
447 buf[i + 1] = '\n';
448 return i + 2;
452 "read" request on "name" special file.
454 static ssize_t variax_get_name(struct device *dev,
455 struct device_attribute *attr, char *buf)
457 struct usb_line6_variax *variax =
458 usb_get_intfdata(to_usb_interface(dev));
459 line6_dump_wait_interruptible(&variax->dumpreq);
460 return get_string(buf, variax->model_data.name,
461 sizeof(variax->model_data.name));
465 "read" request on "bank" special file.
467 static ssize_t variax_get_bank(struct device *dev,
468 struct device_attribute *attr, char *buf)
470 struct usb_line6_variax *variax =
471 usb_get_intfdata(to_usb_interface(dev));
472 line6_dump_wait_interruptible(&variax->dumpreq);
473 return get_string(buf, variax->bank, sizeof(variax->bank));
477 "read" request on "dump" special file.
479 static ssize_t variax_get_dump(struct device *dev,
480 struct device_attribute *attr, char *buf)
482 struct usb_line6_variax *variax =
483 usb_get_intfdata(to_usb_interface(dev));
484 int retval;
485 retval = line6_dump_wait_interruptible(&variax->dumpreq);
486 if (retval < 0)
487 return retval;
488 memcpy(buf, &variax->model_data.control,
489 sizeof(variax->model_data.control));
490 return sizeof(variax->model_data.control);
494 "read" request on "guitar" special file.
496 static ssize_t variax_get_guitar(struct device *dev,
497 struct device_attribute *attr, char *buf)
499 struct usb_line6_variax *variax =
500 usb_get_intfdata(to_usb_interface(dev));
501 return sprintf(buf, "%s\n", variax->guitar);
504 #ifdef CONFIG_LINE6_USB_RAW
506 static char *variax_alloc_sysex_buffer(struct usb_line6_variax *variax,
507 int code, int size)
509 return line6_alloc_sysex_buffer(&variax->line6, VARIAX_SYSEX_CODE, code,
510 size);
514 "write" request on "raw" special file.
516 static ssize_t variax_set_raw2(struct device *dev,
517 struct device_attribute *attr,
518 const char *buf, size_t count)
520 struct usb_line6_variax *variax =
521 usb_get_intfdata(to_usb_interface(dev));
522 int size;
523 int i;
524 char *sysex;
526 count -= count % 3;
527 size = count * 2;
528 sysex = variax_alloc_sysex_buffer(variax, VARIAX_SYSEX_PARAM, size);
530 if (!sysex)
531 return 0;
533 for (i = 0; i < count; i += 3) {
534 const unsigned char *p1 = buf + i;
535 char *p2 = sysex + SYSEX_DATA_OFS + i * 2;
536 p2[0] = p1[2] & 0x0f;
537 p2[1] = p1[2] >> 4;
538 p2[2] = p1[1] & 0x0f;
539 p2[3] = p1[1] >> 4;
540 p2[4] = p1[0] & 0x0f;
541 p2[5] = p1[0] >> 4;
544 line6_send_sysex_message(&variax->line6, sysex, size);
545 kfree(sysex);
546 return count;
549 #endif
551 /* Variax workbench special files: */
552 static DEVICE_ATTR(model, S_IWUSR | S_IRUGO, variax_get_model,
553 variax_set_model);
554 static DEVICE_ATTR(volume, S_IWUSR | S_IRUGO, variax_get_volume,
555 variax_set_volume);
556 static DEVICE_ATTR(tone, S_IWUSR | S_IRUGO, variax_get_tone, variax_set_tone);
557 static DEVICE_ATTR(name, S_IRUGO, variax_get_name, line6_nop_write);
558 static DEVICE_ATTR(bank, S_IRUGO, variax_get_bank, line6_nop_write);
559 static DEVICE_ATTR(dump, S_IRUGO, variax_get_dump, line6_nop_write);
560 static DEVICE_ATTR(active, S_IWUSR | S_IRUGO, variax_get_active,
561 variax_set_active);
562 static DEVICE_ATTR(guitar, S_IRUGO, variax_get_guitar, line6_nop_write);
564 #ifdef CONFIG_LINE6_USB_RAW
565 static DEVICE_ATTR(raw, S_IWUSR, line6_nop_read, line6_set_raw);
566 static DEVICE_ATTR(raw2, S_IWUSR, line6_nop_read, variax_set_raw2);
567 #endif
570 Variax destructor.
572 static void variax_destruct(struct usb_interface *interface)
574 struct usb_line6_variax *variax = usb_get_intfdata(interface);
575 struct usb_line6 *line6;
577 if (variax == NULL)
578 return;
579 line6 = &variax->line6;
580 if (line6 == NULL)
581 return;
582 line6_cleanup_audio(line6);
584 del_timer(&variax->startup_timer1);
585 del_timer(&variax->startup_timer2);
586 cancel_work_sync(&variax->startup_work);
588 /* free dump request data: */
589 line6_dumpreq_destructbuf(&variax->dumpreq, 2);
590 line6_dumpreq_destructbuf(&variax->dumpreq, 1);
591 line6_dumpreq_destruct(&variax->dumpreq);
593 kfree(variax->buffer_activate);
597 Create sysfs entries.
599 static int variax_create_files2(struct device *dev)
601 int err;
602 CHECK_RETURN(device_create_file(dev, &dev_attr_model));
603 CHECK_RETURN(device_create_file(dev, &dev_attr_volume));
604 CHECK_RETURN(device_create_file(dev, &dev_attr_tone));
605 CHECK_RETURN(device_create_file(dev, &dev_attr_name));
606 CHECK_RETURN(device_create_file(dev, &dev_attr_bank));
607 CHECK_RETURN(device_create_file(dev, &dev_attr_dump));
608 CHECK_RETURN(device_create_file(dev, &dev_attr_active));
609 CHECK_RETURN(device_create_file(dev, &dev_attr_guitar));
610 #ifdef CONFIG_LINE6_USB_RAW
611 CHECK_RETURN(device_create_file(dev, &dev_attr_raw));
612 CHECK_RETURN(device_create_file(dev, &dev_attr_raw2));
613 #endif
614 return 0;
618 Try to init workbench device.
620 static int variax_try_init(struct usb_interface *interface,
621 struct usb_line6_variax *variax)
623 int err;
625 init_timer(&variax->startup_timer1);
626 init_timer(&variax->startup_timer2);
627 INIT_WORK(&variax->startup_work, variax_startup7);
629 if ((interface == NULL) || (variax == NULL))
630 return -ENODEV;
632 /* initialize USB buffers: */
633 err = line6_dumpreq_init(&variax->dumpreq, variax_request_model1,
634 sizeof(variax_request_model1));
636 if (err < 0) {
637 dev_err(&interface->dev, "Out of memory\n");
638 return err;
641 err = line6_dumpreq_initbuf(&variax->dumpreq, variax_request_model2,
642 sizeof(variax_request_model2), 1);
644 if (err < 0) {
645 dev_err(&interface->dev, "Out of memory\n");
646 return err;
649 err = line6_dumpreq_initbuf(&variax->dumpreq, variax_request_bank,
650 sizeof(variax_request_bank), 2);
652 if (err < 0) {
653 dev_err(&interface->dev, "Out of memory\n");
654 return err;
657 variax->buffer_activate = kmemdup(variax_activate,
658 sizeof(variax_activate), GFP_KERNEL);
660 if (variax->buffer_activate == NULL) {
661 dev_err(&interface->dev, "Out of memory\n");
662 return -ENOMEM;
665 /* initialize audio system: */
666 err = line6_init_audio(&variax->line6);
667 if (err < 0)
668 return err;
670 /* initialize MIDI subsystem: */
671 err = line6_init_midi(&variax->line6);
672 if (err < 0)
673 return err;
675 /* initiate startup procedure: */
676 variax_startup1(variax);
677 return 0;
681 Init workbench device (and clean up in case of failure).
683 int line6_variax_init(struct usb_interface *interface,
684 struct usb_line6_variax *variax)
686 int err = variax_try_init(interface, variax);
688 if (err < 0)
689 variax_destruct(interface);
691 return err;
695 Workbench device disconnected.
697 void line6_variax_disconnect(struct usb_interface *interface)
699 struct device *dev;
701 if (interface == NULL)
702 return;
703 dev = &interface->dev;
705 if (dev != NULL) {
706 /* remove sysfs entries: */
707 line6_variax_remove_files(0, 0, dev);
708 device_remove_file(dev, &dev_attr_model);
709 device_remove_file(dev, &dev_attr_volume);
710 device_remove_file(dev, &dev_attr_tone);
711 device_remove_file(dev, &dev_attr_name);
712 device_remove_file(dev, &dev_attr_bank);
713 device_remove_file(dev, &dev_attr_dump);
714 device_remove_file(dev, &dev_attr_active);
715 device_remove_file(dev, &dev_attr_guitar);
716 #ifdef CONFIG_LINE6_USB_RAW
717 device_remove_file(dev, &dev_attr_raw);
718 device_remove_file(dev, &dev_attr_raw2);
719 #endif
722 variax_destruct(interface);