att_server.c (68591e36e97ed1ccb3a86672f9f79114713a1e1c) | att_server.c (b6df12b64ab4f66f3458f71cd65bcd9604fea387) |
---|---|
1/* 2 * Copyright (C) 2014 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 --- 92 unchanged lines hidden (view full) --- 101static btstack_context_callback_registration_t att_client_waiting_for_can_send_registration; 102 103static att_read_callback_t att_server_client_read_callback; 104static att_write_callback_t att_server_client_write_callback; 105 106// round robin 107static hci_con_handle_t att_server_last_can_send_now = HCI_CON_HANDLE_INVALID; 108 | 1/* 2 * Copyright (C) 2014 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 --- 92 unchanged lines hidden (view full) --- 101static btstack_context_callback_registration_t att_client_waiting_for_can_send_registration; 102 103static att_read_callback_t att_server_client_read_callback; 104static att_write_callback_t att_server_client_write_callback; 105 106// round robin 107static hci_con_handle_t att_server_last_can_send_now = HCI_CON_HANDLE_INVALID; 108 |
109static att_connection_t * att_connection_for_hci_connection(hci_connection_t * hci_connection){ 110 return &hci_connection->att_server.connection; 111} 112 |
|
109#ifdef ENABLE_LE_SIGNED_WRITE 110static hci_connection_t * hci_connection_for_state(att_server_state_t state){ 111 btstack_linked_list_iterator_t it; 112 hci_connections_get_iterator(&it); 113 while(btstack_linked_list_iterator_has_next(&it)){ 114 hci_connection_t * connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it); 115 att_server_t * att_server = &connection->att_server; 116 if (att_server->state == state) return connection; 117 } 118 return NULL; 119} 120#endif 121 122static void att_server_request_can_send_now(hci_connection_t * hci_connection){ | 113#ifdef ENABLE_LE_SIGNED_WRITE 114static hci_connection_t * hci_connection_for_state(att_server_state_t state){ 115 btstack_linked_list_iterator_t it; 116 hci_connections_get_iterator(&it); 117 while(btstack_linked_list_iterator_has_next(&it)){ 118 hci_connection_t * connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it); 119 att_server_t * att_server = &connection->att_server; 120 if (att_server->state == state) return connection; 121 } 122 return NULL; 123} 124#endif 125 126static void att_server_request_can_send_now(hci_connection_t * hci_connection){ |
123 att_server_t * att_server = &hci_connection->att_server; | |
124#ifdef ENABLE_GATT_OVER_CLASSIC | 127#ifdef ENABLE_GATT_OVER_CLASSIC |
128 att_server_t * att_server = &hci_connection->att_server; |
|
125 if (att_server->l2cap_cid != 0){ 126 l2cap_request_can_send_now_event(att_server->l2cap_cid); 127 return; 128 } 129#endif | 129 if (att_server->l2cap_cid != 0){ 130 l2cap_request_can_send_now_event(att_server->l2cap_cid); 131 return; 132 } 133#endif |
130 att_dispatch_server_request_can_send_now_event(att_server->connection.con_handle); | 134 att_connection_t * att_connection = att_connection_for_hci_connection(hci_connection); 135 att_dispatch_server_request_can_send_now_event(att_connection->con_handle); |
131} 132 133static int att_server_can_send_packet(hci_connection_t * hci_connection){ | 136} 137 138static int att_server_can_send_packet(hci_connection_t * hci_connection){ |
134 att_server_t * att_server = &hci_connection->att_server; | |
135#ifdef ENABLE_GATT_OVER_CLASSIC | 139#ifdef ENABLE_GATT_OVER_CLASSIC |
140 att_server_t * att_server = &hci_connection->att_server; |
|
136 if (att_server->l2cap_cid != 0){ 137 return l2cap_can_send_packet_now(att_server->l2cap_cid); 138 } 139#endif | 141 if (att_server->l2cap_cid != 0){ 142 return l2cap_can_send_packet_now(att_server->l2cap_cid); 143 } 144#endif |
140 return att_dispatch_server_can_send_now(att_server->connection.con_handle); | 145 att_connection_t * att_connection = att_connection_for_hci_connection(hci_connection); 146 return att_dispatch_server_can_send_now(att_connection->con_handle); |
141} 142 143static void att_handle_value_indication_notify_client(uint8_t status, uint16_t client_handle, uint16_t attribute_handle){ 144 btstack_packet_handler_t packet_handler = att_server_packet_handler_for_handle(attribute_handle); 145 if (!packet_handler) return; 146 147 uint8_t event[7]; 148 int pos = 0; --- 43 unchanged lines hidden (view full) --- 192 if (!att_client_packet_handler) return; 193 194 uint8_t event[] = { ATT_EVENT_CAN_SEND_NOW, 0}; 195 (*att_client_packet_handler)(HCI_EVENT_PACKET, 0, &event[0], sizeof(event)); 196} 197 198static void att_emit_connected_event(hci_connection_t * hci_connection){ 199 att_server_t * att_server = &hci_connection->att_server; | 147} 148 149static void att_handle_value_indication_notify_client(uint8_t status, uint16_t client_handle, uint16_t attribute_handle){ 150 btstack_packet_handler_t packet_handler = att_server_packet_handler_for_handle(attribute_handle); 151 if (!packet_handler) return; 152 153 uint8_t event[7]; 154 int pos = 0; --- 43 unchanged lines hidden (view full) --- 198 if (!att_client_packet_handler) return; 199 200 uint8_t event[] = { ATT_EVENT_CAN_SEND_NOW, 0}; 201 (*att_client_packet_handler)(HCI_EVENT_PACKET, 0, &event[0], sizeof(event)); 202} 203 204static void att_emit_connected_event(hci_connection_t * hci_connection){ 205 att_server_t * att_server = &hci_connection->att_server; |
206 att_connection_t * att_connection = att_connection_for_hci_connection(hci_connection); |
|
200 uint8_t event[11]; 201 int pos = 0; 202 event[pos++] = ATT_EVENT_CONNECTED; 203 event[pos++] = sizeof(event) - 2u; 204 event[pos++] = att_server->peer_addr_type; 205 reverse_bd_addr(att_server->peer_address, &event[pos]); 206 pos += 6; | 207 uint8_t event[11]; 208 int pos = 0; 209 event[pos++] = ATT_EVENT_CONNECTED; 210 event[pos++] = sizeof(event) - 2u; 211 event[pos++] = att_server->peer_addr_type; 212 reverse_bd_addr(att_server->peer_address, &event[pos]); 213 pos += 6; |
207 little_endian_store_16(event, pos, att_server->connection.con_handle); | 214 little_endian_store_16(event, pos, att_connection->con_handle); |
208 pos += 2; 209 210 // dispatch to app level handler and service handlers 211 att_emit_event_to_all(&event[0], sizeof(event)); 212} 213 214 215static void att_emit_disconnected_event(uint16_t con_handle){ --- 8 unchanged lines hidden (view full) --- 224 att_emit_event_to_all(&event[0], sizeof(event)); 225} 226 227static void att_handle_value_indication_timeout(btstack_timer_source_t *ts){ 228 void * context = btstack_run_loop_get_timer_context(ts); 229 hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) context; 230 hci_connection_t * hci_connection = hci_connection_for_handle(con_handle); 231 if (!hci_connection) return; | 215 pos += 2; 216 217 // dispatch to app level handler and service handlers 218 att_emit_event_to_all(&event[0], sizeof(event)); 219} 220 221 222static void att_emit_disconnected_event(uint16_t con_handle){ --- 8 unchanged lines hidden (view full) --- 231 att_emit_event_to_all(&event[0], sizeof(event)); 232} 233 234static void att_handle_value_indication_timeout(btstack_timer_source_t *ts){ 235 void * context = btstack_run_loop_get_timer_context(ts); 236 hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) context; 237 hci_connection_t * hci_connection = hci_connection_for_handle(con_handle); 238 if (!hci_connection) return; |
232 att_server_t * att_server = &hci_connection->att_server; | |
233 // @note: after a transaction timeout, no more requests shall be sent over this ATT Bearer 234 // (that's why we don't reset the value_indication_handle) | 239 // @note: after a transaction timeout, no more requests shall be sent over this ATT Bearer 240 // (that's why we don't reset the value_indication_handle) |
241 att_server_t * att_server = &hci_connection->att_server; |
|
235 uint16_t att_handle = att_server->value_indication_handle; | 242 uint16_t att_handle = att_server->value_indication_handle; |
236 att_handle_value_indication_notify_client(ATT_HANDLE_VALUE_INDICATION_TIMEOUT, att_server->connection.con_handle, att_handle); | 243 att_connection_t * att_connection = att_connection_for_hci_connection(hci_connection); 244 att_handle_value_indication_notify_client(ATT_HANDLE_VALUE_INDICATION_TIMEOUT, att_connection->con_handle, att_handle); |
237} 238 239static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 240 241 UNUSED(channel); // ok: there is no channel 242 UNUSED(size); // ok: handling own l2cap events 243 244 att_server_t * att_server; | 245} 246 247static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 248 249 UNUSED(channel); // ok: there is no channel 250 UNUSED(size); // ok: handling own l2cap events 251 252 att_server_t * att_server; |
253 att_connection_t * att_connection; |
|
245 hci_con_handle_t con_handle; 246 hci_connection_t * hci_connection; 247#ifdef ENABLE_GATT_OVER_CLASSIC 248 bd_addr_t address; 249 btstack_linked_list_iterator_t it; 250#endif 251 252 switch (packet_type) { --- 10 unchanged lines hidden (view full) --- 263 case L2CAP_EVENT_CHANNEL_OPENED: 264 con_handle = l2cap_event_channel_opened_get_handle(packet); 265 hci_connection = hci_connection_for_handle(con_handle); 266 if (!hci_connection) break; 267 att_server = &hci_connection->att_server; 268 // store connection info 269 att_server->peer_addr_type = BD_ADDR_TYPE_ACL; 270 l2cap_event_channel_opened_get_address(packet, att_server->peer_address); | 254 hci_con_handle_t con_handle; 255 hci_connection_t * hci_connection; 256#ifdef ENABLE_GATT_OVER_CLASSIC 257 bd_addr_t address; 258 btstack_linked_list_iterator_t it; 259#endif 260 261 switch (packet_type) { --- 10 unchanged lines hidden (view full) --- 272 case L2CAP_EVENT_CHANNEL_OPENED: 273 con_handle = l2cap_event_channel_opened_get_handle(packet); 274 hci_connection = hci_connection_for_handle(con_handle); 275 if (!hci_connection) break; 276 att_server = &hci_connection->att_server; 277 // store connection info 278 att_server->peer_addr_type = BD_ADDR_TYPE_ACL; 279 l2cap_event_channel_opened_get_address(packet, att_server->peer_address); |
271 att_server->connection.con_handle = con_handle; | 280 att_connection = att_connection_for_hci_connection(hci_connection); 281 att_connection->con_handle = con_handle; |
272 att_server->l2cap_cid = l2cap_event_channel_opened_get_local_cid(packet); 273 // reset connection properties 274 att_server->state = ATT_SERVER_IDLE; | 282 att_server->l2cap_cid = l2cap_event_channel_opened_get_local_cid(packet); 283 // reset connection properties 284 att_server->state = ATT_SERVER_IDLE; |
275 att_server->connection.mtu = l2cap_event_channel_opened_get_remote_mtu(packet); 276 att_server->connection.max_mtu = l2cap_max_mtu(); 277 if (att_server->connection.max_mtu > ATT_REQUEST_BUFFER_SIZE){ 278 att_server->connection.max_mtu = ATT_REQUEST_BUFFER_SIZE; | 285 att_connection->mtu = l2cap_event_channel_opened_get_remote_mtu(packet); 286 att_connection->max_mtu = l2cap_max_mtu(); 287 if (att_connection->max_mtu > ATT_REQUEST_BUFFER_SIZE){ 288 att_connection->max_mtu = ATT_REQUEST_BUFFER_SIZE; |
279 } 280 | 289 } 290 |
281 log_info("Connection opened %s, l2cap cid %04x, mtu %u", bd_addr_to_str(address), att_server->l2cap_cid, att_server->connection.mtu); | 291 log_info("Connection opened %s, l2cap cid %04x, mtu %u", bd_addr_to_str(address), att_server->l2cap_cid, att_connection->mtu); |
282 283 // update security params | 292 293 // update security params |
284 att_server->connection.encryption_key_size = gap_encryption_key_size(con_handle); 285 att_server->connection.authenticated = gap_authenticated(con_handle); 286 att_server->connection.secure_connection = gap_secure_connection(con_handle); | 294 att_connection->encryption_key_size = gap_encryption_key_size(con_handle); 295 att_connection->authenticated = gap_authenticated(con_handle); 296 att_connection->secure_connection = gap_secure_connection(con_handle); |
287 log_info("encrypted key size %u, authenticated %u, secure connection %u", | 297 log_info("encrypted key size %u, authenticated %u, secure connection %u", |
288 att_server->connection.encryption_key_size, att_server->connection.authenticated, att_server->connection.secure_connection); | 298 att_connection->encryption_key_size, att_connection->authenticated, att_connection->secure_connection); |
289 290 // notify connection opened 291 att_emit_connected_event(hci_connection); 292 293 // restore persisten ccc if encrypted 294 if ( gap_security_level(con_handle) >= LEVEL_2){ 295 att_server_persistent_ccc_restore(hci_connection); 296 } --- 10 unchanged lines hidden (view full) --- 307 case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: 308 con_handle = little_endian_read_16(packet, 4); 309 hci_connection = hci_connection_for_handle(con_handle); 310 if (!hci_connection) break; 311 att_server = &hci_connection->att_server; 312 // store connection info 313 att_server->peer_addr_type = packet[7]; 314 reverse_bd_addr(&packet[8], att_server->peer_address); | 299 300 // notify connection opened 301 att_emit_connected_event(hci_connection); 302 303 // restore persisten ccc if encrypted 304 if ( gap_security_level(con_handle) >= LEVEL_2){ 305 att_server_persistent_ccc_restore(hci_connection); 306 } --- 10 unchanged lines hidden (view full) --- 317 case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: 318 con_handle = little_endian_read_16(packet, 4); 319 hci_connection = hci_connection_for_handle(con_handle); 320 if (!hci_connection) break; 321 att_server = &hci_connection->att_server; 322 // store connection info 323 att_server->peer_addr_type = packet[7]; 324 reverse_bd_addr(&packet[8], att_server->peer_address); |
315 att_server->connection.con_handle = con_handle; | 325 att_connection = att_connection_for_hci_connection(hci_connection); 326 att_connection->con_handle = con_handle; |
316 // reset connection properties 317 att_server->state = ATT_SERVER_IDLE; | 327 // reset connection properties 328 att_server->state = ATT_SERVER_IDLE; |
318 att_server->connection.mtu = ATT_DEFAULT_MTU; 319 att_server->connection.max_mtu = l2cap_max_le_mtu(); 320 if (att_server->connection.max_mtu > ATT_REQUEST_BUFFER_SIZE){ 321 att_server->connection.max_mtu = ATT_REQUEST_BUFFER_SIZE; | 329 att_connection->mtu = ATT_DEFAULT_MTU; 330 att_connection->max_mtu = l2cap_max_le_mtu(); 331 if (att_connection->max_mtu > ATT_REQUEST_BUFFER_SIZE){ 332 att_connection->max_mtu = ATT_REQUEST_BUFFER_SIZE; |
322 } | 333 } |
323 att_server->connection.encryption_key_size = 0; 324 att_server->connection.authenticated = 0; 325 att_server->connection.authorized = 0; | 334 att_connection->encryption_key_size = 0; 335 att_connection->authenticated = 0; 336 att_connection->authorized = 0; |
326 // workaround: identity resolving can already be complete, at least store result 327 att_server->ir_le_device_db_index = sm_le_device_index(con_handle); 328 att_server->ir_lookup_active = 0; 329 att_server->pairing_active = 0; 330 // notify all - old 331 att_emit_event_to_all(packet, size); 332 // notify all - new 333 att_emit_connected_event(hci_connection); --- 8 unchanged lines hidden (view full) --- 342 case HCI_EVENT_ENCRYPTION_KEY_REFRESH_COMPLETE: 343 // check handle 344 con_handle = little_endian_read_16(packet, 3); 345 hci_connection = hci_connection_for_handle(con_handle); 346 if (!hci_connection) break; 347 if (gap_get_connection_type(con_handle) != GAP_CONNECTION_LE) break; 348 // update security params 349 att_server = &hci_connection->att_server; | 337 // workaround: identity resolving can already be complete, at least store result 338 att_server->ir_le_device_db_index = sm_le_device_index(con_handle); 339 att_server->ir_lookup_active = 0; 340 att_server->pairing_active = 0; 341 // notify all - old 342 att_emit_event_to_all(packet, size); 343 // notify all - new 344 att_emit_connected_event(hci_connection); --- 8 unchanged lines hidden (view full) --- 353 case HCI_EVENT_ENCRYPTION_KEY_REFRESH_COMPLETE: 354 // check handle 355 con_handle = little_endian_read_16(packet, 3); 356 hci_connection = hci_connection_for_handle(con_handle); 357 if (!hci_connection) break; 358 if (gap_get_connection_type(con_handle) != GAP_CONNECTION_LE) break; 359 // update security params 360 att_server = &hci_connection->att_server; |
350 att_server->connection.encryption_key_size = gap_encryption_key_size(con_handle); 351 att_server->connection.authenticated = gap_authenticated(con_handle); 352 att_server->connection.secure_connection = gap_secure_connection(con_handle); | 361 att_connection = att_connection_for_hci_connection(hci_connection); 362 att_connection->encryption_key_size = gap_encryption_key_size(con_handle); 363 att_connection->authenticated = gap_authenticated(con_handle); 364 att_connection->secure_connection = gap_secure_connection(con_handle); |
353 log_info("encrypted key size %u, authenticated %u, secure connection %u", | 365 log_info("encrypted key size %u, authenticated %u, secure connection %u", |
354 att_server->connection.encryption_key_size, att_server->connection.authenticated, att_server->connection.secure_connection); | 366 att_connection->encryption_key_size, att_connection->authenticated, att_connection->secure_connection); |
355 if (hci_event_packet_get_type(packet) == HCI_EVENT_ENCRYPTION_CHANGE){ 356 // restore CCC values when encrypted for LE Connections 357 if (hci_event_encryption_change_get_encryption_enabled(packet)){ 358 att_server_persistent_ccc_restore(hci_connection); 359 } 360 } 361 att_run_for_context(hci_connection); 362 break; 363 364 case HCI_EVENT_DISCONNECTION_COMPLETE: 365 // check handle 366 con_handle = hci_event_disconnection_complete_get_connection_handle(packet); 367 hci_connection = hci_connection_for_handle(con_handle); 368 if (!hci_connection) break; 369 att_server = &hci_connection->att_server; | 367 if (hci_event_packet_get_type(packet) == HCI_EVENT_ENCRYPTION_CHANGE){ 368 // restore CCC values when encrypted for LE Connections 369 if (hci_event_encryption_change_get_encryption_enabled(packet)){ 370 att_server_persistent_ccc_restore(hci_connection); 371 } 372 } 373 att_run_for_context(hci_connection); 374 break; 375 376 case HCI_EVENT_DISCONNECTION_COMPLETE: 377 // check handle 378 con_handle = hci_event_disconnection_complete_get_connection_handle(packet); 379 hci_connection = hci_connection_for_handle(con_handle); 380 if (!hci_connection) break; 381 att_server = &hci_connection->att_server; |
370 att_clear_transaction_queue(&att_server->connection); 371 att_server->connection.con_handle = 0; | 382 att_connection = att_connection_for_hci_connection(hci_connection); 383 att_clear_transaction_queue(att_connection); 384 att_connection->con_handle = 0; |
372 att_server->pairing_active = 0; 373 att_server->state = ATT_SERVER_IDLE; 374 if (att_server->value_indication_handle){ 375 btstack_run_loop_remove_timer(&att_server->value_indication_timer); 376 uint16_t att_handle = att_server->value_indication_handle; 377 att_server->value_indication_handle = 0; // reset error state | 385 att_server->pairing_active = 0; 386 att_server->state = ATT_SERVER_IDLE; 387 if (att_server->value_indication_handle){ 388 btstack_run_loop_remove_timer(&att_server->value_indication_timer); 389 uint16_t att_handle = att_server->value_indication_handle; 390 att_server->value_indication_handle = 0; // reset error state |
378 att_handle_value_indication_notify_client(ATT_HANDLE_VALUE_INDICATION_DISCONNECT, att_server->connection.con_handle, att_handle); | 391 att_handle_value_indication_notify_client(ATT_HANDLE_VALUE_INDICATION_DISCONNECT, att_connection->con_handle, att_handle); |
379 } 380 // notify all - new 381 att_emit_disconnected_event(con_handle); 382 // notify all - old 383 att_emit_event_to_all(packet, size); 384 break; 385 386 // Identity Resolving --- 67 unchanged lines hidden (view full) --- 454 break; 455 456 // Authorization 457 case SM_EVENT_AUTHORIZATION_RESULT: { 458 con_handle = sm_event_authorization_result_get_handle(packet); 459 hci_connection = hci_connection_for_handle(con_handle); 460 if (!hci_connection) break; 461 att_server = &hci_connection->att_server; | 392 } 393 // notify all - new 394 att_emit_disconnected_event(con_handle); 395 // notify all - old 396 att_emit_event_to_all(packet, size); 397 break; 398 399 // Identity Resolving --- 67 unchanged lines hidden (view full) --- 467 break; 468 469 // Authorization 470 case SM_EVENT_AUTHORIZATION_RESULT: { 471 con_handle = sm_event_authorization_result_get_handle(packet); 472 hci_connection = hci_connection_for_handle(con_handle); 473 if (!hci_connection) break; 474 att_server = &hci_connection->att_server; |
462 att_server->connection.authorized = sm_event_authorization_result_get_authorization_result(packet); | 475 att_connection = att_connection_for_hci_connection(hci_connection); 476 att_connection->authorized = sm_event_authorization_result_get_authorization_result(packet); |
463 att_server_request_can_send_now(hci_connection); 464 break; 465 } 466 default: 467 break; 468 } 469 break; 470#ifdef ENABLE_GATT_OVER_CLASSIC --- 39 unchanged lines hidden (view full) --- 510} 511#endif 512 513// pre: att_server->state == ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED 514// pre: can send now 515// returns: 1 if packet was sent 516static int att_server_process_validated_request(hci_connection_t * hci_connection){ 517 att_server_t * att_server = & hci_connection->att_server; | 477 att_server_request_can_send_now(hci_connection); 478 break; 479 } 480 default: 481 break; 482 } 483 break; 484#ifdef ENABLE_GATT_OVER_CLASSIC --- 39 unchanged lines hidden (view full) --- 524} 525#endif 526 527// pre: att_server->state == ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED 528// pre: can send now 529// returns: 1 if packet was sent 530static int att_server_process_validated_request(hci_connection_t * hci_connection){ 531 att_server_t * att_server = & hci_connection->att_server; |
532 att_connection_t * att_connection = att_connection_for_hci_connection(hci_connection); |
|
518 519 l2cap_reserve_packet_buffer(); 520 uint8_t * att_response_buffer = l2cap_get_outgoing_buffer(); | 533 534 l2cap_reserve_packet_buffer(); 535 uint8_t * att_response_buffer = l2cap_get_outgoing_buffer(); |
521 uint16_t att_response_size = att_handle_request(&att_server->connection, att_server->request_buffer, att_server->request_size, att_response_buffer); | 536 uint16_t att_response_size = att_handle_request(att_connection, att_server->request_buffer, att_server->request_size, att_response_buffer); |
522 523#ifdef ENABLE_ATT_DELAYED_RESPONSE 524 if ((att_response_size == ATT_READ_RESPONSE_PENDING) || (att_response_size == ATT_INTERNAL_WRITE_RESPONSE_PENDING)){ 525 // update state 526 att_server->state = ATT_SERVER_RESPONSE_PENDING; 527 528 // callback with handle ATT_READ_RESPONSE_PENDING for reads 529 if (att_response_size == ATT_READ_RESPONSE_PENDING){ | 537 538#ifdef ENABLE_ATT_DELAYED_RESPONSE 539 if ((att_response_size == ATT_READ_RESPONSE_PENDING) || (att_response_size == ATT_INTERNAL_WRITE_RESPONSE_PENDING)){ 540 // update state 541 att_server->state = ATT_SERVER_RESPONSE_PENDING; 542 543 // callback with handle ATT_READ_RESPONSE_PENDING for reads 544 if (att_response_size == ATT_READ_RESPONSE_PENDING){ |
530 att_server_client_read_callback(att_server->connection.con_handle, ATT_READ_RESPONSE_PENDING, 0, NULL, 0); | 545 att_server_client_read_callback(att_connection->con_handle, ATT_READ_RESPONSE_PENDING, 0, NULL, 0); |
531 } 532 533 // free reserved buffer 534 l2cap_release_packet_buffer(); 535 return 0; 536 } 537#endif 538 539 // intercept "insufficient authorization" for authenticated connections to allow for user authorization 540 if ((att_response_size >= 4u) 541 && (att_response_buffer[0] == ATT_ERROR_RESPONSE) 542 && (att_response_buffer[4] == ATT_ERROR_INSUFFICIENT_AUTHORIZATION) | 546 } 547 548 // free reserved buffer 549 l2cap_release_packet_buffer(); 550 return 0; 551 } 552#endif 553 554 // intercept "insufficient authorization" for authenticated connections to allow for user authorization 555 if ((att_response_size >= 4u) 556 && (att_response_buffer[0] == ATT_ERROR_RESPONSE) 557 && (att_response_buffer[4] == ATT_ERROR_INSUFFICIENT_AUTHORIZATION) |
543 && (att_server->connection.authenticated)){ | 558 && (att_connection->authenticated)){ |
544 | 559 |
545 switch (gap_authorization_state(att_server->connection.con_handle)){ | 560 switch (gap_authorization_state(att_connection->con_handle)){ |
546 case AUTHORIZATION_UNKNOWN: 547 l2cap_release_packet_buffer(); | 561 case AUTHORIZATION_UNKNOWN: 562 l2cap_release_packet_buffer(); |
548 sm_request_pairing(att_server->connection.con_handle); | 563 sm_request_pairing(att_connection->con_handle); |
549 return 0; 550 case AUTHORIZATION_PENDING: 551 l2cap_release_packet_buffer(); 552 return 0; 553 default: 554 break; 555 } 556 } --- 5 unchanged lines hidden (view full) --- 562 } 563 564#ifdef ENABLE_GATT_OVER_CLASSIC 565 if (att_server->l2cap_cid != 0){ 566 l2cap_send_prepared(att_server->l2cap_cid, att_response_size); 567 } else 568#endif 569 { | 564 return 0; 565 case AUTHORIZATION_PENDING: 566 l2cap_release_packet_buffer(); 567 return 0; 568 default: 569 break; 570 } 571 } --- 5 unchanged lines hidden (view full) --- 577 } 578 579#ifdef ENABLE_GATT_OVER_CLASSIC 580 if (att_server->l2cap_cid != 0){ 581 l2cap_send_prepared(att_server->l2cap_cid, att_response_size); 582 } else 583#endif 584 { |
570 l2cap_send_prepared_connectionless(att_server->connection.con_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, att_response_size); | 585 l2cap_send_prepared_connectionless(att_connection->con_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, att_response_size); |
571 } 572 573 // notify client about MTU exchange result 574 if (att_response_buffer[0] == ATT_EXCHANGE_MTU_RESPONSE){ | 586 } 587 588 // notify client about MTU exchange result 589 if (att_response_buffer[0] == ATT_EXCHANGE_MTU_RESPONSE){ |
575 att_emit_mtu_event(att_server->connection.con_handle, att_server->connection.mtu); | 590 att_emit_mtu_event(att_connection->con_handle, att_connection->mtu); |
576 } 577 return 1; 578} 579 580#ifdef ENABLE_ATT_DELAYED_RESPONSE 581int att_server_response_ready(hci_con_handle_t con_handle){ 582 hci_connection_t * hci_connection = hci_connection_for_handle(con_handle); 583 if (!hci_connection) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; --- 4 unchanged lines hidden (view full) --- 588 att_server->state = ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED; 589 att_server_request_can_send_now(hci_connection); 590 return ERROR_CODE_SUCCESS; 591} 592#endif 593 594static void att_run_for_context(hci_connection_t * hci_connection){ 595 att_server_t * att_server = &hci_connection->att_server; | 591 } 592 return 1; 593} 594 595#ifdef ENABLE_ATT_DELAYED_RESPONSE 596int att_server_response_ready(hci_con_handle_t con_handle){ 597 hci_connection_t * hci_connection = hci_connection_for_handle(con_handle); 598 if (!hci_connection) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; --- 4 unchanged lines hidden (view full) --- 603 att_server->state = ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED; 604 att_server_request_can_send_now(hci_connection); 605 return ERROR_CODE_SUCCESS; 606} 607#endif 608 609static void att_run_for_context(hci_connection_t * hci_connection){ 610 att_server_t * att_server = &hci_connection->att_server; |
611 att_connection_t * att_connection = att_connection_for_hci_connection(hci_connection); |
|
596 switch (att_server->state){ 597 case ATT_SERVER_REQUEST_RECEIVED: 598 599#ifdef ENABLE_GATT_OVER_CLASSIC 600 if (att_server->l2cap_cid != 0){ 601 // ok 602 } else 603#endif 604 { 605 // wait until re-encryption as central is complete | 612 switch (att_server->state){ 613 case ATT_SERVER_REQUEST_RECEIVED: 614 615#ifdef ENABLE_GATT_OVER_CLASSIC 616 if (att_server->l2cap_cid != 0){ 617 // ok 618 } else 619#endif 620 { 621 // wait until re-encryption as central is complete |
606 if (gap_reconnect_security_setup_active(att_server->connection.con_handle)) break; | 622 if (gap_reconnect_security_setup_active(att_connection->con_handle)) break; |
607 } 608 609 // wait until pairing is complete 610 if (att_server->pairing_active) break; 611 612#ifdef ENABLE_LE_SIGNED_WRITE 613 if (att_server->request_buffer[0] == ATT_SIGNED_WRITE_COMMAND){ 614 log_info("ATT Signed Write!"); --- 95 unchanged lines hidden (view full) --- 710 att_server_run_phase_t phase = (att_server_run_phase_t) phase_index; 711 hci_con_handle_t skip_connections_until = att_server_last_can_send_now; 712 while (true){ 713 btstack_linked_list_iterator_t it; 714 hci_connections_get_iterator(&it); 715 while(btstack_linked_list_iterator_has_next(&it)){ 716 hci_connection_t * connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it); 717 att_server_t * att_server = &connection->att_server; | 623 } 624 625 // wait until pairing is complete 626 if (att_server->pairing_active) break; 627 628#ifdef ENABLE_LE_SIGNED_WRITE 629 if (att_server->request_buffer[0] == ATT_SIGNED_WRITE_COMMAND){ 630 log_info("ATT Signed Write!"); --- 95 unchanged lines hidden (view full) --- 726 att_server_run_phase_t phase = (att_server_run_phase_t) phase_index; 727 hci_con_handle_t skip_connections_until = att_server_last_can_send_now; 728 while (true){ 729 btstack_linked_list_iterator_t it; 730 hci_connections_get_iterator(&it); 731 while(btstack_linked_list_iterator_has_next(&it)){ 732 hci_connection_t * connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it); 733 att_server_t * att_server = &connection->att_server; |
734 att_connection_t * att_connection = att_connection_for_hci_connection(connection); |
|
718 719 int data_ready = att_server_data_ready_for_phase(att_server, phase); 720 | 735 736 int data_ready = att_server_data_ready_for_phase(att_server, phase); 737 |
721 // log_debug("phase %u, handle 0x%04x, skip until 0x%04x, data ready %u", phase, att_server->connection.con_handle, skip_connections_until, data_ready); | 738 // log_debug("phase %u, handle 0x%04x, skip until 0x%04x, data ready %u", phase, att_connection->con_handle, skip_connections_until, data_ready); |
722 723 // skip until last sender found (which is also skipped) 724 if (skip_connections_until != HCI_CON_HANDLE_INVALID){ 725 if (data_ready && (request_hci_connection == NULL)){ 726 request_hci_connection = connection; 727 } | 739 740 // skip until last sender found (which is also skipped) 741 if (skip_connections_until != HCI_CON_HANDLE_INVALID){ 742 if (data_ready && (request_hci_connection == NULL)){ 743 request_hci_connection = connection; 744 } |
728 if (skip_connections_until == att_server->connection.con_handle){ | 745 if (skip_connections_until == att_connection->con_handle){ |
729 skip_connections_until = HCI_CON_HANDLE_INVALID; 730 } 731 continue; 732 }; 733 734 if (data_ready){ 735 if (can_send_now){ 736 att_server_trigger_send_for_phase(connection, phase); | 746 skip_connections_until = HCI_CON_HANDLE_INVALID; 747 } 748 continue; 749 }; 750 751 if (data_ready){ 752 if (can_send_now){ 753 att_server_trigger_send_for_phase(connection, phase); |
737 last_send_con_handle = att_server->connection.con_handle; | 754 last_send_con_handle = att_connection->con_handle; |
738 can_send_now = att_server_can_send_packet(connection); 739 data_ready = att_server_data_ready_for_phase(att_server, phase); 740 if (data_ready && (request_hci_connection == NULL)){ 741 request_hci_connection = connection; 742 } 743 } else { 744 request_hci_connection = connection; 745 break; --- 20 unchanged lines hidden (view full) --- 766 } 767 768 if (request_hci_connection == NULL) return; 769 att_server_request_can_send_now(request_hci_connection); 770} 771 772static void att_server_handle_att_pdu(hci_connection_t * hci_connection, uint8_t * packet, uint16_t size){ 773 att_server_t * att_server = &hci_connection->att_server; | 755 can_send_now = att_server_can_send_packet(connection); 756 data_ready = att_server_data_ready_for_phase(att_server, phase); 757 if (data_ready && (request_hci_connection == NULL)){ 758 request_hci_connection = connection; 759 } 760 } else { 761 request_hci_connection = connection; 762 break; --- 20 unchanged lines hidden (view full) --- 783 } 784 785 if (request_hci_connection == NULL) return; 786 att_server_request_can_send_now(request_hci_connection); 787} 788 789static void att_server_handle_att_pdu(hci_connection_t * hci_connection, uint8_t * packet, uint16_t size){ 790 att_server_t * att_server = &hci_connection->att_server; |
791 att_connection_t * att_connection = att_connection_for_hci_connection(hci_connection); |
|
774 775 // handle value indication confirms 776 if ((packet[0] == ATT_HANDLE_VALUE_CONFIRMATION) && att_server->value_indication_handle){ 777 btstack_run_loop_remove_timer(&att_server->value_indication_timer); 778 uint16_t att_handle = att_server->value_indication_handle; 779 att_server->value_indication_handle = 0; | 792 793 // handle value indication confirms 794 if ((packet[0] == ATT_HANDLE_VALUE_CONFIRMATION) && att_server->value_indication_handle){ 795 btstack_run_loop_remove_timer(&att_server->value_indication_timer); 796 uint16_t att_handle = att_server->value_indication_handle; 797 att_server->value_indication_handle = 0; |
780 att_handle_value_indication_notify_client(0, att_server->connection.con_handle, att_handle); | 798 att_handle_value_indication_notify_client(0, att_connection->con_handle, att_handle); |
781 att_server_request_can_send_now(hci_connection); 782 return; 783 } 784 785 // directly process command 786 // note: signed write cannot be handled directly as authentication needs to be verified 787 if (packet[0] == ATT_WRITE_COMMAND){ | 799 att_server_request_can_send_now(hci_connection); 800 return; 801 } 802 803 // directly process command 804 // note: signed write cannot be handled directly as authentication needs to be verified 805 if (packet[0] == ATT_WRITE_COMMAND){ |
788 att_handle_request(&att_server->connection, packet, size, NULL); | 806 att_handle_request(att_connection, packet, size, NULL); |
789 return; 790 } 791 792 // check size 793 if (size > sizeof(att_server->request_buffer)) { 794 log_info("drop att pdu 0x%02x as size %u > att_server->request_buffer %u", packet[0], size, (int) sizeof(att_server->request_buffer)); 795 return; 796 } --- 20 unchanged lines hidden (view full) --- 817 att_server->state = ATT_SERVER_REQUEST_RECEIVED; 818 att_server->request_size = size; 819 (void)memcpy(att_server->request_buffer, packet, size); 820 821 att_run_for_context(hci_connection); 822} 823 824static void att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){ | 807 return; 808 } 809 810 // check size 811 if (size > sizeof(att_server->request_buffer)) { 812 log_info("drop att pdu 0x%02x as size %u > att_server->request_buffer %u", packet[0], size, (int) sizeof(att_server->request_buffer)); 813 return; 814 } --- 20 unchanged lines hidden (view full) --- 835 att_server->state = ATT_SERVER_REQUEST_RECEIVED; 836 att_server->request_size = size; 837 (void)memcpy(att_server->request_buffer, packet, size); 838 839 att_run_for_context(hci_connection); 840} 841 842static void att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){ |
825 att_server_t * att_server; | |
826 hci_connection_t * hci_connection; | 843 hci_connection_t * hci_connection; |
844 att_connection_t * att_connection; |
|
827 828 switch (packet_type){ 829 case HCI_EVENT_PACKET: 830 switch (packet[0]){ 831 case L2CAP_EVENT_CAN_SEND_NOW: 832 att_server_handle_can_send_now(); 833 break; 834 case ATT_EVENT_MTU_EXCHANGE_COMPLETE: 835 // GATT client has negotiated the mtu for this connection 836 hci_connection = hci_connection_for_handle(handle); 837 if (!hci_connection) break; | 845 846 switch (packet_type){ 847 case HCI_EVENT_PACKET: 848 switch (packet[0]){ 849 case L2CAP_EVENT_CAN_SEND_NOW: 850 att_server_handle_can_send_now(); 851 break; 852 case ATT_EVENT_MTU_EXCHANGE_COMPLETE: 853 // GATT client has negotiated the mtu for this connection 854 hci_connection = hci_connection_for_handle(handle); 855 if (!hci_connection) break; |
838 att_server = &hci_connection->att_server; 839 att_server->connection.mtu = little_endian_read_16(packet, 4); | 856 att_connection = att_connection_for_hci_connection(hci_connection); 857 att_connection->mtu = little_endian_read_16(packet, 4); |
840 break; 841 default: 842 break; 843 } 844 break; 845 846 case ATT_DATA_PACKET: 847 log_debug("ATT Packet, handle 0x%04x", handle); --- 134 unchanged lines hidden (view full) --- 982 log_info("CCC Index %u: Delete", index); 983 tlv_impl->delete_tag(tlv_context, tag); 984 } 985} 986 987static void att_server_persistent_ccc_restore(hci_connection_t * hci_connection){ 988 if (!hci_connection) return; 989 att_server_t * att_server = &hci_connection->att_server; | 858 break; 859 default: 860 break; 861 } 862 break; 863 864 case ATT_DATA_PACKET: 865 log_debug("ATT Packet, handle 0x%04x", handle); --- 134 unchanged lines hidden (view full) --- 1000 log_info("CCC Index %u: Delete", index); 1001 tlv_impl->delete_tag(tlv_context, tag); 1002 } 1003} 1004 1005static void att_server_persistent_ccc_restore(hci_connection_t * hci_connection){ 1006 if (!hci_connection) return; 1007 att_server_t * att_server = &hci_connection->att_server; |
1008 att_connection_t * att_connection = att_connection_for_hci_connection(hci_connection); |
|
990 991 int le_device_index = att_server->ir_le_device_db_index; 992 log_info("Restore CCC values of remote %s, le device id %d", bd_addr_to_str(att_server->peer_address), le_device_index); 993 // check if bonded 994 if (le_device_index < 0) return; 995 // get btstack_tlv 996 const btstack_tlv_t * tlv_impl = NULL; 997 void * tlv_context; --- 9 unchanged lines hidden (view full) --- 1007 if (entry.device_index != le_device_index) continue; 1008 // simulate write callback 1009 uint16_t attribute_handle = entry.att_handle; 1010 uint8_t value[2]; 1011 little_endian_store_16(value, 0, entry.value); 1012 att_write_callback_t callback = att_server_write_callback_for_handle(attribute_handle); 1013 if (!callback) continue; 1014 log_info("CCC Index %u: Set Attribute handle 0x%04x to value 0x%04x", index, attribute_handle, entry.value ); | 1009 1010 int le_device_index = att_server->ir_le_device_db_index; 1011 log_info("Restore CCC values of remote %s, le device id %d", bd_addr_to_str(att_server->peer_address), le_device_index); 1012 // check if bonded 1013 if (le_device_index < 0) return; 1014 // get btstack_tlv 1015 const btstack_tlv_t * tlv_impl = NULL; 1016 void * tlv_context; --- 9 unchanged lines hidden (view full) --- 1026 if (entry.device_index != le_device_index) continue; 1027 // simulate write callback 1028 uint16_t attribute_handle = entry.att_handle; 1029 uint8_t value[2]; 1030 little_endian_store_16(value, 0, entry.value); 1031 att_write_callback_t callback = att_server_write_callback_for_handle(attribute_handle); 1032 if (!callback) continue; 1033 log_info("CCC Index %u: Set Attribute handle 0x%04x to value 0x%04x", index, attribute_handle, entry.value ); |
1015 (*callback)(att_server->connection.con_handle, attribute_handle, ATT_TRANSACTION_MODE_NONE, 0, value, sizeof(value)); | 1034 (*callback)(att_connection->con_handle, attribute_handle, ATT_TRANSACTION_MODE_NONE, 0, value, sizeof(value)); |
1016 } 1017} 1018 1019// persistent CCC writes 1020// --------------------- 1021 1022// gatt service management 1023static att_service_handler_t * att_service_handler_for_handle(uint16_t handle){ --- 166 unchanged lines hidden (view full) --- 1190 } else { 1191 return ERROR_CODE_COMMAND_DISALLOWED; 1192 } 1193} 1194 1195int att_server_notify(hci_con_handle_t con_handle, uint16_t attribute_handle, const uint8_t *value, uint16_t value_len){ 1196 hci_connection_t * hci_connection = hci_connection_for_handle(con_handle); 1197 if (!hci_connection) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; | 1035 } 1036} 1037 1038// persistent CCC writes 1039// --------------------- 1040 1041// gatt service management 1042static att_service_handler_t * att_service_handler_for_handle(uint16_t handle){ --- 166 unchanged lines hidden (view full) --- 1209 } else { 1210 return ERROR_CODE_COMMAND_DISALLOWED; 1211 } 1212} 1213 1214int att_server_notify(hci_con_handle_t con_handle, uint16_t attribute_handle, const uint8_t *value, uint16_t value_len){ 1215 hci_connection_t * hci_connection = hci_connection_for_handle(con_handle); 1216 if (!hci_connection) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; |
1198 att_server_t * att_server = &hci_connection->att_server; | 1217 att_connection_t * att_connection = att_connection_for_hci_connection(hci_connection); |
1199 1200 if (!att_server_can_send_packet(hci_connection)) return BTSTACK_ACL_BUFFERS_FULL; 1201 1202 l2cap_reserve_packet_buffer(); 1203 uint8_t * packet_buffer = l2cap_get_outgoing_buffer(); | 1218 1219 if (!att_server_can_send_packet(hci_connection)) return BTSTACK_ACL_BUFFERS_FULL; 1220 1221 l2cap_reserve_packet_buffer(); 1222 uint8_t * packet_buffer = l2cap_get_outgoing_buffer(); |
1204 uint16_t size = att_prepare_handle_value_notification(&att_server->connection, attribute_handle, value, value_len, packet_buffer); 1205 return l2cap_send_prepared_connectionless(att_server->connection.con_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, size); | 1223 uint16_t size = att_prepare_handle_value_notification(att_connection, attribute_handle, value, value_len, packet_buffer); 1224 return l2cap_send_prepared_connectionless(att_connection->con_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, size); |
1206} 1207 1208int att_server_indicate(hci_con_handle_t con_handle, uint16_t attribute_handle, const uint8_t *value, uint16_t value_len){ 1209 hci_connection_t * hci_connection = hci_connection_for_handle(con_handle); 1210 if (!hci_connection) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 1211 att_server_t * att_server = &hci_connection->att_server; | 1225} 1226 1227int att_server_indicate(hci_con_handle_t con_handle, uint16_t attribute_handle, const uint8_t *value, uint16_t value_len){ 1228 hci_connection_t * hci_connection = hci_connection_for_handle(con_handle); 1229 if (!hci_connection) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 1230 att_server_t * att_server = &hci_connection->att_server; |
1231 att_connection_t * att_connection = att_connection_for_hci_connection(hci_connection); |
|
1212 1213 if (att_server->value_indication_handle) return ATT_HANDLE_VALUE_INDICATION_IN_PROGRESS; 1214 if (!att_server_can_send_packet(hci_connection)) return BTSTACK_ACL_BUFFERS_FULL; 1215 1216 // track indication 1217 att_server->value_indication_handle = attribute_handle; 1218 btstack_run_loop_set_timer_handler(&att_server->value_indication_timer, att_handle_value_indication_timeout); 1219 btstack_run_loop_set_timer(&att_server->value_indication_timer, ATT_TRANSACTION_TIMEOUT_MS); 1220 btstack_run_loop_add_timer(&att_server->value_indication_timer); 1221 1222 l2cap_reserve_packet_buffer(); 1223 uint8_t * packet_buffer = l2cap_get_outgoing_buffer(); | 1232 1233 if (att_server->value_indication_handle) return ATT_HANDLE_VALUE_INDICATION_IN_PROGRESS; 1234 if (!att_server_can_send_packet(hci_connection)) return BTSTACK_ACL_BUFFERS_FULL; 1235 1236 // track indication 1237 att_server->value_indication_handle = attribute_handle; 1238 btstack_run_loop_set_timer_handler(&att_server->value_indication_timer, att_handle_value_indication_timeout); 1239 btstack_run_loop_set_timer(&att_server->value_indication_timer, ATT_TRANSACTION_TIMEOUT_MS); 1240 btstack_run_loop_add_timer(&att_server->value_indication_timer); 1241 1242 l2cap_reserve_packet_buffer(); 1243 uint8_t * packet_buffer = l2cap_get_outgoing_buffer(); |
1224 uint16_t size = att_prepare_handle_value_indication(&att_server->connection, attribute_handle, value, value_len, packet_buffer); 1225 l2cap_send_prepared_connectionless(att_server->connection.con_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, size); | 1244 uint16_t size = att_prepare_handle_value_indication(att_connection, attribute_handle, value, value_len, packet_buffer); 1245 l2cap_send_prepared_connectionless(att_connection->con_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, size); |
1226 return 0; 1227} 1228 1229uint16_t att_server_get_mtu(hci_con_handle_t con_handle){ 1230 hci_connection_t * hci_connection = hci_connection_for_handle(con_handle); 1231 if (!hci_connection) return 0; | 1246 return 0; 1247} 1248 1249uint16_t att_server_get_mtu(hci_con_handle_t con_handle){ 1250 hci_connection_t * hci_connection = hci_connection_for_handle(con_handle); 1251 if (!hci_connection) return 0; |
1232 att_server_t * att_server = &hci_connection->att_server; 1233 return att_server->connection.mtu; | 1252 att_connection_t * att_connection = att_connection_for_hci_connection(hci_connection); 1253 return att_connection->mtu; |
1234} | 1254} |