This source file includes following definitions.
- variax_activate_async
- variax_startup
- line6_variax_process_message
- line6_variax_disconnect
- variax_init
- variax_probe
1
2
3
4
5
6
7
8 #include <linux/slab.h>
9 #include <linux/spinlock.h>
10 #include <linux/usb.h>
11 #include <linux/wait.h>
12 #include <linux/module.h>
13 #include <sound/core.h>
14
15 #include "driver.h"
16
17 #define VARIAX_STARTUP_DELAY1 1000
18 #define VARIAX_STARTUP_DELAY3 100
19 #define VARIAX_STARTUP_DELAY4 100
20
21
22
23
24 enum {
25 VARIAX_STARTUP_VERSIONREQ,
26 VARIAX_STARTUP_ACTIVATE,
27 VARIAX_STARTUP_SETUP,
28 };
29
30 enum {
31 LINE6_PODXTLIVE_VARIAX,
32 LINE6_VARIAX
33 };
34
35 struct usb_line6_variax {
36
37 struct usb_line6 line6;
38
39
40 unsigned char *buffer_activate;
41
42
43 int startup_progress;
44 };
45
46 #define line6_to_variax(x) container_of(x, struct usb_line6_variax, line6)
47
48 #define VARIAX_OFFSET_ACTIVATE 7
49
50
51
52
53
54 static const char variax_init_version[] = {
55 0xf0, 0x7e, 0x7f, 0x06, 0x02, 0x00, 0x01, 0x0c,
56 0x07, 0x00, 0x00, 0x00
57 };
58
59
60
61
62 static const char variax_init_done[] = {
63 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6b
64 };
65
66 static const char variax_activate[] = {
67 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x2a, 0x01,
68 0xf7
69 };
70
71 static void variax_activate_async(struct usb_line6_variax *variax, int a)
72 {
73 variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a;
74 line6_send_raw_message_async(&variax->line6, variax->buffer_activate,
75 sizeof(variax_activate));
76 }
77
78
79
80
81
82
83
84
85 static void variax_startup(struct usb_line6 *line6)
86 {
87 struct usb_line6_variax *variax = line6_to_variax(line6);
88
89 switch (variax->startup_progress) {
90 case VARIAX_STARTUP_VERSIONREQ:
91
92 schedule_delayed_work(&line6->startup_work,
93 msecs_to_jiffies(VARIAX_STARTUP_DELAY1));
94
95 line6_version_request_async(line6);
96 break;
97 case VARIAX_STARTUP_ACTIVATE:
98
99 variax_activate_async(variax, 1);
100 variax->startup_progress = VARIAX_STARTUP_SETUP;
101 schedule_delayed_work(&line6->startup_work,
102 msecs_to_jiffies(VARIAX_STARTUP_DELAY4));
103 break;
104 case VARIAX_STARTUP_SETUP:
105
106 snd_card_register(variax->line6.card);
107 break;
108 }
109 }
110
111
112
113
114 static void line6_variax_process_message(struct usb_line6 *line6)
115 {
116 struct usb_line6_variax *variax = line6_to_variax(line6);
117 const unsigned char *buf = variax->line6.buffer_message;
118
119 switch (buf[0]) {
120 case LINE6_RESET:
121 dev_info(variax->line6.ifcdev, "VARIAX reset\n");
122 break;
123
124 case LINE6_SYSEX_BEGIN:
125 if (memcmp(buf + 1, variax_init_version + 1,
126 sizeof(variax_init_version) - 1) == 0) {
127 if (variax->startup_progress >= VARIAX_STARTUP_ACTIVATE)
128 break;
129 variax->startup_progress = VARIAX_STARTUP_ACTIVATE;
130 cancel_delayed_work(&line6->startup_work);
131 schedule_delayed_work(&line6->startup_work,
132 msecs_to_jiffies(VARIAX_STARTUP_DELAY3));
133 } else if (memcmp(buf + 1, variax_init_done + 1,
134 sizeof(variax_init_done) - 1) == 0) {
135
136 if (variax->startup_progress >= VARIAX_STARTUP_SETUP)
137 break;
138 cancel_delayed_work(&line6->startup_work);
139 schedule_delayed_work(&line6->startup_work, 0);
140 }
141 break;
142 }
143 }
144
145
146
147
148 static void line6_variax_disconnect(struct usb_line6 *line6)
149 {
150 struct usb_line6_variax *variax = line6_to_variax(line6);
151
152 kfree(variax->buffer_activate);
153 }
154
155
156
157
158 static int variax_init(struct usb_line6 *line6,
159 const struct usb_device_id *id)
160 {
161 struct usb_line6_variax *variax = line6_to_variax(line6);
162 int err;
163
164 line6->process_message = line6_variax_process_message;
165 line6->disconnect = line6_variax_disconnect;
166 line6->startup = variax_startup;
167
168
169 variax->buffer_activate = kmemdup(variax_activate,
170 sizeof(variax_activate), GFP_KERNEL);
171
172 if (variax->buffer_activate == NULL)
173 return -ENOMEM;
174
175
176 err = line6_init_midi(&variax->line6);
177 if (err < 0)
178 return err;
179
180
181 schedule_delayed_work(&line6->startup_work,
182 msecs_to_jiffies(VARIAX_STARTUP_DELAY1));
183 return 0;
184 }
185
186 #define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
187 #define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
188
189
190 static const struct usb_device_id variax_id_table[] = {
191 { LINE6_IF_NUM(0x4650, 1), .driver_info = LINE6_PODXTLIVE_VARIAX },
192 { LINE6_DEVICE(0x534d), .driver_info = LINE6_VARIAX },
193 {}
194 };
195
196 MODULE_DEVICE_TABLE(usb, variax_id_table);
197
198 static const struct line6_properties variax_properties_table[] = {
199 [LINE6_PODXTLIVE_VARIAX] = {
200 .id = "PODxtLive",
201 .name = "PODxt Live",
202 .capabilities = LINE6_CAP_CONTROL
203 | LINE6_CAP_CONTROL_MIDI,
204 .altsetting = 1,
205 .ep_ctrl_r = 0x86,
206 .ep_ctrl_w = 0x05,
207 .ep_audio_r = 0x82,
208 .ep_audio_w = 0x01,
209 },
210 [LINE6_VARIAX] = {
211 .id = "Variax",
212 .name = "Variax Workbench",
213 .capabilities = LINE6_CAP_CONTROL
214 | LINE6_CAP_CONTROL_MIDI,
215 .altsetting = 1,
216 .ep_ctrl_r = 0x82,
217 .ep_ctrl_w = 0x01,
218
219 }
220 };
221
222
223
224
225 static int variax_probe(struct usb_interface *interface,
226 const struct usb_device_id *id)
227 {
228 return line6_probe(interface, id, "Line6-Variax",
229 &variax_properties_table[id->driver_info],
230 variax_init, sizeof(struct usb_line6_variax));
231 }
232
233 static struct usb_driver variax_driver = {
234 .name = KBUILD_MODNAME,
235 .probe = variax_probe,
236 .disconnect = line6_disconnect,
237 #ifdef CONFIG_PM
238 .suspend = line6_suspend,
239 .resume = line6_resume,
240 .reset_resume = line6_resume,
241 #endif
242 .id_table = variax_id_table,
243 };
244
245 module_usb_driver(variax_driver);
246
247 MODULE_DESCRIPTION("Variax Workbench USB driver");
248 MODULE_LICENSE("GPL");