1 /****************************************************************************** 2 * 3 * Copyright (C) 2014 Google, Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 #define LOG_TAG "bt_l2cap_client" 20 21 #include "stack/include/l2cap_client.h" 22 23 #include <assert.h> 24 #include <string.h> 25 26 #include "btcore/include/bdaddr.h" 27 #include "osi/include/allocator.h" 28 #include "osi/include/buffer.h" 29 #include "osi/include/list.h" 30 #include "osi/include/log.h" 31 #include "osi/include/osi.h" 32 #include "stack/include/l2c_api.h" 33 34 struct l2cap_client_t { 35 l2cap_client_callbacks_t callbacks; 36 void *context; 37 38 uint16_t local_channel_id; 39 uint16_t remote_mtu; 40 bool configured_self; 41 bool configured_peer; 42 bool is_congested; 43 list_t *outbound_fragments; 44 }; 45 46 static void connect_completed_cb(uint16_t local_channel_id, uint16_t error_code); 47 static void config_request_cb(uint16_t local_channel_id, tL2CAP_CFG_INFO *requested_parameters); 48 static void config_completed_cb(uint16_t local_channel_id, tL2CAP_CFG_INFO *negotiated_parameters); 49 static void disconnect_request_cb(uint16_t local_channel_id, bool ack_required); 50 static void disconnect_completed_cb(uint16_t local_channel_id, uint16_t error_code); 51 static void congestion_cb(uint16_t local_channel_id, bool is_congested); 52 static void read_ready_cb(uint16_t local_channel_id, BT_HDR *packet); 53 static void write_completed_cb(uint16_t local_channel_id, uint16_t packets_completed); 54 55 static void fragment_packet(l2cap_client_t *client, buffer_t *packet); 56 static void dispatch_fragments(l2cap_client_t *client); 57 static l2cap_client_t *find(uint16_t local_channel_id); 58 59 // From the Bluetooth Core specification. 60 static const uint16_t L2CAP_MTU_DEFAULT = 672; 61 static const uint16_t L2CAP_MTU_MINIMUM = 48; 62 63 static const tL2CAP_APPL_INFO l2cap_callbacks = { 64 .pL2CA_ConnectCfm_Cb = connect_completed_cb, 65 .pL2CA_ConfigInd_Cb = config_request_cb, 66 .pL2CA_ConfigCfm_Cb = config_completed_cb, 67 .pL2CA_DisconnectInd_Cb = disconnect_request_cb, 68 .pL2CA_DisconnectCfm_Cb = disconnect_completed_cb, 69 .pL2CA_CongestionStatus_Cb = congestion_cb, 70 .pL2CA_DataInd_Cb = read_ready_cb, 71 .pL2CA_TxComplete_Cb = write_completed_cb, 72 }; 73 74 static list_t *l2cap_clients; // A list of l2cap_client_t. Container does not own objects. 75 76 buffer_t *l2cap_buffer_new(size_t size) { 77 buffer_t *buf = buffer_new(size + L2CAP_MIN_OFFSET); 78 buffer_t *slice = NULL; 79 if (buf) 80 slice = buffer_new_slice(buf, size); 81 buffer_free(buf); 82 return slice; 83 } 84 85 l2cap_client_t *l2cap_client_new(const l2cap_client_callbacks_t *callbacks, void *context) { 86 assert(callbacks != NULL); 87 assert(callbacks->connected != NULL); 88 assert(callbacks->disconnected != NULL); 89 assert(callbacks->read_ready != NULL); 90 assert(callbacks->write_ready != NULL); 91 92 if (!l2cap_clients) { 93 l2cap_clients = list_new(NULL); 94 if (!l2cap_clients) { 95 LOG_ERROR(LOG_TAG, "%s unable to allocate space for L2CAP client list.", __func__); 96 return NULL; 97 } 98 } 99 100 l2cap_client_t *ret = (l2cap_client_t *)osi_calloc(sizeof(l2cap_client_t)); 101 102 ret->callbacks = *callbacks; 103 ret->context = context; 104 105 ret->remote_mtu = L2CAP_MTU_DEFAULT; 106 ret->outbound_fragments = list_new(NULL); 107 if (!ret) { 108 LOG_ERROR(LOG_TAG, "%s unable to allocate outbound L2CAP fragment list.", __func__); 109 goto error; 110 } 111 112 list_append(l2cap_clients, ret); 113 114 return ret; 115 116 error:; 117 osi_free(ret); 118 return NULL; 119 } 120 121 void l2cap_client_free(l2cap_client_t *client) { 122 if (!client) 123 return; 124 125 list_remove(l2cap_clients, client); 126 l2cap_client_disconnect(client); 127 list_free(client->outbound_fragments); 128 osi_free(client); 129 } 130 131 bool l2cap_client_connect(l2cap_client_t *client, const bt_bdaddr_t *remote_bdaddr, uint16_t psm) { 132 assert(client != NULL); 133 assert(remote_bdaddr != NULL); 134 assert(psm != 0); 135 assert(!bdaddr_is_empty(remote_bdaddr)); 136 assert(client->local_channel_id == 0); 137 assert(!client->configured_self); 138 assert(!client->configured_peer); 139 assert(!L2C_INVALID_PSM(psm)); 140 141 client->local_channel_id = L2CA_ConnectReq(psm, (uint8_t *)remote_bdaddr); 142 if (!client->local_channel_id) { 143 LOG_ERROR(LOG_TAG, "%s unable to create L2CAP connection.", __func__); 144 return false; 145 } 146 147 L2CA_SetConnectionCallbacks(client->local_channel_id, &l2cap_callbacks); 148 return true; 149 } 150 151 void l2cap_client_disconnect(l2cap_client_t *client) { 152 assert(client != NULL); 153 154 if (client->local_channel_id && !L2CA_DisconnectReq(client->local_channel_id)) 155 LOG_ERROR(LOG_TAG, "%s unable to send disconnect message for LCID 0x%04x.", __func__, client->local_channel_id); 156 157 client->local_channel_id = 0; 158 client->remote_mtu = L2CAP_MTU_DEFAULT; 159 client->configured_self = false; 160 client->configured_peer = false; 161 client->is_congested = false; 162 163 for (const list_node_t *node = list_begin(client->outbound_fragments); node != list_end(client->outbound_fragments); node = list_next(node)) 164 osi_free(list_node(node)); 165 166 list_clear(client->outbound_fragments); 167 } 168 169 bool l2cap_client_is_connected(const l2cap_client_t *client) { 170 assert(client != NULL); 171 172 return client->local_channel_id != 0 && client->configured_self && client->configured_peer; 173 } 174 175 bool l2cap_client_write(l2cap_client_t *client, buffer_t *packet) { 176 assert(client != NULL); 177 assert(packet != NULL); 178 assert(l2cap_client_is_connected(client)); 179 180 if (client->is_congested) 181 return false; 182 183 fragment_packet(client, packet); 184 dispatch_fragments(client); 185 return true; 186 } 187 188 static void connect_completed_cb(uint16_t local_channel_id, uint16_t error_code) { 189 assert(local_channel_id != 0); 190 191 l2cap_client_t *client = find(local_channel_id); 192 if (!client) { 193 LOG_ERROR(LOG_TAG, "%s unable to find L2CAP client for LCID 0x%04x.", __func__, local_channel_id); 194 return; 195 } 196 197 if (error_code != L2CAP_CONN_OK) { 198 LOG_ERROR(LOG_TAG, "%s error connecting L2CAP channel: %d.", __func__, error_code); 199 client->callbacks.disconnected(client, client->context); 200 return; 201 } 202 203 // Use default L2CAP parameters. 204 tL2CAP_CFG_INFO desired_parameters; 205 memset(&desired_parameters, 0, sizeof(desired_parameters)); 206 if (!L2CA_ConfigReq(local_channel_id, &desired_parameters)) { 207 LOG_ERROR(LOG_TAG, "%s error sending L2CAP config parameters.", __func__); 208 client->callbacks.disconnected(client, client->context); 209 } 210 } 211 212 static void config_request_cb(uint16_t local_channel_id, tL2CAP_CFG_INFO *requested_parameters) { 213 tL2CAP_CFG_INFO response; 214 l2cap_client_t *client = find(local_channel_id); 215 216 if (!client) { 217 LOG_ERROR(LOG_TAG, "%s unable to find L2CAP client matching LCID 0x%04x.", __func__, local_channel_id); 218 return; 219 } 220 221 memset(&response, 0, sizeof(response)); 222 response.result = L2CAP_CFG_OK; 223 224 if (requested_parameters->mtu_present) { 225 // Make sure the peer chose an MTU at least as large as the minimum L2CAP MTU defined 226 // by the Bluetooth Core spec. 227 if (requested_parameters->mtu < L2CAP_MTU_MINIMUM) { 228 response.mtu = L2CAP_MTU_MINIMUM; 229 response.mtu_present = true; 230 response.result = L2CAP_CFG_UNACCEPTABLE_PARAMS; 231 } else { 232 client->remote_mtu = requested_parameters->mtu; 233 } 234 } 235 236 if (requested_parameters->fcr_present) { 237 if (requested_parameters->fcr.mode != L2CAP_FCR_BASIC_MODE) { 238 response.fcr_present = true; 239 response.fcr = requested_parameters->fcr; 240 response.fcr.mode = L2CAP_FCR_BASIC_MODE; 241 response.result = L2CAP_CFG_UNACCEPTABLE_PARAMS; 242 } 243 } 244 245 if (!L2CA_ConfigRsp(local_channel_id, &response)) { 246 LOG_ERROR(LOG_TAG, "%s unable to send config response for LCID 0x%04x.", __func__, local_channel_id); 247 l2cap_client_disconnect(client); 248 return; 249 } 250 251 // If we've configured both endpoints, let the listener know we've connected. 252 client->configured_peer = true; 253 if (l2cap_client_is_connected(client)) 254 client->callbacks.connected(client, client->context); 255 } 256 257 static void config_completed_cb(uint16_t local_channel_id, tL2CAP_CFG_INFO *negotiated_parameters) { 258 l2cap_client_t *client = find(local_channel_id); 259 260 if (!client) { 261 LOG_ERROR(LOG_TAG, "%s unable to find L2CAP client matching LCID 0x%04x.", __func__, local_channel_id); 262 return; 263 } 264 265 switch (negotiated_parameters->result) { 266 // We'll get another configuration response later. 267 case L2CAP_CFG_PENDING: 268 break; 269 270 case L2CAP_CFG_UNACCEPTABLE_PARAMS: 271 // TODO: see if we can renegotiate parameters instead of dropping the connection. 272 LOG_WARN(LOG_TAG, "%s dropping L2CAP connection due to unacceptable config parameters.", __func__); 273 l2cap_client_disconnect(client); 274 break; 275 276 case L2CAP_CFG_OK: 277 // If we've configured both endpoints, let the listener know we've connected. 278 client->configured_self = true; 279 if (l2cap_client_is_connected(client)) 280 client->callbacks.connected(client, client->context); 281 break; 282 283 // Failure, no further parameter negotiation possible. 284 default: 285 LOG_WARN(LOG_TAG, "%s L2CAP parameter negotiation failed with error code %d.", __func__, negotiated_parameters->result); 286 l2cap_client_disconnect(client); 287 break; 288 } 289 } 290 291 static void disconnect_request_cb(uint16_t local_channel_id, bool ack_required) { 292 l2cap_client_t *client = find(local_channel_id); 293 if (!client) { 294 LOG_ERROR(LOG_TAG, "%s unable to find L2CAP client with LCID 0x%04x.", __func__, local_channel_id); 295 return; 296 } 297 298 if (ack_required) 299 L2CA_DisconnectRsp(local_channel_id); 300 301 // We already sent a disconnect response so this LCID is now invalid. 302 client->local_channel_id = 0; 303 l2cap_client_disconnect(client); 304 305 client->callbacks.disconnected(client, client->context); 306 } 307 308 static void disconnect_completed_cb(uint16_t local_channel_id, UNUSED_ATTR uint16_t error_code) { 309 assert(local_channel_id != 0); 310 311 l2cap_client_t *client = find(local_channel_id); 312 if (!client) { 313 LOG_ERROR(LOG_TAG, "%s unable to find L2CAP client with LCID 0x%04x.", __func__, local_channel_id); 314 return; 315 } 316 317 client->local_channel_id = 0; 318 l2cap_client_disconnect(client); 319 320 client->callbacks.disconnected(client, client->context); 321 } 322 323 static void congestion_cb(uint16_t local_channel_id, bool is_congested) { 324 assert(local_channel_id != 0); 325 326 l2cap_client_t *client = find(local_channel_id); 327 if (!client) { 328 LOG_ERROR(LOG_TAG, "%s unable to find L2CAP client matching LCID 0x%04x.", __func__, local_channel_id); 329 return; 330 } 331 332 client->is_congested = is_congested; 333 334 if (!is_congested) { 335 // If we just decongested, dispatch whatever we have left over in our queue. 336 // Once that's done, if we're still decongested, notify the listener so it 337 // can start writing again. 338 dispatch_fragments(client); 339 if (!client->is_congested) 340 client->callbacks.write_ready(client, client->context); 341 } 342 } 343 344 static void read_ready_cb(uint16_t local_channel_id, BT_HDR *packet) { 345 assert(local_channel_id != 0); 346 347 l2cap_client_t *client = find(local_channel_id); 348 if (!client) { 349 LOG_ERROR(LOG_TAG, "%s unable to find L2CAP client matching LCID 0x%04x.", __func__, local_channel_id); 350 return; 351 } 352 353 // TODO(sharvil): eliminate copy from BT_HDR. 354 buffer_t *buffer = buffer_new(packet->len); 355 memcpy(buffer_ptr(buffer), packet->data + packet->offset, packet->len); 356 osi_free(packet); 357 358 client->callbacks.read_ready(client, buffer, client->context); 359 buffer_free(buffer); 360 } 361 362 static void write_completed_cb(UNUSED_ATTR uint16_t local_channel_id, UNUSED_ATTR uint16_t packets_completed) { 363 // Do nothing. We update congestion state based on the congestion callback 364 // and we've already removed items from outbound_fragments list so we don't 365 // really care how many packets were successfully dispatched. 366 } 367 368 static void fragment_packet(l2cap_client_t *client, buffer_t *packet) { 369 assert(client != NULL); 370 assert(packet != NULL); 371 372 // TODO(sharvil): eliminate copy into BT_HDR. 373 BT_HDR *bt_packet = osi_malloc(buffer_length(packet) + L2CAP_MIN_OFFSET); 374 bt_packet->offset = L2CAP_MIN_OFFSET; 375 bt_packet->len = buffer_length(packet); 376 memcpy(bt_packet->data + bt_packet->offset, buffer_ptr(packet), buffer_length(packet)); 377 378 for (;;) { 379 if (bt_packet->len <= client->remote_mtu) { 380 if (bt_packet->len > 0) 381 list_append(client->outbound_fragments, bt_packet); 382 else 383 osi_free(bt_packet); 384 break; 385 } 386 387 BT_HDR *fragment = osi_malloc(client->remote_mtu + L2CAP_MIN_OFFSET); 388 fragment->offset = L2CAP_MIN_OFFSET; 389 fragment->len = client->remote_mtu; 390 memcpy(fragment->data + fragment->offset, bt_packet->data + bt_packet->offset, client->remote_mtu); 391 392 list_append(client->outbound_fragments, fragment); 393 394 bt_packet->offset += client->remote_mtu; 395 bt_packet->len -= client->remote_mtu; 396 } 397 } 398 399 static void dispatch_fragments(l2cap_client_t *client) { 400 assert(client != NULL); 401 assert(!client->is_congested); 402 403 while (!list_is_empty(client->outbound_fragments)) { 404 BT_HDR *packet = (BT_HDR *)list_front(client->outbound_fragments); 405 list_remove(client->outbound_fragments, packet); 406 407 switch (L2CA_DataWrite(client->local_channel_id, packet)) { 408 case L2CAP_DW_CONGESTED: 409 client->is_congested = true; 410 return; 411 412 case L2CAP_DW_FAILED: 413 LOG_ERROR(LOG_TAG, "%s error writing data to L2CAP connection LCID 0x%04x; disconnecting.", __func__, client->local_channel_id); 414 l2cap_client_disconnect(client); 415 return; 416 417 case L2CAP_DW_SUCCESS: 418 break; 419 } 420 } 421 } 422 423 static l2cap_client_t *find(uint16_t local_channel_id) { 424 assert(local_channel_id != 0); 425 426 for (const list_node_t *node = list_begin(l2cap_clients); node != list_end(l2cap_clients); node = list_next(node)) { 427 l2cap_client_t *client = (l2cap_client_t *)list_node(node); 428 if (client->local_channel_id == local_channel_id) 429 return client; 430 } 431 432 return NULL; 433 } 434