Esempio n. 1
0
static int
nm_ble_out(struct nmgr_transport *nt, struct os_mbuf *om)
{
    struct ble_gatt_attr attr;
    uint16_t conn_handle;
    int rc;

    assert(OS_MBUF_USRHDR_LEN(om) == 2);
    memcpy(&conn_handle, OS_MBUF_USRHDR(om), 2);

    assert(OS_MBUF_PKTLEN(om) <= sizeof nm_buf);
    rc = os_mbuf_copydata(om, 0, OS_MBUF_PKTLEN(om), nm_buf);
    assert(rc == 0);

    attr.handle = nm_attr_val_handle;
    attr.offset = 0;
    attr.value_len = OS_MBUF_PKTLEN(om);
    attr.value = nm_buf;

    rc = ble_gattc_notify_custom(conn_handle, &attr);
    console_printf("nm_ble_out(); conn_handle = %d notify-rc=%d\n",
                   conn_handle, rc);

    return rc;
}
Esempio n. 2
0
static int
nmgr_rsp_fragment(struct nmgr_transport *nt, struct nmgr_hdr *rsp_hdr,
                  struct os_mbuf *rsp, struct os_mbuf *req)
{
    uint16_t mtu;
    uint16_t rsplen;
    uint16_t len ;
    int rc;

    len = 0;

    mtu = nt->nt_get_mtu(req);

    do {
        len = OS_MBUF_PKTLEN(rsp);
        if (len >= mtu) {
            rsplen = mtu;
        } else {
            rsplen = len;
        }

        rc = nmgr_send_rspfrag(nt, rsp, req, rsplen);
        if (rc) {
            goto err;
        }

        os_mbuf_adj(rsp, rsplen);

    } while (OS_MBUF_PKTLEN(rsp));

