stability and midi fixes
This commit is contained in:
parent
cc31e81f60
commit
ba4e73b926
|
|
@ -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! ---"
|
||||
21
us144mkii.c
21
us144mkii.c
|
|
@ -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--;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -11,19 +11,19 @@
|
|||
* 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);
|
||||
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;
|
||||
u8 clean_buf[MIDI_IN_BUF_SIZE];
|
||||
unsigned int len, clean_len;
|
||||
|
||||
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);
|
||||
len = kfifo_out_spinlocked(&tascam->midi_in_fifo,
|
||||
buf, sizeof(buf), &tascam->midi_in_lock);
|
||||
|
||||
if (len == 0)
|
||||
continue;
|
||||
|
|
@ -31,30 +31,15 @@ static void tascam_midi_in_work_handler(struct work_struct *work) {
|
|||
if (!tascam->midi_in_substream)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
u8 byte = 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);
|
||||
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];
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
|
|
|||
|
|
@ -16,53 +16,21 @@
|
|||
*/
|
||||
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) {
|
||||
diff = target_sum - (size * initial_value);
|
||||
for (i = 0; i < abs(diff); ++i) {
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue