Skip to content

Commit c8f3a2e

Browse files
jfischer-nokartben
authored andcommitted
usb: host: allow dynamic allocation of USB devices
Allow dynamic allocation of USB devices on connected event. Add very basic USB device validation and configuration. Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
1 parent 96f4f3f commit c8f3a2e

File tree

9 files changed

+648
-44
lines changed

9 files changed

+648
-44
lines changed

include/zephyr/drivers/usb/uhc.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,61 @@ enum usb_device_state {
3535
USB_STATE_CONFIGURED,
3636
};
3737

38+
/**
39+
* @brief USB device operating speed
40+
*/
41+
enum usb_device_speed {
42+
/** Device is probably not connected */
43+
USB_SPEED_UNKNOWN,
44+
/** Low speed */
45+
USB_SPEED_SPEED_LS,
46+
/** Full speed */
47+
USB_SPEED_SPEED_FS,
48+
/** High speed */
49+
USB_SPEED_SPEED_HS,
50+
/** Super speed */
51+
USB_SPEED_SPEED_SS,
52+
};
53+
54+
#define UHC_INTERFACES_MAX 32
55+
56+
struct usb_host_interface {
57+
struct usb_desc_header *dhp;
58+
uint8_t alternate;
59+
};
60+
61+
struct usb_host_ep {
62+
struct usb_ep_descriptor *desc;
63+
};
64+
3865
/**
3966
* Host representation of a USB device
4067
*/
4168
struct usb_device {
69+
/** dlist node */
70+
sys_dnode_t node;
4271
/** An opaque pointer to the host context to which this device belongs */
4372
void *ctx;
73+
/** Device mutex */
74+
struct k_mutex mutex;
4475
/** USB device descriptor */
4576
struct usb_device_descriptor dev_desc;
4677
/** Device state */
4778
enum usb_device_state state;
79+
/** Device speed */
80+
enum usb_device_speed speed;
4881
/** Actual active device configuration */
4982
uint8_t actual_cfg;
5083
/** Device address */
5184
uint8_t addr;
85+
/** Pointer to actual device configuration descriptor */
86+
void *cfg_desc;
87+
/** Pointers to device interfaces */
88+
struct usb_host_interface ifaces[UHC_INTERFACES_MAX + 1];
89+
/** Pointers to device OUT endpoints */
90+
struct usb_host_ep ep_out[16];
91+
/** Pointers to device IN endpoints */
92+
struct usb_host_ep ep_in[16];
5293
};
5394

5495
/**

include/zephyr/usb/usbh.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <zephyr/device.h>
1919
#include <zephyr/net_buf.h>
2020
#include <zephyr/sys/dlist.h>
21+
#include <zephyr/sys/bitarray.h>
2122
#include <zephyr/drivers/usb/uhc.h>
2223
#include <zephyr/sys/iterable_sections.h>
2324

@@ -42,15 +43,21 @@ struct usbh_contex {
4243
struct k_mutex mutex;
4344
/** Pointer to UHC device struct */
4445
const struct device *dev;
45-
/** peripheral list */
46-
sys_dlist_t peripherals;
46+
/** USB device list */
47+
sys_dlist_t udevs;
48+
/** USB root device */
49+
struct usb_device *root;
50+
/** Allocated device addresses bit array */
51+
struct sys_bitarray *addr_ba;
4752
};
4853