    return MGMT_ERR_EOK;
err:
    return rc;
}
int
ble_hs_test_util_l2cap_rx_payload_flat(struct ble_hs_conn *conn,
                                       struct ble_l2cap_chan *chan,
                                       const void *data, int len)
{
    struct hci_data_hdr hci_hdr;
    struct os_mbuf *om;
    int rc;

    om = ble_hs_misc_pkthdr();
    TEST_ASSERT_FATAL(om != NULL);

    om->om_data += BLE_L2CAP_HDR_SZ;

    rc = os_mbuf_append(om, data, len);
    TEST_ASSERT_FATAL(rc == 0);

    om = ble_l2cap_prepend_hdr(om, chan->blc_cid, OS_MBUF_PKTLEN(om));
    TEST_ASSERT_FATAL(om != NULL);

    hci_hdr.hdh_handle_pb_bc =
        host_hci_handle_pb_bc_join(conn->bhc_handle,
                                   BLE_HCI_PB_FIRST_FLUSH, 0);
    hci_hdr.hdh_len = OS_MBUF_PKTHDR(om)->omp_len;

    rc = ble_hs_test_util_l2cap_rx(conn, &hci_hdr, om);
    return rc;
}
static void
ble_att_clt_test_misc_prep_good(uint16_t handle, uint16_t offset,
                                uint8_t *attr_data, uint16_t attr_data_len)
{
    struct ble_att_prep_write_cmd req;
    struct ble_l2cap_chan *chan;
    struct ble_hs_conn *conn;
    struct os_mbuf *om;
    int rc;
    int i;

    ble_att_clt_test_misc_init(&conn, &chan);

    req.bapc_handle = handle;
    req.bapc_offset = offset;
    rc = ble_att_clt_tx_prep_write(conn->bhc_handle, &req, attr_data,
                                   attr_data_len);
    TEST_ASSERT(rc == 0);

    ble_hs_test_util_tx_all();
    TEST_ASSERT_FATAL(ble_hs_test_util_prev_tx != NULL);

    om = os_mbuf_pullup(ble_hs_test_util_prev_tx,
                        OS_MBUF_PKTLEN(ble_hs_test_util_prev_tx));
    TEST_ASSERT_FATAL(om != NULL);
    TEST_ASSERT(om->om_len == BLE_ATT_PREP_WRITE_CMD_BASE_SZ + attr_data_len);

    ble_att_prep_write_req_parse(om->om_data, om->om_len, &req);
    TEST_ASSERT(req.bapc_handle == handle);
    TEST_ASSERT(req.bapc_offset == offset);
    for (i = 0; i < attr_data_len; i++) {
        TEST_ASSERT(om->om_data[BLE_ATT_PREP_WRITE_CMD_BASE_SZ + i] ==
                    attr_data[i]);
    }
}
static void
ble_gatt_find_s_test_misc_verify_tx_read_type(uint16_t start_handle,
                                              uint16_t end_handle)
{
    struct ble_att_read_type_req req;
    struct os_mbuf *om;
    uint16_t uuid16;
    int rc;

    ble_hs_test_util_tx_all();

    TEST_ASSERT_FATAL(ble_hs_test_util_prev_tx != NULL);

    om = os_mbuf_pullup(ble_hs_test_util_prev_tx,
                        OS_MBUF_PKTLEN(ble_hs_test_util_prev_tx));
    TEST_ASSERT_FATAL(om != NULL);

    rc = ble_att_read_type_req_parse(om->om_data, om->om_len, &req);
    TEST_ASSERT(rc == 0);

    TEST_ASSERT(req.batq_start_handle == start_handle);
    TEST_ASSERT(req.batq_end_handle == end_handle);
    TEST_ASSERT(om->om_len == BLE_ATT_READ_TYPE_REQ_BASE_SZ + 2);
    uuid16 = le16toh(om->om_data + BLE_ATT_READ_TYPE_REQ_BASE_SZ);
    TEST_ASSERT(uuid16 == BLE_ATT_UUID_INCLUDE);
}
static void
ble_att_clt_test_misc_verify_tx_write(uint16_t handle_id, void *value,
                                      int value_len, int is_req)
{
    struct ble_att_write_req req;
    struct os_mbuf *om;
    int rc;

    TEST_ASSERT_FATAL(ble_hs_test_util_prev_tx != NULL);

    om = os_mbuf_pullup(ble_hs_test_util_prev_tx,
                        OS_MBUF_PKTLEN(ble_hs_test_util_prev_tx));
    TEST_ASSERT_FATAL(om != NULL);

    if (is_req) {
        rc = ble_att_write_req_parse(om->om_data, om->om_len, &req);
    } else {
        rc = ble_att_write_cmd_parse(om->om_data, om->om_len, &req);
    }
    TEST_ASSERT_FATAL(rc == 0);

    TEST_ASSERT(req.bawq_handle == handle_id);
    TEST_ASSERT(om->om_len == BLE_ATT_WRITE_REQ_BASE_SZ + value_len);
    TEST_ASSERT(memcmp(om->om_data + BLE_ATT_WRITE_REQ_BASE_SZ, value,
                       value_len) == 0);
}
int
ble_att_clt_rx_find_type_value(uint16_t conn_handle, struct os_mbuf **rxom)
{
#if !NIMBLE_OPT(ATT_CLT_FIND_TYPE)
    return BLE_HS_ENOTSUP;
#endif

    struct ble_att_find_type_value_hinfo hinfo;
    int rc;

    /* Reponse consists of a one-byte opcode (already verified) and a variable
     * length Handles-Information-List field.  Strip the opcode from the
     * response.
     */
    os_mbuf_adj(*rxom, BLE_ATT_FIND_TYPE_VALUE_RSP_BASE_SZ);

    /* Parse the Handles-Information-List field, passing each entry to GATT. */
    rc = 0;
    while (OS_MBUF_PKTLEN(*rxom) > 0) {
        rc = ble_att_clt_parse_find_type_value_hinfo(rxom, &hinfo);
        if (rc != 0) {
            break;
        }

        ble_gattc_rx_find_type_value_hinfo(conn_handle, &hinfo);
        os_mbuf_adj(*rxom, BLE_ATT_FIND_TYPE_VALUE_HINFO_BASE_SZ);
    }

    /* Notify GATT client that the full response has been parsed. */
    ble_gattc_rx_find_type_value_complete(conn_handle, rc);

    return 0;
}
static void
ble_att_clt_test_misc_exec_good(uint8_t flags)
{
    struct ble_att_exec_write_req req;
    struct ble_l2cap_chan *chan;
    struct ble_hs_conn *conn;
    struct os_mbuf *om;
    int rc;

    ble_att_clt_test_misc_init(&conn, &chan);

    req.baeq_flags = flags;
    rc = ble_att_clt_tx_exec_write(conn->bhc_handle, &req);
    TEST_ASSERT(rc == 0);

    ble_hs_test_util_tx_all();
    TEST_ASSERT_FATAL(ble_hs_test_util_prev_tx != NULL);

    om = os_mbuf_pullup(ble_hs_test_util_prev_tx,
                        OS_MBUF_PKTLEN(ble_hs_test_util_prev_tx));
    TEST_ASSERT_FATAL(om != NULL);
    TEST_ASSERT(om->om_len == BLE_ATT_EXEC_WRITE_REQ_SZ);

    ble_att_exec_write_req_parse(om->om_data, om->om_len, &req);
    TEST_ASSERT(req.baeq_flags == flags);
}
Esempio n. 9
0
static int
ble_svc_gap_access(uint16_t conn_handle, uint16_t attr_handle,
                   struct ble_gatt_access_ctxt *ctxt, void *arg)
{
    uint16_t uuid16;
    int rc;

