linux/drivers/staging/line6/variax.c
<<
>>
Prefs
   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