ble_ipsp.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981
  1. /**
  2. * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. /* Attention!
  41. * To maintain compliance with Nordic Semiconductor ASA's Bluetooth profile
  42. * qualification listings, this section of source code must not be modified.
  43. */
  44. #include <stdbool.h>
  45. #include <string.h>
  46. #include "nordic_common.h"
  47. #include "sdk_errors.h"
  48. #include "nrf.h"
  49. #include "sdk_config.h"
  50. #include "ble_ipsp.h"
  51. #include "ble_srv_common.h"
  52. #include "sdk_os.h"
  53. /**
  54. * @defgroup ble_ipsp_log Module's Log Macros
  55. * @details Macros used for creating module logs which can be useful in understanding handling
  56. * of events or actions on API requests. These are intended for debugging purposes and
  57. * can be enabled by defining the IOT_BLE_IPSP_CONFIG_LOG_ENABLED to 1.
  58. * @note If NRF_LOG_ENABLED is disabled, having IOT_BLE_IPSP_CONFIG_LOG_ENABLED
  59. * has no effect.
  60. * @{
  61. */
  62. #if IOT_BLE_IPSP_CONFIG_LOG_ENABLED
  63. #define NRF_LOG_MODULE_NAME ipsp
  64. #define NRF_LOG_LEVEL IOT_BLE_IPSP_CONFIG_LOG_LEVEL
  65. #define NRF_LOG_INFO_COLOR IOT_BLE_IPSP_CONFIG_INFO_COLOR
  66. #define NRF_LOG_DEBUG_COLOR IOT_BLE_IPSP_CONFIG_DEBUG_COLOR
  67. #include "nrf_log.h"
  68. NRF_LOG_MODULE_REGISTER();
  69. #define BLE_IPSP_TRC NRF_LOG_DEBUG /**< Used for getting trace of execution in the module. */
  70. #define BLE_IPSP_ERR NRF_LOG_ERROR /**< Used for logging errors in the module. */
  71. #define BLE_IPSP_DUMP NRF_LOG_HEXDUMP_DEBUG /**< Used for dumping octet information to get details of bond information etc. */
  72. #define BLE_IPSP_ENTRY() BLE_IPSP_TRC(">> %s", __func__)
  73. #define BLE_IPSP_EXIT() BLE_IPSP_TRC("<< %s", __func__)
  74. #define BLE_IPSP_EXIT_WITH_RESULT(result) BLE_IPSP_TRC("<< %s, result 0x%08lX", __func__, result)
  75. #else // IOT_BLE_IPSP_CONFIG_LOG_ENABLED
  76. #define BLE_IPSP_TRC(...) /**< Disables traces. */
  77. #define BLE_IPSP_DUMP(...) /**< Disables dumping of octet streams. */
  78. #define BLE_IPSP_ERR(...) /**< Disables error logs. */
  79. #define BLE_IPSP_ENTRY(...)
  80. #define BLE_IPSP_EXIT(...)
  81. #define BLE_IPSP_EXIT_WITH_RESULT(...)
  82. #endif // IOT_BLE_IPSP_CONFIG_LOG_ENABLED
  83. #define IPSP_ANY_CID 0xFFFE /**< Identifier for any channel. Usage: Search for existing channel on a connection handle. */
  84. /**
  85. * @defgroup api_param_check API Parameters check macros.
  86. *
  87. * @details Macros that verify parameters passed to the module in the APIs. These macros
  88. * could be mapped to nothing in final versions of code to save execution and size.
  89. * BLE_HPS_DISABLE_API_PARAM_CHECK should be defined to disable these checks.
  90. *
  91. * @{
  92. */
  93. #if (BLE_IPSP_DISABLE_API_PARAM_CHECK == 0)
  94. /**@brief Macro to check is module is initialized before requesting one of the module procedures. */
  95. #define VERIFY_MODULE_IS_INITIALIZED() \
  96. if (m_evt_handler == NULL) \
  97. { \
  98. return (NRF_ERROR_MODULE_NOT_INITIALIZED + NRF_ERROR_BLE_IPSP_ERR_BASE); \
  99. }
  100. /**@brief Macro to check is module is initialized before requesting one of the module
  101. procedures but does not use any return code. */
  102. #define VERIFY_MODULE_IS_INITIALIZED_VOID() \
  103. if (m_evt_handler == NULL) \
  104. { \
  105. return; \
  106. }
  107. /**@brief Verify NULL parameters are not passed to API by application. */
  108. #define NULL_PARAM_CHECK(PARAM) \
  109. if ((PARAM) == NULL) \
  110. { \
  111. return (NRF_ERROR_NULL + NRF_ERROR_BLE_IPSP_ERR_BASE); \
  112. }
  113. /**@brief Verify the connection handle passed to the API. */
  114. #define VERIFY_CON_HANDLE(CON_HANDLE) \
  115. if ((CON_HANDLE) == BLE_CONN_HANDLE_INVALID) \
  116. { \
  117. return (NRF_ERROR_INVALID_PARAM + NRF_ERROR_BLE_IPSP_ERR_BASE); \
  118. }
  119. #else // BLE_IPSP_DISABLE_API_PARAM_CHECK
  120. #define VERIFY_MODULE_IS_INITIALIZED()
  121. #define VERIFY_MODULE_IS_INITIALIZED_VOID()
  122. #define NULL_PARAM_CHECK(PARAM)
  123. #define VERIFY_CON_HANDLE(CON_HANDLE)
  124. #endif //BLE_IPSP_DISABLE_API_PARAM_CHECK
  125. /**
  126. * @defgroup ble_ipsp_mutex_lock_unlock Module's Mutex Lock/Unlock Macros.
  127. *
  128. * @details Macros used to lock and unlock modules. Currently, SDK does not use mutexes but
  129. * framework is provided in case the need to use an alternative architecture arises.
  130. * @{
  131. */
  132. #define BLE_IPSP_MUTEX_LOCK() SDK_MUTEX_LOCK(m_ipsp_mutex) /**< Lock module using mutex */
  133. #define BLE_IPSP_MUTEX_UNLOCK() SDK_MUTEX_UNLOCK(m_ipsp_mutex) /**< Unlock module using mutex */
  134. /** @} */
  135. #define IPSP_MAX_CONNECTED_DEVICES BLE_IPSP_MAX_CHANNELS /**< Table for maximum number of connected devices the module will keep track of. */
  136. #define RX_BUFFER_TOTAL_SIZE (BLE_IPSP_RX_BUFFER_SIZE * BLE_IPSP_RX_BUFFER_COUNT) /**< Total receive buffer size reserved for each IPSP channel. */
  137. #define MAX_L2CAP_RX_BUFFER (RX_BUFFER_TOTAL_SIZE * BLE_IPSP_MAX_CHANNELS) /**< Total receive buffer received for all channels. */
  138. #define INVALID_CHANNEL_INSTANCE 0xFF /**< Indicates channel instance is invalid. */
  139. /**@brief IPSP Channel States. */
  140. typedef enum
  141. {
  142. CHANNEL_IDLE, /**< Indicates the channel is free and not in use. */
  143. CHANNEL_CONNECTING, /**< Indicates the channel creation is requested and is awaiting a response. */
  144. CHANNEL_CONNECTED, /**< Indicates the channel is connected and ready for data exchange. */
  145. CHANNEL_DISCONNECTING /**< Indicates the channel is in the process of being disconnected. */
  146. } channel_state_t;
  147. /**@brief Possible response actions for an incoming channel. Default is to accept. */
  148. typedef enum
  149. {
  150. INCOMING_CHANNEL_ACCEPT, /**< Indicates that the incoming channel should be accepted if all other criteria are met. */
  151. INCOMING_CHANNEL_REJECT /**< Indicates that the incoming channel for IPSP PSM should be rejected regardless of the other criteria. */
  152. } incoming_channel_action_t;
  153. /**@brief Data type for book keeping connected devices.
  154. *
  155. * @note Not all connected devices establish an L2CAP connection.
  156. */
  157. typedef struct
  158. {
  159. volatile incoming_channel_action_t response; /**< Indicator if the incoming channel should be accepted or rejected. */
  160. ble_gap_addr_t ble_addr; /**< Bluetooth device address of the peer. */
  161. uint16_t conn_handle; /**< Connection handle identifying the link with the peer. */
  162. } peer_connection_t;
  163. /**@brief IPSP Channel Information. */
  164. typedef struct
  165. {
  166. uint16_t conn_handle; /**< Identifies the BLE link on which channel is established. BLE_CONN_HANDLE_INVALID if channel is unassigned. */
  167. uint16_t cid; /**< L2CAP channel identifier needed to manage the channel once established. BLE_L2CAP_CID_INVALID if channel is unassigned. */
  168. uint16_t rx_buffer_status; /**< Usage status of RX buffers. */
  169. uint8_t state; /**< State information for the channel. See @ref channel_state_t for details. */
  170. uint8_t * p_rx_buffer; /**< Receive buffer for the channel. */
  171. } channel_t;
  172. static ble_ipsp_evt_handler_t m_evt_handler = NULL; /**< Asynchronous event notification callback registered with the module. */
  173. static channel_t m_channel[BLE_IPSP_MAX_CHANNELS]; /**< Table of channels managed by the module. */
  174. static uint8_t m_rx_buffer[MAX_L2CAP_RX_BUFFER]; /**< Receive buffer reserved for all channels to receive data on the L2CAP IPSP channel. */
  175. static peer_connection_t m_connected_device[IPSP_MAX_CONNECTED_DEVICES]; /**< Table maintaining list of peer devices and the connection handle.
  176. \n This information is needed for the 6lowpan compression and decompression.
  177. \n And no interface exists to query the softdevice. */
  178. SDK_MUTEX_DEFINE(m_ipsp_mutex) /**< Mutex variable. Currently unused, this declaration does not occupy any space in RAM. */
  179. /**@brief Initialize the peer connected device in the list.
  180. *
  181. * @param[in] index Identifies the list element to be initialized.
  182. */
  183. static __INLINE void connected_device_init(uint32_t index)
  184. {
  185. memset (&m_connected_device[index].ble_addr, 0, sizeof(ble_gap_addr_t));
  186. m_connected_device[index].conn_handle = BLE_CONN_HANDLE_INVALID;
  187. m_connected_device[index].response = INCOMING_CHANNEL_ACCEPT;
  188. }
  189. /**@brief Allocate an entry for the peer connected device in the list.
  190. *
  191. * @param[in] p_peer_addr Pointer to peer's device address.
  192. * @param[in] conn_handle Connection handle identifying the link with the peer.
  193. */
  194. static __INLINE void connected_device_allocate(ble_gap_addr_t const * p_peer_addr,
  195. uint16_t conn_handle)
  196. {
  197. for (uint32_t index = 0; index < IPSP_MAX_CONNECTED_DEVICES; index++)
  198. {
  199. if (m_connected_device[index].conn_handle == BLE_CONN_HANDLE_INVALID)
  200. {
  201. m_connected_device[index].conn_handle = conn_handle;
  202. memcpy(m_connected_device[index].ble_addr.addr, p_peer_addr->addr, BLE_GAP_ADDR_LEN);
  203. break;
  204. }
  205. }
  206. }
  207. /**@brief Search for an entry for the peer connected device in the list.
  208. *
  209. * @param[in] conn_handle Connection handle identifying the link with the peer.
  210. *
  211. * @retval A valid device index in the list if found, else,
  212. * IPSP_MAX_CONNECTED_DEVICES indicating the search failed.
  213. */
  214. static __INLINE uint32_t connected_device_search(uint16_t conn_handle)
  215. {
  216. for (uint32_t index = 0; index < IPSP_MAX_CONNECTED_DEVICES; index++)
  217. {
  218. if (m_connected_device[index].conn_handle == conn_handle)
  219. {
  220. return index;
  221. }
  222. }
  223. return IPSP_MAX_CONNECTED_DEVICES;
  224. }
  225. /**@brief Initialize channel.
  226. *
  227. * @param[in] ch_id Identifies the IPSP channel on which the procedure is requested.
  228. */
  229. static __INLINE void channel_init(uint8_t ch_id)
  230. {
  231. m_channel[ch_id].conn_handle = BLE_CONN_HANDLE_INVALID;
  232. m_channel[ch_id].cid = BLE_L2CAP_CID_INVALID;
  233. m_channel[ch_id].rx_buffer_status = 0;
  234. m_channel[ch_id].state = CHANNEL_IDLE;
  235. m_channel[ch_id].p_rx_buffer = &m_rx_buffer[ch_id*RX_BUFFER_TOTAL_SIZE];
  236. }
  237. /**@brief Free channel.
  238. *
  239. * @param[in] ch_id Identifies the IPSP channel on which the procedure is requested.
  240. */
  241. static __INLINE void channel_free(uint8_t ch_id)
  242. {
  243. BLE_IPSP_TRC("[Index 0x%02X]:[Conn Handle 0x%04X]:[CID 0x%04X]: Freeing channel",
  244. ch_id, m_channel[ch_id].conn_handle, m_channel[ch_id].cid);
  245. channel_init(ch_id);
  246. }
  247. /**@brief Searches the IPSP channel based on connection handle and local L2CAP channel identifier.
  248. *
  249. * @param[in] conn_handle The connection handle, identifying the peer device.
  250. * @param[in] l2cap_cid The local L2CAP channel identifier, identifying the L2CAP channel.
  251. * @param[out] p_ch_id The IPSP channel identifier, if the search succeeded, else,
  252. * BLE_IPSP_MAX_CHANNELS indicating no IPSP channel was found.
  253. */
  254. static __INLINE uint32_t channel_search(uint16_t conn_handle, uint16_t l2cap_cid, uint8_t * p_ch_id)
  255. {
  256. BLE_IPSP_TRC("[Conn Handle 0x%04X]:[CID 0x%04X]: channel_search",
  257. conn_handle, l2cap_cid);
  258. for (int i = 0; i < BLE_IPSP_MAX_CHANNELS; i++)
  259. {
  260. BLE_IPSP_TRC("[@ Index 0x%02X] ==> Conn Handle: 0x%04X"
  261. " CID : 0x%04X",
  262. i, m_channel[i].conn_handle, m_channel[i].cid);
  263. if (m_channel[i].conn_handle == conn_handle)
  264. {
  265. if ((l2cap_cid == IPSP_ANY_CID) || (m_channel[i].cid == l2cap_cid))
  266. {
  267. BLE_IPSP_TRC("channel_search succeeded, index 0x%04X", i);
  268. *p_ch_id = (uint8_t)i;
  269. return NRF_SUCCESS;
  270. }
  271. }
  272. }
  273. BLE_IPSP_TRC("No matching channel found!");
  274. return (NRF_ERROR_BLE_IPSP_ERR_BASE + NRF_ERROR_NOT_FOUND);
  275. }
  276. /**@brief Notify application of an event.
  277. *
  278. * @param[in] Identifies the IPSP instance for which the event is notified.
  279. * @param[in] Describes the notified event and its parameters, if any.
  280. */
  281. static __INLINE void app_notify(ble_ipsp_handle_t * p_handle, ble_ipsp_evt_t * p_event)
  282. {
  283. BLE_IPSP_MUTEX_UNLOCK();
  284. BLE_IPSP_TRC("[Conn Handle 0x%04X]:[CID 0x%04X]: Notifying application of event 0x%04X",
  285. p_handle->conn_handle, p_handle->cid, p_event->evt_id);
  286. UNUSED_VARIABLE(m_evt_handler(p_handle, p_event));
  287. BLE_IPSP_MUTEX_LOCK();
  288. }
  289. /**@brief Verifies if the buffer is TX buffer on the channel or not.
  290. *
  291. * @param[in] ch_id Identifies the IPSP channel for which the procedure is requested.
  292. * @param[in] p_buffer Address of the buffer being verified to be TX or not.
  293. */
  294. static __INLINE bool is_tx_buffer(uint32_t ch_id, const uint8_t * p_buffer)
  295. {
  296. // If the buffer is in the RX buffer list, then it is not TX!
  297. if ((p_buffer >= (uint8_t *)&m_channel[ch_id].p_rx_buffer) &&
  298. (p_buffer < (uint8_t *)&m_channel[ch_id].p_rx_buffer[RX_BUFFER_TOTAL_SIZE]))
  299. {
  300. return false;
  301. }
  302. return true;
  303. }
  304. /**@brief Submit receive buffers to the softdevice for a channel.
  305. *
  306. * @param[in] ch_id Identifies the IPSP channel for which the procedure is requested.
  307. */
  308. static __INLINE void rx_buffers_submit(uint32_t ch_id)
  309. {
  310. uint32_t retval;
  311. for (uint32_t buffer_index = 0; buffer_index < BLE_IPSP_RX_BUFFER_COUNT; buffer_index++)
  312. {
  313. const ble_data_t sdu_buf =
  314. {
  315. .p_data = (uint8_t *)&m_channel[ch_id].p_rx_buffer[buffer_index * BLE_IPSP_MTU],
  316. .len = BLE_IPSP_MTU
  317. };
  318. if (IS_SET(m_channel[ch_id].rx_buffer_status, buffer_index) == 0)
  319. {
  320. retval = sd_ble_l2cap_ch_rx(m_channel[ch_id].conn_handle,
  321. m_channel[ch_id].cid,
  322. &sdu_buf);
  323. if (retval == NRF_SUCCESS)
  324. {
  325. SET_BIT(m_channel[ch_id].rx_buffer_status, buffer_index);
  326. }
  327. }
  328. }
  329. }
  330. /**@brief Mark a receive buffer as not in use for a particular channel.
  331. *
  332. * @param[in] ch_id Identifies the IPSP channel for which the procedure is requested.
  333. * @param[in] p_buffer The buffer to be marked as unused.
  334. *
  335. * @note This is a temporary state for the receive buffer before it is resubmitted to the SoftDevice.
  336. */
  337. static __INLINE void rx_buffer_mark_unused(uint32_t ch_id, uint8_t * p_buffer)
  338. {
  339. for (uint32_t buffer_index = 0; buffer_index < BLE_IPSP_RX_BUFFER_COUNT; buffer_index++)
  340. {
  341. if (&m_channel[ch_id].p_rx_buffer[buffer_index * BLE_IPSP_MTU] == p_buffer)
  342. {
  343. CLR_BIT(m_channel[ch_id].rx_buffer_status, buffer_index);
  344. }
  345. }
  346. }
  347. void ble_ipsp_evt_handler(ble_evt_t const * p_evt)
  348. {
  349. VERIFY_MODULE_IS_INITIALIZED_VOID();
  350. ble_ipsp_handle_t handle;
  351. ble_ipsp_evt_t ipsp_event;
  352. uint32_t retval;
  353. uint8_t ch_id;
  354. bool notify_event;
  355. bool submit_rx_buffer;
  356. ch_id = INVALID_CHANNEL_INSTANCE;
  357. notify_event = false;
  358. submit_rx_buffer = false;
  359. retval = NRF_SUCCESS;
  360. ipsp_event.evt_result = NRF_SUCCESS;
  361. handle.conn_handle = BLE_CONN_HANDLE_INVALID;
  362. handle.cid = BLE_L2CAP_CID_INVALID;
  363. BLE_IPSP_TRC("Received BLE Event 0x%04X",p_evt->header.evt_id);
  364. BLE_IPSP_MUTEX_LOCK();
  365. switch (p_evt->header.evt_id)
  366. {
  367. case BLE_GAP_EVT_CONNECTED:
  368. {
  369. // Create an entry in the connected devices table.
  370. // This is needed to be able to fetch the peer address on IPSP channel establishment.
  371. connected_device_allocate(&p_evt->evt.gap_evt.params.connected.peer_addr,
  372. p_evt->evt.gap_evt.conn_handle);
  373. break;
  374. }
  375. case BLE_L2CAP_EVT_CH_SETUP_REQUEST:
  376. {
  377. // This event is generated for the acceptor role and indicates an channel establishment
  378. // request from the peer.
  379. ble_l2cap_ch_setup_params_t reply_param;
  380. uint16_t local_cid;
  381. memset(&reply_param, 0, sizeof(ble_l2cap_ch_setup_params_t));
  382. reply_param.le_psm = p_evt->evt.l2cap_evt.params.ch_setup_request.le_psm;
  383. reply_param.rx_params.rx_mtu = BLE_IPSP_MTU;
  384. reply_param.rx_params.rx_mps = BLE_IPSP_RX_MPS;
  385. // Check if a channel already exists with the peer.
  386. retval = channel_search(p_evt->evt.l2cap_evt.conn_handle,
  387. IPSP_ANY_CID,
  388. &ch_id);
  389. BLE_IPSP_TRC("Exiting channel_search result 0x%08X", ch_id);
  390. if (retval == NRF_SUCCESS)
  391. {
  392. BLE_IPSP_TRC("Rejecting channel, as IPSP channel already exists "
  393. "0x%08X in state 0x%08X", ch_id, m_channel[ch_id].state);
  394. reply_param.status = BLE_L2CAP_CH_STATUS_CODE_NO_RESOURCES;
  395. // Reinitialize ch_id to invalid so that existing channel is not impacted.
  396. ch_id = INVALID_CHANNEL_INSTANCE;
  397. }
  398. else
  399. {
  400. uint32_t peer_device_index = connected_device_search(p_evt->evt.l2cap_evt.conn_handle);
  401. local_cid = p_evt->evt.l2cap_evt.local_cid;
  402. if (p_evt->evt.l2cap_evt.params.ch_setup_request.le_psm != BLE_IPSP_PSM)
  403. {
  404. reply_param.status = BLE_L2CAP_CH_STATUS_CODE_LE_PSM_NOT_SUPPORTED;
  405. BLE_IPSP_TRC("Rejecting L2CAP Channel, unknown PSM %04X!",
  406. p_evt->evt.l2cap_evt.params.ch_setup_request.le_psm);
  407. }
  408. else if ((peer_device_index != IPSP_MAX_CONNECTED_DEVICES) &&
  409. (m_connected_device[peer_device_index].response == INCOMING_CHANNEL_REJECT))
  410. {
  411. reply_param.status = BLE_L2CAP_CH_STATUS_CODE_NO_RESOURCES;
  412. BLE_IPSP_ERR("Barred incoming requests by the application. "
  413. "Rejecting L2CAP Channel %04X!",
  414. p_evt->evt.l2cap_evt.params.ch_setup_request.le_psm);
  415. }
  416. else if (p_evt->evt.l2cap_evt.params.ch_setup_request.tx_params.tx_mtu < BLE_IPSP_MTU)
  417. {
  418. reply_param.status = BLE_L2CAP_CH_STATUS_CODE_UNACCEPTABLE_PARAMS;
  419. BLE_IPSP_TRC("Rejecting L2CAP Channel, unacceptable TX parameters!");
  420. }
  421. else
  422. {
  423. // Peer request acceptable, look for a free channel.
  424. retval = channel_search(BLE_CONN_HANDLE_INVALID, BLE_L2CAP_CID_INVALID, &ch_id);
  425. BLE_IPSP_TRC("Free channel search result 0x%08X", ch_id);
  426. if (retval != NRF_SUCCESS)
  427. {
  428. BLE_IPSP_TRC("Rejecting L2CAP Channel, no resources!");
  429. reply_param.status = BLE_L2CAP_CH_STATUS_CODE_NO_RESOURCES;
  430. }
  431. else
  432. {
  433. BLE_IPSP_TRC("Accepting L2CAP Channel");
  434. reply_param.rx_params.sdu_buf.p_data = NULL;
  435. reply_param.rx_params.sdu_buf.len = 0;
  436. reply_param.status = BLE_L2CAP_CH_STATUS_CODE_SUCCESS;
  437. }
  438. }
  439. }
  440. retval = sd_ble_l2cap_ch_setup(p_evt->evt.l2cap_evt.conn_handle,
  441. &local_cid,
  442. &reply_param);
  443. BLE_IPSP_TRC("sd_ble_l2cap_ch_setup result = 0x%08lX", retval);
  444. if ((retval == NRF_SUCCESS) &&
  445. (reply_param.status == BLE_L2CAP_CH_STATUS_CODE_SUCCESS) &&
  446. (ch_id != INVALID_CHANNEL_INSTANCE))
  447. {
  448. BLE_IPSP_TRC("[0x%04X][0x%04X]: Channel Connected. Rx MPS = 0x%04X",
  449. p_evt->evt.l2cap_evt.conn_handle,
  450. p_evt->evt.l2cap_evt.local_cid,
  451. reply_param.rx_params.rx_mps);
  452. ipsp_event.evt_id = BLE_IPSP_EVT_CHANNEL_CONNECTED;
  453. ipsp_event.evt_result = NRF_SUCCESS;
  454. // Channel is assigned to this link.
  455. m_channel[ch_id].state = CHANNEL_CONNECTING;
  456. m_channel[ch_id].conn_handle = p_evt->evt.l2cap_evt.conn_handle;
  457. m_channel[ch_id].cid = local_cid;
  458. }
  459. else if (ch_id != INVALID_CHANNEL_INSTANCE)
  460. {
  461. // Free the allocated channel.
  462. channel_init(ch_id);
  463. }
  464. break;
  465. }
  466. case BLE_L2CAP_EVT_CH_SETUP:
  467. {
  468. // This event is generated for both initiator and acceptor roles.
  469. // This event indicates that the IPSP channel is successfully established.
  470. retval = channel_search(p_evt->evt.l2cap_evt.conn_handle,
  471. p_evt->evt.l2cap_evt.local_cid,
  472. &ch_id);
  473. if (retval != NRF_SUCCESS)
  474. {
  475. BLE_IPSP_TRC("Reply on unknown channel, dropping the event.");
  476. }
  477. else
  478. {
  479. if (m_channel[ch_id].state == CHANNEL_CONNECTING)
  480. {
  481. // Channel created successfully.
  482. // Initialize IPSP handle.
  483. handle.conn_handle = p_evt->evt.l2cap_evt.conn_handle;
  484. handle.cid = p_evt->evt.l2cap_evt.local_cid;
  485. // Initialize the event.
  486. ipsp_event.evt_id = BLE_IPSP_EVT_CHANNEL_CONNECTED;
  487. ipsp_event.evt_result = NRF_SUCCESS;
  488. // Set the channel state appropriately.
  489. m_channel[ch_id].state = CHANNEL_CONNECTED;
  490. // Set the flag to trigger submission of the receive buffers to the softdevice.
  491. submit_rx_buffer = true;
  492. // Notify the event to the application.
  493. notify_event = true;
  494. }
  495. }
  496. break;
  497. }
  498. case BLE_L2CAP_EVT_CH_SETUP_REFUSED:
  499. {
  500. // This event is generated for both initiator and acceptor roles.
  501. // This event indicates that the IPSP channel establishment failed.
  502. retval = channel_search(p_evt->evt.l2cap_evt.conn_handle,
  503. p_evt->evt.l2cap_evt.local_cid,
  504. &ch_id);
  505. if (retval != NRF_SUCCESS)
  506. {
  507. BLE_IPSP_TRC("Reply on unknown channel, dropping the event.");
  508. }
  509. else
  510. {
  511. if (m_channel[ch_id].state == CHANNEL_CONNECTING)
  512. {
  513. // Channel creation failed as peer rejected the connection.
  514. // Initialize the event.
  515. ipsp_event.evt_id = BLE_IPSP_EVT_CHANNEL_CONNECTED;
  516. ipsp_event.evt_result = NRF_ERROR_BLE_IPSP_PEER_REJECTED;
  517. BLE_IPSP_ERR("Peer rejected channel creation request, reason %d",
  518. p_evt->evt.l2cap_evt.params.ch_setup_refused.status);
  519. // Free the channel.
  520. channel_free(ch_id);
  521. // Notify the event to the application.
  522. notify_event = true;
  523. }
  524. }
  525. break;
  526. }
  527. case BLE_L2CAP_EVT_CH_RELEASED:
  528. {
  529. BLE_IPSP_TRC("L2CAP Channel disconnected.");
  530. ipsp_event.evt_id = BLE_IPSP_EVT_CHANNEL_DISCONNECTED;
  531. retval = channel_search(p_evt->evt.l2cap_evt.conn_handle,
  532. p_evt->evt.l2cap_evt.local_cid,
  533. &ch_id);
  534. // Notify application of disconnection.
  535. if (retval == NRF_SUCCESS)
  536. {
  537. handle.conn_handle = p_evt->evt.l2cap_evt.conn_handle;
  538. handle.cid = p_evt->evt.l2cap_evt.local_cid;
  539. channel_free(ch_id);
  540. // Notify the event to the application.
  541. notify_event = true;
  542. }
  543. break;
  544. }
  545. case BLE_L2CAP_EVT_CH_RX:
  546. {
  547. ipsp_event.evt_id = BLE_IPSP_EVT_CHANNEL_DATA_RX;
  548. retval = channel_search(p_evt->evt.l2cap_evt.conn_handle,
  549. p_evt->evt.l2cap_evt.local_cid,
  550. &ch_id);
  551. if (retval == NRF_SUCCESS)
  552. {
  553. handle.conn_handle = p_evt->evt.l2cap_evt.conn_handle;
  554. handle.cid = p_evt->evt.l2cap_evt.local_cid;
  555. rx_buffer_mark_unused(ch_id, p_evt->evt.l2cap_evt.params.rx.sdu_buf.p_data);
  556. // Set the flag to trigger submission of the receive buffers to the softdevice.
  557. submit_rx_buffer = true;
  558. // Notify the event to the application.
  559. notify_event = true;
  560. }
  561. break;
  562. }
  563. case BLE_L2CAP_EVT_CH_TX:
  564. {
  565. BLE_IPSP_TRC("BLE_L2CAP_EVT_CH_TX --> p_sdu_buf = %p, p_sdu_buf.p_data = %p",
  566. &p_evt->evt.l2cap_evt.params.tx.sdu_buf, p_evt->evt.l2cap_evt.params.tx.sdu_buf.p_data);
  567. retval = channel_search(p_evt->evt.l2cap_evt.conn_handle,
  568. p_evt->evt.l2cap_evt.local_cid,
  569. &ch_id);
  570. if ((ch_id != INVALID_CHANNEL_INSTANCE) &&
  571. p_evt->evt.l2cap_evt.local_cid == m_channel[ch_id].cid)
  572. {
  573. // Initialize the event.
  574. ipsp_event.evt_id = BLE_IPSP_EVT_CHANNEL_DATA_TX_COMPLETE;
  575. // Initialize the handle.
  576. handle.conn_handle = m_channel[ch_id].conn_handle;
  577. handle.cid = m_channel[ch_id].cid;
  578. // Notify the event to the application.
  579. notify_event = true;
  580. }
  581. break;
  582. }
  583. case BLE_L2CAP_EVT_CH_SDU_BUF_RELEASED:
  584. {
  585. BLE_IPSP_TRC("BLE_L2CAP_EVT_CH_SDU_BUF_RELEASED --> p_sdu_buf = %p, p_sdu_buf.p_data = %p",
  586. &p_evt->evt.l2cap_evt.params.ch_sdu_buf_released.sdu_buf,
  587. p_evt->evt.l2cap_evt.params.ch_sdu_buf_released.sdu_buf.p_data);
  588. retval = channel_search(p_evt->evt.l2cap_evt.conn_handle,
  589. p_evt->evt.l2cap_evt.local_cid,
  590. &ch_id);
  591. if ((ch_id != INVALID_CHANNEL_INSTANCE) &&
  592. (p_evt->evt.l2cap_evt.local_cid == m_channel[ch_id].cid) &&
  593. (is_tx_buffer(ch_id, p_evt->evt.l2cap_evt.params.ch_sdu_buf_released.sdu_buf.p_data)))
  594. {
  595. // Initialize the event.
  596. ipsp_event.evt_id = BLE_IPSP_EVT_CHANNEL_DATA_TX_COMPLETE;
  597. ipsp_event.evt_result = NRF_ERROR_BLE_IPSP_LINK_DISCONNECTED;
  598. // Initialize the handle.
  599. handle.conn_handle = m_channel[ch_id].conn_handle;
  600. handle.cid = m_channel[ch_id].cid;
  601. // Notify the event to the application.
  602. notify_event = true;
  603. }
  604. break;
  605. }
  606. case BLE_GAP_EVT_DISCONNECTED:
  607. {
  608. uint32_t peer_device_index = connected_device_search(handle.conn_handle);
  609. if (peer_device_index < IPSP_MAX_CONNECTED_DEVICES)
  610. {
  611. connected_device_init(peer_device_index);
  612. }
  613. break;
  614. }
  615. default:
  616. break;
  617. }
  618. if (notify_event)
  619. {
  620. ble_ipsp_event_param_t event_param;
  621. uint32_t peer_device_index;
  622. peer_device_index = connected_device_search(handle.conn_handle);
  623. if (peer_device_index < IPSP_MAX_CONNECTED_DEVICES)
  624. {
  625. event_param.p_peer = &m_connected_device[peer_device_index].ble_addr;
  626. BLE_IPSP_TRC("Found peer device. Address type = 0x%02x",
  627. event_param.p_peer->addr_type);
  628. BLE_IPSP_DUMP((uint8_t *)event_param.p_peer->addr, 6);
  629. }
  630. else
  631. {
  632. event_param.p_peer = NULL;
  633. }
  634. event_param.p_l2cap_evt = &p_evt->evt.l2cap_evt;
  635. ipsp_event.p_evt_param = &event_param;
  636. app_notify(&handle, &ipsp_event);
  637. }
  638. // Trigger submission of the receive buffers to the softdevice.
  639. if (submit_rx_buffer)
  640. {
  641. rx_buffers_submit(ch_id);
  642. }
  643. BLE_IPSP_MUTEX_UNLOCK();
  644. UNUSED_VARIABLE(retval);
  645. }
  646. uint32_t ble_ipsp_init(const ble_ipsp_init_t * p_init)
  647. {
  648. BLE_IPSP_ENTRY();
  649. ble_uuid_t ble_uuid;
  650. uint32_t err_code;
  651. uint16_t handle;
  652. NULL_PARAM_CHECK(p_init);
  653. NULL_PARAM_CHECK(p_init->evt_handler);
  654. SDK_MUTEX_INIT(m_ipsp_mutex);
  655. BLE_IPSP_MUTEX_LOCK();
  656. // Add service to indicate IPSP support.
  657. BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_IPSP_SERVICE);
  658. err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &handle);
  659. if (err_code != NRF_SUCCESS)
  660. {
  661. return err_code;
  662. }
  663. m_evt_handler = p_init->evt_handler;
  664. // Initialize the channel.
  665. for (int i = 0; i < BLE_IPSP_MAX_CHANNELS; i++)
  666. {
  667. channel_init(i);
  668. }
  669. // Initialize the connected peer device table.
  670. for (int i = 0; i < IPSP_MAX_CONNECTED_DEVICES; i++)
  671. {
  672. connected_device_init(i);
  673. }
  674. BLE_IPSP_MUTEX_UNLOCK();
  675. BLE_IPSP_EXIT();
  676. return NRF_SUCCESS;
  677. }
  678. uint32_t ble_ipsp_connect(const ble_ipsp_handle_t * p_handle)
  679. {
  680. VERIFY_MODULE_IS_INITIALIZED();
  681. NULL_PARAM_CHECK(p_handle);
  682. VERIFY_CON_HANDLE(p_handle->conn_handle);
  683. uint32_t err_code;
  684. uint8_t ch_id = INVALID_CHANNEL_INSTANCE;
  685. BLE_IPSP_TRC("[Conn Handle 0x%04X]: >> ble_ipsp_connect",
  686. p_handle->conn_handle);
  687. BLE_IPSP_MUTEX_LOCK();
  688. // Check if channel already exists with the peer.
  689. err_code = channel_search(p_handle->conn_handle, IPSP_ANY_CID, &ch_id);
  690. if (err_code == NRF_SUCCESS)
  691. {
  692. // IPSP channel already exists.
  693. err_code = NRF_ERROR_BLE_IPSP_CHANNEL_ALREADY_EXISTS;
  694. }
  695. else
  696. {
  697. // Search for a free channel.
  698. err_code = channel_search(BLE_CONN_HANDLE_INVALID, BLE_L2CAP_CID_INVALID, &ch_id);
  699. BLE_IPSP_TRC("2 channel_search result %08X", err_code);
  700. if (err_code == NRF_SUCCESS)
  701. {
  702. m_channel[ch_id].state = CHANNEL_CONNECTING;
  703. ble_l2cap_ch_setup_params_t param =
  704. {
  705. .le_psm = BLE_IPSP_PSM,
  706. .rx_params = {
  707. .rx_mtu = BLE_IPSP_MTU,
  708. .rx_mps = BLE_IPSP_RX_MPS,
  709. .sdu_buf =
  710. {
  711. .p_data = NULL,
  712. .len = 0
  713. }
  714. }
  715. };
  716. BLE_IPSP_TRC("Requesting sd_ble_l2cap_ch_setup");
  717. err_code = sd_ble_l2cap_ch_setup(p_handle->conn_handle,
  718. &m_channel[ch_id].cid,
  719. &param);
  720. if (err_code != NRF_SUCCESS)
  721. {
  722. BLE_IPSP_ERR("sd_ble_l2cap_ch_conn_request failed, reason %08lX", err_code);
  723. channel_free(ch_id);
  724. }
  725. else
  726. {
  727. BLE_IPSP_TRC("Local channel id from SD %04X.", m_channel[ch_id].cid);
  728. m_channel[ch_id].conn_handle = p_handle->conn_handle;
  729. }
  730. }
  731. else
  732. {
  733. err_code = (NRF_ERROR_BLE_IPSP_ERR_BASE + NRF_ERROR_NO_MEM);
  734. }
  735. }
  736. BLE_IPSP_MUTEX_UNLOCK();
  737. BLE_IPSP_EXIT_WITH_RESULT(err_code);
  738. return err_code;
  739. }
  740. uint32_t ble_ipsp_send(ble_ipsp_handle_t const * p_handle,
  741. uint8_t const * p_data,
  742. uint16_t data_len)
  743. {
  744. BLE_IPSP_ENTRY();
  745. VERIFY_MODULE_IS_INITIALIZED();
  746. NULL_PARAM_CHECK(p_handle);
  747. NULL_PARAM_CHECK(p_data);
  748. VERIFY_CON_HANDLE(p_handle->conn_handle);
  749. uint32_t err_code;
  750. uint8_t ch_id;
  751. BLE_IPSP_MUTEX_LOCK();
  752. err_code = channel_search(p_handle->conn_handle, p_handle->cid, &ch_id);
  753. if (err_code == NRF_SUCCESS)
  754. {
  755. const ble_data_t p_sdu_buf =
  756. {
  757. .p_data = (uint8_t *)p_data,
  758. .len = data_len
  759. };
  760. BLE_IPSP_TRC("p_sdu_buf = %p, p_sdu_buf.p_data = %p",
  761. &p_sdu_buf, p_data);
  762. err_code = sd_ble_l2cap_ch_tx(p_handle->conn_handle,
  763. p_handle->cid,
  764. &p_sdu_buf);
  765. }
  766. BLE_IPSP_MUTEX_UNLOCK();
  767. BLE_IPSP_EXIT_WITH_RESULT(err_code);
  768. return err_code;
  769. }
  770. uint32_t ble_ipsp_disconnect(ble_ipsp_handle_t const * p_handle)
  771. {
  772. BLE_IPSP_ENTRY();
  773. VERIFY_MODULE_IS_INITIALIZED();
  774. NULL_PARAM_CHECK(p_handle);
  775. VERIFY_CON_HANDLE(p_handle->conn_handle);
  776. uint32_t err_code;
  777. uint8_t ch_id;
  778. BLE_IPSP_MUTEX_LOCK();
  779. err_code = channel_search(p_handle->conn_handle, p_handle->cid, &ch_id);
  780. if (err_code == NRF_SUCCESS)
  781. {
  782. m_channel[ch_id].state = CHANNEL_DISCONNECTING;
  783. err_code = sd_ble_l2cap_ch_release(p_handle->conn_handle,
  784. p_handle->cid);
  785. }
  786. BLE_IPSP_MUTEX_UNLOCK();
  787. BLE_IPSP_EXIT_WITH_RESULT(err_code);
  788. return err_code;
  789. }
  790. void ble_ipsp_incoming_channel_reject(uint16_t conn_handle)
  791. {
  792. uint32_t peer_device_index = connected_device_search(conn_handle);
  793. if (peer_device_index != IPSP_MAX_CONNECTED_DEVICES)
  794. {
  795. m_connected_device[peer_device_index].response = INCOMING_CHANNEL_REJECT;
  796. }
  797. }
  798. void ble_ipsp_incoming_channel_accept(uint16_t conn_handle)
  799. {
  800. uint32_t peer_device_index = connected_device_search(conn_handle);
  801. if (peer_device_index != IPSP_MAX_CONNECTED_DEVICES)
  802. {
  803. m_connected_device[peer_device_index].response = INCOMING_CHANNEL_ACCEPT;
  804. }
  805. }