File Index
Files and directories
Sign in
FILE

us144mkii.h

File preview with syntax highlighting.

linux-6.19.14/sound/usb/usx2y/us144mkii.h C
  1/* SPDX-License-Identifier: GPL-2.0-only */
  2// Copyright (c) 2025 Ĺ erif Rami <ramiserifpersia@gmail.com>
  3
  4#ifndef __US144MKII_H
  5#define __US144MKII_H
  6
  7#include <linux/kfifo.h>
  8#include <linux/timer.h>
  9#include <linux/usb.h>
 10#include <linux/workqueue.h>
 11#include <sound/control.h>
 12#include <sound/core.h>
 13#include <sound/initval.h>
 14#include <sound/pcm.h>
 15#include <sound/rawmidi.h>
 16
 17#define DRIVER_NAME "us144mkii"
 18
 19/* --- USB Device Identification --- */
 20#define USB_VID_TASCAM 0x0644
 21#define USB_PID_TASCAM_US144 0x800f
 22#define USB_PID_TASCAM_US144MKII 0x8020
 23
 24/* --- USB Endpoints (Alternate Setting 1) --- */
 25#define EP_PLAYBACK_FEEDBACK 0x81
 26#define EP_AUDIO_OUT 0x02
 27#define EP_MIDI_IN 0x83
 28#define EP_MIDI_OUT 0x04
 29#define EP_AUDIO_IN 0x86
 30
 31/* --- USB Control Message Protocol --- */
 32#define RT_H2D_CLASS_EP (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT)
 33#define RT_D2H_CLASS_EP (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT)
 34#define RT_H2D_VENDOR_DEV (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
 35#define RT_D2H_VENDOR_DEV (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
 36
 37enum uac_request {
 38	UAC_SET_CUR = 0x01,
 39	UAC_GET_CUR = 0x81,
 40};
 41
 42enum uac_control_selector {
 43	UAC_SAMPLING_FREQ_CONTROL = 0x0100,
 44};
 45
 46enum tascam_vendor_request {
 47	VENDOR_REQ_REGISTER_WRITE = 0x41,
 48	VENDOR_REQ_DEEP_SLEEP = 0x44,
 49	VENDOR_REQ_MODE_CONTROL = 0x49,
 50};
 51
 52enum tascam_mode_value {
 53	MODE_VAL_HANDSHAKE_READ = 0x0000,
 54	MODE_VAL_CONFIG = 0x0010,
 55	MODE_VAL_STREAM_START = 0x0030,
 56};
 57
 58#define HANDSHAKE_SUCCESS_VAL 0x12
 59
 60enum tascam_register {
 61	REG_ADDR_UNKNOWN_0D = 0x0d04,
 62	REG_ADDR_UNKNOWN_0E = 0x0e00,
 63	REG_ADDR_UNKNOWN_0F = 0x0f00,
 64	REG_ADDR_RATE_44100 = 0x1000,
 65	REG_ADDR_RATE_48000 = 0x1002,
 66	REG_ADDR_RATE_88200 = 0x1008,
 67	REG_ADDR_RATE_96000 = 0x100a,
 68	REG_ADDR_UNKNOWN_11 = 0x110b,
 69};
 70
 71#define REG_VAL_ENABLE 0x0101
 72
 73/* --- URB Configuration --- */
 74#define NUM_PLAYBACK_URBS 4
 75#define PLAYBACK_URB_PACKETS 8
 76#define NUM_FEEDBACK_URBS 4
 77#define FEEDBACK_URB_PACKETS 1
 78#define FEEDBACK_PACKET_SIZE 3
 79#define NUM_CAPTURE_URBS 8
 80#define CAPTURE_URB_SIZE 512
 81#define CAPTURE_RING_BUFFER_SIZE (CAPTURE_URB_SIZE * NUM_CAPTURE_URBS * 4)
 82#define NUM_MIDI_IN_URBS 4
 83#define MIDI_IN_BUF_SIZE 64
 84#define MIDI_IN_FIFO_SIZE (MIDI_IN_BUF_SIZE * NUM_MIDI_IN_URBS)
 85#define MIDI_OUT_BUF_SIZE 64
 86#define NUM_MIDI_OUT_URBS 4
 87#define USB_CTRL_TIMEOUT_MS 1000
 88#define FEEDBACK_SYNC_LOSS_THRESHOLD 41
 89
 90/* --- Audio Format Configuration --- */
 91#define BYTES_PER_SAMPLE 3
 92#define NUM_CHANNELS 4
 93#define BYTES_PER_FRAME (NUM_CHANNELS * BYTES_PER_SAMPLE)
 94#define FEEDBACK_ACCUMULATOR_SIZE 128
 95
 96/* --- Capture Decoding Defines --- */
 97#define DECODED_CHANNELS_PER_FRAME 4
 98#define DECODED_SAMPLE_SIZE 4
 99#define FRAMES_PER_DECODE_BLOCK 8
