Maxim Integrated / Mbed OS MAXREFDES155#

Dependencies:   MaximInterface

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers CC3100.cpp Source File

CC3100.cpp

00001 /*******************************************************************************
00002 * Copyright (C) Maxim Integrated Products, Inc., All Rights Reserved.
00003 *
00004 * Permission is hereby granted, free of charge, to any person obtaining a
00005 * copy of this software and associated documentation files (the "Software"),
00006 * to deal in the Software without restriction, including without limitation
00007 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008 * and/or sell copies of the Software, and to permit persons to whom the
00009 * Software is furnished to do so, subject to the following conditions:
00010 *
00011 * The above copyright notice and this permission notice shall be included
00012 * in all copies or substantial portions of the Software.
00013 *
00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00015 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00017 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
00018 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00019 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00020 * OTHER DEALINGS IN THE SOFTWARE.
00021 *
00022 * Except as contained in this notice, the name of Maxim Integrated
00023 * Products, Inc. shall not be used except as stated in the Maxim Integrated
00024 * Products, Inc. Branding Policy.
00025 *
00026 * The mere transfer of this software does not imply any licenses
00027 * of trade secrets, proprietary technology, copyrights, patents,
00028 * trademarks, maskwork rights, or any other form of intellectual
00029 * property whatsoever. Maxim Integrated Products, Inc. retains all
00030 * ownership rights.
00031 *******************************************************************************/
00032 
00033 #include <cstdio>
00034 #include <cstring>
00035 #include <simplelink.h>
00036 #include <mbed-os/drivers/InterruptIn.h>
00037 #include <mbed-os/platform/mbed_wait_api.h>
00038 #include "CC3100.hpp"
00039 
00040 using std::printf;
00041 using std::strlen;
00042 
00043 static CC3100::State currentState = CC3100::Stopped;
00044 
00045 static mbed::InterruptIn irq(MBED_CONF_APP_CC3100_INTR_PIN);
00046 static mbed::DigitalOut nHIB(MBED_CONF_APP_CC3100_NHIB_PIN, 0);
00047 
00048 static SL_P_EVENT_HANDLER pIrqEventHandler = NULL;
00049 static void * pIrqEventHandlerValue = NULL;
00050 
00051 _SlFd_t sl_IfOpen(const char * ifName, unsigned long flags) {
00052   _SlFd_t fd = NULL;
00053   if (ifName) {
00054     std::sscanf(ifName, "%p", &fd);
00055   }
00056   return fd;
00057 }
00058 
00059 int sl_IfClose(_SlFd_t fd) {
00060   return 0; // Success
00061 }
00062 
00063 int sl_IfRead(_SlFd_t fd, unsigned char * pBuff, int len) {
00064   if (!fd) {
00065     return 0; // Failure
00066   }
00067   std::memset(pBuff, 0xFF, len);
00068   static_cast<CC3100::SPI *>(fd)->transfer(pBuff, len, pBuff);
00069   return len; // Success
00070 }
00071 
00072 int sl_IfWrite(_SlFd_t fd, const unsigned char * pBuff, int len) {
00073   if (!fd) {
00074     return 0; // Failure
00075   }
00076   static_cast<CC3100::SPI *>(fd)->transfer(pBuff, len, NULL);
00077   return len; // Success
00078 }
00079 
00080 int sl_IfRegIntHdlr(SL_P_EVENT_HANDLER InterruptHdl, void * pValue) {
00081   pIrqEventHandler = InterruptHdl;
00082   pIrqEventHandlerValue = pValue;
00083   return 0; // Success
00084 }
00085 
00086 static void interruptHandler(void) {
00087   if (pIrqEventHandler) {
00088     pIrqEventHandler(pIrqEventHandlerValue);
00089   }
00090 }
00091 
00092 void sl_DeviceEnable(void) {
00093   irq.rise(&interruptHandler);
00094   nHIB = 1;
00095 }
00096 
00097 void sl_DeviceDisable(void) {
00098   irq.rise(NULL);
00099   nHIB = 0;
00100 }
00101 
00102 /*!
00103     \brief This function handles general error events indication
00104 
00105     \param[in]      pDevEvent is the event passed to the handler
00106 
00107     \return         None
00108 */
00109 void SimpleLinkGeneralEventHandler(SlDeviceEvent_t * pDevEvent) {
00110   /*
00111    * Most of the general errors are not FATAL are are to be handled
00112    * appropriately by the application
00113    */
00114   printf(" [GENERAL EVENT] \n\r");
00115 }
00116 
00117 /*!
00118     \brief This function handles WLAN events
00119 
00120     \param[in]      pWlanEvent is the event passed to the handler
00121 
00122     \return         None
00123 
00124     \note
00125 
00126     \warning
00127 */
00128 void SimpleLinkWlanEventHandler(SlWlanEvent_t * pWlanEvent) {
00129   if (!pWlanEvent) {
00130     printf(" [WLAN EVENT] NULL Pointer Error \n\r");
00131     return;
00132   }
00133 
00134   switch (pWlanEvent->Event) {
00135   case SL_WLAN_CONNECT_EVENT:
00136     currentState = CC3100::Connected;
00137 
00138     /*
00139      * Information about the connected AP (like name, MAC etc) will be
00140      * available in 'slWlanConnectAsyncResponse_t' - Applications
00141      * can use it if required
00142      *
00143      * slWlanConnectAsyncResponse_t *pEventData = NULL;
00144      * pEventData = &pWlanEvent->EventData.STAandP2PModeWlanConnected;
00145      *
00146      */
00147     break;
00148 
00149   case SL_WLAN_DISCONNECT_EVENT: {
00150     currentState = CC3100::Disconnected;
00151 
00152     slWlanConnectAsyncResponse_t & pEventData =
00153         pWlanEvent->EventData.STAandP2PModeDisconnected;
00154 
00155     /* If the user has initiated 'Disconnect' request, 'reason_code' is SL_USER_INITIATED_DISCONNECTION */
00156     if (SL_WLAN_DISCONNECT_USER_INITIATED_DISCONNECTION ==
00157         pEventData.reason_code) {
00158       printf(" Device disconnected from the AP on application's request \n\r");
00159     } else {
00160       printf(" Device disconnected from the AP on an ERROR..!! \n\r");
00161     }
00162   } break;
00163 
00164   default:
00165     printf(" [WLAN EVENT] Unexpected event \n\r");
00166     break;
00167   }
00168 }
00169 
00170 /*!
00171     \brief This function handles events for IP address acquisition via DHCP
00172            indication
00173 
00174     \param[in]      pNetAppEvent is the event passed to the handler
00175 
00176     \return         None
00177 
00178     \note
00179 
00180     \warning
00181 */
00182 void SimpleLinkNetAppEventHandler(SlNetAppEvent_t * pNetAppEvent) {
00183   if (!pNetAppEvent) {
00184     printf(" [NETAPP EVENT] NULL Pointer Error \n\r");
00185     return;
00186   }
00187 
00188   switch (pNetAppEvent->Event) {
00189   case SL_NETAPP_IPV4_IPACQUIRED_EVENT:
00190     currentState = CC3100::Connected;
00191 
00192     //SlIpV4AcquiredAsync_t & pEventData = pNetAppEvent->EventData.ipAcquiredV4;
00193     break;
00194 
00195   default:
00196     printf(" [NETAPP EVENT] Unexpected event \n\r");
00197     break;
00198   }
00199 }
00200 
00201 /*!
00202     \brief This function handles socket events indication
00203 
00204     \param[in]      pSock is the event passed to the handler
00205 
00206     \return         None
00207 */
00208 void SimpleLinkSockEventHandler(SlSockEvent_t * pSock) {
00209   if (!pSock) {
00210     printf(" [SOCK EVENT] NULL Pointer Error \n\r");
00211     return;
00212   }
00213 
00214   switch (pSock->Event) {
00215   case SL_SOCKET_TX_FAILED_EVENT:
00216     /*
00217      * TX Failed
00218      *
00219      * Information about the socket descriptor and status will be
00220      * available in 'SlSockEventData_t' - Applications can use it if
00221      * required
00222      *
00223      * SlSockEventData_u *pEventData = NULL;
00224      * pEventData = & pSock->socketAsyncEvent;
00225      */
00226     switch (pSock->socketAsyncEvent.SockTxFailData.status) {
00227     case SL_ECLOSE:
00228       printf(" [SOCK EVENT] Close socket operation failed to transmit all "
00229              "queued packets\n\r");
00230       break;
00231 
00232     default:
00233       printf(" [SOCK EVENT] Unexpected event \n\r");
00234       break;
00235     }
00236     break;
00237 
00238   default:
00239     printf(" [SOCK EVENT] Unexpected event \n\r");
00240     break;
00241   }
00242 }
00243 
00244 /*!
00245     \brief This function handles ping report events
00246 
00247     \param[in]      pPingReport holds the ping report statistics
00248 
00249     \return         None
00250 
00251     \note
00252 
00253     \warning
00254 */
00255 static void SimpleLinkPingReport(SlPingReport_t * pPingReport) {
00256   currentState = CC3100::Connected;
00257 
00258   if (!pPingReport) {
00259     printf(" [PING REPORT] NULL Pointer Error\r\n");
00260     return;
00261   }
00262 
00263   printf(" [PING REPORT] Sent: %lu, Received: %lu\r\n",
00264          pPingReport->PacketsSent, pPingReport->PacketsReceived);
00265 }
00266 
00267 CC3100::SPI::SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel)
00268     : spi(mosi, miso, sclk), cs(ssel, 1) {}
00269 
00270 void CC3100::SPI::transfer(const uint8_t * txData, size_t dataSize,
00271                            uint8_t * rxData) {
00272   const int cs_delay_ms = 5;
00273 
00274   cs = 0;
00275   wait_ms(cs_delay_ms);
00276   for (size_t i = 0; i < dataSize; ++i) {
00277     if (rxData) {
00278       rxData[i] = spi.write(txData[i]);
00279     } else {
00280       spi.write(txData[i]);
00281     }
00282   }
00283   wait_ms(cs_delay_ms);
00284   cs = 1;
00285 }
00286 
00287 CC3100::CC3100()
00288     : spi(MBED_CONF_APP_CC3100_MOSI_PIN, MBED_CONF_APP_CC3100_MISO_PIN,
00289           MBED_CONF_APP_CC3100_CLK_PIN, MBED_CONF_APP_CC3100_NCS_PIN) {}
00290 
00291 CC3100 & CC3100::instance() {
00292   static CC3100 instance;
00293   return instance;
00294 }
00295 
00296 int CC3100::start() {
00297   // Adapter should be stopped.
00298   if (currentState != Stopped) {
00299     return invalidState;
00300   }
00301 
00302   const int result = sl_Start(&spi, NULL, NULL);
00303   if (result >= 0) {
00304     currentState = Disconnected;
00305   }
00306   return result;
00307 }
00308 
00309 CC3100::State CC3100::state() const { return currentState; }
00310 
00311 int CC3100::stop() {
00312   // Adapter should not be stopped.
00313   if (currentState == Stopped) {
00314     return invalidState;
00315   }
00316 
00317   const int result = sl_Stop(0xFF);
00318   if (result >= 0) {
00319     currentState = Stopped;
00320   }
00321   return result;
00322 }
00323 
00324 void CC3100::update() { sl_Task(); }
00325 
00326 int CC3100::setDateTime(const std::tm & dateTime) {
00327   const SlDateTime_t slDateTime = {
00328       static_cast<_u32>(dateTime.tm_sec),  // sl_tm_sec
00329       static_cast<_u32>(dateTime.tm_min),  // sl_tm_min
00330       static_cast<_u32>(dateTime.tm_hour), // sl_tm_hour
00331       static_cast<_u32>(dateTime.tm_mday), // sl_tm_day
00332       static_cast<_u32>(dateTime.tm_mon),  // sl_tm_mon
00333       static_cast<_u32>(dateTime.tm_year)  // sl_tm_year
00334   };
00335   return sl_DevSet(SL_DEVICE_GENERAL_CONFIGURATION,
00336                    SL_DEVICE_GENERAL_CONFIGURATION_DATE_TIME,
00337                    sizeof(SlDateTime_t),
00338                    reinterpret_cast<const _u8 *>(&slDateTime));
00339 }
00340 
00341 int CC3100::set_credentials(const char * ssid, const char * pass,
00342                             nsapi_security_t security) {
00343   this->ssid.assign(ssid);
00344   this->pass.assign(pass);
00345   this->security = security;
00346   return 0;
00347 }
00348 
00349 int CC3100::connect(const char * ssid, const char * pass,
00350                     nsapi_security_t security, uint8_t channel) {
00351   // Adapter should be disconnected.
00352   if (currentState != Disconnected) {
00353     return invalidState;
00354   }
00355 
00356   SlSecParams_t secParams = {
00357       SL_SEC_TYPE_OPEN,                                       // Type
00358       const_cast<_i8 *>(reinterpret_cast<const _i8 *>(pass)), // Key
00359       static_cast<_u8>(strlen(pass)),                         // KeyLen
00360   };
00361   switch (security) {
00362   case NSAPI_SECURITY_WPA2:
00363   case NSAPI_SECURITY_WPA:
00364   case NSAPI_SECURITY_WPA_WPA2:
00365     secParams.Type = SL_SEC_TYPE_WPA_WPA2;
00366     break;
00367 
00368   case NSAPI_SECURITY_WEP:
00369     secParams.Type = SL_SEC_TYPE_WEP;
00370     break;
00371 
00372   case NSAPI_SECURITY_NONE:
00373   case NSAPI_SECURITY_UNKNOWN:
00374     secParams.Type = SL_SEC_TYPE_OPEN;
00375     break;
00376 
00377   default:
00378     return invalidState;
00379   }
00380   int result = sl_WlanConnect(reinterpret_cast<const _i8 *>(ssid), strlen(ssid),
00381                               NULL, &secParams, NULL);
00382   if (result == SL_RET_CODE_OK) {
00383     // Wait for completion.
00384     int attempts = 1000;
00385     do {
00386       wait_ms(10);
00387       update();
00388     } while ((currentState != Connected) && (--attempts > 0));
00389     if (attempts == 0) {
00390       result = SL_RET_CODE_ABORT;
00391     }
00392   }
00393   return result;
00394 }
00395 
00396 int CC3100::connect(const char * ssid, const char * username,
00397                     const char * password) {
00398   // Adapter should be disconnected.
00399   if (currentState != Disconnected) {
00400     return invalidState;
00401   }
00402 
00403   uint8_t values = 0;
00404   sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, 19, 1, &values);
00405 
00406   SlSecParams_t secParams = {
00407       SL_SEC_TYPE_WPA_ENT,                                        // Type
00408       const_cast<_i8 *>(reinterpret_cast<const _i8 *>(password)), // Key
00409       static_cast<_u8>(strlen(password))                          // KeyLen
00410   };
00411   SlSecParamsExt_t secParamsExt = {
00412       const_cast<_i8 *>(reinterpret_cast<const _i8 *>(username)), // User
00413       static_cast<_u8>(strlen(username)),                         // UserLen
00414       NULL,                                                       // AnonUser
00415       0,                                                          // AnonUserLen
00416       0,                                                          // CertIndex
00417       SL_ENT_EAP_METHOD_PEAP0_MSCHAPv2                            // EapMethod
00418   };
00419   int result = sl_WlanConnect(reinterpret_cast<const _i8 *>(ssid), strlen(ssid),
00420                               NULL, &secParams, &secParamsExt);
00421   if (result == SL_RET_CODE_OK) {
00422     // Wait for completion.
00423     int attempts = 1000;
00424     do {
00425       wait_ms(10);
00426       update();
00427     } while ((currentState != Connected) && (--attempts > 0));
00428     if (attempts == 0) {
00429       result = SL_RET_CODE_ABORT;
00430     }
00431   }
00432   return result;
00433 }
00434 
00435 int CC3100::disconnect() {
00436   // Adapter should be connected.
00437   if (currentState != Connected) {
00438     return invalidState;
00439   }
00440 
00441   return sl_WlanDisconnect();
00442 }
00443 
00444 int CC3100::gethostbyname(const char * host, SocketAddress * address,
00445                           nsapi_version_t version) {
00446   // TODO: Add IPv6 support
00447 
00448   // Adapter should be connected.
00449   if (currentState != Connected) {
00450     return invalidState;
00451   }
00452 
00453   uint32_t addressInt;
00454   int result;
00455   int attempts = 1000;
00456   // Wait for DNS servers.
00457   do {
00458     wait_ms(10);
00459     result = sl_NetAppDnsGetHostByName(
00460         const_cast<_i8 *>(reinterpret_cast<const _i8 *>(host)), strlen(host),
00461         reinterpret_cast<_u32 *>(&addressInt), SL_AF_INET);
00462   } while ((result == SL_NET_APP_DNS_NO_SERVER) && (--attempts > 0));
00463   if (result == SL_RET_CODE_OK) {
00464     nsapi_addr_t addressBytes = {
00465         NSAPI_IPv4, // version
00466         0,          // bytes
00467     };
00468     for (int i = 4; i > 0; --i) {
00469       addressBytes.bytes[i - 1] = addressInt;
00470       addressInt >>= 8;
00471     }
00472     address->set_addr(addressBytes);
00473   }
00474   return result;
00475 }
00476 
00477 int CC3100::ping(const SocketAddress & address) {
00478   // Adapter should be connected.
00479   if (currentState != Connected) {
00480     return invalidState;
00481   }
00482 
00483   SlPingStartCommand_t pingParams = {
00484       1000, // PingIntervalTime
00485       20,   // PingSize
00486       3000, // PingRequestTimeout
00487       3,    // TotalNumberOfAttempts
00488       0,    // Flags
00489       0     // Ip
00490   };
00491   for (int i = 0; i < 4; ++i) {
00492     pingParams.Ip <<= 8;
00493     pingParams.Ip |= address.get_addr().bytes[i];
00494   }
00495   SlPingReport_t pingReport;
00496   int result = sl_NetAppPingStart(
00497       (SlPingStartCommand_t *)&pingParams, SL_AF_INET,
00498       static_cast<SlPingReport_t *>(&pingReport), SimpleLinkPingReport);
00499   if (result == SL_RET_CODE_OK) {
00500     // Wait for completion.
00501     currentState = Pinging;
00502     int attempts = 1000;
00503     do {
00504       wait_ms(10);
00505       update();
00506     } while ((currentState == Pinging) && (--attempts > 0));
00507     if (attempts == 0) {
00508       result = SL_RET_CODE_ABORT;
00509     }
00510   }
00511   return result;
00512 }
00513 
00514 int CC3100::socket_open(nsapi_socket_t * handle, nsapi_protocol_t proto) {
00515   int16_t result;
00516   switch (proto) {
00517   case NSAPI_TCP:
00518     result = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, 0);
00519     break;
00520 
00521   case NSAPI_UDP:
00522     result = sl_Socket(SL_AF_INET, SL_SOCK_DGRAM, 0);
00523     break;
00524 
00525   /*case SL_SEC_SOCKET:
00526     result = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_SEC_SOCKET);
00527     break;*/
00528 
00529   default:
00530     result = SL_SOC_ERROR;
00531     break;
00532   }
00533   if (result >= 0) {
00534     *handle = new int16_t(result);
00535 
00536     // Set non-blocking.
00537     SlSockNonblocking_t enableOption = {
00538         1 // NonblockingEnabled
00539     };
00540     result = sl_SetSockOpt(
00541         *static_cast<int16_t *>(*handle), SL_SOL_SOCKET, SL_SO_NONBLOCKING,
00542         reinterpret_cast<_u8 *>(&enableOption), sizeof(enableOption));
00543 
00544     if (result < 0) {
00545       socket_close(*handle);
00546     }
00547   }
00548   return result;
00549 }
00550 
00551 int CC3100::socket_set_cert_path(nsapi_socket_t handle, const char * certPath) {
00552   // Set CA certificate.
00553   return sl_SetSockOpt(*static_cast<int16_t *>(handle), SL_SOL_SOCKET,
00554                        SL_SO_SECURE_FILES_CA_FILE_NAME, certPath,
00555                        strlen(certPath));
00556 }
00557 
00558 int CC3100::socket_close(nsapi_socket_t handle) {
00559   int16_t * castedHandle = static_cast<int16_t *>(handle);
00560   const int result = sl_Close(*castedHandle);
00561   delete castedHandle;
00562   return result;
00563 }
00564 
00565 int CC3100::socket_bind(nsapi_socket_t handle, const SocketAddress & address) {
00566   // TODO: Add IPv6 support
00567   if (address.get_addr().version != NSAPI_IPv4) {
00568     return SL_SOC_ERROR;
00569   }
00570 
00571   SlSockAddrIn_t localAddr = {AF_INET,                      // sin_family
00572                               sl_Htons(address.get_port()), // sin_port
00573                               {                             // sin_addr
00574                                   0 // s_addr
00575                               }};
00576   for (int i = 4; i > 0; --i) {
00577     localAddr.sin_addr.s_addr <<= 8;
00578     localAddr.sin_addr.s_addr |= address.get_addr().bytes[i - 1];
00579   }
00580   return sl_Bind(*static_cast<int16_t *>(handle),
00581                  reinterpret_cast<SlSockAddr_t *>(&localAddr),
00582                  sizeof(localAddr));
00583 }
00584 
00585 int CC3100::socket_listen(nsapi_socket_t handle, int backlog) {
00586   return sl_Listen(*static_cast<int16_t *>(handle), backlog);
00587 }
00588 
00589 int CC3100::socket_connect(nsapi_socket_t handle,
00590                            const SocketAddress & address) {
00591   // TODO: Add IPv6 support
00592   if (address.get_addr().version != NSAPI_IPv4) {
00593     return SL_SOC_ERROR;
00594   }
00595 
00596   SlSockAddrIn_t addr = {AF_INET,                      // sin_family
00597                          sl_Htons(address.get_port()), // sin_port
00598                          {                             // sin_addr 
00599                              0 // s_addr
00600                          }};
00601   for (int i = 4; i > 0; --i) {
00602     addr.sin_addr.s_addr <<= 8;
00603     addr.sin_addr.s_addr |= address.get_addr().bytes[i - 1];
00604   }
00605   int result;
00606   int attempts = 1000;
00607   do {
00608     wait_ms(10);
00609     result = sl_Connect(*static_cast<int16_t *>(handle),
00610                         reinterpret_cast<SlSockAddr_t *>(&addr), sizeof(addr));
00611   } while ((result == SL_EALREADY) && (--attempts > 0));
00612   if (result > 0) {
00613     result = 0;
00614   }
00615   return result;
00616 }
00617 
00618 int CC3100::socket_send(nsapi_socket_t handle, const void * data,
00619                         unsigned size) {
00620   return sl_Send(*static_cast<int16_t *>(handle), data, size, 0);
00621 }
00622 
00623 int CC3100::socket_recv(nsapi_socket_t handle, void * data, unsigned size) {
00624   int result = sl_Recv(*static_cast<int16_t *>(handle), data, size, 0);
00625   if (result == SL_EAGAIN) {
00626     result = NSAPI_ERROR_WOULD_BLOCK;
00627   }
00628   return result;
00629 }