• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2008-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 GATT server functions
22  *
23  ******************************************************************************/
24 
25 #include "bt_target.h"
26 #include "bt_utils.h"
27 
28 #if BLE_INCLUDED == TRUE
29 #include <string.h>
30 #include "gatt_int.h"
31 #include "l2c_api.h"
32 #include "l2c_int.h"
33 #define GATT_MTU_REQ_MIN_LEN        2
34 
35 
36 /*******************************************************************************
37 **
38 ** Function         gatt_sr_enqueue_cmd
39 **
40 ** Description      This function enqueue the request from client which needs a
41 **                  application response, and update the transaction ID.
42 **
43 ** Returns          void
44 **
45 *******************************************************************************/
gatt_sr_enqueue_cmd(tGATT_TCB * p_tcb,UINT8 op_code,UINT16 handle)46 UINT32 gatt_sr_enqueue_cmd (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 handle)
47 {
48     tGATT_SR_CMD   *p_cmd = &p_tcb->sr_cmd;
49     UINT32          trans_id = 0;
50 
51     if ( (p_cmd->op_code == 0) ||
52          (op_code == GATT_HANDLE_VALUE_CONF)) /* no pending request */
53     {
54         if (op_code == GATT_CMD_WRITE ||
55             op_code == GATT_SIGN_CMD_WRITE  ||
56             op_code == GATT_REQ_MTU ||
57             op_code == GATT_HANDLE_VALUE_CONF)
58         {
59             trans_id = ++p_tcb->trans_id;
60         }
61         else
62         {
63             p_cmd->trans_id   = ++p_tcb->trans_id;
64             p_cmd->op_code    = op_code;
65             p_cmd->handle     = handle;
66             p_cmd->status     = GATT_NOT_FOUND;
67             p_tcb->trans_id %= GATT_TRANS_ID_MAX;
68             trans_id = p_cmd->trans_id;
69         }
70     }
71 
72     return trans_id;
73 }
74 
75 /*******************************************************************************
76 **
77 ** Function         gatt_sr_cmd_empty
78 **
79 ** Description      This function check the server command queue is empty or not.
80 **
81 ** Returns          TRUE if empty, FALSE if there is pending command.
82 **
83 *******************************************************************************/
gatt_sr_cmd_empty(tGATT_TCB * p_tcb)84 BOOLEAN gatt_sr_cmd_empty (tGATT_TCB *p_tcb)
85 {
86     return(p_tcb->sr_cmd.op_code == 0);
87 }
88 
89 /*******************************************************************************
90 **
91 ** Function         gatt_dequeue_sr_cmd
92 **
93 ** Description      This function dequeue the request from command queue.
94 **
95 ** Returns          void
96 **
97 *******************************************************************************/
gatt_dequeue_sr_cmd(tGATT_TCB * p_tcb)98 void gatt_dequeue_sr_cmd (tGATT_TCB *p_tcb)
99 {
100     /* Double check in case any buffers are queued */
101     GATT_TRACE_DEBUG("gatt_dequeue_sr_cmd" );
102     if (p_tcb->sr_cmd.p_rsp_msg)
103         GATT_TRACE_ERROR("free p_tcb->sr_cmd.p_rsp_msg = %d", p_tcb->sr_cmd.p_rsp_msg);
104     osi_free_and_reset((void **)&p_tcb->sr_cmd.p_rsp_msg);
105 
106     while (!fixed_queue_is_empty(p_tcb->sr_cmd.multi_rsp_q))
107         osi_free(fixed_queue_try_dequeue(p_tcb->sr_cmd.multi_rsp_q));
108     fixed_queue_free(p_tcb->sr_cmd.multi_rsp_q, NULL);
109     memset( &p_tcb->sr_cmd, 0, sizeof(tGATT_SR_CMD));
110 }
111 
112 /*******************************************************************************
113 **
114 ** Function         process_read_multi_rsp
115 **
116 ** Description      This function check the read multiple response.
117 **
118 ** Returns          BOOLEAN if all replies have been received
119 **
120 *******************************************************************************/
process_read_multi_rsp(tGATT_SR_CMD * p_cmd,tGATT_STATUS status,tGATTS_RSP * p_msg,UINT16 mtu)121 static BOOLEAN process_read_multi_rsp (tGATT_SR_CMD *p_cmd, tGATT_STATUS status,
122                                        tGATTS_RSP *p_msg, UINT16 mtu)
123 {
124     UINT16          ii, total_len, len;
125     UINT8           *p;
126     BOOLEAN         is_overflow = FALSE;
127 
128     GATT_TRACE_DEBUG ("%s status=%d mtu=%d", __func__, status, mtu);
129 
130     if (p_cmd->multi_rsp_q == NULL)
131         p_cmd->multi_rsp_q = fixed_queue_new(SIZE_MAX);
132 
133     /* Enqueue the response */
134     BT_HDR  *p_buf = (BT_HDR *)osi_malloc(sizeof(tGATTS_RSP));
135     memcpy((void *)p_buf, (const void *)p_msg, sizeof(tGATTS_RSP));
136     fixed_queue_enqueue(p_cmd->multi_rsp_q, p_buf);
137 
138     p_cmd->status = status;
139     if (status == GATT_SUCCESS)
140     {
141         GATT_TRACE_DEBUG("Multi read count=%d num_hdls=%d",
142                          fixed_queue_length(p_cmd->multi_rsp_q),
143                          p_cmd->multi_req.num_handles);
144         /* Wait till we get all the responses */
145         if (fixed_queue_length(p_cmd->multi_rsp_q) == p_cmd->multi_req.num_handles)
146         {
147             len = sizeof(BT_HDR) + L2CAP_MIN_OFFSET + mtu;
148             p_buf = (BT_HDR *)osi_calloc(len);
149             p_buf->offset = L2CAP_MIN_OFFSET;
150             p = (UINT8 *)(p_buf + 1) + p_buf->offset;
151 
152             /* First byte in the response is the opcode */
153             *p++ = GATT_RSP_READ_MULTI;
154             p_buf->len = 1;
155 
156             /* Now walk through the buffers puting the data into the response in order */
157             list_t *list = NULL;
158             const list_node_t *node = NULL;
159             if (! fixed_queue_is_empty(p_cmd->multi_rsp_q))
160                 list = fixed_queue_get_list(p_cmd->multi_rsp_q);
161             for (ii = 0; ii < p_cmd->multi_req.num_handles; ii++)
162             {
163                 tGATTS_RSP *p_rsp = NULL;
164 
165                 if (list != NULL) {
166                     if (ii == 0)
167                         node = list_begin(list);
168                     else
169                         node = list_next(node);
170                     if (node != list_end(list))
171                         p_rsp = (tGATTS_RSP *)list_node(node);
172                 }
173 
174                 if (p_rsp != NULL)
175                 {
176 
177                     total_len = (p_buf->len + p_rsp->attr_value.len);
178 
179                     if (total_len >  mtu)
180                     {
181                         /* just send the partial response for the overflow case */
182                         len = p_rsp->attr_value.len - (total_len - mtu);
183                         is_overflow = TRUE;
184                         GATT_TRACE_DEBUG ("multi read overflow available len=%d val_len=%d", len, p_rsp->attr_value.len );
185                     }
186                     else
187                     {
188                         len = p_rsp->attr_value.len;
189                     }
190 
191                     if (p_rsp->attr_value.handle == p_cmd->multi_req.handles[ii])
192                     {
193                         memcpy (p, p_rsp->attr_value.value, len);
194                         if (!is_overflow)
195                             p += len;
196                         p_buf->len += len;
197                     }
198                     else
199                     {
200                         p_cmd->status        = GATT_NOT_FOUND;
201                         break;
202                     }
203 
204                     if (is_overflow)
205                         break;
206 
207                 }
208                 else
209                 {
210                     p_cmd->status        = GATT_NOT_FOUND;
211                     break;
212                 }
213 
214             } /* loop through all handles*/
215 
216 
217             /* Sanity check on the buffer length */
218             if (p_buf->len == 0)
219             {
220                 GATT_TRACE_ERROR("process_read_multi_rsp - nothing found!!");
221                 p_cmd->status = GATT_NOT_FOUND;
222                 osi_free(p_buf);
223                 GATT_TRACE_DEBUG("osi_free(p_buf)");
224             }
225             else if (p_cmd->p_rsp_msg != NULL)
226             {
227                 osi_free(p_buf);
228             }
229             else
230             {
231                 p_cmd->p_rsp_msg = p_buf;
232             }
233 
234             return(TRUE);
235         }
236     }
237     else    /* any handle read exception occurs, return error */
238     {
239         return(TRUE);
240     }
241 
242     /* If here, still waiting */
243     return(FALSE);
244 }
245 
246 /*******************************************************************************
247 **
248 ** Function         gatt_sr_process_app_rsp
249 **
250 ** Description      This function checks whether the response message from application
251 **                  match any pending request or not.
252 **
253 ** Returns          void
254 **
255 *******************************************************************************/
gatt_sr_process_app_rsp(tGATT_TCB * p_tcb,tGATT_IF gatt_if,UINT32 trans_id,UINT8 op_code,tGATT_STATUS status,tGATTS_RSP * p_msg)256 tGATT_STATUS gatt_sr_process_app_rsp (tGATT_TCB *p_tcb, tGATT_IF gatt_if,
257                                       UINT32 trans_id, UINT8 op_code,
258                                       tGATT_STATUS status, tGATTS_RSP *p_msg)
259 {
260     tGATT_STATUS    ret_code = GATT_SUCCESS;
261     UNUSED(trans_id);
262 
263     GATT_TRACE_DEBUG("gatt_sr_process_app_rsp gatt_if=%d", gatt_if);
264 
265     gatt_sr_update_cback_cnt(p_tcb, gatt_if, FALSE, FALSE);
266 
267     if (op_code == GATT_REQ_READ_MULTI)
268     {
269         /* If no error and still waiting, just return */
270         if (!process_read_multi_rsp (&p_tcb->sr_cmd, status, p_msg, p_tcb->payload_size))
271             return(GATT_SUCCESS);
272     }
273     else
274     {
275         if (op_code == GATT_REQ_PREPARE_WRITE && status == GATT_SUCCESS)
276             gatt_sr_update_prep_cnt(p_tcb, gatt_if, TRUE, FALSE);
277 
278         if (op_code == GATT_REQ_EXEC_WRITE && status != GATT_SUCCESS)
279             gatt_sr_reset_cback_cnt(p_tcb);
280 
281         p_tcb->sr_cmd.status = status;
282 
283         if (gatt_sr_is_cback_cnt_zero(p_tcb)
284             && status == GATT_SUCCESS)
285         {
286             if (p_tcb->sr_cmd.p_rsp_msg == NULL)
287             {
288                 p_tcb->sr_cmd.p_rsp_msg = attp_build_sr_msg (p_tcb, (UINT8)(op_code + 1), (tGATT_SR_MSG *)p_msg);
289             }
290             else
291             {
292                 GATT_TRACE_ERROR("Exception!!! already has respond message");
293             }
294         }
295     }
296     if (gatt_sr_is_cback_cnt_zero(p_tcb))
297     {
298         if ( (p_tcb->sr_cmd.status == GATT_SUCCESS) && (p_tcb->sr_cmd.p_rsp_msg) )
299         {
300             ret_code = attp_send_sr_msg (p_tcb, p_tcb->sr_cmd.p_rsp_msg);
301             p_tcb->sr_cmd.p_rsp_msg = NULL;
302         }
303         else
304         {
305             ret_code = gatt_send_error_rsp (p_tcb, status, op_code, p_tcb->sr_cmd.handle, FALSE);
306         }
307 
308         gatt_dequeue_sr_cmd(p_tcb);
309     }
310 
311     GATT_TRACE_DEBUG("gatt_sr_process_app_rsp ret_code=%d", ret_code);
312 
313     return ret_code;
314 }
315 
316 /*******************************************************************************
317 **
318 ** Function         gatt_process_exec_write_req
319 **
320 ** Description      This function is called to process the execute write request
321 **                  from client.
322 **
323 ** Returns          void
324 **
325 *******************************************************************************/
gatt_process_exec_write_req(tGATT_TCB * p_tcb,UINT8 op_code,UINT16 len,UINT8 * p_data)326 void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data)
327 {
328     UINT8   *p = p_data, flag, i = 0;
329     UINT32  trans_id = 0;
330     tGATT_IF gatt_if;
331     UINT16  conn_id;
332 
333     UNUSED(len);
334 
335 #if GATT_CONFORMANCE_TESTING == TRUE
336     if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
337     {
338         GATT_TRACE_DEBUG("Conformance tst: forced err rspv for Execute Write: error status=%d",
339         gatt_cb.err_status);
340 
341         gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, gatt_cb.handle, FALSE);
342 
343         return;
344     }
345 #endif
346 
347     STREAM_TO_UINT8(flag, p);
348 
349     /* mask the flag */
350     flag &= GATT_PREP_WRITE_EXEC;
351 
352 
353     /* no prep write is queued */
354     if (!gatt_sr_is_prep_cnt_zero(p_tcb))
355     {
356         trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, 0);
357         gatt_sr_copy_prep_cnt_to_cback_cnt(p_tcb);
358 
359         for (i=0; i<GATT_MAX_APPS; i++)
360         {
361             if (p_tcb->prep_cnt[i])
362             {
363                 gatt_if = (tGATT_IF) (i+1);
364                 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
365                 gatt_sr_send_req_callback(conn_id,
366                                           trans_id,
367                                           GATTS_REQ_TYPE_WRITE_EXEC,
368                                           (tGATTS_DATA *)&flag);
369                 p_tcb->prep_cnt[i]= 0;
370             }
371         }
372     }
373     else /* nothing needs to be executed , send response now */
374     {
375         GATT_TRACE_ERROR("gatt_process_exec_write_req: no prepare write pending");
376         gatt_send_error_rsp(p_tcb, GATT_ERROR, GATT_REQ_EXEC_WRITE, 0, FALSE);
377     }
378 }
379 
380 /*******************************************************************************
381 **
382 ** Function         gatt_process_read_multi_req
383 **
384 ** Description      This function is called to process the read multiple request
385 **                  from client.
386 **
387 ** Returns          void
388 **
389 *******************************************************************************/
gatt_process_read_multi_req(tGATT_TCB * p_tcb,UINT8 op_code,UINT16 len,UINT8 * p_data)390 void gatt_process_read_multi_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data)
391 {
392     UINT32          trans_id;
393     UINT16          handle = 0, ll = len;
394     UINT8           *p = p_data, i_rcb;
395     tGATT_STATUS    err = GATT_SUCCESS;
396     UINT8           sec_flag, key_size;
397 
398     GATT_TRACE_DEBUG("gatt_process_read_multi_req" );
399     p_tcb->sr_cmd.multi_req.num_handles = 0;
400 
401     gatt_sr_get_sec_info(p_tcb->peer_bda,
402                          p_tcb->transport,
403                          &sec_flag,
404                          &key_size);
405 
406 #if GATT_CONFORMANCE_TESTING == TRUE
407     if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
408     {
409         GATT_TRACE_DEBUG("Conformance tst: forced err rspvofr ReadMultiple: error status=%d", gatt_cb.err_status);
410 
411         STREAM_TO_UINT16(handle, p);
412 
413         gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, handle, FALSE);
414 
415         return;
416     }
417 #endif
418 
419     while (ll >= 2 && p_tcb->sr_cmd.multi_req.num_handles < GATT_MAX_READ_MULTI_HANDLES)
420     {
421         STREAM_TO_UINT16(handle, p);
422 
423         if ((i_rcb = gatt_sr_find_i_rcb_by_handle(handle)) < GATT_MAX_SR_PROFILES)
424         {
425             p_tcb->sr_cmd.multi_req.handles[p_tcb->sr_cmd.multi_req.num_handles++] = handle;
426 
427             /* check read permission */
428             if ((err = gatts_read_attr_perm_check(   gatt_cb.sr_reg[i_rcb].p_db,
429                                                      FALSE,
430                                                      handle,
431                                                      sec_flag,
432                                                      key_size))
433                 != GATT_SUCCESS)
434             {
435                 GATT_TRACE_DEBUG("read permission denied : 0x%02x", err);
436                 break;
437             }
438         }
439         else
440         {
441             /* invalid handle */
442             err = GATT_INVALID_HANDLE;
443             break;
444         }
445         ll -= 2;
446     }
447 
448     if (ll != 0)
449     {
450         GATT_TRACE_ERROR("max attribute handle reached in ReadMultiple Request.");
451     }
452 
453     if (p_tcb->sr_cmd.multi_req.num_handles == 0)
454         err = GATT_INVALID_HANDLE;
455 
456     if (err == GATT_SUCCESS)
457     {
458         if ((trans_id = gatt_sr_enqueue_cmd (p_tcb, op_code, p_tcb->sr_cmd.multi_req.handles[0])) != 0)
459         {
460             gatt_sr_reset_cback_cnt(p_tcb); /* read multiple use multi_rsp_q's count*/
461 
462             for (ll = 0; ll < p_tcb->sr_cmd.multi_req.num_handles; ll ++) {
463                 tGATTS_RSP *p_msg = (tGATTS_RSP *)osi_calloc(sizeof(tGATTS_RSP));
464                 handle = p_tcb->sr_cmd.multi_req.handles[ll];
465                 i_rcb = gatt_sr_find_i_rcb_by_handle(handle);
466 
467                 p_msg->attr_value.handle = handle;
468                 err = gatts_read_attr_value_by_handle(p_tcb,
469                                                       gatt_cb.sr_reg[i_rcb].p_db,
470                                                       op_code,
471                                                       handle,
472                                                       0,
473                                                       p_msg->attr_value.value,
474                                                       &p_msg->attr_value.len,
475                                                       GATT_MAX_ATTR_LEN,
476                                                       sec_flag,
477                                                       key_size,
478                                                       trans_id);
479 
480                 if (err == GATT_SUCCESS) {
481                     gatt_sr_process_app_rsp(p_tcb, gatt_cb.sr_reg[i_rcb].gatt_if ,trans_id, op_code, GATT_SUCCESS, p_msg);
482                 }
483                 /* either not using or done using the buffer, release it now */
484                 osi_free(p_msg);
485             }
486         }
487         else
488             err = GATT_NO_RESOURCES;
489     }
490 
491     /* in theroy BUSY is not possible(should already been checked), protected check */
492     if (err != GATT_SUCCESS && err != GATT_PENDING && err != GATT_BUSY)
493         gatt_send_error_rsp(p_tcb, err, op_code, handle, FALSE);
494 }
495 
496 /*******************************************************************************
497 **
498 ** Function         gatt_build_primary_service_rsp
499 **
500 ** Description      Primamry service request processed internally. Theretically
501 **                  only deal with ReadByTypeVAlue and ReadByGroupType.
502 **
503 ** Returns          void
504 **
505 *******************************************************************************/
gatt_build_primary_service_rsp(BT_HDR * p_msg,tGATT_TCB * p_tcb,UINT8 op_code,UINT16 s_hdl,UINT16 e_hdl,UINT8 * p_data,tBT_UUID value)506 static tGATT_STATUS gatt_build_primary_service_rsp (BT_HDR *p_msg, tGATT_TCB *p_tcb,
507                                                     UINT8 op_code, UINT16 s_hdl,
508                                                     UINT16 e_hdl, UINT8 *p_data, tBT_UUID value)
509 {
510     tGATT_STATUS    status = GATT_NOT_FOUND;
511     UINT8           handle_len =4, *p ;
512     tGATT_SR_REG    *p_rcb;
513     tGATT_SRV_LIST_INFO *p_list= &gatt_cb.srv_list_info;
514     tGATT_SRV_LIST_ELEM  *p_srv=NULL;
515     tBT_UUID       *p_uuid;
516 
517     UNUSED(p_data);
518 
519     p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
520 
521     p_srv = p_list->p_first;
522 
523     while (p_srv)
524     {
525         p_rcb = GATT_GET_SR_REG_PTR(p_srv->i_sreg);
526 
527         if (p_rcb->in_use &&
528             p_rcb->s_hdl >= s_hdl &&
529             p_rcb->s_hdl <= e_hdl &&
530             p_rcb->type == GATT_UUID_PRI_SERVICE)
531         {
532             if ((p_uuid = gatts_get_service_uuid (p_rcb->p_db)) != NULL)
533             {
534                 if (op_code == GATT_REQ_READ_BY_GRP_TYPE)
535                     handle_len = 4 + p_uuid->len;
536 
537                 /* get the length byte in the repsonse */
538                 if (p_msg->offset ==0)
539                 {
540                     *p ++ = op_code + 1;
541                     p_msg->len ++;
542                     p_msg->offset = handle_len;
543 
544                     if (op_code == GATT_REQ_READ_BY_GRP_TYPE)
545                     {
546                         *p ++ =  (UINT8)p_msg->offset; /* length byte */
547                         p_msg->len ++;
548                     }
549                 }
550 
551                 if (p_msg->len + p_msg->offset <= p_tcb->payload_size &&
552                     handle_len == p_msg->offset)
553                 {
554                     if (op_code != GATT_REQ_FIND_TYPE_VALUE ||
555                         gatt_uuid_compare(value, *p_uuid))
556                     {
557                         UINT16_TO_STREAM(p, p_rcb->s_hdl);
558 
559                         if (p_list->p_last_primary == p_srv &&
560                             p_list->p_last_primary == p_list->p_last)
561                         {
562                             GATT_TRACE_DEBUG("Use 0xFFFF for the last primary attribute");
563                             UINT16_TO_STREAM(p, 0xFFFF); /* see GATT ERRATA 4065, 4063, ATT ERRATA 4062 */
564                         }
565                         else
566                         {
567                             UINT16_TO_STREAM(p, p_rcb->e_hdl);
568                         }
569 
570                         if (op_code == GATT_REQ_READ_BY_GRP_TYPE)
571                             gatt_build_uuid_to_stream(&p, *p_uuid);
572 
573                         status = GATT_SUCCESS;
574                         p_msg->len += p_msg->offset;
575                     }
576                 }
577                 else
578                     break;
579             }
580         }
581         p_srv = p_srv->p_next;
582     }
583     p_msg->offset = L2CAP_MIN_OFFSET;
584 
585     return status;
586 }
587 
588 /*******************************************************************************
589 **
590 ** Function         gatt_build_find_info_rsp
591 **
592 ** Description      fill the find information response information in the given
593 **                  buffer.
594 **
595 ** Returns          TRUE: if data filled sucessfully.
596 **                  FALSE: packet full, or format mismatch.
597 **
598 *******************************************************************************/
gatt_build_find_info_rsp(tGATT_SR_REG * p_rcb,BT_HDR * p_msg,UINT16 * p_len,UINT16 s_hdl,UINT16 e_hdl)599 static tGATT_STATUS gatt_build_find_info_rsp(tGATT_SR_REG *p_rcb, BT_HDR *p_msg, UINT16 *p_len,
600                                              UINT16 s_hdl, UINT16 e_hdl)
601 {
602     tGATT_STATUS        status = GATT_NOT_FOUND;
603     UINT8               *p;
604     UINT16              len = *p_len;
605     tGATT_ATTR16        *p_attr = NULL;
606     UINT8               info_pair_len[2] = {4, 18};
607 
608     if (!p_rcb->p_db || !p_rcb->p_db->p_attr_list)
609         return status;
610 
611     /* check the attribute database */
612     p_attr = (tGATT_ATTR16 *) p_rcb->p_db->p_attr_list;
613 
614     p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET + p_msg->len;
615 
616     while (p_attr)
617     {
618         if (p_attr->handle > e_hdl)
619         {
620             break;
621         }
622 
623         if (p_attr->handle >= s_hdl)
624         {
625             if (p_msg->offset == 0)
626                 p_msg->offset = (p_attr->uuid_type == GATT_ATTR_UUID_TYPE_16) ? GATT_INFO_TYPE_PAIR_16 : GATT_INFO_TYPE_PAIR_128;
627 
628             if (len >= info_pair_len[p_msg->offset - 1])
629             {
630                 if (p_msg->offset == GATT_INFO_TYPE_PAIR_16 && p_attr->uuid_type == GATT_ATTR_UUID_TYPE_16)
631                 {
632                     UINT16_TO_STREAM(p, p_attr->handle);
633                     UINT16_TO_STREAM(p, p_attr->uuid);
634                 }
635                 else if (p_msg->offset == GATT_INFO_TYPE_PAIR_128 && p_attr->uuid_type == GATT_ATTR_UUID_TYPE_128  )
636                 {
637                     UINT16_TO_STREAM(p, p_attr->handle);
638                     ARRAY_TO_STREAM (p, ((tGATT_ATTR128 *) p_attr)->uuid, LEN_UUID_128);
639                 }
640                 else if (p_msg->offset == GATT_INFO_TYPE_PAIR_128 && p_attr->uuid_type == GATT_ATTR_UUID_TYPE_32)
641                 {
642                     UINT16_TO_STREAM(p, p_attr->handle);
643                     gatt_convert_uuid32_to_uuid128(p, ((tGATT_ATTR32 *) p_attr)->uuid);
644                     p += LEN_UUID_128;
645                 }
646                 else
647                 {
648                     GATT_TRACE_ERROR("format mismatch");
649                     status = GATT_NO_RESOURCES;
650                     break;
651                     /* format mismatch */
652                 }
653                 p_msg->len += info_pair_len[p_msg->offset - 1];
654                 len -= info_pair_len[p_msg->offset - 1];
655                 status = GATT_SUCCESS;
656 
657             }
658             else
659             {
660                 status = GATT_NO_RESOURCES;
661                 break;
662             }
663         }
664         p_attr = (tGATT_ATTR16 *)p_attr->p_next;
665     }
666 
667     *p_len = len;
668     return status;
669 }
670 
671 /*******************************************************************************
672 **
673 ** Function         gatts_internal_read_by_type_req
674 **
675 ** Description      check to see if the ReadByType request can be handled internally.
676 **
677 ** Returns          void
678 **
679 *******************************************************************************/
gatts_validate_packet_format(UINT8 op_code,UINT16 * p_len,UINT8 ** p_data,tBT_UUID * p_uuid_filter,UINT16 * p_s_hdl,UINT16 * p_e_hdl)680 static tGATT_STATUS gatts_validate_packet_format(UINT8 op_code, UINT16 *p_len,
681                                                  UINT8 **p_data, tBT_UUID *p_uuid_filter,
682                                                  UINT16 *p_s_hdl, UINT16 *p_e_hdl)
683 {
684     tGATT_STATUS    reason = GATT_SUCCESS;
685     UINT16          uuid_len, s_hdl = 0, e_hdl = 0;
686     UINT16          len = *p_len;
687     UINT8           *p = *p_data;
688 
689     if (len >= 4)
690     {
691         /* obtain starting handle, and ending handle */
692         STREAM_TO_UINT16(s_hdl, p);
693         STREAM_TO_UINT16(e_hdl, p);
694         len -= 4;
695 
696         if (s_hdl > e_hdl || !GATT_HANDLE_IS_VALID(s_hdl) || !GATT_HANDLE_IS_VALID(e_hdl))
697         {
698             reason = GATT_INVALID_HANDLE;
699         }
700         /* for these PDUs, uuid filter must present */
701         else if (op_code == GATT_REQ_READ_BY_GRP_TYPE ||
702                  op_code == GATT_REQ_FIND_TYPE_VALUE ||
703                  op_code == GATT_REQ_READ_BY_TYPE)
704         {
705             if (len >= 2 && p_uuid_filter != NULL)
706             {
707                 uuid_len = (op_code == GATT_REQ_FIND_TYPE_VALUE) ? 2 : len;
708 
709                 /* parse uuid now */
710                 if (gatt_parse_uuid_from_cmd (p_uuid_filter, uuid_len, &p) == FALSE ||
711                     p_uuid_filter->len == 0)
712                 {
713                     GATT_TRACE_DEBUG("UUID filter does not exsit");
714                     reason = GATT_INVALID_PDU;
715                 }
716                 else
717                     len -= p_uuid_filter->len;
718             }
719             else
720                 reason = GATT_INVALID_PDU;
721         }
722     }
723     else
724         reason = GATT_INVALID_PDU;
725 
726     *p_data     = p;
727     *p_len      = len;
728     *p_s_hdl    = s_hdl;
729     *p_e_hdl    = e_hdl;
730 
731     return reason;
732 }
733 
734 /*******************************************************************************
735 **
736 ** Function         gatts_process_primary_service_req
737 **
738 ** Description      process ReadByGroupType/ReadByTypeValue request, for discover
739 **                  all primary services or discover primary service by UUID request.
740 **
741 ** Returns          void
742 **
743 *******************************************************************************/
gatts_process_primary_service_req(tGATT_TCB * p_tcb,UINT8 op_code,UINT16 len,UINT8 * p_data)744 void gatts_process_primary_service_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data)
745 {
746     UINT8           reason = GATT_INVALID_PDU;
747     UINT16          s_hdl = 0, e_hdl = 0;
748     tBT_UUID        uuid, value, primary_service = {LEN_UUID_16, {GATT_UUID_PRI_SERVICE}};
749     BT_HDR          *p_msg = NULL;
750     UINT16          msg_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET);
751 
752     memset (&value, 0, sizeof(tBT_UUID));
753     reason = gatts_validate_packet_format(op_code, &len, &p_data, &uuid, &s_hdl, &e_hdl);
754 
755     if (reason == GATT_SUCCESS)
756     {
757         if (gatt_uuid_compare(uuid, primary_service))
758         {
759             if (op_code == GATT_REQ_FIND_TYPE_VALUE)
760             {
761                 if (gatt_parse_uuid_from_cmd(&value, len, &p_data) == FALSE)
762                     reason = GATT_INVALID_PDU;
763             }
764 
765             if (reason == GATT_SUCCESS) {
766                 p_msg = (BT_HDR *)osi_calloc(msg_len);
767                 reason = gatt_build_primary_service_rsp (p_msg, p_tcb, op_code,
768                                                          s_hdl, e_hdl, p_data,
769                                                          value);
770             }
771         }
772         else
773         {
774             if (op_code == GATT_REQ_READ_BY_GRP_TYPE)
775             {
776                 reason = GATT_UNSUPPORT_GRP_TYPE;
777                 GATT_TRACE_DEBUG("unexpected ReadByGrpType Group: 0x%04x", uuid.uu.uuid16);
778             }
779             else
780             {
781                 /* we do not support ReadByTypeValue with any non-primamry_service type */
782                 reason = GATT_NOT_FOUND;
783                 GATT_TRACE_DEBUG("unexpected ReadByTypeValue type: 0x%04x", uuid.uu.uuid16);
784             }
785         }
786     }
787 
788     if (reason != GATT_SUCCESS)
789     {
790         osi_free(p_msg);
791         gatt_send_error_rsp (p_tcb, reason, op_code, s_hdl, FALSE);
792     }
793     else
794         attp_send_sr_msg(p_tcb, p_msg);
795 
796 }
797 
798 /*******************************************************************************
799 **
800 ** Function         gatts_process_find_info
801 **
802 ** Description      process find information request, for discover character
803 **                  descriptors.
804 **
805 ** Returns          void
806 **
807 *******************************************************************************/
gatts_process_find_info(tGATT_TCB * p_tcb,UINT8 op_code,UINT16 len,UINT8 * p_data)808 static void gatts_process_find_info(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data)
809 {
810     UINT8           reason = GATT_INVALID_PDU, *p;
811     UINT16          s_hdl = 0, e_hdl = 0, buf_len;
812     BT_HDR          *p_msg = NULL;
813     tGATT_SR_REG    *p_rcb;
814     tGATT_SRV_LIST_INFO *p_list= &gatt_cb.srv_list_info;
815     tGATT_SRV_LIST_ELEM  *p_srv=NULL;
816 
817     reason = gatts_validate_packet_format(op_code, &len, &p_data, NULL, &s_hdl, &e_hdl);
818 
819     if (reason == GATT_SUCCESS)
820     {
821         buf_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET);
822 
823         p_msg = (BT_HDR *)osi_calloc(buf_len);
824         reason = GATT_NOT_FOUND;
825 
826         p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
827         *p ++ = op_code + 1;
828         p_msg->len = 2;
829 
830         buf_len = p_tcb->payload_size - 2;
831 
832         p_srv = p_list->p_first;
833 
834         while (p_srv) {
835             p_rcb = GATT_GET_SR_REG_PTR(p_srv->i_sreg);
836 
837             if (p_rcb->in_use && !(p_rcb->s_hdl > e_hdl ||
838                                    p_rcb->e_hdl < s_hdl)) {
839                 reason = gatt_build_find_info_rsp(p_rcb, p_msg, &buf_len,
840                                                   s_hdl, e_hdl);
841                 if (reason == GATT_NO_RESOURCES) {
842                     reason = GATT_SUCCESS;
843                     break;
844                 }
845             }
846             p_srv = p_srv->p_next;
847         }
848         *p = (UINT8)p_msg->offset;
849 
850         p_msg->offset = L2CAP_MIN_OFFSET;
851     }
852 
853     if (reason != GATT_SUCCESS)
854     {
855         osi_free(p_msg);
856         gatt_send_error_rsp (p_tcb, reason, op_code, s_hdl, FALSE);
857     }
858     else
859         attp_send_sr_msg(p_tcb, p_msg);
860 
861 }
862 
863 /*******************************************************************************
864 **
865 ** Function         gatts_process_mtu_req
866 **
867 ** Description      This function is called to process excahnge MTU request.
868 **                  Only used on LE.
869 **
870 ** Returns          void
871 **
872 *******************************************************************************/
gatts_process_mtu_req(tGATT_TCB * p_tcb,UINT16 len,UINT8 * p_data)873 static void gatts_process_mtu_req (tGATT_TCB *p_tcb, UINT16 len, UINT8 *p_data)
874 {
875     UINT16        mtu = 0;
876     UINT8         *p = p_data, i;
877     BT_HDR        *p_buf;
878     UINT16   conn_id;
879 
880     /* BR/EDR conenction, send error response */
881     if (p_tcb->att_lcid != L2CAP_ATT_CID)
882     {
883         gatt_send_error_rsp (p_tcb, GATT_REQ_NOT_SUPPORTED, GATT_REQ_MTU, 0, FALSE);
884     }
885     else if (len < GATT_MTU_REQ_MIN_LEN)
886     {
887         GATT_TRACE_ERROR("invalid MTU request PDU received.");
888         gatt_send_error_rsp (p_tcb, GATT_INVALID_PDU, GATT_REQ_MTU, 0, FALSE);
889     }
890     else
891     {
892         STREAM_TO_UINT16 (mtu, p);
893         /* mtu must be greater than default MTU which is 23/48 */
894         if (mtu < GATT_DEF_BLE_MTU_SIZE)
895             p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
896         else if (mtu > GATT_MAX_MTU_SIZE)
897             p_tcb->payload_size = GATT_MAX_MTU_SIZE;
898         else
899             p_tcb->payload_size = mtu;
900 
901         GATT_TRACE_ERROR("MTU request PDU with MTU size %d", p_tcb->payload_size);
902 
903         l2cble_set_fixed_channel_tx_data_length(p_tcb->peer_bda, L2CAP_ATT_CID, p_tcb->payload_size);
904 
905         if ((p_buf = attp_build_sr_msg(p_tcb, GATT_RSP_MTU, (tGATT_SR_MSG *) &p_tcb->payload_size)) != NULL)
906         {
907             attp_send_sr_msg (p_tcb, p_buf);
908 
909             /* Notify all registered applicaiton with new MTU size. Us a transaction ID */
910             /* of 0, as no response is allowed from applcations                    */
911 
912             for (i = 0; i < GATT_MAX_APPS; i ++)
913             {
914                 if (gatt_cb.cl_rcb[i].in_use )
915                 {
916                     conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_cb.cl_rcb[i].gatt_if);
917                     gatt_sr_send_req_callback(conn_id, 0, GATTS_REQ_TYPE_MTU,
918                                               (tGATTS_DATA *)&p_tcb->payload_size);
919                 }
920             }
921 
922         }
923     }
924 }
925 
926 /*******************************************************************************
927 **
928 ** Function         gatts_process_read_by_type_req
929 **
930 ** Description      process Read By type request.
931 **                  This PDU can be used to perform:
932 **                  - read characteristic value
933 **                  - read characteristic descriptor value
934 **                  - discover characteristic
935 **                  - discover characteristic by UUID
936 **                  - relationship discovery
937 **
938 ** Returns          void
939 **
940 *******************************************************************************/
gatts_process_read_by_type_req(tGATT_TCB * p_tcb,UINT8 op_code,UINT16 len,UINT8 * p_data)941 void gatts_process_read_by_type_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data)
942 {
943     tBT_UUID            uuid;
944     tGATT_SR_REG        *p_rcb;
945     size_t              msg_len = sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET;
946     UINT16              buf_len, s_hdl, e_hdl, err_hdl = 0;
947     BT_HDR              *p_msg = NULL;
948     tGATT_STATUS        reason, ret;
949     UINT8               *p;
950     UINT8               sec_flag, key_size;
951     tGATT_SRV_LIST_INFO *p_list= &gatt_cb.srv_list_info;
952     tGATT_SRV_LIST_ELEM  *p_srv=NULL;
953 
954     reason = gatts_validate_packet_format(op_code, &len, &p_data, &uuid, &s_hdl, &e_hdl);
955 
956 #if GATT_CONFORMANCE_TESTING == TRUE
957     if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
958     {
959         GATT_TRACE_DEBUG("Conformance tst: forced err rsp for ReadByType: error status=%d", gatt_cb.err_status);
960 
961         gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, s_hdl, FALSE);
962 
963         return;
964     }
965 #endif
966 
967     if (reason == GATT_SUCCESS)
968     {
969         p_msg = (BT_HDR *)osi_calloc(msg_len);
970         p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
971 
972         *p ++ = op_code + 1;
973         /* reserve length byte */
974         p_msg->len = 2;
975         buf_len = p_tcb->payload_size - 2;
976 
977         reason = GATT_NOT_FOUND;
978 
979         p_srv = p_list->p_first;
980 
981         while (p_srv) {
982             p_rcb = GATT_GET_SR_REG_PTR(p_srv->i_sreg);
983 
984             if (p_rcb->in_use && !(p_rcb->s_hdl > e_hdl ||
985                                    p_rcb->e_hdl < s_hdl)) {
986                 gatt_sr_get_sec_info(p_tcb->peer_bda, p_tcb->transport,
987                                      &sec_flag, &key_size);
988 
989                 ret = gatts_db_read_attr_value_by_type(p_tcb,
990                                                        p_rcb->p_db,
991                                                        op_code,
992                                                        p_msg,
993                                                        s_hdl,
994                                                        e_hdl,
995                                                        uuid,
996                                                        &buf_len,
997                                                        sec_flag,
998                                                        key_size,
999                                                        0,
1000                                                        &err_hdl);
1001                 if (ret != GATT_NOT_FOUND) {
1002                     reason = ret;
1003 
1004                     if (ret == GATT_NO_RESOURCES)
1005                         reason = GATT_SUCCESS;
1006                 }
1007                 if (ret != GATT_SUCCESS && ret != GATT_NOT_FOUND) {
1008                     s_hdl = err_hdl;
1009                     break;
1010                 }
1011             }
1012             p_srv = p_srv->p_next;
1013         }
1014         *p = (UINT8)p_msg->offset;
1015         p_msg->offset = L2CAP_MIN_OFFSET;
1016     }
1017     if (reason != GATT_SUCCESS)
1018     {
1019         osi_free(p_msg);
1020 
1021         /* in theroy BUSY is not possible(should already been checked), protected check */
1022         if (reason != GATT_PENDING && reason != GATT_BUSY)
1023             gatt_send_error_rsp (p_tcb, reason, op_code, s_hdl, FALSE);
1024     }
1025     else
1026         attp_send_sr_msg(p_tcb, p_msg);
1027 
1028 }
1029 
1030 /*******************************************************************************
1031 **
1032 ** Function         gatts_process_write_req
1033 **
1034 ** Description      This function is called to process the write request
1035 **                  from client.
1036 **
1037 ** Returns          void
1038 **
1039 *******************************************************************************/
gatts_process_write_req(tGATT_TCB * p_tcb,UINT8 i_rcb,UINT16 handle,UINT8 op_code,UINT16 len,UINT8 * p_data)1040 void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
1041                               UINT8 op_code, UINT16 len, UINT8 *p_data)
1042 {
1043     tGATTS_DATA     sr_data;
1044     UINT32          trans_id;
1045     tGATT_STATUS    status;
1046     UINT8           sec_flag, key_size, *p = p_data;
1047     tGATT_SR_REG    *p_sreg;
1048     UINT16          conn_id;
1049 
1050     memset(&sr_data, 0, sizeof(tGATTS_DATA));
1051 
1052     switch (op_code)
1053     {
1054         case GATT_REQ_PREPARE_WRITE:
1055             if (len < 2) {
1056                 GATT_TRACE_ERROR("%s: Prepare write request was invalid - missing offset, sending error response", __func__);
1057                 gatt_send_error_rsp(p_tcb, GATT_INVALID_PDU, op_code, handle, FALSE);
1058                 return;
1059             }
1060             sr_data.write_req.is_prep = TRUE;
1061             STREAM_TO_UINT16(sr_data.write_req.offset, p);
1062             len -= 2;
1063             /* fall through */
1064         case GATT_SIGN_CMD_WRITE:
1065             if (op_code == GATT_SIGN_CMD_WRITE)
1066             {
1067                 GATT_TRACE_DEBUG("Write CMD with data sigining" );
1068                 len -= GATT_AUTH_SIGN_LEN;
1069             }
1070             /* fall through */
1071         case GATT_CMD_WRITE:
1072         case GATT_REQ_WRITE:
1073             if (op_code == GATT_REQ_WRITE || op_code == GATT_REQ_PREPARE_WRITE)
1074                 sr_data.write_req.need_rsp = TRUE;
1075             sr_data.write_req.handle = handle;
1076             sr_data.write_req.len = len;
1077             if (len != 0 && p != NULL)
1078             {
1079                 memcpy (sr_data.write_req.value, p, len);
1080             }
1081             break;
1082     }
1083 
1084     gatt_sr_get_sec_info(p_tcb->peer_bda,
1085                          p_tcb->transport,
1086                          &sec_flag,
1087                          &key_size);
1088 
1089     status = gatts_write_attr_perm_check (gatt_cb.sr_reg[i_rcb].p_db,
1090                                           op_code,
1091                                           handle,
1092                                           sr_data.write_req.offset,
1093                                           p,
1094                                           len,
1095                                           sec_flag,
1096                                           key_size);
1097 
1098     if (status == GATT_SUCCESS)
1099     {
1100         if ((trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, handle)) != 0)
1101         {
1102             p_sreg = &gatt_cb.sr_reg[i_rcb];
1103             conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_sreg->gatt_if);
1104             gatt_sr_send_req_callback(conn_id,
1105                                       trans_id,
1106                                       GATTS_REQ_TYPE_WRITE,
1107                                       &sr_data);
1108 
1109             status = GATT_PENDING;
1110         }
1111         else
1112         {
1113             GATT_TRACE_ERROR("max pending command, send error");
1114             status = GATT_BUSY; /* max pending command, application error */
1115         }
1116     }
1117 
1118     /* in theroy BUSY is not possible(should already been checked), protected check */
1119     if (status != GATT_PENDING && status != GATT_BUSY &&
1120         (op_code == GATT_REQ_PREPARE_WRITE || op_code == GATT_REQ_WRITE))
1121     {
1122         gatt_send_error_rsp (p_tcb, status, op_code, handle, FALSE);
1123     }
1124     return;
1125 }
1126 
1127 /*******************************************************************************
1128 **
1129 ** Function         gatts_process_read_req
1130 **
1131 ** Description      This function is called to process the read request
1132 **                  from client.
1133 **
1134 ** Returns          void
1135 **
1136 *******************************************************************************/
gatts_process_read_req(tGATT_TCB * p_tcb,tGATT_SR_REG * p_rcb,UINT8 op_code,UINT16 handle,UINT16 len,UINT8 * p_data)1137 static void gatts_process_read_req(tGATT_TCB *p_tcb, tGATT_SR_REG *p_rcb, UINT8 op_code,
1138                                    UINT16 handle, UINT16 len, UINT8 *p_data)
1139 {
1140     size_t          buf_len = sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET;
1141     tGATT_STATUS    reason;
1142     UINT8           sec_flag, key_size, *p;
1143     UINT16          offset = 0, value_len = 0;
1144     BT_HDR          *p_msg = (BT_HDR *)osi_calloc(buf_len);
1145 
1146     UNUSED(len);
1147 
1148     if (op_code == GATT_REQ_READ_BLOB)
1149         STREAM_TO_UINT16(offset, p_data);
1150 
1151     p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
1152     *p ++ = op_code + 1;
1153     p_msg->len = 1;
1154     buf_len = p_tcb->payload_size - 1;
1155 
1156     gatt_sr_get_sec_info(p_tcb->peer_bda, p_tcb->transport, &sec_flag,
1157                          &key_size);
1158 
1159     reason = gatts_read_attr_value_by_handle(p_tcb,
1160                                              p_rcb->p_db,
1161                                              op_code,
1162                                              handle,
1163                                              offset,
1164                                              p,
1165                                              &value_len,
1166                                              (uint16_t)buf_len,
1167                                              sec_flag,
1168                                              key_size,
1169                                              0);
1170 
1171     p_msg->len += value_len;
1172 
1173     if (reason != GATT_SUCCESS)
1174     {
1175         osi_free(p_msg);
1176 
1177         /* in theroy BUSY is not possible(should already been checked), protected check */
1178         if (reason != GATT_PENDING && reason != GATT_BUSY)
1179             gatt_send_error_rsp (p_tcb, reason, op_code, handle, FALSE);
1180     }
1181     else
1182         attp_send_sr_msg(p_tcb, p_msg);
1183 
1184 }
1185 
1186 /*******************************************************************************
1187 **
1188 ** Function         gatts_process_attribute_req
1189 **
1190 ** Description      This function is called to process the per attribute handle request
1191 **                  from client.
1192 **
1193 ** Returns          void
1194 **
1195 *******************************************************************************/
gatts_process_attribute_req(tGATT_TCB * p_tcb,UINT8 op_code,UINT16 len,UINT8 * p_data)1196 void gatts_process_attribute_req (tGATT_TCB *p_tcb, UINT8 op_code,
1197                                   UINT16 len, UINT8 *p_data)
1198 {
1199     UINT16          handle = 0;
1200     UINT8           *p = p_data, i;
1201     tGATT_SR_REG    *p_rcb = gatt_cb.sr_reg;
1202     tGATT_STATUS    status = GATT_INVALID_HANDLE;
1203     tGATT_ATTR16    *p_attr;
1204 
1205     if (len < 2)
1206     {
1207         GATT_TRACE_ERROR("Illegal PDU length, discard request");
1208         status = GATT_INVALID_PDU;
1209     }
1210     else
1211     {
1212         STREAM_TO_UINT16(handle, p);
1213         len -= 2;
1214     }
1215 
1216 #if GATT_CONFORMANCE_TESTING == TRUE
1217     gatt_cb.handle = handle;
1218     if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
1219     {
1220         GATT_TRACE_DEBUG("Conformance tst: forced err rsp: error status=%d", gatt_cb.err_status);
1221 
1222         gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, handle, FALSE);
1223 
1224         return;
1225     }
1226 #endif
1227 
1228     if (GATT_HANDLE_IS_VALID(handle))
1229     {
1230         for (i = 0; i < GATT_MAX_SR_PROFILES; i ++, p_rcb ++)
1231         {
1232             if (p_rcb->in_use && p_rcb->s_hdl <= handle && p_rcb->e_hdl >= handle)
1233             {
1234                 p_attr = (tGATT_ATTR16 *)p_rcb->p_db->p_attr_list;
1235 
1236                 while (p_attr)
1237                 {
1238                     if (p_attr->handle == handle)
1239                     {
1240                         switch (op_code)
1241                         {
1242                             case GATT_REQ_READ: /* read char/char descriptor value */
1243                             case GATT_REQ_READ_BLOB:
1244                                 gatts_process_read_req(p_tcb, p_rcb, op_code, handle, len, p);
1245                                 break;
1246 
1247                             case GATT_REQ_WRITE: /* write char/char descriptor value */
1248                             case GATT_CMD_WRITE:
1249                             case GATT_SIGN_CMD_WRITE:
1250                             case GATT_REQ_PREPARE_WRITE:
1251                                 gatts_process_write_req(p_tcb, i, handle, op_code, len, p);
1252                                 break;
1253                             default:
1254                                 break;
1255                         }
1256                         status = GATT_SUCCESS;
1257                         break;
1258                     }
1259                     p_attr = (tGATT_ATTR16 *)p_attr->p_next;
1260                 }
1261                 break;
1262             }
1263         }
1264     }
1265 
1266     if (status != GATT_SUCCESS && op_code != GATT_CMD_WRITE && op_code != GATT_SIGN_CMD_WRITE)
1267         gatt_send_error_rsp (p_tcb, status, op_code, handle, FALSE);
1268 }
1269 
1270 /*******************************************************************************
1271 **
1272 ** Function         gatts_proc_srv_chg_ind_ack
1273 **
1274 ** Description      This function process the service changed indicaiton ACK
1275 **
1276 ** Returns          void
1277 **
1278 *******************************************************************************/
gatts_proc_srv_chg_ind_ack(tGATT_TCB * p_tcb)1279 static void gatts_proc_srv_chg_ind_ack(tGATT_TCB *p_tcb )
1280 {
1281     tGATTS_SRV_CHG_REQ  req;
1282     tGATTS_SRV_CHG      *p_buf = NULL;
1283 
1284     GATT_TRACE_DEBUG("gatts_proc_srv_chg_ind_ack");
1285 
1286     if ((p_buf = gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda)) != NULL)
1287     {
1288         GATT_TRACE_DEBUG("NV update set srv chg = FALSE");
1289         p_buf->srv_changed = FALSE;
1290         memcpy(&req.srv_chg, p_buf, sizeof(tGATTS_SRV_CHG));
1291         if (gatt_cb.cb_info.p_srv_chg_callback)
1292             (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_UPDATE_CLIENT,&req, NULL);
1293     }
1294 }
1295 
1296 /*******************************************************************************
1297 **
1298 ** Function         gatts_chk_pending_ind
1299 **
1300 ** Description      This function check any pending indication needs to be sent if
1301 **                  there is a pending indication then sent the indication
1302 **
1303 ** Returns          void
1304 **
1305 *******************************************************************************/
gatts_chk_pending_ind(tGATT_TCB * p_tcb)1306 static void gatts_chk_pending_ind(tGATT_TCB *p_tcb )
1307 {
1308     GATT_TRACE_DEBUG("%s", __func__);
1309 
1310     tGATT_VALUE *p_buf = (tGATT_VALUE *)fixed_queue_try_peek_first(p_tcb->pending_ind_q);
1311     if (p_buf != NULL)
1312     {
1313         GATTS_HandleValueIndication(p_buf->conn_id,
1314                                     p_buf->handle,
1315                                     p_buf->len,
1316                                     p_buf->value);
1317         osi_free(fixed_queue_try_remove_from_queue(p_tcb->pending_ind_q,
1318                                                       p_buf));
1319     }
1320 }
1321 
1322 /*******************************************************************************
1323 **
1324 ** Function         gatts_proc_ind_ack
1325 **
1326 ** Description      This function process the Indication ack
1327 **
1328 ** Returns          TRUE continue to process the indication ack by the aaplication
1329 **                  if the ACk is not a Service Changed Indication Ack
1330 **
1331 *******************************************************************************/
gatts_proc_ind_ack(tGATT_TCB * p_tcb,UINT16 ack_handle)1332 static BOOLEAN gatts_proc_ind_ack(tGATT_TCB *p_tcb, UINT16 ack_handle)
1333 {
1334     BOOLEAN continue_processing = TRUE;
1335 
1336     GATT_TRACE_DEBUG ("gatts_proc_ind_ack ack handle=%d", ack_handle);
1337 
1338     if (ack_handle == gatt_cb.handle_of_h_r)
1339     {
1340         gatts_proc_srv_chg_ind_ack(p_tcb);
1341         /* there is no need to inform the application since srv chg is handled internally by GATT */
1342         continue_processing = FALSE;
1343     }
1344 
1345     gatts_chk_pending_ind(p_tcb);
1346     return continue_processing;
1347 }
1348 
1349 /*******************************************************************************
1350 **
1351 ** Function         gatts_process_value_conf
1352 **
1353 ** Description      This function is called to process the handle value confirmation.
1354 **
1355 ** Returns          void
1356 **
1357 *******************************************************************************/
gatts_process_value_conf(tGATT_TCB * p_tcb,UINT8 op_code)1358 void gatts_process_value_conf(tGATT_TCB *p_tcb, UINT8 op_code)
1359 {
1360     UINT16          handle = p_tcb->indicate_handle;
1361     UINT32          trans_id;
1362     UINT8           i;
1363     tGATT_SR_REG    *p_rcb = gatt_cb.sr_reg;
1364     BOOLEAN         continue_processing;
1365     UINT16          conn_id;
1366 
1367     alarm_cancel(p_tcb->conf_timer);
1368     if (GATT_HANDLE_IS_VALID(handle))
1369     {
1370         p_tcb->indicate_handle = 0;
1371         continue_processing = gatts_proc_ind_ack(p_tcb, handle);
1372 
1373         if (continue_processing)
1374         {
1375             for (i = 0; i < GATT_MAX_SR_PROFILES; i ++, p_rcb ++)
1376             {
1377                 if (p_rcb->in_use && p_rcb->s_hdl <= handle && p_rcb->e_hdl >= handle)
1378                 {
1379                     trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, handle);
1380                     conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_rcb->gatt_if);
1381                     gatt_sr_send_req_callback(conn_id,
1382                                               trans_id, GATTS_REQ_TYPE_CONF, (tGATTS_DATA *)&handle);
1383                 }
1384             }
1385         }
1386     }
1387     else
1388     {
1389         GATT_TRACE_ERROR("unexpected handle value confirmation");
1390     }
1391 }
1392 
1393 /*******************************************************************************
1394 **
1395 ** Function         gatt_server_handle_client_req
1396 **
1397 ** Description      This function is called to handle the client requests to
1398 **                  server.
1399 **
1400 **
1401 ** Returns          void
1402 **
1403 *******************************************************************************/
gatt_server_handle_client_req(tGATT_TCB * p_tcb,UINT8 op_code,UINT16 len,UINT8 * p_data)1404 void gatt_server_handle_client_req (tGATT_TCB *p_tcb, UINT8 op_code,
1405                                     UINT16 len, UINT8 *p_data)
1406 {
1407     /* there is pending command, discard this one */
1408     if (!gatt_sr_cmd_empty(p_tcb) && op_code != GATT_HANDLE_VALUE_CONF)
1409         return;
1410 
1411     /* the size of the message may not be bigger than the local max PDU size*/
1412     /* The message has to be smaller than the agreed MTU, len does not include op code */
1413     if (len >= p_tcb->payload_size)
1414     {
1415         GATT_TRACE_ERROR("server receive invalid PDU size:%d pdu size:%d", len + 1, p_tcb->payload_size );
1416         /* for invalid request expecting response, send it now */
1417         if (op_code != GATT_CMD_WRITE &&
1418             op_code != GATT_SIGN_CMD_WRITE &&
1419             op_code != GATT_HANDLE_VALUE_CONF)
1420         {
1421             gatt_send_error_rsp (p_tcb, GATT_INVALID_PDU, op_code, 0, FALSE);
1422         }
1423         /* otherwise, ignore the pkt */
1424     }
1425     else
1426     {
1427         switch (op_code)
1428         {
1429             case GATT_REQ_READ_BY_GRP_TYPE: /* discover primary services */
1430             case GATT_REQ_FIND_TYPE_VALUE: /* discover service by UUID */
1431                 gatts_process_primary_service_req (p_tcb, op_code, len, p_data);
1432                 break;
1433 
1434             case GATT_REQ_FIND_INFO:/* discover char descrptor */
1435                 gatts_process_find_info(p_tcb, op_code, len, p_data);
1436                 break;
1437 
1438             case GATT_REQ_READ_BY_TYPE: /* read characteristic value, char descriptor value */
1439                 /* discover characteristic, discover char by UUID */
1440                 gatts_process_read_by_type_req(p_tcb, op_code, len, p_data);
1441                 break;
1442 
1443 
1444             case GATT_REQ_READ: /* read char/char descriptor value */
1445             case GATT_REQ_READ_BLOB:
1446             case GATT_REQ_WRITE: /* write char/char descriptor value */
1447             case GATT_CMD_WRITE:
1448             case GATT_SIGN_CMD_WRITE:
1449             case GATT_REQ_PREPARE_WRITE:
1450                 gatts_process_attribute_req (p_tcb, op_code, len, p_data);
1451                 break;
1452 
1453             case GATT_HANDLE_VALUE_CONF:
1454                 gatts_process_value_conf (p_tcb, op_code);
1455                 break;
1456 
1457             case GATT_REQ_MTU:
1458                 gatts_process_mtu_req (p_tcb, len, p_data);
1459                 break;
1460 
1461             case GATT_REQ_EXEC_WRITE:
1462                 gatt_process_exec_write_req (p_tcb, op_code, len, p_data);
1463                 break;
1464 
1465             case GATT_REQ_READ_MULTI:
1466                 gatt_process_read_multi_req (p_tcb, op_code, len, p_data);
1467                 break;
1468 
1469             default:
1470                 break;
1471         }
1472     }
1473 }
1474 
1475 #endif /* BLE_INCLUDED */
1476