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