driver for the WNC M14A2A Cellular Data Module

Revision:
0:6a2d96c2a520
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WNC14A2AInterface/WNC14A2AInterface.h	Tue Feb 06 16:10:48 2018 +0000
@@ -0,0 +1,443 @@
+/**
+* copyright (c) 2017-2018, James Flynn
+* SPDX-License-Identifier: Apache-2.0
+*/
+
+/*
+* 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.
+*/
+
+/**
+*  @file WNC14A2AInterface.h
+*  @brief Implements a standard NetworkInterface class for use with WNC M14A2A 
+*  data module. 
+*
+*  @author James Flynn
+* 
+*  @date 1-Feb-2018
+*  
+*/
+ 
+#ifndef WNC14A2A_INTERFACE_H
+#define WNC14A2A_INTERFACE_H
+
+#include <stdint.h>
+
+#include "mbed.h"
+#include "Callback.h"
+#include "WNCDebug.h"
+#include "WncControllerK64F/WncControllerK64F.h"
+
+#define WNC14A2A_SOCKET_COUNT 5
+
+typedef struct smsmsg_t {
+        string number;
+        string date;
+        string time;
+        string msg;
+    } IOTSMS;
+
+typedef struct socket_t {
+        int socket;                         //index of this socket
+        string url;
+        SocketAddress addr;                 //hold info for this socket
+        bool opened;                        //has the socket been opened
+        bool _wnc_opened;                   //has the socket been opened
+        int proto;                          //this is a TCP or UDP socket
+        void (*_callback)(void*);           //callback used with attach
+        void *_cb_data;                     //callback data to be returned
+    } WNCSOCKET;
+
+#define WNC_DEBUG   0           //1=enable the WNC startup debug output
+                                //0=disable the WNC startup debug output
+#define STOP_ON_FE  1           //1=hang forever if a fatal error occurs
+                                //0=simply return failed response for all socket calls
+#define DISPLAY_FE  1           //1 to display the fatal error when it occurs
+                                //0 to NOT display the fatal error
+#define RESETON_FE  0           //1 to cause the MCU to reset on fatal error
+                                //0 to NOT reset the MCU
+
+#define APN_DEFAULT             "m2m.com.attz"
+                        
+/** Error Handling macros & data
+*   @brief  The macros CHK_WNCFE is used to check if a fatal error has occured. If it has
+*           then execute the action specified: fail, void, null, resume
+*
+*    CHK_WNCFE( condition-to-check, fail|void|null|resume )
+*
+*     'fail'   if you want to FATAL_WNC_ERROR will be called.  
+*     'void'   if you want to execute a void return
+*     'null'   if you want to execute a null return
+*     'resume' if you simply want to resume program execution
+*
+*  There are several settings that control how FATAL_WNC_ERROR behaves:
+*      1) RESETON_FE determines if the system will reset or hang.
+*      2) DISPLAY_FE determine if an error message is generated or not
+*
+*  The DISPLAY_FE setting determines if a failure message is displayed. 
+*  If set to 1, user sees this messageo:
+*
+*      WNC FAILED @ source-file-name:source-file-line-number
+*
+*  if not set, nothing is displayed.
+*/
+
+#define FATAL_FLAG  WncController::WNC_NO_RESPONSE
+#define WNC_GOOD    WncController::WNC_ON
+
+#define RETfail return -1
+#define RETvoid return
+#define RETnull return NULL
+#define RETresume   
+
+#define DORET(x) RET##x
+
+#define TOSTR(x) #x
+#define INTSTR(x) TOSTR(x)
+#define FATAL_STR (char*)(__FILE__ ":" INTSTR(__LINE__))
+
+#if RESETON_FE == 1   //reset on fatal error
+#define MCURESET     ((*((volatile unsigned long *)0xE000ED0CU))=(unsigned long)((0x5fa<<16) | 0x04L))
+#define RSTMSG       "RESET MCU! "
+#else
+#define MCURESET
+#define RSTMSG       ""
+#endif
+
+#if DISPLAY_FE == 1  //display fatal error message
+#define PFE     {if(_debugUart)_debugUart->printf((char*)RSTMSG "\r\n>>WNC FAILED @ %s\r\n", FATAL_STR);}
+#else
+#define PFE
+#endif
+
+#if STOP_ON_FE == 1  //halt cpu on fatal error
+#define FATAL_WNC_ERROR(v)  {_fatal_err_loc=FATAL_STR;PFE;MCURESET;while(1);}
+#else
+#define FATAL_WNC_ERROR(v)  {_fatal_err_loc=FATAL_STR;PFE;DORET(v);}
+#endif
+
+#define CHK_WNCFE(x,y)    if( x ){FATAL_WNC_ERROR(y);}
+
+#define MAX_SMS_MSGS    3
+
+using namespace WncController_fk;
+ 
+/** WNC14A2AInterface class
+ *  Implementation of the NetworkInterface for WNC14A2A 
+ */
+class WNC14A2AInterface : public NetworkStack, public CellularInterface
+{
+public:
+    /** WNC14A2AInterface Constructor.
+     * @param optionally include a pointer to WNCDEBUG object for 
+     * debug information to be displayed.
+     */
+    WNC14A2AInterface(WNCDebug *_dbgUart = NULL);
+    virtual ~WNC14A2AInterface();
+
+    /** Set the cellular network credentials
+     *
+     *  @param apn      Optional, APN of network
+     *  @param user     Optional, username --not used--
+     *  @param pass     Optional, password --not used--
+     *  @return         nsapi_error_t
+     */
+    virtual nsapi_error_t set_credentials(const char *apn = 0,
+            const char *username = 0, const char *password = 0);
+ 
+    /** Connect to the network
+     *
+     *  @param apn      Optional, APN of network
+     *  @param user     Optional, username --not used--
+     *  @param pass     Optional, password --not used--
+     *  @return         nsapi_error_t
+     */
+    virtual nsapi_error_t connect(const char *apn,
+            const char *username = 0, const char *password = 0);
+ 
+    /** Connect to the network (no parameters)
+     *
+     *  @return         nsapi_error_t
+     */
+    virtual nsapi_error_t connect();
+
+    /** disconnect from the network
+     *
+     *  provided for completness, but function does nothing becase
+     *  WNC part can not disconnect from network once connected.
+     *
+     *  @return         nsapi_error_t
+     */
+    virtual nsapi_error_t disconnect();
+ 
+    /** Get the IP address of WNC device. From NetworkStack Class
+     *
+     *  @return         IP address string or null 
+     */
+    virtual const char *get_ip_address();
+ 
+    /** Get the network assigned IP address.
+     *
+     *  @return         IP address or null 
+     */
+    const char *get_my_ip_address();
+
+    /** Get the MAC address of the WNC device.  
+     *
+     *  @return         MAC address of the interface
+     */
+    virtual const char *get_mac_address();
+ 
+    /** Attach a callback function for when a SMS is recevied
+     *
+     *  @param          function pointer to call
+     */
+    void sms_attach(void (*callback)(IOTSMS *));
+
+    /** Set the level of Debug output
+     *
+     *  @param          bit field 
+     *         basic AT command info= 0x01
+     *         more AT command info = 0x02
+     *         mbed driver info     = 0x04
+     *         dump buffers         = 0x08
+     *         all debug            = 0x0f
+     */
+    void doDebug(int v);
+
+    /** Query registered state of WNC
+     *
+     *  @return         true if registerd, false if not 
+     */
+    bool registered();
+
+    /** Start the SMS monitoring service
+     */
+    void sms_start(void);
+
+    /** start listening for incomming SMS messages
+     *
+     *  @param time in msec to check
+     */
+    void sms_listen(uint16_t=1000);         // Configure device to listen for text messages 
+        
+    /** retrieve a SMS message
+     *
+     *  @param          pointer to an array of IOTSMS messages
+     */
+    int getSMS(IOTSMS **msg);
+
+    /** send a SMS message
+     *
+     *  @param          a string containing number to send message to
+     *  @param          a string containing message to send
+     *  @return         true on success, 0 on failure
+     */
+    int sendIOTSms(const string&, const string&);
+
+    /** return this devices SMS number
+     *
+     *  @brief The IOTSMS number used, isn't phone number, it is device ICCID.  
+     *
+     *  @return          this devices IOTSMS number
+     */
+    char* getSMSnbr();
+
+
+protected:
+
+    /** Get Host IP by name. 
+     *
+     *  @return         nsapi_error_t
+     */
+    virtual nsapi_error_t gethostbyname(const char* name, SocketAddress *address, nsapi_version_t version);
+
+
+    /** return a pointer to the NetworkStack object
+     *
+     *  @return          The underlying NetworkStack object
+     */
+    virtual NetworkStack *get_stack();
+
+    /** Open a socket. 
+     *
+     *  @param handle       Handle in which to store new socket
+     *  @param proto        Type of socket to open, NSAPI_TCP or NSAPI_UDP
+     *  @return             0 on success, negative on failure
+     */
+    virtual int socket_open(void **handle, nsapi_protocol_t proto);
+ 
+    /** Close the socket. 
+     *
+     *  @param handle       Socket handle
+     *  @return             0 on success, negative on failure
+     */
+    virtual int socket_close(void *handle);
+ 
+    /** Bind a server socket to a specific port.
+     *
+     *  @brief              NOT SUPPORTED
+     *  @param handle       Socket handle
+     *  @param address      address to listen for incoming connections on 
+     *  @return             NSAPI_ERROR_UNSUPPORTED;
+     */
+    virtual int socket_bind(void *handle, const SocketAddress &address);
+ 
+    /** Start listening for incoming connections.
+     *
+     *  @brief              NOT SUPPORTED
+     *  @param handle       Socket handle
+     *  @param backlog      Number of pending connections that can be queued up at any
+     *                      one time [Default: 1]
+     *  @return             NSAPI_ERROR_UNSUPPORTED;
+     */
+    virtual int socket_listen(void *handle, int backlog);
+ 
+    /** Accept a new connection.
+     *
+     *  @brief              NOT SUPPORTED
+     *  @return             NSAPI_ERROR_UNSUPPORTED;
+     */
+    virtual int socket_accept(nsapi_socket_t server,
+            nsapi_socket_t *handle, SocketAddress *address=0);
+ 
+    /** Connects this socket to the server.
+     *
+     *  @param handle       Socket handle
+     *  @param address      SocketAddress 
+     *  @return             0 on success, negative on failure
+     */
+    virtual int socket_connect(void *handle, const SocketAddress &address);
+ 
+    /** Send data to the remote host.
+     *
+     *  @param handle       Socket handle
+     *  @param data         buffer to send
+     *  @param size         length of buffer
+     *  @return             Number of bytes written or negative on failure
+     *
+     *  @note This call is blocking. 
+     */
+    virtual int socket_send(void *handle, const void *data, unsigned size);
+ 
+    /** Receive data from the remote host.
+     *
+     *  @param handle       Socket handle
+     *  @param data         buffer to store the recived data
+     *  @param size         bytes to receive
+     *  @return             received bytes received, negative on failure
+     *
+     *  @note This call is not-blocking 
+     */
+    virtual int socket_recv(void *handle, void *data, unsigned size);
+ 
+    /** Send a packet to a remote endpoint.
+     *
+     *  @param handle       Socket handle
+     *  @param address      SocketAddress
+     *  @param data         data to send
+     *  @param size         number of bytes to send
+     *  @return the         number of bytes sent or negative on failure
+     *
+     *  @note This call is blocking.
+     */
+    virtual int socket_sendto(void *handle, const SocketAddress &address, const void *data, unsigned size);
+ 
+    /** Receive packet remote endpoint
+     *
+     *  @param handle       Socket handle
+     *  @param address      SocketAddress 
+     *  @param buffer       buffer to store data to
+     *  @param size         number of bytes to receive
+     *  @return the         number bytes received or negative on failure
+     *
+     *  @note This call is not-blocking.
+     */
+    virtual int socket_recvfrom(void *handle, SocketAddress *address, void *buffer, unsigned size);
+ 
+    /** Register a callback on state change of the socket
+     *
+     *  @param handle       Socket handle
+     *  @param callback     Function to call on state change
+     *  @param data         Argument to pass to callback
+     *
+     *  @note Callback may be called in an interrupt context.
+     */
+    virtual void socket_attach(void *handle, void (*callback)(void *), void *data);
+    
+    /** get the status of internal errors
+     *
+     *  @brief Called after any WNC14A2A operation to determine error specifics 
+     *  @param none.
+     */
+    uint16_t wnc14a2a_chk_error(void) { return _errors; }
+
+
+private:
+    //! WncController Class for managing the 14A2a hardware
+    friend class WncControllerK64F;  
+
+    bool     m_wncpoweredup;                //track if WNC has been power-up
+    unsigned m_debug;
+
+    WncIpStats myNetStats;                  //maintaint the network statistics
+    WncControllerK64F_fk::WncControllerK64F *_pwnc; //pointer to the WncController instance
+
+    int m_active_socket;                    // a 'pseudo' global to track the active socket
+    WNCDebug *_debugUart;                     // Serial object for parser to communicate with radio
+    char *_fatal_err_loc;                   // holds string containing location of fatal error
+    nsapi_error_t _errors;
+
+    bool m_smsmoning;                       // Track if the SMS monitoring thread is running
+    EventQueue sms_queue;                   // Queue used to schedule for SMS checks
+    EventQueue isr_queue;                   // Queue used to schedule for receiving data
+    void (*_sms_cb)(IOTSMS *);              // Callback when text message is received. User must define this as 
+                                            // a static function because I'm not handling an object offset
+    IOTSMS m_MsgText, m_MsgText_array[MAX_SMS_MSGS];       // Used to pass SMS message to the user
+    struct WncController::WncSmsList m_smsmsgs;            //use the WncSmsList structure to hold messages
+
+    void handle_sms_event();                // SMS tx/rx handler
+    void wnc_isr_event();                   // Simulated ISR
+    int  rx_event();                        // receive data handler
+    int  tx_event();                        // tx data handler
+
+    char _mac_address[NSAPI_MAC_SIZE];      // local Mac
+    void _dbOut(const char *format, ...);
+    void _dbDump_arry( const uint8_t* data, unsigned int size );
+
+    // Receive Interrupt simulation to enabled non-blocking operation
+    uint8_t *m_recv_dptr;
+    int      m_recv_wnc_state;
+    int      m_recv_events;
+    int      m_recv_socket;
+    int      m_recv_timer;
+    unsigned m_recv_orig_size;
+    uint32_t m_recv_req_size, m_recv_total_cnt;
+    uint32_t m_recv_return_cnt;
+    void    (*m_recv_callback)(void*);
+    void     *m_recv_cb_data;
+
+    // Transmit Interrupt simulation to enabled non-blocking operation
+    uint8_t *m_tx_dptr;
+    int      m_tx_wnc_state;
+    int      m_tx_socket;
+    unsigned m_tx_orig_size;
+    uint32_t m_tx_req_size, m_tx_total_sent;
+    void    (*m_tx_callback)(void*);
+    void     *m_tx_cb_data;
+
+};
+
+#endif
+