2 * Line 6 Linux USB driver
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>
13 #include <linux/spinlock.h>
14 #include <linux/usb.h>
15 #include <linux/wait.h>
16 #include <linux/module.h>
17 #include <sound/core.h>
22 #define VARIAX_STARTUP_DELAY1 1000
23 #define VARIAX_STARTUP_DELAY3 100
24 #define VARIAX_STARTUP_DELAY4 100
27 Stages of Variax startup procedure
30 VARIAX_STARTUP_INIT = 1,
31 VARIAX_STARTUP_VERSIONREQ,
33 VARIAX_STARTUP_ACTIVATE,
34 VARIAX_STARTUP_WORKQUEUE,
36 VARIAX_STARTUP_LAST = VARIAX_STARTUP_SETUP - 1
40 LINE6_PODXTLIVE_VARIAX,
44 struct usb_line6_variax {
45 /* Generic Line 6 USB data */
46 struct usb_line6 line6;
48 /* Buffer for activation code */
49 unsigned char *buffer_activate;
51 /* Handler for device initialization */
52 struct work_struct startup_work;
54 /* Timers for device initialization */
55 struct timer_list startup_timer1;
56 struct timer_list startup_timer2;
58 /* Current progress in startup procedure */
62 #define VARIAX_OFFSET_ACTIVATE 7
65 This message is sent by the device during initialization and identifies
66 the connected guitar version.
68 static const char variax_init_version[] = {
69 0xf0, 0x7e, 0x7f, 0x06, 0x02, 0x00, 0x01, 0x0c,
70 0x07, 0x00, 0x00, 0x00
74 This message is the last one sent by the device during initialization.
76 static const char variax_init_done[] = {
77 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6b
80 static const char variax_activate[] = {
81 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x2a, 0x01,
85 /* forward declarations: */
86 static void variax_startup2(unsigned long data);
87 static void variax_startup4(unsigned long data);
88 static void variax_startup5(unsigned long data);
90 static void variax_activate_async(struct usb_line6_variax *variax, int a)
92 variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a;
93 line6_send_raw_message_async(&variax->line6, variax->buffer_activate,
94 sizeof(variax_activate));
98 Variax startup procedure.
99 This is a sequence of functions with special requirements (e.g., must
100 not run immediately after initialization, must not run in interrupt
101 context). After the last one has finished, the device is ready to use.
104 static void variax_startup1(struct usb_line6_variax *variax)
106 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_INIT);
108 /* delay startup procedure: */
109 line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
110 variax_startup2, (unsigned long)variax);
113 static void variax_startup2(unsigned long data)
115 struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
116 struct usb_line6 *line6 = &variax->line6;
118 /* schedule another startup procedure until startup is complete: */
119 if (variax->startup_progress >= VARIAX_STARTUP_LAST)
122 variax->startup_progress = VARIAX_STARTUP_VERSIONREQ;
123 line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
124 variax_startup2, (unsigned long)variax);
126 /* request firmware version: */
127 line6_version_request_async(line6);
130 static void variax_startup3(struct usb_line6_variax *variax)
132 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_WAIT);
134 /* delay startup procedure: */
135 line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY3,
136 variax_startup4, (unsigned long)variax);
139 static void variax_startup4(unsigned long data)
141 struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
143 CHECK_STARTUP_PROGRESS(variax->startup_progress,
144 VARIAX_STARTUP_ACTIVATE);
146 /* activate device: */
147 variax_activate_async(variax, 1);
148 line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY4,
149 variax_startup5, (unsigned long)variax);
152 static void variax_startup5(unsigned long data)
154 struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
156 CHECK_STARTUP_PROGRESS(variax->startup_progress,
157 VARIAX_STARTUP_WORKQUEUE);
159 /* schedule work for global work queue: */
160 schedule_work(&variax->startup_work);
163 static void variax_startup6(struct work_struct *work)
165 struct usb_line6_variax *variax =
166 container_of(work, struct usb_line6_variax, startup_work);
168 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_SETUP);
170 /* ALSA audio interface: */
171 snd_card_register(variax->line6.card);
175 Process a completely received message.
177 static void line6_variax_process_message(struct usb_line6 *line6)
179 struct usb_line6_variax *variax = (struct usb_line6_variax *) line6;
180 const unsigned char *buf = variax->line6.buffer_message;
184 dev_info(variax->line6.ifcdev, "VARIAX reset\n");
187 case LINE6_SYSEX_BEGIN:
188 if (memcmp(buf + 1, variax_init_version + 1,
189 sizeof(variax_init_version) - 1) == 0) {
190 variax_startup3(variax);
191 } else if (memcmp(buf + 1, variax_init_done + 1,
192 sizeof(variax_init_done) - 1) == 0) {
193 /* notify of complete initialization: */
194 variax_startup4((unsigned long)variax);
203 static void line6_variax_disconnect(struct usb_line6 *line6)
205 struct usb_line6_variax *variax = (struct usb_line6_variax *)line6;
207 del_timer(&variax->startup_timer1);
208 del_timer(&variax->startup_timer2);
209 cancel_work_sync(&variax->startup_work);
211 kfree(variax->buffer_activate);
215 Try to init workbench device.
217 static int variax_init(struct usb_line6 *line6,
218 const struct usb_device_id *id)
220 struct usb_line6_variax *variax = (struct usb_line6_variax *) line6;
223 line6->process_message = line6_variax_process_message;
224 line6->disconnect = line6_variax_disconnect;
226 init_timer(&variax->startup_timer1);
227 init_timer(&variax->startup_timer2);
228 INIT_WORK(&variax->startup_work, variax_startup6);
230 /* initialize USB buffers: */
231 variax->buffer_activate = kmemdup(variax_activate,
232 sizeof(variax_activate), GFP_KERNEL);
234 if (variax->buffer_activate == NULL)
237 /* initialize MIDI subsystem: */
238 err = line6_init_midi(&variax->line6);
242 /* initiate startup procedure: */
243 variax_startup1(variax);
247 #define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
248 #define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
250 /* table of devices that work with this driver */
251 static const struct usb_device_id variax_id_table[] = {
252 { LINE6_IF_NUM(0x4650, 1), .driver_info = LINE6_PODXTLIVE_VARIAX },
253 { LINE6_DEVICE(0x534d), .driver_info = LINE6_VARIAX },
257 MODULE_DEVICE_TABLE(usb, variax_id_table);
259 static const struct line6_properties variax_properties_table[] = {
260 [LINE6_PODXTLIVE_VARIAX] = {
262 .name = "PODxt Live",
263 .capabilities = LINE6_CAP_CONTROL
274 .name = "Variax Workbench",
275 .capabilities = LINE6_CAP_CONTROL,
279 /* no audio channel */
286 static int variax_probe(struct usb_interface *interface,
287 const struct usb_device_id *id)
289 return line6_probe(interface, id,
290 &variax_properties_table[id->driver_info],
291 variax_init, sizeof(struct usb_line6_variax));
294 static struct usb_driver variax_driver = {
295 .name = KBUILD_MODNAME,
296 .probe = variax_probe,
297 .disconnect = line6_disconnect,
299 .suspend = line6_suspend,
300 .resume = line6_resume,
301 .reset_resume = line6_resume,
303 .id_table = variax_id_table,
306 module_usb_driver(variax_driver);
308 MODULE_DESCRIPTION("Vairax Workbench USB driver");
309 MODULE_LICENSE("GPL");