//*****************************************************************************
//
//!  simple_link_send
//!
//!  @param sd       socket handle
//!  @param buf      write buffer
//!  @param len      buffer length
//!  @param flags    On this version, this parameter is not supported
//!  @param to       pointer to an address structure indicating destination
//!                  address
//!  @param tolen    destination address structure size
//!
//!  @return         Return the number of bytes transmitted, or -1 if an error
//!                  occurred, or -2 in case there are no free buffers available
//!                 (only when SEND_NON_BLOCKING is enabled)
//!
//!  @brief          This function is used to transmit a message to another
//!                  socket
//
//*****************************************************************************
INT16 simple_link_send(INT32 sd, const void *buf, INT32 len, INT32 flags,
	const sockaddr *to, INT32 tolen, INT32 opcode)
{    
	UINT8 uArgSize = 0,  addrlen;
	UINT8 *ptr, *pDataPtr = 0, *args;
	UINT32 addr_offset = 0;
	INT16 res;
	tBsdReadReturnParams tSocketSendEvent;

	// Check the bsd_arguments
	if (0 != (res = HostFlowControlConsumeBuff(sd)))
	{
		return res;
	}

	//Update the number of sent packets
	tSLInformation.NumberOfSentPackets++;

	// Allocate a buffer and construct a packet and send it over spi
	ptr = tSLInformation.pucTxCommandBuffer;
	args = (ptr + HEADERS_SIZE_DATA);

	// Update the offset of data and parameters according to the command
	switch(opcode)
	{ 
	case HCI_CMND_SENDTO:
		{
			addr_offset = len + sizeof(len) + sizeof(len);
			addrlen = 8;
			uArgSize = SOCKET_SENDTO_PARAMS_LEN;
			pDataPtr = ptr + HEADERS_SIZE_DATA + SOCKET_SENDTO_PARAMS_LEN;
			break;
		}

	case HCI_CMND_SEND:
		{
			tolen = 0;
			to = NULL;
			uArgSize = HCI_CMND_SEND_ARG_LENGTH;
			pDataPtr = ptr + HEADERS_SIZE_DATA + HCI_CMND_SEND_ARG_LENGTH;
			break;
		}

	default:
		{
			break;
		}
	}

	// Fill in temporary command buffer
	args = UINT32_TO_STREAM(args, sd);
	args = UINT32_TO_STREAM(args, uArgSize - sizeof(sd));
	args = UINT32_TO_STREAM(args, len);
	args = UINT32_TO_STREAM(args, flags);

	if (opcode == HCI_CMND_SENDTO)
	{
		args = UINT32_TO_STREAM(args, addr_offset);
		args = UINT32_TO_STREAM(args, addrlen);
	}

	// Copy the data received from user into the TX Buffer
	ARRAY_TO_STREAM(pDataPtr, ((UINT8 *)buf), len);

	// In case we are using SendTo, copy the to parameters
	if (opcode == HCI_CMND_SENDTO)
	{	
		ARRAY_TO_STREAM(pDataPtr, ((UINT8 *)to), tolen);
	}

	// Initiate a HCI command
	hci_data_send(opcode, ptr, uArgSize, len,(UINT8*)to, tolen);

	if (opcode == HCI_CMND_SENDTO)
		SimpleLinkWaitEvent(HCI_EVNT_SENDTO, &tSocketSendEvent);
	else
		SimpleLinkWaitEvent(HCI_EVNT_SEND, &tSocketSendEvent);

	return	(len);
}
INT16 select(INT32 nfds, fd_set *readsds, fd_set *writesds, fd_set *exceptsds, 
struct timeval *timeout)
{
	UINT8 *ptr, *args;
	tBsdSelectRecvParams tParams;
	UINT32 is_blocking;

	if( timeout == NULL)
	{
		is_blocking = 1; /* blocking , infinity timeout */
	}
	else
	{
		is_blocking = 0; /* no blocking, timeout */
	}

	// Fill in HCI packet structure
	ptr = tSLInformation.pucTxCommandBuffer;
	args = (ptr + HEADERS_SIZE_CMD);

