xref: /btstack/src/classic/hid_device.c (revision d40c9ac6cf1a34ffc9b2aba4e96744f8a621b6b1)
1*d40c9ac6SMatthias Ringwald /*
2*d40c9ac6SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
3*d40c9ac6SMatthias Ringwald  *
4*d40c9ac6SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5*d40c9ac6SMatthias Ringwald  * modification, are permitted provided that the following conditions
6*d40c9ac6SMatthias Ringwald  * are met:
7*d40c9ac6SMatthias Ringwald  *
8*d40c9ac6SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9*d40c9ac6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10*d40c9ac6SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11*d40c9ac6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12*d40c9ac6SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13*d40c9ac6SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14*d40c9ac6SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15*d40c9ac6SMatthias Ringwald  *    from this software without specific prior written permission.
16*d40c9ac6SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17*d40c9ac6SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18*d40c9ac6SMatthias Ringwald  *    monetary gain.
19*d40c9ac6SMatthias Ringwald  *
20*d40c9ac6SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21*d40c9ac6SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*d40c9ac6SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*d40c9ac6SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24*d40c9ac6SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25*d40c9ac6SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26*d40c9ac6SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27*d40c9ac6SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28*d40c9ac6SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29*d40c9ac6SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30*d40c9ac6SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*d40c9ac6SMatthias Ringwald  * SUCH DAMAGE.
32*d40c9ac6SMatthias Ringwald  *
33*d40c9ac6SMatthias Ringwald  * Please inquire about commercial licensing options at
34*d40c9ac6SMatthias Ringwald  * [email protected]
35*d40c9ac6SMatthias Ringwald  *
36*d40c9ac6SMatthias Ringwald  */
37*d40c9ac6SMatthias Ringwald 
38*d40c9ac6SMatthias Ringwald #define __BTSTACK_FILE__ "hid_device.c"
39*d40c9ac6SMatthias Ringwald 
40*d40c9ac6SMatthias Ringwald #include <string.h>
41*d40c9ac6SMatthias Ringwald 
42*d40c9ac6SMatthias Ringwald #include "classic/hid_device.h"
43*d40c9ac6SMatthias Ringwald #include "classic/sdp_util.h"
44*d40c9ac6SMatthias Ringwald #include "bluetooth.h"
45*d40c9ac6SMatthias Ringwald #include "bluetooth_sdp.h"
46*d40c9ac6SMatthias Ringwald 
47*d40c9ac6SMatthias Ringwald void hid_create_sdp_record(
48*d40c9ac6SMatthias Ringwald     uint8_t *service,
49*d40c9ac6SMatthias Ringwald     uint32_t service_record_handle,
50*d40c9ac6SMatthias Ringwald     uint16_t hid_device_subclass,
51*d40c9ac6SMatthias Ringwald     uint8_t  hid_country_code,
52*d40c9ac6SMatthias Ringwald     uint8_t  hid_virtual_cable,
53*d40c9ac6SMatthias Ringwald     uint8_t  hid_reconnect_initiate,
54*d40c9ac6SMatthias Ringwald     uint8_t  hid_boot_device,
55*d40c9ac6SMatthias Ringwald     const uint8_t * hid_descriptor, uint16_t hid_descriptor_size,
56*d40c9ac6SMatthias Ringwald     const char *device_name){
57*d40c9ac6SMatthias Ringwald 
58*d40c9ac6SMatthias Ringwald     uint8_t * attribute;
59*d40c9ac6SMatthias Ringwald     de_create_sequence(service);
60*d40c9ac6SMatthias Ringwald 
61*d40c9ac6SMatthias Ringwald     de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_RECORD_HANDLE);
62*d40c9ac6SMatthias Ringwald     de_add_number(service, DE_UINT, DE_SIZE_32, service_record_handle);
63*d40c9ac6SMatthias Ringwald 
64*d40c9ac6SMatthias Ringwald     de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_CLASS_ID_LIST);
65*d40c9ac6SMatthias Ringwald     attribute = de_push_sequence(service);
66*d40c9ac6SMatthias Ringwald     {
67*d40c9ac6SMatthias Ringwald         de_add_number(attribute,  DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE_SERVICE);
68*d40c9ac6SMatthias Ringwald     }
69*d40c9ac6SMatthias Ringwald     de_pop_sequence(service, attribute);
70*d40c9ac6SMatthias Ringwald 
71*d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST);
72*d40c9ac6SMatthias Ringwald     attribute = de_push_sequence(service);
73*d40c9ac6SMatthias Ringwald     {
74*d40c9ac6SMatthias Ringwald         uint8_t * l2cpProtocol = de_push_sequence(attribute);
75*d40c9ac6SMatthias Ringwald         {
76*d40c9ac6SMatthias Ringwald             de_add_number(l2cpProtocol,  DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_L2CAP);
77*d40c9ac6SMatthias Ringwald             de_add_number(l2cpProtocol,  DE_UINT, DE_SIZE_16, PSM_HID_CONTROL);
78*d40c9ac6SMatthias Ringwald         }
79*d40c9ac6SMatthias Ringwald         de_pop_sequence(attribute, l2cpProtocol);
80*d40c9ac6SMatthias Ringwald 
81*d40c9ac6SMatthias Ringwald         uint8_t * hidProtocol = de_push_sequence(attribute);
82*d40c9ac6SMatthias Ringwald         {
83*d40c9ac6SMatthias Ringwald             de_add_number(hidProtocol,  DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_HIDP);
84*d40c9ac6SMatthias Ringwald         }
85*d40c9ac6SMatthias Ringwald         de_pop_sequence(attribute, hidProtocol);
86*d40c9ac6SMatthias Ringwald     }
87*d40c9ac6SMatthias Ringwald     de_pop_sequence(service, attribute);
88*d40c9ac6SMatthias Ringwald 
89*d40c9ac6SMatthias Ringwald     // TODO?
90*d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
91*d40c9ac6SMatthias Ringwald     attribute = de_push_sequence(service);
92*d40c9ac6SMatthias Ringwald     {
93*d40c9ac6SMatthias Ringwald         de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x656e);
94*d40c9ac6SMatthias Ringwald         de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x006a);
95*d40c9ac6SMatthias Ringwald         de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x0100);
96*d40c9ac6SMatthias Ringwald     }
97*d40c9ac6SMatthias Ringwald     de_pop_sequence(service, attribute);
98*d40c9ac6SMatthias Ringwald 
99*d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS);
100*d40c9ac6SMatthias Ringwald     attribute = de_push_sequence(service);
101*d40c9ac6SMatthias Ringwald     {
102*d40c9ac6SMatthias Ringwald         uint8_t * additionalDescriptorAttribute = de_push_sequence(attribute);
103*d40c9ac6SMatthias Ringwald         {
104*d40c9ac6SMatthias Ringwald             uint8_t * l2cpProtocol = de_push_sequence(additionalDescriptorAttribute);
105*d40c9ac6SMatthias Ringwald             {
106*d40c9ac6SMatthias Ringwald                 de_add_number(l2cpProtocol,  DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_L2CAP);
107*d40c9ac6SMatthias Ringwald                 de_add_number(l2cpProtocol,  DE_UINT, DE_SIZE_16, PSM_HID_INTERRUPT);
108*d40c9ac6SMatthias Ringwald             }
109*d40c9ac6SMatthias Ringwald             de_pop_sequence(additionalDescriptorAttribute, l2cpProtocol);
110*d40c9ac6SMatthias Ringwald 
111*d40c9ac6SMatthias Ringwald             uint8_t * hidProtocol = de_push_sequence(attribute);
112*d40c9ac6SMatthias Ringwald             {
113*d40c9ac6SMatthias Ringwald                 de_add_number(hidProtocol,  DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_HIDP);
114*d40c9ac6SMatthias Ringwald             }
115*d40c9ac6SMatthias Ringwald             de_pop_sequence(attribute, hidProtocol);
116*d40c9ac6SMatthias Ringwald         }
117*d40c9ac6SMatthias Ringwald         de_pop_sequence(attribute, additionalDescriptorAttribute);
118*d40c9ac6SMatthias Ringwald     }
119*d40c9ac6SMatthias Ringwald     de_pop_sequence(service, attribute);
120*d40c9ac6SMatthias Ringwald 
121*d40c9ac6SMatthias Ringwald     // 0x0100 "ServiceName"
122*d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, 0x0100);
123*d40c9ac6SMatthias Ringwald     de_add_data(service,  DE_STRING, strlen(device_name), (uint8_t *) device_name);
124*d40c9ac6SMatthias Ringwald 
125*d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
126*d40c9ac6SMatthias Ringwald     attribute = de_push_sequence(service);
127*d40c9ac6SMatthias Ringwald     {
128*d40c9ac6SMatthias Ringwald         uint8_t * hidProfile = de_push_sequence(attribute);
129*d40c9ac6SMatthias Ringwald         {
130*d40c9ac6SMatthias Ringwald             de_add_number(hidProfile,  DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE_SERVICE);
131*d40c9ac6SMatthias Ringwald             de_add_number(hidProfile,  DE_UINT, DE_SIZE_16, 0x0101);    // Version 1.1
132*d40c9ac6SMatthias Ringwald         }
133*d40c9ac6SMatthias Ringwald         de_pop_sequence(attribute, hidProfile);
134*d40c9ac6SMatthias Ringwald     }
135*d40c9ac6SMatthias Ringwald     de_pop_sequence(service, attribute);
136*d40c9ac6SMatthias Ringwald 
137*d40c9ac6SMatthias Ringwald     // Deprecated in v1.1.1
138*d40c9ac6SMatthias Ringwald     // de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_DEVICE_RELEASE_NUMBER);
139*d40c9ac6SMatthias Ringwald     // de_add_number(service,  DE_UINT, DE_SIZE_16, 0x0101);
140*d40c9ac6SMatthias Ringwald 
141*d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_PARSER_VERSION);
142*d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, 0x0111);  // v1.1.1
143*d40c9ac6SMatthias Ringwald 
144*d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_DEVICE_SUBCLASS);
145*d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, hid_device_subclass);
146*d40c9ac6SMatthias Ringwald 
147*d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_COUNTRY_CODE);
148*d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, hid_country_code);
149*d40c9ac6SMatthias Ringwald 
150*d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_VIRTUAL_CABLE);
151*d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_BOOL, DE_SIZE_8,  hid_virtual_cable);
152*d40c9ac6SMatthias Ringwald 
153*d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_RECONNECT_INITIATE);
154*d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_BOOL, DE_SIZE_8,  hid_reconnect_initiate);
155*d40c9ac6SMatthias Ringwald 
156*d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_DESCRIPTOR_LIST);
157*d40c9ac6SMatthias Ringwald     attribute = de_push_sequence(service);
158*d40c9ac6SMatthias Ringwald     {
159*d40c9ac6SMatthias Ringwald         uint8_t* hidDescriptor = de_push_sequence(attribute);
160*d40c9ac6SMatthias Ringwald         {
161*d40c9ac6SMatthias Ringwald             de_add_number(hidDescriptor,  DE_UINT, DE_SIZE_8, 0x22);    // Report Descriptor
162*d40c9ac6SMatthias Ringwald             de_add_data(hidDescriptor,  DE_STRING, hid_descriptor_size, (uint8_t *) hid_descriptor);
163*d40c9ac6SMatthias Ringwald         }
164*d40c9ac6SMatthias Ringwald         de_pop_sequence(attribute, hidDescriptor);
165*d40c9ac6SMatthias Ringwald     }
166*d40c9ac6SMatthias Ringwald     de_pop_sequence(service, attribute);
167*d40c9ac6SMatthias Ringwald 
168*d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_HID_BOOT_DEVICE);
169*d40c9ac6SMatthias Ringwald     de_add_number(service,  DE_BOOL, DE_SIZE_8,  hid_boot_device);
170*d40c9ac6SMatthias Ringwald }
171