xref: /btstack/src/classic/hid_device.c (revision 8eb8d46326a076a39756a0743157c8a065b9a912)
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"
46*8eb8d463SMatthias Ringwald #include "l2cap.h"
47*8eb8d463SMatthias Ringwald #include "btstack_event.h"
48*8eb8d463SMatthias Ringwald #include "btstack_debug.h"
49*8eb8d463SMatthias Ringwald 
50*8eb8d463SMatthias Ringwald // hid device state
51*8eb8d463SMatthias Ringwald typedef struct hid_device {
52*8eb8d463SMatthias Ringwald     uint16_t  cid;
53*8eb8d463SMatthias Ringwald     bd_addr_t bd_addr;
54*8eb8d463SMatthias Ringwald     hci_con_handle_t con_handle;
55*8eb8d463SMatthias Ringwald     uint16_t  control_cid;
56*8eb8d463SMatthias Ringwald     uint16_t  interrupt_cid;
57*8eb8d463SMatthias Ringwald     uint8_t   incoming;
58*8eb8d463SMatthias Ringwald } hid_device_t;
59*8eb8d463SMatthias Ringwald 
60*8eb8d463SMatthias Ringwald static hid_device_t _hid_device;
61*8eb8d463SMatthias Ringwald static hid_device_t * hid_device = &_hid_device;
62*8eb8d463SMatthias Ringwald 
63*8eb8d463SMatthias 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);
163d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, hid_device_subclass);
164d40c9ac6SMatthias Ringwald 
165d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_COUNTRY_CODE);
166d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, 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 
186d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_BOOT_DEVICE);
187d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_BOOL, DE_SIZE_8,  hid_boot_device);
188d40c9ac6SMatthias Ringwald }
189*8eb8d463SMatthias Ringwald 
190*8eb8d463SMatthias Ringwald static inline void hid_device_emit_connected_event(hid_device_t * context, uint8_t status){
191*8eb8d463SMatthias Ringwald     uint8_t event[15];
192*8eb8d463SMatthias Ringwald     int pos = 0;
193*8eb8d463SMatthias Ringwald     event[pos++] = HCI_EVENT_HID_META;
194*8eb8d463SMatthias Ringwald     pos++;  // skip len
195*8eb8d463SMatthias Ringwald     event[pos++] = HID_SUBEVENT_CONNECTION_OPENED;
196*8eb8d463SMatthias Ringwald     little_endian_store_16(event,pos,context->cid);
197*8eb8d463SMatthias Ringwald     pos+=2;
198*8eb8d463SMatthias Ringwald     event[pos++] = status;
199*8eb8d463SMatthias Ringwald     memcpy(&event[pos], context->bd_addr, 6);
200*8eb8d463SMatthias Ringwald     pos += 6;
201*8eb8d463SMatthias Ringwald     little_endian_store_16(event,pos,context->con_handle);
202*8eb8d463SMatthias Ringwald     pos += 2;
203*8eb8d463SMatthias Ringwald     event[pos++] = context->incoming;
204*8eb8d463SMatthias Ringwald     event[1] = pos - 2;
205*8eb8d463SMatthias Ringwald     if (pos != sizeof(event)) log_error("hid_device_emit_connected_event size %u", pos);
206*8eb8d463SMatthias Ringwald     hid_callback(HCI_EVENT_PACKET, context->cid, &event[0], pos);
207*8eb8d463SMatthias Ringwald }
208*8eb8d463SMatthias Ringwald 
209*8eb8d463SMatthias Ringwald static inline void hid_device_emit_connection_closed_event(hid_device_t * context){
210*8eb8d463SMatthias Ringwald     uint8_t event[5];
211*8eb8d463SMatthias Ringwald     int pos = 0;
212*8eb8d463SMatthias Ringwald     event[pos++] = HCI_EVENT_HID_META;
213*8eb8d463SMatthias Ringwald     pos++;  // skip len
214*8eb8d463SMatthias Ringwald     event[pos++] = HID_SUBEVENT_CONNECTION_CLOSED;
215*8eb8d463SMatthias Ringwald     little_endian_store_16(event,pos,context->cid);
216*8eb8d463SMatthias Ringwald     pos+=2;
217*8eb8d463SMatthias Ringwald     event[1] = pos - 2;
218*8eb8d463SMatthias Ringwald     if (pos != sizeof(event)) log_error("hid_device_emit_connection_closed_event size %u", pos);
219*8eb8d463SMatthias Ringwald     hid_callback(HCI_EVENT_PACKET, context->cid, &event[0], pos);
220*8eb8d463SMatthias Ringwald }
221*8eb8d463SMatthias Ringwald 
222*8eb8d463SMatthias Ringwald static inline void hid_device_emit_can_send_now_event(hid_device_t * context){
223*8eb8d463SMatthias Ringwald     uint8_t event[5];
224*8eb8d463SMatthias Ringwald     int pos = 0;
225*8eb8d463SMatthias Ringwald     event[pos++] = HCI_EVENT_HID_META;
226*8eb8d463SMatthias Ringwald     pos++;  // skip len
227*8eb8d463SMatthias Ringwald     event[pos++] = HID_SUBEVENT_CAN_SEND_NOW;
228*8eb8d463SMatthias Ringwald     little_endian_store_16(event,pos,context->cid);
229*8eb8d463SMatthias Ringwald     pos+=2;
230*8eb8d463SMatthias Ringwald     event[1] = pos - 2;
231*8eb8d463SMatthias Ringwald     if (pos != sizeof(event)) log_error("hid_device_emit_can_send_now_event size %u", pos);
232*8eb8d463SMatthias Ringwald     hid_callback(HCI_EVENT_PACKET, context->cid, &event[0], pos);
233*8eb8d463SMatthias Ringwald }
234*8eb8d463SMatthias Ringwald 
235*8eb8d463SMatthias Ringwald 
236*8eb8d463SMatthias Ringwald static int hid_connected(void){
237*8eb8d463SMatthias Ringwald     return hid_device->control_cid && hid_device->interrupt_cid;
238*8eb8d463SMatthias Ringwald }
239*8eb8d463SMatthias Ringwald 
240*8eb8d463SMatthias Ringwald static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t packet_size){
241*8eb8d463SMatthias Ringwald     UNUSED(channel);
242*8eb8d463SMatthias Ringwald     UNUSED(packet_size);
243*8eb8d463SMatthias Ringwald     int connected_before;
244*8eb8d463SMatthias Ringwald     switch (packet_type){
245*8eb8d463SMatthias Ringwald         case HCI_EVENT_PACKET:
246*8eb8d463SMatthias Ringwald             switch (packet[0]){
247*8eb8d463SMatthias Ringwald                 case L2CAP_EVENT_INCOMING_CONNECTION:
248*8eb8d463SMatthias Ringwald                     switch (l2cap_event_incoming_connection_get_psm(packet)){
249*8eb8d463SMatthias Ringwald                         case PSM_HID_CONTROL:
250*8eb8d463SMatthias Ringwald                         case PSM_HID_INTERRUPT:
251*8eb8d463SMatthias Ringwald                             if (hid_device->con_handle == 0 || l2cap_event_incoming_connection_get_handle(packet) == hid_device->con_handle){
252*8eb8d463SMatthias Ringwald                                 hid_device->con_handle = l2cap_event_incoming_connection_get_handle(packet);
253*8eb8d463SMatthias Ringwald                                 l2cap_accept_connection(channel);
254*8eb8d463SMatthias Ringwald                             } else {
255*8eb8d463SMatthias Ringwald                                 l2cap_decline_connection(channel);
256*8eb8d463SMatthias Ringwald                             }
257*8eb8d463SMatthias Ringwald                             break;
258*8eb8d463SMatthias Ringwald                         default:
259*8eb8d463SMatthias Ringwald                             l2cap_decline_connection(channel);
260*8eb8d463SMatthias Ringwald                             break;
261*8eb8d463SMatthias Ringwald                     }
262*8eb8d463SMatthias Ringwald                     break;
263*8eb8d463SMatthias Ringwald                 case L2CAP_EVENT_CHANNEL_OPENED:
264*8eb8d463SMatthias Ringwald                     if (l2cap_event_channel_opened_get_status(packet)) return;
265*8eb8d463SMatthias Ringwald                     connected_before = hid_connected();
266*8eb8d463SMatthias Ringwald                     switch (l2cap_event_channel_opened_get_psm(packet)){
267*8eb8d463SMatthias Ringwald                         case PSM_HID_CONTROL:
268*8eb8d463SMatthias Ringwald                             hid_device->control_cid = l2cap_event_channel_opened_get_local_cid(packet);
269*8eb8d463SMatthias Ringwald                             log_info("HID Control opened, cid 0x%02x", hid_device->control_cid);
270*8eb8d463SMatthias Ringwald                             break;
271*8eb8d463SMatthias Ringwald                         case PSM_HID_INTERRUPT:
272*8eb8d463SMatthias Ringwald                             hid_device->interrupt_cid = l2cap_event_channel_opened_get_local_cid(packet);
273*8eb8d463SMatthias Ringwald                             log_info("HID Interrupt opened, cid 0x%02x", hid_device->interrupt_cid);
274*8eb8d463SMatthias Ringwald                             break;
275*8eb8d463SMatthias Ringwald                         default:
276*8eb8d463SMatthias Ringwald                             break;
277*8eb8d463SMatthias Ringwald                     }
278*8eb8d463SMatthias Ringwald                     if (!connected_before && hid_connected()){
279*8eb8d463SMatthias Ringwald                         hid_device->incoming = 1;
280*8eb8d463SMatthias Ringwald                         log_info("HID Connected");
281*8eb8d463SMatthias Ringwald                         hid_device_emit_connected_event(hid_device, 0);
282*8eb8d463SMatthias Ringwald                     }
283*8eb8d463SMatthias Ringwald                     break;
284*8eb8d463SMatthias Ringwald                 case L2CAP_EVENT_CHANNEL_CLOSED:
285*8eb8d463SMatthias Ringwald                     connected_before = hid_connected();
286*8eb8d463SMatthias Ringwald                     if (l2cap_event_channel_closed_get_local_cid(packet) == hid_device->control_cid){
287*8eb8d463SMatthias Ringwald                         log_info("HID Control closed");
288*8eb8d463SMatthias Ringwald                         hid_device->control_cid = 0;
289*8eb8d463SMatthias Ringwald                     }
290*8eb8d463SMatthias Ringwald                     if (l2cap_event_channel_closed_get_local_cid(packet) == hid_device->interrupt_cid){
291*8eb8d463SMatthias Ringwald                         log_info("HID Interrupt closed");
292*8eb8d463SMatthias Ringwald                         hid_device->interrupt_cid = 0;
293*8eb8d463SMatthias Ringwald                     }
294*8eb8d463SMatthias Ringwald                     if (connected_before && !hid_connected()){
295*8eb8d463SMatthias Ringwald                         hid_device->con_handle = 0;
296*8eb8d463SMatthias Ringwald                         log_info("HID Disconnected");
297*8eb8d463SMatthias Ringwald                         hid_device_emit_connection_closed_event(hid_device);
298*8eb8d463SMatthias Ringwald                     }
299*8eb8d463SMatthias Ringwald                     break;
300*8eb8d463SMatthias Ringwald                 case L2CAP_EVENT_CAN_SEND_NOW:
301*8eb8d463SMatthias Ringwald                     log_info("HID Can send now, emit event");
302*8eb8d463SMatthias Ringwald                     hid_device_emit_can_send_now_event(hid_device);
303*8eb8d463SMatthias Ringwald                     break;
304*8eb8d463SMatthias Ringwald                 default:
305*8eb8d463SMatthias Ringwald                     break;
306*8eb8d463SMatthias Ringwald             }
307*8eb8d463SMatthias Ringwald             break;
308*8eb8d463SMatthias Ringwald         default:
309*8eb8d463SMatthias Ringwald             break;
310*8eb8d463SMatthias Ringwald     }
311*8eb8d463SMatthias Ringwald }
312*8eb8d463SMatthias Ringwald 
313*8eb8d463SMatthias Ringwald /**
314*8eb8d463SMatthias Ringwald  * @brief Set up HID Device
315*8eb8d463SMatthias Ringwald  */
316*8eb8d463SMatthias Ringwald void hid_device_init(void){
317*8eb8d463SMatthias Ringwald     memset(hid_device, 0, sizeof(hid_device_t));
318*8eb8d463SMatthias Ringwald     hid_device->cid = 1;
319*8eb8d463SMatthias Ringwald     l2cap_register_service(packet_handler, PSM_HID_INTERRUPT, 100, LEVEL_0);
320*8eb8d463SMatthias Ringwald     l2cap_register_service(packet_handler, PSM_HID_CONTROL,   100, LEVEL_0);
321*8eb8d463SMatthias Ringwald }
322*8eb8d463SMatthias Ringwald 
323*8eb8d463SMatthias Ringwald /**
324*8eb8d463SMatthias Ringwald  * @brief Register callback for the HID Device client.
325*8eb8d463SMatthias Ringwald  * @param callback
326*8eb8d463SMatthias Ringwald  */
327*8eb8d463SMatthias Ringwald void hid_device_register_packet_handler(btstack_packet_handler_t callback){
328*8eb8d463SMatthias Ringwald     hid_callback = callback;
329*8eb8d463SMatthias Ringwald }
330*8eb8d463SMatthias Ringwald 
331*8eb8d463SMatthias Ringwald /**
332*8eb8d463SMatthias Ringwald  * @brief Request can send now event to send HID Report
333*8eb8d463SMatthias Ringwald  * @param hid_cid
334*8eb8d463SMatthias Ringwald  */
335*8eb8d463SMatthias Ringwald void hid_device_request_can_send_now_event(uint16_t hid_cid){
336*8eb8d463SMatthias Ringwald     UNUSED(hid_cid);
337*8eb8d463SMatthias Ringwald     if (!hid_device->control_cid) return;
338*8eb8d463SMatthias Ringwald     l2cap_request_can_send_now_event(hid_device->control_cid);
339*8eb8d463SMatthias Ringwald }
340*8eb8d463SMatthias Ringwald 
341*8eb8d463SMatthias Ringwald /**
342*8eb8d463SMatthias Ringwald  * @brief Send HID messageon interrupt channel
343*8eb8d463SMatthias Ringwald  * @param hid_cid
344*8eb8d463SMatthias Ringwald  */
345*8eb8d463SMatthias Ringwald void hid_device_send_interrupt_message(uint16_t hid_cid, const uint8_t * message, uint16_t message_len){
346*8eb8d463SMatthias Ringwald     UNUSED(hid_cid);
347*8eb8d463SMatthias Ringwald     if (!hid_device->interrupt_cid) return;
348*8eb8d463SMatthias Ringwald     l2cap_send(hid_device->interrupt_cid, (uint8_t*) message, message_len);
349*8eb8d463SMatthias Ringwald }
350*8eb8d463SMatthias Ringwald 
351*8eb8d463SMatthias Ringwald /**
352*8eb8d463SMatthias Ringwald  * @brief Send HID messageon control channel
353*8eb8d463SMatthias Ringwald  * @param hid_cid
354*8eb8d463SMatthias Ringwald  */
355*8eb8d463SMatthias Ringwald void hid_device_send_contro_message(uint16_t hid_cid, const uint8_t * message, uint16_t message_len){
356*8eb8d463SMatthias Ringwald     UNUSED(hid_cid);
357*8eb8d463SMatthias Ringwald     if (!hid_device->control_cid) return;
358*8eb8d463SMatthias Ringwald     l2cap_send(hid_device->control_cid, (uint8_t*) message, message_len);
359*8eb8d463SMatthias Ringwald }
360*8eb8d463SMatthias Ringwald 
361