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
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 *******************************************************************************/
gatt_sr_enqueue_cmd(tGATT_TCB * p_tcb,UINT8 op_code,UINT16 handle)43 UINT32 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 *******************************************************************************/
gatt_sr_cmd_empty(tGATT_TCB * p_tcb)81 BOOLEAN 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 *******************************************************************************/
gatt_dequeue_sr_cmd(tGATT_TCB * p_tcb)95 void 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 *******************************************************************************/
process_read_multi_rsp(tGATT_SR_CMD * p_cmd,tGATT_STATUS status,tGATTS_RSP * p_msg,UINT16 mtu)120 static 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 *******************************************************************************/
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)258 tGATT_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 *******************************************************************************/
gatt_process_exec_write_req(tGATT_TCB * p_tcb,UINT8 op_code,UINT16 len,UINT8 * p_data)327 void 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
335 #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
341 gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, 0, 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_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 *******************************************************************************/
gatt_process_read_multi_req(tGATT_TCB * p_tcb,UINT8 op_code,UINT16 len,UINT8 * p_data)395 void gatt_process_read_multi_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data)
396 {
397 UINT32 trans_id;
398 UINT16 handle, ll = len;
399 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 *******************************************************************************/
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)524 static 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 *******************************************************************************/
gatt_build_find_info_rsp(tGATT_SR_REG * p_rcb,BT_HDR * p_msg,UINT16 * p_len,UINT16 s_hdl,UINT16 e_hdl)614 static 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 *******************************************************************************/
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)690 static 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 *******************************************************************************/
gatts_process_primary_service_req(tGATT_TCB * p_tcb,UINT8 op_code,UINT16 len,UINT8 * p_data)752 void 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 *******************************************************************************/
gatts_process_find_info(tGATT_TCB * p_tcb,UINT8 op_code,UINT16 len,UINT8 * p_data)822 static 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 *******************************************************************************/
gatts_process_mtu_req(tGATT_TCB * p_tcb,UINT16 len,UINT8 * p_data)897 static 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 */
914 if (mtu <= GATT_MAX_MTU_SIZE)
915 p_tcb->payload_size = mtu;
916 else
917 p_tcb->payload_size = GATT_MAX_MTU_SIZE;
918
919 if ((p_buf = attp_build_sr_msg(p_tcb, GATT_RSP_MTU, (tGATT_SR_MSG *) &p_tcb->payload_size)) != NULL)
920 {
921 attp_send_sr_msg (p_tcb, p_buf);
922
923 /* Notify all registered applicaiton with new MTU size. Us a transaction ID */
924 /* of 0, as no response is allowed from applcations */
925
926 for (i = 0; i < GATT_MAX_APPS; i ++)
927 {
928 if (gatt_cb.cl_rcb[i].in_use )
929 {
930 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_cb.cl_rcb[i].gatt_if);
931 gatt_sr_send_req_callback(conn_id, 0, GATTS_REQ_TYPE_MTU,
932 (tGATTS_DATA *)&p_tcb->payload_size);
933 }
934 }
935
936 }
937 }
938 }
939
940 /*******************************************************************************
941 **
942 ** Function gatts_process_read_by_type_req
943 **
944 ** Description process Read By type request.
945 ** This PDU can be used to perform:
946 ** - read characteristic value
947 ** - read characteristic descriptor value
948 ** - discover characteristic
949 ** - discover characteristic by UUID
950 ** - relationship discovery
951 **
952 ** Returns void
953 **
954 *******************************************************************************/
gatts_process_read_by_type_req(tGATT_TCB * p_tcb,UINT8 op_code,UINT16 len,UINT8 * p_data)955 void gatts_process_read_by_type_req(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data)
956 {
957 tBT_UUID uuid;
958 tGATT_SR_REG *p_rcb;
959 UINT16 msg_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET),
960 buf_len,
961 s_hdl, e_hdl, err_hdl = 0;
962 BT_HDR *p_msg = NULL;
963 tGATT_STATUS reason, ret;
964 UINT8 *p;
965 UINT8 sec_flag, key_size;
966 tGATT_SRV_LIST_INFO *p_list= &gatt_cb.srv_list_info;
967 tGATT_SRV_LIST_ELEM *p_srv=NULL;
968
969 reason = gatts_validate_packet_format(op_code, &len, &p_data, &uuid, &s_hdl, &e_hdl);
970
971 #if GATT_CONFORMANCE_TESTING == TRUE
972 if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
973 {
974 GATT_TRACE_DEBUG1("Conformance tst: forced err rsp for ReadByType: error status=%d", gatt_cb.err_status);
975
976 gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, s_hdl, FALSE);
977
978 return;
979 }
980 #endif
981
982 if (reason == GATT_SUCCESS)
983 {
984 if ((p_msg = (BT_HDR *)GKI_getbuf(msg_len)) == NULL)
985 {
986 GATT_TRACE_ERROR0("gatts_process_find_info failed. no resources.");
987
988 reason = GATT_NO_RESOURCES;
989 }
990 else
991 {
992 memset(p_msg, 0, msg_len);
993 p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
994
995 *p ++ = op_code + 1;
996 /* reserve length byte */
997 p_msg->len = 2;
998 buf_len = p_tcb->payload_size - 2;
999
1000 reason = GATT_NOT_FOUND;
1001
1002 p_srv = p_list->p_first;
1003
1004 while (p_srv)
1005 {
1006 p_rcb = GATT_GET_SR_REG_PTR(p_srv->i_sreg);
1007
1008 if (p_rcb->in_use &&
1009 !(p_rcb->s_hdl > e_hdl ||
1010 p_rcb->e_hdl < s_hdl))
1011 {
1012 gatt_sr_get_sec_info(p_tcb->peer_bda,
1013 (BOOLEAN)(p_tcb->att_lcid == L2CAP_ATT_CID),
1014 &sec_flag,
1015 &key_size);
1016
1017 ret = gatts_db_read_attr_value_by_type(p_tcb,
1018 p_rcb->p_db,
1019 op_code,
1020 p_msg,
1021 s_hdl,
1022 e_hdl,
1023 uuid,
1024 &buf_len,
1025 sec_flag,
1026 key_size,
1027 0,
1028 &err_hdl);
1029 if (ret != GATT_NOT_FOUND)
1030 {
1031 reason = ret;
1032
1033 if (ret == GATT_NO_RESOURCES)
1034 reason = GATT_SUCCESS;
1035 }
1036 if (ret != GATT_SUCCESS && ret != GATT_NOT_FOUND)
1037 {
1038 s_hdl = err_hdl;
1039 break;
1040 }
1041 }
1042 p_srv = p_srv->p_next;
1043 }
1044 *p = (UINT8)p_msg->offset;
1045 p_msg->offset = L2CAP_MIN_OFFSET;
1046 }
1047 }
1048 if (reason != GATT_SUCCESS)
1049 {
1050 if (p_msg) GKI_freebuf(p_msg);
1051
1052 /* in theroy BUSY is not possible(should already been checked), protected check */
1053 if (reason != GATT_PENDING && reason != GATT_BUSY)
1054 gatt_send_error_rsp (p_tcb, reason, op_code, s_hdl, FALSE);
1055 }
1056 else
1057 attp_send_sr_msg(p_tcb, p_msg);
1058
1059 }
1060
1061 /*******************************************************************************
1062 **
1063 ** Function gatts_process_write_req
1064 **
1065 ** Description This function is called to process the write request
1066 ** from client.
1067 **
1068 ** Returns void
1069 **
1070 *******************************************************************************/
gatts_process_write_req(tGATT_TCB * p_tcb,UINT8 i_rcb,UINT16 handle,UINT8 op_code,UINT16 len,UINT8 * p_data)1071 void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
1072 UINT8 op_code, UINT16 len, UINT8 *p_data)
1073 {
1074 tGATTS_DATA sr_data;
1075 UINT32 trans_id;
1076 tGATT_STATUS status;
1077 UINT8 sec_flag, key_size, *p = p_data;
1078 tGATT_SR_REG *p_sreg;
1079 UINT16 conn_id;
1080
1081 memset(&sr_data, 0, sizeof(tGATTS_DATA));
1082
1083 switch (op_code)
1084 {
1085 case GATT_REQ_PREPARE_WRITE:
1086 sr_data.write_req.is_prep = TRUE;
1087 STREAM_TO_UINT16(sr_data.write_req.offset, p);
1088 len -= 2;
1089 /* fall through */
1090 case GATT_SIGN_CMD_WRITE:
1091 if (op_code == GATT_SIGN_CMD_WRITE)
1092 {
1093 GATT_TRACE_DEBUG0("Write CMD with data sigining" );
1094 len -= GATT_AUTH_SIGN_LEN;
1095 }
1096 /* fall through */
1097 case GATT_CMD_WRITE:
1098 case GATT_REQ_WRITE:
1099 if (op_code == GATT_REQ_WRITE || op_code == GATT_REQ_PREPARE_WRITE)
1100 sr_data.write_req.need_rsp = TRUE;
1101 sr_data.write_req.handle = handle;
1102 sr_data.write_req.len = len;
1103 memcpy (sr_data.write_req.value, p, len);
1104 break;
1105 }
1106
1107 gatt_sr_get_sec_info(p_tcb->peer_bda,
1108 (BOOLEAN)(p_tcb->att_lcid == L2CAP_ATT_CID),
1109 &sec_flag,
1110 &key_size);
1111
1112 status = gatts_write_attr_perm_check (gatt_cb.sr_reg[i_rcb].p_db,
1113 op_code,
1114 handle,
1115 sr_data.write_req.offset,
1116 p,
1117 len,
1118 sec_flag,
1119 key_size);
1120
1121 if (status == GATT_SUCCESS)
1122 {
1123 if ((trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, handle)) != 0)
1124 {
1125 p_sreg = &gatt_cb.sr_reg[i_rcb];
1126 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_sreg->gatt_if);
1127 gatt_sr_send_req_callback(conn_id,
1128 trans_id,
1129 GATTS_REQ_TYPE_WRITE,
1130 &sr_data);
1131
1132 status = GATT_PENDING;
1133 }
1134 else
1135 {
1136 GATT_TRACE_ERROR0("max pending command, send error");
1137 status = GATT_BUSY; /* max pending command, application error */
1138 }
1139 }
1140
1141 /* in theroy BUSY is not possible(should already been checked), protected check */
1142 if (status != GATT_PENDING && status != GATT_BUSY &&
1143 (op_code == GATT_REQ_PREPARE_WRITE || op_code == GATT_REQ_WRITE))
1144 {
1145 gatt_send_error_rsp (p_tcb, status, op_code, handle, FALSE);
1146 }
1147 return;
1148 }
1149
1150 /*******************************************************************************
1151 **
1152 ** Function gatts_process_read_req
1153 **
1154 ** Description This function is called to process the read request
1155 ** from client.
1156 **
1157 ** Returns void
1158 **
1159 *******************************************************************************/
gatts_process_read_req(tGATT_TCB * p_tcb,tGATT_SR_REG * p_rcb,UINT8 op_code,UINT16 handle,UINT16 len,UINT8 * p_data)1160 static void gatts_process_read_req(tGATT_TCB *p_tcb, tGATT_SR_REG *p_rcb, UINT8 op_code,
1161 UINT16 handle, UINT16 len, UINT8 *p_data)
1162 {
1163 UINT16 buf_len = (UINT16)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET);
1164 tGATT_STATUS reason;
1165 BT_HDR *p_msg = NULL;
1166 UINT8 sec_flag, key_size, *p;
1167 UINT16 offset = 0, value_len = 0;
1168
1169 if ((p_msg = (BT_HDR *)GKI_getbuf(buf_len)) == NULL)
1170 {
1171 GATT_TRACE_ERROR0("gatts_process_find_info failed. no resources.");
1172
1173 reason = GATT_NO_RESOURCES;
1174 }
1175 else
1176 {
1177 if (op_code == GATT_REQ_READ_BLOB)
1178 STREAM_TO_UINT16(offset, p_data);
1179
1180 memset(p_msg, 0, buf_len);
1181 p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
1182 *p ++ = op_code + 1;
1183 p_msg->len = 1;
1184 buf_len = p_tcb->payload_size - 1;
1185
1186 gatt_sr_get_sec_info(p_tcb->peer_bda,
1187 (BOOLEAN)(p_tcb->att_lcid == L2CAP_ATT_CID),
1188 &sec_flag,
1189 &key_size);
1190
1191 reason = gatts_read_attr_value_by_handle(p_tcb,
1192 p_rcb->p_db,
1193 op_code,
1194 handle,
1195 offset,
1196 p,
1197 &value_len,
1198 buf_len,
1199 sec_flag,
1200 key_size,
1201 0);
1202
1203 p_msg->len += value_len;
1204 }
1205
1206 if (reason != GATT_SUCCESS)
1207 {
1208 if (p_msg) GKI_freebuf(p_msg);
1209
1210 /* in theroy BUSY is not possible(should already been checked), protected check */
1211 if (reason != GATT_PENDING && reason != GATT_BUSY)
1212 gatt_send_error_rsp (p_tcb, reason, op_code, handle, FALSE);
1213 }
1214 else
1215 attp_send_sr_msg(p_tcb, p_msg);
1216
1217 }
1218
1219 /*******************************************************************************
1220 **
1221 ** Function gatts_process_attribute_req
1222 **
1223 ** Description This function is called to process the per attribute handle request
1224 ** from client.
1225 **
1226 ** Returns void
1227 **
1228 *******************************************************************************/
gatts_process_attribute_req(tGATT_TCB * p_tcb,UINT8 op_code,UINT16 len,UINT8 * p_data)1229 void gatts_process_attribute_req (tGATT_TCB *p_tcb, UINT8 op_code,
1230 UINT16 len, UINT8 *p_data)
1231 {
1232 UINT16 handle;
1233 UINT8 *p = p_data, i;
1234 tGATT_SR_REG *p_rcb = gatt_cb.sr_reg;
1235 tGATT_STATUS status = GATT_INVALID_HANDLE;
1236 tGATT_ATTR16 *p_attr;
1237
1238 STREAM_TO_UINT16(handle, p);
1239 len -= 2;
1240
1241 #if GATT_CONFORMANCE_TESTING == TRUE
1242 if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
1243 {
1244 GATT_TRACE_DEBUG1("Conformance tst: forced err rsp: error status=%d", gatt_cb.err_status);
1245
1246 gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, handle, FALSE);
1247
1248 return;
1249 }
1250 #endif
1251
1252 if (GATT_HANDLE_IS_VALID(handle))
1253 {
1254 for (i = 0; i < GATT_MAX_SR_PROFILES; i ++, p_rcb ++)
1255 {
1256 if (p_rcb->in_use && p_rcb->s_hdl <= handle && p_rcb->e_hdl >= handle)
1257 {
1258 p_attr = (tGATT_ATTR16 *)p_rcb->p_db->p_attr_list;
1259
1260 while (p_attr)
1261 {
1262 if (p_attr->handle == handle)
1263 {
1264 switch (op_code)
1265 {
1266 case GATT_REQ_READ: /* read char/char descriptor value */
1267 case GATT_REQ_READ_BLOB:
1268 gatts_process_read_req(p_tcb, p_rcb, op_code, handle, len, p);
1269 break;
1270
1271 case GATT_REQ_WRITE: /* write char/char descriptor value */
1272 case GATT_CMD_WRITE:
1273 case GATT_SIGN_CMD_WRITE:
1274 case GATT_REQ_PREPARE_WRITE:
1275 gatts_process_write_req(p_tcb, i, handle, op_code, len, p);
1276 break;
1277 default:
1278 break;
1279 }
1280 status = GATT_SUCCESS;
1281 break;
1282 }
1283 p_attr = (tGATT_ATTR16 *)p_attr->p_next;
1284 }
1285 break;
1286 }
1287 }
1288 }
1289
1290 if (status != GATT_SUCCESS && op_code != GATT_CMD_WRITE && op_code != GATT_SIGN_CMD_WRITE)
1291 gatt_send_error_rsp (p_tcb, status, op_code, handle, FALSE);
1292 }
1293
1294 /*******************************************************************************
1295 **
1296 ** Function gatts_proc_srv_chg_ind_ack
1297 **
1298 ** Description This function process the service changed indicaiton ACK
1299 **
1300 ** Returns void
1301 **
1302 *******************************************************************************/
gatts_proc_srv_chg_ind_ack(tGATT_TCB * p_tcb)1303 static void gatts_proc_srv_chg_ind_ack(tGATT_TCB *p_tcb )
1304 {
1305 tGATTS_SRV_CHG_REQ req;
1306 tGATTS_SRV_CHG *p_buf = NULL;
1307
1308 GATT_TRACE_DEBUG0("gatts_proc_srv_chg_ind_ack");
1309
1310 if ((p_buf = gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda)) != NULL)
1311 {
1312 GATT_TRACE_DEBUG0("NV update set srv chg = FALSE");
1313 p_buf->srv_changed = FALSE;
1314 memcpy(&req.srv_chg, p_buf, sizeof(tGATTS_SRV_CHG));
1315 if (gatt_cb.cb_info.p_srv_chg_callback)
1316 (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_UPDATE_CLIENT,&req, NULL);
1317 }
1318 }
1319
1320 /*******************************************************************************
1321 **
1322 ** Function gatts_chk_pending_ind
1323 **
1324 ** Description This function check any pending indication needs to be sent if
1325 ** there is a pending indication then sent the indication
1326 **
1327 ** Returns void
1328 **
1329 *******************************************************************************/
gatts_chk_pending_ind(tGATT_TCB * p_tcb)1330 static void gatts_chk_pending_ind(tGATT_TCB *p_tcb )
1331 {
1332 tGATT_VALUE *p_buf = (tGATT_VALUE *)GKI_getfirst(&p_tcb->pending_ind_q);
1333 GATT_TRACE_DEBUG0("gatts_chk_pending_ind");
1334
1335 if (p_buf )
1336 {
1337 GATTS_HandleValueIndication (p_buf->conn_id,
1338 p_buf->handle,
1339 p_buf->len,
1340 p_buf->value);
1341 GKI_freebuf(GKI_remove_from_queue (&p_tcb->pending_ind_q, p_buf));
1342 }
1343 }
1344
1345 /*******************************************************************************
1346 **
1347 ** Function gatts_proc_ind_ack
1348 **
1349 ** Description This function process the Indication ack
1350 **
1351 ** Returns TRUE continue to process the indication ack by the aaplication
1352 ** if the ACk is not a Service Changed Indication Ack
1353 **
1354 *******************************************************************************/
gatts_proc_ind_ack(tGATT_TCB * p_tcb,UINT16 ack_handle)1355 static BOOLEAN gatts_proc_ind_ack(tGATT_TCB *p_tcb, UINT16 ack_handle)
1356 {
1357 BOOLEAN continue_processing = TRUE;
1358
1359 GATT_TRACE_DEBUG1 ("gatts_proc_ind_ack ack handle=%d", ack_handle);
1360
1361 if (ack_handle == gatt_cb.handle_of_h_r)
1362 {
1363 gatts_proc_srv_chg_ind_ack(p_tcb);
1364 /* there is no need to inform the application since srv chg is handled internally by GATT */
1365 continue_processing = FALSE;
1366 }
1367
1368 gatts_chk_pending_ind(p_tcb);
1369 return continue_processing;
1370 }
1371
1372 /*******************************************************************************
1373 **
1374 ** Function gatts_process_value_conf
1375 **
1376 ** Description This function is called to process the handle value confirmation.
1377 **
1378 ** Returns void
1379 **
1380 *******************************************************************************/
gatts_process_value_conf(tGATT_TCB * p_tcb,UINT8 op_code)1381 void gatts_process_value_conf(tGATT_TCB *p_tcb, UINT8 op_code)
1382 {
1383 UINT16 handle = p_tcb->indicate_handle;
1384 UINT32 trans_id;
1385 UINT8 i;
1386 tGATT_SR_REG *p_rcb = gatt_cb.sr_reg;
1387 BOOLEAN continue_processing;
1388 UINT16 conn_id;
1389
1390 btu_stop_timer (&p_tcb->conf_timer_ent);
1391 if (GATT_HANDLE_IS_VALID(handle))
1392 {
1393 p_tcb->indicate_handle = 0;
1394 continue_processing = gatts_proc_ind_ack(p_tcb, handle);
1395
1396 if (continue_processing)
1397 {
1398 for (i = 0; i < GATT_MAX_SR_PROFILES; i ++, p_rcb ++)
1399 {
1400 if (p_rcb->in_use && p_rcb->s_hdl <= handle && p_rcb->e_hdl >= handle)
1401 {
1402 trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, handle);
1403 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_rcb->gatt_if);
1404 gatt_sr_send_req_callback(conn_id,
1405 trans_id, GATTS_REQ_TYPE_CONF, (tGATTS_DATA *)&handle);
1406 }
1407 }
1408 }
1409 }
1410 else
1411 {
1412 GATT_TRACE_ERROR0("unexpected handle value confirmation");
1413 }
1414 }
1415
1416 /*******************************************************************************
1417 **
1418 ** Function gatt_server_handle_client_req
1419 **
1420 ** Description This function is called to handle the client requests to
1421 ** server.
1422 **
1423 **
1424 ** Returns void
1425 **
1426 *******************************************************************************/
gatt_server_handle_client_req(tGATT_TCB * p_tcb,UINT8 op_code,UINT16 len,UINT8 * p_data)1427 void gatt_server_handle_client_req (tGATT_TCB *p_tcb, UINT8 op_code,
1428 UINT16 len, UINT8 *p_data)
1429 {
1430 /* there is pending command, discard this one */
1431 if (!gatt_sr_cmd_empty(p_tcb) && op_code != GATT_HANDLE_VALUE_CONF)
1432 return;
1433
1434 /* the size of the message may not be bigger than the local max PDU size*/
1435 /* The message has to be smaller than the agreed MTU, len does not include op code */
1436 if (len >= p_tcb->payload_size)
1437 {
1438 GATT_TRACE_ERROR2("server receive invalid PDU size:%d pdu size:%d", len + 1, p_tcb->payload_size );
1439 /* for invalid request expecting response, send it now */
1440 if (op_code != GATT_CMD_WRITE &&
1441 op_code != GATT_SIGN_CMD_WRITE &&
1442 op_code != GATT_HANDLE_VALUE_CONF)
1443 {
1444 gatt_send_error_rsp (p_tcb, GATT_INVALID_PDU, op_code, 0, FALSE);
1445 }
1446 /* otherwise, ignore the pkt */
1447 }
1448 else
1449 {
1450 switch (op_code)
1451 {
1452 case GATT_REQ_READ_BY_GRP_TYPE: /* discover primary services */
1453 case GATT_REQ_FIND_TYPE_VALUE: /* discover service by UUID */
1454 gatts_process_primary_service_req (p_tcb, op_code, len, p_data);
1455 break;
1456
1457 case GATT_REQ_FIND_INFO:/* discover char descrptor */
1458 gatts_process_find_info(p_tcb, op_code, len, p_data);
1459 break;
1460
1461 case GATT_REQ_READ_BY_TYPE: /* read characteristic value, char descriptor value */
1462 /* discover characteristic, discover char by UUID */
1463 gatts_process_read_by_type_req(p_tcb, op_code, len, p_data);
1464 break;
1465
1466
1467 case GATT_REQ_READ: /* read char/char descriptor value */
1468 case GATT_REQ_READ_BLOB:
1469 case GATT_REQ_WRITE: /* write char/char descriptor value */
1470 case GATT_CMD_WRITE:
1471 case GATT_SIGN_CMD_WRITE:
1472 case GATT_REQ_PREPARE_WRITE:
1473 gatts_process_attribute_req (p_tcb, op_code, len, p_data);
1474 break;
1475
1476 case GATT_HANDLE_VALUE_CONF:
1477 gatts_process_value_conf (p_tcb, op_code);
1478 break;
1479
1480 case GATT_REQ_MTU:
1481 gatts_process_mtu_req (p_tcb, len, p_data);
1482 break;
1483
1484 case GATT_REQ_EXEC_WRITE:
1485 gatt_process_exec_write_req (p_tcb, op_code, len, p_data);
1486 break;
1487
1488 case GATT_REQ_READ_MULTI:
1489 gatt_process_read_multi_req (p_tcb, op_code, len, p_data);
1490 break;
1491
1492 default:
1493 break;
1494 }
1495 }
1496 }
1497
1498 #endif /* BLE_INCLUDED */
1499