	// Fill in temporary command buffer
	args = UINT32_TO_STREAM(args, nfds);
	args = UINT32_TO_STREAM(args, 0x00000014);
	args = UINT32_TO_STREAM(args, 0x00000014);
	args = UINT32_TO_STREAM(args, 0x00000014);
	args = UINT32_TO_STREAM(args, 0x00000014);
	args = UINT32_TO_STREAM(args, is_blocking);
	args = UINT32_TO_STREAM(args, ((readsds) ? *(UINT32*)readsds : 0));
	args = UINT32_TO_STREAM(args, ((writesds) ? *(UINT32*)writesds : 0));
	args = UINT32_TO_STREAM(args, ((exceptsds) ? *(UINT32*)exceptsds : 0));

	if (timeout)
	{
		if ( 0 == timeout->tv_sec && timeout->tv_usec < 
			SELECT_TIMEOUT_MIN_MICRO_SECONDS)
		{
			timeout->tv_usec = SELECT_TIMEOUT_MIN_MICRO_SECONDS;
		}
		args = UINT32_TO_STREAM(args, timeout->tv_sec);
		args = UINT32_TO_STREAM(args, timeout->tv_usec);
	}

	// Initiate a HCI command
	hci_command_send(HCI_CMND_BSD_SELECT, ptr, SOCKET_SELECT_PARAMS_LEN);

	// Since we are in blocking state - wait for event complete
	SimpleLinkWaitEvent(HCI_EVNT_SELECT, &tParams);

