| #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 <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] = {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] = {0}; |
| snprintf(cmd,1024,"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; |
| } |
| |