hid_host.c (63bf37cdf290a24499821ad093bb095cca27d8e2) | hid_host.c (fd7ba7a6d25e1504d0db40d88bc9982ee89b87bd) |
---|---|
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 --- 31 unchanged lines hidden (view full) --- 40#include <string.h> 41 42#include "bluetooth.h" 43#include "bluetooth_psm.h" 44#include "bluetooth_sdp.h" 45#include "btstack_debug.h" 46#include "btstack_event.h" 47#include "btstack_hid_parser.h" | 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 --- 31 unchanged lines hidden (view full) --- 40#include <string.h> 41 42#include "bluetooth.h" 43#include "bluetooth_psm.h" 44#include "bluetooth_sdp.h" 45#include "btstack_debug.h" 46#include "btstack_event.h" 47#include "btstack_hid_parser.h" |
48#include "btstack_memory.h" |
|
48#include "classic/hid.h" 49#include "classic/hid_host.h" 50#include "classic/sdp_util.h" | 49#include "classic/hid.h" 50#include "classic/hid_host.h" 51#include "classic/sdp_util.h" |
52#include "classic/sdp_client.h" |
|
51#include "l2cap.h" 52 | 53#include "l2cap.h" 54 |
53typedef enum { 54 HID_HOST_IDLE, 55 HID_HOST_CONTROL_CONNECTION_ESTABLISHED, 56 HID_HOST_W4_SET_BOOT_MODE, 57 HID_HOST_W4_INTERRUPT_CONNECTION_ESTABLISHED, 58 HID_HOST_CONNECTION_ESTABLISHED, 59 HID_HOST_W2_SEND_GET_REPORT, 60 HID_HOST_W4_GET_REPORT_RESPONSE, 61 HID_HOST_W2_SEND_SET_REPORT, 62 HID_HOST_W4_SET_REPORT_RESPONSE, 63 HID_HOST_W2_SEND_GET_PROTOCOL, 64 HID_HOST_W4_GET_PROTOCOL_RESPONSE, 65 HID_HOST_W2_SEND_SET_PROTOCOL, 66 HID_HOST_W4_SET_PROTOCOL_RESPONSE, 67 HID_HOST_W2_SEND_REPORT, 68 HID_HOST_W4_SEND_REPORT_RESPONSE 69} hid_host_state_t; | 55#define MAX_ATTRIBUTE_VALUE_SIZE 300 |
70 | 56 |
71typedef struct { 72 uint16_t cid; 73 bd_addr_t bd_addr; 74 hci_con_handle_t con_handle; 75 uint16_t control_cid; 76 uint16_t interrupt_cid; | 57static btstack_packet_handler_t hid_callback; |
77 | 58 |
78 hid_host_state_t state; 79 hid_protocol_mode_t protocol_mode; | 59static uint8_t * hid_host_descriptor_storage; 60static uint16_t hid_host_descriptor_storage_len; |
80 | 61 |
81 uint8_t user_request_can_send_now; | 62static btstack_linked_list_t connections; 63static uint16_t hid_host_cid_counter = 0; |
82 | 64 |
83 // get report 84 hid_report_type_t report_type; 85 uint8_t report_id; | 65// SDP 66static uint8_t attribute_value[MAX_ATTRIBUTE_VALUE_SIZE]; 67static const unsigned int attribute_value_buffer_size = MAX_ATTRIBUTE_VALUE_SIZE; |
86 | 68 |
87 // set report 88 uint8_t * report; 89 uint16_t report_len; 90} hid_host_connection_t; | 69static uint16_t sdp_query_context_hid_host_control_cid = 0; |
91 | 70 |
92static const uint8_t * hid_host_descriptor_storage; 93static uint16_t hid_host_descriptor_storage_len; | 71static btstack_context_callback_registration_t hid_host_handle_sdp_client_query_request; 72static void hid_host_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); |
94 | 73 |
95static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ | 74static uint16_t hid_descriptor_storage_get_available_space(void){ 75 // assumes all descriptors are back to back 76 uint16_t free_space = hid_host_descriptor_storage_len; 77 78 btstack_linked_list_iterator_t it; 79 btstack_linked_list_iterator_init(&it, &connections); 80 while (btstack_linked_list_iterator_has_next(&it)){ 81 hid_host_connection_t * connection = (hid_host_connection_t *)btstack_linked_list_iterator_next(&it); 82 free_space -= connection->hid_descriptor_len; 83 } 84 return free_space; 85} 86 87static void hid_descriptor_storage_init(hid_host_connection_t * connection){ 88 connection->hid_descriptor_len = 0; 89 connection->hid_descriptor_max_len = hid_descriptor_storage_get_available_space(); 90 connection->hid_descriptor_offset = hid_host_descriptor_storage_len - connection->hid_descriptor_max_len; 91} 92 93static bool hid_descriptor_storage_store(hid_host_connection_t * connection, uint8_t byte){ 94 if (connection->hid_descriptor_len >= connection->hid_descriptor_max_len) return false; 95 96 hid_host_descriptor_storage[connection->hid_descriptor_offset + connection->hid_descriptor_len] = byte; 97 connection->hid_descriptor_len++; 98 return true; 99} 100 101 102static void hid_descriptor_storage_delete(hid_host_connection_t * connection){ 103 uint16_t next_offset = connection->hid_descriptor_offset + connection->hid_descriptor_len; 104 105 memmove(&hid_host_descriptor_storage[connection->hid_descriptor_offset], 106 &hid_host_descriptor_storage[next_offset], 107 hid_host_descriptor_storage_len - next_offset); 108 109 connection->hid_descriptor_len = 0; 110 connection->hid_descriptor_offset = 0; 111 112 btstack_linked_list_iterator_t it; 113 btstack_linked_list_iterator_init(&it, &connections); 114 while (btstack_linked_list_iterator_has_next(&it)){ 115 hid_host_connection_t * conn = (hid_host_connection_t *)btstack_linked_list_iterator_next(&it); 116 if (conn->hid_descriptor_offset >= next_offset){ 117 conn->hid_descriptor_offset = next_offset; 118 next_offset += conn->hid_descriptor_len; 119 } 120 } 121} 122 123// HID Util 124static inline void hid_emit_connected_event(hid_host_connection_t * context, uint8_t status){ 125 uint8_t event[15]; 126 int pos = 0; 127 event[pos++] = HCI_EVENT_HID_META; 128 pos++; // skip len 129 event[pos++] = HID_SUBEVENT_CONNECTION_OPENED; 130 little_endian_store_16(event, pos, context->hid_cid); 131 pos+=2; 132 event[pos++] = status; 133 reverse_bd_addr(context->remote_addr, &event[pos]); 134 pos += 6; 135 little_endian_store_16(event,pos,context->con_handle); 136 pos += 2; 137 event[pos++] = context->incoming; 138 event[1] = pos - 2; 139 hid_callback(HCI_EVENT_PACKET, context->hid_cid, &event[0], pos); 140} 141 142// HID Host 143 144static uint16_t hid_host_get_next_cid(void){ 145 if (hid_host_cid_counter == 0xffff) { 146 hid_host_cid_counter = 1; 147 } else { 148 hid_host_cid_counter++; 149 } 150 return hid_host_cid_counter; 151} 152 153static hid_host_connection_t * hid_host_create_connection(bd_addr_t remote_addr){ 154 hid_host_connection_t * connection = btstack_memory_hid_host_connection_get(); 155 if (!connection){ 156 log_error("Not enough memory to create connection"); 157 return NULL; 158 } 159 connection->state = HID_HOST_IDLE; 160 connection->hid_cid = hid_host_get_next_cid(); 161 (void)memcpy(connection->remote_addr, remote_addr, 6); 162 printf("hid_host_create_connection, cid 0x%02x, %s \n", connection->hid_cid, bd_addr_to_str(connection->remote_addr)); 163 164 btstack_linked_list_add(&connections, (btstack_linked_item_t *) connection); 165 return connection; 166} 167 168static hid_host_connection_t * hid_host_get_connection_for_bd_addr(bd_addr_t addr){ 169 btstack_linked_list_iterator_t it; 170 btstack_linked_list_iterator_init(&it, &connections); 171 while (btstack_linked_list_iterator_has_next(&it)){ 172 hid_host_connection_t * connection = (hid_host_connection_t *)btstack_linked_list_iterator_next(&it); 173 if (memcmp(addr, connection->remote_addr, 6) != 0) continue; 174 return connection; 175 } 176 return NULL; 177} 178 179static hid_host_connection_t * hid_host_connection_for_hid_cid(uint16_t hid_cid){ 180 btstack_linked_list_iterator_t it; 181 btstack_linked_list_iterator_init(&it, &connections); 182 while (btstack_linked_list_iterator_has_next(&it)){ 183 hid_host_connection_t * connection = (hid_host_connection_t *)btstack_linked_list_iterator_next(&it); 184 if (connection->hid_cid != hid_cid) continue; 185 return connection; 186 } 187 return NULL; 188} 189 190static void hid_host_finalize_connection(hid_host_connection_t * connection){ 191 btstack_linked_list_remove(&connections, (btstack_linked_item_t*) connection); 192 btstack_memory_hid_host_connection_free(connection); 193} 194 195static void hid_host_handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) { 196 UNUSED(packet_type); 197 UNUSED(channel); 198 UNUSED(size); 199 200 des_iterator_t attribute_list_it; 201 des_iterator_t additional_des_it; 202 des_iterator_t prot_it; 203 uint8_t *des_element; 204 uint8_t *element; 205 uint32_t uuid; 206 uint8_t status = ERROR_CODE_SUCCESS; 207 208 hid_host_connection_t * connection = hid_host_connection_for_hid_cid(sdp_query_context_hid_host_control_cid); 209 if (!connection) { 210 log_error("SDP query, connection with 0x%02x cid not found", sdp_query_context_hid_host_control_cid); 211 return; 212 } 213 214 switch (hci_event_packet_get_type(packet)){ 215 case SDP_EVENT_QUERY_ATTRIBUTE_VALUE: 216 217 if (sdp_event_query_attribute_byte_get_attribute_length(packet) <= attribute_value_buffer_size) { 218 219 attribute_value[sdp_event_query_attribute_byte_get_data_offset(packet)] = sdp_event_query_attribute_byte_get_data(packet); 220 221 if ((uint16_t)(sdp_event_query_attribute_byte_get_data_offset(packet)+1) == sdp_event_query_attribute_byte_get_attribute_length(packet)) { 222 switch(sdp_event_query_attribute_byte_get_attribute_id(packet)) { 223 224 case BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST: 225 for (des_iterator_init(&attribute_list_it, attribute_value); des_iterator_has_more(&attribute_list_it); des_iterator_next(&attribute_list_it)) { 226 if (des_iterator_get_type(&attribute_list_it) != DE_DES) continue; 227 des_element = des_iterator_get_element(&attribute_list_it); 228 des_iterator_init(&prot_it, des_element); 229 element = des_iterator_get_element(&prot_it); 230 if (de_get_element_type(element) != DE_UUID) continue; 231 uuid = de_get_uuid32(element); 232 switch (uuid){ 233 case BLUETOOTH_PROTOCOL_L2CAP: 234 if (!des_iterator_has_more(&prot_it)) continue; 235 des_iterator_next(&prot_it); 236 de_element_get_uint16(des_iterator_get_element(&prot_it), &connection->control_psm); 237 log_info("HID Control PSM: 0x%04x", (int) &connection->control_psm); 238 break; 239 default: 240 break; 241 } 242 } 243 break; 244 case BLUETOOTH_ATTRIBUTE_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS: 245 for (des_iterator_init(&attribute_list_it, attribute_value); des_iterator_has_more(&attribute_list_it); des_iterator_next(&attribute_list_it)) { 246 if (des_iterator_get_type(&attribute_list_it) != DE_DES) continue; 247 des_element = des_iterator_get_element(&attribute_list_it); 248 for (des_iterator_init(&additional_des_it, des_element); des_iterator_has_more(&additional_des_it); des_iterator_next(&additional_des_it)) { 249 if (des_iterator_get_type(&additional_des_it) != DE_DES) continue; 250 des_element = des_iterator_get_element(&additional_des_it); 251 des_iterator_init(&prot_it, des_element); 252 element = des_iterator_get_element(&prot_it); 253 if (de_get_element_type(element) != DE_UUID) continue; 254 uuid = de_get_uuid32(element); 255 switch (uuid){ 256 case BLUETOOTH_PROTOCOL_L2CAP: 257 if (!des_iterator_has_more(&prot_it)) continue; 258 des_iterator_next(&prot_it); 259 de_element_get_uint16(des_iterator_get_element(&prot_it), &connection->interrupt_psm); 260 log_info("HID Interrupt PSM: 0x%04x", (int) &connection->interrupt_psm); 261 break; 262 default: 263 break; 264 } 265 } 266 } 267 break; 268 269 case BLUETOOTH_ATTRIBUTE_HID_DESCRIPTOR_LIST: 270 for (des_iterator_init(&attribute_list_it, attribute_value); des_iterator_has_more(&attribute_list_it); des_iterator_next(&attribute_list_it)) { 271 if (des_iterator_get_type(&attribute_list_it) != DE_DES) continue; 272 des_element = des_iterator_get_element(&attribute_list_it); 273 for (des_iterator_init(&additional_des_it, des_element); des_iterator_has_more(&additional_des_it); des_iterator_next(&additional_des_it)) { 274 if (des_iterator_get_type(&additional_des_it) != DE_STRING) continue; 275 element = des_iterator_get_element(&additional_des_it); 276 277 const uint8_t * descriptor = de_get_string(element); 278 uint16_t descriptor_len = de_get_data_size(element); 279 280 uint16_t i; 281 for (i = 0; i < descriptor_len; i++){ 282 hid_descriptor_storage_store(connection, descriptor[i]); 283 } 284 printf("HID Descriptor:\n"); 285 printf_hexdump(descriptor, descriptor_len); 286 } 287 } 288 break; 289 default: 290 break; 291 } 292 } 293 } else { 294 fprintf(stderr, "SDP attribute value buffer size exceeded: available %d, required %d\n", attribute_value_buffer_size, sdp_event_query_attribute_byte_get_attribute_length(packet)); 295 } 296 break; 297 298 case SDP_EVENT_QUERY_COMPLETE: 299 if (!connection->control_psm) { 300 printf("HID Control PSM missing\n"); 301 status = ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE; 302 break; 303 } 304 if (!connection->interrupt_psm) { 305 printf("HID Interrupt PSM missing\n"); 306 status = ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE; 307 break; 308 } 309 310 printf("Setup HID\n"); 311 status = l2cap_create_channel(hid_host_packet_handler, connection->remote_addr, connection->control_psm, 48, &connection->control_cid); 312 if (status){ 313 printf("Connecting to HID Control failed: 0x%02x\n", status); 314 } 315 break; 316 317 default: 318 // bail out, we must have had an incoming connection in the meantime; just trigger next sdp query on complete 319 if (hci_event_packet_get_type(packet) == SDP_EVENT_QUERY_COMPLETE){ 320 (void) sdp_client_register_query_callback(&hid_host_handle_sdp_client_query_request); 321 } 322 return; 323 } 324 325 if (status != ERROR_CODE_SUCCESS){ 326 hid_emit_connected_event(connection, status); 327 hid_host_finalize_connection(connection); 328 sdp_query_context_hid_host_control_cid = 0; 329 } 330} 331 332static void hid_host_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 333 UNUSED(channel); 334 UNUSED(size); 335 |
96 uint8_t event; | 336 uint8_t event; |
97 // bd_addr_t address; 98 // uint8_t status; 99 // uint16_t l2cap_cid; 100 // hid_host_t * hid_host; | 337 bd_addr_t address; 338 uint8_t status; 339 uint16_t cid; 340 hid_host_connection_t * connection; 341 |
101 // uint8_t param; 102 // hid_message_type_t message_type; 103 // hid_handshake_param_type_t message_status; 104 105 switch (packet_type) { 106 case HCI_EVENT_PACKET: 107 event = hci_event_packet_get_type(packet); 108 switch (event) { | 342 // uint8_t param; 343 // hid_message_type_t message_type; 344 // hid_handshake_param_type_t message_status; 345 346 switch (packet_type) { 347 case HCI_EVENT_PACKET: 348 event = hci_event_packet_get_type(packet); 349 switch (event) { |
109 case BTSTACK_EVENT_STATE: 110 if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){ 111 printf("BTstack up and running. \n"); | 350 case L2CAP_EVENT_INCOMING_CONNECTION: 351 l2cap_event_incoming_connection_get_address(packet, address); 352 connection = hid_host_get_connection_for_bd_addr(address); 353 354 if (connection && connection->unplugged){ 355 log_info("Decline connection for %s, host is unplugged", bd_addr_to_str(address)); 356 l2cap_decline_connection(channel); 357 break; |
112 } | 358 } |
359 360 switch (l2cap_event_incoming_connection_get_psm(packet)){ 361 case PSM_HID_CONTROL: 362 if (connection){ 363 log_error("Connection already exists %s", bd_addr_to_str(address)); 364 l2cap_decline_connection(channel); 365 break; 366 } 367 368 connection = hid_host_create_connection(address); 369 if (!connection) { 370 log_error("Cannot create connection for %s", bd_addr_to_str(address)); 371 l2cap_decline_connection(channel); 372 break; 373 } 374 375 connection->state = HID_HOST_W4_CONTROL_CONNECTION_ESTABLISHED; 376 connection->con_handle = l2cap_event_incoming_connection_get_handle(packet); 377 connection->control_cid = l2cap_event_incoming_connection_get_local_cid(packet); 378 connection->incoming = true; 379 log_info("Accept connection on Control channel %s", bd_addr_to_str(address)); 380 l2cap_accept_connection(channel); 381 break; 382 383 case PSM_HID_INTERRUPT: 384 if (!connection || (connection->interrupt_cid != 0) || (l2cap_event_incoming_connection_get_handle(packet) != connection->con_handle)){ 385 log_error("Decline connection for %s", bd_addr_to_str(address)); 386 l2cap_decline_connection(channel); 387 break; 388 } 389 390 connection->state = HID_HOST_W4_INTERRUPT_CONNECTION_ESTABLISHED; 391 connection->interrupt_cid = l2cap_event_incoming_connection_get_local_cid(packet); 392 log_info("Accept connection on Interrupt channel %s", bd_addr_to_str(address)); 393 l2cap_accept_connection(channel); 394 break; 395 396 default: 397 log_info("Decline connection for %s", bd_addr_to_str(address)); 398 l2cap_decline_connection(channel); 399 break; 400 } |
|
113 break; | 401 break; |
402 403 case L2CAP_EVENT_CHANNEL_OPENED: 404 l2cap_event_channel_opened_get_address(packet, address); 405 406 status = l2cap_event_channel_opened_get_status(packet); 407 if (status){ 408 log_info("L2CAP connection %s failed: 0x%02xn", bd_addr_to_str(address), status); 409 break; 410 } 411 412 connection = hid_host_get_connection_for_bd_addr(address); 413 if (!connection){ 414 log_error("Connection does not exist %s", bd_addr_to_str(address)); 415 break; 416 } 417 418 cid = l2cap_event_channel_opened_get_local_cid(packet); 419 420 switch (l2cap_event_channel_opened_get_psm(packet)){ 421 case PSM_HID_CONTROL: 422 if (connection->state != HID_HOST_W4_CONTROL_CONNECTION_ESTABLISHED) break; 423 connection->state = HID_HOST_CONTROL_CONNECTION_ESTABLISHED; 424 425 if (connection->boot_mode){ 426 break; 427 } 428 429 if (!connection->incoming){ 430 status = l2cap_create_channel(hid_host_packet_handler, address, connection->interrupt_psm, 48, &connection->interrupt_cid); 431 if (status){ 432 log_info("Connecting to HID Interrupt failed: 0x%02x", status); 433 break; 434 } 435 connection->con_handle = l2cap_event_channel_opened_get_handle(packet); 436 connection->state = HID_HOST_W4_INTERRUPT_CONNECTION_ESTABLISHED; 437 } 438 break; 439 440 case PSM_HID_INTERRUPT: 441 if (connection->state != HID_HOST_W4_INTERRUPT_CONNECTION_ESTABLISHED) break; 442 if (connection->con_handle != l2cap_event_channel_opened_get_handle(packet)) break; 443 444 connection->state = HID_HOST_CONNECTION_ESTABLISHED; 445 hid_emit_connected_event(connection, ERROR_CODE_SUCCESS); 446 447 log_info("Connection on interrupt channel established, interrupt_cid 0x%02x", connection->interrupt_cid); 448 break; 449 450 default: 451 break; 452 } 453 // disconnect? 454 break; 455 |
|
114 default: 115 break; 116 } 117 default: 118 break; 119 } 120} 121 | 456 default: 457 break; 458 } 459 default: 460 break; 461 } 462} 463 |
122void hid_host_init(const uint8_t * hid_descriptor_storage, uint16_t hid_descriptor_storage_len){ | 464 465void hid_host_init(uint8_t * hid_descriptor_storage, uint16_t hid_descriptor_storage_len){ |
123 hid_host_descriptor_storage = hid_descriptor_storage; 124 hid_host_descriptor_storage_len = hid_descriptor_storage_len; 125 126 // register L2CAP Services for reconnections | 466 hid_host_descriptor_storage = hid_descriptor_storage; 467 hid_host_descriptor_storage_len = hid_descriptor_storage_len; 468 469 // register L2CAP Services for reconnections |
127 l2cap_register_service(packet_handler, PSM_HID_INTERRUPT, 0xffff, gap_get_security_level()); 128 l2cap_register_service(packet_handler, PSM_HID_CONTROL, 0xffff, gap_get_security_level()); | 470 l2cap_register_service(hid_host_packet_handler, PSM_HID_INTERRUPT, 0xffff, gap_get_security_level()); 471 l2cap_register_service(hid_host_packet_handler, PSM_HID_CONTROL, 0xffff, gap_get_security_level()); |
129} 130 131void hid_host_register_packet_handler(btstack_packet_handler_t callback){ | 472} 473 474void hid_host_register_packet_handler(btstack_packet_handler_t callback){ |
132 UNUSED(callback); | 475 hid_callback = callback; |
133} 134 | 476} 477 |
135uint8_t hid_host_connect(bd_addr_t addr, hid_protocol_mode_t protocol_mode, uint16_t * hid_cid){ 136 UNUSED(hid_cid); | 478 479static void hid_host_handle_start_sdp_client_query(void * context){ 480 UNUSED(context); 481 482 btstack_linked_list_iterator_t it; 483 btstack_linked_list_iterator_init(&it, &connections); 484 while (btstack_linked_list_iterator_has_next(&it)){ 485 hid_host_connection_t * connection = (hid_host_connection_t *)btstack_linked_list_iterator_next(&it); 486 487 switch (connection->state){ 488 case HID_HOST_W2_SEND_SDP_QUERY: 489 connection->state = HID_HOST_W4_SDP_QUERY_RESULT; 490 break; 491 default: 492 continue; 493 } 494 printf("hid_descriptor_storage_init, start query, cid 0x%02x, %s \n", connection->hid_cid, bd_addr_to_str(connection->remote_addr)); 495 hid_descriptor_storage_init(connection); 496 sdp_query_context_hid_host_control_cid = connection->hid_cid; 497 sdp_client_query_uuid16(&hid_host_handle_sdp_client_query_result, (uint8_t *) connection->remote_addr, BLUETOOTH_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE_SERVICE); 498 return; 499 } 500} 501 502uint8_t hid_host_connect(bd_addr_t remote_addr, hid_protocol_mode_t protocol_mode, uint16_t * hid_cid){ |
137 UNUSED(protocol_mode); | 503 UNUSED(protocol_mode); |
504 505 if (hid_cid == NULL) { 506 return ERROR_CODE_COMMAND_DISALLOWED; 507 } 508 509 hid_host_connection_t * connection = hid_host_get_connection_for_bd_addr(remote_addr); 510 if (connection){ 511 return ERROR_CODE_COMMAND_DISALLOWED; 512 } 513 514 connection = hid_host_create_connection(remote_addr); 515 if (!connection) return BTSTACK_MEMORY_ALLOC_FAILED; 516 517 518 *hid_cid = connection->hid_cid; 519 520 connection->state = HID_HOST_W2_SEND_SDP_QUERY; 521 connection->incoming = false; 522 connection->control_cid = 0; 523 connection->control_psm = 0; 524 connection->interrupt_cid = 0; 525 connection->interrupt_psm = 0; 526 printf("hid_host_connect, cid 0x%02x, %s \n", connection->hid_cid, bd_addr_to_str(connection->remote_addr)); 527 528 hid_host_handle_sdp_client_query_request.callback = &hid_host_handle_start_sdp_client_query; 529 // ignore ERROR_CODE_COMMAND_DISALLOWED because in that case, we already have requested an SDP callback 530 (void) sdp_client_register_query_callback(&hid_host_handle_sdp_client_query_request); 531 |
|
138 return ERROR_CODE_SUCCESS; 139} 140 141 142void hid_host_disconnect(uint16_t hid_cid){ 143 UNUSED(hid_cid); 144} 145 --- 15 unchanged lines hidden --- | 532 return ERROR_CODE_SUCCESS; 533} 534 535 536void hid_host_disconnect(uint16_t hid_cid){ 537 UNUSED(hid_cid); 538} 539 --- 15 unchanged lines hidden --- |