/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#ifndef H_BLE_HS_ADV_
#define H_BLE_HS_ADV_

#include <inttypes.h>
#include "host/ble_uuid.h"
#include "syscfg/syscfg.h"

#ifdef __cplusplus
extern "C" {
#endif

#define BLE_HS_ADV_MAX_SZ           BLE_HCI_MAX_ADV_DATA_LEN

/** Max field payload size (account for 2-byte header). */
#define BLE_HS_ADV_MAX_FIELD_SZ     (BLE_HS_ADV_MAX_SZ - 2)

#define BLE_HS_ADV_LE_SUPP_FEAT_LEN             6

struct ble_hs_adv_field {
    uint8_t length;
    uint8_t type;
    uint8_t value[0];
};

typedef int (* ble_hs_adv_parse_func_t) (const struct ble_hs_adv_field *,
                                         void *);

struct ble_hs_adv_fields {
    /*** 0x01 - Flags. */
    uint8_t flags;

    /*** 0x02,0x03 - 16-bit service class UUIDs. */
    const ble_uuid16_t *uuids16;
    uint8_t num_uuids16;
    unsigned uuids16_is_complete:1;

    /*** 0x04,0x05 - 32-bit service class UUIDs. */
    const ble_uuid32_t *uuids32;
    uint8_t num_uuids32;
    unsigned uuids32_is_complete:1;

    /*** 0x06,0x07 - 128-bit service class UUIDs. */
    const ble_uuid128_t *uuids128;
    uint8_t num_uuids128;
    unsigned uuids128_is_complete:1;

    /*** 0x08,0x09 - Local name. */
    const uint8_t *name;
    uint8_t name_len;
    unsigned name_is_complete:1;

    /*** 0x0a - Tx power level. */
    int8_t tx_pwr_lvl;
    unsigned tx_pwr_lvl_is_present:1;

    /*** 0x0d - Slave connection interval range. */
    const uint8_t *slave_itvl_range;

    /*** 0x10 - Security Manager TK value */
    const uint8_t *sm_tk_value;
    unsigned sm_tk_value_is_present:1;

    /*** 0x11 - Security Manager OOB flag */
    uint8_t sm_oob_flag;
    unsigned sm_oob_flag_is_present:1;

    /*** 0x14 - 16-bit service soliciation list. */
    const ble_uuid16_t *sol_uuids16;
    uint8_t sol_num_uuids16;

    /*** 0x15 - 128-bit service solicitation UUIDs. */
    const ble_uuid128_t *sol_uuids128;
    uint8_t sol_num_uuids128;

    /*** 0x16 - Service data - 16-bit UUID. */
    const uint8_t *svc_data_uuid16;
    uint8_t svc_data_uuid16_len;

    /*** 0x17 - Public target address. */
    const uint8_t *public_tgt_addr;
    uint8_t num_public_tgt_addrs;

    /*** 0x18 - Random target address. */
    const uint8_t *random_tgt_addr;
    uint8_t num_random_tgt_addrs;

    /*** 0x19 - Appearance. */
    uint16_t appearance;
    unsigned appearance_is_present:1;

    /*** 0x1a - Advertising interval. */
    uint16_t adv_itvl;
    unsigned adv_itvl_is_present:1;

    /*** 0x1b - LE Bluetooth device address */
    const uint8_t *device_addr;
    unsigned device_addr_type;
    unsigned device_addr_is_present:1;

    /*** 0x1f - 32-bit service solicitation UUIDs */
    const ble_uuid32_t *sol_uuids32;
    uint8_t sol_num_uuids32;

    /*** 0x1c - LE Role */
    uint8_t le_role;
    unsigned le_role_is_present:1;

    /*** 0x20 - Service data - 32-bit UUID. */
    const uint8_t *svc_data_uuid32;
    uint8_t svc_data_uuid32_len;

    /*** 0x21 - Service data - 128-bit UUID. */
    const uint8_t *svc_data_uuid128;
    uint8_t svc_data_uuid128_len;

    /*** 0x24 - URI. */
    const uint8_t *uri;
    uint8_t uri_len;

    /*** 0x27 - LE Supported Features. */
    /*** Core Spec v5.4 Vol. 6 Part B 4.6 */
    uint8_t le_supp_feat[BLE_HS_ADV_LE_SUPP_FEAT_LEN];
    unsigned le_supp_feat_is_present;

    /*** 0x2f - Advertising interval - long. */
    uint32_t adv_itvl_long;
    unsigned adv_itvl_long_is_present:1;

#if MYNEWT_VAL(ENC_ADV_DATA)
    /*** 0x31 - Encrypted Advertising Data. */
    const uint8_t *enc_adv_data;
    uint8_t enc_adv_data_len;
#endif

    /*** 0xff - Manufacturer specific data. */
    const uint8_t *mfg_data;
    uint8_t mfg_data_len;
};

#define BLE_HS_ADV_TYPE_FLAGS                   0x01
#define BLE_HS_ADV_TYPE_INCOMP_UUIDS16          0x02
#define BLE_HS_ADV_TYPE_COMP_UUIDS16            0x03
#define BLE_HS_ADV_TYPE_INCOMP_UUIDS32          0x04
#define BLE_HS_ADV_TYPE_COMP_UUIDS32            0x05
#define BLE_HS_ADV_TYPE_INCOMP_UUIDS128         0x06
#define BLE_HS_ADV_TYPE_COMP_UUIDS128           0x07
#define BLE_HS_ADV_TYPE_INCOMP_NAME             0x08
#define BLE_HS_ADV_TYPE_COMP_NAME               0x09
#define BLE_HS_ADV_TYPE_TX_PWR_LVL              0x0a
#define BLE_HS_ADV_TYPE_SEC_MGR_TK_VALUE        0x10
#define BLE_HS_ADV_TYPE_SEC_MGR_OOB_FLAG        0x11
#define BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE        0x12
#define BLE_HS_ADV_TYPE_SOL_UUIDS16             0x14
#define BLE_HS_ADV_TYPE_SOL_UUIDS128            0x15
#define BLE_HS_ADV_TYPE_SVC_DATA_UUID16         0x16
#define BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR         0x17
#define BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR         0x18
#define BLE_HS_ADV_TYPE_APPEARANCE              0x19
#define BLE_HS_ADV_TYPE_ADV_ITVL                0x1a
#define BLE_HS_ADV_TYPE_DEVICE_ADDR             0x1b
#define BLE_HS_ADV_TYPE_LE_ROLE                 0x1c
#define BLE_HS_ADV_TYPE_SOL_UUIDS32             0x1f
#define BLE_HS_ADV_TYPE_SVC_DATA_UUID32         0x20
#define BLE_HS_ADV_TYPE_SVC_DATA_UUID128        0x21
#define BLE_HS_ADV_TYPE_URI                     0x24
#define BLE_HS_ADV_TYPE_LE_SUPP_FEAT            0x27
#define BLE_HS_ADV_TYPE_MESH_PROV               0x29
#define BLE_HS_ADV_TYPE_MESH_MESSAGE            0x2a
#define BLE_HS_ADV_TYPE_MESH_BEACON             0x2b
#define BLE_HS_ADV_TYPE_ADV_ITVL_LONG           0x2f
#define BLE_HS_ADV_TYPE_ENC_ADV_DATA            0x31
#define BLE_HS_ADV_TYPE_MFG_DATA                0xff

#define BLE_HS_ADV_FLAGS_LEN                    1
#define BLE_HS_ADV_F_DISC_LTD                   0x01
#define BLE_HS_ADV_F_DISC_GEN                   0x02
#define BLE_HS_ADV_F_BREDR_UNSUP                0x04

#define BLE_HS_ADV_TX_PWR_LVL_LEN               1

/**
 * Set the tx_pwr_lvl field to this if you want the stack to fill in the tx
 * power level field.
 */
#define BLE_HS_ADV_TX_PWR_LVL_AUTO              (-128)

#define BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN         4

#define BLE_HS_ADV_SVC_DATA_UUID16_MIN_LEN      2

#define BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN    6

#define BLE_HS_ADV_APPEARANCE_LEN               2

#define BLE_HS_ADV_ADV_ITVL_LEN                 2

#define BLE_HS_ADV_SVC_DATA_UUID32_MIN_LEN      4

#define BLE_HS_ADV_SVC_DATA_UUID128_MIN_LEN     16

#define BLE_HS_ADV_ADDR_TYPE_LEN		1

#define BLE_HS_ADV_ADV_ITVL_LONG_LEN            4

int ble_hs_adv_set_fields_mbuf(const struct ble_hs_adv_fields *adv_fields,
                               struct os_mbuf *om);

int ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
                          uint8_t *dst, uint8_t *dst_len, uint8_t max_len);

int ble_hs_adv_parse_fields(struct ble_hs_adv_fields *adv_fields,
                            const uint8_t *src, uint8_t src_len);

int ble_hs_adv_parse(const uint8_t *data, uint8_t length,
                     ble_hs_adv_parse_func_t func, void *user_data);

int ble_hs_adv_find_field(uint8_t type, const uint8_t *data, uint8_t length,
                          const struct ble_hs_adv_field **out);

void ble_hs_adv_parse_free(void);
#ifdef __cplusplus
}
#endif

#endif
