xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/src/ble_hs_mbuf.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 "host/ble_hs.h"
21*042d53a7SEvalZero #include "ble_hs_priv.h"
22*042d53a7SEvalZero 
23*042d53a7SEvalZero /**
24*042d53a7SEvalZero  * Allocates an mbuf for use by the nimble host.
25*042d53a7SEvalZero  */
26*042d53a7SEvalZero static struct os_mbuf *
ble_hs_mbuf_gen_pkt(uint16_t leading_space)27*042d53a7SEvalZero ble_hs_mbuf_gen_pkt(uint16_t leading_space)
28*042d53a7SEvalZero {
29*042d53a7SEvalZero     struct os_mbuf *om;
30*042d53a7SEvalZero     int rc;
31*042d53a7SEvalZero 
32*042d53a7SEvalZero     om = os_msys_get_pkthdr(0, 0);
33*042d53a7SEvalZero     if (om == NULL) {
34*042d53a7SEvalZero         return NULL;
35*042d53a7SEvalZero     }
36*042d53a7SEvalZero 
37*042d53a7SEvalZero     if (om->om_omp->omp_databuf_len < leading_space) {
38*042d53a7SEvalZero         rc = os_mbuf_free_chain(om);
39*042d53a7SEvalZero         BLE_HS_DBG_ASSERT_EVAL(rc == 0);
40*042d53a7SEvalZero         return NULL;
41*042d53a7SEvalZero     }
42*042d53a7SEvalZero 
43*042d53a7SEvalZero     om->om_data += leading_space;
44*042d53a7SEvalZero 
45*042d53a7SEvalZero     return om;
46*042d53a7SEvalZero }
47*042d53a7SEvalZero 
48*042d53a7SEvalZero /**
49*042d53a7SEvalZero  * Allocates an mbuf with no leading space.
50*042d53a7SEvalZero  *
51*042d53a7SEvalZero  * @return                  An empty mbuf on success; null on memory
52*042d53a7SEvalZero  *                              exhaustion.
53*042d53a7SEvalZero  */
54*042d53a7SEvalZero struct os_mbuf *
ble_hs_mbuf_bare_pkt(void)55*042d53a7SEvalZero ble_hs_mbuf_bare_pkt(void)
56*042d53a7SEvalZero {
57*042d53a7SEvalZero     return ble_hs_mbuf_gen_pkt(0);
58*042d53a7SEvalZero }
59*042d53a7SEvalZero 
60*042d53a7SEvalZero /**
61*042d53a7SEvalZero  * Allocates an mbuf suitable for an HCI ACL data packet.
62*042d53a7SEvalZero  *
63*042d53a7SEvalZero  * @return                  An empty mbuf on success; null on memory
64*042d53a7SEvalZero  *                              exhaustion.
65*042d53a7SEvalZero  */
66*042d53a7SEvalZero struct os_mbuf *
ble_hs_mbuf_acl_pkt(void)67*042d53a7SEvalZero ble_hs_mbuf_acl_pkt(void)
68*042d53a7SEvalZero {
69*042d53a7SEvalZero     return ble_hs_mbuf_gen_pkt(BLE_HCI_DATA_HDR_SZ);
70*042d53a7SEvalZero }
71*042d53a7SEvalZero 
72*042d53a7SEvalZero /**
73*042d53a7SEvalZero  * Allocates an mbuf suitable for an L2CAP data packet.  The resulting packet
74*042d53a7SEvalZero  * has sufficient leading space for:
75*042d53a7SEvalZero  *     o ACL data header
76*042d53a7SEvalZero  *     o L2CAP B-frame header
77*042d53a7SEvalZero  *
78*042d53a7SEvalZero  * @return                  An empty mbuf on success; null on memory
79*042d53a7SEvalZero  *                              exhaustion.
80*042d53a7SEvalZero  */
81*042d53a7SEvalZero struct os_mbuf *
ble_hs_mbuf_l2cap_pkt(void)82*042d53a7SEvalZero ble_hs_mbuf_l2cap_pkt(void)
83*042d53a7SEvalZero {
84*042d53a7SEvalZero     return ble_hs_mbuf_gen_pkt(BLE_HCI_DATA_HDR_SZ + BLE_L2CAP_HDR_SZ);
85*042d53a7SEvalZero }
86*042d53a7SEvalZero 
87*042d53a7SEvalZero struct os_mbuf *
ble_hs_mbuf_att_pkt(void)88*042d53a7SEvalZero ble_hs_mbuf_att_pkt(void)
89*042d53a7SEvalZero {
90*042d53a7SEvalZero     /* Prepare write request and response are the larget ATT commands which
91*042d53a7SEvalZero      * contain attribute data.
92*042d53a7SEvalZero      */
93*042d53a7SEvalZero      return ble_hs_mbuf_gen_pkt(BLE_HCI_DATA_HDR_SZ +
94*042d53a7SEvalZero                                 BLE_L2CAP_HDR_SZ +
95*042d53a7SEvalZero                                 BLE_ATT_PREP_WRITE_CMD_BASE_SZ);
96*042d53a7SEvalZero }
97*042d53a7SEvalZero 
98*042d53a7SEvalZero struct os_mbuf *
ble_hs_mbuf_from_flat(const void * buf,uint16_t len)99*042d53a7SEvalZero ble_hs_mbuf_from_flat(const void *buf, uint16_t len)
100*042d53a7SEvalZero {
101*042d53a7SEvalZero     struct os_mbuf *om;
102*042d53a7SEvalZero     int rc;
103*042d53a7SEvalZero 
104*042d53a7SEvalZero     om = ble_hs_mbuf_att_pkt();
105*042d53a7SEvalZero     if (om == NULL) {
106*042d53a7SEvalZero         return NULL;
107*042d53a7SEvalZero     }
108*042d53a7SEvalZero 
109*042d53a7SEvalZero     rc = os_mbuf_copyinto(om, 0, buf, len);
110*042d53a7SEvalZero     if (rc != 0) {
111*042d53a7SEvalZero         os_mbuf_free_chain(om);
112*042d53a7SEvalZero         return NULL;
113*042d53a7SEvalZero     }
114*042d53a7SEvalZero 
115*042d53a7SEvalZero     return om;
116*042d53a7SEvalZero }
117*042d53a7SEvalZero 
118*042d53a7SEvalZero int
ble_hs_mbuf_to_flat(const struct os_mbuf * om,void * flat,uint16_t max_len,uint16_t * out_copy_len)119*042d53a7SEvalZero ble_hs_mbuf_to_flat(const struct os_mbuf *om, void *flat, uint16_t max_len,
120*042d53a7SEvalZero                     uint16_t *out_copy_len)
121*042d53a7SEvalZero {
122*042d53a7SEvalZero     uint16_t copy_len;
123*042d53a7SEvalZero     int rc;
124*042d53a7SEvalZero 
125*042d53a7SEvalZero     if (OS_MBUF_PKTLEN(om) <= max_len) {
126*042d53a7SEvalZero         copy_len = OS_MBUF_PKTLEN(om);
127*042d53a7SEvalZero     } else {
128*042d53a7SEvalZero         copy_len = max_len;
129*042d53a7SEvalZero     }
130*042d53a7SEvalZero 
131*042d53a7SEvalZero     rc = os_mbuf_copydata(om, 0, copy_len, flat);
132*042d53a7SEvalZero     if (rc != 0) {
133*042d53a7SEvalZero         return BLE_HS_EUNKNOWN;
134*042d53a7SEvalZero     }
135*042d53a7SEvalZero 
136*042d53a7SEvalZero     if (copy_len > max_len) {
137*042d53a7SEvalZero         rc = BLE_HS_EMSGSIZE;
138*042d53a7SEvalZero     } else {
139*042d53a7SEvalZero         rc = 0;
140*042d53a7SEvalZero     }
141*042d53a7SEvalZero 
142*042d53a7SEvalZero     if (out_copy_len != NULL) {
143*042d53a7SEvalZero         *out_copy_len = copy_len;
144*042d53a7SEvalZero     }
145*042d53a7SEvalZero     return rc;
146*042d53a7SEvalZero }
147*042d53a7SEvalZero 
148*042d53a7SEvalZero int
ble_hs_mbuf_pullup_base(struct os_mbuf ** om,int base_len)149*042d53a7SEvalZero ble_hs_mbuf_pullup_base(struct os_mbuf **om, int base_len)
150*042d53a7SEvalZero {
151*042d53a7SEvalZero     if (OS_MBUF_PKTLEN(*om) < base_len) {
152*042d53a7SEvalZero         return BLE_HS_EBADDATA;
153*042d53a7SEvalZero     }
154*042d53a7SEvalZero 
155*042d53a7SEvalZero     *om = os_mbuf_pullup(*om, base_len);
156*042d53a7SEvalZero     if (*om == NULL) {
157*042d53a7SEvalZero         return BLE_HS_ENOMEM;
158*042d53a7SEvalZero     }
159*042d53a7SEvalZero 
160*042d53a7SEvalZero     return 0;
161*042d53a7SEvalZero }
162