1 /* 2 * Copyright (C) 2019 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 #define BTSTACK_FILE__ "goep_server.c" 39 40 #include "btstack_config.h" 41 42 #include <stdint.h> 43 #include <string.h> 44 45 #include "hci_cmd.h" 46 #include "btstack_debug.h" 47 #include "btstack_defines.h" 48 #include "hci.h" 49 #include "btstack_memory.h" 50 #include "hci_dump.h" 51 #include "btstack_event.h" 52 53 #include "classic/goep_server.h" 54 #include "classic/obex_message_builder.h" 55 56 #ifdef ENABLE_GOEP_L2CAP 57 #include "l2cap.h" 58 59 static l2cap_ertm_config_t ertm_config = { 60 1, // ertm mandatory 61 2, // max transmit, some tests require > 1 62 2000, 63 12000, 64 (GOEP_SERVER_ERTM_BUFFER / 2), // l2cap ertm mtu 65 2, 66 2, 67 1, // 16-bit FCS 68 }; 69 70 static uint8_t goep_server_l2cap_packet_buffer[1000]; 71 72 #endif 73 74 static btstack_linked_list_t goep_server_connections = NULL; 75 static btstack_linked_list_t goep_server_services = NULL; 76 static uint16_t goep_server_cid_counter = 0; 77 78 static goep_server_service_t * goep_server_get_service_for_rfcomm_channel(uint8_t rfcomm_channel){ 79 btstack_linked_item_t *it; 80 for (it = (btstack_linked_item_t *) goep_server_services; it ; it = it->next){ 81 goep_server_service_t * service = ((goep_server_service_t *) it); 82 if (service->rfcomm_channel == rfcomm_channel){ 83 return service; 84 }; 85 } 86 return NULL; 87 } 88 89 static goep_server_service_t * goep_server_get_service_for_l2cap_psm(uint16_t l2cap_psm){ 90 btstack_linked_item_t *it; 91 for (it = (btstack_linked_item_t *) goep_server_services; it ; it = it->next){ 92 goep_server_service_t * service = ((goep_server_service_t *) it); 93 if (service->l2cap_psm == l2cap_psm){ 94 return service; 95 }; 96 } 97 return NULL; 98 } 99 100 static goep_server_connection_t * goep_server_get_connection_for_rfcomm_cid(uint16_t bearer_cid){ 101 btstack_linked_item_t *it; 102 for (it = (btstack_linked_item_t *) goep_server_connections; it ; it = it->next){ 103 goep_server_connection_t * connection = ((goep_server_connection_t *) it); 104 if (connection->type != GOEP_CONNECTION_RFCOMM) continue; 105 if (connection->bearer_cid == bearer_cid){ 106 return connection; 107 }; 108 } 109 return NULL; 110 } 111 112 static goep_server_connection_t * goep_server_get_connection_for_l2cap_cid(uint16_t bearer_cid){ 113 btstack_linked_item_t *it; 114 for (it = (btstack_linked_item_t *) goep_server_connections; it ; it = it->next){ 115 goep_server_connection_t * connection = ((goep_server_connection_t *) it); 116 if (connection->type != GOEP_CONNECTION_L2CAP) continue; 117 if (connection->bearer_cid == bearer_cid){ 118 return connection; 119 }; 120 } 121 return NULL; 122 } 123 124 static goep_server_connection_t * goep_server_get_connection_for_goep_cid(uint16_t goep_cid){ 125 btstack_linked_item_t *it; 126 for (it = (btstack_linked_item_t *) goep_server_connections; it ; it = it->next){ 127 goep_server_connection_t * connection = ((goep_server_connection_t *) it); 128 if (connection->goep_cid == goep_cid){ 129 return connection; 130 }; 131 } 132 return NULL; 133 } 134 135 static uint16_t goep_server_get_next_goep_cid(void){ 136 goep_server_cid_counter++; 137 if (goep_server_cid_counter == 0){ 138 goep_server_cid_counter = 1; 139 } 140 return goep_server_cid_counter; 141 } 142 143 static inline void goep_server_emit_incoming_connection(btstack_packet_handler_t callback, uint16_t goep_cid, bd_addr_t bd_addr, hci_con_handle_t con_handle){ 144 uint8_t event[13]; 145 uint16_t pos = 0; 146 event[pos++] = HCI_EVENT_GOEP_META; 147 event[pos++] = 15 - 2; 148 event[pos++] = GOEP_SUBEVENT_INCOMING_CONNECTION; 149 little_endian_store_16(event, pos, goep_cid); 150 pos+=2; 151 memcpy(&event[pos], bd_addr, 6); 152 pos += 6; 153 little_endian_store_16(event, pos, con_handle); 154 pos += 2; 155 btstack_assert(pos == sizeof(event)); 156 callback(HCI_EVENT_PACKET, goep_cid, &event[0], pos); 157 } 158 159 static inline void goep_server_emit_connection_opened(btstack_packet_handler_t callback, uint16_t goep_cid, bd_addr_t bd_addr, hci_con_handle_t con_handle, uint8_t status){ 160 uint8_t event[15]; 161 uint16_t pos = 0; 162 event[pos++] = HCI_EVENT_GOEP_META; 163 event[pos++] = 15 - 2; 164 event[pos++] = GOEP_SUBEVENT_CONNECTION_OPENED; 165 little_endian_store_16(event, pos, goep_cid); 166 pos+=2; 167 event[pos++] = status; 168 memcpy(&event[pos], bd_addr, 6); 169 pos += 6; 170 little_endian_store_16(event, pos, con_handle); 171 pos += 2; 172 event[pos++] = 1; 173 btstack_assert(pos == sizeof(event)); 174 callback(HCI_EVENT_PACKET, goep_cid, &event[0], pos); 175 } 176 177 static inline void goep_server_emit_connection_closed(btstack_packet_handler_t callback, uint16_t goep_cid){ 178 uint8_t event[5]; 179 uint16_t pos = 0; 180 event[pos++] = HCI_EVENT_GOEP_META; 181 event[pos++] = 5 - 3; 182 event[pos++] = GOEP_SUBEVENT_CONNECTION_CLOSED; 183 little_endian_store_16(event, pos, goep_cid); 184 pos += 2; 185 btstack_assert(pos == sizeof(event)); 186 callback(HCI_EVENT_PACKET, goep_cid, &event[0], pos); 187 } 188 189 static inline void goep_server_emit_can_send_now_event(goep_server_connection_t * connection){ 190 uint8_t event[5]; 191 uint16_t pos = 0; 192 event[pos++] = HCI_EVENT_GOEP_META; 193 event[pos++] = 5 - 3; 194 event[pos++] = GOEP_SUBEVENT_CAN_SEND_NOW; 195 little_endian_store_16(event,pos,connection->goep_cid); 196 pos += 2; 197 btstack_assert(pos == sizeof(event)); 198 connection->callback(HCI_EVENT_PACKET, connection->goep_cid, &event[0], pos); 199 } 200 201 static void goep_server_handle_connection_opened(goep_server_connection_t * context, bd_addr_t addr, hci_con_handle_t con_handle, uint8_t status, uint16_t bearer_cid, uint16_t bearer_mtu){ 202 203 uint16_t goep_cid = context->goep_cid; 204 btstack_packet_handler_t packet_handler = context->callback; 205 206 if (status) { 207 log_info("goep_client: open failed, status %u", status); 208 btstack_linked_list_remove(&goep_server_connections, (btstack_linked_item_t *) context); 209 btstack_memory_goep_server_connection_free(context); 210 } else { 211 // context->bearer_mtu = mtu; 212 context->state = GOEP_SERVER_CONNECTED; 213 context->bearer_cid = bearer_cid; 214 #ifdef ENABLE_GOEP_L2CAP 215 if (context->type == GOEP_CONNECTION_L2CAP){ 216 bearer_mtu = btstack_min(bearer_mtu, sizeof(goep_server_l2cap_packet_buffer)); 217 } 218 #endif 219 context->bearer_mtu = bearer_mtu; 220 log_info("goep_server: connection opened. cid %u, max frame size %u", context->bearer_cid, bearer_mtu); 221 } 222 223 goep_server_emit_connection_opened(packet_handler, goep_cid, addr, con_handle, status); 224 } 225 226 static void goep_server_handle_connection_closed(goep_server_connection_t * goep_connection){ 227 uint16_t goep_cid = goep_connection->goep_cid; 228 btstack_packet_handler_t packet_handler = goep_connection->callback; 229 230 btstack_linked_list_remove(&goep_server_connections, (btstack_linked_item_t *) goep_connection); 231 btstack_memory_goep_server_connection_free(goep_connection); 232 233 goep_server_emit_connection_closed(packet_handler, goep_cid); 234 } 235 236 #ifdef ENABLE_GOEP_L2CAP 237 static void goep_server_packet_handler_l2cap(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 238 UNUSED(channel); 239 UNUSED(size); 240 241 bd_addr_t event_addr; 242 uint16_t l2cap_psm; 243 uint16_t l2cap_cid; 244 goep_server_connection_t * goep_connection; 245 goep_server_service_t * goep_service; 246 247 switch (packet_type){ 248 case HCI_EVENT_PACKET: 249 switch (hci_event_packet_get_type(packet)) { 250 case L2CAP_EVENT_INCOMING_CONNECTION: 251 l2cap_psm = l2cap_event_incoming_connection_get_psm(packet); 252 l2cap_cid = l2cap_event_incoming_connection_get_local_cid(packet); 253 goep_service = goep_server_get_service_for_l2cap_psm(l2cap_psm); 254 if (!goep_service){ 255 l2cap_decline_connection(l2cap_cid); 256 break; 257 } 258 259 // alloc structure 260 goep_connection = btstack_memory_goep_server_connection_get(); 261 if (!goep_connection){ 262 l2cap_decline_connection(l2cap_cid); 263 break; 264 } 265 266 // setup connection 267 goep_connection->goep_cid = goep_server_get_next_goep_cid(); 268 goep_connection->bearer_cid = l2cap_cid; 269 goep_connection->callback = goep_service->callback; 270 goep_connection->type = GOEP_CONNECTION_L2CAP; 271 goep_connection->state = GOEP_SERVER_W4_ACCEPT_REJECT; 272 btstack_linked_list_add(&goep_server_connections, (btstack_linked_item_t *) goep_connection); 273 274 // notify user 275 l2cap_event_incoming_connection_get_address(packet, event_addr); 276 goep_server_emit_incoming_connection(goep_service->callback, goep_connection->goep_cid, event_addr, 277 l2cap_event_incoming_connection_get_handle(packet)); 278 break; 279 280 case L2CAP_EVENT_CHANNEL_OPENED: 281 l2cap_cid = l2cap_event_channel_opened_get_local_cid(packet); 282 goep_connection = goep_server_get_connection_for_l2cap_cid(l2cap_cid); 283 btstack_assert(goep_connection != NULL); 284 btstack_assert(goep_connection->state == GOEP_SERVER_W4_CONNECTED); 285 l2cap_event_channel_opened_get_address(packet, event_addr); 286 goep_server_handle_connection_opened(goep_connection, event_addr, 287 l2cap_event_channel_opened_get_handle(packet), 288 l2cap_event_channel_opened_get_status(packet), 289 l2cap_cid, 290 l2cap_event_channel_opened_get_remote_mtu(packet) ); 291 return; 292 case L2CAP_EVENT_CAN_SEND_NOW: 293 l2cap_cid = l2cap_event_can_send_now_get_local_cid(packet); 294 goep_connection = goep_server_get_connection_for_l2cap_cid(l2cap_cid); 295 btstack_assert(goep_connection != NULL); 296 goep_server_emit_can_send_now_event(goep_connection); 297 break; 298 case L2CAP_EVENT_CHANNEL_CLOSED: 299 l2cap_cid = l2cap_event_channel_closed_get_local_cid(packet); 300 goep_connection = goep_server_get_connection_for_l2cap_cid(l2cap_cid); 301 btstack_assert(goep_connection != NULL); 302 goep_server_handle_connection_closed(goep_connection); 303 break; 304 default: 305 break; 306 } 307 break; 308 case L2CAP_DATA_PACKET: 309 goep_connection = goep_server_get_connection_for_l2cap_cid(channel); 310 btstack_assert(goep_connection != NULL); 311 goep_connection->callback(GOEP_DATA_PACKET, goep_connection->goep_cid, packet, size); 312 break; 313 default: 314 break; 315 } 316 } 317 #endif 318 319 static void goep_server_packet_handler_rfcomm(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 320 UNUSED(channel); 321 UNUSED(size); 322 323 bd_addr_t event_addr; 324 uint8_t rfcomm_channel; 325 uint16_t rfcomm_cid; 326 goep_server_service_t * goep_service; 327 goep_server_connection_t * goep_connection; 328 329 switch (packet_type){ 330 case HCI_EVENT_PACKET: 331 switch (hci_event_packet_get_type(packet)) { 332 case RFCOMM_EVENT_INCOMING_CONNECTION: 333 rfcomm_channel = rfcomm_event_incoming_connection_get_server_channel(packet); 334 rfcomm_cid = rfcomm_event_incoming_connection_get_rfcomm_cid(packet); 335 336 goep_service = goep_server_get_service_for_rfcomm_channel(rfcomm_channel); 337 if (!goep_service){ 338 rfcomm_decline_connection(rfcomm_cid); 339 break; 340 } 341 342 // alloc structure 343 goep_connection = btstack_memory_goep_server_connection_get(); 344 if (!goep_connection){ 345 rfcomm_decline_connection(rfcomm_cid); 346 break; 347 } 348 349 // setup connection 350 goep_connection->goep_cid = goep_server_get_next_goep_cid(); 351 goep_connection->bearer_cid = rfcomm_cid; 352 goep_connection->callback = goep_service->callback; 353 goep_connection->type = GOEP_CONNECTION_RFCOMM; 354 goep_connection->state = GOEP_SERVER_W4_ACCEPT_REJECT; 355 btstack_linked_list_add(&goep_server_connections, (btstack_linked_item_t *) goep_connection); 356 357 // notify user 358 rfcomm_event_incoming_connection_get_bd_addr(packet, event_addr); 359 goep_server_emit_incoming_connection(goep_service->callback, goep_connection->goep_cid, event_addr, 360 rfcomm_event_incoming_connection_get_con_handle(packet)); 361 break; 362 363 case RFCOMM_EVENT_CHANNEL_OPENED: 364 rfcomm_cid = rfcomm_event_channel_opened_get_rfcomm_cid(packet); 365 goep_connection = goep_server_get_connection_for_rfcomm_cid(rfcomm_cid); 366 btstack_assert(goep_connection != NULL); 367 btstack_assert(goep_connection->state == GOEP_SERVER_W4_CONNECTED); 368 rfcomm_event_channel_opened_get_bd_addr(packet, event_addr); 369 goep_server_handle_connection_opened(goep_connection, event_addr, 370 rfcomm_event_channel_opened_get_con_handle(packet), 371 rfcomm_event_channel_opened_get_status(packet), 372 rfcomm_cid, 373 rfcomm_event_channel_opened_get_max_frame_size(packet) ); 374 break; 375 376 case RFCOMM_EVENT_CAN_SEND_NOW: 377 rfcomm_cid = rfcomm_event_can_send_now_get_rfcomm_cid(packet); 378 goep_connection = goep_server_get_connection_for_rfcomm_cid(rfcomm_cid); 379 btstack_assert(goep_connection != NULL); 380 goep_server_emit_can_send_now_event(goep_connection); 381 break; 382 383 case RFCOMM_EVENT_CHANNEL_CLOSED: 384 rfcomm_cid = rfcomm_event_channel_closed_get_rfcomm_cid(packet); 385 goep_connection = goep_server_get_connection_for_rfcomm_cid(rfcomm_cid); 386 btstack_assert(goep_connection != NULL); 387 goep_server_handle_connection_closed(goep_connection); 388 break; 389 390 default: 391 break; 392 } 393 break; 394 395 case RFCOMM_DATA_PACKET: 396 goep_connection = goep_server_get_connection_for_rfcomm_cid(channel); 397 btstack_assert(goep_connection != NULL); 398 goep_connection->callback(GOEP_DATA_PACKET, goep_connection->goep_cid, packet, size); 399 break; 400 401 default: 402 break; 403 } 404 } 405 406 void goep_server_init(void){ 407 } 408 409 uint8_t goep_server_register_service(btstack_packet_handler_t callback, uint8_t rfcomm_channel, uint16_t rfcomm_max_frame_size, 410 uint16_t l2cap_psm, uint16_t l2cap_mtu, gap_security_level_t security_level){ 411 412 log_info("rfcomm_channel 0x%02x rfcomm_max_frame_size %u l2cap_psm 0x%02x l2cap_mtu %u", 413 rfcomm_channel, rfcomm_max_frame_size, l2cap_psm, l2cap_mtu); 414 415 // check if service is already registered 416 goep_server_service_t * service; 417 service = goep_server_get_service_for_rfcomm_channel(rfcomm_channel); 418 if (service != NULL) { 419 return RFCOMM_CHANNEL_ALREADY_REGISTERED; 420 } 421 422 #ifdef ENABLE_GOEP_L2CAP 423 if (l2cap_psm != 0){ 424 service = goep_server_get_service_for_l2cap_psm(l2cap_psm); 425 if (service != NULL) { 426 return L2CAP_SERVICE_ALREADY_REGISTERED; 427 } 428 } 429 #endif 430 431 // alloc structure 432 service = btstack_memory_goep_server_service_get(); 433 if (service == NULL) { 434 return BTSTACK_MEMORY_ALLOC_FAILED; 435 } 436 437 // fill in 438 service->callback = callback; 439 service->rfcomm_channel = rfcomm_channel; 440 service->l2cap_psm = l2cap_psm; 441 442 uint8_t status = ERROR_CODE_SUCCESS; 443 bool rfcomm_registered = false; 444 445 #ifdef ENABLE_GOEP_L2CAP 446 bool l2cap_registered = false; 447 // register with L2CAP 448 if (l2cap_psm != 0){ 449 status = l2cap_register_service(goep_server_packet_handler_l2cap, l2cap_psm, l2cap_mtu, security_level); 450 if (status == ERROR_CODE_SUCCESS){ 451 l2cap_registered = true; 452 } 453 } 454 #endif 455 456 // register with RFCOMM 457 if (status == ERROR_CODE_SUCCESS){ 458 status = rfcomm_register_service(goep_server_packet_handler_rfcomm, rfcomm_channel, rfcomm_max_frame_size); 459 if (status == ERROR_CODE_SUCCESS){ 460 rfcomm_registered = true; 461 } 462 } 463 464 // add service on success 465 if (status == ERROR_CODE_SUCCESS){ 466 btstack_linked_list_add(&goep_server_services, (btstack_linked_item_t *) service); 467 return ERROR_CODE_SUCCESS; 468 } 469 470 // unrestore otherwise 471 btstack_memory_goep_server_service_free(service); 472 #ifdef ENABLE_GOEP_L2CAP 473 if (l2cap_registered){ 474 l2cap_unregister_service(l2cap_psm); 475 } 476 #endif 477 if (rfcomm_registered){ 478 rfcomm_unregister_service(rfcomm_channel); 479 } 480 return status; 481 } 482 483 uint8_t goep_server_accept_connection(uint16_t goep_cid){ 484 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 485 if (connection == NULL){ 486 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 487 } 488 if (connection->state != GOEP_SERVER_W4_ACCEPT_REJECT){ 489 return ERROR_CODE_COMMAND_DISALLOWED; 490 } 491 connection->state = GOEP_SERVER_W4_CONNECTED; 492 #ifdef ENABLE_GOEP_L2CAP 493 if (connection->type == GOEP_CONNECTION_L2CAP){ 494 return l2cap_ertm_accept_connection(connection->bearer_cid, &ertm_config, connection->ertm_buffer, GOEP_SERVER_ERTM_BUFFER); 495 } 496 #endif 497 return rfcomm_accept_connection(connection->bearer_cid); 498 } 499 500 uint8_t goep_server_decline_connection(uint16_t goep_cid){ 501 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 502 if (connection == NULL){ 503 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 504 } 505 connection->state = GOEP_SERVER_W4_CONNECTED; 506 if (connection->state != GOEP_SERVER_W4_ACCEPT_REJECT){ 507 return ERROR_CODE_COMMAND_DISALLOWED; 508 } 509 #ifdef ENABLE_GOEP_L2CAP 510 if (connection->type == GOEP_CONNECTION_L2CAP){ 511 l2cap_decline_connection(connection->bearer_cid); 512 return ERROR_CODE_SUCCESS; 513 } 514 #endif 515 return rfcomm_decline_connection(connection->bearer_cid); 516 } 517 518 uint8_t goep_server_request_can_send_now(uint16_t goep_cid){ 519 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 520 if (connection == NULL){ 521 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 522 } 523 524 switch (connection->type){ 525 case GOEP_CONNECTION_RFCOMM: 526 rfcomm_request_can_send_now_event(connection->bearer_cid); 527 break; 528 #ifdef ENABLE_GOEP_L2CAP 529 case GOEP_CONNECTION_L2CAP: 530 l2cap_request_can_send_now_event(connection->bearer_cid); 531 break; 532 #endif 533 default: 534 btstack_unreachable(); 535 break; 536 } 537 return ERROR_CODE_SUCCESS; 538 } 539 540 static uint8_t * goep_server_get_outgoing_buffer(goep_server_connection_t * connection){ 541 switch (connection->type){ 542 #ifdef ENABLE_GOEP_L2CAP 543 case GOEP_CONNECTION_L2CAP: 544 return goep_server_l2cap_packet_buffer; 545 #endif 546 case GOEP_CONNECTION_RFCOMM: 547 return rfcomm_get_outgoing_buffer(); 548 default: 549 btstack_unreachable(); 550 return NULL; 551 } 552 } 553 554 static uint16_t goep_server_get_outgoing_buffer_len(goep_server_connection_t * connection){ 555 return connection->bearer_mtu; 556 } 557 558 static void goep_server_packet_init(goep_server_connection_t * connection){ 559 switch (connection->type){ 560 #ifdef ENABLE_GOEP_L2CAP 561 case GOEP_CONNECTION_L2CAP: 562 break; 563 #endif 564 case GOEP_CONNECTION_RFCOMM: 565 rfcomm_reserve_packet_buffer(); 566 break; 567 default: 568 btstack_unreachable(); 569 break; 570 } 571 } 572 573 uint8_t goep_server_response_create_connect(uint16_t goep_cid, uint8_t obex_version_number, uint8_t flags, uint16_t maximum_obex_packet_length){ 574 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 575 if (connection == NULL) { 576 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 577 } 578 579 goep_server_packet_init(connection); 580 581 // workaround: limit OBEX packet len to L2CAP/RFCOMM MTU 582 maximum_obex_packet_length = btstack_min(maximum_obex_packet_length, connection->bearer_mtu); 583 584 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 585 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 586 return obex_message_builder_response_create_connect(buffer, buffer_len, obex_version_number, flags, maximum_obex_packet_length, (uint32_t) goep_cid); 587 } 588 589 uint8_t goep_server_response_create_general(uint16_t goep_cid, uint8_t opcode){ 590 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 591 if (connection == NULL) { 592 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 593 } 594 goep_server_packet_init(connection); 595 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 596 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 597 return obex_message_builder_response_create_general(buffer, buffer_len, opcode); 598 } 599 600 uint8_t goep_server_header_add_end_of_body(uint16_t goep_cid, const uint8_t * end_of_body, uint16_t length){ 601 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 602 if (connection == NULL) { 603 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 604 } 605 606 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 607 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 608 return obex_message_builder_body_add_static(buffer, buffer_len, end_of_body, length); 609 } 610 611 uint8_t goep_server_header_add_who(uint16_t goep_cid, const uint8_t * target){ 612 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 613 if (connection == NULL) { 614 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 615 } 616 617 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 618 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 619 return obex_message_builder_header_add_who(buffer, buffer_len, target); 620 } 621 622 uint8_t goep_server_header_add_srm_enable(uint16_t goep_cid){ 623 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 624 if (connection == NULL) { 625 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 626 } 627 628 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 629 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 630 return obex_message_builder_header_add_srm_enable(buffer, buffer_len); 631 } 632 633 uint8_t goep_server_execute(uint16_t goep_cid){ 634 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 635 if (connection == NULL) { 636 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 637 } 638 639 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 640 uint16_t pos = big_endian_read_16(buffer, 1); 641 switch (connection->type) { 642 #ifdef ENABLE_GOEP_L2CAP 643 case GOEP_CONNECTION_L2CAP: 644 return l2cap_send(connection->bearer_cid, buffer, pos); 645 break; 646 #endif 647 case GOEP_CONNECTION_RFCOMM: 648 return rfcomm_send_prepared(connection->bearer_cid, pos); 649 break; 650 default: 651 btstack_unreachable(); 652 return ERROR_CODE_SUCCESS; 653 } 654 } 655 656 void goep_server_deinit(void){ 657 goep_server_cid_counter = 0; 658 goep_server_services = NULL; 659 } 660