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(struct timer_list *t);
 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}
 291
 292static void pod_startup2(struct timer_list *t)
 293{
 294        struct usb_line6_pod *pod = from_timer(pod, t, startup_timer);
 295        struct usb_line6 *line6 = &pod->line6;
 296
 297        CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
 298
 299        /* request firmware version: */
 300        line6_version_request_async(line6);
 301}
 302
 303static void pod_startup3(struct usb_line6_pod *pod)
 304{
 305        CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
 306
 307        /* schedule work for global work queue: */
 308        schedule_work(&pod->startup_work);
 309}
 310
 311static void pod_startup4(struct work_struct *work)
 312{
 313        struct usb_line6_pod *pod =
 314            container_of(work, struct usb_line6_pod, startup_work);
 315        struct usb_line6 *line6 = &pod->line6;
 316
 317        CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
 318
 319        /* serial number: */
 320        line6_read_serial_number(&pod->line6, &pod->serial_number);
 321
 322        /* ALSA audio interface: */
 323        snd_card_register(line6->card);
 324}
 325
 326/* POD special files: */
 327static DEVICE_ATTR_RO(device_id);
 328static DEVICE_ATTR_RO(firmware_version);
 329static DEVICE_ATTR_RO(serial_number);
 330
 331static struct attribute *pod_dev_attrs[] = {
 332        &dev_attr_device_id.attr,
 333        &dev_attr_firmware_version.attr,
 334        &dev_attr_serial_number.attr,
 335        NULL
 336};
 337
 338static const struct attribute_group pod_dev_attr_group = {
 339        .name = "pod",
 340        .attrs = pod_dev_attrs,
 341};
 342
 343/* control info callback */
 344static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,
 345                                        struct snd_ctl_elem_info *uinfo)
 346{
 347        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 348        uinfo->count = 1;
 349        uinfo->value.integer.min = 0;
 350        uinfo->value.integer.max = 65535;
 351        return 0;
 352}
 353
 354/* control get callback */
 355static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
 356                                       struct snd_ctl_elem_value *ucontrol)
 357{
 358        struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
 359        struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
 360
 361        ucontrol->value.integer.value[0] = pod->monitor_level;
 362        return 0;
 363}
 364
 365/* control put callback */
 366static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
 367                                       struct snd_ctl_elem_value *ucontrol)
 368{
 369        struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
 370        struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
 371
 372        if (ucontrol->value.integer.value[0] == pod->monitor_level)
 373                return 0;
 374
 375        pod->monitor_level = ucontrol->value.integer.value[0];
 376        pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
 377                                 POD_MONITOR_LEVEL);
 378        return 1;
 379}
 380
 381/* control definition */
 382static const struct snd_kcontrol_new pod_control_monitor = {
 383        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 384        .name = "Monitor Playback Volume",
 385        .index = 0,
 386        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
 387        .info = snd_pod_control_monitor_info,
 388        .get = snd_pod_control_monitor_get,
 389        .put = snd_pod_control_monitor_put
 390};
 391
 392/*
 393        POD device disconnected.
 394*/
 395static void line6_pod_disconnect(struct usb_line6 *line6)
 396{
 397        struct usb_line6_pod *pod = (struct usb_line6_pod *)line6;
 398
 399        del_timer_sync(&pod->startup_timer);
 400        cancel_work_sync(&pod->startup_work);
 401}
 402
 403/*
 404         Try to init POD device.
 405*/
 406static int pod_init(struct usb_line6 *line6,
 407                    const struct usb_device_id *id)
 408{
 409        int err;
 410        struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
 411
 412        line6->process_message = line6_pod_process_message;
 413        line6->disconnect = line6_pod_disconnect;
 414
 415        timer_setup(&pod->startup_timer, NULL, 0);
 416        INIT_WORK(&pod->startup_work, pod_startup4);
 417
 418        /* create sysfs entries: */
 419        err = snd_card_add_dev_attr(line6->card, &pod_dev_attr_group);
 420        if (err < 0)
 421                return err;
 422
 423        /* initialize MIDI subsystem: */
 424        err = line6_init_midi(line6);
 425        if (err < 0)
 426                return err;
 427
 428        /* initialize PCM subsystem: */
 429        err = line6_init_pcm(line6, &pod_pcm_properties);
 430        if (err < 0)
 431                return err;
 432
 433        /* register monitor control: */
 434        err = snd_ctl_add(line6->card,
 435                          snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
 436        if (err < 0)
 437                return err;
 438
 439        /*
 440           When the sound card is registered at this point, the PODxt Live
 441           displays "Invalid Code Error 07", so we do it later in the event
 442           handler.
 443         */
 444
 445        if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
 446                pod->monitor_level = POD_SYSTEM_INVALID;
 447
 448                /* initiate startup procedure: */
 449                pod_startup1(pod);
 450        }
 451
 452        return 0;
 453}
 454
 455#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
 456#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
 457
 458/* table of devices that work with this driver */
 459static const struct usb_device_id pod_id_table[] = {
 460        { LINE6_DEVICE(0x4250),    .driver_info = LINE6_BASSPODXT },
 461        { LINE6_DEVICE(0x4642),    .driver_info = LINE6_BASSPODXTLIVE },
 462        { LINE6_DEVICE(0x4252),    .driver_info = LINE6_BASSPODXTPRO },
 463        { LINE6_IF_NUM(0x5051, 1), .driver_info = LINE6_POCKETPOD },
 464        { LINE6_DEVICE(0x5044),    .driver_info = LINE6_PODXT },
 465        { LINE6_IF_NUM(0x4650, 0), .driver_info = LINE6_PODXTLIVE_POD },
 466        { LINE6_DEVICE(0x5050),    .driver_info = LINE6_PODXTPRO },
 467        {}
 468};
 469
 470MODULE_DEVICE_TABLE(usb, pod_id_table);
 471
 472static const struct line6_properties pod_properties_table[] = {
 473        [LINE6_BASSPODXT] = {
 474                .id = "BassPODxt",
 475                .name = "BassPODxt",
 476                .capabilities   = LINE6_CAP_CONTROL
 477                                | LINE6_CAP_CONTROL_MIDI
 478                                | LINE6_CAP_PCM
 479                                | LINE6_CAP_HWMON,
 480                .altsetting = 5,
 481                .ep_ctrl_r = 0x84,
 482                .ep_ctrl_w = 0x03,
 483                .ep_audio_r = 0x82,
 484                .ep_audio_w = 0x01,
 485        },
 486        [LINE6_BASSPODXTLIVE] = {
 487                .id = "BassPODxtLive",
 488                .name = "BassPODxt Live",
 489                .capabilities   = LINE6_CAP_CONTROL
 490                                | LINE6_CAP_CONTROL_MIDI
 491                                | LINE6_CAP_PCM
 492                                | LINE6_CAP_HWMON,
 493                .altsetting = 1,
 494                .ep_ctrl_r = 0x84,
 495                .ep_ctrl_w = 0x03,
 496                .ep_audio_r = 0x82,
 497                .ep_audio_w = 0x01,
 498        },
 499        [LINE6_BASSPODXTPRO] = {
 500                .id = "BassPODxtPro",
 501                .name = "BassPODxt Pro",
 502                .capabilities   = LINE6_CAP_CONTROL
 503                                | LINE6_CAP_CONTROL_MIDI
 504                                | LINE6_CAP_PCM
 505                                | LINE6_CAP_HWMON,
 506                .altsetting = 5,
 507                .ep_ctrl_r = 0x84,
 508                .ep_ctrl_w = 0x03,
 509                .ep_audio_r = 0x82,
 510                .ep_audio_w = 0x01,
 511        },
 512        [LINE6_POCKETPOD] = {
 513                .id = "PocketPOD",
 514                .name = "Pocket POD",
 515                .capabilities   = LINE6_CAP_CONTROL
 516                                | LINE6_CAP_CONTROL_MIDI,
 517                .altsetting = 0,
 518                .ep_ctrl_r = 0x82,
 519                .ep_ctrl_w = 0x02,
 520                /* no audio channel */
 521        },
 522        [LINE6_PODXT] = {
 523                .id = "PODxt",
 524                .name = "PODxt",
 525                .capabilities   = LINE6_CAP_CONTROL
 526                                | LINE6_CAP_CONTROL_MIDI
 527                                | LINE6_CAP_PCM
 528                                | LINE6_CAP_HWMON,
 529                .altsetting = 5,
 530                .ep_ctrl_r = 0x84,
 531                .ep_ctrl_w = 0x03,
 532                .ep_audio_r = 0x82,
 533                .ep_audio_w = 0x01,
 534        },
 535        [LINE6_PODXTLIVE_POD] = {
 536                .id = "PODxtLive",
 537                .name = "PODxt Live",
 538                .capabilities   = LINE6_CAP_CONTROL
 539                                | LINE6_CAP_CONTROL_MIDI
 540                                | LINE6_CAP_PCM
 541                                | LINE6_CAP_HWMON,
 542                .altsetting = 1,
 543                .ep_ctrl_r = 0x84,
 544                .ep_ctrl_w = 0x03,
 545                .ep_audio_r = 0x82,
 546                .ep_audio_w = 0x01,
 547        },
 548        [LINE6_PODXTPRO] = {
 549                .id = "PODxtPro",
 550                .name = "PODxt Pro",
 551                .capabilities   = LINE6_CAP_CONTROL
 552                                | LINE6_CAP_CONTROL_MIDI
 553                                | LINE6_CAP_PCM
 554                                | LINE6_CAP_HWMON,
 555                .altsetting = 5,
 556                .ep_ctrl_r = 0x84,
 557                .ep_ctrl_w = 0x03,
 558                .ep_audio_r = 0x82,
 559                .ep_audio_w = 0x01,
 560        },
 561};
 562
 563/*
 564        Probe USB device.
 565*/
 566static int pod_probe(struct usb_interface *interface,
 567                     const struct usb_device_id *id)
 568{
 569        return line6_probe(interface, id, "Line6-POD",
 570                           &pod_properties_table[id->driver_info],
 571                           pod_init, sizeof(struct usb_line6_pod));
 572}
 573
 574static struct usb_driver pod_driver = {
 575        .name = KBUILD_MODNAME,
 576        .probe = pod_probe,
 577        .disconnect = line6_disconnect,
 578#ifdef CONFIG_PM
 579        .suspend = line6_suspend,
 580        .resume = line6_resume,
 581        .reset_resume = line6_resume,
 582#endif
 583        .id_table = pod_id_table,
 584};
 585
 586module_usb_driver(pod_driver);
 587
 588MODULE_DESCRIPTION("Line 6 POD USB driver");
 589MODULE_LICENSE("GPL");
 590