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*/
30static 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*/
39static 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*/
47static const char variax_init_done[] = {
48	0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6b
49};
50
51static const char variax_activate[] = {
52	0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x2a, 0x01,
53	0xf7
54};
55
56static const char variax_request_bank[] = {
57	0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6d, 0xf7
58};
59
60static 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
66static 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: */
73static int variax_create_files2(struct device *dev);
74static void variax_startup2(unsigned long data);
75static void variax_startup4(unsigned long data);
76static void variax_startup5(unsigned long data);
77
78/*
79	Decode data transmitted by workbench.
80*/
81static 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
93static 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
107static 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
116static 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
133static 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
142static 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
154static 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 variax_startup6 */
164}
165
166static void variax_startup6(struct usb_line6_variax *variax)
167{
168	CHECK_STARTUP_PROGRESS(variax->startup_progress,
169			       VARIAX_STARTUP_WORKQUEUE);
170
171	/* schedule work for global work queue: */
172	schedule_work(&variax->startup_work);
173}
174
175static void variax_startup7(struct work_struct *work)
176{
177	struct usb_line6_variax *variax =
178	    container_of(work, struct usb_line6_variax, startup_work);
179	struct usb_line6 *line6 = &variax->line6;
180
181	CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_SETUP);
182
183	/* ALSA audio interface: */
184	line6_register_audio(&variax->line6);
185
186	/* device files: */
187	line6_variax_create_files(0, 0, line6->ifcdev);
188	variax_create_files2(line6->ifcdev);
189}
190
191/*
192	Process a completely received message.
193*/
194void line6_variax_process_message(struct usb_line6_variax *variax)
195{
196	const unsigned char *buf = variax->line6.buffer_message;
197
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;
204
205		case VARIAXMIDI_tone:
206			variax->tone = buf[2];
207		}
208
209		break;
210
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;
217
218	case LINE6_RESET:
219		dev_info(variax->line6.ifcdev, "VARIAX reset\n");
220		break;
221
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;
244
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);
261				}
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);
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		DEBUG_MESSAGES(dev_err
297			       (variax->line6.ifcdev,
298				"Variax: unknown message %02X\n", buf[0]));
299	}
300}
301
302/*
303	"read" request on "volume" special file.
304*/
305static ssize_t variax_get_volume(struct device *dev,
306				 struct device_attribute *attr, char *buf)
307{
308	struct usb_line6_variax *variax =
309	    usb_get_intfdata(to_usb_interface(dev));
310	return sprintf(buf, "%d\n", variax->volume);
311}
312
313/*
314	"write" request on "volume" special file.
315*/
316static ssize_t variax_set_volume(struct device *dev,
317				 struct device_attribute *attr,
318				 const char *buf, size_t count)
319{
320	struct usb_line6_variax *variax =
321	    usb_get_intfdata(to_usb_interface(dev));
322	unsigned long value;
323	int ret;
324
325	ret = strict_strtoul(buf, 10, &value);
326	if (ret)
327		return ret;
328
329	if (line6_transmit_parameter(&variax->line6, VARIAXMIDI_volume,
330				     value) == 0)
331		variax->volume = value;
332
333	return count;
334}
335
336/*
337	"read" request on "model" special file.
338*/
339static ssize_t variax_get_model(struct device *dev,
340				struct device_attribute *attr, char *buf)
341{
342	struct usb_line6_variax *variax =
343	    usb_get_intfdata(to_usb_interface(dev));
344	return sprintf(buf, "%d\n", variax->model);
345}
346
347/*
348	"write" request on "model" special file.
349*/
350static ssize_t variax_set_model(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	unsigned long value;
357	int ret;
358
359	ret = strict_strtoul(buf, 10, &value);
360	if (ret)
361		return ret;
362
363	if (line6_send_program(&variax->line6, value) == 0)
364		variax->model = value;
365
366	return count;
367}
368
369/*
370	"read" request on "active" special file.
371*/
372static ssize_t variax_get_active(struct device *dev,
373				 struct device_attribute *attr, char *buf)
374{
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]);
379}
380
381/*
382	"write" request on "active" special file.
383*/
384static ssize_t variax_set_active(struct device *dev,
385				 struct device_attribute *attr,
386				 const char *buf, size_t count)
387{
388	struct usb_line6_variax *variax =
389	    usb_get_intfdata(to_usb_interface(dev));
390	unsigned long value;
391	int ret;
392
393	ret = strict_strtoul(buf, 10, &value);
394	if (ret)
395		return ret;
396
397	variax_activate_async(variax, value ? 1 : 0);
398	return count;
399}
400
401/*
402	"read" request on "tone" special file.
403*/
404static ssize_t variax_get_tone(struct device *dev,
405			       struct device_attribute *attr, char *buf)
406{
407	struct usb_line6_variax *variax =
408	    usb_get_intfdata(to_usb_interface(dev));
409	return sprintf(buf, "%d\n", variax->tone);
410}
411
412/*
413	"write" request on "tone" special file.
414*/
415static ssize_t variax_set_tone(struct device *dev,
416			       struct device_attribute *attr,
417			       const char *buf, size_t count)
418{
419	struct usb_line6_variax *variax =
420	    usb_get_intfdata(to_usb_interface(dev));
421	unsigned long value;
422	int ret;
423
424	ret = strict_strtoul(buf, 10, &value);
425	if (ret)
426		return ret;
427
428	if (line6_transmit_parameter(&variax->line6, VARIAXMIDI_tone,
429				     value) == 0)
430		variax->tone = value;
431
432	return count;
433}
434
435static ssize_t get_string(char *buf, const char *data, int length)
436{
437	int i;
438	memcpy(buf, data, length);
439
440	for (i = length; i--;) {
441		char c = buf[i];
442
443		if ((c != 0) && (c != ' '))
444			break;
445	}
446
447	buf[i + 1] = '\n';
448	return i + 2;
449}
450
451/*
452	"read" request on "name" special file.
453*/
454static ssize_t variax_get_name(struct device *dev,
455			       struct device_attribute *attr, char *buf)
456{
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));
462}
463
464/*
465	"read" request on "bank" special file.
466*/
467static ssize_t variax_get_bank(struct device *dev,
468			       struct device_attribute *attr, char *buf)
469{
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));
474}
475
476/*
477	"read" request on "dump" special file.
478*/
479static ssize_t variax_get_dump(struct device *dev,
480			       struct device_attribute *attr, char *buf)
481{
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);
491}
492
493/*
494	"read" request on "guitar" special file.
495*/
496static ssize_t variax_get_guitar(struct device *dev,
497				 struct device_attribute *attr, char *buf)
498{
499	struct usb_line6_variax *variax =
500	    usb_get_intfdata(to_usb_interface(dev));
501	return sprintf(buf, "%s\n", variax->guitar);
502}
503
504#ifdef CONFIG_LINE6_USB_RAW
505
506static char *variax_alloc_sysex_buffer(struct usb_line6_variax *variax,
507				       int code, int size)
508{
509	return line6_alloc_sysex_buffer(&variax->line6, VARIAX_SYSEX_CODE, code,
510					size);
511}
512
513/*
514	"write" request on "raw" special file.
515*/
516static ssize_t variax_set_raw2(struct device *dev,
517			       struct device_attribute *attr,
518			       const char *buf, size_t count)
519{
520	struct usb_line6_variax *variax =
521	    usb_get_intfdata(to_usb_interface(dev));
522	int size;
523	int i;
524	char *sysex;
525
526	count -= count % 3;
527	size = count * 2;
528	sysex = variax_alloc_sysex_buffer(variax, VARIAX_SYSEX_PARAM, size);
529
530	if (!sysex)
531		return 0;
532
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;
542	}
543
544	line6_send_sysex_message(&variax->line6, sysex, size);
545	kfree(sysex);
546	return count;
547}
548
549#endif
550
551/* Variax workbench special files: */
552static DEVICE_ATTR(model, S_IWUSR | S_IRUGO, variax_get_model,
553		   variax_set_model);
554static DEVICE_ATTR(volume, S_IWUSR | S_IRUGO, variax_get_volume,
555		   variax_set_volume);
556static DEVICE_ATTR(tone, S_IWUSR | S_IRUGO, variax_get_tone, variax_set_tone);
557static DEVICE_ATTR(name, S_IRUGO, variax_get_name, line6_nop_write);
558static DEVICE_ATTR(bank, S_IRUGO, variax_get_bank, line6_nop_write);
559static DEVICE_ATTR(dump, S_IRUGO, variax_get_dump, line6_nop_write);
560static DEVICE_ATTR(active, S_IWUSR | S_IRUGO, variax_get_active,
561		   variax_set_active);
562static DEVICE_ATTR(guitar, S_IRUGO, variax_get_guitar, line6_nop_write);
563
564#ifdef CONFIG_LINE6_USB_RAW
565static DEVICE_ATTR(raw, S_IWUSR, line6_nop_read, line6_set_raw);
566static DEVICE_ATTR(raw2, S_IWUSR, line6_nop_read, variax_set_raw2);
567#endif
568
569/*
570	Variax destructor.
571*/
572static void variax_destruct(struct usb_interface *interface)
573{
574	struct usb_line6_variax *variax = usb_get_intfdata(interface);
575
576	if (variax == NULL)
577		return;
578	line6_cleanup_audio(&variax->line6);
579
580	del_timer(&variax->startup_timer1);
581	del_timer(&variax->startup_timer2);
582	cancel_work_sync(&variax->startup_work);
583
584	/* free dump request data: */
585	line6_dumpreq_destructbuf(&variax->dumpreq, 2);
586	line6_dumpreq_destructbuf(&variax->dumpreq, 1);
587	line6_dumpreq_destruct(&variax->dumpreq);
588
589	kfree(variax->buffer_activate);
590}
591
592/*
593	Create sysfs entries.
594*/
595static int variax_create_files2(struct device *dev)
596{
597	int err;
598	CHECK_RETURN(device_create_file(dev, &dev_attr_model));
599	CHECK_RETURN(device_create_file(dev, &dev_attr_volume));
600	CHECK_RETURN(device_create_file(dev, &dev_attr_tone));
601	CHECK_RETURN(device_create_file(dev, &dev_attr_name));
602	CHECK_RETURN(device_create_file(dev, &dev_attr_bank));
603	CHECK_RETURN(device_create_file(dev, &dev_attr_dump));
604	CHECK_RETURN(device_create_file(dev, &dev_attr_active));
605	CHECK_RETURN(device_create_file(dev, &dev_attr_guitar));
606#ifdef CONFIG_LINE6_USB_RAW
607	CHECK_RETURN(device_create_file(dev, &dev_attr_raw));
608	CHECK_RETURN(device_create_file(dev, &dev_attr_raw2));
609#endif
610	return 0;
611}
612
613/*
614	 Try to init workbench device.
615*/
616static int variax_try_init(struct usb_interface *interface,
617			   struct usb_line6_variax *variax)
618{
619	int err;
620
621	init_timer(&variax->startup_timer1);
622	init_timer(&variax->startup_timer2);
623	INIT_WORK(&variax->startup_work, variax_startup7);
624
625	if ((interface == NULL) || (variax == NULL))
626		return -ENODEV;
627
628	/* initialize USB buffers: */
629	err = line6_dumpreq_init(&variax->dumpreq, variax_request_model1,
630				 sizeof(variax_request_model1));
631
632	if (err < 0) {
633		dev_err(&interface->dev, "Out of memory\n");
634		return err;
635	}
636
637	err = line6_dumpreq_initbuf(&variax->dumpreq, variax_request_model2,
638				    sizeof(variax_request_model2), 1);
639
640	if (err < 0) {
641		dev_err(&interface->dev, "Out of memory\n");
642		return err;
643	}
644
645	err = line6_dumpreq_initbuf(&variax->dumpreq, variax_request_bank,
646				    sizeof(variax_request_bank), 2);
647
648	if (err < 0) {
649		dev_err(&interface->dev, "Out of memory\n");
650		return err;
651	}
652
653	variax->buffer_activate = kmemdup(variax_activate,
654					  sizeof(variax_activate), GFP_KERNEL);
655
656	if (variax->buffer_activate == NULL) {
657		dev_err(&interface->dev, "Out of memory\n");
658		return -ENOMEM;
659	}
660
661	/* initialize audio system: */
662	err = line6_init_audio(&variax->line6);
663	if (err < 0)
664		return err;
665
666	/* initialize MIDI subsystem: */
667	err = line6_init_midi(&variax->line6);
668	if (err < 0)
669		return err;
670
671	/* initiate startup procedure: */
672	variax_startup1(variax);
673	return 0;
674}
675
676/*
677	 Init workbench device (and clean up in case of failure).
678*/
679int line6_variax_init(struct usb_interface *interface,
680		      struct usb_line6_variax *variax)
681{
682	int err = variax_try_init(interface, variax);
683
684	if (err < 0)
685		variax_destruct(interface);
686
687	return err;
688}
689
690/*
691	Workbench device disconnected.
692*/
693void line6_variax_disconnect(struct usb_interface *interface)
694{
695	struct device *dev;
696
697	if (interface == NULL)
698		return;
699	dev = &interface->dev;
700
701	if (dev != NULL) {
702		/* remove sysfs entries: */
703		line6_variax_remove_files(0, 0, dev);
704		device_remove_file(dev, &dev_attr_model);
705		device_remove_file(dev, &dev_attr_volume);
706		device_remove_file(dev, &dev_attr_tone);
707		device_remove_file(dev, &dev_attr_name);
708		device_remove_file(dev, &dev_attr_bank);
709		device_remove_file(dev, &dev_attr_dump);
710		device_remove_file(dev, &dev_attr_active);
711		device_remove_file(dev, &dev_attr_guitar);
712#ifdef CONFIG_LINE6_USB_RAW
713		device_remove_file(dev, &dev_attr_raw);
714		device_remove_file(dev, &dev_attr_raw2);
715#endif
716	}
717
718	variax_destruct(interface);
719}
720