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