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