#include "common.h"


/* Wrapper to get the index and opcode to the response callback */
struct command_data
{
    uint16_t id;
    uint16_t op;
    void (*callback)(uint16_t id, uint16_t op, uint8_t status,
                     uint16_t len, const void *param);
};











static uint16_t mgmt_index = MGMT_INDEX_NONE;

static const char *settings_str[] = {
    "powered",
    "connectable",
    "fast-connectable",
    "discoverable",
    "bondable",
    "link-security",
    "ssp",
    "br/edr",
    "hs",
    "le",
    "advertising",
    "secure-conn",
    "debug-keys",
    "privacy",
    "configuration",
    "static-addr",
};

static const char *settings2str(uint32_t settings)
{
    static char str[256];
    unsigned i;
    int off;

    off = 0;
    str[0] = '\0';

    for (i = 0; i < NELEM(settings_str); i++)
    {
        if ((settings & (1 << i)) != 0)
            off += snprintf(str + off, sizeof(str) - off, "%s ",
                            settings_str[i]);
    }

    return str;
}


static void cmd_rsp(uint8_t status, uint16_t len, const void *param,
                    void *user_data)
{
    struct command_data *data = user_data;

    printf("cmd rsp\n");
    data->callback(data->op, data->id, status, len, param);
}

void setting_rsp(uint16_t op, uint16_t id, uint8_t status, uint16_t len,
                        const void *param)
{
    const uint32_t *rp = param;

    if (status != 0)
    {
        printf("%s for hci%u failed with status 0x%02x (%s)",
               mgmt_opstr(op), id, status, mgmt_errstr(status));
        return;
    }

    if (len < sizeof(*rp))
    {
        printf("Too small %s response (%u bytes)",
               mgmt_opstr(op), len);
        return;
    }

    printf("hci%u %s complete, settings: %s", id, mgmt_opstr(op),
           settings2str(get_le32(rp)));
}


unsigned int send_cmd(struct mgmt *mgmt, uint16_t op, uint16_t id,
                             uint16_t len, const void *param,
                             void (*cb)(uint16_t id, uint16_t op,
                                        uint8_t status, uint16_t len,
                                        const void *param))
{
    struct command_data *data;
    unsigned int send_id;

    data = new0(struct command_data, 1);
    if (!data)
        return 0;

    data->id = id;
    data->op = op;
    data->callback = cb;

    send_id = mgmt_send(mgmt, op, id, len, param, cmd_rsp, data, free);
    if (send_id == 0)
    {
        printf("Unable to send %s cmd", mgmt_opstr(op));
        free(data);
    }

    return send_id;
}

