Exemple #1
0
static void process_data(struct net_pkt *pkt)
{
	struct net_buf *buf = net_buf_frag_last(pkt->frags);
	u8_t seq, num_attr;
	int ret, i;

	seq = net_buf_pull_u8(buf);
	num_attr = net_buf_pull_u8(buf);

	SYS_LOG_DBG("seq %u num_attr %u", seq, num_attr);

	/**
	 * There are some attributes sent over this protocol
	 * discard them and return packet data report.
	 */

	for (i = 0; i < num_attr; i++) {
		/* attr */
		net_buf_pull_u8(buf);
		/* value */
		net_buf_pull_be16(buf);
	}

	/* Transmit data through radio */
	ret = radio_api->tx(ieee802154_dev, pkt, buf);
	if (ret) {
		SYS_LOG_ERR("Error transmit data");
	}

	/* TODO: Return correct status codes */
	/* TODO: Implement re-transmissions if needed */

	/* Send packet data report */
	send_pkt_report(seq, ret, 1);
}
Exemple #2
0
static void rx_thread(void)
{
	SYS_LOG_INF("RX thread started");

	while (1) {
		struct net_pkt *pkt;
		struct net_buf *buf;
		u8_t specifier;

		pkt = k_fifo_get(&rx_queue, K_FOREVER);
		buf = net_buf_frag_last(pkt->frags);

		SYS_LOG_DBG("Got pkt %p buf %p", pkt, buf);

		hexdump("SLIP >", buf->data, buf->len);

		/* TODO: process */
		specifier = net_buf_pull_u8(buf);
		switch (specifier) {
		case '?':
			process_request(buf);
			break;
		case '!':
			process_config(pkt);
			break;
		default:
			SYS_LOG_ERR("Unknown message specifier %c", specifier);
			break;
		}

		net_pkt_unref(pkt);

		k_yield();
	}
}
Exemple #3
0
static void tx_thread(void)
{
	SYS_LOG_DBG("Tx thread started");

	while (1) {
		uint8_t cmd;
		struct net_buf *pkt, *buf;

		pkt = net_buf_get(&tx_queue, K_FOREVER);
		buf = net_buf_frag_last(pkt);
		cmd = net_buf_pull_u8(buf);

		hexdump(">", buf->data, buf->len);

		switch (cmd) {
		case RESET:
			SYS_LOG_DBG("Reset device");
			break;
		case TX:
			tx(pkt);
			break;
		case START:
			start();
			break;
		case STOP:
			stop();
			break;
		case SET_CHANNEL:
			set_channel(buf->data, buf->len);
			break;
		case SET_IEEE_ADDR:
			set_ieee_addr(buf->data, buf->len);
			break;
		case SET_SHORT_ADDR:
			set_short_addr(buf->data, buf->len);
			break;
		case SET_PAN_ID:
			set_pan_id(buf->data, buf->len);
			break;
		default:
			SYS_LOG_ERR("%x: Not handled for now", cmd);
			break;
		}

		net_nbuf_unref(pkt);

		k_yield();
	}
}
Exemple #4
0
static void l2cap_chan_le_recv_sdu(struct bt_l2cap_le_chan *chan,
				   struct net_buf *buf)
{
	struct net_buf *frag;
	uint16_t len;

	BT_DBG("chan %p len %u sdu %zu", chan, buf->len,
	       net_buf_frags_len(chan->_sdu));

	if (net_buf_frags_len(chan->_sdu) + buf->len > chan->_sdu_len) {
		BT_ERR("SDU length mismatch");
		bt_l2cap_chan_disconnect(&chan->chan);
		return;
	}

	/* Jump to last fragment */
	frag = net_buf_frag_last(chan->_sdu);

	while (buf->len) {
		/* Check if there is any space left in the current fragment */
		if (!net_buf_tailroom(frag)) {
			frag = l2cap_alloc_frag(chan);
			if (!frag) {
				BT_ERR("Unable to store SDU");
				bt_l2cap_chan_disconnect(&chan->chan);
				return;
			}
		}

		len = min(net_buf_tailroom(frag), buf->len);
		net_buf_add_mem(frag, buf->data, len);
		net_buf_pull(buf, len);

		BT_DBG("frag %p len %u", frag, frag->len);
	}

	if (net_buf_frags_len(chan->_sdu) == chan->_sdu_len) {
		/* Receiving complete SDU, notify channel and reset SDU buf */
		chan->chan.ops->recv(&chan->chan, chan->_sdu);
		net_buf_unref(chan->_sdu);
		chan->_sdu = NULL;
		chan->_sdu_len = 0;
	}

