1
0
mirror of https://github.com/arduino/Arduino.git synced 2025-03-21 12:29:23 +01:00

Porting HD API ver. 2.7

This commit is contained in:
Mimmo La Fauci 2012-05-20 23:54:32 +02:00
parent 69387c1b32
commit f1917d85f3
46 changed files with 2859 additions and 960 deletions

View File

@ -53,17 +53,17 @@
<option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.option.optimization.level.187661945" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" value="gnu.c.optimization.level.optimize" valueType="enumerated"/>
<option id="gnu.c.compiler.option.debugging.level.957359437" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" value="gnu.c.debugging.level.max" valueType="enumerated"/>
<option id="avr32.c.compiler.option.mcu.442256180" name="Microcontroller Unit" superClass="avr32.c.compiler.option.mcu" value="-mpart=uc3a1256" valueType="string"/>
<option id="gnu.c.compiler.option.optimization.flags.1362317068" name="Other optimization flags" superClass="gnu.c.compiler.option.optimization.flags" value="-fdata-sections" valueType="string"/>
<option id="gnu.c.compiler.option.optimization.flags.1362317068" name="Other optimization flags" superClass="gnu.c.compiler.option.optimization.flags" value="-fdata-sections -ffunction-sections" valueType="string"/>
<option id="gnu.c.compiler.option.preprocessor.def.symbols.2032815329" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
<listOptionValue builtIn="false" value="BOARD=ARDUINO"/>
<listOptionValue builtIn="false" value="NO_SYS"/>
<listOptionValue builtIn="false" value="_DEBUG_"/>
<listOptionValue builtIn="false" value="_ASSERT_ENABLE_"/>
<listOptionValue builtIn="false" value="EXT_BOARD=SPB104"/>
<listOptionValue builtIn="false" value="WITH_KEY"/>
<listOptionValue builtIn="false" value="WITH_WPA"/>
<listOptionValue builtIn="false" value="WITH_NO_DMA"/>
<listOptionValue builtIn="false" value="DATAFLASH=1"/>
<listOptionValue builtIn="false" value="_INFO_DEBUG_=1"/>
</option>
<option id="gnu.c.compiler.option.include.paths.199111087" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="../src/SOFTWARE_FRAMEWORK/DRIVERS/PDCA"/>
@ -109,12 +109,12 @@
<option id="gnu.c.link.option.paths.1433794230" name="Library search path (-L)" superClass="gnu.c.link.option.paths" valueType="libPaths">
<listOptionValue builtIn="false" value="../src/SOFTWARE_FRAMEWORK/UTILS/LIBS/NEWLIB_ADDONS"/>
<listOptionValue builtIn="false" value="../src/SOFTWARE_FRAMEWORK/BOARDS"/>
<listOptionValue builtIn="false" value="../src/SOFTWARE_FRAMEWORK/COMPONENTS/WIFI/HD/v2.1.1/UCR2/GCC"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/wifiHD/src/SOFTWARE_FRAMEWORK/COMPONENTS/WIFI/HD/v2.7.0/UCR2/GCC}&quot;"/>
</option>
<option id="gnu.c.link.option.libs.1720035119" name="Libraries (-l)" superClass="gnu.c.link.option.libs" valueType="libs">
<listOptionValue builtIn="false" value="newlib_addons-at32ucr2-speed_opt"/>
<listOptionValue builtIn="false" value="_ucr2_hd_spi_standalone_v2.1.1"/>
<listOptionValue builtIn="false" value="_ucr2_hd_wl_standalone_v2.1.1"/>
<listOptionValue builtIn="false" value="_ucr2_hd_spi_v2.7.0"/>
<listOptionValue builtIn="false" value="_ucr2_hd_wl_sta_intwpa_v2.7.0"/>
</option>
<option id="gnu.c.link.option.strip.878241046" name="Omit all symbol information (-s)" superClass="gnu.c.link.option.strip" value="false" valueType="boolean"/>
<option id="avr32.c.linker.option.gc-sections.1193662367" name="Garbage collect unused sections" superClass="avr32.c.linker.option.gc-sections" value="true" valueType="boolean"/>
@ -193,8 +193,8 @@
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="ttcp.h|ttcp.c|fsdata.c|hdwireless_gif.h|http_server_gui.h|http_server_gui.c|SOFTWARE_FRAMEWORK/COMPONENTS/TOUCH|SOFTWARE_FRAMEWORK/DRIVERS/ADC|SOFTWARE_FRAMEWORK/COMPONENTS/WIFI/HD/wl_fw.h|gui.c|SOFTWARE_FRAMEWORK/DRIVERS/EBI/SMC|SOFTWARE_FRAMEWORK/COMPONENTS/MEMORY|SOFTWARE_FRAMEWORK/COMPONENTS/DISPLAY/ET024006DHU|gui_getstring.c|SOFTWARE_FRAMEWORK/BOARDS/EVK1105" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src/SOFTWARE_FRAMEWORK/COMPONENTS/MEMORY/DATA_FLASH/AT45DBX"/>
<entry excluding="spb.h|httpd.h|httpd.c|platform_spi.h|clocks.c|clocks.h|nor_flash.h|nor_flash.c|wl_util.h|wl_util.c|startup.h|startup.c|ttcp.h|ttcp.c|fsdata.c|hdwireless_gif.h|http_server_gui.h|http_server_gui.c|SOFTWARE_FRAMEWORK/COMPONENTS/TOUCH|SOFTWARE_FRAMEWORK/DRIVERS/ADC|SOFTWARE_FRAMEWORK/COMPONENTS/WIFI/HD/wl_fw.h|gui.c|SOFTWARE_FRAMEWORK/DRIVERS/EBI/SMC|SOFTWARE_FRAMEWORK/COMPONENTS/MEMORY|SOFTWARE_FRAMEWORK/COMPONENTS/DISPLAY/ET024006DHU|gui_getstring.c|SOFTWARE_FRAMEWORK/BOARDS/EVK1105" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
</sourceEntries>
</configuration>
</storageModule>
@ -1078,6 +1078,7 @@
<listOptionValue builtIn="false" value="WITH_WPA"/>
<listOptionValue builtIn="false" value="WITH_NO_DMA"/>
<listOptionValue builtIn="false" value="DATAFLASH=1"/>
<listOptionValue builtIn="false" value="_INFO_DEBUG_=1"/>
</option>
<option id="gnu.c.compiler.option.include.paths.1012245137" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="../src/SOFTWARE_FRAMEWORK/DRIVERS/PDCA"/>
@ -1199,8 +1200,8 @@
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="ttcp.h|ttcp.c|fsdata.c|hdwireless_gif.h|http_server_gui.h|http_server_gui.c|SOFTWARE_FRAMEWORK/COMPONENTS/TOUCH|SOFTWARE_FRAMEWORK/DRIVERS/ADC|SOFTWARE_FRAMEWORK/COMPONENTS/WIFI/HD/wl_fw.h|gui.c|SOFTWARE_FRAMEWORK/DRIVERS/EBI/SMC|SOFTWARE_FRAMEWORK/COMPONENTS/MEMORY|SOFTWARE_FRAMEWORK/COMPONENTS/DISPLAY/ET024006DHU|gui_getstring.c|SOFTWARE_FRAMEWORK/BOARDS/EVK1105" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src/SOFTWARE_FRAMEWORK/COMPONENTS/MEMORY/DATA_FLASH/AT45DBX"/>
<entry excluding="spb.h|httpd.h|httpd.c|platform_spi.h|clocks.c|clocks.h|nor_flash.h|nor_flash.c|wl_util.h|wl_util.c|startup.h|startup.c|ttcp.h|ttcp.c|fsdata.c|hdwireless_gif.h|http_server_gui.h|http_server_gui.c|SOFTWARE_FRAMEWORK/COMPONENTS/TOUCH|SOFTWARE_FRAMEWORK/DRIVERS/ADC|SOFTWARE_FRAMEWORK/COMPONENTS/WIFI/HD/wl_fw.h|gui.c|SOFTWARE_FRAMEWORK/DRIVERS/EBI/SMC|SOFTWARE_FRAMEWORK/COMPONENTS/MEMORY|SOFTWARE_FRAMEWORK/COMPONENTS/DISPLAY/ET024006DHU|gui_getstring.c|SOFTWARE_FRAMEWORK/BOARDS/EVK1105" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
</sourceEntries>
</configuration>
</storageModule>
@ -2085,6 +2086,7 @@
<listOptionValue builtIn="false" value="WITH_WPA"/>
<listOptionValue builtIn="false" value="WITH_NO_DMA"/>
<listOptionValue builtIn="false" value="LWIP_DEBUG"/>
<listOptionValue builtIn="false" value="_INFO_DEBUG_=1"/>
</option>
<option id="gnu.c.compiler.option.include.paths.1906241430" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="../src/SOFTWARE_FRAMEWORK/DRIVERS/PDCA"/>
@ -2207,7 +2209,7 @@
</folderInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src/SOFTWARE_FRAMEWORK/COMPONENTS/MEMORY/DATA_FLASH/AT45DBX"/>
<entry excluding="ttcp.h|ttcp.c|fsdata.c|hdwireless_gif.h|http_server_gui.h|http_server_gui.c|SOFTWARE_FRAMEWORK/COMPONENTS/TOUCH|SOFTWARE_FRAMEWORK/DRIVERS/ADC|SOFTWARE_FRAMEWORK/COMPONENTS/WIFI/HD/wl_fw.h|gui.c|SOFTWARE_FRAMEWORK/DRIVERS/EBI/SMC|SOFTWARE_FRAMEWORK/COMPONENTS/MEMORY|SOFTWARE_FRAMEWORK/COMPONENTS/DISPLAY/ET024006DHU|gui_getstring.c|SOFTWARE_FRAMEWORK/BOARDS/EVK1105" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
<entry excluding="spb.h|httpd.h|httpd.c|platform_spi.h|clocks.c|clocks.h|nor_flash.h|nor_flash.c|wl_util.h|wl_util.c|startup.h|startup.c|ttcp.h|ttcp.c|fsdata.c|hdwireless_gif.h|http_server_gui.h|http_server_gui.c|SOFTWARE_FRAMEWORK/COMPONENTS/TOUCH|SOFTWARE_FRAMEWORK/DRIVERS/ADC|SOFTWARE_FRAMEWORK/COMPONENTS/WIFI/HD/wl_fw.h|gui.c|SOFTWARE_FRAMEWORK/DRIVERS/EBI/SMC|SOFTWARE_FRAMEWORK/COMPONENTS/MEMORY|SOFTWARE_FRAMEWORK/COMPONENTS/DISPLAY/ET024006DHU|gui_getstring.c|SOFTWARE_FRAMEWORK/BOARDS/EVK1105" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
</sourceEntries>
</configuration>
</storageModule>
@ -3091,6 +3093,7 @@
<listOptionValue builtIn="false" value="WITH_WPA"/>
<listOptionValue builtIn="false" value="WITH_NO_DMA"/>
<listOptionValue builtIn="false" value="LWIP_DEBUG"/>
<listOptionValue builtIn="false" value="_INFO_DEBUG_=1"/>
</option>
<option id="gnu.c.compiler.option.include.paths.193739172" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="../src/SOFTWARE_FRAMEWORK/DRIVERS/PDCA"/>
@ -3211,7 +3214,7 @@
</folderInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src/SOFTWARE_FRAMEWORK/COMPONENTS/MEMORY/DATA_FLASH/AT45DBX"/>
<entry excluding="ttcp.h|ttcp.c|fsdata.c|hdwireless_gif.h|http_server_gui.h|http_server_gui.c|SOFTWARE_FRAMEWORK/COMPONENTS/TOUCH|SOFTWARE_FRAMEWORK/DRIVERS/ADC|SOFTWARE_FRAMEWORK/COMPONENTS/WIFI/HD/wl_fw.h|gui.c|SOFTWARE_FRAMEWORK/DRIVERS/EBI/SMC|SOFTWARE_FRAMEWORK/COMPONENTS/MEMORY|SOFTWARE_FRAMEWORK/COMPONENTS/DISPLAY/ET024006DHU|gui_getstring.c|SOFTWARE_FRAMEWORK/BOARDS/EVK1105" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
<entry excluding="spb.h|httpd.h|httpd.c|platform_spi.h|clocks.c|clocks.h|nor_flash.h|nor_flash.c|wl_util.h|wl_util.c|startup.h|startup.c|ttcp.h|ttcp.c|fsdata.c|hdwireless_gif.h|http_server_gui.h|http_server_gui.c|SOFTWARE_FRAMEWORK/COMPONENTS/TOUCH|SOFTWARE_FRAMEWORK/DRIVERS/ADC|SOFTWARE_FRAMEWORK/COMPONENTS/WIFI/HD/wl_fw.h|gui.c|SOFTWARE_FRAMEWORK/DRIVERS/EBI/SMC|SOFTWARE_FRAMEWORK/COMPONENTS/MEMORY|SOFTWARE_FRAMEWORK/COMPONENTS/DISPLAY/ET024006DHU|gui_getstring.c|SOFTWARE_FRAMEWORK/BOARDS/EVK1105" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
</sourceEntries>
</configuration>
</storageModule>

View File

@ -60,11 +60,6 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.atmel.avr32.managedbuilder.ui.extras.ListingBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.atmel.avr32.core.nature</nature>

View File

@ -0,0 +1 @@
Revision: 2491

View File

