Fix problem about USB MIDI TX data format, that some devices only accept
a maximum of 4 bytes (one command) per short terminated USB transfer. Optimise the TX case by sending multiple USB frames. MFC after: 1 week
This commit is contained in:
parent
55d4d6f414
commit
910f1dcf71
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=223727
@ -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 @@ umidi_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user