- 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.