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;
}
Пример #2
0
int
ble_uuid_extract(struct os_mbuf *om, int off, void *uuid128)
{
    uint16_t uuid16;
    int remlen;
    int rc;

    remlen = OS_MBUF_PKTHDR(om)->omp_len - off;
    switch (remlen) {
    case 2:
        rc = os_mbuf_copydata(om, off, 2, &uuid16);
        BLE_HS_DBG_ASSERT_EVAL(rc == 0);

        uuid16 = le16toh(&uuid16);
        rc = ble_uuid_16_to_128(uuid16, uuid128);
        if (rc != 0) {
            return rc;
        }
        return 0;

    case 16:
        rc = os_mbuf_copydata(om, off, 16, uuid128);
        BLE_HS_DBG_ASSERT_EVAL(rc == 0);
        return 0;

    default:
        return BLE_HS_EMSGSIZE;
    }
}
Пример #3
0
/**
 * Called to put a packet on the Link Layer receive packet queue.
 *
 * @param rxpdu Pointer to received PDU
 */
void
ble_ll_rx_pdu_in(struct os_mbuf *rxpdu)
{
    struct os_mbuf_pkthdr *pkthdr;

    pkthdr = OS_MBUF_PKTHDR(rxpdu);
    STAILQ_INSERT_TAIL(&g_ble_ll_data.ll_rx_pkt_q, pkthdr, omp_next);
    os_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_rx_pkt_ev);
}
Пример #4
0
/**
 * Allocate a pdu (chain) for reception.
 *
 * @param len
 *
 * @return struct os_mbuf*
 */
struct os_mbuf *
ble_ll_rxpdu_alloc(uint16_t len)
{
    uint16_t mb_bytes;
    struct os_mbuf *m;
    struct os_mbuf *n;
    struct os_mbuf *p;
    struct os_mbuf_pkthdr *pkthdr;

    p = os_msys_get_pkthdr(len, sizeof(struct ble_mbuf_hdr));
    if (!p) {
        goto rxpdu_alloc_exit;
    }

    /* Set packet length */
    pkthdr = OS_MBUF_PKTHDR(p);
    pkthdr->omp_len = len;

    /*
     * NOTE: first mbuf in chain will have data pre-pended to it so we adjust
     * m_data by a word.
     */
    p->om_data += 4;
    mb_bytes = (p->om_omp->omp_databuf_len - p->om_pkthdr_len - 4);

    if (mb_bytes < len) {
        n = p;
        len -= mb_bytes;
        while (len) {
            m = os_msys_get(len, 0);
            if (!m) {
                os_mbuf_free_chain(p);
                p = NULL;
                goto rxpdu_alloc_exit;
            }
            /* Chain new mbuf to existing chain */
            SLIST_NEXT(n, om_next) = m;
            n = m;
            mb_bytes = m->om_omp->omp_databuf_len;
            if (mb_bytes >= len) {
                len = 0;
            } else {
                len -= mb_bytes;
            }
        }
    }


rxpdu_alloc_exit:
    if (!p) {
        STATS_INC(ble_ll_stats, no_bufs);
    }
    return p;
}
Пример #5
0
/**
 * Called to put a packet on the Link Layer transmit packet queue.
 *
 * @param txpdu Pointer to transmit packet
 */
void
ble_ll_acl_data_in(struct os_mbuf *txpkt)
{
    os_sr_t sr;
    struct os_mbuf_pkthdr *pkthdr;

    pkthdr = OS_MBUF_PKTHDR(txpkt);
    OS_ENTER_CRITICAL(sr);
    STAILQ_INSERT_TAIL(&g_ble_ll_data.ll_tx_pkt_q, pkthdr, omp_next);
    OS_EXIT_CRITICAL(sr);
    os_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_tx_pkt_ev);
}
Пример #6
0
/**
 * Called when a data packet is received from the controller.  This function
 * consumes the supplied mbuf, regardless of the outcome.
 *
 * @param om                    The incoming data packet, beginning with the
 *                                  HCI ACL data header.
 *
 * @return                      0 on success; nonzero on failure.
 */
