blob: 7457dcb14fd6f9ca6648ef8f05be459ca9b4848e [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
2 *
3 * Copyright (C) 1999-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19/******************************************************************************
20 *
21 * this file contains the main GATT client functions
22 *
23 ******************************************************************************/
24
25#include "bt_target.h"
26
27#if BLE_INCLUDED == TRUE
28
29#include <string.h>
30#include "gki.h"
31#include "gatt_int.h"
32
33#define GATT_WRITE_LONG_HDR_SIZE 5 /* 1 opcode + 2 handle + 2 offset */
34#define GATT_READ_CHAR_VALUE_HDL (GATT_READ_CHAR_VALUE | 0x80)
35#define GATT_READ_INC_SRV_UUID128 (GATT_DISC_INC_SRVC | 0x90)
36
Andre Eisenbachccf9c152013-10-02 15:37:21 -070037#define GATT_PREP_WRITE_RSP_MIN_LEN 4
38#define GATT_NOTIFICATION_MIN_LEN 2
39#define GATT_WRITE_RSP_MIN_LEN 2
40#define GATT_INFO_RSP_MIN_LEN 1
41#define GATT_MTU_RSP_MIN_LEN 2
42#define GATT_READ_BY_TYPE_RSP_MIN_LEN 1
43
The Android Open Source Project5738f832012-12-12 16:00:35 -080044/********************************************************************************
45** G L O B A L G A T T D A T A *
46*********************************************************************************/
47void gatt_send_prepare_write(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb);
48
49UINT8 disc_type_to_att_opcode[GATT_DISC_MAX] =
50{
51 0,
52 GATT_REQ_READ_BY_GRP_TYPE, /* GATT_DISC_SRVC_ALL = 1, */
53 GATT_REQ_FIND_TYPE_VALUE, /* GATT_DISC_SRVC_BY_UUID, */
54 GATT_REQ_READ_BY_TYPE, /* GATT_DISC_INC_SRVC, */
55 GATT_REQ_READ_BY_TYPE, /* GATT_DISC_CHAR, */
56 GATT_REQ_FIND_INFO /* GATT_DISC_CHAR_DSCPT, */
57};
58
59UINT16 disc_type_to_uuid[GATT_DISC_MAX] =
60{
61 0, /* reserved */
62 GATT_UUID_PRI_SERVICE, /* <service> DISC_SRVC_ALL */
63 GATT_UUID_PRI_SERVICE, /* <service> for DISC_SERVC_BY_UUID */
64 GATT_UUID_INCLUDE_SERVICE, /* <include_service> for DISC_INC_SRVC */
65 GATT_UUID_CHAR_DECLARE, /* <characteristic> for DISC_CHAR */
66 0 /* no type filtering for DISC_CHAR_DSCPT */
67};
68
69
70/*******************************************************************************
71**
72** Function gatt_act_discovery
73**
74** Description GATT discovery operation.
75**
76** Returns void.
77**
78*******************************************************************************/
79void gatt_act_discovery(tGATT_CLCB *p_clcb)
80{
81 UINT8 op_code = disc_type_to_att_opcode[p_clcb->op_subtype];
82 tGATT_CL_MSG cl_req;
Andre Eisenbach6975b4d2013-08-05 16:55:38 -070083 tGATT_STATUS st;
The Android Open Source Project5738f832012-12-12 16:00:35 -080084
85 if (p_clcb->s_handle <= p_clcb->e_handle && p_clcb->s_handle != 0)
86 {
87 memset(&cl_req, 0, sizeof(tGATT_CL_MSG));
88
89 cl_req.browse.s_handle = p_clcb->s_handle;
90 cl_req.browse.e_handle = p_clcb->e_handle;
91
92 if (disc_type_to_uuid[p_clcb->op_subtype] != 0)
93 {
94 cl_req.browse.uuid.len = 2;
95 cl_req.browse.uuid.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype];
96 }
97
98 if (p_clcb->op_subtype == GATT_DISC_SRVC_BY_UUID) /* fill in the FindByTypeValue request info*/
99 {
100 cl_req.find_type_value.uuid.len = 2;
101 cl_req.find_type_value.uuid.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype];
102 cl_req.find_type_value.s_handle = p_clcb->s_handle;
103 cl_req.find_type_value.e_handle = p_clcb->e_handle;
104 cl_req.find_type_value.value_len = p_clcb->uuid.len;
105 memcpy (cl_req.find_type_value.value, &p_clcb->uuid.uu, p_clcb->uuid.len);
106 }
107
Andre Eisenbach6975b4d2013-08-05 16:55:38 -0700108 st = attp_send_cl_msg(p_clcb->p_tcb, p_clcb->clcb_idx, op_code, &cl_req);
109
110 if (st != GATT_SUCCESS && st != GATT_CMD_STARTED)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800111 {
112 gatt_end_operation(p_clcb, GATT_ERROR, NULL);
113 }
114 }
115 else /* end of handle range */
116 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
117}
118
119/*******************************************************************************
120**
121** Function gatt_act_read
122**
123** Description GATT read operation.
124**
125** Returns void.
126**
127*******************************************************************************/
128void gatt_act_read (tGATT_CLCB *p_clcb, UINT16 offset)
129{
130 tGATT_TCB *p_tcb = p_clcb->p_tcb;
131 UINT8 rt = GATT_INTERNAL_ERROR;
132 tGATT_CL_MSG msg;
133 UINT8 op_code = 0;
134
135 memset (&msg, 0, sizeof(tGATT_CL_MSG));
136
137 switch (p_clcb->op_subtype)
138 {
139 case GATT_READ_CHAR_VALUE:
140 case GATT_READ_BY_TYPE:
141 op_code = GATT_REQ_READ_BY_TYPE;
142 msg.browse.s_handle = p_clcb->s_handle;
143 msg.browse.e_handle = p_clcb->e_handle;
144 if (p_clcb->op_subtype == GATT_READ_BY_TYPE)
145 memcpy(&msg.browse.uuid, &p_clcb->uuid, sizeof(tBT_UUID));
146 else
147 {
148 msg.browse.uuid.len = LEN_UUID_16;
149 msg.browse.uuid.uu.uuid16 = GATT_UUID_CHAR_DECLARE;
150 }
151 break;
152
153 case GATT_READ_CHAR_VALUE_HDL:
154 case GATT_READ_BY_HANDLE:
155 if (!p_clcb->counter)
156 {
157 op_code = GATT_REQ_READ;
158 msg.handle = p_clcb->s_handle;
159 }
160 else
161 {
162 if (!p_clcb->first_read_blob_after_read)
163 p_clcb->first_read_blob_after_read = TRUE;
164 else
165 p_clcb->first_read_blob_after_read = FALSE;
166
167 GATT_TRACE_DEBUG1("gatt_act_read first_read_blob_after_read=%d",
168 p_clcb->first_read_blob_after_read);
169 op_code = GATT_REQ_READ_BLOB;
170 msg.read_blob.offset = offset;
171 msg.read_blob.handle = p_clcb->s_handle;
172 }
173 p_clcb->op_subtype &= ~ 0x80;
174 break;
175
176 case GATT_READ_PARTIAL:
177 op_code = GATT_REQ_READ_BLOB;
178 msg.read_blob.handle = p_clcb->s_handle;
179 msg.read_blob.offset = offset;
180 break;
181
182 case GATT_READ_MULTIPLE:
183 op_code = GATT_REQ_READ_MULTI;
184 memcpy (&msg.read_multi, p_clcb->p_attr_buf, sizeof(tGATT_READ_MULTI));
185 break;
186
187 case GATT_READ_INC_SRV_UUID128:
188 op_code = GATT_REQ_READ;
189 msg.handle = p_clcb->s_handle;
190 p_clcb->op_subtype &= ~ 0x90;
191 break;
192
193 default:
194 GATT_TRACE_ERROR1("Unknown read type: %d", p_clcb->op_subtype);
195 break;
196 }
197
Andre Eisenbach6975b4d2013-08-05 16:55:38 -0700198 if (op_code != 0)
199 rt = attp_send_cl_msg(p_tcb, p_clcb->clcb_idx, op_code, &msg);
200
201 if ( op_code == 0 || (rt != GATT_SUCCESS && rt != GATT_CMD_STARTED))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800202 {
203 gatt_end_operation(p_clcb, rt, NULL);
204 }
205}
206
207/*******************************************************************************
208**
209** Function gatt_act_write
210**
211** Description GATT write operation.
212**
213** Returns void.
214**
215*******************************************************************************/
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800216void gatt_act_write (tGATT_CLCB *p_clcb, UINT8 sec_act)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800217{
218 tGATT_TCB *p_tcb = p_clcb->p_tcb;
Andre Eisenbach6975b4d2013-08-05 16:55:38 -0700219 UINT8 rt = GATT_SUCCESS, op_code = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800220 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
221
222 if (p_attr)
223 {
224 switch (p_clcb->op_subtype)
225 {
226 case GATT_WRITE_NO_RSP:
227 p_clcb->s_handle = p_attr->handle;
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800228 op_code = (sec_act == GATT_SEC_SIGN_DATA) ? GATT_SIGN_CMD_WRITE : GATT_CMD_WRITE;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800229 rt = gatt_send_write_msg(p_tcb,
230 p_clcb->clcb_idx,
231 op_code,
232 p_attr->handle,
233 p_attr->len,
234 0,
235 p_attr->value);
236 break;
237
238 case GATT_WRITE:
239 if (p_attr->len <= (p_tcb->payload_size - GATT_HDR_SIZE))
240 {
241 p_clcb->s_handle = p_attr->handle;
242
243 rt = gatt_send_write_msg(p_tcb,
244 p_clcb->clcb_idx,
245 GATT_REQ_WRITE,
246 p_attr->handle,
247 p_attr->len,
248 0,
249 p_attr->value);
250 }
251 else /* prepare write for long attribute */
252 {
253 gatt_send_prepare_write(p_tcb, p_clcb);
254 }
255 break;
256
257 case GATT_WRITE_PREPARE:
258 gatt_send_prepare_write(p_tcb, p_clcb);
259 break;
260
261 default:
262 rt = GATT_INTERNAL_ERROR;
263 GATT_TRACE_ERROR1("Unknown write type: %d", p_clcb->op_subtype);
264 break;
265 }
266 }
267 else
268 rt = GATT_INTERNAL_ERROR;
269
270 if ((rt != GATT_SUCCESS && rt != GATT_CMD_STARTED)
271 || (rt != GATT_CMD_STARTED && p_clcb->op_subtype == GATT_WRITE_NO_RSP))
272 {
273 if (rt != GATT_SUCCESS)
274 {
275 GATT_TRACE_ERROR1("gatt_act_write() failed op_code=0x%x", op_code);
276 }
277 gatt_end_operation(p_clcb, rt, NULL);
278 }
279}
280/*******************************************************************************
281**
282** Function gatt_send_queue_write_cancel
283**
284** Description send queue write cancel
285**
286** Returns void.
287**
288*******************************************************************************/
289void gatt_send_queue_write_cancel (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, tGATT_EXEC_FLAG flag)
290{
291 UINT8 rt ;
292
293 GATT_TRACE_DEBUG0("gatt_send_queue_write_cancel ");
294
295 rt = attp_send_cl_msg(p_tcb, p_clcb->clcb_idx, GATT_REQ_EXEC_WRITE, (tGATT_CL_MSG *)&flag);
296
297 if (rt != GATT_SUCCESS)
298 {
299 gatt_end_operation(p_clcb, rt, NULL);
300 }
301}
302/*******************************************************************************
303**
304** Function gatt_check_write_long_terminate
305**
306** Description To terminate write long or not.
307**
308** Returns TRUE: write long is terminated; FALSE keep sending.
309**
310*******************************************************************************/
311BOOLEAN gatt_check_write_long_terminate(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, tGATT_VALUE *p_rsp_value)
312{
313 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
314 BOOLEAN exec = FALSE;
315 tGATT_EXEC_FLAG flag = GATT_PREP_WRITE_EXEC;
316
317 GATT_TRACE_DEBUG0("gatt_check_write_long_terminate ");
318 /* check the first write response status */
319 if (p_rsp_value != NULL)
320 {
321 if (p_rsp_value->handle != p_attr->handle ||
322 p_rsp_value->len != p_clcb->counter ||
323 memcmp(p_rsp_value->value, p_attr->value + p_attr->offset, p_rsp_value->len))
324 {
325 /* data does not match */
326 p_clcb->status = GATT_ERROR;
327 flag = GATT_PREP_WRITE_CANCEL;
328 exec = TRUE;
329 }
330 else /* response checking is good */
331 {
332 p_clcb->status = GATT_SUCCESS;
333 /* update write offset and check if end of attribute value */
334 if ((p_attr->offset += p_rsp_value->len) >= p_attr->len)
335 exec = TRUE;
336 }
337 }
338 if (exec)
339 {
340 gatt_send_queue_write_cancel (p_tcb, p_clcb, flag);
341 return TRUE;
342 }
343 return FALSE;
344}
345/*******************************************************************************
346**
347** Function gatt_send_prepare_write
348**
349** Description Send prepare write.
350**
351** Returns void.
352**
353*******************************************************************************/
354void gatt_send_prepare_write(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb)
355{
356 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
357 UINT16 to_send, offset;
358 UINT8 rt = GATT_SUCCESS;
359 UINT8 type = p_clcb->op_subtype;
360
361 GATT_TRACE_DEBUG1("gatt_send_prepare_write type=0x%x", type );
362 to_send = p_attr->len - p_attr->offset;
363
364 if (to_send > (p_tcb->payload_size - GATT_WRITE_LONG_HDR_SIZE)) /* 2 = UINT16 offset bytes */
365 to_send = p_tcb->payload_size - GATT_WRITE_LONG_HDR_SIZE;
366
367 p_clcb->s_handle = p_attr->handle;
368
369 offset = p_attr->offset;
370 if (type == GATT_WRITE_PREPARE)
371 {
372 offset += p_clcb->start_offset;
373 }
374
375 GATT_TRACE_DEBUG2("offset =0x%x len=%d", offset, to_send );
376
377 rt = gatt_send_write_msg(p_tcb,
378 p_clcb->clcb_idx,
379 GATT_REQ_PREPARE_WRITE,
380 p_attr->handle,
381 to_send, /* length */
382 offset, /* used as offset */
383 p_attr->value + p_attr->offset); /* data */
384
385 /* remember the write long attribute length */
386 p_clcb->counter = to_send;
387
Andre Eisenbach6975b4d2013-08-05 16:55:38 -0700388 if (rt != GATT_SUCCESS && rt != GATT_CMD_STARTED)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800389 {
390 gatt_end_operation(p_clcb, rt, NULL);
391 }
392}
393
The Android Open Source Project5738f832012-12-12 16:00:35 -0800394
The Android Open Source Project5738f832012-12-12 16:00:35 -0800395/*******************************************************************************
396**
397** Function gatt_process_find_type_value_rsp
398**
399** Description This function is called to handle find by type value response.
400**
401**
402** Returns void
403**
404*******************************************************************************/
405void gatt_process_find_type_value_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
406{
407 tGATT_DISC_RES result;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800408 UINT8 *p = p_data;
409
410 GATT_TRACE_DEBUG0("gatt_process_find_type_value_rsp ");
411 /* unexpected response */
412 if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_SRVC_BY_UUID)
413 return;
414
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800415 memset (&result, 0, sizeof(tGATT_DISC_RES));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800416 result.type.len = 2;
417 result.type.uu.uuid16 = GATT_UUID_PRI_SERVICE;
418
419 /* returns a series of handle ranges */
420 while (len >= 4)
421 {
422 STREAM_TO_UINT16 (result.handle, p);
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800423 STREAM_TO_UINT16 (result.value.group_value.e_handle, p);
424 memcpy (&result.value.group_value.service_type, &p_clcb->uuid, sizeof(tBT_UUID));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800425
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800426 len -= 4;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800427
428 if (p_clcb->p_reg->app_cb.p_disc_res_cb)
429 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
430 }
431
432 /* last handle + 1 */
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800433 p_clcb->s_handle = (result.value.group_value.e_handle == 0) ? 0 : (result.value.group_value.e_handle + 1);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800434 /* initiate another request */
435 gatt_act_discovery(p_clcb) ;
436}
437/*******************************************************************************
438**
439** Function gatt_process_read_info_rsp
440**
441** Description This function is called to handle the read information
442** response.
443**
444**
445** Returns void
446**
447*******************************************************************************/
448void gatt_process_read_info_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
449 UINT16 len, UINT8 *p_data)
450{
451 tGATT_DISC_RES result;
452 UINT8 *p = p_data, uuid_len = 0, type;
453
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700454 if (len < GATT_INFO_RSP_MIN_LEN)
455 {
456 GATT_TRACE_ERROR0("invalid Info Response PDU received, discard.");
457 gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
458 return;
459 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800460 /* unexpected response */
461 if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_CHAR_DSCPT)
462 return;
463
464 STREAM_TO_UINT8(type, p);
465 len -= 1;
466
467 if (type == GATT_INFO_TYPE_PAIR_16)
468 uuid_len = LEN_UUID_16;
469 else if (type == GATT_INFO_TYPE_PAIR_128)
470 uuid_len = LEN_UUID_128;
471
472 while (len >= uuid_len + 2)
473 {
474 STREAM_TO_UINT16 (result.handle, p);
475
476 if (uuid_len > 0)
477 {
478 if (!gatt_parse_uuid_from_cmd(&result.type, uuid_len, &p))
479 break;
480 }
481 else
482 memcpy (&result.type, &p_clcb->uuid, sizeof(tBT_UUID));
483
484 len -= (uuid_len + 2);
485
486 if (p_clcb->p_reg->app_cb.p_disc_res_cb)
487 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
488 }
489
490 p_clcb->s_handle = (result.handle == 0) ? 0 :(result.handle + 1);
491 /* initiate another request */
492 gatt_act_discovery(p_clcb) ;
493}
494/*******************************************************************************
495**
496** Function gatt_proc_disc_error_rsp
497**
498** Description This function process the read by type response and send another
499** request if needed.
500**
501** Returns void.
502**
503*******************************************************************************/
504void gatt_proc_disc_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 opcode,
505 UINT16 handle, UINT8 reason)
506{
507 tGATT_STATUS status = (tGATT_STATUS) reason;
508
509 GATT_TRACE_DEBUG2("gatt_proc_disc_error_rsp reason: %02x cmd_code %04x", reason, opcode);
510
511 switch (opcode)
512 {
513 case GATT_REQ_READ_BY_GRP_TYPE:
514 case GATT_REQ_FIND_TYPE_VALUE:
515 case GATT_REQ_READ_BY_TYPE:
516 case GATT_REQ_FIND_INFO:
517 if (reason == GATT_NOT_FOUND)
518 {
519 status = GATT_SUCCESS;
520 GATT_TRACE_DEBUG0("Discovery completed");
521 }
522 break;
523 default:
524 GATT_TRACE_ERROR1("Incorrect discovery opcode %04x", opcode);
525 break;
526 }
527
528 gatt_end_operation(p_clcb, status, NULL);
529}
530
531/*******************************************************************************
532**
533** Function gatt_process_error_rsp
534**
535** Description This function is called to handle the error response
536**
537**
538** Returns void
539**
540*******************************************************************************/
541void gatt_process_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
542 UINT16 len, UINT8 *p_data)
543{
544 UINT8 opcode, reason, * p= p_data;
545 UINT16 handle;
546 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
547
548 GATT_TRACE_DEBUG0("gatt_process_error_rsp ");
549 STREAM_TO_UINT8(opcode, p);
550 STREAM_TO_UINT16(handle, p);
551 STREAM_TO_UINT8(reason, p);
552
553 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)
554 {
555 gatt_proc_disc_error_rsp(p_tcb, p_clcb, opcode, handle, reason);
556 }
557 else
558 {
559 if ( (p_clcb->operation == GATTC_OPTYPE_WRITE) &&
560 (p_clcb->op_subtype == GATT_WRITE) &&
561 (opcode == GATT_REQ_PREPARE_WRITE) &&
562 (p_attr) &&
563 (handle == p_attr->handle) )
564 {
565 p_clcb->status = reason;
566 gatt_send_queue_write_cancel(p_tcb, p_clcb, GATT_PREP_WRITE_CANCEL);
567 }
568 else if ((p_clcb->operation == GATTC_OPTYPE_READ) &&
569 ((p_clcb->op_subtype == GATT_READ_CHAR_VALUE_HDL) ||
570 (p_clcb->op_subtype == GATT_READ_BY_HANDLE)) &&
571 (opcode == GATT_REQ_READ_BLOB) &&
572 p_clcb->first_read_blob_after_read &&
573 (reason == GATT_NOT_LONG))
574 {
575 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf);
576 }
577 else
578 gatt_end_operation(p_clcb, reason, NULL);
579 }
580}
581/*******************************************************************************
582**
583** Function gatt_process_prep_write_rsp
584**
585** Description This function is called to handle the read response
586**
587**
588** Returns void
589**
590*******************************************************************************/
591void gatt_process_prep_write_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
592 UINT16 len, UINT8 *p_data)
593{
594 tGATT_VALUE value = {0};
595 UINT8 *p= p_data;
596
597 GATT_TRACE_ERROR2("value resp op_code = %s len = %d", gatt_dbg_op_name(op_code), len);
598
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700599 if (len < GATT_PREP_WRITE_RSP_MIN_LEN)
600 {
601 GATT_TRACE_ERROR0("illegal prepare write response length, discard");
602 gatt_end_operation(p_clcb, GATT_INVALID_PDU, &value);
603 return;
604 }
605
The Android Open Source Project5738f832012-12-12 16:00:35 -0800606 STREAM_TO_UINT16 (value.handle, p);
607 STREAM_TO_UINT16 (value.offset, p);
608
609 value.len = len - 4;
610
611 memcpy (value.value, p, value.len);
612
613 if (p_clcb->op_subtype == GATT_WRITE_PREPARE)
614 {
615 p_clcb->status = GATT_SUCCESS;
616 /* application should verify handle offset
617 and value are matched or not */
618
619 gatt_end_operation(p_clcb, p_clcb->status, &value);
620 }
621 else if (p_clcb->op_subtype == GATT_WRITE )
622 {
623 if (!gatt_check_write_long_terminate(p_tcb, p_clcb, &value))
624 gatt_send_prepare_write(p_tcb, p_clcb);
625 }
626
627}
628/*******************************************************************************
629**
630** Function gatt_process_notification
631**
632** Description This function is called to handle the handle value indication
633** or handle value notification.
634**
635**
636** Returns void
637**
638*******************************************************************************/
639void gatt_process_notification(tGATT_TCB *p_tcb, UINT8 op_code,
640 UINT16 len, UINT8 *p_data)
641{
642 tGATT_VALUE value = {0};
643 tGATT_REG *p_reg;
644 UINT16 conn_id;
645 tGATT_STATUS encrypt_status;
646 UINT8 *p= p_data, i,
647 event = (op_code == GATT_HANDLE_VALUE_NOTIF) ? GATTC_OPTYPE_NOTIFICATION : GATTC_OPTYPE_INDICATION;
648
649 GATT_TRACE_DEBUG0("gatt_process_notification ");
650
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700651 if (len < GATT_NOTIFICATION_MIN_LEN)
652 {
653 GATT_TRACE_ERROR0("illegal notification PDU length, discard");
654 return;
655 }
656
The Android Open Source Project5738f832012-12-12 16:00:35 -0800657 STREAM_TO_UINT16 (value.handle, p);
658 value.len = len - 2;
659 memcpy (value.value, p, value.len);
660
661 if (!GATT_HANDLE_IS_VALID(value.handle))
662 {
663 /* illegal handle, send ack now */
664 if (op_code == GATT_HANDLE_VALUE_IND)
665 attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
666 return;
667 }
668
669 if (event == GATTC_OPTYPE_INDICATION)
670 {
671 if (p_tcb->ind_count)
672 {
673 /* this is an error case that receiving an indication but we
674 still has an indication not being acked yet.
675 For now, just log the error reset the counter.
676 Later we need to disconnect the link unconditionally.
677 */
678 GATT_TRACE_ERROR1("gatt_process_notification rcv Ind. but ind_count=%d (will reset ind_count)", p_tcb->ind_count);
679 }
680 p_tcb->ind_count = 0;
681 }
682
683 /* should notify all registered client with the handle value notificaion/indication
684 Note: need to do the indication count and start timer first then do callback
685 */
686
687 for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++)
688 {
689 if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb && (event == GATTC_OPTYPE_INDICATION))
690 p_tcb->ind_count++;
691 }
692
693 if (event == GATTC_OPTYPE_INDICATION)
694 {
695 /* start a timer for app confirmation */
696 if (p_tcb->ind_count > 0)
697 gatt_start_ind_ack_timer(p_tcb);
698 else /* no app to indicate, or invalid handle */
699 attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
700 }
701
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800702 encrypt_status = gatt_get_link_encrypt_status(p_tcb);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800703 for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++)
704 {
705 if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb)
706 {
707 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800708 (*p_reg->app_cb.p_cmpl_cb) (conn_id, event, encrypt_status, (tGATT_CL_COMPLETE *)&value);
709 }
710 }
711
712}
713
714/*******************************************************************************
715**
716** Function gatt_process_read_by_type_rsp
717**
718** Description This function is called to handle the read by type response.
719** read by type can be used for discovery, or read by type or
720** read characteristic value.
721**
722** Returns void
723**
724*******************************************************************************/
725void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
726 UINT16 len, UINT8 *p_data)
727{
728 tGATT_DISC_RES result;
729 tGATT_DISC_VALUE record_value;
730 UINT8 *p = p_data, value_len, handle_len = 2;
731 UINT16 handle = 0;
732
733 /* discovery procedure and no callback function registered */
734 if (((!p_clcb->p_reg) || (!p_clcb->p_reg->app_cb.p_disc_res_cb)) && (p_clcb->operation == GATTC_OPTYPE_DISCOVERY))
735 return;
736
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700737 if (len < GATT_READ_BY_TYPE_RSP_MIN_LEN)
738 {
739 GATT_TRACE_ERROR0("Illegal ReadByType/ReadByGroupType Response length, discard");
740 gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
741 return;
742 }
743
The Android Open Source Project5738f832012-12-12 16:00:35 -0800744 STREAM_TO_UINT8(value_len, p);
745
746 if ((value_len > (p_tcb->payload_size - 2)) || (value_len > (len-1)) )
747 {
748 /* this is an error case that server's response containing a value length which is larger than MTU-2
749 or value_len > message total length -1 */
750 GATT_TRACE_ERROR4("gatt_process_read_by_type_rsp: Discard response op_code=%d vale_len=%d > (MTU-2=%d or msg_len-1=%d)",
751 op_code, value_len, (p_tcb->payload_size - 2), (len-1));
752 gatt_end_operation(p_clcb, GATT_ERROR, NULL);
753 return;
754 }
755
756 if (op_code == GATT_RSP_READ_BY_GRP_TYPE)
757 handle_len = 4;
758
759 value_len -= handle_len; /* substract the handle pairs bytes */
760 len -= 1;
761
762 while (len >= (handle_len + value_len))
763 {
764 STREAM_TO_UINT16(handle, p);
765
766 if (!GATT_HANDLE_IS_VALID(handle))
767 {
768 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
769 return;
770 }
771
772 memset(&result, 0, sizeof(tGATT_DISC_RES));
773 memset(&record_value, 0, sizeof(tGATT_DISC_VALUE));
774
775 result.handle = handle;
776 result.type.len = 2;
777 result.type.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype];
778
779 /* discover all services */
780 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
781 p_clcb->op_subtype == GATT_DISC_SRVC_ALL &&
782 op_code == GATT_RSP_READ_BY_GRP_TYPE)
783 {
784 STREAM_TO_UINT16(handle, p);
785
786 if (!GATT_HANDLE_IS_VALID(handle))
787 {
788 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
789 return;
790 }
791 else
792 {
793 record_value.group_value.e_handle = handle;
794 if (!gatt_parse_uuid_from_cmd(&record_value.group_value.service_type, value_len, &p))
795 {
796 GATT_TRACE_ERROR0("discover all service response parsing failure");
797 break;
798 }
799 }
800 }
801 /* discover included service */
802 else if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->op_subtype == GATT_DISC_INC_SRVC)
803 {
804 STREAM_TO_UINT16(record_value.incl_service.s_handle, p);
805 STREAM_TO_UINT16(record_value.incl_service.e_handle, p);
806
807 if (!GATT_HANDLE_IS_VALID(record_value.incl_service.s_handle) ||
808 !GATT_HANDLE_IS_VALID(record_value.incl_service.e_handle))
809 {
810 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
811 return;
812 }
813
814 if(value_len == 6)
815 {
816 STREAM_TO_UINT16(record_value.incl_service.service_type.uu.uuid16, p);
817 record_value.incl_service.service_type.len = LEN_UUID_16;
818 }
819 else if (value_len == 4)
820 {
821 p_clcb->s_handle = record_value.incl_service.s_handle;
822 p_clcb->read_uuid128.wait_for_read_rsp = TRUE;
823 p_clcb->read_uuid128.next_disc_start_hdl = handle + 1;
824 memcpy(&p_clcb->read_uuid128.result, &result, sizeof(result));
825 memcpy(&p_clcb->read_uuid128.result.value, &record_value, sizeof (result.value));
826 p_clcb->op_subtype |= 0x90;
827 gatt_act_read(p_clcb, 0);
828 return;
829 }
830 else
831 {
832 GATT_TRACE_ERROR1("gatt_process_read_by_type_rsp INCL_SRVC failed with invalid data value_len=%d", value_len);
833 gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p);
834 return;
835 }
836 }
837 /* read by type */
838 else if (p_clcb->operation == GATTC_OPTYPE_READ && p_clcb->op_subtype == GATT_READ_BY_TYPE)
839 {
840 p_clcb->counter = len - 2;
841 p_clcb->s_handle = handle;
842 if ( p_clcb->counter == (p_clcb->p_tcb->payload_size -4))
843 {
844 p_clcb->op_subtype = GATT_READ_BY_HANDLE;
845 if (!p_clcb->p_attr_buf)
846 p_clcb->p_attr_buf = (UINT8 *)GKI_getbuf(GATT_MAX_ATTR_LEN);
847 if (p_clcb->p_attr_buf && p_clcb->counter <= GATT_MAX_ATTR_LEN)
848 {
849 memcpy(p_clcb->p_attr_buf, p, p_clcb->counter);
850 gatt_act_read(p_clcb, p_clcb->counter);
851 }
852 else
853 gatt_end_operation(p_clcb, GATT_INTERNAL_ERROR, (void *)p);
854 }
855 else
856 {
857 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p);
858 }
859 return;
860 }
Andre Eisenbach6975b4d2013-08-05 16:55:38 -0700861 else /* discover characterisitic */
The Android Open Source Project5738f832012-12-12 16:00:35 -0800862 {
863 STREAM_TO_UINT8 (record_value.dclr_value.char_prop, p);
864 STREAM_TO_UINT16(record_value.dclr_value.val_handle, p);
865 if (!GATT_HANDLE_IS_VALID(record_value.dclr_value.val_handle))
866 {
867 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
868 return;
869 }
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800870 if (!gatt_parse_uuid_from_cmd(&record_value.dclr_value.char_uuid, (UINT16)(value_len - 3), &p))
871 {
872 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
873 /* invalid format, and skip the result */
874 return;
875 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800876
877 /* UUID not matching */
878 if (!gatt_uuid_compare(record_value.dclr_value.char_uuid, p_clcb->uuid))
879 {
880 len -= (value_len + 2);
881 continue; /* skip the result, and look for next one */
882 }
883 else if (p_clcb->operation == GATTC_OPTYPE_READ)
884 /* UUID match for read characteristic value */
885 {
886 /* only read the first matching UUID characteristic value, and
887 discard the rest results */
888 p_clcb->s_handle = record_value.dclr_value.val_handle;
889 p_clcb->op_subtype |= 0x80;
890 gatt_act_read(p_clcb, 0);
891 return;
892 }
893 }
894 len -= (value_len + handle_len);
895
896 /* result is (handle, 16bits UUID) pairs */
897 memcpy (&result.value, &record_value, sizeof (result.value));
898
899 /* send callback if is discover procedure */
900 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->p_reg->app_cb.p_disc_res_cb)
901 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
902 }
903
904 p_clcb->s_handle = (handle == 0) ? 0 : (handle + 1);
905
906 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)
907 {
908 /* initiate another request */
909 gatt_act_discovery(p_clcb) ;
910 }
911 else /* read characteristic value */
912 {
913 gatt_act_read(p_clcb, 0);
914 }
915}
916
917/*******************************************************************************
918**
919** Function gatt_process_read_rsp
920**
921** Description This function is called to handle the read BLOB response
922**
923**
924** Returns void
925**
926*******************************************************************************/
927void gatt_process_read_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
928 UINT16 len, UINT8 *p_data)
929{
930 UINT16 offset = p_clcb->counter;
931 UINT8 * p= p_data;
932
933 if (p_clcb->operation == GATTC_OPTYPE_READ)
934 {
935 if (p_clcb->op_subtype != GATT_READ_BY_HANDLE)
936 {
937 p_clcb->counter = len;
938 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p);
939 }
940 else
941 {
942
943 /* allocate GKI buffer holding up long attribute value */
944 if (!p_clcb->p_attr_buf)
945 p_clcb->p_attr_buf = (UINT8 *)GKI_getbuf(GATT_MAX_ATTR_LEN);
946
947 /* copy attrobute value into cb buffer */
948 if (p_clcb->p_attr_buf && offset < GATT_MAX_ATTR_LEN)
949 {
950 if ((len + offset) > GATT_MAX_ATTR_LEN)
951 len = GATT_MAX_ATTR_LEN - offset;
952
953 p_clcb->counter += len;
954
955 memcpy(p_clcb->p_attr_buf + offset, p, len);
956
957 /* send next request if needed */
958
959 if (len == (p_tcb->payload_size - 1) && /* full packet for read or read blob rsp */
960 len + offset < GATT_MAX_ATTR_LEN)
961 {
962 GATT_TRACE_DEBUG3("full pkt issue read blob for remianing bytes old offset=%d len=%d new offset=%d",
963 offset, len, p_clcb->counter);
964 gatt_act_read(p_clcb, p_clcb->counter);
965 }
966 else /* end of request, send callback */
967 {
968 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf);
969 }
970 }
971 else /* exception, should not happen */
972 {
973 GATT_TRACE_ERROR2("attr offset = %d p_attr_buf = %d ", offset, p_clcb->p_attr_buf);
974 gatt_end_operation(p_clcb, GATT_NO_RESOURCES, (void *)p_clcb->p_attr_buf);
975 }
976 }
977 }
978 else
979 {
980 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
981 p_clcb->op_subtype == GATT_DISC_INC_SRVC &&
982 p_clcb->read_uuid128.wait_for_read_rsp )
983 {
984 p_clcb->s_handle = p_clcb->read_uuid128.next_disc_start_hdl;
985 p_clcb->read_uuid128.wait_for_read_rsp = FALSE;
986 if (len == LEN_UUID_128)
987 {
988
989 memcpy(p_clcb->read_uuid128.result.value.incl_service.service_type.uu.uuid128, p, len);
990 p_clcb->read_uuid128.result.value.incl_service.service_type.len = LEN_UUID_128;
991 if ( p_clcb->p_reg->app_cb.p_disc_res_cb)
992 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &p_clcb->read_uuid128.result);
993 gatt_act_discovery(p_clcb) ;
994 }
995 else
996 {
997 gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p);
998 }
999 }
1000 }
1001
1002}
1003
1004
1005/*******************************************************************************
1006**
1007** Function gatt_process_handle_rsp
1008**
1009** Description This function is called to handle the write response
1010**
1011**
1012** Returns void
1013**
1014*******************************************************************************/
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001015void gatt_process_handle_rsp(tGATT_CLCB *p_clcb)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001016{
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001017 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001018}
1019/*******************************************************************************
1020**
1021** Function gatt_process_mtu_rsp
1022**
1023** Description This function is called to process the configure MTU response.
1024**
1025**
1026** Returns void
1027**
1028*******************************************************************************/
1029void gatt_process_mtu_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
1030{
1031 UINT16 mtu;
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001032 tGATT_STATUS status = GATT_SUCCESS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001033
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001034 if (len < GATT_MTU_RSP_MIN_LEN)
1035 {
1036 GATT_TRACE_ERROR0("invalid MTU response PDU received, discard.");
1037 status = GATT_INVALID_PDU;
1038 }
1039 else
1040 {
The Android Open Source Project5738f832012-12-12 16:00:35 -08001041 STREAM_TO_UINT16(mtu, p_data);
1042
1043 if (mtu < p_tcb->payload_size && mtu >= GATT_DEF_BLE_MTU_SIZE)
1044 p_tcb->payload_size = mtu;
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001045 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001046
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001047 gatt_end_operation(p_clcb, status, NULL);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001048}
1049/*******************************************************************************
1050**
1051** Function gatt_cmd_to_rsp_code
1052**
1053** Description The function convert a ATT command op code into the corresponding
1054** response code assume no error occurs.
1055**
1056** Returns response code.
1057**
1058*******************************************************************************/
1059UINT8 gatt_cmd_to_rsp_code (UINT8 cmd_code)
1060{
1061 UINT8 rsp_code = 0;
1062
1063 if (cmd_code > 1 && cmd_code != GATT_CMD_WRITE)
1064 {
1065 rsp_code = cmd_code + 1;
1066 }
1067 return rsp_code;
1068}
1069/*******************************************************************************
1070**
1071** Function gatt_cl_send_next_cmd_inq
1072**
1073** Description Find next command in queue and sent to server
1074**
1075** Returns TRUE if command sent, otherwise FALSE.
1076**
1077*******************************************************************************/
1078BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb)
1079{
1080 tGATT_CMD_Q *p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1081 BOOLEAN sent = FALSE;
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001082 UINT8 rsp_code;
1083 tGATT_CLCB *p_clcb = NULL;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001084
1085 while (!sent &&
1086 p_tcb->pending_cl_req != p_tcb->next_slot_inq &&
1087 p_cmd->to_send && p_cmd->p_cmd != NULL)
1088 {
1089 sent = attp_send_msg_to_L2CAP(p_tcb, p_cmd->p_cmd);
1090
1091 if (sent)
1092 {
1093 p_cmd->to_send = FALSE;
1094 p_cmd->p_cmd = NULL;
1095
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001096 /* dequeue the request if is write command or sign write */
1097 if (p_cmd->op_code != GATT_CMD_WRITE && p_cmd->op_code != GATT_SIGN_CMD_WRITE)
1098 {
Zhihai Xu5fba60a2014-02-05 20:04:48 -08001099 gatt_start_rsp_timer (p_cmd->clcb_idx);
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001100 }
1101 else
1102 {
1103 p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
1104
1105 /* if no ack needed, keep sending */
1106 sent = FALSE;
1107 p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1108 /* send command complete callback here */
1109 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
1110 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001111 }
1112 else
1113 {
1114 GATT_TRACE_ERROR0("gatt_cl_send_next_cmd_inq: L2CAP sent error");
1115
1116 memset(p_cmd, 0, sizeof(tGATT_CMD_Q));
1117 p_tcb->pending_cl_req ++;
1118 p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1119 }
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001120
The Android Open Source Project5738f832012-12-12 16:00:35 -08001121 }
1122 return sent;
1123}
1124
1125/*******************************************************************************
1126**
1127** Function gatt_client_handle_server_rsp
1128**
1129** Description This function is called to handle the server response to
1130** client.
1131**
1132**
1133** Returns void
1134**
1135*******************************************************************************/
1136void gatt_client_handle_server_rsp (tGATT_TCB *p_tcb, UINT8 op_code,
1137 UINT16 len, UINT8 *p_data)
1138{
1139 tGATT_CLCB *p_clcb = NULL;
1140 UINT8 rsp_code;
1141
1142 if (op_code != GATT_HANDLE_VALUE_IND && op_code != GATT_HANDLE_VALUE_NOTIF)
1143 {
1144 p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
1145
1146 rsp_code = gatt_cmd_to_rsp_code(rsp_code);
1147
1148 if (p_clcb == NULL || (rsp_code != op_code && op_code != GATT_RSP_ERROR))
1149 {
1150 GATT_TRACE_WARNING2 ("ATT - Ignore wrong response. Receives (%02x) \
1151 Request(%02x) Ignored", op_code, rsp_code);
1152
1153 return;
1154 }
1155 else
Zhihai Xu5fba60a2014-02-05 20:04:48 -08001156 {
1157 btu_stop_timer (&p_clcb->rsp_timer_ent);
1158 p_clcb->retry_count = 0;
1159 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001160 }
1161 /* the size of the message may not be bigger than the local max PDU size*/
1162 /* The message has to be smaller than the agreed MTU, len does not count op_code */
1163 if (len >= p_tcb->payload_size)
1164 {
1165 GATT_TRACE_ERROR2("invalid response/indicate pkt size: %d, PDU size: %d", len + 1, p_tcb->payload_size);
1166 if (op_code != GATT_HANDLE_VALUE_NOTIF &&
1167 op_code != GATT_HANDLE_VALUE_IND)
1168 gatt_end_operation(p_clcb, GATT_ERROR, NULL);
1169 }
1170 else
1171 {
1172 switch (op_code)
1173 {
1174 case GATT_RSP_ERROR:
1175 gatt_process_error_rsp(p_tcb, p_clcb, op_code, len, p_data);
1176 break;
1177
1178 case GATT_RSP_MTU: /* 2 bytes mtu */
1179 gatt_process_mtu_rsp(p_tcb, p_clcb, len ,p_data);
1180 break;
1181
1182 case GATT_RSP_FIND_INFO:
1183 gatt_process_read_info_rsp(p_tcb, p_clcb, op_code, len, p_data);
1184 break;
1185
1186 case GATT_RSP_READ_BY_TYPE:
1187 case GATT_RSP_READ_BY_GRP_TYPE:
1188 gatt_process_read_by_type_rsp(p_tcb, p_clcb, op_code, len, p_data);
1189 break;
1190
1191 case GATT_RSP_READ:
1192 case GATT_RSP_READ_BLOB:
1193 case GATT_RSP_READ_MULTI:
1194 gatt_process_read_rsp(p_tcb, p_clcb, op_code, len, p_data);
1195 break;
1196
1197 case GATT_RSP_FIND_TYPE_VALUE: /* disc service with UUID */
1198 gatt_process_find_type_value_rsp(p_tcb, p_clcb, len, p_data);
1199 break;
1200
1201 case GATT_RSP_WRITE:
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001202 gatt_process_handle_rsp(p_clcb);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001203 break;
1204
1205 case GATT_RSP_PREPARE_WRITE:
1206 gatt_process_prep_write_rsp(p_tcb, p_clcb, op_code, len, p_data);
1207 break;
1208
1209 case GATT_RSP_EXEC_WRITE:
1210 gatt_end_operation(p_clcb, p_clcb->status, NULL);
1211 break;
1212
1213 case GATT_HANDLE_VALUE_NOTIF:
1214 case GATT_HANDLE_VALUE_IND:
1215 gatt_process_notification(p_tcb, op_code, len, p_data);
1216 break;
1217
1218 default:
1219 GATT_TRACE_ERROR1("Unknown opcode = %d", op_code);
1220 break;
1221 }
1222 }
1223
1224 if (op_code != GATT_HANDLE_VALUE_IND && op_code != GATT_HANDLE_VALUE_NOTIF)
1225 {
1226 gatt_cl_send_next_cmd_inq(p_tcb);
1227 }
1228
1229 return;
1230}
1231
1232#endif /* BLE_INCLUDED */