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