xref: /btstack/src/classic/hid_device.c (revision 45a58b3093f5320b8ffda59b52081d2b540d3217)
1d40c9ac6SMatthias Ringwald /*
2d40c9ac6SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
3d40c9ac6SMatthias Ringwald  *
4d40c9ac6SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5d40c9ac6SMatthias Ringwald  * modification, are permitted provided that the following conditions
6d40c9ac6SMatthias Ringwald  * are met:
7d40c9ac6SMatthias Ringwald  *
8d40c9ac6SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9d40c9ac6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10d40c9ac6SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11d40c9ac6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12d40c9ac6SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13d40c9ac6SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14d40c9ac6SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15d40c9ac6SMatthias Ringwald  *    from this software without specific prior written permission.
16d40c9ac6SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17d40c9ac6SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18d40c9ac6SMatthias Ringwald  *    monetary gain.
19d40c9ac6SMatthias Ringwald  *
20d40c9ac6SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21d40c9ac6SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22d40c9ac6SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23d40c9ac6SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24d40c9ac6SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25d40c9ac6SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26d40c9ac6SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27d40c9ac6SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28d40c9ac6SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29d40c9ac6SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30d40c9ac6SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31d40c9ac6SMatthias Ringwald  * SUCH DAMAGE.
32d40c9ac6SMatthias Ringwald  *
33d40c9ac6SMatthias Ringwald  * Please inquire about commercial licensing options at
34d40c9ac6SMatthias Ringwald  * [email protected]
35d40c9ac6SMatthias Ringwald  *
36d40c9ac6SMatthias Ringwald  */
37d40c9ac6SMatthias Ringwald 
38d40c9ac6SMatthias Ringwald #define __BTSTACK_FILE__ "hid_device.c"
39d40c9ac6SMatthias Ringwald 
40d40c9ac6SMatthias Ringwald #include <string.h>
41d40c9ac6SMatthias Ringwald 
42d40c9ac6SMatthias Ringwald #include "classic/hid_device.h"
43d40c9ac6SMatthias Ringwald #include "classic/sdp_util.h"
44d40c9ac6SMatthias Ringwald #include "bluetooth.h"
45d40c9ac6SMatthias Ringwald #include "bluetooth_sdp.h"
468eb8d463SMatthias Ringwald #include "l2cap.h"
478eb8d463SMatthias Ringwald #include "btstack_event.h"
488eb8d463SMatthias Ringwald #include "btstack_debug.h"
498eb8d463SMatthias Ringwald 
508eb8d463SMatthias Ringwald // hid device state
518eb8d463SMatthias Ringwald typedef struct hid_device {
528eb8d463SMatthias Ringwald     uint16_t  cid;
538eb8d463SMatthias Ringwald     bd_addr_t bd_addr;
548eb8d463SMatthias Ringwald     hci_con_handle_t con_handle;
558eb8d463SMatthias Ringwald     uint16_t  control_cid;
568eb8d463SMatthias Ringwald     uint16_t  interrupt_cid;
578eb8d463SMatthias Ringwald     uint8_t   incoming;
588eb8d463SMatthias Ringwald } hid_device_t;
598eb8d463SMatthias Ringwald 
608eb8d463SMatthias Ringwald static hid_device_t _hid_device;
618eb8d463SMatthias Ringwald static hid_device_t * hid_device = &_hid_device;
628eb8d463SMatthias Ringwald 
638eb8d463SMatthias Ringwald static btstack_packet_handler_t hid_callback;
64d40c9ac6SMatthias Ringwald 
65d40c9ac6SMatthias Ringwald void hid_create_sdp_record(
66d40c9ac6SMatthias Ringwald     uint8_t *service,
67d40c9ac6SMatthias Ringwald     uint32_t service_record_handle,
68d40c9ac6SMatthias Ringwald     uint16_t hid_device_subclass,
69d40c9ac6SMatthias Ringwald     uint8_t  hid_country_code,
70d40c9ac6SMatthias Ringwald     uint8_t  hid_virtual_cable,
71d40c9ac6SMatthias Ringwald     uint8_t  hid_reconnect_initiate,
72d40c9ac6SMatthias Ringwald     uint8_t  hid_boot_device,
73d40c9ac6SMatthias Ringwald     const uint8_t * hid_descriptor, uint16_t hid_descriptor_size,
74d40c9ac6SMatthias Ringwald     const char *device_name){
75d40c9ac6SMatthias Ringwald 
76d40c9ac6SMatthias Ringwald     uint8_t * attribute;
77d40c9ac6SMatthias Ringwald     de_create_sequence(service);
78d40c9ac6SMatthias Ringwald 
79d40c9ac6SMatthias Ringwald     de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_RECORD_HANDLE);
80d40c9ac6SMatthias Ringwald     de_add_number(service, DE_UINT, DE_SIZE_32, service_record_handle);
81d40c9ac6SMatthias Ringwald 
82d40c9ac6SMatthias Ringwald     de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_CLASS_ID_LIST);
83d40c9ac6SMatthias Ringwald     attribute = de_push_sequence(service);
84d40c9ac6SMatthias Ringwald     {
85d40c9ac6SMatthias Ringwald         de_add_number(attribute,  DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE_SERVICE);
86d40c9ac6SMatthias Ringwald     }
87d40c9ac6SMatthias Ringwald     de_pop_sequence(service, attribute);
88d40c9ac6SMatthias Ringwald 
89d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST);
90d40c9ac6SMatthias Ringwald     attribute = de_push_sequence(service);
91d40c9ac6SMatthias Ringwald     {
92d40c9ac6SMatthias Ringwald         uint8_t * l2cpProtocol = de_push_sequence(attribute);
93d40c9ac6SMatthias Ringwald         {
94d40c9ac6SMatthias Ringwald             de_add_number(l2cpProtocol,  DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_L2CAP);
95d40c9ac6SMatthias Ringwald             de_add_number(l2cpProtocol,  DE_UINT, DE_SIZE_16, PSM_HID_CONTROL);
96d40c9ac6SMatthias Ringwald         }
97d40c9ac6SMatthias Ringwald         de_pop_sequence(attribute, l2cpProtocol);
98d40c9ac6SMatthias Ringwald 
99d40c9ac6SMatthias Ringwald         uint8_t * hidProtocol = de_push_sequence(attribute);
100d40c9ac6SMatthias Ringwald         {
101d40c9ac6SMatthias Ringwald             de_add_number(hidProtocol,  DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_HIDP);
102d40c9ac6SMatthias Ringwald         }
103d40c9ac6SMatthias Ringwald         de_pop_sequence(attribute, hidProtocol);
104d40c9ac6SMatthias Ringwald     }
105d40c9ac6SMatthias Ringwald     de_pop_sequence(service, attribute);
106d40c9ac6SMatthias Ringwald 
107d40c9ac6SMatthias Ringwald     // TODO?
108d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
109d40c9ac6SMatthias Ringwald     attribute = de_push_sequence(service);
110d40c9ac6SMatthias Ringwald     {
111d40c9ac6SMatthias Ringwald         de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x656e);
112d40c9ac6SMatthias Ringwald         de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x006a);
113d40c9ac6SMatthias Ringwald         de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x0100);
114d40c9ac6SMatthias Ringwald     }
115d40c9ac6SMatthias Ringwald     de_pop_sequence(service, attribute);
116d40c9ac6SMatthias Ringwald 
117d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS);
118d40c9ac6SMatthias Ringwald     attribute = de_push_sequence(service);
119d40c9ac6SMatthias Ringwald     {
120d40c9ac6SMatthias Ringwald         uint8_t * additionalDescriptorAttribute = de_push_sequence(attribute);
121d40c9ac6SMatthias Ringwald         {
122d40c9ac6SMatthias Ringwald             uint8_t * l2cpProtocol = de_push_sequence(additionalDescriptorAttribute);
123d40c9ac6SMatthias Ringwald             {
124d40c9ac6SMatthias Ringwald                 de_add_number(l2cpProtocol,  DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_L2CAP);
125d40c9ac6SMatthias Ringwald                 de_add_number(l2cpProtocol,  DE_UINT, DE_SIZE_16, PSM_HID_INTERRUPT);
126d40c9ac6SMatthias Ringwald             }
127d40c9ac6SMatthias Ringwald             de_pop_sequence(additionalDescriptorAttribute, l2cpProtocol);
128d40c9ac6SMatthias Ringwald 
129d40c9ac6SMatthias Ringwald             uint8_t * hidProtocol = de_push_sequence(attribute);
130d40c9ac6SMatthias Ringwald             {
131d40c9ac6SMatthias Ringwald                 de_add_number(hidProtocol,  DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_HIDP);
132d40c9ac6SMatthias Ringwald             }
133d40c9ac6SMatthias Ringwald             de_pop_sequence(attribute, hidProtocol);
134d40c9ac6SMatthias Ringwald         }
135d40c9ac6SMatthias Ringwald         de_pop_sequence(attribute, additionalDescriptorAttribute);
136d40c9ac6SMatthias Ringwald     }
137d40c9ac6SMatthias Ringwald     de_pop_sequence(service, attribute);
138d40c9ac6SMatthias Ringwald 
139d40c9ac6SMatthias Ringwald     // 0x0100 "ServiceName"
140d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, 0x0100);
141d40c9ac6SMatthias Ringwald     de_add_data(service,  DE_STRING, strlen(device_name), (uint8_t *) device_name);
142d40c9ac6SMatthias Ringwald 
143d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
144d40c9ac6SMatthias Ringwald     attribute = de_push_sequence(service);
145d40c9ac6SMatthias Ringwald     {
146d40c9ac6SMatthias Ringwald         uint8_t * hidProfile = de_push_sequence(attribute);
147d40c9ac6SMatthias Ringwald         {
148d40c9ac6SMatthias Ringwald             de_add_number(hidProfile,  DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE_SERVICE);
149d40c9ac6SMatthias Ringwald             de_add_number(hidProfile,  DE_UINT, DE_SIZE_16, 0x0101);    // Version 1.1
150d40c9ac6SMatthias Ringwald         }
151d40c9ac6SMatthias Ringwald         de_pop_sequence(attribute, hidProfile);
152d40c9ac6SMatthias Ringwald     }
153d40c9ac6SMatthias Ringwald     de_pop_sequence(service, attribute);
154d40c9ac6SMatthias Ringwald 
155d40c9ac6SMatthias Ringwald     // Deprecated in v1.1.1
156d40c9ac6SMatthias Ringwald     // de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_DEVICE_RELEASE_NUMBER);
157d40c9ac6SMatthias Ringwald     // de_add_number(service,  DE_UINT, DE_SIZE_16, 0x0101);
158d40c9ac6SMatthias Ringwald 
159d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_PARSER_VERSION);
160d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, 0x0111);  // v1.1.1
161d40c9ac6SMatthias Ringwald 
162d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_DEVICE_SUBCLASS);
1639679ea81SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_8,  hid_device_subclass);
164d40c9ac6SMatthias Ringwald 
165d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_COUNTRY_CODE);
1669679ea81SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_8,  hid_country_code);
167d40c9ac6SMatthias Ringwald 
168d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_VIRTUAL_CABLE);
169d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_BOOL, DE_SIZE_8,  hid_virtual_cable);
170d40c9ac6SMatthias Ringwald 
171d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_RECONNECT_INITIATE);
172d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_BOOL, DE_SIZE_8,  hid_reconnect_initiate);
173d40c9ac6SMatthias Ringwald 
174d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_DESCRIPTOR_LIST);
175d40c9ac6SMatthias Ringwald     attribute = de_push_sequence(service);
176d40c9ac6SMatthias Ringwald     {
177d40c9ac6SMatthias Ringwald         uint8_t* hidDescriptor = de_push_sequence(attribute);
178d40c9ac6SMatthias Ringwald         {
179d40c9ac6SMatthias Ringwald             de_add_number(hidDescriptor,  DE_UINT, DE_SIZE_8, 0x22);    // Report Descriptor
180d40c9ac6SMatthias Ringwald             de_add_data(hidDescriptor,  DE_STRING, hid_descriptor_size, (uint8_t *) hid_descriptor);
181d40c9ac6SMatthias Ringwald         }
182d40c9ac6SMatthias Ringwald         de_pop_sequence(attribute, hidDescriptor);
183d40c9ac6SMatthias Ringwald     }
184d40c9ac6SMatthias Ringwald     de_pop_sequence(service, attribute);
185d40c9ac6SMatthias Ringwald 
1869679ea81SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HIDLANGID_BASE_LIST);
1879679ea81SMatthias Ringwald     attribute = de_push_sequence(service);
1889679ea81SMatthias Ringwald     {
1899679ea81SMatthias Ringwald         uint8_t* hig_lang_base = de_push_sequence(attribute);
1909679ea81SMatthias Ringwald         {
1919679ea81SMatthias Ringwald             // see: http://www.usb.org/developers/docs/USB_LANGIDs.pdf
1929679ea81SMatthias Ringwald             de_add_number(hig_lang_base,  DE_UINT, DE_SIZE_16, 0x0409);    // HIDLANGID = English (US)
1939679ea81SMatthias Ringwald             de_add_number(hig_lang_base,  DE_UINT, DE_SIZE_16, 0x0100);    // HIDLanguageBase = 0x0100 default
1949679ea81SMatthias Ringwald         }
1959679ea81SMatthias Ringwald         de_pop_sequence(attribute, hig_lang_base);
1969679ea81SMatthias Ringwald     }
1979679ea81SMatthias Ringwald     de_pop_sequence(service, attribute);
1989679ea81SMatthias Ringwald 
199d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_BOOT_DEVICE);
200d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_BOOL, DE_SIZE_8,  hid_boot_device);
201d40c9ac6SMatthias Ringwald }
2028eb8d463SMatthias Ringwald 
2038eb8d463SMatthias Ringwald static inline void hid_device_emit_connected_event(hid_device_t * context, uint8_t status){
2048eb8d463SMatthias Ringwald     uint8_t event[15];
2058eb8d463SMatthias Ringwald     int pos = 0;
2068eb8d463SMatthias Ringwald     event[pos++] = HCI_EVENT_HID_META;
2078eb8d463SMatthias Ringwald     pos++;  // skip len
2088eb8d463SMatthias Ringwald     event[pos++] = HID_SUBEVENT_CONNECTION_OPENED;
2098eb8d463SMatthias Ringwald     little_endian_store_16(event,pos,context->cid);
2108eb8d463SMatthias Ringwald     pos+=2;
2118eb8d463SMatthias Ringwald     event[pos++] = status;
2128eb8d463SMatthias Ringwald     memcpy(&event[pos], context->bd_addr, 6);
2138eb8d463SMatthias Ringwald     pos += 6;
2148eb8d463SMatthias Ringwald     little_endian_store_16(event,pos,context->con_handle);
2158eb8d463SMatthias Ringwald     pos += 2;
2168eb8d463SMatthias Ringwald     event[pos++] = context->incoming;
2178eb8d463SMatthias Ringwald     event[1] = pos - 2;
2188eb8d463SMatthias Ringwald     if (pos != sizeof(event)) log_error("hid_device_emit_connected_event size %u", pos);
2198eb8d463SMatthias Ringwald     hid_callback(HCI_EVENT_PACKET, context->cid, &event[0], pos);
2208eb8d463SMatthias Ringwald }
2218eb8d463SMatthias Ringwald 
2228eb8d463SMatthias Ringwald static inline void hid_device_emit_connection_closed_event(hid_device_t * context){
2238eb8d463SMatthias Ringwald     uint8_t event[5];
2248eb8d463SMatthias Ringwald     int pos = 0;
2258eb8d463SMatthias Ringwald     event[pos++] = HCI_EVENT_HID_META;
2268eb8d463SMatthias Ringwald     pos++;  // skip len
2278eb8d463SMatthias Ringwald     event[pos++] = HID_SUBEVENT_CONNECTION_CLOSED;
2288eb8d463SMatthias Ringwald     little_endian_store_16(event,pos,context->cid);
2298eb8d463SMatthias Ringwald     pos+=2;
2308eb8d463SMatthias Ringwald     event[1] = pos - 2;
2318eb8d463SMatthias Ringwald     if (pos != sizeof(event)) log_error("hid_device_emit_connection_closed_event size %u", pos);
2328eb8d463SMatthias Ringwald     hid_callback(HCI_EVENT_PACKET, context->cid, &event[0], pos);
2338eb8d463SMatthias Ringwald }
2348eb8d463SMatthias Ringwald 
2358eb8d463SMatthias Ringwald static inline void hid_device_emit_can_send_now_event(hid_device_t * context){
2368eb8d463SMatthias Ringwald     uint8_t event[5];
2378eb8d463SMatthias Ringwald     int pos = 0;
2388eb8d463SMatthias Ringwald     event[pos++] = HCI_EVENT_HID_META;
2398eb8d463SMatthias Ringwald     pos++;  // skip len
2408eb8d463SMatthias Ringwald     event[pos++] = HID_SUBEVENT_CAN_SEND_NOW;
2418eb8d463SMatthias Ringwald     little_endian_store_16(event,pos,context->cid);
2428eb8d463SMatthias Ringwald     pos+=2;
2438eb8d463SMatthias Ringwald     event[1] = pos - 2;
2448eb8d463SMatthias Ringwald     if (pos != sizeof(event)) log_error("hid_device_emit_can_send_now_event size %u", pos);
2458eb8d463SMatthias Ringwald     hid_callback(HCI_EVENT_PACKET, context->cid, &event[0], pos);
2468eb8d463SMatthias Ringwald }
2478eb8d463SMatthias Ringwald 
2488eb8d463SMatthias Ringwald 
2498eb8d463SMatthias Ringwald static int hid_connected(void){
2508eb8d463SMatthias Ringwald     return hid_device->control_cid && hid_device->interrupt_cid;
2518eb8d463SMatthias Ringwald }
2528eb8d463SMatthias Ringwald 
2538eb8d463SMatthias Ringwald static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t packet_size){
2548eb8d463SMatthias Ringwald     UNUSED(channel);
2558eb8d463SMatthias Ringwald     UNUSED(packet_size);
2568eb8d463SMatthias Ringwald     int connected_before;
2578eb8d463SMatthias Ringwald     switch (packet_type){
2588eb8d463SMatthias Ringwald         case HCI_EVENT_PACKET:
2598eb8d463SMatthias Ringwald             switch (packet[0]){
2608eb8d463SMatthias Ringwald                 case L2CAP_EVENT_INCOMING_CONNECTION:
2618eb8d463SMatthias Ringwald                     switch (l2cap_event_incoming_connection_get_psm(packet)){
2628eb8d463SMatthias Ringwald                         case PSM_HID_CONTROL:
2638eb8d463SMatthias Ringwald                         case PSM_HID_INTERRUPT:
2648eb8d463SMatthias Ringwald                             if (hid_device->con_handle == 0 || l2cap_event_incoming_connection_get_handle(packet) == hid_device->con_handle){
2658eb8d463SMatthias Ringwald                                 hid_device->con_handle = l2cap_event_incoming_connection_get_handle(packet);
2668eb8d463SMatthias Ringwald                                 l2cap_accept_connection(channel);
2678eb8d463SMatthias Ringwald                             } else {
2688eb8d463SMatthias Ringwald                                 l2cap_decline_connection(channel);
2698eb8d463SMatthias Ringwald                             }
2708eb8d463SMatthias Ringwald                             break;
2718eb8d463SMatthias Ringwald                         default:
2728eb8d463SMatthias Ringwald                             l2cap_decline_connection(channel);
2738eb8d463SMatthias Ringwald                             break;
2748eb8d463SMatthias Ringwald                     }
2758eb8d463SMatthias Ringwald                     break;
2768eb8d463SMatthias Ringwald                 case L2CAP_EVENT_CHANNEL_OPENED:
2778eb8d463SMatthias Ringwald                     if (l2cap_event_channel_opened_get_status(packet)) return;
2788eb8d463SMatthias Ringwald                     connected_before = hid_connected();
2798eb8d463SMatthias Ringwald                     switch (l2cap_event_channel_opened_get_psm(packet)){
2808eb8d463SMatthias Ringwald                         case PSM_HID_CONTROL:
2818eb8d463SMatthias Ringwald                             hid_device->control_cid = l2cap_event_channel_opened_get_local_cid(packet);
2828eb8d463SMatthias Ringwald                             log_info("HID Control opened, cid 0x%02x", hid_device->control_cid);
2838eb8d463SMatthias Ringwald                             break;
2848eb8d463SMatthias Ringwald                         case PSM_HID_INTERRUPT:
2858eb8d463SMatthias Ringwald                             hid_device->interrupt_cid = l2cap_event_channel_opened_get_local_cid(packet);
2868eb8d463SMatthias Ringwald                             log_info("HID Interrupt opened, cid 0x%02x", hid_device->interrupt_cid);
2878eb8d463SMatthias Ringwald                             break;
2888eb8d463SMatthias Ringwald                         default:
2898eb8d463SMatthias Ringwald                             break;
2908eb8d463SMatthias Ringwald                     }
2918eb8d463SMatthias Ringwald                     if (!connected_before && hid_connected()){
2928eb8d463SMatthias Ringwald                         hid_device->incoming = 1;
2938eb8d463SMatthias Ringwald                         log_info("HID Connected");
2948eb8d463SMatthias Ringwald                         hid_device_emit_connected_event(hid_device, 0);
2958eb8d463SMatthias Ringwald                     }
2968eb8d463SMatthias Ringwald                     break;
2978eb8d463SMatthias Ringwald                 case L2CAP_EVENT_CHANNEL_CLOSED:
2988eb8d463SMatthias Ringwald                     connected_before = hid_connected();
2998eb8d463SMatthias Ringwald                     if (l2cap_event_channel_closed_get_local_cid(packet) == hid_device->control_cid){
3008eb8d463SMatthias Ringwald                         log_info("HID Control closed");
3018eb8d463SMatthias Ringwald                         hid_device->control_cid = 0;
3028eb8d463SMatthias Ringwald                     }
3038eb8d463SMatthias Ringwald                     if (l2cap_event_channel_closed_get_local_cid(packet) == hid_device->interrupt_cid){
3048eb8d463SMatthias Ringwald                         log_info("HID Interrupt closed");
3058eb8d463SMatthias Ringwald                         hid_device->interrupt_cid = 0;
3068eb8d463SMatthias Ringwald                     }
3078eb8d463SMatthias Ringwald                     if (connected_before && !hid_connected()){
3088eb8d463SMatthias Ringwald                         hid_device->con_handle = 0;
3098eb8d463SMatthias Ringwald                         log_info("HID Disconnected");
3108eb8d463SMatthias Ringwald                         hid_device_emit_connection_closed_event(hid_device);
3118eb8d463SMatthias Ringwald                     }
3128eb8d463SMatthias Ringwald                     break;
3138eb8d463SMatthias Ringwald                 case L2CAP_EVENT_CAN_SEND_NOW:
3148eb8d463SMatthias Ringwald                     log_info("HID Can send now, emit event");
3158eb8d463SMatthias Ringwald                     hid_device_emit_can_send_now_event(hid_device);
3168eb8d463SMatthias Ringwald                     break;
3178eb8d463SMatthias Ringwald                 default:
3188eb8d463SMatthias Ringwald                     break;
3198eb8d463SMatthias Ringwald             }
3208eb8d463SMatthias Ringwald             break;
3218eb8d463SMatthias Ringwald         default:
3228eb8d463SMatthias Ringwald             break;
3238eb8d463SMatthias Ringwald     }
3248eb8d463SMatthias Ringwald }
3258eb8d463SMatthias Ringwald 
3268eb8d463SMatthias Ringwald /**
3278eb8d463SMatthias Ringwald  * @brief Set up HID Device
3288eb8d463SMatthias Ringwald  */
3298eb8d463SMatthias Ringwald void hid_device_init(void){
3308eb8d463SMatthias Ringwald     memset(hid_device, 0, sizeof(hid_device_t));
3318eb8d463SMatthias Ringwald     hid_device->cid = 1;
332*45a58b30SMatthias Ringwald     l2cap_register_service(packet_handler, PSM_HID_INTERRUPT, 100, LEVEL_2);
333*45a58b30SMatthias Ringwald     l2cap_register_service(packet_handler, PSM_HID_CONTROL,   100, LEVEL_2);
3348eb8d463SMatthias Ringwald }
3358eb8d463SMatthias Ringwald 
3368eb8d463SMatthias Ringwald /**
3378eb8d463SMatthias Ringwald  * @brief Register callback for the HID Device client.
3388eb8d463SMatthias Ringwald  * @param callback
3398eb8d463SMatthias Ringwald  */
3408eb8d463SMatthias Ringwald void hid_device_register_packet_handler(btstack_packet_handler_t callback){
3418eb8d463SMatthias Ringwald     hid_callback = callback;
3428eb8d463SMatthias Ringwald }
3438eb8d463SMatthias Ringwald 
3448eb8d463SMatthias Ringwald /**
3458eb8d463SMatthias Ringwald  * @brief Request can send now event to send HID Report
3468eb8d463SMatthias Ringwald  * @param hid_cid
3478eb8d463SMatthias Ringwald  */
3488eb8d463SMatthias Ringwald void hid_device_request_can_send_now_event(uint16_t hid_cid){
3498eb8d463SMatthias Ringwald     UNUSED(hid_cid);
3508eb8d463SMatthias Ringwald     if (!hid_device->control_cid) return;
3518eb8d463SMatthias Ringwald     l2cap_request_can_send_now_event(hid_device->control_cid);
3528eb8d463SMatthias Ringwald }
3538eb8d463SMatthias Ringwald 
3548eb8d463SMatthias Ringwald /**
3558eb8d463SMatthias Ringwald  * @brief Send HID messageon interrupt channel
3568eb8d463SMatthias Ringwald  * @param hid_cid
3578eb8d463SMatthias Ringwald  */
3588eb8d463SMatthias Ringwald void hid_device_send_interrupt_message(uint16_t hid_cid, const uint8_t * message, uint16_t message_len){
3598eb8d463SMatthias Ringwald     UNUSED(hid_cid);
3608eb8d463SMatthias Ringwald     if (!hid_device->interrupt_cid) return;
3618eb8d463SMatthias Ringwald     l2cap_send(hid_device->interrupt_cid, (uint8_t*) message, message_len);
3628eb8d463SMatthias Ringwald }
3638eb8d463SMatthias Ringwald 
3648eb8d463SMatthias Ringwald /**
3658eb8d463SMatthias Ringwald  * @brief Send HID messageon control channel
3668eb8d463SMatthias Ringwald  * @param hid_cid
3678eb8d463SMatthias Ringwald  */
3688eb8d463SMatthias Ringwald void hid_device_send_contro_message(uint16_t hid_cid, const uint8_t * message, uint16_t message_len){
3698eb8d463SMatthias Ringwald     UNUSED(hid_cid);
3708eb8d463SMatthias Ringwald     if (!hid_device->control_cid) return;
3718eb8d463SMatthias Ringwald     l2cap_send(hid_device->control_cid, (uint8_t*) message, message_len);
3728eb8d463SMatthias Ringwald }
3738eb8d463SMatthias Ringwald 
374