K2.6 patches and update.
[tomato.git] / release / src-rt / wl / exe / wlu_client_shared.c
blob7efe68716a273a9abfb78bb25fd0625563360ee8
1 /*
2 * Common code for remotewl client
4 * Copyright (C) 2010, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
8 * the contents of this file may not be disclosed to third parties, copied
9 * or duplicated in any form, in whole or in part, without the prior
10 * written permission of Broadcom Corporation.
12 * $Id: wlu_client_shared.c,v 1.32 2010-01-30 06:03:24 Exp $
14 #ifdef WIN32
15 #define NEED_IR_TYPES
17 #include <winsock2.h>
18 #include <windows.h>
19 #include <ntddndis.h>
20 #include <epictrl.h>
21 #include <irelay.h>
22 #include <winioctl.h>
23 #include <nuiouser.h>
24 #else /* LINUX */
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <arpa/inet.h>
28 #include <sys/ioctl.h>
29 #include <sys/time.h>
30 #include <net/if.h>
31 #include <unistd.h>
32 #endif /* WIN32 */
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <malloc.h>
36 #include <assert.h>
37 #include <ctype.h>
38 #include <string.h>
39 #include <typedefs.h>
40 #include <wlioctl.h>
41 #include <proto/ethernet.h>
42 #include <bcmendian.h>
43 #include <bcmutils.h>
44 #include <bcmcdc.h>
45 #include <proto/802.11.h>
46 #ifndef UNDER_CE
47 #include <signal.h>
48 #endif
49 #if defined(RWL_WIFI) || defined(WIFI_REFLECTOR)
50 #include <rwl_wifi.h>
51 #endif /* defined(RWL_WIFI) || defined(WIFI_REFLECTOR) */
52 #include "wlu.h"
53 #include "wlu_remote.h"
54 #include "wlu_pipe.h"
55 #include "wlu_client_shared.h"
57 char* remote_vista_cmds[] = {"join", "sup_wpa", "wsec", "set_pmk", "legacylink", "list",
58 "disassoc", "xlist", NULL};
59 int vista_cmd_index;
60 #define SHELL_CMD_LEN (256)
62 #ifdef RWL_SOCKET
63 extern int validate_server_address();
64 static int rwl_socket_shellresp(void *wl, rem_ioctl_t *rem_ptr, uchar *input_buf);
65 #endif
66 static int rwl_dongle_shellresp(void *wl, rem_ioctl_t *rem_ptr, uchar *input_buf, int cmd);
67 #ifdef RWL_WIFI
68 static int rwl_wifi_shellresp(void *wl, rem_ioctl_t *rem_ptr, uchar *input_buf);
69 #endif
70 /* We don't want the server to allocate bigger buffers for some of the commands
71 * like scanresults. Server can still allocate 8K memory and send the response
72 * in fragments. This is used in case of Get commands only.
74 #define SERVER_RESPONSE_MAX_BUF_LEN 8192
76 extern unsigned short g_rwl_servport;
77 extern char *g_rwl_servIP;
78 int g_child_pid;
79 #ifdef RWL_WIFI
80 /* dword align allocation */
81 static union {
82 char bufdata[WLC_IOCTL_MAXLEN];
83 uint32 alignme;
84 } bufstruct_wlu;
85 static char *g_rwl_aligned_buf = (char*) &bufstruct_wlu.bufdata;
87 extern char *g_rwl_buf_mac;
88 #endif
89 #ifdef RWL_SOCKET
90 /* Make initial connection from client to server through sockets */
91 static int
92 rwl_connect_socket_server(void)
94 int SockDes = -1;
95 struct sockaddr_in servAddr;
96 memset(&servAddr, 0, sizeof(servAddr));
97 if ((SockDes = (*(int *)rwl_open_pipe(remote_type, "\0", 0, 0))) == FAIL)
98 return FAIL;
99 if (!validate_server_address())
100 return FAIL;
101 DPRINT_DBG(OUTPUT, "ServerIP:%s,ServerPort:%d\n", g_rwl_servIP, g_rwl_servport);
102 servAddr.sin_family = AF_INET;
103 servAddr.sin_port = hton16(g_rwl_servport);
104 servAddr.sin_addr.s_addr = inet_addr(g_rwl_servIP);
106 if (rwl_sockconnect(SockDes, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0) {
107 rwl_close_pipe(remote_type, (void*) &SockDes);
108 return FAIL;
110 return SockDes;
113 /* This routine is used for both Get and Set Ioctls for the socket */
114 static int
115 rwl_information_socket(void *wl, int cmd, void* input_buf, unsigned long *input_len,
116 unsigned long *tx_len, uint flags)
118 int error, Sockfd;
119 rem_ioctl_t *rem_ptr = NULL;
121 if ((Sockfd = rwl_connect_socket_server()) < 0) {
122 DPRINT_ERR(ERR, "Error in getting the Socket Descriptor\n");
123 return FAIL;
125 wl = (void *)(&Sockfd);
127 if (remote_CDC_tx(wl, cmd, input_buf, *input_len,
128 *tx_len, flags, 0) < 0) {
129 DPRINT_ERR(ERR, "query_info_fe: Send command failed\n");
130 rwl_close_pipe(remote_type, wl);
131 return FAIL;
134 if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
135 DPRINT_ERR(ERR, "query_info_fe: Reading CDC header failed\n");
136 rwl_close_pipe(remote_type, wl);
137 return FAIL;
139 rwl_swap_header(rem_ptr, NETWORK_TO_HOST);
141 if (rem_ptr->msg.len > *input_len) {
142 DPRINT_ERR(ERR, "query_info_fe: needed size(%d) > "
143 "actual size(%ld)\n", rem_ptr->msg.len, *input_len);
144 rwl_close_pipe(remote_type, wl);
145 return FAIL;
148 if (remote_CDC_rx(wl, rem_ptr, input_buf, *input_len, 0) == FAIL) {
149 DPRINT_ERR(ERR, "query_info_fe: No results!\n");
150 rwl_close_pipe(remote_type, wl);
151 return FAIL;
154 if (rem_ptr->msg.flags & REMOTE_REPLY)
155 error = rem_ptr->msg.cmd;
156 else
157 error = 0;
159 rwl_close_pipe(remote_type, wl);
161 return error;
163 #endif /* RWL_SOCKET */
165 * Receives the fragmented response from serial server.
166 * Called from rwl_queryinformation_fe front end function for dongle case only when
167 * the client expects data in chunks more than DATA_FRAME_LEN * (960) bytes.
169 static int
170 rwl_serial_fragmented_response_fe(void *wl, rem_ioctl_t *rem_ptr, void* input_buf,
171 unsigned long *bytes_to_read)
173 int error;
174 uint32 total_numread;
175 uchar *local_buf, *local_result;
176 uint frames_to_read, frame_count;
178 DPRINT_DBG(OUTPUT, "rem_ptr->msg.len=%d \t rem_ptr->data_len=%d\n",
179 rem_ptr->msg.len, rem_ptr->data_len);
181 /* Calculate the number of frames for the response */
182 if (rem_ptr->data_len == 0) {
183 DPRINT_ERR(ERR, "data_len is:%d\n", rem_ptr->data_len);
184 return (FAIL);
186 frames_to_read = (*bytes_to_read)/rem_ptr->data_len;
187 if ((*bytes_to_read) % rem_ptr->data_len > 0)
188 frames_to_read += 1;
190 DPRINT_DBG(OUTPUT, "No of frames=%d\n", frames_to_read);
192 if ((local_result = (uchar*)malloc(rem_ptr->msg.len)) == NULL) {
193 DPRINT_ERR(ERR, "Malloc failed for serial fragmented frame"
194 "local result \n");
195 return FAIL;
198 /* Response will come in DATA_FRAME_LEN + REMOTE_SIZE (960+16) bytes
199 * packet with CDC header and then followed by response.
201 total_numread = 0;
202 frame_count = 0;
203 while (total_numread != *bytes_to_read) {
204 local_buf = (uchar*)malloc(rem_ptr->data_len);
205 if (local_buf == NULL) {
206 free(local_result);
207 return FAIL;
210 DPRINT_DBG(OUTPUT, "Total bytes=%d\n", total_numread);
211 DPRINT_DBG(OUTPUT, "Frame (Reverse):%d\n", frames_to_read);
213 if (remote_CDC_rx(wl, rem_ptr, local_buf, rem_ptr->data_len, 0) == -1) {
214 free(local_buf);
215 free(local_result);
216 return FAIL;
219 /* Concatenate the response to loc_res. */
220 memcpy(&local_result[frame_count*DATA_FRAME_LEN], local_buf,
221 rem_ptr->data_len);
223 total_numread += rem_ptr->data_len;
224 frame_count++;
225 frames_to_read--;
227 DPRINT_DBG(OUTPUT, "Total bytes=%d\n", total_numread);
229 if (frames_to_read == 0) {
230 /* When all the frames are received copy the data to original buf */
231 memcpy(input_buf, local_result, total_numread);
232 if (rem_ptr->msg.flags & REMOTE_REPLY) {
233 error = rem_ptr->msg.cmd;
237 if (total_numread != *bytes_to_read) {
238 /* Receive the next header */
239 if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
240 DPRINT_ERR(ERR, "query_info_fe: Reading CDC header failed");
243 free(local_buf);
245 free(local_result);
246 return error;
249 /* This routine is common to both set and Get Ioctls for the dongle case */
250 static int
251 rwl_information_dongle(void *wl, int cmd, void* input_buf, unsigned long *input_len,
252 uint tx_len, uint flags)
254 int error;
255 rem_ioctl_t *rem_ptr = NULL;
257 if (remote_CDC_tx(wl, cmd, input_buf, *input_len,
258 tx_len, flags, 0) < 0) {
259 DPRINT_ERR(ERR, "query_info_fe: Send command failed\n");
260 return FAIL;
263 /* Get the header */
264 if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
265 DPRINT_ERR(ERR, "query_info_fe: Reading CDC header failed\n");
266 return SERIAL_PORT_ERR;
269 /* Make sure there is enough room */
270 if (rem_ptr->msg.len > *input_len) {
271 DPRINT_DBG(OUTPUT, "query_info_fe: needed size(%d) > actual"
272 "size(%ld)\n", rem_ptr->msg.len, *input_len);
273 return FAIL;
276 /* We can grab short frames all at once. Longer frames (> 960 bytes)
277 * come in fragments.
279 if (rem_ptr->data_len < DATA_FRAME_LEN) {
280 if (remote_CDC_rx(wl, rem_ptr, input_buf, *input_len, 0) == FAIL) {
281 DPRINT_ERR(ERR, "query_info_fe: No results!\n");
282 return FAIL;
284 if (rem_ptr->msg.flags & REMOTE_REPLY)
285 error = rem_ptr->msg.cmd;
286 else
287 error = 0;
288 } else {
289 /* rwl_serial_fragmented_response_fe returns either valid number or FAIL.
290 * In any case return the same value to caller
292 error = rwl_serial_fragmented_response_fe(wl, rem_ptr, input_buf, input_len);
294 return error;
296 /* Handler to signal the reader thread that ctrl-C is pressed */
297 #ifndef UNDER_CE
298 volatile sig_atomic_t g_sig_ctrlc = 1;
299 void ctrlc_handler(int num)
301 UNUSED_PARAMETER(num);
302 g_sig_ctrlc = 0;
304 #else
305 int g_sig_ctrlc = 1;
306 #endif
308 /* Issue shell commands independent of transport type and return result */
309 static int
310 rwl_shell_information_fe(void *wl, int cmd, uchar* input_buf, unsigned long *input_len)
312 int error, remote_cmd;
313 uchar* resp_buf = NULL;
314 rem_ioctl_t *rem_ptr = NULL;
316 #ifdef RWL_WIFI
317 char *cbuf, retry;
318 dot11_action_wifi_vendor_specific_t *list;
319 #endif
321 #ifdef RWL_SOCKET
322 int Sockfd;
323 #endif
325 remote_cmd = REMOTE_SHELL_CMD;
327 #ifdef RWLASD
328 if (cmd == ASD_CMD)
329 remote_cmd = REMOTE_ASD_CMD;
330 #endif
331 if (cmd == VISTA_CMD)
332 remote_cmd = REMOTE_VISTA_CMD;
334 switch (remote_type) {
335 case REMOTE_SOCKET:
336 #ifdef RWL_SOCKET
337 if ((Sockfd = rwl_connect_socket_server()) < 0) {
338 DPRINT_ERR(ERR, " Error in getting the SocDes\n");
339 return BCME_ERROR;
342 wl = (void *)(&Sockfd);
343 if (remote_CDC_tx(wl, cmd, input_buf, *input_len, *input_len,
344 remote_cmd, 0) < 0) {
345 DPRINT_ERR(ERR, "shell_info_fe: Send command failed\n");
346 rwl_close_pipe(remote_type, wl);
347 return BCME_ERROR;
349 /* For backward compatibility for ASD, async and kill commands do the
350 * old way
352 if (remote_cmd == REMOTE_SHELL_CMD && !strstr((char*)input_buf, "%") &&
353 !strstr((char*)input_buf, "kill"))
354 error = rwl_socket_shellresp(wl, rem_ptr, input_buf);
355 else {
356 if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
357 DPRINT_ERR(ERR, "shell_info_fe: Receiving CDC"
358 "header failed\n");
359 rwl_close_pipe(remote_type, wl);
360 return FAIL;
363 if ((resp_buf = malloc(rem_ptr->msg.len + 1)) == NULL) {
364 DPRINT_ERR(ERR, "Mem alloc fails\n");
365 rwl_close_pipe(remote_type, wl);
366 return FAIL;
369 if (remote_CDC_rx(wl, rem_ptr, resp_buf,
370 rem_ptr->msg.len, 0) == FAIL) {
371 DPRINT_ERR(ERR, "shell_info_fe: No results!\n");
372 rwl_close_pipe(remote_type, wl);
373 free(resp_buf);
374 return FAIL;
377 /* print the shell result */
378 resp_buf[rem_ptr->msg.len] = '\0';
379 /* The return value of the shell command
380 * will be stored in rem_ptr->msg.cmd
381 * Return that value to the client process
383 if (rem_ptr->msg.flags & REMOTE_REPLY)
384 error = rem_ptr->msg.cmd;
385 fputs((char*)resp_buf, stdout);
387 rwl_close_pipe(remote_type, wl);
388 #endif /* RWL_SOCKET */
389 break;
390 case REMOTE_DONGLE:
391 case REMOTE_SERIAL:
392 if (remote_CDC_tx(wl, cmd, input_buf, *input_len, *input_len,
393 remote_cmd, 0) < 0) {
394 DPRINT_ERR(ERR, "shell_info_fe: Send command failed\n");
395 return FAIL;
398 /* For backward compatibility for ASD, async and kill commands do the
399 * old way
401 if (remote_cmd != REMOTE_ASD_CMD && !strstr((char*)input_buf, "%") &&
402 !strstr((char*)input_buf, "kill"))
403 error = rwl_dongle_shellresp(wl, rem_ptr, input_buf, cmd);
404 else {
405 if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
406 DPRINT_ERR(ERR, "shell_info_fe:"
407 "Receiving CDC header failed\n");
408 return SERIAL_PORT_ERR;
410 rwl_swap_header(rem_ptr, NETWORK_TO_HOST);
411 /* In case of shell or ASD commands the response
412 * size is not known in advance
413 * Hence based on response from the server memory is allocated
415 if ((resp_buf = malloc(rem_ptr->msg.len + 1)) == NULL) {
416 DPRINT_ERR(ERR, "Mem alloc fails for shell response buffer\n");
417 return FAIL;
420 if (rem_ptr->data_len < DATA_FRAME_LEN) {
421 /* Response comes in one shot not in fragments */
422 if (remote_CDC_rx(wl, rem_ptr, resp_buf,
423 rem_ptr->msg.len, 0) == FAIL) {
424 DPRINT_ERR(ERR, "shell_info_fe: No results!\n");
425 free(resp_buf);
426 return FAIL;
428 } else {
429 error = rwl_serial_fragmented_response_fe(wl, rem_ptr,
430 resp_buf, (unsigned long *)&(rem_ptr->msg.len));
432 /* print the shell result */
433 resp_buf[rem_ptr->msg.len] = '\0';
434 /* The return value of the shell command will be stored in rem_ptr->msg.cmd
435 * Return that value to the client process
437 if (rem_ptr->msg.flags & REMOTE_REPLY)
438 error = rem_ptr->msg.cmd;
439 fputs((char*)resp_buf, stdout);
441 break;
443 case REMOTE_WIFI:
444 #ifdef RWL_WIFI
445 /* Unlike dongle or UART case the response for wi-fi comes in single frame.
446 * (CDC header + data). Hence the single read is called for header and data.
447 * If any error in reading then we sleep for some time before retrying.
449 if ((list = (dot11_action_wifi_vendor_specific_t *)
450 malloc(RWL_WIFI_ACTION_FRAME_SIZE)) == NULL) {
451 return FAIL;
453 if ((rem_ptr = (rem_ioctl_t *)malloc(REMOTE_SIZE)) == NULL) {
454 free(list);
455 return FAIL;
458 if ((cbuf = (char*) malloc(*input_len)) == NULL) {
459 DPRINT_ERR(ERR, "Malloc failed for shell response\n");
460 free(rem_ptr);
461 free(list);
462 return FAIL;
465 /* copy of the original buf is required for retry */
466 memcpy(cbuf, (char*)input_buf, *input_len);
467 for (retry = 0; retry < RWL_WIFI_RETRY; retry++) {
469 rwl_wifi_purge_actionframes(wl);
470 if (remote_CDC_tx(wl, cmd, input_buf, *input_len, *input_len,
471 remote_cmd, 0) < 0) {
472 DPRINT_DBG(OUTPUT, "rwl_shell_information_fe(wifi):"
473 "Send command failed\n");
474 rwl_sleep(RWL_WIFI_RETRY_DELAY);
475 free(rem_ptr);
476 free(list);
477 return FAIL;
479 /* For backward compatibility for ASD,
480 * async and kill commands do the
481 * old way
483 if (remote_cmd == REMOTE_SHELL_CMD &&
484 !strstr((char*)input_buf, "%") &&
485 !strstr((char*)input_buf, "kill")) {
486 error = rwl_wifi_shellresp(wl, rem_ptr, input_buf);
487 if (rem_ptr->msg.len == 0)
488 break;
490 else if (remote_cmd == REMOTE_VISTA_CMD) {
491 if ((error = remote_CDC_DATA_wifi_rx_frag(wl, rem_ptr, 0,
492 NULL, RWL_WIFI_SHELL_CMD)) < 0) {
493 DPRINT_DBG(OUTPUT, "rwl_shell_information_fe(wifi):"
494 "error in reading shell response\n");
495 continue;
497 if (rem_ptr->msg.flags & REMOTE_REPLY) {
498 error = rem_ptr->msg.cmd;
499 break;
500 } else {
501 rwl_sleep(RWL_WIFI_RETRY_DELAY);
502 continue;
505 else {
506 /* ASD commands may take long time to give back
507 * the response (eg: file transfer)
509 if (remote_cmd == REMOTE_ASD_CMD) {
510 for (;;) {
511 /* copy back the buffer to input buffer */
512 memcpy((char*)input_buf, cbuf, *input_len);
514 if ((error = remote_CDC_DATA_wifi_rx_frag(
515 wl, rem_ptr, 0, NULL,
516 RWL_WIFI_SHELL_CMD)) < 0) {
517 DPRINT_DBG(OUTPUT,
518 "rwl_shell_information_fe(wifi):"
519 "err in reading shell response\n");
520 continue;
522 if (rem_ptr->msg.flags & REMOTE_REPLY) {
523 error = rem_ptr->msg.cmd;
524 retry = RWL_WIFI_RETRY;
525 break;
526 } else {
527 rwl_sleep(RWL_WIFI_RETRY_DELAY);
528 continue;
535 free(rem_ptr);
536 free(list);
537 if (cbuf != NULL)
538 free(cbuf);
539 #endif /* RWL_WIFI */
540 break;
542 default:
543 break;
544 } /* End of switch (remote_type) */
546 if (resp_buf)
547 free(resp_buf);
549 return error;
552 /* Prepare to issue shell command */
554 rwl_shell_cmd_proc(void *wl, char **argv, int cmd)
556 uchar *buff;
557 unsigned long len = SHELL_CMD_LEN;
558 int err;
560 if ((buff = malloc(SHELL_CMD_LEN)) == NULL) {
561 DPRINT_ERR(ERR, "\n Mem alloc fails for shell cmd buffer\n");
562 return FAIL;
565 memset(buff, 0, sizeof(SHELL_CMD_LEN));
566 while (*argv) {
567 strcat((char*)buff, *argv);
568 argv++;
569 if (*argv)
570 strcat((char*)buff, " "); /* leave space between args */
573 err = rwl_shell_information_fe(wl, cmd, buff, &len);
574 free(buff);
575 return err;
578 /* transport independent entry point for GET ioctls */
580 rwl_queryinformation_fe(void *wl, int cmd, void* input_buf,
581 unsigned long *input_len, int debug, int rem_ioctl_select) {
582 int error = 0;
583 uint tx_len;
584 #if defined(RWL_SERIAL) || RWL_WIFI
585 rem_ioctl_t *rem_ptr = NULL;
586 #endif
588 #ifdef RWL_WIFI
589 int retry;
590 char *cinput_buf;
591 #endif
593 UNUSED_PARAMETER(debug);
595 switch (remote_type) {
596 case REMOTE_SOCKET:
597 #ifdef RWL_SOCKET
598 /* We don't want the server to allocate bigger buffers
599 * for some of the commands
600 * like scanresults. Server can still allocate 8K memory
601 * and send the response
603 if (*input_len > SERVER_RESPONSE_MAX_BUF_LEN)
604 *input_len = SERVER_RESPONSE_MAX_BUF_LEN;
605 error = rwl_information_socket(wl, cmd, input_buf, input_len,
606 input_len, rem_ioctl_select);
607 #endif /* RWL_SOCKET */
608 break;
610 #ifdef RWL_SERIAL
611 /* System serial transport is not supported in Linux. Only XP */
612 case REMOTE_SERIAL:
613 #ifdef SERDOWNLOAD
614 tx_len = MIN(*input_len, 512);
615 #else
616 tx_len = MIN(*input_len, 1024);
617 #endif
618 /* Time estimate assumes 115K baud */
619 if (*input_len > (1024 *10))
620 /* Multiply by 2. The buffer has to go there and back */
621 DPRINT_DBG(OUTPUT, "Wait time: %lu seconds\n",
622 ((*input_len)+ tx_len) / (115200/8));
624 if (remote_CDC_tx(wl, cmd, input_buf, *input_len,
625 tx_len, rem_ioctl_select, debug) < 0) {
626 DPRINT_ERR(ERR, "query_info_fe: Send command failed\n");
627 return FAIL;
630 if ((rem_ptr = remote_CDC_rx_hdr(wl, debug)) == NULL) {
631 DPRINT_ERR(ERR, "query_info_fe: Reading CDC header failed\n");
632 return FAIL;
635 if (rem_ptr->msg.flags != REMOTE_REPLY) {
636 DPRINT_ERR(ERR, "query_info_fe: response format error.\n");
637 return FAIL;
639 if (rem_ptr->msg.len > *input_len) {
640 DPRINT_ERR(ERR, "query_info_fe: needed size(%d) greater than "
641 "actual size(%lu)\n", rem_ptr->msg.len, *input_len);
642 return FAIL;
645 if (error != 0)
646 DPRINT_ERR(ERR, "query_info_fe: remote cdc header return "
647 "error code %d\n", error);
648 if (remote_CDC_rx(wl, rem_ptr, input_buf, *input_len, debug) == -1) {
649 DPRINT_ERR(ERR, "query_info_fe: No results!\n");
650 return FAIL;
652 if (rem_ptr->msg.flags & REMOTE_REPLY)
653 error = rem_ptr->msg.cmd;
654 break;
656 #endif /* RWL_SERIAL */
657 case REMOTE_DONGLE:
658 /* We don't want the server to allocate bigger buffers
659 * for some of the commands
660 * like scanresults. Server can still allocate 8K
661 *memory and send the response
662 * in fragments.
664 if (*input_len > SERVER_RESPONSE_MAX_BUF_LEN)
665 *input_len = SERVER_RESPONSE_MAX_BUF_LEN;
667 /* Actual buffer to be sent should be max 256 bytes as
668 *UART input buffer
669 * is 512 bytes
671 tx_len = MIN(*input_len, 256);
672 error = rwl_information_dongle(wl, cmd, input_buf, input_len,
673 tx_len, rem_ioctl_select);
675 break;
677 case REMOTE_WIFI:
678 #ifdef RWL_WIFI
679 /* We don't want the server to allocate bigger buffers
680 * for some of the commands
681 * like scanresults. Server can still allocate 8K memory
682 * and send the response
683 * in fragments.
685 if (*input_len > SERVER_RESPONSE_MAX_BUF_LEN)
686 *input_len = SERVER_RESPONSE_MAX_BUF_LEN;
688 /* Actual buffer to be sent should be max 960 bytes
689 * as wifi max frame size if 960
690 * and actual data for any command will not exceed 960 bytes
692 tx_len = MIN(*input_len, RWL_WIFI_FRAG_DATA_SIZE);
694 if ((rem_ptr = (rem_ioctl_t *)malloc(REMOTE_SIZE)) == NULL) {
695 return FAIL;
697 if ((cinput_buf = (char*)malloc(tx_len)) == NULL) {
698 DPRINT_ERR(ERR, "Malloc failed for query information fe"
699 "character buf \n");
700 free(rem_ptr);
701 return FAIL;
704 memcpy(cinput_buf, (char*)input_buf, tx_len); /* Keep a copy of input_buf */
706 for (retry = 0; retry < RWL_WIFI_RETRY; retry++) {
708 rwl_wifi_purge_actionframes(wl);
710 if (retry > 3)
711 DPRINT_INFO(OUTPUT, "ir_queryinformation_fe : retry %d"
712 "cmd %d\n", retry, cmd);
714 /* copy back the buffer to input buffer */
715 memcpy((char*)input_buf, cinput_buf, tx_len);
717 /* Issue the command */
718 if ((error = remote_CDC_wifi_tx(wl, cmd, input_buf,
719 *input_len, tx_len, rem_ioctl_select)) < 0) {
720 DPRINT_DBG(OUTPUT, "query_info_fe: Send command failed\n");
721 rwl_sleep(RWL_WIFI_RETRY_DELAY);
722 continue;
725 if ((error = remote_CDC_DATA_wifi_rx_frag(wl, rem_ptr,
726 *input_len, input_buf, RWL_WIFI_WL_CMD) < 0)) {
727 DPRINT_DBG(OUTPUT, "ir_queryinformation_fe :"
728 "Error in reading the frag bytes\n");
729 rwl_sleep(RWL_WIFI_RETRY_DELAY);
730 continue;
733 if (rem_ptr->msg.flags & REMOTE_REPLY) {
734 error = rem_ptr->msg.cmd;
735 break;
736 } else {
737 rwl_sleep(RWL_WIFI_RETRY_DELAY);
741 free(rem_ptr);
742 if (cinput_buf)
743 free(cinput_buf);
744 break;
745 #endif /* RWL_WIFI */
746 default:
747 DPRINT_ERR(ERR, "rwl_queryinformation_fe: Unknown"
748 "remote_type %d\n", remote_type);
749 break;
751 return error;
755 * This is the front end query function for Set Ioctls. This is used by clients
756 for executing Set Ioctls.
759 rwl_setinformation_fe(void *wl, int cmd, void* buf,
760 unsigned long *len, int debug, int rem_ioctl_select) {
761 int error = 0;
762 uint tx_len;
763 #if defined(RWL_SERIAL) || RWL_WIFI
764 rem_ioctl_t *rem_ptr = NULL;
765 #endif
767 #ifdef RWL_WIFI
768 dot11_action_wifi_vendor_specific_t *list = NULL;
769 char *cbuf, retry;
770 #endif
772 UNUSED_PARAMETER(debug);
774 switch (remote_type) {
775 case REMOTE_SOCKET:
776 #ifdef RWL_SOCKET
777 error = rwl_information_socket(wl, cmd, buf, len, len, rem_ioctl_select);
778 #endif
779 break;
780 #ifdef RWL_SERIAL
781 case REMOTE_SERIAL:
782 if (*len > (1024 *10))
783 DPRINT_DBG(OUTPUT, "Wait time: %lu seconds\n", (*len)/(115200/8));
785 if (remote_CDC_tx(wl, cmd, buf, *len, *len, rem_ioctl_select, debug) < 0) {
786 DPRINT_ERR(ERR, "set_info_fe: Send command failed\n");
787 return FAIL;
790 if ((rem_ptr = remote_CDC_rx_hdr(wl, debug)) == NULL) {
791 DPRINT_ERR(ERR, "set_info_fe: Reading CDC header failed\n");
792 return FAIL;
795 if (rem_ptr->msg.flags != REMOTE_REPLY) {
796 DPRINT_ERR(ERR, "set_info_fe: response format error.\n");
797 return FAIL;
800 if (rem_ptr->msg.len > *len) {
801 DPRINT_ERR(ERR, "set_info_fe: needed size (%d) greater than "
802 "actual size (%lu)\n", rem_ptr->msg.len, *len);
803 return FAIL;
806 if (error != 0) {
807 DPRINT_ERR(ERR, "set_info_fe: remote cdc header return "
808 "error code (%d)\n", error);
810 if (remote_CDC_rx(wl, rem_ptr, buf, rem_ptr->msg.len, debug) == -1) {
811 DPRINT_ERR(ERR, "set_info_fe: fetching results failed\n");
812 return FAIL;
815 if (rem_ptr->msg.flags & REMOTE_REPLY)
816 error = rem_ptr->msg.cmd;
817 break;
818 #endif /* RWL_SERIAL */
819 case REMOTE_DONGLE:
820 if (*len > SERVER_RESPONSE_MAX_BUF_LEN)
821 *len = SERVER_RESPONSE_MAX_BUF_LEN;
823 /* Actual buffer to be sent should be max 256 bytes as
824 *UART input buffer
825 * is 512 bytes
827 tx_len = MIN(*len, 512);
828 error = rwl_information_dongle(wl, cmd, buf, len, tx_len, rem_ioctl_select);
829 break;
831 case REMOTE_WIFI:
832 #ifdef RWL_WIFI
833 if (*len > SERVER_RESPONSE_MAX_BUF_LEN)
834 *len = SERVER_RESPONSE_MAX_BUF_LEN;
836 /* Actual buffer to be sent should be max 960 bytes
837 * as wifi max frame size if 960
838 * and actual data for any command will not exceed 960 bytes
840 tx_len = MIN(*len, RWL_WIFI_FRAG_DATA_SIZE);
842 if ((cbuf = (char*) malloc(tx_len)) == NULL) {
843 DPRINT_ERR(ERR, "Malloc failed for set_info_fe character buf\n");
844 return FAIL;
846 if ((list = (dot11_action_wifi_vendor_specific_t *)
847 malloc(RWL_WIFI_ACTION_FRAME_SIZE)) == NULL) {
848 free(cbuf);
849 return FAIL;
852 if ((rem_ptr = (rem_ioctl_t *)malloc(sizeof(rem_ioctl_t))) == NULL) {
853 free(list);
854 free(cbuf);
855 return FAIL;
858 memcpy(cbuf, (char*)buf, tx_len);
860 for (retry = 0; retry < RWL_WIFI_RETRY; retry++) {
862 rwl_wifi_purge_actionframes(wl);
863 /* copy back the buffer to input buffer */
864 memcpy((char*)buf, (char*)cbuf, tx_len);
866 if (retry > 3)
867 DPRINT_INFO(OUTPUT, "retry %d cmd %d\n", retry, cmd);
869 if ((error = remote_CDC_wifi_tx(wl, cmd, buf, *len,
870 tx_len, rem_ioctl_select) < 0)) {
871 DPRINT_ERR(ERR, "ir_setinformation_fe: Send"
872 "command failed\n");
873 rwl_sleep(RWL_WIFI_RETRY_DELAY);
874 continue;
877 if ((char*)buf != NULL) {
878 /* In case cmd is findserver, response is not
879 * required from the server
881 if (!strcmp((char*)buf, RWL_WIFI_FIND_SER_CMD)) {
882 break;
886 /* Read the CDC header and data of for the sent cmd
887 * resposne
889 if ((error = remote_CDC_DATA_wifi_rx((void*)wl, list) < 0)) {
890 DPRINT_ERR(ERR, "ir_setinformation_fe: failed to read"
891 "the response\n");
892 rwl_sleep(RWL_WIFI_RETRY_DELAY);
893 continue;
896 memcpy((char*)rem_ptr,
897 (char*)&list->data[RWL_WIFI_CDC_HEADER_OFFSET],
898 REMOTE_SIZE);
899 rwl_swap_header(rem_ptr, NETWORK_TO_HOST);
901 memcpy((char*)buf, (char*)&list->data[REMOTE_SIZE],
902 rem_ptr->msg.len);
904 if (rem_ptr->msg.flags & REMOTE_REPLY) {
905 error = rem_ptr->msg.cmd;
906 break;
907 } else {
908 rwl_sleep(RWL_WIFI_RETRY_DELAY);
911 free(rem_ptr);
912 free(list);
913 if (cbuf != NULL)
914 free(cbuf);
915 break;
916 #endif /* RWL_WIFI */
917 default:
918 DPRINT_ERR(ERR, "rwl_setinformation_fe: Unknown remote_type:%d\n",
919 remote_type);
920 break;
923 return error;
926 #ifdef RWL_WIFI
928 rwl_var_getbuf(void *wl, const char *iovar, void *param, int param_len, void **bufptr)
930 int len, error;
932 memset((char*)g_rwl_aligned_buf, 0, WLC_IOCTL_MAXLEN);
933 strcpy(g_rwl_aligned_buf, iovar);
935 /* include the null */
936 len = strlen(iovar) + 1;
938 if (param_len)
939 memcpy(&g_rwl_aligned_buf[len], param, param_len);
941 *bufptr = g_rwl_aligned_buf;
942 /* When user wants to execute local CMD being in remote wifi mode,
943 * rwl_wifi_swap_remote_type fucntion is used to change the remote types.
945 rwl_wifi_swap_remote_type(remote_type);
947 error = wl_get(wl, WLC_GET_VAR, &g_rwl_aligned_buf[0], WLC_IOCTL_MAXLEN);
948 /* revert back to the old remote type */
949 rwl_wifi_swap_remote_type(remote_type);
950 return error;
954 rwl_var_setbuf(void *wl, const char *iovar, void *param, int param_len)
956 int len, error;
958 memset(g_rwl_aligned_buf, 0, WLC_IOCTL_MAXLEN);
959 strcpy(g_rwl_aligned_buf, iovar);
961 /* include the null */
962 len = strlen(iovar) + 1;
964 if (param_len)
965 memcpy(&g_rwl_aligned_buf[len], param, param_len);
967 len += param_len;
968 /* When user wants to execute local CMD being in remote wifi mode,
969 * rwl_wifi_swap_remote_type fucntion is used to change the remote types.
971 rwl_wifi_swap_remote_type(remote_type);
972 error = wl_set(wl, WLC_SET_VAR, &g_rwl_aligned_buf[0], len);
973 /* revert back to the old type */
974 rwl_wifi_swap_remote_type(remote_type);
975 return error;
978 /* This function will send the buffer to the dongle driver */
980 rwl_var_send_vs_actionframe(void* wl, const char* iovar, void* param, int param_len)
982 int len, error;
984 memset(g_rwl_aligned_buf, 0, WLC_IOCTL_MAXLEN);
985 strcpy(g_rwl_aligned_buf, iovar);
987 /* include the null */
988 len = strlen(iovar) + 1;
990 if (param_len)
991 memcpy((void*)&g_rwl_aligned_buf[len+ OFFSETOF(wl_action_frame_t, data)],
992 param,
993 param_len);
995 /* Set the PacketID (not used by remote WL */
996 memset((void*)&g_rwl_aligned_buf[len + OFFSETOF(wl_action_frame_t, packetId)], 0, 4);
998 /* Set the dest addr */
999 memcpy((void*)&g_rwl_aligned_buf[len + OFFSETOF(wl_action_frame_t, da)],
1000 (void*)g_rwl_buf_mac,
1001 ETHER_ADDR_LEN);
1003 /* set the length */
1004 memcpy((void*)&g_rwl_aligned_buf[len + OFFSETOF(wl_action_frame_t, len)],
1005 (void*) &param_len,
1008 len += param_len + ETHER_ADDR_LEN + 2 + 4;
1010 /* When user wants to execute local CMD being in remote wifi mode,
1011 * rwl_wifi_swap_remote_type fucntion is used to change the remote types.
1013 rwl_wifi_swap_remote_type(remote_type);
1015 error = wl_set(wl, WLC_SET_VAR, &g_rwl_aligned_buf[0], len);
1016 /* revert back to the old type */
1017 rwl_wifi_swap_remote_type(remote_type);
1018 return error;
1020 #endif /* RWL_WIFI */
1022 * Function for printing the usage if user type invalid command line
1023 * options(e.g wl --serial or --dongle or --socket or --wifi)
1025 void
1026 rwl_usage(int remote_type)
1028 switch (remote_type) {
1029 case REMOTE_SERIAL:
1030 fprintf(stderr, " Usage: wl/dhd [--linuxdut/linux] [--debug]");
1031 fprintf(stderr, " [--serial port no]");
1032 fprintf(stderr, "[--ReadTimeout n] [--interactive] [--clientbatch] \n");
1033 fprintf(stderr, "\t--linuxdut/linux removes the WLC_OID_BASE");
1034 fprintf(stderr, "when sending the IOCTL command \n");
1035 fprintf(stderr, "\t--debug prints out tx packets sending down ");
1036 fprintf(stderr, " the serial line, and other debug info \n");
1037 fprintf(stderr, "\t--serial enables the remoteWL serial port number\n");
1038 fprintf(stderr, "\t--interactive enables using WL in interactive mode\n");
1039 fprintf(stderr, "\t--clientbatch enables command batchinng on the client,");
1040 fprintf(stderr, " the default is batching on driver\n");
1041 break;
1042 case REMOTE_DONGLE:
1043 fprintf(stderr, " Usage: wl/dhd --dongle <Device Name> <command>\n");
1044 fprintf(stderr, "\t<Device Name> COM1/COM2 (WinXP) or /dev/ttyS0"
1045 " or /dev/ttyS1 (Linux)\n");
1046 fprintf(stderr, "\t<command> - wl, shell or dhd command\n");
1047 fprintf(stderr, "\tDepending on the client you are using(wl or dhd)\n");
1048 fprintf(stderr, "\t\t shell command usage: sh <command>\n");
1049 break;
1050 case REMOTE_SOCKET:
1051 fprintf(stderr, " Usage: wl/dhd --socket <IP ADDRESS> <PORT>\n");
1052 fprintf(stderr, "\t<IPADDRESS> IP address of server machine\n");
1053 fprintf(stderr, "\t<PORT> Port no of server\n");
1054 fprintf(stderr, "\t<command> - wl, shell or dhd command\n");
1055 fprintf(stderr, "\tDepending on the client you are using(wl or dhd)\n");
1056 fprintf(stderr, "\t\t shell command usage: sh <command>\n");
1057 break;
1058 case REMOTE_WIFI:
1059 fprintf(stderr, " Usage: wl/dhd --wifi <MAC Address> <command>\n");
1060 fprintf(stderr, "\t<MAC Address> MAC Address\n");
1061 fprintf(stderr, "\t<command> - wl, shell or dhd command\n");
1062 fprintf(stderr, "\tDepending on the client you are using(wl or dhd)\n");
1063 fprintf(stderr, "\t\t shell command usage: sh <command>\n");
1064 break;
1065 default:
1066 break;
1069 #ifdef RWL_SOCKET
1070 static int
1071 rwl_socket_shellresp(void *wl, rem_ioctl_t *rem_ptr, uchar *input_buf)
1073 uchar* resp_buf = NULL;
1074 int pid, msg_len, error;
1075 g_sig_ctrlc = 1;
1076 g_child_pid = pid = rwl_shell_createproc(wl);
1077 if (pid == 0) {
1078 while (g_sig_ctrlc);
1079 remote_CDC_tx(wl, 0, input_buf, 0, 0, CTRLC_FLAG, 0);
1080 exit(0);
1083 do {
1084 if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
1085 DPRINT_ERR(ERR, "rwl_socket_shellresp: Receiving CDC"
1086 "header failed\n");
1087 rwl_close_pipe(remote_type, wl);
1088 return FAIL;
1090 msg_len = rem_ptr->msg.len;
1091 if ((resp_buf = malloc(rem_ptr->msg.len + 1)) == NULL) {
1092 DPRINT_ERR(ERR, "rwl_socket_shellresp: Mem alloc fails\n");
1093 rwl_close_pipe(remote_type, wl);
1094 return FAIL;
1096 if (msg_len > 0) {
1097 if (remote_CDC_rx(wl, rem_ptr, resp_buf,
1098 rem_ptr->msg.len, 0) == FAIL) {
1099 DPRINT_ERR(ERR, "rwl_socket_shellresp: No results!\n");
1100 rwl_close_pipe(remote_type, wl);
1101 free(resp_buf);
1102 return FAIL;
1105 /* print the shell result */
1106 resp_buf[rem_ptr->msg.len] = '\0';
1107 /* The return value of the shell command
1108 * will be stored in rem_ptr->msg.cmd
1109 * Return that value to the client process
1111 if (rem_ptr->msg.flags & REMOTE_REPLY)
1112 error = rem_ptr->msg.cmd;
1113 write(1, resp_buf, msg_len);
1114 } while (msg_len);
1115 rwl_shell_killproc(pid);
1116 return error;
1118 #endif /* RWL_SOCKET */
1119 /* For wifi shell responses read data until server stops sending */
1120 #ifdef RWL_WIFI
1121 static int
1122 rwl_wifi_shellresp(void *wl, rem_ioctl_t *rem_ptr, uchar *input_buf)
1124 int pid, msg_len, error;
1125 g_sig_ctrlc = 1;
1126 g_child_pid = pid = rwl_shell_createproc(wl);
1127 if (pid == 0)
1129 while (g_sig_ctrlc);
1130 remote_CDC_tx(wl, 0, input_buf, 0, 0, CTRLC_FLAG, 0);
1131 exit(0);
1134 do {
1135 if ((error = remote_CDC_DATA_wifi_rx_frag(wl, rem_ptr, 0,
1136 NULL, RWL_WIFI_SHELL_CMD)) < 0) {
1137 DPRINT_DBG(OUTPUT, "rwl_shell_information_fe(wifi):"
1138 "error in reading shell response\n");
1139 continue;
1141 msg_len = rem_ptr->msg.len;
1142 error = rem_ptr->msg.cmd;
1143 } while (msg_len);
1145 rwl_shell_killproc(pid);
1146 return error;
1148 #endif /* RWL_WIFI */
1150 /* For dongle or system serial shell responses read data until server stops sending */
1151 static int
1152 rwl_dongle_shellresp(void *wl, rem_ioctl_t *rem_ptr, uchar *input_buf, int cmd)
1154 int pid, msg_len, error;
1155 uchar *resp_buf;
1157 g_sig_ctrlc = 1;
1158 g_child_pid = pid = rwl_shell_createproc(wl);
1159 if (pid == 0) {
1160 while (g_sig_ctrlc);
1161 remote_CDC_tx(wl, cmd, input_buf, 0, 0, CTRLC_FLAG, 0);
1162 exit(0);
1165 do {
1166 if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
1167 DPRINT_ERR(ERR, "shell_info_fe: Receiving CDC header failed\n");
1168 return SERIAL_PORT_ERR;
1170 /* In case of shell or ASD commands the response size is not known in advance
1171 * Hence based on response from the server memory is allocated
1173 msg_len = rem_ptr->msg.len;
1174 if ((resp_buf = malloc(rem_ptr->msg.len + 1)) == NULL) {
1175 DPRINT_ERR(ERR, "Mem alloc fails for shell response buffer\n");
1176 return FAIL;
1178 /* Response comes in one shot not in fragments */
1179 if (remote_CDC_rx(wl, rem_ptr, resp_buf,
1180 rem_ptr->msg.len, 0) == FAIL) {
1181 DPRINT_ERR(ERR, "shell_info_fe: No results!\n");
1182 free(resp_buf);
1183 return FAIL;
1185 /* print the shell result */
1186 resp_buf[rem_ptr->msg.len] = '\0';
1187 /* The return value of the shell command will be stored in rem_ptr->msg.cmd
1188 * Return that value to the client process
1190 if (rem_ptr->msg.flags & REMOTE_REPLY)
1191 error = rem_ptr->msg.cmd;
1192 write(1, resp_buf, msg_len);
1193 } while (msg_len);
1194 rwl_shell_killproc(pid);
1195 return error;