summaryrefslogtreecommitdiff
path: root/Libraries/WiShield
diff options
context:
space:
mode:
authorbzztbomb <skinny@knowhere.net>2010-04-15 12:13:53 -0700
committerbzztbomb <skinny@knowhere.net>2010-04-15 12:13:53 -0700
commitcc23a46941106a6515b3fe958daba0f3a1551883 (patch)
tree280dad14cdb4c8c806e212c8c143f25e652338ba /Libraries/WiShield
Initial commit of working OSC parsing over Wifi
Diffstat (limited to 'Libraries/WiShield')
-rw-r--r--Libraries/WiShield/README26
-rw-r--r--Libraries/WiShield/WiServer.cpp737
-rw-r--r--Libraries/WiShield/WiServer.h272
-rw-r--r--Libraries/WiShield/WiShield.cpp87
-rw-r--r--Libraries/WiShield/WiShield.h53
-rw-r--r--Libraries/WiShield/apps-conf.h65
-rw-r--r--Libraries/WiShield/avrlibdefs.h83
-rw-r--r--Libraries/WiShield/avrlibtypes.h84
-rw-r--r--Libraries/WiShield/clock-arch.c86
-rw-r--r--Libraries/WiShield/clock-arch.h47
-rw-r--r--Libraries/WiShield/clock.h88
-rw-r--r--Libraries/WiShield/config.h60
-rw-r--r--Libraries/WiShield/examples/Flash/Flash.pde89
-rw-r--r--Libraries/WiShield/examples/Flash/webserver.c125
-rw-r--r--Libraries/WiShield/examples/SimpleClient/SimpleClient.pde88
-rw-r--r--Libraries/WiShield/examples/SimpleServer/SimpleServer.pde74
-rw-r--r--Libraries/WiShield/examples/SimpleTweeter/SimpleTweeter.pde79
-rw-r--r--Libraries/WiShield/examples/SocketApp/SocketApp.pde48
-rw-r--r--Libraries/WiShield/examples/SocketApp/socketapp.c118
-rw-r--r--Libraries/WiShield/examples/UDPApp/UDPApp.pde48
-rw-r--r--Libraries/WiShield/examples/UDPApp/udpapp.c137
-rw-r--r--Libraries/WiShield/examples/UDPApp/udpapp.c~137
-rw-r--r--Libraries/WiShield/examples/WebClient/WebClient.pde74
-rw-r--r--Libraries/WiShield/examples/WebClient/webclient.c372
-rw-r--r--Libraries/WiShield/examples/WebServer/WebServer.pde51
-rw-r--r--Libraries/WiShield/examples/WebServer/webserver.c118
-rw-r--r--Libraries/WiShield/g2100.c595
-rw-r--r--Libraries/WiShield/g2100.h302
-rw-r--r--Libraries/WiShield/global-conf.h45
-rw-r--r--Libraries/WiShield/global.h34
-rw-r--r--Libraries/WiShield/lc-addrlabels.h83
-rw-r--r--Libraries/WiShield/lc-switch.h76
-rw-r--r--Libraries/WiShield/lc.h131
-rw-r--r--Libraries/WiShield/memb.c104
-rw-r--r--Libraries/WiShield/memb.h142
-rw-r--r--Libraries/WiShield/network.c71
-rw-r--r--Libraries/WiShield/network.h53
-rw-r--r--Libraries/WiShield/psock.c338
-rw-r--r--Libraries/WiShield/psock.h380
-rw-r--r--Libraries/WiShield/pt.h323
-rw-r--r--Libraries/WiShield/request.cpp104
-rw-r--r--Libraries/WiShield/server.h69
-rw-r--r--Libraries/WiShield/socketapp.h62
-rw-r--r--Libraries/WiShield/spi.h167
-rw-r--r--Libraries/WiShield/stack.c165
-rw-r--r--Libraries/WiShield/strings.c79
-rw-r--r--Libraries/WiShield/timer.c127
-rw-r--r--Libraries/WiShield/timer.h86
-rw-r--r--Libraries/WiShield/udpapp.h71
-rw-r--r--Libraries/WiShield/uip-conf.h146
-rw-r--r--Libraries/WiShield/uip-fw.c532
-rw-r--r--Libraries/WiShield/uip-fw.h176
-rw-r--r--Libraries/WiShield/uip-neighbor.c158
-rw-r--r--Libraries/WiShield/uip-neighbor.h61
-rw-r--r--Libraries/WiShield/uip-split.c136
-rw-r--r--Libraries/WiShield/uip-split.h96
-rw-r--r--Libraries/WiShield/uip.c1927
-rw-r--r--Libraries/WiShield/uip.h1634
-rw-r--r--Libraries/WiShield/uip_arch.h138
-rw-r--r--Libraries/WiShield/uip_arp.c481
-rw-r--r--Libraries/WiShield/uip_arp.h179
-rw-r--r--Libraries/WiShield/uiplib.c74
-rw-r--r--Libraries/WiShield/uiplib.h71
-rw-r--r--Libraries/WiShield/uipopt.h574
-rw-r--r--Libraries/WiShield/webclient.h262
-rw-r--r--Libraries/WiShield/webserver.h52
-rw-r--r--Libraries/WiShield/witypes.h72
67 files changed, 13622 insertions, 0 deletions
diff --git a/Libraries/WiShield/README b/Libraries/WiShield/README
new file mode 100644
index 0000000..4a2dba5
--- /dev/null
+++ b/Libraries/WiShield/README
@@ -0,0 +1,26 @@
+WiShield library and TCP/IP stack files for the WiShield 1.0 wireless devices
+
+Async Labs Inc.
+www.asynclabs.com
+
+-------------------------------------------------------------------------------
+Version 1.2.0
+-------------------------------------------------------------------------------
+Changes:
+- Fixed buffer overflow issue
+- Added files for WiServer implementation
+- Removed stray debug prints from source code
+- Made sketches uniform to existing examples
+- Added missing implementation for setURL function
+- Adding support for using Digital pin 8 on Arduino as the interrupt pin for
+ WiShield
+- Added function for base64 encoding
+- Fixing IP address assignment macro
+
+New features:
+- Adding sample SocketApp sketch to demonstrate using WiShield for socket
+ communication
+- Adding UDPApp sketch to demonstarte use of UDP protocol for communication
+
+Known issues:
+None
diff --git a/Libraries/WiShield/WiServer.cpp b/Libraries/WiShield/WiServer.cpp
new file mode 100644
index 0000000..b3c4018
--- /dev/null
+++ b/Libraries/WiShield/WiServer.cpp
@@ -0,0 +1,737 @@
+/******************************************************************************
+
+ Filename: WiSever.cpp
+ Description: Main library code for the WiServer library
+
+ ******************************************************************************
+
+ Copyright(c) 2009 Mark A. Patel All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ Mark A. Patel 05/27/2009 Initial version
+
+ Mark A. Patel 06/05/2009 Revised to work with stack version 1.1,
+ plus added various enhancements such as
+ multi-pass transmission, local client
+ checks, activity LED support, etc.
+
+
+ *****************************************************************************/
+
+
+#include "WProgram.h"
+#include "WiServer.h"
+
+extern "C" {
+ #include "g2100.h"
+ #include "spi.h"
+ #include "uip.h"
+ #include "server.h"
+ #include "global-conf.h"
+ void stack_init(void);
+ void stack_process(void);
+}
+
+#ifdef APP_WISERVER
+
+#define CR 13
+#define LF 10
+
+// Strings stored in program memory (defined in strings.c)
+extern const prog_char httpOK[];
+extern const prog_char httpNotFound[];
+extern const prog_char http10[];
+extern const prog_char post[];
+extern const prog_char get[];
+extern const prog_char authBasic[];
+extern const prog_char host[];
+extern const prog_char userAgent[];
+extern const prog_char contentTypeForm[];
+extern const prog_char contentLength[];
+extern const prog_char status[];
+extern const prog_char base64Chars[];
+
+
+
+/* Application's callback function for serving pages */
+pageServingFunction callbackFunc;
+
+/* Digital output pin to indicate TX activity */
+char txPin = -1;
+
+/* Digital output pin to indicate RX activity */
+char rxPin = -1;
+
+/* Enables basic log messages via Serial */
+boolean verbose = false;
+
+
+void Server::init(pageServingFunction function) {
+
+ // WiShield init
+ zg_init();
+
+#ifdef USE_DIG0_INTR
+ attachInterrupt(0, zg_isr, LOW);
+#endif
+
+#ifdef USE_DIG8_INTR
+ // set digital pin 8 on Arduino
+ // as ZG interrupt pin
+ PCICR |= (1<<PCIE0);
+ PCMSK0 |= (1<<PCINT0);
+#endif
+
+ while(zg_get_conn_state() != 1) {
+ zg_drv_process();
+ }
+
+ // Start the stack
+ stack_init();
+
+ // Store the callback function for serving pages
+ // and start listening for connections on port 80 if
+ // the function is non-null
+ callbackFunc = function;
+ if (callbackFunc) {
+ // Listen for server requests on port 80
+ uip_listen(HTONS(80));
+ }
+
+#ifdef DEBUG
+ verbose = true;
+ Serial.println("WiServer init called");
+#endif // DEBUG
+}
+
+#ifdef USE_DIG8_INTR
+// PCINT0 interrupt vector
+ISR(PCINT0_vect)
+{
+ zg_isr();
+}
+#endif
+
+void Server::setIndicatorPins(int tx, int rx) {
+ // Store the pin numbers
+ txPin = tx;
+ rxPin = rx;
+ // Set pin modes as needed
+ if (tx != -1) pinMode(tx, OUTPUT);
+ if (rx != -1) pinMode(rx, OUTPUT);
+}
+
+/*
+ * Sets the TX pin (if enabled) to the specified value (HIGH or LOW)
+ */
+void setTXPin(byte value) {
+ if (txPin != -1) digitalWrite(txPin, value);
+}
+
+/*
+ * Sets the RX pin (if enabled) to the specified value (HIGH or LOW)
+ */
+void setRXPin(byte value) {
+ if (rxPin != -1) digitalWrite(rxPin, value);
+}
+
+
+void Server::enableVerboseMode(boolean enable) {
+ verbose = enable;
+}
+
+
+
+/******* Generic printing and sending functions ********/
+
+
+void Server::write_P(const char data[], int len) {
+ while (len-- > 0) {
+ this->write(pgm_read_byte(data++));
+ }
+}
+
+
+void Server::print_P(const char s[]) {
+ char c = pgm_read_byte(s);
+ while (c) {
+ this->print(c);
+ c = pgm_read_byte(++s);
+ }
+}
+
+
+void Server::println_P(const char c[]) {
+ this->print_P(c);
+ this->println();
+}
+
+
+
+void Server::printTime(long t) {
+
+ long secs = t / 1000;
+ int mins = (int)(secs / 60);
+ int hours = mins / 60;
+
+ hours %= 24;
+ this->print(hours / 10);
+ this->print(hours % 10);
+ this->print(':');
+
+ mins %= 60;
+ this->print(mins / 10);
+ this->print(mins % 10);
+ this->print(':');
+
+ secs %= 60;
+ this->print(secs / 10);
+ this->print(secs % 10);
+}
+
+
+/*
+ * Writes a byte to the virtual buffer for the current connection
+ */
+void Server::write(uint8_t b) {
+
+ // Make sure there's a current connection
+ if (uip_conn) {
+ // Check if the cursor is within the range that maps to the uip_appdata buffer
+ // (and we'll increment the cursor while we're at it)
+ int offset = (int)(uip_conn->appstate.cursor++) - uip_conn->appstate.ackedCount;
+ if ((offset >= 0) && (offset < (int)uip_conn->mss)) {
+ // Write the byte to the corresponding location in the buffer
+ *((char*)uip_appdata + offset) = b;
+ }
+ }
+}
+
+
+/*
+ * Sends the real data in the current connection's virtual buffer
+ */
+void send() {
+
+ uip_tcp_appstate_t *app = &(uip_conn->appstate);
+
+ // Find the intersection of the virtual buffer and the real uip buffer
+ int len = (int)app->cursor - app->ackedCount;
+ len = len < 0 ? 0 : len;
+ len = len > (int)uip_conn->mss ? (int)uip_conn->mss : len;
+
+ if (verbose) {
+ Serial.print("TX ");
+ Serial.print(len);
+ Serial.println(" bytes");
+ }
+
+#ifdef DEBUG
+ Serial.print(app->ackedCount);
+ Serial.print(" - ");
+ Serial.print(app->ackedCount + len - 1);
+ Serial.print(" of ");
+ Serial.println((int)app->cursor);
+#endif // DEBUG
+
+ // Send the real bytes from the virtual buffer and record how many were sent
+ uip_send(uip_appdata, len);
+ app->sentCount = len;
+ setTXPin(HIGH);
+}
+
+
+/******* Server mode functions ********/
+
+
+/*
+ * Processes a line of data in an HTTP request. This function looks
+ * for GET and saves a copy of the URL in the current connection's
+ * server request. It also sets the request's isValid flag if the
+ * URL has been saved and an empty line is found.
+ */
+boolean processLine(char* data, int len) {
+
+ // Check for a valid GET line
+ if ((uip_conn->appstate.request == NULL) && (strncmp(data, "GET /", 4) == 0)) {
+ // URL starts at the '/'
+ char* start = data + 4;
+ // Find trailing space after the URL
+ data = start;
+ char* end = data + len;
+ while (++data < end) {
+ if (*data == ' ') {
+ // Replace the space with a NULL to terminate it
+ *(data++) = 0;
+ // Compute length of the URL including the NULL
+ int len = data - start;
+ // Allocate space for the URL and copy the contents
+ uip_conn->appstate.request = malloc(len);
+ memcpy(uip_conn->appstate.request, start, len);
+ return false;
+ }
+ }
+ // No space, not valid
+ }
+
+ return (len == 0);
+}
+
+
+/*
+ * Processes a packet of data that supposedly contains an HTTP request
+ * This function looks for CR/LF (or just LF) and calls processLine
+ * with each line of data found.
+ */
+boolean processPacket(char* data, int len) {
+
+ // Address after the last byte of data
+ char* end = data + len;
+ // Start of current line
+ char* start = data;
+
+ // Scan through the bytes in the packet looking for a Line Feed character
+ while (data < end) {
+ if (*data == LF) {
+ // Determine the length of the line excluding the Line Feed
+ int lineLength = data - start;
+
+ if (*(data - 1) == CR) {
+ lineLength--;
+ }
+
+ *(start + lineLength) = 0;
+ // Process the line
+ if (processLine(start, lineLength)) {
+ return true;
+ }
+ // Set up for the start of the next line
+ start = ++data;
+ } else {
+ // Go to the next byte
+ data++;
+ }
+ }
+ return false;
+}
+
+
+/*
+ * Attempts to send the requested page for the current connection
+ */
+void sendPage() {
+
+ // Reset the virtual buffer cursor
+ uip_conn->appstate.cursor = 0;
+
+ // Start off with an HTTP OK response header and a blank line
+ WiServer.println_P(httpOK);
+ WiServer.println();
+
+ // Call the application's 'sendPage' function and ask it to
+ // generate the requested page content.
+ if (!callbackFunc((char*)uip_conn->appstate.request)) {
+ // The URL is not recognized by the sketch
+ // Reset the cursor and overwrite the HTTP OK header with a 404 message
+ uip_conn->appstate.cursor = 0;
+ WiServer.println_P(httpNotFound);
+ WiServer.println();
+#ifdef DEBUG
+ Serial.println("URL Not Found");
+#endif // DEBUG
+ }
+ // Send the 'real' bytes in the buffer
+ send();
+}
+
+
+boolean Server::sendInProgress() {
+ return false; // FIX ME
+}
+
+
+boolean Server::clientIsLocal() {
+ // Check if there is a current connection
+ if (uip_conn != NULL) {
+ // Check if the remote host is local to the server
+ uip_ipaddr_t hostaddr, mask;
+ // Get the server's address
+ uip_gethostaddr(&hostaddr);
+ // Get the subnet mask
+ uip_getnetmask(&mask);
+ // Compare with the client's address
+ return uip_ipaddr_maskcmp(&hostaddr, uip_conn->ripaddr, &mask);
+ }
+ return false;
+}
+
+/*
+ * Handles high-level server communications
+ */
+void server_task_impl() {
+
+ // Get the connection's app state
+ uip_tcp_appstate_t *app = &(uip_conn->appstate);
+
+ if (uip_connected()) {
+
+ if (verbose) {
+ Serial.println("Server connected");
+ }
+
+ // Initialize the server request data
+ app->ackedCount = 0;
+ app->request = NULL;
+ }
+
+ if (uip_newdata()) {
+ setRXPin(HIGH);
+ // Process the received packet and check if a valid GET request had been received
+ if (processPacket((char*)uip_appdata, uip_datalen()) && app->request) {
+ if (verbose) {
+ Serial.print("Processing request for ");
+ Serial.println((char*)app->request);
+ }
+ sendPage();
+ }
+ }
+
+
+ // Did we get an ack for the last packet?
+ if (uip_acked()) {
+ // Record the bytes that were successfully sent
+ app->ackedCount += app->sentCount;
+ app->sentCount = 0;
+
+ // Check if we're done or need to send more content for this
+ // request
+ if (app->ackedCount == (int)app->cursor) {
+ // Done with the current request and connection
+ uip_close();
+ } else {
+ // Generate the content again to send the next packet of data
+ sendPage();
+ }
+ }
+
+ // Check if we need to retransmit
+ if (uip_rexmit()) {
+ // Send the same data again (same ackedCount value)
+ sendPage();
+ }
+
+ if (uip_aborted() || uip_closed() || uip_timedout()) {
+
+ // Check if a URL was stored for this connection
+ if (app->request != NULL) {
+ if (verbose) {
+ Serial.println("Server connection closed");
+ }
+
+ // Free RAM and clear the pointer
+ free(app->request);
+ app->request = NULL;
+ }
+ }
+}
+
+
+
+/******* Client mode functions ********/
+#ifdef ENABLE_CLIENT_MODE
+
+/* Linked list of queued client requests */
+GETrequest* queue = NULL;
+
+void Server::submitRequest(GETrequest *req) {
+ // Check for an empty queue
+ if (queue == NULL) {
+ // Point to the new request
+ queue = req;
+ } else {
+ // Find the tail of the queue
+ GETrequest* r = queue;
+ while (r->next != NULL) {
+ r = r->next;
+ }
+ // Append the new request
+ r->next = req;
+ }
+ // Set the request as being active
+ req->active = true;
+}
+
+
+/**
+ * Sends the request for the current connection
+ */
+void sendRequest() {
+
+ uip_tcp_appstate_t *app = &(uip_conn->appstate);
+ GETrequest *req = (GETrequest*)app->request;
+
+ // Reset the virtual buffer
+ app->cursor = 0;
+
+ // Indicates if this is a POST request (instead of a GET)
+ // Main difference is that POST requests have a body and a
+ // callback function to generate said body
+ bool isPost = req->body != NULL;
+
+ // Write out the request header
+ WiServer.print_P(isPost ? post : get);
+ WiServer.print(req->URL);
+ WiServer.println_P(http10);
+
+ // Host name
+ WiServer.print_P(host);
+ WiServer.println(req->hostName);
+
+ // Auth data (if applicable)
+ if (req->auth) {
+ WiServer.print_P(authBasic);
+ WiServer.println(req->auth);
+ }
+
+ // User agent (WiServer, of course!)
+ WiServer.println_P(userAgent);
+
+ if (isPost) {
+ // Since a post has a body after the blank header line, it has to include
+ // an accurate content length so that the server knows when it has received
+ // all of the body data.
+ char* lengthFieldPos; // Cursor position where the content length place holder starts
+ char* contentStart; // Start of the body
+ char* contentEnd; // End of the body
+
+ // Just form data for now
+ WiServer.println_P(contentTypeForm);
+
+ // Content length line (with 4-space placeholder for the value)
+ WiServer.println_P(contentLength);
+ // Make a note of where the place holder is so we can fill it in later
+ lengthFieldPos = app->cursor - 6; // 6 bytes for CR, LF, and 4 spaces
+
+ // Blank line to indicate end of header
+ WiServer.println();
+
+ // Body starts here
+ contentStart = app->cursor;
+
+ // Print the body preamble if the request has one
+ if (req->bodyPreamble) {
+ WiServer.print(req->bodyPreamble);
+ }
+
+ // Have the sketch provide the body for the POST
+ req->body();
+
+ // Body ends here
+ contentEnd = app->cursor;
+
+ // Move the cursor back to the content length value and write in the real length
+ app->cursor = lengthFieldPos;
+ WiServer.print((int)(contentEnd - contentStart));
+
+ // Put the cursor back at the end of the body so that all of the data gets sent
+ app->cursor = contentEnd;
+
+ } else {
+ // Blank line to indicate end of GET header
+ WiServer.println();
+ }
+
+ // Send the 'real' bytes in the buffer
+ send();
+}
+
+/**
+ * Handle client communications
+ */
+void client_task_impl() {
+
+ uip_tcp_appstate_t *app = &(uip_conn->appstate);
+ GETrequest *req = (GETrequest*)app->request;
+
+ if (uip_connected()) {
+
+ if (verbose) {
+ Serial.print("Connected to ");
+ Serial.println(req->hostName);
+ }
+ app->ackedCount = 0;
+ sendRequest();
+ }
+
+ // Did we get an ack for the last packet?
+ if (uip_acked()) {
+ // Record the bytes that were successfully sent
+ app->ackedCount += app->sentCount;
+ app->sentCount = 0;
+
+ // Check if we're done or need to send more content for this
+ // request
+ if (app->ackedCount != (int)app->cursor) {
+ // Generate the post again to send the next packet of data
+ sendRequest();
+ }
+ }
+
+ if (uip_rexmit()) {
+ sendRequest();
+ }
+
+ if (uip_newdata()) {
+ setRXPin(HIGH);
+
+ if (verbose) {
+ Serial.print("RX ");
+ Serial.print(uip_datalen());
+ Serial.print(" bytes from ");
+ Serial.println(req->hostName);
+ }
+
+ // Check if the sketch cares about the returned data
+ if ((req->returnFunc) && (uip_datalen() > 0)){
+ // Call the sketch's callback function
+ req->returnFunc((char*)uip_appdata, uip_datalen());
+ }
+ }
+
+ if (uip_aborted() || uip_timedout() || uip_closed()) {
+ if (req != NULL) {
+ if (verbose) {
+ Serial.print("Ended connection with ");
+ Serial.println(req->hostName);
+ }
+
+ if (req->returnFunc) {
+ // Call the sketch's callback function with 0 bytes to indicate End Of Data
+ req->returnFunc((char*)uip_appdata, 0);
+ }
+ // Remove the request from the connection
+ app->request = NULL;
+ // Request is no longer active
+ req->active = false;
+ }
+ }
+}
+
+
+char getChar(int nibble) {
+ return pgm_read_byte(base64Chars + nibble);
+}
+
+void storeBlock(char* src, char* dest, int len) {
+
+ dest[0] = getChar(src[0] >> 2);
+ dest[1] = getChar(((src[0] & 0x03) << 4) | ((src[1] & 0xf0) >> 4));
+ dest[2] = len > 1 ? getChar(((src[1] & 0x0f) << 2) | ((src[2] & 0xc0) >> 6)) : '=';
+ dest[3] = len > 2 ? getChar(src[2] & 0x3f ) : '=';
+}
+
+char* Server::base64encode(char* data) {
+
+ int len = strlen(data);
+ int outLenPadded = ((len + 2) / 3) << 2;
+ char* out = (char*)malloc(outLenPadded + 1);
+
+ char* outP = out;
+ while (len > 0) {
+
+ storeBlock(data, outP, min(len,3));
+ outP += 4;
+ data += 3;
+ len -= 3;
+ }
+ *(out + outLenPadded) = 0;
+ return out;
+}
+
+
+
+#endif // ENABLE_CLIENT_MODE
+
+
+
+/********* High-level WiServer functions ***********/
+
+/*
+ * This function is called by uip whenever a stack event occurs
+ */
+void server_app_task() {
+
+ // Clear the activity pins
+ setTXPin(LOW);
+ setRXPin(LOW);
+
+ // Check for an active connection
+ if (uip_conn) {
+ // Is the connection for local port 80?
+ if (uip_conn->lport == HTONS(80)) {
+ // Server mode
+ server_task_impl();
+ } else {
+#ifdef ENABLE_CLIENT_MODE
+ // Client mode
+ client_task_impl();
+#endif // ENABLE_CLIENT_MODE
+ }
+ }
+}
+
+
+/*
+ * Called by the sketch's main loop
+ */
+void Server::server_task() {
+
+ // Run the stack state machine
+ stack_process();
+
+ // Run the driver
+ zg_drv_process();
+
+#ifdef ENABLE_CLIENT_MODE
+ // Check if there is a pending client request
+ if (queue) {
+ // Attempt to connect to the server
+ struct uip_conn *conn = uip_connect(&(queue->ipAddr), queue->port);
+
+ if (conn != NULL) {
+#ifdef DEBUG
+ Serial.print("Got connection for ");
+ Serial.println(queue->hostName);
+#endif // DEBUG
+
+ // Attach the request object to its connection
+ conn->appstate.request = queue;
+ // Move the head of the queue to the next request in the queue
+ queue = queue->next;
+ // Clear the next pointer of the connected request
+ ((GETrequest*)conn->appstate.request)->next = NULL;
+ }
+ }
+#endif // ENABLE_CLIENT_MODE
+}
+
+// Single instance of the server
+Server WiServer;
+
+#endif /* APP_WISERVER */
diff --git a/Libraries/WiShield/WiServer.h b/Libraries/WiShield/WiServer.h
new file mode 100644
index 0000000..a8d9e4b
--- /dev/null
+++ b/Libraries/WiShield/WiServer.h
@@ -0,0 +1,272 @@
+/******************************************************************************
+
+ Filename: WiSever.h
+ Description: Main header file for the WiServer library
+
+ ******************************************************************************
+
+ Copyright(c) 2009 Mark A. Patel All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ Mark A. Patel 05/27/2009 Initial version
+
+ Mark A. Patel 06/05/2009 Revised to work with stack version 1.1,
+ plus added various enhancements such as
+ multi-pass transmission, local client
+ checks, activity LED support, etc.
+
+ Mark A. Patel 06/22/2009 Revised client API
+
+
+ *****************************************************************************/
+
+#ifndef WISERVER_H_
+#define WISERVER_H_
+
+extern "C" {
+ #include "witypes.h"
+ #include "server.h"
+ #include "config.h"
+ #include "uip.h"
+}
+
+#include "Print.h"
+
+
+/*
+ * Function for handling data returned by a POST or GET request
+ */
+typedef void (*returnFunction)(char* data, int len);
+
+/*
+ * Function for serving web pages
+ */
+typedef boolean (*pageServingFunction)(char* URL);
+
+/*
+ * Function for providing the body of a POST request
+ */
+typedef void (*bodyFunction)();
+
+
+
+#ifdef ENABLE_CLIENT_MODE
+/*********** Classes for client-mode functionality *********/
+
+/*
+ * Class that encapsulates an HTTP GET request
+ */
+class GETrequest
+ {
+ public:
+
+ /*
+ * Creates a new GETrequest with the provided IP, port, host name and URL
+ */
+ GETrequest(uint8* ipAddr, int port, char* hostName, char* URL);
+
+ /*
+ * Submits the request and prevents further changes to the request until it has been
+ * processed.
+ */
+ void submit();
+
+ /*
+ * Sets the function that should be called with data returned by the server.
+ */
+ void setReturnFunc(returnFunction func);
+
+ /*
+ * Sets the authorization string for the request. Calls to this method will be ignored if the request
+ * has been submitted and is still being processed by WiServer.
+ */
+ void setAuth(char* auth);
+
+ /*
+ * Checks if this request is currently being processed by the WiServer (i.e. it is awaiting a connection
+ * or is currently connected and communicating with the server). If it is, any calls that attempt
+ * to change the properties of the request will be ignored.
+ */
+ boolean isActive();
+
+ /*
+ * Sets the URL for the request. Calls to this method will be ignored if the request
+ * has been submitted and is currently being processed by WiServer.
+ */
+ void setURL(char* URL);
+
+ // Server IP address (network byte order)
+ uip_ipaddr_t ipAddr;
+ // Server port number
+ int port;
+ // Server domain name
+ char* hostName;
+ // Request URL
+ char* URL;
+ // Authorization string (may be NULL)
+ char* auth;
+ // Return value callback function (may be NULL)
+ returnFunction returnFunc;
+ // Indicates if the request is currently active (i.e. has a connection)
+ boolean active;
+ // Body data callback function (may be NULL)
+ bodyFunction body;
+ // Body preamble (may be NULL)
+ char* bodyPreamble;
+ // Pointer to the next request in the queue
+ GETrequest* next;
+ };
+
+
+/*
+ * Class that encapsulates aN HTTP POST request
+ */
+class POSTrequest : public GETrequest
+ {
+ public:
+
+ /*
+ * Creates a new POSTrequest with the provided IP, port, host name, URL and body function.
+ */
+ POSTrequest(uint8* ipAddr, int port, char* hostName, char* URL, bodyFunction body);
+
+ void setBodyFunc(bodyFunction body);
+
+ };
+
+
+/*
+ * Class that encapsulates a TWEET request (basically a POST request populated with Twitter-specific data)
+ */
+class TWEETrequest : public POSTrequest
+ {
+ public:
+
+ /*
+ * Creates a new TWEETrequest with the provided auth string and message function.
+ * The body function will be called to provide the contents of the message; the
+ * 'status=' prefix is automatically inserted before the message.
+ */
+ TWEETrequest(char* auth, bodyFunction message);
+ };
+
+#endif // ENABLE_CLIENT_MODE
+
+
+class Server: public Print
+{
+ public:
+
+ /**
+ * Inits the server with the provided page serving function
+ *
+ * @param pageServerFunc name of the sketch's page serving function
+ */
+ void init(pageServingFunction function);
+
+ /*
+ * Enables or disables verbose mode. If verbose mode is true, then WiServer
+ * will output log info via the Serial class. Verbose mode is disabled by
+ * default, but is automatically enabled if DEBUG is defined
+ */
+ void enableVerboseMode(boolean enable);
+
+ /**
+ * The server task method (must be called in the main loop to run the WiServer)
+ */
+ void server_task();
+
+ /**
+ * Writes a single byte to the current connection buffer
+ */
+ virtual void write(uint8_t);
+
+ /**
+ * Prints a string that is stored in program memory
+ */
+ void print_P(const char[]);
+
+ /**
+ * Prints a string that is stored in program memory followed by a line feed
+ */
+ void println_P(const char[]);
+
+ /**
+ * Writes data of a specified length that is stored in program memory
+ */
+ void write_P(const char[], int len);
+
+ /**
+ * Prints a time value in the form HH:MM:SS. The time value is in milliseconds.
+ *
+ */
+ void printTime(long t);
+
+ /**
+ * Indicates if a page is currently being sent, and that a subsequent call to the page
+ * serving function may occur to request more data or to retransmit data that was lost
+ * in the network. Changes to the content of the page should only be made if this method
+ * returns false.
+ */
+ boolean sendInProgress();
+
+ /**
+ * Checks if the client for the current server request resides on the same local network
+ * as the server. This information can be used to control access to data
+ * and capabilities based on where the client is located. The check is made
+ * by comparing the server and client addresses using the subnet mask.
+ * <br>
+ * For example, a web page front-end for a HVAC system might display read-only data
+ * to all clients, but may restrict changes to the settings to only those clients
+ * connected via the building's local network.
+ * <br>
+ * Note that security checks based on the client IP address are not 100% reliable,
+ * so this feature should not be relied upon to control access to sensitive data!
+ */
+ boolean clientIsLocal();
+
+ /**
+ * Sets the pins used to indicate TX and RX activity over the network.
+ * These pins will be set to a HIGH output when activity occurs, and may
+ * be connected to LEDs via a suitable resistor to provide indicator lights.
+ * A value of -1 disables activity indication.
+ */
+ void setIndicatorPins(int tx, int rx);
+
+#ifdef ENABLE_CLIENT_MODE
+
+ /*
+ * Called by request classes to submit themselves to the queue
+ */
+ void submitRequest(GETrequest *req);
+
+ char* base64encode(char* data);
+
+
+
+#endif // ENABLE_CLIENT_MODE
+
+};
+
+// Single instance of the Server
+extern Server WiServer;
+
+
+
+#endif /* WISERVER_H_ */
diff --git a/Libraries/WiShield/WiShield.cpp b/Libraries/WiShield/WiShield.cpp
new file mode 100644
index 0000000..2e61afa
--- /dev/null
+++ b/Libraries/WiShield/WiShield.cpp
@@ -0,0 +1,87 @@
+
+/******************************************************************************
+
+ Filename: WiShield.cpp
+ Description: WiShield library file for the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/01/2009 Initial version
+ AsyncLabs 05/29/2009 Adding support for new library
+
+ *****************************************************************************/
+
+extern "C" {
+ #include "witypes.h"
+ #include "global-conf.h"
+ #include "network.h"
+ #include "g2100.h"
+ #include "spi.h"
+ void stack_init(void);
+ void stack_process(void);
+}
+
+#include "WProgram.h"
+#include "WiShield.h"
+
+void WiShield::init()
+{
+ zg_init();
+
+#ifdef USE_DIG0_INTR
+ attachInterrupt(0, zg_isr, LOW);
+#endif
+
+#ifdef USE_DIG8_INTR
+ // set digital pin 8 on Arduino
+ // as ZG interrupt pin
+ PCICR |= (1<<PCIE0);
+ PCMSK0 |= (1<<PCINT0);
+#endif
+
+ while(zg_get_conn_state() != 1) {
+ zg_drv_process();
+ }
+
+ stack_init();
+}
+
+void WiShield::run()
+{
+ stack_process();
+ zg_drv_process();
+}
+
+#if defined USE_DIG8_INTR && !defined APP_WISERVER
+// PCINT0 interrupt vector
+ISR(PCINT0_vect)
+{
+ zg_isr();
+}
+
+#endif
+
+WiShield WiFi;
+
diff --git a/Libraries/WiShield/WiShield.h b/Libraries/WiShield/WiShield.h
new file mode 100644
index 0000000..85d6648
--- /dev/null
+++ b/Libraries/WiShield/WiShield.h
@@ -0,0 +1,53 @@
+
+/******************************************************************************
+
+ Filename: WiShield.h
+ Description: WiShield library file for the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/01/2009 Initial version
+ AsyncLabs 05/29/2009 Adding support for new library
+
+ *****************************************************************************/
+
+#ifndef WISHIELD_H_
+#define WISHIELD_H_
+
+extern "C" {
+ #include "config.h"
+ #include "spi.h"
+ extern unsigned char webclient_get(char *host, unsigned int port, char *file);
+}
+
+class WiShield {
+ public:
+ void init();
+ void run();
+};
+
+extern WiShield WiFi;
+
+#endif /* WISHIELD_H_ */
diff --git a/Libraries/WiShield/apps-conf.h b/Libraries/WiShield/apps-conf.h
new file mode 100644
index 0000000..a169197
--- /dev/null
+++ b/Libraries/WiShield/apps-conf.h
@@ -0,0 +1,65 @@
+
+/******************************************************************************
+
+ Filename: apps-conf.h
+ Description: Web application configuration file
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/29/2009 Initial port
+
+ *****************************************************************************/
+
+#ifndef __APPS_CONF_H__
+#define __APPS_CONF_H__
+
+//Here we include the header file for the application(s) we use in our project.
+//#define APP_WEBSERVER
+//#define APP_WEBCLIENT
+//#define APP_SOCKAPP
+#define APP_UDPAPP
+//#define APP_WISERVER
+
+#ifdef APP_WEBSERVER
+#include "webserver.h"
+#endif
+
+#ifdef APP_WEBCLIENT
+#include "webclient.h"
+#endif
+
+#ifdef APP_SOCKAPP
+#include "socketapp.h"
+#endif
+
+#ifdef APP_UDPAPP
+#include "udpapp.h"
+#endif
+
+#ifdef APP_WISERVER
+#include "server.h"
+#endif
+
+#endif /*__APPS_CONF_H__*/
diff --git a/Libraries/WiShield/avrlibdefs.h b/Libraries/WiShield/avrlibdefs.h
new file mode 100644
index 0000000..0762225
--- /dev/null
+++ b/Libraries/WiShield/avrlibdefs.h
@@ -0,0 +1,83 @@
+/*! \file avrlibdefs.h \brief AVRlib global defines and macros. */
+//*****************************************************************************
+//
+// File Name : 'avrlibdefs.h'
+// Title : AVRlib global defines and macros include file
+// Author : Pascal Stang
+// Created : 7/12/2001
+// Revised : 9/30/2002
+// Version : 1.1
+// Target MCU : Atmel AVR series
+// Editor Tabs : 4
+//
+// Description : This include file is designed to contain items useful to all
+// code files and projects, regardless of specific implementation.
+//
+// This code is distributed under the GNU Public License
+// which can be found at http://www.gnu.org/licenses/gpl.txt
+//
+//*****************************************************************************
+
+
+#ifndef AVRLIBDEFS_H
+#define AVRLIBDEFS_H
+
+// Code compatibility to new AVR-libc
+// outb(), inb(), inw(), outw(), BV(), sbi(), cbi(), sei(), cli()
+#ifndef outb
+ #define outb(addr, data) addr = (data)
+#endif
+#ifndef inb
+ #define inb(addr) (addr)
+#endif
+#ifndef outw
+ #define outw(addr, data) addr = (data)
+#endif
+#ifndef inw
+ #define inw(addr) (addr)
+#endif
+#ifndef BV
+ #define BV(bit) (1<<(bit))
+#endif
+#ifndef cbi
+ #define cbi(reg,bit) reg &= ~(BV(bit))
+#endif
+#ifndef sbi
+ #define sbi(reg,bit) reg |= (BV(bit))
+#endif
+#ifndef cli
+ #define cli() __asm__ __volatile__ ("cli" ::)
+#endif
+#ifndef sei
+ #define sei() __asm__ __volatile__ ("sei" ::)
+#endif
+
+// support for individual port pin naming in the mega128
+// see port128.h for details
+#ifdef __AVR_ATmega128__
+// not currently necessary due to inclusion
+// of these defines in newest AVR-GCC
+// do a quick test to see if include is needed
+#ifndef PD0
+ #include "port128.h"
+#endif
+#endif
+
+// use this for packed structures
+// (this is seldom necessary on an 8-bit architecture like AVR,
+// but can assist in code portability to AVR)
+#define GNUC_PACKED __attribute__((packed))
+
+// port address helpers
+#define DDR(x) ((x)-1) // address of data direction register of port x
+#define PIN(x) ((x)-2) // address of input register of port x
+
+// MIN/MAX/ABS macros
+#define MIN(a,b) ((a<b)?(a):(b))
+#define MAX(a,b) ((a>b)?(a):(b))
+#define ABS(x) ((x>0)?(x):(-x))
+
+// constants
+#define PI 3.14159265359
+
+#endif
diff --git a/Libraries/WiShield/avrlibtypes.h b/Libraries/WiShield/avrlibtypes.h
new file mode 100644
index 0000000..6b04bdd
--- /dev/null
+++ b/Libraries/WiShield/avrlibtypes.h
@@ -0,0 +1,84 @@
+/*! \file avrlibtypes.h \brief AVRlib global types and typedefines. */
+//*****************************************************************************
+//
+// File Name : 'avrlibtypes.h'
+// Title : AVRlib global types and typedefines include file
+// Author : Pascal Stang
+// Created : 7/12/2001
+// Revised : 9/30/2002
+// Version : 1.0
+// Target MCU : Atmel AVR series
+// Editor Tabs : 4
+//
+// Description : Type-defines required and used by AVRlib. Most types are also
+// generally useful.
+//
+// This code is distributed under the GNU Public License
+// which can be found at http://www.gnu.org/licenses/gpl.txt
+//
+//*****************************************************************************
+
+
+#ifndef AVRLIBTYPES_H
+#define AVRLIBTYPES_H
+
+#ifndef WIN32
+ // true/false defines
+ #define FALSE 0
+ #define TRUE -1
+#endif
+
+// datatype definitions macros
+typedef unsigned char u08;
+typedef signed char s08;
+typedef unsigned short u16;
+typedef signed short s16;
+typedef unsigned long u32;
+typedef signed long s32;
+typedef unsigned long long u64;
+typedef signed long long s64;
+
+/* use inttypes.h instead
+// C99 standard integer type definitions
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
+typedef unsigned short uint16_t;
+typedef signed short int16_t;
+typedef unsigned long uint32_t;
+typedef signed long int32_t;
+typedef unsigned long uint64_t;
+typedef signed long int64_t;
+*/
+// maximum value that can be held
+// by unsigned data types (8,16,32bits)
+#define MAX_U08 255
+#define MAX_U16 65535
+#define MAX_U32 4294967295
+
+// maximum values that can be held
+// by signed data types (8,16,32bits)
+#define MIN_S08 -128
+#define MAX_S08 127
+#define MIN_S16 -32768
+#define MAX_S16 32767
+#define MIN_S32 -2147483648
+#define MAX_S32 2147483647
+
+#ifndef WIN32
+ // more type redefinitions
+ typedef unsigned char BOOL;
+ typedef unsigned char BYTE;
+ typedef unsigned int WORD;
+ typedef unsigned long DWORD;
+
+ typedef unsigned char UCHAR;
+ typedef unsigned int UINT;
+ typedef unsigned short USHORT;
+ typedef unsigned long ULONG;
+
+ typedef char CHAR;
+ typedef int INT;
+ typedef long LONG;
+#endif
+
+#endif
diff --git a/Libraries/WiShield/clock-arch.c b/Libraries/WiShield/clock-arch.c
new file mode 100644
index 0000000..9dc7e5d
--- /dev/null
+++ b/Libraries/WiShield/clock-arch.c
@@ -0,0 +1,86 @@
+
+/******************************************************************************
+
+ Filename: clock-arch.c
+ Description: Timer routine file
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/29/2009 Initial port
+
+ *****************************************************************************/
+
+#include "global-conf.h"
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <avr/interrupt.h>
+#include <avr/io.h>
+#include <avr/sfr_defs.h>
+
+#include "clock-arch.h"
+#include "wiring.h"
+
+#if 0
+//Counted time
+clock_time_t clock_datetime = 0;
+
+//Overflow interrupt
+ISR(TIMER0_OVF_vect)
+{
+ clock_datetime += 1;
+ TIFR0 |= (1<<TOV0);
+}
+*/
+
+//Initialise the clock
+void clock_init(){
+ //Activate overflow interrupt for timer0
+ TIMSK0 |= (1<<TOIE0);
+
+ //Use prescaler 1024
+ TCCR0B |= ((1<<CS12)|(1<<CS10));
+
+ //Activate interrupts
+ sei();
+}
+
+//Return time
+clock_time_t clock_time(){
+ clock_time_t time;
+
+ cli();
+ time = clock_datetime;
+ sei();
+
+ return time;
+}
+#endif
+
+//Return time
+clock_time_t clock_time()
+{
+ return millis();
+}
diff --git a/Libraries/WiShield/clock-arch.h b/Libraries/WiShield/clock-arch.h
new file mode 100644
index 0000000..4f8cef6
--- /dev/null
+++ b/Libraries/WiShield/clock-arch.h
@@ -0,0 +1,47 @@
+
+/******************************************************************************
+
+ Filename: clock-arch.h
+ Description: Timer routine file
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/29/2009 Initial port
+
+ *****************************************************************************/
+
+#ifndef __CLOCK_ARCH_H__
+#define __CLOCK_ARCH_H__
+
+#include <stdint.h>
+
+typedef uint32_t clock_time_t;
+#define CLOCK_CONF_SECOND (clock_time_t)1000
+ //(F_CPU / (1024*255)), this cannot be used as it gives overflows
+ //Freqency divided prescaler and counter register size
+
+#include "clock.h"
+
+#endif /* __CLOCK_ARCH_H__ */
diff --git a/Libraries/WiShield/clock.h b/Libraries/WiShield/clock.h
new file mode 100644
index 0000000..f34d78f
--- /dev/null
+++ b/Libraries/WiShield/clock.h
@@ -0,0 +1,88 @@
+/**
+ * \defgroup clock Clock interface
+ *
+ * The clock interface is the interface between the \ref timer "timer library"
+ * and the platform specific clock functionality. The clock
+ * interface must be implemented for each platform that uses the \ref
+ * timer "timer library".
+ *
+ * The clock interface does only one this: it measures time. The clock
+ * interface provides a macro, CLOCK_SECOND, which corresponds to one
+ * second of system time.
+ *
+ * \sa \ref timer "Timer library"
+ *
+ * @{
+ */
+
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: clock.h,v 1.3 2006/06/11 21:46:39 adam Exp $
+ */
+#ifndef __CLOCK_H__
+#define __CLOCK_H__
+
+#include "clock-arch.h"
+
+/**
+ * Initialize the clock library.
+ *
+ * This function initializes the clock library and should be called
+ * from the main() function of the system.
+ *
+ */
+void clock_init(void);
+
+/**
+ * Get the current clock time.
+ *
+ * This function returns the current system clock time.
+ *
+ * \return The current clock time, measured in system ticks.
+ */
+clock_time_t clock_time(void);
+
+/**
+ * A second, measured in system clock time.
+ *
+ * \hideinitializer
+ */
+#ifdef CLOCK_CONF_SECOND
+#define CLOCK_SECOND CLOCK_CONF_SECOND
+#else
+#define CLOCK_SECOND (clock_time_t)32
+#endif
+
+#endif /* __CLOCK_H__ */
+
+/** @} */
diff --git a/Libraries/WiShield/config.h b/Libraries/WiShield/config.h
new file mode 100644
index 0000000..2897503
--- /dev/null
+++ b/Libraries/WiShield/config.h
@@ -0,0 +1,60 @@
+
+/******************************************************************************
+
+ Filename: config.h
+ Description: Wireless configuration parameters for the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/01/2009 Initial version
+ AsyncLabs 05/29/2009 Adding support for new library
+
+ *****************************************************************************/
+
+#ifndef CONFIG_H_
+#define CONFIG_H_
+
+#include "witypes.h"
+
+extern U8 local_ip[];
+extern U8 gateway_ip[];
+extern U8 subnet_mask[];
+extern const prog_char ssid[];
+extern U8 ssid_len;
+extern const prog_char security_passphrase[];
+extern U8 security_passphrase_len;
+extern U8 security_type;
+extern U8 wireless_mode;
+
+extern prog_uchar wep_keys[];
+
+extern const prog_char webpage[];
+extern const prog_char twitter[];
+extern unsigned char mfg_id[4];
+
+#define WIRELESS_MODE_INFRA 1
+#define WIRELESS_MODE_ADHOC 2
+
+#endif /* CONFIG_H_ */
diff --git a/Libraries/WiShield/examples/Flash/Flash.pde b/Libraries/WiShield/examples/Flash/Flash.pde
new file mode 100644
index 0000000..1e5ad51
--- /dev/null
+++ b/Libraries/WiShield/examples/Flash/Flash.pde
@@ -0,0 +1,89 @@
+/*
+ * Web Server using Flash
+ *
+ * A simple web server example using the WiShield 2.0
+ * that reads the manufacturing ID from the Flash and
+ * displays it on a webpage.
+ */
+
+#include <WiShield.h>
+#include <dataflash.h>
+
+#define WIRELESS_MODE_INFRA 1
+#define WIRELESS_MODE_ADHOC 2
+
+#define FLASH_SLAVE_SELECT 7
+#define WIFI_SLAVE_SELECT 10
+
+// Wireless configuration parameters ----------------------------------------
+unsigned char local_ip[] = {192,168,1,2}; // IP address of WiShield
+unsigned char gateway_ip[] = {192,168,1,1}; // router or gateway IP address
+unsigned char subnet_mask[] = {255,255,255,0}; // subnet mask for the local network
+const prog_char ssid[] PROGMEM = {"ASYNCLABS"}; // max 32 bytes
+
+unsigned char security_type = 0; // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2
+
+// WPA/WPA2 passphrase
+const prog_char security_passphrase[] PROGMEM = {"12345678"}; // max 64 characters
+
+// WEP 128-bit keys
+// sample HEX keys
+prog_uchar wep_keys[] PROGMEM = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, // Key 0
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 1
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 2
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Key 3
+ };
+
+// setup the wireless mode
+// infrastructure - connect to AP
+// adhoc - connect to another WiFi device
+unsigned char wireless_mode = WIRELESS_MODE_INFRA;
+
+unsigned char ssid_len;
+unsigned char security_passphrase_len;
+//---------------------------------------------------------------------------
+
+unsigned char mfg_id[4];
+
+void setup()
+{
+ initShield();
+}
+
+// This is the webpage that is served up by the webserver
+const prog_char webpage[] PROGMEM = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"
+ "<html><body style=\"margin:100px\">"
+ "<center>"
+ "<h1>Flash Mfg ID: 000 000 000</h1>"
+ "<form method=post action=\"/upload\" enctype=\"multipart/form-data\">"
+ "<b>FS Image Upload</b>"
+ "<p>"
+ "<input type=file name=i size=40> &nbsp; <input type=submit value=\"Upload\">"
+ "</form>"
+ "</center>"
+ "</body></html>";
+
+void loop()
+{
+ dflash.read_id(mfg_id);
+
+ WiFi.run();
+}
+
+void initShield()
+{
+ // there is some contention on the SPI between the flash and wifi chip,
+ // so disable both devices at the beginning until they are properly
+ // initialized by their respective libraries
+ pinMode(FLASH_SLAVE_SELECT, OUTPUT);
+ digitalWrite(FLASH_SLAVE_SELECT, HIGH);
+ pinMode(WIFI_SLAVE_SELECT, OUTPUT);
+ digitalWrite(WIFI_SLAVE_SELECT, HIGH);
+
+ // now init dataflash
+ dflash.init(FLASH_SLAVE_SELECT);
+
+ // now init wifi
+ WiFi.init();
+}
+
diff --git a/Libraries/WiShield/examples/Flash/webserver.c b/Libraries/WiShield/examples/Flash/webserver.c
new file mode 100644
index 0000000..045b843
--- /dev/null
+++ b/Libraries/WiShield/examples/Flash/webserver.c
@@ -0,0 +1,125 @@
+
+/******************************************************************************
+
+ Filename: webserver.h
+ Description: Webserver app for the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/29/2009 Initial version
+
+ *****************************************************************************/
+
+#include "uip.h"
+#include <string.h>
+#include "webserver.h"
+#include "config.h"
+
+static int handle_connection(struct webserver_state *s);
+
+void webserver_init(void)
+{
+ uip_listen(HTONS(80));
+}
+
+void webserver_appcall(void)
+{
+ struct webserver_state *s = &(uip_conn->appstate);
+
+ if(uip_connected()) {
+ PSOCK_INIT(&s->p, s->inputbuf, sizeof(s->inputbuf));
+ }
+
+ handle_connection(s);
+}
+
+#define ISO_nl 0x0a
+#define ISO_space 0x20
+#define ISO_slash 0x2f
+
+const char http_get[5] = {0x47, 0x45, 0x54, 0x20, }; /* "GET " */
+
+unsigned short fill_buf(void* blk)
+{
+ unsigned short webpage_len;
+ char int_string[4];
+
+ webpage_len = (strlen_P(webpage)>uip_mss())?uip_mss():strlen_P(webpage);
+
+ memcpy_P(uip_appdata, webpage, webpage_len);
+
+ sprintf(int_string, "%X", mfg_id[0]);
+ memcpy(&uip_appdata[104], int_string, 2);
+ sprintf(int_string, "%X", mfg_id[1]);
+ memcpy(&uip_appdata[108], int_string, 2);
+
+ return webpage_len;
+}
+
+static int handle_connection(struct webserver_state *s)
+{
+ PSOCK_BEGIN(&s->p);
+
+ // the incoming GET request will have the following format:
+ // GET / HTTP/1.1 ....
+ // we have to parse this string to determine the resource being requested
+ // if the requested resource is not the root webpage ('/') then,
+ // GET /<resource name> HTTP/1.1 ....
+ // we should parse the specific resource and react appropriately
+
+ // read incoming data until we read a space character
+ PSOCK_READTO(&s->p, ISO_space);
+
+ // parse the data to determine if it was a GET request
+ if(strncmp(s->inputbuf, http_get, 4) != 0) {
+ PSOCK_CLOSE_EXIT(&s->p);
+ }
+
+ // continue reading until the next space character
+ PSOCK_READTO(&s->p, ISO_space);
+
+ // determine the requested resource
+ // in this case, we check if the request was for the '/' root page
+ // AKA index.html
+ if(s->inputbuf[0] != ISO_slash) {
+ // request for unknown webpage, close and exit
+ PSOCK_CLOSE_EXIT(&s->p);
+ }
+
+ if(s->inputbuf[1] != ISO_space) {
+ // request for unavailable resource
+ // not supported, modify to add support for additional resources
+ PSOCK_CLOSE_EXIT(&s->p);
+ }
+
+ //PSOCK_SEND_STR(&s->p, "HTTP/1.1 200 OK\r\n");
+ //PSOCK_SEND_STR(&s->p, "Content-Type: text/html\r\n");
+ //PSOCK_SEND_STR(&s->p, "\r\n");
+ //PSOCK_SEND_STR(&s->p, "Hello World, I am WiShield");
+ //PSOCK_SEND_STR(&s->p, "<center><h1>Hello World!! I am WiShield</h1></center>");
+ PSOCK_GENERATOR_SEND(&s->p, fill_buf, 0);
+ PSOCK_CLOSE(&s->p);
+ PSOCK_END(&s->p);
+}
diff --git a/Libraries/WiShield/examples/SimpleClient/SimpleClient.pde b/Libraries/WiShield/examples/SimpleClient/SimpleClient.pde
new file mode 100644
index 0000000..52c9e56
--- /dev/null
+++ b/Libraries/WiShield/examples/SimpleClient/SimpleClient.pde
@@ -0,0 +1,88 @@
+/*
+ * A simple sketch that uses WiServer to get the hourly weather data from LAX and prints
+ * it via the Serial API
+ */
+
+#include <WiServer.h>
+
+#define WIRELESS_MODE_INFRA 1
+#define WIRELESS_MODE_ADHOC 2
+
+// Wireless configuration parameters ----------------------------------------
+unsigned char local_ip[] = {192,168,1,2}; // IP address of WiShield
+unsigned char gateway_ip[] = {192,168,1,1}; // router or gateway IP address
+unsigned char subnet_mask[] = {255,255,255,0}; // subnet mask for the local network
+const prog_char ssid[] PROGMEM = {"ASYNCLABS"}; // max 32 bytes
+
+unsigned char security_type = 0; // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2
+
+// WPA/WPA2 passphrase
+const prog_char security_passphrase[] PROGMEM = {"12345678"}; // max 64 characters
+
+// WEP 128-bit keys
+// sample HEX keys
+prog_uchar wep_keys[] PROGMEM = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, // Key 0
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 1
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 2
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Key 3
+ };
+
+// setup the wireless mode
+// infrastructure - connect to AP
+// adhoc - connect to another WiFi device
+unsigned char wireless_mode = WIRELESS_MODE_INFRA;
+
+unsigned char ssid_len;
+unsigned char security_passphrase_len;
+// End of wireless configuration parameters ----------------------------------------
+
+
+// Function that prints data from the server
+void printData(char* data, int len) {
+
+ // Print the data returned by the server
+ // Note that the data is not null-terminated, may be broken up into smaller packets, and
+ // includes the HTTP header.
+ while (len-- > 0) {
+ Serial.print(*(data++));
+ }
+}
+
+
+// IP Address for www.weather.gov
+uint8 ip[] = {140,90,113,200};
+
+// A request that gets the latest METAR weather data for LAX
+GETrequest getWeather(ip, 80, "www.weather.gov", "/data/METAR/KLAX.1.txt");
+
+
+void setup() {
+ // Initialize WiServer (we'll pass NULL for the page serving function since we don't need to serve web pages)
+ WiServer.init(NULL);
+
+ // Enable Serial output and ask WiServer to generate log messages (optional)
+ Serial.begin(57600);
+ WiServer.enableVerboseMode(true);
+
+ // Have the processData function called when data is returned by the server
+ getWeather.setReturnFunc(printData);
+}
+
+
+// Time (in millis) when the data should be retrieved
+long updateTime = 0;
+
+void loop(){
+
+ // Check if it's time to get an update
+ if (millis() >= updateTime) {
+ getWeather.submit();
+ // Get another update one hour from now
+ updateTime += 1000 * 60 * 60;
+ }
+
+ // Run WiServer
+ WiServer.server_task();
+
+ delay(10);
+}
diff --git a/Libraries/WiShield/examples/SimpleServer/SimpleServer.pde b/Libraries/WiShield/examples/SimpleServer/SimpleServer.pde
new file mode 100644
index 0000000..aeb9288
--- /dev/null
+++ b/Libraries/WiShield/examples/SimpleServer/SimpleServer.pde
@@ -0,0 +1,74 @@
+/*
+ * A simple sketch that uses WiServer to serve a web page
+ */
+
+
+#include <WiServer.h>
+
+#define WIRELESS_MODE_INFRA 1
+#define WIRELESS_MODE_ADHOC 2
+
+// Wireless configuration parameters ----------------------------------------
+unsigned char local_ip[] = {192,168,1,2}; // IP address of WiShield
+unsigned char gateway_ip[] = {192,168,1,1}; // router or gateway IP address
+unsigned char subnet_mask[] = {255,255,255,0}; // subnet mask for the local network
+const prog_char ssid[] PROGMEM = {"ASYNCLABS"}; // max 32 bytes
+
+unsigned char security_type = 0; // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2
+
+// WPA/WPA2 passphrase
+const prog_char security_passphrase[] PROGMEM = {"12345678"}; // max 64 characters
+
+// WEP 128-bit keys
+// sample HEX keys
+prog_uchar wep_keys[] PROGMEM = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, // Key 0
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 1
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 2
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Key 3
+ };
+
+// setup the wireless mode
+// infrastructure - connect to AP
+// adhoc - connect to another WiFi device
+unsigned char wireless_mode = WIRELESS_MODE_INFRA;
+
+unsigned char ssid_len;
+unsigned char security_passphrase_len;
+// End of wireless configuration parameters ----------------------------------------
+
+
+// This is our page serving function that generates web pages
+boolean sendMyPage(char* URL) {
+
+ // Check if the requested URL matches "/"
+ if (strcmp(URL, "/") == 0) {
+ // Use WiServer's print and println functions to write out the page content
+ WiServer.print("<html>");
+ WiServer.print("Hello World!");
+ WiServer.print("</html>");
+
+ // URL was recognized
+ return true;
+ }
+ // URL not found
+ return false;
+}
+
+
+void setup() {
+ // Initialize WiServer and have it use the sendMyPage function to serve pages
+ WiServer.init(sendMyPage);
+
+ // Enable Serial output and ask WiServer to generate log messages (optional)
+ Serial.begin(57600);
+ WiServer.enableVerboseMode(true);
+}
+
+void loop(){
+
+ // Run WiServer
+ WiServer.server_task();
+
+ delay(10);
+}
+
diff --git a/Libraries/WiShield/examples/SimpleTweeter/SimpleTweeter.pde b/Libraries/WiShield/examples/SimpleTweeter/SimpleTweeter.pde
new file mode 100644
index 0000000..d7b6caf
--- /dev/null
+++ b/Libraries/WiShield/examples/SimpleTweeter/SimpleTweeter.pde
@@ -0,0 +1,79 @@
+/*
+ * A simple sketch that uses WiServer to send a tweet with the current system time every 5 minutes
+ */
+
+#include <WiServer.h>
+
+#define WIRELESS_MODE_INFRA 1
+#define WIRELESS_MODE_ADHOC 2
+
+// Wireless configuration parameters ----------------------------------------
+unsigned char local_ip[] = {192,168,1,2}; // IP address of WiShield
+unsigned char gateway_ip[] = {192,168,1,1}; // router or gateway IP address
+unsigned char subnet_mask[] = {255,255,255,0}; // subnet mask for the local network
+const prog_char ssid[] PROGMEM = {"ASYNCLABS"}; // max 32 bytes
+
+unsigned char security_type = 0; // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2
+
+// WPA/WPA2 passphrase
+const prog_char security_passphrase[] PROGMEM = {"12345678"}; // max 64 characters
+
+// WEP 128-bit keys
+// sample HEX keys
+prog_uchar wep_keys[] PROGMEM = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, // Key 0
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 1
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 2
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Key 3
+ };
+
+// setup the wireless mode
+// infrastructure - connect to AP
+// adhoc - connect to another WiFi device
+unsigned char wireless_mode = WIRELESS_MODE_INFRA;
+
+unsigned char ssid_len;
+unsigned char security_passphrase_len;
+// End of wireless configuration parameters ----------------------------------------
+
+
+// Auth string for the Twitter account
+char* auth = "[YOUR DATA HERE]"; // Base64 encoded USERNAME:PASSWORD
+
+
+// This function generates a message with the current system time
+void currentTime() {
+ WiServer.print("Arduino has been running for ");
+ WiServer.printTime(millis());
+}
+
+// A request that sends a Tweet using the currentTime function
+TWEETrequest sentMyTweet(auth, currentTime);
+
+
+void setup() {
+ // Initialize WiServer (we'll pass NULL for the page serving function since we don't need to serve web pages)
+ WiServer.init(NULL);
+
+ // Enable Serial output and ask WiServer to generate log messages (optional)
+ Serial.begin(57600);
+ WiServer.enableVerboseMode(true);
+}
+
+
+// Time (in millis) when the next tweet should be sent
+long tweetTime = 0;
+
+void loop(){
+
+ // Check if it's time to sent a tweet
+ if (millis() >= tweetTime) {
+ sentMyTweet.submit();
+ // Send next tweet 5 minutes from now
+ tweetTime += 1000 * 60 * 5;
+ }
+
+ // Run WiServer
+ WiServer.server_task();
+
+ delay(10);
+}
diff --git a/Libraries/WiShield/examples/SocketApp/SocketApp.pde b/Libraries/WiShield/examples/SocketApp/SocketApp.pde
new file mode 100644
index 0000000..662bc07
--- /dev/null
+++ b/Libraries/WiShield/examples/SocketApp/SocketApp.pde
@@ -0,0 +1,48 @@
+/*
+ * Socket App
+ *
+ * A simple socket application example using the WiShield 1.0
+ */
+
+#include <WiShield.h>
+
+#define WIRELESS_MODE_INFRA 1
+#define WIRELESS_MODE_ADHOC 2
+
+// Wireless configuration parameters ----------------------------------------
+unsigned char local_ip[] = {192,168,1,2}; // IP address of WiShield
+unsigned char gateway_ip[] = {192,168,1,1}; // router or gateway IP address
+unsigned char subnet_mask[] = {255,255,255,0}; // subnet mask for the local network
+const prog_char ssid[] PROGMEM = {"ASYNCLABS"}; // max 32 bytes
+
+unsigned char security_type = 0; // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2
+
+// WPA/WPA2 passphrase
+const prog_char security_passphrase[] PROGMEM = {"12345678"}; // max 64 characters
+
+// WEP 128-bit keys
+// sample HEX keys
+prog_uchar wep_keys[] PROGMEM = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, // Key 0
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 1
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 2
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Key 3
+ };
+
+// setup the wireless mode
+// infrastructure - connect to AP
+// adhoc - connect to another WiFi device
+unsigned char wireless_mode = WIRELESS_MODE_INFRA;
+
+unsigned char ssid_len;
+unsigned char security_passphrase_len;
+//---------------------------------------------------------------------------
+
+void setup()
+{
+ WiFi.init();
+}
+
+void loop()
+{
+ WiFi.run();
+}
diff --git a/Libraries/WiShield/examples/SocketApp/socketapp.c b/Libraries/WiShield/examples/SocketApp/socketapp.c
new file mode 100644
index 0000000..c815560
--- /dev/null
+++ b/Libraries/WiShield/examples/SocketApp/socketapp.c
@@ -0,0 +1,118 @@
+
+/******************************************************************************
+
+ Filename: socketapp.c
+ Description: Simple socket programming example for the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 06/06/2009 Initial version
+
+ *****************************************************************************/
+
+/*
+ * This is a short example of how to write uIP applications using
+ * protosockets.
+ */
+
+/*
+ * We define the application state (struct socket_app_state) in the
+ * socketapp.h file, so we need to include it here. We also include
+ * uip.h (since this cannot be included in socketapp.h) and
+ * <string.h>, since we use the memcpy() function in the code.
+ */
+#include "socketapp.h"
+#include "uip.h"
+#include <string.h>
+
+/*
+ * Declaration of the protosocket function that handles the connection
+ * (defined at the end of the code).
+ */
+static int handle_connection(struct socket_app_state *s);
+/*---------------------------------------------------------------------------*/
+/*
+ * The initialization function. We must explicitly call this function
+ * from the system initialization code, some time after uip_init() is
+ * called.
+ */
+void socket_app_init(void)
+{
+ /* We start to listen for connections on TCP port 1000. */
+ uip_listen(HTONS(1000));
+}
+/*---------------------------------------------------------------------------*/
+/*
+ * In socketapp.h we have defined the UIP_APPCALL macro to
+ * socket_app_appcall so that this function is uIP's application
+ * function. This function is called whenever an uIP event occurs
+ * (e.g. when a new connection is established, new data arrives, sent
+ * data is acknowledged, data needs to be retransmitted, etc.).
+ */
+void socket_app_appcall(void)
+{
+ /*
+ * The uip_conn structure has a field called "appstate" that holds
+ * the application state of the connection. We make a pointer to
+ * this to access it easier.
+ */
+ struct socket_app_state *s = &(uip_conn->appstate);
+
+ /*
+ * If a new connection was just established, we should initialize
+ * the protosocket in our applications' state structure.
+ */
+ if(uip_connected()) {
+ PSOCK_INIT(&s->p, s->inputbuffer, sizeof(s->inputbuffer));
+ }
+
+ /*
+ * Finally, we run the protosocket function that actually handles
+ * the communication. We pass it a pointer to the application state
+ * of the current connection.
+ */
+ handle_connection(s);
+}
+/*---------------------------------------------------------------------------*/
+/*
+ * This is the protosocket function that handles the communication. A
+ * protosocket function must always return an int, but must never
+ * explicitly return - all return statements are hidden in the PSOCK
+ * macros.
+ */
+static int handle_connection(struct socket_app_state *s)
+{
+ PSOCK_BEGIN(&s->p);
+
+ PSOCK_SEND_STR(&s->p, "Hello. What is you name?\n");
+ PSOCK_READTO(&s->p, '\n');
+ PSOCK_SEND_STR(&s->p, "Hello ");
+ PSOCK_SEND_STR(&s->p, s->inputbuffer);
+ memset(s->inputbuffer, 0x00, sizeof(s->inputbuffer));
+ PSOCK_CLOSE(&s->p);
+
+ PSOCK_END(&s->p);
+}
+/*---------------------------------------------------------------------------*/
diff --git a/Libraries/WiShield/examples/UDPApp/UDPApp.pde b/Libraries/WiShield/examples/UDPApp/UDPApp.pde
new file mode 100644
index 0000000..92a0cf1
--- /dev/null
+++ b/Libraries/WiShield/examples/UDPApp/UDPApp.pde
@@ -0,0 +1,48 @@
+/*
+ * UDP endpoint
+ *
+ * A simple UDP endpoint example using the WiShield 1.0
+ */
+
+#include <WiShield.h>
+
+#define WIRELESS_MODE_INFRA 1
+#define WIRELESS_MODE_ADHOC 2
+
+// Wireless configuration parameters ----------------------------------------
+unsigned char local_ip[] = {192,168,1,2}; // IP address of WiShield
+unsigned char gateway_ip[] = {192,168,1,1}; // router or gateway IP address
+unsigned char subnet_mask[] = {255,255,255,0}; // subnet mask for the local network
+const prog_char ssid[] PROGMEM = {"ASYNCLABS"}; // max 32 bytes
+
+unsigned char security_type = 0; // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2
+
+// WPA/WPA2 passphrase
+const prog_char security_passphrase[] PROGMEM = {"12345678"}; // max 64 characters
+
+// WEP 128-bit keys
+// sample HEX keys
+prog_uchar wep_keys[] PROGMEM = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, // Key 0
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 1
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 2
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Key 3
+ };
+
+// setup the wireless mode
+// infrastructure - connect to AP
+// adhoc - connect to another WiFi device
+unsigned char wireless_mode = WIRELESS_MODE_INFRA;
+
+unsigned char ssid_len;
+unsigned char security_passphrase_len;
+//---------------------------------------------------------------------------
+
+void setup()
+{
+ WiFi.init();
+}
+
+void loop()
+{
+ WiFi.run();
+}
diff --git a/Libraries/WiShield/examples/UDPApp/udpapp.c b/Libraries/WiShield/examples/UDPApp/udpapp.c
new file mode 100644
index 0000000..cdf2d28
--- /dev/null
+++ b/Libraries/WiShield/examples/UDPApp/udpapp.c
@@ -0,0 +1,137 @@
+
+/******************************************************************************
+
+ Filename: udpapp.h
+ Description: UDP app for the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 07/11/2009 Initial version
+
+ *****************************************************************************/
+
+#include "uip.h"
+#include <string.h>
+#include "udpapp.h"
+#include "config.h"
+
+#define STATE_INIT 0
+#define STATE_LISTENING 1
+#define STATE_HELLO_RECEIVED 2
+#define STATE_NAME_RECEIVED 3
+
+static struct udpapp_state s;
+
+void dummy_app_appcall(void)
+{
+}
+
+void udpapp_init(void)
+{
+ uip_ipaddr_t addr;
+ struct uip_udp_conn *c;
+
+ uip_ipaddr(&addr, 192,168,1,23);
+ c = uip_udp_new(&addr, HTONS(0));
+ if(c != NULL) {
+ uip_udp_bind(c, HTONS(12344));
+ }
+
+ s.state = STATE_INIT;
+
+ PT_INIT(&s.pt);
+}
+
+static unsigned char parse_msg(void)
+{
+ if (memcmp(uip_appdata, "Hello", 5) == 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static void send_request(void)
+{
+ char str[] = "Hello. What is your name?\n";
+
+ memcpy(uip_appdata, str, strlen(str));
+ uip_send(uip_appdata, strlen(str));
+}
+
+static void send_response(void)
+{
+ char i = 0;
+ char str[] = "Hello ";
+
+ while ( ( ((char*)uip_appdata)[i] != '\n') && i < 9) {
+ s.inputbuf[i] = ((char*)uip_appdata)[i];
+ i++;
+ }
+ s.inputbuf[i] = '\n';
+
+ memcpy(uip_appdata, str, 6);
+ memcpy(uip_appdata+6, s.inputbuf, i+1);
+ uip_send(uip_appdata, i+7);
+}
+
+static PT_THREAD(handle_connection(void))
+{
+ PT_BEGIN(&s.pt);
+
+ s.state = STATE_LISTENING;
+
+ do {
+ PT_WAIT_UNTIL(&s.pt, uip_newdata());
+
+ if(uip_newdata() && parse_msg()) {
+ s.state = STATE_HELLO_RECEIVED;
+ uip_flags &= (~UIP_NEWDATA);
+ break;
+ }
+ } while(s.state != STATE_HELLO_RECEIVED);
+
+ do {
+ send_request();
+ PT_WAIT_UNTIL(&s.pt, uip_newdata());
+
+ if(uip_newdata()) {
+ s.state = STATE_NAME_RECEIVED;
+ uip_flags &= (~UIP_NEWDATA);
+ break;
+ }
+ } while(s.state != STATE_NAME_RECEIVED);
+
+ send_response();
+
+ s.state = STATE_INIT;
+
+ PT_END(&s.pt);
+}
+
+void udpapp_appcall(void)
+{
+ handle_connection();
+}
diff --git a/Libraries/WiShield/examples/UDPApp/udpapp.c~ b/Libraries/WiShield/examples/UDPApp/udpapp.c~
new file mode 100644
index 0000000..f019164
--- /dev/null
+++ b/Libraries/WiShield/examples/UDPApp/udpapp.c~
@@ -0,0 +1,137 @@
+
+/******************************************************************************
+
+ Filename: udpapp.h
+ Description: UDP app for the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 07/11/2009 Initial version
+
+ *****************************************************************************/
+
+#include "uip.h"
+#include <string.h>
+#include "udpapp.h"
+#include "config.h"
+
+#define STATE_INIT 0
+#define STATE_LISTENING 1
+#define STATE_HELLO_RECEIVED 2
+#define STATE_NAME_RECEIVED 3
+
+static struct udpapp_state s;
+
+void dummy_app_appcall(void)
+{
+}
+
+void udpapp_init(void)
+{
+ uip_ipaddr_t addr;
+ struct uip_udp_conn *c;
+
+ uip_ipaddr(&addr, 192,168,1,100);
+ c = uip_udp_new(&addr, HTONS(0));
+ if(c != NULL) {
+ uip_udp_bind(c, HTONS(12344));
+ }
+
+ s.state = STATE_INIT;
+
+ PT_INIT(&s.pt);
+}
+
+static unsigned char parse_msg(void)
+{
+ if (memcmp(uip_appdata, "Hello", 5) == 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static void send_request(void)
+{
+ char str[] = "Hello. What is your name?\n";
+
+ memcpy(uip_appdata, str, strlen(str));
+ uip_send(uip_appdata, strlen(str));
+}
+
+static void send_response(void)
+{
+ char i = 0;
+ char str[] = "Hello ";
+
+ while ( ( ((char*)uip_appdata)[i] != '\n') && i < 9) {
+ s.inputbuf[i] = ((char*)uip_appdata)[i];
+ i++;
+ }
+ s.inputbuf[i] = '\n';
+
+ memcpy(uip_appdata, str, 6);
+ memcpy(uip_appdata+6, s.inputbuf, i+1);
+ uip_send(uip_appdata, i+7);
+}
+
+static PT_THREAD(handle_connection(void))
+{
+ PT_BEGIN(&s.pt);
+
+ s.state = STATE_LISTENING;
+
+ do {
+ PT_WAIT_UNTIL(&s.pt, uip_newdata());
+
+ if(uip_newdata() && parse_msg()) {
+ s.state = STATE_HELLO_RECEIVED;
+ uip_flags &= (~UIP_NEWDATA);
+ break;
+ }
+ } while(s.state != STATE_HELLO_RECEIVED);
+
+ do {
+ send_request();
+ PT_WAIT_UNTIL(&s.pt, uip_newdata());
+
+ if(uip_newdata()) {
+ s.state = STATE_NAME_RECEIVED;
+ uip_flags &= (~UIP_NEWDATA);
+ break;
+ }
+ } while(s.state != STATE_NAME_RECEIVED);
+
+ send_response();
+
+ s.state = STATE_INIT;
+
+ PT_END(&s.pt);
+}
+
+void udpapp_appcall(void)
+{
+ handle_connection();
+}
diff --git a/Libraries/WiShield/examples/WebClient/WebClient.pde b/Libraries/WiShield/examples/WebClient/WebClient.pde
new file mode 100644
index 0000000..53e243c
--- /dev/null
+++ b/Libraries/WiShield/examples/WebClient/WebClient.pde
@@ -0,0 +1,74 @@
+/*
+ * Web Client
+ *
+ * A simple web client example using the WiShield 1.0
+ */
+
+#include <WiShield.h>
+
+#define WIRELESS_MODE_INFRA 1
+#define WIRELESS_MODE_ADHOC 2
+
+// Wireless configuration parameters ----------------------------------------
+unsigned char local_ip[] = {192,168,1,2}; // IP address of WiShield
+unsigned char gateway_ip[] = {192,168,1,1}; // router or gateway IP address
+unsigned char subnet_mask[] = {255,255,255,0}; // subnet mask for the local network
+const prog_char ssid[] PROGMEM = {"ASYNCLABS"}; // max 32 bytes
+
+unsigned char security_type = 0; // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2
+
+// WPA/WPA2 passphrase
+const prog_char security_passphrase[] PROGMEM = {"12345678"}; // max 64 characters
+
+// WEP 128-bit keys
+// sample HEX keys
+prog_uchar wep_keys[] PROGMEM = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, // Key 0
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 1
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 2
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Key 3
+ };
+
+// setup the wireless mode
+// infrastructure - connect to AP
+// adhoc - connect to another WiFi device
+unsigned char wireless_mode = WIRELESS_MODE_INFRA;
+
+unsigned char ssid_len;
+unsigned char security_passphrase_len;
+//---------------------------------------------------------------------------
+
+void setup()
+{
+ WiFi.init();
+}
+
+unsigned char loop_cnt = 0;
+
+// The stack does not have support for DNS and therefore cannot resolve
+// host names. It needs actual IP addresses of the servers. This info
+// can be obtained by executing, for example, $ ping twitter.com on
+// a terminal on your PC
+//char google_ip[] = {74,125,67,100}; // Google
+char twitter_ip[] = {128,121,146,100}; // Twitter
+
+// This string can be used to send a request to Twitter.com to update your status
+// It will need a valid Authorization string which can be derived from your
+// Twitter.com username and password using Base64 algorithm
+// See, http://en.wikipedia.org/wiki/Basic_access_authentication
+// You need to replace <-!!-Authorization String-!!-> with a valid string before
+// using this sample sketch.
+// The Content-Length variable should equal the length of the data string
+// In the example below, "Content-Length: 21" corresponds to "status=Ready to sleep"
+const prog_char twitter[] PROGMEM = {"POST /statuses/update.xml HTTP/1.1\r\nAuthorization: Basic <-!!-Authorization String-!!->\r\nUser-Agent: uIP/1.0\r\nHost: twitter.com\r\nContent-Length: 21\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\nstatus=Ready to sleep"};
+
+void loop()
+{
+ // if this is the first iteration
+ // send the request
+ if (loop_cnt == 0) {
+ webclient_get(twitter_ip, 80, "/");
+ loop_cnt = 1;
+ }
+
+ WiFi.run();
+}
diff --git a/Libraries/WiShield/examples/WebClient/webclient.c b/Libraries/WiShield/examples/WebClient/webclient.c
new file mode 100644
index 0000000..19fae3a
--- /dev/null
+++ b/Libraries/WiShield/examples/WebClient/webclient.c
@@ -0,0 +1,372 @@
+
+/******************************************************************************
+
+ Filename: webclient.c
+ Description: Webclient app for the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/29/2009 Initial version
+
+ *****************************************************************************/
+
+#include "uip.h"
+#include "uiplib.h"
+#include "webclient.h"
+#include "config.h"
+
+#include <string.h>
+
+#define WEBCLIENT_TIMEOUT 100
+
+#define WEBCLIENT_STATE_STATUSLINE 0
+#define WEBCLIENT_STATE_HEADERS 1
+#define WEBCLIENT_STATE_DATA 2
+#define WEBCLIENT_STATE_CLOSE 3
+
+#define HTTPFLAG_NONE 0
+#define HTTPFLAG_OK 1
+#define HTTPFLAG_MOVED 2
+#define HTTPFLAG_ERROR 3
+
+
+#define ISO_nl 0x0a
+#define ISO_cr 0x0d
+
+static struct webclient_state s;
+
+const char http_11[9] =
+ /* "HTTP/1.1" */
+{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0 };
+const char http_200[5] =
+ /* "200 " */
+{0x32, 0x30, 0x30, 0x20, 0 };
+const char http_301[5] =
+ /* "301 " */
+{0x33, 0x30, 0x31, 0x20, 0 };
+const char http_302[5] =
+ /* "302 " */
+{0x33, 0x30, 0x32, 0x20, 0 };
+
+/*-----------------------------------------------------------------------------------*/
+char* webclient_mimetype(void)
+{
+ return s.mimetype;
+}
+/*-----------------------------------------------------------------------------------*/
+char* webclient_filename(void)
+{
+ return s.file;
+}
+/*-----------------------------------------------------------------------------------*/
+char* webclient_hostname(void)
+{
+ return s.host;
+}
+/*-----------------------------------------------------------------------------------*/
+unsigned short webclient_port(void)
+{
+ return s.port;
+}
+/*-----------------------------------------------------------------------------------*/
+void webclient_init(void)
+{
+
+}
+/*-----------------------------------------------------------------------------------*/
+static void init_connection(void)
+{
+ s.state = WEBCLIENT_STATE_STATUSLINE;
+
+ // set the length of the client string to be transmitted
+ s.getrequestleft = strlen_P(twitter);
+
+ s.getrequestptr = 0;
+
+ s.httpheaderlineptr = 0;
+}
+/*-----------------------------------------------------------------------------------*/
+void webclient_close(void)
+{
+ s.state = WEBCLIENT_STATE_CLOSE;
+}
+/*-----------------------------------------------------------------------------------*/
+unsigned char webclient_get(char *host, u16_t port, char *file)
+{
+ struct uip_conn *conn;
+ uip_ipaddr_t ipaddr;
+
+ uip_ipaddr(&ipaddr, host[0],host[1],host[2],host[3]);
+
+ conn = uip_connect(&ipaddr, htons(port));
+
+ if(conn == NULL) {
+ return 0;
+ }
+
+ s.port = port;
+ strncpy(s.file, file, sizeof(s.file));
+ strncpy(s.host, host, sizeof(s.host));
+
+ init_connection();
+ return 1;
+}
+/*-----------------------------------------------------------------------------------*/
+static unsigned char* copy_string(unsigned char *dest, const unsigned char *src, unsigned char len)
+{
+ strncpy(dest, src, len);
+ return dest + len;
+}
+/*-----------------------------------------------------------------------------------*/
+static void senddata(void)
+{
+ u16_t len;
+ char *getrequest;
+ char *cptr;
+
+ if(s.getrequestleft > 0) {
+ cptr = getrequest = (char *)uip_appdata;
+
+#if 0
+ cptr = copy_string(cptr, http_get, sizeof(http_get) - 1);
+ cptr = copy_string(cptr, s.file, strlen(s.file));
+ *cptr++ = ISO_space;
+ cptr = copy_string(cptr, http_10, sizeof(http_10) - 1);
+
+ cptr = copy_string(cptr, http_crnl, sizeof(http_crnl) - 1);
+
+ cptr = copy_string(cptr, http_host, sizeof(http_host) - 1);
+ cptr = copy_string(cptr, s.host, strlen(s.host));
+ cptr = copy_string(cptr, http_crnl, sizeof(http_crnl) - 1);
+
+ cptr = copy_string(cptr, http_user_agent_fields,
+ strlen(http_user_agent_fields));
+#endif
+
+ // copy the client transmit string into the TX buffer
+ memcpy_P(cptr, twitter, strlen_P(twitter));
+
+ len = s.getrequestleft > uip_mss()?uip_mss():s.getrequestleft;
+ uip_send(&(getrequest[s.getrequestptr]), len);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+static void acked(void)
+{
+ u16_t len;
+
+ if(s.getrequestleft > 0) {
+ len = s.getrequestleft > uip_mss()?uip_mss():s.getrequestleft;
+ s.getrequestleft -= len;
+ s.getrequestptr += len;
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+static u16_t parse_statusline(u16_t len)
+{
+ char *cptr;
+ char* temp;
+
+ while(len > 0 && s.httpheaderlineptr < sizeof(s.httpheaderline)) {
+ s.httpheaderline[s.httpheaderlineptr] = *(char *)uip_appdata;
+ //((char *)uip_appdata)++;
+ temp = (char *)uip_appdata;
+ temp++;
+ uip_appdata = temp;
+ --len;
+ if(s.httpheaderline[s.httpheaderlineptr] == ISO_nl) {
+
+ if((strncmp(s.httpheaderline, http_11,sizeof(http_11) - 1) == 0)) {
+ cptr = &(s.httpheaderline[9]);
+ s.httpflag = HTTPFLAG_NONE;
+ if(strncmp(cptr, http_200, sizeof(http_200) - 1) == 0) {
+ /* 200 OK */
+ s.httpflag = HTTPFLAG_OK;
+ }
+ else if(strncmp(cptr, http_301, sizeof(http_301) - 1) == 0 ||
+ strncmp(cptr, http_302, sizeof(http_302) - 1) == 0) {
+ /* 301 Moved permanently or 302 Found. Location: header line
+ * will contain the new location. */
+ s.httpflag = HTTPFLAG_MOVED;
+ }
+ else {
+ s.httpheaderline[s.httpheaderlineptr - 1] = 0;
+ }
+ }
+ else {
+ uip_abort();
+ webclient_aborted();
+ return 0;
+ }
+
+ /* We're done parsing the status line, so we reset the pointer
+ * and start parsing the HTTP headers.*/
+ s.httpheaderlineptr = 0;
+ s.state = WEBCLIENT_STATE_HEADERS;
+ break;
+ }
+ else {
+ ++s.httpheaderlineptr;
+ }
+ }
+ return len;
+}
+/*-----------------------------------------------------------------------------------*/
+static u16_t parse_headers(u16_t len)
+{
+ char *cptr;
+ static unsigned char i;
+ char* temp;
+
+ while(len > 0 && s.httpheaderlineptr < sizeof(s.httpheaderline)) {
+ s.httpheaderline[s.httpheaderlineptr] = *(char *)uip_appdata;
+ //++((char *)uip_appdata);
+ temp = (char *)uip_appdata;
+ temp++;
+ uip_appdata = temp;
+ --len;
+ if(s.httpheaderline[s.httpheaderlineptr] == ISO_nl) {
+ /* We have an entire HTTP header line in s.httpheaderline, so
+ * we parse it. */
+ if(s.httpheaderline[0] == ISO_cr) {
+ /* This was the last header line (i.e., and empty "\r\n"), so
+ * we are done with the headers and proceed with the actual
+ * data. */
+ s.state = WEBCLIENT_STATE_DATA;
+ return len;
+ }
+
+ /* We're done parsing, so we reset the pointer and start the
+ * next line. */
+ s.httpheaderlineptr = 0;
+ }
+ else {
+ ++s.httpheaderlineptr;
+ }
+ }
+
+ return len;
+}
+/*-----------------------------------------------------------------------------------*/
+static void newdata(void)
+{
+ u16_t len;
+
+ len = uip_datalen();
+
+ if(s.state == WEBCLIENT_STATE_STATUSLINE) {
+ len = parse_statusline(len);
+ }
+
+ if(s.state == WEBCLIENT_STATE_HEADERS && len > 0) {
+ len = parse_headers(len);
+ }
+
+ if(len > 0 && s.state == WEBCLIENT_STATE_DATA &&
+ s.httpflag != HTTPFLAG_MOVED) {
+ webclient_datahandler((char *)uip_appdata, len);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+void webclient_appcall(void)
+{
+ if(uip_connected()) {
+ s.timer = 0;
+ s.state = WEBCLIENT_STATE_STATUSLINE;
+ senddata();
+ webclient_connected();
+ return;
+ }
+
+ if(s.state == WEBCLIENT_STATE_CLOSE) {
+ webclient_closed();
+ uip_abort();
+ return;
+ }
+
+ if(uip_aborted()) {
+ webclient_aborted();
+ }
+
+ if(uip_timedout()) {
+ webclient_timedout();
+ }
+
+ if(uip_acked()) {
+ s.timer = 0;
+ acked();
+ }
+
+ if(uip_newdata()) {
+ s.timer = 0;
+ newdata();
+ }
+
+ if(uip_rexmit() || uip_newdata() || uip_acked()) {
+ senddata();
+ }
+ else if(uip_poll()) {
+ ++s.timer;
+ if(s.timer == WEBCLIENT_TIMEOUT) {
+ webclient_timedout();
+ uip_abort();
+ return;
+ }
+ }
+
+ if(uip_closed()) {
+ if(s.httpflag != HTTPFLAG_MOVED) {
+ /* Send NULL data to signal EOF. */
+ webclient_datahandler(NULL, 0);
+ }
+ else {
+ //webclient_get(s.host, s.port, s.file);
+ }
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+
+void webclient_datahandler(char *data, u16_t len)
+{
+}
+
+void webclient_connected(void)
+{
+}
+
+void webclient_timedout(void)
+{
+}
+
+void webclient_aborted(void)
+{
+}
+
+void webclient_closed(void)
+{
+}
+
+/** @} */
+/** @} */
diff --git a/Libraries/WiShield/examples/WebServer/WebServer.pde b/Libraries/WiShield/examples/WebServer/WebServer.pde
new file mode 100644
index 0000000..d0d23b9
--- /dev/null
+++ b/Libraries/WiShield/examples/WebServer/WebServer.pde
@@ -0,0 +1,51 @@
+/*
+ * Web Server
+ *
+ * A simple web server example using the WiShield 1.0
+ */
+
+#include <WiShield.h>
+
+#define WIRELESS_MODE_INFRA 1
+#define WIRELESS_MODE_ADHOC 2
+
+// Wireless configuration parameters ----------------------------------------
+unsigned char local_ip[] = {192,168,1,2}; // IP address of WiShield
+unsigned char gateway_ip[] = {192,168,1,1}; // router or gateway IP address
+unsigned char subnet_mask[] = {255,255,255,0}; // subnet mask for the local network
+const prog_char ssid[] PROGMEM = {"ASYNCLABS"}; // max 32 bytes
+
+unsigned char security_type = 0; // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2
+
+// WPA/WPA2 passphrase
+const prog_char security_passphrase[] PROGMEM = {"12345678"}; // max 64 characters
+
+// WEP 128-bit keys
+// sample HEX keys
+prog_uchar wep_keys[] PROGMEM = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, // Key 0
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 1
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 2
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Key 3
+ };
+
+// setup the wireless mode
+// infrastructure - connect to AP
+// adhoc - connect to another WiFi device
+unsigned char wireless_mode = WIRELESS_MODE_INFRA;
+
+unsigned char ssid_len;
+unsigned char security_passphrase_len;
+//---------------------------------------------------------------------------
+
+void setup()
+{
+ WiFi.init();
+}
+
+// This is the webpage that is served up by the webserver
+const prog_char webpage[] PROGMEM = {"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<center><h1>Hello World!! I am WiShield</h1><form method=\"get\" action=\"0\">Toggle LED:<input type=\"submit\" name=\"0\" value=\"LED1\"></input></form></center>"};
+
+void loop()
+{
+ WiFi.run();
+}
diff --git a/Libraries/WiShield/examples/WebServer/webserver.c b/Libraries/WiShield/examples/WebServer/webserver.c
new file mode 100644
index 0000000..68c293e
--- /dev/null
+++ b/Libraries/WiShield/examples/WebServer/webserver.c
@@ -0,0 +1,118 @@
+
+/******************************************************************************
+
+ Filename: webserver.h
+ Description: Webserver app for the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/29/2009 Initial version
+
+ *****************************************************************************/
+
+#include "uip.h"
+#include <string.h>
+#include "webserver.h"
+#include "config.h"
+
+static int handle_connection(struct webserver_state *s);
+
+void webserver_init(void)
+{
+ uip_listen(HTONS(80));
+}
+
+void webserver_appcall(void)
+{
+ struct webserver_state *s = &(uip_conn->appstate);
+
+ if(uip_connected()) {
+ PSOCK_INIT(&s->p, s->inputbuf, sizeof(s->inputbuf));
+ }
+
+ handle_connection(s);
+}
+
+#define ISO_nl 0x0a
+#define ISO_space 0x20
+#define ISO_slash 0x2f
+
+const char http_get[5] = {0x47, 0x45, 0x54, 0x20, }; /* "GET " */
+
+unsigned short fill_buf(void* blk)
+{
+ unsigned short webpage_len;
+
+ webpage_len = (strlen_P(webpage)>uip_mss())?uip_mss():strlen_P(webpage);
+
+ memcpy_P(uip_appdata, webpage, webpage_len);
+ return webpage_len;
+}
+
+static int handle_connection(struct webserver_state *s)
+{
+ PSOCK_BEGIN(&s->p);
+
+ // the incoming GET request will have the following format:
+ // GET / HTTP/1.1 ....
+ // we have to parse this string to determine the resource being requested
+ // if the requested resource is not the root webpage ('/') then,
+ // GET /<resource name> HTTP/1.1 ....
+ // we should parse the specific resource and react appropriately
+
+ // read incoming data until we read a space character
+ PSOCK_READTO(&s->p, ISO_space);
+
+ // parse the data to determine if it was a GET request
+ if(strncmp(s->inputbuf, http_get, 4) != 0) {
+ PSOCK_CLOSE_EXIT(&s->p);
+ }
+
+ // continue reading until the next space character
+ PSOCK_READTO(&s->p, ISO_space);
+
+ // determine the requested resource
+ // in this case, we check if the request was for the '/' root page
+ // AKA index.html
+ if(s->inputbuf[0] != ISO_slash) {
+ // request for unknown webpage, close and exit
+ PSOCK_CLOSE_EXIT(&s->p);
+ }
+
+ if(s->inputbuf[1] != ISO_space) {
+ // request for unavailable resource
+ // not supported, modify to add support for additional resources
+ PSOCK_CLOSE_EXIT(&s->p);
+ }
+
+ //PSOCK_SEND_STR(&s->p, "HTTP/1.1 200 OK\r\n");
+ //PSOCK_SEND_STR(&s->p, "Content-Type: text/html\r\n");
+ //PSOCK_SEND_STR(&s->p, "\r\n");
+ //PSOCK_SEND_STR(&s->p, "Hello World, I am WiShield");
+ //PSOCK_SEND_STR(&s->p, "<center><h1>Hello World!! I am WiShield</h1></center>");
+ PSOCK_GENERATOR_SEND(&s->p, fill_buf, 0);
+ PSOCK_CLOSE(&s->p);
+ PSOCK_END(&s->p);
+}
diff --git a/Libraries/WiShield/g2100.c b/Libraries/WiShield/g2100.c
new file mode 100644
index 0000000..a721d87
--- /dev/null
+++ b/Libraries/WiShield/g2100.c
@@ -0,0 +1,595 @@
+
+/*****************************************************************************
+
+ Filename: g2100.c
+ Description: Driver for the ZeroG Wireless G2100 series devices
+
+ *****************************************************************************
+
+ Driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ----------------------------------------------------------------------------
+ AsyncLabs 02/25/2009 Initial port
+ AsyncLabs 05/29/2009 Adding support for new library
+
+ *****************************************************************************/
+
+#include <string.h>
+#include "witypes.h"
+#include "config.h"
+#include "g2100.h"
+#include "spi.h"
+#include "global-conf.h"
+
+static U8 mac[6];
+static U8 zg_conn_status;
+
+static U8 hdr[5];
+static U8 intr_occured;
+static U8 intr_valid;
+static U8 zg_drv_state;
+static U8 tx_ready;
+static U8 rx_ready;
+static U8 cnf_pending;
+static U8* zg_buf;
+static U16 zg_buf_len;
+
+static U8 wpa_psk_key[32];
+
+void zg_init()
+{
+ U8 clr;
+
+ ZG2100_SpiInit();
+ clr = SPSR;
+ clr = SPDR;
+
+ intr_occured = 0;
+ intr_valid = 0;
+ zg_drv_state = DRV_STATE_INIT;
+ zg_conn_status = 0;
+ tx_ready = 0;
+ rx_ready = 0;
+ cnf_pending = 0;
+ zg_buf = uip_buf;
+ zg_buf_len = UIP_BUFSIZE;
+
+ zg_chip_reset();
+ zg_interrupt2_reg();
+ zg_interrupt_reg(0xff, 0);
+ zg_interrupt_reg(0x80|0x40, 1);
+
+ ssid_len = (U8)strlen_P(ssid);
+ security_passphrase_len = (U8)strlen_P(security_passphrase);
+}
+
+void spi_transfer(volatile U8* buf, U16 len, U8 toggle_cs)
+{
+ U16 i;
+
+ ZG2100_CSoff();
+
+ for (i = 0; i < len; i++) {
+ ZG2100_SpiSendData(buf[i]); // Start the transmission
+ buf[i] = ZG2100_SpiRecvData();
+ }
+
+ if (toggle_cs)
+ ZG2100_CSon();
+
+ return;
+}
+
+void zg_chip_reset()
+{
+ U8 loop_cnt = 0;
+
+ do {
+ // write reset register addr
+ hdr[0] = ZG_INDEX_ADDR_REG;
+ hdr[1] = 0x00;
+ hdr[2] = ZG_RESET_REG;
+ spi_transfer(hdr, 3, 1);
+
+ hdr[0] = ZG_INDEX_DATA_REG;
+ hdr[1] = (loop_cnt == 0)?(0x80):(0x0f);
+ hdr[2] = 0xff;
+ spi_transfer(hdr, 3, 1);
+ } while(loop_cnt++ < 1);
+
+ // write reset register data
+ hdr[0] = ZG_INDEX_ADDR_REG;
+ hdr[1] = 0x00;
+ hdr[2] = ZG_RESET_STATUS_REG;
+ spi_transfer(hdr, 3, 1);
+
+ do {
+ hdr[0] = 0x40 | ZG_INDEX_DATA_REG;
+ hdr[1] = 0x00;
+ hdr[2] = 0x00;
+ spi_transfer(hdr, 3, 1);
+ } while((hdr[1] & ZG_RESET_MASK) == 0);
+
+ do {
+ hdr[0] = 0x40 | ZG_BYTE_COUNT_REG;
+ hdr[1] = 0x00;
+ hdr[2] = 0x00;
+ spi_transfer(hdr, 3, 1);
+ } while((hdr[1] == 0) && (hdr[2] == 0));
+}
+
+void zg_interrupt2_reg()
+{
+ // read the interrupt2 mask register
+ hdr[0] = 0x40 | ZG_INTR2_MASK_REG;
+ hdr[1] = 0x00;
+ hdr[2] = 0x00;
+ spi_transfer(hdr, 3, 1);
+
+ // modify the interrupt mask value and re-write the value to the interrupt
+ // mask register clearing the interrupt register first
+ hdr[0] = ZG_INTR2_REG;
+ hdr[1] = 0xff;
+ hdr[2] = 0xff;
+ hdr[3] = 0;
+ hdr[4] = 0;
+ spi_transfer(hdr, 5, 1);
+
+ return;
+}
+
+void zg_interrupt_reg(U8 mask, U8 state)
+{
+ // read the interrupt register
+ hdr[0] = 0x40 | ZG_INTR_MASK_REG;
+ hdr[1] = 0x00;
+ spi_transfer(hdr, 2, 1);
+
+ // now regBuf[0] contains the current setting for the
+ // interrupt mask register
+ // this is to clear any currently set interrupts of interest
+ hdr[0] = ZG_INTR_REG;
+ hdr[2] = (hdr[1] & ~mask) | ( (state == 0)? 0 : mask );
+ hdr[1] = mask;
+ spi_transfer(hdr, 3, 1);
+
+ return;
+}
+
+void zg_isr()
+{
+ ZG2100_ISR_DISABLE();
+ intr_occured = 1;
+}
+
+void zg_process_isr()
+{
+ U8 intr_state = 0;
+ U8 next_cmd = 0;
+
+ hdr[0] = 0x40 | ZG_INTR_REG;
+ hdr[1] = 0x00;
+ hdr[2] = 0x00;
+ spi_transfer(hdr, 3, 1);
+
+ intr_state = ZG_INTR_ST_RD_INTR_REG;
+
+ do {
+ switch(intr_state) {
+ case ZG_INTR_ST_RD_INTR_REG:
+ {
+ U8 intr_val = hdr[1] & hdr[2];
+
+ if ( (intr_val & ZG_INTR_MASK_FIFO1) == ZG_INTR_MASK_FIFO1) {
+ hdr[0] = ZG_INTR_REG;
+ hdr[1] = ZG_INTR_MASK_FIFO1;
+ spi_transfer(hdr, 2, 1);
+
+ intr_state = ZG_INTR_ST_WT_INTR_REG;
+ next_cmd = ZG_BYTE_COUNT_FIFO1_REG;
+ }
+ else if ( (intr_val & ZG_INTR_MASK_FIFO0) == ZG_INTR_MASK_FIFO0) {
+ hdr[0] = ZG_INTR_REG;
+ hdr[1] = ZG_INTR_MASK_FIFO0;
+ spi_transfer(hdr, 2, 1);
+
+ intr_state = ZG_INTR_ST_WT_INTR_REG;
+ next_cmd = ZG_BYTE_COUNT_FIFO0_REG;
+ }
+ else if (intr_val) {
+ intr_state = 0;
+ }
+ else {
+ intr_state = 0;
+ }
+
+ break;
+ }
+ case ZG_INTR_ST_WT_INTR_REG:
+ hdr[0] = 0x40 | next_cmd;
+ hdr[1] = 0x00;
+ hdr[2] = 0x00;
+ spi_transfer(hdr, 3, 1);
+
+ intr_state = ZG_INTR_ST_RD_CTRL_REG;
+ break;
+ case ZG_INTR_ST_RD_CTRL_REG:
+ {
+ U16 rx_byte_cnt = (0x0000 | (hdr[1] << 8) | hdr[2]) & 0x0fff;
+
+ zg_buf[0] = ZG_CMD_RD_FIFO;
+ spi_transfer(zg_buf, rx_byte_cnt + 1, 1);
+
+ hdr[0] = ZG_CMD_RD_FIFO_DONE;
+ spi_transfer(hdr, 1, 1);
+
+ intr_valid = 1;
+
+ intr_state = 0;
+ break;
+ }
+ }
+ } while (intr_state);
+#ifdef USE_DIG8_INTR
+ // PCINT0 supports only edge triggered INT
+ if (PORTB & 0x01) {
+ intr_occured = 0;
+ ZG2100_ISR_ENABLE();
+ }
+ else {
+ intr_occured = 1;
+ }
+#else
+ intr_occured = 0;
+ ZG2100_ISR_ENABLE();
+#endif
+}
+
+void zg_send(U8* buf, U16 len)
+{
+ hdr[0] = ZG_CMD_WT_FIFO_DATA;
+ hdr[1] = ZG_MAC_TYPE_TXDATA_REQ;
+ hdr[2] = ZG_MAC_SUBTYPE_TXDATA_REQ_STD;
+ hdr[3] = 0x00;
+ hdr[4] = 0x00;
+ spi_transfer(hdr, 5, 0);
+
+ buf[6] = 0xaa;
+ buf[7] = 0xaa;
+ buf[8] = 0x03;
+ buf[9] = buf[10] = buf[11] = 0x00;
+ spi_transfer(buf, len, 1);
+
+ hdr[0] = ZG_CMD_WT_FIFO_DONE;
+ spi_transfer(hdr, 1, 1);
+}
+
+void zg_recv(U8* buf, U16* len)
+{
+ zg_rx_data_ind_t* ptr = (zg_rx_data_ind_t*)&(zg_buf[3]);
+ *len = ZGSTOHS( ptr->dataLen );
+
+ memcpy(&zg_buf[0], &zg_buf[5], 6);
+ memcpy(&zg_buf[6], &zg_buf[11], 6);
+ memcpy(&zg_buf[12], &zg_buf[29], *len);
+
+ *len += 12;
+}
+
+U16 zg_get_rx_status()
+{
+ if (rx_ready) {
+ rx_ready = 0;
+ return zg_buf_len;
+ }
+ else {
+ return 0;
+ }
+}
+
+void zg_clear_rx_status()
+{
+ rx_ready = 0;
+}
+
+void zg_set_tx_status(U8 status)
+{
+ tx_ready = status;
+}
+
+U8 zg_get_conn_state()
+{
+ return zg_conn_status;
+}
+
+void zg_set_buf(U8* buf, U16 buf_len)
+{
+ zg_buf = buf;
+ zg_buf_len = buf_len;
+}
+
+U8* zg_get_mac()
+{
+ return mac;
+}
+
+void zg_write_wep_key(U8* cmd_buf)
+{
+ zg_wep_key_req_t* cmd = (zg_wep_key_req_t*)cmd_buf;
+
+ cmd->slot = 3; // WEP key slot
+ cmd->keyLen = 13; // Key length: 5 bytes (64-bit WEP); 13 bytes (128-bit WEP)
+ cmd->defID = 0; // Default key ID: Key 0, 1, 2, 3
+ cmd->ssidLen = ssid_len;
+ memset(cmd->ssid, 0x00, 32);
+ memcpy_P(cmd->ssid, ssid, ssid_len);
+ memcpy_P(cmd->key, wep_keys, ZG_MAX_ENCRYPTION_KEYS * ZG_MAX_ENCRYPTION_KEY_SIZE);
+
+ return;
+}
+
+static void zg_calc_psk_key(U8* cmd_buf)
+{
+ zg_psk_calc_req_t* cmd = (zg_psk_calc_req_t*)cmd_buf;
+
+ cmd->configBits = 0;
+ cmd->phraseLen = security_passphrase_len;
+ cmd->ssidLen = ssid_len;
+ cmd->reserved = 0;
+ memset(cmd->ssid, 0x00, 32);
+ memcpy_P(cmd->ssid, ssid, ssid_len);
+ memset(cmd->passPhrase, 0x00, 64);
+ memcpy_P(cmd->passPhrase, security_passphrase, security_passphrase_len);
+
+ return;
+}
+
+static void zg_write_psk_key(U8* cmd_buf)
+{
+ zg_pmk_key_req_t* cmd = (zg_pmk_key_req_t*)cmd_buf;
+
+ cmd->slot = 0; // WPA/WPA2 PSK slot
+ cmd->ssidLen = ssid_len;
+ memset(cmd->ssid, 0x00, 32);
+ memcpy_P(cmd->ssid, ssid, cmd->ssidLen);
+ memcpy(cmd->keyData, wpa_psk_key, ZG_MAX_PMK_LEN);
+
+ return;
+}
+
+void zg_drv_process()
+{
+ // TX frame
+ if (tx_ready && !cnf_pending) {
+ zg_send(zg_buf, zg_buf_len);
+ tx_ready = 0;
+ cnf_pending = 1;
+ }
+
+ // process interrupt
+ if (intr_occured) {
+ zg_process_isr();
+ }
+
+ if (intr_valid) {
+ switch (zg_buf[1]) {
+ case ZG_MAC_TYPE_TXDATA_CONFIRM:
+ cnf_pending = 0;
+ break;
+ case ZG_MAC_TYPE_MGMT_CONFIRM:
+ if (zg_buf[3] == ZG_RESULT_SUCCESS) {
+ switch (zg_buf[2]) {
+ case ZG_MAC_SUBTYPE_MGMT_REQ_GET_PARAM:
+ mac[0] = zg_buf[7];
+ mac[1] = zg_buf[8];
+ mac[2] = zg_buf[9];
+ mac[3] = zg_buf[10];
+ mac[4] = zg_buf[11];
+ mac[5] = zg_buf[12];
+ zg_drv_state = DRV_STATE_SETUP_SECURITY;
+ break;
+ case ZG_MAC_SUBTYPE_MGMT_REQ_WEP_KEY:
+ zg_drv_state = DRV_STATE_ENABLE_CONN_MANAGE;
+ break;
+ case ZG_MAC_SUBTYPE_MGMT_REQ_CALC_PSK:
+ memcpy(wpa_psk_key, ((zg_psk_calc_cnf_t*)&zg_buf[3])->psk, 32);
+ zg_drv_state = DRV_STATE_INSTALL_PSK;
+ break;
+ case ZG_MAC_SUBTYPE_MGMT_REQ_PMK_KEY:
+ zg_drv_state = DRV_STATE_ENABLE_CONN_MANAGE;
+ break;
+ case ZG_MAC_SUBTYPE_MGMT_REQ_CONNECT_MANAGE:
+ zg_drv_state = DRV_STATE_START_CONN;
+ break;
+ case ZG_MAC_SUBTYPE_MGMT_REQ_CONNECT:
+ LEDConn_on();
+ zg_conn_status = 1; // connected
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case ZG_MAC_TYPE_RXDATA_INDICATE:
+ zg_drv_state = DRV_STATE_PROCESS_RX;
+ break;
+ case ZG_MAC_TYPE_MGMT_INDICATE:
+ switch (zg_buf[2]) {
+ case ZG_MAC_SUBTYPE_MGMT_IND_DISASSOC:
+ case ZG_MAC_SUBTYPE_MGMT_IND_DEAUTH:
+ LEDConn_off();
+ zg_conn_status = 0; // lost connection
+
+ //try to reconnect
+ zg_drv_state = DRV_STATE_START_CONN;
+ break;
+ case ZG_MAC_SUBTYPE_MGMT_IND_CONN_STATUS:
+ {
+ U16 status = (((U16)(zg_buf[3]))<<8)|zg_buf[4];
+
+ if (status == 1 || status == 5) {
+ LEDConn_off();
+ zg_conn_status = 0; // not connected
+ }
+ else if (status == 2 || status == 6) {
+ LEDConn_on();
+ zg_conn_status = 1; // connected
+ }
+ }
+ break;
+ }
+ break;
+ }
+
+ intr_valid = 0;
+ }
+
+ switch (zg_drv_state) {
+ case DRV_STATE_INIT:
+ zg_drv_state = DRV_STATE_GET_MAC;
+ break;
+ case DRV_STATE_GET_MAC:
+ // get MAC address
+ zg_buf[0] = ZG_CMD_WT_FIFO_MGMT;
+ zg_buf[1] = ZG_MAC_TYPE_MGMT_REQ;
+ zg_buf[2] = ZG_MAC_SUBTYPE_MGMT_REQ_GET_PARAM;
+ zg_buf[3] = 0;
+ zg_buf[4] = ZG_PARAM_MAC_ADDRESS;
+ spi_transfer(zg_buf, 5, 1);
+
+ zg_buf[0] = ZG_CMD_WT_FIFO_DONE;
+ spi_transfer(zg_buf, 1, 1);
+
+ zg_drv_state = DRV_STATE_IDLE;
+ break;
+ case DRV_STATE_SETUP_SECURITY:
+ switch (security_type) {
+ case ZG_SECURITY_TYPE_NONE:
+ zg_drv_state = DRV_STATE_ENABLE_CONN_MANAGE;
+ break;
+ case ZG_SECURITY_TYPE_WEP:
+ // Install all four WEP keys on G2100
+ zg_buf[0] = ZG_CMD_WT_FIFO_MGMT;
+ zg_buf[1] = ZG_MAC_TYPE_MGMT_REQ;
+ zg_buf[2] = ZG_MAC_SUBTYPE_MGMT_REQ_WEP_KEY;
+ zg_write_wep_key(&zg_buf[3]);
+ spi_transfer(zg_buf, ZG_WEP_KEY_REQ_SIZE+3, 1);
+
+ zg_buf[0] = ZG_CMD_WT_FIFO_DONE;
+ spi_transfer(zg_buf, 1, 1);
+
+ zg_drv_state = DRV_STATE_IDLE;
+ break;
+ case ZG_SECURITY_TYPE_WPA:
+ case ZG_SECURITY_TYPE_WPA2:
+ // Initiate PSK calculation on G2100
+ zg_buf[0] = ZG_CMD_WT_FIFO_MGMT;
+ zg_buf[1] = ZG_MAC_TYPE_MGMT_REQ;
+ zg_buf[2] = ZG_MAC_SUBTYPE_MGMT_REQ_CALC_PSK;
+ zg_calc_psk_key(&zg_buf[3]);
+ spi_transfer(zg_buf, ZG_PSK_CALC_REQ_SIZE+3, 1);
+
+ zg_buf[0] = ZG_CMD_WT_FIFO_DONE;
+ spi_transfer(zg_buf, 1, 1);
+
+ zg_drv_state = DRV_STATE_IDLE;
+ break;
+ default:
+ break;
+ }
+ break;
+ case DRV_STATE_INSTALL_PSK:
+ // Install the PSK key on G2100
+ zg_buf[0] = ZG_CMD_WT_FIFO_MGMT;
+ zg_buf[1] = ZG_MAC_TYPE_MGMT_REQ;
+ zg_buf[2] = ZG_MAC_SUBTYPE_MGMT_REQ_PMK_KEY;
+ zg_write_psk_key(&zg_buf[3]);
+ spi_transfer(zg_buf, ZG_PMK_KEY_REQ_SIZE+3, 1);
+
+ zg_buf[0] = ZG_CMD_WT_FIFO_DONE;
+ spi_transfer(zg_buf, 1, 1);
+
+ zg_drv_state = DRV_STATE_IDLE;
+ break;
+ case DRV_STATE_ENABLE_CONN_MANAGE:
+ // enable connection manager
+ zg_buf[0] = ZG_CMD_WT_FIFO_MGMT;
+ zg_buf[1] = ZG_MAC_TYPE_MGMT_REQ;
+ zg_buf[2] = ZG_MAC_SUBTYPE_MGMT_REQ_CONNECT_MANAGE;
+ zg_buf[3] = 0x01; // 0x01 - enable; 0x00 - disable
+ zg_buf[4] = 10; // num retries to reconnect
+ zg_buf[5] = 0x10 | 0x02 | 0x01; // 0x10 - enable start and stop indication messages
+ // from G2100 during reconnection
+ // 0x02 - start reconnection on receiving a deauthentication
+ // message from the AP
+ // 0x01 - start reconnection when the missed beacon count
+ // exceeds the threshold. uses default value of
+ // 100 missed beacons if not set during initialization
+ zg_buf[6] = 0;
+ spi_transfer(zg_buf, 7, 1);
+
+ zg_buf[0] = ZG_CMD_WT_FIFO_DONE;
+ spi_transfer(zg_buf, 1, 1);
+
+ zg_drv_state = DRV_STATE_IDLE;
+ break;
+ case DRV_STATE_START_CONN:
+ {
+ zg_connect_req_t* cmd = (zg_connect_req_t*)&zg_buf[3];
+
+ // start connection to AP
+ zg_buf[0] = ZG_CMD_WT_FIFO_MGMT;
+ zg_buf[1] = ZG_MAC_TYPE_MGMT_REQ;
+ zg_buf[2] = ZG_MAC_SUBTYPE_MGMT_REQ_CONNECT;
+
+ cmd->secType = security_type;
+
+ cmd->ssidLen = ssid_len;
+ memset(cmd->ssid, 0, 32);
+ memcpy_P(cmd->ssid, ssid, ssid_len);
+
+ // units of 100 milliseconds
+ cmd->sleepDuration = 0;
+
+ if (wireless_mode == WIRELESS_MODE_INFRA)
+ cmd->modeBss = 1;
+ else if (wireless_mode == WIRELESS_MODE_ADHOC)
+ cmd->modeBss = 2;
+
+ spi_transfer(zg_buf, ZG_CONNECT_REQ_SIZE+3, 1);
+
+ zg_buf[0] = ZG_CMD_WT_FIFO_DONE;
+ spi_transfer(zg_buf, 1, 1);
+
+ zg_drv_state = DRV_STATE_IDLE;
+ break;
+ }
+ case DRV_STATE_PROCESS_RX:
+ zg_recv(zg_buf, &zg_buf_len);
+ rx_ready = 1;
+
+ zg_drv_state = DRV_STATE_IDLE;
+ break;
+ case DRV_STATE_IDLE:
+ break;
+ }
+}
diff --git a/Libraries/WiShield/g2100.h b/Libraries/WiShield/g2100.h
new file mode 100644
index 0000000..6cdc4f1
--- /dev/null
+++ b/Libraries/WiShield/g2100.h
@@ -0,0 +1,302 @@
+
+/*****************************************************************************
+
+ Filename: g2100.h
+ Description: Driver for the ZeroG Wireless G2100 series devices
+
+ *****************************************************************************
+
+ Driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ----------------------------------------------------------------------------
+ AsyncLabs 02/25/2009 Initial port
+ AsyncLabs 05/29/2009 Adding support for new library
+
+ *****************************************************************************/
+
+#ifndef G2100_H_
+#define G2100_H_
+
+#define DRV_STATE_INIT 0
+#define DRV_STATE_GET_MAC 2
+#define DRV_STATE_START_CONN 3
+#define DRV_STATE_PROCESS_RX 4
+#define DRV_STATE_IDLE 5
+#define DRV_STATE_SETUP_SECURITY 6
+#define DRV_STATE_INSTALL_PSK 7
+#define DRV_STATE_ENABLE_CONN_MANAGE 8
+
+//Host to Zero G long
+#define HTOZGL(a) ( ((a & 0x000000ff)<<24) \
+ |((a & 0x0000ff00)<<8) \
+ |((a & 0x00ff0000)>>8) \
+ |((a & 0xff000000)>>24) )
+#define ZGTOHL(a) HTOZGL(a)
+
+// Host to Zero G short
+#define HSTOZGS(a) (u16)(((a)<<8) | ((a)>>8))
+#define ZGSTOHS(a) HSTOZGS(a)
+//#define HTONS(a) HSTOZGS(a)
+
+#define ZG_INTERRUPT_PIN 0 // Pin on Arduino
+
+// Command values which appear in ZG_PREAMBLE_CMD_IDX for each SPI message
+#define ZG_CMD_FIFO_ACCESS (0x80)
+#define ZG_CMD_WT_FIFO_DATA (ZG_CMD_FIFO_ACCESS | 0x20)
+#define ZG_CMD_WT_FIFO_MGMT (ZG_CMD_FIFO_ACCESS | 0x30)
+#define ZG_CMD_RD_FIFO (ZG_CMD_FIFO_ACCESS | 0x00)
+#define ZG_CMD_WT_FIFO_DONE (ZG_CMD_FIFO_ACCESS | 0x40)
+#define ZG_CMD_RD_FIFO_DONE (ZG_CMD_FIFO_ACCESS | 0x50)
+#define ZG_CMD_WT_REG (0x00)
+#define ZG_CMD_RD_REG (0x40)
+
+// Type values which appear in ZG_PREAMBLE_TYPE_IDX for each SPI message
+#define ZG_MAC_TYPE_TXDATA_REQ ((u8)1)
+#define ZG_MAC_TYPE_MGMT_REQ ((u8)2)
+
+#define ZG_MAC_TYPE_TXDATA_CONFIRM ((u8)1)
+#define ZG_MAC_TYPE_MGMT_CONFIRM ((u8)2)
+#define ZG_MAC_TYPE_RXDATA_INDICATE ((u8)3)
+#define ZG_MAC_TYPE_MGMT_INDICATE ((u8)4)
+
+// Subtype values which appear in ZG_PREAMBLE_SUBTYPE_IDX for each SPI message
+// Subtype for ZG_MAC_TYPE_TXDATA_REQ and ZG_MAC_TYPE_TXDATA_CONFIRM
+#define ZG_MAC_SUBTYPE_TXDATA_REQ_STD ((u8)1)
+
+// Subtype for ZG_MAC_TYPE_MGMT_REQ and ZG_MAC_TYPE_MGMT_CONFIRM
+#define ZG_MAC_SUBTYPE_MGMT_REQ_PMK_KEY ((u8)8)
+#define ZG_MAC_SUBTYPE_MGMT_REQ_WEP_KEY ((u8)10)
+#define ZG_MAC_SUBTYPE_MGMT_REQ_CALC_PSK ((u8)12)
+#define ZG_MAC_SUBTYPE_MGMT_REQ_SET_PARAM ((u8)15)
+#define ZG_MAC_SUBTYPE_MGMT_REQ_GET_PARAM ((u8)16)
+#define ZG_MAC_SUBTYPE_MGMT_REQ_ADHOC_START ((u8)18)
+#define ZG_MAC_SUBTYPE_MGMT_REQ_CONNECT ((u8)19)
+#define ZG_MAC_SUBTYPE_MGMT_REQ_CONNECT_MANAGE ((u8)20)
+
+// Subtype for ZG_MAC_TYPE_RXDATA_INDICATE
+#define ZG_MAC_SUBTYPE_RXDATA_IND_STD ((u8)1)
+
+// Subtype for ZG_MAC_TYPE_MGMT_INDICATE
+#define ZG_MAC_SUBTYPE_MGMT_IND_DISASSOC ((u8)1)
+#define ZG_MAC_SUBTYPE_MGMT_IND_DEAUTH ((u8)2)
+#define ZG_MAC_SUBTYPE_MGMT_IND_CONN_STATUS ((u8)4)
+
+// Parameter IDs for ZG_MAC_SUBTYPE_MGMT_REQ_SET_PARAM
+#define ZG_PARAM_MAC_ADDRESS (1)
+
+// MAC result code
+enum {
+ ZG_RESULT_SUCCESS = 1,
+ ZG_RESULT_INVALID_SUBTYPE,
+ ZG_RESULT_CANCELLED,
+ ZG_RESULT_FRAME_EOL,
+ ZG_RESULT_FRAME_RETRY_LIMIT,
+ ZG_RESULT_FRAME_NO_BSS,
+ ZG_RESULT_FRAME_TOO_BIG,
+ ZG_RESULT_FRAME_ENCRYPT_FAILURE,
+ ZG_RESULT_INVALID_PARAMS,
+ ZG_RESULT_ALREADY_AUTH,
+ ZG_RESULT_ALREADY_ASSOC,
+ ZG_RESULT_INSUFFICIENT_RSRCS,
+ ZG_RESULT_TIMEOUT,
+ ZG_RESULT_BAD_EXCHANGE, // frame exchange problem with peer (AP or STA)
+ ZG_RESULT_AUTH_REFUSED, // authenticating node refused our request
+ ZG_RESULT_ASSOC_REFUSED, // associating node refused our request
+ ZG_RESULT_REQ_IN_PROGRESS, // only one mlme request at a time allowed
+ ZG_RESULT_NOT_JOINED, // operation requires that device be joined
+ // with target
+ ZG_RESULT_NOT_ASSOC, // operation requires that device be
+ // associated with target
+ ZG_RESULT_NOT_AUTH, // operation requires that device be
+ // authenticated with target
+ ZG_RESULT_SUPPLICANT_FAILED,
+ ZG_RESULT_UNSUPPORTED_FEATURE,
+ ZG_RESULT_REQUEST_OUT_OF_SYNC // Returned when a request is recognized
+ // but invalid given the current state
+ // of the MAC
+};
+
+/*
+ * G2100 command registers
+ */
+#define ZG_INTR_REG (0x01) // 8-bit register containing interrupt bits
+#define ZG_INTR_MASK_REG (0x02) // 8-bit register containing interrupt mask
+#define ZG_SYS_INFO_DATA_REG (0x21) // 8-bit register to read system info data window
+#define ZG_SYS_INFO_IDX_REG (0x2b)
+#define ZG_INTR2_REG (0x2d) // 16-bit register containing interrupt bits
+#define ZG_INTR2_MASK_REG (0x2e) // 16-bit register containing interrupt mask
+#define ZG_BYTE_COUNT_REG (0x2f) // 16-bit register containing available write size for fifo0
+#define ZG_BYTE_COUNT_FIFO0_REG (0x33) // 16-bit register containing bytes ready to read on fifo0
+#define ZG_BYTE_COUNT_FIFO1_REG (0x35) // 16-bit register containing bytes ready to read on fifo1
+#define ZG_PWR_CTRL_REG (0x3d) // 16-bit register used to control low power mode
+#define ZG_INDEX_ADDR_REG (0x3e) // 16-bit register to move the data window
+#define ZG_INDEX_DATA_REG (0x3f) // 16-bit register to read the address in the ZG_INDEX_ADDR_REG
+
+#define ZG_INTR_REG_LEN (1)
+#define ZG_INTR_MASK_REG_LEN (1)
+#define ZG_SYS_INFO_DATA_REG_LEN (1)
+#define ZG_SYS_INFO_IDX_REG_LEN (2)
+#define ZG_INTR2_REG_LEN (2)
+#define ZG_INTR2_MASK_REG_LEN (2)
+#define ZG_BYTE_COUNT_REG_LEN (2)
+#define ZG_BYTE_COUNT_FIFO0_REG_LEN (2)
+#define ZG_BYTE_COUNT_FIFO1_REG_LEN (2)
+#define ZG_PWR_CTRL_REG_LEN (2)
+#define ZG_INDEX_ADDR_REG_LEN (2)
+#define ZG_INDEX_DATA_REG_LEN (2)
+
+// Registers accessed through ZG_INDEX_ADDR_REG
+#define ZG_RESET_STATUS_REG (0x2a) // 16-bit read only register providing HW status bits
+#define ZG_RESET_REG (0x2e) // 16-bit register used to initiate hard reset
+#define ZG_PWR_STATUS_REG (0x3e) // 16-bit register read to determine when device
+ // out of sleep state
+
+#define ZG_RESET_MASK (0x10) // the first byte of the ZG_RESET_STATUS_REG
+ // used to determine when the G2100 is in reset
+
+#define ZG_ENABLE_LOW_PWR_MASK (0x01) // used by the Host to enable/disable sleep state
+ // indicates to G2100 that the Host has completed
+ // transactions and the device can go into sleep
+ // state if possible
+
+// states for interrupt state machine
+#define ZG_INTR_ST_RD_INTR_REG (1)
+#define ZG_INTR_ST_WT_INTR_REG (2)
+#define ZG_INTR_ST_RD_CTRL_REG (3)
+
+// interrupt state
+#define ZG_INTR_DISABLE ((u8)0)
+#define ZG_INTR_ENABLE ((u8)1)
+
+// mask values for ZG_INTR_REG and ZG_INTR2_REG
+#define ZG_INTR_MASK_FIFO1 (0x80)
+#define ZG_INTR_MASK_FIFO0 (0x40)
+#define ZG_INTR_MASK_ALL (0xff)
+#define ZG_INTR2_MASK_ALL (0xffff)
+
+// Buffer size
+#define ZG_BUFFER_SIZE 450
+
+// Types of networks
+#define ZG_BSS_INFRA (1) // infrastructure only
+#define ZG_BSS_ADHOC (2) // Ad-hoc only (ibss)
+
+// Max characters in network SSID
+#define ZG_MAX_SSID_LENGTH 32
+
+// Security keys
+#define ZG_MAX_ENCRYPTION_KEYS 4
+#define ZG_MAX_ENCRYPTION_KEY_SIZE 13
+#define ZG_MAX_WPA_PASSPHRASE_LEN 64
+#define ZG_MAX_PMK_LEN 32
+
+#define ZG_SECURITY_TYPE_NONE 0
+#define ZG_SECURITY_TYPE_WEP 1
+#define ZG_SECURITY_TYPE_WPA 2
+#define ZG_SECURITY_TYPE_WPA2 3
+
+typedef struct
+{
+ u8 slot; /* slot index */
+ u8 keyLen;
+ u8 defID; /* the default wep key id */
+ u8 ssidLen; /* num valid bytes in ssid */
+ u8 ssid[ZG_MAX_SSID_LENGTH]; /* ssid of network */
+ u8 key[ZG_MAX_ENCRYPTION_KEYS][ZG_MAX_ENCRYPTION_KEY_SIZE]; /* wep key data for 4 default keys */
+} zg_wep_key_req_t;
+
+#define ZG_WEP_KEY_REQ_SIZE (4 + ZG_MAX_SSID_LENGTH + ZG_MAX_ENCRYPTION_KEYS*ZG_MAX_ENCRYPTION_KEY_SIZE)
+
+typedef struct
+{
+ u8 configBits;
+ u8 phraseLen; /* number of valid bytes in passphrase */
+ u8 ssidLen; /* number of valid bytes in ssid */
+ u8 reserved; /* alignment byte */
+ u8 ssid[ZG_MAX_SSID_LENGTH]; /* the string of characters representing the ssid */
+ u8 passPhrase[ZG_MAX_WPA_PASSPHRASE_LEN]; /* the string of characters representing the passphrase */
+} zg_psk_calc_req_t;
+
+#define ZG_PSK_CALC_REQ_SIZE (4 + ZG_MAX_SSID_LENGTH + ZG_MAX_WPA_PASSPHRASE_LEN) /* 100 bytes */
+
+typedef struct
+{
+ u8 result; /* indicating success or other */
+ u8 macState; /* current State of the on-chip MAC */
+ u8 keyReturned; /* 1 if psk contains key data, 0 otherwise */
+ u8 reserved; /* pad byte */
+ u8 psk[ZG_MAX_PMK_LEN]; /* the psk bytes */
+} zg_psk_calc_cnf_t;
+
+typedef struct
+{
+ u8 slot;
+ u8 ssidLen;
+ u8 ssid[ZG_MAX_SSID_LENGTH];
+ u8 keyData[ZG_MAX_PMK_LEN];
+} zg_pmk_key_req_t;
+
+#define ZG_PMK_KEY_REQ_SIZE (2 + ZG_MAX_SSID_LENGTH + ZG_MAX_PMK_LEN)
+
+typedef struct
+{
+ u16 rssi; /* the value of the G1000 RSSI when the data frame was received */
+ u8 dstAddr[6]; /* MAC Address to which the data frame was directed. */
+ u8 srcAddr[6]; /* MAC Address of the Station that sent the Data frame. */
+ u16 arrivalTime_th; /* the value of the 32-bit G1000 system clock when the frame arrived */
+ u16 arrivalTime_bh;
+ u16 dataLen; /* the length in bytes of the payload which immediately follows this data structure */
+} zg_rx_data_ind_t;
+
+typedef struct
+{
+ u8 secType; /* security type : 0 - none; 1 - wep; 2 - wpa; 3 - wpa2; 0xff - best available */
+ u8 ssidLen; /* num valid bytes in ssid */
+ u8 ssid[ZG_MAX_SSID_LENGTH]; /* the ssid of the target */
+ u16 sleepDuration; /* power save sleep duration in units of 100 milliseconds */
+ u8 modeBss; /* 1 - infra; 2 - adhoc */
+ u8 reserved;
+} zg_connect_req_t;
+
+#define ZG_CONNECT_REQ_SIZE (38)
+
+void zg_init();
+void zg_reset();
+void spi_transfer(volatile U8* buf, U16 len, U8 toggle_cs);
+void zg_chip_reset();
+void zg_interrupt2_reg();
+void zg_interrupt_reg(U8 mask, U8 state);
+void zg_isr();
+void zg_process_isr();
+void zg_send(U8* buf, U16 len);
+void zg_recv(U8* buf, U16* len);
+U16 zg_get_rx_status();
+void zg_clear_rx_status();
+void zg_set_tx_status(U8 status);
+U8 zg_get_conn_state();
+void zg_set_buf(U8* buf, U16 buf_len);
+U8* zg_get_mac();
+void zg_set_ssid(U8* ssid, U8 ssid_len);
+void zg_set_sec(U8 sec_type, U8* sec_key, U8 sec_key_len);
+void zg_drv_process();
+
+#endif /* G2100_H_ */
diff --git a/Libraries/WiShield/global-conf.h b/Libraries/WiShield/global-conf.h
new file mode 100644
index 0000000..d97f5d0
--- /dev/null
+++ b/Libraries/WiShield/global-conf.h
@@ -0,0 +1,45 @@
+
+/******************************************************************************
+
+ Filename: global-conf.h
+ Description: Stack configuration for the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/29/2009 Initial version
+
+ *****************************************************************************/
+
+//Project specific configurations
+#ifndef __GLOBAL_CONF_H__
+#define __GLOBAL_CONF_H__
+
+//Define frequency
+//#define F_CPU 12500000UL
+
+//Include uip.h gives all the uip configurations in uip-conf.h
+#include "uip.h"
+
+#endif /*__GLOBAL_CONF_H__*/
diff --git a/Libraries/WiShield/global.h b/Libraries/WiShield/global.h
new file mode 100644
index 0000000..f268c4f
--- /dev/null
+++ b/Libraries/WiShield/global.h
@@ -0,0 +1,34 @@
+/*! \file global.h \brief AVRlib project global include. */
+//*****************************************************************************
+//
+// File Name : 'global.h'
+// Title : AVRlib project global include
+// Author : Pascal Stang - Copyright (C) 2001-2002
+// Created : 7/12/2001
+// Revised : 9/30/2002
+// Version : 1.1
+// Target MCU : Atmel AVR series
+// Editor Tabs : 4
+//
+// Description : This include file is designed to contain items useful to all
+// code files and projects.
+//
+// This code is distributed under the GNU Public License
+// which can be found at http://www.gnu.org/licenses/gpl.txt
+//
+//*****************************************************************************
+
+#ifndef GLOBAL_H
+#define GLOBAL_H
+
+#include "uip.h"
+
+// global AVRLIB defines
+#include "avrlibdefs.h"
+// global AVRLIB types definitions
+#include "avrlibtypes.h"
+
+// project/system dependent defines
+#define CYCLES_PER_US ((F_CPU+500000)/1000000) // cpu cycles per microsecond
+
+#endif
diff --git a/Libraries/WiShield/lc-addrlabels.h b/Libraries/WiShield/lc-addrlabels.h
new file mode 100644
index 0000000..fe1387e
--- /dev/null
+++ b/Libraries/WiShield/lc-addrlabels.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: lc-addrlabels.h,v 1.3 2006/06/12 08:00:30 adam Exp $
+ */
+
+/**
+ * \addtogroup lc
+ * @{
+ */
+
+/**
+ * \file
+ * Implementation of local continuations based on the "Labels as
+ * values" feature of gcc
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ * This implementation of local continuations is based on a special
+ * feature of the GCC C compiler called "labels as values". This
+ * feature allows assigning pointers with the address of the code
+ * corresponding to a particular C label.
+ *
+ * For more information, see the GCC documentation:
+ * http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
+ *
+ * Thanks to dividuum for finding the nice local scope label
+ * implementation.
+ */
+
+#ifndef __LC_ADDRLABELS_H__
+#define __LC_ADDRLABELS_H__
+
+/** \hideinitializer */
+typedef void * lc_t;
+
+#define LC_INIT(s) s = NULL
+
+
+#define LC_RESUME(s) \
+ do { \
+ if(s != NULL) { \
+ goto *s; \
+ } \
+ } while(0)
+
+#define LC_SET(s) \
+ do { ({ __label__ resume; resume: (s) = &&resume; }); }while(0)
+
+#define LC_END(s)
+
+#endif /* __LC_ADDRLABELS_H__ */
+
+/** @} */
diff --git a/Libraries/WiShield/lc-switch.h b/Libraries/WiShield/lc-switch.h
new file mode 100644
index 0000000..f32885f
--- /dev/null
+++ b/Libraries/WiShield/lc-switch.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: lc-switch.h,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+
+/**
+ * \addtogroup lc
+ * @{
+ */
+
+/**
+ * \file
+ * Implementation of local continuations based on switch() statment
+ * \author Adam Dunkels <adam@sics.se>
+ *
+ * This implementation of local continuations uses the C switch()
+ * statement to resume execution of a function somewhere inside the
+ * function's body. The implementation is based on the fact that
+ * switch() statements are able to jump directly into the bodies of
+ * control structures such as if() or while() statmenets.
+ *
+ * This implementation borrows heavily from Simon Tatham's coroutines
+ * implementation in C:
+ * http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
+ */
+
+#ifndef __LC_SWITCH_H__
+#define __LC_SWTICH_H__
+
+/* WARNING! lc implementation using switch() does not work if an
+ LC_SET() is done within another switch() statement! */
+
+/** \hideinitializer */
+typedef unsigned short lc_t;
+
+#define LC_INIT(s) s = 0;
+
+#define LC_RESUME(s) switch(s) { case 0:
+
+#define LC_SET(s) s = __LINE__; case __LINE__:
+
+#define LC_END(s) }
+
+#endif /* __LC_SWITCH_H__ */
+
+/** @} */
diff --git a/Libraries/WiShield/lc.h b/Libraries/WiShield/lc.h
new file mode 100644
index 0000000..a9e9d46
--- /dev/null
+++ b/Libraries/WiShield/lc.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: lc.h,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+
+/**
+ * \addtogroup pt
+ * @{
+ */
+
+/**
+ * \defgroup lc Local continuations
+ * @{
+ *
+ * Local continuations form the basis for implementing protothreads. A
+ * local continuation can be <i>set</i> in a specific function to
+ * capture the state of the function. After a local continuation has
+ * been set can be <i>resumed</i> in order to restore the state of the
+ * function at the point where the local continuation was set.
+ *
+ *
+ */
+
+/**
+ * \file lc.h
+ * Local continuations
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifdef DOXYGEN
+/**
+ * Initialize a local continuation.
+ *
+ * This operation initializes the local continuation, thereby
+ * unsetting any previously set continuation state.
+ *
+ * \hideinitializer
+ */
+#define LC_INIT(lc)
+
+/**
+ * Set a local continuation.
+ *
+ * The set operation saves the state of the function at the point
+ * where the operation is executed. As far as the set operation is
+ * concerned, the state of the function does <b>not</b> include the
+ * call-stack or local (automatic) variables, but only the program
+ * counter and such CPU registers that needs to be saved.
+ *
+ * \hideinitializer
+ */
+#define LC_SET(lc)
+
+/**
+ * Resume a local continuation.
+ *
+ * The resume operation resumes a previously set local continuation, thus
+ * restoring the state in which the function was when the local
+ * continuation was set. If the local continuation has not been
+ * previously set, the resume operation does nothing.
+ *
+ * \hideinitializer
+ */
+#define LC_RESUME(lc)
+
+/**
+ * Mark the end of local continuation usage.
+ *
+ * The end operation signifies that local continuations should not be
+ * used any more in the function. This operation is not needed for
+ * most implementations of local continuation, but is required by a
+ * few implementations.
+ *
+ * \hideinitializer
+ */
+#define LC_END(lc)
+
+/**
+ * \var typedef lc_t;
+ *
+ * The local continuation type.
+ *
+ * \hideinitializer
+ */
+#endif /* DOXYGEN */
+
+#ifndef __LC_H__
+#define __LC_H__
+
+#ifdef LC_CONF_INCLUDE
+#include LC_CONF_INCLUDE
+#else
+#include "lc-switch.h"
+#endif /* LC_CONF_INCLUDE */
+
+#endif /* __LC_H__ */
+
+/** @} */
+/** @} */
diff --git a/Libraries/WiShield/memb.c b/Libraries/WiShield/memb.c
new file mode 100644
index 0000000..777b52f
--- /dev/null
+++ b/Libraries/WiShield/memb.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: memb.c,v 1.1 2006/06/12 08:21:43 adam Exp $
+ */
+
+/**
+ * \addtogroup memb
+ * @{
+ */
+
+ /**
+ * \file
+ * Memory block allocation routines.
+ * \author Adam Dunkels <adam@sics.se>
+ */
+#include <string.h>
+
+#include "memb.h"
+
+/*---------------------------------------------------------------------------*/
+void
+memb_init(struct memb_blocks *m)
+{
+ memset(m->count, 0, m->num);
+ memset(m->mem, 0, m->size * m->num);
+}
+/*---------------------------------------------------------------------------*/
+void *
+memb_alloc(struct memb_blocks *m)
+{
+ int i;
+
+ for(i = 0; i < m->num; ++i) {
+ if(m->count[i] == 0) {
+ /* If this block was unused, we increase the reference count to
+ indicate that it now is used and return a pointer to the
+ memory block. */
+ ++(m->count[i]);
+ return (void *)((char *)m->mem + (i * m->size));
+ }
+ }
+
+ /* No free block was found, so we return NULL to indicate failure to
+ allocate block. */
+ return NULL;
+}
+/*---------------------------------------------------------------------------*/
+char
+memb_free(struct memb_blocks *m, void *ptr)
+{
+ int i;
+ char *ptr2;
+
+ /* Walk through the list of blocks and try to find the block to
+ which the pointer "ptr" points to. */
+ ptr2 = (char *)m->mem;
+ for(i = 0; i < m->num; ++i) {
+
+ if(ptr2 == (char *)ptr) {
+ /* We've found to block to which "ptr" points so we decrease the
+ reference count and return the new value of it. */
+ if(m->count[i] > 0) {
+ /* Make sure that we don't deallocate free memory. */
+ --(m->count[i]);
+ }
+ return m->count[i];
+ }
+ ptr2 += m->size;
+ }
+ return -1;
+}
+/*---------------------------------------------------------------------------*/
+
+/** @} */
diff --git a/Libraries/WiShield/memb.h b/Libraries/WiShield/memb.h
new file mode 100644
index 0000000..b725ebe
--- /dev/null
+++ b/Libraries/WiShield/memb.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: memb.h,v 1.1 2006/06/12 08:21:43 adam Exp $
+ */
+
+/**
+ * \defgroup memb Memory block management functions
+ *
+ * The memory block allocation routines provide a simple yet powerful
+ * set of functions for managing a set of memory blocks of fixed
+ * size. A set of memory blocks is statically declared with the
+ * MEMB() macro. Memory blocks are allocated from the declared
+ * memory by the memb_alloc() function, and are deallocated with the
+ * memb_free() function.
+ *
+ * \note Because of namespace clashes only one MEMB() can be
+ * declared per C module, and the name scope of a MEMB() memory
+ * block is local to each C module.
+ *
+ * The following example shows how to declare and use a memory block
+ * called "cmem" which has 8 chunks of memory with each memory chunk
+ * being 20 bytes large.
+ *
+ * @{
+ */
+
+
+/**
+ * \file
+ * Memory block allocation routines.
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifndef __MEMB_H__
+#define __MEMB_H__
+
+/*
+ * Here we define a C preprocessing macro for concatenating to
+ * strings. We need use two macros in order to allow concatenation of
+ * two #defined macros.
+ */
+#define MEMB_CONCAT2(s1, s2) s1##s2
+#define MEMB_CONCAT(s1, s2) MEMB_CONCAT2(s1, s2)
+
+/**
+ * Declare a memory block.
+ *
+ * This macro is used to staticall declare a block of memory that can
+ * be used by the block allocation functions. The macro statically
+ * declares a C array with a size that matches the specified number of
+ * blocks and their individual sizes.
+ *
+ * Example:
+ \code
+MEMB(connections, sizeof(struct connection), 16);
+ \endcode
+ *
+ * \param name The name of the memory block (later used with
+ * memb_init(), memb_alloc() and memb_free()).
+ *
+ * \param size The size of each memory chunk, in bytes.
+ *
+ * \param num The total number of memory chunks in the block.
+ *
+ */
+#define MEMB(name, structure, num) \
+ static char MEMB_CONCAT(name,_memb_count)[num]; \
+ static structure MEMB_CONCAT(name,_memb_mem)[num]; \
+ static struct memb_blocks name = {sizeof(structure), num, \
+ MEMB_CONCAT(name,_memb_count), \
+ (void *)MEMB_CONCAT(name,_memb_mem)}
+
+struct memb_blocks {
+ unsigned short size;
+ unsigned short num;
+ char *count;
+ void *mem;
+};
+
+/**
+ * Initialize a memory block that was declared with MEMB().
+ *
+ * \param m A memory block previosly declared with MEMB().
+ */
+void memb_init(struct memb_blocks *m);
+
+/**
+ * Allocate a memory block from a block of memory declared with MEMB().
+ *
+ * \param m A memory block previosly declared with MEMB().
+ */
+void *memb_alloc(struct memb_blocks *m);
+
+/**
+ * Deallocate a memory block from a memory block previously declared
+ * with MEMB().
+ *
+ * \param m m A memory block previosly declared with MEMB().
+ *
+ * \param ptr A pointer to the memory block that is to be deallocated.
+ *
+ * \return The new reference count for the memory block (should be 0
+ * if successfully deallocated) or -1 if the pointer "ptr" did not
+ * point to a legal memory block.
+ */
+char memb_free(struct memb_blocks *m, void *ptr);
+
+/** @} */
+
+#endif /* __MEMB_H__ */
diff --git a/Libraries/WiShield/network.c b/Libraries/WiShield/network.c
new file mode 100644
index 0000000..fa8b7ab
--- /dev/null
+++ b/Libraries/WiShield/network.c
@@ -0,0 +1,71 @@
+
+/******************************************************************************
+
+ Filename: network.c
+ Description: Network interface for the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/29/2009 Initial version
+
+ *****************************************************************************/
+
+#include "global-conf.h"
+#include <avr/io.h>
+#include <util/delay.h>
+#include <string.h>
+#include "witypes.h"
+#include "g2100.h"
+
+void network_init(void)
+{
+}
+
+unsigned int network_read(void)
+{
+ return zg_get_rx_status();
+}
+
+void network_send(void)
+{
+ if (uip_len > 0) {
+ if(uip_len <= UIP_LLH_LEN + 40){
+ zg_set_buf(uip_buf, uip_len);
+ }
+ else{
+ memcpy((u8*)&uip_buf[54], (u8*)uip_appdata, (uip_len-54));
+ zg_set_buf(uip_buf, uip_len);
+ }
+ zg_set_tx_status(1);
+ }
+}
+
+void network_get_MAC(u8* macaddr)
+{
+}
+
+void network_set_MAC(u8* macaddr)
+{
+}
diff --git a/Libraries/WiShield/network.h b/Libraries/WiShield/network.h
new file mode 100644
index 0000000..e64ef61
--- /dev/null
+++ b/Libraries/WiShield/network.h
@@ -0,0 +1,53 @@
+
+/******************************************************************************
+
+ Filename: network.h
+ Description: Network interface for the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/29/2009 Initial version
+
+ *****************************************************************************/
+
+#ifndef __NETWORK_H__
+#define __NETWORK_H__
+
+/*Initialize the network*/
+void network_init(void);
+
+/*Read from the network, returns number of read bytes*/
+unsigned int network_read(void);
+
+/*Send using the network*/
+void network_send(void);
+
+/*Sets the MAC address of the device*/
+void network_set_MAC(uint8_t* mac);
+
+/*Gets the MAC address of the device*/
+void network_get_MAC(uint8_t* mac);
+
+#endif /* __NETWORK_H__ */
diff --git a/Libraries/WiShield/psock.c b/Libraries/WiShield/psock.c
new file mode 100644
index 0000000..731e8e0
--- /dev/null
+++ b/Libraries/WiShield/psock.c
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: psock.c,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "uipopt.h"
+#include "psock.h"
+#include "uip.h"
+
+#define STATE_NONE 0
+#define STATE_ACKED 1
+#define STATE_READ 2
+#define STATE_BLOCKED_NEWDATA 3
+#define STATE_BLOCKED_CLOSE 4
+#define STATE_BLOCKED_SEND 5
+#define STATE_DATA_SENT 6
+
+/*
+ * Return value of the buffering functions that indicates that a
+ * buffer was not filled by incoming data.
+ *
+ */
+#define BUF_NOT_FULL 0
+#define BUF_NOT_FOUND 0
+
+/*
+ * Return value of the buffering functions that indicates that a
+ * buffer was completely filled by incoming data.
+ *
+ */
+#define BUF_FULL 1
+
+/*
+ * Return value of the buffering functions that indicates that an
+ * end-marker byte was found.
+ *
+ */
+#define BUF_FOUND 2
+
+/*---------------------------------------------------------------------------*/
+static void
+buf_setup(struct psock_buf *buf,
+ u8_t *bufptr, u16_t bufsize)
+{
+ buf->ptr = bufptr;
+ buf->left = bufsize;
+}
+/*---------------------------------------------------------------------------*/
+static u8_t
+buf_bufdata(struct psock_buf *buf, u16_t len,
+ u8_t **dataptr, u16_t *datalen)
+{
+ if(*datalen < buf->left) {
+ memcpy(buf->ptr, *dataptr, *datalen);
+ buf->ptr += *datalen;
+ buf->left -= *datalen;
+ *dataptr += *datalen;
+ *datalen = 0;
+ return BUF_NOT_FULL;
+ } else if(*datalen == buf->left) {
+ memcpy(buf->ptr, *dataptr, *datalen);
+ buf->ptr += *datalen;
+ buf->left = 0;
+ *dataptr += *datalen;
+ *datalen = 0;
+ return BUF_FULL;
+ } else {
+ memcpy(buf->ptr, *dataptr, buf->left);
+ buf->ptr += buf->left;
+ *datalen -= buf->left;
+ *dataptr += buf->left;
+ buf->left = 0;
+ return BUF_FULL;
+ }
+}
+/*---------------------------------------------------------------------------*/
+static u8_t
+buf_bufto(register struct psock_buf *buf, u8_t endmarker,
+ register u8_t **dataptr, register u16_t *datalen)
+{
+ u8_t c;
+ while(buf->left > 0 && *datalen > 0) {
+ c = *buf->ptr = **dataptr;
+ ++*dataptr;
+ ++buf->ptr;
+ --*datalen;
+ --buf->left;
+
+ if(c == endmarker) {
+ return BUF_FOUND;
+ }
+ }
+
+ if(*datalen == 0) {
+ return BUF_NOT_FOUND;
+ }
+
+ while(*datalen > 0) {
+ c = **dataptr;
+ --*datalen;
+ ++*dataptr;
+
+ if(c == endmarker) {
+ return BUF_FOUND | BUF_FULL;
+ }
+ }
+
+ return BUF_FULL;
+}
+/*---------------------------------------------------------------------------*/
+static char
+send_data(register struct psock *s)
+{
+ if(s->state != STATE_DATA_SENT || uip_rexmit()) {
+ if(s->sendlen > uip_mss()) {
+ uip_send(s->sendptr, uip_mss());
+ } else {
+ uip_send(s->sendptr, s->sendlen);
+ }
+ s->state = STATE_DATA_SENT;
+ return 1;
+ }
+ return 0;
+}
+/*---------------------------------------------------------------------------*/
+static char
+data_acked(register struct psock *s)
+{
+ if(s->state == STATE_DATA_SENT && uip_acked()) {
+ if(s->sendlen > uip_mss()) {
+ s->sendlen -= uip_mss();
+ s->sendptr += uip_mss();
+ } else {
+ s->sendptr += s->sendlen;
+ s->sendlen = 0;
+ }
+ s->state = STATE_ACKED;
+ return 1;
+ }
+ return 0;
+}
+/*---------------------------------------------------------------------------*/
+PT_THREAD(psock_send(register struct psock *s, const unsigned char *buf,
+ unsigned int len))
+{
+ PT_BEGIN(&s->psockpt);
+
+ /* If there is no data to send, we exit immediately. */
+ if(len == 0) {
+ PT_EXIT(&s->psockpt);
+ }
+
+ /* Save the length of and a pointer to the data that is to be
+ sent. */
+ s->sendptr = buf;
+ s->sendlen = len;
+
+ s->state = STATE_NONE;
+
+ /* We loop here until all data is sent. The s->sendlen variable is
+ updated by the data_sent() function. */
+ while(s->sendlen > 0) {
+
+ /*
+ * The condition for this PT_WAIT_UNTIL is a little tricky: the
+ * protothread will wait here until all data has been acknowledged
+ * (data_acked() returns true) and until all data has been sent
+ * (send_data() returns true). The two functions data_acked() and
+ * send_data() must be called in succession to ensure that all
+ * data is sent. Therefore the & operator is used instead of the
+ * && operator, which would cause only the data_acked() function
+ * to be called when it returns false.
+ */
+ PT_WAIT_UNTIL(&s->psockpt, data_acked(s) & send_data(s));
+ }
+
+ s->state = STATE_NONE;
+
+ PT_END(&s->psockpt);
+}
+/*---------------------------------------------------------------------------*/
+PT_THREAD(psock_generator_send(register struct psock *s,
+ unsigned short (*generate)(void *), void *arg))
+{
+ PT_BEGIN(&s->psockpt);
+
+ /* Ensure that there is a generator function to call. */
+ if(generate == NULL) {
+ PT_EXIT(&s->psockpt);
+ }
+
+ /* Call the generator function to generate the data in the
+ uip_appdata buffer. */
+ s->sendlen = generate(arg);
+ s->sendptr = uip_appdata;
+
+ s->state = STATE_NONE;
+ do {
+ /* Call the generator function again if we are called to perform a
+ retransmission. */
+ if(uip_rexmit()) {
+ generate(arg);
+ }
+ /* Wait until all data is sent and acknowledged. */
+ PT_WAIT_UNTIL(&s->psockpt, data_acked(s) & send_data(s));
+ } while(s->sendlen > 0);
+
+ s->state = STATE_NONE;
+
+ PT_END(&s->psockpt);
+}
+/*---------------------------------------------------------------------------*/
+u16_t
+psock_datalen(struct psock *psock)
+{
+ return psock->bufsize - psock->buf.left;
+}
+/*---------------------------------------------------------------------------*/
+char
+psock_newdata(struct psock *s)
+{
+ if(s->readlen > 0) {
+ /* There is data in the uip_appdata buffer that has not yet been
+ read with the PSOCK_READ functions. */
+ return 1;
+ } else if(s->state == STATE_READ) {
+ /* All data in uip_appdata buffer already consumed. */
+ s->state = STATE_BLOCKED_NEWDATA;
+ return 0;
+ } else if(uip_newdata()) {
+ /* There is new data that has not been consumed. */
+ return 1;
+ } else {
+ /* There is no new data. */
+ return 0;
+ }
+}
+/*---------------------------------------------------------------------------*/
+PT_THREAD(psock_readto(register struct psock *psock, unsigned char c))
+{
+ PT_BEGIN(&psock->psockpt);
+
+ buf_setup(&psock->buf, psock->bufptr, psock->bufsize);
+
+ /* XXX: Should add buf_checkmarker() before do{} loop, if
+ incoming data has been handled while waiting for a write. */
+
+ do {
+ if(psock->readlen == 0) {
+ PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock));
+ psock->state = STATE_READ;
+ psock->readptr = (u8_t *)uip_appdata;
+ psock->readlen = uip_datalen();
+ }
+ } while((buf_bufto(&psock->buf, c,
+ &psock->readptr,
+ &psock->readlen) & BUF_FOUND) == 0);
+
+ if(psock_datalen(psock) == 0) {
+ psock->state = STATE_NONE;
+ PT_RESTART(&psock->psockpt);
+ }
+ PT_END(&psock->psockpt);
+}
+/*---------------------------------------------------------------------------*/
+PT_THREAD(psock_readbuf(register struct psock *psock))
+{
+ PT_BEGIN(&psock->psockpt);
+
+ buf_setup(&psock->buf, psock->bufptr, psock->bufsize);
+
+ /* XXX: Should add buf_checkmarker() before do{} loop, if
+ incoming data has been handled while waiting for a write. */
+
+ do {
+ if(psock->readlen == 0) {
+ PT_WAIT_UNTIL(&psock->psockpt, psock_newdata(psock));
+ printf("Waited for newdata\n");
+ psock->state = STATE_READ;
+ psock->readptr = (u8_t *)uip_appdata;
+ psock->readlen = uip_datalen();
+ }
+ } while(buf_bufdata(&psock->buf, psock->bufsize,
+ &psock->readptr,
+ &psock->readlen) != BUF_FULL);
+
+ if(psock_datalen(psock) == 0) {
+ psock->state = STATE_NONE;
+ PT_RESTART(&psock->psockpt);
+ }
+ PT_END(&psock->psockpt);
+}
+/*---------------------------------------------------------------------------*/
+void
+psock_init(register struct psock *psock, unsigned char *buffer, unsigned int buffersize)
+{
+ psock->state = STATE_NONE;
+ psock->readlen = 0;
+ psock->bufptr = buffer;
+ psock->bufsize = buffersize;
+ buf_setup(&psock->buf, buffer, buffersize);
+ PT_INIT(&psock->pt);
+ PT_INIT(&psock->psockpt);
+}
+/*---------------------------------------------------------------------------*/
diff --git a/Libraries/WiShield/psock.h b/Libraries/WiShield/psock.h
new file mode 100644
index 0000000..ca848af
--- /dev/null
+++ b/Libraries/WiShield/psock.h
@@ -0,0 +1,380 @@
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: psock.h,v 1.3 2006/06/12 08:00:30 adam Exp $
+ */
+
+/**
+ * \defgroup psock Protosockets library
+ * @{
+ *
+ * The protosocket library provides an interface to the uIP stack that is
+ * similar to the traditional BSD socket interface. Unlike programs
+ * written for the ordinary uIP event-driven interface, programs
+ * written with the protosocket library are executed in a sequential
+ * fashion and does not have to be implemented as explicit state
+ * machines.
+ *
+ * Protosockets only work with TCP connections.
+ *
+ * The protosocket library uses \ref pt protothreads to provide
+ * sequential control flow. This makes the protosockets lightweight in
+ * terms of memory, but also means that protosockets inherits the
+ * functional limitations of protothreads. Each protosocket lives only
+ * within a single function. Automatic variables (stack variables) are
+ * not retained across a protosocket library function call.
+ *
+ * \note Because the protosocket library uses protothreads, local
+ * variables will not always be saved across a call to a protosocket
+ * library function. It is therefore advised that local variables are
+ * used with extreme care.
+ *
+ * The protosocket library provides functions for sending data without
+ * having to deal with retransmissions and acknowledgements, as well
+ * as functions for reading data without having to deal with data
+ * being split across more than one TCP segment.
+ *
+ * Because each protosocket runs as a protothread, the protosocket has to be
+ * started with a call to PSOCK_BEGIN() at the start of the function
+ * in which the protosocket is used. Similarly, the protosocket protothread can
+ * be terminated by a call to PSOCK_EXIT().
+ *
+ */
+
+/**
+ * \file
+ * Protosocket library header file
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifndef __PSOCK_H__
+#define __PSOCK_H__
+
+#include "uipopt.h"
+#include "pt.h"
+
+ /*
+ * The structure that holds the state of a buffer.
+ *
+ * This structure holds the state of a uIP buffer. The structure has
+ * no user-visible elements, but is used through the functions
+ * provided by the library.
+ *
+ */
+struct psock_buf {
+ u8_t *ptr;
+ unsigned short left;
+};
+
+/**
+ * The representation of a protosocket.
+ *
+ * The protosocket structrure is an opaque structure with no user-visible
+ * elements.
+ */
+struct psock {
+ struct pt pt, psockpt; /* Protothreads - one that's using the psock
+ functions, and one that runs inside the
+ psock functions. */
+ const u8_t *sendptr; /* Pointer to the next data to be sent. */
+ u8_t *readptr; /* Pointer to the next data to be read. */
+
+ unsigned char *bufptr; /* Pointer to the buffer used for buffering
+ incoming data. */
+
+ u16_t sendlen; /* The number of bytes left to be sent. */
+ u16_t readlen; /* The number of bytes left to be read. */
+
+ struct psock_buf buf; /* The structure holding the state of the
+ input buffer. */
+ unsigned int bufsize; /* The size of the input buffer. */
+
+ unsigned char state; /* The state of the protosocket. */
+};
+
+void psock_init(struct psock *psock, unsigned char *buffer, unsigned int buffersize);
+/**
+ * Initialize a protosocket.
+ *
+ * This macro initializes a protosocket and must be called before the
+ * protosocket is used. The initialization also specifies the input buffer
+ * for the protosocket.
+ *
+ * \param psock (struct psock *) A pointer to the protosocket to be
+ * initialized
+ *
+ * \param buffer (char *) A pointer to the input buffer for the
+ * protosocket.
+ *
+ * \param buffersize (unsigned int) The size of the input buffer.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_INIT(psock, buffer, buffersize) \
+ psock_init(psock, buffer, buffersize)
+
+/**
+ * Start the protosocket protothread in a function.
+ *
+ * This macro starts the protothread associated with the protosocket and
+ * must come before other protosocket calls in the function it is used.
+ *
+ * \param psock (struct psock *) A pointer to the protosocket to be
+ * started.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_BEGIN(psock) PT_BEGIN(&((psock)->pt))
+
+PT_THREAD(psock_send(struct psock *psock, const unsigned char *buf, unsigned int len));
+/**
+ * Send data.
+ *
+ * This macro sends data over a protosocket. The protosocket protothread blocks
+ * until all data has been sent and is known to have been received by
+ * the remote end of the TCP connection.
+ *
+ * \param psock (struct psock *) A pointer to the protosocket over which
+ * data is to be sent.
+ *
+ * \param data (char *) A pointer to the data that is to be sent.
+ *
+ * \param datalen (unsigned int) The length of the data that is to be
+ * sent.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_SEND(psock, data, datalen) \
+ PT_WAIT_THREAD(&((psock)->pt), psock_send(psock, data, datalen))
+
+/**
+ * \brief Send a null-terminated string.
+ * \param psock Pointer to the protosocket.
+ * \param str The string to be sent.
+ *
+ * This function sends a null-terminated string over the
+ * protosocket.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_SEND_STR(psock, str) \
+ PT_WAIT_THREAD(&((psock)->pt), psock_send(psock, str, strlen(str)))
+
+PT_THREAD(psock_generator_send(struct psock *psock,
+ unsigned short (*f)(void *), void *arg));
+
+/**
+ * \brief Generate data with a function and send it
+ * \param psock Pointer to the protosocket.
+ * \param generator Pointer to the generator function
+ * \param arg Argument to the generator function
+ *
+ * This function generates data and sends it over the
+ * protosocket. This can be used to dynamically generate
+ * data for a transmission, instead of generating the data
+ * in a buffer beforehand. This function reduces the need for
+ * buffer memory. The generator function is implemented by
+ * the application, and a pointer to the function is given
+ * as an argument with the call to PSOCK_GENERATOR_SEND().
+ *
+ * The generator function should place the generated data
+ * directly in the uip_appdata buffer, and return the
+ * length of the generated data. The generator function is
+ * called by the protosocket layer when the data first is
+ * sent, and once for every retransmission that is needed.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_GENERATOR_SEND(psock, generator, arg) \
+ PT_WAIT_THREAD(&((psock)->pt), \
+ psock_generator_send(psock, generator, arg))
+
+
+/**
+ * Close a protosocket.
+ *
+ * This macro closes a protosocket and can only be called from within the
+ * protothread in which the protosocket lives.
+ *
+ * \param psock (struct psock *) A pointer to the protosocket that is to
+ * be closed.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_CLOSE(psock) uip_close()
+
+PT_THREAD(psock_readbuf(struct psock *psock));
+/**
+ * Read data until the buffer is full.
+ *
+ * This macro will block waiting for data and read the data into the
+ * input buffer specified with the call to PSOCK_INIT(). Data is read
+ * until the buffer is full..
+ *
+ * \param psock (struct psock *) A pointer to the protosocket from which
+ * data should be read.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_READBUF(psock) \
+ PT_WAIT_THREAD(&((psock)->pt), psock_readbuf(psock))
+
+PT_THREAD(psock_readto(struct psock *psock, unsigned char c));
+/**
+ * Read data up to a specified character.
+ *
+ * This macro will block waiting for data and read the data into the
+ * input buffer specified with the call to PSOCK_INIT(). Data is only
+ * read until the specifieed character appears in the data stream.
+ *
+ * \param psock (struct psock *) A pointer to the protosocket from which
+ * data should be read.
+ *
+ * \param c (char) The character at which to stop reading.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_READTO(psock, c) \
+ PT_WAIT_THREAD(&((psock)->pt), psock_readto(psock, c))
+
+/**
+ * The length of the data that was previously read.
+ *
+ * This macro returns the length of the data that was previously read
+ * using PSOCK_READTO() or PSOCK_READ().
+ *
+ * \param psock (struct psock *) A pointer to the protosocket holding the data.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_DATALEN(psock) psock_datalen(psock)
+
+u16_t psock_datalen(struct psock *psock);
+
+/**
+ * Exit the protosocket's protothread.
+ *
+ * This macro terminates the protothread of the protosocket and should
+ * almost always be used in conjunction with PSOCK_CLOSE().
+ *
+ * \sa PSOCK_CLOSE_EXIT()
+ *
+ * \param psock (struct psock *) A pointer to the protosocket.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_EXIT(psock) PT_EXIT(&((psock)->pt))
+
+/**
+ * Close a protosocket and exit the protosocket's protothread.
+ *
+ * This macro closes a protosocket and exits the protosocket's protothread.
+ *
+ * \param psock (struct psock *) A pointer to the protosocket.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_CLOSE_EXIT(psock) \
+ do { \
+ PSOCK_CLOSE(psock); \
+ PSOCK_EXIT(psock); \
+ } while(0)
+
+/**
+ * Declare the end of a protosocket's protothread.
+ *
+ * This macro is used for declaring that the protosocket's protothread
+ * ends. It must always be used together with a matching PSOCK_BEGIN()
+ * macro.
+ *
+ * \param psock (struct psock *) A pointer to the protosocket.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_END(psock) PT_END(&((psock)->pt))
+
+char psock_newdata(struct psock *s);
+
+/**
+ * Check if new data has arrived on a protosocket.
+ *
+ * This macro is used in conjunction with the PSOCK_WAIT_UNTIL()
+ * macro to check if data has arrived on a protosocket.
+ *
+ * \param psock (struct psock *) A pointer to the protosocket.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_NEWDATA(psock) psock_newdata(psock)
+
+/**
+ * Wait until a condition is true.
+ *
+ * This macro blocks the protothread until the specified condition is
+ * true. The macro PSOCK_NEWDATA() can be used to check if new data
+ * arrives when the protosocket is waiting.
+ *
+ * Typically, this macro is used as follows:
+ *
+ \code
+ PT_THREAD(thread(struct psock *s, struct timer *t))
+ {
+ PSOCK_BEGIN(s);
+
+ PSOCK_WAIT_UNTIL(s, PSOCK_NEWADATA(s) || timer_expired(t));
+
+ if(PSOCK_NEWDATA(s)) {
+ PSOCK_READTO(s, '\n');
+ } else {
+ handle_timed_out(s);
+ }
+
+ PSOCK_END(s);
+ }
+ \endcode
+ *
+ * \param psock (struct psock *) A pointer to the protosocket.
+ * \param condition The condition to wait for.
+ *
+ * \hideinitializer
+ */
+#define PSOCK_WAIT_UNTIL(psock, condition) \
+ PT_WAIT_UNTIL(&((psock)->pt), (condition));
+
+#define PSOCK_WAIT_THREAD(psock, condition) \
+ PT_WAIT_THREAD(&((psock)->pt), (condition))
+
+#endif /* __PSOCK_H__ */
+
+/** @} */
diff --git a/Libraries/WiShield/pt.h b/Libraries/WiShield/pt.h
new file mode 100644
index 0000000..9f1f64d
--- /dev/null
+++ b/Libraries/WiShield/pt.h
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: pt.h,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+
+/**
+ * \addtogroup pt
+ * @{
+ */
+
+/**
+ * \file
+ * Protothreads implementation.
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifndef __PT_H__
+#define __PT_H__
+
+#include "lc.h"
+
+struct pt {
+ lc_t lc;
+};
+
+#define PT_WAITING 0
+#define PT_EXITED 1
+#define PT_ENDED 2
+#define PT_YIELDED 3
+
+/**
+ * \name Initialization
+ * @{
+ */
+
+/**
+ * Initialize a protothread.
+ *
+ * Initializes a protothread. Initialization must be done prior to
+ * starting to execute the protothread.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \sa PT_SPAWN()
+ *
+ * \hideinitializer
+ */
+#define PT_INIT(pt) LC_INIT((pt)->lc)
+
+/** @} */
+
+/**
+ * \name Declaration and definition
+ * @{
+ */
+
+/**
+ * Declaration of a protothread.
+ *
+ * This macro is used to declare a protothread. All protothreads must
+ * be declared with this macro.
+ *
+ * \param name_args The name and arguments of the C function
+ * implementing the protothread.
+ *
+ * \hideinitializer
+ */
+#define PT_THREAD(name_args) char name_args
+
+/**
+ * Declare the start of a protothread inside the C function
+ * implementing the protothread.
+ *
+ * This macro is used to declare the starting point of a
+ * protothread. It should be placed at the start of the function in
+ * which the protothread runs. All C statements above the PT_BEGIN()
+ * invokation will be executed each time the protothread is scheduled.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc)
+
+/**
+ * Declare the end of a protothread.
+ *
+ * This macro is used for declaring that a protothread ends. It must
+ * always be used together with a matching PT_BEGIN() macro.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \
+ PT_INIT(pt); return PT_ENDED; }
+
+/** @} */
+
+/**
+ * \name Blocked wait
+ * @{
+ */
+
+/**
+ * Block and wait until condition is true.
+ *
+ * This macro blocks the protothread until the specified condition is
+ * true.
+ *
+ * \param pt A pointer to the protothread control structure.
+ * \param condition The condition.
+ *
+ * \hideinitializer
+ */
+#define PT_WAIT_UNTIL(pt, condition) \
+ do { \
+ LC_SET((pt)->lc); \
+ if(!(condition)) { \
+ return PT_WAITING; \
+ } \
+ } while(0)
+
+/**
+ * Block and wait while condition is true.
+ *
+ * This function blocks and waits while condition is true. See
+ * PT_WAIT_UNTIL().
+ *
+ * \param pt A pointer to the protothread control structure.
+ * \param cond The condition.
+ *
+ * \hideinitializer
+ */
+#define PT_WAIT_WHILE(pt, cond) PT_WAIT_UNTIL((pt), !(cond))
+
+/** @} */
+
+/**
+ * \name Hierarchical protothreads
+ * @{
+ */
+
+/**
+ * Block and wait until a child protothread completes.
+ *
+ * This macro schedules a child protothread. The current protothread
+ * will block until the child protothread completes.
+ *
+ * \note The child protothread must be manually initialized with the
+ * PT_INIT() function before this function is used.
+ *
+ * \param pt A pointer to the protothread control structure.
+ * \param thread The child protothread with arguments
+ *
+ * \sa PT_SPAWN()
+ *
+ * \hideinitializer
+ */
+#define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread))
+
+/**
+ * Spawn a child protothread and wait until it exits.
+ *
+ * This macro spawns a child protothread and waits until it exits. The
+ * macro can only be used within a protothread.
+ *
+ * \param pt A pointer to the protothread control structure.
+ * \param child A pointer to the child protothread's control structure.
+ * \param thread The child protothread with arguments
+ *
+ * \hideinitializer
+ */
+#define PT_SPAWN(pt, child, thread) \
+ do { \
+ PT_INIT((child)); \
+ PT_WAIT_THREAD((pt), (thread)); \
+ } while(0)
+
+/** @} */
+
+/**
+ * \name Exiting and restarting
+ * @{
+ */
+
+/**
+ * Restart the protothread.
+ *
+ * This macro will block and cause the running protothread to restart
+ * its execution at the place of the PT_BEGIN() call.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_RESTART(pt) \
+ do { \
+ PT_INIT(pt); \
+ return PT_WAITING; \
+ } while(0)
+
+/**
+ * Exit the protothread.
+ *
+ * This macro causes the protothread to exit. If the protothread was
+ * spawned by another protothread, the parent protothread will become
+ * unblocked and can continue to run.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_EXIT(pt) \
+ do { \
+ PT_INIT(pt); \
+ return PT_EXITED; \
+ } while(0)
+
+/** @} */
+
+/**
+ * \name Calling a protothread
+ * @{
+ */
+
+/**
+ * Schedule a protothread.
+ *
+ * This function shedules a protothread. The return value of the
+ * function is non-zero if the protothread is running or zero if the
+ * protothread has exited.
+ *
+ * \param f The call to the C function implementing the protothread to
+ * be scheduled
+ *
+ * \hideinitializer
+ */
+#define PT_SCHEDULE(f) ((f) == PT_WAITING)
+
+/** @} */
+
+/**
+ * \name Yielding from a protothread
+ * @{
+ */
+
+/**
+ * Yield from the current protothread.
+ *
+ * This function will yield the protothread, thereby allowing other
+ * processing to take place in the system.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_YIELD(pt) \
+ do { \
+ PT_YIELD_FLAG = 0; \
+ LC_SET((pt)->lc); \
+ if(PT_YIELD_FLAG == 0) { \
+ return PT_YIELDED; \
+ } \
+ } while(0)
+
+/**
+ * \brief Yield from the protothread until a condition occurs.
+ * \param pt A pointer to the protothread control structure.
+ * \param cond The condition.
+ *
+ * This function will yield the protothread, until the
+ * specified condition evaluates to true.
+ *
+ *
+ * \hideinitializer
+ */
+#define PT_YIELD_UNTIL(pt, cond) \
+ do { \
+ PT_YIELD_FLAG = 0; \
+ LC_SET((pt)->lc); \
+ if((PT_YIELD_FLAG == 0) || !(cond)) { \
+ return PT_YIELDED; \
+ } \
+ } while(0)
+
+/** @} */
+
+#endif /* __PT_H__ */
+
+/** @} */
diff --git a/Libraries/WiShield/request.cpp b/Libraries/WiShield/request.cpp
new file mode 100644
index 0000000..8841820
--- /dev/null
+++ b/Libraries/WiShield/request.cpp
@@ -0,0 +1,104 @@
+/******************************************************************************
+
+ Filename: request.cpp
+ Description: Request code for the WiServer library
+
+ ******************************************************************************
+
+ Copyright(c) 2009 Mark A. Patel All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ Mark A. Patel 06/20/2009 Initial version
+
+
+ *****************************************************************************/
+
+#include "WiServer.h"
+
+#ifdef ENABLE_CLIENT_MODE
+
+// IP, host name and URL for the TWEET class
+uint8 twitterIP[] = {128, 121, 146, 100};
+char twitterHost[] = {"twitter.com"};
+char twitterURL[] = {"/statuses/update.xml"};
+
+
+GETrequest::GETrequest(uint8* ipAddr, int port, char* hostName, char* URL) {
+ // Store IP address using the uIP type
+ uip_ipaddr(this->ipAddr, ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3]);
+ // Store port in network order
+ this->port = htons(port);
+ // Store host name and URL
+ this->hostName = hostName;
+ this->URL = URL;
+
+ // Set remaining members to NULL
+ this->auth = NULL;
+ this->returnFunc = NULL;
+ this->active = false;
+ this->body = NULL;
+ this->bodyPreamble = NULL;
+ this->next = NULL;
+}
+
+void GETrequest::setReturnFunc(returnFunction func) {
+ if (!this->active) this->returnFunc = func;
+}
+
+void GETrequest::setAuth(char* auth) {
+ if (!this->active) this->auth = auth;
+}
+
+void GETrequest::setURL(char* URL) {
+ if (!this->active) this->URL = URL;
+}
+
+void GETrequest::submit() {
+ // Ignore submit request if already active
+ if (!this->active) WiServer.submitRequest(this);
+}
+
+boolean GETrequest::isActive() {
+ return this->active;
+}
+
+
+
+
+POSTrequest::POSTrequest(uint8* ipAddr, int port, char* hostName, char* URL, bodyFunction body) :
+ // Create a request with the IP, port, host name and URL
+ GETrequest (ipAddr, port, hostName, URL) {
+ // Set the body callback function
+ this->body = body;
+}
+
+void POSTrequest::setBodyFunc(bodyFunction body) {
+ if (!this->active) this->body = body;
+}
+
+TWEETrequest::TWEETrequest(char* auth, bodyFunction message) :
+ // Create a POST request with the Twitter-specific data
+ POSTrequest (twitterIP, 80, twitterHost, twitterURL, message) {
+ // Set the auth string
+ this->auth = auth;
+ // Automatically insert 'status=' before calling the body function
+ this->bodyPreamble = (char*)"status=";
+}
+
+#endif // ENABLE_CLIENT_MODE
diff --git a/Libraries/WiShield/server.h b/Libraries/WiShield/server.h
new file mode 100644
index 0000000..80ee3e9
--- /dev/null
+++ b/Libraries/WiShield/server.h
@@ -0,0 +1,69 @@
+/******************************************************************************
+
+ Filename: server.h
+ Description: Private header file for WiServer
+
+ ******************************************************************************
+
+ Copyright(c) 2009 Mark A. Patel All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ Mark A. Patel 06/10/2009 Initial version
+
+ *****************************************************************************/
+
+#ifndef __SERVER_H__
+#define __SERVER_H__
+
+#include <avr/pgmspace.h>
+#include <uip-conf.h>
+
+#ifdef APP_WISERVER
+
+// Enables client mode (i.e. for sending Tweets and HTTP POST or GET requests)
+// Comment out this #define if client mode isn't required
+// (it'll save a bunch of code size and a bit of RAM too!)
+#define ENABLE_CLIENT_MODE
+
+// If DEBUG is defined, the Serial class is used to output lots of diagnostic data
+// (verbose mode is also enabled automatically)
+// Warning: this increases RAM usage and code size and will slow execution speed
+//#define DEBUG
+
+
+// Declare the server's uip callback function
+void server_app_task();
+
+#define UIP_APPCALL server_app_task
+
+/*
+ * Stores the state for a single connection
+ */
+struct conn_state {
+ int ackedCount; // Number of bytes sent and acked
+ int sentCount; // Number of bytes awaiting an ack
+ char* cursor; // Virtual cursor for write operations
+ void* request; // Points to a char* URL (server mode) or a request object (client mode)
+};
+
+typedef struct conn_state uip_tcp_appstate_t;
+
+#endif /* APP_WISERVER */
+
+#endif //__SERVER_H__
diff --git a/Libraries/WiShield/socketapp.h b/Libraries/WiShield/socketapp.h
new file mode 100644
index 0000000..f29022f
--- /dev/null
+++ b/Libraries/WiShield/socketapp.h
@@ -0,0 +1,62 @@
+
+/******************************************************************************
+
+ Filename: socketapp.h
+ Description: Simple socket programming example for the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 06/06/2009 Initial version
+
+ *****************************************************************************/
+
+#ifndef __SOCKET_APP_H__
+#define __SOCKET_APP_H__
+
+/* Since this file will be included by uip.h, we cannot include uip.h
+ here. But we might need to include uipopt.h if we need the u8_t and
+ u16_t datatypes. */
+#include "uipopt.h"
+#include "psock.h"
+
+/* Next, we define the uip_tcp_appstate_t datatype. This is the state
+ of our application, and the memory required for this state is
+ allocated together with each TCP connection. One application state
+ for each TCP connection. */
+typedef struct socket_app_state {
+ struct psock p;
+ char inputbuffer[20];
+ char name[20];
+} uip_tcp_appstate_t;
+
+/* Finally we define the application function to be called by uIP. */
+void socket_app_appcall(void);
+#ifndef UIP_APPCALL
+#define UIP_APPCALL socket_app_appcall
+#endif /* UIP_APPCALL */
+
+void socket_app_init(void);
+
+#endif /* __SOCKET_APP_H__ */
diff --git a/Libraries/WiShield/spi.h b/Libraries/WiShield/spi.h
new file mode 100644
index 0000000..77dcfcc
--- /dev/null
+++ b/Libraries/WiShield/spi.h
@@ -0,0 +1,167 @@
+
+/******************************************************************************
+
+ Filename: spi.h
+ Description: SPI bus configuration for the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/01/2009 Initial version
+ AsyncLabs 05/29/2009 Adding support for new library
+
+ *****************************************************************************/
+
+#ifndef SPI_H_
+#define SPI_H_
+
+// Uncomment one line below to
+// specify which Arduino pin
+// to use as WiShield interrupt
+#define USE_DIG0_INTR // use digital pin 0
+//#define USE_DIG8_INTR // use digital pin 8
+
+
+#ifdef USE_DIG0_INTR
+#define ZG2100_ISR_DISABLE() (EIMSK &= ~(0x01))
+#define ZG2100_ISR_ENABLE() (EIMSK |= 0x01)
+#define ZG2100_ISR_GET(X) (X = EIMSK)
+#define ZG2100_ISR_SET(X) (EIMSK = X)
+#endif
+
+#ifdef USE_DIG8_INTR
+#define ZG2100_ISR_DISABLE() (PCMSK0 &= ~(0x01))
+#define ZG2100_ISR_ENABLE() (PCMSK0 |= 0x01)
+#define ZG2100_ISR_GET(X) (X = PCMSK0)
+#define ZG2100_ISR_SET(X) (PCMSK0 = X)
+#endif
+
+//AVR Mega168 SPI HAL
+#define BIT0 0x01
+#define BIT1 0x02
+#define BIT2 0x04
+#define BIT3 0x08
+#define BIT4 0x10
+#define BIT5 0x20
+#define BIT6 0x40
+#define BIT7 0x80
+
+#ifdef USE_DIG8_INTR
+#define ZG2100_INTR BIT0
+#endif
+
+#define SPI0_SS_BIT BIT2
+#define SPI0_SS_DDR DDRB
+#define SPI0_SS_PORT PORTB
+
+#define SPI0_SCLK_BIT BIT5
+#define SPI0_SCLK_DDR DDRB
+#define SPI0_SCLK_PORT PORTB
+
+#define SPI0_MOSI_BIT BIT3
+#define SPI0_MOSI_DDR DDRB
+#define SPI0_MOSI_PORT PORTB
+
+#define SPI0_MISO_BIT BIT4
+#define SPI0_MISO_DDR DDRB
+#define SPI0_MISO_PORT PORTB
+
+
+#define SPI0_WaitForReceive()
+#define SPI0_RxData() (SPDR)
+
+#define SPI0_TxData(Data) (SPDR = Data)
+#define SPI0_WaitForSend() while( (SPSR & 0x80)==0x00 )
+
+#define SPI0_SendByte(Data) SPI0_TxData(Data);SPI0_WaitForSend()
+#define SPI0_RecvBute() SPI0_RxData()
+
+// PB4(MISO), PB3(MOSI), PB5(SCK), PB2(/SS) // CS=1, waiting for SPI start // SPI mode 0, 8MHz
+#ifdef USE_DIG8_INTR
+#define SPI0_Init() DDRB |= SPI0_SS_BIT|SPI0_SCLK_BIT|SPI0_MOSI_BIT|LEDConn_BIT;\
+ DDRB &= ~(SPI0_MISO_BIT|ZG2100_INTR);\
+ PORTB = SPI0_SS_BIT;\
+ SPCR = 0x50;\
+ SPSR = 0x01
+#else
+#define SPI0_Init() DDRB |= SPI0_SS_BIT|SPI0_SCLK_BIT|SPI0_MOSI_BIT|LEDConn_BIT;\
+ DDRB &= ~SPI0_MISO_BIT;\
+ PORTB = SPI0_SS_BIT;\
+ SPCR = 0x50;\
+ SPSR = 0x01
+#endif
+
+//ZG2100 SPI HAL
+#define ZG2100_SpiInit SPI0_Init
+#define ZG2100_SpiSendData SPI0_SendByte
+#define ZG2100_SpiRecvData SPI0_RxData
+
+
+#define ZG2100_CS_BIT BIT2
+#define ZG2100_CS_DDR DDRB
+#define ZG2100_CS_PORT PORTB
+
+#define ZG2100_CSInit() (ZG2100_CS_DDR |= ZG2100_CS_BIT)
+#define ZG2100_CSon() (ZG2100_CS_PORT |= ZG2100_CS_BIT)
+#define ZG2100_CSoff() (ZG2100_CS_PORT &= ~ZG2100_CS_BIT)
+
+#define LEDConn_BIT BIT1
+#define LEDConn_DDR DDRB
+#define LEDConn_PORT PORTB
+
+#define LED0_BIT BIT0
+#define LED0_DDR DDRC
+#define LED0_PORT PORTC
+
+#define LED1_BIT BIT1
+#define LED1_DDR DDRC
+#define LED1_PORT PORTC
+
+#define LED2_BIT BIT2
+#define LED2_DDR DDRC
+#define LED2_PORT PORTC
+
+#define LED3_BIT BIT3
+#define LED3_DDR DDRC
+#define LED3_PORT PORTC
+
+#define LED_Init() (DDRC |= LED0_BIT | LED1_BIT | LED2_BIT | LED3_BIT)
+
+#define LEDConn_on() (LEDConn_PORT |= LEDConn_BIT)
+#define LED0_on() (LED0_PORT |= LED0_BIT)
+#define LED1_on() (LED0_PORT |= LED1_BIT)
+#define LED2_on() (LED0_PORT |= LED2_BIT)
+#define LED3_on() (LED0_PORT |= LED3_BIT)
+
+#define LEDConn_off() (LEDConn_PORT &= ~LEDConn_BIT)
+#define LED0_off() (LED0_PORT &= ~LED0_BIT)
+#define LED1_off() (LED0_PORT &= ~LED1_BIT)
+#define LED2_off() (LED0_PORT &= ~LED2_BIT)
+#define LED3_off() (LED0_PORT &= ~LED3_BIT)
+
+#define LED0_toggle() ((LED0_PORT & LED0_BIT)?(LED0_PORT &= ~LED0_BIT):(LED0_PORT |= LED0_BIT))
+#define LED1_toggle() ((LED0_PORT & LED1_BIT)?(LED0_PORT &= ~LED1_BIT):(LED0_PORT |= LED1_BIT))
+#define LED3_toggle() ((LED0_PORT & LED3_BIT)?(LED0_PORT &= ~LED3_BIT):(LED0_PORT |= LED3_BIT))
+
+#endif /* SPI_H_ */
diff --git a/Libraries/WiShield/stack.c b/Libraries/WiShield/stack.c
new file mode 100644
index 0000000..85675f5
--- /dev/null
+++ b/Libraries/WiShield/stack.c
@@ -0,0 +1,165 @@
+
+/******************************************************************************
+
+ Filename: stack.c
+ Description: Stack process for the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/29/2009 Initial version
+
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <avr/io.h>
+
+#include "timer.h"
+#include "global-conf.h"
+#include "uip_arp.h"
+#include "network.h"
+#include "witypes.h"
+#include "config.h"
+#include "g2100.h"
+#include "spi.h"
+
+#include <string.h>
+#define BUF ((struct uip_eth_hdr *)&uip_buf[0])
+
+static struct timer periodic_timer, arp_timer, self_arp_timer;
+
+void stack_init(void)
+{
+ uip_ipaddr_t ipaddr;
+
+ struct uip_eth_addr mac;
+
+ U8* mac_addr = zg_get_mac();
+
+ mac.addr[0] = mac_addr[0];
+ mac.addr[1] = mac_addr[1];
+ mac.addr[2] = mac_addr[2];
+ mac.addr[3] = mac_addr[3];
+ mac.addr[4] = mac_addr[4];
+ mac.addr[5] = mac_addr[5];
+
+ timer_set(&periodic_timer, CLOCK_SECOND / 2);
+ timer_set(&arp_timer, CLOCK_SECOND * 10);
+ timer_set(&self_arp_timer, CLOCK_SECOND * 30);
+
+ uip_init();
+
+ uip_setethaddr(mac);
+
+#ifdef APP_WEBSERVER
+ webserver_init();
+#endif
+
+#ifdef APP_WEBCLIENT
+ webclient_init();
+#endif
+
+#ifdef APP_SOCKAPP
+ socket_app_init();
+#endif
+
+#ifdef APP_UDPAPP
+ udpapp_init();
+#endif
+
+ uip_ipaddr(ipaddr, local_ip[0], local_ip[1], local_ip[2], local_ip[3]);
+ uip_sethostaddr(ipaddr);
+ uip_ipaddr(ipaddr, gateway_ip[0],gateway_ip[1],gateway_ip[2],gateway_ip[3]);
+ uip_setdraddr(ipaddr);
+ uip_ipaddr(ipaddr, subnet_mask[0],subnet_mask[1],subnet_mask[2],subnet_mask[3]);
+ uip_setnetmask(ipaddr);
+}
+
+void stack_process(void)
+{
+ int i;
+
+ uip_len = network_read();
+
+ if(uip_len > 0) {
+ if(BUF->type == htons(UIP_ETHTYPE_IP)){
+ uip_arp_ipin();
+ uip_input();
+ if(uip_len > 0) {
+ uip_arp_out();
+ network_send();
+ }
+ }else if(BUF->type == htons(UIP_ETHTYPE_ARP)){
+ uip_arp_arpin();
+ if(uip_len > 0){
+ network_send();
+ }
+ }
+
+ }else if(timer_expired(&periodic_timer)) {
+ timer_reset(&periodic_timer);
+
+ for(i = 0; i < UIP_CONNS; i++) {
+ uip_periodic(i);
+ if(uip_len > 0) {
+ uip_arp_out();
+ network_send();
+ }
+ }
+
+#if UIP_UDP
+ //GregEigsti - added to get UIP_APPCALL polling working for UDP
+ for(i = 0; i < UIP_UDP_CONNS; i++) {
+ uip_udp_periodic(i);
+ if(uip_len > 0) {
+ uip_arp_out();
+ network_send();
+ }
+ }
+ //GregEigsti - added to get UIP_APPCALL polling working for UDP
+#endif /* UIP_UDP */
+
+ // if nothing to TX and the self ARP timer expired
+ // TX a broadcast ARP reply. This was implemented to
+ // cause periodic TX to prevent the AP from disconnecting
+ // us from the network
+ if (uip_len == 0 && timer_expired(&self_arp_timer)) {
+ timer_reset(&self_arp_timer);
+ uip_self_arp_out();
+ network_send();
+ }
+
+ if(timer_expired(&arp_timer)) {
+ timer_reset(&arp_timer);
+ uip_arp_timer();
+ }
+ }
+ return;
+}
+
+void uip_log(char *m)
+{
+ //TODO: Get debug information out here somehow, does anybody know a smart way to do that?
+}
diff --git a/Libraries/WiShield/strings.c b/Libraries/WiShield/strings.c
new file mode 100644
index 0000000..f49dec9
--- /dev/null
+++ b/Libraries/WiShield/strings.c
@@ -0,0 +1,79 @@
+/******************************************************************************
+
+ Filename: strings.c
+ Description: Contains program memory strings for the WiServer
+
+ ******************************************************************************
+
+ Copyright(c) 2009 Mark A. Patel All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ Mark A. Patel 06/10/2009 Initial version
+
+ *****************************************************************************/
+
+#include "server.h"
+#include <avr/pgmspace.h>
+
+
+// This file contains various strings used by the WiServer
+// They are stored in program memory to reduce RAM usage.
+
+// HTTP OK response
+const prog_char httpOK[] = {"HTTP/1.0 200 OK"};
+
+// HTTP Not Found response
+const prog_char httpNotFound[] = {"HTTP/1.0 404 Not Found"};
+
+
+#ifdef ENABLE_CLIENT_MODE
+
+// Trailing HTTP/1.0 for GET and POST requests
+const prog_char http10[] = {" HTTP/1.0"};
+
+// Authorization: Basic field name
+const prog_char authBasic[] = {"Authorization: Basic "};
+
+// Content-Length field name
+const prog_char contentLength[] = {"Content-Length: "};
+
+// User agent field with value
+const prog_char userAgent[] = {"User-Agent: WiServer/1.1"};
+
+// Content type form data
+const prog_char contentTypeForm[] = {"Content-Type: application/x-www-form-urlencoded"};
+
+// POST request
+const prog_char post[] = {"POST "};
+
+// GET request
+const prog_char get[] = {"GET "};
+
+// Host, User-Agent, and Content-Type lines for Twitter POSTs
+const prog_char host[] = {"Host: "};
+
+// Status prefix for Twitter
+const prog_char status[] = {"status="};
+
+/* Base64 Encoder data */
+const prog_char base64Chars[] PROGMEM = {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"};
+
+
+#endif // ENABLE_CLIENT_MODE
+
diff --git a/Libraries/WiShield/timer.c b/Libraries/WiShield/timer.c
new file mode 100644
index 0000000..74eedf6
--- /dev/null
+++ b/Libraries/WiShield/timer.c
@@ -0,0 +1,127 @@
+/**
+ * \addtogroup timer
+ * @{
+ */
+
+/**
+ * \file
+ * Timer library implementation.
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ */
+
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: timer.c,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+
+#include "clock.h"
+#include "timer.h"
+
+/*---------------------------------------------------------------------------*/
+/**
+ * Set a timer.
+ *
+ * This function is used to set a timer for a time sometime in the
+ * future. The function timer_expired() will evaluate to true after
+ * the timer has expired.
+ *
+ * \param t A pointer to the timer
+ * \param interval The interval before the timer expires.
+ *
+ */
+void
+timer_set(struct timer *t, clock_time_t interval)
+{
+ t->interval = interval;
+ t->start = clock_time();
+}
+/*---------------------------------------------------------------------------*/
+/**
+ * Reset the timer with the same interval.
+ *
+ * This function resets the timer with the same interval that was
+ * given to the timer_set() function. The start point of the interval
+ * is the exact time that the timer last expired. Therefore, this
+ * function will cause the timer to be stable over time, unlike the
+ * timer_rester() function.
+ *
+ * \param t A pointer to the timer.
+ *
+ * \sa timer_restart()
+ */
+void
+timer_reset(struct timer *t)
+{
+ t->start += t->interval;
+}
+/*---------------------------------------------------------------------------*/
+/**
+ * Restart the timer from the current point in time
+ *
+ * This function restarts a timer with the same interval that was
+ * given to the timer_set() function. The timer will start at the
+ * current time.
+ *
+ * \note A periodic timer will drift if this function is used to reset
+ * it. For preioric timers, use the timer_reset() function instead.
+ *
+ * \param t A pointer to the timer.
+ *
+ * \sa timer_reset()
+ */
+void
+timer_restart(struct timer *t)
+{
+ t->start = clock_time();
+}
+/*---------------------------------------------------------------------------*/
+/**
+ * Check if a timer has expired.
+ *
+ * This function tests if a timer has expired and returns true or
+ * false depending on its status.
+ *
+ * \param t A pointer to the timer
+ *
+ * \return Non-zero if the timer has expired, zero otherwise.
+ *
+ */
+int
+timer_expired(struct timer *t)
+{
+ return (clock_time_t)(clock_time() - t->start) >= (clock_time_t)t->interval;
+}
+/*---------------------------------------------------------------------------*/
+
+/** @} */
diff --git a/Libraries/WiShield/timer.h b/Libraries/WiShield/timer.h
new file mode 100644
index 0000000..057bea4
--- /dev/null
+++ b/Libraries/WiShield/timer.h
@@ -0,0 +1,86 @@
+/**
+ * \defgroup timer Timer library
+ *
+ * The timer library provides functions for setting, resetting and
+ * restarting timers, and for checking if a timer has expired. An
+ * application must "manually" check if its timers have expired; this
+ * is not done automatically.
+ *
+ * A timer is declared as a \c struct \c timer and all access to the
+ * timer is made by a pointer to the declared timer.
+ *
+ * \note The timer library uses the \ref clock "Clock library" to
+ * measure time. Intervals should be specified in the format used by
+ * the clock library.
+ *
+ * @{
+ */
+
+
+/**
+ * \file
+ * Timer library header file.
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ */
+
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: timer.h,v 1.3 2006/06/11 21:46:39 adam Exp $
+ */
+#ifndef __TIMER_H__
+#define __TIMER_H__
+
+#include "clock.h"
+
+/**
+ * A timer.
+ *
+ * This structure is used for declaring a timer. The timer must be set
+ * with timer_set() before it can be used.
+ *
+ * \hideinitializer
+ */
+struct timer {
+ clock_time_t start;
+ clock_time_t interval;
+};
+
+void timer_set(struct timer *t, clock_time_t interval);
+void timer_reset(struct timer *t);
+void timer_restart(struct timer *t);
+int timer_expired(struct timer *t);
+
+#endif /* __TIMER_H__ */
+
+/** @} */
diff --git a/Libraries/WiShield/udpapp.h b/Libraries/WiShield/udpapp.h
new file mode 100644
index 0000000..f127135
--- /dev/null
+++ b/Libraries/WiShield/udpapp.h
@@ -0,0 +1,71 @@
+
+/******************************************************************************
+
+ Filename: udpapp.h
+ Description: UDP app for the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 07/11/2009 Initial version
+
+ *****************************************************************************/
+
+#ifndef __UDPAPP_H__
+#define __UDPAPP_H__
+
+#include "pt.h"
+
+typedef struct socket_app_state {
+ char name;
+} uip_tcp_appstate_t;
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void dummy_app_appcall(void);
+#ifndef UIP_APPCALL
+#define UIP_APPCALL dummy_app_appcall
+#endif /* UIP_APPCALL */
+
+typedef struct udpapp_state {
+ struct pt pt;
+ char state;
+ char inputbuf[10];
+} uip_udp_appstate_t;
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void udpapp_appcall(void);
+#ifndef UIP_UDP_APPCALL
+#define UIP_UDP_APPCALL udpapp_appcall
+#endif /* UIP_UDP_APPCALL */
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void udpapp_init(void);
+
+#endif /* __UDPAPP_H__ */
diff --git a/Libraries/WiShield/uip-conf.h b/Libraries/WiShield/uip-conf.h
new file mode 100644
index 0000000..f35c895
--- /dev/null
+++ b/Libraries/WiShield/uip-conf.h
@@ -0,0 +1,146 @@
+
+/******************************************************************************
+
+ Filename: uip-conf.h
+ Description: uIP configuration file
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/29/2009 Initial port
+
+ *****************************************************************************/
+
+#ifndef __UIP_CONF_H__
+#define __UIP_CONF_H__
+
+#include <inttypes.h>
+#include <avr/io.h>
+#include <stdio.h>
+//#include <stdbool.h>
+
+/**
+ * 8 bit datatype
+ *
+ * This typedef defines the 8-bit type used throughout uIP.
+ *
+ * \hideinitializer
+ */
+typedef uint8_t u8_t;
+
+/**
+ * 16 bit datatype
+ *
+ * This typedef defines the 16-bit type used throughout uIP.
+ *
+ * \hideinitializer
+ */
+typedef uint16_t u16_t;
+
+/**
+ * Statistics datatype
+ *
+ * This typedef defines the dataype used for keeping statistics in
+ * uIP.
+ *
+ * \hideinitializer
+ */
+typedef unsigned short uip_stats_t;
+
+/**
+ * Maximum number of TCP connections.
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_MAX_CONNECTIONS 1
+
+/**
+ * Maximum number of listening TCP ports.
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_MAX_LISTENPORTS 1
+
+/**
+ * uIP buffer size.
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_BUFFER_SIZE 400
+/**
+ * CPU byte order.
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_BYTE_ORDER LITTLE_ENDIAN
+
+/**
+ * Logging on or off
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_LOGGING 0
+
+/**
+ * UDP support on or off
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_UDP 1
+
+/**
+ * UDP checksums on or off
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_UDP_CHECKSUMS 1
+
+/**
+ * uIP statistics on or off
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_STATISTICS 1
+
+/**
+ * Broadcast support.
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_BROADCAST 0
+
+/**
+ * The maximum amount of concurrent UDP connections.
+ *
+ * \hideinitializer
+ */
+#define UIP_CONF_UDP_CONNS 1
+
+//Include app configuration
+#include "apps-conf.h"
+
+#endif /* __UIP_CONF_H__ */
+
+/** @} */
+/** @} */
diff --git a/Libraries/WiShield/uip-fw.c b/Libraries/WiShield/uip-fw.c
new file mode 100644
index 0000000..01858ea
--- /dev/null
+++ b/Libraries/WiShield/uip-fw.c
@@ -0,0 +1,532 @@
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: uip-fw.c,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+/**
+ * \addtogroup uip
+ * @{
+ */
+
+/**
+ * \defgroup uipfw uIP packet forwarding
+ * @{
+ *
+ */
+
+/**
+ * \file
+ * uIP packet forwarding.
+ * \author Adam Dunkels <adam@sics.se>
+ *
+ * This file implements a number of simple functions which do packet
+ * forwarding over multiple network interfaces with uIP.
+ *
+ */
+
+#include "uip.h"
+#include "uip_arch.h"
+#include "uip-fw.h"
+
+#include <string.h> /* for memcpy() */
+
+/*
+ * The list of registered network interfaces.
+ */
+static struct uip_fw_netif *netifs = NULL;
+
+/*
+ * A pointer to the default network interface.
+ */
+static struct uip_fw_netif *defaultnetif = NULL;
+
+struct tcpip_hdr {
+ /* IP header. */
+ u8_t vhl,
+ tos;
+ u16_t len,
+ ipid,
+ ipoffset;
+ u8_t ttl,
+ proto;
+ u16_t ipchksum;
+ u16_t srcipaddr[2],
+ destipaddr[2];
+
+ /* TCP header. */
+ u16_t srcport,
+ destport;
+ u8_t seqno[4],
+ ackno[4],
+ tcpoffset,
+ flags,
+ wnd[2];
+ u16_t tcpchksum;
+ u8_t urgp[2];
+ u8_t optdata[4];
+};
+
+struct icmpip_hdr {
+ /* IP header. */
+ u8_t vhl,
+ tos,
+ len[2],
+ ipid[2],
+ ipoffset[2],
+ ttl,
+ proto;
+ u16_t ipchksum;
+ u16_t srcipaddr[2],
+ destipaddr[2];
+ /* ICMP (echo) header. */
+ u8_t type, icode;
+ u16_t icmpchksum;
+ u16_t id, seqno;
+ u8_t payload[1];
+};
+
+/* ICMP ECHO. */
+#define ICMP_ECHO 8
+
+/* ICMP TIME-EXCEEDED. */
+#define ICMP_TE 11
+
+/*
+ * Pointer to the TCP/IP headers of the packet in the uip_buf buffer.
+ */
+#define BUF ((struct tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
+
+/*
+ * Pointer to the ICMP/IP headers of the packet in the uip_buf buffer.
+ */
+#define ICMPBUF ((struct icmpip_hdr *)&uip_buf[UIP_LLH_LEN])
+
+/*
+ * Certain fields of an IP packet that are used for identifying
+ * duplicate packets.
+ */
+struct fwcache_entry {
+ u16_t timer;
+
+ u16_t srcipaddr[2];
+ u16_t destipaddr[2];
+ u16_t ipid;
+ u8_t proto;
+ u8_t unused;
+
+#if notdef
+ u16_t payload[2];
+#endif
+
+#if UIP_REASSEMBLY > 0
+ u16_t len, offset;
+#endif
+};
+
+/*
+ * The number of packets to remember when looking for duplicates.
+ */
+#ifdef UIP_CONF_FWCACHE_SIZE
+#define FWCACHE_SIZE UIP_CONF_FWCACHE_SIZE
+#else
+#define FWCACHE_SIZE 2
+#endif
+
+
+/*
+ * A cache of packet header fields which are used for
+ * identifying duplicate packets.
+ */
+static struct fwcache_entry fwcache[FWCACHE_SIZE];
+
+/**
+ * \internal
+ * The time that a packet cache is active.
+ */
+#define FW_TIME 20
+
+/*------------------------------------------------------------------------------*/
+/**
+ * Initialize the uIP packet forwarding module.
+ */
+/*------------------------------------------------------------------------------*/
+void
+uip_fw_init(void)
+{
+ struct uip_fw_netif *t;
+ defaultnetif = NULL;
+ while(netifs != NULL) {
+ t = netifs;
+ netifs = netifs->next;
+ t->next = NULL;
+ }
+}
+/*------------------------------------------------------------------------------*/
+/**
+ * \internal
+ * Check if an IP address is within the network defined by an IP
+ * address and a netmask.
+ *
+ * \param ipaddr The IP address to be checked.
+ * \param netipaddr The IP address of the network.
+ * \param netmask The netmask of the network.
+ *
+ * \return Non-zero if IP address is in network, zero otherwise.
+ */
+/*------------------------------------------------------------------------------*/
+static unsigned char
+ipaddr_maskcmp(u16_t *ipaddr, u16_t *netipaddr, u16_t *netmask)
+{
+ return (ipaddr[0] & netmask [0]) == (netipaddr[0] & netmask[0]) &&
+ (ipaddr[1] & netmask[1]) == (netipaddr[1] & netmask[1]);
+}
+/*------------------------------------------------------------------------------*/
+/**
+ * \internal
+ * Send out an ICMP TIME-EXCEEDED message.
+ *
+ * This function replaces the packet in the uip_buf buffer with the
+ * ICMP packet.
+ */
+/*------------------------------------------------------------------------------*/
+static void
+time_exceeded(void)
+{
+ u16_t tmp16;
+
+ /* We don't send out ICMP errors for ICMP messages. */
+ if(ICMPBUF->proto == UIP_PROTO_ICMP) {
+ uip_len = 0;
+ return;
+ }
+ /* Copy fields from packet header into payload of this ICMP packet. */
+ memcpy(&(ICMPBUF->payload[0]), ICMPBUF, 28);
+
+ /* Set the ICMP type and code. */
+ ICMPBUF->type = ICMP_TE;
+ ICMPBUF->icode = 0;
+
+ /* Calculate the ICMP checksum. */
+ ICMPBUF->icmpchksum = 0;
+ ICMPBUF->icmpchksum = ~uip_chksum((u16_t *)&(ICMPBUF->type), 36);
+
+ /* Set the IP destination address to be the source address of the
+ original packet. */
+ tmp16= BUF->destipaddr[0];
+ BUF->destipaddr[0] = BUF->srcipaddr[0];
+ BUF->srcipaddr[0] = tmp16;
+ tmp16 = BUF->destipaddr[1];
+ BUF->destipaddr[1] = BUF->srcipaddr[1];
+ BUF->srcipaddr[1] = tmp16;
+
+ /* Set our IP address as the source address. */
+ BUF->srcipaddr[0] = uip_hostaddr[0];
+ BUF->srcipaddr[1] = uip_hostaddr[1];
+
+ /* The size of the ICMP time exceeded packet is 36 + the size of the
+ IP header (20) = 56. */
+ uip_len = 56;
+ ICMPBUF->len[0] = 0;
+ ICMPBUF->len[1] = uip_len;
+
+ /* Fill in the other fields in the IP header. */
+ ICMPBUF->vhl = 0x45;
+ ICMPBUF->tos = 0;
+ ICMPBUF->ipoffset[0] = ICMPBUF->ipoffset[1] = 0;
+ ICMPBUF->ttl = UIP_TTL;
+ ICMPBUF->proto = UIP_PROTO_ICMP;
+
+ /* Calculate IP checksum. */
+ ICMPBUF->ipchksum = 0;
+ ICMPBUF->ipchksum = ~(uip_ipchksum());
+
+
+}
+/*------------------------------------------------------------------------------*/
+/**
+ * \internal
+ * Register a packet in the forwarding cache so that it won't be
+ * forwarded again.
+ */
+/*------------------------------------------------------------------------------*/
+static void
+fwcache_register(void)
+{
+ struct fwcache_entry *fw;
+ int i, oldest;
+
+ oldest = FW_TIME;
+ fw = NULL;
+
+ /* Find the oldest entry in the cache. */
+ for(i = 0; i < FWCACHE_SIZE; ++i) {
+ if(fwcache[i].timer == 0) {
+ fw = &fwcache[i];
+ break;
+ } else if(fwcache[i].timer <= oldest) {
+ fw = &fwcache[i];
+ oldest = fwcache[i].timer;
+ }
+ }
+
+ fw->timer = FW_TIME;
+ fw->ipid = BUF->ipid;
+ fw->srcipaddr[0] = BUF->srcipaddr[0];
+ fw->srcipaddr[1] = BUF->srcipaddr[1];
+ fw->destipaddr[0] = BUF->destipaddr[0];
+ fw->destipaddr[1] = BUF->destipaddr[1];
+ fw->proto = BUF->proto;
+#if notdef
+ fw->payload[0] = BUF->srcport;
+ fw->payload[1] = BUF->destport;
+#endif
+#if UIP_REASSEMBLY > 0
+ fw->len = BUF->len;
+ fw->offset = BUF->ipoffset;
+#endif
+}
+/*------------------------------------------------------------------------------*/
+/**
+ * \internal
+ * Find a network interface for the IP packet in uip_buf.
+ */
+/*------------------------------------------------------------------------------*/
+static struct uip_fw_netif *
+find_netif(void)
+{
+ struct uip_fw_netif *netif;
+
+ /* Walk through every network interface to check for a match. */
+ for(netif = netifs; netif != NULL; netif = netif->next) {
+ if(ipaddr_maskcmp(BUF->destipaddr, netif->ipaddr,
+ netif->netmask)) {
+ /* If there was a match, we break the loop. */
+ return netif;
+ }
+ }
+
+ /* If no matching netif was found, we use default netif. */
+ return defaultnetif;
+}
+/*------------------------------------------------------------------------------*/
+/**
+ * Output an IP packet on the correct network interface.
+ *
+ * The IP packet should be present in the uip_buf buffer and its
+ * length in the global uip_len variable.
+ *
+ * \retval UIP_FW_ZEROLEN Indicates that a zero-length packet
+ * transmission was attempted and that no packet was sent.
+ *
+ * \retval UIP_FW_NOROUTE No suitable network interface could be found
+ * for the outbound packet, and the packet was not sent.
+ *
+ * \return The return value from the actual network interface output
+ * function is passed unmodified as a return value.
+ */
+/*------------------------------------------------------------------------------*/
+u8_t
+uip_fw_output(void)
+{
+ struct uip_fw_netif *netif;
+
+ if(uip_len == 0) {
+ return UIP_FW_ZEROLEN;
+ }
+
+ fwcache_register();
+
+#if UIP_BROADCAST
+ /* Link local broadcasts go out on all interfaces. */
+ if(/*BUF->proto == UIP_PROTO_UDP &&*/
+ BUF->destipaddr[0] == 0xffff &&
+ BUF->destipaddr[1] == 0xffff) {
+ if(defaultnetif != NULL) {
+ defaultnetif->output();
+ }
+ for(netif = netifs; netif != NULL; netif = netif->next) {
+ netif->output();
+ }
+ return UIP_FW_OK;
+ }
+#endif /* UIP_BROADCAST */
+
+ netif = find_netif();
+ /* printf("uip_fw_output: netif %p ->output %p len %d\n", netif,
+ netif->output,
+ uip_len);*/
+
+ if(netif == NULL) {
+ return UIP_FW_NOROUTE;
+ }
+ /* If we now have found a suitable network interface, we call its
+ output function to send out the packet. */
+ return netif->output();
+}
+/*------------------------------------------------------------------------------*/
+/**
+ * Forward an IP packet in the uip_buf buffer.
+ *
+ *
+ *
+ * \return UIP_FW_FORWARDED if the packet was forwarded, UIP_FW_LOCAL if
+ * the packet should be processed locally.
+ */
+/*------------------------------------------------------------------------------*/
+u8_t
+uip_fw_forward(void)
+{
+ struct fwcache_entry *fw;
+
+ /* First check if the packet is destined for ourselves and return 0
+ to indicate that the packet should be processed locally. */
+ if(BUF->destipaddr[0] == uip_hostaddr[0] &&
+ BUF->destipaddr[1] == uip_hostaddr[1]) {
+ return UIP_FW_LOCAL;
+ }
+
+ /* If we use ping IP address configuration, and our IP address is
+ not yet configured, we should intercept all ICMP echo packets. */
+#if UIP_PINGADDRCONF
+ if((uip_hostaddr[0] | uip_hostaddr[1]) == 0 &&
+ BUF->proto == UIP_PROTO_ICMP &&
+ ICMPBUF->type == ICMP_ECHO) {
+ return UIP_FW_LOCAL;
+ }
+#endif /* UIP_PINGADDRCONF */
+
+ /* Check if the packet is in the forwarding cache already, and if so
+ we drop it. */
+
+ for(fw = fwcache; fw < &fwcache[FWCACHE_SIZE]; ++fw) {
+ if(fw->timer != 0 &&
+#if UIP_REASSEMBLY > 0
+ fw->len == BUF->len &&
+ fw->offset == BUF->ipoffset &&
+#endif
+ fw->ipid == BUF->ipid &&
+ fw->srcipaddr[0] == BUF->srcipaddr[0] &&
+ fw->srcipaddr[1] == BUF->srcipaddr[1] &&
+ fw->destipaddr[0] == BUF->destipaddr[0] &&
+ fw->destipaddr[1] == BUF->destipaddr[1] &&
+#if notdef
+ fw->payload[0] == BUF->srcport &&
+ fw->payload[1] == BUF->destport &&
+#endif
+ fw->proto == BUF->proto) {
+ /* Drop packet. */
+ return UIP_FW_FORWARDED;
+ }
+ }
+
+ /* If the TTL reaches zero we produce an ICMP time exceeded message
+ in the uip_buf buffer and forward that packet back to the sender
+ of the packet. */
+ if(BUF->ttl <= 1) {
+ /* No time exceeded for broadcasts and multicasts! */
+ if(BUF->destipaddr[0] == 0xffff && BUF->destipaddr[1] == 0xffff) {
+ return UIP_FW_LOCAL;
+ }
+ time_exceeded();
+ }
+
+ /* Decrement the TTL (time-to-live) value in the IP header */
+ BUF->ttl = BUF->ttl - 1;
+
+ /* Update the IP checksum. */
+ if(BUF->ipchksum >= HTONS(0xffff - 0x0100)) {
+ BUF->ipchksum = BUF->ipchksum + HTONS(0x0100) + 1;
+ } else {
+ BUF->ipchksum = BUF->ipchksum + HTONS(0x0100);
+ }
+
+ if(uip_len > 0) {
+ uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN];
+ uip_fw_output();
+ }
+
+#if UIP_BROADCAST
+ if(BUF->destipaddr[0] == 0xffff && BUF->destipaddr[1] == 0xffff) {
+ return UIP_FW_LOCAL;
+ }
+#endif /* UIP_BROADCAST */
+
+ /* Return non-zero to indicate that the packet was forwarded and that no
+ other processing should be made. */
+ return UIP_FW_FORWARDED;
+}
+/*------------------------------------------------------------------------------*/
+/**
+ * Register a network interface with the forwarding module.
+ *
+ * \param netif A pointer to the network interface that is to be
+ * registered.
+ */
+/*------------------------------------------------------------------------------*/
+void
+uip_fw_register(struct uip_fw_netif *netif)
+{
+ netif->next = netifs;
+ netifs = netif;
+}
+/*------------------------------------------------------------------------------*/
+/**
+ * Register a default network interface.
+ *
+ * All packets that don't go out on any of the other interfaces will
+ * be routed to the default interface.
+ *
+ * \param netif A pointer to the network interface that is to be
+ * registered.
+ */
+/*------------------------------------------------------------------------------*/
+void
+uip_fw_default(struct uip_fw_netif *netif)
+{
+ defaultnetif = netif;
+}
+/*------------------------------------------------------------------------------*/
+/**
+ * Perform periodic processing.
+ */
+/*------------------------------------------------------------------------------*/
+void
+uip_fw_periodic(void)
+{
+ struct fwcache_entry *fw;
+ for(fw = fwcache; fw < &fwcache[FWCACHE_SIZE]; ++fw) {
+ if(fw->timer > 0) {
+ --fw->timer;
+ }
+ }
+}
+/*------------------------------------------------------------------------------*/
diff --git a/Libraries/WiShield/uip-fw.h b/Libraries/WiShield/uip-fw.h
new file mode 100644
index 0000000..9033850
--- /dev/null
+++ b/Libraries/WiShield/uip-fw.h
@@ -0,0 +1,176 @@
+/**
+ * \addtogroup uipfw
+ * @{
+ */
+
+/**
+ * \file
+ * uIP packet forwarding header file.
+ * \author Adam Dunkels <adam@sics.se>
+ */
+
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: uip-fw.h,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+#ifndef __UIP_FW_H__
+#define __UIP_FW_H__
+
+#include "uip.h"
+
+/**
+ * Representation of a uIP network interface.
+ */
+struct uip_fw_netif {
+ struct uip_fw_netif *next; /**< Pointer to the next interface when
+ linked in a list. */
+ u16_t ipaddr[2]; /**< The IP address of this interface. */
+ u16_t netmask[2]; /**< The netmask of the interface. */
+ u8_t (* output)(void);
+ /**< A pointer to the function that
+ sends a packet. */
+};
+
+/**
+ * Intantiating macro for a uIP network interface.
+ *
+ * Example:
+ \code
+ struct uip_fw_netif slipnetif =
+ {UIP_FW_NETIF(192,168,76,1, 255,255,255,0, slip_output)};
+ \endcode
+ * \param ip1,ip2,ip3,ip4 The IP address of the network interface.
+ *
+ * \param nm1,nm2,nm3,nm4 The netmask of the network interface.
+ *
+ * \param outputfunc A pointer to the output function of the network interface.
+ *
+ * \hideinitializer
+ */
+#define UIP_FW_NETIF(ip1,ip2,ip3,ip4, nm1,nm2,nm3,nm4, outputfunc) \
+ NULL, \
+ {HTONS((ip1 << 8) | ip2), HTONS((ip3 << 8) | ip4)}, \
+ {HTONS((nm1 << 8) | nm2), HTONS((nm3 << 8) | nm4)}, \
+ outputfunc
+
+/**
+ * Set the IP address of a network interface.
+ *
+ * \param netif A pointer to the uip_fw_netif structure for the network interface.
+ *
+ * \param addr A pointer to an IP address.
+ *
+ * \hideinitializer
+ */
+#define uip_fw_setipaddr(netif, addr) \
+ do { (netif)->ipaddr[0] = ((u16_t *)(addr))[0]; \
+ (netif)->ipaddr[1] = ((u16_t *)(addr))[1]; } while(0)
+/**
+ * Set the netmask of a network interface.
+ *
+ * \param netif A pointer to the uip_fw_netif structure for the network interface.
+ *
+ * \param addr A pointer to an IP address representing the netmask.
+ *
+ * \hideinitializer
+ */
+#define uip_fw_setnetmask(netif, addr) \
+ do { (netif)->netmask[0] = ((u16_t *)(addr))[0]; \
+ (netif)->netmask[1] = ((u16_t *)(addr))[1]; } while(0)
+
+void uip_fw_init(void);
+u8_t uip_fw_forward(void);
+u8_t uip_fw_output(void);
+void uip_fw_register(struct uip_fw_netif *netif);
+void uip_fw_default(struct uip_fw_netif *netif);
+void uip_fw_periodic(void);
+
+
+/**
+ * A non-error message that indicates that a packet should be
+ * processed locally.
+ *
+ * \hideinitializer
+ */
+#define UIP_FW_LOCAL 0
+
+/**
+ * A non-error message that indicates that something went OK.
+ *
+ * \hideinitializer
+ */
+#define UIP_FW_OK 0
+
+/**
+ * A non-error message that indicates that a packet was forwarded.
+ *
+ * \hideinitializer
+ */
+#define UIP_FW_FORWARDED 1
+
+/**
+ * A non-error message that indicates that a zero-length packet
+ * transmission was attempted, and that no packet was sent.
+ *
+ * \hideinitializer
+ */
+#define UIP_FW_ZEROLEN 2
+
+/**
+ * An error message that indicates that a packet that was too large
+ * for the outbound network interface was detected.
+ *
+ * \hideinitializer
+ */
+#define UIP_FW_TOOLARGE 3
+
+/**
+ * An error message that indicates that no suitable interface could be
+ * found for an outbound packet.
+ *
+ * \hideinitializer
+ */
+#define UIP_FW_NOROUTE 4
+
+/**
+ * An error message that indicates that a packet that should be
+ * forwarded or output was dropped.
+ *
+ * \hideinitializer
+ */
+#define UIP_FW_DROPPED 5
+
+
+#endif /* __UIP_FW_H__ */
+
+/** @} */
diff --git a/Libraries/WiShield/uip-neighbor.c b/Libraries/WiShield/uip-neighbor.c
new file mode 100644
index 0000000..739c03e
--- /dev/null
+++ b/Libraries/WiShield/uip-neighbor.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2006, Swedish Institute of Computer Science.
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * $Id: uip-neighbor.c,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+
+/**
+ * \file
+ * Database of link-local neighbors, used by IPv6 code and
+ * to be used by a future ARP code rewrite.
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ */
+
+#include "uip-neighbor.h"
+
+#include <string.h>
+
+#define MAX_TIME 128
+
+#ifdef UIP_NEIGHBOR_CONF_ENTRIES
+#define ENTRIES UIP_NEIGHBOR_CONF_ENTRIES
+#else /* UIP_NEIGHBOR_CONF_ENTRIES */
+#define ENTRIES 8
+#endif /* UIP_NEIGHBOR_CONF_ENTRIES */
+
+struct neighbor_entry {
+ uip_ipaddr_t ipaddr;
+ struct uip_neighbor_addr addr;
+ u8_t time;
+};
+static struct neighbor_entry entries[ENTRIES];
+
+/*---------------------------------------------------------------------------*/
+void
+uip_neighbor_init(void)
+{
+ int i;
+
+ for(i = 0; i < ENTRIES; ++i) {
+ entries[i].time = MAX_TIME;
+ }
+}
+/*---------------------------------------------------------------------------*/
+void
+uip_neighbor_periodic(void)
+{
+ int i;
+
+ for(i = 0; i < ENTRIES; ++i) {
+ if(entries[i].time < MAX_TIME) {
+ entries[i].time++;
+ }
+ }
+}
+/*---------------------------------------------------------------------------*/
+void
+uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr *addr)
+{
+ int i, oldest;
+ u8_t oldest_time;
+
+ printf("Adding neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n",
+ addr->addr.addr[0], addr->addr.addr[1], addr->addr.addr[2], addr->addr.addr[3],
+ addr->addr.addr[4], addr->addr.addr[5]);
+
+ /* Find the first unused entry or the oldest used entry. */
+ oldest_time = 0;
+ oldest = 0;
+ for(i = 0; i < ENTRIES; ++i) {
+ if(entries[i].time == MAX_TIME) {
+ oldest = i;
+ break;
+ }
+ if(uip_ipaddr_cmp(entries[i].ipaddr, addr)) {
+ oldest = i;
+ break;
+ }
+ if(entries[i].time > oldest_time) {
+ oldest = i;
+ oldest_time = entries[i].time;
+ }
+ }
+
+ /* Use the oldest or first free entry (either pointed to by the
+ "oldest" variable). */
+ entries[oldest].time = 0;
+ uip_ipaddr_copy(entries[oldest].ipaddr, ipaddr);
+ memcpy(&entries[oldest].addr, addr, sizeof(struct uip_neighbor_addr));
+}
+/*---------------------------------------------------------------------------*/
+static struct neighbor_entry *
+find_entry(uip_ipaddr_t ipaddr)
+{
+ int i;
+
+ for(i = 0; i < ENTRIES; ++i) {
+ if(uip_ipaddr_cmp(entries[i].ipaddr, ipaddr)) {
+ return &entries[i];
+ }
+ }
+ return NULL;
+}
+/*---------------------------------------------------------------------------*/
+void
+uip_neighbor_update(uip_ipaddr_t ipaddr)
+{
+ struct neighbor_entry *e;
+
+ e = find_entry(ipaddr);
+ if(e != NULL) {
+ e->time = 0;
+ }
+}
+/*---------------------------------------------------------------------------*/
+struct uip_neighbor_addr *
+uip_neighbor_lookup(uip_ipaddr_t ipaddr)
+{
+ struct neighbor_entry *e;
+
+ e = find_entry(ipaddr);
+ if(e != NULL) {
+ /* printf("Lookup neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n",
+ e->addr.addr.addr[0], e->addr.addr.addr[1], e->addr.addr.addr[2], e->addr.addr.addr[3],
+ e->addr.addr.addr[4], e->addr.addr.addr[5]);*/
+
+ return &e->addr;
+ }
+ return NULL;
+}
+/*---------------------------------------------------------------------------*/
diff --git a/Libraries/WiShield/uip-neighbor.h b/Libraries/WiShield/uip-neighbor.h
new file mode 100644
index 0000000..d3b351c
--- /dev/null
+++ b/Libraries/WiShield/uip-neighbor.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2006, Swedish Institute of Computer Science.
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * $Id: uip-neighbor.h,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+
+/**
+ * \file
+ * Header file for database of link-local neighbors, used by
+ * IPv6 code and to be used by future ARP code.
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ */
+
+#ifndef __UIP_NEIGHBOR_H__
+#define __UIP_NEIGHBOR_H__
+
+#include "uip.h"
+
+struct uip_neighbor_addr {
+#if UIP_NEIGHBOR_CONF_ADDRTYPE
+ UIP_NEIGHBOR_CONF_ADDRTYPE addr;
+#else
+ struct uip_eth_addr addr;
+#endif
+};
+
+void uip_neighbor_init(void);
+void uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr *addr);
+void uip_neighbor_update(uip_ipaddr_t ipaddr);
+struct uip_neighbor_addr *uip_neighbor_lookup(uip_ipaddr_t ipaddr);
+void uip_neighbor_periodic(void);
+
+#endif /* __UIP-NEIGHBOR_H__ */
diff --git a/Libraries/WiShield/uip-split.c b/Libraries/WiShield/uip-split.c
new file mode 100644
index 0000000..82d0280
--- /dev/null
+++ b/Libraries/WiShield/uip-split.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: uip-split.c,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+
+#include <string.h>
+
+#include "uip-split.h"
+#include "uip.h"
+#include "uip-fw.h"
+#include "uip_arch.h"
+
+
+
+#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
+
+/*-----------------------------------------------------------------------------*/
+void
+uip_split_output(void)
+{
+ u16_t tcplen, len1, len2;
+
+ /* We only try to split maximum sized TCP segments. */
+ if(BUF->proto == UIP_PROTO_TCP &&
+ uip_len == UIP_BUFSIZE - UIP_LLH_LEN) {
+
+ tcplen = uip_len - UIP_TCPIP_HLEN;
+ /* Split the segment in two. If the original packet length was
+ odd, we make the second packet one byte larger. */
+ len1 = len2 = tcplen / 2;
+ if(len1 + len2 < tcplen) {
+ ++len2;
+ }
+
+ /* Create the first packet. This is done by altering the length
+ field of the IP header and updating the checksums. */
+ uip_len = len1 + UIP_TCPIP_HLEN;
+#if UIP_CONF_IPV6
+ /* For IPv6, the IP length field does not include the IPv6 IP header
+ length. */
+ BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
+ BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
+#else /* UIP_CONF_IPV6 */
+ BUF->len[0] = uip_len >> 8;
+ BUF->len[1] = uip_len & 0xff;
+#endif /* UIP_CONF_IPV6 */
+
+ /* Recalculate the TCP checksum. */
+ BUF->tcpchksum = 0;
+ BUF->tcpchksum = ~(uip_tcpchksum());
+
+#if !UIP_CONF_IPV6
+ /* Recalculate the IP checksum. */
+ BUF->ipchksum = 0;
+ BUF->ipchksum = ~(uip_ipchksum());
+#endif /* UIP_CONF_IPV6 */
+
+ /* Transmit the first packet. */
+ uip_fw_output();
+ /*tcpip_output();*/
+
+ /* Now, create the second packet. To do this, it is not enough to
+ just alter the length field, but we must also update the TCP
+ sequence number and point the uip_appdata to a new place in
+ memory. This place is detemined by the length of the first
+ packet (len1). */
+ uip_len = len2 + UIP_TCPIP_HLEN;
+#if UIP_CONF_IPV6
+ /* For IPv6, the IP length field does not include the IPv6 IP header
+ length. */
+ BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
+ BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
+#else /* UIP_CONF_IPV6 */
+ BUF->len[0] = uip_len >> 8;
+ BUF->len[1] = uip_len & 0xff;
+#endif /* UIP_CONF_IPV6 */
+
+ /* uip_appdata += len1;*/
+ memcpy(uip_appdata, (u8_t *)uip_appdata + len1, len2);
+
+ uip_add32(BUF->seqno, len1);
+ BUF->seqno[0] = uip_acc32[0];
+ BUF->seqno[1] = uip_acc32[1];
+ BUF->seqno[2] = uip_acc32[2];
+ BUF->seqno[3] = uip_acc32[3];
+
+ /* Recalculate the TCP checksum. */
+ BUF->tcpchksum = 0;
+ BUF->tcpchksum = ~(uip_tcpchksum());
+
+#if !UIP_CONF_IPV6
+ /* Recalculate the IP checksum. */
+ BUF->ipchksum = 0;
+ BUF->ipchksum = ~(uip_ipchksum());
+#endif /* UIP_CONF_IPV6 */
+
+ /* Transmit the second packet. */
+ uip_fw_output();
+ /*tcpip_output();*/
+ } else {
+ uip_fw_output();
+ /*tcpip_output();*/
+ }
+
+}
+/*-----------------------------------------------------------------------------*/
diff --git a/Libraries/WiShield/uip-split.h b/Libraries/WiShield/uip-split.h
new file mode 100644
index 0000000..c2c1789
--- /dev/null
+++ b/Libraries/WiShield/uip-split.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: uip-split.h,v 1.2 2006/06/12 08:00:30 adam Exp $
+ */
+/**
+ * \addtogroup uip
+ * @{
+ */
+
+/**
+ * \defgroup uipsplit uIP TCP throughput booster hack
+ * @{
+ *
+ * The basic uIP TCP implementation only allows each TCP connection to
+ * have a single TCP segment in flight at any given time. Because of
+ * the delayed ACK algorithm employed by most TCP receivers, uIP's
+ * limit on the amount of in-flight TCP segments seriously reduces the
+ * maximum achievable throughput for sending data from uIP.
+ *
+ * The uip-split module is a hack which tries to remedy this
+ * situation. By splitting maximum sized outgoing TCP segments into
+ * two, the delayed ACK algorithm is not invoked at TCP
+ * receivers. This improves the throughput when sending data from uIP
+ * by orders of magnitude.
+ *
+ * The uip-split module uses the uip-fw module (uIP IP packet
+ * forwarding) for sending packets. Therefore, the uip-fw module must
+ * be set up with the appropriate network interfaces for this module
+ * to work.
+ */
+
+
+/**
+ * \file
+ * Module for splitting outbound TCP segments in two to avoid the
+ * delayed ACK throughput degradation.
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifndef __UIP_SPLIT_H__
+#define __UIP_SPLIT_H__
+
+/**
+ * Handle outgoing packets.
+ *
+ * This function inspects an outgoing packet in the uip_buf buffer and
+ * sends it out using the uip_fw_output() function. If the packet is a
+ * full-sized TCP segment it will be split into two segments and
+ * transmitted separately. This function should be called instead of
+ * the actual device driver output function, or the uip_fw_output()
+ * function.
+ *
+ * The headers of the outgoing packet is assumed to be in the uip_buf
+ * buffer and the payload is assumed to be wherever uip_appdata
+ * points. The length of the outgoing packet is assumed to be in the
+ * uip_len variable.
+ *
+ */
+void uip_split_output(void);
+
+#endif /* __UIP_SPLIT_H__ */
+
+/** @} */
+/** @} */
diff --git a/Libraries/WiShield/uip.c b/Libraries/WiShield/uip.c
new file mode 100644
index 0000000..6af0271
--- /dev/null
+++ b/Libraries/WiShield/uip.c
@@ -0,0 +1,1927 @@
+
+/******************************************************************************
+
+ Filename: uip.c
+ Description: uIP TCP/IP stack for the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/29/2009 Initial port
+
+ *****************************************************************************/
+
+#define DEBUG_PRINTF(...) /*printf(__VA_ARGS__)*/
+
+/**
+ * \defgroup uip The uIP TCP/IP stack
+ * @{
+ *
+ * uIP is an implementation of the TCP/IP protocol stack intended for
+ * small 8-bit and 16-bit microcontrollers.
+ *
+ * uIP provides the necessary protocols for Internet communication,
+ * with a very small code footprint and RAM requirements - the uIP
+ * code size is on the order of a few kilobytes and RAM usage is on
+ * the order of a few hundred bytes.
+ */
+
+/**
+ * \file
+ * The uIP TCP/IP stack code.
+ * \author Adam Dunkels <adam@dunkels.com>
+ */
+
+/*
+ * Copyright (c) 2001-2003, Adam Dunkels.
+ * 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 the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: uip.c,v 1.65 2006/06/11 21:46:39 adam Exp $
+ *
+ */
+
+/*
+ * uIP is a small implementation of the IP, UDP and TCP protocols (as
+ * well as some basic ICMP stuff). The implementation couples the IP,
+ * UDP, TCP and the application layers very tightly. To keep the size
+ * of the compiled code down, this code frequently uses the goto
+ * statement. While it would be possible to break the uip_process()
+ * function into many smaller functions, this would increase the code
+ * size because of the overhead of parameter passing and the fact that
+ * the optimier would not be as efficient.
+ *
+ * The principle is that we have a small buffer, called the uip_buf,
+ * in which the device driver puts an incoming packet. The TCP/IP
+ * stack parses the headers in the packet, and calls the
+ * application. If the remote host has sent data to the application,
+ * this data is present in the uip_buf and the application read the
+ * data from there. It is up to the application to put this data into
+ * a byte stream if needed. The application will not be fed with data
+ * that is out of sequence.
+ *
+ * If the application whishes to send data to the peer, it should put
+ * its data into the uip_buf. The uip_appdata pointer points to the
+ * first available byte. The TCP/IP stack will calculate the
+ * checksums, and fill in the necessary header fields and finally send
+ * the packet back to the peer.
+*/
+
+#include "uip.h"
+#include "uipopt.h"
+#include "uip_arch.h"
+
+#if UIP_CONF_IPV6
+#include "uip-neighbor.h"
+#endif /* UIP_CONF_IPV6 */
+
+#include <string.h>
+
+/*---------------------------------------------------------------------------*/
+/* Variable definitions. */
+
+
+/* The IP address of this host. If it is defined to be fixed (by
+ setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set
+ here. Otherwise, the address */
+#if UIP_FIXEDADDR > 0
+const uip_ipaddr_t uip_hostaddr =
+ {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1),
+ HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)};
+const uip_ipaddr_t uip_draddr =
+ {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1),
+ HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)};
+const uip_ipaddr_t uip_netmask =
+ {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1),
+ HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)};
+#else
+uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask;
+#endif /* UIP_FIXEDADDR */
+
+static const uip_ipaddr_t all_ones_addr =
+#if UIP_CONF_IPV6
+ {0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff};
+#else /* UIP_CONF_IPV6 */
+ {0xffff,0xffff};
+#endif /* UIP_CONF_IPV6 */
+static const uip_ipaddr_t all_zeroes_addr =
+#if UIP_CONF_IPV6
+ {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000};
+#else /* UIP_CONF_IPV6 */
+ {0x0000,0x0000};
+#endif /* UIP_CONF_IPV6 */
+
+
+struct uip_eth_addr uip_ethaddr = {{0,0,0,0,0,0}};
+
+#ifndef UIP_CONF_EXTERNAL_BUFFER
+u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains
+ incoming packets. */
+#endif /* UIP_CONF_EXTERNAL_BUFFER */
+
+void *uip_appdata; /* The uip_appdata pointer points to
+ application data. */
+void *uip_sappdata; /* The uip_appdata pointer points to
+ the application data which is to
+ be sent. */
+#if UIP_URGDATA > 0
+void *uip_urgdata; /* The uip_urgdata pointer points to
+ urgent data (out-of-band data), if
+ present. */
+u16_t uip_urglen, uip_surglen;
+#endif /* UIP_URGDATA > 0 */
+
+u16_t uip_len, uip_slen;
+ /* The uip_len is either 8 or 16 bits,
+ depending on the maximum packet
+ size. */
+
+u8_t uip_flags; /* The uip_flags variable is used for
+ communication between the TCP/IP stack
+ and the application program. */
+struct uip_conn *uip_conn; /* uip_conn always points to the current
+ connection. */
+
+struct uip_conn uip_conns[UIP_CONNS];
+ /* The uip_conns array holds all TCP
+ connections. */
+u16_t uip_listenports[UIP_LISTENPORTS];
+ /* The uip_listenports list all currently
+ listning ports. */
+#if UIP_UDP
+struct uip_udp_conn *uip_udp_conn;
+struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
+#endif /* UIP_UDP */
+
+static u16_t ipid; /* Ths ipid variable is an increasing
+ number that is used for the IP ID
+ field. */
+
+void uip_setipid(u16_t id) { ipid = id; }
+
+static u8_t iss[4]; /* The iss variable is used for the TCP
+ initial sequence number. */
+
+#if UIP_ACTIVE_OPEN
+static u16_t lastport; /* Keeps track of the last port used for
+ a new connection. */
+#endif /* UIP_ACTIVE_OPEN */
+
+/* Temporary variables. */
+u8_t uip_acc32[4];
+static u8_t c, opt;
+static u16_t tmp16;
+
+/* Structures and definitions. */
+#define TCP_FIN 0x01
+#define TCP_SYN 0x02
+#define TCP_RST 0x04
+#define TCP_PSH 0x08
+#define TCP_ACK 0x10
+#define TCP_URG 0x20
+#define TCP_CTL 0x3f
+
+#define TCP_OPT_END 0 /* End of TCP options list */
+#define TCP_OPT_NOOP 1 /* "No-operation" TCP option */
+#define TCP_OPT_MSS 2 /* Maximum segment size TCP option */
+
+#define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */
+
+#define ICMP_ECHO_REPLY 0
+#define ICMP_ECHO 8
+
+#define ICMP6_ECHO_REPLY 129
+#define ICMP6_ECHO 128
+#define ICMP6_NEIGHBOR_SOLICITATION 135
+#define ICMP6_NEIGHBOR_ADVERTISEMENT 136
+
+#define ICMP6_FLAG_S (1 << 6)
+
+#define ICMP6_OPTION_SOURCE_LINK_ADDRESS 1
+#define ICMP6_OPTION_TARGET_LINK_ADDRESS 2
+
+
+/* Macros. */
+#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
+#define FBUF ((struct uip_tcpip_hdr *)&uip_reassbuf[0])
+#define ICMPBUF ((struct uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN])
+#define UDPBUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
+
+
+#if UIP_STATISTICS == 1
+struct uip_stats uip_stat;
+#define UIP_STAT(s) s
+#else
+#define UIP_STAT(s)
+#endif /* UIP_STATISTICS == 1 */
+
+#if UIP_LOGGING == 1
+#include <stdio.h>
+void uip_log(char *msg);
+#define UIP_LOG(m) uip_log(m)
+#else
+#define UIP_LOG(m)
+#endif /* UIP_LOGGING == 1 */
+
+#if ! UIP_ARCH_ADD32
+void
+uip_add32(u8_t *op32, u16_t op16)
+{
+ uip_acc32[3] = op32[3] + (op16 & 0xff);
+ uip_acc32[2] = op32[2] + (op16 >> 8);
+ uip_acc32[1] = op32[1];
+ uip_acc32[0] = op32[0];
+
+ if(uip_acc32[2] < (op16 >> 8)) {
+ ++uip_acc32[1];
+ if(uip_acc32[1] == 0) {
+ ++uip_acc32[0];
+ }
+ }
+
+
+ if(uip_acc32[3] < (op16 & 0xff)) {
+ ++uip_acc32[2];
+ if(uip_acc32[2] == 0) {
+ ++uip_acc32[1];
+ if(uip_acc32[1] == 0) {
+ ++uip_acc32[0];
+ }
+ }
+ }
+}
+
+#endif /* UIP_ARCH_ADD32 */
+
+#if ! UIP_ARCH_CHKSUM
+/*---------------------------------------------------------------------------*/
+static u16_t
+chksum(u16_t sum, const u8_t *data, u16_t len)
+{
+ u16_t t;
+ const u8_t *dataptr;
+ const u8_t *last_byte;
+
+ dataptr = data;
+ last_byte = data + len - 1;
+
+ while(dataptr < last_byte) { /* At least two more bytes */
+ t = (dataptr[0] << 8) + dataptr[1];
+ sum += t;
+ if(sum < t) {
+ sum++; /* carry */
+ }
+ dataptr += 2;
+ }
+
+ if(dataptr == last_byte) {
+ t = (dataptr[0] << 8) + 0;
+ sum += t;
+ if(sum < t) {
+ sum++; /* carry */
+ }
+ }
+
+ /* Return sum in host byte order. */
+ return sum;
+}
+/*---------------------------------------------------------------------------*/
+u16_t
+uip_chksum(u16_t *data, u16_t len)
+{
+ return htons(chksum(0, (u8_t *)data, len));
+}
+/*---------------------------------------------------------------------------*/
+#ifndef UIP_ARCH_IPCHKSUM
+u16_t
+uip_ipchksum(void)
+{
+ u16_t sum;
+
+ sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN);
+ DEBUG_PRINTF("uip_ipchksum: sum 0x%04x\n", sum);
+ return (sum == 0) ? 0xffff : htons(sum);
+}
+#endif
+/*---------------------------------------------------------------------------*/
+static u16_t
+upper_layer_chksum(u8_t proto)
+{
+ u16_t upper_layer_len;
+ u16_t sum;
+
+#if UIP_CONF_IPV6
+ upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]);
+#else /* UIP_CONF_IPV6 */
+ upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN;
+#endif /* UIP_CONF_IPV6 */
+
+ /* First sum pseudoheader. */
+
+ /* IP protocol and length fields. This addition cannot carry. */
+ sum = upper_layer_len + proto;
+ /* Sum IP source and destination addresses. */
+ sum = chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t));
+
+ /* Sum TCP header and data. */
+ sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN],
+ upper_layer_len);
+
+ return (sum == 0) ? 0xffff : htons(sum);
+}
+/*---------------------------------------------------------------------------*/
+#if UIP_CONF_IPV6
+u16_t
+uip_icmp6chksum(void)
+{
+ return upper_layer_chksum(UIP_PROTO_ICMP6);
+
+}
+#endif /* UIP_CONF_IPV6 */
+/*---------------------------------------------------------------------------*/
+u16_t
+uip_tcpchksum(void)
+{
+ return upper_layer_chksum(UIP_PROTO_TCP);
+}
+/*---------------------------------------------------------------------------*/
+#if UIP_UDP_CHECKSUMS
+u16_t
+uip_udpchksum(void)
+{
+ return upper_layer_chksum(UIP_PROTO_UDP);
+}
+#endif /* UIP_UDP_CHECKSUMS */
+#endif /* UIP_ARCH_CHKSUM */
+/*---------------------------------------------------------------------------*/
+void
+uip_init(void)
+{
+ for(c = 0; c < UIP_LISTENPORTS; ++c) {
+ uip_listenports[c] = 0;
+ }
+ for(c = 0; c < UIP_CONNS; ++c) {
+ uip_conns[c].tcpstateflags = UIP_CLOSED;
+ }
+#if UIP_ACTIVE_OPEN
+ lastport = 1024;
+#endif /* UIP_ACTIVE_OPEN */
+
+#if UIP_UDP
+ for(c = 0; c < UIP_UDP_CONNS; ++c) {
+ uip_udp_conns[c].lport = 0;
+ }
+#endif /* UIP_UDP */
+
+
+ /* IPv4 initialization. */
+#if UIP_FIXEDADDR == 0
+ /* uip_hostaddr[0] = uip_hostaddr[1] = 0;*/
+#endif /* UIP_FIXEDADDR */
+
+}
+/*---------------------------------------------------------------------------*/
+#if UIP_ACTIVE_OPEN
+struct uip_conn *
+uip_connect(uip_ipaddr_t *ripaddr, u16_t rport)
+{
+ register struct uip_conn *conn, *cconn;
+
+ /* Find an unused local port. */
+ again:
+ ++lastport;
+
+ if(lastport >= 32000) {
+ lastport = 4096;
+ }
+
+ /* Check if this port is already in use, and if so try to find
+ another one. */
+ for(c = 0; c < UIP_CONNS; ++c) {
+ conn = &uip_conns[c];
+ if(conn->tcpstateflags != UIP_CLOSED &&
+ conn->lport == htons(lastport)) {
+ goto again;
+ }
+ }
+
+ conn = 0;
+ for(c = 0; c < UIP_CONNS; ++c) {
+ cconn = &uip_conns[c];
+ if(cconn->tcpstateflags == UIP_CLOSED) {
+ conn = cconn;
+ break;
+ }
+ if(cconn->tcpstateflags == UIP_TIME_WAIT) {
+ if(conn == 0 ||
+ cconn->timer > conn->timer) {
+ conn = cconn;
+ }
+ }
+ }
+
+ if(conn == 0) {
+ return 0;
+ }
+
+ conn->tcpstateflags = UIP_SYN_SENT;
+
+ conn->snd_nxt[0] = iss[0];
+ conn->snd_nxt[1] = iss[1];
+ conn->snd_nxt[2] = iss[2];
+ conn->snd_nxt[3] = iss[3];
+
+ conn->initialmss = conn->mss = UIP_TCP_MSS;
+
+ conn->len = 1; /* TCP length of the SYN is one. */
+ conn->nrtx = 0;
+ conn->timer = 1; /* Send the SYN next time around. */
+ conn->rto = UIP_RTO;
+ conn->sa = 0;
+ conn->sv = 16; /* Initial value of the RTT variance. */
+ conn->lport = htons(lastport);
+ conn->rport = rport;
+ uip_ipaddr_copy(&conn->ripaddr, ripaddr);
+
+ return conn;
+}
+#endif /* UIP_ACTIVE_OPEN */
+/*---------------------------------------------------------------------------*/
+#if UIP_UDP
+struct uip_udp_conn *
+uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport)
+{
+ register struct uip_udp_conn *conn;
+
+ /* Find an unused local port. */
+ again:
+ ++lastport;
+
+ if(lastport >= 32000) {
+ lastport = 4096;
+ }
+
+ for(c = 0; c < UIP_UDP_CONNS; ++c) {
+ if(uip_udp_conns[c].lport == htons(lastport)) {
+ goto again;
+ }
+ }
+
+
+ conn = 0;
+ for(c = 0; c < UIP_UDP_CONNS; ++c) {
+ if(uip_udp_conns[c].lport == 0) {
+ conn = &uip_udp_conns[c];
+ break;
+ }
+ }
+
+ if(conn == 0) {
+ return 0;
+ }
+
+ conn->lport = HTONS(lastport);
+ conn->rport = rport;
+ if(ripaddr == NULL) {
+ memset(conn->ripaddr, 0, sizeof(uip_ipaddr_t));
+ } else {
+ uip_ipaddr_copy(&conn->ripaddr, ripaddr);
+ }
+ conn->ttl = UIP_TTL;
+
+ return conn;
+}
+#endif /* UIP_UDP */
+/*---------------------------------------------------------------------------*/
+void
+uip_unlisten(u16_t port)
+{
+ for(c = 0; c < UIP_LISTENPORTS; ++c) {
+ if(uip_listenports[c] == port) {
+ uip_listenports[c] = 0;
+ return;
+ }
+ }
+}
+/*---------------------------------------------------------------------------*/
+void
+uip_listen(u16_t port)
+{
+ for(c = 0; c < UIP_LISTENPORTS; ++c) {
+ if(uip_listenports[c] == 0) {
+ uip_listenports[c] = port;
+ return;
+ }
+ }
+}
+/*---------------------------------------------------------------------------*/
+/* XXX: IP fragment reassembly: not well-tested. */
+
+#if UIP_REASSEMBLY && !UIP_CONF_IPV6
+#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN)
+static u8_t uip_reassbuf[UIP_REASS_BUFSIZE];
+static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)];
+static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f,
+ 0x0f, 0x07, 0x03, 0x01};
+static u16_t uip_reasslen;
+static u8_t uip_reassflags;
+#define UIP_REASS_FLAG_LASTFRAG 0x01
+static u8_t uip_reasstmr;
+
+#define IP_MF 0x20
+
+static u8_t
+uip_reass(void)
+{
+ u16_t offset, len;
+ u16_t i;
+
+ /* If ip_reasstmr is zero, no packet is present in the buffer, so we
+ write the IP header of the fragment into the reassembly
+ buffer. The timer is updated with the maximum age. */
+ if(uip_reasstmr == 0) {
+ memcpy(uip_reassbuf, &BUF->vhl, UIP_IPH_LEN);
+ uip_reasstmr = UIP_REASS_MAXAGE;
+ uip_reassflags = 0;
+ /* Clear the bitmap. */
+ memset(uip_reassbitmap, 0, sizeof(uip_reassbitmap));
+ }
+
+ /* Check if the incoming fragment matches the one currently present
+ in the reasembly buffer. If so, we proceed with copying the
+ fragment into the buffer. */
+ if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] &&
+ BUF->srcipaddr[1] == FBUF->srcipaddr[1] &&
+ BUF->destipaddr[0] == FBUF->destipaddr[0] &&
+ BUF->destipaddr[1] == FBUF->destipaddr[1] &&
+ BUF->ipid[0] == FBUF->ipid[0] &&
+ BUF->ipid[1] == FBUF->ipid[1]) {
+
+ len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4;
+ offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8;
+
+ /* If the offset or the offset + fragment length overflows the
+ reassembly buffer, we discard the entire packet. */
+ if(offset > UIP_REASS_BUFSIZE ||
+ offset + len > UIP_REASS_BUFSIZE) {
+ uip_reasstmr = 0;
+ goto nullreturn;
+ }
+
+ /* Copy the fragment into the reassembly buffer, at the right
+ offset. */
+ memcpy(&uip_reassbuf[UIP_IPH_LEN + offset],
+ (char *)BUF + (int)((BUF->vhl & 0x0f) * 4),
+ len);
+
+ /* Update the bitmap. */
+ if(offset / (8 * 8) == (offset + len) / (8 * 8)) {
+ /* If the two endpoints are in the same byte, we only update
+ that byte. */
+
+ uip_reassbitmap[offset / (8 * 8)] |=
+ bitmap_bits[(offset / 8 ) & 7] &
+ ~bitmap_bits[((offset + len) / 8 ) & 7];
+ } else {
+ /* If the two endpoints are in different bytes, we update the
+ bytes in the endpoints and fill the stuff inbetween with
+ 0xff. */
+ uip_reassbitmap[offset / (8 * 8)] |=
+ bitmap_bits[(offset / 8 ) & 7];
+ for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
+ uip_reassbitmap[i] = 0xff;
+ }
+ uip_reassbitmap[(offset + len) / (8 * 8)] |=
+ ~bitmap_bits[((offset + len) / 8 ) & 7];
+ }
+
+ /* If this fragment has the More Fragments flag set to zero, we
+ know that this is the last fragment, so we can calculate the
+ size of the entire packet. We also set the
+ IP_REASS_FLAG_LASTFRAG flag to indicate that we have received
+ the final fragment. */
+
+ if((BUF->ipoffset[0] & IP_MF) == 0) {
+ uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;
+ uip_reasslen = offset + len;
+ }
+
+ /* Finally, we check if we have a full packet in the buffer. We do
+ this by checking if we have the last fragment and if all bits
+ in the bitmap are set. */
+ if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) {
+ /* Check all bytes up to and including all but the last byte in
+ the bitmap. */
+ for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) {
+ if(uip_reassbitmap[i] != 0xff) {
+ goto nullreturn;
+ }
+ }
+ /* Check the last byte in the bitmap. It should contain just the
+ right amount of bits. */
+ if(uip_reassbitmap[uip_reasslen / (8 * 8)] !=
+ (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) {
+ goto nullreturn;
+ }
+
+ /* If we have come this far, we have a full packet in the
+ buffer, so we allocate a pbuf and copy the packet into it. We
+ also reset the timer. */
+ uip_reasstmr = 0;
+ memcpy(BUF, FBUF, uip_reasslen);
+
+ /* Pretend to be a "normal" (i.e., not fragmented) IP packet
+ from now on. */
+ BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
+ BUF->len[0] = uip_reasslen >> 8;
+ BUF->len[1] = uip_reasslen & 0xff;
+ BUF->ipchksum = 0;
+ BUF->ipchksum = ~(uip_ipchksum());
+
+ return uip_reasslen;
+ }
+ }
+
+ nullreturn:
+ return 0;
+}
+#endif /* UIP_REASSEMBLY */
+/*---------------------------------------------------------------------------*/
+static void
+uip_add_rcv_nxt(u16_t n)
+{
+ uip_add32(uip_conn->rcv_nxt, n);
+ uip_conn->rcv_nxt[0] = uip_acc32[0];
+ uip_conn->rcv_nxt[1] = uip_acc32[1];
+ uip_conn->rcv_nxt[2] = uip_acc32[2];
+ uip_conn->rcv_nxt[3] = uip_acc32[3];
+}
+/*---------------------------------------------------------------------------*/
+void
+uip_process(u8_t flag)
+{
+ register struct uip_conn *uip_connr = uip_conn;
+
+#if UIP_UDP
+ if(flag == UIP_UDP_SEND_CONN) {
+ goto udp_send;
+ }
+#endif /* UIP_UDP */
+
+ uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];
+
+ /* Check if we were invoked because of a poll request for a
+ particular connection. */
+ if(flag == UIP_POLL_REQUEST) {
+ if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED &&
+ !uip_outstanding(uip_connr)) {
+ uip_flags = UIP_POLL;
+ UIP_APPCALL();
+ goto appsend;
+ }
+ goto drop;
+
+ /* Check if we were invoked because of the perodic timer fireing. */
+ } else if(flag == UIP_TIMER) {
+#if UIP_REASSEMBLY
+ if(uip_reasstmr != 0) {
+ --uip_reasstmr;
+ }
+#endif /* UIP_REASSEMBLY */
+ /* Increase the initial sequence number. */
+ if(++iss[3] == 0) {
+ if(++iss[2] == 0) {
+ if(++iss[1] == 0) {
+ ++iss[0];
+ }
+ }
+ }
+
+ /* Reset the length variables. */
+ uip_len = 0;
+ uip_slen = 0;
+
+ /* Check if the connection is in a state in which we simply wait
+ for the connection to time out. If so, we increase the
+ connection's timer and remove the connection if it times
+ out. */
+ if(uip_connr->tcpstateflags == UIP_TIME_WAIT ||
+ uip_connr->tcpstateflags == UIP_FIN_WAIT_2) {
+ ++(uip_connr->timer);
+ if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) {
+ uip_connr->tcpstateflags = UIP_CLOSED;
+ }
+ } else if(uip_connr->tcpstateflags != UIP_CLOSED) {
+ /* If the connection has outstanding data, we increase the
+ connection's timer and see if it has reached the RTO value
+ in which case we retransmit. */
+ if(uip_outstanding(uip_connr)) {
+ if(uip_connr->timer-- == 0) {
+ if(uip_connr->nrtx == UIP_MAXRTX ||
+ ((uip_connr->tcpstateflags == UIP_SYN_SENT ||
+ uip_connr->tcpstateflags == UIP_SYN_RCVD) &&
+ uip_connr->nrtx == UIP_MAXSYNRTX)) {
+ uip_connr->tcpstateflags = UIP_CLOSED;
+
+ /* We call UIP_APPCALL() with uip_flags set to
+ UIP_TIMEDOUT to inform the application that the
+ connection has timed out. */
+ uip_flags = UIP_TIMEDOUT;
+ UIP_APPCALL();
+
+ /* We also send a reset packet to the remote host. */
+ BUF->flags = TCP_RST | TCP_ACK;
+ goto tcp_send_nodata;
+ }
+
+ /* Exponential backoff. */
+ uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4?
+ 4:
+ uip_connr->nrtx);
+ ++(uip_connr->nrtx);
+
+ /* Ok, so we need to retransmit. We do this differently
+ depending on which state we are in. In ESTABLISHED, we
+ call upon the application so that it may prepare the
+ data for the retransmit. In SYN_RCVD, we resend the
+ SYNACK that we sent earlier and in LAST_ACK we have to
+ retransmit our FINACK. */
+ UIP_STAT(++uip_stat.tcp.rexmit);
+ switch(uip_connr->tcpstateflags & UIP_TS_MASK) {
+ case UIP_SYN_RCVD:
+ /* In the SYN_RCVD state, we should retransmit our
+ SYNACK. */
+ goto tcp_send_synack;
+
+#if UIP_ACTIVE_OPEN
+ case UIP_SYN_SENT:
+ /* In the SYN_SENT state, we retransmit out SYN. */
+ BUF->flags = 0;
+ goto tcp_send_syn;
+#endif /* UIP_ACTIVE_OPEN */
+
+ case UIP_ESTABLISHED:
+ /* In the ESTABLISHED state, we call upon the application
+ to do the actual retransmit after which we jump into
+ the code for sending out the packet (the apprexmit
+ label). */
+ uip_flags = UIP_REXMIT;
+ UIP_APPCALL();
+ goto apprexmit;
+
+ case UIP_FIN_WAIT_1:
+ case UIP_CLOSING:
+ case UIP_LAST_ACK:
+ /* In all these states we should retransmit a FINACK. */
+ goto tcp_send_finack;
+
+ }
+ }
+ } else if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) {
+ /* If there was no need for a retransmission, we poll the
+ application for new data. */
+ uip_flags = UIP_POLL;
+ UIP_APPCALL();
+ goto appsend;
+ }
+ }
+ goto drop;
+ }
+#if UIP_UDP
+ if(flag == UIP_UDP_TIMER) {
+ if(uip_udp_conn->lport != 0) {
+ uip_conn = NULL;
+ uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
+ uip_len = uip_slen = 0;
+ uip_flags = UIP_POLL;
+ UIP_UDP_APPCALL();
+ goto udp_send;
+ } else {
+ goto drop;
+ }
+ }
+#endif
+
+ /* This is where the input processing starts. */
+ UIP_STAT(++uip_stat.ip.recv);
+
+ /* Start of IP input header processing code. */
+
+#if UIP_CONF_IPV6
+ /* Check validity of the IP header. */
+ if((BUF->vtc & 0xf0) != 0x60) { /* IP version and header length. */
+ UIP_STAT(++uip_stat.ip.drop);
+ UIP_STAT(++uip_stat.ip.vhlerr);
+ UIP_LOG("ipv6: invalid version.");
+ goto drop;
+ }
+#else /* UIP_CONF_IPV6 */
+ /* Check validity of the IP header. */
+ if(BUF->vhl != 0x45) { /* IP version and header length. */
+ UIP_STAT(++uip_stat.ip.drop);
+ UIP_STAT(++uip_stat.ip.vhlerr);
+ UIP_LOG("ip: invalid version or header length.");
+ goto drop;
+ }
+#endif /* UIP_CONF_IPV6 */
+
+ /* Check the size of the packet. If the size reported to us in
+ uip_len is smaller the size reported in the IP header, we assume
+ that the packet has been corrupted in transit. If the size of
+ uip_len is larger than the size reported in the IP packet header,
+ the packet has been padded and we set uip_len to the correct
+ value.. */
+
+ if((BUF->len[0] << 8) + BUF->len[1] <= uip_len) {
+ uip_len = (BUF->len[0] << 8) + BUF->len[1];
+#if UIP_CONF_IPV6
+ uip_len += 40; /* The length reported in the IPv6 header is the
+ length of the payload that follows the
+ header. However, uIP uses the uip_len variable
+ for holding the size of the entire packet,
+ including the IP header. For IPv4 this is not a
+ problem as the length field in the IPv4 header
+ contains the length of the entire packet. But
+ for IPv6 we need to add the size of the IPv6
+ header (40 bytes). */
+#endif /* UIP_CONF_IPV6 */
+ } else {
+ UIP_LOG("ip: packet shorter than reported in IP header.");
+ goto drop;
+ }
+
+#if !UIP_CONF_IPV6
+ /* Check the fragment flag. */
+ if((BUF->ipoffset[0] & 0x3f) != 0 ||
+ BUF->ipoffset[1] != 0) {
+#if UIP_REASSEMBLY
+ uip_len = uip_reass();
+ if(uip_len == 0) {
+ goto drop;
+ }
+#else /* UIP_REASSEMBLY */
+ UIP_STAT(++uip_stat.ip.drop);
+ UIP_STAT(++uip_stat.ip.fragerr);
+ UIP_LOG("ip: fragment dropped.");
+ goto drop;
+#endif /* UIP_REASSEMBLY */
+ }
+#endif /* UIP_CONF_IPV6 */
+
+ if(uip_ipaddr_cmp(uip_hostaddr, all_zeroes_addr)) {
+ /* If we are configured to use ping IP address configuration and
+ hasn't been assigned an IP address yet, we accept all ICMP
+ packets. */
+#if UIP_PINGADDRCONF && !UIP_CONF_IPV6
+ if(BUF->proto == UIP_PROTO_ICMP) {
+ UIP_LOG("ip: possible ping config packet received.");
+ goto icmp_input;
+ } else {
+ UIP_LOG("ip: packet dropped since no address assigned.");
+ goto drop;
+ }
+#endif /* UIP_PINGADDRCONF */
+
+ } else {
+ /* If IP broadcast support is configured, we check for a broadcast
+ UDP packet, which may be destined to us. */
+#if UIP_BROADCAST
+ DEBUG_PRINTF("UDP IP checksum 0x%04x\n", uip_ipchksum());
+ if(BUF->proto == UIP_PROTO_UDP &&
+ uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr)
+ /*&&
+ uip_ipchksum() == 0xffff*/) {
+ goto udp_input;
+ }
+#endif /* UIP_BROADCAST */
+
+ /* Check if the packet is destined for our IP address. */
+#if !UIP_CONF_IPV6
+ if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr)) {
+ UIP_STAT(++uip_stat.ip.drop);
+ goto drop;
+ }
+#else /* UIP_CONF_IPV6 */
+ /* For IPv6, packet reception is a little trickier as we need to
+ make sure that we listen to certain multicast addresses (all
+ hosts multicast address, and the solicited-node multicast
+ address) as well. However, we will cheat here and accept all
+ multicast packets that are sent to the ff02::/16 addresses. */
+ if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr) &&
+ BUF->destipaddr[0] != HTONS(0xff02)) {
+ UIP_STAT(++uip_stat.ip.drop);
+ goto drop;
+ }
+#endif /* UIP_CONF_IPV6 */
+ }
+
+#if !UIP_CONF_IPV6
+ if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header
+ checksum. */
+ UIP_STAT(++uip_stat.ip.drop);
+ UIP_STAT(++uip_stat.ip.chkerr);
+ UIP_LOG("ip: bad checksum.");
+ goto drop;
+ }
+#endif /* UIP_CONF_IPV6 */
+
+ if(BUF->proto == UIP_PROTO_TCP) { /* Check for TCP packet. If so,
+ proceed with TCP input
+ processing. */
+ goto tcp_input;
+ }
+
+#if UIP_UDP
+ if(BUF->proto == UIP_PROTO_UDP) {
+ goto udp_input;
+ }
+#endif /* UIP_UDP */
+
+#if !UIP_CONF_IPV6
+ /* ICMPv4 processing code follows. */
+ if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from
+ here. */
+ UIP_STAT(++uip_stat.ip.drop);
+ UIP_STAT(++uip_stat.ip.protoerr);
+ UIP_LOG("ip: neither tcp nor icmp.");
+ goto drop;
+ }
+
+#if UIP_PINGADDRCONF
+ icmp_input:
+#endif /* UIP_PINGADDRCONF */
+ UIP_STAT(++uip_stat.icmp.recv);
+
+ /* ICMP echo (i.e., ping) processing. This is simple, we only change
+ the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP
+ checksum before we return the packet. */
+ if(ICMPBUF->type != ICMP_ECHO) {
+ UIP_STAT(++uip_stat.icmp.drop);
+ UIP_STAT(++uip_stat.icmp.typeerr);
+ UIP_LOG("icmp: not icmp echo.");
+ goto drop;
+ }
+
+ /* If we are configured to use ping IP address assignment, we use
+ the destination IP address of this ping packet and assign it to
+ ourself. */
+#if UIP_PINGADDRCONF
+ if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) {
+ uip_hostaddr[0] = BUF->destipaddr[0];
+ uip_hostaddr[1] = BUF->destipaddr[1];
+ }
+#endif /* UIP_PINGADDRCONF */
+
+ ICMPBUF->type = ICMP_ECHO_REPLY;
+
+ if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) {
+ ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1;
+ } else {
+ ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8);
+ }
+
+ /* Swap IP addresses. */
+ uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
+ uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
+
+ UIP_STAT(++uip_stat.icmp.sent);
+ goto send;
+
+ /* End of IPv4 input header processing code. */
+#else /* !UIP_CONF_IPV6 */
+
+ /* This is IPv6 ICMPv6 processing code. */
+ DEBUG_PRINTF("icmp6_input: length %d\n", uip_len);
+
+ if(BUF->proto != UIP_PROTO_ICMP6) { /* We only allow ICMPv6 packets from
+ here. */
+ UIP_STAT(++uip_stat.ip.drop);
+ UIP_STAT(++uip_stat.ip.protoerr);
+ UIP_LOG("ip: neither tcp nor icmp6.");
+ goto drop;
+ }
+
+ UIP_STAT(++uip_stat.icmp.recv);
+
+ /* If we get a neighbor solicitation for our address we should send
+ a neighbor advertisement message back. */
+ if(ICMPBUF->type == ICMP6_NEIGHBOR_SOLICITATION) {
+ if(uip_ipaddr_cmp(ICMPBUF->icmp6data, uip_hostaddr)) {
+
+ if(ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS) {
+ /* Save the sender's address in our neighbor list. */
+ uip_neighbor_add(ICMPBUF->srcipaddr, &(ICMPBUF->options[2]));
+ }
+
+ /* We should now send a neighbor advertisement back to where the
+ neighbor solicication came from. */
+ ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT;
+ ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */
+
+ ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0;
+
+ uip_ipaddr_copy(ICMPBUF->destipaddr, ICMPBUF->srcipaddr);
+ uip_ipaddr_copy(ICMPBUF->srcipaddr, uip_hostaddr);
+ ICMPBUF->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS;
+ ICMPBUF->options[1] = 1; /* Options length, 1 = 8 bytes. */
+ memcpy(&(ICMPBUF->options[2]), &uip_ethaddr, sizeof(uip_ethaddr));
+ ICMPBUF->icmpchksum = 0;
+ ICMPBUF->icmpchksum = ~uip_icmp6chksum();
+ goto send;
+
+ }
+ goto drop;
+ } else if(ICMPBUF->type == ICMP6_ECHO) {
+ /* ICMP echo (i.e., ping) processing. This is simple, we only
+ change the ICMP type from ECHO to ECHO_REPLY and update the
+ ICMP checksum before we return the packet. */
+
+ ICMPBUF->type = ICMP6_ECHO_REPLY;
+
+ uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
+ uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
+ ICMPBUF->icmpchksum = 0;
+ ICMPBUF->icmpchksum = ~uip_icmp6chksum();
+
+ UIP_STAT(++uip_stat.icmp.sent);
+ goto send;
+ } else {
+ DEBUG_PRINTF("Unknown icmp6 message type %d\n", ICMPBUF->type);
+ UIP_STAT(++uip_stat.icmp.drop);
+ UIP_STAT(++uip_stat.icmp.typeerr);
+ UIP_LOG("icmp: unknown ICMP message.");
+ goto drop;
+ }
+
+ /* End of IPv6 ICMP processing. */
+
+#endif /* !UIP_CONF_IPV6 */
+
+#if UIP_UDP
+ /* UDP input processing. */
+ udp_input:
+ /* UDP processing is really just a hack. We don't do anything to the
+ UDP/IP headers, but let the UDP application do all the hard
+ work. If the application sets uip_slen, it has a packet to
+ send. */
+#if UIP_UDP_CHECKSUMS
+ uip_len = uip_len - UIP_IPUDPH_LEN;
+ uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
+ if(UDPBUF->udpchksum != 0 && uip_udpchksum() != 0xffff) {
+ UIP_STAT(++uip_stat.udp.drop);
+ UIP_STAT(++uip_stat.udp.chkerr);
+ UIP_LOG("udp: bad checksum.");
+ goto drop;
+ }
+#else /* UIP_UDP_CHECKSUMS */
+ uip_len = uip_len - UIP_IPUDPH_LEN;
+#endif /* UIP_UDP_CHECKSUMS */
+
+ /* Demultiplex this UDP packet between the UDP "connections". */
+ for(uip_udp_conn = &uip_udp_conns[0];
+ uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS];
+ ++uip_udp_conn) {
+ /* If the local UDP port is non-zero, the connection is considered
+ to be used. If so, the local port number is checked against the
+ destination port number in the received packet. If the two port
+ numbers match, the remote port number is checked if the
+ connection is bound to a remote port. Finally, if the
+ connection is bound to a remote IP address, the source IP
+ address of the packet is checked. */
+ if(uip_udp_conn->lport != 0 &&
+ UDPBUF->destport == uip_udp_conn->lport &&
+ (uip_udp_conn->rport == 0 ||
+ UDPBUF->srcport == uip_udp_conn->rport) &&
+ (uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) ||
+ uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) ||
+ uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) {
+ goto udp_found;
+ }
+ }
+ UIP_LOG("udp: no matching connection found");
+ goto drop;
+
+ udp_found:
+ if (uip_udp_conn->rport == 0) {
+ uip_udp_conn->rport = UDPBUF->srcport;
+ }
+ uip_conn = NULL;
+ uip_flags = UIP_NEWDATA;
+ uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
+ uip_slen = 0;
+ UIP_UDP_APPCALL();
+ udp_send:
+ if(uip_slen == 0) {
+ goto drop;
+ }
+ uip_len = uip_slen + UIP_IPUDPH_LEN;
+
+#if UIP_CONF_IPV6
+ /* For IPv6, the IP length field does not include the IPv6 IP header
+ length. */
+ BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
+ BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
+#else /* UIP_CONF_IPV6 */
+ BUF->len[0] = (uip_len >> 8);
+ BUF->len[1] = (uip_len & 0xff);
+#endif /* UIP_CONF_IPV6 */
+
+ BUF->ttl = uip_udp_conn->ttl;
+ BUF->proto = UIP_PROTO_UDP;
+
+ UDPBUF->udplen = HTONS(uip_slen + UIP_UDPH_LEN);
+ UDPBUF->udpchksum = 0;
+
+ BUF->srcport = uip_udp_conn->lport;
+ BUF->destport = uip_udp_conn->rport;
+
+ uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
+ uip_ipaddr_copy(BUF->destipaddr, uip_udp_conn->ripaddr);
+
+ uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN];
+
+#if UIP_UDP_CHECKSUMS
+ /* Calculate UDP checksum. */
+ UDPBUF->udpchksum = ~(uip_udpchksum());
+ if(UDPBUF->udpchksum == 0) {
+ UDPBUF->udpchksum = 0xffff;
+ }
+#endif /* UIP_UDP_CHECKSUMS */
+
+ goto ip_send_nolen;
+#endif /* UIP_UDP */
+
+ /* TCP input processing. */
+ tcp_input:
+ UIP_STAT(++uip_stat.tcp.recv);
+
+ /* Start of TCP input header processing code. */
+
+ if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP
+ checksum. */
+ UIP_STAT(++uip_stat.tcp.drop);
+ UIP_STAT(++uip_stat.tcp.chkerr);
+ UIP_LOG("tcp: bad checksum.");
+ goto drop;
+ }
+
+
+ /* Demultiplex this segment. */
+ /* First check any active connections. */
+ for(uip_connr = &uip_conns[0]; uip_connr <= &uip_conns[UIP_CONNS - 1];
+ ++uip_connr) {
+ if(uip_connr->tcpstateflags != UIP_CLOSED &&
+ BUF->destport == uip_connr->lport &&
+ BUF->srcport == uip_connr->rport &&
+ uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr)) {
+ goto found;
+ }
+ }
+
+ /* If we didn't find and active connection that expected the packet,
+ either this packet is an old duplicate, or this is a SYN packet
+ destined for a connection in LISTEN. If the SYN flag isn't set,
+ it is an old packet and we send a RST. */
+ if((BUF->flags & TCP_CTL) != TCP_SYN) {
+ goto reset;
+ }
+
+ tmp16 = BUF->destport;
+ /* Next, check listening connections. */
+ for(c = 0; c < UIP_LISTENPORTS; ++c) {
+ if(tmp16 == uip_listenports[c])
+ goto found_listen;
+ }
+
+ /* No matching connection found, so we send a RST packet. */
+ UIP_STAT(++uip_stat.tcp.synrst);
+ reset:
+
+ /* We do not send resets in response to resets. */
+ if(BUF->flags & TCP_RST) {
+ goto drop;
+ }
+
+ UIP_STAT(++uip_stat.tcp.rst);
+
+ BUF->flags = TCP_RST | TCP_ACK;
+ uip_len = UIP_IPTCPH_LEN;
+ BUF->tcpoffset = 5 << 4;
+
+ /* Flip the seqno and ackno fields in the TCP header. */
+ c = BUF->seqno[3];
+ BUF->seqno[3] = BUF->ackno[3];
+ BUF->ackno[3] = c;
+
+ c = BUF->seqno[2];
+ BUF->seqno[2] = BUF->ackno[2];
+ BUF->ackno[2] = c;
+
+ c = BUF->seqno[1];
+ BUF->seqno[1] = BUF->ackno[1];
+ BUF->ackno[1] = c;
+
+ c = BUF->seqno[0];
+ BUF->seqno[0] = BUF->ackno[0];
+ BUF->ackno[0] = c;
+
+ /* We also have to increase the sequence number we are
+ acknowledging. If the least significant byte overflowed, we need
+ to propagate the carry to the other bytes as well. */
+ if(++BUF->ackno[3] == 0) {
+ if(++BUF->ackno[2] == 0) {
+ if(++BUF->ackno[1] == 0) {
+ ++BUF->ackno[0];
+ }
+ }
+ }
+
+ /* Swap port numbers. */
+ tmp16 = BUF->srcport;
+ BUF->srcport = BUF->destport;
+ BUF->destport = tmp16;
+
+ /* Swap IP addresses. */
+ uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
+ uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
+
+ /* And send out the RST packet! */
+ goto tcp_send_noconn;
+
+ /* This label will be jumped to if we matched the incoming packet
+ with a connection in LISTEN. In that case, we should create a new
+ connection and send a SYNACK in return. */
+ found_listen:
+ /* First we check if there are any connections avaliable. Unused
+ connections are kept in the same table as used connections, but
+ unused ones have the tcpstate set to CLOSED. Also, connections in
+ TIME_WAIT are kept track of and we'll use the oldest one if no
+ CLOSED connections are found. Thanks to Eddie C. Dost for a very
+ nice algorithm for the TIME_WAIT search. */
+ uip_connr = 0;
+ for(c = 0; c < UIP_CONNS; ++c) {
+ if(uip_conns[c].tcpstateflags == UIP_CLOSED) {
+ uip_connr = &uip_conns[c];
+ break;
+ }
+ if(uip_conns[c].tcpstateflags == UIP_TIME_WAIT) {
+ if(uip_connr == 0 ||
+ uip_conns[c].timer > uip_connr->timer) {
+ uip_connr = &uip_conns[c];
+ }
+ }
+ }
+
+ if(uip_connr == 0) {
+ /* All connections are used already, we drop packet and hope that
+ the remote end will retransmit the packet at a time when we
+ have more spare connections. */
+ UIP_STAT(++uip_stat.tcp.syndrop);
+ UIP_LOG("tcp: found no unused connections.");
+ goto drop;
+ }
+ uip_conn = uip_connr;
+
+ /* Fill in the necessary fields for the new connection. */
+ uip_connr->rto = uip_connr->timer = UIP_RTO;
+ uip_connr->sa = 0;
+ uip_connr->sv = 4;
+ uip_connr->nrtx = 0;
+ uip_connr->lport = BUF->destport;
+ uip_connr->rport = BUF->srcport;
+ uip_ipaddr_copy(uip_connr->ripaddr, BUF->srcipaddr);
+ uip_connr->tcpstateflags = UIP_SYN_RCVD;
+
+ uip_connr->snd_nxt[0] = iss[0];
+ uip_connr->snd_nxt[1] = iss[1];
+ uip_connr->snd_nxt[2] = iss[2];
+ uip_connr->snd_nxt[3] = iss[3];
+ uip_connr->len = 1;
+
+ /* rcv_nxt should be the seqno from the incoming packet + 1. */
+ uip_connr->rcv_nxt[3] = BUF->seqno[3];
+ uip_connr->rcv_nxt[2] = BUF->seqno[2];
+ uip_connr->rcv_nxt[1] = BUF->seqno[1];
+ uip_connr->rcv_nxt[0] = BUF->seqno[0];
+ uip_add_rcv_nxt(1);
+
+ /* Parse the TCP MSS option, if present. */
+ if((BUF->tcpoffset & 0xf0) > 0x50) {
+ for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
+ opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];
+ if(opt == TCP_OPT_END) {
+ /* End of options. */
+ break;
+ } else if(opt == TCP_OPT_NOOP) {
+ ++c;
+ /* NOP option. */
+ } else if(opt == TCP_OPT_MSS &&
+ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
+ /* An MSS option with the right option length. */
+ tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
+ (u16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c];
+ uip_connr->initialmss = uip_connr->mss =
+ tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
+
+ /* And we are done processing options. */
+ break;
+ } else {
+ /* All other options have a length field, so that we easily
+ can skip past them. */
+ if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
+ /* If the length field is zero, the options are malformed
+ and we don't process them further. */
+ break;
+ }
+ c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
+ }
+ }
+ }
+
+ /* Our response will be a SYNACK. */
+#if UIP_ACTIVE_OPEN
+ tcp_send_synack:
+ BUF->flags = TCP_ACK;
+
+ tcp_send_syn:
+ BUF->flags |= TCP_SYN;
+#else /* UIP_ACTIVE_OPEN */
+ tcp_send_synack:
+ BUF->flags = TCP_SYN | TCP_ACK;
+#endif /* UIP_ACTIVE_OPEN */
+
+ /* We send out the TCP Maximum Segment Size option with our
+ SYNACK. */
+ BUF->optdata[0] = TCP_OPT_MSS;
+ BUF->optdata[1] = TCP_OPT_MSS_LEN;
+ BUF->optdata[2] = (UIP_TCP_MSS) / 256;
+ BUF->optdata[3] = (UIP_TCP_MSS) & 255;
+ uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN;
+ BUF->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4;
+ goto tcp_send;
+
+ /* This label will be jumped to if we found an active connection. */
+ found:
+ uip_conn = uip_connr;
+ uip_flags = 0;
+ /* We do a very naive form of TCP reset processing; we just accept
+ any RST and kill our connection. We should in fact check if the
+ sequence number of this reset is wihtin our advertised window
+ before we accept the reset. */
+ if(BUF->flags & TCP_RST) {
+ uip_connr->tcpstateflags = UIP_CLOSED;
+ UIP_LOG("tcp: got reset, aborting connection.");
+ uip_flags = UIP_ABORT;
+ UIP_APPCALL();
+ goto drop;
+ }
+ /* Calculated the length of the data, if the application has sent
+ any data to us. */
+ c = (BUF->tcpoffset >> 4) << 2;
+ /* uip_len will contain the length of the actual TCP data. This is
+ calculated by subtracing the length of the TCP header (in
+ c) and the length of the IP header (20 bytes). */
+ uip_len = uip_len - c - UIP_IPH_LEN;
+
+ /* First, check if the sequence number of the incoming packet is
+ what we're expecting next. If not, we send out an ACK with the
+ correct numbers in. */
+ if(!(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) &&
+ ((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)))) {
+ if((uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) &&
+ (BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
+ BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
+ BUF->seqno[2] != uip_connr->rcv_nxt[2] ||
+ BUF->seqno[3] != uip_connr->rcv_nxt[3])) {
+ goto tcp_send_ack;
+ }
+ }
+
+ /* Next, check if the incoming segment acknowledges any outstanding
+ data. If so, we update the sequence number, reset the length of
+ the outstanding data, calculate RTT estimations, and reset the
+ retransmission timer. */
+ if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) {
+ uip_add32(uip_connr->snd_nxt, uip_connr->len);
+
+ if(BUF->ackno[0] == uip_acc32[0] &&
+ BUF->ackno[1] == uip_acc32[1] &&
+ BUF->ackno[2] == uip_acc32[2] &&
+ BUF->ackno[3] == uip_acc32[3]) {
+ /* Update sequence number. */
+ uip_connr->snd_nxt[0] = uip_acc32[0];
+ uip_connr->snd_nxt[1] = uip_acc32[1];
+ uip_connr->snd_nxt[2] = uip_acc32[2];
+ uip_connr->snd_nxt[3] = uip_acc32[3];
+
+
+ /* Do RTT estimation, unless we have done retransmissions. */
+ if(uip_connr->nrtx == 0) {
+ signed char m;
+ m = uip_connr->rto - uip_connr->timer;
+ /* This is taken directly from VJs original code in his paper */
+ m = m - (uip_connr->sa >> 3);
+ uip_connr->sa += m;
+ if(m < 0) {
+ m = -m;
+ }
+ m = m - (uip_connr->sv >> 2);
+ uip_connr->sv += m;
+ uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv;
+
+ }
+ /* Set the acknowledged flag. */
+ uip_flags = UIP_ACKDATA;
+ /* Reset the retransmission timer. */
+ uip_connr->timer = uip_connr->rto;
+
+ /* Reset length of outstanding data. */
+ uip_connr->len = 0;
+ }
+
+ }
+
+ /* Do different things depending on in what state the connection is. */
+ switch(uip_connr->tcpstateflags & UIP_TS_MASK) {
+ /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not
+ implemented, since we force the application to close when the
+ peer sends a FIN (hence the application goes directly from
+ ESTABLISHED to LAST_ACK). */
+ case UIP_SYN_RCVD:
+ /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and
+ we are waiting for an ACK that acknowledges the data we sent
+ out the last time. Therefore, we want to have the UIP_ACKDATA
+ flag set. If so, we enter the ESTABLISHED state. */
+ if(uip_flags & UIP_ACKDATA) {
+ uip_connr->tcpstateflags = UIP_ESTABLISHED;
+ uip_flags = UIP_CONNECTED;
+ uip_connr->len = 0;
+ if(uip_len > 0) {
+ uip_flags |= UIP_NEWDATA;
+ uip_add_rcv_nxt(uip_len);
+ }
+ uip_slen = 0;
+ UIP_APPCALL();
+ goto appsend;
+ }
+ goto drop;
+#if UIP_ACTIVE_OPEN
+ case UIP_SYN_SENT:
+ /* In SYN_SENT, we wait for a SYNACK that is sent in response to
+ our SYN. The rcv_nxt is set to sequence number in the SYNACK
+ plus one, and we send an ACK. We move into the ESTABLISHED
+ state. */
+ if((uip_flags & UIP_ACKDATA) &&
+ (BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) {
+
+ /* Parse the TCP MSS option, if present. */
+ if((BUF->tcpoffset & 0xf0) > 0x50) {
+ for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) {
+ opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c];
+ if(opt == TCP_OPT_END) {
+ /* End of options. */
+ break;
+ } else if(opt == TCP_OPT_NOOP) {
+ ++c;
+ /* NOP option. */
+ } else if(opt == TCP_OPT_MSS &&
+ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
+ /* An MSS option with the right option length. */
+ tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
+ uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];
+ uip_connr->initialmss =
+ uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
+
+ /* And we are done processing options. */
+ break;
+ } else {
+ /* All other options have a length field, so that we easily
+ can skip past them. */
+ if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
+ /* If the length field is zero, the options are malformed
+ and we don't process them further. */
+ break;
+ }
+ c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
+ }
+ }
+ }
+ uip_connr->tcpstateflags = UIP_ESTABLISHED;
+ uip_connr->rcv_nxt[0] = BUF->seqno[0];
+ uip_connr->rcv_nxt[1] = BUF->seqno[1];
+ uip_connr->rcv_nxt[2] = BUF->seqno[2];
+ uip_connr->rcv_nxt[3] = BUF->seqno[3];
+ uip_add_rcv_nxt(1);
+ uip_flags = UIP_CONNECTED | UIP_NEWDATA;
+ uip_connr->len = 0;
+ uip_len = 0;
+ uip_slen = 0;
+ UIP_APPCALL();
+ goto appsend;
+ }
+ /* Inform the application that the connection failed */
+ uip_flags = UIP_ABORT;
+ UIP_APPCALL();
+ /* The connection is closed after we send the RST */
+ uip_conn->tcpstateflags = UIP_CLOSED;
+ goto reset;
+#endif /* UIP_ACTIVE_OPEN */
+
+ case UIP_ESTABLISHED:
+ /* In the ESTABLISHED state, we call upon the application to feed
+ data into the uip_buf. If the UIP_ACKDATA flag is set, the
+ application should put new data into the buffer, otherwise we are
+ retransmitting an old segment, and the application should put that
+ data into the buffer.
+
+ If the incoming packet is a FIN, we should close the connection on
+ this side as well, and we send out a FIN and enter the LAST_ACK
+ state. We require that there is no outstanding data; otherwise the
+ sequence numbers will be screwed up. */
+
+ if(BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
+ if(uip_outstanding(uip_connr)) {
+ goto drop;
+ }
+ uip_add_rcv_nxt(1 + uip_len);
+ uip_flags |= UIP_CLOSE;
+ if(uip_len > 0) {
+ uip_flags |= UIP_NEWDATA;
+ }
+ UIP_APPCALL();
+ uip_connr->len = 1;
+ uip_connr->tcpstateflags = UIP_LAST_ACK;
+ uip_connr->nrtx = 0;
+ tcp_send_finack:
+ BUF->flags = TCP_FIN | TCP_ACK;
+ goto tcp_send_nodata;
+ }
+
+ /* Check the URG flag. If this is set, the segment carries urgent
+ data that we must pass to the application. */
+ if((BUF->flags & TCP_URG) != 0) {
+#if UIP_URGDATA > 0
+ uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1];
+ if(uip_urglen > uip_len) {
+ /* There is more urgent data in the next segment to come. */
+ uip_urglen = uip_len;
+ }
+ uip_add_rcv_nxt(uip_urglen);
+ uip_len -= uip_urglen;
+ uip_urgdata = uip_appdata;
+ uip_appdata += uip_urglen;
+ } else {
+ uip_urglen = 0;
+#else /* UIP_URGDATA > 0 */
+ uip_appdata = ((char *)uip_appdata) + ((BUF->urgp[0] << 8) | BUF->urgp[1]);
+ uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1];
+#endif /* UIP_URGDATA > 0 */
+ }
+
+ /* If uip_len > 0 we have TCP data in the packet, and we flag this
+ by setting the UIP_NEWDATA flag and update the sequence number
+ we acknowledge. If the application has stopped the dataflow
+ using uip_stop(), we must not accept any data packets from the
+ remote host. */
+ if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) {
+ uip_flags |= UIP_NEWDATA;
+ uip_add_rcv_nxt(uip_len);
+ }
+
+ /* Check if the available buffer space advertised by the other end
+ is smaller than the initial MSS for this connection. If so, we
+ set the current MSS to the window size to ensure that the
+ application does not send more data than the other end can
+ handle.
+
+ If the remote host advertises a zero window, we set the MSS to
+ the initial MSS so that the application will send an entire MSS
+ of data. This data will not be acknowledged by the receiver,
+ and the application will retransmit it. This is called the
+ "persistent timer" and uses the retransmission mechanim.
+ */
+ tmp16 = ((u16_t)BUF->wnd[0] << 8) + (u16_t)BUF->wnd[1];
+ if(tmp16 > uip_connr->initialmss ||
+ tmp16 == 0) {
+ tmp16 = uip_connr->initialmss;
+ }
+ uip_connr->mss = tmp16;
+
+ /* If this packet constitutes an ACK for outstanding data (flagged
+ by the UIP_ACKDATA flag, we should call the application since it
+ might want to send more data. If the incoming packet had data
+ from the peer (as flagged by the UIP_NEWDATA flag), the
+ application must also be notified.
+
+ When the application is called, the global variable uip_len
+ contains the length of the incoming data. The application can
+ access the incoming data through the global pointer
+ uip_appdata, which usually points UIP_IPTCPH_LEN + UIP_LLH_LEN
+ bytes into the uip_buf array.
+
+ If the application wishes to send any data, this data should be
+ put into the uip_appdata and the length of the data should be
+ put into uip_len. If the application don't have any data to
+ send, uip_len must be set to 0. */
+ if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) {
+ uip_slen = 0;
+ UIP_APPCALL();
+
+ appsend:
+
+ if(uip_flags & UIP_ABORT) {
+ uip_slen = 0;
+ uip_connr->tcpstateflags = UIP_CLOSED;
+ BUF->flags = TCP_RST | TCP_ACK;
+ goto tcp_send_nodata;
+ }
+
+ if(uip_flags & UIP_CLOSE) {
+ uip_slen = 0;
+ uip_connr->len = 1;
+ uip_connr->tcpstateflags = UIP_FIN_WAIT_1;
+ uip_connr->nrtx = 0;
+ BUF->flags = TCP_FIN | TCP_ACK;
+ goto tcp_send_nodata;
+ }
+
+ /* If uip_slen > 0, the application has data to be sent. */
+ if(uip_slen > 0) {
+
+ /* If the connection has acknowledged data, the contents of
+ the ->len variable should be discarded. */
+ if((uip_flags & UIP_ACKDATA) != 0) {
+ uip_connr->len = 0;
+ }
+
+ /* If the ->len variable is non-zero the connection has
+ already data in transit and cannot send anymore right
+ now. */
+ if(uip_connr->len == 0) {
+
+ /* The application cannot send more than what is allowed by
+ the mss (the minumum of the MSS and the available
+ window). */
+ if(uip_slen > uip_connr->mss) {
+ uip_slen = uip_connr->mss;
+ }
+
+ /* Remember how much data we send out now so that we know
+ when everything has been acknowledged. */
+ uip_connr->len = uip_slen;
+ } else {
+
+ /* If the application already had unacknowledged data, we
+ make sure that the application does not send (i.e.,
+ retransmit) out more than it previously sent out. */
+ uip_slen = uip_connr->len;
+ }
+ }
+ uip_connr->nrtx = 0;
+ apprexmit:
+ uip_appdata = uip_sappdata;
+
+ /* If the application has data to be sent, or if the incoming
+ packet had new data in it, we must send out a packet. */
+ if(uip_slen > 0 && uip_connr->len > 0) {
+ /* Add the length of the IP and TCP headers. */
+ uip_len = uip_connr->len + UIP_TCPIP_HLEN;
+ /* We always set the ACK flag in response packets. */
+ BUF->flags = TCP_ACK | TCP_PSH;
+ /* Send the packet. */
+ goto tcp_send_noopts;
+ }
+ /* If there is no data to send, just send out a pure ACK if
+ there is newdata. */
+ if(uip_flags & UIP_NEWDATA) {
+ uip_len = UIP_TCPIP_HLEN;
+ BUF->flags = TCP_ACK;
+ goto tcp_send_noopts;
+ }
+ }
+ goto drop;
+ case UIP_LAST_ACK:
+ /* We can close this connection if the peer has acknowledged our
+ FIN. This is indicated by the UIP_ACKDATA flag. */
+ if(uip_flags & UIP_ACKDATA) {
+ uip_connr->tcpstateflags = UIP_CLOSED;
+ uip_flags = UIP_CLOSE;
+ UIP_APPCALL();
+ }
+ break;
+
+ case UIP_FIN_WAIT_1:
+ /* The application has closed the connection, but the remote host
+ hasn't closed its end yet. Thus we do nothing but wait for a
+ FIN from the other side. */
+ if(uip_len > 0) {
+ uip_add_rcv_nxt(uip_len);
+ }
+ if(BUF->flags & TCP_FIN) {
+ if(uip_flags & UIP_ACKDATA) {
+ uip_connr->tcpstateflags = UIP_TIME_WAIT;
+ uip_connr->timer = 0;
+ uip_connr->len = 0;
+ } else {
+ uip_connr->tcpstateflags = UIP_CLOSING;
+ }
+ uip_add_rcv_nxt(1);
+ uip_flags = UIP_CLOSE;
+ UIP_APPCALL();
+ goto tcp_send_ack;
+ } else if(uip_flags & UIP_ACKDATA) {
+ uip_connr->tcpstateflags = UIP_FIN_WAIT_2;
+ uip_connr->len = 0;
+ goto drop;
+ }
+ if(uip_len > 0) {
+ goto tcp_send_ack;
+ }
+ goto drop;
+
+ case UIP_FIN_WAIT_2:
+ if(uip_len > 0) {
+ uip_add_rcv_nxt(uip_len);
+ }
+ if(BUF->flags & TCP_FIN) {
+ uip_connr->tcpstateflags = UIP_TIME_WAIT;
+ uip_connr->timer = 0;
+ uip_add_rcv_nxt(1);
+ uip_flags = UIP_CLOSE;
+ UIP_APPCALL();
+ goto tcp_send_ack;
+ }
+ if(uip_len > 0) {
+ goto tcp_send_ack;
+ }
+ goto drop;
+
+ case UIP_TIME_WAIT:
+ goto tcp_send_ack;
+
+ case UIP_CLOSING:
+ if(uip_flags & UIP_ACKDATA) {
+ uip_connr->tcpstateflags = UIP_TIME_WAIT;
+ uip_connr->timer = 0;
+ }
+ }
+ goto drop;
+
+
+ /* We jump here when we are ready to send the packet, and just want
+ to set the appropriate TCP sequence numbers in the TCP header. */
+ tcp_send_ack:
+ BUF->flags = TCP_ACK;
+ tcp_send_nodata:
+ uip_len = UIP_IPTCPH_LEN;
+ tcp_send_noopts:
+ BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4;
+ tcp_send:
+ /* We're done with the input processing. We are now ready to send a
+ reply. Our job is to fill in all the fields of the TCP and IP
+ headers before calculating the checksum and finally send the
+ packet. */
+ BUF->ackno[0] = uip_connr->rcv_nxt[0];
+ BUF->ackno[1] = uip_connr->rcv_nxt[1];
+ BUF->ackno[2] = uip_connr->rcv_nxt[2];
+ BUF->ackno[3] = uip_connr->rcv_nxt[3];
+
+ BUF->seqno[0] = uip_connr->snd_nxt[0];
+ BUF->seqno[1] = uip_connr->snd_nxt[1];
+ BUF->seqno[2] = uip_connr->snd_nxt[2];
+ BUF->seqno[3] = uip_connr->snd_nxt[3];
+
+ BUF->proto = UIP_PROTO_TCP;
+
+ BUF->srcport = uip_connr->lport;
+ BUF->destport = uip_connr->rport;
+
+ uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr);
+ uip_ipaddr_copy(BUF->destipaddr, uip_connr->ripaddr);
+
+ if(uip_connr->tcpstateflags & UIP_STOPPED) {
+ /* If the connection has issued uip_stop(), we advertise a zero
+ window so that the remote host will stop sending data. */
+ BUF->wnd[0] = BUF->wnd[1] = 0;
+ } else {
+ BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8);
+ BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff);
+ }
+
+ tcp_send_noconn:
+ BUF->ttl = UIP_TTL;
+#if UIP_CONF_IPV6
+ /* For IPv6, the IP length field does not include the IPv6 IP header
+ length. */
+ BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
+ BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
+#else /* UIP_CONF_IPV6 */
+ BUF->len[0] = (uip_len >> 8);
+ BUF->len[1] = (uip_len & 0xff);
+#endif /* UIP_CONF_IPV6 */
+
+ BUF->urgp[0] = BUF->urgp[1] = 0;
+
+ /* Calculate TCP checksum. */
+ BUF->tcpchksum = 0;
+ BUF->tcpchksum = ~(uip_tcpchksum());
+
+#if UIP_UDP
+ip_send_nolen:
+#endif /* UIP_UDP */
+
+#if UIP_CONF_IPV6
+ BUF->vtc = 0x60;
+ BUF->tcflow = 0x00;
+ BUF->flow = 0x00;
+#else /* UIP_CONF_IPV6 */
+ BUF->vhl = 0x45;
+ BUF->tos = 0;
+ BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
+ ++ipid;
+ BUF->ipid[0] = ipid >> 8;
+ BUF->ipid[1] = ipid & 0xff;
+ /* Calculate IP checksum. */
+ BUF->ipchksum = 0;
+ BUF->ipchksum = ~(uip_ipchksum());
+ DEBUG_PRINTF("uip ip_send_nolen: chkecum 0x%04x\n", uip_ipchksum());
+#endif /* UIP_CONF_IPV6 */
+
+ UIP_STAT(++uip_stat.tcp.sent);
+ send:
+ DEBUG_PRINTF("Sending packet with length %d (%d)\n", uip_len,
+ (BUF->len[0] << 8) | BUF->len[1]);
+
+ UIP_STAT(++uip_stat.ip.sent);
+ /* Return and let the caller do the actual transmission. */
+ uip_flags = 0;
+ return;
+ drop:
+ uip_len = 0;
+ uip_flags = 0;
+ return;
+}
+/*---------------------------------------------------------------------------*/
+u16_t
+htons(u16_t val)
+{
+ return HTONS(val);
+}
+/*---------------------------------------------------------------------------*/
+void
+uip_send(const void *data, int len)
+{
+ if(len > 0) {
+ uip_slen = len;
+ if(data != uip_sappdata) {
+ memcpy(uip_sappdata, (data), uip_slen);
+ }
+ }
+}
+/** @} */
diff --git a/Libraries/WiShield/uip.h b/Libraries/WiShield/uip.h
new file mode 100644
index 0000000..9f2d843
--- /dev/null
+++ b/Libraries/WiShield/uip.h
@@ -0,0 +1,1634 @@
+
+/******************************************************************************
+
+ Filename: uip.h
+ Description: uIP TCP/IP stack for the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/29/2009 Initial port
+
+ *****************************************************************************/
+
+/**
+ * \addtogroup uip
+ * @{
+ */
+
+/**
+ * \file
+ * Header file for the uIP TCP/IP stack.
+ * \author Adam Dunkels <adam@dunkels.com>
+ *
+ * The uIP TCP/IP stack header file contains definitions for a number
+ * of C macros that are used by uIP programs as well as internal uIP
+ * structures, TCP/IP header structures and function declarations.
+ *
+ */
+
+
+/*
+ * Copyright (c) 2001-2003, Adam Dunkels.
+ * 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 the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: uip.h,v 1.40 2006/06/08 07:12:07 adam Exp $
+ *
+ */
+
+#ifndef __UIP_H__
+#define __UIP_H__
+
+#include "uipopt.h"
+
+/**
+ * Repressentation of an IP address.
+ *
+ */
+typedef u16_t uip_ip4addr_t[2];
+typedef u16_t uip_ip6addr_t[8];
+#if UIP_CONF_IPV6
+typedef uip_ip6addr_t uip_ipaddr_t;
+#else /* UIP_CONF_IPV6 */
+typedef uip_ip4addr_t uip_ipaddr_t;
+#endif /* UIP_CONF_IPV6 */
+
+/*---------------------------------------------------------------------------*/
+/* First, the functions that should be called from the
+ * system. Initialization, the periodic timer and incoming packets are
+ * handled by the following three functions.
+ */
+
+/**
+ * \defgroup uipconffunc uIP configuration functions
+ * @{
+ *
+ * The uIP configuration functions are used for setting run-time
+ * parameters in uIP such as IP addresses.
+ */
+
+/**
+ * Set the IP address of this host.
+ *
+ * The IP address is represented as a 4-byte array where the first
+ * octet of the IP address is put in the first member of the 4-byte
+ * array.
+ *
+ * Example:
+ \code
+
+ uip_ipaddr_t addr;
+
+ uip_ipaddr(&addr, 192,168,1,2);
+ uip_sethostaddr(&addr);
+
+ \endcode
+ * \param addr A pointer to an IP address of type uip_ipaddr_t;
+ *
+ * \sa uip_ipaddr()
+ *
+ * \hideinitializer
+ */
+#define uip_sethostaddr(addr) uip_ipaddr_copy(uip_hostaddr, (addr))
+
+/**
+ * Get the IP address of this host.
+ *
+ * The IP address is represented as a 4-byte array where the first
+ * octet of the IP address is put in the first member of the 4-byte
+ * array.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t hostaddr;
+
+ uip_gethostaddr(&hostaddr);
+ \endcode
+ * \param addr A pointer to a uip_ipaddr_t variable that will be
+ * filled in with the currently configured IP address.
+ *
+ * \hideinitializer
+ */
+#define uip_gethostaddr(addr) uip_ipaddr_copy((addr), uip_hostaddr)
+
+/**
+ * Set the default router's IP address.
+ *
+ * \param addr A pointer to a uip_ipaddr_t variable containing the IP
+ * address of the default router.
+ *
+ * \sa uip_ipaddr()
+ *
+ * \hideinitializer
+ */
+#define uip_setdraddr(addr) uip_ipaddr_copy(uip_draddr, (addr))
+
+/**
+ * Set the netmask.
+ *
+ * \param addr A pointer to a uip_ipaddr_t variable containing the IP
+ * address of the netmask.
+ *
+ * \sa uip_ipaddr()
+ *
+ * \hideinitializer
+ */
+#define uip_setnetmask(addr) uip_ipaddr_copy(uip_netmask, (addr))
+
+
+/**
+ * Get the default router's IP address.
+ *
+ * \param addr A pointer to a uip_ipaddr_t variable that will be
+ * filled in with the IP address of the default router.
+ *
+ * \hideinitializer
+ */
+#define uip_getdraddr(addr) uip_ipaddr_copy((addr), uip_draddr)
+
+/**
+ * Get the netmask.
+ *
+ * \param addr A pointer to a uip_ipaddr_t variable that will be
+ * filled in with the value of the netmask.
+ *
+ * \hideinitializer
+ */
+#define uip_getnetmask(addr) uip_ipaddr_copy((addr), uip_netmask)
+
+/** @} */
+
+/**
+ * \defgroup uipinit uIP initialization functions
+ * @{
+ *
+ * The uIP initialization functions are used for booting uIP.
+ */
+
+/**
+ * uIP initialization function.
+ *
+ * This function should be called at boot up to initilize the uIP
+ * TCP/IP stack.
+ */
+void uip_init(void);
+
+/**
+ * uIP initialization function.
+ *
+ * This function may be used at boot time to set the initial ip_id.
+ */
+void uip_setipid(u16_t id);
+
+/** @} */
+
+/**
+ * \defgroup uipdevfunc uIP device driver functions
+ * @{
+ *
+ * These functions are used by a network device driver for interacting
+ * with uIP.
+ */
+
+/**
+ * Process an incoming packet.
+ *
+ * This function should be called when the device driver has received
+ * a packet from the network. The packet from the device driver must
+ * be present in the uip_buf buffer, and the length of the packet
+ * should be placed in the uip_len variable.
+ *
+ * When the function returns, there may be an outbound packet placed
+ * in the uip_buf packet buffer. If so, the uip_len variable is set to
+ * the length of the packet. If no packet is to be sent out, the
+ * uip_len variable is set to 0.
+ *
+ * The usual way of calling the function is presented by the source
+ * code below.
+ \code
+ uip_len = devicedriver_poll();
+ if(uip_len > 0) {
+ uip_input();
+ if(uip_len > 0) {
+ devicedriver_send();
+ }
+ }
+ \endcode
+ *
+ * \note If you are writing a uIP device driver that needs ARP
+ * (Address Resolution Protocol), e.g., when running uIP over
+ * Ethernet, you will need to call the uIP ARP code before calling
+ * this function:
+ \code
+ #define BUF ((struct uip_eth_hdr *)&uip_buf[0])
+ uip_len = ethernet_devicedrver_poll();
+ if(uip_len > 0) {
+ if(BUF->type == HTONS(UIP_ETHTYPE_IP)) {
+ uip_arp_ipin();
+ uip_input();
+ if(uip_len > 0) {
+ uip_arp_out();
+ ethernet_devicedriver_send();
+ }
+ } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) {
+ uip_arp_arpin();
+ if(uip_len > 0) {
+ ethernet_devicedriver_send();
+ }
+ }
+ \endcode
+ *
+ * \hideinitializer
+ */
+#define uip_input() uip_process(UIP_DATA)
+
+/**
+ * Periodic processing for a connection identified by its number.
+ *
+ * This function does the necessary periodic processing (timers,
+ * polling) for a uIP TCP conneciton, and should be called when the
+ * periodic uIP timer goes off. It should be called for every
+ * connection, regardless of whether they are open of closed.
+ *
+ * When the function returns, it may have an outbound packet waiting
+ * for service in the uIP packet buffer, and if so the uip_len
+ * variable is set to a value larger than zero. The device driver
+ * should be called to send out the packet.
+ *
+ * The ususal way of calling the function is through a for() loop like
+ * this:
+ \code
+ for(i = 0; i < UIP_CONNS; ++i) {
+ uip_periodic(i);
+ if(uip_len > 0) {
+ devicedriver_send();
+ }
+ }
+ \endcode
+ *
+ * \note If you are writing a uIP device driver that needs ARP
+ * (Address Resolution Protocol), e.g., when running uIP over
+ * Ethernet, you will need to call the uip_arp_out() function before
+ * calling the device driver:
+ \code
+ for(i = 0; i < UIP_CONNS; ++i) {
+ uip_periodic(i);
+ if(uip_len > 0) {
+ uip_arp_out();
+ ethernet_devicedriver_send();
+ }
+ }
+ \endcode
+ *
+ * \param conn The number of the connection which is to be periodically polled.
+ *
+ * \hideinitializer
+ */
+#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \
+ uip_process(UIP_TIMER); } while (0)
+
+/**
+ *
+ *
+ */
+#define uip_conn_active(conn) (uip_conns[conn].tcpstateflags != UIP_CLOSED)
+
+/**
+ * Perform periodic processing for a connection identified by a pointer
+ * to its structure.
+ *
+ * Same as uip_periodic() but takes a pointer to the actual uip_conn
+ * struct instead of an integer as its argument. This function can be
+ * used to force periodic processing of a specific connection.
+ *
+ * \param conn A pointer to the uip_conn struct for the connection to
+ * be processed.
+ *
+ * \hideinitializer
+ */
+#define uip_periodic_conn(conn) do { uip_conn = conn; \
+ uip_process(UIP_TIMER); } while (0)
+
+/**
+ * Reuqest that a particular connection should be polled.
+ *
+ * Similar to uip_periodic_conn() but does not perform any timer
+ * processing. The application is polled for new data.
+ *
+ * \param conn A pointer to the uip_conn struct for the connection to
+ * be processed.
+ *
+ * \hideinitializer
+ */
+#define uip_poll_conn(conn) do { uip_conn = conn; \
+ uip_process(UIP_POLL_REQUEST); } while (0)
+
+
+#if UIP_UDP
+/**
+ * Periodic processing for a UDP connection identified by its number.
+ *
+ * This function is essentially the same as uip_periodic(), but for
+ * UDP connections. It is called in a similar fashion as the
+ * uip_periodic() function:
+ \code
+ for(i = 0; i < UIP_UDP_CONNS; i++) {
+ uip_udp_periodic(i);
+ if(uip_len > 0) {
+ devicedriver_send();
+ }
+ }
+ \endcode
+ *
+ * \note As for the uip_periodic() function, special care has to be
+ * taken when using uIP together with ARP and Ethernet:
+ \code
+ for(i = 0; i < UIP_UDP_CONNS; i++) {
+ uip_udp_periodic(i);
+ if(uip_len > 0) {
+ uip_arp_out();
+ ethernet_devicedriver_send();
+ }
+ }
+ \endcode
+ *
+ * \param conn The number of the UDP connection to be processed.
+ *
+ * \hideinitializer
+ */
+#define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \
+ uip_process(UIP_UDP_TIMER); } while (0)
+
+/**
+ * Periodic processing for a UDP connection identified by a pointer to
+ * its structure.
+ *
+ * Same as uip_udp_periodic() but takes a pointer to the actual
+ * uip_conn struct instead of an integer as its argument. This
+ * function can be used to force periodic processing of a specific
+ * connection.
+ *
+ * \param conn A pointer to the uip_udp_conn struct for the connection
+ * to be processed.
+ *
+ * \hideinitializer
+ */
+#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \
+ uip_process(UIP_UDP_TIMER); } while (0)
+
+
+#endif /* UIP_UDP */
+
+/**
+ * The uIP packet buffer.
+ *
+ * The uip_buf array is used to hold incoming and outgoing
+ * packets. The device driver should place incoming data into this
+ * buffer. When sending data, the device driver should read the link
+ * level headers and the TCP/IP headers from this buffer. The size of
+ * the link level headers is configured by the UIP_LLH_LEN define.
+ *
+ * \note The application data need not be placed in this buffer, so
+ * the device driver must read it from the place pointed to by the
+ * uip_appdata pointer as illustrated by the following example:
+ \code
+ void
+ devicedriver_send(void)
+ {
+ hwsend(&uip_buf[0], UIP_LLH_LEN);
+ if(uip_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN) {
+ hwsend(&uip_buf[UIP_LLH_LEN], uip_len - UIP_LLH_LEN);
+ } else {
+ hwsend(&uip_buf[UIP_LLH_LEN], UIP_TCPIP_HLEN);
+ hwsend(uip_appdata, uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN);
+ }
+ }
+ \endcode
+ */
+extern u8_t uip_buf[UIP_BUFSIZE+2];
+
+/** @} */
+
+/*---------------------------------------------------------------------------*/
+/* Functions that are used by the uIP application program. Opening and
+ * closing connections, sending and receiving data, etc. is all
+ * handled by the functions below.
+*/
+/**
+ * \defgroup uipappfunc uIP application functions
+ * @{
+ *
+ * Functions used by an application running of top of uIP.
+ */
+
+/**
+ * Start listening to the specified port.
+ *
+ * \note Since this function expects the port number in network byte
+ * order, a conversion using HTONS() or htons() is necessary.
+ *
+ \code
+ uip_listen(HTONS(80));
+ \endcode
+ *
+ * \param port A 16-bit port number in network byte order.
+ */
+void uip_listen(u16_t port);
+
+/**
+ * Stop listening to the specified port.
+ *
+ * \note Since this function expects the port number in network byte
+ * order, a conversion using HTONS() or htons() is necessary.
+ *
+ \code
+ uip_unlisten(HTONS(80));
+ \endcode
+ *
+ * \param port A 16-bit port number in network byte order.
+ */
+void uip_unlisten(u16_t port);
+
+/**
+ * Connect to a remote host using TCP.
+ *
+ * This function is used to start a new connection to the specified
+ * port on the specied host. It allocates a new connection identifier,
+ * sets the connection to the SYN_SENT state and sets the
+ * retransmission timer to 0. This will cause a TCP SYN segment to be
+ * sent out the next time this connection is periodically processed,
+ * which usually is done within 0.5 seconds after the call to
+ * uip_connect().
+ *
+ * \note This function is avaliable only if support for active open
+ * has been configured by defining UIP_ACTIVE_OPEN to 1 in uipopt.h.
+ *
+ * \note Since this function requires the port number to be in network
+ * byte order, a conversion using HTONS() or htons() is necessary.
+ *
+ \code
+ uip_ipaddr_t ipaddr;
+
+ uip_ipaddr(&ipaddr, 192,168,1,2);
+ uip_connect(&ipaddr, HTONS(80));
+ \endcode
+ *
+ * \param ripaddr The IP address of the remote hot.
+ *
+ * \param port A 16-bit port number in network byte order.
+ *
+ * \return A pointer to the uIP connection identifier for the new connection,
+ * or NULL if no connection could be allocated.
+ *
+ */
+struct uip_conn *uip_connect(uip_ipaddr_t *ripaddr, u16_t port);
+
+
+
+/**
+ * \internal
+ *
+ * Check if a connection has outstanding (i.e., unacknowledged) data.
+ *
+ * \param conn A pointer to the uip_conn structure for the connection.
+ *
+ * \hideinitializer
+ */
+#define uip_outstanding(conn) ((conn)->len)
+
+/**
+ * Send data on the current connection.
+ *
+ * This function is used to send out a single segment of TCP
+ * data. Only applications that have been invoked by uIP for event
+ * processing can send data.
+ *
+ * The amount of data that actually is sent out after a call to this
+ * funcion is determined by the maximum amount of data TCP allows. uIP
+ * will automatically crop the data so that only the appropriate
+ * amount of data is sent. The function uip_mss() can be used to query
+ * uIP for the amount of data that actually will be sent.
+ *
+ * \note This function does not guarantee that the sent data will
+ * arrive at the destination. If the data is lost in the network, the
+ * application will be invoked with the uip_rexmit() event being
+ * set. The application will then have to resend the data using this
+ * function.
+ *
+ * \param data A pointer to the data which is to be sent.
+ *
+ * \param len The maximum amount of data bytes to be sent.
+ *
+ * \hideinitializer
+ */
+void uip_send(const void *data, int len);
+
+/**
+ * The length of any incoming data that is currently avaliable (if avaliable)
+ * in the uip_appdata buffer.
+ *
+ * The test function uip_data() must first be used to check if there
+ * is any data available at all.
+ *
+ * \hideinitializer
+ */
+/*void uip_datalen(void);*/
+#define uip_datalen() uip_len
+
+/**
+ * The length of any out-of-band data (urgent data) that has arrived
+ * on the connection.
+ *
+ * \note The configuration parameter UIP_URGDATA must be set for this
+ * function to be enabled.
+ *
+ * \hideinitializer
+ */
+#define uip_urgdatalen() uip_urglen
+
+/**
+ * Close the current connection.
+ *
+ * This function will close the current connection in a nice way.
+ *
+ * \hideinitializer
+ */
+#define uip_close() (uip_flags = UIP_CLOSE)
+
+/**
+ * Abort the current connection.
+ *
+ * This function will abort (reset) the current connection, and is
+ * usually used when an error has occured that prevents using the
+ * uip_close() function.
+ *
+ * \hideinitializer
+ */
+#define uip_abort() (uip_flags = UIP_ABORT)
+
+/**
+ * Tell the sending host to stop sending data.
+ *
+ * This function will close our receiver's window so that we stop
+ * receiving data for the current connection.
+ *
+ * \hideinitializer
+ */
+#define uip_stop() (uip_conn->tcpstateflags |= UIP_STOPPED)
+
+/**
+ * Find out if the current connection has been previously stopped with
+ * uip_stop().
+ *
+ * \hideinitializer
+ */
+#define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED)
+
+/**
+ * Restart the current connection, if is has previously been stopped
+ * with uip_stop().
+ *
+ * This function will open the receiver's window again so that we
+ * start receiving data for the current connection.
+ *
+ * \hideinitializer
+ */
+#define uip_restart() do { uip_flags |= UIP_NEWDATA; \
+ uip_conn->tcpstateflags &= ~UIP_STOPPED; \
+ } while(0)
+
+
+/* uIP tests that can be made to determine in what state the current
+ connection is, and what the application function should do. */
+
+/**
+ * Is the current connection a UDP connection?
+ *
+ * This function checks whether the current connection is a UDP connection.
+ *
+ * \hideinitializer
+ *
+ */
+#define uip_udpconnection() (uip_conn == NULL)
+
+/**
+ * Is new incoming data available?
+ *
+ * Will reduce to non-zero if there is new data for the application
+ * present at the uip_appdata pointer. The size of the data is
+ * avaliable through the uip_len variable.
+ *
+ * \hideinitializer
+ */
+#define uip_newdata() (uip_flags & UIP_NEWDATA)
+
+/**
+ * Has previously sent data been acknowledged?
+ *
+ * Will reduce to non-zero if the previously sent data has been
+ * acknowledged by the remote host. This means that the application
+ * can send new data.
+ *
+ * \hideinitializer
+ */
+#define uip_acked() (uip_flags & UIP_ACKDATA)
+
+/**
+ * Has the connection just been connected?
+ *
+ * Reduces to non-zero if the current connection has been connected to
+ * a remote host. This will happen both if the connection has been
+ * actively opened (with uip_connect()) or passively opened (with
+ * uip_listen()).
+ *
+ * \hideinitializer
+ */
+#define uip_connected() (uip_flags & UIP_CONNECTED)
+
+/**
+ * Has the connection been closed by the other end?
+ *
+ * Is non-zero if the connection has been closed by the remote
+ * host. The application may then do the necessary clean-ups.
+ *
+ * \hideinitializer
+ */
+#define uip_closed() (uip_flags & UIP_CLOSE)
+
+/**
+ * Has the connection been aborted by the other end?
+ *
+ * Non-zero if the current connection has been aborted (reset) by the
+ * remote host.
+ *
+ * \hideinitializer
+ */
+#define uip_aborted() (uip_flags & UIP_ABORT)
+
+/**
+ * Has the connection timed out?
+ *
+ * Non-zero if the current connection has been aborted due to too many
+ * retransmissions.
+ *
+ * \hideinitializer
+ */
+#define uip_timedout() (uip_flags & UIP_TIMEDOUT)
+
+/**
+ * Do we need to retransmit previously data?
+ *
+ * Reduces to non-zero if the previously sent data has been lost in
+ * the network, and the application should retransmit it. The
+ * application should send the exact same data as it did the last
+ * time, using the uip_send() function.
+ *
+ * \hideinitializer
+ */
+#define uip_rexmit() (uip_flags & UIP_REXMIT)
+
+/**
+ * Is the connection being polled by uIP?
+ *
+ * Is non-zero if the reason the application is invoked is that the
+ * current connection has been idle for a while and should be
+ * polled.
+ *
+ * The polling event can be used for sending data without having to
+ * wait for the remote host to send data.
+ *
+ * \hideinitializer
+ */
+#define uip_poll() (uip_flags & UIP_POLL)
+
+/**
+ * Get the initial maxium segment size (MSS) of the current
+ * connection.
+ *
+ * \hideinitializer
+ */
+#define uip_initialmss() (uip_conn->initialmss)
+
+/**
+ * Get the current maxium segment size that can be sent on the current
+ * connection.
+ *
+ * The current maxiumum segment size that can be sent on the
+ * connection is computed from the receiver's window and the MSS of
+ * the connection (which also is available by calling
+ * uip_initialmss()).
+ *
+ * \hideinitializer
+ */
+#define uip_mss() (uip_conn->mss)
+
+/**
+ * Set up a new UDP connection.
+ *
+ * This function sets up a new UDP connection. The function will
+ * automatically allocate an unused local port for the new
+ * connection. However, another port can be chosen by using the
+ * uip_udp_bind() call, after the uip_udp_new() function has been
+ * called.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t addr;
+ struct uip_udp_conn *c;
+
+ uip_ipaddr(&addr, 192,168,2,1);
+ c = uip_udp_new(&addr, HTONS(12345));
+ if(c != NULL) {
+ uip_udp_bind(c, HTONS(12344));
+ }
+ \endcode
+ * \param ripaddr The IP address of the remote host.
+ *
+ * \param rport The remote port number in network byte order.
+ *
+ * \return The uip_udp_conn structure for the new connection or NULL
+ * if no connection could be allocated.
+ */
+struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport);
+
+/**
+ * Removed a UDP connection.
+ *
+ * \param conn A pointer to the uip_udp_conn structure for the connection.
+ *
+ * \hideinitializer
+ */
+#define uip_udp_remove(conn) (conn)->lport = 0
+
+/**
+ * Bind a UDP connection to a local port.
+ *
+ * \param conn A pointer to the uip_udp_conn structure for the
+ * connection.
+ *
+ * \param port The local port number, in network byte order.
+ *
+ * \hideinitializer
+ */
+#define uip_udp_bind(conn, port) (conn)->lport = port
+
+/**
+ * Send a UDP datagram of length len on the current connection.
+ *
+ * This function can only be called in response to a UDP event (poll
+ * or newdata). The data must be present in the uip_buf buffer, at the
+ * place pointed to by the uip_appdata pointer.
+ *
+ * \param len The length of the data in the uip_buf buffer.
+ *
+ * \hideinitializer
+ */
+#define uip_udp_send(len) uip_send((char *)uip_appdata, len)
+
+/** @} */
+
+/* uIP convenience and converting functions. */
+
+/**
+ * \defgroup uipconvfunc uIP conversion functions
+ * @{
+ *
+ * These functions can be used for converting between different data
+ * formats used by uIP.
+ */
+
+/**
+ * Construct an IP address from four bytes.
+ *
+ * This function constructs an IP address of the type that uIP handles
+ * internally from four bytes. The function is handy for specifying IP
+ * addresses to use with e.g. the uip_connect() function.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t ipaddr;
+ struct uip_conn *c;
+
+ uip_ipaddr(&ipaddr, 192,168,1,2);
+ c = uip_connect(&ipaddr, HTONS(80));
+ \endcode
+ *
+ * \param addr A pointer to a uip_ipaddr_t variable that will be
+ * filled in with the IP address.
+ *
+ * \param addr0 The first octet of the IP address.
+ * \param addr1 The second octet of the IP address.
+ * \param addr2 The third octet of the IP address.
+ * \param addr3 The forth octet of the IP address.
+ *
+ * \hideinitializer
+ */
+#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \
+ ((u16_t *)(addr))[0] = HTONS(((addr0) << 8) | (addr1 & 0x00ff)); \
+ ((u16_t *)(addr))[1] = HTONS(((addr2) << 8) | (addr3 & 0x00ff)); \
+ } while(0)
+
+/**
+ * Construct an IPv6 address from eight 16-bit words.
+ *
+ * This function constructs an IPv6 address.
+ *
+ * \hideinitializer
+ */
+#define uip_ip6addr(addr, addr0,addr1,addr2,addr3,addr4,addr5,addr6,addr7) do { \
+ ((u16_t *)(addr))[0] = HTONS((addr0)); \
+ ((u16_t *)(addr))[1] = HTONS((addr1)); \
+ ((u16_t *)(addr))[2] = HTONS((addr2)); \
+ ((u16_t *)(addr))[3] = HTONS((addr3)); \
+ ((u16_t *)(addr))[4] = HTONS((addr4)); \
+ ((u16_t *)(addr))[5] = HTONS((addr5)); \
+ ((u16_t *)(addr))[6] = HTONS((addr6)); \
+ ((u16_t *)(addr))[7] = HTONS((addr7)); \
+ } while(0)
+
+/**
+ * Copy an IP address to another IP address.
+ *
+ * Copies an IP address from one place to another.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t ipaddr1, ipaddr2;
+
+ uip_ipaddr(&ipaddr1, 192,16,1,2);
+ uip_ipaddr_copy(&ipaddr2, &ipaddr1);
+ \endcode
+ *
+ * \param dest The destination for the copy.
+ * \param src The source from where to copy.
+ *
+ * \hideinitializer
+ */
+#if !UIP_CONF_IPV6
+#define uip_ipaddr_copy(dest, src) do { \
+ ((u16_t *)dest)[0] = ((u16_t *)src)[0]; \
+ ((u16_t *)dest)[1] = ((u16_t *)src)[1]; \
+ } while(0)
+#else /* !UIP_CONF_IPV6 */
+#define uip_ipaddr_copy(dest, src) memcpy(dest, src, sizeof(uip_ip6addr_t))
+#endif /* !UIP_CONF_IPV6 */
+
+/**
+ * Compare two IP addresses
+ *
+ * Compares two IP addresses.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t ipaddr1, ipaddr2;
+
+ uip_ipaddr(&ipaddr1, 192,16,1,2);
+ if(uip_ipaddr_cmp(&ipaddr2, &ipaddr1)) {
+ printf("They are the same");
+ }
+ \endcode
+ *
+ * \param addr1 The first IP address.
+ * \param addr2 The second IP address.
+ *
+ * \hideinitializer
+ */
+#if !UIP_CONF_IPV6
+#define uip_ipaddr_cmp(addr1, addr2) (((u16_t *)addr1)[0] == ((u16_t *)addr2)[0] && \
+ ((u16_t *)addr1)[1] == ((u16_t *)addr2)[1])
+#else /* !UIP_CONF_IPV6 */
+#define uip_ipaddr_cmp(addr1, addr2) (memcmp(addr1, addr2, sizeof(uip_ip6addr_t)) == 0)
+#endif /* !UIP_CONF_IPV6 */
+
+/**
+ * Compare two IP addresses with netmasks
+ *
+ * Compares two IP addresses with netmasks. The masks are used to mask
+ * out the bits that are to be compared.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t ipaddr1, ipaddr2, mask;
+
+ uip_ipaddr(&mask, 255,255,255,0);
+ uip_ipaddr(&ipaddr1, 192,16,1,2);
+ uip_ipaddr(&ipaddr2, 192,16,1,3);
+ if(uip_ipaddr_maskcmp(&ipaddr1, &ipaddr2, &mask)) {
+ printf("They are the same");
+ }
+ \endcode
+ *
+ * \param addr1 The first IP address.
+ * \param addr2 The second IP address.
+ * \param mask The netmask.
+ *
+ * \hideinitializer
+ */
+#define uip_ipaddr_maskcmp(addr1, addr2, mask) \
+ (((((u16_t *)addr1)[0] & ((u16_t *)mask)[0]) == \
+ (((u16_t *)addr2)[0] & ((u16_t *)mask)[0])) && \
+ ((((u16_t *)addr1)[1] & ((u16_t *)mask)[1]) == \
+ (((u16_t *)addr2)[1] & ((u16_t *)mask)[1])))
+
+
+/**
+ * Mask out the network part of an IP address.
+ *
+ * Masks out the network part of an IP address, given the address and
+ * the netmask.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t ipaddr1, ipaddr2, netmask;
+
+ uip_ipaddr(&ipaddr1, 192,16,1,2);
+ uip_ipaddr(&netmask, 255,255,255,0);
+ uip_ipaddr_mask(&ipaddr2, &ipaddr1, &netmask);
+ \endcode
+ *
+ * In the example above, the variable "ipaddr2" will contain the IP
+ * address 192.168.1.0.
+ *
+ * \param dest Where the result is to be placed.
+ * \param src The IP address.
+ * \param mask The netmask.
+ *
+ * \hideinitializer
+ */
+#define uip_ipaddr_mask(dest, src, mask) do { \
+ ((u16_t *)dest)[0] = ((u16_t *)src)[0] & ((u16_t *)mask)[0]; \
+ ((u16_t *)dest)[1] = ((u16_t *)src)[1] & ((u16_t *)mask)[1]; \
+ } while(0)
+
+/**
+ * Pick the first octet of an IP address.
+ *
+ * Picks out the first octet of an IP address.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t ipaddr;
+ u8_t octet;
+
+ uip_ipaddr(&ipaddr, 1,2,3,4);
+ octet = uip_ipaddr1(&ipaddr);
+ \endcode
+ *
+ * In the example above, the variable "octet" will contain the value 1.
+ *
+ * \hideinitializer
+ */
+#define uip_ipaddr1(addr) (htons(((u16_t *)(addr))[0]) >> 8)
+
+/**
+ * Pick the second octet of an IP address.
+ *
+ * Picks out the second octet of an IP address.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t ipaddr;
+ u8_t octet;
+
+ uip_ipaddr(&ipaddr, 1,2,3,4);
+ octet = uip_ipaddr2(&ipaddr);
+ \endcode
+ *
+ * In the example above, the variable "octet" will contain the value 2.
+ *
+ * \hideinitializer
+ */
+#define uip_ipaddr2(addr) (htons(((u16_t *)(addr))[0]) & 0xff)
+
+/**
+ * Pick the third octet of an IP address.
+ *
+ * Picks out the third octet of an IP address.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t ipaddr;
+ u8_t octet;
+
+ uip_ipaddr(&ipaddr, 1,2,3,4);
+ octet = uip_ipaddr3(&ipaddr);
+ \endcode
+ *
+ * In the example above, the variable "octet" will contain the value 3.
+ *
+ * \hideinitializer
+ */
+#define uip_ipaddr3(addr) (htons(((u16_t *)(addr))[1]) >> 8)
+
+/**
+ * Pick the fourth octet of an IP address.
+ *
+ * Picks out the fourth octet of an IP address.
+ *
+ * Example:
+ \code
+ uip_ipaddr_t ipaddr;
+ u8_t octet;
+
+ uip_ipaddr(&ipaddr, 1,2,3,4);
+ octet = uip_ipaddr4(&ipaddr);
+ \endcode
+ *
+ * In the example above, the variable "octet" will contain the value 4.
+ *
+ * \hideinitializer
+ */
+#define uip_ipaddr4(addr) (htons(((u16_t *)(addr))[1]) & 0xff)
+
+/**
+ * Convert 16-bit quantity from host byte order to network byte order.
+ *
+ * This macro is primarily used for converting constants from host
+ * byte order to network byte order. For converting variables to
+ * network byte order, use the htons() function instead.
+ *
+ * \hideinitializer
+ */
+#ifndef HTONS
+# if UIP_BYTE_ORDER == UIP_BIG_ENDIAN
+# define HTONS(n) (n)
+# else /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */
+# define HTONS(n) (u16_t)((((u16_t) (n)) << 8) | (((u16_t) (n)) >> 8))
+# endif /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */
+#else
+#error "HTONS already defined!"
+#endif /* HTONS */
+
+/**
+ * Convert 16-bit quantity from host byte order to network byte order.
+ *
+ * This function is primarily used for converting variables from host
+ * byte order to network byte order. For converting constants to
+ * network byte order, use the HTONS() macro instead.
+ */
+#ifndef htons
+u16_t htons(u16_t val);
+#endif /* htons */
+#ifndef ntohs
+#define ntohs htons
+#endif
+
+/** @} */
+
+/**
+ * Pointer to the application data in the packet buffer.
+ *
+ * This pointer points to the application data when the application is
+ * called. If the application wishes to send data, the application may
+ * use this space to write the data into before calling uip_send().
+ */
+extern void *uip_appdata;
+
+#if UIP_URGDATA > 0
+/* u8_t *uip_urgdata:
+ *
+ * This pointer points to any urgent data that has been received. Only
+ * present if compiled with support for urgent data (UIP_URGDATA).
+ */
+extern void *uip_urgdata;
+#endif /* UIP_URGDATA > 0 */
+
+
+/**
+ * \defgroup uipdrivervars Variables used in uIP device drivers
+ * @{
+ *
+ * uIP has a few global variables that are used in device drivers for
+ * uIP.
+ */
+
+/**
+ * The length of the packet in the uip_buf buffer.
+ *
+ * The global variable uip_len holds the length of the packet in the
+ * uip_buf buffer.
+ *
+ * When the network device driver calls the uIP input function,
+ * uip_len should be set to the length of the packet in the uip_buf
+ * buffer.
+ *
+ * When sending packets, the device driver should use the contents of
+ * the uip_len variable to determine the length of the outgoing
+ * packet.
+ *
+ */
+extern u16_t uip_len;
+
+/** @} */
+
+#if UIP_URGDATA > 0
+extern u16_t uip_urglen, uip_surglen;
+#endif /* UIP_URGDATA > 0 */
+
+
+/**
+ * Representation of a uIP TCP connection.
+ *
+ * The uip_conn structure is used for identifying a connection. All
+ * but one field in the structure are to be considered read-only by an
+ * application. The only exception is the appstate field whos purpose
+ * is to let the application store application-specific state (e.g.,
+ * file pointers) for the connection. The type of this field is
+ * configured in the "uipopt.h" header file.
+ */
+struct uip_conn {
+ uip_ipaddr_t ripaddr; /**< The IP address of the remote host. */
+
+ u16_t lport; /**< The local TCP port, in network byte order. */
+ u16_t rport; /**< The local remote TCP port, in network byte
+ order. */
+
+ u8_t rcv_nxt[4]; /**< The sequence number that we expect to
+ receive next. */
+ u8_t snd_nxt[4]; /**< The sequence number that was last sent by
+ us. */
+ u16_t len; /**< Length of the data that was previously sent. */
+ u16_t mss; /**< Current maximum segment size for the
+ connection. */
+ u16_t initialmss; /**< Initial maximum segment size for the
+ connection. */
+ u8_t sa; /**< Retransmission time-out calculation state
+ variable. */
+ u8_t sv; /**< Retransmission time-out calculation state
+ variable. */
+ u8_t rto; /**< Retransmission time-out. */
+ u8_t tcpstateflags; /**< TCP state and flags. */
+ u8_t timer; /**< The retransmission timer. */
+ u8_t nrtx; /**< The number of retransmissions for the last
+ segment sent. */
+
+ /** The application state. */
+ uip_tcp_appstate_t appstate;
+};
+
+
+/**
+ * Pointer to the current TCP connection.
+ *
+ * The uip_conn pointer can be used to access the current TCP
+ * connection.
+ */
+extern struct uip_conn *uip_conn;
+/* The array containing all uIP connections. */
+extern struct uip_conn uip_conns[UIP_CONNS];
+/**
+ * \addtogroup uiparch
+ * @{
+ */
+
+/**
+ * 4-byte array used for the 32-bit sequence number calculations.
+ */
+extern u8_t uip_acc32[4];
+
+/** @} */
+
+
+#if UIP_UDP
+/**
+ * Representation of a uIP UDP connection.
+ */
+struct uip_udp_conn {
+ uip_ipaddr_t ripaddr; /**< The IP address of the remote peer. */
+ u16_t lport; /**< The local port number in network byte order. */
+ u16_t rport; /**< The remote port number in network byte order. */
+ u8_t ttl; /**< Default time-to-live. */
+
+ /** The application state. */
+ uip_udp_appstate_t appstate;
+};
+
+/**
+ * The current UDP connection.
+ */
+extern struct uip_udp_conn *uip_udp_conn;
+extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
+#endif /* UIP_UDP */
+
+/**
+ * The structure holding the TCP/IP statistics that are gathered if
+ * UIP_STATISTICS is set to 1.
+ *
+ */
+struct uip_stats {
+ struct {
+ uip_stats_t drop; /**< Number of dropped packets at the IP
+ layer. */
+ uip_stats_t recv; /**< Number of received packets at the IP
+ layer. */
+ uip_stats_t sent; /**< Number of sent packets at the IP
+ layer. */
+ uip_stats_t vhlerr; /**< Number of packets dropped due to wrong
+ IP version or header length. */
+ uip_stats_t hblenerr; /**< Number of packets dropped due to wrong
+ IP length, high byte. */
+ uip_stats_t lblenerr; /**< Number of packets dropped due to wrong
+ IP length, low byte. */
+ uip_stats_t fragerr; /**< Number of packets dropped since they
+ were IP fragments. */
+ uip_stats_t chkerr; /**< Number of packets dropped due to IP
+ checksum errors. */
+ uip_stats_t protoerr; /**< Number of packets dropped since they
+ were neither ICMP, UDP nor TCP. */
+ } ip; /**< IP statistics. */
+ struct {
+ uip_stats_t drop; /**< Number of dropped ICMP packets. */
+ uip_stats_t recv; /**< Number of received ICMP packets. */
+ uip_stats_t sent; /**< Number of sent ICMP packets. */
+ uip_stats_t typeerr; /**< Number of ICMP packets with a wrong
+ type. */
+ } icmp; /**< ICMP statistics. */
+ struct {
+ uip_stats_t drop; /**< Number of dropped TCP segments. */
+ uip_stats_t recv; /**< Number of recived TCP segments. */
+ uip_stats_t sent; /**< Number of sent TCP segments. */
+ uip_stats_t chkerr; /**< Number of TCP segments with a bad
+ checksum. */
+ uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK
+ number. */
+ uip_stats_t rst; /**< Number of recevied TCP RST (reset) segments. */
+ uip_stats_t rexmit; /**< Number of retransmitted TCP segments. */
+ uip_stats_t syndrop; /**< Number of dropped SYNs due to too few
+ connections was avaliable. */
+ uip_stats_t synrst; /**< Number of SYNs for closed ports,
+ triggering a RST. */
+ } tcp; /**< TCP statistics. */
+#if UIP_UDP
+ struct {
+ uip_stats_t drop; /**< Number of dropped UDP segments. */
+ uip_stats_t recv; /**< Number of recived UDP segments. */
+ uip_stats_t sent; /**< Number of sent UDP segments. */
+ uip_stats_t chkerr; /**< Number of UDP segments with a bad
+ checksum. */
+ } udp; /**< UDP statistics. */
+#endif /* UIP_UDP */
+};
+
+/**
+ * The uIP TCP/IP statistics.
+ *
+ * This is the variable in which the uIP TCP/IP statistics are gathered.
+ */
+extern struct uip_stats uip_stat;
+
+
+/*---------------------------------------------------------------------------*/
+/* All the stuff below this point is internal to uIP and should not be
+ * used directly by an application or by a device driver.
+ */
+/*---------------------------------------------------------------------------*/
+/* u8_t uip_flags:
+ *
+ * When the application is called, uip_flags will contain the flags
+ * that are defined in this file. Please read below for more
+ * infomation.
+ */
+extern u8_t uip_flags;
+
+/* The following flags may be set in the global variable uip_flags
+ before calling the application callback. The UIP_ACKDATA,
+ UIP_NEWDATA, and UIP_CLOSE flags may both be set at the same time,
+ whereas the others are mutualy exclusive. Note that these flags
+ should *NOT* be accessed directly, but only through the uIP
+ functions/macros. */
+
+#define UIP_ACKDATA 1 /* Signifies that the outstanding data was
+ acked and the application should send
+ out new data instead of retransmitting
+ the last data. */
+#define UIP_NEWDATA 2 /* Flags the fact that the peer has sent
+ us new data. */
+#define UIP_REXMIT 4 /* Tells the application to retransmit the
+ data that was last sent. */
+#define UIP_POLL 8 /* Used for polling the application, to
+ check if the application has data that
+ it wants to send. */
+#define UIP_CLOSE 16 /* The remote host has closed the
+ connection, thus the connection has
+ gone away. Or the application signals
+ that it wants to close the
+ connection. */
+#define UIP_ABORT 32 /* The remote host has aborted the
+ connection, thus the connection has
+ gone away. Or the application signals
+ that it wants to abort the
+ connection. */
+#define UIP_CONNECTED 64 /* We have got a connection from a remote
+ host and have set up a new connection
+ for it, or an active connection has
+ been successfully established. */
+
+#define UIP_TIMEDOUT 128 /* The connection has been aborted due to
+ too many retransmissions. */
+
+/* uip_process(flag):
+ *
+ * The actual uIP function which does all the work.
+ */
+void uip_process(u8_t flag);
+
+/* The following flags are passed as an argument to the uip_process()
+ function. They are used to distinguish between the two cases where
+ uip_process() is called. It can be called either because we have
+ incoming data that should be processed, or because the periodic
+ timer has fired. These values are never used directly, but only in
+ the macrose defined in this file. */
+
+#define UIP_DATA 1 /* Tells uIP that there is incoming
+ data in the uip_buf buffer. The
+ length of the data is stored in the
+ global variable uip_len. */
+#define UIP_TIMER 2 /* Tells uIP that the periodic timer
+ has fired. */
+#define UIP_POLL_REQUEST 3 /* Tells uIP that a connection should
+ be polled. */
+#define UIP_UDP_SEND_CONN 4 /* Tells uIP that a UDP datagram
+ should be constructed in the
+ uip_buf buffer. */
+#if UIP_UDP
+#define UIP_UDP_TIMER 5
+#endif /* UIP_UDP */
+
+/* The TCP states used in the uip_conn->tcpstateflags. */
+#define UIP_CLOSED 0
+#define UIP_SYN_RCVD 1
+#define UIP_SYN_SENT 2
+#define UIP_ESTABLISHED 3
+#define UIP_FIN_WAIT_1 4
+#define UIP_FIN_WAIT_2 5
+#define UIP_CLOSING 6
+#define UIP_TIME_WAIT 7
+#define UIP_LAST_ACK 8
+#define UIP_TS_MASK 15
+
+#define UIP_STOPPED 16
+
+/* The TCP and IP headers. */
+struct uip_tcpip_hdr {
+#if UIP_CONF_IPV6
+ /* IPv6 header. */
+ u8_t vtc,
+ tcflow;
+ u16_t flow;
+ u8_t len[2];
+ u8_t proto, ttl;
+ uip_ip6addr_t srcipaddr, destipaddr;
+#else /* UIP_CONF_IPV6 */
+ /* IPv4 header. */
+ u8_t vhl,
+ tos,
+ len[2],
+ ipid[2],
+ ipoffset[2],
+ ttl,
+ proto;
+ u16_t ipchksum;
+ u16_t srcipaddr[2],
+ destipaddr[2];
+#endif /* UIP_CONF_IPV6 */
+
+ /* TCP header. */
+ u16_t srcport,
+ destport;
+ u8_t seqno[4],
+ ackno[4],
+ tcpoffset,
+ flags,
+ wnd[2];
+ u16_t tcpchksum;
+ u8_t urgp[2];
+ u8_t optdata[4];
+};
+
+/* The ICMP and IP headers. */
+struct uip_icmpip_hdr {
+#if UIP_CONF_IPV6
+ /* IPv6 header. */
+ u8_t vtc,
+ tcf;
+ u16_t flow;
+ u8_t len[2];
+ u8_t proto, ttl;
+ uip_ip6addr_t srcipaddr, destipaddr;
+#else /* UIP_CONF_IPV6 */
+ /* IPv4 header. */
+ u8_t vhl,
+ tos,
+ len[2],
+ ipid[2],
+ ipoffset[2],
+ ttl,
+ proto;
+ u16_t ipchksum;
+ u16_t srcipaddr[2],
+ destipaddr[2];
+#endif /* UIP_CONF_IPV6 */
+
+ /* ICMP (echo) header. */
+ u8_t type, icode;
+ u16_t icmpchksum;
+#if !UIP_CONF_IPV6
+ u16_t id, seqno;
+#else /* !UIP_CONF_IPV6 */
+ u8_t flags, reserved1, reserved2, reserved3;
+ u8_t icmp6data[16];
+ u8_t options[1];
+#endif /* !UIP_CONF_IPV6 */
+};
+
+
+/* The UDP and IP headers. */
+struct uip_udpip_hdr {
+#if UIP_CONF_IPV6
+ /* IPv6 header. */
+ u8_t vtc,
+ tcf;
+ u16_t flow;
+ u8_t len[2];
+ u8_t proto, ttl;
+ uip_ip6addr_t srcipaddr, destipaddr;
+#else /* UIP_CONF_IPV6 */
+ /* IP header. */
+ u8_t vhl,
+ tos,
+ len[2],
+ ipid[2],
+ ipoffset[2],
+ ttl,
+ proto;
+ u16_t ipchksum;
+ u16_t srcipaddr[2],
+ destipaddr[2];
+#endif /* UIP_CONF_IPV6 */
+
+ /* UDP header. */
+ u16_t srcport,
+ destport;
+ u16_t udplen;
+ u16_t udpchksum;
+};
+
+
+
+/**
+ * The buffer size available for user data in the \ref uip_buf buffer.
+ *
+ * This macro holds the available size for user data in the \ref
+ * uip_buf buffer. The macro is intended to be used for checking
+ * bounds of available user data.
+ *
+ * Example:
+ \code
+ snprintf(uip_appdata, UIP_APPDATA_SIZE, "%u\n", i);
+ \endcode
+ *
+ * \hideinitializer
+ */
+#define UIP_APPDATA_SIZE (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN)
+
+
+#define UIP_PROTO_ICMP 1
+#define UIP_PROTO_TCP 6
+#define UIP_PROTO_UDP 17
+#define UIP_PROTO_ICMP6 58
+
+/* Header sizes. */
+#if UIP_CONF_IPV6
+#define UIP_IPH_LEN 40
+#else /* UIP_CONF_IPV6 */
+#define UIP_IPH_LEN 20 /* Size of IP header */
+#endif /* UIP_CONF_IPV6 */
+#define UIP_UDPH_LEN 8 /* Size of UDP header */
+#define UIP_TCPH_LEN 20 /* Size of TCP header */
+#define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN) /* Size of IP +
+ UDP
+ header */
+#define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP +
+ TCP
+ header */
+#define UIP_TCPIP_HLEN UIP_IPTCPH_LEN
+
+
+#if UIP_FIXEDADDR
+extern const uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr;
+#else /* UIP_FIXEDADDR */
+extern uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr;
+#endif /* UIP_FIXEDADDR */
+
+
+
+/**
+ * Representation of a 48-bit Ethernet address.
+ */
+struct uip_eth_addr {
+ u8_t addr[6];
+};
+
+/**
+ * Calculate the Internet checksum over a buffer.
+ *
+ * The Internet checksum is the one's complement of the one's
+ * complement sum of all 16-bit words in the buffer.
+ *
+ * See RFC1071.
+ *
+ * \param buf A pointer to the buffer over which the checksum is to be
+ * computed.
+ *
+ * \param len The length of the buffer over which the checksum is to
+ * be computed.
+ *
+ * \return The Internet checksum of the buffer.
+ */
+u16_t uip_chksum(u16_t *buf, u16_t len);
+
+/**
+ * Calculate the IP header checksum of the packet header in uip_buf.
+ *
+ * The IP header checksum is the Internet checksum of the 20 bytes of
+ * the IP header.
+ *
+ * \return The IP header checksum of the IP header in the uip_buf
+ * buffer.
+ */
+u16_t uip_ipchksum(void);
+
+/**
+ * Calculate the TCP checksum of the packet in uip_buf and uip_appdata.
+ *
+ * The TCP checksum is the Internet checksum of data contents of the
+ * TCP segment, and a pseudo-header as defined in RFC793.
+ *
+ * \return The TCP checksum of the TCP segment in uip_buf and pointed
+ * to by uip_appdata.
+ */
+u16_t uip_tcpchksum(void);
+
+/**
+ * Calculate the UDP checksum of the packet in uip_buf and uip_appdata.
+ *
+ * The UDP checksum is the Internet checksum of data contents of the
+ * UDP segment, and a pseudo-header as defined in RFC768.
+ *
+ * \return The UDP checksum of the UDP segment in uip_buf and pointed
+ * to by uip_appdata.
+ */
+u16_t uip_udpchksum(void);
+
+
+#endif /* __UIP_H__ */
+
+
+/** @} */
diff --git a/Libraries/WiShield/uip_arch.h b/Libraries/WiShield/uip_arch.h
new file mode 100644
index 0000000..71fd84b
--- /dev/null
+++ b/Libraries/WiShield/uip_arch.h
@@ -0,0 +1,138 @@
+/**
+ * \addtogroup uip
+ * {@
+ */
+
+/**
+ * \defgroup uiparch Architecture specific uIP functions
+ * @{
+ *
+ * The functions in the architecture specific module implement the IP
+ * check sum and 32-bit additions.
+ *
+ * The IP checksum calculation is the most computationally expensive
+ * operation in the TCP/IP stack and it therefore pays off to
+ * implement this in efficient assembler. The purpose of the uip-arch
+ * module is to let the checksum functions to be implemented in
+ * architecture specific assembler.
+ *
+ */
+
+/**
+ * \file
+ * Declarations of architecture specific functions.
+ * \author Adam Dunkels <adam@dunkels.com>
+ */
+
+/*
+ * Copyright (c) 2001, Adam Dunkels.
+ * 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 the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: uip_arch.h,v 1.2 2006/06/07 09:15:19 adam Exp $
+ *
+ */
+
+#ifndef __UIP_ARCH_H__
+#define __UIP_ARCH_H__
+
+#include "uip.h"
+
+/**
+ * Carry out a 32-bit addition.
+ *
+ * Because not all architectures for which uIP is intended has native
+ * 32-bit arithmetic, uIP uses an external C function for doing the
+ * required 32-bit additions in the TCP protocol processing. This
+ * function should add the two arguments and place the result in the
+ * global variable uip_acc32.
+ *
+ * \note The 32-bit integer pointed to by the op32 parameter and the
+ * result in the uip_acc32 variable are in network byte order (big
+ * endian).
+ *
+ * \param op32 A pointer to a 4-byte array representing a 32-bit
+ * integer in network byte order (big endian).
+ *
+ * \param op16 A 16-bit integer in host byte order.
+ */
+void uip_add32(u8_t *op32, u16_t op16);
+
+/**
+ * Calculate the Internet checksum over a buffer.
+ *
+ * The Internet checksum is the one's complement of the one's
+ * complement sum of all 16-bit words in the buffer.
+ *
+ * See RFC1071.
+ *
+ * \note This function is not called in the current version of uIP,
+ * but future versions might make use of it.
+ *
+ * \param buf A pointer to the buffer over which the checksum is to be
+ * computed.
+ *
+ * \param len The length of the buffer over which the checksum is to
+ * be computed.
+ *
+ * \return The Internet checksum of the buffer.
+ */
+u16_t uip_chksum(u16_t *buf, u16_t len);
+
+/**
+ * Calculate the IP header checksum of the packet header in uip_buf.
+ *
+ * The IP header checksum is the Internet checksum of the 20 bytes of
+ * the IP header.
+ *
+ * \return The IP header checksum of the IP header in the uip_buf
+ * buffer.
+ */
+u16_t uip_ipchksum(void);
+
+/**
+ * Calculate the TCP checksum of the packet in uip_buf and uip_appdata.
+ *
+ * The TCP checksum is the Internet checksum of data contents of the
+ * TCP segment, and a pseudo-header as defined in RFC793.
+ *
+ * \note The uip_appdata pointer that points to the packet data may
+ * point anywhere in memory, so it is not possible to simply calculate
+ * the Internet checksum of the contents of the uip_buf buffer.
+ *
+ * \return The TCP checksum of the TCP segment in uip_buf and pointed
+ * to by uip_appdata.
+ */
+u16_t uip_tcpchksum(void);
+
+u16_t uip_udpchksum(void);
+
+/** @} */
+/** @} */
+
+#endif /* __UIP_ARCH_H__ */
diff --git a/Libraries/WiShield/uip_arp.c b/Libraries/WiShield/uip_arp.c
new file mode 100644
index 0000000..b1de66a
--- /dev/null
+++ b/Libraries/WiShield/uip_arp.c
@@ -0,0 +1,481 @@
+
+/******************************************************************************
+
+ Filename: uip_arp.c
+ Description: ARP for uIP on the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/29/2009 Initial port
+
+ *****************************************************************************/
+
+/**
+ * \addtogroup uip
+ * @{
+ */
+
+/**
+ * \defgroup uiparp uIP Address Resolution Protocol
+ * @{
+ *
+ * The Address Resolution Protocol ARP is used for mapping between IP
+ * addresses and link level addresses such as the Ethernet MAC
+ * addresses. ARP uses broadcast queries to ask for the link level
+ * address of a known IP address and the host which is configured with
+ * the IP address for which the query was meant, will respond with its
+ * link level address.
+ *
+ * \note This ARP implementation only supports Ethernet.
+ */
+
+/**
+ * \file
+ * Implementation of the ARP Address Resolution Protocol.
+ * \author Adam Dunkels <adam@dunkels.com>
+ *
+ */
+
+/*
+ * Copyright (c) 2001-2003, Adam Dunkels.
+ * 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 the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: uip_arp.c,v 1.8 2006/06/02 23:36:21 adam Exp $
+ *
+ */
+
+
+#include "uip_arp.h"
+
+#include <string.h>
+
+struct arp_hdr {
+ struct uip_eth_hdr ethhdr;
+ u16_t hwtype;
+ u16_t protocol;
+ u8_t hwlen;
+ u8_t protolen;
+ u16_t opcode;
+ struct uip_eth_addr shwaddr;
+ u16_t sipaddr[2];
+ struct uip_eth_addr dhwaddr;
+ u16_t dipaddr[2];
+};
+
+struct ethip_hdr {
+ struct uip_eth_hdr ethhdr;
+ /* IP header. */
+ u8_t vhl,
+ tos,
+ len[2],
+ ipid[2],
+ ipoffset[2],
+ ttl,
+ proto;
+ u16_t ipchksum;
+ u16_t srcipaddr[2],
+ destipaddr[2];
+};
+
+#define ARP_REQUEST 1
+#define ARP_REPLY 2
+
+#define ARP_HWTYPE_ETH 1
+
+struct arp_entry {
+ u16_t ipaddr[2];
+ struct uip_eth_addr ethaddr;
+ u8_t time;
+};
+
+static const struct uip_eth_addr broadcast_ethaddr =
+ {{0xff,0xff,0xff,0xff,0xff,0xff}};
+static const u16_t broadcast_ipaddr[2] = {0xffff,0xffff};
+
+static struct arp_entry arp_table[UIP_ARPTAB_SIZE];
+static u16_t ipaddr[2];
+static u8_t i, c;
+
+static u8_t arptime;
+static u8_t tmpage;
+
+#define BUF ((struct arp_hdr *)&uip_buf[0])
+#define IPBUF ((struct ethip_hdr *)&uip_buf[0])
+/*-----------------------------------------------------------------------------------*/
+/**
+ * Initialize the ARP module.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+uip_arp_init(void)
+{
+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
+ memset(arp_table[i].ipaddr, 0, 4);
+ }
+}
+/*-----------------------------------------------------------------------------------*/
+/**
+ * Periodic ARP processing function.
+ *
+ * This function performs periodic timer processing in the ARP module
+ * and should be called at regular intervals. The recommended interval
+ * is 10 seconds between the calls.
+ *
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+uip_arp_timer(void)
+{
+ struct arp_entry *tabptr;
+
+ ++arptime;
+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
+ tabptr = &arp_table[i];
+ if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 &&
+ arptime - tabptr->time >= UIP_ARP_MAXAGE) {
+ memset(tabptr->ipaddr, 0, 4);
+ }
+ }
+
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr)
+{
+ register struct arp_entry *tabptr = NULL;
+ /* Walk through the ARP mapping table and try to find an entry to
+ update. If none is found, the IP -> MAC address mapping is
+ inserted in the ARP table. */
+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
+
+ tabptr = &arp_table[i];
+ /* Only check those entries that are actually in use. */
+ if(tabptr->ipaddr[0] != 0 &&
+ tabptr->ipaddr[1] != 0) {
+
+ /* Check if the source IP address of the incoming packet matches
+ the IP address in this ARP table entry. */
+ if(ipaddr[0] == tabptr->ipaddr[0] &&
+ ipaddr[1] == tabptr->ipaddr[1]) {
+
+ /* An old entry found, update this and return. */
+ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
+ tabptr->time = arptime;
+
+ return;
+ }
+ }
+ }
+
+ /* If we get here, no existing ARP table entry was found, so we
+ create one. */
+
+ /* First, we try to find an unused entry in the ARP table. */
+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
+ tabptr = &arp_table[i];
+ if(tabptr->ipaddr[0] == 0 &&
+ tabptr->ipaddr[1] == 0) {
+ break;
+ }
+ }
+
+ /* If no unused entry is found, we try to find the oldest entry and
+ throw it away. */
+ if(i == UIP_ARPTAB_SIZE) {
+ tmpage = 0;
+ c = 0;
+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
+ tabptr = &arp_table[i];
+ if(arptime - tabptr->time > tmpage) {
+ tmpage = arptime - tabptr->time;
+ c = i;
+ }
+ }
+ i = c;
+ tabptr = &arp_table[i];
+ }
+
+ /* Now, i is the ARP table entry which we will fill with the new
+ information. */
+ memcpy(tabptr->ipaddr, ipaddr, 4);
+ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
+ tabptr->time = arptime;
+}
+/*-----------------------------------------------------------------------------------*/
+/**
+ * ARP processing for incoming IP packets
+ *
+ * This function should be called by the device driver when an IP
+ * packet has been received. The function will check if the address is
+ * in the ARP cache, and if so the ARP cache entry will be
+ * refreshed. If no ARP cache entry was found, a new one is created.
+ *
+ * This function expects an IP packet with a prepended Ethernet header
+ * in the uip_buf[] buffer, and the length of the packet in the global
+ * variable uip_len.
+ */
+/*-----------------------------------------------------------------------------------*/
+#if 0
+void
+uip_arp_ipin(void)
+{
+ uip_len -= sizeof(struct uip_eth_hdr);
+
+ /* Only insert/update an entry if the source IP address of the
+ incoming IP packet comes from a host on the local network. */
+ if((IPBUF->srcipaddr[0] & uip_netmask[0]) !=
+ (uip_hostaddr[0] & uip_netmask[0])) {
+ return;
+ }
+ if((IPBUF->srcipaddr[1] & uip_netmask[1]) !=
+ (uip_hostaddr[1] & uip_netmask[1])) {
+ return;
+ }
+ uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src));
+
+ return;
+}
+#endif /* 0 */
+/*-----------------------------------------------------------------------------------*/
+/**
+ * ARP processing for incoming ARP packets.
+ *
+ * This function should be called by the device driver when an ARP
+ * packet has been received. The function will act differently
+ * depending on the ARP packet type: if it is a reply for a request
+ * that we previously sent out, the ARP cache will be filled in with
+ * the values from the ARP reply. If the incoming ARP packet is an ARP
+ * request for our IP address, an ARP reply packet is created and put
+ * into the uip_buf[] buffer.
+ *
+ * When the function returns, the value of the global variable uip_len
+ * indicates whether the device driver should send out a packet or
+ * not. If uip_len is zero, no packet should be sent. If uip_len is
+ * non-zero, it contains the length of the outbound packet that is
+ * present in the uip_buf[] buffer.
+ *
+ * This function expects an ARP packet with a prepended Ethernet
+ * header in the uip_buf[] buffer, and the length of the packet in the
+ * global variable uip_len.
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+uip_arp_arpin(void)
+{
+
+ if(uip_len < sizeof(struct arp_hdr)) {
+ uip_len = 0;
+ return;
+ }
+ uip_len = 0;
+
+ switch(BUF->opcode) {
+ case HTONS(ARP_REQUEST):
+ /* ARP request. If it asked for our address, we send out a
+ reply. */
+ if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) {
+ /* First, we register the one who made the request in our ARP
+ table, since it is likely that we will do more communication
+ with this host in the future. */
+ uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
+
+ /* The reply opcode is 2. */
+ BUF->opcode = HTONS(2);
+
+ memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6);
+ memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
+ memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
+ memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6);
+
+ BUF->dipaddr[0] = BUF->sipaddr[0];
+ BUF->dipaddr[1] = BUF->sipaddr[1];
+ BUF->sipaddr[0] = uip_hostaddr[0];
+ BUF->sipaddr[1] = uip_hostaddr[1];
+
+ BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
+ uip_len = sizeof(struct arp_hdr);
+ }
+ break;
+ case HTONS(ARP_REPLY):
+ /* ARP reply. We insert or update the ARP table if it was meant
+ for us. */
+ if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) {
+ uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
+ }
+ break;
+ }
+
+ return;
+}
+/*-----------------------------------------------------------------------------------*/
+/**
+ * Prepend Ethernet header to an outbound IP packet and see if we need
+ * to send out an ARP request.
+ *
+ * This function should be called before sending out an IP packet. The
+ * function checks the destination IP address of the IP packet to see
+ * what Ethernet MAC address that should be used as a destination MAC
+ * address on the Ethernet.
+ *
+ * If the destination IP address is in the local network (determined
+ * by logical ANDing of netmask and our IP address), the function
+ * checks the ARP cache to see if an entry for the destination IP
+ * address is found. If so, an Ethernet header is prepended and the
+ * function returns. If no ARP cache entry is found for the
+ * destination IP address, the packet in the uip_buf[] is replaced by
+ * an ARP request packet for the IP address. The IP packet is dropped
+ * and it is assumed that they higher level protocols (e.g., TCP)
+ * eventually will retransmit the dropped packet.
+ *
+ * If the destination IP address is not on the local network, the IP
+ * address of the default router is used instead.
+ *
+ * When the function returns, a packet is present in the uip_buf[]
+ * buffer, and the length of the packet is in the global variable
+ * uip_len.
+ */
+/*-----------------------------------------------------------------------------------*/
+void
+uip_arp_out(void)
+{
+ struct arp_entry *tabptr = NULL;
+
+ /* Find the destination IP address in the ARP table and construct
+ the Ethernet header. If the destination IP addres isn't on the
+ local network, we use the default router's IP address instead.
+
+ If not ARP table entry is found, we overwrite the original IP
+ packet with an ARP request for the IP address. */
+
+ /* First check if destination is a local broadcast. */
+ if(uip_ipaddr_cmp(IPBUF->destipaddr, broadcast_ipaddr)) {
+ memcpy(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, 6);
+ } else {
+ /* Check if the destination address is on the local network. */
+ if(!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask)) {
+ /* Destination address was not on the local network, so we need to
+ use the default router's IP address instead of the destination
+ address when determining the MAC address. */
+ uip_ipaddr_copy(ipaddr, uip_draddr);
+ } else {
+ /* Else, we use the destination IP address. */
+ uip_ipaddr_copy(ipaddr, IPBUF->destipaddr);
+ }
+
+ for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
+ tabptr = &arp_table[i];
+ if(uip_ipaddr_cmp(ipaddr, tabptr->ipaddr)) {
+ break;
+ }
+ }
+
+ if(i == UIP_ARPTAB_SIZE) {
+ /* The destination address was not in our ARP table, so we
+ overwrite the IP packet with an ARP request. */
+
+ memset(BUF->ethhdr.dest.addr, 0xff, 6);
+ memset(BUF->dhwaddr.addr, 0x00, 6);
+ memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
+ memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
+
+ uip_ipaddr_copy(BUF->dipaddr, ipaddr);
+ uip_ipaddr_copy(BUF->sipaddr, uip_hostaddr);
+ BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */
+ BUF->hwtype = HTONS(ARP_HWTYPE_ETH);
+ BUF->protocol = HTONS(UIP_ETHTYPE_IP);
+ BUF->hwlen = 6;
+ BUF->protolen = 4;
+ BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
+
+ uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN];
+
+ uip_len = sizeof(struct arp_hdr);
+ return;
+ }
+
+ /* Build an ethernet header. */
+ memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6);
+ }
+ memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
+
+ IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP);
+
+ uip_len += sizeof(struct uip_eth_hdr);
+}
+
+void
+uip_self_arp_out(void)
+{
+ memset(BUF->ethhdr.dest.addr, 0xff, 6);
+ memcpy(BUF->dhwaddr.addr, uip_ethaddr.addr, 6);
+ memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
+ memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
+
+ uip_ipaddr_copy(BUF->dipaddr, uip_hostaddr);
+ uip_ipaddr_copy(BUF->sipaddr, uip_hostaddr);
+ BUF->opcode = HTONS(ARP_REPLY); /* ARP reply */
+ BUF->hwtype = HTONS(ARP_HWTYPE_ETH);
+ BUF->protocol = HTONS(UIP_ETHTYPE_IP);
+ BUF->hwlen = 6;
+ BUF->protolen = 4;
+ BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
+
+ uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN];
+
+ uip_len = sizeof(struct arp_hdr);
+ return;
+}
+
+/*-----------------------------------------------------------------------------------*/
+
+/** @} */
+/** @} */
diff --git a/Libraries/WiShield/uip_arp.h b/Libraries/WiShield/uip_arp.h
new file mode 100644
index 0000000..5539e8a
--- /dev/null
+++ b/Libraries/WiShield/uip_arp.h
@@ -0,0 +1,179 @@
+
+/******************************************************************************
+
+ Filename: uip_arp.h
+ Description: ARP for uIP on the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/29/2009 Initial port
+
+ *****************************************************************************/
+
+/**
+ * \addtogroup uip
+ * @{
+ */
+
+/**
+ * \addtogroup uiparp
+ * @{
+ */
+
+/**
+ * \file
+ * Macros and definitions for the ARP module.
+ * \author Adam Dunkels <adam@dunkels.com>
+ */
+
+
+/*
+ * Copyright (c) 2001-2003, Adam Dunkels.
+ * 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 the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: uip_arp.h,v 1.5 2006/06/11 21:46:39 adam Exp $
+ *
+ */
+
+#ifndef __UIP_ARP_H__
+#define __UIP_ARP_H__
+
+#include "uip.h"
+
+
+extern struct uip_eth_addr uip_ethaddr;
+
+/**
+ * The Ethernet header.
+ */
+struct uip_eth_hdr {
+ struct uip_eth_addr dest;
+ struct uip_eth_addr src;
+ u16_t type;
+};
+
+#define UIP_ETHTYPE_ARP 0x0806
+#define UIP_ETHTYPE_IP 0x0800
+#define UIP_ETHTYPE_IP6 0x86dd
+
+
+/* The uip_arp_init() function must be called before any of the other
+ ARP functions. */
+void uip_arp_init(void);
+
+/* The uip_arp_ipin() function should be called whenever an IP packet
+ arrives from the Ethernet. This function refreshes the ARP table or
+ inserts a new mapping if none exists. The function assumes that an
+ IP packet with an Ethernet header is present in the uip_buf buffer
+ and that the length of the packet is in the uip_len variable. */
+/*void uip_arp_ipin(void);*/
+#define uip_arp_ipin()
+
+/* The uip_arp_arpin() should be called when an ARP packet is received
+ by the Ethernet driver. This function also assumes that the
+ Ethernet frame is present in the uip_buf buffer. When the
+ uip_arp_arpin() function returns, the contents of the uip_buf
+ buffer should be sent out on the Ethernet if the uip_len variable
+ is > 0. */
+void uip_arp_arpin(void);
+
+/* The uip_arp_out() function should be called when an IP packet
+ should be sent out on the Ethernet. This function creates an
+ Ethernet header before the IP header in the uip_buf buffer. The
+ Ethernet header will have the correct Ethernet MAC destination
+ address filled in if an ARP table entry for the destination IP
+ address (or the IP address of the default router) is present. If no
+ such table entry is found, the IP packet is overwritten with an ARP
+ request and we rely on TCP to retransmit the packet that was
+ overwritten. In any case, the uip_len variable holds the length of
+ the Ethernet frame that should be transmitted. */
+void uip_arp_out(void);
+
+/* The uip_arp_timer() function should be called every ten seconds. It
+ is responsible for flushing old entries in the ARP table. */
+void uip_arp_timer(void);
+
+void uip_self_arp_out(void);
+/** @} */
+
+/**
+ * \addtogroup uipconffunc
+ * @{
+ */
+
+
+/**
+ * Specifiy the Ethernet MAC address.
+ *
+ * The ARP code needs to know the MAC address of the Ethernet card in
+ * order to be able to respond to ARP queries and to generate working
+ * Ethernet headers.
+ *
+ * \note This macro only specifies the Ethernet MAC address to the ARP
+ * code. It cannot be used to change the MAC address of the Ethernet
+ * card.
+ *
+ * \param eaddr A pointer to a struct uip_eth_addr containing the
+ * Ethernet MAC address of the Ethernet card.
+ *
+ * \hideinitializer
+ */
+#define uip_setethaddr(eaddr) do {uip_ethaddr.addr[0] = eaddr.addr[0]; \
+ uip_ethaddr.addr[1] = eaddr.addr[1];\
+ uip_ethaddr.addr[2] = eaddr.addr[2];\
+ uip_ethaddr.addr[3] = eaddr.addr[3];\
+ uip_ethaddr.addr[4] = eaddr.addr[4];\
+ uip_ethaddr.addr[5] = eaddr.addr[5];} while(0)
+
+/** @} */
+/** @} */
+
+#endif /* __UIP_ARP_H__ */
diff --git a/Libraries/WiShield/uiplib.c b/Libraries/WiShield/uiplib.c
new file mode 100644
index 0000000..cb5af2c
--- /dev/null
+++ b/Libraries/WiShield/uiplib.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2004, Adam Dunkels and the Swedish Institute of
+ * Computer Science.
+ * 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 the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * $Id: uiplib.c,v 1.2 2006/06/12 08:00:31 adam Exp $
+ *
+ */
+
+
+#include "uip.h"
+#include "uiplib.h"
+
+
+/*-----------------------------------------------------------------------------------*/
+unsigned char
+uiplib_ipaddrconv(char *addrstr, unsigned char *ipaddr)
+{
+ unsigned char tmp;
+ char c;
+ unsigned char i, j;
+
+ tmp = 0;
+
+ for(i = 0; i < 4; ++i) {
+ j = 0;
+ do {
+ c = *addrstr;
+ ++j;
+ if(j > 4) {
+ return 0;
+ }
+ if(c == '.' || c == 0) {
+ *ipaddr = tmp;
+ ++ipaddr;
+ tmp = 0;
+ } else if(c >= '0' && c <= '9') {
+ tmp = (tmp * 10) + (c - '0');
+ } else {
+ return 0;
+ }
+ ++addrstr;
+ } while(c != '.' && c != 0);
+ }
+ return 1;
+}
+
+/*-----------------------------------------------------------------------------------*/
diff --git a/Libraries/WiShield/uiplib.h b/Libraries/WiShield/uiplib.h
new file mode 100644
index 0000000..c676849
--- /dev/null
+++ b/Libraries/WiShield/uiplib.h
@@ -0,0 +1,71 @@
+/**
+ * \file
+ * Various uIP library functions.
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+/*
+ * Copyright (c) 2002, Adam Dunkels.
+ * 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 the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
+ *
+ * This file is part of the uIP TCP/IP stack
+ *
+ * $Id: uiplib.h,v 1.1 2006/06/07 09:15:19 adam Exp $
+ *
+ */
+#ifndef __UIPLIB_H__
+#define __UIPLIB_H__
+
+/**
+ * \addtogroup uipconvfunc
+ * @{
+ */
+
+/**
+ * Convert a textual representation of an IP address to a numerical representation.
+ *
+ * This function takes a textual representation of an IP address in
+ * the form a.b.c.d and converts it into a 4-byte array that can be
+ * used by other uIP functions.
+ *
+ * \param addrstr A pointer to a string containing the IP address in
+ * textual form.
+ *
+ * \param addr A pointer to a 4-byte array that will be filled in with
+ * the numerical representation of the address.
+ *
+ * \retval 0 If the IP address could not be parsed.
+ * \retval Non-zero If the IP address was parsed.
+ */
+unsigned char uiplib_ipaddrconv(char *addrstr, unsigned char *addr);
+
+/** @} */
+
+#endif /* __UIPLIB_H__ */
diff --git a/Libraries/WiShield/uipopt.h b/Libraries/WiShield/uipopt.h
new file mode 100644
index 0000000..ae871ba
--- /dev/null
+++ b/Libraries/WiShield/uipopt.h
@@ -0,0 +1,574 @@
+
+/******************************************************************************
+
+ Filename: uipopt.h
+ Description: uIP TCP/IP stack options for the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/29/2009 Initial port
+
+ *****************************************************************************/
+
+/**
+ * \defgroup uipopt Configuration options for uIP
+ * @{
+ *
+ * uIP is configured using the per-project configuration file
+ * uipopt.h. This file contains all compile-time options for uIP and
+ * should be tweaked to match each specific project. The uIP
+ * distribution contains a documented example "uipopt.h" that can be
+ * copied and modified for each project.
+ *
+ * \note Most of the configuration options in the uipopt.h should not
+ * be changed, but rather the per-project uip-conf.h file.
+ */
+
+/**
+ * \file
+ * Configuration options for uIP.
+ * \author Adam Dunkels <adam@dunkels.com>
+ *
+ * This file is used for tweaking various configuration options for
+ * uIP. You should make a copy of this file into one of your project's
+ * directories instead of editing this example "uipopt.h" file that
+ * comes with the uIP distribution.
+ */
+
+/*
+ * Copyright (c) 2001-2003, Adam Dunkels.
+ * 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 the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: uipopt.h,v 1.4 2006/06/12 08:00:31 adam Exp $
+ *
+ */
+
+#ifndef __UIPOPT_H__
+#define __UIPOPT_H__
+
+#ifndef UIP_LITTLE_ENDIAN
+#define UIP_LITTLE_ENDIAN 3412
+#endif /* UIP_LITTLE_ENDIAN */
+#ifndef UIP_BIG_ENDIAN
+#define UIP_BIG_ENDIAN 1234
+#endif /* UIP_BIG_ENDIAN */
+
+#include "uip-conf.h"
+
+/*------------------------------------------------------------------------------*/
+
+/**
+ * \name Static configuration options
+ * @{
+ *
+ * These configuration options can be used for setting the IP address
+ * settings statically, but only if UIP_FIXEDADDR is set to 1. The
+ * configuration options for a specific node includes IP address,
+ * netmask and default router as well as the Ethernet address. The
+ * netmask, default router and Ethernet address are appliciable only
+ * if uIP should be run over Ethernet.
+ *
+ * All of these should be changed to suit your project.
+*/
+
+/**
+ * Determines if uIP should use a fixed IP address or not.
+ *
+ * If uIP should use a fixed IP address, the settings are set in the
+ * uipopt.h file. If not, the macros uip_sethostaddr(),
+ * uip_setdraddr() and uip_setnetmask() should be used instead.
+ *
+ * \hideinitializer
+ */
+#define UIP_FIXEDADDR 0
+
+/**
+ * Ping IP address asignment.
+ *
+ * uIP uses a "ping" packets for setting its own IP address if this
+ * option is set. If so, uIP will start with an empty IP address and
+ * the destination IP address of the first incoming "ping" (ICMP echo)
+ * packet will be used for setting the hosts IP address.
+ *
+ * \note This works only if UIP_FIXEDADDR is 0.
+ *
+ * \hideinitializer
+ */
+#ifdef UIP_CONF_PINGADDRCONF
+#define UIP_PINGADDRCONF UIP_CONF_PINGADDRCONF
+#else /* UIP_CONF_PINGADDRCONF */
+#define UIP_PINGADDRCONF 0
+#endif /* UIP_CONF_PINGADDRCONF */
+
+
+/**
+ * Specifies if the uIP ARP module should be compiled with a fixed
+ * Ethernet MAC address or not.
+ *
+ * If this configuration option is 0, the macro uip_setethaddr() can
+ * be used to specify the Ethernet address at run-time.
+ *
+ * \hideinitializer
+ */
+#define UIP_FIXEDETHADDR 0
+
+/** @} */
+/*------------------------------------------------------------------------------*/
+/**
+ * \name IP configuration options
+ * @{
+ *
+ */
+/**
+ * The IP TTL (time to live) of IP packets sent by uIP.
+ *
+ * This should normally not be changed.
+ */
+#define UIP_TTL 64
+
+/**
+ * Turn on support for IP packet reassembly.
+ *
+ * uIP supports reassembly of fragmented IP packets. This features
+ * requires an additonal amount of RAM to hold the reassembly buffer
+ * and the reassembly code size is approximately 700 bytes. The
+ * reassembly buffer is of the same size as the uip_buf buffer
+ * (configured by UIP_BUFSIZE).
+ *
+ * \note IP packet reassembly is not heavily tested.
+ *
+ * \hideinitializer
+ */
+#define UIP_REASSEMBLY 0
+
+/**
+ * The maximum time an IP fragment should wait in the reassembly
+ * buffer before it is dropped.
+ *
+ */
+#define UIP_REASS_MAXAGE 40
+
+/** @} */
+
+/*------------------------------------------------------------------------------*/
+/**
+ * \name UDP configuration options
+ * @{
+ */
+
+/**
+ * Toggles wether UDP support should be compiled in or not.
+ *
+ * \hideinitializer
+ */
+#ifdef UIP_CONF_UDP
+#define UIP_UDP UIP_CONF_UDP
+#else /* UIP_CONF_UDP */
+#define UIP_UDP 0
+#endif /* UIP_CONF_UDP */
+
+/**
+ * Toggles if UDP checksums should be used or not.
+ *
+ * \note Support for UDP checksums is currently not included in uIP,
+ * so this option has no function.
+ *
+ * \hideinitializer
+ */
+#ifdef UIP_CONF_UDP_CHECKSUMS
+#define UIP_UDP_CHECKSUMS UIP_CONF_UDP_CHECKSUMS
+#else
+#define UIP_UDP_CHECKSUMS 0
+#endif
+
+/**
+ * The maximum amount of concurrent UDP connections.
+ *
+ * \hideinitializer
+ */
+#ifdef UIP_CONF_UDP_CONNS
+#define UIP_UDP_CONNS UIP_CONF_UDP_CONNS
+#else /* UIP_CONF_UDP_CONNS */
+#define UIP_UDP_CONNS 10
+#endif /* UIP_CONF_UDP_CONNS */
+
+/**
+ * The name of the function that should be called when UDP datagrams arrive.
+ *
+ * \hideinitializer
+ */
+
+
+/** @} */
+/*------------------------------------------------------------------------------*/
+/**
+ * \name TCP configuration options
+ * @{
+ */
+
+/**
+ * Determines if support for opening connections from uIP should be
+ * compiled in.
+ *
+ * If the applications that are running on top of uIP for this project
+ * do not need to open outgoing TCP connections, this configration
+ * option can be turned off to reduce the code size of uIP.
+ *
+ * \hideinitializer
+ */
+#define UIP_ACTIVE_OPEN 1
+
+/**
+ * The maximum number of simultaneously open TCP connections.
+ *
+ * Since the TCP connections are statically allocated, turning this
+ * configuration knob down results in less RAM used. Each TCP
+ * connection requires approximatly 30 bytes of memory.
+ *
+ * \hideinitializer
+ */
+#ifndef UIP_CONF_MAX_CONNECTIONS
+#define UIP_CONNS 10
+#else /* UIP_CONF_MAX_CONNECTIONS */
+#define UIP_CONNS UIP_CONF_MAX_CONNECTIONS
+#endif /* UIP_CONF_MAX_CONNECTIONS */
+
+
+/**
+ * The maximum number of simultaneously listening TCP ports.
+ *
+ * Each listening TCP port requires 2 bytes of memory.
+ *
+ * \hideinitializer
+ */
+#ifndef UIP_CONF_MAX_LISTENPORTS
+#define UIP_LISTENPORTS 20
+#else /* UIP_CONF_MAX_LISTENPORTS */
+#define UIP_LISTENPORTS UIP_CONF_MAX_LISTENPORTS
+#endif /* UIP_CONF_MAX_LISTENPORTS */
+
+/**
+ * Determines if support for TCP urgent data notification should be
+ * compiled in.
+ *
+ * Urgent data (out-of-band data) is a rarely used TCP feature that
+ * very seldom would be required.
+ *
+ * \hideinitializer
+ */
+#define UIP_URGDATA 0
+
+/**
+ * The initial retransmission timeout counted in timer pulses.
+ *
+ * This should not be changed.
+ */
+#define UIP_RTO 3
+
+/**
+ * The maximum number of times a segment should be retransmitted
+ * before the connection should be aborted.
+ *
+ * This should not be changed.
+ */
+#define UIP_MAXRTX 8
+
+/**
+ * The maximum number of times a SYN segment should be retransmitted
+ * before a connection request should be deemed to have been
+ * unsuccessful.
+ *
+ * This should not need to be changed.
+ */
+#define UIP_MAXSYNRTX 5
+
+/**
+ * The TCP maximum segment size.
+ *
+ * This is should not be to set to more than
+ * UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN.
+ */
+#define ZG_RX_HDR_LEN 17 // ZeroG G2100 RX Indicate header length
+#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN - ZG_RX_HDR_LEN)
+
+/**
+ * The size of the advertised receiver's window.
+ *
+ * Should be set low (i.e., to the size of the uip_buf buffer) is the
+ * application is slow to process incoming data, or high (32768 bytes)
+ * if the application processes data quickly.
+ *
+ * \hideinitializer
+ */
+#ifndef UIP_CONF_RECEIVE_WINDOW
+#define UIP_RECEIVE_WINDOW UIP_TCP_MSS
+#else
+#define UIP_RECEIVE_WINDOW UIP_CONF_RECEIVE_WINDOW
+#endif
+
+/**
+ * How long a connection should stay in the TIME_WAIT state.
+ *
+ * This configiration option has no real implication, and it should be
+ * left untouched.
+ */
+#define UIP_TIME_WAIT_TIMEOUT 120
+
+
+/** @} */
+/*------------------------------------------------------------------------------*/
+/**
+ * \name ARP configuration options
+ * @{
+ */
+
+/**
+ * The size of the ARP table.
+ *
+ * This option should be set to a larger value if this uIP node will
+ * have many connections from the local network.
+ *
+ * \hideinitializer
+ */
+#ifdef UIP_CONF_ARPTAB_SIZE
+#define UIP_ARPTAB_SIZE UIP_CONF_ARPTAB_SIZE
+#else
+#define UIP_ARPTAB_SIZE 8
+#endif
+
+/**
+ * The maxium age of ARP table entries measured in 10ths of seconds.
+ *
+ * An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD
+ * default).
+ */
+#define UIP_ARP_MAXAGE 120
+
+/** @} */
+
+/*------------------------------------------------------------------------------*/
+
+/**
+ * \name General configuration options
+ * @{
+ */
+
+/**
+ * The size of the uIP packet buffer.
+ *
+ * The uIP packet buffer should not be smaller than 60 bytes, and does
+ * not need to be larger than 1500 bytes. Lower size results in lower
+ * TCP throughput, larger size results in higher TCP throughput.
+ *
+ * \hideinitializer
+ */
+#ifndef UIP_CONF_BUFFER_SIZE
+#define UIP_BUFSIZE 400
+#else /* UIP_CONF_BUFFER_SIZE */
+#define UIP_BUFSIZE UIP_CONF_BUFFER_SIZE
+#endif /* UIP_CONF_BUFFER_SIZE */
+
+
+/**
+ * Determines if statistics support should be compiled in.
+ *
+ * The statistics is useful for debugging and to show the user.
+ *
+ * \hideinitializer
+ */
+#ifndef UIP_CONF_STATISTICS
+#define UIP_STATISTICS 0
+#else /* UIP_CONF_STATISTICS */
+#define UIP_STATISTICS UIP_CONF_STATISTICS
+#endif /* UIP_CONF_STATISTICS */
+
+/**
+ * Determines if logging of certain events should be compiled in.
+ *
+ * This is useful mostly for debugging. The function uip_log()
+ * must be implemented to suit the architecture of the project, if
+ * logging is turned on.
+ *
+ * \hideinitializer
+ */
+#ifndef UIP_CONF_LOGGING
+#define UIP_LOGGING 0
+#else /* UIP_CONF_LOGGING */
+#define UIP_LOGGING UIP_CONF_LOGGING
+#endif /* UIP_CONF_LOGGING */
+
+/**
+ * Broadcast support.
+ *
+ * This flag configures IP broadcast support. This is useful only
+ * together with UDP.
+ *
+ * \hideinitializer
+ *
+ */
+#ifndef UIP_CONF_BROADCAST
+#define UIP_BROADCAST 0
+#else /* UIP_CONF_BROADCAST */
+#define UIP_BROADCAST UIP_CONF_BROADCAST
+#endif /* UIP_CONF_BROADCAST */
+
+/**
+ * Print out a uIP log message.
+ *
+ * This function must be implemented by the module that uses uIP, and
+ * is called by uIP whenever a log message is generated.
+ */
+void uip_log(char *msg);
+
+/**
+ * The link level header length.
+ *
+ * This is the offset into the uip_buf where the IP header can be
+ * found. For Ethernet, this should be set to 14. For SLIP, this
+ * should be set to 0.
+ *
+ * \hideinitializer
+ */
+#ifdef UIP_CONF_LLH_LEN
+#define UIP_LLH_LEN UIP_CONF_LLH_LEN
+#else /* UIP_CONF_LLH_LEN */
+#define UIP_LLH_LEN 14
+#endif /* UIP_CONF_LLH_LEN */
+
+/** @} */
+/*------------------------------------------------------------------------------*/
+/**
+ * \name CPU architecture configuration
+ * @{
+ *
+ * The CPU architecture configuration is where the endianess of the
+ * CPU on which uIP is to be run is specified. Most CPUs today are
+ * little endian, and the most notable exception are the Motorolas
+ * which are big endian. The BYTE_ORDER macro should be changed to
+ * reflect the CPU architecture on which uIP is to be run.
+ */
+
+/**
+ * The byte order of the CPU architecture on which uIP is to be run.
+ *
+ * This option can be either BIG_ENDIAN (Motorola byte order) or
+ * LITTLE_ENDIAN (Intel byte order).
+ *
+ * \hideinitializer
+ */
+#ifdef UIP_CONF_BYTE_ORDER
+#define UIP_BYTE_ORDER UIP_CONF_BYTE_ORDER
+#else /* UIP_CONF_BYTE_ORDER */
+#define UIP_BYTE_ORDER UIP_LITTLE_ENDIAN
+#endif /* UIP_CONF_BYTE_ORDER */
+
+/** @} */
+/*------------------------------------------------------------------------------*/
+
+/**
+ * \name Appication specific configurations
+ * @{
+ *
+ * An uIP application is implemented using a single application
+ * function that is called by uIP whenever a TCP/IP event occurs. The
+ * name of this function must be registered with uIP at compile time
+ * using the UIP_APPCALL definition.
+ *
+ * uIP applications can store the application state within the
+ * uip_conn structure by specifying the type of the application
+ * structure by typedef:ing the type uip_tcp_appstate_t and uip_udp_appstate_t.
+ *
+ * The file containing the definitions must be included in the
+ * uipopt.h file.
+ *
+ * The following example illustrates how this can look.
+ \code
+
+void httpd_appcall(void);
+#define UIP_APPCALL httpd_appcall
+
+struct httpd_state {
+ u8_t state;
+ u16_t count;
+ char *dataptr;
+ char *script;
+};
+typedef struct httpd_state uip_tcp_appstate_t
+ \endcode
+ */
+
+/**
+ * \var #define UIP_APPCALL
+ *
+ * The name of the application function that uIP should call in
+ * response to TCP/IP events.
+ *
+ */
+
+/**
+ * \var typedef uip_tcp_appstate_t
+ *
+ * The type of the application state that is to be stored in the
+ * uip_conn structure. This usually is typedef:ed to a struct holding
+ * application state information.
+ */
+
+/**
+ * \var typedef uip_udp_appstate_t
+ *
+ * The type of the application state that is to be stored in the
+ * uip_conn structure. This usually is typedef:ed to a struct holding
+ * application state information.
+ */
+/** @} */
+/** @} */
+
+#endif /* __UIPOPT_H__ */
diff --git a/Libraries/WiShield/webclient.h b/Libraries/WiShield/webclient.h
new file mode 100644
index 0000000..f7b3850
--- /dev/null
+++ b/Libraries/WiShield/webclient.h
@@ -0,0 +1,262 @@
+
+/******************************************************************************
+
+ Filename: webclient.h
+ Description: Webclient app for the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/29/2009 Initial version
+
+ *****************************************************************************/
+
+/**
+ * \addtogroup webclient
+ * @{
+ */
+
+/**
+ * \file
+ * Header file for the HTTP client.
+ * \author Adam Dunkels <adam@dunkels.com>
+ */
+
+/*
+ * Copyright (c) 2002, Adam Dunkels.
+ * 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 the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ * $Id: webclient.h,v 1.2 2006/06/11 21:46:37 adam Exp $
+ *
+ */
+#ifndef __WEBCLIENT_H__
+#define __WEBCLIENT_H__
+
+
+//#include "webclient-strings.h"
+#include "uipopt.h"
+
+#define WEBCLIENT_CONF_MAX_URLLEN 10 //100
+
+struct webclient_state {
+ u8_t timer;
+ u8_t state;
+ u8_t httpflag;
+
+ u16_t port;
+ char host[2]; //[40];
+ char file[WEBCLIENT_CONF_MAX_URLLEN];
+ u16_t getrequestptr;
+ u16_t getrequestleft;
+
+ char httpheaderline[10]; //[200];
+ u16_t httpheaderlineptr;
+
+ char mimetype[2]; //[32];
+};
+
+typedef struct webclient_state uip_tcp_appstate_t;
+#define UIP_APPCALL webclient_appcall
+
+/**
+ * Callback function that is called from the webclient code when HTTP
+ * data has been received.
+ *
+ * This function must be implemented by the module that uses the
+ * webclient code. The function is called from the webclient module
+ * when HTTP data has been received. The function is not called when
+ * HTTP headers are received, only for the actual data.
+ *
+ * \note This function is called many times, repetedly, when data is
+ * being received, and not once when all data has been received.
+ *
+ * \param data A pointer to the data that has been received.
+ * \param len The length of the data that has been received.
+ */
+void webclient_datahandler(char *data, u16_t len);
+
+/**
+ * Callback function that is called from the webclient code when the
+ * HTTP connection has been connected to the web server.
+ *
+ * This function must be implemented by the module that uses the
+ * webclient code.
+ */
+void webclient_connected(void);
+
+/**
+ * Callback function that is called from the webclient code if the
+ * HTTP connection to the web server has timed out.
+ *
+ * This function must be implemented by the module that uses the
+ * webclient code.
+ */
+void webclient_timedout(void);
+
+/**
+ * Callback function that is called from the webclient code if the
+ * HTTP connection to the web server has been aborted by the web
+ * server.
+ *
+ * This function must be implemented by the module that uses the
+ * webclient code.
+ */
+void webclient_aborted(void);
+
+/**
+ * Callback function that is called from the webclient code when the
+ * HTTP connection to the web server has been closed.
+ *
+ * This function must be implemented by the module that uses the
+ * webclient code.
+ */
+void webclient_closed(void);
+
+
+
+/**
+ * Initialize the webclient module.
+ */
+void webclient_init(void);
+
+/**
+ * Open an HTTP connection to a web server and ask for a file using
+ * the GET method.
+ *
+ * This function opens an HTTP connection to the specified web server
+ * and requests the specified file using the GET method. When the HTTP
+ * connection has been connected, the webclient_connected() callback
+ * function is called and when the HTTP data arrives the
+ * webclient_datahandler() callback function is called.
+ *
+ * The callback function webclient_timedout() is called if the web
+ * server could not be contacted, and the webclient_aborted() callback
+ * function is called if the HTTP connection is aborted by the web
+ * server.
+ *
+ * When the HTTP request has been completed and the HTTP connection is
+ * closed, the webclient_closed() callback function will be called.
+ *
+ * \note If the function is passed a host name, it must already be in
+ * the resolver cache in order for the function to connect to the web
+ * server. It is therefore up to the calling module to implement the
+ * resolver calls and the signal handler used for reporting a resolv
+ * query answer.
+ *
+ * \param host A pointer to a string containing either a host name or
+ * a numerical IP address in dotted decimal notation (e.g., 192.168.23.1).
+ *
+ * \param port The port number to which to connect, in host byte order.
+ *
+ * \param file A pointer to the name of the file to get.
+ *
+ * \retval 0 if the host name could not be found in the cache, or
+ * if a TCP connection could not be created.
+ *
+ * \retval 1 if the connection was initiated.
+ */
+unsigned char webclient_get(char *host, u16_t port, char *file);
+
+/**
+ * Close the currently open HTTP connection.
+ */
+void webclient_close(void);
+void webclient_appcall(void);
+
+/**
+ * Obtain the MIME type of the current HTTP data stream.
+ *
+ * \return A pointer to a string contaning the MIME type. The string
+ * may be empty if no MIME type was reported by the web server.
+ */
+char *webclient_mimetype(void);
+
+/**
+ * Obtain the filename of the current HTTP data stream.
+ *
+ * The filename of an HTTP request may be changed by the web server,
+ * and may therefore not be the same as when the original GET request
+ * was made with webclient_get(). This function is used for obtaining
+ * the current filename.
+ *
+ * \return A pointer to the current filename.
+ */
+char *webclient_filename(void);
+
+/**
+ * Obtain the hostname of the current HTTP data stream.
+ *
+ * The hostname of the web server of an HTTP request may be changed
+ * by the web server, and may therefore not be the same as when the
+ * original GET request was made with webclient_get(). This function
+ * is used for obtaining the current hostname.
+ *
+ * \return A pointer to the current hostname.
+ */
+char *webclient_hostname(void);
+
+/**
+ * Obtain the port number of the current HTTP data stream.
+ *
+ * The port number of an HTTP request may be changed by the web
+ * server, and may therefore not be the same as when the original GET
+ * request was made with webclient_get(). This function is used for
+ * obtaining the current port number.
+ *
+ * \return The port number of the current HTTP data stream, in host byte order.
+ */
+unsigned short webclient_port(void);
+
+
+
+#endif /* __WEBCLIENT_H__ */
+
+/** @} */
diff --git a/Libraries/WiShield/webserver.h b/Libraries/WiShield/webserver.h
new file mode 100644
index 0000000..eb030e3
--- /dev/null
+++ b/Libraries/WiShield/webserver.h
@@ -0,0 +1,52 @@
+
+/******************************************************************************
+
+ Filename: webserver.h
+ Description: Webserver app for the WiShield 1.0
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/29/2009 Initial version
+
+ *****************************************************************************/
+
+#ifndef __WEBSERVER_H__
+#define __WEBSERVER_H__
+
+#include "psock.h"
+asdf
+typedef struct webserver_state {
+ struct psock p;
+ char inputbuf[10];
+} uip_tcp_appstate_t;
+
+void webserver_appcall(void);
+#ifndef UIP_APPCALL
+#define UIP_APPCALL webserver_appcall
+#endif /* UIP_APPCALL */
+
+void webserver_init(void);
+
+#endif /* __WEBSERVER_H__ */
diff --git a/Libraries/WiShield/witypes.h b/Libraries/WiShield/witypes.h
new file mode 100644
index 0000000..6bbe885
--- /dev/null
+++ b/Libraries/WiShield/witypes.h
@@ -0,0 +1,72 @@
+
+/******************************************************************************
+
+ Filename: witypes.h
+ Description: Data types
+
+ ******************************************************************************
+
+ TCP/IP stack and driver for the WiShield 1.0 wireless devices
+
+ Copyright(c) 2009 Async Labs Inc. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Contact Information:
+ <asynclabs@asynclabs.com>
+
+ Author Date Comment
+ ---------------------------------------------------------------
+ AsyncLabs 05/01/2009 Initial version
+ AsyncLabs 05/29/2009 Adding support for new library
+
+ *****************************************************************************/
+
+#ifndef WITYPES_H_
+#define WITYPES_H_
+
+#include <avr/pgmspace.h>
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+#ifndef _SIZE_T
+#define _SIZE_T
+typedef unsigned int size_t;
+#endif
+
+typedef char int8;
+typedef volatile char vint8;
+typedef unsigned char uint8;
+typedef volatile unsigned char vuint8;
+typedef int int16;
+typedef volatile int vint16;
+typedef unsigned int uint16;
+typedef volatile unsigned int vuint16;
+typedef long int32;
+typedef volatile long vint32;
+typedef unsigned long uint32;
+typedef volatile unsigned long vuint32;
+
+typedef unsigned char u8;
+typedef unsigned char U8;
+typedef unsigned int u16;
+typedef unsigned int U16;
+typedef unsigned long u32;
+typedef unsigned long U32;
+
+typedef uint8_t boolean;
+
+#endif /* WITYPES_H_ */