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