Maxim Integrated / MaximBLE

Dependents:   BLE_Thermometer MAXWSNENV_demo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MaximBLE.cpp Source File

MaximBLE.cpp

00001 /*******************************************************************************
00002  * Copyright (C) 2016 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 
00034 #include "mbed.h"
00035 #include "us_ticker_api.h"
00036 #include "MaximBLE.h"
00037 #include "wsf_types.h"
00038 #include "wsf_msg.h"
00039 #include "wsf_os.h"
00040 #include "wsf_buf.h"
00041 #include "wsf_sec.h"
00042 #include "wsf_timer.h"
00043 #include "hci_handler.h"
00044 #include "dm_handler.h"
00045 #include "l2c_handler.h"
00046 #include "att_handler.h"
00047 #include "smp_handler.h"
00048 #include "l2c_api.h"
00049 #include "att_api.h"
00050 #include "smp_api.h"
00051 #include "hci_drv.h"
00052 #include "hci_vs.h"
00053 
00054 /* Number of WSF buffer pools */
00055 #define WSF_BUF_POOLS               4
00056 
00057 /*! Free memory for pool buffers. */
00058 static uint8_t mainBufMem[768];
00059 
00060 /*! Default pool descriptor. */
00061 static wsfBufPoolDesc_t  mainPoolDesc[WSF_BUF_POOLS] =
00062 {
00063   {  16,  8 },
00064   {  32,  4 },
00065   {  64,  2 },
00066   { 128,  2 }
00067 };
00068 
00069 /*! WSF handler ID */
00070 wsfHandlerId_t maximHandlerId;
00071 static volatile int reset_complete;
00072 
00073 /* Current mbed SPI API does not support HW slave selects. Configured in HCI driver. */
00074 static DigitalOut _csn(HCI_CSN, 1);
00075 static SPI _spi(HCI_MOSI, HCI_MISO, HCI_SCK, HCI_CSN);
00076 static DigitalOut _rst(HCI_RST, 0);
00077 static InterruptIn _irq(HCI_IRQ);
00078 
00079 /**
00080  * The singleton which represents the MaximBLE transport for the BLE.
00081  */
00082 static MaximBLE deviceInstance;
00083 
00084 /**
00085  * BLE-API requires an implementation of the following function in order to
00086  * obtain its transport handle.
00087  */
00088 BLEInstanceBase *createBLEInstance(void)
00089 {
00090     return (&deviceInstance);
00091 }
00092 
00093 MaximBLE::MaximBLE(void) : initialized(false), instanceID(BLE::DEFAULT_INSTANCE)
00094 {
00095 }
00096 
00097 MaximBLE::~MaximBLE(void)
00098 {
00099 }
00100 
00101 const char *MaximBLE::getVersion(void)
00102 {
00103     static char versionString[32];
00104 
00105     strncpy(versionString, "unknown", sizeof(versionString));
00106 
00107     return versionString;
00108 }
00109 
00110 static void DmCback(dmEvt_t  *pDmEvt)
00111 {
00112     dmEvt_t  *pMsg;
00113 
00114     if ((pMsg = (dmEvt_t *)WsfMsgAlloc(sizeof(dmEvt_t ))) != NULL)
00115     {
00116         memcpy(pMsg, pDmEvt, sizeof(dmEvt_t ));
00117         WsfMsgSend(maximHandlerId, pMsg);
00118     }
00119 }
00120 
00121 static void maximHandler(wsfEventMask_t event, wsfMsgHdr_t  *pMsg)
00122 {
00123     if (pMsg != NULL)
00124     {
00125         switch(pMsg->event )
00126         {
00127             case DM_RESET_CMPL_IND:
00128                 reset_complete = 1;
00129                 break;
00130             case DM_ADV_START_IND :
00131                 break;
00132             case DM_ADV_STOP_IND :
00133                 MaximGap::getInstance().advertisingStopped();
00134                 break;
00135             case DM_SCAN_REPORT_IND :
00136                 {
00137                     hciLeAdvReportEvt_t  *scanReport = (hciLeAdvReportEvt_t *)pMsg;
00138                     MaximGap::getInstance().processAdvertisementReport( scanReport->addr,
00139                                                                         scanReport->rssi,
00140                                                                         (scanReport->eventType == DM_ADV_SCAN_RESPONSE) ? true : false,
00141                                                                         (GapAdvertisingParams::AdvertisingType_t)scanReport->eventType,
00142                                                                         scanReport->len,
00143                                                                         scanReport->pData);
00144                 }
00145                 break;
00146             case DM_CONN_OPEN_IND :
00147                 {
00148                     hciLeConnCmplEvt_t  *connOpen = (hciLeConnCmplEvt_t *)pMsg;
00149                     MaximGap::getInstance().setConnectionHandle(connOpen->handle);
00150                     Gap::ConnectionParams_t params = { connOpen->connInterval, connOpen->connInterval, connOpen->connLatency, connOpen->supTimeout };
00151                     Gap::AddressType_t ownAddrType;
00152                     Gap::Address_t ownAddr;
00153                     MaximGap::getInstance().getAddress(&ownAddrType, ownAddr);
00154                     MaximGap::getInstance().processConnectionEvent(connOpen->handle,
00155                                                                    Gap::PERIPHERAL,
00156                                                                    (Gap::AddressType_t)connOpen->addrType,
00157                                                                    connOpen->peerAddr,
00158                                                                    ownAddrType,
00159                                                                    ownAddr,
00160                                                                    &params);
00161                 }
00162                 break;
00163             case DM_CONN_CLOSE_IND :
00164                 {
00165                     hciDisconnectCmplEvt_t  *connClose = (hciDisconnectCmplEvt_t *)pMsg;
00166                     MaximGap::getInstance().setConnectionHandle(DM_CONN_ID_NONE);
00167                     MaximGap::getInstance().processDisconnectionEvent(connClose->handle, (Gap::DisconnectionReason_t)connClose->reason);
00168                 }
00169                 break;
00170             case DM_HW_ERROR_IND :
00171                 {
00172                     hciHwErrorEvt_t  *error = (hciHwErrorEvt_t *)pMsg;
00173                     printf("HCI Hardware Error 0x%02x occurred\n", error->code);
00174                 }
00175                 break;
00176             default:
00177                 break;
00178         }
00179     }
00180 }
00181 
00182 static void AppServerConnCback(dmEvt_t  *pDmEvt)
00183 {
00184   dmConnId_t  connId = (dmConnId_t )pDmEvt->hdr.param;
00185 
00186   switch (pDmEvt->hdr.event )
00187   {
00188     case DM_CONN_OPEN_IND :
00189       /* set up CCC table with uninitialized (all zero) values */
00190       AttsCccInitTable(connId, NULL);
00191       break;
00192     case DM_CONN_CLOSE_IND :
00193       /* clear CCC table on connection close */
00194       AttsCccClearTable(connId);
00195       break;
00196     default:
00197       break;
00198   }
00199 }
00200 
00201 ble_error_t MaximBLE::init(BLE::InstanceID_t instanceID, FunctionPointerWithContext<BLE::InitializationCompleteCallbackContext *> initCallback)
00202 {
00203     wsfHandlerId_t handlerId;
00204 
00205     /* init OS subsystems */
00206     WsfTimerInit(1);
00207     WsfBufInit(sizeof(mainBufMem), mainBufMem, WSF_BUF_POOLS, mainPoolDesc);
00208     WsfSecInit();
00209 
00210     /* init stack */
00211     handlerId = WsfOsSetNextHandler(HciHandler);
00212     HciHandlerInit(handlerId);
00213 
00214     handlerId = WsfOsSetNextHandler(DmHandler);
00215     DmAdvInit();
00216     DmScanInit();
00217     DmConnInit();
00218     DmConnSlaveInit();
00219     DmSecInit();
00220     DmHandlerInit(handlerId);
00221 
00222     handlerId = WsfOsSetNextHandler(L2cSlaveHandler);
00223     L2cSlaveHandlerInit(handlerId);
00224     L2cInit();
00225     L2cMasterInit();
00226     L2cSlaveInit();
00227 
00228     handlerId = WsfOsSetNextHandler(AttHandler);
00229     AttHandlerInit(handlerId);
00230     AttsInit();
00231     AttsIndInit();
00232     AttcInit();
00233 
00234     handlerId = WsfOsSetNextHandler(SmpHandler);
00235     SmpHandlerInit(handlerId);
00236     SmpiInit();
00237     SmprInit();
00238 
00239     /* store handler ID */
00240     maximHandlerId = WsfOsSetNextHandler(maximHandler);
00241 
00242     /* init HCI */
00243     _irq.disable_irq();
00244     _irq.rise(hciDrvIsr);
00245     _irq.fall(NULL);
00246     hciDrvInit(HCI_CSN, HCI_RST, HCI_IRQ);
00247 
00248     /* Register for stack callbacks */
00249     DmRegister(DmCback);
00250     DmConnRegister(DM_CLIENT_ID_APP, DmCback);
00251     AttConnRegister(AppServerConnCback);
00252 
00253     /* Reset the device */
00254     reset_complete = 0;
00255     DmDevReset();
00256 
00257     while (!reset_complete) {
00258         callDispatcher();
00259     }
00260 
00261     initialized = true;
00262     BLE::InitializationCompleteCallbackContext context = {
00263         BLE::Instance(instanceID),
00264         BLE_ERROR_NONE
00265     };
00266     initCallback.call(&context);
00267     return BLE_ERROR_NONE;
00268 }
00269 
00270 ble_error_t MaximBLE::shutdown(void)
00271 {
00272     return BLE_ERROR_NOT_IMPLEMENTED;
00273 }
00274 
00275 void MaximBLE::waitForEvent(void)
00276 {
00277     static LowPowerTimeout nextTimeout;
00278     timestamp_t nextTimestamp;
00279     bool_t pTimerRunning;
00280 
00281     callDispatcher();
00282 
00283     if (wsfOsReadyToSleep()) {
00284         // setup an mbed timer for the next Wicentric timeout
00285         nextTimestamp = (timestamp_t)WsfTimerNextExpiration(&pTimerRunning) * 1000;
00286         if (pTimerRunning) {
00287             nextTimeout.attach_us(timeoutCallback, nextTimestamp);
00288         }
00289 
00290         // go to sleep
00291         if (hciDrvReadyToSleep()) {
00292             // go to deep sleep
00293             deepsleep();
00294             hciDrvResume();
00295         }
00296         else {
00297             sleep();
00298         }
00299     }
00300 }
00301 
00302 void MaximBLE::processEvents()
00303 {
00304     callDispatcher();
00305 }
00306 
00307 void MaximBLE::timeoutCallback(void)
00308 {
00309     // do nothing. just an interrupt for wake up.
00310 }
00311 
00312 void MaximBLE::callDispatcher(void)
00313 {
00314     static uint32_t lastTimeUs = us_ticker_read();
00315     uint32_t currTimeUs, deltaTimeMs;
00316 
00317     // Update the current Wicentric time
00318     currTimeUs = us_ticker_read();
00319     deltaTimeMs = (currTimeUs - lastTimeUs) / 1000;
00320     if (deltaTimeMs > 0) {
00321         WsfTimerUpdate(deltaTimeMs);
00322         lastTimeUs += deltaTimeMs * 1000;
00323     }
00324 
00325     wsfOsDispatcher();
00326 }