USB core updated for reentrance based on Christian Cier-Zniewski's branch

This commit is contained in:
Jason Kotzin
2012-08-16 18:50:38 -07:00
parent 4958fae906
commit 34beeae925
27 changed files with 1496 additions and 772 deletions

View File

@@ -21,15 +21,18 @@
#include <libopencm3/usb/usbd.h>
#include "usb_private.h"
void usbd_register_set_config_callback(void (*callback)(u16 wValue))
void usbd_register_set_config_callback(usbd_device *usbd_dev,
void (*callback)(usbd_device *usbd_dev,
u16 wValue))
{
_usbd_device.user_callback_set_config = callback;
usbd_dev->user_callback_set_config = callback;
}
static u16 build_config_descriptor(u8 index, u8 *buf, u16 len)
static u16 build_config_descriptor(usbd_device *usbd_dev,
u8 index, u8 *buf, u16 len)
{
u8 *tmpbuf = buf;
const struct usb_config_descriptor *cfg = &_usbd_device.config[index];
const struct usb_config_descriptor *cfg = &usbd_dev->config[index];
u16 count, total = 0, totallen = 0;
u16 i, j, k;
@@ -43,7 +46,7 @@ static u16 build_config_descriptor(u8 index, u8 *buf, u16 len)
for (i = 0; i < cfg->bNumInterfaces; i++) {
/* Interface Association Descriptor, if any */
if (cfg->interface[i].iface_assoc) {
const struct usb_iface_assoc_descriptor *assoc =
const struct usb_iface_assoc_descriptor *assoc =
cfg->interface[i].iface_assoc;
memcpy(buf, assoc, count = MIN(len, assoc->bLength));
buf += count;
@@ -87,7 +90,8 @@ static u16 build_config_descriptor(u8 index, u8 *buf, u16 len)
return total;
}
static int usb_standard_get_descriptor(struct usb_setup_data *req,
static int usb_standard_get_descriptor(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len)
{
int i;
@@ -95,25 +99,26 @@ static int usb_standard_get_descriptor(struct usb_setup_data *req,
switch (req->wValue >> 8) {
case USB_DT_DEVICE:
*buf = (u8 *) _usbd_device.desc;
*len = MIN(*len, _usbd_device.desc->bLength);
*buf = (u8 *) usbd_dev->desc;
*len = MIN(*len, usbd_dev->desc->bLength);
return 1;
case USB_DT_CONFIGURATION:
*buf = _usbd_device.ctrl_buf;
*len = build_config_descriptor(req->wValue & 0xff, *buf, *len);
*buf = usbd_dev->ctrl_buf;
*len = build_config_descriptor(usbd_dev, req->wValue & 0xff,
*buf, *len);
return 1;
case USB_DT_STRING:
sd = (struct usb_string_descriptor *)_usbd_device.ctrl_buf;
sd = (struct usb_string_descriptor *)usbd_dev->ctrl_buf;
if (!_usbd_device.strings)
if (!usbd_dev->strings)
return 0; /* Device doesn't support strings. */
/* Check that string index is in range. */
for (i = 0; i <= (req->wValue & 0xff); i++)
if (_usbd_device.strings[i] == NULL)
if (usbd_dev->strings[i] == NULL)
return 0;
sd->bLength = strlen(_usbd_device.strings[req->wValue & 0xff])
sd->bLength = strlen(usbd_dev->strings[req->wValue & 0xff])
* 2 + 2;
sd->bDescriptorType = USB_DT_STRING;
@@ -122,7 +127,7 @@ static int usb_standard_get_descriptor(struct usb_setup_data *req,
for (i = 0; i < (*len / 2) - 1; i++)
sd->wData[i] =
_usbd_device.strings[req->wValue & 0xff][i];
usbd_dev->strings[req->wValue & 0xff][i];
/* Send sane Language ID descriptor... */
if ((req->wValue & 0xff) == 0)
@@ -133,7 +138,8 @@ static int usb_standard_get_descriptor(struct usb_setup_data *req,
return 0;
}
static int usb_standard_set_address(struct usb_setup_data *req, u8 **buf,
static int usb_standard_set_address(usbd_device *usbd_dev,
struct usb_setup_data *req, u8 **buf,
u16 *len)
{
(void)req;
@@ -144,19 +150,20 @@ static int usb_standard_set_address(struct usb_setup_data *req, u8 **buf,
if ((req->bmRequestType != 0) || (req->wValue >= 128))
return 0;
_usbd_device.current_address = req->wValue;
usbd_dev->current_address = req->wValue;
/*
* Special workaround for STM32F10[57] that require the address
* to be set here. This is undocumented!
*/
if (_usbd_device.driver == &stm32f107_usb_driver)
_usbd_device.driver->set_address(req->wValue);
if ( usbd_dev->driver->set_address_before_status)
usbd_dev->driver->set_address(usbd_dev, req->wValue);
return 1;
}
static int usb_standard_set_configuration(struct usb_setup_data *req,
static int usb_standard_set_configuration(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len)
{
int i;
@@ -166,43 +173,46 @@ static int usb_standard_set_configuration(struct usb_setup_data *req,
(void)len;
/* Is this correct, or should we reset alternate settings. */
if (req->wValue == _usbd_device.current_config)
if (req->wValue == usbd_dev->current_config)
return 1;
_usbd_device.current_config = req->wValue;
usbd_dev->current_config = req->wValue;
/* Reset all endpoints. */
_usbd_hw_endpoints_reset();
usbd_dev->driver->ep_reset(usbd_dev);
if (_usbd_device.user_callback_set_config) {
if (usbd_dev->user_callback_set_config) {
/*
* Flush control callbacks. These will be reregistered
* by the user handler.
*/
for (i = 0; i < MAX_USER_CONTROL_CALLBACK; i++)
_usbd_device.user_control_callback[i].cb = NULL;
usbd_dev->user_control_callback[i].cb = NULL;
_usbd_device.user_callback_set_config(req->wValue);
usbd_dev->user_callback_set_config(usbd_dev, req->wValue);
}
return 1;
}
static int usb_standard_get_configuration(struct usb_setup_data *req,
static int usb_standard_get_configuration(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len)
{
(void)req;
if (*len > 1)
*len = 1;
(*buf)[0] = _usbd_device.current_config;
(*buf)[0] = usbd_dev->current_config;
return 1;
}
static int usb_standard_set_interface(struct usb_setup_data *req,
static int usb_standard_set_interface(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len)
{
(void)usbd_dev;
(void)req;
(void)buf;
@@ -214,9 +224,11 @@ static int usb_standard_set_interface(struct usb_setup_data *req,
return 1;
}
static int usb_standard_get_interface(struct usb_setup_data *req,
static int usb_standard_get_interface(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len)
{
(void)usbd_dev;
(void)req;
(void)buf;
@@ -227,9 +239,11 @@ static int usb_standard_get_interface(struct usb_setup_data *req,
return 1;
}
static int usb_standard_device_get_status(struct usb_setup_data *req,
static int usb_standard_device_get_status(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len)
{
(void)usbd_dev;
(void)req;
/* bit 0: self powered */
@@ -242,9 +256,11 @@ static int usb_standard_device_get_status(struct usb_setup_data *req,
return 1;
}
static int usb_standard_interface_get_status(struct usb_setup_data *req,
static int usb_standard_interface_get_status(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len)
{
(void)usbd_dev;
(void)req;
/* not defined */
@@ -256,45 +272,50 @@ static int usb_standard_interface_get_status(struct usb_setup_data *req,
return 1;
}
static int usb_standard_endpoint_get_status(struct usb_setup_data *req,
static int usb_standard_endpoint_get_status(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len)
{
(void)req;
if (*len > 2)
*len = 2;
(*buf)[0] = usbd_ep_stall_get(req->wIndex) ? 1 : 0;
(*buf)[0] = usbd_ep_stall_get(usbd_dev, req->wIndex) ? 1 : 0;
(*buf)[1] = 0;
return 1;
}
static int usb_standard_endpoint_stall(struct usb_setup_data *req,
static int usb_standard_endpoint_stall(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len)
{
(void)buf;
(void)len;
usbd_ep_stall_set(req->wIndex, 1);
usbd_ep_stall_set(usbd_dev, req->wIndex, 1);
return 1;
}
static int usb_standard_endpoint_unstall(struct usb_setup_data *req,
static int usb_standard_endpoint_unstall(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len)
{
(void)buf;
(void)len;
usbd_ep_stall_set(req->wIndex, 0);
usbd_ep_stall_set(usbd_dev, req->wIndex, 0);
return 1;
}
int _usbd_standard_request_device(struct usb_setup_data *req, u8 **buf,
int _usbd_standard_request_device(usbd_device *usbd_dev,
struct usb_setup_data *req, u8 **buf,
u16 *len)
{
int (*command)(struct usb_setup_data *req, u8 **buf, u16 *len) = NULL;
int (*command)(usbd_device *usbd_dev, struct usb_setup_data *req, u8
**buf, u16 *len) = NULL;
switch (req->bRequest) {
case USB_REQ_CLEAR_FEATURE:
@@ -337,13 +358,15 @@ int _usbd_standard_request_device(struct usb_setup_data *req, u8 **buf,
if (!command)
return 0;
return command(req, buf, len);
return command(usbd_dev, req, buf, len);
}
int _usbd_standard_request_interface(struct usb_setup_data *req, u8 **buf,
int _usbd_standard_request_interface(usbd_device *usbd_dev,
struct usb_setup_data *req, u8 **buf,
u16 *len)
{
int (*command)(struct usb_setup_data *req, u8 **buf, u16 *len) = NULL;
int (*command)(usbd_device *usbd_dev, struct usb_setup_data *req,
u8 **buf, u16 *len) = NULL;
switch (req->bRequest) {
case USB_REQ_CLEAR_FEATURE:
@@ -364,13 +387,15 @@ int _usbd_standard_request_interface(struct usb_setup_data *req, u8 **buf,
if (!command)
return 0;
return command(req, buf, len);
return command(usbd_dev, req, buf, len);
}
int _usbd_standard_request_endpoint(struct usb_setup_data *req, u8 **buf,
int _usbd_standard_request_endpoint(usbd_device *usbd_dev,
struct usb_setup_data *req, u8 **buf,
u16 *len)
{
int (*command) (struct usb_setup_data *req, u8 **buf, u16 *len) = NULL;
int (*command) (usbd_device *usbd_dev, struct usb_setup_data *req,
u8 **buf, u16 *len) = NULL;
switch (req->bRequest) {
case USB_REQ_CLEAR_FEATURE:
@@ -396,10 +421,11 @@ int _usbd_standard_request_endpoint(struct usb_setup_data *req, u8 **buf,
if (!command)
return 0;
return command(req, buf, len);
return command(usbd_dev, req, buf, len);
}
int _usbd_standard_request(struct usb_setup_data *req, u8 **buf, u16 *len)
int _usbd_standard_request(usbd_device *usbd_dev,
struct usb_setup_data *req, u8 **buf, u16 *len)
{
/* FIXME: Have class/vendor requests as well. */
if ((req->bmRequestType & USB_REQ_TYPE_TYPE) != USB_REQ_TYPE_STANDARD)
@@ -407,11 +433,12 @@ int _usbd_standard_request(struct usb_setup_data *req, u8 **buf, u16 *len)
switch (req->bmRequestType & USB_REQ_TYPE_RECIPIENT) {
case USB_REQ_TYPE_DEVICE:
return _usbd_standard_request_device(req, buf, len);
return _usbd_standard_request_device(usbd_dev, req, buf, len);
case USB_REQ_TYPE_INTERFACE:
return _usbd_standard_request_interface(req, buf, len);
return _usbd_standard_request_interface(usbd_dev, req,
buf, len);
case USB_REQ_TYPE_ENDPOINT:
return _usbd_standard_request_endpoint(req, buf, len);
return _usbd_standard_request_endpoint(usbd_dev, req, buf, len);
default:
return 0;
}