summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKrzysztof Opasiak <k.opasiak@samsung.com>2016-12-16 13:10:30 +0100
committerKrzysztof Opasiak <k.opasiak@samsung.com>2017-03-03 14:02:27 +0100
commitb656ce0845abba50b71f5b5fad989c82bf02cd16 (patch)
tree3be682dcb5f911410a8dc63d181df2afcbf7d97a
parent784e693fe5b397516b8b8521386205512e989c70 (diff)
downloadlibusbg-b656ce0845abba50b71f5b5fad989c82bf02cd16.tar.gz
libusbg-b656ce0845abba50b71f5b5fad989c82bf02cd16.tar.bz2
libusbg-b656ce0845abba50b71f5b5fad989c82bf02cd16.zip
libusbgx: Add support for HID function
HID function has been ported to ConfigFS interface quite long time ago so let's add support for it also in libusbgx. Signed-off-by: Krzysztof Opasiak <k.opasiak@samsung.com>
-rw-r--r--include/usbg/function/hid.h300
-rw-r--r--include/usbg/usbg.h1
-rw-r--r--src/Makefile.am2
-rw-r--r--src/function/hid.c349
-rw-r--r--src/usbg.c2
5 files changed, 653 insertions, 1 deletions
diff --git a/include/usbg/function/hid.h b/include/usbg/function/hid.h
new file mode 100644
index 0000000..83ae51a
--- /dev/null
+++ b/include/usbg/function/hid.h
@@ -0,0 +1,300 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ */
+
+#ifndef USBG_FUNCTION_HID__
+#define USBG_FUNCTION_HID__
+
+#include <usbg/usbg.h>
+
+#include <malloc.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct usbg_f_hid;
+typedef struct usbg_f_hid usbg_f_hid;
+
+struct usbg_f_hid_report_desc {
+ char *desc;
+ unsigned int len;
+};
+
+struct usbg_f_hid_attrs {
+ dev_t dev;
+ unsigned int protocol;
+ struct usbg_f_hid_report_desc report_desc;
+ unsigned int report_length;
+ unsigned int subclass;
+};
+
+enum usbg_f_hid_attr {
+ USBG_F_HID_ATTR_MIN = 0,
+ USBG_F_HID_DEV = USBG_F_HID_ATTR_MIN,
+ USBG_F_HID_PROTOCOL,
+ USBG_F_HID_REPORT_DESC,
+ USBG_F_HID_REPORT_LENGTH,
+ USBG_F_HID_SUBCLASS,
+ USBG_F_HID_ATTR_MAX
+};
+
+union usbg_f_hid_attr_val {
+ dev_t dev;
+ unsigned int protocol;
+ struct usbg_f_hid_report_desc report_desc;
+ unsigned int report_length;
+ unsigned int subclass;
+};
+
+/**
+ * @brief Cast from generic function to hid function
+ * @param[in] f function to be converted to hid funciton.
+ * Function should be one of type hid.
+ * @return Converted hid function or NULL if function hasn't suitable type
+ */
+usbg_f_hid *usbg_to_hid_function(usbg_function *f);
+
+/**
+ * @brief Cast form hid function to generic one
+ * @param[in] hf function to be converted to generic one
+ * @return Generic usbg function
+ */
+usbg_function *usbg_from_hid_function(usbg_f_hid *hf);
+
+/**
+ * @brief Get attributes of given hid function
+ * @param[in] hf Pointer to hid function
+ * @param[out] attrs Structure to be filled with data
+ * @return 0 on success usbg_error if error occurred.
+ */
+int usbg_f_hid_get_attrs(usbg_f_hid *hf,
+ struct usbg_f_hid_attrs *attrs);
+
+/**
+ * @brief Set attributes of given hid function
+ * @param[in] hf Pointer to hid function
+ * @param[in] attrs to be set
+ * @return 0 on success usbg_error if error occurred.
+ */
+int usbg_f_hid_set_attrs(usbg_f_hid *hf,
+ const struct usbg_f_hid_attrs *attrs);
+
+
+/**
+ * @brief Cleanup HID report descriptor structure after usage
+ * @param[in] report_desc to be cleaned up
+ */
+static inline void usbg_f_hid_cleanup_report_desc(
+ struct usbg_f_hid_report_desc *report_desc)
+{
+ if (report_desc->desc) {
+ free(report_desc->desc);
+ /* Just for safety */
+ report_desc->desc = NULL;
+ }
+}
+
+/**
+ * @brief Cleanup attributes structure after usage
+ * @param[in] attrs to be cleaned up
+ */
+static inline void usbg_f_hid_cleanup_attrs(struct usbg_f_hid_attrs *attrs)
+{
+ if (attrs)
+ usbg_f_hid_cleanup_report_desc(&attrs->report_desc);
+}
+
+/**
+ * @brief Get the value of single attribute
+ * @param[in] hf Pointer to hid function
+ * @param[in] attr Code of attribute which value should be taken
+ * @param[out] val Current value of this attribute
+ * @return 0 on success usbg_error if error occurred.
+ */
+int usbg_f_hid_get_attr_val(usbg_f_hid *hf, enum usbg_f_hid_attr attr,
+ union usbg_f_hid_attr_val *val);
+
+/**
+ * @brief Set the value of single attribute
+ * @param[in] hf Pointer to hid function
+ * @param[in] attr Code of attribute which value should be set
+ * @param[in] val Value of attribute which should be set
+ * @return 0 on success usbg_error if error occurred.
+ */
+int usbg_f_hid_set_attr_val(usbg_f_hid *hf, enum usbg_f_hid_attr attr,
+ union usbg_f_hid_attr_val val);
+
+/**
+ * @brief Get the minor and major of corresponding character device
+ * @param[in] hf Pointer to hid function
+ * @param[out] dev Minor and major of corresponding
+ * @return 0 on success usbg_error if error occurred.
+ */
+static inline int usbg_f_hid_get_dev(usbg_f_hid *hf, dev_t *dev)
+{
+ return usbg_f_hid_get_attr_val(hf, USBG_F_HID_DEV,
+ (union usbg_f_hid_attr_val *)dev);
+}
+
+/**
+ * @brief Get HID protocol code
+ * @param[in] hf Pointer to hid function
+ * @param[out] protocol code
+ * @return 0 on success usbg_error if error occurred.
+ */
+static inline int usbg_f_hid_get_protocol(usbg_f_hid *hf,
+ unsigned int *protocol)
+{
+ return usbg_f_hid_get_attr_val(hf, USBG_F_HID_PROTOCOL,
+ (union usbg_f_hid_attr_val *)protocol);
+}
+
+/**
+ * @brief Set HID protocol code
+ * @param[in] hf Pointer to hid function
+ * @param[out] protocol code
+ * @return 0 on success usbg_error if error occurred.
+ */
+static inline int usbg_f_hid_set_protocol(usbg_f_hid *hf,
+ unsigned int protocol)
+{
+ return usbg_f_hid_set_attr_val(hf, USBG_F_HID_PROTOCOL,
+ (union usbg_f_hid_attr_val)protocol);
+}
+
+/**
+ * @brief Get HID report descriptor
+ * @param[in] hf Pointer to hid function
+ * @param[out] report_desc Report descriptor
+ * @return 0 on success usbg_error if error occurred.
+ */
+static inline int usbg_f_hid_get_report_desc(usbg_f_hid *hf,
+ struct usbg_f_hid_report_desc *report_desc)
+{
+ return usbg_f_hid_get_attr_val(hf, USBG_F_HID_REPORT_DESC,
+ (union usbg_f_hid_attr_val *)report_desc);
+}
+
+/**
+ * @brief Set HID report descriptor
+ * @param[in] hf Pointer to hid function
+ * @param[out] report_desc Report descriptor
+ * @return 0 on success usbg_error if error occurred.
+ */
+static inline int usbg_f_hid_set_report_desc(usbg_f_hid *hf,
+ struct usbg_f_hid_report_desc report_desc)
+{
+ return usbg_f_hid_set_attr_val(hf, USBG_F_HID_REPORT_DESC,
+ (union usbg_f_hid_attr_val)report_desc);
+}
+
+/**
+ * @brief Get HID report descriptor
+ * @param[in] hf Pointer to hid function
+ * @param[out] report_desc Report descriptor
+ * @return 0 on success usbg_error if error occurred.
+ */
+static inline int usbg_f_hid_get_report_desc_raw(usbg_f_hid *hf,
+ char **desc,
+ unsigned int *len)
+{
+ struct usbg_f_hid_report_desc report_desc;
+ int ret;
+
+ ret = usbg_f_hid_get_attr_val(hf, USBG_F_HID_REPORT_DESC,
+ (union usbg_f_hid_attr_val *)&report_desc);
+ if (ret != USBG_SUCCESS)
+ return ret;
+
+ *desc = report_desc.desc;
+ *len = report_desc.len;
+
+ return USBG_SUCCESS;
+}
+
+/**
+ * @brief Set HID report descriptor
+ * @param[in] hf Pointer to hid function
+ * @param[out] report_desc Report descriptor
+ * @return 0 on success usbg_error if error occurred.
+ */
+static inline int usbg_f_hid_set_report_desc_raw(usbg_f_hid *hf,
+ char *desc,
+ unsigned int len)
+{
+ struct usbg_f_hid_report_desc report_desc = {
+ .desc = desc,
+ .len = len,
+ };
+
+ return usbg_f_hid_set_attr_val(hf, USBG_F_HID_REPORT_DESC,
+ (union usbg_f_hid_attr_val)report_desc);
+}
+
+/**
+ * @brief Get HID report length
+ * @param[in] hf Pointer to hid function
+ * @param[out] report_length Length of HID report
+ * @return 0 on success usbg_error if error occurred.
+ */
+static inline int usbg_f_hid_get_report_length(usbg_f_hid *hf,
+ unsigned int *report_length)
+{
+ return usbg_f_hid_get_attr_val(hf, USBG_F_HID_REPORT_LENGTH,
+ (union usbg_f_hid_attr_val *)report_length);
+}
+
+/**
+ * @brief Set HID report length
+ * @param[in] hf Pointer to hid function
+ * @param[out] report_length Length of HID report
+ * @return 0 on success usbg_error if error occurred.
+ */
+static inline int usbg_f_hid_set_report_length(usbg_f_hid *hf,
+ unsigned int report_length)
+{
+ return usbg_f_hid_set_attr_val(hf, USBG_F_HID_REPORT_LENGTH,
+ (union usbg_f_hid_attr_val)report_length);
+}
+
+/**
+ * @brief Get HID subclass code
+ * @param[in] hf Pointer to hid function
+ * @param[out] subclass code
+ * @return 0 on success usbg_error if error occurred.
+ */
+static inline int usbg_f_hid_get_subclass(usbg_f_hid *hf,
+ unsigned int *subclass)
+{
+ return usbg_f_hid_get_attr_val(hf, USBG_F_HID_SUBCLASS,
+ (union usbg_f_hid_attr_val *)subclass);
+}
+
+/**
+ * @brief Set HID subclass code
+ * @param[in] hf Pointer to hid function
+ * @param[out] subclass code
+ * @return 0 on success usbg_error if error occurred.
+ */
+static inline int usbg_f_hid_set_subclass(usbg_f_hid *hf,
+ unsigned int subclass)
+{
+ return usbg_f_hid_set_attr_val(hf, USBG_F_HID_SUBCLASS,
+ (union usbg_f_hid_attr_val)subclass);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USBG_FUNCTION_MIDI__ */
diff --git a/include/usbg/usbg.h b/include/usbg/usbg.h
index 31d9862..692c188 100644
--- a/include/usbg/usbg.h
+++ b/include/usbg/usbg.h
@@ -190,6 +190,7 @@ typedef enum
USBG_F_MASS_STORAGE,
USBG_F_MIDI,
USBG_F_LOOPBACK,
+ USBG_F_HID,
USBG_FUNCTION_TYPE_MAX,
} usbg_function_type;
diff --git a/src/Makefile.am b/src/Makefile.am
index 3f18281..98aebcd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,6 @@
AUTOMAKE_OPTIONS = std-options subdir-objects
lib_LTLIBRARIES = libusbgx.la
-libusbgx_la_SOURCES = usbg.c usbg_error.c usbg_common.c function/ether.c function/ffs.c function/midi.c function/ms.c function/phonet.c function/serial.c function/loopback.c
+libusbgx_la_SOURCES = usbg.c usbg_error.c usbg_common.c function/ether.c function/ffs.c function/midi.c function/ms.c function/phonet.c function/serial.c function/loopback.c function/hid.c
if TEST_GADGET_SCHEMES
libusbgx_la_SOURCES += usbg_schemes_libconfig.c
else
diff --git a/src/function/hid.c b/src/function/hid.c
new file mode 100644
index 0000000..a60333a
--- /dev/null
+++ b/src/function/hid.c
@@ -0,0 +1,349 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ */
+
+#include "usbg/usbg.h"
+#include "usbg/usbg_internal.h"
+#include "usbg/function/hid.h"
+
+#include <malloc.h>
+#include <assert.h>
+#ifdef HAS_LIBCONFIG
+#include <libconfig.h>
+#endif
+
+struct usbg_f_hid {
+ struct usbg_function func;
+};
+
+#define HID_DEC_ATTR(_name) \
+ { \
+ .name = #_name, \
+ .ro = false, \
+ .offset = offsetof(struct usbg_f_hid_attrs, _name), \
+ .get = usbg_get_dec, \
+ .set = usbg_set_dec, \
+ .import = usbg_get_config_node_int, \
+ .export = usbg_set_config_node_int, \
+ }
+
+#define HID_DEV_ATTR_RO(_name) \
+ { \
+ .name = #_name, \
+ .ro = true, \
+ .offset = offsetof(struct usbg_f_hid_attrs, _name), \
+ .get = usbg_get_dev, \
+ .export = usbg_set_config_node_dev, \
+ }
+
+static int hid_get_report(const char *path, const char *name, const char *attr,
+ void *val)
+{
+ struct usbg_f_hid_report_desc *report_desc = val;
+ char buf[USBG_MAX_FILE_SIZE];
+ int ret;
+
+ ret = usbg_read_buf(path, name, attr, buf);
+ if (ret < 0)
+ return ret;
+
+ report_desc->len = ret;
+ if (ret == 0) {
+ report_desc->desc = NULL;
+ } else {
+ report_desc->desc = malloc(report_desc->len);
+ if (!report_desc->desc)
+ return USBG_ERROR_NO_MEM;
+ memcpy(report_desc->desc, buf, report_desc->len);
+ }
+
+ return 0;
+}
+
+static int hid_set_report(const char *path, const char *name, const char *attr,
+ void *val)
+{
+ struct usbg_f_hid_report_desc *report_desc = val;
+ char *buf = report_desc->desc;
+ int len = report_desc->len;
+ int ret;
+
+ if (len == 0) {
+ buf = "";
+ len = 1;
+ }
+
+ ret = usbg_write_buf(path, name, attr, buf, len);
+ if (ret > 0)
+ ret = USBG_SUCCESS;
+
+ return ret;
+}
+
+static int hid_get_config_node_report(config_setting_t *root,
+ const char *node_name, void *val)
+{
+ struct usbg_f_hid_report_desc *report_desc = val;
+ char *buf;
+ int tmp, i;
+ config_setting_t *list_node, *node;
+ int len;
+ int ret;
+
+ list_node = config_setting_get_member(root, node_name);
+ if (!list_node)
+ return 0;
+
+ if (!config_setting_is_list(list_node))
+ return USBG_ERROR_INVALID_TYPE;
+
+ len = config_setting_length(list_node);
+
+ buf = malloc(len * sizeof(char));
+ if (!buf)
+ return USBG_ERROR_NO_MEM;
+
+ for (i = 0; i < len; ++i) {
+ node = config_setting_get_elem(list_node, i);
+ assert(node);
+
+ if (!usbg_config_is_int(node)) {
+ ret = USBG_ERROR_INVALID_TYPE;
+ goto free_buf;
+ }
+
+ tmp = config_setting_get_int(node);
+ if (tmp < 0 || tmp > 255) {
+ ret = USBG_ERROR_INVALID_VALUE;
+ goto free_buf;
+ }
+ buf[i] = (char)tmp;
+ }
+
+ report_desc->desc = buf;
+ report_desc->len = len;
+
+ return 1;
+
+free_buf:
+ free(buf);
+ return ret;
+}
+
+static int hid_set_config_node_report(config_setting_t *root,
+ const char *node_name, void *val)
+{
+ struct usbg_f_hid_report_desc *report_desc = val;
+ config_setting_t *node;
+ int i;
+ int ret = 0;
+
+ node = config_setting_add(root, node_name, CONFIG_TYPE_LIST);
+ if (!node)
+ return USBG_ERROR_NO_MEM;
+
+ for (i = 0; i < report_desc->len; ++i) {
+ int tmp = report_desc->desc[i];
+ ret = usbg_set_config_node_int_hex(node, NULL, &tmp);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+#define HID_RD_ATTR(_name) \
+ { \
+ .name = #_name, \
+ .ro = false, \
+ .offset = offsetof(struct usbg_f_hid_attrs, _name), \
+ .get = hid_get_report, \
+ .set = hid_set_report, \
+ .import = hid_get_config_node_report, \
+ .export = hid_set_config_node_report, \
+ }
+
+struct {
+ const char *name;
+ bool ro;
+ size_t offset;
+ usbg_attr_get_func get;
+ usbg_attr_set_func set;
+ usbg_import_node_func import;
+ usbg_export_node_func export;
+} hid_attr[USBG_F_HID_ATTR_MAX] = {
+ [USBG_F_HID_DEV] = HID_DEV_ATTR_RO(dev),
+ [USBG_F_HID_PROTOCOL] = HID_DEC_ATTR(protocol),
+ [USBG_F_HID_REPORT_DESC] = HID_RD_ATTR(report_desc),
+ [USBG_F_HID_REPORT_LENGTH] = HID_DEC_ATTR(report_length),
+ [USBG_F_HID_SUBCLASS] = HID_DEC_ATTR(subclass),
+};
+
+#undef HID_DEC_ATTR
+#undef HID_DEV_ATTR_RO
+#undef HID_RD_ATTR
+
+GENERIC_ALLOC_INST(hid, struct usbg_f_hid, func);
+
+GENERIC_FREE_INST(hid, struct usbg_f_hid, func);
+
+static int hid_set_attrs(struct usbg_function *f, void *f_attrs)
+{
+ return usbg_f_hid_set_attrs(usbg_to_hid_function(f), f_attrs);
+}
+
+static int hid_get_attrs(struct usbg_function *f, void *f_attrs)
+{
+ return usbg_f_hid_get_attrs(usbg_to_hid_function(f), f_attrs);
+}
+
+static void hid_cleanup_attrs(struct usbg_function *f, void *f_attrs)
+{
+ usbg_f_hid_cleanup_attrs(f_attrs);
+}
+
+#ifdef HAS_LIBCONFIG
+
+static int hid_libconfig_import(struct usbg_function *f,
+ config_setting_t *root)
+{
+ struct usbg_f_hid *hf = usbg_to_hid_function(f);
+ union usbg_f_hid_attr_val val;
+ int i;
+ int ret = 0;
+
+ for (i = USBG_F_HID_ATTR_MIN; i < USBG_F_HID_ATTR_MAX; ++i) {
+ if (hid_attr[i].ro)
+ continue;
+
+ ret = hid_attr[i].import(root, hid_attr[i].name, &val);
+ /* node not found */
+ if (ret == 0)
+ continue;
+ /* error */
+ if (ret < 0)
+ break;
+
+ ret = usbg_f_hid_set_attr_val(hf, i, val);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+static int hid_libconfig_export(struct usbg_function *f,
+ config_setting_t *root)
+{
+ struct usbg_f_hid *hf = usbg_to_hid_function(f);
+ union usbg_f_hid_attr_val val;
+ int i;
+ int ret = 0;
+
+ for (i = USBG_F_HID_ATTR_MIN; i < USBG_F_HID_ATTR_MAX; ++i) {
+ ret = usbg_f_hid_get_attr_val(hf, i, &val);
+ if (ret)
+ break;
+
+ ret = hid_attr[i].export(root, hid_attr[i].name, &val);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+#endif /* HAS_LIBCONFIG */
+
+struct usbg_function_type usbg_f_type_hid = {
+ .name = "hid",
+ .alloc_inst = hid_alloc_inst,
+ .free_inst = hid_free_inst,
+ .set_attrs = hid_set_attrs,
+ .get_attrs = hid_get_attrs,
+ .cleanup_attrs = hid_cleanup_attrs,
+
+#ifdef HAS_LIBCONFIG
+ .import = hid_libconfig_import,
+ .export = hid_libconfig_export,
+#endif
+};
+
+/* API implementation */
+
+usbg_f_hid *usbg_to_hid_function(usbg_function *f)
+{
+ return f->ops == &usbg_f_type_hid ?
+ container_of(f, struct usbg_f_hid, func) : NULL;
+}
+
+usbg_function *usbg_from_hid_function(usbg_f_hid *hf)
+{
+ return &hf->func;
+}
+
+int usbg_f_hid_get_attrs(usbg_f_hid *hf,
+ struct usbg_f_hid_attrs *attrs)
+{
+ int i;
+ int ret = 0;
+
+ for (i = USBG_F_HID_ATTR_MIN; i < USBG_F_HID_ATTR_MAX; ++i) {
+ ret = usbg_f_hid_get_attr_val(hf, i,
+ (union usbg_f_hid_attr_val *)
+ ((char *)attrs
+ + hid_attr[i].offset));
+ if (ret)
+ break;
+ }
+
+ return ret;
+
+}
+
+int usbg_f_hid_set_attrs(usbg_f_hid *hf,
+ const struct usbg_f_hid_attrs *attrs)
+{
+ int i;
+ int ret = 0;
+
+ for (i = USBG_F_HID_ATTR_MIN; i < USBG_F_HID_ATTR_MAX; ++i) {
+ if (hid_attr[i].ro)
+ continue;
+
+ ret = usbg_f_hid_set_attr_val(hf, i,
+ *(union usbg_f_hid_attr_val *)
+ ((char *)attrs
+ + hid_attr[i].offset));
+ if (ret)
+ break;
+ }
+
+ return ret;
+
+}
+
+int usbg_f_hid_get_attr_val(usbg_f_hid *hf, enum usbg_f_hid_attr attr,
+ union usbg_f_hid_attr_val *val)
+{
+ return hid_attr[attr].get(hf->func.path, hf->func.name,
+ hid_attr[attr].name, val);
+}
+
+int usbg_f_hid_set_attr_val(usbg_f_hid *hf, enum usbg_f_hid_attr attr,
+ union usbg_f_hid_attr_val val)
+{
+ return hid_attr[attr].ro ?
+ USBG_ERROR_INVALID_PARAM :
+ hid_attr[attr].set(hf->func.path, hf->func.name,
+ hid_attr[attr].name, &val);
+}
+
diff --git a/src/usbg.c b/src/usbg.c
index fb6ee4b..3a2c674 100644
--- a/src/usbg.c
+++ b/src/usbg.c
@@ -50,6 +50,7 @@ extern struct usbg_function_type usbg_f_type_midi;
extern struct usbg_function_type usbg_f_type_ms;
extern struct usbg_function_type usbg_f_type_phonet;
extern struct usbg_function_type usbg_f_type_loopback;
+extern struct usbg_function_type usbg_f_type_hid;
/**
* @var function_types
@@ -69,6 +70,7 @@ struct usbg_function_type* function_types[] = {
[USBG_F_MASS_STORAGE] = &usbg_f_type_ms,
[USBG_F_PHONET] = &usbg_f_type_phonet,
[USBG_F_LOOPBACK] = &usbg_f_type_loopback,
+ [USBG_F_HID] = &usbg_f_type_hid,
};
ARRAY_SIZE_SENTINEL(function_types, USBG_FUNCTION_TYPE_MAX);