int
host_hci_data_rx(struct os_mbuf *om)
{
    struct hci_data_hdr hci_hdr;
    struct ble_hs_conn *conn;
    ble_l2cap_rx_fn *rx_cb;
    struct os_mbuf *rx_buf;
    uint16_t handle;
    int rc;

    rc = host_hci_data_hdr_strip(om, &hci_hdr);
    if (rc == 0) {
        BLE_HS_LOG(DEBUG, "host_hci_data_rx(): handle=%u pb=%x len=%u data=",
                   BLE_HCI_DATA_HANDLE(hci_hdr.hdh_handle_pb_bc), 
                   BLE_HCI_DATA_PB(hci_hdr.hdh_handle_pb_bc), 
                   hci_hdr.hdh_len);
        ble_hs_misc_log_mbuf(om);

        if (hci_hdr.hdh_len != OS_MBUF_PKTHDR(om)->omp_len) {
            rc = BLE_HS_EBADDATA;
        } else {
            handle = BLE_HCI_DATA_HANDLE(hci_hdr.hdh_handle_pb_bc);

            ble_hs_conn_lock();

            conn = ble_hs_conn_find(handle);
            if (conn == NULL) {
                rc = BLE_HS_ENOTCONN;
            } else {
                rc = ble_l2cap_rx(conn, &hci_hdr, om, &rx_cb, &rx_buf);
                om = NULL;
            }

            ble_hs_conn_unlock();
        }
    }

    os_mbuf_free_chain(om);

    if (rc == 0) {
        assert(rx_cb != NULL);
        assert(rx_buf != NULL);
        rc = rx_cb(handle, &rx_buf);
        os_mbuf_free_chain(rx_buf);
    } else if (rc == BLE_HS_EAGAIN) {
        /* More fragments on the way. */
        rc = 0;
    }

    return rc;
}
Пример #7
0
/**
 * Called to initialize a mbuf used by the controller
 *
 * NOTE: this is only used when the mbuf is created by the controller;
 * it should not be used for data packets (ACL data packets) that come from
 * the host. This routine assumes that the entire pdu length can fit in
 * one mbuf contiguously.
 *
 * @param m
 * @param pdulen
 * @param hdr
 */
void
ble_ll_mbuf_init(struct os_mbuf *m, uint8_t pdulen, uint8_t hdr)
{
    struct ble_mbuf_hdr *ble_hdr;

    /* Set mbuf length and packet length */
    m->om_len = pdulen;
    OS_MBUF_PKTHDR(m)->omp_len = pdulen;

    /* Set BLE transmit header */
    ble_hdr = BLE_MBUF_HDR_PTR(m);
    ble_hdr->txinfo.flags = 0;
    ble_hdr->txinfo.offset = 0;
    ble_hdr->txinfo.pyld_len = pdulen;
    ble_hdr->txinfo.hdr_byte = hdr;
}
Пример #8
0
/*
 * Receive a character from UART.
 */