	// Update actually read FD
	if (tParams.iStatus >= 0)
	{
		if (readsds)
		{
			memcpy(readsds, &tParams.uiRdfd, sizeof(tParams.uiRdfd));
		}

		if (writesds)
		{
			memcpy(writesds, &tParams.uiWrfd, sizeof(tParams.uiWrfd)); 
		}

		if (exceptsds)
		{
			memcpy(exceptsds, &tParams.uiExfd, sizeof(tParams.uiExfd)); 
		}

		return(tParams.iStatus);

	}
	else
	{
		errno = tParams.iStatus;
		return(-1);
	}
}
Beispiel #3
0
INT32 wlan_add_profile(UINT32 ulSecType,
								 UINT8* ucSsid,
								 UINT32 ulSsidLen,
								 UINT8 *ucBssid,
								 UINT32 ulPriority,
								 UINT32 ulPairwiseCipher_Or_TxKeyLen,
								 UINT32 ulGroupCipher_TxKeyIndex,
								 UINT32 ulKeyMgmt,
								 UINT8* ucPf_OrKey,
								 UINT32 ulPassPhraseLen)
{
	UINT16 arg_len;
	INT32 ret;
	UINT8 *ptr;
	INT32 i = 0;
	UINT8 *args;
	UINT8 bssid_zero[] = {0, 0, 0, 0, 0, 0};

	ptr = tSLInformation.pucTxCommandBuffer;
	args = (ptr + HEADERS_SIZE_CMD);

	args = UINT32_TO_STREAM(args, ulSecType);

	// Setup arguments in accordance with the security type
	switch (ulSecType)
	{
		//OPEN
	case WLAN_SEC_UNSEC:
		{
			args = UINT32_TO_STREAM(args, 0x00000014);
			args = UINT32_TO_STREAM(args, ulSsidLen);
			args = UINT16_TO_STREAM(args, 0);
			if(ucBssid)
			{
				ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN);
			}
			else
			{
				ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
			}
			args = UINT32_TO_STREAM(args, ulPriority);
			ARRAY_TO_STREAM(args, ucSsid, ulSsidLen);

			arg_len = WLAN_ADD_PROFILE_NOSEC_PARAM_LEN + ulSsidLen;
		}
		break;

		//WEP
	case WLAN_SEC_WEP:
		{
			args = UINT32_TO_STREAM(args, 0x00000020);
			args = UINT32_TO_STREAM(args, ulSsidLen);
			args = UINT16_TO_STREAM(args, 0);
			if(ucBssid)
			{
				ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN);
			}
			else
			{
				ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
			}
			args = UINT32_TO_STREAM(args, ulPriority);
			args = UINT32_TO_STREAM(args, 0x0000000C + ulSsidLen);
			args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen);
			args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex);
			ARRAY_TO_STREAM(args, ucSsid, ulSsidLen);

			for(i = 0; i < 4; i++)
			{
				UINT8 *p = &ucPf_OrKey[i * ulPairwiseCipher_Or_TxKeyLen];

				ARRAY_TO_STREAM(args, p, ulPairwiseCipher_Or_TxKeyLen);
			}

			arg_len = WLAN_ADD_PROFILE_WEP_PARAM_LEN + ulSsidLen +
				ulPairwiseCipher_Or_TxKeyLen * 4;

		}
		break;

		//WPA
		//WPA2
	case WLAN_SEC_WPA:
	case WLAN_SEC_WPA2:
		{
			args = UINT32_TO_STREAM(args, 0x00000028);
			args = UINT32_TO_STREAM(args, ulSsidLen);
			args = UINT16_TO_STREAM(args, 0);
			if(ucBssid)
			{
				ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN);
			}
			else
			{
				ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
			}
			args = UINT32_TO_STREAM(args, ulPriority);
			args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen);
			args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex);
			args = UINT32_TO_STREAM(args, ulKeyMgmt);
			args = UINT32_TO_STREAM(args, 0x00000008 + ulSsidLen);
			args = UINT32_TO_STREAM(args, ulPassPhraseLen);
			ARRAY_TO_STREAM(args, ucSsid, ulSsidLen);
			ARRAY_TO_STREAM(args, ucPf_OrKey, ulPassPhraseLen);

			arg_len = WLAN_ADD_PROFILE_WPA_PARAM_LEN + ulSsidLen + ulPassPhraseLen;
		}

		break;
	}

	// Initiate a HCI command
	hci_command_send(HCI_CMND_WLAN_IOCTL_ADD_PROFILE,
									 ptr, arg_len);

	// Wait for command complete event
	SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, &ret);

	return(ret);
}
Beispiel #4
0
void
wlan_start(unsigned short usPatchesAvailableAtHost)
{
	unsigned long ulSpiIRQState;
	
	tSLInformation.NumberOfSentPackets = 0;
	tSLInformation.NumberOfReleasedPackets = 0;
        
        tSLInformation.usRxEventOpcode = 0;
	tSLInformation.usNumberOfFreeBuffers = 0;
	tSLInformation.usSlBufferLength = 0;
	tSLInformation.usBufferSize = 0;
	tSLInformation.usRxDataPending = 0;
        
	tSLInformation.slTransmitDataError = 0;
	tSLInformation.usEventOrDataReceived = 0;
        
        tSLInformation.pucReceivedData = 0;

    //
	// Allocate the memory for the RX/TX data transactions
	//
	//tSLInformation.pucTxCommandBuffer = (unsigned char *)wlan_tx_buffer;
    TXPtr = (char *)TX_START_ADD;
    tSLInformation.pucTxCommandBuffer = (unsigned char *)TXPtr;

	//
	// init spi
	//
	SpiOpen(SpiReceiveHandler);

	//
	// Check the IRQ line
	//
	ulSpiIRQState = tSLInformation.ReadWlanInterruptPin();
	
    //
    // ASIC 1273 chip enable: toggle WLAN EN line
    //
    tSLInformation.WriteWlanPin( WLAN_ENABLE );

	if (ulSpiIRQState)
	{
		//
		// wait till the IRQ line goes low
		//
		while(tSLInformation.ReadWlanInterruptPin() != 0)
		{
		}
	}
	else
	{
		//
		// wait till the IRQ line goes high and than low
		//
		while(tSLInformation.ReadWlanInterruptPin() == 0)
		{
		}

		while(tSLInformation.ReadWlanInterruptPin() != 0)
		{
		}
	}
	
	SimpleLink_Init_Start(usPatchesAvailableAtHost);

	// Read Buffer's size and finish
	hci_command_send(HCI_CMND_READ_BUFFER_SIZE, tSLInformation.pucTxCommandBuffer, 0);
	SimpleLinkWaitEvent(HCI_CMND_READ_BUFFER_SIZE, 0);
}
long wlan_add_profile(unsigned long ulSecType, uint8_t* ucSsid,
                      unsigned long ulSsidLen, uint8_t *ucBssid,
                      unsigned long ulPriority,
                      unsigned long ulPairwiseCipher_Or_TxKeyLen,
                      unsigned long ulGroupCipher_TxKeyIndex,
                      unsigned long ulKeyMgmt, uint8_t* ucPf_OrKey,
                      unsigned long ulPassPhraseLen)
{
  uint16_t arg_len = 0;
  long ret;
  uint8_t *ptr;
  long i = 0;
  uint8_t *args;
  uint8_t bssid_zero[] = {0, 0, 0, 0, 0, 0};

  cc3000_lib_lock();

  ptr  = tSLInformation.pucTxCommandBuffer;
  args = (ptr + HEADERS_SIZE_CMD);

  args = UINT32_TO_STREAM(args, ulSecType);

  /* Setup arguments in accordance with the security type */

  switch (ulSecType)
    {
    /* OPEN */

    case WLAN_SEC_UNSEC:
      {
        args = UINT32_TO_STREAM(args, 0x00000014);
        args = UINT32_TO_STREAM(args, ulSsidLen);
        args = UINT16_TO_STREAM(args, 0);
        if (ucBssid)
          {
            ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN);
          }
        else
          {
            ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
          }

        args = UINT32_TO_STREAM(args, ulPriority);
        ARRAY_TO_STREAM(args, ucSsid, ulSsidLen);

        arg_len = WLAN_ADD_PROFILE_NOSEC_PARAM_LEN + ulSsidLen;
      }
      break;

    /* WEP */

    case WLAN_SEC_WEP:
      {
        args = UINT32_TO_STREAM(args, 0x00000020);
        args = UINT32_TO_STREAM(args, ulSsidLen);
        args = UINT16_TO_STREAM(args, 0);
        if (ucBssid)
          {
            ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN);
          }
        else
          {
            ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
          }

        args = UINT32_TO_STREAM(args, ulPriority);
        args = UINT32_TO_STREAM(args, 0x0000000C + ulSsidLen);
        args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen);
        args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex);
        ARRAY_TO_STREAM(args, ucSsid, ulSsidLen);

        for (i = 0; i < 4; i++)
          {
            uint8_t *p = &ucPf_OrKey[i * ulPairwiseCipher_Or_TxKeyLen];

            ARRAY_TO_STREAM(args, p, ulPairwiseCipher_Or_TxKeyLen);
          }

        arg_len = WLAN_ADD_PROFILE_WEP_PARAM_LEN + ulSsidLen +
          ulPairwiseCipher_Or_TxKeyLen * 4;
      }
      break;

    /*WPA, WPA2 */

    case WLAN_SEC_WPA:
    case WLAN_SEC_WPA2:
      {
        args = UINT32_TO_STREAM(args, 0x00000028);
        args = UINT32_TO_STREAM(args, ulSsidLen);
        args = UINT16_TO_STREAM(args, 0);
        if (ucBssid)
          {
            ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN);
          }
        else
          {
            ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
          }

        args = UINT32_TO_STREAM(args, ulPriority);
        args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen);
        args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex);
        args = UINT32_TO_STREAM(args, ulKeyMgmt);
        args = UINT32_TO_STREAM(args, 0x00000008 + ulSsidLen);
        args = UINT32_TO_STREAM(args, ulPassPhraseLen);
        ARRAY_TO_STREAM(args, ucSsid, ulSsidLen);
        ARRAY_TO_STREAM(args, ucPf_OrKey, ulPassPhraseLen);

        arg_len = WLAN_ADD_PROFILE_WPA_PARAM_LEN + ulSsidLen + ulPassPhraseLen;
      }
      break;
  }

  /* Initiate a HCI command */

  hci_command_send(HCI_CMND_WLAN_IOCTL_ADD_PROFILE,
                   ptr, arg_len);

  /* Wait for command complete event */

  SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, &ret);
  cc3000_lib_unlock();
  return ret;
}
    /* init io callback */
    tSLInformation.ReadWlanInterruptPin = sReadWlanInterruptPin;
    tSLInformation.WlanInterruptEnable  = sWlanInterruptEnable;
    tSLInformation.WlanInterruptDisable = sWlanInterruptDisable;
    tSLInformation.WriteWlanPin = sWriteWlanPin;

    //init asynchronous events callback
    tSLInformation.sWlanCB= sWlanCB;

    // By default TX Complete events are routed to host too
    tSLInformation.InformHostOnTxComplete = 1;
}