    uuid16 = ble_uuid_128_to_16(ctxt->chr->uuid128);
    assert(uuid16 != 0);

    switch (uuid16) {
    case BLE_SVC_GAP_CHR_UUID16_DEVICE_NAME:
        assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
        rc = os_mbuf_append(ctxt->om, ble_svc_gap_name,
                            strlen(ble_svc_gap_name));
        return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;

    case BLE_SVC_GAP_CHR_UUID16_APPEARANCE:
        assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
        rc = os_mbuf_append(ctxt->om, &ble_svc_gap_appearance,
                            sizeof ble_svc_gap_appearance);
        return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;

    case BLE_SVC_GAP_CHR_UUID16_PERIPH_PRIV_FLAG:
        assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
        rc = os_mbuf_append(ctxt->om, &ble_svc_gap_privacy_flag,
                            sizeof ble_svc_gap_privacy_flag);
        return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;

    case BLE_SVC_GAP_CHR_UUID16_RECONNECT_ADDR:
        assert(ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR);
        if (OS_MBUF_PKTLEN(ctxt->om) != sizeof ble_svc_gap_reconnect_addr) {
            return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
        }
        ble_hs_mbuf_to_flat(ctxt->om, ble_svc_gap_reconnect_addr,
                            sizeof ble_svc_gap_reconnect_addr, NULL);
        return 0;

    case BLE_SVC_GAP_CHR_UUID16_PERIPH_PREF_CONN_PARAMS:
        assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
        rc = os_mbuf_append(ctxt->om, &ble_svc_gap_pref_conn_params,
                            sizeof ble_svc_gap_pref_conn_params);
        return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;

    default:
        assert(0);
        return BLE_ATT_ERR_UNLIKELY;
    }
}
Esempio n. 10
0
static int
gatt_svr_chr_write(struct os_mbuf *om, uint16_t min_len, uint16_t max_len,
                   void *dst, uint16_t *len)
{
    uint16_t om_len;
    int rc;

    om_len = OS_MBUF_PKTLEN(om);
    if (om_len < min_len || om_len > max_len) {
        return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
    }

    rc = ble_hs_mbuf_to_flat(om, dst, max_len, len);
    if (rc != 0) {
        return BLE_ATT_ERR_UNLIKELY;
    }

    return 0;
}
static int
ble_att_clt_tx_req_flags(uint16_t conn_handle, struct os_mbuf *txom,
                         ble_hs_conn_flags_t flags_on_success)
{
    struct ble_l2cap_chan *chan;
    struct ble_hs_conn *conn;
    uint16_t total_len;
    uint16_t mtu;
    int extra_len;
    int rc;

    BLE_HS_DBG_ASSERT_EVAL(txom->om_len >= 1);
    ble_att_inc_tx_stat(txom->om_data[0]);

    ble_hs_lock();

    rc = ble_att_conn_chan_find(conn_handle, &conn, &chan);
    if (rc == 0) {
        /* Reduce the size of the transmission to fit the connection's ATT
         * MTU.
         */
        total_len = OS_MBUF_PKTLEN(txom);
        mtu = ble_l2cap_chan_mtu(chan);
        extra_len = total_len - mtu;
        if (extra_len > 0) {
            os_mbuf_adj(txom, -extra_len);
        }

        rc = ble_l2cap_tx(conn, chan, txom);
        txom = NULL;

        if (rc == 0) {
            conn->bhc_flags |= flags_on_success;
        }
    }

    ble_hs_unlock();

    os_mbuf_free_chain(txom);
    return rc;
}
static void
ble_gatt_find_s_test_misc_verify_tx_read(uint16_t handle)
{
    struct ble_att_read_req req;
    struct os_mbuf *om;
    int rc;

    ble_hs_test_util_tx_all();

    TEST_ASSERT_FATAL(ble_hs_test_util_prev_tx != NULL);

    om = os_mbuf_pullup(ble_hs_test_util_prev_tx,
                        OS_MBUF_PKTLEN(ble_hs_test_util_prev_tx));
    TEST_ASSERT_FATAL(om != NULL);

    rc = ble_att_read_req_parse(om->om_data, om->om_len, &req);
    TEST_ASSERT(rc == 0);

    TEST_ASSERT(req.barq_handle == handle);
    TEST_ASSERT(om->om_len == BLE_ATT_READ_REQ_SZ);
}
static int
ble_att_clt_copy_attr_to_flatbuf(struct os_mbuf *om, void **out_attr_val,
                                 uint16_t *out_attr_len)
{
    uint8_t *flat_buf;
    uint16_t attr_len;

    /* Make sure the attribute value isn't too big. */
    attr_len = OS_MBUF_PKTLEN(om);
    if (attr_len > BLE_ATT_ATTR_MAX_LEN) {
        *out_attr_len = 0;
        *out_attr_val = NULL;
        return BLE_HS_EBADDATA;
    }

    /* Copy the attribute data into the global ATT flat buffer. */
    flat_buf = ble_att_get_flat_buf();
    os_mbuf_copydata(om, 0, attr_len, flat_buf);
    *out_attr_val = flat_buf;
    *out_attr_len = attr_len;
    return 0;
}
int
ble_att_clt_rx_read_group_type(uint16_t conn_handle, struct os_mbuf **rxom)
{
#if !NIMBLE_OPT(ATT_CLT_READ_GROUP_TYPE)
    return BLE_HS_ENOTSUP;
#endif

    struct ble_att_read_group_type_adata adata;
    struct ble_att_read_group_type_rsp rsp;
    int rc;

    rc = ble_hs_misc_pullup_base(rxom, BLE_ATT_READ_GROUP_TYPE_RSP_BASE_SZ);
    if (rc != 0) {
        goto done;
    }

    ble_att_read_group_type_rsp_parse((*rxom)->om_data, (*rxom)->om_len, &rsp);

    /* Strip the base from the front of the response. */
    os_mbuf_adj(*rxom, BLE_ATT_READ_GROUP_TYPE_RSP_BASE_SZ);

    /* Parse the Attribute Data List field, passing each entry to GATT. */
    while (OS_MBUF_PKTLEN(*rxom) > 0) {
        rc = ble_att_clt_parse_read_group_type_adata(rxom, rsp.bagp_length,
                                                     &adata);
        if (rc != 0) {
            goto done;
        }

        ble_gattc_rx_read_group_type_adata(conn_handle, &adata);
        os_mbuf_adj(*rxom, rsp.bagp_length);
    }

done:
    /* Notify GATT that the response is done being parsed. */
    ble_gattc_rx_read_group_type_complete(conn_handle, rc);
    return rc;
}
int
ble_att_clt_rx_find_info(uint16_t conn_handle, struct os_mbuf **om)
{
#if !NIMBLE_OPT(ATT_CLT_FIND_INFO)
    return BLE_HS_ENOTSUP;
#endif

    struct ble_att_find_info_idata idata;
    struct ble_att_find_info_rsp rsp;
    int rc;

    rc = ble_hs_misc_pullup_base(om, BLE_ATT_FIND_INFO_RSP_BASE_SZ);
    if (rc != 0) {
        goto done;
    }

    ble_att_find_info_rsp_parse((*om)->om_data, (*om)->om_len, &rsp);

    /* Strip the response base from the front of the mbuf. */
    os_mbuf_adj((*om), BLE_ATT_FIND_INFO_RSP_BASE_SZ);

    while (OS_MBUF_PKTLEN(*om) > 0) {
        rc = ble_att_clt_parse_find_info_entry(om, rsp.bafp_format, &idata);
        if (rc != 0) {
            goto done;
        }

        /* Hand find-info entry to GATT. */
        ble_gattc_rx_find_info_idata(conn_handle, &idata);
    }

    rc = 0;

done:
    /* Notify GATT that response processing is done. */
    ble_gattc_rx_find_info_complete(conn_handle, rc);
    return rc;
}
Esempio n. 16
0
static int
gatt_svr_chr_access_newtmgr(uint16_t conn_handle, uint16_t attr_handle,
                            struct ble_gatt_access_ctxt *ctxt, void *arg)
{
    int rc;
    struct os_mbuf *m_req;

