gap_ble.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792
  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 "bt_target.h"
  19. #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
  20. #include "bt_defs.h"
  21. #include <string.h>
  22. #include "gap_int.h"
  23. #include "gap_api.h"
  24. #include "gattdefs.h"
  25. #include "gatt_api.h"
  26. #include "gatt_int.h"
  27. #include "btm_int.h"
  28. #include "hcimsgs.h"
  29. #include "sdpdefs.h"
  30. #define GAP_CHAR_ICON_SIZE 2
  31. #define GAP_CHAR_DEV_NAME_SIZE 248
  32. #define GAP_MAX_NUM_INC_SVR 0
  33. #define GAP_MAX_ATTR_NUM (2 * GAP_MAX_CHAR_NUM + GAP_MAX_NUM_INC_SVR + 1)
  34. #define GAP_MAX_CHAR_VALUE_SIZE (30 + GAP_CHAR_DEV_NAME_SIZE)
  35. #ifndef GAP_ATTR_DB_SIZE
  36. #define GAP_ATTR_DB_SIZE GATT_DB_MEM_SIZE(GAP_MAX_NUM_INC_SVR, GAP_MAX_CHAR_NUM, GAP_MAX_CHAR_VALUE_SIZE)
  37. #endif
  38. static void gap_ble_s_attr_request_cback (UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYPE op_code, tGATTS_DATA *p_data);
  39. /* client connection callback */
  40. static void gap_ble_c_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, BOOLEAN connected,
  41. tGATT_DISCONN_REASON reason, tGATT_TRANSPORT transport);
  42. static void gap_ble_c_cmpl_cback (UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, tGATT_CL_COMPLETE *p_data);
  43. static tGATT_CBACK gap_cback = {
  44. gap_ble_c_connect_cback,
  45. gap_ble_c_cmpl_cback,
  46. NULL,
  47. NULL,
  48. gap_ble_s_attr_request_cback,
  49. NULL,
  50. NULL
  51. };
  52. /*******************************************************************************
  53. **
  54. ** Function gap_find_clcb_by_bd_addr
  55. **
  56. ** Description The function searches all LCB with macthing bd address
  57. **
  58. ** Returns total number of clcb found.
  59. **
  60. *******************************************************************************/
  61. tGAP_CLCB *gap_find_clcb_by_bd_addr(BD_ADDR bda)
  62. {
  63. UINT8 i_clcb;
  64. tGAP_CLCB *p_clcb = NULL;
  65. for (i_clcb = 0, p_clcb = gap_cb.clcb; i_clcb < GAP_MAX_CL; i_clcb++, p_clcb++) {
  66. if (p_clcb->in_use && !memcmp(p_clcb->bda, bda, BD_ADDR_LEN)) {
  67. return p_clcb;
  68. }
  69. }
  70. return NULL;
  71. }
  72. /*******************************************************************************
  73. **
  74. ** Function gap_ble_find_clcb_by_conn_id
  75. **
  76. ** Description The function searches all LCB with macthing connection ID
  77. **
  78. ** Returns total number of clcb found.
  79. **
  80. *******************************************************************************/
  81. tGAP_CLCB *gap_ble_find_clcb_by_conn_id(UINT16 conn_id)
  82. {
  83. UINT8 i_clcb;
  84. tGAP_CLCB *p_clcb = NULL;
  85. for (i_clcb = 0, p_clcb = gap_cb.clcb; i_clcb < GAP_MAX_CL; i_clcb++, p_clcb++) {
  86. if (p_clcb->in_use && p_clcb->connected && p_clcb->conn_id == conn_id) {
  87. return p_clcb;
  88. }
  89. }
  90. return p_clcb;
  91. }
  92. /*******************************************************************************
  93. **
  94. ** Function gap_clcb_alloc
  95. **
  96. ** Description The function allocates a GAP connection link control block
  97. **
  98. ** Returns NULL if not found. Otherwise pointer to the connection link block.
  99. **
  100. *******************************************************************************/
  101. tGAP_CLCB *gap_clcb_alloc (BD_ADDR bda)
  102. {
  103. UINT8 i_clcb = 0;
  104. tGAP_CLCB *p_clcb = NULL;
  105. for (i_clcb = 0, p_clcb = gap_cb.clcb; i_clcb < GAP_MAX_CL; i_clcb++, p_clcb++) {
  106. if (!p_clcb->in_use) {
  107. memset(p_clcb, 0, sizeof(tGAP_CLCB));
  108. p_clcb->in_use = TRUE;
  109. memcpy (p_clcb->bda, bda, BD_ADDR_LEN);
  110. break;
  111. }
  112. }
  113. return p_clcb;
  114. }
  115. /*******************************************************************************
  116. **
  117. ** Function gap_ble_dealloc_clcb
  118. **
  119. ** Description The function clean up the pending request queue in GAP
  120. **
  121. ** Returns none
  122. **
  123. *******************************************************************************/
  124. void gap_ble_dealloc_clcb(tGAP_CLCB *p_clcb)
  125. {
  126. tGAP_BLE_REQ *p_q;
  127. while ((p_q = (tGAP_BLE_REQ *)GKI_dequeue(&p_clcb->pending_req_q)) != NULL) {
  128. /* send callback to all pending requests if being removed*/
  129. if (p_q->p_cback != NULL) {
  130. (*p_q->p_cback)(FALSE, p_clcb->bda, 0, NULL);
  131. }
  132. GKI_freebuf (p_q);
  133. }
  134. memset(p_clcb, 0, sizeof(tGAP_CLCB));
  135. }
  136. /*******************************************************************************
  137. **
  138. ** Function gap_ble_enqueue_request
  139. **
  140. ** Description The function enqueue a GAP client request
  141. **
  142. ** Returns TRUE is successul; FALSE otherwise
  143. **
  144. *******************************************************************************/
  145. BOOLEAN gap_ble_enqueue_request (tGAP_CLCB *p_clcb, UINT16 uuid, tGAP_BLE_CMPL_CBACK *p_cback)
  146. {
  147. tGAP_BLE_REQ *p_q = (tGAP_BLE_REQ *)GKI_getbuf(sizeof(tGAP_BLE_REQ));
  148. if (p_q != NULL) {
  149. p_q->p_cback = p_cback;
  150. p_q->uuid = uuid;
  151. GKI_enqueue(&p_clcb->pending_req_q, p_q);
  152. return TRUE;
  153. }
  154. return FALSE;
  155. }
  156. /*******************************************************************************
  157. **
  158. ** Function gap_ble_dequeue_request
  159. **
  160. ** Description The function dequeue a GAP client request if any
  161. **
  162. ** Returns TRUE is successul; FALSE otherwise
  163. **
  164. *******************************************************************************/
  165. BOOLEAN gap_ble_dequeue_request (tGAP_CLCB *p_clcb, UINT16 *p_uuid, tGAP_BLE_CMPL_CBACK **p_cback)
  166. {
  167. tGAP_BLE_REQ *p_q = (tGAP_BLE_REQ *)GKI_dequeue(&p_clcb->pending_req_q);;
  168. if (p_q != NULL) {
  169. *p_cback = p_q->p_cback;
  170. *p_uuid = p_q->uuid;
  171. GKI_freebuf((void *)p_q);
  172. return TRUE;
  173. }
  174. return FALSE;
  175. }
  176. /*******************************************************************************
  177. ** GAP Attributes Database Request callback
  178. *******************************************************************************/
  179. tGATT_STATUS gap_read_attr_value (UINT16 handle, tGATT_VALUE *p_value, BOOLEAN is_long)
  180. {
  181. tGAP_ATTR *p_db_attr = gap_cb.gatt_attr;
  182. UINT8 *p = p_value->value, i;
  183. UINT16 offset = p_value->offset;
  184. UINT8 *p_dev_name = NULL;
  185. for (i = 0; i < GAP_MAX_CHAR_NUM; i ++, p_db_attr ++) {
  186. if (handle == p_db_attr->handle) {
  187. if (p_db_attr->uuid != GATT_UUID_GAP_DEVICE_NAME &&
  188. is_long == TRUE) {
  189. return GATT_NOT_LONG;
  190. }
  191. switch (p_db_attr->uuid) {
  192. case GATT_UUID_GAP_DEVICE_NAME:
  193. BTM_ReadLocalDeviceName((char **)&p_dev_name);
  194. if (strlen ((char *)p_dev_name) > GATT_MAX_ATTR_LEN) {
  195. p_value->len = GATT_MAX_ATTR_LEN;
  196. } else {
  197. p_value->len = (UINT16)strlen ((char *)p_dev_name);
  198. }
  199. if (offset > p_value->len) {
  200. return GATT_INVALID_OFFSET;
  201. } else {
  202. p_value->len -= offset;
  203. p_dev_name += offset;
  204. ARRAY_TO_STREAM(p, p_dev_name, p_value->len);
  205. GAP_TRACE_EVENT("GATT_UUID_GAP_DEVICE_NAME len=0x%04x", p_value->len);
  206. }
  207. break;
  208. case GATT_UUID_GAP_ICON:
  209. UINT16_TO_STREAM(p, p_db_attr->attr_value.icon);
  210. p_value->len = 2;
  211. break;
  212. case GATT_UUID_GAP_PREF_CONN_PARAM:
  213. UINT16_TO_STREAM(p, p_db_attr->attr_value.conn_param.int_min); /* int_min */
  214. UINT16_TO_STREAM(p, p_db_attr->attr_value.conn_param.int_max); /* int_max */
  215. UINT16_TO_STREAM(p, p_db_attr->attr_value.conn_param.latency); /* latency */
  216. UINT16_TO_STREAM(p, p_db_attr->attr_value.conn_param.sp_tout); /* sp_tout */
  217. p_value->len = 8;
  218. break;
  219. /* address resolution */
  220. case GATT_UUID_GAP_CENTRAL_ADDR_RESOL:
  221. UINT8_TO_STREAM(p, p_db_attr->attr_value.addr_resolution);
  222. p_value->len = 1;
  223. break;
  224. }
  225. return GATT_SUCCESS;
  226. }
  227. }
  228. return GATT_NOT_FOUND;
  229. }
  230. /*******************************************************************************
  231. ** GAP Attributes Database Read/Read Blob Request process
  232. *******************************************************************************/
  233. tGATT_STATUS gap_proc_read (tGATTS_REQ_TYPE type, tGATT_READ_REQ *p_data, tGATTS_RSP *p_rsp)
  234. {
  235. tGATT_STATUS status = GATT_NO_RESOURCES;
  236. UNUSED(type);
  237. if (p_data->is_long) {
  238. p_rsp->attr_value.offset = p_data->offset;
  239. }
  240. p_rsp->attr_value.handle = p_data->handle;
  241. status = gap_read_attr_value(p_data->handle, &p_rsp->attr_value, p_data->is_long);
  242. return status;
  243. }
  244. /******************************************************************************
  245. **
  246. ** Function gap_proc_write_req
  247. **
  248. ** Description GAP ATT server process a write request.
  249. **
  250. ** Returns void.
  251. **
  252. *******************************************************************************/
  253. UINT8 gap_proc_write_req( tGATTS_REQ_TYPE type, tGATT_WRITE_REQ *p_data)
  254. {
  255. tGAP_ATTR *p_db_attr = gap_cb.gatt_attr;
  256. UINT8 i;
  257. UNUSED(type);
  258. for (i = 0; i < GAP_MAX_CHAR_NUM; i ++, p_db_attr ++) {
  259. if (p_data-> handle == p_db_attr->handle) {
  260. return GATT_WRITE_NOT_PERMIT;
  261. }
  262. }
  263. return GATT_NOT_FOUND;
  264. }
  265. /******************************************************************************
  266. **
  267. ** Function gap_ble_s_attr_request_cback
  268. **
  269. ** Description GAP ATT server attribute access request callback.
  270. **
  271. ** Returns void.
  272. **
  273. *******************************************************************************/
  274. void gap_ble_s_attr_request_cback (UINT16 conn_id, UINT32 trans_id,
  275. tGATTS_REQ_TYPE type, tGATTS_DATA *p_data)
  276. {
  277. UINT8 status = GATT_INVALID_PDU;
  278. tGATTS_RSP rsp_msg;
  279. BOOLEAN ignore = FALSE;
  280. GAP_TRACE_EVENT("gap_ble_s_attr_request_cback : recv type (0x%02x)", type);
  281. memset(&rsp_msg, 0, sizeof(tGATTS_RSP));
  282. switch (type) {
  283. case GATTS_REQ_TYPE_READ:
  284. status = gap_proc_read(type, &p_data->read_req, &rsp_msg);
  285. break;
  286. case GATTS_REQ_TYPE_WRITE:
  287. if (!p_data->write_req.need_rsp) {
  288. ignore = TRUE;
  289. }
  290. status = gap_proc_write_req(type, &p_data->write_req);
  291. break;
  292. case GATTS_REQ_TYPE_WRITE_EXEC:
  293. ignore = TRUE;
  294. GAP_TRACE_EVENT("Ignore GATTS_REQ_TYPE_WRITE_EXEC" );
  295. break;
  296. case GATTS_REQ_TYPE_MTU:
  297. GAP_TRACE_EVENT("Get MTU exchange new mtu size: %d", p_data->mtu);
  298. ignore = TRUE;
  299. break;
  300. default:
  301. GAP_TRACE_EVENT("Unknown/unexpected LE GAP ATT request: 0x%02x", type);
  302. break;
  303. }
  304. if (!ignore) {
  305. GATTS_SendRsp (conn_id, trans_id, status, &rsp_msg);
  306. }
  307. }
  308. /*******************************************************************************
  309. **
  310. ** Function btm_ble_att_db_init
  311. **
  312. ** Description GAP ATT database initalization.
  313. **
  314. ** Returns void.
  315. **
  316. *******************************************************************************/
  317. void gap_attr_db_init(void)
  318. {
  319. tBT_UUID app_uuid = {LEN_UUID_128, {0}};
  320. tBT_UUID uuid = {LEN_UUID_16, {UUID_SERVCLASS_GAP_SERVER}};
  321. UINT16 service_handle;
  322. tGAP_ATTR *p_db_attr = &gap_cb.gatt_attr[0];
  323. tGATT_STATUS status;
  324. /* Fill our internal UUID with a fixed pattern 0x82 */
  325. memset (&app_uuid.uu.uuid128, 0x82, LEN_UUID_128);
  326. memset(gap_cb.gatt_attr, 0, sizeof(tGAP_ATTR) *GAP_MAX_CHAR_NUM);
  327. gap_cb.gatt_if = GATT_Register(&app_uuid, &gap_cback);
  328. GATT_StartIf(gap_cb.gatt_if);
  329. /* Create a GAP service */
  330. service_handle = GATTS_CreateService (gap_cb.gatt_if, &uuid, 0, GAP_MAX_ATTR_NUM, TRUE);
  331. GAP_TRACE_EVENT ("gap_attr_db_init service_handle = %d", service_handle);
  332. /* add Device Name Characteristic
  333. */
  334. uuid.len = LEN_UUID_16;
  335. uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_DEVICE_NAME;
  336. p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid, GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ,
  337. NULL, NULL);
  338. p_db_attr ++;
  339. /* add Icon characteristic
  340. */
  341. uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_ICON;
  342. p_db_attr->handle = GATTS_AddCharacteristic(service_handle,
  343. &uuid,
  344. GATT_PERM_READ,
  345. GATT_CHAR_PROP_BIT_READ,
  346. NULL, NULL);
  347. p_db_attr ++;
  348. #if ((defined BTM_PERIPHERAL_ENABLED) && (BTM_PERIPHERAL_ENABLED == TRUE))
  349. /* Only needed for peripheral testing */
  350. /* add preferred connection parameter characteristic
  351. */
  352. uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_PREF_CONN_PARAM;
  353. p_db_attr->attr_value.conn_param.int_max = GAP_PREFER_CONN_INT_MAX; /* 6 */
  354. p_db_attr->attr_value.conn_param.int_min = GAP_PREFER_CONN_INT_MIN; /* 0 */
  355. p_db_attr->attr_value.conn_param.latency = GAP_PREFER_CONN_LATENCY; /* 0 */
  356. p_db_attr->attr_value.conn_param.sp_tout = GAP_PREFER_CONN_SP_TOUT; /* 2000 */
  357. p_db_attr->handle = GATTS_AddCharacteristic(service_handle,
  358. &uuid,
  359. GATT_PERM_READ,
  360. GATT_CHAR_PROP_BIT_READ,
  361. NULL, NULL);
  362. p_db_attr ++;
  363. #endif
  364. /* add Central address resolution Characteristic */
  365. uuid.len = LEN_UUID_16;
  366. uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_CENTRAL_ADDR_RESOL;
  367. p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid,
  368. GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ,
  369. NULL, NULL);
  370. p_db_attr->attr_value.addr_resolution = 0;
  371. p_db_attr++;
  372. /* start service now */
  373. memset (&app_uuid.uu.uuid128, 0x81, LEN_UUID_128);
  374. status = GATTS_StartService(gap_cb.gatt_if, service_handle, GAP_TRANSPORT_SUPPORTED );
  375. GAP_TRACE_EVENT ("GAP App gatt_if: %d s_hdl = %d start_status=%d",
  376. gap_cb.gatt_if, service_handle, status);
  377. }
  378. /*******************************************************************************
  379. **
  380. ** Function GAP_BleAttrDBUpdate
  381. **
  382. ** Description GAP ATT database update.
  383. **
  384. ** Returns void.
  385. **
  386. *******************************************************************************/
  387. void GAP_BleAttrDBUpdate(UINT16 attr_uuid, tGAP_BLE_ATTR_VALUE *p_value)
  388. {
  389. tGAP_ATTR *p_db_attr = gap_cb.gatt_attr;
  390. UINT8 i = 0;
  391. GAP_TRACE_EVENT("GAP_BleAttrDBUpdate attr_uuid=0x%04x\n", attr_uuid);
  392. for (i = 0; i < GAP_MAX_CHAR_NUM; i ++, p_db_attr ++) {
  393. if (p_db_attr->uuid == attr_uuid) {
  394. GAP_TRACE_EVENT("Found attr_uuid=0x%04x\n", attr_uuid);
  395. switch (attr_uuid) {
  396. case GATT_UUID_GAP_ICON:
  397. p_db_attr->attr_value.icon = p_value->icon;
  398. break;
  399. case GATT_UUID_GAP_PREF_CONN_PARAM:
  400. memcpy((void *)&p_db_attr->attr_value.conn_param,
  401. (const void *)&p_value->conn_param, sizeof(tGAP_BLE_PREF_PARAM));
  402. break;
  403. case GATT_UUID_GAP_DEVICE_NAME:
  404. BTM_SetLocalDeviceName((char *)p_value->p_dev_name);
  405. break;
  406. case GATT_UUID_GAP_CENTRAL_ADDR_RESOL:
  407. p_db_attr->attr_value.addr_resolution = p_value->addr_resolution;
  408. break;
  409. }
  410. break;
  411. }
  412. }
  413. return;
  414. }
  415. /*******************************************************************************
  416. **
  417. ** Function gap_ble_send_cl_read_request
  418. **
  419. ** Description utility function to send a read request for a GAP charactersitic
  420. **
  421. ** Returns TRUE if read started, else FALSE if GAP is busy
  422. **
  423. *******************************************************************************/
  424. BOOLEAN gap_ble_send_cl_read_request(tGAP_CLCB *p_clcb)
  425. {
  426. tGATT_READ_PARAM param;
  427. UINT16 uuid = 0;
  428. BOOLEAN started = FALSE;
  429. if (gap_ble_dequeue_request(p_clcb, &uuid, &p_clcb->p_cback)) {
  430. memset(&param, 0, sizeof(tGATT_READ_PARAM));
  431. param.service.uuid.len = LEN_UUID_16;
  432. param.service.uuid.uu.uuid16 = uuid;
  433. param.service.s_handle = 1;
  434. param.service.e_handle = 0xFFFF;
  435. param.service.auth_req = 0;
  436. if (GATTC_Read(p_clcb->conn_id, GATT_READ_BY_TYPE, &param) == GATT_SUCCESS) {
  437. p_clcb->cl_op_uuid = uuid;
  438. started = TRUE;
  439. }
  440. }
  441. return started;
  442. }
  443. /*******************************************************************************
  444. **
  445. ** Function gap_ble_cl_op_cmpl
  446. **
  447. ** Description GAP client operation complete callback
  448. **
  449. ** Returns void
  450. **
  451. *******************************************************************************/
  452. void gap_ble_cl_op_cmpl(tGAP_CLCB *p_clcb, BOOLEAN status, UINT16 len, UINT8 *p_name)
  453. {
  454. tGAP_BLE_CMPL_CBACK *p_cback = p_clcb->p_cback;
  455. UINT16 op = p_clcb->cl_op_uuid;
  456. GAP_TRACE_EVENT("gap_ble_cl_op_cmpl status: %d", status);
  457. p_clcb->cl_op_uuid = 0;
  458. p_clcb->p_cback = NULL;
  459. if (p_cback && op) {
  460. GAP_TRACE_EVENT("calling gap_ble_cl_op_cmpl");
  461. (* p_cback)(status, p_clcb->bda, len, (char *)p_name);
  462. }
  463. /* if no further activity is requested in callback, drop the link */
  464. if (p_clcb->connected) {
  465. if (!gap_ble_send_cl_read_request(p_clcb)) {
  466. GATT_Disconnect(p_clcb->conn_id);
  467. gap_ble_dealloc_clcb(p_clcb);
  468. }
  469. }
  470. }
  471. /*******************************************************************************
  472. **
  473. ** Function gap_ble_c_connect_cback
  474. **
  475. ** Description Client connection callback.
  476. **
  477. ** Returns void
  478. **
  479. *******************************************************************************/
  480. static void gap_ble_c_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
  481. BOOLEAN connected, tGATT_DISCONN_REASON reason,
  482. tGATT_TRANSPORT transport)
  483. {
  484. tGAP_CLCB *p_clcb = gap_find_clcb_by_bd_addr (bda);
  485. UNUSED(gatt_if);
  486. UNUSED(transport);
  487. if (p_clcb != NULL) {
  488. if (connected) {
  489. p_clcb->conn_id = conn_id;
  490. p_clcb->connected = TRUE;
  491. /* start operation is pending */
  492. gap_ble_send_cl_read_request(p_clcb);
  493. } else {
  494. p_clcb->connected = FALSE;
  495. gap_ble_cl_op_cmpl(p_clcb, FALSE, 0, NULL);
  496. /* clean up clcb */
  497. gap_ble_dealloc_clcb(p_clcb);
  498. }
  499. }
  500. }
  501. /*******************************************************************************
  502. **
  503. ** Function gap_ble_c_cmpl_cback
  504. **
  505. ** Description Client operation complete callback.
  506. **
  507. ** Returns void
  508. **
  509. *******************************************************************************/
  510. static void gap_ble_c_cmpl_cback (UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, tGATT_CL_COMPLETE *p_data)
  511. {
  512. tGAP_CLCB *p_clcb = gap_ble_find_clcb_by_conn_id(conn_id);
  513. UINT16 op_type;
  514. UINT16 min, max, latency, tout;
  515. UINT16 len;
  516. UINT8 *pp;
  517. if (p_clcb == NULL) {
  518. return;
  519. }
  520. op_type = p_clcb->cl_op_uuid;
  521. GAP_TRACE_EVENT ("gap_ble_c_cmpl_cback() - op_code: 0x%02x status: 0x%02x read_type: 0x%04x\n", op, status, op_type);
  522. /* Currently we only issue read commands */
  523. if (op != GATTC_OPTYPE_READ) {
  524. return;
  525. }
  526. if (status != GATT_SUCCESS) {
  527. gap_ble_cl_op_cmpl(p_clcb, FALSE, 0, NULL);
  528. return;
  529. }
  530. pp = p_data->att_value.value;
  531. switch (op_type) {
  532. case GATT_UUID_GAP_PREF_CONN_PARAM:
  533. GAP_TRACE_EVENT ("GATT_UUID_GAP_PREF_CONN_PARAM");
  534. /* Extract the peripheral preferred connection parameters and save them */
  535. STREAM_TO_UINT16 (min, pp);
  536. STREAM_TO_UINT16 (max, pp);
  537. STREAM_TO_UINT16 (latency, pp);
  538. STREAM_TO_UINT16 (tout, pp);
  539. BTM_BleSetPrefConnParams (p_clcb->bda, min, max, latency, tout);
  540. /* release the connection here */
  541. gap_ble_cl_op_cmpl(p_clcb, TRUE, 0, NULL);
  542. break;
  543. case GATT_UUID_GAP_DEVICE_NAME:
  544. GAP_TRACE_EVENT ("GATT_UUID_GAP_DEVICE_NAME\n");
  545. len = (UINT16)strlen((char *)pp);
  546. if (len > GAP_CHAR_DEV_NAME_SIZE) {
  547. len = GAP_CHAR_DEV_NAME_SIZE;
  548. }
  549. gap_ble_cl_op_cmpl(p_clcb, TRUE, len, pp);
  550. break;
  551. case GATT_UUID_GAP_CENTRAL_ADDR_RESOL:
  552. gap_ble_cl_op_cmpl(p_clcb, TRUE, 1, pp);
  553. break;
  554. }
  555. }
  556. /*******************************************************************************
  557. **
  558. ** Function gap_ble_accept_cl_operation
  559. **
  560. ** Description Start a process to read peer address resolution capability
  561. **
  562. ** Returns TRUE if request accepted
  563. **
  564. *******************************************************************************/
  565. BOOLEAN gap_ble_accept_cl_operation(BD_ADDR peer_bda, UINT16 uuid, tGAP_BLE_CMPL_CBACK *p_cback)
  566. {
  567. tGAP_CLCB *p_clcb;
  568. BOOLEAN started = FALSE;
  569. if (p_cback == NULL && uuid != GATT_UUID_GAP_PREF_CONN_PARAM) {
  570. return (started);
  571. }
  572. if ((p_clcb = gap_find_clcb_by_bd_addr (peer_bda)) == NULL) {
  573. if ((p_clcb = gap_clcb_alloc(peer_bda)) == NULL) {
  574. GAP_TRACE_ERROR("gap_ble_accept_cl_operation max connection reached");
  575. return started;
  576. }
  577. }
  578. GAP_TRACE_EVENT ("%s() - BDA: %08x%04x cl_op_uuid: 0x%04x",
  579. __FUNCTION__,
  580. (peer_bda[0] << 24) + (peer_bda[1] << 16) + (peer_bda[2] << 8) + peer_bda[3],
  581. (peer_bda[4] << 8) + peer_bda[5], uuid);
  582. if (GATT_GetConnIdIfConnected(gap_cb.gatt_if, peer_bda, &p_clcb->conn_id, BT_TRANSPORT_LE)) {
  583. p_clcb->connected = TRUE;
  584. }
  585. /* hold the link here */
  586. if (!GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE, BT_TRANSPORT_LE)) {
  587. return started;
  588. }
  589. /* enqueue the request */
  590. gap_ble_enqueue_request(p_clcb, uuid, p_cback);
  591. if (p_clcb->connected && p_clcb->cl_op_uuid == 0) {
  592. started = gap_ble_send_cl_read_request(p_clcb);
  593. } else { /* wait for connection up or pending operation to finish */
  594. started = TRUE;
  595. }
  596. return started;
  597. }
  598. /*******************************************************************************
  599. **
  600. ** Function GAP_BleReadPeerPrefConnParams
  601. **
  602. ** Description Start a process to read a connected peripheral's preferred
  603. ** connection parameters
  604. **
  605. ** Returns TRUE if read started, else FALSE if GAP is busy
  606. **
  607. *******************************************************************************/
  608. BOOLEAN GAP_BleReadPeerPrefConnParams (BD_ADDR peer_bda)
  609. {
  610. return gap_ble_accept_cl_operation (peer_bda, GATT_UUID_GAP_PREF_CONN_PARAM, NULL);
  611. }
  612. /*******************************************************************************
  613. **
  614. ** Function GAP_BleReadPeerDevName
  615. **
  616. ** Description Start a process to read a connected peripheral's device name.
  617. **
  618. ** Returns TRUE if request accepted
  619. **
  620. *******************************************************************************/
  621. BOOLEAN GAP_BleReadPeerDevName (BD_ADDR peer_bda, tGAP_BLE_CMPL_CBACK *p_cback)
  622. {
  623. return gap_ble_accept_cl_operation (peer_bda, GATT_UUID_GAP_DEVICE_NAME, p_cback);
  624. }
  625. /*******************************************************************************
  626. **
  627. ** Function GAP_BleReadPeerAddressResolutionCap
  628. **
  629. ** Description Start a process to read peer address resolution capability
  630. **
  631. ** Returns TRUE if request accepted
  632. **
  633. *******************************************************************************/
  634. BOOLEAN GAP_BleReadPeerAddressResolutionCap (BD_ADDR peer_bda, tGAP_BLE_CMPL_CBACK *p_cback)
  635. {
  636. return gap_ble_accept_cl_operation(peer_bda, GATT_UUID_GAP_CENTRAL_ADDR_RESOL, p_cback);
  637. }
  638. /*******************************************************************************
  639. **
  640. ** Function GAP_BleCancelReadPeerDevName
  641. **
  642. ** Description Cancel reading a peripheral's device name.
  643. **
  644. ** Returns TRUE if request accepted
  645. **
  646. *******************************************************************************/
  647. BOOLEAN GAP_BleCancelReadPeerDevName (BD_ADDR peer_bda)
  648. {
  649. tGAP_CLCB *p_clcb = gap_find_clcb_by_bd_addr (peer_bda);
  650. GAP_TRACE_EVENT ("GAP_BleCancelReadPeerDevName() - BDA: %08x%04x cl_op_uuid: 0x%04x",
  651. (peer_bda[0] << 24) + (peer_bda[1] << 16) + (peer_bda[2] << 8) + peer_bda[3],
  652. (peer_bda[4] << 8) + peer_bda[5], (p_clcb == NULL) ? 0 : p_clcb->cl_op_uuid);
  653. if (p_clcb == NULL) {
  654. GAP_TRACE_ERROR ("Cannot cancel current op is not get dev name");
  655. return FALSE;
  656. }
  657. if (!p_clcb->connected) {
  658. if (!GATT_CancelConnect(gap_cb.gatt_if, peer_bda, TRUE)) {
  659. GAP_TRACE_ERROR ("Cannot cancel where No connection id");
  660. return FALSE;
  661. }
  662. }
  663. gap_ble_cl_op_cmpl(p_clcb, FALSE, 0, NULL);
  664. return (TRUE);
  665. }
  666. #endif /* BLE_INCLUDED */