Poerting the Xbee library to use teh wifi functionality of the LPC4088.
Dependents: XBee_WiFi_EA_LPC4088
Fork of XBee by
Diff: XBeeWiFi.cpp
- Revision:
- 2:6efb3541af61
- Child:
- 3:8573b122fa84
diff -r e3b2027e685c -r 6efb3541af61 XBeeWiFi.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/XBeeWiFi.cpp Fri Jul 29 16:22:15 2011 +0000 @@ -0,0 +1,438 @@ +/** + * XBee Wi-Fi library for mbed + * Copyright (c) 2011 Hiroshi Suga + * Released under the MIT License: http://mbed.org/license/mit + */ + +/** @file + * @brief Weather Station + */ + +#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) : XBee(p_tx, p_rx) { +} + +int XBeeWiFi::setup (int security, const char *ssid, const char *pin) { + int len; + uint8_t cmd[2], val[32]; + AtCommandRequest atRequest; + + // security type + memcpy(cmd, "EE", 2); + val[0] = security; + atRequest.setCommand(cmd); + atRequest.setCommandValue(val); + atRequest.setCommandValueLength(1); + send(atRequest); + getWiResponse(AT_COMMAND_RESPONSE); + + if (security != SECURITY_OPEN) { + // SSID + memcpy(cmd, "ID", 2); + len = strlen(ssid); + memcpy(val, ssid, len); + atRequest.setCommand(cmd); + atRequest.setCommandValue(val); + atRequest.setCommandValueLength(len); + send(atRequest); + getWiResponse(AT_COMMAND_RESPONSE); + + // PIN + memcpy(cmd, "PK", 2); + len = strlen(pin); + memcpy(val, pin, len); + atRequest.setCommand(cmd); + atRequest.setCommandValue(val); + atRequest.setCommandValueLength(len); + send(atRequest); + getWiResponse(AT_COMMAND_RESPONSE); + } + + return 0; +} + +int XBeeWiFi::setup (const char *ssid) { + return setup(SECURITY_OPEN, ssid, NULL); +} + +int XBeeWiFi::reset () { + // RESET + uint8_t cmd[2] = {'N', 'R'}; + AtCommandRequest atRequest; + + atRequest.setCommand(cmd); + send(atRequest); + + return getWiResponse(AT_COMMAND_RESPONSE); +} + +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); + send(atRequest); + + return getWiResponse(AT_COMMAND_RESPONSE); +} + +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); + send(atRequest); + getWiResponse(AT_COMMAND_RESPONSE); + + // 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)); + send(atRequest); + getWiResponse(AT_COMMAND_RESPONSE); + + // 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)); + send(atRequest); + getWiResponse(AT_COMMAND_RESPONSE); + + // 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)); + send(atRequest); + getWiResponse(AT_COMMAND_RESPONSE); + + // name server + _nameserver = nameserver; + + return 0; +} + +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); + send(atRequest); + + return getWiResponse(AT_COMMAND_RESPONSE); +} + +int XBeeWiFi::getStatus () { + // AI + uint8_t cmd[2] = {'A', 'I'}; + AtCommandRequest atRequest; + + atRequest.setCommand(cmd); + send(atRequest); + + return getWiResponse(AT_COMMAND_RESPONSE); +} + +int XBeeWiFi::getWiResponse (int apiId, int timeout) { + AtCommandResponse atResponse; + + if (readPacket(timeout)) { + if (getResponse().getApiId() == apiId) { + getResponse().getAtCommandResponse(atResponse); + + if (atResponse.isOk()) { + + return atResponse.getValue()[0]; + + } else { + printf("Command return error code: %x\r\n", atResponse.getStatus()); + } + } else { + printf("Expected AT response but got %x\r\n", getResponse().getApiId()); + } + } else { + if (getResponse().isError()) { + printf("Error reading packet. Error code: %x\r\n", getResponse().getErrorCode()); + } else { + printf("No response from radio"); + } + } + + return -1; +} + +#ifdef USE_WIFIDNS +int XBeeWiFi::getHostByName (const char* name, IpAddr &addr) { + char buf[1024]; + int len; + IPv4TransmitRequest dnsRequest; + AtCommandRequest atRequest; + AtCommandResponse atResponse; + + if (!strcmp(name, "localhost")) { + addr = IpAddr(127, 0, 0, 1); + return 0; + } + + len = createDnsRequest(name, buf); + + // send DNS request + dnsRequest.setAddress(_nameserver); + dnsRequest.setDstPort(53); + dnsRequest.setSrcPort(1243); + dnsRequest.setProtocol(PROTOCOL_UDP); + dnsRequest.setPayload((uint8_t*)buf); + dnsRequest.setPayloadLength(len); + send(dnsRequest); + + if (getWiResponse(IPv4_TRANSMIT_STATUS) == 0) { + // recv DNS request + if (getWiResponse(IPv4_RX_FRAME, 30000) != -1) { + getResponse().getAtCommandResponse(atResponse); + if (atResponse.isOk()) { + return getDnsResponse(atResponse.getValue(), atResponse.getValueLength(), addr); + } + } + } + + 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; + len = sizeof(dnsHeader); + + // DNS question + num = (int)strchr(name, '.'); + while (num) { + num = num - (int)name; + buf[len] = num; + len ++; + strncpy(&buf[len], name, num); + name = name + num; + len = len + num; + num = (int)strchr(name, '.'); + } + + num = (int)strlen(name); + if (num) { + buf[len] = num; + len ++; + strncpy(&buf[len], name, num); + len = len + num + 1; + } + + dnsEnd = (DnsQuestionEnd*)&buf[len]; + dnsEnd->type = REVERSE_ENDIAN(DNS_QUERY_A); + dnsEnd->clas = REVERSE_ENDIAN(DNS_CLASS_IN); + + return len + sizeof(dnsEnd); +} + +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, uint8_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, uint8_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(uint8_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]; + } +} + +uint8_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; +} + + +IpAddr& IPV4RxFrame::getSrcAddress() { + _srcAddr = IpAddr(getFrameData()[4], getFrameData()[5], getFrameData()[6], getFrameData()[7]); + return _srcAddr; +} + +uint16_t IPV4RxFrame::getDstPort() { + return (getFrameData()[8] << 8) + getFrameData()[9]; +} + +uint16_t IPV4RxFrame::getSrcPort() { + return (getFrameData()[10] << 8) + getFrameData()[11]; +} + +uint8_t IPV4RxFrame::getProtocol() { + return getFrameData()[12]; +} + +uint8_t IPV4RxFrame::getStatus() { + return getFrameData()[13]; +} + +// markers to read data from packet array. this is the index, so the 12th item in the array +uint8_t IPV4RxFrame::getDataOffset() { + return 14; +} + +uint8_t IPV4RxFrame::getDataLength() { + return getPacketLength() - getDataOffset() - 1; +}