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 2, 67 2, 68 1, // 16-bit FCS 69 }; 70 71 static uint8_t goep_server_l2cap_packet_buffer[1000]; 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 #endif 435 436 // alloc structure 437 service = btstack_memory_goep_server_service_get(); 438 if (service == NULL) { 439 return BTSTACK_MEMORY_ALLOC_FAILED; 440 } 441 442 // fill in 443 service->callback = callback; 444 service->rfcomm_channel = rfcomm_channel; 445 service->l2cap_psm = l2cap_psm; 446 447 uint8_t status = ERROR_CODE_SUCCESS; 448 bool rfcomm_registered = false; 449 450 #ifdef ENABLE_GOEP_L2CAP 451 bool l2cap_registered = false; 452 // register with L2CAP 453 if (l2cap_psm != 0){ 454 status = l2cap_register_service(goep_server_packet_handler_l2cap, l2cap_psm, l2cap_mtu, security_level); 455 if (status == ERROR_CODE_SUCCESS){ 456 l2cap_registered = true; 457 } 458 } 459 #endif 460 461 // register with RFCOMM 462 if (status == ERROR_CODE_SUCCESS){ 463 status = rfcomm_register_service(goep_server_packet_handler_rfcomm, rfcomm_channel, rfcomm_max_frame_size); 464 if (status == ERROR_CODE_SUCCESS){ 465 rfcomm_registered = true; 466 } 467 } 468 469 // add service on success 470 if (status == ERROR_CODE_SUCCESS){ 471 btstack_linked_list_add(&goep_server_services, (btstack_linked_item_t *) service); 472 return ERROR_CODE_SUCCESS; 473 } 474 475 // unrestore otherwise 476 btstack_memory_goep_server_service_free(service); 477 #ifdef ENABLE_GOEP_L2CAP 478 if (l2cap_registered){ 479 l2cap_unregister_service(l2cap_psm); 480 } 481 #endif 482 if (rfcomm_registered){ 483 rfcomm_unregister_service(rfcomm_channel); 484 } 485 return status; 486 } 487 488 uint8_t goep_server_accept_connection(uint16_t goep_cid){ 489 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 490 if (connection == NULL){ 491 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 492 } 493 if (connection->state != GOEP_SERVER_W4_ACCEPT_REJECT){ 494 return ERROR_CODE_COMMAND_DISALLOWED; 495 } 496 connection->state = GOEP_SERVER_W4_CONNECTED; 497 #ifdef ENABLE_GOEP_L2CAP 498 if (connection->type == GOEP_CONNECTION_L2CAP){ 499 return l2cap_ertm_accept_connection(connection->bearer_cid, &ertm_config, connection->ertm_buffer, GOEP_SERVER_ERTM_BUFFER); 500 } 501 #endif 502 return rfcomm_accept_connection(connection->bearer_cid); 503 } 504 505 uint8_t goep_server_decline_connection(uint16_t goep_cid){ 506 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 507 if (connection == NULL){ 508 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 509 } 510 connection->state = GOEP_SERVER_W4_CONNECTED; 511 if (connection->state != GOEP_SERVER_W4_ACCEPT_REJECT){ 512 return ERROR_CODE_COMMAND_DISALLOWED; 513 } 514 #ifdef ENABLE_GOEP_L2CAP 515 if (connection->type == GOEP_CONNECTION_L2CAP){ 516 l2cap_decline_connection(connection->bearer_cid); 517 return ERROR_CODE_SUCCESS; 518 } 519 #endif 520 return rfcomm_decline_connection(connection->bearer_cid); 521 } 522 523 uint8_t goep_server_request_can_send_now(uint16_t goep_cid){ 524 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 525 if (connection == NULL){ 526 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 527 } 528 529 btstack_assert(connection->state == GOEP_SERVER_CONNECTED); 530 531 switch (connection->type){ 532 case GOEP_CONNECTION_RFCOMM: 533 rfcomm_request_can_send_now_event(connection->bearer_cid); 534 break; 535 #ifdef ENABLE_GOEP_L2CAP 536 case GOEP_CONNECTION_L2CAP: 537 l2cap_request_can_send_now_event(connection->bearer_cid); 538 break; 539 #endif 540 default: 541 btstack_unreachable(); 542 break; 543 } 544 return ERROR_CODE_SUCCESS; 545 } 546 547 static uint8_t * goep_server_get_outgoing_buffer(goep_server_connection_t * connection){ 548 switch (connection->type){ 549 #ifdef ENABLE_GOEP_L2CAP 550 case GOEP_CONNECTION_L2CAP: 551 return goep_server_l2cap_packet_buffer; 552 #endif 553 case GOEP_CONNECTION_RFCOMM: 554 return rfcomm_get_outgoing_buffer(); 555 default: 556 btstack_unreachable(); 557 return NULL; 558 } 559 } 560 561 static uint16_t goep_server_get_outgoing_buffer_len(goep_server_connection_t * connection){ 562 return connection->bearer_mtu; 563 } 564 565 static void goep_server_packet_init(goep_server_connection_t * connection){ 566 btstack_assert(connection->state == GOEP_SERVER_CONNECTED); 567 switch (connection->type){ 568 #ifdef ENABLE_GOEP_L2CAP 569 case GOEP_CONNECTION_L2CAP: 570 break; 571 #endif 572 case GOEP_CONNECTION_RFCOMM: 573 rfcomm_reserve_packet_buffer(); 574 break; 575 default: 576 btstack_unreachable(); 577 break; 578 } 579 connection->state = GOEP_SERVER_OUTGOING_BUFFER_RESERVED; 580 } 581 582 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){ 583 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 584 if (connection == NULL) { 585 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 586 } 587 588 goep_server_packet_init(connection); 589 590 // workaround: limit OBEX packet len to L2CAP/RFCOMM MTU 591 maximum_obex_packet_length = btstack_min(maximum_obex_packet_length, connection->bearer_mtu); 592 593 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 594 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 595 return obex_message_builder_response_create_connect(buffer, buffer_len, obex_version_number, flags, maximum_obex_packet_length, (uint32_t) goep_cid); 596 } 597 598 uint8_t goep_server_response_create_general(uint16_t goep_cid){ 599 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 600 if (connection == NULL) { 601 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 602 } 603 goep_server_packet_init(connection); 604 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 605 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 606 return obex_message_builder_response_create_general(buffer, buffer_len, OBEX_RESP_SUCCESS); 607 } 608 609 uint16_t goep_server_response_get_max_message_size(uint16_t goep_cid){ 610 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 611 if (connection == NULL) { 612 return 0; 613 } 614 return goep_server_get_outgoing_buffer_len(connection); 615 } 616 617 uint8_t goep_server_header_add_end_of_body(uint16_t goep_cid, const uint8_t * end_of_body, uint16_t length){ 618 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 619 if (connection == NULL) { 620 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 621 } 622 623 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 624 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 625 return obex_message_builder_body_add_static(buffer, buffer_len, end_of_body, length); 626 } 627 628 uint8_t goep_server_header_add_who(uint16_t goep_cid, const uint8_t * target){ 629 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 630 if (connection == NULL) { 631 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 632 } 633 634 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 635 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 636 return obex_message_builder_header_add_who(buffer, buffer_len, target); 637 } 638 639 uint8_t goep_server_header_add_srm_enable(uint16_t goep_cid){ 640 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 641 if (connection == NULL) { 642 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 643 } 644 645 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 646 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 647 return obex_message_builder_header_add_srm_enable(buffer, buffer_len); 648 } 649 650 uint8_t goep_server_header_add_application_parameters(uint16_t goep_cid, const uint8_t * data, uint16_t length){ 651 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 652 if (connection == NULL) { 653 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 654 } 655 656 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 657 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 658 return obex_message_builder_header_add_application_parameters(buffer, buffer_len, data, length); 659 } 660 661 uint8_t goep_server_execute(uint16_t goep_cid, uint8_t response_code){ 662 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 663 if (connection == NULL) { 664 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 665 } 666 667 btstack_assert(connection->state == GOEP_SERVER_OUTGOING_BUFFER_RESERVED); 668 669 connection->state = GOEP_SERVER_CONNECTED; 670 671 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 672 // set response code 673 buffer[0] = response_code; 674 uint16_t pos = big_endian_read_16(buffer, 1); 675 switch (connection->type) { 676 #ifdef ENABLE_GOEP_L2CAP 677 case GOEP_CONNECTION_L2CAP: 678 return l2cap_send(connection->bearer_cid, buffer, pos); 679 break; 680 #endif 681 case GOEP_CONNECTION_RFCOMM: 682 return rfcomm_send_prepared(connection->bearer_cid, pos); 683 break; 684 default: 685 btstack_unreachable(); 686 return ERROR_CODE_SUCCESS; 687 } 688 } 689 690 void goep_server_deinit(void){ 691 goep_server_cid_counter = 0; 692 goep_server_services = NULL; 693 } 694