diff options
author | Patrick Georgi <pgeorgi@google.com> | 2015-06-18 00:15:00 +0200 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2015-06-23 08:20:45 +0200 |
commit | f4227c4b01840c092b5431cbe6d92de282fe5628 (patch) | |
tree | 633273d321aa2cef3666f93fd39fe27ee11e671c /payloads/libpayload/drivers | |
parent | 68f42be887fa0d98400babf30c1738e580d05f67 (diff) | |
download | coreboot-f4227c4b01840c092b5431cbe6d92de282fe5628.tar.xz |
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@chromium.org>
Original-Commit-Id: f0bc4242057d3edc4f4796ebeed2d98d89d60a1d
Original-Change-Id: Ibe42f1b49f412e5482cebb7ebe20f6034352fd12
Original-Signed-off-by: Patrick Georgi <pgeorgi@google.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/278300
Original-Tested-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Original-Commit-Queue: Patrick Georgi <pgeorgi@chromium.org>
Reviewed-on: http://review.coreboot.org/10626
Tested-by: build bot (Jenkins)
Reviewed-by: Furquan Shaikh <furquan@google.com>
Diffstat (limited to 'payloads/libpayload/drivers')
-rw-r--r-- | payloads/libpayload/drivers/udc/chipidea.c | 1 | ||||
-rw-r--r-- | payloads/libpayload/drivers/udc/udc.c | 68 |
2 files changed, 69 insertions, 0 deletions
diff --git a/payloads/libpayload/drivers/udc/chipidea.c b/payloads/libpayload/drivers/udc/chipidea.c index 8299a08859..16a42e45a3 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 d0683ff328..01aa4b1003 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)); |