|  | #include <stdio.h> | 
|  | #include <stdlib.h> | 
|  | #include <unistd.h> | 
|  | #include <errno.h> | 
|  | #include <fcntl.h> | 
|  | #include <stdint.h> | 
|  | #include <string.h> | 
|  | #include <cutils/properties.h> | 
|  | #include <time.h> | 
|  | #include <sys/time.h> | 
|  | #include <termios.h>    //UART | 
|  | #include <pthread.h> | 
|  |  | 
|  | #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 + 10] = {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"); | 
|  |  | 
|  |  | 
|  | if(chdir("/")) { | 
|  | LOGE("chdir / fail."); | 
|  | } | 
|  | 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 * 3] = {0}; | 
|  | snprintf(cmd,sizeof(cmd),"kill `pidof %s | awk '{print $1}'`", shell_cmd + 6); | 
|  | mbtk_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"); | 
|  |  | 
|  | MBTK_SOURCE_INFO_PRINT("mbtk_adbd"); | 
|  |  | 
|  | #ifdef MBTK_DUMP_SUPPORT | 
|  | mbtk_debug_open(NULL, TRUE); | 
|  | #endif | 
|  |  | 
|  | 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; | 
|  | } | 
|  |  |