18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Line 6 Linux USB driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#ifndef DRIVER_H 98c2ecf20Sopenharmony_ci#define DRIVER_H 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/usb.h> 128c2ecf20Sopenharmony_ci#include <linux/mutex.h> 138c2ecf20Sopenharmony_ci#include <linux/kfifo.h> 148c2ecf20Sopenharmony_ci#include <sound/core.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include "midi.h" 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci/* USB 1.1 speed configuration */ 198c2ecf20Sopenharmony_ci#define USB_LOW_INTERVALS_PER_SECOND 1000 208c2ecf20Sopenharmony_ci#define USB_LOW_ISO_BUFFERS 2 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci/* USB 2.0+ speed configuration */ 238c2ecf20Sopenharmony_ci#define USB_HIGH_INTERVALS_PER_SECOND 8000 248c2ecf20Sopenharmony_ci#define USB_HIGH_ISO_BUFFERS 16 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci/* Fallback USB interval and max packet size values */ 278c2ecf20Sopenharmony_ci#define LINE6_FALLBACK_INTERVAL 10 288c2ecf20Sopenharmony_ci#define LINE6_FALLBACK_MAXPACKETSIZE 16 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define LINE6_TIMEOUT 1000 318c2ecf20Sopenharmony_ci#define LINE6_BUFSIZE_LISTEN 64 328c2ecf20Sopenharmony_ci#define LINE6_MIDI_MESSAGE_MAXLEN 256 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define LINE6_RAW_MESSAGES_MAXCOUNT_ORDER 7 358c2ecf20Sopenharmony_ci/* 4k packets are common, BUFSIZE * MAXCOUNT should be bigger... */ 368c2ecf20Sopenharmony_ci#define LINE6_RAW_MESSAGES_MAXCOUNT (1 << LINE6_RAW_MESSAGES_MAXCOUNT_ORDER) 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#if LINE6_BUFSIZE_LISTEN > 65535 408c2ecf20Sopenharmony_ci#error "Use dynamic fifo instead" 418c2ecf20Sopenharmony_ci#endif 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* 448c2ecf20Sopenharmony_ci Line 6 MIDI control commands 458c2ecf20Sopenharmony_ci*/ 468c2ecf20Sopenharmony_ci#define LINE6_PARAM_CHANGE 0xb0 478c2ecf20Sopenharmony_ci#define LINE6_PROGRAM_CHANGE 0xc0 488c2ecf20Sopenharmony_ci#define LINE6_SYSEX_BEGIN 0xf0 498c2ecf20Sopenharmony_ci#define LINE6_SYSEX_END 0xf7 508c2ecf20Sopenharmony_ci#define LINE6_RESET 0xff 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci/* 538c2ecf20Sopenharmony_ci MIDI channel for messages initiated by the host 548c2ecf20Sopenharmony_ci (and eventually echoed back by the device) 558c2ecf20Sopenharmony_ci*/ 568c2ecf20Sopenharmony_ci#define LINE6_CHANNEL_HOST 0x00 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci/* 598c2ecf20Sopenharmony_ci MIDI channel for messages initiated by the device 608c2ecf20Sopenharmony_ci*/ 618c2ecf20Sopenharmony_ci#define LINE6_CHANNEL_DEVICE 0x02 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci#define LINE6_CHANNEL_UNKNOWN 5 /* don't know yet what this is good for */ 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci#define LINE6_CHANNEL_MASK 0x0f 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ciextern const unsigned char line6_midi_id[3]; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci#define SYSEX_DATA_OFS (sizeof(line6_midi_id) + 3) 708c2ecf20Sopenharmony_ci#define SYSEX_EXTRA_SIZE (sizeof(line6_midi_id) + 4) 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci/* 738c2ecf20Sopenharmony_ci Common properties of Line 6 devices. 748c2ecf20Sopenharmony_ci*/ 758c2ecf20Sopenharmony_cistruct line6_properties { 768c2ecf20Sopenharmony_ci /* Card id string (maximum 16 characters). 778c2ecf20Sopenharmony_ci * This can be used to address the device in ALSA programs as 788c2ecf20Sopenharmony_ci * "default:CARD=<id>" 798c2ecf20Sopenharmony_ci */ 808c2ecf20Sopenharmony_ci const char *id; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci /* Card short name (maximum 32 characters) */ 838c2ecf20Sopenharmony_ci const char *name; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci /* Bit vector defining this device's capabilities in line6usb driver */ 868c2ecf20Sopenharmony_ci int capabilities; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci int altsetting; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci unsigned int ctrl_if; 918c2ecf20Sopenharmony_ci unsigned int ep_ctrl_r; 928c2ecf20Sopenharmony_ci unsigned int ep_ctrl_w; 938c2ecf20Sopenharmony_ci unsigned int ep_audio_r; 948c2ecf20Sopenharmony_ci unsigned int ep_audio_w; 958c2ecf20Sopenharmony_ci}; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci/* Capability bits */ 988c2ecf20Sopenharmony_cienum { 998c2ecf20Sopenharmony_ci /* device supports settings parameter via USB */ 1008c2ecf20Sopenharmony_ci LINE6_CAP_CONTROL = 1 << 0, 1018c2ecf20Sopenharmony_ci /* device supports PCM input/output via USB */ 1028c2ecf20Sopenharmony_ci LINE6_CAP_PCM = 1 << 1, 1038c2ecf20Sopenharmony_ci /* device supports hardware monitoring */ 1048c2ecf20Sopenharmony_ci LINE6_CAP_HWMON = 1 << 2, 1058c2ecf20Sopenharmony_ci /* device requires output data when input is read */ 1068c2ecf20Sopenharmony_ci LINE6_CAP_IN_NEEDS_OUT = 1 << 3, 1078c2ecf20Sopenharmony_ci /* device uses raw MIDI via USB (data endpoints) */ 1088c2ecf20Sopenharmony_ci LINE6_CAP_CONTROL_MIDI = 1 << 4, 1098c2ecf20Sopenharmony_ci /* device provides low-level information */ 1108c2ecf20Sopenharmony_ci LINE6_CAP_CONTROL_INFO = 1 << 5, 1118c2ecf20Sopenharmony_ci /* device provides hardware monitoring volume control */ 1128c2ecf20Sopenharmony_ci LINE6_CAP_HWMON_CTL = 1 << 6, 1138c2ecf20Sopenharmony_ci}; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci/* 1168c2ecf20Sopenharmony_ci Common data shared by all Line 6 devices. 1178c2ecf20Sopenharmony_ci Corresponds to a pair of USB endpoints. 1188c2ecf20Sopenharmony_ci*/ 1198c2ecf20Sopenharmony_cistruct usb_line6 { 1208c2ecf20Sopenharmony_ci /* USB device */ 1218c2ecf20Sopenharmony_ci struct usb_device *usbdev; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci /* Properties */ 1248c2ecf20Sopenharmony_ci const struct line6_properties *properties; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci /* Interval for data USB packets */ 1278c2ecf20Sopenharmony_ci int interval; 1288c2ecf20Sopenharmony_ci /* ...for isochronous transfers framing */ 1298c2ecf20Sopenharmony_ci int intervals_per_second; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci /* Number of isochronous URBs used for frame transfers */ 1328c2ecf20Sopenharmony_ci int iso_buffers; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci /* Maximum size of data USB packet */ 1358c2ecf20Sopenharmony_ci int max_packet_size; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci /* Device representing the USB interface */ 1388c2ecf20Sopenharmony_ci struct device *ifcdev; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci /* Line 6 sound card data structure. 1418c2ecf20Sopenharmony_ci * Each device has at least MIDI or PCM. 1428c2ecf20Sopenharmony_ci */ 1438c2ecf20Sopenharmony_ci struct snd_card *card; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci /* Line 6 PCM device data structure */ 1468c2ecf20Sopenharmony_ci struct snd_line6_pcm *line6pcm; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci /* Line 6 MIDI device data structure */ 1498c2ecf20Sopenharmony_ci struct snd_line6_midi *line6midi; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci /* URB for listening to POD data endpoint */ 1528c2ecf20Sopenharmony_ci struct urb *urb_listen; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci /* Buffer for incoming data from POD data endpoint */ 1558c2ecf20Sopenharmony_ci unsigned char *buffer_listen; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci /* Buffer for message to be processed, generated from MIDI layer */ 1588c2ecf20Sopenharmony_ci unsigned char *buffer_message; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci /* Length of message to be processed, generated from MIDI layer */ 1618c2ecf20Sopenharmony_ci int message_length; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* Circular buffer for non-MIDI control messages */ 1648c2ecf20Sopenharmony_ci struct { 1658c2ecf20Sopenharmony_ci struct mutex read_lock; 1668c2ecf20Sopenharmony_ci wait_queue_head_t wait_queue; 1678c2ecf20Sopenharmony_ci unsigned int active:1; 1688c2ecf20Sopenharmony_ci unsigned int nonblock:1; 1698c2ecf20Sopenharmony_ci STRUCT_KFIFO_REC_2(LINE6_BUFSIZE_LISTEN * LINE6_RAW_MESSAGES_MAXCOUNT) 1708c2ecf20Sopenharmony_ci fifo; 1718c2ecf20Sopenharmony_ci } messages; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci /* Work for delayed PCM startup */ 1748c2ecf20Sopenharmony_ci struct delayed_work startup_work; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci /* If MIDI is supported, buffer_message contains the pre-processed data; 1778c2ecf20Sopenharmony_ci * otherwise the data is only in urb_listen (buffer_incoming). 1788c2ecf20Sopenharmony_ci */ 1798c2ecf20Sopenharmony_ci void (*process_message)(struct usb_line6 *); 1808c2ecf20Sopenharmony_ci void (*disconnect)(struct usb_line6 *line6); 1818c2ecf20Sopenharmony_ci void (*startup)(struct usb_line6 *line6); 1828c2ecf20Sopenharmony_ci}; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ciextern char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1, 1858c2ecf20Sopenharmony_ci int code2, int size); 1868c2ecf20Sopenharmony_ciextern int line6_read_data(struct usb_line6 *line6, unsigned address, 1878c2ecf20Sopenharmony_ci void *data, unsigned datalen); 1888c2ecf20Sopenharmony_ciextern int line6_read_serial_number(struct usb_line6 *line6, 1898c2ecf20Sopenharmony_ci u32 *serial_number); 1908c2ecf20Sopenharmony_ciextern int line6_send_raw_message(struct usb_line6 *line6, 1918c2ecf20Sopenharmony_ci const char *buffer, int size); 1928c2ecf20Sopenharmony_ciextern int line6_send_raw_message_async(struct usb_line6 *line6, 1938c2ecf20Sopenharmony_ci const char *buffer, int size); 1948c2ecf20Sopenharmony_ciextern int line6_send_sysex_message(struct usb_line6 *line6, 1958c2ecf20Sopenharmony_ci const char *buffer, int size); 1968c2ecf20Sopenharmony_ciextern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr, 1978c2ecf20Sopenharmony_ci const char *buf, size_t count); 1988c2ecf20Sopenharmony_ciextern int line6_version_request_async(struct usb_line6 *line6); 1998c2ecf20Sopenharmony_ciextern int line6_write_data(struct usb_line6 *line6, unsigned address, 2008c2ecf20Sopenharmony_ci void *data, unsigned datalen); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ciint line6_probe(struct usb_interface *interface, 2038c2ecf20Sopenharmony_ci const struct usb_device_id *id, 2048c2ecf20Sopenharmony_ci const char *driver_name, 2058c2ecf20Sopenharmony_ci const struct line6_properties *properties, 2068c2ecf20Sopenharmony_ci int (*private_init)(struct usb_line6 *, const struct usb_device_id *id), 2078c2ecf20Sopenharmony_ci size_t data_size); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_civoid line6_disconnect(struct usb_interface *interface); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 2128c2ecf20Sopenharmony_ciint line6_suspend(struct usb_interface *interface, pm_message_t message); 2138c2ecf20Sopenharmony_ciint line6_resume(struct usb_interface *interface); 2148c2ecf20Sopenharmony_ci#endif 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci#endif 217