stability and midi fixes

This commit is contained in:
Šerif Rami 2025-08-08 08:58:13 +02:00
parent cc31e81f60
commit ba4e73b926
7 changed files with 107 additions and 95 deletions

32
build_and_install.sh Executable file
View File

@ -0,0 +1,32 @@
#!/bin/bash
# Exit immediately if a command exits with a non-zero status.
set -e
echo "--- Cleaning build directory ---"
make clean
echo "--- Compiling the driver ---"
make
echo "--- Installing the driver ---"
SUDO_CMD="sudo"
KERNEL_MODULE_DIR="/lib/modules/$(uname -r)/extra"
echo "Creating directory if it doesn't exist: $KERNEL_MODULE_DIR"
$SUDO_CMD mkdir -p "$KERNEL_MODULE_DIR"
echo "Copying snd-usb-us144mkii.ko to $KERNEL_MODULE_DIR"
$SUDO_CMD cp snd-usb-us144mkii.ko "$KERNEL_MODULE_DIR"
echo "--- Updating module dependencies ---"
$SUDO_CMD depmod -a
echo "--- Reloading the driver ---"
echo "Unloading old driver (if present)..."
$SUDO_CMD rmmod snd_usb_us144mkii -f || true
echo "Loading new driver..."
$SUDO_CMD modprobe snd-usb-us144mkii
echo "--- Driver build and installation complete! ---"

View File

@ -286,7 +286,6 @@ void tascam_stop_work_handler(struct work_struct *work) {
usb_kill_anchored_urbs(&tascam->feedback_anchor);
usb_kill_anchored_urbs(&tascam->capture_anchor);
atomic_set(&tascam->active_urbs, 0);
cancel_work_sync(&tascam->capture_work);
}
/**
@ -508,6 +507,7 @@ static int tascam_probe(struct usb_interface *intf,
}
tascam = card->private_data;
card->private_free = tascam_card_private_free;
tascam->dev = usb_get_dev(dev);
tascam->card = card;
tascam->iface0 = intf;
@ -525,10 +525,10 @@ static int tascam_probe(struct usb_interface *intf,
INIT_WORK(&tascam->stop_work, tascam_stop_work_handler);
if (kfifo_alloc(&tascam->midi_in_fifo, MIDI_IN_FIFO_SIZE, GFP_KERNEL))
goto free_card;
card->private_free = tascam_card_private_free;
if (kfifo_alloc(&tascam->midi_in_fifo, MIDI_IN_FIFO_SIZE, GFP_KERNEL)) {
snd_card_free(card);
return -ENOMEM;
}
strscpy(card->driver, DRIVER_NAME, sizeof(card->driver));
if (dev->descriptor.idProduct == USB_PID_TASCAM_US144) {
@ -599,15 +599,20 @@ static void tascam_disconnect(struct usb_interface *intf) {
if (intf->cur_altsetting->desc.bInterfaceNumber == 0) {
device_remove_file(&tascam->dev->dev, &dev_attr_driver_version);
device_remove_file(&intf->dev, &dev_attr_driver_version);
/* Ensure all deferred work is complete before freeing resources */
snd_card_disconnect(tascam->card);
cancel_work_sync(&tascam->stop_work);
cancel_work_sync(&tascam->capture_work);
cancel_work_sync(&tascam->midi_in_work);
cancel_work_sync(&tascam->midi_out_work);
usb_kill_anchored_urbs(&tascam->playback_anchor);
usb_kill_anchored_urbs(&tascam->capture_anchor);
usb_kill_anchored_urbs(&tascam->feedback_anchor);
usb_kill_anchored_urbs(&tascam->midi_in_anchor);
usb_kill_anchored_urbs(&tascam->midi_out_anchor);
timer_delete_sync(&tascam->error_timer);
snd_card_disconnect(tascam->card);
tascam_free_urbs(tascam);
snd_card_free(tascam->card);
dev_idx--;
}

View File

