Ejemplo n.º 1
0
static int
rwl_socket_shellresp(void *wl, rem_ioctl_t *rem_ptr, uchar *input_buf)
{
	uchar* resp_buf = NULL;
	int pid, msg_len, error;
	g_sig_ctrlc = 1;
	g_child_pid = pid = rwl_shell_createproc(wl);
	if (pid == 0) {
		while (g_sig_ctrlc);
		remote_CDC_tx(wl, 0, input_buf, 0, 0, CTRLC_FLAG, 0);
		exit(0);
	}

	do {
		if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
		DPRINT_ERR(ERR, "rwl_socket_shellresp: Receiving CDC"
			"header failed\n");
		rwl_close_pipe(remote_type, wl);
		return FAIL;
		}
		msg_len = rem_ptr->msg.len;
		if ((resp_buf = malloc(rem_ptr->msg.len + 1)) == NULL) {
			DPRINT_ERR(ERR, "rwl_socket_shellresp: Mem alloc fails\n");
			rwl_close_pipe(remote_type, wl);
			return FAIL;
		}
		if (msg_len > 0) {
			if (remote_CDC_rx(wl, rem_ptr, resp_buf,
				rem_ptr->msg.len, 0) == FAIL) {
				DPRINT_ERR(ERR, "rwl_socket_shellresp: 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;
#ifdef LINUX
		write(1, resp_buf, msg_len);
#else
		fputs((char*)resp_buf, stdout);
#endif
	} while (msg_len);
	rwl_shell_killproc(pid);
	return error;
}
Ejemplo n.º 2
0
/* This routine is used for both Get and Set Ioctls for the socket */
static int
rwl_information_socket(void *wl, int cmd, void* input_buf, unsigned long *input_len,
	unsigned long *tx_len, uint flags)
{
	int error, Sockfd;
	rem_ioctl_t *rem_ptr = NULL;

	if ((Sockfd = rwl_connect_socket_server()) < 0) {
		DPRINT_ERR(ERR, "Error in getting the Socket Descriptor\n");
		return FAIL;
	}
	wl = (void *)(&Sockfd);

	if (remote_CDC_tx(wl, cmd, input_buf, *input_len,
		*tx_len, flags, 0) < 0) {
		DPRINT_ERR(ERR, "query_info_fe: Send command failed\n");
		rwl_close_pipe(remote_type, wl);
		return FAIL;
	}

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

	if (rem_ptr->msg.len > *input_len) {
		DPRINT_ERR(ERR, "query_info_fe: needed size(%d) > "
		           "actual size(%ld)\n", rem_ptr->msg.len, *input_len);
		rwl_close_pipe(remote_type, wl);
		return FAIL;
	}

	if (remote_CDC_rx(wl, rem_ptr, input_buf, *input_len, 0) == FAIL) {
		DPRINT_ERR(ERR, "query_info_fe: No results!\n");
		rwl_close_pipe(remote_type, wl);
		return FAIL;
	}

	if (rem_ptr->msg.flags & REMOTE_REPLY)
		error = rem_ptr->msg.cmd;
	else
		error = 0;

	rwl_close_pipe(remote_type, wl);

	return error;
}
Ejemplo n.º 3
0
/* Close the Socket handle */
void close_sock_handle(int hndle)
{
#ifdef RWL_SOCKET
	rwl_close_pipe(remote_type, (void*)&hndle);
#else
	UNUSED_PARAMETER(hndle);
#endif
}
Ejemplo n.º 4
0
/* Make initial connection from client to server through sockets */
static int
rwl_connect_socket_server(void)
{
	int SockDes = -1;
	struct sockaddr_in servAddr;
	int retries = 0;
	int max_retries = 20;
	int connected = 0;

	memset(&servAddr, 0, sizeof(servAddr));

	while ((connected == 0) && (retries < max_retries)) {
		DPRINT_DBG(OUTPUT, "rwl_connect_socket_server retry %d\n", retries);
		if ((SockDes = (*(int *)rwl_open_pipe(remote_type, "\0", 0, 0))) == FAIL) {
			retries++;
			continue;
		}
		/*if (!validate_server_address()) {
			retries++;
			continue;
		}*/

		DPRINT_DBG(OUTPUT, "ServerIP:%s,ServerPort:%d\n", g_rwl_servIP, g_rwl_servport);
		servAddr.sin_family = AF_INET;
		servAddr.sin_port = hton16(g_rwl_servport);
		servAddr.sin_addr.s_addr = inet_addr(g_rwl_servIP);

		if (rwl_sockconnect(SockDes, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0) {
			rwl_close_pipe(remote_type, (void*) &SockDes);
			retries++;
			continue;
		} else
			connected = 1;
	}
	return SockDes;
}
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;
}
Ejemplo n.º 6
0
/* Main server module common for all transports
 * This module will do the initial transport setups.
 * Then it receives the command from client in CDC format
 * and transmits the response back to the client.
 * In the case of socket, it receives the command from the client
 * and sends the response directly to the client via TCP socket.
 *
 * In the case of serial & wifi , it receives the command from the driver
 * and sends the response to the driver.
 */
int
remote_server_exec(int argc, char **argv, void *wl)
{
	int err;
	int transport_descriptor;
	char *async_cmd_flag = NULL;
	int skip;
	int download_flag = 0;
#if defined(LINUX) || defined(vxworks) || defined(OLYMPIC_RWL)
	char old_intf_name[IFNAMSIZ];
#endif
#ifdef WIN32
	char shell_fname[MAX_SHELL_FILE_LENGTH];
	DWORD dwlen;
#endif
#ifdef RWL_DONGLE
	int uart_enable = 1;
	/* To set dongle flag when dongle server starts */
	if ((err = rwl_var_setbuf(wl, dongleset, &uart_enable,
		sizeof(int))) < 0) {
			DPRINT_INFO(OUTPUT, "Unable to send to wl driver,error=%d\n", err);
	}
#endif
	if (rwl_iovar_check (wl) < 0) {
		DPRINT_ERR(ERR, "wl_server: RWL_WIFI/RWL_DONGLE not defined ");
		DPRINT_ERR(ERR, "Or In-Dongle mode enabled\n");
		exit(0);
	}
	/* Initialise for all the transports - socket, serial, and wifi
	 * In Socket transport, main socket handler will be returned.
	 */
	if ((transport_descriptor = rwl_transport_setup(argc, argv)) < 0)
		return BCME_ERROR;

#ifdef RWL_WIFI
	remote_wifi_ser_init_cmds(wl);
#endif
	/* Create a directory /tmp/RWL for the shell response files */
	if (rwl_create_dir() < 0)
		return BCME_ERROR;


#ifdef RWLASD
	/* DUT initialization function */
	wfa_dut_init(&trafficBuf, &respBuf, &parmsVal, &xcCmdBuf, &toutvalp);
#endif

#if defined(LINUX) || defined(vxworks)
	/* Copy old interface name to restore it */
	store_old_interface(wl, old_intf_name);
#endif /* defined(LINUX) || defined(vxworks) */

	while (1) {
		uchar *buf_ptr = NULL;
#ifdef VISTA_SERVER
		int index;
		char *vista_buf[MAX_VISTA_ARGC];
#endif
#ifdef RWL_SERIAL
		g_rwl_hndle = transport_descriptor;
#else
		g_rwl_hndle = -1;
#endif
#ifdef RWL_DONGLE
		if (set_ctrlc) {
			uart_enable = 0;
			if ((err = rwl_var_setbuf(wl, dongleset, &uart_enable,
				sizeof(int))) < 0) {
				DPRINT_INFO(OUTPUT, "Unable to send to wl driver,error=%d\n", err);
			}
			set_ctrlc = 0;
			exit(0);
		}
#endif /* RWL_DONGLE */

		/* Receive the CDC header */
		if ((remote_rx_header(wl, transport_descriptor)) == BCME_ERROR) {
			DPRINT_DBG(OUTPUT, "\n Waiting for client to transmit command\n");
			continue;
		}

		DPRINT_INFO(OUTPUT, "REC : cmd %d\t msg len %d  msg flag %d\t msg status %d\n",
		            g_rem_ptr->msg.cmd, g_rem_ptr->msg.len,
		            g_rem_ptr->msg.flags, g_rem_ptr->msg.status);

#ifdef RWL_WIFI
		/* send the response to remote if it is findserver cmd, this is specific to wifi */
		if (g_rem_ptr->msg.flags & REMOTE_FINDSERVER_IOCTL) {
			remote_wifi_response(wl);
			continue;
		}
#endif /* RWL_WIFI */

		/*
		 * Allocate buffer only if there is a response message expected.
		 * Some commands such as up/down do not output anything.
		 */
		if (g_rem_ptr->msg.len) {
			if ((buf_ptr = malloc(g_rem_ptr->msg.len)) == NULL) {
				DPRINT_ERR(ERR, "malloc of %d bytes failed\n", g_rem_ptr->msg.len);
				continue;
			}
		}

		/* Receive the data */
		if ((err = remote_rx_data(buf_ptr)) == BCME_ERROR) {
			if (buf_ptr)
				free(buf_ptr);
			continue;
		}

		/* Process RWL negotiate commands */
		if (g_rem_ptr->msg.flags & REMOTE_NEGOTIATE_CMD) {
			if (g_rem_ptr->msg.cmd == NEGOTIATE_GET_OS) {
				if (g_rem_ptr->msg.len >= sizeof(int)) {
#if defined(LINUX)
					*(int*)buf_ptr = LINUX_OS;
#elif defined(VISTA_SERVER)
					*(int*)buf_ptr = WINVISTA_OS;
#elif defined(WIN32)
					*(int*)buf_ptr = WIN32_OS;
#elif defined(MACOSX)
					*(int*)buf_ptr = MAC_OSX;
#else
					*(int*)buf_ptr = UNKNOWN_OS;
#endif
					g_rem_ptr->msg.len = sizeof(int);

					DPRINT_INFO(OUTPUT, "RESP : os type %d\n", *(int*)buf_ptr);
					if (remote_tx_response(wl, buf_ptr, 0) < 0)
						DPRINT_ERR(ERR, "\nReturn results failed\n");
				}
			}
#ifdef RWL_SOCKET
			close_sock_handle(g_rwl_hndle);
#endif /* RWL_SOCKET */
			if (buf_ptr)
				free(buf_ptr);
			continue;
		}

		/* Process command */
		if (g_rem_ptr->msg.flags & REMOTE_SHELL_CMD) {
			/* Get the response length first and get the response buffer in case of
			 * synchronous shell commands and the buf_ptr will have the response file
			 * name. In case of asynchronous shell commands, buf_ptr
			 * will be get updated by the remote_shell_execute function.
			 */
			need_speedy_response = 1;
#ifndef WIN32
			if (buf_ptr) {
				async_cmd_flag = strstr((char*)buf_ptr, "%");
			}
			if ((err = remote_shell_execute((char*)buf_ptr, wl)) > 0) {
				if (async_cmd_flag)
					g_rem_ptr->msg.len = err;
			}
			/* Sync shell command: No need to send response from here */
			else {
#ifdef RWL_SOCKET
				/* Transmitted to client. Then close the handle &
				 * get the new handle for next transmission & reception.
				 */
				close_sock_handle(g_rwl_hndle);
#endif /* RWL_SOCKET */
				continue;
			}
#else
			if ((err = remote_shell_execute((char*)buf_ptr, wl)) != SUCCESS) {
				DPRINT_ERR(ERR, "Error in executing shell command\n");
				if (buf_ptr)
					free(buf_ptr);
#ifdef RWL_SOCKET
				/* Transmitted to client. Then close the handle &
				 * get the new handle for next transmission & reception.
				 */
				close_sock_handle(g_rwl_hndle);
#endif /* RWL_SOCKET */
				continue;
			}
			/* Get the response from the temporary file */
			if ((err = remote_shell_get_resp(shell_fname, wl)) != SUCCESS) {
				DPRINT_ERR(ERR, "Error in executing shell command\n");
			}
			if (buf_ptr)
				free(buf_ptr);
#ifdef RWL_SOCKET
			/* Transmitted to client. Then close the handle &
			 * get the new handle for next transmission & reception.
			 */
			close_sock_handle(g_rwl_hndle);
#endif /* RWL_SOCKET */
			continue;
#endif	/* WIN32 */
		} /* REMOTE_SHELL_CMD */

#ifdef RWLASD
		if (g_rem_ptr->msg.flags & REMOTE_ASD_CMD) {
			if ((err = remote_asd_exec(buf_ptr, (int *)&g_rem_ptr->msg.len)) < 0) {
				DPRINT_ERR(ERR, "Error in executing asd command\n");
			}
		} /* REMOTE_ASD_CMD */
#endif

/*
 * added to take care of OID base problem for cross OS RWL cleint server
 * In case of LX Server and WIN32 client OID base need to be removed
 * In case of WIN32 server and LX client OID base need to be added
 */
		if (!(g_rem_ptr->msg.flags & REMOTE_ASD_CMD)) {
#if defined(LINUX) || defined(vxworks)
		if (g_rem_ptr->msg.cmd > MAX_IOVAR)
			g_rem_ptr->msg.cmd -= WL_OID_BASE;
#endif
#if defined(WIN32)
		if (g_rem_ptr->msg.cmd < MAX_IOVAR)
			g_rem_ptr->msg.cmd += WL_OID_BASE;
#endif
		}
#ifdef VISTA_SERVER
		if (g_rem_ptr->msg.flags & REMOTE_VISTA_CMD) {
			vista_buf[0] = strtok(buf_ptr, " \t\n");
			for (index = 1; (vista_buf[index] = strtok(NULL, " \t\n")) != NULL;
				index++);
			if ((err = remote_vista_exec(wl, vista_buf)) < 0) {
				DPRINT_ERR(ERR, "Error in executing vista command\n");
			}
			memcpy(buf_ptr, vista_buf[0], strlen(vista_buf[0]));
			g_rem_ptr->msg.len = strlen(vista_buf[0]);
		} /* REMOTE_VISTA_CMD */
#endif /* VISTA_SERVER */

#ifndef OLYMPIC_RWL
#if defined(LINUX) || defined(vxworks)
#ifndef RWL_DONGLE
		if (g_rem_ptr->msg.flags & REMOTE_GET_IOCTL ||
			g_rem_ptr->msg.flags & REMOTE_SET_IOCTL) {
			if (strlen(g_rem_ptr->intf_name) != 0) {
#if defined(LINUX)
				struct ifreq ifr;
				/* validate the interface */
				memset(&ifr, 0, sizeof(ifr));
				if (g_rem_ptr->intf_name)
					strncpy(ifr.ifr_name, g_rem_ptr->intf_name, IFNAMSIZ);

				if (wl_check((void *)&ifr)) {
					DPRINT_ERR(ERR, "%s: wl driver adapter not found\n",
						g_rem_ptr->intf_name);
					/* Signal end of command output */
					g_rem_ptr->msg.len = 0;
					remote_tx_response(wl, NULL, BCME_NODEVICE);
					if (buf_ptr)
						free(buf_ptr);
#ifdef RWL_SOCKET
					close_sock_handle(g_rwl_hndle);
#endif
					continue;
				}
#endif /* LINUX */
#if defined(vxworks)
				if (wl_check((void *)g_rem_ptr->intf_name)) {
					DPRINT_ERR(ERR, "%s: wl driver adapter not found\n",
						g_rem_ptr->intf_name);
					/* Signal end of command output */
					g_rem_ptr->msg.len = 0;
					remote_tx_response(wl, NULL, BCME_NODEVICE);
					if (buf_ptr)
						free(buf_ptr);
#ifdef RWL_SOCKET
					close_sock_handle(g_rwl_hndle);
#endif
					continue;
				}
#endif /* vxworks */

				if (set_interface(wl, g_rem_ptr->intf_name) == BCME_OK)
					DPRINT_DBG(OUTPUT, "\n %s Interface will be used \n",
						(char *)wl);
			}
		}
#endif /* ifndef RWL_DONGLE */
#endif /* defined(LINUX) || defined(vxworks) */
#endif /* ifndef OLYMPIC_RWL */
		if (g_rem_ptr->msg.flags & REMOTE_SET_IOCTL ||
			g_rem_ptr->msg.flags & RDHD_SET_IOCTL) {
#ifdef WIN32
#if defined (RWL_DONGLE) || defined (RWL_WIFI)
			/* For commands with msg length as zero initialize the buffer to null */
			if (g_rem_ptr->msg.len == 0)
				buf_ptr = NULL;
#endif
#else
			if (g_rem_ptr->msg.len == 0)
				buf_ptr = NULL;
#endif /* WIN32 */

#if defined(LINUX) || defined(TARGETOS_symbian) || defined(TARGETOS_nucleus) || defined(MACOSX) || defined(TARGET_wiced)
#ifdef OLYMPIC_RWL
			set_interface(wl, old_intf_name);
#endif
#if defined( TARGET_wiced )
            set_interface(wl, g_rem_ptr->intf_name);
#endif
			if (g_rem_ptr->msg.flags & REMOTE_SET_IOCTL) {
				if (g_rem_ptr->msg.cmd == WLC_SET_VAR && buf_ptr &&
				    !strncmp((const char *)buf_ptr,
					     "init", g_rem_ptr->msg.len)) {
					DPRINT_INFO(OUTPUT, "REC : init command\n");
					err = 0;
				} else if (g_rem_ptr->msg.cmd == WLC_SET_VAR && buf_ptr &&
				   !strncmp((const char *)buf_ptr,
					    "download", g_rem_ptr->msg.len)) {
					DPRINT_INFO(OUTPUT, "REC : download command\n");
					download_flag =  download_flag? 0: 1;
					if (download_flag) {
						DPRINT_INFO(OUTPUT, "download started\n");
						start_download( );
					} else {
						DPRINT_INFO(OUTPUT, "download completed\n");
						finish_download( );
					}
					err = 0;
				} else if (g_rem_ptr->msg.cmd == WLC_SET_VAR && buf_ptr &&
				   !strncmp((const char *)buf_ptr,
					    "membytes", g_rem_ptr->msg.len)) {
					DPRINT_INFO(OUTPUT, "REC : membytes command\n");
					skip = strlen("membytes ");
					uint32_t address = *((uint32_t*)(buf_ptr + skip));
					skip += sizeof(uint32_t);
                    uint32_t len = *((uint32_t*)(buf_ptr + skip));
                    skip += sizeof(uint32_t);
                    if ( len != g_rem_ptr->msg.len - skip )
                    {
                        DPRINT_ERR(ERR, "Length does not match\n");
                    }
					membytes_write( address, buf_ptr + skip, g_rem_ptr->msg.len - skip );
					err = 0;
				} else {
					err = wl_ioctl(wl, g_rem_ptr->msg.cmd,
					       (void *)buf_ptr, g_rem_ptr->msg.len, TRUE);
					DPRINT_INFO(OUTPUT, "SEND : cmd %d\t msg len %d\n",
					    g_rem_ptr->msg.cmd, g_rem_ptr->msg.len);
					DPRINT_INFO(OUTPUT, "error code: %d\n", err);
				}
			}
#if defined(LINUX)
			if (err == IOCTL_ERROR) {
				DPRINT_ERR(ERR, "Error in executing wl_ioctl\n");
				DPRINT_ERR(ERR, "Setting Default Interface1 \n");
				set_interface(wl, old_intf_name);
			}

			if (g_rem_ptr->msg.flags & RDHD_SET_IOCTL) {
				err = dhd_ioctl(wl, g_rem_ptr->msg.cmd,
				(void *)buf_ptr, g_rem_ptr->msg.len, TRUE);
			}
#endif /* LINUX */

#elif vxworks
			if ((err = wl_ioctl_vx(wl, g_rem_ptr->msg.cmd, (void *)buf_ptr,
				g_rem_ptr->msg.len)) != 0) {
				DPRINT_ERR(ERR, "Error in executing wl_ioctl_vx\n");
			}

			if (err == IOCTL_ERROR) {
				DPRINT_ERR(ERR, "Error in executing wl_ioctl\n");
				DPRINT_ERR(ERR, "Setting Default Interface \n");
				set_interface(wl, old_intf_name);
			}
#elif WIN32
			dwlen = g_rem_ptr->msg.len;
			if (g_rem_ptr->msg.flags & RDHD_SET_IOCTL) {
				g_rem_ptr->msg.cmd = g_rem_ptr->msg.cmd
					- WL_OID_BASE + OID_DHD_IOCTLS;
			}

			err = (int)ir_setinformation(wl, g_rem_ptr->msg.cmd,
			                       buf_ptr, &dwlen);
#endif /* LINUX TARGETOS_symbian MACOSX */
			g_rem_ptr->msg.flags = REMOTE_SET_IOCTL;

		} /* RDHD/REMOTE_SET_IOCTL */

		if (g_rem_ptr->msg.flags & REMOTE_GET_IOCTL ||
			g_rem_ptr->msg.flags & RDHD_GET_IOCTL) {
#if defined(LINUX) || defined(TARGETOS_symbian) || defined(TARGETOS_nucleus) || defined(MACOSX) || defined(TARGET_wiced)
			if (g_rem_ptr->msg.cmd == WLC_GET_VAR && buf_ptr &&
				strncmp((const char *)buf_ptr, "exit", g_rem_ptr->msg.len) == 0) {
					/* exit command from remote client terminates server */
					free(buf_ptr);
					break;
			}
#if defined( TARGET_wiced )
            set_interface(wl, g_rem_ptr->intf_name);
#endif
			if (g_rem_ptr->msg.flags & REMOTE_GET_IOCTL)
				err = wl_ioctl(wl, g_rem_ptr->msg.cmd, (void *)buf_ptr,
					g_rem_ptr->msg.len, FALSE);
#if defined (LINUX)
			if (err == IOCTL_ERROR) {
				DPRINT_ERR(ERR, "REMOTE_GET_IOCTL::Error in executing wl_ioctl\n");
				DPRINT_ERR(ERR, "Setting Default Interface \n");
				set_interface(wl, old_intf_name);
			}

			if (g_rem_ptr->msg.flags & RDHD_GET_IOCTL)
				err = dhd_ioctl(wl, g_rem_ptr->msg.cmd, (void *)buf_ptr,
					g_rem_ptr->msg.len, FALSE);
#endif /* LINUX */
#elif vxworks
			if ((err = wl_ioctl_vx(wl, g_rem_ptr->msg.cmd, (void *)buf_ptr,
				g_rem_ptr->msg.len)) != 0) {
				DPRINT_ERR(ERR, "Error in executing wl_ioctl_vx\n");
			}

			if (err == IOCTL_ERROR) {
				DPRINT_ERR(ERR, "Error in executing wl_ioctl_vx\n");
				DPRINT_ERR(ERR, "Setting Default Interface \n");
				set_interface(wl, old_intf_name);
			}
#elif WIN32
			if (g_rem_ptr->msg.cmd == (WL_OID_BASE + WLC_GET_VAR) &&
				strncmp(buf_ptr, "exit", g_rem_ptr->msg.len) == 0) {
					/* exit command from remote client terminates server */
					if (buf_ptr) {
						free(buf_ptr);
					}
					break;
			}

			dwlen = g_rem_ptr->msg.len;
			if (g_rem_ptr->msg.flags & RDHD_GET_IOCTL) {
				g_rem_ptr->msg.cmd = g_rem_ptr->msg.cmd -
					WL_OID_BASE + OID_DHD_IOCTLS;
				}

			err = (int)ir_queryinformation(wl,
			g_rem_ptr->msg.cmd, buf_ptr, &dwlen);

#endif /* defined(LINUX) || defined(TARGETOS_symbian) || defined(TARGETOS_nucleus)  || defined(TARGET_wiced) */
			g_rem_ptr->msg.flags = REMOTE_GET_IOCTL;
		} /* REMOTE_GET_IOCTL */
		DPRINT_INFO(OUTPUT, "RESP : cmd %d\t msg len %d\n",
		g_rem_ptr->msg.cmd, g_rem_ptr->msg.len);
#if defined(LINUX) || defined(vxworks)
		/* setting back default interface  */
		set_interface(wl, old_intf_name);
#endif /*  defined(LINUX) || defined(vxworks) */
		/* Transmit the response results */
		if (remote_tx_response(wl, buf_ptr, err) < 0) {
			DPRINT_ERR(ERR, "\nReturn results failed\n");
		}

#ifdef RWL_SOCKET
		if (g_rem_ptr->msg.flags != REMOTE_SHELL_CMD)
		/* Transmitted to client. Then close the handle & get the new handle
		 * for next transmission & reception. In case of shell commands this
		 * should be closed in respective shellproc files.
		 */
		close_sock_handle(g_rwl_hndle);
#endif /* RWL_SOCKET */

		if (buf_ptr) {
			free(buf_ptr);
		}
	} /* end of while */
#if defined (RWL_SOCKET)
	/* Close the main handle for socket */
	close_sock_handle(transport_descriptor);
#elif defined(RWL_SERIAL)
	/* Close the main handle for serial pipe  */
	rwl_close_pipe(remote_type, (void*)&transport_descriptor);
#endif

#ifdef RWLASD
	wfa_dut_deinit();
#endif

	return err;
}
int
wl_lib(char *input_str)
{
    struct ifreq ifr;
    char *ifname = NULL;
    int err = 0;
    int help = 0;
    int status = CMD_WL;
    void* serialHandle = NULL;
    char *tmp_argv[LINUX_NUM_ARGS];
    char **argv = tmp_argv;
    int argc;

    /* buf_to_args return 0 if no args or string too long
     * or return NDIS_NUM_ARGS if too many args
     */
    if (((argc = buf_to_args(input_str, argv)) == 0) || (argc == LINUX_NUM_ARGS)) {
        printf("wl:error: can't convert input string\n");
        return (-1);
    }
#else
/* Main client function */
int
main(int argc, char **argv)
{
    struct ifreq ifr;
    char *ifname = NULL;
    int err = 0;
    int help = 0;
    int status = CMD_WL;
#if defined(RWL_DONGLE) || RWL_SERIAL
    void* serialHandle = NULL;
#endif

#endif /* WLMSO */
    wlu_av0 = argv[0];

    wlu_init();
    memset(&ifr, 0, sizeof(ifr));
    (void)*argv++;

    if ((status = wl_option(&argv, &ifname, &help)) == CMD_OPT) {
        if (ifname)
        {
            if (strcmp(ifname, "eth1") == 0)
            {
                strncpy(ifr.ifr_name, "wl0", IFNAMSIZ);
            }
            else if (strcmp(ifname, "eth2") == 0)
            {
                strncpy(ifr.ifr_name, "wl1", IFNAMSIZ);
            }
            else
            {
                strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
            }
        }
        /* Bug fix: If -h is used as an option, the above function call
         * will notice it and raise the flag but it won't be processed
         * in this function so we undo the argv increment so that the -h
         * can be spotted by the next call of wl_option. This will ensure
         * that wl -h [cmd] will function as desired.
         */
        else if (help)
            (void)*argv--;
    }

    /* Linux client looking for a indongle reflector */
    if (*argv && strncmp (*argv, "--indongle", strlen(*argv)) == 0) {
        rwl_dut_autodetect = FALSE;
        (void)*argv++;
    }
    /* Linux client looking for a WinVista server */
    if (*argv && strncmp (*argv, "--vista", strlen(*argv)) == 0) {
        rwl_os_type = WINVISTA_OS;
        rwl_dut_autodetect = FALSE;
        (void)*argv++;
    }

    /* Provide option for disabling remote DUT autodetect */
    if (*argv && strncmp(*argv, "--nodetect", strlen(*argv)) == 0) {
        rwl_dut_autodetect = FALSE;
        argv++;
    }

    if (*argv && strncmp (*argv, "--debug", strlen(*argv)) == 0) {
        debug = TRUE;
        argv++;
    }

    /* RWL socket transport Usage: --socket ipaddr/hostname [port num] */
    if (*argv && strncmp (*argv, "--socket", strlen(*argv)) == 0) {
        (void)*argv++;

        remote_type = REMOTE_SOCKET;

        if (!(*argv)) {
            rwl_usage(remote_type);
            return err;
        }
        /* IP address validation is done in client_shared file */
        g_rwl_servIP = *argv;
        (void)*argv++;

        g_rwl_servport = DEFAULT_SERVER_PORT;
        if ((*argv) && isdigit(**argv)) {
            g_rwl_servport = atoi(*argv);
            (void)*argv++;
        }
    }

    /* RWL from system serial port on client to uart serial port on server */
    /* Usage: --serial /dev/ttyS0 */
    if (*argv && strncmp (*argv, "--serial", strlen(*argv)) == 0) {
        (void)*argv++;
        remote_type = REMOTE_SERIAL;
    }

    /* RWL from system serial port on client to uart dongle port on server */
    /* Usage: --dongle /dev/ttyS0 */
    if (*argv && strncmp (*argv, "--dongle", strlen(*argv)) == 0) {
        (void)*argv++;
        remote_type = REMOTE_DONGLE;
    }

#if defined(RWL_SERIAL) || defined(RWL_DONGLE)
    if (remote_type == REMOTE_SERIAL || remote_type == REMOTE_DONGLE) {
        if (!(*argv)) {
            rwl_usage(remote_type);
            return err;
        }
        g_rwl_device_name_serial = *argv;
        (void)*argv++;
        if ((serialHandle = rwl_open_pipe(remote_type, g_rwl_device_name_serial, 0, 0))
                == NULL) {
            DPRINT_ERR(ERR, "serial device open error\r\n");
            return -1;
        }
        ifr = (*(struct ifreq *)serialHandle);
    }
#endif /*  RWL_SERIAL */

    /* RWL over wifi.  Usage: --wifi mac_address */
    if (*argv && strncmp (*argv, "--wifi", strlen(*argv)) == 0) {
        (void)*argv++;
        /* use default interface */
        if (!*ifr.ifr_name)
            wl_find(&ifr);
        /* validate the interface */
        if (!*ifr.ifr_name) {
            errno = ENXIO;
            syserr("interface");
        }
        if ((err = wl_check((void *)&ifr)) < 0) {
            fprintf(stderr, "%s: wl driver adapter not found\n", wlu_av0);
            exit(1);
        }

        remote_type = REMOTE_WIFI;

        if (argc < 4) {
            rwl_usage(remote_type);
            return err;
        }
        /* copy server mac address to local buffer for later use by findserver cmd */
        if (!wl_ether_atoe(*argv, (struct ether_addr *)g_rwl_buf_mac)) {
            fprintf(stderr,
                    "could not parse as an ethternet MAC address\n");
            return FAIL;
        }
        (void)*argv++;
    }

    if ((*argv) && (strlen(*argv) > 2) &&
            (strncmp(*argv, "--interactive", strlen(*argv)) == 0)) {
        interactive_flag = 1;
    }

    /* Process for local wl */
    if (remote_type == NO_REMOTE) {
        if (interactive_flag == 1)
            (void)*argv--;
        err = process_args(&ifr, argv);
        return err;
    } else {
#ifndef OLYMPIC_RWL
        /* Autodetect remote DUT */
        if (rwl_dut_autodetect == TRUE)
            rwl_detect((void*)&ifr, debug, &rwl_os_type);
#endif /* OLYMPIC_RWL */
    }

    /* RWL client needs to initialize ioctl_version */
    if (wl_check((void *)&ifr) != 0) {
        fprintf(stderr, "%s: wl driver adapter not found\n", wlu_av0);
        exit(1);
    }

    if (interactive_flag == 1) {
        err = do_interactive(&ifr);
        return err;
    }

    if ((*argv) && (interactive_flag == 0)) {
        err = process_args(&ifr, argv);
        if ((err == SERIAL_PORT_ERR) && (remote_type == REMOTE_DONGLE)) {
            DPRINT_ERR(ERR, "\n Retry again\n");
            err = process_args((struct ifreq*)&ifr, argv);
        }
        return err;
    }
    rwl_usage(remote_type);
#if defined(RWL_DONGLE) || RWL_SERIAL
    if (remote_type == REMOTE_DONGLE || remote_type == REMOTE_SERIAL)
        rwl_close_pipe(remote_type, (void*)&ifr);
#endif /* RWL_DONGLE || RWL_SERIAL */
    return err;
}

/*
 * Function called for  'local' execution and for 'remote' non-interactive session
 * (shell cmd, wl cmd)
 */
int
process_args(struct ifreq* ifr, char **argv)
{
    char *ifname = NULL;
    int help = 0;
    int status = 0;
    int vista_cmd_index;
    int err = 0;
    cmd_t *cmd = NULL;
#ifdef RWL_WIFI
    int retry;
#endif

    while (*argv) {
        if ((strcmp (*argv, "sh") == 0) && (remote_type != NO_REMOTE)) {
            (void)*argv++; /* Get the shell command */
            if (*argv) {
                /* Register handler in case of shell command only */
                err = rwl_shell_cmd_proc((void*)ifr, argv, SHELL_CMD);
            } else {
                DPRINT_ERR(ERR, "Enter the shell "
                           "command, e.g. ls(Linux) or dir(Win CE)\n");
                err = -1;
            }
            return err;
        }

#ifdef RWLASD
        if ((strcmp (*argv, "asd") == 0) && (remote_type != NO_REMOTE)) {
            (void)*argv++; /* Get the asd command */
            if (*argv) {
                err = rwl_shell_cmd_proc((void*)ifr, argv, ASD_CMD);
            } else {
                DPRINT_ERR(ERR, "Enter the ASD command, e.g. ca_get_version\n");
                err = -1;
            }
            return err;
        }
#endif
        if (rwl_os_type == WINVISTA_OS) {
            for (vista_cmd_index = 0; remote_vista_cmds[vista_cmd_index] &&
                    strcmp(remote_vista_cmds[vista_cmd_index], *argv);
                    vista_cmd_index++);
            if (remote_vista_cmds[vista_cmd_index] != NULL) {
                err = rwl_shell_cmd_proc((void *)ifr, argv, VISTA_CMD);
                if ((remote_type == REMOTE_WIFI) && ((!strcmp(*argv, "join")))) {
#ifdef RWL_WIFI
                    DPRINT_INFO(OUTPUT,
                                "\nChannel will be synchronized by Findserver\n\n");
                    sleep(RWL_WIFI_JOIN_DELAY);
                    for (retry = 0; retry < RWL_WIFI_RETRY; retry++) {
                        if ((rwl_find_remote_wifi_server(ifr,
                                                         &g_rwl_buf_mac[0]) == 0)) {
                            break;
                        }
                    }
#endif /* RWL_WIFI */
                }
                return err;
            }
        }

        if ((status = wl_option(&argv, &ifname, &help)) == CMD_OPT) {
            if (help)
                break;
            if (ifname) {
                if (remote_type == NO_REMOTE) {
                    strncpy((*ifr).ifr_name, ifname, IFNAMSIZ);
                }
                else {
                    strncpy(g_rem_ifname, ifname, IFNAMSIZ);
                }
            }
            continue;
        }
        /* parse error */
        else if (status == CMD_ERR)
            break;

        if (remote_type == NO_REMOTE) {
            /* use default interface */
            if (!*(*ifr).ifr_name)
                wl_find(ifr);
            /* validate the interface */
            if (!*(*ifr).ifr_name) {
                errno = ENXIO;
                syserr("interface");
            }
            if ((err = wl_check((void *)ifr)) < 0) {
                fprintf(stderr, "%s: wl driver adapter not found\n", wlu_av0);
                exit(1);
            }

            if ((strcmp (*argv, "--interactive") == 0) || (interactive_flag == 1)) {
                err = do_interactive(ifr);
                return err;
            }
        }
        /* search for command */
        cmd = wl_find_cmd(*argv);
        /* if not found, use default set_var and get_var commands */
        if (!cmd) {
            cmd = &wl_varcmd;
        }
#ifdef RWL_WIFI
        if (!strcmp(cmd->name, "findserver")) {
            remote_wifi_ser_init_cmds((void *) ifr);
        }
#endif /* RWL_WIFI */

        /* RWL over Wifi supports 'lchannel' command which lets client
         * (ie *this* machine) change channels since normal 'channel' command
         * applies to the server (ie target machine)
         */
        if (remote_type == REMOTE_WIFI)	{
#ifdef RWL_WIFI
            if (!strcmp(argv[0], "lchannel")) {
                strcpy(argv[0], "channel");
                rwl_wifi_swap_remote_type(remote_type);
                err = (*cmd->func)((void *) ifr, cmd, argv);
                rwl_wifi_swap_remote_type(remote_type);
            } else {
                err = (*cmd->func)((void *) ifr, cmd, argv);
            }
            /* After join cmd's gets exeuted on the server side , client needs to know
            * the channel on which the server is associated with AP , after delay of
            * few seconds client will intiate the scan on diffrent channels by calling
            * rwl_find_remote_wifi_server fucntion
            */
            if ((!strcmp(cmd->name, "join") || ((!strcmp(cmd->name, "ssid") &&
                                                 (*(++argv) != NULL))))) {
                DPRINT_INFO(OUTPUT, "\n Findserver is called to synchronize the"
                            "channel\n\n");
                sleep(RWL_WIFI_JOIN_DELAY);
                for (retry = 0; retry < RWL_WIFI_RETRY; retry++) {
                    if ((rwl_find_remote_wifi_server(ifr,
                                                     &g_rwl_buf_mac[0]) == 0)) {
                        break;
                    }
                }
            }
#endif /* RWL_WIFI */
        } else {
            /* do command */
            err = (*cmd->func)((void *) ifr, cmd, argv);
        }
        break;
    } /* while loop end */

    /* provide for help on a particular command */
    if (help && *argv) {
        cmd = wl_find_cmd(*argv);
        if (cmd) {
            wl_cmd_usage(stdout, cmd);
        } else {
            DPRINT_ERR(ERR, "%s: Unrecognized command \"%s\", type -h for help\n",
                       wlu_av0, *argv);
        }
    } else if (!cmd)
        wl_usage(stdout, NULL);
    else if (err == USAGE_ERROR)
        wl_cmd_usage(stderr, cmd);
    else if (err == IOCTL_ERROR)
        wl_printlasterror((void *) ifr);
    else if (err == BCME_NODEVICE)
        DPRINT_ERR(ERR, "%s : wl driver adapter not found\n", g_rem_ifname);

    return err;
}
Ejemplo n.º 8
0
/* Main client function
 * The code is mostly from wlu_linux.c. This function takes care of executing remote dhd commands
 * along with the local dhd commands now.
 */
int
main(int argc, char **argv)
{
	struct ifreq ifr;
	char *ifname = NULL;
	int err = 0;
	int help = 0;
	int status = CMD_DHD;
	void* serialHandle = NULL;
	struct ipv4_addr temp;

	UNUSED_PARAMETER(argc);

	av0 = argv[0];
	memset(&ifr, 0, sizeof(ifr));
	argv++;

	if ((status = dhd_option(&argv, &ifname, &help)) == CMD_OPT) {
		if (ifname)
			strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
	}
	/* Linux client looking for a Win32 server */
	if (*argv && strncmp (*argv, "--wince", strlen(*argv)) == 0) {
		rwl_os_type = WIN32_OS;
		argv++;
	}

	/* RWL socket transport Usage: --socket ipaddr [port num] */
	if (*argv && strncmp (*argv, "--socket", strlen(*argv)) == 0) {
		argv++;

		remote_type = REMOTE_SOCKET;

		if (!(*argv)) {
			rwl_usage(remote_type);
			return err;
		}

		if (!dhd_atoip(*argv, &temp)) {
			rwl_usage(remote_type);
			return err;
		}
		g_rwl_servIP = *argv;
		argv++;

		g_rwl_servport = DEFAULT_SERVER_PORT;
		if ((*argv) && isdigit(**argv)) {
			g_rwl_servport = atoi(*argv);
			argv++;
		}
	}

	/* RWL from system serial port on client to uart dongle port on server */
	/* Usage: --dongle /dev/ttyS0 */
	if (*argv && strncmp (*argv, "--dongle", strlen(*argv)) == 0) {
		argv++;
		remote_type = REMOTE_DONGLE;

		if (!(*argv)) {
			rwl_usage(remote_type);
			return err;
		}
		g_rwl_device_name_serial = *argv;
		argv++;
		if ((serialHandle = rwl_open_pipe(remote_type, "\0", 0, 0)) == NULL) {
			DPRINT_ERR(ERR, "serial device open error\r\n");
			return BCME_ERROR;
		}
		ifr = (*(struct ifreq *)serialHandle);
	}

	/* RWL over wifi.  Usage: --wifi mac_address */
	if (*argv && strncmp (*argv, "--wifi", strlen(*argv)) == 0) {
		argv++;
		remote_type = NO_REMOTE;
		if (!ifr.ifr_name[0])
		{
			dhd_find(&ifr, "wl");
		}
		/* validate the interface */
		if (!ifr.ifr_name[0] || wl_check((void*)&ifr)) {
			fprintf(stderr, "%s: wl driver adapter not found\n", av0);
			exit(1);
		}
		remote_type = REMOTE_WIFI;

		if (argc < 4) {
			rwl_usage(remote_type);
			return err;
		}
		/* copy server mac address to local buffer for later use by findserver cmd */
		if (!dhd_ether_atoe(*argv, (struct ether_addr *)g_rwl_buf_mac)) {
			fprintf(stderr,
			        "could not parse as an ethernet MAC address\n");
			return FAIL;
		}
		argv++;
	}

	/* Process for local dhd */
	if (remote_type == NO_REMOTE) {
		err = process_args(&ifr, argv);
		return err;
	}

	if (*argv) {
		err = process_args(&ifr, argv);
		if ((err == SERIAL_PORT_ERR) && (remote_type == REMOTE_DONGLE)) {
			DPRINT_ERR(ERR, "\n Retry again\n");
			err = process_args((struct ifreq*)&ifr, argv);
		}
		return err;
	}
	rwl_usage(remote_type);

	if (remote_type == REMOTE_DONGLE)
		rwl_close_pipe(remote_type, (void*)&ifr);

	return err;
}