xref: /btstack/src/classic/hid_device.c (revision 09cf8159072d80e092b9c303cea9b43a81b36aee)
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     uint8_t   connected;
59 } hid_device_t;
60 
61 static hid_device_t _hid_device;
62 static hid_device_t * hid_device = &_hid_device;
63 
64 static btstack_packet_handler_t hid_callback;
65 
66 void hid_create_sdp_record(
67     uint8_t *service,
68     uint32_t service_record_handle,
69     uint16_t hid_device_subclass,
70     uint8_t  hid_country_code,
71     uint8_t  hid_virtual_cable,
72     uint8_t  hid_reconnect_initiate,
73     uint8_t  hid_boot_device,
74     const uint8_t * hid_descriptor, uint16_t hid_descriptor_size,
75     const char *device_name){
76 
77     uint8_t * attribute;
78     de_create_sequence(service);
79 
80     de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_RECORD_HANDLE);
81     de_add_number(service, DE_UINT, DE_SIZE_32, service_record_handle);
82 
83     de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_CLASS_ID_LIST);
84     attribute = de_push_sequence(service);
85     {
86         de_add_number(attribute,  DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE_SERVICE);
87     }
88     de_pop_sequence(service, attribute);
89 
90     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST);
91     attribute = de_push_sequence(service);
92     {
93         uint8_t * l2cpProtocol = de_push_sequence(attribute);
94         {
95             de_add_number(l2cpProtocol,  DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_L2CAP);
96             de_add_number(l2cpProtocol,  DE_UINT, DE_SIZE_16, PSM_HID_CONTROL);
97         }
98         de_pop_sequence(attribute, l2cpProtocol);
99 
100         uint8_t * hidProtocol = de_push_sequence(attribute);
101         {
102             de_add_number(hidProtocol,  DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_HIDP);
103         }
104         de_pop_sequence(attribute, hidProtocol);
105     }
106     de_pop_sequence(service, attribute);
107 
108     // TODO?
109     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
110     attribute = de_push_sequence(service);
111     {
112         de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x656e);
113         de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x006a);
114         de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x0100);
115     }
116     de_pop_sequence(service, attribute);
117 
118     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS);
119     attribute = de_push_sequence(service);
120     {
121         uint8_t * additionalDescriptorAttribute = de_push_sequence(attribute);
122         {
123             uint8_t * l2cpProtocol = de_push_sequence(additionalDescriptorAttribute);
124             {
125                 de_add_number(l2cpProtocol,  DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_L2CAP);
126                 de_add_number(l2cpProtocol,  DE_UINT, DE_SIZE_16, PSM_HID_INTERRUPT);
127             }
128             de_pop_sequence(additionalDescriptorAttribute, l2cpProtocol);
129 
130             uint8_t * hidProtocol = de_push_sequence(attribute);
131             {
132                 de_add_number(hidProtocol,  DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_HIDP);
133             }
134             de_pop_sequence(attribute, hidProtocol);
135         }
136         de_pop_sequence(attribute, additionalDescriptorAttribute);
137     }
138     de_pop_sequence(service, attribute);
139 
140     // 0x0100 "ServiceName"
141     de_add_number(service,  DE_UINT, DE_SIZE_16, 0x0100);
142     de_add_data(service,  DE_STRING, strlen(device_name), (uint8_t *) device_name);
143 
144     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
145     attribute = de_push_sequence(service);
146     {
147         uint8_t * hidProfile = de_push_sequence(attribute);
148         {
149             de_add_number(hidProfile,  DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE_SERVICE);
150             de_add_number(hidProfile,  DE_UINT, DE_SIZE_16, 0x0101);    // Version 1.1
151         }
152         de_pop_sequence(attribute, hidProfile);
153     }
154     de_pop_sequence(service, attribute);
155 
156     // Deprecated in v1.1.1
157     // de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_DEVICE_RELEASE_NUMBER);
158     // de_add_number(service,  DE_UINT, DE_SIZE_16, 0x0101);
159 
160     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_PARSER_VERSION);
161     de_add_number(service,  DE_UINT, DE_SIZE_16, 0x0111);  // v1.1.1
162 
163     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_DEVICE_SUBCLASS);
164     de_add_number(service,  DE_UINT, DE_SIZE_8,  hid_device_subclass);
165 
166     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_COUNTRY_CODE);
167     de_add_number(service,  DE_UINT, DE_SIZE_8,  hid_country_code);
168 
169     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_VIRTUAL_CABLE);
170     de_add_number(service,  DE_BOOL, DE_SIZE_8,  hid_virtual_cable);
171 
172     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_RECONNECT_INITIATE);
173     de_add_number(service,  DE_BOOL, DE_SIZE_8,  hid_reconnect_initiate);
174 
175     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_DESCRIPTOR_LIST);
176     attribute = de_push_sequence(service);
177     {
178         uint8_t* hidDescriptor = de_push_sequence(attribute);
179         {
180             de_add_number(hidDescriptor,  DE_UINT, DE_SIZE_8, 0x22);    // Report Descriptor
181             de_add_data(hidDescriptor,  DE_STRING, hid_descriptor_size, (uint8_t *) hid_descriptor);
182         }
183         de_pop_sequence(attribute, hidDescriptor);
184     }
185     de_pop_sequence(service, attribute);
186 
187     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HIDLANGID_BASE_LIST);
188     attribute = de_push_sequence(service);
189     {
190         uint8_t* hig_lang_base = de_push_sequence(attribute);
191         {
192             // see: http://www.usb.org/developers/docs/USB_LANGIDs.pdf
193             de_add_number(hig_lang_base,  DE_UINT, DE_SIZE_16, 0x0409);    // HIDLANGID = English (US)
194             de_add_number(hig_lang_base,  DE_UINT, DE_SIZE_16, 0x0100);    // HIDLanguageBase = 0x0100 default
195         }
196         de_pop_sequence(attribute, hig_lang_base);
197     }
198     de_pop_sequence(service, attribute);
199 
200     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_BOOT_DEVICE);
201     de_add_number(service,  DE_BOOL, DE_SIZE_8,  hid_boot_device);
202 }
203 
204 static inline void hid_device_emit_connected_event(hid_device_t * context, uint8_t status){
205     uint8_t event[15];
206     int pos = 0;
207     event[pos++] = HCI_EVENT_HID_META;
208     pos++;  // skip len
209     event[pos++] = HID_SUBEVENT_CONNECTION_OPENED;
210     little_endian_store_16(event,pos,context->cid);
211     pos+=2;
212     event[pos++] = status;
213     memcpy(&event[pos], context->bd_addr, 6);
214     pos += 6;
215     little_endian_store_16(event,pos,context->con_handle);
216     pos += 2;
217     event[pos++] = context->incoming;
218     event[1] = pos - 2;
219     if (pos != sizeof(event)) log_error("hid_device_emit_connected_event size %u", pos);
220     hid_callback(HCI_EVENT_PACKET, context->cid, &event[0], pos);
221 }
222 
223 static inline void hid_device_emit_connection_closed_event(hid_device_t * context){
224     uint8_t event[5];
225     int pos = 0;
226     event[pos++] = HCI_EVENT_HID_META;
227     pos++;  // skip len
228     event[pos++] = HID_SUBEVENT_CONNECTION_CLOSED;
229     little_endian_store_16(event,pos,context->cid);
230     pos+=2;
231     event[1] = pos - 2;
232     if (pos != sizeof(event)) log_error("hid_device_emit_connection_closed_event size %u", pos);
233     hid_callback(HCI_EVENT_PACKET, context->cid, &event[0], pos);
234 }
235 
236 static inline void hid_device_emit_can_send_now_event(hid_device_t * context){
237     uint8_t event[5];
238     int pos = 0;
239     event[pos++] = HCI_EVENT_HID_META;
240     pos++;  // skip len
241     event[pos++] = HID_SUBEVENT_CAN_SEND_NOW;
242     little_endian_store_16(event,pos,context->cid);
243     pos+=2;
244     event[1] = pos - 2;
245     if (pos != sizeof(event)) log_error("hid_device_emit_can_send_now_event size %u", pos);
246     hid_callback(HCI_EVENT_PACKET, context->cid, &event[0], pos);
247 }
248 
249 
250 static int hid_connected(void){
251     return hid_device->connected;
252 }
253 
254 static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t packet_size){
255     UNUSED(channel);
256     UNUSED(packet_size);
257     int connected_before;
258     uint16_t psm;
259     uint8_t status;
260     switch (packet_type){
261         case HCI_EVENT_PACKET:
262             switch (packet[0]){
263                 case L2CAP_EVENT_INCOMING_CONNECTION:
264                     switch (l2cap_event_incoming_connection_get_psm(packet)){
265                         case PSM_HID_CONTROL:
266                         case PSM_HID_INTERRUPT:
267                             if (hid_device->con_handle == 0 || l2cap_event_incoming_connection_get_handle(packet) == hid_device->con_handle){
268                                 hid_device->con_handle = l2cap_event_incoming_connection_get_handle(packet);
269                                 hid_device->incoming = 1;
270                                 l2cap_accept_connection(channel);
271                             } else {
272                                 l2cap_decline_connection(channel);
273                             }
274                             break;
275                         default:
276                             l2cap_decline_connection(channel);
277                             break;
278                     }
279                     break;
280                 case L2CAP_EVENT_CHANNEL_OPENED:
281                     status = l2cap_event_channel_opened_get_status(packet);
282                     if (status) {
283                         if (hid_device->incoming == 0){
284                             // report error for outgoing connection
285                             hid_device_emit_connected_event(hid_device, status);
286                         }
287                         return;
288                     }
289                     psm = l2cap_event_channel_opened_get_psm(packet);
290                     connected_before = hid_connected();
291                     switch (psm){
292                         case PSM_HID_CONTROL:
293                             hid_device->control_cid = l2cap_event_channel_opened_get_local_cid(packet);
294                             log_info("HID Control opened, cid 0x%02x", hid_device->control_cid);
295                             break;
296                         case PSM_HID_INTERRUPT:
297                             hid_device->interrupt_cid = l2cap_event_channel_opened_get_local_cid(packet);
298                             log_info("HID Interrupt opened, cid 0x%02x", hid_device->interrupt_cid);
299                             break;
300                         default:
301                             break;
302                     }
303                     // connect HID Interrupt for outgoing
304                     if (hid_device->incoming == 0 && psm == PSM_HID_CONTROL){
305                         log_info("Create outgoing HID Interrupt");
306                         status = l2cap_create_channel(packet_handler, hid_device->bd_addr, PSM_HID_INTERRUPT, 48, &hid_device->interrupt_cid);
307                         break;
308                     }
309                     if (!connected_before && hid_device->control_cid && hid_device->interrupt_cid){
310                         hid_device->connected = 1;
311                         log_info("HID Connected");
312                         hid_device_emit_connected_event(hid_device, 0);
313                     }
314                     break;
315                 case L2CAP_EVENT_CHANNEL_CLOSED:
316                     hid_device->incoming  = 0;
317                     hid_device->connected = 0;
318                     connected_before = hid_connected();
319                     if (l2cap_event_channel_closed_get_local_cid(packet) == hid_device->control_cid){
320                         log_info("HID Control closed");
321                         hid_device->control_cid = 0;
322                     }
323                     if (l2cap_event_channel_closed_get_local_cid(packet) == hid_device->interrupt_cid){
324                         log_info("HID Interrupt closed");
325                         hid_device->interrupt_cid = 0;
326                     }
327                     if (connected_before && !hid_connected()){
328                         hid_device->con_handle = 0;
329                         log_info("HID Disconnected");
330                         hid_device_emit_connection_closed_event(hid_device);
331                     }
332                     break;
333                 case L2CAP_EVENT_CAN_SEND_NOW:
334                     log_info("HID Can send now, emit event");
335                     hid_device_emit_can_send_now_event(hid_device);
336                     break;
337                 default:
338                     break;
339             }
340             break;
341         default:
342             break;
343     }
344 }
345 
346 /**
347  * @brief Set up HID Device
348  */
349 void hid_device_init(void){
350     memset(hid_device, 0, sizeof(hid_device_t));
351     hid_device->cid = 1;
352     l2cap_register_service(packet_handler, PSM_HID_INTERRUPT, 100, LEVEL_2);
353     l2cap_register_service(packet_handler, PSM_HID_CONTROL,   100, LEVEL_2);
354 }
355 
356 /**
357  * @brief Register callback for the HID Device client.
358  * @param callback
359  */
360 void hid_device_register_packet_handler(btstack_packet_handler_t callback){
361     hid_callback = callback;
362 }
363 
364 /**
365  * @brief Request can send now event to send HID Report
366  * @param hid_cid
367  */
368 void hid_device_request_can_send_now_event(uint16_t hid_cid){
369     UNUSED(hid_cid);
370     if (!hid_device->control_cid) return;
371     l2cap_request_can_send_now_event(hid_device->control_cid);
372 }
373 
374 /**
375  * @brief Send HID messageon interrupt channel
376  * @param hid_cid
377  */
378 void hid_device_send_interrupt_message(uint16_t hid_cid, const uint8_t * message, uint16_t message_len){
379     UNUSED(hid_cid);
380     if (!hid_device->interrupt_cid) return;
381     l2cap_send(hid_device->interrupt_cid, (uint8_t*) message, message_len);
382 }
383 
384 /**
385  * @brief Send HID messageon control channel
386  * @param hid_cid
387  */
388 void hid_device_send_contro_message(uint16_t hid_cid, const uint8_t * message, uint16_t message_len){
389     UNUSED(hid_cid);
390     if (!hid_device->control_cid) return;
391     l2cap_send(hid_device->control_cid, (uint8_t*) message, message_len);
392 }
393 
394 /*
395  * @brief Create HID connection to HID Host
396  * @param addr
397  * @param hid_cid to use for other commands
398  * @result status
399  */
400 uint8_t hid_device_connect(bd_addr_t addr, uint16_t * hid_cid){
401 
402     // assign hic_cid
403     *hid_cid = hid_device->cid;
404 
405     // store address
406     memcpy(hid_device->bd_addr, addr, 6);
407 
408     // reset state
409     hid_device->incoming      = 0;
410     hid_device->connected     = 0;
411     hid_device->control_cid   = 0;
412     hid_device->interrupt_cid = 0;
413 
414     // create l2cap control using fixed HID L2CAP PSM
415     log_info("Create outgoing HID Control");
416     uint8_t status = l2cap_create_channel(packet_handler, hid_device->bd_addr, PSM_HID_CONTROL, 48, &hid_device->control_cid);
417 
418     return status;
419 }
420