diff --git a/sys/include/usb/usbus.h b/sys/include/usb/usbus.h index 008a6ac7ad..090f969d9c 100644 --- a/sys/include/usb/usbus.h +++ b/sys/include/usb/usbus.h @@ -182,8 +182,21 @@ typedef enum { */ typedef struct { /** - * @brief function pointer to retrieve the header content of this header - * generator + * @brief function pointer to format the descriptor content of this + * descriptor generator. The content of this descriptor is prefixes before + * the descriptor of the object it is part of. + * + * @param usbus The usbus context + * @param arg Additional argument for the header generator + * + * @return Length of the generated descriptor + */ + size_t (*fmt_pre_descriptor)(usbus_t *usbus, void *arg); + + /** + * @brief function pointer to format the descriptor content of this + * descriptor generator. The content of this descriptor is appended after + * the descriptor of the object it is part of. * * @param usbus The usbus context * @param arg Additional argument for the header generator @@ -195,8 +208,10 @@ typedef struct { /** * @brief USBUS generic header generator generated length * - * Must return the length of the header that will be generated by - * @ref get_header + * Must return the total length of the descriptors that will be + * generated by @ref fmt_pre_descriptor and @ref get_header + * This function is used when @ref len_type is set to + * @ref USBUS_HDR_LEN_FUNC. * * @param usbus The usbus context * @param arg Additional argument for the header generator @@ -204,7 +219,14 @@ typedef struct { * @return Length of the generated header */ size_t (*get_header_len)(usbus_t *usbus, void *arg); - size_t fixed_len; /**< length of the header if it is a fixed length */ + /** + * @brief Fixed total length of the generated descriptors + * + * Must return the total length of the descriptors that will be + * generated by the @ref fmt_pre_descriptor and @ref get_header. + * This value is used when @ref len_type is set to @ref USBUS_HDR_LEN_FIXED. + */ + size_t fixed_len; } len; /**< Fixed or generated length of the header */ usbus_hdr_len_type_t len_type; /**< Either USBUS_HDR_LEN_FIXED or USBUS_HDR_LEN_FUNC */ } usbus_hdr_gen_funcs_t; diff --git a/sys/usb/usbus/usbus_fmt.c b/sys/usb/usbus/usbus_fmt.c index fe9738b119..8cc5b212f5 100644 --- a/sys/usb/usbus/usbus_fmt.c +++ b/sys/usb/usbus/usbus_fmt.c @@ -130,9 +130,28 @@ static size_t _hdrs_config_size(usbus_t *usbus) return len; } -static inline size_t call_get_header(usbus_t *usbus, usbus_hdr_gen_t *hdr) +static inline size_t _get_pre_header(usbus_t *usbus, usbus_hdr_gen_t *hdr) { - return hdr->funcs->get_header(usbus, hdr->arg); + return (hdr->funcs->fmt_pre_descriptor != NULL) + ? hdr->funcs->fmt_pre_descriptor(usbus, hdr->arg) + : 0; +} + +static inline size_t _get_additional_header(usbus_t *usbus, usbus_hdr_gen_t *hdr) +{ + return (hdr->funcs->get_header != NULL) + ? hdr->funcs->get_header(usbus, hdr->arg) + : 0; +} + +static size_t _hdrs_fmt_pre(usbus_t *usbus, usbus_hdr_gen_t *hdr) +{ + size_t len = 0; + + for (; hdr; hdr = hdr->next) { + len += _get_pre_header(usbus, hdr); + } + return len; } static size_t _hdrs_fmt_additional(usbus_t *usbus, usbus_hdr_gen_t *hdr) @@ -140,7 +159,7 @@ static size_t _hdrs_fmt_additional(usbus_t *usbus, usbus_hdr_gen_t *hdr) size_t len = 0; for (; hdr; hdr = hdr->next) { - len += call_get_header(usbus, hdr); + len += _get_additional_header(usbus, hdr); } return len; } @@ -155,6 +174,7 @@ static size_t _hdrs_fmt_endpoints(usbus_t *usbus, usbus_endpoint_t *ep) size_t len = 0; while (ep) { + _hdrs_fmt_pre(usbus, ep->hdr_gen); usb_descriptor_endpoint_t usb_ep; memset(&usb_ep, 0, sizeof(usb_descriptor_endpoint_t)); usb_ep.length = sizeof(usb_descriptor_endpoint_t); @@ -215,6 +235,7 @@ static size_t _hdrs_fmt_ifaces(usbus_t *usbus) for (usbus_interface_t *iface = usbus->iface; iface; iface = iface->next) { + len += _hdrs_fmt_pre(usbus, iface->hdr_gen); usb_descriptor_interface_t usb_iface; _hdrs_fmt_iface(iface, &usb_iface); usb_iface.num_endpoints = _num_endpoints(iface);