    switch (ctxt->op) {
        case BLE_GATT_ACCESS_OP_WRITE_CHR:
            /* Try to reuse the BLE packet mbuf as the newtmgr request.  This
             * requires a two-byte usrhdr to hold the BLE connection handle so
             * that the newtmgr response can be sent to the correct peer.  If
             * it is not possible to reuse the mbuf, then allocate a new one
             * and copy the request contents.
             */
            if (OS_MBUF_USRHDR_LEN(ctxt->om) >= sizeof (conn_handle)) {
                /* Sufficient usrhdr space already present. */
                m_req = ctxt->om;
                ctxt->om = NULL;
            } else if (OS_MBUF_LEADINGSPACE(ctxt->om) >=
                       sizeof (conn_handle)) {

                /* Usrhdr isn't present, but there is enough leading space to
                 * add one.
                 */
                m_req = ctxt->om;
                ctxt->om = NULL;

                m_req->om_pkthdr_len += sizeof (conn_handle);
            } else {
                /* The mbuf can't be reused.  Allocate a new one and perform a
                 * copy.  Don't set ctxt->om to NULL; let the NimBLE host free
                 * it.
                 */
                m_req = os_msys_get_pkthdr(OS_MBUF_PKTLEN(ctxt->om),
                                           sizeof (conn_handle));
                if (!m_req) {
                    return BLE_ATT_ERR_INSUFFICIENT_RES;
                }
                rc = os_mbuf_appendfrom(m_req, ctxt->om, 0,
                                        OS_MBUF_PKTLEN(ctxt->om));
                if (rc) {
                    return BLE_ATT_ERR_INSUFFICIENT_RES;
                }
            }

            /* Write the connection handle to the newtmgr request usrhdr.  This
             * is necessary so that we later know who to send the newtmgr
             * response to.
             */
            memcpy(OS_MBUF_USRHDR(m_req), &conn_handle, sizeof(conn_handle));

            rc = nmgr_rx_req(&ble_nt, m_req);
            if (rc != 0) {
                return BLE_ATT_ERR_UNLIKELY;
            }
            return 0;

        default:
            assert(0);
            return BLE_ATT_ERR_UNLIKELY;
    }
}
Esempio n. 17
0
File: main.c Progetto: A-Paul/RIOT
static int gatt_svr_chr_access_rw_demo(
        uint16_t conn_handle, uint16_t attr_handle,
        struct ble_gatt_access_ctxt *ctxt, void *arg)
{
    puts("service 'rw demo' callback triggered");

