xref: /haiku/src/add-ons/kernel/network/protocols/l2cap/L2capEndpoint.cpp (revision 7cc7cada6a78b0f0a38da5dea553de57de73b899)
1b9b8d43cSOliver Ruiz Dorantes #include "L2capEndpoint.h"
2b9b8d43cSOliver Ruiz Dorantes 
3b9b8d43cSOliver Ruiz Dorantes #include <stdio.h>
4b9b8d43cSOliver Ruiz Dorantes #include <sys/stat.h>
5b9b8d43cSOliver Ruiz Dorantes #include <string.h>
6b9b8d43cSOliver Ruiz Dorantes 
7b9b8d43cSOliver Ruiz Dorantes #include "l2cap_address.h"
8b9b8d43cSOliver Ruiz Dorantes 
9b9b8d43cSOliver Ruiz Dorantes #include <bluetooth/L2CAP/btL2CAP.h>
10b9b8d43cSOliver Ruiz Dorantes #define BT_DEBUG_THIS_MODULE
11b9b8d43cSOliver Ruiz Dorantes #include <btDebug.h>
12b9b8d43cSOliver Ruiz Dorantes 
13b9b8d43cSOliver Ruiz Dorantes static inline bigtime_t
14b9b8d43cSOliver Ruiz Dorantes absolute_timeout(bigtime_t timeout)
15b9b8d43cSOliver Ruiz Dorantes {
16b9b8d43cSOliver Ruiz Dorantes 	if (timeout == 0 || timeout == B_INFINITE_TIMEOUT)
17b9b8d43cSOliver Ruiz Dorantes 		return timeout;
18b9b8d43cSOliver Ruiz Dorantes 
19b9b8d43cSOliver Ruiz Dorantes 	// TODO: Make overflow safe!
20b9b8d43cSOliver Ruiz Dorantes 	return timeout + system_time();
21b9b8d43cSOliver Ruiz Dorantes }
22b9b8d43cSOliver Ruiz Dorantes 
23b9b8d43cSOliver Ruiz Dorantes 
24b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::L2capEndpoint(net_socket* socket)
25b9b8d43cSOliver Ruiz Dorantes 	:
26b9b8d43cSOliver Ruiz Dorantes 	ProtocolSocket(socket),
27b9b8d43cSOliver Ruiz Dorantes 	fPeerEndpoint(NULL),
28b9b8d43cSOliver Ruiz Dorantes 	fAcceptSemaphore(-1)
29b9b8d43cSOliver Ruiz Dorantes {
30b9b8d43cSOliver Ruiz Dorantes 	debugf("[%ld] %p->L2capEndpoint::L2capEndpoint()\n", find_thread(NULL), this);
31b9b8d43cSOliver Ruiz Dorantes 
32*7cc7cadaSOliver Ruiz Dorantes 	/* Set MTU and flow control settings to defaults */
33*7cc7cadaSOliver Ruiz Dorantes 	configuration.imtu = L2CAP_MTU_DEFAULT;
34*7cc7cadaSOliver Ruiz Dorantes 	memcpy(&configuration.iflow, &default_qos , sizeof(l2cap_flow_t) );
35b9b8d43cSOliver Ruiz Dorantes 
36*7cc7cadaSOliver Ruiz Dorantes 	configuration.omtu = L2CAP_MTU_DEFAULT;
37*7cc7cadaSOliver Ruiz Dorantes 	memcpy(&configuration.oflow, &default_qos , sizeof(l2cap_flow_t) );
38*7cc7cadaSOliver Ruiz Dorantes 
39*7cc7cadaSOliver Ruiz Dorantes 	configuration.flush_timo = L2CAP_FLUSH_TIMO_DEFAULT;
40*7cc7cadaSOliver Ruiz Dorantes 	configuration.link_timo  = L2CAP_LINK_TIMO_DEFAULT;
41*7cc7cadaSOliver Ruiz Dorantes 
42*7cc7cadaSOliver Ruiz Dorantes 	configurationSet = false;
43*7cc7cadaSOliver Ruiz Dorantes 
44*7cc7cadaSOliver Ruiz Dorantes 	gStackModule->init_fifo(&fReceivingFifo, "l2cap recvfifo", L2CAP_MTU_DEFAULT);
45b9b8d43cSOliver Ruiz Dorantes }
46b9b8d43cSOliver Ruiz Dorantes 
47b9b8d43cSOliver Ruiz Dorantes 
48b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::~L2capEndpoint()
49b9b8d43cSOliver Ruiz Dorantes {
50b9b8d43cSOliver Ruiz Dorantes 	debugf("[%ld] %p->L2capEndpoint::~L2capEndpoint()\n", find_thread(NULL), this);
51b9b8d43cSOliver Ruiz Dorantes 
52b9b8d43cSOliver Ruiz Dorantes 
53b9b8d43cSOliver Ruiz Dorantes }
54b9b8d43cSOliver Ruiz Dorantes 
55b9b8d43cSOliver Ruiz Dorantes 
56b9b8d43cSOliver Ruiz Dorantes status_t
57b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Init()
58b9b8d43cSOliver Ruiz Dorantes {
59b9b8d43cSOliver Ruiz Dorantes 	debugf("[%ld] %p->L2capEndpoint::Init()\n", find_thread(NULL), this);
60b9b8d43cSOliver Ruiz Dorantes 
61b9b8d43cSOliver Ruiz Dorantes 	return(B_OK);
62b9b8d43cSOliver Ruiz Dorantes }
63b9b8d43cSOliver Ruiz Dorantes 
64b9b8d43cSOliver Ruiz Dorantes 
65b9b8d43cSOliver Ruiz Dorantes void
66b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Uninit()
67b9b8d43cSOliver Ruiz Dorantes {
68b9b8d43cSOliver Ruiz Dorantes 	debugf("[%ld] %p->L2capEndpoint::Uninit()\n", find_thread(NULL), this);
69b9b8d43cSOliver Ruiz Dorantes 
70b9b8d43cSOliver Ruiz Dorantes 
71b9b8d43cSOliver Ruiz Dorantes }
72b9b8d43cSOliver Ruiz Dorantes 
73b9b8d43cSOliver Ruiz Dorantes 
74b9b8d43cSOliver Ruiz Dorantes status_t
75b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Open()
76b9b8d43cSOliver Ruiz Dorantes {
77b9b8d43cSOliver Ruiz Dorantes 	debugf("[%ld] %p->L2capEndpoint::Open()\n", find_thread(NULL), this);
78b9b8d43cSOliver Ruiz Dorantes 
79b9b8d43cSOliver Ruiz Dorantes     status_t error = ProtocolSocket::Open();
80b9b8d43cSOliver Ruiz Dorantes 	if (error != B_OK)
81b9b8d43cSOliver Ruiz Dorantes 		return(error);
82b9b8d43cSOliver Ruiz Dorantes 
83b9b8d43cSOliver Ruiz Dorantes 
84b9b8d43cSOliver Ruiz Dorantes 
85b9b8d43cSOliver Ruiz Dorantes 	return(B_OK);
86b9b8d43cSOliver Ruiz Dorantes }
87b9b8d43cSOliver Ruiz Dorantes 
88b9b8d43cSOliver Ruiz Dorantes 
89b9b8d43cSOliver Ruiz Dorantes status_t
90b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Close()
91b9b8d43cSOliver Ruiz Dorantes {
92b9b8d43cSOliver Ruiz Dorantes 	debugf("[%ld] %p->L2capEndpoint::Close()\n", find_thread(NULL), this);
93b9b8d43cSOliver Ruiz Dorantes 
94b9b8d43cSOliver Ruiz Dorantes 	return(B_OK);
95b9b8d43cSOliver Ruiz Dorantes }
96b9b8d43cSOliver Ruiz Dorantes 
97b9b8d43cSOliver Ruiz Dorantes 
98b9b8d43cSOliver Ruiz Dorantes status_t
99b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Free()
100b9b8d43cSOliver Ruiz Dorantes {
101b9b8d43cSOliver Ruiz Dorantes 	debugf("[%ld] %p->L2capEndpoint::Free()\n", find_thread(NULL), this);
102b9b8d43cSOliver Ruiz Dorantes 
103b9b8d43cSOliver Ruiz Dorantes 	return(B_OK);
104b9b8d43cSOliver Ruiz Dorantes }
105b9b8d43cSOliver Ruiz Dorantes 
106b9b8d43cSOliver Ruiz Dorantes 
107b9b8d43cSOliver Ruiz Dorantes status_t
108b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Bind(const struct sockaddr *_address)
109b9b8d43cSOliver Ruiz Dorantes {
110b9b8d43cSOliver Ruiz Dorantes 	if (_address == NULL)
111b9b8d43cSOliver Ruiz Dorantes 		panic("null adrresss!");
112b9b8d43cSOliver Ruiz Dorantes 
113b9b8d43cSOliver Ruiz Dorantes 	if (_address->sa_family != AF_BLUETOOTH )
114b9b8d43cSOliver Ruiz Dorantes 		return(EAFNOSUPPORT);
115b9b8d43cSOliver Ruiz Dorantes 
116b9b8d43cSOliver Ruiz Dorantes 	// TODO: Check socladdr_l2cap size
117b9b8d43cSOliver Ruiz Dorantes 
118b9b8d43cSOliver Ruiz Dorantes 	// TODO: Check if that PSM is already bound
119b9b8d43cSOliver Ruiz Dorantes 	// return EADDRINUSE;
120b9b8d43cSOliver Ruiz Dorantes 
121b9b8d43cSOliver Ruiz Dorantes 
122b9b8d43cSOliver Ruiz Dorantes 	// TODO: Check if the PSM is valid, check assigned numbers document for valid
123b9b8d43cSOliver Ruiz Dorantes 	// psm available to applications.
124b9b8d43cSOliver Ruiz Dorantes 	// All PSM values shall be ODD, that is, the least significant bit of the least
125b9b8d43cSOliver Ruiz Dorantes 	// significant octet must be ’1’. Also, all PSM values shall have the least
126b9b8d43cSOliver Ruiz Dorantes 	// significant bit of the most significant octet equal to ’0’. This allows the
127b9b8d43cSOliver Ruiz Dorantes 	// PSM field to be extended beyond 16 bits.
128b9b8d43cSOliver Ruiz Dorantes 	if ((((struct sockaddr_l2cap*)_address)->l2cap_psm & 1) == 0)
129b9b8d43cSOliver Ruiz Dorantes 		return B_ERROR;
130b9b8d43cSOliver Ruiz Dorantes 
131b9b8d43cSOliver Ruiz Dorantes 	flowf("\n")
132b9b8d43cSOliver Ruiz Dorantes 	memcpy(&socket->address, _address, sizeof(struct sockaddr_l2cap));
133b9b8d43cSOliver Ruiz Dorantes 	socket->address.ss_len = sizeof(struct sockaddr_l2cap);
134b9b8d43cSOliver Ruiz Dorantes 
135b9b8d43cSOliver Ruiz Dorantes 	fState = LISTEN;
136b9b8d43cSOliver Ruiz Dorantes 
137b9b8d43cSOliver Ruiz Dorantes 	return B_OK;
138b9b8d43cSOliver Ruiz Dorantes 
139b9b8d43cSOliver Ruiz Dorantes }
140b9b8d43cSOliver Ruiz Dorantes 
141b9b8d43cSOliver Ruiz Dorantes 
142b9b8d43cSOliver Ruiz Dorantes status_t
143b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Unbind()
144b9b8d43cSOliver Ruiz Dorantes {
145b9b8d43cSOliver Ruiz Dorantes 	debugf("[%ld] %p->L2capEndpoint::Unbind()\n", find_thread(NULL), this);
146b9b8d43cSOliver Ruiz Dorantes 
147b9b8d43cSOliver Ruiz Dorantes 	return(B_OK);
148b9b8d43cSOliver Ruiz Dorantes }
149b9b8d43cSOliver Ruiz Dorantes 
150b9b8d43cSOliver Ruiz Dorantes 
151b9b8d43cSOliver Ruiz Dorantes status_t
152b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Listen(int backlog)
153b9b8d43cSOliver Ruiz Dorantes {
154b9b8d43cSOliver Ruiz Dorantes 	if (fState != CLOSED)
155b9b8d43cSOliver Ruiz Dorantes 		return B_BAD_VALUE;
156b9b8d43cSOliver Ruiz Dorantes 
157b9b8d43cSOliver Ruiz Dorantes 	fAcceptSemaphore = create_sem(0, "tcp accept");
158b9b8d43cSOliver Ruiz Dorantes 	if (fAcceptSemaphore < B_OK)
159b9b8d43cSOliver Ruiz Dorantes 		return ENOBUFS;
160b9b8d43cSOliver Ruiz Dorantes 
161b9b8d43cSOliver Ruiz Dorantes 	fState = LISTEN;
162b9b8d43cSOliver Ruiz Dorantes 
163b9b8d43cSOliver Ruiz Dorantes 	return B_OK;
164b9b8d43cSOliver Ruiz Dorantes }
165b9b8d43cSOliver Ruiz Dorantes 
166b9b8d43cSOliver Ruiz Dorantes 
167b9b8d43cSOliver Ruiz Dorantes status_t
168b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Connect(const struct sockaddr *_address)
169b9b8d43cSOliver Ruiz Dorantes {
170b9b8d43cSOliver Ruiz Dorantes 	if (_address->sa_family != AF_BLUETOOTH)
171b9b8d43cSOliver Ruiz Dorantes 		return(EAFNOSUPPORT);
172b9b8d43cSOliver Ruiz Dorantes 
173*7cc7cadaSOliver Ruiz Dorantes 	debugf("[%ld] %p->L2capEndpoint::Connect(\"%s\")\n", find_thread(NULL), this,
174b9b8d43cSOliver Ruiz Dorantes 		ConstSocketAddress(&gL2cap4AddressModule, _address).AsString().Data());
175b9b8d43cSOliver Ruiz Dorantes 
176b9b8d43cSOliver Ruiz Dorantes 	const sockaddr_l2cap* address = (const sockaddr_l2cap*)_address;
177b9b8d43cSOliver Ruiz Dorantes 
178b9b8d43cSOliver Ruiz Dorantes 	/**/
179b9b8d43cSOliver Ruiz Dorantes 	TOUCH(address);
180b9b8d43cSOliver Ruiz Dorantes 
181b9b8d43cSOliver Ruiz Dorantes 	return B_OK;
182b9b8d43cSOliver Ruiz Dorantes }
183b9b8d43cSOliver Ruiz Dorantes 
184b9b8d43cSOliver Ruiz Dorantes 
185b9b8d43cSOliver Ruiz Dorantes status_t
186b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Accept(net_socket **_acceptedSocket)
187b9b8d43cSOliver Ruiz Dorantes {
188*7cc7cadaSOliver Ruiz Dorantes 	debugf("[%ld] %p->L2capEndpoint::Accept()\n", find_thread(NULL), this);
189b9b8d43cSOliver Ruiz Dorantes 
190b9b8d43cSOliver Ruiz Dorantes 	bigtime_t timeout = absolute_timeout(socket->receive.timeout);
191b9b8d43cSOliver Ruiz Dorantes 
192b9b8d43cSOliver Ruiz Dorantes 	TOUCH(timeout);
193b9b8d43cSOliver Ruiz Dorantes 	return B_OK;
194b9b8d43cSOliver Ruiz Dorantes }
195b9b8d43cSOliver Ruiz Dorantes 
196b9b8d43cSOliver Ruiz Dorantes 
197b9b8d43cSOliver Ruiz Dorantes ssize_t
198b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Send(const iovec *vecs, size_t vecCount,
199b9b8d43cSOliver Ruiz Dorantes 	ancillary_data_container *ancillaryData)
200b9b8d43cSOliver Ruiz Dorantes {
201*7cc7cadaSOliver Ruiz Dorantes 	debugf("[%ld] %p->L2capEndpoint::Send(%p, %ld, %p)\n", find_thread(NULL),
202b9b8d43cSOliver Ruiz Dorantes 		this, vecs, vecCount, ancillaryData);
203b9b8d43cSOliver Ruiz Dorantes 
204b9b8d43cSOliver Ruiz Dorantes 	return B_OK;
205b9b8d43cSOliver Ruiz Dorantes }
206b9b8d43cSOliver Ruiz Dorantes 
207b9b8d43cSOliver Ruiz Dorantes 
208b9b8d43cSOliver Ruiz Dorantes ssize_t
209b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Receive(const iovec *vecs, size_t vecCount,
210b9b8d43cSOliver Ruiz Dorantes 	ancillary_data_container **_ancillaryData, struct sockaddr *_address,
211b9b8d43cSOliver Ruiz Dorantes 	socklen_t *_addressLength)
212b9b8d43cSOliver Ruiz Dorantes {
213*7cc7cadaSOliver Ruiz Dorantes 	debugf("[%ld] %p->L2capEndpoint::Receive(%p, %ld)\n", find_thread(NULL),
214b9b8d43cSOliver Ruiz Dorantes 		this, vecs, vecCount);
215b9b8d43cSOliver Ruiz Dorantes 
216b9b8d43cSOliver Ruiz Dorantes 
217b9b8d43cSOliver Ruiz Dorantes 	return B_OK;
218b9b8d43cSOliver Ruiz Dorantes }
219b9b8d43cSOliver Ruiz Dorantes 
220b9b8d43cSOliver Ruiz Dorantes 
221b9b8d43cSOliver Ruiz Dorantes ssize_t
222*7cc7cadaSOliver Ruiz Dorantes L2capEndpoint::ReadData(size_t numBytes, uint32 flags, net_buffer** _buffer)
223*7cc7cadaSOliver Ruiz Dorantes {
224*7cc7cadaSOliver Ruiz Dorantes 
225*7cc7cadaSOliver Ruiz Dorantes 	return gStackModule->fifo_dequeue_buffer(&fReceivingFifo, flags, B_INFINITE_TIMEOUT, _buffer);
226*7cc7cadaSOliver Ruiz Dorantes 
227*7cc7cadaSOliver Ruiz Dorantes }
228*7cc7cadaSOliver Ruiz Dorantes 
229*7cc7cadaSOliver Ruiz Dorantes 
230*7cc7cadaSOliver Ruiz Dorantes ssize_t
231b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Sendable()
232b9b8d43cSOliver Ruiz Dorantes {
233*7cc7cadaSOliver Ruiz Dorantes 	debugf("[%ld] %p->L2capEndpoint::Sendable()\n", find_thread(NULL), this);
234b9b8d43cSOliver Ruiz Dorantes 
235b9b8d43cSOliver Ruiz Dorantes 
236b9b8d43cSOliver Ruiz Dorantes 	return 0;
237b9b8d43cSOliver Ruiz Dorantes }
238b9b8d43cSOliver Ruiz Dorantes 
239b9b8d43cSOliver Ruiz Dorantes 
240b9b8d43cSOliver Ruiz Dorantes ssize_t
241b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Receivable()
242b9b8d43cSOliver Ruiz Dorantes {
243*7cc7cadaSOliver Ruiz Dorantes 	debugf("[%ld] %p->L2capEndpoint::Receivable()\n", find_thread(NULL), this);
244b9b8d43cSOliver Ruiz Dorantes 
245b9b8d43cSOliver Ruiz Dorantes 	return 0;
246b9b8d43cSOliver Ruiz Dorantes }
247b9b8d43cSOliver Ruiz Dorantes 
248b9b8d43cSOliver Ruiz Dorantes 
249b9b8d43cSOliver Ruiz Dorantes L2capEndpoint*
250b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::ForPsm(uint16 psm)
251b9b8d43cSOliver Ruiz Dorantes {
252b9b8d43cSOliver Ruiz Dorantes 
253b9b8d43cSOliver Ruiz Dorantes 	L2capEndpoint*	endpoint;
254b9b8d43cSOliver Ruiz Dorantes 
255b9b8d43cSOliver Ruiz Dorantes 	DoublyLinkedList<L2capEndpoint>::Iterator iterator = EndpointList.GetIterator();
256b9b8d43cSOliver Ruiz Dorantes 
257b9b8d43cSOliver Ruiz Dorantes 	while (iterator.HasNext()) {
258b9b8d43cSOliver Ruiz Dorantes 
259b9b8d43cSOliver Ruiz Dorantes 		endpoint = iterator.Next();
260b9b8d43cSOliver Ruiz Dorantes 		if (((struct sockaddr_l2cap*)&endpoint->socket->address)->l2cap_psm == psm &&
261b9b8d43cSOliver Ruiz Dorantes 			endpoint->fState == LISTEN) {
262*7cc7cadaSOliver Ruiz Dorantes 			// TODO endpoint ocupied, lock it! define a channel for it
263b9b8d43cSOliver Ruiz Dorantes 			return endpoint;
264b9b8d43cSOliver Ruiz Dorantes 		}
265b9b8d43cSOliver Ruiz Dorantes 	}
266b9b8d43cSOliver Ruiz Dorantes 
267b9b8d43cSOliver Ruiz Dorantes 	return NULL;
268b9b8d43cSOliver Ruiz Dorantes }
269*7cc7cadaSOliver Ruiz Dorantes 
270*7cc7cadaSOliver Ruiz Dorantes 
271*7cc7cadaSOliver Ruiz Dorantes void
272*7cc7cadaSOliver Ruiz Dorantes L2capEndpoint::BindToChannel(L2capChannel* channel)
273*7cc7cadaSOliver Ruiz Dorantes {
274*7cc7cadaSOliver Ruiz Dorantes 
275*7cc7cadaSOliver Ruiz Dorantes 	this->channel = channel;
276*7cc7cadaSOliver Ruiz Dorantes 	channel->configuration = &configuration;
277*7cc7cadaSOliver Ruiz Dorantes 
278*7cc7cadaSOliver Ruiz Dorantes }
279