Example #1
0
/* 
 * Read the valid action frame through the REF/DUT driver interface.
 * Retry for no of times, wait for action frame for the specified time.
 */
int
remote_CDC_DATA_wifi_rx(void *wl, dot11_action_wifi_vendor_specific_t * rec_frame)
{
	int error, read_try;
	void *ptr = NULL;


	/* retry is to ensure to read late arrival action frame */
	for (read_try = 0; read_try < RWL_WIFI_RX_RETRY; read_try++) {
		/* read the action frame queued in the local driver wifi queue */
		if ((error = rwl_var_getbuf(wl, RWL_WIFI_GET_ACTION_CMD, rec_frame,
		 RWL_WIFI_ACTION_FRAME_SIZE, &ptr)) < 0) {
			DPRINT_ERR(ERR, "remote_CDC_DATA_wifi_rx: Error in reading the frame %d\n",
			error);
			return error;
		}
		/* copy the read action frame to the user frame and cjheck for the action category. 
		 *  If the action category matches with RWL_ACTION_WIFI_CATEGORY ,
		 *  then its the valid frame, otherwise ignore it.
		 */
		memcpy((char*)rec_frame, ptr, RWL_WIFI_ACTION_FRAME_SIZE);

		if (rec_frame->category == RWL_ACTION_WIFI_CATEGORY) {
			break;
		} else {
			rwl_sleep(RWL_WIFI_RX_DELAY);
		}
	}
	/* If failed to get the valid frame , indicate the error  */
	if (!(rec_frame->category == RWL_ACTION_WIFI_CATEGORY)) {
		return (FAIL);
	}
	return error;
}
Example #2
0
/* 
 * check for the channel of remote and respond if it matches with its current
 * channel. Once the server gets the handshake cmd, it will check the channel
 * number of the remote with its channel and if it matches , then it send out the
 * ack to the remote client. This fucntion is used only by the server.
 */
