blob: 66c55f550133cb3800b7bae2fca777334d10e9de [file] [log] [blame]
b.liu15f456b2024-10-31 20:16:06 +08001#include <string.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <pthread.h>
5#include <unistd.h>
6#include <sys/epoll.h>
7#include <errno.h>
8#include <sys/wait.h>
9#include <sys/types.h>
10
11#include "wpa_ctrl.h"
12#include "sta_ctrl.h"
13//#include "sta_log.h"
14
15#define WPA_SUPPLICANT_LOG_FILE "/data/wpa_supplicant.log"
16
17static void
18sta_ctrl_wpa_req_cb(char *msg, size_t len);
19
20static void*
21sta_ctrl_event_thread_run( void *arg );
22
23static sta_err_enum
24sta_ctrl_close_connection(void);
25
26static sta_err_enum
27sta_ctrl_open_connection(void);
28
29static sta_err_enum
30sta_ctrl_reconnect(void);
31
32static void
33sta_ctrl_recv_event(void);
34
35static sta_err_enum
36sta_ctrl_conf_file_parse
37(
38 const char *key,
39 char *value
40);
41
42extern struct wpa_ctrl;
43
44static struct wpa_ctrl *sta_ctrl_conn;
45static struct wpa_ctrl *sta_mon_conn;
46static int sta_ctrl_attached = 0;
47static pthread_t sta_event_thread_id = -1;
48static int sta_event_thread_is_running = 0;
49static char sta_ctrl_conf_file_path[50];
50static char sta_ctrl_ifname[10];
51static sta_ctrl_msg_cb sta_ctrl_msg = NULL;
52static int sta_ctrl_pipe_fd[2];
53
54static void
55sta_ctrl_wpa_req_cb(char *msg, size_t len)
56{
57 printf("%s\n", msg);
58}
59
60bool
61sta_ctrl_system
62(
63 const char *command
64)
65{
66 int result = TRUE;
67 FILE *stream = NULL;
68
69 printf("system call: %s\n", command);
70
71 stream = popen( command, "w" );
72 if( stream == NULL )
73 {
74 printf("system command failed\n");
75 result = FALSE;
76 }
77 else if( 0 > pclose( stream ) )
78 {
79 printf("pclose command failed\n");
80 }
81
82 return result;
83}
84
85/*
86* Return TRUE if process <name> is not running after 2 second.
87*/
88bool
89sta_ctrl_kill_check(const char *name)
90{
91#define PROCESS_KILL_RETRY 40
92 bool result;
93 int tmp = 0;
94 FILE *cmd;
95 char pid_s[STA_BUF_SIZE];
96 int pid;
97 tmp = snprintf(pid_s,STA_BUF_SIZE,
98 "pidof %s",name);
99 pid_s[tmp] = '\0';
100 tmp = 0;
101 while (tmp++ < PROCESS_KILL_RETRY)
102 {
103 usleep(50000);/*50 mili second*/
104 cmd = popen(pid_s, "r");
105 pid = 0;
106 bzero(pid_s, STA_BUF_SIZE);
107 if(cmd)
108 {
109 fgets(pid_s, STA_BUF_SIZE, cmd);
110 pclose(cmd);
111 }
112 pid = atoi(pid_s);
113 printf("%s pid =%d\n", name,pid);
114 /* If pid is zero we break from while*/
115 if(pid == 0)
116 {
117 result = TRUE;
118 goto exit_end;
119 }
120 }
121
122 printf("PID still running after waiting 2 second.\n");
123 result = FALSE;
124exit_end:
125#undef PROCESS_KILL_RETRY
126 return result;
127}
128
129/*
130* Return TRUE if process <name> is running.
131*/
132bool
133sta_ctrl_process_running(const char *name)
134{
135 char pid_s[STA_BUF_SIZE];
136 int tmp = snprintf(pid_s,STA_BUF_SIZE,
137 "pidof %s",name);
138 pid_s[tmp] = '\0';
139 FILE *cmd = popen(pid_s, "r");
140 bzero(pid_s, STA_BUF_SIZE);
141 if(cmd)
142 {
143 fgets(pid_s, STA_BUF_SIZE, cmd);
144 pclose(cmd);
145 }
146
147 int pid = atoi(pid_s);
148 printf("%s pid =%d\n", name,pid);
149 /* If pid is zero we break from while*/
150 if(pid == 0)
151 {
152 printf("%s not runnig.\n",name);
153 return FALSE;
154 }else{
155 printf("%s is runnig.\n",name);
156 return TRUE;
157 }
158}
159
160
161static void*
162sta_ctrl_event_thread_run( void *arg )
163{
164 printf("Thread[%ld] run().\n",pthread_self());
165
166 int nready;
167 struct epoll_event ev_sock,ev_pipe,events[20];
168 int epfd = epoll_create(256);
169 ev_sock.data.fd = wpa_ctrl_get_fd(sta_mon_conn);
170 ev_sock.events = EPOLLIN | EPOLLET;
171 epoll_ctl(epfd,EPOLL_CTL_ADD,wpa_ctrl_get_fd(sta_mon_conn),&ev_sock);
172
173 ev_pipe.data.fd = sta_ctrl_pipe_fd[0];
174 ev_pipe.events = EPOLLIN | EPOLLET;
175 epoll_ctl(epfd,EPOLL_CTL_ADD,sta_ctrl_pipe_fd[0],&ev_pipe);
176
177 for ( ; ; ) {
178 if(!sta_event_thread_is_running){
179 break;
180 }
181 printf("epoll_wait waitting...\n",nready);
182 nready = epoll_wait(epfd,events,20,-1);
183 printf("epoll_wait return.(count = %d)\n",nready);
184 int i;
185 for(i=0;i<nready;++i) {
186 if (events[i].events & EPOLLIN) {// Read
187 if (events[i].data.fd < 0)
188 continue;
189
190 if(sta_mon_conn // sta_mon_conn can not be NULL
191 && events[i].data.fd == wpa_ctrl_get_fd(sta_mon_conn)){
192 sta_ctrl_recv_event();
193 }else if(events[i].data.fd == sta_ctrl_pipe_fd[0]){
194 printf("Thread end.[fd = %d]\n",events[i].data.fd);
195 // End thread
196 char buf_end[10] = {0};
197 if(read(sta_ctrl_pipe_fd[0],buf_end,10) > 0
198 && strcmp(buf_end,"0") == 0){
199 sta_event_thread_is_running = 0;
200 break;
201 }
202 }else{
203 printf("No such fd[%d].\n",events[i].data.fd);
204 }
205 } else {
206 printf("event error.\n");
207 }
208 }
209 }
210
211 close(epfd);
212 printf("Thread exit.\n");
213 return ((void*)0);
214}
215
216static sta_err_enum
217sta_ctrl_close_connection(void)
218{
219 printf("start.\n");
220 if (sta_ctrl_conn == NULL)
221 return STA_ERR_UNKNOWN;
222
223 if (sta_ctrl_attached) {
224 wpa_ctrl_detach(sta_mon_conn);
225 sta_ctrl_attached = 0;
226 }
227 wpa_ctrl_close(sta_ctrl_conn);
228 sta_ctrl_conn = NULL;
229 if (sta_mon_conn) {
230 wpa_ctrl_close(sta_mon_conn);
231 sta_mon_conn = NULL;
232 }
233
234 printf("end.\n");
235 return STA_ERR_SUCCESS;
236}
237
238static sta_err_enum
239sta_ctrl_open_connection(void)
240{
241 sta_err_enum result = STA_ERR_SUCCESS;
242
243 if(sta_ctrl_conn){
244 return STA_ERR_UNKNOWN;
245 }
246
247 char ctrl_path[100] = {0};
248 result = sta_ctrl_conf_file_parse("ctrl_interface", ctrl_path);
249 if(STA_ERR_SUCCESS != result){
250 printf("sta_ctrl_conf_file_parse() fail(%d).\n",result);
251 return result;
252 }
253 snprintf(ctrl_path + strlen(ctrl_path),10,
254 "/%s",
255 sta_ctrl_ifname);
256
257 printf("ctrl_path = \"%s\"\n",ctrl_path);
258
259 sta_ctrl_conn = wpa_ctrl_open(ctrl_path);
260 if (sta_ctrl_conn == NULL) {
261 sleep(1);
262 return sta_ctrl_open_connection();
263 }
264
265 sta_mon_conn = wpa_ctrl_open(ctrl_path);
266 if (sta_mon_conn == NULL) {
267 return STA_ERR_UNKNOWN;
268 }
269
270 if (wpa_ctrl_attach(sta_mon_conn) == 0) {
271 sta_ctrl_attached = 1;
272 } else {
273 printf("Warning: Failed to attach to "
274 "wpa_supplicant.\n");
275 sta_ctrl_close_connection();
276 return STA_ERR_UNKNOWN;
277 }
278
279 if(!sta_event_thread_is_running) {
280 sta_event_thread_is_running = 1;
281 int ret = pthread_create(&sta_event_thread_id,
282 NULL,
283 sta_ctrl_event_thread_run,
284 NULL);
285 if( ret != 0 ) {
286 printf( "Create thread error!\n");
287 }
288 }else{
289 printf("sta_event_thread is running.\n");
290 return STA_ERR_UNKNOWN;
291 }
292 return result;
293}
294
295static sta_err_enum
296sta_ctrl_reconnect(void)
297{
298 if(STA_ERR_SUCCESS == sta_ctrl_close_connection()){
299 return sta_ctrl_open_connection();
300 }else{
301 return STA_ERR_UNKNOWN;
302 }
303}
304
305static void
306sta_ctrl_recv_event(void)
307{
308 printf("start.\n");
309 if (sta_ctrl_conn == NULL) {
310 sta_ctrl_reconnect();
311 printf("sta_ctrl_conn == NULL:end.\n");
312 return;
313 }
314
315 while (wpa_ctrl_pending(sta_mon_conn) > 0) {
316 char buf[4096];
317 size_t len = sizeof(buf) - 1;
318 if (wpa_ctrl_recv(sta_mon_conn, buf, &len) == 0) {
319 buf[len] = '\0';
320 printf("<<%s>>\n",buf);
321 if(sta_ctrl_msg)
322 sta_ctrl_msg(buf);
323 } else {
324 printf("Could not read pending message.\n");
325 break;
326 }
327 }
328
329 if (wpa_ctrl_pending(sta_mon_conn) < 0) {
330 printf("Connection to wpa_supplicant lost - trying to "
331 "reconnect\n");
332 sta_ctrl_reconnect();
333 }
334
335 printf("end.\n");
336}
337
338static sta_err_enum
339sta_ctrl_conf_file_parse
340(
341 const char *key,
342 char *value
343)
344{
345 sta_err_enum result = STA_ERR_UNKNOWN;
346 FILE *fd = fopen(sta_ctrl_conf_file_path,"r");
347 if(!fd){
348 printf("Open file(%s) fail(%d).\n",sta_ctrl_conf_file_path,errno);
349 return STA_ERR_UNKNOWN;
350 }
351
352 char buf[1024];
353 while(fgets(buf,1024,fd)){
354 char *start = strstr(buf,key);
355 if(start){ // Find key
356 char *tmp = start + strlen(start) -1;
357 while(*tmp){
358 if(*tmp == '\r'
359 || *tmp == '\n'){
360 *tmp = '\0';
361 }else{
362 break;
363 }
364 *tmp--;
365 }
366
367 int size = snprintf(value,100,
368 "%s",
369 start + strlen(key) + 1);
370 value[size] = '\0';
371 result = STA_ERR_SUCCESS;
372 break;
373 }
374 }
375
376 fclose(fd);
377
378 return result;
379}
380
381/***************************************************************/
382/************************ Public Fuction ***********************/
383/***************************************************************/
384sta_err_enum
385sta_ctrl_cmd_process
386(
387 const char *cmd,
388 char *reply,
389 size_t reply_len
390)
391{
392 sta_err_enum result = STA_ERR_SUCCESS;
393 bzero(reply,reply_len);
394 reply_len = reply_len - 1;
395 int ret = wpa_ctrl_request(sta_ctrl_conn,
396 cmd,
397 strlen(cmd),
398 reply,
399 &reply_len,
400 sta_ctrl_wpa_req_cb);
401 if (ret == -2) {
402 printf("command timed out.\n");
403 result = STA_ERR_TIMEOUT;
404 goto end_fail;
405 } else if (ret < 0) {
406 printf("command failed.\n");
407 result = STA_ERR_UNKNOWN;
408 goto end_fail;
409 } else {
410 reply[reply_len] = '\0';
411 printf("1:%s\n", reply);
412
413 if(reply_len > 0 && reply[reply_len - 1] != '\n')
414 printf("\n");
415 }
416
417end_success:
418
419 return result;
420end_fail:
421
422 return result;
423}
424
425/**
426* Open or close wlan driver.
427*/
428sta_err_enum
429sta_ctrl_driver_init(bool open)
430{
431 sta_err_enum result = STA_ERR_SUCCESS;
432
433 FILE *fd_tmp = NULL;
434 if(open){
435 fd_tmp = popen("/etc/wifi/mbtk_wifi_driver.sh sta start","r");
436 }else{
437 fd_tmp = popen("/etc/wifi/mbtk_wifi_driver.sh driver_rmmod","r");
438 }
439
440 if(fd_tmp){
441 char buf[200] = {0};
442 fgets(buf,200,fd_tmp);
443 pclose(fd_tmp);
444 if(strlen(buf) > 0){
445 printf("Driver %s fail.(%s)\n",(open?"open":"close"),buf);
446 result = STA_ERR_DRIVER;
447 }else{// Open wpa_supplicant
448 printf("Driver %s success.\n",(open?"open":"close"));
449 }
450 }else{
451 printf("Driver %s fail.(%s)\n",(open?"open":"close"));
452 result = STA_ERR_DRIVER;
453 }
454
455 return result;
456}
457
458sta_err_enum
459sta_ctrl_wpa_init
460(
461 const char *conf_file,
462 const char *interface,
463 sta_ctrl_msg_cb cb
464)
465{
466 sta_err_enum result = STA_ERR_SUCCESS;
467 if(!conf_file
468 || strlen(conf_file) == 0){
469 result = STA_ERR_UNKNOWN;
470 goto end_fail;
471 }
472
473 if(!interface
474 || strlen(interface) == 0){
475 result = STA_ERR_UNKNOWN;
476 goto end_fail;
477 }
478
479 sta_ctrl_msg = cb;
480
481 int size = snprintf(sta_ctrl_conf_file_path,
482 50,
483 "%s",
484 conf_file);
485 sta_ctrl_conf_file_path[size] = '\0';
486 size = snprintf(sta_ctrl_ifname,
487 10,
488 "%s",
489 interface);
490 sta_ctrl_ifname[size] = '\0';
491
492 if(pipe(sta_ctrl_pipe_fd)){
493 printf("pipe() fail(%d).\n",errno);
494 result = STA_ERR_UNKNOWN;
495 goto end_fail;
496 }
497
498 FILE *fd_tmp = popen("pidof wpa_supplicant","r");
499 if(fd_tmp){
500 char buf[200] = {0};
501 fgets(buf,200,fd_tmp);
502 pclose(fd_tmp);
503 if(strlen(buf) > 0){
504 printf("wpa_supplicant is running.(%s)\n",buf);
505 }else{// Open wpa_supplicant
506 bzero(buf,200);
507
508 snprintf(buf,200,
509 "wpa_supplicant -Dnl80211 -c%s -i%s -f%s -ddd &",
510 conf_file,
511 interface,
512 WPA_SUPPLICANT_LOG_FILE);
513
514 /*
515 snprintf(buf,200,
516 "wpa_supplicant -Dnl80211 -iwlan0 -c/etc/wifi/wpa_supplicant.conf -B");
517 */
518 if (sta_ctrl_system(buf)){
519 printf("\"%s\" success.\n",buf);
520 sleep(1);
521 }else{
522 printf("\"%s\" fail.\n",buf);
523 result = STA_ERR_UNKNOWN;
524 goto end_fail;
525 }
526 }
527 }else{
528 printf("\"pidof wpa_supplicant\" fail\n");
529 result = STA_ERR_UNKNOWN;
530 goto end_fail;
531 }
532
533 result = sta_ctrl_open_connection();
534 if(STA_ERR_SUCCESS != result) {
535 printf("sta_ctrl_open_connection() fail(%d).\n",result);
536 goto end_fail;
537 }
538
539end_success:
540
541 return result;
542end_fail:
543
544 return result;
545}
546
547sta_err_enum
548sta_ctrl_wpa_deinit
549(
550 void
551)
552{
553 sta_err_enum result = STA_ERR_SUCCESS;
554 result = sta_ctrl_close_connection();
555 if(STA_ERR_SUCCESS != result){
556 goto end_fail;
557 }
558
559 bzero(sta_ctrl_conf_file_path,50);
560 bzero(sta_ctrl_ifname,10);
561
562 sta_event_thread_is_running = 0;
563 // End thread.
564 write(sta_ctrl_pipe_fd[1],"0",1);
565
566
567 printf("Waitting for thread(%ld) exit.\n",sta_event_thread_id);
568
569 pthread_join(sta_event_thread_id,NULL);
570
571 printf("pthread_join() return.\n");
572
573
574 close(sta_ctrl_pipe_fd[0]);
575 close(sta_ctrl_pipe_fd[1]);
576
577 sta_event_thread_id = -1;
578 sta_ctrl_msg = NULL;
579
580 // Stop process wpa_supplicant
581 if(sta_ctrl_system("killall -15 wpa_supplicant")
582 && sta_ctrl_kill_check("wpa_supplicant")){
583 printf("\"killall -15 wpa_supplicant\" success.\n");
584 }else{
585 if(sta_ctrl_system("killall -9 wpa_supplicant")){
586 printf("\"killall -9 wpa_supplicant\" success.\n");
587 }else{
588 printf("\"killall -9 wpa_supplicant\" fail.\n");
589 }
590 }
591
592end_success:
593 printf("sta_ctrl_wpa_deinit() end(success).\n");
594 return result;
595end_fail:
596 printf("sta_ctrl_wpa_deinit() end(fail)[%s].\n",result);
597 return result;
598}
599