コード例 #1
0
ファイル: l2cap.c プロジェクト: cyysu/AliOS-Things
static void l2cap_chan_update_credits(struct bt_l2cap_le_chan *chan)
{
	struct net_buf *buf;
	struct bt_l2cap_le_credits *ev;
	uint16_t credits;

	/* Only give more credits if it went bellow the defined threshold */
	if (k_sem_count_get(&chan->rx.credits) >
	    L2CAP_LE_CREDITS_THRESHOLD(chan->rx.init_credits)) {
		goto done;
	}

	/* Restore credits */
	credits = chan->rx.init_credits - k_sem_count_get(&chan->rx.credits);
	l2cap_chan_rx_give_credits(chan, credits);

	buf = l2cap_create_le_sig_pdu(BT_L2CAP_LE_CREDITS, get_ident(),
				      sizeof(*ev));

	ev = net_buf_add(buf, sizeof(*ev));
	ev->cid = sys_cpu_to_le16(chan->rx.cid);
	ev->credits = sys_cpu_to_le16(credits);

	bt_l2cap_send(chan->chan.conn, BT_L2CAP_CID_LE_SIG, buf);

done:
	BT_DBG("chan %p credits %u", chan, k_sem_count_get(&chan->rx.credits));
}
コード例 #2
0
ファイル: poll.c プロジェクト: bboozzoo/zephyr
/* must be called with interrupts locked */
static inline int is_condition_met(struct k_poll_event *event, u32_t *state)
{
	switch (event->type) {
	case K_POLL_TYPE_SEM_AVAILABLE:
		if (k_sem_count_get(event->sem) > 0) {
			*state = K_POLL_STATE_SEM_AVAILABLE;
			return 1;
		}
		break;
	case K_POLL_TYPE_DATA_AVAILABLE:
		if (!k_queue_is_empty(event->queue)) {
			*state = K_POLL_STATE_FIFO_DATA_AVAILABLE;
			return 1;
		}
		break;
	case K_POLL_TYPE_SIGNAL:
		if (event->signal->signaled) {
			*state = K_POLL_STATE_SIGNALED;
			return 1;
		}
		break;
	case K_POLL_TYPE_IGNORE:
		return 0;
	default:
		__ASSERT(0, "invalid event type (0x%x)\n", event->type);
		break;
	}

	return 0;
}
コード例 #3
0
ファイル: l2cap.c プロジェクト: cyysu/AliOS-Things
static int l2cap_chan_le_send(struct bt_l2cap_le_chan *ch, struct net_buf *buf,
			      uint16_t sdu_hdr_len)
{
	int len;

	/* Wait for credits */
	if (k_sem_take(&ch->tx.credits, K_NO_WAIT)) {
		BT_DBG("No credits to transmit packet");
		return -EAGAIN;
	}

	buf = l2cap_chan_create_seg(ch, buf, sdu_hdr_len);
	if (!buf) {
		return -ENOMEM;
	}

	/* Channel may have been disconnected while waiting for credits */
	if (!ch->chan.conn) {
		net_buf_unref(buf);
		return -ECONNRESET;
	}

	BT_DBG("ch %p cid 0x%04x len %u credits %u", ch, ch->tx.cid,
	       buf->len, k_sem_count_get(&ch->tx.credits));

	len = buf->len;

	bt_l2cap_send(ch->chan.conn, ch->tx.cid, buf);

	return len;
}
コード例 #4
0
void test_sema_count_get(void)
{
	k_sem_init(&sema, SEM_INITIAL, SEM_LIMIT);
	/**TESTPOINT: sem count get upon init*/
	zassert_equal(k_sem_count_get(&sema), SEM_INITIAL, NULL);
	k_sem_give(&sema);
	/**TESTPOINT: sem count get after give*/
	zassert_equal(k_sem_count_get(&sema), SEM_INITIAL + 1, NULL);
	k_sem_take(&sema, K_FOREVER);
	/**TESTPOINT: sem count get after take*/
	for (int i = 0; i < SEM_LIMIT; i++) {
		zassert_equal(k_sem_count_get(&sema), SEM_INITIAL + i, NULL);
		k_sem_give(&sema);
	}
	/**TESTPOINT: sem give above limit*/
	k_sem_give(&sema);
	zassert_equal(k_sem_count_get(&sema), SEM_LIMIT, NULL);
}
コード例 #5
0
ファイル: l2cap.c プロジェクト: cyysu/AliOS-Things
static void le_credits(struct bt_l2cap *l2cap, uint8_t ident,
		       struct net_buf *buf)
{
	struct bt_conn *conn = l2cap->chan.chan.conn;
	struct bt_l2cap_chan *chan;
	struct bt_l2cap_le_credits *ev = (void *)buf->data;
	struct bt_l2cap_le_chan *ch;
	uint16_t credits, cid;

	if (buf->len < sizeof(*ev)) {
		BT_ERR("Too small LE Credits packet size");
		return;
	}

	cid = sys_le16_to_cpu(ev->cid);
	credits = sys_le16_to_cpu(ev->credits);

	BT_DBG("cid 0x%04x credits %u", cid, credits);

	chan = bt_l2cap_le_lookup_tx_cid(conn, cid);
	if (!chan) {
		BT_ERR("Unable to find channel of LE Credits packet");
		return;
	}

	ch = BT_L2CAP_LE_CHAN(chan);

	if (k_sem_count_get(&ch->tx.credits) + credits > UINT16_MAX) {
		BT_ERR("Credits overflow");
		bt_l2cap_chan_disconnect(chan);
		return;
	}

	l2cap_chan_tx_give_credits(ch, credits);

	BT_DBG("chan %p total credits %u", ch,
	       k_sem_count_get(&ch->tx.credits));

	l2cap_chan_le_send_resume(ch);
}
コード例 #6
0
void test_sema_reset(void)
{
	k_sem_init(&sema, SEM_INITIAL, SEM_LIMIT);
	k_sem_give(&sema);
	k_sem_reset(&sema);
	zassert_false(k_sem_count_get(&sema), NULL);
	/**TESTPOINT: sem take return -EBUSY*/
	zassert_equal(k_sem_take(&sema, K_NO_WAIT), -EBUSY, NULL);
	/**TESTPOINT: sem take return -EAGAIN*/
	zassert_equal(k_sem_take(&sema, TIMEOUT), -EAGAIN, NULL);
	k_sem_give(&sema);
	zassert_false(k_sem_take(&sema, K_FOREVER), NULL);
}