Revert "Revert "Modify the packet size in transport protocol.""
[sdk/target/sdbd.git] / src / usb_linux_client.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <string.h>
21
22 #include <sys/ioctl.h>
23 #include <sys/types.h>
24 #include <dirent.h>
25 #include <errno.h>
26
27 #include "sysdeps.h"
28
29 #define   TRACE_TAG  TRACE_USB
30 #include "log.h"
31
32 #include "sdb.h"
33
34
35 struct usb_handle
36 {
37     int fd;
38     sdb_cond_t notify;
39     sdb_mutex_t lock;
40 };
41
42 static void *usb_open_thread(void *x)
43 {
44     struct usb_handle *usb = (struct usb_handle *)x;
45     int fd;
46
47     while (1) {
48         // wait until the USB device needs opening
49         sdb_mutex_lock(&usb->lock);
50         while (usb->fd != -1)
51             sdb_cond_wait(&usb->notify, &usb->lock);
52         sdb_mutex_unlock(&usb->lock);
53
54         D("[ usb_thread - opening device ]\n");
55         do {
56             /* XXX use inotify? */
57             fd = unix_open(USB_NODE_FILE, O_RDWR); /* tizen-specific */
58             if (fd < 0) {
59                 // to support older kernels
60                 //fd = unix_open("/dev/android", O_RDWR);
61                 D("[ opening %s device failed ]\n", USB_NODE_FILE);
62             }
63             if (fd < 0) {
64                 sdb_sleep_ms(1000);
65             }
66         } while (fd < 0);
67         D("[ opening device succeeded ]\n");
68
69         if (close_on_exec(fd) < 0) {
70             D("[closing fd exec failed ]\n");
71         }
72         usb->fd = fd;
73
74         D("[ usb_thread - registering device ]\n");
75         register_usb_transport(usb, 0, 1);
76     }
77
78     // never gets here
79     return 0;
80 }
81
82 // Public host/client interface
83
84 int linux_usb_write(usb_handle *h, const void *data, int len)
85 {
86     int n;
87
88     D("about to write (fd=%d, len=%d)\n", h->fd, len);
89     n = sdb_write(h->fd, data, len);
90     if(n != len) {
91         D("ERROR: fd = %d, n = %d, errno = %d\n",
92             h->fd, n, errno);
93         return -1;
94     }
95     D("[ done fd=%d ]\n", h->fd);
96     return 0;
97 }
98
99 int linux_usb_read(usb_handle *h, void *data, size_t len)
100 {
101       D("about to read (fd=%d, len=%d)\n", h->fd, len);
102         while (len > 0) {
103             /* The sdb_read does not support read larger than 4096 bytes at once.
104                Read 4096 byte block repeatedly when reading data is larger than 4096 bytes. */
105             int bytes_to_read = len < 4096 ? len : 4096;
106             int n = sdb_read(h->fd, data, bytes_to_read);
107             if(n < 0) {
108                 if(errno == EINTR) {
109                     continue;
110                 } else {
111                     D("ERROR: fd = %d, n = %d, errno = %d\n", h->fd, n, errno);
112                     return -1;
113                 }
114             }
115             len -= n;
116             data = ((char*) data) + n;
117         }
118         D("[ done fd=%d ]\n", h->fd);
119         return 0;
120 }
121
122 void linux_usb_init()
123 {
124     usb_handle *h;
125     sdb_thread_t tid;
126 //  int fd;
127
128     h = calloc(1, sizeof(usb_handle));
129     if (h == NULL) {
130         D("failed to allocate memory of usb_handle\n");
131         return;
132     }
133
134     h->fd = -1;
135     sdb_cond_init(&h->notify, 0);
136     sdb_mutex_init(&h->lock, 0);
137
138     // Open the file /dev/android_sdb_enable to trigger
139     // the enabling of the sdb USB function in the kernel.
140     // We never touch this file again - just leave it open
141     // indefinitely so the kernel will know when we are running
142     // and when we are not.
143 #if 0 /* tizen specific */
144     fd = unix_open("/dev/android_sdb_enable", O_RDWR);
145     if (fd < 0) {
146        D("failed to open /dev/android_sdb_enable\n");
147     } else {
148         close_on_exec(fd);
149     }
150 #endif
151     D("[ usb_init - starting thread ]\n");
152     if(sdb_thread_create(&tid, usb_open_thread, h)){
153         fatal_errno("cannot create usb thread");
154     }
155 }
156
157 void linux_usb_kick(usb_handle *h)
158 {
159     D("usb_kick\n");
160     sdb_mutex_lock(&h->lock);
161     sdb_close(h->fd);
162     h->fd = -1;
163
164     // notify usb_open_thread that we are disconnected
165     sdb_cond_signal(&h->notify);
166     sdb_mutex_unlock(&h->lock);
167 }
168
169 int linux_usb_close(usb_handle *h)
170 {
171     // nothing to do here
172     return 0;
173 }
174
175 void linux_usb_cleanup()
176 {
177     // nothing to do here
178 }