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->feedback_anchor);
|
||||||
usb_kill_anchored_urbs(&tascam->capture_anchor);
|
usb_kill_anchored_urbs(&tascam->capture_anchor);
|
||||||
atomic_set(&tascam->active_urbs, 0);
|
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;
|
tascam = card->private_data;
|
||||||
|
card->private_free = tascam_card_private_free;
|
||||||
tascam->dev = usb_get_dev(dev);
|
tascam->dev = usb_get_dev(dev);
|
||||||
tascam->card = card;
|
tascam->card = card;
|
||||||
tascam->iface0 = intf;
|
tascam->iface0 = intf;
|
||||||
|
|
@ -525,10 +525,10 @@ static int tascam_probe(struct usb_interface *intf,
|
||||||
|
|
||||||
INIT_WORK(&tascam->stop_work, tascam_stop_work_handler);
|
INIT_WORK(&tascam->stop_work, tascam_stop_work_handler);
|
||||||
|
|
||||||
if (kfifo_alloc(&tascam->midi_in_fifo, MIDI_IN_FIFO_SIZE, GFP_KERNEL))
|
if (kfifo_alloc(&tascam->midi_in_fifo, MIDI_IN_FIFO_SIZE, GFP_KERNEL)) {
|
||||||
goto free_card;
|
snd_card_free(card);
|
||||||
|
return -ENOMEM;
|
||||||
card->private_free = tascam_card_private_free;
|
}
|
||||||
|
|
||||||
strscpy(card->driver, DRIVER_NAME, sizeof(card->driver));
|
strscpy(card->driver, DRIVER_NAME, sizeof(card->driver));
|
||||||
if (dev->descriptor.idProduct == USB_PID_TASCAM_US144) {
|
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) {
|
if (intf->cur_altsetting->desc.bInterfaceNumber == 0) {
|
||||||
device_remove_file(&tascam->dev->dev, &dev_attr_driver_version);
|
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->playback_anchor);
|
||||||
usb_kill_anchored_urbs(&tascam->capture_anchor);
|
usb_kill_anchored_urbs(&tascam->capture_anchor);
|
||||||
usb_kill_anchored_urbs(&tascam->feedback_anchor);
|
usb_kill_anchored_urbs(&tascam->feedback_anchor);
|
||||||
usb_kill_anchored_urbs(&tascam->midi_in_anchor);
|
usb_kill_anchored_urbs(&tascam->midi_in_anchor);
|
||||||
usb_kill_anchored_urbs(&tascam->midi_out_anchor);
|
usb_kill_anchored_urbs(&tascam->midi_out_anchor);
|
||||||
timer_delete_sync(&tascam->error_timer);
|
timer_delete_sync(&tascam->error_timer);
|
||||||
snd_card_disconnect(tascam->card);
|
|
||||||
tascam_free_urbs(tascam);
|
|
||||||
snd_card_free(tascam->card);
|
snd_card_free(tascam->card);
|
||||||
dev_idx--;
|
dev_idx--;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
#include <sound/rawmidi.h>
|
#include <sound/rawmidi.h>
|
||||||
|
|
||||||
#define DRIVER_NAME "us144mkii"
|
#define DRIVER_NAME "us144mkii"
|
||||||
#define DRIVER_VERSION "1.7.5"
|
#define DRIVER_VERSION "1.7.6"
|
||||||
|
|
||||||
/* --- USB Device Identification --- */
|
/* --- USB Device Identification --- */
|
||||||
#define USB_VID_TASCAM 0x0644
|
#define USB_VID_TASCAM 0x0644
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,9 @@ tascam_capture_pointer(struct snd_pcm_substream *substream) {
|
||||||
pos = tascam->capture_frames_processed;
|
pos = tascam->capture_frames_processed;
|
||||||
spin_unlock_irqrestore(&tascam->lock, flags);
|
spin_unlock_irqrestore(&tascam->lock, flags);
|
||||||
|
|
||||||
|
if (runtime->buffer_size == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
u64 remainder = do_div(pos, runtime->buffer_size);
|
u64 remainder = do_div(pos, runtime->buffer_size);
|
||||||
return runtime ? remainder : 0;
|
return runtime ? remainder : 0;
|
||||||
}
|
}
|
||||||
|
|
@ -261,16 +264,21 @@ void capture_urb_complete(struct urb *urb) {
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (urb->actual_length > 0) {
|
if (urb->actual_length > 0) {
|
||||||
size_t i;
|
|
||||||
size_t write_ptr;
|
size_t write_ptr;
|
||||||
|
size_t bytes_to_end;
|
||||||
|
|
||||||
spin_lock_irqsave(&tascam->lock, flags);
|
spin_lock_irqsave(&tascam->lock, flags);
|
||||||
write_ptr = tascam->capture_ring_buffer_write_ptr;
|
write_ptr = tascam->capture_ring_buffer_write_ptr;
|
||||||
for (i = 0; i < urb->actual_length; i++) {
|
bytes_to_end = CAPTURE_RING_BUFFER_SIZE - write_ptr;
|
||||||
tascam->capture_ring_buffer[write_ptr] = ((u8 *)urb->transfer_buffer)[i];
|
|
||||||
write_ptr = (write_ptr + 1) % CAPTURE_RING_BUFFER_SIZE;
|
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);
|
spin_unlock_irqrestore(&tascam->lock, flags);
|
||||||
|
|
||||||
schedule_work(&tascam->capture_work);
|
schedule_work(&tascam->capture_work);
|
||||||
|
|
|
||||||
|
|
@ -11,51 +11,36 @@
|
||||||
* the kfifo, processes it by stripping protocol-specific padding bytes, and
|
* the kfifo, processes it by stripping protocol-specific padding bytes, and
|
||||||
* passes the clean MIDI data to the ALSA rawmidi subsystem.
|
* passes the clean MIDI data to the ALSA rawmidi subsystem.
|
||||||
*/
|
*/
|
||||||
static void tascam_midi_in_work_handler(struct work_struct *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);
|
struct tascam_card *tascam = container_of(work, struct tascam_card, midi_in_work);
|
||||||
u8 buf[MIDI_IN_BUF_SIZE];
|
u8 buf[MIDI_IN_BUF_SIZE];
|
||||||
unsigned int len;
|
u8 clean_buf[MIDI_IN_BUF_SIZE];
|
||||||
int i;
|
unsigned int len, clean_len;
|
||||||
|
|
||||||
if (!tascam->midi_in_substream)
|
if (!tascam->midi_in_substream)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (!kfifo_is_empty(&tascam->midi_in_fifo)) {
|
while (!kfifo_is_empty(&tascam->midi_in_fifo)) {
|
||||||
len = kfifo_out_spinlocked(&tascam->midi_in_fifo, buf, sizeof(buf),
|
len = kfifo_out_spinlocked(&tascam->midi_in_fifo,
|
||||||
&tascam->midi_in_lock);
|
buf, sizeof(buf), &tascam->midi_in_lock);
|
||||||
|
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!tascam->midi_in_substream)
|
if (!tascam->midi_in_substream)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (i = 0; i < len; ++i) {
|
clean_len = 0;
|
||||||
u8 byte = buf[i];
|
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 (clean_len > 0)
|
||||||
if (byte == 0xfd)
|
snd_rawmidi_receive(tascam->midi_in_substream, clean_buf, clean_len);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -75,7 +60,6 @@ void tascam_midi_in_urb_complete(struct urb *urb) {
|
||||||
urb->status != -ESHUTDOWN && urb->status != -EPROTO) {
|
urb->status != -ESHUTDOWN && urb->status != -EPROTO) {
|
||||||
dev_err_ratelimited(tascam->card->dev, "MIDI IN URB failed: status %d\n",
|
dev_err_ratelimited(tascam->card->dev, "MIDI IN URB failed: status %d\n",
|
||||||
urb->status);
|
urb->status);
|
||||||
mod_timer(&tascam->error_timer, jiffies + msecs_to_jiffies(50));
|
|
||||||
}
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
@ -199,7 +183,6 @@ void tascam_midi_out_urb_complete(struct urb *urb) {
|
||||||
urb->status != -ESHUTDOWN) {
|
urb->status != -ESHUTDOWN) {
|
||||||
dev_err_ratelimited(tascam->card->dev, "MIDI OUT URB failed: %d\n",
|
dev_err_ratelimited(tascam->card->dev, "MIDI OUT URB failed: %d\n",
|
||||||
urb->status);
|
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) {
|
static void tascam_midi_out_drain(struct snd_rawmidi_substream *substream) {
|
||||||
struct tascam_card *tascam = substream->rmidi->private_data;
|
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);
|
cancel_work_sync(&tascam->midi_out_work);
|
||||||
usb_kill_anchored_urbs(&tascam->midi_out_anchor);
|
usb_kill_anchored_urbs(&tascam->midi_out_anchor);
|
||||||
|
|
|
||||||
|
|
@ -16,52 +16,20 @@
|
||||||
*/
|
*/
|
||||||
static void fpoInitPattern(unsigned int size, unsigned int *pattern_array,
|
static void fpoInitPattern(unsigned int size, unsigned int *pattern_array,
|
||||||
unsigned int initial_value, int target_sum) {
|
unsigned int initial_value, int target_sum) {
|
||||||
unsigned int current_sum;
|
int diff, i;
|
||||||
int diff;
|
|
||||||
int abs_diff;
|
|
||||||
unsigned int stride;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
if (!size)
|
if (!size)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* 1. Initialize the array with the base value. */
|
for (i = 0; i < size; ++i)
|
||||||
current_sum = 0;
|
|
||||||
for (i = 0; i < size; ++i) {
|
|
||||||
pattern_array[i] = initial_value;
|
pattern_array[i] = initial_value;
|
||||||
}
|
|
||||||
current_sum = size * initial_value;
|
|
||||||
|
|
||||||
/* 2. Iteratively adjust until the sum is correct. */
|
diff = target_sum - (size * initial_value);
|
||||||
while (current_sum != target_sum) {
|
for (i = 0; i < abs(diff); ++i) {
|
||||||
diff = target_sum - current_sum;
|
if (diff > 0)
|
||||||
abs_diff = (diff > 0) ? diff : -diff;
|
pattern_array[i]++;
|
||||||
|
else
|
||||||
if (abs_diff == 0)
|
pattern_array[i]--;
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,9 @@ tascam_playback_pointer(struct snd_pcm_substream *substream) {
|
||||||
pos = tascam->playback_frames_consumed;
|
pos = tascam->playback_frames_consumed;
|
||||||
spin_unlock_irqrestore(&tascam->lock, flags);
|
spin_unlock_irqrestore(&tascam->lock, flags);
|
||||||
|
|
||||||
|
if (runtime->buffer_size == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
u64 remainder = do_div(pos, runtime->buffer_size);
|
u64 remainder = do_div(pos, runtime->buffer_size);
|
||||||
return runtime ? remainder : 0;
|
return runtime ? remainder : 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue