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
goep_server_get_service_for_rfcomm_channel(uint8_t rfcomm_channel)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
goep_server_get_service_for_l2cap_psm(uint16_t l2cap_psm)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
goep_server_get_connection_for_rfcomm_cid(uint16_t bearer_cid)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
goep_server_get_connection_for_l2cap_cid(uint16_t bearer_cid)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
goep_server_get_connection_for_goep_cid(uint16_t goep_cid)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
goep_server_get_next_goep_cid(void)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
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)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 reverse_bd_addr(bd_addr, &event[pos]);
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
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)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 reverse_bd_addr(bd_addr, &event[pos]);
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
goep_server_emit_connection_closed(btstack_packet_handler_t callback,uint16_t goep_cid)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
goep_server_emit_can_send_now_event(goep_server_connection_t * connection)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
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)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
goep_server_handle_connection_closed(goep_server_connection_t * goep_connection)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
goep_server_packet_handler_l2cap(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)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
goep_server_packet_handler_rfcomm(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)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
goep_server_init(void)411 void goep_server_init(void){
412 }
413
goep_server_register_service(btstack_packet_handler_t callback,uint8_t rfcomm_channel,uint16_t rfcomm_max_frame_size,uint16_t l2cap_psm,uint16_t l2cap_mtu,gap_security_level_t security_level)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
goep_server_accept_connection(uint16_t goep_cid)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
goep_server_decline_connection(uint16_t goep_cid)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
goep_server_request_can_send_now(uint16_t goep_cid)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
goep_server_get_outgoing_buffer(goep_server_connection_t * connection)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
goep_server_get_outgoing_buffer_len(goep_server_connection_t * connection)565 static uint16_t goep_server_get_outgoing_buffer_len(goep_server_connection_t * connection){
566 return connection->bearer_mtu;
567 }
568
goep_server_packet_init(goep_server_connection_t * connection)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
goep_server_response_create_connect(uint16_t goep_cid,uint8_t obex_version_number,uint8_t flags,uint16_t maximum_obex_packet_length)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
goep_server_response_create_general(uint16_t goep_cid)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
goep_server_response_get_max_message_size(uint16_t goep_cid)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
goep_server_header_add_end_of_body(uint16_t goep_cid,const uint8_t * end_of_body,uint16_t length)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
goep_server_header_add_who(uint16_t goep_cid,const uint8_t * target)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
goep_server_header_add_srm_enable(uint16_t goep_cid)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
goep_server_header_add_srm_enable_wait(uint16_t goep_cid)654 uint8_t goep_server_header_add_srm_enable_wait(uint16_t goep_cid) {
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_srm_enable(buffer, buffer_len)
663 || obex_message_builder_header_add_srmp_wait(buffer, buffer_len);
664 }
665
goep_server_header_add_name(uint16_t goep_cid,const char * name)666 uint8_t goep_server_header_add_name(uint16_t goep_cid, const char* name) {
667
668 if (name == NULL) {
669 return OBEX_UNKNOWN_ERROR;
670 }
671
672 goep_server_connection_t* connection = goep_server_get_connection_for_goep_cid(goep_cid);
673 if (connection == NULL) {
674 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
675 }
676
677 uint8_t* buffer = goep_server_get_outgoing_buffer(connection);
678 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection);
679 return obex_message_builder_header_add_name(buffer, buffer_len, name);
680 }
681
goep_server_header_add_type(uint16_t goep_cid,const char * type)682 uint8_t goep_server_header_add_type(uint16_t goep_cid, const char* type) {
683
684 if (type == NULL) {
685 return OBEX_UNKNOWN_ERROR;
686 }
687
688 goep_server_connection_t* connection = goep_server_get_connection_for_goep_cid(goep_cid);
689 if (connection == NULL) {
690 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
691 }
692
693 uint8_t* buffer = goep_server_get_outgoing_buffer(connection);
694 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection);
695 return obex_message_builder_header_add_type(buffer, buffer_len, type);
696 }
697
goep_server_header_add_application_parameters(uint16_t goep_cid,const uint8_t * data,uint16_t length)698 uint8_t goep_server_header_add_application_parameters(uint16_t goep_cid, const uint8_t * data, uint16_t length){
699 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
700 if (connection == NULL) {
701 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
702 }
703
704 uint8_t * buffer = goep_server_get_outgoing_buffer(connection);
705 uint16_t buffer_len = goep_server_get_outgoing_buffer_len(connection);
706 return obex_message_builder_header_add_application_parameters(buffer, buffer_len, data, length);
707 }
708
goep_server_execute(uint16_t goep_cid,uint8_t response_code)709 uint8_t goep_server_execute(uint16_t goep_cid, uint8_t response_code){
710 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
711 if (connection == NULL) {
712 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
713 }
714
715 btstack_assert(connection->state == GOEP_SERVER_OUTGOING_BUFFER_RESERVED);
716
717 connection->state = GOEP_SERVER_CONNECTED;
718
719 uint8_t * buffer = goep_server_get_outgoing_buffer(connection);
720 // set response code
721 buffer[0] = response_code;
722 uint16_t pos = big_endian_read_16(buffer, 1);
723 switch (connection->type) {
724 #ifdef ENABLE_GOEP_L2CAP
725 case GOEP_CONNECTION_L2CAP:
726 return l2cap_send(connection->bearer_cid, buffer, pos);
727 break;
728 #endif
729 case GOEP_CONNECTION_RFCOMM:
730 return rfcomm_send_prepared(connection->bearer_cid, pos);
731 default:
732 btstack_unreachable();
733 return ERROR_CODE_SUCCESS;
734 }
735 }
736
goep_server_disconnect(uint16_t goep_cid)737 uint8_t goep_server_disconnect(uint16_t goep_cid){
738 goep_server_connection_t * connection = goep_server_get_connection_for_goep_cid(goep_cid);
739 if (connection == NULL) {
740 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
741 }
742
743 if (connection->state < GOEP_SERVER_CONNECTED){
744 return ERROR_CODE_COMMAND_DISALLOWED;
745 }
746
747 switch (connection->type) {
748 #ifdef ENABLE_GOEP_L2CAP
749 case GOEP_CONNECTION_L2CAP:
750 return l2cap_disconnect(connection->bearer_cid);
751 #endif
752 case GOEP_CONNECTION_RFCOMM:
753 return rfcomm_disconnect(connection->bearer_cid);
754 default:
755 btstack_unreachable();
756 break;
757 }
758 return ERROR_CODE_SUCCESS;
759 }
760
goep_server_deinit(void)761 void goep_server_deinit(void){
762 goep_server_cid_counter = 0;
763 goep_server_services = NULL;
764 }
765