xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/src/ble_att.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1*042d53a7SEvalZero /*
2*042d53a7SEvalZero  * Licensed to the Apache Software Foundation (ASF) under one
3*042d53a7SEvalZero  * or more contributor license agreements.  See the NOTICE file
4*042d53a7SEvalZero  * distributed with this work for additional information
5*042d53a7SEvalZero  * regarding copyright ownership.  The ASF licenses this file
6*042d53a7SEvalZero  * to you under the Apache License, Version 2.0 (the
7*042d53a7SEvalZero  * "License"); you may not use this file except in compliance
8*042d53a7SEvalZero  * with the License.  You may obtain a copy of the License at
9*042d53a7SEvalZero  *
10*042d53a7SEvalZero  *  http://www.apache.org/licenses/LICENSE-2.0
11*042d53a7SEvalZero  *
12*042d53a7SEvalZero  * Unless required by applicable law or agreed to in writing,
13*042d53a7SEvalZero  * software distributed under the License is distributed on an
14*042d53a7SEvalZero  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15*042d53a7SEvalZero  * KIND, either express or implied.  See the License for the
16*042d53a7SEvalZero  * specific language governing permissions and limitations
17*042d53a7SEvalZero  * under the License.
18*042d53a7SEvalZero  */
19*042d53a7SEvalZero 
20*042d53a7SEvalZero #include <stddef.h>
21*042d53a7SEvalZero #include <errno.h>
22*042d53a7SEvalZero #include "ble_hs_priv.h"
23*042d53a7SEvalZero 
24*042d53a7SEvalZero static uint16_t ble_att_preferred_mtu_val;
25*042d53a7SEvalZero 
26*042d53a7SEvalZero /** Dispatch table for incoming ATT requests.  Sorted by op code. */
27*042d53a7SEvalZero typedef int ble_att_rx_fn(uint16_t conn_handle, struct os_mbuf **om);
28*042d53a7SEvalZero struct ble_att_rx_dispatch_entry {
29*042d53a7SEvalZero     uint8_t bde_op;
30*042d53a7SEvalZero     ble_att_rx_fn *bde_fn;
31*042d53a7SEvalZero };
32*042d53a7SEvalZero 
33*042d53a7SEvalZero /** Dispatch table for incoming ATT commands.  Must be ordered by op code. */
34*042d53a7SEvalZero static const struct ble_att_rx_dispatch_entry ble_att_rx_dispatch[] = {
35*042d53a7SEvalZero     { BLE_ATT_OP_ERROR_RSP,            ble_att_clt_rx_error },
36*042d53a7SEvalZero     { BLE_ATT_OP_MTU_REQ,              ble_att_svr_rx_mtu },
37*042d53a7SEvalZero     { BLE_ATT_OP_MTU_RSP,              ble_att_clt_rx_mtu },
38*042d53a7SEvalZero     { BLE_ATT_OP_FIND_INFO_REQ,        ble_att_svr_rx_find_info },
39*042d53a7SEvalZero     { BLE_ATT_OP_FIND_INFO_RSP,        ble_att_clt_rx_find_info },
40*042d53a7SEvalZero     { BLE_ATT_OP_FIND_TYPE_VALUE_REQ,  ble_att_svr_rx_find_type_value },
41*042d53a7SEvalZero     { BLE_ATT_OP_FIND_TYPE_VALUE_RSP,  ble_att_clt_rx_find_type_value },
42*042d53a7SEvalZero     { BLE_ATT_OP_READ_TYPE_REQ,        ble_att_svr_rx_read_type },
43*042d53a7SEvalZero     { BLE_ATT_OP_READ_TYPE_RSP,        ble_att_clt_rx_read_type },
44*042d53a7SEvalZero     { BLE_ATT_OP_READ_REQ,             ble_att_svr_rx_read },
45*042d53a7SEvalZero     { BLE_ATT_OP_READ_RSP,             ble_att_clt_rx_read },
46*042d53a7SEvalZero     { BLE_ATT_OP_READ_BLOB_REQ,        ble_att_svr_rx_read_blob },
47*042d53a7SEvalZero     { BLE_ATT_OP_READ_BLOB_RSP,        ble_att_clt_rx_read_blob },
48*042d53a7SEvalZero     { BLE_ATT_OP_READ_MULT_REQ,        ble_att_svr_rx_read_mult },
49*042d53a7SEvalZero     { BLE_ATT_OP_READ_MULT_RSP,        ble_att_clt_rx_read_mult },
50*042d53a7SEvalZero     { BLE_ATT_OP_READ_GROUP_TYPE_REQ,  ble_att_svr_rx_read_group_type },
51*042d53a7SEvalZero     { BLE_ATT_OP_READ_GROUP_TYPE_RSP,  ble_att_clt_rx_read_group_type },
52*042d53a7SEvalZero     { BLE_ATT_OP_WRITE_REQ,            ble_att_svr_rx_write },
53*042d53a7SEvalZero     { BLE_ATT_OP_WRITE_RSP,            ble_att_clt_rx_write },
54*042d53a7SEvalZero     { BLE_ATT_OP_PREP_WRITE_REQ,       ble_att_svr_rx_prep_write },
55*042d53a7SEvalZero     { BLE_ATT_OP_PREP_WRITE_RSP,       ble_att_clt_rx_prep_write },
56*042d53a7SEvalZero     { BLE_ATT_OP_EXEC_WRITE_REQ,       ble_att_svr_rx_exec_write },
57*042d53a7SEvalZero     { BLE_ATT_OP_EXEC_WRITE_RSP,       ble_att_clt_rx_exec_write },
58*042d53a7SEvalZero     { BLE_ATT_OP_NOTIFY_REQ,           ble_att_svr_rx_notify },
59*042d53a7SEvalZero     { BLE_ATT_OP_INDICATE_REQ,         ble_att_svr_rx_indicate },
60*042d53a7SEvalZero     { BLE_ATT_OP_INDICATE_RSP,         ble_att_clt_rx_indicate },
61*042d53a7SEvalZero     { BLE_ATT_OP_WRITE_CMD,            ble_att_svr_rx_write_no_rsp },
62*042d53a7SEvalZero };
63*042d53a7SEvalZero 
64*042d53a7SEvalZero #define BLE_ATT_RX_DISPATCH_SZ \
65*042d53a7SEvalZero     (sizeof ble_att_rx_dispatch / sizeof ble_att_rx_dispatch[0])
66*042d53a7SEvalZero 
67*042d53a7SEvalZero STATS_SECT_DECL(ble_att_stats) ble_att_stats;
68*042d53a7SEvalZero STATS_NAME_START(ble_att_stats)
STATS_NAME(ble_att_stats,error_rsp_rx)69*042d53a7SEvalZero     STATS_NAME(ble_att_stats, error_rsp_rx)
70*042d53a7SEvalZero     STATS_NAME(ble_att_stats, error_rsp_tx)
71*042d53a7SEvalZero     STATS_NAME(ble_att_stats, mtu_req_rx)
72*042d53a7SEvalZero     STATS_NAME(ble_att_stats, mtu_req_tx)
73*042d53a7SEvalZero     STATS_NAME(ble_att_stats, mtu_rsp_rx)
74*042d53a7SEvalZero     STATS_NAME(ble_att_stats, mtu_rsp_tx)
75*042d53a7SEvalZero     STATS_NAME(ble_att_stats, find_info_req_rx)
76*042d53a7SEvalZero     STATS_NAME(ble_att_stats, find_info_req_tx)
77*042d53a7SEvalZero     STATS_NAME(ble_att_stats, find_info_rsp_rx)
78*042d53a7SEvalZero     STATS_NAME(ble_att_stats, find_info_rsp_tx)
79*042d53a7SEvalZero     STATS_NAME(ble_att_stats, find_type_value_req_rx)
80*042d53a7SEvalZero     STATS_NAME(ble_att_stats, find_type_value_req_tx)
81*042d53a7SEvalZero     STATS_NAME(ble_att_stats, find_type_value_rsp_rx)
82*042d53a7SEvalZero     STATS_NAME(ble_att_stats, find_type_value_rsp_tx)
83*042d53a7SEvalZero     STATS_NAME(ble_att_stats, read_type_req_rx)
84*042d53a7SEvalZero     STATS_NAME(ble_att_stats, read_type_req_tx)
85*042d53a7SEvalZero     STATS_NAME(ble_att_stats, read_type_rsp_rx)
86*042d53a7SEvalZero     STATS_NAME(ble_att_stats, read_type_rsp_tx)
87*042d53a7SEvalZero     STATS_NAME(ble_att_stats, read_req_rx)
88*042d53a7SEvalZero     STATS_NAME(ble_att_stats, read_req_tx)
89*042d53a7SEvalZero     STATS_NAME(ble_att_stats, read_rsp_rx)
90*042d53a7SEvalZero     STATS_NAME(ble_att_stats, read_rsp_tx)
91*042d53a7SEvalZero     STATS_NAME(ble_att_stats, read_blob_req_rx)
92*042d53a7SEvalZero     STATS_NAME(ble_att_stats, read_blob_req_tx)
93*042d53a7SEvalZero     STATS_NAME(ble_att_stats, read_blob_rsp_rx)
94*042d53a7SEvalZero     STATS_NAME(ble_att_stats, read_blob_rsp_tx)
95*042d53a7SEvalZero     STATS_NAME(ble_att_stats, read_mult_req_rx)
96*042d53a7SEvalZero     STATS_NAME(ble_att_stats, read_mult_req_tx)
97*042d53a7SEvalZero     STATS_NAME(ble_att_stats, read_mult_rsp_rx)
98*042d53a7SEvalZero     STATS_NAME(ble_att_stats, read_mult_rsp_tx)
99*042d53a7SEvalZero     STATS_NAME(ble_att_stats, read_group_type_req_rx)
100*042d53a7SEvalZero     STATS_NAME(ble_att_stats, read_group_type_req_tx)
101*042d53a7SEvalZero     STATS_NAME(ble_att_stats, read_group_type_rsp_rx)
102*042d53a7SEvalZero     STATS_NAME(ble_att_stats, read_group_type_rsp_tx)
103*042d53a7SEvalZero     STATS_NAME(ble_att_stats, write_req_rx)
104*042d53a7SEvalZero     STATS_NAME(ble_att_stats, write_req_tx)
105*042d53a7SEvalZero     STATS_NAME(ble_att_stats, write_rsp_rx)
106*042d53a7SEvalZero     STATS_NAME(ble_att_stats, write_rsp_tx)
107*042d53a7SEvalZero     STATS_NAME(ble_att_stats, prep_write_req_rx)
108*042d53a7SEvalZero     STATS_NAME(ble_att_stats, prep_write_req_tx)
109*042d53a7SEvalZero     STATS_NAME(ble_att_stats, prep_write_rsp_rx)
110*042d53a7SEvalZero     STATS_NAME(ble_att_stats, prep_write_rsp_tx)
111*042d53a7SEvalZero     STATS_NAME(ble_att_stats, exec_write_req_rx)
112*042d53a7SEvalZero     STATS_NAME(ble_att_stats, exec_write_req_tx)
113*042d53a7SEvalZero     STATS_NAME(ble_att_stats, exec_write_rsp_rx)
114*042d53a7SEvalZero     STATS_NAME(ble_att_stats, exec_write_rsp_tx)
115*042d53a7SEvalZero     STATS_NAME(ble_att_stats, notify_req_rx)
116*042d53a7SEvalZero     STATS_NAME(ble_att_stats, notify_req_tx)
117*042d53a7SEvalZero     STATS_NAME(ble_att_stats, indicate_req_rx)
118*042d53a7SEvalZero     STATS_NAME(ble_att_stats, indicate_req_tx)
119*042d53a7SEvalZero     STATS_NAME(ble_att_stats, indicate_rsp_rx)
120*042d53a7SEvalZero     STATS_NAME(ble_att_stats, indicate_rsp_tx)
121*042d53a7SEvalZero     STATS_NAME(ble_att_stats, write_cmd_rx)
122*042d53a7SEvalZero     STATS_NAME(ble_att_stats, write_cmd_tx)
123*042d53a7SEvalZero STATS_NAME_END(ble_att_stats)
124*042d53a7SEvalZero 
125*042d53a7SEvalZero static const struct ble_att_rx_dispatch_entry *
126*042d53a7SEvalZero ble_att_rx_dispatch_entry_find(uint8_t op)
127*042d53a7SEvalZero {
128*042d53a7SEvalZero     const struct ble_att_rx_dispatch_entry *entry;
129*042d53a7SEvalZero     int i;
130*042d53a7SEvalZero 
131*042d53a7SEvalZero     for (i = 0; i < BLE_ATT_RX_DISPATCH_SZ; i++) {
132*042d53a7SEvalZero         entry = ble_att_rx_dispatch + i;
133*042d53a7SEvalZero         if (entry->bde_op == op) {
134*042d53a7SEvalZero             return entry;
135*042d53a7SEvalZero         }
136*042d53a7SEvalZero 
137*042d53a7SEvalZero         if (entry->bde_op > op) {
138*042d53a7SEvalZero             break;
139*042d53a7SEvalZero         }
140*042d53a7SEvalZero     }
141*042d53a7SEvalZero 
142*042d53a7SEvalZero     return NULL;
143*042d53a7SEvalZero }
144*042d53a7SEvalZero 
145*042d53a7SEvalZero int
ble_att_conn_chan_find(uint16_t conn_handle,struct ble_hs_conn ** out_conn,struct ble_l2cap_chan ** out_chan)146*042d53a7SEvalZero ble_att_conn_chan_find(uint16_t conn_handle, struct ble_hs_conn **out_conn,
147*042d53a7SEvalZero                        struct ble_l2cap_chan **out_chan)
148*042d53a7SEvalZero {
149*042d53a7SEvalZero     return ble_hs_misc_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT,
150*042d53a7SEvalZero                                       out_conn, out_chan);
151*042d53a7SEvalZero }
152*042d53a7SEvalZero 
153*042d53a7SEvalZero void
ble_att_inc_tx_stat(uint8_t att_op)154*042d53a7SEvalZero ble_att_inc_tx_stat(uint8_t att_op)
155*042d53a7SEvalZero {
156*042d53a7SEvalZero     switch (att_op) {
157*042d53a7SEvalZero     case BLE_ATT_OP_ERROR_RSP:
158*042d53a7SEvalZero         STATS_INC(ble_att_stats, error_rsp_tx);
159*042d53a7SEvalZero         break;
160*042d53a7SEvalZero 
161*042d53a7SEvalZero     case BLE_ATT_OP_MTU_REQ:
162*042d53a7SEvalZero         STATS_INC(ble_att_stats, mtu_req_tx);
163*042d53a7SEvalZero         break;
164*042d53a7SEvalZero 
165*042d53a7SEvalZero     case BLE_ATT_OP_MTU_RSP:
166*042d53a7SEvalZero         STATS_INC(ble_att_stats, mtu_rsp_tx);
167*042d53a7SEvalZero         break;
168*042d53a7SEvalZero 
169*042d53a7SEvalZero     case BLE_ATT_OP_FIND_INFO_REQ:
170*042d53a7SEvalZero         STATS_INC(ble_att_stats, find_info_req_tx);
171*042d53a7SEvalZero         break;
172*042d53a7SEvalZero 
173*042d53a7SEvalZero     case BLE_ATT_OP_FIND_INFO_RSP:
174*042d53a7SEvalZero         STATS_INC(ble_att_stats, find_info_rsp_tx);
175*042d53a7SEvalZero         break;
176*042d53a7SEvalZero 
177*042d53a7SEvalZero     case BLE_ATT_OP_FIND_TYPE_VALUE_REQ:
178*042d53a7SEvalZero         STATS_INC(ble_att_stats, find_type_value_req_tx);
179*042d53a7SEvalZero         break;
180*042d53a7SEvalZero 
181*042d53a7SEvalZero     case BLE_ATT_OP_FIND_TYPE_VALUE_RSP:
182*042d53a7SEvalZero         STATS_INC(ble_att_stats, find_type_value_rsp_tx);
183*042d53a7SEvalZero         break;
184*042d53a7SEvalZero 
185*042d53a7SEvalZero     case BLE_ATT_OP_READ_TYPE_REQ:
186*042d53a7SEvalZero         STATS_INC(ble_att_stats, read_type_req_tx);
187*042d53a7SEvalZero         break;
188*042d53a7SEvalZero 
189*042d53a7SEvalZero     case BLE_ATT_OP_READ_TYPE_RSP:
190*042d53a7SEvalZero         STATS_INC(ble_att_stats, read_type_rsp_tx);
191*042d53a7SEvalZero         break;
192*042d53a7SEvalZero 
193*042d53a7SEvalZero     case BLE_ATT_OP_READ_REQ:
194*042d53a7SEvalZero         STATS_INC(ble_att_stats, read_req_tx);
195*042d53a7SEvalZero         break;
196*042d53a7SEvalZero 
197*042d53a7SEvalZero     case BLE_ATT_OP_READ_RSP:
198*042d53a7SEvalZero         STATS_INC(ble_att_stats, read_rsp_tx);
199*042d53a7SEvalZero         break;
200*042d53a7SEvalZero 
201*042d53a7SEvalZero     case BLE_ATT_OP_READ_BLOB_REQ:
202*042d53a7SEvalZero         STATS_INC(ble_att_stats, read_blob_req_tx);
203*042d53a7SEvalZero         break;
204*042d53a7SEvalZero 
205*042d53a7SEvalZero     case BLE_ATT_OP_READ_BLOB_RSP:
206*042d53a7SEvalZero         STATS_INC(ble_att_stats, read_blob_rsp_tx);
207*042d53a7SEvalZero         break;
208*042d53a7SEvalZero 
209*042d53a7SEvalZero     case BLE_ATT_OP_READ_MULT_REQ:
210*042d53a7SEvalZero         STATS_INC(ble_att_stats, read_mult_req_tx);
211*042d53a7SEvalZero         break;
212*042d53a7SEvalZero 
213*042d53a7SEvalZero     case BLE_ATT_OP_READ_MULT_RSP:
214*042d53a7SEvalZero         STATS_INC(ble_att_stats, read_mult_rsp_tx);
215*042d53a7SEvalZero         break;
216*042d53a7SEvalZero 
217*042d53a7SEvalZero     case BLE_ATT_OP_READ_GROUP_TYPE_REQ:
218*042d53a7SEvalZero         STATS_INC(ble_att_stats, read_group_type_req_tx);
219*042d53a7SEvalZero         break;
220*042d53a7SEvalZero 
221*042d53a7SEvalZero     case BLE_ATT_OP_READ_GROUP_TYPE_RSP:
222*042d53a7SEvalZero         STATS_INC(ble_att_stats, read_group_type_rsp_tx);
223*042d53a7SEvalZero         break;
224*042d53a7SEvalZero 
225*042d53a7SEvalZero     case BLE_ATT_OP_WRITE_REQ:
226*042d53a7SEvalZero         STATS_INC(ble_att_stats, write_req_tx);
227*042d53a7SEvalZero         break;
228*042d53a7SEvalZero 
229*042d53a7SEvalZero     case BLE_ATT_OP_WRITE_RSP:
230*042d53a7SEvalZero         STATS_INC(ble_att_stats, write_rsp_tx);
231*042d53a7SEvalZero         break;
232*042d53a7SEvalZero 
233*042d53a7SEvalZero     case BLE_ATT_OP_PREP_WRITE_REQ:
234*042d53a7SEvalZero         STATS_INC(ble_att_stats, prep_write_req_tx);
235*042d53a7SEvalZero         break;
236*042d53a7SEvalZero 
237*042d53a7SEvalZero     case BLE_ATT_OP_PREP_WRITE_RSP:
238*042d53a7SEvalZero         STATS_INC(ble_att_stats, prep_write_rsp_tx);
239*042d53a7SEvalZero         break;
240*042d53a7SEvalZero 
241*042d53a7SEvalZero     case BLE_ATT_OP_EXEC_WRITE_REQ:
242*042d53a7SEvalZero         STATS_INC(ble_att_stats, exec_write_req_tx);
243*042d53a7SEvalZero         break;
244*042d53a7SEvalZero 
245*042d53a7SEvalZero     case BLE_ATT_OP_EXEC_WRITE_RSP:
246*042d53a7SEvalZero         STATS_INC(ble_att_stats, exec_write_rsp_tx);
247*042d53a7SEvalZero         break;
248*042d53a7SEvalZero 
249*042d53a7SEvalZero     case BLE_ATT_OP_NOTIFY_REQ:
250*042d53a7SEvalZero         STATS_INC(ble_att_stats, notify_req_tx);
251*042d53a7SEvalZero         break;
252*042d53a7SEvalZero 
253*042d53a7SEvalZero     case BLE_ATT_OP_INDICATE_REQ:
254*042d53a7SEvalZero         STATS_INC(ble_att_stats, indicate_req_tx);
255*042d53a7SEvalZero         break;
256*042d53a7SEvalZero 
257*042d53a7SEvalZero     case BLE_ATT_OP_INDICATE_RSP:
258*042d53a7SEvalZero         STATS_INC(ble_att_stats, indicate_rsp_tx);
259*042d53a7SEvalZero         break;
260*042d53a7SEvalZero 
261*042d53a7SEvalZero     case BLE_ATT_OP_WRITE_CMD:
262*042d53a7SEvalZero         STATS_INC(ble_att_stats, write_cmd_tx);
263*042d53a7SEvalZero         break;
264*042d53a7SEvalZero 
265*042d53a7SEvalZero     default:
266*042d53a7SEvalZero         break;
267*042d53a7SEvalZero     }
268*042d53a7SEvalZero }
269*042d53a7SEvalZero 
270*042d53a7SEvalZero static void
ble_att_inc_rx_stat(uint8_t att_op)271*042d53a7SEvalZero ble_att_inc_rx_stat(uint8_t att_op)
272*042d53a7SEvalZero {
273*042d53a7SEvalZero     switch (att_op) {
274*042d53a7SEvalZero     case BLE_ATT_OP_ERROR_RSP:
275*042d53a7SEvalZero         STATS_INC(ble_att_stats, error_rsp_rx);
276*042d53a7SEvalZero         break;
277*042d53a7SEvalZero 
278*042d53a7SEvalZero     case BLE_ATT_OP_MTU_REQ:
279*042d53a7SEvalZero         STATS_INC(ble_att_stats, mtu_req_rx);
280*042d53a7SEvalZero         break;
281*042d53a7SEvalZero 
282*042d53a7SEvalZero     case BLE_ATT_OP_MTU_RSP:
283*042d53a7SEvalZero         STATS_INC(ble_att_stats, mtu_rsp_rx);
284*042d53a7SEvalZero         break;
285*042d53a7SEvalZero 
286*042d53a7SEvalZero     case BLE_ATT_OP_FIND_INFO_REQ:
287*042d53a7SEvalZero         STATS_INC(ble_att_stats, find_info_req_rx);
288*042d53a7SEvalZero         break;
289*042d53a7SEvalZero 
290*042d53a7SEvalZero     case BLE_ATT_OP_FIND_INFO_RSP:
291*042d53a7SEvalZero         STATS_INC(ble_att_stats, find_info_rsp_rx);
292*042d53a7SEvalZero         break;
293*042d53a7SEvalZero 
294*042d53a7SEvalZero     case BLE_ATT_OP_FIND_TYPE_VALUE_REQ:
295*042d53a7SEvalZero         STATS_INC(ble_att_stats, find_type_value_req_rx);
296*042d53a7SEvalZero         break;
297*042d53a7SEvalZero 
298*042d53a7SEvalZero     case BLE_ATT_OP_FIND_TYPE_VALUE_RSP:
299*042d53a7SEvalZero         STATS_INC(ble_att_stats, find_type_value_rsp_rx);
300*042d53a7SEvalZero         break;
301*042d53a7SEvalZero 
302*042d53a7SEvalZero     case BLE_ATT_OP_READ_TYPE_REQ:
303*042d53a7SEvalZero         STATS_INC(ble_att_stats, read_type_req_rx);
304*042d53a7SEvalZero         break;
305*042d53a7SEvalZero 
306*042d53a7SEvalZero     case BLE_ATT_OP_READ_TYPE_RSP:
307*042d53a7SEvalZero         STATS_INC(ble_att_stats, read_type_rsp_rx);
308*042d53a7SEvalZero         break;
309*042d53a7SEvalZero 
310*042d53a7SEvalZero     case BLE_ATT_OP_READ_REQ:
311*042d53a7SEvalZero         STATS_INC(ble_att_stats, read_req_rx);
312*042d53a7SEvalZero         break;
313*042d53a7SEvalZero 
314*042d53a7SEvalZero     case BLE_ATT_OP_READ_RSP:
315*042d53a7SEvalZero         STATS_INC(ble_att_stats, read_rsp_rx);
316*042d53a7SEvalZero         break;
317*042d53a7SEvalZero 
318*042d53a7SEvalZero     case BLE_ATT_OP_READ_BLOB_REQ:
319*042d53a7SEvalZero         STATS_INC(ble_att_stats, read_blob_req_rx);
320*042d53a7SEvalZero         break;
321*042d53a7SEvalZero 
322*042d53a7SEvalZero     case BLE_ATT_OP_READ_BLOB_RSP:
323*042d53a7SEvalZero         STATS_INC(ble_att_stats, read_blob_rsp_rx);
324*042d53a7SEvalZero         break;
325*042d53a7SEvalZero 
326*042d53a7SEvalZero     case BLE_ATT_OP_READ_MULT_REQ:
327*042d53a7SEvalZero         STATS_INC(ble_att_stats, read_mult_req_rx);
328*042d53a7SEvalZero         break;
329*042d53a7SEvalZero 
330*042d53a7SEvalZero     case BLE_ATT_OP_READ_MULT_RSP:
331*042d53a7SEvalZero         STATS_INC(ble_att_stats, read_mult_rsp_rx);
332*042d53a7SEvalZero         break;
333*042d53a7SEvalZero 
334*042d53a7SEvalZero     case BLE_ATT_OP_READ_GROUP_TYPE_REQ:
335*042d53a7SEvalZero         STATS_INC(ble_att_stats, read_group_type_req_rx);
336*042d53a7SEvalZero         break;
337*042d53a7SEvalZero 
338*042d53a7SEvalZero     case BLE_ATT_OP_READ_GROUP_TYPE_RSP:
339*042d53a7SEvalZero         STATS_INC(ble_att_stats, read_group_type_rsp_rx);
340*042d53a7SEvalZero         break;
341*042d53a7SEvalZero 
342*042d53a7SEvalZero     case BLE_ATT_OP_WRITE_REQ:
343*042d53a7SEvalZero         STATS_INC(ble_att_stats, write_req_rx);
344*042d53a7SEvalZero         break;
345*042d53a7SEvalZero 
346*042d53a7SEvalZero     case BLE_ATT_OP_WRITE_RSP:
347*042d53a7SEvalZero         STATS_INC(ble_att_stats, write_rsp_rx);
348*042d53a7SEvalZero         break;
349*042d53a7SEvalZero 
350*042d53a7SEvalZero     case BLE_ATT_OP_PREP_WRITE_REQ:
351*042d53a7SEvalZero         STATS_INC(ble_att_stats, prep_write_req_rx);
352*042d53a7SEvalZero         break;
353*042d53a7SEvalZero 
354*042d53a7SEvalZero     case BLE_ATT_OP_PREP_WRITE_RSP:
355*042d53a7SEvalZero         STATS_INC(ble_att_stats, prep_write_rsp_rx);
356*042d53a7SEvalZero         break;
357*042d53a7SEvalZero 
358*042d53a7SEvalZero     case BLE_ATT_OP_EXEC_WRITE_REQ:
359*042d53a7SEvalZero         STATS_INC(ble_att_stats, exec_write_req_rx);
360*042d53a7SEvalZero         break;
361*042d53a7SEvalZero 
362*042d53a7SEvalZero     case BLE_ATT_OP_EXEC_WRITE_RSP:
363*042d53a7SEvalZero         STATS_INC(ble_att_stats, exec_write_rsp_rx);
364*042d53a7SEvalZero         break;
365*042d53a7SEvalZero 
366*042d53a7SEvalZero     case BLE_ATT_OP_NOTIFY_REQ:
367*042d53a7SEvalZero         STATS_INC(ble_att_stats, notify_req_rx);
368*042d53a7SEvalZero         break;
369*042d53a7SEvalZero 
370*042d53a7SEvalZero     case BLE_ATT_OP_INDICATE_REQ:
371*042d53a7SEvalZero         STATS_INC(ble_att_stats, indicate_req_rx);
372*042d53a7SEvalZero         break;
373*042d53a7SEvalZero 
374*042d53a7SEvalZero     case BLE_ATT_OP_INDICATE_RSP:
375*042d53a7SEvalZero         STATS_INC(ble_att_stats, indicate_rsp_rx);
376*042d53a7SEvalZero         break;
377*042d53a7SEvalZero 
378*042d53a7SEvalZero     case BLE_ATT_OP_WRITE_CMD:
379*042d53a7SEvalZero         STATS_INC(ble_att_stats, write_cmd_rx);
380*042d53a7SEvalZero         break;
381*042d53a7SEvalZero 
382*042d53a7SEvalZero     default:
383*042d53a7SEvalZero         break;
384*042d53a7SEvalZero     }
385*042d53a7SEvalZero }
386*042d53a7SEvalZero 
387*042d53a7SEvalZero void
ble_att_truncate_to_mtu(const struct ble_l2cap_chan * att_chan,struct os_mbuf * txom)388*042d53a7SEvalZero ble_att_truncate_to_mtu(const struct ble_l2cap_chan *att_chan,
389*042d53a7SEvalZero                         struct os_mbuf *txom)
390*042d53a7SEvalZero {
391*042d53a7SEvalZero     int32_t extra_len;
392*042d53a7SEvalZero     uint16_t mtu;
393*042d53a7SEvalZero 
394*042d53a7SEvalZero     mtu = ble_att_chan_mtu(att_chan);
395*042d53a7SEvalZero     extra_len = OS_MBUF_PKTLEN(txom) - mtu;
396*042d53a7SEvalZero     if (extra_len > 0) {
397*042d53a7SEvalZero         os_mbuf_adj(txom, -extra_len);
398*042d53a7SEvalZero     }
399*042d53a7SEvalZero }
400*042d53a7SEvalZero 
401*042d53a7SEvalZero uint16_t
ble_att_mtu(uint16_t conn_handle)402*042d53a7SEvalZero ble_att_mtu(uint16_t conn_handle)
403*042d53a7SEvalZero {
404*042d53a7SEvalZero     struct ble_l2cap_chan *chan;
405*042d53a7SEvalZero     struct ble_hs_conn *conn;
406*042d53a7SEvalZero     uint16_t mtu;
407*042d53a7SEvalZero     int rc;
408*042d53a7SEvalZero 
409*042d53a7SEvalZero     ble_hs_lock();
410*042d53a7SEvalZero 
411*042d53a7SEvalZero     rc = ble_att_conn_chan_find(conn_handle, &conn, &chan);
412*042d53a7SEvalZero     if (rc == 0) {
413*042d53a7SEvalZero         mtu = ble_att_chan_mtu(chan);
414*042d53a7SEvalZero     } else {
415*042d53a7SEvalZero         mtu = 0;
416*042d53a7SEvalZero     }
417*042d53a7SEvalZero 
418*042d53a7SEvalZero     ble_hs_unlock();
419*042d53a7SEvalZero 
420*042d53a7SEvalZero     return mtu;
421*042d53a7SEvalZero }
422*042d53a7SEvalZero 
423*042d53a7SEvalZero void
ble_att_set_peer_mtu(struct ble_l2cap_chan * chan,uint16_t peer_mtu)424*042d53a7SEvalZero ble_att_set_peer_mtu(struct ble_l2cap_chan *chan, uint16_t peer_mtu)
425*042d53a7SEvalZero {
426*042d53a7SEvalZero     if (peer_mtu < BLE_ATT_MTU_DFLT) {
427*042d53a7SEvalZero         peer_mtu = BLE_ATT_MTU_DFLT;
428*042d53a7SEvalZero     }
429*042d53a7SEvalZero 
430*042d53a7SEvalZero     chan->peer_mtu = peer_mtu;
431*042d53a7SEvalZero }
432*042d53a7SEvalZero 
433*042d53a7SEvalZero uint16_t
ble_att_chan_mtu(const struct ble_l2cap_chan * chan)434*042d53a7SEvalZero ble_att_chan_mtu(const struct ble_l2cap_chan *chan)
435*042d53a7SEvalZero {
436*042d53a7SEvalZero     uint16_t mtu;
437*042d53a7SEvalZero 
438*042d53a7SEvalZero     /* If either side has not exchanged MTU size, use the default.  Otherwise,
439*042d53a7SEvalZero      * use the lesser of the two exchanged values.
440*042d53a7SEvalZero      */
441*042d53a7SEvalZero     if (!(ble_l2cap_is_mtu_req_sent(chan)) ||
442*042d53a7SEvalZero         chan->peer_mtu == 0) {
443*042d53a7SEvalZero 
444*042d53a7SEvalZero         mtu = BLE_ATT_MTU_DFLT;
445*042d53a7SEvalZero     } else {
446*042d53a7SEvalZero         mtu = min(chan->my_mtu, chan->peer_mtu);
447*042d53a7SEvalZero     }
448*042d53a7SEvalZero 
449*042d53a7SEvalZero     BLE_HS_DBG_ASSERT(mtu >= BLE_ATT_MTU_DFLT);
450*042d53a7SEvalZero 
451*042d53a7SEvalZero     return mtu;
452*042d53a7SEvalZero }
453*042d53a7SEvalZero 
454*042d53a7SEvalZero static void
ble_att_rx_handle_unknown_request(uint8_t op,uint16_t conn_handle,struct os_mbuf ** om)455*042d53a7SEvalZero ble_att_rx_handle_unknown_request(uint8_t op, uint16_t conn_handle,
456*042d53a7SEvalZero                                   struct os_mbuf **om)
457*042d53a7SEvalZero {
458*042d53a7SEvalZero     /* If this is command (bit6 is set to 1), do nothing */
459*042d53a7SEvalZero     if (op & 0x40) {
460*042d53a7SEvalZero         return;
461*042d53a7SEvalZero     }
462*042d53a7SEvalZero 
463*042d53a7SEvalZero     os_mbuf_adj(*om, OS_MBUF_PKTLEN(*om));
464*042d53a7SEvalZero     ble_att_svr_tx_error_rsp(conn_handle, *om, op, 0,
465*042d53a7SEvalZero                              BLE_ATT_ERR_REQ_NOT_SUPPORTED);
466*042d53a7SEvalZero 
467*042d53a7SEvalZero     *om = NULL;
468*042d53a7SEvalZero }
469*042d53a7SEvalZero 
470*042d53a7SEvalZero static int
ble_att_rx(struct ble_l2cap_chan * chan)471*042d53a7SEvalZero ble_att_rx(struct ble_l2cap_chan *chan)
472*042d53a7SEvalZero {
473*042d53a7SEvalZero     const struct ble_att_rx_dispatch_entry *entry;
474*042d53a7SEvalZero     uint8_t op;
475*042d53a7SEvalZero     uint16_t conn_handle;
476*042d53a7SEvalZero     struct os_mbuf **om;
477*042d53a7SEvalZero     int rc;
478*042d53a7SEvalZero 
479*042d53a7SEvalZero     conn_handle = ble_l2cap_get_conn_handle(chan);
480*042d53a7SEvalZero     if (conn_handle == BLE_HS_CONN_HANDLE_NONE) {
481*042d53a7SEvalZero         return BLE_HS_ENOTCONN;
482*042d53a7SEvalZero     }
483*042d53a7SEvalZero 
484*042d53a7SEvalZero     om = &chan->rx_buf;
485*042d53a7SEvalZero     BLE_HS_DBG_ASSERT(*om != NULL);
486*042d53a7SEvalZero 
487*042d53a7SEvalZero     rc = os_mbuf_copydata(*om, 0, 1, &op);
488*042d53a7SEvalZero     if (rc != 0) {
489*042d53a7SEvalZero         return BLE_HS_EMSGSIZE;
490*042d53a7SEvalZero     }
491*042d53a7SEvalZero 
492*042d53a7SEvalZero     entry = ble_att_rx_dispatch_entry_find(op);
493*042d53a7SEvalZero     if (entry == NULL) {
494*042d53a7SEvalZero         ble_att_rx_handle_unknown_request(op, conn_handle, om);
495*042d53a7SEvalZero         return BLE_HS_ENOTSUP;
496*042d53a7SEvalZero     }
497*042d53a7SEvalZero 
498*042d53a7SEvalZero     ble_att_inc_rx_stat(op);
499*042d53a7SEvalZero 
500*042d53a7SEvalZero     /* Strip L2CAP ATT header from the front of the mbuf. */
501*042d53a7SEvalZero     os_mbuf_adj(*om, 1);
502*042d53a7SEvalZero 
503*042d53a7SEvalZero     rc = entry->bde_fn(conn_handle, om);
504*042d53a7SEvalZero     if (rc != 0) {
505*042d53a7SEvalZero         if (rc == BLE_HS_ENOTSUP) {
506*042d53a7SEvalZero             ble_att_rx_handle_unknown_request(op, conn_handle, om);
507*042d53a7SEvalZero         }
508*042d53a7SEvalZero         return rc;
509*042d53a7SEvalZero     }
510*042d53a7SEvalZero 
511*042d53a7SEvalZero     return 0;
512*042d53a7SEvalZero }
513*042d53a7SEvalZero 
514*042d53a7SEvalZero uint16_t
ble_att_preferred_mtu(void)515*042d53a7SEvalZero ble_att_preferred_mtu(void)
516*042d53a7SEvalZero {
517*042d53a7SEvalZero     return ble_att_preferred_mtu_val;
518*042d53a7SEvalZero }
519*042d53a7SEvalZero 
520*042d53a7SEvalZero int
ble_att_set_preferred_mtu(uint16_t mtu)521*042d53a7SEvalZero ble_att_set_preferred_mtu(uint16_t mtu)
522*042d53a7SEvalZero {
523*042d53a7SEvalZero     struct ble_l2cap_chan *chan;
524*042d53a7SEvalZero     struct ble_hs_conn *conn;
525*042d53a7SEvalZero     int i;
526*042d53a7SEvalZero 
527*042d53a7SEvalZero     if (mtu < BLE_ATT_MTU_DFLT) {
528*042d53a7SEvalZero         return BLE_HS_EINVAL;
529*042d53a7SEvalZero     }
530*042d53a7SEvalZero     if (mtu > BLE_ATT_MTU_MAX) {
531*042d53a7SEvalZero         return BLE_HS_EINVAL;
532*042d53a7SEvalZero     }
533*042d53a7SEvalZero 
534*042d53a7SEvalZero     ble_att_preferred_mtu_val = mtu;
535*042d53a7SEvalZero 
536*042d53a7SEvalZero     /* Set my_mtu for established connections that haven't exchanged. */
537*042d53a7SEvalZero     ble_hs_lock();
538*042d53a7SEvalZero 
539*042d53a7SEvalZero     i = 0;
540*042d53a7SEvalZero     while ((conn = ble_hs_conn_find_by_idx(i)) != NULL) {
541*042d53a7SEvalZero         chan = ble_hs_conn_chan_find_by_scid(conn, BLE_L2CAP_CID_ATT);
542*042d53a7SEvalZero         BLE_HS_DBG_ASSERT(chan != NULL);
543*042d53a7SEvalZero 
544*042d53a7SEvalZero         if (!(chan->flags & BLE_L2CAP_CHAN_F_TXED_MTU)) {
545*042d53a7SEvalZero             chan->my_mtu = mtu;
546*042d53a7SEvalZero         }
547*042d53a7SEvalZero 
548*042d53a7SEvalZero         i++;
549*042d53a7SEvalZero     }
550*042d53a7SEvalZero 
551*042d53a7SEvalZero     ble_hs_unlock();
552*042d53a7SEvalZero 
553*042d53a7SEvalZero     return 0;
554*042d53a7SEvalZero }
555*042d53a7SEvalZero 
556*042d53a7SEvalZero struct ble_l2cap_chan *
ble_att_create_chan(uint16_t conn_handle)557*042d53a7SEvalZero ble_att_create_chan(uint16_t conn_handle)
558*042d53a7SEvalZero {
559*042d53a7SEvalZero     struct ble_l2cap_chan *chan;
560*042d53a7SEvalZero 
561*042d53a7SEvalZero     chan = ble_l2cap_chan_alloc(conn_handle);
562*042d53a7SEvalZero     if (chan == NULL) {
563*042d53a7SEvalZero         return NULL;
564*042d53a7SEvalZero     }
565*042d53a7SEvalZero 
566*042d53a7SEvalZero     chan->scid = BLE_L2CAP_CID_ATT;
567*042d53a7SEvalZero     chan->dcid = BLE_L2CAP_CID_ATT;
568*042d53a7SEvalZero     chan->my_mtu = ble_att_preferred_mtu_val;
569*042d53a7SEvalZero     chan->rx_fn = ble_att_rx;
570*042d53a7SEvalZero 
571*042d53a7SEvalZero     return chan;
572*042d53a7SEvalZero }
573*042d53a7SEvalZero 
574*042d53a7SEvalZero int
ble_att_init(void)575*042d53a7SEvalZero ble_att_init(void)
576*042d53a7SEvalZero {
577*042d53a7SEvalZero     int rc;
578*042d53a7SEvalZero 
579*042d53a7SEvalZero     ble_att_preferred_mtu_val = MYNEWT_VAL(BLE_ATT_PREFERRED_MTU);
580*042d53a7SEvalZero 
581*042d53a7SEvalZero     rc = stats_init_and_reg(
582*042d53a7SEvalZero         STATS_HDR(ble_att_stats), STATS_SIZE_INIT_PARMS(ble_att_stats,
583*042d53a7SEvalZero         STATS_SIZE_32), STATS_NAME_INIT_PARMS(ble_att_stats), "ble_att");
584*042d53a7SEvalZero     if (rc != 0) {
585*042d53a7SEvalZero         return BLE_HS_EOS;
586*042d53a7SEvalZero     }
587*042d53a7SEvalZero 
588*042d53a7SEvalZero     return 0;
589*042d53a7SEvalZero }
590