xref: /haiku/src/add-ons/kernel/network/protocols/l2cap/L2capEndpoint.cpp (revision a58b3b32350051afd1b2d40541550ba9272cd96e)
1a94c1dc5SOliver Ruiz Dorantes /*
2*a58b3b32SOliver Ruiz Dorantes  * Copyright 2008 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
3*a58b3b32SOliver Ruiz Dorantes  * All rights reserved. Distributed under the terms of the MIT License.
4a94c1dc5SOliver Ruiz Dorantes  */
5b9b8d43cSOliver Ruiz Dorantes #include "L2capEndpoint.h"
6a94c1dc5SOliver Ruiz Dorantes #include "l2cap_address.h"
7b9b8d43cSOliver Ruiz Dorantes 
8b9b8d43cSOliver Ruiz Dorantes #include <stdio.h>
9b9b8d43cSOliver Ruiz Dorantes #include <string.h>
10a94c1dc5SOliver Ruiz Dorantes #include <sys/stat.h>
11b9b8d43cSOliver Ruiz Dorantes 
12b9b8d43cSOliver Ruiz Dorantes 
13b9b8d43cSOliver Ruiz Dorantes #include <bluetooth/L2CAP/btL2CAP.h>
14b9b8d43cSOliver Ruiz Dorantes #define BT_DEBUG_THIS_MODULE
15*a58b3b32SOliver Ruiz Dorantes #define MODULE_NAME "l2cap"
16*a58b3b32SOliver Ruiz Dorantes #define SUBMODULE_NAME "Endpoint"
17*a58b3b32SOliver Ruiz Dorantes #define SUBMODULE_COLOR 32
18b9b8d43cSOliver Ruiz Dorantes #include <btDebug.h>
19b9b8d43cSOliver Ruiz Dorantes 
20a94c1dc5SOliver Ruiz Dorantes 
21b9b8d43cSOliver Ruiz Dorantes static inline bigtime_t
22b9b8d43cSOliver Ruiz Dorantes absolute_timeout(bigtime_t timeout)
23b9b8d43cSOliver Ruiz Dorantes {
24b9b8d43cSOliver Ruiz Dorantes 	if (timeout == 0 || timeout == B_INFINITE_TIMEOUT)
25b9b8d43cSOliver Ruiz Dorantes 		return timeout;
26b9b8d43cSOliver Ruiz Dorantes 
27b9b8d43cSOliver Ruiz Dorantes 	// TODO: Make overflow safe!
28b9b8d43cSOliver Ruiz Dorantes 	return timeout + system_time();
29b9b8d43cSOliver Ruiz Dorantes }
30b9b8d43cSOliver Ruiz Dorantes 
31b9b8d43cSOliver Ruiz Dorantes 
32b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::L2capEndpoint(net_socket* socket)
33b9b8d43cSOliver Ruiz Dorantes 	:
34b9b8d43cSOliver Ruiz Dorantes 	ProtocolSocket(socket),
35*a58b3b32SOliver Ruiz Dorantes 	fConfigurationSet(false),
36b9b8d43cSOliver Ruiz Dorantes 	fPeerEndpoint(NULL),
37*a58b3b32SOliver Ruiz Dorantes 	fAcceptSemaphore(-1),
38*a58b3b32SOliver Ruiz Dorantes 	fChannel(NULL)
39b9b8d43cSOliver Ruiz Dorantes {
40*a58b3b32SOliver Ruiz Dorantes 	debugf("[%ld] %p\n", find_thread(NULL), this);
41b9b8d43cSOliver Ruiz Dorantes 
427cc7cadaSOliver Ruiz Dorantes 	/* Set MTU and flow control settings to defaults */
437cc7cadaSOliver Ruiz Dorantes 	configuration.imtu = L2CAP_MTU_DEFAULT;
447cc7cadaSOliver Ruiz Dorantes 	memcpy(&configuration.iflow, &default_qos , sizeof(l2cap_flow_t) );
45b9b8d43cSOliver Ruiz Dorantes 
467cc7cadaSOliver Ruiz Dorantes 	configuration.omtu = L2CAP_MTU_DEFAULT;
477cc7cadaSOliver Ruiz Dorantes 	memcpy(&configuration.oflow, &default_qos , sizeof(l2cap_flow_t) );
487cc7cadaSOliver Ruiz Dorantes 
497cc7cadaSOliver Ruiz Dorantes 	configuration.flush_timo = L2CAP_FLUSH_TIMO_DEFAULT;
507cc7cadaSOliver Ruiz Dorantes 	configuration.link_timo  = L2CAP_LINK_TIMO_DEFAULT;
517cc7cadaSOliver Ruiz Dorantes 
527cc7cadaSOliver Ruiz Dorantes 	gStackModule->init_fifo(&fReceivingFifo, "l2cap recvfifo", L2CAP_MTU_DEFAULT);
53b9b8d43cSOliver Ruiz Dorantes }
54b9b8d43cSOliver Ruiz Dorantes 
55b9b8d43cSOliver Ruiz Dorantes 
56b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::~L2capEndpoint()
57b9b8d43cSOliver Ruiz Dorantes {
58*a58b3b32SOliver Ruiz Dorantes 	debugf("[%ld] %p\n", find_thread(NULL), this);
59b9b8d43cSOliver Ruiz Dorantes 
60b9b8d43cSOliver Ruiz Dorantes }
61b9b8d43cSOliver Ruiz Dorantes 
62b9b8d43cSOliver Ruiz Dorantes 
63b9b8d43cSOliver Ruiz Dorantes status_t
64b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Init()
65b9b8d43cSOliver Ruiz Dorantes {
66*a58b3b32SOliver Ruiz Dorantes 	debugf("[%ld] %p\n", find_thread(NULL), this);
67b9b8d43cSOliver Ruiz Dorantes 
68a94c1dc5SOliver Ruiz Dorantes 	return B_OK;
69b9b8d43cSOliver Ruiz Dorantes }
70b9b8d43cSOliver Ruiz Dorantes 
71b9b8d43cSOliver Ruiz Dorantes 
72b9b8d43cSOliver Ruiz Dorantes void
73b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Uninit()
74b9b8d43cSOliver Ruiz Dorantes {
75*a58b3b32SOliver Ruiz Dorantes 	debugf("[%ld] %p\n", find_thread(NULL), this);
76b9b8d43cSOliver Ruiz Dorantes 
77b9b8d43cSOliver Ruiz Dorantes }
78b9b8d43cSOliver Ruiz Dorantes 
79b9b8d43cSOliver Ruiz Dorantes 
80b9b8d43cSOliver Ruiz Dorantes status_t
81b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Open()
82b9b8d43cSOliver Ruiz Dorantes {
83*a58b3b32SOliver Ruiz Dorantes 	debugf("[%ld] %p\n", find_thread(NULL), this);
84b9b8d43cSOliver Ruiz Dorantes 
85b9b8d43cSOliver Ruiz Dorantes 	status_t error = ProtocolSocket::Open();
86b9b8d43cSOliver Ruiz Dorantes 	if (error != B_OK)
87a94c1dc5SOliver Ruiz Dorantes 		return error;
88b9b8d43cSOliver Ruiz Dorantes 
89a94c1dc5SOliver Ruiz Dorantes 	return B_OK;
90b9b8d43cSOliver Ruiz Dorantes }
91b9b8d43cSOliver Ruiz Dorantes 
92b9b8d43cSOliver Ruiz Dorantes 
93b9b8d43cSOliver Ruiz Dorantes status_t
94b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Close()
95b9b8d43cSOliver Ruiz Dorantes {
96*a58b3b32SOliver Ruiz Dorantes 	debugf("[%ld] %p\n", find_thread(NULL), this);
97b9b8d43cSOliver Ruiz Dorantes 
98a94c1dc5SOliver Ruiz Dorantes 	return B_OK;
99b9b8d43cSOliver Ruiz Dorantes }
100b9b8d43cSOliver Ruiz Dorantes 
101b9b8d43cSOliver Ruiz Dorantes 
102b9b8d43cSOliver Ruiz Dorantes status_t
103b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Free()
104b9b8d43cSOliver Ruiz Dorantes {
105*a58b3b32SOliver Ruiz Dorantes 	debugf("[%ld] %p\n", find_thread(NULL), this);
106b9b8d43cSOliver Ruiz Dorantes 
107a94c1dc5SOliver Ruiz Dorantes 	return B_OK;
108b9b8d43cSOliver Ruiz Dorantes }
109b9b8d43cSOliver Ruiz Dorantes 
110b9b8d43cSOliver Ruiz Dorantes 
111b9b8d43cSOliver Ruiz Dorantes status_t
112b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Bind(const struct sockaddr *_address)
113b9b8d43cSOliver Ruiz Dorantes {
114b9b8d43cSOliver Ruiz Dorantes 	if (_address == NULL)
115b9b8d43cSOliver Ruiz Dorantes 		panic("null adrresss!");
116b9b8d43cSOliver Ruiz Dorantes 
117b9b8d43cSOliver Ruiz Dorantes 	if (_address->sa_family != AF_BLUETOOTH )
118a94c1dc5SOliver Ruiz Dorantes 		return EAFNOSUPPORT;
119b9b8d43cSOliver Ruiz Dorantes 
120b9b8d43cSOliver Ruiz Dorantes 	// TODO: Check socladdr_l2cap size
121b9b8d43cSOliver Ruiz Dorantes 
122b9b8d43cSOliver Ruiz Dorantes 	// TODO: Check if that PSM is already bound
123b9b8d43cSOliver Ruiz Dorantes 	// return EADDRINUSE;
124b9b8d43cSOliver Ruiz Dorantes 
125b9b8d43cSOliver Ruiz Dorantes 
126b9b8d43cSOliver Ruiz Dorantes 	// TODO: Check if the PSM is valid, check assigned numbers document for valid
127b9b8d43cSOliver Ruiz Dorantes 	// psm available to applications.
128b9b8d43cSOliver Ruiz Dorantes 	// All PSM values shall be ODD, that is, the least significant bit of the least
129b9b8d43cSOliver Ruiz Dorantes 	// significant octet must be ’1’. Also, all PSM values shall have the least
130b9b8d43cSOliver Ruiz Dorantes 	// significant bit of the most significant octet equal to ’0’. This allows the
131b9b8d43cSOliver Ruiz Dorantes 	// PSM field to be extended beyond 16 bits.
132b9b8d43cSOliver Ruiz Dorantes 	if ((((struct sockaddr_l2cap*)_address)->l2cap_psm & 1) == 0)
133b9b8d43cSOliver Ruiz Dorantes 		return B_ERROR;
134b9b8d43cSOliver Ruiz Dorantes 
135b9b8d43cSOliver Ruiz Dorantes 	flowf("\n")
136b9b8d43cSOliver Ruiz Dorantes 	memcpy(&socket->address, _address, sizeof(struct sockaddr_l2cap));
137b9b8d43cSOliver Ruiz Dorantes 	socket->address.ss_len = sizeof(struct sockaddr_l2cap);
138b9b8d43cSOliver Ruiz Dorantes 
139*a58b3b32SOliver Ruiz Dorantes 	fState = CLOSED;
140b9b8d43cSOliver Ruiz Dorantes 
141b9b8d43cSOliver Ruiz Dorantes 	return B_OK;
142b9b8d43cSOliver Ruiz Dorantes 
143b9b8d43cSOliver Ruiz Dorantes }
144b9b8d43cSOliver Ruiz Dorantes 
145b9b8d43cSOliver Ruiz Dorantes 
146b9b8d43cSOliver Ruiz Dorantes status_t
147b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Unbind()
148b9b8d43cSOliver Ruiz Dorantes {
149*a58b3b32SOliver Ruiz Dorantes 	debugf("[%ld] %p\n", find_thread(NULL), this);
150b9b8d43cSOliver Ruiz Dorantes 
151a94c1dc5SOliver Ruiz Dorantes 	return B_OK;
152b9b8d43cSOliver Ruiz Dorantes }
153b9b8d43cSOliver Ruiz Dorantes 
154b9b8d43cSOliver Ruiz Dorantes 
155b9b8d43cSOliver Ruiz Dorantes status_t
156b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Listen(int backlog)
157b9b8d43cSOliver Ruiz Dorantes {
158*a58b3b32SOliver Ruiz Dorantes 	debugf("[%ld] %p\n", find_thread(NULL), this);
159b9b8d43cSOliver Ruiz Dorantes 
160*a58b3b32SOliver Ruiz Dorantes 	if (fState != CLOSED) {
161*a58b3b32SOliver Ruiz Dorantes 		flowf("Invalid State\n");
162*a58b3b32SOliver Ruiz Dorantes 		return B_BAD_VALUE;
163*a58b3b32SOliver Ruiz Dorantes 	}
164*a58b3b32SOliver Ruiz Dorantes 
165*a58b3b32SOliver Ruiz Dorantes 	fAcceptSemaphore = create_sem(0, "l2cap serv accept");
166*a58b3b32SOliver Ruiz Dorantes 	if (fAcceptSemaphore < B_OK) {
167*a58b3b32SOliver Ruiz Dorantes 		flowf("Semaphore could not be created\n");
168b9b8d43cSOliver Ruiz Dorantes 		return ENOBUFS;
169*a58b3b32SOliver Ruiz Dorantes 	}
170*a58b3b32SOliver Ruiz Dorantes 
171*a58b3b32SOliver Ruiz Dorantes 	gSocketModule->set_max_backlog(socket, backlog);
172b9b8d43cSOliver Ruiz Dorantes 
173b9b8d43cSOliver Ruiz Dorantes 	fState = LISTEN;
174b9b8d43cSOliver Ruiz Dorantes 
175b9b8d43cSOliver Ruiz Dorantes 	return B_OK;
176b9b8d43cSOliver Ruiz Dorantes }
177b9b8d43cSOliver Ruiz Dorantes 
178b9b8d43cSOliver Ruiz Dorantes 
179b9b8d43cSOliver Ruiz Dorantes status_t
180b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Connect(const struct sockaddr *_address)
181b9b8d43cSOliver Ruiz Dorantes {
182b9b8d43cSOliver Ruiz Dorantes 	if (_address->sa_family != AF_BLUETOOTH)
183a94c1dc5SOliver Ruiz Dorantes 		return EAFNOSUPPORT;
184b9b8d43cSOliver Ruiz Dorantes 
1857cc7cadaSOliver Ruiz Dorantes 	debugf("[%ld] %p->L2capEndpoint::Connect(\"%s\")\n", find_thread(NULL), this,
186b9b8d43cSOliver Ruiz Dorantes 		ConstSocketAddress(&gL2cap4AddressModule, _address).AsString().Data());
187b9b8d43cSOliver Ruiz Dorantes 
188b9b8d43cSOliver Ruiz Dorantes 	const sockaddr_l2cap* address = (const sockaddr_l2cap*)_address;
189b9b8d43cSOliver Ruiz Dorantes 
190b9b8d43cSOliver Ruiz Dorantes 	/**/
191b9b8d43cSOliver Ruiz Dorantes 	TOUCH(address);
192b9b8d43cSOliver Ruiz Dorantes 
193b9b8d43cSOliver Ruiz Dorantes 	return B_OK;
194b9b8d43cSOliver Ruiz Dorantes }
195b9b8d43cSOliver Ruiz Dorantes 
196b9b8d43cSOliver Ruiz Dorantes 
197b9b8d43cSOliver Ruiz Dorantes status_t
198b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Accept(net_socket **_acceptedSocket)
199b9b8d43cSOliver Ruiz Dorantes {
200*a58b3b32SOliver Ruiz Dorantes 	debugf("[%ld]\n", find_thread(NULL));
201b9b8d43cSOliver Ruiz Dorantes 
202*a58b3b32SOliver Ruiz Dorantes 	// MutexLocker locker(fLock);
203b9b8d43cSOliver Ruiz Dorantes 
204*a58b3b32SOliver Ruiz Dorantes 	status_t status;
205*a58b3b32SOliver Ruiz Dorantes 	bigtime_t timeout = absolute_timeout(300*1000*1000);
206*a58b3b32SOliver Ruiz Dorantes 
207*a58b3b32SOliver Ruiz Dorantes 	do {
208*a58b3b32SOliver Ruiz Dorantes 		// locker.Unlock();
209*a58b3b32SOliver Ruiz Dorantes 
210*a58b3b32SOliver Ruiz Dorantes 		status = acquire_sem_etc(fAcceptSemaphore, 1, B_ABSOLUTE_TIMEOUT
211*a58b3b32SOliver Ruiz Dorantes 			| B_CAN_INTERRUPT, timeout);
212*a58b3b32SOliver Ruiz Dorantes 
213*a58b3b32SOliver Ruiz Dorantes 		if (status != B_OK)
214*a58b3b32SOliver Ruiz Dorantes 			return status;
215*a58b3b32SOliver Ruiz Dorantes 
216*a58b3b32SOliver Ruiz Dorantes 		// locker.Lock();
217*a58b3b32SOliver Ruiz Dorantes 		status = gSocketModule->dequeue_connected(socket, _acceptedSocket);
218*a58b3b32SOliver Ruiz Dorantes 
219*a58b3b32SOliver Ruiz Dorantes 		if (status != B_OK)
220*a58b3b32SOliver Ruiz Dorantes 			debugf("Could not dequeue socket %s\n", strerror(status));
221*a58b3b32SOliver Ruiz Dorantes 
222*a58b3b32SOliver Ruiz Dorantes 		//TODO: Establish relationship with the negotiated channel by the parent endpoint
223*a58b3b32SOliver Ruiz Dorantes 		((L2capEndpoint*)socket)->fChannel = fChannel;
224*a58b3b32SOliver Ruiz Dorantes 
225*a58b3b32SOliver Ruiz Dorantes 		// point parent
226*a58b3b32SOliver Ruiz Dorantes 		((L2capEndpoint*)socket)->fPeerEndpoint = this;
227*a58b3b32SOliver Ruiz Dorantes 
228*a58b3b32SOliver Ruiz Dorantes 		// unassign any channel for the parent endpoint
229*a58b3b32SOliver Ruiz Dorantes 		fChannel = NULL;
230*a58b3b32SOliver Ruiz Dorantes 
231*a58b3b32SOliver Ruiz Dorantes 		fState = LISTEN;
232*a58b3b32SOliver Ruiz Dorantes 
233*a58b3b32SOliver Ruiz Dorantes 	} while (status != B_OK);
234*a58b3b32SOliver Ruiz Dorantes 
235*a58b3b32SOliver Ruiz Dorantes 	return status;
236b9b8d43cSOliver Ruiz Dorantes }
237b9b8d43cSOliver Ruiz Dorantes 
238b9b8d43cSOliver Ruiz Dorantes 
239b9b8d43cSOliver Ruiz Dorantes ssize_t
240b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Send(const iovec *vecs, size_t vecCount,
241b9b8d43cSOliver Ruiz Dorantes 	ancillary_data_container *ancillaryData)
242b9b8d43cSOliver Ruiz Dorantes {
243*a58b3b32SOliver Ruiz Dorantes 	debugf("[%ld] %p Send(%p, %ld, %p)\n", find_thread(NULL),
244b9b8d43cSOliver Ruiz Dorantes 		this, vecs, vecCount, ancillaryData);
245b9b8d43cSOliver Ruiz Dorantes 
246b9b8d43cSOliver Ruiz Dorantes 	return B_OK;
247b9b8d43cSOliver Ruiz Dorantes }
248b9b8d43cSOliver Ruiz Dorantes 
249b9b8d43cSOliver Ruiz Dorantes 
250b9b8d43cSOliver Ruiz Dorantes ssize_t
251b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Receive(const iovec *vecs, size_t vecCount,
252b9b8d43cSOliver Ruiz Dorantes 	ancillary_data_container **_ancillaryData, struct sockaddr *_address,
253b9b8d43cSOliver Ruiz Dorantes 	socklen_t *_addressLength)
254b9b8d43cSOliver Ruiz Dorantes {
255*a58b3b32SOliver Ruiz Dorantes 	debugf("[%ld] %p Receive(%p, %ld)\n", find_thread(NULL),
256b9b8d43cSOliver Ruiz Dorantes 		this, vecs, vecCount);
257b9b8d43cSOliver Ruiz Dorantes 
258b9b8d43cSOliver Ruiz Dorantes 
259b9b8d43cSOliver Ruiz Dorantes 	return B_OK;
260b9b8d43cSOliver Ruiz Dorantes }
261b9b8d43cSOliver Ruiz Dorantes 
262b9b8d43cSOliver Ruiz Dorantes 
263b9b8d43cSOliver Ruiz Dorantes ssize_t
2647cc7cadaSOliver Ruiz Dorantes L2capEndpoint::ReadData(size_t numBytes, uint32 flags, net_buffer** _buffer)
2657cc7cadaSOliver Ruiz Dorantes {
2667cc7cadaSOliver Ruiz Dorantes 
267*a58b3b32SOliver Ruiz Dorantes 	return gStackModule->fifo_dequeue_buffer(&fReceivingFifo, flags,
268*a58b3b32SOliver Ruiz Dorantes 		B_INFINITE_TIMEOUT, _buffer);
2697cc7cadaSOliver Ruiz Dorantes }
2707cc7cadaSOliver Ruiz Dorantes 
2717cc7cadaSOliver Ruiz Dorantes 
2727cc7cadaSOliver Ruiz Dorantes ssize_t
273b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Sendable()
274b9b8d43cSOliver Ruiz Dorantes {
275*a58b3b32SOliver Ruiz Dorantes 	debugf("[%ld] %p\n", find_thread(NULL), this);
276b9b8d43cSOliver Ruiz Dorantes 
277b9b8d43cSOliver Ruiz Dorantes 	return 0;
278b9b8d43cSOliver Ruiz Dorantes }
279b9b8d43cSOliver Ruiz Dorantes 
280b9b8d43cSOliver Ruiz Dorantes 
281b9b8d43cSOliver Ruiz Dorantes ssize_t
282b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::Receivable()
283b9b8d43cSOliver Ruiz Dorantes {
284*a58b3b32SOliver Ruiz Dorantes 	debugf("[%ld] %p\n", find_thread(NULL), this);
285b9b8d43cSOliver Ruiz Dorantes 
286b9b8d43cSOliver Ruiz Dorantes 	return 0;
287b9b8d43cSOliver Ruiz Dorantes }
288b9b8d43cSOliver Ruiz Dorantes 
289b9b8d43cSOliver Ruiz Dorantes 
290b9b8d43cSOliver Ruiz Dorantes L2capEndpoint*
291b9b8d43cSOliver Ruiz Dorantes L2capEndpoint::ForPsm(uint16 psm)
292b9b8d43cSOliver Ruiz Dorantes {
293b9b8d43cSOliver Ruiz Dorantes 	L2capEndpoint* endpoint;
294b9b8d43cSOliver Ruiz Dorantes 
295b9b8d43cSOliver Ruiz Dorantes 	DoublyLinkedList<L2capEndpoint>::Iterator iterator = EndpointList.GetIterator();
296b9b8d43cSOliver Ruiz Dorantes 
297b9b8d43cSOliver Ruiz Dorantes 	while (iterator.HasNext()) {
298b9b8d43cSOliver Ruiz Dorantes 
299b9b8d43cSOliver Ruiz Dorantes 		endpoint = iterator.Next();
300a94c1dc5SOliver Ruiz Dorantes 		if (((struct sockaddr_l2cap*)&endpoint->socket->address)->l2cap_psm == psm
301a94c1dc5SOliver Ruiz Dorantes 			&& endpoint->fState == LISTEN) {
3027cc7cadaSOliver Ruiz Dorantes 			// TODO endpoint ocupied, lock it! define a channel for it
303b9b8d43cSOliver Ruiz Dorantes 			return endpoint;
304b9b8d43cSOliver Ruiz Dorantes 		}
305b9b8d43cSOliver Ruiz Dorantes 	}
306b9b8d43cSOliver Ruiz Dorantes 
307b9b8d43cSOliver Ruiz Dorantes 	return NULL;
308b9b8d43cSOliver Ruiz Dorantes }
3097cc7cadaSOliver Ruiz Dorantes 
3107cc7cadaSOliver Ruiz Dorantes 
3117cc7cadaSOliver Ruiz Dorantes void
3127cc7cadaSOliver Ruiz Dorantes L2capEndpoint::BindToChannel(L2capChannel* channel)
3137cc7cadaSOliver Ruiz Dorantes {
314*a58b3b32SOliver Ruiz Dorantes 	fChannel = channel;
315*a58b3b32SOliver Ruiz Dorantes 	fChannel->endpoint = this;
3167cc7cadaSOliver Ruiz Dorantes 
317*a58b3b32SOliver Ruiz Dorantes 	fChannel->configuration = &configuration;
3187cc7cadaSOliver Ruiz Dorantes 
319*a58b3b32SOliver Ruiz Dorantes 	debugf("Endpoint %p for psm %d, schannel %x dchannel %x\n", this,
320*a58b3b32SOliver Ruiz Dorantes 		channel->psm, channel->scid, channel->dcid);
321*a58b3b32SOliver Ruiz Dorantes 
322*a58b3b32SOliver Ruiz Dorantes }
323*a58b3b32SOliver Ruiz Dorantes 
324*a58b3b32SOliver Ruiz Dorantes 
325*a58b3b32SOliver Ruiz Dorantes status_t
326*a58b3b32SOliver Ruiz Dorantes L2capEndpoint::MarkEstablished()
327*a58b3b32SOliver Ruiz Dorantes {
328*a58b3b32SOliver Ruiz Dorantes 	debugf("Endpoint %p for psm %d, schannel %x dchannel %x\n", this,
329*a58b3b32SOliver Ruiz Dorantes 		fChannel->psm, fChannel->scid, fChannel->dcid);
330*a58b3b32SOliver Ruiz Dorantes 
331*a58b3b32SOliver Ruiz Dorantes 	net_socket* newSocket;
332*a58b3b32SOliver Ruiz Dorantes 	status_t error = gSocketModule->spawn_pending_socket(socket,	&newSocket);
333*a58b3b32SOliver Ruiz Dorantes 
334*a58b3b32SOliver Ruiz Dorantes 	gSocketModule->set_connected(newSocket);
335*a58b3b32SOliver Ruiz Dorantes 
336*a58b3b32SOliver Ruiz Dorantes 	release_sem(fAcceptSemaphore);
337*a58b3b32SOliver Ruiz Dorantes 
338*a58b3b32SOliver Ruiz Dorantes 	return error;
3397cc7cadaSOliver Ruiz Dorantes }
340