static int
nmgr_uart_rx_char(void *arg, uint8_t data)
{
    struct nmgr_uart_state *nus = (struct nmgr_uart_state *)arg;
    struct os_mbuf *m;
    int rc;

    if (!nus->nus_rx) {
        m = os_msys_get_pkthdr(SHELL_NLIP_MAX_FRAME, 0);
        if (!m) {
            return 0;
        }
        nus->nus_rx = OS_MBUF_PKTHDR(m);
        if (OS_MBUF_TRAILINGSPACE(m) < SHELL_NLIP_MAX_FRAME) {
            /*
             * mbuf is too small.
             */
            os_mbuf_free_chain(m);
            nus->nus_rx = NULL;
            return 0;
        }
    }

    m = OS_MBUF_PKTHDR_TO_MBUF(nus->nus_rx);
    if (data == '\n') {
        /*
         * Full line of input. Process it outside interrupt context.
         */
        assert(!nus->nus_rx_q);
        nus->nus_rx_q = nus->nus_rx;
        nus->nus_rx = NULL;
        os_eventq_put(g_mgmt_evq, &nus->nus_cb_ev);
        return 0;
    } else {
        rc = os_mbuf_append(m, &data, 1);
        if (rc == 0) {
            return 0;
        }
    }
    /* failed */
    nus->nus_rx->omp_len = 0;
    m->om_len = 0;
    os_mbuf_free_chain(SLIST_NEXT(m, om_next));
    SLIST_NEXT(m, om_next) = NULL;
    return 0;
}
Пример #9
0
static struct os_mbuf *
bletest_send_packet(uint16_t handle)
{
    int j;
    uint8_t val;
    struct os_mbuf *om;
    uint16_t pktlen;

    om = bletest_get_packet();
    if (om) {
        /* set payload length */
#if BLETEST_THROUGHPUT_TEST
        pktlen = BLETEST_PKT_SIZE;
#else
#if (BLETEST_CFG_RAND_PKT_SIZE == 1)
        pktlen = rand() % (BLETEST_MAX_PKT_SIZE + 1);
#else
        pktlen = BLETEST_PKT_SIZE;
#endif
#endif

        /* Put the HCI header in the mbuf */
        put_le16(om->om_data, handle);
        put_le16(om->om_data + 2, pktlen + 4);

        /* Place L2CAP header in packet */
        put_le16(om->om_data + 4, pktlen);
        om->om_data[6] = 0;
        om->om_data[7] = 0;
        om->om_len = 8;
        OS_MBUF_PKTHDR(om)->omp_len = 8;

        /* Fill with incrementing pattern (starting from 1) */
        for (j = 0; j < pktlen; ++j) {
            val = j + 1;
            os_mbuf_append(om, &val, 1);
        }

        /* Transmit it */
        ble_hci_trans_hs_acl_tx(om);
    }

    return om;
}
Пример #10
0
static struct os_mbuf *
host_hci_data_hdr_prepend(struct os_mbuf *om, uint16_t handle, uint8_t pb_flag)
{
    struct hci_data_hdr hci_hdr;

    hci_hdr.hdh_handle_pb_bc = host_hci_handle_pb_bc_join(handle, pb_flag, 0);
    htole16(&hci_hdr.hdh_len, OS_MBUF_PKTHDR(om)->omp_len);

    om = os_mbuf_prepend(om, sizeof hci_hdr);
    if (om == NULL) {
        return NULL;
    }

    memcpy(om->om_data, &hci_hdr, sizeof hci_hdr);

    BLE_HS_LOG(DEBUG, "host tx hci data; handle=%d length=%d\n", handle,
               le16toh(&hci_hdr.hdh_len));

    return om;
}
Пример #11
0
/**
 * Called when a data packet is received from the controller.  This function
 * consumes the supplied mbuf, regardless of the outcome.
 *
 * @param om                    The incoming data packet, beginning with the
 *                                  HCI ACL data header.
 *
 * @return                      0 on success; nonzero on failure.
 */
