more fixes & formatting
This commit is contained in:
parent
2eba5f83c4
commit
d199e9ccaf
49
us144mkii.c
49
us144mkii.c
|
|
@ -226,9 +226,6 @@ static int tascam_probe(struct usb_interface *intf, const struct usb_device_id *
|
||||||
int err;
|
int err;
|
||||||
int idx;
|
int idx;
|
||||||
|
|
||||||
char *handshake_buf __free(kfree) = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
if (intf->cur_altsetting->desc.bInterfaceNumber == 1)
|
if (intf->cur_altsetting->desc.bInterfaceNumber == 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
@ -242,25 +239,6 @@ static int tascam_probe(struct usb_interface *intf, const struct usb_device_id *
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
handshake_buf = kmalloc(1, GFP_KERNEL);
|
|
||||||
if (!handshake_buf) {
|
|
||||||
atomic_dec(&dev_idx);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
|
||||||
VENDOR_REQ_MODE_CONTROL, RT_D2H_VENDOR_DEV,
|
|
||||||
MODE_VAL_HANDSHAKE_READ, 0x0000, handshake_buf, 1,
|
|
||||||
USB_CTRL_TIMEOUT_MS);
|
|
||||||
if (err < 0) {
|
|
||||||
dev_err(&dev->dev, "Handshake failed: %d\n", err);
|
|
||||||
atomic_dec(&dev_idx);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
usb_set_interface(dev, 0, 1);
|
|
||||||
usb_set_interface(dev, 1, 1);
|
|
||||||
|
|
||||||
err = snd_card_new(&dev->dev, index[idx], id[idx], THIS_MODULE,
|
err = snd_card_new(&dev->dev, index[idx], id[idx], THIS_MODULE,
|
||||||
sizeof(struct tascam_card), &card);
|
sizeof(struct tascam_card), &card);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
|
|
@ -312,6 +290,33 @@ static int tascam_probe(struct usb_interface *intf, const struct usb_device_id *
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto free_card;
|
goto free_card;
|
||||||
|
|
||||||
|
tascam->scratch_buf = devm_kzalloc(&dev->dev, 4, GFP_KERNEL);
|
||||||
|
if (!tascam->scratch_buf) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto free_card;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
||||||
|
VENDOR_REQ_MODE_CONTROL, RT_D2H_VENDOR_DEV,
|
||||||
|
MODE_VAL_HANDSHAKE_READ, 0x0000, tascam->scratch_buf, 1,
|
||||||
|
USB_CTRL_TIMEOUT_MS);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(&dev->dev, "Handshake failed: %d\n", err);
|
||||||
|
goto free_card;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = usb_set_interface(dev, 0, 1);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(&dev->dev, "Failed to set interface 0: %d\n", err);
|
||||||
|
goto free_card;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = usb_set_interface(dev, 1, 1);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(&dev->dev, "Failed to set interface 1: %d\n", err);
|
||||||
|
goto free_card;
|
||||||
|
}
|
||||||
|
|
||||||
if (us144mkii_configure_device_for_rate(tascam, 48000) < 0)
|
if (us144mkii_configure_device_for_rate(tascam, 48000) < 0)
|
||||||
dev_warn(&dev->dev, "Failed to initialize device at 48khz\n");
|
dev_warn(&dev->dev, "Failed to initialize device at 48khz\n");
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -64,12 +64,12 @@ enum tascam_register {
|
||||||
|
|
||||||
#define REG_VAL_ENABLE 0x0101
|
#define REG_VAL_ENABLE 0x0101
|
||||||
|
|
||||||
#define NUM_PLAYBACK_URBS 8
|
#define NUM_PLAYBACK_URBS 4
|
||||||
#define PLAYBACK_URB_PACKETS 2
|
#define PLAYBACK_URB_PACKETS 4
|
||||||
#define NUM_FEEDBACK_URBS 2
|
#define NUM_FEEDBACK_URBS 2
|
||||||
#define FEEDBACK_URB_PACKETS 1
|
#define FEEDBACK_URB_PACKETS 1
|
||||||
#define FEEDBACK_PACKET_SIZE 3
|
#define FEEDBACK_PACKET_SIZE 3
|
||||||
#define NUM_CAPTURE_URBS 4
|
#define NUM_CAPTURE_URBS 8
|
||||||
#define CAPTURE_PACKET_SIZE 512
|
#define CAPTURE_PACKET_SIZE 512
|
||||||
|
|
||||||
#define MIDI_PACKET_SIZE 9
|
#define MIDI_PACKET_SIZE 9
|
||||||
|
|
@ -92,6 +92,7 @@ enum tascam_register {
|
||||||
* @card: pointer to the ALSA sound card
|
* @card: pointer to the ALSA sound card
|
||||||
* @pcm: pointer to the ALSA PCM device
|
* @pcm: pointer to the ALSA PCM device
|
||||||
* @rmidi: pointer to the ALSA raw MIDI device
|
* @rmidi: pointer to the ALSA raw MIDI device
|
||||||
|
* @scratch_buf: temporary buffer for control messages
|
||||||
* @playback_substream: pointer to the PCM playback substream
|
* @playback_substream: pointer to the PCM playback substream
|
||||||
* @capture_substream: pointer to the PCM capture substream
|
* @capture_substream: pointer to the PCM capture substream
|
||||||
* @playback_urbs: array of URBs for PCM playback
|
* @playback_urbs: array of URBs for PCM playback
|
||||||
|
|
@ -136,6 +137,8 @@ struct tascam_card {
|
||||||
struct snd_pcm *pcm;
|
struct snd_pcm *pcm;
|
||||||
struct snd_rawmidi *rmidi;
|
struct snd_rawmidi *rmidi;
|
||||||
|
|
||||||
|
u8 *scratch_buf;
|
||||||
|
|
||||||
struct snd_pcm_substream *playback_substream;
|
struct snd_pcm_substream *playback_substream;
|
||||||
struct snd_pcm_substream *capture_substream;
|
struct snd_pcm_substream *capture_substream;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
// Copyright (c) 2025 Šerif Rami <ramiserifpersia@gmail.com>
|
// Copyright (c) 2025 Šerif Rami <ramiserifpersia@gmail.com>
|
||||||
|
|
||||||
|
#include <linux/unaligned.h>
|
||||||
#include "us144mkii_pcm.h"
|
#include "us144mkii_pcm.h"
|
||||||
|
|
||||||
const struct snd_pcm_hardware tascam_capture_hw = {
|
const struct snd_pcm_hardware tascam_capture_hw = {
|
||||||
|
|
@ -35,6 +36,8 @@ 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);
|
||||||
|
|
||||||
|
atomic_set(&tascam->capture_active, 0);
|
||||||
|
usb_kill_anchored_urbs(&tascam->capture_anchor);
|
||||||
tascam->capture_substream = NULL;
|
tascam->capture_substream = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -97,7 +100,7 @@ static int tascam_capture_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||||
spin_unlock_irqrestore(&tascam->lock, flags);
|
spin_unlock_irqrestore(&tascam->lock, flags);
|
||||||
|
|
||||||
if (stop) {
|
if (stop) {
|
||||||
/* Ensure capture_active is updated before unlinking URBs */
|
/* Ensure capture_active is updated before unlinking URBs. */
|
||||||
smp_mb();
|
smp_mb();
|
||||||
for (i = 0; i < NUM_CAPTURE_URBS; i++) {
|
for (i = 0; i < NUM_CAPTURE_URBS; i++) {
|
||||||
if (tascam->capture_urbs[i])
|
if (tascam->capture_urbs[i])
|
||||||
|
|
@ -111,7 +114,7 @@ static int tascam_capture_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||||
if (usb_submit_urb(tascam->capture_urbs[i], GFP_ATOMIC) < 0) {
|
if (usb_submit_urb(tascam->capture_urbs[i], GFP_ATOMIC) < 0) {
|
||||||
usb_unanchor_urb(tascam->capture_urbs[i]);
|
usb_unanchor_urb(tascam->capture_urbs[i]);
|
||||||
atomic_set(&tascam->capture_active, 0);
|
atomic_set(&tascam->capture_active, 0);
|
||||||
/* Ensure capture_active is cleared before unlinking URBs */
|
/* Ensure capture_active is updated before unlinking URBs due to submission error. */
|
||||||
smp_mb();
|
smp_mb();
|
||||||
for (int j = 0; j < i; j++)
|
for (int j = 0; j < i; j++)
|
||||||
usb_unlink_urb(tascam->capture_urbs[j]);
|
usb_unlink_urb(tascam->capture_urbs[j]);
|
||||||
|
|
@ -124,46 +127,44 @@ static int tascam_capture_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u8 tascam_pack_byte(const u8 *src, int bit_offset)
|
static inline void tascam_unpack_8bytes(const u8 *src, u8 *out_bit0, u8 *out_bit1)
|
||||||
{
|
{
|
||||||
return (((src[0] >> bit_offset) & 1) << 7) |
|
u64 val = get_unaligned_le64(src);
|
||||||
(((src[1] >> bit_offset) & 1) << 6) |
|
u8 b0 = 0, b1 = 0;
|
||||||
(((src[2] >> bit_offset) & 1) << 5) |
|
int i;
|
||||||
(((src[3] >> bit_offset) & 1) << 4) |
|
|
||||||
(((src[4] >> bit_offset) & 1) << 3) |
|
for (i = 0; i < 8; i++) {
|
||||||
(((src[5] >> bit_offset) & 1) << 2) |
|
b0 |= ((val >> (i * 8)) & 1) << (7 - i);
|
||||||
(((src[6] >> bit_offset) & 1) << 1) |
|
b1 |= ((val >> (i * 8 + 1)) & 1) << (7 - i);
|
||||||
(((src[7] >> bit_offset) & 1));
|
}
|
||||||
|
|
||||||
|
*out_bit0 = b0;
|
||||||
|
*out_bit1 = b1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tascam_decode_capture_chunk(const u8 *src, u32 *dst, int frames_to_decode)
|
static void tascam_decode_capture_chunk(const u8 *src, u32 *dst, int frames_to_decode)
|
||||||
{
|
{
|
||||||
int frame;
|
int i;
|
||||||
u8 h, m, l;
|
u8 h[4], m[4], l[4];
|
||||||
|
|
||||||
for (frame = 0; frame < frames_to_decode; frame++) {
|
for (i = 0; i < frames_to_decode; i++) {
|
||||||
const u8 *p_src_a = src + (frame * 64);
|
const u8 *p_src_a = src + (i * 64);
|
||||||
const u8 *p_src_b = src + (frame * 64) + 32;
|
const u8 *p_src_b = src + (i * 64) + 32;
|
||||||
|
|
||||||
h = tascam_pack_byte(p_src_a, 0);
|
/* Channel 1 (h0) and Channel 3 (h2) */
|
||||||
m = tascam_pack_byte(p_src_a + 8, 0);
|
tascam_unpack_8bytes(p_src_a, &h[0], &h[2]);
|
||||||
l = tascam_pack_byte(p_src_a + 16, 0);
|
tascam_unpack_8bytes(p_src_a + 8, &m[0], &m[2]);
|
||||||
*dst++ = (h << 24) | (m << 16) | (l << 8);
|
tascam_unpack_8bytes(p_src_a + 16, &l[0], &l[2]);
|
||||||
|
|
||||||
h = tascam_pack_byte(p_src_b, 0);
|
/* Channel 2 (h1) and Channel 4 (h3) */
|
||||||
m = tascam_pack_byte(p_src_b + 8, 0);
|
tascam_unpack_8bytes(p_src_b, &h[1], &h[3]);
|
||||||
l = tascam_pack_byte(p_src_b + 16, 0);
|
tascam_unpack_8bytes(p_src_b + 8, &m[1], &m[3]);
|
||||||
*dst++ = (h << 24) | (m << 16) | (l << 8);
|
tascam_unpack_8bytes(p_src_b + 16, &l[1], &l[3]);
|
||||||
|
|
||||||
h = tascam_pack_byte(p_src_a, 1);
|
*dst++ = (h[0] << 24) | (m[0] << 16) | (l[0] << 8);
|
||||||
m = tascam_pack_byte(p_src_a + 8, 1);
|
*dst++ = (h[1] << 24) | (m[1] << 16) | (l[1] << 8);
|
||||||
l = tascam_pack_byte(p_src_a + 16, 1);
|
*dst++ = (h[2] << 24) | (m[2] << 16) | (l[2] << 8);
|
||||||
*dst++ = (h << 24) | (m << 16) | (l << 8);
|
*dst++ = (h[3] << 24) | (m[3] << 16) | (l[3] << 8);
|
||||||
|
|
||||||
h = tascam_pack_byte(p_src_b, 1);
|
|
||||||
m = tascam_pack_byte(p_src_b + 8, 1);
|
|
||||||
l = tascam_pack_byte(p_src_b + 16, 1);
|
|
||||||
*dst++ = (h << 24) | (m << 16) | (l << 8);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -200,18 +201,21 @@ void capture_urb_complete(struct urb *urb)
|
||||||
}
|
}
|
||||||
|
|
||||||
substream = tascam->capture_substream;
|
substream = tascam->capture_substream;
|
||||||
if (!substream) {
|
if (!substream || !substream->runtime) {
|
||||||
atomic_dec(&tascam->active_urbs);
|
atomic_dec(&tascam->active_urbs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
runtime = substream->runtime;
|
runtime = substream->runtime;
|
||||||
if (!runtime) {
|
if (!runtime->dma_area) {
|
||||||
atomic_dec(&tascam->active_urbs);
|
atomic_dec(&tascam->active_urbs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_size = runtime->buffer_size;
|
buffer_size = runtime->buffer_size;
|
||||||
period_size = runtime->period_size;
|
period_size = runtime->period_size;
|
||||||
|
|
||||||
|
if (urb->actual_length % 64 != 0)
|
||||||
|
dev_warn_ratelimited(&tascam->dev->dev, "Unaligned capture packet size: %d\n", urb->actual_length);
|
||||||
frames_received = urb->actual_length / 64;
|
frames_received = urb->actual_length / 64;
|
||||||
|
|
||||||
if (frames_received > 0) {
|
if (frames_received > 0) {
|
||||||
|
|
@ -252,9 +256,12 @@ void capture_urb_complete(struct urb *urb)
|
||||||
snd_pcm_period_elapsed(substream);
|
snd_pcm_period_elapsed(substream);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usb_submit_urb(urb, GFP_ATOMIC) < 0)
|
usb_anchor_urb(urb, &tascam->capture_anchor);
|
||||||
|
if (usb_submit_urb(urb, GFP_ATOMIC) < 0) {
|
||||||
|
usb_unanchor_urb(urb);
|
||||||
atomic_dec(&tascam->active_urbs);
|
atomic_dec(&tascam->active_urbs);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const struct snd_pcm_ops tascam_capture_ops = {
|
const struct snd_pcm_ops tascam_capture_ops = {
|
||||||
.open = tascam_capture_open,
|
.open = tascam_capture_open,
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,9 @@ static void tascam_midi_out_complete(struct urb *urb)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (submit) {
|
if (submit) {
|
||||||
|
usb_anchor_urb(urb, &tascam->midi_anchor);
|
||||||
if (usb_submit_urb(urb, GFP_ATOMIC) < 0) {
|
if (usb_submit_urb(urb, GFP_ATOMIC) < 0) {
|
||||||
|
usb_unanchor_urb(urb);
|
||||||
spin_lock_irqsave(&tascam->midi_lock, flags);
|
spin_lock_irqsave(&tascam->midi_lock, flags);
|
||||||
tascam->midi_out_active = false;
|
tascam->midi_out_active = false;
|
||||||
spin_unlock_irqrestore(&tascam->midi_lock, flags);
|
spin_unlock_irqrestore(&tascam->midi_lock, flags);
|
||||||
|
|
@ -111,6 +113,7 @@ static void tascam_midi_in_complete(struct urb *urb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
usb_anchor_urb(urb, &tascam->midi_anchor);
|
||||||
if (usb_submit_urb(urb, GFP_ATOMIC) < 0)
|
if (usb_submit_urb(urb, GFP_ATOMIC) < 0)
|
||||||
usb_unanchor_urb(urb);
|
usb_unanchor_urb(urb);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,10 @@ 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);
|
||||||
|
|
||||||
|
atomic_set(&tascam->playback_active, 0);
|
||||||
cancel_work_sync(&tascam->stop_pcm_work);
|
cancel_work_sync(&tascam->stop_pcm_work);
|
||||||
|
usb_kill_anchored_urbs(&tascam->playback_anchor);
|
||||||
|
usb_kill_anchored_urbs(&tascam->feedback_anchor);
|
||||||
tascam->playback_substream = NULL;
|
tascam->playback_substream = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -130,7 +133,7 @@ static int tascam_playback_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||||
spin_unlock_irqrestore(&tascam->lock, flags);
|
spin_unlock_irqrestore(&tascam->lock, flags);
|
||||||
|
|
||||||
if (stop) {
|
if (stop) {
|
||||||
/* Ensure playback_active is updated before unlinking URBs */
|
/* Ensure playback_active is updated before unlinking URBs. */
|
||||||
smp_mb();
|
smp_mb();
|
||||||
for (i = 0; i < NUM_FEEDBACK_URBS; i++) {
|
for (i = 0; i < NUM_FEEDBACK_URBS; i++) {
|
||||||
if (tascam->feedback_urbs[i])
|
if (tascam->feedback_urbs[i])
|
||||||
|
|
@ -149,7 +152,7 @@ static int tascam_playback_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||||
usb_unanchor_urb(tascam->feedback_urbs[i]);
|
usb_unanchor_urb(tascam->feedback_urbs[i]);
|
||||||
dev_err(&tascam->dev->dev, "Failed to submit feedback URB %d\n", i);
|
dev_err(&tascam->dev->dev, "Failed to submit feedback URB %d\n", i);
|
||||||
atomic_set(&tascam->playback_active, 0);
|
atomic_set(&tascam->playback_active, 0);
|
||||||
/* Ensure playback_active is cleared before unlinking URBs */
|
/* Ensure playback_active is updated before unlinking feedback URBs due to submission error. */
|
||||||
smp_mb();
|
smp_mb();
|
||||||
for (int j = 0; j < i; j++)
|
for (int j = 0; j < i; j++)
|
||||||
usb_unlink_urb(tascam->feedback_urbs[j]);
|
usb_unlink_urb(tascam->feedback_urbs[j]);
|
||||||
|
|
@ -164,7 +167,7 @@ static int tascam_playback_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||||
usb_unanchor_urb(tascam->playback_urbs[i]);
|
usb_unanchor_urb(tascam->playback_urbs[i]);
|
||||||
dev_err(&tascam->dev->dev, "Failed to submit playback URB %d\n", i);
|
dev_err(&tascam->dev->dev, "Failed to submit playback URB %d\n", i);
|
||||||
atomic_set(&tascam->playback_active, 0);
|
atomic_set(&tascam->playback_active, 0);
|
||||||
/* Ensure playback_active is cleared before unlinking URBs */
|
/* Ensure playback_active is updated before unlinking playback URBs due to submission error. */
|
||||||
smp_mb();
|
smp_mb();
|
||||||
for (int j = 0; j < NUM_FEEDBACK_URBS; j++)
|
for (int j = 0; j < NUM_FEEDBACK_URBS; j++)
|
||||||
usb_unlink_urb(tascam->feedback_urbs[j]);
|
usb_unlink_urb(tascam->feedback_urbs[j]);
|
||||||
|
|
@ -217,12 +220,12 @@ void playback_urb_complete(struct urb *urb)
|
||||||
}
|
}
|
||||||
|
|
||||||
substream = tascam->playback_substream;
|
substream = tascam->playback_substream;
|
||||||
if (!substream) {
|
if (!substream || !substream->runtime) {
|
||||||
atomic_dec(&tascam->active_urbs);
|
atomic_dec(&tascam->active_urbs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
runtime = substream->runtime;
|
runtime = substream->runtime;
|
||||||
if (!runtime) {
|
if (!runtime->dma_area) {
|
||||||
atomic_dec(&tascam->active_urbs);
|
atomic_dec(&tascam->active_urbs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -278,9 +281,12 @@ void playback_urb_complete(struct urb *urb)
|
||||||
if (need_period_elapsed)
|
if (need_period_elapsed)
|
||||||
snd_pcm_period_elapsed(substream);
|
snd_pcm_period_elapsed(substream);
|
||||||
|
|
||||||
if (usb_submit_urb(urb, GFP_ATOMIC) < 0)
|
usb_anchor_urb(urb, &tascam->playback_anchor);
|
||||||
|
if (usb_submit_urb(urb, GFP_ATOMIC) < 0) {
|
||||||
|
usb_unanchor_urb(urb);
|
||||||
atomic_dec(&tascam->active_urbs);
|
atomic_dec(&tascam->active_urbs);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* feedback_urb_complete() - completion handler for feedback isochronous URBs
|
* feedback_urb_complete() - completion handler for feedback isochronous URBs
|
||||||
|
|
@ -331,6 +337,7 @@ void feedback_urb_complete(struct urb *urb)
|
||||||
spin_unlock_irqrestore(&tascam->lock, flags);
|
spin_unlock_irqrestore(&tascam->lock, flags);
|
||||||
|
|
||||||
resubmit:
|
resubmit:
|
||||||
|
usb_anchor_urb(urb, &tascam->feedback_anchor);
|
||||||
ret = usb_submit_urb(urb, GFP_ATOMIC);
|
ret = usb_submit_urb(urb, GFP_ATOMIC);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
usb_unanchor_urb(urb);
|
usb_unanchor_urb(urb);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue