1
2
3
4
5
6
7
8
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
22
23
24static const char variax_init_version[] = {
25 0xf0, 0x7e, 0x7f, 0x06, 0x02, 0x00, 0x01, 0x0c,
26 0x07, 0x00, 0x00, 0x00
27};
28
29
30
31
32static const char variax_init_done[] = {
33 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6b
34};
35
36static const char variax_activate[] = {
37 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x2a, 0x01,
38 0xf7
39};
40
41
42static void variax_startup2(unsigned long data);
43static void variax_startup4(unsigned long data);
44static void variax_startup5(unsigned long data);
45
46static 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
55
56
57
58
59
60static void variax_startup1(struct usb_line6_variax *variax)
61{
62 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_INIT);
63
64
65 line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
66 variax_startup2, (unsigned long)variax);
67}
68
69static 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
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
83 line6_version_request_async(line6);
84}
85
86static void variax_startup3(struct usb_line6_variax *variax)
87{
88 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_WAIT);
89
90
91 line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY3,
92 variax_startup4, (unsigned long)variax);
93}
94
95static void variax_startup4(unsigned long data)
96{
97 struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
98 CHECK_STARTUP_PROGRESS(variax->startup_progress,
99 VARIAX_STARTUP_ACTIVATE);
100
101
102 variax_activate_async(variax, 1);
103 line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY4,
104 variax_startup5, (unsigned long)variax);
105}
106
107static void variax_startup5(unsigned long data)
108{
109 struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
110 CHECK_STARTUP_PROGRESS(variax->startup_progress,
111 VARIAX_STARTUP_WORKQUEUE);
112
113
114 schedule_work(&variax->startup_work);
115}
116
117static void variax_startup6(struct work_struct *work)
118{
119 struct usb_line6_variax *variax =
120 container_of(work, struct usb_line6_variax, startup_work);
121
122 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_SETUP);
123
124
125 line6_register_audio(&variax->line6);
126}
127
128
129
130
131void line6_variax_process_message(struct usb_line6_variax *variax)
132{
133 const unsigned char *buf = variax->line6.buffer_message;
134
135 switch (buf[0]) {
136 case LINE6_RESET:
137 dev_info(variax->line6.ifcdev, "VARIAX reset\n");
138 break;
139
140 case LINE6_SYSEX_BEGIN:
141 if (memcmp(buf + 1, variax_init_version + 1,
142 sizeof(variax_init_version) - 1) == 0) {
143 variax_startup3(variax);
144 } else if (memcmp(buf + 1, variax_init_done + 1,
145 sizeof(variax_init_done) - 1) == 0) {
146
147 variax_startup4((unsigned long)variax);
148 }
149 break;
150 }
151}
152
153
154
155
156static void variax_destruct(struct usb_interface *interface)
157{
158 struct usb_line6_variax *variax = usb_get_intfdata(interface);
159
160 if (variax == NULL)
161 return;
162 line6_cleanup_audio(&variax->line6);
163
164 del_timer(&variax->startup_timer1);
165 del_timer(&variax->startup_timer2);
166 cancel_work_sync(&variax->startup_work);
167
168 kfree(variax->buffer_activate);
169}
170
171
172
173
174static int variax_try_init(struct usb_interface *interface,
175 struct usb_line6_variax *variax)
176{
177 int err;
178
179 init_timer(&variax->startup_timer1);
180 init_timer(&variax->startup_timer2);
181 INIT_WORK(&variax->startup_work, variax_startup6);
182
183 if ((interface == NULL) || (variax == NULL))
184 return -ENODEV;
185
186
187 variax->buffer_activate = kmemdup(variax_activate,
188 sizeof(variax_activate), GFP_KERNEL);
189
190 if (variax->buffer_activate == NULL) {
191 dev_err(&interface->dev, "Out of memory\n");
192 return -ENOMEM;
193 }
194
195
196 err = line6_init_audio(&variax->line6);
197 if (err < 0)
198 return err;
199
200
201 err = line6_init_midi(&variax->line6);
202 if (err < 0)
203 return err;
204
205
206 variax_startup1(variax);
207 return 0;
208}
209
210
211
212
213int line6_variax_init(struct usb_interface *interface,
214 struct usb_line6_variax *variax)
215{
216 int err = variax_try_init(interface, variax);
217
218 if (err < 0)
219 variax_destruct(interface);
220
221 return err;
222}
223
224
225
226
227void line6_variax_disconnect(struct usb_interface *interface)
228{
229 if (interface == NULL)
230 return;
231
232 variax_destruct(interface);
233}
234