int
ble_hs_hci_evt_acl_process(struct os_mbuf *om)
{
    struct hci_data_hdr hci_hdr;
    struct ble_hs_conn *conn;
    ble_l2cap_rx_fn *rx_cb;
    uint16_t conn_handle;
    int reject_cid;
    int rc;

    rc = ble_hs_hci_util_data_hdr_strip(om, &hci_hdr);
    if (rc != 0) {
        goto err;
    }

#if (BLETEST_THROUGHPUT_TEST == 0)
    BLE_HS_LOG(DEBUG, "ble_hs_hci_evt_acl_process(): conn_handle=%u pb=%x "
                      "len=%u data=",
               BLE_HCI_DATA_HANDLE(hci_hdr.hdh_handle_pb_bc), 
               BLE_HCI_DATA_PB(hci_hdr.hdh_handle_pb_bc), 
               hci_hdr.hdh_len);
    ble_hs_log_mbuf(om);
    BLE_HS_LOG(DEBUG, "\n");
#endif

    if (hci_hdr.hdh_len != OS_MBUF_PKTHDR(om)->omp_len) {
        rc = BLE_HS_EBADDATA;
        goto err;
    }

    conn_handle = BLE_HCI_DATA_HANDLE(hci_hdr.hdh_handle_pb_bc);

    ble_hs_lock();

    conn = ble_hs_conn_find(conn_handle);
    if (conn == NULL) {
        /* Peer not connected; quietly discard packet. */
        rc = BLE_HS_ENOTCONN;
        reject_cid = -1;
    } else {
        /* Forward ACL data to L2CAP. */
        rc = ble_l2cap_rx(conn, &hci_hdr, om, &rx_cb, &reject_cid);
        om = NULL;
    }

    ble_hs_unlock();

    switch (rc) {
    case 0:
        /* Final fragment received. */
        BLE_HS_DBG_ASSERT(rx_cb != NULL);
        rc = rx_cb(conn->bhc_rx_chan);
        ble_l2cap_forget_rx(conn, conn->bhc_rx_chan);
        break;

    case BLE_HS_EAGAIN:
        /* More fragments on the way. */
        break;

    default:
        if (reject_cid != -1) {
            ble_l2cap_sig_reject_invalid_cid_tx(conn_handle, 0, 0, reject_cid);
        }
        goto err;
    }

    return 0;

err:
    os_mbuf_free_chain(om);
    return rc;
}
Пример #12
0
/**
 * Copies the data from the phy receive buffer into a mbuf chain.
 *
 * @param dptr Pointer to receive buffer
 * @param rxpdu Pointer to already allocated mbuf chain
 *
 * NOTE: the packet header already has the total mbuf length in it. The
 * lengths of the individual mbufs are not set prior to calling.
 *
 */
