📄 gprs.c
字号:
// ----------------------------------------------------------------------------// Copyright 2006-2007, Martin D. Flynn// All rights reserved// ----------------------------------------------------------------------------//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at// // http://www.apache.org/licenses/LICENSE-2.0// // Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.//// ----------------------------------------------------------------------------// Description:// GPRS data transport.// Notes:// - This implementation supports UDP/TCP communications with a DMTP server// and was designed to work with the BlueTree M2M Express wireless GPRS modem// (which is really a Wavecom modem internally and thus may work with any // Wavecom modem, but no other modem has been tested).// ---// Change History:// 2006/01/23 Martin D. Flynn// -Initial release// 2007/01/28 Martin D. Flynn// -Initial support for Window CE (not yet fully functional). On most// Windows CE platforms this module may not be neccessary as the Windows CE// environment may already handle GPRS/CDMA connections, in which case the// 'socket' transport media may be used.// ----------------------------------------------------------------------------#include "stdafx.h" // TARGET_WINCE#include "custom/defaults.h"// ----------------------------------------------------------------------------#include <stdio.h>#include <string.h>//#include <unistd.h>//#include <fcntl.h>#include <ctype.h>//#include <errno.h>//#include <termios.h>//#include <sys/select.h>//#include <time.h>#include <stdlib.h>//#include <pthread.h>#include "custom/log.h"#include "custom/transport/gprs.h"#include "tools/stdtypes.h"#include "tools/strtools.h"#include "tools/bintools.h"#include "tools/utctools.h"#include "tools/comport.h"#include "tools/buffer.h"#include "tools/threads.h"#include "base/props.h"#include "base/propman.h"#include "base/packet.h"// ----------------------------------------------------------------------------// Note: This implementation was tested to work with the Following modem(s):// - BlueTree M2M Express GPRS (internal WaveCom modem)// ----------------------------------------------------------------------------#define DNS_NULL "0.0.0.0"#define MODEM_SPEED_BPS BPS_115200 // default speedvoid blueInitialize();void blueResetConnection();const char *blueGetDataHost();Int16 blueGetDataPort();const char *blueGetDNS(int ndx);const char *blueGetApnName();const char *blueGetApnServer();const char *blueGetApnUser();const char *blueGetApnPassword();utBool blueIsOpen();utBool blueOpenCom();void blueCloseCom();int blueConnect();utBool blueOpenTCPSocket();utBool blueIsTCPSocketOpen();utBool blueCloseSocket();int blueWrite(const char *buf, int bufLen);int blueWriteString(const char *msg);int blueWriteStringFmt(const char *fmt, ...);int blueRead(char *resp, int respLen, long timeoutMS);int blueReadString(char *resp, int respLen, long timeoutMS);utBool blueSendDatagram(char *buf, int bufLen);utBool bluePing(const char *server);// ----------------------------------------------------------------------------/* transport structure */typedef struct { TransportType_t type; utBool isOpen; // add whatever is needed to provide platform specific transport requirements} GprsTransport_t;static GprsTransport_t gprsXport;// ----------------------------------------------------------------------------static TransportFtns_t gprsXportFtns = { MEDIA_GPRS, "XportGPRS" };// The size of the datagram buffer is arbitrary, however the amount of // data transmitted in a single datagram should not be larger than the MTU// to avoid possible fragmentation which could result in a higher possibility// of data loss.static UInt8 gprsDatagramData[2000];static Buffer_t gprsDatagramBuffer;// ----------------------------------------------------------------------------static const char *gprs_transportTypeName(TransportType_t type){ switch (type) { case TRANSPORT_NONE : return "None"; case TRANSPORT_SIMPLEX : return "Simplex"; case TRANSPORT_DUPLEX : return "Duplex"; default : return "Unknown"; }}// ----------------------------------------------------------------------------/* flush input buffer */static void gprs_transportReadFlush(){ // NO-OP}/* return true if transport is open */static utBool gprs_transportIsOpen(){ // this may be called by threads other than the protocol thread. return gprsXport.isOpen;}/* close transport */static utBool gprs_transportClose(utBool sendUDP){ if (gprsXport.isOpen) { logDEBUG(LOGSRC,"%s Transport close ...\n\n", gprs_transportTypeName(gprsXport.type)); utBool rtn = utTrue; /* check for datagram transmission */ if (sendUDP && (gprsXport.type == TRANSPORT_SIMPLEX)) { // transmit queued datagram Buffer_t *bf = &gprsDatagramBuffer; UInt8 *data = BUFFER_PTR(bf); int dataLen = BUFFER_DATA_LENGTH(bf); utBool ok = blueSendDatagram((char*)data, dataLen); rtn = ok; } /* transport is closed */ gprsXport.type = TRANSPORT_NONE; gprsXport.isOpen = utFalse; /* reset buffers */ binResetBuffer(&gprsDatagramBuffer); return rtn; } else { /* wasn't open */ return utFalse; }}/* open transport */static utBool gprs_transportOpen(TransportType_t type){ /* close, if already open */ if (gprsXport.isOpen) { // it shouldn't already be open logWARNING(LOGSRC,"Transport seems to still be open!"); gprs_transportClose(utFalse); } /* establish ISP connection */ // we stay here until we can connect (or until timeout) UInt32 connectTimoutSec = MINUTE_SECONDS(5); TimerSec_t connectErrorTimer = utcGetTimer(); while (utTrue) { int err = blueConnect(); if (err > 0) { // success break; } else if (err < 0) { // critical error (unable to open serial port) return utFalse; } else if (utcIsTimerExpired(connectErrorTimer,connectTimoutSec)) { return utFalse; } logWARNING(LOGSRC,"Retrying connect ..."); threadSleepMS(5000L); } /* open TCP socket */ if (type == TRANSPORT_DUPLEX) { // Duplex if (blueOpenTCPSocket()) { // socket is ready writing/reading gprsXport.type = type; gprsXport.isOpen = utTrue; // fall through to 'true' return below } else { // If we can't open the socket, then the connection is suspect. // close and reopen connection logINFO(LOGSRC,"Unable to open socket"); blueResetConnection(); threadSleepMS(1000L); return utFalse; } } else { // Simplex gprsXport.type = type; gprsXport.isOpen = utTrue; // fall through to 'true' return below } /* reset buffers and return success */ binResetBuffer(&gprsDatagramBuffer); logDEBUG(LOGSRC,"Openned %s Transport ...\n", gprs_transportTypeName(type)); return gprsXport.isOpen; }// ----------------------------------------------------------------------------static int _transportRead(UInt8 *buf, int bufLen){ /* transport not open? */ if (!gprsXport.isOpen) { logERROR(LOGSRC,"Transport is not open"); return -1; } /* cannot read when connecting via Simplex */ if (gprsXport.type == TRANSPORT_SIMPLEX) { logERROR(LOGSRC,"Cannot read from Simplex transport"); return -1; } /* no data was requested */ if (bufLen == 0) { return 0; } /* return bytes read */ int readLen = 0; readLen = blueRead((char*)buf, bufLen, 5000L); return readLen; }/* read packet from transport */static int gprs_transportReadPacket(UInt8 *buf, int bufLen){ UInt8 *b = buf; int readLen, len; /* check minimum 'bufLen' */ if (bufLen < PACKET_HEADER_LENGTH) { logERROR(LOGSRC,"Read overflow"); return -1; } /* read header */ // This will read the header/type/length of a binary encoded packet, or // the '$' and 2 ASCII hex digits of an ASCII encoded packet. len = _transportRead(b, PACKET_HEADER_LENGTH); if (len < 0) { logERROR(LOGSRC,"Read error"); return -1; } else if (len == 0) { logERROR(LOGSRC,"Timeout"); return 0; } /* make sure entire header has been read */ if (len < PACKET_HEADER_LENGTH) { // partial packet read (just close socket) logERROR(LOGSRC,"Read error [len=%d, expected %d]", len, PACKET_HEADER_LENGTH); return -1; } b += PACKET_HEADER_LENGTH; /* read payload */ if (buf[0] == PACKET_ASCII_ENCODING_CHAR) { // ASCII encoded, read until '\r' for (; (b - buf) < bufLen; b++) { len = _transportRead(b, 1); if (len < 0) { logERROR(LOGSRC,"Read error"); return -1; } else if (len == 0) { // timeout (partial packet read) logERROR(LOGSRC,"Timeoout"); return 0; } if (*b == PACKET_ASCII_ENCODING_EOL) { *b = 0; break; } } if ((b - buf) < bufLen) { readLen = (b - buf); } else { // overflow (just close socket) - (unlikely to occur) logERROR(LOGSRC,"Read overflow"); return -1; } } else if (buf[PACKET_HEADER_LENGTH - 1] != 0) { // read 'b[2]' bytes UInt16 payloadLen = (UInt16)buf[PACKET_HEADER_LENGTH - 1]; len = _transportRead(b, payloadLen); if (len < 0) { logERROR(LOGSRC,"Read error"); return -1; } if (len < payloadLen) { // timeout (partial packet read) logERROR(LOGSRC,"Timeout"); //ClientPacketType_t hdrType = CLIENT_HEADER_TYPE(buf[0],buf[1]); //protocolQueueError(0,"%2x%2x", (UInt32)ERROR_PACKET_LENGTH, (UInt32)hdrType); return -1; } readLen = PACKET_HEADER_LENGTH + len; } else { readLen = PACKET_HEADER_LENGTH; } /* return lengtht */ return readLen; }// ----------------------------------------------------------------------------/* write packet to transport */static int gprs_transportWritePacket(const UInt8 *buf, int bufLen){ /* transport not open? */ if (!gprsXport.isOpen) { logERROR(LOGSRC,"Transport is not open"); return -1; } /* nothing specified to write */ if (bufLen == 0) { return 0; } /* write data per transport type */ int len = 0; switch (gprsXport.type) { case TRANSPORT_SIMPLEX: // queue data until the close len = binBufPrintf(&gprsDatagramBuffer, "%*b", bufLen, buf); return len; case TRANSPORT_DUPLEX: len = blueWrite((char*)buf, bufLen); return len; default: logERROR(LOGSRC,"Unknown transport type %d\n", gprsXport.type); return -1; } }// ----------------------------------------------------------------------------static utBool bluePowerOnReset = utTrue;/* initialize transport */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -