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_SIMPLE_TRANSLATOR_H__
21 #include <hw/usb_gadget.h>
27 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
28 #define zalloc(amount) calloc(1, amount)
30 /* Based on slp-gadget and initial version of USB HAL by Taeyoung Kim */
31 #define DEFAULT_VID 0x04e8
32 #define DEFAULT_PID 0x6860
33 #define DEFAULT_BCD_DEVICE 0xffff
35 #define DEFAULT_LANG 0x409 /* US_en */
36 #define DEFAULT_MANUFACTURER "Samsung"
37 #define DEFAULT_PRODUCT "TIZEN"
38 #define DEFAULT_SERIAL "01234TEST"
40 #define DEFAULT_BMATTRIBUTES ((1 << 7) | (1 << 6))
41 #define DEFAULT_MAX_POWER 500
43 static void simple_cleanup_config(struct usb_configuration *config)
51 for (i = 0; config->strs[i].lang_code; ++i)
52 free(config->strs[i].config_str);
58 * Each function will be free later,
59 * for now we cleanup only pointers.
67 static void simple_cleanup_gadget(struct usb_gadget *gadget)
75 for (i = 0; gadget->strs[i].lang_code; ++i) {
76 free(gadget->strs[i].manufacturer);
77 free(gadget->strs[i].product);
78 free(gadget->strs[i].serial);
83 if (gadget->configs) {
84 for (i = 0; gadget->configs[i]; ++i)
85 simple_cleanup_config(gadget->configs[i]);
87 free(gadget->configs);
91 for (i = 0; gadget->funcs[i]; ++i)
92 gadget->funcs[i]->free_func(gadget->funcs[i]);
100 static int alloc_default_config(struct usb_configuration **_config)
102 struct usb_configuration *config;
104 config = zalloc(sizeof(*config));
108 config->strs = calloc(1, sizeof(*config->strs));
112 config->attrs.bmAttributs = DEFAULT_BMATTRIBUTES;
113 config->attrs.MaxPower = DEFAULT_MAX_POWER;
125 static int alloc_default_gadget(struct usb_gadget **_gadget)
127 struct usb_gadget *gadget;
128 struct usb_gadget_strings *strs;
129 struct usb_configuration **configs;
131 gadget = zalloc(sizeof(*gadget));
135 gadget->attrs.idVendor = DEFAULT_VID;
136 gadget->attrs.idProduct = DEFAULT_PID;
137 gadget->attrs.bcdDevice = DEFAULT_BCD_DEVICE;
139 strs = calloc(2, sizeof(*strs));
143 strs[0].lang_code = 0x409;
144 strs[0].manufacturer = strdup(DEFAULT_MANUFACTURER);
145 strs[0].product = strdup(DEFAULT_PRODUCT);
146 strs[0].serial = strdup(DEFAULT_SERIAL);
148 if (!strs[0].manufacturer || !strs[0].product || !strs[0].serial)
153 /* slp-gadget use max 2 confiuration and NULL termination */
154 configs = calloc(3, sizeof(*configs));
158 gadget->configs = configs;
164 free(strs[0].manufacturer);
165 free(strs[0].product);
166 free(strs[0].serial);
174 static inline struct usb_function *find_func(struct usb_gadget *gadget,
179 for (i = 0; gadget->funcs[i] && gadget->funcs[i]->id != func_id; ++i);
181 return gadget->funcs[i];
184 static int simple_id_to_gadget(struct usb_gadget_id *gadget_id,
185 struct usb_gadget **_gadget)
187 struct usb_gadget *gadget;
189 /* zero terminates */
190 int functions[2][sizeof(gadget_id->function_mask)*8];
192 struct usb_function **funcs;
196 if (!gadget_id || !_gadget)
199 ret = alloc_default_gadget(&gadget);
204 * Currently all gadgets use inly single configuration but
205 * slp-gadget is capable to handle two of them
207 * Order of interfaces in configuration is significant
208 * so in this switch we sort our functions in a correct order
210 switch (gadget_id->function_mask) {
211 case USB_FUNCTION_SDB:
213 functions[0][0] = USB_FUNCTION_SDB;
215 gadget->attrs.idProduct = 0x685d;
217 case USB_FUNCTION_MTP:
219 functions[0][0] = USB_FUNCTION_MTP;
221 gadget->attrs.idProduct = 0x6860;
223 case USB_FUNCTION_RNDIS:
225 functions[0][0] = USB_FUNCTION_RNDIS;
227 gadget->attrs.idProduct = 0x6863;
229 case USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB:
231 functions[0][0] = USB_FUNCTION_MTP;
232 functions[0][1] = USB_FUNCTION_ACM;
233 functions[0][2] = USB_FUNCTION_SDB;
235 gadget->attrs.idProduct = 0x6860;
237 case USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB
240 functions[0][0] = USB_FUNCTION_MTP;
241 functions[0][1] = USB_FUNCTION_ACM;
242 functions[0][2] = USB_FUNCTION_SDB;
243 functions[0][3] = USB_FUNCTION_DIAG;
245 gadget->attrs.idProduct = 0x6860;
247 case USB_FUNCTION_RNDIS | USB_FUNCTION_SDB:
249 functions[0][0] = USB_FUNCTION_RNDIS;
250 functions[0][1] = USB_FUNCTION_SDB;
252 gadget->attrs.idProduct = 0x6864;
254 case USB_FUNCTION_RNDIS | USB_FUNCTION_SDB | USB_FUNCTION_ACM | USB_FUNCTION_DIAG:
256 functions[0][0] = USB_FUNCTION_RNDIS;
257 functions[0][1] = USB_FUNCTION_SDB;
258 functions[0][2] = USB_FUNCTION_ACM;
259 functions[0][3] = USB_FUNCTION_DIAG;
261 gadget->attrs.idProduct = 0x6864;
263 case USB_FUNCTION_RNDIS | USB_FUNCTION_DIAG:
265 functions[0][0] = USB_FUNCTION_RNDIS;
266 functions[0][1] = USB_FUNCTION_DIAG;
268 gadget->attrs.idProduct = 0x6864;
270 case USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_DM:
272 functions[0][0] = USB_FUNCTION_ACM;
273 functions[0][1] = USB_FUNCTION_SDB;
274 functions[0][2] = USB_FUNCTION_DM;
276 gadget->attrs.idProduct = 0x6860;
278 case USB_FUNCTION_DIAG | USB_FUNCTION_ACM | USB_FUNCTION_RMNET:
280 functions[0][0] = USB_FUNCTION_DIAG;
281 functions[0][1] = USB_FUNCTION_ACM;
282 functions[0][2] = USB_FUNCTION_RMNET;
284 gadget->attrs.idProduct = 0x685d;
293 n_functions = __builtin_popcount(gadget_id->function_mask);
295 funcs = calloc(n_functions + 1, sizeof(*funcs));
301 gadget->funcs = funcs;
304 for (i = 0; i < ARRAY_SIZE(_available_funcs); ++i) {
305 int func_id = 1 << i;
307 if (!(gadget_id->function_mask & func_id))
310 ret = _available_funcs[i]->clone(_available_funcs[i],
311 gadget->funcs + idx);
317 for (j = 0; j < n_configs; ++j) {
318 struct usb_configuration *config;
319 int n_funcs_in_config;
321 for (i = 0; functions[j][i]; ++i);
322 n_funcs_in_config = i;
324 ret = alloc_default_config(&config);
328 gadget->configs[j] = config;
329 config->funcs = calloc(n_funcs_in_config + 1,
334 for (i = 0; functions[j][i]; ++i)
335 config->funcs[i] = find_func(gadget, functions[j][i]);
343 simple_cleanup_gadget(gadget);
348 static int simple_translator_open(struct hw_info *info,
349 const char *id, struct hw_common **common)
351 struct usb_gadget_translator *simple_translator;
353 if (!info || !common)
356 simple_translator = zalloc(sizeof(*simple_translator));
357 if (!simple_translator)
360 simple_translator->common.info = info;
361 simple_translator->id_to_gadget = simple_id_to_gadget;
362 simple_translator->cleanup_gadget = simple_cleanup_gadget;
364 *common = &simple_translator->common;
368 static int simple_translator_close(struct hw_common *common)
370 struct usb_gadget_translator *simple_translator;
375 simple_translator = container_of(common, struct usb_gadget_translator,
378 free(simple_translator);
382 HARDWARE_MODULE_STRUCTURE = {
383 .magic = HARDWARE_INFO_TAG,
384 .hal_version = HARDWARE_INFO_VERSION,
385 .device_version = USB_GADGET_DEVICE_VERSION,
386 .id = USB_GADGET_DEVICE_ID,
387 .name = "simple_translator",
388 .open = simple_translator_open,
389 .close = simple_translator_close,