100#define RAW_BYTES_PER_DECODE_BLOCK 512
101
102/**
103 * struct us144mkii_frame_pattern_observer - State for dynamic feedback
104 * patterns.
105 * @sample_rate_khz: The current sample rate in kHz.
106 * @base_feedback_value: The nominal feedback value for the current rate.
107 * @feedback_offset: An offset to align the feedback value range.
108 * @full_frame_patterns: A 2D array of pre-calculated packet size patterns.
109 * @current_index: The current index into the pattern array.
110 * @previous_index: The previous index, used for state tracking.
111 * @sync_locked: A flag indicating if the pattern has locked to the stream.
112 */
113struct us144mkii_frame_pattern_observer {
114	unsigned int sample_rate_khz;
115	unsigned int base_feedback_value;
116	int feedback_offset;
117	unsigned int full_frame_patterns[5][8];
118	unsigned int current_index;
119	unsigned int previous_index;
120	bool sync_locked;
121};
122
123/**
124 * struct tascam_card - Main driver data structure for the TASCAM US-144MKII.
125 * @dev: Pointer to the USB device.
126 * @iface0: Pointer to USB interface 0 (audio).
127 * @iface1: Pointer to USB interface 1 (MIDI).
128 * @card: Pointer to the ALSA sound card instance.
129 * @pcm: Pointer to the ALSA PCM device.
130 * @rmidi: Pointer to the ALSA rawmidi device.
131 *
132 * @playback_substream: Pointer to the active playback PCM substream.
133 * @playback_urbs: Array of URBs for playback.
134 * @playback_urb_alloc_size: Size of allocated buffer for each playback URB.
135 * @feedback_urbs: Array of URBs for feedback.
136 * @feedback_urb_alloc_size: Size of allocated buffer for each feedback URB.
137 * @playback_active: Atomic flag indicating if playback is active.
138 * @playback_frames_consumed: Total frames consumed by playback.
139 * @driver_playback_pos: Current position in the ALSA playback buffer (frames).
140 * @last_period_pos: Last reported period position for playback.
141 *
142 * @capture_substream: Pointer to the active capture PCM substream.
143 * @capture_urbs: Array of URBs for capture.
144 * @capture_urb_alloc_size: Size of allocated buffer for each capture URB.
145 * @capture_active: Atomic flag indicating if capture is active.
146 * @driver_capture_pos: Current position in the ALSA capture buffer (frames).
147 * @capture_frames_processed: Total frames processed for capture.
148 * @last_capture_period_pos: Last reported period position for capture.
149 * @capture_ring_buffer: Ring buffer for raw capture data from USB.
150 * @capture_ring_buffer_read_ptr: Read pointer for the capture ring buffer.
151 * @capture_ring_buffer_write_ptr: Write pointer for the capture ring buffer.
152 * @capture_decode_raw_block: Buffer for a raw 512-byte capture block.
153 * @capture_decode_dst_block: Buffer for decoded 32-bit capture samples.
154 * @capture_routing_buffer: Intermediate buffer for capture routing.
155 * @capture_work: Work struct for deferred capture processing.
156 * @stop_work: Work struct for deferred stream stopping.
157 * @stop_pcm_work: Work struct for stopping PCM due to a fatal error (e.g.
158 * xrun).
159 *
160 * @midi_in_substream: Pointer to the active MIDI input substream.
161 * @midi_out_substream: Pointer to the active MIDI output substream.
162 * @midi_in_urbs: Array of URBs for MIDI input.
163 * @midi_out_urbs: Array of URBs for MIDI output.
164 * @midi_in_active: Atomic flag indicating if MIDI input is active.
165 * @midi_out_active: Atomic flag indicating if MIDI output is active.
166 * @midi_in_fifo: FIFO for raw MIDI input data.
167 * @midi_in_work: Work struct for deferred MIDI input processing.
168 * @midi_out_work: Work struct for deferred MIDI output processing.
169 * @midi_in_lock: Spinlock for MIDI input FIFO.
170 * @midi_out_lock: Spinlock for MIDI output.
171 * @midi_out_urbs_in_flight: Bitmap of MIDI output URBs currently in flight.
172 * @midi_running_status: Stores the last MIDI status byte for running status.
173 * @error_timer: Timer for MIDI error retry logic.
174 *
175 * @lock: Main spinlock for protecting shared driver state.
176 * @active_urbs: Atomic counter for active URBs.
177 * @current_rate: Currently configured sample rate of the device.
178 * @line_out_source: Source for Line Outputs (0: Playback 1-2, 1: Playback 3-4).
179 * @digital_out_source: Source for Digital Outputs (0: Playback 1-2, 1: Playback
180 * 3-4).
181 * @capture_12_source: Source for Capture channels 1-2 (0: Analog In, 1: Digital
182 * In).
183 * @capture_34_source: Source for Capture channels 3-4 (0: Analog In, 1: Digital
184 * In).
185 *
186 * @feedback_accumulator_pattern: Stores the calculated frames per packet for
187 * feedback.
188 * @feedback_pattern_out_idx: Read index for feedback_accumulator_pattern.
189 * @feedback_pattern_in_idx: Write index for feedback_accumulator_pattern.
190 * @feedback_synced: Flag indicating if feedback is synced.
191 * @feedback_consecutive_errors: Counter for consecutive feedback errors.
192 * @feedback_urb_skip_count: Number of feedback URBs to skip initially for
193 * stabilization.
194 * @fpo: Holds the state for the dynamic feedback pattern generation.
195 *
196 * @playback_anchor: USB anchor for playback URBs.
197 * @capture_anchor: USB anchor for capture URBs.
198 * @feedback_anchor: USB anchor for feedback URBs.
199 * @midi_in_anchor: USB anchor for MIDI input URBs.
200 * @midi_out_anchor: USB anchor for MIDI output URBs.
201 */
202struct tascam_card {
203	/* --- Core device pointers --- */
204	struct usb_device *dev;
205	struct usb_interface *iface0;
206	struct usb_interface *iface1;
207	struct snd_card *card;
208	struct snd_pcm *pcm;
209	struct snd_rawmidi *rmidi;
210
211	/* --- PCM Substreams --- */
212	struct snd_pcm_substream *playback_substream;
213	struct snd_pcm_substream *capture_substream;
214
215	/* --- URBs and Anchors --- */
216	struct urb *playback_urbs[NUM_PLAYBACK_URBS];
217	size_t playback_urb_alloc_size;
218	struct urb *feedback_urbs[NUM_FEEDBACK_URBS];
219	size_t feedback_urb_alloc_size;
220	struct urb *capture_urbs[NUM_CAPTURE_URBS];
221	size_t capture_urb_alloc_size;
222	struct urb *midi_in_urbs[NUM_MIDI_IN_URBS];
223	struct urb *midi_out_urbs[NUM_MIDI_OUT_URBS];
224	struct usb_anchor playback_anchor;
225	struct usb_anchor capture_anchor;
226	struct usb_anchor feedback_anchor;
227	struct usb_anchor midi_in_anchor;
228	struct usb_anchor midi_out_anchor;
229
230	/* --- Stream State --- */
231	spinlock_t lock;
232	atomic_t playback_active;
233	atomic_t capture_active;
234	atomic_t active_urbs;
235	int current_rate;
236
237	/* --- Playback State --- */
238	u64 playback_frames_consumed;
239	snd_pcm_uframes_t driver_playback_pos;
240	u64 last_period_pos;
241
242	/* --- Capture State --- */
243	u64 capture_frames_processed;
244	snd_pcm_uframes_t driver_capture_pos;
245	u64 last_capture_period_pos;
246	u8 *capture_ring_buffer;
247	size_t capture_ring_buffer_read_ptr;
248	size_t capture_ring_buffer_write_ptr;
249	u8 *capture_decode_raw_block;
250	s32 *capture_decode_dst_block;
251	s32 *capture_routing_buffer;
252
253	/* --- MIDI State --- */
254	struct snd_rawmidi_substream *midi_in_substream;
255	struct snd_rawmidi_substream *midi_out_substream;
256	atomic_t midi_in_active;
257	atomic_t midi_out_active;
258	struct kfifo midi_in_fifo;
259	spinlock_t midi_in_lock;
260	spinlock_t midi_out_lock;
261	unsigned long midi_out_urbs_in_flight;
262	u8 midi_running_status;
263	struct timer_list error_timer;
264	struct completion midi_out_drain_completion;
265
266	/* --- Feedback Sync State --- */
267	unsigned int feedback_accumulator_pattern[FEEDBACK_ACCUMULATOR_SIZE];
268	unsigned int feedback_pattern_out_idx;
269	unsigned int feedback_pattern_in_idx;
270	bool feedback_synced;
271	unsigned int feedback_consecutive_errors;
272	unsigned int feedback_urb_skip_count;
273	struct us144mkii_frame_pattern_observer fpo;
274
275	/* --- Workqueues --- */
276	struct work_struct stop_work;
277	struct work_struct stop_pcm_work;
278	struct work_struct capture_work;
279	struct work_struct midi_in_work;
280	struct work_struct midi_out_work;
281
282	/* --- Mixer/Routing State --- */
283	unsigned int line_out_source;
284	unsigned int digital_out_source;
285	unsigned int capture_12_source;
286	unsigned int capture_34_source;
287};
288
289/* main.c */
290/**
291 * tascam_free_urbs() - Free all allocated URBs and associated buffers.
292 * @tascam: the tascam_card instance
293 *
294 * This function kills, unlinks, and frees all playback, feedback, capture,
295 * and MIDI URBs, along with their transfer buffers and the capture
296 * ring/decode buffers.
297 */
298void tascam_free_urbs(struct tascam_card *tascam);
299
300/**
301 * tascam_alloc_urbs() - Allocate all URBs and associated buffers.
302 * @tascam: the tascam_card instance
303 *
304 * This function allocates and initializes all URBs for playback, feedback,
305 * capture, and MIDI, as well as the necessary buffers for data processing.
306 *
307 * Return: 0 on success, or a negative error code on failure.
308 */
309int tascam_alloc_urbs(struct tascam_card *tascam);
310
311/**
312 * tascam_stop_work_handler() - Work handler to stop all active streams.
313 * @work: Pointer to the work_struct.
314 *
315 * This function is scheduled to stop all active URBs (playback, feedback,
316 * capture) and reset the active_urbs counter.
317 */
318void tascam_stop_work_handler(struct work_struct *work);
319
320/* us144mkii_pcm.h */
321#include "us144mkii_pcm.h"
322
323/* us144mkii_midi.c */
324/**
325 * tascam_midi_in_urb_complete() - Completion handler for MIDI IN URBs
326 * @urb: The completed URB.
327 *
328 * This function runs in interrupt context. It places the raw data from the
329 * USB endpoint into a kfifo and schedules a work item to process it later,
330 * ensuring the interrupt handler remains fast.
331 */
332void tascam_midi_in_urb_complete(struct urb *urb);
333
334/**
335 * tascam_midi_out_urb_complete() - Completion handler for MIDI OUT bulk URB.
336 * @urb: The completed URB.
337 *
338 * This function runs in interrupt context. It marks the output URB as no
339 * longer in-flight. It then re-schedules the work handler to check for and
340 * send any more data waiting in the ALSA buffer. This is a safe, non-blocking
341 * way to continue the data transmission chain.
342 */
343void tascam_midi_out_urb_complete(struct urb *urb);
344
345/**
346 * tascam_create_midi() - Create and initialize the ALSA rawmidi device.
347 * @tascam: The driver instance.
348 *
349 * Return: 0 on success, or a negative error code on failure.
350 */
351int tascam_create_midi(struct tascam_card *tascam);
352
353/* us144mkii_controls.c */
354/**
355 * tascam_create_controls() - Creates and adds ALSA mixer controls for the
356 * device.
357 * @tascam: The driver instance.
358 *
359 * This function registers custom ALSA controls for managing audio routing
360 * (line out source, digital out source, capture 1-2 source, capture 3-4 source)
361 * and displaying the current sample rate.
362 *
363 * Return: 0 on success, or a negative error code on failure.
364 */
365int tascam_create_controls(struct tascam_card *tascam);
366
367#endif /* __US144MKII_H */
~/ Read-only file preview.