1/*
2 * Copyright 2008 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
5#include <string.h>
6
7#include <l2cap.h>
8#include <bluetooth/HCI/btHCI_command.h>
9
10#include <btDebug.h>
11
12#include "ChannelInterface.h"
13#include "FrameInterface.h"
14
15
16L2capChannel*
17ChannelBySourceID(HciConnection *conn, uint16 scid)
18{
19	L2capChannel*	channel = NULL;
20
21	DoublyLinkedList<L2capChannel>::Iterator iterator = conn->ChannelList.GetIterator();
22
23	while (iterator.HasNext()) {
24		channel = iterator.Next();
25		if (channel->scid == scid)
26			return channel;
27	}
28
29	return NULL;
30}
31
32
33uint16
34ChannelAllocateCid(HciConnection* conn)
35{
36	uint16 cid = conn->lastCid;
37	TRACE("%s: Starting search cid %d\n", __func__, cid);
38	do {
39		cid = (cid == L2CAP_LAST_CID) ? L2CAP_FIRST_CID : cid + 1;
40
41		if (ChannelBySourceID(conn, cid) == NULL) {
42			conn->lastCid = cid;
43			return cid;
44		}
45
46	} while (cid != conn->lastCid);
47
48	return L2CAP_NULL_CID;
49}
50
51
52uint16
53ChannelAllocateIdent(HciConnection* conn)
54{
55	uint8 ident = conn->lastIdent + 1;
56
57	if (ident < L2CAP_FIRST_IDENT)
58		ident = L2CAP_FIRST_IDENT;
59
60	while (ident != conn->lastIdent) {
61		if (SignalByIdent(conn, ident) == NULL) {
62			conn->lastIdent = ident;
63
64			return ident;
65		}
66
67		ident++;
68		if (ident < L2CAP_FIRST_IDENT)
69			ident = L2CAP_FIRST_IDENT;
70	}
71
72	return L2CAP_NULL_IDENT;
73}
74
75
76L2capChannel*
77AddChannel(HciConnection* conn, uint16 psm)
78{
79	L2capChannel* channel = new (std::nothrow) L2capChannel;
80
81	if (channel == NULL) {
82		ERROR("%s: Unable to allocate memory for channel!\n", __func__);
83		return NULL;
84	}
85
86	/* Get a new Source CID */
87	channel->scid = ChannelAllocateCid(conn);
88
89	if (channel->scid != L2CAP_NULL_CID) {
90		/* Initialize channel */
91		channel->psm = psm;
92		channel->conn = conn;
93		channel->state = L2CAP_CHAN_CLOSED;
94		channel->cfgState = 0;
95		channel->endpoint = NULL;
96
97		// the last assigned CID should be the last in the list
98		// Think if keeping an ordered list will improve the search method
99		// as it is called in every reception
100		conn->ChannelList.Add(channel);
101		//conn->num_channels++;
102
103		// Any constance of the new channel created ...? ng_l2cap_con_ref(con);
104
105	} else {
106		ERROR("%s: no CID available\n", __func__);
107		delete channel;
108		channel = NULL;
109	}
110
111	return channel;
112}
113
114
115void
116RemoveChannel(HciConnection* conn, uint16 scid)
117{
118	//TODO make it safer
119	conn->ChannelList.Remove(ChannelBySourceID(conn, scid));
120}
121