162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Line 6 Linux USB driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#ifndef DRIVER_H
962306a36Sopenharmony_ci#define DRIVER_H
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/usb.h>
1262306a36Sopenharmony_ci#include <linux/mutex.h>
1362306a36Sopenharmony_ci#include <linux/kfifo.h>
1462306a36Sopenharmony_ci#include <sound/core.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include "midi.h"
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/* USB 1.1 speed configuration */
1962306a36Sopenharmony_ci#define USB_LOW_INTERVALS_PER_SECOND 1000
2062306a36Sopenharmony_ci#define USB_LOW_ISO_BUFFERS 2
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci/* USB 2.0+ speed configuration */
2362306a36Sopenharmony_ci#define USB_HIGH_INTERVALS_PER_SECOND 8000
2462306a36Sopenharmony_ci#define USB_HIGH_ISO_BUFFERS 16
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci/* Fallback USB interval and max packet size values */
2762306a36Sopenharmony_ci#define LINE6_FALLBACK_INTERVAL 10
2862306a36Sopenharmony_ci#define LINE6_FALLBACK_MAXPACKETSIZE 16
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#define LINE6_TIMEOUT 1000
3162306a36Sopenharmony_ci#define LINE6_BUFSIZE_LISTEN 64
3262306a36Sopenharmony_ci#define LINE6_MIDI_MESSAGE_MAXLEN 256
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define LINE6_RAW_MESSAGES_MAXCOUNT_ORDER 7
3562306a36Sopenharmony_ci/* 4k packets are common, BUFSIZE * MAXCOUNT should be bigger... */
3662306a36Sopenharmony_ci#define LINE6_RAW_MESSAGES_MAXCOUNT (1 << LINE6_RAW_MESSAGES_MAXCOUNT_ORDER)
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#if LINE6_BUFSIZE_LISTEN > 65535
4062306a36Sopenharmony_ci#error "Use dynamic fifo instead"
4162306a36Sopenharmony_ci#endif
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci/*
4462306a36Sopenharmony_ci	Line 6 MIDI control commands
4562306a36Sopenharmony_ci*/
4662306a36Sopenharmony_ci#define LINE6_PARAM_CHANGE   0xb0
4762306a36Sopenharmony_ci#define LINE6_PROGRAM_CHANGE 0xc0
4862306a36Sopenharmony_ci#define LINE6_SYSEX_BEGIN    0xf0
4962306a36Sopenharmony_ci#define LINE6_SYSEX_END      0xf7
5062306a36Sopenharmony_ci#define LINE6_RESET          0xff
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci/*
5362306a36Sopenharmony_ci	MIDI channel for messages initiated by the host
5462306a36Sopenharmony_ci	(and eventually echoed back by the device)
5562306a36Sopenharmony_ci*/
5662306a36Sopenharmony_ci#define LINE6_CHANNEL_HOST   0x00
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci/*
5962306a36Sopenharmony_ci	MIDI channel for messages initiated by the device
6062306a36Sopenharmony_ci*/
6162306a36Sopenharmony_ci#define LINE6_CHANNEL_DEVICE 0x02
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci#define LINE6_CHANNEL_UNKNOWN 5	/* don't know yet what this is good for */
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci#define LINE6_CHANNEL_MASK 0x0f
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ciextern const unsigned char line6_midi_id[3];
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci#define SYSEX_DATA_OFS (sizeof(line6_midi_id) + 3)
7062306a36Sopenharmony_ci#define SYSEX_EXTRA_SIZE (sizeof(line6_midi_id) + 4)
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci/*
7362306a36Sopenharmony_ci	 Common properties of Line 6 devices.
7462306a36Sopenharmony_ci*/
7562306a36Sopenharmony_cistruct line6_properties {
7662306a36Sopenharmony_ci	/* Card id string (maximum 16 characters).
7762306a36Sopenharmony_ci	 * This can be used to address the device in ALSA programs as
7862306a36Sopenharmony_ci	 * "default:CARD=<id>"
7962306a36Sopenharmony_ci	 */
8062306a36Sopenharmony_ci	const char *id;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	/* Card short name (maximum 32 characters) */
8362306a36Sopenharmony_ci	const char *name;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	/* Bit vector defining this device's capabilities in line6usb driver */
8662306a36Sopenharmony_ci	int capabilities;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	int altsetting;
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	unsigned int ctrl_if;
9162306a36Sopenharmony_ci	unsigned int ep_ctrl_r;
9262306a36Sopenharmony_ci	unsigned int ep_ctrl_w;
9362306a36Sopenharmony_ci	unsigned int ep_audio_r;
9462306a36Sopenharmony_ci	unsigned int ep_audio_w;
9562306a36Sopenharmony_ci};
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci/* Capability bits */
9862306a36Sopenharmony_cienum {
9962306a36Sopenharmony_ci	/* device supports settings parameter via USB */
10062306a36Sopenharmony_ci	LINE6_CAP_CONTROL =	1 << 0,
10162306a36Sopenharmony_ci	/* device supports PCM input/output via USB */
10262306a36Sopenharmony_ci	LINE6_CAP_PCM =		1 << 1,
10362306a36Sopenharmony_ci	/* device supports hardware monitoring */
10462306a36Sopenharmony_ci	LINE6_CAP_HWMON =	1 << 2,
10562306a36Sopenharmony_ci	/* device requires output data when input is read */
10662306a36Sopenharmony_ci	LINE6_CAP_IN_NEEDS_OUT = 1 << 3,
10762306a36Sopenharmony_ci	/* device uses raw MIDI via USB (data endpoints) */
10862306a36Sopenharmony_ci	LINE6_CAP_CONTROL_MIDI = 1 << 4,
10962306a36Sopenharmony_ci	/* device provides low-level information */
11062306a36Sopenharmony_ci	LINE6_CAP_CONTROL_INFO = 1 << 5,
11162306a36Sopenharmony_ci	/* device provides hardware monitoring volume control */
11262306a36Sopenharmony_ci	LINE6_CAP_HWMON_CTL =	1 << 6,
11362306a36Sopenharmony_ci};
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci/*
11662306a36Sopenharmony_ci	 Common data shared by all Line 6 devices.
11762306a36Sopenharmony_ci	 Corresponds to a pair of USB endpoints.
11862306a36Sopenharmony_ci*/
11962306a36Sopenharmony_cistruct usb_line6 {
12062306a36Sopenharmony_ci	/* USB device */
12162306a36Sopenharmony_ci	struct usb_device *usbdev;
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	/* Properties */
12462306a36Sopenharmony_ci	const struct line6_properties *properties;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	/* Interval for data USB packets */
12762306a36Sopenharmony_ci	int interval;
12862306a36Sopenharmony_ci	/* ...for isochronous transfers framing */
12962306a36Sopenharmony_ci	int intervals_per_second;
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	/* Number of isochronous URBs used for frame transfers */
13262306a36Sopenharmony_ci	int iso_buffers;
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	/* Maximum size of data USB packet */
13562306a36Sopenharmony_ci	int max_packet_size;
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	/* Device representing the USB interface */
13862306a36Sopenharmony_ci	struct device *ifcdev;
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	/* Line 6 sound card data structure.
14162306a36Sopenharmony_ci	 * Each device has at least MIDI or PCM.
14262306a36Sopenharmony_ci	 */
14362306a36Sopenharmony_ci	struct snd_card *card;
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	/* Line 6 PCM device data structure */
14662306a36Sopenharmony_ci	struct snd_line6_pcm *line6pcm;
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	/* Line 6 MIDI device data structure */
14962306a36Sopenharmony_ci	struct snd_line6_midi *line6midi;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	/* URB for listening to POD data endpoint */
15262306a36Sopenharmony_ci	struct urb *urb_listen;
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	/* Buffer for incoming data from POD data endpoint */
15562306a36Sopenharmony_ci	unsigned char *buffer_listen;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	/* Buffer for message to be processed, generated from MIDI layer */
15862306a36Sopenharmony_ci	unsigned char *buffer_message;
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	/* Length of message to be processed, generated from MIDI layer  */
16162306a36Sopenharmony_ci	int message_length;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	/* Circular buffer for non-MIDI control messages */
16462306a36Sopenharmony_ci	struct {
16562306a36Sopenharmony_ci		struct mutex read_lock;
16662306a36Sopenharmony_ci		wait_queue_head_t wait_queue;
16762306a36Sopenharmony_ci		unsigned int active:1;
16862306a36Sopenharmony_ci		unsigned int nonblock:1;
16962306a36Sopenharmony_ci		STRUCT_KFIFO_REC_2(LINE6_BUFSIZE_LISTEN * LINE6_RAW_MESSAGES_MAXCOUNT)
17062306a36Sopenharmony_ci			fifo;
17162306a36Sopenharmony_ci	} messages;
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	/* Work for delayed PCM startup */
17462306a36Sopenharmony_ci	struct delayed_work startup_work;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	/* If MIDI is supported, buffer_message contains the pre-processed data;
17762306a36Sopenharmony_ci	 * otherwise the data is only in urb_listen (buffer_incoming).
17862306a36Sopenharmony_ci	 */
17962306a36Sopenharmony_ci	void (*process_message)(struct usb_line6 *);
18062306a36Sopenharmony_ci	void (*disconnect)(struct usb_line6 *line6);
18162306a36Sopenharmony_ci	void (*startup)(struct usb_line6 *line6);
18262306a36Sopenharmony_ci};
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ciextern char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1,
18562306a36Sopenharmony_ci				      int code2, int size);
18662306a36Sopenharmony_ciextern int line6_read_data(struct usb_line6 *line6, unsigned address,
18762306a36Sopenharmony_ci			   void *data, unsigned datalen);
18862306a36Sopenharmony_ciextern int line6_read_serial_number(struct usb_line6 *line6,
18962306a36Sopenharmony_ci				    u32 *serial_number);
19062306a36Sopenharmony_ciextern int line6_send_raw_message(struct usb_line6 *line6,
19162306a36Sopenharmony_ci					const char *buffer, int size);
19262306a36Sopenharmony_ciextern int line6_send_raw_message_async(struct usb_line6 *line6,
19362306a36Sopenharmony_ci					const char *buffer, int size);
19462306a36Sopenharmony_ciextern int line6_send_sysex_message(struct usb_line6 *line6,
19562306a36Sopenharmony_ci				    const char *buffer, int size);
19662306a36Sopenharmony_ciextern int line6_version_request_async(struct usb_line6 *line6);
19762306a36Sopenharmony_ciextern int line6_write_data(struct usb_line6 *line6, unsigned address,
19862306a36Sopenharmony_ci			    void *data, unsigned datalen);
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ciint line6_probe(struct usb_interface *interface,
20162306a36Sopenharmony_ci		const struct usb_device_id *id,
20262306a36Sopenharmony_ci		const char *driver_name,
20362306a36Sopenharmony_ci		const struct line6_properties *properties,
20462306a36Sopenharmony_ci		int (*private_init)(struct usb_line6 *, const struct usb_device_id *id),
20562306a36Sopenharmony_ci		size_t data_size);
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_civoid line6_disconnect(struct usb_interface *interface);
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci#ifdef CONFIG_PM
21062306a36Sopenharmony_ciint line6_suspend(struct usb_interface *interface, pm_message_t message);
21162306a36Sopenharmony_ciint line6_resume(struct usb_interface *interface);
21262306a36Sopenharmony_ci#endif
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci#endif
215