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