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:
Hans Petter Selasky 2011-07-02 20:26:37 +00:00
parent 55d4d6f414
commit 910f1dcf71
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=223727

View File

@ -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;