Implementation of the CellularInterface for u-blox C030 boards with N2xx modems. Note: requires the N211 module firmware to be at least 06.57 A01.02.

Dependents:   example-ublox-cellular-interface HelloMQTT example-ublox-cellular-interface_r410M example-ublox-mbed-client ... more

Revision:
6:658419981430
Parent:
4:2bf3875a13f1
Child:
7:69e676f4af84
Child:
9:f6d022f5c4f5
--- a/UbloxATCellularInterfaceN2xx.cpp	Tue Aug 22 16:37:41 2017 +0100
+++ b/UbloxATCellularInterfaceN2xx.cpp	Wed Sep 13 15:57:06 2017 +0100
@@ -299,49 +299,59 @@
 nsapi_size_or_error_t UbloxATCellularInterfaceN2xx::sendto(SockCtrl *socket, const SocketAddress &address, const char *buf, int size) {
     nsapi_size_or_error_t sent = NSAPI_ERROR_DEVICE_ERROR;
     int id;
-    
-    tr_debug("Malloc %d * 2 + 1 bytes", size);
-    char *str = (char *) malloc((size * 2) + 1);
-    if (str == NULL) {
-        tr_error("Nope, could allocate it!");
+        
+    char *dataStr = (char *) malloc((size * 2) + 1);
+    if (dataStr == NULL) {
+        tr_error("Couldn't allocate memory for hex string conversion.");
         return NSAPI_ERROR_NO_MEMORY;
     }
     
     tr_debug("Converting byte array to hex string");
-    bin_to_hex(buf, size, str);
+    bin_to_hex(buf, size, dataStr);
     tr_debug("Got hex string");
     
-    LOCK();
+    
         
     // AT+NSOSTF= socket, remote_addr, remote_port, length, data
-    tr_debug("Writing AT+NSOSTF=<sktid>,<ipaddr>,<port>,<flags>,<size>,<hex string> command...");
-    char cmd[50];
-    int cmdsize = sprintf(cmd, "AT+NSOSTF=%d,%s,%d,0x0,%d,", socket->modem_handle, address.get_ip_address(), address.get_port(), size);    
-    if (_at->write(cmd, cmdsize+1) && sendATChopped(str)) {
-        tr_debug("Reading back the Sent Size...");
+    tr_debug("Writing AT+NSOSTF=<sktid>,<ipaddr>,<port>,<flags>,<size>,<hex string> command...");    
+    char *cmdStr = (char *) malloc(50);
+    if (cmdStr == NULL) {
+        tr_error("Couldn't allocate memory for AT cmd string.");
+        return NSAPI_ERROR_NO_MEMORY;
+    }
+            
+    int cmdsize = sprintf(cmdStr, "AT+NSOSTF=%d,%s,%d,0x0,%d,", socket->modem_handle, address.get_ip_address(), address.get_port(), size);    
+    tr_debug("%s", cmdStr);
+    
+    LOCK();
+    if (_at->write(cmdStr, cmdsize) && sendATChopped(dataStr)) 
+    {
+        tr_debug("Finished sending AT+NSOST comamnd, reading back the 'sent' size...");
         if (_at->recv("%d,%d\n", &id, &sent) && _at->recv("OK")) {            
-            tr_debug("Received %d bytes on socket %d", sent, id);
+            tr_debug("Sent %d bytes on socket %d", sent, id);
         } else {
             tr_error("Didn't get the Sent size or OK");
         }
     } else {
         tr_error("Didn't send the AT command!");
     }
+    UNLOCK();  
 
-    UNLOCK();  
-    free(str);
-    
+    free(cmdStr);    
+    free(dataStr);
+       
     return sent;
 }
 
 bool UbloxATCellularInterfaceN2xx::sendATChopped(const char *cmd)
 {
     char buff[SENDTO_CHUNK_SIZE];
+    tr_debug("Chopping up large AT text of %d characters.", strlen(cmd));
+    
     while (*cmd != '\0')
     {
         int i=0;
         
-        tr_debug("Copying up to 50 chars... ");
         for (i=0; i<SENDTO_CHUNK_SIZE; i++) {
             buff[i] = *cmd;
             
@@ -352,14 +362,15 @@
             // still more characters to copy, so move along
             cmd++;
         }
-        tr_debug("Copied %d chars. ", i);
-        
+       
+       // if we are at the end of the line, use the send command to 
+       // provide the \r\n terminator for the AT command
         if (*cmd == '\0') {
-            tr_debug("send()\n");
+            tr_debug("send(%d): %s", i, buff);
             if (!_at->send(buff))
                 return false;
         } else {
-            tr_debug("write()\n");
+            tr_debug("write(50): %s", buff);
             if (!_at->write(buff, 50))
                 return false;
         }
@@ -404,32 +415,32 @@
     char *buf = (char *) data;
     nsapi_size_t read_blk;
     nsapi_size_t count = 0;
-    char ipAddress[NSAPI_IP_SIZE];
-    
+    int at_timeout = _at_timeout;
+        
     char * tmpBuf = NULL;
 
     Timer timer;
     SockCtrl *socket = (SockCtrl *) handle;
-    int at_timeout = _at_timeout;
 
-    tr_debug("socket_recvfrom(0x%08x, 0x%08x, %d)", (unsigned int) handle,
-             (unsigned int) data, size);
+    tr_debug("socket_recvfrom(0x%08x, 0x%08x, SIZE=%d)", (unsigned int) handle, (unsigned int) data, size);
 
     MBED_ASSERT (check_socket(socket));
-
     timer.start();
 
     while (success && (size > 0)) {
         LOCK();
+        at_timeout = _at_timeout;
         at_set_timeout(1000);
-
-        read_blk = socket->pending;
-        if (read_blk > MAX_READ_SIZE) {
-            read_blk = MAX_READ_SIZE;
+        
+        read_blk = MAX_READ_SIZE;
+        if (read_blk > size) {
+            read_blk = size;
         }
-        if (read_blk > 0) {
-            memset (ipAddress, 0, sizeof (ipAddress)); // Ensure terminator
-
+        
+        if (socket->pending > 0) {
+            tr_debug("Socket 0x%08x: modem handle %d has %d byte(s) pending",
+                     (unsigned int) socket, socket->modem_handle, socket->pending);
+    
             tmpBuf = (char *) malloc(read_blk);
             if (tmpBuf == NULL) {
                 return NSAPI_ERROR_NO_MEMORY;
@@ -437,48 +448,62 @@
             
             // call the AT helper function to get the bytes
             nsapi_error_size = receivefrom(socket->modem_handle, address, read_blk, tmpBuf);
-                
+                    
             if (nsapi_error_size >= 0) {
                 memcpy(buf, tmpBuf, nsapi_error_size);
 
-                socket->pending -= read_blk;
-                tr_debug("Socket 0x%08x: modem handle %d now has only %d byte(s) pending",
-                         (unsigned int) socket, socket->modem_handle, socket->pending);
-
+                if (read_blk != (uint) nsapi_error_size)
+                    tr_error("Requested size is not the same as the returned size!");
+                
+                socket->pending -= nsapi_error_size;                
                 count += nsapi_error_size;
                 buf += nsapi_error_size;
-                size = 0; // A UDP packet arrives in one piece, so this means DONE.
+                size -= nsapi_error_size;
+                
+                if (((uint)nsapi_error_size < read_blk) || (nsapi_error_size == MAX_READ_SIZE))
+                    size = 0;     // If we've received less than we asked for, or
+                                  // the max size, then a whole UDP packet has arrived and
+                                  // this means DONE.
             } else {
-              // Should never fail to read when there is pending data
+                // Should never fail to read when there is pending data
                 success = false;
             }
         } else if (timer.read_ms() < SOCKET_TIMEOUT) {
             // Wait for URCs
+            tr_debug("Waiting for URC...");
             _at->recv(UNNATURAL_STRING);
         } else {
-            // Timeout with nothing received
-            nsapi_error_size = NSAPI_ERROR_WOULD_BLOCK;
-            success = false;
+            tr_debug("Nothing pending...");
+            if (count == 0) {
+                tr_debug("Nothing received, so timeout with block");
+                // Timeout with nothing received
+                nsapi_error_size = NSAPI_ERROR_WOULD_BLOCK;
+                success = false;
+            }
+            
+            // quit while loop
+            break;
         }
-
+        
         at_set_timeout(at_timeout);
         UNLOCK();
     }
     timer.stop();
 
     if (success) {
+        tr_debug("socket_recvfrom: %d SUCCESS!", count);
         nsapi_error_size = count;
+    } else {
+       tr_debug("socket_recvfrom: FAILED");
     }
-
-    tr_debug("socket_recvfrom: %d \"%*.*s\"", count, count, count, buf - count);
-
+    
     return nsapi_error_size;
 }
 
 nsapi_size_or_error_t UbloxATCellularInterfaceN2xx::receivefrom(int modem_handle, SocketAddress *address, int length, char *buf) {
     char ipAddress[NSAPI_IP_SIZE];
     nsapi_size_or_error_t size;
-    
+
     memset (ipAddress, 0, sizeof (ipAddress)); // Ensure terminator
     
     if (length > MAX_READ_SIZE) {
@@ -489,9 +514,14 @@
     if (tmpBuf == NULL)
         return NSAPI_ERROR_NO_MEMORY;
     
-    LOCK();      
+    int remaining;
+    
+    _at->debug_on(false); // ABSOLUTELY no time for debug here if you want to
+                      // be able to read packets of any size without
+                      // losing characters in UARTSerial
     
     // Ask for x bytes from Socket 
+    tr_debug("Requesting to read back %d bytes from socket %d", length, modem_handle);
     if (_at->send("AT+NSORF=%d,%d", modem_handle, length)) {
         unsigned int id, port;
         
@@ -508,22 +538,24 @@
                 // convert to bytes
                 hex_to_bin(tmpBuf, buf, size);
              
-                // read the "remaining" value
-                char remaining[4];                
-                if (!_at->recv(",%3[^\n]\n", remaining)) {
+                // read the "remaining" value               
+                if (!_at->recv(",%d\n", &remaining)) {
+                    tr_error("Failed reading the 'remaining' value after the received data.");
                     size = NSAPI_ERROR_DEVICE_ERROR;
                 }
             }
         }
         
         // we should get the OK (even if there is no data to read)
-        if (!_at->recv("OK")) {
+        if (_at->recv("OK")) {          
+            tr_debug("Socket RecvFrom: Read %d bytes, %d bytes remaining.", size, remaining);
+        } else {
+            tr_error("Socket RecvFrom: Didn't receive OK from AT+NSORF command.");
             size = NSAPI_ERROR_DEVICE_ERROR;
         }
     }
     
-    UNLOCK();
-    
+    _at->debug_on(_debug_trace_on);
     free(tmpBuf);
     
     return size;