void
ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu)
{
    uint16_t rem_bytes;
    uint16_t mb_bytes;
    uint16_t copylen;
    uint32_t *dst;
    uint32_t *src;
    struct os_mbuf *m;
    struct ble_mbuf_hdr *ble_hdr;
    struct os_mbuf_pkthdr *pkthdr;

    /* Better be aligned */
    assert(((uint32_t)dptr & 3) == 0);

    pkthdr = OS_MBUF_PKTHDR(rxpdu);
    rem_bytes = pkthdr->omp_len;

    /* Fill in the mbuf pkthdr first. */
    dst = (uint32_t *)(rxpdu->om_data);
    src = (uint32_t *)dptr;

    mb_bytes = (rxpdu->om_omp->omp_databuf_len - rxpdu->om_pkthdr_len - 4);
    copylen = min(mb_bytes, rem_bytes);
    copylen &= 0xFFFC;
    rem_bytes -= copylen;
    mb_bytes -= copylen;
    rxpdu->om_len = copylen;
    while (copylen > 0) {
        *dst = *src;
        ++dst;
        ++src;
        copylen -= 4;
    }

    /* Copy remaining bytes */
    m = rxpdu;
    while (rem_bytes > 0) {
        /* If there are enough bytes in the mbuf, copy them and leave */
        if (rem_bytes <= mb_bytes) {
            memcpy(m->om_data + m->om_len, src, rem_bytes);
            m->om_len += rem_bytes;
            break;
        }

        m = SLIST_NEXT(m, om_next);
        assert(m != NULL);

        mb_bytes = m->om_omp->omp_databuf_len;
        copylen = min(mb_bytes, rem_bytes);
        copylen &= 0xFFFC;
        rem_bytes -= copylen;
        mb_bytes -= copylen;
        m->om_len = copylen;
        dst = (uint32_t *)m->om_data;
        while (copylen > 0) {
            *dst = *src;
            ++dst;
            ++src;
            copylen -= 4;
        }
    }

    /* Copy ble header */
    ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
    memcpy(ble_hdr, &g_ble_phy_data.rxhdr, sizeof(struct ble_mbuf_hdr));
}
Пример #13
0
static void
bletest_execute_advertiser(void)
{
    int i,j;
    int rc;
    uint16_t handle;
    uint16_t pktlen;
    struct os_mbuf *om;

    /* See if we should start advertising again */
    if (g_bletest_current_conns < BLETEST_CFG_CONCURRENT_CONNS) {
        handle = g_bletest_current_conns + 1;
        if (ble_ll_conn_find_active_conn(handle)) {
            /* Set LED to slower blink rate */
            g_bletest_led_rate = OS_TICKS_PER_SEC;

            /* advertising better be stopped! */
            assert(ble_ll_adv_enabled() == 0);

            /* Send the remote used features command */
            rc = host_hci_cmd_le_read_rem_used_feat(handle);
            host_hci_outstanding_opcode = 0;
            assert(rc == 0);

            /* Send the remote used features command */
            rc = host_hci_cmd_rd_rem_version(handle);
            host_hci_outstanding_opcode = 0;
            assert(rc == 0);

            /* set conn update time */
            g_bletest_conn_upd_time = os_time_get() + (OS_TICKS_PER_SEC * 5);
            g_bletest_start_update = 1;

            /* Add to current connections */
            ++g_bletest_current_conns;

            /* Move to next connection */
            if (g_bletest_current_conns < BLETEST_CFG_CONCURRENT_CONNS) {
                /* restart initiating */
                g_bletest_cur_peer_addr[5] += 1;
                g_dev_addr[5] += 1;
                bletest_init_advertising();
                rc = host_hci_cmd_le_set_adv_enable(1);
                host_hci_outstanding_opcode = 0;
                assert(rc == 0);
            }
        }
    }
#if 0
    if (g_bletest_start_update) {
        if ((int32_t)(os_time_get() - g_bletest_conn_upd_time) >= 0) {
            bletest_send_conn_update(1);
            g_bletest_start_update = 0;
        }
    }
#endif
    /* See if it is time to hand a data packet to the connection */
    if ((int32_t)(os_time_get() - g_next_os_time) >= 0) {
        if (g_bletest_current_conns) {
            for (i = 0; i < g_bletest_current_conns; ++i) {
                if ((g_last_handle_used == 0) || 
                    (g_last_handle_used > g_bletest_current_conns)) {
                    g_last_handle_used = 1;
                }
                handle = g_last_handle_used;
                if (ble_ll_conn_find_active_conn(handle)) {
                    om = bletest_get_packet();
                    if (om) {
                        /* set payload length */
                        pktlen = BLETEST_PKT_SIZE;
                        om->om_len = BLETEST_PKT_SIZE + 4;

                        /* Put the HCI header in the mbuf */
                        htole16(om->om_data, handle);
                        htole16(om->om_data + 2, om->om_len);

                        /* Place L2CAP header in packet */
                        htole16(om->om_data + 4, pktlen);
                        om->om_data[6] = 0;
                        om->om_data[7] = 0;

                        /* Fill with incrementing pattern (starting from 1) */
                        for (j = 0; j < pktlen; ++j) {
                            om->om_data[8 + j] = (uint8_t)(j + 1);
                        }

                        /* Add length */
                        om->om_len += 4;
                        OS_MBUF_PKTHDR(om)->omp_len = om->om_len;
                        ble_hci_transport_host_acl_data_send(om);

                        /* Increment last handle used */
                        ++g_last_handle_used;
                    }
                }
            }
        }
        g_next_os_time += OS_TICKS_PER_SEC;
    }
}
Пример #14
0
void
bletest_execute(void)
{
    int rc;

    int i;
    uint16_t pktlen;
    uint16_t handle;
    struct os_mbuf *om;
    struct ble_ll_conn_sm *connsm;

    handle = 1;
    if ((int32_t)(os_time_get() - g_next_os_time) >= 0) {
        if (g_bletest_state == 0) {
            rc = host_hci_cmd_le_set_adv_enable(1);
            host_hci_outstanding_opcode = 0;
            assert(rc == 0);
            g_bletest_state = 1;
        } else if (g_bletest_state == 1) {
            /* See if handle 1 has been created. If so, send packets */
            connsm = ble_ll_conn_find_active_conn(handle);
            if (connsm) {
                /* Set connection end time */
                g_bletest_conn_end = os_time_get() + 
                    (OS_TICKS_PER_SEC * (60 * 15));
                g_bletest_state = 2;
            }
        } else if (g_bletest_state == 2) {
            if ((int32_t)(os_time_get() - g_bletest_conn_end) >= 0) {
                g_bletest_state = 3;
                host_hci_cmd_disconnect(handle, BLE_ERR_REM_USER_CONN_TERM);
            } else {
                om = bletest_get_packet();
                if (om) {
                    /* set payload length */
                    pktlen = BLETEST_PKT_SIZE;
                    om->om_len = BLETEST_PKT_SIZE + 4;

                    /* Put the HCI header in the mbuf */
                    htole16(om->om_data, handle);
                    htole16(om->om_data + 2, om->om_len);

                    /* Place L2CAP header in packet */
                    htole16(om->om_data + 4, pktlen);
                    om->om_data[6] = 0;
                    om->om_data[7] = 0;

                    /* Fill with incrementing pattern (starting from 1) */
                    for (i = 0; i < pktlen; ++i) {
                        om->om_data[8 + i] = (uint8_t)(i + 1);
                    }

                    /* Add length */
                    om->om_len += 4;
                    OS_MBUF_PKTHDR(om)->omp_len = om->om_len;
                    ble_hci_transport_host_acl_data_send(om);
                }
                g_next_os_time += OS_TICKS_PER_SEC / 10;
                return;
            }
        } else if (g_bletest_state == 3) {
            /* We should be waiting for disconnect */
            connsm = ble_ll_conn_find_active_conn(handle);
            if (!connsm) {
                /* Set to 0 if you want to restart advertising */
                //g_bletest_state = 0;
                g_bletest_state = 4;
            }
        }
        g_next_os_time += OS_TICKS_PER_SEC;
    }
}
Пример #15
0
/*
 * Called by mgmt to queue packet out to UART.
 */
