[coreboot-gerrit] New patch to review for coreboot: libpayload udc: add interface to add string descriptors

Patrick Georgi (pgeorgi@google.com) gerrit at coreboot.org
Mon Jun 22 19:25:32 CEST 2015


Patrick Georgi (pgeorgi at google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/10626

-gerrit

commit 415537fa31dfba34c25c0dcd7ff4b269847c1987
Author: Patrick Georgi <pgeorgi at google.com>
Date:   Thu Jun 18 00:15:00 2015 +0200

    libpayload udc: add interface to add string descriptors
    
    They're ASCII only, with only one language at a time,
    but they should be good enough to report device names and
    serial numbers.
    
    BUG=none
    BRANCH=none
    TEST=with depthcharge CL, check dmesg on the host device
    
    Change-Id: If888e05b2f372f7f0f43fadb108ca7ef4ed3b7c1
    Signed-off-by: Patrick Georgi <pgeorgi at chromium.org>
    Original-Commit-Id: f0bc4242057d3edc4f4796ebeed2d98d89d60a1d
    Original-Change-Id: Ibe42f1b49f412e5482cebb7ebe20f6034352fd12
    Original-Signed-off-by: Patrick Georgi <pgeorgi at google.com>
    Original-Reviewed-on: https://chromium-review.googlesource.com/278300
    Original-Tested-by: Patrick Georgi <pgeorgi at chromium.org>
    Original-Reviewed-by: Furquan Shaikh <furquan at chromium.org>
    Original-Commit-Queue: Patrick Georgi <pgeorgi at chromium.org>
---
 payloads/libpayload/drivers/udc/chipidea.c |  1 +
 payloads/libpayload/drivers/udc/udc.c      | 68 ++++++++++++++++++++++++++++++
 payloads/libpayload/include/udc/udc.h      | 21 +++++++++
 3 files changed, 90 insertions(+)

diff --git a/payloads/libpayload/drivers/udc/chipidea.c b/payloads/libpayload/drivers/udc/chipidea.c
index 8299a08..16a42e4 100644
--- a/payloads/libpayload/drivers/udc/chipidea.c
+++ b/payloads/libpayload/drivers/udc/chipidea.c
@@ -489,6 +489,7 @@ struct usbdev_ctrl *chipidea_init(device_descriptor_t *dd)
 
 	ctrl->poll = chipidea_poll;
 	ctrl->add_gadget = udc_add_gadget;
+	ctrl->add_strings = udc_add_strings;
 	ctrl->enqueue_packet = chipidea_enqueue_packet;
 	ctrl->shutdown = chipidea_shutdown;
 	ctrl->set_address = chipidea_set_address;
diff --git a/payloads/libpayload/drivers/udc/udc.c b/payloads/libpayload/drivers/udc/udc.c
index d0683ff..01aa4b1 100644
--- a/payloads/libpayload/drivers/udc/udc.c
+++ b/payloads/libpayload/drivers/udc/udc.c
@@ -47,6 +47,18 @@
 
 #define min(a, b) (((a) < (b)) ? (a) : (b))
 
+static unsigned short strings_lang_id = 0;
+static unsigned char strings_count = 0;
+static const char **strings;
+
+void udc_add_strings(unsigned short lang_id, unsigned char count,
+	const char **str)
+{
+	strings_lang_id = lang_id;
+	strings_count = count;
+	strings = str;
+}
+
 /* determine if an additional zero length packet is necessary for
  * a transfer */
 static unsigned int zlp(struct usbdev_ctrl *this, const int epnum,
@@ -303,6 +315,62 @@ static int setup_ep0(struct usbdev_ctrl *this, dev_req_t *dr)
 	} else
 	if ((dr->bmRequestType == 0x80) &&
 	    (dr->bRequest == GET_DESCRIPTOR) &&
+	    ((dr->wValue & 0xff00) == 0x0300)) {
+		int id = (dr->wValue & 0xff);
+		if (id == 0) {
+			if (strings_lang_id == 0)
+				return 0;
+
+			uint8_t *data = dma_malloc(4);
+			data[0] = 0x04; // length
+			data[1] = 0x03; // string descriptor
+			data[2] = strings_lang_id & 0xff;
+			data[3] = strings_lang_id >> 8;
+			/* data phase IN */
+			this->enqueue_packet(this, 0, 1,
+				data,
+				min(data[0], dr->wLength),
+				zlp(this, 0, data[0], dr->wLength),
+				1);
+
+			/* status phase OUT */
+			this->enqueue_packet(this, 0, 0, NULL, 0, 0, 0);
+		} else {
+			if (strings_lang_id == 0)
+				return 0;
+
+			int lang = dr->wIndex;
+			if (lang != strings_lang_id)
+				return 0;
+
+			if (id > strings_count)
+				return 0;
+
+			int s_len = strlen(strings[id]);
+			int d_len = s_len * 2;
+
+			uint8_t *data = dma_malloc(d_len + 2);
+			memset(data, 0, d_len);
+			data[0] = d_len + 2; // length
+			data[1] = 0x03; // string descriptor
+			int i;
+			for (i = 0; i < s_len; i++)
+				data[i * 2 + 2] = strings[id][i];
+
+			/* data phase IN */
+			this->enqueue_packet(this, 0, 1,
+				data,
+				min(d_len + 2, dr->wLength),
+				zlp(this, 0, d_len + 2, dr->wLength),
+				1);
+
+			/* status phase OUT */
+			this->enqueue_packet(this, 0, 0, NULL, 0, 0, 0);
+		}
+		return 1;
+	} else
+	if ((dr->bmRequestType == 0x80) &&
+	    (dr->bRequest == GET_DESCRIPTOR) &&
 	    ((dr->wValue & 0xff00) == 0x0100)) {
 		device_descriptor_t *dd = dma_malloc(sizeof(*dd));
 		memcpy(dd, &this->device_descriptor, sizeof(*dd));
diff --git a/payloads/libpayload/include/udc/udc.h b/payloads/libpayload/include/udc/udc.h
index 7987c51..99cbb1b 100644
--- a/payloads/libpayload/include/udc/udc.h
+++ b/payloads/libpayload/include/udc/udc.h
@@ -103,6 +103,22 @@ struct usbdev_ctrl {
 		struct usbdev_configuration *config);
 
 	/**
+	 * Add a set of strings to use for string descriptors.
+         *
+         * 's' must point to an array of strings of which the first
+         * element is unused, with at most 255 elements.
+         *
+         * 'm' is the size of 'strings' (ie. the index of the last entry).
+         *
+         * 'l' is the USB language code, of which some are defined below,
+         * eg. LANG_EN_US.
+	 *
+	 * For now, only one language is ever exposed: Calling add_strings overwrites
+         * older configuration.
+	 */
+	void (*add_strings)(unsigned short l, unsigned char m, const char **s);
+
+	/**
 	 * Add packet to process by the controller.
 	 * zlp: zero length packet, if such a termination is necessary
 	 * autofree: free data after use
@@ -136,8 +152,13 @@ struct usbdev_ctrl {
 	void (*free_data)(void *);
 };
 
+#define LANG_DE_DE 0x0407
+#define LANG_EN_US 0x0409
+
 void udc_add_gadget(struct usbdev_ctrl *this,
 	struct usbdev_configuration *config);
+void udc_add_strings(unsigned short id, unsigned char count,
+	const char *strings[]);
 void udc_handle_setup(struct usbdev_ctrl *this, int ep, dev_req_t *dr);
 
 #endif



More information about the coreboot-gerrit mailing list