void
rwl_wifi_find_server_response(void *wl, dot11_action_wifi_vendor_specific_t *rec_frame)
{
	int error, send, server_channel;

	if (rec_frame->type == RWL_WIFI_FIND_MY_PEER) {

		rec_frame->type = RWL_WIFI_FOUND_PEER;
		/* read channel on of the SERVER */
		rwl_wifi_config_channel(wl, WLC_GET_CHANNEL, &server_channel);
		/* overlapping channel not supported, 
		so server will only respond to client on the channel of the client
		*/
		if (rec_frame->data[RWL_WIFI_CLIENT_CHANNEL_OFFSET] == server_channel) {
			/* send the response by updating server channel in the frame */
			rec_frame->data[RWL_WIFI_SERVER_CHANNEL_OFFSET] = server_channel;
			/* change the TYPE feild for giving the ACK */
			for (send = 0; send < RWL_WIFI_SEND; send++) {
				if ((error = rwl_var_setbuf(wl, RWL_WIFI_ACTION_CMD, rec_frame,
					RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
					DPRINT_ERR(ERR, "rwl_wifi_find_server_response: Failed"
					"to Send the Frame %d\n", error);
					break;
				}
				rwl_sleep(RWL_WIFI_SEND_DELAY);
			}
		}
	}
	return;
}
void
rwl_sync_delay(uint noframes)
{
	if (noframes > 1) {
		rwl_sleep(LINUX_SYNC_DELAY);
	}
}
/* 
 * This function runs a set of commands before running the wi-fi server
 * This is avoids packet drops and improves performance.
 * We run the following wl commands
 * up, mpc 0, wsec 0, slow_timer 999999, fast_timer 999999, glacial_timer 999999
 * legacylink 1, monitor 1.
 */
void remote_wifi_ser_init_cmds(void *wl)
{
	int err;
	char bigbuf[RWL_WIFI_BUF_LEN];
	uint len = 0, count;
	/* The array stores command, length and then data format */
	remote_wifi_cmds_t wifi_cmds[] = {
						{WLC_UP,  NULL, 0x0},
						{WLC_SET_VAR,  "mpc", 0},
						{WLC_SET_WSEC,  NULL, 0x0},
						{WLC_SET_VAR, "slow_timer", 999999},
						{WLC_SET_VAR, "fast_timer", 999999},
						{WLC_SET_VAR, "glacial_timer", 999999},
						{WLC_SET_MONITOR, NULL, 0x1},
						{WLC_SET_PM, NULL, 0x0}
	};

	for (count = 0; count < ARRAYSIZE(wifi_cmds); count++) {

		if (wifi_cmds[count].data == NULL)
			len = sizeof(int);
		else
			len = strlen(wifi_cmds[count].data) + 1 + sizeof(int);

		/* If the command length exceeds the buffer length continue 
		 * executing the next command
		 */
		if (len > sizeof(bigbuf)) {
			DPRINT_ERR(ERR, "Err: command len exceeds buf len. Check"
				"initialization cmds\n");
			continue;
		}

		if (wifi_cmds[count].data != NULL) {
			strcpy(bigbuf, wifi_cmds[count].data);
			memcpy(&bigbuf[strlen(wifi_cmds[count].data)+1],
			(char*)&wifi_cmds[count].value, sizeof(int));
		} else {
			memcpy(&bigbuf[0], (char*)&wifi_cmds[count].value, sizeof(int));
		}
#ifdef WIN32
		/* Add OID base for NDIS commands */

		err = (int)ir_setinformation(wl, wifi_cmds[count].cmd + WL_OID_BASE,
		bigbuf, &len);
#endif

		if (wifi_cmds[count].cmd == WLC_UP)
			/* NULL needs to be passed to the driver if WL UP command needs to 
			 * be executed Otherwise driver hangs
			 */
			err = wl_ioctl(wl, wifi_cmds[count].cmd,
				NULL, 0, TRUE);
		else
			err = wl_ioctl(wl, wifi_cmds[count].cmd,
			(void*)&bigbuf, len, TRUE);

		rwl_sleep(INIT_CMD_SLEEP);
	}
}
Example #5
0
void
rwl_sync_delay(unsigned int noframes)
{
    if (noframes > 1) {
        rwl_sleep(200);
    }
}
Example #6
0
int
remote_CDC_tx(void *wl, uint cmd, uchar *buf, uint buf_len, uint data_len, uint flags, int debug)
{
#if defined(RWL_SOCKET) || defined(RWL_SERIAL)
	unsigned long numwritten = 0;
#endif
	rem_ioctl_t *rem_ptr = &rem_cdc;
#ifdef RWL_WIFI
	int error;
	uint totalframes, tx_count;
	dot11_action_wifi_vendor_specific_t *rem_wifi_send;
#endif
	UNUSED_PARAMETER(debug);

	rem_ptr->msg.cmd = cmd;
	rem_ptr->msg.len = buf_len;
	rem_ptr->msg.flags = flags;
	rem_ptr->data_len = data_len;

	if (data_len > buf_len) {
		DPRINT_ERR(ERR, "remote_CDC_tx: data_len (%d) > buf_len (%d)\n", data_len, buf_len);
		return (FAIL);
	}
#ifdef RWL_SERIAL
	if (remote_type == REMOTE_SERIAL) {
		int ret;
		/* Send CDC header first */
		if ((ret = rwl_write_serial_port(wl, (char *)rem_ptr,
			REMOTE_SIZE, &numwritten)) == -1) {
			DPRINT_ERR(ERR, "CDC_Tx: Data: Write failed \n");
			return (FAIL);
		}
		numwritten = ret;

		/* Send data second */
		if ((ret = rwl_write_serial_port(wl, (char*)buf,
			data_len, &numwritten)) == -1) {
			DPRINT_ERR(ERR, "CDC_Tx: Data: Write failed \n");
			return (FAIL);
		}
		numwritten = ret;

		return (buf_len);
	}
#endif /* RWL_SERIAL */
#ifdef RWL_DONGLE
	if (remote_type == REMOTE_DONGLE) {
		return (remote_CDC_tx_dongle(wl, rem_ptr, buf));
	}
#endif /* RWL_DONGLE */
#ifdef RWL_SOCKET
	if (remote_type == REMOTE_SOCKET) {
		int ret;

		/* Send CDC header first */
		if ((ret = rwl_send_to_streamsocket(*(int*)wl, (char *)rem_ptr,
			REMOTE_SIZE, 0)) == -1) {
			DPRINT_ERR(ERR, "CDC_Tx: Data: Write failed \n");
			return (FAIL);
		}
		numwritten = ret;

		/* Send data second */
		if ((ret = rwl_send_to_streamsocket(*(int*)wl, (const char*)buf,
			data_len, 0)) == -1) {
			DPRINT_ERR(ERR, "CDC_Tx: Data: Write failed \n");
			return (FAIL);
		}
		numwritten = ret;

		return (buf_len);
	}
#endif /* RWL_SOCKET */

#ifdef RWL_WIFI
	/* 
	 * wifi action frame is formed based on the CDC header and data.
	 * If the data is bigger than RWL_WIFI_FRAG_DATA_SIZE size, number of fragments are
	 * calculated and sent
	 * similar number of action frames with subtype incremented with sequence.
	 * Frames are sent with delay to avoid the outof order at receving end
	 */
	if (remote_type == REMOTE_WIFI) {
		if ((rem_wifi_send = rwl_wifi_allocate_actionframe()) == NULL) {
			DPRINT_ERR(ERR, "remote_CDC_tx: Failed to get allocated buffer\n");
			return (FAIL);
		}

		if (rem_ptr->msg.len > RWL_WIFI_FRAG_DATA_SIZE) {
			/* response needs to be sent in fragments */
			totalframes = rem_ptr->msg.len / RWL_WIFI_FRAG_DATA_SIZE;
			memcpy((char*)&rem_wifi_send->data[RWL_WIFI_CDC_HEADER_OFFSET],
			(char*)rem_ptr,	REMOTE_SIZE);
			memcpy((char*)&rem_wifi_send->data[REMOTE_SIZE], &buf[0],
			RWL_WIFI_FRAG_DATA_SIZE);
			/* update type feild to inform receiver it's frammeted response frame
			*/
			rem_wifi_send->type = RWL_ACTION_WIFI_FRAG_TYPE;
			rem_wifi_send->subtype = RWL_WIFI_DEFAULT_SUBTYPE;

			if ((error = rwl_var_setbuf(wl, RWL_WIFI_ACTION_CMD, rem_wifi_send,
			RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
				DPRINT_DBG(OUTPUT, "Failed to Send the Frame %d\n", error);
				free(rem_wifi_send);
				return error;
			}
			/* Send remaining bytes in fragments */
			for (tx_count = 1; tx_count < totalframes; tx_count++) {
				rem_wifi_send->type = RWL_ACTION_WIFI_FRAG_TYPE;
				rem_wifi_send->subtype = tx_count;
				/* First frame onwards , buf contains only data */
				memcpy((char*)&rem_wifi_send->data,
				&buf[tx_count*RWL_WIFI_FRAG_DATA_SIZE], RWL_WIFI_FRAG_DATA_SIZE);
				if ((error = rwl_var_setbuf(wl, RWL_WIFI_ACTION_CMD,
					rem_wifi_send, RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
					free(rem_wifi_send);
					return error;
				}
				rwl_sleep(RWL_WIFI_SEND_DELAY);
			}

			/* Check for remaing bytes to send */
			if ((totalframes*RWL_WIFI_FRAG_DATA_SIZE) != rem_ptr->msg.len) {
				rem_wifi_send->type = RWL_ACTION_WIFI_FRAG_TYPE;
				rem_wifi_send->subtype = tx_count;
				memcpy((char*)&rem_wifi_send->data,
				&buf[tx_count*RWL_WIFI_FRAG_DATA_SIZE],
				(rem_ptr->msg.len - (tx_count*RWL_WIFI_FRAG_DATA_SIZE)));
				if ((error = rwl_var_setbuf(wl, RWL_WIFI_ACTION_CMD, rem_wifi_send,
				RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
					free(rem_wifi_send);
					return error;
				}
			}
		} else {
			/* response fits to single frame */
			memcpy((char*)&rem_wifi_send->data[RWL_WIFI_CDC_HEADER_OFFSET],
			(char*)rem_ptr,	REMOTE_SIZE);
			/* when data_len is 0 , buf will be NULL */
			if (buf != NULL) {
				memcpy((char*)&rem_wifi_send->data[REMOTE_SIZE],
				&buf[0], data_len);
			}
			error = rwl_var_setbuf(wl, RWL_WIFI_ACTION_CMD, rem_wifi_send,
			RWL_WIFI_ACTION_FRAME_SIZE);
			free(rem_wifi_send);
			return error;
		}
	}
#endif /* RWL_WIFI */
	return (0);
}
Example #7
0
static int
remote_CDC_tx_dongle(void *wl, rem_ioctl_t *rem_ptr, uchar *buf)
{
	unsigned long numwritten;
	char end_of_packet[END_OF_PACK_SEP_LEN] = "\n\n";
	uchar loc_buf[UART_FIFO_LEN];
	uint len = END_OF_PACK_SEP_LEN;
	uint noframes, frame_count, rem_bytes;
	uint n_bytes;

	/* Converting the CDC header with keyword 'rwl ' in ascii format
	 * as dongle UART understands only ascii format.
	 * In dongle UART driver CDC structure is made from the ascii data
	 * it received.
	 */
	sprintf((char*)loc_buf, "rwl %d %d %d %d ", rem_ptr->msg.cmd, rem_ptr->msg.len,
		rem_ptr->msg.flags, rem_ptr->data_len);
	n_bytes = strlen((char*)loc_buf);

	DPRINT_DBG(OUTPUT, "rwl %x %d %d %d ", rem_ptr->msg.cmd, rem_ptr->msg.len,
		rem_ptr->msg.flags, rem_ptr->data_len);
	DPRINT_DBG(OUTPUT, "CDC Header:No of bytes to be sent=%d\n", n_bytes);
	DPRINT_DBG(OUTPUT, "Data:No of bytes to be sent=%d\n", rem_ptr->data_len);

	/* Send the CDC Header */
	if (rwl_write_serial_port(wl, (char*)loc_buf, n_bytes, &numwritten) < 0) {
		DPRINT_ERR(ERR, "CDC_Tx: Header: Write failed\n");
		DPRINT_ERR(ERR, "CDC_Tx: Header: numwritten %ld != n_bytes %d\n",
			numwritten, n_bytes);
		return (FAIL);
	}

	/* Dongle UART FIFO len is 64 bytes and flow control is absent. 
	 * While transmitting large chunk of data the data was getting lost
	 * at UART driver so for large chunk of data 64 bytes are sent at a time
	 * folowed by delay and then next set of 64 bytes and so on.
	 * For data which is less than 64 bytes it is sent in one shot
	 */

	noframes = rem_ptr->data_len/UART_FIFO_LEN;
	if (noframes == 0) {
		/* Send the data now */
		if (rwl_write_serial_port(wl, (char*)buf, rem_ptr->data_len, &numwritten) < 0) {
			DPRINT_ERR(ERR, "Data_Tx: Header: Write failed\n");
			DPRINT_ERR(ERR, "Data_Tx: Header: numwritten %ld != len %d\n",
			numwritten, rem_ptr->data_len);
			return (FAIL);
		}

	} else {
		if (rem_ptr->data_len % UART_FIFO_LEN == 0) {
			rem_bytes = UART_FIFO_LEN;
		} else {
			rem_bytes = rem_ptr->data_len % UART_FIFO_LEN;
			noframes += 1;
		}

		for (frame_count = 0; frame_count < noframes; frame_count++) {
			if (frame_count != noframes-1) {
				memcpy(loc_buf, (char*)(&buf[frame_count*UART_FIFO_LEN]),
				UART_FIFO_LEN);
				/* Send the data now */
				if (rwl_write_serial_port(wl, (char*)loc_buf, UART_FIFO_LEN,
				&numwritten) == -1) {
					DPRINT_ERR(ERR, "Data_Tx: Header: Write failed\n");
					return (-1);
				}

			} else {
				memcpy(loc_buf, (char*)(&buf[frame_count*UART_FIFO_LEN]),
				rem_bytes);

				if (rwl_write_serial_port(wl, (char*)loc_buf, rem_bytes,
				&numwritten) == -1) {
					DPRINT_ERR(ERR, "Data_Tx: Header: Write failed\n");
					return (-1);
				}

			}
			rwl_sleep(SYNC_TIME);
		}
	}

	/* Send end of packet now */
	if (rwl_write_serial_port(wl, end_of_packet, len, &numwritten) == -1) {
		DPRINT_ERR(ERR, "CDC_Tx: Header: Write failed\n");
		DPRINT_ERR(ERR, "CDC_Tx: Header: numwritten %ld != len %d\n",
			numwritten, len);
		return (FAIL);
	}

	DPRINT_DBG(OUTPUT, "Packet sent!\n");

	return (rem_ptr->msg.len);	/* Return size of actual buffer to satisfy accounting
								going on above this level
								*/
}
Example #8
0
/*
 * This function is used by client only. Sends the finmypeer sync frame to remote
 * server on diffrent channels and  waits for the response.
 */
int
rwl_find_remote_wifi_server(void *wl, char *id)
{
	dot11_action_wifi_vendor_specific_t *rem_wifi_send, *rem_wifi_recv;
	rem_ioctl_t *rem_ptr = &rem_cdc;
	/* This list is generated considering valid channel and if this 
	 * may requires updation or deletion. This needs to be identified.
	 * we have assumed that server band is not known and considered all band channels.
	 */
	int wifichannel[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
	11, 36, 40, 44, 48, 149, 153, 157, 161, 165};
	int i, error, schannel, channel_count;

	if ((rem_wifi_send = rwl_wifi_allocate_actionframe()) == NULL) {
		DPRINT_ERR(ERR, " rwl_find_remote_wifi_server : Failed to allocate \n");
		return FAIL;
	}
	if ((rem_wifi_recv = rwl_wifi_allocate_actionframe()) == NULL) {
		DPRINT_ERR(ERR, " rwl_find_remote_wifi_server : Failed to allocate\n");
		free(rem_wifi_send);
		return FAIL;
	}

	channel_count = sizeof(wifichannel) / sizeof(int);

	/* make dummy read to make sure we don't read the already queued
	 * actionframes against the cmd we issue
	 */
	rwl_wifi_purge_actionframes(wl);

	/* update the client sync specifier */
	rem_wifi_send->type = RWL_WIFI_FIND_MY_PEER;
	/* update the CDC flag to indicate it is handshake frame */
	rem_ptr->msg.cmd = 0;
	/* cmd =0 ,this will be ignored when server receive frame 
	 * with REMOTE_FINDSERVER_IOCTL flag
	 */
	rem_ptr->msg.len = RWL_WIFI_FRAG_DATA_SIZE;
	rem_ptr->msg.flags = REMOTE_FINDSERVER_IOCTL;
	rem_ptr->data_len = RWL_WIFI_FRAG_DATA_SIZE;

	memcpy((char*)&rem_wifi_send->data, (char*)rem_ptr, REMOTE_SIZE);
	/* copy server mac to which ref driver needs to send unicast action frame */
	memcpy(&rem_wifi_send->data[RWL_REF_MAC_ADDRESS_OFFSET], &id[0], ETHER_ADDR_LEN);

	/* Start with the channel in the list and keep changing till the server
	 * responds or channels list ends
	 */
	for (i = 0; i < channel_count; i++) {
		if ((error = rwl_wifi_config_channel(wl, WLC_SET_CHANNEL,
		&wifichannel[i])) < 0) {
			DPRINT_ERR(ERR, " Failed to set the specified channel %d\n",
			wifichannel[i]);
			break;
		}
		/* send channel detail of client to server */
		rem_wifi_send->data[RWL_WIFI_CLIENT_CHANNEL_OFFSET] = wifichannel[i];

		if ((error = rwl_var_setbuf(wl, RWL_WIFI_ACTION_CMD, rem_wifi_send,
		RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
			DPRINT_DBG(OUTPUT, "Failed to Send the Frame %d\n", error);
			break;
		}
		/* read the server response on the same channel */
		if ((error = remote_CDC_DATA_wifi_rx(wl, rem_wifi_recv)) < 0) {
			rwl_sleep(RWL_WIFI_RETRY_DELAY);
			continue;
		}
		/* Verify for the Type RWL_WIFI_FOUND_PEER */
		if (rem_wifi_recv->type == RWL_WIFI_FOUND_PEER) {
			if (rem_wifi_recv->data[RWL_WIFI_SERVER_CHANNEL_OFFSET] ==
				rem_wifi_recv->data[RWL_WIFI_CLIENT_CHANNEL_OFFSET]) {

				DPRINT_INFO(OUTPUT, "Server is on channel # %d\n",
				rem_wifi_recv->data[RWL_WIFI_SERVER_CHANNEL_OFFSET]);

				schannel = rem_wifi_recv->data[RWL_WIFI_SERVER_CHANNEL_OFFSET];
				/* Set the back to the channel on which REF was originally */
				if ((error = rwl_wifi_config_channel(wl,
				WLC_SET_CHANNEL, &schannel) < 0)) {
					DPRINT_ERR(ERR, "Failed to set the specified"
					"channel %d\n", schannel);
				} else {
					DPRINT_ERR(ERR, "REF now moved to the"
					"channel of server # %d\n", schannel);
				}
				/* we are done here, end the loop */
				break;
			} else {
				DPRINT_INFO(OUTPUT, "Server is operating on diffrent channel."
				"continue scanning\n");
			}
		}
		/* before chaning the channel of client and sending sync frame
		 * wait for while and send
		 */
		rwl_sleep(RWL_WIFI_RETRY_DELAY);
	}

	free(rem_wifi_send);
	free(rem_wifi_recv);
	return error;
}
/*
* This is the front end query function for Set Ioctls. This is used by clients
for executing Set Ioctls.
*/
int
rwl_setinformation_fe(void *wl, int cmd, void* buf,
	unsigned long *len, int debug, int rem_ioctl_select) {
	int error = 0;
	uint tx_len;
#if defined  (RWL_SERIAL) || (RWL_WIFI)
	rem_ioctl_t *rem_ptr = NULL;
#endif

#ifdef RWL_WIFI
	dot11_action_wifi_vendor_specific_t *list = NULL;
	char *cbuf, retry;
#endif

	UNUSED_PARAMETER(debug);

	switch (remote_type) {
		case REMOTE_SOCKET:
#ifdef RWL_SOCKET
			error = rwl_information_socket(wl, cmd, buf, len, len, rem_ioctl_select);
#endif
			break;
#ifdef RWL_SERIAL
		case REMOTE_SERIAL:
			if (remote_CDC_tx(wl, cmd, buf, *len, *len, rem_ioctl_select, debug) < 0) {
				DPRINT_ERR(ERR, "set_info_fe: Send command failed\n");
				return FAIL;
			}

			if ((rem_ptr = remote_CDC_rx_hdr(wl, debug)) == NULL) {
				DPRINT_ERR(ERR, "set_info_fe: Reading CDC header failed\n");
				return FAIL;
			}

			if (rem_ptr->msg.flags != REMOTE_REPLY)	{
				DPRINT_ERR(ERR, "set_info_fe: response format error.\n");
				return FAIL;
			}

			if (rem_ptr->msg.len > *len) {
				DPRINT_ERR(ERR, "set_info_fe: needed size (%d) greater than "
					   "actual size (%lu)\n", rem_ptr->msg.len, *len);
				return FAIL;
			}

			error = rem_ptr->msg.cmd;
			if (error != 0) {
				DPRINT_ERR(ERR, "set_info_fe: remote cdc header return "
					   "error code (%d)\n", error);
			}

			if (remote_CDC_rx(wl, rem_ptr, buf, rem_ptr->msg.len, debug) == -1) {
				DPRINT_ERR(ERR, "set_info_fe: fetching results failed\n");
				return FAIL;
			}

			if (rem_ptr->msg.flags & REMOTE_REPLY)
				error = rem_ptr->msg.cmd;
			break;
#endif /* RWL_SERIAL */
#ifdef RWL_DONGLE
		case REMOTE_DONGLE:
			if ((int)(*len) > SERVER_RESPONSE_MAX_BUF_LEN)
				*len = SERVER_RESPONSE_MAX_BUF_LEN;

			/* Actual buffer to be sent should be max 256 bytes as
			 *UART input buffer
			 * is 512 bytes
			 */
			tx_len = MIN(*len, 512);
			error = rwl_information_dongle(wl, cmd, buf, len, tx_len, rem_ioctl_select);
			break;
#endif //ifdef RWL_DONGLE
		case REMOTE_WIFI:
#ifdef RWL_WIFI
			if ((int)(*len) > SERVER_RESPONSE_MAX_BUF_LEN)
				*len = SERVER_RESPONSE_MAX_BUF_LEN;

			/* Actual buffer to be sent should be max 960 bytes
			 * as wifi max frame size if 960
			 * and actual data for any command will not exceed 960 bytes
			*/
			tx_len = MIN(*len, RWL_WIFI_FRAG_DATA_SIZE);

			if ((cbuf = (char*) malloc(tx_len)) == NULL) {
				DPRINT_ERR(ERR, "Malloc failed for set_info_fe character buf\n");
				return FAIL;
			}
			if ((list = (dot11_action_wifi_vendor_specific_t *)
					malloc(RWL_WIFI_ACTION_FRAME_SIZE)) == NULL) {
				free(cbuf);
				return FAIL;
			}

			if ((rem_ptr = (rem_ioctl_t *)malloc(sizeof(rem_ioctl_t))) == NULL) {
				free(list);
				free(cbuf);
				return FAIL;
			}

			memcpy(cbuf, (char*)buf, tx_len);

			for (retry = 0; retry < RWL_WIFI_RETRY; retry++) {

				rwl_wifi_purge_actionframes(wl);
				/* copy back the buffer to input buffer */
				memcpy((char*)buf, (char*)cbuf, tx_len);

				if (retry > 3)
					DPRINT_INFO(OUTPUT, "retry %d cmd %d\n", retry, cmd);

				if ((error = remote_CDC_wifi_tx(wl, cmd, buf, *len,
				                                tx_len, rem_ioctl_select) < 0)) {
					DPRINT_ERR(ERR, "ir_setinformation_fe: Send"
					"command failed\n");
					rwl_sleep(RWL_WIFI_RETRY_DELAY);
					continue;
				}

				if ((char*)buf != NULL) {
					/* In case cmd is findserver, response is not
					 * required from the server
					 */
					if (!strcmp((char*)buf, RWL_WIFI_FIND_SER_CMD)) {
						break;
					}
				}

				/* Read the CDC header and data of for the sent cmd
				 * resposne
				 */
				if ((error = remote_CDC_DATA_wifi_rx((void*)wl, list) < 0)) {
					DPRINT_ERR(ERR, "ir_setinformation_fe: failed to read"
						"the response\n");
					rwl_sleep(RWL_WIFI_RETRY_DELAY);
					continue;
				}

				memcpy((char*)rem_ptr,
				(char*)&list->data[RWL_WIFI_CDC_HEADER_OFFSET],
				REMOTE_SIZE);
				rwl_swap_header(rem_ptr, NETWORK_TO_HOST);

				memcpy((char*)buf, (char*)&list->data[REMOTE_SIZE],
				rem_ptr->msg.len);

				if (rem_ptr->msg.flags & REMOTE_REPLY) {
					error = rem_ptr->msg.cmd;
					break;
				} else {
					rwl_sleep(RWL_WIFI_RETRY_DELAY);
				}
			}
				free(rem_ptr);
				free(list);
			if (cbuf != NULL)
				free(cbuf);
			break;
#endif /* RWL_WIFI */
		default:
			DPRINT_ERR(ERR, "rwl_setinformation_fe: Unknown remote_type:%d\n",
			remote_type);
		break;
	}

	return error;
}
/* transport independent entry point for GET ioctls */
int
rwl_queryinformation_fe(void *wl, int cmd, void* input_buf,
	unsigned long *input_len, int debug, int rem_ioctl_select) {
	int error = 0;
	uint tx_len;
#if defined (RWL_SERIAL) || (RWL_WIFI)
	rem_ioctl_t *rem_ptr = NULL;
#endif

#ifdef RWL_WIFI
	int retry;
	char *cinput_buf;
#endif

	UNUSED_PARAMETER(debug);

	switch (remote_type) {
		case REMOTE_SOCKET:
#ifdef RWL_SOCKET
		/* We don't want the server to allocate bigger buffers
		 * for some of the commands
		 * like scanresults. Server can still allocate 8K memory
		 * and send the response
		 */
		if ((int)(*input_len) > SERVER_RESPONSE_MAX_BUF_LEN)
			*input_len = SERVER_RESPONSE_MAX_BUF_LEN;

		error = rwl_information_socket(wl, cmd, input_buf,
			input_len, input_len, rem_ioctl_select);
#endif /* RWL_SOCKET */
		break;

#ifdef RWL_SERIAL
		/* System serial transport is not supported in Linux. Only XP */
		case REMOTE_SERIAL:
			tx_len = MIN(*input_len, SERVER_RESPONSE_MAX_BUF_LEN);

			if (remote_CDC_tx(wl, cmd, input_buf, tx_len,
			tx_len, rem_ioctl_select, debug) < 0) {
				DPRINT_ERR(ERR, "query_info_fe: Send command failed\n");
				return FAIL;
			}

			if ((rem_ptr = remote_CDC_rx_hdr(wl, debug)) == NULL) {
				DPRINT_ERR(ERR, "query_info_fe: Reading CDC header failed\n");
				return FAIL;
			}

			if (rem_ptr->msg.flags != REMOTE_REPLY) {
				DPRINT_ERR(ERR, "query_info_fe: response format error.\n");
				return FAIL;
			}
			if (rem_ptr->msg.len > *input_len) {
				DPRINT_ERR(ERR, "query_info_fe: needed size(%d) greater than "
				"actual size(%lu)\n", rem_ptr->msg.len, *input_len);
				return FAIL;
			}

			error = rem_ptr->msg.status;
			if (error != 0)
				DPRINT_ERR(ERR, "query_info_fe: remote cdc header return "
					   "error code %d\n", error);
			if (remote_CDC_rx(wl, rem_ptr, input_buf, *input_len, debug) == -1) {
				DPRINT_ERR(ERR, "query_info_fe: No results!\n");
				return FAIL;
			}
			if (rem_ptr->msg.flags & REMOTE_REPLY)
				error = rem_ptr->msg.cmd;
			break;

#endif /* RWL_SERIAL */
#ifdef RWL_DONGLE
		case REMOTE_DONGLE:
			/* We don't want the server to allocate bigger buffers
			 * for some of the commands
			 * like scanresults. Server can still allocate 8K
			 *memory and send the response
			 * in fragments.
			 */
			if ((int)(*input_len) > SERVER_RESPONSE_MAX_BUF_LEN)
				*input_len = SERVER_RESPONSE_MAX_BUF_LEN;

			/* Actual buffer to be sent should be max 256 bytes as
			 *UART input buffer
			 * is 512 bytes
			 */
			tx_len = MIN(*input_len, 256);
			error = rwl_information_dongle(wl, cmd, input_buf, input_len,
				tx_len, rem_ioctl_select);

			break;
#endif //ifdef RWL_DONGLE

		case REMOTE_WIFI:
#ifdef RWL_WIFI
			/* We don't want the server to allocate bigger buffers
			 * for some of the commands
			 * like scanresults. Server can still allocate 8K memory
			 * and send the response
			 * in fragments.
			 */
			if ((int)(*input_len) > SERVER_RESPONSE_MAX_BUF_LEN)
				*input_len = SERVER_RESPONSE_MAX_BUF_LEN;

			/* Actual buffer to be sent should be max 960 bytes
			 * as wifi max frame size if 960
			 * and actual data for any command will not exceed 960 bytes
			*/
			tx_len = MIN(*input_len, RWL_WIFI_FRAG_DATA_SIZE);

			if ((rem_ptr = (rem_ioctl_t *)malloc(REMOTE_SIZE)) == NULL) {
				return FAIL;
			}
			if ((cinput_buf = (char*)malloc(tx_len)) == NULL) {
				DPRINT_ERR(ERR, "Malloc failed for query information fe"
				"character buf \n");
				free(rem_ptr);
				return FAIL;
			}

			memcpy(cinput_buf, (char*)input_buf, tx_len); /* Keep a copy of input_buf */

			for (retry = 0; retry < RWL_WIFI_RETRY; retry++) {

				rwl_wifi_purge_actionframes(wl);

				if (retry > 3)
					DPRINT_INFO(OUTPUT, "ir_queryinformation_fe : retry %d"
					"cmd %d\n", retry, cmd);

				/* copy back the buffer to input buffer */
				memcpy((char*)input_buf, cinput_buf, tx_len);

				/* Issue the command */
				if ((error = remote_CDC_wifi_tx(wl, cmd, input_buf,
					*input_len, tx_len, rem_ioctl_select)) < 0) {
					DPRINT_DBG(OUTPUT, "query_info_fe: Send command failed\n");
						rwl_sleep(RWL_WIFI_RETRY_DELAY);
						continue;
				}

				if ((error = remote_CDC_DATA_wifi_rx_frag(wl, rem_ptr,
					*input_len, input_buf, RWL_WIFI_WL_CMD) < 0)) {
					DPRINT_DBG(OUTPUT, "ir_queryinformation_fe :"
					"Error in reading the frag bytes\n");
					rwl_sleep(RWL_WIFI_RETRY_DELAY);
					continue;
				}

				if (rem_ptr->msg.flags & REMOTE_REPLY) {
					error = rem_ptr->msg.cmd;
					break;
				} else {
					rwl_sleep(RWL_WIFI_RETRY_DELAY);
				}
			}

			free(rem_ptr);
			if (cinput_buf)
				free(cinput_buf);
			break;
#endif /* RWL_WIFI */
		default:
			DPRINT_ERR(ERR, "rwl_queryinformation_fe: Unknown"
				"remote_type %d\n", remote_type);
		break;
	}
	return error;
}
/* Issue shell commands independent of transport type and return result */
static int
rwl_shell_information_fe(void *wl, int cmd, uchar* input_buf, unsigned long *input_len)
{
	int error = 0, remote_cmd;
	uchar* resp_buf = NULL;
	rem_ioctl_t *rem_ptr = NULL;

#ifdef RWL_WIFI
	char *cbuf, retry;
	dot11_action_wifi_vendor_specific_t *list;
#endif

#ifdef RWL_SOCKET
	int Sockfd;
#endif

	remote_cmd = REMOTE_SHELL_CMD;

#ifdef RWLASD
	if (cmd == ASD_CMD)
		remote_cmd = REMOTE_ASD_CMD;
#endif
	if (cmd == VISTA_CMD)
		remote_cmd = REMOTE_VISTA_CMD;

	switch (remote_type) {
		case REMOTE_SOCKET:
#ifdef RWL_SOCKET
			if ((Sockfd = rwl_connect_socket_server()) < 0) {
				DPRINT_ERR(ERR, " Error in getting the SocDes\n");
				return BCME_ERROR;
			}

			wl = (void *)(&Sockfd);
			if (remote_CDC_tx(wl, cmd, input_buf, *input_len, *input_len,
				remote_cmd, 0) < 0) {
				DPRINT_ERR(ERR, "shell_info_fe: Send command failed\n");
				rwl_close_pipe(remote_type, wl);
				return BCME_ERROR;
			}
			/* For backward compatibility for ASD, async and kill commands do the
			 * old way
			 */
			if (remote_cmd == REMOTE_SHELL_CMD && !strstr((char*)input_buf, "%") &&
				!strstr((char*)input_buf, "kill"))
				error = rwl_socket_shellresp(wl, rem_ptr, input_buf);
			else {
				if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
					DPRINT_ERR(ERR, "shell_info_fe: Receiving CDC"
						"header failed\n");
					rwl_close_pipe(remote_type, wl);
					return FAIL;
				}

				if ((resp_buf = malloc(rem_ptr->msg.len + 1)) == NULL) {
					DPRINT_ERR(ERR, "Mem alloc fails\n");
					rwl_close_pipe(remote_type, wl);
					return FAIL;
				}

				if (remote_CDC_rx(wl, rem_ptr, resp_buf,
					rem_ptr->msg.len, 0) == FAIL) {
					DPRINT_ERR(ERR, "shell_info_fe: No results!\n");
					rwl_close_pipe(remote_type, wl);
					free(resp_buf);
					return FAIL;
				}

				/* print the shell result */
				resp_buf[rem_ptr->msg.len] = '\0';
				/* The return value of the shell command
				 * will be stored in rem_ptr->msg.cmd
				 * Return that value to the client process
				 */
				if (rem_ptr->msg.flags & REMOTE_REPLY)
					error = rem_ptr->msg.cmd;
				fputs((char*)resp_buf, stdout);
			}
			rwl_close_pipe(remote_type, wl);
#endif /* RWL_SOCKET */
			break;
#if defined( RWL_DONGLE ) || defined( RWL_SERIAL )
		case REMOTE_DONGLE:
		case REMOTE_SERIAL:
			if (remote_CDC_tx(wl, cmd, input_buf, *input_len, *input_len,
			                  remote_cmd, 0) < 0) {
				DPRINT_ERR(ERR, "shell_info_fe: Send command failed\n");
				return FAIL;
			}

			/* For backward compatibility for ASD, async and kill commands do the
			 * old way
			 */
//			if (remote_cmd != REMOTE_ASD_CMD && !strstr((char*)input_buf, "%") &&
//				!strstr((char*)input_buf, "kill"))
//				error = rwl_dongle_shellresp(wl, rem_ptr, input_buf, cmd);
//			else 
			{
				if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
					DPRINT_ERR(ERR, "shell_info_fe:"
					"Receiving CDC header failed\n");
					return BCME_SERIAL_PORT_ERR;
				}
			rwl_swap_header(rem_ptr, NETWORK_TO_HOST);
			/* In case of shell or ASD commands the response
			 * size is not known in advance
			 * Hence based on response from the server memory is allocated
			 */
			if ((resp_buf = malloc(rem_ptr->msg.len + 1)) == NULL) {
				DPRINT_ERR(ERR, "Mem alloc fails for shell response buffer\n");
				return FAIL;
			}

			if (rem_ptr->data_len < DATA_FRAME_LEN) {
				/* Response comes in one shot not in fragments */
				if (remote_CDC_rx(wl, rem_ptr, resp_buf,
					rem_ptr->msg.len, 0) == FAIL) {
					DPRINT_ERR(ERR, "shell_info_fe: No results!\n");
					free(resp_buf);
					return FAIL;
				}
			} else {
				error = rwl_serial_fragmented_response_fe(wl, rem_ptr,
					resp_buf, (unsigned long *)&(rem_ptr->msg.len));
			}
			/* print the shell result */
			resp_buf[rem_ptr->msg.len] = '\0';
			/* The return value of the shell command will be stored in rem_ptr->msg.cmd
			 * Return that value to the client process
			 */
				if (rem_ptr->msg.flags & REMOTE_REPLY)
					error = rem_ptr->msg.cmd;
			fputs((char*)resp_buf, stdout);
			}
			break;
#endif //if defined( RWL_DONGLE ) || defined( RWL_SERIAL )

		case REMOTE_WIFI:
#ifdef RWL_WIFI
			/* Unlike dongle or UART case the response for wi-fi comes in single frame.
			 * (CDC header + data). Hence the single read is called for header and data.
			 * If any error in reading then we sleep for some time before retrying.
			 */
			if ((list = (dot11_action_wifi_vendor_specific_t *)
				malloc(RWL_WIFI_ACTION_FRAME_SIZE)) == NULL) {
				return FAIL;
			}
			if ((rem_ptr = (rem_ioctl_t *)malloc(REMOTE_SIZE)) == NULL) {
				free(list);
				return FAIL;
			}

			if ((cbuf = (char*) malloc(*input_len)) == NULL) {
				DPRINT_ERR(ERR, "Malloc failed for shell response\n");
				free(rem_ptr);
				free(list);
				return FAIL;
			}

			/* copy of the original buf is required for retry */
			memcpy(cbuf, (char*)input_buf, *input_len);
			for (retry = 0; retry < RWL_WIFI_RETRY; retry++) {

				rwl_wifi_purge_actionframes(wl);
				if (remote_CDC_tx(wl, cmd, input_buf, *input_len, *input_len,
				remote_cmd, 0) < 0) {
						DPRINT_DBG(OUTPUT, "rwl_shell_information_fe(wifi):"
							"Send command failed\n");
						rwl_sleep(RWL_WIFI_RETRY_DELAY);
						free(rem_ptr);
						free(list);
						return FAIL;
				}
				/* For backward compatibility for ASD,
				 * async and kill commands do the
				 * old way
				 */
				if (remote_cmd == REMOTE_SHELL_CMD &&
					!strstr((char*)input_buf, "%") &&
					!strstr((char*)input_buf, "kill")) {
					error = rwl_wifi_shellresp(wl, rem_ptr, input_buf);
						if (rem_ptr->msg.len == 0)
						break;
					}
				else if (remote_cmd == REMOTE_VISTA_CMD) {
					if ((error = remote_CDC_DATA_wifi_rx_frag(wl, rem_ptr, 0,
					NULL, RWL_WIFI_SHELL_CMD)) < 0) {
						DPRINT_DBG(OUTPUT, "rwl_shell_information_fe(wifi):"
						"error in reading shell response\n");
						continue;
					}
					if (rem_ptr->msg.flags & REMOTE_REPLY) {
						 error = rem_ptr->msg.cmd;
						 break;
					} else {
						rwl_sleep(RWL_WIFI_RETRY_DELAY);
						continue;
					}
				}
				else {
					/* ASD commands may take long time to give back
					* the response (eg: file transfer)
					*/
					if (remote_cmd == REMOTE_ASD_CMD) {
						for (;;) {
						/* copy back the buffer to input buffer */
						memcpy((char*)input_buf, cbuf, *input_len);

							if ((error = remote_CDC_DATA_wifi_rx_frag(
								wl, rem_ptr, 0, NULL,
								RWL_WIFI_SHELL_CMD)) < 0) {
								DPRINT_DBG(OUTPUT,
								"rwl_shell_information_fe(wifi):"
								"err in reading shell response\n");
								continue;
							}
							if (rem_ptr->msg.flags & REMOTE_REPLY) {
								error = rem_ptr->msg.cmd;
								retry = RWL_WIFI_RETRY;
								break;
							} else {
								rwl_sleep(RWL_WIFI_RETRY_DELAY);
								continue;
							}
						}
					}
				}

			}
			free(rem_ptr);
			free(list);
			if (cbuf != NULL)
				free(cbuf);
#endif /* RWL_WIFI */
			break;

		default:
			break;
	} /* End of switch (remote_type) */

	if (resp_buf)
		free(resp_buf);

	return error;
}
Example #12
0
/* Function: remote_rx_header
 * This function will receive the CDC header from client
 * for socket transport
 * It will receive the command or ioctl from dongle driver for
 * dongle UART serial transport and wifi transport.
 * Arguments: wl - handle to driver
 *          : Des - Socket Descriptor to pass in AcceptConnection
 *          : g_rwl_hndle - Return socket handle that is used for transmission
 *          :           and reception of data in case of socket
 *                        In case of serial, it is just a return value
 */
static int
remote_rx_header(void *wl, int trans_Des)
{
	UNUSED_PARAMETER(wl);
	UNUSED_PARAMETER(trans_Des);

#ifdef RWL_SOCKET
	{
		struct sockaddr_in ClientAddress;
		int SizeOfCliAdd = sizeof(ClientAddress);

		/* Get the socket handle g_rwl_hndle for transmission & reception */
		if ((g_rwl_hndle = rwl_acceptconnection(trans_Des,
		                                        (struct sockaddr *)&ClientAddress,
		                                        &SizeOfCliAdd)) == BCME_ERROR) {
			return BCME_ERROR;
		}

		/* Get CDC header in order to determine buffer requirements */
		if ((g_rem_ptr = remote_CDC_rx_hdr((void *)&g_rwl_hndle, 0)) == NULL) {
			DPRINT_DBG(OUTPUT, "\n Waiting for client to transmit command\n");
			return BCME_ERROR;
		}
	}
#endif /* RWL_SOCKET */

#ifdef RWL_DONGLE
	{
		void *pkt_ptr = NULL;
		int error;

		/* wl driver is polled after every 200 ms (POLLING_TIME) */
		rwl_sleep(POLLING_TIME);

		if ((error = rwl_var_getbuf(wl, cmdname, NULL, 0, &pkt_ptr)) < 0) {
			DPRINT_ERR(ERR, "No packet in wl driver\r\n");
			return BCME_ERROR;
		}

		DPRINT_DBG(OUTPUT, "Polling the wl driver, error status=%d\n", error);

		if ((*(int *)pkt_ptr) == 0) {
			DPRINT_DBG(ERR, "packet not received\n");
			return BCME_ERROR;
		}

		DPRINT_DBG(OUTPUT, "packet received\n");

		/* Extract CDC header in order to determine buffer requirements */
		memcpy(g_rem_pkt_ptr, pkt_ptr, sizeof(rem_packet_t));
		g_rem_ptr = &g_rem_pkt_ptr->rem_cdc;
	}
#endif /* RWL_DONGLE */

#ifdef RWL_SERIAL
	{
		if (g_rwl_hndle == -1) {
			DPRINT_ERR(ERR, "failed to open com port.\r\n");
			return BCME_ERROR;
		}

		if ((g_rem_ptr = remote_CDC_rx_hdr((void *)&g_rwl_hndle, 1)) == NULL) {
			DPRINT_DBG(OUTPUT, "\n Waiting for client to transmit command\n");
			return BCME_ERROR;
		}
	}
#endif  /* RWL_SERIAL */

#ifdef RWL_WIFI
	{
		/* Poll the driver for the valid action frame and update the CDC + data  */
		dot11_action_wifi_vendor_specific_t *list;

		if ((list = rwl_wifi_allocate_actionframe()) == NULL) {
			DPRINT_DBG(OUTPUT, "remote_rx_header: Failed to allocate frame \n");
			return BCME_ERROR;
		}

		if (remote_CDC_DATA_wifi_rx((void *)wl, list) < 0) {
			free(list);
			return BCME_ERROR;
		}

		/* copy the valid length of the data to the g_rem_pkt_ptr */
		memcpy(g_rem_pkt_ptr, &list->data[0], sizeof(rem_packet_t));
		g_rem_ptr = &g_rem_pkt_ptr->rem_cdc;
		free(list);
	}
#endif /* RWL_WIFI */

	rwl_swap_header(g_rem_ptr, NETWORK_TO_HOST);

	DPRINT_INFO(OUTPUT, "%d %d %d %d\r\n", g_rem_ptr->msg.cmd,
	g_rem_ptr->msg.len, g_rem_ptr->msg.flags, g_rem_ptr->data_len);

	return SUCCESS;

}