system: add Android Debug Bridge daemon
This commit is contained in:
parent
efd81744d1
commit
c1c488e835
158
system/adb/Kconfig
Normal file
158
system/adb/Kconfig
Normal file
@ -0,0 +1,158 @@
|
||||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
|
||||
menuconfig SYSTEM_ADBD
|
||||
tristate "ADB daemon application"
|
||||
default n
|
||||
---help---
|
||||
Enable support for adb daemon.
|
||||
|
||||
if SYSTEM_ADBD
|
||||
|
||||
config ADBD_PROGNAME
|
||||
string "Program name"
|
||||
default "adbd"
|
||||
---help---
|
||||
This is the name of the program that will be used.
|
||||
|
||||
config ADBD_STACKSIZE
|
||||
int "Stack size"
|
||||
default DEFAULT_TASK_STACKSIZE
|
||||
---help---
|
||||
The size of stack allocated for the adb daemon task.
|
||||
|
||||
config ADBD_PRIORITY
|
||||
int "Task priority"
|
||||
default 100
|
||||
---help---
|
||||
The priority of the adb daemon task.
|
||||
|
||||
config ADBD_AUTHENTICATION
|
||||
bool "Authentication support"
|
||||
default n
|
||||
---help---
|
||||
Enable authentication for adb daemon.
|
||||
|
||||
if ADBD_AUTHENTICATION
|
||||
|
||||
config ADBD_AUTH_PUBKEY
|
||||
bool "Public key authentication"
|
||||
default n
|
||||
---help---
|
||||
Enable hook to accept new public keys.
|
||||
|
||||
config ADBD_TOKEN_SIZE
|
||||
int "Authentication token size"
|
||||
default 20
|
||||
|
||||
endif # ADBD_AUTHENTICATION
|
||||
|
||||
if ! BOARDCTL_UNIQUEID
|
||||
config ADBD_DEVICE_ID
|
||||
string "Default adb device id"
|
||||
default ""
|
||||
endif # BOARDCTL_UNIQUEID
|
||||
|
||||
config ADBD_PRODUCT_NAME
|
||||
string "Default adb product name"
|
||||
default "adb dev"
|
||||
|
||||
config ADBD_PRODUCT_MODEL
|
||||
string "Default adb product model"
|
||||
default "adb board"
|
||||
|
||||
config ADBD_PRODUCT_DEVICE
|
||||
string "Default adb product device"
|
||||
default "NuttX device"
|
||||
|
||||
config ADBD_FEATURES
|
||||
string "Default adb server features list"
|
||||
default "cmd"
|
||||
|
||||
config ADBD_PAYLOAD_SIZE
|
||||
int "Normal ADB frame size"
|
||||
default 64
|
||||
---help---
|
||||
Normal frame size in bytes.
|
||||
|
||||
config ADBD_CNXN_PAYLOAD_SIZE
|
||||
int "Connection frame size"
|
||||
default 1024
|
||||
---help---
|
||||
Connection frame is bigger than others.
|
||||
Can be between 128 to 256 bytes in most of the cases.
|
||||
If authentication is enabled, frame size must bigger
|
||||
to receive public key from host (around 1024 bytes).
|
||||
|
||||
config ADBD_FRAME_MAX
|
||||
int "Frame pool size"
|
||||
default 1
|
||||
---help---
|
||||
ADB frame pool size.
|
||||
|
||||
config ADBD_TCP_SERVER
|
||||
bool "Network socket transport support"
|
||||
depends on NET_TCP
|
||||
default n
|
||||
---help---
|
||||
Run adb daemon on network socket.
|
||||
|
||||
config ADBD_TCP_SERVER_PORT
|
||||
int "Network socket transport port"
|
||||
depends on ADBD_TCP_SERVER
|
||||
default 5555
|
||||
---help---
|
||||
Port used by adb daemon socket server
|
||||
|
||||
config ADBD_USB_SERVER
|
||||
bool "USB transport support"
|
||||
depends on USBADB
|
||||
default n
|
||||
---help---
|
||||
Run adb daemon on USB bus
|
||||
|
||||
config ADBD_LOGCAT_SERVICE
|
||||
bool "ADB logcat support"
|
||||
depends on RAMLOG_SYSLOG
|
||||
default n
|
||||
---help---
|
||||
Enable "adb logcat" feature.
|
||||
|
||||
config ADBD_FILE_SERVICE
|
||||
bool "ADB file sync support"
|
||||
default n
|
||||
---help---
|
||||
Enable "adb ls/push/pull" feature.
|
||||
|
||||
config ADBD_SHELL_SERVICE
|
||||
bool "ADB shell support"
|
||||
depends on NSH_CONSOLE
|
||||
default n
|
||||
---help---
|
||||
Enable "adb shell" feature.
|
||||
|
||||
config ADBD_FILE_SYMLINK
|
||||
bool "File service symlink support"
|
||||
default n
|
||||
depends on PSEUDOFS_SOFTLINKS
|
||||
---help---
|
||||
Enable fs symlink support.
|
||||
|
||||
config ADBD_BOARD_INIT
|
||||
bool "Board initialization"
|
||||
depends on LIB_BOARDCTL
|
||||
default n
|
||||
---help---
|
||||
Setup board before running adb daemon.
|
||||
|
||||
config ADBD_NET_INIT
|
||||
bool "Network initialization"
|
||||
default n
|
||||
depends on NET
|
||||
select NETUTILS_NETINIT
|
||||
---help---
|
||||
This option enables/disables all network initialization in ADB server.
|
||||
|
||||
endif # SYSTEM_ADBD
|
23
system/adb/Make.defs
Normal file
23
system/adb/Make.defs
Normal file
@ -0,0 +1,23 @@
|
||||
############################################################################
|
||||
# system/adb/Make.defs
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
ifneq ($(CONFIG_SYSTEM_ADBD),)
|
||||
CONFIGURED_APPS += $(APPDIR)/system/adb
|
||||
endif
|
92
system/adb/Makefile
Normal file
92
system/adb/Makefile
Normal file
@ -0,0 +1,92 @@
|
||||
############################################################################
|
||||
# system/adb/Makefile
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
include $(APPDIR)/Make.defs
|
||||
|
||||
ADB_DIR := $(APPDIR)/system/adb
|
||||
CONFIG_ADBD_URL ?= "https://github.com/spiriou/microADB.git"
|
||||
CONFIG_ADBD_VERSION ?= bbd1e74bd795aa2fc53eae2b76bff993d6ccaa37
|
||||
|
||||
ADB_UNPACKNAME := microADB
|
||||
ADB_UNPACKDIR := $(ADB_DIR)/$(ADB_UNPACKNAME)
|
||||
|
||||
$(ADB_UNPACKDIR):
|
||||
@echo "Downloading: $(ADB_UNPACKNAME)"
|
||||
$(call DELDIR, "$@")
|
||||
$(Q) mkdir "$@"
|
||||
$(Q) cd "$@" && git init && \
|
||||
git remote add origin "$(CONFIG_ADBD_URL)" && \
|
||||
git fetch origin $(CONFIG_ADBD_VERSION) --depth=1 && \
|
||||
git reset --hard FETCH_HEAD
|
||||
|
||||
# adb server app
|
||||
|
||||
PROGNAME := $(CONFIG_ADBD_PROGNAME)
|
||||
PRIORITY := $(CONFIG_ADBD_PRIORITY)
|
||||
STACKSIZE := $(CONFIG_ADBD_STACKSIZE)
|
||||
MODULE := $(CONFIG_ADB_SERVER)
|
||||
|
||||
# Files
|
||||
|
||||
MAINSRC := adb_main.c
|
||||
CSRCS += adb_banner.c
|
||||
CSRCS += $(ADB_UNPACKNAME)/adb_client.c
|
||||
CSRCS += $(ADB_UNPACKNAME)/adb_frame.c
|
||||
|
||||
CSRCS += $(ADB_UNPACKNAME)/hal/hal_uv.c
|
||||
CSRCS += $(ADB_UNPACKNAME)/hal/hal_uv_packet.c
|
||||
|
||||
CFLAGS += -D__NUTTX__=1
|
||||
CFLAGS += -I$(ADB_UNPACKNAME)
|
||||
|
||||
ifeq ($(CONFIG_ADBD_TCP_SERVER),y)
|
||||
CSRCS += $(ADB_UNPACKNAME)/hal/hal_uv_client_tcp.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ADBD_USB_SERVER),y)
|
||||
CSRCS += $(ADB_UNPACKNAME)/hal/hal_uv_client_usb.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ADBD_AUTHENTICATION),y)
|
||||
CSRCS += $(ADB_UNPACKNAME)/adb_auth_key.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ADBD_FILE_SERVICE),y)
|
||||
CSRCS += $(ADB_UNPACKNAME)/file_sync_service.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ADBD_LOGCAT_SERVICE),y)
|
||||
CSRCS += logcat_service.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ADBD_SHELL_SERVICE),y)
|
||||
CSRCS += shell_service.c
|
||||
CSRCS += shell_pipe.c
|
||||
endif
|
||||
|
||||
context:: $(ADB_UNPACKDIR)
|
||||
|
||||
clean::
|
||||
$(call DELFILE, $(OBJS))
|
||||
|
||||
distclean::
|
||||
$(call DELDIR, $(ADB_UNPACKDIR))
|
||||
|
||||
include $(APPDIR)/Application.mk
|
117
system/adb/adb_banner.c
Normal file
117
system/adb/adb_banner.c
Normal file
@ -0,0 +1,117 @@
|
||||
/****************************************************************************
|
||||
* system/adb/adb_main.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "adb.h"
|
||||
#ifdef CONFIG_BOARDCTL_UNIQUEID
|
||||
#include <sys/boardctl.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int adb_fill_connect_data(char *buf, size_t bufsize)
|
||||
{
|
||||
size_t len;
|
||||
size_t remaining = bufsize;
|
||||
|
||||
#ifdef CONFIG_BOARDCTL_UNIQUEID
|
||||
/* Get board id */
|
||||
|
||||
int ret;
|
||||
uint8_t board_id[CONFIG_BOARDCTL_UNIQUEID_SIZE];
|
||||
|
||||
memset(board_id, 0, CONFIG_BOARDCTL_UNIQUEID_SIZE);
|
||||
ret = boardctl(BOARDIOC_UNIQUEID, (uintptr_t)board_id);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
/* Failed to get board id */
|
||||
|
||||
adb_log("failed to get board id\n");
|
||||
len = snprintf(buf, remaining, "device::");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME only keep first 4 bytes */
|
||||
|
||||
len = snprintf(buf, remaining, "device:%x:", *(uint32_t *)board_id);
|
||||
}
|
||||
#else
|
||||
len = snprintf(buf, remaining, "device:" CONFIG_ADBD_DEVICE_ID ":");
|
||||
#endif
|
||||
|
||||
if (len >= remaining)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ADBD_PRODUCT_NAME
|
||||
remaining -= len;
|
||||
buf += len;
|
||||
len = snprintf(buf, remaining,
|
||||
"ro.product.name=" CONFIG_ADBD_PRODUCT_NAME ";");
|
||||
|
||||
if (len >= remaining)
|
||||
{
|
||||
return bufsize;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ADBD_PRODUCT_MODEL
|
||||
remaining -= len;
|
||||
buf += len;
|
||||
len = snprintf(buf, remaining,
|
||||
"ro.product.model=" CONFIG_ADBD_PRODUCT_MODEL ";");
|
||||
|
||||
if (len >= remaining)
|
||||
{
|
||||
return bufsize;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ADBD_PRODUCT_DEVICE
|
||||
remaining -= len;
|
||||
buf += len;
|
||||
len = snprintf(buf, remaining,
|
||||
"ro.product.device=" CONFIG_ADBD_PRODUCT_DEVICE ";");
|
||||
|
||||
if (len >= remaining)
|
||||
{
|
||||
return bufsize;
|
||||
}
|
||||
#endif
|
||||
|
||||
remaining -= len;
|
||||
buf += len;
|
||||
len = snprintf(buf, remaining, "features=" CONFIG_ADBD_FEATURES);
|
||||
|
||||
if (len >= remaining)
|
||||
{
|
||||
return bufsize;
|
||||
}
|
||||
|
||||
return bufsize - remaining + len;
|
||||
}
|
119
system/adb/adb_main.c
Normal file
119
system/adb/adb_main.c
Normal file
@ -0,0 +1,119 @@
|
||||
/****************************************************************************
|
||||
* system/adb/adb_main.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "adb.h"
|
||||
|
||||
#ifdef CONFIG_ADBD_BOARD_INIT
|
||||
#include <sys/boardctl.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ADBD_NET_INIT
|
||||
#include "netutils/netinit.h"
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
void adb_log_impl(FAR const char *func, int line, FAR const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
fprintf(stderr, "%s (%d): ", func, line);
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
int main(int argc, FAR char **argv)
|
||||
{
|
||||
UNUSED(argc);
|
||||
UNUSED(argv);
|
||||
|
||||
adb_context_t *ctx;
|
||||
|
||||
#ifdef CONFIG_ADBD_BOARD_INIT
|
||||
{
|
||||
boardctl(BOARDIOC_INIT, 0);
|
||||
|
||||
#if defined(CONFIG_ADBD_USB_SERVER) && \
|
||||
defined(CONFIG_USBDEV_COMPOSITE) && \
|
||||
defined (CONFIG_BOARDCTL_USBDEVCTRL)
|
||||
|
||||
/* Setup composite USB device */
|
||||
|
||||
struct boardioc_usbdev_ctrl_s ctrl;
|
||||
int ret;
|
||||
FAR void *handle;
|
||||
|
||||
/* Perform architecture-specific initialization */
|
||||
|
||||
ctrl.usbdev = BOARDIOC_USBDEV_COMPOSITE;
|
||||
ctrl.action = BOARDIOC_USBDEV_INITIALIZE;
|
||||
ctrl.instance = 0;
|
||||
ctrl.config = 0;
|
||||
ctrl.handle = NULL;
|
||||
|
||||
ret = boardctl(BOARDIOC_USBDEV_CONTROL, (uintptr_t)&ctrl);
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("boardctl(BOARDIOC_USBDEV_CONTROL) failed: %d\n", ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Initialize the USB composite device device */
|
||||
|
||||
ctrl.usbdev = BOARDIOC_USBDEV_COMPOSITE;
|
||||
ctrl.action = BOARDIOC_USBDEV_CONNECT;
|
||||
ctrl.instance = 0;
|
||||
ctrl.config = 0;
|
||||
ctrl.handle = &handle;
|
||||
|
||||
ret = boardctl(BOARDIOC_USBDEV_CONTROL, (uintptr_t)&ctrl);
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("boardctl(BOARDIOC_USBDEV_CONTROL) failed: %d\n", ret);
|
||||
return 1;
|
||||
}
|
||||
#endif /* ADBD_USB_SERVER && USBDEV_COMPOSITE && BOARDCTL_USBDEVCTRL */
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ADBD_BOARD_INIT */
|
||||
|
||||
#ifdef CONFIG_ADBD_NET_INIT
|
||||
/* Bring up the network */
|
||||
|
||||
netinit_bringup();
|
||||
#endif
|
||||
|
||||
ctx = adb_hal_create_context();
|
||||
if (!ctx)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
adb_hal_run(ctx);
|
||||
adb_hal_destroy_context(ctx);
|
||||
return 0;
|
||||
}
|
213
system/adb/logcat_service.c
Normal file
213
system/adb/logcat_service.c
Normal file
@ -0,0 +1,213 @@
|
||||
/****************************************************************************
|
||||
* system/adb/logcat_service_uv.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <nuttx/syslog/ramlog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "adb.h"
|
||||
#include "logcat_service.h"
|
||||
#include "hal/hal_uv_priv.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private types
|
||||
****************************************************************************/
|
||||
|
||||
typedef struct alog_service_s
|
||||
{
|
||||
adb_service_t service;
|
||||
uv_poll_t poll;
|
||||
int wait_ack;
|
||||
} alog_service_t;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static void logcat_on_data_available(uv_poll_t * handle,
|
||||
int status, int events);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int alog_on_write(adb_service_t *service, apacket *p)
|
||||
{
|
||||
UNUSED(p);
|
||||
UNUSED(service);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void alog_on_kick(struct adb_service_s *service)
|
||||
{
|
||||
alog_service_t *svc = container_of(service, alog_service_t, service);
|
||||
if (!svc->wait_ack)
|
||||
{
|
||||
int ret;
|
||||
ret = uv_poll_start(&svc->poll, UV_READABLE, logcat_on_data_available);
|
||||
assert(ret == 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int alog_on_ack(adb_service_t *service, apacket *p)
|
||||
{
|
||||
UNUSED(p);
|
||||
alog_service_t *svc = container_of(service, alog_service_t, service);
|
||||
svc->wait_ack = 0;
|
||||
alog_on_kick(service);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void close_cb(uv_handle_t *handle)
|
||||
{
|
||||
alog_service_t *service = container_of(handle, alog_service_t, poll);
|
||||
free(service);
|
||||
}
|
||||
|
||||
static void alog_close(struct adb_service_s *service)
|
||||
{
|
||||
int fd;
|
||||
int ret;
|
||||
alog_service_t *svc = container_of(service, alog_service_t, service);
|
||||
|
||||
ret = uv_fileno((uv_handle_t *)&svc->poll, &fd);
|
||||
assert(ret == 0);
|
||||
|
||||
close(fd);
|
||||
uv_close((uv_handle_t *)&svc->poll, close_cb);
|
||||
}
|
||||
|
||||
static const adb_service_ops_t logcat_ops =
|
||||
{
|
||||
.on_write_frame = alog_on_write,
|
||||
.on_ack_frame = alog_on_ack,
|
||||
.on_kick = alog_on_kick,
|
||||
.close = alog_close
|
||||
};
|
||||
|
||||
static void logcat_on_data_available(uv_poll_t * handle,
|
||||
int status, int events)
|
||||
{
|
||||
int ret;
|
||||
int fd;
|
||||
apacket_uv_t *ap;
|
||||
alog_service_t *service = container_of(handle, alog_service_t, poll);
|
||||
adb_client_uv_t *client = (adb_client_uv_t *)handle->data;
|
||||
|
||||
ap = adb_uv_packet_allocate(client, 0);
|
||||
if (ap == NULL)
|
||||
{
|
||||
uv_poll_stop(handle);
|
||||
return;
|
||||
}
|
||||
|
||||
if (status)
|
||||
{
|
||||
adb_log("status error %d\n", status);
|
||||
|
||||
/* Fatal error, stop service */
|
||||
|
||||
goto exit_stop_service;
|
||||
}
|
||||
|
||||
assert(uv_fileno((uv_handle_t *)handle, &fd) == 0);
|
||||
ret = read(fd, ap->p.data, CONFIG_ADBD_PAYLOAD_SIZE);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
adb_log("frame read failed %d %d\n", ret, errno);
|
||||
if (errno == EAGAIN)
|
||||
{
|
||||
/* TODO this should never happen */
|
||||
|
||||
goto exit_release_packet;
|
||||
}
|
||||
|
||||
/* Fatal error, stop service */
|
||||
|
||||
goto exit_stop_service;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
goto exit_release_packet;
|
||||
}
|
||||
|
||||
service->wait_ack = 1;
|
||||
uv_poll_stop(handle);
|
||||
|
||||
ap->p.write_len = ret;
|
||||
ap->p.msg.arg0 = service->service.id;
|
||||
ap->p.msg.arg1 = service->service.peer_id;
|
||||
adb_send_data_frame(&client->client, &ap->p);
|
||||
return;
|
||||
|
||||
exit_release_packet:
|
||||
adb_hal_apacket_release(&client->client, &ap->p);
|
||||
return;
|
||||
|
||||
exit_stop_service:
|
||||
adb_service_close(&client->client, &service->service, &ap->p);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
adb_service_t * logcat_service(adb_client_t *client, const char *params)
|
||||
{
|
||||
int ret;
|
||||
alog_service_t *service =
|
||||
(alog_service_t *)malloc(sizeof(alog_service_t));
|
||||
|
||||
if (service == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
service->service.ops = &logcat_ops;
|
||||
service->wait_ack = 0;
|
||||
|
||||
/* TODO parse params string to extract logcat parameters */
|
||||
|
||||
ret = open(CONFIG_SYSLOG_DEVPATH, O_RDONLY | O_CLOEXEC);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
adb_log("failed to open %s (%d)\n", CONFIG_SYSLOG_DEVPATH, errno);
|
||||
free(service);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uv_handle_t *handle = adb_uv_get_client_handle(client);
|
||||
ret = uv_poll_init(handle->loop, &service->poll, ret);
|
||||
assert(ret == 0);
|
||||
|
||||
service->poll.data = client;
|
||||
alog_on_kick(&service->service);
|
||||
|
||||
return &service->service;
|
||||
}
|
237
system/adb/shell_pipe.c
Normal file
237
system/adb/shell_pipe.c
Normal file
@ -0,0 +1,237 @@
|
||||
/****************************************************************************
|
||||
* system/adb/shell_pipe.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <uv.h>
|
||||
#include <unistd.h>
|
||||
#include "adb.h"
|
||||
#include "shell_pipe.h"
|
||||
#include "hal/hal_uv_priv.h"
|
||||
|
||||
#include <nshlib/nshlib.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static void shell_on_data_available(uv_poll_t * handle,
|
||||
int status, int events)
|
||||
{
|
||||
int ret;
|
||||
apacket_uv_t *ap;
|
||||
shell_pipe_t *pipe = container_of(handle, shell_pipe_t, handle);
|
||||
|
||||
adb_client_t *client = (adb_client_t *)pipe->handle.data;
|
||||
|
||||
if (status)
|
||||
{
|
||||
adb_log("status error %d\n", status);
|
||||
|
||||
/* FIXME missing logic here */
|
||||
|
||||
pipe->on_data_cb(pipe, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
ap = adb_uv_packet_allocate((adb_client_uv_t *)client, 0);
|
||||
if (ap == NULL)
|
||||
{
|
||||
/* frame allocation failed. Try again later */
|
||||
|
||||
uv_poll_stop(&pipe->handle);
|
||||
return;
|
||||
}
|
||||
|
||||
int nread = 0;
|
||||
do
|
||||
{
|
||||
ret = read(handle->io_watcher.fd, &ap->p.data[nread], 1);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
/* EOF */
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
/* Revisit. EAGAIN should not happen but it happens a lot */
|
||||
|
||||
if (errno == EAGAIN)
|
||||
{
|
||||
if (nread <= 0)
|
||||
{
|
||||
adb_hal_apacket_release(
|
||||
(adb_client_t *)pipe->handle.data, &ap->p);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Release packet and forward error */
|
||||
|
||||
adb_hal_apacket_release((adb_client_t *)pipe->handle.data, &ap->p);
|
||||
pipe->on_data_cb(pipe, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* FIXME CR LF conversion */
|
||||
|
||||
if (ap->p.data[nread++] == '\n')
|
||||
{
|
||||
ap->p.data[nread++] = '\r';
|
||||
}
|
||||
}
|
||||
while (nread < CONFIG_ADBD_PAYLOAD_SIZE - 1);
|
||||
|
||||
ap->p.msg.data_length = nread;
|
||||
pipe->on_data_cb(pipe, &ap->p);
|
||||
}
|
||||
|
||||
static void shell_pipe_close_callback(uv_handle_t *handle)
|
||||
{
|
||||
shell_pipe_t *pipe = container_of(handle, shell_pipe_t, handle);
|
||||
|
||||
/* Notify caller pipe is closed */
|
||||
|
||||
pipe->close_cb(pipe);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int shell_pipe_setup(adb_client_t *client, shell_pipe_t *apipe)
|
||||
{
|
||||
apipe->handle.data = client;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void shell_pipe_destroy(shell_pipe_t *pipe, void (*close_cb)(shell_pipe_t *))
|
||||
{
|
||||
pipe->close_cb = close_cb;
|
||||
close(pipe->write_fd);
|
||||
uv_close((uv_handle_t *)&pipe->handle, shell_pipe_close_callback);
|
||||
}
|
||||
|
||||
int shell_pipe_write(shell_pipe_t *pipe, const void *buf, size_t count)
|
||||
{
|
||||
/* TODO revisit */
|
||||
|
||||
return write(pipe->write_fd, buf, count);
|
||||
}
|
||||
|
||||
int shell_pipe_start(shell_pipe_t *pipe,
|
||||
void (*on_data_cb)(shell_pipe_t *, apacket *))
|
||||
{
|
||||
pipe->on_data_cb = on_data_cb;
|
||||
return uv_poll_start(&pipe->handle, UV_READABLE, shell_on_data_available);
|
||||
}
|
||||
|
||||
int shell_pipe_exec(char * const argv[], shell_pipe_t *apipe,
|
||||
void (*on_data_cb)(shell_pipe_t *, apacket *))
|
||||
{
|
||||
int ret;
|
||||
int in_fds[2];
|
||||
int out_fds[2];
|
||||
|
||||
adb_client_uv_t *client = (adb_client_uv_t *)apipe->handle.data;
|
||||
|
||||
/* Create pipe for stdin */
|
||||
|
||||
ret = pipe(in_fds);
|
||||
assert(ret == 0);
|
||||
ret = pipe(out_fds);
|
||||
assert(ret == 0);
|
||||
|
||||
/* TODO check return code */
|
||||
|
||||
apipe->write_fd = in_fds[1];
|
||||
|
||||
/* Setup stdout (read: adb, write: child) */
|
||||
|
||||
ret = dup2(out_fds[1], 1);
|
||||
assert(ret == 0);
|
||||
|
||||
ret = close(out_fds[1]);
|
||||
assert(ret == 0);
|
||||
|
||||
ret = fcntl(out_fds[0], F_GETFD);
|
||||
assert(ret >= 0);
|
||||
ret = fcntl(out_fds[0], F_SETFD, ret | FD_CLOEXEC);
|
||||
assert(ret == 0);
|
||||
ret = fcntl(out_fds[0], F_GETFL);
|
||||
assert(ret >= 0);
|
||||
ret = fcntl(out_fds[0], F_SETFL, ret | O_NONBLOCK);
|
||||
assert(ret >= 0);
|
||||
|
||||
/* Setup stdin */
|
||||
|
||||
ret = dup2(in_fds[0], 0);
|
||||
assert(ret == 0);
|
||||
|
||||
ret = close(in_fds[0]);
|
||||
assert(ret == 0);
|
||||
|
||||
ret = fcntl(in_fds[1], F_GETFD);
|
||||
assert(ret >= 0);
|
||||
ret = fcntl(in_fds[1], F_SETFD, ret | FD_CLOEXEC);
|
||||
assert(ret == 0);
|
||||
ret = fcntl(in_fds[1], F_GETFL);
|
||||
assert(ret >= 0);
|
||||
ret = fcntl(in_fds[1], F_SETFL, ret | O_NONBLOCK);
|
||||
assert(ret == 0);
|
||||
|
||||
ret = uv_poll_init(
|
||||
adb_uv_get_client_handle(client)->loop,
|
||||
&apipe->handle, out_fds[0]);
|
||||
|
||||
/* TODO check return code */
|
||||
|
||||
assert(ret == 0);
|
||||
|
||||
/* Create shell process */
|
||||
|
||||
ret = task_create("ADB shell", CONFIG_SYSTEM_NSH_PRIORITY,
|
||||
CONFIG_SYSTEM_NSH_STACKSIZE, nsh_consolemain,
|
||||
argv);
|
||||
|
||||
/* Close stdin and stdout */
|
||||
|
||||
dup2(2, 0);
|
||||
dup2(2, 1);
|
||||
|
||||
/* TODO check return code */
|
||||
|
||||
assert(ret >= 0);
|
||||
|
||||
/* Start listening shell process stdout */
|
||||
|
||||
ret = shell_pipe_start(apipe, on_data_cb);
|
||||
|
||||
/* TODO check return code */
|
||||
|
||||
assert(ret == 0);
|
||||
return 0;
|
||||
}
|
56
system/adb/shell_pipe.h
Normal file
56
system/adb/shell_pipe.h
Normal file
@ -0,0 +1,56 @@
|
||||
/****************************************************************************
|
||||
* system/adb/shell_pipe.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <uv.h>
|
||||
#include "adb.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private types
|
||||
****************************************************************************/
|
||||
|
||||
struct shell_pipe_s
|
||||
{
|
||||
uv_poll_t handle;
|
||||
int write_fd;
|
||||
void (*close_cb)(struct shell_pipe_s *);
|
||||
void (*on_data_cb)(struct shell_pipe_s *, struct apacket_s *);
|
||||
};
|
||||
|
||||
typedef struct shell_pipe_s shell_pipe_t;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
int shell_pipe_setup(adb_client_t *client, shell_pipe_t *pipe);
|
||||
int shell_pipe_start(shell_pipe_t *pipe,
|
||||
void (*on_data_cb)(shell_pipe_t *, apacket *));
|
||||
void shell_pipe_destroy(shell_pipe_t *pipe,
|
||||
void (*close_cb)(shell_pipe_t *));
|
||||
int shell_pipe_write(shell_pipe_t *pipe, const void *buf, size_t count);
|
||||
|
||||
int shell_pipe_exec(char * const argv[], shell_pipe_t *pipe,
|
||||
void (*on_data_cb)(shell_pipe_t *, apacket *));
|
||||
int shell_exec_builtin(const char *appname, FAR char *const *argv,
|
||||
shell_pipe_t *apipe);
|
209
system/adb/shell_service.c
Normal file
209
system/adb/shell_service.c
Normal file
@ -0,0 +1,209 @@
|
||||
/****************************************************************************
|
||||
* system/adb/shell_service.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "adb.h"
|
||||
#include "shell_service.h"
|
||||
#include "shell_pipe.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private types
|
||||
****************************************************************************/
|
||||
|
||||
typedef struct ash_service_s
|
||||
{
|
||||
adb_service_t service;
|
||||
shell_pipe_t pipe;
|
||||
adb_client_t *client;
|
||||
} ash_service_t;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static void exec_on_data_available(shell_pipe_t * pipe, apacket * p);
|
||||
|
||||
static int shell_ack(adb_service_t *service, apacket *p);
|
||||
static int shell_write(adb_service_t *service, apacket *p);
|
||||
static void shell_close(struct adb_service_s *service);
|
||||
static void shell_kick(adb_service_t *service);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static void exec_on_data_available(shell_pipe_t * pipe, apacket * p)
|
||||
{
|
||||
ash_service_t *service = container_of(pipe, ash_service_t, pipe);
|
||||
|
||||
if (p->msg.data_length <= 0)
|
||||
{
|
||||
/* Got EOF */
|
||||
|
||||
adb_service_close(service->client, &service->service, p);
|
||||
return;
|
||||
}
|
||||
|
||||
p->write_len = p->msg.data_length;
|
||||
p->msg.arg0 = service->service.id;
|
||||
p->msg.arg1 = service->service.peer_id;
|
||||
adb_send_data_frame(service->client, p);
|
||||
}
|
||||
|
||||
static int shell_write(adb_service_t *service, apacket *p)
|
||||
{
|
||||
int ret;
|
||||
ash_service_t *svc = container_of(service, ash_service_t, service);
|
||||
UNUSED(svc);
|
||||
|
||||
if (p->msg.data_length <= 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = shell_pipe_write(&svc->pipe, p->data, p->msg.data_length);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
/* Shell process terminated, close service */
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(ret == p->msg.data_length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shell_ack(adb_service_t *service, apacket *p)
|
||||
{
|
||||
UNUSED(service);
|
||||
UNUSED(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void shell_kick(adb_service_t *service)
|
||||
{
|
||||
int ret;
|
||||
ash_service_t *svc = container_of(service, ash_service_t, service);
|
||||
ret = shell_pipe_start(&svc->pipe, exec_on_data_available);
|
||||
|
||||
/* TODO handle return code */
|
||||
|
||||
assert(ret == 0);
|
||||
}
|
||||
|
||||
static void shell_on_close(shell_pipe_t *pipe)
|
||||
{
|
||||
ash_service_t *svc = container_of(pipe, ash_service_t, pipe);
|
||||
free(svc);
|
||||
}
|
||||
|
||||
static void shell_close(adb_service_t *service)
|
||||
{
|
||||
ash_service_t *svc = container_of(service, ash_service_t, service);
|
||||
|
||||
/* FIXME missing logic here if shell process is still running */
|
||||
|
||||
shell_pipe_destroy(&svc->pipe, shell_on_close);
|
||||
}
|
||||
|
||||
static const adb_service_ops_t shell_ops =
|
||||
{
|
||||
.on_write_frame = shell_write,
|
||||
.on_ack_frame = shell_ack,
|
||||
.on_kick = shell_kick,
|
||||
.close = shell_close
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
adb_service_t * shell_service(adb_client_t *client, const char *params)
|
||||
{
|
||||
UNUSED(params);
|
||||
UNUSED(client);
|
||||
|
||||
int ret;
|
||||
char **argv;
|
||||
const char *target;
|
||||
ash_service_t *service =
|
||||
(ash_service_t *)malloc(sizeof(ash_service_t));
|
||||
|
||||
if (service == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
service->client = client;
|
||||
service->service.ops = &shell_ops;
|
||||
|
||||
ret = shell_pipe_setup(client, &service->pipe);
|
||||
|
||||
/* TODO check return code */
|
||||
|
||||
assert(ret == 0);
|
||||
|
||||
/* Check parameters after "shell:" */
|
||||
|
||||
target = ¶ms[6];
|
||||
|
||||
if (target[0] != 0)
|
||||
{
|
||||
/* Build argv: <nsh -c "command">
|
||||
* argv[0] => "-c"
|
||||
* argv[1] => command
|
||||
* argv[2] => NULL
|
||||
*
|
||||
* malloc content:
|
||||
* - x3 argv pointers
|
||||
* - 3 characters: "-c\0"
|
||||
* - space for command string
|
||||
*/
|
||||
|
||||
argv = malloc(sizeof(char *) * 3 + 3 + (strlen(target)+1));
|
||||
|
||||
argv[0] = (char *)&argv[3];
|
||||
argv[1] = &((char *)&argv[3])[3];
|
||||
argv[2] = NULL;
|
||||
strcpy(argv[0], "-c");
|
||||
strcpy(argv[1], target);
|
||||
}
|
||||
else
|
||||
{
|
||||
argv = NULL;
|
||||
}
|
||||
|
||||
ret = shell_pipe_exec(argv, &service->pipe,
|
||||
exec_on_data_available);
|
||||
|
||||
/* TODO check return code */
|
||||
|
||||
assert(ret == 0);
|
||||
|
||||
free(argv);
|
||||
|
||||
return &service->service;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user