staging: comedi: 8255_pci: fix possible NULL deref during detach
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / line6 / variax.c
CommitLineData
705ececd 1/*
e1a164d7 2 * Line6 Linux USB driver - 0.9.1beta
705ececd 3 *
1027f476 4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
705ececd
MG
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
5a0e3ad6
TH
12#include <linux/slab.h>
13
705ececd
MG
14#include "audio.h"
15#include "control.h"
1027f476 16#include "driver.h"
705ececd
MG
17#include "variax.h"
18
705ececd
MG
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
25
1027f476
MG
26/*
27 This message is sent by the device during initialization and identifies
28 the connected guitar model.
29*/
30static const char variax_init_model[] = {
31 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x69, 0x02,
32 0x00
33};
34
35/*
36 This message is sent by the device during initialization and identifies
37 the connected guitar version.
38*/
39static const char variax_init_version[] = {
40 0xf0, 0x7e, 0x7f, 0x06, 0x02, 0x00, 0x01, 0x0c,
41 0x07, 0x00, 0x00, 0x00
42};
43
44/*
45 This message is the last one sent by the device during initialization.
46*/
47static const char variax_init_done[] = {
48 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6b
49};
50
705ececd
MG
51static const char variax_activate[] = {
52 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x2a, 0x01,
53 0xf7
54};
1027f476 55
705ececd
MG
56static const char variax_request_bank[] = {
57 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6d, 0xf7
58};
1027f476 59
705ececd
MG
60static 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
64};
1027f476 65
705ececd
MG
66static 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
70};
71
1027f476
MG
72/* forward declarations: */
73static int variax_create_files2(struct device *dev);
74static void variax_startup2(unsigned long data);
75static void variax_startup4(unsigned long data);
76static void variax_startup5(unsigned long data);
77
705ececd
MG
78/*
79 Decode data transmitted by workbench.
80*/
9cd57f77
GKH
81static void variax_decode(const unsigned char *raw_data, unsigned char *data,
82 int raw_size)
705ececd 83{
9cd57f77 84 for (; raw_size > 0; raw_size -= 6) {
705ececd
MG
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);
88 raw_data += 6;
89 data += 3;
90 }
91}
92
1027f476 93static void variax_activate_async(struct usb_line6_variax *variax, int a)
705ececd 94{
1027f476 95 variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a;
9cd57f77
GKH
96 line6_send_raw_message_async(&variax->line6, variax->buffer_activate,
97 sizeof(variax_activate));
705ececd
MG
98}
99
100/*
1027f476
MG
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.
705ececd 105*/
1027f476
MG
106
107static void variax_startup1(struct usb_line6_variax *variax)
705ececd 108{
e1a164d7 109 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_INIT);
1027f476
MG
110
111 /* delay startup procedure: */
e1a164d7
MG
112 line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
113 variax_startup2, (unsigned long)variax);
705ececd
MG
114}
115
1027f476 116static void variax_startup2(unsigned long data)
705ececd 117{
1027f476
MG
118 struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
119 struct usb_line6 *line6 = &variax->line6;
e1a164d7
MG
120
121 /* schedule another startup procedure until startup is complete: */
122 if (variax->startup_progress >= VARIAX_STARTUP_LAST)
123 return;
124
125 variax->startup_progress = VARIAX_STARTUP_VERSIONREQ;
126 line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
127 variax_startup2, (unsigned long)variax);
705ececd 128
1027f476
MG
129 /* request firmware version: */
130 line6_version_request_async(line6);
131}
705ececd 132
1027f476
MG
133static void variax_startup3(struct usb_line6_variax *variax)
134{
e1a164d7 135 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_WAIT);
1027f476
MG
136
137 /* delay startup procedure: */
e1a164d7
MG
138 line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY3,
139 variax_startup4, (unsigned long)variax);
1027f476
MG
140}
141
142static void variax_startup4(unsigned long data)
143{
144 struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
e1a164d7
MG
145 CHECK_STARTUP_PROGRESS(variax->startup_progress,
146 VARIAX_STARTUP_ACTIVATE);
1027f476
MG
147
148 /* activate device: */
149 variax_activate_async(variax, 1);
e1a164d7
MG
150 line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY4,
151 variax_startup5, (unsigned long)variax);
1027f476
MG
152}
153
154static void variax_startup5(unsigned long data)
155{
156 struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
e1a164d7
MG
157 CHECK_STARTUP_PROGRESS(variax->startup_progress,
158 VARIAX_STARTUP_DUMPREQ);
1027f476
MG
159
160 /* current model dump: */
e1a164d7
MG
161 line6_dump_request_async(&variax->dumpreq, &variax->line6, 0,
162 VARIAX_DUMP_PASS1);
1027f476
MG
163 /* passes 2 and 3 are performed implicitly before entering variax_startup6 */
164}
165
166static void variax_startup6(struct usb_line6_variax *variax)
167{
e1a164d7
MG
168 CHECK_STARTUP_PROGRESS(variax->startup_progress,
169 VARIAX_STARTUP_WORKQUEUE);
1027f476
MG
170
171 /* schedule work for global work queue: */
172 schedule_work(&variax->startup_work);
173}
174
175static void variax_startup7(struct work_struct *work)
176{
e1a164d7
MG
177 struct usb_line6_variax *variax =
178 container_of(work, struct usb_line6_variax, startup_work);
1027f476
MG
179 struct usb_line6 *line6 = &variax->line6;
180
e1a164d7 181 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_SETUP);
1027f476
MG
182
183 /* ALSA audio interface: */
184 line6_register_audio(&variax->line6);
185
186 /* device files: */
187 line6_variax_create_files(0, 0, line6->ifcdev);
188 variax_create_files2(line6->ifcdev);
705ececd
MG
189}
190
191/*
192 Process a completely received message.
193*/
1027f476 194void line6_variax_process_message(struct usb_line6_variax *variax)
705ececd
MG
195{
196 const unsigned char *buf = variax->line6.buffer_message;
197
9cd57f77 198 switch (buf[0]) {
705ececd 199 case LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST:
9cd57f77 200 switch (buf[1]) {
705ececd
MG
201 case VARIAXMIDI_volume:
202 variax->volume = buf[2];
203 break;
204
205 case VARIAXMIDI_tone:
206 variax->tone = buf[2];
207 }
208
209 break;
210
211 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE:
212 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST:
213 variax->model = buf[1];
e1a164d7
MG
214 line6_dump_request_async(&variax->dumpreq, &variax->line6, 0,
215 VARIAX_DUMP_PASS1);
705ececd
MG
216 break;
217
218 case LINE6_RESET:
219 dev_info(variax->line6.ifcdev, "VARIAX reset\n");
705ececd
MG
220 break;
221
222 case LINE6_SYSEX_BEGIN:
9cd57f77
GKH
223 if (memcmp(buf + 1, variax_request_model1 + 1,
224 VARIAX_MODEL_HEADER_LENGTH - 1) == 0) {
225 if (variax->line6.message_length ==
226 VARIAX_MODEL_MESSAGE_LENGTH) {
227 switch (variax->dumpreq.in_progress) {
705ececd 228 case VARIAX_DUMP_PASS1:
e1a164d7
MG
229 variax_decode(buf +
230 VARIAX_MODEL_HEADER_LENGTH,
231 (unsigned char *)
232 &variax->model_data,
233 (sizeof
234 (variax->model_data.
235 name) +
236 sizeof(variax->
237 model_data.
238 control)
239 / 2) * 2);
240 line6_dump_request_async
241 (&variax->dumpreq, &variax->line6,
242 1, VARIAX_DUMP_PASS2);
705ececd
MG
243 break;
244
245 case VARIAX_DUMP_PASS2:
246 /* model name is transmitted twice, so skip it here: */
e1a164d7
MG
247 variax_decode(buf +
248 VARIAX_MODEL_HEADER_LENGTH,
249 (unsigned char *)
250 &variax->
251 model_data.control +
252 sizeof(variax->model_data.
253 control)
254 / 2,
255 sizeof(variax->model_data.
256 control)
257 / 2 * 2);
258 line6_dump_request_async
259 (&variax->dumpreq, &variax->line6,
260 2, VARIAX_DUMP_PASS3);
705ececd 261 }
9cd57f77 262 } else {
e1a164d7
MG
263 DEBUG_MESSAGES(dev_err
264 (variax->line6.ifcdev,
265 "illegal length %d of model data\n",
266 variax->line6.message_length));
705ececd
MG
267 line6_dump_finished(&variax->dumpreq);
268 }
9cd57f77 269 } else if (memcmp(buf + 1, variax_request_bank + 1,
1027f476 270 sizeof(variax_request_bank) - 2) == 0) {
9cd57f77
GKH
271 memcpy(variax->bank,
272 buf + sizeof(variax_request_bank) - 1,
273 sizeof(variax->bank));
705ececd 274 line6_dump_finished(&variax->dumpreq);
1027f476
MG
275 variax_startup6(variax);
276 } else if (memcmp(buf + 1, variax_init_model + 1,
277 sizeof(variax_init_model) - 1) == 0) {
278 memcpy(variax->guitar,
279 buf + sizeof(variax_init_model),
280 sizeof(variax->guitar));
281 } else if (memcmp(buf + 1, variax_init_version + 1,
282 sizeof(variax_init_version) - 1) == 0) {
283 variax_startup3(variax);
284 } else if (memcmp(buf + 1, variax_init_done + 1,
285 sizeof(variax_init_done) - 1) == 0) {
286 /* notify of complete initialization: */
287 variax_startup4((unsigned long)variax);
705ececd
MG
288 }
289
290 break;
291
292 case LINE6_SYSEX_END:
293 break;
294
295 default:
e1a164d7
MG
296 DEBUG_MESSAGES(dev_err
297 (variax->line6.ifcdev,
298 "Variax: unknown message %02X\n", buf[0]));
705ececd
MG
299 }
300}
301
302/*
303 "read" request on "volume" special file.
304*/
77491e52
GKH
305static ssize_t variax_get_volume(struct device *dev,
306 struct device_attribute *attr, char *buf)
705ececd 307{
e1a164d7
MG
308 struct usb_line6_variax *variax =
309 usb_get_intfdata(to_usb_interface(dev));
705ececd
MG
310 return sprintf(buf, "%d\n", variax->volume);
311}
312
313/*
314 "write" request on "volume" special file.
315*/
77491e52
GKH
316static ssize_t variax_set_volume(struct device *dev,
317 struct device_attribute *attr,
318 const char *buf, size_t count)
705ececd 319{
e1a164d7
MG
320 struct usb_line6_variax *variax =
321 usb_get_intfdata(to_usb_interface(dev));
1383ec4d 322 u8 value;
c0e6e7c1
SB
323 int ret;
324
1383ec4d 325 ret = kstrtou8(buf, 10, &value);
c0e6e7c1
SB
326 if (ret)
327 return ret;
705ececd 328
9cd57f77
GKH
329 if (line6_transmit_parameter(&variax->line6, VARIAXMIDI_volume,
330 value) == 0)
705ececd
MG
331 variax->volume = value;
332
333 return count;
334}
335
336/*
337 "read" request on "model" special file.
338*/
77491e52
GKH
339static ssize_t variax_get_model(struct device *dev,
340 struct device_attribute *attr, char *buf)
705ececd 341{
e1a164d7
MG
342 struct usb_line6_variax *variax =
343 usb_get_intfdata(to_usb_interface(dev));
705ececd
MG
344 return sprintf(buf, "%d\n", variax->model);
345}
346
347/*
348 "write" request on "model" special file.
349*/
77491e52
GKH
350static ssize_t variax_set_model(struct device *dev,
351 struct device_attribute *attr,
352 const char *buf, size_t count)
705ececd 353{
e1a164d7
MG
354 struct usb_line6_variax *variax =
355 usb_get_intfdata(to_usb_interface(dev));
9291975d 356 u8 value;
c0e6e7c1
SB
357 int ret;
358
9291975d 359 ret = kstrtou8(buf, 10, &value);
c0e6e7c1
SB
360 if (ret)
361 return ret;
705ececd 362
9cd57f77 363 if (line6_send_program(&variax->line6, value) == 0)
705ececd
MG
364 variax->model = value;
365
366 return count;
367}
368
369/*
370 "read" request on "active" special file.
371*/
77491e52
GKH
372static ssize_t variax_get_active(struct device *dev,
373 struct device_attribute *attr, char *buf)
705ececd 374{
e1a164d7
MG
375 struct usb_line6_variax *variax =
376 usb_get_intfdata(to_usb_interface(dev));
377 return sprintf(buf, "%d\n",
378 variax->buffer_activate[VARIAX_OFFSET_ACTIVATE]);
705ececd
MG
379}
380
381/*
382 "write" request on "active" special file.
383*/
77491e52
GKH
384static ssize_t variax_set_active(struct device *dev,
385 struct device_attribute *attr,
386 const char *buf, size_t count)
705ececd 387{
e1a164d7
MG
388 struct usb_line6_variax *variax =
389 usb_get_intfdata(to_usb_interface(dev));
9291975d 390 u8 value;
c0e6e7c1
SB
391 int ret;
392
9291975d 393 ret = kstrtou8(buf, 10, &value);
c0e6e7c1
SB
394 if (ret)
395 return ret;
396
1027f476 397 variax_activate_async(variax, value ? 1 : 0);
705ececd
MG
398 return count;
399}
400
401/*
402 "read" request on "tone" special file.
403*/
77491e52
GKH
404static ssize_t variax_get_tone(struct device *dev,
405 struct device_attribute *attr, char *buf)
705ececd 406{
e1a164d7
MG
407 struct usb_line6_variax *variax =
408 usb_get_intfdata(to_usb_interface(dev));
705ececd
MG
409 return sprintf(buf, "%d\n", variax->tone);
410}
411
412/*
413 "write" request on "tone" special file.
414*/
77491e52
GKH
415static ssize_t variax_set_tone(struct device *dev,
416 struct device_attribute *attr,
417 const char *buf, size_t count)
705ececd 418{
e1a164d7
MG
419 struct usb_line6_variax *variax =
420 usb_get_intfdata(to_usb_interface(dev));
1383ec4d 421 u8 value;
c0e6e7c1
SB
422 int ret;
423
1383ec4d 424 ret = kstrtou8(buf, 10, &value);
c0e6e7c1
SB
425 if (ret)
426 return ret;
705ececd 427
9cd57f77
GKH
428 if (line6_transmit_parameter(&variax->line6, VARIAXMIDI_tone,
429 value) == 0)
705ececd
MG
430 variax->tone = value;
431
432 return count;
433}
434
435static ssize_t get_string(char *buf, const char *data, int length)
436{
437 int i;
438 memcpy(buf, data, length);
439
9cd57f77 440 for (i = length; i--;) {
705ececd
MG
441 char c = buf[i];
442
9cd57f77 443 if ((c != 0) && (c != ' '))
705ececd
MG
444 break;
445 }
446
447 buf[i + 1] = '\n';
448 return i + 2;
449}
450
451/*
452 "read" request on "name" special file.
453*/
77491e52
GKH
454static ssize_t variax_get_name(struct device *dev,
455 struct device_attribute *attr, char *buf)
705ececd 456{
e1a164d7
MG
457 struct usb_line6_variax *variax =
458 usb_get_intfdata(to_usb_interface(dev));
1027f476 459 line6_dump_wait_interruptible(&variax->dumpreq);
9cd57f77
GKH
460 return get_string(buf, variax->model_data.name,
461 sizeof(variax->model_data.name));
705ececd
MG
462}
463
464/*
465 "read" request on "bank" special file.
466*/
77491e52
GKH
467static ssize_t variax_get_bank(struct device *dev,
468 struct device_attribute *attr, char *buf)
705ececd 469{
e1a164d7
MG
470 struct usb_line6_variax *variax =
471 usb_get_intfdata(to_usb_interface(dev));
1027f476 472 line6_dump_wait_interruptible(&variax->dumpreq);
705ececd
MG
473 return get_string(buf, variax->bank, sizeof(variax->bank));
474}
475
476/*
477 "read" request on "dump" special file.
478*/
77491e52
GKH
479static ssize_t variax_get_dump(struct device *dev,
480 struct device_attribute *attr, char *buf)
705ececd 481{
e1a164d7
MG
482 struct usb_line6_variax *variax =
483 usb_get_intfdata(to_usb_interface(dev));
705ececd 484 int retval;
1027f476 485 retval = line6_dump_wait_interruptible(&variax->dumpreq);
9cd57f77
GKH
486 if (retval < 0)
487 return retval;
488 memcpy(buf, &variax->model_data.control,
489 sizeof(variax->model_data.control));
705ececd
MG
490 return sizeof(variax->model_data.control);
491}
492
1027f476
MG
493/*
494 "read" request on "guitar" special file.
495*/
496static ssize_t variax_get_guitar(struct device *dev,
497 struct device_attribute *attr, char *buf)
498{
e1a164d7
MG
499 struct usb_line6_variax *variax =
500 usb_get_intfdata(to_usb_interface(dev));
1027f476
MG
501 return sprintf(buf, "%s\n", variax->guitar);
502}
503
504#ifdef CONFIG_LINE6_USB_RAW
505
e1a164d7
MG
506static char *variax_alloc_sysex_buffer(struct usb_line6_variax *variax,
507 int code, int size)
1027f476 508{
e1a164d7
MG
509 return line6_alloc_sysex_buffer(&variax->line6, VARIAX_SYSEX_CODE, code,
510 size);
1027f476 511}
705ececd
MG
512
513/*
514 "write" request on "raw" special file.
515*/
77491e52
GKH
516static ssize_t variax_set_raw2(struct device *dev,
517 struct device_attribute *attr,
518 const char *buf, size_t count)
705ececd 519{
e1a164d7
MG
520 struct usb_line6_variax *variax =
521 usb_get_intfdata(to_usb_interface(dev));
705ececd
MG
522 int size;
523 int i;
524 char *sysex;
525
526 count -= count % 3;
527 size = count * 2;
528 sysex = variax_alloc_sysex_buffer(variax, VARIAX_SYSEX_PARAM, size);
529
9cd57f77 530 if (!sysex)
705ececd
MG
531 return 0;
532
9cd57f77 533 for (i = 0; i < count; i += 3) {
705ececd
MG
534 const unsigned char *p1 = buf + i;
535 char *p2 = sysex + SYSEX_DATA_OFS + i * 2;
536 p2[0] = p1[2] & 0x0f;
537 p2[1] = p1[2] >> 4;
538 p2[2] = p1[1] & 0x0f;
539 p2[3] = p1[1] >> 4;
540 p2[4] = p1[0] & 0x0f;
541 p2[5] = p1[0] >> 4;
542 }
543
544 line6_send_sysex_message(&variax->line6, sysex, size);
545 kfree(sysex);
546 return count;
547}
548
549#endif
550
551/* Variax workbench special files: */
a3a972a0 552static DEVICE_ATTR(model, S_IWUSR | S_IRUGO, variax_get_model,
e1a164d7 553 variax_set_model);
a3a972a0 554static DEVICE_ATTR(volume, S_IWUSR | S_IRUGO, variax_get_volume,
e1a164d7 555 variax_set_volume);
a3a972a0 556static DEVICE_ATTR(tone, S_IWUSR | S_IRUGO, variax_get_tone, variax_set_tone);
705ececd
MG
557static DEVICE_ATTR(name, S_IRUGO, variax_get_name, line6_nop_write);
558static DEVICE_ATTR(bank, S_IRUGO, variax_get_bank, line6_nop_write);
559static DEVICE_ATTR(dump, S_IRUGO, variax_get_dump, line6_nop_write);
a3a972a0 560static DEVICE_ATTR(active, S_IWUSR | S_IRUGO, variax_get_active,
e1a164d7 561 variax_set_active);
1027f476 562static DEVICE_ATTR(guitar, S_IRUGO, variax_get_guitar, line6_nop_write);
705ececd 563
1027f476 564#ifdef CONFIG_LINE6_USB_RAW
a3a972a0
GKH
565static DEVICE_ATTR(raw, S_IWUSR, line6_nop_read, line6_set_raw);
566static DEVICE_ATTR(raw2, S_IWUSR, line6_nop_read, variax_set_raw2);
705ececd
MG
567#endif
568
705ececd
MG
569/*
570 Variax destructor.
571*/
572static void variax_destruct(struct usb_interface *interface)
573{
574 struct usb_line6_variax *variax = usb_get_intfdata(interface);
705ececd 575
9cd57f77
GKH
576 if (variax == NULL)
577 return;
188e6645 578 line6_cleanup_audio(&variax->line6);
705ececd 579
e1a164d7
MG
580 del_timer(&variax->startup_timer1);
581 del_timer(&variax->startup_timer2);
582 cancel_work_sync(&variax->startup_work);
583
705ececd
MG
584 /* free dump request data: */
585 line6_dumpreq_destructbuf(&variax->dumpreq, 2);
586 line6_dumpreq_destructbuf(&variax->dumpreq, 1);
587 line6_dumpreq_destruct(&variax->dumpreq);
588
9cd57f77 589 kfree(variax->buffer_activate);
705ececd
MG
590}
591
592/*
593 Create sysfs entries.
594*/
b702ed25 595static int variax_create_files2(struct device *dev)
705ececd
MG
596{
597 int err;
598 CHECK_RETURN(device_create_file(dev, &dev_attr_model));
599 CHECK_RETURN(device_create_file(dev, &dev_attr_volume));
600 CHECK_RETURN(device_create_file(dev, &dev_attr_tone));
601 CHECK_RETURN(device_create_file(dev, &dev_attr_name));
602 CHECK_RETURN(device_create_file(dev, &dev_attr_bank));
603 CHECK_RETURN(device_create_file(dev, &dev_attr_dump));
604 CHECK_RETURN(device_create_file(dev, &dev_attr_active));
1027f476
MG
605 CHECK_RETURN(device_create_file(dev, &dev_attr_guitar));
606#ifdef CONFIG_LINE6_USB_RAW
705ececd
MG
607 CHECK_RETURN(device_create_file(dev, &dev_attr_raw));
608 CHECK_RETURN(device_create_file(dev, &dev_attr_raw2));
609#endif
610 return 0;
611}
612
613/*
1027f476 614 Try to init workbench device.
705ececd 615*/
1027f476
MG
616static int variax_try_init(struct usb_interface *interface,
617 struct usb_line6_variax *variax)
705ececd
MG
618{
619 int err;
620
e1a164d7
MG
621 init_timer(&variax->startup_timer1);
622 init_timer(&variax->startup_timer2);
623 INIT_WORK(&variax->startup_work, variax_startup7);
624
9cd57f77
GKH
625 if ((interface == NULL) || (variax == NULL))
626 return -ENODEV;
705ececd
MG
627
628 /* initialize USB buffers: */
9cd57f77
GKH
629 err = line6_dumpreq_init(&variax->dumpreq, variax_request_model1,
630 sizeof(variax_request_model1));
705ececd 631
9cd57f77 632 if (err < 0) {
705ececd 633 dev_err(&interface->dev, "Out of memory\n");
705ececd
MG
634 return err;
635 }
636
9cd57f77
GKH
637 err = line6_dumpreq_initbuf(&variax->dumpreq, variax_request_model2,
638 sizeof(variax_request_model2), 1);
705ececd 639
9cd57f77 640 if (err < 0) {
705ececd 641 dev_err(&interface->dev, "Out of memory\n");
705ececd
MG
642 return err;
643 }
644
9cd57f77
GKH
645 err = line6_dumpreq_initbuf(&variax->dumpreq, variax_request_bank,
646 sizeof(variax_request_bank), 2);
705ececd 647
9cd57f77 648 if (err < 0) {
705ececd 649 dev_err(&interface->dev, "Out of memory\n");
705ececd
MG
650 return err;
651 }
652
94002c07
JL
653 variax->buffer_activate = kmemdup(variax_activate,
654 sizeof(variax_activate), GFP_KERNEL);
705ececd 655
9cd57f77 656 if (variax->buffer_activate == NULL) {
705ececd 657 dev_err(&interface->dev, "Out of memory\n");
705ececd
MG
658 return -ENOMEM;
659 }
660
705ececd 661 /* initialize audio system: */
9cd57f77 662 err = line6_init_audio(&variax->line6);
027360c5 663 if (err < 0)
705ececd 664 return err;
705ececd
MG
665
666 /* initialize MIDI subsystem: */
9cd57f77 667 err = line6_init_midi(&variax->line6);
027360c5 668 if (err < 0)
705ececd 669 return err;
705ececd 670
1027f476
MG
671 /* initiate startup procedure: */
672 variax_startup1(variax);
673 return 0;
674}
675
676/*
677 Init workbench device (and clean up in case of failure).
678*/
679int line6_variax_init(struct usb_interface *interface,
680 struct usb_line6_variax *variax)
681{
682 int err = variax_try_init(interface, variax);
683
027360c5 684 if (err < 0)
705ececd 685 variax_destruct(interface);
705ececd 686
1027f476 687 return err;
705ececd
MG
688}
689
690/*
691 Workbench device disconnected.
692*/
1027f476 693void line6_variax_disconnect(struct usb_interface *interface)
705ececd
MG
694{
695 struct device *dev;
696
9cd57f77
GKH
697 if (interface == NULL)
698 return;
705ececd
MG
699 dev = &interface->dev;
700
9cd57f77 701 if (dev != NULL) {
705ececd 702 /* remove sysfs entries: */
1027f476 703 line6_variax_remove_files(0, 0, dev);
705ececd
MG
704 device_remove_file(dev, &dev_attr_model);
705 device_remove_file(dev, &dev_attr_volume);
706 device_remove_file(dev, &dev_attr_tone);
707 device_remove_file(dev, &dev_attr_name);
708 device_remove_file(dev, &dev_attr_bank);
709 device_remove_file(dev, &dev_attr_dump);
710 device_remove_file(dev, &dev_attr_active);
1027f476
MG
711 device_remove_file(dev, &dev_attr_guitar);
712#ifdef CONFIG_LINE6_USB_RAW
705ececd
MG
713 device_remove_file(dev, &dev_attr_raw);
714 device_remove_file(dev, &dev_attr_raw2);
715#endif
716 }
717
718 variax_destruct(interface);
719}