MakingThings
  • Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

network.c

Go to the documentation of this file.
00001 /*********************************************************************************
00002 
00003  Copyright 2006-2008 MakingThings
00004 
00005  Licensed under the Apache License, 
00006  Version 2.0 (the "License"); you may not use this file except in compliance 
00007  with the License. You may obtain a copy of the License at
00008 
00009  http://www.apache.org/licenses/LICENSE-2.0 
00010  
00011  Unless required by applicable law or agreed to in writing, software distributed
00012  under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
00013  CONDITIONS OF ANY KIND, either express or implied. See the License for
00014  the specific language governing permissions and limitations under the License.
00015 
00016 *********************************************************************************/
00017 
00018 /** \file network.c 
00019   Communicate with the Make Controller Board via Ethernet.
00020 */
00021 
00022 #include "config.h"
00023 #ifdef MAKE_CTRL_NETWORK
00024 
00025 #include "stdio.h"
00026 #include "io.h"
00027 #include "eeprom.h"
00028 #include "timer.h"
00029 
00030 /* lwIP includes. */
00031 #include "lwip/api.h"
00032 #include "lwip/tcpip.h"
00033 #include "lwip/memp.h" 
00034 #include "lwip/netbuf.h" 
00035 #include "lwip/stats.h"
00036 #include "netif/loopif.h"
00037 #include "lwip/dhcp.h"
00038 #include "lwip/dns.h"
00039 
00040 /* Low level includes. */
00041 #include "SAM7_EMAC.h"
00042 
00043 int Network_AddressConvert( char* address, int* a0, int* a1, int* a2, int* a3 );
00044 
00045 /* MAC address definition.  The MAC address must be unique on the network. */
00046 char emacETHADDR0 = 0xAC;
00047 char emacETHADDR1 = 0xDE;
00048 char emacETHADDR2 = 0x48;
00049 char emacETHADDR3 = 0x55;
00050 char emacETHADDR4 = 0x0;
00051 char emacETHADDR5 = 0x0;
00052 
00053 #include "network.h"
00054 
00055 typedef struct Network_
00056 {
00057   int pending; // if somebody has started the process of getting an IP address, don't start another process
00058   int TempIpAddress; // hold onto the values that will ultimately get set for the network
00059   int TempGateway; // once it's all set as valid
00060   int TempMask;
00061   int OscUdpListenPort;
00062   int OscUdpSendPort;
00063   int TcpOutAddress;
00064   int TcpOutPort;
00065   bool TcpRequested;
00066   int DnsResolvedAddress;
00067   #ifdef OSC
00068   char scratch1[ OSC_SCRATCH_SIZE ];
00069   char scratch2[ OSC_SCRATCH_SIZE ];
00070   #endif // OSC
00071 } NetworkStruct;
00072 
00073 xSemaphoreHandle Network_DnsSemaphore;
00074 
00075 // a few globals
00076 NetworkStruct* Network;
00077 
00078 enum { NET_UNCHECKED, NET_INVALID, NET_VALID } Network_Valid;
00079 
00080 void Network_SetPending( int state );
00081 int Network_GetPending( void );
00082 void Network_DhcpStart( struct netif* netif );
00083 void Network_DhcpStop( struct netif* netif );
00084 void Network_SetDefaults( void );
00085 static void Network_DnsCallback(const char *name, struct ip_addr *addr, void *arg);
00086 
00087 /** \defgroup Sockets Sockets
00088   The Sockets system provides a simple interface for creating, reading and writing over both TCP and UDP.  
00089   This subsystem is a light wrapper around LwIP, the open source TCP/IP stack used by the Make Controller Kit.
00090   There are 3 groups of socket functions:
00091   - DatagramSocket - sockets for \b UDP communication
00092   - Socket - sockets for \b TCP communication
00093   - ServerSocket - sockets for accepting \b incoming TCP client connections
00094   \ingroup Core
00095   @{
00096 */
00097 
00098 /** 
00099   Create a new TCP socket connected to the address and port specified.
00100   @param address An integer specifying the IP address to connect to.
00101   @param port An integer specifying the port to connect on.
00102   @return A pointer to the socket, if it was created successfully.  NULL if unsuccessful.
00103   @see SocketRead(), SocketWrite(), SocketClose()
00104 
00105   \par Example
00106   \code
00107   // use the IP_ADDRESS macro to format the address properly
00108   int addr = IP_ADDRESS( 192, 168, 0, 54 );
00109   // then create the socket, connecting on port 10101
00110   struct netconn* socket = Socket( addr, 10101 );
00111   \endcode
00112 */
00113 void* Socket( int address, int port )
00114 {
00115   Network_SetActive( 1 );
00116 
00117   struct netconn* conn;
00118   err_t retval;
00119 
00120   conn = netconn_new( NETCONN_TCP );
00121   // This is our addition to the conn structure to help with reading
00122   conn->readingbuf = NULL;
00123 
00124   struct ip_addr remote_addr;
00125   remote_addr.addr = htonl(address);
00126 
00127   retval = netconn_connect( conn, &remote_addr, port );
00128   
00129   if( ERR_OK != retval )
00130   {
00131     //netconn_delete( conn );
00132     while( netconn_delete( conn ) != ERR_OK )
00133       Sleep( 10 );
00134 
00135     conn = NULL;
00136   }
00137   
00138   return conn;
00139 }
00140 
00141 /**
00142   Get the number of bytes available in a TCP socket.
00143   Handy before calling SocketRead() so you know how many to read.
00144   @param socket The socket.
00145   @return The number of bytes available in that socket.
00146 
00147   \b Example
00148   \code
00149   struct netconn* mysocket = Socket(IP_ADDRESS( 192, 168, 0, 54 ), 10101);
00150   // ... reading and writing ...
00151   int avail = Socket_BytesAvailable(mysocket);
00152   \endcode
00153 */
00154 int SocketBytesAvailable( void* socket )
00155 {
00156   if(!socket)
00157     return 0;
00158   struct netconn *conn = socket;
00159   int len = conn->recv_avail;
00160   if(conn->readingbuf)
00161     len += (netbuf_len( conn->readingbuf ) - conn->readingoffset);
00162   return len;
00163 }
00164 
00165 /** 
00166   Read from a TCP socket.
00167   Make sure you have an open socket before trying to read from it.  This function
00168   will block until the requested number of bytes are read.  See Socket_BytesAvailable()
00169   to get the number of bytes waiting to be read.
00170   @param socket A pointer to the existing socket.
00171   @param data A pointer to the buffer to read to.
00172   @param length An integer specifying the maximum length in bytes that can be read.
00173   @return An integer: length of data read if successful, zero on failure.
00174   @see Socket(), SocketClose()
00175 
00176   \par Example
00177   \code
00178   // we should already have created a socket sock with Socket().
00179   struct netconn* sock = Socket( addr, 10101 );
00180   int length_read = SocketRead( sock, data, length )
00181   // if 0 bytes were read, there was some sort of error
00182   if( length_read == 0 )
00183     SocketClose( sock );
00184   \endcode
00185 */
00186 int SocketRead( void* socket, char* data, int length )
00187 {
00188   if(!socket)
00189     return 0;
00190   struct netconn *conn = socket;
00191   struct netbuf *buf;
00192   int totalBytesRead = 0;
00193   int extraBytes = 0;
00194   
00195   while(totalBytesRead < length)
00196   {
00197     if ( conn->readingbuf == NULL )
00198     {
00199       buf = netconn_recv( conn );
00200       if ( buf == NULL )
00201         return 0;
00202       
00203       /* 
00204       Now deal appropriately with what we got.  If we got more than we asked for,
00205       keep the extras in the conn->readingbuf and set the conn->readingoffset.
00206       Otherwise, copy everything we got back into the calling buffer.
00207       */
00208       int bytesRead = netbuf_len( buf );
00209       totalBytesRead += bytesRead;
00210       if( totalBytesRead <= length ) 
00211       {
00212         netbuf_copy( buf, data, bytesRead );
00213         netbuf_delete( buf );
00214         data += bytesRead;
00215         // conn->readingbuf remains NULL
00216       }
00217       else // if we got more than we asked for
00218       {
00219         extraBytes = totalBytesRead - length;
00220         bytesRead -= extraBytes; // how many do we need to write to get the originally requested len
00221         netbuf_copy( buf, data, bytesRead );
00222         conn->readingbuf = buf;
00223         conn->readingoffset = bytesRead;
00224       }
00225     }
00226     else // conn->readingbuf != NULL
00227     {
00228       buf = conn->readingbuf;
00229       int bytesRead = netbuf_len( buf ) - conn->readingoffset; // grab whatever was lying around from a previous read
00230       totalBytesRead += bytesRead;
00231       
00232       if( totalBytesRead <= length ) // there's less than or just enough left for what we need
00233       {
00234         netbuf_copy_partial( buf, data, bytesRead, conn->readingoffset ); // copy out the rest of what was in the netbuf
00235         netbuf_delete( buf ); // and get rid of it
00236         conn->readingbuf = NULL;
00237       }  
00238       else // there's more in there than we were asked for
00239       {
00240         extraBytes = totalBytesRead - length;
00241         bytesRead -= extraBytes; // how many do we need to write to get the originally requested len
00242         netbuf_copy_partial( buf, data, bytesRead, conn->readingoffset ); // only read out what we need
00243         //netbuf_copy( buf, data, bytesRead );
00244         conn->readingoffset += bytesRead;
00245       }
00246       data += bytesRead;
00247     }
00248   }
00249   return totalBytesRead - extraBytes;
00250 }
00251 
00252 /** 
00253   Read a line from a TCP socket terminated by CR LF (0x0D 0x0A).  
00254   Make sure you have an open socket before trying to read from it.
00255   @param socket A pointer to the existing socket.
00256   @param data A pointer to the buffer to read to.
00257   @param length An integer specifying the maximum length in bytes to read.
00258   @return An integer: length of data read if successful, zero on failure.
00259   @see Socket(), SocketRead(), SocketClose()
00260 */
00261 
00262 int SocketReadLine( void* socket, char* data, int length )
00263 {
00264   int readLength;
00265   int lineLength = -1;
00266   //int terminated = false;
00267   data--;
00268 
00269   // Upon entering, data points to char prior to buffer, length is -1
00270   do 
00271   {
00272     data++;
00273     // here data points to where byte will be written
00274     lineLength++;
00275     // linelength now reflects true number of bytes
00276     readLength = SocketRead( socket, data, 1 );
00277     // here, if readlength == 1, data has a new char in next position, linelength is one off,
00278     //       if readlength == 0, data had no new char and linelength is right
00279   } while ( ( readLength == 1 ) && ( lineLength < length - 1 ) && ( *data != '\n' ) );
00280 
00281   // here, length is corrected if there was a character  
00282   if ( readLength == 1 )
00283     lineLength++;
00284   
00285   return lineLength;
00286 }
00287 
00288 
00289 /** 
00290   Write to a TCP socket.
00291   Not surprisingly, we need an existing socket before we can write to it.
00292 
00293   @param socket A pointer to the existing socket.
00294   @param data A pointer to the buffer to write from.
00295   @param length An integer specifying the length in bytes of how much data should be written.
00296   @return An integer: 'length written' if successful, 0 on failure.
00297   @see Socket()
00298 
00299   \par Example
00300   \code
00301   // we should already have created a socket with Socket()
00302   struct netconn* sock = Socket( addr, 10101 );
00303   int length_written = SocketWrite( sock, data, length )
00304   // if 0 bytes were written, there was some sort of error
00305   if( length_written == 0 )
00306     SocketClose( sock );
00307   \endcode
00308 */
00309 int SocketWrite( void* socket, char* data, int length )
00310 {
00311   int err = netconn_write( (struct netconn *)socket, data, length, NETCONN_COPY);
00312   if ( err != ERR_OK )
00313     return 0;
00314   else
00315     return length;
00316 }
00317 
00318 /** 
00319   Close an existing TCP socket.
00320   Anytime you get an error when trying to read or write, it's best to close the socket and reopen
00321   it to make sure that the connection is corrently configured.
00322   @param socket A pointer to the existing socket.
00323   @return void
00324   @see Socket()
00325 
00326   \par Example
00327   \code
00328   // we should already have created a socket 'sock' with Socket().
00329   struct netconn* sock = Socket( addr, 10101 );
00330   // now close it
00331   SocketClose( sock )
00332   \endcode
00333 */
00334 void SocketClose( void* socket )
00335 { 
00336   // Make sure there is no buffer lying around
00337   struct netconn *conn = socket;
00338   if ( conn->readingbuf != NULL )
00339   {   
00340     netbuf_delete( conn->readingbuf );
00341     conn->readingbuf = NULL;
00342   }
00343 
00344   netconn_close( (struct netconn *)socket );
00345   netconn_delete( (struct netconn *)socket );
00346   return;
00347 }
00348 
00349 /** 
00350   Create a new TCP server socket and start listening for connections.
00351   @param port An integer specifying the port to listen on.
00352   @return A pointer to the socket created.
00353   @see ServerSocketAccept( )
00354   
00355   \par Example
00356   \code
00357   // create a socket and start listening on port 10101
00358   struct netconn* server = ServerSocket( 10101 );
00359   // ServerSocketAccept( ) will block until an incoming connection is made
00360   struct netconn* newConnection = ServerSocketAccept( server );
00361   // now grab the data from the new connection
00362   \endcode
00363 */
00364 void* ServerSocket( int port )
00365 {
00366   Network_SetActive( 1 );
00367 
00368   struct netconn *conn;
00369 
00370   conn = netconn_new( NETCONN_TCP );
00371   if ( conn != NULL )
00372   { 
00373     netconn_bind( conn, 0, port );
00374     netconn_listen( conn );
00375   }
00376 
00377   return conn;
00378 }
00379 
00380 /** 
00381   Accept an incoming connection to a ServerSocket that you have created.  This
00382   function will block until a new connection is waiting to be serviced.  It returns
00383   a regular socket on which you can use SocketWrite(), SocketRead() and SocketClose().
00384   @param serverSocket a pointer to a ServerSocket that you created
00385   @return a pointer to the new socket created to handle the connection
00386   @see ServerSocket(), SocketWrite(), SocketRead(), SocketClose()
00387 */
00388 void* ServerSocketAccept( void* serverSocket )
00389 {
00390   struct netconn *conn;
00391   conn = netconn_accept( (struct netconn *)serverSocket );
00392   // This is our addition to the conn structure to help with reading
00393   if ( conn != NULL )
00394     conn->readingbuf = NULL;
00395   return conn;
00396 }
00397 
00398 /** 
00399   Close a ServerSocket that you have created.
00400   @param serverSocket A pointer to a ServerSocket.
00401   @return 0 if the process was successful.
00402   @see ServerSocket()
00403   
00404   \par Example
00405   \code
00406   // we created a server socket at some point
00407   struct netconn* server = ServerSocket( 10101 );
00408   // now close it
00409   ServerSocketClose( server );
00410   \endcode
00411 */
00412 int ServerSocketClose( void* serverSocket )
00413 {
00414   // netconn_close( serverSocket );
00415   netconn_delete( serverSocket );
00416   return 0;
00417 }
00418 
00419 /** 
00420   Create a socket to read and write UDP packets.
00421   @param port An integer specifying the port to open.
00422   @return a pointer to the socket created.
00423   @see DatagramSocketSend( ), DatagramSocketReceive( )
00424   
00425   \par Example
00426   \code
00427   // create a new UDP socket on port 10101
00428   struct netconn* udpSocket = DatagramSocket( 10101 );
00429   // now read and write to it using DatagramSocketSend( ) and DatagramSocketReceive( )
00430   \endcode
00431 */
00432 void* DatagramSocket( int port )
00433 {
00434   Network_SetActive( 1 );
00435 
00436   struct netconn *conn;
00437 
00438   conn = netconn_new( NETCONN_UDP );
00439   if( conn == NULL || conn->err != ERR_OK )
00440     return NULL;
00441   // This is our addition to the conn structure to help with reading
00442   conn->readingbuf = NULL;
00443 
00444   // hook it up
00445   netconn_bind( conn, NULL, port );
00446 
00447   return conn;
00448 }
00449 
00450 /** 
00451   Send a UDP packet to a specified address.
00452   @param datagramSocket A pointer to the DatagramSocket() you're using to write.
00453   @param address An integer specifying the IP address to write to.
00454   @param port An integer specifying the port to write to.
00455   @param data A pointer to the packet to send.
00456   @param length An integer specifying the number of bytes in the packet being sent.
00457   @return An integer corresponding to the number of bytes successfully written.
00458   @see DatagramSocket( )
00459   
00460   \par Example
00461   \code
00462   struct netconn* udpSocket = DatagramSocket( 10101 ); // our socket
00463   int address = IP_ADDRESS( 192, 168, 0, 200 );
00464   int sent = DatagramSocketSend( udpSocket, address, 10101, myBuffer, myLength );
00465   \endcode
00466 */
00467 int DatagramSocketSend( void* datagramSocket, int address, int port, void* data, int length )
00468 { 
00469   struct netconn *conn = (struct netconn *)datagramSocket;
00470   struct netbuf *buf;
00471   struct ip_addr remote_addr;
00472   int lengthsent = 0;
00473 
00474   remote_addr.addr = htonl(address);
00475   if( ERR_OK != netconn_connect(conn, &remote_addr, port) )
00476     return lengthsent;
00477 
00478   // create a buffer
00479   buf = netbuf_new();
00480   if( buf != NULL )
00481   {
00482     netbuf_ref( buf, data, length); // make the buffer point to the data that should be sent
00483     if( ERR_OK != netconn_send( conn, buf) ) // send the data
00484     {
00485       netbuf_delete(buf);
00486       return 0;
00487     }
00488     lengthsent = length;
00489     netbuf_delete(buf); // deallocate the buffer
00490   }
00491 
00492   return lengthsent;
00493 }
00494 
00495 /** 
00496   Receive a UDP packet.  
00497   This function will block until a packet is received. The address and port of the 
00498   sender are returned in the locations pointed to by the address and port parameters.  
00499   If the incoming packet is larger than the specified size of the buffer, it will
00500   be truncated.
00501   @param datagramSocket A pointer to the DatagramSocket() you're using to read.
00502   @param incomingPort An integer specifying the port to listen on.
00503   @param address A pointer to the IP address that sent the packet.
00504   @param port A pointer to the port of the sender.
00505   @param data A pointer to the buffer to read into.
00506   @param length An integer specifying the number of bytes in the packet being read.
00507   @return An integer corresponding to the number of bytes successfully read.
00508   @see DatagramSocket( )
00509   
00510   \par Example
00511   \code
00512   struct netconn* udpSocket = DatagramSocket( 10101 ); // our socket
00513   int address, port;
00514   int sent = DatagramSocketReceive( udpSocket, &address, &port, myBuffer, myLength );
00515   \endcode
00516 */
00517 int DatagramSocketReceive( void* datagramSocket, int incomingPort, int* address, int* port, void* data, int length )
00518 {
00519   struct netconn *conn = (struct netconn*)datagramSocket;
00520   struct netbuf *buf;
00521   struct ip_addr *addr;
00522   int buflen = 0;
00523 
00524   if( ERR_OK != netconn_bind( conn, IP_ADDR_ANY, incomingPort ) )
00525     return buflen;
00526     
00527   buf = netconn_recv( conn );
00528   if( buf != NULL )
00529   {
00530     buflen = netbuf_len( buf );
00531     // copy the contents of the received buffer into
00532     //the supplied memory pointer 
00533     netbuf_copy(buf, data, length);
00534     addr = netbuf_fromaddr(buf);
00535     *port = netbuf_fromport(buf);
00536     *address = ntohl( addr->addr );
00537     netbuf_delete(buf);
00538   }
00539 
00540   /* if the length of the received data is larger than
00541   len, this data is discarded and we return len.
00542   otherwise we return the actual length of the received
00543   data */
00544   if(length > buflen)
00545     return buflen;
00546   else
00547     return length;
00548 }
00549 
00550 /** 
00551   Close a DatagramSocket().
00552   @param socket A pointer to the DatagramSocket() to close.
00553   @see DatagramSocket( )
00554   
00555   \par Example
00556   \code
00557   struct netconn* udpSocket = DatagramSocket( 10101 ); // create our socket
00558   // now close it
00559   DatagramSocketClose( udpSocket );
00560   \endcode
00561 */
00562 void DatagramSocketClose( void* socket )
00563 {
00564   netconn_close( socket );
00565   netconn_delete( socket );
00566 }
00567 
00568 /** @}
00569 */
00570 
00571 /** \defgroup Network Network
00572   The Network subsystem manages the Ethernet controller.
00573   
00574   Like any other network enabled device, the Make Controller has an IP address, net mask and gateway.
00575   - The default IP address is 192.168.0.200
00576   - The default mask is 255.255.255.0
00577   - The default gateway 192.168.0.1
00578   
00579   You can set any of these values manually, or use DHCP to get them automatically.
00580   
00581   \section MAC
00582   The Make Controller's MAC address defaults to AC.DE.48.55.x.y where x & y are calculated from the 
00583   unit's serial number, handled by the \ref System subsystem.
00584   
00585   \section webserver Web Server
00586   The Make Controller Kit can also act as a web server.  The demo web server running on the Make Controller
00587   displays some stats about the board's current state through a web interface.  It is intended mainly as
00588   a starting point for more useful web applications.  See the source in webserver.c.
00589 
00590   \ingroup Core
00591   @{
00592 */
00593 
00594 /**
00595   Sets whether the Network subsystem is active.  
00596   This fires up the networking system on the Make Controller, and will not return until a network is found,
00597   ie. a network cable is plugged in.
00598   @param state An integer specifying the active state - 1 (active) or 0 (inactive).
00599   @return 0 on success.
00600 */
00601 int Network_SetActive( int state )
00602 {
00603   if ( state ) 
00604   {
00605     if( Network == NULL )
00606     {
00607       Network = MallocWait( sizeof( NetworkStruct ), 100 );
00608       Network->pending = 1;
00609       Network->TcpRequested = 0;
00610       Network_DnsSemaphore = NULL;
00611       Network->DnsResolvedAddress = -1;
00612 
00613 
00614       if( !Network_GetValid() ) // if we don't have good values, set the defaults
00615         Network_SetDefaults( );
00616       else // load the values from EEPROM
00617       {
00618         Eeprom_Read( EEPROM_SYSTEM_NET_ADDRESS, (uchar*)&Network->TempIpAddress, 4 );
00619         Eeprom_Read( EEPROM_SYSTEM_NET_GATEWAY, (uchar*)&Network->TempGateway, 4 );
00620         Eeprom_Read( EEPROM_SYSTEM_NET_MASK, (uchar*)&Network->TempMask, 4 );
00621       }
00622 
00623       Network->OscUdpListenPort = NetworkOsc_GetUdpListenPort( );
00624       Network->OscUdpSendPort = NetworkOsc_GetUdpSendPort( );
00625       Eeprom_Read( EEPROM_TCP_OUT_ADDRESS, (uchar*)&Network->TcpOutAddress, 4 );
00626       Eeprom_Read( EEPROM_TCP_OUT_PORT, (uchar*)&Network->TcpOutPort, 4 );
00627       Network_Init();
00628     }
00629   }
00630   else 
00631   {
00632     if( Network )
00633     {
00634       Free( Network );
00635       Network = NULL;
00636     }
00637   }
00638 
00639   return CONTROLLER_OK;
00640 }
00641 
00642 /**
00643   Returns the active state of the Network subsystem.
00644   @return State - 1 (active) or 0 (inactive).
00645 */
00646 int Network_GetActive( void )
00647 {
00648   if( Network == NULL || Network_GetPending( ) )
00649     return 0;
00650   else
00651     return 1;
00652 }
00653 
00654 /**
00655   Set the IP address of the Make Controller.
00656   The IP address of the Make Controller, in dotted decimal form (xxx.xxx.xxx.xxx),
00657   can be set by passing in each of the numbers as a separate parameter.
00658   The default IP address of each Make Controller as it ships from the factory
00659   is 192.168.0.200.  
00660 
00661   This value is stored in EEPROM, so it persists even after the board
00662   is powered down.
00663 
00664   @param a0 An integer corresponding to the first of 4 numbers in the address.
00665   @param a1 An integer corresponding to the second of 4 numbers in the address.
00666   @param a2 An integer corresponding to the third of 4 numbers in the address.
00667   @param a3 An integer corresponding to the fourth of 4 numbers in the address.
00668   @return 0 on success.
00669 
00670   \par Example
00671   \code
00672   // set the address to 192.168.0.23
00673   Network_SetAddress( 192, 168, 0, 23 );
00674   \endcode
00675 
00676 */
00677 int Network_SetAddress( int a0, int a1, int a2, int a3 )
00678 {
00679   // just store this address, since we're only going to do something with it in response to
00680   if( !Network_GetValid() )
00681   {
00682     Network_SetDefaults( );
00683     Network_SetValid( 1 );
00684   }
00685   Network->TempIpAddress = NETIF_IP_ADDRESS( a0, a1, a2, a3 );
00686   Network_SetValid( 1 );
00687 
00688   return CONTROLLER_OK;
00689 }
00690 
00691 /**
00692   Set the network mask of the Make Controller on your local network.
00693   When on a subnet or local network, the network mask must be set in order
00694   for the gateway to route information to the board's IP address properly.
00695   The mask is commonly 255.255.255.0 for many home networks.
00696   Set the mask in dotted decimal form (xxx.xxx.xxx.xxx), passing in each 
00697   number as a separate parameter.
00698 
00699   This value is stored in EEPROM, so it persists even after the board
00700   is powered down.
00701 
00702   @param a0 An integer corresponding to the first of 4 numbers in the mask.
00703   @param a1 An integer corresponding to the second of 4 numbers in the mask.
00704   @param a2 An integer corresponding to the third of 4 numbers in the mask.
00705   @param a3 An integer corresponding to the fourth of 4 numbers in the mask.
00706   @return 0 on success.
00707 
00708   \par Example
00709   \code
00710   // set the mask to 255.255.255.254
00711   if( 0 != Network_SetMask( 255, 255, 255, 254 ) )
00712     // then there was a problem.
00713   \endcode
00714 */
00715 int Network_SetMask( int a0, int a1, int a2, int a3 )
00716 {
00717   // just store this address, since we're only going to do something with it in response to
00718   if( !Network_GetValid() )
00719   {
00720     Network_SetDefaults( );
00721     Network_SetValid( 1 );
00722   }
00723   Network->TempMask = NETIF_IP_ADDRESS( a0, a1, a2, a3 );
00724   Network_SetValid( 1 );
00725 
00726   return CONTROLLER_OK;
00727 }
00728 
00729 /**
00730   Set the gateway address for the local network the Make Controller is on.
00731   The gateway address is commonly 192.168.0.1 for many home networks.
00732   Set the gateway address in dotted decimal form (xxx.xxx.xxx.xxx), passing in each 
00733   number as a separate parameter.
00734 
00735   This value is stored in EEPROM, so it persists even after the board
00736   is powered down.
00737 
00738   @param a0 An integer corresponding to the first of 4 numbers in the gateway address.
00739   @param a1 An integer corresponding to the second of 4 numbers in the gateway address.
00740   @param a2 An integer corresponding to the third of 4 numbers in the gateway address.
00741   @param a3 An integer corresponding to the fourth of 4 numbers in the gateway address.
00742   @return 0 on success.
00743 
00744   \par Example
00745   \code
00746   // set the gateway to 192.168.5.1
00747   if( 0 != Network_SetGateway( 192, 168, 5, 1 ) )
00748     // then there was a problem.
00749   \endcode
00750 */
00751 int Network_SetGateway( int a0, int a1, int a2, int a3 )
00752 {
00753   // just store this address, since we're only going to do something with it in response to
00754   if( !Network_GetValid() )
00755   {
00756     Network_SetDefaults( );
00757     Network_SetValid( 1 );
00758   }
00759   Network->TempGateway = NETIF_IP_ADDRESS( a0, a1, a2, a3 );
00760   Network_SetValid( 1 );
00761   
00762   return CONTROLLER_OK;
00763 }
00764 
00765 /**
00766   Read the board's current IP address.
00767   Pass in pointers to integers where the address should be stored.
00768 
00769   @param a0 A pointer to an integer where the first of 4 numbers of the address is to be stored.
00770   @param a1 A pointer to an integer where the second of 4 numbers of the address is to be stored.
00771   @param a2 A pointer to an integer where the third of 4 numbers of the address is to be stored.
00772   @param a3 A pointer to an integer where the fourth of 4 numbers of the address is to be stored.
00773   @return 0 on success.
00774   
00775   \par Example
00776   \code
00777   int a0, a1, a2, a3;
00778   Network_GetAddress( &a0, &a1, &a2, &a3 );
00779   // now our variables are filled with the current address values
00780   \endcode
00781 */
00782 int Network_GetAddress( int* a0, int* a1, int* a2, int* a3 )
00783 {
00784   if( Network_GetPending() )
00785     return CONTROLLER_ERROR_NO_NETWORK;
00786 
00787   struct netif* mc_netif;
00788   int address = 0;
00789   // we specify our network interface as en0 when we init
00790   mc_netif = netif_find( "en0" );
00791   if( mc_netif != NULL )
00792   {
00793     address = mc_netif->ip_addr.addr;
00794 
00795     *a0 = NETIF_IP_ADDRESS_A( address );
00796     *a1 = NETIF_IP_ADDRESS_B( address );
00797     *a2 = NETIF_IP_ADDRESS_C( address );
00798     *a3 = NETIF_IP_ADDRESS_D( address );
00799   }
00800   // if the Ethernet interface is not up, we'll just get garbage back
00801   if( *a0 < 0 || *a0 > 255 )
00802     *a0 = *a1 = *a2 = *a3 = -1;
00803 
00804   return CONTROLLER_OK;
00805 }
00806 
00807 /**
00808   Read the board's current network mask.
00809   Pass in pointers to integers where the mask should be stored.
00810 
00811   @param a0 A pointer to an integer where the first of 4 numbers of the mask is to be stored.
00812   @param a1 A pointer to an integer where the second of 4 numbers of the mask is to be stored.
00813   @param a2 A pointer to an integer where the third of 4 numbers of the mask is to be stored.
00814   @param a3 A pointer to an integer where the fourth of 4 numbers of the mask is to be stored.
00815   @return 0 on success.
00816   
00817   \par Example
00818   \code
00819   int a0, a1, a2, a3;
00820   Network_GetMask( &a0, &a1, &a2, &a3 );
00821   // now our variables are filled with the current mask values
00822   \endcode
00823 */
00824 int Network_GetMask( int* a0, int* a1, int* a2, int* a3 )
00825 {
00826   if( Network_GetPending() )
00827     return CONTROLLER_ERROR_NO_NETWORK;
00828   
00829   struct netif* mc_netif;
00830   int address = 0;
00831   // we specify our network interface as en0 when we init
00832   mc_netif = netif_find( "en0" );
00833   if( mc_netif != NULL )
00834   {
00835     address = mc_netif->netmask.addr;
00836 
00837     *a0 = NETIF_IP_ADDRESS_A( address );
00838     *a1 = NETIF_IP_ADDRESS_B( address );
00839     *a2 = NETIF_IP_ADDRESS_C( address );
00840     *a3 = NETIF_IP_ADDRESS_D( address );
00841   }
00842   if( *a0 < 0 || *a0 > 255 )
00843     *a0 = *a1 = *a2 = *a3 = -1;
00844     
00845   return CONTROLLER_OK;
00846 }
00847 
00848 /**
00849   Read the board's current gateway address.
00850   Pass in pointers to integers where the gateway address should be stored.
00851 
00852   @param a0 A pointer to an integer where the first of 4 numbers of the gateway address is to be stored.
00853   @param a1 A pointer to an integer where the second of 4 numbers of the gateway address is to be stored.
00854   @param a2 A pointer to an integer where the third of 4 numbers of the gateway address is to be stored.
00855   @param a3 A pointer to an integer where the fourth of 4 numbers of the gateway address is to be stored.
00856   @return 0 on success.
00857   
00858   \par Example
00859   \code
00860   int a0, a1, a2, a3;
00861   Network_GetGateway( &a0, &a1, &a2, &a3 );
00862   // now our variables are filled with the current gateway values
00863   \endcode
00864 */
00865 int Network_GetGateway( int* a0, int* a1, int* a2, int* a3 )
00866 {
00867   if( Network_GetPending() )
00868     return CONTROLLER_ERROR_NO_NETWORK;
00869   
00870   struct netif* mc_netif;
00871   int address = 0;
00872   // we specify our network interface as en0 when we init
00873   mc_netif = netif_find( "en0" );
00874   if( mc_netif != NULL )
00875   {
00876     address = mc_netif->gw.addr;
00877 
00878     *a0 = NETIF_IP_ADDRESS_A( address );
00879     *a1 = NETIF_IP_ADDRESS_B( address );
00880     *a2 = NETIF_IP_ADDRESS_C( address );
00881     *a3 = NETIF_IP_ADDRESS_D( address );
00882   }
00883   if( *a0 < 0 || *a0 > 255 )
00884     *a0 = *a1 = *a2 = *a3 = -1;
00885   
00886   return CONTROLLER_OK;
00887 }
00888 
00889 /**
00890   Set whether DHCP is enabled.
00891   The Make Controller can use DHCP (Dynamic Host Configuration Protocol) to automatically
00892   retrieve an IP address from a router.  If you're using your Make Controller on a network
00893   with a router, it is generally preferred (and more convenient) to use DHCP.  Otherwise, turn
00894   DHCP off and set the IP address, mask, and gateway manually.
00895   
00896   Wikipedia has a good article about DHCP at http://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol
00897   
00898   This value is stored persistently, so it will remain constant across system reboots.
00899   @param enabled An integer specifying whether to enable DHCP - 1 (enable) or 0 (disable).
00900 */
00901 void Network_SetDhcpEnabled( int enabled )
00902 {
00903   if( enabled && !Network_GetDhcpEnabled() )
00904   {
00905     struct netif* mc_netif;
00906     // we specify our network interface as en0 when we init
00907     mc_netif = netif_find( "en0" );
00908     if( mc_netif != NULL )
00909       Network_DhcpStart( mc_netif );
00910       
00911     Eeprom_Write( EEPROM_DHCP_ENABLED, (uchar*)&enabled, 4 );
00912   }
00913   
00914   if( !enabled && Network_GetDhcpEnabled() )
00915   {
00916     struct netif* mc_netif;
00917     // we specify our network interface as en0 when we init
00918     mc_netif = netif_find( "en0" );
00919     if( mc_netif != NULL )
00920       Network_DhcpStop( mc_netif );
00921     Eeprom_Write( EEPROM_DHCP_ENABLED, (uchar*)&enabled, 4 );
00922     Network_SetValid( 1 );
00923   }
00924   return;
00925 }
00926 
00927 /**
00928   Read whether DHCP is currently enabled.
00929   This value is stored presistently, so it will be the same across system reboots.
00930   @return An integer specifying whether DHCP is enabled - 1 (enabled) or 0 (disabled).
00931 */
00932 int Network_GetDhcpEnabled( )
00933 {
00934   int state;
00935   Eeprom_Read( EEPROM_DHCP_ENABLED, (uchar*)&state, 4 );
00936   return (state == 1) ? 1 : 0;
00937 }
00938 
00939 /**
00940   Resolve the IP address for a given host name.
00941   Up to 4 DNS entries are cached, so if you make successive calls to this function, 
00942   you won't incur a whole lookup roundtrip - you'll just get the cached value.
00943   The cached values are maintained internally, so if one of them becomes invalid, a
00944   new lookup will be fired off the next time it's asked for.
00945   @param name A string specifying the name of the host to look up.
00946   @return An integer representation of the IP address of the host.  This can be 
00947   passed to the \ref Sockets functions to read and write.  Returns -1 on error.
00948 
00949   \b Example
00950   \code
00951   // try to open a socket connection to makingthings.com
00952   int addr = Network_DnsGetHostByName("makingthings.com");
00953   struct netconn* socket = Socket(addr, 80); // open up a new connection to that address
00954   \endcode
00955 */
00956 int Network_DnsGetHostByName( const char *name )
00957 {
00958   struct ip_addr addr;
00959   int retval = -1;
00960   if(!Network_DnsSemaphore)
00961   {
00962     Network_DnsSemaphore = SemaphoreCreate();
00963     if(!Network_DnsSemaphore) // the semaphore was not created successfully
00964       return retval;
00965     if(!SemaphoreTake(Network_DnsSemaphore, 0)) // do the initial take
00966       return retval;
00967   }
00968   err_t result = dns_gethostbyname( name, &addr, Network_DnsCallback, 0);
00969   if(result == ERR_OK) // the result was cached, just return it
00970     retval = addr.addr;
00971   else if(result == ERR_INPROGRESS) // a lookup is in progress - wait for the callback to signal that we've gotten a response
00972   {
00973     if(SemaphoreTake(Network_DnsSemaphore, 30000)) // timeout is 30 seconds by default
00974       retval = Network->DnsResolvedAddress;
00975   }
00976   return ntohl(retval);
00977 }
00978 
00979 // static
00980 /*
00981   The callback for a DNS look up.  The original request is waiting (via semaphore) on
00982   this to pop the looked up address in the right spot.
00983 */
00984 void Network_DnsCallback(const char *name, struct ip_addr *addr, void *arg)
00985 {
00986   LWIP_UNUSED_ARG(arg);
00987   LWIP_UNUSED_ARG(name);
00988   if(addr)
00989     Network->DnsResolvedAddress = addr->addr;
00990   else
00991     Network->DnsResolvedAddress = -1; // we didn't get an address, stuff an error value in there
00992   SemaphoreGive(Network_DnsSemaphore);
00993 }
00994 
00995 /** @}
00996 */
00997 
00998 /**
00999   Create a checksum for the current address settings and store it in EEPROM.
01000   This should be called each time an address setting is changed so that if
01001   the board gets powered down, it will know when it comes back up whether or
01002   not the address settings is currently has are valid.
01003 
01004   @param v An integer specifying whether to validate the current settings (1)
01005   or to force them to be invalidated (0).
01006   Passing in 0 returns the address settings to their factory defaults.
01007   @return 0 on success.
01008 */
01009 int Network_SetValid( int v )
01010 {
01011   if ( v )
01012   {
01013     struct ip_addr ip, gw, mask;
01014     struct netif* mc_netif;
01015 
01016     ip.addr = Network->TempIpAddress; // these should each have been set previously
01017     mask.addr = Network->TempMask;  // by Network_SetAddress(), etc.
01018     gw.addr = Network->TempGateway;
01019     if( !Network_GetDhcpEnabled() ) // only actually change the address if we're not using DHCP
01020     {
01021       // we specify our network interface as en0 when we init
01022       mc_netif = netif_find( "en0" );
01023       if( mc_netif != NULL )
01024         netif_set_addr( mc_netif, &ip, &mask, &gw );
01025     }
01026     
01027     // but write the addresses to memory regardless, so we can use them next time we boot up without DHCP
01028     Eeprom_Write( EEPROM_SYSTEM_NET_ADDRESS, (uchar*)&ip.addr, 4 );
01029     Eeprom_Write( EEPROM_SYSTEM_NET_MASK, (uchar*)&mask.addr, 4 );
01030     Eeprom_Write( EEPROM_SYSTEM_NET_GATEWAY, (uchar*)&gw.addr, 4 );
01031 
01032     int total = Network->TempIpAddress + Network->TempMask + Network->TempGateway;
01033     Eeprom_Write( EEPROM_SYSTEM_NET_CHECK, (uchar*)&total, 4 );
01034 
01035     Network_Valid = NET_VALID;
01036   }
01037   else
01038   {
01039     int value = 0;
01040     Eeprom_Write( EEPROM_SYSTEM_NET_CHECK, (uchar*)&value, 4 );
01041     Network_Valid = NET_INVALID;
01042   }
01043 
01044   return CONTROLLER_OK;
01045 }
01046 
01047 /**
01048   Read the checksum for address settings in EEPROM, and determine if it matches 
01049   the current settings.
01050 
01051   @return An integer specifying the validity of the settings - 1 (valid) or 0 (invalid).
01052 */
01053 int Network_GetValid( )
01054 {
01055   int address, mask, gateway, total;
01056   Eeprom_Read( EEPROM_SYSTEM_NET_ADDRESS, (uchar*)&address, 4 );
01057   Eeprom_Read( EEPROM_SYSTEM_NET_MASK, (uchar*)&mask, 4 );
01058   Eeprom_Read( EEPROM_SYSTEM_NET_GATEWAY, (uchar*)&gateway, 4 );
01059   Eeprom_Read( EEPROM_SYSTEM_NET_CHECK, (uchar*)&total, 4 );
01060 
01061   if ( total == address + mask + gateway )
01062   {
01063     Network_Valid = NET_VALID;
01064     return 1;
01065   }
01066   else
01067   {
01068     Network_Valid = NET_INVALID;
01069     return 0;
01070   }
01071 }
01072 
01073 // if things aren't valid, just set the defaults
01074 void Network_SetDefaults( )
01075 {
01076   Network->TempIpAddress = NETIF_IP_ADDRESS( 192, 168, 0, 200 );
01077   Network->TempGateway = NETIF_IP_ADDRESS( 192, 168, 0, 1 );
01078   Network->TempMask = NETIF_IP_ADDRESS( 255, 255, 255, 0 );
01079   Network_SetValid( 1 );
01080 }
01081 
01082 /**
01083   Sets whether the Network subsystem is currently trying to negotiate its settings.
01084   This is mostly used by the Network init and deinit processes, so you shouldn't
01085   be calling this yourself unless you have a good reason to.
01086   @param state An integer specifying the pending state - 1 (pending) or 0 (not pending).
01087 */
01088 void Network_SetPending( int state )
01089 {
01090   if( state && !Network->pending )
01091       Network->pending = state;
01092   if( !state && Network->pending )
01093     Network->pending = state;
01094 }
01095 
01096 int Network_GetPending( )
01097 {
01098   return Network->pending;
01099 }
01100 
01101 void NetworkOsc_SetTcpOutAddress( int a0, int a1, int a2, int a3 )
01102 {
01103   int address = IP_ADDRESS( a0, a1, a2, a3 );
01104   if( address != Network->TcpOutAddress )
01105   {
01106     Network->TcpOutAddress = address;
01107     Eeprom_Write( EEPROM_TCP_OUT_ADDRESS, (uchar*)&address, 4 );
01108   }
01109 }
01110 
01111 int NetworkOsc_GetTcpOutAddress( )
01112 {
01113   return Network->TcpOutAddress;
01114 }
01115 
01116 void NetworkOsc_SetTcpOutPort( int port )
01117 {
01118   if( port != Network->TcpOutPort ) // only change if it's a new value
01119   {
01120     Network->TcpOutPort = port;
01121     Eeprom_Write( EEPROM_TCP_OUT_PORT, (uchar*)&port, 4 );
01122   }
01123 }
01124 
01125 int NetworkOsc_GetTcpOutPort( )
01126 {
01127   return Network->TcpOutPort;
01128 }
01129 
01130 void NetworkOsc_SetUdpListenPort( int port )
01131 {
01132   if( port != Network->OscUdpListenPort ) // only change things if it's a new value
01133   {
01134     Network->OscUdpListenPort = port;
01135     Eeprom_Write( EEPROM_OSC_UDP_LISTEN_PORT, (uchar*)&port, 4 );
01136   }
01137 }
01138 
01139 int NetworkOsc_GetUdpListenPort(  )
01140 {
01141   int port;
01142   Eeprom_Read( EEPROM_OSC_UDP_LISTEN_PORT, (uchar*)&port, 4 );
01143   
01144   if( port > 0 && port < 65536 )
01145     return port;
01146   else
01147     return 10000;
01148 }
01149 
01150 void NetworkOsc_SetUdpSendPort( int port )
01151 {
01152   if( port != Network->OscUdpSendPort ) // only change things if it's a new value
01153   {
01154     Network->OscUdpSendPort = port;
01155     Eeprom_Write( EEPROM_OSC_UDP_SEND_PORT, (uchar*)&port, 4 );
01156   }
01157 }
01158 
01159 int NetworkOsc_GetUdpSendPort(  )
01160 {
01161   int port;
01162   Eeprom_Read( EEPROM_OSC_UDP_SEND_PORT, (uchar*)&port, 4 );
01163   
01164   if( port > 0 && port < 65536 )
01165     return port;
01166   else
01167     return 10000;
01168 }
01169 
01170 void Network_DhcpStart( struct netif* netif )
01171 {
01172   Network_SetPending( 1 ); // set a flag so nobody else tries to set up this netif
01173   int count = 0;
01174   dhcp_start( netif );
01175   // now hang out for a second until we get an address
01176   // if DHCP is enabled but we don't find a DHCP server, just use the network config stored in EEPROM
01177   while( netif->ip_addr.addr == 0 && count < 100 ) // timeout after 10 (?) seconds of waiting for a DHCP address
01178   {
01179     count++;
01180     Sleep( 100 );
01181   }
01182   if( netif->ip_addr.addr == 0 ) // if we timed out getting an address via DHCP, just use whatever's in EEPROM
01183   {
01184     struct ip_addr ip, gw, mask; // network config stored in EEPROM
01185     ip.addr = Network->TempIpAddress;
01186     mask.addr = Network->TempMask;
01187     gw.addr = Network->TempGateway;
01188     netif_set_addr( netif, &ip, &mask, &gw );
01189   }
01190   Network_SetPending( 0 );
01191   return;
01192 }
01193 
01194 void Network_DhcpStop( struct netif* netif )
01195 {
01196   dhcp_release( netif );
01197   netif_set_up(netif); // bring the interface back up, as dhcp_release() takes it down
01198   return;
01199 }
01200 
01201 int Network_AddressConvert( char* address, int* a0, int* a1, int* a2, int* a3 )
01202 {
01203   return ( sscanf( address, "%d.%d.%d.%d", a0, a1, a2, a3 ) == 4 ) ? CONTROLLER_OK : CONTROLLER_ERROR_NO_ADDRESS;
01204 }
01205 
01206 #if ( CONTROLLER_VERSION == 50 || CONTROLLER_VERSION == 95 || CONTROLLER_VERSION == 100 || CONTROLLER_VERSION == 200 )
01207 #define NETWORK_BITS IO_PB00_BIT | IO_PB01_BIT | IO_PB02_BIT | IO_PB03_BIT | IO_PB04_BIT | \
01208                      IO_PB05_BIT | IO_PB06_BIT | IO_PB07_BIT | IO_PB08_BIT | IO_PB09_BIT | \
01209                      IO_PB10_BIT | IO_PB11_BIT | IO_PB12_BIT | IO_PB13_BIT | IO_PB14_BIT | \
01210                      IO_PB15_BIT | IO_PB16_BIT | IO_PB17_BIT | IO_PB18_BIT | IO_PB26_BIT
01211 #elif ( CONTROLLER_VERSION == 90 )
01212 #define NETWORK_BITS IO_PB00_BIT | IO_PB01_BIT | IO_PB02_BIT | IO_PB03_BIT | IO_PB04_BIT | \
01213                      IO_PB05_BIT | IO_PB06_BIT | IO_PB07_BIT | IO_PB08_BIT | IO_PB09_BIT | \
01214                      IO_PB15_BIT | IO_PB26_BIT
01215 #endif
01216 
01217 int Network_Init( )
01218 {
01219   // Start and Lock all the bits to do with the Ethernet Phy - can do this immediately, since there's no undoing this
01220   Network_SetPending( 1 );
01221   Io_StartBits( NETWORK_BITS, true );
01222 
01223   // Attempt to get a serial number and set it into the mac address low bytes to make a unique MAC address
01224   int serialNumber = System_GetSerialNumber();
01225   emacETHADDR5 = serialNumber & 0xFF;
01226   emacETHADDR4 = ( serialNumber >> 8 ) & 0xFF;
01227   // Low nibble of the third byte - gives us around 1M serial numbers
01228   emacETHADDR3 = 0x50 | ( ( serialNumber >> 12 ) & 0xF );
01229 
01230   /* Initialize lwIP and its interface layer. */
01231   tcpip_init( NULL, NULL ); // init all of lwip...see lwip_init() inside for the whole init story
01232 
01233   extern err_t ethernetif_init( struct netif *netif );
01234   static struct netif EMAC_if;
01235   int address, mask, gateway, dhcp;
01236   dhcp = Network_GetDhcpEnabled();
01237 
01238   if( dhcp )
01239   {
01240     address = 0;
01241     mask = 0;
01242     gateway = 0;
01243   }
01244   else // DHCP not enabled, just read whatever the manual IP address in EEPROM is.
01245   {
01246     address = Network->TempIpAddress;
01247     mask = Network->TempMask;
01248     gateway = Network->TempGateway;
01249   }
01250   // add our network interface to the system
01251   Network_SetPending( 1 ); //netif_add goes away for a long time if there's no Ethernet cable connected.
01252   netif_add(&EMAC_if, (struct ip_addr*)&address, (struct ip_addr*)&mask, 
01253                         (struct ip_addr*)&gateway, NULL, ethernetif_init, tcpip_input);
01254   // make it the default interface
01255   netif_set_default(&EMAC_if);
01256   // bring it up
01257   netif_set_up(&EMAC_if);
01258   // name it so we can find it later
01259   EMAC_if.name[0] = 'e';
01260   EMAC_if.name[1] = 'n';
01261   EMAC_if.num = 0;
01262   
01263   #ifdef OSC
01264   if( NetworkOsc_GetTcpAutoConnect( ) )
01265   {
01266     Network->TcpRequested = 1;
01267     Osc_StartTcpTask( );
01268   }
01269   #endif
01270   
01271   if( dhcp )
01272     Network_DhcpStart( &EMAC_if );
01273 
01274   Network_SetPending( 0 );
01275   return CONTROLLER_OK;
01276 }
01277 
01278 /** \defgroup NetworkOSC Network - OSC
01279   Configure the Controller Board's Network Settings via OSC.
01280   \ingroup OSC
01281    
01282     \section devices Devices
01283     There is only one Network system, so a device index is not used.
01284    
01285     \section properties Properties
01286     The Network system has the following properties
01287     - address
01288     - mask
01289     - gateway
01290     - valid
01291     - mac
01292     - osc_udp_listen_port
01293     - osc_udp_send_port
01294     - dhcp
01295 
01296     \par Address
01297     The \b address property corresponds to the IP address of the Controller Board.
01298     This value can be both read and written.  To set a new address, send a message like
01299     \verbatim /network/address 192.168.0.235 \endverbatim
01300     \par
01301     To read the current IP address, omit the argument value from the end of the message:
01302     \verbatim /network/address \endverbatim
01303    
01304     \par Mask
01305     The \b mask property corresponds to the network mask of the Controller Board.
01306     When on a subnet or local network, the network mask must be set in order
01307     for the gateway to route information to the board's IP address properly.
01308     The mask is commonly 255.255.255.0 for many home networks.
01309     \par
01310     To set the board's network mask, send a message like
01311     \verbatim /network/mask 255.255.255.0 \endverbatim
01312     To read the current mask, omit the argument value from the end of the message:
01313     \verbatim /network/mask \endverbatim
01314    
01315     \par Gateway
01316     The \b gateway property corresponds to the gateway address for the local network the Make Controller is on.
01317     The gateway address is the address
01318     The gateway address is commonly the address of the router on many home networks, and its
01319     value is commonly 192.168.0.1.\n
01320     This value is stored in EEPROM, so it persists even after the board
01321     is powered down.
01322     \par
01323     To set the board's gateway address, send a message like
01324     \verbatim /network/gateway 192.168.0.1 \endverbatim
01325     To read the current gateway, omit the argument value from the end of the message:
01326     \verbatim /network/gateway \endverbatim
01327 
01328     \par Valid
01329     The \b valid property is used to make sure the board's network settings are valid.
01330     If you're manually setting the \b address, \b gateway, or \b mask settings, you'll need
01331     to send the valid message for them to take effect.
01332     \par
01333     To set the board's current network settings as valid, send the message
01334     \verbatim /network/valid 1 \endverbatim
01335     To check if the current settings have been set as valid, send the message:
01336     \verbatim /network/valid \endverbatim
01337     with no argument value.
01338 
01339     \par OSC UDP Port
01340     The \b osc_udp_port property corresponds to the port that the Make Controller listens on for
01341     incoming OSC messages via UDP.  This value is stored persistently, so it's available
01342     even after the board has rebooted.  This is 10000 by default.
01343     \par
01344     To tell the board to listen on port 10001, instead of the default 10000, send the message
01345     \code /network/osc_udp_port 10001 \endcode
01346     To read back the port that the board is currently listening on, send the message
01347     \verbatim /network/osc_udp_port \endverbatim
01348     with no argument value.
01349 
01350     \par DHCP
01351     The \b dhcp property sets whether the board should try to dynamically retrieve a network address from 
01352     a network router.  If no DHCP server is available, the board will use the network settings stored in memory
01353     for the \b address, \b gateway, and \b mask properties. If you're connecting the board directly to your computer, 
01354     DHCP will not be available, so you should turn this off.
01355     \par
01356     To turn DHCP on, send the message
01357     \code /network/dhcp 1 \endcode
01358     and the board will immediately try to get an address.  To check what address the board got, send the message
01359     \code /network/address \endcode
01360     as you normally would.  To turn DHCP off, send the message
01361     \code /network/dhcp 0 \endcode
01362     To read whether DHCP is currently enabled on the board, send the message
01363     \code /network/dhcp \endcode
01364     with no argument value.
01365    
01366     \par MAC
01367     The \b mac property corresponds to the Ethernet MAC address of the Controller Board.
01368     This value is read-only.  Each board on a network must have a unique MAC address.  The MAC address is generated
01369     using the board's serial number, so ensure that your board's serial numbers are unique.
01370     \par
01371     To read the MAC address of the Controller, send the message
01372     \verbatim /network/mac \endverbatim
01373     The board will respond by sending back an OSC message with the MAC address.
01374 */
01375 #ifdef OSC
01376 
01377 void NetworkOsc_SetTcpAutoConnect( int yesorno )
01378 {
01379   int val = yesorno;
01380   if( val != 1 )
01381     val = 0;
01382   if( yesorno != NetworkOsc_GetTcpAutoConnect( ) ) // only write it if it has changed
01383     Eeprom_Write( EEPROM_TCP_AUTOCONNECT, (uchar*)&yesorno, 4 );
01384   if( Network->TcpRequested == 0 && yesorno ) // if we're not already connected, connect now
01385   {
01386     Network->TcpRequested = 1;
01387     Osc_StartTcpTask( );
01388   }
01389 }
01390 
01391 int NetworkOsc_GetTcpAutoConnect( )
01392 {
01393   int state;
01394   Eeprom_Read( EEPROM_TCP_AUTOCONNECT, (uchar*)&state, 4 );
01395   if( state != 1 )
01396     return 0;
01397   else
01398     return state;
01399 }
01400 
01401 int NetworkOsc_GetTcpRequested( )
01402 {
01403   return Network->TcpRequested;
01404 }
01405 
01406 
01407 #include "osc.h"
01408 static char* NetworkOsc_Name = "network";
01409 static char* NetworkOsc_PropertyNames[] = { "active", "address", "mask", "gateway", "valid", "mac", 
01410                                               "osc_udp_listen_port", "osc_tcpout_address", "osc_tcpout_port", 
01411                                               "osc_tcpout_connect", "osc_tcpout_auto", "dhcp", 
01412                                               "find", "osc_udp_send_port", 0 }; // must have a trailing 0
01413 
01414 int NetworkOsc_PropertySet( int property, char* typedata, int channel );
01415 int NetworkOsc_PropertyGet( int property, int channel );
01416 
01417 const char* NetworkOsc_GetName( void )
01418 {
01419   return NetworkOsc_Name;
01420 }
01421 
01422 int NetworkOsc_ReceiveMessage( int channel, char* message, int length )
01423 {
01424   if ( Network_GetPending() )
01425     return CONTROLLER_ERROR_NO_NETWORK;
01426   
01427   int status = Osc_GeneralReceiverHelper( channel, message, length, 
01428                                 NetworkOsc_Name,
01429                                 NetworkOsc_PropertySet, NetworkOsc_PropertyGet, 
01430                                 NetworkOsc_PropertyNames );
01431 
01432   if ( status != CONTROLLER_OK )
01433     return Osc_SendError( channel, NetworkOsc_Name, status );
01434 
01435   return CONTROLLER_OK;
01436 }
01437 
01438 int NetworkOsc_Poll( )
01439 {
01440   return CONTROLLER_OK;
01441 }
01442 
01443 // Sets the property with the value
01444 int NetworkOsc_PropertySet( int property, char* typedata, int channel )
01445 {
01446   int a0;
01447   int a1; 
01448   int a2;
01449   int a3;
01450 
01451   switch ( property )
01452   {
01453     case 0: // active
01454     {
01455       int value;
01456       int count = Osc_ExtractData( typedata, "i", &value );
01457       if ( count != 1 )
01458         return Osc_SubsystemError( channel, NetworkOsc_Name, "Incorrect data - need an int" );
01459 
01460       Network_SetActive( value );
01461       break;
01462     }
01463     case 1: // address
01464     {
01465       char* address;
01466       int count = Osc_ExtractData( typedata, "s", &address );
01467       if ( count != 1 ) 
01468         return Osc_SubsystemError( channel, NetworkOsc_Name, "Incorrect data - need a string" );
01469       int status = Network_AddressConvert( address, &a0, &a1, &a2, &a3 );
01470       if ( status != CONTROLLER_OK )
01471         return Osc_SubsystemError( channel, NetworkOsc_Name, "Incorrect address - need 'a.b.c.d'" );
01472 
01473       Network_SetAddress( a0, a1, a2, a3 );
01474 
01475       break;
01476     }
01477     case 2: // mask
01478     {
01479       char* address;
01480       int count = Osc_ExtractData( typedata, "s", &address );
01481       if ( count != 1 ) 
01482         return Osc_SubsystemError( channel, NetworkOsc_Name, "Incorrect data - need a string" );
01483       int status = Network_AddressConvert( address, &a0, &a1, &a2, &a3 );
01484       if ( status != CONTROLLER_OK )
01485         return Osc_SubsystemError( channel, NetworkOsc_Name, "Incorrect mask - need 'a.b.c.d'" );
01486 
01487       Network_SetMask( a0, a1, a2, a3 );
01488 
01489       break;
01490     }
01491     case 3: // gateway 
01492     {
01493       char* address;
01494       int count = Osc_ExtractData( typedata, "s", &address );
01495       if ( count != 1 ) 
01496         return Osc_SubsystemError( channel, NetworkOsc_Name, "Incorrect data - need a string" );
01497       int status = Network_AddressConvert( address, &a0, &a1, &a2, &a3 );
01498       if ( status != CONTROLLER_OK )
01499         return Osc_SubsystemError( channel, NetworkOsc_Name, "Incorrect gateway - need 'a.b.c.d'" );
01500 
01501       Network_SetGateway( a0, a1, a2, a3 );
01502 
01503       break;
01504     }
01505     case 4: // valid
01506     {
01507       int value;
01508       int count = Osc_ExtractData( typedata, "i", &value );
01509       if ( count != 1 )
01510         return Osc_SubsystemError( channel, NetworkOsc_Name, "Incorrect data - need an int" );
01511 
01512       Network_SetValid( value ); 
01513       break;
01514     }
01515     case 5: // mac
01516     {
01517       return Osc_SubsystemError( channel, NetworkOsc_Name, "MAC is read only." );
01518     }
01519     case 6: // osc_udp_listen_port
01520     {
01521       int value;
01522       int count = Osc_ExtractData( typedata, "i", &value );
01523       if ( count != 1 )
01524         return Osc_SubsystemError( channel, NetworkOsc_Name, "Incorrect data - need an int" );
01525 
01526       NetworkOsc_SetUdpListenPort( value );
01527       break;
01528     }
01529     case 7: // osc_tcpout_address
01530     {
01531       char* address;
01532       int count = Osc_ExtractData( typedata, "s", &address );
01533       if ( count != 1 ) 
01534         return Osc_SubsystemError( channel, NetworkOsc_Name, "Incorrect data - need a string" );
01535       // don't strictly need to do this, but it's god to make sure it's a proper address
01536       int status = Network_AddressConvert( address, &a0, &a1, &a2, &a3 );
01537       if ( status != CONTROLLER_OK )
01538         return Osc_SubsystemError( channel, NetworkOsc_Name, "Incorrect TCP address - need 'xxx.xxx.xxx.xxx'" );
01539       
01540       NetworkOsc_SetTcpOutAddress( a0, a1, a2, a3 );
01541       break;
01542     }
01543     case 8: // osc_tcpout_port
01544     {
01545       int value;
01546       int count = Osc_ExtractData( typedata, "i", &value );
01547       if ( count != 1 )
01548         return Osc_SubsystemError( channel, NetworkOsc_Name, "Incorrect data - need an int" );
01549 
01550       NetworkOsc_SetTcpOutPort( value );
01551       break;
01552     }
01553     case 9: // osc_tcpout_connect
01554     {
01555       int value;
01556       int count = Osc_ExtractData( typedata, "i", &value );
01557       if ( count != 1 )
01558         return Osc_SubsystemError( channel, NetworkOsc_Name, "Incorrect data - need an int" );
01559 
01560       if( value && Network->TcpRequested == 0 )
01561       {
01562         Network->TcpRequested = 1;
01563         Osc_StartTcpTask( );
01564       }
01565       if( !value && Network->TcpRequested == 1 )  
01566         Network->TcpRequested = 0;
01567 
01568       break;
01569     }
01570     case 10: // osc_tcpout_auto
01571     {
01572       int value;
01573       int count = Osc_ExtractData( typedata, "i", &value );
01574       if ( count != 1 )
01575         return Osc_SubsystemError( channel, NetworkOsc_Name, "Incorrect data - need an int" );
01576 
01577       NetworkOsc_SetTcpAutoConnect( value );
01578       break;
01579     }
01580     case 11: // dhcp
01581     {
01582       int value;
01583       int count = Osc_ExtractData( typedata, "i", &value );
01584       if ( count != 1 )
01585         return Osc_SubsystemError( channel, NetworkOsc_Name, "Incorrect data - need an int" );
01586       
01587       Network_SetDhcpEnabled( value );
01588       break;
01589     }
01590     case 13: // osc_udp_send_port
01591     {
01592       int value;
01593       int count = Osc_ExtractData( typedata, "i", &value );
01594       if ( count != 1 )
01595         return Osc_SubsystemError( channel, NetworkOsc_Name, "Incorrect data - need an int" );
01596 
01597       NetworkOsc_SetUdpSendPort( value );
01598       break;
01599     }
01600   }
01601   return CONTROLLER_OK;
01602 }
01603 
01604 // Get the property
01605 int NetworkOsc_PropertyGet( int property, int channel )
01606 {
01607   int value;
01608   int result = CONTROLLER_OK;
01609   int a0;
01610   int a1; 
01611   int a2;
01612   int a3;
01613 
01614   switch ( property )
01615   {
01616     case 0:
01617       value = Network_GetActive( );
01618       snprintf( Network->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", NetworkOsc_Name, NetworkOsc_PropertyNames[ property ] ); 
01619       Osc_CreateMessage( channel, Network->scratch1, ",i", value );      
01620       break;
01621     case 1:
01622       if ( Network_GetAddress( &a0, &a1, &a2, &a3 ) == CONTROLLER_ERROR_NO_NETWORK )
01623         return Osc_SubsystemError( channel, NetworkOsc_Name, "No network address available - try plugging in an Ethernet cable." );
01624       snprintf( Network->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", NetworkOsc_Name, NetworkOsc_PropertyNames[ property ] ); 
01625       snprintf( Network->scratch2, OSC_SCRATCH_SIZE, "%d.%d.%d.%d", a0, a1, a2, a3 );
01626       Osc_CreateMessage( channel, Network->scratch1, ",s", Network->scratch2 );      
01627       break;
01628     case 2:
01629       if ( Network_GetMask( &a0, &a1, &a2, &a3 ) == CONTROLLER_ERROR_NO_NETWORK )
01630         return Osc_SubsystemError( channel, NetworkOsc_Name, "No mask available - try plugging in an Ethernet cable." );
01631       snprintf( Network->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", NetworkOsc_Name, NetworkOsc_PropertyNames[ property ] ); 
01632       snprintf( Network->scratch2, OSC_SCRATCH_SIZE, "%d.%d.%d.%d", a0, a1, a2, a3 );
01633       Osc_CreateMessage( channel, Network->scratch1, ",s", Network->scratch2 );      
01634       break;
01635     case 3:
01636       if ( Network_GetGateway( &a0, &a1, &a2, &a3 ) == CONTROLLER_ERROR_NO_NETWORK )
01637         return Osc_SubsystemError( channel, NetworkOsc_Name, "No gateway available - try plugging in an Ethernet cable." );
01638       snprintf( Network->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", NetworkOsc_Name, NetworkOsc_PropertyNames[ property ] ); 
01639       snprintf( Network->scratch2, OSC_SCRATCH_SIZE, "%d.%d.%d.%d", a0, a1, a2, a3 );
01640       Osc_CreateMessage( channel, Network->scratch1, ",s", Network->scratch2 );      
01641       break;
01642     case 4:
01643       value = Network_GetValid( );
01644       snprintf( Network->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", NetworkOsc_Name, NetworkOsc_PropertyNames[ property ] ); 
01645       Osc_CreateMessage( channel, Network->scratch1, ",i", value );      
01646       break;
01647     case 5:
01648       snprintf( Network->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", NetworkOsc_Name, NetworkOsc_PropertyNames[ property ] ); 
01649       snprintf( Network->scratch2, OSC_SCRATCH_SIZE, "%02X:%02X:%02X:%02X:%02X:%02X", 
01650                 emacETHADDR0, emacETHADDR1, emacETHADDR2, emacETHADDR3, emacETHADDR4, emacETHADDR5 );
01651       Osc_CreateMessage( channel, Network->scratch1, ",s", Network->scratch2 );      
01652       break;
01653     case 6: // osc_udp_listen_port
01654       value = NetworkOsc_GetUdpListenPort( );
01655       snprintf( Network->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", NetworkOsc_Name, NetworkOsc_PropertyNames[ property ] ); 
01656       Osc_CreateMessage( channel, Network->scratch1, ",i", value );      
01657       break;
01658     case 7: // osc_tcpout_address
01659       value = NetworkOsc_GetTcpOutAddress( );
01660       a0 = IP_ADDRESS_A( value );
01661       a1 = IP_ADDRESS_B( value );
01662       a2 = IP_ADDRESS_C( value );
01663       a3 = IP_ADDRESS_D( value );
01664       Network_AddressConvert( Network->scratch1, &a0, &a1, &a2, &a3 );
01665       snprintf( Network->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", NetworkOsc_Name, NetworkOsc_PropertyNames[ property ] ); 
01666       snprintf( Network->scratch2, OSC_SCRATCH_SIZE, "%d.%d.%d.%d", a0, a1, a2, a3 );
01667       Osc_CreateMessage( channel, Network->scratch1, ",s", Network->scratch2 );    
01668       break;
01669     case 8: // osc_tcpout_port
01670       value = NetworkOsc_GetTcpOutPort( );
01671       snprintf( Network->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", NetworkOsc_Name, NetworkOsc_PropertyNames[ property ] ); 
01672       Osc_CreateMessage( channel, Network->scratch1, ",i", value );
01673       break;
01674     case 9: // osc_tcpout_connect
01675       value = NetworkOsc_GetTcpRequested( );
01676       snprintf( Network->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", NetworkOsc_Name, NetworkOsc_PropertyNames[ property ] ); 
01677       Osc_CreateMessage( channel, Network->scratch1, ",i", value );
01678       break;
01679     case 10: // osc_tcpout_auto
01680       value = NetworkOsc_GetTcpAutoConnect( );
01681       snprintf( Network->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", NetworkOsc_Name, NetworkOsc_PropertyNames[ property ] ); 
01682       Osc_CreateMessage( channel, Network->scratch1, ",i", value );
01683       break;
01684     case 11: // dhcp
01685       value = Network_GetDhcpEnabled( );
01686       snprintf( Network->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", NetworkOsc_Name, NetworkOsc_PropertyNames[ property ] ); 
01687       Osc_CreateMessage( channel, Network->scratch1, ",i", value );      
01688       break;
01689     case 12: // find
01690     {
01691       if ( Network_GetAddress( &a0, &a1, &a2, &a3 ) == CONTROLLER_ERROR_NO_NETWORK )
01692         return Osc_SubsystemError( channel, NetworkOsc_Name, "No network address available - try plugging in an Ethernet cable." );
01693       snprintf( Network->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", NetworkOsc_Name, NetworkOsc_PropertyNames[ property ] ); 
01694       snprintf( Network->scratch2, OSC_SCRATCH_SIZE, "%d.%d.%d.%d", a0, a1, a2, a3 );
01695       int listen = NetworkOsc_GetUdpListenPort( );
01696       int send = NetworkOsc_GetUdpSendPort( );
01697       char* sysName = System_GetName( );
01698       Osc_CreateMessage( channel, Network->scratch1, ",siis", Network->scratch2, listen, send, sysName );      
01699       break;
01700     }
01701     case 13: // osc_udp_send_port
01702       value = NetworkOsc_GetUdpSendPort( );
01703       snprintf( Network->scratch1, OSC_SCRATCH_SIZE, "/%s/%s", NetworkOsc_Name, NetworkOsc_PropertyNames[ property ] ); 
01704       Osc_CreateMessage( channel, Network->scratch1, ",i", value );         
01705       break;
01706   }
01707   
01708   return result;
01709 }
01710 
01711 #endif // OSC
01712 
01713 #endif // MAKE_CTRL_NETWORK
01714 
01715 

The Make Controller Kit is an open source project maintained by MakingThings.
MakingThings code is released under the Apache 2.0 license.
Bug tracker, development wiki and status can be found at http://dev.makingthings.com.
This document was last updated on 18 May 2009.