summaryrefslogtreecommitdiffstatshomepage
path: root/drivers/cc3000/src
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2014-09-26 00:56:45 +0100
committerDamien George <damien.p.george@gmail.com>2014-09-26 00:56:45 +0100
commitf996d8854f0cdd88446a8a369e1b330c14ea3eb7 (patch)
tree3cd5949d155bc412e4b28b8c47bb9cd19e51fd0c /drivers/cc3000/src
parent55a5b807937a4be8d57153970d723bc31113b6d4 (diff)
downloadmicropython-f996d8854f0cdd88446a8a369e1b330c14ea3eb7.tar.gz
micropython-f996d8854f0cdd88446a8a369e1b330c14ea3eb7.zip
drivers, cc3k: Move cc3000 driver from stmhal to drivers directory.
Diffstat (limited to 'drivers/cc3000/src')
-rw-r--r--drivers/cc3000/src/cc3000_common.c164
-rw-r--r--drivers/cc3000/src/ccspi.c461
-rw-r--r--drivers/cc3000/src/evnt_handler.c849
-rw-r--r--drivers/cc3000/src/hci.c225
-rw-r--r--drivers/cc3000/src/inet_ntop.c196
-rw-r--r--drivers/cc3000/src/inet_pton.c216
-rw-r--r--drivers/cc3000/src/netapp.c459
-rw-r--r--drivers/cc3000/src/nvmem.c334
-rw-r--r--drivers/cc3000/src/patch.c117
-rw-r--r--drivers/cc3000/src/patch_prog.c414
-rw-r--r--drivers/cc3000/src/security.c530
-rw-r--r--drivers/cc3000/src/socket.c1182
-rw-r--r--drivers/cc3000/src/wlan.c1252
13 files changed, 6399 insertions, 0 deletions
diff --git a/drivers/cc3000/src/cc3000_common.c b/drivers/cc3000/src/cc3000_common.c
new file mode 100644
index 0000000000..b4c87848cf
--- /dev/null
+++ b/drivers/cc3000/src/cc3000_common.c
@@ -0,0 +1,164 @@
+/*****************************************************************************
+*
+* cc3000_common.c.c - CC3000 Host Driver Implementation.
+* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the
+* distribution.
+*
+* Neither the name of Texas Instruments Incorporated nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*****************************************************************************/
+//*****************************************************************************
+//
+//! \addtogroup common_api
+//! @{
+//
+//*****************************************************************************
+/******************************************************************************
+*
+* Include files
+*
+*****************************************************************************/
+
+#include "cc3000_common.h"
+#include "socket.h"
+#include "wlan.h"
+#include "evnt_handler.h"
+
+//*****************************************************************************
+//
+//! __error__
+//!
+//! @param pcFilename - file name, where error occurred
+//! @param ulLine - line number, where error occurred
+//!
+//! @return none
+//!
+//! @brief stub function for ASSERT macro
+//
+//*****************************************************************************
+void __error__(CHAR *pcFilename, UINT32 ulLine)
+{
+ //TODO full up function
+}
+
+
+
+//*****************************************************************************
+//
+//! UINT32_TO_STREAM_f
+//!
+//! @param p pointer to the new stream
+//! @param u32 pointer to the 32 bit
+//!
+//! @return pointer to the new stream
+//!
+//! @brief This function is used for copying 32 bit to stream
+//! while converting to little endian format.
+//
+//*****************************************************************************
+
+UINT8* UINT32_TO_STREAM_f (UINT8 *p, UINT32 u32)
+{
+ *(p)++ = (UINT8)(u32);
+ *(p)++ = (UINT8)((u32) >> 8);
+ *(p)++ = (UINT8)((u32) >> 16);
+ *(p)++ = (UINT8)((u32) >> 24);
+ return p;
+}
+
+//*****************************************************************************
+//
+//! UINT16_TO_STREAM_f
+//!
+//! @param p pointer to the new stream
+//! @param u32 pointer to the 16 bit
+//!
+//! @return pointer to the new stream
+//!
+//! @brief This function is used for copying 16 bit to stream
+//! while converting to little endian format.
+//
+//*****************************************************************************
+
+UINT8* UINT16_TO_STREAM_f (UINT8 *p, UINT16 u16)
+{
+ *(p)++ = (UINT8)(u16);
+ *(p)++ = (UINT8)((u16) >> 8);
+ return p;
+}
+
+//*****************************************************************************
+//
+//! STREAM_TO_UINT16_f
+//!
+//! @param p pointer to the stream
+//! @param offset offset in the stream
+//!
+//! @return pointer to the new 16 bit
+//!
+//! @brief This function is used for copying received stream to
+//! 16 bit in little endian format.
+//
+//*****************************************************************************
+
+UINT16 STREAM_TO_UINT16_f(CHAR* p, UINT16 offset)
+{
+ return (UINT16)((UINT16)((UINT16)
+ (*(p + offset + 1)) << 8) + (UINT16)(*(p + offset)));
+}
+
+//*****************************************************************************
+//
+//! STREAM_TO_UINT32_f
+//!
+//! @param p pointer to the stream
+//! @param offset offset in the stream
+//!
+//! @return pointer to the new 32 bit
+//!
+//! @brief This function is used for copying received stream to
+//! 32 bit in little endian format.
+//
+//*****************************************************************************
+
+UINT32 STREAM_TO_UINT32_f(CHAR* p, UINT16 offset)
+{
+ return (UINT32)((UINT32)((UINT32)
+ (*(p + offset + 3)) << 24) + (UINT32)((UINT32)
+ (*(p + offset + 2)) << 16) + (UINT32)((UINT32)
+ (*(p + offset + 1)) << 8) + (UINT32)(*(p + offset)));
+}
+
+
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/drivers/cc3000/src/ccspi.c b/drivers/cc3000/src/ccspi.c
new file mode 100644
index 0000000000..2abc637fee
--- /dev/null
+++ b/drivers/cc3000/src/ccspi.c
@@ -0,0 +1,461 @@
+/*****************************************************************************
+ *
+ * spi.c - CC3000 Host Driver Implementation.
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+
+#include <string.h>
+
+#include "stm32f4xx_hal.h"
+#include "mpconfig.h"
+#include "nlr.h"
+#include "misc.h"
+#include "qstr.h"
+#include "obj.h"
+#include "runtime.h"
+#include "pin.h"
+#include "led.h"
+#include "extint.h"
+#include "spi.h"
+#include "ccspi.h"
+#include "evnt_handler.h"
+
+#if 0 // print debugging info
+#include <stdio.h>
+#define DEBUG_printf(args...) printf(args)
+#else // don't print debugging info
+#define DEBUG_printf(args...) (void)0
+#endif
+
+// these need to be set to valid values before anything in this file will work
+STATIC SPI_HandleTypeDef *SPI_HANDLE = NULL;
+STATIC const pin_obj_t *PIN_CS = NULL;
+STATIC const pin_obj_t *PIN_EN = NULL;
+STATIC const pin_obj_t *PIN_IRQ = NULL;
+
+#define CS_LOW() HAL_GPIO_WritePin(PIN_CS->gpio, PIN_CS->pin_mask, GPIO_PIN_RESET)
+#define CS_HIGH() HAL_GPIO_WritePin(PIN_CS->gpio, PIN_CS->pin_mask, GPIO_PIN_SET)
+
+#define READ 3
+#define WRITE 1
+
+#define HI(value) (((value) & 0xFF00) >> 8)
+#define LO(value) ((value) & 0x00FF)
+
+#define SPI_TIMEOUT (1000)
+#define HEADERS_SIZE_EVNT (SPI_HEADER_SIZE + 5)
+
+/* SPI bus states */
+#define eSPI_STATE_POWERUP (0)
+#define eSPI_STATE_INITIALIZED (1)
+#define eSPI_STATE_IDLE (2)
+#define eSPI_STATE_WRITE_IRQ (3)
+#define eSPI_STATE_WRITE_FIRST_PORTION (4)
+#define eSPI_STATE_WRITE_EOT (5)
+#define eSPI_STATE_READ_IRQ (6)
+#define eSPI_STATE_READ_FIRST_PORTION (7)
+#define eSPI_STATE_READ_EOT (8)
+
+// The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size)
+// for the purpose of detection of the overrun. The location of the memory where the magic number
+// resides shall never be written. In case it is written - the overrun occured and either recevie function
+// or send function will stuck forever.
+#define CC3000_BUFFER_MAGIC_NUMBER (0xDE)
+
+typedef struct {
+ gcSpiHandleRx SPIRxHandler;
+ unsigned short usTxPacketLength;
+ unsigned short usRxPacketLength;
+ unsigned long ulSpiState;
+ unsigned char *pTxPacket;
+ unsigned char *pRxPacket;
+} tSpiInformation;
+tSpiInformation sSpiInformation;
+
+char spi_buffer[CC3000_RX_BUFFER_SIZE];
+unsigned char wlan_tx_buffer[CC3000_TX_BUFFER_SIZE];
+
+STATIC const mp_obj_fun_builtin_t irq_callback_obj;
+void SpiWriteDataSynchronous(unsigned char *data, unsigned short size);
+void SpiReadDataSynchronous(unsigned char *data, unsigned short size);
+
+// set the pins to use to communicate with the CC3000
+// the arguments must be of type pin_obj_t* and SPI_HandleTypeDef*
+void SpiInit(void *spi, const void *pin_cs, const void *pin_en, const void *pin_irq) {
+ SPI_HANDLE = spi;
+ PIN_CS = pin_cs;
+ PIN_EN = pin_en;
+ PIN_IRQ = pin_irq;
+}
+
+void SpiClose(void)
+{
+ if (sSpiInformation.pRxPacket) {
+ sSpiInformation.pRxPacket = 0;
+ }
+
+ tSLInformation.WlanInterruptDisable();
+
+ //HAL_SPI_DeInit(SPI_HANDLE);
+}
+
+void SpiOpen(gcSpiHandleRx pfRxHandler)
+{
+ DEBUG_printf("SpiOpen\n");
+
+ /* initialize SPI state */
+ sSpiInformation.ulSpiState = eSPI_STATE_POWERUP;
+ sSpiInformation.SPIRxHandler = pfRxHandler;
+ sSpiInformation.usTxPacketLength = 0;
+ sSpiInformation.pTxPacket = NULL;
+ sSpiInformation.pRxPacket = (unsigned char *)spi_buffer;
+ sSpiInformation.usRxPacketLength = 0;
+ spi_buffer[CC3000_RX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER;
+ wlan_tx_buffer[CC3000_TX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER;
+
+ /* SPI configuration */
+ SPI_HANDLE->Init.Mode = SPI_MODE_MASTER;
+ SPI_HANDLE->Init.Direction = SPI_DIRECTION_2LINES;
+ SPI_HANDLE->Init.DataSize = SPI_DATASIZE_8BIT;
+ SPI_HANDLE->Init.CLKPolarity = SPI_POLARITY_LOW;
+ SPI_HANDLE->Init.CLKPhase = SPI_PHASE_2EDGE;
+ SPI_HANDLE->Init.NSS = SPI_NSS_SOFT;
+ SPI_HANDLE->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
+ SPI_HANDLE->Init.FirstBit = SPI_FIRSTBIT_MSB;
+ SPI_HANDLE->Init.TIMode = SPI_TIMODE_DISABLED;
+ SPI_HANDLE->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
+ SPI_HANDLE->Init.CRCPolynomial = 7;
+ spi_init(SPI_HANDLE);
+
+ // configure wlan CS and EN pins
+ GPIO_InitTypeDef GPIO_InitStructure;
+ GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
+ GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStructure.Pull = GPIO_NOPULL;
+ GPIO_InitStructure.Alternate = 0;
+
+ GPIO_InitStructure.Pin = PIN_CS->pin_mask;
+ HAL_GPIO_Init(PIN_CS->gpio, &GPIO_InitStructure);
+
+ GPIO_InitStructure.Pin = PIN_EN->pin_mask;
+ HAL_GPIO_Init(PIN_EN->gpio, &GPIO_InitStructure);
+
+ HAL_GPIO_WritePin(PIN_CS->gpio, PIN_CS->pin_mask, GPIO_PIN_SET);
+ HAL_GPIO_WritePin(PIN_EN->gpio, PIN_EN->pin_mask, GPIO_PIN_RESET);
+
+ /* do a dummy read, this ensures SCLK is low before
+ actual communications start, it might be required */
+ CS_LOW();
+ uint8_t buf[1];
+ HAL_SPI_Receive(SPI_HANDLE, buf, sizeof(buf), SPI_TIMEOUT);
+ CS_HIGH();
+
+ // register EXTI
+ extint_register((mp_obj_t)PIN_IRQ, GPIO_MODE_IT_FALLING, GPIO_PULLUP, (mp_obj_t)&irq_callback_obj, true, NULL);
+ extint_enable(PIN_IRQ->pin);
+
+ DEBUG_printf("SpiOpen finished; IRQ.pin=%d IRQ_LINE=%d\n", PIN_IRQ->pin, PIN_IRQ->pin);
+}
+
+
+void SpiPauseSpi(void)
+{
+ extint_disable(PIN_IRQ->pin);
+}
+
+void SpiResumeSpi(void)
+{
+ extint_enable(PIN_IRQ->pin);
+}
+
+long ReadWlanInterruptPin(void)
+{
+ return HAL_GPIO_ReadPin(PIN_IRQ->gpio, PIN_IRQ->pin_mask);
+}
+
+void WriteWlanPin(unsigned char val)
+{
+ HAL_GPIO_WritePin(PIN_EN->gpio, PIN_EN->pin_mask,
+ (WLAN_ENABLE)? GPIO_PIN_SET:GPIO_PIN_RESET);
+}
+
+void __delay_cycles(volatile int x)
+{
+ x *= 6; // for 168 MHz CPU
+ while (x--);
+}
+
+long SpiFirstWrite(unsigned char *ucBuf, unsigned short usLength)
+{
+ DEBUG_printf("SpiFirstWrite %lu\n", sSpiInformation.ulSpiState);
+
+ CS_LOW();
+
+ // Assuming we are running on 24 MHz ~50 micro delay is 1200 cycles;
+ __delay_cycles(1200);
+
+ // SPI writes first 4 bytes of data
+ SpiWriteDataSynchronous(ucBuf, 4);
+
+ __delay_cycles(1200);
+
+ SpiWriteDataSynchronous(ucBuf + 4, usLength - 4);
+
+ // From this point on - operate in a regular way
+ sSpiInformation.ulSpiState = eSPI_STATE_IDLE;
+
+ CS_HIGH();
+
+ return(0);
+}
+
+long SpiWrite(unsigned char *pUserBuffer, unsigned short usLength)
+{
+ DEBUG_printf("SpiWrite %lu\n", sSpiInformation.ulSpiState);
+
+ unsigned char ucPad = 0;
+
+ // Figure out the total length of the packet in order to figure out if there
+ // is padding or not
+ if(!(usLength & 0x0001)) {
+ ucPad++;
+ }
+
+ pUserBuffer[0] = WRITE;
+ pUserBuffer[1] = HI(usLength + ucPad);
+ pUserBuffer[2] = LO(usLength + ucPad);
+ pUserBuffer[3] = 0;
+ pUserBuffer[4] = 0;
+
+ usLength += (SPI_HEADER_SIZE + ucPad);
+
+ // The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size)
+ // for the purpose of detection of the overrun. If the magic number is overriten - buffer overrun
+ // occurred - and we will stuck here forever!
+ if (wlan_tx_buffer[CC3000_TX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) {
+ while (1);
+ }
+
+ if (sSpiInformation.ulSpiState == eSPI_STATE_POWERUP) {
+ while (sSpiInformation.ulSpiState != eSPI_STATE_INITIALIZED);
+ }
+
+ if (sSpiInformation.ulSpiState == eSPI_STATE_INITIALIZED) {
+ // This is time for first TX/RX transactions over SPI:
+ // the IRQ is down - so need to send read buffer size command
+ SpiFirstWrite(pUserBuffer, usLength);
+ } else {
+ //
+ // We need to prevent here race that can occur in case 2 back to back packets are sent to the
+ // device, so the state will move to IDLE and once again to not IDLE due to IRQ
+ //
+ tSLInformation.WlanInterruptDisable();
+
+ while (sSpiInformation.ulSpiState != eSPI_STATE_IDLE);
+
+ sSpiInformation.ulSpiState = eSPI_STATE_WRITE_IRQ;
+ sSpiInformation.pTxPacket = pUserBuffer;
+ sSpiInformation.usTxPacketLength = usLength;
+
+ // Assert the CS line and wait till SSI IRQ line is active and then initialize write operation
+ CS_LOW();
+
+ // Re-enable IRQ - if it was not disabled - this is not a problem...
+ tSLInformation.WlanInterruptEnable();
+
+ // check for a missing interrupt between the CS assertion and enabling back the interrupts
+ if (tSLInformation.ReadWlanInterruptPin() == 0) {
+ SpiWriteDataSynchronous(sSpiInformation.pTxPacket, sSpiInformation.usTxPacketLength);
+
+ sSpiInformation.ulSpiState = eSPI_STATE_IDLE;
+
+ CS_HIGH();
+ }
+ }
+
+ // Due to the fact that we are currently implementing a blocking situation
+ // here we will wait till end of transaction
+ while (eSPI_STATE_IDLE != sSpiInformation.ulSpiState);
+
+ return(0);
+}
+
+void SpiWriteDataSynchronous(unsigned char *data, unsigned short size)
+{
+ DEBUG_printf("SpiWriteDataSynchronous(data=%p [%x %x %x %x], size=%u)\n", data, data[0], data[1], data[2], data[3], size);
+ __disable_irq();
+ if (HAL_SPI_TransmitReceive(SPI_HANDLE, data, data, size, SPI_TIMEOUT) != HAL_OK) {
+ //BREAK();
+ }
+ __enable_irq();
+ DEBUG_printf(" - rx data = [%x %x %x %x]\n", data[0], data[1], data[2], data[3]);
+}
+
+void SpiReadDataSynchronous(unsigned char *data, unsigned short size)
+{
+ memset(data, READ, size);
+ __disable_irq();
+ if (HAL_SPI_TransmitReceive(SPI_HANDLE, data, data, size, SPI_TIMEOUT) != HAL_OK) {
+ //BREAK();
+ }
+ __enable_irq();
+}
+
+void SpiReadPacket(void)
+{
+ int length;
+
+ /* read SPI header */
+ SpiReadDataSynchronous(sSpiInformation.pRxPacket, SPI_HEADER_SIZE);
+
+ /* parse data length */
+ STREAM_TO_UINT8(sSpiInformation.pRxPacket, SPI_HEADER_SIZE-1, length);
+
+ /* read the remainder of the packet */
+ SpiReadDataSynchronous(sSpiInformation.pRxPacket + SPI_HEADER_SIZE, length);
+
+ sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT;
+}
+
+void SpiReadHeader(void)
+{
+ SpiReadDataSynchronous(sSpiInformation.pRxPacket, 10);
+}
+
+void SpiTriggerRxProcessing(void)
+{
+ SpiPauseSpi();
+ CS_HIGH();
+
+ // The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size)
+ // for the purpose of detection of the overrun. If the magic number is overriten - buffer overrun
+ // occurred - and we will stuck here forever!
+ if (sSpiInformation.pRxPacket[CC3000_RX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) {
+ while (1);
+ }
+
+ sSpiInformation.ulSpiState = eSPI_STATE_IDLE;
+ sSpiInformation.SPIRxHandler(sSpiInformation.pRxPacket + SPI_HEADER_SIZE);
+}
+
+
+long SpiReadDataCont(void)
+{
+ long data_to_recv=0;
+ unsigned char *evnt_buff, type;
+
+ //determine what type of packet we have
+ evnt_buff = sSpiInformation.pRxPacket;
+ STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), HCI_PACKET_TYPE_OFFSET, type);
+
+ switch (type) {
+ case HCI_TYPE_DATA:{
+ // We need to read the rest of data..
+ STREAM_TO_UINT16((char *)(evnt_buff + SPI_HEADER_SIZE),
+ HCI_DATA_LENGTH_OFFSET, data_to_recv);
+ if (!((HEADERS_SIZE_EVNT + data_to_recv) & 1)) {
+ data_to_recv++;
+ }
+
+ if (data_to_recv) {
+ SpiReadDataSynchronous(evnt_buff + 10, data_to_recv);
+ }
+ break;
+ }
+ case HCI_TYPE_EVNT: {
+ // Calculate the rest length of the data
+ STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE),
+ HCI_EVENT_LENGTH_OFFSET, data_to_recv);
+ data_to_recv -= 1;
+
+ // Add padding byte if needed
+ if ((HEADERS_SIZE_EVNT + data_to_recv) & 1) {
+ data_to_recv++;
+ }
+
+ if (data_to_recv) {
+ SpiReadDataSynchronous(evnt_buff + 10, data_to_recv);
+ }
+
+ sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+void SSIContReadOperation(void)
+{
+ // The header was read - continue with the payload read
+ if (!SpiReadDataCont()) {
+ /* All the data was read - finalize handling by switching
+ to the task and calling from task Event Handler */
+ SpiTriggerRxProcessing();
+ }
+}
+
+STATIC mp_obj_t irq_callback(mp_obj_t line)
+{
+ DEBUG_printf("<< IRQ; state=%lu >>\n", sSpiInformation.ulSpiState);
+ switch (sSpiInformation.ulSpiState) {
+ case eSPI_STATE_POWERUP:
+ /* This means IRQ line was low call a callback of HCI Layer to inform on event */
+ DEBUG_printf(" - POWERUP\n");
+ sSpiInformation.ulSpiState = eSPI_STATE_INITIALIZED;
+ break;
+ case eSPI_STATE_IDLE:
+ DEBUG_printf(" - IDLE\n");
+ sSpiInformation.ulSpiState = eSPI_STATE_READ_IRQ;
+
+ /* IRQ line goes down - we are start reception */
+ CS_LOW();
+
+ // Wait for TX/RX Compete which will come as DMA interrupt
+ SpiReadHeader();
+
+ sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT;
+
+ SSIContReadOperation();
+ break;
+ case eSPI_STATE_WRITE_IRQ:
+ DEBUG_printf(" - WRITE IRQ\n");
+ SpiWriteDataSynchronous(sSpiInformation.pTxPacket, sSpiInformation.usTxPacketLength);
+
+ sSpiInformation.ulSpiState = eSPI_STATE_IDLE;
+
+ CS_HIGH();
+ break;
+ }
+ return mp_const_none;
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(irq_callback_obj, irq_callback);
diff --git a/drivers/cc3000/src/evnt_handler.c b/drivers/cc3000/src/evnt_handler.c
new file mode 100644
index 0000000000..80f34e469b
--- /dev/null
+++ b/drivers/cc3000/src/evnt_handler.c
@@ -0,0 +1,849 @@
+/*****************************************************************************
+*
+* evnt_handler.c - CC3000 Host Driver Implementation.
+* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the
+* distribution.
+*
+* Neither the name of Texas Instruments Incorporated nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*****************************************************************************/
+//*****************************************************************************
+//
+//! \addtogroup evnt_handler_api
+//! @{
+//
+//******************************************************************************
+
+//******************************************************************************
+// INCLUDE FILES
+//******************************************************************************
+
+#include "cc3000_common.h"
+#include "string.h"
+#include "hci.h"
+#include "evnt_handler.h"
+#include "wlan.h"
+#include "socket.h"
+#include "netapp.h"
+#include "ccspi.h"
+
+
+
+//*****************************************************************************
+// COMMON DEFINES
+//*****************************************************************************
+
+#define FLOW_CONTROL_EVENT_HANDLE_OFFSET (0)
+#define FLOW_CONTROL_EVENT_BLOCK_MODE_OFFSET (1)
+#define FLOW_CONTROL_EVENT_FREE_BUFFS_OFFSET (2)
+#define FLOW_CONTROL_EVENT_SIZE (4)
+
+#define BSD_RSP_PARAMS_SOCKET_OFFSET (0)
+#define BSD_RSP_PARAMS_STATUS_OFFSET (4)
+
+#define GET_HOST_BY_NAME_RETVAL_OFFSET (0)
+#define GET_HOST_BY_NAME_ADDR_OFFSET (4)
+
+#define ACCEPT_SD_OFFSET (0)
+#define ACCEPT_RETURN_STATUS_OFFSET (4)
+#define ACCEPT_ADDRESS__OFFSET (8)
+
+#define SL_RECEIVE_SD_OFFSET (0)
+#define SL_RECEIVE_NUM_BYTES_OFFSET (4)
+#define SL_RECEIVE__FLAGS__OFFSET (8)
+
+
+#define SELECT_STATUS_OFFSET (0)
+#define SELECT_READFD_OFFSET (4)
+#define SELECT_WRITEFD_OFFSET (8)
+#define SELECT_EXFD_OFFSET (12)
+
+
+#define NETAPP_IPCONFIG_IP_OFFSET (0)
+#define NETAPP_IPCONFIG_SUBNET_OFFSET (4)
+#define NETAPP_IPCONFIG_GW_OFFSET (8)
+#define NETAPP_IPCONFIG_DHCP_OFFSET (12)
+#define NETAPP_IPCONFIG_DNS_OFFSET (16)
+#define NETAPP_IPCONFIG_MAC_OFFSET (20)
+#define NETAPP_IPCONFIG_SSID_OFFSET (26)
+
+#define NETAPP_IPCONFIG_IP_LENGTH (4)
+#define NETAPP_IPCONFIG_MAC_LENGTH (6)
+#define NETAPP_IPCONFIG_SSID_LENGTH (32)
+
+
+#define NETAPP_PING_PACKETS_SENT_OFFSET (0)
+#define NETAPP_PING_PACKETS_RCVD_OFFSET (4)
+#define NETAPP_PING_MIN_RTT_OFFSET (8)
+#define NETAPP_PING_MAX_RTT_OFFSET (12)
+#define NETAPP_PING_AVG_RTT_OFFSET (16)
+
+#define GET_SCAN_RESULTS_TABlE_COUNT_OFFSET (0)
+#define GET_SCAN_RESULTS_SCANRESULT_STATUS_OFFSET (4)
+#define GET_SCAN_RESULTS_ISVALID_TO_SSIDLEN_OFFSET (8)
+#define GET_SCAN_RESULTS_FRAME_TIME_OFFSET (10)
+#define GET_SCAN_RESULTS_SSID_MAC_LENGTH (38)
+
+#define GET_MSS_VAL_RETVAL_OFFSET (0)
+
+//*****************************************************************************
+// GLOBAL VARAIABLES
+//*****************************************************************************
+
+UINT32 socket_active_status = SOCKET_STATUS_INIT_VAL;
+
+
+//*****************************************************************************
+// Prototypes for the static functions
+//*****************************************************************************
+
+static INT32 hci_event_unsol_flowcontrol_handler(CHAR *pEvent);
+
+static void update_socket_active_status(CHAR *resp_params);
+
+
+//*****************************************************************************
+//
+//! hci_unsol_handle_patch_request
+//!
+//! @param event_hdr event header
+//!
+//! @return none
+//!
+//! @brief Handle unsolicited event from type patch request
+//
+//*****************************************************************************
+void hci_unsol_handle_patch_request(CHAR *event_hdr)
+{
+ CHAR *params = (CHAR *)(event_hdr) + HCI_EVENT_HEADER_SIZE;
+ UINT32 ucLength = 0;
+ CHAR *patch;
+
+ switch (*params)
+ {
+ case HCI_EVENT_PATCHES_DRV_REQ:
+
+ if (tSLInformation.sDriverPatches)
+ {
+ patch = tSLInformation.sDriverPatches(&ucLength);
+
+ if (patch)
+ {
+ hci_patch_send(HCI_EVENT_PATCHES_DRV_REQ,
+ tSLInformation.pucTxCommandBuffer, patch, ucLength);
+ return;
+ }
+ }
+
+ // Send 0 length Patches response event
+ hci_patch_send(HCI_EVENT_PATCHES_DRV_REQ,
+ tSLInformation.pucTxCommandBuffer, 0, 0);
+ break;
+
+ case HCI_EVENT_PATCHES_FW_REQ:
+
+ if (tSLInformation.sFWPatches)
+ {
+ patch = tSLInformation.sFWPatches(&ucLength);
+
+ // Build and send a patch
+ if (patch)
+ {
+ hci_patch_send(HCI_EVENT_PATCHES_FW_REQ,
+ tSLInformation.pucTxCommandBuffer, patch, ucLength);
+ return;
+ }
+ }
+
+ // Send 0 length Patches response event
+ hci_patch_send(HCI_EVENT_PATCHES_FW_REQ,
+ tSLInformation.pucTxCommandBuffer, 0, 0);
+ break;
+
+ case HCI_EVENT_PATCHES_BOOTLOAD_REQ:
+
+ if (tSLInformation.sBootLoaderPatches)
+ {
+ patch = tSLInformation.sBootLoaderPatches(&ucLength);
+
+ if (patch)
+ {
+ hci_patch_send(HCI_EVENT_PATCHES_BOOTLOAD_REQ,
+ tSLInformation.pucTxCommandBuffer, patch, ucLength);
+ return;
+ }
+ }
+
+ // Send 0 length Patches response event
+ hci_patch_send(HCI_EVENT_PATCHES_BOOTLOAD_REQ,
+ tSLInformation.pucTxCommandBuffer, 0, 0);
+ break;
+ }
+}
+
+
+
+//*****************************************************************************
+//
+//! hci_event_handler
+//!
+//! @param pRetParams incoming data buffer
+//! @param from from information (in case of data received)
+//! @param fromlen from information length (in case of data received)
+//!
+//! @return none
+//!
+//! @brief Parse the incoming events packets and issues corresponding
+//! event handler from global array of handlers pointers
+//
+//*****************************************************************************
+
+
+UINT8 * hci_event_handler(void *pRetParams, UINT8 *from, UINT8 *fromlen)
+{
+ UINT8 *pucReceivedData, ucArgsize;
+ UINT16 usLength;
+ UINT8 *pucReceivedParams;
+ UINT16 usReceivedEventOpcode = 0;
+ UINT32 retValue32;
+ UINT8 * RecvParams;
+ UINT8 *RetParams;
+
+
+ while (1)
+ {
+ if (tSLInformation.usEventOrDataReceived != 0)
+ {
+ pucReceivedData = (tSLInformation.pucReceivedData);
+
+ if (*pucReceivedData == HCI_TYPE_EVNT)
+ {
+ // Event Received
+ STREAM_TO_UINT16((CHAR *)pucReceivedData, HCI_EVENT_OPCODE_OFFSET,
+ usReceivedEventOpcode);
+ pucReceivedParams = pucReceivedData + HCI_EVENT_HEADER_SIZE;
+ RecvParams = pucReceivedParams;
+ RetParams = pRetParams;
+
+ // In case unsolicited event received - here the handling finished
+ if (hci_unsol_event_handler((CHAR *)pucReceivedData) == 0)
+ {
+ STREAM_TO_UINT8(pucReceivedData, HCI_DATA_LENGTH_OFFSET, usLength);
+
+ switch(usReceivedEventOpcode)
+ {
+ case HCI_CMND_READ_BUFFER_SIZE:
+ {
+ STREAM_TO_UINT8((CHAR *)pucReceivedParams, 0,
+ tSLInformation.usNumberOfFreeBuffers);
+ STREAM_TO_UINT16((CHAR *)pucReceivedParams, 1,
+ tSLInformation.usSlBufferLength);
+ }
+ break;
+
+ case HCI_CMND_WLAN_CONFIGURE_PATCH:
+ case HCI_NETAPP_DHCP:
+ case HCI_NETAPP_PING_SEND:
+ case HCI_NETAPP_PING_STOP:
+ case HCI_NETAPP_ARP_FLUSH:
+ case HCI_NETAPP_SET_DEBUG_LEVEL:
+ case HCI_NETAPP_SET_TIMERS:
+ case HCI_EVNT_NVMEM_READ:
+ case HCI_EVNT_NVMEM_CREATE_ENTRY:
+ case HCI_CMND_NVMEM_WRITE_PATCH:
+ case HCI_NETAPP_PING_REPORT:
+ case HCI_EVNT_MDNS_ADVERTISE:
+
+ STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET
+ ,*(UINT8 *)pRetParams);
+ break;
+
+ case HCI_CMND_SETSOCKOPT:
+ case HCI_CMND_WLAN_CONNECT:
+ case HCI_CMND_WLAN_IOCTL_STATUSGET:
+ case HCI_EVNT_WLAN_IOCTL_ADD_PROFILE:
+ case HCI_CMND_WLAN_IOCTL_DEL_PROFILE:
+ case HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY:
+ case HCI_CMND_WLAN_IOCTL_SET_SCANPARAM:
+ case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START:
+ case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP:
+ case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX:
+ case HCI_CMND_EVENT_MASK:
+ case HCI_EVNT_WLAN_DISCONNECT:
+ case HCI_EVNT_SOCKET:
+ case HCI_EVNT_BIND:
+ case HCI_CMND_LISTEN:
+ case HCI_EVNT_CLOSE_SOCKET:
+ case HCI_EVNT_CONNECT:
+ case HCI_EVNT_NVMEM_WRITE:
+
+ STREAM_TO_UINT32((CHAR *)pucReceivedParams,0
+ ,*(UINT32 *)pRetParams);
+ break;
+
+ case HCI_EVNT_READ_SP_VERSION:
+
+ STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET
+ ,*(UINT8 *)pRetParams);
+ pRetParams = ((CHAR *)pRetParams) + 1;
+ STREAM_TO_UINT32((CHAR *)pucReceivedParams, 0, retValue32);
+ UINT32_TO_STREAM((UINT8 *)pRetParams, retValue32);
+ break;
+
+ case HCI_EVNT_BSD_GETHOSTBYNAME:
+
+ STREAM_TO_UINT32((CHAR *)pucReceivedParams
+ ,GET_HOST_BY_NAME_RETVAL_OFFSET,*(UINT32 *)pRetParams);
+ pRetParams = ((CHAR *)pRetParams) + 4;
+ STREAM_TO_UINT32((CHAR *)pucReceivedParams
+ ,GET_HOST_BY_NAME_ADDR_OFFSET,*(UINT32 *)pRetParams);
+ break;
+
+ case HCI_EVNT_GETMSSVALUE:
+
+ STREAM_TO_UINT16((CHAR *)pucReceivedParams
+ ,GET_MSS_VAL_RETVAL_OFFSET,*(UINT16 *)pRetParams);
+
+ break;
+
+ case HCI_EVNT_ACCEPT:
+ {
+ STREAM_TO_UINT32((CHAR *)pucReceivedParams,ACCEPT_SD_OFFSET
+ ,*(UINT32 *)pRetParams);
+ pRetParams = ((CHAR *)pRetParams) + 4;
+ STREAM_TO_UINT32((CHAR *)pucReceivedParams
+ ,ACCEPT_RETURN_STATUS_OFFSET,*(UINT32 *)pRetParams);
+ pRetParams = ((CHAR *)pRetParams) + 4;
+
+ //This argument returns in network order
+ memcpy((UINT8 *)pRetParams,
+ pucReceivedParams + ACCEPT_ADDRESS__OFFSET, sizeof(sockaddr));
+ break;
+ }
+
+ case HCI_EVNT_RECV:
+ case HCI_EVNT_RECVFROM:
+ {
+ STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_SD_OFFSET ,*(UINT32 *)pRetParams);
+ pRetParams = ((CHAR *)pRetParams) + 4;
+ STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_NUM_BYTES_OFFSET,*(UINT32 *)pRetParams);
+ pRetParams = ((CHAR *)pRetParams) + 4;
+ STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE__FLAGS__OFFSET,*(UINT32 *)pRetParams);
+
+ if(((tBsdReadReturnParams *)pRetParams)->iNumberOfBytes == ERROR_SOCKET_INACTIVE)
+ {
+ set_socket_active_status(((tBsdReadReturnParams *)pRetParams)->iSocketDescriptor,SOCKET_STATUS_INACTIVE);
+ }
+ break;
+ }
+
+ case HCI_EVNT_SEND:
+ case HCI_EVNT_SENDTO:
+ {
+ STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_SD_OFFSET ,*(UINT32 *)pRetParams);
+ pRetParams = ((CHAR *)pRetParams) + 4;
+ STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_NUM_BYTES_OFFSET,*(UINT32 *)pRetParams);
+ pRetParams = ((CHAR *)pRetParams) + 4;
+
+ break;
+ }
+
+ case HCI_EVNT_SELECT:
+ {
+ STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_STATUS_OFFSET,*(UINT32 *)pRetParams);
+ pRetParams = ((CHAR *)pRetParams) + 4;
+ STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_READFD_OFFSET,*(UINT32 *)pRetParams);
+ pRetParams = ((CHAR *)pRetParams) + 4;
+ STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_WRITEFD_OFFSET,*(UINT32 *)pRetParams);
+ pRetParams = ((CHAR *)pRetParams) + 4;
+ STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_EXFD_OFFSET,*(UINT32 *)pRetParams);
+ break;
+ }
+
+ case HCI_CMND_GETSOCKOPT:
+
+ STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET,((tBsdGetSockOptReturnParams *)pRetParams)->iStatus);
+ //This argument returns in network order
+ memcpy((UINT8 *)pRetParams, pucReceivedParams, 4);
+ break;
+
+ case HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS:
+
+ STREAM_TO_UINT32((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_TABlE_COUNT_OFFSET,*(UINT32 *)pRetParams);
+ pRetParams = ((CHAR *)pRetParams) + 4;
+ STREAM_TO_UINT32((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_SCANRESULT_STATUS_OFFSET,*(UINT32 *)pRetParams);
+ pRetParams = ((CHAR *)pRetParams) + 4;
+ STREAM_TO_UINT16((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_ISVALID_TO_SSIDLEN_OFFSET,*(UINT32 *)pRetParams);
+ pRetParams = ((CHAR *)pRetParams) + 2;
+ STREAM_TO_UINT16((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_FRAME_TIME_OFFSET,*(UINT32 *)pRetParams);
+ pRetParams = ((CHAR *)pRetParams) + 2;
+ memcpy((UINT8 *)pRetParams, (CHAR *)(pucReceivedParams + GET_SCAN_RESULTS_FRAME_TIME_OFFSET + 2), GET_SCAN_RESULTS_SSID_MAC_LENGTH);
+ break;
+
+ case HCI_CMND_SIMPLE_LINK_START:
+ break;
+
+ case HCI_NETAPP_IPCONFIG:
+
+ //Read IP address
+ STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH);
+ RecvParams += 4;
+
+ //Read subnet
+ STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH);
+ RecvParams += 4;
+
+ //Read default GW
+ STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH);
+ RecvParams += 4;
+
+ //Read DHCP server
+ STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH);
+ RecvParams += 4;
+
+ //Read DNS server
+ STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH);
+ RecvParams += 4;
+
+ //Read Mac address
+ STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_MAC_LENGTH);
+ RecvParams += 6;
+
+ //Read SSID
+ STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_SSID_LENGTH);
+
+ }
+ }
+
+ if (usReceivedEventOpcode == tSLInformation.usRxEventOpcode)
+ {
+ tSLInformation.usRxEventOpcode = 0;
+ }
+ }
+ else
+ {
+ pucReceivedParams = pucReceivedData;
+ STREAM_TO_UINT8((CHAR *)pucReceivedData, HCI_PACKET_ARGSIZE_OFFSET, ucArgsize);
+
+ STREAM_TO_UINT16((CHAR *)pucReceivedData, HCI_PACKET_LENGTH_OFFSET, usLength);
+
+ // Data received: note that the only case where from and from length
+ // are not null is in recv from, so fill the args accordingly
+ if (from)
+ {
+ STREAM_TO_UINT32((CHAR *)(pucReceivedData + HCI_DATA_HEADER_SIZE), BSD_RECV_FROM_FROMLEN_OFFSET, *(UINT32 *)fromlen);
+ memcpy(from, (pucReceivedData + HCI_DATA_HEADER_SIZE + BSD_RECV_FROM_FROM_OFFSET) ,*fromlen);
+ }
+
+ memcpy(pRetParams, pucReceivedParams + HCI_DATA_HEADER_SIZE + ucArgsize,
+ usLength - ucArgsize);
+
+ tSLInformation.usRxDataPending = 0;
+ }
+
+ tSLInformation.usEventOrDataReceived = 0;
+
+ SpiResumeSpi();
+
+ // Since we are going to TX - we need to handle this event after the
+ // ResumeSPi since we need interrupts
+ if ((*pucReceivedData == HCI_TYPE_EVNT) &&
+ (usReceivedEventOpcode == HCI_EVNT_PATCHES_REQ))
+ {
+ hci_unsol_handle_patch_request((CHAR *)pucReceivedData);
+ }
+
+ if ((tSLInformation.usRxEventOpcode == 0) && (tSLInformation.usRxDataPending == 0))
+ {
+ return NULL;
+ }
+ }
+ }
+
+}
+
+//*****************************************************************************
+//
+//! hci_unsol_event_handler
+//!
+//! @param event_hdr event header
+//!
+//! @return 1 if event supported and handled
+//! 0 if event is not supported
+//!
+//! @brief Handle unsolicited events
+//
+//*****************************************************************************
+INT32 hci_unsol_event_handler(CHAR *event_hdr)
+{
+ CHAR * data = NULL;
+ INT32 event_type;
+ UINT32 NumberOfReleasedPackets;
+ UINT32 NumberOfSentPackets;
+
+ STREAM_TO_UINT16(event_hdr, HCI_EVENT_OPCODE_OFFSET,event_type);
+
+ if (event_type & HCI_EVNT_UNSOL_BASE)
+ {
+ switch(event_type)
+ {
+
+ case HCI_EVNT_DATA_UNSOL_FREE_BUFF:
+ {
+ hci_event_unsol_flowcontrol_handler(event_hdr);
+
+ NumberOfReleasedPackets = tSLInformation.NumberOfReleasedPackets;
+ NumberOfSentPackets = tSLInformation.NumberOfSentPackets;
+
+ if (NumberOfReleasedPackets == NumberOfSentPackets)
+ {
+ if (tSLInformation.InformHostOnTxComplete)
+ {
+ tSLInformation.sWlanCB(HCI_EVENT_CC3000_CAN_SHUT_DOWN, NULL, 0);
+ }
+ }
+ return 1;
+
+ }
+ }
+ }
+
+ if(event_type & HCI_EVNT_WLAN_UNSOL_BASE)
+ {
+ switch(event_type)
+ {
+ case HCI_EVNT_WLAN_KEEPALIVE:
+ case HCI_EVNT_WLAN_UNSOL_CONNECT:
+ case HCI_EVNT_WLAN_UNSOL_DISCONNECT:
+ case HCI_EVNT_WLAN_UNSOL_INIT:
+ case HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE:
+
+ if( tSLInformation.sWlanCB )
+ {
+ tSLInformation.sWlanCB(event_type, 0, 0);
+ }
+ break;
+
+ case HCI_EVNT_WLAN_UNSOL_DHCP:
+ {
+ UINT8 params[NETAPP_IPCONFIG_MAC_OFFSET + 1]; // extra byte is for the status
+ UINT8 *recParams = params;
+
+ data = (CHAR*)(event_hdr) + HCI_EVENT_HEADER_SIZE;
+
+ //Read IP address
+ STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH);
+ data += 4;
+ //Read subnet
+ STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH);
+ data += 4;
+ //Read default GW
+ STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH);
+ data += 4;
+ //Read DHCP server
+ STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH);
+ data += 4;
+ //Read DNS server
+ STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH);
+ // read the status
+ STREAM_TO_UINT8(event_hdr, HCI_EVENT_STATUS_OFFSET, *recParams);
+
+
+ if( tSLInformation.sWlanCB )
+ {
+ tSLInformation.sWlanCB(event_type, (CHAR *)params, sizeof(params));
+ }
+ }
+ break;
+
+ case HCI_EVNT_WLAN_ASYNC_PING_REPORT:
+ {
+ netapp_pingreport_args_t params;
+ data = (CHAR*)(event_hdr) + HCI_EVENT_HEADER_SIZE;
+ STREAM_TO_UINT32(data, NETAPP_PING_PACKETS_SENT_OFFSET, params.packets_sent);
+ STREAM_TO_UINT32(data, NETAPP_PING_PACKETS_RCVD_OFFSET, params.packets_received);
+ STREAM_TO_UINT32(data, NETAPP_PING_MIN_RTT_OFFSET, params.min_round_time);
+ STREAM_TO_UINT32(data, NETAPP_PING_MAX_RTT_OFFSET, params.max_round_time);
+ STREAM_TO_UINT32(data, NETAPP_PING_AVG_RTT_OFFSET, params.avg_round_time);
+
+ if( tSLInformation.sWlanCB )
+ {
+ tSLInformation.sWlanCB(event_type, (CHAR *)&params, sizeof(params));
+ }
+ }
+ break;
+ case HCI_EVNT_BSD_TCP_CLOSE_WAIT:
+ {
+ data = (CHAR *)(event_hdr) + HCI_EVENT_HEADER_SIZE;
+ if( tSLInformation.sWlanCB )
+ {
+ //data[0] represents the socket id, for which FIN was received by remote.
+ //Upon receiving this event, the user can close the socket, or else the
+ //socket will be closded after inacvitity timeout (by default 60 seconds)
+ tSLInformation.sWlanCB(event_type, data, 1);
+ }
+ }
+ break;
+
+ //'default' case which means "event not supported"
+ default:
+ return (0);
+ }
+ return(1);
+ }
+
+ if ((event_type == HCI_EVNT_SEND) || (event_type == HCI_EVNT_SENDTO)
+ || (event_type == HCI_EVNT_WRITE))
+ {
+ CHAR *pArg;
+ INT32 status;
+
+ pArg = M_BSD_RESP_PARAMS_OFFSET(event_hdr);
+ STREAM_TO_UINT32(pArg, BSD_RSP_PARAMS_STATUS_OFFSET,status);
+
+ if (ERROR_SOCKET_INACTIVE == status)
+ {
+ // The only synchronous event that can come from SL device in form of
+ // command complete is "Command Complete" on data sent, in case SL device
+ // was unable to transmit
+ STREAM_TO_UINT8(event_hdr, HCI_EVENT_STATUS_OFFSET, tSLInformation.slTransmitDataError);
+ update_socket_active_status(M_BSD_RESP_PARAMS_OFFSET(event_hdr));
+
+ return (1);
+ }
+ else
+ return (0);
+ }
+
+ //handle a case where unsolicited event arrived, but was not handled by any of the cases above
+ if ((event_type != tSLInformation.usRxEventOpcode) && (event_type != HCI_EVNT_PATCHES_REQ))
+ {
+ return(1);
+ }
+
+ return(0);
+}
+
+//*****************************************************************************
+//
+//! hci_unsolicited_event_handler
+//!
+//! @param None
+//!
+//! @return ESUCCESS if successful, EFAIL if an error occurred
+//!
+//! @brief Parse the incoming unsolicited event packets and issues
+//! corresponding event handler.
+//
+//*****************************************************************************
+INT32 hci_unsolicited_event_handler(void)
+{
+ UINT32 res = 0;
+ UINT8 *pucReceivedData;
+
+ if (tSLInformation.usEventOrDataReceived != 0)
+ {
+ pucReceivedData = (tSLInformation.pucReceivedData);
+
+ if (*pucReceivedData == HCI_TYPE_EVNT)
+ {
+
+ // In case unsolicited event received - here the handling finished
+ if (hci_unsol_event_handler((CHAR *)pucReceivedData) == 1)
+ {
+
+ // There was an unsolicited event received - we can release the buffer
+ // and clean the event received
+ tSLInformation.usEventOrDataReceived = 0;
+
+ res = 1;
+ SpiResumeSpi();
+ }
+ }
+ }
+
+ return res;
+}
+
+//*****************************************************************************
+//
+//! set_socket_active_status
+//!
+//! @param Sd
+//! @param Status
+//! @return none
+//!
+//! @brief Check if the socket ID and status are valid and set
+//! accordingly the global socket status
+//
+//*****************************************************************************
+void set_socket_active_status(INT32 Sd, INT32 Status)
+{
+ if(M_IS_VALID_SD(Sd) && M_IS_VALID_STATUS(Status))
+ {
+ socket_active_status &= ~(1 << Sd); /* clean socket's mask */
+ socket_active_status |= (Status << Sd); /* set new socket's mask */
+ }
+}
+
+
+//*****************************************************************************
+//
+//! hci_event_unsol_flowcontrol_handler
+//!
+//! @param pEvent pointer to the string contains parameters for IPERF
+//! @return ESUCCESS if successful, EFAIL if an error occurred
+//!
+//! @brief Called in case unsolicited event from type
+//! HCI_EVNT_DATA_UNSOL_FREE_BUFF has received.
+//! Keep track on the number of packets transmitted and update the
+//! number of free buffer in the SL device.
+//
+//*****************************************************************************
+INT32 hci_event_unsol_flowcontrol_handler(CHAR *pEvent)
+{
+
+ INT32 temp, value;
+ UINT16 i;
+ UINT16 pusNumberOfHandles=0;
+ CHAR *pReadPayload;
+
+ STREAM_TO_UINT16((CHAR *)pEvent,HCI_EVENT_HEADER_SIZE,pusNumberOfHandles);
+ pReadPayload = ((CHAR *)pEvent +
+ HCI_EVENT_HEADER_SIZE + sizeof(pusNumberOfHandles));
+ temp = 0;
+
+ for(i = 0; i < pusNumberOfHandles ; i++)
+ {
+ STREAM_TO_UINT16(pReadPayload, FLOW_CONTROL_EVENT_FREE_BUFFS_OFFSET, value);
+ temp += value;
+ pReadPayload += FLOW_CONTROL_EVENT_SIZE;
+ }
+
+ tSLInformation.usNumberOfFreeBuffers += temp;
+ tSLInformation.NumberOfReleasedPackets += temp;
+
+ return(ESUCCESS);
+}
+
+//*****************************************************************************
+//
+//! get_socket_active_status
+//!
+//! @param Sd Socket IS
+//! @return Current status of the socket.
+//!
+//! @brief Retrieve socket status
+//
+//*****************************************************************************
+
+INT32 get_socket_active_status(INT32 Sd)
+{
+ if(M_IS_VALID_SD(Sd))
+ {
+ return (socket_active_status & (1 << Sd)) ? SOCKET_STATUS_INACTIVE : SOCKET_STATUS_ACTIVE;
+ }
+ return SOCKET_STATUS_INACTIVE;
+}
+
+//*****************************************************************************
+//
+//! update_socket_active_status
+//!
+//! @param resp_params Socket IS
+//! @return Current status of the socket.
+//!
+//! @brief Retrieve socket status
+//
+//*****************************************************************************
+void update_socket_active_status(CHAR *resp_params)
+{
+ INT32 status, sd;
+
+ STREAM_TO_UINT32(resp_params, BSD_RSP_PARAMS_SOCKET_OFFSET,sd);
+ STREAM_TO_UINT32(resp_params, BSD_RSP_PARAMS_STATUS_OFFSET,status);
+
+ if(ERROR_SOCKET_INACTIVE == status)
+ {
+ set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);
+ }
+}
+
+
+//*****************************************************************************
+//
+//! SimpleLinkWaitEvent
+//!
+//! @param usOpcode command operation code
+//! @param pRetParams command return parameters
+//!
+//! @return none
+//!
+//! @brief Wait for event, pass it to the hci_event_handler and
+//! update the event opcode in a global variable.
+//
+//*****************************************************************************
+
+void SimpleLinkWaitEvent(UINT16 usOpcode, void *pRetParams)
+{
+ // In the blocking implementation the control to caller will be returned only
+ // after the end of current transaction
+ tSLInformation.usRxEventOpcode = usOpcode;
+ hci_event_handler(pRetParams, 0, 0);
+}
+
+//*****************************************************************************
+//
+//! SimpleLinkWaitData
+//!
+//! @param pBuf data buffer
+//! @param from from information
+//! @param fromlen from information length
+//!
+//! @return none
+//!
+//! @brief Wait for data, pass it to the hci_event_handler
+//! and update in a global variable that there is
+//! data to read.
+//
+//*****************************************************************************
+
+void SimpleLinkWaitData(UINT8 *pBuf, UINT8 *from, UINT8 *fromlen)
+{
+ // In the blocking implementation the control to caller will be returned only
+ // after the end of current transaction, i.e. only after data will be received
+ tSLInformation.usRxDataPending = 1;
+ hci_event_handler(pBuf, from, fromlen);
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/drivers/cc3000/src/hci.c b/drivers/cc3000/src/hci.c
new file mode 100644
index 0000000000..4391692b8b
--- /dev/null
+++ b/drivers/cc3000/src/hci.c
@@ -0,0 +1,225 @@
+/*****************************************************************************
+*
+* hci.c - CC3000 Host Driver Implementation.
+* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the
+* distribution.
+*
+* Neither the name of Texas Instruments Incorporated nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*****************************************************************************/
+
+//*****************************************************************************
+//
+//! \addtogroup hci_app
+//! @{
+//
+//*****************************************************************************
+
+#include <string.h>
+#include "cc3000_common.h"
+#include "hci.h"
+#include "ccspi.h"
+#include "evnt_handler.h"
+#include "wlan.h"
+
+#define SL_PATCH_PORTION_SIZE (1000)
+
+
+//*****************************************************************************
+//
+//! hci_command_send
+//!
+//! @param usOpcode command operation code
+//! @param pucBuff pointer to the command's arguments buffer
+//! @param ucArgsLength length of the arguments
+//!
+//! @return none
+//!
+//! @brief Initiate an HCI command.
+//
+//*****************************************************************************
+UINT16 hci_command_send(UINT16 usOpcode, UINT8 *pucBuff, UINT8 ucArgsLength)
+{
+ UINT8 *stream;
+
+ stream = (pucBuff + SPI_HEADER_SIZE);
+
+ UINT8_TO_STREAM(stream, HCI_TYPE_CMND);
+ stream = UINT16_TO_STREAM(stream, usOpcode);
+ UINT8_TO_STREAM(stream, ucArgsLength);
+
+ //Update the opcode of the event we will be waiting for
+ SpiWrite(pucBuff, ucArgsLength + SIMPLE_LINK_HCI_CMND_HEADER_SIZE);
+
+ return(0);
+}
+
+//*****************************************************************************
+//
+//! hci_data_send
+//!
+//! @param usOpcode command operation code
+//! @param ucArgs pointer to the command's arguments buffer
+//! @param usArgsLength length of the arguments
+//! @param ucTail pointer to the data buffer
+//! @param usTailLength buffer length
+//!
+//! @return none
+//!
+//! @brief Initiate an HCI data write operation
+//
+//*****************************************************************************
+INT32 hci_data_send(UINT8 ucOpcode,
+ UINT8 *ucArgs,
+ UINT16 usArgsLength,
+ UINT16 usDataLength,
+ const UINT8 *ucTail,
+ UINT16 usTailLength)
+{
+ UINT8 *stream;
+
+ stream = ((ucArgs) + SPI_HEADER_SIZE);
+
+ UINT8_TO_STREAM(stream, HCI_TYPE_DATA);
+ UINT8_TO_STREAM(stream, ucOpcode);
+ UINT8_TO_STREAM(stream, usArgsLength);
+ stream = UINT16_TO_STREAM(stream, usArgsLength + usDataLength + usTailLength);
+
+ // Send the packet over the SPI
+ SpiWrite(ucArgs, SIMPLE_LINK_HCI_DATA_HEADER_SIZE + usArgsLength + usDataLength + usTailLength);
+
+ return(ESUCCESS);
+}
+
+
+//*****************************************************************************
+//
+//! hci_data_command_send
+//!
+//! @param usOpcode command operation code
+//! @param pucBuff pointer to the data buffer
+//! @param ucArgsLength arguments length
+//! @param ucDataLength data length
+//!
+//! @return none
+//!
+//! @brief Prepeare HCI header and initiate an HCI data write operation
+//
+//*****************************************************************************
+void hci_data_command_send(UINT16 usOpcode, UINT8 *pucBuff, UINT8 ucArgsLength,UINT16 ucDataLength)
+{
+ UINT8 *stream = (pucBuff + SPI_HEADER_SIZE);
+
+ UINT8_TO_STREAM(stream, HCI_TYPE_DATA);
+ UINT8_TO_STREAM(stream, usOpcode);
+ UINT8_TO_STREAM(stream, ucArgsLength);
+ stream = UINT16_TO_STREAM(stream, ucArgsLength + ucDataLength);
+
+ // Send the command over SPI on data channel
+ SpiWrite(pucBuff, ucArgsLength + ucDataLength + SIMPLE_LINK_HCI_DATA_CMND_HEADER_SIZE);
+
+ return;
+}
+
+//*****************************************************************************
+//
+//! hci_patch_send
+//!
+//! @param usOpcode command operation code
+//! @param pucBuff pointer to the command's arguments buffer
+//! @param patch pointer to patch content buffer
+//! @param usDataLength data length
+//!
+//! @return none
+//!
+//! @brief Prepeare HCI header and initiate an HCI patch write operation
+//
+//*****************************************************************************
+void hci_patch_send(UINT8 ucOpcode, UINT8 *pucBuff, CHAR *patch, UINT16 usDataLength)
+{
+ UINT8 *data_ptr = (pucBuff + SPI_HEADER_SIZE);
+ UINT16 usTransLength;
+ UINT8 *stream = (pucBuff + SPI_HEADER_SIZE);
+
+ UINT8_TO_STREAM(stream, HCI_TYPE_PATCH);
+ UINT8_TO_STREAM(stream, ucOpcode);
+ stream = UINT16_TO_STREAM(stream, usDataLength + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE);
+
+ if (usDataLength <= SL_PATCH_PORTION_SIZE)
+ {
+ UINT16_TO_STREAM(stream, usDataLength);
+ stream = UINT16_TO_STREAM(stream, usDataLength);
+ memcpy((pucBuff + SPI_HEADER_SIZE) + HCI_PATCH_HEADER_SIZE, patch, usDataLength);
+
+ // Update the opcode of the event we will be waiting for
+ SpiWrite(pucBuff, usDataLength + HCI_PATCH_HEADER_SIZE);
+ }
+ else
+ {
+
+ usTransLength = (usDataLength/SL_PATCH_PORTION_SIZE);
+ UINT16_TO_STREAM(stream, usDataLength + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE + usTransLength*SIMPLE_LINK_HCI_PATCH_HEADER_SIZE);
+ stream = UINT16_TO_STREAM(stream, SL_PATCH_PORTION_SIZE);
+ memcpy(pucBuff + SPI_HEADER_SIZE + HCI_PATCH_HEADER_SIZE, patch, SL_PATCH_PORTION_SIZE);
+ usDataLength -= SL_PATCH_PORTION_SIZE;
+ patch += SL_PATCH_PORTION_SIZE;
+
+ // Update the opcode of the event we will be waiting for
+ SpiWrite(pucBuff, SL_PATCH_PORTION_SIZE + HCI_PATCH_HEADER_SIZE);
+
+ while (usDataLength)
+ {
+ if (usDataLength <= SL_PATCH_PORTION_SIZE)
+ {
+ usTransLength = usDataLength;
+ usDataLength = 0;
+
+ }
+ else
+ {
+ usTransLength = SL_PATCH_PORTION_SIZE;
+ usDataLength -= usTransLength;
+ }
+
+ *(UINT16 *)data_ptr = usTransLength;
+ memcpy(data_ptr + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE, patch, usTransLength);
+ patch += usTransLength;
+
+ // Update the opcode of the event we will be waiting for
+ SpiWrite((UINT8 *)data_ptr, usTransLength + sizeof(usTransLength));
+ }
+ }
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//
+//*****************************************************************************
diff --git a/drivers/cc3000/src/inet_ntop.c b/drivers/cc3000/src/inet_ntop.c
new file mode 100644
index 0000000000..1b7e01a235
--- /dev/null
+++ b/drivers/cc3000/src/inet_ntop.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 1996-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <std.h>
+#include <string.h>
+#include "cc3000_common.h"
+#include "socket.h"
+#include "inet_ntop.h"
+
+#define IN6ADDRSZ 16
+#define INADDRSZ 4
+#define INT16SZ 2
+
+#define ENOSPC (28)
+#define EAFNOSUPPORT (106)
+#define SET_ERRNO(err) (errno=-err)
+
+/*
+ * Format an IPv4 address, more or less like inet_ntoa().
+ *
+ * Returns `dst' (as a const)
+ * Note:
+ * - uses no statics
+ * - takes a unsigned char* not an in_addr as input
+ */
+static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size)
+{
+ size_t len;
+ char tmp[sizeof "255.255.255.255"];
+
+ tmp[0] = '\0';
+ (void)snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d",
+ ((int)((unsigned char)src[3])) & 0xff,
+ ((int)((unsigned char)src[2])) & 0xff,
+ ((int)((unsigned char)src[1])) & 0xff,
+ ((int)((unsigned char)src[0])) & 0xff);
+
+ len = strlen(tmp);
+ if(len == 0 || len >= size)
+ {
+ SET_ERRNO(ENOSPC);
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return dst;
+}
+
+#ifdef ENABLE_IPV6
+/*
+ * Convert IPv6 binary address into presentation (printable) format.
+ */
+static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
+{
+ /*
+ * Note that int32_t and int16_t need only be "at least" large enough
+ * to contain a value of the specified size. On some systems, like
+ * Crays, there is no such thing as an integer variable with 16 bits.
+ * Keep this in mind if you think this function should have been coded
+ * to use pointer overlays. All the world's not a VAX.
+ */
+ char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
+ char *tp;
+ struct {
+ long base;
+ long len;
+ } best, cur;
+ unsigned long words[IN6ADDRSZ / INT16SZ];
+ int i;
+
+ /* Preprocess:
+ * Copy the input (bytewise) array into a wordwise array.
+ * Find the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ memset(words, '\0', sizeof(words));
+ for (i = 0; i < IN6ADDRSZ; i++)
+ words[i/2] |= (src[i] << ((1 - (i % 2)) << 3));
+
+ best.base = -1;
+ cur.base = -1;
+ best.len = 0;
+ cur.len = 0;
+
+ for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
+ {
+ if(words[i] == 0)
+ {
+ if(cur.base == -1)
+ cur.base = i, cur.len = 1;
+ else
+ cur.len++;
+ }
+ else if(cur.base != -1)
+ {
+ if(best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ if((cur.base != -1) && (best.base == -1 || cur.len > best.len))
+ best = cur;
+ if(best.base != -1 && best.len < 2)
+ best.base = -1;
+
+ /* Format the result.
+ */
+ tp = tmp;
+ for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
+ {
+ /* Are we inside the best run of 0x00's?
+ */
+ if(best.base != -1 && i >= best.base && i < (best.base + best.len))
+ {
+ if(i == best.base)
+ *tp++ = ':';
+ continue;
+ }
+
+ /* Are we following an initial run of 0x00s or any real hex?
+ */
+ if(i != 0)
+ *tp++ = ':';
+
+ /* Is this address an encapsulated IPv4?
+ */
+ if(i == 6 && best.base == 0 &&
+ (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
+ {
+ if(!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp)))
+ {
+ SET_ERRNO(ENOSPC);
+ return (NULL);
+ }
+ tp += strlen(tp);
+ break;
+ }
+ tp += snprintf(tp, 5, "%lx", words[i]);
+ }
+
+ /* Was it a trailing run of 0x00's?
+ */
+ if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
+ *tp++ = ':';
+ *tp++ = '\0';
+
+ /* Check for overflow, copy, and we're done.
+ */
+ if((size_t)(tp - tmp) > size)
+ {
+ SET_ERRNO(ENOSPC);
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return dst;
+}
+#endif /* ENABLE_IPV6 */
+
+/*
+ * Convert a network format address to presentation format.
+ *
+ * Returns pointer to presentation format address (`buf').
+ * Returns NULL on error and errno set with the specific
+ * error, EAFNOSUPPORT or ENOSPC.
+ *
+ * On Windows we store the error in the thread errno, not
+ * in the winsock error code. This is to avoid loosing the
+ * actual last winsock error. So use macro ERRNO to fetch the
+ * errno this funtion sets when returning NULL, not SOCKERRNO.
+ */
+char *inet_ntop(int af, const void *src, char *buf, size_t size)
+{
+ switch (af) {
+ case AF_INET:
+ return inet_ntop4((const unsigned char*)src, buf, size);
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ return inet_ntop6((const unsigned char*)src, buf, size);
+#endif
+ default:
+ SET_ERRNO(EAFNOSUPPORT);
+ return NULL;
+ }
+}
diff --git a/drivers/cc3000/src/inet_pton.c b/drivers/cc3000/src/inet_pton.c
new file mode 100644
index 0000000000..88c7858666
--- /dev/null
+++ b/drivers/cc3000/src/inet_pton.c
@@ -0,0 +1,216 @@
+/* This is from the BIND 4.9.4 release, modified to compile by itself */
+
+/* Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include <string.h>
+#include "cc3000_common.h"
+#include "socket.h"
+#include "inet_pton.h"
+
+#define IN6ADDRSZ 16
+#define INADDRSZ 4
+#define INT16SZ 2
+
+static int inet_pton4(const char *src, unsigned char *dst);
+#ifdef ENABLE_IPV6
+static int inet_pton6(const char *src, unsigned char *dst);
+#endif
+
+#define EAFNOSUPPORT (106)
+#define SET_ERRNO(err) (errno=-err)
+
+/* int
+ * inet_pton(af, src, dst)
+ * convert from presentation format (which usually means ASCII printable)
+ * to network format (which is usually some kind of binary format).
+ * return:
+ * 1 if the address was valid for the specified address family
+ * 0 if the address wasn't valid (`dst' is untouched in this case)
+ * -1 if some other error occurred (`dst' is untouched in this case, too)
+ * notice:
+ * On Windows we store the error in the thread errno, not
+ * in the winsock error code. This is to avoid loosing the
+ * actual last winsock error. So use macro ERRNO to fetch the
+ * errno this funtion sets when returning (-1), not SOCKERRNO.
+ * author:
+ * Paul Vixie, 1996.
+ */
+int inet_pton(int af, const char *src, void *dst)
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_pton4(src, (unsigned char *)dst));
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ return (inet_pton6(src, (unsigned char *)dst));
+#endif
+ default:
+ SET_ERRNO(EAFNOSUPPORT);
+ return (-1);
+ }
+ /* NOTREACHED */
+}
+
+/* int
+ * inet_pton4(src, dst)
+ * like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ * 1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ * does not touch `dst' unless it's returning 1.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int inet_pton4(const char *src, unsigned char *dst)
+{
+ static const char digits[] = "0123456789";
+ int saw_digit, octets, ch;
+ unsigned char tmp[INADDRSZ], *tp;
+
+ saw_digit = 0;
+ octets = 0;
+ tp = tmp;
+ *tp = 0;
+ while((ch = *src++) != '\0') {
+ const char *pch;
+
+ if((pch = strchr(digits, ch)) != NULL) {
+ unsigned int val = *tp * 10 + (unsigned int)(pch - digits);
+
+ if(saw_digit && *tp == 0)
+ return (0);
+ if(val > 255)
+ return (0);
+ *tp = (unsigned char)val;
+ if(! saw_digit) {
+ if(++octets > 4)
+ return (0);
+ saw_digit = 1;
+ }
+ }
+ else if(ch == '.' && saw_digit) {
+ if(octets == 4)
+ return (0);
+ *++tp = 0;
+ saw_digit = 0;
+ }
+ else
+ return (0);
+ }
+ if(octets < 4)
+ return (0);
+ memcpy(dst, tmp, INADDRSZ);
+ return (1);
+}
+
+#ifdef ENABLE_IPV6
+/* int
+ * inet_pton6(src, dst)
+ * convert presentation level address to network order binary form.
+ * return:
+ * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ * (1) does not touch `dst' unless it's returning 1.
+ * (2) :: in a full address is silently ignored.
+ * credit:
+ * inspired by Mark Andrews.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int inet_pton6(const char *src, unsigned char *dst)
+{
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, saw_xdigit;
+ unsigned int val;
+
+ memset((tp = tmp), 0, IN6ADDRSZ);
+ endp = tp + IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if(*src == ':')
+ if(*++src != ':')
+ return (0);
+ curtok = src;
+ saw_xdigit = 0;
+ val = 0;
+ while((ch = *src++) != '\0') {
+ const char *pch;
+
+ if((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if(pch != NULL) {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if(++saw_xdigit > 4)
+ return (0);
+ continue;
+ }
+ if(ch == ':') {
+ curtok = src;
+ if(!saw_xdigit) {
+ if(colonp)
+ return (0);
+ colonp = tp;
+ continue;
+ }
+ if(tp + INT16SZ > endp)
+ return (0);
+ *tp++ = (unsigned char) (val >> 8) & 0xff;
+ *tp++ = (unsigned char) val & 0xff;
+ saw_xdigit = 0;
+ val = 0;
+ continue;
+ }
+ if(ch == '.' && ((tp + INADDRSZ) <= endp) &&
+ inet_pton4(curtok, tp) > 0) {
+ tp += INADDRSZ;
+ saw_xdigit = 0;
+ break; /* '\0' was seen by inet_pton4(). */
+ }
+ return (0);
+ }
+ if(saw_xdigit) {
+ if(tp + INT16SZ > endp)
+ return (0);
+ *tp++ = (unsigned char) (val >> 8) & 0xff;
+ *tp++ = (unsigned char) val & 0xff;
+ }
+ if(colonp != NULL) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const long n = tp - colonp;
+ long i;
+
+ if(tp == endp)
+ return (0);
+ for (i = 1; i <= n; i++) {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+ if(tp != endp)
+ return (0);
+ memcpy(dst, tmp, IN6ADDRSZ);
+ return (1);
+}
+#endif /* ENABLE_IPV6 */
diff --git a/drivers/cc3000/src/netapp.c b/drivers/cc3000/src/netapp.c
new file mode 100644
index 0000000000..a6f60feda0
--- /dev/null
+++ b/drivers/cc3000/src/netapp.c
@@ -0,0 +1,459 @@
+/*****************************************************************************
+*
+* netapp.c - CC3000 Host Driver Implementation.
+* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the
+* distribution.
+*
+* Neither the name of Texas Instruments Incorporated nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*****************************************************************************/
+
+#include <string.h>
+#include "netapp.h"
+#include "hci.h"
+#include "socket.h"
+#include "evnt_handler.h"
+#include "nvmem.h"
+
+#define MIN_TIMER_VAL_SECONDS 10
+#define MIN_TIMER_SET(t) if ((0 != t) && (t < MIN_TIMER_VAL_SECONDS)) \
+ { \
+ t = MIN_TIMER_VAL_SECONDS; \
+ }
+
+
+#define NETAPP_DHCP_PARAMS_LEN (20)
+#define NETAPP_SET_TIMER_PARAMS_LEN (20)
+#define NETAPP_SET_DEBUG_LEVEL_PARAMS_LEN (4)
+#define NETAPP_PING_SEND_PARAMS_LEN (16)
+
+
+//*****************************************************************************
+//
+//! netapp_config_mac_adrress
+//!
+//! @param mac device mac address, 6 bytes. Saved: yes
+//!
+//! @return return on success 0, otherwise error.
+//!
+//! @brief Configure device MAC address and store it in NVMEM.
+//! The value of the MAC address configured through the API will
+//! be stored in CC3000 non volatile memory, thus preserved
+//! over resets.
+//
+//*****************************************************************************
+INT32 netapp_config_mac_adrress(UINT8 * mac)
+{
+ return nvmem_set_mac_address(mac);
+}
+
+//*****************************************************************************
+//
+//! netapp_dhcp
+//!
+//! @param aucIP device mac address, 6 bytes. Saved: yes
+//! @param aucSubnetMask device mac address, 6 bytes. Saved: yes
+//! @param aucDefaultGateway device mac address, 6 bytes. Saved: yes
+//! @param aucDNSServer device mac address, 6 bytes. Saved: yes
+//!
+//! @return return on success 0, otherwise error.
+//!
+//! @brief netapp_dhcp is used to configure the network interface,
+//! static or dynamic (DHCP).\n In order to activate DHCP mode,
+//! aucIP, aucSubnetMask, aucDefaultGateway must be 0.
+//! The default mode of CC3000 is DHCP mode.
+//! Note that the configuration is saved in non volatile memory
+//! and thus preserved over resets.
+//!
+//! @note If the mode is altered a reset of CC3000 device is required
+//! in order to apply changes.\nAlso note that asynchronous event
+//! of DHCP_EVENT, which is generated when an IP address is
+//! allocated either by the DHCP server or due to static
+//! allocation is generated only upon a connection to the
+//! AP was established.
+//!
+//*****************************************************************************
+INT32 netapp_dhcp(UINT32 *aucIP, UINT32 *aucSubnetMask,UINT32 *aucDefaultGateway, UINT32 *aucDNSServer)
+{
+ INT8 scRet;
+ UINT8 *ptr;
+ UINT8 *args;
+
+ scRet = EFAIL;
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (ptr + HEADERS_SIZE_CMD);
+
+ // Fill in temporary command buffer
+ ARRAY_TO_STREAM(args,aucIP,4);
+ ARRAY_TO_STREAM(args,aucSubnetMask,4);
+ ARRAY_TO_STREAM(args,aucDefaultGateway,4);
+ args = UINT32_TO_STREAM(args, 0);
+ ARRAY_TO_STREAM(args,aucDNSServer,4);
+
+ // Initiate a HCI command
+ hci_command_send(HCI_NETAPP_DHCP, ptr, NETAPP_DHCP_PARAMS_LEN);
+
+ // Wait for command complete event
+ SimpleLinkWaitEvent(HCI_NETAPP_DHCP, &scRet);
+
+ return(scRet);
+}
+
+
+//*****************************************************************************
+//
+//! netapp_timeout_values
+//!
+//! @param aucDHCP DHCP lease time request, also impact
+//! the DHCP renew timeout. Range: [0-0xffffffff] seconds,
+//! 0 or 0xffffffff == infinity lease timeout.
+//! Resolution:10 seconds. Influence: only after
+//! reconnecting to the AP.
+//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds.
+//! The parameter is saved into the CC3000 NVMEM.
+//! The default value on CC3000 is 14400 seconds.
+//!
+//! @param aucARP ARP refresh timeout, if ARP entry is not updated by
+//! incoming packet, the ARP entry will be deleted by
+//! the end of the timeout.
+//! Range: [0-0xffffffff] seconds, 0 == infinity ARP timeout
+//! Resolution: 10 seconds. Influence: on runtime.
+//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds
+//! The parameter is saved into the CC3000 NVMEM.
+//! The default value on CC3000 is 3600 seconds.
+//!
+//! @param aucKeepalive Keepalive event sent by the end of keepalive timeout
+//! Range: [0-0xffffffff] seconds, 0 == infinity timeout
+//! Resolution: 10 seconds.
+//! Influence: on runtime.
+//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec
+//! The parameter is saved into the CC3000 NVMEM.
+//! The default value on CC3000 is 10 seconds.
+//!
+//! @param aucInactivity Socket inactivity timeout, socket timeout is
+//! refreshed by incoming or outgoing packet, by the
+//! end of the socket timeout the socket will be closed
+//! Range: [0-0xffffffff] sec, 0 == infinity timeout.
+//! Resolution: 10 seconds. Influence: on runtime.
+//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec
+//! The parameter is saved into the CC3000 NVMEM.
+//! The default value on CC3000 is 60 seconds.
+//!
+//! @return return on success 0, otherwise error.
+//!
+//! @brief Set new timeout values. Function set new timeout values for:
+//! DHCP lease timeout, ARP refresh timeout, keepalive event
+//! timeout and socket inactivity timeout
+//!
+//! @note If a parameter set to non zero value which is less than 10s,
+//! it will be set automatically to 10s.
+//!
+//*****************************************************************************
+
+#ifndef CC3000_TINY_DRIVER
+INT32 netapp_timeout_values(UINT32 *aucDHCP, UINT32 *aucARP,UINT32 *aucKeepalive, UINT32 *aucInactivity)
+{
+ INT8 scRet;
+ UINT8 *ptr;
+ UINT8 *args;
+
+ scRet = EFAIL;
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (ptr + HEADERS_SIZE_CMD);
+
+ // Set minimal values of timers
+ MIN_TIMER_SET(*aucDHCP)
+ MIN_TIMER_SET(*aucARP)
+ MIN_TIMER_SET(*aucKeepalive)
+ MIN_TIMER_SET(*aucInactivity)
+
+ // Fill in temporary command buffer
+ args = UINT32_TO_STREAM(args, *aucDHCP);
+ args = UINT32_TO_STREAM(args, *aucARP);
+ args = UINT32_TO_STREAM(args, *aucKeepalive);
+ args = UINT32_TO_STREAM(args, *aucInactivity);
+
+ // Initiate a HCI command
+ hci_command_send(HCI_NETAPP_SET_TIMERS, ptr, NETAPP_SET_TIMER_PARAMS_LEN);
+
+ // Wait for command complete event
+ SimpleLinkWaitEvent(HCI_NETAPP_SET_TIMERS, &scRet);
+
+ return(scRet);
+}
+#endif
+
+
+//*****************************************************************************
+//
+//! netapp_ping_send
+//!
+//! @param ip destination IP address
+//! @param pingAttempts number of echo requests to send
+//! @param pingSize send buffer size which may be up to 1400 bytes
+//! @param pingTimeout Time to wait for a response,in milliseconds.
+//!
+//! @return return on success 0, otherwise error.
+//!
+//! @brief send ICMP ECHO_REQUEST to network hosts
+//!
+//! @note If an operation finished successfully asynchronous ping report
+//! event will be generated. The report structure is as defined
+//! by structure netapp_pingreport_args_t.
+//!
+//! @warning Calling this function while a previous Ping Requests are in
+//! progress will stop the previous ping request.
+//*****************************************************************************
+
+#ifndef CC3000_TINY_DRIVER
+INT32
+ netapp_ping_send(UINT32 *ip, UINT32 ulPingAttempts, UINT32 ulPingSize, UINT32 ulPingTimeout)
+{
+ INT8 scRet;
+ UINT8 *ptr, *args;
+
+ scRet = EFAIL;
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (ptr + HEADERS_SIZE_CMD);
+
+ // Fill in temporary command buffer
+ args = UINT32_TO_STREAM(args, *ip);
+ args = UINT32_TO_STREAM(args, ulPingAttempts);
+ args = UINT32_TO_STREAM(args, ulPingSize);
+ args = UINT32_TO_STREAM(args, ulPingTimeout);
+
+ // Initiate a HCI command
+ hci_command_send(HCI_NETAPP_PING_SEND, ptr, NETAPP_PING_SEND_PARAMS_LEN);
+
+ // Wait for command complete event
+ SimpleLinkWaitEvent(HCI_NETAPP_PING_SEND, &scRet);
+
+ return(scRet);
+}
+#endif
+
+//*****************************************************************************
+//
+//! netapp_ping_report
+//!
+//! @param none
+//!
+//! @return none
+//!
+//! @brief Request for ping status. This API triggers the CC3000 to send
+//! asynchronous events: HCI_EVNT_WLAN_ASYNC_PING_REPORT.
+//! This event will carry the report structure:
+//! netapp_pingreport_args_t. This structure is filled in with ping
+//! results up till point of triggering API.
+//! netapp_pingreport_args_t:\n packets_sent - echo sent,
+//! packets_received - echo reply, min_round_time - minimum
+//! round time, max_round_time - max round time,
+//! avg_round_time - average round time
+//!
+//! @note When a ping operation is not active, the returned structure
+//! fields are 0.
+//!
+//*****************************************************************************
+
+
+#ifndef CC3000_TINY_DRIVER
+void netapp_ping_report()
+{
+ UINT8 *ptr;
+ ptr = tSLInformation.pucTxCommandBuffer;
+ INT8 scRet;
+
+ scRet = EFAIL;
+
+ // Initiate a HCI command
+ hci_command_send(HCI_NETAPP_PING_REPORT, ptr, 0);
+
+ // Wait for command complete event
+ SimpleLinkWaitEvent(HCI_NETAPP_PING_REPORT, &scRet);
+}
+#endif
+
+//*****************************************************************************
+//
+//! netapp_ping_stop
+//!
+//! @param none
+//!
+//! @return On success, zero is returned. On error, -1 is returned.
+//!
+//! @brief Stop any ping request.
+//!
+//!
+//*****************************************************************************
+
+#ifndef CC3000_TINY_DRIVER
+INT32 netapp_ping_stop()
+{
+ INT8 scRet;
+ UINT8 *ptr;
+
+ scRet = EFAIL;
+ ptr = tSLInformation.pucTxCommandBuffer;
+
+ // Initiate a HCI command
+ hci_command_send(HCI_NETAPP_PING_STOP, ptr, 0);
+
+ // Wait for command complete event
+ SimpleLinkWaitEvent(HCI_NETAPP_PING_STOP, &scRet);
+
+ return(scRet);
+}
+#endif
+
+//*****************************************************************************
+//
+//! netapp_ipconfig
+//!
+//! @param[out] ipconfig This argument is a pointer to a
+//! tNetappIpconfigRetArgs structure. This structure is
+//! filled in with the network interface configuration.
+//! tNetappIpconfigRetArgs:\n aucIP - ip address,
+//! aucSubnetMask - mask, aucDefaultGateway - default
+//! gateway address, aucDHCPServer - dhcp server address
+//! aucDNSServer - dns server address, uaMacAddr - mac
+//! address, uaSSID - connected AP ssid
+//!
+//! @return none
+//!
+//! @brief Obtain the CC3000 Network interface information.
+//! Note that the information is available only after the WLAN
+//! connection was established. Calling this function before
+//! associated, will cause non-defined values to be returned.
+//!
+//! @note The function is useful for figuring out the IP Configuration of
+//! the device when DHCP is used and for figuring out the SSID of
+//! the Wireless network the device is associated with.
+//!
+//*****************************************************************************
+
+#ifndef CC3000_TINY_DRIVER
+void netapp_ipconfig( tNetappIpconfigRetArgs * ipconfig )
+{
+ UINT8 *ptr;
+
+ ptr = tSLInformation.pucTxCommandBuffer;
+
+ // Initiate a HCI command
+ hci_command_send(HCI_NETAPP_IPCONFIG, ptr, 0);
+
+ // Wait for command complete event
+ SimpleLinkWaitEvent(HCI_NETAPP_IPCONFIG, ipconfig );
+
+}
+#else
+void netapp_ipconfig( tNetappIpconfigRetArgs * ipconfig )
+{
+
+}
+#endif
+
+//*****************************************************************************
+//
+//! netapp_arp_flush
+//!
+//! @param none
+//!
+//! @return none
+//!
+//! @brief Flushes ARP table
+//!
+//*****************************************************************************
+
+#ifndef CC3000_TINY_DRIVER
+INT32 netapp_arp_flush(void)
+{
+ INT8 scRet;
+ UINT8 *ptr;
+
+ scRet = EFAIL;
+ ptr = tSLInformation.pucTxCommandBuffer;
+
+ // Initiate a HCI command
+ hci_command_send(HCI_NETAPP_ARP_FLUSH, ptr, 0);
+
+ // Wait for command complete event
+ SimpleLinkWaitEvent(HCI_NETAPP_ARP_FLUSH, &scRet);
+
+ return(scRet);
+}
+#endif
+
+//*****************************************************************************
+//
+//! netapp_set_debug_level
+//!
+//! @param[in] level debug level. Bitwise [0-8],
+//! 0(disable)or 1(enable).\n Bitwise map: 0 - Critical
+//! message, 1 information message, 2 - core messages, 3 -
+//! HCI messages, 4 - Network stack messages, 5 - wlan
+//! messages, 6 - wlan driver messages, 7 - epprom messages,
+//! 8 - general messages. Default: 0x13f. Saved: no
+//!
+//! @return On success, zero is returned. On error, -1 is returned
+//!
+//! @brief Debug messages sent via the UART debug channel, this function
+//! enable/disable the debug level
+//!
+//*****************************************************************************
+
+
+#ifndef CC3000_TINY_DRIVER
+INT32 netapp_set_debug_level(UINT32 ulLevel)
+{
+ INT8 scRet;
+ UINT8 *ptr, *args;
+
+ scRet = EFAIL;
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (ptr + HEADERS_SIZE_CMD);
+
+ //
+ // Fill in temporary command buffer
+ //
+ args = UINT32_TO_STREAM(args, ulLevel);
+
+
+ //
+ // Initiate a HCI command
+ //
+ hci_command_send(HCI_NETAPP_SET_DEBUG_LEVEL, ptr, NETAPP_SET_DEBUG_LEVEL_PARAMS_LEN);
+
+ //
+ // Wait for command complete event
+ //
+ SimpleLinkWaitEvent(HCI_NETAPP_SET_DEBUG_LEVEL, &scRet);
+
+ return(scRet);
+
+}
+#endif
diff --git a/drivers/cc3000/src/nvmem.c b/drivers/cc3000/src/nvmem.c
new file mode 100644
index 0000000000..c6e170a746
--- /dev/null
+++ b/drivers/cc3000/src/nvmem.c
@@ -0,0 +1,334 @@
+/*****************************************************************************
+*
+* nvmem.c - CC3000 Host Driver Implementation.
+* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the
+* distribution.
+*
+* Neither the name of Texas Instruments Incorporated nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*****************************************************************************/
+
+//*****************************************************************************
+//
+//! \addtogroup nvmem_api
+//! @{
+//
+//*****************************************************************************
+
+#include <string.h>
+#include "nvmem.h"
+#include "hci.h"
+#include "socket.h"
+#include "evnt_handler.h"
+
+//*****************************************************************************
+//
+// Prototypes for the structures for APIs.
+//
+//*****************************************************************************
+
+#define NVMEM_READ_PARAMS_LEN (12)
+#define NVMEM_CREATE_PARAMS_LEN (8)
+#define NVMEM_WRITE_PARAMS_LEN (16)
+
+//*****************************************************************************
+//
+//! nvmem_read
+//!
+//! @param ulFileId nvmem file id:\n
+//! NVMEM_NVS_FILEID, NVMEM_NVS_SHADOW_FILEID,
+//! NVMEM_WLAN_CONFIG_FILEID, NVMEM_WLAN_CONFIG_SHADOW_FILEID,
+//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID,
+//! NVMEM_MAC_FILEID, NVMEM_FRONTEND_VARS_FILEID,
+//! NVMEM_IP_CONFIG_FILEID, NVMEM_IP_CONFIG_SHADOW_FILEID,
+//! NVMEM_BOOTLOADER_SP_FILEID, NVMEM_RM_FILEID,
+//! and user files 12-15.
+//! @param ulLength number of bytes to read
+//! @param ulOffset ulOffset in file from where to read
+//! @param buff output buffer pointer
+//!
+//! @return on success 0, error otherwise.
+//!
+//! @brief Reads data from the file referred by the ulFileId parameter.
+//! Reads data from file ulOffset till length. Err if the file can't
+//! be used, is invalid, or if the read is out of bounds.
+//!
+//*****************************************************************************
+
+INT32 nvmem_read(UINT32 ulFileId, UINT32 ulLength, UINT32 ulOffset, UINT8 *buff)
+{
+ UINT8 ucStatus = 0xFF;
+ UINT8 *ptr;
+ UINT8 *args;
+
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (ptr + HEADERS_SIZE_CMD);
+
+ // Fill in HCI packet structure
+ args = UINT32_TO_STREAM(args, ulFileId);
+ args = UINT32_TO_STREAM(args, ulLength);
+ args = UINT32_TO_STREAM(args, ulOffset);
+
+ // Initiate a HCI command
+ hci_command_send(HCI_CMND_NVMEM_READ, ptr, NVMEM_READ_PARAMS_LEN);
+ SimpleLinkWaitEvent(HCI_CMND_NVMEM_READ, &ucStatus);
+
+ // In case there is data - read it - even if an error code is returned
+ // Note: It is the user responsibility to ignore the data in case of an error code
+
+ // Wait for the data in a synchronous way. Here we assume that the buffer is
+ // big enough to store also parameters of nvmem
+
+ SimpleLinkWaitData(buff, 0, 0);
+
+ return(ucStatus);
+}
+
+//*****************************************************************************
+//
+//! nvmem_write
+//!
+//! @param ulFileId nvmem file id:\n
+//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID,
+//! NVMEM_MAC_FILEID, NVMEM_BOOTLOADER_SP_FILEID,
+//! and user files 12-15.
+//! @param ulLength number of bytes to write
+//! @param ulEntryOffset offset in file to start write operation from
+//! @param buff data to write
+//!
+//! @return on success 0, error otherwise.
+//!
+//! @brief Write data to nvmem.
+//! writes data to file referred by the ulFileId parameter.
+//! Writes data to file ulOffset till ulLength.The file id will be
+//! marked invalid till the write is done. The file entry doesn't
+//! need to be valid - only allocated.
+//!
+//*****************************************************************************
+
+INT32 nvmem_write(UINT32 ulFileId, UINT32 ulLength, UINT32 ulEntryOffset, UINT8 *buff)
+{
+ INT32 iRes;
+ UINT8 *ptr;
+ UINT8 *args;
+
+ iRes = EFAIL;
+
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (ptr + SPI_HEADER_SIZE + HCI_DATA_CMD_HEADER_SIZE);
+
+ // Fill in HCI packet structure
+ args = UINT32_TO_STREAM(args, ulFileId);
+ args = UINT32_TO_STREAM(args, 12);
+ args = UINT32_TO_STREAM(args, ulLength);
+ args = UINT32_TO_STREAM(args, ulEntryOffset);
+
+ memcpy((ptr + SPI_HEADER_SIZE + HCI_DATA_CMD_HEADER_SIZE +
+ NVMEM_WRITE_PARAMS_LEN),buff,ulLength);
+
+ // Initiate a HCI command but it will come on data channel
+ hci_data_command_send(HCI_CMND_NVMEM_WRITE, ptr, NVMEM_WRITE_PARAMS_LEN,
+ ulLength);
+
+ SimpleLinkWaitEvent(HCI_EVNT_NVMEM_WRITE, &iRes);
+
+ return(iRes);
+}
+
+
+//*****************************************************************************
+//
+//! nvmem_set_mac_address
+//!
+//! @param mac mac address to be set
+//!
+//! @return on success 0, error otherwise.
+//!
+//! @brief Write MAC address to EEPROM.
+//! mac address as appears over the air (OUI first)
+//!
+//*****************************************************************************
+
+UINT8 nvmem_set_mac_address(UINT8 *mac)
+{
+ return nvmem_write(NVMEM_MAC_FILEID, MAC_ADDR_LEN, 0, mac);
+}
+
+//*****************************************************************************
+//
+//! nvmem_get_mac_address
+//!
+//! @param[out] mac mac address
+//!
+//! @return on success 0, error otherwise.
+//!
+//! @brief Read MAC address from EEPROM.
+//! mac address as appears over the air (OUI first)
+//!
+//*****************************************************************************
+
+UINT8 nvmem_get_mac_address(UINT8 *mac)
+{
+ return nvmem_read(NVMEM_MAC_FILEID, MAC_ADDR_LEN, 0, mac);
+}
+
+//*****************************************************************************
+//
+//! nvmem_write_patch
+//!
+//! @param ulFileId nvmem file id:\n
+//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID,
+//! @param spLength number of bytes to write
+//! @param spData SP data to write
+//!
+//! @return on success 0, error otherwise.
+//!
+//! @brief program a patch to a specific file ID.
+//! The SP data is assumed to be organized in 2-dimensional.
+//! Each line is SP_PORTION_SIZE bytes long. Actual programming is
+//! applied in SP_PORTION_SIZE bytes portions.
+//!
+//*****************************************************************************
+
+UINT8 nvmem_write_patch(UINT32 ulFileId, UINT32 spLength, const UINT8 *spData)
+{
+ UINT8 status = 0;
+ UINT16 offset = 0;
+ UINT8* spDataPtr = (UINT8*)spData;
+
+ while ((status == 0) && (spLength >= SP_PORTION_SIZE))
+ {
+ status = nvmem_write(ulFileId, SP_PORTION_SIZE, offset, spDataPtr);
+ offset += SP_PORTION_SIZE;
+ spLength -= SP_PORTION_SIZE;
+ spDataPtr += SP_PORTION_SIZE;
+ }
+
+ if (status !=0)
+ {
+ // NVMEM error occurred
+ return status;
+ }
+
+ if (spLength != 0)
+ {
+ // if reached here, a reminder is left
+ status = nvmem_write(ulFileId, spLength, offset, spDataPtr);
+ }
+
+ return status;
+}
+
+//*****************************************************************************
+//
+//! nvmem_read_sp_version
+//!
+//! @param[out] patchVer first number indicates package ID and the second
+//! number indicates package build number
+//!
+//! @return on success 0, error otherwise.
+//!
+//! @brief Read patch version. read package version (WiFi FW patch,
+//! driver-supplicant-NS patch, bootloader patch)
+//!
+//*****************************************************************************
+
+#ifndef CC3000_TINY_DRIVER
+UINT8 nvmem_read_sp_version(UINT8* patchVer)
+{
+ UINT8 *ptr;
+ // 1st byte is the status and the rest is the SP version
+ UINT8 retBuf[5];
+
+ ptr = tSLInformation.pucTxCommandBuffer;
+
+ // Initiate a HCI command, no args are required
+ hci_command_send(HCI_CMND_READ_SP_VERSION, ptr, 0);
+ SimpleLinkWaitEvent(HCI_CMND_READ_SP_VERSION, retBuf);
+
+ // package ID
+ *patchVer = retBuf[3];
+ // package build number
+ *(patchVer+1) = retBuf[4];
+
+ return(retBuf[0]);
+}
+#endif
+
+//*****************************************************************************
+//
+//! nvmem_create_entry
+//!
+//! @param ulFileId nvmem file Id:\n
+//! * NVMEM_AES128_KEY_FILEID: 12
+//! * NVMEM_SHARED_MEM_FILEID: 13
+//! * and fileIDs 14 and 15
+//! @param ulNewLen entry ulLength
+//!
+//! @return on success 0, error otherwise.
+//!
+//! @brief Create new file entry and allocate space on the NVMEM.
+//! Applies only to user files.
+//! Modify the size of file.
+//! If the entry is unallocated - allocate it to size
+//! ulNewLen (marked invalid).
+//! If it is allocated then deallocate it first.
+//! To just mark the file as invalid without resizing -
+//! set ulNewLen=0.
+//!
+//*****************************************************************************
+
+INT32 nvmem_create_entry(UINT32 ulFileId, UINT32 ulNewLen)
+{
+ UINT8 *ptr;
+ UINT8 *args;
+ UINT8 retval;
+
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (ptr + HEADERS_SIZE_CMD);
+
+ // Fill in HCI packet structure
+ args = UINT32_TO_STREAM(args, ulFileId);
+ args = UINT32_TO_STREAM(args, ulNewLen);
+
+ // Initiate a HCI command
+ hci_command_send(HCI_CMND_NVMEM_CREATE_ENTRY,ptr, NVMEM_CREATE_PARAMS_LEN);
+
+ SimpleLinkWaitEvent(HCI_CMND_NVMEM_CREATE_ENTRY, &retval);
+
+ return(retval);
+}
+
+
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/drivers/cc3000/src/patch.c b/drivers/cc3000/src/patch.c
new file mode 100644
index 0000000000..227be3c9f2
--- /dev/null
+++ b/drivers/cc3000/src/patch.c
@@ -0,0 +1,117 @@
+/*****************************************************************************
+ *
+ * {PatchProgrammer_DR_Patch.c}
+ *
+ * Burn Patches to EEPROM
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
+ * ALL RIGHTS RESERVED
+ *
+ *****************************************************************************/
+//
+// Service Pack version P1.13.7.15.28 - Driver patches
+// This file contains the CC3K driver and firmware patches
+// From CC3000-FRAM-PATCH V:1.13.7 15-MAY-2014
+
+unsigned short fw_length = 5700;
+unsigned short drv_length = 8024;
+
+const unsigned char wlan_drv_patch[8024] = { 0x00, 0x01, 0x00, 0x00, 0x50, 0x1F, 0x00, 0x00, 0xF0, 0x03, 0x18, 0x00, 0xE4, 0x62, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7A, 0x63, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x10, 0x64, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x20, 0x0C, 0x49, 0x08, 0x60, 0x0C, 0x48, 0x19, 0x30, 0xF7, 0x46, 0x30, 0xB5, 0x05, 0x1C, 0xAC, 0x69, 0x68, 0x68, 0x5F, 0x30, 0x09, 0xD1, 0x60, 0x6B, 0x0C, 0x38, 0x01, 0x21, 0x8E, 0x46, 0x06, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x00, 0x20, 0x60, 0x63, 0xAC, 0x69, 0x6C, 0x60, 0x04, 0x48, 0x5B, 0x30, 0x30, 0xBD, 0x40, 0x3B, 0x08, 0x00, 0x49, 0xD0, 0x01, 0x00, 0x09, 0xEA, 0x02, 0x00, 0x91, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA6, 0x64, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3C, 0x65, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xB5, 0x85, 0xB0, 0x05, 0x1C, 0xA8, 0x88, 0x00, 0x90, 0x28, 0x89, 0x01, 0x90, 0xE9, 0x68, 0x02, 0x91, 0x28, 0x7C, 0x03, 0x90, 0x2A, 0x6A, 0x00, 0x20, 0x17, 0x56, 0x68, 0x60, 0x00, 0x29, 0x4C, 0xD0, 0x00, 0x2F, 0x4A, 0xDC ,
+0xCA, 0x49, 0x0C, 0x1C, 0x08, 0x26, 0x04, 0x90, 0x21, 0x88, 0x00, 0x98, 0x81, 0x42, 0x0C, 0xD1, 0x62, 0x88, 0x01, 0x98, 0x82, 0x42, 0x08, 0xD1, 0x46, 0x20, 0x02, 0x5D, 0x03, 0x98, 0x82, 0x42, 0x03, 0xD1, 0x0E, 0x20, 0x00, 0x57, 0xB8, 0x42, 0x0A, 0xD0, 0x46, 0x20, 0x00, 0x5D, 0x11, 0x28, 0x22, 0xD1, 0x00, 0x98, 0x81, 0x42, 0x1F, 0xD1, 0x0E, 0x20, 0x00, 0x57, 0xFF, 0xFF, 0xD2, 0x65, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xB8, 0x42, 0x1B, 0xD1, 0x04, 0x20, 0x02, 0x1C, 0x02, 0x98, 0xB9, 0x49, 0x01, 0x23, 0x9E, 0x46, 0xEC, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x17, 0xD0, 0x20, 0x1D, 0x02, 0x99, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0xE7, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x0D, 0xD0, 0x46, 0x20, 0x00, 0x5D, 0x11, 0x28, 0x09, 0xD0, 0xA0, 0x6D, 0x00, 0x28, 0x06, 0xD0, 0xAC, 0x34, 0x04, 0x98, 0x01, 0x30, 0x04, 0x90, 0x01, 0x3E, 0xC1, 0xD1, 0x07, 0xE0, 0x04, 0x98, 0x00, 0x06, 0x00, 0x0E ,
+0xAC, 0x21, 0x41, 0x43, 0xA6, 0x48, 0x40, 0x18, 0x68, 0x60, 0xA6, 0x48, 0xAD, 0x30, 0x05, 0xB0, 0xF0, 0xBD, 0x00, 0xB5, 0xC2, 0x68, 0x90, 0x69, 0x02, 0x21, 0x01, 0x23, 0x9E, 0x46, 0xA2, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xA2, 0x48, 0x61, 0x30, 0x00, 0xBD, 0x01, 0x79, 0x0B, 0x29, 0x03, 0xD0, 0x89, 0x00, 0x9F, 0x4A, 0x51, 0x5A, 0x01, 0xE0, 0x01, 0x21, 0x49, 0x02, 0x41, 0x60, 0x9D, 0x48, 0x0D, 0x30, 0xF7, 0x46, 0x01, 0x1C, 0xFF, 0xFF, 0x68, 0x66, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x9C, 0x48, 0x02, 0x68, 0x9C, 0x48, 0x01, 0x2A, 0x01, 0xD1, 0x25, 0x30, 0xF7, 0x46, 0x9B, 0x4A, 0x12, 0x68, 0x4A, 0x60, 0x19, 0x30, 0xF7, 0x46, 0x00, 0x21, 0x41, 0x60, 0x99, 0x48, 0x98, 0x49, 0x08, 0x18, 0xF7, 0x46, 0x00, 0x21, 0x41, 0x60, 0x97, 0x48, 0xE7, 0x49, 0x08, 0x18, 0xF7, 0x46, 0xFF, 0xB5, 0x46, 0x69, 0x40, 0x68, 0x01, 0x90, 0x94, 0x49, 0x0A, 0x7C, 0x9A, 0x4F, 0x01, 0x2A, 0x63, 0xD0, 0x09, 0x7C, 0x03, 0x29 ,
+0x60, 0xD0, 0x91, 0x4A, 0x92, 0x4B, 0x00, 0x21, 0x02, 0x91, 0x59, 0x56, 0x24, 0x23, 0x59, 0x43, 0x53, 0x18, 0x03, 0x93, 0x01, 0x28, 0x17, 0xD1, 0x8A, 0x18, 0x04, 0x23, 0x6C, 0x46, 0x8C, 0x49, 0x15, 0x79, 0x08, 0x78, 0xC0, 0x43, 0x28, 0x43, 0x20, 0x70, 0x01, 0x32, 0x01, 0x31, 0x01, 0x34, 0x01, 0x3B, 0xF5, 0xD1, 0x31, 0x1D, 0x68, 0x46, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0xA9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x40, 0xD0, 0x35, 0x1D, 0x82, 0x48, 0x00, 0x78, 0xFF, 0x28, 0xFF, 0xFF, 0xFE, 0x66, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x11, 0xD0, 0x00, 0x28, 0x0F, 0xD0, 0x03, 0x98, 0x01, 0x1D, 0x28, 0x1C, 0x01, 0x24, 0xA6, 0x46, 0x7E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x00, 0x28, 0x05, 0xD1, 0x7A, 0x48, 0xA6, 0x46, 0x7B, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x05, 0xE0, 0x28, 0x1C, 0x01, 0x21, 0x8E, 0x46, 0x78, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x01, 0x99, 0x01, 0x29, 0x01, 0xD1, 0x00, 0x28, 0x1E, 0xD1 ,
+0x01, 0x99, 0x5F, 0x31, 0x01, 0xD0, 0x00, 0x28, 0x0F, 0xD1, 0xA8, 0x20, 0x81, 0x5D, 0x00, 0x29, 0x08, 0xD0, 0x49, 0x1E, 0x81, 0x55, 0x80, 0x5D, 0x00, 0x28, 0x09, 0xD1, 0x38, 0x1C, 0xFF, 0x30, 0x08, 0x30, 0x11, 0xE0, 0x03, 0x21, 0x02, 0x91, 0x00, 0xE0, 0xA8, 0x20, 0x02, 0x99, 0x81, 0x55, 0x38, 0x1C, 0xFF, 0x30, 0x16, 0x30, 0x07, 0xE0, 0x01, 0x98, 0x01, 0x28, 0x02, 0xD1, 0x38, 0x1C, 0xA3, 0x30, 0x01, 0xE0, 0x38, 0x1C, 0x9F, 0x30, 0x00, 0x90, 0xFF, 0xBD, 0x00, 0xB5, 0x02, 0x1C, 0x10, 0x6A, 0xD1, 0x69, 0x52, 0x69, 0xC3, 0x69, 0x5A, 0x60, 0xFF, 0xFF, 0x94, 0x67, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x01, 0x22, 0x96, 0x46, 0x5E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x5E, 0x48, 0xFF, 0x30, 0x6E, 0x30, 0x00, 0xBD, 0x10, 0xB5, 0x0A, 0x1C, 0x41, 0x69, 0x00, 0x6A, 0x93, 0x69, 0xDB, 0x69, 0x58, 0x60, 0x90, 0x69, 0x01, 0x24, 0xA6, 0x46, 0x56, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0xA6, 0x46, 0x56, 0x48, 0xFE, 0x44 ,
+0x00, 0x47, 0x55, 0x48, 0xFF, 0x30, 0xB6, 0x30, 0x10, 0xBD, 0x70, 0xB5, 0x05, 0x1C, 0x6E, 0x69, 0x53, 0x48, 0x02, 0x68, 0x5C, 0x21, 0x88, 0x5D, 0x04, 0x28, 0x15, 0xD1, 0x07, 0x20, 0x88, 0x55, 0x10, 0x0B, 0x11, 0xD2, 0x01, 0x24, 0xA6, 0x46, 0x4E, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x00, 0x28, 0x0A, 0xD0, 0x47, 0x21, 0x89, 0x57, 0xC1, 0x60, 0x11, 0x21, 0xC9, 0x02, 0x00, 0x22, 0x04, 0x23, 0xA6, 0x46, 0xE8, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x01, 0x20, 0x68, 0x60, 0x43, 0x48, 0xED, 0x49, 0x08, 0x18, 0x70, 0xBD, 0x70, 0xB5, 0x05, 0x1C, 0xAE, 0x69, 0x9C, 0x20, 0x80, 0x19, 0x4B, 0x21, 0x89, 0x00, 0x01, 0x24, 0xFF, 0xFF, 0x2A, 0x68, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xA6, 0x46, 0xE8, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x5C, 0x21, 0x88, 0x5D, 0x07, 0x28, 0x01, 0xD1, 0x09, 0x20, 0x00, 0xE0, 0x05, 0x20, 0xAA, 0x69, 0x88, 0x54, 0x30, 0x1C, 0xA6, 0x46, 0xE9, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x68, 0x60, 0xE8, 0x48 ,
+0x4D, 0x30, 0x70, 0xBD, 0xF0, 0xB5, 0x41, 0x68, 0x82, 0x68, 0x88, 0x23, 0x5E, 0x18, 0x37, 0x88, 0x0B, 0x6F, 0x00, 0x2B, 0x01, 0xD1, 0x00, 0x2F, 0x10, 0xD1, 0x06, 0x2F, 0x02, 0xDD, 0x00, 0x21, 0xC9, 0x43, 0x07, 0xE0, 0x33, 0x88, 0x9B, 0x00, 0xC9, 0x18, 0x0A, 0x67, 0x31, 0x88, 0x01, 0x31, 0x31, 0x80, 0x01, 0x21, 0x81, 0x60, 0xE1, 0x48, 0x1D, 0x30, 0xF0, 0xBD, 0x0B, 0x1C, 0x01, 0x24, 0x5D, 0x6F, 0x1D, 0x67, 0x04, 0x33, 0x01, 0x34, 0x06, 0x2C, 0xE1, 0xDA, 0xF8, 0xE7, 0x00, 0xB5, 0x00, 0x21, 0xC1, 0x60, 0xE9, 0x48, 0x01, 0x68, 0x10, 0x31, 0xE6, 0x48, 0x20, 0x22, 0x01, 0x23, 0x9E, 0x46, 0xE7, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE5, 0x48, 0xFB, 0x30, 0x00, 0xBD, 0xFF, 0xFF, 0xC0, 0x68, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x14, 0x0D, 0x1B, 0x00, 0x54, 0x19, 0x1B, 0x00, 0x91, 0x1A, 0x01, 0x00, 0x4B, 0xAD, 0x03, 0x00, 0x61, 0x4E, 0x01, 0x00, 0x06, 0x32, 0x08, 0x00, 0x1F, 0x0B, 0x02, 0x00, 0x54, 0x3F ,
+0x08, 0x00, 0x45, 0xC1, 0x00, 0x00, 0x84, 0x3C, 0x08, 0x00, 0x1B, 0x02, 0x00, 0x00, 0xED, 0x17, 0x00, 0x00, 0xF3, 0xC1, 0x01, 0x00, 0x34, 0x19, 0x1B, 0x00, 0x08, 0x19, 0x1B, 0x00, 0xA6, 0x44, 0x08, 0x00, 0x1C, 0x17, 0x1B, 0x00, 0x18, 0x17, 0x1B, 0x00, 0xCB, 0x67, 0x03, 0x00, 0x0D, 0x47, 0x02, 0x00, 0x39, 0x42, 0x03, 0x00, 0xBD, 0xE7, 0x02, 0x00, 0xB1, 0x40, 0x03, 0x00, 0xB9, 0xEA, 0x01, 0x00, 0x45, 0xDA, 0x00, 0x00, 0x24, 0x41, 0x08, 0x00, 0x71, 0xC0, 0x02, 0x00, 0xF0, 0xB5, 0x88, 0xB0, 0x06, 0x91, 0x07, 0x90, 0x86, 0x69, 0xF0, 0x1C, 0xD9, 0xA1, 0x04, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x14, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x32, 0xD1, 0xF2, 0x79, 0xD7, 0x48, 0x02, 0x70, 0x35, 0x7A, 0x77, 0x7A, 0x78, 0x1B, 0xFF, 0xFF, 0x56, 0x69, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x43, 0x1C, 0x93, 0x42, 0x1D, 0xD0, 0x16, 0x2A, 0x0C, 0xDB, 0x00, 0x2D, 0x0A, 0xD1, 0xD6, 0x48, 0x04, 0x70, 0x0A, 0x20 ,
+0x81, 0x19, 0xD0, 0x48, 0x1A, 0x1C, 0xA6, 0x46, 0xB8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x74, 0xE0, 0xD2, 0x48, 0x04, 0x70, 0xCC, 0x48, 0x40, 0x19, 0x0A, 0x21, 0x89, 0x19, 0x7A, 0x1B, 0x52, 0x1C, 0xA6, 0x46, 0xB1, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x67, 0xE0, 0x8F, 0xC6, 0x03, 0x00, 0xC9, 0x48, 0x04, 0x70, 0xC9, 0x48, 0x04, 0x70, 0x0A, 0x20, 0x81, 0x19, 0xC2, 0x48, 0xA6, 0x46, 0xAA, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x59, 0xE0, 0xF0, 0x1C, 0x03, 0x21, 0x0A, 0x1C, 0xBC, 0xA1, 0xA6, 0x46, 0xC6, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x4F, 0xD1, 0xF1, 0x79, 0xBB, 0x48, 0x01, 0x70, 0xBB, 0x4D, 0xB2, 0x79, 0x2A, 0x70, 0x03, 0x20, 0x17, 0x49, 0xF4, 0x31, 0xA6, 0x46, 0xB8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x28, 0x78, 0x00, 0x28, 0x0B, 0xD1, 0xFF, 0xE7, 0xB8, 0x49, 0x0C, 0x70, 0xB8, 0x49, 0xFF, 0xFF, 0xEC, 0x69, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0C, 0x70, 0x03, 0x20, 0x0F, 0x49, 0xF5, 0x31, 0xA6, 0x46 ,
+0xB6, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x20, 0x1C, 0xF2, 0x79, 0x35, 0x7A, 0x77, 0x7A, 0x79, 0x1B, 0x4B, 0x1C, 0x93, 0x42, 0x20, 0xD0, 0xA9, 0x49, 0x09, 0x78, 0x16, 0x29, 0x0F, 0xDB, 0x00, 0x2D, 0x0D, 0xD1, 0xAB, 0x49, 0x08, 0x70, 0x0A, 0x20, 0x81, 0x19, 0xE9, 0x48, 0x1A, 0x1C, 0xA6, 0x46, 0x8B, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x1A, 0xE0, 0xC0, 0x46, 0xC7, 0x04, 0x00, 0x00, 0xA5, 0x49, 0x08, 0x70, 0xE3, 0x48, 0x40, 0x19, 0x0A, 0x21, 0x89, 0x19, 0x7A, 0x1B, 0x52, 0x1C, 0xA6, 0x46, 0x83, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x0A, 0xE0, 0x9E, 0x49, 0x08, 0x70, 0x9E, 0x49, 0x08, 0x70, 0x0A, 0x20, 0x81, 0x19, 0xDB, 0x48, 0xA6, 0x46, 0x7D, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x96, 0x48, 0x00, 0x78, 0x00, 0x28, 0x0A, 0xD0, 0x95, 0x48, 0x00, 0x78, 0x00, 0x28, 0x06, 0xD0, 0x94, 0x48, 0x00, 0x78, 0x00, 0x28, 0x02, 0xD0, 0x93, 0x48, 0x00, 0x78, 0x00, 0x28, 0xFF, 0xFF, 0x82, 0x6A, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00 ,
+0x00, 0xD1, 0x8C, 0xE0, 0x03, 0x20, 0x17, 0x21, 0x89, 0x01, 0xA6, 0x46, 0x90, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x87, 0x48, 0x01, 0x78, 0x87, 0x48, 0x07, 0x78, 0x84, 0x4E, 0x83, 0x4D, 0xE0, 0x48, 0x00, 0x68, 0x00, 0x28, 0x2E, 0xD1, 0x07, 0x98, 0x41, 0x61, 0x06, 0x62, 0xC6, 0x48, 0x06, 0x9A, 0x10, 0x64, 0x02, 0x2F, 0x01, 0xD0, 0x03, 0x2F, 0x01, 0xD1, 0x03, 0x22, 0x00, 0xE0, 0x3A, 0x1C, 0x06, 0x9B, 0xDA, 0x63, 0x2A, 0x78, 0x9A, 0x63, 0x01, 0x2F, 0x03, 0xD1, 0x05, 0x29, 0x04, 0xD0, 0x0D, 0x29, 0x02, 0xD0, 0xEC, 0x48, 0xDB, 0x30, 0x64, 0xE0, 0x00, 0x25, 0x00, 0x95, 0x01, 0x91, 0x02, 0x96, 0x03, 0x95, 0x04, 0x90, 0x2B, 0x1C, 0x20, 0x1C, 0x01, 0x1C, 0x8E, 0x46, 0xE6, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0xE6, 0x48, 0x04, 0x60, 0x28, 0x1C, 0xA6, 0x46, 0xE5, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x4C, 0xE0, 0x0D, 0x27, 0x00, 0x20, 0x39, 0x1C, 0x05, 0xAA, 0xA6, 0x46, 0xE3, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x68, 0x46 ,
+0xFF, 0xFF, 0x18, 0x6B, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x80, 0x8A, 0x40, 0x08, 0x05, 0xD2, 0x38, 0x1C, 0x50, 0x21, 0xA6, 0x46, 0xDC, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x38, 0x1C, 0x21, 0x1C, 0x0B, 0x1C, 0x29, 0x1C, 0x00, 0x22, 0xA6, 0x46, 0xD9, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x2B, 0x78, 0x0D, 0x20, 0x31, 0x1C, 0x22, 0x1C, 0xA6, 0x46, 0xD5, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0x28, 0x78, 0x01, 0x30, 0x02, 0x1C, 0x0D, 0x20, 0x57, 0x49, 0x23, 0x1C, 0xA6, 0x46, 0xD0, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0x55, 0x4E, 0x28, 0x78, 0x02, 0x30, 0x02, 0x1C, 0x0D, 0x20, 0x31, 0x1C, 0x23, 0x1C, 0xA6, 0x46, 0xCA, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x30, 0x78, 0x00, 0x28, 0x0A, 0xD0, 0x28, 0x78, 0x03, 0x30, 0x02, 0x1C, 0x4C, 0x48, 0x03, 0x78, 0x0D, 0x20, 0x8F, 0x49, 0xA6, 0x46, 0xC3, 0x4D, 0xFE, 0x44, 0x28, 0x47, 0xBF, 0x48, 0x04, 0x60, 0x00, 0x20, 0xA6, 0x46, 0xBE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0xB9, 0x48, 0xEC, 0x49 ,
+0x08, 0x18, 0x08, 0xB0, 0xF0, 0xBD, 0xC0, 0x46, 0x7B, 0xC0, 0xFF, 0xFF, 0xAE, 0x6B, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x1C, 0xE9, 0x48, 0x02, 0x68, 0xE9, 0x48, 0x00, 0x2A, 0x04, 0xD0, 0x00, 0x22, 0x0A, 0x62, 0x8A, 0x61, 0x1D, 0x30, 0xF7, 0x46, 0xD7, 0x30, 0xF7, 0x46, 0xC0, 0x46, 0x9F, 0x03, 0x00, 0x00, 0x7D, 0xB8, 0x03, 0x00, 0x01, 0x1C, 0xE2, 0x48, 0x02, 0x68, 0xE2, 0x48, 0x00, 0x2A, 0x02, 0xD0, 0xFF, 0x30, 0xB4, 0x30, 0xF7, 0x46, 0x00, 0x22, 0xCA, 0x61, 0x8A, 0x61, 0x4F, 0x30, 0xF7, 0x46, 0xC9, 0x21, 0x01, 0x00, 0x91, 0xE1, 0x00, 0x00, 0xDB, 0x48, 0x01, 0x68, 0x8A, 0x69, 0x01, 0x20, 0xC0, 0x03, 0x10, 0x43, 0x88, 0x61, 0x00, 0x20, 0x08, 0x61, 0xD8, 0x48, 0x23, 0x30, 0xF7, 0x46, 0x89, 0x17, 0x02, 0x00, 0x70, 0xB5, 0x05, 0x1C, 0xD5, 0x4E, 0x29, 0x6A, 0xEA, 0x69, 0x30, 0x1C, 0x01, 0x24, 0xA6, 0x46, 0x0B, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x68, 0x69, 0xA6, 0x46, 0xD1, 0x49 ,
+0xFE, 0x44, 0x08, 0x47, 0xA8, 0x69, 0x06, 0x30, 0xA8, 0x60, 0xCF, 0x48, 0x00, 0x68, 0x68, 0x60, 0xEE, 0x60, 0xCE, 0x48, 0xFF, 0xFF, 0x44, 0x6C, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x6D, 0x30, 0x70, 0xBD, 0x46, 0x17, 0x1B, 0x00, 0x30, 0x3F, 0x08, 0x00, 0x41, 0xEB, 0x00, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x30, 0xB5, 0xEE, 0x48, 0x01, 0x6D, 0x80, 0x6C, 0x08, 0x43, 0x18, 0xD0, 0xEC, 0x49, 0x08, 0x1C, 0x07, 0x22, 0xFF, 0x23, 0x09, 0x33, 0x1B, 0x58, 0x00, 0x2B, 0x04, 0xD0, 0xFF, 0x30, 0x1D, 0x30, 0x01, 0x3A, 0xF6, 0xD1, 0x0B, 0xE0, 0x02, 0x20, 0xF0, 0x4A, 0xF1, 0x4B, 0x01, 0x24, 0xA6, 0x46, 0xF0, 0x4D, 0xFE, 0x44, 0x28, 0x47, 0xA6, 0x46, 0xEF, 0x48, 0xFE, 0x44, 0x00, 0x47, 0xEF, 0x48, 0xFF, 0x30, 0x5C, 0x30, 0x30, 0xBD, 0xC0, 0x46, 0x53, 0x53, 0x49, 0x44, 0x00, 0xC0, 0x46, 0xC0, 0x4B, 0x45, 0x59, 0x00, 0xEE, 0x62, 0x08, 0x00, 0xF0, 0x62, 0x08, 0x00, 0xEC, 0x62, 0x08, 0x00, 0xED, 0x62, 0x08, 0x00 ,
+0xE7, 0x7E, 0x03, 0x00, 0xE8, 0x62, 0x08, 0x00, 0xE9, 0x62, 0x08, 0x00, 0xEA, 0x62, 0x08, 0x00, 0xEB, 0x62, 0x08, 0x00, 0xDD, 0x7E, 0x03, 0x00, 0x8F, 0xC6, 0x03, 0x00, 0xF0, 0xB5, 0xFF, 0xFF, 0xDA, 0x6C, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x87, 0xB0, 0x00, 0x91, 0x01, 0x90, 0x6B, 0x48, 0x01, 0x68, 0xCC, 0x4A, 0x14, 0x1C, 0x02, 0x94, 0x07, 0x26, 0x00, 0x25, 0x03, 0x95, 0x04, 0x94, 0x05, 0x95, 0xDF, 0x48, 0x00, 0x68, 0x08, 0x43, 0x27, 0xD0, 0xE0, 0x68, 0x03, 0x99, 0x88, 0x42, 0x0A, 0xDD, 0x03, 0x90, 0x40, 0x1C, 0x00, 0x99, 0x88, 0x60, 0xC2, 0x49, 0xFF, 0x20, 0x1D, 0x30, 0x68, 0x43, 0x0C, 0x18, 0xE0, 0x68, 0x04, 0x91, 0x02, 0x99, 0xC9, 0x68, 0x88, 0x42, 0x10, 0xDB, 0x88, 0x42, 0x10, 0xD1, 0x02, 0x98, 0x01, 0x27, 0xBE, 0x46, 0xCE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x06, 0x90, 0x20, 0x1C, 0xBE, 0x46, 0xCB, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x06, 0x99, 0x88, 0x42, 0x01, 0xDA, 0x05, 0x95, 0x02, 0x94 ,
+0x51, 0x48, 0x01, 0x68, 0xFF, 0x27, 0x09, 0x37, 0x38, 0x59, 0x00, 0x28, 0x06, 0xD0, 0xC7, 0x48, 0x00, 0x68, 0x07, 0x2E, 0x00, 0xD1, 0x2E, 0x1C, 0x08, 0x43, 0x04, 0xD0, 0xFF, 0x34, 0x1D, 0x34, 0x01, 0x35, 0x07, 0x2D, 0xC2, 0xDB, 0x07, 0x2E, 0xFF, 0xFF, 0x70, 0x6D, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0A, 0xD1, 0xC0, 0x48, 0x00, 0x68, 0x08, 0x43, 0x06, 0xD0, 0x05, 0x9E, 0x30, 0x1C, 0x01, 0x21, 0x8E, 0x46, 0xBA, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x01, 0x98, 0x47, 0x61, 0x00, 0x21, 0x81, 0x61, 0xFF, 0x22, 0x1D, 0x32, 0x72, 0x43, 0x04, 0x99, 0x89, 0x18, 0xC1, 0x61, 0x06, 0x62, 0xB4, 0x48, 0x39, 0x30, 0x07, 0xB0, 0xF0, 0xBD, 0x10, 0xB5, 0x04, 0x1C, 0x00, 0x20, 0x01, 0x21, 0x8E, 0x46, 0xB1, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x40, 0x1E, 0x00, 0xD5, 0x00, 0x20, 0x60, 0x60, 0xE0, 0x61, 0xAE, 0x48, 0x21, 0x30, 0x10, 0xBD, 0xC0, 0x46, 0x10, 0x63, 0x08, 0x00, 0x70, 0xB5, 0x04, 0x1C, 0xE5, 0x69, 0x66, 0x69 ,
+0x00, 0x20, 0x01, 0x21, 0x8E, 0x46, 0xA7, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x60, 0x60, 0xAB, 0x19, 0xA6, 0x4A, 0xA5, 0x49, 0x93, 0x42, 0x02, 0xD3, 0x9A, 0x1A, 0x82, 0x42, 0x02, 0xD9, 0x08, 0x1C, 0x99, 0x30, 0x70, 0xBD, 0x08, 0x1C, 0xAB, 0x30, 0x70, 0xBD, 0x08, 0x6B, 0x41, 0x7D, 0x02, 0x88, 0x92, 0x00, 0xFF, 0xFF, 0x06, 0x6E, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x51, 0x1A, 0x3C, 0x39, 0xFF, 0x22, 0x5F, 0x32, 0x91, 0x42, 0x03, 0xD9, 0x65, 0x21, 0x01, 0x80, 0x02, 0x21, 0x81, 0x73, 0x9B, 0x48, 0x99, 0x49, 0x08, 0x18, 0xF7, 0x46, 0xC0, 0x46, 0x30, 0x63, 0x08, 0x00, 0xF8, 0xB5, 0x40, 0x68, 0x24, 0x21, 0x41, 0x43, 0x97, 0x48, 0x45, 0x18, 0x28, 0x1D, 0x0C, 0x21, 0x49, 0x19, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x94, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x91, 0x4C, 0x00, 0x28, 0x1B, 0xD0, 0x2B, 0x1C, 0x04, 0x22, 0x6E, 0x46, 0x91, 0x49, 0x1F, 0x7B, 0x08, 0x78, 0xC0, 0x43, 0x38, 0x43, 0x30, 0x70, 0x01, 0x33 ,
+0x01, 0x31, 0x01, 0x36, 0x01, 0x3A, 0xF5, 0xD1, 0x0C, 0x20, 0x41, 0x19, 0x68, 0x46, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x87, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x02, 0xD0, 0x20, 0x1C, 0x4A, 0x30, 0xF8, 0xBD, 0x20, 0x1C, 0xF8, 0xBD, 0xB1, 0xBD, 0x00, 0x00, 0x15, 0x95, 0x00, 0x00, 0x58, 0x3F, 0x08, 0x00, 0xF3, 0xF8, 0x00, 0x00, 0xE9, 0x09, 0x02, 0x00, 0xFF, 0xFF, 0x9C, 0x6E, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x2B, 0x09, 0x02, 0x00, 0xDD, 0x0A, 0x02, 0x00, 0xF8, 0xB5, 0x05, 0x1C, 0xAA, 0x69, 0x7D, 0x49, 0x00, 0x20, 0x08, 0x56, 0x24, 0x21, 0x41, 0x43, 0x76, 0x48, 0x43, 0x18, 0x04, 0x24, 0x6E, 0x46, 0x76, 0x49, 0x1F, 0x79, 0x08, 0x78, 0xC0, 0x43, 0x38, 0x43, 0x30, 0x70, 0x01, 0x33, 0x01, 0x31, 0x01, 0x36, 0x01, 0x3C, 0xF5, 0xD1, 0x11, 0x1D, 0x68, 0x46, 0x04, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x6D, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x01, 0x1C, 0x6D, 0x48, 0x04, 0xD0, 0x6E, 0x49, 0x09, 0x78 ,
+0x69, 0x60, 0x45, 0x30, 0xF8, 0xBD, 0xEC, 0x61, 0xAF, 0x30, 0xF8, 0xBD, 0x70, 0xB5, 0xC5, 0x68, 0x81, 0x68, 0x0A, 0x89, 0x6D, 0x4E, 0x00, 0x2A, 0x22, 0xD0, 0x01, 0x24, 0xC2, 0x6D, 0xA2, 0x18, 0xC2, 0x65, 0x08, 0x89, 0x0D, 0x28, 0x1B, 0xD1, 0x68, 0x6B, 0x21, 0x1C, 0xA6, 0x46, 0x63, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x22, 0x1C, 0x28, 0x1C, 0x00, 0x21, 0xA6, 0x46, 0x60, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x2C, 0x60, 0xE9, 0x6B, 0xFF, 0xFF, 0x32, 0x6F, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x28, 0x1C, 0xA6, 0x46, 0x5E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x28, 0x1C, 0xA6, 0x46, 0x5C, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x30, 0x1C, 0x3D, 0x30, 0x70, 0xBD, 0x30, 0x1C, 0x23, 0x30, 0x70, 0xBD, 0xC0, 0x46, 0xB1, 0x02, 0x00, 0x00, 0x74, 0x3F, 0x08, 0x00, 0x19, 0xC6, 0x00, 0x00, 0x5C, 0x3F, 0x08, 0x00, 0x1D, 0xC2, 0x00, 0x00, 0x68, 0x44, 0x08, 0x00, 0x43, 0x12, 0x03, 0x00, 0x34, 0x63, 0x08, 0x00, 0x2F, 0x7A, 0x02, 0x00 ,
+0xB4, 0x36, 0x08, 0x00, 0x8F, 0xF4, 0x01, 0x00, 0xF0, 0xB5, 0x05, 0x1C, 0xAB, 0x69, 0xEC, 0x69, 0x60, 0x68, 0x00, 0x68, 0x2A, 0x30, 0x01, 0x78, 0x0A, 0x06, 0x41, 0x78, 0x09, 0x04, 0x8A, 0x18, 0x81, 0x78, 0x09, 0x02, 0x8A, 0x18, 0xC1, 0x78, 0x8A, 0x18, 0x8E, 0x26, 0xF1, 0x5A, 0x09, 0x0A, 0x01, 0x70, 0xF0, 0x5C, 0x61, 0x68, 0x09, 0x68, 0x2B, 0x26, 0x70, 0x54, 0x8C, 0x20, 0xC0, 0x18, 0x61, 0x68, 0x0E, 0x68, 0x01, 0x88, 0x09, 0x0A, 0x2C, 0x27, 0xB9, 0x55, 0x61, 0x68, 0x09, 0x68, 0xFF, 0xFF, 0xC8, 0x6F, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x2D, 0x26, 0x00, 0x78, 0x70, 0x54, 0x60, 0x68, 0x01, 0x68, 0x32, 0x31, 0x08, 0x78, 0x00, 0x02, 0x49, 0x78, 0x08, 0x18, 0x00, 0x04, 0x00, 0x0C, 0x8C, 0x21, 0xCB, 0x58, 0x35, 0x49, 0x41, 0x40, 0x08, 0x04, 0x00, 0x0C, 0xC0, 0x18, 0x80, 0x1A, 0x01, 0x21, 0x8E, 0x46, 0x32, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x61, 0x68, 0x0A, 0x68, 0x32, 0x23, 0x01, 0x0A, 0x99, 0x54 ,
+0x61, 0x68, 0x09, 0x68, 0x33, 0x22, 0x50, 0x54, 0x60, 0x68, 0x68, 0x60, 0x2C, 0x48, 0xF0, 0xBD, 0x00, 0x00, 0x1B, 0x00, 0x34, 0x04, 0x1B, 0x00, 0x02, 0x6A, 0x8B, 0x69, 0xDB, 0x69, 0x1B, 0x68, 0x83, 0x60, 0x88, 0x69, 0xC0, 0x69, 0x41, 0x68, 0x8A, 0x42, 0x00, 0xDA, 0x42, 0x60, 0x25, 0x48, 0x79, 0x30, 0xF7, 0x46, 0x24, 0x48, 0x57, 0x30, 0xF7, 0x46, 0x24, 0x48, 0x91, 0x30, 0xF7, 0x46, 0x32, 0x04, 0x00, 0x00, 0xC4, 0x07, 0x00, 0x00, 0x15, 0x09, 0x02, 0x00, 0xC5, 0x93, 0x00, 0x00, 0x0D, 0x91, 0x00, 0x00, 0x40, 0x1E, 0x80, 0x00, 0x1E, 0x4B, 0xFF, 0xFF, 0x5E, 0x70, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x19, 0x50, 0x1C, 0x49, 0x0A, 0x50, 0xF7, 0x46, 0xC0, 0x46, 0xBD, 0xB5, 0x00, 0x00, 0x95, 0x92, 0x00, 0x00, 0xFD, 0x93, 0x00, 0x00, 0x54, 0x3F, 0x08, 0x00, 0x29, 0x4F, 0x03, 0x00, 0xDF, 0xE8, 0x02, 0x00, 0x36, 0x89, 0x41, 0x00, 0x81, 0x06, 0x00, 0x00, 0xB1, 0x78, 0x00, 0x00, 0x94, 0xEC, 0x01, 0x00 ,
+0x08, 0x19, 0x1B, 0x00, 0x8F, 0xC6, 0x03, 0x00, 0x1C, 0x17, 0x1B, 0x00, 0x67, 0x66, 0x03, 0x00, 0xA6, 0x44, 0x08, 0x00, 0x18, 0x17, 0x1B, 0x00, 0xA7, 0x2F, 0x02, 0x00, 0x91, 0x44, 0x03, 0x00, 0x91, 0x63, 0x03, 0x00, 0x5B, 0x44, 0x03, 0x00, 0xE7, 0x44, 0x03, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x61, 0xA2, 0x03, 0x00, 0x6A, 0x1E, 0x01, 0x00, 0x45, 0xDA, 0x00, 0x00, 0xD7, 0xE8, 0x01, 0x00, 0xE9, 0x78, 0x02, 0x00, 0x04, 0xF3, 0x1A, 0x00, 0x80, 0x7B, 0x08, 0x00, 0xFC, 0xB5, 0x04, 0x1C, 0xA5, 0x69, 0x60, 0x6A, 0x01, 0x90, 0x20, 0x69, 0x00, 0x28, 0x35, 0xD4, 0x08, 0x28, 0x33, 0xDA, 0xE1, 0x69, 0x09, 0x68, 0xFF, 0xFF, 0xF4, 0x70, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x10, 0x29, 0x2F, 0xD1, 0xAC, 0x21, 0x41, 0x43, 0x9E, 0x4A, 0x51, 0x5C, 0x49, 0x08, 0x27, 0xD3, 0x00, 0x06, 0x00, 0x16, 0xA2, 0x68, 0x69, 0x46, 0x01, 0x23, 0x9E, 0x46, 0x9A, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x06, 0x1C, 0x39, 0x30, 0x1F, 0xD0 ,
+0x00, 0x2E, 0x1D, 0xD0, 0x00, 0x98, 0x07, 0x68, 0x00, 0x99, 0x0C, 0x39, 0x01, 0x98, 0x01, 0x60, 0x28, 0x1D, 0x10, 0x21, 0x79, 0x1A, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x91, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x02, 0x22, 0x2A, 0x80, 0xA8, 0x1C, 0x08, 0x21, 0x79, 0x1A, 0x01, 0x23, 0x9E, 0x46, 0x8C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x03, 0xE0, 0x38, 0x20, 0x00, 0xE0, 0x00, 0x20, 0xC6, 0x43, 0x26, 0x60, 0x89, 0x48, 0x7C, 0x30, 0x20, 0x62, 0xFC, 0xBD, 0x30, 0xB5, 0x05, 0x1C, 0x28, 0x69, 0xA9, 0x69, 0x90, 0x29, 0x1D, 0xD1, 0x69, 0x69, 0x09, 0x78, 0x04, 0x29, 0x19, 0xD0, 0x05, 0x29, 0x17, 0xD0, 0x0A, 0x29, 0x15, 0xD0, 0x06, 0x29, 0x13, 0xD0, 0x0C, 0x29, 0x01, 0xDB, 0xFF, 0xFF, 0x8A, 0x71, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x10, 0x29, 0x0F, 0xD1, 0x01, 0x24, 0xA6, 0x46, 0x7D, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x7C, 0x48, 0x7D, 0x49, 0x00, 0x22, 0xA6, 0x46, 0x7C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x7C, 0x48 ,
+0xFF, 0x30, 0x5F, 0x30, 0x28, 0x62, 0x30, 0xBD, 0xF0, 0xB5, 0x89, 0xB0, 0x05, 0x90, 0x41, 0x69, 0x02, 0x69, 0x75, 0x48, 0x79, 0x4E, 0x82, 0x42, 0x3A, 0xD0, 0x04, 0x30, 0x82, 0x42, 0x25, 0xD0, 0x74, 0x4D, 0xAA, 0x42, 0x00, 0xD0, 0xCC, 0xE0, 0x08, 0x68, 0x06, 0x1C, 0x0C, 0x22, 0x8F, 0x1A, 0x4A, 0x68, 0x89, 0x18, 0x09, 0x1D, 0x10, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x6E, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x01, 0x1C, 0x09, 0xD1, 0xAC, 0x22, 0x72, 0x43, 0xCB, 0x48, 0x80, 0x18, 0x46, 0x22, 0x12, 0x5C, 0x11, 0x2A, 0x01, 0xD1, 0x44, 0x22, 0x14, 0x54, 0x28, 0x1C, 0x3A, 0x1C, 0xA6, 0x46, 0x62, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x69, 0x48, 0xEC, 0x30, 0xAB, 0xE0, 0x08, 0x68, 0xC0, 0x00, 0x30, 0x18, 0x8A, 0x68, 0x02, 0x2A, 0x02, 0xD0, 0xFF, 0xFF, 0x20, 0x72, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xE7, 0x20, 0x80, 0x00, 0xA2, 0xE0, 0xCA, 0x68, 0x89, 0x18, 0x09, 0x7B, 0x41, 0x60, 0x80, 0x21, 0x01, 0x60, 0x3B, 0x20 ,
+0x00, 0x01, 0x99, 0xE0, 0x08, 0x68, 0x06, 0x90, 0xC0, 0x00, 0x34, 0x58, 0x10, 0x20, 0x04, 0x90, 0x01, 0x25, 0xAE, 0x46, 0x57, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x07, 0x90, 0x00, 0x28, 0x00, 0xD1, 0x89, 0xE0, 0x0C, 0x21, 0x07, 0x98, 0x0F, 0x18, 0xB0, 0x49, 0xAC, 0x20, 0x06, 0x9A, 0x50, 0x43, 0x08, 0x18, 0x48, 0x22, 0x13, 0x5C, 0x5B, 0x06, 0x5B, 0x0E, 0x13, 0x54, 0x06, 0x9A, 0xD2, 0x00, 0xB6, 0x18, 0x71, 0x68, 0x00, 0x29, 0x47, 0xD1, 0x00, 0x2C, 0x01, 0xDD, 0x08, 0x2C, 0x21, 0xDB, 0x00, 0x22, 0x69, 0x46, 0x0A, 0x70, 0x01, 0x92, 0x0A, 0x81, 0x8A, 0x72, 0xCD, 0x72, 0x0D, 0x73, 0x4D, 0x73, 0x01, 0x88, 0x44, 0x48, 0x06, 0x23, 0xAE, 0x46, 0x44, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x04, 0x1C, 0x02, 0xDC, 0x00, 0x20, 0xC0, 0x43, 0x36, 0xE0, 0x34, 0x60, 0xAC, 0x20, 0x60, 0x43, 0x9A, 0x49, 0xFF, 0xFF, 0xB6, 0x72, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x09, 0x18, 0x5C, 0x22, 0x28, 0x1C, 0x50, 0x54, 0x48, 0x20 ,
+0x42, 0x5C, 0x52, 0x06, 0x52, 0x0E, 0x42, 0x54, 0xAC, 0x20, 0x60, 0x43, 0x94, 0x49, 0x08, 0x18, 0x5C, 0x21, 0x09, 0x5C, 0x49, 0x1E, 0x02, 0x29, 0x16, 0xD9, 0x03, 0x39, 0x08, 0xD0, 0x00, 0x20, 0x30, 0x56, 0xAE, 0x46, 0xEA, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x80, 0x20, 0x30, 0x60, 0xDB, 0xE7, 0x08, 0x94, 0x80, 0x21, 0x31, 0x60, 0x48, 0x22, 0x13, 0x5C, 0x19, 0x43, 0x11, 0x54, 0xAE, 0x46, 0xE4, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x0A, 0xE0, 0x01, 0x20, 0xCE, 0xE7, 0x06, 0x98, 0x39, 0x1C, 0x04, 0xAA, 0xAE, 0x46, 0xE0, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x04, 0x1C, 0x08, 0x90, 0x06, 0x98, 0x38, 0x60, 0x08, 0x98, 0x78, 0x60, 0x00, 0x28, 0x15, 0xD0, 0xAC, 0x20, 0x60, 0x43, 0x7C, 0x49, 0x09, 0x18, 0x48, 0x88, 0x02, 0x04, 0x02, 0x20, 0x10, 0x43, 0xB8, 0x60, 0x48, 0x68, 0x02, 0x0E, 0x01, 0x02, 0x09, 0x0E, 0x09, 0x02, 0x11, 0x43, 0x02, 0x04, 0x12, 0x0E, 0xFF, 0xFF, 0x4C, 0x73, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00 ,
+0x12, 0x04, 0x0A, 0x43, 0x00, 0x06, 0x10, 0x43, 0xF8, 0x60, 0x07, 0x98, 0x0D, 0x49, 0x00, 0x22, 0x10, 0x23, 0xAE, 0x46, 0xCE, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x13, 0x48, 0x00, 0xE0, 0x16, 0x20, 0xCC, 0x49, 0x09, 0x18, 0x05, 0x98, 0x01, 0x62, 0x09, 0xB0, 0xF0, 0xBD, 0x5D, 0x0D, 0x1B, 0x00, 0x81, 0xE7, 0x02, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x27, 0x1A, 0x02, 0x00, 0x2F, 0x7A, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x05, 0x10, 0x00, 0x00, 0xCF, 0xF6, 0x00, 0x00, 0xD5, 0xF4, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x91, 0x19, 0x02, 0x00, 0x50, 0x65, 0x08, 0x00, 0x71, 0xC0, 0x02, 0x00, 0x50, 0x19, 0x1B, 0x00, 0x29, 0x16, 0x01, 0x00, 0x2A, 0x03, 0x00, 0x00, 0xF0, 0xB5, 0x8B, 0xB0, 0x07, 0x90, 0x05, 0x69, 0x47, 0x69, 0x0C, 0x20, 0x38, 0x1A, 0x08, 0x90, 0xB6, 0x49, 0x8D, 0x42, 0x16, 0xD1, 0x78, 0x68, 0x0F, 0x30, 0x00, 0x11, 0x00, 0x01, 0x78, 0x60, 0x38, 0x68, 0x0B, 0x28, 0x0E, 0xD8, 0x00, 0x23, 0x68, 0x46 ,
+0xFF, 0xFF, 0xE2, 0x73, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x03, 0x70, 0x08, 0x98, 0x05, 0x22, 0x01, 0x24, 0xA6, 0x46, 0xAE, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0xAE, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x07, 0x99, 0x08, 0x62, 0xAC, 0x48, 0x85, 0x42, 0x23, 0xD1, 0xAC, 0x48, 0x02, 0x78, 0x6C, 0x46, 0x22, 0x72, 0x43, 0x78, 0x63, 0x72, 0x81, 0x78, 0xA1, 0x72, 0xC0, 0x78, 0xE0, 0x72, 0x00, 0x91, 0x01, 0x90, 0x03, 0x20, 0xA6, 0x49, 0x01, 0x39, 0x01, 0x26, 0xB6, 0x46, 0xF3, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0x04, 0x20, 0x20, 0x70, 0x08, 0x98, 0x9F, 0x49, 0x00, 0x22, 0x02, 0xAB, 0x01, 0x24, 0xA6, 0x46, 0x9B, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x9A, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x07, 0x99, 0x08, 0x62, 0xEB, 0x49, 0x8D, 0x42, 0x14, 0xD1, 0x02, 0x22, 0x68, 0x46, 0x02, 0x70, 0x3A, 0x68, 0xAC, 0x20, 0x42, 0x43, 0x30, 0x48, 0x68, 0x30, 0x83, 0x18, 0x08, 0x98, 0x00, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x8F, 0x4C, 0xFE, 0x44 ,
+0x20, 0x47, 0x8E, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x07, 0x99, 0xFF, 0xFF, 0x78, 0x74, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x08, 0x62, 0xEF, 0x48, 0x85, 0x42, 0x00, 0xD0, 0x04, 0xE1, 0x03, 0x20, 0x8C, 0x49, 0x01, 0x22, 0x96, 0x46, 0xEC, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x86, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x09, 0x90, 0x38, 0x68, 0xEA, 0x4D, 0x00, 0x28, 0x00, 0xD1, 0xE2, 0xE0, 0x01, 0x24, 0xA6, 0x46, 0xE6, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x00, 0x28, 0x00, 0xD1, 0xD6, 0xE0, 0xE4, 0x48, 0x02, 0x68, 0x03, 0x20, 0x7F, 0x49, 0x01, 0x31, 0xA6, 0x46, 0xE2, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xDF, 0x48, 0x00, 0x68, 0x00, 0x28, 0x5A, 0xD1, 0xDF, 0x4D, 0x2E, 0x20, 0x41, 0x19, 0xB8, 0x68, 0x03, 0x30, 0x08, 0x70, 0x38, 0x7A, 0x48, 0x70, 0x2E, 0x1C, 0x30, 0x36, 0xB8, 0x68, 0x28, 0x18, 0x30, 0x30, 0xDA, 0x49, 0x0A, 0x68, 0x30, 0x3A, 0x31, 0x1C, 0xA6, 0x46, 0xD8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x78, 0x68, 0x38, 0x18 ,
+0x01, 0x1D, 0xBA, 0x68, 0x30, 0x1C, 0xA6, 0x46, 0xD9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xB8, 0x68, 0x41, 0x19, 0x97, 0x22, 0xFF, 0xFF, 0x0E, 0x75, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x09, 0x30, 0x50, 0x54, 0xB8, 0x68, 0x46, 0x19, 0x9E, 0x36, 0x30, 0x70, 0x01, 0x36, 0xB8, 0x68, 0x01, 0xE0, 0x14, 0x0D, 0x1B, 0x00, 0x30, 0x18, 0xCA, 0x49, 0x0A, 0x68, 0x9E, 0x3A, 0x31, 0x1C, 0xA6, 0x46, 0xC8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x78, 0x68, 0x38, 0x18, 0x01, 0x1D, 0xBA, 0x68, 0x30, 0x1C, 0xA6, 0x46, 0xC9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xB8, 0x68, 0x40, 0x00, 0xC0, 0x49, 0x09, 0x68, 0x08, 0x18, 0x28, 0x18, 0xC0, 0x49, 0x0A, 0x79, 0x02, 0x70, 0x4A, 0x79, 0x42, 0x70, 0x8A, 0x79, 0x82, 0x70, 0xC9, 0x79, 0xC1, 0x70, 0x04, 0x30, 0x0F, 0x21, 0x41, 0x1A, 0x0A, 0x78, 0xBB, 0x68, 0x9A, 0x18, 0x0A, 0x70, 0x40, 0x1B, 0x00, 0x04, 0x00, 0x0C, 0xB5, 0x49, 0x08, 0x60, 0xB1, 0x48, 0x04, 0x60, 0x02, 0x20, 0x01, 0x1C ,
+0x11, 0x22, 0xA6, 0x46, 0xB4, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x06, 0x1C, 0x63, 0xD4, 0x03, 0x20, 0xA6, 0x46, 0xB1, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x0A, 0x90, 0x00, 0x25, 0x01, 0x1C, 0xFF, 0xFF, 0xA4, 0x75, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x8D, 0x42, 0x50, 0xD0, 0x29, 0x1C, 0x2B, 0x22, 0xA6, 0x46, 0xAD, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x0C, 0x20, 0x0A, 0x99, 0x40, 0x18, 0xAC, 0x22, 0x72, 0x43, 0xAB, 0x49, 0x8F, 0x18, 0x78, 0x63, 0x29, 0x1C, 0x18, 0x22, 0xA6, 0x46, 0xA6, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x9F, 0x48, 0x02, 0x68, 0x79, 0x6B, 0x4A, 0x60, 0x0A, 0x98, 0xAC, 0x30, 0x08, 0x60, 0x08, 0x68, 0x9A, 0x49, 0xA6, 0x46, 0xA0, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x29, 0x1C, 0x03, 0xA8, 0x10, 0x22, 0xA6, 0x46, 0x9C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE0, 0x21, 0x68, 0x46, 0x01, 0x74, 0x45, 0x74, 0x85, 0x74, 0xFB, 0x21, 0xC1, 0x74, 0xEE, 0x49, 0xC1, 0x81, 0x02, 0x21, 0x81, 0x81, 0x79, 0x6B, 0xCA, 0x68 ,
+0x01, 0x20, 0xC0, 0x03, 0x10, 0x43, 0xC8, 0x60, 0x48, 0x68, 0x00, 0x90, 0x2A, 0x1C, 0x30, 0x1C, 0x0A, 0x9D, 0x29, 0x1C, 0x03, 0xAB, 0xA6, 0x46, 0xE6, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x07, 0x1C, 0x30, 0x06, 0x00, 0x16, 0xA6, 0x46, 0xEF, 0x49, 0xFF, 0xFF, 0x3A, 0x76, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xFE, 0x44, 0x08, 0x47, 0x28, 0x1C, 0xA6, 0x46, 0xEE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x11, 0xE0, 0x30, 0x06, 0x00, 0x16, 0xA6, 0x46, 0xE9, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x01, 0x20, 0xC7, 0x43, 0x08, 0xE0, 0x07, 0x1C, 0x06, 0xE0, 0x00, 0x20, 0x00, 0x21, 0xCF, 0x43, 0x01, 0xE0, 0x00, 0x20, 0x07, 0x1C, 0x28, 0x60, 0x00, 0x23, 0x68, 0x46, 0x03, 0x70, 0x3A, 0x06, 0x12, 0x0E, 0x08, 0x98, 0x6F, 0x49, 0x01, 0x24, 0xA6, 0x46, 0x09, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x07, 0x98, 0x09, 0x99, 0x01, 0x62, 0x0B, 0xB0, 0xF0, 0xBD, 0xC1, 0x18, 0x01, 0x00, 0xF1, 0x1B, 0x01, 0x00, 0xF3, 0x1C, 0x02, 0x00, 0x7B, 0xC0 ,
+0x02, 0x00, 0x91, 0xF0, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0xA3, 0xC0, 0x02, 0x00, 0xA9, 0xE9, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00, 0xE4, 0x62, 0x08, 0x00, 0xAC, 0x05, 0x00, 0x00, 0xFE, 0xB5, 0x07, 0x1C, 0x7D, 0x69, 0xBE, 0x69, 0x0C, 0x20, 0x30, 0x1A, 0x01, 0x90, 0xDF, 0x4C, 0x0A, 0x2D, 0x13, 0xD1, 0xFF, 0xFF, 0xD0, 0x76, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x30, 0x68, 0xDB, 0x49, 0x08, 0x60, 0x01, 0x20, 0x86, 0x46, 0xDA, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x0A, 0x20, 0x00, 0x21, 0x01, 0x9A, 0x01, 0x23, 0x9E, 0x46, 0xE6, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xF5, 0x20, 0x80, 0x00, 0x00, 0x19, 0x38, 0x62, 0x03, 0x2D, 0x79, 0xD1, 0xF5, 0x20, 0x80, 0x00, 0x00, 0x19, 0x02, 0x90, 0x70, 0x68, 0x00, 0x28, 0x0C, 0xD1, 0x00, 0x21, 0xCF, 0x48, 0x01, 0x60, 0xCF, 0x48, 0x00, 0x68, 0x00, 0x28, 0x61, 0xD0, 0x01, 0x21, 0x8E, 0x46, 0xCD, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x5B, 0xE0, 0xCC, 0x48, 0xB1, 0x68, 0x01, 0x60 ,
+0xF1, 0x68, 0x41, 0x60, 0x31, 0x69, 0x81, 0x60, 0x71, 0x69, 0xC1, 0x60, 0xB1, 0x69, 0xC1, 0x63, 0xF1, 0x69, 0x01, 0x64, 0x31, 0x6A, 0xC1, 0x64, 0x01, 0x24, 0xA6, 0x46, 0xC5, 0x48, 0xFE, 0x44, 0x00, 0x47, 0xA6, 0x46, 0xC4, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x70, 0x68, 0x7D, 0x25, 0xED, 0x00, 0xA8, 0x42, 0x21, 0xD8, 0x01, 0x28, 0x18, 0xD0, 0x02, 0x28, 0x05, 0xD0, 0xFF, 0xFF, 0x66, 0x77, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x28, 0x1C, 0xA6, 0x46, 0xBE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x1C, 0xE0, 0xB9, 0x48, 0x00, 0x23, 0x19, 0x1C, 0x59, 0x43, 0x3E, 0x22, 0x4A, 0x43, 0x82, 0x83, 0x02, 0x30, 0x01, 0x33, 0x10, 0x2B, 0xF6, 0xDB, 0xA6, 0x46, 0xB4, 0x48, 0xFE, 0x44, 0x00, 0x47, 0xB5, 0x48, 0x0D, 0xE0, 0xB5, 0x4D, 0x28, 0x1C, 0xA6, 0x46, 0xB2, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x04, 0xE0, 0xA6, 0x46, 0xAF, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x75, 0x68, 0xAE, 0x48, 0x05, 0x60, 0x05, 0x1C, 0xA7, 0x4E, 0x30, 0x68 ,
+0x00, 0x28, 0x06, 0xD1, 0xAD, 0x48, 0x00, 0x68, 0xA6, 0x46, 0xAC, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x30, 0x60, 0x00, 0x94, 0x2B, 0x68, 0xAA, 0x49, 0xAB, 0x4A, 0xA6, 0x46, 0xAB, 0x4D, 0xFE, 0x44, 0x28, 0x47, 0x9C, 0x48, 0x04, 0x60, 0x03, 0x20, 0x00, 0x21, 0x01, 0x9A, 0x01, 0x23, 0x9E, 0x46, 0xA7, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x02, 0x98, 0x38, 0x62, 0xFE, 0xBD, 0xC0, 0x46, 0x13, 0x7F, 0x03, 0x00, 0x12, 0x10, 0x00, 0x00, 0xFF, 0xFF, 0xFC, 0x77, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x30, 0xB5, 0x05, 0x1C, 0x00, 0x20, 0x01, 0x24, 0xA6, 0x46, 0xA0, 0x49, 0xFE, 0x44, 0x08, 0x47, 0xA6, 0x46, 0x9F, 0x49, 0xFE, 0x44, 0x08, 0x47, 0xA6, 0x46, 0x9E, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x7D, 0x21, 0xC9, 0x00, 0xA6, 0x46, 0x9E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x9B, 0x49, 0x08, 0x18, 0x99, 0x49, 0x08, 0x80, 0x9B, 0x48, 0x0A, 0x30, 0x28, 0x62, 0x30, 0xBD, 0x11, 0x10, 0x00, 0x00, 0xDD, 0x7E, 0x03, 0x00, 0xB9, 0x90 ,
+0x00, 0x00, 0x6C, 0x64, 0x08, 0x00, 0xE7, 0x7E, 0x03, 0x00, 0x74, 0x64, 0x08, 0x00, 0x70, 0x64, 0x08, 0x00, 0x6D, 0xC6, 0x03, 0x00, 0x08, 0x19, 0x1B, 0x00, 0x11, 0x18, 0x02, 0x00, 0xD1, 0x78, 0x02, 0x00, 0xC9, 0xBA, 0x03, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x14, 0x0D, 0x1B, 0x00, 0xFE, 0xB5, 0x02, 0x90, 0x45, 0x69, 0x68, 0x46, 0x01, 0x21, 0x8E, 0x46, 0x89, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x89, 0x48, 0x04, 0x1C, 0x68, 0x68, 0x01, 0x69, 0x4A, 0x78, 0x00, 0x27, 0x3E, 0x1C, 0x20, 0x88, 0xFF, 0xFF, 0x92, 0x78, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x40, 0x08, 0x22, 0xD3, 0x20, 0x1D, 0x89, 0x1C, 0x01, 0x23, 0x9E, 0x46, 0x83, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x07, 0xD1, 0x68, 0x68, 0x00, 0x69, 0x40, 0x78, 0x21, 0x88, 0x09, 0x04, 0x89, 0x16, 0x81, 0x42, 0x3D, 0xD0, 0x02, 0x20, 0x00, 0x5F, 0x00, 0x99, 0x08, 0x1A, 0x00, 0x04, 0x00, 0x14, 0x3C, 0x28, 0x03, 0xDD, 0x20, 0x88, 0x40, 0x10, 0x40, 0x00 ,
+0x20, 0x80, 0x78, 0x1C, 0x07, 0x06, 0x3F, 0x0E, 0x68, 0x68, 0x01, 0x69, 0x4A, 0x78, 0x2A, 0x34, 0x01, 0x36, 0x14, 0x2E, 0xD5, 0xDB, 0x00, 0x2A, 0x02, 0xD1, 0xAB, 0x20, 0x40, 0x00, 0x50, 0xE0, 0x00, 0x9B, 0x6D, 0x48, 0x14, 0x21, 0x00, 0x22, 0x04, 0x88, 0x64, 0x08, 0x03, 0xD3, 0x2A, 0x30, 0x01, 0x32, 0x01, 0x39, 0xF8, 0xD1, 0x12, 0x06, 0x12, 0x0E, 0x14, 0x2F, 0x16, 0xD1, 0x66, 0x48, 0x00, 0x88, 0x00, 0x06, 0x44, 0x16, 0x64, 0x49, 0x00, 0x22, 0x01, 0x20, 0x4E, 0x8D, 0x36, 0x06, 0x76, 0x16, 0xA6, 0x42, 0x02, 0xDD, 0x34, 0x1C, 0x02, 0x06, 0xFF, 0xFF, 0x28, 0x79, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x12, 0x0E, 0x2A, 0x31, 0x01, 0x30, 0x14, 0x28, 0xF3, 0xDB, 0x02, 0xE0, 0x32, 0x06, 0x12, 0x0E, 0x00, 0x9B, 0x2A, 0x20, 0x42, 0x43, 0x5A, 0x48, 0x11, 0x18, 0x0C, 0x88, 0x01, 0x20, 0x20, 0x43, 0x00, 0x04, 0x00, 0x0C, 0x08, 0x80, 0xFE, 0x24, 0xA0, 0x43, 0x14, 0x24, 0x64, 0x57, 0x64, 0x06, 0x24, 0x0E ,
+0x04, 0x43, 0x52, 0x48, 0x14, 0x52, 0x14, 0x18, 0x63, 0x80, 0x08, 0x88, 0x80, 0x05, 0x82, 0x0D, 0x68, 0x68, 0x00, 0x69, 0x40, 0x78, 0x80, 0x02, 0x10, 0x43, 0x08, 0x80, 0x68, 0x68, 0x02, 0x69, 0x20, 0x1D, 0x91, 0x1C, 0x52, 0x78, 0x01, 0x23, 0x9E, 0x46, 0x4B, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x02, 0x98, 0x04, 0x61, 0xFE, 0x20, 0x47, 0x49, 0x09, 0x18, 0x02, 0x98, 0x01, 0x62, 0xFE, 0xBD, 0x82, 0x69, 0x41, 0x69, 0x03, 0x69, 0x02, 0x2B, 0x0A, 0xD1, 0x01, 0x2A, 0x01, 0xD1, 0x00, 0x29, 0x05, 0xD0, 0x02, 0x2A, 0x04, 0xD1, 0x00, 0x29, 0x02, 0xD1, 0x11, 0x21, 0x00, 0xE0, 0x06, 0x21, 0x41, 0x61, 0xF7, 0x46, 0xFF, 0xFF, 0xBE, 0x79, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xC0, 0x46, 0x14, 0xE9, 0x00, 0x00, 0xC9, 0x18, 0x02, 0x00, 0x30, 0xB5, 0x05, 0x1C, 0x3A, 0x48, 0x00, 0x78, 0x00, 0x28, 0x04, 0xD0, 0x01, 0x20, 0x86, 0x46, 0x38, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x01, 0x24, 0xA6, 0x46, 0x37, 0x48, 0xFE, 0x44 ,
+0x00, 0x47, 0xA6, 0x46, 0x36, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x35, 0x48, 0x0E, 0x30, 0x28, 0x62, 0x30, 0xBD, 0x49, 0x19, 0x01, 0x00, 0x2F, 0x7A, 0x02, 0x00, 0x18, 0xB5, 0x43, 0x69, 0x81, 0x69, 0x31, 0x48, 0x81, 0x29, 0x00, 0xD1, 0x0B, 0x38, 0x00, 0x21, 0x00, 0x91, 0x1A, 0x68, 0x9B, 0x68, 0x01, 0x24, 0xA6, 0x46, 0x2D, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x18, 0xBD, 0x18, 0xB5, 0x40, 0x69, 0x00, 0x21, 0x00, 0x91, 0x02, 0x68, 0x83, 0x68, 0x27, 0x48, 0x01, 0x30, 0x01, 0x24, 0xA6, 0x46, 0x26, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x18, 0xBD, 0xC0, 0x46, 0x30, 0x63, 0x08, 0x00, 0x19, 0x9E, 0x00, 0x00, 0xB9, 0xEC, 0x00, 0x00, 0x74, 0x3F, 0x08, 0x00, 0x80, 0x3F, 0x08, 0x00, 0xFF, 0xFF, 0x54, 0x7A, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xB7, 0x5D, 0x03, 0x00, 0x00, 0x00, 0x1B, 0x00, 0xD3, 0x8E, 0x00, 0x00, 0xF7, 0xC6, 0x00, 0x00, 0xE5, 0x90, 0x00, 0x00, 0x68, 0x64, 0x08, 0x00, 0xC0, 0x27, 0x09, 0x00, 0xA0, 0x3B ,
+0x08, 0x00, 0x3D, 0x5D, 0x03, 0x00, 0x19, 0xC6, 0x00, 0x00, 0xE8, 0x3A, 0x08, 0x00, 0x81, 0x5D, 0x03, 0x00, 0xCF, 0xF6, 0x00, 0x00, 0x4B, 0x4F, 0x03, 0x00, 0x6B, 0xC0, 0x03, 0x00, 0x95, 0x1E, 0x01, 0x00, 0xDA, 0x40, 0x08, 0x00, 0xDC, 0x05, 0x00, 0x00, 0x55, 0xAA, 0x03, 0x00, 0x0D, 0x91, 0x00, 0x00, 0xD7, 0x56, 0x03, 0x00, 0x08, 0x51, 0x08, 0x00, 0x8F, 0xC6, 0x03, 0x00, 0x65, 0xB8, 0x00, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x84, 0x17, 0x1B, 0x00, 0xB5, 0x86, 0x01, 0x00, 0x3D, 0x47, 0x02, 0x00, 0x73, 0x49, 0x02, 0x00, 0x5F, 0x90, 0x00, 0x00, 0x0E, 0x10, 0x00, 0x00, 0xF7, 0xF6, 0x00, 0x00, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x76, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x5A, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5, 0xFF, 0xFF, 0xEA, 0x7A, 0x08, 0x00, 0x58, 0x00, 0x00, 0x00, 0x68, 0x46, 0xFF, 0xF7, 0x99, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x83, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5 ,
+0x68, 0x46, 0xFF, 0xF7, 0xB6, 0xFE, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x55, 0xFC, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x27, 0xFB, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0xDD, 0xFA, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x68, 0xFE, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x3D, 0xFB, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0xBE, 0xFD, 0xFF, 0xBD, 0x78, 0x7B, 0x08, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0xB5, 0xF8, 0xF0, 0x43, 0xFA, 0x00, 0xBD, 0x35, 0x66, 0x08, 0x00, 0x67, 0x66, 0x08, 0x00, 0x71, 0x65, 0x08, 0x00, 0x4D, 0x66, 0x08, 0x00, 0x25, 0x64, 0x08, 0x00, 0x81, 0x66, 0x08, 0x00, 0x8D, 0x66, 0x08, 0x00, 0x99, 0x66, 0x08, 0x00, 0x87, 0x67, 0x08, 0x00, 0xA7, 0x67, 0x08, 0x00, 0xD1, 0x67, 0x08, 0x00, 0x1B, 0x68, 0x08, 0x00, 0x57, 0x68, 0x08, 0x00, 0x2D, 0x69, 0x08, 0x00, 0xB1, 0x6B, 0x08, 0x00, 0xD5, 0x6B, 0x08, 0x00, 0xF9, 0x6B ,
+0x08, 0x00, 0x15, 0x6C, 0x08, 0x00, 0xA1, 0x68, 0x08, 0x00, 0x59, 0x6C, 0x08, 0x00, 0xA7, 0x6D, 0x08, 0x00, 0xFF, 0x6D, 0x08, 0x00, 0x29, 0x6E, 0x08, 0x00, 0xF9, 0x6E, 0x08, 0x00, 0xD9, 0x6C, 0x08, 0x00, 0xA5, 0x6E, 0x08, 0x00, 0xCD, 0x6D, 0x08, 0x00, 0x81, 0x6F, 0x08, 0x00, 0x1D, 0x70, 0x08, 0x00, 0x31, 0x64, 0x08, 0x00, 0x39, 0x70, 0x08, 0x00, 0x3F, 0x70, 0x08, 0x00, 0x04, 0xF3, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x00, 0xB2, 0x4E, 0x01, 0x00, 0x5A, 0xC1, 0x00, 0x00, 0x96, 0x1A, 0x01, 0x00, 0x22, 0x0B, 0x02, 0x00, 0x60, 0xD0, 0x01, 0x00, 0x06, 0x1A, 0x00, 0x00, 0xB8, 0xC6, 0x01, 0x00, 0xD8, 0x42, 0x03, 0x00, 0x16, 0x42, 0x03, 0x00, 0xEE, 0xDB, 0x00, 0x00, 0x62, 0xDC, 0x00, 0x00, 0xC8, 0xE1, 0x00, 0x00, 0x8A, 0x17, 0x02, 0x00, 0x38, 0xBE, 0x00, 0x00, 0x26, 0xC6, 0x00, 0x00, 0x56, 0xC2, 0x00, 0x00, 0x62, 0x12, 0x03, 0x00, 0xE4, 0xF4, 0x01, 0x00, 0x3A, 0xEC, 0x00, 0x00, 0x5E, 0x92, 0x00, 0x00 ,
+0xFE, 0xE8, 0x02, 0x00, 0x18, 0x7F, 0x00, 0x00, 0x64, 0xEC, 0x01, 0x00, 0xFE, 0x44, 0x03, 0x00, 0x1C, 0x94, 0x00, 0x00, 0xA8, 0x66, 0x03, 0x00, 0x74, 0xE9, 0x02, 0x00, 0x68, 0x1E, 0x01, 0x00, 0xBC, 0xDA, 0x00, 0x00, 0xEA, 0xE1, 0x00, 0x00, 0x24, 0xE9, 0x01, 0x00, 0x70, 0x79, 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x1C, 0xF0, 0xB5, 0x88, 0xB0, 0xCA, 0x4C, 0x03, 0x20, 0x22, 0x78, 0x63, 0x78, 0xCA, 0x4E, 0x31, 0x1C, 0x01, 0x39, 0x01, 0x25, 0xAE, 0x46, 0xC7, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0xA2, 0x78, 0xE3, 0x78, 0x03, 0x20, 0x31, 0x1C, 0xAE, 0x46, 0xC3, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x03, 0x20, 0x31, 0x1C, 0x01, 0x31, 0xAE, 0x46, 0xC1, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0xC1, 0x48, 0x21, 0x78, 0x01, 0x70, 0x61, 0x78, 0x41, 0x70, 0xE1, 0x78, 0xC1, 0x70, 0xA1, 0x78, 0x81, 0x70, 0xBF, 0x48, 0x04, 0x1C, 0x33, 0x3C, 0x20, 0x1C, 0x00, 0x21, 0xDC, 0x22, 0xAE, 0x46 ,
+0xBA, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x84, 0x20, 0xA0, 0x70, 0x05, 0x27, 0xE7, 0x71, 0x0C, 0x26, 0x26, 0x73, 0x0D, 0x20, 0x00, 0x19, 0x98, 0xA1, 0x32, 0x1C, 0xAE, 0x46, 0xB4, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x04, 0x20, 0x60, 0x76, 0x1A, 0x20, 0x00, 0x19, 0x97, 0xA1, 0x06, 0x91, 0x04, 0x22, 0xAE, 0x46, 0xAE, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xFF, 0xFF, 0x96, 0x00, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0xA7, 0x77, 0x1F, 0x34, 0x95, 0xA1, 0x07, 0x91, 0x20, 0x1C, 0x3A, 0x1C, 0xAE, 0x46, 0xA9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE6, 0x71, 0x28, 0x1C, 0x60, 0x72, 0x11, 0x20, 0x20, 0x73, 0x94, 0x20, 0x60, 0x73, 0xC0, 0x25, 0x65, 0x74, 0xA6, 0x74, 0x09, 0x22, 0xE2, 0x74, 0xA3, 0x4C, 0x20, 0x1C, 0x8C, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x9F, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x07, 0x22, 0x62, 0x72, 0x9E, 0x4C, 0x0A, 0x34, 0x20, 0x1C, 0x89, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x9A, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x04, 0x20 ,
+0xE0, 0x71, 0x98, 0x4C, 0x12, 0x34, 0x20, 0x1C, 0x06, 0x99, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x94, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x27, 0x71, 0x93, 0x4C, 0x17, 0x34, 0x20, 0x1C, 0x07, 0x99, 0x3A, 0x1C, 0x01, 0x23, 0x9E, 0x46, 0x8E, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE6, 0x71, 0x01, 0x20, 0x60, 0x72, 0x11, 0x20, 0x20, 0x73, 0x94, 0x20, 0x60, 0x73, 0x02, 0x20, 0xE0, 0x73, 0x25, 0x74, 0x66, 0x74, 0xFF, 0xFF, 0x2C, 0x01, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0xA5, 0x74, 0x2F, 0x27, 0xE7, 0x74, 0x10, 0x20, 0x60, 0x75, 0x80, 0x26, 0xA6, 0x75, 0x01, 0x20, 0xE0, 0x75, 0x11, 0x20, 0xA0, 0x76, 0x94, 0x20, 0xE0, 0x76, 0x24, 0x20, 0x60, 0x77, 0x0A, 0x22, 0xA2, 0x77, 0x80, 0x4C, 0x36, 0x34, 0x20, 0x1C, 0x6D, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x7C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x18, 0x22, 0xA2, 0x72, 0x7A, 0x4C, 0x41, 0x34, 0x20, 0x1C, 0x6B, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x76, 0x4B, 0xFE, 0x44, 0x18, 0x47 ,
+0x25, 0x76, 0x67, 0x76, 0x21, 0x20, 0xE0, 0x76, 0x26, 0x77, 0x01, 0x20, 0x60, 0x77, 0x72, 0x48, 0x61, 0x30, 0x11, 0x21, 0x01, 0x70, 0x94, 0x21, 0x41, 0x70, 0x04, 0x21, 0x01, 0x72, 0xD2, 0x21, 0x41, 0x72, 0xC5, 0x72, 0x1E, 0x21, 0x01, 0x73, 0x45, 0x73, 0x9E, 0x21, 0x81, 0x73, 0x01, 0x21, 0x01, 0x74, 0x46, 0x74, 0x81, 0x74, 0x11, 0x21, 0x41, 0x75, 0x94, 0x21, 0x81, 0x75, 0x04, 0x21, 0x01, 0x76, 0xAD, 0x20, 0x66, 0x49, 0x08, 0x60, 0x00, 0x24, 0x0F, 0x25, 0xFF, 0xFF, 0xC2, 0x01, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x29, 0x06, 0x09, 0x0E, 0x00, 0x20, 0x6A, 0x46, 0x01, 0x23, 0x9E, 0x46, 0x62, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x6B, 0x46, 0x18, 0x88, 0x40, 0x08, 0x0E, 0xD3, 0xA0, 0x00, 0x0F, 0x21, 0xCA, 0x43, 0x69, 0x46, 0x0E, 0x88, 0x16, 0x40, 0x01, 0xAF, 0x3E, 0x52, 0x49, 0x88, 0x11, 0x40, 0x68, 0x44, 0xC1, 0x80, 0x60, 0x1C, 0x04, 0x04, 0x24, 0x0C, 0x01, 0x3D, 0x0B, 0x2D, 0xE0, 0xDA, 0x60, 0x1E ,
+0x00, 0x04, 0x00, 0x0C, 0x1D, 0xD0, 0x86, 0x46, 0x01, 0x1C, 0x01, 0xAD, 0x01, 0x22, 0xAE, 0x88, 0x90, 0x00, 0xC7, 0x5A, 0xB7, 0x42, 0x0A, 0xDA, 0xBC, 0x46, 0x07, 0x1C, 0x6F, 0x44, 0x7F, 0x88, 0x68, 0x44, 0x06, 0x80, 0xEE, 0x88, 0x46, 0x80, 0x60, 0x46, 0xA8, 0x80, 0xEF, 0x80, 0x04, 0x35, 0x50, 0x1C, 0x02, 0x04, 0x12, 0x0C, 0x01, 0x39, 0xE9, 0xD1, 0x70, 0x46, 0x01, 0x38, 0x86, 0x46, 0xE2, 0xD1, 0x99, 0x88, 0x68, 0x46, 0xC0, 0x88, 0x40, 0x18, 0x00, 0x04, 0x00, 0x0C, 0x42, 0x4B, 0x18, 0x80, 0x42, 0x49, 0x08, 0x1A, 0xFF, 0xFF, 0x58, 0x02, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x58, 0x80, 0x02, 0x2C, 0x1E, 0xDB, 0x65, 0x1E, 0x01, 0xAA, 0x01, 0x20, 0x01, 0x1C, 0x8C, 0x00, 0x6B, 0x46, 0xE6, 0x5A, 0x93, 0x88, 0xD4, 0x88, 0xE7, 0x18, 0xB7, 0x42, 0x0C, 0xDA, 0x06, 0x24, 0x44, 0x43, 0x38, 0x4B, 0x1B, 0x19, 0x1F, 0x80, 0x1C, 0x88, 0x34, 0x1B, 0x5C, 0x80, 0x01, 0x24, 0x1C, 0x71, 0x40, 0x1C, 0x00, 0x04 ,
+0x00, 0x0C, 0x04, 0x32, 0x49, 0x1C, 0x09, 0x06, 0x09, 0x0E, 0x01, 0x3D, 0xE4, 0xD1, 0x00, 0x24, 0x31, 0x48, 0x04, 0x70, 0x31, 0x48, 0x04, 0x70, 0x31, 0x48, 0x04, 0x70, 0x31, 0x48, 0x04, 0x70, 0x01, 0x20, 0x86, 0x46, 0x30, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x2F, 0x49, 0x22, 0x1C, 0x08, 0x68, 0x00, 0x28, 0x02, 0xD0, 0x01, 0x20, 0x90, 0x40, 0x04, 0x43, 0x04, 0x31, 0x01, 0x32, 0x20, 0x2A, 0xF5, 0xD3, 0x2A, 0x48, 0x04, 0x60, 0x08, 0xB0, 0xF0, 0xBD, 0x5F, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2D, 0x69, 0x6E, 0x66, 0x6F, 0x00, 0xC0, 0x46, 0xC0, 0x5F, 0x75, 0x64, 0x70, 0x00, 0xC0, 0xFF, 0xFF, 0xEE, 0x02, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x46, 0xC0, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x00, 0xC0, 0x46, 0x5F, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x00, 0xC0, 0x46, 0x5F, 0x64, 0x6E, 0x73, 0x2D, 0x73, 0x64, 0x00, 0x64, 0x65, 0x76, 0x3D, 0x43, 0x43, 0x33, 0x30, 0x30, 0x30, 0x00, 0xC0, 0x76, 0x65 ,
+0x6E, 0x64, 0x6F, 0x72, 0x3D, 0x54, 0x65, 0x78, 0x61, 0x73, 0x2D, 0x49, 0x6E, 0x73, 0x74, 0x72, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x73, 0x00, 0xC0, 0x46, 0xC0, 0x00, 0x00, 0x18, 0x00, 0xF3, 0x7E, 0x03, 0x00, 0xC6, 0x05, 0x00, 0x00, 0xDD, 0x7E, 0x03, 0x00, 0xE4, 0x62, 0x08, 0x00, 0xC9, 0xBA, 0x03, 0x00, 0x09, 0xB4, 0x03, 0x00, 0xA7, 0x64, 0x08, 0x00, 0x70, 0x64, 0x08, 0x00, 0xDD, 0x0A, 0x02, 0x00, 0x48, 0x32, 0x08, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xE8, 0x62, 0x08, 0x00, 0xE9, 0x62, 0x08, 0x00, 0xEA, 0x62, 0x08, 0x00, 0xEB, 0x62, 0x08, 0x00, 0x81, 0x03, 0x18, 0x00, 0x80, 0x7B, 0x08, 0x00, 0x84, 0xF3, 0x1A, 0x00, 0x0D, 0x49, 0x0E, 0x48, 0xFF, 0xFF, 0x84, 0x03, 0x18, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x88, 0x67, 0x0E, 0x48, 0x88, 0x64, 0x0E, 0x48, 0x48, 0x64, 0x0E, 0x48, 0xC8, 0x64, 0x0E, 0x48, 0x08, 0x65, 0x11, 0x48, 0x02, 0x1C, 0x04, 0x32, 0x0C, 0x4B, 0x13, 0x60, 0x0C, 0x4B, 0x93, 0x62, 0x0C, 0x4A ,
+0x8A, 0x66, 0x0D, 0x49, 0x01, 0x60, 0x0D, 0x48, 0x0E, 0x49, 0x01, 0x60, 0x0E, 0x49, 0x41, 0x60, 0xF7, 0x46, 0x1C, 0x21, 0x08, 0x00, 0x1B, 0x7B, 0x08, 0x00, 0x11, 0x7B, 0x08, 0x00, 0x07, 0x7B, 0x08, 0x00, 0x39, 0x7B, 0x08, 0x00, 0x2F, 0x7B, 0x08, 0x00, 0x25, 0x7B, 0x08, 0x00, 0xFD, 0x7A, 0x08, 0x00, 0xDF, 0x7A, 0x08, 0x00, 0x50, 0x23, 0x08, 0x00, 0xD5, 0x7A, 0x08, 0x00, 0x58, 0x26, 0x08, 0x00, 0xF3, 0x7A, 0x08, 0x00, 0xE9, 0x7A, 0x08, 0x00 };
+
+
+const unsigned char cRMdefaultParams[128] = { 0x03, 0x00, 0x01, 0x01, 0x14, 0x14, 0x00, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x23, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x23, 0x23, 0x23, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x01, 0x77, 0x80, 0x1D, 0x1F, 0x22, 0x26, 0x28, 0x29, 0x1A, 0x1F, 0x22, 0x24, 0x26, 0x28, 0x16, 0x1D, 0x1E, 0x20, 0x24, 0x25, 0x1E, 0x2D, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x15, 0x15, 0x15, 0x11, 0x15, 0x15, 0x0E, 0x00};
+
+//
+//Service Pack version P1.13.7.15.15 - FW patches
+//
+const unsigned char fw_patch[5700] = { 0x00, 0x01, 0x00, 0x00, 0x3C, 0x16, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x14, 0x03, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x68, 0x46, 0x25, 0xF0, 0x95, 0xFB, 0xE0, 0x6B, 0xD0, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x25, 0xF0, 0x38, 0xFB, 0x2C, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x25, 0xF0, 0x0A, 0xFB, 0x04, 0x15, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB8, 0xF1, 0x90, 0x0F, 0xA4, 0x16, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x66, 0xE0, 0x04, 0xA8, 0x35, 0x1D, 0x21, 0xF0, 0x99, 0xFC, 0x68, 0x46, 0x23, 0xF0, 0x28, 0xFB, 0x9A, 0xF8, 0x00, 0x00, 0x01, 0x28, 0x07, 0xD1, 0x28, 0x46, 0x05, 0xF0, 0xC3, 0xFE, 0x01, 0x46, 0x01, 0xAA, 0x00, 0x20, 0x21, 0xF0, 0x50, 0xF9, 0x28, 0x46, 0x05, 0xF0, 0xBB, 0xFE, 0x01, 0xA9, 0x21, 0xF0, 0x2A, 0xFA, 0xE9, 0x79, 0x4F, 0xEA, 0xE0, 0x00, 0x40, 0xB2, 0x11, 0xB1, 0x00, 0xF1, 0x06, 0x00, 0x40, 0xB2, 0xA8, 0x71, 0x1F, 0x38, 0x40, 0x00, 0xE8, 0x71, 0x30, 0x46 ,
+0x01, 0xF0, 0x0D, 0xFF, 0x10, 0xF1, 0x00, 0x09, 0x4F, 0xF0, 0x00, 0x01, 0x09, 0xD0, 0x28, 0x68, 0x40, 0x0C, 0x09, 0xD3, 0xE8, 0x68, 0xC0, 0x0B, 0x03, 0xD2, 0x48, 0x46, 0xFF, 0xF7, 0xDD, 0xFE, 0x01, 0x21, 0x28, 0x68, 0x40, 0x0C, 0x0A, 0xD2, 0x38, 0x68, 0x40, 0x1C, 0x38, 0x60, 0x20, 0x68, 0x6F, 0xF3, 0x0F, 0x00, 0x20, 0x60, 0x22, 0x68, 0x38, 0x68, 0x10, 0x43, 0x20, 0x60, 0xE8, 0x68, 0xC0, 0x0B, 0x0F, 0xD3, 0xD8, 0xF8, 0x00, 0x00, 0x00, 0xF1, 0x01, 0x00, 0xC8, 0xF8, 0x00, 0x00, 0x20, 0x68, 0x6F, 0xF3, 0x1F, 0x40, 0x20, 0x60, 0xD8, 0xF8, 0x00, 0x20, 0x20, 0x68, 0x40, 0xEA, 0x02, 0x40, 0x20, 0x60, 0x49, 0xB9, 0xB9, 0xF1, 0x00, 0x0F, 0x03, 0xD1, 0x30, 0x46, 0x07, 0xF0, 0xBE, 0xF9, 0x02, 0xE0, 0x48, 0x46, 0x07, 0xF0, 0x06, 0xFA, 0x6C, 0x17, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x68, 0x46, 0x0E, 0xF0, 0x85, 0xFB, 0x00, 0x9E, 0x00, 0x2E, 0x96, 0xD1, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xC0, 0x46 ,
+0x9C, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x23, 0xF0, 0x2A, 0xFE, 0x74, 0x47, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x21, 0x21, 0xF0, 0x41, 0xFA, 0x20, 0x68, 0x18, 0x4B, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x21, 0xF0, 0x1C, 0xF9, 0x0A, 0xE0, 0x20, 0x68, 0x00, 0x68, 0x0C, 0x21, 0x40, 0xF0, 0x20, 0x00, 0x21, 0xF0, 0x14, 0xF9, 0x10, 0x57, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0xA8, 0x20, 0xF0, 0x97, 0xF9, 0x01, 0x98, 0x5C, 0x57, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x20, 0xF0, 0x71, 0xF9, 0x03, 0x98, 0x00, 0x58, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0xF0, 0x20, 0xF9, 0x1C, 0x58, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0xF0, 0x12, 0xF9, 0x54, 0x58, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0xA8, 0x20, 0xF0, 0xF5, 0xF8, 0x04, 0xAB, 0x04, 0x62, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x79, 0x1F, 0xF0, 0x1B, 0xFD, 0x69, 0xE0, 0x60, 0x93, 0x00, 0x00, 0x40, 0x00 ,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xA6, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1B, 0xF0, 0x39, 0xFB, 0x28, 0x46, 0x90, 0xA8, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1B, 0xF0, 0x69, 0xF9, 0x1E, 0x48, 0x34, 0xAD, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x68, 0xFF, 0x29, 0x98, 0xAD, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0xD4, 0x21, 0xD4, 0xB2, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0xD0, 0x1A, 0xF0, 0x47, 0xFC, 0x20, 0x98, 0xAC, 0xC5, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x78, 0x19, 0xF0 ,
+0xDB, 0xFA, 0x09, 0x49, 0x28, 0xC6, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x19, 0xF0, 0x9E, 0xFA, 0xDC, 0xD3, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xB5, 0x18, 0xF0, 0xAB, 0xFC, 0x00, 0xF0, 0x03, 0xF8, 0x00, 0xBD, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xDF, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x17, 0xF0, 0xA8, 0xFD, 0xCC, 0xEB, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x38, 0x78, 0x17, 0xF0, 0x77, 0xF8, 0x38, 0x78, 0x16, 0xF0, 0xF0, 0xFF, 0xA8, 0xF7, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0E, 0x49, 0x09, 0x68, 0x23, 0x22, 0x41, 0x61, 0xC8, 0xF7, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x31, 0x2E, 0x31, 0x39, 0x2E, 0x33, 0x31, 0x34, 0x5F, 0x4E, 0x65, 0x77, 0x5F, 0x43, 0x43, 0x41, 0x5F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x00, 0xC0, 0x74, 0x56, 0x30, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xF9, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x16, 0xF0, 0x79, 0xF8 ,
+0x12, 0xE0, 0x38, 0xFA, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0xA8, 0x16, 0xF0, 0x03, 0xF8, 0x32, 0x20, 0x94, 0xFB, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x0C, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x14, 0xF0, 0x05, 0xFF, 0x01, 0xF0, 0x10, 0x1B, 0x01, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x1E, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x13, 0xF0, 0x46, 0xBF, 0x18, 0x30, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x30, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x12, 0xF0, 0xD8, 0xFC, 0x9C, 0x31, 0x01, 0x00, 0x08, 0x00 ,
+0x00, 0x00, 0x68, 0x46, 0x12, 0xF0, 0x51, 0xFC, 0xFE, 0xF7, 0xF0, 0x35, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x68, 0x46, 0x12, 0xF0, 0x27, 0xFA, 0xFE, 0xF7, 0xF0, 0x3D, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0xA9, 0x11, 0xF0, 0x27, 0xFE, 0x20, 0x6F, 0xD0, 0x62, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0xB8, 0xFB, 0x80, 0x7E, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0xDF, 0xF8, 0x58, 0x82, 0xE0, 0x7E, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0D, 0xF0, 0x6A, 0xFE, 0x0B, 0xF0, 0x9A, 0xF9, 0x03, 0x20, 0xA8, 0xF5, 0x88, 0x71, 0x08, 0x60, 0xF2, 0xF7, 0x16, 0xF9, 0x7A, 0x48, 0x6B, 0x49, 0x9C, 0x7F, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x70, 0x51, 0x4D, 0xC4, 0x7F, 0x01, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x40, 0x49, 0x00, 0xF1, 0x52, 0x00, 0x3A, 0x4A, 0xA8, 0x81, 0x28, 0x83, 0xE8, 0x83, 0xE8, 0x84, 0xA8, 0x85, 0x2A, 0x60, 0x39, 0x48, 0x41, 0xF2, 0x11, 0x12, 0x2A, 0x85, 0x18, 0x90, 0x19, 0x91 ,
+0x39, 0x49, 0x1A, 0x91, 0x39, 0x49, 0x1B, 0x91, 0x39, 0x49, 0x20, 0x46, 0xDF, 0xF8, 0xC4, 0x90, 0x1C, 0x91, 0x38, 0x49, 0xDF, 0xF8, 0xC0, 0xB0, 0x31, 0x4E, 0x1D, 0x91, 0x48, 0x80, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0D, 0xF0, 0x7C, 0xFA, 0xB4, 0x80, 0x01, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x12, 0x66, 0x09, 0x84, 0x6B, 0x00, 0x20, 0x94, 0x70, 0x00, 0x20, 0xB4, 0x70, 0x00, 0x20, 0xC4, 0x78, 0x00, 0x20, 0x50, 0x7A, 0x00, 0x20, 0xFE, 0xFF, 0x03, 0x00, 0xA4, 0x70, 0x00, 0x20, 0xB0, 0x70, 0x00, 0x20, 0xB8, 0x70, 0x00, 0x20, 0x60, 0x55, 0x30, 0x80, 0x3C, 0x5C, 0x00, 0x20, 0x04, 0x74, 0x00, 0x20, 0xB8, 0xE4, 0x01, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x78, 0x07, 0xF0, 0x01, 0xFC, 0x20, 0x78, 0x07, 0xF0, 0x7A, 0xFB, 0x04, 0x4D, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xAD, 0xF1, 0x8C, 0x0D, 0x04, 0x68, 0x0F, 0x30, 0x03, 0x94, 0xFE, 0xF7, 0xDB, 0xFA, 0x04, 0xF1, 0x14, 0x00 ,
+0x04, 0x90, 0x21, 0x7D, 0x00, 0x20, 0x21, 0xF0, 0x73, 0x01, 0x88, 0x29, 0x08, 0xBF, 0x01, 0x20, 0x05, 0x90, 0x03, 0x98, 0x00, 0x1D, 0x06, 0x90, 0x5D, 0x48, 0x00, 0x68, 0x01, 0x28, 0x40, 0xF0, 0xFA, 0x83, 0x5B, 0x4D, 0x5C, 0x48, 0xDF, 0xF8, 0x70, 0x91, 0x29, 0x68, 0xDF, 0xF8, 0x70, 0x81, 0xDF, 0xF8, 0x74, 0xA1, 0x88, 0x42, 0x21, 0xD1, 0x10, 0x22, 0x00, 0x21, 0x48, 0x46, 0x4F, 0x46, 0xFB, 0xF7, 0xB7, 0xFE, 0x10, 0x22, 0x00, 0x21, 0x40, 0x46, 0xFB, 0xF7, 0xB2, 0xFE, 0x54, 0x49, 0x08, 0x68, 0x40, 0xF4, 0x80, 0x10, 0x08, 0x60, 0x01, 0x20, 0x51, 0x46, 0x08, 0x60, 0x00, 0x21, 0x29, 0x60, 0x39, 0x78, 0x46, 0x46, 0x00, 0x91, 0x31, 0x78, 0x41, 0xF2, 0x11, 0x13, 0x04, 0x22, 0x01, 0x91, 0x07, 0x21, 0x02, 0x90, 0x03, 0x20, 0xF3, 0xF7, 0x41, 0xFC, 0x51, 0x46, 0x07, 0x91, 0x08, 0x68, 0x56, 0x49, 0xDF, 0xF8, 0x5C, 0xB1, 0x01, 0x28, 0x08, 0x91, 0x56, 0x49, 0xDF, 0xF8, 0x48, 0xA1, 0x09, 0x91, 0x55, 0x49 ,
+0x0A, 0x91, 0x44, 0x49, 0x0B, 0x91, 0x44, 0x49, 0x0C, 0x91, 0x44, 0x49, 0x0D, 0x91, 0x44, 0x49, 0x0E, 0x91, 0x44, 0x49, 0x0F, 0x91, 0x44, 0x49, 0x10, 0x91, 0x44, 0x49, 0xCC, 0x4D, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x11, 0x91, 0x44, 0x49, 0x12, 0x91, 0x44, 0x49, 0x13, 0x91, 0x44, 0x49, 0x14, 0x91, 0x44, 0x49, 0x15, 0x91, 0x44, 0x49, 0x16, 0x91, 0x9F, 0x49, 0x17, 0x91, 0x9F, 0x49, 0x18, 0x91, 0x9F, 0x49, 0x19, 0x91, 0x9F, 0x49, 0x1A, 0x91, 0x9F, 0x49, 0x1B, 0x91, 0x9F, 0x49, 0x1C, 0x91, 0x9F, 0x49, 0x1D, 0x91, 0x9F, 0x49, 0x1E, 0x91, 0x9F, 0x49, 0x1F, 0x91, 0x40, 0xF0, 0x00, 0x81, 0x04, 0x98, 0x40, 0x78, 0x00, 0xF0, 0x03, 0x01, 0x01, 0x29, 0x40, 0xF0, 0xF9, 0x80, 0x04, 0x99, 0x09, 0x78, 0x01, 0xF0, 0x0C, 0x01, 0x08, 0x29, 0x40, 0xF0, 0xF2, 0x80, 0x06, 0x99, 0x09, 0x88, 0xA1, 0xF1, 0x3C, 0x01, 0x0E, 0xB2, 0x05, 0x99, 0x11, 0xB1, 0xA6, 0xF1, 0x02, 0x06, 0x36, 0xB2, 0xC0, 0x09, 0x4F, 0xF0 ,
+0x00, 0x07, 0x15, 0xD3, 0x08, 0x3E, 0x36, 0xB2, 0x03, 0x2E, 0x10, 0xD0, 0x17, 0x2E, 0x0E, 0xD0, 0x08, 0x3E, 0x36, 0xB2, 0x03, 0x2E, 0x08, 0xD0, 0x17, 0x2E, 0x06, 0xD0, 0x36, 0x1F, 0x36, 0xB2, 0x03, 0x2E, 0x14, 0xBF, 0x17, 0x2E, 0x02, 0x27, 0x02, 0xE0, 0x03, 0x27, 0x00, 0xE0, 0x01, 0x27, 0x03, 0x2E, 0x18, 0xBF, 0x17, 0x2E, 0x04, 0x9A, 0x40, 0xF0, 0xC8, 0x80, 0x0A, 0x32, 0x12, 0xF8, 0x01, 0x1B, 0x05, 0x24, 0x12, 0xF8, 0x01, 0x3B, 0x4B, 0x40, 0x64, 0x1E, 0xD9, 0xB2, 0xF9, 0xD1, 0x81, 0xEA, 0x21, 0x11, 0x03, 0x2E, 0x94, 0x4E, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x0F, 0x01, 0x48, 0x46, 0x35, 0xD0, 0x43, 0x46, 0xCA, 0x5C, 0x52, 0x1C, 0xCA, 0x54, 0x0C, 0x18, 0x33, 0xE0, 0x50, 0x57, 0x02, 0x00, 0x04, 0x74, 0x00, 0x20, 0x34, 0x12, 0x66, 0x09, 0x60, 0x57, 0x02, 0x00, 0x70, 0x57, 0x02, 0x00, 0xC8, 0x48, 0x30, 0x80, 0x4C, 0x57, 0x02, 0x00, 0x88, 0x57, 0x02, 0x00, 0x80, 0x57, 0x02, 0x00 ,
+0x18, 0x58, 0x02, 0x00, 0x20, 0x58, 0x02, 0x00, 0x28, 0x58, 0x02, 0x00, 0x30, 0x58, 0x02, 0x00, 0x38, 0x58, 0x02, 0x00, 0x40, 0x58, 0x02, 0x00, 0xE4, 0x58, 0x02, 0x00, 0xE2, 0x58, 0x02, 0x00, 0x14, 0x58, 0x02, 0x00, 0xEF, 0x58, 0x02, 0x00, 0xE0, 0x58, 0x02, 0x00, 0xEE, 0x58, 0x02, 0x00, 0x5C, 0x57, 0x02, 0x00, 0xE6, 0x58, 0x02, 0x00, 0xE8, 0x58, 0x02, 0x00, 0x0C, 0x18, 0x20, 0x78, 0x40, 0x1C, 0x20, 0x70, 0x20, 0x78, 0x43, 0x46, 0x03, 0xEB, 0x01, 0x08, 0x0A, 0x28, 0x76, 0xDB, 0x98, 0xF8, 0x00, 0x00, 0x0A, 0x28, 0x72, 0xDB, 0x94, 0x48, 0x00, 0x25, 0x01, 0x60, 0x04, 0x98, 0x00, 0xF1, 0x0A, 0x09, 0x40, 0x78, 0x41, 0x08, 0x24, 0xBF, 0x04, 0x99, 0x09, 0x1D, 0x04, 0xD2, 0x80, 0x08, 0x2E, 0xBF, 0x49, 0x46, 0x04, 0x99, 0x10, 0x31, 0x0B, 0x98, 0x06, 0x22, 0xFA, 0xF7, 0xB9, 0xFC, 0x0C, 0x98, 0x06, 0x22, 0x49, 0x46, 0xFA, 0xF7, 0xB4, 0xFC, 0x9B, 0x48, 0x9A, 0x49, 0x5C, 0x4F, 0x02, 0x00, 0xC8, 0x00 ,
+0x00, 0x00, 0x00, 0x78, 0x08, 0x22, 0x08, 0x60, 0x58, 0x46, 0x07, 0x60, 0x0D, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xAF, 0xFD, 0x08, 0x22, 0x0E, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xAA, 0xFD, 0x08, 0x22, 0x0F, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xA5, 0xFD, 0x08, 0x22, 0x10, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xA0, 0xFD, 0x08, 0x22, 0x11, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0x9B, 0xFD, 0x08, 0x22, 0x12, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0x96, 0xFD, 0x07, 0x99, 0x02, 0x20, 0x08, 0x60, 0x13, 0x99, 0x28, 0x46, 0x08, 0x80, 0x08, 0x99, 0x08, 0x70, 0x14, 0x99, 0x08, 0x70, 0x15, 0x99, 0x08, 0x60, 0x16, 0x99, 0x08, 0x70, 0x17, 0x99, 0x08, 0x60, 0x18, 0x99, 0x08, 0x60, 0x19, 0x99, 0x08, 0x60, 0x09, 0x99, 0x08, 0x80, 0x0A, 0x99, 0x08, 0x80, 0x1A, 0x99, 0x08, 0x80, 0x7D, 0x49, 0x0D, 0x60, 0x1B, 0x99, 0x08, 0x70, 0x1C, 0x99, 0x08, 0x70, 0x1D, 0x99, 0x08, 0x70, 0x1E, 0x99, 0x08, 0x80, 0x1F, 0x99, 0x08, 0x80, 0x51, 0x46, 0x08, 0x80 ,
+0x20, 0x78, 0x00, 0x96, 0x04, 0x22, 0x01, 0x90, 0x98, 0xF8, 0x00, 0x00, 0x41, 0xF2, 0x14, 0x13, 0x07, 0x21, 0x02, 0x90, 0x03, 0x20, 0xF3, 0xF7, 0x07, 0xFB, 0x07, 0x98, 0xA2, 0x49, 0x00, 0x68, 0x20, 0x91, 0xA2, 0x49, 0x05, 0x28, 0x21, 0x91, 0x9E, 0x49, 0x22, 0x91, 0x40, 0xF0, 0x37, 0x82, 0x04, 0x98, 0x40, 0x78, 0x24, 0x50, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x41, 0x08, 0x24, 0xBF, 0x04, 0x99, 0x09, 0x1D, 0x05, 0xD2, 0x80, 0x08, 0x27, 0xBF, 0x04, 0x99, 0x0A, 0x31, 0x04, 0x99, 0x10, 0x31, 0x0B, 0x98, 0xF8, 0xF7, 0x2D, 0xFC, 0x01, 0x28, 0x04, 0x98, 0x40, 0xF0, 0x23, 0x82, 0x40, 0x78, 0x00, 0xF0, 0x03, 0x00, 0x03, 0x28, 0x18, 0xD0, 0x02, 0x28, 0x07, 0xBF, 0x04, 0x99, 0x10, 0x31, 0x04, 0x99, 0x0A, 0x31, 0x13, 0xE0, 0x48, 0x58, 0x02, 0x00, 0x4C, 0x58, 0x02, 0x00, 0x50, 0x58, 0x02, 0x00, 0xF0, 0x58, 0x02, 0x00, 0xF2, 0x58, 0x02, 0x00, 0xF3, 0x58, 0x02, 0x00, 0xF4, 0x58, 0x02, 0x00, 0xEA, 0x58 ,
+0x02, 0x00, 0xEC, 0x58, 0x02, 0x00, 0x04, 0x99, 0x18, 0x31, 0x0C, 0x98, 0xF8, 0xF7, 0x06, 0xFC, 0x04, 0x99, 0x01, 0x28, 0x40, 0xF0, 0xFC, 0x81, 0x49, 0x78, 0x01, 0xF0, 0x03, 0x01, 0x01, 0x29, 0x40, 0xF0, 0xF6, 0x81, 0x59, 0x46, 0x09, 0x68, 0x04, 0x9A, 0x8E, 0x46, 0x51, 0x46, 0xD2, 0x8A, 0x0B, 0x88, 0x12, 0x11, 0x93, 0x42, 0x00, 0xF0, 0x37, 0x82, 0x0A, 0x80, 0x06, 0x99, 0x09, 0x88, 0x3C, 0x39, 0x0B, 0xB2, 0x71, 0x46, 0x49, 0x1E, 0x09, 0xD0, 0x49, 0x1E, 0x04, 0xD0, 0x49, 0x1E, 0x08, 0xD1, 0xA3, 0xF1, 0x10, 0x03, 0x04, 0xE0, 0xA3, 0xF1, 0x14, 0x03, 0x01, 0xE0, 0xA3, 0xF1, 0x08, 0x03, 0x1B, 0xB2, 0x05, 0x98, 0x10, 0xB1, 0xA3, 0xF1, 0x02, 0x03, 0x1B, 0xB2, 0xEC, 0x50, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0xF1, 0xCE, 0x81, 0x16, 0x98, 0x40, 0xF2, 0x77, 0x51, 0x99, 0x42, 0x0B, 0x90, 0x14, 0x98, 0x05, 0x90, 0x00, 0xF0, 0xA3, 0x81, 0x08, 0x46, 0x00, 0xF1, 0x3C, 0x00, 0x98, 0x42 ,
+0x05, 0x9A, 0x00, 0xF0, 0x9A, 0x81, 0xDF, 0xF8, 0x48, 0x82, 0x14, 0x78, 0x0B, 0x9A, 0xBB, 0x2C, 0x12, 0x78, 0x0C, 0x92, 0x63, 0xD1, 0xDD, 0xF8, 0x68, 0xC0, 0xBC, 0xF9, 0x00, 0x20, 0x91, 0x42, 0x18, 0xBF, 0x90, 0x42, 0x5B, 0xD1, 0x1C, 0x2B, 0x4F, 0xF0, 0x00, 0x00, 0xC0, 0xF2, 0x82, 0x81, 0x3D, 0x2B, 0x13, 0x9D, 0x80, 0xF2, 0x7E, 0x81, 0xA3, 0xF1, 0x1C, 0x01, 0x09, 0xB2, 0x29, 0x80, 0x1E, 0x9A, 0xDD, 0xF8, 0x30, 0x90, 0xB2, 0xF9, 0x00, 0x60, 0xB9, 0xF1, 0x01, 0x0F, 0x15, 0xD1, 0xDD, 0xF8, 0x24, 0x90, 0x03, 0x2E, 0x0D, 0xDA, 0xB9, 0xF9, 0x00, 0x70, 0xB9, 0x42, 0x07, 0xD0, 0x01, 0x26, 0x16, 0x80, 0x4A, 0x46, 0x0E, 0x46, 0x03, 0xE0, 0xC0, 0x46, 0x90, 0x57, 0x02, 0x00, 0x76, 0x1C, 0x16, 0x80, 0x1B, 0x9A, 0x16, 0x78, 0x1D, 0x9A, 0x16, 0x70, 0x0C, 0x9A, 0x1F, 0x9E, 0x02, 0x2A, 0x28, 0xD1, 0xB6, 0xF9, 0x00, 0x20, 0xBE, 0xF1, 0x00, 0x0F, 0x1A, 0xD0, 0x03, 0x2A, 0x35, 0x46, 0x0B, 0xDA, 0x0A, 0x9E ,
+0xB6, 0xF9, 0x00, 0x70, 0xB9, 0x42, 0x04, 0xD0, 0x01, 0x22, 0x2A, 0x80, 0x0A, 0x46, 0x35, 0x46, 0x00, 0xE0, 0xB4, 0x51, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x52, 0x1C, 0x2A, 0x80, 0x1C, 0x99, 0x0A, 0x78, 0x1D, 0x99, 0x0A, 0x70, 0x0F, 0xE0, 0xC0, 0x46, 0x58, 0x57, 0x02, 0x00, 0xA6, 0x64, 0x00, 0x20, 0x54, 0x57, 0x02, 0x00, 0x28, 0x80, 0x05, 0x99, 0x08, 0x70, 0x08, 0x9A, 0x11, 0x78, 0x41, 0xF0, 0x04, 0x01, 0x11, 0x70, 0x04, 0x46, 0x45, 0x46, 0xAC, 0xF8, 0x00, 0x00, 0x28, 0x70, 0xCC, 0x2C, 0x09, 0x9A, 0x40, 0xF0, 0x00, 0x81, 0xDD, 0xF8, 0x7C, 0xC0, 0x0A, 0x99, 0x1E, 0x9F, 0x45, 0x46, 0xB1, 0xF9, 0x00, 0x60, 0xB2, 0xF9, 0x00, 0x90, 0x28, 0x78, 0xCD, 0xF8, 0x50, 0xC0, 0x16, 0x91, 0x0A, 0x97, 0x13, 0x92, 0x09, 0x95, 0x0C, 0x99, 0x01, 0x29, 0x05, 0xD1, 0x05, 0x9A, 0xB0, 0xEB, 0x49, 0x0F, 0x01, 0xD1, 0x00, 0x21, 0x11, 0x70, 0x0C, 0x99, 0x02, 0x29, 0x05, 0xD1, 0x05, 0x9A, 0xB0, 0xEB, 0x46, 0x0F ,
+0x01, 0xD1, 0x00, 0x21, 0x11, 0x70, 0xB3, 0xF5, 0x14, 0x7F, 0x40, 0xF3, 0xBA, 0x80, 0x40, 0xF2, 0x51, 0x31, 0x99, 0x42, 0x08, 0x99, 0x40, 0xF3, 0xB4, 0x80, 0x09, 0x78, 0x06, 0x29, 0x00, 0xF0, 0xB0, 0x80, 0xA3, 0xF2, 0x51, 0x21, 0x0B, 0xB2, 0x4F, 0xEA, 0xE3, 0x01, 0x03, 0xEB, 0x11, 0x71, 0x4F, 0xEA, 0x21, 0x11, 0xCA, 0xB2, 0x4F, 0xEA, 0xE3, 0x01, 0x03, 0xEB, 0x11, 0x71, 0x15, 0x9D, 0x21, 0xF0, 0x0F, 0x01, 0xA3, 0xEB, 0x01, 0x03, 0x1D, 0x99, 0x2E, 0x68, 0x7C, 0x52, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x91, 0xF8, 0x00, 0xE0, 0x5F, 0xFA, 0x83, 0xF8, 0x60, 0xB1, 0x31, 0x18, 0x11, 0xF8, 0x01, 0x1C, 0x51, 0x40, 0xCB, 0xB2, 0x07, 0xE0, 0xC0, 0x46, 0x58, 0x58, 0x02, 0x00, 0x54, 0x58, 0x02, 0x00, 0xDC, 0x58, 0x02, 0x00, 0x13, 0x46, 0x19, 0x99, 0xDD, 0xF8, 0x6C, 0xA0, 0xDD, 0xF8, 0x70, 0xB0, 0xD1, 0xF8, 0x00, 0xC0, 0x00, 0xF0, 0x0F, 0x01, 0x99, 0x42, 0x22, 0xD0, 0x0A, 0x9B, 0x86, 0x45, 0x9A, 0xF8 ,
+0x00, 0x10, 0xB3, 0xF9, 0x00, 0x30, 0x9B, 0xF8, 0x00, 0x50, 0x15, 0xDD, 0x37, 0x5C, 0x44, 0x1C, 0x82, 0xEA, 0x07, 0x0C, 0x04, 0xF0, 0x0F, 0x07, 0x67, 0x45, 0x0B, 0xD0, 0xA6, 0x45, 0x06, 0x44, 0x0A, 0xDD, 0x76, 0x78, 0x72, 0x40, 0x86, 0x1C, 0x06, 0xF0, 0x0F, 0x06, 0x96, 0x42, 0x03, 0xD1, 0xC0, 0x1C, 0x4D, 0xE0, 0x80, 0x1C, 0x4B, 0xE0, 0x05, 0x9E, 0x00, 0x22, 0x32, 0x70, 0x4A, 0xE0, 0x00, 0xF0, 0x1F, 0x01, 0x01, 0x22, 0x8A, 0x40, 0x17, 0x99, 0xC4, 0x10, 0x0B, 0x68, 0x24, 0xF0, 0x03, 0x01, 0x5C, 0xF8, 0x01, 0x70, 0x3A, 0x42, 0x32, 0xD1, 0x5F, 0x58, 0x3A, 0x42, 0x06, 0x44, 0x1F, 0xD0, 0x18, 0x9B, 0x37, 0x78, 0x1B, 0x68, 0xB8, 0x45, 0x04, 0xD1, 0x58, 0x58, 0x02, 0x42, 0x19, 0xD0, 0x63, 0x46, 0x15, 0xE0, 0xA1, 0x10, 0x8C, 0x00, 0x19, 0x59, 0x91, 0x43, 0x19, 0x51, 0x00, 0x90, 0x30, 0x78, 0x01, 0x90, 0x44, 0x53, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x03, 0x20, 0x06, 0x21, 0x02, 0x46, 0x4D, 0xF6 ,
+0x80, 0x53, 0xF3, 0xF7, 0x63, 0xF9, 0x09, 0x99, 0x28, 0x68, 0x0E, 0x78, 0x36, 0x18, 0x06, 0xE0, 0xE3, 0x58, 0x02, 0x00, 0xA0, 0x10, 0x81, 0x00, 0x58, 0x58, 0x02, 0x43, 0x5A, 0x50, 0x86, 0xF8, 0x00, 0x80, 0x0B, 0x98, 0x00, 0x78, 0x0C, 0x90, 0x13, 0x98, 0xB0, 0xF9, 0x00, 0x90, 0x09, 0x98, 0x00, 0x78, 0x0A, 0x9A, 0x40, 0x1C, 0x9B, 0xF8, 0x00, 0x50, 0x9A, 0xF8, 0x00, 0x10, 0xB2, 0xF9, 0x00, 0x30, 0x09, 0x9A, 0xC0, 0xB2, 0x10, 0x70, 0x0C, 0x9A, 0x01, 0x2A, 0x03, 0xD1, 0x88, 0x42, 0xC8, 0xBF, 0x8A, 0xF8, 0x00, 0x00, 0x0C, 0x99, 0x02, 0x29, 0x07, 0xD1, 0xA8, 0x42, 0xC8, 0xBF, 0x8B, 0xF8, 0x00, 0x00, 0x02, 0xE0, 0x0A, 0x98, 0xB0, 0xF9, 0x00, 0x30, 0xB9, 0xF1, 0x00, 0x0F, 0x06, 0xDD, 0x03, 0x2B, 0x04, 0xD1, 0x11, 0x98, 0x01, 0x22, 0x49, 0x46, 0x00, 0xF0, 0x72, 0xFB, 0x16, 0x98, 0xB0, 0xF9, 0x00, 0x10, 0x14, 0x98, 0x00, 0x29, 0xB0, 0xF9, 0x00, 0x00, 0x05, 0xDD, 0x03, 0x28, 0x03, 0xD1, 0x12, 0x98 ,
+0x02, 0x22, 0x00, 0xF0, 0x64, 0xFB, 0x05, 0x98, 0x04, 0x78, 0x0B, 0x98, 0x00, 0x78, 0x0C, 0x90, 0x08, 0x98, 0xBB, 0x2C, 0x01, 0x78, 0x02, 0xD0, 0xAA, 0x2C, 0x2F, 0xD0, 0x31, 0xE0, 0x0C, 0x98, 0x01, 0x28, 0x0B, 0xD1, 0x0D, 0x98, 0x17, 0x9A, 0x10, 0x60, 0x0C, 0x54, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x0F, 0x98, 0x18, 0x9A, 0x10, 0x60, 0x19, 0x9A, 0x11, 0x98, 0x10, 0x60, 0x47, 0x4A, 0x15, 0x98, 0x02, 0x60, 0x0C, 0x98, 0x02, 0x28, 0x0B, 0xD1, 0x0E, 0x98, 0x17, 0x9A, 0x10, 0x60, 0x10, 0x98, 0x18, 0x9A, 0x10, 0x60, 0x19, 0x9A, 0x12, 0x98, 0x10, 0x60, 0x41, 0x4A, 0x15, 0x98, 0x02, 0x60, 0xCC, 0x20, 0x0F, 0xE0, 0x08, 0x99, 0x09, 0x78, 0x0C, 0xE0, 0x02, 0x20, 0x00, 0xE0, 0x01, 0x20, 0x0B, 0x99, 0x08, 0x70, 0x1A, 0x99, 0x0B, 0x80, 0x13, 0x99, 0x00, 0x20, 0x08, 0x80, 0x08, 0x98, 0x01, 0x78, 0xBB, 0x20, 0x05, 0x9A, 0x10, 0x70, 0x06, 0x29, 0x07, 0x99, 0x11, 0xD1, 0x06, 0x20, 0x08, 0x60, 0x20, 0x98 ,
+0x00, 0x25, 0x05, 0x70, 0x21, 0x98, 0x29, 0x46, 0x04, 0x22, 0xFB, 0xF7, 0x27, 0xFB, 0x01, 0x20, 0x00, 0xF0, 0x3A, 0xFA, 0x02, 0x20, 0x00, 0xF0, 0x37, 0xFA, 0x22, 0x98, 0x05, 0x60, 0x07, 0x98, 0x04, 0x99, 0x00, 0x68, 0x07, 0x28, 0x44, 0xD1, 0x09, 0x78, 0x03, 0x9C, 0x80, 0x29, 0x40, 0xD1, 0x38, 0x34, 0x21, 0x78, 0x64, 0x1C, 0x22, 0x46, 0x00, 0x29, 0x3A, 0xD1, 0x20, 0x98, 0x90, 0xF8, 0x00, 0xA0, 0x22, 0x98, 0x05, 0x90, 0xD0, 0xF8, 0x00, 0x90, 0x51, 0x46, 0x48, 0x46, 0xFD, 0xF7, 0x79, 0xF9, 0x5F, 0xFA, 0x80, 0xF8, 0x21, 0x9F, 0x15, 0x78, 0x51, 0x46, 0x48, 0x46, 0x17, 0xF8, 0x08, 0x30, 0xFD, 0xF7, 0xD4, 0x54, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x6F, 0xF9, 0x1E, 0x46, 0x1B, 0x1D, 0xC0, 0xB2, 0x38, 0x5C, 0x00, 0x1D, 0xA8, 0x42, 0x28, 0x46, 0x07, 0xDD, 0x80, 0x18, 0x82, 0x1C, 0x10, 0x78, 0x2D, 0x18, 0xAD, 0x1C, 0xAD, 0xB2, 0xAB, 0x42, 0xF7, 0xDC, 0x04, 0xF8, 0x01, 0x6B, 0x11, 0x49, 0x32, 0x46 ,
+0x20, 0x46, 0x01, 0xEB, 0x48, 0x11, 0xFA, 0xF7, 0xDC, 0xF9, 0xAD, 0x1B, 0xFF, 0x20, 0x34, 0x19, 0xAD, 0x1E, 0x04, 0xF8, 0x01, 0x0B, 0x25, 0x70, 0x05, 0x98, 0x01, 0x68, 0x49, 0x1C, 0x01, 0x60, 0x07, 0x98, 0x00, 0x68, 0x07, 0x28, 0x04, 0xD0, 0x06, 0x99, 0x08, 0x68, 0x20, 0xF4, 0x80, 0x30, 0x08, 0x60, 0x23, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xC0, 0x46, 0x94, 0x57, 0x02, 0x00, 0xD4, 0x57, 0x02, 0x00, 0x5C, 0x58, 0x02, 0x00, 0x6E, 0x48, 0x2D, 0xE9, 0xF0, 0x47, 0x6E, 0x4D, 0x82, 0x89, 0x4A, 0xF6, 0x55, 0x21, 0xAD, 0xF5, 0xFE, 0x7D, 0x91, 0x42, 0x4F, 0xF0, 0x00, 0x01, 0xAD, 0xF1, 0x38, 0x0D, 0x12, 0xD1, 0x29, 0x60, 0x68, 0x4A, 0x11, 0x70, 0x41, 0xF2, 0x10, 0x41, 0x81, 0x81, 0x4F, 0xF6, 0xFF, 0x70, 0x66, 0x49, 0x08, 0x60, 0x28, 0x68, 0x00, 0x90, 0x02, 0x22, 0x05, 0x21, 0x03, 0x20, 0x41, 0xF2, 0x34, 0x23, 0xF3, 0xF7, 0x48, 0xF8, 0x29, 0x68, 0x61, 0x4C, 0x01, 0x29, 0x20, 0x68, 0x40, 0xF0, 0xAF, 0x80 ,
+0x5F, 0x4D, 0x02, 0x28, 0x29, 0x68, 0x23, 0xD1, 0x9C, 0x55, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x5E, 0x48, 0x00, 0x68, 0x5F, 0x4A, 0x12, 0x5C, 0x00, 0x92, 0x01, 0x91, 0x5E, 0x49, 0x09, 0x68, 0x02, 0x91, 0x5B, 0x49, 0x0B, 0x5C, 0x03, 0x20, 0x07, 0x21, 0x04, 0x22, 0xF3, 0xF7, 0x2E, 0xF8, 0x5B, 0x49, 0x4A, 0x79, 0x59, 0x48, 0x00, 0x92, 0x02, 0x79, 0x01, 0x92, 0x40, 0x79, 0x04, 0x22, 0x02, 0x90, 0x03, 0x20, 0x0B, 0x79, 0x07, 0x21, 0xF3, 0xF7, 0x20, 0xF8, 0x03, 0x20, 0x20, 0x60, 0xEC, 0xF7, 0x1A, 0xFF, 0x20, 0x68, 0x29, 0x68, 0x04, 0x28, 0x15, 0xD1, 0x0D, 0x20, 0x8D, 0xF8, 0x10, 0x00, 0x00, 0x25, 0x8D, 0xF8, 0x14, 0x50, 0x8D, 0xF8, 0x15, 0x10, 0x28, 0x46, 0x63, 0x21, 0x00, 0xF0, 0xAA, 0xFB, 0x63, 0x21, 0x28, 0x46, 0x00, 0xF0, 0xFA, 0xFA, 0x03, 0xA9, 0x04, 0xA8, 0xE0, 0xF7, 0xCA, 0xFC, 0x05, 0x20, 0x20, 0x60, 0x46, 0x4D, 0x05, 0x28, 0x29, 0x68, 0x01, 0xF1, 0x01, 0x01, 0x29, 0x60, 0x1D, 0xD1 ,
+0x44, 0x4A, 0x8A, 0x42, 0x1A, 0xD1, 0x43, 0x48, 0x01, 0x68, 0x00, 0x91, 0x40, 0x68, 0x01, 0x90, 0x03, 0x20, 0x02, 0x46, 0x06, 0x21, 0x41, 0x4E, 0x33, 0x46, 0x22, 0x3B, 0xF2, 0xF7, 0xEB, 0xFF, 0x3E, 0x48, 0x01, 0x68, 0x00, 0x91, 0x40, 0x68, 0x33, 0x46, 0x06, 0x21, 0x01, 0x90, 0x03, 0x20, 0x02, 0x46, 0xF2, 0xF7, 0xE0, 0xFF, 0x00, 0x20, 0x28, 0x60, 0x20, 0x68, 0x06, 0x28, 0x47, 0xD1, 0x4F, 0xF0, 0x64, 0x56, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x07, 0x0A, 0xC4, 0xF8, 0x00, 0xA0, 0x03, 0x20, 0x48, 0xF2, 0x70, 0x53, 0x01, 0x22, 0x04, 0x21, 0xF2, 0xF7, 0xD0, 0xFF, 0xDF, 0xF8, 0xCC, 0x80, 0x31, 0x4F, 0x48, 0xF2, 0x70, 0x59, 0x01, 0x25, 0x49, 0xEA, 0x05, 0x03, 0x01, 0x22, 0x04, 0x21, 0x03, 0x20, 0xF2, 0xF7, 0xC3, 0xFF, 0x00, 0x24, 0x17, 0xF8, 0x02, 0x0F, 0x20, 0xE0, 0x69, 0x01, 0x04, 0xEB, 0x08, 0x02, 0x88, 0x18, 0xC6, 0x1C, 0x43, 0x78, 0x00, 0x93, 0x80, 0x78, 0x01, 0x90, 0x30, 0x78, 0x02, 0x90 ,
+0x53, 0x5C, 0x51, 0x46, 0x04, 0x22, 0x03, 0x20, 0xF2, 0xF7, 0xAE, 0xFF, 0x38, 0x78, 0x01, 0x1B, 0xB1, 0xF1, 0xFF, 0x3F, 0x08, 0xD1, 0xF0, 0x78, 0x00, 0x90, 0xB3, 0x78, 0x03, 0x20, 0x02, 0x22, 0x05, 0x21, 0xF2, 0xF7, 0xA1, 0xFF, 0x38, 0x78, 0x24, 0x1D, 0xE4, 0xB2, 0xA0, 0x42, 0xDC, 0xDC, 0xAD, 0x1C, 0xED, 0xB2, 0x04, 0x2D, 0xCD, 0xDB, 0x63, 0x21, 0x4F, 0xF4, 0x05, 0x70, 0xF1, 0xF7, 0xA3, 0xFC, 0xE1, 0xF7, 0x85, 0xFD, 0x7F, 0xB0, 0x0E, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xC0, 0x46, 0x04, 0x74, 0x00, 0x20, 0x50, 0x57, 0x02, 0x00, 0x6C, 0x5D, 0x02, 0x00, 0x40, 0x00, 0x3D, 0x80, 0x4C, 0x57, 0x02, 0x00, 0x58, 0x57, 0x02, 0x00, 0x90, 0x57, 0x02, 0x00, 0x60, 0x57, 0x02, 0x00, 0x70, 0x57, 0x02, 0x00, 0x5C, 0x57, 0x02, 0x00, 0x80, 0x57, 0x02, 0x00, 0x2C, 0x57, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x88, 0x57, 0x02, 0x00, 0x54, 0x57, 0x02, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x38, 0x58, 0x02, 0x00, 0x40, 0x58 ,
+0x02, 0x00, 0x66, 0x55, 0xDD, 0xEE, 0xDB, 0x58, 0x02, 0x00, 0x5C, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF4, 0x57, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBC, 0x58, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0xE9, 0xFE, 0x4F, 0x4A, 0x4A, 0x49, 0x4D, 0x00, 0x90, 0xB2, 0xF9, 0x00, 0x20, 0x43, 0xA3, 0x29, 0x78, 0x01, 0x93, 0x43, 0xA3, 0x01, 0x28, 0x02, 0x93, 0x47, 0x4E, 0xDF, 0xF8, 0x1C, 0x81, 0xDF, 0xF8, 0x1C, 0x91, 0x1E, 0xD0, 0x43, 0x48, 0x04, 0x78, 0x48, 0x01, 0x87, 0x19, 0x30, 0x18, 0x01, 0x99, 0x06, 0x22, 0xF9, 0xF7, 0xC8, 0xFF, 0x40, 0x46, 0x01, 0x78, 0x00, 0x68, 0x07, 0xF1, 0x06, 0x07, 0x07, 0xF8, 0x01, 0x1B, 0x07, 0xF8, 0x01, 0x4B, 0x4F, 0xF0, 0x00, 0x01, 0x07, 0xF8, 0x01, 0x1B, 0x20, 0xB9, 0x39, 0x70, 0x28, 0x78, 0x4E, 0x46, 0x0A, 0x21, 0x58, 0xE0, 0xDF, 0xF8, 0xE4, 0xB0, 0x0F, 0xE0, 0xD4, 0xB2, 0x48, 0x01, 0x87, 0x19, 0x30, 0x18, 0x02, 0x99, 0x07, 0x22, 0xF9, 0xF7, 0xAA, 0xFF, 0xFF, 0x1D, 0x00, 0x20, 0xDF, 0xF8, 0xCC, 0xB0, 0x07, 0xF8, 0x01, 0x4B, 0x07, 0xF8, 0x01, 0x0B, 0x16, 0x2C, 0xB2, 0x46, 0xAE, 0xBF, 0x14, 0x20, 0x84, 0x59 ,
+0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x60, 0x1E, 0xC0, 0xB2, 0x38, 0x70, 0x4E, 0x46, 0x7F, 0x1C, 0x40, 0x1C, 0xC2, 0xB2, 0x28, 0x78, 0x5B, 0x46, 0x00, 0x21, 0x32, 0x54, 0x38, 0x46, 0x00, 0xF0, 0xBC, 0xF9, 0x28, 0x78, 0x16, 0x2C, 0x31, 0x5C, 0x01, 0xF1, 0x0A, 0x01, 0x31, 0x54, 0x00, 0xF1, 0x01, 0x00, 0xC0, 0xB2, 0x28, 0x70, 0x2B, 0xDB, 0x00, 0x99, 0x0A, 0xEB, 0x40, 0x10, 0x07, 0x46, 0x01, 0x29, 0xA4, 0xF1, 0x01, 0x09, 0x09, 0xD0, 0x01, 0x99, 0x06, 0x22, 0xF9, 0xF7, 0x79, 0xFF, 0x40, 0x46, 0x00, 0x78, 0xBF, 0x1D, 0x07, 0xF8, 0x01, 0x0B, 0x04, 0xE0, 0x02, 0x99, 0x07, 0x22, 0xF9, 0xF7, 0x6F, 0xFF, 0xFF, 0x1D, 0x07, 0xF8, 0x01, 0x4B, 0x15, 0x3C, 0x15, 0x21, 0x28, 0x78, 0xE2, 0xB2, 0x5B, 0x46, 0x07, 0xF8, 0x01, 0x1B, 0x32, 0x54, 0x07, 0xF8, 0x01, 0x9B, 0x38, 0x46, 0x00, 0xF0, 0x8B, 0xF9, 0x28, 0x78, 0x31, 0x5C, 0x0A, 0x31, 0x31, 0x54, 0x40, 0x1C, 0x28, 0x70, 0xBD, 0xE8, 0xFE, 0x8F, 0xC0, 0x46 ,
+0x54, 0x54, 0x54, 0x4B, 0x45, 0x59, 0x00, 0xC0, 0x54, 0x54, 0x54, 0x53, 0x53, 0x49, 0x44, 0x00, 0x54, 0x58, 0x02, 0x00, 0xE6, 0x58, 0x02, 0x00, 0xE8, 0x58, 0x02, 0x00, 0x5C, 0x58, 0x02, 0x00, 0x5C, 0x57, 0x02, 0x00, 0xDC, 0x58, 0x02, 0x00, 0xD4, 0x57, 0x02, 0x00, 0x94, 0x57, 0x02, 0x00, 0xFF, 0xB5, 0x0C, 0x46, 0x06, 0x46, 0xF7, 0xF7, 0x4C, 0x5A, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xE3, 0xFE, 0x15, 0x49, 0x15, 0x4A, 0x0D, 0x68, 0x01, 0xA9, 0x92, 0xE8, 0x8C, 0x00, 0x81, 0xE8, 0x8C, 0x00, 0xF7, 0xF7, 0xFD, 0xFE, 0x01, 0x98, 0x11, 0x49, 0x28, 0x1A, 0x03, 0x9D, 0x25, 0x60, 0x02, 0x9A, 0x80, 0x18, 0x82, 0x42, 0x30, 0x60, 0x0E, 0xD8, 0x08, 0x46, 0x00, 0x68, 0x22, 0x68, 0x82, 0x42, 0x0E, 0xD2, 0x68, 0x46, 0xE8, 0xF7, 0xB9, 0xFF, 0x9D, 0xF8, 0x00, 0x00, 0x05, 0xF1, 0x01, 0x05, 0x30, 0xB9, 0x03, 0x95, 0x03, 0xE0, 0x25, 0x68, 0x6D, 0x1C, 0x25, 0x60, 0x0C, 0x46, 0x25, 0x60, 0x00, 0x20, 0x00, 0x90 ,
+0xFF, 0xBD, 0x60, 0x55, 0x30, 0x80, 0x24, 0x5D, 0x00, 0x20, 0x6C, 0x5D, 0x02, 0x00, 0x70, 0xB5, 0x4D, 0x00, 0x20, 0x2D, 0x4F, 0xF0, 0x00, 0x01, 0x0C, 0x46, 0x4F, 0xEA, 0x55, 0x13, 0x09, 0xD3, 0x50, 0xF8, 0x21, 0x60, 0xB6, 0xF1, 0xFF, 0x3F, 0x04, 0xD1, 0x49, 0x1C, 0xC9, 0xB2, 0x20, 0x3D, 0x5B, 0x1E, 0xF5, 0xD1, 0x4D, 0xB1, 0x20, 0x2D, 0x09, 0xD2, 0x01, 0x23, 0xAB, 0x40, 0x5B, 0x1E, 0x50, 0xF8, 0x21, 0x00, 0x18, 0x40, 0x83, 0x42, 0x01, 0xD1, 0x4F, 0xF0, 0x01, 0x04, 0x07, 0x48, 0x03, 0x78, 0x2C, 0xB9, 0x01, 0x21, 0x91, 0x40, 0xC9, 0x43, 0xC9, 0xB2, 0x0B, 0x40, 0x03, 0xE0, 0x01, 0x21, 0x91, 0x40, 0xC9, 0xB2, 0x0B, 0x43, 0x03, 0x70, 0x70, 0xBD, 0xC0, 0x46, 0xEE, 0x58, 0x02, 0x00, 0x14, 0x5B, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x7E, 0xB5, 0x05, 0x46, 0x95, 0xF8, 0x36, 0x20, 0x0E, 0x46, 0x0F, 0x49, 0x07, 0x2A, 0x12, 0xBF, 0x08, 0x68, 0x01, 0x20, 0x08, 0x60, 0x0D, 0x4C, 0x00, 0x92, 0x21, 0x68 ,
+0x41, 0xF2, 0x12, 0x13, 0x04, 0x22, 0x01, 0x91, 0x07, 0x21, 0x02, 0x90, 0x03, 0x20, 0xF2, 0xF7, 0x6B, 0xFD, 0x31, 0x46, 0x28, 0x46, 0xE7, 0xF7, 0x21, 0xFC, 0x21, 0x68, 0x00, 0x22, 0x05, 0x29, 0x02, 0xD1, 0x04, 0x49, 0x08, 0x31, 0x0A, 0x60, 0x7E, 0xBD, 0xC0, 0x46, 0x50, 0x57, 0x02, 0x00, 0x4C, 0x57, 0x02, 0x00, 0x00, 0x7C, 0x00, 0x20, 0x0E, 0x49, 0x09, 0x68, 0x49, 0x08, 0x15, 0xD2, 0x0D, 0x49, 0x09, 0x78, 0x91, 0xB1, 0x44, 0xF2, 0xE9, 0x21, 0x68, 0xB9, 0x0B, 0x48, 0x01, 0x78, 0x07, 0x48, 0x01, 0x29, 0x03, 0xD1, 0x0A, 0x49, 0x09, 0x78, 0x0E, 0x29, 0x02, 0xD0, 0x44, 0xF2, 0xDE, 0x21, 0x41, 0x60, 0x01, 0x21, 0x00, 0xE0, 0x06, 0x48, 0x01, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x00, 0x97, 0x3C, 0x80, 0x10, 0x0C, 0x30, 0x80, 0xDD, 0x6A, 0x00, 0x20, 0xE0, 0x7C, 0x00, 0x20, 0xA6, 0x64, 0x00, 0x20, 0x04, 0x97, 0x3C, 0x80, 0x00, 0xB5, 0xAD, 0xF1, 0x18, 0x0D, 0x4F, 0xF0, 0x09, 0x00, 0x00, 0x90, 0x4F, 0xF4 ,
+0x0C, 0x60, 0x03, 0x90, 0x4F, 0xF0, 0x00, 0x00, 0x01, 0x90, 0x02, 0x90, 0x08, 0x48, 0x08, 0x49, 0x05, 0x90, 0x08, 0x68, 0x20, 0xB9, 0xDC, 0x5B, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x68, 0x46, 0x03, 0x22, 0xED, 0xF7, 0x3A, 0xFA, 0x03, 0xE0, 0x68, 0x46, 0x03, 0x22, 0xED, 0xF7, 0xC1, 0xFC, 0x06, 0xB0, 0x00, 0xBD, 0xC0, 0x46, 0x81, 0x5C, 0x02, 0x00, 0xDC, 0x7C, 0x00, 0x20, 0x1C, 0xB5, 0x0F, 0x4C, 0x22, 0x68, 0x01, 0x2A, 0x15, 0xD1, 0x0C, 0x48, 0x00, 0x68, 0x07, 0x28, 0x14, 0xBF, 0x40, 0x20, 0x4F, 0xF4, 0x05, 0x70, 0x63, 0x21, 0xF1, 0xF7, 0x0F, 0xFA, 0x20, 0x68, 0x00, 0x90, 0x43, 0xF2, 0x33, 0x33, 0x06, 0x21, 0x40, 0x20, 0x01, 0x90, 0x03, 0x20, 0x02, 0x46, 0xF2, 0xF7, 0xF4, 0xFC, 0x1C, 0xBD, 0xF1, 0xF7, 0x01, 0xFA, 0x1C, 0xBD, 0x4C, 0x57, 0x02, 0x00, 0x50, 0x57, 0x02, 0x00, 0x1E, 0xB5, 0x04, 0x46, 0x0A, 0x49, 0x00, 0x20, 0x0A, 0x4A, 0x08, 0x60, 0x0A, 0x49, 0x00, 0x90, 0x01, 0x90, 0x11, 0x60 ,
+0x09, 0x4A, 0x45, 0xF2, 0x55, 0x53, 0x02, 0x91, 0x10, 0x60, 0x07, 0x21, 0x04, 0x22, 0x03, 0x20, 0xF2, 0xF7, 0xD8, 0xFC, 0x20, 0x46, 0xE7, 0xF7, 0x59, 0xFD, 0x1E, 0xBD, 0x50, 0x57, 0x02, 0x00, 0x04, 0x74, 0x00, 0x20, 0x34, 0x12, 0x66, 0x09, 0x4C, 0x57, 0x02, 0x00, 0x00, 0xB5, 0x0B, 0x49, 0x00, 0x20, 0x08, 0x60, 0xE0, 0x20, 0xF7, 0xF7, 0xAA, 0xFD, 0x09, 0x49, 0x09, 0x78, 0x49, 0xB1, 0x08, 0x49, 0x0A, 0x78, 0x08, 0x49, 0x00, 0x2A, 0x06, 0xBF, 0x01, 0x22, 0x09, 0x1F, 0x44, 0xF2, 0xA4, 0x5C, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xE9, 0x22, 0x0A, 0x60, 0xF7, 0xF7, 0xA1, 0xFD, 0x00, 0xBD, 0xC0, 0x46, 0xDC, 0x7C, 0x00, 0x20, 0xDD, 0x6A, 0x00, 0x20, 0xA7, 0x64, 0x00, 0x20, 0x04, 0x97, 0x3C, 0x80, 0x50, 0xB9, 0x09, 0x48, 0x00, 0x78, 0x01, 0x28, 0x06, 0xD1, 0x08, 0x48, 0x00, 0x78, 0x0E, 0x28, 0x08, 0xBF, 0x44, 0xF2, 0xCB, 0x20, 0x01, 0xD0, 0x44, 0xF2, 0xDE, 0x20, 0x04, 0x49, 0x08, 0x60, 0x01, 0x20 ,
+0x41, 0xF8, 0x04, 0x0C, 0x70, 0x47, 0xE0, 0x7C, 0x00, 0x20, 0xA6, 0x64, 0x00, 0x20, 0x04, 0x97, 0x3C, 0x80, 0x30, 0xB5, 0x0D, 0x46, 0x84, 0x69, 0xDC, 0xF7, 0x97, 0xFB, 0x24, 0x1D, 0x01, 0x28, 0x04, 0xEB, 0x45, 0x01, 0x06, 0xD1, 0x89, 0x8E, 0x04, 0xEB, 0x85, 0x04, 0x11, 0xB9, 0x21, 0x69, 0x01, 0xB9, 0x00, 0x20, 0x30, 0xBD, 0x30, 0xB5, 0x05, 0x46, 0x5A, 0xB1, 0x03, 0xEB, 0x41, 0x03, 0x1C, 0x78, 0x59, 0x78, 0x41, 0xEA, 0x04, 0x11, 0x52, 0x1E, 0x03, 0xF1, 0x02, 0x03, 0x05, 0xF8, 0x01, 0x1B, 0xF5, 0xD1, 0x30, 0xBD, 0x00, 0xB5, 0x00, 0x20, 0xE7, 0xF7, 0xD6, 0xFE, 0x03, 0x48, 0x01, 0x68, 0x03, 0x29, 0x04, 0xBF, 0x04, 0x21, 0x01, 0x60, 0x00, 0xBD, 0xC0, 0x46, 0x4C, 0x57, 0x02, 0x00, 0x03, 0x4A, 0x12, 0x68, 0x01, 0x2A, 0x04, 0xBF, 0x02, 0x48, 0x63, 0x21, 0xF1, 0xF7, 0x76, 0xB9, 0x50, 0x57, 0x02, 0x00, 0x02, 0x20, 0x01, 0x00, 0x6C, 0x5D, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
diff --git a/drivers/cc3000/src/patch_prog.c b/drivers/cc3000/src/patch_prog.c
new file mode 100644
index 0000000000..fd128928fb
--- /dev/null
+++ b/drivers/cc3000/src/patch_prog.c
@@ -0,0 +1,414 @@
+#include <stdio.h>
+#include <string.h>
+#include "cc3000_common.h"
+#include "nvmem.h"
+#include "ccspi.h"
+#include "hci.h"
+#include "wlan.h"
+#include "patch_prog.h"
+#define BIT0 0x1
+#define BIT1 0x2
+#define BIT2 0x4
+#define BIT3 0x8
+#define BIT4 0x10
+#define BIT5 0x20
+#define BIT6 0x40
+#define BIT7 0x80
+
+static unsigned char ucStatus_Dr;
+static unsigned char ucStatus_FW;
+static unsigned char return_status = 0xFF;
+
+static signed char mac_status = -1;
+static unsigned char counter = 0;
+
+// Array to store RM parameters from EEPROM.
+static unsigned char cRMParamsFromEeprom[128];
+// Array to store MAC address from EEPROM.
+static unsigned char cMacFromEeprom[MAC_ADDR_LEN];
+// Smart Config Prefix
+static const char aucCC3000_prefix[] = {'T', 'T', 'T'};
+
+static void systick_sleep(unsigned long ms) {
+ extern void HAL_Delay(volatile uint32_t Delay);
+ HAL_Delay(ms);
+}
+
+// 2 dim array to store address and length of new FAT
+static const unsigned short aFATEntries[2][NVMEM_RM_FILEID + 1] =
+/* address */ {{0x50, 0x1f0, 0x390, 0x1390, 0x2390, 0x4390, 0x6390, 0x63a0, 0x63b0, 0x63f0, 0x6430, 0x6830},
+/* length */ {0x1a0, 0x1a0, 0x1000, 0x1000, 0x2000, 0x2000, 0x10, 0x10, 0x40, 0x40, 0x400, 0x200}};
+/* 0. NVS */
+/* 1. NVS Shadow */
+/* 2. Wireless Conf */
+/* 3. Wireless Conf Shadow */
+/* 4. BT (WLAN driver) Patches */
+/* 5. WiLink (Firmware) Patches */
+/* 6. MAC addr */
+/* 7. Frontend Vars */
+/* 8. IP config */
+/* 9. IP config Shadow */
+/* 10. Bootloader Patches */
+/* 11. Radio Module params */
+/* 12. AES128 for smart config */
+/* 13. user file */
+/* 14. user file */
+/* 15. user file */
+
+//*****************************************************************************
+//
+//! sendDriverPatch
+//!
+//! \param pointer to the length
+//!
+//! \return none
+//!
+//! \brief The function returns a pointer to the driver patch:
+//! since there is no patch yet - it returns 0
+//
+//*****************************************************************************
+
+static char *sendDriverPatch(unsigned long *Length)
+{
+ *Length = 0;
+ return NULL;
+}
+
+
+//*****************************************************************************
+//
+//! sendBootLoaderPatch
+//!
+//! \param pointer to the length
+//!
+//! \return none
+//!
+//! \brief The function returns a pointer to the boot loader patch:
+//! since there is no patch yet - it returns 0
+//
+//*****************************************************************************
+
+static char *sendBootLoaderPatch(unsigned long *Length)
+{
+ *Length = 0;
+ return NULL;
+}
+
+//*****************************************************************************
+//
+//! sendWLFWPatch
+//!
+//! \param pointer to the length
+//!
+//! \return none
+//!
+//! \brief The function returns a pointer to the FW patch:
+//! since there is no patch yet - it returns 0
+//
+//*****************************************************************************
+
+static char *sendWLFWPatch(unsigned long *Length)
+{
+ *Length = 0;
+ return NULL;
+}
+
+//*****************************************************************************
+//
+//! CC3000_UsynchCallback
+//!
+//! \param Event type
+//!
+//! \return none
+//!
+//! \brief The function handles asynchronous events that come from CC3000
+//! device and operates a LED4 to have an on-board indication
+//
+//*****************************************************************************
+
+static void CC3000_UsynchCallback(long lEventType, char * data, unsigned char length)
+{
+
+}
+
+//*****************************************************************************
+//
+//! initDriver
+//!
+//! \param[in] cRequestPatch 0 to load with EEPROM patches
+//! and 1 to load with no patches
+//!
+//! \return none
+//!
+//! \brief The function initializes a CC3000 device
+//! and triggers it to start operation
+//
+//*****************************************************************************
+static int initDriver(unsigned short cRequestPatch)
+{
+ // WLAN On API Implementation
+ wlan_init(CC3000_UsynchCallback, sendWLFWPatch, sendDriverPatch, sendBootLoaderPatch,
+ ReadWlanInterruptPin, SpiResumeSpi, SpiPauseSpi, WriteWlanPin);
+
+ // Trigger a WLAN device
+ wlan_start(cRequestPatch);
+ wlan_smart_config_set_prefix((char*)aucCC3000_prefix);
+ wlan_ioctl_set_connection_policy(0, 0, 0);
+ wlan_ioctl_del_profile(255);
+
+ // Mask out all non-required events from CC3000
+ wlan_set_event_mask(HCI_EVNT_WLAN_KEEPALIVE|
+ HCI_EVNT_WLAN_UNSOL_INIT|
+ HCI_EVNT_WLAN_ASYNC_PING_REPORT);
+
+ //unsolicicted_events_timer_init();
+ systick_sleep(100);
+ return(0);
+}
+
+
+//*****************************************************************************
+//
+//! fat_read_content
+//!
+//! \param[out] is_allocated array of is_allocated in FAT table:\n
+//! an allocated entry implies the address and length of the
+//! file are valid.
+//! 0: not allocated; 1: allocated.
+//! \param[out] is_valid array of is_valid in FAT table:\n
+//! a valid entry implies the content of the file is relevant.
+//! 0: not valid; 1: valid.
+//! \param[out] write_protected array of write_protected in FAT table:\n
+//! a write protected entry implies it is not possible to write
+//! into this entry.
+//! 0: not protected; 1: protected.
+//! \param[out] file_address array of file address in FAT table:\n
+//! this is the absolute address of the file in the EEPROM.
+//! \param[out] file_length array of file length in FAT table:\n
+//! this is the upper limit of the file size in the EEPROM.
+//!
+//! \return on succes 0, error otherwise
+//!
+//! \brief parse the FAT table from eeprom
+//
+//*****************************************************************************
+static unsigned char __attribute__ ((unused))
+fat_read_content(unsigned char *is_allocated, unsigned char *is_valid,
+ unsigned char *write_protected, unsigned short *file_address, unsigned short *file_length)
+{
+ unsigned short index;
+ unsigned char ucStatus;
+ unsigned char fatTable[48];
+ unsigned char* fatTablePtr = fatTable;
+
+ //
+ // Read in 6 parts to work with tiny driver
+ //
+ for (index = 0; index < 6; index++)
+ {
+ ucStatus = nvmem_read(16, 8, 4 + 8*index, fatTablePtr);
+ fatTablePtr += 8;
+ }
+
+ fatTablePtr = fatTable;
+
+ for (index = 0; index <= NVMEM_RM_FILEID; index++)
+ {
+ *is_allocated++ = (*fatTablePtr) & BIT0;
+ *is_valid++ = ((*fatTablePtr) & BIT1) >> 1;
+ *write_protected++ = ((*fatTablePtr) & BIT2) >> 2;
+ *file_address++ = ((*(fatTablePtr+1)<<8) | (*fatTablePtr)) & (BIT4|BIT5|BIT6|BIT7);
+ *file_length++ = ((*(fatTablePtr+3)<<8) | (*(fatTablePtr+2))) & (BIT4|BIT5|BIT6|BIT7);
+
+ //
+ // Move to next file ID
+ //
+ fatTablePtr += 4;
+ }
+
+ return ucStatus;
+}
+
+//*****************************************************************************
+//
+//! fat_write_content
+//!
+//! \param[in] file_address array of file address in FAT table:\n
+//! this is the absolute address of the file in the EEPROM.
+//! \param[in] file_length array of file length in FAT table:\n
+//! this is the upper limit of the file size in the EEPROM.
+//!
+//! \return on succes 0, error otherwise
+//!
+//! \brief parse the FAT table from eeprom
+//
+//*****************************************************************************
+static unsigned char fat_write_content(unsigned short const *file_address,
+ unsigned short const *file_length)
+{
+ unsigned short index = 0;
+ unsigned char ucStatus;
+ unsigned char fatTable[48];
+ unsigned char* fatTablePtr = fatTable;
+
+ //
+ // First, write the magic number.
+ //
+ ucStatus = nvmem_write(16, 2, 0, (unsigned char*)"LS");
+
+ for (; index <= NVMEM_RM_FILEID; index++)
+ {
+ //
+ // Write address low char and mark as allocated.
+ //
+ *fatTablePtr++ = (unsigned char)(file_address[index] & 0xff) | BIT0;
+
+ //
+ // Write address high char.
+ //
+ *fatTablePtr++ = (unsigned char)((file_address[index]>>8) & 0xff);
+
+ //
+ // Write length low char.
+ //
+ *fatTablePtr++ = (unsigned char)(file_length[index] & 0xff);
+
+ //
+ // Write length high char.
+ //
+ *fatTablePtr++ = (unsigned char)((file_length[index]>>8) & 0xff);
+ }
+
+ //
+ // Second, write the FAT.
+ // Write in two parts to work with tiny driver.
+ //
+ ucStatus = nvmem_write(16, 24, 4, fatTable);
+ ucStatus = nvmem_write(16, 24, 24+4, &fatTable[24]);
+
+ //
+ // Third, we want to erase any user files.
+ //
+ memset(fatTable, 0, sizeof(fatTable));
+ ucStatus = nvmem_write(16, 16, 52, fatTable);
+
+ return ucStatus;
+}
+
+void patch_prog_start()
+{
+ unsigned short index;
+ unsigned char *pRMParams;
+
+ printf("Initializing module...\n");
+
+ // Init module and request to load with no patches.
+ // This is in order to overwrite restrictions to
+ // write to specific places in EEPROM.
+ initDriver(1);
+
+ // Read MAC address.
+ mac_status = nvmem_get_mac_address(cMacFromEeprom);
+
+ return_status = 1;
+
+ printf("Reading RM parameters...\n");
+ while ((return_status) && (counter < 3)) {
+ // Read RM parameters.
+ // Read in 16 parts to work with tiny driver.
+ return_status = 0;
+ pRMParams = cRMParamsFromEeprom;
+ for (index = 0; index < 16; index++) {
+ return_status |= nvmem_read(NVMEM_RM_FILEID, 8, 8*index, pRMParams);
+ pRMParams += 8;
+ }
+ counter++;
+ }
+
+ // If RM file is not valid, load the default one.
+ if (counter == 3) {
+ printf("RM is not valid, loading default one...\n");
+ pRMParams = (unsigned char *)cRMdefaultParams;
+ } else {
+ printf("RM is valid.\n");
+ pRMParams = cRMParamsFromEeprom;
+ }
+
+ return_status = 1;
+
+ printf("Writing new FAT\n");
+ while (return_status) {
+ // Write new FAT.
+ return_status = fat_write_content(aFATEntries[0], aFATEntries[1]);
+ }
+
+ return_status = 1;
+
+ printf("Writing RM parameters...\n");
+ while (return_status) {
+ // Write RM parameters.
+ // Write in 4 parts to work with tiny driver.
+ return_status = 0;
+
+ for (index = 0; index < 4; index++) {
+ return_status |= nvmem_write(NVMEM_RM_FILEID,
+ 32,
+ 32*index,
+ (pRMParams + 32*index));
+ }
+ }
+
+ return_status = 1;
+
+ // Write back the MAC address, only if exists.
+ if (mac_status == 0) {
+ // Zero out MCAST bit if set.
+ cMacFromEeprom[0] &= 0xfe;
+ printf("Writing back MAC address..\n");
+ while (return_status) {
+ return_status = nvmem_set_mac_address(cMacFromEeprom);
+ }
+ }
+
+ // Update driver
+ ucStatus_Dr = 1;
+ printf("Updating driver patch...\n");
+ while (ucStatus_Dr) {
+ // Writing driver patch to EEPRROM - PROTABLE CODE
+ // Note that the array itself is changing between the
+ // different Service Packs.
+ ucStatus_Dr = nvmem_write_patch(NVMEM_WLAN_DRIVER_SP_FILEID,
+ drv_length,
+ wlan_drv_patch);
+ }
+
+ // Update firmware
+ ucStatus_FW = 1;
+ printf("Updating firmware patch...\n");
+ while (ucStatus_FW) {
+ // Writing FW patch to EEPRROM - PROTABLE CODE
+ // Note that the array itself is changing between the
+ // different Service Packs.
+ ucStatus_FW = nvmem_write_patch(NVMEM_WLAN_FW_SP_FILEID,
+ fw_length,
+ fw_patch);
+ }
+
+ printf("Update complete, resetting module\n"\
+ "If this doesn't work, reset manually...\n");
+
+ wlan_stop();
+ systick_sleep(500);
+
+ // Re-Init module and request to load with patches.
+ initDriver(0);
+
+ // If MAC does not exist, it is recommended
+ // that the user will write a valid mac address.
+ if (mac_status != 0) {
+ printf("MAC address is not valid, please write a new one\n");
+ }
+
+ // Patch update done
+ printf("All done, call wlan.patch_version()\n");
+}
diff --git a/drivers/cc3000/src/security.c b/drivers/cc3000/src/security.c
new file mode 100644
index 0000000000..62b4f88134
--- /dev/null
+++ b/drivers/cc3000/src/security.c
@@ -0,0 +1,530 @@
+/*****************************************************************************
+*
+* security.c - CC3000 Host Driver Implementation.
+* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the
+* distribution.
+*
+* Neither the name of Texas Instruments Incorporated nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*****************************************************************************/
+
+//*****************************************************************************
+//
+//! \addtogroup security_api
+//! @{
+//
+//*****************************************************************************
+
+#include "security.h"
+
+#ifndef CC3000_UNENCRYPTED_SMART_CONFIG
+// foreward sbox
+const UINT8 sbox[256] = {
+//0 1 2 3 4 5 6 7 8 9 A B C D E F
+0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, //0
+0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, //1
+0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, //2
+0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, //3
+0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, //4
+0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, //5
+0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, //6
+0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, //7
+0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, //8
+0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, //9
+0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, //A
+0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, //B
+0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, //C
+0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, //D
+0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, //E
+0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; //F
+// inverse sbox
+const UINT8 rsbox[256] =
+{ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb
+, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb
+, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e
+, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25
+, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92
+, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84
+, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06
+, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b
+, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73
+, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e
+, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b
+, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4
+, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f
+, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef
+, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61
+, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d };
+// round constant
+const UINT8 Rcon[11] = {
+ 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
+
+
+UINT8 expandedKey[176];
+
+//*****************************************************************************
+//
+//! expandKey
+//!
+//! @param key AES128 key - 16 bytes
+//! @param expandedKey expanded AES128 key
+//!
+//! @return none
+//!
+//! @brief expend a 16 bytes key for AES128 implementation
+//!
+//*****************************************************************************
+
+void expandKey(UINT8 *expandedKey, UINT8 *key)
+{
+ UINT16 ii, buf1;
+ for (ii=0;ii<16;ii++)
+ expandedKey[ii] = key[ii];
+ for (ii=1;ii<11;ii++){
+ buf1 = expandedKey[ii*16 - 4];
+ expandedKey[ii*16 + 0] = sbox[expandedKey[ii*16 - 3]]^expandedKey[(ii-1)*16 + 0]^Rcon[ii];
+ expandedKey[ii*16 + 1] = sbox[expandedKey[ii*16 - 2]]^expandedKey[(ii-1)*16 + 1];
+ expandedKey[ii*16 + 2] = sbox[expandedKey[ii*16 - 1]]^expandedKey[(ii-1)*16 + 2];
+ expandedKey[ii*16 + 3] = sbox[buf1 ]^expandedKey[(ii-1)*16 + 3];
+ expandedKey[ii*16 + 4] = expandedKey[(ii-1)*16 + 4]^expandedKey[ii*16 + 0];
+ expandedKey[ii*16 + 5] = expandedKey[(ii-1)*16 + 5]^expandedKey[ii*16 + 1];
+ expandedKey[ii*16 + 6] = expandedKey[(ii-1)*16 + 6]^expandedKey[ii*16 + 2];
+ expandedKey[ii*16 + 7] = expandedKey[(ii-1)*16 + 7]^expandedKey[ii*16 + 3];
+ expandedKey[ii*16 + 8] = expandedKey[(ii-1)*16 + 8]^expandedKey[ii*16 + 4];
+ expandedKey[ii*16 + 9] = expandedKey[(ii-1)*16 + 9]^expandedKey[ii*16 + 5];
+ expandedKey[ii*16 +10] = expandedKey[(ii-1)*16 +10]^expandedKey[ii*16 + 6];
+ expandedKey[ii*16 +11] = expandedKey[(ii-1)*16 +11]^expandedKey[ii*16 + 7];
+ expandedKey[ii*16 +12] = expandedKey[(ii-1)*16 +12]^expandedKey[ii*16 + 8];
+ expandedKey[ii*16 +13] = expandedKey[(ii-1)*16 +13]^expandedKey[ii*16 + 9];
+ expandedKey[ii*16 +14] = expandedKey[(ii-1)*16 +14]^expandedKey[ii*16 +10];
+ expandedKey[ii*16 +15] = expandedKey[(ii-1)*16 +15]^expandedKey[ii*16 +11];
+ }
+
+}
+
+//*****************************************************************************
+//
+//! galois_mul2
+//!
+//! @param value argument to multiply
+//!
+//! @return multiplied argument
+//!
+//! @brief multiply by 2 in the galois field
+//!
+//*****************************************************************************
+
+UINT8 galois_mul2(UINT8 value)
+{
+ if (value>>7)
+ {
+ value = value << 1;
+ return (value^0x1b);
+ } else
+ return value<<1;
+}
+
+//*****************************************************************************
+//
+//! aes_encr
+//!
+//! @param[in] expandedKey expanded AES128 key
+//! @param[in/out] state 16 bytes of plain text and cipher text
+//!
+//! @return none
+//!
+//! @brief internal implementation of AES128 encryption.
+//! straight forward aes encryption implementation
+//! first the group of operations
+//! - addRoundKey
+//! - subbytes
+//! - shiftrows
+//! - mixcolums
+//! is executed 9 times, after this addroundkey to finish the 9th
+//! round, after that the 10th round without mixcolums
+//! no further subfunctions to save cycles for function calls
+//! no structuring with "for (....)" to save cycles.
+//!
+//!
+//*****************************************************************************
+
+void aes_encr(UINT8 *state, UINT8 *expandedKey)
+{
+ UINT8 buf1, buf2, buf3, round;
+
+ for (round = 0; round < 9; round ++){
+ // addroundkey, sbox and shiftrows
+ // row 0
+ state[ 0] = sbox[(state[ 0] ^ expandedKey[(round*16) ])];
+ state[ 4] = sbox[(state[ 4] ^ expandedKey[(round*16) + 4])];
+ state[ 8] = sbox[(state[ 8] ^ expandedKey[(round*16) + 8])];
+ state[12] = sbox[(state[12] ^ expandedKey[(round*16) + 12])];
+ // row 1
+ buf1 = state[1] ^ expandedKey[(round*16) + 1];
+ state[ 1] = sbox[(state[ 5] ^ expandedKey[(round*16) + 5])];
+ state[ 5] = sbox[(state[ 9] ^ expandedKey[(round*16) + 9])];
+ state[ 9] = sbox[(state[13] ^ expandedKey[(round*16) + 13])];
+ state[13] = sbox[buf1];
+ // row 2
+ buf1 = state[2] ^ expandedKey[(round*16) + 2];
+ buf2 = state[6] ^ expandedKey[(round*16) + 6];
+ state[ 2] = sbox[(state[10] ^ expandedKey[(round*16) + 10])];
+ state[ 6] = sbox[(state[14] ^ expandedKey[(round*16) + 14])];
+ state[10] = sbox[buf1];
+ state[14] = sbox[buf2];
+ // row 3
+ buf1 = state[15] ^ expandedKey[(round*16) + 15];
+ state[15] = sbox[(state[11] ^ expandedKey[(round*16) + 11])];
+ state[11] = sbox[(state[ 7] ^ expandedKey[(round*16) + 7])];
+ state[ 7] = sbox[(state[ 3] ^ expandedKey[(round*16) + 3])];
+ state[ 3] = sbox[buf1];
+
+ // mixcolums //////////
+ // col1
+ buf1 = state[0] ^ state[1] ^ state[2] ^ state[3];
+ buf2 = state[0];
+ buf3 = state[0]^state[1]; buf3=galois_mul2(buf3); state[0] = state[0] ^ buf3 ^ buf1;
+ buf3 = state[1]^state[2]; buf3=galois_mul2(buf3); state[1] = state[1] ^ buf3 ^ buf1;
+ buf3 = state[2]^state[3]; buf3=galois_mul2(buf3); state[2] = state[2] ^ buf3 ^ buf1;
+ buf3 = state[3]^buf2; buf3=galois_mul2(buf3); state[3] = state[3] ^ buf3 ^ buf1;
+ // col2
+ buf1 = state[4] ^ state[5] ^ state[6] ^ state[7];
+ buf2 = state[4];
+ buf3 = state[4]^state[5]; buf3=galois_mul2(buf3); state[4] = state[4] ^ buf3 ^ buf1;
+ buf3 = state[5]^state[6]; buf3=galois_mul2(buf3); state[5] = state[5] ^ buf3 ^ buf1;
+ buf3 = state[6]^state[7]; buf3=galois_mul2(buf3); state[6] = state[6] ^ buf3 ^ buf1;
+ buf3 = state[7]^buf2; buf3=galois_mul2(buf3); state[7] = state[7] ^ buf3 ^ buf1;
+ // col3
+ buf1 = state[8] ^ state[9] ^ state[10] ^ state[11];
+ buf2 = state[8];
+ buf3 = state[8]^state[9]; buf3=galois_mul2(buf3); state[8] = state[8] ^ buf3 ^ buf1;
+ buf3 = state[9]^state[10]; buf3=galois_mul2(buf3); state[9] = state[9] ^ buf3 ^ buf1;
+ buf3 = state[10]^state[11]; buf3=galois_mul2(buf3); state[10] = state[10] ^ buf3 ^ buf1;
+ buf3 = state[11]^buf2; buf3=galois_mul2(buf3); state[11] = state[11] ^ buf3 ^ buf1;
+ // col4
+ buf1 = state[12] ^ state[13] ^ state[14] ^ state[15];
+ buf2 = state[12];
+ buf3 = state[12]^state[13]; buf3=galois_mul2(buf3); state[12] = state[12] ^ buf3 ^ buf1;
+ buf3 = state[13]^state[14]; buf3=galois_mul2(buf3); state[13] = state[13] ^ buf3 ^ buf1;
+ buf3 = state[14]^state[15]; buf3=galois_mul2(buf3); state[14] = state[14] ^ buf3 ^ buf1;
+ buf3 = state[15]^buf2; buf3=galois_mul2(buf3); state[15] = state[15] ^ buf3 ^ buf1;
+
+ }
+ // 10th round without mixcols
+ state[ 0] = sbox[(state[ 0] ^ expandedKey[(round*16) ])];
+ state[ 4] = sbox[(state[ 4] ^ expandedKey[(round*16) + 4])];
+ state[ 8] = sbox[(state[ 8] ^ expandedKey[(round*16) + 8])];
+ state[12] = sbox[(state[12] ^ expandedKey[(round*16) + 12])];
+ // row 1
+ buf1 = state[1] ^ expandedKey[(round*16) + 1];
+ state[ 1] = sbox[(state[ 5] ^ expandedKey[(round*16) + 5])];
+ state[ 5] = sbox[(state[ 9] ^ expandedKey[(round*16) + 9])];
+ state[ 9] = sbox[(state[13] ^ expandedKey[(round*16) + 13])];
+ state[13] = sbox[buf1];
+ // row 2
+ buf1 = state[2] ^ expandedKey[(round*16) + 2];
+ buf2 = state[6] ^ expandedKey[(round*16) + 6];
+ state[ 2] = sbox[(state[10] ^ expandedKey[(round*16) + 10])];
+ state[ 6] = sbox[(state[14] ^ expandedKey[(round*16) + 14])];
+ state[10] = sbox[buf1];
+ state[14] = sbox[buf2];
+ // row 3
+ buf1 = state[15] ^ expandedKey[(round*16) + 15];
+ state[15] = sbox[(state[11] ^ expandedKey[(round*16) + 11])];
+ state[11] = sbox[(state[ 7] ^ expandedKey[(round*16) + 7])];
+ state[ 7] = sbox[(state[ 3] ^ expandedKey[(round*16) + 3])];
+ state[ 3] = sbox[buf1];
+ // last addroundkey
+ state[ 0]^=expandedKey[160];
+ state[ 1]^=expandedKey[161];
+ state[ 2]^=expandedKey[162];
+ state[ 3]^=expandedKey[163];
+ state[ 4]^=expandedKey[164];
+ state[ 5]^=expandedKey[165];
+ state[ 6]^=expandedKey[166];
+ state[ 7]^=expandedKey[167];
+ state[ 8]^=expandedKey[168];
+ state[ 9]^=expandedKey[169];
+ state[10]^=expandedKey[170];
+ state[11]^=expandedKey[171];
+ state[12]^=expandedKey[172];
+ state[13]^=expandedKey[173];
+ state[14]^=expandedKey[174];
+ state[15]^=expandedKey[175];
+}
+
+//*****************************************************************************
+//
+//! aes_decr
+//!
+//! @param[in] expandedKey expanded AES128 key
+//! @param[in\out] state 16 bytes of cipher text and plain text
+//!
+//! @return none
+//!
+//! @brief internal implementation of AES128 decryption.
+//! straight forward aes decryption implementation
+//! the order of substeps is the exact reverse of decryption
+//! inverse functions:
+//! - addRoundKey is its own inverse
+//! - rsbox is inverse of sbox
+//! - rightshift instead of leftshift
+//! - invMixColumns = barreto + mixColumns
+//! no further subfunctions to save cycles for function calls
+//! no structuring with "for (....)" to save cycles
+//!
+//*****************************************************************************
+
+void aes_decr(UINT8 *state, UINT8 *expandedKey)
+{
+ UINT8 buf1, buf2, buf3;
+ INT8 round;
+ round = 9;
+
+ // initial addroundkey
+ state[ 0]^=expandedKey[160];
+ state[ 1]^=expandedKey[161];
+ state[ 2]^=expandedKey[162];
+ state[ 3]^=expandedKey[163];
+ state[ 4]^=expandedKey[164];
+ state[ 5]^=expandedKey[165];
+ state[ 6]^=expandedKey[166];
+ state[ 7]^=expandedKey[167];
+ state[ 8]^=expandedKey[168];
+ state[ 9]^=expandedKey[169];
+ state[10]^=expandedKey[170];
+ state[11]^=expandedKey[171];
+ state[12]^=expandedKey[172];
+ state[13]^=expandedKey[173];
+ state[14]^=expandedKey[174];
+ state[15]^=expandedKey[175];
+
+ // 10th round without mixcols
+ state[ 0] = rsbox[state[ 0]] ^ expandedKey[(round*16) ];
+ state[ 4] = rsbox[state[ 4]] ^ expandedKey[(round*16) + 4];
+ state[ 8] = rsbox[state[ 8]] ^ expandedKey[(round*16) + 8];
+ state[12] = rsbox[state[12]] ^ expandedKey[(round*16) + 12];
+ // row 1
+ buf1 = rsbox[state[13]] ^ expandedKey[(round*16) + 1];
+ state[13] = rsbox[state[ 9]] ^ expandedKey[(round*16) + 13];
+ state[ 9] = rsbox[state[ 5]] ^ expandedKey[(round*16) + 9];
+ state[ 5] = rsbox[state[ 1]] ^ expandedKey[(round*16) + 5];
+ state[ 1] = buf1;
+ // row 2
+ buf1 = rsbox[state[ 2]] ^ expandedKey[(round*16) + 10];
+ buf2 = rsbox[state[ 6]] ^ expandedKey[(round*16) + 14];
+ state[ 2] = rsbox[state[10]] ^ expandedKey[(round*16) + 2];
+ state[ 6] = rsbox[state[14]] ^ expandedKey[(round*16) + 6];
+ state[10] = buf1;
+ state[14] = buf2;
+ // row 3
+ buf1 = rsbox[state[ 3]] ^ expandedKey[(round*16) + 15];
+ state[ 3] = rsbox[state[ 7]] ^ expandedKey[(round*16) + 3];
+ state[ 7] = rsbox[state[11]] ^ expandedKey[(round*16) + 7];
+ state[11] = rsbox[state[15]] ^ expandedKey[(round*16) + 11];
+ state[15] = buf1;
+
+ for (round = 8; round >= 0; round--){
+ // barreto
+ //col1
+ buf1 = galois_mul2(galois_mul2(state[0]^state[2]));
+ buf2 = galois_mul2(galois_mul2(state[1]^state[3]));
+ state[0] ^= buf1; state[1] ^= buf2; state[2] ^= buf1; state[3] ^= buf2;
+ //col2
+ buf1 = galois_mul2(galois_mul2(state[4]^state[6]));
+ buf2 = galois_mul2(galois_mul2(state[5]^state[7]));
+ state[4] ^= buf1; state[5] ^= buf2; state[6] ^= buf1; state[7] ^= buf2;
+ //col3
+ buf1 = galois_mul2(galois_mul2(state[8]^state[10]));
+ buf2 = galois_mul2(galois_mul2(state[9]^state[11]));
+ state[8] ^= buf1; state[9] ^= buf2; state[10] ^= buf1; state[11] ^= buf2;
+ //col4
+ buf1 = galois_mul2(galois_mul2(state[12]^state[14]));
+ buf2 = galois_mul2(galois_mul2(state[13]^state[15]));
+ state[12] ^= buf1; state[13] ^= buf2; state[14] ^= buf1; state[15] ^= buf2;
+ // mixcolums //////////
+ // col1
+ buf1 = state[0] ^ state[1] ^ state[2] ^ state[3];
+ buf2 = state[0];
+ buf3 = state[0]^state[1]; buf3=galois_mul2(buf3); state[0] = state[0] ^ buf3 ^ buf1;
+ buf3 = state[1]^state[2]; buf3=galois_mul2(buf3); state[1] = state[1] ^ buf3 ^ buf1;
+ buf3 = state[2]^state[3]; buf3=galois_mul2(buf3); state[2] = state[2] ^ buf3 ^ buf1;
+ buf3 = state[3]^buf2; buf3=galois_mul2(buf3); state[3] = state[3] ^ buf3 ^ buf1;
+ // col2
+ buf1 = state[4] ^ state[5] ^ state[6] ^ state[7];
+ buf2 = state[4];
+ buf3 = state[4]^state[5]; buf3=galois_mul2(buf3); state[4] = state[4] ^ buf3 ^ buf1;
+ buf3 = state[5]^state[6]; buf3=galois_mul2(buf3); state[5] = state[5] ^ buf3 ^ buf1;
+ buf3 = state[6]^state[7]; buf3=galois_mul2(buf3); state[6] = state[6] ^ buf3 ^ buf1;
+ buf3 = state[7]^buf2; buf3=galois_mul2(buf3); state[7] = state[7] ^ buf3 ^ buf1;
+ // col3
+ buf1 = state[8] ^ state[9] ^ state[10] ^ state[11];
+ buf2 = state[8];
+ buf3 = state[8]^state[9]; buf3=galois_mul2(buf3); state[8] = state[8] ^ buf3 ^ buf1;
+ buf3 = state[9]^state[10]; buf3=galois_mul2(buf3); state[9] = state[9] ^ buf3 ^ buf1;
+ buf3 = state[10]^state[11]; buf3=galois_mul2(buf3); state[10] = state[10] ^ buf3 ^ buf1;
+ buf3 = state[11]^buf2; buf3=galois_mul2(buf3); state[11] = state[11] ^ buf3 ^ buf1;
+ // col4
+ buf1 = state[12] ^ state[13] ^ state[14] ^ state[15];
+ buf2 = state[12];
+ buf3 = state[12]^state[13]; buf3=galois_mul2(buf3); state[12] = state[12] ^ buf3 ^ buf1;
+ buf3 = state[13]^state[14]; buf3=galois_mul2(buf3); state[13] = state[13] ^ buf3 ^ buf1;
+ buf3 = state[14]^state[15]; buf3=galois_mul2(buf3); state[14] = state[14] ^ buf3 ^ buf1;
+ buf3 = state[15]^buf2; buf3=galois_mul2(buf3); state[15] = state[15] ^ buf3 ^ buf1;
+
+ // addroundkey, rsbox and shiftrows
+ // row 0
+ state[ 0] = rsbox[state[ 0]] ^ expandedKey[(round*16) ];
+ state[ 4] = rsbox[state[ 4]] ^ expandedKey[(round*16) + 4];
+ state[ 8] = rsbox[state[ 8]] ^ expandedKey[(round*16) + 8];
+ state[12] = rsbox[state[12]] ^ expandedKey[(round*16) + 12];
+ // row 1
+ buf1 = rsbox[state[13]] ^ expandedKey[(round*16) + 1];
+ state[13] = rsbox[state[ 9]] ^ expandedKey[(round*16) + 13];
+ state[ 9] = rsbox[state[ 5]] ^ expandedKey[(round*16) + 9];
+ state[ 5] = rsbox[state[ 1]] ^ expandedKey[(round*16) + 5];
+ state[ 1] = buf1;
+ // row 2
+ buf1 = rsbox[state[ 2]] ^ expandedKey[(round*16) + 10];
+ buf2 = rsbox[state[ 6]] ^ expandedKey[(round*16) + 14];
+ state[ 2] = rsbox[state[10]] ^ expandedKey[(round*16) + 2];
+ state[ 6] = rsbox[state[14]] ^ expandedKey[(round*16) + 6];
+ state[10] = buf1;
+ state[14] = buf2;
+ // row 3
+ buf1 = rsbox[state[ 3]] ^ expandedKey[(round*16) + 15];
+ state[ 3] = rsbox[state[ 7]] ^ expandedKey[(round*16) + 3];
+ state[ 7] = rsbox[state[11]] ^ expandedKey[(round*16) + 7];
+ state[11] = rsbox[state[15]] ^ expandedKey[(round*16) + 11];
+ state[15] = buf1;
+ }
+
+}
+
+//*****************************************************************************
+//
+//! aes_encrypt
+//!
+//! @param[in] key AES128 key of size 16 bytes
+//! @param[in\out] state 16 bytes of plain text and cipher text
+//!
+//! @return none
+//!
+//! @brief AES128 encryption:
+//! Given AES128 key and 16 bytes plain text, cipher text of 16 bytes
+//! is computed. The AES implementation is in mode ECB (Electronic
+//! Code Book).
+//!
+//!
+//*****************************************************************************
+
+void aes_encrypt(UINT8 *state, UINT8 *key)
+{
+ // expand the key into 176 bytes
+ expandKey(expandedKey, key);
+ aes_encr(state, expandedKey);
+}
+
+//*****************************************************************************
+//
+//! aes_decrypt
+//!
+//! @param[in] key AES128 key of size 16 bytes
+//! @param[in\out] state 16 bytes of cipher text and plain text
+//!
+//! @return none
+//!
+//! @brief AES128 decryption:
+//! Given AES128 key and 16 bytes cipher text, plain text of 16 bytes
+//! is computed The AES implementation is in mode ECB
+//! (Electronic Code Book).
+//!
+//!
+//*****************************************************************************
+
+void aes_decrypt(UINT8 *state, UINT8 *key)
+{
+ expandKey(expandedKey, key); // expand the key into 176 bytes
+ aes_decr(state, expandedKey);
+}
+
+//*****************************************************************************
+//
+//! aes_read_key
+//!
+//! @param[out] key AES128 key of size 16 bytes
+//!
+//! @return on success 0, error otherwise.
+//!
+//! @brief Reads AES128 key from EEPROM
+//! Reads the AES128 key from fileID #12 in EEPROM
+//! returns an error if the key does not exist.
+//!
+//!
+//*****************************************************************************
+
+INT32 aes_read_key(UINT8 *key)
+{
+ INT32 returnValue;
+
+ returnValue = nvmem_read(NVMEM_AES128_KEY_FILEID, AES128_KEY_SIZE, 0, key);
+
+ return returnValue;
+}
+
+//*****************************************************************************
+//
+//! aes_write_key
+//!
+//! @param[out] key AES128 key of size 16 bytes
+//!
+//! @return on success 0, error otherwise.
+//!
+//! @brief writes AES128 key from EEPROM
+//! Writes the AES128 key to fileID #12 in EEPROM
+//!
+//!
+//*****************************************************************************
+
+INT32 aes_write_key(UINT8 *key)
+{
+ INT32 returnValue;
+
+ returnValue = nvmem_write(NVMEM_AES128_KEY_FILEID, AES128_KEY_SIZE, 0, key);
+
+ return returnValue;
+}
+
+#endif //CC3000_UNENCRYPTED_SMART_CONFIG
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
diff --git a/drivers/cc3000/src/socket.c b/drivers/cc3000/src/socket.c
new file mode 100644
index 0000000000..bcc608e5f5
--- /dev/null
+++ b/drivers/cc3000/src/socket.c
@@ -0,0 +1,1182 @@
+/*****************************************************************************
+*
+* socket.c - CC3000 Host Driver Implementation.
+* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the
+* distribution.
+*
+* Neither the name of Texas Instruments Incorporated nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*****************************************************************************/
+
+//*****************************************************************************
+//
+//! \addtogroup socket_api
+//! @{
+//
+//*****************************************************************************
+
+#include <string.h>
+#include <stdlib.h>
+#include "hci.h"
+#include "socket.h"
+#include "evnt_handler.h"
+#include "netapp.h"
+
+
+
+//Enable this flag if and only if you must comply with BSD socket
+//close() function
+#ifdef _API_USE_BSD_CLOSE
+#define close(sd) closesocket(sd)
+#endif
+
+//Enable this flag if and only if you must comply with BSD socket read() and
+//write() functions
+#ifdef _API_USE_BSD_READ_WRITE
+#define read(sd, buf, len, flags) recv(sd, buf, len, flags)
+#define write(sd, buf, len, flags) send(sd, buf, len, flags)
+#endif
+
+#define SOCKET_OPEN_PARAMS_LEN (12)
+#define SOCKET_CLOSE_PARAMS_LEN (4)
+#define SOCKET_ACCEPT_PARAMS_LEN (4)
+#define SOCKET_BIND_PARAMS_LEN (20)
+#define SOCKET_LISTEN_PARAMS_LEN (8)
+#define SOCKET_GET_HOST_BY_NAME_PARAMS_LEN (9)
+#define SOCKET_CONNECT_PARAMS_LEN (20)
+#define SOCKET_SELECT_PARAMS_LEN (44)
+#define SOCKET_SET_SOCK_OPT_PARAMS_LEN (20)
+#define SOCKET_GET_SOCK_OPT_PARAMS_LEN (12)
+#define SOCKET_RECV_FROM_PARAMS_LEN (12)
+#define SOCKET_SENDTO_PARAMS_LEN (24)
+#define SOCKET_MDNS_ADVERTISE_PARAMS_LEN (12)
+#define SOCKET_GET_MSS_VALUE_PARAMS_LEN (4)
+
+// The legnth of arguments for the SEND command: sd + buff_offset + len + flags,
+// while size of each parameter is 32 bit - so the total length is 16 bytes;
+
+#define HCI_CMND_SEND_ARG_LENGTH (16)
+
+
+#define SELECT_TIMEOUT_MIN_MICRO_SECONDS 5000
+
+#define HEADERS_SIZE_DATA (SPI_HEADER_SIZE + 5)
+
+#define SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE (SPI_HEADER_SIZE + SIMPLE_LINK_HCI_CMND_HEADER_SIZE)
+
+#define MDNS_DEVICE_SERVICE_MAX_LENGTH (32)
+
+
+//*****************************************************************************
+//
+//! HostFlowControlConsumeBuff
+//!
+//! @param sd socket descriptor
+//!
+//! @return 0 in case there are buffers available,
+//! -1 in case of bad socket
+//! -2 if there are no free buffers present (only when
+//! SEND_NON_BLOCKING is enabled)
+//!
+//! @brief if SEND_NON_BLOCKING not define - block until have free buffer
+//! becomes available, else return immediately with correct status
+//! regarding the buffers available.
+//
+//*****************************************************************************
+INT16 HostFlowControlConsumeBuff(INT16 sd)
+{
+#ifndef SEND_NON_BLOCKING
+ /* wait in busy loop */
+ do
+ {
+ // In case last transmission failed then we will return the last failure
+ // reason here.
+ // Note that the buffer will not be allocated in this case
+ if (tSLInformation.slTransmitDataError != 0)
+ {
+ errno = tSLInformation.slTransmitDataError;
+ tSLInformation.slTransmitDataError = 0;
+ return errno;
+ }
+
+ if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd))
+ return -1;
+ } while(0 == tSLInformation.usNumberOfFreeBuffers);
+
+ tSLInformation.usNumberOfFreeBuffers--;
+
+ return 0;
+#else
+
+ // In case last transmission failed then we will return the last failure
+ // reason here.
+ // Note that the buffer will not be allocated in this case
+ if (tSLInformation.slTransmitDataError != 0)
+ {
+ errno = tSLInformation.slTransmitDataError;
+ tSLInformation.slTransmitDataError = 0;
+ return errno;
+ }
+ if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd))
+ return -1;
+
+ //If there are no available buffers, return -2. It is recommended to use
+ // select or receive to see if there is any buffer occupied with received data
+ // If so, call receive() to release the buffer.
+ if(0 == tSLInformation.usNumberOfFreeBuffers)
+ {
+ return -2;
+ }
+ else
+ {
+ tSLInformation.usNumberOfFreeBuffers--;
+ return 0;
+ }
+#endif
+}
+
+//*****************************************************************************
+//
+//! socket
+//!
+//! @param domain selects the protocol family which will be used for
+//! communication. On this version only AF_INET is supported
+//! @param type specifies the communication semantics. On this version
+//! only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW are supported
+//! @param protocol specifies a particular protocol to be used with the
+//! socket IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW are
+//! supported.
+//!
+//! @return On success, socket handle that is used for consequent socket
+//! operations. On error, -1 is returned.
+//!
+//! @brief create an endpoint for communication
+//! The socket function creates a socket that is bound to a specific
+//! transport service provider. This function is called by the
+//! application layer to obtain a socket handle.
+//
+//*****************************************************************************
+
+INT16 socket(INT32 domain, INT32 type, INT32 protocol)
+{
+ INT32 ret;
+ UINT8 *ptr, *args;
+
+ ret = EFAIL;
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (ptr + HEADERS_SIZE_CMD);
+
+ // Fill in HCI packet structure
+ args = UINT32_TO_STREAM(args, domain);
+ args = UINT32_TO_STREAM(args, type);
+ args = UINT32_TO_STREAM(args, protocol);
+
+ // Initiate a HCI command
+ hci_command_send(HCI_CMND_SOCKET, ptr, SOCKET_OPEN_PARAMS_LEN);
+
+ // Since we are in blocking state - wait for event complete
+ SimpleLinkWaitEvent(HCI_CMND_SOCKET, &ret);
+
+ // Process the event
+ errno = ret;
+
+ set_socket_active_status(ret, SOCKET_STATUS_ACTIVE);
+
+ return(ret);
+}
+
+//*****************************************************************************
+//
+//! closesocket
+//!
+//! @param sd socket handle.
+//!
+//! @return On success, zero is returned. On error, -1 is returned.
+//!
+//! @brief The socket function closes a created socket.
+//
+//*****************************************************************************
+
+INT32 closesocket(INT32 sd)
+{
+ INT32 ret;
+ UINT8 *ptr, *args;
+
+ ret = EFAIL;
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (ptr + HEADERS_SIZE_CMD);
+
+ // Fill in HCI packet structure
+ args = UINT32_TO_STREAM(args, sd);
+
+ // Initiate a HCI command
+ hci_command_send(HCI_CMND_CLOSE_SOCKET,
+ ptr, SOCKET_CLOSE_PARAMS_LEN);
+
+ // Since we are in blocking state - wait for event complete
+ SimpleLinkWaitEvent(HCI_CMND_CLOSE_SOCKET, &ret);
+ errno = ret;
+
+ // since 'close' call may result in either OK (and then it closed) or error
+ // mark this socket as invalid
+ set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);
+
+ return(ret);
+}
+
+//*****************************************************************************
+//
+//! accept
+//!
+//! @param[in] sd socket descriptor (handle)
+//! @param[out] addr the argument addr is a pointer to a sockaddr structure
+//! This structure is filled in with the address of the
+//! peer socket, as known to the communications layer.
+//! determined. The exact format of the address returned
+//! addr is by the socket's address sockaddr.
+//! On this version only AF_INET is supported.
+//! This argument returns in network order.
+//! @param[out] addrlen the addrlen argument is a value-result argument:
+//! it should initially contain the size of the structure
+//! pointed to by addr.
+//!
+//! @return For socket in blocking mode:
+//! On success, socket handle. on failure negative
+//! For socket in non-blocking mode:
+//! - On connection establishment, socket handle
+//! - On connection pending, SOC_IN_PROGRESS (-2)
+//! - On failure, SOC_ERROR (-1)
+//!
+//! @brief accept a connection on a socket:
+//! This function is used with connection-based socket types
+//! (SOCK_STREAM). It extracts the first connection request on the
+//! queue of pending connections, creates a new connected socket, and
+//! returns a new file descriptor referring to that socket.
+//! The newly created socket is not in the listening state.
+//! The original socket sd is unaffected by this call.
+//! The argument sd is a socket that has been created with socket(),
+//! bound to a local address with bind(), and is listening for
+//! connections after a listen(). The argument addr is a pointer
+//! to a sockaddr structure. This structure is filled in with the
+//! address of the peer socket, as known to the communications layer.
+//! The exact format of the address returned addr is determined by the
+//! socket's address family. The addrlen argument is a value-result
+//! argument: it should initially contain the size of the structure
+//! pointed to by addr, on return it will contain the actual
+//! length (in bytes) of the address returned.
+//!
+//! @sa socket ; bind ; listen
+//
+//*****************************************************************************
+
+INT32 accept(INT32 sd, sockaddr *addr, socklen_t *addrlen)
+{
+ INT32 ret;
+ UINT8 *ptr, *args;
+ tBsdReturnParams tAcceptReturnArguments;
+
+ ret = EFAIL;
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (ptr + HEADERS_SIZE_CMD);
+
+ // Fill in temporary command buffer
+ args = UINT32_TO_STREAM(args, sd);
+
+ // Initiate a HCI command
+ hci_command_send(HCI_CMND_ACCEPT,
+ ptr, SOCKET_ACCEPT_PARAMS_LEN);
+
+ // Since we are in blocking state - wait for event complete
+ SimpleLinkWaitEvent(HCI_CMND_ACCEPT, &tAcceptReturnArguments);
+
+
+ // need specify return parameters!!!
+ memcpy(addr, &tAcceptReturnArguments.tSocketAddress, ASIC_ADDR_LEN);
+ *addrlen = ASIC_ADDR_LEN;
+ errno = tAcceptReturnArguments.iStatus;
+ ret = errno;
+
+ // if succeeded, iStatus = new socket descriptor. otherwise - error number
+ if(M_IS_VALID_SD(ret))
+ {
+ set_socket_active_status(ret, SOCKET_STATUS_ACTIVE);
+ }
+ else
+ {
+ set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);
+ }
+
+ return(ret);
+}
+
+//*****************************************************************************
+//
+//! bind
+//!
+//! @param[in] sd socket descriptor (handle)
+//! @param[out] addr specifies the destination address. On this version
+//! only AF_INET is supported.
+//! @param[out] addrlen contains the size of the structure pointed to by addr.
+//!
+//! @return On success, zero is returned. On error, -1 is returned.
+//!
+//! @brief assign a name to a socket
+//! This function gives the socket the local address addr.
+//! addr is addrlen bytes long. Traditionally, this is called when a
+//! socket is created with socket, it exists in a name space (address
+//! family) but has no name assigned.
+//! It is necessary to assign a local address before a SOCK_STREAM
+//! socket may receive connections.
+//!
+//! @sa socket ; accept ; listen
+//
+//*****************************************************************************
+
+INT32 bind(INT32 sd, const sockaddr *addr, INT32 addrlen)
+{
+ INT32 ret;
+ UINT8 *ptr, *args;
+
+ ret = EFAIL;
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (ptr + HEADERS_SIZE_CMD);
+
+ addrlen = ASIC_ADDR_LEN;
+
+ // Fill in temporary command buffer
+ args = UINT32_TO_STREAM(args, sd);
+ args = UINT32_TO_STREAM(args, 0x00000008);
+ args = UINT32_TO_STREAM(args, addrlen);
+ ARRAY_TO_STREAM(args, ((UINT8 *)addr), addrlen);
+
+ // Initiate a HCI command
+ hci_command_send(HCI_CMND_BIND,
+ ptr, SOCKET_BIND_PARAMS_LEN);
+
+ // Since we are in blocking state - wait for event complete
+ SimpleLinkWaitEvent(HCI_CMND_BIND, &ret);
+
+ errno = ret;
+
+ return(ret);
+}
+
+//*****************************************************************************
+//
+//! listen
+//!
+//! @param[in] sd socket descriptor (handle)
+//! @param[in] backlog specifies the listen queue depth. On this version
+//! backlog is not supported.
+//! @return On success, zero is returned. On error, -1 is returned.
+//!
+//! @brief listen for connections on a socket
+//! The willingness to accept incoming connections and a queue
+//! limit for incoming connections are specified with listen(),
+//! and then the connections are accepted with accept.
+//! The listen() call applies only to sockets of type SOCK_STREAM
+//! The backlog parameter defines the maximum length the queue of
+//! pending connections may grow to.
+//!
+//! @sa socket ; accept ; bind
+//!
+//! @note On this version, backlog is not supported
+//
+//*****************************************************************************
+
+INT32 listen(INT32 sd, INT32 backlog)
+{
+ INT32 ret;
+ UINT8 *ptr, *args;
+
+ ret = EFAIL;
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (ptr + HEADERS_SIZE_CMD);
+
+ // Fill in temporary command buffer
+ args = UINT32_TO_STREAM(args, sd);
+ args = UINT32_TO_STREAM(args, backlog);
+
+ // Initiate a HCI command
+ hci_command_send(HCI_CMND_LISTEN,
+ ptr, SOCKET_LISTEN_PARAMS_LEN);
+
+ // Since we are in blocking state - wait for event complete
+ SimpleLinkWaitEvent(HCI_CMND_LISTEN, &ret);
+ errno = ret;
+
+ return(ret);
+}
+
+//*****************************************************************************
+//
+//! gethostbyname
+//!
+//! @param[in] hostname host name
+//! @param[in] usNameLen name length
+//! @param[out] out_ip_addr This parameter is filled in with host IP address.
+//! In case that host name is not resolved,
+//! out_ip_addr is zero.
+//! @return On success, positive is returned. On error, negative is returned
+//!
+//! @brief Get host IP by name. Obtain the IP Address of machine on network,
+//! by its name.
+//!
+//! @note On this version, only blocking mode is supported. Also note that
+//! the function requires DNS server to be configured prior to its usage.
+//
+//*****************************************************************************
+
+#ifndef CC3000_TINY_DRIVER
+INT16 gethostbyname(CHAR * hostname, UINT16 usNameLen,
+ UINT32* out_ip_addr)
+{
+ tBsdGethostbynameParams ret;
+ UINT8 *ptr, *args;
+
+ errno = EFAIL;
+
+ if (usNameLen > HOSTNAME_MAX_LENGTH)
+ {
+ return errno;
+ }
+
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
+
+ // Fill in HCI packet structure
+ args = UINT32_TO_STREAM(args, 8);
+ args = UINT32_TO_STREAM(args, usNameLen);
+ ARRAY_TO_STREAM(args, hostname, usNameLen);
+
+ // Initiate a HCI command
+ hci_command_send(HCI_CMND_GETHOSTNAME, ptr, SOCKET_GET_HOST_BY_NAME_PARAMS_LEN
+ + usNameLen - 1);
+
+ // Since we are in blocking state - wait for event complete
+ SimpleLinkWaitEvent(HCI_EVNT_BSD_GETHOSTBYNAME, &ret);
+
+ errno = ret.retVal;
+
+ (*((INT32*)out_ip_addr)) = ret.outputAddress;
+
+ return (errno);
+
+}
+#endif
+
+//*****************************************************************************
+//
+//! connect
+//!
+//! @param[in] sd socket descriptor (handle)
+//! @param[in] addr specifies the destination addr. On this version
+//! only AF_INET is supported.
+//! @param[out] addrlen contains the size of the structure pointed to by addr
+//! @return On success, zero is returned. On error, -1 is returned
+//!
+//! @brief initiate a connection on a socket
+//! Function connects the socket referred to by the socket descriptor
+//! sd, to the address specified by addr. The addrlen argument
+//! specifies the size of addr. The format of the address in addr is
+//! determined by the address space of the socket. If it is of type
+//! SOCK_DGRAM, this call specifies the peer with which the socket is
+//! to be associated; this address is that to which datagrams are to be
+//! sent, and the only address from which datagrams are to be received.
+//! If the socket is of type SOCK_STREAM, this call attempts to make a
+//! connection to another socket. The other socket is specified by
+//! address, which is an address in the communications space of the
+//! socket. Note that the function implements only blocking behavior
+//! thus the caller will be waiting either for the connection
+//! establishment or for the connection establishment failure.
+//!
+//! @sa socket
+//
+//*****************************************************************************
+
+INT32 connect(INT32 sd, const sockaddr *addr, INT32 addrlen)
+{
+ INT32 ret;
+ UINT8 *ptr, *args;
+
+ ret = EFAIL;
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
+ addrlen = 8;
+
+ // Fill in temporary command buffer
+ args = UINT32_TO_STREAM(args, sd);
+ args = UINT32_TO_STREAM(args, 0x00000008);
+ args = UINT32_TO_STREAM(args, addrlen);
+ ARRAY_TO_STREAM(args, ((UINT8 *)addr), addrlen);
+
+ // Initiate a HCI command
+ hci_command_send(HCI_CMND_CONNECT,
+ ptr, SOCKET_CONNECT_PARAMS_LEN);
+
+ // Since we are in blocking state - wait for event complete
+ SimpleLinkWaitEvent(HCI_CMND_CONNECT, &ret);
+
+ errno = ret;
+
+ return((INT32)ret);
+}
+
+
+//*****************************************************************************
+//
+//! select
+//!
+//! @param[in] nfds the highest-numbered file descriptor in any of the
+//! three sets, plus 1.
+//! @param[out] writesds socket descriptors list for write monitoring
+//! @param[out] readsds socket descriptors list for read monitoring
+//! @param[out] exceptsds socket descriptors list for exception monitoring
+//! @param[in] timeout is an upper bound on the amount of time elapsed
+//! before select() returns. Null means infinity
+//! timeout. The minimum timeout is 5 milliseconds,
+//! less than 5 milliseconds will be set
+//! automatically to 5 milliseconds.
+//! @return On success, select() returns the number of file descriptors
+//! contained in the three returned descriptor sets (that is, the
+//! total number of bits that are set in readfds, writefds,
+//! exceptfds) which may be zero if the timeout expires before
+//! anything interesting happens.
+//! On error, -1 is returned.
+//! *readsds - return the sockets on which Read request will
+//! return without delay with valid data.
+//! *writesds - return the sockets on which Write request
+//! will return without delay.
+//! *exceptsds - return the sockets which closed recently.
+//!
+//! @brief Monitor socket activity
+//! Select allow a program to monitor multiple file descriptors,
+//! waiting until one or more of the file descriptors become
+//! "ready" for some class of I/O operation
+//!
+//! @Note If the timeout value set to less than 5ms it will automatically set
+//! to 5ms to prevent overload of the system
+//!
+//! @sa socket
+//
+//*****************************************************************************
+
+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);
+ }
+}
+
+//*****************************************************************************
+//
+//! setsockopt
+//!
+//! @param[in] sd socket handle
+//! @param[in] level defines the protocol level for this option
+//! @param[in] optname defines the option name to Interrogate
+//! @param[in] optval specifies a value for the option
+//! @param[in] optlen specifies the length of the option value
+//! @return On success, zero is returned. On error, -1 is returned
+//!
+//! @brief set socket options
+//! This function manipulate the options associated with a socket.
+//! Options may exist at multiple protocol levels; they are always
+//! present at the uppermost socket level.
+//! When manipulating socket options the level at which the option
+//! resides and the name of the option must be specified.
+//! To manipulate options at the socket level, level is specified as
+//! SOL_SOCKET. To manipulate options at any other level the protocol
+//! number of the appropriate protocol controlling the option is
+//! supplied. For example, to indicate that an option is to be
+//! interpreted by the TCP protocol, level should be set to the
+//! protocol number of TCP;
+//! The parameters optval and optlen are used to access optval -
+//! use for setsockopt(). For getsockopt() they identify a buffer
+//! in which the value for the requested option(s) are to
+//! be returned. For getsockopt(), optlen is a value-result
+//! parameter, initially containing the size of the buffer
+//! pointed to by option_value, and modified on return to
+//! indicate the actual size of the value returned. If no option
+//! value is to be supplied or returned, option_value may be NULL.
+//!
+//! @Note On this version the following two socket options are enabled:
+//! The only protocol level supported in this version
+//! is SOL_SOCKET (level).
+//! 1. SOCKOPT_RECV_TIMEOUT (optname)
+//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout
+//! in milliseconds.
+//! In that case optval should be pointer to UINT32.
+//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on
+//! or off.
+//! In that case optval should be SOCK_ON or SOCK_OFF (optval).
+//!
+//! @sa getsockopt
+//
+//*****************************************************************************
+
+#ifndef CC3000_TINY_DRIVER
+INT16 setsockopt(INT32 sd, INT32 level, INT32 optname, const void *optval,
+ socklen_t optlen)
+{
+ INT32 ret;
+ UINT8 *ptr, *args;
+
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (ptr + HEADERS_SIZE_CMD);
+
+ // Fill in temporary command buffer
+ args = UINT32_TO_STREAM(args, sd);
+ args = UINT32_TO_STREAM(args, level);
+ args = UINT32_TO_STREAM(args, optname);
+ args = UINT32_TO_STREAM(args, 0x00000008);
+ args = UINT32_TO_STREAM(args, optlen);
+ ARRAY_TO_STREAM(args, ((UINT8 *)optval), optlen);
+
+ // Initiate a HCI command
+ hci_command_send(HCI_CMND_SETSOCKOPT,
+ ptr, SOCKET_SET_SOCK_OPT_PARAMS_LEN + optlen);
+
+ // Since we are in blocking state - wait for event complete
+ SimpleLinkWaitEvent(HCI_CMND_SETSOCKOPT, &ret);
+
+ if (ret >= 0)
+ {
+ return (0);
+ }
+ else
+ {
+ errno = ret;
+ return ret;
+ }
+}
+#endif
+
+//*****************************************************************************
+//
+//! getsockopt
+//!
+//! @param[in] sd socket handle
+//! @param[in] level defines the protocol level for this option
+//! @param[in] optname defines the option name to Interrogate
+//! @param[out] optval specifies a value for the option
+//! @param[out] optlen specifies the length of the option value
+//! @return On success, zero is returned. On error, -1 is returned
+//!
+//! @brief set socket options
+//! This function manipulate the options associated with a socket.
+//! Options may exist at multiple protocol levels; they are always
+//! present at the uppermost socket level.
+//! When manipulating socket options the level at which the option
+//! resides and the name of the option must be specified.
+//! To manipulate options at the socket level, level is specified as
+//! SOL_SOCKET. To manipulate options at any other level the protocol
+//! number of the appropriate protocol controlling the option is
+//! supplied. For example, to indicate that an option is to be
+//! interpreted by the TCP protocol, level should be set to the
+//! protocol number of TCP;
+//! The parameters optval and optlen are used to access optval -
+//! use for setsockopt(). For getsockopt() they identify a buffer
+//! in which the value for the requested option(s) are to
+//! be returned. For getsockopt(), optlen is a value-result
+//! parameter, initially containing the size of the buffer
+//! pointed to by option_value, and modified on return to
+//! indicate the actual size of the value returned. If no option
+//! value is to be supplied or returned, option_value may be NULL.
+//!
+//! @Note On this version the following two socket options are enabled:
+//! The only protocol level supported in this version
+//! is SOL_SOCKET (level).
+//! 1. SOCKOPT_RECV_TIMEOUT (optname)
+//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout
+//! in milliseconds.
+//! In that case optval should be pointer to UINT32.
+//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on
+//! or off.
+//! In that case optval should be SOCK_ON or SOCK_OFF (optval).
+//!
+//! @sa setsockopt
+//
+//*****************************************************************************
+
+INT16 getsockopt (INT32 sd, INT32 level, INT32 optname, void *optval, socklen_t *optlen)
+{
+ UINT8 *ptr, *args;
+ tBsdGetSockOptReturnParams tRetParams;
+
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (ptr + HEADERS_SIZE_CMD);
+
+ // Fill in temporary command buffer
+ args = UINT32_TO_STREAM(args, sd);
+ args = UINT32_TO_STREAM(args, level);
+ args = UINT32_TO_STREAM(args, optname);
+
+ // Initiate a HCI command
+ hci_command_send(HCI_CMND_GETSOCKOPT,
+ ptr, SOCKET_GET_SOCK_OPT_PARAMS_LEN);
+
+ // Since we are in blocking state - wait for event complete
+ SimpleLinkWaitEvent(HCI_CMND_GETSOCKOPT, &tRetParams);
+
+ if (((INT8)tRetParams.iStatus) >= 0)
+ {
+ *optlen = 4;
+ memcpy(optval, tRetParams.ucOptValue, 4);
+ return (0);
+ }
+ else
+ {
+ errno = tRetParams.iStatus;
+ return errno;
+ }
+}
+
+//*****************************************************************************
+//
+//! simple_link_recv
+//!
+//! @param sd socket handle
+//! @param buf read buffer
+//! @param len buffer length
+//! @param flags indicates blocking or non-blocking operation
+//! @param from pointer to an address structure indicating source address
+//! @param fromlen source address structure size
+//!
+//! @return Return the number of bytes received, or -1 if an error
+//! occurred
+//!
+//! @brief Read data from socket
+//! Return the length of the message on successful completion.
+//! If a message is too long to fit in the supplied buffer,
+//! excess bytes may be discarded depending on the type of
+//! socket the message is received from
+//
+//*****************************************************************************
+INT16 simple_link_recv(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from,
+ socklen_t *fromlen, INT32 opcode)
+{
+ UINT8 *ptr, *args;
+ tBsdReadReturnParams tSocketReadEvent;
+
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (ptr + HEADERS_SIZE_CMD);
+
+ // Fill in HCI packet structure
+ args = UINT32_TO_STREAM(args, sd);
+ args = UINT32_TO_STREAM(args, len);
+ args = UINT32_TO_STREAM(args, flags);
+
+ // Generate the read command, and wait for the
+ hci_command_send(opcode, ptr, SOCKET_RECV_FROM_PARAMS_LEN);
+
+ // Since we are in blocking state - wait for event complete
+ SimpleLinkWaitEvent(opcode, &tSocketReadEvent);
+
+ // In case the number of bytes is more then zero - read data
+ if (tSocketReadEvent.iNumberOfBytes > 0)
+ {
+ // Wait for the data in a synchronous way. Here we assume that the bug is
+ // big enough to store also parameters of receive from too....
+ SimpleLinkWaitData(buf, (UINT8 *)from, (UINT8 *)fromlen);
+ }
+
+ errno = tSocketReadEvent.iNumberOfBytes;
+
+ return(tSocketReadEvent.iNumberOfBytes);
+}
+
+//*****************************************************************************
+//
+//! recv
+//!
+//! @param[in] sd socket handle
+//! @param[out] buf Points to the buffer where the message should be stored
+//! @param[in] len Specifies the length in bytes of the buffer pointed to
+//! by the buffer argument.
+//! @param[in] flags Specifies the type of message reception.
+//! On this version, this parameter is not supported.
+//!
+//! @return Return the number of bytes received, or -1 if an error
+//! occurred
+//!
+//! @brief function receives a message from a connection-mode socket
+//!
+//! @sa recvfrom
+//!
+//! @Note On this version, only blocking mode is supported.
+//
+//*****************************************************************************
+
+INT16 recv(INT32 sd, void *buf, INT32 len, INT32 flags)
+{
+ return(simple_link_recv(sd, buf, len, flags, NULL, NULL, HCI_CMND_RECV));
+}
+
+//*****************************************************************************
+//
+//! recvfrom
+//!
+//! @param[in] sd socket handle
+//! @param[out] buf Points to the buffer where the message should be stored
+//! @param[in] len Specifies the length in bytes of the buffer pointed to
+//! by the buffer argument.
+//! @param[in] flags Specifies the type of message reception.
+//! On this version, this parameter is not supported.
+//! @param[in] from pointer to an address structure indicating the source
+//! address: sockaddr. On this version only AF_INET is
+//! supported.
+//! @param[in] fromlen source address tructure size
+//!
+//! @return Return the number of bytes received, or -1 if an error
+//! occurred
+//!
+//! @brief read data from socket
+//! function receives a message from a connection-mode or
+//! connectionless-mode socket. Note that raw sockets are not
+//! supported.
+//!
+//! @sa recv
+//!
+//! @Note On this version, only blocking mode is supported.
+//
+//*****************************************************************************
+INT16 recvfrom(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from,
+ socklen_t *fromlen)
+{
+ return(simple_link_recv(sd, buf, len, flags, from, fromlen,
+ HCI_CMND_RECVFROM));
+}
+
+//*****************************************************************************
+//
+//! 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);
+}
+
+
+//*****************************************************************************
+//
+//! send
+//!
+//! @param sd socket handle
+//! @param buf Points to a buffer containing the message to be sent
+//! @param len message size in bytes
+//! @param flags On this version, this parameter is not supported
+//!
+//! @return Return the number of bytes transmitted, or -1 if an
+//! error occurred
+//!
+//! @brief Write data to TCP socket
+//! This function is used to transmit a message to another
+//! socket.
+//!
+//! @Note On this version, only blocking mode is supported.
+//!
+//! @sa sendto
+//
+//*****************************************************************************
+
+INT16 send(INT32 sd, const void *buf, INT32 len, INT32 flags)
+{
+ return(simple_link_send(sd, buf, len, flags, NULL, 0, HCI_CMND_SEND));
+}
+
+//*****************************************************************************
+//
+//! sendto
+//!
+//! @param sd socket handle
+//! @param buf Points to a buffer containing the message to be sent
+//! @param len message size in bytes
+//! @param flags On this version, this parameter is not supported
+//! @param to pointer to an address structure indicating the destination
+//! address: sockaddr. On this version only AF_INET is
+//! supported.
+//! @param tolen destination address structure size
+//!
+//! @return Return the number of bytes transmitted, or -1 if an
+//! error occurred
+//!
+//! @brief Write data to TCP socket
+//! This function is used to transmit a message to another
+//! socket.
+//!
+//! @Note On this version, only blocking mode is supported.
+//!
+//! @sa send
+//
+//*****************************************************************************
+
+INT16 sendto(INT32 sd, const void *buf, INT32 len, INT32 flags, const sockaddr *to,
+ socklen_t tolen)
+{
+ return(simple_link_send(sd, buf, len, flags, to, tolen, HCI_CMND_SENDTO));
+}
+
+//*****************************************************************************
+//
+//! mdnsAdvertiser
+//!
+//! @param[in] mdnsEnabled flag to enable/disable the mDNS feature
+//! @param[in] deviceServiceName Service name as part of the published
+//! canonical domain name
+//! @param[in] deviceServiceNameLength Length of the service name - up to 32 chars
+//!
+//!
+//! @return On success, zero is returned, return SOC_ERROR if socket was not
+//! opened successfully, or if an error occurred.
+//!
+//! @brief Set CC3000 in mDNS advertiser mode in order to advertise itself.
+//
+//*****************************************************************************
+
+INT16 mdnsAdvertiser(UINT16 mdnsEnabled, CHAR * deviceServiceName, UINT16 deviceServiceNameLength)
+{
+ INT8 ret;
+ UINT8 *pTxBuffer, *pArgs;
+
+ if (deviceServiceNameLength > MDNS_DEVICE_SERVICE_MAX_LENGTH)
+ {
+ return EFAIL;
+ }
+
+ pTxBuffer = tSLInformation.pucTxCommandBuffer;
+ pArgs = (pTxBuffer + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
+
+ // Fill in HCI packet structure
+ pArgs = UINT32_TO_STREAM(pArgs, mdnsEnabled);
+ pArgs = UINT32_TO_STREAM(pArgs, 8);
+ pArgs = UINT32_TO_STREAM(pArgs, deviceServiceNameLength);
+ ARRAY_TO_STREAM(pArgs, deviceServiceName, deviceServiceNameLength);
+
+ // Initiate a HCI command
+ hci_command_send(HCI_CMND_MDNS_ADVERTISE, pTxBuffer, SOCKET_MDNS_ADVERTISE_PARAMS_LEN + deviceServiceNameLength);
+
+ // Since we are in blocking state - wait for event complete
+ SimpleLinkWaitEvent(HCI_EVNT_MDNS_ADVERTISE, &ret);
+
+ return ret;
+
+}
+
+
+//*****************************************************************************
+//
+//! getmssvalue
+//!
+//! @param[in] sd socket descriptor
+//!
+//! @return On success, returns the MSS value of a TCP connection
+//!
+//! @brief Returns the MSS value of a TCP connection according to the socket descriptor
+//
+//*****************************************************************************
+UINT16 getmssvalue (INT32 sd)
+{
+ UINT8 *ptr, *args;
+ UINT16 ret;
+
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (ptr + HEADERS_SIZE_CMD);
+
+ // Fill in temporary command buffer
+ args = UINT32_TO_STREAM(args, sd);
+
+ // Initiate a HCI command
+ hci_command_send(HCI_CMND_GETMSSVALUE, ptr, SOCKET_GET_MSS_VALUE_PARAMS_LEN);
+
+ // Since we are in blocking state - wait for event complete
+ SimpleLinkWaitEvent(HCI_EVNT_GETMSSVALUE, &ret);
+
+ return ret;
+}
diff --git a/drivers/cc3000/src/wlan.c b/drivers/cc3000/src/wlan.c
new file mode 100644
index 0000000000..0514d11502
--- /dev/null
+++ b/drivers/cc3000/src/wlan.c
@@ -0,0 +1,1252 @@
+/*****************************************************************************
+*
+* wlan.c - CC3000 Host Driver Implementation.
+* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the
+* distribution.
+*
+* Neither the name of Texas Instruments Incorporated nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*****************************************************************************/
+
+//*****************************************************************************
+//
+//! \addtogroup wlan_api
+//! @{
+//
+//*****************************************************************************
+
+#include <string.h>
+#include "wlan.h"
+#include "hci.h"
+#include "ccspi.h"
+#include "socket.h"
+#include "nvmem.h"
+#include "security.h"
+#include "evnt_handler.h"
+
+
+volatile sSimplLinkInformation tSLInformation;
+
+#define SMART_CONFIG_PROFILE_SIZE 67 // 67 = 32 (max ssid) + 32 (max key) + 1 (SSID length) + 1 (security type) + 1 (key length)
+
+#ifndef CC3000_UNENCRYPTED_SMART_CONFIG
+UINT8 key[AES128_KEY_SIZE];
+UINT8 profileArray[SMART_CONFIG_PROFILE_SIZE];
+#endif //CC3000_UNENCRYPTED_SMART_CONFIG
+
+/* patches type */
+#define PATCHES_HOST_TYPE_WLAN_DRIVER 0x01
+#define PATCHES_HOST_TYPE_WLAN_FW 0x02
+#define PATCHES_HOST_TYPE_BOOTLOADER 0x03
+
+#define SL_SET_SCAN_PARAMS_INTERVAL_LIST_SIZE (16)
+#define SL_SIMPLE_CONFIG_PREFIX_LENGTH (3)
+#define ETH_ALEN (6)
+#define MAXIMAL_SSID_LENGTH (32)
+
+#define SL_PATCHES_REQUEST_DEFAULT (0)
+#define SL_PATCHES_REQUEST_FORCE_HOST (1)
+#define SL_PATCHES_REQUEST_FORCE_NONE (2)
+
+
+#define WLAN_SEC_UNSEC (0)
+#define WLAN_SEC_WEP (1)
+#define WLAN_SEC_WPA (2)
+#define WLAN_SEC_WPA2 (3)
+
+
+#define WLAN_SL_INIT_START_PARAMS_LEN (1)
+#define WLAN_PATCH_PARAMS_LENGTH (8)
+#define WLAN_SET_CONNECTION_POLICY_PARAMS_LEN (12)
+#define WLAN_DEL_PROFILE_PARAMS_LEN (4)
+#define WLAN_SET_MASK_PARAMS_LEN (4)
+#define WLAN_SET_SCAN_PARAMS_LEN (100)
+#define WLAN_GET_SCAN_RESULTS_PARAMS_LEN (4)
+#define WLAN_ADD_PROFILE_NOSEC_PARAM_LEN (24)
+#define WLAN_ADD_PROFILE_WEP_PARAM_LEN (36)
+#define WLAN_ADD_PROFILE_WPA_PARAM_LEN (44)
+#define WLAN_CONNECT_PARAM_LEN (29)
+#define WLAN_SMART_CONFIG_START_PARAMS_LEN (4)
+
+
+
+
+//*****************************************************************************
+//
+//! SimpleLink_Init_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 Send HCI_CMND_SIMPLE_LINK_START to CC3000
+//
+//*****************************************************************************
+static void SimpleLink_Init_Start(UINT16 usPatchesAvailableAtHost)
+{
+ UINT8 *ptr;
+ UINT8 *args;
+
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (UINT8 *)(ptr + HEADERS_SIZE_CMD);
+
+ UINT8_TO_STREAM(args, ((usPatchesAvailableAtHost) ? SL_PATCHES_REQUEST_FORCE_NONE : SL_PATCHES_REQUEST_DEFAULT));
+
+ // IRQ Line asserted - send HCI_CMND_SIMPLE_LINK_START to CC3000
+ hci_command_send(HCI_CMND_SIMPLE_LINK_START, ptr, WLAN_SL_INIT_START_PARAMS_LEN);
+
+ SimpleLinkWaitEvent(HCI_CMND_SIMPLE_LINK_START, 0);
+}
+
+
+
+//*****************************************************************************
+//
+//! wlan_init
+//!
+//! @param sWlanCB Asynchronous events callback.
+//! 0 no event call back.
+//! -call back parameters:
+//! 1) event_type: HCI_EVNT_WLAN_UNSOL_CONNECT connect event,
+//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event,
+//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE config done,
+//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp report,
+//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report OR
+//! HCI_EVNT_WLAN_KEEPALIVE keepalive.
+//! 2) data: pointer to extra data that received by the event
+//! (NULL no data).
+//! 3) length: data length.
+//! -Events with extra data:
+//! HCI_EVNT_WLAN_UNSOL_DHCP: 4 bytes IP, 4 bytes Mask,
+//! 4 bytes default gateway, 4 bytes DHCP server and 4 bytes
+//! for DNS server.
+//! HCI_EVNT_WLAN_ASYNC_PING_REPORT: 4 bytes Packets sent,
+//! 4 bytes Packets received, 4 bytes Min round time,
+//! 4 bytes Max round time and 4 bytes for Avg round time.
+//!
+//! @param sFWPatches 0 no patch or pointer to FW patches
+//! @param sDriverPatches 0 no patch or pointer to driver patches
+//! @param sBootLoaderPatches 0 no patch or pointer to bootloader patches
+//! @param sReadWlanInterruptPin init callback. the callback read wlan
+//! interrupt status.
+//! @param sWlanInterruptEnable init callback. the callback enable wlan
+//! interrupt.
+//! @param sWlanInterruptDisable init callback. the callback disable wlan
+//! interrupt.
+//! @param sWriteWlanPin init callback. the callback write value
+//! to device pin.
+//!
+//! @return none
+//!
+//! @sa wlan_set_event_mask , wlan_start , wlan_stop
+//!
+//! @brief Initialize wlan driver
+//!
+//! @warning This function must be called before ANY other wlan driver function
+//
+//*****************************************************************************
+
+void wlan_init( tWlanCB sWlanCB,
+ tFWPatches sFWPatches,
+ tDriverPatches sDriverPatches,
+ tBootLoaderPatches sBootLoaderPatches,
+ tWlanReadInteruptPin sReadWlanInterruptPin,
+ tWlanInterruptEnable sWlanInterruptEnable,
+ tWlanInterruptDisable sWlanInterruptDisable,
+ tWriteWlanPin sWriteWlanPin)
+{
+
+ tSLInformation.sFWPatches = sFWPatches;
+ tSLInformation.sDriverPatches = sDriverPatches;
+ tSLInformation.sBootLoaderPatches = sBootLoaderPatches;
+
+ // 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 = (UINT8 *)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
+//!
+//
+//*****************************************************************************
+#define TIMEOUT (500000)
+
+int wlan_start(UINT16 usPatchesAvailableAtHost)
+{
+
+ UINT32 ulSpiIRQState;
+ UINT32 wlan_timeout;
+
+ 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 = (UINT8 *)wlan_tx_buffer;
+
+ // init spi
+ SpiOpen(SpiReceiveHandler);
+
+ // Check the IRQ line
+ ulSpiIRQState = tSLInformation.ReadWlanInterruptPin();
+
+ // Chip enable: toggle WLAN EN line
+ tSLInformation.WriteWlanPin( WLAN_ENABLE );
+
+ wlan_timeout = TIMEOUT;
+ if (ulSpiIRQState) {
+ // wait till the IRQ line goes low
+ while(tSLInformation.ReadWlanInterruptPin() != 0 && --wlan_timeout)
+ {
+ }
+ }
+ else
+ {
+ // wait till the IRQ line goes high and than low
+ while(tSLInformation.ReadWlanInterruptPin() == 0 && --wlan_timeout)
+ {
+ }
+
+ if (wlan_timeout == 0) {
+ return -1;
+ }
+
+ wlan_timeout = TIMEOUT;
+ while(tSLInformation.ReadWlanInterruptPin() != 0 && --wlan_timeout)
+ {
+ }
+ }
+
+ if (wlan_timeout ==0) {
+ return -1;
+ }
+
+ 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);
+
+ return 0;
+}
+
+
+//*****************************************************************************
+//
+//! wlan_stop
+//!
+//! @param none
+//!
+//! @return none
+//!
+//! @brief Stop WLAN device by putting it into reset state.
+//!
+//! @sa wlan_start
+//
+//*****************************************************************************
+
+void wlan_stop(void)
+{
+ // 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 32 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
+INT32 wlan_connect(UINT32 ulSecType, CHAR *ssid, INT32 ssid_len,
+ UINT8 *bssid, UINT8 *key, INT32 key_len)
+{
+ INT32 ret;
+ UINT8 *ptr;
+ UINT8 *args;
+ UINT8 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
+INT32 wlan_connect(CHAR *ssid, INT32 ssid_len)
+{
+ INT32 ret;
+ UINT8 *ptr;
+ UINT8 *args;
+ UINT8 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
+//
+//*****************************************************************************
+
+INT32 wlan_disconnect()
+{
+ INT32 ret;
+ UINT8 *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
+//
+//*****************************************************************************
+
+INT32 wlan_ioctl_set_connection_policy(UINT32 should_connect_to_open_ap,
+ UINT32 ulShouldUseFastConnect,
+ UINT32 ulUseProfiles)
+{
+ INT32 ret;
+ UINT8 *ptr;
+ UINT8 *args;
+
+ ret = EFAIL;
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (UINT8 *)(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
+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=0;
+ 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);
+}
+#else
+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)
+{
+ return -1;
+}
+#endif
+
+//*****************************************************************************
+//
+//! wlan_ioctl_del_profile
+//!
+//! @param index number of profile to delete
+//!
+//! @return On success, zero is returned. On error, -1 is returned
+//!
+//! @brief Delete WLAN profile
+//!
+//! @Note In order to delete all stored profile, set index to 255.
+//!
+//! @sa wlan_add_profile
+//
+//*****************************************************************************
+
+INT32 wlan_ioctl_del_profile(UINT32 ulIndex)
+{
+ INT32 ret;
+ UINT8 *ptr;
+ UINT8 *args;
+
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (UINT8 *)(ptr + HEADERS_SIZE_CMD);
+
+ // Fill in HCI packet structure
+ args = UINT32_TO_STREAM(args, ulIndex);
+ ret = EFAIL;
+
+ // Initiate a HCI command
+ hci_command_send(HCI_CMND_WLAN_IOCTL_DEL_PROFILE,
+ ptr, WLAN_DEL_PROFILE_PARAMS_LEN);
+
+ // Wait for command complete event
+ SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_DEL_PROFILE, &ret);
+
+ return(ret);
+}
+
+//*****************************************************************************
+//
+//! wlan_ioctl_get_scan_results
+//!
+//! @param[in] scan_timeout parameter not supported
+//! @param[out] ucResults scan results (_wlan_full_scan_results_args_t)
+//!
+//! @return On success, zero is returned. On error, -1 is returned
+//!
+//! @brief Gets entry from scan result table.
+//! The scan results are returned one by one, and each entry
+//! represents a single AP found in the area. The following is a
+//! format of the scan result:
+//! - 4 Bytes: number of networks found
+//! - 4 Bytes: The status of the scan: 0 - aged results,
+//! 1 - results valid, 2 - no results
+//! - 42 bytes: Result entry, where the bytes are arranged as follows:
+//!
+//! - 1 bit isValid - is result valid or not
+//! - 7 bits rssi - RSSI value;
+//! - 2 bits: securityMode - security mode of the AP:
+//! 0 - Open, 1 - WEP, 2 WPA, 3 WPA2
+//! - 6 bits: SSID name length
+//! - 2 bytes: the time at which the entry has entered into
+//! scans result table
+//! - 32 bytes: SSID name
+//! - 6 bytes: BSSID
+//!
+//! @Note scan_timeout, is not supported on this version.
+//!
+//! @sa wlan_ioctl_set_scan_params
+//
+//*****************************************************************************
+
+#ifndef CC3000_TINY_DRIVER
+INT32 wlan_ioctl_get_scan_results(UINT32 ulScanTimeout,
+ UINT8 *ucResults)
+{
+ UINT8 *ptr;
+ UINT8 *args;
+
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (ptr + HEADERS_SIZE_CMD);
+
+ // Fill in temporary command buffer
+ args = UINT32_TO_STREAM(args, ulScanTimeout);
+
+ // Initiate a HCI command
+ hci_command_send(HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS,
+ ptr, WLAN_GET_SCAN_RESULTS_PARAMS_LEN);
+
+ // Wait for command complete event
+ SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS, ucResults);
+
+ return(0);
+}
+#endif
+
+//*****************************************************************************
+//
+//! wlan_ioctl_set_scan_params
+//!
+//! @param uiEnable - start/stop application scan:
+//! 1 = start scan with default interval value of 10 min.
+//! in order to set a different scan interval value apply the value
+//! in milliseconds. minimum 1 second. 0=stop). Wlan reset
+//! (wlan_stop() wlan_start()) is needed when changing scan interval
+//! value. Saved: No
+//! @param uiMinDwellTime minimum dwell time value to be used for each
+//! channel, in milliseconds. Saved: yes
+//! Recommended Value: 100 (Default: 20)
+//! @param uiMaxDwellTime maximum dwell time value to be used for each
+//! channel, in milliseconds. Saved: yes
+//! Recommended Value: 100 (Default: 30)
+//! @param uiNumOfProbeRequests max probe request between dwell time.
+//! Saved: yes. Recommended Value: 5 (Default:2)
+//! @param uiChannelMask bitwise, up to 13 channels (0x1fff).
+//! Saved: yes. Default: 0x7ff
+//! @param uiRSSIThreshold RSSI threshold. Saved: yes (Default: -80)
+//! @param uiSNRThreshold NSR threshold. Saved: yes (Default: 0)
+//! @param uiDefaultTxPower probe Tx power. Saved: yes (Default: 205)
+//! @param aiIntervalList pointer to array with 16 entries (16 channels)
+//! each entry (UINT32) holds timeout between periodic scan
+//! (connection scan) - in millisecond. Saved: yes. Default 2000ms.
+//!
+//! @return On success, zero is returned. On error, -1 is returned
+//!
+//! @brief start and stop scan procedure. Set scan parameters.
+//!
+//! @Note uiDefaultTxPower, is not supported on this version.
+//!
+//! @sa wlan_ioctl_get_scan_results
+//
+//*****************************************************************************
+
+#ifndef CC3000_TINY_DRIVER
+INT32 wlan_ioctl_set_scan_params(UINT32 uiEnable, UINT32 uiMinDwellTime,
+ UINT32 uiMaxDwellTime,
+ UINT32 uiNumOfProbeRequests,
+ UINT32 uiChannelMask,INT32 iRSSIThreshold,
+ UINT32 uiSNRThreshold,
+ UINT32 uiDefaultTxPower,
+ UINT32 *aiIntervalList)
+{
+ UINT32 uiRes;
+ UINT8 *ptr;
+ UINT8 *args;
+
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (ptr + HEADERS_SIZE_CMD);
+
+ // Fill in temporary command buffer
+ args = UINT32_TO_STREAM(args, 36);
+ args = UINT32_TO_STREAM(args, uiEnable);
+ args = UINT32_TO_STREAM(args, uiMinDwellTime);
+ args = UINT32_TO_STREAM(args, uiMaxDwellTime);
+ args = UINT32_TO_STREAM(args, uiNumOfProbeRequests);
+ args = UINT32_TO_STREAM(args, uiChannelMask);
+ args = UINT32_TO_STREAM(args, iRSSIThreshold);
+ args = UINT32_TO_STREAM(args, uiSNRThreshold);
+ args = UINT32_TO_STREAM(args, uiDefaultTxPower);
+ ARRAY_TO_STREAM(args, aiIntervalList, sizeof(UINT32) *
+ SL_SET_SCAN_PARAMS_INTERVAL_LIST_SIZE);
+
+ // Initiate a HCI command
+ hci_command_send(HCI_CMND_WLAN_IOCTL_SET_SCANPARAM,
+ ptr, WLAN_SET_SCAN_PARAMS_LEN);
+
+ // Wait for command complete event
+ SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SET_SCANPARAM, &uiRes);
+
+ return(uiRes);
+}
+#endif
+
+//*****************************************************************************
+//
+//! wlan_set_event_mask
+//!
+//! @param mask mask option:
+//! HCI_EVNT_WLAN_UNSOL_CONNECT connect event
+//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event
+//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE smart config done
+//! HCI_EVNT_WLAN_UNSOL_INIT init done
+//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp event report
+//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report
+//! HCI_EVNT_WLAN_KEEPALIVE keepalive
+//! HCI_EVNT_WLAN_TX_COMPLETE - disable information on end of transmission
+//! Saved: no.
+//!
+//! @return On success, zero is returned. On error, -1 is returned
+//!
+//! @brief Mask event according to bit mask. In case that event is
+//! masked (1), the device will not send the masked event to host.
+//
+//*****************************************************************************
+
+INT32 wlan_set_event_mask(UINT32 ulMask)
+{
+ INT32 ret;
+ UINT8 *ptr;
+ UINT8 *args;
+
+
+ if ((ulMask & HCI_EVNT_WLAN_TX_COMPLETE) == HCI_EVNT_WLAN_TX_COMPLETE)
+ {
+ tSLInformation.InformHostOnTxComplete = 0;
+
+ // Since an event is a virtual event - i.e. it is not coming from CC3000
+ // there is no need to send anything to the device if it was an only event
+ if (ulMask == HCI_EVNT_WLAN_TX_COMPLETE)
+ {
+ return 0;
+ }
+
+ ulMask &= ~HCI_EVNT_WLAN_TX_COMPLETE;
+ ulMask |= HCI_EVNT_WLAN_UNSOL_BASE;
+ }
+ else
+ {
+ tSLInformation.InformHostOnTxComplete = 1;
+ }
+
+ ret = EFAIL;
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (UINT8 *)(ptr + HEADERS_SIZE_CMD);
+
+ // Fill in HCI packet structure
+ args = UINT32_TO_STREAM(args, ulMask);
+
+ // Initiate a HCI command
+ hci_command_send(HCI_CMND_EVENT_MASK,
+ ptr, WLAN_SET_MASK_PARAMS_LEN);
+
+ // Wait for command complete event
+ SimpleLinkWaitEvent(HCI_CMND_EVENT_MASK, &ret);
+
+ return(ret);
+}
+
+//*****************************************************************************
+//
+//! wlan_ioctl_statusget
+//!
+//! @param none
+//!
+//! @return WLAN_STATUS_DISCONNECTED, WLAN_STATUS_SCANING,
+//! STATUS_CONNECTING or WLAN_STATUS_CONNECTED
+//!
+//! @brief get wlan status: disconnected, scanning, connecting or connected
+//
+//*****************************************************************************
+
+#ifndef CC3000_TINY_DRIVER
+INT32 wlan_ioctl_statusget(void)
+{
+ INT32 ret;
+ UINT8 *ptr;
+
+ ret = EFAIL;
+ ptr = tSLInformation.pucTxCommandBuffer;
+
+ hci_command_send(HCI_CMND_WLAN_IOCTL_STATUSGET,
+ ptr, 0);
+
+ // Wait for command complete event
+ SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_STATUSGET, &ret);
+
+ return(ret);
+}
+#endif
+
+//*****************************************************************************
+//
+//! wlan_smart_config_start
+//!
+//! @param algoEncryptedFlag indicates whether the information is encrypted
+//!
+//! @return On success, zero is returned. On error, -1 is returned
+//!
+//! @brief Start to acquire device profile. The device acquire its own
+//! profile, if profile message is found. The acquired AP information
+//! is stored in CC3000 EEPROM only in case AES128 encryption is used.
+//! In case AES128 encryption is not used, a profile is created by
+//! CC3000 internally.
+//!
+//! @Note An asynchronous event - Smart Config Done will be generated as soon
+//! as the process finishes successfully.
+//!
+//! @sa wlan_smart_config_set_prefix , wlan_smart_config_stop
+//
+//*****************************************************************************
+
+INT32 wlan_smart_config_start(UINT32 algoEncryptedFlag)
+{
+ INT32 ret;
+ UINT8 *ptr;
+ UINT8 *args;
+
+ ret = EFAIL;
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (UINT8 *)(ptr + HEADERS_SIZE_CMD);
+
+ // Fill in HCI packet structure
+ args = UINT32_TO_STREAM(args, algoEncryptedFlag);
+ ret = EFAIL;
+
+ hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START, ptr,
+ WLAN_SMART_CONFIG_START_PARAMS_LEN);
+
+ // Wait for command complete event
+ SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START, &ret);
+
+ return(ret);
+}
+
+//*****************************************************************************
+//
+//! wlan_smart_config_stop
+//!
+//! @param algoEncryptedFlag indicates whether the information is encrypted
+//!
+//! @return On success, zero is returned. On error, -1 is returned
+//!
+//! @brief Stop the acquire profile procedure
+//!
+//! @sa wlan_smart_config_start , wlan_smart_config_set_prefix
+//
+//*****************************************************************************
+
+INT32 wlan_smart_config_stop(void)
+{
+ INT32 ret;
+ UINT8 *ptr;
+
+ ret = EFAIL;
+ ptr = tSLInformation.pucTxCommandBuffer;
+
+ hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP, ptr, 0);
+
+ // Wait for command complete event
+ SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP, &ret);
+
+ return(ret);
+}
+
+//*****************************************************************************
+//
+//! wlan_smart_config_set_prefix
+//!
+//! @param newPrefix 3 bytes identify the SSID prefix for the Smart Config.
+//!
+//! @return On success, zero is returned. On error, -1 is returned
+//!
+//! @brief Configure station ssid prefix. The prefix is used internally
+//! in CC3000. It should always be TTT.
+//!
+//! @Note The prefix is stored in CC3000 NVMEM
+//!
+//! @sa wlan_smart_config_start , wlan_smart_config_stop
+//
+//*****************************************************************************
+
+INT32 wlan_smart_config_set_prefix(CHAR* cNewPrefix)
+{
+ INT32 ret;
+ UINT8 *ptr;
+ UINT8 *args;
+
+ ret = EFAIL;
+ ptr = tSLInformation.pucTxCommandBuffer;
+ args = (ptr + HEADERS_SIZE_CMD);
+
+ if (cNewPrefix == NULL)
+ return ret;
+ else // with the new Smart Config, prefix must be TTT
+ {
+ *cNewPrefix = 'T';
+ *(cNewPrefix + 1) = 'T';
+ *(cNewPrefix + 2) = 'T';
+ }
+
+ ARRAY_TO_STREAM(args, cNewPrefix, SL_SIMPLE_CONFIG_PREFIX_LENGTH);
+
+ hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX, ptr,
+ SL_SIMPLE_CONFIG_PREFIX_LENGTH);
+
+ // Wait for command complete event
+ SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX, &ret);
+
+ return(ret);
+}
+
+//*****************************************************************************
+//
+//! wlan_smart_config_process
+//!
+//! @param none
+//!
+//! @return On success, zero is returned. On error, -1 is returned
+//!
+//! @brief process the acquired data and store it as a profile. The acquired
+//! AP information is stored in CC3000 EEPROM encrypted.
+//! The encrypted data is decrypted and stored as a profile.
+//! behavior is as defined by connection policy.
+//
+//*****************************************************************************
+
+
+#ifndef CC3000_UNENCRYPTED_SMART_CONFIG
+INT32 wlan_smart_config_process()
+{
+ INT32 returnValue;
+ UINT32 ssidLen, keyLen;
+ UINT8 *decKeyPtr;
+ UINT8 *ssidPtr;
+
+ // read the key from EEPROM - fileID 12
+ returnValue = aes_read_key(key);
+
+ if (returnValue != 0)
+ return returnValue;
+
+ // read the received data from fileID #13 and parse it according to the followings:
+ // 1) SSID LEN - not encrypted
+ // 2) SSID - not encrypted
+ // 3) KEY LEN - not encrypted. always 32 bytes long
+ // 4) Security type - not encrypted
+ // 5) KEY - encrypted together with true key length as the first byte in KEY
+ // to elaborate, there are two corner cases:
+ // 1) the KEY is 32 bytes long. In this case, the first byte does not represent KEY length
+ // 2) the KEY is 31 bytes long. In this case, the first byte represent KEY length and equals 31
+ returnValue = nvmem_read(NVMEM_SHARED_MEM_FILEID, SMART_CONFIG_PROFILE_SIZE, 0, profileArray);
+
+ if (returnValue != 0)
+ return returnValue;
+
+ ssidPtr = &profileArray[1];
+
+ ssidLen = profileArray[0];
+
+ decKeyPtr = &profileArray[profileArray[0] + 3];
+
+ aes_decrypt(decKeyPtr, key);
+ if (profileArray[profileArray[0] + 1] > 16)
+ aes_decrypt((UINT8 *)(decKeyPtr + 16), key);
+
+ if (*(UINT8 *)(decKeyPtr +31) != 0)
+ {
+ if (*decKeyPtr == 31)
+ {
+ keyLen = 31;
+ decKeyPtr++;
+ }
+ else
+ {
+ keyLen = 32;
+ }
+ }
+ else
+ {
+ keyLen = *decKeyPtr;
+ decKeyPtr++;
+ }
+
+ // add a profile
+ switch (profileArray[profileArray[0] + 2])
+ {
+ case WLAN_SEC_UNSEC://None
+ {
+ returnValue = wlan_add_profile(profileArray[profileArray[0] + 2], // security type
+ ssidPtr, // SSID
+ ssidLen, // SSID length
+ NULL, // BSSID
+ 1, // Priority
+ 0, 0, 0, 0, 0);
+
+ break;
+ }
+
+ case WLAN_SEC_WEP://WEP
+ {
+ returnValue = wlan_add_profile(profileArray[profileArray[0] + 2], // security type
+ ssidPtr, // SSID
+ ssidLen, // SSID length
+ NULL, // BSSID
+ 1, // Priority
+ keyLen, // KEY length
+ 0, // KEY index
+ 0,
+ decKeyPtr, // KEY
+ 0);
+
+ break;
+ }
+
+ case WLAN_SEC_WPA://WPA
+ case WLAN_SEC_WPA2://WPA2
+ {
+ returnValue = wlan_add_profile(WLAN_SEC_WPA2, // security type
+ ssidPtr,
+ ssidLen,
+ NULL, // BSSID
+ 1, // Priority
+ 0x18, // PairwiseCipher
+ 0x1e, // GroupCipher
+ 2, // KEY management
+ decKeyPtr, // KEY
+ keyLen); // KEY length
+
+ break;
+ }
+ }
+
+ return returnValue;
+}
+#endif //CC3000_UNENCRYPTED_SMART_CONFIG
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************