//*****************************************************************************
//
//!  SpiReceiveHandler
//!
//!  @param         pvBuffer - pointer to the received data buffer
//!                      The function triggers Received event/data processing
//!
//!  @param         Pointer to the received data
//!  @return        none
//!
//!  @brief         The function triggers Received event/data processing. It is
//!                       called from the SPI library to receive the data
//
//*****************************************************************************
void SpiReceiveHandler(void *pvBuffer)
{
    tSLInformation.usEventOrDataReceived = 1;
    tSLInformation.pucReceivedData = (unsigned char     *)pvBuffer;

    hci_unsolicited_event_handler();
}


//*****************************************************************************
//
//!  wlan_start
//!
//!  @param   usPatchesAvailableAtHost -  flag to indicate if patches available
//!                                    from host or from EEPROM. Due to the
//!                                    fact the patches are burn to the EEPROM
//!                                    using the patch programmer utility, the
//!                                    patches will be available from the EEPROM
//!                                    and not from the host.
//!
//!  @return        none
//!
//!  @brief        Start WLAN device. This function asserts the enable pin of
//!                the device (WLAN_EN), starting the HW initialization process.
//!                The function blocked until device Initialization is completed.
//!                Function also configure patches (FW, driver or bootloader)
//!                and calls appropriate device callbacks.
//!
//!  @Note          Prior calling the function wlan_init shall be called.
//!  @Warning       This function must be called after wlan_init and before any
//!                 other wlan API
//!  @sa            wlan_init , wlan_stop
//!
//
//*****************************************************************************