	l2cap_chan_update_credits(chan);
}
Exemple #5
0
static void process_config(struct net_pkt *pkt)
{
	struct net_buf *buf = net_buf_frag_last(pkt->frags);
	u8_t cmd = net_buf_pull_u8(buf);

	SYS_LOG_DBG("Process config %c", cmd);

	switch (cmd) {
	case 'S':
		process_data(pkt);
		break;
	case 'C':
		set_channel(net_buf_pull_u8(buf));
		break;
	default:
		SYS_LOG_ERR("Unhandled cmd %u", cmd);
	}
}
Exemple #6
0
/**
 * TX - transmit to SLIP interface
 */
static void tx_thread(void)
{
	SYS_LOG_DBG("TX thread started");

	/* Allow to send one TX */
	k_sem_give(&tx_sem);

	while (1) {
		struct net_pkt *pkt;
		struct net_buf *buf;
		size_t len;

		k_sem_take(&tx_sem, K_FOREVER);

		pkt = k_fifo_get(&tx_queue, K_FOREVER);
		buf = net_buf_frag_last(pkt->frags);
		len = net_pkt_get_len(pkt);

		SYS_LOG_DBG("Send pkt %p buf %p len %d", pkt, buf, len);

		hexdump("SLIP <", buf->data, buf->len);

		/* Remove LQI */
		/* TODO: Reuse get_lqi() */
		buf->len -= 1;

		/* remove FCS 2 bytes */
		buf->len -= 2;

		/* SLIP encode and send */
		len = slip_buffer(slip_buf, buf);
		uart_fifo_fill(uart_dev, slip_buf, len);

		net_pkt_unref(pkt);

#if 0
		k_yield();
#endif
	}
}
Exemple #7
0
int net_recv_data(struct net_if *iface, struct net_buf *buf)
{
	struct net_buf *frag;

	SYS_LOG_DBG("Got data, buf %p, len %d frags->len %d",
		    buf, buf->len, net_buf_frags_len(buf));

	frag = net_buf_frag_last(buf);

	/**
	 * Add length 1 byte, do not forget to reserve it
	 */
	net_buf_push_u8(frag, net_buf_frags_len(buf) - 1);

	hexdump("<", frag->data, net_buf_frags_len(buf));

	try_write(WPANUSB_ENDP_BULK_IN, frag->data, net_buf_frags_len(buf));

	net_nbuf_unref(buf);

	return 0;
}
Exemple #8
0
static int tx(struct net_buf *pkt)
{
	struct net_buf *buf = net_buf_frag_last(pkt);
	uint8_t seq = net_buf_pull_u8(buf);
	int retries = 3;
	int ret;

	SYS_LOG_DBG("len %d seq %u", buf->len, seq);

	do {
		ret = radio_api->tx(ieee802154_dev, pkt);
	} while (ret && retries--);

	if (ret) {
		SYS_LOG_ERR("Error sending data, seq %u", seq);
		/* Send seq = 0 for unsuccessful send */
		seq = 0;
	}

	try_write(WPANUSB_ENDP_BULK_IN, &seq, sizeof(seq));

	return ret;
}
Exemple #9
0
static int slip_process_byte(unsigned char c)
{
	struct net_buf *buf;
#ifdef VERBOSE_DEBUG
	SYS_LOG_DBG("recv: state %u byte %x", slip_state, c);
#endif
	switch (slip_state) {
	case STATE_GARBAGE:
		if (c == SLIP_END) {
			slip_state = STATE_OK;
		}
		SYS_LOG_DBG("garbage: discard byte %x", c);
		return 0;

	case STATE_ESC:
		if (c == SLIP_ESC_END) {
			c = SLIP_END;
		} else if (c == SLIP_ESC_ESC) {
			c = SLIP_ESC;
		} else {
			slip_state = STATE_GARBAGE;
			return 0;
		}
		slip_state = STATE_OK;
		break;

	case STATE_OK:
		if (c == SLIP_ESC) {
			slip_state = STATE_ESC;
			return 0;
		} else if (c == SLIP_END) {
			return 1;
		}
		break;
	}

#ifdef VERBOSE_DEBUG
	SYS_LOG_DBG("processed: state %u byte %x", slip_state, c);
#endif

	if (!pkt_curr) {
		pkt_curr = net_pkt_get_reserve_rx(0, K_NO_WAIT);
		if (!pkt_curr) {
			SYS_LOG_ERR("No more buffers");
			return 0;
		}
		buf = net_pkt_get_frag(pkt_curr, K_NO_WAIT);
		if (!buf) {
			SYS_LOG_ERR("No more buffers");
			net_pkt_unref(pkt_curr);
			return 0;
		}
		net_pkt_frag_insert(pkt_curr, buf);
	} else {
		buf = net_buf_frag_last(pkt_curr->frags);
	}

	if (!net_buf_tailroom(buf)) {
		SYS_LOG_ERR("No more buf space: buf %p len %u", buf, buf->len);

		net_pkt_unref(pkt_curr);
		pkt_curr = NULL;
		return 0;
	}

	net_buf_add_u8(buf, c);

	return 0;
}
Exemple #10
0
static void test_pkt_read_append(void)
{
	int remaining = strlen(sample_data);
	u8_t verify_rw_short[sizeof(test_rw_short)];
	u8_t verify_rw_long[sizeof(test_rw_long)];
	struct net_pkt *pkt;
	struct net_buf *frag;
	struct net_buf *tfrag;
	struct ipv6_hdr *ipv6;
	struct udp_hdr *udp;
	u8_t data[10];
	int pos = 0;
	int bytes;
	u16_t off;
	u16_t tpos;
	u16_t fail_pos;

	/* Example of multi fragment read, append and skip APS's */
	pkt = net_pkt_get_reserve_rx(0, K_FOREVER);
	frag = net_pkt_get_reserve_rx_data(LL_RESERVE, K_FOREVER);

	/* Place the IP + UDP header in the first fragment */
	if (!net_buf_tailroom(frag)) {
		ipv6 = (struct ipv6_hdr *)(frag->data);
		udp = (struct udp_hdr *)((void *)ipv6 + sizeof(*ipv6));
		if (net_buf_tailroom(frag) < sizeof(ipv6)) {
			printk("Not enough space for IPv6 header, "
			       "needed %zd bytes, has %zd bytes\n",
			       sizeof(ipv6), net_buf_tailroom(frag));
			zassert_true(false, "No space for IPv6 header");
		}
		net_buf_add(frag, sizeof(ipv6));

		if (net_buf_tailroom(frag) < sizeof(udp)) {
			printk("Not enough space for UDP header, "
			       "needed %zd bytes, has %zd bytes\n",
			       sizeof(udp), net_buf_tailroom(frag));
			zassert_true(false, "No space for UDP header");
		}

		net_pkt_set_appdata(pkt, (void *)udp + sizeof(*udp));
		net_pkt_set_appdatalen(pkt, 0);
	}

	net_pkt_frag_add(pkt, frag);

	/* Put some data to rest of the fragments */
	frag = net_pkt_get_reserve_rx_data(LL_RESERVE, K_FOREVER);
	if (net_buf_tailroom(frag) -
	      (CONFIG_NET_BUF_DATA_SIZE - LL_RESERVE)) {
		printk("Invalid number of bytes available in the buf, "
		       "should be 0 but was %zd - %d\n",
		       net_buf_tailroom(frag),
		       CONFIG_NET_BUF_DATA_SIZE - LL_RESERVE);
		zassert_true(false, "Invalid number of bytes avail");
	}

	if (((int)net_buf_tailroom(frag) - remaining) > 0) {
		printk("We should have been out of space now, "
		       "tailroom %zd user data len %zd\n",
		       net_buf_tailroom(frag),
		       strlen(sample_data));
		zassert_true(false, "Not out of space");
	}

	while (remaining > 0) {
		int copy;

		bytes = net_buf_tailroom(frag);
		copy = remaining > bytes ? bytes : remaining;
		memcpy(net_buf_add(frag, copy), &sample_data[pos], copy);

		DBG("Remaining %d left %d copy %d\n", remaining, bytes, copy);

		pos += bytes;
		remaining -= bytes;
		if (net_buf_tailroom(frag) - (bytes - copy)) {
			printk("There should have not been any tailroom left, "
			       "tailroom %zd\n",
			       net_buf_tailroom(frag) - (bytes - copy));
			zassert_true(false, "Still tailroom left");
		}

		net_pkt_frag_add(pkt, frag);
		if (remaining > 0) {
			frag = net_pkt_get_reserve_rx_data(LL_RESERVE,
							   K_FOREVER);
		}
	}

	bytes = net_pkt_get_len(pkt);
	if (bytes != strlen(sample_data)) {
		printk("Invalid number of bytes in message, %zd vs %d\n",
		       strlen(sample_data), bytes);
		zassert_true(false, "Message size wrong");
	}

	/* Failure cases */
	/* Invalid buffer */
	tfrag = net_frag_skip(NULL, 10, &fail_pos, 10);
	zassert_true(!tfrag && fail_pos == 0xffff, "Invalid case NULL buffer");

	/* Invalid: Skip more than a buffer length.*/
	tfrag = net_buf_frag_last(pkt->frags);
	tfrag = net_frag_skip(tfrag, tfrag->len - 1, &fail_pos, tfrag->len + 2);
	if (!(!tfrag && fail_pos == 0xffff)) {
		printk("Invalid case offset %d length to skip %d,"
		       "frag length %d\n",
		       tfrag->len - 1, tfrag->len + 2, tfrag->len);
		zassert_true(false, "Invalid offset");
	}

	/* Invalid offset */
	tfrag = net_buf_frag_last(pkt->frags);
	tfrag = net_frag_skip(tfrag, tfrag->len + 10, &fail_pos, 10);
	if (!(!tfrag && fail_pos == 0xffff)) {
		printk("Invalid case offset %d length to skip %d,"
		       "frag length %d\n",
		       tfrag->len + 10, 10, tfrag->len);
		zassert_true(false, "Invalid offset");
	}

	/* Valid cases */

	/* Offset is more than single fragment length */
	/* Get the first data fragment */
	tfrag = pkt->frags;
	tfrag = tfrag->frags;
	off = tfrag->len;
	tfrag = net_frag_read(tfrag, off + 10, &tpos, 10, data);
	if (!tfrag ||
	    memcmp(sample_data + off + 10, data, 10)) {
		printk("Failed to read from offset %d, frag length %d "
		       "read length %d\n",
		       tfrag->len + 10, tfrag->len, 10);
		zassert_true(false, "Fail offset read");
	}

	/* Skip till end of all fragments */
	/* Get the first data fragment */
	tfrag = pkt->frags;
	tfrag = tfrag->frags;
	tfrag = net_frag_skip(tfrag, 0, &tpos, strlen(sample_data));
	zassert_true(!tfrag && tpos == 0,
		     "Invalid skip till end of all fragments");

	/* Short data test case */
	/* Test case scenario:
	 * 1) Cache the current fragment and offset
	 * 2) Append short data
	 * 3) Append short data again
	 * 4) Skip first short data from cached frag or offset
	 * 5) Read short data and compare
	 */
	tfrag = net_buf_frag_last(pkt->frags);
	off = tfrag->len;

	zassert_true(net_pkt_append_all(pkt, (u16_t)sizeof(test_rw_short),
					test_rw_short, K_FOREVER),
		     "net_pkt_append failed");

	zassert_true(net_pkt_append_all(pkt, (u16_t)sizeof(test_rw_short),
					test_rw_short, K_FOREVER),
		     "net_pkt_append failed");

	tfrag = net_frag_skip(tfrag, off, &tpos,
			     (u16_t)sizeof(test_rw_short));
	zassert_not_null(tfrag, "net_frag_skip failed");

	tfrag = net_frag_read(tfrag, tpos, &tpos,
			     (u16_t)sizeof(test_rw_short),
			     verify_rw_short);
	zassert_true(!tfrag && tpos == 0, "net_frag_read failed");
	zassert_false(memcmp(test_rw_short, verify_rw_short,
			     sizeof(test_rw_short)),
		      "net_frag_read failed with mismatch data");

	/* Long data test case */
	/* Test case scenario:
	 * 1) Cache the current fragment and offset
	 * 2) Append long data
	 * 3) Append long data again
	 * 4) Skip first long data from cached frag or offset
	 * 5) Read long data and compare
	 */
	tfrag = net_buf_frag_last(pkt->frags);
	off = tfrag->len;

	zassert_true(net_pkt_append_all(pkt, (u16_t)sizeof(test_rw_long),
					test_rw_long, K_FOREVER),
		     "net_pkt_append failed");

	zassert_true(net_pkt_append_all(pkt, (u16_t)sizeof(test_rw_long),
					test_rw_long, K_FOREVER),
		     "net_pkt_append failed");

	tfrag = net_frag_skip(tfrag, off, &tpos,
			      (u16_t)sizeof(test_rw_long));
	zassert_not_null(tfrag, "net_frag_skip failed");

	tfrag = net_frag_read(tfrag, tpos, &tpos,
			     (u16_t)sizeof(test_rw_long),
			     verify_rw_long);
	zassert_true(!tfrag && tpos == 0, "net_frag_read failed");
	zassert_false(memcmp(test_rw_long, verify_rw_long,
			     sizeof(test_rw_long)),
		      "net_frag_read failed with mismatch data");

	net_pkt_unref(pkt);

	DBG("test_pkt_read_append passed\n");
}