xref: /btstack/src/classic/hid_device.c (revision c37cd8f3d1350b92a2f66c31b2a5fcd75f8c91a4)
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
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 #define __BTSTACK_FILE__ "hid_device.c"
39 
40 #include <string.h>
41 
42 #include "classic/hid_device.h"
43 #include "classic/sdp_util.h"
44 #include "bluetooth.h"
45 #include "bluetooth_sdp.h"
46 #include "l2cap.h"
47 #include "btstack_event.h"
48 #include "btstack_debug.h"
49 
50 // hid device state
51 typedef struct hid_device {
52     uint16_t  cid;
53     bd_addr_t bd_addr;
54     hci_con_handle_t con_handle;
55     uint16_t  control_cid;
56     uint16_t  interrupt_cid;
57     uint8_t   incoming;
58 } hid_device_t;
59 
60 static hid_device_t _hid_device;
61 static hid_device_t * hid_device = &_hid_device;
62 
63 static btstack_packet_handler_t hid_callback;
64 
65 void hid_create_sdp_record(
66     uint8_t *service,
67     uint32_t service_record_handle,
68     uint16_t hid_device_subclass,
69     uint8_t  hid_country_code,
70     uint8_t  hid_virtual_cable,
71     uint8_t  hid_reconnect_initiate,
72     uint8_t  hid_boot_device,
73     const uint8_t * hid_descriptor, uint16_t hid_descriptor_size,
74     const char *device_name){
75 
76     uint8_t * attribute;
77     de_create_sequence(service);
78 
79     de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_RECORD_HANDLE);
80     de_add_number(service, DE_UINT, DE_SIZE_32, service_record_handle);
81 
82     de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_CLASS_ID_LIST);
83     attribute = de_push_sequence(service);
84     {
85         de_add_number(attribute,  DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE_SERVICE);
86     }
87     de_pop_sequence(service, attribute);
88 
89     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST);
90     attribute = de_push_sequence(service);
91     {
92         uint8_t * l2cpProtocol = de_push_sequence(attribute);
93         {
94             de_add_number(l2cpProtocol,  DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_L2CAP);
95             de_add_number(l2cpProtocol,  DE_UINT, DE_SIZE_16, PSM_HID_CONTROL);
96         }
97         de_pop_sequence(attribute, l2cpProtocol);
98 
99         uint8_t * hidProtocol = de_push_sequence(attribute);
100         {
101             de_add_number(hidProtocol,  DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_HIDP);
102         }
103         de_pop_sequence(attribute, hidProtocol);
104     }
105     de_pop_sequence(service, attribute);
106 
107     // TODO?
108     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
109     attribute = de_push_sequence(service);
110     {
111         de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x656e);
112         de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x006a);
113         de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x0100);
114     }
115     de_pop_sequence(service, attribute);
116 
117     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS);
118     attribute = de_push_sequence(service);
119     {
120         uint8_t * additionalDescriptorAttribute = de_push_sequence(attribute);
121         {
122             uint8_t * l2cpProtocol = de_push_sequence(additionalDescriptorAttribute);
123             {
124                 de_add_number(l2cpProtocol,  DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_L2CAP);
125                 de_add_number(l2cpProtocol,  DE_UINT, DE_SIZE_16, PSM_HID_INTERRUPT);
126             }
127             de_pop_sequence(additionalDescriptorAttribute, l2cpProtocol);
128 
129             uint8_t * hidProtocol = de_push_sequence(attribute);
130             {
131                 de_add_number(hidProtocol,  DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_HIDP);
132             }
133             de_pop_sequence(attribute, hidProtocol);
134         }
135         de_pop_sequence(attribute, additionalDescriptorAttribute);
136     }
137     de_pop_sequence(service, attribute);
138 
139     // 0x0100 "ServiceName"
140     de_add_number(service,  DE_UINT, DE_SIZE_16, 0x0100);
141     de_add_data(service,  DE_STRING, strlen(device_name), (uint8_t *) device_name);
142 
143     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
144     attribute = de_push_sequence(service);
145     {
146         uint8_t * hidProfile = de_push_sequence(attribute);
147         {
148             de_add_number(hidProfile,  DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE_SERVICE);
149             de_add_number(hidProfile,  DE_UINT, DE_SIZE_16, 0x0101);    // Version 1.1
150         }
151         de_pop_sequence(attribute, hidProfile);
152     }
153     de_pop_sequence(service, attribute);
154 
155     // Deprecated in v1.1.1
156     // de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_DEVICE_RELEASE_NUMBER);
157     // de_add_number(service,  DE_UINT, DE_SIZE_16, 0x0101);
158 
159     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_PARSER_VERSION);
160     de_add_number(service,  DE_UINT, DE_SIZE_16, 0x0111);  // v1.1.1
161 
162     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_DEVICE_SUBCLASS);
163     de_add_number(service,  DE_UINT, DE_SIZE_8,  hid_device_subclass);
164 
165     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_COUNTRY_CODE);
166     de_add_number(service,  DE_UINT, DE_SIZE_8,  hid_country_code);
167 
168     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_VIRTUAL_CABLE);
169     de_add_number(service,  DE_BOOL, DE_SIZE_8,  hid_virtual_cable);
170 
171     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_RECONNECT_INITIATE);
172     de_add_number(service,  DE_BOOL, DE_SIZE_8,  hid_reconnect_initiate);
173 
174     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_DESCRIPTOR_LIST);
175     attribute = de_push_sequence(service);
176     {
177         uint8_t* hidDescriptor = de_push_sequence(attribute);
178         {
179             de_add_number(hidDescriptor,  DE_UINT, DE_SIZE_8, 0x22);    // Report Descriptor
180             de_add_data(hidDescriptor,  DE_STRING, hid_descriptor_size, (uint8_t *) hid_descriptor);
181         }
182         de_pop_sequence(attribute, hidDescriptor);
183     }
184     de_pop_sequence(service, attribute);
185 
186     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HIDLANGID_BASE_LIST);
187     attribute = de_push_sequence(service);
188     {
189         uint8_t* hig_lang_base = de_push_sequence(attribute);
190         {
191             // see: http://www.usb.org/developers/docs/USB_LANGIDs.pdf
192             de_add_number(hig_lang_base,  DE_UINT, DE_SIZE_16, 0x0409);    // HIDLANGID = English (US)
193             de_add_number(hig_lang_base,  DE_UINT, DE_SIZE_16, 0x0100);    // HIDLanguageBase = 0x0100 default
194         }
195         de_pop_sequence(attribute, hig_lang_base);
196     }
197     de_pop_sequence(service, attribute);
198 
199     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_BOOT_DEVICE);
200     de_add_number(service,  DE_BOOL, DE_SIZE_8,  hid_boot_device);
201 }
202 
203 static inline void hid_device_emit_connected_event(hid_device_t * context, uint8_t status){
204     uint8_t event[15];
205     int pos = 0;
206     event[pos++] = HCI_EVENT_HID_META;
207     pos++;  // skip len
208     event[pos++] = HID_SUBEVENT_CONNECTION_OPENED;
209     little_endian_store_16(event,pos,context->cid);
210     pos+=2;
211     event[pos++] = status;
212     memcpy(&event[pos], context->bd_addr, 6);
213     pos += 6;
214     little_endian_store_16(event,pos,context->con_handle);
215     pos += 2;
216     event[pos++] = context->incoming;
217     event[1] = pos - 2;
218     if (pos != sizeof(event)) log_error("hid_device_emit_connected_event size %u", pos);
219     hid_callback(HCI_EVENT_PACKET, context->cid, &event[0], pos);
220 }
221 
222 static inline void hid_device_emit_connection_closed_event(hid_device_t * context){
223     uint8_t event[5];
224     int pos = 0;
225     event[pos++] = HCI_EVENT_HID_META;
226     pos++;  // skip len
227     event[pos++] = HID_SUBEVENT_CONNECTION_CLOSED;
228     little_endian_store_16(event,pos,context->cid);
229     pos+=2;
230     event[1] = pos - 2;
231     if (pos != sizeof(event)) log_error("hid_device_emit_connection_closed_event size %u", pos);
232     hid_callback(HCI_EVENT_PACKET, context->cid, &event[0], pos);
233 }
234 
235 static inline void hid_device_emit_can_send_now_event(hid_device_t * context){
236     uint8_t event[5];
237     int pos = 0;
238     event[pos++] = HCI_EVENT_HID_META;
239     pos++;  // skip len
240     event[pos++] = HID_SUBEVENT_CAN_SEND_NOW;
241     little_endian_store_16(event,pos,context->cid);
242     pos+=2;
243     event[1] = pos - 2;
244     if (pos != sizeof(event)) log_error("hid_device_emit_can_send_now_event size %u", pos);
245     hid_callback(HCI_EVENT_PACKET, context->cid, &event[0], pos);
246 }
247 
248 
249 static int hid_connected(void){
250     return hid_device->control_cid && hid_device->interrupt_cid;
251 }
252 
253 static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t packet_size){
254     UNUSED(channel);
255     UNUSED(packet_size);
256     int connected_before;
257     switch (packet_type){
258         case HCI_EVENT_PACKET:
259             switch (packet[0]){
260                 case L2CAP_EVENT_INCOMING_CONNECTION:
261                     switch (l2cap_event_incoming_connection_get_psm(packet)){
262                         case PSM_HID_CONTROL:
263                         case PSM_HID_INTERRUPT:
264                             if (hid_device->con_handle == 0 || l2cap_event_incoming_connection_get_handle(packet) == hid_device->con_handle){
265                                 hid_device->con_handle = l2cap_event_incoming_connection_get_handle(packet);
266                                 l2cap_accept_connection(channel);
267                             } else {
268                                 l2cap_decline_connection(channel);
269                             }
270                             break;
271                         default:
272                             l2cap_decline_connection(channel);
273                             break;
274                     }
275                     break;
276                 case L2CAP_EVENT_CHANNEL_OPENED:
277                     if (l2cap_event_channel_opened_get_status(packet)) return;
278                     connected_before = hid_connected();
279                     switch (l2cap_event_channel_opened_get_psm(packet)){
280                         case PSM_HID_CONTROL:
281                             hid_device->control_cid = l2cap_event_channel_opened_get_local_cid(packet);
282                             log_info("HID Control opened, cid 0x%02x", hid_device->control_cid);
283                             break;
284                         case PSM_HID_INTERRUPT:
285                             hid_device->interrupt_cid = l2cap_event_channel_opened_get_local_cid(packet);
286                             log_info("HID Interrupt opened, cid 0x%02x", hid_device->interrupt_cid);
287                             break;
288                         default:
289                             break;
290                     }
291                     if (!connected_before && hid_connected()){
292                         hid_device->incoming = 1;
293                         log_info("HID Connected");
294                         hid_device_emit_connected_event(hid_device, 0);
295                     }
296                     break;
297                 case L2CAP_EVENT_CHANNEL_CLOSED:
298                     connected_before = hid_connected();
299                     if (l2cap_event_channel_closed_get_local_cid(packet) == hid_device->control_cid){
300                         log_info("HID Control closed");
301                         hid_device->control_cid = 0;
302                     }
303                     if (l2cap_event_channel_closed_get_local_cid(packet) == hid_device->interrupt_cid){
304                         log_info("HID Interrupt closed");
305                         hid_device->interrupt_cid = 0;
306                     }
307                     if (connected_before && !hid_connected()){
308                         hid_device->con_handle = 0;
309                         log_info("HID Disconnected");
310                         hid_device_emit_connection_closed_event(hid_device);
311                     }
312                     break;
313                 case L2CAP_EVENT_CAN_SEND_NOW:
314                     log_info("HID Can send now, emit event");
315                     hid_device_emit_can_send_now_event(hid_device);
316                     break;
317                 default:
318                     break;
319             }
320             break;
321         default:
322             break;
323     }
324 }
325 
326 /**
327  * @brief Set up HID Device
328  */
329 void hid_device_init(void){
330     memset(hid_device, 0, sizeof(hid_device_t));
331     hid_device->cid = 1;
332     l2cap_register_service(packet_handler, PSM_HID_INTERRUPT, 100, LEVEL_0);
333     l2cap_register_service(packet_handler, PSM_HID_CONTROL,   100, LEVEL_0);
334 }
335 
336 /**
337  * @brief Register callback for the HID Device client.
338  * @param callback
339  */
340 void hid_device_register_packet_handler(btstack_packet_handler_t callback){
341     hid_callback = callback;
342 }
343 
344 /**
345  * @brief Request can send now event to send HID Report
346  * @param hid_cid
347  */
348 void hid_device_request_can_send_now_event(uint16_t hid_cid){
349     UNUSED(hid_cid);
350     if (!hid_device->control_cid) return;
351     l2cap_request_can_send_now_event(hid_device->control_cid);
352 }
353 
354 /**
355  * @brief Send HID messageon interrupt channel
356  * @param hid_cid
357  */
358 void hid_device_send_interrupt_message(uint16_t hid_cid, const uint8_t * message, uint16_t message_len){
359     UNUSED(hid_cid);
360     if (!hid_device->interrupt_cid) return;
361     l2cap_send(hid_device->interrupt_cid, (uint8_t*) message, message_len);
362 }
363 
364 /**
365  * @brief Send HID messageon control channel
366  * @param hid_cid
367  */
368 void hid_device_send_contro_message(uint16_t hid_cid, const uint8_t * message, uint16_t message_len){
369     UNUSED(hid_cid);
370     if (!hid_device->control_cid) return;
371     l2cap_send(hid_device->control_cid, (uint8_t*) message, message_len);
372 }
373 
374