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