#ifdef __ENABLE_MULTITHREADED_SUPPORT__
void c_wlan_start(unsigned short usPatchesAvailableAtHost)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
void wlan_start(unsigned short usPatchesAvailableAtHost)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{

    unsigned long ulSpiIRQState;

    tSLInformation.NumberOfSentPackets = 0;
    tSLInformation.NumberOfReleasedPackets = 0;
    tSLInformation.usRxEventOpcode = 0;
    tSLInformation.usNumberOfFreeBuffers = 0;
    tSLInformation.usSlBufferLength = 0;
    tSLInformation.usBufferSize = 0;
    tSLInformation.usRxDataPending = 0;
    tSLInformation.slTransmitDataError = 0;
    tSLInformation.usEventOrDataReceived = 0;
    tSLInformation.pucReceivedData = 0;

    // Allocate the memory for the RX/TX data transactions
    tSLInformation.pucTxCommandBuffer = (unsigned char *)wlan_tx_buffer;

    // init spi
    SpiOpen(SpiReceiveHandler);

    // Check the IRQ line
    ulSpiIRQState = tSLInformation.ReadWlanInterruptPin();

    // ASIC 1273 chip enable: toggle WLAN EN line
    tSLInformation.WriteWlanPin( WLAN_ENABLE );

    if (ulSpiIRQState)
    {
        // wait till the IRQ line goes low
        while(tSLInformation.ReadWlanInterruptPin() != 0)
        {
        }
    }
    else
    {
        // Wait till the IRQ line goes high and then low.
        while(tSLInformation.ReadWlanInterruptPin() == 0)
        {
        }

        while(tSLInformation.ReadWlanInterruptPin() != 0)
        {
        }
    }

    SimpleLink_Init_Start(usPatchesAvailableAtHost);

    // Read Buffer's size and finish
    hci_command_send(HCI_CMND_READ_BUFFER_SIZE, tSLInformation.pucTxCommandBuffer, 0);
    SimpleLinkWaitEvent(HCI_CMND_READ_BUFFER_SIZE, 0);
}


//*****************************************************************************
//
//!  wlan_stop
//!
//!  @param         none
//!
//!  @return        none
//!
//!  @brief         Stop WLAN device by putting it into reset state.
//!
//!  @sa            wlan_start
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
void c_wlan_stop(void)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
void wlan_stop(void)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    // ASIC 1273 chip disable
    tSLInformation.WriteWlanPin( WLAN_DISABLE );

    // Wait till IRQ line goes high...
    while(tSLInformation.ReadWlanInterruptPin() == 0)
    {
    }

    // Free the used by WLAN Driver memory
    if (tSLInformation.pucTxCommandBuffer)
    {
        tSLInformation.pucTxCommandBuffer = 0;
    }

    SpiClose();
}


