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.h" 55 #include "classic/obex_message_builder.h" 56 57 #ifdef ENABLE_GOEP_L2CAP 58 #include "l2cap.h" 59 60 static l2cap_ertm_config_t ertm_config = { 61 1, // ertm mandatory 62 2, // max transmit, some tests require > 1 63 2000, 64 12000, 65 (GOEP_SERVER_ERTM_BUFFER / 2), // l2cap ertm mtu 66 4, 67 4, 68 1, // 16-bit FCS 69 }; 70 71 static uint8_t goep_server_l2cap_packet_buffer[GOEP_SERVER_ERTM_BUFFER]; 72 73 #endif 74 75 static btstack_linked_list_t goep_server_connections = NULL; 76 static btstack_linked_list_t goep_server_services = NULL; 77 static uint16_t goep_server_cid_counter = 0; 78 79 static goep_server_service_t * goep_server_get_service_for_rfcomm_channel(uint8_t rfcomm_channel){ 80 btstack_linked_item_t *it; 81 for (it = (btstack_linked_item_t *) goep_server_services; it ; it = it->next){ 82 goep_server_service_t * service = ((goep_server_service_t *) it); 83 if (service->rfcomm_channel == rfcomm_channel){ 84 return service; 85 }; 86 } 87 return NULL; 88 } 89 90 #ifdef ENABLE_GOEP_L2CAP 91 static goep_server_service_t * goep_server_get_service_for_l2cap_psm(uint16_t l2cap_psm){ 92 btstack_linked_item_t *it; 93 for (it = (btstack_linked_item_t *) goep_server_services; it ; it = it->next){ 94 goep_server_service_t * service = ((goep_server_service_t *) it); 95 if (service->l2cap_psm == l2cap_psm){ 96 return service; 97 }; 98 } 99 return NULL; 100 } 101 #endif 102 103 static goep_server_connection_t * goep_server_get_connection_for_rfcomm_cid(uint16_t bearer_cid){ 104 btstack_linked_item_t *it; 105 for (it = (btstack_linked_item_t *) goep_server_connections; it ; it = it->next){ 106 goep_server_connection_t * connection = ((goep_server_connection_t *) it); 107 if (connection->type != GOEP_CONNECTION_RFCOMM) continue; 108 if (connection->bearer_cid == bearer_cid){ 109 return connection; 110 }; 111 } 112 return NULL; 113 } 114 115 #ifdef ENABLE_GOEP_L2CAP 116 static goep_server_connection_t * goep_server_get_connection_for_l2cap_cid(uint16_t bearer_cid){ 117 btstack_linked_item_t *it; 118 for (it = (btstack_linked_item_t *) goep_server_connections; it ; it = it->next){ 119 goep_server_connection_t * connection = ((goep_server_connection_t *) it); 120 if (connection->type != GOEP_CONNECTION_L2CAP) continue; 121 if (connection->bearer_cid == bearer_cid){ 122 return connection; 123 }; 124 } 125 return NULL; 126 } 127 #endif 128 129 static goep_server_connection_t * goep_server_get_connection_for_goep_cid(uint16_t goep_cid){ 130 btstack_linked_item_t *it; 131 for (it = (btstack_linked_item_t *) goep_server_connections; it ; it = it->next){ 132 goep_server_connection_t * connection = ((goep_server_connection_t *) it); 133 if (connection->goep_cid == goep_cid){ 134 return connection; 135 }; 136 } 137 return NULL; 138 } 139 140 static uint16_t goep_server_get_next_goep_cid(void){ 141 goep_server_cid_counter++; 142 if (goep_server_cid_counter == 0){ 143 goep_server_cid_counter = 1; 144 } 145 return goep_server_cid_counter; 146 } 147 148 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){ 149 uint8_t event[13]; 150 uint16_t pos = 0; 151 event[pos++] = HCI_EVENT_GOEP_META; 152 event[pos++] = 15 - 2; 153 event[pos++] = GOEP_SUBEVENT_INCOMING_CONNECTION; 154 little_endian_store_16(event, pos, goep_cid); 155 pos+=2; 156 memcpy(&event[pos], bd_addr, 6); 157 pos += 6; 158 little_endian_store_16(event, pos, con_handle); 159 pos += 2; 160 btstack_assert(pos == sizeof(event)); 161 callback(HCI_EVENT_PACKET, goep_cid, &event[0], pos); 162 } 163 164 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){ 165 uint8_t event[15]; 166 uint16_t pos = 0; 167 event[pos++] = HCI_EVENT_GOEP_META; 168 event[pos++] = 15 - 2; 169 event[pos++] = GOEP_SUBEVENT_CONNECTION_OPENED; 170 little_endian_store_16(event, pos, goep_cid); 171 pos+=2; 172 event[pos++] = status; 173 memcpy(&event[pos], bd_addr, 6); 174 pos += 6; 175 little_endian_store_16(event, pos, con_handle); 176 pos += 2; 177 event[pos++] = 1; 178 btstack_assert(pos == sizeof(event)); 179 callback(HCI_EVENT_PACKET, goep_cid, &event[0], pos); 180 } 181 182 static inline void goep_server_emit_connection_closed(btstack_packet_handler_t callback, uint16_t goep_cid){ 183 uint8_t event[5]; 184 uint16_t pos = 0; 185 event[pos++] = HCI_EVENT_GOEP_META; 186 event[pos++] = 5 - 3; 187 event[pos++] = GOEP_SUBEVENT_CONNECTION_CLOSED; 188 little_endian_store_16(event, pos, goep_cid); 189 pos += 2; 190 btstack_assert(pos == sizeof(event)); 191 callback(HCI_EVENT_PACKET, goep_cid, &event[0], pos); 192 } 193 194 static inline void goep_server_emit_can_send_now_event(goep_server_connection_t * connection){ 195 uint8_t event[5]; 196 uint16_t pos = 0; 197 event[pos++] = HCI_EVENT_GOEP_META; 198 event[pos++] = 5 - 3; 199 event[pos++] = GOEP_SUBEVENT_CAN_SEND_NOW; 200 little_endian_store_16(event,pos,connection->goep_cid); 201 pos += 2; 202 btstack_assert(pos == sizeof(event)); 203 connection->callback(HCI_EVENT_PACKET, connection->goep_cid, &event[0], pos); 204 } 205 206 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){ 207 208 uint16_t goep_cid = context->goep_cid; 209 btstack_packet_handler_t packet_handler = context->callback; 210 211 if (status) { 212 log_info("goep_client: open failed, status %u", status); 213 btstack_linked_list_remove(&goep_server_connections, (btstack_linked_item_t *) context); 214 btstack_memory_goep_server_connection_free(context); 215 } else { 216 // context->bearer_mtu = mtu; 217 context->state = GOEP_SERVER_CONNECTED; 218 context->bearer_cid = bearer_cid; 219 #ifdef ENABLE_GOEP_L2CAP 220 if (context->type == GOEP_CONNECTION_L2CAP){ 221 bearer_mtu = btstack_min(bearer_mtu, sizeof(goep_server_l2cap_packet_buffer)); 222 } 223 #endif 224 context->bearer_mtu = bearer_mtu; 225 log_info("goep_server: connection opened. cid %u, max frame size %u", context->bearer_cid, bearer_mtu); 226 } 227 228 goep_server_emit_connection_opened(packet_handler, goep_cid, addr, con_handle, status); 229 } 230 231 static void goep_server_handle_connection_closed(goep_server_connection_t * goep_connection){ 232 uint16_t goep_cid = goep_connection->goep_cid; 233 btstack_packet_handler_t packet_handler = goep_connection->callback; 234 235 btstack_linked_list_remove(&goep_server_connections, (btstack_linked_item_t *) goep_connection); 236 btstack_memory_goep_server_connection_free(goep_connection); 237 238 goep_server_emit_connection_closed(packet_handler, goep_cid); 239 } 240 241 #ifdef ENABLE_GOEP_L2CAP 242 static void goep_server_packet_handler_l2cap(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 243 UNUSED(channel); 244 UNUSED(size); 245 246 bd_addr_t event_addr; 247 uint16_t l2cap_psm; 248 uint16_t l2cap_cid; 249 goep_server_connection_t * goep_connection; 250 goep_server_service_t * goep_service; 251 252 switch (packet_type){ 253 case HCI_EVENT_PACKET: 254 switch (hci_event_packet_get_type(packet)) { 255 case L2CAP_EVENT_INCOMING_CONNECTION: 256 l2cap_psm = l2cap_event_incoming_connection_get_psm(packet); 257 l2cap_cid = l2cap_event_incoming_connection_get_local_cid(packet); 258 goep_service = goep_server_get_service_for_l2cap_psm(l2cap_psm); 259 if (!goep_service){ 260 l2cap_decline_connection(l2cap_cid); 261 break; 262 } 263 264 // alloc structure 265 goep_connection = btstack_memory_goep_server_connection_get(); 266 if (!goep_connection){ 267 l2cap_decline_connection(l2cap_cid); 268 break; 269 } 270 271 // setup connection 272 goep_connection->goep_cid = goep_server_get_next_goep_cid(); 273 goep_connection->bearer_cid = l2cap_cid; 274 goep_connection->callback = goep_service->callback; 275 goep_connection->type = GOEP_CONNECTION_L2CAP; 276 goep_connection->state = GOEP_SERVER_W4_ACCEPT_REJECT; 277 btstack_linked_list_add(&goep_server_connections, (btstack_linked_item_t *) goep_connection); 278 279 // notify user 280 l2cap_event_incoming_connection_get_address(packet, event_addr); 281 goep_server_emit_incoming_connection(goep_service->callback, goep_connection->goep_cid, event_addr, 282 l2cap_event_incoming_connection_get_handle(packet)); 283 break; 284 285 case L2CAP_EVENT_CHANNEL_OPENED: 286 l2cap_cid = l2cap_event_channel_opened_get_local_cid(packet); 287 goep_connection = goep_server_get_connection_for_l2cap_cid(l2cap_cid); 288 btstack_assert(goep_connection != NULL); 289 btstack_assert(goep_connection->state == GOEP_SERVER_W4_CONNECTED); 290 l2cap_event_channel_opened_get_address(packet, event_addr); 291 goep_server_handle_connection_opened(goep_connection, event_addr, 292 l2cap_event_channel_opened_get_handle(packet), 293 l2cap_event_channel_opened_get_status(packet), 294 l2cap_cid, 295 l2cap_event_channel_opened_get_remote_mtu(packet) ); 296 return; 297 case L2CAP_EVENT_CAN_SEND_NOW: 298 l2cap_cid = l2cap_event_can_send_now_get_local_cid(packet); 299 goep_connection = goep_server_get_connection_for_l2cap_cid(l2cap_cid); 300 btstack_assert(goep_connection != NULL); 301 goep_server_emit_can_send_now_event(goep_connection); 302 break; 303 case L2CAP_EVENT_CHANNEL_CLOSED: 304 l2cap_cid = l2cap_event_channel_closed_get_local_cid(packet); 305 goep_connection = goep_server_get_connection_for_l2cap_cid(l2cap_cid); 306 btstack_assert(goep_connection != NULL); 307 goep_server_handle_connection_closed(goep_connection); 308 break; 309 default: 310 break; 311 } 312 break; 313 case L2CAP_DATA_PACKET: 314 goep_connection = goep_server_get_connection_for_l2cap_cid(channel); 315 btstack_assert(goep_connection != NULL); 316 goep_connection->callback(GOEP_DATA_PACKET, goep_connection->goep_cid, packet, size); 317 break; 318 default: 319 break; 320 } 321 } 322 #endif 323 324 static void goep_server_packet_handler_rfcomm(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 325 UNUSED(channel); 326 UNUSED(size); 327 328 bd_addr_t event_addr; 329 uint8_t rfcomm_channel; 330 uint16_t rfcomm_cid; 331 goep_server_service_t * goep_service; 332 goep_server_connection_t * goep_connection; 333 334 switch (packet_type){ 335 case HCI_EVENT_PACKET: 336 switch (hci_event_packet_get_type(packet)) { 337 case RFCOMM_EVENT_INCOMING_CONNECTION: 338 rfcomm_channel = rfcomm_event_incoming_connection_get_server_channel(packet); 339 rfcomm_cid = rfcomm_event_incoming_connection_get_rfcomm_cid(packet); 340 341 goep_service = goep_server_get_service_for_rfcomm_channel(rfcomm_channel); 342 if (!goep_service){ 343 rfcomm_decline_connection(rfcomm_cid); 344 break; 345 } 346 347 // alloc structure 348 goep_connection = btstack_memory_goep_server_connection_get(); 349 if (!goep_connection){ 350 rfcomm_decline_connection(rfcomm_cid); 351 break; 352 } 353 354 // setup connection 355 goep_connection->goep_cid = goep_server_get_next_goep_cid(); 356 goep_connection->bearer_cid = rfcomm_cid; 357 goep_connection->callback = goep_service->callback; 358 goep_connection->type = GOEP_CONNECTION_RFCOMM; 359 goep_connection->state = GOEP_SERVER_W4_ACCEPT_REJECT; 360 btstack_linked_list_add(&goep_server_connections, (btstack_linked_item_t *) goep_connection); 361 362 // notify user 363 rfcomm_event_incoming_connection_get_bd_addr(packet, event_addr); 364 goep_server_emit_incoming_connection(goep_service->callback, goep_connection->goep_cid, event_addr, 365 rfcomm_event_incoming_connection_get_con_handle(packet)); 366 break; 367 368 case RFCOMM_EVENT_CHANNEL_OPENED: 369 rfcomm_cid = rfcomm_event_channel_opened_get_rfcomm_cid(packet); 370 goep_connection = goep_server_get_connection_for_rfcomm_cid(rfcomm_cid); 371 btstack_assert(goep_connection != NULL); 372 btstack_assert(goep_connection->state == GOEP_SERVER_W4_CONNECTED); 373 rfcomm_event_channel_opened_get_bd_addr(packet, event_addr); 374 goep_server_handle_connection_opened(goep_connection, event_addr, 375 rfcomm_event_channel_opened_get_con_handle(packet), 376 rfcomm_event_channel_opened_get_status(packet), 377 rfcomm_cid, 378 rfcomm_event_channel_opened_get_max_frame_size(packet) ); 379 break; 380 381 case RFCOMM_EVENT_CAN_SEND_NOW: 382 rfcomm_cid = rfcomm_event_can_send_now_get_rfcomm_cid(packet); 383 goep_connection = goep_server_get_connection_for_rfcomm_cid(rfcomm_cid); 384 btstack_assert(goep_connection != NULL); 385 goep_server_emit_can_send_now_event(goep_connection); 386 break; 387 388 case RFCOMM_EVENT_CHANNEL_CLOSED: 389 rfcomm_cid = rfcomm_event_channel_closed_get_rfcomm_cid(packet); 390 goep_connection = goep_server_get_connection_for_rfcomm_cid(rfcomm_cid); 391 btstack_assert(goep_connection != NULL); 392 goep_server_handle_connection_closed(goep_connection); 393 break; 394 395 default: 396 break; 397 } 398 break; 399 400 case RFCOMM_DATA_PACKET: 401 goep_connection = goep_server_get_connection_for_rfcomm_cid(channel); 402 btstack_assert(goep_connection != NULL); 403 goep_connection->callback(GOEP_DATA_PACKET, goep_connection->goep_cid, packet, size); 404 break; 405 406 default: 407 break; 408 } 409 } 410 411 void goep_server_init(void){ 412 } 413 414 uint8_t goep_server_register_service(btstack_packet_handler_t callback, uint8_t rfcomm_channel, uint16_t rfcomm_max_frame_size, 415 uint16_t l2cap_psm, uint16_t l2cap_mtu, gap_security_level_t security_level){ 416 417 log_info("rfcomm_channel 0x%02x rfcomm_max_frame_size %u l2cap_psm 0x%02x l2cap_mtu %u", 418 rfcomm_channel, rfcomm_max_frame_size, l2cap_psm, l2cap_mtu); 419 420 // check if service is already registered 421 goep_server_service_t * service; 422 service = goep_server_get_service_for_rfcomm_channel(rfcomm_channel); 423 if (service != NULL) { 424 return RFCOMM_CHANNEL_ALREADY_REGISTERED; 425 } 426 427 #ifdef ENABLE_GOEP_L2CAP 428 if (l2cap_psm != 0){ 429 service = goep_server_get_service_for_l2cap_psm(l2cap_psm); 430 if (service != NULL) { 431 return L2CAP_SERVICE_ALREADY_REGISTERED; 432 } 433 } 434 #else 435 UNUSED(l2cap_mtu); 436 UNUSED(l2cap_psm); 437 UNUSED(security_level); 438 #endif 439 440 // alloc structure 441 service = btstack_memory_goep_server_service_get(); 442 if (service == NULL) { 443 return BTSTACK_MEMORY_ALLOC_FAILED; 444 } 445 446 // fill in 447 service->callback = callback; 448 service->rfcomm_channel = rfcomm_channel; 449 service->l2cap_psm = l2cap_psm; 450 451 uint8_t status = ERROR_CODE_SUCCESS; 452 bool rfcomm_registered = false; 453 454 #ifdef ENABLE_GOEP_L2CAP 455 bool l2cap_registered = false; 456 // register with L2CAP 457 if (l2cap_psm != 0){ 458 status = l2cap_register_service(goep_server_packet_handler_l2cap, l2cap_psm, l2cap_mtu, security_level); 459 if (status == ERROR_CODE_SUCCESS){ 460 l2cap_registered = true; 461 } 462 } 463 #endif 464 465 // register with RFCOMM 466 if (status == ERROR_CODE_SUCCESS){ 467 status = rfcomm_register_service(goep_server_packet_handler_rfcomm, rfcomm_channel, rfcomm_max_frame_size); 468 if (status == ERROR_CODE_SUCCESS){ 469 rfcomm_registered = true; 470 } 471 } 472 473 // add service on success 474 if (status == ERROR_CODE_SUCCESS){ 475 btstack_linked_list_add(&goep_server_services, (btstack_linked_item_t *) service); 476 return ERROR_CODE_SUCCESS; 477 } 478 479 // unrestore otherwise 480 btstack_memory_goep_server_service_free(service); 481 #ifdef ENABLE_GOEP_L2CAP 482 if (l2cap_registered){ 483 l2cap_unregister_service(l2cap_psm); 484 } 485 #endif 486 if (rfcomm_registered){ 487 rfcomm_unregister_service(rfcomm_channel); 488 } 489 return status; 490 } 491 492 uint8_t goep_server_accept_connection(uint16_t goep_cid){ 493 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 494 if (connection == NULL){ 495 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 496 } 497 if (connection->state != GOEP_SERVER_W4_ACCEPT_REJECT){ 498 return ERROR_CODE_COMMAND_DISALLOWED; 499 } 500 connection->state = GOEP_SERVER_W4_CONNECTED; 501 #ifdef ENABLE_GOEP_L2CAP 502 if (connection->type == GOEP_CONNECTION_L2CAP){ 503 return l2cap_ertm_accept_connection(connection->bearer_cid, &ertm_config, connection->ertm_buffer, GOEP_SERVER_ERTM_BUFFER); 504 } 505 #endif 506 return rfcomm_accept_connection(connection->bearer_cid); 507 } 508 509 uint8_t goep_server_decline_connection(uint16_t goep_cid){ 510 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 511 if (connection == NULL){ 512 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 513 } 514 connection->state = GOEP_SERVER_W4_CONNECTED; 515 if (connection->state != GOEP_SERVER_W4_ACCEPT_REJECT){ 516 return ERROR_CODE_COMMAND_DISALLOWED; 517 } 518 #ifdef ENABLE_GOEP_L2CAP 519 if (connection->type == GOEP_CONNECTION_L2CAP){ 520 l2cap_decline_connection(connection->bearer_cid); 521 return ERROR_CODE_SUCCESS; 522 } 523 #endif 524 return rfcomm_decline_connection(connection->bearer_cid); 525 } 526 527 uint8_t goep_server_request_can_send_now(uint16_t goep_cid){ 528 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 529 if (connection == NULL){ 530 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 531 } 532 533 btstack_assert(connection->state == GOEP_SERVER_CONNECTED); 534 535 switch (connection->type){ 536 case GOEP_CONNECTION_RFCOMM: 537 rfcomm_request_can_send_now_event(connection->bearer_cid); 538 break; 539 #ifdef ENABLE_GOEP_L2CAP 540 case GOEP_CONNECTION_L2CAP: 541 l2cap_request_can_send_now_event(connection->bearer_cid); 542 break; 543 #endif 544 default: 545 btstack_unreachable(); 546 break; 547 } 548 return ERROR_CODE_SUCCESS; 549 } 550 551 static uint8_t * goep_server_get_outgoing_buffer(goep_server_connection_t * connection){ 552 switch (connection->type){ 553 #ifdef ENABLE_GOEP_L2CAP 554 case GOEP_CONNECTION_L2CAP: 555 return goep_server_l2cap_packet_buffer; 556 #endif 557 case GOEP_CONNECTION_RFCOMM: 558 return rfcomm_get_outgoing_buffer(); 559 default: 560 btstack_unreachable(); 561 return NULL; 562 } 563 } 564 565 static uint16_t goep_server_get_outgoing_buffer_len(goep_server_connection_t * connection){ 566 return connection->bearer_mtu; 567 } 568 569 static void goep_server_packet_init(goep_server_connection_t * connection){ 570 btstack_assert(connection->state == GOEP_SERVER_CONNECTED); 571 switch (connection->type){ 572 #ifdef ENABLE_GOEP_L2CAP 573 case GOEP_CONNECTION_L2CAP: 574 break; 575 #endif 576 case GOEP_CONNECTION_RFCOMM: 577 rfcomm_reserve_packet_buffer(); 578 break; 579 default: 580 btstack_unreachable(); 581 break; 582 } 583 connection->state = GOEP_SERVER_OUTGOING_BUFFER_RESERVED; 584 } 585 586 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){ 587 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 588 if (connection == NULL) { 589 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 590 } 591 592 goep_server_packet_init(connection); 593 594 // workaround: limit OBEX packet len to L2CAP/RFCOMM MTU 595 maximum_obex_packet_length = btstack_min(maximum_obex_packet_length, connection->bearer_mtu); 596 597 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 598 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 599 return obex_message_builder_response_create_connect(buffer, buffer_len, obex_version_number, flags, maximum_obex_packet_length, (uint32_t) goep_cid); 600 } 601 602 uint8_t goep_server_response_create_general(uint16_t goep_cid){ 603 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 604 if (connection == NULL) { 605 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 606 } 607 goep_server_packet_init(connection); 608 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 609 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 610 return obex_message_builder_response_create_general(buffer, buffer_len, OBEX_RESP_SUCCESS); 611 } 612 613 uint16_t goep_server_response_get_max_message_size(uint16_t goep_cid){ 614 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 615 if (connection == NULL) { 616 return 0; 617 } 618 return goep_server_get_outgoing_buffer_len(connection); 619 } 620 621 uint8_t goep_server_header_add_end_of_body(uint16_t goep_cid, const uint8_t * end_of_body, uint16_t length){ 622 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 623 if (connection == NULL) { 624 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 625 } 626 627 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 628 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 629 return obex_message_builder_body_add_static(buffer, buffer_len, end_of_body, length); 630 } 631 632 uint8_t goep_server_header_add_who(uint16_t goep_cid, const uint8_t * target){ 633 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 634 if (connection == NULL) { 635 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 636 } 637 638 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 639 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 640 return obex_message_builder_header_add_who(buffer, buffer_len, target); 641 } 642 643 uint8_t goep_server_header_add_srm_enable(uint16_t goep_cid){ 644 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 645 if (connection == NULL) { 646 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 647 } 648 649 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 650 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 651 return obex_message_builder_header_add_srm_enable(buffer, buffer_len); 652 } 653 654 uint8_t goep_server_header_add_application_parameters(uint16_t goep_cid, const uint8_t * data, uint16_t length){ 655 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 656 if (connection == NULL) { 657 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 658 } 659 660 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 661 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 662 return obex_message_builder_header_add_application_parameters(buffer, buffer_len, data, length); 663 } 664 665 uint8_t goep_server_execute(uint16_t goep_cid, uint8_t response_code){ 666 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 667 if (connection == NULL) { 668 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 669 } 670 671 btstack_assert(connection->state == GOEP_SERVER_OUTGOING_BUFFER_RESERVED); 672 673 connection->state = GOEP_SERVER_CONNECTED; 674 675 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 676 // set response code 677 buffer[0] = response_code; 678 uint16_t pos = big_endian_read_16(buffer, 1); 679 switch (connection->type) { 680 #ifdef ENABLE_GOEP_L2CAP 681 case GOEP_CONNECTION_L2CAP: 682 return l2cap_send(connection->bearer_cid, buffer, pos); 683 break; 684 #endif 685 case GOEP_CONNECTION_RFCOMM: 686 return rfcomm_send_prepared(connection->bearer_cid, pos); 687 default: 688 btstack_unreachable(); 689 return ERROR_CODE_SUCCESS; 690 } 691 } 692 693 uint8_t goep_server_disconnect(uint16_t goep_cid){ 694 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 695 if (connection == NULL) { 696 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 697 } 698 699 if (connection->state < GOEP_SERVER_CONNECTED){ 700 return ERROR_CODE_COMMAND_DISALLOWED; 701 } 702 703 switch (connection->type) { 704 #ifdef ENABLE_GOEP_L2CAP 705 case GOEP_CONNECTION_L2CAP: 706 return l2cap_disconnect(connection->bearer_cid); 707 #endif 708 case GOEP_CONNECTION_RFCOMM: 709 return rfcomm_disconnect(connection->bearer_cid); 710 default: 711 btstack_unreachable(); 712 break; 713 } 714 return ERROR_CODE_SUCCESS; 715 } 716 717 void goep_server_deinit(void){ 718 goep_server_cid_counter = 0; 719 goep_server_services = NULL; 720 } 721