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 "control.h" 16#include "driver.h" 17#include "variax.h" 18 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 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 51static const char variax_activate[] = { 52 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x2a, 0x01, 53 0xf7 54}; 55 56static const char variax_request_bank[] = { 57 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6d, 0xf7 58}; 59 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}; 65 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 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 78/* 79 Decode data transmitted by workbench. 80*/ 81static void variax_decode(const unsigned char *raw_data, unsigned char *data, 82 int raw_size) 83{ 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); 88 raw_data += 6; 89 data += 3; 90 } 91} 92 93static void variax_activate_async(struct usb_line6_variax *variax, int a) 94{ 95 variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a; 96 line6_send_raw_message_async(&variax->line6, variax->buffer_activate, 97 sizeof(variax_activate)); 98} 99 100/* 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. 105*/ 106 107static void variax_startup1(struct usb_line6_variax *variax) 108{ 109 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_INIT); 110 111 /* delay startup procedure: */ 112 line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1, 113 variax_startup2, (unsigned long)variax); 114} 115 116static void variax_startup2(unsigned long data) 117{ 118 struct usb_line6_variax *variax = (struct usb_line6_variax *)data; 119 struct usb_line6 *line6 = &variax->line6; 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); 128 129 /* request firmware version: */ 130 line6_version_request_async(line6); 131} 132 133static void variax_startup3(struct usb_line6_variax *variax) 134{ 135 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_WAIT); 136 137 /* delay startup procedure: */ 138 line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY3, 139 variax_startup4, (unsigned long)variax); 140} 141 142static void variax_startup4(unsigned long data) 143{ 144 struct usb_line6_variax *variax = (struct usb_line6_variax *)data; 145 CHECK_STARTUP_PROGRESS(variax->startup_progress, 146 VARIAX_STARTUP_ACTIVATE); 147 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); 152} 153 154static void variax_startup5(unsigned long data) 155{ 156 struct usb_line6_variax *variax = (struct usb_line6_variax *)data; 157 CHECK_STARTUP_PROGRESS(variax->startup_progress, 158 VARIAX_STARTUP_DUMPREQ); 159 160 /* current model dump: */ 161 line6_dump_request_async(&variax->dumpreq, &variax->line6, 0, 162 VARIAX_DUMP_PASS1); 163 /* passes 2 and 3 are performed implicitly before entering variax_startup6 */ 164} 165 166static void variax_startup6(struct usb_line6_variax *variax) 167{ 168 CHECK_STARTUP_PROGRESS(variax->startup_progress, 169 VARIAX_STARTUP_WORKQUEUE); 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{ 177 struct usb_line6_variax *variax = 178 container_of(work, struct usb_line6_variax, startup_work); 179 struct usb_line6 *line6 = &variax->line6; 180 181 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_SETUP); 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); 189} 190 191/* 192 Process a completely received message. 193*/ 194void line6_variax_process_message(struct usb_line6_variax *variax) 195{ 196 const unsigned char *buf = variax->line6.buffer_message; 197 198 switch (buf[0]) { 199 case LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST: 200 switch (buf[1]) { 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]; 214 line6_dump_request_async(&variax->dumpreq, &variax->line6, 0, 215 VARIAX_DUMP_PASS1); 216 break; 217 218 case LINE6_RESET: 219 dev_info(variax->line6.ifcdev, "VARIAX reset\n"); 220 break; 221 222 case LINE6_SYSEX_BEGIN: 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) { 228 case VARIAX_DUMP_PASS1: 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); 243 break; 244 245 case VARIAX_DUMP_PASS2: 246 /* model name is transmitted twice, so skip it here: */ 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); 261 } 262 } else { 263 DEBUG_MESSAGES(dev_err 264 (variax->line6.ifcdev, 265 "illegal length %d of model data\n", 266 variax->line6.message_length)); 267 line6_dump_finished(&variax->dumpreq); 268 } 269 } else if (memcmp(buf + 1, variax_request_bank + 1, 270 sizeof(variax_request_bank) - 2) == 0) { 271 memcpy(variax->bank, 272 buf + sizeof(variax_request_bank) - 1, 273 sizeof(variax->bank)); 274 line6_dump_finished(&variax->dumpreq); 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); 288 } 289 290 break; 291 292 case LINE6_SYSEX_END: 293 break; 294 295 default: 296 DEBUG_MESSAGES(dev_err 297 (variax->line6.ifcdev, 298 "Variax: unknown message %02X\n", buf[0])); 299 } 300} 301 302/* 303 "read" request on "volume" special file. 304*/ 305static ssize_t variax_get_volume(struct device *dev, 306 struct device_attribute *attr, char *buf) 307{ 308 struct usb_line6_variax *variax = 309 usb_get_intfdata(to_usb_interface(dev)); 310 return sprintf(buf, "%d\n", variax->volume); 311} 312 313/* 314 "write" request on "volume" special file. 315*/ 316static ssize_t variax_set_volume(struct device *dev, 317 struct device_attribute *attr, 318 const char *buf, size_t count) 319{ 320 struct usb_line6_variax *variax = 321 usb_get_intfdata(to_usb_interface(dev)); 322 unsigned long value; 323 int ret; 324 325 ret = strict_strtoul(buf, 10, &value); 326 if (ret) 327 return ret; 328 329 if (line6_transmit_parameter(&variax->line6, VARIAXMIDI_volume, 330 value) == 0) 331 variax->volume = value; 332 333 return count; 334} 335 336/* 337 "read" request on "model" special file. 338*/ 339static ssize_t variax_get_model(struct device *dev, 340 struct device_attribute *attr, char *buf) 341{ 342 struct usb_line6_variax *variax = 343 usb_get_intfdata(to_usb_interface(dev)); 344 return sprintf(buf, "%d\n", variax->model); 345} 346 347/* 348 "write" request on "model" special file. 349*/ 350static ssize_t variax_set_model(struct device *dev, 351 struct device_attribute *attr, 352 const char *buf, size_t count) 353{ 354 struct usb_line6_variax *variax = 355 usb_get_intfdata(to_usb_interface(dev)); 356 unsigned long value; 357 int ret; 358 359 ret = strict_strtoul(buf, 10, &value); 360 if (ret) 361 return ret; 362 363 if (line6_send_program(&variax->line6, value) == 0) 364 variax->model = value; 365 366 return count; 367} 368 369/* 370 "read" request on "active" special file. 371*/ 372static ssize_t variax_get_active(struct device *dev, 373 struct device_attribute *attr, char *buf) 374{ 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]); 379} 380 381/* 382 "write" request on "active" special file. 383*/ 384static ssize_t variax_set_active(struct device *dev, 385 struct device_attribute *attr, 386 const char *buf, size_t count) 387{ 388 struct usb_line6_variax *variax = 389 usb_get_intfdata(to_usb_interface(dev)); 390 unsigned long value; 391 int ret; 392 393 ret = strict_strtoul(buf, 10, &value); 394 if (ret) 395 return ret; 396 397 variax_activate_async(variax, value ? 1 : 0); 398 return count; 399} 400 401/* 402 "read" request on "tone" special file. 403*/ 404static ssize_t variax_get_tone(struct device *dev, 405 struct device_attribute *attr, char *buf) 406{ 407 struct usb_line6_variax *variax = 408 usb_get_intfdata(to_usb_interface(dev)); 409 return sprintf(buf, "%d\n", variax->tone); 410} 411 412/* 413 "write" request on "tone" special file. 414*/ 415static ssize_t variax_set_tone(struct device *dev, 416 struct device_attribute *attr, 417 const char *buf, size_t count) 418{ 419 struct usb_line6_variax *variax = 420 usb_get_intfdata(to_usb_interface(dev)); 421 unsigned long value; 422 int ret; 423 424 ret = strict_strtoul(buf, 10, &value); 425 if (ret) 426 return ret; 427 428 if (line6_transmit_parameter(&variax->line6, VARIAXMIDI_tone, 429 value) == 0) 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 440 for (i = length; i--;) { 441 char c = buf[i]; 442 443 if ((c != 0) && (c != ' ')) 444 break; 445 } 446 447 buf[i + 1] = '\n'; 448 return i + 2; 449} 450 451/* 452 "read" request on "name" special file. 453*/ 454static ssize_t variax_get_name(struct device *dev, 455 struct device_attribute *attr, char *buf) 456{ 457 struct usb_line6_variax *variax = 458 usb_get_intfdata(to_usb_interface(dev)); 459 line6_dump_wait_interruptible(&variax->dumpreq); 460 return get_string(buf, variax->model_data.name, 461 sizeof(variax->model_data.name)); 462} 463 464/* 465 "read" request on "bank" special file. 466*/ 467static ssize_t variax_get_bank(struct device *dev, 468 struct device_attribute *attr, char *buf) 469{ 470 struct usb_line6_variax *variax = 471 usb_get_intfdata(to_usb_interface(dev)); 472 line6_dump_wait_interruptible(&variax->dumpreq); 473 return get_string(buf, variax->bank, sizeof(variax->bank)); 474} 475 476/* 477 "read" request on "dump" special file. 478*/ 479static ssize_t variax_get_dump(struct device *dev, 480 struct device_attribute *attr, char *buf) 481{ 482 struct usb_line6_variax *variax = 483 usb_get_intfdata(to_usb_interface(dev)); 484 int retval; 485 retval = line6_dump_wait_interruptible(&variax->dumpreq); 486 if (retval < 0) 487 return retval; 488 memcpy(buf, &variax->model_data.control, 489 sizeof(variax->model_data.control)); 490 return sizeof(variax->model_data.control); 491} 492 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{ 499 struct usb_line6_variax *variax = 500 usb_get_intfdata(to_usb_interface(dev)); 501 return sprintf(buf, "%s\n", variax->guitar); 502} 503 504#ifdef CONFIG_LINE6_USB_RAW 505 506static char *variax_alloc_sysex_buffer(struct usb_line6_variax *variax, 507 int code, int size) 508{ 509 return line6_alloc_sysex_buffer(&variax->line6, VARIAX_SYSEX_CODE, code, 510 size); 511} 512 513/* 514 "write" request on "raw" special file. 515*/ 516static ssize_t variax_set_raw2(struct device *dev, 517 struct device_attribute *attr, 518 const char *buf, size_t count) 519{ 520 struct usb_line6_variax *variax = 521 usb_get_intfdata(to_usb_interface(dev)); 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 530 if (!sysex) 531 return 0; 532 533 for (i = 0; i < count; i += 3) { 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: */ 552static DEVICE_ATTR(model, S_IWUSR | S_IRUGO, variax_get_model, 553 variax_set_model); 554static DEVICE_ATTR(volume, S_IWUSR | S_IRUGO, variax_get_volume, 555 variax_set_volume); 556static DEVICE_ATTR(tone, S_IWUSR | S_IRUGO, variax_get_tone, variax_set_tone); 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); 560static DEVICE_ATTR(active, S_IWUSR | S_IRUGO, variax_get_active, 561 variax_set_active); 562static DEVICE_ATTR(guitar, S_IRUGO, variax_get_guitar, line6_nop_write); 563 564#ifdef CONFIG_LINE6_USB_RAW 565static DEVICE_ATTR(raw, S_IWUSR, line6_nop_read, line6_set_raw); 566static DEVICE_ATTR(raw2, S_IWUSR, line6_nop_read, variax_set_raw2); 567#endif 568 569/* 570 Variax destructor. 571*/ 572static void variax_destruct(struct usb_interface *interface) 573{ 574 struct usb_line6_variax *variax = usb_get_intfdata(interface); 575 576 if (variax == NULL) 577 return; 578 line6_cleanup_audio(&variax->line6); 579 580 del_timer(&variax->startup_timer1); 581 del_timer(&variax->startup_timer2); 582 cancel_work_sync(&variax->startup_work); 583 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 589 kfree(variax->buffer_activate); 590} 591 592/* 593 Create sysfs entries. 594*/ 595static int variax_create_files2(struct device *dev) 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)); 605 CHECK_RETURN(device_create_file(dev, &dev_attr_guitar)); 606#ifdef CONFIG_LINE6_USB_RAW 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/* 614 Try to init workbench device. 615*/ 616static int variax_try_init(struct usb_interface *interface, 617 struct usb_line6_variax *variax) 618{ 619 int err; 620 621 init_timer(&variax->startup_timer1); 622 init_timer(&variax->startup_timer2); 623 INIT_WORK(&variax->startup_work, variax_startup7); 624 625 if ((interface == NULL) || (variax == NULL)) 626 return -ENODEV; 627 628 /* initialize USB buffers: */ 629 err = line6_dumpreq_init(&variax->dumpreq, variax_request_model1, 630 sizeof(variax_request_model1)); 631 632 if (err < 0) { 633 dev_err(&interface->dev, "Out of memory\n"); 634 return err; 635 } 636 637 err = line6_dumpreq_initbuf(&variax->dumpreq, variax_request_model2, 638 sizeof(variax_request_model2), 1); 639 640 if (err < 0) { 641 dev_err(&interface->dev, "Out of memory\n"); 642 return err; 643 } 644 645 err = line6_dumpreq_initbuf(&variax->dumpreq, variax_request_bank, 646 sizeof(variax_request_bank), 2); 647 648 if (err < 0) { 649 dev_err(&interface->dev, "Out of memory\n"); 650 return err; 651 } 652 653 variax->buffer_activate = kmemdup(variax_activate, 654 sizeof(variax_activate), GFP_KERNEL); 655 656 if (variax->buffer_activate == NULL) { 657 dev_err(&interface->dev, "Out of memory\n"); 658 return -ENOMEM; 659 } 660 661 /* initialize audio system: */ 662 err = line6_init_audio(&variax->line6); 663 if (err < 0) 664 return err; 665 666 /* initialize MIDI subsystem: */ 667 err = line6_init_midi(&variax->line6); 668 if (err < 0) 669 return err; 670 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 684 if (err < 0) 685 variax_destruct(interface); 686 687 return err; 688} 689 690/* 691 Workbench device disconnected. 692*/ 693void line6_variax_disconnect(struct usb_interface *interface) 694{ 695 struct device *dev; 696 697 if (interface == NULL) 698 return; 699 dev = &interface->dev; 700 701 if (dev != NULL) { 702 /* remove sysfs entries: */ 703 line6_variax_remove_files(0, 0, dev); 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); 711 device_remove_file(dev, &dev_attr_guitar); 712#ifdef CONFIG_LINE6_USB_RAW 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} 720