usb_linux_client.c revision e109d266c12c5f537d429ca4b892f2719e02c2da
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License.
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License.
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/ioctl.h>
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h>
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <dirent.h>
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "sysdeps.h"
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define   TRACE_TAG  TRACE_USB
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "adb.h"
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct usb_handle
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd;
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_cond_t notify;
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_t lock;
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usb_cleanup()
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // nothing to do here
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void *usb_open_thread(void *x)
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct usb_handle *usb = (struct usb_handle *)x;
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd;
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (1) {
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // wait until the USB device needs opening
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_mutex_lock(&usb->lock);
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        while (usb->fd != -1)
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            adb_cond_wait(&usb->notify, &usb->lock);
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_mutex_unlock(&usb->lock);
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("[ usb_thread - opening device ]\n");
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        do {
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* XXX use inotify? */
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fd = unix_open("/dev/android_adb", O_RDWR);
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (fd < 0) {
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // to support older kernels
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                fd = unix_open("/dev/android", O_RDWR);
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (fd < 0) {
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                adb_sleep_ms(1000);
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } while (fd < 0);
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("[ opening device succeeded ]\n");
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        close_on_exec(fd);
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        usb->fd = fd;
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("[ usb_thread - registering device ]\n");
75e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson        register_usb_transport(usb, 0, 0, 1);
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // never gets here
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_write(usb_handle *h, const void *data, int len)
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int n;
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
86408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    D("about to write (fd=%d, len=%d)\n", h->fd, len);
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    n = adb_write(h->fd, data, len);
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(n != len) {
89408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        D("ERROR: fd = %d, n = %d, errno = %d (%s)\n",
90408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            h->fd, n, errno, strerror(errno));
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
93408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    D("[ done fd=%d ]\n", h->fd);
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_read(usb_handle *h, void *data, int len)
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int n;
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
101408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    D("about to read (fd=%d, len=%d)\n", h->fd, len);
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    n = adb_read(h->fd, data, len);
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(n != len) {
104408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        D("ERROR: fd = %d, n = %d, errno = %d (%s)\n",
105408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            h->fd, n, errno, strerror(errno));
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
108408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    D("[ done fd=%d ]\n", h->fd);
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usb_init()
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    usb_handle *h;
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_thread_t tid;
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd;
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    h = calloc(1, sizeof(usb_handle));
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    h->fd = -1;
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_cond_init(&h->notify, 0);
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_init(&h->lock, 0);
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Open the file /dev/android_adb_enable to trigger
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // the enabling of the adb USB function in the kernel.
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // We never touch this file again - just leave it open
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // indefinitely so the kernel will know when we are running
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // and when we are not.
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd = unix_open("/dev/android_adb_enable", O_RDWR);
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (fd < 0) {
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project       D("failed to open /dev/android_adb_enable\n");
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        close_on_exec(fd);
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("[ usb_init - starting thread ]\n");
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(adb_thread_create(&tid, usb_open_thread, h)){
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fatal_errno("cannot create usb thread");
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usb_kick(usb_handle *h)
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("usb_kick\n");
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_lock(&h->lock);
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_close(h->fd);
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    h->fd = -1;
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // notify usb_open_thread that we are disconnected
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_cond_signal(&h->notify);
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_unlock(&h->lock);
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_close(usb_handle *h)
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // nothing to do here
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
158