]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/line6/variax.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid...
[karo-tx-linux.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 "driver.h"
16 #include "variax.h"
17
18 #define VARIAX_OFFSET_ACTIVATE 7
19
20 /*
21         This message is sent by the device during initialization and identifies
22         the connected guitar version.
23 */
24 static const char variax_init_version[] = {
25         0xf0, 0x7e, 0x7f, 0x06, 0x02, 0x00, 0x01, 0x0c,
26         0x07, 0x00, 0x00, 0x00
27 };
28
29 /*
30         This message is the last one sent by the device during initialization.
31 */
32 static const char variax_init_done[] = {
33         0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6b
34 };
35
36 static const char variax_activate[] = {
37         0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x2a, 0x01,
38         0xf7
39 };
40
41 /* forward declarations: */
42 static void variax_startup2(unsigned long data);
43 static void variax_startup4(unsigned long data);
44 static void variax_startup5(unsigned long data);
45
46 static void variax_activate_async(struct usb_line6_variax *variax, int a)
47 {
48         variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a;
49         line6_send_raw_message_async(&variax->line6, variax->buffer_activate,
50                                      sizeof(variax_activate));
51 }
52
53 /*
54         Variax startup procedure.
55         This is a sequence of functions with special requirements (e.g., must
56         not run immediately after initialization, must not run in interrupt
57         context). After the last one has finished, the device is ready to use.
58 */
59
60 static void variax_startup1(struct usb_line6_variax *variax)
61 {
62         CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_INIT);
63
64         /* delay startup procedure: */
65         line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
66                           variax_startup2, (unsigned long)variax);
67 }
68
69 static void variax_startup2(unsigned long data)
70 {
71         struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
72         struct usb_line6 *line6 = &variax->line6;
73
74         /* schedule another startup procedure until startup is complete: */
75         if (variax->startup_progress >= VARIAX_STARTUP_LAST)
76                 return;
77
78         variax->startup_progress = VARIAX_STARTUP_VERSIONREQ;
79         line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
80                           variax_startup2, (unsigned long)variax);
81
82         /* request firmware version: */
83         line6_version_request_async(line6);
84 }
85
86 static void variax_startup3(struct usb_line6_variax *variax)
87 {
88         CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_WAIT);
89
90         /* delay startup procedure: */
91         line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY3,
92                           variax_startup4, (unsigned long)variax);
93 }
94
95 static void variax_startup4(unsigned long data)
96 {
97         struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
98
99         CHECK_STARTUP_PROGRESS(variax->startup_progress,
100                                VARIAX_STARTUP_ACTIVATE);
101
102         /* activate device: */
103         variax_activate_async(variax, 1);
104         line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY4,
105                           variax_startup5, (unsigned long)variax);
106 }
107
108 static void variax_startup5(unsigned long data)
109 {
110         struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
111
112         CHECK_STARTUP_PROGRESS(variax->startup_progress,
113                                VARIAX_STARTUP_WORKQUEUE);
114
115         /* schedule work for global work queue: */
116         schedule_work(&variax->startup_work);
117 }
118
119 static void variax_startup6(struct work_struct *work)
120 {
121         struct usb_line6_variax *variax =
122             container_of(work, struct usb_line6_variax, startup_work);
123
124         CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_SETUP);
125
126         /* ALSA audio interface: */
127         line6_register_audio(&variax->line6);
128 }
129
130 /*
131         Process a completely received message.
132 */
133 void line6_variax_process_message(struct usb_line6_variax *variax)
134 {
135         const unsigned char *buf = variax->line6.buffer_message;
136
137         switch (buf[0]) {
138         case LINE6_RESET:
139                 dev_info(variax->line6.ifcdev, "VARIAX reset\n");
140                 break;
141
142         case LINE6_SYSEX_BEGIN:
143                 if (memcmp(buf + 1, variax_init_version + 1,
144                            sizeof(variax_init_version) - 1) == 0) {
145                         variax_startup3(variax);
146                 } else if (memcmp(buf + 1, variax_init_done + 1,
147                                   sizeof(variax_init_done) - 1) == 0) {
148                         /* notify of complete initialization: */
149                         variax_startup4((unsigned long)variax);
150                 }
151                 break;
152         }
153 }
154
155 /*
156         Variax destructor.
157 */
158 static void variax_destruct(struct usb_interface *interface)
159 {
160         struct usb_line6_variax *variax = usb_get_intfdata(interface);
161
162         if (variax == NULL)
163                 return;
164         line6_cleanup_audio(&variax->line6);
165
166         del_timer(&variax->startup_timer1);
167         del_timer(&variax->startup_timer2);
168         cancel_work_sync(&variax->startup_work);
169
170         kfree(variax->buffer_activate);
171 }
172
173 /*
174          Try to init workbench device.
175 */
176 static int variax_try_init(struct usb_interface *interface,
177                            struct usb_line6_variax *variax)
178 {
179         int err;
180
181         init_timer(&variax->startup_timer1);
182         init_timer(&variax->startup_timer2);
183         INIT_WORK(&variax->startup_work, variax_startup6);
184
185         if ((interface == NULL) || (variax == NULL))
186                 return -ENODEV;
187
188         /* initialize USB buffers: */
189         variax->buffer_activate = kmemdup(variax_activate,
190                                           sizeof(variax_activate), GFP_KERNEL);
191
192         if (variax->buffer_activate == NULL) {
193                 dev_err(&interface->dev, "Out of memory\n");
194                 return -ENOMEM;
195         }
196
197         /* initialize audio system: */
198         err = line6_init_audio(&variax->line6);
199         if (err < 0)
200                 return err;
201
202         /* initialize MIDI subsystem: */
203         err = line6_init_midi(&variax->line6);
204         if (err < 0)
205                 return err;
206
207         /* initiate startup procedure: */
208         variax_startup1(variax);
209         return 0;
210 }
211
212 /*
213          Init workbench device (and clean up in case of failure).
214 */
215 int line6_variax_init(struct usb_interface *interface,
216                       struct usb_line6_variax *variax)
217 {
218         int err = variax_try_init(interface, variax);
219
220         if (err < 0)
221                 variax_destruct(interface);
222
223         return err;
224 }
225
226 /*
227         Workbench device disconnected.
228 */
229 void line6_variax_disconnect(struct usb_interface *interface)
230 {
231         if (interface == NULL)
232                 return;
233
234         variax_destruct(interface);
235 }