usb_linux_client.c revision dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h>
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h>
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h>
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h>
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/ioctl.h>
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/types.h>
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <dirent.h>
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <errno.h>
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "sysdeps.h"
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define   TRACE_TAG  TRACE_USB
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "adb.h"
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct usb_handle
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int fd;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    adb_cond_t notify;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    adb_mutex_t lock;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid usb_cleanup()
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // nothing to do here
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void *usb_open_thread(void *x)
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct usb_handle *usb = (struct usb_handle *)x;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int fd;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (1) {
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // wait until the USB device needs opening
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        adb_mutex_lock(&usb->lock);
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (usb->fd != -1)
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            adb_cond_wait(&usb->notify, &usb->lock);
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        adb_mutex_unlock(&usb->lock);
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        D("[ usb_thread - opening device ]\n");
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        do {
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /* XXX use inotify? */
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fd = unix_open("/dev/android_adb", O_RDWR);
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (fd < 0) {
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // to support older kernels
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fd = unix_open("/dev/android", O_RDWR);
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (fd < 0) {
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                adb_sleep_ms(1000);
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } while (fd < 0);
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        D("[ opening device succeeded ]\n");
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        close_on_exec(fd);
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        usb->fd = fd;
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        D("[ usb_thread - registering device ]\n");
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        register_usb_transport(usb, 0);
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // never gets here
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint usb_write(usb_handle *h, const void *data, int len)
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int n;
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    D("[ write %d ]\n", len);
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n = adb_write(h->fd, data, len);
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if(n != len) {
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        D("ERROR: n = %d, errno = %d (%s)\n",
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            n, errno, strerror(errno));
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    D("[ done ]\n");
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint usb_read(usb_handle *h, void *data, int len)
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int n;
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    D("[ read %d ]\n", len);
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    n = adb_read(h->fd, data, len);
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if(n != len) {
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        D("ERROR: n = %d, errno = %d (%s)\n",
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            n, errno, strerror(errno));
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid usb_init()
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    usb_handle *h;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    adb_thread_t tid;
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int fd;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    h = calloc(1, sizeof(usb_handle));
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    h->fd = -1;
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    adb_cond_init(&h->notify, 0);
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    adb_mutex_init(&h->lock, 0);
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Open the file /dev/android_adb_enable to trigger
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // the enabling of the adb USB function in the kernel.
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // We never touch this file again - just leave it open
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // indefinitely so the kernel will know when we are running
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // and when we are not.
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fd = unix_open("/dev/android_adb_enable", O_RDWR);
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (fd < 0) {
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project       D("failed to open /dev/android_adb_enable\n");
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    } else {
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        close_on_exec(fd);
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    D("[ usb_init - starting thread ]\n");
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if(adb_thread_create(&tid, usb_open_thread, h)){
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fatal_errno("cannot create usb thread");
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid usb_kick(usb_handle *h)
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    D("usb_kick\n");
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    adb_mutex_lock(&h->lock);
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    adb_close(h->fd);
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    h->fd = -1;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // notify usb_open_thread that we are disconnected
1481473f46cbc82aa6f0ba744cc896a36923823d55bMathias Agopian    adb_cond_signal(&h->notify);
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    adb_mutex_unlock(&h->lock);
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint usb_close(usb_handle *h)
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // nothing to do here
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return 0;
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project