2 * Copyright 2008 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
3 * All rights reserved. Distributed under the terms of the MIT License.
5 #include "L2capEndpoint.h"
6 #include "l2cap_address.h"
7 #include "l2cap_upper.h"
8 #include "l2cap_lower.h"
14 #include <bluetooth/bdaddrUtils.h>
15 #include <bluetooth/L2CAP/btL2CAP.h>
20 static inline bigtime_t
21 absolute_timeout(bigtime_t timeout
)
23 if (timeout
== 0 || timeout
== B_INFINITE_TIMEOUT
)
26 // TODO: Make overflow safe!
27 return timeout
+ system_time();
31 L2capEndpoint::L2capEndpoint(net_socket
* socket
)
33 ProtocolSocket(socket
),
34 fConfigurationSet(false),
35 fEstablishSemaphore(-1),
41 /* Set MTU and flow control settings to defaults */
42 fConfiguration
.imtu
= L2CAP_MTU_DEFAULT
;
43 memcpy(&fConfiguration
.iflow
, &default_qos
, sizeof(l2cap_flow_t
) );
45 fConfiguration
.omtu
= L2CAP_MTU_DEFAULT
;
46 memcpy(&fConfiguration
.oflow
, &default_qos
, sizeof(l2cap_flow_t
) );
48 fConfiguration
.flush_timo
= L2CAP_FLUSH_TIMO_DEFAULT
;
49 fConfiguration
.link_timo
= L2CAP_LINK_TIMO_DEFAULT
;
51 // TODO: XXX not for listening endpoints, imtu should be known first
52 gStackModule
->init_fifo(&fReceivingFifo
, "l2cap recvfifo", L2CAP_MTU_DEFAULT
);
56 L2capEndpoint::~L2capEndpoint()
60 gStackModule
->uninit_fifo(&fReceivingFifo
);
74 L2capEndpoint::Uninit()
86 status_t error
= ProtocolSocket::Open();
95 L2capEndpoint::Close()
99 if (fChannel
== NULL
) {
100 // TODO: Parent socket
104 if (fState
== CLOSED
) {
105 // TODO: Clean needed stuff
108 // Issue Disconnection request over the channel
111 bigtime_t timeout
= absolute_timeout(300 * 1000 * 1000);
113 status_t error
= l2cap_upper_dis_req(fChannel
);
118 return acquire_sem_etc(fEstablishSemaphore
, 1,
119 B_ABSOLUTE_TIMEOUT
| B_CAN_INTERRUPT
, timeout
);
123 if (fEstablishSemaphore
!= -1) {
124 delete_sem(fEstablishSemaphore
);
132 L2capEndpoint::Free()
141 L2capEndpoint::Bind(const struct sockaddr
* _address
)
143 const sockaddr_l2cap
* address
144 = reinterpret_cast<const sockaddr_l2cap
*>(_address
);
146 if (_address
== NULL
)
149 if (address
->l2cap_family
!= AF_BLUETOOTH
)
152 if (address
->l2cap_len
!= sizeof(struct sockaddr_l2cap
))
155 // TODO: Check if that PSM is already bound
156 // return EADDRINUSE;
158 // TODO: Check if the PSM is valid, check assigned numbers document for valid
159 // psm available to applications.
160 // All PSM values shall be ODD, that is, the least significant bit of the least
161 // significant octet must be ’1’. Also, all PSM values shall have the least
162 // significant bit of the most significant octet equal to ’0’. This allows
163 // the PSM field to be extended beyond 16 bits.
164 if ((address
->l2cap_psm
& 1) == 0)
167 memcpy(&socket
->address
, _address
, sizeof(struct sockaddr_l2cap
));
168 socket
->address
.ss_len
= sizeof(struct sockaddr_l2cap
);
177 L2capEndpoint::Unbind()
186 L2capEndpoint::Listen(int backlog
)
190 if (fState
!= BOUND
) {
191 ERROR("%s: Invalid State\n", __func__
);
195 fEstablishSemaphore
= create_sem(0, "l2cap serv accept");
196 if (fEstablishSemaphore
< B_OK
) {
197 ERROR("%s: Semaphore could not be created\n", __func__
);
201 gSocketModule
->set_max_backlog(socket
, backlog
);
210 L2capEndpoint::Connect(const struct sockaddr
* _address
)
212 const sockaddr_l2cap
* address
213 = reinterpret_cast<const sockaddr_l2cap
*>(_address
);
215 if (address
->l2cap_len
!= sizeof(*address
))
218 // Check for any specific status?
219 if (fState
== CONNECTING
)
222 // TODO: should not be in the BOUND status first?
225 TRACE("%s: [%ld] %p->L2capEndpoint::Connect(\"%s\")\n", __func__
,
226 find_thread(NULL
), this,
227 ConstSocketAddress(&gL2cap4AddressModule
, _address
)
231 // TODO: If we were bound to a specific source address
233 // Route, we must find a Connection descriptor with address->l2cap_address
234 hci_id hid
= btCoreData
->RouteConnection(address
->l2cap_bdaddr
);
237 TRACE("%s: %" B_PRId32
" for route %s\n", __func__
, hid
,
238 bdaddrUtils::ToString(address
->l2cap_bdaddr
).String());
242 HciConnection
* connection
= btCoreData
->ConnectionByDestination(
243 address
->l2cap_bdaddr
, hid
);
245 L2capChannel
* channel
= btCoreData
->AddChannel(connection
,
251 // Send connection request
252 if (l2cap_upper_con_req(channel
) == B_OK
) {
255 BindToChannel(channel
);
257 fEstablishSemaphore
= create_sem(0, "l2cap client");
258 if (fEstablishSemaphore
< B_OK
) {
259 ERROR("%s: Semaphore could not be created\n", __func__
);
263 bigtime_t timeout
= absolute_timeout(300 * 1000 * 1000);
265 return acquire_sem_etc(fEstablishSemaphore
, 1,
266 B_ABSOLUTE_TIMEOUT
| B_CAN_INTERRUPT
, timeout
);
278 L2capEndpoint::Accept(net_socket
** _acceptedSocket
)
282 // MutexLocker locker(fLock);
285 bigtime_t timeout
= absolute_timeout(300 * 1000 * 1000);
290 status
= acquire_sem_etc(fEstablishSemaphore
, 1, B_ABSOLUTE_TIMEOUT
291 | B_CAN_INTERRUPT
, timeout
);
297 status
= gSocketModule
->dequeue_connected(socket
, _acceptedSocket
);
299 if (status
!= B_OK
) {
300 ERROR("%s: Could not dequeue socket %s\n", __func__
,
304 ((L2capEndpoint
*)((*_acceptedSocket
)->first_protocol
))->fState
= ESTABLISHED
;
305 // unassign any channel for the parent endpoint
307 // we are listening again
311 } while (status
!= B_OK
);
318 L2capEndpoint::Send(const iovec
* vecs
, size_t vecCount
,
319 ancillary_data_container
* ancillaryData
)
328 L2capEndpoint::Receive(const iovec
* vecs
, size_t vecCount
,
329 ancillary_data_container
** _ancillaryData
, struct sockaddr
* _address
,
330 socklen_t
* _addressLength
)
334 if (fState
!= ESTABLISHED
) {
335 ERROR("%s: Invalid State %p\n", __func__
, this);
344 L2capEndpoint::ReadData(size_t numBytes
, uint32 flags
, net_buffer
** _buffer
)
348 if (fState
!= ESTABLISHED
) {
349 ERROR("%s: Invalid State %p\n", __func__
, this);
353 return gStackModule
->fifo_dequeue_buffer(&fReceivingFifo
, flags
,
354 B_INFINITE_TIMEOUT
, _buffer
);
359 L2capEndpoint::SendData(net_buffer
* buffer
)
363 if (fState
!= ESTABLISHED
) {
364 ERROR("%s: Invalid State %p\n", __func__
, this);
368 btCoreData
->SpawnFrame(fChannel
->conn
, fChannel
, buffer
, L2CAP_B_FRAME
);
370 SchedConnectionPurgeThread(fChannel
->conn
);
372 // TODO: Report bytes sent?
378 L2capEndpoint::Sendable()
386 L2capEndpoint::Receivable()
394 L2capEndpoint::ForPsm(uint16 psm
)
396 L2capEndpoint
* endpoint
;
398 DoublyLinkedList
<L2capEndpoint
>::Iterator iterator
399 = EndpointList
.GetIterator();
401 while (iterator
.HasNext()) {
403 endpoint
= iterator
.Next();
404 if (((struct sockaddr_l2cap
*)&endpoint
->socket
->address
)->l2cap_psm
== psm
405 && endpoint
->fState
== LISTEN
) {
406 // TODO endpoint ocupied, lock it! define a channel for it
416 L2capEndpoint::BindNewEnpointToChannel(L2capChannel
* channel
)
418 net_socket
* newSocket
;
419 status_t error
= gSocketModule
->spawn_pending_socket(socket
, &newSocket
);
421 ERROR("%s: Could not spawn child for Endpoint %p\n", __func__
, this);
422 // TODO: Handle situation
426 L2capEndpoint
* endpoint
= (L2capEndpoint
*)newSocket
->first_protocol
;
428 endpoint
->fChannel
= channel
;
429 endpoint
->fPeerEndpoint
= this;
431 channel
->endpoint
= endpoint
;
433 //debugf("new socket %p/e->%p from parent %p/e->%p\n",
434 // newSocket, endpoint, socket, this);
436 // Provide the channel the configuration set by the user socket
437 channel
->configuration
= &fConfiguration
;
439 // It might be used keep the last negotiated channel
440 // fChannel = channel;
442 //debugf("New endpoint %p for psm %d, schannel %x dchannel %x\n", endpoint,
443 // channel->psm, channel->scid, channel->dcid);
448 L2capEndpoint::BindToChannel(L2capChannel
* channel
)
450 this->fChannel
= channel
;
451 channel
->endpoint
= this;
453 // Provide the channel the configuration set by the user socket
454 channel
->configuration
= &fConfiguration
;
456 // no parent to give feedback
457 fPeerEndpoint
= NULL
;
462 L2capEndpoint::MarkEstablished()
466 status_t error
= B_OK
;
467 fChannel
->state
= L2CAP_CHAN_OPEN
;
468 fState
= ESTABLISHED
;
470 if (fPeerEndpoint
!= NULL
) {
472 error
= gSocketModule
->set_connected(socket
);
474 release_sem(fPeerEndpoint
->fEstablishSemaphore
);
476 ERROR("%s: Could not set child Endpoint %p %s\n", __func__
, this,
480 release_sem(fEstablishSemaphore
);
487 L2capEndpoint::MarkClosed()
491 if (fState
== CLOSED
)
492 release_sem(fEstablishSemaphore
);