123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544 |
- /*! \mainpage Arduino ENC28J60 EtherShield Library
- \section Introduction
- This library is derived from original code by Guido Socher and Pascal Stang, and hence licensed as GPL2. See http://www.gnu.org/licenses/gpl.html
- It comprises a C++ class wrapper and a number of C files. It still follows pretty much the same structure as the original code that it was based on.
- The Arduino EtherShield Library was initially created by Xing Yu of Nuelectronics, http://www.nuelectronics.com/estore/index.php?main_page=product_info&cPath=1&products_id=4
- The library was heavily modified and improved by Andrew D. Lindsay (http://blog.thiseldo.co.uk) with extra code from the Tuxgraphics.org ethernet library (http://www.tuxgraphics.org/electronics/200905/embedded-tcp-ip-stack.shtml), which also originated from the Pascal Stang code.
- Further additions include the DHCP implementation with some assistance from JCW at http://jeelabs.org which is now used in their own version of the library for their EtherCard at http://jeelabs.net/projects/hardware/wiki/Ether_Card.
- The library is now being used successfully with the Nanode, as minimal Ethernet connected Arduino compatible board, details available from http://wiki.london.hackspace.org.uk/view/Project:Nanode
- \section Download
- Download the latest library and examples from https://github.com/thiseldo/EtherShield
- To fully utilise the Nanode board, you will also require a library that can access the onboard MAC address chip.
- One such library is available from https://github.com/thiseldo/NanodeMAC and is used in the examples provided with this library.
- \section Instalation
- The library .zip file downloaded from https://github.com/thiseldo/EtherShield should be renamed to EtherShield.zip or EtherShield.tar.gz depending on the archive file you're downloading.
- The file should be extracted to the sketchbook/libraries/ folder so that there is a subdirectory called EtherSheild containing all the files from the archive.
- \section License
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
- A copy of the GNU Lesser General Public
- License is available from http://www.gnu.org/licenses/gpl.html; or write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
- #include "ip_config.h"
- #include "enc28j60.h"
- #include "ip_arp_udp_tcp.h"
- #include "websrv_help_functions.h"
- #ifdef DNS_client
- #include "dnslkup.h"
- #endif
- #ifdef DHCP_client
- #include "dhcp.h"
- #endif
- #include "EtherShield.h"
- /**
- * Initialise SPI, separate from main initialisation so that
- * multiple SPI devices can be used together
- */
- void ES_enc28j60SpiInit(SPI_HandleTypeDef *hspi){
- // ENC28J60_SPI1_Configuration();
- enc28j60_set_spi(hspi);
- }
- /**
- * Initialise the ENC28J60 using default chip select pin
- * Flash the 2 MagJack LEDs
- */
- void ES_enc28j60Init( uint8_t* macaddr ) {
- /*initialize enc28j60*/
- enc28j60Init( macaddr );
- enc28j60clkout(2); // change clkout from 6.25MHz to 12.5MHz
- HAL_Delay(10);
- int f;
- for( f=0; f<3; f++ ) {
- // 0x880 is PHLCON LEDB=on, LEDA=on
- // enc28j60PhyWrite(PHLCON,0b0011 1000 1000 00 00);
- enc28j60PhyWrite(PHLCON,0x3880);
- HAL_Delay(500);
- // 0x990 is PHLCON LEDB=off, LEDA=off
- // enc28j60PhyWrite(PHLCON,0b0011 1001 1001 00 00);
- enc28j60PhyWrite(PHLCON,0x3990);
- HAL_Delay(500);
- }
- // 0x476 is PHLCON LEDA=links status, LEDB=receive/transmit
- // enc28j60PhyWrite(PHLCON,0b0011 0100 0111 01 10);
- enc28j60PhyWrite(PHLCON,0x3476);
- HAL_Delay(100);
- }
- void ES_enc28j60clkout(uint8_t clk){
- enc28j60clkout(clk);
- }
- uint8_t ES_enc28j60linkup(void) {
- return enc28j60linkup();
- }
- void ES_enc28j60EnableBroadcast( void ) {
- enc28j60EnableBroadcast();
- }
- void ES_enc28j60DisableBroadcast( void ) {
- enc28j60DisableBroadcast();
- }
- void ES_enc28j60EnableMulticast( void ) {
- enc28j60EnableMulticast();
- }
- void ES_enc28j60DisableMulticast( void ) {
- enc28j60DisableMulticast();
- }
- uint8_t ES_enc28j60Read( uint8_t address ) {
- return enc28j60Read( address );
- }
- uint8_t ES_enc28j60Revision(void) {
- return enc28j60getrev();
- }
- void ES_enc28j60PhyWrite(uint8_t address, uint16_t data){
- enc28j60PhyWrite(address, data);
- }
- uint16_t ES_enc28j60PacketReceive(uint16_t len, uint8_t* packet){
- return enc28j60PacketReceive(len, packet);
- }
- void ES_enc28j60PacketSend(uint16_t len, uint8_t* packet){
- enc28j60PacketSend(len, packet);
- }
- void ES_init_ip_arp_udp_tcp(uint8_t *mymac,uint8_t *myip,uint16_t wwwp){
- init_ip_arp_udp_tcp(mymac,myip,wwwp);
- }
- uint8_t ES_eth_type_is_arp_and_my_ip(uint8_t *buf,uint16_t len) {
- return eth_type_is_arp_and_my_ip(buf,len);
- }
- uint8_t ES_eth_type_is_ip_and_my_ip(uint8_t *buf,uint16_t len) {
- return eth_type_is_ip_and_my_ip(buf, len);
- }
- void ES_make_echo_reply_from_request(uint8_t *buf,uint16_t len) {
- make_echo_reply_from_request(buf,len);
- }
- void ES_make_tcp_synack_from_syn(uint8_t *buf) {
- make_tcp_synack_from_syn(buf);
- }
- void ES_make_tcp_ack_from_any(uint8_t *buf,int16_t datlentoack,uint8_t addflags ) {
- void make_tcp_ack_from_any(uint8_t *buf,int16_t datlentoack,uint8_t addflags );
- }
- void ES_make_tcp_ack_with_data(uint8_t *buf,uint16_t dlen ) {
- make_tcp_ack_with_data(buf, dlen);
- }
-
- void ES_make_tcp_ack_with_data_noflags(uint8_t *buf,uint16_t dlen ) {
- make_tcp_ack_with_data_noflags(buf, dlen);
- }
- uint16_t ES_build_tcp_data(uint8_t *buf, uint16_t srcPort ) {
- return build_tcp_data( buf, srcPort );
- }
- void ES_send_tcp_data(uint8_t *buf,uint16_t dlen ) {
- send_tcp_data(buf, dlen);
- }
- void ES_send_udp_data2(uint8_t *buf, uint8_t *destmac,uint16_t dlen,uint16_t source_port, uint8_t *dest_ip, uint16_t dest_port) {
- send_udp_prepare(buf,source_port, dest_ip, dest_port);
- uint8_t i;
- for(i = 0; i< 6; i++ )
- buf[ETH_DST_MAC+i] = destmac[i];
- send_udp_transmit(buf,dlen);
- }
- void ES_send_udp_data1(uint8_t *buf,uint16_t dlen,uint16_t source_port, uint8_t *dest_ip, uint16_t dest_port) {
- send_udp_prepare(buf,source_port, dest_ip, dest_port);
- send_udp_transmit(buf,dlen);
- }
- void ES_init_len_info(uint8_t *buf) {
- init_len_info(buf);
- }
- /*void ES_fill_buf_p(uint8_t *buf,uint16_t len, const prog_char *progmem_s) {
- fill_buf_p(buf, len, progmem_s);
- }*/
- uint16_t ES_checksum(uint8_t *buf, uint16_t len,uint8_t type) {
- return checksum(buf, len, type);
- }
- void ES_fill_ip_hdr_checksum(uint8_t *buf) {
- fill_ip_hdr_checksum(buf);
- }
- uint16_t ES_get_tcp_data_pointer(void) {
- return get_tcp_data_pointer();
- }
- uint16_t ES_packetloop_icmp_tcp(uint8_t *buf,uint16_t plen) {
- return packetloop_icmp_tcp(buf,plen);
- }
- /*uint16_t ES_fill_tcp_data_p(uint8_t *buf,uint16_t pos, const prog_char *progmem_s){
- return fill_tcp_data_p(buf, pos, progmem_s);
- }*/
- uint16_t ES_fill_tcp_data(uint8_t *buf,uint16_t pos, const char *s){
- return fill_tcp_data(buf,pos, s);
- }
- uint16_t ES_fill_tcp_data_len(uint8_t *buf,uint16_t pos, const char *s, uint16_t len ){
- return fill_tcp_data_len(buf,pos, s, len);
- }
- void ES_www_server_reply(uint8_t *buf,uint16_t dlen) {
- www_server_reply(buf,dlen);
- }
-
- uint8_t ES_client_store_gw_mac(uint8_t *buf) {
- return client_store_gw_mac(buf);
- }
- void ES_client_set_gwip(uint8_t *gwipaddr) {
- client_set_gwip(gwipaddr);
- }
- void ES_client_set_wwwip(uint8_t *wwwipaddr) {
- //client_set_wwwip(wwwipaddr);
- client_tcp_set_serverip(wwwipaddr);
- }
- void ES_client_tcp_set_serverip(uint8_t *ipaddr) {
- client_tcp_set_serverip(ipaddr);
- }
- void ES_client_arp_whohas(uint8_t *buf,uint8_t *ip_we_search) {
- client_arp_whohas(buf, ip_we_search);
- }
- #if defined (TCP_client) || defined (WWW_client) || defined (NTP_client)
- uint8_t ES_client_tcp_req(uint8_t (*result_callback)(uint8_t fd,uint8_t statuscode,uint16_t data_start_pos_in_buf, uint16_t len_of_data),uint16_t (*datafill_callback)(uint8_t fd),uint16_t port ) {
- return client_tcp_req( result_callback, datafill_callback, port );
- }
- void ES_tcp_client_send_packet(uint8_t *buf,uint16_t dest_port, uint16_t src_port, uint8_t flags, uint8_t max_segment_size,
- uint8_t clear_seqck, uint16_t next_ack_num, uint16_t dlength, uint8_t *dest_mac, uint8_t *dest_ip){
-
- tcp_client_send_packet(buf, dest_port, src_port, flags, max_segment_size, clear_seqck, next_ack_num, dlength,dest_mac,dest_ip);
- }
- uint16_t ES_tcp_get_dlength( uint8_t *buf ){
- return tcp_get_dlength(buf);
- }
- #endif // TCP_client WWW_Client etc
- #ifdef WWW_client
- // ----- http get
- void ES_client_browse_url(char *urlbuf, char *urlbuf_varpart, char *hoststr,
- void (*callback)(uint8_t,uint16_t,uint16_t)) {
- client_browse_url(urlbuf, urlbuf_varpart, hoststr, callback);
- }
- void ES_client_http_post(char *urlbuf, char *hoststr, char *additionalheaderline,
- char *method, char *postval,void (*callback)(uint8_t,uint16_t)) {
- client_http_post(urlbuf, hoststr, additionalheaderline, method, postval,callback);
- }
- #endif // WWW_client
- #ifdef NTP_client
- void ES_client_ntp_request(uint8_t *buf,uint8_t *ntpip,uint8_t srcport) {
- client_ntp_request(buf,ntpip,srcport);
- }
- uint8_t ES_client_ntp_process_answer(uint8_t *buf,uint32_t *time,uint8_t dstport_l) {
- return client_ntp_process_answer(buf,time,dstport_l);
- }
- #endif // NTP_client
- void ES_register_ping_rec_callback(void (*callback)(uint8_t *srcip)) {
- register_ping_rec_callback(callback);
- }
- #ifdef PING_client
- void ES_client_icmp_request(uint8_t *buf,uint8_t *destip) {
- client_icmp_request(buf,destip);
- }
- uint8_t ES_packetloop_icmp_checkreply(uint8_t *buf,uint8_t *ip_monitoredhost) {
- return packetloop_icmp_checkreply(buf,ip_monitoredhost);
- }
- #endif // PING_client
- #ifdef WOL_client
- void ES_send_wol(uint8_t *buf,uint8_t *wolmac) {
- send_wol(buf,wolmac);
- }
- #endif // WOL_client
- #ifdef FROMDECODE_websrv_help
- uint8_t ES_find_key_val(char *str,char *strbuf, uint16_t maxlen,char *key) {
- return find_key_val(str,strbuf, maxlen,key);
- }
- void ES_urldecode(char *urlbuf) {
- urldecode(urlbuf);
- }
- #endif
- #ifdef URLENCODE_websrv_help
- void ES_urlencode(char *str,char *urlbuf) {
- urlencode(str,urlbuf);
- }
- #endif
- uint8_t ES_parse_ip(uint8_t *bytestr,char *str) {
- return parse_ip(bytestr,str);
- }
- void ES_mk_net_str(char *resultstr,uint8_t *bytestr,uint16_t len,char separator,uint8_t base) {
- mk_net_str(resultstr,bytestr,len,separator,base);
- }
- uint8_t ES_client_waiting_gw() {
- return( client_waiting_gw() );
- }
- #ifdef DNS_client
- uint8_t ES_dnslkup_haveanswer(void)
- {
- return( dnslkup_haveanswer() );
- }
- uint8_t ES_dnslkup_get_error_info(void)
- {
- return( dnslkup_get_error_info() );
- }
- uint8_t * ES_dnslkup_getip(void)
- {
- return(dnslkup_getip() );
- }
- void ES_dnslkup_set_dnsip(uint8_t *dnsipaddr) {
- dnslkup_set_dnsip(dnsipaddr);
- }
- void ES_dnslkup_request(uint8_t *buf,uint8_t *hostname) {
- return( dnslkup_request(buf, hostname) );
- }
- uint8_t ES_udp_client_check_for_dns_answer(uint8_t *buf,uint16_t plen){
- return( udp_client_check_for_dns_answer( buf, plen) );
- }
- // Perform all processing to resolve a hostname to IP address.
- // Returns 1 for successful Name resolution, 0 otherwise
- uint8_t resolveHostname(uint8_t *buf, uint16_t buffer_size, uint8_t *hostname ) {
- uint16_t dat_p;
- int plen = 0;
- long lastDnsRequest = HAL_GetTick();
- uint8_t dns_state = DNS_STATE_INIT;
- bool gotAddress = FALSE;
- uint8_t dnsTries = 3; // After 10 attempts fail gracefully so other action can be carried out
- while( !gotAddress ) {
- // handle ping and wait for a tcp packet
- plen = enc28j60PacketReceive(buffer_size, buf);
- dat_p=packetloop_icmp_tcp(buf,plen);
- // We have a packet
- // Check if IP data
- if (dat_p == 0) {
- if (client_waiting_gw() ) {
- // No ARP received for gateway
- continue;
- }
- // It has IP data
- if (dns_state==DNS_STATE_INIT) {
- dns_state=DNS_STATE_REQUESTED;
- lastDnsRequest = HAL_GetTick();
- dnslkup_request(buf,hostname);
- continue;
- }
- if (dns_state!=DNS_STATE_ANSWER){
- // retry every minute if dns-lookup failed:
- if (HAL_GetTick() > (lastDnsRequest + 60000L) ){
- if( --dnsTries <= 0 )
- return 0; // Failed to allocate address
- dns_state=DNS_STATE_INIT;
- lastDnsRequest = HAL_GetTick();
- }
- // don't try to use client before
- // we have a result of dns-lookup
- continue;
- }
- }
- else {
- if (dns_state==DNS_STATE_REQUESTED && udp_client_check_for_dns_answer( buf, plen ) ){
- dns_state=DNS_STATE_ANSWER;
- //client_set_wwwip(dnslkup_getip());
- client_tcp_set_serverip(dnslkup_getip());
- gotAddress = TRUE;
- }
- }
- }
-
- return 1;
- }
- #endif // DNS_client
- #ifdef DHCP_client
- void ES_dhcp_start(uint8_t *buf, uint8_t *macaddrin, uint8_t *ipaddrin,
- uint8_t *maskin, uint8_t *gwipin, uint8_t *dhcpsvrin, uint8_t *dnssvrin ) {
- dhcp_start(buf, macaddrin, ipaddrin, maskin, gwipin, dhcpsvrin, dnssvrin );
- }
- uint8_t ES_dhcp_state(void)
- {
- return( dhcp_state() );
- }
- uint8_t ES_check_for_dhcp_answer(uint8_t *buf,uint16_t plen){
- return( check_for_dhcp_answer( buf, plen) );
- }
- // Utility functions
- // Perform all processing to get an IP address plus other addresses returned, e.g. gw, dns, dhcp server.
- // Returns 1 for successful IP address allocation, 0 otherwise
- uint8_t allocateIPAddress(uint8_t *buf, uint16_t buffer_size, uint8_t *mymac, uint16_t myport, uint8_t *myip, uint8_t *mynetmask, uint8_t *gwip, uint8_t *dnsip, uint8_t *dhcpsvrip ) {
- uint16_t dat_p;
- int plen = 0;
- long lastDhcpRequest = HAL_GetTick();
- uint8_t dhcpState = 0;
- bool gotIp = FALSE;
- uint8_t dhcpTries = 10; // After 10 attempts fail gracefully so other action can be carried out
- dhcp_start( buf, mymac, myip, mynetmask,gwip, dnsip, dhcpsvrip );
- while( !gotIp ) {
- // handle ping and wait for a tcp packet
- plen = enc28j60PacketReceive(buffer_size, buf);
- dat_p=packetloop_icmp_tcp(buf,plen);
- if(dat_p==0) {
- check_for_dhcp_answer( buf, plen);
- dhcpState = dhcp_state();
- // we are idle here
- if( dhcpState != DHCP_STATE_OK ) {
- if (HAL_GetTick() > (lastDhcpRequest + 10000L) ){
- lastDhcpRequest = HAL_GetTick();
- if( --dhcpTries <= 0 )
- return 0; // Failed to allocate address
- // send dhcp
- dhcp_start( buf, mymac, myip, mynetmask,gwip, dnsip, dhcpsvrip );
- }
- } else {
- if( !gotIp ) {
- gotIp = TRUE;
- //init the ethernet/ip layer:
- init_ip_arp_udp_tcp(mymac, myip, myport);
- // Set the Router IP
- client_set_gwip(gwip); // e.g internal IP of dsl router
- // Set the DNS server IP address if required, or use default
- dnslkup_set_dnsip( dnsip );
- }
- }
- }
- }
- return 1;
- }
- #endif // DHCP_client
- void ES_enc28j60PowerUp(){
- enc28j60PowerUp();
- }
- void ES_enc28j60PowerDown(){
- enc28j60PowerDown();
- }
- // TCP functions broken out here for testing
- uint8_t ES_nextTcpState( uint8_t *buf, uint16_t plen ) {
- return nextTcpState(buf, plen );
- }
- uint8_t ES_currentTcpState( ) {
- return currentTcpState( );
- }
- uint8_t ES_tcpActiveOpen( uint8_t *buf,uint16_t plen,
- uint8_t (*result_callback)(uint8_t fd,uint8_t statuscode,uint16_t data_start_pos_in_buf, uint16_t len_of_data),
- uint16_t (*datafill_callback)(uint8_t fd),
- uint16_t port ) {
- return tcpActiveOpen(buf, plen, result_callback, datafill_callback, port );
- }
- void ES_tcpPassiveOpen( uint8_t *buf,uint16_t plen ) {
- tcpPassiveOpen(buf, plen );
- }
- void ES_tcpClose( uint8_t *buf,uint16_t plen ) {
- tcpClose(buf, plen );
- }
- // End
|