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