4 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 #ifndef __HW_USB_GADGET_H__
20 #define __HW_USB_GADGET_H__
22 #include <hw/common.h>
30 * The id of this device
32 #define USB_GADGET_DEVICE_ID "usb_gadget"
35 * The version of this device
37 #define USB_GADGET_DEVICE_VERSION MAKE_VERSION(0,1)
39 #define _HELPER_Y(x) ((x) & -(x))
41 /* Count number of trailing zeros using Dean Gaudet's algorithm */
42 #define _HELPER_CTZ(mask) \
43 ((_HELPER_Y(mask) ? 0 : 1) + \
44 ((_HELPER_Y(mask) & 0x0000FFFF) ? 0 : 16) + \
45 ((_HELPER_Y(mask) & 0x00FF00FF) ? 0 : 8) + \
46 ((_HELPER_Y(mask) & 0x0F0F0F0F) ? 0 : 4) + \
47 ((_HELPER_Y(mask) & 0x33333333) ? 0 : 2) + \
48 ((_HELPER_Y(mask) & 0x55555555) ? 0 : 1))
50 /* Function IDX in array is number of trailing zeros */
51 #define FUNC_IDX_FROM_MASK(mask) _HELPER_CTZ(mask)
54 USB_FUNCTION_GROUP_SIMPLE,
55 USB_FUNCTION_GROUP_WITH_SERVICE,
56 } usb_function_group_e;
64 int (*clone)(struct usb_function *func, struct usb_function **_clone);
65 void (*free_func)(struct usb_function *func);
68 struct usb_function_with_service {
69 struct usb_function func;
73 struct usb_configuration_attributes {
78 struct usb_configuration_strings {
83 struct usb_configuration {
84 struct usb_configuration_attributes attrs;
85 struct usb_configuration_strings *strs;
86 struct usb_function **funcs;
89 struct usb_gadget_attrs {
91 uint8_t bDeviceSubClass;
92 uint8_t bDeviceProtocol;
98 struct usb_gadget_strings {
106 struct usb_gadget_attrs attrs;
107 struct usb_gadget_strings *strs;
108 struct usb_function **funcs;
109 struct usb_configuration **configs;
113 USB_FUNCTION_NONE = 0,
114 USB_FUNCTION_MTP = 1 << 0,
115 USB_FUNCTION_ACM = 1 << 1,
116 USB_FUNCTION_SDB = 1 << 2,
117 USB_FUNCTION_RNDIS = 1 << 3,
118 USB_FUNCTION_DIAG = 1 << 4,
119 USB_FUNCTION_CONN_GADGET = 1 << 5,
120 USB_FUNCTION_DM = 1 << 6,
121 USB_FUNCTION_RMNET = 1 << 7,
124 static void free_simple_func_content(struct usb_function *func)
126 free((void *)func->name);
127 free((void *)func->instance);
130 static void free_simple_func(struct usb_function *func)
132 free_simple_func_content(func);
136 static int clone_simple_func_to(struct usb_function *func,
137 struct usb_function *other)
140 other->name = strdup(func->name);
141 other->instance = strdup(func->instance);
143 if (!other->name || !other->instance)
148 free((void *)other->name);
149 free((void *)other->instance);
153 static int clone_simple_func(struct usb_function *func,
154 struct usb_function **clone)
156 struct usb_function *other;
162 other = (struct usb_function *)malloc(sizeof(*other));
166 ret = clone_simple_func_to(func, other);
178 #define DEFINE_SIMPLE_USB_FUNCTION(_id, _name) \
179 static struct usb_function _##_name##_function = { \
180 .function_group = USB_FUNCTION_GROUP_SIMPLE, \
183 .instance = "default", \
184 .clone = clone_simple_func, \
185 .free_func = free_simple_func, \
188 DEFINE_SIMPLE_USB_FUNCTION(USB_FUNCTION_ACM, acm);
189 DEFINE_SIMPLE_USB_FUNCTION(USB_FUNCTION_RNDIS, rndis);
190 DEFINE_SIMPLE_USB_FUNCTION(USB_FUNCTION_DIAG, diag);
191 DEFINE_SIMPLE_USB_FUNCTION(USB_FUNCTION_RMNET, rmnet);
192 DEFINE_SIMPLE_USB_FUNCTION(USB_FUNCTION_DM, dm);
193 DEFINE_SIMPLE_USB_FUNCTION(USB_FUNCTION_CONN_GADGET, conn_gadget);
195 #undef DEFINE_SIMPLE_USB_FUNCTION
197 static void free_func_with_service(struct usb_function *func)
199 struct usb_function_with_service *fws;
201 fws = container_of(func, struct usb_function_with_service, func);
203 free_simple_func_content(func);
204 free((void *)fws->service);
208 static int clone_func_with_service(struct usb_function *func,
209 struct usb_function **clone)
211 struct usb_function_with_service *fws;
212 struct usb_function_with_service *other;
218 other = (struct usb_function_with_service *)malloc(sizeof(*other));
222 ret = clone_simple_func_to(func, &other->func);
226 fws = container_of(func, struct usb_function_with_service, func);
228 other->service = strdup(fws->service);
232 other->service = NULL;
235 *clone = &other->func;
238 free_simple_func_content(&other->func);
245 #define DEFINE_USB_FUNCTION_WITH_SERVICE(_id, _name, _service) \
246 static struct usb_function_with_service _##_name##_function = { \
248 .function_group = USB_FUNCTION_GROUP_WITH_SERVICE, \
251 .instance = "default", \
252 .clone = clone_func_with_service, \
253 .free_func = free_func_with_service, \
255 .service = _service, \
258 DEFINE_USB_FUNCTION_WITH_SERVICE(USB_FUNCTION_SDB, sdb, "sdbd");
259 DEFINE_USB_FUNCTION_WITH_SERVICE(USB_FUNCTION_MTP, mtp, "mtp-responder");
261 #define MAKE_FUNC_AVAILABLE(_name, _vname) \
262 [FUNC_IDX_FROM_MASK(USB_FUNCTION_##_name)] = &_##_vname##_function
264 #define MAKE_FUNC_WS_AVAILABLE(_name, _vname) \
265 [FUNC_IDX_FROM_MASK(USB_FUNCTION_##_name)] = &_##_vname##_function.func
267 static struct usb_function *_available_funcs[] = {
268 MAKE_FUNC_WS_AVAILABLE(MTP, mtp),
269 MAKE_FUNC_AVAILABLE(ACM, acm),
270 MAKE_FUNC_WS_AVAILABLE(SDB, sdb),
271 MAKE_FUNC_AVAILABLE(RNDIS, rndis),
272 MAKE_FUNC_AVAILABLE(DIAG, diag),
273 MAKE_FUNC_AVAILABLE(CONN_GADGET, conn_gadget),
274 MAKE_FUNC_AVAILABLE(DM, dm),
275 MAKE_FUNC_AVAILABLE(RMNET, rmnet),
278 #undef MAKE_FUNC_AVAILABLE
280 struct usb_gadget_id {
281 unsigned int function_mask;
284 struct usb_gadget_translator {
285 struct hw_common common;
287 int (*id_to_gadget)(struct usb_gadget_id *gadget_id,
288 struct usb_gadget **gadget);
290 void (*cleanup_gadget)(struct usb_gadget *gadget);
293 int simple_translator_open(struct hw_info *info,
294 const char *id, struct hw_common **common);
295 int simple_translator_close(struct hw_common *common);