gap_conn.c 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211
  1. /******************************************************************************
  2. *
  3. * Copyright (C) 2009-2013 Broadcom Corporation
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at:
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. ******************************************************************************/
  18. #include "common/bt_target.h"
  19. #include "common/bt_defs.h"
  20. #include "stack/btu.h"
  21. #include "gap_int.h"
  22. #include "stack/l2cdefs.h"
  23. #include "l2c_int.h"
  24. #include <string.h>
  25. #include "osi/mutex.h"
  26. #include "osi/allocator.h"
  27. #if GAP_CONN_INCLUDED == TRUE
  28. #include "btm_int.h"
  29. /********************************************************************************/
  30. /* L O C A L F U N C T I O N P R O T O T Y P E S */
  31. /********************************************************************************/
  32. static void gap_connect_ind (BD_ADDR bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id);
  33. static void gap_connect_cfm (UINT16 l2cap_cid, UINT16 result);
  34. static void gap_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
  35. static void gap_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
  36. static void gap_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed);
  37. static void gap_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg);
  38. static void gap_congestion_ind (UINT16 lcid, BOOLEAN is_congested);
  39. static tGAP_CCB *gap_find_ccb_by_cid (UINT16 cid);
  40. static tGAP_CCB *gap_find_ccb_by_handle (UINT16 handle);
  41. static tGAP_CCB *gap_allocate_ccb (void);
  42. static void gap_release_ccb (tGAP_CCB *p_ccb);
  43. /*******************************************************************************
  44. **
  45. ** Function gap_conn_init
  46. **
  47. ** Description This function is called to initialize GAP connection management
  48. **
  49. ** Returns void
  50. **
  51. *******************************************************************************/
  52. void gap_conn_init (void)
  53. {
  54. #if ((defined AMP_INCLUDED) && (AMP_INCLUDED == TRUE))
  55. gap_cb.conn.reg_info.pAMP_ConnectInd_Cb = gap_connect_ind;
  56. gap_cb.conn.reg_info.pAMP_ConnectCfm_Cb = gap_connect_cfm;
  57. gap_cb.conn.reg_info.pAMP_ConnectPnd_Cb = NULL;
  58. gap_cb.conn.reg_info.pAMP_ConfigInd_Cb = gap_config_ind;
  59. gap_cb.conn.reg_info.pAMP_ConfigCfm_Cb = gap_config_cfm;
  60. gap_cb.conn.reg_info.pAMP_DisconnectInd_Cb = gap_disconnect_ind;
  61. gap_cb.conn.reg_info.pAMP_DisconnectCfm_Cb = NULL;
  62. gap_cb.conn.reg_info.pAMP_QoSViolationInd_Cb = NULL;
  63. gap_cb.conn.reg_info.pAMP_DataInd_Cb = gap_data_ind;
  64. gap_cb.conn.reg_info.pAMP_CongestionStatus_Cb = gap_congestion_ind;
  65. gap_cb.conn.reg_info.pAMP_TxComplete_Cb = NULL;
  66. gap_cb.conn.reg_info.pAMP_MoveInd_Cb = NULL;
  67. gap_cb.conn.reg_info.pAMP_MoveRsp_Cb = NULL;
  68. gap_cb.conn.reg_info.pAMP_MoveCfm_Cb = NULL; //gap_move_cfm
  69. gap_cb.conn.reg_info.pAMP_MoveCfmRsp_Cb = NULL; //gap_move_cfm_rsp
  70. #else
  71. gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind;
  72. gap_cb.conn.reg_info.pL2CA_ConnectCfm_Cb = gap_connect_cfm;
  73. gap_cb.conn.reg_info.pL2CA_ConnectPnd_Cb = NULL;
  74. gap_cb.conn.reg_info.pL2CA_ConfigInd_Cb = gap_config_ind;
  75. gap_cb.conn.reg_info.pL2CA_ConfigCfm_Cb = gap_config_cfm;
  76. gap_cb.conn.reg_info.pL2CA_DisconnectInd_Cb = gap_disconnect_ind;
  77. gap_cb.conn.reg_info.pL2CA_DisconnectCfm_Cb = NULL;
  78. gap_cb.conn.reg_info.pL2CA_QoSViolationInd_Cb = NULL;
  79. gap_cb.conn.reg_info.pL2CA_DataInd_Cb = gap_data_ind;
  80. gap_cb.conn.reg_info.pL2CA_CongestionStatus_Cb = gap_congestion_ind;
  81. gap_cb.conn.reg_info.pL2CA_TxComplete_Cb = NULL;
  82. #endif
  83. }
  84. /*******************************************************************************
  85. **
  86. ** Function GAP_ConnOpen
  87. **
  88. ** Description This function is called to open an L2CAP connection.
  89. **
  90. ** Parameters: is_server - If TRUE, the connection is not created
  91. ** but put into a "listen" mode waiting for
  92. ** the remote side to connect.
  93. **
  94. ** service_id - Unique service ID from
  95. ** BTM_SEC_SERVICE_FIRST_EMPTY (6)
  96. ** to BTM_SEC_MAX_SERVICE_RECORDS (32)
  97. **
  98. ** p_rem_bda - Pointer to remote BD Address.
  99. ** If a server, and we don't care about the
  100. ** remote BD Address, then NULL should be passed.
  101. **
  102. ** psm - the PSM used for the connection
  103. **
  104. ** p_config - Optional pointer to configuration structure.
  105. ** If NULL, the default GAP configuration will
  106. ** be used.
  107. **
  108. ** security - security flags
  109. ** chan_mode_mask - (GAP_FCR_CHAN_OPT_BASIC, GAP_FCR_CHAN_OPT_ERTM,
  110. ** GAP_FCR_CHAN_OPT_STREAM)
  111. **
  112. ** p_cb - Pointer to callback function for events.
  113. **
  114. ** Returns handle of the connection if successful, else GAP_INVALID_HANDLE
  115. **
  116. *******************************************************************************/
  117. UINT16 GAP_ConnOpen (const char *p_serv_name, UINT8 service_id, BOOLEAN is_server,
  118. BD_ADDR p_rem_bda, UINT16 psm, tL2CAP_CFG_INFO *p_cfg,
  119. tL2CAP_ERTM_INFO *ertm_info, UINT16 security, UINT8 chan_mode_mask,
  120. tGAP_CONN_CALLBACK *p_cb)
  121. {
  122. tGAP_CCB *p_ccb;
  123. UINT16 cid;
  124. //tBT_UUID bt_uuid = {2, {GAP_PROTOCOL_ID}};
  125. GAP_TRACE_EVENT ("GAP_CONN - Open Request");
  126. /* Allocate a new CCB. Return if none available. */
  127. if ((p_ccb = gap_allocate_ccb()) == NULL) {
  128. return (GAP_INVALID_HANDLE);
  129. }
  130. /* If caller specified a BD address, save it */
  131. if (p_rem_bda) {
  132. /* the bd addr is not BT_BD_ANY, then a bd address was specified */
  133. if (memcmp (p_rem_bda, BT_BD_ANY, BD_ADDR_LEN)) {
  134. p_ccb->rem_addr_specified = TRUE;
  135. }
  136. memcpy (&p_ccb->rem_dev_address[0], p_rem_bda, BD_ADDR_LEN);
  137. } else if (!is_server) {
  138. /* remore addr is not specified and is not a server -> bad */
  139. return (GAP_INVALID_HANDLE);
  140. }
  141. /* A client MUST have specified a bd addr to connect with */
  142. if (!p_ccb->rem_addr_specified && !is_server) {
  143. gap_release_ccb (p_ccb);
  144. GAP_TRACE_ERROR ("GAP ERROR: Client must specify a remote BD ADDR to connect to!");
  145. return (GAP_INVALID_HANDLE);
  146. }
  147. /* Check if configuration was specified */
  148. if (p_cfg) {
  149. p_ccb->cfg = *p_cfg;
  150. }
  151. p_ccb->p_callback = p_cb;
  152. /* If originator, use a dynamic PSM */
  153. #if ((defined AMP_INCLUDED) && (AMP_INCLUDED == TRUE))
  154. if (!is_server) {
  155. gap_cb.conn.reg_info.pAMP_ConnectInd_Cb = NULL;
  156. } else {
  157. gap_cb.conn.reg_info.pAMP_ConnectInd_Cb = gap_connect_ind;
  158. }
  159. #else
  160. if (!is_server) {
  161. gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = NULL;
  162. } else {
  163. gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind;
  164. }
  165. #endif
  166. /* Register the PSM with L2CAP */
  167. if ((p_ccb->psm = L2CA_REGISTER (psm, &gap_cb.conn.reg_info,
  168. AMP_AUTOSWITCH_ALLOWED | AMP_USE_AMP_IF_POSSIBLE)) == 0) {
  169. GAP_TRACE_ERROR ("GAP_ConnOpen: Failure registering PSM 0x%04x", psm);
  170. gap_release_ccb (p_ccb);
  171. return (GAP_INVALID_HANDLE);
  172. }
  173. /* Register with Security Manager for the specific security level */
  174. p_ccb->service_id = service_id;
  175. if (!BTM_SetSecurityLevel ((UINT8)!is_server, p_serv_name,
  176. p_ccb->service_id, security, p_ccb->psm, 0, 0)) {
  177. GAP_TRACE_ERROR ("GAP_CONN - Security Error");
  178. gap_release_ccb (p_ccb);
  179. return (GAP_INVALID_HANDLE);
  180. }
  181. /* Fill in eL2CAP parameter data */
  182. if ( p_ccb->cfg.fcr_present ) {
  183. if (ertm_info == NULL) {
  184. p_ccb->ertm_info.preferred_mode = p_ccb->cfg.fcr.mode;
  185. p_ccb->ertm_info.user_rx_buf_size = GAP_DATA_BUF_SIZE;
  186. p_ccb->ertm_info.user_tx_buf_size = GAP_DATA_BUF_SIZE;
  187. p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_INVALID_ERM_BUF_SIZE;
  188. p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_INVALID_ERM_BUF_SIZE;
  189. } else {
  190. p_ccb->ertm_info = *ertm_info;
  191. }
  192. }
  193. /* optional FCR channel modes */
  194. if (ertm_info != NULL) {
  195. p_ccb->ertm_info.allowed_modes =
  196. (chan_mode_mask) ? chan_mode_mask : (UINT8)L2CAP_FCR_CHAN_OPT_BASIC;
  197. }
  198. if (is_server) {
  199. p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE; /* assume btm/l2cap would handle it */
  200. p_ccb->con_state = GAP_CCB_STATE_LISTENING;
  201. return (p_ccb->gap_handle);
  202. } else {
  203. /* We are the originator of this connection */
  204. p_ccb->con_flags = GAP_CCB_FLAGS_IS_ORIG;
  205. /* Transition to the next appropriate state, waiting for connection confirm. */
  206. p_ccb->con_state = GAP_CCB_STATE_CONN_SETUP;
  207. /* mark security done flag, when security is not required */
  208. if ((security & (BTM_SEC_OUT_AUTHORIZE | BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT) ) == 0) {
  209. p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
  210. }
  211. /* Check if L2CAP started the connection process */
  212. if (p_rem_bda && ((cid = L2CA_CONNECT_REQ (p_ccb->psm, p_rem_bda, &p_ccb->ertm_info, &bt_uuid)) != 0)) {
  213. p_ccb->connection_id = cid;
  214. return (p_ccb->gap_handle);
  215. } else {
  216. gap_release_ccb (p_ccb);
  217. return (GAP_INVALID_HANDLE);
  218. }
  219. }
  220. }
  221. /*******************************************************************************
  222. **
  223. ** Function GAP_ConnClose
  224. **
  225. ** Description This function is called to close a connection.
  226. **
  227. ** Parameters: handle - Handle of the connection returned by GAP_ConnOpen
  228. **
  229. ** Returns BT_PASS - closed OK
  230. ** GAP_ERR_BAD_HANDLE - invalid handle
  231. **
  232. *******************************************************************************/
  233. UINT16 GAP_ConnClose (UINT16 gap_handle)
  234. {
  235. tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
  236. GAP_TRACE_EVENT ("GAP_CONN - close handle: 0x%x", gap_handle);
  237. if (p_ccb) {
  238. /* Check if we have a connection ID */
  239. if (p_ccb->con_state != GAP_CCB_STATE_LISTENING) {
  240. L2CA_DISCONNECT_REQ (p_ccb->connection_id);
  241. }
  242. gap_release_ccb (p_ccb);
  243. return (BT_PASS);
  244. }
  245. return (GAP_ERR_BAD_HANDLE);
  246. }
  247. /*******************************************************************************
  248. **
  249. ** Function GAP_ConnReadData
  250. **
  251. ** Description Normally not GKI aware application will call this function
  252. ** after receiving GAP_EVT_RXDATA event.
  253. **
  254. ** Parameters: handle - Handle of the connection returned in the Open
  255. ** p_data - Data area
  256. ** max_len - Byte count requested
  257. ** p_len - Byte count received
  258. **
  259. ** Returns BT_PASS - data read
  260. ** GAP_ERR_BAD_HANDLE - invalid handle
  261. ** GAP_NO_DATA_AVAIL - no data available
  262. **
  263. *******************************************************************************/
  264. UINT16 GAP_ConnReadData (UINT16 gap_handle, UINT8 *p_data, UINT16 max_len, UINT16 *p_len)
  265. {
  266. tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
  267. UINT16 copy_len;
  268. if (!p_ccb) {
  269. return (GAP_ERR_BAD_HANDLE);
  270. }
  271. *p_len = 0;
  272. if (fixed_queue_is_empty(p_ccb->rx_queue)) {
  273. return (GAP_NO_DATA_AVAIL);
  274. }
  275. osi_mutex_global_lock();
  276. while (max_len) {
  277. BT_HDR *p_buf = fixed_queue_try_peek_first(p_ccb->rx_queue);
  278. if (p_buf == NULL) {
  279. break;
  280. }
  281. copy_len = (p_buf->len > max_len)?max_len:p_buf->len;
  282. max_len -= copy_len;
  283. *p_len += copy_len;
  284. if (p_data) {
  285. memcpy (p_data, (UINT8 *)(p_buf + 1) + p_buf->offset, copy_len);
  286. p_data += copy_len;
  287. }
  288. if (p_buf->len > copy_len) {
  289. p_buf->offset += copy_len;
  290. p_buf->len -= copy_len;
  291. break;
  292. }
  293. osi_free(fixed_queue_dequeue(p_ccb->rx_queue, 0));
  294. }
  295. p_ccb->rx_queue_size -= *p_len;
  296. osi_mutex_global_unlock();
  297. GAP_TRACE_EVENT ("GAP_ConnReadData - rx_queue_size left=%d, *p_len=%d",
  298. p_ccb->rx_queue_size, *p_len);
  299. return (BT_PASS);
  300. }
  301. /*******************************************************************************
  302. **
  303. ** Function GAP_GetRxQueueCnt
  304. **
  305. ** Description This function return number of bytes on the rx queue.
  306. **
  307. ** Parameters: handle - Handle returned in the GAP_ConnOpen
  308. ** p_rx_queue_count - Pointer to return queue count in.
  309. **
  310. **
  311. *******************************************************************************/
  312. int GAP_GetRxQueueCnt (UINT16 handle, UINT32 *p_rx_queue_count)
  313. {
  314. tGAP_CCB *p_ccb;
  315. int rc = BT_PASS;
  316. /* Check that handle is valid */
  317. if (handle < GAP_MAX_CONNECTIONS) {
  318. p_ccb = &gap_cb.conn.ccb_pool[handle];
  319. if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED) {
  320. *p_rx_queue_count = p_ccb->rx_queue_size;
  321. } else {
  322. rc = GAP_INVALID_HANDLE;
  323. }
  324. } else {
  325. rc = GAP_INVALID_HANDLE;
  326. }
  327. GAP_TRACE_EVENT ("GAP_GetRxQueueCnt - rc = 0x%04x, rx_queue_count=%d",
  328. rc , *p_rx_queue_count);
  329. return (rc);
  330. }
  331. /*******************************************************************************
  332. **
  333. ** Function GAP_ConnBTRead
  334. **
  335. ** Description Bluetooth aware applications will call this function after receiving
  336. ** GAP_EVT_RXDATA event.
  337. **
  338. ** Parameters: handle - Handle of the connection returned in the Open
  339. ** pp_buf - pointer to address of buffer with data,
  340. **
  341. ** Returns BT_PASS - data read
  342. ** GAP_ERR_BAD_HANDLE - invalid handle
  343. ** GAP_NO_DATA_AVAIL - no data available
  344. **
  345. *******************************************************************************/
  346. UINT16 GAP_ConnBTRead (UINT16 gap_handle, BT_HDR **pp_buf)
  347. {
  348. tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
  349. BT_HDR *p_buf;
  350. if (!p_ccb) {
  351. return (GAP_ERR_BAD_HANDLE);
  352. }
  353. p_buf = (BT_HDR *)fixed_queue_dequeue(p_ccb->rx_queue, 0);
  354. if (p_buf) {
  355. *pp_buf = p_buf;
  356. p_ccb->rx_queue_size -= p_buf->len;
  357. return (BT_PASS);
  358. } else {
  359. *pp_buf = NULL;
  360. return (GAP_NO_DATA_AVAIL);
  361. }
  362. }
  363. /*******************************************************************************
  364. **
  365. ** Function GAP_ConnBTWrite
  366. **
  367. ** Description Bluetooth Aware applications can call this function to write data.
  368. **
  369. ** Parameters: handle - Handle of the connection returned in the Open
  370. ** p_buf - pointer to address of buffer with data,
  371. **
  372. ** Returns BT_PASS - data read
  373. ** GAP_ERR_BAD_HANDLE - invalid handle
  374. ** GAP_ERR_BAD_STATE - connection not established
  375. ** GAP_INVALID_BUF_OFFSET - buffer offset is invalid
  376. *******************************************************************************/
  377. UINT16 GAP_ConnBTWrite (UINT16 gap_handle, BT_HDR *p_buf)
  378. {
  379. tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
  380. if (!p_ccb) {
  381. osi_free (p_buf);
  382. return (GAP_ERR_BAD_HANDLE);
  383. }
  384. if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED) {
  385. osi_free (p_buf);
  386. return (GAP_ERR_BAD_STATE);
  387. }
  388. if (p_buf->offset < L2CAP_MIN_OFFSET) {
  389. osi_free (p_buf);
  390. return (GAP_ERR_BUF_OFFSET);
  391. }
  392. fixed_queue_enqueue(p_ccb->tx_queue, p_buf, FIXED_QUEUE_MAX_TIMEOUT);
  393. if (p_ccb->is_congested) {
  394. return (BT_PASS);
  395. }
  396. /* Send the buffer through L2CAP */
  397. #if (GAP_CONN_POST_EVT_INCLUDED == TRUE)
  398. gap_send_event (gap_handle);
  399. #else
  400. while ((p_buf = (BT_HDR *)fixed_queue_dequeue(p_ccb->tx_queue, 0)) != NULL) {
  401. UINT8 status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf);
  402. if (status == L2CAP_DW_CONGESTED) {
  403. p_ccb->is_congested = TRUE;
  404. break;
  405. } else if (status != L2CAP_DW_SUCCESS) {
  406. return (GAP_ERR_BAD_STATE);
  407. }
  408. }
  409. #endif
  410. return (BT_PASS);
  411. }
  412. /*******************************************************************************
  413. **
  414. ** Function GAP_ConnWriteData
  415. **
  416. ** Description Normally not GKI aware application will call this function
  417. ** to send data to the connection.
  418. **
  419. ** Parameters: handle - Handle of the connection returned in the Open
  420. ** p_data - Data area
  421. ** max_len - Byte count requested
  422. ** p_len - Byte count received
  423. **
  424. ** Returns BT_PASS - data read
  425. ** GAP_ERR_BAD_HANDLE - invalid handle
  426. ** GAP_ERR_BAD_STATE - connection not established
  427. ** GAP_CONGESTION - system is congested
  428. **
  429. *******************************************************************************/
  430. UINT16 GAP_ConnWriteData (UINT16 gap_handle, UINT8 *p_data, UINT16 max_len, UINT16 *p_len)
  431. {
  432. tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
  433. BT_HDR *p_buf;
  434. *p_len = 0;
  435. if (!p_ccb) {
  436. return (GAP_ERR_BAD_HANDLE);
  437. }
  438. if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED) {
  439. return (GAP_ERR_BAD_STATE);
  440. }
  441. while (max_len) {
  442. if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) {
  443. if ((p_buf = (BT_HDR *)osi_malloc(L2CAP_FCR_ERTM_BUF_SIZE)) == NULL) {
  444. return (GAP_ERR_CONGESTED);
  445. }
  446. } else {
  447. if ((p_buf = (BT_HDR *)osi_malloc(GAP_DATA_BUF_SIZE)) == NULL) {
  448. return (GAP_ERR_CONGESTED);
  449. }
  450. }
  451. p_buf->offset = L2CAP_MIN_OFFSET;
  452. p_buf->len = (p_ccb->rem_mtu_size < max_len) ? p_ccb->rem_mtu_size : max_len;
  453. p_buf->event = BT_EVT_TO_BTU_SP_DATA;
  454. memcpy ((UINT8 *)(p_buf + 1) + p_buf->offset, p_data, p_buf->len);
  455. *p_len += p_buf->len;
  456. max_len -= p_buf->len;
  457. p_data += p_buf->len;
  458. GAP_TRACE_EVENT ("GAP_WriteData %d bytes", p_buf->len);
  459. fixed_queue_enqueue(p_ccb->tx_queue, p_buf, FIXED_QUEUE_MAX_TIMEOUT);
  460. }
  461. if (p_ccb->is_congested) {
  462. return (BT_PASS);
  463. }
  464. /* Send the buffer through L2CAP */
  465. #if (GAP_CONN_POST_EVT_INCLUDED == TRUE)
  466. gap_send_event (gap_handle);
  467. #else
  468. while ((p_buf = (BT_HDR *)fixed_queue_dequeue(p_ccb->tx_queue, 0)) != NULL)
  469. {
  470. UINT8 status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf);
  471. if (status == L2CAP_DW_CONGESTED) {
  472. p_ccb->is_congested = TRUE;
  473. break;
  474. } else if (status != L2CAP_DW_SUCCESS) {
  475. return (GAP_ERR_BAD_STATE);
  476. }
  477. }
  478. #endif
  479. return (BT_PASS);
  480. }
  481. /*******************************************************************************
  482. **
  483. ** Function GAP_ConnReconfig
  484. **
  485. ** Description Applications can call this function to reconfigure the connection.
  486. **
  487. ** Parameters: handle - Handle of the connection
  488. ** p_cfg - Pointer to new configuration
  489. **
  490. ** Returns BT_PASS - config process started
  491. ** GAP_ERR_BAD_HANDLE - invalid handle
  492. **
  493. *******************************************************************************/
  494. UINT16 GAP_ConnReconfig (UINT16 gap_handle, tL2CAP_CFG_INFO *p_cfg)
  495. {
  496. tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
  497. if (!p_ccb) {
  498. return (GAP_ERR_BAD_HANDLE);
  499. }
  500. p_ccb->cfg = *p_cfg;
  501. if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED) {
  502. L2CA_CONFIG_REQ (p_ccb->connection_id, p_cfg);
  503. }
  504. return (BT_PASS);
  505. }
  506. /*******************************************************************************
  507. **
  508. ** Function GAP_ConnSetIdleTimeout
  509. **
  510. ** Description Higher layers call this function to set the idle timeout for
  511. ** a connection, or for all future connections. The "idle timeout"
  512. ** is the amount of time that a connection can remain up with
  513. ** no L2CAP channels on it. A timeout of zero means that the
  514. ** connection will be torn down immediately when the last channel
  515. ** is removed. A timeout of 0xFFFF means no timeout. Values are
  516. ** in seconds.
  517. **
  518. ** Parameters: handle - Handle of the connection
  519. ** timeout - in secs
  520. ** 0 = immediate disconnect when last channel is removed
  521. ** 0xFFFF = no idle timeout
  522. **
  523. ** Returns BT_PASS - config process started
  524. ** GAP_ERR_BAD_HANDLE - invalid handle
  525. **
  526. *******************************************************************************/
  527. UINT16 GAP_ConnSetIdleTimeout (UINT16 gap_handle, UINT16 timeout)
  528. {
  529. tGAP_CCB *p_ccb;
  530. if ((p_ccb = gap_find_ccb_by_handle (gap_handle)) == NULL) {
  531. return (GAP_ERR_BAD_HANDLE);
  532. }
  533. if (L2CA_SetIdleTimeout (p_ccb->connection_id, timeout, FALSE)) {
  534. return (BT_PASS);
  535. } else {
  536. return (GAP_ERR_BAD_HANDLE);
  537. }
  538. }
  539. /*******************************************************************************
  540. **
  541. ** Function GAP_ConnGetRemoteAddr
  542. **
  543. ** Description This function is called to get the remote BD address
  544. ** of a connection.
  545. **
  546. ** Parameters: handle - Handle of the connection returned by GAP_ConnOpen
  547. **
  548. ** Returns BT_PASS - closed OK
  549. ** GAP_ERR_BAD_HANDLE - invalid handle
  550. **
  551. *******************************************************************************/
  552. UINT8 *GAP_ConnGetRemoteAddr (UINT16 gap_handle)
  553. {
  554. tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
  555. GAP_TRACE_EVENT ("GAP_ConnGetRemoteAddr gap_handle = %d", gap_handle);
  556. if ((p_ccb) && (p_ccb->con_state > GAP_CCB_STATE_LISTENING)) {
  557. GAP_TRACE_EVENT("GAP_ConnGetRemoteAddr bda :0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", \
  558. p_ccb->rem_dev_address[0], p_ccb->rem_dev_address[1], p_ccb->rem_dev_address[2],
  559. p_ccb->rem_dev_address[3], p_ccb->rem_dev_address[4], p_ccb->rem_dev_address[5]);
  560. return (p_ccb->rem_dev_address);
  561. } else {
  562. GAP_TRACE_EVENT ("GAP_ConnGetRemoteAddr return Error ");
  563. return (NULL);
  564. }
  565. }
  566. /*******************************************************************************
  567. **
  568. ** Function GAP_ConnGetRemMtuSize
  569. **
  570. ** Description Returns the remote device's MTU size
  571. **
  572. ** Parameters: handle - Handle of the connection
  573. **
  574. ** Returns UINT16 - maximum size buffer that can be transmitted to the peer
  575. **
  576. *******************************************************************************/
  577. UINT16 GAP_ConnGetRemMtuSize (UINT16 gap_handle)
  578. {
  579. tGAP_CCB *p_ccb;
  580. if ((p_ccb = gap_find_ccb_by_handle (gap_handle)) == NULL) {
  581. return (0);
  582. }
  583. return (p_ccb->rem_mtu_size);
  584. }
  585. /*******************************************************************************
  586. **
  587. ** Function GAP_ConnGetL2CAPCid
  588. **
  589. ** Description Returns the L2CAP channel id
  590. **
  591. ** Parameters: handle - Handle of the connection
  592. **
  593. ** Returns UINT16 - The L2CAP channel id
  594. ** 0, if error
  595. **
  596. *******************************************************************************/
  597. UINT16 GAP_ConnGetL2CAPCid (UINT16 gap_handle)
  598. {
  599. tGAP_CCB *p_ccb;
  600. if ((p_ccb = gap_find_ccb_by_handle (gap_handle)) == NULL) {
  601. return (0);
  602. }
  603. return (p_ccb->connection_id);
  604. }
  605. /*******************************************************************************
  606. **
  607. ** Function gap_connect_ind
  608. **
  609. ** Description This function handles an inbound connection indication
  610. ** from L2CAP. This is the case where we are acting as a
  611. ** server.
  612. **
  613. ** Returns void
  614. **
  615. *******************************************************************************/
  616. static void gap_connect_ind (BD_ADDR bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id)
  617. {
  618. UINT16 xx;
  619. tGAP_CCB *p_ccb;
  620. //tBT_UUID bt_uuid = {2, {GAP_PROTOCOL_ID}};
  621. /* See if we have a CCB listening for the connection */
  622. for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) {
  623. if ((p_ccb->con_state == GAP_CCB_STATE_LISTENING)
  624. && (p_ccb->psm == psm)
  625. && ((p_ccb->rem_addr_specified == FALSE)
  626. || (!memcmp (bd_addr, p_ccb->rem_dev_address, BD_ADDR_LEN)))) {
  627. break;
  628. }
  629. }
  630. if (xx == GAP_MAX_CONNECTIONS) {
  631. GAP_TRACE_WARNING("*******");
  632. GAP_TRACE_WARNING("WARNING: GAP Conn Indication for Unexpected Bd Addr...Disconnecting");
  633. GAP_TRACE_WARNING("*******");
  634. /* Disconnect because it is an unexpected connection */
  635. L2CA_DISCONNECT_REQ (l2cap_cid);
  636. return;
  637. }
  638. /* Transition to the next appropriate state, waiting for config setup. */
  639. p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP;
  640. /* Save the BD Address and Channel ID. */
  641. memcpy (&p_ccb->rem_dev_address[0], bd_addr, BD_ADDR_LEN);
  642. p_ccb->connection_id = l2cap_cid;
  643. /* Send response to the L2CAP layer. */
  644. L2CA_CONNECT_RSP (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK, &p_ccb->ertm_info, &bt_uuid);
  645. GAP_TRACE_EVENT("GAP_CONN - Rcvd L2CAP conn ind, CID: 0x%x", p_ccb->connection_id);
  646. /* Send a Configuration Request. */
  647. L2CA_CONFIG_REQ (l2cap_cid, &p_ccb->cfg);
  648. }
  649. /*******************************************************************************
  650. **
  651. ** Function gap_checks_con_flags
  652. **
  653. ** Description This function processes the L2CAP configuration indication
  654. ** event.
  655. **
  656. ** Returns void
  657. **
  658. *******************************************************************************/
  659. static void gap_checks_con_flags (tGAP_CCB *p_ccb)
  660. {
  661. GAP_TRACE_EVENT ("gap_checks_con_flags conn_flags:0x%x, ", p_ccb->con_flags);
  662. /* if all the required con_flags are set, report the OPEN event now */
  663. if ((p_ccb->con_flags & GAP_CCB_FLAGS_CONN_DONE) == GAP_CCB_FLAGS_CONN_DONE) {
  664. p_ccb->con_state = GAP_CCB_STATE_CONNECTED;
  665. p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_OPENED);
  666. }
  667. }
  668. /*******************************************************************************
  669. **
  670. ** Function gap_sec_check_complete
  671. **
  672. ** Description The function called when Security Manager finishes
  673. ** verification of the service side connection
  674. **
  675. ** Returns void
  676. **
  677. *******************************************************************************/
  678. static void gap_sec_check_complete (BD_ADDR bd_addr, tBT_TRANSPORT transport, void *p_ref_data, UINT8 res)
  679. {
  680. tGAP_CCB *p_ccb = (tGAP_CCB *)p_ref_data;
  681. UNUSED(bd_addr);
  682. UNUSED (transport);
  683. GAP_TRACE_EVENT ("gap_sec_check_complete conn_state:%d, conn_flags:0x%x, status:%d",
  684. p_ccb->con_state, p_ccb->con_flags, res);
  685. if (p_ccb->con_state == GAP_CCB_STATE_IDLE) {
  686. return;
  687. }
  688. if (res == BTM_SUCCESS) {
  689. p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
  690. gap_checks_con_flags (p_ccb);
  691. } else {
  692. /* security failed - disconnect the channel */
  693. L2CA_DISCONNECT_REQ (p_ccb->connection_id);
  694. }
  695. }
  696. /*******************************************************************************
  697. **
  698. ** Function gap_connect_cfm
  699. **
  700. ** Description This function handles the connect confirm events
  701. ** from L2CAP. This is the case when we are acting as a
  702. ** client and have sent a connect request.
  703. **
  704. ** Returns void
  705. **
  706. *******************************************************************************/
  707. static void gap_connect_cfm (UINT16 l2cap_cid, UINT16 result)
  708. {
  709. tGAP_CCB *p_ccb;
  710. /* Find CCB based on CID */
  711. if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL) {
  712. return;
  713. }
  714. /* initiate security process, if needed */
  715. if ( (p_ccb->con_flags & GAP_CCB_FLAGS_SEC_DONE) == 0) {
  716. btm_sec_mx_access_request (p_ccb->rem_dev_address, p_ccb->psm, TRUE,
  717. 0, 0, &gap_sec_check_complete, p_ccb);
  718. }
  719. /* If the connection response contains success status, then */
  720. /* Transition to the next state and startup the timer. */
  721. if ((result == L2CAP_CONN_OK) && (p_ccb->con_state == GAP_CCB_STATE_CONN_SETUP)) {
  722. p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP;
  723. /* Send a Configuration Request. */
  724. L2CA_CONFIG_REQ (l2cap_cid, &p_ccb->cfg);
  725. } else {
  726. /* Tell the user if he has a callback */
  727. if (p_ccb->p_callback) {
  728. (*p_ccb->p_callback) (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);
  729. }
  730. gap_release_ccb (p_ccb);
  731. }
  732. }
  733. /*******************************************************************************
  734. **
  735. ** Function gap_config_ind
  736. **
  737. ** Description This function processes the L2CAP configuration indication
  738. ** event.
  739. **
  740. ** Returns void
  741. **
  742. *******************************************************************************/
  743. static void gap_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
  744. {
  745. tGAP_CCB *p_ccb;
  746. UINT16 local_mtu_size;
  747. /* Find CCB based on CID */
  748. if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL) {
  749. return;
  750. }
  751. /* Remember the remote MTU size */
  752. if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) {
  753. local_mtu_size = p_ccb->ertm_info.user_tx_buf_size
  754. - sizeof(BT_HDR) - L2CAP_MIN_OFFSET;
  755. } else {
  756. local_mtu_size = L2CAP_MTU_SIZE;
  757. }
  758. if ((!p_cfg->mtu_present) || (p_cfg->mtu > local_mtu_size)) {
  759. p_ccb->rem_mtu_size = local_mtu_size;
  760. } else {
  761. p_ccb->rem_mtu_size = p_cfg->mtu;
  762. }
  763. /* For now, always accept configuration from the other side */
  764. p_cfg->flush_to_present = FALSE;
  765. p_cfg->mtu_present = FALSE;
  766. p_cfg->result = L2CAP_CFG_OK;
  767. p_cfg->fcs_present = FALSE;
  768. L2CA_CONFIG_RSP (l2cap_cid, p_cfg);
  769. p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE;
  770. gap_checks_con_flags (p_ccb);
  771. }
  772. /*******************************************************************************
  773. **
  774. ** Function gap_config_cfm
  775. **
  776. ** Description This function processes the L2CAP configuration confirmation
  777. ** event.
  778. **
  779. ** Returns void
  780. **
  781. *******************************************************************************/
  782. static void gap_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
  783. {
  784. tGAP_CCB *p_ccb;
  785. /* Find CCB based on CID */
  786. if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL) {
  787. return;
  788. }
  789. if (p_cfg->result == L2CAP_CFG_OK) {
  790. p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE;
  791. if (p_ccb->cfg.fcr_present) {
  792. p_ccb->cfg.fcr.mode = p_cfg->fcr.mode;
  793. } else {
  794. p_ccb->cfg.fcr.mode = L2CAP_FCR_BASIC_MODE;
  795. }
  796. gap_checks_con_flags (p_ccb);
  797. } else {
  798. p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);
  799. gap_release_ccb (p_ccb);
  800. }
  801. }
  802. /*******************************************************************************
  803. **
  804. ** Function gap_disconnect_ind
  805. **
  806. ** Description This function handles a disconnect event from L2CAP. If
  807. ** requested to, we ack the disconnect before dropping the CCB
  808. **
  809. ** Returns void
  810. **
  811. *******************************************************************************/
  812. static void gap_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed)
  813. {
  814. tGAP_CCB *p_ccb;
  815. GAP_TRACE_EVENT ("GAP_CONN - Rcvd L2CAP disc, CID: 0x%x", l2cap_cid);
  816. /* Find CCB based on CID */
  817. if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL) {
  818. return;
  819. }
  820. if (ack_needed) {
  821. L2CA_DISCONNECT_RSP (l2cap_cid);
  822. }
  823. p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);
  824. gap_release_ccb (p_ccb);
  825. }
  826. /*******************************************************************************
  827. **
  828. ** Function gap_data_ind
  829. **
  830. ** Description This function is called when data is received from L2CAP.
  831. **
  832. ** Returns void
  833. **
  834. *******************************************************************************/
  835. static void gap_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg)
  836. {
  837. tGAP_CCB *p_ccb;
  838. /* Find CCB based on CID */
  839. if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL) {
  840. osi_free (p_msg);
  841. return;
  842. }
  843. if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED) {
  844. fixed_queue_enqueue(p_ccb->rx_queue, p_msg, FIXED_QUEUE_MAX_TIMEOUT);
  845. p_ccb->rx_queue_size += p_msg->len;
  846. /*
  847. GAP_TRACE_EVENT ("gap_data_ind - rx_queue_size=%d, msg len=%d",
  848. p_ccb->rx_queue_size, p_msg->len);
  849. */
  850. p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_DATA_AVAIL);
  851. } else {
  852. osi_free (p_msg);
  853. }
  854. }
  855. /*******************************************************************************
  856. **
  857. ** Function gap_congestion_ind
  858. **
  859. ** Description This is a callback function called by L2CAP when
  860. ** data L2CAP congestion status changes
  861. **
  862. *******************************************************************************/
  863. static void gap_congestion_ind (UINT16 lcid, BOOLEAN is_congested)
  864. {
  865. tGAP_CCB *p_ccb;
  866. UINT16 event;
  867. BT_HDR *p_buf;
  868. UINT8 status;
  869. GAP_TRACE_EVENT ("GAP_CONN - Rcvd L2CAP Is Congested (%d), CID: 0x%x",
  870. is_congested, lcid);
  871. /* Find CCB based on CID */
  872. if ((p_ccb = gap_find_ccb_by_cid (lcid)) == NULL) {
  873. return;
  874. }
  875. p_ccb->is_congested = is_congested;
  876. event = (is_congested) ? GAP_EVT_CONN_CONGESTED : GAP_EVT_CONN_UNCONGESTED;
  877. p_ccb->p_callback (p_ccb->gap_handle, event);
  878. if (!is_congested) {
  879. while ((p_buf = (BT_HDR *)fixed_queue_dequeue(p_ccb->tx_queue, 0)) != NULL) {
  880. status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf);
  881. if (status == L2CAP_DW_CONGESTED) {
  882. p_ccb->is_congested = TRUE;
  883. break;
  884. } else if (status != L2CAP_DW_SUCCESS) {
  885. break;
  886. }
  887. }
  888. }
  889. }
  890. /*******************************************************************************
  891. **
  892. ** Function gap_find_ccb_by_cid
  893. **
  894. ** Description This function searches the CCB table for an entry with the
  895. ** passed CID.
  896. **
  897. ** Returns the CCB address, or NULL if not found.
  898. **
  899. *******************************************************************************/
  900. static tGAP_CCB *gap_find_ccb_by_cid (UINT16 cid)
  901. {
  902. UINT16 xx;
  903. tGAP_CCB *p_ccb;
  904. /* Look through each connection control block */
  905. for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) {
  906. if ((p_ccb->con_state != GAP_CCB_STATE_IDLE) && (p_ccb->connection_id == cid)) {
  907. return (p_ccb);
  908. }
  909. }
  910. /* If here, not found */
  911. return (NULL);
  912. }
  913. /*******************************************************************************
  914. **
  915. ** Function gap_find_ccb_by_handle
  916. **
  917. ** Description This function searches the CCB table for an entry with the
  918. ** passed handle.
  919. **
  920. ** Returns the CCB address, or NULL if not found.
  921. **
  922. *******************************************************************************/
  923. static tGAP_CCB *gap_find_ccb_by_handle (UINT16 handle)
  924. {
  925. tGAP_CCB *p_ccb;
  926. /* Check that handle is valid */
  927. if (handle < GAP_MAX_CONNECTIONS) {
  928. p_ccb = &gap_cb.conn.ccb_pool[handle];
  929. if (p_ccb->con_state != GAP_CCB_STATE_IDLE) {
  930. return (p_ccb);
  931. }
  932. }
  933. /* If here, handle points to invalid connection */
  934. return (NULL);
  935. }
  936. /*******************************************************************************
  937. **
  938. ** Function gap_allocate_ccb
  939. **
  940. ** Description This function allocates a new CCB.
  941. **
  942. ** Returns CCB address, or NULL if none available.
  943. **
  944. *******************************************************************************/
  945. static tGAP_CCB *gap_allocate_ccb (void)
  946. {
  947. UINT16 xx;
  948. tGAP_CCB *p_ccb;
  949. /* Look through each connection control block for a free one */
  950. for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) {
  951. if (p_ccb->con_state == GAP_CCB_STATE_IDLE) {
  952. memset (p_ccb, 0, sizeof (tGAP_CCB));
  953. p_ccb->tx_queue = fixed_queue_new(QUEUE_SIZE_MAX);
  954. p_ccb->rx_queue = fixed_queue_new(QUEUE_SIZE_MAX);
  955. p_ccb->gap_handle = xx;
  956. p_ccb->rem_mtu_size = L2CAP_MTU_SIZE;
  957. return (p_ccb);
  958. }
  959. }
  960. /* If here, no free CCB found */
  961. return (NULL);
  962. }
  963. /*******************************************************************************
  964. **
  965. ** Function gap_release_ccb
  966. **
  967. ** Description This function releases a CCB.
  968. **
  969. ** Returns void
  970. **
  971. *******************************************************************************/
  972. static void gap_release_ccb (tGAP_CCB *p_ccb)
  973. {
  974. UINT16 xx;
  975. UINT16 psm = p_ccb->psm;
  976. UINT8 service_id = p_ccb->service_id;
  977. /* Drop any buffers we may be holding */
  978. p_ccb->rx_queue_size = 0;
  979. while (!fixed_queue_is_empty(p_ccb->rx_queue)) {
  980. osi_free(fixed_queue_dequeue(p_ccb->rx_queue, 0));
  981. }
  982. fixed_queue_free(p_ccb->rx_queue, NULL);
  983. p_ccb->rx_queue = NULL;
  984. while (!fixed_queue_is_empty(p_ccb->tx_queue)) {
  985. osi_free(fixed_queue_dequeue(p_ccb->tx_queue, 0));
  986. }
  987. fixed_queue_free(p_ccb->tx_queue, NULL);
  988. p_ccb->tx_queue = NULL;
  989. p_ccb->con_state = GAP_CCB_STATE_IDLE;
  990. /* If no-one else is using the PSM, deregister from L2CAP */
  991. for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) {
  992. if ((p_ccb->con_state != GAP_CCB_STATE_IDLE) && (p_ccb->psm == psm)) {
  993. return;
  994. }
  995. }
  996. #if (SDP_INCLUDED == TRUE)
  997. /* Free the security record for this PSM */
  998. BTM_SecClrService(service_id);
  999. #endif ///SDP_INCLUDED == TRUE
  1000. L2CA_DEREGISTER (psm);
  1001. }
  1002. #if (GAP_CONN_POST_EVT_INCLUDED == TRUE)
  1003. /*******************************************************************************
  1004. **
  1005. ** Function gap_send_event
  1006. **
  1007. ** Description Send BT_EVT_TO_GAP_MSG event to BTU task
  1008. **
  1009. ** Returns None
  1010. **
  1011. *******************************************************************************/
  1012. void gap_send_event (UINT16 gap_handle)
  1013. {
  1014. BT_HDR *p_msg;
  1015. if ((p_msg = (BT_HDR *)osi_malloc(BT_HDR_SIZE)) != NULL) {
  1016. p_msg->event = BT_EVT_TO_GAP_MSG;
  1017. p_msg->len = 0;
  1018. p_msg->offset = 0;
  1019. p_msg->layer_specific = gap_handle;
  1020. GKI_send_msg(BTU_TASK, BTU_HCI_RCV_MBOX, p_msg);
  1021. } else {
  1022. GAP_TRACE_ERROR("Unable to allocate message buffer for event.");
  1023. }
  1024. }
  1025. #endif /* (GAP_CONN_POST_EVT_INCLUDED == TRUE) */
  1026. #endif /* GAP_CONN_INCLUDED */