summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/usbg/usbg.h64
-rw-r--r--include/usbg/usbg_internal.h1
-rw-r--r--src/usbg.c92
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)
{
diff --git a/src/usbg.c b/src/usbg.c
index 3a2c674..1c93f7b 100644
--- a/src/usbg.c
+++ b/src/usbg.c
@@ -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)
{