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