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