static int
nmgr_uart_out(struct nmgr_transport *nt, struct os_mbuf *m)
{
    struct nmgr_uart_state *nus = (struct nmgr_uart_state *)nt;
    struct os_mbuf_pkthdr *mpkt;
    struct os_mbuf *n;
    char tmp_buf[12];
    uint16_t crc;
    char *dst;
    int off;
    int boff;
    int slen;
    int sr;
    int rc;
    int last;
    int tx_sz;

    assert(OS_MBUF_IS_PKTHDR(m));
    mpkt = OS_MBUF_PKTHDR(m);

    off = 0;
    crc = CRC16_INITIAL_CRC;
    for (n = m; n; n = SLIST_NEXT(n, om_next)) {
        crc = crc16_ccitt(crc, n->om_data, n->om_len);
    }
    crc = htons(crc);
    dst = os_mbuf_extend(m, sizeof(crc));
    if (!dst) {
        goto err;
    }
    memcpy(dst, &crc, sizeof(crc));

    n = os_msys_get(SHELL_NLIP_MAX_FRAME, 0);
    if (!n || OS_MBUF_TRAILINGSPACE(n) < 32) {
        goto err;
    }

    while (off < mpkt->omp_len) {
        tx_sz = 2;
        dst = os_mbuf_extend(n, 2);
        if (off == 0) {
            *(uint16_t *)dst = htons(SHELL_NLIP_PKT);
            *(uint16_t *)tmp_buf = htons(mpkt->omp_len);
            boff = 2;
        } else {
            *(uint16_t *)dst = htons(SHELL_NLIP_DATA);
            boff = 0;
        }

        while (off < mpkt->omp_len) {
            slen = mpkt->omp_len - off;
            last = 1;
            if (slen > sizeof(tmp_buf) + boff) {
                slen = sizeof(tmp_buf) - boff;
                last = 0;
            }
            if (tx_sz + BASE64_ENCODE_SIZE(slen + boff) >= 124) {
                break;
            }
            rc = os_mbuf_copydata(m, off, slen, tmp_buf + boff);
            assert(rc == 0);

            off += slen;
            slen += boff;

            dst = os_mbuf_extend(n, BASE64_ENCODE_SIZE(slen));
            if (!dst) {
                goto err;
            }
            tx_sz += base64_encode(tmp_buf, slen, dst, last);
            boff = 0;
        }

        if (os_mbuf_append(n, "\n", 1)) {
            goto err;
        }
    }

    os_mbuf_free_chain(m);
    OS_ENTER_CRITICAL(sr);
    if (!nus->nus_tx) {
        nus->nus_tx = n;
        uart_start_tx(nus->nus_dev);
    } else {
        os_mbuf_concat(nus->nus_tx, n);
    }
    OS_EXIT_CRITICAL(sr);

    return 0;
err:
    os_mbuf_free_chain(m);
    os_mbuf_free_chain(n);
    return -1;
}
Пример #16
0
static void
nmgr_handle_req(struct nmgr_transport *nt, struct os_mbuf *req)
{
    struct os_mbuf *rsp;
    const struct mgmt_handler *handler;
    struct nmgr_hdr *rsp_hdr;
    struct nmgr_hdr hdr;
    int off;
    uint16_t len;
    int rc;

    rsp_hdr = NULL;

    rsp = os_msys_get_pkthdr(512, OS_MBUF_USRHDR_LEN(req));
    if (!rsp) {
        rc = os_mbuf_copydata(req, 0, sizeof(hdr), &hdr);
        if (rc < 0) {
            goto err_norsp;
        }
        rsp = req;
        req = NULL;
        goto err;
    }

    /* Copy the request packet header into the response. */
    memcpy(OS_MBUF_USRHDR(rsp), OS_MBUF_USRHDR(req), OS_MBUF_USRHDR_LEN(req));

    off = 0;
    len = OS_MBUF_PKTHDR(req)->omp_len;

    while (off < len) {
        rc = os_mbuf_copydata(req, off, sizeof(hdr), &hdr);
        if (rc < 0) {
            rc = MGMT_ERR_EINVAL;
            goto err_norsp;
        }

        hdr.nh_len = ntohs(hdr.nh_len);

        handler = mgmt_find_handler(ntohs(hdr.nh_group), hdr.nh_id);
        if (!handler) {
            rc = MGMT_ERR_ENOENT;
            goto err;
        }

        /* Build response header apriori.  Then pass to the handlers
         * to fill out the response data, and adjust length & flags.
         */
        rsp_hdr = nmgr_init_rsp(rsp, &hdr);
        if (!rsp_hdr) {
            rc = MGMT_ERR_ENOMEM;
            goto err_norsp;
        }

        cbor_mbuf_reader_init(&nmgr_task_cbuf.reader, req, sizeof(hdr));
        cbor_parser_init(&nmgr_task_cbuf.reader.r, 0,
                         &nmgr_task_cbuf.n_b.parser, &nmgr_task_cbuf.n_b.it);

        if (hdr.nh_op == NMGR_OP_READ) {
            if (handler->mh_read) {
                rc = handler->mh_read(&nmgr_task_cbuf.n_b);
            } else {
                rc = MGMT_ERR_ENOENT;
            }
        } else if (hdr.nh_op == NMGR_OP_WRITE) {
            if (handler->mh_write) {
                rc = handler->mh_write(&nmgr_task_cbuf.n_b);
            } else {
                rc = MGMT_ERR_ENOENT;
            }
        } else {
            rc = MGMT_ERR_EINVAL;
        }

        if (rc != 0) {
            goto err;
        }

        rsp_hdr->nh_len +=
            cbor_encode_bytes_written(&nmgr_task_cbuf.n_b.encoder);
        off += sizeof(hdr) + OS_ALIGN(hdr.nh_len, 4);

        rsp_hdr->nh_len = htons(rsp_hdr->nh_len);
        rc = nmgr_rsp_fragment(nt, rsp_hdr, rsp, req);
        if (rc) {
            goto err;
        }
    }

    os_mbuf_free_chain(rsp);
    os_mbuf_free_chain(req);
    return;
err:
    OS_MBUF_PKTHDR(rsp)->omp_len = rsp->om_len = 0;
    nmgr_send_err_rsp(nt, rsp, &hdr, rc);
    os_mbuf_free_chain(req);
    return;
err_norsp:
    os_mbuf_free_chain(rsp);
    os_mbuf_free_chain(req);
    return;
}
Пример #17
0
/*
 * Check for full packet. If frame is not right, free the mbuf.
 */
