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>
This commit is contained in:
parent
68f42be887
commit
f4227c4b01
|
@ -489,6 +489,7 @@ struct usbdev_ctrl *chipidea_init(device_descriptor_t *dd)
|
||||||
|
|
||||||
ctrl->poll = chipidea_poll;
|
ctrl->poll = chipidea_poll;
|
||||||
ctrl->add_gadget = udc_add_gadget;
|
ctrl->add_gadget = udc_add_gadget;
|
||||||
|
ctrl->add_strings = udc_add_strings;
|
||||||
ctrl->enqueue_packet = chipidea_enqueue_packet;
|
ctrl->enqueue_packet = chipidea_enqueue_packet;
|
||||||
ctrl->shutdown = chipidea_shutdown;
|
ctrl->shutdown = chipidea_shutdown;
|
||||||
ctrl->set_address = chipidea_set_address;
|
ctrl->set_address = chipidea_set_address;
|
||||||
|
|
|
@ -47,6 +47,18 @@
|
||||||
|
|
||||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
#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
|
/* determine if an additional zero length packet is necessary for
|
||||||
* a transfer */
|
* a transfer */
|
||||||
static unsigned int zlp(struct usbdev_ctrl *this, const int epnum,
|
static unsigned int zlp(struct usbdev_ctrl *this, const int epnum,
|
||||||
|
@ -301,6 +313,62 @@ static int setup_ep0(struct usbdev_ctrl *this, dev_req_t *dr)
|
||||||
this->enqueue_packet(this, 0, 0, NULL, 0, 0, 0);
|
this->enqueue_packet(this, 0, 0, NULL, 0, 0, 0);
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
} 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) &&
|
if ((dr->bmRequestType == 0x80) &&
|
||||||
(dr->bRequest == GET_DESCRIPTOR) &&
|
(dr->bRequest == GET_DESCRIPTOR) &&
|
||||||
((dr->wValue & 0xff00) == 0x0100)) {
|
((dr->wValue & 0xff00) == 0x0100)) {
|
||||||
|
|
|
@ -102,6 +102,22 @@ struct usbdev_ctrl {
|
||||||
void (*add_gadget)(struct usbdev_ctrl *,
|
void (*add_gadget)(struct usbdev_ctrl *,
|
||||||
struct usbdev_configuration *config);
|
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.
|
* Add packet to process by the controller.
|
||||||
* zlp: zero length packet, if such a termination is necessary
|
* zlp: zero length packet, if such a termination is necessary
|
||||||
|
@ -136,8 +152,13 @@ struct usbdev_ctrl {
|
||||||
void (*free_data)(void *);
|
void (*free_data)(void *);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define LANG_DE_DE 0x0407
|
||||||
|
#define LANG_EN_US 0x0409
|
||||||
|
|
||||||
void udc_add_gadget(struct usbdev_ctrl *this,
|
void udc_add_gadget(struct usbdev_ctrl *this,
|
||||||
struct usbdev_configuration *config);
|
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);
|
void udc_handle_setup(struct usbdev_ctrl *this, int ep, dev_req_t *dr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue