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