Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ project (adbd)

find_package(uv REQUIRED)

option(ADBD_USB_HOTPLUG_BYTIMER "adb usb hotplug check by timer" OFF)

option(ADBD_AUTHENTICATION "adb authentication" OFF)
option(ADBD_AUTH_PUBKEY "adb auth public key" OFF)
option(ADBD_FILE_SERVICE "adb file sync service" ON)
Expand Down
168 changes: 117 additions & 51 deletions hal/hal_uv_client_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ typedef struct adb_client_usb_s {
/* FIXME libuv handle must be right after adb_client_uv_t */
uv_pipe_t read_pipe;
uv_pipe_t write_pipe;
#ifdef CONFIG_ADBD_USB_HOTPLUG_BYTIMER
uv_timer_t timer;
#endif
char path[0];
Comment on lines +32 to +35

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to handle the hotplug timer outside of the hal_uv_client_usb file. This new hotplug timer could periodically check for "/dev/adb0" file, and call adb_uv_usb_setup(adbd, "/dev/adb0") when required to setup usb port.

} adb_client_usb_t;

/****************************************************************************
Expand All @@ -50,6 +54,102 @@ static void usb_uv_on_data_available(uv_stream_t* handle,
adb_uv_on_data_available(&client->uc, handle, nread, buf);
}

static int usb_uv_open(adb_client_usb_t *client) {
char devname[32];
int ret;
int fd;

ret = uv_pipe_init(uv_default_loop(), &client->read_pipe, 0);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's better to use the uv loop from client instead of uv_default_loop().

if (ret) {
adb_err("usb init error %d %d\n", ret, errno);
return ret;
}

snprintf(devname, sizeof(devname), "%s/ep2", client->path);
fd = open(devname, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
adb_err("failed to open usb device %d %d\n", fd, errno);
return fd;
}

ret = uv_pipe_open(&client->read_pipe, fd);
if (ret) {
adb_err("usb pipe open error %d %d\n", ret, errno);
close(fd);
return ret;
}

ret = uv_pipe_init(uv_default_loop(), &client->write_pipe, 0);
if (ret) {
adb_err("usb init error %d %d\n", ret, errno);
goto err_with_write;
}

snprintf(devname, sizeof(devname), "%s/ep1", client->path);
fd = open(devname, O_WRONLY | O_CLOEXEC);
if (fd < 0) {
adb_err("failed to open usb device %d %d\n", fd, errno);
goto err_with_write;
}

ret = uv_pipe_open(&client->write_pipe, fd);
if (ret) {
adb_err("usb pipe open error %d %d\n", ret, errno);
close(fd);
goto err_with_write;
}

ret = uv_read_start((uv_stream_t*)&client->read_pipe,
usb_uv_allocate_frame,
usb_uv_on_data_available);
if (ret < 0) {
goto err_with_read;
}

return ret;

err_with_read:
uv_close((uv_handle_t*)&client->read_pipe, NULL);
err_with_write:
uv_close((uv_handle_t*)&client->write_pipe, NULL);
return ret;
}

#ifdef CONFIG_ADBD_USB_HOTPLUG_BYTIMER
static void usb_hotplug_check_cb(uv_timer_t* handle) {
adb_client_usb_t *client = container_of(handle, adb_client_usb_t, timer);
struct stat statbuf;
char devname[32];
int ret;

snprintf(devname, sizeof(devname), "%s/ep2", client->path);
ret = stat(devname, &statbuf);
if (ret >= 0) {
ret = usb_uv_open(client);
if (ret >= 0) {
uv_timer_stop(handle);
}
}
}

static void usb_hotplug_check(adb_client_usb_t* client) {
int ret;

ret = uv_timer_init(uv_default_loop(), &client->timer);
if (ret) {
adb_log("usb timer init error %d %d\n", ret, errno);
return;
}

/* Using 1s timer to check usb hotplug */

ret = uv_timer_start(&client->timer, usb_hotplug_check_cb, 0, 1000);
if (ret) {
adb_log("usb timer start error %d %d\n", ret, errno);
}
}
#endif

static int usb_uv_write(adb_client_t *c, apacket *p) {
int ret;
uv_buf_t buf[2];
Expand Down Expand Up @@ -103,7 +203,11 @@ static void usb_uv_kick(adb_client_t *c) {
static void usb_uv_on_close(uv_handle_t* handle) {
adb_client_usb_t *client = container_of(handle, adb_client_usb_t, read_pipe);

#ifdef CONFIG_ADBD_USB_HOTPLUG_BYTIMER
usb_hotplug_check(client);
#else
adb_uv_close_client(&client->uc);
#endif
}

static void usb_uv_close(adb_client_t *c) {
Expand All @@ -125,12 +229,11 @@ static const adb_client_ops_t adb_usb_uv_ops = {
****************************************************************************/

int adb_uv_usb_setup(adb_context_uv_t *adbd, const char *path) {
char devname[32];
adb_client_usb_t *client;
int ret;
int fd;

client = (adb_client_usb_t*)adb_uv_create_client(sizeof(*client));
client = (adb_client_usb_t*)adb_uv_create_client(sizeof(*client) +
strlen(path) + 1);
if (client == NULL) {
adb_err("failed to allocate usb client\n");
return -ENOMEM;
Expand All @@ -139,54 +242,17 @@ int adb_uv_usb_setup(adb_context_uv_t *adbd, const char *path) {
/* Setup adb_client */

client->uc.client.ops = &adb_usb_uv_ops;

ret = uv_pipe_init(adbd->loop, &client->read_pipe, 0);
client->read_pipe.data = adbd;
if (ret) {
adb_err("usb init error %d %d\n", ret, errno);
return ret;
}

snprintf(devname, sizeof(devname), "%s/ep2", path);
fd = open(devname, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
adb_err("failed to open usb device %d %d\n", fd, errno);
return fd;
}

ret = uv_pipe_open(&client->read_pipe, fd);
if (ret) {
adb_err("usb pipe open error %d %d\n", ret, errno);
close(fd);
return ret;
}

ret = uv_pipe_init(adbd->loop, &client->write_pipe, 0);
client->write_pipe.data = adbd;
if (ret) {
adb_err("usb init error %d %d\n", ret, errno);
return ret;
}

snprintf(devname, sizeof(devname), "%s/ep1", path);
fd = open(devname, O_WRONLY | O_CLOEXEC);
if (fd < 0) {
adb_err("failed to open usb device %d %d\n", fd, errno);
return fd;
strcpy(client->path, path);

ret = usb_uv_open(client);
if (ret < 0) {
#ifdef CONFIG_ADBD_USB_HOTPLUG_BYTIMER
usb_hotplug_check(client);
ret = 0;
#else
adb_uv_close_client(&client->uc);
#endif
}

ret = uv_pipe_open(&client->write_pipe, fd);
if (ret) {
adb_err("usb pipe open error %d %d\n", ret, errno);
close(fd);
return ret;
}

ret = uv_read_start((uv_stream_t*)&client->read_pipe,
usb_uv_allocate_frame,
usb_uv_on_data_available);
/* TODO check return code */
assert(ret == 0);

return 0;
return ret;
}