conform to linux kernel code styles
This commit is contained in:
parent
42cb351089
commit
8f78ebe3a3
323
us144mkii.c
323
us144mkii.c
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// Copyright (c) 2025 serifpersia <ramiserifpersia@gmail.com>
|
||||
/*
|
||||
* ALSA Driver for TASCAM US-144MKII Audio Interface
|
||||
|
|
@ -18,7 +18,7 @@ MODULE_DESCRIPTION("ALSA Driver for TASCAM US-144MKII");
|
|||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
#define DRIVER_NAME "us144mkii"
|
||||
#define DRIVER_VERSION "1.6"
|
||||
#define DRIVER_VERSION "1.6.1"
|
||||
|
||||
/* --- Module Parameters --- */
|
||||
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
|
||||
|
|
@ -32,59 +32,59 @@ static int dev_idx;
|
|||
|
||||
/* --- USB Endpoints (Alternate Setting 1) --- */
|
||||
#define EP_PLAYBACK_FEEDBACK 0x81
|
||||
#define EP_AUDIO_OUT 0x02
|
||||
#define EP_MIDI_IN 0x83
|
||||
#define EP_MIDI_OUT 0x04
|
||||
#define EP_AUDIO_IN 0x86
|
||||
#define EP_AUDIO_OUT 0x02
|
||||
#define EP_MIDI_IN 0x83
|
||||
#define EP_MIDI_OUT 0x04
|
||||
#define EP_AUDIO_IN 0x86
|
||||
|
||||
/* --- USB Control Message Protocol --- */
|
||||
#define RT_H2D_CLASS_EP (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT)
|
||||
#define RT_D2H_CLASS_EP (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT)
|
||||
#define RT_D2H_CLASS_EP (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT)
|
||||
#define RT_H2D_VENDOR_DEV (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
|
||||
#define RT_D2H_VENDOR_DEV (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
|
||||
#define UAC_SET_CUR 0x01
|
||||
#define UAC_GET_CUR 0x81
|
||||
#define UAC_SAMPLING_FREQ_CONTROL 0x0100
|
||||
#define UAC_SET_CUR 0x01
|
||||
#define UAC_GET_CUR 0x81
|
||||
#define UAC_SAMPLING_FREQ_CONTROL 0x0100
|
||||
#define VENDOR_REQ_REGISTER_WRITE 0x41
|
||||
#define VENDOR_REQ_MODE_CONTROL 0x49
|
||||
#define MODE_VAL_HANDSHAKE_READ 0x0000
|
||||
#define MODE_VAL_CONFIG 0x0010
|
||||
#define MODE_VAL_CONFIG 0x0010
|
||||
#define MODE_VAL_STREAM_START 0x0030
|
||||
#define HANDSHAKE_SUCCESS_VAL 0x12
|
||||
#define REG_ADDR_UNKNOWN_0D 0x0d04
|
||||
#define REG_ADDR_UNKNOWN_0E 0x0e00
|
||||
#define REG_ADDR_UNKNOWN_0F 0x0f00
|
||||
#define REG_ADDR_RATE_44100 0x1000
|
||||
#define REG_ADDR_RATE_48000 0x1002
|
||||
#define REG_ADDR_RATE_88200 0x1008
|
||||
#define REG_ADDR_RATE_96000 0x100a
|
||||
#define REG_ADDR_UNKNOWN_11 0x110b
|
||||
#define REG_VAL_ENABLE 0x0101
|
||||
#define REG_ADDR_UNKNOWN_0D 0x0d04
|
||||
#define REG_ADDR_UNKNOWN_0E 0x0e00
|
||||
#define REG_ADDR_UNKNOWN_0F 0x0f00
|
||||
#define REG_ADDR_RATE_44100 0x1000
|
||||
#define REG_ADDR_RATE_48000 0x1002
|
||||
#define REG_ADDR_RATE_88200 0x1008
|
||||
#define REG_ADDR_RATE_96000 0x100a
|
||||
#define REG_ADDR_UNKNOWN_11 0x110b
|
||||
#define REG_VAL_ENABLE 0x0101
|
||||
|
||||
/* --- URB Configuration --- */
|
||||
#define NUM_PLAYBACK_URBS 8
|
||||
#define NUM_PLAYBACK_URBS 8
|
||||
#define PLAYBACK_URB_PACKETS 4
|
||||
#define NUM_FEEDBACK_URBS 4
|
||||
#define NUM_FEEDBACK_URBS 4
|
||||
#define MAX_FEEDBACK_PACKETS 5
|
||||
#define FEEDBACK_PACKET_SIZE 3
|
||||
#define NUM_CAPTURE_URBS 8
|
||||
#define CAPTURE_URB_SIZE 512
|
||||
#define NUM_CAPTURE_URBS 8
|
||||
#define CAPTURE_URB_SIZE 512
|
||||
#define CAPTURE_RING_BUFFER_SIZE (CAPTURE_URB_SIZE * NUM_CAPTURE_URBS * 4)
|
||||
#define NUM_MIDI_IN_URBS 4
|
||||
#define MIDI_IN_BUF_SIZE 64
|
||||
#define MIDI_OUT_BUF_SIZE 64
|
||||
#define NUM_MIDI_OUT_URBS 4
|
||||
#define USB_CTRL_TIMEOUT_MS 1000
|
||||
#define NUM_MIDI_IN_URBS 4
|
||||
#define MIDI_IN_BUF_SIZE 64
|
||||
#define MIDI_OUT_BUF_SIZE 64
|
||||
#define NUM_MIDI_OUT_URBS 4
|
||||
#define USB_CTRL_TIMEOUT_MS 1000
|
||||
|
||||
/* --- Audio Format Configuration --- */
|
||||
#define BYTES_PER_SAMPLE 3
|
||||
#define NUM_CHANNELS 4
|
||||
#define BYTES_PER_FRAME (NUM_CHANNELS * BYTES_PER_SAMPLE)
|
||||
#define FEEDBACK_ACCUMULATOR_SIZE 128
|
||||
#define BYTES_PER_SAMPLE 3
|
||||
#define NUM_CHANNELS 4
|
||||
#define BYTES_PER_FRAME (NUM_CHANNELS * BYTES_PER_SAMPLE)
|
||||
#define FEEDBACK_ACCUMULATOR_SIZE 128
|
||||
|
||||
/* --- Capture Decoding Defines --- */
|
||||
#define DECODED_CHANNELS_PER_FRAME 4
|
||||
#define DECODED_SAMPLE_SIZE 4
|
||||
#define DECODED_SAMPLE_SIZE 4
|
||||
#define FRAMES_PER_DECODE_BLOCK 8
|
||||
#define RAW_BYTES_PER_DECODE_BLOCK 512
|
||||
|
||||
|
|
@ -119,7 +119,7 @@ struct tascam_card {
|
|||
u64 last_capture_period_pos;
|
||||
u8 *capture_ring_buffer;
|
||||
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;
|
||||
s32 *capture_decode_dst_block;
|
||||
s32 *capture_routing_buffer;
|
||||
|
|
@ -179,9 +179,9 @@ static int tascam_resume(struct usb_interface *intf);
|
|||
|
||||
/* --- Sysfs Attribute for Driver Version --- */
|
||||
static ssize_t driver_version_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sysfs_emit(buf, "%s\n", DRIVER_VERSION);
|
||||
return sysfs_emit(buf, "%s\n", DRIVER_VERSION);
|
||||
}
|
||||
static DEVICE_ATTR_RO(driver_version);
|
||||
|
||||
|
|
@ -196,13 +196,16 @@ static int tascam_playback_source_info(struct snd_kcontrol *kcontrol, struct snd
|
|||
uinfo->value.enumerated.items = 2;
|
||||
if (uinfo->value.enumerated.item >= 2)
|
||||
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;
|
||||
}
|
||||
|
||||
static int tascam_line_out_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct tascam_card *tascam = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = tascam->line_out_source;
|
||||
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)
|
||||
{
|
||||
struct tascam_card *tascam = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
if (ucontrol->value.enumerated.item[0] > 1)
|
||||
return -EINVAL;
|
||||
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)
|
||||
{
|
||||
struct tascam_card *tascam = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = tascam->digital_out_source;
|
||||
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)
|
||||
{
|
||||
struct tascam_card *tascam = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
if (ucontrol->value.enumerated.item[0] > 1)
|
||||
return -EINVAL;
|
||||
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;
|
||||
if (uinfo->value.enumerated.item >= 2)
|
||||
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;
|
||||
}
|
||||
|
||||
static int tascam_capture_12_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct tascam_card *tascam = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = tascam->capture_12_source;
|
||||
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)
|
||||
{
|
||||
struct tascam_card *tascam = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
if (ucontrol->value.enumerated.item[0] > 1)
|
||||
return -EINVAL;
|
||||
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)
|
||||
{
|
||||
struct tascam_card *tascam = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = tascam->capture_34_source;
|
||||
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)
|
||||
{
|
||||
struct tascam_card *tascam = snd_kcontrol_chip(kcontrol);
|
||||
|
||||
if (ucontrol->value.enumerated.item[0] > 1)
|
||||
return -EINVAL;
|
||||
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.
|
||||
* @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.
|
||||
*/
|
||||
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;
|
||||
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_digital = dst_line + (2 * BYTES_PER_SAMPLE);
|
||||
|
||||
// LINE OUTPUTS (ch1/2 on device)
|
||||
if (tascam->line_out_source == 0) // "ch1 and ch2"
|
||||
/* LINE OUTPUTS (ch1/2 on device) */
|
||||
if (tascam->line_out_source == 0) /* "ch1 and ch2" */
|
||||
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);
|
||||
|
||||
// DIGITAL OUTPUTS (ch3/4 on device)
|
||||
if (tascam->digital_out_source == 0) // "ch1 and ch2"
|
||||
/* DIGITAL OUTPUTS (ch3/4 on device) */
|
||||
if (tascam->digital_out_source == 0) /* "ch1 and ch2" */
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* process_capture_routing_us144mkii
|
||||
* process_capture_routing_us144mkii() - Apply capture routing matrix
|
||||
* @tascam: The driver instance.
|
||||
* @decoded_block: Buffer containing 4 channels of S32LE decoded audio from device.
|
||||
* @routed_block: Buffer to be filled with 4 channels of S32LE audio for ALSA.
|
||||
* @decoded_block: Buffer containing 4 channels of S32LE decoded audio.
|
||||
* @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;
|
||||
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);
|
||||
dst_frame = routed_block + (f * DECODED_CHANNELS_PER_FRAME);
|
||||
|
||||
// ch1 and ch2 Source
|
||||
if (tascam->capture_12_source == 0) { // analog inputs
|
||||
dst_frame[0] = src_frame[0]; // Analog L
|
||||
dst_frame[1] = src_frame[1]; // Analog R
|
||||
} else { // digital inputs
|
||||
dst_frame[0] = src_frame[2]; // Digital L
|
||||
dst_frame[1] = src_frame[3]; // Digital R
|
||||
/* ch1 and ch2 Source */
|
||||
if (tascam->capture_12_source == 0) { /* analog inputs */
|
||||
dst_frame[0] = src_frame[0]; /* Analog L */
|
||||
dst_frame[1] = src_frame[1]; /* Analog R */
|
||||
} else { /* digital inputs */
|
||||
dst_frame[0] = src_frame[2]; /* Digital L */
|
||||
dst_frame[1] = src_frame[3]; /* Digital R */
|
||||
}
|
||||
|
||||
// ch3 and ch4 Source
|
||||
if (tascam->capture_34_source == 0) { // analog inputs
|
||||
dst_frame[2] = src_frame[0]; // Analog L (Duplicate)
|
||||
dst_frame[3] = src_frame[1]; // Analog R (Duplicate)
|
||||
} else { // digital inputs
|
||||
dst_frame[2] = src_frame[2]; // Digital L
|
||||
dst_frame[3] = src_frame[3]; // Digital R
|
||||
/* ch3 and ch4 Source */
|
||||
if (tascam->capture_34_source == 0) { /* analog inputs */
|
||||
dst_frame[2] = src_frame[0]; /* Analog L (Duplicate) */
|
||||
dst_frame[3] = src_frame[1]; /* Analog R (Duplicate) */
|
||||
} else { /* digital inputs */
|
||||
dst_frame[2] = src_frame[2]; /* Digital L */
|
||||
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: the tascam_card instance.
|
||||
* tascam_free_urbs() - Free all allocated URBs and associated buffers.
|
||||
* @tascam: the tascam_card instance
|
||||
*
|
||||
* This function kills, unlinks, and frees all playback, feedback, 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: the tascam_card instance.
|
||||
* tascam_alloc_urbs() - Allocate all URBs and associated buffers.
|
||||
* @tascam: the tascam_card instance
|
||||
*
|
||||
* This function allocates and initializes all URBs for playback, feedback,
|
||||
* 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++) {
|
||||
struct urb *urb = usb_alloc_urb(PLAYBACK_URB_PACKETS, GFP_KERNEL);
|
||||
|
||||
if (!urb)
|
||||
goto error;
|
||||
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++) {
|
||||
struct urb *f_urb = usb_alloc_urb(MAX_FEEDBACK_PACKETS, GFP_KERNEL);
|
||||
|
||||
if (!f_urb)
|
||||
goto error;
|
||||
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;
|
||||
for (i = 0; i < NUM_CAPTURE_URBS; i++) {
|
||||
struct urb *c_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
|
||||
if (!c_urb)
|
||||
goto error;
|
||||
tascam->capture_urbs[i] = c_urb;
|
||||
|
|
@ -617,6 +636,7 @@ static int tascam_alloc_urbs(struct tascam_card *tascam)
|
|||
/* MIDI URB and buffer allocation */
|
||||
for (i = 0; i < NUM_MIDI_IN_URBS; i++) {
|
||||
struct urb *m_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
|
||||
if (!m_urb)
|
||||
goto error;
|
||||
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++) {
|
||||
struct urb *m_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
|
||||
if (!m_urb)
|
||||
goto error;
|
||||
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)
|
||||
{
|
||||
struct tascam_card *tascam = snd_pcm_substream_chip(substream);
|
||||
|
||||
tascam->playback_substream = NULL;
|
||||
|
||||
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)
|
||||
{
|
||||
struct tascam_card *tascam = snd_pcm_substream_chip(substream);
|
||||
|
||||
tascam->capture_substream = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* us144mkii_configure_device_for_rate - Send USB control messages to set sample rate.
|
||||
* @tascam: the tascam_card instance.
|
||||
* @rate: the target sample rate (e.g., 44100, 96000).
|
||||
* us144mkii_configure_device_for_rate() - Set sample rate via USB control msgs
|
||||
* @tascam: the tascam_card instance
|
||||
* @rate: the target sample rate (e.g., 44100, 96000)
|
||||
*
|
||||
* This function sends a sequence of vendor-specific and UAC control messages
|
||||
* 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;
|
||||
u16 rate_vendor_wValue;
|
||||
int err = 0;
|
||||
const u8 *current_payload_src;
|
||||
|
||||
static const u8 payload_44100[] = {0x44, 0xac, 0x00};
|
||||
static const u8 payload_48000[] = {0x80, 0xbb, 0x00};
|
||||
static const u8 payload_88200[] = {0x88, 0x58, 0x01};
|
||||
static const u8 payload_96000[] = {0x00, 0x77, 0x01};
|
||||
const u8 *current_payload_src;
|
||||
|
||||
switch (rate) {
|
||||
case 44100: current_payload_src = payload_44100; rate_vendor_wValue = REG_ADDR_RATE_44100; 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;
|
||||
case 44100:
|
||||
current_payload_src = payload_44100;
|
||||
rate_vendor_wValue = REG_ADDR_RATE_44100;
|
||||
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:
|
||||
dev_err(&dev->dev, "Unsupported sample rate %d for configuration\n", rate);
|
||||
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);
|
||||
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
if (err < 0) goto fail;
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
|
||||
kfree(rate_payload_buf);
|
||||
return 0;
|
||||
|
|
@ -794,19 +838,23 @@ static int tascam_pcm_hw_params(struct snd_pcm_substream *substream,
|
|||
switch (rate) {
|
||||
case 44100:
|
||||
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;
|
||||
case 48000:
|
||||
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;
|
||||
case 88200:
|
||||
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;
|
||||
case 96000:
|
||||
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;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
|
@ -857,6 +905,7 @@ static int tascam_playback_prepare(struct snd_pcm_substream *substream)
|
|||
for (i = 0; i < NUM_FEEDBACK_URBS; i++) {
|
||||
struct urb *f_urb = tascam->feedback_urbs[i];
|
||||
int j;
|
||||
|
||||
f_urb->number_of_packets = feedback_packets;
|
||||
f_urb->transfer_buffer_length = feedback_packets * FEEDBACK_PACKET_SIZE;
|
||||
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++) {
|
||||
struct urb *urb = tascam->playback_urbs[u];
|
||||
|
||||
memset(urb->transfer_buffer, 0, tascam->playback_urb_alloc_size);
|
||||
urb->transfer_buffer_length = total_bytes_in_urb;
|
||||
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.
|
||||
* @urb: the completed URB.
|
||||
* playback_urb_complete() - Completion handler for playback isochronous URBs.
|
||||
* @urb: the completed URB
|
||||
*
|
||||
* 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,
|
||||
|
|
@ -1102,6 +1152,7 @@ static void playback_urb_complete(struct urb *urb)
|
|||
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 second_chunk_bytes = total_bytes_for_urb - first_chunk_bytes;
|
||||
|
||||
memcpy(dst_buf, src_buf, first_chunk_bytes);
|
||||
memcpy(dst_buf + first_chunk_bytes, runtime->dma_area, second_chunk_bytes);
|
||||
} else {
|
||||
|
|
@ -1120,8 +1171,8 @@ static void playback_urb_complete(struct urb *urb)
|
|||
}
|
||||
|
||||
/**
|
||||
* feedback_urb_complete - Completion handler for feedback isochronous URBs.
|
||||
* @urb: the completed URB.
|
||||
* feedback_urb_complete() - Completion handler for feedback isochronous URBs.
|
||||
* @urb: the completed URB
|
||||
*
|
||||
* 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
|
||||
|
|
@ -1181,14 +1232,17 @@ static void feedback_urb_complete(struct urb *urb)
|
|||
pattern = tascam->feedback_patterns[feedback_value - tascam->feedback_base_value];
|
||||
tascam->feedback_consecutive_errors = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
unsigned int in_idx = (tascam->feedback_pattern_in_idx + i) % FEEDBACK_ACCUMULATOR_SIZE;
|
||||
|
||||
tascam->feedback_accumulator_pattern[in_idx] = pattern[i];
|
||||
total_frames_in_urb += pattern[i];
|
||||
}
|
||||
} else {
|
||||
unsigned int nominal_frames = playback_rt->rate / 8000;
|
||||
int i;
|
||||
|
||||
if (tascam->feedback_synced) {
|
||||
tascam->feedback_consecutive_errors++;
|
||||
if (tascam->feedback_consecutive_errors > 10) {
|
||||
|
|
@ -1199,6 +1253,7 @@ static void feedback_urb_complete(struct urb *urb)
|
|||
}
|
||||
for (i = 0; i < 8; i++) {
|
||||
unsigned int in_idx = (tascam->feedback_pattern_in_idx + i) % FEEDBACK_ACCUMULATOR_SIZE;
|
||||
|
||||
tascam->feedback_accumulator_pattern[in_idx] = 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) {
|
||||
u64 current_period = div_u64(tascam->playback_frames_consumed, playback_rt->period_size);
|
||||
|
||||
if (current_period > tascam->last_period_pos) {
|
||||
tascam->last_period_pos = current_period;
|
||||
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) {
|
||||
u64 current_capture_period = div_u64(tascam->capture_frames_processed, capture_rt->period_size);
|
||||
|
||||
if (current_capture_period > tascam->last_capture_period_pos) {
|
||||
tascam->last_capture_period_pos = current_capture_period;
|
||||
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.
|
||||
* @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);
|
||||
}
|
||||
|
||||
/* 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).
|
||||
*/
|
||||
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.
|
||||
* @work: the work_struct instance.
|
||||
* tascam_capture_work_handler() - Deferred work for processing capture data.
|
||||
* @work: the work_struct instance
|
||||
*
|
||||
* 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
|
||||
|
|
@ -1338,6 +1396,7 @@ static void tascam_capture_work_handler(struct work_struct *work)
|
|||
|
||||
if (can_process) {
|
||||
size_t 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];
|
||||
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);
|
||||
if (atomic_read(&tascam->capture_active)) {
|
||||
int 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);
|
||||
// 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);
|
||||
int 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);
|
||||
// Pointer to the source s32 for the current channel
|
||||
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);
|
||||
}
|
||||
|
||||
// Advance the driver's position in the ALSA buffer
|
||||
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.
|
||||
* @urb: the completed URB.
|
||||
* capture_urb_complete() - Completion handler for capture bulk URBs.
|
||||
* @urb: the completed URB
|
||||
*
|
||||
* This function runs in interrupt context. It copies the received raw data
|
||||
* 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 --- */
|
||||
|
||||
/**
|
||||
* tascam_midi_in_urb_complete
|
||||
* tascam_midi_in_urb_complete() - Completion handler for MIDI IN URBs
|
||||
* @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.
|
||||
*/
|
||||
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 != -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;
|
||||
}
|
||||
|
||||
|
|
@ -1485,9 +1539,8 @@ static void tascam_midi_in_urb_complete(struct urb *urb)
|
|||
stripped_len--;
|
||||
}
|
||||
|
||||
if (stripped_len > 0) {
|
||||
if (stripped_len > 0)
|
||||
snd_rawmidi_receive(tascam->midi_in_substream, stripped_buf, stripped_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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)
|
||||
{
|
||||
struct tascam_card *tascam = substream->rmidi->private_data;
|
||||
|
||||
tascam->midi_in_substream = substream;
|
||||
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.
|
||||
*
|
||||
* 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.
|
||||
* 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
|
||||
* 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
|
||||
|
|
@ -1659,6 +1714,7 @@ start_work:
|
|||
static int tascam_midi_out_open(struct snd_rawmidi_substream *substream)
|
||||
{
|
||||
struct tascam_card *tascam = substream->rmidi->private_data;
|
||||
|
||||
tascam->midi_out_substream = substream;
|
||||
/* Initialize the running status state for the packet packer. */
|
||||
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.
|
||||
*
|
||||
* 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;
|
||||
|
||||
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));
|
||||
if (err < 0) return err;
|
||||
if (err < 0)
|
||||
return err;
|
||||
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));
|
||||
if (err < 0) return err;
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = snd_ctl_add(tascam->card, snd_ctl_new1(&tascam_samplerate_control, tascam));
|
||||
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)
|
||||
{
|
||||
struct tascam_card *tascam = card->private_data;
|
||||
|
||||
if (tascam && tascam->dev) {
|
||||
usb_put_dev(tascam->dev);
|
||||
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)) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_MIDI_IN_URBS; i++)
|
||||
usb_kill_urb(tascam->midi_in_urbs[i]);
|
||||
}
|
||||
if (atomic_read(&tascam->midi_out_active)) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_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 */
|
||||
if (atomic_read(&tascam->midi_in_active)) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_MIDI_IN_URBS; i++) {
|
||||
err = usb_submit_urb(tascam->midi_in_urbs[i], GFP_KERNEL);
|
||||
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.
|
||||
* @intf: the USB interface that was matched.
|
||||
* @usb_id: the matching USB device ID.
|
||||
* tascam_probe() - Entry point for when the USB device is detected.
|
||||
* @intf: the USB interface that was matched
|
||||
* @usb_id: the matching USB device ID
|
||||
*
|
||||
* 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
|
||||
|
|
@ -1941,10 +2005,9 @@ static int tascam_probe(struct usb_interface *intf, const struct usb_device_id *
|
|||
}
|
||||
kfree(handshake_buf);
|
||||
|
||||
|
||||
/*
|
||||
* Allocate all URBs now that the device is initialized.
|
||||
*/
|
||||
*/
|
||||
err = tascam_alloc_urbs(tascam);
|
||||
if (err < 0)
|
||||
goto release_iface1_and_free_card;
|
||||
|
|
@ -1986,8 +2049,8 @@ free_card_obj:
|
|||
}
|
||||
|
||||
/**
|
||||
* tascam_disconnect - Entry point for when the USB device is disconnected.
|
||||
* @intf: the USB interface being disconnected.
|
||||
* tascam_disconnect() - Entry point for when the USB device is disconnected.
|
||||
* @intf: the USB interface being disconnected
|
||||
*
|
||||
* 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
|
||||
|
|
@ -2012,8 +2075,8 @@ static void tascam_disconnect(struct usb_interface *intf)
|
|||
cancel_work_sync(&tascam->midi_out_work);
|
||||
|
||||
/*
|
||||
* Free all URBs before freeing the card.
|
||||
*/
|
||||
* Free all URBs before freeing the card.
|
||||
*/
|
||||
tascam_free_urbs(tascam);
|
||||
|
||||
if (tascam->iface1) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue