Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1450246 > unrolled thread

[PATCH 0/4] MIDI Function improvements

Started by"Felipe F. Tonello" <eu@felipetonello.com>
First post2016-07-26 01:20 +0200
Last post2016-08-10 21:00 +0200
Articles 7 — 3 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH 0/4] MIDI Function improvements "Felipe F. Tonello" <eu@felipetonello.com> - 2016-07-26 01:20 +0200
    [PATCH 2/4] usb: gadget: f_midi: defaults buflen sizes to 512 "Felipe F. Tonello" <eu@felipetonello.com> - 2016-07-26 01:20 +0200
      Re: [PATCH 2/4] usb: gadget: f_midi: defaults buflen sizes to 512 Felipe Balbi <balbi@kernel.org> - 2016-08-10 21:40 +0200
    [PATCH 3/4] usb: gadget: f_midi: refactor state machine "Felipe F. Tonello" <eu@felipetonello.com> - 2016-07-26 01:20 +0200
    [PATCH 1/4] usb: gadget: f_midi: fixed endianness when using wMaxPacketSize "Felipe F. Tonello" <eu@felipetonello.com> - 2016-07-26 01:20 +0200
      Re: [PATCH 1/4] usb: gadget: f_midi: fixed endianness when using wMaxPacketSize Baolin Wang <baolin.wang@linaro.org> - 2016-07-26 04:00 +0200
        Re: [PATCH 1/4] usb: gadget: f_midi: fixed endianness when using wMaxPacketSize Felipe Balbi <balbi@kernel.org> - 2016-08-10 21:00 +0200

#1450246 — [PATCH 0/4] MIDI Function improvements

From"Felipe F. Tonello" <eu@felipetonello.com>
Date2016-07-26 01:20 +0200
Subject[PATCH 0/4] MIDI Function improvements
Message-ID<rYXkd-2G4-5@gated-at.bofh.it>
Here follows few improvements on the MIDI driver. Those improvements
have been tested for months now, that's why I feel confident to submit
these patches now.

Patches number 1 and 4 contain bug fixes.
Patches number 2 and 3 are not critical but it improves the code and
default configuration, which is nice to have.

Felipe F. Tonello (4):
  usb: gadget: f_midi: fixed endianness when using wMaxPacketSize
  usb: gadget: f_midi: defaults buflen sizes to 512
  usb: gadget: f_midi: refactor state machine
  usb: gadget: f_midi: drop substreams when disabling endpoint

 drivers/usb/gadget/function/f_midi.c | 229 ++++++++++++++++++++++-------------
 drivers/usb/gadget/legacy/gmidi.c    |   2 +-
 2 files changed, 144 insertions(+), 87 deletions(-)

-- 
2.9.2

[toc] | [next] | [standalone]


#1450248 — [PATCH 2/4] usb: gadget: f_midi: defaults buflen sizes to 512

From"Felipe F. Tonello" <eu@felipetonello.com>
Date2016-07-26 01:20 +0200
Subject[PATCH 2/4] usb: gadget: f_midi: defaults buflen sizes to 512
Message-ID<rYXkd-2G4-13@gated-at.bofh.it>
In reply to#1450246
512 is the value used by wMaxPacketSize, as specified by the USB Spec. This
makes sure this driver uses, by default, the most optimal value for IN and OUT
endpoint requests.

Signed-off-by: Felipe F. Tonello <eu@felipetonello.com>
---
 drivers/usb/gadget/function/f_midi.c | 2 +-
 drivers/usb/gadget/legacy/gmidi.c    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c
index a83d852b1da5..dd5cca6eae7c 100644
--- a/drivers/usb/gadget/function/f_midi.c
+++ b/drivers/usb/gadget/function/f_midi.c
@@ -1123,7 +1123,7 @@ static struct usb_function_instance *f_midi_alloc_inst(void)
 	opts->func_inst.free_func_inst = f_midi_free_inst;
 	opts->index = SNDRV_DEFAULT_IDX1;
 	opts->id = SNDRV_DEFAULT_STR1;
-	opts->buflen = 256;
+	opts->buflen = 512;
 	opts->qlen = 32;
 	opts->in_ports = 1;
 	opts->out_ports = 1;
diff --git a/drivers/usb/gadget/legacy/gmidi.c b/drivers/usb/gadget/legacy/gmidi.c
index fc2ac150f5ff..0bf39c3ccdb1 100644
--- a/drivers/usb/gadget/legacy/gmidi.c
+++ b/drivers/usb/gadget/legacy/gmidi.c
@@ -47,7 +47,7 @@ static char *id = SNDRV_DEFAULT_STR1;
 module_param(id, charp, S_IRUGO);
 MODULE_PARM_DESC(id, "ID string for the USB MIDI Gadget adapter.");
 
-static unsigned int buflen = 256;
+static unsigned int buflen = 512;
 module_param(buflen, uint, S_IRUGO);
 MODULE_PARM_DESC(buflen, "MIDI buffer length");
 
-- 
2.9.2

[toc] | [prev] | [next] | [standalone]


#1459678 — Re: [PATCH 2/4] usb: gadget: f_midi: defaults buflen sizes to 512

FromFelipe Balbi <balbi@kernel.org>
Date2016-08-10 21:40 +0200
SubjectRe: [PATCH 2/4] usb: gadget: f_midi: defaults buflen sizes to 512
Message-ID<s4Hw6-YV-7@gated-at.bofh.it>
In reply to#1450248

[Multipart message — attachments visible in raw view] — view raw

Hi,

"Felipe F. Tonello" <eu@felipetonello.com> writes:
> 512 is the value used by wMaxPacketSize, as specified by the USB Spec. This

this is only true for HS :-) FS and SS use different sizes. Do you want
to use 1024 (SS maxp) by default instead? Then all speeds will have this
working out just fine.

-- 
balbi

[toc] | [prev] | [next] | [standalone]


#1450249 — [PATCH 3/4] usb: gadget: f_midi: refactor state machine

From"Felipe F. Tonello" <eu@felipetonello.com>
Date2016-07-26 01:20 +0200
Subject[PATCH 3/4] usb: gadget: f_midi: refactor state machine
Message-ID<rYXkd-2G4-15@gated-at.bofh.it>
In reply to#1450246
This refactor results in a cleaner state machine code and promotes
consistency, readability, and maintanability of this driver.

This refactor state machine was well tested and it is currently running in
production code and devices.

Signed-off-by: Felipe F. Tonello <eu@felipetonello.com>
---
 drivers/usb/gadget/function/f_midi.c | 204 ++++++++++++++++++++++-------------
 1 file changed, 129 insertions(+), 75 deletions(-)

diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c
index dd5cca6eae7c..49328f208a63 100644
--- a/drivers/usb/gadget/function/f_midi.c
+++ b/drivers/usb/gadget/function/f_midi.c
@@ -51,6 +51,19 @@ static const char f_midi_longname[] = "MIDI Gadget";
  */
 #define MAX_PORTS 16
 
+/* MIDI message states */
+enum {
+	STATE_INITIAL = 0,	/* pseudo state */
+	STATE_1PARAM,
+	STATE_2PARAM_1,
+	STATE_2PARAM_2,
+	STATE_SYSEX_0,
+	STATE_SYSEX_1,
+	STATE_SYSEX_2,
+	STATE_REAL_TIME,
+	STATE_FINISHED,		/* pseudo state */
+};
+
 /*
  * This is a gadget, and the IN/OUT naming is from the host's perspective.
  * USB -> OUT endpoint -> rawmidi
@@ -61,13 +74,6 @@ struct gmidi_in_port {
 	int active;
 	uint8_t cable;
 	uint8_t state;
-#define STATE_UNKNOWN	0
-#define STATE_1PARAM	1
-#define STATE_2PARAM_1	2
-#define STATE_2PARAM_2	3
-#define STATE_SYSEX_0	4
-#define STATE_SYSEX_1	5
-#define STATE_SYSEX_2	6
 	uint8_t data[2];
 };
 
@@ -404,118 +410,166 @@ static int f_midi_snd_free(struct snd_device *device)
 	return 0;
 }
 
-static void f_midi_transmit_packet(struct usb_request *req, uint8_t p0,
-					uint8_t p1, uint8_t p2, uint8_t p3)
-{
-	unsigned length = req->length;
-	u8 *buf = (u8 *)req->buf + length;
-
-	buf[0] = p0;
-	buf[1] = p1;
-	buf[2] = p2;
-	buf[3] = p3;
-	req->length = length + 4;
-}
-
 /*
  * Converts MIDI commands to USB MIDI packets.
  */
 static void f_midi_transmit_byte(struct usb_request *req,
 				 struct gmidi_in_port *port, uint8_t b)
 {
-	uint8_t p0 = port->cable << 4;
+	uint8_t p[4] = { port->cable << 4, 0, 0, 0 };
+	uint8_t next_state = STATE_INITIAL;
+
+	switch (b) {
+	case 0xf8 ... 0xff:
+		/* System Real-Time Messages */
+		p[0] |= 0x0f;
+		p[1] = b;
+		next_state = port->state;
+		port->state = STATE_REAL_TIME;
+		break;
+
+	case 0xf7:
+		/* End of SysEx */
+		switch (port->state) {
+		case STATE_SYSEX_0:
+			p[0] |= 0x05;
+			p[1] = 0xf7;
+			next_state = STATE_FINISHED;
+			break;
+		case STATE_SYSEX_1:
+			p[0] |= 0x06;
+			p[1] = port->data[0];
+			p[2] = 0xf7;
+			next_state = STATE_FINISHED;
+			break;
+		case STATE_SYSEX_2:
+			p[0] |= 0x07;
+			p[1] = port->data[0];
+			p[2] = port->data[1];
+			p[3] = 0xf7;
+			next_state = STATE_FINISHED;
+			break;
+		default:
+			/* Ignore byte */
+			next_state = port->state;
+			port->state = STATE_INITIAL;
+		}
+		break;
 
-	if (b >= 0xf8) {
-		f_midi_transmit_packet(req, p0 | 0x0f, b, 0, 0);
-	} else if (b >= 0xf0) {
+	case 0xf0 ... 0xf6:
+		/* System Common Messages */
+		port->data[0] = port->data[1] = 0;
+		port->state = STATE_INITIAL;
 		switch (b) {
 		case 0xf0:
 			port->data[0] = b;
-			port->state = STATE_SYSEX_1;
+			port->data[1] = 0;
+			next_state = STATE_SYSEX_1;
 			break;
 		case 0xf1:
 		case 0xf3:
 			port->data[0] = b;
-			port->state = STATE_1PARAM;
+			next_state = STATE_1PARAM;
 			break;
 		case 0xf2:
 			port->data[0] = b;
-			port->state = STATE_2PARAM_1;
+			next_state = STATE_2PARAM_1;
 			break;
 		case 0xf4:
 		case 0xf5:
-			port->state = STATE_UNKNOWN;
+			next_state = STATE_INITIAL;
 			break;
 		case 0xf6:
-			f_midi_transmit_packet(req, p0 | 0x05, 0xf6, 0, 0);
-			port->state = STATE_UNKNOWN;
-			break;
-		case 0xf7:
-			switch (port->state) {
-			case STATE_SYSEX_0:
-				f_midi_transmit_packet(req,
-					p0 | 0x05, 0xf7, 0, 0);
-				break;
-			case STATE_SYSEX_1:
-				f_midi_transmit_packet(req,
-					p0 | 0x06, port->data[0], 0xf7, 0);
-				break;
-			case STATE_SYSEX_2:
-				f_midi_transmit_packet(req,
-					p0 | 0x07, port->data[0],
-					port->data[1], 0xf7);
-				break;
-			}
-			port->state = STATE_UNKNOWN;
+			p[0] |= 0x05;
+			p[1] = 0xf6;
+			next_state = STATE_FINISHED;
 			break;
 		}
-	} else if (b >= 0x80) {
+		break;
+
+	case 0x80 ... 0xef:
+		/*
+		 * Channel Voice Messages, Channel Mode Messages
+		 * and Control Change Messages.
+		 */
 		port->data[0] = b;
+		port->data[1] = 0;
+		port->state = STATE_INITIAL;
 		if (b >= 0xc0 && b <= 0xdf)
-			port->state = STATE_1PARAM;
+			next_state = STATE_1PARAM;
 		else
-			port->state = STATE_2PARAM_1;
-	} else { /* b < 0x80 */
+			next_state = STATE_2PARAM_1;
+		break;
+
+	case 0x00 ... 0x7f:
+		/* Message parameters */
 		switch (port->state) {
 		case STATE_1PARAM:
-			if (port->data[0] < 0xf0) {
-				p0 |= port->data[0] >> 4;
-			} else {
-				p0 |= 0x02;
-				port->state = STATE_UNKNOWN;
-			}
-			f_midi_transmit_packet(req, p0, port->data[0], b, 0);
+			if (port->data[0] < 0xf0)
+				p[0] |= port->data[0] >> 4;
+			else
+				p[0] |= 0x02;
+
+			p[1] = port->data[0];
+			p[2] = b;
+			/* This is to allow Running State Messages */
+			next_state = STATE_1PARAM;
 			break;
 		case STATE_2PARAM_1:
 			port->data[1] = b;
-			port->state = STATE_2PARAM_2;
+			next_state = STATE_2PARAM_2;
 			break;
 		case STATE_2PARAM_2:
-			if (port->data[0] < 0xf0) {
-				p0 |= port->data[0] >> 4;
-				port->state = STATE_2PARAM_1;
-			} else {
-				p0 |= 0x03;
-				port->state = STATE_UNKNOWN;
-			}
-			f_midi_transmit_packet(req,
-				p0, port->data[0], port->data[1], b);
+			if (port->data[0] < 0xf0)
+				p[0] |= port->data[0] >> 4;
+			else
+				p[0] |= 0x03;
+
+			p[1] = port->data[0];
+			p[2] = port->data[1];
+			p[3] = b;
+			/* This is to allow Running State Messages */
+			next_state = STATE_2PARAM_1;
 			break;
 		case STATE_SYSEX_0:
 			port->data[0] = b;
-			port->state = STATE_SYSEX_1;
+			next_state = STATE_SYSEX_1;
 			break;
 		case STATE_SYSEX_1:
 			port->data[1] = b;
-			port->state = STATE_SYSEX_2;
+			next_state = STATE_SYSEX_2;
 			break;
 		case STATE_SYSEX_2:
-			f_midi_transmit_packet(req,
-				p0 | 0x04, port->data[0], port->data[1], b);
-			port->state = STATE_SYSEX_0;
+			p[0] |= 0x04;
+			p[1] = port->data[0];
+			p[2] = port->data[1];
+			p[3] = b;
+			next_state = STATE_SYSEX_0;
 			break;
 		}
+		break;
+	}
+
+	/* States where we have to write into the USB request */
+	if (next_state == STATE_FINISHED ||
+	    port->state == STATE_SYSEX_2 ||
+	    port->state == STATE_1PARAM ||
+	    port->state == STATE_2PARAM_2 ||
+	    port->state == STATE_REAL_TIME) {
+
+		unsigned int length = req->length;
+		u8 *buf = (u8 *)req->buf + length;
+
+		memcpy(buf, p, sizeof(p));
+		req->length = length + sizeof(p);
+
+		if (next_state == STATE_FINISHED) {
+			next_state = STATE_INITIAL;
+			port->data[0] = port->data[1] = 0;
+		}
 	}
+
+	port->state = next_state;
 }
 
 static void f_midi_drop_out_substreams(struct f_midi *midi)
@@ -642,7 +696,7 @@ static int f_midi_in_open(struct snd_rawmidi_substream *substream)
 	VDBG(midi, "%s()\n", __func__);
 	port = midi->in_ports_array + substream->number;
 	port->substream = substream;
-	port->state = STATE_UNKNOWN;
+	port->state = STATE_INITIAL;
 	return 0;
 }
 
