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