Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/next/external/cache/sources/wl/shared/wlu_pipe.c
Views: 3959
/*1* Common Functionality for pipe2*3* $Copyright (C) 2008 Broadcom Corporation$4*5* $Id: wlu_pipe.c 385622 2013-02-16 03:40:23Z jwang $6*/7#ifdef WIN328#define NEED_IR_TYPES910#include <windows.h>11#ifdef UNDER_CE12/* Expected order for succesfull compliation */13#include <winsock2.h>14#endif15#include <epictrl.h>16#include <irelay.h>17#endif /* WIN32 */1819#ifdef LINUX20#include <sys/types.h>21#include <sys/socket.h>22#include <arpa/inet.h>23#include <unistd.h>24#include <netdb.h>25#include <signal.h>26#include <sys/ioctl.h>27#include <wlioctl.h>28#include <net/if.h>29#endif3031#ifdef vxworks32#include "wlu_vx.h"33#include "inetLib.h"34#endif35#include <stdio.h>36#include <stdlib.h>37#include <string.h>38#include <ctype.h>39#ifdef TARGETOS_symbian40#include <sys/types.h>41#include <sys/socket.h>42#include <netinet/in.h>43#else44#if !defined(TARGETOS_nucleus) && !defined (MACOSX) && !defined (vxworks)45#include <malloc.h>46#endif47#endif /* TARGETOS_symbian */48#include <typedefs.h>49#include <wlioctl.h>5051#include <proto/ethernet.h>52#include <bcmendian.h>53#include <bcmutils.h>54#include <bcmcdc.h>55#include <proto/802.11.h>56#if defined(RWL_WIFI) || defined(WIFI_REFLECTOR)57#include <rwl_wifi.h>58#endif /* defined(RWL_WIFI) || defined(WIFI_REFLECTOR) */59#include "wlu.h"60#include "wlu_remote.h"6162static rem_ioctl_t rem_cdc;63char *g_rwl_device_name_serial = "";64bool g_rwl_swap = FALSE;65char g_rem_ifname[IFNAMSIZ] = "\0";66int need_speedy_response; /* Indicate findserver is checking channels */6768#ifdef LINUX69/* Linux 100 usec */70#define SYNC_TIME 10071#else72/* WinXP 1 sec */73#define SYNC_TIME 174#endif7576#define UART_FIFO_LEN 6477#define END_OF_PACK_SEP_LEN 278#define INIT_CMD_SLEEP 50079#define dtoh32(i) i8081/* dword align allocation */82union {83uchar bufdata[ETHER_ADDR_LEN];84uint32 alignme;85} bufmac_wlu;86char *g_rwl_buf_mac = (char*) &bufmac_wlu.bufdata;8788#ifdef RWL_WIFI89/* dword align allocation */90union {91uchar shelldata[WL_MAX_BUF_LEN];92uint32 alignme;93} shell_wlu;94char *g_rwl_buf_shell = (char*) &shell_wlu.shelldata;95int rwl_find_remote_wifi_server(void *wl, char *id);96int wl_ioctl(void *wl, int cmd, void *buf, int len, bool set);9798/*99* This function runs a set of commands before running the wi-fi server100* This is avoids packet drops and improves performance.101* We run the following wl commands102* up, mpc 0, wsec 0, slow_timer 999999, fast_timer 999999, glacial_timer 999999103* legacylink 1, monitor 1.104*/105void remote_wifi_ser_init_cmds(void *wl)106{107int err;108char bigbuf[RWL_WIFI_BUF_LEN];109uint len = 0, count;110/* The array stores command, length and then data format */111remote_wifi_cmds_t wifi_cmds[] = {112{WLC_UP, NULL, 0x0},113{WLC_SET_VAR, "mpc", 0},114{WLC_SET_WSEC, NULL, 0x0},115{WLC_SET_VAR, "slow_timer", 999999},116{WLC_SET_VAR, "fast_timer", 999999},117{WLC_SET_VAR, "glacial_timer", 999999},118{WLC_SET_MONITOR, NULL, 0x1},119{WLC_SET_PM, NULL, 0x0}120};121122for (count = 0; count < ARRAYSIZE(wifi_cmds); count++) {123124if (wifi_cmds[count].data == NULL)125len = sizeof(int);126else127len = strlen(wifi_cmds[count].data) + 1 + sizeof(int);128129/* If the command length exceeds the buffer length continue130* executing the next command131*/132if (len > sizeof(bigbuf)) {133DPRINT_ERR(ERR, "Err: command len exceeds buf len. Check"134"initialization cmds\n");135continue;136}137138if (wifi_cmds[count].data != NULL) {139strcpy(bigbuf, wifi_cmds[count].data);140memcpy(&bigbuf[strlen(wifi_cmds[count].data)+1],141(char*)&wifi_cmds[count].value, sizeof(int));142} else {143memcpy(&bigbuf[0], (char*)&wifi_cmds[count].value, sizeof(int));144}145#ifdef WIN32146/* Add OID base for NDIS commands */147148err = (int)ir_setinformation(wl, wifi_cmds[count].cmd + WL_OID_BASE,149bigbuf, &len);150#endif151152#if defined(LINUX) || defined(TARGETOS_symbian) || defined(MACOSX)153if (wifi_cmds[count].cmd == WLC_UP)154/* NULL needs to be passed to the driver if WL UP command needs to155* be executed Otherwise driver hangs156*/157err = wl_ioctl(wl, wifi_cmds[count].cmd,158NULL, 0, TRUE);159else160err = wl_ioctl(wl, wifi_cmds[count].cmd,161(void*)&bigbuf, len, TRUE);162163#elif vxworks164if (wifi_cmds[count].cmd == WLC_UP) {165/* NULL needs to be passed to the driver if WL UP command needs to166* be executed Otherwise driver hangs167*/168if ((err = wl_ioctl_vx(wl, wifi_cmds[count].cmd,169NULL, 0)) == FAIL)170DPRINT_ERR(ERR, "wifi_cmds: Error in wl_ioctl_vx\n");171}172else {173if ((err = wl_ioctl_vx(wl, wifi_cmds[count].cmd,174(void*)&bigbuf, len)) == FAIL)175DPRINT_ERR(ERR, "remote_wifi_ser_init_cmds:Error in wl_ioctl_vx\n");176}177#endif /* LINUX || TARGETOS_symbian || MACOSX */178rwl_sleep(INIT_CMD_SLEEP);179}180BCM_REFERENCE(err);181}182183/* When user wants to execute local CMD being in remote wifi mode, this fucntion is used184* to change the remote types.185* This fucntion is called to swap the remote type to execute the cmd using the local186* driver interface.187* This is required for to call proper front end fucntions to achive the local set/get ioctl.188*/189void190rwl_wifi_swap_remote_type(int flag)191{192static int remote_flag;193if (flag == REMOTE_WIFI) {194remote_type = NO_REMOTE;195remote_flag = flag;196} else if (remote_flag == REMOTE_WIFI) {197remote_type = remote_flag;198remote_flag = flag;199}200return;201}202203void204rwl_wifi_free_list(dot11_action_wifi_vendor_specific_t *list[])205{206int i;207for (i = 0; i < RWL_DEFAULT_WIFI_FRAG_COUNT; i++) {208if (list[i])209free(list[i]);210}211}212213/*214* Configures local channel for finding server.215* Server call this fucntion for getting its current channel,216* client uses this fucntion for setting its channel to new channel.217*/218static int219rwl_wifi_config_channel(void *wl, int cmd, int *channel)220{221int error;222channel_info_t ci;223error = -1;224/* Get functionality is used only by server */225if (cmd == WLC_GET_CHANNEL) {226memset((char*)&ci, 0, sizeof(ci));227if ((error = wl_get(wl, cmd, &ci, sizeof(channel_info_t))) < 0)228return error;229ci.hw_channel = dtoh32(ci.hw_channel);230ci.scan_channel = dtoh32(ci.scan_channel);231ci.target_channel = dtoh32(ci.target_channel);232if (ci.scan_channel) {233printf("Scan in progress.\n");234}235*channel = ci.hw_channel;236}237238if (cmd == WLC_SET_CHANNEL) {239/* Set functionality is used by the client */240ci.target_channel = *channel;241/* When user wants to execute local CMD being in remote wifi mode,242* rwl_wifi_swap_remote_type fucntion is used to change the remote types.243*/244rwl_wifi_swap_remote_type(remote_type);245error = wl_set(wl, cmd, &ci.target_channel, sizeof(int));246/* rever it back to same old remote type */247rwl_wifi_swap_remote_type(remote_type);248}249return error;250}251/*252allocate the memory for action frame and update with wifi tranport header.253*/254dot11_action_wifi_vendor_specific_t *255rwl_wifi_allocate_actionframe()256{257dot11_action_wifi_vendor_specific_t *action_frame;258259if ((action_frame = (dot11_action_wifi_vendor_specific_t *)260malloc(RWL_WIFI_ACTION_FRAME_SIZE)) == NULL) {261DPRINT_ERR(ERR, "rwl_wifi_allocate_actionframe: unable to allocate frame \n");262return action_frame;263}264action_frame->category = RWL_ACTION_WIFI_CATEGORY;265action_frame->OUI[0] = RWL_WIFI_OUI_BYTE0;266action_frame->OUI[1] = RWL_WIFI_OUI_BYTE1;267action_frame->OUI[2] = RWL_WIFI_OUI_BYTE2;268action_frame->type = RWL_WIFI_DEFAULT_TYPE;269action_frame->subtype = RWL_WIFI_DEFAULT_SUBTYPE;270271return action_frame;272}273/*274* Send the valid action frame (CDC+DATA) through the REF driver interface.275* if the CMD is "findserver" then "findmypeer" frames are sent on the diffrent276* channels to reconnect277* to with server. Other wl cmd takes the normal path.278* parameter 3 , i.e. buf contains the cmd line arguments and buf_len is the actual279* length of the buf. data_len is the length of the actual data to be sent to remote server.280*/281int282remote_CDC_wifi_tx(void *wl, uint cmd, uchar *buf, uint buf_len, uint data_len, uint flags)283{284rem_ioctl_t *rem_ptr = &rem_cdc;285int error, read_try;286dot11_action_wifi_vendor_specific_t *rem_wifi_send;287288/* prepare CDC header */289rem_ptr->msg.cmd = cmd;290rem_ptr->msg.len = buf_len;291rem_ptr->msg.flags = flags;292rem_ptr->data_len = data_len;293#ifndef OLYMPIC_RWL294if (strlen(g_rem_ifname) != 0)295strncpy(rem_ptr->intf_name, g_rem_ifname, (int)IFNAMSIZ);296rwl_swap_header(rem_ptr, HOST_TO_NETWORK);297#endif298299if ((data_len > buf_len)) {300DPRINT_ERR(ERR, "remote_CDC_wifi_tx: data_len (%d) > buf_len (%d)\n",301data_len, buf_len);302return (FAIL);303}304/* client will not send data greater than RWL_WIFI_FRAG_DATA_SIZE to server,305* this condition should not be hit on client side, when sending the cmd306* to remote server307*/308if (data_len > RWL_WIFI_FRAG_DATA_SIZE)309DPRINT_DBG(OUTPUT, "data size exceeds data_len %d\n", rem_ptr->msg.len);310311if ((buf != NULL) && (strlen((char*)buf) >= (sizeof(RWL_WIFI_FIND_SER_CMD)-1)) &&312(!strcmp((char*)buf, RWL_WIFI_FIND_SER_CMD))) {313/* This is special case for wifi, when user wants to findserver,314* client has to execute it locally.Find the channel on the on315* which DUT is operating and sync up with specified MAC address,316* retry if fails to find the server317*/318for (read_try = 0; read_try < RWL_WIFI_RETRY; read_try++) {319if (((error = rwl_find_remote_wifi_server(wl,320&g_rwl_buf_mac[0])) == 0)) {321break;322}323}324return error;325}326327if ((rem_wifi_send = rwl_wifi_allocate_actionframe()) == NULL) {328DPRINT_ERR(ERR, "remote_CDC_wifi_tx: Failed to allocate memory\n");329return (FAIL);330}331/* only data length needs to be sent to remote server using this function332* This function is only meant for client to send data to server333* Copy the CDC header and data to action frame data feild334* Now we have encapsulated the CDC header and data completely to in the335* action frame.336*/337memcpy((void*)&rem_wifi_send->data[RWL_WIFI_CDC_HEADER_OFFSET],338(char*)rem_ptr, REMOTE_SIZE);339if (buf != NULL) {340memcpy((void*)&rem_wifi_send->data[REMOTE_SIZE], buf, data_len);341}342343/* Send the action frame to remote server using the rwl_var_setbuf fucntion,344* which will use the local driver interface to send this frame on the air345*/346if ((error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD, rem_wifi_send,347RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {348DPRINT_ERR(ERR, "Unable to read the action frame %d error\n", error);349}350free(rem_wifi_send);351return error;352}353354/*355* Read the valid action frame through the REF/DUT driver interface.356* Retry for no of times, wait for action frame for the specified time.357*/358int359remote_CDC_DATA_wifi_rx(void *wl, dot11_action_wifi_vendor_specific_t * rec_frame)360{361int error, read_try;362void *ptr = NULL;363364365/* retry is to ensure to read late arrival action frame */366for (read_try = 0; read_try < RWL_WIFI_RX_RETRY; read_try++) {367/* read the action frame queued in the local driver wifi queue */368if ((error = rwl_var_getbuf(wl, RWL_WIFI_GET_ACTION_CMD, rec_frame,369RWL_WIFI_ACTION_FRAME_SIZE, &ptr)) < 0) {370DPRINT_ERR(ERR, "remote_CDC_DATA_wifi_rx: Error in reading the frame %d\n",371error);372return error;373}374/* copy the read action frame to the user frame and cjheck for the action category.375* If the action category matches with RWL_ACTION_WIFI_CATEGORY ,376* then its the valid frame, otherwise ignore it.377*/378memcpy((char*)rec_frame, ptr, RWL_WIFI_ACTION_FRAME_SIZE);379380if (rec_frame->category == RWL_ACTION_WIFI_CATEGORY) {381break;382} else {383/* If we are executing findserver then sleep less */384if (!need_speedy_response)385rwl_sleep(RWL_WIFI_RX_DELAY);386else387rwl_sleep(RWL_CHANNEL_RX_SCAN_DELAY);388}389}390/* If failed to get the valid frame , indicate the error */391if (!(rec_frame->category == RWL_ACTION_WIFI_CATEGORY)) {392return (FAIL);393}394return error;395}396/*397* read data that has reached client in fragments. If the functtion is398* called from rwl_shell_information_fe then the flag will be set to 1.399* For shell response this function will output the response on the standard interface.400* Response will be coming in out of order , this fucntion will make it inorder.401* Duplicate action frames are ignored.402*/403int404remote_CDC_DATA_wifi_rx_frag(void *wl, rem_ioctl_t *rem_ptr, uint input_len,405void *input, bool shell)406{407int error, totalfrag, seq_num, num_frags, remainingbytes;408dot11_action_wifi_vendor_specific_t *rec_frame;409uchar *input_buf = (uchar*)input;410/* An array of pointers to each recieved frag */411dot11_action_wifi_vendor_specific_t *master_list[RWL_DEFAULT_WIFI_FRAG_COUNT];412413UNUSED_PARAMETER(input_len);414remainingbytes = 0;415416memset(master_list, 0, sizeof(master_list));417/* in case of shell cmd's receive size is unknown */418if (shell) {419input_buf = (uchar*)g_rwl_buf_shell;420memset(input_buf, 0, WL_MAX_BUF_LEN);421}422423/* We don't yet know how many fragments we will need to read since the424length is contained in the first frgment of the message itself. Set425totalfrag to an arbitry large number and we will readjust it after we426successfully recieve the first frag.427*/428totalfrag = RWL_DEFAULT_WIFI_FRAG_COUNT;429430for (num_frags = 0; num_frags <= totalfrag; num_frags++) {431if ((rec_frame = rwl_wifi_allocate_actionframe()) == NULL) {432DPRINT_DBG(OUTPUT, "malloc failure\n");433rwl_wifi_free_list(master_list);434return (FAIL);435}436if ((error = remote_CDC_DATA_wifi_rx((void*)wl, rec_frame)) < 0) {437free(rec_frame);438rwl_wifi_free_list(master_list);439return FAIL;440}441442if (rec_frame->subtype >= RWL_DEFAULT_WIFI_FRAG_COUNT) {443DPRINT_DBG(OUTPUT, " Read bogus subtype %d\n", rec_frame->subtype);444free(rec_frame);445continue;446}447/* Keep only originals and discard any dup frags */448if (!master_list[rec_frame->subtype]) {449master_list[rec_frame->subtype] = rec_frame;450} else {451num_frags--;452free(rec_frame);453}454455/* Look for first frag so we can accurately calculate totalfrag */456if (rec_frame->subtype == RWL_WIFI_DEFAULT_SUBTYPE) {457memcpy((char*)rem_ptr,458(char*)&master_list[rec_frame->subtype]->459data[RWL_WIFI_CDC_HEADER_OFFSET], REMOTE_SIZE);460rwl_swap_header(rem_ptr, NETWORK_TO_HOST);461totalfrag = rem_ptr->msg.len / RWL_WIFI_FRAG_DATA_SIZE;462remainingbytes = rem_ptr->msg.len % RWL_WIFI_FRAG_DATA_SIZE;463}464}465466/* All frags are now read and there are no dups. Check for missing frags */467for (seq_num = 0; seq_num < totalfrag; seq_num++) {468if (!master_list[seq_num]) {469DPRINT_DBG(OUTPUT, "Missing frag number %d\n", seq_num);470rwl_wifi_free_list(master_list);471return (FAIL);472}473}474/*475case 1: response in one frame i.e if (totalfrag==0)476case 2: response in multiple frame ( multiple of RWL_WIFI_FRAG_DATA_SIZE)477case 3: response in multiple frame and not in multiple of RWL_WIFI_FRAG_DATA_SIZE478*/479480/* case 1: Check for the response in single frame */481if (totalfrag == 0)482memcpy((char*)&input_buf[0],483(char*)&master_list[0]->data[REMOTE_SIZE], rem_ptr->msg.len);484else /* case 2: Copy fragments into contiguous frame */485memcpy((char*)&input_buf[0],486(char*)&master_list[0]->data[REMOTE_SIZE], RWL_WIFI_FRAG_DATA_SIZE);487488/*489* If all the frames are recieved , copy them to a contigues buffer490*/491for (seq_num = 1; seq_num < totalfrag; seq_num++) {492memcpy((char*)&input_buf[seq_num*RWL_WIFI_FRAG_DATA_SIZE],493(char*)&master_list[seq_num]->data, RWL_WIFI_FRAG_DATA_SIZE);494}495496/* case 3 : if response is in fragments and valid data in the last frame is less497* than RWL_WIFI_FRAG_DATA_SIZE498*/499if (remainingbytes && (totalfrag > 0))500memcpy((char*)&input_buf[seq_num*RWL_WIFI_FRAG_DATA_SIZE],501(char*)&master_list[seq_num]->data, remainingbytes);502503if (shell) {504#ifdef LINUX505write(1, (char*)input_buf, strlen((char*)input_buf));506#else507fputs((char*)input_buf, stdout);508#endif /* LINUX */509}510511rwl_wifi_free_list(master_list);512return error;513}514/*515* read out all the action frame which are queued in the driver even516* before issuing any wl cmd. This is essential because due to late arrival of frame it can517* get queued after the read expires.518*/519void520rwl_wifi_purge_actionframes(void *wl)521{522dot11_action_wifi_vendor_specific_t *rec_frame;523void *ptr = NULL;524525if ((rec_frame = (dot11_action_wifi_vendor_specific_t *)526malloc(RWL_WIFI_ACTION_FRAME_SIZE)) == NULL) {527DPRINT_DBG(OUTPUT, "Purge Error in reading the frame \n");528return;529}530531for (;;) {532if (rwl_var_getbuf(wl, RWL_WIFI_GET_ACTION_CMD, rec_frame,533RWL_WIFI_ACTION_FRAME_SIZE, &ptr) < 0) {534DPRINT_DBG(OUTPUT, "rwl_wifi_purge_actionframes:"535"Purge Error in reading the frame \n");536break;537}538memcpy((char*)rec_frame, ptr, RWL_WIFI_ACTION_FRAME_SIZE);539540if ((rec_frame->category != RWL_ACTION_WIFI_CATEGORY))541break;542}543544free(rec_frame);545546return;547}548/*549* check for the channel of remote and respond if it matches with its current550* channel. Once the server gets the handshake cmd, it will check the channel551* number of the remote with its channel and if it matches , then it send out the552* ack to the remote client. This fucntion is used only by the server.553*/554void555rwl_wifi_find_server_response(void *wl, dot11_action_wifi_vendor_specific_t *rec_frame)556{557int error, send, server_channel;558559if (rec_frame->type == RWL_WIFI_FIND_MY_PEER) {560561rec_frame->type = RWL_WIFI_FOUND_PEER;562/* read channel on of the SERVER */563rwl_wifi_config_channel(wl, WLC_GET_CHANNEL, &server_channel);564/* overlapping channel not supported,565so server will only respond to client on the channel of the client566*/567if (rec_frame->data[RWL_WIFI_CLIENT_CHANNEL_OFFSET] == server_channel) {568/* send the response by updating server channel in the frame */569rec_frame->data[RWL_WIFI_SERVER_CHANNEL_OFFSET] = server_channel;570/* change the TYPE feild for giving the ACK */571for (send = 0; send < RWL_WIFI_SEND; send++) {572if ((error = rwl_var_send_vs_actionframe(wl,573RWL_WIFI_ACTION_CMD,574rec_frame,575RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {576DPRINT_ERR(ERR, "rwl_wifi_find_server_response: Failed"577"to Send the Frame %d\n", error);578break;579}580rwl_sleep(RWL_WIFI_SEND_DELAY);581}582}583}584return;585}586/*587* This function is used by client only. Sends the finmypeer sync frame to remote588* server on diffrent channels and waits for the response.589*/590int591rwl_find_remote_wifi_server(void *wl, char *id)592{593dot11_action_wifi_vendor_specific_t *rem_wifi_send, *rem_wifi_recv;594rem_ioctl_t *rem_ptr = &rem_cdc;595/* This list is generated considering valid channel and if this596* may requires updation or deletion. This needs to be identified.597* we have assumed that server band is not known and considered all band channels.598*/599int wifichannel[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,60011, 36, 40, 44, 48, 149, 153, 157, 161, 165};601int i, error, schannel, channel_count;602struct ether_addr * curr_macaddr;603int ret;604need_speedy_response = TRUE;605606if ((rem_wifi_send = rwl_wifi_allocate_actionframe()) == NULL) {607DPRINT_ERR(ERR, " rwl_find_remote_wifi_server : Failed to allocate \n");608return FAIL;609}610if ((rem_wifi_recv = rwl_wifi_allocate_actionframe()) == NULL) {611DPRINT_ERR(ERR, " rwl_find_remote_wifi_server : Failed to allocate\n");612free(rem_wifi_send);613return FAIL;614}615616channel_count = sizeof(wifichannel) / sizeof(int);617618/* make dummy read to make sure we don't read the already queued619* actionframes against the cmd we issue620*/621rwl_wifi_purge_actionframes(wl);622623/* update the client sync specifier */624rem_wifi_send->type = RWL_WIFI_FIND_MY_PEER;625/* update the CDC flag to indicate it is handshake frame */626rem_ptr->msg.cmd = 0;627/* cmd =0 ,this will be ignored when server receive frame628* with REMOTE_FINDSERVER_IOCTL flag629*/630rem_ptr->msg.len = RWL_WIFI_FRAG_DATA_SIZE;631rem_ptr->msg.flags = REMOTE_FINDSERVER_IOCTL;632rem_ptr->data_len = RWL_WIFI_FRAG_DATA_SIZE;633rwl_swap_header(rem_ptr, HOST_TO_NETWORK);634635memcpy((char*)&rem_wifi_send->data, (char*)rem_ptr, REMOTE_SIZE);636/* copy server mac to which ref driver needs to send unicast action frame */637memcpy((char*)&rem_wifi_send->data[RWL_REF_MAC_ADDRESS_OFFSET], &id[0], ETHER_ADDR_LEN);638639if ((ret = rwl_var_getbuf(wl, "cur_etheraddr", NULL, 0, (void**) &curr_macaddr)) < 0) {640DPRINT_ERR(ERR, "Error getting current Mac addr \n");641return FAIL;642}643644memcpy((char*)&rem_wifi_send->data[RWL_DUT_MAC_ADDRESS_OFFSET], (char*)curr_macaddr->octet,645ETHER_ADDR_LEN);646/* Start with the channel in the list and keep changing till the server647* responds or channels list ends648*/649for (i = 0; i < channel_count; i++) {650DPRINT_INFO(OUTPUT, "Scanning Channel: %d ...\n", wifichannel[i]);651if ((error = rwl_wifi_config_channel(wl, WLC_SET_CHANNEL,652&wifichannel[i])) < 0) {653DPRINT_ERR(ERR, " Failed to set the specified channel %d\n",654wifichannel[i]);655break;656}657/* send channel detail of client to server */658rem_wifi_send->data[RWL_WIFI_CLIENT_CHANNEL_OFFSET] = wifichannel[i];659660if ((error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD, rem_wifi_send,661RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {662DPRINT_DBG(OUTPUT, "Failed to Send the Frame %d\n", error);663break;664}665/* read the server response on the same channel */666if ((error = remote_CDC_DATA_wifi_rx(wl, rem_wifi_recv)) < 0) {667rwl_sleep(RWL_CHANNEL_SCAN_WAIT);668continue;669}670/* Verify for the Type RWL_WIFI_FOUND_PEER */671if (rem_wifi_recv->type == RWL_WIFI_FOUND_PEER) {672if (rem_wifi_recv->data[RWL_WIFI_SERVER_CHANNEL_OFFSET] ==673rem_wifi_recv->data[RWL_WIFI_CLIENT_CHANNEL_OFFSET]) {674675DPRINT_INFO(OUTPUT, "Server is on channel # %d\n",676rem_wifi_recv->data[RWL_WIFI_SERVER_CHANNEL_OFFSET]);677678schannel = rem_wifi_recv->data[RWL_WIFI_SERVER_CHANNEL_OFFSET];679/* Set the back to the channel on which REF was originally */680if ((error = rwl_wifi_config_channel(wl,681WLC_SET_CHANNEL, &schannel) < 0)) {682DPRINT_ERR(ERR, "Failed to set the specified"683"channel %d\n", schannel);684} else {685DPRINT_ERR(ERR, "REF now moved to the"686"channel of server # %d\n", schannel);687}688need_speedy_response = FALSE;689/* we are done here, end the loop */690break;691} else {692DPRINT_INFO(OUTPUT, "Server is operating on diffrent channel."693"continue scanning\n");694}695}696/* before chaning the channel of client and sending sync frame697* wait for while and send698*/699rwl_sleep(RWL_CHANNEL_SCAN_WAIT);700}701need_speedy_response = FALSE;702703free(rem_wifi_send);704free(rem_wifi_recv);705return error;706}707#endif /* RWL_WIFI */708#ifdef RWL_DONGLE709static int710remote_CDC_tx_dongle(void *wl, rem_ioctl_t *rem_ptr, uchar *buf)711{712unsigned long numwritten;713char end_of_packet[END_OF_PACK_SEP_LEN] = "\n\n";714uchar loc_buf[UART_FIFO_LEN];715uint len = END_OF_PACK_SEP_LEN;716uint noframes, frame_count, rem_bytes;717uint n_bytes;718uint data_len;719720/* Converting the CDC header with keyword 'rwl ' in ascii format721* as dongle UART understands only ascii format.722* In dongle UART driver CDC structure is made from the ascii data723* it received.724*/725sprintf((char*)loc_buf, "rwl %d %d %d %d ", rem_ptr->msg.cmd, rem_ptr->msg.len,726rem_ptr->msg.flags, rem_ptr->data_len);727n_bytes = strlen((char*)loc_buf);728729data_len = ltoh32(rem_ptr->data_len);730DPRINT_DBG(OUTPUT, "rwl %x %d %d %d ", ltoh32(rem_ptr->msg.cmd), ltoh32(rem_ptr->msg.len),731ltoh32(rem_ptr->msg.flags), data_len);732DPRINT_DBG(OUTPUT, "CDC Header:No of bytes to be sent=%d\n", n_bytes);733DPRINT_DBG(OUTPUT, "Data:No of bytes to be sent=%d\n", data_len);734735/* Send the CDC Header */736if (rwl_write_serial_port(wl, (char*)loc_buf, n_bytes, &numwritten) < 0) {737DPRINT_ERR(ERR, "CDC_Tx: Header: Write failed\n");738DPRINT_ERR(ERR, "CDC_Tx: Header: numwritten %ld != n_bytes %d\n",739numwritten, n_bytes);740return (FAIL);741}742743/* Dongle UART FIFO len is 64 bytes and flow control is absent.744* While transmitting large chunk of data the data was getting lost745* at UART driver so for large chunk of data 64 bytes are sent at a time746* folowed by delay and then next set of 64 bytes and so on.747* For data which is less than 64 bytes it is sent in one shot748*/749750noframes = rem_ptr->data_len/UART_FIFO_LEN;751if (noframes == 0) {752/* Send the data now */753if (rwl_write_serial_port(wl, (char*)buf, rem_ptr->data_len, &numwritten) < 0) {754DPRINT_ERR(ERR, "Data_Tx: Header: Write failed\n");755DPRINT_ERR(ERR, "Data_Tx: Header: numwritten %ld != len %d\n",756numwritten, rem_ptr->data_len);757return (FAIL);758}759760} else {761if (rem_ptr->data_len % UART_FIFO_LEN == 0) {762rem_bytes = UART_FIFO_LEN;763} else {764rem_bytes = rem_ptr->data_len % UART_FIFO_LEN;765noframes += 1;766}767768for (frame_count = 0; frame_count < noframes; frame_count++) {769if (frame_count != noframes-1) {770memcpy(loc_buf, (char*)(&buf[frame_count*UART_FIFO_LEN]),771UART_FIFO_LEN);772/* Send the data now */773if (rwl_write_serial_port(wl, (char*)loc_buf, UART_FIFO_LEN,774&numwritten) == -1) {775DPRINT_ERR(ERR, "Data_Tx: Header: Write failed\n");776return (-1);777}778779} else {780memcpy(loc_buf, (char*)(&buf[frame_count*UART_FIFO_LEN]),781rem_bytes);782783if (rwl_write_serial_port(wl, (char*)loc_buf, rem_bytes,784&numwritten) == -1) {785DPRINT_ERR(ERR, "Data_Tx: Header: Write failed\n");786return (-1);787}788789}790rwl_sleep(SYNC_TIME);791}792}793794/* Send end of packet now */795if (rwl_write_serial_port(wl, end_of_packet, len, &numwritten) == -1) {796DPRINT_ERR(ERR, "CDC_Tx: Header: Write failed\n");797DPRINT_ERR(ERR, "CDC_Tx: Header: numwritten %ld != len %d\n",798numwritten, len);799return (FAIL);800}801802DPRINT_DBG(OUTPUT, "Packet sent!\n");803804/* Return size of actual buffer to satisfy accounting going on above this level */805return (ltoh32(rem_ptr->msg.len));806}807#endif /* RWL_DONGLE */808809#if defined (RWL_SERIAL) || defined (RWL_DONGLE)|| defined (RWL_SOCKET)810void *811rwl_open_pipe(int remote_type, char *port, int ReadTotalTimeout, int debug)812{813return rwl_open_transport(remote_type, port, ReadTotalTimeout, debug);814}815816int817rwl_close_pipe(int remote_type, void* handle)818{819return rwl_close_transport(remote_type, handle);820}821#endif822823int824remote_CDC_tx(void *wl, uint cmd, uchar *buf, uint buf_len, uint data_len, uint flags, int debug)825{826#ifdef RWL_SERIAL827unsigned long numwritten = 0;828#endif829rem_ioctl_t *rem_ptr = &rem_cdc;830#ifdef RWL_WIFI831int error;832uint totalframes, tx_count;833dot11_action_wifi_vendor_specific_t *rem_wifi_send;834#endif835UNUSED_PARAMETER(debug);836UNUSED_PARAMETER(buf);837UNUSED_PARAMETER(wl);838839memset(rem_ptr, 0, sizeof(rem_ioctl_t));840rem_ptr->msg.cmd = cmd;841rem_ptr->msg.len = buf_len;842rem_ptr->msg.flags = flags;843rem_ptr->data_len = data_len;844#ifndef OLYMPIC_RWL845if (strlen(g_rem_ifname) != 0)846strncpy(rem_ptr->intf_name, g_rem_ifname, (int)IFNAMSIZ);847rwl_swap_header(rem_ptr, HOST_TO_NETWORK);848#endif849if (data_len > buf_len) {850DPRINT_ERR(ERR, "remote_CDC_tx: data_len (%d) > buf_len (%d)\n", data_len, buf_len);851return (FAIL);852}853#ifdef RWL_SERIAL854if (remote_type == REMOTE_SERIAL) {855int ret;856/* Send CDC header first */857if ((ret = rwl_write_serial_port(wl, (char *)rem_ptr,858REMOTE_SIZE, &numwritten)) == -1) {859DPRINT_ERR(ERR, "CDC_Tx: Data: Write failed \n");860return (FAIL);861}862numwritten = ret;863864/* Send data second */865if ((ret = rwl_write_serial_port(wl, (char*)buf,866data_len, &numwritten)) == -1) {867DPRINT_ERR(ERR, "CDC_Tx: Data: Write failed \n");868return (FAIL);869}870numwritten = ret;871872return (buf_len);873}874#endif /* RWL_SERIAL */875#ifdef RWL_DONGLE876if (remote_type == REMOTE_DONGLE) {877return (remote_CDC_tx_dongle(wl, rem_ptr, buf));878}879#endif /* RWL_DONGLE */880#ifdef RWL_SOCKET881if (remote_type == REMOTE_SOCKET) {882int ret;883884/* Send CDC header first */885if ((ret = rwl_send_to_streamsocket(*(int*)wl, (char *)rem_ptr,886REMOTE_SIZE, 0)) == -1) {887DPRINT_ERR(ERR, "CDC_Tx: Data: Write failed \n");888return (FAIL);889}890891/* Send data second */892if ((ret = rwl_send_to_streamsocket(*(int*)wl, (const char*)buf,893data_len, 0)) == -1) {894DPRINT_ERR(ERR, "CDC_Tx: Data: Write failed \n");895return (FAIL);896}897898return (buf_len);899}900#endif /* RWL_SOCKET */901902#ifdef RWL_WIFI903/*904* wifi action frame is formed based on the CDC header and data.905* If the data is bigger than RWL_WIFI_FRAG_DATA_SIZE size, number of fragments are906* calculated and sent907* similar number of action frames with subtype incremented with sequence.908* Frames are sent with delay to avoid the outof order at receving end909*/910if (remote_type == REMOTE_WIFI) {911if ((rem_wifi_send = rwl_wifi_allocate_actionframe()) == NULL) {912DPRINT_ERR(ERR, "remote_CDC_tx: Failed to get allocated buffer\n");913return (FAIL);914}915916if (buf_len > RWL_WIFI_FRAG_DATA_SIZE) {917/* response needs to be sent in fragments */918totalframes = buf_len / RWL_WIFI_FRAG_DATA_SIZE;919memcpy((char*)&rem_wifi_send->data[RWL_WIFI_CDC_HEADER_OFFSET],920(char*)rem_ptr, REMOTE_SIZE);921memcpy((char*)&rem_wifi_send->data[REMOTE_SIZE], &buf[0],922RWL_WIFI_FRAG_DATA_SIZE);923/* update type feild to inform receiver it's frammeted response frame924*/925rem_wifi_send->type = RWL_ACTION_WIFI_FRAG_TYPE;926rem_wifi_send->subtype = RWL_WIFI_DEFAULT_SUBTYPE;927928if ((error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD,929rem_wifi_send, RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {930DPRINT_DBG(OUTPUT, "Failed to Send the Frame %d\n", error);931free(rem_wifi_send);932return error;933}934/* Send remaining bytes in fragments */935for (tx_count = 1; tx_count < totalframes; tx_count++) {936rem_wifi_send->type = RWL_ACTION_WIFI_FRAG_TYPE;937rem_wifi_send->subtype = tx_count;938/* First frame onwards , buf contains only data */939memcpy((char*)&rem_wifi_send->data,940&buf[tx_count*RWL_WIFI_FRAG_DATA_SIZE], RWL_WIFI_FRAG_DATA_SIZE);941if ((error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD,942rem_wifi_send, RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {943free(rem_wifi_send);944return error;945}946rwl_sleep(RWL_WIFI_SEND_DELAY);947}948949/* Check for remaing bytes to send */950if ((totalframes*RWL_WIFI_FRAG_DATA_SIZE) != buf_len) {951rem_wifi_send->type = RWL_ACTION_WIFI_FRAG_TYPE;952rem_wifi_send->subtype = tx_count;953memcpy((char*)&rem_wifi_send->data,954&buf[tx_count*RWL_WIFI_FRAG_DATA_SIZE],955(buf_len - (tx_count*RWL_WIFI_FRAG_DATA_SIZE)));956if ((error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD,957rem_wifi_send, RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {958free(rem_wifi_send);959return error;960}961}962} else {963/* response fits to single frame */964memcpy((char*)&rem_wifi_send->data[RWL_WIFI_CDC_HEADER_OFFSET],965(char*)rem_ptr, REMOTE_SIZE);966/* when data_len is 0 , buf will be NULL */967if (buf != NULL) {968memcpy((char*)&rem_wifi_send->data[REMOTE_SIZE],969&buf[0], data_len);970}971error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD, rem_wifi_send,972RWL_WIFI_ACTION_FRAME_SIZE);973free(rem_wifi_send);974return error;975}976}977#endif /* RWL_WIFI */978return (0);979}980981982rem_ioctl_t *983remote_CDC_rx_hdr(void *remote, int debug)984{985#ifdef RWL_SOCKET986int ret;987#endif /* RWL_SOCKET */988989#if defined(RWL_SERIAL) || defined (RWL_DONGLE) || defined (RWL_SOCKET)990uint numread = 0;991#endif992rem_ioctl_t *rem_ptr = &rem_cdc;993memset(rem_ptr, 0, sizeof(rem_ioctl_t));994995UNUSED_PARAMETER(remote);996UNUSED_PARAMETER(debug);997998switch (remote_type) {999#if defined(RWL_SERIAL) || defined (RWL_DONGLE)1000case REMOTE_SERIAL:1001case REMOTE_DONGLE:1002if (rwl_read_serial_port(remote, (char *)rem_ptr, sizeof(rem_ioctl_t),1003&numread) < 0) {1004DPRINT_ERR(ERR, "remote_CDC_rx_hdr: Header Read failed \n");1005return (NULL);1006}1007break;1008#endif /* RWL_SERIAL | RWL_DONGLE */100910101011#ifdef RWL_SOCKET1012case REMOTE_SOCKET:1013ret = rwl_receive_from_streamsocket(*(int*)remote, (char *)rem_ptr,1014sizeof(rem_ioctl_t), 0);1015numread = ret;1016if (ret == -1) {1017DPRINT_ERR(ERR, "remote_CDC_rx_hdr: numread:%d", numread);1018return (NULL);1019}1020if (numread == 0) {1021DPRINT_DBG(OUTPUT, "\n remote_CDC_rx_hdr:No data to receive\n");1022return NULL;1023}1024break;1025#endif1026default:1027DPRINT_ERR(ERR, "\n Unknown Transport Type\n");1028break;1029}10301031return (rem_ptr);1032}10331034/* Return a CDC type buffer */1035int1036remote_CDC_rx(void *wl, rem_ioctl_t *rem_ptr, uchar *readbuf, uint buflen, int debug)1037{1038uint numread = 0;10391040#ifdef RWL_SOCKET1041int ret;1042#endif10431044#ifdef RWL_WIFI1045UNUSED_PARAMETER(numread);1046#endif /* RWL_WIFI */1047UNUSED_PARAMETER(wl);1048UNUSED_PARAMETER(readbuf);1049UNUSED_PARAMETER(buflen);1050UNUSED_PARAMETER(debug);1051UNUSED_PARAMETER(numread);10521053if (rem_ptr->data_len > rem_ptr->msg.len) {1054DPRINT_ERR(ERR, "remote_CDC_rx: remote data len (%d) > msg len (%d)\n",1055rem_ptr->data_len, rem_ptr->msg.len);1056return (FAIL);1057}105810591060#if defined (RWL_DONGLE) || defined (RWL_SERIAL)1061if ((remote_type == REMOTE_DONGLE) || (remote_type == REMOTE_SERIAL)) {1062if (rwl_read_serial_port(wl, (char*)readbuf, rem_ptr->data_len,1063&numread) < 0) {1064DPRINT_ERR(ERR, "remote_CDC_rx_hdr: Data Receivefailed \n");1065return (FAIL);1066}1067}1068#endif /* RWL_DONGLE || RWL_SERIAL */10691070#ifdef RWL_SOCKET1071if (remote_type == REMOTE_SOCKET) {1072if (((ret = rwl_receive_from_streamsocket(*(int*)wl, (char*)readbuf,1073rem_ptr->data_len, 0)) == -1)) {1074DPRINT_ERR(ERR, "remote_CDC_rx:Data Receive failed\n");1075return (FAIL);1076}1077}1078#endif /* RWL_SOCKET */1079return (SUCCESS);1080}1081#ifdef RWL_SOCKET1082int1083rwl_sockconnect(int SockDes, struct sockaddr *servAddr, int size)1084{1085DPRINT_DBG(OUTPUT, "sockconnet SockDes=%d\n", SockDes);1086if (rwl_connectsocket(SockDes, servAddr, size) < 0) {1087DPRINT_ERR(ERR, "\n rwl_socketconnect failed\n");1088return FAIL;1089}1090return SUCCESS;1091}1092#endif /* RWL_SOCKET */1093void1094rwl_swap_header(rem_ioctl_t *rem_ptr, bool host_to_network)1095{1096rem_ptr->msg.cmd = host_to_network?(htol32(rem_ptr->msg.cmd)):(ltoh32(rem_ptr->msg.cmd));1097rem_ptr->msg.len = host_to_network?(htol32(rem_ptr->msg.len)):(ltoh32(rem_ptr->msg.len));1098rem_ptr->msg.flags = host_to_network?(htol32(rem_ptr->msg.flags)):1099(ltoh32(rem_ptr->msg.flags));1100rem_ptr->msg.status = host_to_network?(htol32(rem_ptr->msg.status)):1101(ltoh32(rem_ptr->msg.status));1102rem_ptr->data_len = host_to_network?(htol32(rem_ptr->data_len)):(ltoh32(rem_ptr->data_len));1103}110411051106