blob: f678dfce2641009c97c4c417418df5bff55d502a [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>
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -070030#include "bt_utils.h"
Pavlin Radoslavov258c2532015-09-27 20:59:05 -070031#include "bt_common.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080032#include "gatt_int.h"
Priti Aghera636d6712014-12-18 13:55:48 -080033#include "l2c_int.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080034
35#define GATT_WRITE_LONG_HDR_SIZE 5 /* 1 opcode + 2 handle + 2 offset */
36#define GATT_READ_CHAR_VALUE_HDL (GATT_READ_CHAR_VALUE | 0x80)
37#define GATT_READ_INC_SRV_UUID128 (GATT_DISC_INC_SRVC | 0x90)
38
Andre Eisenbachccf9c152013-10-02 15:37:21 -070039#define GATT_PREP_WRITE_RSP_MIN_LEN 4
40#define GATT_NOTIFICATION_MIN_LEN 2
41#define GATT_WRITE_RSP_MIN_LEN 2
42#define GATT_INFO_RSP_MIN_LEN 1
43#define GATT_MTU_RSP_MIN_LEN 2
44#define GATT_READ_BY_TYPE_RSP_MIN_LEN 1
45
The Android Open Source Project5738f832012-12-12 16:00:35 -080046/********************************************************************************
47** G L O B A L G A T T D A T A *
48*********************************************************************************/
49void gatt_send_prepare_write(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb);
50
51UINT8 disc_type_to_att_opcode[GATT_DISC_MAX] =
52{
53 0,
54 GATT_REQ_READ_BY_GRP_TYPE, /* GATT_DISC_SRVC_ALL = 1, */
55 GATT_REQ_FIND_TYPE_VALUE, /* GATT_DISC_SRVC_BY_UUID, */
56 GATT_REQ_READ_BY_TYPE, /* GATT_DISC_INC_SRVC, */
57 GATT_REQ_READ_BY_TYPE, /* GATT_DISC_CHAR, */
58 GATT_REQ_FIND_INFO /* GATT_DISC_CHAR_DSCPT, */
59};
60
61UINT16 disc_type_to_uuid[GATT_DISC_MAX] =
62{
63 0, /* reserved */
64 GATT_UUID_PRI_SERVICE, /* <service> DISC_SRVC_ALL */
65 GATT_UUID_PRI_SERVICE, /* <service> for DISC_SERVC_BY_UUID */
66 GATT_UUID_INCLUDE_SERVICE, /* <include_service> for DISC_INC_SRVC */
67 GATT_UUID_CHAR_DECLARE, /* <characteristic> for DISC_CHAR */
68 0 /* no type filtering for DISC_CHAR_DSCPT */
69};
70
71
72/*******************************************************************************
73**
74** Function gatt_act_discovery
75**
76** Description GATT discovery operation.
77**
78** Returns void.
79**
80*******************************************************************************/
81void gatt_act_discovery(tGATT_CLCB *p_clcb)
82{
83 UINT8 op_code = disc_type_to_att_opcode[p_clcb->op_subtype];
84 tGATT_CL_MSG cl_req;
Andre Eisenbach6975b4d2013-08-05 16:55:38 -070085 tGATT_STATUS st;
The Android Open Source Project5738f832012-12-12 16:00:35 -080086
87 if (p_clcb->s_handle <= p_clcb->e_handle && p_clcb->s_handle != 0)
88 {
89 memset(&cl_req, 0, sizeof(tGATT_CL_MSG));
90
91 cl_req.browse.s_handle = p_clcb->s_handle;
92 cl_req.browse.e_handle = p_clcb->e_handle;
93
94 if (disc_type_to_uuid[p_clcb->op_subtype] != 0)
95 {
96 cl_req.browse.uuid.len = 2;
97 cl_req.browse.uuid.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype];
98 }
99
100 if (p_clcb->op_subtype == GATT_DISC_SRVC_BY_UUID) /* fill in the FindByTypeValue request info*/
101 {
102 cl_req.find_type_value.uuid.len = 2;
103 cl_req.find_type_value.uuid.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype];
104 cl_req.find_type_value.s_handle = p_clcb->s_handle;
105 cl_req.find_type_value.e_handle = p_clcb->e_handle;
106 cl_req.find_type_value.value_len = p_clcb->uuid.len;
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -0700107 /* if service type is 32 bits UUID, convert it now */
108 if (p_clcb->uuid.len == LEN_UUID_32)
109 {
110 cl_req.find_type_value.value_len = LEN_UUID_128;
111 gatt_convert_uuid32_to_uuid128(cl_req.find_type_value.value, p_clcb->uuid.uu.uuid32);
112 }
113 else
The Android Open Source Project5738f832012-12-12 16:00:35 -0800114 memcpy (cl_req.find_type_value.value, &p_clcb->uuid.uu, p_clcb->uuid.len);
115 }
116
Andre Eisenbach6975b4d2013-08-05 16:55:38 -0700117 st = attp_send_cl_msg(p_clcb->p_tcb, p_clcb->clcb_idx, op_code, &cl_req);
118
119 if (st != GATT_SUCCESS && st != GATT_CMD_STARTED)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800120 {
121 gatt_end_operation(p_clcb, GATT_ERROR, NULL);
122 }
123 }
124 else /* end of handle range */
125 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
126}
127
128/*******************************************************************************
129**
130** Function gatt_act_read
131**
132** Description GATT read operation.
133**
134** Returns void.
135**
136*******************************************************************************/
137void gatt_act_read (tGATT_CLCB *p_clcb, UINT16 offset)
138{
139 tGATT_TCB *p_tcb = p_clcb->p_tcb;
140 UINT8 rt = GATT_INTERNAL_ERROR;
141 tGATT_CL_MSG msg;
142 UINT8 op_code = 0;
143
144 memset (&msg, 0, sizeof(tGATT_CL_MSG));
145
146 switch (p_clcb->op_subtype)
147 {
148 case GATT_READ_CHAR_VALUE:
149 case GATT_READ_BY_TYPE:
150 op_code = GATT_REQ_READ_BY_TYPE;
151 msg.browse.s_handle = p_clcb->s_handle;
152 msg.browse.e_handle = p_clcb->e_handle;
153 if (p_clcb->op_subtype == GATT_READ_BY_TYPE)
154 memcpy(&msg.browse.uuid, &p_clcb->uuid, sizeof(tBT_UUID));
155 else
156 {
157 msg.browse.uuid.len = LEN_UUID_16;
158 msg.browse.uuid.uu.uuid16 = GATT_UUID_CHAR_DECLARE;
159 }
160 break;
161
162 case GATT_READ_CHAR_VALUE_HDL:
163 case GATT_READ_BY_HANDLE:
164 if (!p_clcb->counter)
165 {
166 op_code = GATT_REQ_READ;
167 msg.handle = p_clcb->s_handle;
168 }
169 else
170 {
171 if (!p_clcb->first_read_blob_after_read)
172 p_clcb->first_read_blob_after_read = TRUE;
173 else
174 p_clcb->first_read_blob_after_read = FALSE;
175
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700176 GATT_TRACE_DEBUG("gatt_act_read first_read_blob_after_read=%d",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800177 p_clcb->first_read_blob_after_read);
178 op_code = GATT_REQ_READ_BLOB;
179 msg.read_blob.offset = offset;
180 msg.read_blob.handle = p_clcb->s_handle;
181 }
182 p_clcb->op_subtype &= ~ 0x80;
183 break;
184
185 case GATT_READ_PARTIAL:
186 op_code = GATT_REQ_READ_BLOB;
187 msg.read_blob.handle = p_clcb->s_handle;
188 msg.read_blob.offset = offset;
189 break;
190
191 case GATT_READ_MULTIPLE:
192 op_code = GATT_REQ_READ_MULTI;
193 memcpy (&msg.read_multi, p_clcb->p_attr_buf, sizeof(tGATT_READ_MULTI));
194 break;
195
196 case GATT_READ_INC_SRV_UUID128:
197 op_code = GATT_REQ_READ;
198 msg.handle = p_clcb->s_handle;
199 p_clcb->op_subtype &= ~ 0x90;
200 break;
201
202 default:
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700203 GATT_TRACE_ERROR("Unknown read type: %d", p_clcb->op_subtype);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800204 break;
205 }
206
Andre Eisenbach6975b4d2013-08-05 16:55:38 -0700207 if (op_code != 0)
208 rt = attp_send_cl_msg(p_tcb, p_clcb->clcb_idx, op_code, &msg);
209
210 if ( op_code == 0 || (rt != GATT_SUCCESS && rt != GATT_CMD_STARTED))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800211 {
212 gatt_end_operation(p_clcb, rt, NULL);
213 }
214}
215
216/*******************************************************************************
217**
218** Function gatt_act_write
219**
220** Description GATT write operation.
221**
222** Returns void.
223**
224*******************************************************************************/
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800225void gatt_act_write (tGATT_CLCB *p_clcb, UINT8 sec_act)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800226{
227 tGATT_TCB *p_tcb = p_clcb->p_tcb;
Andre Eisenbach6975b4d2013-08-05 16:55:38 -0700228 UINT8 rt = GATT_SUCCESS, op_code = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800229 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
230
231 if (p_attr)
232 {
233 switch (p_clcb->op_subtype)
234 {
235 case GATT_WRITE_NO_RSP:
236 p_clcb->s_handle = p_attr->handle;
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800237 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 -0800238 rt = gatt_send_write_msg(p_tcb,
239 p_clcb->clcb_idx,
240 op_code,
241 p_attr->handle,
242 p_attr->len,
243 0,
244 p_attr->value);
245 break;
246
247 case GATT_WRITE:
248 if (p_attr->len <= (p_tcb->payload_size - GATT_HDR_SIZE))
249 {
250 p_clcb->s_handle = p_attr->handle;
251
252 rt = gatt_send_write_msg(p_tcb,
253 p_clcb->clcb_idx,
254 GATT_REQ_WRITE,
255 p_attr->handle,
256 p_attr->len,
257 0,
258 p_attr->value);
259 }
260 else /* prepare write for long attribute */
261 {
262 gatt_send_prepare_write(p_tcb, p_clcb);
263 }
264 break;
265
266 case GATT_WRITE_PREPARE:
267 gatt_send_prepare_write(p_tcb, p_clcb);
268 break;
269
270 default:
271 rt = GATT_INTERNAL_ERROR;
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700272 GATT_TRACE_ERROR("Unknown write type: %d", p_clcb->op_subtype);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800273 break;
274 }
275 }
276 else
277 rt = GATT_INTERNAL_ERROR;
278
Andre Eisenbach17b04bd2014-03-28 14:54:22 -0700279 if ((rt != GATT_SUCCESS && rt != GATT_CMD_STARTED && rt != GATT_CONGESTED)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800280 || (rt != GATT_CMD_STARTED && p_clcb->op_subtype == GATT_WRITE_NO_RSP))
281 {
282 if (rt != GATT_SUCCESS)
283 {
Andre Eisenbach5d5b0412015-01-12 13:34:01 -0800284 GATT_TRACE_ERROR("gatt_act_write() failed op_code=0x%x rt=%d", op_code, rt);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800285 }
286 gatt_end_operation(p_clcb, rt, NULL);
287 }
288}
289/*******************************************************************************
290**
291** Function gatt_send_queue_write_cancel
292**
293** Description send queue write cancel
294**
295** Returns void.
296**
297*******************************************************************************/
298void gatt_send_queue_write_cancel (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, tGATT_EXEC_FLAG flag)
299{
300 UINT8 rt ;
301
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700302 GATT_TRACE_DEBUG("gatt_send_queue_write_cancel ");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800303
304 rt = attp_send_cl_msg(p_tcb, p_clcb->clcb_idx, GATT_REQ_EXEC_WRITE, (tGATT_CL_MSG *)&flag);
305
306 if (rt != GATT_SUCCESS)
307 {
308 gatt_end_operation(p_clcb, rt, NULL);
309 }
310}
311/*******************************************************************************
312**
313** Function gatt_check_write_long_terminate
314**
315** Description To terminate write long or not.
316**
317** Returns TRUE: write long is terminated; FALSE keep sending.
318**
319*******************************************************************************/
320BOOLEAN gatt_check_write_long_terminate(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, tGATT_VALUE *p_rsp_value)
321{
322 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
323 BOOLEAN exec = FALSE;
324 tGATT_EXEC_FLAG flag = GATT_PREP_WRITE_EXEC;
325
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700326 GATT_TRACE_DEBUG("gatt_check_write_long_terminate ");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800327 /* check the first write response status */
328 if (p_rsp_value != NULL)
329 {
330 if (p_rsp_value->handle != p_attr->handle ||
331 p_rsp_value->len != p_clcb->counter ||
332 memcmp(p_rsp_value->value, p_attr->value + p_attr->offset, p_rsp_value->len))
333 {
334 /* data does not match */
335 p_clcb->status = GATT_ERROR;
336 flag = GATT_PREP_WRITE_CANCEL;
337 exec = TRUE;
338 }
339 else /* response checking is good */
340 {
341 p_clcb->status = GATT_SUCCESS;
342 /* update write offset and check if end of attribute value */
343 if ((p_attr->offset += p_rsp_value->len) >= p_attr->len)
344 exec = TRUE;
345 }
346 }
347 if (exec)
348 {
349 gatt_send_queue_write_cancel (p_tcb, p_clcb, flag);
350 return TRUE;
351 }
352 return FALSE;
353}
354/*******************************************************************************
355**
356** Function gatt_send_prepare_write
357**
358** Description Send prepare write.
359**
360** Returns void.
361**
362*******************************************************************************/
363void gatt_send_prepare_write(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb)
364{
365 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
366 UINT16 to_send, offset;
367 UINT8 rt = GATT_SUCCESS;
368 UINT8 type = p_clcb->op_subtype;
369
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700370 GATT_TRACE_DEBUG("gatt_send_prepare_write type=0x%x", type );
The Android Open Source Project5738f832012-12-12 16:00:35 -0800371 to_send = p_attr->len - p_attr->offset;
372
373 if (to_send > (p_tcb->payload_size - GATT_WRITE_LONG_HDR_SIZE)) /* 2 = UINT16 offset bytes */
374 to_send = p_tcb->payload_size - GATT_WRITE_LONG_HDR_SIZE;
375
376 p_clcb->s_handle = p_attr->handle;
377
378 offset = p_attr->offset;
379 if (type == GATT_WRITE_PREPARE)
380 {
381 offset += p_clcb->start_offset;
382 }
383
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700384 GATT_TRACE_DEBUG("offset =0x%x len=%d", offset, to_send );
The Android Open Source Project5738f832012-12-12 16:00:35 -0800385
386 rt = gatt_send_write_msg(p_tcb,
387 p_clcb->clcb_idx,
388 GATT_REQ_PREPARE_WRITE,
389 p_attr->handle,
390 to_send, /* length */
391 offset, /* used as offset */
392 p_attr->value + p_attr->offset); /* data */
393
394 /* remember the write long attribute length */
395 p_clcb->counter = to_send;
396
Andre Eisenbach6975b4d2013-08-05 16:55:38 -0700397 if (rt != GATT_SUCCESS && rt != GATT_CMD_STARTED)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800398 {
399 gatt_end_operation(p_clcb, rt, NULL);
400 }
401}
402
The Android Open Source Project5738f832012-12-12 16:00:35 -0800403
The Android Open Source Project5738f832012-12-12 16:00:35 -0800404/*******************************************************************************
405**
406** Function gatt_process_find_type_value_rsp
407**
408** Description This function is called to handle find by type value response.
409**
410**
411** Returns void
412**
413*******************************************************************************/
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -0700414void gatt_process_find_type_value_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800415{
416 tGATT_DISC_RES result;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800417 UINT8 *p = p_data;
418
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -0700419 UNUSED(p_tcb);
420
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700421 GATT_TRACE_DEBUG("gatt_process_find_type_value_rsp ");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800422 /* unexpected response */
423 if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_SRVC_BY_UUID)
424 return;
425
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800426 memset (&result, 0, sizeof(tGATT_DISC_RES));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800427 result.type.len = 2;
428 result.type.uu.uuid16 = GATT_UUID_PRI_SERVICE;
429
430 /* returns a series of handle ranges */
431 while (len >= 4)
432 {
433 STREAM_TO_UINT16 (result.handle, p);
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800434 STREAM_TO_UINT16 (result.value.group_value.e_handle, p);
435 memcpy (&result.value.group_value.service_type, &p_clcb->uuid, sizeof(tBT_UUID));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800436
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800437 len -= 4;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800438
439 if (p_clcb->p_reg->app_cb.p_disc_res_cb)
440 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
441 }
442
443 /* last handle + 1 */
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800444 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 -0800445 /* initiate another request */
446 gatt_act_discovery(p_clcb) ;
447}
448/*******************************************************************************
449**
450** Function gatt_process_read_info_rsp
451**
452** Description This function is called to handle the read information
453** response.
454**
455**
456** Returns void
457**
458*******************************************************************************/
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -0700459void gatt_process_read_info_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
460 UINT16 len, UINT8 *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800461{
462 tGATT_DISC_RES result;
463 UINT8 *p = p_data, uuid_len = 0, type;
464
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -0700465 UNUSED(p_tcb);
466 UNUSED(op_code);
467
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700468 if (len < GATT_INFO_RSP_MIN_LEN)
469 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700470 GATT_TRACE_ERROR("invalid Info Response PDU received, discard.");
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700471 gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
472 return;
473 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800474 /* unexpected response */
475 if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_CHAR_DSCPT)
476 return;
477
478 STREAM_TO_UINT8(type, p);
479 len -= 1;
480
481 if (type == GATT_INFO_TYPE_PAIR_16)
482 uuid_len = LEN_UUID_16;
483 else if (type == GATT_INFO_TYPE_PAIR_128)
484 uuid_len = LEN_UUID_128;
485
486 while (len >= uuid_len + 2)
487 {
488 STREAM_TO_UINT16 (result.handle, p);
489
490 if (uuid_len > 0)
491 {
492 if (!gatt_parse_uuid_from_cmd(&result.type, uuid_len, &p))
493 break;
494 }
495 else
496 memcpy (&result.type, &p_clcb->uuid, sizeof(tBT_UUID));
497
498 len -= (uuid_len + 2);
499
500 if (p_clcb->p_reg->app_cb.p_disc_res_cb)
501 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
502 }
503
504 p_clcb->s_handle = (result.handle == 0) ? 0 :(result.handle + 1);
505 /* initiate another request */
506 gatt_act_discovery(p_clcb) ;
507}
508/*******************************************************************************
509**
510** Function gatt_proc_disc_error_rsp
511**
512** Description This function process the read by type response and send another
513** request if needed.
514**
515** Returns void.
516**
517*******************************************************************************/
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -0700518void gatt_proc_disc_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 opcode,
519 UINT16 handle, UINT8 reason)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800520{
521 tGATT_STATUS status = (tGATT_STATUS) reason;
522
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -0700523 UNUSED(p_tcb);
524 UNUSED(handle);
525
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700526 GATT_TRACE_DEBUG("gatt_proc_disc_error_rsp reason: %02x cmd_code %04x", reason, opcode);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800527
528 switch (opcode)
529 {
530 case GATT_REQ_READ_BY_GRP_TYPE:
531 case GATT_REQ_FIND_TYPE_VALUE:
532 case GATT_REQ_READ_BY_TYPE:
533 case GATT_REQ_FIND_INFO:
534 if (reason == GATT_NOT_FOUND)
535 {
536 status = GATT_SUCCESS;
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700537 GATT_TRACE_DEBUG("Discovery completed");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800538 }
539 break;
540 default:
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700541 GATT_TRACE_ERROR("Incorrect discovery opcode %04x", opcode);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800542 break;
543 }
544
545 gatt_end_operation(p_clcb, status, NULL);
546}
547
548/*******************************************************************************
549**
550** Function gatt_process_error_rsp
551**
552** Description This function is called to handle the error response
553**
554**
555** Returns void
556**
557*******************************************************************************/
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -0700558void gatt_process_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
559 UINT16 len, UINT8 *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800560{
561 UINT8 opcode, reason, * p= p_data;
562 UINT16 handle;
563 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
564
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -0700565 UNUSED(op_code);
566 UNUSED(len);
567
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700568 GATT_TRACE_DEBUG("gatt_process_error_rsp ");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800569 STREAM_TO_UINT8(opcode, p);
570 STREAM_TO_UINT16(handle, p);
571 STREAM_TO_UINT8(reason, p);
572
573 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)
574 {
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -0700575 gatt_proc_disc_error_rsp(p_tcb, p_clcb, opcode, handle, reason);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800576 }
577 else
578 {
579 if ( (p_clcb->operation == GATTC_OPTYPE_WRITE) &&
580 (p_clcb->op_subtype == GATT_WRITE) &&
581 (opcode == GATT_REQ_PREPARE_WRITE) &&
582 (p_attr) &&
583 (handle == p_attr->handle) )
584 {
585 p_clcb->status = reason;
586 gatt_send_queue_write_cancel(p_tcb, p_clcb, GATT_PREP_WRITE_CANCEL);
587 }
588 else if ((p_clcb->operation == GATTC_OPTYPE_READ) &&
589 ((p_clcb->op_subtype == GATT_READ_CHAR_VALUE_HDL) ||
590 (p_clcb->op_subtype == GATT_READ_BY_HANDLE)) &&
591 (opcode == GATT_REQ_READ_BLOB) &&
592 p_clcb->first_read_blob_after_read &&
593 (reason == GATT_NOT_LONG))
594 {
595 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf);
596 }
597 else
598 gatt_end_operation(p_clcb, reason, NULL);
599 }
600}
601/*******************************************************************************
602**
603** Function gatt_process_prep_write_rsp
604**
605** Description This function is called to handle the read response
606**
607**
608** Returns void
609**
610*******************************************************************************/
611void gatt_process_prep_write_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
612 UINT16 len, UINT8 *p_data)
613{
614 tGATT_VALUE value = {0};
615 UINT8 *p= p_data;
616
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700617 GATT_TRACE_ERROR("value resp op_code = %s len = %d", gatt_dbg_op_name(op_code), len);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800618
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700619 if (len < GATT_PREP_WRITE_RSP_MIN_LEN)
620 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700621 GATT_TRACE_ERROR("illegal prepare write response length, discard");
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700622 gatt_end_operation(p_clcb, GATT_INVALID_PDU, &value);
623 return;
624 }
625
The Android Open Source Project5738f832012-12-12 16:00:35 -0800626 STREAM_TO_UINT16 (value.handle, p);
627 STREAM_TO_UINT16 (value.offset, p);
628
629 value.len = len - 4;
630
631 memcpy (value.value, p, value.len);
632
633 if (p_clcb->op_subtype == GATT_WRITE_PREPARE)
634 {
635 p_clcb->status = GATT_SUCCESS;
636 /* application should verify handle offset
637 and value are matched or not */
638
639 gatt_end_operation(p_clcb, p_clcb->status, &value);
640 }
641 else if (p_clcb->op_subtype == GATT_WRITE )
642 {
643 if (!gatt_check_write_long_terminate(p_tcb, p_clcb, &value))
644 gatt_send_prepare_write(p_tcb, p_clcb);
645 }
646
647}
648/*******************************************************************************
649**
650** Function gatt_process_notification
651**
652** Description This function is called to handle the handle value indication
653** or handle value notification.
654**
655**
656** Returns void
657**
658*******************************************************************************/
659void gatt_process_notification(tGATT_TCB *p_tcb, UINT8 op_code,
660 UINT16 len, UINT8 *p_data)
661{
662 tGATT_VALUE value = {0};
663 tGATT_REG *p_reg;
664 UINT16 conn_id;
665 tGATT_STATUS encrypt_status;
666 UINT8 *p= p_data, i,
667 event = (op_code == GATT_HANDLE_VALUE_NOTIF) ? GATTC_OPTYPE_NOTIFICATION : GATTC_OPTYPE_INDICATION;
668
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700669 GATT_TRACE_DEBUG("gatt_process_notification ");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800670
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700671 if (len < GATT_NOTIFICATION_MIN_LEN)
672 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700673 GATT_TRACE_ERROR("illegal notification PDU length, discard");
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700674 return;
675 }
676
The Android Open Source Project5738f832012-12-12 16:00:35 -0800677 STREAM_TO_UINT16 (value.handle, p);
678 value.len = len - 2;
679 memcpy (value.value, p, value.len);
680
681 if (!GATT_HANDLE_IS_VALID(value.handle))
682 {
683 /* illegal handle, send ack now */
684 if (op_code == GATT_HANDLE_VALUE_IND)
685 attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
686 return;
687 }
688
689 if (event == GATTC_OPTYPE_INDICATION)
690 {
691 if (p_tcb->ind_count)
692 {
693 /* this is an error case that receiving an indication but we
694 still has an indication not being acked yet.
695 For now, just log the error reset the counter.
696 Later we need to disconnect the link unconditionally.
697 */
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700698 GATT_TRACE_ERROR("gatt_process_notification rcv Ind. but ind_count=%d (will reset ind_count)", p_tcb->ind_count);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800699 }
700 p_tcb->ind_count = 0;
701 }
702
703 /* should notify all registered client with the handle value notificaion/indication
704 Note: need to do the indication count and start timer first then do callback
705 */
706
707 for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++)
708 {
709 if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb && (event == GATTC_OPTYPE_INDICATION))
710 p_tcb->ind_count++;
711 }
712
713 if (event == GATTC_OPTYPE_INDICATION)
714 {
715 /* start a timer for app confirmation */
716 if (p_tcb->ind_count > 0)
717 gatt_start_ind_ack_timer(p_tcb);
718 else /* no app to indicate, or invalid handle */
719 attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
720 }
721
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800722 encrypt_status = gatt_get_link_encrypt_status(p_tcb);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800723 for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++)
724 {
725 if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb)
726 {
727 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800728 (*p_reg->app_cb.p_cmpl_cb) (conn_id, event, encrypt_status, (tGATT_CL_COMPLETE *)&value);
729 }
730 }
731
732}
733
734/*******************************************************************************
735**
736** Function gatt_process_read_by_type_rsp
737**
738** Description This function is called to handle the read by type response.
739** read by type can be used for discovery, or read by type or
740** read characteristic value.
741**
742** Returns void
743**
744*******************************************************************************/
745void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
746 UINT16 len, UINT8 *p_data)
747{
748 tGATT_DISC_RES result;
749 tGATT_DISC_VALUE record_value;
750 UINT8 *p = p_data, value_len, handle_len = 2;
751 UINT16 handle = 0;
752
753 /* discovery procedure and no callback function registered */
754 if (((!p_clcb->p_reg) || (!p_clcb->p_reg->app_cb.p_disc_res_cb)) && (p_clcb->operation == GATTC_OPTYPE_DISCOVERY))
755 return;
756
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700757 if (len < GATT_READ_BY_TYPE_RSP_MIN_LEN)
758 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700759 GATT_TRACE_ERROR("Illegal ReadByType/ReadByGroupType Response length, discard");
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700760 gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
761 return;
762 }
763
The Android Open Source Project5738f832012-12-12 16:00:35 -0800764 STREAM_TO_UINT8(value_len, p);
765
766 if ((value_len > (p_tcb->payload_size - 2)) || (value_len > (len-1)) )
767 {
768 /* this is an error case that server's response containing a value length which is larger than MTU-2
769 or value_len > message total length -1 */
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700770 GATT_TRACE_ERROR("gatt_process_read_by_type_rsp: Discard response op_code=%d vale_len=%d > (MTU-2=%d or msg_len-1=%d)",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800771 op_code, value_len, (p_tcb->payload_size - 2), (len-1));
772 gatt_end_operation(p_clcb, GATT_ERROR, NULL);
773 return;
774 }
775
776 if (op_code == GATT_RSP_READ_BY_GRP_TYPE)
777 handle_len = 4;
778
779 value_len -= handle_len; /* substract the handle pairs bytes */
780 len -= 1;
781
782 while (len >= (handle_len + value_len))
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
792 memset(&result, 0, sizeof(tGATT_DISC_RES));
793 memset(&record_value, 0, sizeof(tGATT_DISC_VALUE));
794
795 result.handle = handle;
796 result.type.len = 2;
797 result.type.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype];
798
799 /* discover all services */
800 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
801 p_clcb->op_subtype == GATT_DISC_SRVC_ALL &&
802 op_code == GATT_RSP_READ_BY_GRP_TYPE)
803 {
804 STREAM_TO_UINT16(handle, p);
805
806 if (!GATT_HANDLE_IS_VALID(handle))
807 {
808 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
809 return;
810 }
811 else
812 {
813 record_value.group_value.e_handle = handle;
814 if (!gatt_parse_uuid_from_cmd(&record_value.group_value.service_type, value_len, &p))
815 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700816 GATT_TRACE_ERROR("discover all service response parsing failure");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800817 break;
818 }
819 }
820 }
821 /* discover included service */
822 else if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->op_subtype == GATT_DISC_INC_SRVC)
823 {
824 STREAM_TO_UINT16(record_value.incl_service.s_handle, p);
825 STREAM_TO_UINT16(record_value.incl_service.e_handle, p);
826
827 if (!GATT_HANDLE_IS_VALID(record_value.incl_service.s_handle) ||
828 !GATT_HANDLE_IS_VALID(record_value.incl_service.e_handle))
829 {
830 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
831 return;
832 }
833
834 if(value_len == 6)
835 {
836 STREAM_TO_UINT16(record_value.incl_service.service_type.uu.uuid16, p);
837 record_value.incl_service.service_type.len = LEN_UUID_16;
838 }
839 else if (value_len == 4)
840 {
841 p_clcb->s_handle = record_value.incl_service.s_handle;
842 p_clcb->read_uuid128.wait_for_read_rsp = TRUE;
843 p_clcb->read_uuid128.next_disc_start_hdl = handle + 1;
844 memcpy(&p_clcb->read_uuid128.result, &result, sizeof(result));
845 memcpy(&p_clcb->read_uuid128.result.value, &record_value, sizeof (result.value));
846 p_clcb->op_subtype |= 0x90;
847 gatt_act_read(p_clcb, 0);
848 return;
849 }
850 else
851 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700852 GATT_TRACE_ERROR("gatt_process_read_by_type_rsp INCL_SRVC failed with invalid data value_len=%d", value_len);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800853 gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p);
854 return;
855 }
856 }
857 /* read by type */
858 else if (p_clcb->operation == GATTC_OPTYPE_READ && p_clcb->op_subtype == GATT_READ_BY_TYPE)
859 {
860 p_clcb->counter = len - 2;
861 p_clcb->s_handle = handle;
862 if ( p_clcb->counter == (p_clcb->p_tcb->payload_size -4))
863 {
864 p_clcb->op_subtype = GATT_READ_BY_HANDLE;
865 if (!p_clcb->p_attr_buf)
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800866 p_clcb->p_attr_buf = (UINT8 *)osi_malloc(GATT_MAX_ATTR_LEN);
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800867 if (p_clcb->counter <= GATT_MAX_ATTR_LEN) {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800868 memcpy(p_clcb->p_attr_buf, p, p_clcb->counter);
869 gatt_act_read(p_clcb, p_clcb->counter);
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800870 } else {
871 gatt_end_operation(p_clcb, GATT_INTERNAL_ERROR, (void *)p);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800872 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800873 }
874 else
875 {
876 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p);
877 }
878 return;
879 }
Andre Eisenbach6975b4d2013-08-05 16:55:38 -0700880 else /* discover characterisitic */
The Android Open Source Project5738f832012-12-12 16:00:35 -0800881 {
882 STREAM_TO_UINT8 (record_value.dclr_value.char_prop, p);
883 STREAM_TO_UINT16(record_value.dclr_value.val_handle, p);
884 if (!GATT_HANDLE_IS_VALID(record_value.dclr_value.val_handle))
885 {
886 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
887 return;
888 }
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800889 if (!gatt_parse_uuid_from_cmd(&record_value.dclr_value.char_uuid, (UINT16)(value_len - 3), &p))
890 {
891 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
892 /* invalid format, and skip the result */
893 return;
894 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800895
896 /* UUID not matching */
897 if (!gatt_uuid_compare(record_value.dclr_value.char_uuid, p_clcb->uuid))
898 {
899 len -= (value_len + 2);
900 continue; /* skip the result, and look for next one */
901 }
902 else if (p_clcb->operation == GATTC_OPTYPE_READ)
903 /* UUID match for read characteristic value */
904 {
905 /* only read the first matching UUID characteristic value, and
906 discard the rest results */
907 p_clcb->s_handle = record_value.dclr_value.val_handle;
908 p_clcb->op_subtype |= 0x80;
909 gatt_act_read(p_clcb, 0);
910 return;
911 }
912 }
913 len -= (value_len + handle_len);
914
915 /* result is (handle, 16bits UUID) pairs */
916 memcpy (&result.value, &record_value, sizeof (result.value));
917
918 /* send callback if is discover procedure */
919 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->p_reg->app_cb.p_disc_res_cb)
920 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
921 }
922
923 p_clcb->s_handle = (handle == 0) ? 0 : (handle + 1);
924
925 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)
926 {
927 /* initiate another request */
928 gatt_act_discovery(p_clcb) ;
929 }
930 else /* read characteristic value */
931 {
932 gatt_act_read(p_clcb, 0);
933 }
934}
935
936/*******************************************************************************
937**
938** Function gatt_process_read_rsp
939**
940** Description This function is called to handle the read BLOB response
941**
942**
943** Returns void
944**
945*******************************************************************************/
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -0700946void gatt_process_read_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code,
947 UINT16 len, UINT8 *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800948{
949 UINT16 offset = p_clcb->counter;
950 UINT8 * p= p_data;
951
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -0700952 UNUSED(op_code);
953
The Android Open Source Project5738f832012-12-12 16:00:35 -0800954 if (p_clcb->operation == GATTC_OPTYPE_READ)
955 {
956 if (p_clcb->op_subtype != GATT_READ_BY_HANDLE)
957 {
958 p_clcb->counter = len;
959 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p);
960 }
961 else
962 {
963
964 /* allocate GKI buffer holding up long attribute value */
965 if (!p_clcb->p_attr_buf)
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800966 p_clcb->p_attr_buf = (UINT8 *)osi_malloc(GATT_MAX_ATTR_LEN);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800967
968 /* copy attrobute value into cb buffer */
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800969 if (offset < GATT_MAX_ATTR_LEN) {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800970 if ((len + offset) > GATT_MAX_ATTR_LEN)
971 len = GATT_MAX_ATTR_LEN - offset;
972
973 p_clcb->counter += len;
974
975 memcpy(p_clcb->p_attr_buf + offset, p, len);
976
977 /* send next request if needed */
978
979 if (len == (p_tcb->payload_size - 1) && /* full packet for read or read blob rsp */
980 len + offset < GATT_MAX_ATTR_LEN)
981 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700982 GATT_TRACE_DEBUG("full pkt issue read blob for remianing bytes old offset=%d len=%d new offset=%d",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800983 offset, len, p_clcb->counter);
984 gatt_act_read(p_clcb, p_clcb->counter);
985 }
986 else /* end of request, send callback */
987 {
988 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf);
989 }
990 }
991 else /* exception, should not happen */
992 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700993 GATT_TRACE_ERROR("attr offset = %d p_attr_buf = %d ", offset, p_clcb->p_attr_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800994 gatt_end_operation(p_clcb, GATT_NO_RESOURCES, (void *)p_clcb->p_attr_buf);
995 }
996 }
997 }
998 else
999 {
1000 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
1001 p_clcb->op_subtype == GATT_DISC_INC_SRVC &&
1002 p_clcb->read_uuid128.wait_for_read_rsp )
1003 {
1004 p_clcb->s_handle = p_clcb->read_uuid128.next_disc_start_hdl;
1005 p_clcb->read_uuid128.wait_for_read_rsp = FALSE;
1006 if (len == LEN_UUID_128)
1007 {
1008
1009 memcpy(p_clcb->read_uuid128.result.value.incl_service.service_type.uu.uuid128, p, len);
1010 p_clcb->read_uuid128.result.value.incl_service.service_type.len = LEN_UUID_128;
1011 if ( p_clcb->p_reg->app_cb.p_disc_res_cb)
1012 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &p_clcb->read_uuid128.result);
1013 gatt_act_discovery(p_clcb) ;
1014 }
1015 else
1016 {
1017 gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p);
1018 }
1019 }
1020 }
1021
1022}
1023
1024
1025/*******************************************************************************
1026**
1027** Function gatt_process_handle_rsp
1028**
1029** Description This function is called to handle the write response
1030**
1031**
1032** Returns void
1033**
1034*******************************************************************************/
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001035void gatt_process_handle_rsp(tGATT_CLCB *p_clcb)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001036{
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001037 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001038}
1039/*******************************************************************************
1040**
1041** Function gatt_process_mtu_rsp
1042**
1043** Description This function is called to process the configure MTU response.
1044**
1045**
1046** Returns void
1047**
1048*******************************************************************************/
1049void gatt_process_mtu_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
1050{
1051 UINT16 mtu;
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001052 tGATT_STATUS status = GATT_SUCCESS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001053
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001054 if (len < GATT_MTU_RSP_MIN_LEN)
1055 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001056 GATT_TRACE_ERROR("invalid MTU response PDU received, discard.");
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001057 status = GATT_INVALID_PDU;
1058 }
1059 else
1060 {
The Android Open Source Project5738f832012-12-12 16:00:35 -08001061 STREAM_TO_UINT16(mtu, p_data);
1062
1063 if (mtu < p_tcb->payload_size && mtu >= GATT_DEF_BLE_MTU_SIZE)
1064 p_tcb->payload_size = mtu;
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001065 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001066
Priti Aghera636d6712014-12-18 13:55:48 -08001067 l2cble_set_fixed_channel_tx_data_length(p_tcb->peer_bda, L2CAP_ATT_CID, p_tcb->payload_size);
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001068 gatt_end_operation(p_clcb, status, NULL);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001069}
1070/*******************************************************************************
1071**
1072** Function gatt_cmd_to_rsp_code
1073**
1074** Description The function convert a ATT command op code into the corresponding
1075** response code assume no error occurs.
1076**
1077** Returns response code.
1078**
1079*******************************************************************************/
1080UINT8 gatt_cmd_to_rsp_code (UINT8 cmd_code)
1081{
1082 UINT8 rsp_code = 0;
1083
1084 if (cmd_code > 1 && cmd_code != GATT_CMD_WRITE)
1085 {
1086 rsp_code = cmd_code + 1;
1087 }
1088 return rsp_code;
1089}
1090/*******************************************************************************
1091**
1092** Function gatt_cl_send_next_cmd_inq
1093**
1094** Description Find next command in queue and sent to server
1095**
1096** Returns TRUE if command sent, otherwise FALSE.
1097**
1098*******************************************************************************/
1099BOOLEAN gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb)
1100{
1101 tGATT_CMD_Q *p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1102 BOOLEAN sent = FALSE;
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001103 UINT8 rsp_code;
1104 tGATT_CLCB *p_clcb = NULL;
Andre Eisenbach17b04bd2014-03-28 14:54:22 -07001105 tGATT_STATUS att_ret = GATT_SUCCESS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001106
1107 while (!sent &&
1108 p_tcb->pending_cl_req != p_tcb->next_slot_inq &&
1109 p_cmd->to_send && p_cmd->p_cmd != NULL)
1110 {
Andre Eisenbach17b04bd2014-03-28 14:54:22 -07001111 att_ret = attp_send_msg_to_l2cap(p_tcb, p_cmd->p_cmd);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001112
Andre Eisenbach17b04bd2014-03-28 14:54:22 -07001113 if (att_ret == GATT_SUCCESS || att_ret == GATT_CONGESTED)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001114 {
Andre Eisenbach17b04bd2014-03-28 14:54:22 -07001115 sent = TRUE;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001116 p_cmd->to_send = FALSE;
1117 p_cmd->p_cmd = NULL;
1118
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001119 /* dequeue the request if is write command or sign write */
1120 if (p_cmd->op_code != GATT_CMD_WRITE && p_cmd->op_code != GATT_SIGN_CMD_WRITE)
1121 {
Zhihai Xu5fba60a2014-02-05 20:04:48 -08001122 gatt_start_rsp_timer (p_cmd->clcb_idx);
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001123 }
1124 else
1125 {
1126 p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
1127
1128 /* if no ack needed, keep sending */
Andre Eisenbach17b04bd2014-03-28 14:54:22 -07001129 if (att_ret == GATT_SUCCESS)
1130 sent = FALSE;
1131
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001132 p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1133 /* send command complete callback here */
Andre Eisenbach17b04bd2014-03-28 14:54:22 -07001134 gatt_end_operation(p_clcb, att_ret, NULL);
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001135 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001136 }
1137 else
1138 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001139 GATT_TRACE_ERROR("gatt_cl_send_next_cmd_inq: L2CAP sent error");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001140
1141 memset(p_cmd, 0, sizeof(tGATT_CMD_Q));
1142 p_tcb->pending_cl_req ++;
1143 p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1144 }
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001145
The Android Open Source Project5738f832012-12-12 16:00:35 -08001146 }
1147 return sent;
1148}
1149
1150/*******************************************************************************
1151**
1152** Function gatt_client_handle_server_rsp
1153**
1154** Description This function is called to handle the server response to
1155** client.
1156**
1157**
1158** Returns void
1159**
1160*******************************************************************************/
1161void gatt_client_handle_server_rsp (tGATT_TCB *p_tcb, UINT8 op_code,
1162 UINT16 len, UINT8 *p_data)
1163{
1164 tGATT_CLCB *p_clcb = NULL;
1165 UINT8 rsp_code;
1166
1167 if (op_code != GATT_HANDLE_VALUE_IND && op_code != GATT_HANDLE_VALUE_NOTIF)
1168 {
1169 p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
1170
1171 rsp_code = gatt_cmd_to_rsp_code(rsp_code);
1172
1173 if (p_clcb == NULL || (rsp_code != op_code && op_code != GATT_RSP_ERROR))
1174 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001175 GATT_TRACE_WARNING ("ATT - Ignore wrong response. Receives (%02x) \
The Android Open Source Project5738f832012-12-12 16:00:35 -08001176 Request(%02x) Ignored", op_code, rsp_code);
1177
1178 return;
1179 }
1180 else
Zhihai Xu5fba60a2014-02-05 20:04:48 -08001181 {
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08001182 alarm_cancel(p_clcb->gatt_rsp_timer_ent);
Zhihai Xu5fba60a2014-02-05 20:04:48 -08001183 p_clcb->retry_count = 0;
1184 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001185 }
1186 /* the size of the message may not be bigger than the local max PDU size*/
1187 /* The message has to be smaller than the agreed MTU, len does not count op_code */
1188 if (len >= p_tcb->payload_size)
1189 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001190 GATT_TRACE_ERROR("invalid response/indicate pkt size: %d, PDU size: %d", len + 1, p_tcb->payload_size);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001191 if (op_code != GATT_HANDLE_VALUE_NOTIF &&
1192 op_code != GATT_HANDLE_VALUE_IND)
1193 gatt_end_operation(p_clcb, GATT_ERROR, NULL);
1194 }
1195 else
1196 {
1197 switch (op_code)
1198 {
1199 case GATT_RSP_ERROR:
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -07001200 gatt_process_error_rsp(p_tcb, p_clcb, op_code, len, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001201 break;
1202
1203 case GATT_RSP_MTU: /* 2 bytes mtu */
1204 gatt_process_mtu_rsp(p_tcb, p_clcb, len ,p_data);
1205 break;
1206
1207 case GATT_RSP_FIND_INFO:
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -07001208 gatt_process_read_info_rsp(p_tcb, p_clcb, op_code, len, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001209 break;
1210
1211 case GATT_RSP_READ_BY_TYPE:
1212 case GATT_RSP_READ_BY_GRP_TYPE:
1213 gatt_process_read_by_type_rsp(p_tcb, p_clcb, op_code, len, p_data);
1214 break;
1215
1216 case GATT_RSP_READ:
1217 case GATT_RSP_READ_BLOB:
1218 case GATT_RSP_READ_MULTI:
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -07001219 gatt_process_read_rsp(p_tcb, p_clcb, op_code, len, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001220 break;
1221
1222 case GATT_RSP_FIND_TYPE_VALUE: /* disc service with UUID */
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -07001223 gatt_process_find_type_value_rsp(p_tcb, p_clcb, len, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001224 break;
1225
1226 case GATT_RSP_WRITE:
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001227 gatt_process_handle_rsp(p_clcb);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001228 break;
1229
1230 case GATT_RSP_PREPARE_WRITE:
1231 gatt_process_prep_write_rsp(p_tcb, p_clcb, op_code, len, p_data);
1232 break;
1233
1234 case GATT_RSP_EXEC_WRITE:
1235 gatt_end_operation(p_clcb, p_clcb->status, NULL);
1236 break;
1237
1238 case GATT_HANDLE_VALUE_NOTIF:
1239 case GATT_HANDLE_VALUE_IND:
1240 gatt_process_notification(p_tcb, op_code, len, p_data);
1241 break;
1242
1243 default:
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001244 GATT_TRACE_ERROR("Unknown opcode = %d", op_code);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001245 break;
1246 }
1247 }
1248
1249 if (op_code != GATT_HANDLE_VALUE_IND && op_code != GATT_HANDLE_VALUE_NOTIF)
1250 {
1251 gatt_cl_send_next_cmd_inq(p_tcb);
1252 }
1253
1254 return;
1255}
1256
1257#endif /* BLE_INCLUDED */