diff options
-rw-r--r-- | sys/dev/sound/usb/uaudio.c | 53 |
1 files changed, 30 insertions, 23 deletions
diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c index f40ada7..59fc4f8 100644 --- a/sys/dev/sound/usb/uaudio.c +++ b/sys/dev/sound/usb/uaudio.c @@ -192,7 +192,8 @@ struct uaudio_chan { }; #define UMIDI_CABLES_MAX 16 /* units */ -#define UMIDI_BULK_SIZE 1024 /* bytes */ +#define UMIDI_TX_FRAMES 64 /* units */ +#define UMIDI_TX_BUFFER (UMIDI_TX_FRAMES * 4) /* bytes */ enum { UMIDI_TX_TRANSFER, @@ -497,8 +498,8 @@ static const struct usb_config .type = UE_BULK, .endpoint = UE_ADDR_ANY, .direction = UE_DIR_OUT, - .bufsize = UMIDI_BULK_SIZE, - .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, + .bufsize = UMIDI_TX_BUFFER, + .frames = UMIDI_TX_FRAMES, .callback = &umidi_bulk_write_callback, }, @@ -507,7 +508,7 @@ static const struct usb_config .endpoint = UE_ADDR_ANY, .direction = UE_DIR_IN, .bufsize = 4, /* bytes */ - .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1,}, + .flags = {.short_xfer_ok = 1,.proxy_buffer = 1,}, .callback = &umidi_bulk_read_callback, }, }; @@ -3541,7 +3542,7 @@ umidi_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) struct umidi_sub_chan *sub; struct usb_page_cache *pc; uint32_t actlen; - uint16_t total_length; + uint16_t nframes; uint8_t buf; uint8_t start_cable; uint8_t tr_any; @@ -3549,6 +3550,10 @@ umidi_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) usbd_xfer_status(xfer, &len, NULL, NULL, NULL); + /* + * NOTE: Some MIDI devices only accept 4 bytes of data per + * short terminated USB transfer. + */ switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: DPRINTF("actlen=%d bytes\n", len); @@ -3557,10 +3562,9 @@ umidi_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) tr_setup: DPRINTF("start\n"); - total_length = 0; /* reset */ + nframes = 0; /* reset */ start_cable = chan->curr_cable; tr_any = 0; - pc = usbd_xfer_get_frame(xfer, 0); while (1) { @@ -3569,51 +3573,54 @@ tr_setup: sub = &chan->sub[chan->curr_cable]; if (sub->write_open) { - usb_fifo_get_data(sub->fifo.fp[USB_FIFO_TX], - pc, total_length, 1, &actlen, 0); + usb_fifo_get_data_linear(sub->fifo.fp[USB_FIFO_TX], + &buf, 1, &actlen, 0); } else { actlen = 0; } if (actlen) { - usbd_copy_out(pc, total_length, &buf, 1); tr_any = 1; - DPRINTF("byte=0x%02x\n", buf); + DPRINTF("byte=0x%02x from FIFO %u\n", buf, + (unsigned int)chan->curr_cable); if (umidi_convert_to_usb(sub, chan->curr_cable, buf)) { - DPRINTF("sub= %02x %02x %02x %02x\n", + DPRINTF("sub=0x%02x 0x%02x 0x%02x 0x%02x\n", sub->temp_cmd[0], sub->temp_cmd[1], sub->temp_cmd[2], sub->temp_cmd[3]); - usbd_copy_in(pc, total_length, - sub->temp_cmd, 4); + usbd_xfer_set_frame_offset(xfer, 4 * nframes, nframes); + usbd_xfer_set_frame_len(xfer, nframes, 4); - total_length += 4; + pc = usbd_xfer_get_frame(xfer, nframes); - if (total_length >= UMIDI_BULK_SIZE) { + usbd_copy_in(pc, 0, sub->temp_cmd, 4); + + nframes++; + if (nframes >= UMIDI_TX_FRAMES) break; - } } else { continue; } } + chan->curr_cable++; - if (chan->curr_cable >= chan->max_cable) { + if (chan->curr_cable >= chan->max_cable) chan->curr_cable = 0; - } + if (chan->curr_cable == start_cable) { - if (tr_any == 0) { + if (tr_any == 0) break; - } tr_any = 0; } } - if (total_length) { - usbd_xfer_set_frame_len(xfer, 0, total_length); + if (nframes > 0) { + DPRINTF("Transferring %d frames\n", (int)nframes); + usbd_xfer_set_frames(xfer, nframes); usbd_transfer_submit(xfer); } break; |