//*****************************************************************************
//
//!  wlan_connect
//!
//!  @param    sec_type   security options:
//!               WLAN_SEC_UNSEC,
//!               WLAN_SEC_WEP (ASCII support only),
//!               WLAN_SEC_WPA or WLAN_SEC_WPA2
//!  @param    ssid       up to 32 bytes and is ASCII SSID of the AP
//!  @param    ssid_len   length of the SSID
//!  @param    bssid      6 bytes specified the AP bssid
//!  @param    key        up to 16 bytes specified the AP security key
//!  @param    key_len    key length
//!
//!  @return     On success, zero is returned. On error, negative is returned.
//!              Note that even though a zero is returned on success to trigger
//!              connection operation, it does not mean that CCC3000 is already
//!              connected. An asynchronous "Connected" event is generated when
//!              actual association process finishes and CC3000 is connected to
//!              the AP. If DHCP is set, An asynchronous "DHCP" event is
//!              generated when DHCP process is finish.
//!
//!
//!  @brief      Connect to AP
//!  @warning    Please Note that when connection to AP configured with security
//!              type WEP, please confirm that the key is set as ASCII and not
//!              as HEX.
//!  @sa         wlan_disconnect
//
//*****************************************************************************

#ifndef CC3000_TINY_DRIVER
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_wlan_connect(unsigned long ulSecType, char *ssid, long ssid_len,
                    unsigned char *bssid, unsigned char *key, long key_len)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long wlan_connect(unsigned long ulSecType, char *ssid, long ssid_len,
                  unsigned char *bssid, unsigned char *key, long key_len)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr;
    unsigned char *args;
    unsigned char bssid_zero[] = {0, 0, 0, 0, 0, 0};

    ret     = EFAIL;
    ptr     = tSLInformation.pucTxCommandBuffer;
    args    = (ptr + HEADERS_SIZE_CMD);

    // Fill in command buffer
    args = UINT32_TO_STREAM(args, 0x0000001c);
    args = UINT32_TO_STREAM(args, ssid_len);
    args = UINT32_TO_STREAM(args, ulSecType);
    args = UINT32_TO_STREAM(args, 0x00000010 + ssid_len);
    args = UINT32_TO_STREAM(args, key_len);
    args = UINT16_TO_STREAM(args, 0);

    // padding shall be zeroed
    if(bssid)
    {
        ARRAY_TO_STREAM(args, bssid, ETH_ALEN);
    }
    else
    {
        ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
    }

    ARRAY_TO_STREAM(args, ssid, ssid_len);

    if(key_len && key)
    {
        ARRAY_TO_STREAM(args, key, key_len);
    }

    // Initiate a HCI command
    hci_command_send(HCI_CMND_WLAN_CONNECT, ptr, WLAN_CONNECT_PARAM_LEN +
                                     ssid_len + key_len - 1);

    // Wait for command complete event
    SimpleLinkWaitEvent(HCI_CMND_WLAN_CONNECT, &ret);
    errno = ret;

    return(ret);
}
#else
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_wlan_connect(char *ssid, long ssid_len)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long wlan_connect(char *ssid, long ssid_len)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr;
    unsigned char *args;
    unsigned char bssid_zero[] = {0, 0, 0, 0, 0, 0};

    ret     = EFAIL;
    ptr     = tSLInformation.pucTxCommandBuffer;
    args    = (ptr + HEADERS_SIZE_CMD);

    // Fill in command buffer
    args = UINT32_TO_STREAM(args, 0x0000001c);
    args = UINT32_TO_STREAM(args, ssid_len);
    args = UINT32_TO_STREAM(args, 0);
    args = UINT32_TO_STREAM(args, 0x00000010 + ssid_len);
    args = UINT32_TO_STREAM(args, 0);
    args = UINT16_TO_STREAM(args, 0);

    // padding shall be zeroed
    ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
    ARRAY_TO_STREAM(args, ssid, ssid_len);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_WLAN_CONNECT, ptr, WLAN_CONNECT_PARAM_LEN +
                                     ssid_len  - 1);

    // Wait for command complete event
    SimpleLinkWaitEvent(HCI_CMND_WLAN_CONNECT, &ret);
    errno = ret;

    return(ret);
}
#endif

//*****************************************************************************
//
//!  wlan_disconnect
//!
//!  @return    0 disconnected done, other CC3000 already disconnected
//!
//!  @brief      Disconnect connection from AP.
//!
//!  @sa         wlan_connect
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_wlan_disconnect(void)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long wlan_disconnect(void)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr;

    ret = EFAIL;
    ptr = tSLInformation.pucTxCommandBuffer;

    hci_command_send(HCI_CMND_WLAN_DISCONNECT, ptr, 0);

    // Wait for command complete event
    SimpleLinkWaitEvent(HCI_CMND_WLAN_DISCONNECT, &ret);
    errno = ret;

    return(ret);
}

