/* * Copyright (c) 2017 Rockchip, Inc. All Rights Reserved. * * Licensed 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rkbtsource_common.h" static pthread_t rk_bt_recv_t = 0, rk_bt_spp_s_t = 0; static int spp_is_connected = 0; static int sockfd = 0, spp_client_fd = 0; static int bt_server_open_state = 0; static int bt_server_close_state = 0; static void bt_cmd_list() { unsigned int i; for (i = 1; i < sizeof(bt_command_tbs) / sizeof(bt_commands_t); i++) { printf("%02d. %s \n", i, bt_command_tbs[i].cmd); } } static int rk_spp_client_recv(void *p) { int bytes_read; char buf[64]; wait_client: while (spp_is_connected == 0) sleep(1); while (1) { //check spp link if (spp_is_connected == 0) { close(spp_client_fd); spp_client_fd = 0; spp_is_connected = 0; goto wait_client; } memset(buf, 0, sizeof(buf)); bytes_read = read(spp_client_fd, buf, sizeof(buf)); if (bytes_read < 0) { printf("[BT SPP] error: %d:%s!\n", bytes_read, strerror(errno)); close(spp_client_fd); spp_client_fd = 0; spp_is_connected = 0; goto wait_client; } printf("spp client recv: [%s] \n", buf); //echo bytes_read = write(spp_client_fd, buf, sizeof(buf)); } } static int rk_bt_check_server(void) { if (bt_server_open_state && bt_server_close_state) { //close socket, exit. bt_server_open_state = 0; bt_server_close_state = 0; close(sockfd); return 0; } return 1; } static int rk_bt_recv(void *p) { int ret, status; bt_msg_t evt; char buff[256] = ""; struct iovec io; struct msghdr msg; struct cmsghdr *cmsg; while (1) { memset(&evt, 0, sizeof(bt_msg_t)); io.iov_base = &evt, io.iov_len = sizeof(bt_msg_t), msg.msg_iov = &io, msg.msg_iovlen = 1, msg.msg_control = buff, msg.msg_controllen = sizeof(buff), ret = recvmsg(sockfd, &msg, MSG_CMSG_CLOEXEC); if (ret <= 0) continue; switch(evt.id) { case RK_BT_EVT_SCAN_ADD_DEV: printf("%s: device is found\n", PRINT_FLAG_RKBTSOURCE); printf(" address: %s\n", evt.dev.addr); printf(" name: %s\n", evt.dev.name); printf(" role: 0x%x\n", evt.dev.role); printf(" rssi: %d\n", evt.dev.rssi); break; case RK_BT_EVT_SCAN_REMOVE_DEV: printf("%s: device is removed\n", PRINT_FLAG_RKBTSOURCE); printf(" address: %s\n", evt.dev.addr); printf(" name: %s\n", evt.dev.name); break; case RK_BT_EVT_SCAN_CHANGE_DEV: printf("%s: device is changed\n", PRINT_FLAG_RKBTSOURCE); printf(" address: %s\n", evt.dev.addr); printf(" name: %s\n", evt.dev.name); printf(" rssi: %d\n", evt.dev.rssi); break; case RK_BT_EVT_PAIRED_DEV: printf("%s: device is paired\n", PRINT_FLAG_RKBTSOURCE); printf(" address: %s\n", evt.dev.addr); printf(" name: %s\n", evt.dev.name); printf(" is_connected: %d\n", evt.dev.is_connected); break; case RK_BT_EVT_SPP_DISCONNECTED: printf("RK_BT_EVT_SPP_DISCONNECTED\n"); spp_is_connected = 0; break; case RK_BT_EVT_SPP_CONNECT_FAILED: printf("RK_BT_EVT_SPP_CONNECT_FAILED\n"); spp_is_connected = 0; break; case RK_BT_EVT_SPP_CONNECTED: printf("RK_BT_EVT_SPP_CONNECTED\n"); cmsg = CMSG_FIRSTHDR(&msg); if (cmsg->cmsg_level != SOL_SOCKET) continue; if (cmsg->cmsg_level != SCM_RIGHTS) continue; spp_client_fd = *((int *)CMSG_DATA(cmsg)); printf("RK_BT_EVT_SPP_CLIENT_FD: %d\n", spp_client_fd); spp_is_connected = 1; break; case RK_BT_EVT_INIT_OK: printf("RK_BT_SERVER OPEN SUCCESS\n"); bt_server_open_state = 1; break; case RK_BT_EVT_DEINIT_OK: printf("RK_BT_SERVER CLOSED\n"); bt_server_close_state = 1; return 0; case RK_BT_EVT_SCAN_ON: printf("RK_BT_SERVER SCAN\n"); break; case RK_BT_EVT_SCAN_OFF: printf("RK_BT_SERVER SCAN OFF\n"); break; case RK_BT_EVT_SOURCE_OPEN: printf("RK_BT_SERVER SOURCE OPEN\n"); break; case RK_BT_EVT_SOURCE_CLOSE: printf("RK_BT_SERVER SOURCE OFF\n"); break; case RK_BT_EVT_SOURCE_CONNECTED: printf("RK_BT_SERVER SOURCE CONNECTED\n"); printf(" address: %s\n", evt.dev.addr); printf(" name: %s\n", evt.dev.name); break; case RK_BT_EVT_SOURCE_DISCONNECTED: printf("RK_BT_SERVER SOURCE DISCONNECTED\n"); printf(" address: %s\n", evt.dev.addr); printf(" name: %s\n", evt.dev.name); break; case RK_BT_EVT_PONG: printf("RK_BT_SERVER_LIVE\n"); bt_server_open_state = 1; break; default: printf("[s_t_c: %s]\n", bt_evt_str_table[evt.id].desc); } } } int main(int argc, char *argv[]) { int i, item_cnt, ret; char cmdbuf[64], cmd[64]; char *input_start; bt_msg_t msg; bt_server_open_state = 0; bt_server_close_state = 0; unlink(RKBTSOURCE_CLIENT_SOCKET_PATH); //start rkwifibt_server system("killall rkwifibt_server"); //realpath system("rkwifibt_server &"); sockfd = socket(AF_UNIX, SOCK_DGRAM, 0); if (sockfd < 0) { printf("%s: Socket create failed!\n", PRINT_FLAG_ERR); return -1; } struct sockaddr_un addr; addr.sun_family = AF_UNIX; strcpy(addr.sun_path, RKBTSOURCE_CLIENT_SOCKET_PATH); ret = bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)); if (ret < 0) { printf("%s: Bind Local addr failed!\n", PRINT_FLAG_ERR); goto OUT; } struct timeval t = {4, 0}; setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&t, sizeof(t)); /* Set server address */ struct sockaddr_un dst; dst.sun_family = AF_UNIX; strcpy(dst.sun_path, RKBTSOURCE_SERVER_SOCKET_PATH); bt_cmd_list(); item_cnt = sizeof(bt_command_tbs) / sizeof(bt_commands_t); if (rk_bt_recv_t) return 0; if (pthread_create(&rk_bt_recv_t, NULL, rk_bt_recv, NULL)) { printf("%s: Create rk_bt_init_thread thread failed\n", __func__); return -1; } pthread_setname_np(rk_bt_recv_t, "rk_bt_recv_t"); pthread_detach(rk_bt_recv_t); if (pthread_create(&rk_bt_spp_s_t, NULL, rk_spp_client_recv, NULL)) { printf("%s: Create rk_bt_init_thread thread failed\n", __func__); return -1; } pthread_setname_np(rk_bt_spp_s_t, "rk_bt_spp_s_t"); pthread_detach(rk_bt_spp_s_t); while (1) { if (!rk_bt_check_server()) return 0; memset(cmdbuf, 0, sizeof(cmdbuf)); memset(&msg, 0, sizeof(bt_msg_t)); printf("Please input number or help to run: "); if (fgets(cmdbuf, 64, stdin) == NULL) continue; if (!strncmp("help", cmdbuf, 4) || !strncmp("h", cmdbuf, 1)) bt_cmd_list(); //remove end space cmdbuf[strlen(cmdbuf) - 1] = 0; input_start = strstr(cmdbuf, "input"); if (input_start == NULL) { i = atoi(cmdbuf); if ((i < 1) && (i > item_cnt)) continue; msg.type = RK_BT_CMD; msg.id = bt_command_tbs[i].cmd_id; } else { memset(cmd, 0, sizeof(cmd)); strncpy(cmd, cmdbuf, strlen(cmdbuf) - strlen(input_start) - 1); i = atoi(cmd); if ((i < 1) && (i > item_cnt)) continue; msg.type = RK_BT_CMD; msg.id = bt_command_tbs[i].cmd_id; if (msg.id == RK_BT_INIT) strncpy(msg.data, input_start + strlen("input") + 1, 17); //set bt name else strncpy(msg.addr, input_start + strlen("input") + 1, 17); //set bt addr } if (!rk_bt_check_server()) return 0; ret = sendto(sockfd, &msg, sizeof(bt_msg_t), 0, (struct sockaddr *)&dst, sizeof(dst)); if (ret < 0) { printf("%s: Socket send failed! ret = %d\n", PRINT_FLAG_ERR, ret); goto OUT; } } OUT: if(sockfd) close(sockfd); return ret; }