2 * flash-manager - Tizen kernel-level image flashing solution
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
23 #include <sys/types.h>
24 #include <sys/mount.h>
28 #include <usbg/usbg.h>
29 #include <asm/byteorder.h>
31 #include <linux/usb/functionfs.h>
32 #include <linux/usb/cdc.h>
34 #include "interface.h"
36 #define TFMFFS_PATH "/dev/tfmffs"
37 #define TFMFFS_GADGET "g1"
38 #define TFMFFS_DEV "tfm"
39 #define TFMFFS_BIND_LINK "tfm.ffs"
40 #define TFMFFS_VID 0x04e8
41 #define TFMFFS_PID 0x685d
54 int eps[TFMFFS_EP_MAX];
58 pthread_mutex_t mutex;
62 struct usbg_gadget_attrs g_attrs = {
63 .idVendor = TFMFFS_VID,
64 .idProduct = TFMFFS_PID,
67 struct usbg_gadget_strs g_strs = {
68 .serial = "Unavailable", /* Serial number */
69 .manufacturer = "Tizen", /* Manufacturer */
70 .product = "iot-refboard" /* Product string */
73 struct usbg_config_strs c_strs = {
74 .configuration = "Conf 1"
77 /******************** Descriptors and Strings *******************************/
80 struct usb_functionfs_descs_head header;
82 struct usb_interface_descriptor acm;
83 struct usb_endpoint_descriptor_no_audio int_in;
84 struct usb_interface_descriptor intf;
85 struct usb_endpoint_descriptor_no_audio bulk_in;
86 struct usb_endpoint_descriptor_no_audio bulk_out;
87 } __attribute__ ((__packed__)) fs_descs, hs_descs;
88 } __attribute__ ((__packed__)) descriptors = {
90 .magic = __cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC),
91 .length = __cpu_to_le32(sizeof(descriptors)),
92 .fs_count = __cpu_to_le32(5),
93 .hs_count = __cpu_to_le32(5),
97 .bLength = sizeof(descriptors.fs_descs.intf),
98 .bDescriptorType = USB_DT_INTERFACE,
99 .bInterfaceNumber = 0,
101 .bInterfaceClass = USB_CLASS_COMM,
102 .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
103 .bInterfaceProtocol = USB_CDC_ACM_PROTO_AT_V25TER,
107 .bLength = sizeof(descriptors.fs_descs.bulk_in),
108 .bDescriptorType = USB_DT_ENDPOINT,
109 .bEndpointAddress = 3 | USB_DIR_IN,
110 .bmAttributes = USB_ENDPOINT_XFER_INT,
113 .bLength = sizeof(descriptors.fs_descs.intf),
114 .bDescriptorType = USB_DT_INTERFACE,
115 .bInterfaceNumber = 1,
117 .bInterfaceClass = USB_CLASS_CDC_DATA,
121 .bLength = sizeof(descriptors.fs_descs.bulk_in),
122 .bDescriptorType = USB_DT_ENDPOINT,
123 .bEndpointAddress = 1 | USB_DIR_IN,
124 .bmAttributes = USB_ENDPOINT_XFER_BULK,
127 .bLength = sizeof(descriptors.fs_descs.bulk_out),
128 .bDescriptorType = USB_DT_ENDPOINT,
129 .bEndpointAddress = 2 | USB_DIR_OUT,
130 .bmAttributes = USB_ENDPOINT_XFER_BULK,
135 .bLength = sizeof(descriptors.fs_descs.intf),
136 .bDescriptorType = USB_DT_INTERFACE,
137 .bInterfaceNumber = 0,
139 .bInterfaceClass = USB_CLASS_COMM,
140 .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
141 .bInterfaceProtocol = USB_CDC_ACM_PROTO_AT_V25TER,
145 .bLength = sizeof(descriptors.fs_descs.bulk_in),
146 .bDescriptorType = USB_DT_ENDPOINT,
147 .bEndpointAddress = 3 | USB_DIR_IN,
148 .bmAttributes = USB_ENDPOINT_XFER_INT,
149 .wMaxPacketSize = __cpu_to_le16(16),
153 .bLength = sizeof(descriptors.hs_descs.intf),
154 .bDescriptorType = USB_DT_INTERFACE,
155 .bInterfaceNumber = 1,
157 .bInterfaceClass = USB_CLASS_CDC_DATA,
161 .bLength = sizeof(descriptors.hs_descs.bulk_in),
162 .bDescriptorType = USB_DT_ENDPOINT,
163 .bEndpointAddress = 1 | USB_DIR_IN,
164 .bmAttributes = USB_ENDPOINT_XFER_BULK,
165 .wMaxPacketSize = __cpu_to_le16(512),
168 .bLength = sizeof(descriptors.hs_descs.bulk_out),
169 .bDescriptorType = USB_DT_ENDPOINT,
170 .bEndpointAddress = 2 | USB_DIR_OUT,
171 .bmAttributes = USB_ENDPOINT_XFER_BULK,
172 .wMaxPacketSize = __cpu_to_le16(512),
177 #define STR_INTERFACE "TIZEN USB DRIVER"
179 static const struct {
180 struct usb_functionfs_strings_head header;
183 const char str1[sizeof(STR_INTERFACE)];
184 } __attribute__ ((__packed__)) lang0;
185 } __attribute__ ((__packed__)) strings = {
187 .magic = __cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC),
188 .length = __cpu_to_le32(sizeof(strings)),
189 .str_count = __cpu_to_le32(1),
190 .lang_count = __cpu_to_le32(1),
193 __cpu_to_le16(0x0409), /* en-us */
198 static ssize_t usb_rx_data(int fd, void *buf, ssize_t len)
200 return read(fd, buf, len);
203 static ssize_t usb_tx_data(int fd, void *buf, ssize_t len)
205 return write(fd, buf, len);
208 static void *ep0_handler(void *data)
210 struct usb_context *ctx = data;
211 struct usb_functionfs_event evt;
212 int ret, ep0 = ctx->eps[TFMFFS_EP0];
214 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
217 ret = read(ep0, &evt, sizeof(evt));
222 case FUNCTIONFS_SETUP:
224 struct usb_ctrlrequest *ctrl = &evt.u.setup;
226 if (ctrl->bRequestType & USB_DIR_IN) {
227 if (write(ep0, NULL, 0) < 0)
229 } else { /* ctrl->bRequestType & USB_DIR_OUT */
230 switch (ctrl->bRequest) {
231 /* handle CDC ACM setup request */
232 case USB_CDC_REQ_SET_LINE_CODING:
234 int value = __le16_to_cpu(ctrl->wLength);
241 if (read(ep0, buf, value) < 0) {
248 case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
252 if (read(ep0, &buf, sizeof(buf)) < 0)
257 if (read(ep0, NULL, 0) < 0)
263 case FUNCTIONFS_ENABLE:
264 pthread_mutex_lock(&ctx->mutex);
266 pthread_mutex_unlock(&ctx->mutex);
267 pthread_cond_signal(&ctx->ready);
269 case FUNCTIONFS_DISABLE:
270 case FUNCTIONFS_BIND:
271 case FUNCTIONFS_UNBIND:
278 fprintf(stderr, "Error occurs while handling ep0 event");
282 static int usb_setup_ffs_daemon(struct usb_context *ctx)
286 int ep_path_len = strlen(TFMFFS_PATH) + 4 /* "/ep#" */ + 1 /* '\0' */;
289 ep_path = malloc(ep_path_len);
293 snprintf(ep_path, ep_path_len, TFMFFS_PATH"/ep%d", TFMFFS_EP0);
295 ep[TFMFFS_EP0] = open(ep_path, O_RDWR);
296 if (ep[TFMFFS_EP0] < 0) {
297 fprintf(stderr, "failed to open ffs ep0\n");
302 if (write(ep[TFMFFS_EP0], &descriptors, sizeof(descriptors)) < 0) {
303 fprintf(stderr, "failed to write descriptors\n");
307 if (write(ep[TFMFFS_EP0], &strings, sizeof(strings)) < 0) {
308 fprintf(stderr, "failed to write strings\n");
313 for (i = 1; i < TFMFFS_EP_MAX; i++) {
314 snprintf(ep_path, ep_path_len, TFMFFS_PATH"/ep%d", i);
316 ep[i] = open(ep_path, O_RDWR);
318 fprintf(stderr, "failed to open ffs ep%d\n", i);
319 /* close opened endpoints */
320 for (i -= 1; i >= 1; i--)
327 pthread_mutex_init(&ctx->mutex, NULL);
328 pthread_cond_init(&ctx->ready, NULL);
330 pthread_create(&ctx->ep0_thread, NULL, ep0_handler, ctx);
331 pthread_detach(ctx->ep0_thread);
338 close(ep[TFMFFS_EP0]);
346 static void usb_cleanup_ffs_daemon(struct usb_context *ctx)
350 pthread_cancel(ctx->ep0_thread);
351 close(ep[TFMFFS_EP0]);
354 static int mount_ffs(void)
358 ret = mkdir(TFMFFS_PATH, 0770);
360 fprintf(stderr, "Failed to create ffs directory\n");
364 ret = mount("tfm", TFMFFS_PATH, "functionfs", 0, NULL);
366 fprintf(stderr, "Failed to mount ffs function\n");
373 static void umount_ffs(void)
379 static int usb_connect(struct tfm_interface *intf)
381 struct usb_context *ctx;
388 ctx = (struct usb_context *)malloc(sizeof(*ctx));
392 ret = usbg_init("/sys/kernel/config", &s);
394 fprintf(stderr, "Failed to init USB gadget\n");
398 ret = usbg_create_gadget(s, TFMFFS_GADGET, &g_attrs, &g_strs, &g);
400 fprintf(stderr, "Failed to create USB gadget\n");
404 ret = usbg_create_function(g, USBG_F_FFS, TFMFFS_DEV, NULL, &f);
406 fprintf(stderr, "Failed to create USB function\n");
410 ret = usbg_create_config(g, 1, NULL, NULL, &c_strs, &c);
412 fprintf(stderr, "Failed to create USB config\n");
416 ret = usbg_add_config_function(c, TFMFFS_BIND_LINK, f);
418 fprintf(stderr, "Failed to bind USB function\n");
422 if (mount_ffs() < 0) {
423 fprintf(stderr, "Failed to mount functionfs\n");
427 if (usb_setup_ffs_daemon(ctx) < 0) {
428 fprintf(stderr, "Failed to setup ffs daemon\n");
432 ret = usbg_enable_gadget(g, DEFAULT_UDC);
434 fprintf(stderr, "Failed to enable USB gadget\n");
438 pthread_mutex_lock(&ctx->mutex);
439 while (!ctx->enabled)
440 pthread_cond_wait(&ctx->ready, &ctx->mutex);
441 pthread_mutex_unlock(&ctx->mutex);
445 intf->txd = ctx->eps[TFMFFS_EP_BULK_IN];
446 intf->rxd = ctx->eps[TFMFFS_EP_BULK_OUT];
447 intf->priv = (void *)ctx;
452 usb_cleanup_ffs_daemon(ctx);
466 static int usb_disconnect(struct tfm_interface *intf)
468 struct usb_context *ctx = intf->priv;
472 for (i = 1; i < TFMFFS_EP_MAX; i++)
475 usb_cleanup_ffs_daemon(ctx);
478 usbg_cleanup(ctx->usbg);
483 static struct tfm_interface_driver usb = {
486 .connect = usb_connect,
487 .disconnect = usb_disconnect,
488 .rx_data = usb_rx_data,
489 .tx_data = usb_tx_data,
492 INTERFACE_REGISTER(usb)