MMEx with SPI Slave to allow legacy devices to communicate with modern media such as USB, SD cards, the internet and all of the mbed\'s other interfaces
Dependencies: NetServices MSCUsbHost mbed TMP102 SDFileSystem
nfuncs.cpp
- Committer:
- DeMein
- Date:
- 2011-02-27
- Revision:
- 0:67a55a82ce06
File content as of revision 0:67a55a82ce06:
/* MMEx for MBED - Network Command processing * Copyright (c) 2011 MK * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ /** \file nfuncs.cpp \brief Commands starting with N for Networking commands */ #include "nfuncs.h" EthernetNetIf *eth; HTTPClient http; HTTPResult result; HTTPServer *server; bool completed = false; /** * Global variable to indicate if network is running */ bool network_enabled = false; /** * Global variable to indicate if HTTP Server is running */ bool httpserver_enabled = false; /** * Poll the network (must be called periodically while server is active) */ void netpoll() { if (network_enabled) { _led3 = 1; Net::poll(); _led3 = 0; } } /** main entry for parsing C-commands * */ void parse_N() { // process parameters DBG_msg("parse_N", inbuf); err_num = noerror; wipesp(inbuf); // remove all spaces from string if (inbuf[1] != NULL) { switch (inbuf[1]) { case ninit : do_ninit(); break; case nstop : do_nstop(); break; case ntime : do_ntime(); break; case nget : do_nget(); break; case nhttp : do_nhttp(); break; default : do_ndefault(); // command not recognized break; } } else { do_ndefault(); } } /** initialize the network interface * * syntax: NI */ void do_ninit() { char * hostname; char * ipnums; char s[50]; char ips[4][25]; DBG_msg("do_ninit", "Network initialisation\n"); EthernetErr ethErr; // check for alternate hostname in parameters hostname = new char [param[par_H_].size() + 1]; // Host parameter strcpy (hostname, param[par_H_].c_str()); if (hostname == NULL) hostname = MMEx_Hostname; // check for DCHP or not // Parameter J is the fixed IP address in the following format: // ip netmask gateway dns // each ip address is in the format x.y.z.t, separated by spaces // When Param J is empty, DHCP will be used ipnums = new char [param[par_J_].size() + 1]; // Host parameter strcpy (ipnums, param[par_J_].c_str()); if (param[par_J_].size()< 10) { DBG_msg("do_ninit", "DHCP config"); // DHCP chosen, initialize network eth = new EthernetNetIf(hostname); // eth->setup(); } else { // process fixed IP adresses DBG_msg("do_ninit", "fixed IP"); DBG_msg("IP adresses", ipnums); IpAddr *ipparam[4]; sscanf(ipnums, "%s %s %s %s", ips[0], ips[1], ips[2], ips[3]); DBG_msg("IP number", ips[0]); DBG_msg("netmask ", ips[1]); DBG_msg("gateway ", ips[2]); DBG_msg("dns ", ips[3]); for ( int i = 0; i < 4; ++i ) { int ip1, ip2, ip3, ip4; sscanf(ips[i], "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4); ipparam[i] = new IpAddr(ip1, ip2, ip3, ip4); } // Setup IP with given adresses eth = new EthernetNetIf(*ipparam[0],*ipparam[1],*ipparam[2],*ipparam[3]); // eth->setup(); } int count = 0; do { DBG_int("do_ninit setup", ++count); ethErr = eth->setup(); if (ethErr) DBG_int("do_ninit timeout", ethErr); } while ((ethErr != ETH_OK) && (count < 5)); if (ethErr == ETH_OK) { // connection worked network_enabled = true; mldl.attach(&netpoll); DBG_msg("do_ninit", "Connected OK\n"); const char* hwAddr = eth->getHwAddr(); sprintf(s, "%02x:%02x:%02x:%02x:%02x:%02x", hwAddr[0], hwAddr[1], hwAddr[2], hwAddr[3], hwAddr[4], hwAddr[5]); DBG_msg("ninit MAC addr", s); param[par_M_].assign(s); // set MAC address IpAddr ethIp = eth->getIp(); sprintf(s, "%d.%d.%d.%d", ethIp[0], ethIp[1], ethIp[2], ethIp[3]); upstring(s); DBG_msg("ninit MAC addr", s); param[par_I_].assign(s); // set MAC address sprintf(s, "%s", eth->getHostname()); DBG_msg("ninit Hostname", s); param[par_H_].assign(s); // set Hostname } else { // in case initialization did not work network_enabled = false; DBG_msg("ninit", "network timout"); send_error(err_net_timeout); } } /** stop the network interface * * syntax: NS */ void do_nstop() { DBG_msg("do_nstop", inbuf); mldl.attach(NULL); delete eth; network_enabled = false; } /** get network time * * syntax: NT * URL of NTP server must be in parameter U */ void do_ntime() { char s[255]; // for intermediate results char s1[255]; // for intermediate results time_t ctTime; NTPClient ntp; DBG_msg("do_ntime", inbuf); ctTime = time(NULL); // current system time sprintf(s, "%d %s", ctTime, ctime(&ctTime)); DBG_msg("MMEx time", s); strcpy(s, param[par_U_].c_str()); // URL from parameter U Host server(IpAddr(), 123, s); NTPResult r = ntp.setTime(server); if (r == NTP_OK) { // time set ctTime = time(NULL); sprintf(s1, "%d %s", ctTime, ctime(&ctTime)); DBG_msg("MMEx time", s1); } else { // error in setting the time send_error(err_net_NTP); } } void request_callback(HTTPResult r) { result = r; completed = true; } /** get file through HTTP Stream * * syntax: NG * URL of must be in parameter U, %n may be used for filename */ void do_nget() { HTTPStream stream; char Buf[512 + 1] = {0}; char s[255]; // for temp storage int pnum, pos, count; char * cstr; int rdata, i; bool go = true; bool stopread = false; int numbytes = 0; DBG_msg("do_nget", inbuf); completed = false; count = 0; // next chars on the commandline is the number of bytes to read if (inbuf[2] == NULL) { // no value on the command line numbytes = 0; } else { // now process line for (i = 2; ((inbuf[i] >='0') && (inbuf[i] <= '9')); i++ ) { numbytes = 10 * numbytes + (inbuf[i] - '0'); } } DBG_int("do_nget bytes:", numbytes); stream.readNext((byte*)Buf, 512); //Point to buffer for the first read strcpy(s, param[par_U_].c_str()); // URL from parameter U // check for a % sign in s pos = 0; while ((s[pos] != NULL) && (s[pos] != c_percent)) pos++; if ((s[pos] != NULL) && ((pnum = getpnum(s[pos + 1])) >= 0)) { // found and valid parameter, now insert cstr = new char [param[pnum].size() + 1]; strcpy (cstr, param[pnum].c_str()); DBG_msg("param", cstr); DBG_int("pos", pos); remchar(s, pos, 2); // remove %n, works better for insert DBG_msg("do_nget", s); insertstr(s, cstr, pos); // insert DBG_msg("do_nget", s); delete[] cstr; } HTTPResult r = http.get(s, &stream, request_callback); // try to get the data // this is the main loop for reading the file while((!completed)) { Net::poll(); // polls the Networking stack if(stream.readable()) { rdata = stream.readLen(); // number of bytes read DBG_int("rdata", rdata); Buf[stream.readLen()] = 0; //Transform this buffer in zero-terminated char* string // now send data to our transmit buffer i = 0; while (go && (i < rdata)) { DBG_chr("rd", Buf[i]); mldl.tx_addp(Buf[i]); i++; count++; // now check if we have to stop? if (!mldl.rx_empty()) { stopread = (mldl.rxx_read(data_mode) < 0); // intentional stop of read DBG_msg("do_nget", "forced stop"); } go = !((count == numbytes) || stopread); } //Buffer has been read, now we can put more data in it stream.readNext((byte*)Buf, 512); } } // we are done with the required number of bytes or found EOF if (!stopread && (count != numbytes)) { // real EOF found, so terminate by sending EOF mldl.tx_add(c_escape); mldl.tx_add(c_eof); DBG_int("do_nget: EOF at byte ", count); } if (stopread) { DBG_msg("do_nget", "forced stop read received"); mldl.flush_tx(); // empty transmit buffer } DBG_int("do_nget: end read at byte ", count); } /** HTTP Server commands * * syntax: NHI[medium]: initialise and start HTTP Server * [medium] = S, U or L for the filesystem to be used * default filesystem is "/local" * \n NHS: stop HTTP Server * */ void do_nhttp() { char c; char medium[10]; DBG_msg("do_nhttp", inbuf); c = inbuf[3]; // [medium] switch (c) { case f_sdcard : strcpy(medium, rt_sd); // "/sd" break; case f_local : strcpy(medium, rt_local); // "/local" break; case f_usb : strcpy(medium, rt_usb); // "/usb" break; default : strcpy(medium, "/local"); // default break; } if (inbuf[2] == ninit) { // HTTP server initialize DBG_msg("HTTP Init", medium); if (!network_enabled) do_ninit(); server = new HTTPServer; FSHandler::mount(medium, "/" ); server->addHandler<FSHandler>("/"); server->addHandler<RPCHandler>("/rpc"); server->addHandler<SimpleHandler>("/simple"); server->bind(80); httpserver_enabled = true; DBG_msg( "HTTP server", "started" ); return; } if (inbuf[2] == nstop) { // HTTP Server stop delete server; httpserver_enabled = false; DBG_msg( "HTTP server", "stopped" ); return; } do_ndefault(); } /** send error message, command not recognized * */ void do_ndefault() { // command not recognized DBG_msg("do_ndefault", inbuf); send_error(err_notrecognized); }