K2.6 patches and update.
[tomato.git] / release / src-rt / wl / exe / wlu_pipe.c
blob73441cb31084a56a2691beec91521e6a23b309e2
1 /*
2 * Common Functionality for pipe
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_pipe.c,v 1.22 2009-10-15 17:54:48 Exp $
14 #ifdef WIN32
15 #define NEED_IR_TYPES
17 #include <windows.h>
18 #ifdef UNDER_CE
19 /* Expected order for succesfull compliation */
20 #include <winsock2.h>
21 #endif
22 #include <epictrl.h>
23 #include <irelay.h>
24 #endif /* WIN32 */
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <arpa/inet.h>
29 #include <unistd.h>
30 #include <netdb.h>
31 #include <signal.h>
32 #include <sys/ioctl.h>
33 #include <wlioctl.h>
34 #include <net/if.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <ctype.h>
40 #ifdef SYMBIAN
41 #include <sys/types.h>
42 #include <sys/socket.h>
43 #include <netinet/in.h>
44 #else
45 #if !defined(TARGETOS_nucleus) && !defined(MACOSX)
46 #include <malloc.h>
47 #endif
48 #endif /* SYMBIAN */
49 #include <typedefs.h>
50 #include <wlioctl.h>
52 #include <proto/ethernet.h>
53 #include <bcmendian.h>
54 #include <bcmutils.h>
55 #include <bcmcdc.h>
56 #include <proto/802.11.h>
57 #if defined(RWL_WIFI) || defined(WIFI_REFLECTOR)
58 #include <rwl_wifi.h>
59 #endif /* defined(RWL_WIFI) || defined(WIFI_REFLECTOR) */
60 #include "wlu.h"
61 #include "wlu_remote.h"
63 static rem_ioctl_t rem_cdc;
64 char *g_rwl_device_name_serial = "";
65 bool g_rwl_swap = FALSE;
66 char g_rem_ifname[IFNAMSIZ] = "\0";
67 int need_speedy_response; /* Indicate findserver is checking channels */
69 /* Linux 100 usec */
70 #define SYNC_TIME 100
72 #define UART_FIFO_LEN 64
73 #define END_OF_PACK_SEP_LEN 2
74 #define INIT_CMD_SLEEP 500
75 #define dtoh32(i) i
77 /* dword align allocation */
78 union {
79 uchar bufdata[ETHER_ADDR_LEN];
80 uint32 alignme;
81 } bufmac_wlu;
82 char *g_rwl_buf_mac = (char*) &bufmac_wlu.bufdata;
84 #ifdef RWL_WIFI
85 /* dword align allocation */
86 union {
87 uchar shelldata[WL_MAX_BUF_LEN];
88 uint32 alignme;
89 } shell_wlu;
90 char *g_rwl_buf_shell = (char*) &shell_wlu.shelldata;
91 int rwl_find_remote_wifi_server(void *wl, char *id);
92 int wl_ioctl(void *wl, int cmd, void *buf, int len, bool set);
94 /*
95 * This function runs a set of commands before running the wi-fi server
96 * This is avoids packet drops and improves performance.
97 * We run the following wl commands
98 * up, mpc 0, wsec 0, slow_timer 999999, fast_timer 999999, glacial_timer 999999
99 * legacylink 1, monitor 1.
101 void remote_wifi_ser_init_cmds(void *wl)
103 int err;
104 char bigbuf[RWL_WIFI_BUF_LEN];
105 uint len = 0, count;
106 /* The array stores command, length and then data format */
107 remote_wifi_cmds_t wifi_cmds[] = {
108 {WLC_UP, NULL, 0x0},
109 {WLC_SET_VAR, "mpc", 0},
110 {WLC_SET_WSEC, NULL, 0x0},
111 {WLC_SET_VAR, "slow_timer", 999999},
112 {WLC_SET_VAR, "fast_timer", 999999},
113 {WLC_SET_VAR, "glacial_timer", 999999},
114 {WLC_SET_MONITOR, NULL, 0x1},
115 {WLC_SET_PM, NULL, 0x0}
118 for (count = 0; count < ARRAYSIZE(wifi_cmds); count++) {
120 if (wifi_cmds[count].data == NULL)
121 len = sizeof(int);
122 else
123 len = strlen(wifi_cmds[count].data) + 1 + sizeof(int);
125 /* If the command length exceeds the buffer length continue
126 * executing the next command
128 if (len > sizeof(bigbuf)) {
129 DPRINT_ERR(ERR, "Err: command len exceeds buf len. Check"
130 "initialization cmds\n");
131 continue;
134 if (wifi_cmds[count].data != NULL) {
135 strcpy(bigbuf, wifi_cmds[count].data);
136 memcpy(&bigbuf[strlen(wifi_cmds[count].data)+1],
137 (char*)&wifi_cmds[count].value, sizeof(int));
138 } else {
139 memcpy(&bigbuf[0], (char*)&wifi_cmds[count].value, sizeof(int));
141 #ifdef WIN32
142 /* Add OID base for NDIS commands */
144 err = (int)ir_setinformation(wl, wifi_cmds[count].cmd + WL_OID_BASE,
145 bigbuf, &len);
146 #endif
148 if (wifi_cmds[count].cmd == WLC_UP)
149 /* NULL needs to be passed to the driver if WL UP command needs to
150 * be executed Otherwise driver hangs
152 err = wl_ioctl(wl, wifi_cmds[count].cmd,
153 NULL, 0, TRUE);
154 else
155 err = wl_ioctl(wl, wifi_cmds[count].cmd,
156 (void*)&bigbuf, len, TRUE);
158 rwl_sleep(INIT_CMD_SLEEP);
162 /* When user wants to execute local CMD being in remote wifi mode, this fucntion is used
163 * to change the remote types.
164 * This fucntion is called to swap the remote type to execute the cmd using the local
165 * driver interface.
166 * This is required for to call proper front end fucntions to achive the local set/get ioctl.
168 void
169 rwl_wifi_swap_remote_type(int flag)
171 static int remote_flag;
172 if (flag == REMOTE_WIFI) {
173 remote_type = NO_REMOTE;
174 remote_flag = flag;
175 } else if (remote_flag == REMOTE_WIFI) {
176 remote_type = remote_flag;
177 remote_flag = flag;
179 return;
182 void
183 rwl_wifi_free_list(dot11_action_wifi_vendor_specific_t *list[])
185 int i;
186 for (i = 0; i < RWL_DEFAULT_WIFI_FRAG_COUNT; i++) {
187 if (list[i])
188 free(list[i]);
193 * Configures local channel for finding server.
194 * Server call this fucntion for getting its current channel,
195 * client uses this fucntion for setting its channel to new channel.
197 static int
198 rwl_wifi_config_channel(void *wl, int cmd, int *channel)
200 int error;
201 channel_info_t ci;
202 error = -1;
203 /* Get functionality is used only by server */
204 if (cmd == WLC_GET_CHANNEL) {
205 memset((char*)&ci, 0, sizeof(ci));
206 if ((error = wl_get(wl, cmd, &ci, sizeof(channel_info_t))))
207 return error;
208 ci.hw_channel = dtoh32(ci.hw_channel);
209 ci.scan_channel = dtoh32(ci.scan_channel);
210 ci.target_channel = dtoh32(ci.target_channel);
211 if (ci.scan_channel) {
212 printf("Scan in progress.\n");
214 *channel = ci.hw_channel;
217 if (cmd == WLC_SET_CHANNEL) {
218 /* Set functionality is used by the client */
219 ci.target_channel = *channel;
220 /* When user wants to execute local CMD being in remote wifi mode,
221 * rwl_wifi_swap_remote_type fucntion is used to change the remote types.
223 rwl_wifi_swap_remote_type(remote_type);
224 error = wl_set(wl, cmd, &ci.target_channel, sizeof(int));
225 /* rever it back to same old remote type */
226 rwl_wifi_swap_remote_type(remote_type);
228 return error;
231 allocate the memory for action frame and update with wifi tranport header.
233 dot11_action_wifi_vendor_specific_t *
234 rwl_wifi_allocate_actionframe()
236 dot11_action_wifi_vendor_specific_t *action_frame;
238 if ((action_frame = (dot11_action_wifi_vendor_specific_t *)
239 malloc(RWL_WIFI_ACTION_FRAME_SIZE)) == NULL) {
240 DPRINT_ERR(ERR, "rwl_wifi_allocate_actionframe: unable to allocate frame \n");
241 return action_frame;
243 action_frame->category = RWL_ACTION_WIFI_CATEGORY;
244 action_frame->OUI[0] = RWL_WIFI_OUI_BYTE0;
245 action_frame->OUI[1] = RWL_WIFI_OUI_BYTE1;
246 action_frame->OUI[2] = RWL_WIFI_OUI_BYTE2;
247 action_frame->type = RWL_WIFI_DEFAULT_TYPE;
248 action_frame->subtype = RWL_WIFI_DEFAULT_SUBTYPE;
250 return action_frame;
253 * Send the valid action frame (CDC+DATA) through the REF driver interface.
254 * if the CMD is "findserver" then "findmypeer" frames are sent on the diffrent
255 * channels to reconnect
256 * to with server. Other wl cmd takes the normal path.
257 * parameter 3 , i.e. buf contains the cmd line arguments and buf_len is the actual
258 * length of the buf. data_len is the length of the actual data to be sent to remote server.
261 remote_CDC_wifi_tx(void *wl, uint cmd, uchar *buf, uint buf_len, uint data_len, uint flags)
263 rem_ioctl_t *rem_ptr = &rem_cdc;
264 int error, read_try;
265 dot11_action_wifi_vendor_specific_t *rem_wifi_send;
267 /* prepare CDC header */
268 rem_ptr->msg.cmd = cmd;
269 rem_ptr->msg.len = buf_len;
270 rem_ptr->msg.flags = flags;
271 rem_ptr->data_len = data_len;
272 if (strlen(g_rem_ifname) != 0)
273 strncpy(rem_ptr->intf_name, g_rem_ifname, (int)IFNAMSIZ);
274 rwl_swap_header(rem_ptr, HOST_TO_NETWORK);
276 if ((data_len > buf_len)) {
277 DPRINT_ERR(ERR, "remote_CDC_wifi_tx: data_len (%d) > buf_len (%d)\n",
278 data_len, buf_len);
279 return (FAIL);
281 /* client will not send data greater than RWL_WIFI_FRAG_DATA_SIZE to server,
282 * this condition should not be hit on client side, when sending the cmd
283 * to remote server
285 if (data_len > RWL_WIFI_FRAG_DATA_SIZE)
286 DPRINT_DBG(OUTPUT, "data size exceeds data_len %d\n", rem_ptr->msg.len);
288 if ((buf != NULL) && (strlen((char*)buf) >= (sizeof(RWL_WIFI_FIND_SER_CMD)-1)) &&
289 (!strcmp((char*)buf, RWL_WIFI_FIND_SER_CMD))) {
290 /* This is special case for wifi, when user wants to findserver,
291 * client has to execute it locally.Find the channel on the on
292 * which DUT is operating and sync up with specified MAC address,
293 * retry if fails to find the server
295 for (read_try = 0; read_try < RWL_WIFI_RETRY; read_try++) {
296 if (((error = rwl_find_remote_wifi_server(wl,
297 &g_rwl_buf_mac[0])) == 0)) {
298 break;
301 return error;
304 if ((rem_wifi_send = rwl_wifi_allocate_actionframe()) == NULL) {
305 DPRINT_ERR(ERR, "remote_CDC_wifi_tx: Failed to allocate memory\n");
306 return (FAIL);
308 /* only data length needs to be sent to remote server using this function
309 * This function is only meant for client to send data to server
310 * Copy the CDC header and data to action frame data feild
311 * Now we have encapsulated the CDC header and data completely to in the
312 * action frame.
314 memcpy((void*)&rem_wifi_send->data[RWL_WIFI_CDC_HEADER_OFFSET],
315 (char*)rem_ptr, REMOTE_SIZE);
316 if (buf != NULL) {
317 memcpy((void*)&rem_wifi_send->data[REMOTE_SIZE], buf, data_len);
320 /* Send the action frame to remote server using the rwl_var_setbuf fucntion,
321 * which will use the local driver interface to send this frame on the air
323 if ((error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD, rem_wifi_send,
324 RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
325 DPRINT_ERR(ERR, "Unable to read the action frame %d error\n", error);
327 free(rem_wifi_send);
328 return error;
332 * Read the valid action frame through the REF/DUT driver interface.
333 * Retry for no of times, wait for action frame for the specified time.
336 remote_CDC_DATA_wifi_rx(void *wl, dot11_action_wifi_vendor_specific_t * rec_frame)
338 int error, read_try;
339 void *ptr = NULL;
342 /* retry is to ensure to read late arrival action frame */
343 for (read_try = 0; read_try < RWL_WIFI_RX_RETRY; read_try++) {
344 /* read the action frame queued in the local driver wifi queue */
345 if ((error = rwl_var_getbuf(wl, RWL_WIFI_GET_ACTION_CMD, rec_frame,
346 RWL_WIFI_ACTION_FRAME_SIZE, &ptr)) < 0) {
347 DPRINT_ERR(ERR, "remote_CDC_DATA_wifi_rx: Error in reading the frame %d\n",
348 error);
349 return error;
351 /* copy the read action frame to the user frame and cjheck for the action category.
352 * If the action category matches with RWL_ACTION_WIFI_CATEGORY ,
353 * then its the valid frame, otherwise ignore it.
355 memcpy((char*)rec_frame, ptr, RWL_WIFI_ACTION_FRAME_SIZE);
357 if (rec_frame->category == RWL_ACTION_WIFI_CATEGORY) {
358 break;
359 } else {
360 /* If we are executing findserver then sleep less */
361 if (!need_speedy_response)
362 rwl_sleep(RWL_WIFI_RX_DELAY);
363 else
364 rwl_sleep(RWL_CHANNEL_RX_SCAN_DELAY);
367 /* If failed to get the valid frame , indicate the error */
368 if (!(rec_frame->category == RWL_ACTION_WIFI_CATEGORY)) {
369 return (FAIL);
371 return error;
374 * read data that has reached client in fragments. If the functtion is
375 * called from rwl_shell_information_fe then the flag will be set to 1.
376 * For shell response this function will output the response on the standard interface.
377 * Response will be coming in out of order , this fucntion will make it inorder.
378 * Duplicate action frames are ignored.
381 remote_CDC_DATA_wifi_rx_frag(void *wl, rem_ioctl_t *rem_ptr, uint input_len,
382 void *input, bool shell)
384 int error, totalfrag, seq_num, num_frags, remainingbytes;
385 dot11_action_wifi_vendor_specific_t *rec_frame;
386 uchar *input_buf = (uchar*)input;
387 /* An array of pointers to each recieved frag */
388 dot11_action_wifi_vendor_specific_t *master_list[RWL_DEFAULT_WIFI_FRAG_COUNT];
390 UNUSED_PARAMETER(input_len);
391 remainingbytes = 0;
393 memset(master_list, 0, sizeof(master_list));
394 /* in case of shell cmd's receive size is unknown */
395 if (shell) {
396 input_buf = (uchar*)g_rwl_buf_shell;
397 memset(input_buf, 0, WL_MAX_BUF_LEN);
400 /* We don't yet know how many fragments we will need to read since the
401 length is contained in the first frgment of the message itself. Set
402 totalfrag to an arbitry large number and we will readjust it after we
403 successfully recieve the first frag.
405 totalfrag = RWL_DEFAULT_WIFI_FRAG_COUNT;
407 for (num_frags = 0; num_frags <= totalfrag; num_frags++) {
408 if ((rec_frame = rwl_wifi_allocate_actionframe()) == NULL) {
409 DPRINT_DBG(OUTPUT, "malloc failure\n");
410 rwl_wifi_free_list(master_list);
411 return (FAIL);
413 if ((error = remote_CDC_DATA_wifi_rx((void*)wl, rec_frame)) < 0) {
414 free(rec_frame);
415 rwl_wifi_free_list(master_list);
416 return FAIL;
419 if (rec_frame->subtype >= RWL_DEFAULT_WIFI_FRAG_COUNT) {
420 DPRINT_DBG(OUTPUT, " Read bogus subtype %d\n", rec_frame->subtype);
421 free(rec_frame);
422 continue;
424 /* Keep only originals and discard any dup frags */
425 if (!master_list[rec_frame->subtype]) {
426 master_list[rec_frame->subtype] = rec_frame;
427 } else {
428 num_frags--;
429 free(rec_frame);
432 /* Look for first frag so we can accurately calculate totalfrag */
433 if (rec_frame->subtype == RWL_WIFI_DEFAULT_SUBTYPE) {
434 memcpy((char*)rem_ptr,
435 (char*)&master_list[rec_frame->subtype]->
436 data[RWL_WIFI_CDC_HEADER_OFFSET], REMOTE_SIZE);
437 rwl_swap_header(rem_ptr, NETWORK_TO_HOST);
438 totalfrag = rem_ptr->msg.len / RWL_WIFI_FRAG_DATA_SIZE;
439 remainingbytes = rem_ptr->msg.len % RWL_WIFI_FRAG_DATA_SIZE;
443 /* All frags are now read and there are no dups. Check for missing frags */
444 for (seq_num = 0; seq_num < totalfrag; seq_num++) {
445 if (!master_list[seq_num]) {
446 DPRINT_DBG(OUTPUT, "Missing frag number %d\n", seq_num);
447 rwl_wifi_free_list(master_list);
448 return (FAIL);
452 case 1: response in one frame i.e if (totalfrag==0)
453 case 2: response in multiple frame ( multiple of RWL_WIFI_FRAG_DATA_SIZE)
454 case 3: response in multiple frame and not in multiple of RWL_WIFI_FRAG_DATA_SIZE
457 /* case 1: Check for the response in single frame */
458 if (totalfrag == 0)
459 memcpy((char*)&input_buf[0],
460 (char*)&master_list[0]->data[REMOTE_SIZE], rem_ptr->msg.len);
461 else /* case 2: Copy fragments into contiguous frame */
462 memcpy((char*)&input_buf[0],
463 (char*)&master_list[0]->data[REMOTE_SIZE], RWL_WIFI_FRAG_DATA_SIZE);
466 * If all the frames are recieved , copy them to a contigues buffer
468 for (seq_num = 1; seq_num < totalfrag; seq_num++) {
469 memcpy((char*)&input_buf[seq_num*RWL_WIFI_FRAG_DATA_SIZE],
470 (char*)&master_list[seq_num]->data, RWL_WIFI_FRAG_DATA_SIZE);
473 /* case 3 : if response is in fragments and valid data in the last frame is less
474 * than RWL_WIFI_FRAG_DATA_SIZE
476 if (remainingbytes && (totalfrag > 0))
477 memcpy((char*)&input_buf[seq_num*RWL_WIFI_FRAG_DATA_SIZE],
478 (char*)&master_list[seq_num]->data, remainingbytes);
480 if (shell) {
481 write(1, (char*)input_buf, strlen((char*)input_buf));
484 rwl_wifi_free_list(master_list);
485 return error;
488 * read out all the action frame which are queued in the driver even
489 * before issuing any wl cmd. This is essential because due to late arrival of frame it can
490 * get queued after the read expires.
492 void
493 rwl_wifi_purge_actionframes(void *wl)
495 dot11_action_wifi_vendor_specific_t *rec_frame;
496 void *ptr = NULL;
498 if ((rec_frame = (dot11_action_wifi_vendor_specific_t *)
499 malloc(RWL_WIFI_ACTION_FRAME_SIZE)) == NULL) {
500 DPRINT_DBG(OUTPUT, "Purge Error in reading the frame \n");
501 return;
504 for (;;) {
505 if (rwl_var_getbuf(wl, RWL_WIFI_GET_ACTION_CMD, rec_frame,
506 RWL_WIFI_ACTION_FRAME_SIZE, &ptr) < 0) {
507 DPRINT_DBG(OUTPUT, "rwl_wifi_purge_actionframes:"
508 "Purge Error in reading the frame \n");
509 break;
511 memcpy((char*)rec_frame, ptr, RWL_WIFI_ACTION_FRAME_SIZE);
513 if ((rec_frame->category != RWL_ACTION_WIFI_CATEGORY))
514 break;
517 free(rec_frame);
519 return;
522 * check for the channel of remote and respond if it matches with its current
523 * channel. Once the server gets the handshake cmd, it will check the channel
524 * number of the remote with its channel and if it matches , then it send out the
525 * ack to the remote client. This fucntion is used only by the server.
527 void
528 rwl_wifi_find_server_response(void *wl, dot11_action_wifi_vendor_specific_t *rec_frame)
530 int error, send, server_channel;
532 if (rec_frame->type == RWL_WIFI_FIND_MY_PEER) {
534 rec_frame->type = RWL_WIFI_FOUND_PEER;
535 /* read channel on of the SERVER */
536 rwl_wifi_config_channel(wl, WLC_GET_CHANNEL, &server_channel);
537 /* overlapping channel not supported,
538 so server will only respond to client on the channel of the client
540 if (rec_frame->data[RWL_WIFI_CLIENT_CHANNEL_OFFSET] == server_channel) {
541 /* send the response by updating server channel in the frame */
542 rec_frame->data[RWL_WIFI_SERVER_CHANNEL_OFFSET] = server_channel;
543 /* change the TYPE feild for giving the ACK */
544 for (send = 0; send < RWL_WIFI_SEND; send++) {
545 if ((error = rwl_var_send_vs_actionframe(wl,
546 RWL_WIFI_ACTION_CMD,
547 rec_frame,
548 RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
549 DPRINT_ERR(ERR, "rwl_wifi_find_server_response: Failed"
550 "to Send the Frame %d\n", error);
551 break;
553 rwl_sleep(RWL_WIFI_SEND_DELAY);
557 return;
560 * This function is used by client only. Sends the finmypeer sync frame to remote
561 * server on diffrent channels and waits for the response.
564 rwl_find_remote_wifi_server(void *wl, char *id)
566 dot11_action_wifi_vendor_specific_t *rem_wifi_send, *rem_wifi_recv;
567 rem_ioctl_t *rem_ptr = &rem_cdc;
568 /* This list is generated considering valid channel and if this
569 * may requires updation or deletion. This needs to be identified.
570 * we have assumed that server band is not known and considered all band channels.
572 int wifichannel[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
573 11, 36, 40, 44, 48, 149, 153, 157, 161, 165};
574 int i, error, schannel, channel_count;
575 struct ether_addr * curr_macaddr;
576 int ret;
577 need_speedy_response = TRUE;
579 if ((rem_wifi_send = rwl_wifi_allocate_actionframe()) == NULL) {
580 DPRINT_ERR(ERR, " rwl_find_remote_wifi_server : Failed to allocate \n");
581 return FAIL;
583 if ((rem_wifi_recv = rwl_wifi_allocate_actionframe()) == NULL) {
584 DPRINT_ERR(ERR, " rwl_find_remote_wifi_server : Failed to allocate\n");
585 free(rem_wifi_send);
586 return FAIL;
589 channel_count = sizeof(wifichannel) / sizeof(int);
591 /* make dummy read to make sure we don't read the already queued
592 * actionframes against the cmd we issue
594 rwl_wifi_purge_actionframes(wl);
596 /* update the client sync specifier */
597 rem_wifi_send->type = RWL_WIFI_FIND_MY_PEER;
598 /* update the CDC flag to indicate it is handshake frame */
599 rem_ptr->msg.cmd = 0;
600 /* cmd =0 ,this will be ignored when server receive frame
601 * with REMOTE_FINDSERVER_IOCTL flag
603 rem_ptr->msg.len = RWL_WIFI_FRAG_DATA_SIZE;
604 rem_ptr->msg.flags = REMOTE_FINDSERVER_IOCTL;
605 rem_ptr->data_len = RWL_WIFI_FRAG_DATA_SIZE;
606 rwl_swap_header(rem_ptr, HOST_TO_NETWORK);
608 memcpy((char*)&rem_wifi_send->data, (char*)rem_ptr, REMOTE_SIZE);
609 /* copy server mac to which ref driver needs to send unicast action frame */
610 memcpy((char*)&rem_wifi_send->data[RWL_REF_MAC_ADDRESS_OFFSET], &id[0], ETHER_ADDR_LEN);
612 if ((ret = rwl_var_getbuf(wl, "cur_etheraddr", NULL, 0, (void**) &curr_macaddr)) < 0) {
613 DPRINT_ERR(ERR, "Error getting current Mac addr \n");
614 return FAIL;
617 memcpy((char*)&rem_wifi_send->data[RWL_DUT_MAC_ADDRESS_OFFSET], (char*)curr_macaddr->octet,
618 ETHER_ADDR_LEN);
619 /* Start with the channel in the list and keep changing till the server
620 * responds or channels list ends
622 for (i = 0; i < channel_count; i++) {
623 DPRINT_INFO(OUTPUT, "Scanning Channel: %d ...\n", wifichannel[i]);
624 if ((error = rwl_wifi_config_channel(wl, WLC_SET_CHANNEL,
625 &wifichannel[i])) < 0) {
626 DPRINT_ERR(ERR, " Failed to set the specified channel %d\n",
627 wifichannel[i]);
628 break;
630 /* send channel detail of client to server */
631 rem_wifi_send->data[RWL_WIFI_CLIENT_CHANNEL_OFFSET] = wifichannel[i];
633 if ((error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD, rem_wifi_send,
634 RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
635 DPRINT_DBG(OUTPUT, "Failed to Send the Frame %d\n", error);
636 break;
638 /* read the server response on the same channel */
639 if ((error = remote_CDC_DATA_wifi_rx(wl, rem_wifi_recv)) < 0) {
640 rwl_sleep(RWL_CHANNEL_SCAN_WAIT);
641 continue;
643 /* Verify for the Type RWL_WIFI_FOUND_PEER */
644 if (rem_wifi_recv->type == RWL_WIFI_FOUND_PEER) {
645 if (rem_wifi_recv->data[RWL_WIFI_SERVER_CHANNEL_OFFSET] ==
646 rem_wifi_recv->data[RWL_WIFI_CLIENT_CHANNEL_OFFSET]) {
648 DPRINT_INFO(OUTPUT, "Server is on channel # %d\n",
649 rem_wifi_recv->data[RWL_WIFI_SERVER_CHANNEL_OFFSET]);
651 schannel = rem_wifi_recv->data[RWL_WIFI_SERVER_CHANNEL_OFFSET];
652 /* Set the back to the channel on which REF was originally */
653 if ((error = rwl_wifi_config_channel(wl,
654 WLC_SET_CHANNEL, &schannel) < 0)) {
655 DPRINT_ERR(ERR, "Failed to set the specified"
656 "channel %d\n", schannel);
657 } else {
658 DPRINT_ERR(ERR, "REF now moved to the"
659 "channel of server # %d\n", schannel);
661 need_speedy_response = FALSE;
662 /* we are done here, end the loop */
663 break;
664 } else {
665 DPRINT_INFO(OUTPUT, "Server is operating on diffrent channel."
666 "continue scanning\n");
669 /* before chaning the channel of client and sending sync frame
670 * wait for while and send
672 rwl_sleep(RWL_CHANNEL_SCAN_WAIT);
674 need_speedy_response = FALSE;
676 free(rem_wifi_send);
677 free(rem_wifi_recv);
678 return error;
680 #endif /* RWL_WIFI */
681 #ifdef RWL_DONGLE
682 static int
683 remote_CDC_tx_dongle(void *wl, rem_ioctl_t *rem_ptr, uchar *buf)
685 unsigned long numwritten;
686 char end_of_packet[END_OF_PACK_SEP_LEN] = "\n\n";
687 uchar loc_buf[UART_FIFO_LEN];
688 uint len = END_OF_PACK_SEP_LEN;
689 uint noframes, frame_count, rem_bytes;
690 uint n_bytes;
691 uint data_len;
693 /* Converting the CDC header with keyword 'rwl ' in ascii format
694 * as dongle UART understands only ascii format.
695 * In dongle UART driver CDC structure is made from the ascii data
696 * it received.
698 sprintf((char*)loc_buf, "rwl %d %d %d %d ", rem_ptr->msg.cmd, rem_ptr->msg.len,
699 rem_ptr->msg.flags, rem_ptr->data_len);
700 n_bytes = strlen((char*)loc_buf);
702 data_len = ltoh32(rem_ptr->data_len);
703 DPRINT_DBG(OUTPUT, "rwl %x %d %d %d ", ltoh32(rem_ptr->msg.cmd), ltoh32(rem_ptr->msg.len),
704 ltoh32(rem_ptr->msg.flags), data_len);
705 DPRINT_DBG(OUTPUT, "CDC Header:No of bytes to be sent=%d\n", n_bytes);
706 DPRINT_DBG(OUTPUT, "Data:No of bytes to be sent=%d\n", data_len);
708 /* Send the CDC Header */
709 if (rwl_write_serial_port(wl, (char*)loc_buf, n_bytes, &numwritten) < 0) {
710 DPRINT_ERR(ERR, "CDC_Tx: Header: Write failed\n");
711 DPRINT_ERR(ERR, "CDC_Tx: Header: numwritten %ld != n_bytes %d\n",
712 numwritten, n_bytes);
713 return (FAIL);
716 /* Dongle UART FIFO len is 64 bytes and flow control is absent.
717 * While transmitting large chunk of data the data was getting lost
718 * at UART driver so for large chunk of data 64 bytes are sent at a time
719 * folowed by delay and then next set of 64 bytes and so on.
720 * For data which is less than 64 bytes it is sent in one shot
723 noframes = rem_ptr->data_len/UART_FIFO_LEN;
724 if (noframes == 0) {
725 /* Send the data now */
726 if (rwl_write_serial_port(wl, (char*)buf, rem_ptr->data_len, &numwritten) < 0) {
727 DPRINT_ERR(ERR, "Data_Tx: Header: Write failed\n");
728 DPRINT_ERR(ERR, "Data_Tx: Header: numwritten %ld != len %d\n",
729 numwritten, rem_ptr->data_len);
730 return (FAIL);
733 } else {
734 if (rem_ptr->data_len % UART_FIFO_LEN == 0) {
735 rem_bytes = UART_FIFO_LEN;
736 } else {
737 rem_bytes = rem_ptr->data_len % UART_FIFO_LEN;
738 noframes += 1;
741 for (frame_count = 0; frame_count < noframes; frame_count++) {
742 if (frame_count != noframes-1) {
743 memcpy(loc_buf, (char*)(&buf[frame_count*UART_FIFO_LEN]),
744 UART_FIFO_LEN);
745 /* Send the data now */
746 if (rwl_write_serial_port(wl, (char*)loc_buf, UART_FIFO_LEN,
747 &numwritten) == -1) {
748 DPRINT_ERR(ERR, "Data_Tx: Header: Write failed\n");
749 return (-1);
752 } else {
753 memcpy(loc_buf, (char*)(&buf[frame_count*UART_FIFO_LEN]),
754 rem_bytes);
756 if (rwl_write_serial_port(wl, (char*)loc_buf, rem_bytes,
757 &numwritten) == -1) {
758 DPRINT_ERR(ERR, "Data_Tx: Header: Write failed\n");
759 return (-1);
763 rwl_sleep(SYNC_TIME);
767 /* Send end of packet now */
768 if (rwl_write_serial_port(wl, end_of_packet, len, &numwritten) == -1) {
769 DPRINT_ERR(ERR, "CDC_Tx: Header: Write failed\n");
770 DPRINT_ERR(ERR, "CDC_Tx: Header: numwritten %ld != len %d\n",
771 numwritten, len);
772 return (FAIL);
775 DPRINT_DBG(OUTPUT, "Packet sent!\n");
777 /* Return size of actual buffer to satisfy accounting going on above this level */
778 return (ltoh32(rem_ptr->msg.len));
780 #endif /* RWL_DONGLE */
782 #if defined(RWL_SERIAL) || defined(RWL_DONGLE)|| defined(RWL_SOCKET)
783 void *
784 rwl_open_pipe(int remote_type, char *port, int ReadTotalTimeout, int debug)
786 return rwl_open_transport(remote_type, port, ReadTotalTimeout, debug);
790 rwl_close_pipe(int remote_type, void* handle)
792 return rwl_close_transport(remote_type, handle);
794 #endif
797 remote_CDC_tx(void *wl, uint cmd, uchar *buf, uint buf_len, uint data_len, uint flags, int debug)
799 #if defined(RWL_SOCKET) || defined(RWL_SERIAL)
800 unsigned long numwritten = 0;
801 #endif
802 rem_ioctl_t *rem_ptr = &rem_cdc;
803 #ifdef RWL_WIFI
804 int error;
805 uint totalframes, tx_count;
806 dot11_action_wifi_vendor_specific_t *rem_wifi_send;
807 #endif
808 UNUSED_PARAMETER(debug);
810 memset(rem_ptr, 0, sizeof(rem_ioctl_t));
811 rem_ptr->msg.cmd = cmd;
812 rem_ptr->msg.len = buf_len;
813 rem_ptr->msg.flags = flags;
814 rem_ptr->data_len = data_len;
815 if (strlen(g_rem_ifname) != 0)
816 strncpy(rem_ptr->intf_name, g_rem_ifname, (int)IFNAMSIZ);
817 rwl_swap_header(rem_ptr, HOST_TO_NETWORK);
819 if (data_len > buf_len) {
820 DPRINT_ERR(ERR, "remote_CDC_tx: data_len (%d) > buf_len (%d)\n", data_len, buf_len);
821 return (FAIL);
823 #ifdef RWL_SERIAL
824 if (remote_type == REMOTE_SERIAL) {
825 int ret;
826 /* Send CDC header first */
827 if ((ret = rwl_write_serial_port(wl, (char *)rem_ptr,
828 REMOTE_SIZE, &numwritten)) == -1) {
829 DPRINT_ERR(ERR, "CDC_Tx: Data: Write failed \n");
830 return (FAIL);
832 numwritten = ret;
834 /* Send data second */
835 if ((ret = rwl_write_serial_port(wl, (char*)buf,
836 data_len, &numwritten)) == -1) {
837 DPRINT_ERR(ERR, "CDC_Tx: Data: Write failed \n");
838 return (FAIL);
840 numwritten = ret;
842 return (buf_len);
844 #endif /* RWL_SERIAL */
845 #ifdef RWL_DONGLE
846 if (remote_type == REMOTE_DONGLE) {
847 return (remote_CDC_tx_dongle(wl, rem_ptr, buf));
849 #endif /* RWL_DONGLE */
850 #ifdef RWL_SOCKET
851 if (remote_type == REMOTE_SOCKET) {
852 int ret;
854 /* Send CDC header first */
855 if ((ret = rwl_send_to_streamsocket(*(int*)wl, (char *)rem_ptr,
856 REMOTE_SIZE, 0)) == -1) {
857 DPRINT_ERR(ERR, "CDC_Tx: Data: Write failed \n");
858 return (FAIL);
860 numwritten = ret;
862 /* Send data second */
863 if ((ret = rwl_send_to_streamsocket(*(int*)wl, (const char*)buf,
864 data_len, 0)) == -1) {
865 DPRINT_ERR(ERR, "CDC_Tx: Data: Write failed \n");
866 return (FAIL);
868 numwritten = ret;
870 return (buf_len);
872 #endif /* RWL_SOCKET */
874 #ifdef RWL_WIFI
876 * wifi action frame is formed based on the CDC header and data.
877 * If the data is bigger than RWL_WIFI_FRAG_DATA_SIZE size, number of fragments are
878 * calculated and sent
879 * similar number of action frames with subtype incremented with sequence.
880 * Frames are sent with delay to avoid the outof order at receving end
882 if (remote_type == REMOTE_WIFI) {
883 if ((rem_wifi_send = rwl_wifi_allocate_actionframe()) == NULL) {
884 DPRINT_ERR(ERR, "remote_CDC_tx: Failed to get allocated buffer\n");
885 return (FAIL);
888 if (buf_len > RWL_WIFI_FRAG_DATA_SIZE) {
889 /* response needs to be sent in fragments */
890 totalframes = buf_len / RWL_WIFI_FRAG_DATA_SIZE;
891 memcpy((char*)&rem_wifi_send->data[RWL_WIFI_CDC_HEADER_OFFSET],
892 (char*)rem_ptr, REMOTE_SIZE);
893 memcpy((char*)&rem_wifi_send->data[REMOTE_SIZE], &buf[0],
894 RWL_WIFI_FRAG_DATA_SIZE);
895 /* update type feild to inform receiver it's frammeted response frame
897 rem_wifi_send->type = RWL_ACTION_WIFI_FRAG_TYPE;
898 rem_wifi_send->subtype = RWL_WIFI_DEFAULT_SUBTYPE;
900 if ((error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD,
901 rem_wifi_send, RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
902 DPRINT_DBG(OUTPUT, "Failed to Send the Frame %d\n", error);
903 free(rem_wifi_send);
904 return error;
906 /* Send remaining bytes in fragments */
907 for (tx_count = 1; tx_count < totalframes; tx_count++) {
908 rem_wifi_send->type = RWL_ACTION_WIFI_FRAG_TYPE;
909 rem_wifi_send->subtype = tx_count;
910 /* First frame onwards , buf contains only data */
911 memcpy((char*)&rem_wifi_send->data,
912 &buf[tx_count*RWL_WIFI_FRAG_DATA_SIZE], RWL_WIFI_FRAG_DATA_SIZE);
913 if ((error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD,
914 rem_wifi_send, RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
915 free(rem_wifi_send);
916 return error;
918 rwl_sleep(RWL_WIFI_SEND_DELAY);
921 /* Check for remaing bytes to send */
922 if ((totalframes*RWL_WIFI_FRAG_DATA_SIZE) != buf_len) {
923 rem_wifi_send->type = RWL_ACTION_WIFI_FRAG_TYPE;
924 rem_wifi_send->subtype = tx_count;
925 memcpy((char*)&rem_wifi_send->data,
926 &buf[tx_count*RWL_WIFI_FRAG_DATA_SIZE],
927 (buf_len - (tx_count*RWL_WIFI_FRAG_DATA_SIZE)));
928 if ((error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD,
929 rem_wifi_send, RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
930 free(rem_wifi_send);
931 return error;
934 } else {
935 /* response fits to single frame */
936 memcpy((char*)&rem_wifi_send->data[RWL_WIFI_CDC_HEADER_OFFSET],
937 (char*)rem_ptr, REMOTE_SIZE);
938 /* when data_len is 0 , buf will be NULL */
939 if (buf != NULL) {
940 memcpy((char*)&rem_wifi_send->data[REMOTE_SIZE],
941 &buf[0], data_len);
943 error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD, rem_wifi_send,
944 RWL_WIFI_ACTION_FRAME_SIZE);
945 free(rem_wifi_send);
946 return error;
949 #endif /* RWL_WIFI */
950 return (0);
954 rem_ioctl_t *
955 remote_CDC_rx_hdr(void *remote, int debug)
957 #ifdef RWL_SOCKET
958 int ret;
959 #endif /* RWL_SOCKET */
960 uint numread = 0;
961 rem_ioctl_t *rem_ptr = &rem_cdc;
962 memset(rem_ptr, 0, sizeof(rem_ioctl_t));
964 #ifdef RWL_WIFI
965 UNUSED_PARAMETER(remote);
966 UNUSED_PARAMETER(numread);
967 #endif /* RWL_WIFI */
969 UNUSED_PARAMETER(debug);
971 switch (remote_type) {
972 #if defined(RWL_SERIAL) || defined(RWL_DONGLE)
973 case REMOTE_SERIAL:
974 case REMOTE_DONGLE:
975 if (rwl_read_serial_port(remote, (char *)rem_ptr, sizeof(rem_ioctl_t),
976 &numread) < 0) {
977 DPRINT_ERR(ERR, "remote_CDC_rx_hdr: Header Read failed \n");
978 return (NULL);
980 break;
981 #endif /* RWL_SERIAL | RWL_DONGLE */
984 #ifdef RWL_SOCKET
985 case REMOTE_SOCKET:
986 ret = rwl_receive_from_streamsocket(*(int*)remote, (char *)rem_ptr,
987 sizeof(rem_ioctl_t), 0);
988 numread = ret;
989 if (ret == -1) {
990 DPRINT_ERR(ERR, "remote_CDC_rx_hdr: numread:%d", numread);
991 return (NULL);
993 if (numread == 0) {
994 DPRINT_DBG(OUTPUT, "\n remote_CDC_rx_hdr:No data to receive\n");
995 return NULL;
997 break;
998 #endif
999 default:
1000 DPRINT_ERR(ERR, "\n Unknown Transport Type\n");
1001 break;
1004 return (rem_ptr);
1007 /* Return a CDC type buffer */
1009 remote_CDC_rx(void *wl, rem_ioctl_t *rem_ptr, uchar *readbuf, uint buflen, int debug)
1011 uint numread = 0;
1013 #ifdef RWL_SOCKET
1014 int ret;
1015 #endif
1017 #ifdef RWL_WIFI
1018 UNUSED_PARAMETER(wl);
1019 UNUSED_PARAMETER(readbuf);
1020 UNUSED_PARAMETER(numread);
1021 #endif /* RWL_WIFI */
1022 UNUSED_PARAMETER(buflen);
1023 UNUSED_PARAMETER(debug);
1024 UNUSED_PARAMETER(numread);
1026 if (rem_ptr->data_len > rem_ptr->msg.len) {
1027 DPRINT_ERR(ERR, "remote_CDC_rx: remote data len (%d) > msg len (%d)\n",
1028 rem_ptr->data_len, rem_ptr->msg.len);
1029 return (FAIL);
1033 #if defined(RWL_DONGLE) || defined(RWL_SERIAL)
1034 if ((remote_type == REMOTE_DONGLE) || (remote_type == REMOTE_SERIAL)) {
1035 if (rwl_read_serial_port(wl, (char*)readbuf, rem_ptr->data_len,
1036 &numread) < 0) {
1037 DPRINT_ERR(ERR, "remote_CDC_rx_hdr: Data Receivefailed \n");
1038 return (FAIL);
1041 #endif /* RWL_DONGLE || RWL_SERIAL */
1043 #ifdef RWL_SOCKET
1044 if (remote_type == REMOTE_SOCKET) {
1045 if (((ret = rwl_receive_from_streamsocket(*(int*)wl, (char*)readbuf,
1046 rem_ptr->data_len, 0)) == -1)) {
1047 DPRINT_ERR(ERR, "remote_CDC_rx:Data Receive failed\n");
1048 return (FAIL);
1051 #endif /* RWL_SOCKET */
1052 return (SUCCESS);
1054 #ifdef RWL_SOCKET
1056 rwl_sockconnect(int SockDes, struct sockaddr *servAddr, int size)
1058 DPRINT_DBG(OUTPUT, "sockconnet SockDes=%d\n", SockDes);
1059 if (rwl_connectsocket(SockDes, servAddr, size) < 0) {
1060 DPRINT_ERR(ERR, "\n Server is not running\n");
1061 return FAIL;
1063 return SUCCESS;
1065 #endif /* RWL_SOCKET */
1066 void
1067 rwl_swap_header(rem_ioctl_t *rem_ptr, bool host_to_network)
1069 rem_ptr->msg.cmd = host_to_network?(htol32(rem_ptr->msg.cmd)):(ltoh32(rem_ptr->msg.cmd));
1070 rem_ptr->msg.len = host_to_network?(htol32(rem_ptr->msg.len)):(ltoh32(rem_ptr->msg.len));
1071 rem_ptr->msg.flags = host_to_network?(htol32(rem_ptr->msg.flags)):
1072 (ltoh32(rem_ptr->msg.flags));
1073 rem_ptr->msg.status = host_to_network?(htol32(rem_ptr->msg.status)):
1074 (ltoh32(rem_ptr->msg.status));
1075 rem_ptr->data_len = host_to_network?(htol32(rem_ptr->data_len)):(ltoh32(rem_ptr->data_len));