xref: /btstack/src/ble/att_server.c (revision 3deb3ec68039c68a16974dffc53343233662f909)
1*3deb3ec6SMatthias Ringwald /*
2*3deb3ec6SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
3*3deb3ec6SMatthias Ringwald  *
4*3deb3ec6SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5*3deb3ec6SMatthias Ringwald  * modification, are permitted provided that the following conditions
6*3deb3ec6SMatthias Ringwald  * are met:
7*3deb3ec6SMatthias Ringwald  *
8*3deb3ec6SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9*3deb3ec6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10*3deb3ec6SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11*3deb3ec6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12*3deb3ec6SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13*3deb3ec6SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14*3deb3ec6SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15*3deb3ec6SMatthias Ringwald  *    from this software without specific prior written permission.
16*3deb3ec6SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17*3deb3ec6SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18*3deb3ec6SMatthias Ringwald  *    monetary gain.
19*3deb3ec6SMatthias Ringwald  *
20*3deb3ec6SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21*3deb3ec6SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*3deb3ec6SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*3deb3ec6SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24*3deb3ec6SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25*3deb3ec6SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26*3deb3ec6SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27*3deb3ec6SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28*3deb3ec6SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29*3deb3ec6SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30*3deb3ec6SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*3deb3ec6SMatthias Ringwald  * SUCH DAMAGE.
32*3deb3ec6SMatthias Ringwald  *
33*3deb3ec6SMatthias Ringwald  * Please inquire about commercial licensing options at
34*3deb3ec6SMatthias Ringwald  * [email protected]
35*3deb3ec6SMatthias Ringwald  *
36*3deb3ec6SMatthias Ringwald  */
37*3deb3ec6SMatthias Ringwald 
38*3deb3ec6SMatthias Ringwald 
39*3deb3ec6SMatthias Ringwald //
40*3deb3ec6SMatthias Ringwald // ATT Server Globals
41*3deb3ec6SMatthias Ringwald //
42*3deb3ec6SMatthias Ringwald 
43*3deb3ec6SMatthias Ringwald #include <stdint.h>
44*3deb3ec6SMatthias Ringwald #include <stdio.h>
45*3deb3ec6SMatthias Ringwald #include <stdlib.h>
46*3deb3ec6SMatthias Ringwald #include <string.h>
47*3deb3ec6SMatthias Ringwald #include <inttypes.h>
48*3deb3ec6SMatthias Ringwald 
49*3deb3ec6SMatthias Ringwald #include "btstack-config.h"
50*3deb3ec6SMatthias Ringwald 
51*3deb3ec6SMatthias Ringwald #include "run_loop.h"
52*3deb3ec6SMatthias Ringwald #include "debug.h"
53*3deb3ec6SMatthias Ringwald #include "btstack_memory.h"
54*3deb3ec6SMatthias Ringwald #include "hci.h"
55*3deb3ec6SMatthias Ringwald #include "hci_dump.h"
56*3deb3ec6SMatthias Ringwald 
57*3deb3ec6SMatthias Ringwald #include "l2cap.h"
58*3deb3ec6SMatthias Ringwald 
59*3deb3ec6SMatthias Ringwald #include "sm.h"
60*3deb3ec6SMatthias Ringwald #include "att.h"
61*3deb3ec6SMatthias Ringwald #include "att_dispatch.h"
62*3deb3ec6SMatthias Ringwald #include "gap_le.h"
63*3deb3ec6SMatthias Ringwald #include "le_device_db.h"
64*3deb3ec6SMatthias Ringwald 
65*3deb3ec6SMatthias Ringwald #include "att_server.h"
66*3deb3ec6SMatthias Ringwald 
67*3deb3ec6SMatthias Ringwald static void att_run(void);
68*3deb3ec6SMatthias Ringwald 
69*3deb3ec6SMatthias Ringwald typedef enum {
70*3deb3ec6SMatthias Ringwald     ATT_SERVER_IDLE,
71*3deb3ec6SMatthias Ringwald     ATT_SERVER_REQUEST_RECEIVED,
72*3deb3ec6SMatthias Ringwald     ATT_SERVER_W4_SIGNED_WRITE_VALIDATION,
73*3deb3ec6SMatthias Ringwald     ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED,
74*3deb3ec6SMatthias Ringwald } att_server_state_t;
75*3deb3ec6SMatthias Ringwald 
76*3deb3ec6SMatthias Ringwald static att_connection_t att_connection;
77*3deb3ec6SMatthias Ringwald static att_server_state_t att_server_state;
78*3deb3ec6SMatthias Ringwald 
79*3deb3ec6SMatthias Ringwald static uint8_t   att_client_addr_type;
80*3deb3ec6SMatthias Ringwald static bd_addr_t att_client_address;
81*3deb3ec6SMatthias Ringwald static uint16_t  att_request_size   = 0;
82*3deb3ec6SMatthias Ringwald static uint8_t   att_request_buffer[HCI_ACL_PAYLOAD_SIZE];
83*3deb3ec6SMatthias Ringwald 
84*3deb3ec6SMatthias Ringwald static int       att_ir_le_device_db_index = -1;
85*3deb3ec6SMatthias Ringwald static int       att_ir_lookup_active = 0;
86*3deb3ec6SMatthias Ringwald 
87*3deb3ec6SMatthias Ringwald static int       att_handle_value_indication_handle = 0;
88*3deb3ec6SMatthias Ringwald static timer_source_t att_handle_value_indication_timer;
89*3deb3ec6SMatthias Ringwald 
90*3deb3ec6SMatthias Ringwald static btstack_packet_handler_t att_client_packet_handler = NULL;
91*3deb3ec6SMatthias Ringwald 
92*3deb3ec6SMatthias Ringwald static void att_handle_value_indication_notify_client(uint8_t status, uint16_t client_handle, uint16_t attribute_handle){
93*3deb3ec6SMatthias Ringwald 
94*3deb3ec6SMatthias Ringwald     if (!att_client_packet_handler) return;
95*3deb3ec6SMatthias Ringwald 
96*3deb3ec6SMatthias Ringwald     uint8_t event[7];
97*3deb3ec6SMatthias Ringwald     int pos = 0;
98*3deb3ec6SMatthias Ringwald     event[pos++] = ATT_HANDLE_VALUE_INDICATION_COMPLETE;
99*3deb3ec6SMatthias Ringwald     event[pos++] = sizeof(event) - 2;
100*3deb3ec6SMatthias Ringwald     event[pos++] = status;
101*3deb3ec6SMatthias Ringwald     bt_store_16(event, pos, client_handle);
102*3deb3ec6SMatthias Ringwald     pos += 2;
103*3deb3ec6SMatthias Ringwald     bt_store_16(event, pos, attribute_handle);
104*3deb3ec6SMatthias Ringwald     pos += 2;
105*3deb3ec6SMatthias Ringwald     (*att_client_packet_handler)(HCI_EVENT_PACKET, 0, &event[0], sizeof(event));
106*3deb3ec6SMatthias Ringwald }
107*3deb3ec6SMatthias Ringwald 
108*3deb3ec6SMatthias Ringwald static void att_emit_mtu_event(uint16_t handle, uint16_t mtu){
109*3deb3ec6SMatthias Ringwald 
110*3deb3ec6SMatthias Ringwald     if (!att_client_packet_handler) return;
111*3deb3ec6SMatthias Ringwald 
112*3deb3ec6SMatthias Ringwald     uint8_t event[6];
113*3deb3ec6SMatthias Ringwald     int pos = 0;
114*3deb3ec6SMatthias Ringwald     event[pos++] = ATT_MTU_EXCHANGE_COMPLETE;
115*3deb3ec6SMatthias Ringwald     event[pos++] = sizeof(event) - 2;
116*3deb3ec6SMatthias Ringwald     bt_store_16(event, pos, handle);
117*3deb3ec6SMatthias Ringwald     pos += 2;
118*3deb3ec6SMatthias Ringwald     bt_store_16(event, pos, mtu);
119*3deb3ec6SMatthias Ringwald     pos += 2;
120*3deb3ec6SMatthias Ringwald     (*att_client_packet_handler)(HCI_EVENT_PACKET, 0, &event[0], sizeof(event));
121*3deb3ec6SMatthias Ringwald }
122*3deb3ec6SMatthias Ringwald 
123*3deb3ec6SMatthias Ringwald static void att_handle_value_indication_timeout(timer_source_t *ts){
124*3deb3ec6SMatthias Ringwald     uint16_t att_handle = att_handle_value_indication_handle;
125*3deb3ec6SMatthias Ringwald     att_handle_value_indication_notify_client(ATT_HANDLE_VALUE_INDICATION_TIMEOUT, att_connection.con_handle, att_handle);
126*3deb3ec6SMatthias Ringwald }
127*3deb3ec6SMatthias Ringwald 
128*3deb3ec6SMatthias Ringwald static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
129*3deb3ec6SMatthias Ringwald 
130*3deb3ec6SMatthias Ringwald     bd_addr_t event_address;
131*3deb3ec6SMatthias Ringwald     switch (packet_type) {
132*3deb3ec6SMatthias Ringwald 
133*3deb3ec6SMatthias Ringwald         case HCI_EVENT_PACKET:
134*3deb3ec6SMatthias Ringwald             switch (packet[0]) {
135*3deb3ec6SMatthias Ringwald 
136*3deb3ec6SMatthias Ringwald                 case DAEMON_EVENT_HCI_PACKET_SENT:
137*3deb3ec6SMatthias Ringwald                     att_run();
138*3deb3ec6SMatthias Ringwald                     break;
139*3deb3ec6SMatthias Ringwald 
140*3deb3ec6SMatthias Ringwald                 case HCI_EVENT_LE_META:
141*3deb3ec6SMatthias Ringwald                     switch (packet[2]) {
142*3deb3ec6SMatthias Ringwald                         case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
143*3deb3ec6SMatthias Ringwald                         	// store connection info
144*3deb3ec6SMatthias Ringwald                         	att_client_addr_type = packet[7];
145*3deb3ec6SMatthias Ringwald                             bt_flip_addr(att_client_address, &packet[8]);
146*3deb3ec6SMatthias Ringwald                             // reset connection properties
147*3deb3ec6SMatthias Ringwald                             att_connection.con_handle = READ_BT_16(packet, 4);
148*3deb3ec6SMatthias Ringwald                             att_connection.mtu = ATT_DEFAULT_MTU;
149*3deb3ec6SMatthias Ringwald                             att_connection.max_mtu = l2cap_max_le_mtu();
150*3deb3ec6SMatthias Ringwald                             att_connection.encryption_key_size = 0;
151*3deb3ec6SMatthias Ringwald                             att_connection.authenticated = 0;
152*3deb3ec6SMatthias Ringwald 		                	att_connection.authorized = 0;
153*3deb3ec6SMatthias Ringwald                             break;
154*3deb3ec6SMatthias Ringwald 
155*3deb3ec6SMatthias Ringwald                         default:
156*3deb3ec6SMatthias Ringwald                             break;
157*3deb3ec6SMatthias Ringwald                     }
158*3deb3ec6SMatthias Ringwald                     break;
159*3deb3ec6SMatthias Ringwald 
160*3deb3ec6SMatthias Ringwald                 case HCI_EVENT_ENCRYPTION_CHANGE:
161*3deb3ec6SMatthias Ringwald                 case HCI_EVENT_ENCRYPTION_KEY_REFRESH_COMPLETE:
162*3deb3ec6SMatthias Ringwald                 	// check handle
163*3deb3ec6SMatthias Ringwald                 	if (att_connection.con_handle != READ_BT_16(packet, 3)) break;
164*3deb3ec6SMatthias Ringwald                 	att_connection.encryption_key_size = sm_encryption_key_size(att_connection.con_handle);
165*3deb3ec6SMatthias Ringwald                 	att_connection.authenticated = sm_authenticated(att_connection.con_handle);
166*3deb3ec6SMatthias Ringwald                 	break;
167*3deb3ec6SMatthias Ringwald 
168*3deb3ec6SMatthias Ringwald                 case HCI_EVENT_DISCONNECTION_COMPLETE:
169*3deb3ec6SMatthias Ringwald                     att_clear_transaction_queue(&att_connection);
170*3deb3ec6SMatthias Ringwald                     att_connection.con_handle = 0;
171*3deb3ec6SMatthias Ringwald                     att_handle_value_indication_handle = 0; // reset error state
172*3deb3ec6SMatthias Ringwald                     // restart advertising if we have been connected before
173*3deb3ec6SMatthias Ringwald                     // -> avoid sending advertise enable a second time before command complete was received
174*3deb3ec6SMatthias Ringwald                     att_server_state = ATT_SERVER_IDLE;
175*3deb3ec6SMatthias Ringwald                     break;
176*3deb3ec6SMatthias Ringwald 
177*3deb3ec6SMatthias Ringwald                 case SM_IDENTITY_RESOLVING_STARTED:
178*3deb3ec6SMatthias Ringwald                     log_info("SM_IDENTITY_RESOLVING_STARTED");
179*3deb3ec6SMatthias Ringwald                     att_ir_lookup_active = 1;
180*3deb3ec6SMatthias Ringwald                     break;
181*3deb3ec6SMatthias Ringwald                 case SM_IDENTITY_RESOLVING_SUCCEEDED:
182*3deb3ec6SMatthias Ringwald                     att_ir_lookup_active = 0;
183*3deb3ec6SMatthias Ringwald                     att_ir_le_device_db_index = READ_BT_16(packet, 11);
184*3deb3ec6SMatthias Ringwald                     log_info("SM_IDENTITY_RESOLVING_SUCCEEDED id %u", att_ir_le_device_db_index);
185*3deb3ec6SMatthias Ringwald                     att_run();
186*3deb3ec6SMatthias Ringwald                     break;
187*3deb3ec6SMatthias Ringwald                 case SM_IDENTITY_RESOLVING_FAILED:
188*3deb3ec6SMatthias Ringwald                     log_info("SM_IDENTITY_RESOLVING_FAILED");
189*3deb3ec6SMatthias Ringwald                     att_ir_lookup_active = 0;
190*3deb3ec6SMatthias Ringwald                     att_ir_le_device_db_index = -1;
191*3deb3ec6SMatthias Ringwald                     att_run();
192*3deb3ec6SMatthias Ringwald                     break;
193*3deb3ec6SMatthias Ringwald 
194*3deb3ec6SMatthias Ringwald                 case SM_AUTHORIZATION_RESULT: {
195*3deb3ec6SMatthias Ringwald                     if (packet[4] != att_client_addr_type) break;
196*3deb3ec6SMatthias Ringwald                     bt_flip_addr(event_address, &packet[5]);
197*3deb3ec6SMatthias Ringwald                     if (memcmp(event_address, att_client_address, 6) != 0) break;
198*3deb3ec6SMatthias Ringwald                     att_connection.authorized = packet[11];
199*3deb3ec6SMatthias Ringwald                     att_run();
200*3deb3ec6SMatthias Ringwald                 	break;
201*3deb3ec6SMatthias Ringwald                 }
202*3deb3ec6SMatthias Ringwald 
203*3deb3ec6SMatthias Ringwald                 default:
204*3deb3ec6SMatthias Ringwald                     break;
205*3deb3ec6SMatthias Ringwald             }
206*3deb3ec6SMatthias Ringwald     }
207*3deb3ec6SMatthias Ringwald     if (att_client_packet_handler){
208*3deb3ec6SMatthias Ringwald         att_client_packet_handler(packet_type, channel, packet, size);
209*3deb3ec6SMatthias Ringwald     }
210*3deb3ec6SMatthias Ringwald }
211*3deb3ec6SMatthias Ringwald 
212*3deb3ec6SMatthias Ringwald static void att_signed_write_handle_cmac_result(uint8_t hash[8]){
213*3deb3ec6SMatthias Ringwald 
214*3deb3ec6SMatthias Ringwald     if (att_server_state != ATT_SERVER_W4_SIGNED_WRITE_VALIDATION) return;
215*3deb3ec6SMatthias Ringwald 
216*3deb3ec6SMatthias Ringwald     uint8_t hash_flipped[8];
217*3deb3ec6SMatthias Ringwald     swap64(hash, hash_flipped);
218*3deb3ec6SMatthias Ringwald     if (memcmp(hash_flipped, &att_request_buffer[att_request_size-8], 8)){
219*3deb3ec6SMatthias Ringwald         log_info("ATT Signed Write, invalid signature");
220*3deb3ec6SMatthias Ringwald         att_server_state = ATT_SERVER_IDLE;
221*3deb3ec6SMatthias Ringwald         return;
222*3deb3ec6SMatthias Ringwald     }
223*3deb3ec6SMatthias Ringwald     log_info("ATT Signed Write, valid signature");
224*3deb3ec6SMatthias Ringwald 
225*3deb3ec6SMatthias Ringwald     // update sequence number
226*3deb3ec6SMatthias Ringwald     uint32_t counter_packet = READ_BT_32(att_request_buffer, att_request_size-12);
227*3deb3ec6SMatthias Ringwald     le_device_db_remote_counter_set(att_ir_le_device_db_index, counter_packet+1);
228*3deb3ec6SMatthias Ringwald     att_server_state = ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED;
229*3deb3ec6SMatthias Ringwald     att_run();
230*3deb3ec6SMatthias Ringwald }
231*3deb3ec6SMatthias Ringwald 
232*3deb3ec6SMatthias Ringwald static void att_run(void){
233*3deb3ec6SMatthias Ringwald     switch (att_server_state){
234*3deb3ec6SMatthias Ringwald         case ATT_SERVER_IDLE:
235*3deb3ec6SMatthias Ringwald         case ATT_SERVER_W4_SIGNED_WRITE_VALIDATION:
236*3deb3ec6SMatthias Ringwald             return;
237*3deb3ec6SMatthias Ringwald         case ATT_SERVER_REQUEST_RECEIVED:
238*3deb3ec6SMatthias Ringwald             if (att_request_buffer[0] == ATT_SIGNED_WRITE_COMMAND){
239*3deb3ec6SMatthias Ringwald                 log_info("ATT Signed Write!");
240*3deb3ec6SMatthias Ringwald                 if (!sm_cmac_ready()) {
241*3deb3ec6SMatthias Ringwald                     log_info("ATT Signed Write, sm_cmac engine not ready. Abort");
242*3deb3ec6SMatthias Ringwald                     att_server_state = ATT_SERVER_IDLE;
243*3deb3ec6SMatthias Ringwald                      return;
244*3deb3ec6SMatthias Ringwald                 }
245*3deb3ec6SMatthias Ringwald                 if (att_request_size < (3 + 12)) {
246*3deb3ec6SMatthias Ringwald                     log_info("ATT Signed Write, request to short. Abort.");
247*3deb3ec6SMatthias Ringwald                     att_server_state = ATT_SERVER_IDLE;
248*3deb3ec6SMatthias Ringwald                     return;
249*3deb3ec6SMatthias Ringwald                 }
250*3deb3ec6SMatthias Ringwald                 if (att_ir_lookup_active){
251*3deb3ec6SMatthias Ringwald                     return;
252*3deb3ec6SMatthias Ringwald                 }
253*3deb3ec6SMatthias Ringwald                 if (att_ir_le_device_db_index < 0){
254*3deb3ec6SMatthias Ringwald                     log_info("ATT Signed Write, CSRK not available");
255*3deb3ec6SMatthias Ringwald                     att_server_state = ATT_SERVER_IDLE;
256*3deb3ec6SMatthias Ringwald                     return;
257*3deb3ec6SMatthias Ringwald                 }
258*3deb3ec6SMatthias Ringwald 
259*3deb3ec6SMatthias Ringwald                 // check counter
260*3deb3ec6SMatthias Ringwald                 uint32_t counter_packet = READ_BT_32(att_request_buffer, att_request_size-12);
261*3deb3ec6SMatthias Ringwald                 uint32_t counter_db     = le_device_db_remote_counter_get(att_ir_le_device_db_index);
262*3deb3ec6SMatthias Ringwald                 log_info("ATT Signed Write, DB counter %"PRIu32", packet counter %"PRIu32, counter_db, counter_packet);
263*3deb3ec6SMatthias Ringwald                 if (counter_packet < counter_db){
264*3deb3ec6SMatthias Ringwald                     log_info("ATT Signed Write, db reports higher counter, abort");
265*3deb3ec6SMatthias Ringwald                     att_server_state = ATT_SERVER_IDLE;
266*3deb3ec6SMatthias Ringwald                     return;
267*3deb3ec6SMatthias Ringwald                 }
268*3deb3ec6SMatthias Ringwald 
269*3deb3ec6SMatthias Ringwald                 // signature is { sequence counter, secure hash }
270*3deb3ec6SMatthias Ringwald                 sm_key_t csrk;
271*3deb3ec6SMatthias Ringwald                 le_device_db_remote_csrk_get(att_ir_le_device_db_index, csrk);
272*3deb3ec6SMatthias Ringwald                 att_server_state = ATT_SERVER_W4_SIGNED_WRITE_VALIDATION;
273*3deb3ec6SMatthias Ringwald                 log_info("Orig Signature: ");
274*3deb3ec6SMatthias Ringwald                 hexdump( &att_request_buffer[att_request_size-8], 8);
275*3deb3ec6SMatthias Ringwald                 uint16_t attribute_handle = READ_BT_16(att_request_buffer, 1);
276*3deb3ec6SMatthias Ringwald                 sm_cmac_start(csrk, att_request_buffer[0], attribute_handle, att_request_size - 15, &att_request_buffer[3], counter_packet, att_signed_write_handle_cmac_result);
277*3deb3ec6SMatthias Ringwald                 return;
278*3deb3ec6SMatthias Ringwald             }
279*3deb3ec6SMatthias Ringwald             // NOTE: fall through for regular commands
280*3deb3ec6SMatthias Ringwald 
281*3deb3ec6SMatthias Ringwald         case ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED:
282*3deb3ec6SMatthias Ringwald             if (!l2cap_can_send_fixed_channel_packet_now(att_connection.con_handle)) return;
283*3deb3ec6SMatthias Ringwald 
284*3deb3ec6SMatthias Ringwald             l2cap_reserve_packet_buffer();
285*3deb3ec6SMatthias Ringwald             uint8_t * att_response_buffer = l2cap_get_outgoing_buffer();
286*3deb3ec6SMatthias Ringwald             uint16_t  att_response_size   = att_handle_request(&att_connection, att_request_buffer, att_request_size, att_response_buffer);
287*3deb3ec6SMatthias Ringwald 
288*3deb3ec6SMatthias Ringwald             // intercept "insufficient authorization" for authenticated connections to allow for user authorization
289*3deb3ec6SMatthias Ringwald             if ((att_response_size     >= 4)
290*3deb3ec6SMatthias Ringwald             && (att_response_buffer[0] == ATT_ERROR_RESPONSE)
291*3deb3ec6SMatthias Ringwald             && (att_response_buffer[4] == ATT_ERROR_INSUFFICIENT_AUTHORIZATION)
292*3deb3ec6SMatthias Ringwald             && (att_connection.authenticated)){
293*3deb3ec6SMatthias Ringwald 
294*3deb3ec6SMatthias Ringwald             	switch (sm_authorization_state(att_connection.con_handle)){
295*3deb3ec6SMatthias Ringwald             		case AUTHORIZATION_UNKNOWN:
296*3deb3ec6SMatthias Ringwald                         l2cap_release_packet_buffer();
297*3deb3ec6SMatthias Ringwald 		             	sm_request_pairing(att_connection.con_handle);
298*3deb3ec6SMatthias Ringwald 	    		        return;
299*3deb3ec6SMatthias Ringwald 	    		    case AUTHORIZATION_PENDING:
300*3deb3ec6SMatthias Ringwald                         l2cap_release_packet_buffer();
301*3deb3ec6SMatthias Ringwald 	    		    	return;
302*3deb3ec6SMatthias Ringwald 	    		    default:
303*3deb3ec6SMatthias Ringwald 	    		    	break;
304*3deb3ec6SMatthias Ringwald             	}
305*3deb3ec6SMatthias Ringwald             }
306*3deb3ec6SMatthias Ringwald 
307*3deb3ec6SMatthias Ringwald             att_server_state = ATT_SERVER_IDLE;
308*3deb3ec6SMatthias Ringwald             if (att_response_size == 0) {
309*3deb3ec6SMatthias Ringwald                 l2cap_release_packet_buffer();
310*3deb3ec6SMatthias Ringwald                 return;
311*3deb3ec6SMatthias Ringwald             }
312*3deb3ec6SMatthias Ringwald 
313*3deb3ec6SMatthias Ringwald             l2cap_send_prepared_connectionless(att_connection.con_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, att_response_size);
314*3deb3ec6SMatthias Ringwald 
315*3deb3ec6SMatthias Ringwald             // notify client about MTU exchange result
316*3deb3ec6SMatthias Ringwald             if (att_response_buffer[0] == ATT_EXCHANGE_MTU_RESPONSE){
317*3deb3ec6SMatthias Ringwald                 att_emit_mtu_event(att_connection.con_handle, att_connection.mtu);
318*3deb3ec6SMatthias Ringwald             }
319*3deb3ec6SMatthias Ringwald 
320*3deb3ec6SMatthias Ringwald             break;
321*3deb3ec6SMatthias Ringwald     }
322*3deb3ec6SMatthias Ringwald }
323*3deb3ec6SMatthias Ringwald 
324*3deb3ec6SMatthias Ringwald static void att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){
325*3deb3ec6SMatthias Ringwald     if (packet_type != ATT_DATA_PACKET) return;
326*3deb3ec6SMatthias Ringwald 
327*3deb3ec6SMatthias Ringwald     // handle value indication confirms
328*3deb3ec6SMatthias Ringwald     if (packet[0] == ATT_HANDLE_VALUE_CONFIRMATION && att_handle_value_indication_handle){
329*3deb3ec6SMatthias Ringwald         run_loop_remove_timer(&att_handle_value_indication_timer);
330*3deb3ec6SMatthias Ringwald         uint16_t att_handle = att_handle_value_indication_handle;
331*3deb3ec6SMatthias Ringwald         att_handle_value_indication_handle = 0;
332*3deb3ec6SMatthias Ringwald         att_handle_value_indication_notify_client(0, att_connection.con_handle, att_handle);
333*3deb3ec6SMatthias Ringwald         return;
334*3deb3ec6SMatthias Ringwald     }
335*3deb3ec6SMatthias Ringwald 
336*3deb3ec6SMatthias Ringwald     // check size
337*3deb3ec6SMatthias Ringwald     if (size > sizeof(att_request_buffer)) return;
338*3deb3ec6SMatthias Ringwald 
339*3deb3ec6SMatthias Ringwald     // last request still in processing?
340*3deb3ec6SMatthias Ringwald     if (att_server_state != ATT_SERVER_IDLE) return;
341*3deb3ec6SMatthias Ringwald 
342*3deb3ec6SMatthias Ringwald     // store request
343*3deb3ec6SMatthias Ringwald     att_server_state = ATT_SERVER_REQUEST_RECEIVED;
344*3deb3ec6SMatthias Ringwald     att_request_size = size;
345*3deb3ec6SMatthias Ringwald     memcpy(att_request_buffer, packet, size);
346*3deb3ec6SMatthias Ringwald 
347*3deb3ec6SMatthias Ringwald     att_run();
348*3deb3ec6SMatthias Ringwald }
349*3deb3ec6SMatthias Ringwald 
350*3deb3ec6SMatthias Ringwald void att_server_init(uint8_t const * db, att_read_callback_t read_callback, att_write_callback_t write_callback){
351*3deb3ec6SMatthias Ringwald 
352*3deb3ec6SMatthias Ringwald     sm_register_packet_handler(att_event_packet_handler);
353*3deb3ec6SMatthias Ringwald 
354*3deb3ec6SMatthias Ringwald     att_dispatch_register_server(att_packet_handler);
355*3deb3ec6SMatthias Ringwald 
356*3deb3ec6SMatthias Ringwald     att_server_state = ATT_SERVER_IDLE;
357*3deb3ec6SMatthias Ringwald     att_set_db(db);
358*3deb3ec6SMatthias Ringwald     att_set_read_callback(read_callback);
359*3deb3ec6SMatthias Ringwald     att_set_write_callback(write_callback);
360*3deb3ec6SMatthias Ringwald 
361*3deb3ec6SMatthias Ringwald }
362*3deb3ec6SMatthias Ringwald 
363*3deb3ec6SMatthias Ringwald void att_server_register_packet_handler(btstack_packet_handler_t handler){
364*3deb3ec6SMatthias Ringwald     att_client_packet_handler = handler;
365*3deb3ec6SMatthias Ringwald }
366*3deb3ec6SMatthias Ringwald 
367*3deb3ec6SMatthias Ringwald int  att_server_can_send(void){
368*3deb3ec6SMatthias Ringwald 	if (att_connection.con_handle == 0) return 0;
369*3deb3ec6SMatthias Ringwald 	return l2cap_can_send_fixed_channel_packet_now(att_connection.con_handle);
370*3deb3ec6SMatthias Ringwald }
371*3deb3ec6SMatthias Ringwald 
372*3deb3ec6SMatthias Ringwald int att_server_notify(uint16_t handle, uint8_t *value, uint16_t value_len){
373*3deb3ec6SMatthias Ringwald     if (!l2cap_can_send_fixed_channel_packet_now(att_connection.con_handle)) return BTSTACK_ACL_BUFFERS_FULL;
374*3deb3ec6SMatthias Ringwald 
375*3deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
376*3deb3ec6SMatthias Ringwald     uint8_t * packet_buffer = l2cap_get_outgoing_buffer();
377*3deb3ec6SMatthias Ringwald     uint16_t size = att_prepare_handle_value_notification(&att_connection, handle, value, value_len, packet_buffer);
378*3deb3ec6SMatthias Ringwald 	return l2cap_send_prepared_connectionless(att_connection.con_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, size);
379*3deb3ec6SMatthias Ringwald }
380*3deb3ec6SMatthias Ringwald 
381*3deb3ec6SMatthias Ringwald int att_server_indicate(uint16_t handle, uint8_t *value, uint16_t value_len){
382*3deb3ec6SMatthias Ringwald     if (att_handle_value_indication_handle) return ATT_HANDLE_VALUE_INDICATION_IN_PORGRESS;
383*3deb3ec6SMatthias Ringwald     if (!l2cap_can_send_fixed_channel_packet_now(att_connection.con_handle)) return BTSTACK_ACL_BUFFERS_FULL;
384*3deb3ec6SMatthias Ringwald 
385*3deb3ec6SMatthias Ringwald     // track indication
386*3deb3ec6SMatthias Ringwald     att_handle_value_indication_handle = handle;
387*3deb3ec6SMatthias Ringwald     run_loop_set_timer_handler(&att_handle_value_indication_timer, att_handle_value_indication_timeout);
388*3deb3ec6SMatthias Ringwald     run_loop_set_timer(&att_handle_value_indication_timer, ATT_TRANSACTION_TIMEOUT_MS);
389*3deb3ec6SMatthias Ringwald     run_loop_add_timer(&att_handle_value_indication_timer);
390*3deb3ec6SMatthias Ringwald 
391*3deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
392*3deb3ec6SMatthias Ringwald     uint8_t * packet_buffer = l2cap_get_outgoing_buffer();
393*3deb3ec6SMatthias Ringwald     uint16_t size = att_prepare_handle_value_indication(&att_connection, handle, value, value_len, packet_buffer);
394*3deb3ec6SMatthias Ringwald 	l2cap_send_prepared_connectionless(att_connection.con_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, size);
395*3deb3ec6SMatthias Ringwald     return 0;
396*3deb3ec6SMatthias Ringwald }
397