//*****************************************************************************
//
//!  wlan_ioctl_set_connection_policy
//!
//!  @param    should_connect_to_open_ap  enable(1), disable(0) connect to any
//!            available AP. This parameter corresponds to the configuration of
//!            item # 3 in the brief description.
//!  @param    should_use_fast_connect enable(1), disable(0). if enabled, tries
//!            to connect to the last connected AP. This parameter corresponds
//!            to the configuration of item # 1 in the brief description.
//!  @param    auto_start enable(1), disable(0) auto connect
//!            after reset and periodically reconnect if needed. This
//!            configuration configures option 2 in the above description.
//!
//!  @return     On success, zero is returned. On error, -1 is returned
//!
//!  @brief      When auto is enabled, the device tries to connect according
//!              the following policy:
//!              1) If fast connect is enabled and last connection is valid,
//!                 the device will try to connect to it without the scanning
//!                 procedure (fast). The last connection will be marked as
//!                 invalid, due to adding/removing profile.
//!              2) If profile exists, the device will try to connect it
//!                 (Up to seven profiles).
//!              3) If fast and profiles are not found, and open mode is
//!                 enabled, the device will try to connect to any AP.
//!              * Note that the policy settings are stored in the CC3000 NVMEM.
//!
//!  @sa         wlan_add_profile , wlan_ioctl_del_profile
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_wlan_ioctl_set_connection_policy(unsigned long should_connect_to_open_ap,
                                        unsigned long ulShouldUseFastConnect,
                                        unsigned long ulUseProfiles)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long wlan_ioctl_set_connection_policy(unsigned long should_connect_to_open_ap,
                                        unsigned long ulShouldUseFastConnect,
                                        unsigned long ulUseProfiles)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr;
    unsigned char *args;

    ret = EFAIL;
    ptr = tSLInformation.pucTxCommandBuffer;
    args = (unsigned char *)(ptr + HEADERS_SIZE_CMD);

    // Fill in HCI packet structure
    args = UINT32_TO_STREAM(args, should_connect_to_open_ap);
    args = UINT32_TO_STREAM(args, ulShouldUseFastConnect);
    args = UINT32_TO_STREAM(args, ulUseProfiles);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY,
                    ptr, WLAN_SET_CONNECTION_POLICY_PARAMS_LEN);

    // Wait for command complete event
    SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY, &ret);

    return(ret);
}

//*****************************************************************************
//
//!  wlan_add_profile
//!
//!  @param    ulSecType  WLAN_SEC_UNSEC,WLAN_SEC_WEP,WLAN_SEC_WPA,WLAN_SEC_WPA2
//!  @param    ucSsid    ssid  SSID up to 32 bytes
//!  @param    ulSsidLen ssid length
//!  @param    ucBssid   bssid  6 bytes
//!  @param    ulPriority ulPriority profile priority. Lowest priority:0.
//!			   Important Note: Smartconfig process (in unencrypted mode)
//!			   stores the profile internally with priority 1, so changing
//!			   priorities when adding new profiles should be done with extra care
//!  @param    ulPairwiseCipher_Or_TxKeyLen  key length for WEP security
//!  @param    ulGroupCipher_TxKeyIndex  key index
//!  @param    ulKeyMgmt        KEY management
//!  @param    ucPf_OrKey       security key
//!  @param    ulPassPhraseLen  security key length for WPA\WPA2
//!
//!  @return    On success, index (1-7) of the stored profile is returned.
//!				On error, -1 is returned.
//!
//!  @brief     When auto start is enabled, the device connects to
//!             station from the profiles table. Up to 7 profiles are supported.
//!             If several profiles configured the device choose the highest
//!             priority profile, within each priority group, device will choose
//!             profile based on security policy, signal strength, etc
//!             parameters. All the profiles are stored in CC3000 NVMEM.
//!
//!  @sa        wlan_ioctl_del_profile
//
//*****************************************************************************