-- 
2.9.2

[toc] | [prev] | [next] | [standalone]


#1450251 — [PATCH 1/4] usb: gadget: f_midi: fixed endianness when using wMaxPacketSize

From"Felipe F. Tonello" <eu@felipetonello.com>
Date2016-07-26 01:20 +0200
Subject[PATCH 1/4] usb: gadget: f_midi: fixed endianness when using wMaxPacketSize
Message-ID<rYXkd-2G4-17@gated-at.bofh.it>
In reply to#1450246
USB spec specifies wMaxPacketSize to be little endian (as other properties),
so when using this variable in the driver we should convert to the current
CPU endianness if necessary.

Signed-off-by: Felipe F. Tonello <eu@felipetonello.com>
---
 drivers/usb/gadget/function/f_midi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c
index 58fc199a18ec..a83d852b1da5 100644
--- a/drivers/usb/gadget/function/f_midi.c
+++ b/drivers/usb/gadget/function/f_midi.c
@@ -362,7 +362,7 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 		struct usb_request *req =
 			midi_alloc_ep_req(midi->out_ep,
 				max_t(unsigned, midi->buflen,
-					bulk_out_desc.wMaxPacketSize));
+					le16_to_cpu(bulk_out_desc.wMaxPacketSize)));
 		if (req == NULL)
 			return -ENOMEM;
 
