1 /******************************************************************************
3 * Copyright (C) 1999-2012 Broadcom Corporation
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
19 /******************************************************************************
21 * this file contains the main GATT client functions
23 ******************************************************************************/
25 #include "bt_target.h"
27 #if BLE_INCLUDED == TRUE
31 #include "bt_common.h"
35 #define GATT_WRITE_LONG_HDR_SIZE 5 /* 1 opcode + 2 handle + 2 offset */
36 #define GATT_READ_CHAR_VALUE_HDL (GATT_READ_CHAR_VALUE | 0x80)
37 #define GATT_READ_INC_SRV_UUID128 (GATT_DISC_INC_SRVC | 0x90)
39 #define GATT_PREP_WRITE_RSP_MIN_LEN 4
40 #define GATT_NOTIFICATION_MIN_LEN 2
41 #define GATT_WRITE_RSP_MIN_LEN 2
42 #define GATT_INFO_RSP_MIN_LEN 1
43 #define GATT_MTU_RSP_MIN_LEN 2
44 #define GATT_READ_BY_TYPE_RSP_MIN_LEN 1
46 /********************************************************************************
47 ** G L O B A L G A T T D A T A *
48 *********************************************************************************/
49 void gatt_send_prepare_write(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb);
51 UINT8 disc_type_to_att_opcode[GATT_DISC_MAX] =
54 GATT_REQ_READ_BY_GRP_TYPE, /* GATT_DISC_SRVC_ALL = 1, */
55 GATT_REQ_FIND_TYPE_VALUE, /* GATT_DISC_SRVC_BY_UUID, */
56 GATT_REQ_READ_BY_TYPE, /* GATT_DISC_INC_SRVC, */
57 GATT_REQ_READ_BY_TYPE, /* GATT_DISC_CHAR, */
58 GATT_REQ_FIND_INFO /* GATT_DISC_CHAR_DSCPT, */
61 UINT16 disc_type_to_uuid[GATT_DISC_MAX] =
64 GATT_UUID_PRI_SERVICE, /* <service> DISC_SRVC_ALL */
65 GATT_UUID_PRI_SERVICE, /* <service> for DISC_SERVC_BY_UUID */
66 GATT_UUID_INCLUDE_SERVICE, /* <include_service> for DISC_INC_SRVC */
67 GATT_UUID_CHAR_DECLARE, /* <characteristic> for DISC_CHAR */
68 0 /* no type filtering for DISC_CHAR_DSCPT */
72 /*******************************************************************************
74 ** Function gatt_act_discovery
76 ** Description GATT discovery operation.
80 *******************************************************************************/
81 void gatt_act_discovery(tGATT_CLCB *p_clcb)
83 UINT8 op_code = disc_type_to_att_opcode[p_clcb->op_subtype];
87 if (p_clcb->s_handle <= p_clcb->e_handle && p_clcb->s_handle != 0)
89 memset(&cl_req, 0, sizeof(tGATT_CL_MSG));
91 cl_req.browse.s_handle = p_clcb->s_handle;
92 cl_req.browse.e_handle = p_clcb->e_handle;
94 if (disc_type_to_uuid[p_clcb->op_subtype] != 0)
96 cl_req.browse.uuid.len = 2;
97 cl_req.browse.uuid.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype];
100 if (p_clcb->op_subtype == GATT_DISC_SRVC_BY_UUID) /* fill in the FindByTypeValue request info*/
102 cl_req.find_type_value.uuid.len = 2;
103 cl_req.find_type_value.uuid.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype];
104 cl_req.find_type_value.s_handle = p_clcb->s_handle;
105 cl_req.find_type_value.e_handle = p_clcb->e_handle;
106 cl_req.find_type_value.value_len = p_clcb->uuid.len;
107 /* if service type is 32 bits UUID, convert it now */
108 if (p_clcb->uuid.len == LEN_UUID_32)
110 cl_req.find_type_value.value_len = LEN_UUID_128;
111 gatt_convert_uuid32_to_uuid128(cl_req.find_type_value.value, p_clcb->uuid.uu.uuid32);
114 memcpy (cl_req.find_type_value.value, &p_clcb->uuid.uu, p_clcb->uuid.len);
117 st = attp_send_cl_msg(p_clcb->p_tcb, p_clcb->clcb_idx, op_code, &cl_req);
119 if (st != GATT_SUCCESS && st != GATT_CMD_STARTED)
121 gatt_end_operation(p_clcb, GATT_ERROR, NULL);
124 else /* end of handle range */
125 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
128 /*******************************************************************************
130 ** Function gatt_act_read
132 ** Description GATT read operation.
136 *******************************************************************************/
137 void gatt_act_read (tGATT_CLCB *p_clcb, UINT16 offset)
139 tGATT_TCB *p_tcb = p_clcb->p_tcb;
140 UINT8 rt = GATT_INTERNAL_ERROR;
144 memset (&msg, 0, sizeof(tGATT_CL_MSG));
146 switch (p_clcb->op_subtype)
148 case GATT_READ_CHAR_VALUE:
149 case GATT_READ_BY_TYPE:
150 op_code = GATT_REQ_READ_BY_TYPE;
151 msg.browse.s_handle = p_clcb->s_handle;
152 msg.browse.e_handle = p_clcb->e_handle;
153 if (p_clcb->op_subtype == GATT_READ_BY_TYPE)
154 memcpy(&msg.browse.uuid, &p_clcb->uuid, sizeof(tBT_UUID));
157 msg.browse.uuid.len = LEN_UUID_16;
158 msg.browse.uuid.uu.uuid16 = GATT_UUID_CHAR_DECLARE;
162 case GATT_READ_CHAR_VALUE_HDL:
163 case GATT_READ_BY_HANDLE:
164 if (!p_clcb->counter)
166 op_code = GATT_REQ_READ;
167 msg.handle = p_clcb->s_handle;
171 if (!p_clcb->first_read_blob_after_read)
172 p_clcb->first_read_blob_after_read = TRUE;
174 p_clcb->first_read_blob_after_read = FALSE;
176 GATT_TRACE_DEBUG("gatt_act_read first_read_blob_after_read=%d",
177 p_clcb->first_read_blob_after_read);
178 op_code = GATT_REQ_READ_BLOB;
179 msg.read_blob.offset = offset;
180 msg.read_blob.handle = p_clcb->s_handle;
182 p_clcb->op_subtype &= ~ 0x80;
185 case GATT_READ_PARTIAL:
186 op_code = GATT_REQ_READ_BLOB;
187 msg.read_blob.handle = p_clcb->s_handle;
188 msg.read_blob.offset = offset;
191 case GATT_READ_MULTIPLE:
192 op_code = GATT_REQ_READ_MULTI;
193 memcpy (&msg.read_multi, p_clcb->p_attr_buf, sizeof(tGATT_READ_MULTI));
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;
203 GATT_TRACE_ERROR("Unknown read type: %d", p_clcb->op_subtype);
208 rt = attp_send_cl_msg(p_tcb, p_clcb->clcb_idx, op_code, &msg);
210 if ( op_code == 0 || (rt != GATT_SUCCESS && rt != GATT_CMD_STARTED))
212 gatt_end_operation(p_clcb, rt, NULL);
216 /*******************************************************************************
218 ** Function gatt_act_write
220 ** Description GATT write operation.
224 *******************************************************************************/
225 void gatt_act_write (tGATT_CLCB *p_clcb, UINT8 sec_act)
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;
233 switch (p_clcb->op_subtype)
235 case GATT_WRITE_NO_RSP:
236 p_clcb->s_handle = p_attr->handle;
237 op_code = (sec_act == GATT_SEC_SIGN_DATA) ? GATT_SIGN_CMD_WRITE : GATT_CMD_WRITE;
238 rt = gatt_send_write_msg(p_tcb,
248 if (p_attr->len <= (p_tcb->payload_size - GATT_HDR_SIZE))
250 p_clcb->s_handle = p_attr->handle;
252 rt = gatt_send_write_msg(p_tcb,
260 else /* prepare write for long attribute */
262 gatt_send_prepare_write(p_tcb, p_clcb);
266 case GATT_WRITE_PREPARE:
267 gatt_send_prepare_write(p_tcb, p_clcb);
271 rt = GATT_INTERNAL_ERROR;
272 GATT_TRACE_ERROR("Unknown write type: %d", p_clcb->op_subtype);
277 rt = GATT_INTERNAL_ERROR;
279 if ((rt != GATT_SUCCESS && rt != GATT_CMD_STARTED && rt != GATT_CONGESTED)
280 || (rt != GATT_CMD_STARTED && p_clcb->op_subtype == GATT_WRITE_NO_RSP))
282 if (rt != GATT_SUCCESS)
284 GATT_TRACE_ERROR("gatt_act_write() failed op_code=0x%x rt=%d", op_code, rt);
286 gatt_end_operation(p_clcb, rt, NULL);
289 /*******************************************************************************
291 ** Function gatt_send_queue_write_cancel
293 ** Description send queue write cancel
297 *******************************************************************************/
298 void gatt_send_queue_write_cancel (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, tGATT_EXEC_FLAG flag)
302 GATT_TRACE_DEBUG("gatt_send_queue_write_cancel ");
304 rt = attp_send_cl_msg(p_tcb, p_clcb->clcb_idx, GATT_REQ_EXEC_WRITE, (tGATT_CL_MSG *)&flag);
306 if (rt != GATT_SUCCESS)
308 gatt_end_operation(p_clcb, rt, NULL);
311 /*******************************************************************************
313 ** Function gatt_check_write_long_terminate
315 ** Description To terminate write long or not.
317 ** Returns TRUE: write long is terminated; FALSE keep sending.
319 *******************************************************************************/
320 BOOLEAN gatt_check_write_long_terminate(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, tGATT_VALUE *p_rsp_value)
322 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
323 BOOLEAN exec = FALSE;
324 tGATT_EXEC_FLAG flag = GATT_PREP_WRITE_EXEC;
326 GATT_TRACE_DEBUG("gatt_check_write_long_terminate ");
327 /* check the first write response status */
328 if (p_rsp_value != NULL)
330 if (p_rsp_value->handle != p_attr->handle ||
331 p_rsp_value->len != p_clcb->counter ||
332 memcmp(p_rsp_value->value, p_attr->value + p_attr->offset, p_rsp_value->len))
334 /* data does not match */
335 p_clcb->status = GATT_ERROR;
336 flag = GATT_PREP_WRITE_CANCEL;
339 else /* response checking is good */
341 p_clcb->status = GATT_SUCCESS;
342 /* update write offset and check if end of attribute value */
343 if ((p_attr->offset += p_rsp_value->len) >= p_attr->len)
349 gatt_send_queue_write_cancel (p_tcb, p_clcb, flag);
354 /*******************************************************************************
356 ** Function gatt_send_prepare_write
358 ** Description Send prepare write.
362 *******************************************************************************/
363 void gatt_send_prepare_write(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb)
365 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
366 UINT16 to_send, offset;
367 UINT8 rt = GATT_SUCCESS;
368 UINT8 type = p_clcb->op_subtype;
370 GATT_TRACE_DEBUG("gatt_send_prepare_write type=0x%x", type );
371 to_send = p_attr->len - p_attr->offset;
373 if (to_send > (p_tcb->payload_size - GATT_WRITE_LONG_HDR_SIZE)) /* 2 = UINT16 offset bytes */
374 to_send = p_tcb->payload_size - GATT_WRITE_LONG_HDR_SIZE;
376 p_clcb->s_handle = p_attr->handle;
378 offset = p_attr->offset;
379 if (type == GATT_WRITE_PREPARE)
381 offset += p_clcb->start_offset;
384 GATT_TRACE_DEBUG("offset =0x%x len=%d", offset, to_send );
386 rt = gatt_send_write_msg(p_tcb,
388 GATT_REQ_PREPARE_WRITE,
390 to_send, /* length */
391 offset, /* used as offset */
392 p_attr->value + p_attr->offset); /* data */
394 /* remember the write long attribute length */
395 p_clcb->counter = to_send;
397 if (rt != GATT_SUCCESS && rt != GATT_CMD_STARTED)
399 gatt_end_operation(p_clcb, rt, NULL);
404 /*******************************************************************************
406 ** Function gatt_process_find_type_value_rsp
408 ** Description This function is called to handle find by type value response.
413 *******************************************************************************/
414 void gatt_process_find_type_value_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
416 tGATT_DISC_RES result;
421 GATT_TRACE_DEBUG("gatt_process_find_type_value_rsp ");
422 /* unexpected response */
423 if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_SRVC_BY_UUID)
426 memset (&result, 0, sizeof(tGATT_DISC_RES));
428 result.type.uu.uuid16 = GATT_UUID_PRI_SERVICE;
430 /* returns a series of handle ranges */
433 STREAM_TO_UINT16 (result.handle, p);
434 STREAM_TO_UINT16 (result.value.group_value.e_handle, p);
435 memcpy (&result.value.group_value.service_type, &p_clcb->uuid, sizeof(tBT_UUID));
439 if (p_clcb->p_reg->app_cb.p_disc_res_cb)
440 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
443 /* last handle + 1 */
444 p_clcb->s_handle = (result.value.group_value.e_handle == 0) ? 0 : (result.value.group_value.e_handle + 1);
445 /* initiate another request */
446 gatt_act_discovery(p_clcb) ;
448 /*******************************************************************************
450 ** Function gatt_process_read_info_rsp
452 ** Description This function is called to handle the read information
458 *******************************************************************************/
459 void gatt_process_read_info_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
460 UINT16 len, UINT8 *p_data)
462 tGATT_DISC_RES result;
463 UINT8 *p = p_data, uuid_len = 0, type;
468 if (len < GATT_INFO_RSP_MIN_LEN)
470 GATT_TRACE_ERROR("invalid Info Response PDU received, discard.");
471 gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
474 /* unexpected response */
475 if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_CHAR_DSCPT)
478 STREAM_TO_UINT8(type, p);
481 if (type == GATT_INFO_TYPE_PAIR_16)
482 uuid_len = LEN_UUID_16;
483 else if (type == GATT_INFO_TYPE_PAIR_128)
484 uuid_len = LEN_UUID_128;
486 while (len >= uuid_len + 2)
488 STREAM_TO_UINT16 (result.handle, p);
492 if (!gatt_parse_uuid_from_cmd(&result.type, uuid_len, &p))
496 memcpy (&result.type, &p_clcb->uuid, sizeof(tBT_UUID));
498 len -= (uuid_len + 2);
500 if (p_clcb->p_reg->app_cb.p_disc_res_cb)
501 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
504 p_clcb->s_handle = (result.handle == 0) ? 0 :(result.handle + 1);
505 /* initiate another request */
506 gatt_act_discovery(p_clcb) ;
508 /*******************************************************************************
510 ** Function gatt_proc_disc_error_rsp
512 ** Description This function process the read by type response and send another
513 ** request if needed.
517 *******************************************************************************/
518 void gatt_proc_disc_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 opcode,
519 UINT16 handle, UINT8 reason)
521 tGATT_STATUS status = (tGATT_STATUS) reason;
526 GATT_TRACE_DEBUG("gatt_proc_disc_error_rsp reason: %02x cmd_code %04x", reason, opcode);
530 case GATT_REQ_READ_BY_GRP_TYPE:
531 case GATT_REQ_FIND_TYPE_VALUE:
532 case GATT_REQ_READ_BY_TYPE:
533 case GATT_REQ_FIND_INFO:
534 if (reason == GATT_NOT_FOUND)
536 status = GATT_SUCCESS;
537 GATT_TRACE_DEBUG("Discovery completed");
541 GATT_TRACE_ERROR("Incorrect discovery opcode %04x", opcode);
545 gatt_end_operation(p_clcb, status, NULL);
548 /*******************************************************************************
550 ** Function gatt_process_error_rsp
552 ** Description This function is called to handle the error response
557 *******************************************************************************/
558 void gatt_process_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
559 UINT16 len, UINT8 *p_data)
561 UINT8 opcode, reason, * p= p_data;
563 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
568 GATT_TRACE_DEBUG("gatt_process_error_rsp ");
569 STREAM_TO_UINT8(opcode, p);
570 STREAM_TO_UINT16(handle, p);
571 STREAM_TO_UINT8(reason, p);
573 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)
575 gatt_proc_disc_error_rsp(p_tcb, p_clcb, opcode, handle, reason);
579 if ( (p_clcb->operation == GATTC_OPTYPE_WRITE) &&
580 (p_clcb->op_subtype == GATT_WRITE) &&
581 (opcode == GATT_REQ_PREPARE_WRITE) &&
583 (handle == p_attr->handle) )
585 p_clcb->status = reason;
586 gatt_send_queue_write_cancel(p_tcb, p_clcb, GATT_PREP_WRITE_CANCEL);
588 else if ((p_clcb->operation == GATTC_OPTYPE_READ) &&
589 ((p_clcb->op_subtype == GATT_READ_CHAR_VALUE_HDL) ||
590 (p_clcb->op_subtype == GATT_READ_BY_HANDLE)) &&
591 (opcode == GATT_REQ_READ_BLOB) &&
592 p_clcb->first_read_blob_after_read &&
593 (reason == GATT_NOT_LONG))
595 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf);
598 gatt_end_operation(p_clcb, reason, NULL);
601 /*******************************************************************************
603 ** Function gatt_process_prep_write_rsp
605 ** Description This function is called to handle the read response
610 *******************************************************************************/
611 void gatt_process_prep_write_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
612 UINT16 len, UINT8 *p_data)
616 tGATT_VALUE value = {
617 .conn_id = p_clcb->conn_id,
618 .auth_req = GATT_AUTH_REQ_NONE,
621 GATT_TRACE_ERROR("value resp op_code = %s len = %d", gatt_dbg_op_name(op_code), len);
623 if (len < GATT_PREP_WRITE_RSP_MIN_LEN)
625 GATT_TRACE_ERROR("illegal prepare write response length, discard");
626 gatt_end_operation(p_clcb, GATT_INVALID_PDU, &value);
630 STREAM_TO_UINT16 (value.handle, p);
631 STREAM_TO_UINT16 (value.offset, p);
635 memcpy (value.value, p, value.len);
637 if (p_clcb->op_subtype == GATT_WRITE_PREPARE)
639 p_clcb->status = GATT_SUCCESS;
640 /* application should verify handle offset
641 and value are matched or not */
643 gatt_end_operation(p_clcb, p_clcb->status, &value);
645 else if (p_clcb->op_subtype == GATT_WRITE )
647 if (!gatt_check_write_long_terminate(p_tcb, p_clcb, &value))
648 gatt_send_prepare_write(p_tcb, p_clcb);
652 /*******************************************************************************
654 ** Function gatt_process_notification
656 ** Description This function is called to handle the handle value indication
657 ** or handle value notification.
662 *******************************************************************************/
663 void gatt_process_notification(tGATT_TCB *p_tcb, UINT8 op_code,
664 UINT16 len, UINT8 *p_data)
669 tGATT_STATUS encrypt_status;
671 event = (op_code == GATT_HANDLE_VALUE_NOTIF) ? GATTC_OPTYPE_NOTIFICATION : GATTC_OPTYPE_INDICATION;
673 GATT_TRACE_DEBUG("gatt_process_notification ");
675 if (len < GATT_NOTIFICATION_MIN_LEN)
677 GATT_TRACE_ERROR("illegal notification PDU length, discard");
681 memset(&value, 0, sizeof(value));
682 STREAM_TO_UINT16(value.handle, p);
684 memcpy (value.value, p, value.len);
686 if (!GATT_HANDLE_IS_VALID(value.handle))
688 /* illegal handle, send ack now */
689 if (op_code == GATT_HANDLE_VALUE_IND)
690 attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
694 if (event == GATTC_OPTYPE_INDICATION)
696 if (p_tcb->ind_count)
698 /* this is an error case that receiving an indication but we
699 still has an indication not being acked yet.
700 For now, just log the error reset the counter.
701 Later we need to disconnect the link unconditionally.
703 GATT_TRACE_ERROR("gatt_process_notification rcv Ind. but ind_count=%d (will reset ind_count)", p_tcb->ind_count);
705 p_tcb->ind_count = 0;
708 /* should notify all registered client with the handle value notificaion/indication
709 Note: need to do the indication count and start timer first then do callback
712 for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++)
714 if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb && (event == GATTC_OPTYPE_INDICATION))
718 if (event == GATTC_OPTYPE_INDICATION)
720 /* start a timer for app confirmation */
721 if (p_tcb->ind_count > 0)
722 gatt_start_ind_ack_timer(p_tcb);
723 else /* no app to indicate, or invalid handle */
724 attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
727 encrypt_status = gatt_get_link_encrypt_status(p_tcb);
728 for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++)
730 if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb)
732 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
733 (*p_reg->app_cb.p_cmpl_cb) (conn_id, event, encrypt_status, (tGATT_CL_COMPLETE *)&value);
739 /*******************************************************************************
741 ** Function gatt_process_read_by_type_rsp
743 ** Description This function is called to handle the read by type response.
744 ** read by type can be used for discovery, or read by type or
745 ** read characteristic value.
749 *******************************************************************************/
750 void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
751 UINT16 len, UINT8 *p_data)
753 tGATT_DISC_RES result;
754 tGATT_DISC_VALUE record_value;
755 UINT8 *p = p_data, value_len, handle_len = 2;
758 /* discovery procedure and no callback function registered */
759 if (((!p_clcb->p_reg) || (!p_clcb->p_reg->app_cb.p_disc_res_cb)) && (p_clcb->operation == GATTC_OPTYPE_DISCOVERY))
762 if (len < GATT_READ_BY_TYPE_RSP_MIN_LEN)
764 GATT_TRACE_ERROR("Illegal ReadByType/ReadByGroupType Response length, discard");
765 gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
769 STREAM_TO_UINT8(value_len, p);
771 if ((value_len > (p_tcb->payload_size - 2)) || (value_len > (len-1)) )
773 /* this is an error case that server's response containing a value length which is larger than MTU-2
774 or value_len > message total length -1 */
775 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)",
776 op_code, value_len, (p_tcb->payload_size - 2), (len-1));
777 gatt_end_operation(p_clcb, GATT_ERROR, NULL);
781 if (op_code == GATT_RSP_READ_BY_GRP_TYPE)
784 value_len -= handle_len; /* substract the handle pairs bytes */
787 while (len >= (handle_len + value_len))
789 STREAM_TO_UINT16(handle, p);
791 if (!GATT_HANDLE_IS_VALID(handle))
793 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
797 memset(&result, 0, sizeof(tGATT_DISC_RES));
798 memset(&record_value, 0, sizeof(tGATT_DISC_VALUE));
800 result.handle = handle;
802 result.type.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype];
804 /* discover all services */
805 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
806 p_clcb->op_subtype == GATT_DISC_SRVC_ALL &&
807 op_code == GATT_RSP_READ_BY_GRP_TYPE)
809 STREAM_TO_UINT16(handle, p);
811 if (!GATT_HANDLE_IS_VALID(handle))
813 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
818 record_value.group_value.e_handle = handle;
819 if (!gatt_parse_uuid_from_cmd(&record_value.group_value.service_type, value_len, &p))
821 GATT_TRACE_ERROR("discover all service response parsing failure");
826 /* discover included service */
827 else if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->op_subtype == GATT_DISC_INC_SRVC)
829 STREAM_TO_UINT16(record_value.incl_service.s_handle, p);
830 STREAM_TO_UINT16(record_value.incl_service.e_handle, p);
832 if (!GATT_HANDLE_IS_VALID(record_value.incl_service.s_handle) ||
833 !GATT_HANDLE_IS_VALID(record_value.incl_service.e_handle))
835 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
841 STREAM_TO_UINT16(record_value.incl_service.service_type.uu.uuid16, p);
842 record_value.incl_service.service_type.len = LEN_UUID_16;
844 else if (value_len == 4)
846 p_clcb->s_handle = record_value.incl_service.s_handle;
847 p_clcb->read_uuid128.wait_for_read_rsp = TRUE;
848 p_clcb->read_uuid128.next_disc_start_hdl = handle + 1;
849 memcpy(&p_clcb->read_uuid128.result, &result, sizeof(result));
850 memcpy(&p_clcb->read_uuid128.result.value, &record_value, sizeof (result.value));
851 p_clcb->op_subtype |= 0x90;
852 gatt_act_read(p_clcb, 0);
857 GATT_TRACE_ERROR("gatt_process_read_by_type_rsp INCL_SRVC failed with invalid data value_len=%d", value_len);
858 gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p);
863 else if (p_clcb->operation == GATTC_OPTYPE_READ && p_clcb->op_subtype == GATT_READ_BY_TYPE)
865 p_clcb->counter = len - 2;
866 p_clcb->s_handle = handle;
867 if ( p_clcb->counter == (p_clcb->p_tcb->payload_size -4))
869 p_clcb->op_subtype = GATT_READ_BY_HANDLE;
870 if (!p_clcb->p_attr_buf)
871 p_clcb->p_attr_buf = (UINT8 *)osi_malloc(GATT_MAX_ATTR_LEN);
872 if (p_clcb->counter <= GATT_MAX_ATTR_LEN) {
873 memcpy(p_clcb->p_attr_buf, p, p_clcb->counter);
874 gatt_act_read(p_clcb, p_clcb->counter);
876 gatt_end_operation(p_clcb, GATT_INTERNAL_ERROR, (void *)p);
881 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p);
885 else /* discover characterisitic */
887 STREAM_TO_UINT8 (record_value.dclr_value.char_prop, p);
888 STREAM_TO_UINT16(record_value.dclr_value.val_handle, p);
889 if (!GATT_HANDLE_IS_VALID(record_value.dclr_value.val_handle))
891 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
894 if (!gatt_parse_uuid_from_cmd(&record_value.dclr_value.char_uuid, (UINT16)(value_len - 3), &p))
896 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
897 /* invalid format, and skip the result */
901 /* UUID not matching */
902 if (!gatt_uuid_compare(record_value.dclr_value.char_uuid, p_clcb->uuid))
904 len -= (value_len + 2);
905 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 */
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);
918 len -= (value_len + handle_len);
920 /* result is (handle, 16bits UUID) pairs */
921 memcpy (&result.value, &record_value, sizeof (result.value));
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);
928 p_clcb->s_handle = (handle == 0) ? 0 : (handle + 1);
930 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)
932 /* initiate another request */
933 gatt_act_discovery(p_clcb) ;
935 else /* read characteristic value */
937 gatt_act_read(p_clcb, 0);
941 /*******************************************************************************
943 ** Function gatt_process_read_rsp
945 ** Description This function is called to handle the read BLOB response
950 *******************************************************************************/
951 void gatt_process_read_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
952 UINT16 len, UINT8 *p_data)
954 UINT16 offset = p_clcb->counter;
959 if (p_clcb->operation == GATTC_OPTYPE_READ)
961 if (p_clcb->op_subtype != GATT_READ_BY_HANDLE)
963 p_clcb->counter = len;
964 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p);
969 /* allocate GKI buffer holding up long attribute value */
970 if (!p_clcb->p_attr_buf)
971 p_clcb->p_attr_buf = (UINT8 *)osi_malloc(GATT_MAX_ATTR_LEN);
973 /* copy attrobute value into cb buffer */
974 if (offset < GATT_MAX_ATTR_LEN) {
975 if ((len + offset) > GATT_MAX_ATTR_LEN)
976 len = GATT_MAX_ATTR_LEN - offset;
978 p_clcb->counter += len;
980 memcpy(p_clcb->p_attr_buf + offset, p, len);
982 /* send next request if needed */
984 if (len == (p_tcb->payload_size - 1) && /* full packet for read or read blob rsp */
985 len + offset < GATT_MAX_ATTR_LEN)
987 GATT_TRACE_DEBUG("full pkt issue read blob for remianing bytes old offset=%d len=%d new offset=%d",
988 offset, len, p_clcb->counter);
989 gatt_act_read(p_clcb, p_clcb->counter);
991 else /* end of request, send callback */
993 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf);
996 else /* exception, should not happen */
998 GATT_TRACE_ERROR("attr offset = %d p_attr_buf = %d ", offset, p_clcb->p_attr_buf);
999 gatt_end_operation(p_clcb, GATT_NO_RESOURCES, (void *)p_clcb->p_attr_buf);
1005 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
1006 p_clcb->op_subtype == GATT_DISC_INC_SRVC &&
1007 p_clcb->read_uuid128.wait_for_read_rsp )
1009 p_clcb->s_handle = p_clcb->read_uuid128.next_disc_start_hdl;
1010 p_clcb->read_uuid128.wait_for_read_rsp = FALSE;
1011 if (len == LEN_UUID_128)
1014 memcpy(p_clcb->read_uuid128.result.value.incl_service.service_type.uu.uuid128, p, len);
1015 p_clcb->read_uuid128.result.value.incl_service.service_type.len = LEN_UUID_128;
1016 if ( p_clcb->p_reg->app_cb.p_disc_res_cb)
1017 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &p_clcb->read_uuid128.result);
1018 gatt_act_discovery(p_clcb) ;
1022 gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p);
1030 /*******************************************************************************
1032 ** Function gatt_process_handle_rsp
1034 ** Description This function is called to handle the write response
1039 *******************************************************************************/
1040 void gatt_process_handle_rsp(tGATT_CLCB *p_clcb)
1042 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
1044 /*******************************************************************************
1046 ** Function gatt_process_mtu_rsp
1048 ** Description This function is called to process the configure MTU response.
1053 *******************************************************************************/
1054 void gatt_process_mtu_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
1057 tGATT_STATUS status = GATT_SUCCESS;
1059 if (len < GATT_MTU_RSP_MIN_LEN)
1061 GATT_TRACE_ERROR("invalid MTU response PDU received, discard.");
1062 status = GATT_INVALID_PDU;
1066 STREAM_TO_UINT16(mtu, p_data);
1068 if (mtu < p_tcb->payload_size && mtu >= GATT_DEF_BLE_MTU_SIZE)
1069 p_tcb->payload_size = mtu;
1072 l2cble_set_fixed_channel_tx_data_length(p_tcb->peer_bda, L2CAP_ATT_CID, p_tcb->payload_size);
1073 gatt_end_operation(p_clcb, status, NULL);
1075 /*******************************************************************************
1077 ** Function gatt_cmd_to_rsp_code
1079 ** Description The function convert a ATT command op code into the corresponding
1080 ** response code assume no error occurs.
1082 ** Returns response code.
1084 *******************************************************************************/
1085 UINT8 gatt_cmd_to_rsp_code (UINT8 cmd_code)
1089 if (cmd_code > 1 && cmd_code != GATT_CMD_WRITE)
1091 rsp_code = cmd_code + 1;
1095 /*******************************************************************************
1097 ** Function gatt_cl_send_next_cmd_inq
1099 ** Description Find next command in queue and sent to server
1101 ** Returns TRUE if command sent, otherwise FALSE.
1103 *******************************************************************************/
1104 BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb)
1106 tGATT_CMD_Q *p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1107 BOOLEAN sent = FALSE;
1109 tGATT_CLCB *p_clcb = NULL;
1110 tGATT_STATUS att_ret = GATT_SUCCESS;
1113 p_tcb->pending_cl_req != p_tcb->next_slot_inq &&
1114 p_cmd->to_send && p_cmd->p_cmd != NULL)
1116 att_ret = attp_send_msg_to_l2cap(p_tcb, p_cmd->p_cmd);
1118 if (att_ret == GATT_SUCCESS || att_ret == GATT_CONGESTED)
1121 p_cmd->to_send = FALSE;
1122 p_cmd->p_cmd = NULL;
1124 /* dequeue the request if is write command or sign write */
1125 if (p_cmd->op_code != GATT_CMD_WRITE && p_cmd->op_code != GATT_SIGN_CMD_WRITE)
1127 gatt_start_rsp_timer (p_cmd->clcb_idx);
1131 p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
1133 /* if no ack needed, keep sending */
1134 if (att_ret == GATT_SUCCESS)
1137 p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1138 /* send command complete callback here */
1139 gatt_end_operation(p_clcb, att_ret, NULL);
1144 GATT_TRACE_ERROR("gatt_cl_send_next_cmd_inq: L2CAP sent error");
1146 memset(p_cmd, 0, sizeof(tGATT_CMD_Q));
1147 p_tcb->pending_cl_req ++;
1148 p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1155 /*******************************************************************************
1157 ** Function gatt_client_handle_server_rsp
1159 ** Description This function is called to handle the server response to
1165 *******************************************************************************/
1166 void gatt_client_handle_server_rsp (tGATT_TCB *p_tcb, UINT8 op_code,
1167 UINT16 len, UINT8 *p_data)
1169 tGATT_CLCB *p_clcb = NULL;
1172 if (op_code != GATT_HANDLE_VALUE_IND && op_code != GATT_HANDLE_VALUE_NOTIF)
1174 p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
1176 rsp_code = gatt_cmd_to_rsp_code(rsp_code);
1178 if (p_clcb == NULL || (rsp_code != op_code && op_code != GATT_RSP_ERROR))
1180 GATT_TRACE_WARNING ("ATT - Ignore wrong response. Receives (%02x) \
1181 Request(%02x) Ignored", op_code, rsp_code);
1187 alarm_cancel(p_clcb->gatt_rsp_timer_ent);
1188 p_clcb->retry_count = 0;
1191 /* the size of the message may not be bigger than the local max PDU size*/
1192 /* The message has to be smaller than the agreed MTU, len does not count op_code */
1193 if (len >= p_tcb->payload_size)
1195 GATT_TRACE_ERROR("invalid response/indicate pkt size: %d, PDU size: %d", len + 1, p_tcb->payload_size);
1196 if (op_code != GATT_HANDLE_VALUE_NOTIF &&
1197 op_code != GATT_HANDLE_VALUE_IND)
1198 gatt_end_operation(p_clcb, GATT_ERROR, NULL);
1204 case GATT_RSP_ERROR:
1205 gatt_process_error_rsp(p_tcb, p_clcb, op_code, len, p_data);
1208 case GATT_RSP_MTU: /* 2 bytes mtu */
1209 gatt_process_mtu_rsp(p_tcb, p_clcb, len ,p_data);
1212 case GATT_RSP_FIND_INFO:
1213 gatt_process_read_info_rsp(p_tcb, p_clcb, op_code, len, p_data);
1216 case GATT_RSP_READ_BY_TYPE:
1217 case GATT_RSP_READ_BY_GRP_TYPE:
1218 gatt_process_read_by_type_rsp(p_tcb, p_clcb, op_code, len, p_data);
1222 case GATT_RSP_READ_BLOB:
1223 case GATT_RSP_READ_MULTI:
1224 gatt_process_read_rsp(p_tcb, p_clcb, op_code, len, p_data);
1227 case GATT_RSP_FIND_TYPE_VALUE: /* disc service with UUID */
1228 gatt_process_find_type_value_rsp(p_tcb, p_clcb, len, p_data);
1231 case GATT_RSP_WRITE:
1232 gatt_process_handle_rsp(p_clcb);
1235 case GATT_RSP_PREPARE_WRITE:
1236 gatt_process_prep_write_rsp(p_tcb, p_clcb, op_code, len, p_data);
1239 case GATT_RSP_EXEC_WRITE:
1240 gatt_end_operation(p_clcb, p_clcb->status, NULL);
1243 case GATT_HANDLE_VALUE_NOTIF:
1244 case GATT_HANDLE_VALUE_IND:
1245 gatt_process_notification(p_tcb, op_code, len, p_data);
1249 GATT_TRACE_ERROR("Unknown opcode = %d", op_code);
1254 if (op_code != GATT_HANDLE_VALUE_IND && op_code != GATT_HANDLE_VALUE_NOTIF)
1256 gatt_cl_send_next_cmd_inq(p_tcb);
1262 #endif /* BLE_INCLUDED */