conform to linux kernel code styles

This commit is contained in:
serifpersia 2025-07-20 11:32:43 +02:00
parent 42cb351089
commit 8f78ebe3a3
1 changed files with 193 additions and 130 deletions

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2025 serifpersia <ramiserifpersia@gmail.com> // Copyright (c) 2025 serifpersia <ramiserifpersia@gmail.com>
/* /*
* ALSA Driver for TASCAM US-144MKII Audio Interface * ALSA Driver for TASCAM US-144MKII Audio Interface
@ -18,7 +18,7 @@ MODULE_DESCRIPTION("ALSA Driver for TASCAM US-144MKII");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
#define DRIVER_NAME "us144mkii" #define DRIVER_NAME "us144mkii"
#define DRIVER_VERSION "1.6" #define DRIVER_VERSION "1.6.1"
/* --- Module Parameters --- */ /* --- Module Parameters --- */
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
@ -119,7 +119,7 @@ struct tascam_card {
u64 last_capture_period_pos; u64 last_capture_period_pos;
u8 *capture_ring_buffer; u8 *capture_ring_buffer;
size_t capture_ring_buffer_read_ptr; size_t capture_ring_buffer_read_ptr;
volatile size_t capture_ring_buffer_write_ptr; size_t capture_ring_buffer_write_ptr;
u8 *capture_decode_raw_block; u8 *capture_decode_raw_block;
s32 *capture_decode_dst_block; s32 *capture_decode_dst_block;
s32 *capture_routing_buffer; s32 *capture_routing_buffer;
@ -196,13 +196,16 @@ static int tascam_playback_source_info(struct snd_kcontrol *kcontrol, struct snd
uinfo->value.enumerated.items = 2; uinfo->value.enumerated.items = 2;
if (uinfo->value.enumerated.item >= 2) if (uinfo->value.enumerated.item >= 2)
uinfo->value.enumerated.item = 1; uinfo->value.enumerated.item = 1;
strcpy(uinfo->value.enumerated.name, playback_source_texts[uinfo->value.enumerated.item]); strscpy(uinfo->value.enumerated.name,
playback_source_texts[uinfo->value.enumerated.item],
sizeof(uinfo->value.enumerated.name));
return 0; return 0;
} }
static int tascam_line_out_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) static int tascam_line_out_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ {
struct tascam_card *tascam = snd_kcontrol_chip(kcontrol); struct tascam_card *tascam = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = tascam->line_out_source; ucontrol->value.enumerated.item[0] = tascam->line_out_source;
return 0; return 0;
} }
@ -210,6 +213,7 @@ static int tascam_line_out_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ele
static int tascam_line_out_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) static int tascam_line_out_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ {
struct tascam_card *tascam = snd_kcontrol_chip(kcontrol); struct tascam_card *tascam = snd_kcontrol_chip(kcontrol);
if (ucontrol->value.enumerated.item[0] > 1) if (ucontrol->value.enumerated.item[0] > 1)
return -EINVAL; return -EINVAL;
if (tascam->line_out_source == ucontrol->value.enumerated.item[0]) if (tascam->line_out_source == ucontrol->value.enumerated.item[0])
@ -226,6 +230,7 @@ static const struct snd_kcontrol_new tascam_line_out_control = {
static int tascam_digital_out_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) static int tascam_digital_out_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ {
struct tascam_card *tascam = snd_kcontrol_chip(kcontrol); struct tascam_card *tascam = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = tascam->digital_out_source; ucontrol->value.enumerated.item[0] = tascam->digital_out_source;
return 0; return 0;
} }
@ -233,6 +238,7 @@ static int tascam_digital_out_get(struct snd_kcontrol *kcontrol, struct snd_ctl_
static int tascam_digital_out_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) static int tascam_digital_out_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ {
struct tascam_card *tascam = snd_kcontrol_chip(kcontrol); struct tascam_card *tascam = snd_kcontrol_chip(kcontrol);
if (ucontrol->value.enumerated.item[0] > 1) if (ucontrol->value.enumerated.item[0] > 1)
return -EINVAL; return -EINVAL;
if (tascam->digital_out_source == ucontrol->value.enumerated.item[0]) if (tascam->digital_out_source == ucontrol->value.enumerated.item[0])
@ -253,13 +259,16 @@ static int tascam_capture_source_info(struct snd_kcontrol *kcontrol, struct snd_
uinfo->value.enumerated.items = 2; uinfo->value.enumerated.items = 2;
if (uinfo->value.enumerated.item >= 2) if (uinfo->value.enumerated.item >= 2)
uinfo->value.enumerated.item = 1; uinfo->value.enumerated.item = 1;
strcpy(uinfo->value.enumerated.name, capture_source_texts[uinfo->value.enumerated.item]); strscpy(uinfo->value.enumerated.name,
capture_source_texts[uinfo->value.enumerated.item],
sizeof(uinfo->value.enumerated.name));
return 0; return 0;
} }
static int tascam_capture_12_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) static int tascam_capture_12_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ {
struct tascam_card *tascam = snd_kcontrol_chip(kcontrol); struct tascam_card *tascam = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = tascam->capture_12_source; ucontrol->value.enumerated.item[0] = tascam->capture_12_source;
return 0; return 0;
} }
@ -267,6 +276,7 @@ static int tascam_capture_12_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e
static int tascam_capture_12_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) static int tascam_capture_12_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ {
struct tascam_card *tascam = snd_kcontrol_chip(kcontrol); struct tascam_card *tascam = snd_kcontrol_chip(kcontrol);
if (ucontrol->value.enumerated.item[0] > 1) if (ucontrol->value.enumerated.item[0] > 1)
return -EINVAL; return -EINVAL;
if (tascam->capture_12_source == ucontrol->value.enumerated.item[0]) if (tascam->capture_12_source == ucontrol->value.enumerated.item[0])
@ -283,6 +293,7 @@ static const struct snd_kcontrol_new tascam_capture_12_control = {
static int tascam_capture_34_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) static int tascam_capture_34_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ {
struct tascam_card *tascam = snd_kcontrol_chip(kcontrol); struct tascam_card *tascam = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = tascam->capture_34_source; ucontrol->value.enumerated.item[0] = tascam->capture_34_source;
return 0; return 0;
} }
@ -290,6 +301,7 @@ static int tascam_capture_34_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e
static int tascam_capture_34_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) static int tascam_capture_34_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ {
struct tascam_card *tascam = snd_kcontrol_chip(kcontrol); struct tascam_card *tascam = snd_kcontrol_chip(kcontrol);
if (ucontrol->value.enumerated.item[0] > 1) if (ucontrol->value.enumerated.item[0] > 1)
return -EINVAL; return -EINVAL;
if (tascam->capture_34_source == ucontrol->value.enumerated.item[0]) if (tascam->capture_34_source == ucontrol->value.enumerated.item[0])
@ -350,13 +362,15 @@ static const struct snd_kcontrol_new tascam_samplerate_control = {
}; };
/** /**
* process_playback_routing_us144mkii * process_playback_routing_us144mkii() - Apply playback routing matrix
* @tascam: The driver instance. * @tascam: The driver instance.
* @src_buffer: Buffer containing 4 channels of S24_3LE audio from ALSA. * @src_buffer: Buffer containing 4 channels of S24_3LE audio from ALSA.
* @dst_buffer: Buffer to be filled with 4 channels of S24_3LE audio for the USB device. * @dst_buffer: Buffer to be filled for the USB device.
* @frames: Number of frames to process. * @frames: Number of frames to process.
*/ */
static void process_playback_routing_us144mkii(struct tascam_card *tascam, const u8 *src_buffer, u8 *dst_buffer, size_t frames) static void process_playback_routing_us144mkii(struct tascam_card *tascam,
const u8 *src_buffer,
u8 *dst_buffer, size_t frames)
{ {
size_t f; size_t f;
const u8 *src_12, *src_34; const u8 *src_12, *src_34;
@ -368,27 +382,29 @@ static void process_playback_routing_us144mkii(struct tascam_card *tascam, const
dst_line = dst_buffer + f * BYTES_PER_FRAME; dst_line = dst_buffer + f * BYTES_PER_FRAME;
dst_digital = dst_line + (2 * BYTES_PER_SAMPLE); dst_digital = dst_line + (2 * BYTES_PER_SAMPLE);
// LINE OUTPUTS (ch1/2 on device) /* LINE OUTPUTS (ch1/2 on device) */
if (tascam->line_out_source == 0) // "ch1 and ch2" if (tascam->line_out_source == 0) /* "ch1 and ch2" */
memcpy(dst_line, src_12, 2 * BYTES_PER_SAMPLE); memcpy(dst_line, src_12, 2 * BYTES_PER_SAMPLE);
else // "ch3 and ch4" else /* "ch3 and ch4" */
memcpy(dst_line, src_34, 2 * BYTES_PER_SAMPLE); memcpy(dst_line, src_34, 2 * BYTES_PER_SAMPLE);
// DIGITAL OUTPUTS (ch3/4 on device) /* DIGITAL OUTPUTS (ch3/4 on device) */
if (tascam->digital_out_source == 0) // "ch1 and ch2" if (tascam->digital_out_source == 0) /* "ch1 and ch2" */
memcpy(dst_digital, src_12, 2 * BYTES_PER_SAMPLE); memcpy(dst_digital, src_12, 2 * BYTES_PER_SAMPLE);
else // "ch3 and ch4" else /* "ch3 and ch4" */
memcpy(dst_digital, src_34, 2 * BYTES_PER_SAMPLE); memcpy(dst_digital, src_34, 2 * BYTES_PER_SAMPLE);
} }
} }
/** /**
* process_capture_routing_us144mkii * process_capture_routing_us144mkii() - Apply capture routing matrix
* @tascam: The driver instance. * @tascam: The driver instance.
* @decoded_block: Buffer containing 4 channels of S32LE decoded audio from device. * @decoded_block: Buffer containing 4 channels of S32LE decoded audio.
* @routed_block: Buffer to be filled with 4 channels of S32LE audio for ALSA. * @routed_block: Buffer to be filled for ALSA.
*/ */
static void process_capture_routing_us144mkii(struct tascam_card *tascam, const s32 *decoded_block, s32 *routed_block) static void process_capture_routing_us144mkii(struct tascam_card *tascam,
const s32 *decoded_block,
s32 *routed_block)
{ {
int f; int f;
const s32 *src_frame; const s32 *src_frame;
@ -398,22 +414,22 @@ static void process_capture_routing_us144mkii(struct tascam_card *tascam, const
src_frame = decoded_block + (f * DECODED_CHANNELS_PER_FRAME); src_frame = decoded_block + (f * DECODED_CHANNELS_PER_FRAME);
dst_frame = routed_block + (f * DECODED_CHANNELS_PER_FRAME); dst_frame = routed_block + (f * DECODED_CHANNELS_PER_FRAME);
// ch1 and ch2 Source /* ch1 and ch2 Source */
if (tascam->capture_12_source == 0) { // analog inputs if (tascam->capture_12_source == 0) { /* analog inputs */
dst_frame[0] = src_frame[0]; // Analog L dst_frame[0] = src_frame[0]; /* Analog L */
dst_frame[1] = src_frame[1]; // Analog R dst_frame[1] = src_frame[1]; /* Analog R */
} else { // digital inputs } else { /* digital inputs */
dst_frame[0] = src_frame[2]; // Digital L dst_frame[0] = src_frame[2]; /* Digital L */
dst_frame[1] = src_frame[3]; // Digital R dst_frame[1] = src_frame[3]; /* Digital R */
} }
// ch3 and ch4 Source /* ch3 and ch4 Source */
if (tascam->capture_34_source == 0) { // analog inputs if (tascam->capture_34_source == 0) { /* analog inputs */
dst_frame[2] = src_frame[0]; // Analog L (Duplicate) dst_frame[2] = src_frame[0]; /* Analog L (Duplicate) */
dst_frame[3] = src_frame[1]; // Analog R (Duplicate) dst_frame[3] = src_frame[1]; /* Analog R (Duplicate) */
} else { // digital inputs } else { /* digital inputs */
dst_frame[2] = src_frame[2]; // Digital L dst_frame[2] = src_frame[2]; /* Digital L */
dst_frame[3] = src_frame[3]; // Digital R dst_frame[3] = src_frame[3]; /* Digital R */
} }
} }
} }
@ -457,8 +473,8 @@ static const struct snd_pcm_hardware tascam_pcm_hw = {
}; };
/** /**
* tascam_free_urbs - Free all allocated URBs and associated buffers. * tascam_free_urbs() - Free all allocated URBs and associated buffers.
* @tascam: the tascam_card instance. * @tascam: the tascam_card instance
* *
* This function kills, unlinks, and frees all playback, feedback, capture, * This function kills, unlinks, and frees all playback, feedback, capture,
* and MIDI URBs, along with their transfer buffers and the capture * and MIDI URBs, along with their transfer buffers and the capture
@ -537,8 +553,8 @@ static void tascam_free_urbs(struct tascam_card *tascam)
} }
/** /**
* tascam_alloc_urbs - Allocate all URBs and associated buffers. * tascam_alloc_urbs() - Allocate all URBs and associated buffers.
* @tascam: the tascam_card instance. * @tascam: the tascam_card instance
* *
* This function allocates and initializes all URBs for playback, feedback, * This function allocates and initializes all URBs for playback, feedback,
* capture, and MIDI, as well as the necessary buffers for data processing. * capture, and MIDI, as well as the necessary buffers for data processing.
@ -555,6 +571,7 @@ static int tascam_alloc_urbs(struct tascam_card *tascam)
for (i = 0; i < NUM_PLAYBACK_URBS; i++) { for (i = 0; i < NUM_PLAYBACK_URBS; i++) {
struct urb *urb = usb_alloc_urb(PLAYBACK_URB_PACKETS, GFP_KERNEL); struct urb *urb = usb_alloc_urb(PLAYBACK_URB_PACKETS, GFP_KERNEL);
if (!urb) if (!urb)
goto error; goto error;
tascam->playback_urbs[i] = urb; tascam->playback_urbs[i] = urb;
@ -576,6 +593,7 @@ static int tascam_alloc_urbs(struct tascam_card *tascam)
for (i = 0; i < NUM_FEEDBACK_URBS; i++) { for (i = 0; i < NUM_FEEDBACK_URBS; i++) {
struct urb *f_urb = usb_alloc_urb(MAX_FEEDBACK_PACKETS, GFP_KERNEL); struct urb *f_urb = usb_alloc_urb(MAX_FEEDBACK_PACKETS, GFP_KERNEL);
if (!f_urb) if (!f_urb)
goto error; goto error;
tascam->feedback_urbs[i] = f_urb; tascam->feedback_urbs[i] = f_urb;
@ -596,6 +614,7 @@ static int tascam_alloc_urbs(struct tascam_card *tascam)
tascam->capture_urb_alloc_size = CAPTURE_URB_SIZE; tascam->capture_urb_alloc_size = CAPTURE_URB_SIZE;
for (i = 0; i < NUM_CAPTURE_URBS; i++) { for (i = 0; i < NUM_CAPTURE_URBS; i++) {
struct urb *c_urb = usb_alloc_urb(0, GFP_KERNEL); struct urb *c_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!c_urb) if (!c_urb)
goto error; goto error;
tascam->capture_urbs[i] = c_urb; tascam->capture_urbs[i] = c_urb;
@ -617,6 +636,7 @@ static int tascam_alloc_urbs(struct tascam_card *tascam)
/* MIDI URB and buffer allocation */ /* MIDI URB and buffer allocation */
for (i = 0; i < NUM_MIDI_IN_URBS; i++) { for (i = 0; i < NUM_MIDI_IN_URBS; i++) {
struct urb *m_urb = usb_alloc_urb(0, GFP_KERNEL); struct urb *m_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!m_urb) if (!m_urb)
goto error; goto error;
tascam->midi_in_urbs[i] = m_urb; tascam->midi_in_urbs[i] = m_urb;
@ -632,6 +652,7 @@ static int tascam_alloc_urbs(struct tascam_card *tascam)
for (i = 0; i < NUM_MIDI_OUT_URBS; i++) { for (i = 0; i < NUM_MIDI_OUT_URBS; i++) {
struct urb *m_urb = usb_alloc_urb(0, GFP_KERNEL); struct urb *m_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!m_urb) if (!m_urb)
goto error; goto error;
tascam->midi_out_urbs[i] = m_urb; tascam->midi_out_urbs[i] = m_urb;
@ -699,6 +720,7 @@ static int tascam_capture_open(struct snd_pcm_substream *substream)
static int tascam_playback_close(struct snd_pcm_substream *substream) static int tascam_playback_close(struct snd_pcm_substream *substream)
{ {
struct tascam_card *tascam = snd_pcm_substream_chip(substream); struct tascam_card *tascam = snd_pcm_substream_chip(substream);
tascam->playback_substream = NULL; tascam->playback_substream = NULL;
return 0; return 0;
@ -707,15 +729,16 @@ static int tascam_playback_close(struct snd_pcm_substream *substream)
static int tascam_capture_close(struct snd_pcm_substream *substream) static int tascam_capture_close(struct snd_pcm_substream *substream)
{ {
struct tascam_card *tascam = snd_pcm_substream_chip(substream); struct tascam_card *tascam = snd_pcm_substream_chip(substream);
tascam->capture_substream = NULL; tascam->capture_substream = NULL;
return 0; return 0;
} }
/** /**
* us144mkii_configure_device_for_rate - Send USB control messages to set sample rate. * us144mkii_configure_device_for_rate() - Set sample rate via USB control msgs
* @tascam: the tascam_card instance. * @tascam: the tascam_card instance
* @rate: the target sample rate (e.g., 44100, 96000). * @rate: the target sample rate (e.g., 44100, 96000)
* *
* This function sends a sequence of vendor-specific and UAC control messages * This function sends a sequence of vendor-specific and UAC control messages
* to configure the device hardware for the specified sample rate. * to configure the device hardware for the specified sample rate.
@ -728,18 +751,30 @@ static int us144mkii_configure_device_for_rate(struct tascam_card *tascam, int r
u8 *rate_payload_buf; u8 *rate_payload_buf;
u16 rate_vendor_wValue; u16 rate_vendor_wValue;
int err = 0; int err = 0;
const u8 *current_payload_src;
static const u8 payload_44100[] = {0x44, 0xac, 0x00}; static const u8 payload_44100[] = {0x44, 0xac, 0x00};
static const u8 payload_48000[] = {0x80, 0xbb, 0x00}; static const u8 payload_48000[] = {0x80, 0xbb, 0x00};
static const u8 payload_88200[] = {0x88, 0x58, 0x01}; static const u8 payload_88200[] = {0x88, 0x58, 0x01};
static const u8 payload_96000[] = {0x00, 0x77, 0x01}; static const u8 payload_96000[] = {0x00, 0x77, 0x01};
const u8 *current_payload_src;
switch (rate) { switch (rate) {
case 44100: current_payload_src = payload_44100; rate_vendor_wValue = REG_ADDR_RATE_44100; break; case 44100:
case 48000: current_payload_src = payload_48000; rate_vendor_wValue = REG_ADDR_RATE_48000; break; current_payload_src = payload_44100;
case 88200: current_payload_src = payload_88200; rate_vendor_wValue = REG_ADDR_RATE_88200; break; rate_vendor_wValue = REG_ADDR_RATE_44100;
case 96000: current_payload_src = payload_96000; rate_vendor_wValue = REG_ADDR_RATE_96000; break; break;
case 48000:
current_payload_src = payload_48000;
rate_vendor_wValue = REG_ADDR_RATE_48000;
break;
case 88200:
current_payload_src = payload_88200;
rate_vendor_wValue = REG_ADDR_RATE_88200;
break;
case 96000:
current_payload_src = payload_96000;
rate_vendor_wValue = REG_ADDR_RATE_96000;
break;
default: default:
dev_err(&dev->dev, "Unsupported sample rate %d for configuration\n", rate); dev_err(&dev->dev, "Unsupported sample rate %d for configuration\n", rate);
return -EINVAL; return -EINVAL;
@ -752,23 +787,32 @@ static int us144mkii_configure_device_for_rate(struct tascam_card *tascam, int r
dev_info(&dev->dev, "Configuring device for %d Hz\n", rate); dev_info(&dev->dev, "Configuring device for %d Hz\n", rate);
err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), VENDOR_REQ_MODE_CONTROL, RT_H2D_VENDOR_DEV, MODE_VAL_CONFIG, 0x0000, NULL, 0, USB_CTRL_TIMEOUT_MS); err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), VENDOR_REQ_MODE_CONTROL, RT_H2D_VENDOR_DEV, MODE_VAL_CONFIG, 0x0000, NULL, 0, USB_CTRL_TIMEOUT_MS);
if (err < 0) goto fail; if (err < 0)
goto fail;
err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, RT_H2D_CLASS_EP, UAC_SAMPLING_FREQ_CONTROL, EP_AUDIO_IN, rate_payload_buf, 3, USB_CTRL_TIMEOUT_MS); err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, RT_H2D_CLASS_EP, UAC_SAMPLING_FREQ_CONTROL, EP_AUDIO_IN, rate_payload_buf, 3, USB_CTRL_TIMEOUT_MS);
if (err < 0) goto fail; if (err < 0)
goto fail;
err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, RT_H2D_CLASS_EP, UAC_SAMPLING_FREQ_CONTROL, EP_AUDIO_OUT, rate_payload_buf, 3, USB_CTRL_TIMEOUT_MS); err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, RT_H2D_CLASS_EP, UAC_SAMPLING_FREQ_CONTROL, EP_AUDIO_OUT, rate_payload_buf, 3, USB_CTRL_TIMEOUT_MS);
if (err < 0) goto fail; if (err < 0)
goto fail;
err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV, REG_ADDR_UNKNOWN_0D, REG_VAL_ENABLE, NULL, 0, USB_CTRL_TIMEOUT_MS); err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV, REG_ADDR_UNKNOWN_0D, REG_VAL_ENABLE, NULL, 0, USB_CTRL_TIMEOUT_MS);
if (err < 0) goto fail; if (err < 0)
goto fail;
err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV, REG_ADDR_UNKNOWN_0E, REG_VAL_ENABLE, NULL, 0, USB_CTRL_TIMEOUT_MS); err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV, REG_ADDR_UNKNOWN_0E, REG_VAL_ENABLE, NULL, 0, USB_CTRL_TIMEOUT_MS);
if (err < 0) goto fail; if (err < 0)
goto fail;
err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV, REG_ADDR_UNKNOWN_0F, REG_VAL_ENABLE, NULL, 0, USB_CTRL_TIMEOUT_MS); err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV, REG_ADDR_UNKNOWN_0F, REG_VAL_ENABLE, NULL, 0, USB_CTRL_TIMEOUT_MS);
if (err < 0) goto fail; if (err < 0)
goto fail;
err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV, rate_vendor_wValue, REG_VAL_ENABLE, NULL, 0, USB_CTRL_TIMEOUT_MS); err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV, rate_vendor_wValue, REG_VAL_ENABLE, NULL, 0, USB_CTRL_TIMEOUT_MS);
if (err < 0) goto fail; if (err < 0)
goto fail;
err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV, REG_ADDR_UNKNOWN_11, REG_VAL_ENABLE, NULL, 0, USB_CTRL_TIMEOUT_MS); err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), VENDOR_REQ_REGISTER_WRITE, RT_H2D_VENDOR_DEV, REG_ADDR_UNKNOWN_11, REG_VAL_ENABLE, NULL, 0, USB_CTRL_TIMEOUT_MS);
if (err < 0) goto fail; if (err < 0)
goto fail;
err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), VENDOR_REQ_MODE_CONTROL, RT_H2D_VENDOR_DEV, MODE_VAL_STREAM_START, 0x0000, NULL, 0, USB_CTRL_TIMEOUT_MS); err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), VENDOR_REQ_MODE_CONTROL, RT_H2D_VENDOR_DEV, MODE_VAL_STREAM_START, 0x0000, NULL, 0, USB_CTRL_TIMEOUT_MS);
if (err < 0) goto fail; if (err < 0)
goto fail;
kfree(rate_payload_buf); kfree(rate_payload_buf);
return 0; return 0;
@ -794,19 +838,23 @@ static int tascam_pcm_hw_params(struct snd_pcm_substream *substream,
switch (rate) { switch (rate) {
case 44100: case 44100:
tascam->feedback_patterns = patterns_44khz; tascam->feedback_patterns = patterns_44khz;
tascam->feedback_base_value = 42; tascam->feedback_max_value = 46; tascam->feedback_base_value = 42;
tascam->feedback_max_value = 46;
break; break;
case 48000: case 48000:
tascam->feedback_patterns = patterns_48khz; tascam->feedback_patterns = patterns_48khz;
tascam->feedback_base_value = 46; tascam->feedback_max_value = 50; tascam->feedback_base_value = 46;
tascam->feedback_max_value = 50;
break; break;
case 88200: case 88200:
tascam->feedback_patterns = patterns_88khz; tascam->feedback_patterns = patterns_88khz;
tascam->feedback_base_value = 86; tascam->feedback_max_value = 90; tascam->feedback_base_value = 86;
tascam->feedback_max_value = 90;
break; break;
case 96000: case 96000:
tascam->feedback_patterns = patterns_96khz; tascam->feedback_patterns = patterns_96khz;
tascam->feedback_base_value = 94; tascam->feedback_max_value = 98; tascam->feedback_base_value = 94;
tascam->feedback_max_value = 98;
break; break;
default: default:
return -EINVAL; return -EINVAL;
@ -857,6 +905,7 @@ static int tascam_playback_prepare(struct snd_pcm_substream *substream)
for (i = 0; i < NUM_FEEDBACK_URBS; i++) { for (i = 0; i < NUM_FEEDBACK_URBS; i++) {
struct urb *f_urb = tascam->feedback_urbs[i]; struct urb *f_urb = tascam->feedback_urbs[i];
int j; int j;
f_urb->number_of_packets = feedback_packets; f_urb->number_of_packets = feedback_packets;
f_urb->transfer_buffer_length = feedback_packets * FEEDBACK_PACKET_SIZE; f_urb->transfer_buffer_length = feedback_packets * FEEDBACK_PACKET_SIZE;
for (j = 0; j < feedback_packets; j++) { for (j = 0; j < feedback_packets; j++) {
@ -870,6 +919,7 @@ static int tascam_playback_prepare(struct snd_pcm_substream *substream)
for (u = 0; u < NUM_PLAYBACK_URBS; u++) { for (u = 0; u < NUM_PLAYBACK_URBS; u++) {
struct urb *urb = tascam->playback_urbs[u]; struct urb *urb = tascam->playback_urbs[u];
memset(urb->transfer_buffer, 0, tascam->playback_urb_alloc_size); memset(urb->transfer_buffer, 0, tascam->playback_urb_alloc_size);
urb->transfer_buffer_length = total_bytes_in_urb; urb->transfer_buffer_length = total_bytes_in_urb;
urb->number_of_packets = PLAYBACK_URB_PACKETS; urb->number_of_packets = PLAYBACK_URB_PACKETS;
@ -1035,8 +1085,8 @@ static struct snd_pcm_ops tascam_capture_ops = {
}; };
/** /**
* playback_urb_complete - Completion handler for playback isochronous URBs. * playback_urb_complete() - Completion handler for playback isochronous URBs.
* @urb: the completed URB. * @urb: the completed URB
* *
* This function runs in interrupt context. It calculates the number of bytes * This function runs in interrupt context. It calculates the number of bytes
* to send in the next set of packets based on the feedback-driven clock, * to send in the next set of packets based on the feedback-driven clock,
@ -1102,6 +1152,7 @@ static void playback_urb_complete(struct urb *urb)
if (offset_frames + frames_to_copy > runtime->buffer_size) { if (offset_frames + frames_to_copy > runtime->buffer_size) {
size_t first_chunk_bytes = frames_to_bytes(runtime, runtime->buffer_size - offset_frames); size_t first_chunk_bytes = frames_to_bytes(runtime, runtime->buffer_size - offset_frames);
size_t second_chunk_bytes = total_bytes_for_urb - first_chunk_bytes; size_t second_chunk_bytes = total_bytes_for_urb - first_chunk_bytes;
memcpy(dst_buf, src_buf, first_chunk_bytes); memcpy(dst_buf, src_buf, first_chunk_bytes);
memcpy(dst_buf + first_chunk_bytes, runtime->dma_area, second_chunk_bytes); memcpy(dst_buf + first_chunk_bytes, runtime->dma_area, second_chunk_bytes);
} else { } else {
@ -1120,8 +1171,8 @@ static void playback_urb_complete(struct urb *urb)
} }
/** /**
* feedback_urb_complete - Completion handler for feedback isochronous URBs. * feedback_urb_complete() - Completion handler for feedback isochronous URBs.
* @urb: the completed URB. * @urb: the completed URB
* *
* This is the master clock for the driver. It runs in interrupt context. * This is the master clock for the driver. It runs in interrupt context.
* It reads the feedback value from the device, which indicates how many * It reads the feedback value from the device, which indicates how many
@ -1181,14 +1232,17 @@ static void feedback_urb_complete(struct urb *urb)
pattern = tascam->feedback_patterns[feedback_value - tascam->feedback_base_value]; pattern = tascam->feedback_patterns[feedback_value - tascam->feedback_base_value];
tascam->feedback_consecutive_errors = 0; tascam->feedback_consecutive_errors = 0;
int i; int i;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
unsigned int in_idx = (tascam->feedback_pattern_in_idx + i) % FEEDBACK_ACCUMULATOR_SIZE; unsigned int in_idx = (tascam->feedback_pattern_in_idx + i) % FEEDBACK_ACCUMULATOR_SIZE;
tascam->feedback_accumulator_pattern[in_idx] = pattern[i]; tascam->feedback_accumulator_pattern[in_idx] = pattern[i];
total_frames_in_urb += pattern[i]; total_frames_in_urb += pattern[i];
} }
} else { } else {
unsigned int nominal_frames = playback_rt->rate / 8000; unsigned int nominal_frames = playback_rt->rate / 8000;
int i; int i;
if (tascam->feedback_synced) { if (tascam->feedback_synced) {
tascam->feedback_consecutive_errors++; tascam->feedback_consecutive_errors++;
if (tascam->feedback_consecutive_errors > 10) { if (tascam->feedback_consecutive_errors > 10) {
@ -1199,6 +1253,7 @@ static void feedback_urb_complete(struct urb *urb)
} }
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
unsigned int in_idx = (tascam->feedback_pattern_in_idx + i) % FEEDBACK_ACCUMULATOR_SIZE; unsigned int in_idx = (tascam->feedback_pattern_in_idx + i) % FEEDBACK_ACCUMULATOR_SIZE;
tascam->feedback_accumulator_pattern[in_idx] = nominal_frames; tascam->feedback_accumulator_pattern[in_idx] = nominal_frames;
total_frames_in_urb += nominal_frames; total_frames_in_urb += nominal_frames;
} }
@ -1228,6 +1283,7 @@ static void feedback_urb_complete(struct urb *urb)
if (playback_rt->period_size > 0) { if (playback_rt->period_size > 0) {
u64 current_period = div_u64(tascam->playback_frames_consumed, playback_rt->period_size); u64 current_period = div_u64(tascam->playback_frames_consumed, playback_rt->period_size);
if (current_period > tascam->last_period_pos) { if (current_period > tascam->last_period_pos) {
tascam->last_period_pos = current_period; tascam->last_period_pos = current_period;
playback_period_elapsed = true; playback_period_elapsed = true;
@ -1236,6 +1292,7 @@ static void feedback_urb_complete(struct urb *urb)
if (atomic_read(&tascam->capture_active) && capture_rt && capture_rt->period_size > 0) { if (atomic_read(&tascam->capture_active) && capture_rt && capture_rt->period_size > 0) {
u64 current_capture_period = div_u64(tascam->capture_frames_processed, capture_rt->period_size); u64 current_capture_period = div_u64(tascam->capture_frames_processed, capture_rt->period_size);
if (current_capture_period > tascam->last_capture_period_pos) { if (current_capture_period > tascam->last_capture_period_pos) {
tascam->last_capture_period_pos = current_capture_period; tascam->last_capture_period_pos = current_capture_period;
capture_period_elapsed = true; capture_period_elapsed = true;
@ -1257,7 +1314,7 @@ unlock_and_continue:
} }
/** /**
* decode_tascam_capture_block - Decodes a raw 512-byte block from the device. * decode_tascam_capture_block() - Decodes a raw 512-byte block from the device.
* @src_block: Pointer to the 512-byte raw source block. * @src_block: Pointer to the 512-byte raw source block.
* @dst_block: Pointer to the destination buffer for decoded audio frames. * @dst_block: Pointer to the destination buffer for decoded audio frames.
* *
@ -1288,7 +1345,8 @@ static void decode_tascam_capture_block(const u8 *src_block, s32 *dst_block)
ch[3] = (ch[3] << 1) | ((byte2 >> 1) & 1); ch[3] = (ch[3] << 1) | ((byte2 >> 1) & 1);
} }
/* The result is a 24-bit sample. Shift left by 8 to align it to /*
* The result is a 24-bit sample. Shift left by 8 to align it to
* the most significant bits of a 32-bit integer (S32_LE format). * the most significant bits of a 32-bit integer (S32_LE format).
*/ */
p_dst_frame[0] = ch[0] << 8; p_dst_frame[0] = ch[0] << 8;
@ -1299,8 +1357,8 @@ static void decode_tascam_capture_block(const u8 *src_block, s32 *dst_block)
} }
/** /**
* tascam_capture_work_handler - Deferred work handler for processing capture data. * tascam_capture_work_handler() - Deferred work for processing capture data.
* @work: the work_struct instance. * @work: the work_struct instance
* *
* This function runs in a kernel thread context, not an IRQ context. It reads * This function runs in a kernel thread context, not an IRQ context. It reads
* raw data from the capture ring buffer, decodes it, applies routing, and * raw data from the capture ring buffer, decodes it, applies routing, and
@ -1338,6 +1396,7 @@ static void tascam_capture_work_handler(struct work_struct *work)
if (can_process) { if (can_process) {
size_t i; size_t i;
for (i = 0; i < RAW_BYTES_PER_DECODE_BLOCK; i++) for (i = 0; i < RAW_BYTES_PER_DECODE_BLOCK; i++)
raw_block[i] = tascam->capture_ring_buffer[(read_ptr + i) % CAPTURE_RING_BUFFER_SIZE]; raw_block[i] = tascam->capture_ring_buffer[(read_ptr + i) % CAPTURE_RING_BUFFER_SIZE];
tascam->capture_ring_buffer_read_ptr = (read_ptr + RAW_BYTES_PER_DECODE_BLOCK) % CAPTURE_RING_BUFFER_SIZE; tascam->capture_ring_buffer_read_ptr = (read_ptr + RAW_BYTES_PER_DECODE_BLOCK) % CAPTURE_RING_BUFFER_SIZE;
@ -1353,25 +1412,19 @@ static void tascam_capture_work_handler(struct work_struct *work)
spin_lock_irqsave(&tascam->lock, flags); spin_lock_irqsave(&tascam->lock, flags);
if (atomic_read(&tascam->capture_active)) { if (atomic_read(&tascam->capture_active)) {
int f; int f;
for (f = 0; f < FRAMES_PER_DECODE_BLOCK; ++f) { for (f = 0; f < FRAMES_PER_DECODE_BLOCK; ++f) {
// Get a pointer to the start of the current frame in the ALSA buffer
u8 *dst_frame_start = runtime->dma_area + frames_to_bytes(runtime, tascam->driver_capture_pos); u8 *dst_frame_start = runtime->dma_area + frames_to_bytes(runtime, tascam->driver_capture_pos);
// Get a pointer to the start of the current routed frame (which contains 4 s32 channels)
s32 *routed_frame_start = routed_block + (f * NUM_CHANNELS); s32 *routed_frame_start = routed_block + (f * NUM_CHANNELS);
int c; int c;
for (c = 0; c < NUM_CHANNELS; c++) { for (c = 0; c < NUM_CHANNELS; c++) {
// Pointer to the destination for the current channel (3 bytes)
u8 *dst_channel = dst_frame_start + (c * BYTES_PER_SAMPLE); u8 *dst_channel = dst_frame_start + (c * BYTES_PER_SAMPLE);
// Pointer to the source s32 for the current channel
s32 *src_channel_s32 = routed_frame_start + c; s32 *src_channel_s32 = routed_frame_start + c;
// The s32 sample is formatted as [0x00, LSB, Mid, MSB].
// We need to copy the 3 significant bytes, skipping the first 0x00 byte.
memcpy(dst_channel, ((char *)src_channel_s32) + 1, 3); memcpy(dst_channel, ((char *)src_channel_s32) + 1, 3);
} }
// Advance the driver's position in the ALSA buffer
tascam->driver_capture_pos = (tascam->driver_capture_pos + 1) % runtime->buffer_size; tascam->driver_capture_pos = (tascam->driver_capture_pos + 1) % runtime->buffer_size;
} }
} }
@ -1380,8 +1433,8 @@ static void tascam_capture_work_handler(struct work_struct *work)
} }
/** /**
* capture_urb_complete - Completion handler for capture bulk URBs. * capture_urb_complete() - Completion handler for capture bulk URBs.
* @urb: the completed URB. * @urb: the completed URB
* *
* This function runs in interrupt context. It copies the received raw data * This function runs in interrupt context. It copies the received raw data
* into an intermediate ring buffer and then schedules the workqueue to process * into an intermediate ring buffer and then schedules the workqueue to process
@ -1426,9 +1479,10 @@ static void capture_urb_complete(struct urb *urb)
/* --- ALSA RawMIDI Implementation --- */ /* --- ALSA RawMIDI Implementation --- */
/** /**
* tascam_midi_in_urb_complete * tascam_midi_in_urb_complete() - Completion handler for MIDI IN URBs
* @urb: The completed URB. * @urb: The completed URB.
* each 9-byte USB packet contains a variable-length MIDI message fragment. *
* Each 9-byte USB packet contains a variable-length MIDI message fragment.
* All 0xFD bytes are padding and must be stripped. * All 0xFD bytes are padding and must be stripped.
*/ */
static void tascam_midi_in_urb_complete(struct urb *urb) static void tascam_midi_in_urb_complete(struct urb *urb)
@ -1438,7 +1492,7 @@ static void tascam_midi_in_urb_complete(struct urb *urb)
if (urb->status) { if (urb->status) {
if (urb->status != -ENOENT && urb->status != -ECONNRESET && urb->status != -ESHUTDOWN) if (urb->status != -ENOENT && urb->status != -ECONNRESET && urb->status != -ESHUTDOWN)
dev_err(tascam->card->dev, "MIDI IN URB failed: status %d\n", urb->status); dev_err_ratelimited(tascam->card->dev, "MIDI IN URB failed: status %d\n", urb->status);
return; return;
} }
@ -1485,11 +1539,10 @@ static void tascam_midi_in_urb_complete(struct urb *urb)
stripped_len--; stripped_len--;
} }
if (stripped_len > 0) { if (stripped_len > 0)
snd_rawmidi_receive(tascam->midi_in_substream, stripped_buf, stripped_len); snd_rawmidi_receive(tascam->midi_in_substream, stripped_buf, stripped_len);
} }
} }
}
ret = usb_submit_urb(urb, GFP_ATOMIC); ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret < 0) if (ret < 0)
@ -1499,6 +1552,7 @@ static void tascam_midi_in_urb_complete(struct urb *urb)
static int tascam_midi_in_open(struct snd_rawmidi_substream *substream) static int tascam_midi_in_open(struct snd_rawmidi_substream *substream)
{ {
struct tascam_card *tascam = substream->rmidi->private_data; struct tascam_card *tascam = substream->rmidi->private_data;
tascam->midi_in_substream = substream; tascam->midi_in_substream = substream;
return 0; return 0;
} }
@ -1539,7 +1593,7 @@ static struct snd_rawmidi_ops tascam_midi_in_ops = {
}; };
/** /**
* tascam_midi_out_urb_complete - Completion handler for MIDI OUT bulk URB. * tascam_midi_out_urb_complete() - Completion handler for MIDI OUT bulk URB.
* @urb: The completed URB. * @urb: The completed URB.
* *
* This function runs in interrupt context. It marks the output URB as no * This function runs in interrupt context. It marks the output URB as no
@ -1582,9 +1636,10 @@ static void tascam_midi_out_urb_complete(struct urb *urb)
} }
/** /**
* tascam_midi_out_work_handler * tascam_midi_out_work_handler() - Deferred work for sending MIDI data
* @work: The work_struct instance. * @work: The work_struct instance.
* output protocol: take the raw MIDI *
* This function handles the proprietary output protocol: take the raw MIDI
* message bytes from the application, place them at the start of a 9-byte * message bytes from the application, place them at the start of a 9-byte
* buffer, pad the rest with 0xFD, and add a terminator byte (0x00). * buffer, pad the rest with 0xFD, and add a terminator byte (0x00).
* This function pulls as many bytes as will fit into one packet from the * This function pulls as many bytes as will fit into one packet from the
@ -1659,6 +1714,7 @@ start_work:
static int tascam_midi_out_open(struct snd_rawmidi_substream *substream) static int tascam_midi_out_open(struct snd_rawmidi_substream *substream)
{ {
struct tascam_card *tascam = substream->rmidi->private_data; struct tascam_card *tascam = substream->rmidi->private_data;
tascam->midi_out_substream = substream; tascam->midi_out_substream = substream;
/* Initialize the running status state for the packet packer. */ /* Initialize the running status state for the packet packer. */
tascam->midi_running_status = 0; tascam->midi_running_status = 0;
@ -1700,7 +1756,7 @@ static struct snd_rawmidi_ops tascam_midi_out_ops = {
}; };
/** /**
* tascam_create_midi - Create and initialize the ALSA rawmidi device. * tascam_create_midi() - Create and initialize the ALSA rawmidi device.
* @tascam: The driver instance. * @tascam: The driver instance.
* *
* Return: 0 on success, or a negative error code on failure. * Return: 0 on success, or a negative error code on failure.
@ -1732,13 +1788,17 @@ static int tascam_create_pcm(struct snd_pcm *pcm)
int err; int err;
err = snd_ctl_add(tascam->card, snd_ctl_new1(&tascam_line_out_control, tascam)); err = snd_ctl_add(tascam->card, snd_ctl_new1(&tascam_line_out_control, tascam));
if (err < 0) return err; if (err < 0)
return err;
err = snd_ctl_add(tascam->card, snd_ctl_new1(&tascam_digital_out_control, tascam)); err = snd_ctl_add(tascam->card, snd_ctl_new1(&tascam_digital_out_control, tascam));
if (err < 0) return err; if (err < 0)
return err;
err = snd_ctl_add(tascam->card, snd_ctl_new1(&tascam_capture_12_control, tascam)); err = snd_ctl_add(tascam->card, snd_ctl_new1(&tascam_capture_12_control, tascam));
if (err < 0) return err; if (err < 0)
return err;
err = snd_ctl_add(tascam->card, snd_ctl_new1(&tascam_capture_34_control, tascam)); err = snd_ctl_add(tascam->card, snd_ctl_new1(&tascam_capture_34_control, tascam));
if (err < 0) return err; if (err < 0)
return err;
err = snd_ctl_add(tascam->card, snd_ctl_new1(&tascam_samplerate_control, tascam)); err = snd_ctl_add(tascam->card, snd_ctl_new1(&tascam_samplerate_control, tascam));
if (err < 0) if (err < 0)
@ -1756,6 +1816,7 @@ static int tascam_create_pcm(struct snd_pcm *pcm)
static void tascam_card_private_free(struct snd_card *card) static void tascam_card_private_free(struct snd_card *card)
{ {
struct tascam_card *tascam = card->private_data; struct tascam_card *tascam = card->private_data;
if (tascam && tascam->dev) { if (tascam && tascam->dev) {
usb_put_dev(tascam->dev); usb_put_dev(tascam->dev);
tascam->dev = NULL; tascam->dev = NULL;
@ -1775,11 +1836,13 @@ static int tascam_suspend(struct usb_interface *intf, pm_message_t message)
if (atomic_read(&tascam->midi_in_active)) { if (atomic_read(&tascam->midi_in_active)) {
int i; int i;
for (i = 0; i < NUM_MIDI_IN_URBS; i++) for (i = 0; i < NUM_MIDI_IN_URBS; i++)
usb_kill_urb(tascam->midi_in_urbs[i]); usb_kill_urb(tascam->midi_in_urbs[i]);
} }
if (atomic_read(&tascam->midi_out_active)) { if (atomic_read(&tascam->midi_out_active)) {
int i; int i;
for (i = 0; i < NUM_MIDI_OUT_URBS; i++) for (i = 0; i < NUM_MIDI_OUT_URBS; i++)
usb_kill_urb(tascam->midi_out_urbs[i]); usb_kill_urb(tascam->midi_out_urbs[i]);
} }
@ -1823,6 +1886,7 @@ static int tascam_resume(struct usb_interface *intf)
/* Resume MIDI streams if they were active */ /* Resume MIDI streams if they were active */
if (atomic_read(&tascam->midi_in_active)) { if (atomic_read(&tascam->midi_in_active)) {
int i; int i;
for (i = 0; i < NUM_MIDI_IN_URBS; i++) { for (i = 0; i < NUM_MIDI_IN_URBS; i++) {
err = usb_submit_urb(tascam->midi_in_urbs[i], GFP_KERNEL); err = usb_submit_urb(tascam->midi_in_urbs[i], GFP_KERNEL);
if (err < 0) if (err < 0)
@ -1836,9 +1900,9 @@ static int tascam_resume(struct usb_interface *intf)
} }
/** /**
* tascam_probe - Entry point for when the USB device is detected. * tascam_probe() - Entry point for when the USB device is detected.
* @intf: the USB interface that was matched. * @intf: the USB interface that was matched
* @usb_id: the matching USB device ID. * @usb_id: the matching USB device ID
* *
* This function is called by the USB core when a device matching the driver's * This function is called by the USB core when a device matching the driver's
* ID table is connected. It allocates the sound card, initializes the driver * ID table is connected. It allocates the sound card, initializes the driver
@ -1941,7 +2005,6 @@ static int tascam_probe(struct usb_interface *intf, const struct usb_device_id *
} }
kfree(handshake_buf); kfree(handshake_buf);
/* /*
* Allocate all URBs now that the device is initialized. * Allocate all URBs now that the device is initialized.
*/ */
@ -1986,8 +2049,8 @@ free_card_obj:
} }
/** /**
* tascam_disconnect - Entry point for when the USB device is disconnected. * tascam_disconnect() - Entry point for when the USB device is disconnected.
* @intf: the USB interface being disconnected. * @intf: the USB interface being disconnected
* *
* This function is called by the USB core when the device is removed. It * This function is called by the USB core when the device is removed. It
* cancels any pending work, disconnects the sound card from ALSA, releases * cancels any pending work, disconnects the sound card from ALSA, releases