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>
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,
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,
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,
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);
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)
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,
163 /* passes 2 and 3 are performed implicitly before entering
168 static void variax_startup6(struct usb_line6_variax *variax)
170 CHECK_STARTUP_PROGRESS(variax->startup_progress,
171 VARIAX_STARTUP_WORKQUEUE);
173 /* schedule work for global work queue: */
174 schedule_work(&variax->startup_work);
177 static void variax_startup7(struct work_struct *work)
179 struct usb_line6_variax *variax =
180 container_of(work, struct usb_line6_variax, startup_work);
181 struct usb_line6 *line6 = &variax->line6;
183 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_SETUP);
185 /* ALSA audio interface: */
186 line6_register_audio(&variax->line6);
189 line6_variax_create_files(0, 0, line6->ifcdev);
190 variax_create_files2(line6->ifcdev);
194 Process a completely received message.
196 void line6_variax_process_message(struct usb_line6_variax *variax)
198 const unsigned char *buf = variax->line6.buffer_message;
201 case LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST:
204 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE:
205 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST:
206 line6_dump_request_async(&variax->dumpreq, &variax->line6, 0,
211 dev_info(variax->line6.ifcdev, "VARIAX reset\n");
214 case LINE6_SYSEX_BEGIN:
215 if (memcmp(buf + 1, variax_request_model1 + 1,
216 VARIAX_MODEL_HEADER_LENGTH - 1) == 0) {
217 if (variax->line6.message_length ==
218 VARIAX_MODEL_MESSAGE_LENGTH) {
219 switch (variax->dumpreq.in_progress) {
220 case VARIAX_DUMP_PASS1:
221 line6_dump_request_async
222 (&variax->dumpreq, &variax->line6,
223 1, VARIAX_DUMP_PASS2);
226 case VARIAX_DUMP_PASS2:
227 /* model name is transmitted twice, so skip it here: */
229 VARIAX_MODEL_HEADER_LENGTH,
233 sizeof(variax->model_data.
236 sizeof(variax->model_data.
239 line6_dump_request_async
240 (&variax->dumpreq, &variax->line6,
241 2, VARIAX_DUMP_PASS3);
244 dev_dbg(variax->line6.ifcdev,
245 "illegal length %d of model data\n",
246 variax->line6.message_length);
247 line6_dump_finished(&variax->dumpreq);
249 } else if (memcmp(buf + 1, variax_request_bank + 1,
250 sizeof(variax_request_bank) - 2) == 0) {
251 line6_dump_finished(&variax->dumpreq);
252 variax_startup6(variax);
253 } else if (memcmp(buf + 1, variax_init_model + 1,
254 sizeof(variax_init_model) - 1) == 0) {
255 memcpy(variax->guitar,
256 buf + sizeof(variax_init_model),
257 sizeof(variax->guitar));
258 } else if (memcmp(buf + 1, variax_init_version + 1,
259 sizeof(variax_init_version) - 1) == 0) {
260 variax_startup3(variax);
261 } else if (memcmp(buf + 1, variax_init_done + 1,
262 sizeof(variax_init_done) - 1) == 0) {
263 /* notify of complete initialization: */
264 variax_startup4((unsigned long)variax);
269 case LINE6_SYSEX_END:
273 dev_dbg(variax->line6.ifcdev,
274 "Variax: unknown message %02X\n", buf[0]);
279 "read" request on "active" special file.
281 static ssize_t variax_get_active(struct device *dev,
282 struct device_attribute *attr, char *buf)
284 struct usb_line6_variax *variax =
285 usb_get_intfdata(to_usb_interface(dev));
286 return sprintf(buf, "%d\n",
287 variax->buffer_activate[VARIAX_OFFSET_ACTIVATE]);
291 "write" request on "active" special file.
293 static ssize_t variax_set_active(struct device *dev,
294 struct device_attribute *attr,
295 const char *buf, size_t count)
297 struct usb_line6_variax *variax =
298 usb_get_intfdata(to_usb_interface(dev));
302 ret = kstrtou8(buf, 10, &value);
306 variax_activate_async(variax, value ? 1 : 0);
311 "read" request on "dump" special file.
313 static ssize_t variax_get_dump(struct device *dev,
314 struct device_attribute *attr, char *buf)
316 struct usb_line6_variax *variax =
317 usb_get_intfdata(to_usb_interface(dev));
319 retval = line6_dump_wait_interruptible(&variax->dumpreq);
322 memcpy(buf, &variax->model_data.control,
323 sizeof(variax->model_data.control));
324 return sizeof(variax->model_data.control);
328 "read" request on "guitar" special file.
330 static ssize_t variax_get_guitar(struct device *dev,
331 struct device_attribute *attr, char *buf)
333 struct usb_line6_variax *variax =
334 usb_get_intfdata(to_usb_interface(dev));
335 return sprintf(buf, "%s\n", variax->guitar);
338 #ifdef CONFIG_LINE6_USB_RAW
340 static char *variax_alloc_sysex_buffer(struct usb_line6_variax *variax,
343 return line6_alloc_sysex_buffer(&variax->line6, VARIAX_SYSEX_CODE, code,
348 "write" request on "raw" special file.
350 static ssize_t variax_set_raw2(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));
362 sysex = variax_alloc_sysex_buffer(variax, VARIAX_SYSEX_PARAM, size);
367 for (i = 0; i < count; i += 3) {
368 const unsigned char *p1 = buf + i;
369 char *p2 = sysex + SYSEX_DATA_OFS + i * 2;
370 p2[0] = p1[2] & 0x0f;
372 p2[2] = p1[1] & 0x0f;
374 p2[4] = p1[0] & 0x0f;
378 line6_send_sysex_message(&variax->line6, sysex, size);
385 /* Variax workbench special files: */
386 static DEVICE_ATTR(dump, S_IRUGO, variax_get_dump, line6_nop_write);
387 static DEVICE_ATTR(active, S_IWUSR | S_IRUGO, variax_get_active,
389 static DEVICE_ATTR(guitar, S_IRUGO, variax_get_guitar, line6_nop_write);
391 #ifdef CONFIG_LINE6_USB_RAW
392 static DEVICE_ATTR(raw, S_IWUSR, line6_nop_read, line6_set_raw);
393 static DEVICE_ATTR(raw2, S_IWUSR, line6_nop_read, variax_set_raw2);
399 static void variax_destruct(struct usb_interface *interface)
401 struct usb_line6_variax *variax = usb_get_intfdata(interface);
405 line6_cleanup_audio(&variax->line6);
407 del_timer(&variax->startup_timer1);
408 del_timer(&variax->startup_timer2);
409 cancel_work_sync(&variax->startup_work);
411 /* free dump request data: */
412 line6_dumpreq_destructbuf(&variax->dumpreq, 2);
413 line6_dumpreq_destructbuf(&variax->dumpreq, 1);
414 line6_dumpreq_destruct(&variax->dumpreq);
416 kfree(variax->buffer_activate);
420 Create sysfs entries.
422 static int variax_create_files2(struct device *dev)
425 CHECK_RETURN(device_create_file(dev, &dev_attr_dump));
426 CHECK_RETURN(device_create_file(dev, &dev_attr_active));
427 CHECK_RETURN(device_create_file(dev, &dev_attr_guitar));
428 #ifdef CONFIG_LINE6_USB_RAW
429 CHECK_RETURN(device_create_file(dev, &dev_attr_raw));
430 CHECK_RETURN(device_create_file(dev, &dev_attr_raw2));
436 Try to init workbench device.
438 static int variax_try_init(struct usb_interface *interface,
439 struct usb_line6_variax *variax)
443 init_timer(&variax->startup_timer1);
444 init_timer(&variax->startup_timer2);
445 INIT_WORK(&variax->startup_work, variax_startup7);
447 if ((interface == NULL) || (variax == NULL))
450 /* initialize USB buffers: */
451 err = line6_dumpreq_init(&variax->dumpreq, variax_request_model1,
452 sizeof(variax_request_model1));
455 dev_err(&interface->dev, "Out of memory\n");
459 err = line6_dumpreq_initbuf(&variax->dumpreq, variax_request_model2,
460 sizeof(variax_request_model2), 1);
463 dev_err(&interface->dev, "Out of memory\n");
467 err = line6_dumpreq_initbuf(&variax->dumpreq, variax_request_bank,
468 sizeof(variax_request_bank), 2);
471 dev_err(&interface->dev, "Out of memory\n");
475 variax->buffer_activate = kmemdup(variax_activate,
476 sizeof(variax_activate), GFP_KERNEL);
478 if (variax->buffer_activate == NULL) {
479 dev_err(&interface->dev, "Out of memory\n");
483 /* initialize audio system: */
484 err = line6_init_audio(&variax->line6);
488 /* initialize MIDI subsystem: */
489 err = line6_init_midi(&variax->line6);
493 /* initiate startup procedure: */
494 variax_startup1(variax);
499 Init workbench device (and clean up in case of failure).
501 int line6_variax_init(struct usb_interface *interface,
502 struct usb_line6_variax *variax)
504 int err = variax_try_init(interface, variax);
507 variax_destruct(interface);
513 Workbench device disconnected.
515 void line6_variax_disconnect(struct usb_interface *interface)
519 if (interface == NULL)
521 dev = &interface->dev;
524 /* remove sysfs entries: */
525 line6_variax_remove_files(0, 0, dev);
526 device_remove_file(dev, &dev_attr_dump);
527 device_remove_file(dev, &dev_attr_active);
528 device_remove_file(dev, &dev_attr_guitar);
529 #ifdef CONFIG_LINE6_USB_RAW
530 device_remove_file(dev, &dev_attr_raw);
531 device_remove_file(dev, &dev_attr_raw2);
535 variax_destruct(interface);