blob: 09ad112b78e2d3bd42ad6105369b2b8980076d38 [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*******************************************************************************/
Mike J. Chend2710d02014-01-31 18:08:58 -0800405static void gatt_process_find_type_value_rsp (tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800406{
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*******************************************************************************/
Mike J. Chen22df1f72014-01-31 16:37:03 -0800448static void gatt_process_read_info_rsp(tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800449{
450 tGATT_DISC_RES result;
451 UINT8 *p = p_data, uuid_len = 0, type;
452
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700453 if (len < GATT_INFO_RSP_MIN_LEN)
454 {
455 GATT_TRACE_ERROR0("invalid Info Response PDU received, discard.");
456 gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
457 return;
458 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800459 /* unexpected response */
460 if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_CHAR_DSCPT)
461 return;
462
463 STREAM_TO_UINT8(type, p);
464 len -= 1;
465
466 if (type == GATT_INFO_TYPE_PAIR_16)
467 uuid_len = LEN_UUID_16;
468 else if (type == GATT_INFO_TYPE_PAIR_128)
469 uuid_len = LEN_UUID_128;
470
471 while (len >= uuid_len + 2)
472 {
473 STREAM_TO_UINT16 (result.handle, p);
474
475 if (uuid_len > 0)
476 {
477 if (!gatt_parse_uuid_from_cmd(&result.type, uuid_len, &p))
478 break;
479 }
480 else
481 memcpy (&result.type, &p_clcb->uuid, sizeof(tBT_UUID));
482
483 len -= (uuid_len + 2);
484
485 if (p_clcb->p_reg->app_cb.p_disc_res_cb)
486 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
487 }
488
489 p_clcb->s_handle = (result.handle == 0) ? 0 :(result.handle + 1);
490 /* initiate another request */
491 gatt_act_discovery(p_clcb) ;
492}
493/*******************************************************************************
494**
495** Function gatt_proc_disc_error_rsp
496**
497** Description This function process the read by type response and send another
498** request if needed.
499**
500** Returns void.
501**
502*******************************************************************************/
Mike J. Chen22df1f72014-01-31 16:37:03 -0800503static void gatt_proc_disc_error_rsp(tGATT_CLCB *p_clcb, UINT8 opcode, UINT8 reason)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800504{
505 tGATT_STATUS status = (tGATT_STATUS) reason;
506
507 GATT_TRACE_DEBUG2("gatt_proc_disc_error_rsp reason: %02x cmd_code %04x", reason, opcode);
508
509 switch (opcode)
510 {
511 case GATT_REQ_READ_BY_GRP_TYPE:
512 case GATT_REQ_FIND_TYPE_VALUE:
513 case GATT_REQ_READ_BY_TYPE:
514 case GATT_REQ_FIND_INFO:
515 if (reason == GATT_NOT_FOUND)
516 {
517 status = GATT_SUCCESS;
518 GATT_TRACE_DEBUG0("Discovery completed");
519 }
520 break;
521 default:
522 GATT_TRACE_ERROR1("Incorrect discovery opcode %04x", opcode);
523 break;
524 }
525
526 gatt_end_operation(p_clcb, status, NULL);
527}
528
529/*******************************************************************************
530**
531** Function gatt_process_error_rsp
532**
533** Description This function is called to handle the error response
534**
535**
536** Returns void
537**
538*******************************************************************************/
Mike J. Chen22df1f72014-01-31 16:37:03 -0800539static void gatt_process_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800540{
541 UINT8 opcode, reason, * p= p_data;
542 UINT16 handle;
543 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
544
545 GATT_TRACE_DEBUG0("gatt_process_error_rsp ");
546 STREAM_TO_UINT8(opcode, p);
547 STREAM_TO_UINT16(handle, p);
548 STREAM_TO_UINT8(reason, p);
549
550 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)
551 {
Mike J. Chen22df1f72014-01-31 16:37:03 -0800552 gatt_proc_disc_error_rsp(p_clcb, opcode, reason);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800553 }
554 else
555 {
556 if ( (p_clcb->operation == GATTC_OPTYPE_WRITE) &&
557 (p_clcb->op_subtype == GATT_WRITE) &&
558 (opcode == GATT_REQ_PREPARE_WRITE) &&
559 (p_attr) &&
560 (handle == p_attr->handle) )
561 {
562 p_clcb->status = reason;
563 gatt_send_queue_write_cancel(p_tcb, p_clcb, GATT_PREP_WRITE_CANCEL);
564 }
565 else if ((p_clcb->operation == GATTC_OPTYPE_READ) &&
566 ((p_clcb->op_subtype == GATT_READ_CHAR_VALUE_HDL) ||
567 (p_clcb->op_subtype == GATT_READ_BY_HANDLE)) &&
568 (opcode == GATT_REQ_READ_BLOB) &&
569 p_clcb->first_read_blob_after_read &&
570 (reason == GATT_NOT_LONG))
571 {
572 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf);
573 }
574 else
575 gatt_end_operation(p_clcb, reason, NULL);
576 }
577}
578/*******************************************************************************
579**
580** Function gatt_process_prep_write_rsp
581**
582** Description This function is called to handle the read response
583**
584**
585** Returns void
586**
587*******************************************************************************/
588void gatt_process_prep_write_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
589 UINT16 len, UINT8 *p_data)
590{
591 tGATT_VALUE value = {0};
592 UINT8 *p= p_data;
593
594 GATT_TRACE_ERROR2("value resp op_code = %s len = %d", gatt_dbg_op_name(op_code), len);
595
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700596 if (len < GATT_PREP_WRITE_RSP_MIN_LEN)
597 {
598 GATT_TRACE_ERROR0("illegal prepare write response length, discard");
599 gatt_end_operation(p_clcb, GATT_INVALID_PDU, &value);
600 return;
601 }
602
The Android Open Source Project5738f832012-12-12 16:00:35 -0800603 STREAM_TO_UINT16 (value.handle, p);
604 STREAM_TO_UINT16 (value.offset, p);
605
606 value.len = len - 4;
607
608 memcpy (value.value, p, value.len);
609
610 if (p_clcb->op_subtype == GATT_WRITE_PREPARE)
611 {
612 p_clcb->status = GATT_SUCCESS;
613 /* application should verify handle offset
614 and value are matched or not */
615
616 gatt_end_operation(p_clcb, p_clcb->status, &value);
617 }
618 else if (p_clcb->op_subtype == GATT_WRITE )
619 {
620 if (!gatt_check_write_long_terminate(p_tcb, p_clcb, &value))
621 gatt_send_prepare_write(p_tcb, p_clcb);
622 }
623
624}
625/*******************************************************************************
626**
627** Function gatt_process_notification
628**
629** Description This function is called to handle the handle value indication
630** or handle value notification.
631**
632**
633** Returns void
634**
635*******************************************************************************/
636void gatt_process_notification(tGATT_TCB *p_tcb, UINT8 op_code,
637 UINT16 len, UINT8 *p_data)
638{
639 tGATT_VALUE value = {0};
640 tGATT_REG *p_reg;
641 UINT16 conn_id;
642 tGATT_STATUS encrypt_status;
643 UINT8 *p= p_data, i,
644 event = (op_code == GATT_HANDLE_VALUE_NOTIF) ? GATTC_OPTYPE_NOTIFICATION : GATTC_OPTYPE_INDICATION;
645
646 GATT_TRACE_DEBUG0("gatt_process_notification ");
647
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700648 if (len < GATT_NOTIFICATION_MIN_LEN)
649 {
650 GATT_TRACE_ERROR0("illegal notification PDU length, discard");
651 return;
652 }
653
The Android Open Source Project5738f832012-12-12 16:00:35 -0800654 STREAM_TO_UINT16 (value.handle, p);
655 value.len = len - 2;
656 memcpy (value.value, p, value.len);
657
658 if (!GATT_HANDLE_IS_VALID(value.handle))
659 {
660 /* illegal handle, send ack now */
661 if (op_code == GATT_HANDLE_VALUE_IND)
662 attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
663 return;
664 }
665
666 if (event == GATTC_OPTYPE_INDICATION)
667 {
668 if (p_tcb->ind_count)
669 {
670 /* this is an error case that receiving an indication but we
671 still has an indication not being acked yet.
672 For now, just log the error reset the counter.
673 Later we need to disconnect the link unconditionally.
674 */
675 GATT_TRACE_ERROR1("gatt_process_notification rcv Ind. but ind_count=%d (will reset ind_count)", p_tcb->ind_count);
676 }
677 p_tcb->ind_count = 0;
678 }
679
680 /* should notify all registered client with the handle value notificaion/indication
681 Note: need to do the indication count and start timer first then do callback
682 */
683
684 for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++)
685 {
686 if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb && (event == GATTC_OPTYPE_INDICATION))
687 p_tcb->ind_count++;
688 }
689
690 if (event == GATTC_OPTYPE_INDICATION)
691 {
692 /* start a timer for app confirmation */
693 if (p_tcb->ind_count > 0)
694 gatt_start_ind_ack_timer(p_tcb);
695 else /* no app to indicate, or invalid handle */
696 attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
697 }
698
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800699 encrypt_status = gatt_get_link_encrypt_status(p_tcb);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800700 for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++)
701 {
702 if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb)
703 {
704 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800705 (*p_reg->app_cb.p_cmpl_cb) (conn_id, event, encrypt_status, (tGATT_CL_COMPLETE *)&value);
706 }
707 }
708
709}
710
711/*******************************************************************************
712**
713** Function gatt_process_read_by_type_rsp
714**
715** Description This function is called to handle the read by type response.
716** read by type can be used for discovery, or read by type or
717** read characteristic value.
718**
719** Returns void
720**
721*******************************************************************************/
722void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
723 UINT16 len, UINT8 *p_data)
724{
725 tGATT_DISC_RES result;
726 tGATT_DISC_VALUE record_value;
727 UINT8 *p = p_data, value_len, handle_len = 2;
728 UINT16 handle = 0;
729
730 /* discovery procedure and no callback function registered */
731 if (((!p_clcb->p_reg) || (!p_clcb->p_reg->app_cb.p_disc_res_cb)) && (p_clcb->operation == GATTC_OPTYPE_DISCOVERY))
732 return;
733
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700734 if (len < GATT_READ_BY_TYPE_RSP_MIN_LEN)
735 {
736 GATT_TRACE_ERROR0("Illegal ReadByType/ReadByGroupType Response length, discard");
737 gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
738 return;
739 }
740
The Android Open Source Project5738f832012-12-12 16:00:35 -0800741 STREAM_TO_UINT8(value_len, p);
742
743 if ((value_len > (p_tcb->payload_size - 2)) || (value_len > (len-1)) )
744 {
745 /* this is an error case that server's response containing a value length which is larger than MTU-2
746 or value_len > message total length -1 */
747 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)",
748 op_code, value_len, (p_tcb->payload_size - 2), (len-1));
749 gatt_end_operation(p_clcb, GATT_ERROR, NULL);
750 return;
751 }
752
753 if (op_code == GATT_RSP_READ_BY_GRP_TYPE)
754 handle_len = 4;
755
756 value_len -= handle_len; /* substract the handle pairs bytes */
757 len -= 1;
758
759 while (len >= (handle_len + value_len))
760 {
761 STREAM_TO_UINT16(handle, p);
762
763 if (!GATT_HANDLE_IS_VALID(handle))
764 {
765 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
766 return;
767 }
768
769 memset(&result, 0, sizeof(tGATT_DISC_RES));
770 memset(&record_value, 0, sizeof(tGATT_DISC_VALUE));
771
772 result.handle = handle;
773 result.type.len = 2;
774 result.type.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype];
775
776 /* discover all services */
777 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
778 p_clcb->op_subtype == GATT_DISC_SRVC_ALL &&
779 op_code == GATT_RSP_READ_BY_GRP_TYPE)
780 {
781 STREAM_TO_UINT16(handle, p);
782
783 if (!GATT_HANDLE_IS_VALID(handle))
784 {
785 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
786 return;
787 }
788 else
789 {
790 record_value.group_value.e_handle = handle;
791 if (!gatt_parse_uuid_from_cmd(&record_value.group_value.service_type, value_len, &p))
792 {
793 GATT_TRACE_ERROR0("discover all service response parsing failure");
794 break;
795 }
796 }
797 }
798 /* discover included service */
799 else if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->op_subtype == GATT_DISC_INC_SRVC)
800 {
801 STREAM_TO_UINT16(record_value.incl_service.s_handle, p);
802 STREAM_TO_UINT16(record_value.incl_service.e_handle, p);
803
804 if (!GATT_HANDLE_IS_VALID(record_value.incl_service.s_handle) ||
805 !GATT_HANDLE_IS_VALID(record_value.incl_service.e_handle))
806 {
807 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
808 return;
809 }
810
811 if(value_len == 6)
812 {
813 STREAM_TO_UINT16(record_value.incl_service.service_type.uu.uuid16, p);
814 record_value.incl_service.service_type.len = LEN_UUID_16;
815 }
816 else if (value_len == 4)
817 {
818 p_clcb->s_handle = record_value.incl_service.s_handle;
819 p_clcb->read_uuid128.wait_for_read_rsp = TRUE;
820 p_clcb->read_uuid128.next_disc_start_hdl = handle + 1;
821 memcpy(&p_clcb->read_uuid128.result, &result, sizeof(result));
822 memcpy(&p_clcb->read_uuid128.result.value, &record_value, sizeof (result.value));
823 p_clcb->op_subtype |= 0x90;
824 gatt_act_read(p_clcb, 0);
825 return;
826 }
827 else
828 {
829 GATT_TRACE_ERROR1("gatt_process_read_by_type_rsp INCL_SRVC failed with invalid data value_len=%d", value_len);
830 gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p);
831 return;
832 }
833 }
834 /* read by type */
835 else if (p_clcb->operation == GATTC_OPTYPE_READ && p_clcb->op_subtype == GATT_READ_BY_TYPE)
836 {
837 p_clcb->counter = len - 2;
838 p_clcb->s_handle = handle;
839 if ( p_clcb->counter == (p_clcb->p_tcb->payload_size -4))
840 {
841 p_clcb->op_subtype = GATT_READ_BY_HANDLE;
842 if (!p_clcb->p_attr_buf)
843 p_clcb->p_attr_buf = (UINT8 *)GKI_getbuf(GATT_MAX_ATTR_LEN);
844 if (p_clcb->p_attr_buf && p_clcb->counter <= GATT_MAX_ATTR_LEN)
845 {
846 memcpy(p_clcb->p_attr_buf, p, p_clcb->counter);
847 gatt_act_read(p_clcb, p_clcb->counter);
848 }
849 else
850 gatt_end_operation(p_clcb, GATT_INTERNAL_ERROR, (void *)p);
851 }
852 else
853 {
854 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p);
855 }
856 return;
857 }
Andre Eisenbach6975b4d2013-08-05 16:55:38 -0700858 else /* discover characterisitic */
The Android Open Source Project5738f832012-12-12 16:00:35 -0800859 {
860 STREAM_TO_UINT8 (record_value.dclr_value.char_prop, p);
861 STREAM_TO_UINT16(record_value.dclr_value.val_handle, p);
862 if (!GATT_HANDLE_IS_VALID(record_value.dclr_value.val_handle))
863 {
864 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
865 return;
866 }
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800867 if (!gatt_parse_uuid_from_cmd(&record_value.dclr_value.char_uuid, (UINT16)(value_len - 3), &p))
868 {
869 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
870 /* invalid format, and skip the result */
871 return;
872 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800873
874 /* UUID not matching */
875 if (!gatt_uuid_compare(record_value.dclr_value.char_uuid, p_clcb->uuid))
876 {
877 len -= (value_len + 2);
878 continue; /* skip the result, and look for next one */
879 }
880 else if (p_clcb->operation == GATTC_OPTYPE_READ)
881 /* UUID match for read characteristic value */
882 {
883 /* only read the first matching UUID characteristic value, and
884 discard the rest results */
885 p_clcb->s_handle = record_value.dclr_value.val_handle;
886 p_clcb->op_subtype |= 0x80;
887 gatt_act_read(p_clcb, 0);
888 return;
889 }
890 }
891 len -= (value_len + handle_len);
892
893 /* result is (handle, 16bits UUID) pairs */
894 memcpy (&result.value, &record_value, sizeof (result.value));
895
896 /* send callback if is discover procedure */
897 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->p_reg->app_cb.p_disc_res_cb)
898 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
899 }
900
901 p_clcb->s_handle = (handle == 0) ? 0 : (handle + 1);
902
903 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)
904 {
905 /* initiate another request */
906 gatt_act_discovery(p_clcb) ;
907 }
908 else /* read characteristic value */
909 {
910 gatt_act_read(p_clcb, 0);
911 }
912}
913
914/*******************************************************************************
915**
916** Function gatt_process_read_rsp
917**
918** Description This function is called to handle the read BLOB response
919**
920**
921** Returns void
922**
923*******************************************************************************/
Mike J. Chen22df1f72014-01-31 16:37:03 -0800924static void gatt_process_read_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb,
925 UINT16 len, UINT8 *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800926{
927 UINT16 offset = p_clcb->counter;
928 UINT8 * p= p_data;
929
930 if (p_clcb->operation == GATTC_OPTYPE_READ)
931 {
932 if (p_clcb->op_subtype != GATT_READ_BY_HANDLE)
933 {
934 p_clcb->counter = len;
935 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p);
936 }
937 else
938 {
939
940 /* allocate GKI buffer holding up long attribute value */
941 if (!p_clcb->p_attr_buf)
942 p_clcb->p_attr_buf = (UINT8 *)GKI_getbuf(GATT_MAX_ATTR_LEN);
943
944 /* copy attrobute value into cb buffer */
945 if (p_clcb->p_attr_buf && offset < GATT_MAX_ATTR_LEN)
946 {
947 if ((len + offset) > GATT_MAX_ATTR_LEN)
948 len = GATT_MAX_ATTR_LEN - offset;
949
950 p_clcb->counter += len;
951
952 memcpy(p_clcb->p_attr_buf + offset, p, len);
953
954 /* send next request if needed */
955
956 if (len == (p_tcb->payload_size - 1) && /* full packet for read or read blob rsp */
957 len + offset < GATT_MAX_ATTR_LEN)
958 {
959 GATT_TRACE_DEBUG3("full pkt issue read blob for remianing bytes old offset=%d len=%d new offset=%d",
960 offset, len, p_clcb->counter);
961 gatt_act_read(p_clcb, p_clcb->counter);
962 }
963 else /* end of request, send callback */
964 {
965 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf);
966 }
967 }
968 else /* exception, should not happen */
969 {
970 GATT_TRACE_ERROR2("attr offset = %d p_attr_buf = %d ", offset, p_clcb->p_attr_buf);
971 gatt_end_operation(p_clcb, GATT_NO_RESOURCES, (void *)p_clcb->p_attr_buf);
972 }
973 }
974 }
975 else
976 {
977 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
978 p_clcb->op_subtype == GATT_DISC_INC_SRVC &&
979 p_clcb->read_uuid128.wait_for_read_rsp )
980 {
981 p_clcb->s_handle = p_clcb->read_uuid128.next_disc_start_hdl;
982 p_clcb->read_uuid128.wait_for_read_rsp = FALSE;
983 if (len == LEN_UUID_128)
984 {
985
986 memcpy(p_clcb->read_uuid128.result.value.incl_service.service_type.uu.uuid128, p, len);
987 p_clcb->read_uuid128.result.value.incl_service.service_type.len = LEN_UUID_128;
988 if ( p_clcb->p_reg->app_cb.p_disc_res_cb)
989 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &p_clcb->read_uuid128.result);
990 gatt_act_discovery(p_clcb) ;
991 }
992 else
993 {
994 gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p);
995 }
996 }
997 }
998
999}
1000
1001
1002/*******************************************************************************
1003**
1004** Function gatt_process_handle_rsp
1005**
1006** Description This function is called to handle the write response
1007**
1008**
1009** Returns void
1010**
1011*******************************************************************************/
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001012void gatt_process_handle_rsp(tGATT_CLCB *p_clcb)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001013{
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001014 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001015}
1016/*******************************************************************************
1017**
1018** Function gatt_process_mtu_rsp
1019**
1020** Description This function is called to process the configure MTU response.
1021**
1022**
1023** Returns void
1024**
1025*******************************************************************************/
1026void gatt_process_mtu_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
1027{
1028 UINT16 mtu;
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001029 tGATT_STATUS status = GATT_SUCCESS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001030
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001031 if (len < GATT_MTU_RSP_MIN_LEN)
1032 {
1033 GATT_TRACE_ERROR0("invalid MTU response PDU received, discard.");
1034 status = GATT_INVALID_PDU;
1035 }
1036 else
1037 {
The Android Open Source Project5738f832012-12-12 16:00:35 -08001038 STREAM_TO_UINT16(mtu, p_data);
1039
1040 if (mtu < p_tcb->payload_size && mtu >= GATT_DEF_BLE_MTU_SIZE)
1041 p_tcb->payload_size = mtu;
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001042 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001043
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001044 gatt_end_operation(p_clcb, status, NULL);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001045}
1046/*******************************************************************************
1047**
1048** Function gatt_cmd_to_rsp_code
1049**
1050** Description The function convert a ATT command op code into the corresponding
1051** response code assume no error occurs.
1052**
1053** Returns response code.
1054**
1055*******************************************************************************/
1056UINT8 gatt_cmd_to_rsp_code (UINT8 cmd_code)
1057{
1058 UINT8 rsp_code = 0;
1059
1060 if (cmd_code > 1 && cmd_code != GATT_CMD_WRITE)
1061 {
1062 rsp_code = cmd_code + 1;
1063 }
1064 return rsp_code;
1065}
1066/*******************************************************************************
1067**
1068** Function gatt_cl_send_next_cmd_inq
1069**
1070** Description Find next command in queue and sent to server
1071**
1072** Returns TRUE if command sent, otherwise FALSE.
1073**
1074*******************************************************************************/
1075BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb)
1076{
1077 tGATT_CMD_Q *p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1078 BOOLEAN sent = FALSE;
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001079 UINT8 rsp_code;
1080 tGATT_CLCB *p_clcb = NULL;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001081
1082 while (!sent &&
1083 p_tcb->pending_cl_req != p_tcb->next_slot_inq &&
1084 p_cmd->to_send && p_cmd->p_cmd != NULL)
1085 {
1086 sent = attp_send_msg_to_L2CAP(p_tcb, p_cmd->p_cmd);
1087
1088 if (sent)
1089 {
1090 p_cmd->to_send = FALSE;
1091 p_cmd->p_cmd = NULL;
1092
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001093 /* dequeue the request if is write command or sign write */
1094 if (p_cmd->op_code != GATT_CMD_WRITE && p_cmd->op_code != GATT_SIGN_CMD_WRITE)
1095 {
1096 gatt_start_rsp_timer (p_tcb);
1097 }
1098 else
1099 {
1100 p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
1101
1102 /* if no ack needed, keep sending */
1103 sent = FALSE;
1104 p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1105 /* send command complete callback here */
1106 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
1107 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001108 }
1109 else
1110 {
1111 GATT_TRACE_ERROR0("gatt_cl_send_next_cmd_inq: L2CAP sent error");
1112
1113 memset(p_cmd, 0, sizeof(tGATT_CMD_Q));
1114 p_tcb->pending_cl_req ++;
1115 p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1116 }
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001117
The Android Open Source Project5738f832012-12-12 16:00:35 -08001118 }
1119 return sent;
1120}
1121
1122/*******************************************************************************
1123**
1124** Function gatt_client_handle_server_rsp
1125**
1126** Description This function is called to handle the server response to
1127** client.
1128**
1129**
1130** Returns void
1131**
1132*******************************************************************************/
1133void gatt_client_handle_server_rsp (tGATT_TCB *p_tcb, UINT8 op_code,
1134 UINT16 len, UINT8 *p_data)
1135{
1136 tGATT_CLCB *p_clcb = NULL;
1137 UINT8 rsp_code;
1138
1139 if (op_code != GATT_HANDLE_VALUE_IND && op_code != GATT_HANDLE_VALUE_NOTIF)
1140 {
1141 p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
1142
1143 rsp_code = gatt_cmd_to_rsp_code(rsp_code);
1144
1145 if (p_clcb == NULL || (rsp_code != op_code && op_code != GATT_RSP_ERROR))
1146 {
1147 GATT_TRACE_WARNING2 ("ATT - Ignore wrong response. Receives (%02x) \
1148 Request(%02x) Ignored", op_code, rsp_code);
1149
1150 return;
1151 }
1152 else
1153 btu_stop_timer (&p_tcb->rsp_timer_ent);
1154 }
1155 /* the size of the message may not be bigger than the local max PDU size*/
1156 /* The message has to be smaller than the agreed MTU, len does not count op_code */
1157 if (len >= p_tcb->payload_size)
1158 {
1159 GATT_TRACE_ERROR2("invalid response/indicate pkt size: %d, PDU size: %d", len + 1, p_tcb->payload_size);
1160 if (op_code != GATT_HANDLE_VALUE_NOTIF &&
1161 op_code != GATT_HANDLE_VALUE_IND)
1162 gatt_end_operation(p_clcb, GATT_ERROR, NULL);
1163 }
1164 else
1165 {
1166 switch (op_code)
1167 {
1168 case GATT_RSP_ERROR:
Mike J. Chen22df1f72014-01-31 16:37:03 -08001169 gatt_process_error_rsp(p_tcb, p_clcb, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001170 break;
1171
1172 case GATT_RSP_MTU: /* 2 bytes mtu */
1173 gatt_process_mtu_rsp(p_tcb, p_clcb, len ,p_data);
1174 break;
1175
1176 case GATT_RSP_FIND_INFO:
Mike J. Chen22df1f72014-01-31 16:37:03 -08001177 gatt_process_read_info_rsp(p_clcb, len, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001178 break;
1179
1180 case GATT_RSP_READ_BY_TYPE:
1181 case GATT_RSP_READ_BY_GRP_TYPE:
1182 gatt_process_read_by_type_rsp(p_tcb, p_clcb, op_code, len, p_data);
1183 break;
1184
1185 case GATT_RSP_READ:
1186 case GATT_RSP_READ_BLOB:
1187 case GATT_RSP_READ_MULTI:
Mike J. Chen22df1f72014-01-31 16:37:03 -08001188 gatt_process_read_rsp(p_tcb, p_clcb, len, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001189 break;
1190
1191 case GATT_RSP_FIND_TYPE_VALUE: /* disc service with UUID */
Mike J. Chen22df1f72014-01-31 16:37:03 -08001192 gatt_process_find_type_value_rsp(p_clcb, len, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001193 break;
1194
1195 case GATT_RSP_WRITE:
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001196 gatt_process_handle_rsp(p_clcb);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001197 break;
1198
1199 case GATT_RSP_PREPARE_WRITE:
1200 gatt_process_prep_write_rsp(p_tcb, p_clcb, op_code, len, p_data);
1201 break;
1202
1203 case GATT_RSP_EXEC_WRITE:
1204 gatt_end_operation(p_clcb, p_clcb->status, NULL);
1205 break;
1206
1207 case GATT_HANDLE_VALUE_NOTIF:
1208 case GATT_HANDLE_VALUE_IND:
1209 gatt_process_notification(p_tcb, op_code, len, p_data);
1210 break;
1211
1212 default:
1213 GATT_TRACE_ERROR1("Unknown opcode = %d", op_code);
1214 break;
1215 }
1216 }
1217
1218 if (op_code != GATT_HANDLE_VALUE_IND && op_code != GATT_HANDLE_VALUE_NOTIF)
1219 {
1220 gatt_cl_send_next_cmd_inq(p_tcb);
1221 }
1222
1223 return;
1224}
1225
1226#endif /* BLE_INCLUDED */