rfcomm_session.c revision 1.1.2.2 1 1.1.2.2 yamt /* $NetBSD: rfcomm_session.c,v 1.1.2.2 2006/06/21 15:10:51 yamt Exp $ */
2 1.1.2.2 yamt
3 1.1.2.2 yamt /*-
4 1.1.2.2 yamt * Copyright (c) 2006 Itronix Inc.
5 1.1.2.2 yamt * All rights reserved.
6 1.1.2.2 yamt *
7 1.1.2.2 yamt * Written by Iain Hibbert for Itronix Inc.
8 1.1.2.2 yamt *
9 1.1.2.2 yamt * Redistribution and use in source and binary forms, with or without
10 1.1.2.2 yamt * modification, are permitted provided that the following conditions
11 1.1.2.2 yamt * are met:
12 1.1.2.2 yamt * 1. Redistributions of source code must retain the above copyright
13 1.1.2.2 yamt * notice, this list of conditions and the following disclaimer.
14 1.1.2.2 yamt * 2. Redistributions in binary form must reproduce the above copyright
15 1.1.2.2 yamt * notice, this list of conditions and the following disclaimer in the
16 1.1.2.2 yamt * documentation and/or other materials provided with the distribution.
17 1.1.2.2 yamt * 3. The name of Itronix Inc. may not be used to endorse
18 1.1.2.2 yamt * or promote products derived from this software without specific
19 1.1.2.2 yamt * prior written permission.
20 1.1.2.2 yamt *
21 1.1.2.2 yamt * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
22 1.1.2.2 yamt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 1.1.2.2 yamt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 1.1.2.2 yamt * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
25 1.1.2.2 yamt * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 1.1.2.2 yamt * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 1.1.2.2 yamt * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 1.1.2.2 yamt * ON ANY THEORY OF LIABILITY, WHETHER IN
29 1.1.2.2 yamt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 1.1.2.2 yamt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 1.1.2.2 yamt * POSSIBILITY OF SUCH DAMAGE.
32 1.1.2.2 yamt */
33 1.1.2.2 yamt
34 1.1.2.2 yamt #include <sys/cdefs.h>
35 1.1.2.2 yamt __KERNEL_RCSID(0, "$NetBSD: rfcomm_session.c,v 1.1.2.2 2006/06/21 15:10:51 yamt Exp $");
36 1.1.2.2 yamt
37 1.1.2.2 yamt #include <sys/param.h>
38 1.1.2.2 yamt #include <sys/kernel.h>
39 1.1.2.2 yamt #include <sys/mbuf.h>
40 1.1.2.2 yamt #include <sys/proc.h>
41 1.1.2.2 yamt #include <sys/systm.h>
42 1.1.2.2 yamt #include <sys/types.h>
43 1.1.2.2 yamt
44 1.1.2.2 yamt #include <netbt/bluetooth.h>
45 1.1.2.2 yamt #include <netbt/hci.h>
46 1.1.2.2 yamt #include <netbt/l2cap.h>
47 1.1.2.2 yamt #include <netbt/rfcomm.h>
48 1.1.2.2 yamt
49 1.1.2.2 yamt /******************************************************************************
50 1.1.2.2 yamt *
51 1.1.2.2 yamt * RFCOMM Multiplexer Sessions sit directly on L2CAP channels, and can
52 1.1.2.2 yamt * multiplex up to 30 incoming and 30 outgoing connections.
53 1.1.2.2 yamt * Only one Multiplexer is allowed between any two devices.
54 1.1.2.2 yamt */
55 1.1.2.2 yamt
56 1.1.2.2 yamt static void rfcomm_session_timeout(void *);
57 1.1.2.2 yamt static void rfcomm_session_recv_sabm(struct rfcomm_session *, int);
58 1.1.2.2 yamt static void rfcomm_session_recv_disc(struct rfcomm_session *, int);
59 1.1.2.2 yamt static void rfcomm_session_recv_ua(struct rfcomm_session *, int);
60 1.1.2.2 yamt static void rfcomm_session_recv_dm(struct rfcomm_session *, int);
61 1.1.2.2 yamt static void rfcomm_session_recv_uih(struct rfcomm_session *, int, int, struct mbuf *, int);
62 1.1.2.2 yamt static void rfcomm_session_recv_mcc(struct rfcomm_session *, struct mbuf *);
63 1.1.2.2 yamt static void rfcomm_session_recv_mcc_test(struct rfcomm_session *, int, struct mbuf *);
64 1.1.2.2 yamt static void rfcomm_session_recv_mcc_fcon(struct rfcomm_session *, int);
65 1.1.2.2 yamt static void rfcomm_session_recv_mcc_fcoff(struct rfcomm_session *, int);
66 1.1.2.2 yamt static void rfcomm_session_recv_mcc_msc(struct rfcomm_session *, int, struct mbuf *);
67 1.1.2.2 yamt static void rfcomm_session_recv_mcc_rpn(struct rfcomm_session *, int, struct mbuf *);
68 1.1.2.2 yamt static void rfcomm_session_recv_mcc_rls(struct rfcomm_session *, int, struct mbuf *);
69 1.1.2.2 yamt static void rfcomm_session_recv_mcc_pn(struct rfcomm_session *, int, struct mbuf *);
70 1.1.2.2 yamt static void rfcomm_session_recv_mcc_nsc(struct rfcomm_session *, int, struct mbuf *);
71 1.1.2.2 yamt
72 1.1.2.2 yamt /* L2CAP callbacks */
73 1.1.2.2 yamt static void rfcomm_session_connecting(void *);
74 1.1.2.2 yamt static void rfcomm_session_connected(void *);
75 1.1.2.2 yamt static void rfcomm_session_disconnected(void *, int);
76 1.1.2.2 yamt static void *rfcomm_session_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *);
77 1.1.2.2 yamt static void rfcomm_session_complete(void *, int);
78 1.1.2.2 yamt static void rfcomm_session_input(void *, struct mbuf *);
79 1.1.2.2 yamt
80 1.1.2.2 yamt static const struct btproto rfcomm_session_proto = {
81 1.1.2.2 yamt rfcomm_session_connecting,
82 1.1.2.2 yamt rfcomm_session_connected,
83 1.1.2.2 yamt rfcomm_session_disconnected,
84 1.1.2.2 yamt rfcomm_session_newconn,
85 1.1.2.2 yamt rfcomm_session_complete,
86 1.1.2.2 yamt rfcomm_session_input
87 1.1.2.2 yamt };
88 1.1.2.2 yamt
89 1.1.2.2 yamt struct rfcomm_session_list
90 1.1.2.2 yamt rfcomm_session_active = LIST_HEAD_INITIALIZER(rfcomm_session_active);
91 1.1.2.2 yamt
92 1.1.2.2 yamt struct rfcomm_session_list
93 1.1.2.2 yamt rfcomm_session_listen = LIST_HEAD_INITIALIZER(rfcomm_session_listen);
94 1.1.2.2 yamt
95 1.1.2.2 yamt POOL_INIT(rfcomm_credit_pool, sizeof(struct rfcomm_credit),
96 1.1.2.2 yamt 0, 0, 0, "rfcomm_credit", NULL);
97 1.1.2.2 yamt
98 1.1.2.2 yamt /*
99 1.1.2.2 yamt * RFCOMM System Parameters (see section 5.3)
100 1.1.2.2 yamt */
101 1.1.2.2 yamt int rfcomm_mtu_default = 127; /* bytes */
102 1.1.2.2 yamt int rfcomm_ack_timeout = 20; /* seconds */
103 1.1.2.2 yamt int rfcomm_mcc_timeout = 20; /* seconds */
104 1.1.2.2 yamt
105 1.1.2.2 yamt /*
106 1.1.2.2 yamt * Reversed CRC table as per TS 07.10 Annex B.3.5
107 1.1.2.2 yamt */
108 1.1.2.2 yamt static uint8_t crctable[256] = { /* reversed, 8-bit, poly=0x07 */
109 1.1.2.2 yamt 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
110 1.1.2.2 yamt 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
111 1.1.2.2 yamt 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
112 1.1.2.2 yamt 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
113 1.1.2.2 yamt
114 1.1.2.2 yamt 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
115 1.1.2.2 yamt 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
116 1.1.2.2 yamt 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
117 1.1.2.2 yamt 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
118 1.1.2.2 yamt
119 1.1.2.2 yamt 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
120 1.1.2.2 yamt 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
121 1.1.2.2 yamt 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
122 1.1.2.2 yamt 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
123 1.1.2.2 yamt
124 1.1.2.2 yamt 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
125 1.1.2.2 yamt 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
126 1.1.2.2 yamt 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
127 1.1.2.2 yamt 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
128 1.1.2.2 yamt
129 1.1.2.2 yamt 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
130 1.1.2.2 yamt 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
131 1.1.2.2 yamt 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
132 1.1.2.2 yamt 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
133 1.1.2.2 yamt
134 1.1.2.2 yamt 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
135 1.1.2.2 yamt 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
136 1.1.2.2 yamt 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
137 1.1.2.2 yamt 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
138 1.1.2.2 yamt
139 1.1.2.2 yamt 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
140 1.1.2.2 yamt 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
141 1.1.2.2 yamt 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
142 1.1.2.2 yamt 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
143 1.1.2.2 yamt
144 1.1.2.2 yamt 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
145 1.1.2.2 yamt 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
146 1.1.2.2 yamt 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
147 1.1.2.2 yamt 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
148 1.1.2.2 yamt };
149 1.1.2.2 yamt
150 1.1.2.2 yamt #define FCS(f, d) crctable[(f) ^ (d)]
151 1.1.2.2 yamt
152 1.1.2.2 yamt /*
153 1.1.2.2 yamt * rfcomm_session_alloc(list, sockaddr)
154 1.1.2.2 yamt *
155 1.1.2.2 yamt * allocate a new session and fill in the blanks, then
156 1.1.2.2 yamt * attach session to front of specified list (active or listen)
157 1.1.2.2 yamt */
158 1.1.2.2 yamt struct rfcomm_session *
159 1.1.2.2 yamt rfcomm_session_alloc(struct rfcomm_session_list *list,
160 1.1.2.2 yamt struct sockaddr_bt *laddr)
161 1.1.2.2 yamt {
162 1.1.2.2 yamt struct rfcomm_session *rs;
163 1.1.2.2 yamt int err;
164 1.1.2.2 yamt
165 1.1.2.2 yamt rs = malloc(sizeof(*rs), M_BLUETOOTH, M_NOWAIT | M_ZERO);
166 1.1.2.2 yamt if (rs == NULL)
167 1.1.2.2 yamt return NULL;
168 1.1.2.2 yamt
169 1.1.2.2 yamt rs->rs_state = RFCOMM_SESSION_CLOSED;
170 1.1.2.2 yamt
171 1.1.2.2 yamt callout_init(&rs->rs_timeout);
172 1.1.2.2 yamt callout_setfunc(&rs->rs_timeout, rfcomm_session_timeout, rs);
173 1.1.2.2 yamt
174 1.1.2.2 yamt SIMPLEQ_INIT(&rs->rs_credits);
175 1.1.2.2 yamt LIST_INIT(&rs->rs_dlcs);
176 1.1.2.2 yamt
177 1.1.2.2 yamt err = l2cap_attach(&rs->rs_l2cap, &rfcomm_session_proto, rs);
178 1.1.2.2 yamt if (err) {
179 1.1.2.2 yamt free(rs, M_BLUETOOTH);
180 1.1.2.2 yamt return NULL;
181 1.1.2.2 yamt }
182 1.1.2.2 yamt
183 1.1.2.2 yamt (void)l2cap_getopt(rs->rs_l2cap, SO_L2CAP_OMTU, &rs->rs_mtu);
184 1.1.2.2 yamt
185 1.1.2.2 yamt if (laddr->bt_psm == L2CAP_PSM_ANY)
186 1.1.2.2 yamt laddr->bt_psm = L2CAP_PSM_RFCOMM;
187 1.1.2.2 yamt
188 1.1.2.2 yamt (void)l2cap_bind(rs->rs_l2cap, laddr);
189 1.1.2.2 yamt
190 1.1.2.2 yamt LIST_INSERT_HEAD(list, rs, rs_next);
191 1.1.2.2 yamt
192 1.1.2.2 yamt return rs;
193 1.1.2.2 yamt }
194 1.1.2.2 yamt
195 1.1.2.2 yamt /*
196 1.1.2.2 yamt * rfcomm_session_free(rfcomm_session)
197 1.1.2.2 yamt *
198 1.1.2.2 yamt * release a session, including any cleanup
199 1.1.2.2 yamt */
200 1.1.2.2 yamt void
201 1.1.2.2 yamt rfcomm_session_free(struct rfcomm_session *rs)
202 1.1.2.2 yamt {
203 1.1.2.2 yamt struct rfcomm_credit *credit;
204 1.1.2.2 yamt
205 1.1.2.2 yamt KASSERT(rs != NULL);
206 1.1.2.2 yamt KASSERT(LIST_EMPTY(&rs->rs_dlcs));
207 1.1.2.2 yamt
208 1.1.2.2 yamt rs->rs_state = RFCOMM_SESSION_CLOSED;
209 1.1.2.2 yamt
210 1.1.2.2 yamt /*
211 1.1.2.2 yamt * If the callout is already invoked we have no way to stop it,
212 1.1.2.2 yamt * but it will call us back right away (there are no DLC's) so
213 1.1.2.2 yamt * not to worry.
214 1.1.2.2 yamt */
215 1.1.2.2 yamt callout_stop(&rs->rs_timeout);
216 1.1.2.2 yamt if (callout_invoking(&rs->rs_timeout))
217 1.1.2.2 yamt return;
218 1.1.2.2 yamt
219 1.1.2.2 yamt /*
220 1.1.2.2 yamt * Take care that rfcomm_session_disconnected() doesnt call
221 1.1.2.2 yamt * us back either as it will do if the l2cap_channel has not
222 1.1.2.2 yamt * been closed when we detach it..
223 1.1.2.2 yamt */
224 1.1.2.2 yamt if (rs->rs_flags & RFCOMM_SESSION_FREE)
225 1.1.2.2 yamt return;
226 1.1.2.2 yamt
227 1.1.2.2 yamt rs->rs_flags |= RFCOMM_SESSION_FREE;
228 1.1.2.2 yamt
229 1.1.2.2 yamt /* throw away any remaining credit notes */
230 1.1.2.2 yamt while ((credit = SIMPLEQ_FIRST(&rs->rs_credits)) != NULL) {
231 1.1.2.2 yamt SIMPLEQ_REMOVE_HEAD(&rs->rs_credits, rc_next);
232 1.1.2.2 yamt pool_put(&rfcomm_credit_pool, credit);
233 1.1.2.2 yamt }
234 1.1.2.2 yamt
235 1.1.2.2 yamt KASSERT(SIMPLEQ_EMPTY(&rs->rs_credits));
236 1.1.2.2 yamt
237 1.1.2.2 yamt /* Goodbye! */
238 1.1.2.2 yamt LIST_REMOVE(rs, rs_next);
239 1.1.2.2 yamt l2cap_detach(&rs->rs_l2cap);
240 1.1.2.2 yamt free(rs, M_BLUETOOTH);
241 1.1.2.2 yamt }
242 1.1.2.2 yamt
243 1.1.2.2 yamt /*
244 1.1.2.2 yamt * rfcomm_session_lookup(sockaddr, sockaddr)
245 1.1.2.2 yamt *
246 1.1.2.2 yamt * Find active rfcomm session matching src and dest addresses
247 1.1.2.2 yamt * when src is BDADDR_ANY match any local address
248 1.1.2.2 yamt */
249 1.1.2.2 yamt struct rfcomm_session *
250 1.1.2.2 yamt rfcomm_session_lookup(struct sockaddr_bt *src, struct sockaddr_bt *dest)
251 1.1.2.2 yamt {
252 1.1.2.2 yamt struct rfcomm_session *rs;
253 1.1.2.2 yamt struct sockaddr_bt addr;
254 1.1.2.2 yamt
255 1.1.2.2 yamt LIST_FOREACH(rs, &rfcomm_session_active, rs_next) {
256 1.1.2.2 yamt if (rs->rs_state == RFCOMM_SESSION_CLOSED)
257 1.1.2.2 yamt continue;
258 1.1.2.2 yamt
259 1.1.2.2 yamt l2cap_sockaddr(rs->rs_l2cap, &addr);
260 1.1.2.2 yamt
261 1.1.2.2 yamt if (bdaddr_same(&src->bt_bdaddr, &addr.bt_bdaddr) == 0)
262 1.1.2.2 yamt if (bdaddr_any(&src->bt_bdaddr) == 0)
263 1.1.2.2 yamt continue;
264 1.1.2.2 yamt
265 1.1.2.2 yamt l2cap_peeraddr(rs->rs_l2cap, &addr);
266 1.1.2.2 yamt
267 1.1.2.2 yamt if (addr.bt_psm != dest->bt_psm)
268 1.1.2.2 yamt continue;
269 1.1.2.2 yamt
270 1.1.2.2 yamt if (bdaddr_same(&dest->bt_bdaddr, &addr.bt_bdaddr))
271 1.1.2.2 yamt break;
272 1.1.2.2 yamt }
273 1.1.2.2 yamt
274 1.1.2.2 yamt return rs;
275 1.1.2.2 yamt }
276 1.1.2.2 yamt
277 1.1.2.2 yamt /*
278 1.1.2.2 yamt * rfcomm_session_timeout(rfcomm_session)
279 1.1.2.2 yamt *
280 1.1.2.2 yamt * Session timeouts are scheduled when a session is left or
281 1.1.2.2 yamt * created with no DLCs, and when SABM(0) or DISC(0) are
282 1.1.2.2 yamt * sent.
283 1.1.2.2 yamt *
284 1.1.2.2 yamt * So, if it is in an open state with DLC's attached then
285 1.1.2.2 yamt * we leave it alone, otherwise the session is lost.
286 1.1.2.2 yamt */
287 1.1.2.2 yamt static void
288 1.1.2.2 yamt rfcomm_session_timeout(void *arg)
289 1.1.2.2 yamt {
290 1.1.2.2 yamt struct rfcomm_session *rs = arg;
291 1.1.2.2 yamt struct rfcomm_dlc *dlc;
292 1.1.2.2 yamt int s;
293 1.1.2.2 yamt
294 1.1.2.2 yamt KASSERT(rs != NULL);
295 1.1.2.2 yamt
296 1.1.2.2 yamt s = splsoftnet();
297 1.1.2.2 yamt callout_ack(&rs->rs_timeout);
298 1.1.2.2 yamt
299 1.1.2.2 yamt if (rs->rs_state != RFCOMM_SESSION_OPEN) {
300 1.1.2.2 yamt DPRINTF("timeout\n");
301 1.1.2.2 yamt rs->rs_state = RFCOMM_SESSION_CLOSED;
302 1.1.2.2 yamt
303 1.1.2.2 yamt while (!LIST_EMPTY(&rs->rs_dlcs)) {
304 1.1.2.2 yamt dlc = LIST_FIRST(&rs->rs_dlcs);
305 1.1.2.2 yamt
306 1.1.2.2 yamt rfcomm_dlc_close(dlc, ETIMEDOUT);
307 1.1.2.2 yamt }
308 1.1.2.2 yamt }
309 1.1.2.2 yamt
310 1.1.2.2 yamt if (LIST_EMPTY(&rs->rs_dlcs)) {
311 1.1.2.2 yamt DPRINTF("expiring\n");
312 1.1.2.2 yamt rfcomm_session_free(rs);
313 1.1.2.2 yamt }
314 1.1.2.2 yamt splx(s);
315 1.1.2.2 yamt }
316 1.1.2.2 yamt
317 1.1.2.2 yamt /***********************************************************************
318 1.1.2.2 yamt *
319 1.1.2.2 yamt * RFCOMM Session L2CAP protocol callbacks
320 1.1.2.2 yamt *
321 1.1.2.2 yamt */
322 1.1.2.2 yamt
323 1.1.2.2 yamt static void
324 1.1.2.2 yamt rfcomm_session_connecting(void *arg)
325 1.1.2.2 yamt {
326 1.1.2.2 yamt //struct rfcomm_session *rs = arg;
327 1.1.2.2 yamt
328 1.1.2.2 yamt DPRINTF("Connecting\n");
329 1.1.2.2 yamt }
330 1.1.2.2 yamt
331 1.1.2.2 yamt static void
332 1.1.2.2 yamt rfcomm_session_connected(void *arg)
333 1.1.2.2 yamt {
334 1.1.2.2 yamt struct rfcomm_session *rs = arg;
335 1.1.2.2 yamt
336 1.1.2.2 yamt DPRINTF("Connected\n");
337 1.1.2.2 yamt
338 1.1.2.2 yamt /*
339 1.1.2.2 yamt * L2CAP is open.
340 1.1.2.2 yamt *
341 1.1.2.2 yamt * If we are initiator, we can send our SABM(0)
342 1.1.2.2 yamt * a timeout should be active?
343 1.1.2.2 yamt *
344 1.1.2.2 yamt * We must take note of the L2CAP MTU because currently
345 1.1.2.2 yamt * the L2CAP implementation can only do Basic Mode.
346 1.1.2.2 yamt */
347 1.1.2.2 yamt l2cap_getopt(rs->rs_l2cap, SO_L2CAP_OMTU, &rs->rs_mtu);
348 1.1.2.2 yamt
349 1.1.2.2 yamt rs->rs_mtu -= 6; /* (RFCOMM overhead could be this big) */
350 1.1.2.2 yamt if (rs->rs_mtu < RFCOMM_MTU_MIN) {
351 1.1.2.2 yamt rfcomm_session_disconnected(rs, EINVAL);
352 1.1.2.2 yamt return;
353 1.1.2.2 yamt }
354 1.1.2.2 yamt
355 1.1.2.2 yamt if (IS_INITIATOR(rs)) {
356 1.1.2.2 yamt int err;
357 1.1.2.2 yamt
358 1.1.2.2 yamt err = rfcomm_session_send_frame(rs, RFCOMM_FRAME_SABM, 0);
359 1.1.2.2 yamt if (err)
360 1.1.2.2 yamt rfcomm_session_disconnected(rs, err);
361 1.1.2.2 yamt
362 1.1.2.2 yamt callout_schedule(&rs->rs_timeout, rfcomm_ack_timeout * hz);
363 1.1.2.2 yamt }
364 1.1.2.2 yamt }
365 1.1.2.2 yamt
366 1.1.2.2 yamt static void
367 1.1.2.2 yamt rfcomm_session_disconnected(void *arg, int err)
368 1.1.2.2 yamt {
369 1.1.2.2 yamt struct rfcomm_session *rs = arg;
370 1.1.2.2 yamt struct rfcomm_dlc *dlc;
371 1.1.2.2 yamt
372 1.1.2.2 yamt DPRINTF("Disconnected\n");
373 1.1.2.2 yamt
374 1.1.2.2 yamt rs->rs_state = RFCOMM_SESSION_CLOSED;
375 1.1.2.2 yamt
376 1.1.2.2 yamt while (!LIST_EMPTY(&rs->rs_dlcs)) {
377 1.1.2.2 yamt dlc = LIST_FIRST(&rs->rs_dlcs);
378 1.1.2.2 yamt
379 1.1.2.2 yamt rfcomm_dlc_close(dlc, err);
380 1.1.2.2 yamt }
381 1.1.2.2 yamt
382 1.1.2.2 yamt rfcomm_session_free(rs);
383 1.1.2.2 yamt }
384 1.1.2.2 yamt
385 1.1.2.2 yamt static void *
386 1.1.2.2 yamt rfcomm_session_newconn(void *arg, struct sockaddr_bt *laddr,
387 1.1.2.2 yamt struct sockaddr_bt *raddr)
388 1.1.2.2 yamt {
389 1.1.2.2 yamt struct rfcomm_session *new, *rs = arg;
390 1.1.2.2 yamt
391 1.1.2.2 yamt DPRINTF("New Connection\n");
392 1.1.2.2 yamt
393 1.1.2.2 yamt /*
394 1.1.2.2 yamt * Incoming session connect request. We should return a new
395 1.1.2.2 yamt * session pointer if this is acceptable. The L2CAP layer
396 1.1.2.2 yamt * passes local and remote addresses, which we must check as
397 1.1.2.2 yamt * only one RFCOMM session is allowed between any two devices
398 1.1.2.2 yamt */
399 1.1.2.2 yamt new = rfcomm_session_lookup(laddr, raddr);
400 1.1.2.2 yamt if (new != NULL)
401 1.1.2.2 yamt return NULL;
402 1.1.2.2 yamt
403 1.1.2.2 yamt new = rfcomm_session_alloc(&rfcomm_session_active, laddr);
404 1.1.2.2 yamt if (new == NULL)
405 1.1.2.2 yamt return NULL;
406 1.1.2.2 yamt
407 1.1.2.2 yamt new->rs_mtu = rs->rs_mtu;
408 1.1.2.2 yamt new->rs_state = RFCOMM_SESSION_WAIT_CONNECT;
409 1.1.2.2 yamt
410 1.1.2.2 yamt /*
411 1.1.2.2 yamt * schedule an expiry so that if nothing comes of it we
412 1.1.2.2 yamt * can punt.
413 1.1.2.2 yamt */
414 1.1.2.2 yamt callout_schedule(&new->rs_timeout, rfcomm_mcc_timeout * hz);
415 1.1.2.2 yamt
416 1.1.2.2 yamt return new->rs_l2cap;
417 1.1.2.2 yamt }
418 1.1.2.2 yamt
419 1.1.2.2 yamt static void
420 1.1.2.2 yamt rfcomm_session_complete(void *arg, int count)
421 1.1.2.2 yamt {
422 1.1.2.2 yamt struct rfcomm_session *rs = arg;
423 1.1.2.2 yamt struct rfcomm_credit *credit;
424 1.1.2.2 yamt struct rfcomm_dlc *dlc;
425 1.1.2.2 yamt
426 1.1.2.2 yamt /*
427 1.1.2.2 yamt * count L2CAP packets are 'complete', meaning that they are cleared
428 1.1.2.2 yamt * our buffers (for best effort) or arrived safe (for guaranteed) so
429 1.1.2.2 yamt * we can take it off our list and pass the message on, so that
430 1.1.2.2 yamt * eventually the data can be removed from the sockbuf
431 1.1.2.2 yamt */
432 1.1.2.2 yamt while (count-- > 0) {
433 1.1.2.2 yamt credit = SIMPLEQ_FIRST(&rs->rs_credits);
434 1.1.2.2 yamt #ifdef DIAGNOSTIC
435 1.1.2.2 yamt if (credit == NULL) {
436 1.1.2.2 yamt printf("%s: too many packets completed!\n", __func__);
437 1.1.2.2 yamt break;
438 1.1.2.2 yamt }
439 1.1.2.2 yamt #endif
440 1.1.2.2 yamt dlc = credit->rc_dlc;
441 1.1.2.2 yamt if (dlc != NULL) {
442 1.1.2.2 yamt dlc->rd_pending--;
443 1.1.2.2 yamt (*dlc->rd_proto->complete)
444 1.1.2.2 yamt (dlc->rd_upper, credit->rc_len);
445 1.1.2.2 yamt
446 1.1.2.2 yamt /*
447 1.1.2.2 yamt * if not using credit flow control, we may push
448 1.1.2.2 yamt * more data now
449 1.1.2.2 yamt */
450 1.1.2.2 yamt if ((rs->rs_flags & RFCOMM_SESSION_CFC) == 0
451 1.1.2.2 yamt && dlc->rd_state == RFCOMM_DLC_OPEN) {
452 1.1.2.2 yamt rfcomm_dlc_start(dlc);
453 1.1.2.2 yamt }
454 1.1.2.2 yamt
455 1.1.2.2 yamt /*
456 1.1.2.2 yamt * When shutdown is indicated, we are just waiting to
457 1.1.2.2 yamt * clear outgoing data.
458 1.1.2.2 yamt */
459 1.1.2.2 yamt if ((dlc->rd_flags & RFCOMM_DLC_SHUTDOWN)
460 1.1.2.2 yamt && dlc->rd_txbuf == NULL && dlc->rd_pending == 0) {
461 1.1.2.2 yamt dlc->rd_state = RFCOMM_DLC_WAIT_DISCONNECT;
462 1.1.2.2 yamt rfcomm_session_send_frame(rs, RFCOMM_FRAME_DISC,
463 1.1.2.2 yamt dlc->rd_dlci);
464 1.1.2.2 yamt callout_schedule(&dlc->rd_timeout,
465 1.1.2.2 yamt rfcomm_ack_timeout * hz);
466 1.1.2.2 yamt }
467 1.1.2.2 yamt }
468 1.1.2.2 yamt
469 1.1.2.2 yamt SIMPLEQ_REMOVE_HEAD(&rs->rs_credits, rc_next);
470 1.1.2.2 yamt pool_put(&rfcomm_credit_pool, credit);
471 1.1.2.2 yamt }
472 1.1.2.2 yamt
473 1.1.2.2 yamt /*
474 1.1.2.2 yamt * If session is closed, we are just waiting to clear the queue
475 1.1.2.2 yamt */
476 1.1.2.2 yamt if (rs->rs_state == RFCOMM_SESSION_CLOSED) {
477 1.1.2.2 yamt if (SIMPLEQ_EMPTY(&rs->rs_credits))
478 1.1.2.2 yamt l2cap_disconnect(rs->rs_l2cap, 0);
479 1.1.2.2 yamt }
480 1.1.2.2 yamt }
481 1.1.2.2 yamt
482 1.1.2.2 yamt /*
483 1.1.2.2 yamt * Receive data from L2CAP layer for session. There is always exactly one
484 1.1.2.2 yamt * RFCOMM frame contained in each L2CAP frame.
485 1.1.2.2 yamt */
486 1.1.2.2 yamt static void
487 1.1.2.2 yamt rfcomm_session_input(void *arg, struct mbuf *m)
488 1.1.2.2 yamt {
489 1.1.2.2 yamt struct rfcomm_session *rs = arg;
490 1.1.2.2 yamt int dlci, len, type, pf;
491 1.1.2.2 yamt uint8_t fcs, b;
492 1.1.2.2 yamt
493 1.1.2.2 yamt KASSERT(m != NULL);
494 1.1.2.2 yamt KASSERT(rs != NULL);
495 1.1.2.2 yamt
496 1.1.2.2 yamt /*
497 1.1.2.2 yamt * UIH frames: FCS is only calculated on address and control fields
498 1.1.2.2 yamt * For other frames: FCS is calculated on address, control and length
499 1.1.2.2 yamt * Length may extend to two octets
500 1.1.2.2 yamt */
501 1.1.2.2 yamt fcs = 0xff;
502 1.1.2.2 yamt
503 1.1.2.2 yamt if (m->m_pkthdr.len < 4) {
504 1.1.2.2 yamt DPRINTF("short frame (%d), discarded\n", m->m_pkthdr.len);
505 1.1.2.2 yamt goto done;
506 1.1.2.2 yamt }
507 1.1.2.2 yamt
508 1.1.2.2 yamt /* address - one octet */
509 1.1.2.2 yamt m_copydata(m, 0, 1, &b);
510 1.1.2.2 yamt m_adj(m, 1);
511 1.1.2.2 yamt fcs = FCS(fcs, b);
512 1.1.2.2 yamt dlci = RFCOMM_DLCI(b);
513 1.1.2.2 yamt
514 1.1.2.2 yamt /* control - one octet */
515 1.1.2.2 yamt m_copydata(m, 0, 1, &b);
516 1.1.2.2 yamt m_adj(m, 1);
517 1.1.2.2 yamt fcs = FCS(fcs, b);
518 1.1.2.2 yamt type = RFCOMM_TYPE(b);
519 1.1.2.2 yamt pf = RFCOMM_PF(b);
520 1.1.2.2 yamt
521 1.1.2.2 yamt /* length - may be two octets */
522 1.1.2.2 yamt m_copydata(m, 0, 1, &b);
523 1.1.2.2 yamt m_adj(m, 1);
524 1.1.2.2 yamt if (type != RFCOMM_FRAME_UIH)
525 1.1.2.2 yamt fcs = FCS(fcs, b);
526 1.1.2.2 yamt len = (b >> 1) & 0x7f;
527 1.1.2.2 yamt
528 1.1.2.2 yamt if (RFCOMM_EA(b) == 0) {
529 1.1.2.2 yamt if (m->m_pkthdr.len < 2) {
530 1.1.2.2 yamt DPRINTF("short frame (%d, EA = 0), discarded\n",
531 1.1.2.2 yamt m->m_pkthdr.len);
532 1.1.2.2 yamt goto done;
533 1.1.2.2 yamt }
534 1.1.2.2 yamt
535 1.1.2.2 yamt m_copydata(m, 0, 1, &b);
536 1.1.2.2 yamt m_adj(m, 1);
537 1.1.2.2 yamt if (type != RFCOMM_FRAME_UIH)
538 1.1.2.2 yamt fcs = FCS(fcs, b);
539 1.1.2.2 yamt
540 1.1.2.2 yamt len |= (b << 7);
541 1.1.2.2 yamt }
542 1.1.2.2 yamt
543 1.1.2.2 yamt /* FCS byte is last octet in frame */
544 1.1.2.2 yamt m_copydata(m, m->m_pkthdr.len - 1, 1, &b);
545 1.1.2.2 yamt m_adj(m, -1);
546 1.1.2.2 yamt fcs = FCS(fcs, b);
547 1.1.2.2 yamt
548 1.1.2.2 yamt if (fcs != 0xcf) {
549 1.1.2.2 yamt DPRINTF("Bad FCS value (%#2.2x), frame discarded\n", fcs);
550 1.1.2.2 yamt goto done;
551 1.1.2.2 yamt }
552 1.1.2.2 yamt
553 1.1.2.2 yamt DPRINTFN(10, "dlci %d, type %2.2x, len = %d\n", dlci, type, len);
554 1.1.2.2 yamt
555 1.1.2.2 yamt switch (type) {
556 1.1.2.2 yamt case RFCOMM_FRAME_SABM:
557 1.1.2.2 yamt if (pf)
558 1.1.2.2 yamt rfcomm_session_recv_sabm(rs, dlci);
559 1.1.2.2 yamt break;
560 1.1.2.2 yamt
561 1.1.2.2 yamt case RFCOMM_FRAME_DISC:
562 1.1.2.2 yamt if (pf)
563 1.1.2.2 yamt rfcomm_session_recv_disc(rs, dlci);
564 1.1.2.2 yamt break;
565 1.1.2.2 yamt
566 1.1.2.2 yamt case RFCOMM_FRAME_UA:
567 1.1.2.2 yamt if (pf)
568 1.1.2.2 yamt rfcomm_session_recv_ua(rs, dlci);
569 1.1.2.2 yamt break;
570 1.1.2.2 yamt
571 1.1.2.2 yamt case RFCOMM_FRAME_DM:
572 1.1.2.2 yamt rfcomm_session_recv_dm(rs, dlci);
573 1.1.2.2 yamt break;
574 1.1.2.2 yamt
575 1.1.2.2 yamt case RFCOMM_FRAME_UIH:
576 1.1.2.2 yamt rfcomm_session_recv_uih(rs, dlci, pf, m, len);
577 1.1.2.2 yamt return; /* (no release) */
578 1.1.2.2 yamt
579 1.1.2.2 yamt default:
580 1.1.2.2 yamt UNKNOWN(type);
581 1.1.2.2 yamt break;
582 1.1.2.2 yamt }
583 1.1.2.2 yamt
584 1.1.2.2 yamt done:
585 1.1.2.2 yamt m_freem(m);
586 1.1.2.2 yamt }
587 1.1.2.2 yamt
588 1.1.2.2 yamt /***********************************************************************
589 1.1.2.2 yamt *
590 1.1.2.2 yamt * RFCOMM Session receive processing
591 1.1.2.2 yamt */
592 1.1.2.2 yamt
593 1.1.2.2 yamt /*
594 1.1.2.2 yamt * rfcomm_session_recv_sabm(rfcomm_session, dlci)
595 1.1.2.2 yamt *
596 1.1.2.2 yamt * Set Asyncrhonous Balanced Mode - open the channel.
597 1.1.2.2 yamt */
598 1.1.2.2 yamt static void
599 1.1.2.2 yamt rfcomm_session_recv_sabm(struct rfcomm_session *rs, int dlci)
600 1.1.2.2 yamt {
601 1.1.2.2 yamt struct rfcomm_mcc_msc msc;
602 1.1.2.2 yamt struct rfcomm_dlc *dlc;
603 1.1.2.2 yamt int err;
604 1.1.2.2 yamt
605 1.1.2.2 yamt DPRINTFN(5, "SABM(%d)\n", dlci);
606 1.1.2.2 yamt
607 1.1.2.2 yamt if (dlci == 0) { /* Open Session */
608 1.1.2.2 yamt rs->rs_state = RFCOMM_SESSION_OPEN;
609 1.1.2.2 yamt rfcomm_session_send_frame(rs, RFCOMM_FRAME_UA, 0);
610 1.1.2.2 yamt LIST_FOREACH(dlc, &rs->rs_dlcs, rd_next) {
611 1.1.2.2 yamt if (dlc->rd_state == RFCOMM_DLC_WAIT_SESSION)
612 1.1.2.2 yamt rfcomm_dlc_connect(dlc);
613 1.1.2.2 yamt }
614 1.1.2.2 yamt return;
615 1.1.2.2 yamt }
616 1.1.2.2 yamt
617 1.1.2.2 yamt if (rs->rs_state != RFCOMM_SESSION_OPEN) {
618 1.1.2.2 yamt DPRINTF("session was not even open!\n");
619 1.1.2.2 yamt return;
620 1.1.2.2 yamt }
621 1.1.2.2 yamt
622 1.1.2.2 yamt /* validate direction bit */
623 1.1.2.2 yamt if ((IS_INITIATOR(rs) && !RFCOMM_DIRECTION(dlci))
624 1.1.2.2 yamt || (!IS_INITIATOR(rs) && RFCOMM_DIRECTION(dlci))) {
625 1.1.2.2 yamt DPRINTF("Invalid direction bit on DLCI\n");
626 1.1.2.2 yamt return;
627 1.1.2.2 yamt }
628 1.1.2.2 yamt
629 1.1.2.2 yamt /*
630 1.1.2.2 yamt * look for our DLC - this may exist if we received PN
631 1.1.2.2 yamt * already, or we may have to fabricate a new one.
632 1.1.2.2 yamt */
633 1.1.2.2 yamt dlc = rfcomm_dlc_lookup(rs, dlci);
634 1.1.2.2 yamt if (dlc == NULL) {
635 1.1.2.2 yamt dlc = rfcomm_dlc_newconn(rs, dlci);
636 1.1.2.2 yamt if (dlc == NULL)
637 1.1.2.2 yamt return; /* (DM is sent) */
638 1.1.2.2 yamt }
639 1.1.2.2 yamt
640 1.1.2.2 yamt DPRINTFN(2, "send UA(%d) state = %d\n", dlci, dlc->rd_state);
641 1.1.2.2 yamt
642 1.1.2.2 yamt err = rfcomm_session_send_frame(rs, RFCOMM_FRAME_UA, dlci);
643 1.1.2.2 yamt if (err) {
644 1.1.2.2 yamt rfcomm_dlc_close(dlc, err);
645 1.1.2.2 yamt return;
646 1.1.2.2 yamt }
647 1.1.2.2 yamt
648 1.1.2.2 yamt /*
649 1.1.2.2 yamt * If this was some kind of spurious SABM then lets
650 1.1.2.2 yamt * not do anything, heh.
651 1.1.2.2 yamt */
652 1.1.2.2 yamt if (dlc->rd_state != RFCOMM_DLC_WAIT_CONNECT)
653 1.1.2.2 yamt return;
654 1.1.2.2 yamt
655 1.1.2.2 yamt msc.address = RFCOMM_MKADDRESS(1, dlc->rd_dlci);
656 1.1.2.2 yamt msc.modem = dlc->rd_lmodem & 0xfe; /* EA = 0 */
657 1.1.2.2 yamt msc.brk = 0x00 | 0x01; /* EA = 1 */
658 1.1.2.2 yamt rfcomm_session_send_mcc(rs, 1, RFCOMM_MCC_MSC, &msc, sizeof(msc));
659 1.1.2.2 yamt callout_schedule(&dlc->rd_timeout, rfcomm_mcc_timeout * hz);
660 1.1.2.2 yamt
661 1.1.2.2 yamt dlc->rd_state = RFCOMM_DLC_OPEN;
662 1.1.2.2 yamt (*dlc->rd_proto->connected)(dlc->rd_upper);
663 1.1.2.2 yamt }
664 1.1.2.2 yamt
665 1.1.2.2 yamt /*
666 1.1.2.2 yamt * Receive Disconnect Command
667 1.1.2.2 yamt */
668 1.1.2.2 yamt static void
669 1.1.2.2 yamt rfcomm_session_recv_disc(struct rfcomm_session *rs, int dlci)
670 1.1.2.2 yamt {
671 1.1.2.2 yamt struct rfcomm_dlc *dlc;
672 1.1.2.2 yamt
673 1.1.2.2 yamt DPRINTFN(5, "DISC(%d)\n", dlci);
674 1.1.2.2 yamt
675 1.1.2.2 yamt if (dlci == 0) {
676 1.1.2.2 yamt /*
677 1.1.2.2 yamt * Disconnect Session
678 1.1.2.2 yamt *
679 1.1.2.2 yamt * We set the session state to CLOSED so that when
680 1.1.2.2 yamt * the UA frame is clear the session will be closed
681 1.1.2.2 yamt * automatically. We wont bother to close any DLC's
682 1.1.2.2 yamt * just yet as there should be none. In the unlikely
683 1.1.2.2 yamt * event that something is left, it will get flushed
684 1.1.2.2 yamt * out as the session goes down.
685 1.1.2.2 yamt */
686 1.1.2.2 yamt rfcomm_session_send_frame(rs, RFCOMM_FRAME_UA, 0);
687 1.1.2.2 yamt rs->rs_state = RFCOMM_SESSION_CLOSED;
688 1.1.2.2 yamt return;
689 1.1.2.2 yamt }
690 1.1.2.2 yamt
691 1.1.2.2 yamt dlc = rfcomm_dlc_lookup(rs, dlci);
692 1.1.2.2 yamt if (dlc == NULL) {
693 1.1.2.2 yamt rfcomm_session_send_frame(rs, RFCOMM_FRAME_DM, dlci);
694 1.1.2.2 yamt return;
695 1.1.2.2 yamt }
696 1.1.2.2 yamt
697 1.1.2.2 yamt rfcomm_dlc_close(dlc, ECONNRESET);
698 1.1.2.2 yamt rfcomm_session_send_frame(rs, RFCOMM_FRAME_UA, dlci);
699 1.1.2.2 yamt }
700 1.1.2.2 yamt
701 1.1.2.2 yamt /*
702 1.1.2.2 yamt * Receive Unnumbered Acknowledgement Response
703 1.1.2.2 yamt *
704 1.1.2.2 yamt * This should be a response to a DISC or SABM frame that we
705 1.1.2.2 yamt * have previously sent. If unexpected, ignore it.
706 1.1.2.2 yamt */
707 1.1.2.2 yamt static void
708 1.1.2.2 yamt rfcomm_session_recv_ua(struct rfcomm_session *rs, int dlci)
709 1.1.2.2 yamt {
710 1.1.2.2 yamt struct rfcomm_mcc_msc msc;
711 1.1.2.2 yamt struct rfcomm_dlc *dlc;
712 1.1.2.2 yamt
713 1.1.2.2 yamt DPRINTFN(5, "UA(%d)\n", dlci);
714 1.1.2.2 yamt
715 1.1.2.2 yamt if (dlci == 0) {
716 1.1.2.2 yamt switch (rs->rs_state) {
717 1.1.2.2 yamt case RFCOMM_SESSION_WAIT_CONNECT: /* We sent SABM */
718 1.1.2.2 yamt callout_stop(&rs->rs_timeout);
719 1.1.2.2 yamt rs->rs_state = RFCOMM_SESSION_OPEN;
720 1.1.2.2 yamt LIST_FOREACH(dlc, &rs->rs_dlcs, rd_next) {
721 1.1.2.2 yamt if (dlc->rd_state == RFCOMM_DLC_WAIT_SESSION)
722 1.1.2.2 yamt rfcomm_dlc_connect(dlc);
723 1.1.2.2 yamt }
724 1.1.2.2 yamt break;
725 1.1.2.2 yamt
726 1.1.2.2 yamt case RFCOMM_SESSION_WAIT_DISCONNECT: /* We sent DISC */
727 1.1.2.2 yamt callout_stop(&rs->rs_timeout);
728 1.1.2.2 yamt rs->rs_state = RFCOMM_SESSION_CLOSED;
729 1.1.2.2 yamt l2cap_disconnect(rs->rs_l2cap, 0);
730 1.1.2.2 yamt break;
731 1.1.2.2 yamt
732 1.1.2.2 yamt default:
733 1.1.2.2 yamt DPRINTF("Received spurious UA(0)!\n");
734 1.1.2.2 yamt break;
735 1.1.2.2 yamt }
736 1.1.2.2 yamt
737 1.1.2.2 yamt return;
738 1.1.2.2 yamt }
739 1.1.2.2 yamt
740 1.1.2.2 yamt /*
741 1.1.2.2 yamt * If we have no DLC on this dlci, we may have aborted
742 1.1.2.2 yamt * without shutting down properly, so check if the session
743 1.1.2.2 yamt * needs disconnecting.
744 1.1.2.2 yamt */
745 1.1.2.2 yamt dlc = rfcomm_dlc_lookup(rs, dlci);
746 1.1.2.2 yamt if (dlc == NULL)
747 1.1.2.2 yamt goto check;
748 1.1.2.2 yamt
749 1.1.2.2 yamt switch (dlc->rd_state) {
750 1.1.2.2 yamt case RFCOMM_DLC_WAIT_CONNECT: /* We sent SABM */
751 1.1.2.2 yamt msc.address = RFCOMM_MKADDRESS(1, dlc->rd_dlci);
752 1.1.2.2 yamt msc.modem = dlc->rd_lmodem & 0xfe; /* EA = 0 */
753 1.1.2.2 yamt msc.brk = 0x00 | 0x01; /* EA = 1 */
754 1.1.2.2 yamt rfcomm_session_send_mcc(rs, 1, RFCOMM_MCC_MSC,
755 1.1.2.2 yamt &msc, sizeof(msc));
756 1.1.2.2 yamt callout_schedule(&dlc->rd_timeout, rfcomm_mcc_timeout * hz);
757 1.1.2.2 yamt
758 1.1.2.2 yamt dlc->rd_state = RFCOMM_DLC_OPEN;
759 1.1.2.2 yamt (*dlc->rd_proto->connected)(dlc->rd_upper);
760 1.1.2.2 yamt return;
761 1.1.2.2 yamt
762 1.1.2.2 yamt case RFCOMM_DLC_WAIT_DISCONNECT: /* We sent DISC */
763 1.1.2.2 yamt rfcomm_dlc_close(dlc, 0);
764 1.1.2.2 yamt break;
765 1.1.2.2 yamt
766 1.1.2.2 yamt default:
767 1.1.2.2 yamt DPRINTF("Received spurious UA(%d)!\n", dlci);
768 1.1.2.2 yamt return;
769 1.1.2.2 yamt }
770 1.1.2.2 yamt
771 1.1.2.2 yamt check: /* last one out turns out the light */
772 1.1.2.2 yamt if (LIST_EMPTY(&rs->rs_dlcs)) {
773 1.1.2.2 yamt rs->rs_state = RFCOMM_SESSION_WAIT_DISCONNECT;
774 1.1.2.2 yamt rfcomm_session_send_frame(rs, RFCOMM_FRAME_DISC, 0);
775 1.1.2.2 yamt callout_schedule(&rs->rs_timeout, rfcomm_ack_timeout * hz);
776 1.1.2.2 yamt }
777 1.1.2.2 yamt }
778 1.1.2.2 yamt
779 1.1.2.2 yamt /*
780 1.1.2.2 yamt * Receive Disconnected Mode Response
781 1.1.2.2 yamt *
782 1.1.2.2 yamt * If this does not apply to a known DLC then we may ignore it.
783 1.1.2.2 yamt */
784 1.1.2.2 yamt static void
785 1.1.2.2 yamt rfcomm_session_recv_dm(struct rfcomm_session *rs, int dlci)
786 1.1.2.2 yamt {
787 1.1.2.2 yamt struct rfcomm_dlc *dlc;
788 1.1.2.2 yamt
789 1.1.2.2 yamt DPRINTFN(5, "DM(%d)\n", dlci);
790 1.1.2.2 yamt
791 1.1.2.2 yamt dlc = rfcomm_dlc_lookup(rs, dlci);
792 1.1.2.2 yamt if (dlc == NULL)
793 1.1.2.2 yamt return;
794 1.1.2.2 yamt
795 1.1.2.2 yamt if (dlc->rd_state == RFCOMM_DLC_WAIT_CONNECT)
796 1.1.2.2 yamt rfcomm_dlc_close(dlc, ECONNREFUSED);
797 1.1.2.2 yamt else
798 1.1.2.2 yamt rfcomm_dlc_close(dlc, ECONNRESET);
799 1.1.2.2 yamt }
800 1.1.2.2 yamt
801 1.1.2.2 yamt /*
802 1.1.2.2 yamt * Receive Unnumbered Information with Header check (MCC or data packet)
803 1.1.2.2 yamt */
804 1.1.2.2 yamt static void
805 1.1.2.2 yamt rfcomm_session_recv_uih(struct rfcomm_session *rs, int dlci,
806 1.1.2.2 yamt int pf, struct mbuf *m, int len)
807 1.1.2.2 yamt {
808 1.1.2.2 yamt struct rfcomm_dlc *dlc;
809 1.1.2.2 yamt uint8_t credits = 0;
810 1.1.2.2 yamt
811 1.1.2.2 yamt DPRINTFN(10, "UIH(%d)\n", dlci);
812 1.1.2.2 yamt
813 1.1.2.2 yamt if (dlci == 0) {
814 1.1.2.2 yamt rfcomm_session_recv_mcc(rs, m);
815 1.1.2.2 yamt return;
816 1.1.2.2 yamt }
817 1.1.2.2 yamt
818 1.1.2.2 yamt if (m->m_pkthdr.len != len + pf) {
819 1.1.2.2 yamt DPRINTF("Bad Frame Length (%d), frame discarded\n",
820 1.1.2.2 yamt m->m_pkthdr.len);
821 1.1.2.2 yamt
822 1.1.2.2 yamt goto discard;
823 1.1.2.2 yamt }
824 1.1.2.2 yamt
825 1.1.2.2 yamt dlc = rfcomm_dlc_lookup(rs, dlci);
826 1.1.2.2 yamt if (dlc == NULL) {
827 1.1.2.2 yamt DPRINTF("UIH received for non existent DLC, discarded\n");
828 1.1.2.2 yamt rfcomm_session_send_frame(rs, RFCOMM_FRAME_DM, dlci);
829 1.1.2.2 yamt goto discard;
830 1.1.2.2 yamt }
831 1.1.2.2 yamt
832 1.1.2.2 yamt if (dlc->rd_state != RFCOMM_DLC_OPEN) {
833 1.1.2.2 yamt DPRINTF("non-open DLC (state = %d), discarded\n",
834 1.1.2.2 yamt dlc->rd_state);
835 1.1.2.2 yamt goto discard;
836 1.1.2.2 yamt }
837 1.1.2.2 yamt
838 1.1.2.2 yamt /* if PF is set, credits were included */
839 1.1.2.2 yamt if (rs->rs_flags & RFCOMM_SESSION_CFC) {
840 1.1.2.2 yamt if (pf != 0) {
841 1.1.2.2 yamt if (m->m_pkthdr.len < sizeof(credits)) {
842 1.1.2.2 yamt DPRINTF("Bad PF value, UIH discarded\n");
843 1.1.2.2 yamt goto discard;
844 1.1.2.2 yamt }
845 1.1.2.2 yamt
846 1.1.2.2 yamt m_copydata(m, 0, sizeof(credits), &credits);
847 1.1.2.2 yamt m_adj(m, sizeof(credits));
848 1.1.2.2 yamt
849 1.1.2.2 yamt dlc->rd_txcred += credits;
850 1.1.2.2 yamt
851 1.1.2.2 yamt if (credits > 0 && dlc->rd_txbuf != NULL)
852 1.1.2.2 yamt rfcomm_dlc_start(dlc);
853 1.1.2.2 yamt }
854 1.1.2.2 yamt
855 1.1.2.2 yamt if (len == 0)
856 1.1.2.2 yamt goto discard;
857 1.1.2.2 yamt
858 1.1.2.2 yamt if (dlc->rd_rxcred == 0) {
859 1.1.2.2 yamt DPRINTF("Credit limit reached, UIH discarded\n");
860 1.1.2.2 yamt goto discard;
861 1.1.2.2 yamt }
862 1.1.2.2 yamt
863 1.1.2.2 yamt if (len > dlc->rd_rxsize) {
864 1.1.2.2 yamt DPRINTF("UIH frame exceeds rxsize, discarded\n");
865 1.1.2.2 yamt goto discard;
866 1.1.2.2 yamt }
867 1.1.2.2 yamt
868 1.1.2.2 yamt dlc->rd_rxcred--;
869 1.1.2.2 yamt dlc->rd_rxsize -= len;
870 1.1.2.2 yamt }
871 1.1.2.2 yamt
872 1.1.2.2 yamt (*dlc->rd_proto->input)(dlc->rd_upper, m);
873 1.1.2.2 yamt return;
874 1.1.2.2 yamt
875 1.1.2.2 yamt discard:
876 1.1.2.2 yamt m_freem(m);
877 1.1.2.2 yamt }
878 1.1.2.2 yamt
879 1.1.2.2 yamt /*
880 1.1.2.2 yamt * Receive Multiplexer Control Command
881 1.1.2.2 yamt */
882 1.1.2.2 yamt static void
883 1.1.2.2 yamt rfcomm_session_recv_mcc(struct rfcomm_session *rs, struct mbuf *m)
884 1.1.2.2 yamt {
885 1.1.2.2 yamt int type, cr, len;
886 1.1.2.2 yamt uint8_t b;
887 1.1.2.2 yamt
888 1.1.2.2 yamt /*
889 1.1.2.2 yamt * Extract MCC header.
890 1.1.2.2 yamt *
891 1.1.2.2 yamt * Fields are variable length using extension bit = 1 to signify the
892 1.1.2.2 yamt * last octet in the sequence.
893 1.1.2.2 yamt *
894 1.1.2.2 yamt * Only single octet types are defined in TS 07.10/RFCOMM spec
895 1.1.2.2 yamt *
896 1.1.2.2 yamt * Length can realistically only use 15 bits (max RFCOMM MTU)
897 1.1.2.2 yamt */
898 1.1.2.2 yamt if (m->m_pkthdr.len < sizeof(b)) {
899 1.1.2.2 yamt DPRINTF("Short MCC header, discarded\n");
900 1.1.2.2 yamt goto release;
901 1.1.2.2 yamt }
902 1.1.2.2 yamt
903 1.1.2.2 yamt m_copydata(m, 0, sizeof(b), &b);
904 1.1.2.2 yamt m_adj(m, sizeof(b));
905 1.1.2.2 yamt
906 1.1.2.2 yamt if (RFCOMM_EA(b) == 0) { /* verify no extensions */
907 1.1.2.2 yamt DPRINTF("MCC type EA = 1, discarded\n");
908 1.1.2.2 yamt goto release;
909 1.1.2.2 yamt }
910 1.1.2.2 yamt
911 1.1.2.2 yamt type = RFCOMM_MCC_TYPE(b);
912 1.1.2.2 yamt cr = RFCOMM_CR(b);
913 1.1.2.2 yamt
914 1.1.2.2 yamt len = 0;
915 1.1.2.2 yamt do {
916 1.1.2.2 yamt if (m->m_pkthdr.len < sizeof(b)) {
917 1.1.2.2 yamt DPRINTF("Short MCC header, discarded\n");
918 1.1.2.2 yamt goto release;
919 1.1.2.2 yamt }
920 1.1.2.2 yamt
921 1.1.2.2 yamt m_copydata(m, 0, sizeof(b), &b);
922 1.1.2.2 yamt m_adj(m, sizeof(b));
923 1.1.2.2 yamt
924 1.1.2.2 yamt len = (len << 7) | (b >> 1);
925 1.1.2.2 yamt len = min(len, RFCOMM_MTU_MAX);
926 1.1.2.2 yamt } while (RFCOMM_EA(b) == 0);
927 1.1.2.2 yamt
928 1.1.2.2 yamt if (len != m->m_pkthdr.len) {
929 1.1.2.2 yamt DPRINTF("Incorrect MCC length, discarded\n");
930 1.1.2.2 yamt goto release;
931 1.1.2.2 yamt }
932 1.1.2.2 yamt
933 1.1.2.2 yamt DPRINTFN(2, "MCC %s type %2.2x (%d bytes)\n",
934 1.1.2.2 yamt (cr ? "command" : "response"), type, len);
935 1.1.2.2 yamt
936 1.1.2.2 yamt /*
937 1.1.2.2 yamt * pass to command handler
938 1.1.2.2 yamt */
939 1.1.2.2 yamt switch(type) {
940 1.1.2.2 yamt case RFCOMM_MCC_TEST: /* Test */
941 1.1.2.2 yamt rfcomm_session_recv_mcc_test(rs, cr, m);
942 1.1.2.2 yamt break;
943 1.1.2.2 yamt
944 1.1.2.2 yamt case RFCOMM_MCC_FCON: /* Flow Control On */
945 1.1.2.2 yamt rfcomm_session_recv_mcc_fcon(rs, cr);
946 1.1.2.2 yamt break;
947 1.1.2.2 yamt
948 1.1.2.2 yamt case RFCOMM_MCC_FCOFF: /* Flow Control Off */
949 1.1.2.2 yamt rfcomm_session_recv_mcc_fcoff(rs, cr);
950 1.1.2.2 yamt break;
951 1.1.2.2 yamt
952 1.1.2.2 yamt case RFCOMM_MCC_MSC: /* Modem Status Command */
953 1.1.2.2 yamt rfcomm_session_recv_mcc_msc(rs, cr, m);
954 1.1.2.2 yamt break;
955 1.1.2.2 yamt
956 1.1.2.2 yamt case RFCOMM_MCC_RPN: /* Remote Port Negotiation */
957 1.1.2.2 yamt rfcomm_session_recv_mcc_rpn(rs, cr, m);
958 1.1.2.2 yamt break;
959 1.1.2.2 yamt
960 1.1.2.2 yamt case RFCOMM_MCC_RLS: /* Remote Line Status */
961 1.1.2.2 yamt rfcomm_session_recv_mcc_rls(rs, cr, m);
962 1.1.2.2 yamt break;
963 1.1.2.2 yamt
964 1.1.2.2 yamt case RFCOMM_MCC_PN: /* Parameter Negotiation */
965 1.1.2.2 yamt rfcomm_session_recv_mcc_pn(rs, cr, m);
966 1.1.2.2 yamt break;
967 1.1.2.2 yamt
968 1.1.2.2 yamt case RFCOMM_MCC_NSC: /* Non Supported Command */
969 1.1.2.2 yamt rfcomm_session_recv_mcc_nsc(rs, cr, m);
970 1.1.2.2 yamt break;
971 1.1.2.2 yamt
972 1.1.2.2 yamt default:
973 1.1.2.2 yamt b = RFCOMM_MKMCC_TYPE(cr, type);
974 1.1.2.2 yamt rfcomm_session_send_mcc(rs, 0, RFCOMM_MCC_NSC, &b, sizeof(b));
975 1.1.2.2 yamt }
976 1.1.2.2 yamt
977 1.1.2.2 yamt release:
978 1.1.2.2 yamt m_freem(m);
979 1.1.2.2 yamt }
980 1.1.2.2 yamt
981 1.1.2.2 yamt /*
982 1.1.2.2 yamt * process TEST command/response
983 1.1.2.2 yamt */
984 1.1.2.2 yamt static void
985 1.1.2.2 yamt rfcomm_session_recv_mcc_test(struct rfcomm_session *rs, int cr, struct mbuf *m)
986 1.1.2.2 yamt {
987 1.1.2.2 yamt void *data;
988 1.1.2.2 yamt int len;
989 1.1.2.2 yamt
990 1.1.2.2 yamt if (cr == 0) /* ignore ack */
991 1.1.2.2 yamt return;
992 1.1.2.2 yamt
993 1.1.2.2 yamt /*
994 1.1.2.2 yamt * we must send all the data they included back as is
995 1.1.2.2 yamt */
996 1.1.2.2 yamt
997 1.1.2.2 yamt len = m->m_pkthdr.len;
998 1.1.2.2 yamt if (len > RFCOMM_MTU_MAX)
999 1.1.2.2 yamt return;
1000 1.1.2.2 yamt
1001 1.1.2.2 yamt data = malloc(len, M_BLUETOOTH, M_NOWAIT);
1002 1.1.2.2 yamt if (data == NULL)
1003 1.1.2.2 yamt return;
1004 1.1.2.2 yamt
1005 1.1.2.2 yamt m_copydata(m, 0, len, data);
1006 1.1.2.2 yamt rfcomm_session_send_mcc(rs, 0, RFCOMM_MCC_TEST, data, len);
1007 1.1.2.2 yamt free(data, M_BLUETOOTH);
1008 1.1.2.2 yamt }
1009 1.1.2.2 yamt
1010 1.1.2.2 yamt /*
1011 1.1.2.2 yamt * process Flow Control ON command/response
1012 1.1.2.2 yamt */
1013 1.1.2.2 yamt static void
1014 1.1.2.2 yamt rfcomm_session_recv_mcc_fcon(struct rfcomm_session *rs, int cr)
1015 1.1.2.2 yamt {
1016 1.1.2.2 yamt
1017 1.1.2.2 yamt if (cr == 0) /* ignore ack */
1018 1.1.2.2 yamt return;
1019 1.1.2.2 yamt
1020 1.1.2.2 yamt rs->rs_flags |= RFCOMM_SESSION_RFC;
1021 1.1.2.2 yamt rfcomm_session_send_mcc(rs, 0, RFCOMM_MCC_FCON, NULL, 0);
1022 1.1.2.2 yamt }
1023 1.1.2.2 yamt
1024 1.1.2.2 yamt /*
1025 1.1.2.2 yamt * process Flow Control OFF command/response
1026 1.1.2.2 yamt */
1027 1.1.2.2 yamt static void
1028 1.1.2.2 yamt rfcomm_session_recv_mcc_fcoff(struct rfcomm_session *rs, int cr)
1029 1.1.2.2 yamt {
1030 1.1.2.2 yamt
1031 1.1.2.2 yamt if (cr == 0) /* ignore ack */
1032 1.1.2.2 yamt return;
1033 1.1.2.2 yamt
1034 1.1.2.2 yamt rs->rs_flags &= ~RFCOMM_SESSION_RFC;
1035 1.1.2.2 yamt rfcomm_session_send_mcc(rs, 0, RFCOMM_MCC_FCOFF, NULL, 0);
1036 1.1.2.2 yamt }
1037 1.1.2.2 yamt
1038 1.1.2.2 yamt /*
1039 1.1.2.2 yamt * process Modem Status Command command/response
1040 1.1.2.2 yamt */
1041 1.1.2.2 yamt static void
1042 1.1.2.2 yamt rfcomm_session_recv_mcc_msc(struct rfcomm_session *rs, int cr, struct mbuf *m)
1043 1.1.2.2 yamt {
1044 1.1.2.2 yamt struct rfcomm_mcc_msc msc; /* (3 octets) */
1045 1.1.2.2 yamt struct rfcomm_dlc *dlc;
1046 1.1.2.2 yamt int len = 0;
1047 1.1.2.2 yamt
1048 1.1.2.2 yamt /* [ADDRESS] */
1049 1.1.2.2 yamt if (m->m_pkthdr.len < sizeof(msc.address))
1050 1.1.2.2 yamt return;
1051 1.1.2.2 yamt
1052 1.1.2.2 yamt m_copydata(m, 0, sizeof(msc.address), &msc.address);
1053 1.1.2.2 yamt m_adj(m, sizeof(msc.address));
1054 1.1.2.2 yamt len += sizeof(msc.address);
1055 1.1.2.2 yamt
1056 1.1.2.2 yamt dlc = rfcomm_dlc_lookup(rs, RFCOMM_DLCI(msc.address));
1057 1.1.2.2 yamt
1058 1.1.2.2 yamt if (cr == 0) { /* ignore acks */
1059 1.1.2.2 yamt if (dlc != NULL)
1060 1.1.2.2 yamt callout_stop(&dlc->rd_timeout);
1061 1.1.2.2 yamt
1062 1.1.2.2 yamt return;
1063 1.1.2.2 yamt }
1064 1.1.2.2 yamt
1065 1.1.2.2 yamt if (dlc == NULL) {
1066 1.1.2.2 yamt rfcomm_session_send_frame(rs, RFCOMM_FRAME_DM,
1067 1.1.2.2 yamt RFCOMM_DLCI(msc.address));
1068 1.1.2.2 yamt return;
1069 1.1.2.2 yamt }
1070 1.1.2.2 yamt
1071 1.1.2.2 yamt /* [SIGNALS] */
1072 1.1.2.2 yamt if (m->m_pkthdr.len < sizeof(msc.modem))
1073 1.1.2.2 yamt return;
1074 1.1.2.2 yamt
1075 1.1.2.2 yamt m_copydata(m, 0, sizeof(msc.modem), &msc.modem);
1076 1.1.2.2 yamt m_adj(m, sizeof(msc.modem));
1077 1.1.2.2 yamt len += sizeof(msc.modem);
1078 1.1.2.2 yamt
1079 1.1.2.2 yamt dlc->rd_rmodem = msc.modem;
1080 1.1.2.2 yamt // XXX how do we signal this upstream?
1081 1.1.2.2 yamt
1082 1.1.2.2 yamt if (RFCOMM_EA(msc.modem) == 0) {
1083 1.1.2.2 yamt if (m->m_pkthdr.len < sizeof(msc.brk))
1084 1.1.2.2 yamt return;
1085 1.1.2.2 yamt
1086 1.1.2.2 yamt m_copydata(m, 0, sizeof(msc.brk), &msc.brk);
1087 1.1.2.2 yamt m_adj(m, sizeof(msc.brk));
1088 1.1.2.2 yamt len += sizeof(msc.brk);
1089 1.1.2.2 yamt
1090 1.1.2.2 yamt // XXX how do we signal this upstream?
1091 1.1.2.2 yamt }
1092 1.1.2.2 yamt
1093 1.1.2.2 yamt rfcomm_session_send_mcc(rs, 0, RFCOMM_MCC_MSC, &msc, len);
1094 1.1.2.2 yamt }
1095 1.1.2.2 yamt
1096 1.1.2.2 yamt /*
1097 1.1.2.2 yamt * process Remote Port Negotiation command/response
1098 1.1.2.2 yamt */
1099 1.1.2.2 yamt static void
1100 1.1.2.2 yamt rfcomm_session_recv_mcc_rpn(struct rfcomm_session *rs, int cr, struct mbuf *m)
1101 1.1.2.2 yamt {
1102 1.1.2.2 yamt struct rfcomm_mcc_rpn rpn;
1103 1.1.2.2 yamt uint16_t mask;
1104 1.1.2.2 yamt
1105 1.1.2.2 yamt if (cr == 0) /* ignore ack */
1106 1.1.2.2 yamt return;
1107 1.1.2.2 yamt
1108 1.1.2.2 yamt /* default values */
1109 1.1.2.2 yamt rpn.bit_rate = RFCOMM_RPN_BR_9600;
1110 1.1.2.2 yamt rpn.line_settings = RFCOMM_RPN_8_N_1;
1111 1.1.2.2 yamt rpn.flow_control = RFCOMM_RPN_FLOW_NONE;
1112 1.1.2.2 yamt rpn.xon_char = RFCOMM_RPN_XON_CHAR;
1113 1.1.2.2 yamt rpn.xoff_char = RFCOMM_RPN_XOFF_CHAR;
1114 1.1.2.2 yamt
1115 1.1.2.2 yamt if (m->m_pkthdr.len == sizeof(rpn)) {
1116 1.1.2.2 yamt m_copydata(m, 0, sizeof(rpn), &rpn);
1117 1.1.2.2 yamt rpn.param_mask = RFCOMM_RPN_PM_ALL;
1118 1.1.2.2 yamt } else if (m->m_pkthdr.len == 1) {
1119 1.1.2.2 yamt m_copydata(m, 0, 1, &rpn);
1120 1.1.2.2 yamt rpn.param_mask = le16toh(rpn.param_mask);
1121 1.1.2.2 yamt } else {
1122 1.1.2.2 yamt DPRINTF("Bad RPN length (%d)\n", m->m_pkthdr.len);
1123 1.1.2.2 yamt return;
1124 1.1.2.2 yamt }
1125 1.1.2.2 yamt
1126 1.1.2.2 yamt mask = 0;
1127 1.1.2.2 yamt
1128 1.1.2.2 yamt if (rpn.param_mask & RFCOMM_RPN_PM_RATE)
1129 1.1.2.2 yamt mask |= RFCOMM_RPN_PM_RATE;
1130 1.1.2.2 yamt
1131 1.1.2.2 yamt if (rpn.param_mask & RFCOMM_RPN_PM_DATA
1132 1.1.2.2 yamt && RFCOMM_RPN_DATA_BITS(rpn.line_settings) == RFCOMM_RPN_DATA_8)
1133 1.1.2.2 yamt mask |= RFCOMM_RPN_PM_DATA;
1134 1.1.2.2 yamt
1135 1.1.2.2 yamt if (rpn.param_mask & RFCOMM_RPN_PM_STOP
1136 1.1.2.2 yamt && RFCOMM_RPN_STOP_BITS(rpn.line_settings) == RFCOMM_RPN_STOP_1)
1137 1.1.2.2 yamt mask |= RFCOMM_RPN_PM_STOP;
1138 1.1.2.2 yamt
1139 1.1.2.2 yamt if (rpn.param_mask & RFCOMM_RPN_PM_PARITY
1140 1.1.2.2 yamt && RFCOMM_RPN_PARITY(rpn.line_settings) == RFCOMM_RPN_PARITY_NONE)
1141 1.1.2.2 yamt mask |= RFCOMM_RPN_PM_PARITY;
1142 1.1.2.2 yamt
1143 1.1.2.2 yamt if (rpn.param_mask & RFCOMM_RPN_PM_XON
1144 1.1.2.2 yamt && rpn.xon_char == RFCOMM_RPN_XON_CHAR)
1145 1.1.2.2 yamt mask |= RFCOMM_RPN_PM_XON;
1146 1.1.2.2 yamt
1147 1.1.2.2 yamt if (rpn.param_mask & RFCOMM_RPN_PM_XOFF
1148 1.1.2.2 yamt && rpn.xoff_char == RFCOMM_RPN_XOFF_CHAR)
1149 1.1.2.2 yamt mask |= RFCOMM_RPN_PM_XOFF;
1150 1.1.2.2 yamt
1151 1.1.2.2 yamt if (rpn.param_mask & RFCOMM_RPN_PM_FLOW
1152 1.1.2.2 yamt && rpn.flow_control == RFCOMM_RPN_FLOW_NONE)
1153 1.1.2.2 yamt mask |= RFCOMM_RPN_PM_FLOW;
1154 1.1.2.2 yamt
1155 1.1.2.2 yamt rpn.param_mask = htole16(mask);
1156 1.1.2.2 yamt
1157 1.1.2.2 yamt rfcomm_session_send_mcc(rs, 0, RFCOMM_MCC_RPN, &rpn, sizeof(rpn));
1158 1.1.2.2 yamt }
1159 1.1.2.2 yamt
1160 1.1.2.2 yamt /*
1161 1.1.2.2 yamt * process Remote Line Status command/response
1162 1.1.2.2 yamt */
1163 1.1.2.2 yamt static void
1164 1.1.2.2 yamt rfcomm_session_recv_mcc_rls(struct rfcomm_session *rs, int cr, struct mbuf *m)
1165 1.1.2.2 yamt {
1166 1.1.2.2 yamt struct rfcomm_mcc_rls rls;
1167 1.1.2.2 yamt
1168 1.1.2.2 yamt if (cr == 0) /* ignore ack */
1169 1.1.2.2 yamt return;
1170 1.1.2.2 yamt
1171 1.1.2.2 yamt if (m->m_pkthdr.len != sizeof(rls)) {
1172 1.1.2.2 yamt DPRINTF("Bad RLS length %d\n", m->m_pkthdr.len);
1173 1.1.2.2 yamt return;
1174 1.1.2.2 yamt }
1175 1.1.2.2 yamt
1176 1.1.2.2 yamt m_copydata(m, 0, sizeof(rls), &rls);
1177 1.1.2.2 yamt
1178 1.1.2.2 yamt /*
1179 1.1.2.2 yamt * So far as I can tell, we just send back what
1180 1.1.2.2 yamt * they sent us. This signifies errors that seem
1181 1.1.2.2 yamt * irrelevent for RFCOMM over L2CAP.
1182 1.1.2.2 yamt */
1183 1.1.2.2 yamt rls.address |= 0x03; /* EA = 1, CR = 1 */
1184 1.1.2.2 yamt rls.status &= 0x0f; /* only 4 bits valid */
1185 1.1.2.2 yamt
1186 1.1.2.2 yamt rfcomm_session_send_mcc(rs, 0, RFCOMM_MCC_RLS, &rls, sizeof(rls));
1187 1.1.2.2 yamt }
1188 1.1.2.2 yamt
1189 1.1.2.2 yamt /*
1190 1.1.2.2 yamt * process Parameter Negotiation command/response
1191 1.1.2.2 yamt */
1192 1.1.2.2 yamt static void
1193 1.1.2.2 yamt rfcomm_session_recv_mcc_pn(struct rfcomm_session *rs, int cr, struct mbuf *m)
1194 1.1.2.2 yamt {
1195 1.1.2.2 yamt struct rfcomm_dlc *dlc;
1196 1.1.2.2 yamt struct rfcomm_mcc_pn pn;
1197 1.1.2.2 yamt int err;
1198 1.1.2.2 yamt
1199 1.1.2.2 yamt if (m->m_pkthdr.len != sizeof(pn)) {
1200 1.1.2.2 yamt DPRINTF("Bad PN length %d\n", m->m_pkthdr.len);
1201 1.1.2.2 yamt return;
1202 1.1.2.2 yamt }
1203 1.1.2.2 yamt
1204 1.1.2.2 yamt m_copydata(m, 0, sizeof(pn), &pn);
1205 1.1.2.2 yamt
1206 1.1.2.2 yamt pn.dlci &= 0x3f;
1207 1.1.2.2 yamt pn.mtu = le16toh(pn.mtu);
1208 1.1.2.2 yamt
1209 1.1.2.2 yamt dlc = rfcomm_dlc_lookup(rs, pn.dlci);
1210 1.1.2.2 yamt if (cr) { /* Command */
1211 1.1.2.2 yamt /*
1212 1.1.2.2 yamt * If there is no DLC present, this is a new
1213 1.1.2.2 yamt * connection so attempt to make one
1214 1.1.2.2 yamt */
1215 1.1.2.2 yamt if (dlc == NULL) {
1216 1.1.2.2 yamt dlc = rfcomm_dlc_newconn(rs, pn.dlci);
1217 1.1.2.2 yamt if (dlc == NULL)
1218 1.1.2.2 yamt return; /* (DM is sent) */
1219 1.1.2.2 yamt }
1220 1.1.2.2 yamt
1221 1.1.2.2 yamt /* accept any valid MTU, and offer it back */
1222 1.1.2.2 yamt pn.mtu = min(pn.mtu, RFCOMM_MTU_MAX);
1223 1.1.2.2 yamt pn.mtu = min(pn.mtu, rs->rs_mtu);
1224 1.1.2.2 yamt pn.mtu = max(pn.mtu, RFCOMM_MTU_MIN);
1225 1.1.2.2 yamt dlc->rd_mtu = pn.mtu;
1226 1.1.2.2 yamt pn.mtu = htole16(pn.mtu);
1227 1.1.2.2 yamt
1228 1.1.2.2 yamt /* credits are only set before DLC is open */
1229 1.1.2.2 yamt if (dlc->rd_state == RFCOMM_DLC_WAIT_CONNECT
1230 1.1.2.2 yamt && (pn.flow_control & 0xf0) == 0xf0) {
1231 1.1.2.2 yamt rs->rs_flags |= RFCOMM_SESSION_CFC;
1232 1.1.2.2 yamt dlc->rd_txcred = pn.credits & 0x07;
1233 1.1.2.2 yamt
1234 1.1.2.2 yamt dlc->rd_rxcred = (dlc->rd_rxsize / dlc->rd_mtu);
1235 1.1.2.2 yamt dlc->rd_rxcred = min(dlc->rd_rxcred,
1236 1.1.2.2 yamt RFCOMM_CREDITS_DEFAULT);
1237 1.1.2.2 yamt
1238 1.1.2.2 yamt pn.flow_control = 0xe0;
1239 1.1.2.2 yamt pn.credits = dlc->rd_rxcred;
1240 1.1.2.2 yamt } else {
1241 1.1.2.2 yamt pn.flow_control = 0x00;
1242 1.1.2.2 yamt pn.credits = 0x00;
1243 1.1.2.2 yamt }
1244 1.1.2.2 yamt
1245 1.1.2.2 yamt /* unused fields must be ignored and set to zero */
1246 1.1.2.2 yamt pn.ack_timer = 0;
1247 1.1.2.2 yamt pn.max_retrans = 0;
1248 1.1.2.2 yamt
1249 1.1.2.2 yamt /* send our response */
1250 1.1.2.2 yamt err = rfcomm_session_send_mcc(rs, 0,
1251 1.1.2.2 yamt RFCOMM_MCC_PN, &pn, sizeof(pn));
1252 1.1.2.2 yamt if (err)
1253 1.1.2.2 yamt goto close;
1254 1.1.2.2 yamt
1255 1.1.2.2 yamt } else { /* Response */
1256 1.1.2.2 yamt /* ignore responses with no matching DLC */
1257 1.1.2.2 yamt if (dlc == NULL)
1258 1.1.2.2 yamt return;
1259 1.1.2.2 yamt
1260 1.1.2.2 yamt callout_stop(&dlc->rd_timeout);
1261 1.1.2.2 yamt
1262 1.1.2.2 yamt if (pn.mtu > RFCOMM_MTU_MAX || pn.mtu > dlc->rd_mtu) {
1263 1.1.2.2 yamt dlc->rd_state = RFCOMM_DLC_WAIT_DISCONNECT;
1264 1.1.2.2 yamt err = rfcomm_session_send_frame(rs, RFCOMM_FRAME_DISC,
1265 1.1.2.2 yamt pn.dlci);
1266 1.1.2.2 yamt if (err)
1267 1.1.2.2 yamt goto close;
1268 1.1.2.2 yamt
1269 1.1.2.2 yamt callout_schedule(&dlc->rd_timeout,
1270 1.1.2.2 yamt rfcomm_ack_timeout * hz);
1271 1.1.2.2 yamt return;
1272 1.1.2.2 yamt }
1273 1.1.2.2 yamt dlc->rd_mtu = pn.mtu;
1274 1.1.2.2 yamt
1275 1.1.2.2 yamt /* initial credits can only be set before DLC is open */
1276 1.1.2.2 yamt if (dlc->rd_state == RFCOMM_DLC_WAIT_CONNECT
1277 1.1.2.2 yamt && (pn.flow_control & 0xf0) == 0xe0) {
1278 1.1.2.2 yamt rs->rs_flags |= RFCOMM_SESSION_CFC;
1279 1.1.2.2 yamt dlc->rd_txcred = (pn.credits & 0x07);
1280 1.1.2.2 yamt }
1281 1.1.2.2 yamt
1282 1.1.2.2 yamt /* Ok, lets go with it */
1283 1.1.2.2 yamt err = rfcomm_session_send_frame(rs, RFCOMM_FRAME_SABM, pn.dlci);
1284 1.1.2.2 yamt if (err)
1285 1.1.2.2 yamt goto close;
1286 1.1.2.2 yamt
1287 1.1.2.2 yamt callout_schedule(&dlc->rd_timeout, rfcomm_ack_timeout * hz);
1288 1.1.2.2 yamt }
1289 1.1.2.2 yamt return;
1290 1.1.2.2 yamt
1291 1.1.2.2 yamt close:
1292 1.1.2.2 yamt rfcomm_dlc_close(dlc, err);
1293 1.1.2.2 yamt }
1294 1.1.2.2 yamt
1295 1.1.2.2 yamt /*
1296 1.1.2.2 yamt * process Non Supported Command command/response
1297 1.1.2.2 yamt */
1298 1.1.2.2 yamt static void
1299 1.1.2.2 yamt rfcomm_session_recv_mcc_nsc(struct rfcomm_session *rs, int cr, struct mbuf *m)
1300 1.1.2.2 yamt {
1301 1.1.2.2 yamt struct rfcomm_dlc *dlc;
1302 1.1.2.2 yamt
1303 1.1.2.2 yamt /*
1304 1.1.2.2 yamt * Since we did nothing that is not mandatory,
1305 1.1.2.2 yamt * we just abort the whole session..
1306 1.1.2.2 yamt */
1307 1.1.2.2 yamt LIST_FOREACH(dlc, &rs->rs_dlcs, rd_next)
1308 1.1.2.2 yamt rfcomm_dlc_close(dlc, ECONNABORTED);
1309 1.1.2.2 yamt
1310 1.1.2.2 yamt rfcomm_session_free(rs);
1311 1.1.2.2 yamt }
1312 1.1.2.2 yamt
1313 1.1.2.2 yamt /***********************************************************************
1314 1.1.2.2 yamt *
1315 1.1.2.2 yamt * RFCOMM Session outward frame/uih/mcc building
1316 1.1.2.2 yamt */
1317 1.1.2.2 yamt
1318 1.1.2.2 yamt /*
1319 1.1.2.2 yamt * SABM/DISC/DM/UA frames are all minimal and mostly identical.
1320 1.1.2.2 yamt */
1321 1.1.2.2 yamt int
1322 1.1.2.2 yamt rfcomm_session_send_frame(struct rfcomm_session *rs, int type, int dlci)
1323 1.1.2.2 yamt {
1324 1.1.2.2 yamt struct rfcomm_cmd_hdr *hdr;
1325 1.1.2.2 yamt struct rfcomm_credit *credit;
1326 1.1.2.2 yamt struct mbuf *m;
1327 1.1.2.2 yamt uint8_t fcs, cr;
1328 1.1.2.2 yamt
1329 1.1.2.2 yamt credit = pool_get(&rfcomm_credit_pool, PR_NOWAIT);
1330 1.1.2.2 yamt if (credit == NULL)
1331 1.1.2.2 yamt return ENOMEM;
1332 1.1.2.2 yamt
1333 1.1.2.2 yamt m = m_gethdr(M_DONTWAIT, MT_DATA);
1334 1.1.2.2 yamt if (m == NULL) {
1335 1.1.2.2 yamt pool_put(&rfcomm_credit_pool, credit);
1336 1.1.2.2 yamt return ENOMEM;
1337 1.1.2.2 yamt }
1338 1.1.2.2 yamt
1339 1.1.2.2 yamt /*
1340 1.1.2.2 yamt * The CR (command/response) bit identifies the frame either as a
1341 1.1.2.2 yamt * commmand or a response and is used along with the DLCI to form
1342 1.1.2.2 yamt * the address. Commands contain the non-initiator address, whereas
1343 1.1.2.2 yamt * responses contain the initiator address, so the CR value is
1344 1.1.2.2 yamt * also dependent on the session direction.
1345 1.1.2.2 yamt */
1346 1.1.2.2 yamt if (type == RFCOMM_FRAME_UA || type == RFCOMM_FRAME_DM)
1347 1.1.2.2 yamt cr = IS_INITIATOR(rs) ? 0 : 1;
1348 1.1.2.2 yamt else
1349 1.1.2.2 yamt cr = IS_INITIATOR(rs) ? 1 : 0;
1350 1.1.2.2 yamt
1351 1.1.2.2 yamt hdr = mtod(m, struct rfcomm_cmd_hdr *);
1352 1.1.2.2 yamt hdr->address = RFCOMM_MKADDRESS(cr, dlci);
1353 1.1.2.2 yamt hdr->control = RFCOMM_MKCONTROL(type, 1); /* PF = 1 */
1354 1.1.2.2 yamt hdr->length = (0x00 << 1) | 0x01; /* len = 0x00, EA = 1 */
1355 1.1.2.2 yamt
1356 1.1.2.2 yamt fcs = 0xff;
1357 1.1.2.2 yamt fcs = FCS(fcs, hdr->address);
1358 1.1.2.2 yamt fcs = FCS(fcs, hdr->control);
1359 1.1.2.2 yamt fcs = FCS(fcs, hdr->length);
1360 1.1.2.2 yamt fcs = 0xff - fcs; /* ones complement */
1361 1.1.2.2 yamt hdr->fcs = fcs;
1362 1.1.2.2 yamt
1363 1.1.2.2 yamt m->m_pkthdr.len = m->m_len = sizeof(struct rfcomm_cmd_hdr);
1364 1.1.2.2 yamt
1365 1.1.2.2 yamt /* empty credit note */
1366 1.1.2.2 yamt credit->rc_dlc = NULL;
1367 1.1.2.2 yamt credit->rc_len = m->m_pkthdr.len;
1368 1.1.2.2 yamt SIMPLEQ_INSERT_TAIL(&rs->rs_credits, credit, rc_next);
1369 1.1.2.2 yamt
1370 1.1.2.2 yamt DPRINTFN(5, "dlci %d type %2.2x (%d bytes, fcs=%#2.2x)\n",
1371 1.1.2.2 yamt dlci, type, m->m_pkthdr.len, fcs);
1372 1.1.2.2 yamt
1373 1.1.2.2 yamt return l2cap_send(rs->rs_l2cap, m);
1374 1.1.2.2 yamt }
1375 1.1.2.2 yamt
1376 1.1.2.2 yamt /*
1377 1.1.2.2 yamt * rfcomm_session_send_uih(rfcomm_session, rfcomm_dlc, credits, mbuf)
1378 1.1.2.2 yamt *
1379 1.1.2.2 yamt * UIH frame is per DLC data or Multiplexer Control Commands
1380 1.1.2.2 yamt * when no DLC is given. Data mbuf is optional (just credits
1381 1.1.2.2 yamt * will be sent in that case)
1382 1.1.2.2 yamt */
1383 1.1.2.2 yamt int
1384 1.1.2.2 yamt rfcomm_session_send_uih(struct rfcomm_session *rs, struct rfcomm_dlc *dlc,
1385 1.1.2.2 yamt int credits, struct mbuf *m)
1386 1.1.2.2 yamt {
1387 1.1.2.2 yamt struct rfcomm_credit *credit;
1388 1.1.2.2 yamt struct mbuf *m0 = NULL;
1389 1.1.2.2 yamt int err, len;
1390 1.1.2.2 yamt uint8_t fcs, *hdr;
1391 1.1.2.2 yamt
1392 1.1.2.2 yamt KASSERT(rs != NULL);
1393 1.1.2.2 yamt
1394 1.1.2.2 yamt len = (m == NULL) ? 0 : m->m_pkthdr.len;
1395 1.1.2.2 yamt KASSERT(!(credits == 0 && len == 0));
1396 1.1.2.2 yamt
1397 1.1.2.2 yamt /*
1398 1.1.2.2 yamt * Make a credit note for the completion notification
1399 1.1.2.2 yamt */
1400 1.1.2.2 yamt credit = pool_get(&rfcomm_credit_pool, PR_NOWAIT);
1401 1.1.2.2 yamt if (credit == NULL)
1402 1.1.2.2 yamt goto nomem;
1403 1.1.2.2 yamt
1404 1.1.2.2 yamt credit->rc_len = len;
1405 1.1.2.2 yamt credit->rc_dlc = dlc;
1406 1.1.2.2 yamt
1407 1.1.2.2 yamt /*
1408 1.1.2.2 yamt * Wrap UIH frame information around payload.
1409 1.1.2.2 yamt *
1410 1.1.2.2 yamt * [ADDRESS] [CONTROL] [LENGTH] [CREDITS] [...] [FCS]
1411 1.1.2.2 yamt *
1412 1.1.2.2 yamt * Address is one octet.
1413 1.1.2.2 yamt * Control is one octet.
1414 1.1.2.2 yamt * Length is one or two octets.
1415 1.1.2.2 yamt * Credits may be one octet.
1416 1.1.2.2 yamt *
1417 1.1.2.2 yamt * FCS is one octet and calculated on address and
1418 1.1.2.2 yamt * control octets only.
1419 1.1.2.2 yamt *
1420 1.1.2.2 yamt * If there are credits to be sent, we will set the PF
1421 1.1.2.2 yamt * flag and include them in the frame.
1422 1.1.2.2 yamt */
1423 1.1.2.2 yamt m0 = m_gethdr(M_DONTWAIT, MT_DATA);
1424 1.1.2.2 yamt if (m0 == NULL)
1425 1.1.2.2 yamt goto nomem;
1426 1.1.2.2 yamt
1427 1.1.2.2 yamt MH_ALIGN(m0, 5); /* (max 5 header octets) */
1428 1.1.2.2 yamt hdr = mtod(m0, uint8_t *);
1429 1.1.2.2 yamt
1430 1.1.2.2 yamt /* CR bit is set according to the initiator of the session */
1431 1.1.2.2 yamt *hdr = RFCOMM_MKADDRESS((IS_INITIATOR(rs) ? 1 : 0),
1432 1.1.2.2 yamt (dlc ? dlc->rd_dlci : 0));
1433 1.1.2.2 yamt fcs = FCS(0xff, *hdr);
1434 1.1.2.2 yamt hdr++;
1435 1.1.2.2 yamt
1436 1.1.2.2 yamt /* PF bit is set if credits are being sent */
1437 1.1.2.2 yamt *hdr = RFCOMM_MKCONTROL(RFCOMM_FRAME_UIH, (credits > 0 ? 1 : 0));
1438 1.1.2.2 yamt fcs = FCS(fcs, *hdr);
1439 1.1.2.2 yamt hdr++;
1440 1.1.2.2 yamt
1441 1.1.2.2 yamt if (len < (1 << 7)) {
1442 1.1.2.2 yamt *hdr++ = ((len << 1) & 0xfe) | 0x01; /* 7 bits, EA = 1 */
1443 1.1.2.2 yamt } else {
1444 1.1.2.2 yamt *hdr++ = ((len << 1) & 0xfe); /* 7 bits, EA = 0 */
1445 1.1.2.2 yamt *hdr++ = ((len >> 7) & 0xff); /* 8 bits, no EA */
1446 1.1.2.2 yamt }
1447 1.1.2.2 yamt
1448 1.1.2.2 yamt if (credits > 0)
1449 1.1.2.2 yamt *hdr++ = (uint8_t)credits;
1450 1.1.2.2 yamt
1451 1.1.2.2 yamt m0->m_len = hdr - mtod(m0, uint8_t *);
1452 1.1.2.2 yamt
1453 1.1.2.2 yamt /* Append payload */
1454 1.1.2.2 yamt m0->m_next = m;
1455 1.1.2.2 yamt m = NULL;
1456 1.1.2.2 yamt
1457 1.1.2.2 yamt m0->m_pkthdr.len = m0->m_len + len;
1458 1.1.2.2 yamt
1459 1.1.2.2 yamt /* Append FCS */
1460 1.1.2.2 yamt fcs = 0xff - fcs; /* ones complement */
1461 1.1.2.2 yamt len = m0->m_pkthdr.len;
1462 1.1.2.2 yamt m_copyback(m0, len, sizeof(fcs), &fcs);
1463 1.1.2.2 yamt if (m0->m_pkthdr.len != len + sizeof(fcs))
1464 1.1.2.2 yamt goto nomem;
1465 1.1.2.2 yamt
1466 1.1.2.2 yamt DPRINTFN(10, "dlci %d, pktlen %d (%d data, %d credits), fcs=%#2.2x\n",
1467 1.1.2.2 yamt dlc ? dlc->rd_dlci : 0, m0->m_pkthdr.len, credit->rc_len,
1468 1.1.2.2 yamt credits, fcs);
1469 1.1.2.2 yamt
1470 1.1.2.2 yamt /*
1471 1.1.2.2 yamt * UIH frame ready to go..
1472 1.1.2.2 yamt */
1473 1.1.2.2 yamt err = l2cap_send(rs->rs_l2cap, m0);
1474 1.1.2.2 yamt if (err)
1475 1.1.2.2 yamt goto fail;
1476 1.1.2.2 yamt
1477 1.1.2.2 yamt SIMPLEQ_INSERT_TAIL(&rs->rs_credits, credit, rc_next);
1478 1.1.2.2 yamt return 0;
1479 1.1.2.2 yamt
1480 1.1.2.2 yamt nomem:
1481 1.1.2.2 yamt err = ENOMEM;
1482 1.1.2.2 yamt
1483 1.1.2.2 yamt if (m0 != NULL)
1484 1.1.2.2 yamt m_freem(m0);
1485 1.1.2.2 yamt
1486 1.1.2.2 yamt if (m != NULL)
1487 1.1.2.2 yamt m_freem(m);
1488 1.1.2.2 yamt
1489 1.1.2.2 yamt fail:
1490 1.1.2.2 yamt if (credit != NULL)
1491 1.1.2.2 yamt pool_put(&rfcomm_credit_pool, credit);
1492 1.1.2.2 yamt
1493 1.1.2.2 yamt return err;
1494 1.1.2.2 yamt }
1495 1.1.2.2 yamt
1496 1.1.2.2 yamt /*
1497 1.1.2.2 yamt * send Multiplexer Control Command (or Response) on session
1498 1.1.2.2 yamt */
1499 1.1.2.2 yamt int
1500 1.1.2.2 yamt rfcomm_session_send_mcc(struct rfcomm_session *rs, int cr,
1501 1.1.2.2 yamt uint8_t type, void *data, int len)
1502 1.1.2.2 yamt {
1503 1.1.2.2 yamt struct mbuf *m;
1504 1.1.2.2 yamt uint8_t *hdr;
1505 1.1.2.2 yamt int hlen;
1506 1.1.2.2 yamt
1507 1.1.2.2 yamt m = m_gethdr(M_DONTWAIT, MT_DATA);
1508 1.1.2.2 yamt if (m == NULL)
1509 1.1.2.2 yamt return ENOMEM;
1510 1.1.2.2 yamt
1511 1.1.2.2 yamt hdr = mtod(m, uint8_t *);
1512 1.1.2.2 yamt
1513 1.1.2.2 yamt /*
1514 1.1.2.2 yamt * Technically the type field can extend past one octet, but none
1515 1.1.2.2 yamt * currently defined will do that.
1516 1.1.2.2 yamt */
1517 1.1.2.2 yamt *hdr++ = RFCOMM_MKMCC_TYPE(cr, type);
1518 1.1.2.2 yamt
1519 1.1.2.2 yamt /*
1520 1.1.2.2 yamt * In the frame, the max length size is 2 octets (15 bits) whereas
1521 1.1.2.2 yamt * no max length size is specified for MCC commands. We must allow
1522 1.1.2.2 yamt * for 3 octets since for MCC frames we use 7 bits + EA in each.
1523 1.1.2.2 yamt *
1524 1.1.2.2 yamt * Only test data can possibly be that big.
1525 1.1.2.2 yamt *
1526 1.1.2.2 yamt * XXX Should we check this against the MTU?
1527 1.1.2.2 yamt */
1528 1.1.2.2 yamt if (len < (1 << 7)) {
1529 1.1.2.2 yamt *hdr++ = ((len << 1) & 0xfe) | 0x01; /* 7 bits, EA = 1 */
1530 1.1.2.2 yamt } else if (len < (1 << 14)) {
1531 1.1.2.2 yamt *hdr++ = ((len << 1) & 0xfe); /* 7 bits, EA = 0 */
1532 1.1.2.2 yamt *hdr++ = ((len >> 6) & 0xfe) | 0x01; /* 7 bits, EA = 1 */
1533 1.1.2.2 yamt } else if (len < (1 << 15)) {
1534 1.1.2.2 yamt *hdr++ = ((len << 1) & 0xfe); /* 7 bits, EA = 0 */
1535 1.1.2.2 yamt *hdr++ = ((len >> 6) & 0xfe); /* 7 bits, EA = 0 */
1536 1.1.2.2 yamt *hdr++ = ((len >> 13) & 0x02) | 0x01; /* 1 bit, EA = 1 */
1537 1.1.2.2 yamt } else {
1538 1.1.2.2 yamt DPRINTF("incredible length! (%d)\n", len);
1539 1.1.2.2 yamt m_freem(m);
1540 1.1.2.2 yamt return EMSGSIZE;
1541 1.1.2.2 yamt }
1542 1.1.2.2 yamt
1543 1.1.2.2 yamt /*
1544 1.1.2.2 yamt * add command data (to same mbuf if possible)
1545 1.1.2.2 yamt */
1546 1.1.2.2 yamt hlen = hdr - mtod(m, uint8_t *);
1547 1.1.2.2 yamt
1548 1.1.2.2 yamt if (len > 0) {
1549 1.1.2.2 yamt m->m_pkthdr.len = m->m_len = MHLEN;
1550 1.1.2.2 yamt m_copyback(m, hlen, len, data);
1551 1.1.2.2 yamt if (m->m_pkthdr.len != max(MHLEN, hlen + len)) {
1552 1.1.2.2 yamt m_freem(m);
1553 1.1.2.2 yamt return ENOMEM;
1554 1.1.2.2 yamt }
1555 1.1.2.2 yamt }
1556 1.1.2.2 yamt
1557 1.1.2.2 yamt m->m_pkthdr.len = hlen + len;
1558 1.1.2.2 yamt m->m_len = min(MHLEN, m->m_pkthdr.len);
1559 1.1.2.2 yamt
1560 1.1.2.2 yamt DPRINTFN(5, "%s type %2.2x len %d\n",
1561 1.1.2.2 yamt (cr ? "command" : "response"), type, m->m_pkthdr.len);
1562 1.1.2.2 yamt
1563 1.1.2.2 yamt return rfcomm_session_send_uih(rs, NULL, 0, m);
1564 1.1.2.2 yamt }
1565