Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: BLE_Thermometer MAXWSNENV_demo
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 ¶ms); 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 }
Generated on Tue Jul 12 2022 19:59:22 by
1.7.2