Home | History | Annotate | Download | only in gatt
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2008-2012 Broadcom Corporation
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 /******************************************************************************
     20  *
     21  *  this file contains the main GATT server attributes access request
     22  *  handling functions.
     23  *
     24  ******************************************************************************/
     25 
     26 #include "bt_target.h"
     27 
     28 #include "gatt_api.h"
     29 #include "gatt_int.h"
     30 
     31 #if BLE_INCLUDED == TRUE
     32 
     33 #define GATTP_MAX_NUM_INC_SVR       0
     34 #define GATTP_MAX_CHAR_NUM          2
     35 #define GATTP_MAX_ATTR_NUM          (GATTP_MAX_CHAR_NUM * 2 + GATTP_MAX_NUM_INC_SVR + 1)
     36 #define GATTP_MAX_CHAR_VALUE_SIZE   50
     37 
     38 #ifndef GATTP_ATTR_DB_SIZE
     39 #define GATTP_ATTR_DB_SIZE      GATT_DB_MEM_SIZE(GATTP_MAX_NUM_INC_SVR, GATTP_MAX_CHAR_NUM, GATTP_MAX_CHAR_VALUE_SIZE)
     40 #endif
     41 
     42 static void gatt_profile_request_cback (UINT16 conn_id, UINT32 trans_id, UINT8 op_code, tGATTS_DATA *p_data);
     43 static void gatt_profile_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, BOOLEAN connected, tGATT_DISCONN_REASON reason);
     44 
     45 static tGATT_CBACK gatt_profile_cback =
     46 {
     47     gatt_profile_connect_cback,
     48     NULL,
     49     NULL,
     50     NULL,
     51     gatt_profile_request_cback
     52 } ;
     53 
     54 /*******************************************************************************
     55 **
     56 ** Function         gatt_profile_find_conn_id_by_bd_addr
     57 **
     58 ** Description      The function searches all LCB with macthing bd address
     59 **
     60 ** Returns          total number of clcb found.
     61 **
     62 *******************************************************************************/
     63 UINT16 gatt_profile_find_conn_id_by_bd_addr(BD_ADDR bda)
     64 {
     65     UINT8 i_clcb;
     66     tGATT_PROFILE_CLCB    *p_clcb = NULL;
     67 
     68     for (i_clcb = 0, p_clcb= gatt_cb.profile_clcb; i_clcb < GATT_MAX_APPS; i_clcb++, p_clcb++)
     69     {
     70         if (p_clcb->in_use && p_clcb->connected && !memcmp(p_clcb->bda, bda, BD_ADDR_LEN))
     71         {
     72             return p_clcb->conn_id;
     73         }
     74     }
     75 
     76     return GATT_INVALID_CONN_ID;
     77 }
     78 
     79 /*******************************************************************************
     80 **
     81 ** Function         gatt_profile_find_clcb_by_bd_addr
     82 **
     83 ** Description      The function searches all LCBs with macthing bd address.
     84 **
     85 ** Returns          Pointer to the found link conenction control block.
     86 **
     87 *******************************************************************************/
     88 tGATT_PROFILE_CLCB *gatt_profile_find_clcb_by_bd_addr(BD_ADDR bda)
     89 {
     90     UINT8 i_clcb;
     91     tGATT_PROFILE_CLCB    *p_clcb = NULL;
     92 
     93     for (i_clcb = 0, p_clcb= gatt_cb.profile_clcb; i_clcb < GATT_MAX_APPS; i_clcb++, p_clcb++)
     94     {
     95         if (p_clcb->in_use && p_clcb->connected && !memcmp(p_clcb->bda, bda, BD_ADDR_LEN))
     96         {
     97             return p_clcb;
     98         }
     99     }
    100 
    101     return p_clcb;
    102 }
    103 
    104 /*******************************************************************************
    105 **
    106 ** Function         gatt_profile_clcb_alloc
    107 **
    108 ** Description      The function allocates a GATT profile  connection link control block
    109 **
    110 ** Returns           NULL if not found. Otherwise pointer to the connection link block.
    111 **
    112 *******************************************************************************/
    113 tGATT_PROFILE_CLCB *gatt_profile_clcb_alloc (UINT16 conn_id, BD_ADDR bda)
    114 {
    115     UINT8                   i_clcb = 0;
    116     tGATT_PROFILE_CLCB      *p_clcb = NULL;
    117 
    118     for (i_clcb = 0, p_clcb= gatt_cb.profile_clcb; i_clcb < GATT_MAX_APPS; i_clcb++, p_clcb++)
    119     {
    120         if (!p_clcb->in_use)
    121         {
    122             p_clcb->in_use      = TRUE;
    123             p_clcb->conn_id     = conn_id;
    124             p_clcb->connected   = TRUE;
    125             memcpy (p_clcb->bda, bda, BD_ADDR_LEN);
    126             break;
    127         }
    128     }
    129     return p_clcb;
    130 }
    131 /*******************************************************************************
    132 **
    133 ** Function         gatt_profile_clcb_dealloc
    134 **
    135 ** Description      The function deallocates a GATT profile  connection link control block
    136 **
    137 ** Returns           NTrue the deallocation is successful
    138 **
    139 *******************************************************************************/
    140 BOOLEAN gatt_profile_clcb_dealloc (UINT16 conn_id)
    141 {
    142     UINT8                   i_clcb = 0;
    143     tGATT_PROFILE_CLCB      *p_clcb = NULL;
    144 
    145     for (i_clcb = 0, p_clcb= gatt_cb.profile_clcb; i_clcb < GATT_MAX_APPS; i_clcb++, p_clcb++)
    146     {
    147         if (p_clcb->in_use && p_clcb->connected && (p_clcb->conn_id == conn_id))
    148         {
    149             memset(p_clcb, 0, sizeof(tGATT_PROFILE_CLCB));
    150             return TRUE;
    151         }
    152     }
    153     return FALSE;
    154 }
    155 
    156 
    157 /*******************************************************************************
    158 **
    159 ** Function         gatt_profile_request_cback
    160 **
    161 ** Description      GATT profile attribute access request callback.
    162 **
    163 ** Returns          void.
    164 **
    165 *******************************************************************************/
    166 static void gatt_profile_request_cback (UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYPE type,
    167                                         tGATTS_DATA *p_data)
    168 {
    169     UINT8       status = GATT_INVALID_PDU;
    170     tGATTS_RSP   rsp_msg ;
    171     BOOLEAN     ignore = FALSE;
    172 
    173     memset(&rsp_msg, 0, sizeof(tGATTS_RSP));
    174 
    175     switch (type)
    176     {
    177         case GATTS_REQ_TYPE_READ:
    178             status = GATT_READ_NOT_PERMIT;
    179             break;
    180 
    181         case GATTS_REQ_TYPE_WRITE:
    182             status = GATT_WRITE_NOT_PERMIT;
    183             break;
    184 
    185         case GATTS_REQ_TYPE_WRITE_EXEC:
    186         case GATT_CMD_WRITE:
    187             ignore = TRUE;
    188             GATT_TRACE_EVENT0("Ignore GATT_REQ_EXEC_WRITE/WRITE_CMD" );
    189             break;
    190 
    191         case GATTS_REQ_TYPE_MTU:
    192             GATT_TRACE_EVENT1("Get MTU exchange new mtu size: %d", p_data->mtu);
    193             ignore = TRUE;
    194             break;
    195 
    196         default:
    197             GATT_TRACE_EVENT1("Unknown/unexpected LE GAP ATT request: 0x%02x", type);
    198             break;
    199     }
    200 
    201     if (!ignore)
    202         GATTS_SendRsp (conn_id, trans_id, status, &rsp_msg);
    203 
    204 }
    205 
    206 /*******************************************************************************
    207 **
    208 ** Function         gatt_profile_connect_cback
    209 **
    210 ** Description      Gatt profile connection callback.
    211 **
    212 ** Returns          void
    213 **
    214 *******************************************************************************/
    215 static void gatt_profile_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
    216                                         BOOLEAN connected, tGATT_DISCONN_REASON reason)
    217 {
    218     GATT_TRACE_EVENT5 ("gatt_profile_connect_cback: from %08x%04x connected:%d conn_id=%d reason = 0x%04x",
    219                        (bda[0]<<24)+(bda[1]<<16)+(bda[2]<<8)+bda[3],
    220                        (bda[4]<<8)+bda[5], connected, conn_id, reason);
    221 
    222     if (connected)
    223     {
    224         if (gatt_profile_clcb_alloc(conn_id, bda) == NULL)
    225         {
    226             GATT_TRACE_ERROR0 ("gatt_profile_connect_cback: no_resource");
    227             return;
    228         }
    229     }
    230     else
    231     {
    232         gatt_profile_clcb_dealloc(conn_id);
    233     }
    234 
    235 }
    236 
    237 /*******************************************************************************
    238 **
    239 ** Function         gatt_profile_db_init
    240 **
    241 ** Description      Initializa the GATT profile attribute database.
    242 **
    243 *******************************************************************************/
    244 void gatt_profile_db_init (void)
    245 {
    246     tBT_UUID          app_uuid = {LEN_UUID_128, {0}};
    247     tBT_UUID          uuid = {LEN_UUID_16, {UUID_SERVCLASS_GATT_SERVER}};
    248     UINT16            service_handle = 0;
    249     tGATT_STATUS      status;
    250 
    251     /* Fill our internal UUID with a fixed pattern 0x81 */
    252     memset (&app_uuid.uu.uuid128, 0x81, LEN_UUID_128);
    253 
    254 
    255     /* Create a GATT profile service */
    256     gatt_cb.gatt_if = GATT_Register(&app_uuid, &gatt_profile_cback);
    257     GATT_StartIf(gatt_cb.gatt_if);
    258 
    259     service_handle = GATTS_CreateService (gatt_cb.gatt_if , &uuid, 0, GATTP_MAX_ATTR_NUM, TRUE);
    260     /* add Service Changed characteristic
    261     */
    262     uuid.uu.uuid16 = gatt_cb.gattp_attr.uuid = GATT_UUID_GATT_SRV_CHGD;
    263     gatt_cb.gattp_attr.service_change = 0;
    264     gatt_cb.gattp_attr.handle   =
    265     gatt_cb.handle_of_h_r       = GATTS_AddCharacteristic(service_handle, &uuid, 0, GATT_CHAR_PROP_BIT_INDICATE);
    266 
    267     GATT_TRACE_DEBUG1 ("gatt_profile_db_init:  handle of service changed%d",
    268                        gatt_cb.handle_of_h_r  );
    269 
    270     /* start service
    271     */
    272     status = GATTS_StartService (gatt_cb.gatt_if, service_handle, GATTP_TRANSPORT_SUPPORTED );
    273 
    274     GATT_TRACE_DEBUG2 ("gatt_profile_db_init:  gatt_if=%d   start status%d",
    275                        gatt_cb.gatt_if,  status);
    276 }
    277 
    278 #endif  /* BLE_INCLUDED */
    279