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