Skip to content

Commit b0d7d70

Browse files
jfischer-nofabiobaltieri
authored andcommitted
usb: device_next: add initial BOS support
Use the same scheme as for string descriptors. Descriptors can be added or removed using the existend interface. Signed-off-by: Johann Fischer <[email protected]>
1 parent 29003ff commit b0d7d70

File tree

3 files changed

+114
-10
lines changed

3 files changed

+114
-10
lines changed

include/zephyr/usb/usbd.h

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define ZEPHYR_INCLUDE_USBD_H_
1616

1717
#include <zephyr/device.h>
18+
#include <zephyr/usb/bos.h>
1819
#include <zephyr/usb/usb_ch9.h>
1920
#include <zephyr/usb/usbd_msg.h>
2021
#include <zephyr/net/buf.h>
@@ -69,6 +70,9 @@ enum usbd_str_desc_utype {
6970
USBD_DUT_STRING_INTERFACE,
7071
};
7172

73+
enum usbd_bos_desc_utype {
74+
USBD_DUT_BOS_NONE,
75+
};
7276
/** @endcond */
7377

7478
/**
@@ -85,17 +89,26 @@ struct usbd_str_desc_data {
8589
unsigned int use_hwinfo : 1;
8690
};
8791

92+
/**
93+
* USBD BOS Device Capability descriptor data
94+
*/
95+
struct usbd_bos_desc_data {
96+
/** Descriptor usage type (not bDescriptorType) */
97+
enum usbd_bos_desc_utype utype : 8;
98+
};
99+
88100
/**
89101
* Descriptor node
90102
*
91103
* Descriptor node is used to manage descriptors that are not
92-
* directly part of a structure, such as string or bos descriptors.
104+
* directly part of a structure, such as string or BOS capability descriptors.
93105
*/
94106
struct usbd_desc_node {
95107
/** slist node struct */
96108
sys_dnode_t node;
97109
union {
98110
struct usbd_str_desc_data str;
111+
struct usbd_bos_desc_data bos;
99112
};
100113
/** Opaque pointer to a descriptor payload */
101114
const void *const ptr;
@@ -219,7 +232,7 @@ struct usbd_contex {
219232
usbd_msg_cb_t msg_cb;
220233
/** Middle layer runtime data */
221234
struct usbd_ch9_data ch9_data;
222-
/** slist to manage descriptors like string, bos */
235+
/** slist to manage descriptors like string, BOS */
223236
sys_dlist_t descriptors;
224237
/** slist to manage Full-Speed device configurations */
225238
sys_slist_t fs_configs;
@@ -530,6 +543,26 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c
530543
.bDescriptorType = USB_DESC_STRING, \
531544
}
532545

546+
/**
547+
* @brief Define BOS Device Capability descriptor node
548+
*
549+
* The application defines a BOS capability descriptor node for descriptors
550+
* such as USB 2.0 Extension Descriptor.
551+
*
552+
* @param name Descriptor node identifier
553+
* @param len Device Capability descriptor length
554+
* @param subset Pointer to a Device Capability descriptor
555+
*/
556+
#define USBD_DESC_BOS_DEFINE(name, len, subset) \
557+
static struct usbd_desc_node name = { \
558+
.bos = { \
559+
.utype = USBD_DUT_BOS_NONE, \
560+
}, \
561+
.ptr = subset, \
562+
.bLength = len, \
563+
.bDescriptorType = USB_DESC_BOS, \
564+
}
565+
533566
#define USBD_DEFINE_CLASS(class_name, class_api, class_priv, class_v_reqs) \
534567
static struct usbd_class_data class_name = { \
535568
.name = STRINGIFY(class_name), \
@@ -569,7 +602,7 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c
569602
/**
570603
* @brief Add common USB descriptor
571604
*
572-
* Add common descriptor like string or bos.
605+
* Add common descriptor like string or BOS Device Capability.
573606
*
574607
* @param[in] uds_ctx Pointer to USB device support context
575608
* @param[in] dn Pointer to USB descriptor node

subsys/usb/device_next/usbd_ch9.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,60 @@ static int sreq_get_dev_qualifier(struct usbd_contex *const uds_ctx,
691691
return 0;
692692
}
693693

694+
static void desc_fill_bos_root(struct usbd_contex *const uds_ctx,
695+
struct usb_bos_descriptor *const root)
696+
{
697+
struct usbd_desc_node *desc_nd;
698+
699+
root->bLength = sizeof(struct usb_bos_descriptor);
700+
root->bDescriptorType = USB_DESC_BOS;
701+
root->wTotalLength = root->bLength;
702+
703+
SYS_DLIST_FOR_EACH_CONTAINER(&uds_ctx->descriptors, desc_nd, node) {
704+
if (desc_nd->bDescriptorType == USB_DESC_BOS) {
705+
root->wTotalLength += desc_nd->bLength;
706+
root->bNumDeviceCaps += desc_nd->bLength;
707+
}
708+
}
709+
}
710+
711+
static int sreq_get_desc_bos(struct usbd_contex *const uds_ctx,
712+
struct net_buf *const buf)
713+
{
714+
struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx);
715+
struct usb_bos_descriptor bos;
716+
struct usbd_desc_node *desc_nd;
717+
size_t len;
718+
719+
desc_fill_bos_root(uds_ctx, &bos);
720+
len = MIN(net_buf_tailroom(buf), MIN(setup->wLength, bos.wTotalLength));
721+
722+
LOG_DBG("wLength %u, bLength %u, wTotalLength %u, tailroom %u",
723+
setup->wLength, bos.bLength, bos.wTotalLength, net_buf_tailroom(buf));
724+
725+
net_buf_add_mem(buf, &bos, MIN(len, bos.bLength));
726+
727+
len -= MIN(len, sizeof(bos));
728+
if (len == 0) {
729+
return 0;
730+
}
731+
732+
SYS_DLIST_FOR_EACH_CONTAINER(&uds_ctx->descriptors, desc_nd, node) {
733+
if (desc_nd->bDescriptorType == USB_DESC_BOS) {
734+
LOG_DBG("bLength %u, len %u, tailroom %u",
735+
desc_nd->bLength, len, net_buf_tailroom(buf));
736+
net_buf_add_mem(buf, desc_nd->ptr, MIN(len, desc_nd->bLength));
737+
738+
len -= MIN(len, desc_nd->bLength);
739+
if (len == 0) {
740+
break;
741+
}
742+
}
743+
}
744+
745+
return 0;
746+
}
747+
694748
static int sreq_get_descriptor(struct usbd_contex *const uds_ctx,
695749
struct net_buf *const buf)
696750
{
@@ -722,6 +776,8 @@ static int sreq_get_descriptor(struct usbd_contex *const uds_ctx,
722776
return sreq_get_desc_str(uds_ctx, buf, desc_idx);
723777
case USB_DESC_DEVICE_QUALIFIER:
724778
return sreq_get_dev_qualifier(uds_ctx, buf);
779+
case USB_DESC_BOS:
780+
return sreq_get_desc_bos(uds_ctx, buf);
725781
case USB_DESC_INTERFACE:
726782
case USB_DESC_ENDPOINT:
727783
default:

subsys/usb/device_next/usbd_desc.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,16 @@ struct usbd_desc_node *usbd_get_descriptor(struct usbd_contex *const uds_ctx,
8686
struct usbd_desc_node *desc_nd;
8787

8888
SYS_DLIST_FOR_EACH_CONTAINER(&uds_ctx->descriptors, desc_nd, node) {
89-
if (desc_nd->str.idx == idx && desc_nd->bDescriptorType == type) {
90-
return desc_nd;
89+
if (desc_nd->bDescriptorType == type) {
90+
if (desc_nd->bDescriptorType == USB_DESC_STRING) {
91+
if (desc_nd->str.idx == idx) {
92+
return desc_nd;
93+
}
94+
}
95+
96+
if (desc_nd->bDescriptorType == USB_DESC_BOS) {
97+
return desc_nd;
98+
}
9199
}
92100
}
93101

@@ -133,13 +141,17 @@ int usbd_add_descriptor(struct usbd_contex *const uds_ctx,
133141
goto add_descriptor_error;
134142
}
135143

136-
ret = desc_add_and_update_idx(uds_ctx, desc_nd);
137-
if (ret) {
138-
ret = -EINVAL;
139-
goto add_descriptor_error;
144+
if (desc_nd->bDescriptorType == USB_DESC_BOS) {
145+
sys_dlist_append(&uds_ctx->descriptors, &desc_nd->node);
140146
}
141147

142148
if (desc_nd->bDescriptorType == USB_DESC_STRING) {
149+
ret = desc_add_and_update_idx(uds_ctx, desc_nd);
150+
if (ret) {
151+
ret = -EINVAL;
152+
goto add_descriptor_error;
153+
}
154+
143155
switch (desc_nd->str.utype) {
144156
case USBD_DUT_STRING_LANG:
145157
break;
@@ -178,6 +190,9 @@ void usbd_remove_descriptor(struct usbd_desc_node *const desc_nd)
178190
{
179191
if (sys_dnode_is_linked(&desc_nd->node)) {
180192
sys_dlist_remove(&desc_nd->node);
181-
desc_nd->str.idx = 0;
193+
194+
if (desc_nd->bDescriptorType == USB_DESC_STRING) {
195+
desc_nd->str.idx = 0U;
196+
}
182197
}
183198
}

0 commit comments

Comments
 (0)