svn commit: r223727 - head/sys/dev/sound/usb

Hans Petter Selasky hselasky at FreeBSD.org
Sat Jul 2 20:26:38 UTC 2011


Author: hselasky
Date: Sat Jul  2 20:26:37 2011
New Revision: 223727
URL: http://svn.freebsd.org/changeset/base/223727

Log:
  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

Modified:
  head/sys/dev/sound/usb/uaudio.c

Modified: head/sys/dev/sound/usb/uaudio.c
==============================================================================
--- head/sys/dev/sound/usb/uaudio.c	Sat Jul  2 20:14:40 2011	(r223726)
+++ head/sys/dev/sound/usb/uaudio.c	Sat Jul  2 20:26:37 2011	(r223727)
@@ -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_xfe
 	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_xfe
 
 	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_xfe
 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;


More information about the svn-src-head mailing list