@ -15,7 +15,7 @@
#include <sound/rawmidi.h>
#define DRIVER_NAME "us144mkii"
#define DRIVER_VERSION "1.7.5"
#define DRIVER_VERSION "1.7.6"
/* --- USB Device Identification --- */
#define USB_VID_TASCAM 0x0644

View File

@ -82,6 +82,9 @@ tascam_capture_pointer(struct snd_pcm_substream *substream) {
pos = tascam->capture_frames_processed;
spin_unlock_irqrestore(&tascam->lock, flags);
if (runtime->buffer_size == 0)
return 0;
u64 remainder = do_div(pos, runtime->buffer_size);
return runtime ? remainder : 0;
}
@ -261,16 +264,21 @@ void capture_urb_complete(struct urb *urb) {
goto out;
if (urb->actual_length > 0) {
size_t i;
size_t write_ptr;
size_t bytes_to_end;
spin_lock_irqsave(&tascam->lock, flags);
write_ptr = tascam->capture_ring_buffer_write_ptr;
for (i = 0; i < urb->actual_length; i++) {
tascam->capture_ring_buffer[write_ptr] = ((u8 *)urb->transfer_buffer)[i];
write_ptr = (write_ptr + 1) % CAPTURE_RING_BUFFER_SIZE;
bytes_to_end = CAPTURE_RING_BUFFER_SIZE - write_ptr;
if (urb->actual_length > bytes_to_end) {
memcpy(tascam->capture_ring_buffer + write_ptr, urb->transfer_buffer, bytes_to_end);
memcpy(tascam->capture_ring_buffer, urb->transfer_buffer + bytes_to_end, urb->actual_length - bytes_to_end);
} else {
memcpy(tascam->capture_ring_buffer + write_ptr, urb->transfer_buffer, urb->actual_length);
}
tascam->capture_ring_buffer_write_ptr = write_ptr;
tascam->capture_ring_buffer_write_ptr = (write_ptr + urb->actual_length) % CAPTURE_RING_BUFFER_SIZE;
spin_unlock_irqrestore(&tascam->lock, flags);
schedule_work(&tascam->capture_work);

View File

@ -11,51 +11,36 @@
* the kfifo, processes it by stripping protocol-specific padding bytes, and
* passes the clean MIDI data to the ALSA rawmidi subsystem.
*/
static void tascam_midi_in_work_handler(struct work_struct *work) {
struct tascam_card *tascam =
container_of(work, struct tascam_card, midi_in_work);
u8 buf[MIDI_IN_BUF_SIZE];
unsigned int len;
int i;
static void tascam_midi_in_work_handler(struct work_struct *work)
{
struct tascam_card *tascam = container_of(work, struct tascam_card, midi_in_work);
u8 buf[MIDI_IN_BUF_SIZE];
u8 clean_buf[MIDI_IN_BUF_SIZE];
unsigned int len, clean_len;
if (!tascam->midi_in_substream)
return;
if (!tascam->midi_in_substream)
return;
while (!kfifo_is_empty(&tascam->midi_in_fifo)) {
len = kfifo_out_spinlocked(&tascam->midi_in_fifo, buf, sizeof(buf),
&tascam->midi_in_lock);
while (!kfifo_is_empty(&tascam->midi_in_fifo)) {
len = kfifo_out_spinlocked(&tascam->midi_in_fifo,
buf, sizeof(buf), &tascam->midi_in_lock);
if (len == 0)
continue;
if (len == 0)
continue;
if (!tascam->midi_in_substream)
continue;
if (!tascam->midi_in_substream)
continue;
for (i = 0; i < len; ++i) {
u8 byte = buf[i];
clean_len = 0;
for (int i = 0; i < len; ++i) {
if (buf[i] == 0xfd) continue;
if (i == (len - 1) && (buf[i] == 0x00 || buf[i] == 0xff)) continue;
clean_buf[clean_len++] = buf[i];
}
/* Skip padding bytes */
if (byte == 0xfd)
continue;
if (byte == 0xf0) { /* SysEx Start */
tascam->in_sysex = true;
} else if (byte == 0xf7) { /* SysEx End */
tascam->in_sysex = false;
} else if (tascam->in_sysex) {
/* Inside a SysEx message */
} else if (byte & 0x80) { /* Status byte */
tascam->midi_running_status = byte;
} else { /* Data byte */
if (tascam->midi_running_status != 0)
snd_rawmidi_receive(tascam->midi_in_substream,
&tascam->midi_running_status, 1);
}
/* Submit valid MIDI bytes one by one */
snd_rawmidi_receive(tascam->midi_in_substream, &byte, 1);
}
}
if (clean_len > 0)
snd_rawmidi_receive(tascam->midi_in_substream, clean_buf, clean_len);
}
}
/**
@ -75,7 +60,6 @@ void tascam_midi_in_urb_complete(struct urb *urb) {
urb->status != -ESHUTDOWN && urb->status != -EPROTO) {
dev_err_ratelimited(tascam->card->dev, "MIDI IN URB failed: status %d\n",
urb->status);
mod_timer(&tascam->error_timer, jiffies + msecs_to_jiffies(50));
}
goto out;
}
@ -199,7 +183,6 @@ void tascam_midi_out_urb_complete(struct urb *urb) {
urb->status != -ESHUTDOWN) {
dev_err_ratelimited(tascam->card->dev, "MIDI OUT URB failed: %d\n",
urb->status);
mod_timer(&tascam->error_timer, jiffies + msecs_to_jiffies(50));
}
}
@ -338,6 +321,19 @@ static int tascam_midi_out_close(struct snd_rawmidi_substream *substream) {
*/
static void tascam_midi_out_drain(struct snd_rawmidi_substream *substream) {
struct tascam_card *tascam = substream->rmidi->private_data;
bool in_flight = true;
while (in_flight) {
in_flight = false;
for (int i = 0; i < NUM_MIDI_OUT_URBS; i++) {
if (test_bit(i, &tascam->midi_out_urbs_in_flight)) {
in_flight = true;
break;
}
}
if (in_flight)
schedule_timeout_uninterruptible(1);
}
cancel_work_sync(&tascam->midi_out_work);
usb_kill_anchored_urbs(&tascam->midi_out_anchor);

View File

@ -16,52 +16,20 @@
*/
static void fpoInitPattern(unsigned int size, unsigned int *pattern_array,
unsigned int initial_value, int target_sum) {
unsigned int current_sum;
int diff;
int abs_diff;
unsigned int stride;
unsigned int i;
int diff, i;
if (!size)
return;
/* 1. Initialize the array with the base value. */
current_sum = 0;
for (i = 0; i < size; ++i) {
for (i = 0; i < size; ++i)
pattern_array[i] = initial_value;
}
current_sum = size * initial_value;
/* 2. Iteratively adjust until the sum is correct. */
while (current_sum != target_sum) {
diff = target_sum - current_sum;
abs_diff = (diff > 0) ? diff : -diff;
if (abs_diff == 0)
break;
/* Calculate the stride to distribute the adjustments. */
stride = size / abs_diff;
if (stride == 0) {
/* This would happen if the difference is larger than the array
* size, which indicates a problem. The original code breaks
* here.
*/
break;
}
/* Apply the adjustments. */
for (i = 0; i < size; i += stride) {
if (diff > 0)
pattern_array[i]++;
else
pattern_array[i]--;
}
/* Recalculate the sum for the next iteration. */
current_sum = 0;
for (i = 0; i < size; ++i)
current_sum += pattern_array[i];
diff = target_sum - (size * initial_value);
for (i = 0; i < abs(diff); ++i) {
if (diff > 0)
pattern_array[i]++;
else
pattern_array[i]--;
}
}

View File

@ -122,6 +122,9 @@ tascam_playback_pointer(struct snd_pcm_substream *substream) {
pos = tascam->playback_frames_consumed;
spin_unlock_irqrestore(&tascam->lock, flags);
if (runtime->buffer_size == 0)
return 0;
u64 remainder = do_div(pos, runtime->buffer_size);
return runtime ? remainder : 0;
}