@ -1,51 +1,11 @@
/* This header file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
/*! \page License
* Copyright (C) 2009, H&D Wireless AB All rights reserved.
/*
* Programming interface for wl_api.
* Copyright (C) 2010 HD Wireless AB
*
* The license to use this software in whole and in part and to
* redistribute it in any form follows with the WiFi HW module from H&D
* Wireless and is granted under the following restrictions:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. 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.
*
* 3. The name of H&D Wireless AB may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* 4. The software may only be used together with hardware from H&D
* Wireless all other use is prohibited.
*
* 5. The license to use and redistribute the software is granted
* together with the purchase of a hardware platform on a one to one
* basis
*
* 6. The binary code may not be reversed engineered or by other means
* copied to circumvent this license.
*
* THIS SOFTWARE IS PROVIDED BY H&D WIRELESS AB ``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 EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT
* SHALL HD WIRELESS AB 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.
*
* For more information regarding this software license Contact H&D
* Wireless AB (support@hd-wireless.se).
* You should have received a copy of the license along with this library.
*/
/*! \file wl_api.h **************************************************************
/*! \file wl_api.h *************************************************************
*
* \brief Basic WiFi API
*
@ -133,52 +93,71 @@ The second important property is that wl_api is \b polled. wl_api
never executes "by itself", since it would then have to support
interrupts, timers, locks and other operating system dependent
features. Instead all asynchronous processes proceed when wl_api is
polled by calling the \a wl_poll() function. When \a wl_poll() is called
wl_api reacts to any received packets, expires any internal timers and
polled by calling the \a wl_tick() function. When \a wl_tick() is called
wl_api reacts to any received management frames, expires any internal timers and
performs any other tasks necessary for forward progress. After
\a wl_poll() returns nothing will happen unless it or some other wl_api
function is called again.
\a wl_tick() returns nothing will happen unless it or some other wl_api
function is called again. Also, to send and receive data, the \a wl_process_rx()
and \a wl_process_tx() must be invoked upon reception and transmission of data.
The third important property is that wl_api is \b not \b thread \b safe.
All wl_api calls must execute in the same context since the
library has no knowledge of the locking mechanisms available (if any).
\section wl_api_code_examples A note on the code examples
The code examples illustrate how to call the different wl_api functions.
They do not constitute a complete program. Functions with the prefix "app_"
in the code examples are application specific calls that illustrate a
particular action. These functions are not part of the API and will have
to be implemented if needed. For a complete working code example see
one of the H&D Wireless software reference designs, such as the WiFi HTTP
server demo code in the Atmel Software Framework.
The API is structured into these functional groups:
\li \ref wl_api
\li \ref wl_wifi
\li \ref wl_data
\li \ref wl_transport
\li \ref wl_custom
Also documented here is the transport layers for SPI and SDIO.
There interfaces are only necessary when porting the library to
a new hardware platform.
\li \ref wl_spi
\li \ref wl_sdio
* \section contactinfo Contact Information
* For further information, visit
* <A href="http://www.hd-wireless.se/">H&D Wireless</A>.\n
* Support and FAQ: http://www.atmel.com/
*/
#include <stdint.h>
#include <stdlib.h>
#include "spb.h"
#ifndef WL_API_H
#define WL_API_H
#define WL_API_RELEASE_NAME "v2.7.0"
#define WL_API_RELEASE_NAME "v2.1.1"
/*! Size of the wl_api packet header */
#define WL_HEADER_SIZE 14
/*! Maximum packet size (including wl_api headers and paddings */
#define WL_MAX_PKT_LEN 1600
/*! Maximum size of a SSID */
#define WL_SSID_MAX_LENGTH 32
/*! Size of a MAC-address or BSSID */
#define WL_MAC_ADDR_LENGTH 6
/*! Maximum length of a passphrase */
#define WL_MAX_PASS_LEN 64
/*! Indicates that there is no SNR information */
#define WL_SNR_UNKNOWN -128
#define SPB104 104
#define SPB105 105
/*! \ingroup wl_api
* API Error codes */
typedef enum {
WL_FAILURE = -1,
WL_SUCCESS = 1,
WL_NOEFFECT,
WL_OOM,
WL_INVALID_LENGTH,
WL_NOT_SUPPORTED,
@ -201,8 +180,8 @@ enum wl_event_id_t {
WL_EVENT_MEDIA_CONNECTED = 0,
WL_EVENT_CONN_FAILURE,
WL_EVENT_MEDIA_DISCONNECTED,
WL_EVENT_CONN_LOST,
WL_EVENT_SCAN_COMPLETE,
WL_EVENT_FAILURE,
MAX_WL_EVENT
};
@ -230,6 +209,10 @@ enum wl_enc_type { /* Values map to 802.11 encryption suites... */
ENC_TYPE_AUTO = 8
};
enum wl_host_attention_mode {
WL_HOST_ATTENTION_SDIO = 0x1, /*!< For SDIO or polled SPI */
WL_HOST_ATTENTION_SPI = 0x5a /*!< For SPI with interrupt line */
};
/*! \ingroup wl_wifi
* Event descriptor
@ -239,8 +222,37 @@ struct wl_event_t {
};
/*! Struct member alignment macro */
#define ALIGN __attribute__ ((aligned (4)))
/*! \ingroup wl_wifi
* Infrastructure (ESS) or Ad-hoc (IBSS) connection modes.
*/
enum wl_conn_type_t {
WL_CONN_TYPE_INFRA, /*!< For infrastructure mode (default) */
WL_CONN_TYPE_ADHOC /*!< For ad-hoc mode */
};
/* Note:
* If your environment does not have stdint.h you will have to
* define the fixed-width integer types specified in that file
* yourself, make sure that those definitions are included
* before any inclusions of wl_api.h, and build with the macro
* WITHOUT_STDINT defined. In this case the wl_api library
* must have been built with the same integer type definitions.
*/
#ifndef WITHOUT_STDINT
#include <stdint.h>
#endif
/* Note:
* If your environment does not have stdio.h you will have to define
* the size_t type yourself, make sure that that definition is
* included before any inclusions of wl_api.h, and build with the
* macro WITHOUT_STDIO defined. In this case the wl_api library must
* have been built with the same size_t type definition.
*/
#ifndef WITHOUT_STDIO
#include <stdio.h>
#endif
/*! \ingroup wl_wifi
*
@ -255,7 +267,7 @@ struct wl_ssid_t
char ssid[WL_SSID_MAX_LENGTH]; /**< Octet array containing the SSID data. */
uint8_t len; /**< Length of valid data in ssid member.
* Cannot be longer than WL_SSID_MAX_LENGTH. */
} ALIGN;
};
/*! \ingroup wl_wifi
*
@ -279,9 +291,52 @@ struct wl_network_t
{
struct wl_ssid_t ssid; /**< The SSID of the network. */
struct wl_mac_addr_t bssid; /**< The BSSID of the network. */
uint8_t channel; /**< The wlan channel which the network uses */
uint32_t beacon_period; /**< Beacon period for the network */
uint16_t dtim_period; /**< DTIM period for the network */
int32_t rssi; /**< Received Signal Strength in dBm (measured on beacons) */
int32_t snr; /**< Received Signal to noise ratio in dBm (measured on beacons) */
uint8_t enc_type; /**< The encryption type used in the network. */
} ALIGN;
enum wl_conn_type_t net_type; /**< Type of network (Infrastructure or Ad-Hoc */
size_t ie_len; /**< Always 0 unless wl_api has been built with WL_CONFIG_WPA_SUPPLICANT */
uint8_t ie[0]; /**< Not used unless wl_api has been built with WL_CONFIG_WPA_SUPPLICANT */
};
/*! \ingroup wl_wifi
* Network list representation. Array of pointers to wl_network_t entries.
*
*/
struct wl_network_list_t
{
struct wl_network_t **net; /**< The list of pointers to networks */
size_t cnt; /**< Number of networks */
};
#define WL_RATE_1MBIT 2
#define WL_RATE_2MBIT 4
#define WL_RATE_5_5MBIT 11
#define WL_RATE_6MBIT 12
#define WL_RATE_9MBIT 18
#define WL_RATE_11MBIT 22
#define WL_RATE_12MBIT 24
#define WL_RATE_18MBIT 36
#define WL_RATE_22MBIT 44
#define WL_RATE_24MBIT 48
#define WL_RATE_33MBIT 66
#define WL_RATE_36MBIT 72
#define WL_RATE_48MBIT 96
#define WL_RATE_54MBIT 108
#define WL_RATE_NUM_RATES 14
#define WL_RATE_INVALID WL_RATE_NUM_RATES
/*! \ingroup wl_wifi
*
* Rate representation
*
*/
typedef uint8_t wl_rate_t;
/** \defgroup wl_api Library support functions
*
@ -294,31 +349,51 @@ without an operating system.
Before the library can do anything it needs to start up the WiFi
hardware by downloading a firmware image. The firmware image is
relatively big (around 144kB) and is not included in the library since
relatively big (around 144kB) and is therefore not included in the library
it is only needed once. It is up to the application to decide where to
store the firmware image and how to read it into the wl_api library.
Step one is to write a function of the type \a ::wl_fw_download_cb_t
that wl_api will call to retrive the firmware image. Assuming that
you have some spare RAM on your platform you can simply include
the firmware image from the \a fw.h header file and write a
Step one is to write a function of the type \a ::wl_fw_read_cb_t
that wl_api will call to retrive the firmware image. Assuming that you
have some spare RAM (or whatever memory type is used for read only
data, such as FLASH memory) on your platform you can simply include
the firmware image from the \a wl_fw.h header file and write a
firmware read function like this
\code
static void fw_download_cb(void* ctx, uint8_t** buf, uint32_t* len)
static size_t fw_read_cb(void* ctx,
uint8_t** buf,
size_t offset,
size_t len)
{
*buf = (uint8_t*) fw_buf;
*len = fw_len;
if ( NULL == buf ) {
return 0;
}
*buf = ((uint8_t*) fw_buf) + offset;
if ( len > ( fw_len - offset ) ) {
return fw_len - offset;
}
return len;
}
\endcode
If the firmware image is stored in ROM this function may have to read
it back block by block instead.
The wl_api library is initialized like this
First, firmware must be downloaded to the device
\code
if ( wl_init(NULL, fw_download_cb, init_complete_cb) != WL_SUCCESS ) {
if ( wl_transport_init(fw_read_cb, NULL, &mode) != WL_SUCCESS ) {
app_error("Firmware download failed");
return 0;
}
\endcode
The wl_api library is then initialized like this
\code
if ( wl_init(NULL, init_complete_cb, mode) != WL_SUCCESS ) {
app_error("Init failed");
return 0;
}
@ -350,22 +425,23 @@ if (wl_register_event_cb(event_cb, NULL) != WL_SUCCESS) {
}
\endcode
The \a wl_poll() function takes a free running "tick" counter with
millisecond resolution as an argument so that it can trigger internal
timers when necessary. Assuming that such a tick counter is provided
by the macro GET_MS_TICK() the wl_api execution loop becomes
Similar to \a wl_poll(), there is also a \a wl_tick() function that takes a
free running "tick" counter with millisecond resolution as an argument so
that it can trigger internal timers when necessary. Assuming that such a tick
counter is provided by the macro GET_MS_TICK() the wl_api execution loop becomes
\code
while (TRUE) {
wl_poll(GET_MS_TICK());
wl_tick(GET_MS_TICK());
wl_poll();
}
\endcode
In a stand-alone application this loop would usually be the main application
loop and include application specific calls as well.
After some number of main loop iterations the WL_EVENT_INIT_COMPLETE
event is posted and the application can initialize its IP stack.
After some number of main loop iterations the init_complete_cb will be
invoked and the application can initialize its IP stack.
* @{
*/
@ -388,51 +464,6 @@ event is posted and the application can initialize its IP stack.
typedef void (*wl_event_cb_t) (struct wl_event_t event, void* ctx);
/*! \brief WiFi event callback.
*
* This function is invoked in interrupt context when there is new data
* available from the mac. This function is supplied by the user
* of the API.
*
* This function is typically used only by the TCP/IP stack driver.
*
* @param ctx A context handle. This handle is passed
* untouched to the callback and has the same value
* as the context registered with the callback in
* wl_register_event_cb().
*/
typedef void (*wl_rx_isr_t) (void* ctx);
/*! \brief Firmware access function.
*
* Reads the WiFi firmware image. This function is supplied by
* the user of this API since storage for the firmware image is
* managed by the application.
*
* This function should read a number of bytes of the firmware of the firmware
* image. The number of remaining bytes is given as the input value of
* \a len. Upon return, \a buf should point to a buffer which holds the read
* data and \a len should hold the number of bytes read. Hence, \a len is both
* an input and an output parameter.
*
* The offset where reading starts should be incremented sequentially by the
* ouput value of \a len bytes upon completion of each call.
*
* This function will be called repeatedly until the complete firmware image
* has been read. The last call will have the input value of \a len set to 0
* to indicate that no more data is needed and that any dynamically allocated
* buffer which holds firmware data are safe to free.
*
* @param ctx Opaque context pointer as provided to \a wl_init() that will be
* passed back to the callback.
* @param buf Should be assigned the address of the buffer holding the read
* data upon return.
* @param len Should hold the value of the number of bytes read upon return.
*/
typedef void (wl_fw_download_cb_t)(void *ctx, uint8_t** buf, uint32_t* len);
/*! \brief Initialization complete callback function.
*
* Invoked when WiFi initialization is complete.
@ -442,7 +473,7 @@ typedef void (wl_fw_download_cb_t)(void *ctx, uint8_t** buf, uint32_t* len);
*/
typedef void (wl_init_complete_cb_t)(void* ctx);
/*! \brief Register an event handler.
*
* Register an event handler with the driver. This
@ -468,35 +499,49 @@ wl_err_t wl_register_event_cb(wl_event_cb_t cb, void* ctx);
* init_complete_cb when completed. The callback will not be invoked if any
* error occurs during initialization.
*
* @param ctx Opaque context pointer that will be passed to the callbacks
* when they are invoked. This parameter is never
* accessed by the API.
* @param fw_download_cb callback function to invoke during firmware download.
* This function should be called after firmware has been downloaded to the
* device.
*
* @param ctx Opaque context pointer that will be passed to the callback
* when invoked. This parameter is never accessed by the API.
* @param init_complete_cb callback function to invoke when initialization is
* complete.
* @param mode Indicates the host attention mode used by the device. If
* \a wl_transport_init() was used to download the firmware image to the
* device, the proper mode can be obtained from the mode parameter of
* that function.
*
* @return
* - WL_SUCCESS
* - WL_FAILURE
* - WL_CARD_FAILURE if the wl hardware device is not available
* - WL_FIRMWARE_INVALID if the firmware obtained through fw_download_cb is
* invalid.
*/
wl_err_t wl_init(void* ctx,
wl_fw_download_cb_t fw_download_cb,
wl_init_complete_cb_t init_complete_cb);
wl_err_t wl_init(void* ctx, wl_init_complete_cb_t init_complete_cb,
enum wl_host_attention_mode mode);
/*! \brief WiFi driver forward progress function
/*! \brief Shutdown the wl_api library and free resources.
*
* This function must be called in stand-alone environments to
* ensure forward progress. Periodic timers are triggered from this function
* so it should be called as often as possible if precision
* timing is required (traffic timeouts, authentication timeouts
* etc).
* \a wl_init() must be invoked to startup the library
* again.
*
* @return
* - WL_SUCCESS on success
* - WL_FAILURE
*
*/
wl_err_t wl_shutdown(void);
/*! \brief WiFi driver timer tick function
*
* Periodic timers are triggered from this function so it should be called as
* often as possible if precision timing is required (traffic timeouts,
* authentication timeouts etc).
*
* @param tick A tick count in us. This is used to expire timers
* in the driver.
*/
void wl_poll(uint32_t tick);
void wl_tick(uint32_t tick);
/*! @} */
@ -527,16 +572,14 @@ and retrieve the list of seen networks from the library
\code
static void event_cb(struct wl_event_t event, void* ctx) {
switch(event.id) {
case WL_EVENT_INIT_COMPLETE:
app_init_ip_stack();
break;
case WL_EVENT_SCAN_COMPLETE:
struct wl_network_t* netlist;
struct wl_network_list_t *netlist;
uint8_t netcnt;
wl_get_network_list(&netlist, &netcnt);
wl_get_network_list(&netlist);
netcnt = netlist->cnt;
while (--netcnt) {
print_network(netlist + netcnt);
print_network(netlist->net[netcnt]);
}
break;
}
@ -600,16 +643,14 @@ must be also be caught
\code
static void event_cb(struct wl_event_t event, void* ctx) {
switch(event.id) {
case WL_EVENT_INIT_COMPLETE:
app_init_ip_stack();
break;
case WL_EVENT_SCAN_COMPLETE:
struct wl_network_t* netlist;
struct wl_network_list_t *netlist;
uint8_t netcnt;
wl_get_network_list(&netlist, &netcnt);
wl_get_network_list(&netlist);
netcnt = netlist->cnt;
while (--netcnt) {
print_network(netlist + netcnt);
print_network(netlist->net[netcnt]);
}
break;
case WL_EVENT_CONN_FAILURE:
@ -646,25 +687,6 @@ To set the 40-bit WEP key 0xDEADBEEF00 as default key for key index 0 do
}
\endcode
If Shared Key authentication is required then this is configured through
a call to \a wl_set_auth_mode().
\code
if ( wl_set_auth_mode(AUTH_MODE_SHARED_KEY) != WL_SUCCESS) {
app_error("Failed to set authentication mode.");
return 0;
}
\endcode
It is important to know that \a wl_set_auth_mode() sets a \b forcing
authentication mode. If the mode is set to AUTH_MODE_SHARED_KEY then
all connection attempts made will fail if the target of the connection
attempt does not support Shared Key authentication. This is true of all
non-WEP Access Points, including Access Points with WPA or WPA2. To
reset the authentication mode call \a wl_set_auth_mode() with the
mode set to AUTH_MODE_OPEN_SYSTEM (this is the default mode if
\a wl_set_auth_mode() is never called).
To use WPA/WPA2 with a Pre-shared key a passphrase must be associated
with the network before the connection is initiated.
@ -696,6 +718,7 @@ key from the passphrase before the connection attempt can start.
* @{
*/
/*! \brief Scan all channels.
*
* Starts a scan of all WiFi channels allowed in this regulatory
@ -705,6 +728,13 @@ key from the passphrase before the connection attempt can start.
* The scan will proceed asynchronously and will raise a
* WL_EVENT_SCAN_COMPLETE event when completed.
*
* Currently, there's a limit on the scan list size that depends on the
* architecture (6 networks for the AVR32 UCR1 architecture 16 networks for
* other architectures. If more network exist, the strongest networks are
* chosen. Note that the limitation on the scan list size does not limit the
* networks which the device can connect to. See wl_connect() for more
* details.
*
* @return
* - WL_SUCCESS
* - WL_FAILURE.
@ -724,20 +754,55 @@ wl_err_t wl_scan(void);
* Note that a successful scan does not necessarily
* find any networks.
*
* This function is not thread safe. It must be called in the
* same execution context as wl_poll().
*
* @param network_list Output buffer. The API call returns
* a pointer to allocated memory containing \a network_cnt
* network entries.
* @param network_cnt The number of networks
* allocated in network_list.
* a pointer to allocated memory containing the network list.
* @return
* - WL_SUCCESS
* - WL_FAILURE.
*/
wl_err_t wl_get_network_list(struct wl_network_t** network_list, uint8_t* network_cnt);
wl_err_t wl_get_network_list(struct wl_network_list_t **network_list);
#ifdef WFE_6_12
/*! \brief Start a Ad-hoc network.
*
* Attempt to start a Ad-hoc (IBSS) network. If a Ad-hoc network
* is successfully started then a WL_EVENT_MEDIA_CONNECTED event
* will be raised once the first peer station connects to the Ad-hoc
* network (and not when the network is announced on the air).
*
* If a Ad-hoc network should be started with encryption
* enabled then \a wl_set_passphrase() should be called before
* \a wl_start_adhoc_net() to configure the security parameters.
* The Ad-hoc network is started with the security parameters
* (if any) that was configured for the specified \a ssid.
*
* @param ssid The SSID of the new network. If there's a network
* already present with this SSID this call will fail.
* @param channel The channel to use. Valid channels are 1-14
* @param auth_mode The authentication mode to use. Supported
* authentication modes for Ad-hoc networks are
* AUTH_MODE_OPEN_SYSTEM and AUTH_MODE_SHARED_KEY.
* Passing other modes will cause a WL_INVALID_ARGS return.
* If AUTH_MODE_SHARED_KEY is used then a valid WEP
* key must be set with a call to \a wl_add_wep_key()
* and the default WEP key index must be set with a
* call to \a wl_set_default_wep_key().
* @return
* - WL_SUCCESS on success.
* - WL_INVALID_ARGS if the ssid is malformed, if
* the channel not valid or if the authentication mode
* is invalid.
* - WL_RETRY if the driver is busy resolving a conflicting
* operation. The operation should be retried after a wait
* (at least one call to wl_poll() for polled implementations).
* - WL_BUSY if the driver is already connected or if a network
* with the same SSID is already known.
*
*/
wl_err_t wl_start_adhoc_net(struct wl_ssid_t ssid,
uint8_t channel,
enum wl_auth_mode auth_mode);
#endif
/*! \brief Connect to a SSID.
*
* Attempt to connect to a given SSID. If the driver is already
@ -752,6 +817,11 @@ wl_err_t wl_get_network_list(struct wl_network_t** network_list, uint8_t* networ
* terminated. Note that this can be caused by external factors and can
* happen at any time.
*
* If wl_connect() is invoked with a network that is not shown in the
* scan list, the device will probe for that specific network and connect
* to it, if found. This is also the method to use in order to connect to
* "hidden" networks (AP's that doesn't broadcast its SSID).
*
* @param ssid Pointer to the SSID string.
* Freed by caller.
* @param ssid_len Length of the SSID string in octets. Max value is 32.
@ -779,6 +849,10 @@ wl_err_t wl_connect(char* ssid, size_t ssid_len);
* terminated. Note that this can be caused by external factors and can
* happen at any time.
*
* If wl_connect_bssid() is invoked with a network that is not shown in the
* scan list, the device will probe for that specific network and connect
* to it, if found.
*
* @param bssid Pointer to the BSSID. Freed by caller.
* @return
* - WL_SUCCESS
@ -806,29 +880,6 @@ wl_err_t wl_connect_bssid(struct wl_mac_addr_t bssid);
*/
wl_err_t wl_disconnect(void);
/*! \brief Set the WEP authentication mode of the driver.
*
* Set the authentication mode to use. This is only for
* enforcing Shared Key authentication in WEP networks.
* The default mode is AUTH_MODE_OPEN_SYSTEM which works
* with all types of encryption.
*
* Note that as long as the mode is set to AUTH_MODE_SHARED_KEY
* all connections to APs using no encryption or WPA/WPA2 will
* fail since those require Open System authenticaton.
*
* @param mode AUTH_MODE_OPEN_SYSTEM for Open System authentication
* (that is no authentication). This should be used for WPA/WPA2
* connections.
* AUTH_MODE_SHARED_KEY for WEP shared key authentication.
* Other values of \a mode are invalid with this call
* and will cause WL_FAILURE to be returned.
* @return
* - WL_SUCCESS on success.
* - WL_FAILURE on failure.
*/
wl_err_t wl_set_auth_mode(enum wl_auth_mode mode);
/*!
* @brief Add a WEP encryption key to the device.
*
@ -927,6 +978,7 @@ wl_err_t wl_set_passphrase(const struct wl_network_t *net,
*/
wl_err_t wl_clear_passphrase(struct wl_network_t *net);
/*! \brief Enable legacy power save mode
*
* Enable legacy power save mode. In legacy power save mode, the device
@ -984,8 +1036,7 @@ wl_err_t wl_conf_ps(uint8_t use_ps_poll,
uint32_t ps_delay,
uint8_t rx_all_dtim,
uint16_t listen_interval);
/*! \brief Get the interface MAC address.
*
* Return the 802.3 MAC address of the network interface.
@ -1012,12 +1063,11 @@ struct wl_network_t* wl_get_current_network(void);
/** \defgroup wl_data Data Transfer
*
* \brief Packet transport interface.
*
* These functions access the low level transport driver which makes
* the application independent of the actual physical transport
* layer (usually SDIO or SPI).
* \brief Packet processing interface.
*
* Note that the examples in this group assumes that the transport library
* functions in the \a wl_transport group are being used. For more information,
* See the documentation for those functions in the \a wl_transport group.
For the IP stack integration you need to intercept received packets so
they can be sent up the stack and to transmit packets coming down the
@ -1090,9 +1140,7 @@ Continuing the ip_stack_rx_pkt() example
len,
&stripped_pkt,
&stripped_pkt_len,
&NULL,
&vlan,
NULL);
&vlan);
if (WL_ABSORBED == status) {
// This is normal. The packet was a
// wl_api-internal message.
@ -1110,7 +1158,7 @@ Continuing the ip_stack_rx_pkt() example
If \a wl_process_rx() decides that the packet was a command it processes
it and returns \a WL_ABSORBED to signal that the packet should
not be used by anyone else. Otherwise stripped_pkt is
pointing to the beginning of a 802.3 ethernet frame of length
pointing to the beginning of a 802.3 Ethernet frame of length
stripped_pkt_len. If the IP stack supports VLAN and QoS
the extra VLAN tag should be passed to the IP stack
together with the packet. For IP stacks without this support the VLAN tag
@ -1129,9 +1177,8 @@ packets to send.
\code
int ip_stack_tx_pkt(char *pkt, size_t len, uint16_t vlan_tag) {
int status;
size_t hdr_len;
char wlan_hdr[WL_HEADER_SIZE];
// The packet must have an ethernet header
// The packet must have an Ethernet header
if (len < ETHERNET_HEADER_SIZE) {
app_error("Invalid packet length");
return 0;
@ -1141,7 +1188,6 @@ int ip_stack_tx_pkt(char *pkt, size_t len, uint16_t vlan_tag) {
ETHERNET_HEADER_SIZE,
len,
wlan_hdr,
&hdr_len,
vlan_tag,
NULL);
if ( WL_SUCCESS != status ) {
@ -1174,12 +1220,44 @@ the MAC address of the WiFi interface
* @{
*/
/*! Size of the wl_api packet header */
#ifdef WFE_6_12
#define WL_HEADER_SIZE 16
#else
#define WL_HEADER_SIZE 14
#endif
/*! Maximum packet size (including wl_api headers and paddings)
*
* Maximum packet size is obtained with the following data:
*
* 1500 bytes of Ethernet payload (MTU) + 14 bytes of Ethernet header +
* WL_HEADER_SIZE of wl header. This data is then size-aligned to 16.
*
*/
#define WL_MAX_PKT_LEN 1536
/*!
* \brief Process rx packet.
*
* Processes a raw rx packet by unencrypting it (if necessary)
* and stripping headers so as to output a 802.3 frame.
*
* wl_process_rx() will strip bytes both from the head and from the tail.
*
* Upon return from wl_process_rx(), the pointer at stripped_pkt will
* point to the start of the Ethernet header, hence adjusting the offset
* by WL_HEADER_LEN bytes. Any padding (added by the wifi device) will
* be removed from the tail of the packet, hence making len smaller.
*
* The wl_api library of the device will not perform any Ethernet padding
* removal. The padding removal performed by wl_process_rx() is only for
* the padding used in the protocol shared by the host and the device.
* This padding is mainly there to ensure that the host does not have to
* deal with rx of odd-sized data buffers (which some DMA's have problems
* to handle).
*
* @param pkt Input buffer (raw packet)
* @param pkt_len Length of the input buffer (in bytes)
* @param stripped_pkt Pointer to the packet with the
@ -1211,13 +1289,37 @@ wl_err_t wl_process_rx(char *pkt, size_t pkt_len, char **stripped_pkt,
*
* This function is typically used only by the TCP/IP stack driver.
*
* Takes a Ethernet II frame header and generates a message passing header for it.
* The ethernet header is assumed to have the following layout :
* Takes a Ethernet II frame header and generates a message passing header
* for it.
*
* The caller should ensure that any frames injected into wl_process_tx()
* are proper Ethernet frames. The wl_api library or the device will not
* perform any Ethernet padding if the frames are too short.
*
* The Ethernet header is assumed to have the following layout :
* <dst addr:6><src addr:6><type:2>...
* The rest of the ethernet header buffer (if any) is ignored.
* The rest of the Ethernet header buffer (if any) is ignored.
*
* @param eth_hdr Input buffer (ethernet header)
* A note on the TX packet representation :
* If your TX packets are simple contiguous buffers you can ignore
* the rest of this note and pass NULL in parameter \a pkt_handle.
* A TX packet may have a more complex structure than a RX packet
* (which must be a contiguous, flat buffer). The IP stack may
* for example represent a packet as a linked list of buffers where
* the Ethernet header, the IP header and other headers, are represented
* by separate buffers. In some cases, such as when the driver is
* running in SoftAP mode, a TX packet has to be copied and queued
* internally for later processing and to support this when packets
* have a complicated structure a special data access function can
* be registered. See \a wl_register_pkt_read_cb() for details.
* If you use \a wl_process_tx() with non-simple packets you
* should pass a handle to the packet in parameter \a pkt_handle
* and register an access function with \a wl_register_pkt_read_cb().
*
* @param eth_hdr Input buffer (Ethernet header)
* @param eth_hdr_len Input buffer length (must be >= 14)
* This is usually the same as pkt_len unless e.g linked list or buffers
* chained in other ways are being used.
* @param pkt_len Length of the complete data packet (in bytes)
* @param hdr Pointer to the header buffer (must be
* allocated by the caller). The length of the buffer
@ -1231,6 +1333,12 @@ wl_err_t wl_process_rx(char *pkt, size_t pkt_len, char **stripped_pkt,
* 0| VLANID |PRI
* </PRE>
* Ignored for legacy association (no WMM)
* @param pkt_handle A handle to the complete packet. If this parameter
* is NULL then \a eth_hdr is expected to point to the whole packet
* in a single contiguous buffer (the default). If a different packet
* representation is used this parameter should be a handle to the
* complete packet and will be passed unmodified to the data
* access function that was registered with \a wl_register_pkt_read_cb().
*
* @returns
* - WL_FAILURE
@ -1240,11 +1348,159 @@ wl_err_t wl_process_rx(char *pkt, size_t pkt_len, char **stripped_pkt,
* - WL_AVAIL if network not available
* - WL_SUCCESS if packet is ready for transmission through wl_tx().
*/
wl_err_t wl_process_tx(char *eth_hdr, size_t eth_hdr_len, size_t pkt_len,
char *hdr, uint16_t vlanid_prio);
wl_err_t wl_process_tx(char *eth_hdr,
size_t eth_hdr_len,
size_t pkt_len,
char *hdr,
uint16_t vlanid_prio,
void *pkt_handle);
/*! \brief Get current TX and RX rate used for data transfer
*
* During transmission and reception of data, the actual rate used will depend
* on the signal quality. This function can be used to get the actual rate used
* for the last tx and rx data.
*
* @param tx will hold the tx rate upon successful return.
* @param rx will hold the rx rate upon successful return.
*
* @return
* - WL_SUCCESS on success
* - WL_FAILURE on failure.
*/
wl_err_t wl_get_rate(wl_rate_t *tx, wl_rate_t *rx);
/*! @} */ /* End wl_data group */
/** \defgroup wl_transport Transport interface
*
* \brief Low level transport interface.
*
* These functions access the low level transport driver which makes
* the application independent of the actual physical transport
* layer (usually SDIO or SPI).
*
For applications running on an real time kernel or without an
operating system, the provided transport library will fit right into the
application design. However, when running on a more complex operating system
(such as windows or linux) which has its own transport primitivies and
components (and probably its own IP stack) it might be preferred to design a
custom transport library for that specific environment. Therefore, these
transport interface functions are fully optional.
* @{
*/
#define WL_RX_MIN_PKT_LEN 32
/*! \brief WiFi event callback.
*
* This function is invoked in interrupt context when there is new data
* available from the mac. This function is supplied by the user
* of the API.
*
* This function is typically used only by the TCP/IP stack driver.
*
* @param ctx A context handle. This handle is passed
* untouched to the callback and has the same value
* as the context registered with the callback in
* wl_register_event_cb().
*/
typedef void (*wl_rx_isr_t) (void* ctx);
/*! \brief Firmware access function.
*
* Reads the WiFi firmware image. This function is supplied by
* the user of this API since storage for the firmware image is
* managed by the application.
*
* This function should read the specified number of bytes of the
* firmware image starting at the specified \a offset. The number of
* bytes to read is given in \a len. Upon return, \a buf should point
* to a buffer which holds the read data and the number of valid bytes
* in \a buf is returned from the call.
*
* This function will be called repeatedly until the complete firmware
* image has been read.
*
* This function may be called again at any time while the driver is
* running to download further pieces of the WiFi firmware image as
* needed by the runtime requirements. This will normally only happen
* when the driver switches between networks of different kinds such
* as from WEP to WPA, or from ESS to IBSS for example.
*
* For convenience, any time a firmware chunk has been completely
* downloaded this function will be called once with the \a buf
* parameter set to NULL to indicate that no more data is needed right
* now and that any dynamically allocated buffers which holds firmware
* data can be freed without much performance impact.
*
* @param ctx Opaque context pointer as provided to \a wl_init() that will be
* passed back to the callback.
* @param buf Should be assigned the address of the buffer holding the read
* data upon return. This parameter can be NULL which indicates
* that there are no further immediately pending accesses.
* @param offset Offset in bytes from the start of the firmware image.
* Data should be copied into buf starting at \a offset.
* @param len The number of bytes to copy into \a buf.
* @return The number of bytes copied into buf. This may be smaller than
* \len if the implementation of the function so requires.
*/
typedef size_t (wl_fw_read_cb_t)(void *ctx,
const uint8_t **buf,
size_t offset,
size_t len);
/*! \brief Initialize the transport interface and download the WiFi firmware
* image to the device.
*
* This operation will proceed synchronously until the firmware is completely
* downloaded. wl_init() should be called after this function has returned to
* perform device initialization.
*
* @param fw_read_cb callback function to invoke during firmware download.
* @param ctx Opaque context pointer that will be passed to the callbacks
* when they are invoked. This parameter is never
* accessed by the API.
* @param mode will hold the host attention mode used by the transport layer.
* This parameter can be passed directly to \a wl_init().
*
* @return
*
* - WL_CARD_FAILURE if the wl hardware device is not available
* - WL_FIRMWARE_INVALID if the firmware obtained through fw_read_cb is
* invalid.
* - WL_OOM if the necessary memory could not be allocated.
*/
wl_err_t wl_transport_init(wl_fw_read_cb_t *fw_read_cb,
void *ctx,
enum wl_host_attention_mode *mode);
/*! \brief WiFi driver forward progress function
*
* This function must be called in polled environments to
* ensure forward progress. The call can be made as often as possible from
* the main application loop. However, the call will not have any effect unless
* there is an interrupt pending from the hardware.
*
* In interrupt mode, wl_poll() must be called if no interrupt
* handler is registered through wl_register_rx_isr(). When an interrupt
* handler is registered, it is no longer necessary to invoke wl_poll().
*
* Note that this function should not be invoked from interrupt context.
*
*/
void wl_poll(void);
/*! \brief Register RX callback
*
* Register function to be called by the low level transport driver
@ -1294,7 +1550,137 @@ wl_err_t wl_rx(uint8_t* buf, uint16_t* len);
*/
wl_err_t wl_tx(const uint8_t* buf, uint16_t len);
/*! @} */ /* End wl_data group */
/*! \brief Configure data alignment
*
* This function can be used if the host SDIO/SPI controller has certain
* requirements on the data transfer sizes that can be used on the SDIO/SPI bus.
*
* If the txsize parameter is non-zero, additional padding data should be added
* when performing the low level transfer of data buffer of sizes that are not
* a multiple of the size_align parameter. See \ref wl_sdio and \ref wl_spi for
* more information.
*
* @param txsize will configure the size alignment for tx data.
*
*/
void wl_conf_alignment(uint8_t txsize);
/*! @} */ /* End wl_transport group */
/** \defgroup wl_custom Custom environment support
*
* \brief Support for custom environments
*
* These functions should only be used in cases where the transport library is
* not used at all. This usually applies to operating systems and environments
* where there already exists a transport layer framework, e.g. linux or
* windows.
*
*
Note that the \a wl_poll() function is part of the transport library. Therefore,
it should not be used in custom environments. Therefore, it is necessary to
implement a custom polling or interrupt based scheme to ensure that any
incoming packets are processed by the core.
* @{
*/
/*! \brief Wakeup callback function.
*
* Invoked when the WiFi device should wake up from power save mode.
* This function should send the proper commands to the device.
*
* Note that this type should only be used in custom environments, where
* the transport library is not used.
*
* @param ctx Opaque context pointer as provided to \a wl_register_wakeup_cb()
* that will be passed back to the callback.
* @param wakeup indicates whether wakeup should be set or cleared in the
* device.
*/
typedef void (wl_wakeup_cb_t)(void* ctx, uint8_t wakeup);
/*! \brief Register wakeup callback function.
*
* Register a function that will be invoked when the WiFi device should wake
* up from power save mode.
*
* Note that this function should only be used in custom environments, where
* the transport library is not used.
*
* @param wakeup_cb Will be invoked when the device should wakeup from sleep
* mode.
* @param ctx Opaque context pointer that will be passed back to the callback.
*/
void wl_register_wakeup_cb(wl_wakeup_cb_t *wakeup_cb, void *ctx);
/*! \brief Management tx callback function.
*
* Invoked when the a management message should be transmitted to the
* WiFi device. This function should ensure that the message is passed through
* to the device and should never fail.
*
* Note that this type should only be used in custom environments, where
* the transport library is not used.
*
* @param ctx Opaque context pointer as provided to \a wl_register_mgmt_tx_cb()
* that will be passed back to the callback.
* @param buf Points to the buffer which holds the management data,
* @param len Size of the buffer.
*/
typedef void (wl_mgmt_tx_cb_t)(void *ctx, const uint8_t *buf, uint16_t len);
/*! \brief Register management tx callback function
*
* Register a function that will be invoked when a management message should
* be transmitted to the device.
*
* Note that this function should only be used in custom environments, where
* the transport library is not used.
*
* IMPORTANT : In a custom environment without a transport library \a
* wl_register_mgmt_tx_cb() \b must have been called
* before \a wl_fw_download() is called since \a
* wl_fw_download() depends on the \a mgmt_tx_cb() to send
* the firmware data to the WiFi chip.
*
* @param mgmt_tx_cb The callback function to invoke.
* @param ctx Opaque context pointer that will be passed back to the callback.
*/
void wl_register_mgmt_tx_cb(wl_mgmt_tx_cb_t *mgmt_tx_cb, void *ctx);
/*! \brief Download the WiFi firmware image to the device.
*
* This operation will proceed synchronously until the firmware is completely
* downloaded. wl_init() should be called after this function has returned to
* perform device initialization. This function depends on \a
* wl_register_mgmt_tx_cb(). See that function for details.
*
* @param ctx Opaque context pointer that will be passed to the callbacks
* when they are invoked. This parameter is never
* accessed by the API.
* @param fw_read_cb callback function to invoke during firmware download.
*
* @return
*
* - WL_CARD_FAILURE if the wl hardware device is not available
* - WL_FIRMWARE_INVALID if the firmware obtained through fw_read_cb is
* invalid.
* - WL_OOM if the necessary memory could not be allocated.
*/
wl_err_t wl_fw_download(wl_fw_read_cb_t *fw_read_cb, void *ctx);
/*! @} */ /* End wl_custom group */

View File

@ -1,50 +1,13 @@
/* This header file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
/*! \page License
* Copyright (C) 2009, H&D Wireless AB All rights reserved.
/*
* Programming interface for wl_api.
* Copyright (C) 2010 HD Wireless AB
*
* The license to use this software in whole and in part and to
* redistribute it in any form follows with the WiFi HW module from H&D
* Wireless and is granted under the following restrictions:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. 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.
*
* 3. The name of H&D Wireless AB may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* 4. The software may only be used together with hardware from H&D
* Wireless all other use is prohibited.
*
* 5. The license to use and redistribute the software is granted
* together with the purchase of a hardware platform on a one to one
* basis
*
* 6. The binary code may not be reversed engineered or by other means
* copied to circumvent this license.
*
* THIS SOFTWARE IS PROVIDED BY H&D WIRELESS AB ``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 EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT
* SHALL HD WIRELESS AB 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.
*
* For more information regarding this software license Contact H&D
* Wireless AB (support@hd-wireless.se).
* You should have received a copy of the license along with this library.
*/
#ifndef WITHOUT_STDINT
#include <stdint.h>
#endif
const uint8_t fw_buf[154188] = {
0x10, 0x61, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
0x30, 0x00, 0x00, 0x00, 0x10, 0x61, 0x04, 0x00,
@ -11319,7 +11282,7 @@ const uint8_t fw_buf[154188] = {
0x24, 0x01, 0x07, 0x00, 0x32, 0x00, 0x00, 0x00,
0xe8, 0x03, 0x00, 0x00, 0x40, 0x06, 0x01, 0x00,
0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x4e, 0x61, 0x6e, 0x6f, 0x72, 0x61, 0x64, 0x69,
0x41, 0x6e, 0x62, 0x69, 0x7e, 0x64, 0x61, 0x6f,
0x6f, 0x00, 0x00, 0x00, 0x52, 0x65, 0x6c, 0x65,
0x61, 0x73, 0x65, 0x20, 0x36, 0x5f, 0x37, 0x5f,
0x31, 0x35, 0x20, 0x42, 0x75, 0x69, 0x6c, 0x64,
@ -11819,8 +11782,8 @@ const uint8_t fw_buf[154188] = {
0x00, 0x00, 0x00, 0x00, 0x38, 0x4e, 0x01, 0x00,
0x0e, 0x00, 0x00, 0x64, 0x9c, 0x57, 0x01, 0x01,
0x91, 0x88, 0x41, 0xe3, 0x3c, 0x00, 0x38, 0x4e,
0x01, 0x00, 0x4e, 0x61, 0x6e, 0x6f, 0x72, 0x61,
0x64, 0x69, 0x6f, 0x20, 0x41, 0x42, 0x00, 0x00,
0x01, 0x00, 0x6e, 0x41, 0x67, 0x6f, 0xe2, 0x65,
0x60, 0x69, 0x6f, 0x20, 0x41, 0x42, 0x00, 0x00,
0x00, 0x00, 0xf0, 0x4d, 0x01, 0x00, 0x09, 0x00,
0x00, 0x0a, 0x48, 0x4e, 0x01, 0x00, 0x01, 0x00,
0x00, 0x0a, 0xe8, 0x4d, 0x01, 0x00, 0x01, 0x00,

View File

@ -0,0 +1,35 @@
#ifndef WL_OS_H
#define WL_OS_H
#include <stdarg.h>
#include <stdlib.h>
void *owl_os_alloc(size_t size);
void *owl_os_realloc(void *ptr, size_t size);
void owl_os_free(void *p);
void *owl_os_memcpy(void *dst, const void *src, size_t n);
void *owl_os_memset(void *s, int c, size_t n);
void *owl_os_memmove(void *dst, const void *src, size_t n);
size_t owl_os_strlen(char *s);
char *owl_os_strncpy(char *dst, const char *src, size_t n);
int owl_os_strncmp(const char *s1, const char *s2, size_t n);
int owl_os_strcmp(const char *s1, const char *s2);
char *owl_os_strcpy(char *dst, const char *src);
char *owl_os_strdup(const char *s);
char *owl_os_strndup(const char *s, size_t n);
int owl_os_memcmp(const void *s1, const void *s2, size_t n);
long int owl_os_strtol(const char *nptr, char **endptr, int base);
char *owl_os_strchr(const char *s, int c);
char *owl_os_strrchr(const char *s, int c);
int owl_os_strcasecmp(const char *s1, const char *s2);
char *owl_os_strstr(const char *haystack, const char *needle);
int owl_os_snprintf(char *str, size_t size, const char *format, ...)
__attribute__((format(printf, 3, 4)));
int owl_os_vprintf(const char *format, va_list arg); /* debug only */
int owl_os_printf(const char *format, ...) /* debug only */
__attribute__((format(printf, 1, 2)));
#endif /* WL_OS_H */

View File

@ -0,0 +1,172 @@
/*!
* \file wl_sdio.h
* \brief SDIO interface for wl_api.
* Copyright (C) 2010 HD Wireless AB
*
* You should have received a copy of the license along with this library.
*/
#ifndef WL_SDIO_H
#define WL_SDIO_H
/** \defgroup wl_sdio SDIO Interface
*
* These functions implement the interface that the wl_api library
* needs to work with a SDIO transport layer.
*
* The functions prototyped here must be implemented when porting the
* wl_api library to a new platform with a different SDIO configuration
*
* On platforms supported by H&D Wireless these functions are
* implemented in the file avr32_sdio.c
*
* @{
*/
/**
* Maximum transfer size. This will set an upper limit on the len parameter
* passed to owl_sdio_tx() and owl_sdio_rx().
*
*/
#define MAX_BLOCK_LEN 512
/**
* This flag might be set when owl_sdio_cmd() is called in case the cmd will
* be followed by a data transfer. If the flag is set, the transfer direction is
* from the device to the host (read). Otherwise, the transfer direction is
* from the host to the device (write).
*
*/
#define CMD_FLAG_TO_HOST (1 << 0)
/**
* Indicates that the sdio driver needs to be polled in order to make
* forward progress, i.e. it does not support interrupts
*
* The actual polling will result in owl_sdio_cmd() being called to
* request status information from the device.
*
* To activate polling, this flag should be set in owl_sdio_init().
*/
#define SDIO_FLAG_POLL (1 << 0)
/**
* Indicates that the sdio driver only supports 1-bit mode.
*
* To set 1-bit mode, this flag should be set in owl_sdio_init().
*/
#define SDIO_FLAG_1BIT_MODE (1 << 1)
/**
* This function will be invoked when wlan initialization should be performed,
* this happens when the wl_fw_download() function in the transport group of
* wl_api is invoked.
*
* The wifi device supports sdio high speed mode and clock frequencies up to
* 50 MHz.
*
* The function is responsible for doing any necessary sdio initialization such
* as allocating gpio's, setting up the mci master, one time allocations of
* dma buffers etc.
*
* @param flags is an out parameter that should hold any sdio flags upon return.
* The avaible flags are prefixed with SDIO_FLAG_
*
*
*/
void owl_sdio_init(uint8_t *flags);
/**
* This function will be invoked when an sdio cmd should be sent to the
* device.
*
* @param idx is the sdio command number
* @param arg is the sdio command argument
* @param flags specifies other options, such as any transfer direction.
* @param rsp should hold the command response upon return. If null, the
* response can be ignored.
* @param data holds a pointer to any data that might follow the command. This
* allows the sdio driver to setup dma transfers while waiting for the
* command response. NULL if no data transfer will follow. Note that
* the same data pointer will be passed to owl_sdio_tx(), which should
* start the actual transfer.
* @param len is the length of the data buffer.
*
*/
void owl_sdio_cmd(uint8_t idx, uint32_t arg, uint8_t flags, uint32_t *rsp,
const uint8_t *data, uint16_t len);
/**
* This function will be invoked when data should be transmitted to the device.
*
* If wl_fw_downlad() was called with the size_align parameter set to non-zero,
* the pad parameter should be used. If the pad parameter is not 0, additional
* data must be transmitted after the data buffer has be sent. Depending on
* how the data buffer was first allocated (probably by an TCP/IP stack), it
* might be safe or unsafe to continue reading beyond the data buffer to
* transmit the additional padding bytes.
*
* @param data holds a pointer to the data to transmit, the pointer is the
* same as the one passed to wl_tx().
* @param len is the number of bytes that should be transmitted, including
* padding.
* @param pad is the number of padding bytes to send.
*
*/
void owl_sdio_tx(const uint8_t *data, uint16_t len, uint8_t pad);
/**
* This function will be invoked when data should be received from the device.
*
* @param data should hold the read data upon return.
* @param len is the number of bytes to read.
*
*/
void owl_sdio_rx(uint8_t *data, uint16_t len);
/**
* Invoked when sdio rx interrupts from the device should be enabled or
* disabled.
*
* If SDIO_FLAG_POLL was set in wl_spi_init(), then this function can be
* left empty.
*
* @param enable specifies if interrupts should be enabled or disabled.
*
*/
void owl_sdio_irq(uint8_t enable);
/**
* Delay executiom for the specified number of ms. This function will be called
* with delays in the 10-20 ms range during fw download and startup of the
* Wi-Fi device. This function can be implemented with a simple for-loop if
* desired (beware of optimization). The timing does not have to be accurate as
* long as the actual delay becomes at least the specified number of ms.
*
* @param ms is the minimal amount of time to wait [ms].
*
*/
void owl_sdio_mdelay(uint32_t ms);
/**
* This function should be called whenever an interrupt is detected. It can
* be called from an interrupt context.
*
* If SDIO_FLAG_POLL was set in owl_sdio_init(), then wl_sdio_irq()
* should never be called.
*
*/
extern void wl_sdio_irq(void);
/*! @} */
#endif

View File

@ -0,0 +1,185 @@
/*!
* \file wl_spi.h
* \brief SPI interface for wl_api.
* Copyright (C) 2010 HD Wireless AB
*
* You should have received a copy of the license along with this library.
*/
#ifndef WL_SPI_H
#define WL_SPI_H
#ifndef WITHOUT_STDINT
#include <stdint.h>
#endif
/** \defgroup wl_spi SPI Interface
*
* These functions implement the interface that the wl_api library
* needs to work with a SPI transport layer.
*
* The functions prototyped here must be implemented when porting the
* wl_api library to a new platform with a different SPI configuration
*
* On platforms supported by H&D Wireless these functions are
* implemented in the file avr32_spi.c
*
* @{
*/
/**
* Maximum transfer size. This will set an upper limit on the len parameter
* passed to owl_spi_txrx().
*
*
*/
#define MAX_BLOCK_LEN 512
/**
* Indicates that the spi driver needs to be polled in order to make
* forward progress, i.e. it does not support interrupts through SD pin 8.
*
* The actual polling will result in owl_spi_txrx() being call to
* request status information from the device.
*
* To activate polling, this flag should be set in owl_spi_init().
*
* See wl_poll() and wl_register_rx_isr() for more information regarding
* polled and interrupt modes.
*
*/
#define SPI_FLAG_POLL (1 << 0)
/**
* This function will be invoked when wlan device initialization should be
* performed, this happens when the wl_fw_download() function in the transport
* group of wl_api is invoked.
*
* The wifi device requires spi mode 3, i.e. clock polarity high and sample
* on second phase. This corresponds to CPOL=1, CPHA=1. Maximum frequency on
* spi clock is 30 MHz.
*
* The function is also responsible for doing any necessary spi initialization
* such as allocating gpio's, setting up the SPI master, one time allocations of
* dma buffers etc.
*
*
* If the SPB105 device is used, two signals; POWER (pin 10 on SPB105) and
* SHUTDOWN (pin 4 on SPB105) might be connected to gpio's on the host.
* The GPIO_POWER_PIN is the main power supply to the device. The
* GPIO_SHUTDOWN_PIN (active low) should be defined as an input.
*
* After GPIO_POWER_PIN is pulled high by the host, the device will pull the
* GPIO_SHUTDOWN_PIN high once the device is properly powered.
*
* However, if pin 4 (GPIO_SHUTDOWN_PIN) is not connected to the host, a delay
* of up to 250 ms must be added after GPIO_POWER_PIN is pulled high to ensure
* that startup is completed. The actual time is usually much shorter, therefore
* one might try to reduce the delay for a particualar hardware design.
*
* On SPB104, the GPIO_POWER_PIN will be connected to VCC and GPIO_SHUTDOWN_PIN
* will be unconnected; hence we have to make sure that we have enough delay
* after powering on the host. Since the device power-on usually happens at the
* same time as the host power-on, the startup time of the host can be
* subtracted from any delay put into owl_spi_init().
*
* @param flags is an out parameter that should hold any spi flags upon return.
* The avaible flags are prefixed with SPI_FLAG_
*
* @return 0 on success
* -1 if any error occurs
*
*/
int owl_spi_init(uint8_t *flags);
/**
* Invoked when a spi transfer should be performed.
*
* All buffers that are allocated by the wl library will have a size that is
* aligned to 4. If size-unaligned data is passed to this function, it is
* always allocated by the ip stack. If 4-byte size alignment (e.g. for DMA)
* is required, 1-3 extra padding bytes can be transmitted after the in buffer.
* These bytes must be 0xff.
*
* Since size-unaligned data always comes from the ip stack, the out ptr is
* always NULL for such data.
*
* @param in points a buffer which holds the data to be transmitted. If NULL,
* then \a len bytes with the value 0xff should be transmitted on the
* bus.
* @param out points a buffer should hold the data received from the device. If
* NULL, any received data can be discarded.
* @param len is the length of the in and out buffers.
*
*/
void owl_spi_txrx(const uint8_t *in, uint8_t* out, uint16_t len);
/**
* Invoked when spi rx interrupts from the device should be enabled or disabled.
* Note that the spi interrupts are obtained from pin 8 on SPB104 or pin 3 from
* SPB105. This pin can be be connected to a gpio on the host. The irq line
* will signal an interrupt on both edges.
*
* In general, the wifi device will not issue a new interrupt unless the
* last interrupt has been handled. Also, during normal operation (i.e after
* the complete callback registered in wl_init() has been invoked),
* owl_spi_irq() will never be invoked so interrupts will be enabled all
* the time. For the SPI-mode, the purpose of owl_spi_irq() is basically to
* make sure that the first interrupt (coming after the reset performed in
* owl_spi_init()) is ignored.
*
* If SPI_FLAG_POLL was set in owl_spi_init(), then this function can be
* left empty and the wifi device will be used in polled mode. In polled mode,
* the interrupt line is not used. Regardless of polled or interrupt-mode,
* wl_poll() must be called to ensure progress of the driver.
*
* @param enable specifies if interrupts should be enabled or disabled.
*
*/
void owl_spi_irq(uint8_t enable);
/**
* Invoked when the spi cs for the wifi device should be enabled. Note that
* multiple calls to owl_spi_txrx() might be done during a 'single' chip
* select.
*
* @param enable specifies whether chip select should be asserted or deasserted,
* The chip select signal is active low, so if enable is '1' then the
* chip select connected to the wifi device should be set to '0'.
*
*/
void owl_spi_cs(uint8_t enable);
/**
* Delay executiom for the specified number of ms. This function will be called
* with delays in the 10-20 ms range during fw download and startup of the
* Wi-Fi device. This function can be implemented with a simple for-loop if
* desired (beware of optimization). The timing does not have to be accurate as
* long as the actual delay becomes at least the specified number of ms.
*
* @param ms is the minimal amount of time to wait [ms].
*
*/
void owl_spi_mdelay(uint32_t ms);
/**
* This function should be called whenever an interrupt is detected. It can
* be called from an interrupt context.
*
* If SPI_FLAG_POLL was set in owl_spi_init(), then wl_spi_irq()
* should never be called.
*
*/
extern void wl_spi_irq(void);
/*! @} */
#endif

View File

@ -0,0 +1,154 @@
/*
* Programming interface for wlap_api.
* Copyright (C) 2011 HD Wireless AB
*
* You should have received a copy of the license along with this library.
*/
/*! \file wlap_api.h *************************************************************
*
* \brief WiFi AP API
*
* This file provides the wlap_api interface.
*
* - Compiler: GNU GCC for AVR32
* - Supported devices:
* \li SPB104 + EVK1100
* \li SPB104 + EVK1101
* \li SPB104 + EVK1104
* \li SPB104 + EVK1105 (SPI)
* \li SPB104 + EVK1105 (SPI + irq)
* \li SPB105 + EVK1105 (SPI)
* - AppNote:
*
* \author H&D Wireless AB: \n
*
*****************************************************************************
*
* \section intro Introduction
* This is the documentation for the WiFi AP Driver API \a wlap_api.
*
* \section files Main Files
* - wlap_api.h : WiFi driver interface.
* - libwlap_api_*.*.a - Driver library.
*
*/
#ifndef WLAP_API_H
#define WLAP_API_H
#define WLAP_API_RELEASE_NAME "unknown"
#include <wl_api.h>
/** \defgroup wl_softap Access Point Mode
*
* \brief Support the WiFi Access Point mode.
*
* @{
*/
/*
* Station representation
*
*/
struct wl_sta_t
{
struct wl_mac_addr_t bssid; /**< The BSSID of the network. */
uint8_t queued_pkt_cnt; /**< Number of queueud packets for
this STA. */
uint8_t in_ps; /**< Is the STA in power save mode. */
uint8_t aid; /**< STA AID */
};
/* Station list representation. Array of pointers to wl_sta_t entries. */
struct wl_sta_list_t
{
struct wl_sta_t **sta; /**< The list of pointers to stations */
size_t cnt; /**< Number of stations */
};
/*! \brief Get the list of currently associated stations (SoftAP).
*
* Retrieves the list of current stations from
* the driver.
*
* This function is not thread safe. It must be called in the
* same execution context as wl_poll().
*
* @param network_list Output buffer. The API call returns
* a pointer to allocated memory containing the network list.
* @return
* - WL_SUCCESS
* - WL_FAILURE.
*/
wl_err_t wlap_get_sta_list(struct wl_sta_list_t **network_list);
/*! Callback used to read data from a TX packet.
* This function is supplied by the user of the API.
*
* @param dst Destination buffer. The data should be copied
* to this buffer.
* @param src_handle Handle to the source packet from where
* the data should be copied. This handle is the same one that
* is passed in parameter \a pkt_handle to \a wl_process_tx().
* @param read_len Number of bytes to copy from \a src_handle
* to \a dst.
* @param offset The offset in bytes, counting from the
* beginning of the Ethernet header, from where to copy data.
* @return
* - The number of bytes copied. This number may be smaller
* than the length requested in \a read_len but it may not
* be shorter than the length of the packet counting from
* \a offset. In other words, if the caller of this function
* receives a return count that is shorter than \a read_len
* he will assume that all packet data has been read.
* - < 0 on error.
*/
typedef ssize_t (*wl_pkt_read_cb_t)(char *dst,
void *src_handle,
size_t read_len,
int offset);
/*! \brief Register a data access function for TX packets (SoftAP).
*
* When a TX data packet has a different representation than a single
* contiguous buffer in memory then a packet read function must be
* implemented and registered with this call. Whenever the library
* needs to read packet data it will call this function to do it.
*
* This function can be ignored if the TX packet representation is
* a single contiguous buffer. This function is only needed in SoftAP
* mode.
*
* @param pkt_read_cb Read callback.
* @param ctx Context
*/
void wl_register_pkt_read_cb(wl_pkt_read_cb_t pkt_read_cb);
/*! \brief Start a network using the SoftAP mode.
*
* This call will cause the WiFi chip to start sending beacons
* and accept associations from WiFi stations.
*
*/
wl_err_t wlap_start_ap(const char *ssid,
const size_t ssid_len,
const uint8_t channel,
const enum wl_auth_mode auth_mode,
const enum wl_enc_type enc_type);
/*! \brief Disconnect a STA (SoftAP)
*
* @param bssid The BSSID of the station to disconnect.
* @return
* - WL_SUCCESS
* - WL_FAILURE.
*/
wl_err_t wlap_disconnect_sta(const struct wl_mac_addr_t bssid);
/*! @} */ /* End wl_softap group */
#endif

View File

@ -1,5 +1,3 @@
/* This header file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* All rights reserved.
@ -34,11 +32,6 @@
#ifndef __ARCH_CC_H__
#define __ARCH_CC_H__
/* Include some files for defining library routines */
#include <string.h>
#include <sys/time.h>
#include "printf-stdarg.h"
/* Define platform endianness */
#ifndef BYTE_ORDER
#define BYTE_ORDER BIG_ENDIAN
@ -68,13 +61,19 @@ typedef u32_t mem_ptr_t;
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_END
/* prototypes for printf() and abort() */
#include <stdio.h>
#include <stdlib.h>
/* Plaform specific diagnostic output */
#define LWIP_PLATFORM_DIAG(x) do {printk x;} while(0)
#ifdef CONFIG_OWL
# include <owl/core/owl_debug.h>
# define LWIP_PLATFORM_DIAG(x) owl_printf x
# define LWIP_PLATFORM_ASSERT(x) owl_assert(x)
#else
# include <printf-stdarg.h>
# define LWIP_PLATFORM_DIAG(x) do { printk x; } while(0)
# define LWIP_PLATFORM_ASSERT(x) do { \
printk("Assertion \"%s\" failed at line " \
"%d in %s\n", \
x, __LINE__, __FILE__); while(1); \
} while(0)
#endif
#define LWIP_PLATFORM_ASSERT(x) do {printk("Assertion \"%s\" failed at line %d in %s\n", \
x, __LINE__, __FILE__); fflush(NULL); abort();} while(0)
#endif /* __ARCH_CC_H__ */

View File

@ -1,5 +1,3 @@
/* This header file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
#ifndef __PERF_H__
#define __PERF_H__

View File

@ -1,5 +1,3 @@
/* This header file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
#ifndef __NETIF_NRWLANIF_H__
#define __NETIF_NRWLANIF_H__

View File

@ -1,5 +1,3 @@
/* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
@ -8,7 +6,8 @@
#include "lwip/sys.h"
#include "netif/etharp.h"
#include "netif/wlif.h"
#include "wl_api.h"
#include <wl_api.h>
#include <wlap_api.h>
#define IFNAME0 'w'
#define IFNAME1 'l'
@ -70,7 +69,8 @@ static err_t process_pqueue(struct netif* netif)
p->len - WL_HEADER_SIZE, /* input buffer len */
p->tot_len - WL_HEADER_SIZE, /* pkt len */
p->payload, /* ptr to WE hdr */
0); /* prio */
0, /* prio */
p); /* pkt handle */
/* if we fail due to power save mode, leave packet in queue and
* try again when target is awake again (upon WL_RX_EVENT_WAKEUP).
@ -127,8 +127,10 @@ static err_t
low_level_init(struct netif *netif)
{
/* device capabilities */
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP |
NETIF_FLAG_LINK_UP;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP |
NETIF_FLAG_IGMP;
/* NETIF_FLAG_LINK_UP must be set only when we have an wlan assoc */
/* set MAC hardware address length */
netif->hwaddr_len = ETHARP_HWADDR_LEN;
@ -207,14 +209,19 @@ low_level_input(struct netif *netif)
/* We allocate a continous pbuf */
p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM);
if (p == NULL)
if (p == NULL) {
LWIP_DEBUGF(NETIF_DEBUG, ("low_level_input: fail to alloc "
"pbuf of len:%"S32_F"\n", len));
return NULL;
}
/* Read the entire msg */
wl_rx(p->payload, &len);
priv->rx_pending = 0;
if (len == 0)
wl_rx(p->payload, &len);
if (len == 0) {
LWIP_DEBUGF(NETIF_DEBUG, ("low_level_input: len was 0"));
return NULL;
}
status = wl_process_rx(
p->payload, /* input buf */
@ -224,6 +231,7 @@ low_level_input(struct netif *netif)
&vlan);
if (status == WL_ABSORBED) {
LWIP_DEBUGF(NETIF_DEBUG, ("low_level_input: absorbed"));
pbuf_free(p);
return NULL;
}
@ -284,6 +292,23 @@ wlif_input(struct netif *netif)
}
}
static ssize_t pkt_read_cb(char *dst,
void *src_handle,
size_t read_len,
int offset) {
ssize_t rc;
rc = pbuf_copy_partial((struct pbuf *)src_handle,
dst,
read_len,
offset + WL_HEADER_SIZE);
if ( 0 == rc ) {
return -1;
}
return rc;
}
/**
* Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
@ -299,13 +324,15 @@ wlif_input(struct netif *netif)
err_t
wlif_init(struct netif *netif)
{
static struct wlif_t wlif = { 0 };
static struct wlif_t wlif;
LWIP_ASSERT("netif != NULL", (netif != NULL));
#if LWIP_NETIF_HOSTNAME
/* Initialize interface hostname */
netif->hostname = "wlif";
if ( NULL == netif->hostname ) {
netif->hostname = "wlif";
}
#endif /* LWIP_NETIF_HOSTNAME */
netif->state = &wlif;
@ -320,6 +347,7 @@ wlif_init(struct netif *netif)
netif->linkoutput = low_level_output;
wl_register_rx_isr(rx_isr, netif);
wl_register_pkt_read_cb(pkt_read_cb);
/* initialize the hardware */
return low_level_init(netif);
@ -332,7 +360,13 @@ wlif_init(struct netif *netif)
void
wlif_poll(struct netif* netif)
{
struct wlif_t* priv = (struct wlif_t*) netif->state;
struct wlif_t* priv = NULL;
/* wl api forward progress */
wl_poll();
if (netif)
priv = (struct wlif_t*) netif->state;
/* wlif_init() not called yet? */
if (priv == NULL)

View File

@ -18,12 +18,12 @@
#include "ard_utils.h"
#include "intc.h"
#include "spi.h"
#include "clocks.h"
#include "debug.h"
#include "delay.h"
#include "eic.h"
#include "timer.h"
#include "lwip/dns.h"
#include <board_init.h>
@ -165,10 +165,12 @@ void* mapSockTCP[MAX_SOCK_NUM];
struct netif* ard_netif = NULL;
// Network list retrived in the last scanNetwork
static struct wl_network_t network_list[WL_NETWORKS_LIST_MAXNUM];
static struct wl_network_list_t network_list = { 0 };
struct ip_addr _hostIpAddr;
static hostIpAddrFound = false;
void* getTTCP(uint8_t sock)
{
if (sock < MAX_SOCK_NUM)
@ -497,7 +499,7 @@ int set_key_cmd_cb(int numParam, char* buf, void* ctx) {
memset(&bssid.octet, 0xff, sizeof bssid.octet);
wl_add_wep_key(idx, len, key, &bssid);
wl_set_auth_mode(AUTH_MODE_SHARED_KEY);
//wl_set_auth_mode(AUTH_MODE_SHARED_KEY);
wl_set_default_wep_key(idx);
//Connect
@ -769,8 +771,9 @@ cmd_spi_state_t get_reply_ipaddr_cb(char* recv, char* reply, void* ctx, uint16_t
void foundHostByName(const char *name, struct ip_addr *ipaddr, void *callback_arg)
{
INFO_SPI("foundHostByName: Found Host: name=%s ip=0x%x\n", name, ipaddr->addr);
_hostIpAddr.addr = ipaddr->addr;
_hostIpAddr.addr = (ipaddr)?ipaddr->addr:0xffffffff;
INFO_SPI("foundHostByName: Found Host: name=%s ip=0x%x\n", name, _hostIpAddr.addr);
hostIpAddrFound = true;
}
int req_reply_host_by_name_cb(int numParam, char* buf, void* ctx) {
@ -786,11 +789,14 @@ int req_reply_host_by_name_cb(int numParam, char* buf, void* ctx) {
RETURN_ERR(WL_FAILURE)
}
INFO_SPI("Looking for Host: name=%s\n", hostName);
_hostIpAddr.addr = 0;
hostIpAddrFound = false;
err_t err = dns_gethostbyname(hostName, &_hostIpAddr, foundHostByName, NULL);
if (err == ERR_OK)
{
INFO_SPI("Found Host: name=%s ip=0x%x\n", hostName, _hostIpAddr.addr);
hostIpAddrFound = true;
RETURN_ERR(WL_SUCCESS)
}
RETURN_ERR(WL_FAILURE)
@ -798,11 +804,14 @@ int req_reply_host_by_name_cb(int numParam, char* buf, void* ctx) {
cmd_spi_state_t get_reply_host_by_name_cb(char* recv, char* reply, void* ctx, uint16_t* count) {
u32_t addr = (hostIpAddrFound)?_hostIpAddr.addr : 0xffffffff;
INFO_SPI("Searching for Host: ip=0x%x found=%d\n", addr, hostIpAddrFound);
CHECK_ARD_NETIF(recv, reply, count);
CREATE_HEADER_REPLY(reply, recv, 1);
PUT_LONG_IN_BYTE_NO(_hostIpAddr.addr, reply, 3);
PUT_LONG_IN_BYTE_NO(addr, reply, 3);
END_HEADER_REPLY(reply, 8, *count);
@ -906,23 +915,23 @@ cmd_spi_state_t get_reply_idx_net_cb(char* recv, char* reply, void* ctx, uint16_
default:
case GET_IDX_SSID_CMD:
{
len = network_list[idx].ssid.len;
PUT_BUFDATA_BYTE(network_list[idx].ssid.ssid, len, reply, 3);
INFO_UTIL("SSID:%s\n", network_list[idx].ssid.ssid);
len = network_list.net[idx]->ssid.len;
PUT_BUFDATA_BYTE(network_list.net[idx]->ssid.ssid, len, reply, 3);
INFO_UTIL("SSID:%s\n", network_list.net[idx]->ssid.ssid);
break;
}
case GET_IDX_RSSI_CMD:
{
len = 4;
PUT_LONG_IN_BYTE_HO(network_list[idx].rssi, reply, 3);
INFO_UTIL("RSSI:%d\n", network_list[idx].rssi);
PUT_LONG_IN_BYTE_HO(network_list.net[idx]->rssi, reply, 3);
INFO_UTIL("RSSI:%d\n", network_list.net[idx]->rssi);
break;
}
case GET_IDX_ENCT_CMD:
{
len = 1;
PUT_DATA_BYTE(network_list[idx].enc_type, reply, 3);
INFO_UTIL("ENCT:%d\n", network_list[idx].enc_type);
PUT_DATA_BYTE(network_list.net[idx]->enc_type, reply, 3);
INFO_UTIL("ENCT:%d\n", network_list.net[idx]->enc_type);
break;
}
}
@ -935,6 +944,37 @@ cmd_spi_state_t get_reply_idx_net_cb(char* recv, char* reply, void* ctx, uint16_
return SPI_CMD_DONE;
}
static void copy_network_list(struct wl_network_list_t *dst,
struct wl_network_list_t *src)
{
int i;
for (i = 0; i < dst->cnt; i++)
free(dst->net[i]);
free(dst->net);
dst->cnt = 0;
if (src->cnt == 0)
return;
dst->net = calloc(1, src->cnt * sizeof(struct wl_network_t *));
if (dst->net == NULL) {
printk("could not allocate all gui net array\n");
return;
}
for (i = 0; i < src->cnt; i++) {
struct wl_network_t *net = src->net[i];
dst->net[i] = malloc(sizeof(*net));
if (dst->net[i] == NULL) {
printk("could not allocate all gui nets\n");
return;
}
memcpy(dst->net[i], net, sizeof(*net));
dst->cnt++;
}
}
cmd_spi_state_t get_reply_scan_networks_cb(char* recv, char* reply, void* ctx, uint16_t* count) {
@ -943,39 +983,38 @@ cmd_spi_state_t get_reply_scan_networks_cb(char* recv, char* reply, void* ctx, u
int network_cnt = 0;
struct wl_network_t* wl_network_list;
uint8_t wl_network_cnt;
struct wl_network_list_t* wl_network_list;
wl_get_network_list(&wl_network_list, &wl_network_cnt);
if (wl_network_cnt == 0)
wl_scan();
wl_get_network_list(&wl_network_list);
if (wl_network_list->cnt == 0)
{
CREATE_HEADER_REPLY(reply, recv, 0);
END_HEADER_REPLY(reply, 3, *count);
return SPI_CMD_DONE;
}
if (wl_network_cnt > WL_NETWORKS_LIST_MAXNUM)
if (wl_network_list->cnt > WL_NETWORKS_LIST_MAXNUM)
{
network_cnt = WL_NETWORKS_LIST_MAXNUM ;
}
else{
network_cnt = wl_network_cnt ;
network_cnt = wl_network_list->cnt ;
}
memcpy(network_list, wl_network_list,
sizeof(struct wl_network_t) * network_cnt);
copy_network_list(&network_list, wl_network_list);
CREATE_HEADER_REPLY(reply, recv, network_cnt);
uint8_t start = 3;
int ii = 0;
for (; ii < network_cnt; ii++)
{
uint8_t len = network_list[ii].ssid.len;
PUT_BUFDATA_BYTE(network_list[ii].ssid.ssid, len, reply, start);
uint8_t len = network_list.net[ii]->ssid.len;
PUT_BUFDATA_BYTE(network_list.net[ii]->ssid.ssid, len, reply, start);
start += len+1;
INFO_SPI("%d - %s - %d - %d - 0x%x\n",ii, network_list[ii].ssid.ssid, network_list[ii].enc_type,
network_list[ii].rssi, network_list[ii].bssid);
INFO_SPI("%d - %s - %d - %d - 0x%x\n",ii, network_list.net[ii]->ssid.ssid,
network_list.net[ii]->enc_type,
network_list.net[ii]->rssi, network_list.net[ii]->bssid);
}
END_HEADER_REPLY(reply, start, *count);

View File

@ -62,6 +62,8 @@ cmd_state_t cmd_resetStatSpi(int argc, char* argv[], void* ctx);
cmd_state_t cmd_gethostbyname(int argc, char* argv[], void* ctx);
cmd_state_t cmd_setDnsServer(int argc, char* argv[], void* ctx);
void showTTCPstatus();
int getSock(void * _ttcp);

View File

@ -1,5 +1,3 @@
/* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
/*! \page License
* Copyright (C) 2009, H&D Wireless AB All rights reserved.
*
@ -29,146 +27,142 @@
*/
#include <gpio.h>
#include <intc.h>
#include <avr32/io.h>
#include <compiler.h>
#include <string.h>
#include <board.h>
#include "printf-stdarg.h"
#include "platform_spi.h"
#include "delay.h"
/* This define can be removed if the SPI irq line from the SPB104 board is
* connected to a GPIO on the AVR.
*/
#if EXT_BOARD == SPB104
#define USE_POLL
#endif
#if BOARD == EVK1100
#define AVR32_SPI AVR32_SPI1
#define GPIO_IRQ_PIN AVR32_PIN_PB30 /* J16 pin 6, GPIO62 */
#define GPIO_IRQ AVR32_GPIO_IRQ_7
#define AVR32_PDCA_PID_TX AVR32_PDCA_PID_SPI1_TX
#define AVR32_PDCA_PID_RX AVR32_PDCA_PID_SPI1_RX
#define SPI_CS 1
#elif BOARD == EVK1101 /* only one SPI on 1101 */
#define GPIO_IRQ_PIN AVR32_PIN_PB00 /* GPIO32 */
#define GPIO_IRQ AVR32_GPIO_IRQ_4
#define AVR32_PDCA_PID_TX AVR32_PDCA_PID_SPI_TX
#define AVR32_PDCA_PID_RX AVR32_PDCA_PID_SPI_RX
#define SPI_CS 1
#elif BOARD == EVK1105
#define AVR32_SPI AVR32_SPI0
#define GPIO_IRQ_PIN AVR32_PIN_PB30 /* J16 pin 6, GPIO62 */
#define GPIO_IRQ AVR32_GPIO_IRQ_7
#define AVR32_PDCA_PID_TX AVR32_PDCA_PID_SPI0_TX
#define AVR32_PDCA_PID_RX AVR32_PDCA_PID_SPI0_RX
#if EXT_BOARD == SPB105
#define SPI_CS 2
#elif EXT_BOARD == SPB104
#define SPI_CS 1
#else /* EXT_BOARD */
#error
#endif
#elif BOARD == ARDUINO
//defined in arduino.h
#else /* BOARD */
#error
#endif
#include <stdint.h>
#include <stdlib.h>
#include <wl_spi.h>
#include <printf-stdarg.h>
#include <board_init.h>
#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])
__attribute__((__interrupt__)) void avr32_irq_handler(void);
void owl_spi_mdelay(uint32_t ms);
void platform_init(U8 *flags)
int owl_spi_init(U8 *flags)
{
#ifdef _ASSERT_ENABLE_ /* To silence warning if Assert() macro is empty */
volatile avr32_pm_t *pm = &AVR32_PM;
#endif
const gpio_map_t GPIO_MAP = {
/* EVK1100 pin configuration */
#if BOARD == EVK1100
{ AVR32_SPI1_NPCS_0_0_PIN, AVR32_SPI1_NPCS_0_0_FUNCTION },
{ AVR32_SPI1_NPCS_1_0_PIN, AVR32_SPI1_NPCS_1_0_FUNCTION },
{ AVR32_SPI1_MISO_0_0_PIN, AVR32_SPI1_MISO_0_0_FUNCTION },
{ AVR32_SPI1_MOSI_0_0_PIN, AVR32_SPI1_MOSI_0_0_FUNCTION },
{ AVR32_SPI1_SCK_0_0_PIN, AVR32_SPI1_SCK_0_0_FUNCTION },
/* EVK1101 pin configuration */
#elif BOARD == EVK1101
{ AVR32_SPI_NPCS_0_0_PIN, AVR32_SPI_NPCS_0_0_FUNCTION },
{ AVR32_SPI_NPCS_1_0_PIN, AVR32_SPI_NPCS_1_0_FUNCTION },
{ AVR32_SPI_MISO_0_0_PIN, AVR32_SPI_MISO_0_0_FUNCTION },
{ AVR32_SPI_MOSI_0_0_PIN, AVR32_SPI_MOSI_0_0_FUNCTION },
{ AVR32_SPI_SCK_0_0_PIN, AVR32_SPI_SCK_0_0_FUNCTION },
/* EVK1105 pin configuration */
#elif BOARD == EVK1105
{ AVR32_SPI0_NPCS_0_0_PIN, AVR32_SPI0_NPCS_0_0_FUNCTION },
#if SPI_CS == 1
{ AVR32_SPI0_NPCS_1_0_PIN, AVR32_SPI0_NPCS_1_0_FUNCTION },
#elif SPI_CS == 2
{ AVR32_SPI0_NPCS_2_0_PIN, AVR32_SPI0_NPCS_2_0_FUNCTION },
volatile avr32_spi_t *spi = &WL_SPI;
#if WL_SPI_CS == 1
volatile avr32_spi_csr1_t* CSR = &spi->CSR1;
#elif WL_SPI_CS == 2
volatile avr32_spi_csr2_t* CSR = &spi->CSR2;
#elif WL_SPI_CS == 3
volatile avr32_spi_csr3_t* CSR = &spi->CSR3;
#elif SPI_CS == 0
volatile avr32_spi_csr0_t* CSR = &spi->CSR0;
#endif
{ AVR32_SPI0_MISO_0_0_PIN, AVR32_SPI0_MISO_0_0_FUNCTION },
{ AVR32_SPI0_MOSI_0_0_PIN, AVR32_SPI0_MOSI_0_0_FUNCTION },
{ AVR32_SPI0_SCK_0_0_PIN, AVR32_SPI0_SCK_0_0_FUNCTION },
#elif BOARD == ARDUINO
{ AVR32_SPI1_NPCS_0_0_PIN, AVR32_SPI1_NPCS_0_0_FUNCTION },
{ AVR32_SPI1_MISO_0_0_PIN, AVR32_SPI1_MISO_0_0_FUNCTION },
{ AVR32_SPI1_MOSI_0_0_PIN, AVR32_SPI1_MOSI_0_0_FUNCTION },
{ AVR32_SPI1_SCK_0_0_PIN, AVR32_SPI1_SCK_0_0_FUNCTION },
#else
#error
#endif
};
U32 i;
#ifndef WITH_NO_DMA
volatile avr32_pdca_channel_t *pdca_tx = &AVR32_PDCA.channel[0];
volatile avr32_pdca_channel_t *pdca_rx = &AVR32_PDCA.channel[1];
#endif
#ifdef USE_POLL
#ifndef WL_IRQ_PIN
*flags = SPI_FLAG_POLL;
#else
*flags = 0;
#endif
gpio_enable_module(GPIO_MAP, ARRAY_SIZE(GPIO_MAP));
for (i = 0; i < ARRAY_SIZE(GPIO_MAP); i++)
gpio_enable_pin_pull_up(GPIO_MAP[i].pin);
#ifdef WL_IRQ_PIN
/* input, irq */
gpio_enable_gpio_pin(GPIO_IRQ_PIN);
gpio_enable_pin_pull_up(GPIO_IRQ_PIN);
gpio_enable_gpio_pin(WL_IRQ_PIN);
gpio_enable_pin_pull_up(WL_IRQ_PIN);
#endif
/* shutdown pin */
gpio_set_gpio_pin(GPIO_W_SHUTDOWN_PIN);
//#ifdef WL_RESET_PIN
// /* reset pin */
// gpio_enable_gpio_pin(WL_RESET_PIN);
// gpio_set_gpio_pin(WL_RESET_PIN);
//#endif
delay_ms(10); //2ms
/* reset pin */
gpio_set_gpio_pin(GPIO_W_RESET_PIN);
#ifdef WL_POWER_PIN
/* power off the device */
gpio_enable_gpio_pin(WL_POWER_PIN);
gpio_set_gpio_pin(WL_POWER_PIN);
#endif
#ifdef WL_SHUTDOWN_PIN
gpio_enable_gpio_pin(WL_SHUTDOWN_PIN);
#ifdef WL_NO_INTERNAL_RESET /* never defined for SPB104/SPB105 */
gpio_clr_gpio_pin(WL_SHUTDOWN_PIN);
#endif
#ifdef WL_EXTERNAL_RESET
gpio_enable_gpio_pin(WL_RESET_PIN);
#endif
#endif /* WL_SHUTDOWN_PIN */
#ifdef WL_POWER_PIN
/* power on the device */
gpio_clr_gpio_pin(WL_POWER_PIN);
#endif
#ifdef WL_SHUTDOWN_PIN
#ifdef WL_NO_INTERNAL_RESET /* never defined for SPB104/SPB105 */
owl_spi_mdelay(5);
gpio_set_gpio_pin(WL_SHUTDOWN_PIN);
#elif WL_EXTERNAL_RESET
owl_spi_mdelay(5);
gpio_set_gpio_pin(WL_SHUTDOWN_PIN);
owl_spi_mdelay(20);
//delay_ms(10); //2ms
/* reset pin */
gpio_set_gpio_pin(WL_RESET_PIN);
#else
/* The shutdown pin will go high once the device is powered */
{
#define SHUTDOWN_TIMEOUT 350
uint32_t shutdown_timer = 0;
while (gpio_get_pin_value(WL_SHUTDOWN_PIN) == 0) {
if (shutdown_timer > SHUTDOWN_TIMEOUT)
{
printk("Timeout WL Shutdown\n");
return -1;
}
owl_spi_mdelay(5);
shutdown_timer += 5;
}
}
#endif /* WL_NO_INTERNAL_RESET */
#else
/* We need to make a guess about the time needed to power the device,
* this will depend on the hardware design.
*/
owl_spi_mdelay(5);
#endif /* WL_SHUTDOWN_PIN */
/* Note: SPI0 clock enabled at reset in pm->pbamask (see 13.6.3) */
Assert(pm->pbamask & (1 << 5));
/* Note: GPIO clock enabled at reset in pm->pbamask (see 13.6.3) */
Assert(pm->pbamask & (1 << 1));
#ifdef WL_IRQ_PIN
/* 22.4.7: "In every port there are four interrupt lines
* connected to the interrupt controller. Every eigth
* interrupts in the port are ored together to form an
* interrupt line."
*
* GPIO_IRQ_# = (GPIO_IRQ_PIN / 32) * 4 + (GPIO_IRQ_PIN / 8) % 4
* WL_IRQ_# = (WL_IRQ_PIN / 32) * 4 + (WL_IRQ_PIN / 8) % 4
* 62 => 1 * 4 + 3 = 7
*/
INTC_register_interrupt(&avr32_irq_handler, GPIO_IRQ, AVR32_INTC_INT0);
INTC_register_interrupt(&avr32_irq_handler, WL_IRQ, AVR32_INTC_INT0);
#endif
#ifndef WITH_NO_DMA
INTC_register_interrupt(&avr32_irq_handler, AVR32_PDCA_IRQ_0,
AVR32_INTC_INT0);
@ -177,37 +171,12 @@ void platform_init(U8 *flags)
pdca_tx->IER.terr = 1;
pdca_rx->IER.terr = 1;
#endif
}
void platform_reset(void)
{
volatile avr32_spi_t *spi = &AVR32_SPI;
#if SPI_CS == 1
volatile avr32_spi_csr1_t* CSR = &spi->CSR1;
#elif SPI_CS == 2
volatile avr32_spi_csr2_t* CSR = &spi->CSR2;
#elif SPI_CS == 0
volatile avr32_spi_csr0_t* CSR = &spi->CSR0;
#endif
/* Disable SPI controller during configuration */
spi->CR.spidis = 1;
/* SPI master mode */
spi->MR.mstr = 1;
/* fixed peripheral select */
spi->MR.ps = 0;
#if SPI_CS == 2
spi->MR.pcs = 0x3; /* cs2 */
#elif SPI_CS == 1
spi->MR.pcs = 0x1; /* cs1 */
#elif SPI_CS == 0
spi->MR.pcs = 0x0; /* cs0 */
spi->MR.modfdis = 0x1; /* disable Mode Fault DEtection */
#endif
#ifdef WL_SPI_CLOCK_DIVIDER
CSR->scbr = WL_SPI_CLOCK_DIVIDER;
#else
CSR->scbr = 2;
#endif
/* Use max width of TDR register, 16 bit transfers */
CSR->bits = 0x8;
@ -220,8 +189,13 @@ void platform_reset(void)
/* NRG component requires clock polarity high */
CSR->cpol = 1;
/* Enable SPI controller */
spi->CR.spien = 1;
#ifdef WL_IRQ_PIN
/* make sure to clear any pending bits in ifr here. */
gpio_clear_pin_interrupt_flag(WL_IRQ_PIN);
#endif
return 0;
}
#ifndef WITH_NO_DMA
@ -232,14 +206,14 @@ static void dma_txrx(const U8* in, U8* out, U16 len)
/* setup tx */
pdca_tx->mar = (U32) in;
pdca_tx->PSR.pid = AVR32_PDCA_PID_TX;
pdca_tx->PSR.pid = WL_PDCA_PID_TX;
pdca_tx->tcr = len / 2;
pdca_tx->MR.size = 1; /* 2-byte */
pdca_tx->IER.trc = 1;
/* setup rx */
pdca_rx->mar = (U32) out;
pdca_rx->PSR.pid = AVR32_PDCA_PID_RX;
pdca_rx->PSR.pid = WL_PDCA_PID_RX;
pdca_rx->tcr = len / 2;
pdca_rx->MR.size = 1; /* 2-byte */
pdca_rx->IER.trc = 1;
@ -256,10 +230,22 @@ static void dma_txrx(const U8* in, U8* out, U16 len)
/* access data using byte pointers since we might get unaligned
* data from lwip. The cpu will issue a data abort if we try
* to access data which is not properly aligned. See data sheet.
*
* Note that fifo_txrx() doesn't handle the case where len is not a
* multiple of two bytes properly.
*
* However, there is no actual case where len is odd at the same time
* as the "out" pointer is non-NULL; therefore I think that in practice,
* we'll not write beyond the end of the "out" array.
*
* The extra unknown byte fetched from the in pointer will be discarded
* by the device since a length field included in the packet header will inform
* the device of the actual number of valid bytes (this implementation is
* kind of hidden inside the library).
*/
static void fifo_txrx(const U8 *in, U8* out, U16 len)
{
volatile avr32_spi_t *spi = &AVR32_SPI;
volatile avr32_spi_t *spi = &WL_SPI;
UnionCPtr in_ptr;
UnionPtr out_ptr;
U32 sr;
@ -279,10 +265,9 @@ static void fifo_txrx(const U8 *in, U8* out, U16 len)
while (!spi->SR.tdre);
while (!spi->SR.txempty);
volatile U16 data= (in_ptr.u8ptr[0] << 8) | in_ptr.u8ptr[1];
/* prepare tx data register contents */
if (in_ptr.u8ptr) {
reg.TDR.td |= data; //(in_ptr.u8ptr[0] << 8) | in_ptr.u8ptr[1];
reg.TDR.td |= (in_ptr.u8ptr[0] << 8) | in_ptr.u8ptr[1];
in_ptr.u16ptr++;
}
else
@ -302,9 +287,6 @@ static void fifo_txrx(const U8 *in, U8* out, U16 len)
out_ptr.u16ptr++;
}
/* adjust remaining length. handle the case where len is not
* a multiple of 2 bytes.
*/
if (len >= 2)
len -= 2;
else
@ -316,7 +298,7 @@ static void fifo_txrx(const U8 *in, U8* out, U16 len)
Assert(!(sr & AVR32_SPI_SR_MODF_MASK));
}
void platform_txrx(const U8 *in, U8* out, U16 len)
void owl_spi_txrx(const U8 *in, U8* out, U16 len)
{
#ifndef WITH_NO_DMA
static uint8_t buf[MAX_BLOCK_LEN];
@ -338,47 +320,56 @@ void platform_txrx(const U8 *in, U8* out, U16 len)
#endif
}
void platform_spi_irq(U8 enable)
void owl_spi_irq(U8 enable)
{
#ifdef USE_POLL
return;
#endif
#ifdef WL_IRQ_PIN
if (enable)
gpio_enable_pin_interrupt(GPIO_IRQ_PIN, GPIO_PIN_CHANGE);
gpio_enable_pin_interrupt(WL_IRQ_PIN, GPIO_PIN_CHANGE);
else
gpio_disable_pin_interrupt(GPIO_IRQ_PIN);
gpio_disable_pin_interrupt(WL_IRQ_PIN);
#endif
}
void platform_spi_cs(U8 enable)
void owl_spi_cs(U8 enable)
{
volatile avr32_spi_t *spi = &AVR32_SPI;
if (enable) {
#if SPI_CS == 2
volatile avr32_spi_t *spi = &WL_SPI;
/*
* PCS = xxx0 => NPCS[3:0] = 1110
* PCS = xx01 => NPCS[3:0] = 1101
* PCS = x011 => NPCS[3:0] = 1011
* PCS = 0111 => NPCS[3:0] = 0111
* PCS = 1111 => forbidden (no peripheral is selected)
*/
if (enable)
#if WL_SPI_CS == 2
spi->MR.pcs = 0x3; /* cs2 */
#elif SPI_CS == 1
#elif WL_SPI_CS == 1
spi->MR.pcs = 0x1; /* cs1 */
#elif SPI_CS == 0
spi->MR.pcs = 0x0; /* cs1 */
#elif WL_SPI_CS == 3
spi->MR.pcs = 0x7; /* cs3 */
#elif WL_SPI_CS == 0
spi->MR.pcs = 0x0; /* cs0 */
#endif
}else
else
spi->MR.pcs = 0xf;
}
void owl_spi_mdelay(uint32_t ms)
{
volatile int a = 0;
int i;
for (i = 0; i < ms * 5000; i++)
a++;
}
__attribute__((__interrupt__)) void avr32_irq_handler(void)
{
uint8_t irq_status = 0;
#ifndef WITH_NO_DMA
volatile avr32_pdca_channel_t *pdca_tx = &AVR32_PDCA.channel[0];
volatile avr32_pdca_channel_t *pdca_rx = &AVR32_PDCA.channel[1];
#endif
if (gpio_get_pin_interrupt_flag(GPIO_IRQ_PIN)) {
gpio_clear_pin_interrupt_flag(GPIO_IRQ_PIN);
irq_status |= SPI_IRQ_RX;
}
#ifndef WITH_NO_DMA
/* tx xfer complete */
if (pdca_tx->IMR.trc && pdca_tx->ISR.trc) {
@ -391,14 +382,13 @@ __attribute__((__interrupt__)) void avr32_irq_handler(void)
pdca_rx->IDR.trc = 1;
pdca_rx->CR.tdis = 1; /* disable rx xfer */
}
#endif
#ifdef WL_IRQ_PIN
if (gpio_get_pin_interrupt_flag(WL_IRQ_PIN)) {
gpio_clear_pin_interrupt_flag(WL_IRQ_PIN);
wl_spi_irq();
}
#endif
#if 0
/* tx and rx complete */
if (pdca_tx->ISR.trc && pdca_rx->ISR.trc)
irq_status |= SPI_IRQ_XFER_COMPLETE;
#endif
#endif
if (irq_status)
spi_irq_handler(irq_status);
}

View File

@ -27,14 +27,18 @@
* (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 <top_defs.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "cmd_wl.h"
#include <cmd_wl.h>
#include <wl_cm.h>
#include <console.h>
#include <util.h>
#include <lwip_setup.h>
#include "wl_cm.h"
#include "console.h"
#include "wl_util.h"
#include "util.h"
#include "lwip/netif.h"
#include "lwip/dns.h"
#include "debug.h"
@ -56,6 +60,8 @@ extern void showTTCPstatus();
else verboseDebug &= ~FLAG; \
}while(0);
#define _DNS_CMD_
/**
*
*/
@ -70,6 +76,22 @@ cmd_scan(int argc, char* argv[], void* ctx)
return CMD_DONE;
}
cmd_state_t
cmd_debug_toggle(int argc, char* argv[], void* ctx)
{
extern uint8_t tr_data_trace;
if ( argc != 2 ) {
printk("usage: dt <1|0>\n");
return CMD_DONE;
}
if ( '0' == argv[1][0] ) {
tr_data_trace = 0;
}
if ( '1' == argv[1][0] ) {
tr_data_trace = 1;
}
return CMD_DONE;
}
/**
*
@ -93,10 +115,114 @@ cmd_connect(int argc, char* argv[], void* ctx)
memcpy(ssid.ssid, desired_ssid, len);
ssid.len = len;
/* Start connection manager */
wl_cm_set_network(&ssid, NULL);
wl_cm_start();
return CMD_DONE;
}
#ifdef WFE_6_12
cmd_state_t
cmd_ibss(int argc, char* argv[], void* ctx)
{
struct wl_ssid_t ssid;
char desired_ssid[WL_SSID_MAX_LENGTH];
uint8_t channel;
enum wl_auth_mode amode;
int len = 0;
wl_err_t ret;
if ( 2 == argc && ! strncmp(argv[1], "none", 4) ) {
printk("Disconnecting\n");
wl_disconnect();
wl_cm_stop();
return CMD_DONE;
}
if (argc < 4) {
printk("usage: ibss <ssid> <channel (1-14)> <wep_enable (1|0)>\n");
printk(" ibss none\n");
return CMD_DONE;
}
channel = atoi(argv[argc - 2]);
if ( *argv[argc - 1] == '0' ) {
amode = AUTH_MODE_OPEN_SYSTEM;
} else {
amode = AUTH_MODE_SHARED_KEY;
}
len = join_argv(desired_ssid, sizeof desired_ssid, argc - 3, argv + 1);
if (0 == len) {
return CMD_DONE;
}
if ( channel > 14 ) {
printk("Invalid channel %d\n", (int)channel);
return CMD_DONE;
}
printk("%s : Start with ssid \"%s\", channel %d\n", __func__,
desired_ssid, channel);
memcpy(ssid.ssid, desired_ssid, len);
ssid.len = len;
/* Stop the connection manager */
wl_cm_stop();
ret = wl_start_adhoc_net(ssid, channel, amode);
switch (ret) {
case WL_BUSY:
printk("Driver is busy. Already connected?\n");
break;
case WL_RETRY:
printk("Driver is busy. Retry operation\n");
break;
case WL_OOM:
printk("Out of memory\n");
break;
case WL_INVALID_ARGS:
printk("Invalid argument\n");
break;
case WL_SUCCESS:
break;
default:
printk("Unknown error %d\n", ret);
break;
}
return CMD_DONE;
}
#endif
/**
*
*/
cmd_state_t
cmd_set_ip(int argc, char* argv[], void* ctx)
{
struct net_cfg *ncfg = ctx;
struct ip_addr lwip_addr;
struct netif *nif = ncfg->netif;
if (argc == 2 &&
(strncmp(argv[1], "none", 4) == 0)) {
ncfg->dhcp_enabled = 1;
return CMD_DONE;
}
else if (argc != 4 ) {
printk("usage: ip <ip> <netmask> <gateway-ip>\n");
printk(" or : ip none (to enable DHCP)\n");
return CMD_DONE;
}
/* IP address */
lwip_addr = str2ip(argv[1]);
netif_set_ipaddr(nif, &lwip_addr);
/* Netmask */
lwip_addr = str2ip(argv[2]);
netif_set_netmask(nif, &lwip_addr);
/* Default Gateway address */
lwip_addr = str2ip(argv[3]);
netif_set_gw(nif, &lwip_addr);
/* Disable DHCP */
ncfg->dhcp_enabled = 0;
return CMD_DONE;
}
#ifdef WITH_WPA
@ -210,6 +336,38 @@ cmd_gethostbyname(int argc, char* argv[], void* ctx)
return CMD_DONE;
}
/**
*
*/
cmd_state_t
cmd_setDnsServer(int argc, char* argv[], void* ctx)
{
const char *usage = "usage: setdns [1-2] aaa.bbb.ccc.ddd\n";
struct ip_addr dnsIp;
int dnsIdx = 0;
if (argc < 3) {
printk(usage);
return CMD_DONE;
}
/* DNS IDX */
dnsIdx = atoi(argv[1])-1;
/* IP address */
dnsIp = str2ip(argv[2]);
printk("Set DNS server %d to %s\n", dnsIdx, ip2str(dnsIp));
dns_setserver(dnsIdx, &dnsIp);
struct ip_addr addr1 = dns_getserver(0);
struct ip_addr addr2 = dns_getserver(1);
printk("==> DNS1: %s\n", ip2str(addr1), addr1);
printk("==> DNS2: %s\n", ip2str(addr2), addr2);
return CMD_DONE;
}
#endif
@ -219,6 +377,7 @@ cmd_gethostbyname(int argc, char* argv[], void* ctx)
cmd_state_t
cmd_status(int argc, char* argv[], void* ctx)
{
struct net_cfg *ncfg = ctx;
struct wl_network_t* net;
uint8_t mac[WL_MAC_ADDR_LENGTH];
@ -226,24 +385,37 @@ cmd_status(int argc, char* argv[], void* ctx)
/* print mac address */
if (wl_get_mac_addr(mac) != WL_SUCCESS) {
printk("failed to get mac address\n");
return CMD_DONE;
}
}else{
printk("hw addr: %s\n", mac2str(mac));
}
/* print network info */
net = wl_get_current_network();
printk("link status: ");
if (!net) {
printk("down\n");
return CMD_DONE;
}
}else{
print_network(net);
}
/* print ip address */
if (netif_is_up(netif_default))
printk("ip addr: %s\n", ip2str(netif_default->ip_addr));
else
printk("ip addr: none\n");
printk("ip interface is down\n");
printk("dhcp : ");
if (ncfg->dhcp_enabled) {
printk("enabled\n");
}
else {
printk("disabled\n");
}
struct ip_addr addr1 = dns_getserver(0);
struct ip_addr addr2 = dns_getserver(1);
printk("==> DNS1: %s\n", ip2str(addr1), addr1);
printk("==> DNS2: %s\n", ip2str(addr2), addr2);
showTTCPstatus();
return CMD_DONE;
@ -332,34 +504,6 @@ cmd_psconf(int argc, char* argv[], void* ctx)
}
#endif
#define MAX_KEY_LEN 64
/**
*
*/
uint8_t ascii_to_key(char *outp, const char *inp) {
char buf[3];
int len;
buf[2] = '\0';
len = strlen(inp);
if (len % 2) {
printk("Invalid length\n");
}
len = 0;
while (*inp) {
if (! isxdigit(*inp) || ! isxdigit(*(inp+1)) ||
len > MAX_KEY_LEN) {
return 0;
}
buf[0] = *inp++;
buf[1] = *inp++;
*outp++ = strtol(buf, NULL, 16);
len++;
}
return len;
}
/**
*
*/
@ -375,7 +519,6 @@ cmd_setkey(int argc, char* argv[], void* ctx)
memset(&bssid.octet, 0xff, sizeof bssid.octet);
if (argc == 2 && strcmp(argv[1], "none") == 0) {
printk("Deleting WEP keys\n");
wl_set_auth_mode(AUTH_MODE_OPEN_SYSTEM);
wl_delete_wep_key(0, &bssid);
wl_delete_wep_key(1, &bssid);
wl_delete_wep_key(2, &bssid);
@ -387,17 +530,24 @@ cmd_setkey(int argc, char* argv[], void* ctx)
return CMD_DONE;
}
idx = atoi(argv[1]);
len = ascii_to_key(key, argv[2]);
if (0 == len || idx > 3 || idx < 0 || (idx == 0 && *argv[1] != '0')) {
printk(usage);
return CMD_DONE;
len = strlen(argv[2]);
/* Pass phrase? */
if ( 5 == len || 13 == len ) {
strncpy(key, argv[2], len);
}
if (len != 5 && len != 13) {
printk(" WEP key must be 10 (WEP-40) or 26 (WEP-104) digits\n");
return CMD_DONE;
/* Otherwise it's a hex string */
else {
len = ascii_to_key(key, argv[2]);
if (0 == len || idx > 3 || idx < 0 || (idx == 0 && *argv[1] != '0')) {
printk(usage);
return CMD_DONE;
}
if (len != 5 && len != 13) {
printk(" WEP key must be 10 (WEP-40) or 26 (WEP-104) digits\n");
return CMD_DONE;
}
}
wl_add_wep_key(idx, len, key, &bssid);
wl_set_auth_mode(AUTH_MODE_SHARED_KEY);
wl_set_default_wep_key(idx);
return CMD_DONE;
@ -414,7 +564,7 @@ cmd_debug(int argc, char* argv[], void* ctx)
if (argc == 2 && strcmp(argv[1], "off") == 0) {
printk("Debug OFF\n");
enableDebug = 0;
enableDebug = DEFAULT_INFO_FLAG;
verboseDebug = 0;
return CMD_DONE;
}else if (argc == 2 && strcmp(argv[1], "print") == 0) {

View File

@ -30,10 +30,18 @@
#ifndef CMD_CM_H
#define CMD_CM_H
#include "console.h"
#include <console.h>
#include "netif/wlif.h"
/*! A pointer to a struct of type "struct net_cfg" should be passed as
* the ctx pointer in the callbacks below. The struct must have a
* single instance per netif.
*/
#define _DNS_CMD_
cmd_state_t cmd_scan(int argc, char* argv[], void* ctx);
cmd_state_t cmd_connect(int argc, char* argv[], void* ctx);
cmd_state_t cmd_set_ip(int argc, char* argv[], void* ctx);
cmd_state_t cmd_setkey(int argc, char* argv[], void* ctx);
cmd_state_t cmd_status(int argc, char* argv[], void* ctx);
cmd_state_t cmd_power(int argc, char* argv[], void* ctx);
@ -41,5 +49,10 @@ cmd_state_t cmd_psconf(int argc, char* argv[], void* ctx);
cmd_state_t cmd_setpass(int argc, char* argv[], void* ctx);
cmd_state_t cmd_delpass(int argc, char* argv[], void* ctx);
cmd_state_t cmd_debug(int argc, char* argv[], void* ctx);
cmd_state_t cmd_debug_toggle(int argc, char* argv[], void* ctx);
#ifdef WFE_6_12
cmd_state_t cmd_ibss(int argc, char* argv[], void* ctx);
#endif
#endif

View File

@ -1,5 +1,3 @@
/* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
/*! \page License
* Copyright (C) 2009, H&D Wireless AB All rights reserved.
*
@ -27,64 +25,79 @@
* (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 <avr32/io.h>
#include "compiler.h"
#include "board.h"
#include "power_clocks_lib.h"
#include "gpio.h"
#include "usart.h"
#include "printf-stdarg.h"
#include <string.h>
#include "console.h"
#define MAX_CMD_CONSOLE_NUM 9
#include <top_defs.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <printf-stdarg.h>
#include <console.h>
#include <board_init.h>
#include <usart.h>
#define MAX_CMD_CONSOLE_NUM 12
struct {
cmd_cb_t cb;
const char* str;
void* ctx;
} cmd_list[MAX_CMD_CONSOLE_NUM] = { { 0 } };
#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])
#if BOARD == EVK1104 || BOARD == EVK1100 || BOARD == EVK1101 || BOARD ==ARDUINO
#define AVR32_USART AVR32_USART1
#elif BOARD == EVK1105
#define AVR32_USART AVR32_USART0
#else
#error
#ifndef CMD_MAX_LEN
#define CMD_MAX_LEN 80
#endif
extern int board_putchar(char c);
int io_getc(char *c)
{
int ci;
int status;
status = usart_read_char(&CONFIG_CONSOLE_PORT, &ci);
if (status == USART_RX_EMPTY)
return 1;
if (status == USART_RX_ERROR) {
CONFIG_CONSOLE_PORT.cr = AVR32_USART_CR_RSTSTA_MASK;
return 1;
}
#ifndef CMD_CONSOLE_MAX_LEN
#define CMD_CONSOLE_MAX_LEN 25
#endif
if (ci == '\r') {
board_putchar('\n');
/* Echo char. */
} else if (ci == '\b') {
board_putchar(ci);
board_putchar(' ');
board_putchar(ci);
} else
board_putchar(ci);
static Bool is_initialized = FALSE;
*c = ci;
return 0;
}
static uint8_t is_initialized = 0;
char* console_gets()
{
static char buf[CMD_CONSOLE_MAX_LEN];
static char buf[CMD_MAX_LEN];
static int pos = 0;
int c;
int status;
char c;
for (;;) {
status = usart_read_char(&AVR32_USART, &c);
if (status == USART_RX_EMPTY)
if (io_getc(&c))
return NULL;
if (status == USART_RX_ERROR) {
AVR32_USART.cr = AVR32_USART_CR_RSTSTA_MASK;
return NULL;
}
if (c == '\r') {
usart_putchar(&AVR32_USART, '\n');
if (c == '\r' || c == '\n') {
buf[pos] = 0;
pos = 0;
return buf;
}
usart_putchar(&AVR32_USART, c);
buf[pos++] = c;
if (c == '\b') {
pos -= 1;
if (pos < 0) pos = 0;
buf[pos] = 0;
}
else
buf[pos++] = c;
if (pos == sizeof(buf))
pos = 0;
}
@ -93,7 +106,7 @@ char* console_gets()
int console_add_cmd(const char* str, cmd_cb_t cb, void* ctx)
{
U32 i;
uint32_t i;
for (i = 0; i < ARRAY_SIZE(cmd_list); i++)
if (!cmd_list[i].cb)
break;
@ -110,15 +123,15 @@ int console_add_cmd(const char* str, cmd_cb_t cb, void* ctx)
void console_init(void)
{
printk("\n$ ");
is_initialized = TRUE;
is_initialized = 1;
}
void console_init_silent(void) {
is_initialized = TRUE;
is_initialized = 1;
}
int console_schedule_cmd(char *cmd, int interactive) {
#define MAX_ARGS 8
#define MAX_ARGS 16
static int argc, i;
static char* argv[MAX_ARGS];
static char *buf;
@ -144,7 +157,7 @@ int console_schedule_cmd(char *cmd, int interactive) {
buf);
#endif
for (i = 0; i < ARRAY_SIZE(cmd_list); i++)
if(!strncmp(cmd_list[i].str, buf, 2))
if(cmd_list[i].str && !strncmp(cmd_list[i].str, buf, min(strlen(cmd_list[i].str), strlen(buf))))
break;
if (ARRAY_SIZE(cmd_list) == 0) {
@ -170,7 +183,6 @@ int console_schedule_cmd(char *cmd, int interactive) {
break;
}
state = RUN;
} /* fall through */
@ -182,6 +194,7 @@ int console_schedule_cmd(char *cmd, int interactive) {
interactive ? printk("$ ") : 0;
argc = 0;
memset(argv, 0, sizeof argv);
free(buf);
state = INPUT;
}

View File

@ -1,5 +1,3 @@
/* This header file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
/*! \page License
* Copyright (C) 2009, H&D Wireless AB All rights reserved.
*

View File

@ -22,6 +22,7 @@
#define INFO_D (1<<0xD) // Debug
#define INFO_E (1<<0xE) // Error
#define INFO_WARN_FLAG (1<<0xF) // Warning
#define DEFAULT_INFO_FLAG 0 //INFO_WARN_FLAG
extern uint16_t enableDebug;
extern uint16_t verboseDebug;

View File

@ -31,8 +31,8 @@
#define FW_DOWNLOAD_H
#include <stdint.h>
#include <stdio.h>
int fw_download_init(void);
void fw_download_cb(void *ctx, uint8_t** buf, uint32_t* len);
size_t fw_read_cb(void *ctx, const uint8_t** buf, size_t offset, size_t len);
#endif

View File

@ -1,6 +1,3 @@
#if defined(DATAFLASH)
/* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
/*! \page License
* Copyright (C) 2009, H&D Wireless AB All rights reserved.
*
@ -28,58 +25,58 @@
* (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 "wl_api.h"
#include "fw_download.h"
#include "nor_flash.h"
#include "printf-stdarg.h"
#include <top_defs.h>
#include <wl_api.h>
#include <fw_download.h>
#include <nvram.h>
#include <printf-stdarg.h>
int fw_download_init(void)
{
flash_init();
return 0;
nvram_init();
return 0;
}
void fw_download_cb(void* ctx, uint8_t** buf, uint32_t* len)
{
/* remember accross different calls */
static uint8_t* fw_buf = NULL;
static uint32_t offset = 0;
#define BUF_SIZE 512
//printk("Starting download... 0x%x-0x%x", *buf, *len);
/* when firmware download is completed, this function will be invoked
* on additional time with the input value of len set to 0. we can free
* the firmware buffer at this time since it's no longer needed.
size_t fw_read_cb(void* ctx,
const uint8_t** buf,
size_t offset,
size_t len)
{
static uint8_t* fw_buf = NULL;
size_t rlen;
/* when firmware download is completed, this function will be
* invoked one additional time with buf set to NULL. we can
* free the firmware buffer at this time since it's no longer
* needed.
*/
if (*len == 0) {
if (fw_buf)
if (NULL == buf) {
if (fw_buf) {
free(fw_buf);
return;
fw_buf = NULL;
}
return 0;
}
/* first call? then initialize flash and allocate a buffer to hold
* firmware data.
*/
if (fw_buf == NULL) {
fw_buf = malloc(SECTOR_SIZE);
fw_buf = malloc(BUF_SIZE);
if (fw_buf == NULL) {
printk("could not allocate firmware buffer\n");
*len = 0;
return;
return 0;
}
}
/* decide how much to read. we know *len bytes remains, but we only have
* room for SECTOR_SIEZ bytes in our buffer (fw_buf)
*/
uint32_t fw_len = *len > SECTOR_SIZE ? SECTOR_SIZE : *len;
/* read at most a full buffer */
rlen = len > BUF_SIZE ? BUF_SIZE : len;
/* read data and update output parameters */
flash_read(offset, fw_buf, fw_len);
nvram_read(offset, fw_buf, rlen);
*buf = fw_buf;
*len = fw_len;
/* we need to know where to start reading upon next call */
offset += fw_len;
return rlen;
}
#endif

145
wifiHD/src/lwip_setup.c Normal file
View File

@ -0,0 +1,145 @@
/*! \page License
* Copyright (C) 2009, H&D Wireless AB All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. 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.
*
* 3. The name of H&D Wireless AB may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY H&D WIRELESS AB ``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 EXPRESSLY AND
* SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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.
*/
/*!
* \file lwIP setup code
*
* \brief Collects the lwIP setup code that an application has to
* execute in a standalone environment.
*
* \author H&D Wireless AB \n
*
*/
#include <lwip/init.h>
#include <lwip/dhcp.h>
#include <lwip/tcp.h>
#include <ipv4/lwip/ip_frag.h>
#include <netif/etharp.h>
#include <netif/wlif.h>
#include <timer.h>
#include "lwip_setup.h"
#include "lwip/dns.h"
/**
*
*/
static void
tcp_tmr_cb(void *ctx)
{
tcp_tmr();
}
/**
*
*/
static void
ip_tmr_cb(void *ctx)
{
ip_reass_tmr();
}
/**
*
*/
static void
dns_tmr_cb(void *ctx)
{
dns_tmr();
}
/**
*
*/
static void
etharp_tmr_cb(void *ctx)
{
etharp_tmr();
}
/**
*
*/
static void
dhcp_fine_tmr_cb(void *ctx)
{
dhcp_fine_tmr();
}
/**
*
*/
static void
dhcp_coarse_tmr_cb(void *ctx)
{
dhcp_coarse_tmr();
}
int start_ip_stack(struct net_cfg *cfg,
struct ip_addr ipaddr,
struct ip_addr netmask,
struct ip_addr gw) {
if (cfg->dhcp_enabled) {
IP4_ADDR(&gw, 0,0,0,0);
IP4_ADDR(&ipaddr, 0,0,0,0);
IP4_ADDR(&netmask, 0,0,0,0);
}
/* add wl to lwip interface list and set as default */
cfg->netif = netif_add(cfg->netif,
&ipaddr,
&netmask,
&gw,
NULL,
wlif_init, /* init */
ethernet_input /* handles ARP and IP packets */);
if (cfg->netif == NULL)
return -1;
netif_set_default(cfg->netif);
/* register lwip timer callbacks for tcp, arp and dhcp protocols */
timer_sched_timeout_cb(5000, TIMEOUT_PERIODIC,
etharp_tmr_cb, NULL);
timer_sched_timeout_cb(TCP_TMR_INTERVAL, TIMEOUT_PERIODIC,
tcp_tmr_cb, NULL);
timer_sched_timeout_cb(DHCP_FINE_TIMER_MSECS, TIMEOUT_PERIODIC,
dhcp_fine_tmr_cb, NULL);
timer_sched_timeout_cb(DHCP_COARSE_TIMER_MSECS, TIMEOUT_PERIODIC,
dhcp_coarse_tmr_cb, NULL);
timer_sched_timeout_cb(IP_TMR_INTERVAL, TIMEOUT_PERIODIC,
ip_tmr_cb, NULL);
timer_sched_timeout_cb(DNS_TMR_INTERVAL, TIMEOUT_PERIODIC,
dns_tmr_cb, NULL);
return 1;
}

21
wifiHD/src/lwip_setup.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef _LWIP_SETUP_H
#define _LWIP_SETUP_H
struct net_cfg {
struct netif *netif; /* lwip network interface */
uint8_t dhcp_enabled;
uint8_t dhcp_running;
};
/*! Start the IP stack.
* If cfg->netif must have been allocated and lwip_init()
* must have been called before this function is called
* (since the IP stack may have to be polled before this
* function can be called).
*/
int start_ip_stack(struct net_cfg *cfg,
struct ip_addr ipaddr,
struct ip_addr netmask,
struct ip_addr gw);
#endif /* _LWIP_SETUP_H */

View File

@ -11,6 +11,7 @@
#include "board.h"
#include "gpio.h"
#include <stdint.h>
#include "wl_api.h"
#include "wl_cm.h"
@ -21,16 +22,26 @@
#include "netif/etharp.h"
#include "netif/wlif.h"
#include "board_init.h"
#include "startup.h"
#include "trace.h"
#include "timer.h"
#include "wl_util.h"
#include "util.h"
#include "cmd_wl.h"
#include "httpd.h"
#include "ping.h"
#include "ard_tcp.h"
#include "spi.h"
#include "ard_spi.h"
#include "delay.h"
#include "tc.h"
#include "debug.h"
#include "ard_utils.h"
#include <lwip_setup.h>
//void board_init(void);
#if BOARD == ARDUINO
#if !defined(DATAFLASH)
@ -69,77 +80,23 @@ void fw_download_cb(void* ctx, uint8_t** buf, uint32_t* len)
#endif
#endif
#include "spi.h"
#include "ard_spi.h"
#include "delay.h"
#include "tc.h"
#include "debug.h"
#include "ard_utils.h"
struct ctx_server {
struct netif *netif;
//uint8_t wl_init_complete;
struct net_cfg net_cfg;
uint8_t wl_init_complete;
};
// to maintain the word alignment
#define PAD_CTX_SIZE 0x18
#define PAD_NETIF_SIZE 0x3c
//#define PAD_CTX_SIZE 0x18
//#define PAD_NETIF_SIZE 0x3c
#define PAD_CTX_SIZE 0
#define PAD_NETIF_SIZE 0
static bool initSpiComplete = false;
// variable used as enable flag for debug prints
uint16_t enableDebug = 0; //INFO_WARN_FLAG;
uint16_t enableDebug = DEFAULT_INFO_FLAG;
uint16_t verboseDebug = 0;
/**
*
*/
static void
tcp_tmr_cb(void *ctx)
{
tcp_tmr();
}
/**
*
*/
static void
etharp_tmr_cb(void *ctx)
{
etharp_tmr();
}
/**
*
*/
static void
dhcp_fine_tmr_cb(void *ctx)
{
dhcp_fine_tmr();
}
/**
*
*/
static void
dhcp_coarse_tmr_cb(void *ctx)
{
dhcp_coarse_tmr();
}
/**
*
*/
static void
dns_tmr_cb(void *ctx)
{
dns_tmr();
}
/**
*
*/
@ -162,10 +119,16 @@ wl_cm_conn_cb(struct wl_network_t* net, void* ctx)
INFO_INIT("Connection cb...\n");
printk("link up, connected to \"%s\"\n", ssid2str(&net->ssid));
printk("requesting dhcp ... ");
INFO_INIT("Start DHCP...\n");
dhcp_start(hs->netif);
if ( hs->net_cfg.dhcp_enabled ) {
INFO_INIT("Start DHCP...\n");
printk("requesting dhcp ... ");
int8_t result = dhcp_start(hs->net_cfg.netif);
printk((result==ERR_OK)?"OK\n":"FAILED\n");
hs->net_cfg.dhcp_running = 1;
}
else {
netif_set_up(hs->net_cfg.netif);
}
INFO_INIT("Start DNS...\n");
dns_init();
@ -183,12 +146,14 @@ wl_cm_disconn_cb(void* ctx)
LINK_LED_OFF();
INFO_INIT("Disconnection cb...\n");
if (netif_is_up(hs->netif)) {
if (hs->net_cfg.dhcp_running) {
printk("link down, release dhcp\n");
dhcp_release(hs->netif);
dhcp_stop(hs->netif);
dhcp_release(hs->net_cfg.netif);
dhcp_stop(hs->net_cfg.netif);
hs->net_cfg.dhcp_running = 0;
} else {
printk("link down\n");
netif_set_down(hs->net_cfg.netif);
}
set_result_cmd(WL_FAILURE);
@ -284,11 +249,6 @@ void tc_init(void)
}
void wifi_init()
{
}
/**
*
*/
@ -302,12 +262,12 @@ poll(struct ctx_server* hs)
console_poll();
/* wl api 'tick' */
wl_poll(timer_get_ms());
wl_tick(timer_get_ms());
/* lwip driver poll */
wlif_poll(hs->netif);
wlif_poll(hs->net_cfg.netif);
if (initSpiComplete) spi_poll(hs->netif);
if (initSpiComplete) spi_poll(hs->net_cfg.netif);
#ifdef WITH_GUI
gui_exec(timer_get_ms());
@ -343,6 +303,7 @@ void initShell()
#endif
#ifdef _DNS_CMD_
console_add_cmd("getHost", cmd_gethostbyname, NULL);
console_add_cmd("setDNS", cmd_setDnsServer, NULL);
#endif
}
@ -353,48 +314,46 @@ void
wl_init_complete_cb(void* ctx)
{
struct ctx_server *hs = ctx;
struct ip_addr ipaddr, netmask, gw;
struct ip_addr ipaddr, netmask, gw;
wl_err_t wl_status;
IP4_ADDR(&gw, 0,0,0,0);
IP4_ADDR(&ipaddr, 0,0,0,0);
IP4_ADDR(&netmask, 0,0,0,0);
IP4_ADDR(&gw, 0,0,0,0);
IP4_ADDR(&ipaddr, 0,0,0,0);
IP4_ADDR(&netmask, 0,0,0,0);
/* add wl to lwip interface list and set as default */
hs->netif = netif_add(hs->netif, &ipaddr, &netmask, &gw, NULL,
wlif_init, /* init */
ethernet_input /* handles ARP and IP packets */);
ASSERT(hs->netif, "failed to add netif");
netif_set_default(hs->netif);
netif_set_status_callback(hs->netif, ip_status_cb);
/* register lwip timer callbacks for tcp, arp and dhcp protocols */
timer_sched_timeout_cb(5000, TIMEOUT_PERIODIC,
etharp_tmr_cb, hs);
timer_sched_timeout_cb(TCP_TMR_INTERVAL, TIMEOUT_PERIODIC,
tcp_tmr_cb, hs);
timer_sched_timeout_cb(DHCP_FINE_TIMER_MSECS, TIMEOUT_PERIODIC,
dhcp_fine_tmr_cb, hs);
timer_sched_timeout_cb(DHCP_COARSE_TIMER_MSECS, TIMEOUT_PERIODIC,
dhcp_coarse_tmr_cb, hs);
// timer_sched_timeout_cb(DNS_TMR_INTERVAL, TIMEOUT_PERIODIC,
// dns_tmr_cb, NULL);
if (initSpi())
WARN("Spi not initialized\n");
else
{
initSpiComplete = true;
AVAIL_FOR_SPI();
}
/* default is dhcp enabled */
hs->net_cfg.dhcp_enabled = 1;
start_ip_stack(&hs->net_cfg,
ipaddr,
netmask,
gw);
netif_set_status_callback(hs->net_cfg.netif, ip_status_cb);
INFO_INIT("Starting CM...\n");
/* start connection manager */
INFO_INIT("Starting CM...\n");
wl_status = wl_cm_init(NULL, wl_cm_conn_cb, wl_cm_disconn_cb, hs);
ASSERT(wl_status == WL_SUCCESS, "failed to init wl conn mgr");
wl_cm_start();
wl_status = wl_cm_start(wl_cm_scan_cb, wl_cm_conn_cb, wl_cm_disconn_cb, wl_cm_err_cb, hs);
ASSERT(wl_status == WL_SUCCESS, "failed to init wl conn mgr");
wl_scan();
initShell();
if (initSpi()){
WARN("Spi not initialized\n");
}else
{
initSpiComplete = true;
AVAIL_FOR_SPI();
}
hs->wl_init_complete = 1;
}
void startup_init(void)
{
INIT_SIGNAL_FOR_SPI();
BUSY_FOR_SPI();
}
/**
@ -406,12 +365,13 @@ main(void)
wl_err_t wl_status;
int status;
struct ctx_server *hs;
enum wl_host_attention_mode mode;
startup_init();
led_init();
board_init();
wifi_init();
led_init();
tc_init();
@ -430,45 +390,58 @@ main(void)
#else
printk("Arduino Wifi Startup... [%s]\n", __TIMESTAMP__);
initShell();
size_t size_ctx_server = sizeof(struct ctx_server)+PAD_CTX_SIZE;
hs = calloc(1, size_ctx_server);
ASSERT(hs, "out of memory");
size_t size_netif = sizeof(struct netif)+PAD_NETIF_SIZE;
hs->netif = calloc(1, size_netif);
ASSERT(hs->netif, "out of memory");
hs->net_cfg.netif = calloc(1, size_netif);
ASSERT(hs->net_cfg.netif, "out of memory");
INFO_INIT("hs:%p size:0x%x netif:%p size:0x%x\n", hs, size_ctx_server,
hs->netif, size_netif);
timer_init(NULL, NULL);
lwip_init();
hs->net_cfg.netif, size_netif);
timer_init(NULL, NULL);
lwip_init();
status = fw_download_init();
ASSERT(status == 0, "failed to prepare for firmware download\n");
wl_status = wl_init(hs, fw_download_cb, wl_init_complete_cb);
switch (wl_status) {
case WL_SUCCESS:
/* ok */
break;
wl_status = wl_transport_init(fw_read_cb, hs, &mode);
if (wl_status != WL_SUCCESS)
goto err;
INFO_INIT("Mode: 0x%x\n", mode);
wl_status = wl_init(hs, wl_init_complete_cb, mode);
if (wl_status != WL_SUCCESS)
goto err;
case WL_CARD_FAILURE:
printk("Could not detect wl device, aborting\n");
return -1;
/* start main loop */
for (;;)
poll(hs);
case WL_FIRMWARE_INVALID:
printk("Invalid firmware data, aborting\n");
return -1;
default:
printk("Failed to start wl initialization\n");
return -1;
}
err:
/* show error message on console and display if wlan initialization fails */
/* start main loop */
for (;;)
poll(hs);
#define WL_CARD_FAILURE_STR "Could not detect wl device, aborting\n"
#define WL_FIRMWARE_INVALID_STR "Invalid firmware data, aborting\n"
#define WL_OTHER_FAILURE_STR "Failed to start wl initialization\n"
switch (wl_status) {
case WL_CARD_FAILURE:
printk(WL_CARD_FAILURE_STR);
break;
case WL_FIRMWARE_INVALID:
printk(WL_FIRMWARE_INVALID_STR);
break;
default:
printk(WL_OTHER_FAILURE_STR);
break;
}
for (;;) {
timer_poll();
}
#endif
}

153
wifiHD/src/nvram.c Normal file
View File

@ -0,0 +1,153 @@
/*! \page License
* Copyright (C) 2009, H&D Wireless AB All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. 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.
*
* 3. The name of H&D Wireless AB may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY H&D WIRELESS AB ``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 EXPRESSLY AND
* SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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 "compiler.h"
#include "preprocessor.h"
#include "board.h"
#include "power_clocks_lib.h"
#include "gpio.h"
#include "spi.h"
#include "conf_at45dbx.h"
#include "at45dbx.h"
#include <board_init.h>
#include <nvram.h>
static struct nvram {
uint8_t read;
void *data;
uint32_t len;
uint16_t off;
} PRIV;
int nvram_init(void)
{
spi_options_t spiOptions = {
.reg = AT45DBX_SPI_FIRST_NPCS,
.baudrate = AT45DBX_SPI_MASTER_SPEED,
.bits = AT45DBX_SPI_BITS,
.spck_delay = 0,
.trans_delay = 0,
.stay_act = 1,
.spi_mode = 0,
.modfdis = 1
};
at45dbx_init(spiOptions, FPBA_HZ);
return 0;
}
/**
* Invoked by at45dbx driver
*
*/
void at45dbx_read_multiple_sector_callback(const void *psector)
{
struct nvram *priv = &PRIV;
const uint8_t *buf = psector;
if (!priv->read)
return;
memcpy(priv->data, buf + priv->off, priv->len);
}
/**
* Invoked by at45dbx driver
*
*/
void at45dbx_write_multiple_sector_callback(void *psector)
{
struct nvram *priv = &PRIV;
uint8_t *buf = psector;
memcpy(buf + priv->off, priv->data, priv->len);
}
/**
* Write/read any number bytes into any offset of nor flash by taking care
* of cases where the length is not aligned to the sector size or where
* the addr is not aligned to the sector offsets.
*
*/
static int nvram_rw(uint32_t addr, void *data, uint16_t len, int write)
{
struct nvram *priv = &PRIV;
priv->read = write ? 0 : 1;
while (len) {
uint32_t sector = addr / AT45DBX_SECTOR_SIZE;
priv->data = data;
priv->off = addr % AT45DBX_SECTOR_SIZE;
priv->len = AT45DBX_SECTOR_SIZE;
if (len < AT45DBX_SECTOR_SIZE)
priv->len = len;
if (priv->len > AT45DBX_SECTOR_SIZE - priv->off)
priv->len = AT45DBX_SECTOR_SIZE - priv->off;
at45dbx_read_open(sector);
at45dbx_read_multiple_sector(1);
at45dbx_read_close();
if (write) {
at45dbx_write_open(sector);
at45dbx_write_multiple_sector(1);
at45dbx_write_close();
}
data += priv->len;
len -= priv->len;
addr += priv->len;
}
return 0;
}
/**
* Write any number bytes into any offset of nor flash.
*
*/
int nvram_write(uint32_t addr, const void *data, uint32_t len)
{
return nvram_rw(addr, (void *) data, len, 1);
}
/**
* Read any number bytes into any offset of nor flash.
*
*/
int nvram_read(uint32_t addr, void *data, uint32_t len)
{
return nvram_rw(addr, data, len, 0);
}

10
wifiHD/src/nvram.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef NVRAM_H
#define NVRAM_H
#include <stdint.h>
int nvram_init(void);
int nvram_read(uint32_t addr, void *data, uint32_t len);
int nvram_write(uint32_t addr, const void *data, uint32_t len);
#endif

140
wifiHD/src/owl_os.c Normal file
View File

@ -0,0 +1,140 @@
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <wl_os.h>
void *owl_os_alloc(size_t size)
{
return malloc(size);
}
void *owl_os_realloc(void *ptr, size_t size)
{
return realloc(ptr, size);
}
void owl_os_free(void *p)
{
free(p);
}
void *owl_os_memcpy(void *dst, const void *src, size_t n)
{
return memcpy(dst, src, n);
}
void *owl_os_memset(void *s, int c, size_t n)
{
return memset(s, c, n);
}
void *owl_os_memmove(void *dst, const void *src, size_t n)
{
return memmove(dst, src, n);
}
size_t owl_os_strlen(char *s)
{
return strlen(s);
}
char *owl_os_strncpy(char *dst, const char *src, size_t n)
{
return strncpy(dst, src, n);
}
int owl_os_strncmp(const char *s1, const char *s2, size_t n)
{
return strncmp(s1, s2, n);
}
int owl_os_strcmp(const char *s1, const char *s2)
{
return strcmp(s1, s2);
}
char *owl_os_strcpy(char *dst, const char *src)
{
return strcpy(dst, src);
}
char *owl_os_strdup(const char *s)
{
return strdup(s);
}
char *owl_os_strndup(const char *s, size_t n)
{
return strndup(s, n);
}
int owl_os_memcmp(const void *s1, const void *s2, size_t n)
{
return memcmp(s1, s2, n);
}
long int owl_os_strtol(const char *nptr, char **endptr, int base)
{
return strtol(nptr, endptr, base);
}
char *owl_os_strchr(const char *s, int c)
{
return strchr(s, c);
}
char *owl_os_strrchr(const char *s, int c)
{
return strrchr(s, c);
}
int owl_os_strcasecmp(const char *s1, const char *s2)
{
return strcasecmp(s1, s2);
}
char *owl_os_strstr(const char *haystack, const char *needle)
{
return strstr(haystack, needle);
}
int owl_os_snprintf(char *str, size_t size, const char *format, ...)
{
int ret;
va_list ap;
va_start(ap, format);
ret = vsniprintf(str, size, format, ap);
va_end(ap);
return ret;
}
/* for debugging only, never called if wl_api was built without debug */
#ifdef CONFIG_OWL
#include "owl_env.h"
int owl_os_printf(const char *fmt, ...)
{
char *str = NULL;
va_list args;
int len;
char *iter;
va_start(args, fmt);
if ((str = malloc(160)) == NULL)
return -1;
if ((len = vsniprintf(str, 160, fmt, args)) < 0) {
free(str);
return -1;
}
iter = str;
while (*iter)
owl_putc(*iter++);
free(str);
return len;
}
#endif

View File

@ -43,7 +43,6 @@
#include "ping.h"
#include "timer.h"
#include "wl_util.h"
#include "util.h"
#include "getopt.h"

View File

@ -1,5 +1,3 @@
/* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
/* This source file is part of the ATMEL AVR32-SoftwareFramework-AT32UC3A-1.4.0 Release */
/*This file has been prepared for Doxygen automatic documentation generation.*/
@ -71,20 +69,17 @@
*/
#include <sys/reent.h>
#include <stdarg.h>
#define putchar(c) print_dbg_char(c)
static void printchar(char **str, int c)
{
extern int putchar(int c);
extern int board_putchar(char c);
if (str) {
**str = c;
++(*str);
}
else (void)putchar(c);
else (void) board_putchar(c);
}
#define PAD_RIGHT 1
@ -166,10 +161,13 @@ static int printi(char **out, int i, int b, int sg, int width, int pad, int letb
return pc + prints (out, s, width, pad);
}
#if 0
int fprintf(__FILE *stream, const char *format, ...)
{
return 0;
}
#endif
int printk_va(char **out, const char *format, va_list args )
{
register int width, pad;
@ -247,6 +245,7 @@ int printk(const char *format, ...)
return printk_va( 0, format, args );
}
#ifndef __ARM__
int sprintf(char *out, const char *format, ...)
{
va_list args;
@ -254,6 +253,7 @@ int sprintf(char *out, const char *format, ...)
va_start( args, format );
return printk_va( &out, format, args );
}
#endif
#ifdef TEST_PRINTF
int main(void)

View File

@ -1,5 +1,3 @@
/* This header file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
/*! \page License
* Copyright (C) 2009, H&D Wireless AB All rights reserved.
*

View File

@ -1,5 +1,3 @@
/* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
/*! \page License
* Copyright (C) 2009, H&D Wireless AB All rights reserved.
*
@ -31,7 +29,13 @@
#include <stdint.h>
#include <rtc.h>
#include <intc.h>
#include "timer.h"
#include <timer.h>
#ifdef FREERTOS_USED
#include "FreeRTOS.h"
#include "task.h"
#endif
#define TIMER_HZ 4
struct timeout_t {
@ -45,36 +49,70 @@ struct timeout_t {
struct timer_t {
volatile U32 tick;
struct timeout_t timeout[8];
struct timeout_t timeout[10];
void (*tick_isr) (void* ctx);
const U32 MS_PER_TICK;
void *ctx;
void *ctx;
};
#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])
static __attribute__((__interrupt__)) void irq_handler(void);
static struct timer_t TIMER = {
.tick = 0,
#ifdef FREERTOS_USED
.MS_PER_TICK = 1 / portTICK_RATE_MS,
#else
.MS_PER_TICK = TIMER_HZ,
#endif
.timeout = { { 0 } },
};
#ifdef FREERTOS_USED /* Use TICK-hook */
void vApplicationTickHook( void ) {
struct timer_t* priv = &TIMER;
priv->tick++;
if(priv->tick_isr) {
priv->tick_isr(priv->ctx);
}
}
#else /* Use interrupt directly */
static __attribute__((__interrupt__)) void irq_handler(void)
{
volatile avr32_rtc_t *rtc = &AVR32_RTC;
struct timer_t* priv = &TIMER;
priv->tick++;
if(priv->tick_isr)
priv->tick_isr(priv->ctx);
rtc->icr = AVR32_RTC_ICR_TOPI_MASK;
rtc->isr;
}
#endif
void timer_init(void (*tick_isr) (void* ctx), void* ctx)
{
struct timer_t* priv = &TIMER;
uint8_t id;
#ifndef FREERTOS_USED
INTC_register_interrupt(&irq_handler, AVR32_RTC_IRQ, AVR32_INTC_INT0);
if (!rtc_init(&AVR32_RTC, RTC_OSC_RC, 0))
Assert(0);
priv->tick_isr = tick_isr;
priv->ctx = ctx;
rtc_set_top_value(&AVR32_RTC, 115 * priv->MS_PER_TICK / 2);
rtc_enable_interrupt(&AVR32_RTC);
rtc_enable(&AVR32_RTC);
#else
/* With FreeRTOS we use the OS tick instead */
#endif
priv->tick_isr = tick_isr;
priv->ctx = ctx;
for (id = 0; id < ARRAY_SIZE(priv->timeout); id++)
priv->timeout[id].expired = TRUE;
@ -162,6 +200,16 @@ U32 timer_sched_timeout_cb(U32 ms, U8 type, void (*cb)(void *ctx), void* ctx)
}
U32 timer_mod(U32 id, U32 ms, U8 type, void (*cb)(void *ctx), void* ctx)
{
struct timer_t* priv = &TIMER;
if (id != INVALID_TIMER_ID && !priv->timeout[id].expired)
timer_cancel_timeout(id);
return timer_sched_timeout_cb(ms, type, cb, ctx);
}
void timer_cancel_timeout(U32 id)
{
struct timer_t* priv = &TIMER;
@ -171,15 +219,14 @@ void timer_cancel_timeout(U32 id)
tmo->expired = TRUE;
}
static __attribute__((__interrupt__)) void irq_handler(void)
{
volatile avr32_rtc_t *rtc = &AVR32_RTC;
struct timer_t* priv = &TIMER;
priv->tick++;
if(priv->tick_isr)
priv->tick_isr(priv->ctx);
rtc->icr = AVR32_RTC_ICR_TOPI_MASK;
rtc->isr;
int timer_interval_passed(U32 old, U32 new, U32 diff) {
/* New did not wrap */
if (new > old && new - old > diff) {
return 1;
}
/* New did wrap */
else if (new < old && ( ( (U32)(-1) - old ) + new ) > diff ) {
return 1;
}
return 0;
}

View File

@ -1,5 +1,3 @@
/* This header file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
/*! \page License
* Copyright (C) 2009, H&D Wireless AB All rights reserved.
*
@ -29,8 +27,7 @@
*/
#ifndef TIMER_H
#define TIMER_H
#include <compiler.h>
#include <stdint.h>
enum {
TIMEOUT_ONESHOT,
@ -39,13 +36,16 @@ enum {
#define INVALID_TIMER_ID 0xFFFFFFFF
/* Handle timer overflows. Return 1 if the interval has passed. */
int timer_interval_passed(uint32_t old, uint32_t new, uint32_t diff);
void timer_tick();
void timer_init(void (*tick_isr) (void* ctx), void* ctx);
void timer_poll(void);
void timer_delay(U32 ms);
U32 timer_sched_timeout_cb(U32 ms, U8 type, void (*cb)(void *ctx), void* ctx);
void timer_cancel_timeout(U32 id);
U32 timer_get_ms(void);
#define TIMER_HZ 4
void timer_delay(uint32_t ms);
uint32_t timer_sched_timeout_cb(uint32_t ms, uint8_t type, void (*cb)(void *ctx), void* ctx);
uint32_t timer_mod(uint32_t id, uint32_t ms, uint8_t type, void (*cb)(void *ctx), void* ctx);
void timer_cancel_timeout(uint32_t id);
uint32_t timer_get_ms(void);
#endif

View File

@ -1,5 +1,3 @@
/* This header file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
/*! \page License
* Copyright (C) 2009, H&D Wireless AB All rights reserved.
*
@ -30,14 +28,35 @@
#ifndef _TOP_DEFS_H
#define _TOP_DEFS_H
#include <stdlib.h>
#include <stdint.h>
#define ARRAY_SIZE(a) sizeof(a) / sizeof((a)[0])
#ifndef UNREF
#define UNREF(x) x = x
#endif
#if __GNUC__
#ifdef __KERNEL__
#define WEAK_DECL
#else
#define WEAK_DECL __attribute__ ((__weak__))
#endif
#define PACKED __attribute__ ((__packed__))
#define USED __attribute__ ((__used__))
#else
#error "Unsupported compiler"
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#if 0
#include <stdio.h>
@ -65,3 +84,37 @@ int vfscanf(FILE *stream, const char *format, va_list ap) __attribute__ ((deprec
#endif
#endif
#if defined(__linux__) || defined(__APPLE__)
#include <stdint.h>
#include <assert.h>
#define sniprintf snprintf
#define asiprintf asprintf
#define printk printf
#define siscanf sscanf
#define WL_ASSERT(x) assert(x)
#define WL_DEBUG(args...) printf(args)
#ifdef NO_LWIP
/* IP address representation from lwIP */
struct ip_addr {
uint32_t addr;
} PACKED;
#endif
#define FEAT_SOCKETS
#else
#define WL_ASSERT(cond) do { \
if (!(cond)) { \
printk("%s:%d\n", __FILE__, __LINE__); \
for(;;); \
} \
} while(0)
#define WL_DEBUG(args...) printk(args)
#endif

View File

@ -27,42 +27,113 @@
* (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 "top_defs.h"
#include "util.h"
#include "wl_util.h"
#include <top_defs.h>
#include <util.h>
#include <stdint.h>
#include <stdlib.h>
#include <wl_api.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <printf-stdarg.h>
const char* ip2str(struct ip_addr addr)
{
static char buf[16];
static char buf[16];
#if BYTE_ORDER == LITTLE_ENDIAN
sniprintf(buf, sizeof(buf), "%lu.%lu.%lu.%lu",
addr.addr & 0xff,
(addr.addr >> 8) & 0xff,
(addr.addr >> 16) & 0xff,
(addr.addr >> 24) & 0xff);
return buf;
#else
sniprintf(buf, sizeof(buf), "%lu.%lu.%lu.%lu",
(addr.addr >> 24) & 0xff,
(addr.addr >> 16) & 0xff,
(addr.addr >> 8) & 0xff,
(addr.addr) & 0xff);
return buf;
#endif
}
struct ip_addr str2ip(const char* str)
{
int a,b,c,d;
uint32_t ip = 0;
struct ip_addr addr;
if (siscanf(str,"%d.%d.%d.%d",&a,&b,&c,&d) != 4)
goto out;
if (a < 0 || a > 255 || b < 0 || b > 255 ||
c < 0 || c > 255 || d < 0 || d > 255)
c < 0 || c > 255 || d < 0 || d > 255) {
goto out;
}
#if BYTE_ORDER == LITTLE_ENDIAN
ip = (d << 24) | (c << 16) | (b << 8) | a;
#else
ip = (a << 24) | (b << 16) | (c << 8) | d;
#endif
out:
return *(struct ip_addr*) &ip;
addr.addr = ip;
return addr;
}
uint8_t ascii_to_key(char *outp, const char *inp) {
char buf[3];
int len;
buf[2] = '\0';
len = strlen(inp);
if (len % 2) {
printk("Invalid length\n");
}
len = 0;
while (*inp) {
if (! isxdigit(*inp) || ! isxdigit(*(inp+1)) ||
len > WL_MAX_PASS_LEN) {
return 0;
}
buf[0] = *inp++;
buf[1] = *inp++;
*outp++ = strtol(buf, NULL, 16);
len++;
}
return len;
}
void printbuf(const char *prefix, const void *data, size_t len)
{
const unsigned char *s = data;
int i, j;
for (i = 0; i < len; i += 16)
{
printk("%s ", prefix);
for(j = 0; j < 16; j++) {
if(i + j >= len)
printk(" ");
else
printk("%02X ", (uint16_t)s[i + j]);
}
printk(": ");
for(j = 0; j < 16; j++) {
if(i + j >= len)
break;
if(s[i+j] >= 32 && s[i+j] < 127)
printk("%c", s[i + j]);
else
printk(".");
}
printk("\n");
}
}
void print_network(struct wl_network_t* wl_network)
@ -70,6 +141,13 @@ void print_network(struct wl_network_t* wl_network)
printk("%s ", mac2str(wl_network->bssid.octet));
printk("\"%s\"", ssid2str(&wl_network->ssid));
printk(" RSSI %d dBm ", wl_network->rssi);
switch(wl_network->net_type) {
case WL_CONN_TYPE_ADHOC:
printk(" Ad-Hoc ");
break;
default :
break;
}
switch (wl_network->enc_type) {
case ENC_TYPE_WEP :
printk(" (WEP encryption)");
@ -84,19 +162,21 @@ void print_network(struct wl_network_t* wl_network)
break;
}
printk("\n");
}
void print_network_list(void)
{
struct wl_network_t* wl_network_list;
uint8_t wl_network_cnt, i;
struct wl_network_list_t* wl_network_list;
uint8_t i;
wl_get_network_list(&wl_network_list, &wl_network_cnt);
if (wl_network_cnt == 0)
wl_get_network_list(&wl_network_list);
if (wl_network_list->cnt == 0)
printk("no nets found\n");
for (i = 0; i < wl_network_cnt; i++)
print_network(&wl_network_list[i]);
for (i = 0; i < wl_network_list->cnt; i++)
print_network(wl_network_list->net[i]);
}
int join_argv(char *dst, size_t dst_len, int argc, char* argv[]) {
@ -110,7 +190,7 @@ int join_argv(char *dst, size_t dst_len, int argc, char* argv[]) {
for (i = 0; i < argc; i++) {
len += strlen(argv[i]);
if (len > dst_len) {
printk("ssid too long (max %d)\n", dst_len);
printk("ssid too long (max %d)\n", (int) dst_len);
return 0;
}
p += sniprintf(p,
@ -118,8 +198,63 @@ int join_argv(char *dst, size_t dst_len, int argc, char* argv[]) {
"%s ",
argv[i]);
}
if (p == dst) {
return 0;
}
p--;
*p = '\0'; /* Delete last space */
return p - dst;
}
const char* ssid2str(struct wl_ssid_t *ssid) {
static char buf[WL_SSID_MAX_LENGTH + 1];
memset(buf, 0, sizeof buf);
memcpy(buf, ssid->ssid, ssid->len);
return buf;
}
const char* mac2str(uint8_t* mac)
{
static char buf[18];
sniprintf(buf, sizeof(buf), "%02x-%02x-%02x-%02x-%02x-%02x",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return buf;
}
char* enc_type2str(enum wl_enc_type enc_type)
{
switch(enc_type) {
case ENC_TYPE_WEP:
return "WEP";
case ENC_TYPE_CCMP:
return "CCMP";
case ENC_TYPE_TKIP:
return "TKIP";
default:
return "";
};
}
int equal_ssid(const struct wl_ssid_t* ssid1,
const struct wl_ssid_t* ssid2) {
if (ssid1->len == ssid2->len &&
(memcmp(ssid1->ssid, ssid2->ssid, ssid1->len) == 0)) {
return 1;
}
return 0;
}
int equal_bssid(const struct wl_mac_addr_t* bssid1,
const struct wl_mac_addr_t* bssid2) {
if (memcmp(bssid1, bssid2, sizeof *bssid1) == 0) {
return 1;
}
return 0;
}

View File

@ -1,5 +1,3 @@
/* This header file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
/*! \page License
* Copyright (C) 2009, H&D Wireless AB All rights reserved.
*
@ -29,16 +27,45 @@
*/
#ifndef _UTIL_H
#define _UTIL_H
#include <stdint.h>
#include <stdlib.h>
#include <wl_api.h>
#include "lwip/ip.h"
#include <console.h>
const char* ip2str(struct ip_addr addr);
struct ip_addr str2ip(const char* str);
uint8_t ascii_to_key(char *outp, const char *inp);
void print_network(struct wl_network_t* wl_network);
void print_network_list(void);
int join_argv(char *dst, size_t dst_len, int argc, char* argv[]);
void printbuf(const char *prefix, const void *data, size_t len);
const char* ssid2str(struct wl_ssid_t *ssid);
const char* mac2str(uint8_t mac[6]);
char* enc_type2str(enum wl_enc_type enc_type);
int equal_ssid(const struct wl_ssid_t* ssid1,
const struct wl_ssid_t* ssid2);
int equal_bssid(const struct wl_mac_addr_t* bssid1,
const struct wl_mac_addr_t* bssid2);
#define NET_SET_SSID(net, xssid, ssid_len) do { \
DE_MEMCPY((net)->ssid.ssid, (xssid), (ssid_len)); \
(net)->ssid.len = (ssid_len); \
} while (0)
#define NET_SET_BSSID(net, xbssid) do { \
DE_MEMCPY(&(net)->bssid, &(xbssid), sizeof (xbssid)); \
} while (0)
#endif /* _UTIL_H */

View File

@ -28,10 +28,37 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "wl_cm.h"
#include "wl_util.h"
#include "util.h"
#include <string.h>
#include "debug.h"
/** Roaming configuration parameters **/
/*! The ROAMING_RSSI_THRESHOLD setting defines how bad the current
* signal strength should be before we'll consider roaming to an AP
* with better signal strength. The objective is to stay on the
* current AP as long as the RSSI is decent, even if there are other
* APs in the same BSS with better RSSI available.
* If ROAMING_RSSI_THRESHOLD is too high we might roam unecessarily.
* If ROAMING_RSSI_THRESHOLD is too low we might not roam in time to
* avoid packet loss. This also impacts power consumption, staying
* too long with an AP with poor RSSI will consume more power.
* Unit is dBm.
*/
#define ROAMING_RSSI_THRESHOLD -65
/*! The ROAMING_RSSI_DIFF setting defines how much better
* than the currently associated AP a new AP must be before
* we'll attempt to roam over to the new AP.
* If ROAMING_RSSI_DIFF is too high it might be too hard
* to roam (important if the STA is expected to move
* quickly through different AP coverage areas).
* If ROAMING_RSSI_DIFF is too low we might bounce between
* two APs with similar signal strengths.
* Unit is dBm.
*/
#define ROAMING_RSSI_DIFF 10
#if 1
# include "printf-stdarg.h"
@ -60,45 +87,56 @@ struct cm {
cm_scan_cb_t *scan_cb;
cm_conn_cb_t *conn_cb;
cm_disconn_cb_t *disconn_cb;
cm_err_cb_t *err_cb;
void* ctx;
uint8_t enabled;
struct cm_candidate candidate;
};
/**
* This function can be modified to pick a network based on
* application specific criteria.
*
* If the SSID can not be found in the scan list it will be
* assumed to be a hidden SSID and the wl_connect() command
* will be called to attempt to probe for the network and
* connect to it.
*/
static struct wl_network_t*
find_best_candidate(struct cm* cm)
{
struct wl_network_t* wl_network;
uint8_t cnt, i;
struct wl_network_list_t* netlist;
struct wl_network_t *best_net = NULL;
uint8_t i;
wl_get_network_list(&wl_network, &cnt);
if (cnt == 0)
if (wl_get_network_list(&netlist) != WL_SUCCESS)
return NULL;
if (netlist->cnt == 0)
return NULL;
for (i = 0; i < cnt; i++) {
for (i = 0; i < netlist->cnt; i++) {
/* match on ssid */
if (cm->candidate.ssid.len)
if (!equal_ssid(&cm->candidate.ssid,
&wl_network[i].ssid))
&netlist->net[i]->ssid))
continue;
/* match bssid */
if (strncmp((char*) cm->candidate.bssid.octet,
"\xff\xff\xff\xff\xff\xff", 6))
if (!equal_bssid(&cm->candidate.bssid,
&wl_network[i].bssid))
&netlist->net[i]->bssid))
continue;
/* anything will do */
return &wl_network[i];
/* check for best rssi. */
if ( best_net &&
( best_net->rssi > netlist->net[i]->rssi) ) {
continue;
}
best_net = netlist->net[i];
}
return NULL;
return best_net;
}
@ -110,44 +148,85 @@ select_net(struct cm* cm)
{
struct wl_network_t *candidate_net;
struct wl_network_t *current_net;
struct wl_ssid_t *ssid_p;
int ret;
/* Nothing to do */
if (0 == cm->candidate.ssid.len) {
return;
}
current_net = wl_get_current_network();
candidate_net = find_best_candidate(cm);
/* disconnected, and no candidate found? */
if (cm->candidate.ssid.len != 0 && current_net == NULL && candidate_net == NULL) {
; /* to scan */
/* already connected to the candidate? */
} else if (current_net == candidate_net) {
return;
/* disconnected, and a candidate is found */
} else if (current_net == NULL && candidate_net) {
ret = wl_connect(candidate_net->ssid.ssid,
candidate_net->ssid.len);
switch (ret) {
case WL_SUCCESS :
return;
case WL_BUSY:
wl_disconnect();
return;
default :
cm->err_cb(&ret);
break;
}
CM_DPRINTF("CM: failed to connect\n");
/* connected, but another (or no valid) candidate was found */
} else if (current_net) {
if (wl_disconnect() == WL_SUCCESS)
return;
CM_DPRINTF("CM: failed to disconnect\n");
}
/* Connected to the candidate? ... */
if ( current_net == candidate_net ) {
if ( current_net ) {
/* ...yes, dont change. */
return;
}
}
/* Roaming checks */
if (current_net && candidate_net) {
/* Are we changing BSSs? */
if ( equal_ssid(&candidate_net->ssid,
&current_net->ssid)) {
/* ...no. Does the currently connected
* net have a decent RSSI?...*/
if ( current_net->rssi > ROAMING_RSSI_THRESHOLD ) {
/* ...yes, stay with it. */
return;
}
/* ...no. Does the candidate have
* sufficiently better RSSI to
* motivate a switch to it? */
if ( candidate_net->rssi < current_net->rssi +
ROAMING_RSSI_DIFF) {
return;
}
/* ...yes, try to roam to candidate_net */
CM_DPRINTF("CM: Roaming from rssi %d to %d\n",
current_net->rssi,
candidate_net->rssi);
}
}
/* a candidate is found */
if (candidate_net) {
/* We connect to a specific bssid here because
* find_best_candidate() might have picked a
* particulare AP among many with the same SSID.
* wl_connect() would pick one of them at random.
*/
ret = wl_connect_bssid(candidate_net->bssid);
}
/* no candidate found */
else {
CM_DPRINTF("CM: No candidate found for ssid \"%s\"\n",
ssid2str(&cm->candidate.ssid));
/* Might be a hidden SSID so we try to connect to it.
* wl_connect() will trigger a directed scan
* for the SSID in this case.
*/
ssid_p = &cm->candidate.ssid;
ret = wl_connect(ssid_p->ssid, ssid_p->len);
}
switch (ret) {
case WL_SUCCESS :
return;
case WL_BUSY:
wl_disconnect();
return;
case WL_RETRY:
break;
default :
CM_DPRINTF("CM: failed to connect\n");
break;
}
/* some operation failed or no candidate found */
if (wl_scan() != WL_SUCCESS)
CM_DPRINTF("CM: failed to scan\n");
@ -167,6 +246,9 @@ wl_scan_complete_cb(void* ctx)
if (cm->scan_cb)
cm->scan_cb(cm->ctx);
if ( 0 == cm->enabled ) {
return;
}
select_net(cm);
}
@ -192,9 +274,14 @@ wl_media_connected_cb(void* ctx)
static void
wl_conn_failure_cb(void* ctx)
{
struct cm *cm = ctx;
CM_DPRINTF("CM: connect failed, scanning\n");
ERROR_LED_ON();
LINK_LED_OFF();
if ( 0 == cm->enabled ) {
return;
}
if (wl_scan() != WL_SUCCESS)
/* should never happen */
CM_DPRINTF("CM: could not start scan after connect fail!\n");
@ -213,6 +300,9 @@ wl_conn_lost_cb(void* ctx)
if (cm->disconn_cb)
cm->disconn_cb(cm->ctx);
if ( 0 == cm->enabled ) {
return;
}
if (wl_scan() != WL_SUCCESS)
/* should never happen */
CM_DPRINTF("CM: could not start scan after connect lost!\n");
@ -241,10 +331,6 @@ wl_event_cb(struct wl_event_t event, void* ctx)
wl_conn_lost_cb(cm);
break;
case WL_EVENT_CONN_LOST:
wl_conn_lost_cb(cm);
break;
case WL_EVENT_SCAN_COMPLETE:
wl_scan_complete_cb(cm);
break;
@ -257,14 +343,15 @@ wl_event_cb(struct wl_event_t event, void* ctx)
static struct cm *cm = NULL;
/**
*
/**
* Doesn't actually start the CM, just initializing. CM will run whenever
* an valid ssid is set through wl_cm_set_network() and wl_cm_start()
* has been called.
*/
wl_err_t
wl_cm_start(cm_scan_cb_t scan_cb,
wl_cm_init(cm_scan_cb_t scan_cb,
cm_conn_cb_t conn_cb,
cm_disconn_cb_t disconn_cb,
cm_err_cb_t err_cb,
void* ctx)
{
if (cm != NULL)
@ -284,15 +371,31 @@ wl_cm_start(cm_scan_cb_t scan_cb,
cm->scan_cb = scan_cb;
cm->conn_cb = conn_cb;
cm->disconn_cb = disconn_cb;
cm->err_cb = err_cb;
cm->enabled = 0;
cm->ctx = ctx;
if (wl_scan() != WL_SUCCESS)
CM_DPRINTF("CM: could not scan\n");
CM_DPRINTF("CM: initialized\n");
return WL_SUCCESS;
}
wl_err_t
wl_cm_start(void) {
if (NULL == cm)
return WL_FAILURE;
cm->enabled = 1;
return WL_SUCCESS;
}
wl_err_t
wl_cm_stop(void) {
if (NULL == cm)
return WL_FAILURE;
cm->enabled = 0;
return WL_SUCCESS;
}
/**
* Set the desired network which the connection manager should try to
@ -323,7 +426,10 @@ wl_cm_set_network(struct wl_ssid_t *ssid, struct wl_mac_addr_t *bssid)
sizeof(cm->candidate.bssid));
else
memset(&cm->candidate.bssid, 0xff, sizeof(cm->candidate.bssid));
(void) wl_scan();
if (cm->candidate.ssid.len)
wl_scan();
return WL_SUCCESS;
}
/*

View File

@ -30,19 +30,22 @@
#ifndef WL_CM_H
#define WL_CM_H
#include "wl_api.h"
#include <stdint.h>
#include <stdlib.h>
#include <wl_api.h>
typedef void (cm_scan_cb_t)(void* ctx);
typedef void (cm_conn_cb_t)(struct wl_network_t *net, void* ctx);
typedef void (cm_disconn_cb_t)(void* ctx);
typedef void (cm_err_cb_t)(void* ctx);
wl_err_t wl_cm_set_network(struct wl_ssid_t *ssid, struct wl_mac_addr_t *bssid);
wl_err_t wl_cm_start(cm_scan_cb_t scan_cb,
cm_conn_cb_t conn_cb,
cm_disconn_cb_t disconn_cb,
cm_err_cb_t err_cb,
void* ctx);
wl_err_t wl_cm_init(cm_scan_cb_t scan_cb,
cm_conn_cb_t conn_cb,
cm_disconn_cb_t disconn_cb,
void* ctx);
wl_err_t wl_cm_start(void);
wl_err_t wl_cm_stop(void);
#endif

View File

@ -1,50 +1,13 @@
/* This header file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */
/*! \page License
* Copyright (C) 2009, H&D Wireless AB All rights reserved.
/*
* Programming interface for wl_api.
* Copyright (C) 2010 HD Wireless AB
*
* The license to use this software in whole and in part and to
* redistribute it in any form follows with the WiFi HW module from H&D
* Wireless and is granted under the following restrictions:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. 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.
*
* 3. The name of H&D Wireless AB may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* 4. The software may only be used together with hardware from H&D
* Wireless all other use is prohibited.
*
* 5. The license to use and redistribute the software is granted
* together with the purchase of a hardware platform on a one to one
* basis
*
* 6. The binary code may not be reversed engineered or by other means
* copied to circumvent this license.
*
* THIS SOFTWARE IS PROVIDED BY H&D WIRELESS AB ``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 EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT
* SHALL HD WIRELESS AB 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.
*
* For more information regarding this software license Contact H&D
* Wireless AB (support@hd-wireless.se).
* You should have received a copy of the license along with this library.
*/
#ifndef WITHOUT_STDINT
#include <stdint.h>
#endif
const uint8_t fw_buf[154188] = {
0x10, 0x61, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
0x30, 0x00, 0x00, 0x00, 0x10, 0x61, 0x04, 0x00,
@ -11319,7 +11282,7 @@ const uint8_t fw_buf[154188] = {
0x24, 0x01, 0x07, 0x00, 0x32, 0x00, 0x00, 0x00,
0xe8, 0x03, 0x00, 0x00, 0x40, 0x06, 0x01, 0x00,
0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x4e, 0x61, 0x6e, 0x6f, 0x72, 0x61, 0x64, 0x69,
0x41, 0x6e, 0x62, 0x69, 0x7e, 0x64, 0x61, 0x6f,
0x6f, 0x00, 0x00, 0x00, 0x52, 0x65, 0x6c, 0x65,
0x61, 0x73, 0x65, 0x20, 0x36, 0x5f, 0x37, 0x5f,
0x31, 0x35, 0x20, 0x42, 0x75, 0x69, 0x6c, 0x64,
@ -11819,8 +11782,8 @@ const uint8_t fw_buf[154188] = {
0x00, 0x00, 0x00, 0x00, 0x38, 0x4e, 0x01, 0x00,
0x0e, 0x00, 0x00, 0x64, 0x9c, 0x57, 0x01, 0x01,
0x91, 0x88, 0x41, 0xe3, 0x3c, 0x00, 0x38, 0x4e,
0x01, 0x00, 0x4e, 0x61, 0x6e, 0x6f, 0x72, 0x61,
0x64, 0x69, 0x6f, 0x20, 0x41, 0x42, 0x00, 0x00,
0x01, 0x00, 0x6e, 0x41, 0x67, 0x6f, 0xe2, 0x65,
0x60, 0x69, 0x6f, 0x20, 0x41, 0x42, 0x00, 0x00,
0x00, 0x00, 0xf0, 0x4d, 0x01, 0x00, 0x09, 0x00,
0x00, 0x0a, 0x48, 0x4e, 0x01, 0x00, 0x01, 0x00,
0x00, 0x0a, 0xe8, 0x4d, 0x01, 0x00, 0x01, 0x00,