#ifndef CC3000_TINY_DRIVER
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_wlan_add_profile(unsigned long ulSecType,
                                        unsigned char* ucSsid,
                                        unsigned long ulSsidLen,
                                        unsigned char *ucBssid,
                                        unsigned long ulPriority,
                                        unsigned long ulPairwiseCipher_Or_TxKeyLen,
                                        unsigned long ulGroupCipher_TxKeyIndex,
                                        unsigned long ulKeyMgmt,
                                        unsigned char* ucPf_OrKey,
                                        unsigned long ulPassPhraseLen)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long wlan_add_profile(unsigned long ulSecType,
                                        unsigned char* ucSsid,
                                        unsigned long ulSsidLen,
                                        unsigned char *ucBssid,
                                        unsigned long ulPriority,
                                        unsigned long ulPairwiseCipher_Or_TxKeyLen,
                                        unsigned long ulGroupCipher_TxKeyIndex,
                                        unsigned long ulKeyMgmt,
                                        unsigned char* ucPf_OrKey,
                                        unsigned long ulPassPhraseLen)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    unsigned short arg_len;
    long ret;
    unsigned char *ptr;
    long i = 0;
    unsigned char *args;
    unsigned char bssid_zero[] = {0, 0, 0, 0, 0, 0};

    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    args = UINT32_TO_STREAM(args, ulSecType);

    // Setup arguments in accordance with the security type
    switch (ulSecType)
    {
        //OPEN
        case WLAN_SEC_UNSEC:
        {
            args = UINT32_TO_STREAM(args, 0x00000014);
            args = UINT32_TO_STREAM(args, ulSsidLen);
            args = UINT16_TO_STREAM(args, 0);
            if(ucBssid)
            {
                ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN);
            }
            else
            {
                ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
            }
            args = UINT32_TO_STREAM(args, ulPriority);
            ARRAY_TO_STREAM(args, ucSsid, ulSsidLen);

            arg_len = WLAN_ADD_PROFILE_NOSEC_PARAM_LEN + ulSsidLen;
        }
        break;

        //WEP
        case WLAN_SEC_WEP:
        {
            args = UINT32_TO_STREAM(args, 0x00000020);
            args = UINT32_TO_STREAM(args, ulSsidLen);
            args = UINT16_TO_STREAM(args, 0);
            if(ucBssid)
            {
                ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN);
            }
            else
            {
                ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
            }
            args = UINT32_TO_STREAM(args, ulPriority);
            args = UINT32_TO_STREAM(args, 0x0000000C + ulSsidLen);
            args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen);
            args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex);
            ARRAY_TO_STREAM(args, ucSsid, ulSsidLen);

            for(i = 0; i < 4; i++)
            {
                unsigned char *p = &ucPf_OrKey[i * ulPairwiseCipher_Or_TxKeyLen];

                ARRAY_TO_STREAM(args, p, ulPairwiseCipher_Or_TxKeyLen);
            }

            arg_len = WLAN_ADD_PROFILE_WEP_PARAM_LEN + ulSsidLen +
                ulPairwiseCipher_Or_TxKeyLen * 4;

        }
        break;

        //WPA
        //WPA2
        case WLAN_SEC_WPA:
        case WLAN_SEC_WPA2:
        {
            args = UINT32_TO_STREAM(args, 0x00000028);
            args = UINT32_TO_STREAM(args, ulSsidLen);
            args = UINT16_TO_STREAM(args, 0);
            if(ucBssid)
            {
                ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN);
            }
            else
            {
                ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
            }
            args = UINT32_TO_STREAM(args, ulPriority);
            args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen);
            args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex);
            args = UINT32_TO_STREAM(args, ulKeyMgmt);
            args = UINT32_TO_STREAM(args, 0x00000008 + ulSsidLen);
            args = UINT32_TO_STREAM(args, ulPassPhraseLen);
            ARRAY_TO_STREAM(args, ucSsid, ulSsidLen);
            ARRAY_TO_STREAM(args, ucPf_OrKey, ulPassPhraseLen);

            arg_len = WLAN_ADD_PROFILE_WPA_PARAM_LEN + ulSsidLen + ulPassPhraseLen;
        }

        break;

        //
        // An unrecognized security type was detected. Return an error.
        //
        default:
        {
            return(-1);
        }
    }

    // Initiate a HCI command
    hci_command_send(HCI_CMND_WLAN_IOCTL_ADD_PROFILE,
        ptr, arg_len);

    // Wait for command complete event
    SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, &ret);

    return(ret);
}