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 switch (connection->type){ 530 case GOEP_CONNECTION_RFCOMM: 531 rfcomm_request_can_send_now_event(connection->bearer_cid); 532 break; 533 #ifdef ENABLE_GOEP_L2CAP 534 case GOEP_CONNECTION_L2CAP: 535 l2cap_request_can_send_now_event(connection->bearer_cid); 536 break; 537 #endif 538 default: 539 btstack_unreachable(); 540 break; 541 } 542 return ERROR_CODE_SUCCESS; 543 } 544 545 static uint8_t * goep_server_get_outgoing_buffer(goep_server_connection_t * connection){ 546 switch (connection->type){ 547 #ifdef ENABLE_GOEP_L2CAP 548 case GOEP_CONNECTION_L2CAP: 549 return goep_server_l2cap_packet_buffer; 550 #endif 551 case GOEP_CONNECTION_RFCOMM: 552 return rfcomm_get_outgoing_buffer(); 553 default: 554 btstack_unreachable(); 555 return NULL; 556 } 557 } 558 559 static uint16_t goep_server_get_outgoing_buffer_len(goep_server_connection_t * connection){ 560 return connection->bearer_mtu; 561 } 562 563 static void goep_server_packet_init(goep_server_connection_t * connection){ 564 switch (connection->type){ 565 #ifdef ENABLE_GOEP_L2CAP 566 case GOEP_CONNECTION_L2CAP: 567 break; 568 #endif 569 case GOEP_CONNECTION_RFCOMM: 570 rfcomm_reserve_packet_buffer(); 571 break; 572 default: 573 btstack_unreachable(); 574 break; 575 } 576 } 577 578 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){ 579 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 580 if (connection == NULL) { 581 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 582 } 583 584 goep_server_packet_init(connection); 585 586 // workaround: limit OBEX packet len to L2CAP/RFCOMM MTU 587 maximum_obex_packet_length = btstack_min(maximum_obex_packet_length, connection->bearer_mtu); 588 589 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 590 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 591 return obex_message_builder_response_create_connect(buffer, buffer_len, obex_version_number, flags, maximum_obex_packet_length, (uint32_t) goep_cid); 592 } 593 594 uint8_t goep_server_response_create_general(uint16_t goep_cid){ 595 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 596 if (connection == NULL) { 597 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 598 } 599 goep_server_packet_init(connection); 600 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 601 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 602 return obex_message_builder_response_create_general(buffer, buffer_len, OBEX_RESP_SUCCESS); 603 } 604 605 uint16_t goep_server_response_get_max_body_size(uint16_t goep_cid){ 606 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 607 if (connection == NULL) { 608 return 0; 609 } 610 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 611 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 612 uint16_t pos = big_endian_read_16(buffer, 1); 613 return buffer_len - pos; 614 } 615 616 uint8_t goep_server_header_add_end_of_body(uint16_t goep_cid, const uint8_t * end_of_body, uint16_t length){ 617 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 618 if (connection == NULL) { 619 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 620 } 621 622 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 623 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 624 return obex_message_builder_body_add_static(buffer, buffer_len, end_of_body, length); 625 } 626 627 uint8_t goep_server_header_add_who(uint16_t goep_cid, const uint8_t * target){ 628 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 629 if (connection == NULL) { 630 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 631 } 632 633 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 634 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 635 return obex_message_builder_header_add_who(buffer, buffer_len, target); 636 } 637 638 uint8_t goep_server_header_add_srm_enable(uint16_t goep_cid){ 639 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 640 if (connection == NULL) { 641 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 642 } 643 644 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 645 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 646 return obex_message_builder_header_add_srm_enable(buffer, buffer_len); 647 } 648 649 uint8_t goep_server_header_add_application_parameters(uint16_t goep_cid, const uint8_t * data, uint16_t length){ 650 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 651 if (connection == NULL) { 652 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 653 } 654 655 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 656 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection); 657 return obex_message_builder_header_add_application_parameters(buffer, buffer_len, data, length); 658 } 659 660 uint8_t goep_server_execute(uint16_t goep_cid, uint8_t response_code){ 661 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid); 662 if (connection == NULL) { 663 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 664 } 665 666 uint8_t * buffer = goep_server_get_outgoing_buffer(connection); 667 // set reponse code 668 buffer[0] = response_code; 669 uint16_t pos = big_endian_read_16(buffer, 1); 670 switch (connection->type) { 671 #ifdef ENABLE_GOEP_L2CAP 672 case GOEP_CONNECTION_L2CAP: 673 return l2cap_send(connection->bearer_cid, buffer, pos); 674 break; 675 #endif 676 case GOEP_CONNECTION_RFCOMM: 677 return rfcomm_send_prepared(connection->bearer_cid, pos); 678 break; 679 default: 680 btstack_unreachable(); 681 return ERROR_CODE_SUCCESS; 682 } 683 } 684 685 void goep_server_deinit(void){ 686 goep_server_cid_counter = 0; 687 goep_server_services = NULL; 688 } 689