blob: 075829df211d98bac89f1f361957daa839be6cea [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
2 *
3 * Copyright (C) 2008-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19/******************************************************************************
20 *
21 * this file contains the GATT server functions
22 *
23 ******************************************************************************/
24
25#include "bt_target.h"
Mike J. Chen5cd8bff2014-01-31 18:16:59 -080026#include "bt_utils.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080027
Marie Janssend19e0782016-07-15 12:48:27 -070028#if (BLE_INCLUDED == TRUE)
The Android Open Source Project5738f832012-12-12 16:00:35 -080029#include <string.h>
30#include "gatt_int.h"
31#include "l2c_api.h"
Priti Aghera636d6712014-12-18 13:55:48 -080032#include "l2c_int.h"
Andre Eisenbachccf9c152013-10-02 15:37:21 -070033#define GATT_MTU_REQ_MIN_LEN 2
34
The Android Open Source Project5738f832012-12-12 16:00:35 -080035
36/*******************************************************************************
37**
38** Function gatt_sr_enqueue_cmd
39**
40** Description This function enqueue the request from client which needs a
41** application response, and update the transaction ID.
42**
43** Returns void
44**
45*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -070046uint32_t gatt_sr_enqueue_cmd (tGATT_TCB *p_tcb, uint8_t op_code, uint16_t handle)
The Android Open Source Project5738f832012-12-12 16:00:35 -080047{
48 tGATT_SR_CMD *p_cmd = &p_tcb->sr_cmd;
Marie Janssend19e0782016-07-15 12:48:27 -070049 uint32_t trans_id = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -080050
51 if ( (p_cmd->op_code == 0) ||
52 (op_code == GATT_HANDLE_VALUE_CONF)) /* no pending request */
53 {
54 if (op_code == GATT_CMD_WRITE ||
55 op_code == GATT_SIGN_CMD_WRITE ||
56 op_code == GATT_REQ_MTU ||
57 op_code == GATT_HANDLE_VALUE_CONF)
58 {
59 trans_id = ++p_tcb->trans_id;
60 }
61 else
62 {
63 p_cmd->trans_id = ++p_tcb->trans_id;
64 p_cmd->op_code = op_code;
65 p_cmd->handle = handle;
66 p_cmd->status = GATT_NOT_FOUND;
67 p_tcb->trans_id %= GATT_TRANS_ID_MAX;
68 trans_id = p_cmd->trans_id;
69 }
70 }
71
72 return trans_id;
73}
74
75/*******************************************************************************
76**
77** Function gatt_sr_cmd_empty
78**
79** Description This function check the server command queue is empty or not.
80**
Marie Janssend19e0782016-07-15 12:48:27 -070081** Returns true if empty, false if there is pending command.
The Android Open Source Project5738f832012-12-12 16:00:35 -080082**
83*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -070084bool gatt_sr_cmd_empty (tGATT_TCB *p_tcb)
The Android Open Source Project5738f832012-12-12 16:00:35 -080085{
86 return(p_tcb->sr_cmd.op_code == 0);
87}
88
89/*******************************************************************************
90**
91** Function gatt_dequeue_sr_cmd
92**
93** Description This function dequeue the request from command queue.
94**
95** Returns void
96**
97*******************************************************************************/
98void gatt_dequeue_sr_cmd (tGATT_TCB *p_tcb)
99{
100 /* Double check in case any buffers are queued */
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700101 GATT_TRACE_DEBUG("gatt_dequeue_sr_cmd" );
The Android Open Source Project5738f832012-12-12 16:00:35 -0800102 if (p_tcb->sr_cmd.p_rsp_msg)
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700103 GATT_TRACE_ERROR("free p_tcb->sr_cmd.p_rsp_msg = %d", p_tcb->sr_cmd.p_rsp_msg);
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800104 osi_free_and_reset((void **)&p_tcb->sr_cmd.p_rsp_msg);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800105
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700106 while (!fixed_queue_is_empty(p_tcb->sr_cmd.multi_rsp_q))
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800107 osi_free(fixed_queue_try_dequeue(p_tcb->sr_cmd.multi_rsp_q));
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700108 fixed_queue_free(p_tcb->sr_cmd.multi_rsp_q, NULL);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800109 memset( &p_tcb->sr_cmd, 0, sizeof(tGATT_SR_CMD));
110}
111
112/*******************************************************************************
113**
114** Function process_read_multi_rsp
115**
116** Description This function check the read multiple response.
117**
Marie Janssend19e0782016-07-15 12:48:27 -0700118** Returns bool if all replies have been received
The Android Open Source Project5738f832012-12-12 16:00:35 -0800119**
120*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700121static bool process_read_multi_rsp (tGATT_SR_CMD *p_cmd, tGATT_STATUS status,
122 tGATTS_RSP *p_msg, uint16_t mtu)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800123{
Marie Janssend19e0782016-07-15 12:48:27 -0700124 uint16_t ii, total_len, len;
125 uint8_t *p;
126 bool is_overflow = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800127
Subramanian Srinivasan089cd112016-05-16 11:14:03 -0700128 GATT_TRACE_DEBUG ("%s status=%d mtu=%d", __func__, status, mtu);
129
130 if (p_cmd->multi_rsp_q == NULL)
131 p_cmd->multi_rsp_q = fixed_queue_new(SIZE_MAX);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800132
The Android Open Source Project5738f832012-12-12 16:00:35 -0800133 /* Enqueue the response */
Subramanian Srinivasan089cd112016-05-16 11:14:03 -0700134 BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(tGATTS_RSP));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800135 memcpy((void *)p_buf, (const void *)p_msg, sizeof(tGATTS_RSP));
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700136 fixed_queue_enqueue(p_cmd->multi_rsp_q, p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800137
138 p_cmd->status = status;
139 if (status == GATT_SUCCESS)
140 {
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700141 GATT_TRACE_DEBUG("Multi read count=%d num_hdls=%d",
Pavlin Radoslavov43947202016-02-13 08:47:19 -0800142 fixed_queue_length(p_cmd->multi_rsp_q),
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700143 p_cmd->multi_req.num_handles);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800144 /* Wait till we get all the responses */
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700145 if (fixed_queue_length(p_cmd->multi_rsp_q) == p_cmd->multi_req.num_handles)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800146 {
147 len = sizeof(BT_HDR) + L2CAP_MIN_OFFSET + mtu;
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800148 p_buf = (BT_HDR *)osi_calloc(len);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800149 p_buf->offset = L2CAP_MIN_OFFSET;
Marie Janssend19e0782016-07-15 12:48:27 -0700150 p = (uint8_t *)(p_buf + 1) + p_buf->offset;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800151
152 /* First byte in the response is the opcode */
153 *p++ = GATT_RSP_READ_MULTI;
154 p_buf->len = 1;
155
156 /* Now walk through the buffers puting the data into the response in order */
Pavlin Radoslavov577862e2015-10-07 18:07:48 -0700157 list_t *list = NULL;
158 const list_node_t *node = NULL;
159 if (! fixed_queue_is_empty(p_cmd->multi_rsp_q))
160 list = fixed_queue_get_list(p_cmd->multi_rsp_q);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800161 for (ii = 0; ii < p_cmd->multi_req.num_handles; ii++)
162 {
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700163 tGATTS_RSP *p_rsp = NULL;
164
Pavlin Radoslavov577862e2015-10-07 18:07:48 -0700165 if (list != NULL) {
166 if (ii == 0)
167 node = list_begin(list);
168 else
169 node = list_next(node);
170 if (node != list_end(list))
171 p_rsp = (tGATTS_RSP *)list_node(node);
172 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800173
174 if (p_rsp != NULL)
175 {
176
177 total_len = (p_buf->len + p_rsp->attr_value.len);
178
179 if (total_len > mtu)
180 {
181 /* just send the partial response for the overflow case */
182 len = p_rsp->attr_value.len - (total_len - mtu);
Marie Janssend19e0782016-07-15 12:48:27 -0700183 is_overflow = true;
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700184 GATT_TRACE_DEBUG ("multi read overflow available len=%d val_len=%d", len, p_rsp->attr_value.len );
The Android Open Source Project5738f832012-12-12 16:00:35 -0800185 }
186 else
187 {
188 len = p_rsp->attr_value.len;
189 }
190
191 if (p_rsp->attr_value.handle == p_cmd->multi_req.handles[ii])
192 {
193 memcpy (p, p_rsp->attr_value.value, len);
194 if (!is_overflow)
195 p += len;
196 p_buf->len += len;
197 }
198 else
199 {
200 p_cmd->status = GATT_NOT_FOUND;
201 break;
202 }
203
204 if (is_overflow)
205 break;
206
207 }
208 else
209 {
210 p_cmd->status = GATT_NOT_FOUND;
211 break;
212 }
213
214 } /* loop through all handles*/
215
216
217 /* Sanity check on the buffer length */
218 if (p_buf->len == 0)
219 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700220 GATT_TRACE_ERROR("process_read_multi_rsp - nothing found!!");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800221 p_cmd->status = GATT_NOT_FOUND;
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800222 osi_free(p_buf);
223 GATT_TRACE_DEBUG("osi_free(p_buf)");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800224 }
225 else if (p_cmd->p_rsp_msg != NULL)
226 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800227 osi_free(p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800228 }
229 else
230 {
231 p_cmd->p_rsp_msg = p_buf;
232 }
233
Marie Janssend19e0782016-07-15 12:48:27 -0700234 return(true);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800235 }
236 }
237 else /* any handle read exception occurs, return error */
238 {
Marie Janssend19e0782016-07-15 12:48:27 -0700239 return(true);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800240 }
241
242 /* If here, still waiting */
Marie Janssend19e0782016-07-15 12:48:27 -0700243 return(false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800244}
245
246/*******************************************************************************
247**
248** Function gatt_sr_process_app_rsp
249**
250** Description This function checks whether the response message from application
251** match any pending request or not.
252**
253** Returns void
254**
255*******************************************************************************/
256tGATT_STATUS gatt_sr_process_app_rsp (tGATT_TCB *p_tcb, tGATT_IF gatt_if,
Myles Watsond35a6482016-10-27 08:52:16 -0700257 UNUSED_ATTR uint32_t trans_id, uint8_t op_code,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800258 tGATT_STATUS status, tGATTS_RSP *p_msg)
259{
260 tGATT_STATUS ret_code = GATT_SUCCESS;
261
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700262 GATT_TRACE_DEBUG("gatt_sr_process_app_rsp gatt_if=%d", gatt_if);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800263
Marie Janssend19e0782016-07-15 12:48:27 -0700264 gatt_sr_update_cback_cnt(p_tcb, gatt_if, false, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800265
266 if (op_code == GATT_REQ_READ_MULTI)
267 {
268 /* If no error and still waiting, just return */
269 if (!process_read_multi_rsp (&p_tcb->sr_cmd, status, p_msg, p_tcb->payload_size))
270 return(GATT_SUCCESS);
271 }
272 else
273 {
274 if (op_code == GATT_REQ_PREPARE_WRITE && status == GATT_SUCCESS)
Marie Janssend19e0782016-07-15 12:48:27 -0700275 gatt_sr_update_prep_cnt(p_tcb, gatt_if, true, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800276
277 if (op_code == GATT_REQ_EXEC_WRITE && status != GATT_SUCCESS)
278 gatt_sr_reset_cback_cnt(p_tcb);
279
280 p_tcb->sr_cmd.status = status;
281
282 if (gatt_sr_is_cback_cnt_zero(p_tcb)
283 && status == GATT_SUCCESS)
284 {
285 if (p_tcb->sr_cmd.p_rsp_msg == NULL)
286 {
Marie Janssend19e0782016-07-15 12:48:27 -0700287 p_tcb->sr_cmd.p_rsp_msg = attp_build_sr_msg (p_tcb, (uint8_t)(op_code + 1), (tGATT_SR_MSG *)p_msg);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800288 }
289 else
290 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700291 GATT_TRACE_ERROR("Exception!!! already has respond message");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800292 }
293 }
294 }
295 if (gatt_sr_is_cback_cnt_zero(p_tcb))
296 {
297 if ( (p_tcb->sr_cmd.status == GATT_SUCCESS) && (p_tcb->sr_cmd.p_rsp_msg) )
298 {
299 ret_code = attp_send_sr_msg (p_tcb, p_tcb->sr_cmd.p_rsp_msg);
300 p_tcb->sr_cmd.p_rsp_msg = NULL;
301 }
302 else
303 {
Marie Janssend19e0782016-07-15 12:48:27 -0700304 ret_code = gatt_send_error_rsp (p_tcb, status, op_code, p_tcb->sr_cmd.handle, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800305 }
306
307 gatt_dequeue_sr_cmd(p_tcb);
308 }
309
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700310 GATT_TRACE_DEBUG("gatt_sr_process_app_rsp ret_code=%d", ret_code);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800311
312 return ret_code;
313}
314
315/*******************************************************************************
316**
317** Function gatt_process_exec_write_req
318**
319** Description This function is called to process the execute write request
320** from client.
321**
322** Returns void
323**
324*******************************************************************************/
Myles Watsond35a6482016-10-27 08:52:16 -0700325void gatt_process_exec_write_req (tGATT_TCB *p_tcb, uint8_t op_code,
326 UNUSED_ATTR uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800327{
Marie Janssend19e0782016-07-15 12:48:27 -0700328 uint8_t *p = p_data, flag, i = 0;
329 uint32_t trans_id = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800330 tGATT_IF gatt_if;
Marie Janssend19e0782016-07-15 12:48:27 -0700331 uint16_t conn_id;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800332
Marie Janssend19e0782016-07-15 12:48:27 -0700333#if (GATT_CONFORMANCE_TESTING == TRUE)
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800334 if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
335 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700336 GATT_TRACE_DEBUG("Conformance tst: forced err rspv for Execute Write: error status=%d",
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -0700337 gatt_cb.err_status);
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800338
Marie Janssend19e0782016-07-15 12:48:27 -0700339 gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, gatt_cb.handle, false);
Ganesh Ganapathi Battaead3cde2013-02-05 15:22:31 -0800340
341 return;
342 }
343#endif
344
The Android Open Source Project5738f832012-12-12 16:00:35 -0800345 STREAM_TO_UINT8(flag, p);
346
347 /* mask the flag */
348 flag &= GATT_PREP_WRITE_EXEC;
349
350
351 /* no prep write is queued */
352 if (!gatt_sr_is_prep_cnt_zero(p_tcb))
353 {
354 trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, 0);
355 gatt_sr_copy_prep_cnt_to_cback_cnt(p_tcb);
356
357 for (i=0; i<GATT_MAX_APPS; i++)
358 {
359 if (p_tcb->prep_cnt[i])
360 {
361 gatt_if = (tGATT_IF) (i+1);
362 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
363 gatt_sr_send_req_callback(conn_id,
364 trans_id,
365 GATTS_REQ_TYPE_WRITE_EXEC,
366 (tGATTS_DATA *)&flag);
367 p_tcb->prep_cnt[i]= 0;
368 }
369 }
370 }
371 else /* nothing needs to be executed , send response now */
372 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700373 GATT_TRACE_ERROR("gatt_process_exec_write_req: no prepare write pending");
Marie Janssend19e0782016-07-15 12:48:27 -0700374 gatt_send_error_rsp(p_tcb, GATT_ERROR, GATT_REQ_EXEC_WRITE, 0, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800375 }
376}
377
378/*******************************************************************************
379**
380** Function gatt_process_read_multi_req
381**
382** Description This function is called to process the read multiple request
383** from client.
384**
385** Returns void
386**
387*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700388void gatt_process_read_multi_req (tGATT_TCB *p_tcb, uint8_t op_code, uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800389{
Marie Janssend19e0782016-07-15 12:48:27 -0700390 uint32_t trans_id;
391 uint16_t handle = 0, ll = len;
392 uint8_t *p = p_data, i_rcb;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800393 tGATT_STATUS err = GATT_SUCCESS;
Marie Janssend19e0782016-07-15 12:48:27 -0700394 uint8_t sec_flag, key_size;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800395
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700396 GATT_TRACE_DEBUG("gatt_process_read_multi_req" );
The Android Open Source Project5738f832012-12-12 16:00:35 -0800397 p_tcb->sr_cmd.multi_req.num_handles = 0;
398
399 gatt_sr_get_sec_info(p_tcb->peer_bda,
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -0700400 p_tcb->transport,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800401 &sec_flag,
402 &key_size);
403
Marie Janssend19e0782016-07-15 12:48:27 -0700404#if (GATT_CONFORMANCE_TESTING == TRUE)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800405 if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
406 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700407 GATT_TRACE_DEBUG("Conformance tst: forced err rspvofr ReadMultiple: error status=%d", gatt_cb.err_status);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800408
409 STREAM_TO_UINT16(handle, p);
410
Marie Janssend19e0782016-07-15 12:48:27 -0700411 gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, handle, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800412
413 return;
414 }
415#endif
416
417 while (ll >= 2 && p_tcb->sr_cmd.multi_req.num_handles < GATT_MAX_READ_MULTI_HANDLES)
418 {
419 STREAM_TO_UINT16(handle, p);
420
421 if ((i_rcb = gatt_sr_find_i_rcb_by_handle(handle)) < GATT_MAX_SR_PROFILES)
422 {
423 p_tcb->sr_cmd.multi_req.handles[p_tcb->sr_cmd.multi_req.num_handles++] = handle;
424
425 /* check read permission */
426 if ((err = gatts_read_attr_perm_check( gatt_cb.sr_reg[i_rcb].p_db,
Marie Janssend19e0782016-07-15 12:48:27 -0700427 false,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800428 handle,
429 sec_flag,
430 key_size))
431 != GATT_SUCCESS)
432 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700433 GATT_TRACE_DEBUG("read permission denied : 0x%02x", err);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800434 break;
435 }
436 }
437 else
438 {
439 /* invalid handle */
440 err = GATT_INVALID_HANDLE;
441 break;
442 }
443 ll -= 2;
444 }
445
446 if (ll != 0)
447 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700448 GATT_TRACE_ERROR("max attribute handle reached in ReadMultiple Request.");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800449 }
450
451 if (p_tcb->sr_cmd.multi_req.num_handles == 0)
452 err = GATT_INVALID_HANDLE;
453
454 if (err == GATT_SUCCESS)
455 {
456 if ((trans_id = gatt_sr_enqueue_cmd (p_tcb, op_code, p_tcb->sr_cmd.multi_req.handles[0])) != 0)
457 {
458 gatt_sr_reset_cback_cnt(p_tcb); /* read multiple use multi_rsp_q's count*/
459
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800460 for (ll = 0; ll < p_tcb->sr_cmd.multi_req.num_handles; ll ++) {
461 tGATTS_RSP *p_msg = (tGATTS_RSP *)osi_calloc(sizeof(tGATTS_RSP));
462 handle = p_tcb->sr_cmd.multi_req.handles[ll];
463 i_rcb = gatt_sr_find_i_rcb_by_handle(handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800464
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800465 p_msg->attr_value.handle = handle;
466 err = gatts_read_attr_value_by_handle(p_tcb,
467 gatt_cb.sr_reg[i_rcb].p_db,
468 op_code,
469 handle,
470 0,
471 p_msg->attr_value.value,
472 &p_msg->attr_value.len,
473 GATT_MAX_ATTR_LEN,
474 sec_flag,
475 key_size,
476 trans_id);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800477
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800478 if (err == GATT_SUCCESS) {
479 gatt_sr_process_app_rsp(p_tcb, gatt_cb.sr_reg[i_rcb].gatt_if ,trans_id, op_code, GATT_SUCCESS, p_msg);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800480 }
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800481 /* either not using or done using the buffer, release it now */
482 osi_free(p_msg);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800483 }
484 }
485 else
486 err = GATT_NO_RESOURCES;
487 }
488
489 /* in theroy BUSY is not possible(should already been checked), protected check */
490 if (err != GATT_SUCCESS && err != GATT_PENDING && err != GATT_BUSY)
Marie Janssend19e0782016-07-15 12:48:27 -0700491 gatt_send_error_rsp(p_tcb, err, op_code, handle, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800492}
493
494/*******************************************************************************
495**
496** Function gatt_build_primary_service_rsp
497**
498** Description Primamry service request processed internally. Theretically
499** only deal with ReadByTypeVAlue and ReadByGroupType.
500**
501** Returns void
502**
503*******************************************************************************/
504static tGATT_STATUS gatt_build_primary_service_rsp (BT_HDR *p_msg, tGATT_TCB *p_tcb,
Marie Janssend19e0782016-07-15 12:48:27 -0700505 uint8_t op_code, uint16_t s_hdl,
Myles Watsond35a6482016-10-27 08:52:16 -0700506 uint16_t e_hdl,
507 UNUSED_ATTR uint8_t *p_data, tBT_UUID value)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800508{
509 tGATT_STATUS status = GATT_NOT_FOUND;
Marie Janssend19e0782016-07-15 12:48:27 -0700510 uint8_t handle_len =4, *p ;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800511 tGATT_SR_REG *p_rcb;
512 tGATT_SRV_LIST_INFO *p_list= &gatt_cb.srv_list_info;
513 tGATT_SRV_LIST_ELEM *p_srv=NULL;
514 tBT_UUID *p_uuid;
515
Marie Janssend19e0782016-07-15 12:48:27 -0700516 p = (uint8_t *)(p_msg + 1) + L2CAP_MIN_OFFSET;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800517
518 p_srv = p_list->p_first;
519
520 while (p_srv)
521 {
522 p_rcb = GATT_GET_SR_REG_PTR(p_srv->i_sreg);
523
524 if (p_rcb->in_use &&
525 p_rcb->s_hdl >= s_hdl &&
526 p_rcb->s_hdl <= e_hdl &&
527 p_rcb->type == GATT_UUID_PRI_SERVICE)
528 {
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700529 if ((p_uuid = gatts_get_service_uuid (p_rcb->p_db)) != NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800530 {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800531 if (op_code == GATT_REQ_READ_BY_GRP_TYPE)
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700532 handle_len = 4 + p_uuid->len;
533
534 /* get the length byte in the repsonse */
535 if (p_msg->offset ==0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800536 {
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700537 *p ++ = op_code + 1;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800538 p_msg->len ++;
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700539 p_msg->offset = handle_len;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800540
541 if (op_code == GATT_REQ_READ_BY_GRP_TYPE)
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700542 {
Marie Janssend19e0782016-07-15 12:48:27 -0700543 *p ++ = (uint8_t)p_msg->offset; /* length byte */
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700544 p_msg->len ++;
545 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800546 }
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700547
548 if (p_msg->len + p_msg->offset <= p_tcb->payload_size &&
549 handle_len == p_msg->offset)
550 {
551 if (op_code != GATT_REQ_FIND_TYPE_VALUE ||
552 gatt_uuid_compare(value, *p_uuid))
553 {
554 UINT16_TO_STREAM(p, p_rcb->s_hdl);
555
556 if (p_list->p_last_primary == p_srv &&
557 p_list->p_last_primary == p_list->p_last)
558 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700559 GATT_TRACE_DEBUG("Use 0xFFFF for the last primary attribute");
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700560 UINT16_TO_STREAM(p, 0xFFFF); /* see GATT ERRATA 4065, 4063, ATT ERRATA 4062 */
561 }
562 else
563 {
564 UINT16_TO_STREAM(p, p_rcb->e_hdl);
565 }
566
567 if (op_code == GATT_REQ_READ_BY_GRP_TYPE)
568 gatt_build_uuid_to_stream(&p, *p_uuid);
569
570 status = GATT_SUCCESS;
571 p_msg->len += p_msg->offset;
572 }
573 }
574 else
575 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800576 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800577 }
578 p_srv = p_srv->p_next;
579 }
580 p_msg->offset = L2CAP_MIN_OFFSET;
581
582 return status;
583}
584
585/*******************************************************************************
586**
587** Function gatt_build_find_info_rsp
588**
589** Description fill the find information response information in the given
590** buffer.
591**
Marie Janssend19e0782016-07-15 12:48:27 -0700592** Returns true: if data filled sucessfully.
593** false: packet full, or format mismatch.
The Android Open Source Project5738f832012-12-12 16:00:35 -0800594**
595*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700596static tGATT_STATUS gatt_build_find_info_rsp(tGATT_SR_REG *p_rcb, BT_HDR *p_msg, uint16_t *p_len,
597 uint16_t s_hdl, uint16_t e_hdl)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800598{
599 tGATT_STATUS status = GATT_NOT_FOUND;
Marie Janssend19e0782016-07-15 12:48:27 -0700600 uint8_t *p;
601 uint16_t len = *p_len;
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -0700602 tGATT_ATTR *p_attr = NULL;
Marie Janssend19e0782016-07-15 12:48:27 -0700603 uint8_t info_pair_len[2] = {4, 18};
The Android Open Source Project5738f832012-12-12 16:00:35 -0800604
605 if (!p_rcb->p_db || !p_rcb->p_db->p_attr_list)
606 return status;
607
608 /* check the attribute database */
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -0700609 p_attr = (tGATT_ATTR *) p_rcb->p_db->p_attr_list;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800610
Marie Janssend19e0782016-07-15 12:48:27 -0700611 p = (uint8_t *)(p_msg + 1) + L2CAP_MIN_OFFSET + p_msg->len;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800612
613 while (p_attr)
614 {
615 if (p_attr->handle > e_hdl)
616 {
617 break;
618 }
619
620 if (p_attr->handle >= s_hdl)
621 {
622 if (p_msg->offset == 0)
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -0700623 p_msg->offset = (p_attr->uuid.len == LEN_UUID_16) ? GATT_INFO_TYPE_PAIR_16 : GATT_INFO_TYPE_PAIR_128;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800624
625 if (len >= info_pair_len[p_msg->offset - 1])
626 {
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -0700627 if (p_msg->offset == GATT_INFO_TYPE_PAIR_16 && p_attr->uuid.len == LEN_UUID_16)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800628 {
629 UINT16_TO_STREAM(p, p_attr->handle);
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -0700630 UINT16_TO_STREAM(p, p_attr->uuid.uu.uuid16);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800631 }
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -0700632 else if (p_msg->offset == GATT_INFO_TYPE_PAIR_128 && p_attr->uuid.len == LEN_UUID_128 )
The Android Open Source Project5738f832012-12-12 16:00:35 -0800633 {
634 UINT16_TO_STREAM(p, p_attr->handle);
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -0700635 ARRAY_TO_STREAM (p, p_attr->uuid.uu.uuid128, LEN_UUID_128);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800636 }
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -0700637 else if (p_msg->offset == GATT_INFO_TYPE_PAIR_128 && p_attr->uuid.len == LEN_UUID_32)
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -0700638 {
639 UINT16_TO_STREAM(p, p_attr->handle);
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -0700640 gatt_convert_uuid32_to_uuid128(p, p_attr->uuid.uu.uuid32);
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -0700641 p += LEN_UUID_128;
642 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800643 else
644 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700645 GATT_TRACE_ERROR("format mismatch");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800646 status = GATT_NO_RESOURCES;
647 break;
648 /* format mismatch */
649 }
650 p_msg->len += info_pair_len[p_msg->offset - 1];
651 len -= info_pair_len[p_msg->offset - 1];
652 status = GATT_SUCCESS;
653
654 }
655 else
656 {
657 status = GATT_NO_RESOURCES;
658 break;
659 }
660 }
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -0700661 p_attr = (tGATT_ATTR *)p_attr->p_next;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800662 }
663
664 *p_len = len;
665 return status;
666}
667
668/*******************************************************************************
669**
670** Function gatts_internal_read_by_type_req
671**
672** Description check to see if the ReadByType request can be handled internally.
673**
674** Returns void
675**
676*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700677static tGATT_STATUS gatts_validate_packet_format(uint8_t op_code, uint16_t *p_len,
678 uint8_t **p_data, tBT_UUID *p_uuid_filter,
679 uint16_t *p_s_hdl, uint16_t *p_e_hdl)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800680{
681 tGATT_STATUS reason = GATT_SUCCESS;
Marie Janssend19e0782016-07-15 12:48:27 -0700682 uint16_t uuid_len, s_hdl = 0, e_hdl = 0;
683 uint16_t len = *p_len;
684 uint8_t *p = *p_data;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800685
686 if (len >= 4)
687 {
688 /* obtain starting handle, and ending handle */
689 STREAM_TO_UINT16(s_hdl, p);
690 STREAM_TO_UINT16(e_hdl, p);
691 len -= 4;
692
693 if (s_hdl > e_hdl || !GATT_HANDLE_IS_VALID(s_hdl) || !GATT_HANDLE_IS_VALID(e_hdl))
694 {
695 reason = GATT_INVALID_HANDLE;
696 }
697 /* for these PDUs, uuid filter must present */
698 else if (op_code == GATT_REQ_READ_BY_GRP_TYPE ||
699 op_code == GATT_REQ_FIND_TYPE_VALUE ||
700 op_code == GATT_REQ_READ_BY_TYPE)
701 {
702 if (len >= 2 && p_uuid_filter != NULL)
703 {
704 uuid_len = (op_code == GATT_REQ_FIND_TYPE_VALUE) ? 2 : len;
705
706 /* parse uuid now */
Marie Janssend19e0782016-07-15 12:48:27 -0700707 if (gatt_parse_uuid_from_cmd (p_uuid_filter, uuid_len, &p) == false ||
The Android Open Source Project5738f832012-12-12 16:00:35 -0800708 p_uuid_filter->len == 0)
709 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700710 GATT_TRACE_DEBUG("UUID filter does not exsit");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800711 reason = GATT_INVALID_PDU;
712 }
713 else
714 len -= p_uuid_filter->len;
715 }
716 else
717 reason = GATT_INVALID_PDU;
718 }
719 }
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700720 else
721 reason = GATT_INVALID_PDU;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800722
723 *p_data = p;
724 *p_len = len;
725 *p_s_hdl = s_hdl;
726 *p_e_hdl = e_hdl;
727
728 return reason;
729}
730
731/*******************************************************************************
732**
733** Function gatts_process_primary_service_req
734**
735** Description process ReadByGroupType/ReadByTypeValue request, for discover
736** all primary services or discover primary service by UUID request.
737**
738** Returns void
739**
740*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700741void gatts_process_primary_service_req(tGATT_TCB *p_tcb, uint8_t op_code, uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800742{
Marie Janssend19e0782016-07-15 12:48:27 -0700743 uint8_t reason = GATT_INVALID_PDU;
744 uint16_t s_hdl = 0, e_hdl = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800745 tBT_UUID uuid, value, primary_service = {LEN_UUID_16, {GATT_UUID_PRI_SERVICE}};
746 BT_HDR *p_msg = NULL;
Marie Janssend19e0782016-07-15 12:48:27 -0700747 uint16_t msg_len = (uint16_t)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800748
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -0700749 memset (&value, 0, sizeof(tBT_UUID));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800750 reason = gatts_validate_packet_format(op_code, &len, &p_data, &uuid, &s_hdl, &e_hdl);
751
752 if (reason == GATT_SUCCESS)
753 {
754 if (gatt_uuid_compare(uuid, primary_service))
755 {
756 if (op_code == GATT_REQ_FIND_TYPE_VALUE)
757 {
Marie Janssend19e0782016-07-15 12:48:27 -0700758 if (gatt_parse_uuid_from_cmd(&value, len, &p_data) == false)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800759 reason = GATT_INVALID_PDU;
760 }
761
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800762 if (reason == GATT_SUCCESS) {
763 p_msg = (BT_HDR *)osi_calloc(msg_len);
764 reason = gatt_build_primary_service_rsp (p_msg, p_tcb, op_code,
765 s_hdl, e_hdl, p_data,
766 value);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800767 }
768 }
769 else
770 {
771 if (op_code == GATT_REQ_READ_BY_GRP_TYPE)
772 {
773 reason = GATT_UNSUPPORT_GRP_TYPE;
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700774 GATT_TRACE_DEBUG("unexpected ReadByGrpType Group: 0x%04x", uuid.uu.uuid16);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800775 }
776 else
777 {
778 /* we do not support ReadByTypeValue with any non-primamry_service type */
779 reason = GATT_NOT_FOUND;
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700780 GATT_TRACE_DEBUG("unexpected ReadByTypeValue type: 0x%04x", uuid.uu.uuid16);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800781 }
782 }
783 }
784
785 if (reason != GATT_SUCCESS)
786 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800787 osi_free(p_msg);
Marie Janssend19e0782016-07-15 12:48:27 -0700788 gatt_send_error_rsp (p_tcb, reason, op_code, s_hdl, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800789 }
790 else
791 attp_send_sr_msg(p_tcb, p_msg);
792
793}
794
795/*******************************************************************************
796**
797** Function gatts_process_find_info
798**
799** Description process find information request, for discover character
800** descriptors.
801**
802** Returns void
803**
804*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700805static void gatts_process_find_info(tGATT_TCB *p_tcb, uint8_t op_code, uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800806{
Marie Janssend19e0782016-07-15 12:48:27 -0700807 uint8_t reason = GATT_INVALID_PDU, *p;
808 uint16_t s_hdl = 0, e_hdl = 0, buf_len;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800809 BT_HDR *p_msg = NULL;
810 tGATT_SR_REG *p_rcb;
811 tGATT_SRV_LIST_INFO *p_list= &gatt_cb.srv_list_info;
812 tGATT_SRV_LIST_ELEM *p_srv=NULL;
813
814 reason = gatts_validate_packet_format(op_code, &len, &p_data, NULL, &s_hdl, &e_hdl);
815
816 if (reason == GATT_SUCCESS)
817 {
Marie Janssend19e0782016-07-15 12:48:27 -0700818 buf_len = (uint16_t)(sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800819
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800820 p_msg = (BT_HDR *)osi_calloc(buf_len);
821 reason = GATT_NOT_FOUND;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800822
Marie Janssend19e0782016-07-15 12:48:27 -0700823 p = (uint8_t *)(p_msg + 1) + L2CAP_MIN_OFFSET;
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800824 *p ++ = op_code + 1;
825 p_msg->len = 2;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800826
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800827 buf_len = p_tcb->payload_size - 2;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800828
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800829 p_srv = p_list->p_first;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800830
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800831 while (p_srv) {
832 p_rcb = GATT_GET_SR_REG_PTR(p_srv->i_sreg);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800833
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800834 if (p_rcb->in_use && !(p_rcb->s_hdl > e_hdl ||
835 p_rcb->e_hdl < s_hdl)) {
836 reason = gatt_build_find_info_rsp(p_rcb, p_msg, &buf_len,
837 s_hdl, e_hdl);
838 if (reason == GATT_NO_RESOURCES) {
839 reason = GATT_SUCCESS;
840 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800841 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800842 }
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800843 p_srv = p_srv->p_next;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800844 }
Marie Janssend19e0782016-07-15 12:48:27 -0700845 *p = (uint8_t)p_msg->offset;
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800846
847 p_msg->offset = L2CAP_MIN_OFFSET;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800848 }
849
850 if (reason != GATT_SUCCESS)
851 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800852 osi_free(p_msg);
Marie Janssend19e0782016-07-15 12:48:27 -0700853 gatt_send_error_rsp (p_tcb, reason, op_code, s_hdl, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800854 }
855 else
856 attp_send_sr_msg(p_tcb, p_msg);
857
858}
859
860/*******************************************************************************
861**
862** Function gatts_process_mtu_req
863**
864** Description This function is called to process excahnge MTU request.
865** Only used on LE.
866**
867** Returns void
868**
869*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700870static void gatts_process_mtu_req (tGATT_TCB *p_tcb, uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800871{
Marie Janssend19e0782016-07-15 12:48:27 -0700872 uint16_t mtu = 0;
873 uint8_t *p = p_data, i;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800874 BT_HDR *p_buf;
Marie Janssend19e0782016-07-15 12:48:27 -0700875 uint16_t conn_id;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800876
The Android Open Source Project5738f832012-12-12 16:00:35 -0800877 /* BR/EDR conenction, send error response */
878 if (p_tcb->att_lcid != L2CAP_ATT_CID)
879 {
Marie Janssend19e0782016-07-15 12:48:27 -0700880 gatt_send_error_rsp (p_tcb, GATT_REQ_NOT_SUPPORTED, GATT_REQ_MTU, 0, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800881 }
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700882 else if (len < GATT_MTU_REQ_MIN_LEN)
883 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700884 GATT_TRACE_ERROR("invalid MTU request PDU received.");
Marie Janssend19e0782016-07-15 12:48:27 -0700885 gatt_send_error_rsp (p_tcb, GATT_INVALID_PDU, GATT_REQ_MTU, 0, false);
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700886 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800887 else
888 {
Andre Eisenbachccf9c152013-10-02 15:37:21 -0700889 STREAM_TO_UINT16 (mtu, p);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800890 /* mtu must be greater than default MTU which is 23/48 */
Andre Eisenbach4b638692013-06-14 13:22:25 -0700891 if (mtu < GATT_DEF_BLE_MTU_SIZE)
892 p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
893 else if (mtu > GATT_MAX_MTU_SIZE)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800894 p_tcb->payload_size = GATT_MAX_MTU_SIZE;
Andre Eisenbach4b638692013-06-14 13:22:25 -0700895 else
896 p_tcb->payload_size = mtu;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800897
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700898 GATT_TRACE_ERROR("MTU request PDU with MTU size %d", p_tcb->payload_size);
Zhihai Xu52c0ccb2014-03-20 17:50:12 -0700899
Priti Aghera636d6712014-12-18 13:55:48 -0800900 l2cble_set_fixed_channel_tx_data_length(p_tcb->peer_bda, L2CAP_ATT_CID, p_tcb->payload_size);
901
The Android Open Source Project5738f832012-12-12 16:00:35 -0800902 if ((p_buf = attp_build_sr_msg(p_tcb, GATT_RSP_MTU, (tGATT_SR_MSG *) &p_tcb->payload_size)) != NULL)
903 {
904 attp_send_sr_msg (p_tcb, p_buf);
905
906 /* Notify all registered applicaiton with new MTU size. Us a transaction ID */
907 /* of 0, as no response is allowed from applcations */
908
909 for (i = 0; i < GATT_MAX_APPS; i ++)
910 {
911 if (gatt_cb.cl_rcb[i].in_use )
912 {
913 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_cb.cl_rcb[i].gatt_if);
914 gatt_sr_send_req_callback(conn_id, 0, GATTS_REQ_TYPE_MTU,
915 (tGATTS_DATA *)&p_tcb->payload_size);
916 }
917 }
918
919 }
920 }
921}
922
923/*******************************************************************************
924**
925** Function gatts_process_read_by_type_req
926**
927** Description process Read By type request.
928** This PDU can be used to perform:
929** - read characteristic value
930** - read characteristic descriptor value
931** - discover characteristic
932** - discover characteristic by UUID
933** - relationship discovery
934**
935** Returns void
936**
937*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700938void gatts_process_read_by_type_req(tGATT_TCB *p_tcb, uint8_t op_code, uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800939{
940 tBT_UUID uuid;
941 tGATT_SR_REG *p_rcb;
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800942 size_t msg_len = sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET;
Marie Janssend19e0782016-07-15 12:48:27 -0700943 uint16_t buf_len, s_hdl, e_hdl, err_hdl = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800944 BT_HDR *p_msg = NULL;
945 tGATT_STATUS reason, ret;
Marie Janssend19e0782016-07-15 12:48:27 -0700946 uint8_t *p;
947 uint8_t sec_flag, key_size;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800948 tGATT_SRV_LIST_INFO *p_list= &gatt_cb.srv_list_info;
949 tGATT_SRV_LIST_ELEM *p_srv=NULL;
950
951 reason = gatts_validate_packet_format(op_code, &len, &p_data, &uuid, &s_hdl, &e_hdl);
952
Marie Janssend19e0782016-07-15 12:48:27 -0700953#if (GATT_CONFORMANCE_TESTING == TRUE)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800954 if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
955 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -0700956 GATT_TRACE_DEBUG("Conformance tst: forced err rsp for ReadByType: error status=%d", gatt_cb.err_status);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800957
Marie Janssend19e0782016-07-15 12:48:27 -0700958 gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, s_hdl, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800959
960 return;
961 }
962#endif
963
964 if (reason == GATT_SUCCESS)
965 {
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800966 p_msg = (BT_HDR *)osi_calloc(msg_len);
Marie Janssend19e0782016-07-15 12:48:27 -0700967 p = (uint8_t *)(p_msg + 1) + L2CAP_MIN_OFFSET;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800968
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800969 *p ++ = op_code + 1;
970 /* reserve length byte */
971 p_msg->len = 2;
972 buf_len = p_tcb->payload_size - 2;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800973
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800974 reason = GATT_NOT_FOUND;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800975
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800976 p_srv = p_list->p_first;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800977
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800978 while (p_srv) {
979 p_rcb = GATT_GET_SR_REG_PTR(p_srv->i_sreg);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800980
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800981 if (p_rcb->in_use && !(p_rcb->s_hdl > e_hdl ||
982 p_rcb->e_hdl < s_hdl)) {
983 gatt_sr_get_sec_info(p_tcb->peer_bda, p_tcb->transport,
984 &sec_flag, &key_size);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800985
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800986 ret = gatts_db_read_attr_value_by_type(p_tcb,
987 p_rcb->p_db,
988 op_code,
989 p_msg,
990 s_hdl,
991 e_hdl,
992 uuid,
993 &buf_len,
994 sec_flag,
995 key_size,
996 0,
997 &err_hdl);
998 if (ret != GATT_NOT_FOUND) {
999 reason = ret;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001000
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001001 if (ret == GATT_NO_RESOURCES)
1002 reason = GATT_SUCCESS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001003 }
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001004 if (ret != GATT_SUCCESS && ret != GATT_NOT_FOUND) {
1005 s_hdl = err_hdl;
1006 break;
1007 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001008 }
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001009 p_srv = p_srv->p_next;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001010 }
Marie Janssend19e0782016-07-15 12:48:27 -07001011 *p = (uint8_t)p_msg->offset;
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001012 p_msg->offset = L2CAP_MIN_OFFSET;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001013 }
1014 if (reason != GATT_SUCCESS)
1015 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08001016 osi_free(p_msg);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001017
1018 /* in theroy BUSY is not possible(should already been checked), protected check */
1019 if (reason != GATT_PENDING && reason != GATT_BUSY)
Marie Janssend19e0782016-07-15 12:48:27 -07001020 gatt_send_error_rsp (p_tcb, reason, op_code, s_hdl, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001021 }
1022 else
1023 attp_send_sr_msg(p_tcb, p_msg);
1024
1025}
1026
1027/*******************************************************************************
1028**
1029** Function gatts_process_write_req
1030**
1031** Description This function is called to process the write request
1032** from client.
1033**
1034** Returns void
1035**
1036*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001037void gatts_process_write_req (tGATT_TCB *p_tcb, uint8_t i_rcb, uint16_t handle,
1038 uint8_t op_code, uint16_t len, uint8_t *p_data,
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -07001039 bt_gatt_db_attribute_type_t gatt_type)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001040{
1041 tGATTS_DATA sr_data;
Marie Janssend19e0782016-07-15 12:48:27 -07001042 uint32_t trans_id;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001043 tGATT_STATUS status;
Marie Janssend19e0782016-07-15 12:48:27 -07001044 uint8_t sec_flag, key_size, *p = p_data;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001045 tGATT_SR_REG *p_sreg;
Marie Janssend19e0782016-07-15 12:48:27 -07001046 uint16_t conn_id;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001047
1048 memset(&sr_data, 0, sizeof(tGATTS_DATA));
1049
1050 switch (op_code)
1051 {
1052 case GATT_REQ_PREPARE_WRITE:
Subramanian Srinivasan0acfd132016-02-01 16:21:10 -08001053 if (len < 2) {
1054 GATT_TRACE_ERROR("%s: Prepare write request was invalid - missing offset, sending error response", __func__);
Marie Janssend19e0782016-07-15 12:48:27 -07001055 gatt_send_error_rsp(p_tcb, GATT_INVALID_PDU, op_code, handle, false);
Subramanian Srinivasan0acfd132016-02-01 16:21:10 -08001056 return;
1057 }
Marie Janssend19e0782016-07-15 12:48:27 -07001058 sr_data.write_req.is_prep = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001059 STREAM_TO_UINT16(sr_data.write_req.offset, p);
1060 len -= 2;
1061 /* fall through */
1062 case GATT_SIGN_CMD_WRITE:
1063 if (op_code == GATT_SIGN_CMD_WRITE)
1064 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001065 GATT_TRACE_DEBUG("Write CMD with data sigining" );
The Android Open Source Project5738f832012-12-12 16:00:35 -08001066 len -= GATT_AUTH_SIGN_LEN;
1067 }
1068 /* fall through */
1069 case GATT_CMD_WRITE:
1070 case GATT_REQ_WRITE:
1071 if (op_code == GATT_REQ_WRITE || op_code == GATT_REQ_PREPARE_WRITE)
Marie Janssend19e0782016-07-15 12:48:27 -07001072 sr_data.write_req.need_rsp = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001073 sr_data.write_req.handle = handle;
1074 sr_data.write_req.len = len;
Satya Calloji444a8da2015-03-06 10:38:22 -08001075 if (len != 0 && p != NULL)
1076 {
1077 memcpy (sr_data.write_req.value, p, len);
1078 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001079 break;
1080 }
1081
1082 gatt_sr_get_sec_info(p_tcb->peer_bda,
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -07001083 p_tcb->transport,
The Android Open Source Project5738f832012-12-12 16:00:35 -08001084 &sec_flag,
1085 &key_size);
1086
1087 status = gatts_write_attr_perm_check (gatt_cb.sr_reg[i_rcb].p_db,
1088 op_code,
1089 handle,
1090 sr_data.write_req.offset,
1091 p,
1092 len,
1093 sec_flag,
1094 key_size);
1095
1096 if (status == GATT_SUCCESS)
1097 {
1098 if ((trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, handle)) != 0)
1099 {
1100 p_sreg = &gatt_cb.sr_reg[i_rcb];
1101 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_sreg->gatt_if);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001102
Marie Janssend19e0782016-07-15 12:48:27 -07001103 uint8_t opcode = 0;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -07001104 if (gatt_type == BTGATT_DB_DESCRIPTOR) {
1105 opcode = GATTS_REQ_TYPE_WRITE_DESCRIPTOR;
1106 } else if (gatt_type == BTGATT_DB_CHARACTERISTIC) {
1107 opcode = GATTS_REQ_TYPE_WRITE_CHARACTERISTIC;
1108 } else {
1109 GATT_TRACE_ERROR("%s: Attempt to write attribute that's not tied with"
1110 " characteristic or descriptor value.", __func__);
1111 status = GATT_ERROR;
1112 }
1113
1114 if (opcode) {
1115 gatt_sr_send_req_callback(conn_id, trans_id, opcode, &sr_data);
1116 status = GATT_PENDING;
1117 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001118 }
1119 else
1120 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001121 GATT_TRACE_ERROR("max pending command, send error");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001122 status = GATT_BUSY; /* max pending command, application error */
1123 }
1124 }
1125
1126 /* in theroy BUSY is not possible(should already been checked), protected check */
1127 if (status != GATT_PENDING && status != GATT_BUSY &&
1128 (op_code == GATT_REQ_PREPARE_WRITE || op_code == GATT_REQ_WRITE))
1129 {
Marie Janssend19e0782016-07-15 12:48:27 -07001130 gatt_send_error_rsp (p_tcb, status, op_code, handle, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001131 }
1132 return;
1133}
1134
1135/*******************************************************************************
1136**
1137** Function gatts_process_read_req
1138**
1139** Description This function is called to process the read request
1140** from client.
1141**
1142** Returns void
1143**
1144*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001145static void gatts_process_read_req(tGATT_TCB *p_tcb, tGATT_SR_REG *p_rcb, uint8_t op_code,
Myles Watsond35a6482016-10-27 08:52:16 -07001146 uint16_t handle,
1147 UNUSED_ATTR uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001148{
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08001149 size_t buf_len = sizeof(BT_HDR) + p_tcb->payload_size + L2CAP_MIN_OFFSET;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001150 tGATT_STATUS reason;
Marie Janssend19e0782016-07-15 12:48:27 -07001151 uint8_t sec_flag, key_size, *p;
1152 uint16_t offset = 0, value_len = 0;
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001153 BT_HDR *p_msg = (BT_HDR *)osi_calloc(buf_len);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001154
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001155 if (op_code == GATT_REQ_READ_BLOB)
1156 STREAM_TO_UINT16(offset, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001157
Marie Janssend19e0782016-07-15 12:48:27 -07001158 p = (uint8_t *)(p_msg + 1) + L2CAP_MIN_OFFSET;
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001159 *p ++ = op_code + 1;
1160 p_msg->len = 1;
1161 buf_len = p_tcb->payload_size - 1;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001162
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001163 gatt_sr_get_sec_info(p_tcb->peer_bda, p_tcb->transport, &sec_flag,
1164 &key_size);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001165
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001166 reason = gatts_read_attr_value_by_handle(p_tcb,
1167 p_rcb->p_db,
1168 op_code,
1169 handle,
1170 offset,
1171 p,
1172 &value_len,
1173 (uint16_t)buf_len,
1174 sec_flag,
1175 key_size,
1176 0);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001177
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -08001178 p_msg->len += value_len;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001179
1180 if (reason != GATT_SUCCESS)
1181 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08001182 osi_free(p_msg);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001183
1184 /* in theroy BUSY is not possible(should already been checked), protected check */
1185 if (reason != GATT_PENDING && reason != GATT_BUSY)
Marie Janssend19e0782016-07-15 12:48:27 -07001186 gatt_send_error_rsp (p_tcb, reason, op_code, handle, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001187 }
1188 else
1189 attp_send_sr_msg(p_tcb, p_msg);
1190
1191}
1192
1193/*******************************************************************************
1194**
1195** Function gatts_process_attribute_req
1196**
1197** Description This function is called to process the per attribute handle request
1198** from client.
1199**
1200** Returns void
1201**
1202*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001203void gatts_process_attribute_req (tGATT_TCB *p_tcb, uint8_t op_code,
1204 uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001205{
Marie Janssend19e0782016-07-15 12:48:27 -07001206 uint16_t handle = 0;
1207 uint8_t *p = p_data, i;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001208 tGATT_SR_REG *p_rcb = gatt_cb.sr_reg;
1209 tGATT_STATUS status = GATT_INVALID_HANDLE;
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -07001210 tGATT_ATTR *p_attr;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001211
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001212 if (len < 2)
1213 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001214 GATT_TRACE_ERROR("Illegal PDU length, discard request");
Andre Eisenbachccf9c152013-10-02 15:37:21 -07001215 status = GATT_INVALID_PDU;
1216 }
1217 else
1218 {
1219 STREAM_TO_UINT16(handle, p);
1220 len -= 2;
1221 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001222
Marie Janssend19e0782016-07-15 12:48:27 -07001223#if (GATT_CONFORMANCE_TESTING == TRUE)
Andre Eisenbach6975b4d2013-08-05 16:55:38 -07001224 gatt_cb.handle = handle;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001225 if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
1226 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001227 GATT_TRACE_DEBUG("Conformance tst: forced err rsp: error status=%d", gatt_cb.err_status);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001228
Marie Janssend19e0782016-07-15 12:48:27 -07001229 gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, handle, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001230
1231 return;
1232 }
1233#endif
1234
1235 if (GATT_HANDLE_IS_VALID(handle))
1236 {
1237 for (i = 0; i < GATT_MAX_SR_PROFILES; i ++, p_rcb ++)
1238 {
1239 if (p_rcb->in_use && p_rcb->s_hdl <= handle && p_rcb->e_hdl >= handle)
1240 {
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -07001241 p_attr = (tGATT_ATTR *)p_rcb->p_db->p_attr_list;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001242
1243 while (p_attr)
1244 {
1245 if (p_attr->handle == handle)
1246 {
1247 switch (op_code)
1248 {
1249 case GATT_REQ_READ: /* read char/char descriptor value */
1250 case GATT_REQ_READ_BLOB:
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -07001251 gatts_process_read_req(p_tcb, p_rcb, op_code, handle, len, p);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001252 break;
1253
1254 case GATT_REQ_WRITE: /* write char/char descriptor value */
1255 case GATT_CMD_WRITE:
1256 case GATT_SIGN_CMD_WRITE:
1257 case GATT_REQ_PREPARE_WRITE:
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -07001258 gatts_process_write_req(p_tcb, i, handle, op_code, len, p,
1259 p_attr->gatt_type);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001260 break;
1261 default:
1262 break;
1263 }
1264 status = GATT_SUCCESS;
1265 break;
1266 }
Jakub Pawlowskic88b20a2016-06-21 16:16:09 -07001267 p_attr = (tGATT_ATTR *)p_attr->p_next;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001268 }
1269 break;
1270 }
1271 }
1272 }
1273
1274 if (status != GATT_SUCCESS && op_code != GATT_CMD_WRITE && op_code != GATT_SIGN_CMD_WRITE)
Marie Janssend19e0782016-07-15 12:48:27 -07001275 gatt_send_error_rsp (p_tcb, status, op_code, handle, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001276}
1277
1278/*******************************************************************************
1279**
1280** Function gatts_proc_srv_chg_ind_ack
1281**
1282** Description This function process the service changed indicaiton ACK
1283**
1284** Returns void
1285**
1286*******************************************************************************/
1287static void gatts_proc_srv_chg_ind_ack(tGATT_TCB *p_tcb )
1288{
1289 tGATTS_SRV_CHG_REQ req;
1290 tGATTS_SRV_CHG *p_buf = NULL;
1291
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001292 GATT_TRACE_DEBUG("gatts_proc_srv_chg_ind_ack");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001293
1294 if ((p_buf = gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda)) != NULL)
1295 {
Marie Janssend19e0782016-07-15 12:48:27 -07001296 GATT_TRACE_DEBUG("NV update set srv chg = false");
1297 p_buf->srv_changed = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001298 memcpy(&req.srv_chg, p_buf, sizeof(tGATTS_SRV_CHG));
1299 if (gatt_cb.cb_info.p_srv_chg_callback)
1300 (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_UPDATE_CLIENT,&req, NULL);
1301 }
1302}
1303
1304/*******************************************************************************
1305**
1306** Function gatts_chk_pending_ind
1307**
1308** Description This function check any pending indication needs to be sent if
1309** there is a pending indication then sent the indication
1310**
1311** Returns void
1312**
1313*******************************************************************************/
1314static void gatts_chk_pending_ind(tGATT_TCB *p_tcb )
1315{
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001316 GATT_TRACE_DEBUG("%s", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001317
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001318 tGATT_VALUE *p_buf = (tGATT_VALUE *)fixed_queue_try_peek_first(p_tcb->pending_ind_q);
1319 if (p_buf != NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001320 {
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001321 GATTS_HandleValueIndication(p_buf->conn_id,
1322 p_buf->handle,
1323 p_buf->len,
1324 p_buf->value);
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08001325 osi_free(fixed_queue_try_remove_from_queue(p_tcb->pending_ind_q,
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001326 p_buf));
The Android Open Source Project5738f832012-12-12 16:00:35 -08001327 }
1328}
1329
1330/*******************************************************************************
1331**
1332** Function gatts_proc_ind_ack
1333**
1334** Description This function process the Indication ack
1335**
Marie Janssend19e0782016-07-15 12:48:27 -07001336** Returns true continue to process the indication ack by the aaplication
The Android Open Source Project5738f832012-12-12 16:00:35 -08001337** if the ACk is not a Service Changed Indication Ack
1338**
1339*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001340static bool gatts_proc_ind_ack(tGATT_TCB *p_tcb, uint16_t ack_handle)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001341{
Marie Janssend19e0782016-07-15 12:48:27 -07001342 bool continue_processing = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001343
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001344 GATT_TRACE_DEBUG ("gatts_proc_ind_ack ack handle=%d", ack_handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001345
1346 if (ack_handle == gatt_cb.handle_of_h_r)
1347 {
1348 gatts_proc_srv_chg_ind_ack(p_tcb);
1349 /* there is no need to inform the application since srv chg is handled internally by GATT */
Marie Janssend19e0782016-07-15 12:48:27 -07001350 continue_processing = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001351 }
1352
1353 gatts_chk_pending_ind(p_tcb);
1354 return continue_processing;
1355}
1356
1357/*******************************************************************************
1358**
1359** Function gatts_process_value_conf
1360**
1361** Description This function is called to process the handle value confirmation.
1362**
1363** Returns void
1364**
1365*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001366void gatts_process_value_conf(tGATT_TCB *p_tcb, uint8_t op_code)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001367{
Marie Janssend19e0782016-07-15 12:48:27 -07001368 uint16_t handle = p_tcb->indicate_handle;
1369 uint32_t trans_id;
1370 uint8_t i;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001371 tGATT_SR_REG *p_rcb = gatt_cb.sr_reg;
Marie Janssend19e0782016-07-15 12:48:27 -07001372 bool continue_processing;
1373 uint16_t conn_id;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001374
Pavlin Radoslavov78bcff72015-12-04 17:36:34 -08001375 alarm_cancel(p_tcb->conf_timer);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001376 if (GATT_HANDLE_IS_VALID(handle))
1377 {
1378 p_tcb->indicate_handle = 0;
1379 continue_processing = gatts_proc_ind_ack(p_tcb, handle);
1380
1381 if (continue_processing)
1382 {
1383 for (i = 0; i < GATT_MAX_SR_PROFILES; i ++, p_rcb ++)
1384 {
1385 if (p_rcb->in_use && p_rcb->s_hdl <= handle && p_rcb->e_hdl >= handle)
1386 {
1387 trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, handle);
1388 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_rcb->gatt_if);
1389 gatt_sr_send_req_callback(conn_id,
1390 trans_id, GATTS_REQ_TYPE_CONF, (tGATTS_DATA *)&handle);
1391 }
1392 }
1393 }
1394 }
1395 else
1396 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001397 GATT_TRACE_ERROR("unexpected handle value confirmation");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001398 }
1399}
1400
1401/*******************************************************************************
1402**
1403** Function gatt_server_handle_client_req
1404**
1405** Description This function is called to handle the client requests to
1406** server.
1407**
1408**
1409** Returns void
1410**
1411*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001412void gatt_server_handle_client_req (tGATT_TCB *p_tcb, uint8_t op_code,
1413 uint16_t len, uint8_t *p_data)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001414{
1415 /* there is pending command, discard this one */
1416 if (!gatt_sr_cmd_empty(p_tcb) && op_code != GATT_HANDLE_VALUE_CONF)
1417 return;
1418
1419 /* the size of the message may not be bigger than the local max PDU size*/
1420 /* The message has to be smaller than the agreed MTU, len does not include op code */
1421 if (len >= p_tcb->payload_size)
1422 {
Sharvil Nanavatib44cc592014-05-04 10:03:35 -07001423 GATT_TRACE_ERROR("server receive invalid PDU size:%d pdu size:%d", len + 1, p_tcb->payload_size );
The Android Open Source Project5738f832012-12-12 16:00:35 -08001424 /* for invalid request expecting response, send it now */
1425 if (op_code != GATT_CMD_WRITE &&
1426 op_code != GATT_SIGN_CMD_WRITE &&
1427 op_code != GATT_HANDLE_VALUE_CONF)
1428 {
Marie Janssend19e0782016-07-15 12:48:27 -07001429 gatt_send_error_rsp (p_tcb, GATT_INVALID_PDU, op_code, 0, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001430 }
1431 /* otherwise, ignore the pkt */
1432 }
1433 else
1434 {
1435 switch (op_code)
1436 {
1437 case GATT_REQ_READ_BY_GRP_TYPE: /* discover primary services */
1438 case GATT_REQ_FIND_TYPE_VALUE: /* discover service by UUID */
1439 gatts_process_primary_service_req (p_tcb, op_code, len, p_data);
1440 break;
1441
1442 case GATT_REQ_FIND_INFO:/* discover char descrptor */
1443 gatts_process_find_info(p_tcb, op_code, len, p_data);
1444 break;
1445
1446 case GATT_REQ_READ_BY_TYPE: /* read characteristic value, char descriptor value */
1447 /* discover characteristic, discover char by UUID */
1448 gatts_process_read_by_type_req(p_tcb, op_code, len, p_data);
1449 break;
1450
1451
1452 case GATT_REQ_READ: /* read char/char descriptor value */
1453 case GATT_REQ_READ_BLOB:
1454 case GATT_REQ_WRITE: /* write char/char descriptor value */
1455 case GATT_CMD_WRITE:
1456 case GATT_SIGN_CMD_WRITE:
1457 case GATT_REQ_PREPARE_WRITE:
1458 gatts_process_attribute_req (p_tcb, op_code, len, p_data);
1459 break;
1460
1461 case GATT_HANDLE_VALUE_CONF:
1462 gatts_process_value_conf (p_tcb, op_code);
1463 break;
1464
1465 case GATT_REQ_MTU:
1466 gatts_process_mtu_req (p_tcb, len, p_data);
1467 break;
1468
1469 case GATT_REQ_EXEC_WRITE:
Ganesh Ganapathi Batta8fe58872014-04-16 16:50:09 -07001470 gatt_process_exec_write_req (p_tcb, op_code, len, p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001471 break;
1472
1473 case GATT_REQ_READ_MULTI:
1474 gatt_process_read_multi_req (p_tcb, op_code, len, p_data);
1475 break;
1476
1477 default:
1478 break;
1479 }
1480 }
1481}
1482
1483#endif /* BLE_INCLUDED */