Ejemplo n.º 1
0
/*
 * This function is used for transmitting the response over different
 * transports.
 * In case of socket the data is directly sent to the client which is waiting on a open socket.
 * In case of socket the data is sent in one big chunk unlike other transports
 *
 * In case of serial the data is sent to the driver using remote_CDC_dongle_tx function
 * which in turn may fragment the data and send it in chunks to the client.
 *
 * In case of wi-fi the data is sent to the driver using the remote_CDC_tx. However
 * in this case the data is converted into 802.11 Action frames and sent using wi-fi driver.
 * Arguments: wl - Driver handle
 *            hndle - Socket handle for socket transport.
 */
int
remote_tx_response(void *wl, void* buf_ptr, int cmd)
{
	int error = -1;

	UNUSED_PARAMETER(wl);
	UNUSED_PARAMETER(buf_ptr);
	UNUSED_PARAMETER(cmd);

#if defined (RWL_SOCKET) || defined (RWL_SERIAL)
	if ((error = remote_CDC_tx((void*)&g_rwl_hndle, cmd, buf_ptr, g_rem_ptr->msg.len,
	                                  g_rem_ptr->msg.len, REMOTE_REPLY, 0)) < 0)
		DPRINT_ERR(ERR, "wl_server: Return results failed\n");
#endif /* RWL_SOCKET || RWL_SERIAL */

#ifdef RWL_DONGLE
	if ((error = remote_CDC_dongle_tx(wl, cmd, buf_ptr, g_rem_ptr->msg.len,
	                          g_rem_ptr->data_len, g_rem_ptr->msg.flags)) < 0)
		DPRINT_ERR(ERR, "wl_server: Return results failed\n");
#endif /* RWL_DONGLE */

#ifdef RWL_WIFI
	/* Purge all the queued cmd's , this to ensure late response time out at */
	/* client side and client might issue the next cmd if server is slow */
	rwl_wifi_purge_actionframes(wl);
	if ((g_rem_ptr->msg.flags & REMOTE_SHELL_CMD) ||
		(g_rem_ptr->msg.flags & REMOTE_GET_IOCTL)||
		(g_rem_ptr->msg.flags & REMOTE_ASD_CMD) ||
		(g_rem_ptr->msg.flags & REMOTE_VISTA_CMD)) {
		if ((error = remote_CDC_tx(wl, cmd, buf_ptr, g_rem_ptr->msg.len,
			g_rem_ptr->msg.len, REMOTE_REPLY, 0)) < 0)
			DPRINT_ERR(ERR, "Wifi_server: Return results failed\n");
	} else {
		if ((error = remote_CDC_tx(wl, cmd, buf_ptr, 0, 0, REMOTE_REPLY, 0)) < 0)
			DPRINT_ERR(ERR, "Failed due to bad flag %d\n", g_rem_ptr->msg.flags);
	}
#endif /* RWL_WIFI */
	return error;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
/*
* 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;
}
Ejemplo n.º 4
0
/* 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;
}
Ejemplo n.º 5
0
/* 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;
}