no changes
Fork of XBee by
XBeeWiFi.cpp
- Committer:
- okini3939
- Date:
- 2012-03-13
- Revision:
- 4:f6d73acc1f75
- Parent:
- 3:8573b122fa84
- Child:
- 5:547cfff7adf7
File content as of revision 4:f6d73acc1f75:
/** * XBee Wi-Fi library for mbed * Copyright (c) 2011 Hiroshi Suga * Released under the MIT License: http://mbed.org/license/mit */ /** @file * @brief XBee Wi-Fi library for mbed */ //#define DEBUG #include "dbg.h" #include "mbed.h" #include "XBee.h" #include "XBeeWiFi.h" #include "EthernetNetIf.h" #define REVERSE_ENDIAN(x) (uint16_t)(((uint16_t)x >> 8) | ((uint16_t)x << 8)) #ifdef USE_WIFICLASS XBeeWiFi::XBeeWiFi (PinName p_tx, PinName p_rx, PinName p_cts, PinName p_rts) : XBee(p_tx, p_rx, p_cts, p_rts) { } int XBeeWiFi::setup (int security, const char *ssid, const char *pin) { int len, r; uint8_t cmd[2], val[32]; AtCommandRequest atRequest; // SSID memcpy(cmd, "ID", 2); len = strlen(ssid); memcpy(val, ssid, len); atRequest.setCommand(cmd); atRequest.setCommandValue(val); atRequest.setCommandValueLength(len); atRequest.setFrameId(getNextFrameId()); send(atRequest); r = getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId()); DBG("wifi ID: %d\r\n", r); if (r < 0) return -1; if (security != SECURITY_OPEN) { // PIN memcpy(cmd, "PK", 2); len = strlen(pin); memcpy(val, pin, len); atRequest.setCommand(cmd); atRequest.setCommandValue(val); atRequest.setCommandValueLength(len); atRequest.setFrameId(getNextFrameId()); send(atRequest); r = getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId()); DBG("wifi PK: %d\r\n", r); if (r < 0) return -1; } // security type memcpy(cmd, "EE", 2); val[0] = security; atRequest.setCommand(cmd); atRequest.setCommandValue(val); atRequest.setCommandValueLength(1); atRequest.setFrameId(getNextFrameId()); send(atRequest); r = getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId()); DBG("wifi EE: %d\r\n", r); if (r < 0) return -1; return 0; } int XBeeWiFi::setup (const char *ssid) { return setup(SECURITY_OPEN, ssid, NULL); } int XBeeWiFi::reset () { // RESET uint8_t cmd[2] = {'N', 'R'}; // Network reset // uint8_t cmd[2] = {'F', 'R'}; // Software reset AtCommandRequest atRequest; atRequest.setCommand(cmd); atRequest.setFrameId(getNextFrameId()); send(atRequest); return getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId()); } int XBeeWiFi::baud (int b) { // RESET uint8_t cmd[2] = {'B', 'D'}; char val[4]; AtCommandRequest atRequest; int r, len; if (b < 0x100) { val[0] = b; len = 1; } else { val[0] = (b >> 24) & 0xff; val[1] = (b >> 16) & 0xff; val[2] = (b >> 8) & 0xff; val[3] = b & 0xff; len = 4; } atRequest.setCommand(cmd); atRequest.setCommandValue((uint8_t*)val); atRequest.setCommandValueLength(len); atRequest.setFrameId(getNextFrameId()); send(atRequest); r = getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId()); if (r == 0) { begin(b); } return r; } int XBeeWiFi::setAddress () { // DHCP uint8_t cmd[2] = {'M', 'A'}; char val[1] = {0}; AtCommandRequest atRequest; atRequest.setCommand(cmd); atRequest.setCommandValue((uint8_t*)val); atRequest.setCommandValueLength(1); atRequest.setFrameId(getNextFrameId()); send(atRequest); return getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId()); } int XBeeWiFi::setAddress (IpAddr &ipaddr, IpAddr &netmask, IpAddr &gateway, IpAddr &nameserver) { uint8_t cmd[2]; char val[32]; AtCommandRequest atRequest; // Static memcpy(cmd, "MA", 2); val[0] = 1; atRequest.setCommand(cmd); atRequest.setCommandValue((uint8_t*)val); atRequest.setCommandValueLength(1); atRequest.setFrameId(getNextFrameId()); send(atRequest); getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId()); // IP address memcpy(cmd, "MY", 2); sprintf(val, "%d.%d.%d.%d", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]); atRequest.setCommand(cmd); atRequest.setCommandValue((uint8_t*)val); atRequest.setCommandValueLength(strlen(val)); atRequest.setFrameId(getNextFrameId()); send(atRequest); getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId()); // sub netmask memcpy(cmd, "NK", 2); sprintf(val, "%d.%d.%d.%d", netmask[0], netmask[1], netmask[2], netmask[3]); atRequest.setCommand(cmd); atRequest.setCommandValue((uint8_t*)val); atRequest.setCommandValueLength(strlen(val)); atRequest.setFrameId(getNextFrameId()); send(atRequest); getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId()); // default gateway memcpy(cmd, "GW", 2); sprintf(val, "%d.%d.%d.%d", gateway[0], gateway[1], gateway[2], gateway[3]); atRequest.setCommand(cmd); atRequest.setCommandValue((uint8_t*)val); atRequest.setCommandValueLength(strlen(val)); atRequest.setFrameId(getNextFrameId()); send(atRequest); getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId()); // name server _nameserver = nameserver; return 0; } int XBeeWiFi::getAddress (IpAddr &ipaddr, IpAddr &netmask, IpAddr &gateway, IpAddr &nameserver) { int r; uint8_t cmd[2]; AtCommandRequest atRequest; AtCommandResponse atResponse; memcpy(cmd, "MY", 2); atRequest.setCommand(cmd); atRequest.clearCommandValue(); atRequest.setFrameId(getNextFrameId()); send(atRequest); r = getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId()); DBG("wifi MY: %d\r\n", r); if (r >= 0) { r = getWiAddr(ipaddr); } memcpy(cmd, "MK", 2); atRequest.setCommand(cmd); atRequest.clearCommandValue(); atRequest.setFrameId(getNextFrameId()); send(atRequest); r = getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId()); DBG("wifi MK: %d\r\n", r); if (r >= 0) { r = getWiAddr(netmask); } memcpy(cmd, "GW", 2); atRequest.setCommand(cmd); atRequest.clearCommandValue(); atRequest.setFrameId(getNextFrameId()); send(atRequest); r = getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId()); DBG("wifi GW: %d\r\n", r); if (r >= 0) { r = getWiAddr(gateway); } nameserver = _nameserver; return 0; } int XBeeWiFi::getWiAddr (IpAddr &ipaddr) { int ip1, ip2, ip3, ip4; AtCommandResponse atResponse; getResponse().getAtCommandResponse(atResponse); if (atResponse.isOk() && atResponse.getValueLength() >= 7) { sscanf((char*)atResponse.getValue(), "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4); ipaddr = IpAddr(ip1, ip2, ip3, ip4); return 0; } return -1; } int XBeeWiFi::setTimeout (int timeout) { // timeout uint8_t cmd[2] = {'T', 'P'}; char val[1]; AtCommandRequest atRequest; val[0] = timeout; atRequest.setCommand(cmd); atRequest.setCommandValue((uint8_t*)val); atRequest.setCommandValueLength(1); atRequest.setFrameId(getNextFrameId()); send(atRequest); return getWiResponse(AT_COMMAND_RESPONSE); } int XBeeWiFi::getStatus () { // AI uint8_t cmd[2] = {'A', 'I'}; AtCommandRequest atRequest; atRequest.setCommand(cmd); atRequest.setFrameId(getNextFrameId()); send(atRequest); return getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId()); } int XBeeWiFi::getWiResponse (int apiId, int frameid, int timeout) { AtCommandResponse atResponse; if (readPacket(timeout)) { if (frameid && frameid != getResponse().getFrameData()[0]) { DBG("Expected AT response but got %x (frame %d)\r\n", getResponse().getApiId(), getResponse().getFrameData()[0]); if (! readPacket(timeout)) return -1; DBG("Retry ok\r\n"); } if (getResponse().getApiId() == apiId) { getResponse().getAtCommandResponse(atResponse); if (getResponse().getApiId() == IPv4_RX_FRAME) { return 0; } else if (atResponse.isOk()) { // if (getResponse().getFrameDataLength() > 4) { return atResponse.getValue()[0]; } else { DBG("Command return error code: %x\r\n", atResponse.getStatus()); } } else { DBG("Expected AT response but got %x\r\n", getResponse().getApiId()); } } else { if (getResponse().isError()) { DBG("Error reading packet. Error code: %x\r\n", getResponse().getErrorCode()); } else { DBG("No response from radio\r\n"); } } return -1; } #ifdef USE_WIFIDNS int XBeeWiFi::setNameserver (IpAddr &nameserver) { _nameserver = nameserver; return 0; } // *** Note: wifi is turned off when XBee send the port 53 udp packet. int XBeeWiFi::getHostByName (const char* name, IpAddr &addr) { Timer timeout; char buf[600]; int r, len; uint8_t cmd[2] = {'C', '0'}; char val[2]; IPv4TransmitRequest dnsRequest; AtCommandRequest atRequest; AtCommandResponse atResponse; if (!strcmp(name, "localhost")) { addr = IpAddr(127, 0, 0, 1); return 0; } /* // bind src port val[0] = (DNS_SRC_PORT >> 8) & 0xff; val[1] = DNS_SRC_PORT & 0xff; atRequest.setCommand(cmd); atRequest.setCommandValue((uint8_t*)val); atRequest.setCommandValueLength(2); atRequest.setFrameId(getNextFrameId()); send(atRequest); r = getWiResponse(AT_COMMAND_RESPONSE); DBG("wifi C0: %d\r\n", r); */ // send DNS request len = createDnsRequest(name, buf); dnsRequest.setAddress(_nameserver); dnsRequest.setDstPort(DNS_PORT); dnsRequest.setSrcPort(DNS_SRC_PORT); dnsRequest.setProtocol(PROTOCOL_UDP); dnsRequest.setPayload((uint8_t*)buf); dnsRequest.setPayloadLength(len); // wait responce timeout.reset(); timeout.start(); while (timeout.read_ms() < DNS_TIMEOUT) { dnsRequest.setFrameId(getNextFrameId()); send(dnsRequest); r = getWiResponse(TX_STATUS_RESPONSE, dnsRequest.getFrameId()); DBG("wifi TX: %d\r\n", r); if (r >= 0) { // recv DNS request r = getWiResponse(IPv4_RX_FRAME, 0, 3000); DBG("wifi RX: %d\r\n", r); if (r >= 0) { timeout.stop(); getResponse().getAtCommandResponse(atResponse); return getDnsResponse(atResponse.getValue() + 6, atResponse.getValueLength() - 6, addr); } } else { break; } } timeout.stop(); return -1; } int XBeeWiFi::createDnsRequest (const char* name, char *buf) { struct DNSHeader *dnsHeader; struct DnsQuestionEnd *dnsEnd; int len, num; // DNS header dnsHeader = (DNSHeader*)buf; dnsHeader->id = REVERSE_ENDIAN(0xdead); dnsHeader->flags = REVERSE_ENDIAN(0x100); dnsHeader->questions = REVERSE_ENDIAN(1); dnsHeader->answers = 0; dnsHeader->authorities = 0; dnsHeader->additional = 0; // DNS question len = sizeof(DNSHeader); while ((num = (int)strchr(name, '.')) != NULL) { num = num - (int)name; buf[len] = num; len ++; strncpy(&buf[len], name, num); name = name + num + 1; len = len + num; } if ((num = strlen(name)) != NULL) { buf[len] = num; len ++; strncpy(&buf[len], name, num); len = len + num; } buf[len] = 0; len ++; dnsEnd = (DnsQuestionEnd*)&buf[len]; dnsEnd->type = REVERSE_ENDIAN(DNS_QUERY_A); dnsEnd->clas = REVERSE_ENDIAN(DNS_CLASS_IN); return len + sizeof(DnsQuestionEnd); } int XBeeWiFi::getDnsResponse (const uint8_t *buf, int len, IpAddr &addr) { int i; struct DNSHeader *dnsHeader; struct DnsAnswer *dnsAnswer; // DNS header dnsHeader = (DNSHeader*)buf; if (REVERSE_ENDIAN(dnsHeader->id) != 0xdead || (REVERSE_ENDIAN(dnsHeader->flags) & 0x800f) != 0x8000) { return -1; } // skip question for (i = sizeof(DNSHeader); buf[i] && i < len; i ++); i = i + 1 + sizeof(DnsQuestionEnd); // DNS answer while (i < len) { dnsAnswer = (DnsAnswer*)&buf[i]; if (dnsAnswer->clas != REVERSE_ENDIAN(DNS_CLASS_IN)) { return -1; } i = i + sizeof(DnsAnswer); if (dnsAnswer->type == REVERSE_ENDIAN(DNS_QUERY_A)) { addr = IpAddr(buf[i], buf[i + 1], buf[i + 2], buf[i + 3]); return 0; } i = i + dnsAnswer->length; } return -1; } #endif #endif IPv4TransmitRequest::IPv4TransmitRequest() : PayloadRequest(IPv4_TRANSMIT_REQUEST, DEFAULT_FRAME_ID, NULL, 0) { } IPv4TransmitRequest::IPv4TransmitRequest(IpAddr &dstAddr, uint16_t dstPort, uint16_t srcPort, uint8_t protocol, uint8_t option, uint8_t *data, uint16_t dataLength, uint8_t frameId): PayloadRequest(IPv4_TRANSMIT_REQUEST, frameId, data, dataLength) { _dstAddr = dstAddr; _dstPort = dstPort; _srcPort = srcPort; _protocol = protocol; _option = option; } IPv4TransmitRequest::IPv4TransmitRequest(IpAddr &dstAddr, uint16_t dstPort, uint8_t *data, uint16_t dataLength): PayloadRequest(IPv4_TRANSMIT_REQUEST, DEFAULT_FRAME_ID, data, dataLength) { _dstAddr = dstAddr; _dstPort = dstPort; _srcPort = 0x270f; _protocol = PROTOCOL_UDP; _option = 0; } uint8_t IPv4TransmitRequest::getFrameData(uint16_t pos) { if (pos == 0) { return _dstAddr[0]; } else if (pos == 1) { return _dstAddr[1]; } else if (pos == 2) { return _dstAddr[2]; } else if (pos == 3) { return _dstAddr[3]; } else if (pos == 4) { return (_dstPort >> 8) & 0xff; } else if (pos == 5) { return _dstPort & 0xff; } else if (pos == 6) { return (_srcPort >> 8) & 0xff; } else if (pos == 7) { return _srcPort & 0xff; } else if (pos == 8) { return _protocol; } else if (pos == 9) { return _option; } else { return getPayload()[pos - IPv4_TRANSMIT_REQUEST_API_LENGTH]; } } uint16_t IPv4TransmitRequest::getFrameDataLength() { return IPv4_TRANSMIT_REQUEST_API_LENGTH + getPayloadLength(); } IpAddr& IPv4TransmitRequest::getAddress() { return _dstAddr; } uint16_t IPv4TransmitRequest::getDstPort() { return _dstPort; } uint16_t IPv4TransmitRequest::getSrcPort() { return _srcPort; } uint8_t IPv4TransmitRequest::getProtocol() { return _protocol; } uint8_t IPv4TransmitRequest::getOption() { return _option; } void IPv4TransmitRequest::setAddress(IpAddr &dstAddr) { _dstAddr = dstAddr; } void IPv4TransmitRequest::setDstPort(uint16_t dstPort) { _dstPort = dstPort; } void IPv4TransmitRequest::setSrcPort(uint16_t srcPort) { _srcPort = srcPort; } void IPv4TransmitRequest::setProtocol(uint8_t protocol) { _protocol = protocol; } void IPv4TransmitRequest::setOption(uint8_t option) { _option = option; } Transmit_Status::Transmit_Status() : FrameIdResponse() { } uint8_t Transmit_Status::getStatus() { return getFrameData()[1]; } bool Transmit_Status::isSuccess() { return getStatus() == SUCCESS; } IPV4RxFrame::IPV4RxFrame () { } IpAddr& IPV4RxFrame::getSrcAddress() { _srcAddr = IpAddr(getFrameData()[0], getFrameData()[1], getFrameData()[2], getFrameData()[3]); return _srcAddr; } uint16_t IPV4RxFrame::getDstPort() { return (getFrameData()[4] << 8) + getFrameData()[5]; } uint16_t IPV4RxFrame::getSrcPort() { return (getFrameData()[6] << 8) + getFrameData()[7]; } uint8_t IPV4RxFrame::getProtocol() { return getFrameData()[8]; } uint8_t IPV4RxFrame::getStatus() { return getFrameData()[9]; } // markers to read data from packet array. this is the index, so the 12th item in the array uint8_t IPV4RxFrame::getDataOffset() { return 10; } uint16_t IPV4RxFrame::getDataLength() { return getPacketLength() - getDataOffset() - 1; }