static void
nmgr_uart_rx_pkt(struct nmgr_uart_state *nus, struct os_mbuf_pkthdr *rxm)
{
    struct os_mbuf *m;
    struct nmgr_ser_hdr *nsh;
    uint16_t crc;
    int rc;

    m = OS_MBUF_PKTHDR_TO_MBUF(rxm);

    if (rxm->omp_len <= sizeof(uint16_t) + sizeof(crc)) {
        goto err;
    }

    nsh = (struct nmgr_ser_hdr *)m->om_data;
    switch (nsh->nsh_seq) {
    case htons(SHELL_NLIP_PKT):
        if (nus->nus_rx_pkt) {
            os_mbuf_free_chain(OS_MBUF_PKTHDR_TO_MBUF(nus->nus_rx_pkt));
            nus->nus_rx_pkt = NULL;
        }
        break;
    case htons(SHELL_NLIP_DATA):
        if (!nus->nus_rx_pkt) {
            goto err;
        }
        break;
    default:
        goto err;
    }

    if (os_mbuf_append(m, "\0", 1)) {
        /*
         * Null-terminate the line for base64_decode's sake.
         */
        goto err;
    }
    m = os_mbuf_pullup(m, rxm->omp_len);
    if (!m) {
        /*
         * Make data contiguous for base64_decode's sake.
         */
        goto err;
    }
    rxm = OS_MBUF_PKTHDR(m);
    rc = base64_decode((char *)m->om_data + 2, (char *)m->om_data + 2);
    if (rc < 0) {
        goto err;
    }
    rxm->omp_len = m->om_len = rc + 2;
    if (nus->nus_rx_pkt) {
        os_mbuf_adj(m, 2);
        os_mbuf_concat(OS_MBUF_PKTHDR_TO_MBUF(nus->nus_rx_pkt), m);
    } else {
        nus->nus_rx_pkt = rxm;
    }

    m = OS_MBUF_PKTHDR_TO_MBUF(nus->nus_rx_pkt);
    nsh = (struct nmgr_ser_hdr *)m->om_data;
    if (nus->nus_rx_pkt->omp_len - sizeof(*nsh) == ntohs(nsh->nsh_len)) {
        os_mbuf_adj(m, 4);
        os_mbuf_adj(m, -2);
        nmgr_rx_req(&nus->nus_transport, m);
        nus->nus_rx_pkt = NULL;
    }
    return;
err:
    os_mbuf_free_chain(m);
}