diff options
-rw-r--r-- | include/usbg/usbg.h | 64 | ||||
-rw-r--r-- | include/usbg/usbg_internal.h | 1 | ||||
-rw-r--r-- | src/usbg.c | 92 |
3 files changed, 157 insertions, 0 deletions
diff --git a/include/usbg/usbg.h b/include/usbg/usbg.h index 925c50d..e5de7af 100644 --- a/include/usbg/usbg.h +++ b/include/usbg/usbg.h @@ -154,6 +154,28 @@ struct usbg_gadget_strs }; /** + * @brief USB gadget Microsoft OS Descriptors + */ +struct usbg_gadget_os_descs +{ + bool use; + uint8_t b_vendor_code; + char *qw_sign; +}; + +/** + * @typedef usbg_gadget_os_desc_strs + * @brief Microsoft OS Descriptors strings + */ +typedef enum { + USBG_GADGET_OS_DESC_MIN = 0, + OS_DESC_USE = USBG_GADGET_OS_DESC_MIN, + OS_DESC_B_VENDOR_CODE, + OS_DESC_QW_SIGN, + USBG_GADGET_OS_DESC_MAX, +} usbg_gadget_os_desc_strs; + +/** * @brief USB configuration attributes */ struct usbg_config_attrs @@ -424,6 +446,13 @@ extern int usbg_lookup_gadget_str(const char *name); extern const char *usbg_get_gadget_str_name(usbg_gadget_str str); /** + * @brief Get name of selected OS Descriptor string + * @param str OS Descriptor string code + * @return Name of OS Descriptor associated with this code + */ +extern const char *usbg_get_gadget_os_desc_name(usbg_gadget_os_desc_strs str); + +/** * @brief Set selected attribute to value * @param g Pointer to gadget * @param attr Code of selected attribute @@ -637,6 +666,41 @@ extern int usbg_set_gadget_manufacturer(usbg_gadget *g, int lang, extern int usbg_set_gadget_product(usbg_gadget *g, int lang, const char *prd); +/** + * @brief Get the USB gadget OS Descriptor + * @param g Pointer to gadget + * @param g_os_descs Structure to be filled + * @return 0 on success usbg_error if error occurred + */ + +extern int usbg_get_gadget_os_descs(usbg_gadget *g, + struct usbg_gadget_os_descs *g_os_descs); + +/** + * @brief Free OS Descriptor attributes + * @details This function releases the memory allocated for USB + * gadget OS Descriptor atrributes. + * @param g_os_desc OS Descriptor attributes to be released + */ +static inline void usbg_free_gadget_os_desc( + struct usbg_gadget_os_descs *g_os_desc) +{ + if (!g_os_desc) + return; + + free(g_os_desc->qw_sign); +} + +/** + * @brief Set the USB gadget OS Descriptor + * @param g Pointer to gadget + * @param g_os_descs Structure to be filled + * @return 0 on success usbg_error if error occurred + */ + +extern int usbg_set_gadget_os_descs(usbg_gadget *g, + const struct usbg_gadget_os_descs *g_os_descs); + /* USB function allocation and configuration */ /** diff --git a/include/usbg/usbg_internal.h b/include/usbg/usbg_internal.h index 5634134..db8c77b 100644 --- a/include/usbg/usbg_internal.h +++ b/include/usbg/usbg_internal.h @@ -203,6 +203,7 @@ struct usbg_udc #define CONFIGS_DIR "configs" #define FUNCTIONS_DIR "functions" #define GADGETS_DIR "usb_gadget" +#define OS_DESC_DIR "os_desc" static inline int file_select(const struct dirent *dent) { @@ -98,6 +98,15 @@ const char *gadget_str_names[] = ARRAY_SIZE_SENTINEL(gadget_str_names, USBG_GADGET_STR_MAX); +const char *gadget_os_desc_names[] = +{ + "use", + "b_vendor_code", + "qw_sign", +}; + +ARRAY_SIZE_SENTINEL(gadget_os_desc_names, USBG_GADGET_OS_DESC_MAX); + int usbg_lookup_function_type(const char *name) { int i = USBG_FUNCTION_TYPE_MIN; @@ -167,6 +176,13 @@ const char *usbg_get_gadget_str_name(usbg_gadget_str str) gadget_str_names[str] : NULL; } +const char *usbg_get_gadget_os_desc_name(usbg_gadget_os_desc_strs str) +{ + return str >= USBG_GADGET_OS_DESC_MIN && + str < USBG_GADGET_OS_DESC_MAX ? + gadget_os_desc_names[str] : NULL; +} + static int usbg_split_function_instance_type(const char *full_name, usbg_function_type *f_type, const char **instance) { @@ -802,6 +818,40 @@ out: return ret; } +static int usbg_parse_gadget_os_descs(const char *path, const char *name, + struct usbg_gadget_os_descs *g_os_descs) +{ + int ret; + int nmb; + char spath[USBG_MAX_PATH_LENGTH]; + int val; + + nmb = snprintf(spath, sizeof(spath), "%s/%s/%s", path, name, + OS_DESC_DIR); + if (nmb >= sizeof(spath)) { + ret = USBG_ERROR_PATH_TOO_LONG; + goto out; + } + + ret = usbg_read_string_alloc(spath, "", "qw_sign", &g_os_descs->qw_sign); + if (ret != USBG_SUCCESS) + goto out; + + ret = usbg_read_hex(spath, "", "b_vendor_code", &val); + if (ret != USBG_SUCCESS) + goto out; + + g_os_descs->b_vendor_code = (unsigned char)val; + + ret = usbg_read_int(spath, "", "use", 10, &val); + if (ret != USBG_SUCCESS) + goto out; + + g_os_descs->use = val ? true : false; +out: + return ret; +} + static inline int usbg_parse_gadget(usbg_gadget *g) { int ret; @@ -1853,6 +1903,48 @@ out: return ret; } +int usbg_get_gadget_os_descs(usbg_gadget *g, struct usbg_gadget_os_descs *g_os_descs) +{ + return g && g_os_descs ? + usbg_parse_gadget_os_descs(g->path, g->name, g_os_descs) + : USBG_ERROR_INVALID_PARAM; +} + +int usbg_set_gadget_os_descs(usbg_gadget *g, + const struct usbg_gadget_os_descs *g_os_descs) +{ + int ret; + int nmb; + char spath[USBG_MAX_PATH_LENGTH]; + + nmb = snprintf(spath, sizeof(spath), "%s/%s/%s", g->path, g->name, + OS_DESC_DIR); + if (nmb >= sizeof(spath)) { + ret = USBG_ERROR_PATH_TOO_LONG; + goto out; + } + + ret = usbg_check_dir(spath); + if (ret != USBG_SUCCESS) + goto out; + + ret = usbg_write_string(spath, "", "qw_sign", g_os_descs->qw_sign); + if (ret != USBG_SUCCESS) + goto out; + + ret = usbg_write_hex8(spath, "", "b_vendor_code", + g_os_descs->b_vendor_code); + if (ret != USBG_SUCCESS) + goto out; + + ret = usbg_write_dec(spath, "", "use", g_os_descs->use); + if (ret != USBG_SUCCESS) + goto out; + +out: + return ret; +} + int usbg_create_function(usbg_gadget *g, usbg_function_type type, const char *instance, void *f_attrs, usbg_function **f) { |