    (void) conn_handle;
    (void) attr_handle;
    (void) arg;

    int rc = 0;

    ble_uuid_t* write_uuid = (ble_uuid_t*) &gatt_svr_chr_rw_demo_write_uuid.u;
    ble_uuid_t* readonly_uuid = (ble_uuid_t*) &gatt_svr_chr_rw_demo_readonly_uuid.u;

    if (ble_uuid_cmp(ctxt->chr->uuid, write_uuid) == 0) {

        puts("access to characteristic 'rw demo (write)'");

        switch (ctxt->op) {

            case BLE_GATT_ACCESS_OP_READ_CHR:
                puts("read from characteristic");
                printf("current value of rm_demo_write_data: '%s'\n",
                       rm_demo_write_data);

                /* send given data to the client */
                rc = os_mbuf_append(ctxt->om, &rm_demo_write_data,
                                    strlen(rm_demo_write_data));

                break;

            case BLE_GATT_ACCESS_OP_WRITE_CHR:
                puts("write to characteristic");

                printf("old value of rm_demo_write_data: '%s'\n",
                       rm_demo_write_data);

                uint16_t om_len;
                om_len = OS_MBUF_PKTLEN(ctxt->om);

                /* read sent data */
                rc = ble_hs_mbuf_to_flat(ctxt->om, &rm_demo_write_data,
                                         sizeof rm_demo_write_data, &om_len);
                /* we need to null-terminate the received string */
                rm_demo_write_data[om_len] = '\0';

                printf("new value of rm_demo_write_data: '%s'\n",
                       rm_demo_write_data);

                break;

            case BLE_GATT_ACCESS_OP_READ_DSC:
                puts("read from descriptor");
                break;

            case BLE_GATT_ACCESS_OP_WRITE_DSC:
                puts("write to descriptor");
                break;

            default:
                puts("unhandled operation!");
                rc = 1;
                break;
        }

        puts("");

        return rc;
    }
    else if (ble_uuid_cmp(ctxt->chr->uuid, readonly_uuid) == 0) {

        puts("access to characteristic 'rw demo (read-only)'");

        if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
            char random_digit;
            /* get random char between '0' and '9' */
            random_digit = 48 + (rand() % 10);

            snprintf(str_answer, STR_ANSWER_BUFFER_SIZE,
                     "new random number: %c", random_digit);
            puts(str_answer);

            rc = os_mbuf_append(ctxt->om, &str_answer, strlen(str_answer));

            puts("");

            return rc;
        }

        return 0;
    }

    puts("unhandled uuid!");
    return 1;
}