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 ---