* initial contribution for 2.0 beta (0.0.2)
[framework/system/sdbd.git] / src / usb_linux_client.c
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
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 "sdb.h"
31
32
33 struct usb_handle
34 {
35     int fd;
36     sdb_cond_t notify;
37     sdb_mutex_t lock;
38 };
39
40 void usb_cleanup()
41 {
42     // nothing to do here
43 }
44
45 static void *usb_open_thread(void *x)
46 {
47     struct usb_handle *usb = (struct usb_handle *)x;
48     int fd;
49
50     while (1) {
51         // wait until the USB device needs opening
52         sdb_mutex_lock(&usb->lock);
53         while (usb->fd != -1)
54             sdb_cond_wait(&usb->notify, &usb->lock);
55         sdb_mutex_unlock(&usb->lock);
56
57         D("[ usb_thread - opening device ]\n");
58         do {
59             /* XXX use inotify? */
60             fd = unix_open("/dev/samsung_sdb", O_RDWR);
61 #if 0
62             if (fd < 0) {
63                 // to support older kernels
64                 fd = unix_open("/dev/android", O_RDWR);
65             }
66 #endif
67             if (fd < 0) {
68                 sdb_sleep_ms(1000);
69             }
70         } while (fd < 0);
71         D("[ opening device succeeded ]\n");
72
73         close_on_exec(fd);
74         usb->fd = fd;
75
76         D("[ usb_thread - registering device ]\n");
77         register_usb_transport(usb, 0, 1);
78     }
79
80     // never gets here
81     return 0;
82 }
83
84 int usb_write(usb_handle *h, const void *data, int len)
85 {
86     int n;
87
88     D("[ write %d ]\n", len);
89     n = sdb_write(h->fd, data, len);
90     if(n != len) {
91         D("ERROR: n = %d, errno = %d (%s)\n",
92             n, errno, strerror(errno));
93         return -1;
94     }
95     D("[ done ]\n");
96     return 0;
97 }
98
99 int usb_read(usb_handle *h, void *data, int len)
100 {
101     int n;
102
103     D("[ read %d ]\n", len);
104     n = sdb_read(h->fd, data, len);
105     if(n != len) {
106         D("ERROR: n = %d, errno = %d (%s)\n",
107             n, errno, strerror(errno));
108         return -1;
109     }
110     return 0;
111 }
112
113 void usb_init()
114 {
115     usb_handle *h;
116     sdb_thread_t tid;
117 #if 0 //eric
118     int fd;
119 #endif
120     h = calloc(1, sizeof(usb_handle));
121     h->fd = -1;
122     sdb_cond_init(&h->notify, 0);
123     sdb_mutex_init(&h->lock, 0);
124
125     // Open the file /dev/android_sdb_enable to trigger 
126     // the enabling of the sdb USB function in the kernel.
127     // We never touch this file again - just leave it open
128     // indefinitely so the kernel will know when we are running
129     // and when we are not.
130 #if 0 //eric
131     fd = unix_open("/dev/android_sdb_enable", O_RDWR);
132     if (fd < 0) {
133        D("failed to open /dev/android_sdb_enable\n");
134     } else {
135         close_on_exec(fd);
136     }
137 #endif
138     D("[ usb_init - starting thread ]\n");
139     if(sdb_thread_create(&tid, usb_open_thread, h)){
140         fatal_errno("cannot create usb thread");
141     }
142 }
143
144 void usb_kick(usb_handle *h)
145 {
146     D("usb_kick\n");
147     sdb_mutex_lock(&h->lock);
148     sdb_close(h->fd);
149     h->fd = -1;
150
151     // notify usb_open_thread that we are disconnected
152     sdb_cond_signal(&h->notify);
153     sdb_mutex_unlock(&h->lock);
154 }
155
156 int usb_close(usb_handle *h)
157 {
158     // nothing to do here
159     return 0;
160 }