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