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