16ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach/******************************************************************************
26ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *
36ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *  Copyright (C) 2008-2012 Broadcom Corporation
46ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *
56ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *  Licensed under the Apache License, Version 2.0 (the "License");
66ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *  you may not use this file except in compliance with the License.
76ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *  You may obtain a copy of the License at:
86ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *
96ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *  http://www.apache.org/licenses/LICENSE-2.0
106ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *
116ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *  Unless required by applicable law or agreed to in writing, software
126ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *  distributed under the License is distributed on an "AS IS" BASIS,
136ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
146ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *  See the License for the specific language governing permissions and
156ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *  limitations under the License.
166ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *
176ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach ******************************************************************************/
186ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach
196ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach/******************************************************************************
206ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *
216ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *  this file contains ATT protocol functions
226ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach *
236ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach ******************************************************************************/
24e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
25e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "bt_target.h"
266ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach
27e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#if BLE_INCLUDED == TRUE
28e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
29e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "gatt_int.h"
30e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#include "l2c_api.h"
31e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
32e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#define GATT_HDR_FIND_TYPE_VALUE_LEN    21
33e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#define GATT_OP_CODE_SIZE   1
34e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/**********************************************************************
35e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**   ATT protocl message building utility                              *
36e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach***********************************************************************/
37e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
38e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
39e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         attp_build_mtu_exec_cmd
40e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
41e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      Build a exchange MTU request
42e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
43e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns          None.
44e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
45e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
46e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachBT_HDR *attp_build_mtu_cmd(UINT8 op_code, UINT16 rx_mtu)
47e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
48e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    BT_HDR      *p_buf = NULL;
49e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT8       *p;
50e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
51e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + GATT_HDR_SIZE + L2CAP_MIN_OFFSET)) != NULL)
52e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
53e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
54e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
55e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        UINT8_TO_STREAM (p, op_code);
56e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        UINT16_TO_STREAM (p, rx_mtu);
57e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
58e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->offset = L2CAP_MIN_OFFSET;
596ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach        p_buf->len = GATT_HDR_SIZE; /* opcode + 2 bytes mtu */
60e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
61e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return p_buf;
62e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
63e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
64e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
65e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         attp_build_exec_write_cmd
66e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
67e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      Build a execute write request or response.
68e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
69e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns          None.
70e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
71e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
72e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachBT_HDR *attp_build_exec_write_cmd (UINT8 op_code, UINT8 flag)
73e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
74e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    BT_HDR      *p_buf = NULL;
75e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT8       *p;
76e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
77e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((p_buf = (BT_HDR *)GKI_getbuf((UINT16)(sizeof(BT_HDR) + 10 + L2CAP_MIN_OFFSET))) != NULL)
78e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
79e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
80e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
81e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->offset = L2CAP_MIN_OFFSET;
82e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->len = GATT_OP_CODE_SIZE;
83e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
84e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        UINT8_TO_STREAM (p, op_code);
85e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
86e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (op_code == GATT_REQ_EXEC_WRITE)
87e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        {
88e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            flag &= GATT_PREP_WRITE_EXEC;
89e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            UINT8_TO_STREAM (p, flag);
90e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            p_buf->len += 1;
91e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        }
92e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
93e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
94e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
95e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return p_buf;
96e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
97e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
98e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
99e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
100e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         attp_build_err_cmd
101e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
102e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      Build a exchange MTU request
103e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
104e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns          None.
105e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
106e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
107e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachBT_HDR *attp_build_err_cmd(UINT8 cmd_code, UINT16 err_handle, UINT8 reason)
108e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
109e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    BT_HDR      *p_buf = NULL;
110e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT8       *p;
111e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
112e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + L2CAP_MIN_OFFSET + 5)) != NULL)
113e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
114e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
115e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
116e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        UINT8_TO_STREAM (p, GATT_RSP_ERROR);
117e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        UINT8_TO_STREAM (p, cmd_code);
118e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        UINT16_TO_STREAM(p, err_handle);
1196ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach        UINT8_TO_STREAM (p, reason);
120e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
121e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->offset = L2CAP_MIN_OFFSET;
122e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        /* GATT_HDR_SIZE (1B ERR_RSP op code+ 2B handle) + 1B cmd_op_code  + 1B status */
123e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->len = GATT_HDR_SIZE + 1 + 1;
124e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
125e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return p_buf;
126e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
127e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
128e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
129e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         attp_build_browse_cmd
130e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
131e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      Build a read information request or read by type request
132e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
133e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns          None.
134e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
135e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
136e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachBT_HDR *attp_build_browse_cmd(UINT8 op_code, UINT16 s_hdl, UINT16 e_hdl, tBT_UUID uuid)
137e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
138e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    BT_HDR      *p_buf = NULL;
139e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT8       *p;
140e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
141e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + 8 + L2CAP_MIN_OFFSET)) != NULL)
142e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
143e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
144e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        /* Describe the built message location and size */
145e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->offset = L2CAP_MIN_OFFSET;
146e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->len = GATT_OP_CODE_SIZE + 4;
147e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
148e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        UINT8_TO_STREAM (p, op_code);
149e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        UINT16_TO_STREAM (p, s_hdl);
150e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        UINT16_TO_STREAM (p, e_hdl);
151e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->len += gatt_build_uuid_to_stream(&p, uuid);
152e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
153e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
154e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return p_buf;
155e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
156e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
157e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
158e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         attp_build_read_handles_cmd
159e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
160e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      Build a read by type and value request.
161e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
162e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns          pointer to the command buffer.
163e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
164e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
165e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachBT_HDR *attp_build_read_handles_cmd (UINT16 payload_size, tGATT_FIND_TYPE_VALUE *p_value_type)
166e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
167e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    BT_HDR      *p_buf = NULL;
168e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT8       *p;
1696ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach    UINT16      len = p_value_type->value_len;
170e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
171e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((p_buf = (BT_HDR *)GKI_getbuf((UINT16)(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET))) != NULL)
172e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
173e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
174e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
175e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->offset = L2CAP_MIN_OFFSET;
176e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->len = 5; /* opcode + s_handle + e_handle */
177e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
178e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        UINT8_TO_STREAM  (p, GATT_REQ_FIND_TYPE_VALUE);
179e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        UINT16_TO_STREAM (p, p_value_type->s_handle);
180e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        UINT16_TO_STREAM (p, p_value_type->e_handle);
181e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
182e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->len += gatt_build_uuid_to_stream(&p, p_value_type->uuid);
183e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
184e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (p_value_type->value_len +  p_buf->len > payload_size )
185e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            len = payload_size - p_buf->len;
186e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
187e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        memcpy (p, p_value_type->value, len);
188e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->len += len;
189e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
190e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
191e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return p_buf;
192e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
193e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
194e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
195e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         attp_build_read_multi_cmd
196e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
197e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      Build a read multiple request
198e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
199e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns          None.
200e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
201e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
202e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachBT_HDR *attp_build_read_multi_cmd(UINT16 payload_size, UINT16 num_handle, UINT16 *p_handle)
203e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
204e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    BT_HDR      *p_buf = NULL;
205e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT8       *p, i = 0;
206e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
207e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((p_buf = (BT_HDR *)GKI_getbuf((UINT16)(sizeof(BT_HDR) + num_handle * 2 + 1 + L2CAP_MIN_OFFSET))) != NULL)
208e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
209e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
210e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
211e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->offset = L2CAP_MIN_OFFSET;
212e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->len = 1;
213e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
214e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        UINT8_TO_STREAM (p, GATT_REQ_READ_MULTI);
2156ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach
216e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        for (i = 0; i < num_handle && p_buf->len + 2 <= payload_size; i ++)
217e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        {
218e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            UINT16_TO_STREAM (p, *(p_handle + i));
219e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            p_buf->len += 2;
220e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        }
221e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
222e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
223e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return p_buf;
224e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
225e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
226e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
227e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         attp_build_handle_cmd
228e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
229e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      Build a read /read blob request
230e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
231e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns          None.
232e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
233e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
234e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachBT_HDR *attp_build_handle_cmd(UINT8 op_code, UINT16 handle, UINT16 offset)
235e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
236e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    BT_HDR      *p_buf = NULL;
237e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT8       *p;
238e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
239e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + 5 + L2CAP_MIN_OFFSET)) != NULL)
240e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
241e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
242e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
243e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->offset = L2CAP_MIN_OFFSET;
244e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
245e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        UINT8_TO_STREAM (p, op_code);
246e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->len  = 1;
247e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
248e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        UINT16_TO_STREAM (p, handle);
249e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->len += 2;
250e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
251e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (op_code == GATT_REQ_READ_BLOB)
252e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        {
253e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            UINT16_TO_STREAM (p, offset);
254e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            p_buf->len += 2;
2556ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach        }
256e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
257e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
258e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
259e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return p_buf;
260e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
261e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
262e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
263e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         attp_build_opcode_cmd
264e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
265e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      Build a  request/response with opcode only.
266e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
267e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns          None.
268e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
269e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
270e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachBT_HDR *attp_build_opcode_cmd(UINT8 op_code)
271e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
272e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    BT_HDR      *p_buf = NULL;
273e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT8       *p;
274e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
275e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + 1 + L2CAP_MIN_OFFSET)) != NULL)
276e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
277e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
278e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->offset = L2CAP_MIN_OFFSET;
279e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
280e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        UINT8_TO_STREAM (p, op_code);
281e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->len  = 1;
282e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
283e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
284e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return p_buf;
285e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
286e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
287e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
288e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         attp_build_value_cmd
289e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
290e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      Build a attribute value request
291e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
292e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns          None.
293e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
294e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
2956ef101187774e30ddba6b46bbedef549a42196adAndre EisenbachBT_HDR *attp_build_value_cmd (UINT16 payload_size, UINT8 op_code, UINT16 handle,
296e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                              UINT16 offset, UINT16 len, UINT8 *p_data)
297e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
298e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    BT_HDR      *p_buf = NULL;
299e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT8       *p, *pp, pair_len, *p_pair_len;
300e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
301e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if ((p_buf = (BT_HDR *)GKI_getbuf((UINT16)(sizeof(BT_HDR) + payload_size + L2CAP_MIN_OFFSET))) != NULL)
302e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
303e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p = pp =(UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
304e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
305e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        UINT8_TO_STREAM (p, op_code);
306e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->offset = L2CAP_MIN_OFFSET;
307e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_buf->len = 1;
308e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
309e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (op_code == GATT_RSP_READ_BY_TYPE)
310e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        {
311e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            p_pair_len = p;
312e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            pair_len = len + 2;
313e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            UINT8_TO_STREAM (p, pair_len);
3146ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach            p_buf->len += 1;
315e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        }
316e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (op_code != GATT_RSP_READ_BLOB && op_code != GATT_RSP_READ)
317e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        {
318e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            UINT16_TO_STREAM (p, handle);
3196ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach            p_buf->len += 2;
320e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        }
321e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
322e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (op_code == GATT_REQ_PREPARE_WRITE ||op_code == GATT_RSP_PREPARE_WRITE )
323e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        {
324e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            UINT16_TO_STREAM (p, offset);
325e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            p_buf->len += 2;
326e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        }
327e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
328e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (len > 0 && p_data != NULL)
3296ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach        {
330e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            /* ensure data not exceed MTU size */
331e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            if (payload_size - p_buf->len < len)
332e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            {
333e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                len = payload_size - p_buf->len;
334e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                /* update handle value pair length */
335e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                if (op_code == GATT_RSP_READ_BY_TYPE)
336e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                    *p_pair_len = (len + 2);
337e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
338e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                GATT_TRACE_WARNING1("attribute value too long, to be truncated to %d", len);
339e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            }
340e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
341e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            ARRAY_TO_STREAM (p, p_data, len);
342e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            p_buf->len += len;
343e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        }
344e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
345e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return p_buf;
346e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
347e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
348e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
349e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
350e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         attp_send_msg_to_L2CAP
351e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
352e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      Send message to L2CAP.
353e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
354e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
355e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachBOOLEAN  attp_send_msg_to_L2CAP(tGATT_TCB *p_tcb, BT_HDR *p_toL2CAP)
356e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
357e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT16      l2cap_ret;
358e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
359e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
360e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (p_tcb->att_lcid == L2CAP_ATT_CID)
361e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        l2cap_ret = L2CA_SendFixedChnlData (L2CAP_ATT_CID, p_tcb->peer_bda, p_toL2CAP);
362e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    else
363e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        l2cap_ret = (UINT16) L2CA_DataWrite (p_tcb->att_lcid, p_toL2CAP);
364e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
365e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (l2cap_ret == L2CAP_DW_FAILED)
366e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
3676ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach        GATT_TRACE_ERROR1("ATT   failed to pass msg:0x%0x to L2CAP",
368e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            *((UINT8 *)(p_toL2CAP + 1) + p_toL2CAP->offset));
369e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        GKI_freebuf(p_toL2CAP);
370e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return FALSE;
371e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
372e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    else
373e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
374e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        return TRUE;
375e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
376e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
377e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
378e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
379e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
380e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         attp_build_sr_msg
381e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
382e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      Build ATT Server PDUs.
383e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
384e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
385e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachBT_HDR *attp_build_sr_msg(tGATT_TCB *p_tcb, UINT8 op_code, tGATT_SR_MSG *p_msg)
386e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
3876ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach    BT_HDR          *p_cmd = NULL;
388e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT16          offset = 0;
389e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
390e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    switch (op_code)
391e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
392e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case GATT_RSP_READ_BLOB:
393e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        GATT_TRACE_EVENT2 ("ATT_RSP_READ_BLOB: len = %d offset = %d", p_msg->attr_value.len, p_msg->attr_value.offset);
394e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        offset = p_msg->attr_value.offset;
395e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
396e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case GATT_RSP_PREPARE_WRITE:
397e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (offset == 0)
398e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            offset = p_msg->attr_value.offset;
399e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
400e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case GATT_RSP_READ_BY_TYPE:
401e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case GATT_RSP_READ:
402e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case GATT_HANDLE_VALUE_NOTIF:
403e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case GATT_HANDLE_VALUE_IND:
4046ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach        p_cmd = attp_build_value_cmd(p_tcb->payload_size,
4056ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach                                     op_code,
406e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                                     p_msg->attr_value.handle,
407e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                                     offset,
4086ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach                                     p_msg->attr_value.len,
409e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                                     p_msg->attr_value.value);
410e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        break;
4116ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach
412e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case GATT_RSP_WRITE:
413e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_cmd = attp_build_opcode_cmd(op_code);
414e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        break;
415e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
416e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case GATT_RSP_ERROR:
417e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_cmd = attp_build_err_cmd(p_msg->error.cmd_code, p_msg->error.handle, p_msg->error.reason);
418e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        break;
419e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
420e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case GATT_RSP_EXEC_WRITE:
421e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_cmd = attp_build_exec_write_cmd(op_code, 0);
422e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        break;
423e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
424e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    case GATT_RSP_MTU:
425e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        p_cmd = attp_build_mtu_cmd(op_code, p_msg->mtu);
426e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        break;
427e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
428e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    default:
429e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        GATT_TRACE_DEBUG1("attp_build_sr_msg: unknown op code = %d", op_code);
430e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        break;
431e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
432e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
433e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (!p_cmd)
434e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        GATT_TRACE_ERROR0("No resources");
435e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
436e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return p_cmd;
437e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
438e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
439e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
440e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
441e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         attp_send_sr_msg
442e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
4436ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach** Description      This function sends the server response or indication message
444e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  to client.
445e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
446e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Parameter        p_tcb: pointer to the connecton control block.
447e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  p_msg: pointer to message parameters structure.
448e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
449e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns          GATT_SUCCESS if sucessfully sent; otherwise error code.
4506ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach**
451e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
452e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
453e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachtGATT_STATUS attp_send_sr_msg (tGATT_TCB *p_tcb, BT_HDR *p_msg)
454e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
455e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tGATT_STATUS     cmd_sent = GATT_NO_RESOURCES;
456e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
457e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (p_tcb != NULL)
458e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
459e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (p_msg != NULL)
460e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        {
461e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            p_msg->offset = L2CAP_MIN_OFFSET;
462e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
463e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            if (attp_send_msg_to_L2CAP (p_tcb, p_msg))
464e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                cmd_sent = GATT_SUCCESS;
465e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            else
466e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                cmd_sent = GATT_INTERNAL_ERROR;
467e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        }
468e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
469e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return cmd_sent;
470e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
471e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
472e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
473e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
474e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         attp_cl_send_cmd
475e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
476e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Description      Send a ATT command or enqueue it.
477e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
478e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns          TRUE if command sent, otherwise FALSE.
479e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
480e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
481e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachUINT8 attp_cl_send_cmd(tGATT_TCB *p_tcb, UINT16 clcb_idx, UINT8 cmd_code, BT_HDR *p_cmd)
482e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
483e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT8       att_ret = GATT_SUCCESS;
4846ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach
485e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (p_tcb != NULL)
4866ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach    {
487e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        cmd_code &= ~GATT_AUTH_SIGN_MASK;
488e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
489e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (p_tcb->pending_cl_req == p_tcb->next_slot_inq ||
490e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            cmd_code == GATT_HANDLE_VALUE_CONF)
491e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        {
492e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            /* no penindg request or value confirmation */
493e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            if (attp_send_msg_to_L2CAP(p_tcb, p_cmd))
494e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            {
495e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                /* do not enq cmd if handle value confirmation or set request */
496e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                if (cmd_code != GATT_HANDLE_VALUE_CONF && cmd_code != GATT_CMD_WRITE)
497e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                {
498e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                    gatt_start_rsp_timer (p_tcb);
499e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                    gatt_cmd_enq(p_tcb, clcb_idx, FALSE, cmd_code, NULL);
500e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                }
501e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            }
502e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            else
503e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                att_ret = GATT_INTERNAL_ERROR;
504e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        }
505e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        else
506e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            gatt_cmd_enq(p_tcb, clcb_idx, TRUE, cmd_code, p_cmd);
507e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
508e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    else
509e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        att_ret = GATT_ILLEGAL_PARAMETER;
510e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
511e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return att_ret;
512e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
513e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach/*******************************************************************************
514e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
515e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Function         attp_send_cl_msg
516e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
5176ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach** Description      This function sends the client request or confirmation message
518e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  to server.
519e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
520e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Parameter        p_tcb: pointer to the connectino control block.
521e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  clcb_idx: clcb index
522e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  op_code: message op code.
523e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**                  p_msg: pointer to message parameters structure.
524e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
525e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach** Returns          GATT_SUCCESS if sucessfully sent; otherwise error code.
5266ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach**
527e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach**
528e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach*******************************************************************************/
529e448862a47c08eb23185aaed574b39264f5005fcAndre EisenbachtGATT_STATUS attp_send_cl_msg (tGATT_TCB *p_tcb, UINT16 clcb_idx, UINT8 op_code, tGATT_CL_MSG *p_msg)
530e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach{
531e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    tGATT_STATUS     status = GATT_NO_RESOURCES;
5326ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach    BT_HDR          *p_cmd = NULL;
533e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    UINT16          offset = 0, handle;
534e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
535e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    if (p_tcb != NULL)
536e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
537e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        switch (op_code)
538e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        {
539e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        case GATT_REQ_MTU:
540e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            if (p_msg->mtu <= GATT_MAX_MTU_SIZE)
541e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            {
542e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                p_tcb->payload_size = p_msg->mtu;
543e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                p_cmd = attp_build_mtu_cmd(GATT_REQ_MTU, p_msg->mtu);
544e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            }
545e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            else
546e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                status = GATT_ILLEGAL_PARAMETER;
547e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            break;
548e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
549e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        case GATT_REQ_FIND_INFO:
550e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        case GATT_REQ_READ_BY_TYPE:
551e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        case GATT_REQ_READ_BY_GRP_TYPE:
552e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            if (GATT_HANDLE_IS_VALID (p_msg->browse.s_handle) &&
553e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                GATT_HANDLE_IS_VALID (p_msg->browse.e_handle)  &&
554e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                p_msg->browse.s_handle <= p_msg->browse.e_handle)
555e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            {
5566ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach                p_cmd = attp_build_browse_cmd(op_code,
5576ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach                                            p_msg->browse.s_handle,
5586ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach                                            p_msg->browse.e_handle,
559e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                                            p_msg->browse.uuid);
560e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            }
561e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            else
562e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                status = GATT_ILLEGAL_PARAMETER;
563e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            break;
564e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
565e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        case GATT_REQ_READ_BLOB:
566e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            offset = p_msg->read_blob.offset;
567e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            /* fall through */
568e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        case GATT_REQ_READ:
569e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            handle = (op_code == GATT_REQ_READ) ? p_msg->handle: p_msg->read_blob.handle;
570e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            /*  handle checking */
5716ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach            if (GATT_HANDLE_IS_VALID (handle))
572e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            {
573e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                p_cmd = attp_build_handle_cmd(op_code, handle, offset);
574e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            }
575e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            else
576e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                status = GATT_ILLEGAL_PARAMETER;
577e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            break;
578e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
579e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        case GATT_HANDLE_VALUE_CONF:
580e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            p_cmd = attp_build_opcode_cmd(op_code);
581e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            break;
582e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
583e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        case GATT_REQ_PREPARE_WRITE:
584e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            offset = p_msg->attr_value.offset;
585e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            /* fall through */
586e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        case GATT_REQ_WRITE:
587e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        case GATT_CMD_WRITE:
588e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        case GATT_SIGN_CMD_WRITE:
589e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            if (GATT_HANDLE_IS_VALID (p_msg->attr_value.handle))
590e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            {
5916ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach                p_cmd = attp_build_value_cmd (p_tcb->payload_size,
592e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                                              op_code, p_msg->attr_value.handle,
593e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                                              offset,
594e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                                              p_msg->attr_value.len,
595e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                                              p_msg->attr_value.value);
596e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            }
597e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            else
598e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach                status = GATT_ILLEGAL_PARAMETER;
599e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            break;
600e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
601e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        case GATT_REQ_EXEC_WRITE:
602e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            p_cmd = attp_build_exec_write_cmd(op_code, p_msg->exec_write);
603e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            break;
604e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
6056ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach        case GATT_REQ_FIND_TYPE_VALUE:
6066ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach            p_cmd = attp_build_read_handles_cmd(p_tcb->payload_size, &p_msg->find_type_value);
607e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            break;
608e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
609e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        case GATT_REQ_READ_MULTI:
6106ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach            p_cmd = attp_build_read_multi_cmd(p_tcb->payload_size,
6116ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach                                              p_msg->read_multi.num_handles,
6126ef101187774e30ddba6b46bbedef549a42196adAndre Eisenbach                                              p_msg->read_multi.handles);
613e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            break;
614e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
615e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        default:
616e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            break;
617e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        }
618e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
619e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        if (p_cmd != NULL)
620e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach            status = attp_cl_send_cmd(p_tcb, clcb_idx, op_code, p_cmd);
621e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
622e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
623e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    else
624e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    {
625e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach        GATT_TRACE_ERROR0("Peer device not connected");
626e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    }
627e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach
628e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach    return status;
629e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach}
630e448862a47c08eb23185aaed574b39264f5005fcAndre Eisenbach#endif
631