blob: 996839a2a20ef1203288e5a3685aad2e405884a1 [file] [log] [blame]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <cutils/properties.h>
#include <time.h>
#include <sys/time.h>
#include <termios.h> //UART
#include "mbtk_log.h"
#include "mbtk_adb_info.h"
#include "mbtk_file.h"
#include "mbtk_utils.h"
// 同步收发数据
#define MBTK_ADB_MSG_SYNC 1
#define ADB_BUFF_SIZE 2048
#define DATABITS CS8
#define STOPBITS 0
#define PARITYON 0
#define PARITY 0
static uint8 adb_buff[ADB_BUFF_SIZE];
static int adb_buff_size = 0;
static uint8 *adb_buff_ptr = NULL;
static int file_fd = -1;
static int adb_fd = -1;
static char shell_cmd[ADB_BUFF_SIZE];
static int adb_port_open(const char *dev, unsigned int baud)
{
#if 0
//unsigned int baud = B921600;
//unsigned int baud = B3000000;
struct termios options;
#if MBTK_ADB_MSG_SYNC
int fd = open(dev, O_RDWR | O_NOCTTY, 0644);
#else
int fd = open(dev, O_RDWR | O_NOCTTY | O_NONBLOCK, 0644);
#endif
if (fd < 0)
{
LOGE("Can't open device = (%s)", dev);
return -1;
}
tcgetattr(fd, &options);
cfmakeraw(&options);
cfsetospeed(&options, baud);
if (tcsetattr(fd, TCSAFLUSH, &options) != 0)
{
LOGE("setting fd tc");
close(fd);
return -1;
}
tcflush(fd, TCIFLUSH);
return fd;
#else
int fd = open(dev, O_RDWR);
/* set newtio */
struct termios newtio;
memset(&newtio, 0, sizeof(newtio));
(void)fcntl(fd, F_SETFL, 0);
#if 1 //UART2_AT
/* no flow control for uart by default */
newtio.c_cflag = baud | DATABITS | STOPBITS | PARITYON | PARITY | CLOCAL | CREAD;
#else
newtio.c_cflag = baud | CRTSCTS | DATABITS | STOPBITS | PARITYON | PARITY | CLOCAL | CREAD;
#endif
newtio.c_iflag = IGNPAR;
//newtio.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
newtio.c_oflag = 0;
newtio.c_lflag = 0; /* disable ECHO, ICANON, etc... */
newtio.c_cc[VERASE] = 0x8; /* del */
newtio.c_cc[VEOF] = 4; /* Ctrl-d */
newtio.c_cc[VMIN] = 1; /* blocking read until 1 character arrives */
newtio.c_cc[VEOL] = 0xD; /* '\0' */
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &newtio);
return fd;
#endif
}
static int adb_msg_send(int fd, int msg, const void *data, int data_len)
{
uint8 buff[ADB_BUFF_SIZE] = {0};
uint8 *ptr = buff;
uint32_2_byte(MBTK_ADB_PACK_FLAG, ptr, true);
ptr += sizeof(uint32);
*ptr = (uint8)msg;
ptr++;
uint16_2_byte((uint16)data_len, ptr, false);
ptr += sizeof(uint16);
if(data && data_len > 0) {
memcpy(ptr, data, data_len);
ptr += data_len;
}
int result = file_write(fd, buff, ptr - buff);
LOGD("SEND : %d / %d", result, ptr - buff);
log_hex("SEND", buff, ptr - buff);
return result;
}
static void shell_cmd_cb_func(char *buf,int buf_size)
{
LOGD("data_len : %d", buf_size);
if(buf == NULL || buf_size == 0) { // shell complete
if(adb_msg_send(adb_fd, MBTK_ADB_MSG_CMD_RSP_COMPLETE, NULL, 0) <= 0) {
LOGE("Send MBTK_ADB_MSG_CMD_RSP_COMPLETE fail.");
}
memset(shell_cmd, 0, ADB_BUFF_SIZE);
} else {
if(adb_msg_send(adb_fd, MBTK_ADB_MSG_CMD_RSP, buf, buf_size) <= 0) {
LOGE("Send MBTK_ADB_MSG_CMD_RSP fail.");
}
usleep(10);
}
}
static void* shell_or_at_func(void* argv)
{
UNUSED(argv);
// Process in thread.
LOGD("CMD : %s", shell_cmd);
if(!strncasecmp(shell_cmd, "at ", 3)) { // AT command.
LOGE("Process AT:%s", shell_cmd + 3);
// "at ati"
if(!mbtk_cmd_line_ex(shell_cmd, shell_cmd_cb_func)) {
LOGE("Shell or AT command error.");
}
} else if(!strncasecmp(shell_cmd, "shell ", 6)) { // Shell command.
if(!strcmp(shell_cmd + 6, "cd") || !strncmp(shell_cmd + 6, "cd ", 3)) {
char *cmd = NULL;
if(!strncmp(shell_cmd + 6, "cd ", 3)) {
cmd = shell_cmd + 9;
} else {
cmd = "/";
}
if(chdir(cmd)) {
char buff[ADB_BUFF_SIZE] = {0};
sprintf(buff, "Can't cd to %s", cmd);
if(adb_msg_send(adb_fd, MBTK_ADB_MSG_CMD_RSP_COMPLETE, buff, strlen(buff)) <= 0) {
LOGE("Send MBTK_ADB_MSG_CMD_RSP_COMPLETE fail.");
}
} else {
if(adb_msg_send(adb_fd, MBTK_ADB_MSG_CMD_RSP_COMPLETE, NULL, 0) <= 0) {
LOGE("Send MBTK_ADB_MSG_CMD_RSP_COMPLETE fail.");
}
}
} else {
if(!mbtk_cmd_line_ex(shell_cmd + 6, shell_cmd_cb_func)) {
LOGE("Shell or AT command error.");
}
}
} else {
LOGE("Command error.");
if(adb_msg_send(adb_fd, MBTK_ADB_MSG_ERR_COMMAND, NULL, 0) <= 0) {
LOGE("Send MBTK_ADB_MSG_ERR_COMMAND fail.");
}
}
return NULL;
}
static mbtk_adb_msg_err_enum adb_pack_process(int fd, mbtk_adb_pack_t *pack)
{
static int data_recv_len = 0;
static int data_recv_count_len = 0;
// mbtk_adb_msg_err_enum err = MBTK_ADB_MSG_ERR_SUCCESS;
switch(pack->msg_id) {
case MBTK_ADB_MSG_CONN_START:
{
if(adb_msg_send(fd, MBTK_ADB_MSG_CONN_SUCCESS, NULL, 0) <= 0) {
return MBTK_ADB_MSG_ERR_IO;
}
LOGD("CONN_SUCCESS");
chdir("/");
break;
}
case MBTK_ADB_MSG_PUSH:
{
// data_len[4] path_len[2] path[path_len]
uint8 *ptr = pack->data;
data_recv_count_len = byte_2_uint32(ptr, false);
if(data_recv_count_len <= 0) {
LOGE("File size error:%d", data_recv_count_len);
return MBTK_ADB_MSG_ERR_FILE_SIZE;
}
ptr += sizeof(uint32);
char path[1024] = {0};
int path_len = byte_2_uint16(ptr, false);
if(path_len <= 0) {
LOGE("path length error:%d", path_len);
return MBTK_ADB_MSG_ERR_FILE_PATH;
}
ptr += sizeof(uint16);
memcpy(path, ptr, path_len);
file_fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0777);
if(file_fd < 0) {
LOGE("Open file(%s) error:%d", path, errno);
return MBTK_ADB_MSG_ERR_FILE_PATH;
}
data_recv_len = 0;
if(adb_msg_send(fd, MBTK_ADB_MSG_PUSH_READY, NULL, 0) <= 0) {
return MBTK_ADB_MSG_ERR_IO;
}
LOGD("Start recv file data.");
break;
}
case MBTK_ADB_MSG_PUSH_COMPLETE:
{
close(file_fd);
file_fd = -1;
if(adb_msg_send(fd, MBTK_ADB_MSG_PUSH_SIZE, &data_recv_len, sizeof(uint32)) <= 0) {
return MBTK_ADB_MSG_ERR_IO;
}
LOGD("PUSH_COMPLETE : %d / %d", data_recv_len, data_recv_count_len);
break;
}
case MBTK_ADB_MSG_CMD_REQ:
{
// Shell command or AT command.
memset(shell_cmd, 0, ADB_BUFF_SIZE);
memcpy(shell_cmd, pack->data, pack->data_len);
pthread_t pid;
if (pthread_create(&pid, NULL, shell_or_at_func, NULL) != 0) {
LOGE("Create shell/at thread fail.");
return MBTK_ADB_MSG_ERR_COMMAND;
}
break;
}
case MBTK_ADB_MSG_CMD_KILL:
{
if(!strncasecmp(shell_cmd, "at ", 3)) { // AT command.
LOGE("Kill AT:%s", shell_cmd + 3);
} else if(!strncasecmp(shell_cmd, "shell ", 6)) { // Shell command.
LOGD("Kill cmd:%s", shell_cmd + 6);
char cmd[1024] = {0};
snprintf(cmd,1024,"kill `pidof %s | awk '{print $1}'`", shell_cmd + 6);
system(cmd);
} else {
LOGE("Kill Command/AT error.");
}
break;
}
case MBTK_ADB_MSG_CLOSE_START:
{
if(adb_msg_send(fd, MBTK_ADB_MSG_CLOSE_SUCCESS, NULL, 0) <= 0) {
return MBTK_ADB_MSG_ERR_IO;
}
break;
}
case MBTK_ADB_MSG_DATA:
{
if(file_fd < 0) {
LOGE("Data transfer not started.");
return MBTK_ADB_MSG_ERR_TRANS_NO_START;
}
if(pack->data_len > 0) {
int size = write(file_fd, pack->data, pack->data_len);
if(size == pack->data_len) {
data_recv_len += size;
} else {
LOGE("Write error:%d", errno);
return MBTK_ADB_MSG_ERR_IO;
}
}
break;
}
default:
{
LOGE("MSG id error:%d", pack->msg_id);
return MBTK_ADB_MSG_ERR_UNKNOWN_MSG;
}
}
return MBTK_ADB_MSG_ERR_SUCCESS;
}
/*
* 1 2 data_len
* F6 F7 F8 F9 [msg_id] [data_len] [data...]
*/
static mbtk_adb_msg_err_enum adb_read_a_pack(int fd, mbtk_adb_pack_t *pack)
{
memset(pack, 0x0, sizeof(mbtk_adb_pack_t));
if(adb_buff_size < MBTK_ADB_PACK_HEAD_SIZE) {
read_once:
// LOGD("Will read:adb_buff_size = %d", adb_buff_size);
if(adb_buff_size > 0) {
memmove(adb_buff, adb_buff_ptr, adb_buff_size);
adb_buff_ptr = adb_buff;
} else if(adb_buff_size == 0) {
adb_buff_ptr = adb_buff;
} else {
LOGE("Data error:%d", adb_buff_size);
goto error;
}
int size = read(fd, adb_buff_ptr + adb_buff_size, ADB_BUFF_SIZE - (adb_buff_ptr - adb_buff) - adb_buff_size);
if(size <= 0) {
LOGE("read() error:%d.", errno);
goto error;
}
#if 0
log_hex("RECV", adb_buff_ptr + adb_buff_size, size);
#endif
adb_buff_size += size;
}
if(adb_buff_size < MBTK_ADB_PACK_HEAD_SIZE) {
goto read_once;
}
if(MBTK_ADB_PACK_FLAG != byte_2_uint32(adb_buff_ptr, true))
{
LOGE("Packet FLAG error.");
goto error;
}
pack->msg_id = (mbtk_adb_msg_enum)*(adb_buff_ptr + sizeof(uint32));
pack->data_len = byte_2_uint16(adb_buff_ptr + sizeof(uint32) + sizeof(uint8), false);
if(pack->data_len > 0 && adb_buff_size < MBTK_ADB_PACK_HEAD_SIZE + pack->data_len) {
goto read_once;
}
if(pack->msg_id == MBTK_ADB_MSG_DATA)
LOGD("DATA : %d", pack->data_len);
else
log_hex("PACK", adb_buff_ptr, MBTK_ADB_PACK_HEAD_SIZE + pack->data_len);
// Jump 'flag'
adb_buff_ptr += MBTK_ADB_PACK_HEAD_SIZE;
adb_buff_size -= MBTK_ADB_PACK_HEAD_SIZE;
if(pack->data_len > 0) {
pack->data = adb_buff_ptr;
// Jump 'data'
adb_buff_ptr += pack->data_len;
adb_buff_size -= pack->data_len;
}
return MBTK_ADB_MSG_ERR_SUCCESS;
error:
return MBTK_ADB_MSG_ERR_PACK;
}
int main(int argc, char *argv[])
{
char port_config[32] = {0};
mbtk_log_init("radio", "MBTK_ADBD");
memset(port_config, 0, 32);
property_get("persist.mbtk.dev_ttyGS0", port_config, "at");
if(strcmp(port_config, "adb")) {
memset(port_config, 0, 32);
property_get("persist.mbtk.dev_ttymodem0", port_config, "at");
if(strcmp(port_config, "adb")) {
memset(port_config, 0, 32);
property_get("persist.mbtk.dev_ttyS1", port_config, "at");
if(strcmp(port_config, "adb")) {
LOGE("No config mbtk adb port.");
return 0;
} else {
memset(port_config, 0, 32);
strcpy(port_config, "/dev/ttyS1");
}
} else {
memset(port_config, 0, 32);
strcpy(port_config, "/dev/ttymodem0");
}
} else {
memset(port_config, 0, 32);
strcpy(port_config, "/dev/ttyGS0");
}
LOGD("Port : %s", port_config);
if(access(port_config, R_OK | W_OK)) {
LOGE("Dev %s error:%d", port_config, errno);
return 0;
}
if((adb_fd = adb_port_open(port_config, B921600)) < 0) {
LOGE("Open dev %s fail:%d", port_config, errno);
return 0;
}
#if MBTK_ADB_MSG_SYNC
mbtk_adb_pack_t pack;
mbtk_adb_msg_err_enum err;
while(1) {
memset(adb_buff, 0x0, ADB_BUFF_SIZE);
memset(&pack, 0x0, sizeof(mbtk_adb_pack_t));
adb_buff_size = 0;
adb_buff_ptr = adb_buff;
LOGD("Start/Restart connectting.");
while(1) {
err = adb_read_a_pack(adb_fd, &pack);
if(MBTK_ADB_MSG_ERR_SUCCESS != err) {
adb_msg_send(adb_fd, err, NULL, 0);
break;
}
err = adb_pack_process(adb_fd, &pack);
if(MBTK_ADB_MSG_ERR_SUCCESS != err) {
adb_msg_send(adb_fd, err, NULL, 0);
break;
}
}
}
#else
int select_timeout = 30; // 30s
do
{
struct timeval timeval;
fd_set fdr, fdw;
int ret = 0;
FD_ZERO(&fdw);
FD_ZERO(&fdr);
FD_SET(adb_fd, &fdr);
timeval.tv_sec = select_timeout;
timeval.tv_usec = 0;
ret = select(adb_fd + 1, &fdr, &fdw, 0, &timeval);
if (ret < 0)
{
if (errno == EINTR)
{
continue;
}
LOGE("select error, errno = %d (%s)", errno, strerror(errno));
break;
}
else if (ret == 0)
{
LOGE("select timeout");
continue;
}
// New AT command recv.
if (FD_ISSET(adb_fd, &fdr))
{
}
else
{
LOGW("Unknown select event.");
continue;
}
} while(1);
#endif
LOGD("EXIT!");
return 0;
}