midi parsing fixes

This commit is contained in:
Šerif Rami 2025-08-08 16:33:26 +02:00
parent f4b17d24c8
commit 196cd55787
5 changed files with 50 additions and 62 deletions

View File

@ -320,26 +320,25 @@ static void tascam_card_private_free(struct snd_card *card) {
* *
* Return: 0 on success. * Return: 0 on success.
*/ */
static int tascam_suspend(struct usb_interface *intf, pm_message_t message) static int tascam_suspend(struct usb_interface *intf, pm_message_t message) {
{ struct tascam_card *tascam = usb_get_intfdata(intf);
struct tascam_card *tascam = usb_get_intfdata(intf);
if (!tascam) if (!tascam)
return 0; return 0;
snd_pcm_suspend_all(tascam->pcm); snd_pcm_suspend_all(tascam->pcm);
cancel_work_sync(&tascam->stop_work); cancel_work_sync(&tascam->stop_work);
cancel_work_sync(&tascam->capture_work); cancel_work_sync(&tascam->capture_work);
cancel_work_sync(&tascam->midi_in_work); cancel_work_sync(&tascam->midi_in_work);
cancel_work_sync(&tascam->midi_out_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);
return 0; return 0;
} }
/** /**
@ -458,7 +457,6 @@ static int tascam_probe(struct usb_interface *intf,
return -ENODEV; return -ENODEV;
} }
err = usb_set_interface(dev, 0, 1); err = usb_set_interface(dev, 0, 1);
if (err < 0) { if (err < 0) {
dev_err(&dev->dev, "Failed to set alt setting 1 on interface 0: %d\n", err); dev_err(&dev->dev, "Failed to set alt setting 1 on interface 0: %d\n", err);

View File

@ -196,7 +196,8 @@ void tascam_capture_work_handler(struct work_struct *work) {
memcpy(raw_block, tascam->capture_ring_buffer + read_ptr, memcpy(raw_block, tascam->capture_ring_buffer + read_ptr,
RAW_BYTES_PER_DECODE_BLOCK); RAW_BYTES_PER_DECODE_BLOCK);
} else { } else {
memcpy(raw_block, tascam->capture_ring_buffer + read_ptr, bytes_to_end); memcpy(raw_block, tascam->capture_ring_buffer + read_ptr,
bytes_to_end);
memcpy(raw_block + bytes_to_end, tascam->capture_ring_buffer, memcpy(raw_block + bytes_to_end, tascam->capture_ring_buffer,
RAW_BYTES_PER_DECODE_BLOCK - bytes_to_end); RAW_BYTES_PER_DECODE_BLOCK - bytes_to_end);
} }

View File

@ -11,36 +11,27 @@
* 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 =
struct tascam_card *tascam = container_of(work, struct tascam_card, midi_in_work); container_of(work, struct tascam_card, midi_in_work);
u8 buf[MIDI_IN_BUF_SIZE]; u8 buf[9];
u8 clean_buf[MIDI_IN_BUF_SIZE]; u8 clean_buf[8];
unsigned int len, clean_len; unsigned int count, clean_count;
if (!tascam->midi_in_substream) if (!tascam->midi_in_substream)
return; return;
while (!kfifo_is_empty(&tascam->midi_in_fifo)) { while (kfifo_out_spinlocked(&tascam->midi_in_fifo, buf, sizeof(buf),
len = kfifo_out_spinlocked(&tascam->midi_in_fifo, &tascam->midi_in_lock) == sizeof(buf)) {
buf, sizeof(buf), &tascam->midi_in_lock); clean_count = 0;
for (count = 0; count < 8; ++count) {
if (buf[count] != 0xfd)
clean_buf[clean_count++] = buf[count];
}
if (len == 0) if (clean_count > 0)
continue; snd_rawmidi_receive(tascam->midi_in_substream, clean_buf, clean_count);
}
if (!tascam->midi_in_substream)
continue;
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];
}
if (clean_len > 0)
snd_rawmidi_receive(tascam->midi_in_substream, clean_buf, clean_len);
}
} }
/** /**
@ -327,13 +318,13 @@ static void tascam_midi_out_drain(struct snd_rawmidi_substream *substream) {
while (in_flight) { while (in_flight) {
in_flight = false; in_flight = false;
for (int i = 0; i < NUM_MIDI_OUT_URBS; i++) { for (int i = 0; i < NUM_MIDI_OUT_URBS; i++) {
if (test_bit(i, &tascam->midi_out_urbs_in_flight)) { if (test_bit(i, &tascam->midi_out_urbs_in_flight)) {
in_flight = true; in_flight = true;
break; break;
} }
} }
if (in_flight) if (in_flight)
schedule_timeout_uninterruptible(1); schedule_timeout_uninterruptible(1);
} }
cancel_work_sync(&tascam->midi_out_work); cancel_work_sync(&tascam->midi_out_work);

View File

@ -413,4 +413,3 @@ int tascam_init_pcm(struct snd_pcm *pcm) {
return 0; return 0;
} }

View File

@ -187,9 +187,8 @@ void playback_urb_complete(struct urb *urb) {
size_t bytes_for_packet; size_t bytes_for_packet;
if (tascam->feedback_synced) { if (tascam->feedback_synced) {
frames_for_packet = frames_for_packet = tascam->feedback_accumulator_pattern
tascam->feedback_accumulator_pattern [tascam->feedback_pattern_out_idx];
[tascam->feedback_pattern_out_idx];
tascam->feedback_pattern_out_idx = tascam->feedback_pattern_out_idx =
(tascam->feedback_pattern_out_idx + 1) % FEEDBACK_ACCUMULATOR_SIZE; (tascam->feedback_pattern_out_idx + 1) % FEEDBACK_ACCUMULATOR_SIZE;
} else { } else {
@ -328,8 +327,8 @@ void feedback_urb_complete(struct urb *urb) {
int i; int i;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
unsigned int in_idx = (tascam->feedback_pattern_in_idx + i) % unsigned int in_idx =
FEEDBACK_ACCUMULATOR_SIZE; (tascam->feedback_pattern_in_idx + i) % FEEDBACK_ACCUMULATOR_SIZE;
tascam->feedback_accumulator_pattern[in_idx] = pattern[i]; tascam->feedback_accumulator_pattern[in_idx] = pattern[i];
total_frames_in_urb += pattern[i]; total_frames_in_urb += pattern[i];
@ -353,8 +352,8 @@ void feedback_urb_complete(struct urb *urb) {
} }
} }
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
unsigned int in_idx = (tascam->feedback_pattern_in_idx + i) % unsigned int in_idx =
FEEDBACK_ACCUMULATOR_SIZE; (tascam->feedback_pattern_in_idx + i) % FEEDBACK_ACCUMULATOR_SIZE;
tascam->feedback_accumulator_pattern[in_idx] = nominal_frames; tascam->feedback_accumulator_pattern[in_idx] = nominal_frames;
total_frames_in_urb += nominal_frames; total_frames_in_urb += nominal_frames;
@ -388,8 +387,8 @@ void feedback_urb_complete(struct urb *urb) {
} }
if (playback_rt->period_size > 0) { if (playback_rt->period_size > 0) {
u64 current_period = div_u64(tascam->playback_frames_consumed, u64 current_period =
playback_rt->period_size); div_u64(tascam->playback_frames_consumed, playback_rt->period_size);
if (current_period > tascam->last_period_pos) { if (current_period > tascam->last_period_pos) {
tascam->last_period_pos = current_period; tascam->last_period_pos = current_period;
@ -399,8 +398,8 @@ void feedback_urb_complete(struct urb *urb) {
if (atomic_read(&tascam->capture_active) && capture_rt && if (atomic_read(&tascam->capture_active) && capture_rt &&
capture_rt->period_size > 0) { capture_rt->period_size > 0) {
u64 current_capture_period = div_u64(tascam->capture_frames_processed, u64 current_capture_period =
capture_rt->period_size); div_u64(tascam->capture_frames_processed, capture_rt->period_size);
if (current_capture_period > tascam->last_capture_period_pos) { if (current_capture_period > tascam->last_capture_period_pos) {
tascam->last_capture_period_pos = current_capture_period; tascam->last_capture_period_pos = current_capture_period;