#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //tool role #define SERVER 0 #define CLIENT 1 #define WLAN_CLIENT 2 //interface #define UART 0 #define USB 1 #define WLAN 2 //uart param #define BAUDRATE 1500000 #define DATABITS 8 #define PARTY 'N' #define STOP '1' #define SOFTWARE_HANDSHAKE 0 #define HARDWARE_HANDSHAKE 0 //socket param #define BT_HCI_TOOL_PORT 5001 #define SOCKER_BUFFER_SIZE 1024 #define OK 0 #define ERR -1 #define FALSE 0 #define TRUE 1 #define DOWN_FW_CFG _IOW('E', 176, int) #define GET_USB_INFO _IOR('E', 180, int) #define WLAN_CMD_MAX_CNT 256 #define TXRX_PARA SIOCDEVPRIVATE+1 int server_or_client = SERVER; int interface = USB; int bt_dev_fd = 0; char s_baudrate[8]; char* s_hci_command[256]; char w_ifname[64]; char *w_command[WLAN_CMD_MAX_CNT]; char hci_event[256]; char dev_path[] = "/dev/aicbt_dev"; char hci_reset[] = { 0x01, 0x03, 0x0c, 0x00 }; typedef struct android_wifi_priv_cmd { char *buf; int used_len; int total_len; } android_wifi_priv_cmd; void helper(){ printf("\t<-s> to be tool service. ex. \"bt_test -s uart 115200 /dev/ttyS0\" or \"bt_test -s usb\" or \"bt_test -s wlan wlan0\"\n"); //printf("\t<-s> to be tool service. ex. -s uart 115200 noflow and -s usb\n"); printf("\t<-c> to send hci cmd to interface.\n"); printf("\t<-w> to send wlan cmd to interface.\n"); } int parse_cmd_line(int argc, char **argv){ int command_number = argc; int command_counter = 1; int hci_command_counter = 0; //int error_command = 0; while(command_counter < command_number){ if(!strcmp(argv[command_counter], "-s")){ if(!(command_number >= 3)){ printf("error command \r\n"); return ERR; } printf("bt_hci_tool server setting\r\n"); server_or_client = SERVER; command_counter++; if(!strcmp(argv[command_counter], "usb")){ printf("use USB\r\n"); interface = USB; return OK; }else if(!strcmp(argv[command_counter], "uart")){ interface = UART; if(command_number != 5){ printf("error command \r\n"); return ERR; } command_counter++; memcpy(s_baudrate, argv[command_counter], strlen(argv[command_counter])); command_counter++; memset(dev_path, 0, strlen(dev_path)); memcpy(dev_path, argv[command_counter], strlen(argv[command_counter])); printf("use UART %d %s\r\n", atoi(s_baudrate), dev_path); return OK; }else if(!strcmp(argv[command_counter], "wlan")){ interface = WLAN; if(command_number != 4){ printf("error command \r\n"); return ERR; } command_counter++; memcpy(w_ifname, argv[command_counter], strlen(argv[command_counter])); printf("use WLAN %s\r\n", w_ifname); return OK; }else{ printf("interface set error\r\n"); return ERR; } }else if(!strcmp(argv[command_counter], "-c")){ server_or_client = CLIENT; command_counter++; hci_command_counter = 0; while(command_counter < command_number){ s_hci_command[hci_command_counter++] = argv[command_counter]; command_counter++; } return OK; } else if (!strcmp(argv[command_counter], "-w")) { int w_command_counter = 0; server_or_client = WLAN_CLIENT; if (command_number >= WLAN_CMD_MAX_CNT) { printf("too much args\r\n"); return ERR; } command_counter++; while (command_counter < command_number) { w_command[w_command_counter++] = argv[command_counter]; command_counter++; } return OK; }else{ if (strcmp(argv[1], "-h") != 0) { printf("unknow command %s \r\n", argv[command_counter]); } helper(); return ERR; } command_counter++; } helper(); return ERR; } void uart_set_options(int baudrate, int databits, char parity, char stop, int softwareHandshake, int hardwareHandshake) { struct termios newtio; if (tcgetattr(bt_dev_fd, &newtio)!=0) { printf("tcgetattr() 3 failed \n"); } speed_t _baud=0; printf("set baudrate:%d\n", baudrate); switch (baudrate) { #ifdef B0 case 0: _baud=B0; break; #endif #ifdef B50 case 50: _baud=B50; break; #endif #ifdef B75 case 75: _baud=B75; break; #endif #ifdef B110 case 110: _baud=B110; break; #endif #ifdef B134 case 134: _baud=B134; break; #endif #ifdef B150 case 150: _baud=B150; break; #endif #ifdef B200 case 200: _baud=B200; break; #endif #ifdef B300 case 300: _baud=B300; break; #endif #ifdef B600 case 600: _baud=B600; break; #endif #ifdef B1200 case 1200: _baud=B1200; break; #endif #ifdef B1800 case 1800: _baud=B1800; break; #endif #ifdef B2400 case 2400: _baud=B2400; break; #endif #ifdef B4800 case 4800: _baud=B4800; break; #endif #ifdef B7200 case 7200: _baud=B7200; break; #endif #ifdef B9600 case 9600: _baud=B9600; break; #endif #ifdef B14400 case 14400: _baud=B14400; break; #endif #ifdef B19200 case 19200: _baud=B19200; break; #endif #ifdef B28800 case 28800: _baud=B28800; break; #endif #ifdef B38400 case 38400: _baud=B38400; break; #endif #ifdef B57600 case 57600: _baud=B57600; break; #endif #ifdef B76800 case 76800: _baud=B76800; break; #endif #ifdef B115200 case 115200: _baud=B115200; break; #endif #ifdef B128000 case 128000: _baud=B128000; break; #endif #ifdef B230400 case 230400: _baud=B230400; break; #endif #ifdef B460800 case 460800: _baud=B460800; break; #endif #ifdef B576000 case 576000: _baud=B576000; break; #endif #ifdef B921600 case 921600: _baud=B921600; break; #endif #ifdef B1500000 case 1500000: _baud=B1500000; break; #endif #ifdef B2000000 case 2000000: _baud=B2000000; break; #endif default: break; } cfsetospeed(&newtio, (speed_t)_baud); cfsetispeed(&newtio, (speed_t)_baud); /* We generate mark and space parity ourself. */ if (databits == 7 && (parity=='M' || parity == 'S')) { databits = 8; } switch (databits) { case 5: newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS5; break; case 6: newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS6; break; case 7: newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS7; break; case 8: default: newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS8; break; } newtio.c_cflag |= CLOCAL | CREAD; //parity newtio.c_cflag &= ~(PARENB | PARODD); if (parity == 'E') { newtio.c_cflag |= PARENB; } else if (parity== 'O') { newtio.c_cflag |= (PARENB | PARODD); } //hardware handshake newtio.c_cflag &= ~CRTSCTS; //stopbits if (stop=='2') { newtio.c_cflag |= CSTOPB; } else { newtio.c_cflag &= ~CSTOPB; } newtio.c_iflag=IGNBRK; //software handshake if (softwareHandshake) { newtio.c_iflag |= IXON | IXOFF; } else { newtio.c_iflag &= ~(IXON|IXOFF|IXANY); } newtio.c_lflag=0; newtio.c_oflag=0; // newtio.c_cc[VTIME]=1; // newtio.c_cc[VMIN]=60; if (tcsetattr(bt_dev_fd, TCSANOW, &newtio)!=0) { printf("tcsetattr() 1 failed \n"); } if (tcgetattr(bt_dev_fd, &newtio)!=0) { printf("tcsetattr() 4 failed \n"); } //hardware handshake if (hardwareHandshake) { newtio.c_cflag |= CRTSCTS; } else { newtio.c_cflag &= ~CRTSCTS; } if (tcsetattr(bt_dev_fd, TCSANOW, &newtio)!=0) { printf("tcsetattr() 2 failed \n"); } } unsigned char atoh(char* s_data){ unsigned char ret_value; char temp_value = 0; //h if(s_data[0] >= 48 && s_data[0] <= 57){ temp_value = s_data[0] - 48; }else if(s_data[0] >= 65 && s_data[0] <= 70){ temp_value = (s_data[0] - 65) + 10; }else if(s_data[0] >= 97 && s_data[0] <= 102){ temp_value = (s_data[0] - 97) + 10; } ret_value = temp_value; ret_value = ret_value << 4; //printf("atoh1: ret_value:%x\r\n", ret_value); //l if(s_data[1] >= 48 && s_data[1] <= 57){ temp_value = s_data[1] - 48; }else if(s_data[1] >= 65 && s_data[1] <= 70){ temp_value = (s_data[1] - 65) + 10; }else if(s_data[1] >= 97 && s_data[1] <= 102){ temp_value = (s_data[1] - 97) + 10; } ret_value |= temp_value; //printf("atoh2: ret_value:%x\r\n", ret_value); return ret_value; } int send_to_server(unsigned char* buffer, int len){ int client_socket; struct sockaddr_in serverAddr; //unsigned long long package_totel_counter = 0; if((client_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0){ return ERR; } serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(BT_HCI_TOOL_PORT); serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); if(connect(client_socket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0){ return ERR; } send(client_socket, buffer, len, 0); return OK; } void send_hci_command(){ int i = 0; int command_len = 0; unsigned char buffer[SOCKER_BUFFER_SIZE]; // printf("send hci command: \r\n"); for(i = 0;i < 256; i++){ if(s_hci_command[i] == NULL){ command_len = i; break; } buffer[i] = atoh(s_hci_command[i]); // printf("%02X ", buffer[i]); } send_to_server(buffer, i); // printf("\r\n"); } void send_wlan_command(void) { int i = 0; int command_len = 0; unsigned char buffer[SOCKER_BUFFER_SIZE] = {0,}; while ((w_command[i] != NULL) && (i < WLAN_CMD_MAX_CNT)) { strcat((char*)&buffer[0], w_command[i]); strcat((char*)&buffer[0], " "); i++; } command_len = strlen((char*)&buffer[0]); printf("command_len:%d \r\n", command_len); if (command_len > 1) { //command_len--; // rm last space //buffer[command_len] = '\0'; send_to_server(buffer, command_len); } } int hci_send(char* data, int len){ int i = 0; unsigned char tmp_data[len]; printf("COMMAND(%d): \r\n", len); for(i = 0; i < len; i++){ tmp_data[i] = (unsigned char)data[i]; printf("%02X ", tmp_data[i]); } printf("\r\n"); len = write(bt_dev_fd, tmp_data, len); if (len < 0) { printf("write data error \n"); return FALSE; } return TRUE; } int hci_recv(char* data, int len){ int i = 0; unsigned char tmp_byte[64];// = 0x00; memset(data, 0, len); len = read(bt_dev_fd, data, len); if (len < 0) { printf("read error \n"); return FALSE; } printf("EVENT(%d): \r\n", len); for(i = 0; i < len; i++){ tmp_byte[i] = (unsigned char)data[i]; printf("%02X ", tmp_byte[i]); } printf("\r\n"); if(tmp_byte[1] == 0x0D) { uint32_t rx_pkt_len = tmp_byte[4] | (tmp_byte[5] << 8) | (tmp_byte[6] << 16) | (tmp_byte[7] << 24); uint32_t total_rx_pkts = tmp_byte[8] | (tmp_byte[9] << 8) | (tmp_byte[10] << 16) | (tmp_byte[11] << 24); uint32_t rx_ok_pkts = tmp_byte[12] | (tmp_byte[13] << 8) | (tmp_byte[14] << 16) | (tmp_byte[15] << 24); uint32_t rx_err_pkts = tmp_byte[16] | (tmp_byte[17] << 8) | (tmp_byte[18] << 16) | (tmp_byte[19] << 24); uint32_t rx_err_bits = tmp_byte[20] | (tmp_byte[21] << 8) | (tmp_byte[22] << 16) | (tmp_byte[23] << 24); float per = (float) 100 * rx_err_pkts / total_rx_pkts; float ber = (float) 10000 * rx_err_bits / (total_rx_pkts * rx_pkt_len * 8) ; printf("rx result: pkt_len=%d, total=%d, ok=%d, err=%d, err_bits=%d, per=%.2f%%, ber=%.4f%%%%%%\n", rx_pkt_len, total_rx_pkts, rx_ok_pkts, rx_err_pkts, rx_err_bits, per, ber); } return len; } int wlan_send(char *data, int len) { int sock; struct ifreq ifr; int ret = 0; int i = 0; char wl_cmd[64]; struct android_wifi_priv_cmd priv_cmd; char is_param_err = 0; int buf_len = 0; int argC = 0; int idx = 0; sock = socket(PF_INET, SOCK_DGRAM, 0); if (sock < 0) { printf("bad sock!\n"); return ERR; } memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, w_ifname); if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) { printf("%s Could not read interface %s flags: %s",__func__, w_ifname, strerror(errno)); return ERR; } if (!(ifr.ifr_flags & IFF_UP)) { printf("%s is not up!\n",w_ifname); return ERR; } printf("ifr.ifr_name = %s\n", ifr.ifr_name); memset(&priv_cmd, 0, sizeof(priv_cmd)); memset(wl_cmd, 0, sizeof(wl_cmd)); // extract wlan command & argC for (i = 0; i < len; i++) { if (data[i] != ' ') { if (argC == 0) { wl_cmd[i] = data[i]; } } else { argC++; } } printf("wl_cmd=%s, argC=%d\r\n", wl_cmd, argC); priv_cmd.buf = data; priv_cmd.used_len = len; priv_cmd.total_len = SOCKER_BUFFER_SIZE; ifr.ifr_data = (void*)&priv_cmd; if ((strcasecmp(wl_cmd, "BT_RESET") == 0)) { char bt_reset_hci_cmd[32] = "01 03 0c 00"; if (argC == 1) { buf_len = priv_cmd.used_len; memcpy(&priv_cmd.buf[buf_len], &bt_reset_hci_cmd[0], strlen(bt_reset_hci_cmd)); buf_len += strlen(bt_reset_hci_cmd); priv_cmd.used_len = buf_len; } else { is_param_err = 1; } } else if ((strcasecmp(wl_cmd, "BT_TXDH") == 0)) { char bt_txdh_hci_cmd[255] = "01 06 18 0e "; if (argC == 15) { buf_len = priv_cmd.used_len; int arg_len = strlen("BT_TXDH"); int txdh_cmd_len = strlen(bt_txdh_hci_cmd); memcpy(&bt_txdh_hci_cmd[txdh_cmd_len], &priv_cmd.buf[arg_len+1], buf_len - arg_len - 1); memcpy(&priv_cmd.buf[arg_len+1], &bt_txdh_hci_cmd[0], strlen(bt_txdh_hci_cmd)); buf_len += strlen(bt_txdh_hci_cmd); priv_cmd.used_len = buf_len; } else { is_param_err = 1; } } else if ((strcasecmp(wl_cmd, "BT_RXDH") == 0)) { if (argC == 14) { char bt_rxdh_hci_cmd[255] = "01 0b 18 0d "; buf_len = priv_cmd.used_len; int arg_len = strlen("BT_RXDH"); int rxdh_cmd_len = strlen(bt_rxdh_hci_cmd); memcpy(&bt_rxdh_hci_cmd[rxdh_cmd_len], &priv_cmd.buf[arg_len+1], buf_len - arg_len - 1); memcpy(&priv_cmd.buf[arg_len+1], &bt_rxdh_hci_cmd[0], strlen(bt_rxdh_hci_cmd)); buf_len += strlen(bt_rxdh_hci_cmd); priv_cmd.used_len = buf_len; } else { is_param_err = 1; } } else if ((strcasecmp(wl_cmd, "BT_STOP") == 0)) { char bt_stop_hci_cmd[255] = "01 0C 18 01 "; if (argC == 2) { buf_len = priv_cmd.used_len; int arg_len = strlen("BT_STOP"); int stop_cmd_len = strlen(bt_stop_hci_cmd); memcpy(&bt_stop_hci_cmd[stop_cmd_len], &priv_cmd.buf[arg_len+1], buf_len - arg_len - 1); memcpy(&priv_cmd.buf[arg_len+1], &bt_stop_hci_cmd[0], strlen(bt_stop_hci_cmd)); buf_len += strlen(bt_stop_hci_cmd); priv_cmd.used_len = buf_len; } else if ((strcasecmp(wl_cmd, "BT_DATA") == 0)) { //char bt_raw_data_cmd[255]; int arg_len = strlen(wl_cmd); buf_len = priv_cmd.used_len; memcpy(&priv_cmd.buf[arg_len+1], &priv_cmd.buf[arg_len+1], buf_len - arg_len - 1); priv_cmd.used_len = buf_len - arg_len - 1; } else { is_param_err = 1; } } else { is_param_err = 0; } if (is_param_err) { printf("param error!!!\n"); return ERR; } if ((ret = ioctl(sock, TXRX_PARA, &ifr)) < 0) { printf("%s: error ioctl[TX_PARA] ret= %d\n", __func__, ret); return ret; } memcpy(&priv_cmd, ifr.ifr_data, sizeof(struct android_wifi_priv_cmd)); if (strcasecmp(wl_cmd, "GET_BT_RX_RESULT") == 0) { printf("done: get bt rx total=%d, ok=%d, err=%d\n", *(unsigned int *)priv_cmd.buf, *(unsigned int *)&priv_cmd.buf[4], *(unsigned int *)&priv_cmd.buf[8]); } else if (strcasecmp(wl_cmd, "BT_DATA") == 0) { unsigned char *buff = (unsigned char *)&priv_cmd.buf[1]; int len = priv_cmd.buf[0]; printf("done: %d\n", len); for (idx = 0; idx < len; idx++) { printf("%02x ", buff[idx]); } printf("\n"); } else { printf("done\n"); } return OK; } int dev_open(){ int n = 0; bt_dev_fd = open(dev_path, O_RDWR | O_NDELAY); if(bt_dev_fd < 0) { printf("dev_path %s fail to open \r\n", dev_path); return ERR; } if(interface == UART){ tcflush(bt_dev_fd, TCIOFLUSH); n = fcntl(bt_dev_fd, F_GETFL, 0); fcntl(bt_dev_fd, F_SETFL, n & ~O_NDELAY); uart_set_options(/*BAUDRATE*/atoi(s_baudrate), DATABITS, PARTY, STOP, SOFTWARE_HANDSHAKE, HARDWARE_HANDSHAKE); }else{ ioctl(bt_dev_fd, DOWN_FW_CFG); ioctl(bt_dev_fd, GET_USB_INFO); } printf("bt dev open successful\r\n"); return OK; } void dev_close(){ close(bt_dev_fd); } int socket_init(){ int client; int server_socket; struct sockaddr_in server_addr; struct sockaddr_in clientAddr; int addr_len = sizeof(clientAddr); char buffer[SOCKER_BUFFER_SIZE]; int recv_len = 0; if((server_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0){ return ERR; } //bzero(&server_addr, sizeof(server_addr)); memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(BT_HCI_TOOL_PORT); server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //setsockopt(server_socket ,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL)); if(bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0){ printf("binding error\r\n"); return ERR; } if(listen(server_socket, 5) < 0){ printf("listen error"); return ERR; } while(1){ client = accept(server_socket, (struct sockaddr*)&clientAddr, (socklen_t*)&addr_len); if(client == ERR){ return 0; } recv_len = recv(client, buffer, SOCKER_BUFFER_SIZE, 0); if ((interface == USB) || (interface == UART)) { hci_send(buffer, recv_len); } else { wlan_send(buffer, recv_len); } } } void* hci_recv_thread( void *arg ){ printf("hci recv thread ready %p\r\n", arg); while(1){ hci_recv(hci_event, sizeof(hci_event)); // exit(0); } } void start_server(){ int ret = ERR; if ((interface == USB) || (interface == UART)) { pthread_t hci_recv_th; //init bt communication ret = dev_open(); if(ret == ERR){ printf("dev_open fail \r\n"); return; } //test to send reset printf("to test hci reset for bt device\r\n"); hci_send(hci_reset, sizeof(hci_reset)); hci_recv(hci_event, sizeof(hci_event)); ret = pthread_create( &hci_recv_th, NULL, hci_recv_thread, NULL); printf("bt device test ok \r\n"); } else if (interface == WLAN) { char buf[SOCKER_BUFFER_SIZE] = {"BT_RESET "}; wlan_send(buf, strlen(buf)); } //init localhost socket ret = socket_init(); if (!ret) { printf("socket init done\r\n"); } } int main(int argc, char *argv[]){ int ret = parse_cmd_line(argc, argv); if (ret) { return ret; } if(server_or_client == SERVER){ start_server(); } else if (server_or_client == CLIENT) { send_hci_command(); } else { send_wlan_command(); } return 0; }