linux/sound/usb/line6/pod.c
<<
>>
Prefs
   1/*
   2 * Line 6 Linux USB driver
   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#include <linux/wait.h>
  14#include <linux/interrupt.h>
  15#include <linux/module.h>
  16#include <linux/usb.h>
  17
  18#include <sound/core.h>
  19#include <sound/control.h>
  20
  21#include "capture.h"
  22#include "driver.h"
  23#include "playback.h"
  24
  25/*
  26        Locate name in binary program dump
  27*/
  28#define POD_NAME_OFFSET 0
  29#define POD_NAME_LENGTH 16
  30
  31/*
  32        Other constants
  33*/
  34#define POD_CONTROL_SIZE 0x80
  35#define POD_BUFSIZE_DUMPREQ 7
  36#define POD_STARTUP_DELAY 1000
  37
  38/*
  39        Stages of POD startup procedure
  40*/
  41enum {
  42        POD_STARTUP_INIT = 1,
  43        POD_STARTUP_VERSIONREQ,
  44        POD_STARTUP_WORKQUEUE,
  45        POD_STARTUP_SETUP,
  46        POD_STARTUP_LAST = POD_STARTUP_SETUP - 1
  47};
  48
  49enum {
  50        LINE6_BASSPODXT,
  51        LINE6_BASSPODXTLIVE,
  52        LINE6_BASSPODXTPRO,
  53        LINE6_POCKETPOD,
  54        LINE6_PODXT,
  55        LINE6_PODXTLIVE_POD,
  56        LINE6_PODXTPRO,
  57};
  58
  59struct usb_line6_pod {
  60        /* Generic Line 6 USB data */
  61        struct usb_line6 line6;
  62
  63        /* Instrument monitor level */
  64        int monitor_level;
  65
  66        /* Timer for device initialization */
  67        struct timer_list startup_timer;
  68
  69        /* Work handler for device initialization */
  70        struct work_struct startup_work;
  71
  72        /* Current progress in startup procedure */
  73        int startup_progress;
  74
  75        /* Serial number of device */
  76        u32 serial_number;
  77
  78        /* Firmware version (x 100) */
  79        int firmware_version;
  80
  81        /* Device ID */
  82        int device_id;
  83};
  84
  85#define POD_SYSEX_CODE 3
  86
  87/* *INDENT-OFF* */
  88
  89enum {
  90        POD_SYSEX_SAVE      = 0x24,
  91        POD_SYSEX_SYSTEM    = 0x56,
  92        POD_SYSEX_SYSTEMREQ = 0x57,
  93        /* POD_SYSEX_UPDATE    = 0x6c, */  /* software update! */
  94        POD_SYSEX_STORE     = 0x71,
  95        POD_SYSEX_FINISH    = 0x72,
  96        POD_SYSEX_DUMPMEM   = 0x73,
  97        POD_SYSEX_DUMP      = 0x74,
  98        POD_SYSEX_DUMPREQ   = 0x75
  99
 100        /* dumps entire internal memory of PODxt Pro */
 101        /* POD_SYSEX_DUMPMEM2  = 0x76 */
 102};
 103
 104enum {
 105        POD_MONITOR_LEVEL  = 0x04,
 106        POD_SYSTEM_INVALID = 0x10000
 107};
 108
 109/* *INDENT-ON* */
 110
 111enum {
 112        POD_DUMP_MEMORY = 2
 113};
 114
 115enum {
 116        POD_BUSY_READ,
 117        POD_BUSY_WRITE,
 118        POD_CHANNEL_DIRTY,
 119        POD_SAVE_PRESSED,
 120        POD_BUSY_MIDISEND
 121};
 122
 123static struct snd_ratden pod_ratden = {
 124        .num_min = 78125,
 125        .num_max = 78125,
 126        .num_step = 1,
 127        .den = 2
 128};
 129
 130static struct line6_pcm_properties pod_pcm_properties = {
 131        .playback_hw = {
 132                                  .info = (SNDRV_PCM_INFO_MMAP |
 133                                           SNDRV_PCM_INFO_INTERLEAVED |
 134                                           SNDRV_PCM_INFO_BLOCK_TRANSFER |
 135                                           SNDRV_PCM_INFO_MMAP_VALID |
 136                                           SNDRV_PCM_INFO_PAUSE |
 137                                           SNDRV_PCM_INFO_SYNC_START),
 138                                  .formats = SNDRV_PCM_FMTBIT_S24_3LE,
 139                                  .rates = SNDRV_PCM_RATE_KNOT,
 140                                  .rate_min = 39062,
 141                                  .rate_max = 39063,
 142                                  .channels_min = 2,
 143                                  .channels_max = 2,
 144                                  .buffer_bytes_max = 60000,
 145                                  .period_bytes_min = 64,
 146                                  .period_bytes_max = 8192,
 147                                  .periods_min = 1,
 148                                  .periods_max = 1024},
 149        .capture_hw = {
 150                                 .info = (SNDRV_PCM_INFO_MMAP |
 151                                          SNDRV_PCM_INFO_INTERLEAVED |
 152                                          SNDRV_PCM_INFO_BLOCK_TRANSFER |
 153                                          SNDRV_PCM_INFO_MMAP_VALID |
 154                                          SNDRV_PCM_INFO_SYNC_START),
 155                                 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
 156                                 .rates = SNDRV_PCM_RATE_KNOT,
 157                                 .rate_min = 39062,
 158                                 .rate_max = 39063,
 159                                 .channels_min = 2,
 160                                 .channels_max = 2,
 161                                 .buffer_bytes_max = 60000,
 162                                 .period_bytes_min = 64,
 163                                 .period_bytes_max = 8192,
 164                                 .periods_min = 1,
 165                                 .periods_max = 1024},
 166        .rates = {
 167                            .nrats = 1,
 168                            .rats = &pod_ratden},
 169        .bytes_per_channel = 3 /* SNDRV_PCM_FMTBIT_S24_3LE */
 170};
 171
 172static const char pod_version_header[] = {
 173        0xf2, 0x7e, 0x7f, 0x06, 0x02
 174};
 175
 176/* forward declarations: */
 177static void pod_startup2(unsigned long data);
 178static void pod_startup3(struct usb_line6_pod *pod);
 179
 180static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
 181                                    int size)
 182{
 183        return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code,
 184                                        size);
 185}
 186
 187/*
 188        Process a completely received message.
 189*/
 190static void line6_pod_process_message(struct usb_line6 *line6)
 191{
 192        struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
 193        const unsigned char *buf = pod->line6.buffer_message;
 194
 195        if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {
 196                pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];
 197                pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) |
 198                                 (int) buf[10];
 199                pod_startup3(pod);
 200                return;
 201        }
 202
 203        /* Only look for sysex messages from this device */
 204        if (buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE) &&
 205            buf[0] != (LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN)) {
 206                return;
 207        }
 208        if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) != 0)
 209                return;
 210
 211        if (buf[5] == POD_SYSEX_SYSTEM && buf[6] == POD_MONITOR_LEVEL) {
 212                short value = ((int)buf[7] << 12) | ((int)buf[8] << 8) |
 213                              ((int)buf[9] << 4) | (int)buf[10];
 214                pod->monitor_level = value;
 215        }
 216}
 217
 218/*
 219        Send system parameter (from integer).
 220*/
 221static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
 222                                    int code)
 223{
 224        char *sysex;
 225        static const int size = 5;
 226
 227        sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);
 228        if (!sysex)
 229                return -ENOMEM;
 230        sysex[SYSEX_DATA_OFS] = code;
 231        sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
 232        sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
 233        sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
 234        sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f;
 235        line6_send_sysex_message(&pod->line6, sysex, size);
 236        kfree(sysex);
 237        return 0;
 238}
 239
 240/*
 241        "read" request on "serial_number" special file.
 242*/
 243static ssize_t serial_number_show(struct device *dev,
 244                                  struct device_attribute *attr, char *buf)
 245{
 246        struct snd_card *card = dev_to_snd_card(dev);
 247        struct usb_line6_pod *pod = card->private_data;
 248
 249        return sprintf(buf, "%u\n", pod->serial_number);
 250}
 251
 252/*
 253        "read" request on "firmware_version" special file.
 254*/
 255static ssize_t firmware_version_show(struct device *dev,
 256                                     struct device_attribute *attr, char *buf)
 257{
 258        struct snd_card *card = dev_to_snd_card(dev);
 259        struct usb_line6_pod *pod = card->private_data;
 260
 261        return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100,
 262                       pod->firmware_version % 100);
 263}
 264
 265/*
 266        "read" request on "device_id" special file.
 267*/
 268static ssize_t device_id_show(struct device *dev,
 269                              struct device_attribute *attr, char *buf)
 270{
 271        struct snd_card *card = dev_to_snd_card(dev);
 272        struct usb_line6_pod *pod = card->private_data;
 273
 274        return sprintf(buf, "%d\n", pod->device_id);
 275}
 276
 277/*
 278        POD startup procedure.
 279        This is a sequence of functions with special requirements (e.g., must
 280        not run immediately after initialization, must not run in interrupt
 281        context). After the last one has finished, the device is ready to use.
 282*/
 283
 284static void pod_startup1(struct usb_line6_pod *pod)
 285{
 286        CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
 287
 288        /* delay startup procedure: */
 289        line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
 290                          (unsigned long)pod);
 291}
 292
 293static void pod_startup2(unsigned long data)
 294{
 295        struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
 296        struct usb_line6 *line6 = &pod->line6;
 297
 298        CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
 299
 300        /* request firmware version: */
 301        line6_version_request_async(line6);
 302}
 303
 304static void pod_startup3(struct usb_line6_pod *pod)
 305{
 306        CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
 307
 308        /* schedule work for global work queue: */
 309        schedule_work(&pod->startup_work);
 310}
 311
 312static void pod_startup4(struct work_struct *work)
 313{
 314        struct usb_line6_pod *pod =
 315            container_of(work, struct usb_line6_pod, startup_work);
 316        struct usb_line6 *line6 = &pod->line6;
 317
 318        CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
 319
 320        /* serial number: */
 321        line6_read_serial_number(&pod->line6, &pod->serial_number);
 322
 323        /* ALSA audio interface: */
 324        snd_card_register(line6->card);
 325}
 326
 327/* POD special files: */
 328static DEVICE_ATTR_RO(device_id);
 329static DEVICE_ATTR_RO(firmware_version);
 330static DEVICE_ATTR_RO(serial_number);
 331
 332static struct attribute *pod_dev_attrs[] = {
 333        &dev_attr_device_id.attr,
 334        &dev_attr_firmware_version.attr,
 335        &dev_attr_serial_number.attr,
 336        NULL
 337};
 338
 339static const struct attribute_group pod_dev_attr_group = {
 340        .name = "pod",
 341        .attrs = pod_dev_attrs,
 342};
 343
 344/* control info callback */
 345static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
 346                                        struct snd_ctl_elem_info *uinfo)
 347{
 348        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 349        uinfo->count = 1;
 350        uinfo->value.integer.min = 0;
 351        uinfo->value.integer.max = 65535;
 352        return 0;
 353}
 354
 355/* control get callback */
 356static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
 357                                       struct snd_ctl_elem_value *ucontrol)
 358{
 359        struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
 360        struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
 361
 362        ucontrol->value.integer.value[0] = pod->monitor_level;
 363        return 0;
 364}
 365
 366/* control put callback */
 367static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
 368                                       struct snd_ctl_elem_value *ucontrol)
 369{
 370        struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
 371        struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
 372
 373        if (ucontrol->value.integer.value[0] == pod->monitor_level)
 374                return 0;
 375
 376        pod->monitor_level = ucontrol->value.integer.value[0];
 377        pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
 378                                 POD_MONITOR_LEVEL);
 379        return 1;
 380}
 381
 382/* control definition */
 383static const struct snd_kcontrol_new pod_control_monitor = {
 384        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 385        .name = "Monitor Playback Volume",
 386        .index = 0,
 387        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 388        .info = snd_pod_control_monitor_info,
 389        .get = snd_pod_control_monitor_get,
 390        .put = snd_pod_control_monitor_put
 391};
 392
 393/*
 394        POD device disconnected.
 395*/
 396static void line6_pod_disconnect(struct usb_line6 *line6)
 397{
 398        struct usb_line6_pod *pod = (struct usb_line6_pod *)line6;
 399
 400        del_timer_sync(&pod->startup_timer);
 401        cancel_work_sync(&pod->startup_work);
 402}
 403
 404/*
 405         Try to init POD device.
 406*/
 407static int pod_init(struct usb_line6 *line6,
 408                    const struct usb_device_id *id)
 409{
 410        int err;
 411        struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
 412
 413        line6->process_message = line6_pod_process_message;
 414        line6->disconnect = line6_pod_disconnect;
 415
 416        init_timer(&pod->startup_timer);
 417        INIT_WORK(&pod->startup_work, pod_startup4);
 418
 419        /* create sysfs entries: */
 420        err = snd_card_add_dev_attr(line6->card, &pod_dev_attr_group);
 421        if (err < 0)
 422                return err;
 423
 424        /* initialize MIDI subsystem: */
 425        err = line6_init_midi(line6);
 426        if (err < 0)
 427                return err;
 428
 429        /* initialize PCM subsystem: */
 430        err = line6_init_pcm(line6, &pod_pcm_properties);
 431        if (err < 0)
 432                return err;
 433
 434        /* register monitor control: */
 435        err = snd_ctl_add(line6->card,
 436                          snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
 437        if (err < 0)
 438                return err;
 439
 440        /*
 441           When the sound card is registered at this point, the PODxt Live
 442           displays "Invalid Code Error 07", so we do it later in the event
 443           handler.
 444         */
 445
 446        if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
 447                pod->monitor_level = POD_SYSTEM_INVALID;
 448
 449                /* initiate startup procedure: */
 450                pod_startup1(pod);
 451        }
 452
 453        return 0;
 454}
 455
 456#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
 457#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
 458
 459/* table of devices that work with this driver */
 460static const struct usb_device_id pod_id_table[] = {
 461        { LINE6_DEVICE(0x4250),    .driver_info = LINE6_BASSPODXT },
 462        { LINE6_DEVICE(0x4642),    .driver_info = LINE6_BASSPODXTLIVE },
 463        { LINE6_DEVICE(0x4252),    .driver_info = LINE6_BASSPODXTPRO },
 464        { LINE6_IF_NUM(0x5051, 1), .driver_info = LINE6_POCKETPOD },
 465        { LINE6_DEVICE(0x5044),    .driver_info = LINE6_PODXT },
 466        { LINE6_IF_NUM(0x4650, 0), .driver_info = LINE6_PODXTLIVE_POD },
 467        { LINE6_DEVICE(0x5050),    .driver_info = LINE6_PODXTPRO },
 468        {}
 469};
 470
 471MODULE_DEVICE_TABLE(usb, pod_id_table);
 472
 473static const struct line6_properties pod_properties_table[] = {
 474        [LINE6_BASSPODXT] = {
 475                .id = "BassPODxt",
 476                .name = "BassPODxt",
 477                .capabilities   = LINE6_CAP_CONTROL
 478                                | LINE6_CAP_CONTROL_MIDI
 479                                | LINE6_CAP_PCM
 480                                | LINE6_CAP_HWMON,
 481                .altsetting = 5,
 482                .ep_ctrl_r = 0x84,
 483                .ep_ctrl_w = 0x03,
 484                .ep_audio_r = 0x82,
 485                .ep_audio_w = 0x01,
 486        },
 487        [LINE6_BASSPODXTLIVE] = {
 488                .id = "BassPODxtLive",
 489                .name = "BassPODxt Live",
 490                .capabilities   = LINE6_CAP_CONTROL
 491                                | LINE6_CAP_CONTROL_MIDI
 492                                | LINE6_CAP_PCM
 493                                | LINE6_CAP_HWMON,
 494                .altsetting = 1,
 495                .ep_ctrl_r = 0x84,
 496                .ep_ctrl_w = 0x03,
 497                .ep_audio_r = 0x82,
 498                .ep_audio_w = 0x01,
 499        },
 500        [LINE6_BASSPODXTPRO] = {
 501                .id = "BassPODxtPro",
 502                .name = "BassPODxt Pro",
 503                .capabilities   = LINE6_CAP_CONTROL
 504                                | LINE6_CAP_CONTROL_MIDI
 505                                | LINE6_CAP_PCM
 506                                | LINE6_CAP_HWMON,
 507                .altsetting = 5,
 508                .ep_ctrl_r = 0x84,
 509                .ep_ctrl_w = 0x03,
 510                .ep_audio_r = 0x82,
 511                .ep_audio_w = 0x01,
 512        },
 513        [LINE6_POCKETPOD] = {
 514                .id = "PocketPOD",
 515                .name = "Pocket POD",
 516                .capabilities   = LINE6_CAP_CONTROL
 517                                | LINE6_CAP_CONTROL_MIDI,
 518                .altsetting = 0,
 519                .ep_ctrl_r = 0x82,
 520                .ep_ctrl_w = 0x02,
 521                /* no audio channel */
 522        },
 523        [LINE6_PODXT] = {
 524                .id = "PODxt",
 525                .name = "PODxt",
 526                .capabilities   = LINE6_CAP_CONTROL
 527                                | LINE6_CAP_CONTROL_MIDI
 528                                | LINE6_CAP_PCM
 529                                | LINE6_CAP_HWMON,
 530                .altsetting = 5,
 531                .ep_ctrl_r = 0x84,
 532                .ep_ctrl_w = 0x03,
 533                .ep_audio_r = 0x82,
 534                .ep_audio_w = 0x01,
 535        },
 536        [LINE6_PODXTLIVE_POD] = {
 537                .id = "PODxtLive",
 538                .name = "PODxt Live",
 539                .capabilities   = LINE6_CAP_CONTROL
 540                                | LINE6_CAP_CONTROL_MIDI
 541                                | LINE6_CAP_PCM
 542                                | LINE6_CAP_HWMON,
 543                .altsetting = 1,
 544                .ep_ctrl_r = 0x84,
 545                .ep_ctrl_w = 0x03,
 546                .ep_audio_r = 0x82,
 547                .ep_audio_w = 0x01,
 548        },
 549        [LINE6_PODXTPRO] = {
 550                .id = "PODxtPro",
 551                .name = "PODxt Pro",
 552                .capabilities   = LINE6_CAP_CONTROL
 553                                | LINE6_CAP_CONTROL_MIDI
 554                                | LINE6_CAP_PCM
 555                                | LINE6_CAP_HWMON,
 556                .altsetting = 5,
 557                .ep_ctrl_r = 0x84,
 558                .ep_ctrl_w = 0x03,
 559                .ep_audio_r = 0x82,
 560                .ep_audio_w = 0x01,
 561        },
 562};
 563
 564/*
 565        Probe USB device.
 566*/
 567static int pod_probe(struct usb_interface *interface,
 568                     const struct usb_device_id *id)
 569{
 570        return line6_probe(interface, id, "Line6-POD",
 571                           &pod_properties_table[id->driver_info],
 572                           pod_init, sizeof(struct usb_line6_pod));
 573}
 574
 575static struct usb_driver pod_driver = {
 576        .name = KBUILD_MODNAME,
 577        .probe = pod_probe,
 578        .disconnect = line6_disconnect,
 579#ifdef CONFIG_PM
 580        .suspend = line6_suspend,
 581        .resume = line6_resume,
 582        .reset_resume = line6_resume,
 583#endif
 584        .id_table = pod_id_table,
 585};
 586
 587module_usb_driver(pod_driver);
 588
 589MODULE_DESCRIPTION("Line 6 POD USB driver");
 590MODULE_LICENSE("GPL");
 591