1 /******************************************************************************
2 *
3 * Copyright (C) 1999-2012 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
19 /******************************************************************************
20 *
21 * this file contains the main GATT client functions
22 *
23 ******************************************************************************/
24
25 #include "common/bt_target.h"
26
27 #if BLE_INCLUDED == TRUE && GATTC_INCLUDED == TRUE
28
29 #include <string.h>
30 #include "osi/allocator.h"
31 #include "gatt_int.h"
32 #include "l2c_int.h"
33
34 #define GATT_WRITE_LONG_HDR_SIZE 5 /* 1 opcode + 2 handle + 2 offset */
35 #define GATT_READ_CHAR_VALUE_HDL (GATT_READ_CHAR_VALUE | 0x80)
36 #define GATT_READ_INC_SRV_UUID128 (GATT_DISC_INC_SRVC | 0x90)
37
38 #define GATT_PREP_WRITE_RSP_MIN_LEN 4
39 #define GATT_NOTIFICATION_MIN_LEN 2
40 #define GATT_WRITE_RSP_MIN_LEN 2
41 #define GATT_INFO_RSP_MIN_LEN 1
42 #define GATT_MTU_RSP_MIN_LEN 2
43 #define GATT_READ_BY_TYPE_RSP_MIN_LEN 1
44
45 /********************************************************************************
46 ** G L O B A L G A T T D A T A *
47 *********************************************************************************/
48 void gatt_send_prepare_write(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb);
49
50 static const UINT8 disc_type_to_att_opcode[GATT_DISC_MAX] = {
51 0,
52 GATT_REQ_READ_BY_GRP_TYPE, /* GATT_DISC_SRVC_ALL = 1, */
53 GATT_REQ_FIND_TYPE_VALUE, /* GATT_DISC_SRVC_BY_UUID, */
54 GATT_REQ_READ_BY_TYPE, /* GATT_DISC_INC_SRVC, */
55 GATT_REQ_READ_BY_TYPE, /* GATT_DISC_CHAR, */
56 GATT_REQ_READ_BY_TYPE, /* GATT_DISC_CHAR_BY_UUID, */
57 GATT_REQ_FIND_INFO /* GATT_DISC_CHAR_DSCPT, */
58 };
59
60 static const UINT16 disc_type_to_uuid[GATT_DISC_MAX] = {
61 0, /* reserved */
62 GATT_UUID_PRI_SERVICE, /* <service> DISC_SRVC_ALL */
63 GATT_UUID_PRI_SERVICE, /* <service> for DISC_SERVC_BY_UUID */
64 GATT_UUID_INCLUDE_SERVICE, /* <include_service> for DISC_INC_SRVC */
65 GATT_UUID_CHAR_DECLARE, /* <characteristic> for DISC_CHAR */
66 0 /* no type filtering for DISC_CHAR_DSCPT */
67 };
68
69 // Use for GATTC discover infomation print
70 #define GATT_DISC_INFO(fmt, args...) {if (gatt_cb.auto_disc == FALSE) BT_PRINT_I("BT_GATT", fmt, ## args);}
71
72 /*******************************************************************************
73 **
74 ** Function gatt_act_discovery
75 **
76 ** Description GATT discovery operation.
77 **
78 ** Returns void.
79 **
80 *******************************************************************************/
gatt_act_discovery(tGATT_CLCB * p_clcb)81 void gatt_act_discovery(tGATT_CLCB *p_clcb)
82 {
83 UINT8 op_code = disc_type_to_att_opcode[p_clcb->op_subtype];
84 tGATT_CL_MSG cl_req;
85 tGATT_STATUS st;
86
87 if (p_clcb->s_handle <= p_clcb->e_handle && p_clcb->s_handle != 0) {
88 memset(&cl_req, 0, sizeof(tGATT_CL_MSG));
89
90 cl_req.browse.s_handle = p_clcb->s_handle;
91 cl_req.browse.e_handle = p_clcb->e_handle;
92
93 if (disc_type_to_uuid[p_clcb->op_subtype] != 0) {
94 cl_req.browse.uuid.len = 2;
95 cl_req.browse.uuid.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype];
96 }
97
98 if (p_clcb->op_subtype == GATT_DISC_SRVC_BY_UUID) { /* fill in the FindByTypeValue request info*/
99 cl_req.find_type_value.uuid.len = 2;
100 cl_req.find_type_value.uuid.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype];
101 cl_req.find_type_value.s_handle = p_clcb->s_handle;
102 cl_req.find_type_value.e_handle = p_clcb->e_handle;
103 cl_req.find_type_value.value_len = p_clcb->uuid.len;
104 /* if service type is 32 bits UUID, convert it now */
105 if (p_clcb->uuid.len == LEN_UUID_32) {
106 cl_req.find_type_value.value_len = LEN_UUID_128;
107 gatt_convert_uuid32_to_uuid128(cl_req.find_type_value.value, p_clcb->uuid.uu.uuid32);
108 } else {
109 memcpy (cl_req.find_type_value.value, &p_clcb->uuid.uu, p_clcb->uuid.len);
110 }
111 }
112
113 if (p_clcb->op_subtype == GATT_DISC_CHAR_BY_UUID) {
114 memcpy(&cl_req.browse.uuid, &p_clcb->uuid, sizeof(tBT_UUID));
115 }
116
117 st = attp_send_cl_msg(p_clcb->p_tcb, p_clcb->clcb_idx, op_code, &cl_req);
118
119 if (st != GATT_SUCCESS && st != GATT_CMD_STARTED) {
120 gatt_end_operation(p_clcb, GATT_ERROR, NULL);
121 }
122 } else { /* end of handle range */
123 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
124 }
125 }
126
127 /*******************************************************************************
128 **
129 ** Function gatt_act_read
130 **
131 ** Description GATT read operation.
132 **
133 ** Returns void.
134 **
135 *******************************************************************************/
gatt_act_read(tGATT_CLCB * p_clcb,UINT16 offset)136 void gatt_act_read (tGATT_CLCB *p_clcb, UINT16 offset)
137 {
138 tGATT_TCB *p_tcb = p_clcb->p_tcb;
139 UINT8 rt = GATT_INTERNAL_ERROR;
140 tGATT_CL_MSG msg;
141 UINT8 op_code = 0;
142
143 memset (&msg, 0, sizeof(tGATT_CL_MSG));
144
145 switch (p_clcb->op_subtype) {
146 case GATT_READ_CHAR_VALUE:
147 case GATT_READ_BY_TYPE:
148 op_code = GATT_REQ_READ_BY_TYPE;
149 msg.browse.s_handle = p_clcb->s_handle;
150 msg.browse.e_handle = p_clcb->e_handle;
151 if (p_clcb->op_subtype == GATT_READ_BY_TYPE) {
152 memcpy(&msg.browse.uuid, &p_clcb->uuid, sizeof(tBT_UUID));
153 } else {
154 msg.browse.uuid.len = LEN_UUID_16;
155 msg.browse.uuid.uu.uuid16 = GATT_UUID_CHAR_DECLARE;
156 }
157 break;
158
159 case GATT_READ_CHAR_VALUE_HDL:
160 case GATT_READ_BY_HANDLE:
161 if (!p_clcb->counter) {
162 op_code = GATT_REQ_READ;
163 msg.handle = p_clcb->s_handle;
164 } else {
165 if (!p_clcb->first_read_blob_after_read) {
166 p_clcb->first_read_blob_after_read = TRUE;
167 } else {
168 p_clcb->first_read_blob_after_read = FALSE;
169 }
170
171 GATT_TRACE_DEBUG("gatt_act_read first_read_blob_after_read=%d",
172 p_clcb->first_read_blob_after_read);
173 op_code = GATT_REQ_READ_BLOB;
174 msg.read_blob.offset = offset;
175 msg.read_blob.handle = p_clcb->s_handle;
176 }
177 p_clcb->op_subtype &= ~ 0x80;
178 break;
179
180 case GATT_READ_PARTIAL:
181 op_code = GATT_REQ_READ_BLOB;
182 msg.read_blob.handle = p_clcb->s_handle;
183 msg.read_blob.offset = offset;
184 break;
185
186 case GATT_READ_MULTIPLE:
187 op_code = GATT_REQ_READ_MULTI;
188 memcpy (&msg.read_multi, p_clcb->p_attr_buf, sizeof(tGATT_READ_MULTI));
189 break;
190
191 case GATT_READ_MULTIPLE_VAR:
192 op_code = GATT_REQ_READ_MULTI_VAR;
193 memcpy (&msg.read_multi, p_clcb->p_attr_buf, sizeof(tGATT_READ_MULTI));
194 break;
195
196 case GATT_READ_INC_SRV_UUID128:
197 op_code = GATT_REQ_READ;
198 msg.handle = p_clcb->s_handle;
199 p_clcb->op_subtype &= ~ 0x90;
200 break;
201
202 default:
203 GATT_TRACE_ERROR("Unknown read type: %d", p_clcb->op_subtype);
204 break;
205 }
206
207 if (op_code != 0) {
208 rt = attp_send_cl_msg(p_tcb, p_clcb->clcb_idx, op_code, &msg);
209 }
210
211 if ( op_code == 0 || (rt != GATT_SUCCESS && rt != GATT_CMD_STARTED)) {
212 gatt_end_operation(p_clcb, rt, NULL);
213 }
214 }
215
216 /*******************************************************************************
217 **
218 ** Function gatt_act_write
219 **
220 ** Description GATT write operation.
221 **
222 ** Returns void.
223 **
224 *******************************************************************************/
gatt_act_write(tGATT_CLCB * p_clcb,UINT8 sec_act)225 void gatt_act_write (tGATT_CLCB *p_clcb, UINT8 sec_act)
226 {
227 tGATT_TCB *p_tcb = p_clcb->p_tcb;
228 UINT8 rt = GATT_SUCCESS, op_code = 0;
229 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
230
231 if (p_attr) {
232 switch (p_clcb->op_subtype) {
233 case GATT_WRITE_NO_RSP:
234 l2ble_update_att_acl_pkt_num(L2CA_DECREASE_BTU_NUM, NULL);
235 p_clcb->s_handle = p_attr->handle;
236 op_code = (sec_act == GATT_SEC_SIGN_DATA) ? GATT_SIGN_CMD_WRITE : GATT_CMD_WRITE;
237 rt = gatt_send_write_msg(p_tcb,
238 p_clcb->clcb_idx,
239 op_code,
240 p_attr->handle,
241 p_attr->len,
242 0,
243 p_attr->value);
244 break;
245
246 case GATT_WRITE:
247 if (p_attr->len <= (p_tcb->payload_size - GATT_HDR_SIZE)) {
248 p_clcb->s_handle = p_attr->handle;
249
250 rt = gatt_send_write_msg(p_tcb,
251 p_clcb->clcb_idx,
252 GATT_REQ_WRITE,
253 p_attr->handle,
254 p_attr->len,
255 0,
256 p_attr->value);
257 } else { /* prepare write for long attribute */
258 gatt_send_prepare_write(p_tcb, p_clcb);
259 }
260 break;
261
262 case GATT_WRITE_PREPARE:
263 gatt_send_prepare_write(p_tcb, p_clcb);
264 break;
265
266 default:
267 rt = GATT_INTERNAL_ERROR;
268 GATT_TRACE_ERROR("Unknown write type: %d", p_clcb->op_subtype);
269 break;
270 }
271 } else {
272 rt = GATT_INTERNAL_ERROR;
273 }
274
275 if ((rt != GATT_SUCCESS && rt != GATT_CMD_STARTED && rt != GATT_CONGESTED)
276 || (rt != GATT_CMD_STARTED && p_clcb->op_subtype == GATT_WRITE_NO_RSP)) {
277 if (rt != GATT_SUCCESS) {
278 GATT_TRACE_DEBUG("gatt_act_write() failed op_code=0x%x rt=%d", op_code, rt);
279 }
280 gatt_end_operation(p_clcb, rt, NULL);
281 }
282 }
283 /*******************************************************************************
284 **
285 ** Function gatt_send_queue_write_cancel
286 **
287 ** Description send queue write cancel
288 **
289 ** Returns void.
290 **
291 *******************************************************************************/
gatt_send_queue_write_cancel(tGATT_TCB * p_tcb,tGATT_CLCB * p_clcb,tGATT_EXEC_FLAG flag)292 void gatt_send_queue_write_cancel (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, tGATT_EXEC_FLAG flag)
293 {
294 UINT8 rt ;
295
296 GATT_TRACE_DEBUG("gatt_send_queue_write_cancel ");
297
298 rt = attp_send_cl_msg(p_tcb, p_clcb->clcb_idx, GATT_REQ_EXEC_WRITE, (tGATT_CL_MSG *)&flag);
299
300 if (rt != GATT_SUCCESS) {
301 gatt_end_operation(p_clcb, rt, NULL);
302 }
303 }
304 /*******************************************************************************
305 **
306 ** Function gatt_check_write_long_terminate
307 **
308 ** Description To terminate write long or not.
309 **
310 ** Returns TRUE: write long is terminated; FALSE keep sending.
311 **
312 *******************************************************************************/
gatt_check_write_long_terminate(tGATT_TCB * p_tcb,tGATT_CLCB * p_clcb,tGATT_VALUE * p_rsp_value)313 BOOLEAN gatt_check_write_long_terminate(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, tGATT_VALUE *p_rsp_value)
314 {
315 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
316 BOOLEAN exec = FALSE;
317 tGATT_EXEC_FLAG flag = GATT_PREP_WRITE_EXEC;
318
319 GATT_TRACE_DEBUG("gatt_check_write_long_terminate ");
320 /* check the first write response status */
321 if (p_rsp_value != NULL) {
322 if (p_rsp_value->handle != p_attr->handle ||
323 p_rsp_value->len != p_clcb->counter ||
324 memcmp(p_rsp_value->value, p_attr->value + p_attr->offset, p_rsp_value->len)) {
325 /* data does not match */
326 p_clcb->status = GATT_ERROR;
327 flag = GATT_PREP_WRITE_CANCEL;
328 exec = TRUE;
329 } else { /* response checking is good */
330 p_clcb->status = GATT_SUCCESS;
331 /* update write offset and check if end of attribute value */
332 if ((p_attr->offset += p_rsp_value->len) >= p_attr->len) {
333 exec = TRUE;
334 }
335 }
336 }
337 if (exec) {
338 gatt_send_queue_write_cancel (p_tcb, p_clcb, flag);
339 return TRUE;
340 }
341 return FALSE;
342 }
343 /*******************************************************************************
344 **
345 ** Function gatt_send_prepare_write
346 **
347 ** Description Send prepare write.
348 **
349 ** Returns void.
350 **
351 *******************************************************************************/
gatt_send_prepare_write(tGATT_TCB * p_tcb,tGATT_CLCB * p_clcb)352 void gatt_send_prepare_write(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb)
353 {
354 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
355 UINT16 to_send, offset;
356 UINT8 rt = GATT_SUCCESS;
357 UINT8 type = p_clcb->op_subtype;
358
359 GATT_TRACE_DEBUG("gatt_send_prepare_write type=0x%x", type );
360 to_send = p_attr->len - p_attr->offset;
361
362 if (to_send > (p_tcb->payload_size - GATT_WRITE_LONG_HDR_SIZE)) { /* 2 = UINT16 offset bytes */
363 to_send = p_tcb->payload_size - GATT_WRITE_LONG_HDR_SIZE;
364 }
365
366 p_clcb->s_handle = p_attr->handle;
367
368 offset = p_attr->offset;
369 if (type == GATT_WRITE_PREPARE) {
370 offset += p_clcb->start_offset;
371 }
372
373 GATT_TRACE_DEBUG("offset =0x%x len=%d", offset, to_send );
374
375 rt = gatt_send_write_msg(p_tcb,
376 p_clcb->clcb_idx,
377 GATT_REQ_PREPARE_WRITE,
378 p_attr->handle,
379 to_send, /* length */
380 offset, /* used as offset */
381 p_attr->value + p_attr->offset); /* data */
382
383 /* remember the write long attribute length */
384 p_clcb->counter = to_send;
385
386 if (rt != GATT_SUCCESS && rt != GATT_CMD_STARTED) {
387 gatt_end_operation(p_clcb, rt, NULL);
388 }
389 }
390
391
392 /*******************************************************************************
393 **
394 ** Function gatt_process_find_type_value_rsp
395 **
396 ** Description This function is called to handle find by type value response.
397 **
398 **
399 ** Returns void
400 **
401 *******************************************************************************/
gatt_process_find_type_value_rsp(tGATT_TCB * p_tcb,tGATT_CLCB * p_clcb,UINT16 len,UINT8 * p_data)402 void gatt_process_find_type_value_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
403 {
404 tGATT_DISC_RES result;
405 UINT8 *p = p_data;
406
407 UNUSED(p_tcb);
408
409 GATT_TRACE_DEBUG("gatt_process_find_type_value_rsp ");
410 /* unexpected response */
411 if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_SRVC_BY_UUID) {
412 return;
413 }
414
415 memset (&result, 0, sizeof(tGATT_DISC_RES));
416 result.type.len = 2;
417 result.type.uu.uuid16 = GATT_UUID_PRI_SERVICE;
418
419 /* returns a series of handle ranges */
420 while (len >= 4) {
421 STREAM_TO_UINT16 (result.handle, p);
422 STREAM_TO_UINT16 (result.value.group_value.e_handle, p);
423 GATT_DISC_INFO("%s handle %x, end handle %x", __func__, result.handle, result.value.group_value.e_handle);
424 memcpy (&result.value.group_value.service_type, &p_clcb->uuid, sizeof(tBT_UUID));
425
426 len -= 4;
427
428 if (p_clcb->p_reg->app_cb.p_disc_res_cb) {
429 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
430 }
431 }
432
433 /* last handle + 1 */
434 p_clcb->s_handle = (result.value.group_value.e_handle == 0) ? 0 : (result.value.group_value.e_handle + 1);
435 /* initiate another request */
436 gatt_act_discovery(p_clcb) ;
437 }
438 /*******************************************************************************
439 **
440 ** Function gatt_process_read_info_rsp
441 **
442 ** Description This function is called to handle the read information
443 ** response.
444 **
445 **
446 ** Returns void
447 **
448 *******************************************************************************/
gatt_process_read_info_rsp(tGATT_TCB * p_tcb,tGATT_CLCB * p_clcb,UINT8 op_code,UINT16 len,UINT8 * p_data)449 void gatt_process_read_info_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
450 UINT16 len, UINT8 *p_data)
451 {
452 tGATT_DISC_RES result;
453 UINT8 *p = p_data, uuid_len = 0, type;
454
455 UNUSED(p_tcb);
456 UNUSED(op_code);
457
458 if (len < GATT_INFO_RSP_MIN_LEN) {
459 GATT_TRACE_ERROR("invalid Info Response PDU received, discard.");
460 gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
461 return;
462 }
463 /* unexpected response */
464 if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_CHAR_DSCPT) {
465 return;
466 }
467
468 STREAM_TO_UINT8(type, p);
469 len -= 1;
470
471 if (type == GATT_INFO_TYPE_PAIR_16) {
472 uuid_len = LEN_UUID_16;
473 } else if (type == GATT_INFO_TYPE_PAIR_128) {
474 uuid_len = LEN_UUID_128;
475 }
476
477 while (len >= uuid_len + 2) {
478 STREAM_TO_UINT16 (result.handle, p);
479
480 if (uuid_len > 0) {
481 if (!gatt_parse_uuid_from_cmd(&result.type, uuid_len, &p)) {
482 break;
483 }
484 } else {
485 memcpy (&result.type, &p_clcb->uuid, sizeof(tBT_UUID));
486 }
487
488 len -= (uuid_len + 2);
489
490 GATT_DISC_INFO("%s handle %x, uuid %s", __func__, result.handle, gatt_uuid_to_str(&result.type));
491
492 if (p_clcb->p_reg->app_cb.p_disc_res_cb) {
493 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
494 }
495 }
496
497 p_clcb->s_handle = (result.handle == 0) ? 0 : (result.handle + 1);
498 /* initiate another request */
499 gatt_act_discovery(p_clcb) ;
500 }
501 /*******************************************************************************
502 **
503 ** Function gatt_proc_disc_error_rsp
504 **
505 ** Description This function process the read by type response and send another
506 ** request if needed.
507 **
508 ** Returns void.
509 **
510 *******************************************************************************/
gatt_proc_disc_error_rsp(tGATT_TCB * p_tcb,tGATT_CLCB * p_clcb,UINT8 opcode,UINT16 handle,UINT8 reason)511 void gatt_proc_disc_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 opcode,
512 UINT16 handle, UINT8 reason)
513 {
514 tGATT_STATUS status = (tGATT_STATUS) reason;
515
516 UNUSED(p_tcb);
517 UNUSED(handle);
518
519 GATT_TRACE_DEBUG("gatt_proc_disc_error_rsp reason: %02x cmd_code %04x", reason, opcode);
520
521 switch (opcode) {
522 case GATT_REQ_READ_BY_GRP_TYPE:
523 case GATT_REQ_FIND_TYPE_VALUE:
524 case GATT_REQ_READ_BY_TYPE:
525 case GATT_REQ_FIND_INFO:
526 if (reason == GATT_NOT_FOUND) {
527 status = GATT_SUCCESS;
528 GATT_DISC_INFO("Discovery completed");
529 }
530 break;
531 default:
532 GATT_TRACE_ERROR("Incorrect discovery opcode %04x", opcode);
533 break;
534 }
535
536 gatt_end_operation(p_clcb, status, NULL);
537 }
538
539 /*******************************************************************************
540 **
541 ** Function gatt_process_error_rsp
542 **
543 ** Description This function is called to handle the error response
544 **
545 **
546 ** Returns void
547 **
548 *******************************************************************************/
gatt_process_error_rsp(tGATT_TCB * p_tcb,tGATT_CLCB * p_clcb,UINT8 op_code,UINT16 len,UINT8 * p_data)549 void gatt_process_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
550 UINT16 len, UINT8 *p_data)
551 {
552 UINT8 opcode, reason, * p = p_data;
553 UINT16 handle;
554 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
555
556 UNUSED(op_code);
557 UNUSED(len);
558
559 GATT_TRACE_DEBUG("%s", __func__);
560 STREAM_TO_UINT8(opcode, p);
561 STREAM_TO_UINT16(handle, p);
562 STREAM_TO_UINT8(reason, p);
563
564 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY) {
565 gatt_proc_disc_error_rsp(p_tcb, p_clcb, opcode, handle, reason);
566 } else {
567 if ( (p_clcb->operation == GATTC_OPTYPE_WRITE) &&
568 (p_clcb->op_subtype == GATT_WRITE) &&
569 (opcode == GATT_REQ_PREPARE_WRITE) &&
570 (p_attr) &&
571 (handle == p_attr->handle) ) {
572 if (reason == GATT_SUCCESS){
573 reason = GATT_ERROR;
574 }
575 p_clcb->status = reason;
576 gatt_send_queue_write_cancel(p_tcb, p_clcb, GATT_PREP_WRITE_CANCEL);
577 } else if ((p_clcb->operation == GATTC_OPTYPE_READ) &&
578 ((p_clcb->op_subtype == GATT_READ_CHAR_VALUE_HDL) ||
579 (p_clcb->op_subtype == GATT_READ_BY_HANDLE)) &&
580 (opcode == GATT_REQ_READ_BLOB) &&
581 p_clcb->first_read_blob_after_read &&
582 (reason == GATT_NOT_LONG)) {
583 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf);
584 } else {
585 gatt_end_operation(p_clcb, reason, NULL);
586 }
587 }
588 }
589 /*******************************************************************************
590 **
591 ** Function gatt_process_prep_write_rsp
592 **
593 ** Description This function is called to handle the read response
594 **
595 **
596 ** Returns void
597 **
598 *******************************************************************************/
gatt_process_prep_write_rsp(tGATT_TCB * p_tcb,tGATT_CLCB * p_clcb,UINT8 op_code,UINT16 len,UINT8 * p_data)599 void gatt_process_prep_write_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
600 UINT16 len, UINT8 *p_data)
601 {
602 tGATT_VALUE value = {0};
603 UINT8 *p = p_data;
604
605 GATT_TRACE_DEBUG("value resp op_code = %s len = %d", gatt_dbg_op_name(op_code), len);
606
607 if (len < GATT_PREP_WRITE_RSP_MIN_LEN) {
608 GATT_TRACE_ERROR("illegal prepare write response length, discard");
609 gatt_end_operation(p_clcb, GATT_INVALID_PDU, &value);
610 return;
611 }
612
613 STREAM_TO_UINT16 (value.handle, p);
614 STREAM_TO_UINT16 (value.offset, p);
615
616 value.len = len - 4;
617
618 memcpy (value.value, p, value.len);
619
620 if (p_clcb->op_subtype == GATT_WRITE_PREPARE) {
621 p_clcb->status = GATT_SUCCESS;
622 /* application should verify handle offset
623 and value are matched or not */
624
625 gatt_end_operation(p_clcb, p_clcb->status, &value);
626 } else if (p_clcb->op_subtype == GATT_WRITE ) {
627 if (!gatt_check_write_long_terminate(p_tcb, p_clcb, &value)) {
628 gatt_send_prepare_write(p_tcb, p_clcb);
629 }
630 }
631
632 }
633 /*******************************************************************************
634 **
635 ** Function gatt_process_notification
636 **
637 ** Description This function is called to handle the handle value indication
638 ** or handle value notification.
639 **
640 **
641 ** Returns void
642 **
643 *******************************************************************************/
gatt_process_notification(tGATT_TCB * p_tcb,UINT8 op_code,UINT16 len,UINT8 * p_data)644 void gatt_process_notification(tGATT_TCB *p_tcb, UINT8 op_code,
645 UINT16 len, UINT8 *p_data)
646 {
647 tGATT_VALUE value = {0};
648 tGATT_REG *p_reg;
649 UINT16 conn_id;
650 tGATT_STATUS encrypt_status;
651 UINT8 *p = p_data, i,
652 event = (op_code == GATT_HANDLE_VALUE_IND) ? GATTC_OPTYPE_INDICATION: GATTC_OPTYPE_NOTIFICATION;
653
654 GATT_TRACE_DEBUG("gatt_process_notification ");
655
656 if (len < GATT_NOTIFICATION_MIN_LEN) {
657 GATT_TRACE_ERROR("illegal notification PDU length, discard");
658 return;
659 }
660
661 STREAM_TO_UINT16 (value.handle, p);
662
663 if (!GATT_HANDLE_IS_VALID(value.handle)) {
664 /* illegal handle, send ack now */
665 if (op_code == GATT_HANDLE_VALUE_IND) {
666 attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
667 }
668 return;
669 }
670
671 if (op_code == GATT_HANDLE_MULTI_VALUE_NOTIF) {
672 if (len < GATT_NOTIFICATION_MIN_LEN + 2) {
673 GATT_TRACE_ERROR("illegal notification PDU length, discard");
674 return;
675 }
676
677 STREAM_TO_UINT16(value.len, p);
678 if (value.len > len - 4) {
679 return;
680 }
681 } else {
682 value.len = len - 2;
683 }
684
685 if (value.len > GATT_MAX_ATTR_LEN) {
686 GATT_TRACE_ERROR("value length larger than GATT_MAX_ATTR_LEN, discard");
687 return;
688 }
689
690 memcpy(value.value, p, value.len);
691 p += value.len;
692
693 if (event == GATTC_OPTYPE_INDICATION) {
694 if (p_tcb->ind_count) {
695 /* this is an error case that receiving an indication but we
696 still has an indication not being acked yet.
697 For now, just log the error reset the counter.
698 Later we need to disconnect the link unconditionally.
699 */
700 GATT_TRACE_ERROR("gatt_process_notification rcv Ind. but ind_count=%d (will reset ind_count)", p_tcb->ind_count);
701 }
702 p_tcb->ind_count = 0;
703
704 /* should notify all registered client with the handle value notificaion/indication
705 Note: need to do the indication count and start timer first then do callback
706 */
707 for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) {
708 if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb && (event == GATTC_OPTYPE_INDICATION)) {
709 p_tcb->ind_count++;
710 }
711 }
712
713 /* start a timer for app confirmation */
714 if (p_tcb->ind_count > 0) {
715 gatt_start_ind_ack_timer(p_tcb);
716 } else { /* no app to indicate, or invalid handle */
717 attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
718 }
719 }
720
721 encrypt_status = gatt_get_link_encrypt_status(p_tcb);
722 for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) {
723 if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb) {
724 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
725 (*p_reg->app_cb.p_cmpl_cb) (conn_id, event, encrypt_status, (tGATT_CL_COMPLETE *)&value);
726 }
727 }
728
729 if (op_code != GATT_HANDLE_MULTI_VALUE_NOTIF) {
730 return;
731 }
732
733 if (len < (4 + value.len)) {
734 GATT_TRACE_ERROR("no remain data for multi notification");
735 return;
736 }
737
738 len -= (4 + value.len);
739
740 while (len > 4) {
741 STREAM_TO_UINT16(value.handle, p);
742 STREAM_TO_UINT16(value.len, p);
743 len -= 4;
744 value.len = MIN(len, value.len);
745 memcpy(value.value, p, value.len);
746 p += value.len;
747 len -= value.len;
748
749 for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) {
750 if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb) {
751 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
752 (*p_reg->app_cb.p_cmpl_cb) (conn_id, event, encrypt_status, (tGATT_CL_COMPLETE *)&value);
753 }
754 }
755 }
756 }
757
758 /*******************************************************************************
759 **
760 ** Function gatt_process_read_by_type_rsp
761 **
762 ** Description This function is called to handle the read by type response.
763 ** read by type can be used for discovery, or read by type or
764 ** read characteristic value.
765 **
766 ** Returns void
767 **
768 *******************************************************************************/
gatt_process_read_by_type_rsp(tGATT_TCB * p_tcb,tGATT_CLCB * p_clcb,UINT8 op_code,UINT16 len,UINT8 * p_data)769 void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
770 UINT16 len, UINT8 *p_data)
771 {
772 tGATT_DISC_RES result;
773 tGATT_DISC_VALUE record_value;
774 UINT8 *p = p_data, value_len, handle_len = 2;
775 UINT16 handle = 0;
776
777 /* discovery procedure and no callback function registered */
778 if (((!p_clcb->p_reg) || (!p_clcb->p_reg->app_cb.p_disc_res_cb)) && (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)) {
779 return;
780 }
781
782 if (len < GATT_READ_BY_TYPE_RSP_MIN_LEN) {
783 GATT_TRACE_ERROR("Illegal ReadByType/ReadByGroupType Response length, discard");
784 gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
785 return;
786 }
787
788 STREAM_TO_UINT8(value_len, p);
789
790 if ((value_len > (p_tcb->payload_size - 2)) || (value_len > (len - 1)) ) {
791 /* this is an error case that server's response containing a value length which is larger than MTU-2
792 or value_len > message total length -1 */
793 GATT_TRACE_ERROR("gatt_process_read_by_type_rsp: Discard response op_code=%d vale_len=%d > (MTU-2=%d or msg_len-1=%d)",
794 op_code, value_len, (p_tcb->payload_size - 2), (len - 1));
795 gatt_end_operation(p_clcb, GATT_ERROR, NULL);
796 return;
797 }
798
799 if (op_code == GATT_RSP_READ_BY_GRP_TYPE) {
800 handle_len = 4;
801 }
802
803 value_len -= handle_len; /* substract the handle pairs bytes */
804 len -= 1;
805
806 while (len >= (handle_len + value_len)) {
807 STREAM_TO_UINT16(handle, p);
808 GATT_DISC_INFO("%s op %x, handle %x", __func__, op_code, handle);
809
810 if (!GATT_HANDLE_IS_VALID(handle)) {
811 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
812 return;
813 }
814
815 memset(&result, 0, sizeof(tGATT_DISC_RES));
816 memset(&record_value, 0, sizeof(tGATT_DISC_VALUE));
817
818 result.handle = handle;
819 result.type.len = 2;
820 result.type.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype];
821
822 /* discover all services */
823 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
824 p_clcb->op_subtype == GATT_DISC_SRVC_ALL &&
825 op_code == GATT_RSP_READ_BY_GRP_TYPE) {
826 STREAM_TO_UINT16(handle, p);
827
828 if (!GATT_HANDLE_IS_VALID(handle)) {
829 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
830 return;
831 } else {
832 record_value.group_value.e_handle = handle;
833 if (!gatt_parse_uuid_from_cmd(&record_value.group_value.service_type, value_len, &p)) {
834 GATT_TRACE_ERROR("discover all service response parsing failure");
835 break;
836 }
837 }
838 GATT_DISC_INFO("DISC ALL SVC end handle %x, uuid %s", record_value.group_value.e_handle, gatt_uuid_to_str(&record_value.group_value.service_type));
839 }
840 /* discover included service */
841 else if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->op_subtype == GATT_DISC_INC_SRVC) {
842 STREAM_TO_UINT16(record_value.incl_service.s_handle, p);
843 STREAM_TO_UINT16(record_value.incl_service.e_handle, p);
844
845 if (!GATT_HANDLE_IS_VALID(record_value.incl_service.s_handle) ||
846 !GATT_HANDLE_IS_VALID(record_value.incl_service.e_handle)) {
847 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
848 return;
849 }
850
851 if (value_len == 6) {
852 STREAM_TO_UINT16(record_value.incl_service.service_type.uu.uuid16, p);
853 record_value.incl_service.service_type.len = LEN_UUID_16;
854 GATT_DISC_INFO("DISC INC SVC start handle %x, end handle %x, uuid %s",
855 record_value.incl_service.s_handle, record_value.incl_service.e_handle, gatt_uuid_to_str(&record_value.incl_service.service_type));
856 } else if (value_len == 4) {
857 p_clcb->s_handle = record_value.incl_service.s_handle;
858 p_clcb->read_uuid128.wait_for_read_rsp = TRUE;
859 p_clcb->read_uuid128.next_disc_start_hdl = handle + 1;
860 memcpy(&p_clcb->read_uuid128.result, &result, sizeof(result));
861 memcpy(&p_clcb->read_uuid128.result.value, &record_value, sizeof (result.value));
862 p_clcb->op_subtype |= 0x90;
863 gatt_act_read(p_clcb, 0); // read 128-bit uuid of include service
864 return;
865 } else {
866 GATT_TRACE_ERROR("gatt_process_read_by_type_rsp INCL_SRVC failed with invalid data value_len=%d", value_len);
867 gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p);
868 return;
869 }
870 }
871 /* read by type */
872 else if (p_clcb->operation == GATTC_OPTYPE_READ && p_clcb->op_subtype == GATT_READ_BY_TYPE) {
873 p_clcb->counter = len - 2;
874 p_clcb->s_handle = handle;
875 if ( p_clcb->counter == (p_clcb->p_tcb->payload_size - 4)) {
876 p_clcb->op_subtype = GATT_READ_BY_HANDLE;
877 if (!p_clcb->p_attr_buf) {
878 p_clcb->p_attr_buf = (UINT8 *)osi_malloc(GATT_MAX_ATTR_LEN);
879 }
880 if (p_clcb->p_attr_buf && p_clcb->counter <= GATT_MAX_ATTR_LEN) {
881 memcpy(p_clcb->p_attr_buf, p, p_clcb->counter);
882 gatt_act_read(p_clcb, p_clcb->counter);
883 } else {
884 gatt_end_operation(p_clcb, GATT_INTERNAL_ERROR, (void *)p);
885 }
886 } else {
887 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p);
888 }
889 return;
890 } else { /* discover characterisitic */
891 STREAM_TO_UINT8 (record_value.dclr_value.char_prop, p);
892 STREAM_TO_UINT16(record_value.dclr_value.val_handle, p);
893 if (!GATT_HANDLE_IS_VALID(record_value.dclr_value.val_handle)) {
894 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
895 return;
896 }
897 if (!gatt_parse_uuid_from_cmd(&record_value.dclr_value.char_uuid, (UINT16)(value_len - 3), &p)) {
898 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
899 /* invalid format, and skip the result */
900 return;
901 }
902
903 /* UUID not matching */
904 if (!gatt_uuid_compare(record_value.dclr_value.char_uuid, p_clcb->uuid)) {
905 len -= (value_len + 2);
906 continue; /* skip the result, and look for next one */
907 } else if (p_clcb->operation == GATTC_OPTYPE_READ)
908 /* UUID match for read characteristic value */
909 {
910 /* only read the first matching UUID characteristic value, and
911 discard the rest results */
912 p_clcb->s_handle = record_value.dclr_value.val_handle;
913 p_clcb->op_subtype |= 0x80;
914 gatt_act_read(p_clcb, 0);
915 return;
916 }
917 }
918 len -= (value_len + handle_len);
919
920 /* result is (handle, 16bits UUID) pairs */
921 memcpy (&result.value, &record_value, sizeof (result.value));
922
923 /* send callback if is discover procedure */
924 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->p_reg->app_cb.p_disc_res_cb) {
925 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
926 }
927 }
928
929 p_clcb->s_handle = (handle == 0) ? 0 : (handle + 1);
930
931 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY) {
932 /* initiate another request */
933 gatt_act_discovery(p_clcb) ;
934 } else { /* read characteristic value */
935 gatt_act_read(p_clcb, 0);
936 }
937 }
938
939 /*******************************************************************************
940 **
941 ** Function gatt_process_read_rsp
942 **
943 ** Description This function is called to handle the read BLOB response
944 **
945 **
946 ** Returns void
947 **
948 *******************************************************************************/
gatt_process_read_rsp(tGATT_TCB * p_tcb,tGATT_CLCB * p_clcb,UINT8 op_code,UINT16 len,UINT8 * p_data)949 void gatt_process_read_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
950 UINT16 len, UINT8 *p_data)
951 {
952 UINT16 offset = p_clcb->counter;
953 UINT8 *p = p_data;
954
955 UNUSED(op_code);
956
957 if (p_clcb->operation == GATTC_OPTYPE_READ) {
958 if (p_clcb->op_subtype != GATT_READ_BY_HANDLE) {
959 p_clcb->counter = len;
960 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p);
961 } else {
962
963 /* allocate GKI buffer holding up long attribute value */
964 if (!p_clcb->p_attr_buf) {
965 p_clcb->p_attr_buf = (UINT8 *)osi_malloc(GATT_MAX_ATTR_LEN);
966 }
967
968 /* copy attrobute value into cb buffer */
969 if (p_clcb->p_attr_buf && offset < GATT_MAX_ATTR_LEN) {
970 if ((len + offset) > GATT_MAX_ATTR_LEN) {
971 len = GATT_MAX_ATTR_LEN - offset;
972 }
973
974 p_clcb->counter += len;
975
976 memcpy(p_clcb->p_attr_buf + offset, p, len);
977
978 /* send next request if needed */
979
980 if (len == (p_tcb->payload_size - 1) && /* full packet for read or read blob rsp */
981 len + offset < GATT_MAX_ATTR_LEN) {
982 GATT_TRACE_DEBUG("full pkt issue read blob for remianing bytes old offset=%d len=%d new offset=%d",
983 offset, len, p_clcb->counter);
984 gatt_act_read(p_clcb, p_clcb->counter);
985 } else { /* end of request, send callback */
986 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf);
987 }
988 } else { /* exception, should not happen */
989 GATT_TRACE_ERROR("attr offset = %d p_attr_buf = %p ", offset, p_clcb->p_attr_buf);
990 gatt_end_operation(p_clcb, GATT_NO_RESOURCES, (void *)p_clcb->p_attr_buf);
991 }
992 }
993 } else {
994 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
995 p_clcb->op_subtype == GATT_DISC_INC_SRVC &&
996 p_clcb->read_uuid128.wait_for_read_rsp ) {
997 p_clcb->s_handle = p_clcb->read_uuid128.next_disc_start_hdl;
998 p_clcb->read_uuid128.wait_for_read_rsp = FALSE;
999 if (len == LEN_UUID_128) {
1000
1001 memcpy(p_clcb->read_uuid128.result.value.incl_service.service_type.uu.uuid128, p, len);
1002 p_clcb->read_uuid128.result.value.incl_service.service_type.len = LEN_UUID_128;
1003 tGATT_INCL_SRVC *inc_srvc = &p_clcb->read_uuid128.result.value.incl_service;
1004 GATT_DISC_INFO("DISC INC SRVC start handle %x, end handle %x, uuid %s",
1005 inc_srvc->s_handle, inc_srvc->e_handle, gatt_uuid_to_str(&inc_srvc->service_type));
1006 if ( p_clcb->p_reg->app_cb.p_disc_res_cb) {
1007 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &p_clcb->read_uuid128.result);
1008 }
1009 gatt_act_discovery(p_clcb) ;
1010 } else {
1011 gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p);
1012 }
1013 }
1014 }
1015
1016 }
1017
1018
1019 /*******************************************************************************
1020 **
1021 ** Function gatt_process_handle_rsp
1022 **
1023 ** Description This function is called to handle the write response
1024 **
1025 **
1026 ** Returns void
1027 **
1028 *******************************************************************************/
gatt_process_handle_rsp(tGATT_CLCB * p_clcb)1029 void gatt_process_handle_rsp(tGATT_CLCB *p_clcb)
1030 {
1031 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
1032 }
1033 /*******************************************************************************
1034 **
1035 ** Function gatt_process_mtu_rsp
1036 **
1037 ** Description This function is called to process the configure MTU response.
1038 **
1039 **
1040 ** Returns void
1041 **
1042 *******************************************************************************/
gatt_process_mtu_rsp(tGATT_TCB * p_tcb,tGATT_CLCB * p_clcb,UINT16 len,UINT8 * p_data)1043 void gatt_process_mtu_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
1044 {
1045 UINT16 mtu;
1046 tGATT_STATUS status = GATT_SUCCESS;
1047
1048 if (len < GATT_MTU_RSP_MIN_LEN) {
1049 GATT_TRACE_ERROR("invalid MTU response PDU received, discard.");
1050 status = GATT_INVALID_PDU;
1051 } else {
1052 STREAM_TO_UINT16(mtu, p_data);
1053
1054 if (mtu < p_tcb->payload_size && mtu >= GATT_DEF_BLE_MTU_SIZE) {
1055 p_tcb->payload_size = mtu;
1056 }
1057 }
1058 /* host will set packet data length to 251 automatically if remote device support set packet data length,
1059 so l2cble_set_fixed_channel_tx_data_length() is not necessary.
1060 l2cble_set_fixed_channel_tx_data_length(p_tcb->peer_bda, L2CAP_ATT_CID, p_tcb->payload_size);
1061 */
1062 gatt_end_operation(p_clcb, status, NULL);
1063 }
1064 /*******************************************************************************
1065 **
1066 ** Function gatt_cmd_to_rsp_code
1067 **
1068 ** Description The function convert a ATT command op code into the corresponding
1069 ** response code assume no error occurs.
1070 **
1071 ** Returns response code.
1072 **
1073 *******************************************************************************/
gatt_cmd_to_rsp_code(UINT8 cmd_code)1074 UINT8 gatt_cmd_to_rsp_code (UINT8 cmd_code)
1075 {
1076 UINT8 rsp_code = 0;
1077
1078 if (cmd_code > 1 && cmd_code != GATT_CMD_WRITE) {
1079 rsp_code = cmd_code + 1;
1080 }
1081 return rsp_code;
1082 }
1083 /*******************************************************************************
1084 **
1085 ** Function gatt_cl_send_next_cmd_inq
1086 **
1087 ** Description Find next command in queue and sent to server
1088 **
1089 ** Returns TRUE if command sent, otherwise FALSE.
1090 **
1091 *******************************************************************************/
gatt_cl_send_next_cmd_inq(tGATT_TCB * p_tcb)1092 BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb)
1093 {
1094 tGATT_CMD_Q *p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1095 BOOLEAN sent = FALSE;
1096 UINT8 rsp_code;
1097 tGATT_CLCB *p_clcb = NULL;
1098 tGATT_STATUS att_ret = GATT_SUCCESS;
1099
1100 while (!sent &&
1101 p_tcb->pending_cl_req != p_tcb->next_slot_inq &&
1102 p_cmd->to_send && p_cmd->p_cmd != NULL) {
1103 att_ret = attp_send_msg_to_l2cap(p_tcb, p_cmd->p_cmd);
1104
1105 if (att_ret == GATT_SUCCESS || att_ret == GATT_CONGESTED) {
1106 sent = TRUE;
1107 p_cmd->to_send = FALSE;
1108 if(p_cmd->p_cmd) {
1109 osi_free(p_cmd->p_cmd);
1110 p_cmd->p_cmd = NULL;
1111 }
1112
1113 /* dequeue the request if is write command or sign write */
1114 if (p_cmd->op_code != GATT_CMD_WRITE && p_cmd->op_code != GATT_SIGN_CMD_WRITE) {
1115 gatt_start_rsp_timer (p_cmd->clcb_idx);
1116 } else {
1117 p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
1118
1119 /* if no ack needed, keep sending */
1120 if (att_ret == GATT_SUCCESS) {
1121 sent = FALSE;
1122 }
1123
1124 p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1125 /* send command complete callback here */
1126 gatt_end_operation(p_clcb, att_ret, NULL);
1127 }
1128 } else {
1129 GATT_TRACE_ERROR("gatt_cl_send_next_cmd_inq: L2CAP sent error");
1130
1131 memset(p_cmd, 0, sizeof(tGATT_CMD_Q));
1132 p_tcb->pending_cl_req ++;
1133 p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1134 }
1135
1136 }
1137 return sent;
1138 }
1139
1140 /*******************************************************************************
1141 **
1142 ** Function gatt_client_handle_server_rsp
1143 **
1144 ** Description This function is called to handle the server response to
1145 ** client.
1146 **
1147 **
1148 ** Returns void
1149 **
1150 *******************************************************************************/
gatt_client_handle_server_rsp(tGATT_TCB * p_tcb,UINT8 op_code,UINT16 len,UINT8 * p_data)1151 void gatt_client_handle_server_rsp (tGATT_TCB *p_tcb, UINT8 op_code,
1152 UINT16 len, UINT8 *p_data)
1153 {
1154 tGATT_CLCB *p_clcb = NULL;
1155 UINT8 rsp_code;
1156
1157 if (op_code != GATT_HANDLE_VALUE_IND && op_code != GATT_HANDLE_VALUE_NOTIF &&
1158 op_code != GATT_HANDLE_MULTI_VALUE_NOTIF) {
1159 p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
1160
1161 rsp_code = gatt_cmd_to_rsp_code(rsp_code);
1162
1163 if (p_clcb == NULL || (rsp_code != op_code && op_code != GATT_RSP_ERROR)) {
1164 GATT_TRACE_WARNING ("ATT - Ignore wrong response. Receives (%02x) \
1165 Request(%02x) Ignored", op_code, rsp_code);
1166
1167 return;
1168 } else {
1169 btu_stop_timer (&p_clcb->rsp_timer_ent);
1170 p_clcb->retry_count = 0;
1171 }
1172 }
1173 /* the size of the message may not be bigger than the local max PDU size*/
1174 /* The message has to be smaller than the agreed MTU, len does not count op_code */
1175 if (len >= p_tcb->payload_size) {
1176 GATT_TRACE_ERROR("invalid response/indicate pkt size: %d, PDU size: %d", len + 1, p_tcb->payload_size);
1177 if (op_code != GATT_HANDLE_VALUE_NOTIF && op_code != GATT_HANDLE_VALUE_IND &&
1178 op_code != GATT_HANDLE_MULTI_VALUE_NOTIF) {
1179 gatt_end_operation(p_clcb, GATT_ERROR, NULL);
1180 }
1181 } else {
1182 switch (op_code) {
1183 case GATT_RSP_ERROR:
1184 gatt_process_error_rsp(p_tcb, p_clcb, op_code, len, p_data);
1185 break;
1186
1187 case GATT_RSP_MTU: /* 2 bytes mtu */
1188 gatt_process_mtu_rsp(p_tcb, p_clcb, len , p_data);
1189 break;
1190
1191 case GATT_RSP_FIND_INFO:
1192 gatt_process_read_info_rsp(p_tcb, p_clcb, op_code, len, p_data);
1193 break;
1194
1195 case GATT_RSP_READ_BY_TYPE:
1196 case GATT_RSP_READ_BY_GRP_TYPE:
1197 gatt_process_read_by_type_rsp(p_tcb, p_clcb, op_code, len, p_data);
1198 break;
1199
1200 case GATT_RSP_READ:
1201 case GATT_RSP_READ_BLOB:
1202 case GATT_RSP_READ_MULTI:
1203 case GATT_RSP_READ_MULTI_VAR:
1204 gatt_process_read_rsp(p_tcb, p_clcb, op_code, len, p_data);
1205 break;
1206
1207 case GATT_RSP_FIND_TYPE_VALUE: /* disc service with UUID */
1208 gatt_process_find_type_value_rsp(p_tcb, p_clcb, len, p_data);
1209 break;
1210
1211 case GATT_RSP_WRITE:
1212 gatt_process_handle_rsp(p_clcb);
1213 break;
1214
1215 case GATT_RSP_PREPARE_WRITE:
1216 gatt_process_prep_write_rsp(p_tcb, p_clcb, op_code, len, p_data);
1217 break;
1218
1219 case GATT_RSP_EXEC_WRITE:
1220 gatt_end_operation(p_clcb, p_clcb->status, NULL);
1221 break;
1222
1223 case GATT_HANDLE_VALUE_NOTIF:
1224 case GATT_HANDLE_VALUE_IND:
1225 case GATT_HANDLE_MULTI_VALUE_NOTIF:
1226 gatt_process_notification(p_tcb, op_code, len, p_data);
1227 break;
1228
1229 default:
1230 GATT_TRACE_ERROR("Unknown opcode = %d", op_code);
1231 break;
1232 }
1233 }
1234
1235 if (op_code != GATT_HANDLE_VALUE_IND && op_code != GATT_HANDLE_VALUE_NOTIF &&
1236 op_code != GATT_HANDLE_MULTI_VALUE_NOTIF) {
1237 gatt_cl_send_next_cmd_inq(p_tcb);
1238 }
1239 }
1240
1241 #endif /* BLE_INCLUDED == TRUE && GATTC_INCLUDED == TRUE */
1242