-- 
2.9.2

[toc] | [prev] | [next] | [standalone]


#1450318 — Re: [PATCH 1/4] usb: gadget: f_midi: fixed endianness when using wMaxPacketSize

FromBaolin Wang <baolin.wang@linaro.org>
Date2016-07-26 04:00 +0200
SubjectRe: [PATCH 1/4] usb: gadget: f_midi: fixed endianness when using wMaxPacketSize
Message-ID<rYZP3-459-9@gated-at.bofh.it>
In reply to#1450251
Hi,

On 26 July 2016 at 07:15, Felipe F. Tonello <eu@felipetonello.com> wrote:
> USB spec specifies wMaxPacketSize to be little endian (as other properties),
> so when using this variable in the driver we should convert to the current
> CPU endianness if necessary.
>
> Signed-off-by: Felipe F. Tonello <eu@felipetonello.com>
> ---
>  drivers/usb/gadget/function/f_midi.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c
> index 58fc199a18ec..a83d852b1da5 100644
> --- a/drivers/usb/gadget/function/f_midi.c
> +++ b/drivers/usb/gadget/function/f_midi.c
> @@ -362,7 +362,7 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
>                 struct usb_request *req =
>                         midi_alloc_ep_req(midi->out_ep,
>                                 max_t(unsigned, midi->buflen,
> -                                       bulk_out_desc.wMaxPacketSize));
> +                                       le16_to_cpu(bulk_out_desc.wMaxPacketSize)));

I think here we should use usb_ep_align_maybe() function instead of
max_t() to handle 'quirk_ep_out_aligned_size' quirk, please see the
patch I've send out: https://lkml.org/lkml/2016/7/12/106

>                 if (req == NULL)
>                         return -ENOMEM;
>
> --
> 2.9.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Baolin.wang
Best Regards

[toc] | [prev] | [next] | [standalone]


#1459550 — Re: [PATCH 1/4] usb: gadget: f_midi: fixed endianness when using wMaxPacketSize

FromFelipe Balbi <balbi@kernel.org>
Date2016-08-10 21:00 +0200
SubjectRe: [PATCH 1/4] usb: gadget: f_midi: fixed endianness when using wMaxPacketSize
Message-ID<s4GTp-n4-67@gated-at.bofh.it>
In reply to#1450318

[Multipart message — attachments visible in raw view] — view raw

Hi,

Baolin Wang <baolin.wang@linaro.org> writes:
> On 26 July 2016 at 07:15, Felipe F. Tonello <eu@felipetonello.com> wrote:
>> USB spec specifies wMaxPacketSize to be little endian (as other properties),
>> so when using this variable in the driver we should convert to the current
>> CPU endianness if necessary.
>>
>> Signed-off-by: Felipe F. Tonello <eu@felipetonello.com>
>> ---
>>  drivers/usb/gadget/function/f_midi.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c
>> index 58fc199a18ec..a83d852b1da5 100644
>> --- a/drivers/usb/gadget/function/f_midi.c
>> +++ b/drivers/usb/gadget/function/f_midi.c
>> @@ -362,7 +362,7 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
>>                 struct usb_request *req =
>>                         midi_alloc_ep_req(midi->out_ep,
>>                                 max_t(unsigned, midi->buflen,
>> -                                       bulk_out_desc.wMaxPacketSize));
>> +                                       le16_to_cpu(bulk_out_desc.wMaxPacketSize)));
>
> I think here we should use usb_ep_align_maybe() function instead of
> max_t() to handle 'quirk_ep_out_aligned_size' quirk, please see the
> patch I've send out: https://lkml.org/lkml/2016/7/12/106

agree, if usb_ep_align_maybe() has a bug with endianness, let's fix it
since there are other gadgets using usb_ep_align_maybe()

-- 
balbi

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web