blob: 1c1474734cb590eeb9a9108ea56b926df7bacf04 [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
Marie Janssend19e0782016-07-15 12:48:27 -070027#if (BLE_INCLUDED == TRUE)
The Android Open Source Project5738f832012-12-12 16:00:35 -080028
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
Marie Janssend19e0782016-07-15 12:48:27 -070051uint8_t disc_type_to_att_opcode[GATT_DISC_MAX] =
The Android Open Source Project5738f832012-12-12 16:00:35 -080052{
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
Marie Janssend19e0782016-07-15 12:48:27 -070061uint16_t disc_type_to_uuid[GATT_DISC_MAX] =
The Android Open Source Project5738f832012-12-12 16:00:35 -080062{
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{
Marie Janssend19e0782016-07-15 12:48:27 -070083 uint8_t op_code = disc_type_to_att_opcode[p_clcb->op_subtype];
The Android Open Source Project5738f832012-12-12 16:00:35 -080084 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*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700137void gatt_act_read (tGATT_CLCB *p_clcb, uint16_t offset)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800138{
139 tGATT_TCB *p_tcb = p_clcb->p_tcb;
Marie Janssend19e0782016-07-15 12:48:27 -0700140 uint8_t rt = GATT_INTERNAL_ERROR;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800141 tGATT_CL_MSG msg;
Marie Janssend19e0782016-07-15 12:48:27 -0700142 uint8_t op_code = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800143
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)
Marie Janssend19e0782016-07-15 12:48:27 -0700172 p_clcb->first_read_blob_after_read = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800173 else
Marie Janssend19e0782016-07-15 12:48:27 -0700174 p_clcb->first_read_blob_after_read = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800175
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*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700225void gatt_act_write (tGATT_CLCB *p_clcb, uint8_t sec_act)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800226{
227 tGATT_TCB *p_tcb = p_clcb->p_tcb;
Marie Janssend19e0782016-07-15 12:48:27 -0700228 uint8_t 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{
Marie Janssend19e0782016-07-15 12:48:27 -0700300 uint8_t rt ;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800301
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**
Marie Janssend19e0782016-07-15 12:48:27 -0700317** Returns true: write long is terminated; false keep sending.
The Android Open Source Project5738f832012-12-12 16:00:35 -0800318**
319*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700320bool gatt_check_write_long_terminate(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, tGATT_VALUE *p_rsp_value)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800321{
322 tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
Marie Janssend19e0782016-07-15 12:48:27 -0700323 bool exec = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800324 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;
Marie Janssend19e0782016-07-15 12:48:27 -0700337 exec = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800338 }
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)
Marie Janssend19e0782016-07-15 12:48:27 -0700344 exec = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800345 }
346 }
347 if (exec)
348 {
349 gatt_send_queue_write_cancel (p_tcb, p_clcb, flag);
Marie Janssend19e0782016-07-15 12:48:27 -0700350 return true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800351 }
Marie Janssend19e0782016-07-15 12:48:27 -0700352 return false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800353}
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;
Marie Janssend19e0782016-07-15 12:48:27 -0700366 uint16_t to_send, offset;
367 uint8_t rt = GATT_SUCCESS;
368 uint8_t type = p_clcb->op_subtype;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800369
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
Marie Janssend19e0782016-07-15 12:48:27 -0700373 if (to_send > (p_tcb->payload_size - GATT_WRITE_LONG_HDR_SIZE)) /* 2 = uint16_t offset bytes */
The Android Open Source Project5738f832012-12-12 16:00:35 -0800374 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*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700414void gatt_process_find_type_value_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800415{
416 tGATT_DISC_RES result;
Marie Janssend19e0782016-07-15 12:48:27 -0700417 uint8_t *p = p_data;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800418
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*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700459void gatt_process_read_info_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, uint8_t op_code,
460 uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800461{
462 tGATT_DISC_RES result;
Marie Janssend19e0782016-07-15 12:48:27 -0700463 uint8_t *p = p_data, uuid_len = 0, type;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800464
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*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700518void gatt_proc_disc_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, uint8_t opcode,
519 uint16_t handle, uint8_t 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*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700558void gatt_process_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, uint8_t op_code,
559 uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800560{
Marie Janssend19e0782016-07-15 12:48:27 -0700561 uint8_t opcode, reason, * p= p_data;
562 uint16_t handle;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800563 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*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700611void gatt_process_prep_write_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, uint8_t op_code,
612 uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800613{
Marie Janssend19e0782016-07-15 12:48:27 -0700614 uint8_t *p = p_data;
Pavlin Radoslavov43947202016-02-13 08:47:19 -0800615
616 tGATT_VALUE value = {
617 .conn_id = p_clcb->conn_id,
618 .auth_req = GATT_AUTH_REQ_NONE,
619 };
The Android Open Source Project5738f832012-12-12 16:00:35 -0800620
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700621 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 -0800622
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700623 if (len < GATT_PREP_WRITE_RSP_MIN_LEN)
624 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700625 GATT_TRACE_ERROR("illegal prepare write response length, discard");
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700626 gatt_end_operation(p_clcb, GATT_INVALID_PDU, &value);
627 return;
628 }
629
The Android Open Source Project5738f832012-12-12 16:00:35 -0800630 STREAM_TO_UINT16 (value.handle, p);
631 STREAM_TO_UINT16 (value.offset, p);
632
633 value.len = len - 4;
634
635 memcpy (value.value, p, value.len);
636
637 if (p_clcb->op_subtype == GATT_WRITE_PREPARE)
638 {
639 p_clcb->status = GATT_SUCCESS;
640 /* application should verify handle offset
641 and value are matched or not */
642
643 gatt_end_operation(p_clcb, p_clcb->status, &value);
644 }
645 else if (p_clcb->op_subtype == GATT_WRITE )
646 {
647 if (!gatt_check_write_long_terminate(p_tcb, p_clcb, &value))
648 gatt_send_prepare_write(p_tcb, p_clcb);
649 }
650
651}
652/*******************************************************************************
653**
654** Function gatt_process_notification
655**
656** Description This function is called to handle the handle value indication
657** or handle value notification.
658**
659**
660** Returns void
661**
662*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700663void gatt_process_notification(tGATT_TCB *p_tcb, uint8_t op_code,
664 uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800665{
Pavlin Radoslavov43947202016-02-13 08:47:19 -0800666 tGATT_VALUE value;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800667 tGATT_REG *p_reg;
Marie Janssend19e0782016-07-15 12:48:27 -0700668 uint16_t conn_id;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800669 tGATT_STATUS encrypt_status;
Marie Janssend19e0782016-07-15 12:48:27 -0700670 uint8_t *p= p_data, i,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800671 event = (op_code == GATT_HANDLE_VALUE_NOTIF) ? GATTC_OPTYPE_NOTIFICATION : GATTC_OPTYPE_INDICATION;
672
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700673 GATT_TRACE_DEBUG("gatt_process_notification ");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800674
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700675 if (len < GATT_NOTIFICATION_MIN_LEN)
676 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700677 GATT_TRACE_ERROR("illegal notification PDU length, discard");
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700678 return;
679 }
680
Pavlin Radoslavov43947202016-02-13 08:47:19 -0800681 memset(&value, 0, sizeof(value));
682 STREAM_TO_UINT16(value.handle, p);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800683 value.len = len - 2;
684 memcpy (value.value, p, value.len);
685
686 if (!GATT_HANDLE_IS_VALID(value.handle))
687 {
688 /* illegal handle, send ack now */
689 if (op_code == GATT_HANDLE_VALUE_IND)
690 attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
691 return;
692 }
693
694 if (event == GATTC_OPTYPE_INDICATION)
695 {
696 if (p_tcb->ind_count)
697 {
698 /* this is an error case that receiving an indication but we
699 still has an indication not being acked yet.
700 For now, just log the error reset the counter.
701 Later we need to disconnect the link unconditionally.
702 */
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700703 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 -0800704 }
705 p_tcb->ind_count = 0;
706 }
707
708 /* should notify all registered client with the handle value notificaion/indication
709 Note: need to do the indication count and start timer first then do callback
710 */
711
712 for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++)
713 {
714 if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb && (event == GATTC_OPTYPE_INDICATION))
715 p_tcb->ind_count++;
716 }
717
718 if (event == GATTC_OPTYPE_INDICATION)
719 {
720 /* start a timer for app confirmation */
721 if (p_tcb->ind_count > 0)
722 gatt_start_ind_ack_timer(p_tcb);
723 else /* no app to indicate, or invalid handle */
724 attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
725 }
726
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800727 encrypt_status = gatt_get_link_encrypt_status(p_tcb);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800728 for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++)
729 {
730 if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb)
731 {
732 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800733 (*p_reg->app_cb.p_cmpl_cb) (conn_id, event, encrypt_status, (tGATT_CL_COMPLETE *)&value);
734 }
735 }
736
737}
738
739/*******************************************************************************
740**
741** Function gatt_process_read_by_type_rsp
742**
743** Description This function is called to handle the read by type response.
744** read by type can be used for discovery, or read by type or
745** read characteristic value.
746**
747** Returns void
748**
749*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700750void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, uint8_t op_code,
751 uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800752{
753 tGATT_DISC_RES result;
754 tGATT_DISC_VALUE record_value;
Marie Janssend19e0782016-07-15 12:48:27 -0700755 uint8_t *p = p_data, value_len, handle_len = 2;
756 uint16_t handle = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800757
758 /* discovery procedure and no callback function registered */
759 if (((!p_clcb->p_reg) || (!p_clcb->p_reg->app_cb.p_disc_res_cb)) && (p_clcb->operation == GATTC_OPTYPE_DISCOVERY))
760 return;
761
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700762 if (len < GATT_READ_BY_TYPE_RSP_MIN_LEN)
763 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700764 GATT_TRACE_ERROR("Illegal ReadByType/ReadByGroupType Response length, discard");
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700765 gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL);
766 return;
767 }
768
The Android Open Source Project5738f832012-12-12 16:00:35 -0800769 STREAM_TO_UINT8(value_len, p);
770
771 if ((value_len > (p_tcb->payload_size - 2)) || (value_len > (len-1)) )
772 {
773 /* this is an error case that server's response containing a value length which is larger than MTU-2
774 or value_len > message total length -1 */
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700775 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 -0800776 op_code, value_len, (p_tcb->payload_size - 2), (len-1));
777 gatt_end_operation(p_clcb, GATT_ERROR, NULL);
778 return;
779 }
780
781 if (op_code == GATT_RSP_READ_BY_GRP_TYPE)
782 handle_len = 4;
783
784 value_len -= handle_len; /* substract the handle pairs bytes */
785 len -= 1;
786
787 while (len >= (handle_len + value_len))
788 {
789 STREAM_TO_UINT16(handle, p);
790
791 if (!GATT_HANDLE_IS_VALID(handle))
792 {
793 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
794 return;
795 }
796
797 memset(&result, 0, sizeof(tGATT_DISC_RES));
798 memset(&record_value, 0, sizeof(tGATT_DISC_VALUE));
799
800 result.handle = handle;
801 result.type.len = 2;
802 result.type.uu.uuid16 = disc_type_to_uuid[p_clcb->op_subtype];
803
804 /* discover all services */
805 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
806 p_clcb->op_subtype == GATT_DISC_SRVC_ALL &&
807 op_code == GATT_RSP_READ_BY_GRP_TYPE)
808 {
809 STREAM_TO_UINT16(handle, p);
810
811 if (!GATT_HANDLE_IS_VALID(handle))
812 {
813 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
814 return;
815 }
816 else
817 {
818 record_value.group_value.e_handle = handle;
819 if (!gatt_parse_uuid_from_cmd(&record_value.group_value.service_type, value_len, &p))
820 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700821 GATT_TRACE_ERROR("discover all service response parsing failure");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800822 break;
823 }
824 }
825 }
826 /* discover included service */
827 else if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->op_subtype == GATT_DISC_INC_SRVC)
828 {
829 STREAM_TO_UINT16(record_value.incl_service.s_handle, p);
830 STREAM_TO_UINT16(record_value.incl_service.e_handle, p);
831
832 if (!GATT_HANDLE_IS_VALID(record_value.incl_service.s_handle) ||
833 !GATT_HANDLE_IS_VALID(record_value.incl_service.e_handle))
834 {
835 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
836 return;
837 }
838
839 if(value_len == 6)
840 {
841 STREAM_TO_UINT16(record_value.incl_service.service_type.uu.uuid16, p);
842 record_value.incl_service.service_type.len = LEN_UUID_16;
843 }
844 else if (value_len == 4)
845 {
846 p_clcb->s_handle = record_value.incl_service.s_handle;
Marie Janssend19e0782016-07-15 12:48:27 -0700847 p_clcb->read_uuid128.wait_for_read_rsp = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800848 p_clcb->read_uuid128.next_disc_start_hdl = handle + 1;
849 memcpy(&p_clcb->read_uuid128.result, &result, sizeof(result));
850 memcpy(&p_clcb->read_uuid128.result.value, &record_value, sizeof (result.value));
851 p_clcb->op_subtype |= 0x90;
852 gatt_act_read(p_clcb, 0);
853 return;
854 }
855 else
856 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700857 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 -0800858 gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p);
859 return;
860 }
861 }
862 /* read by type */
863 else if (p_clcb->operation == GATTC_OPTYPE_READ && p_clcb->op_subtype == GATT_READ_BY_TYPE)
864 {
865 p_clcb->counter = len - 2;
866 p_clcb->s_handle = handle;
867 if ( p_clcb->counter == (p_clcb->p_tcb->payload_size -4))
868 {
869 p_clcb->op_subtype = GATT_READ_BY_HANDLE;
870 if (!p_clcb->p_attr_buf)
Marie Janssend19e0782016-07-15 12:48:27 -0700871 p_clcb->p_attr_buf = (uint8_t *)osi_malloc(GATT_MAX_ATTR_LEN);
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800872 if (p_clcb->counter <= GATT_MAX_ATTR_LEN) {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800873 memcpy(p_clcb->p_attr_buf, p, p_clcb->counter);
874 gatt_act_read(p_clcb, p_clcb->counter);
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800875 } else {
876 gatt_end_operation(p_clcb, GATT_INTERNAL_ERROR, (void *)p);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800877 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800878 }
879 else
880 {
881 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p);
882 }
883 return;
884 }
Andre Eisenbach6975b4d2013-08-05 16:55:38 -0700885 else /* discover characterisitic */
The Android Open Source Project5738f832012-12-12 16:00:35 -0800886 {
887 STREAM_TO_UINT8 (record_value.dclr_value.char_prop, p);
888 STREAM_TO_UINT16(record_value.dclr_value.val_handle, p);
889 if (!GATT_HANDLE_IS_VALID(record_value.dclr_value.val_handle))
890 {
891 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
892 return;
893 }
Marie Janssend19e0782016-07-15 12:48:27 -0700894 if (!gatt_parse_uuid_from_cmd(&record_value.dclr_value.char_uuid, (uint16_t)(value_len - 3), &p))
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800895 {
896 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
897 /* invalid format, and skip the result */
898 return;
899 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800900
901 /* UUID not matching */
902 if (!gatt_uuid_compare(record_value.dclr_value.char_uuid, p_clcb->uuid))
903 {
904 len -= (value_len + 2);
905 continue; /* skip the result, and look for next one */
906 }
907 else if (p_clcb->operation == GATTC_OPTYPE_READ)
908 /* UUID match for read characteristic value */
909 {
910 /* only read the first matching UUID characteristic value, and
911 discard the rest results */
912 p_clcb->s_handle = record_value.dclr_value.val_handle;
913 p_clcb->op_subtype |= 0x80;
914 gatt_act_read(p_clcb, 0);
915 return;
916 }
917 }
918 len -= (value_len + handle_len);
919
920 /* result is (handle, 16bits UUID) pairs */
921 memcpy (&result.value, &record_value, sizeof (result.value));
922
923 /* send callback if is discover procedure */
924 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY && p_clcb->p_reg->app_cb.p_disc_res_cb)
925 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
926 }
927
928 p_clcb->s_handle = (handle == 0) ? 0 : (handle + 1);
929
930 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY)
931 {
932 /* initiate another request */
933 gatt_act_discovery(p_clcb) ;
934 }
935 else /* read characteristic value */
936 {
937 gatt_act_read(p_clcb, 0);
938 }
939}
940
941/*******************************************************************************
942**
943** Function gatt_process_read_rsp
944**
945** Description This function is called to handle the read BLOB response
946**
947**
948** Returns void
949**
950*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700951void gatt_process_read_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, uint8_t op_code,
952 uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800953{
Marie Janssend19e0782016-07-15 12:48:27 -0700954 uint16_t offset = p_clcb->counter;
955 uint8_t * p= p_data;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800956
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -0700957 UNUSED(op_code);
958
The Android Open Source Project5738f832012-12-12 16:00:35 -0800959 if (p_clcb->operation == GATTC_OPTYPE_READ)
960 {
961 if (p_clcb->op_subtype != GATT_READ_BY_HANDLE)
962 {
963 p_clcb->counter = len;
964 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p);
965 }
966 else
967 {
968
969 /* allocate GKI buffer holding up long attribute value */
970 if (!p_clcb->p_attr_buf)
Marie Janssend19e0782016-07-15 12:48:27 -0700971 p_clcb->p_attr_buf = (uint8_t *)osi_malloc(GATT_MAX_ATTR_LEN);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800972
973 /* copy attrobute value into cb buffer */
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800974 if (offset < GATT_MAX_ATTR_LEN) {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800975 if ((len + offset) > GATT_MAX_ATTR_LEN)
976 len = GATT_MAX_ATTR_LEN - offset;
977
978 p_clcb->counter += len;
979
980 memcpy(p_clcb->p_attr_buf + offset, p, len);
981
982 /* send next request if needed */
983
984 if (len == (p_tcb->payload_size - 1) && /* full packet for read or read blob rsp */
985 len + offset < GATT_MAX_ATTR_LEN)
986 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700987 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 -0800988 offset, len, p_clcb->counter);
989 gatt_act_read(p_clcb, p_clcb->counter);
990 }
991 else /* end of request, send callback */
992 {
993 gatt_end_operation(p_clcb, GATT_SUCCESS, (void *)p_clcb->p_attr_buf);
994 }
995 }
996 else /* exception, should not happen */
997 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700998 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 -0800999 gatt_end_operation(p_clcb, GATT_NO_RESOURCES, (void *)p_clcb->p_attr_buf);
1000 }
1001 }
1002 }
1003 else
1004 {
1005 if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
1006 p_clcb->op_subtype == GATT_DISC_INC_SRVC &&
1007 p_clcb->read_uuid128.wait_for_read_rsp )
1008 {
1009 p_clcb->s_handle = p_clcb->read_uuid128.next_disc_start_hdl;
Marie Janssend19e0782016-07-15 12:48:27 -07001010 p_clcb->read_uuid128.wait_for_read_rsp = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001011 if (len == LEN_UUID_128)
1012 {
1013
1014 memcpy(p_clcb->read_uuid128.result.value.incl_service.service_type.uu.uuid128, p, len);
1015 p_clcb->read_uuid128.result.value.incl_service.service_type.len = LEN_UUID_128;
1016 if ( p_clcb->p_reg->app_cb.p_disc_res_cb)
1017 (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &p_clcb->read_uuid128.result);
1018 gatt_act_discovery(p_clcb) ;
1019 }
1020 else
1021 {
1022 gatt_end_operation(p_clcb, GATT_INVALID_PDU, (void *)p);
1023 }
1024 }
1025 }
1026
1027}
1028
1029
1030/*******************************************************************************
1031**
1032** Function gatt_process_handle_rsp
1033**
1034** Description This function is called to handle the write response
1035**
1036**
1037** Returns void
1038**
1039*******************************************************************************/
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001040void gatt_process_handle_rsp(tGATT_CLCB *p_clcb)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001041{
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001042 gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001043}
1044/*******************************************************************************
1045**
1046** Function gatt_process_mtu_rsp
1047**
1048** Description This function is called to process the configure MTU response.
1049**
1050**
1051** Returns void
1052**
1053*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001054void gatt_process_mtu_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001055{
Marie Janssend19e0782016-07-15 12:48:27 -07001056 uint16_t mtu;
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001057 tGATT_STATUS status = GATT_SUCCESS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001058
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001059 if (len < GATT_MTU_RSP_MIN_LEN)
1060 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001061 GATT_TRACE_ERROR("invalid MTU response PDU received, discard.");
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001062 status = GATT_INVALID_PDU;
1063 }
1064 else
1065 {
The Android Open Source Project5738f832012-12-12 16:00:35 -08001066 STREAM_TO_UINT16(mtu, p_data);
1067
1068 if (mtu < p_tcb->payload_size && mtu >= GATT_DEF_BLE_MTU_SIZE)
1069 p_tcb->payload_size = mtu;
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001070 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001071
Priti Aghera636d6712014-12-18 13:55:48 -08001072 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 -07001073 gatt_end_operation(p_clcb, status, NULL);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001074}
1075/*******************************************************************************
1076**
1077** Function gatt_cmd_to_rsp_code
1078**
1079** Description The function convert a ATT command op code into the corresponding
1080** response code assume no error occurs.
1081**
1082** Returns response code.
1083**
1084*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001085uint8_t gatt_cmd_to_rsp_code (uint8_t cmd_code)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001086{
Marie Janssend19e0782016-07-15 12:48:27 -07001087 uint8_t rsp_code = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001088
1089 if (cmd_code > 1 && cmd_code != GATT_CMD_WRITE)
1090 {
1091 rsp_code = cmd_code + 1;
1092 }
1093 return rsp_code;
1094}
1095/*******************************************************************************
1096**
1097** Function gatt_cl_send_next_cmd_inq
1098**
1099** Description Find next command in queue and sent to server
1100**
Marie Janssend19e0782016-07-15 12:48:27 -07001101** Returns true if command sent, otherwise false.
The Android Open Source Project5738f832012-12-12 16:00:35 -08001102**
1103*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001104bool gatt_cl_send_next_cmd_inq(tGATT_TCB *p_tcb)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001105{
1106 tGATT_CMD_Q *p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
Marie Janssend19e0782016-07-15 12:48:27 -07001107 bool sent = false;
1108 uint8_t rsp_code;
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001109 tGATT_CLCB *p_clcb = NULL;
Andre Eisenbach17b04bd2014-03-28 14:54:22 -07001110 tGATT_STATUS att_ret = GATT_SUCCESS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001111
1112 while (!sent &&
1113 p_tcb->pending_cl_req != p_tcb->next_slot_inq &&
1114 p_cmd->to_send && p_cmd->p_cmd != NULL)
1115 {
Andre Eisenbach17b04bd2014-03-28 14:54:22 -07001116 att_ret = attp_send_msg_to_l2cap(p_tcb, p_cmd->p_cmd);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001117
Andre Eisenbach17b04bd2014-03-28 14:54:22 -07001118 if (att_ret == GATT_SUCCESS || att_ret == GATT_CONGESTED)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001119 {
Marie Janssend19e0782016-07-15 12:48:27 -07001120 sent = true;
1121 p_cmd->to_send = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001122 p_cmd->p_cmd = NULL;
1123
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001124 /* dequeue the request if is write command or sign write */
1125 if (p_cmd->op_code != GATT_CMD_WRITE && p_cmd->op_code != GATT_SIGN_CMD_WRITE)
1126 {
Zhihai Xu5fba60a2014-02-05 20:04:48 -08001127 gatt_start_rsp_timer (p_cmd->clcb_idx);
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001128 }
1129 else
1130 {
1131 p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
1132
1133 /* if no ack needed, keep sending */
Andre Eisenbach17b04bd2014-03-28 14:54:22 -07001134 if (att_ret == GATT_SUCCESS)
Marie Janssend19e0782016-07-15 12:48:27 -07001135 sent = false;
Andre Eisenbach17b04bd2014-03-28 14:54:22 -07001136
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001137 p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1138 /* send command complete callback here */
Andre Eisenbach17b04bd2014-03-28 14:54:22 -07001139 gatt_end_operation(p_clcb, att_ret, NULL);
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001140 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001141 }
1142 else
1143 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001144 GATT_TRACE_ERROR("gatt_cl_send_next_cmd_inq: L2CAP sent error");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001145
1146 memset(p_cmd, 0, sizeof(tGATT_CMD_Q));
1147 p_tcb->pending_cl_req ++;
1148 p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
1149 }
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -08001150
The Android Open Source Project5738f832012-12-12 16:00:35 -08001151 }
1152 return sent;
1153}
1154
1155/*******************************************************************************
1156**
1157** Function gatt_client_handle_server_rsp
1158**
1159** Description This function is called to handle the server response to
1160** client.
1161**
1162**
1163** Returns void
1164**
1165*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001166void gatt_client_handle_server_rsp (tGATT_TCB *p_tcb, uint8_t op_code,
1167 uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001168{
1169 tGATT_CLCB *p_clcb = NULL;
Marie Janssend19e0782016-07-15 12:48:27 -07001170 uint8_t rsp_code;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001171
1172 if (op_code != GATT_HANDLE_VALUE_IND && op_code != GATT_HANDLE_VALUE_NOTIF)
1173 {
1174 p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
1175
1176 rsp_code = gatt_cmd_to_rsp_code(rsp_code);
1177
1178 if (p_clcb == NULL || (rsp_code != op_code && op_code != GATT_RSP_ERROR))
1179 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001180 GATT_TRACE_WARNING ("ATT - Ignore wrong response. Receives (%02x) \
The Android Open Source Project5738f832012-12-12 16:00:35 -08001181 Request(%02x) Ignored", op_code, rsp_code);
1182
1183 return;
1184 }
1185 else
Zhihai Xu5fba60a2014-02-05 20:04:48 -08001186 {
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08001187 alarm_cancel(p_clcb->gatt_rsp_timer_ent);
Zhihai Xu5fba60a2014-02-05 20:04:48 -08001188 p_clcb->retry_count = 0;
1189 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001190 }
1191 /* the size of the message may not be bigger than the local max PDU size*/
1192 /* The message has to be smaller than the agreed MTU, len does not count op_code */
1193 if (len >= p_tcb->payload_size)
1194 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001195 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 -08001196 if (op_code != GATT_HANDLE_VALUE_NOTIF &&
1197 op_code != GATT_HANDLE_VALUE_IND)
1198 gatt_end_operation(p_clcb, GATT_ERROR, NULL);
1199 }
1200 else
1201 {
1202 switch (op_code)
1203 {
1204 case GATT_RSP_ERROR:
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -07001205 gatt_process_error_rsp(p_tcb, p_clcb, op_code, len, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001206 break;
1207
1208 case GATT_RSP_MTU: /* 2 bytes mtu */
1209 gatt_process_mtu_rsp(p_tcb, p_clcb, len ,p_data);
1210 break;
1211
1212 case GATT_RSP_FIND_INFO:
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -07001213 gatt_process_read_info_rsp(p_tcb, p_clcb, op_code, len, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001214 break;
1215
1216 case GATT_RSP_READ_BY_TYPE:
1217 case GATT_RSP_READ_BY_GRP_TYPE:
1218 gatt_process_read_by_type_rsp(p_tcb, p_clcb, op_code, len, p_data);
1219 break;
1220
1221 case GATT_RSP_READ:
1222 case GATT_RSP_READ_BLOB:
1223 case GATT_RSP_READ_MULTI:
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -07001224 gatt_process_read_rsp(p_tcb, p_clcb, op_code, len, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001225 break;
1226
1227 case GATT_RSP_FIND_TYPE_VALUE: /* disc service with UUID */
Ganesh Ganapathi Batta7fa4fba2014-04-16 16:50:09 -07001228 gatt_process_find_type_value_rsp(p_tcb, p_clcb, len, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001229 break;
1230
1231 case GATT_RSP_WRITE:
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001232 gatt_process_handle_rsp(p_clcb);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001233 break;
1234
1235 case GATT_RSP_PREPARE_WRITE:
1236 gatt_process_prep_write_rsp(p_tcb, p_clcb, op_code, len, p_data);
1237 break;
1238
1239 case GATT_RSP_EXEC_WRITE:
1240 gatt_end_operation(p_clcb, p_clcb->status, NULL);
1241 break;
1242
1243 case GATT_HANDLE_VALUE_NOTIF:
1244 case GATT_HANDLE_VALUE_IND:
1245 gatt_process_notification(p_tcb, op_code, len, p_data);
1246 break;
1247
1248 default:
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001249 GATT_TRACE_ERROR("Unknown opcode = %d", op_code);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001250 break;
1251 }
1252 }
1253
1254 if (op_code != GATT_HANDLE_VALUE_IND && op_code != GATT_HANDLE_VALUE_NOTIF)
1255 {
1256 gatt_cl_send_next_cmd_inq(p_tcb);
1257 }
1258
1259 return;
1260}
1261
1262#endif /* BLE_INCLUDED */