xref: /btstack/src/classic/avrcp_browsing.c (revision 2e97cf5e0fc0f38d10df183040a24072e1bba676)
1 /*
2  * Copyright (C) 2016 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 BLUEKITCHEN
24  * GMBH 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__ "avrcp_browsing.c"
39 
40 #include <stdint.h>
41 #include <string.h>
42 
43 #include "bluetooth_psm.h"
44 #include "bluetooth_sdp.h"
45 #include "btstack_debug.h"
46 #include "btstack_event.h"
47 #include "btstack_memory.h"
48 #include "classic/sdp_client.h"
49 #include "classic/sdp_util.h"
50 #include "classic/avrcp_browsing.h"
51 
52 static void avrcp_browsing_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
53 
54 // higher layer callbacks
55 static btstack_packet_handler_t           avrcp_browsing_callback;
56 static btstack_packet_handler_t avrcp_browsing_controller_packet_handler;
57 static btstack_packet_handler_t avrcp_browsing_target_packet_handler;
58 
59 // sdp query
60 static bd_addr_t avrcp_browsing_sdp_addr;
61 static btstack_context_callback_registration_t avrcp_browsing_handle_sdp_client_query_request;
62 
63 static bool avrcp_browsing_l2cap_service_registered;
64 
65 
avrcp_browsing_request_can_send_now(avrcp_browsing_connection_t * connection,uint16_t l2cap_cid)66 void avrcp_browsing_request_can_send_now(avrcp_browsing_connection_t * connection, uint16_t l2cap_cid){
67     connection->wait_to_send = true;
68     l2cap_request_can_send_now_event(l2cap_cid);
69 }
70 
avrcp_retry_timer_timeout_handler(btstack_timer_source_t * timer)71 static void avrcp_retry_timer_timeout_handler(btstack_timer_source_t * timer){
72     uint16_t avrcp_cid = (uint16_t)(uintptr_t) btstack_run_loop_get_timer_context(timer);
73     avrcp_connection_t * connection_controller = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_CONTROLLER, avrcp_cid);
74     if (connection_controller == NULL) return;
75     avrcp_connection_t * connection_target = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid);
76     if (connection_target == NULL) return;
77 
78     if ((connection_controller->browsing_connection == NULL) || (connection_target->browsing_connection == NULL)) return;
79 
80     if (connection_controller->browsing_connection->state == AVCTP_CONNECTION_W2_L2CAP_RETRY){
81         connection_controller->browsing_connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
82         connection_target->browsing_connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
83 
84         l2cap_ertm_create_channel(avrcp_browsing_packet_handler, connection_controller->remote_addr, connection_controller->browsing_l2cap_psm,
85                 &connection_controller->browsing_connection->ertm_config,
86                 connection_controller->browsing_connection->ertm_buffer,
87                 connection_controller->browsing_connection->ertm_buffer_size, NULL);
88     }
89 }
90 
avrcp_retry_timer_start(avrcp_connection_t * connection)91 static void avrcp_retry_timer_start(avrcp_connection_t * connection){
92     btstack_run_loop_set_timer_handler(&connection->retry_timer, avrcp_retry_timer_timeout_handler);
93     btstack_run_loop_set_timer_context(&connection->retry_timer, (void *)(uintptr_t)connection->avrcp_cid);
94 
95     // add some jitter/randomness to reconnect delay
96     uint32_t timeout = 100 + (btstack_run_loop_get_time_ms() & 0x7F);
97     btstack_run_loop_set_timer(&connection->retry_timer, timeout);
98 
99     btstack_run_loop_add_timer(&connection->retry_timer);
100 }
101 
102 // AVRCP Browsing Service functions
avrcp_browsing_finalize_connection(avrcp_connection_t * connection)103 static void avrcp_browsing_finalize_connection(avrcp_connection_t * connection){
104     btstack_run_loop_remove_timer(&connection->retry_timer);
105     btstack_memory_avrcp_browsing_connection_free(connection->browsing_connection);
106     connection->browsing_connection = NULL;
107 }
108 
avrcp_browsing_emit_connection_established(uint16_t browsing_cid,bd_addr_t addr,uint8_t status)109 static void avrcp_browsing_emit_connection_established(uint16_t browsing_cid, bd_addr_t addr, uint8_t status){
110     btstack_assert(avrcp_browsing_callback != NULL);
111 
112     uint8_t event[12];
113     int pos = 0;
114     event[pos++] = HCI_EVENT_AVRCP_META;
115     event[pos++] = sizeof(event) - 2;
116     event[pos++] = AVRCP_SUBEVENT_BROWSING_CONNECTION_ESTABLISHED;
117     event[pos++] = status;
118     reverse_bd_addr(addr,&event[pos]);
119     pos += 6;
120     little_endian_store_16(event, pos, browsing_cid);
121     pos += 2;
122     (*avrcp_browsing_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
123 }
124 
avrcp_browsing_emit_incoming_connection(uint16_t browsing_cid,bd_addr_t addr)125 static void avrcp_browsing_emit_incoming_connection(uint16_t browsing_cid, bd_addr_t addr){
126     btstack_assert(avrcp_browsing_callback != NULL);
127 
128     uint8_t event[11];
129     int pos = 0;
130     event[pos++] = HCI_EVENT_AVRCP_META;
131     event[pos++] = sizeof(event) - 2;
132     event[pos++] = AVRCP_SUBEVENT_INCOMING_BROWSING_CONNECTION;
133     reverse_bd_addr(addr,&event[pos]);
134     pos += 6;
135     little_endian_store_16(event, pos, browsing_cid);
136     pos += 2;
137     (*avrcp_browsing_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
138 }
139 
avrcp_browsing_emit_connection_closed(uint16_t browsing_cid)140 static void avrcp_browsing_emit_connection_closed(uint16_t browsing_cid){
141     btstack_assert(avrcp_browsing_callback != NULL);
142 
143     uint8_t event[5];
144     int pos = 0;
145     event[pos++] = HCI_EVENT_AVRCP_META;
146     event[pos++] = sizeof(event) - 2;
147     event[pos++] = AVRCP_SUBEVENT_BROWSING_CONNECTION_RELEASED;
148     little_endian_store_16(event, pos, browsing_cid);
149     pos += 2;
150     (*avrcp_browsing_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
151 }
152 
153 
avrcp_browsing_create_connection(avrcp_connection_t * avrcp_connection,uint16_t avrcp_browsing_cid)154 static avrcp_browsing_connection_t * avrcp_browsing_create_connection(avrcp_connection_t * avrcp_connection, uint16_t avrcp_browsing_cid){
155     avrcp_browsing_connection_t * browsing_connection = btstack_memory_avrcp_browsing_connection_get();
156     if (!browsing_connection){
157         log_error("Not enough memory to create browsing connection");
158         return NULL;
159     }
160     browsing_connection->state = AVCTP_CONNECTION_IDLE;
161     browsing_connection->transaction_label = 0xFF;
162 
163     avrcp_connection->avrcp_browsing_cid = avrcp_browsing_cid;
164     avrcp_connection->browsing_connection = browsing_connection;
165 
166     log_info("avrcp_browsing_create_connection, avrcp cid 0x%02x", avrcp_connection->avrcp_browsing_cid);
167     return browsing_connection;
168 }
169 
avrcp_browsing_configure_ertm(avrcp_browsing_connection_t * browsing_connection,uint8_t * ertm_buffer,uint32_t ertm_buffer_size,l2cap_ertm_config_t * ertm_config)170 static void avrcp_browsing_configure_ertm(avrcp_browsing_connection_t * browsing_connection, uint8_t * ertm_buffer, uint32_t ertm_buffer_size, l2cap_ertm_config_t * ertm_config){
171     browsing_connection->ertm_buffer = ertm_buffer;
172     browsing_connection->ertm_buffer_size = ertm_buffer_size;
173 
174     if (ertm_buffer_size > 0) {
175         (void)memcpy(&browsing_connection->ertm_config, ertm_config,
176                  sizeof(l2cap_ertm_config_t));
177         log_info("avrcp_browsing_configure_ertm");
178     }
179 }
180 
avrcp_browsing_handle_incoming_connection(avrcp_connection_t * connection,uint16_t local_cid,uint16_t avrcp_browsing_cid)181 static avrcp_browsing_connection_t * avrcp_browsing_handle_incoming_connection(avrcp_connection_t * connection, uint16_t local_cid, uint16_t avrcp_browsing_cid){
182     if (connection->browsing_connection == NULL){
183         avrcp_browsing_create_connection(connection, avrcp_browsing_cid);
184     }
185     if (connection->browsing_connection) {
186         connection->browsing_connection->l2cap_browsing_cid = local_cid;
187         connection->browsing_connection->state = AVCTP_CONNECTION_W4_ERTM_CONFIGURATION;
188         btstack_run_loop_remove_timer(&connection->retry_timer);
189     }
190     return connection->browsing_connection;
191 }
192 
avrcp_browsing_handle_open_connection_for_role(avrcp_connection_t * connection,uint16_t local_cid)193 static void avrcp_browsing_handle_open_connection_for_role(avrcp_connection_t * connection, uint16_t local_cid){
194     connection->browsing_connection->l2cap_browsing_cid = local_cid;
195     connection->browsing_connection->incoming_declined = false;
196     connection->browsing_connection->state = AVCTP_CONNECTION_OPENED;
197     log_info("L2CAP_EVENT_CHANNEL_OPENED browsing_avrcp_cid 0x%02x, l2cap_signaling_cid 0x%02x, role %d", connection->avrcp_cid, connection->l2cap_signaling_cid, connection->role);
198 }
199 
avrcp_get_frame_type(uint8_t header)200 static avrcp_frame_type_t avrcp_get_frame_type(uint8_t header){
201     return (avrcp_frame_type_t)((header & 0x02) >> 1);
202 }
203 
avrcp_browsing_packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)204 static void avrcp_browsing_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
205     UNUSED(channel);
206     UNUSED(size);
207     bd_addr_t event_addr;
208     uint16_t local_cid;
209     uint8_t  status;
210     bool decline_connection;
211     bool outoing_active;
212 
213     avrcp_connection_t * connection_controller;
214     avrcp_connection_t * connection_target;
215 
216     switch (packet_type){
217         case L2CAP_DATA_PACKET:
218             switch (avrcp_get_frame_type(packet[0])){
219                 case AVRCP_RESPONSE_FRAME:
220                     (*avrcp_browsing_controller_packet_handler)(packet_type, channel, packet, size);
221                     break;
222                 case AVRCP_COMMAND_FRAME:
223                 default:    // make compiler happy
224                     (*avrcp_browsing_target_packet_handler)(packet_type, channel, packet, size);
225                     break;
226             }
227             break;
228         case HCI_EVENT_PACKET:
229             btstack_assert(avrcp_browsing_controller_packet_handler != NULL);
230             btstack_assert(avrcp_browsing_target_packet_handler != NULL);
231 
232             switch (hci_event_packet_get_type(packet)) {
233 
234                 case L2CAP_EVENT_INCOMING_CONNECTION:
235                     btstack_assert(avrcp_browsing_controller_packet_handler != NULL);
236                     btstack_assert(avrcp_browsing_target_packet_handler != NULL);
237 
238                     l2cap_event_incoming_connection_get_address(packet, event_addr);
239                     local_cid = l2cap_event_incoming_connection_get_local_cid(packet);
240                     outoing_active = false;
241 
242                     connection_target = avrcp_get_connection_for_bd_addr_for_role(AVRCP_TARGET, event_addr);
243                     connection_controller = avrcp_get_connection_for_bd_addr_for_role(AVRCP_CONTROLLER, event_addr);
244 
245                     if (connection_target == NULL || connection_controller == NULL) {
246                         l2cap_decline_connection(local_cid);
247                         return;
248                     }
249 
250                     if (connection_target->browsing_connection != NULL){
251                         if (connection_target->browsing_connection->state == AVCTP_CONNECTION_W4_L2CAP_CONNECTED){
252                             outoing_active = true;
253                             connection_target->browsing_connection->incoming_declined = true;
254                         }
255                     }
256 
257                     if (connection_controller->browsing_connection != NULL){
258                         if (connection_controller->browsing_connection->state == AVCTP_CONNECTION_W4_L2CAP_CONNECTED) {
259                             outoing_active = true;
260                             connection_controller->browsing_connection->incoming_declined = true;
261                         }
262                     }
263 
264                     decline_connection = outoing_active;
265                     if (decline_connection == false){
266                         uint16_t avrcp_browsing_cid;
267                         if ((connection_controller->browsing_connection == NULL) || (connection_target->browsing_connection == NULL)){
268                             avrcp_browsing_cid = avrcp_get_next_cid(AVRCP_CONTROLLER);
269                         } else {
270                             avrcp_browsing_cid = connection_controller->avrcp_browsing_cid;
271                         }
272 
273                         // create two connection objects (both)
274                         connection_target->browsing_connection     = avrcp_browsing_handle_incoming_connection(connection_target, local_cid, avrcp_browsing_cid);
275                         connection_controller->browsing_connection = avrcp_browsing_handle_incoming_connection(connection_controller, local_cid, avrcp_browsing_cid);
276 
277                         if ((connection_target->browsing_connection  == NULL) || (connection_controller->browsing_connection == NULL)){
278                             decline_connection = true;
279                             if (connection_target->browsing_connection) {
280                                 avrcp_browsing_finalize_connection(connection_target);
281                             }
282                             if (connection_controller->browsing_connection) {
283                                 avrcp_browsing_finalize_connection(connection_controller);
284                             }
285                         }
286                     }
287                     if (decline_connection){
288                         l2cap_decline_connection(local_cid);
289                     } else {
290                         log_info("AVRCP: L2CAP_EVENT_INCOMING_CONNECTION browsing_avrcp_cid 0x%02x", connection_controller->avrcp_browsing_cid);
291                         avrcp_browsing_emit_incoming_connection(connection_controller->avrcp_browsing_cid, event_addr);
292                     }
293                     break;
294 
295                 case L2CAP_EVENT_CHANNEL_OPENED:
296                     l2cap_event_channel_opened_get_address(packet, event_addr);
297                     status = l2cap_event_channel_opened_get_status(packet);
298                     local_cid = l2cap_event_channel_opened_get_local_cid(packet);
299 
300                     connection_controller = avrcp_get_connection_for_bd_addr_for_role(AVRCP_CONTROLLER, event_addr);
301                     connection_target = avrcp_get_connection_for_bd_addr_for_role(AVRCP_TARGET, event_addr);
302 
303                     // incoming: structs are already created in L2CAP_EVENT_INCOMING_CONNECTION
304                     // outgoing: structs are cteated in avrcp_connect() and avrcp_browsing_connect()
305                     if ((connection_controller == NULL) || (connection_target == NULL)) {
306                         break;
307                     }
308                     if ((connection_controller->browsing_connection == NULL) || (connection_target->browsing_connection == NULL)) {
309                         break;
310                     }
311 
312                     switch (status){
313                         case ERROR_CODE_SUCCESS:
314                             avrcp_browsing_handle_open_connection_for_role(connection_target, local_cid);
315                             avrcp_browsing_handle_open_connection_for_role(connection_controller, local_cid);
316                             avrcp_browsing_emit_connection_established(connection_controller->avrcp_browsing_cid, event_addr, status);
317                             return;
318                         case L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_RESOURCES:
319                             if (connection_controller->browsing_connection->incoming_declined == true){
320                                 log_info("Incoming browsing connection was declined, and the outgoing failed");
321                                 connection_controller->browsing_connection->state = AVCTP_CONNECTION_W2_L2CAP_RETRY;
322                                 connection_controller->browsing_connection->incoming_declined = false;
323                                 connection_target->browsing_connection->state = AVCTP_CONNECTION_W2_L2CAP_RETRY;
324                                 connection_target->browsing_connection->incoming_declined = false;
325                                 avrcp_retry_timer_start(connection_controller);
326                                 return;
327                             }
328                             break;
329                         default:
330                             break;
331                     }
332                     log_info("L2CAP connection to connection %s failed. status code 0x%02x", bd_addr_to_str(event_addr), status);
333                     avrcp_browsing_emit_connection_established(connection_controller->avrcp_browsing_cid, event_addr, status);
334                     avrcp_browsing_finalize_connection(connection_controller);
335                     avrcp_browsing_finalize_connection(connection_target);
336                     break;
337 
338                 case L2CAP_EVENT_CHANNEL_CLOSED:
339                     local_cid = l2cap_event_channel_closed_get_local_cid(packet);
340 
341                     connection_controller = avrcp_get_connection_for_browsing_l2cap_cid_for_role(AVRCP_CONTROLLER, local_cid);
342                     connection_target = avrcp_get_connection_for_browsing_l2cap_cid_for_role(AVRCP_TARGET, local_cid);
343                     if ((connection_controller == NULL) || (connection_target == NULL)) {
344                         break;
345                     }
346                     if ((connection_controller->browsing_connection == NULL) || (connection_target->browsing_connection == NULL)) {
347                         break;
348                     }
349                     avrcp_browsing_emit_connection_closed(connection_controller->avrcp_browsing_cid);
350                     avrcp_browsing_finalize_connection(connection_controller);
351                     avrcp_browsing_finalize_connection(connection_target);
352                     break;
353 
354                 case L2CAP_EVENT_CAN_SEND_NOW:
355                     local_cid = l2cap_event_can_send_now_get_local_cid(packet);
356                     connection_target = avrcp_get_connection_for_browsing_l2cap_cid_for_role(AVRCP_TARGET, local_cid);
357                     if ((connection_target != NULL) && (connection_target->browsing_connection != NULL) && connection_target->browsing_connection->wait_to_send) {
358                         connection_target->browsing_connection->wait_to_send = false;
359                         (*avrcp_browsing_target_packet_handler)(HCI_EVENT_PACKET, channel, packet, size);
360                         break;
361                     }
362                     connection_controller = avrcp_get_connection_for_browsing_l2cap_cid_for_role(AVRCP_CONTROLLER, local_cid);
363                     if ((connection_controller != NULL) && (connection_controller->browsing_connection != NULL) && connection_controller->browsing_connection->wait_to_send) {
364                         connection_controller->browsing_connection->wait_to_send = false;
365                         (*avrcp_browsing_controller_packet_handler)(HCI_EVENT_PACKET, channel, packet, size);
366                         break;
367                     }
368                     break;
369 
370                 default:
371                     break;
372             }
373             break;
374         default:
375             break;
376     }
377 
378 }
379 
avrcp_browsing_handle_sdp_query_complete(avrcp_connection_t * connection,uint8_t status)380 static void avrcp_browsing_handle_sdp_query_complete(avrcp_connection_t * connection, uint8_t status){
381 
382     if (connection->browsing_connection == NULL) {
383         return;
384     }
385     if (connection->browsing_connection->state != AVCTP_CONNECTION_W4_SDP_QUERY_COMPLETE){
386         return;
387     }
388 
389     // l2cap available?
390     if (status == ERROR_CODE_SUCCESS){
391         if (connection->browsing_l2cap_psm == 0){
392             status = SDP_SERVICE_NOT_FOUND;
393         }
394     }
395 
396     if (status == ERROR_CODE_SUCCESS) {
397         // ready to connect
398         connection->browsing_connection->state = AVCTP_CONNECTION_W2_L2CAP_CONNECT;
399 
400         // check if both events have been handled
401         avrcp_connection_t *connection_with_opposite_role;
402         switch (connection->role) {
403             case AVRCP_CONTROLLER:
404                 connection_with_opposite_role = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET,
405                                                                                             connection->avrcp_cid);
406                 break;
407             case AVRCP_TARGET:
408                 connection_with_opposite_role = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_CONTROLLER,
409                                                                                             connection->avrcp_cid);
410                 break;
411             default:
412                 btstack_assert(false);
413                 return;
414         }
415         if (connection_with_opposite_role->browsing_connection->state == AVCTP_CONNECTION_W2_L2CAP_CONNECT) {
416 
417             connection->browsing_connection->state                    = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
418             connection_with_opposite_role->browsing_connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
419 
420             l2cap_ertm_create_channel(avrcp_browsing_packet_handler,
421                                       connection->remote_addr,
422                                       connection->browsing_l2cap_psm,
423                                       &connection->browsing_connection->ertm_config,
424                                       connection->browsing_connection->ertm_buffer,
425                                       connection->browsing_connection->ertm_buffer_size,
426                                       NULL);
427         }
428     } else {
429         avrcp_browsing_finalize_connection(connection);
430         avrcp_browsing_emit_connection_established(connection->avrcp_browsing_cid, connection->remote_addr, status);
431     }
432 }
433 
avrcp_browsing_init(void)434 void avrcp_browsing_init(void){
435     avrcp_register_browsing_sdp_query_complete_handler(&avrcp_browsing_handle_sdp_query_complete);
436     if (avrcp_browsing_l2cap_service_registered) return;
437     uint8_t status = l2cap_register_service(&avrcp_browsing_packet_handler, PSM_AVCTP_BROWSING, 0xffff, LEVEL_2);
438     avrcp_browsing_l2cap_service_registered = status == ERROR_CODE_SUCCESS;
439 }
440 
avrcp_browsing_deinit(void)441 void avrcp_browsing_deinit(void){
442     avrcp_browsing_callback = NULL;
443     avrcp_browsing_controller_packet_handler = NULL;
444     avrcp_browsing_target_packet_handler = NULL;
445 
446     (void) memset(avrcp_browsing_sdp_addr, 0, 6);
447     (void) memset(&avrcp_browsing_handle_sdp_client_query_request, 0, sizeof(avrcp_browsing_handle_sdp_client_query_request));
448 
449     avrcp_browsing_l2cap_service_registered = false;
450 }
451 
avrcp_browsing_connect(bd_addr_t remote_addr,uint8_t * ertm_buffer,uint32_t ertm_buffer_size,l2cap_ertm_config_t * ertm_config,uint16_t * avrcp_browsing_cid)452 uint8_t avrcp_browsing_connect(bd_addr_t remote_addr, uint8_t * ertm_buffer, uint32_t ertm_buffer_size, l2cap_ertm_config_t * ertm_config, uint16_t * avrcp_browsing_cid){
453     btstack_assert(avrcp_browsing_controller_packet_handler != NULL);
454     btstack_assert(avrcp_browsing_target_packet_handler != NULL);
455 
456     avrcp_connection_t * connection_controller = avrcp_get_connection_for_bd_addr_for_role(AVRCP_CONTROLLER, remote_addr);
457     if (!connection_controller){
458         return ERROR_CODE_COMMAND_DISALLOWED;
459     }
460     avrcp_connection_t * connection_target = avrcp_get_connection_for_bd_addr_for_role(AVRCP_TARGET, remote_addr);
461     if (!connection_target){
462         return ERROR_CODE_COMMAND_DISALLOWED;
463     }
464 
465     if (connection_controller->browsing_connection){
466         return ERROR_CODE_COMMAND_DISALLOWED;
467     }
468     if (connection_target->browsing_connection){
469         return ERROR_CODE_COMMAND_DISALLOWED;
470     }
471 
472     uint16_t cid = avrcp_get_next_cid(AVRCP_CONTROLLER);
473 
474     connection_controller->browsing_connection = avrcp_browsing_create_connection(connection_controller, cid);
475     if (!connection_controller->browsing_connection) return BTSTACK_MEMORY_ALLOC_FAILED;
476 
477     connection_target->browsing_connection = avrcp_browsing_create_connection(connection_target, cid);
478     if (!connection_target->browsing_connection){
479         avrcp_browsing_finalize_connection(connection_controller);
480         return BTSTACK_MEMORY_ALLOC_FAILED;
481     }
482     avrcp_browsing_configure_ertm(connection_controller->browsing_connection, ertm_buffer, ertm_buffer_size, ertm_config);
483     avrcp_browsing_configure_ertm(connection_target->browsing_connection, ertm_buffer, ertm_buffer_size, ertm_config);
484 
485     if (avrcp_browsing_cid != NULL){
486         *avrcp_browsing_cid = cid;
487     }
488 
489     if (connection_controller->browsing_l2cap_psm == 0){
490         memcpy(avrcp_browsing_sdp_addr, remote_addr, 6);
491         connection_controller->browsing_connection->state = AVCTP_CONNECTION_W4_SDP_QUERY_COMPLETE;
492         connection_target->browsing_connection->state     = AVCTP_CONNECTION_W4_SDP_QUERY_COMPLETE;
493 
494         avrcp_trigger_sdp_query(connection_controller, connection_target);
495         return ERROR_CODE_SUCCESS;
496     } else {
497         connection_controller->browsing_connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
498         connection_target->browsing_connection->state     = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
499 
500         return l2cap_ertm_create_channel(avrcp_browsing_packet_handler, remote_addr, connection_controller->browsing_l2cap_psm,
501                                          &connection_controller->browsing_connection->ertm_config,
502                                          connection_controller->browsing_connection->ertm_buffer,
503                                          connection_controller->browsing_connection->ertm_buffer_size, NULL);
504     }
505 }
506 
avrcp_browsing_configure_incoming_connection(uint16_t avrcp_browsing_cid,uint8_t * ertm_buffer,uint32_t ertm_buffer_size,l2cap_ertm_config_t * ertm_config)507 uint8_t avrcp_browsing_configure_incoming_connection(uint16_t avrcp_browsing_cid, uint8_t * ertm_buffer, uint32_t ertm_buffer_size, l2cap_ertm_config_t * ertm_config){
508     avrcp_connection_t * connection_controller = avrcp_get_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid);
509     if (!connection_controller){
510         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
511     }
512     avrcp_connection_t * connection_target = avrcp_get_connection_for_browsing_cid_for_role(AVRCP_TARGET, avrcp_browsing_cid);
513     if (!connection_target){
514         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
515     }
516 
517     if (!connection_controller->browsing_connection){
518         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
519     }
520     if (!connection_target->browsing_connection){
521         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
522     }
523 
524     if (connection_controller->browsing_connection->state != AVCTP_CONNECTION_W4_ERTM_CONFIGURATION){
525         return ERROR_CODE_COMMAND_DISALLOWED;
526     }
527 
528     avrcp_browsing_configure_ertm(connection_controller->browsing_connection, ertm_buffer, ertm_buffer_size, ertm_config);
529     avrcp_browsing_configure_ertm(connection_target->browsing_connection, ertm_buffer, ertm_buffer_size, ertm_config);
530 
531     connection_controller->browsing_connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
532     connection_target->browsing_connection->state     = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
533 
534     l2cap_ertm_accept_connection(connection_controller->browsing_connection->l2cap_browsing_cid,
535         &connection_controller->browsing_connection->ertm_config,
536         connection_controller->browsing_connection->ertm_buffer,
537         connection_controller->browsing_connection->ertm_buffer_size);
538     return ERROR_CODE_SUCCESS;
539 }
540 
541 
avrcp_browsing_decline_incoming_connection(uint16_t avrcp_browsing_cid)542 uint8_t avrcp_browsing_decline_incoming_connection(uint16_t avrcp_browsing_cid){
543     avrcp_connection_t * connection_controller = avrcp_get_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid);
544     if (!connection_controller){
545         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
546     }
547     avrcp_connection_t * connection_target = avrcp_get_connection_for_browsing_cid_for_role(AVRCP_TARGET, avrcp_browsing_cid);
548     if (!connection_target){
549         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
550     }
551 
552     if (!connection_controller->browsing_connection){
553         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
554     }
555     if (!connection_target->browsing_connection){
556         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
557     }
558 
559     if (connection_controller->browsing_connection->state != AVCTP_CONNECTION_W4_ERTM_CONFIGURATION){
560         return ERROR_CODE_COMMAND_DISALLOWED;
561     }
562 
563     l2cap_decline_connection(connection_controller->browsing_connection->l2cap_browsing_cid);
564 
565     avrcp_browsing_finalize_connection(connection_controller);
566     avrcp_browsing_finalize_connection(connection_target);
567     return ERROR_CODE_SUCCESS;
568 }
569 
avrcp_browsing_disconnect(uint16_t avrcp_browsing_cid)570 uint8_t avrcp_browsing_disconnect(uint16_t avrcp_browsing_cid){
571     avrcp_connection_t * connection_controller = avrcp_get_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid);
572     if (!connection_controller){
573         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
574     }
575     avrcp_connection_t * connection_target = avrcp_get_connection_for_browsing_cid_for_role(AVRCP_TARGET, avrcp_browsing_cid);
576     if (!connection_target){
577         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
578     }
579 
580     if (!connection_controller->browsing_connection){
581         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
582     }
583     if (!connection_target->browsing_connection){
584         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
585     }
586 
587     l2cap_disconnect(connection_controller->browsing_connection->l2cap_browsing_cid);
588     return ERROR_CODE_SUCCESS;
589 }
590 
avrcp_browsing_register_controller_packet_handler(btstack_packet_handler_t callback)591 void avrcp_browsing_register_controller_packet_handler(btstack_packet_handler_t callback){
592     avrcp_browsing_controller_packet_handler = callback;
593 }
594 
avrcp_browsing_register_target_packet_handler(btstack_packet_handler_t callback)595 void avrcp_browsing_register_target_packet_handler(btstack_packet_handler_t callback){
596     avrcp_browsing_target_packet_handler = callback;
597 }
598 
avrcp_browsing_register_packet_handler(btstack_packet_handler_t callback)599 void avrcp_browsing_register_packet_handler(btstack_packet_handler_t callback){
600     btstack_assert(callback != NULL);
601     avrcp_browsing_callback = callback;
602 }
603