summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorKrzysztof Opasiak <k.opasiak@samsung.com>2016-08-10 22:45:34 +0200
committerKrzysztof Opasiak <k.opasiak@samsung.com>2016-09-05 15:27:11 +0200
commitd52b16382cccd1df1d827ed6339acceebdb410ec (patch)
tree319488293dd6765635cae51ed22846089112a5c1 /hw
parente34e02fd4918405cebc4fc468a54cb66c4e041f0 (diff)
downloadlibdevice-node-d52b16382cccd1df1d827ed6339acceebdb410ec.tar.gz
libdevice-node-d52b16382cccd1df1d827ed6339acceebdb410ec.tar.bz2
libdevice-node-d52b16382cccd1df1d827ed6339acceebdb410ec.zip
USB gadget HAL API
This API provides translation between set of functions which should be available and abstract USB gadget description (reprezented by struct usb_gadget). This HAL can be used bo both define new values for VendorID, ProductID and other stuff, and alse to add some new function available only on this particular device (vendor specific). Change-Id: I63464d9828bfc3fbf06a77d5d9fea82341bddf45 Signed-off-by: Krzysztof Opasiak <k.opasiak@samsung.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/usb_gadget.h298
1 files changed, 298 insertions, 0 deletions
diff --git a/hw/usb_gadget.h b/hw/usb_gadget.h
new file mode 100644
index 0000000..2db9566
--- /dev/null
+++ b/hw/usb_gadget.h
@@ -0,0 +1,298 @@
+/*
+ * libdevice-node
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __HW_USB_GADGET_H__
+#define __HW_USB_GADGET_H__
+
+#include <hw/common.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <errno.h>
+
+/**
+ * The id of this device
+ */
+#define USB_GADGET_DEVICE_ID "usb_gadget"
+
+/**
+ * The version of this device
+ */
+#define USB_GADGET_DEVICE_VERSION MAKE_VERSION(0,1)
+
+#ifndef container_of
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+#endif
+
+#define _HELPER_Y(x) ((x) & -(x))
+
+/* Count number of trailing zeros using Dean Gaudet's algorithm */
+#define _HELPER_CTZ(mask) \
+ ((_HELPER_Y(mask) ? 0 : 1) + \
+ ((_HELPER_Y(mask) & 0x0000FFFF) ? 0 : 16) + \
+ ((_HELPER_Y(mask) & 0x00FF00FF) ? 0 : 8) + \
+ ((_HELPER_Y(mask) & 0x0F0F0F0F) ? 0 : 4) + \
+ ((_HELPER_Y(mask) & 0x33333333) ? 0 : 2) + \
+ ((_HELPER_Y(mask) & 0x55555555) ? 0 : 1))
+
+/* Function IDX in array is number of trailing zeros */
+#define FUNC_IDX_FROM_MASK(mask) _HELPER_CTZ(mask)
+
+typedef enum {
+ USB_FUNCTION_GROUP_SIMPLE,
+ USB_FUNCTION_GROUP_WITH_SERVICE,
+} usb_function_group_e;
+
+struct usb_function {
+ int function_group;
+ int id;
+ char *name;
+ char *instance;
+
+ int (*clone)(struct usb_function *func, struct usb_function **_clone);
+ void (*free_func)(struct usb_function *func);
+};
+
+struct usb_function_with_service {
+ struct usb_function func;
+ const char *service;
+};
+
+struct usb_configuration_attributes {
+ uint8_t bmAttributs;
+ int MaxPower;
+};
+
+struct usb_configuration_strings {
+ uint16_t lang_code;
+ char *config_str;
+};
+
+struct usb_configuration {
+ struct usb_configuration_attributes attrs;
+ struct usb_configuration_strings *strs;
+ struct usb_function **funcs;
+};
+
+struct usb_gadget_attrs {
+ uint8_t bDeviceClass;
+ uint8_t bDeviceSubClass;
+ uint8_t bDeviceProtocol;
+ uint16_t idVendor;
+ uint16_t idProduct;
+ uint16_t bcdDevice;
+};
+
+struct usb_gadget_strings {
+ uint16_t lang_code;
+ char *manufacturer;
+ char *product;
+ char *serial;
+};
+
+struct usb_gadget {
+ struct usb_gadget_attrs attrs;
+ struct usb_gadget_strings *strs;
+ struct usb_function **funcs;
+ struct usb_configuration **configs;
+};
+
+typedef enum {
+ USB_FUNCTION_NONE = 0,
+ USB_FUNCTION_MTP = 1 << 0,
+ USB_FUNCTION_ACM = 1 << 1,
+ USB_FUNCTION_SDB = 1 << 2,
+ USB_FUNCTION_RNDIS = 1 << 3,
+ USB_FUNCTION_DIAG = 1 << 4,
+ USB_FUNCTION_CONN_GADGET = 1 << 5,
+ USB_FUNCTION_DM = 1 << 6,
+ USB_FUNCTION_RMNET = 1 << 7,
+} usb_function_e;
+
+static void free_simple_func_content(struct usb_function *func)
+{
+ free(func->name);
+ free(func->instance);
+}
+
+static void free_simple_func(struct usb_function *func)
+{
+ free_simple_func_content(func);
+ free(func);
+}
+
+static int clone_simple_func_to(struct usb_function *func,
+ struct usb_function *other)
+{
+ *other = *func;
+ other->name = strdup(func->name);
+ other->instance = strdup(func->instance);
+
+ if (!other->name || !other->instance)
+ goto free_strs;
+
+ return 0;
+free_strs:
+ free(other->name);
+ free(other->instance);
+ return -ENOMEM;
+}
+
+static int clone_simple_func(struct usb_function *func,
+ struct usb_function **clone)
+{
+ struct usb_function *other;
+ int ret;
+
+ if (!func || !clone)
+ return -EINVAL;
+
+ other = malloc(sizeof(*other));
+ if (!other)
+ goto out;
+
+ ret = clone_simple_func_to(func, other);
+ if (ret)
+ goto free_other;
+
+ *clone = other;
+ return 0;
+free_other:
+ free(other);
+out:
+ return -ENOMEM;
+}
+
+#define DEFINE_SIMPLE_USB_FUNCTION(_id, _name) \
+ static struct usb_function _##_name##_function = { \
+ .function_group = USB_FUNCTION_GROUP_SIMPLE, \
+ .id = _id, \
+ .name = #_name, \
+ .instance = "default", \
+ .free_func = free_simple_func, \
+ .clone = clone_simple_func, \
+ }
+
+DEFINE_SIMPLE_USB_FUNCTION(USB_FUNCTION_ACM, acm);
+DEFINE_SIMPLE_USB_FUNCTION(USB_FUNCTION_RNDIS, rndis);
+DEFINE_SIMPLE_USB_FUNCTION(USB_FUNCTION_DIAG, diag);
+DEFINE_SIMPLE_USB_FUNCTION(USB_FUNCTION_RMNET, rmnet);
+DEFINE_SIMPLE_USB_FUNCTION(USB_FUNCTION_DM, dm);
+DEFINE_SIMPLE_USB_FUNCTION(USB_FUNCTION_CONN_GADGET, conn_gadget);
+
+#undef DEFINE_SIMPLE_USB_FUNCTION
+
+static void free_func_with_service(struct usb_function *func)
+{
+ struct usb_function_with_service *fws;
+
+ fws = container_of(func, struct usb_function_with_service, func);
+
+ free_simple_func_content(func);
+ free(fws->service);
+ free(fws);
+}
+
+static int clone_func_with_service(struct usb_function *func,
+ struct usb_function **clone)
+{
+ struct usb_function_with_service *fws;
+ struct usb_function_with_service *other;
+ int ret;
+
+ if (!func || !clone)
+ return -EINVAL;
+
+ other = malloc(sizeof(*other));
+ if (!other)
+ goto out;
+
+ ret = clone_simple_func_to(func, &other->func);
+ if (ret)
+ goto free_other;
+
+ fws = container_of(func, struct usb_function_with_service, func);
+ if (fws->service) {
+ other->service = strdup(fws->service);
+ if (!other->service)
+ goto free_content;
+ } else {
+ other->service = NULL;
+ }
+
+ *clone = &other->func;
+ return 0;
+free_content:
+ free_simple_func_content(&other->func);
+free_other:
+ free(other);
+out:
+ return -ENOMEM;
+}
+
+#define DEFINE_USB_FUNCTION_WITH_SERVICE(_id, _name) \
+ static struct usb_function_with_service _##_name##_function = { \
+ .func = { \
+ .function_group = USB_FUNCTION_GROUP_WITH_SERVICE, \
+ .id = _id, \
+ .name = #_name, \
+ .instance = "default", \
+ .free_func = free_func_with_service, \
+ .clone = clone_func_with_service, \
+ }, \
+ .service = NULL, \
+ }
+
+DEFINE_USB_FUNCTION_WITH_SERVICE(USB_FUNCTION_SDB, sdb);
+DEFINE_USB_FUNCTION_WITH_SERVICE(USB_FUNCTION_MTP, mtp);
+
+#define MAKE_FUNC_AVAILABLE(_name, _vname) \
+ [FUNC_IDX_FROM_MASK(USB_FUNCTION_##_name)] = &_##_vname##_function
+
+#define MAKE_FUNC_WS_AVAILABLE(_name, _vname) \
+ [FUNC_IDX_FROM_MASK(USB_FUNCTION_##_name)] = &_##_vname##_function.func
+
+static struct usb_function *_available_funcs[] = {
+ MAKE_FUNC_WS_AVAILABLE(MTP, mtp),
+ MAKE_FUNC_AVAILABLE(ACM, acm),
+ MAKE_FUNC_WS_AVAILABLE(SDB, sdb),
+ MAKE_FUNC_AVAILABLE(RNDIS, rndis),
+ MAKE_FUNC_AVAILABLE(DIAG, diag),
+ MAKE_FUNC_AVAILABLE(CONN_GADGET, conn_gadget),
+ MAKE_FUNC_AVAILABLE(DM, dm),
+ MAKE_FUNC_AVAILABLE(RMNET, rmnet),
+};
+
+#undef MAKE_FUNC_AVAILABLE
+
+struct usb_gadget_id {
+ unsigned int function_mask;
+};
+
+struct usb_gadget_translator {
+ struct hw_common common;
+
+ int (*id_to_gadget)(struct usb_gadget_id *gadget_id,
+ struct usb_gadget **gadget);
+
+ void (*cleanup_gadget)(struct usb_gadget *gadget);
+};
+
+#endif