K2.6 patches and update.
[tomato.git] / release / src-rt / wl / exe / wlu_server_shared.c
blobded15286ca30f5e3edf8b6223790d9afa88435bd
1 /*
2 * File Name: wlu_server_shared.c
3 * Common server specific functions for linux and win32
5 * Copyright (C) 2010, Broadcom Corporation
6 * All Rights Reserved.
7 *
8 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
9 * the contents of this file may not be disclosed to third parties, copied
10 * or duplicated in any form, in whole or in part, without the prior
11 * written permission of Broadcom Corporation.
13 * $Id: wlu_server_shared.c,v 1.38.2.2 2011-01-27 23:11:30 Exp $
17 * Description: Main Server specific wrappers
18 * This module implements all the server specific functions
19 * for Win32 and Linux
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <ctype.h>
25 #ifdef SYMBIAN
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <netinet/in.h>
29 #else
30 #if !defined(TARGETOS_nucleus) && !defined(MACOSX)
31 #include <malloc.h>
32 #endif
33 #endif /* SYMBIAN */
34 #include <assert.h>
36 #ifndef UNDER_CE
37 #include <errno.h>
38 #else
39 #include <winsock2.h>
40 #endif
41 #ifndef WIN32
42 #if !defined(TARGETOS_nucleus)
43 #include <sys/types.h>
44 #include <sys/socket.h>
45 #include <arpa/inet.h>
46 #include <net/if.h>
47 #include <unistd.h>
48 #include <netdb.h>
49 #include <signal.h>
50 #endif /* TARGETOS_nucleus */
51 #endif /* WIN32 */
53 #ifdef WIN32
54 #include <windows.h>
55 #include <winioctl.h>
56 #include <ntddndis.h>
57 #include <typedefs.h>
58 #include <epictrl.h>
59 #include <irelay.h>
60 #include <proto/ethernet.h>
61 #include <nuiouser.h>
62 #include <bcmendian.h>
63 #include <oidencap.h>
64 #include <bcmutils.h>
65 #include <proto/802.11.h>
66 #endif /* WIN32 */
68 #include <bcmcdc.h>
69 #include <wlioctl.h>
70 #include <typedefs.h>
71 #include <bcmendian.h>
72 #include <bcmutils.h>
73 #if defined(RWL_WIFI) || defined(WIFI_REFLECTOR)
74 #include <rwl_wifi.h>
75 #endif /* defined(RWL_WIFI) || defined(WIFI_REFLECTOR) */
76 #include "wlu.h"
77 #include "wlu_remote.h"
78 #include "wlu_pipe.h"
79 #include "wlu_server_shared.h"
80 #ifdef RWLASD
81 extern int g_serv_sock_desc;
82 #endif
83 int g_rwl_hndle;
84 int set_ctrlc = 0;
86 #ifdef RWL_DONGLE
87 static rem_ioctl_t loc_cdc;
88 static const char* cmdname = "remote";
89 static const char* dongleset = "dongleset";
90 #endif
92 extern void store_old_interface(void *wl, char *old_intf_name);
93 extern int wl_check(void *wl);
95 extern void handle_ctrlc(int unused);
96 /* Function: rwl_transport_setup
97 * This will do the initialization for
98 * for all the transports
100 static int
101 rwl_transport_setup(int argc, char** argv)
103 int transport_descriptor = -1;
105 UNUSED_PARAMETER(argc);
106 UNUSED_PARAMETER(argv);
108 #ifdef RWL_SOCKET
109 /* This function will parse the socket command line arguments
110 * & open the socket in listen mode
112 remote_type = REMOTE_SOCKET;
113 transport_descriptor = rwl_init_server_socket_setup(argc, argv, remote_type);
115 if (transport_descriptor < 0) {
116 DPRINT_ERR(ERR, "wl_socket_server:Transport setup failed \n");
118 #endif /* RWL_SOCKET */
119 #if defined(RWL_DONGLE) || defined(RWL_WIFI) || defined(RWL_SERIAL)
120 g_rem_pkt_ptr = &g_rem_pkt;
121 transport_descriptor = 0;
123 #ifdef RWL_WIFI
124 remote_type = REMOTE_WIFI;
125 #endif
127 #ifdef RWL_DONGLE
128 remote_type = REMOTE_DONGLE;
129 #endif /* RWL_DONGLE */
130 #ifdef RWL_SERIAL
131 remote_type = REMOTE_SERIAL;
132 if (argc < 2) {
133 DPRINT_ERR(ERR, "Port name is required from the command line\n");
134 } else {
135 (void)*argv++;
136 DPRINT_DBG(OUTPUT, "Port name is %s\n", *argv);
137 transport_descriptor = *(int*) rwl_open_transport(remote_type, *argv, 0, 0);
139 #endif /* RWL_SERIAL */
140 #endif /* RWL_DONGLE ||RWL_SERIAL ||RWL_WIFI */
141 #ifdef RWLASD
142 g_serv_sock_desc = transport_descriptor;
143 #endif
144 return transport_descriptor;
148 /* Function: remote_rx_header
149 * This function will receive the CDC header from client
150 * for socket transport
151 * It will receive the command or ioctl from dongle driver for
152 * dongle UART serial transport and wifi transport.
153 * Arguments: wl - handle to driver
154 * : Des - Socket Descriptor to pass in AcceptConnection
155 * : g_rwl_hndle - Return socket handle that is used for transmission
156 * : and reception of data in case of socket
157 * In case of serial, it is just a return value
159 static int
160 remote_rx_header(void *wl, int trans_Des)
162 #ifdef RWL_SOCKET
163 struct sockaddr_in ClientAddress;
164 int SizeOfCliAdd;
165 SizeOfCliAdd = sizeof(ClientAddress);
167 UNUSED_PARAMETER(wl);
169 /* Get the socket handle g_rwl_hndle for transmission & reception */
170 if ((g_rwl_hndle = rwl_acceptconnection(trans_Des, (struct sockaddr*)&ClientAddress,
171 &SizeOfCliAdd)) == BCME_ERROR) {
172 return BCME_ERROR;
175 /* Get CDC header in order to determine buffer requirements */
176 if ((g_rem_ptr = remote_CDC_rx_hdr((void *)&g_rwl_hndle, 0)) == NULL) {
177 DPRINT_DBG(OUTPUT, "\n Waiting for client to transmit command\n");
178 return BCME_ERROR;
181 #endif /* RWL_SOCKET */
183 #ifdef RWL_DONGLE
184 void *pkt_ptr = NULL;
185 int error;
187 UNUSED_PARAMETER(trans_Des);
189 /* wl driver is polled after every 200 ms (POLLING_TIME) */
190 rwl_sleep(POLLING_TIME);
192 if ((error = rwl_var_getbuf(wl, cmdname, NULL, 0, &pkt_ptr)) < 0) {
193 DPRINT_ERR(ERR, "No packet in wl driver\r\n");
194 return BCME_ERROR;
197 DPRINT_DBG(OUTPUT, "Polling the wl driver, error status=%d\n", error);
199 if ((*(int *)pkt_ptr) == 0) {
200 DPRINT_DBG(ERR, "packet not received\n");
201 return BCME_ERROR;
204 DPRINT_DBG(OUTPUT, "packet received\n");
206 /* Extract CDC header in order to determine buffer requirements */
207 memcpy((char*)g_rem_pkt_ptr, (char*)pkt_ptr, sizeof(rem_packet_t));
208 g_rem_ptr = &(g_rem_pkt_ptr->rem_cdc);
210 #endif /* RWL_DONGLE */
212 #ifdef RWL_SERIAL
213 UNUSED_PARAMETER(wl);
214 UNUSED_PARAMETER(trans_Des);
215 if (g_rwl_hndle == -1) {
216 DPRINT_ERR(ERR, "failed to open com port.\r\n");
217 return BCME_ERROR;
220 if ((g_rem_ptr = remote_CDC_rx_hdr((void*)&g_rwl_hndle, 1)) == NULL) {
221 DPRINT_DBG(OUTPUT, "\n Waiting for client to transmit command\n");
222 return BCME_ERROR;
224 #endif /* RWL_SERIAL */
227 #ifdef RWL_WIFI
228 /* Poll the driver for the valid action frame and update the CDC + data */
229 dot11_action_wifi_vendor_specific_t *list;
231 UNUSED_PARAMETER(trans_Des);
233 if ((list = rwl_wifi_allocate_actionframe()) == NULL) {
234 DPRINT_DBG(OUTPUT, "remote_rx_header: Failed to allocate frame \n");
235 return BCME_ERROR;
238 if (remote_CDC_DATA_wifi_rx((void*)wl, list) < 0) {
239 free(list);
240 return BCME_ERROR;
243 /* copy the valid length of the data to the g_rem_pkt_ptr */
244 memcpy((char*)g_rem_pkt_ptr, (char*)&list->data[0], sizeof(rem_packet_t));
245 g_rem_ptr = &(g_rem_pkt_ptr->rem_cdc);
246 free(list);
247 #endif /* RWL_WIFI */
248 rwl_swap_header(g_rem_ptr, NETWORK_TO_HOST);
250 DPRINT_INFO(OUTPUT, "%d %d %d %d\r\n", g_rem_ptr->msg.cmd,
251 g_rem_ptr->msg.len, g_rem_ptr->msg.flags, g_rem_ptr->data_len);
253 return SUCCESS;
257 /* Function: remote_rx_data
258 * This function will receive the data from client
259 * for different transports
260 * In case of socket the data comes from a open TCP socket
261 * However in case of dongle UART or wi-fi the data is accessed
262 * from the driver buffers.
265 remote_rx_data(void* buf_ptr)
267 #if defined(RWL_SOCKET) || defined(RWL_SERIAL)
269 if ((remote_CDC_rx((void *)&g_rwl_hndle, g_rem_ptr, buf_ptr,
270 g_rem_ptr->msg.len, 0)) == BCME_ERROR) {
271 DPRINT_ERR(ERR, "Reading CDC %d data bytes failed\n", g_rem_ptr->msg.len);
272 return BCME_ERROR;
274 #elif defined(RWL_DONGLE) || defined(RWL_WIFI)
275 if (g_rem_ptr->data_len != 0) {
276 int length = g_rem_ptr->data_len;
277 if (g_rem_ptr->data_len > g_rem_ptr->msg.len) {
278 length = g_rem_ptr->msg.len;
280 memcpy(buf_ptr, g_rem_pkt_ptr->message, length);
282 else
283 buf_ptr = NULL;
284 #endif /* RWL_SOCKET || RWL_SERIAL */
285 return SUCCESS;
288 #ifdef RWL_DONGLE
290 * Function to send the serial response to wl driver
291 * The function calculates the no of frames based on the DATA_FRAME_LEN
292 * adds cdc header to every frame, copies the header and fragmented frame
293 * into rem_buf_ptr and sends the packet down to wl driver
296 static int
297 rwl_serial_fragmented_tx(void* wl, rem_ioctl_t *rem_ptr, uchar *buf_ptr, int error)
299 rem_ioctl_t *loc_ptr = &loc_cdc;
300 uchar* rem_buf_ptr;
301 uint noframes = 1; /* Default noframes = 1 */
302 uint count;
303 uint frame_count;
304 uint rem_bytes;
306 loc_ptr->msg.cmd = error;
307 loc_ptr->msg.flags = REMOTE_REPLY;
308 loc_ptr->msg.len = rem_ptr->msg.len;
309 loc_ptr->data_len = rem_ptr->data_len;
311 /* Fragment the result if it is more than DATA_FRAME_LEN (960) */
312 if (loc_ptr->msg.len > DATA_FRAME_LEN) {
313 /* Calculate no of frames */
314 noframes = (loc_ptr->msg.len)/DATA_FRAME_LEN;
315 if ((loc_ptr->msg.len) % DATA_FRAME_LEN > 0) {
316 noframes += 1;
317 rem_bytes = (loc_ptr->msg.len) % DATA_FRAME_LEN;
318 } else {
319 rem_bytes = DATA_FRAME_LEN;
321 } else {
322 rem_bytes = loc_ptr->msg.len;
324 DPRINT_INFO(OUTPUT, "No of frames = %d, rem_bytes:%d\n", noframes, rem_bytes);
325 count = 0;
326 frame_count = noframes;
327 rem_buf_ptr = (uchar*)malloc(DONGLE_TX_FRAME_SIZE + REMOTE_SIZE);
329 while (count < noframes) {
330 memset(rem_buf_ptr, 0, DONGLE_TX_FRAME_SIZE + REMOTE_SIZE);
331 /* Send reply to client */
332 rem_ptr->msg.cmd = loc_ptr->msg.cmd;
333 rem_ptr->msg.flags = loc_ptr->msg.flags;
334 rem_ptr->msg.len = loc_ptr->msg.len;
336 if (frame_count == 1)
337 rem_ptr->data_len = rem_bytes;
338 else
339 rem_ptr->data_len = DATA_FRAME_LEN;
341 DPRINT_DBG(OUTPUT, "GET--rem_ptr->data_len=%d\n", rem_ptr->data_len);
343 /* Copy CDC Header */
344 memcpy(rem_buf_ptr, (uchar*)rem_ptr, REMOTE_SIZE);
346 /* Copy Data now */
347 memcpy(&rem_buf_ptr[REMOTE_SIZE], &buf_ptr[count*DATA_FRAME_LEN],
348 rem_ptr->data_len);
349 count++;
350 frame_count--;
352 DPRINT_INFO(OUTPUT, "FRAME %d\n", count);
353 DPRINT_INFO(OUTPUT, "%d %d %d %d\n", rem_ptr->msg.cmd, rem_ptr->msg.len,
354 rem_ptr->msg.flags, rem_ptr->data_len);
356 rwl_sync_delay(noframes);
358 if ((error = rwl_var_setbuf(wl, cmdname, rem_buf_ptr,
359 DONGLE_TX_FRAME_SIZE+REMOTE_SIZE)) < 0) {
360 DPRINT_INFO(OUTPUT, "Unable to send to wl driver,error=%d\n", error);
361 if (rem_buf_ptr)
362 free(rem_buf_ptr);
363 return BCME_ERROR;
365 else
366 DPRINT_INFO(OUTPUT, "Packet sent to wl driver,error=%d\n", error);
369 if (rem_buf_ptr)
370 free(rem_buf_ptr);
372 return error;
375 /* This function transmits the response to the dongle driver in the case
376 * of serial dongle transport.
377 * In the case of big response, it calls the rwl_serial_fragmented_response
378 * function to fragment the response and sends down to the driver.
381 static int
382 remote_CDC_dongle_tx(void *wl, uint cmd, uchar *buf, uint buf_len, uint data_len, uint flags)
384 int error;
385 rem_ioctl_t resp_rem_cdc;
387 if (flags & REMOTE_SET_IOCTL) {
388 uchar* rem_buf_ptr;
389 /* for set commands message length and data length should be set to zero
390 * unlike Get Ioctl which will have valid data and message length
392 resp_rem_cdc.msg.len = 0;
393 resp_rem_cdc.data_len = 0;
394 resp_rem_cdc.msg.cmd = cmd;
395 resp_rem_cdc.msg.flags = REMOTE_REPLY;
397 DPRINT_INFO(OUTPUT, "Set:Resp packet:%d %d %d %d\n", resp_rem_cdc.msg.cmd,
398 resp_rem_cdc.msg.len, resp_rem_cdc.msg.flags, resp_rem_cdc.data_len);
400 if ((rem_buf_ptr = (uchar*)malloc(DONGLE_TX_FRAME_SIZE + REMOTE_SIZE)) == NULL) {
401 DPRINT_ERR(ERR, "malloc failed for remote_CDC_dongle_tx\n");
402 return BCME_ERROR;
405 /* Send reply to client here */
406 memcpy(rem_buf_ptr, (char*)(&resp_rem_cdc), REMOTE_SIZE);
407 if ((error = rwl_var_setbuf((void*)wl, cmdname, rem_buf_ptr,
408 DONGLE_TX_FRAME_SIZE + REMOTE_SIZE)) < 0) {
409 DPRINT_ERR(ERR, "unable to send SET results to driver=%d\n", error);
410 } else
411 DPRINT_INFO(OUTPUT, "Packet sent to wl driver, error=%d\n", error);
413 if (rem_buf_ptr)
414 free(rem_buf_ptr);
416 } else { /* GET_IOCTL */
417 resp_rem_cdc.msg.cmd = cmd;
418 resp_rem_cdc.msg.len = buf_len;
419 resp_rem_cdc.msg.flags = flags;
420 resp_rem_cdc.data_len = data_len;
421 if ((error = rwl_serial_fragmented_tx(wl, &resp_rem_cdc, buf, cmd)) < 0)
422 DPRINT_ERR(ERR, "wl_server_serial: Return error code failed\n");
424 return error;
426 #endif /* RWL_DONGLE */
428 /* This function gets the command send by the client from the dongle driver */
430 rwl_var_getbuf(void* wl, const char* iovar, void* param, int param_len, void** buf_ptr)
432 int len;
434 memset(rwl_buf, 0, WLC_IOCTL_MAXLEN);
435 strcpy((char*)rwl_buf, iovar);
436 /* include the null */
437 len = strlen(iovar) + 1;
439 if (param_len)
440 memcpy(&rwl_buf[len], param, param_len);
442 *buf_ptr = rwl_buf;
444 return wl_get(wl, WLC_GET_VAR, &rwl_buf[0], WLC_IOCTL_MAXLEN);
447 /* This function will send the buffer to the dongle driver */
449 rwl_var_setbuf(void* wl, const char* iovar, void* param, int param_len)
451 int len;
453 memset(rwl_buf, 0, WLC_IOCTL_MAXLEN);
454 strcpy((char*)rwl_buf, iovar);
456 /* include the null */
457 len = strlen(iovar) + 1;
459 if (param_len)
460 memcpy(&rwl_buf[len], param, param_len);
462 len += param_len;
464 DPRINT_DBG(OUTPUT, "setbuf:%s, len:%d\n", rwl_buf, len);
466 return wl_set(wl, WLC_SET_VAR, &rwl_buf[0], len);
469 /* This function will send the buffer to the dongle driver */
471 rwl_var_send_vs_actionframe(void* wl, const char* iovar, void* param, int param_len)
473 int len;
475 memset(rwl_buf, 0, WLC_IOCTL_MAXLEN);
476 strcpy((char*) rwl_buf, iovar);
478 /* include the null */
479 len = strlen(iovar) + 1;
481 if (param_len)
482 memcpy((void*)&rwl_buf[len+ OFFSETOF(wl_action_frame_t, data)], param, param_len);
484 /* Set the PacketID (not used by remote WL */
485 memset((void*)&rwl_buf[len + OFFSETOF(wl_action_frame_t, packetId)], 0, 4);
487 /* Set the dest addr */
488 memcpy((void*)&rwl_buf[len + OFFSETOF(wl_action_frame_t, da)],
489 (void*)&rwlea,
490 ETHER_ADDR_LEN);
492 /* set the length */
493 memcpy((void*)&rwl_buf[len + OFFSETOF(wl_action_frame_t, len)], (void*) &param_len, 2);
495 len += param_len + ETHER_ADDR_LEN + 2 + 4;
497 DPRINT_DBG(OUTPUT, "setbuf:%s, len:%d\n", rwl_buf, len);
499 return wl_set(wl, WLC_SET_VAR, &rwl_buf[0], len);
502 * This function is used for transmitting the response over different
503 * transports.
504 * In case of socket the data is directly sent to the client which is waiting on a open socket.
505 * In case of socket the data is sent in one big chunk unlike other transports
507 * In case of serial the data is sent to the driver using remote_CDC_dongle_tx function
508 * which in turn may fragment the data and send it in chunks to the client.
510 * In case of wi-fi the data is sent to the driver using the remote_CDC_tx. However
511 * in this case the data is converted into 802.11 Action frames and sent using wi-fi driver.
512 * Arguments: wl - Driver handle
513 * hndle - Socket handle for socket transport.
516 remote_tx_response(void *wl, void* buf_ptr, int cmd)
518 int error = -1;
520 #if defined(RWL_SOCKET) || defined(RWL_SERIAL)
521 UNUSED_PARAMETER(wl);
522 if ((error = remote_CDC_tx((void*)&g_rwl_hndle, cmd, buf_ptr, g_rem_ptr->msg.len,
523 g_rem_ptr->msg.len, REMOTE_REPLY, 0)) < 0)
524 DPRINT_ERR(ERR, "wl_server: Return results failed\n");
525 #endif /* RWL_SOCKET || RWL_SERIAL */
527 #ifdef RWL_DONGLE
528 if ((error = remote_CDC_dongle_tx(wl, cmd, buf_ptr, g_rem_ptr->msg.len,
529 g_rem_ptr->data_len, g_rem_ptr->msg.flags)) < 0)
530 DPRINT_ERR(ERR, "wl_server: Return results failed\n");
531 #endif /* RWL_DONGLE */
533 #ifdef RWL_WIFI
534 /* Purge all the queued cmd's , this to ensure late response time out at */
535 /* client side and client might issue the next cmd if server is slow */
536 rwl_wifi_purge_actionframes(wl);
537 if ((g_rem_ptr->msg.flags & REMOTE_SHELL_CMD) ||
538 (g_rem_ptr->msg.flags & REMOTE_GET_IOCTL)||
539 (g_rem_ptr->msg.flags & REMOTE_ASD_CMD) ||
540 (g_rem_ptr->msg.flags & REMOTE_VISTA_CMD)) {
541 if ((error = remote_CDC_tx(wl, cmd, buf_ptr, g_rem_ptr->msg.len,
542 g_rem_ptr->msg.len, REMOTE_REPLY, 0)) < 0)
543 DPRINT_ERR(ERR, "wl_wifi_server_ce: Return results failed\n");
544 } else {
545 if ((error = remote_CDC_tx(wl, cmd, buf_ptr, 0, 0, REMOTE_REPLY, 0)) < 0)
546 DPRINT_ERR(ERR, "wl_wifi_server_ce: Return results failed\n");
548 #endif /* RWL_WIFI */
549 return error;
552 /* Close the Socket handle */
553 void close_sock_handle(int hndle)
555 #ifdef RWL_SOCKET
556 rwl_close_pipe(remote_type, (void*)&hndle);
557 #else
558 UNUSED_PARAMETER(hndle);
559 #endif
564 * Send the response to the remote if the channel of the server matches with the
565 * server channel.
567 void remote_wifi_response(void* wl)
569 #ifdef RWL_WIFI
570 dot11_action_wifi_vendor_specific_t *list;
572 if ((list = rwl_wifi_allocate_actionframe()) == NULL) {
573 DPRINT_DBG(OUTPUT, "remote_wifi_response: Failed to allocate frame \n");
574 return;
577 /* it's sync frame and received from client */
578 memcpy((char*)&list->data[RWL_WIFI_CDC_HEADER_OFFSET],
579 &g_rem_pkt_ptr[RWL_WIFI_CDC_HEADER_OFFSET], REMOTE_SIZE);
580 memcpy((char*)&list->data[REMOTE_SIZE], g_rem_pkt_ptr->message,
581 RWL_WIFI_FRAG_DATA_SIZE);
582 list->type = RWL_WIFI_FIND_MY_PEER;
583 /* Store the client mac addr */
584 memcpy((void*)&rwlea, (void*)&list->data[RWL_DUT_MAC_ADDRESS_OFFSET], ETHER_ADDR_LEN);
585 /* send the response to client if server is on the same channel */
586 rwl_wifi_find_server_response(wl, list);
588 free(list);
589 #else
590 UNUSED_PARAMETER(wl);
591 #endif /* RWL_WIFI */
592 return;
595 /* Function to check IN-dongle mode firmware */
597 rwl_iovar_check(void *wl)
599 void *ptr;
600 #ifdef RWL_WIFI
601 dot11_action_wifi_vendor_specific_t rec_frame;
603 /* Check for indongle mode firmware */
604 return rwl_var_getbuf(wl, RWL_WIFI_GET_ACTION_CMD, &rec_frame,
605 RWL_WIFI_ACTION_FRAME_SIZE, &ptr);
606 #endif
607 UNUSED_PARAMETER(ptr);
608 UNUSED_PARAMETER(wl);
609 #ifdef RWL_DONGLE
610 return rwl_var_getbuf(wl, "remote", NULL, 0, &ptr);
611 #endif
612 return 0;
615 /* Function to get a ctrl-c packet */
617 get_ctrlc_header(void *wl)
619 #if defined(RWL_SOCKET) || defined(RWL_SERIAL)
620 fd_set fdset;
621 struct timeval tv;
622 UNUSED_PARAMETER(wl);
623 FD_ZERO(&fdset);
624 FD_SET((unsigned)g_rwl_hndle, &fdset);
625 tv.tv_sec = 0;
626 tv.tv_usec = 0;
627 if ((select(g_rwl_hndle+1, &fdset, NULL, NULL, &tv)) > 0) {
628 if (FD_ISSET(g_rwl_hndle, &fdset)) {
629 remote_CDC_rx_hdr((void *)&g_rwl_hndle, 0);
630 return BCME_OK;
633 return BCME_ERROR;
635 #else
636 return remote_rx_header(wl, 0);
637 #endif /* if defined(RWL_SOCKET) || defined(RWL_SERIAL) */
640 /* Main server module common for all transports
641 * This module will do the initial transport setups.
642 * Then it receives the command from client in CDC format
643 * and transmits the response back to the client.
644 * In the case of socket, it receives the command from the client
645 * and sends the response directly to the client via TCP socket.
647 * In the case of serial & wifi , it receives the command from the driver
648 * and sends the response to the driver.
651 remote_server_exec(int argc, char **argv, void *wl)
653 int err;
654 int transport_descriptor;
655 char *async_cmd_flag;
656 char old_intf_name[IFNAMSIZ];
657 #ifdef WIN32
658 char shell_fname[MAX_SHELL_FILE_LENGTH];
659 DWORD dwlen;
660 #endif
661 #ifdef RWL_DONGLE
662 int uart_enable = 1;
663 /* To set dongle flag when dongle server starts */
664 if ((err = rwl_var_setbuf(wl, dongleset, &uart_enable,
665 sizeof(int))) < 0) {
666 DPRINT_INFO(OUTPUT, "Unable to send to wl driver,error=%d\n", err);
668 #endif
669 if (rwl_iovar_check (wl) < 0) {
670 DPRINT_ERR(ERR, "wl_server: RWL_WIFI/RWL_DONGLE not defined ");
671 DPRINT_ERR(ERR, "Or In-Dongle mode enabled\n");
672 exit(0);
674 /* Initialise for all the transports - socket, serial, and wifi
675 * In Socket transport, main socket handler will be returned.
677 if ((transport_descriptor = rwl_transport_setup(argc, argv)) < 0)
678 return BCME_ERROR;
680 #ifdef RWL_WIFI
681 remote_wifi_ser_init_cmds(wl);
682 #endif
683 /* Create a directory /tmp/RWL for the shell response files */
684 if (rwl_create_dir() < 0)
685 return BCME_ERROR;
688 #ifdef RWLASD
689 /* DUT initialization function */
690 wfa_dut_init(&trafficBuf, &respBuf, &parmsVal, &xcCmdBuf, &toutvalp);
691 #endif
693 /* Copy old interface name to restore it */
694 store_old_interface(wl, old_intf_name);
696 while (1) {
697 uchar *buf_ptr = NULL;
698 #ifdef VISTA_SERVER
699 int index;
700 char *vista_buf[MAX_VISTA_ARGC];
701 #endif
702 #ifdef RWL_SERIAL
703 g_rwl_hndle = transport_descriptor;
704 #else
705 g_rwl_hndle = -1;
706 #endif
707 #ifdef RWL_DONGLE
708 if (set_ctrlc) {
709 uart_enable = 0;
710 if ((err = rwl_var_setbuf(wl, dongleset, &uart_enable,
711 sizeof(int))) < 0) {
712 DPRINT_INFO(OUTPUT, "Unable to send to wl driver,error=%d\n", err);
714 set_ctrlc = 0;
715 exit(0);
717 #endif /* RWL_DONGLE */
719 /* Receive the CDC header */
720 if ((remote_rx_header(wl, transport_descriptor)) == BCME_ERROR) {
721 DPRINT_DBG(OUTPUT, "\n Waiting for client to transmit command\n");
722 continue;
725 DPRINT_INFO(OUTPUT, "REC : cmd %d\t msg len %d msg flag %d\t msg status %d\n",
726 g_rem_ptr->msg.cmd, g_rem_ptr->msg.len,
727 g_rem_ptr->msg.flags, g_rem_ptr->msg.status);
729 #ifdef RWL_WIFI
730 /* send the response to remote if it is findserver cmd, this is specific to wifi */
731 if (g_rem_ptr->msg.flags & REMOTE_FINDSERVER_IOCTL) {
732 remote_wifi_response(wl);
733 continue;
735 #endif /* RWL_WIFI */
738 * Allocate buffer only if there is a response message expected.
739 * Some commands such as up/down do not output anything.
741 if (g_rem_ptr->msg.len) {
742 if ((buf_ptr = malloc(g_rem_ptr->msg.len)) == NULL) {
743 DPRINT_ERR(ERR, "malloc of %d bytes failed\n", g_rem_ptr->msg.len);
744 continue;
748 /* Receive the data */
749 if ((err = remote_rx_data(buf_ptr)) == BCME_ERROR) {
750 if (buf_ptr)
751 free(buf_ptr);
752 continue;
755 /* Process command */
756 if (g_rem_ptr->msg.flags & REMOTE_SHELL_CMD) {
757 /* Get the response length first and get the response buffer in case of
758 * synchronous shell commands and the buf_ptr will have the response file
759 * name. In case of asynchronous shell commands, buf_ptr
760 * will be get updated by the remote_shell_execute function.
762 need_speedy_response = 1;
763 #ifndef WIN32
764 if (buf_ptr) {
765 async_cmd_flag = strstr((char*)buf_ptr, "%");
767 if ((err = remote_shell_execute((char*)buf_ptr, wl)) > 0) {
768 if (async_cmd_flag)
769 g_rem_ptr->msg.len = err;
771 /* Sync shell command: No need to send response from here */
772 else {
773 #ifdef RWL_SOCKET
774 /* Transmitted to client. Then close the handle &
775 * get the new handle for next transmission & reception.
777 close_sock_handle(g_rwl_hndle);
778 #endif /* RWL_SOCKET */
779 continue;
781 #else
782 if ((err = remote_shell_execute((char*)buf_ptr, wl)) != SUCCESS) {
783 DPRINT_ERR(ERR, "Error in executing shell command\n");
784 if (buf_ptr)
785 free(buf_ptr);
786 #ifdef RWL_SOCKET
787 /* Transmitted to client. Then close the handle &
788 * get the new handle for next transmission & reception.
790 close_sock_handle(g_rwl_hndle);
791 #endif /* RWL_SOCKET */
792 continue;
794 /* Get the response from the temporary file */
795 if ((err = remote_shell_get_resp(shell_fname, wl)) != SUCCESS) {
796 DPRINT_ERR(ERR, "Error in executing shell command\n");
798 if (buf_ptr)
799 free(buf_ptr);
800 #ifdef RWL_SOCKET
801 /* Transmitted to client. Then close the handle &
802 * get the new handle for next transmission & reception.
804 close_sock_handle(g_rwl_hndle);
805 #endif /* RWL_SOCKET */
806 continue;
807 #endif /* WIN32 */
808 } /* REMOTE_SHELL_CMD */
810 #ifdef RWLASD
811 if (g_rem_ptr->msg.flags & REMOTE_ASD_CMD) {
812 if ((err = remote_asd_exec(buf_ptr, (int *)&g_rem_ptr->msg.len)) < 0) {
813 DPRINT_ERR(ERR, "Error in executing asd command\n");
815 } /* REMOTE_ASD_CMD */
816 #endif
819 * added to take care of OID base problem for cross OS RWL cleint server
820 * In case of LX Server and WIN32 client OID base need to be removed
821 * In case of WIN32 server and LX client OID base need to be added
823 if (g_rem_ptr->msg.cmd > MAX_IOVAR)
824 g_rem_ptr->msg.cmd -= WL_OID_BASE;
825 #if defined(WIN32)
826 if (g_rem_ptr->msg.cmd < MAX_IOVAR)
827 g_rem_ptr->msg.cmd += WL_OID_BASE;
828 #endif
829 #ifdef VISTA_SERVER
830 if (g_rem_ptr->msg.flags & REMOTE_VISTA_CMD) {
831 vista_buf[0] = strtok(buf_ptr, " \t\n");
832 for (index = 1; (vista_buf[index] = strtok(NULL, " \t\n")) != NULL;
833 index++);
834 if ((err = remote_vista_exec(wl, vista_buf)) < 0) {
835 DPRINT_ERR(ERR, "Error in executing vista command\n");
837 memcpy(buf_ptr, vista_buf[0], strlen(vista_buf[0]));
838 g_rem_ptr->msg.len = strlen(vista_buf[0]);
839 } /* REMOTE_VISTA_CMD */
840 #endif /* VISTA_SERVER */
842 #ifndef RWL_DONGLE
843 if (g_rem_ptr->msg.flags & REMOTE_GET_IOCTL ||
844 g_rem_ptr->msg.flags & REMOTE_SET_IOCTL) {
845 if (strlen(g_rem_ptr->intf_name) != 0) {
846 struct ifreq ifr;
847 /* validate the interface */
848 memset(&ifr, 0, sizeof(ifr));
849 if (g_rem_ptr->intf_name)
850 strncpy(ifr.ifr_name, g_rem_ptr->intf_name, IFNAMSIZ);
852 if (wl_check((void *)&ifr)) {
853 DPRINT_ERR(ERR, "%s: wl driver adapter not found\n",
854 g_rem_ptr->intf_name);
855 /* Signal end of command output */
856 g_rem_ptr->msg.len = 0;
857 remote_tx_response(wl, NULL, BCME_NODEVICE);
858 if (buf_ptr)
859 free(buf_ptr);
861 #ifdef RWL_SOCKET
862 close_sock_handle(g_rwl_hndle);
863 #endif /* RWL_SOCKET */
864 continue;
867 if (set_interface(wl, g_rem_ptr->intf_name) == BCME_OK)
868 DPRINT_DBG(OUTPUT, "\n %s Interface will be used \n",
869 (char *)wl);
872 #endif /* ifndef RWL_DONGLE */
873 if (g_rem_ptr->msg.flags & REMOTE_SET_IOCTL ||
874 g_rem_ptr->msg.flags & RDHD_SET_IOCTL) {
875 #ifdef WIN32
876 #if defined(RWL_DONGLE) || defined(RWL_WIFI)
877 /* For commands with msg length as zero initialize the buffer to null */
878 if (g_rem_ptr->msg.len == 0)
879 buf_ptr = NULL;
880 #endif
881 #else
882 if (g_rem_ptr->msg.len == 0)
883 buf_ptr = NULL;
884 #endif /* WIN32 */
886 if (g_rem_ptr->msg.flags & REMOTE_SET_IOCTL) {
887 err = wl_ioctl(wl, g_rem_ptr->msg.cmd,
888 (void *)buf_ptr, g_rem_ptr->msg.len, TRUE);
890 if (err == IOCTL_ERROR) {
891 DPRINT_ERR(ERR, "Error in executing wl_ioctl\n");
892 DPRINT_ERR(ERR, "Setting Default Interface1 \n");
893 set_interface(wl, old_intf_name);
896 if (g_rem_ptr->msg.flags & RDHD_SET_IOCTL) {
897 err = dhd_ioctl(wl, g_rem_ptr->msg.cmd,
898 (void *)buf_ptr, g_rem_ptr->msg.len, TRUE);
901 g_rem_ptr->msg.flags = REMOTE_SET_IOCTL;
903 } /* RDHD/REMOTE_SET_IOCTL */
905 if (g_rem_ptr->msg.flags & REMOTE_GET_IOCTL ||
906 g_rem_ptr->msg.flags & RDHD_GET_IOCTL) {
907 if (g_rem_ptr->msg.cmd == WLC_GET_VAR && buf_ptr &&
908 strncmp((const char *)buf_ptr, "exit", g_rem_ptr->msg.len) == 0) {
909 /* exit command from remote client terminates server */
910 free(buf_ptr);
911 break;
913 if (g_rem_ptr->msg.flags & REMOTE_GET_IOCTL)
914 err = wl_ioctl(wl, g_rem_ptr->msg.cmd, (void *)buf_ptr,
915 g_rem_ptr->msg.len, FALSE);
916 if (err == IOCTL_ERROR) {
917 DPRINT_ERR(ERR, "REMOTE_GET_IOCTL::Error in executing wl_ioctl\n");
918 DPRINT_ERR(ERR, "Setting Default Interface \n");
919 set_interface(wl, old_intf_name);
922 if (g_rem_ptr->msg.flags & RDHD_GET_IOCTL)
923 err = dhd_ioctl(wl, g_rem_ptr->msg.cmd, (void *)buf_ptr,
924 g_rem_ptr->msg.len, FALSE);
925 g_rem_ptr->msg.flags = REMOTE_GET_IOCTL;
926 } /* REMOTE_GET_IOCTL */
927 DPRINT_INFO(OUTPUT, "RESP : cmd %d\t msg len %d\n",
928 g_rem_ptr->msg.cmd, g_rem_ptr->msg.len);
929 /* setting back default interface */
930 set_interface(wl, old_intf_name);
931 /* Transmit the response results */
932 if (remote_tx_response(wl, buf_ptr, err) < 0) {
933 DPRINT_ERR(ERR, "\nReturn results failed\n");
936 #ifdef RWL_SOCKET
937 if (g_rem_ptr->msg.flags != REMOTE_SHELL_CMD)
938 /* Transmitted to client. Then close the handle & get the new handle
939 * for next transmission & reception. In case of shell commands this
940 * should be closed in respective shellproc files.
942 close_sock_handle(g_rwl_hndle);
943 #endif /* RWL_SOCKET */
945 if (buf_ptr) {
946 free(buf_ptr);
948 } /* end of while */
949 #if defined(RWL_SOCKET)
950 /* Close the main handle for socket */
951 close_sock_handle(transport_descriptor);
952 #elif defined(RWL_SERIAL)
953 /* Close the main handle for serial pipe */
954 rwl_close_pipe(remote_type, (void*)&transport_descriptor);
955 #endif
957 #ifdef RWLASD
958 wfa_dut_deinit();
959 #endif
961 return err;