4954
#define USBH_CONTROLLER_DEFINE(device_name, uhc_dev) \
55+
SYS_BITARRAY_DEFINE_STATIC(ba_##device_name, 128); \
5056
static STRUCT_SECTION_ITERABLE(usbh_contex, device_name) = { \
5157
.name = STRINGIFY(device_name), \
5258
.mutex = Z_MUTEX_INITIALIZER(device_name.mutex), \
5359
.dev = uhc_dev, \
60+
.addr_ba = &ba_##device_name, \
5461
}
5562

5663
/**

subsys/usb/host/Kconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,20 @@ module = USBH
1515
module-str = usbh
1616
source "subsys/logging/Kconfig.template.log_config"
1717

18+
config USBH_USB_DEVICE_MAX
19+
int "Maximum number of USB devices supported."
20+
default 4
21+
range 2 127
22+
help
23+
Maximum number of USB devices supported for all controllers.
24+
25+
config USBH_USB_DEVICE_HEAP
26+
int "Memory used to cache device descriptors"
27+
default 1024
28+
range 256 16384
29+
help
30+
Memory used to cache device descriptors.
31+
1832
config USBH_SHELL
1933
bool "USB host shell"
2034
depends on SHELL

subsys/usb/host/usbh_ch9.c

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -174,44 +174,17 @@ int usbh_req_set_address(struct usb_device *const udev,
174174
{
175175
const uint8_t bmRequestType = USB_REQTYPE_DIR_TO_DEVICE << 7;
176176
const uint8_t bRequest = USB_SREQ_SET_ADDRESS;
177-
int ret;
178-
179-
ret = usbh_req_setup(udev, bmRequestType, bRequest, addr, 0, 0, NULL);
180-
if (ret == 0) {
181-
udev->addr = addr;
182-
if (addr == 0) {
183-
udev->state = USB_STATE_DEFAULT;
184-
}
185177

186-
if (addr != 0 && udev->state == USB_STATE_DEFAULT) {
187-
udev->state = USB_STATE_ADDRESSED;
188-
}
189-
}
190-
191-
return ret;
178+
return usbh_req_setup(udev, bmRequestType, bRequest, addr, 0, 0, NULL);
192179
}
193180

194181
int usbh_req_set_cfg(struct usb_device *const udev,
195182
const uint8_t cfg)
196183
{
197184
const uint8_t bmRequestType = USB_REQTYPE_DIR_TO_DEVICE << 7;
198185
const uint8_t bRequest = USB_SREQ_SET_CONFIGURATION;
199-
int ret;
200-
201-
/* Ignore the required state change condition for now. */
202-
ret = usbh_req_setup(udev, bmRequestType, bRequest, cfg, 0, 0, NULL);
203-
if (ret == 0) {
204-
udev->actual_cfg = cfg;
205-
if (cfg == 0) {
206-
udev->state = USB_STATE_ADDRESSED;
207-
}
208186

209-
if (cfg != 0 && udev->state == USB_STATE_ADDRESSED) {
210-
udev->state = USB_STATE_CONFIGURED;
211-
}
212-
}
213-
214-
return ret;
187+
return usbh_req_setup(udev, bmRequestType, bRequest, cfg, 0, 0, NULL);
215188
}
216189

217190
int usbh_req_get_cfg(struct usb_device *const udev,

subsys/usb/host/usbh_core.c

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,47 @@ static int usbh_event_carrier(const struct device *dev,
4343
return err;
4444
}
4545

46+
static void dev_connected_handler(struct usbh_contex *const ctx,
47+
const struct uhc_event *const event)
48+
{
49+
50+
LOG_DBG("Device connected event");
51+
if (ctx->root != NULL) {
52+
LOG_ERR("Device already connected");
53+
usbh_device_free(ctx->root);
54+
ctx->root = NULL;
55+
}
56+
57+
ctx->root = usbh_device_alloc(ctx);
58+
if (ctx->root == NULL) {
59+
LOG_ERR("Failed allocate new device");
60+
return;
61+
}
62+
63+
ctx->root->state = USB_STATE_DEFAULT;
64+
65+
if (event->type == UHC_EVT_DEV_CONNECTED_HS) {
66+
ctx->root->speed = USB_SPEED_SPEED_HS;
67+
} else {
68+
ctx->root->speed = USB_SPEED_SPEED_FS;
69+
}
70+
71+
if (usbh_device_init(ctx->root)) {
72+
LOG_ERR("Failed to reset new USB device");
73+
}
74+
}
75+
76+
static void dev_removed_handler(struct usbh_contex *const ctx)
77+
{
78+
if (ctx->root != NULL) {
79+
usbh_device_free(ctx->root);
80+
ctx->root = NULL;
81+
LOG_DBG("Device removed");
82+
} else {
83+
LOG_DBG("Spurious device removed event");
84+
}
85+
}
86+
4687
static int discard_ep_request(struct usbh_contex *const ctx,
4788
struct uhc_transfer *const xfer)
4889
{
@@ -63,12 +104,14 @@ static ALWAYS_INLINE int usbh_event_handler(struct usbh_contex *const ctx,
63104

64105
switch (event->type) {
65106
case UHC_EVT_DEV_CONNECTED_LS:
107+
LOG_ERR("Low speed device not supported (connected event)");
108+
break;
66109
case UHC_EVT_DEV_CONNECTED_FS:
67110
case UHC_EVT_DEV_CONNECTED_HS:
68-
LOG_DBG("Device connected event");
111+
dev_connected_handler(ctx, event);
69112
break;
70113
case UHC_EVT_DEV_REMOVED:
71-
LOG_DBG("Device removed event");
114+
dev_removed_handler(ctx);
72115
break;
73116
case UHC_EVT_RESETED:
74117
LOG_DBG("Bus reset");
@@ -149,6 +192,8 @@ int usbh_init_device_intl(struct usbh_contex *const uhs_ctx)
149192
return ret;
150193
}
151194

195+
sys_dlist_init(&uhs_ctx->udevs);
196+
152197
STRUCT_SECTION_FOREACH(usbh_class_data, cdata) {
153198
/*
154199
* For now, we have not implemented any class drivers,

0 commit comments

Comments
 (0)