1 /*
2 * Copyright (c) 2017 Rockchip, Inc. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdio.h>
18 #include <string.h>
19 #include <pthread.h>
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <math.h>
23 #include <linux/input.h>
24 #include <linux/rtc.h>
25 #include <sys/un.h>
26 #include <sys/time.h>
27 #include <sys/select.h>
28 #include <sys/socket.h>
29 #include <errno.h>
30 #include <stdlib.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
33
34 #include "rkbtsource_common.h"
35
36 static pthread_t rk_bt_recv_t = 0, rk_bt_spp_s_t = 0;
37 static int spp_is_connected = 0;
38 static int sockfd = 0, spp_client_fd = 0;
39 static int bt_server_open_state = 0;
40 static int bt_server_close_state = 0;
41
bt_cmd_list()42 static void bt_cmd_list()
43 {
44 unsigned int i;
45 for (i = 1; i < sizeof(bt_command_tbs) / sizeof(bt_commands_t); i++) {
46 printf("%02d. %s \n", i, bt_command_tbs[i].cmd);
47 }
48 }
49
rk_spp_client_recv(void * p)50 static int rk_spp_client_recv(void *p)
51 {
52 int bytes_read;
53 char buf[64];
54
55 wait_client:
56 while (spp_is_connected == 0)
57 sleep(1);
58
59 while (1) {
60 //check spp link
61 if (spp_is_connected == 0) {
62 close(spp_client_fd);
63 spp_client_fd = 0;
64 spp_is_connected = 0;
65 goto wait_client;
66 }
67
68 memset(buf, 0, sizeof(buf));
69 bytes_read = read(spp_client_fd, buf, sizeof(buf));
70 if (bytes_read < 0) {
71 printf("[BT SPP] error: %d:%s!\n", bytes_read, strerror(errno));
72 close(spp_client_fd);
73 spp_client_fd = 0;
74 spp_is_connected = 0;
75 goto wait_client;
76 }
77
78 printf("spp client recv: [%s] \n", buf);
79
80 //echo
81 bytes_read = write(spp_client_fd, buf, sizeof(buf));
82 }
83 }
84
rk_bt_check_server(void)85 static int rk_bt_check_server(void)
86 {
87 if (bt_server_open_state && bt_server_close_state) {
88 //close socket, exit.
89 bt_server_open_state = 0;
90 bt_server_close_state = 0;
91 close(sockfd);
92 return 0;
93 }
94
95 return 1;
96 }
97
rk_bt_recv(void * p)98 static int rk_bt_recv(void *p)
99 {
100 int ret, status;
101 bt_msg_t evt;
102 char buff[256] = "";
103 struct iovec io;
104 struct msghdr msg;
105 struct cmsghdr *cmsg;
106
107 while (1) {
108 memset(&evt, 0, sizeof(bt_msg_t));
109 io.iov_base = &evt,
110 io.iov_len = sizeof(bt_msg_t),
111
112 msg.msg_iov = &io,
113 msg.msg_iovlen = 1,
114 msg.msg_control = buff,
115 msg.msg_controllen = sizeof(buff),
116
117 ret = recvmsg(sockfd, &msg, MSG_CMSG_CLOEXEC);
118 if (ret <= 0)
119 continue;
120
121 switch(evt.id) {
122 case RK_BT_EVT_SCAN_ADD_DEV:
123 printf("%s: device is found\n", PRINT_FLAG_RKBTSOURCE);
124 printf(" address: %s\n", evt.dev.addr);
125 printf(" name: %s\n", evt.dev.name);
126 printf(" role: 0x%x\n", evt.dev.role);
127 printf(" rssi: %d\n", evt.dev.rssi);
128 break;
129 case RK_BT_EVT_SCAN_REMOVE_DEV:
130 printf("%s: device is removed\n", PRINT_FLAG_RKBTSOURCE);
131 printf(" address: %s\n", evt.dev.addr);
132 printf(" name: %s\n", evt.dev.name);
133 break;
134 case RK_BT_EVT_SCAN_CHANGE_DEV:
135 printf("%s: device is changed\n", PRINT_FLAG_RKBTSOURCE);
136 printf(" address: %s\n", evt.dev.addr);
137 printf(" name: %s\n", evt.dev.name);
138 printf(" rssi: %d\n", evt.dev.rssi);
139 break;
140 case RK_BT_EVT_PAIRED_DEV:
141 printf("%s: device is paired\n", PRINT_FLAG_RKBTSOURCE);
142 printf(" address: %s\n", evt.dev.addr);
143 printf(" name: %s\n", evt.dev.name);
144 printf(" is_connected: %d\n", evt.dev.is_connected);
145 break;
146 case RK_BT_EVT_SPP_DISCONNECTED:
147 printf("RK_BT_EVT_SPP_DISCONNECTED\n");
148 spp_is_connected = 0;
149 break;
150 case RK_BT_EVT_SPP_CONNECT_FAILED:
151 printf("RK_BT_EVT_SPP_CONNECT_FAILED\n");
152 spp_is_connected = 0;
153 break;
154 case RK_BT_EVT_SPP_CONNECTED:
155 printf("RK_BT_EVT_SPP_CONNECTED\n");
156 cmsg = CMSG_FIRSTHDR(&msg);
157 if (cmsg->cmsg_level != SOL_SOCKET)
158 continue;
159 if (cmsg->cmsg_level != SCM_RIGHTS)
160 continue;
161 spp_client_fd = *((int *)CMSG_DATA(cmsg));
162 printf("RK_BT_EVT_SPP_CLIENT_FD: %d\n", spp_client_fd);
163 spp_is_connected = 1;
164 break;
165 case RK_BT_EVT_INIT_OK:
166 printf("RK_BT_SERVER OPEN SUCCESS\n");
167 bt_server_open_state = 1;
168 break;
169 case RK_BT_EVT_DEINIT_OK:
170 printf("RK_BT_SERVER CLOSED\n");
171 bt_server_close_state = 1;
172 return 0;
173 case RK_BT_EVT_SCAN_ON:
174 printf("RK_BT_SERVER SCAN\n");
175 break;
176 case RK_BT_EVT_SCAN_OFF:
177 printf("RK_BT_SERVER SCAN OFF\n");
178 break;
179 case RK_BT_EVT_SOURCE_OPEN:
180 printf("RK_BT_SERVER SOURCE OPEN\n");
181 break;
182 case RK_BT_EVT_SOURCE_CLOSE:
183 printf("RK_BT_SERVER SOURCE OFF\n");
184 break;
185 case RK_BT_EVT_SOURCE_CONNECTED:
186 printf("RK_BT_SERVER SOURCE CONNECTED\n");
187 printf(" address: %s\n", evt.dev.addr);
188 printf(" name: %s\n", evt.dev.name);
189 break;
190 case RK_BT_EVT_SOURCE_DISCONNECTED:
191 printf("RK_BT_SERVER SOURCE DISCONNECTED\n");
192 printf(" address: %s\n", evt.dev.addr);
193 printf(" name: %s\n", evt.dev.name);
194 break;
195 case RK_BT_EVT_PONG:
196 printf("RK_BT_SERVER_LIVE\n");
197 bt_server_open_state = 1;
198 break;
199 default:
200 printf("[s_t_c: %s]\n", bt_evt_str_table[evt.id].desc);
201 }
202 }
203 }
204
main(int argc,char * argv[])205 int main(int argc, char *argv[])
206 {
207 int i, item_cnt, ret;
208 char cmdbuf[64], cmd[64];
209 char *input_start;
210 bt_msg_t msg;
211
212 bt_server_open_state = 0;
213 bt_server_close_state = 0;
214
215 unlink(RKBTSOURCE_CLIENT_SOCKET_PATH);
216 //start rkwifibt_server
217 system("killall rkwifibt_server");
218 //realpath
219 system("rkwifibt_server &");
220
221 sockfd = socket(AF_UNIX, SOCK_DGRAM, 0);
222 if (sockfd < 0) {
223 printf("%s: Socket create failed!\n", PRINT_FLAG_ERR);
224 return -1;
225 }
226
227 struct sockaddr_un addr;
228 addr.sun_family = AF_UNIX;
229 strcpy(addr.sun_path, RKBTSOURCE_CLIENT_SOCKET_PATH);
230 ret = bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
231 if (ret < 0) {
232 printf("%s: Bind Local addr failed!\n", PRINT_FLAG_ERR);
233 goto OUT;
234 }
235
236 struct timeval t = {4, 0};
237 setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&t, sizeof(t));
238
239 /* Set server address */
240 struct sockaddr_un dst;
241 dst.sun_family = AF_UNIX;
242 strcpy(dst.sun_path, RKBTSOURCE_SERVER_SOCKET_PATH);
243
244 bt_cmd_list();
245 item_cnt = sizeof(bt_command_tbs) / sizeof(bt_commands_t);
246
247 if (rk_bt_recv_t)
248 return 0;
249
250 if (pthread_create(&rk_bt_recv_t, NULL, rk_bt_recv, NULL)) {
251 printf("%s: Create rk_bt_init_thread thread failed\n", __func__);
252 return -1;
253 }
254 pthread_setname_np(rk_bt_recv_t, "rk_bt_recv_t");
255 pthread_detach(rk_bt_recv_t);
256
257 if (pthread_create(&rk_bt_spp_s_t, NULL, rk_spp_client_recv, NULL)) {
258 printf("%s: Create rk_bt_init_thread thread failed\n", __func__);
259 return -1;
260 }
261 pthread_setname_np(rk_bt_spp_s_t, "rk_bt_spp_s_t");
262 pthread_detach(rk_bt_spp_s_t);
263
264 while (1) {
265 if (!rk_bt_check_server())
266 return 0;
267 memset(cmdbuf, 0, sizeof(cmdbuf));
268 memset(&msg, 0, sizeof(bt_msg_t));
269 printf("Please input number or help to run: ");
270
271 if (fgets(cmdbuf, 64, stdin) == NULL)
272 continue;
273
274 if (!strncmp("help", cmdbuf, 4) || !strncmp("h", cmdbuf, 1))
275 bt_cmd_list();
276
277 //remove end space
278 cmdbuf[strlen(cmdbuf) - 1] = 0;
279
280 input_start = strstr(cmdbuf, "input");
281 if (input_start == NULL) {
282 i = atoi(cmdbuf);
283 if ((i < 1) && (i > item_cnt))
284 continue;
285
286 msg.type = RK_BT_CMD;
287 msg.id = bt_command_tbs[i].cmd_id;
288
289 } else {
290 memset(cmd, 0, sizeof(cmd));
291 strncpy(cmd, cmdbuf, strlen(cmdbuf) - strlen(input_start) - 1);
292 i = atoi(cmd);
293 if ((i < 1) && (i > item_cnt))
294 continue;
295
296 msg.type = RK_BT_CMD;
297 msg.id = bt_command_tbs[i].cmd_id;
298 if (msg.id == RK_BT_INIT)
299 strncpy(msg.data, input_start + strlen("input") + 1, 17); //set bt name
300 else
301 strncpy(msg.addr, input_start + strlen("input") + 1, 17); //set bt addr
302 }
303
304 if (!rk_bt_check_server())
305 return 0;
306
307 ret = sendto(sockfd, &msg, sizeof(bt_msg_t), 0, (struct sockaddr *)&dst, sizeof(dst));
308 if (ret < 0) {
309 printf("%s: Socket send failed! ret = %d\n", PRINT_FLAG_ERR, ret);
310 goto OUT;
311 }
312 }
313
314 OUT:
315 if(sockfd)
316 close(sockfd);
317 return ret;
318 }
319