1 /* $NetBSD: rfcomm_upper.c,v 1.12 2009/11/22 19:09:16 mbalmer Exp $ */
4 * Copyright (c) 2006 Itronix Inc.
7 * Written by Iain Hibbert for Itronix Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of Itronix Inc. may not be used to endorse
18 * or promote products derived from this software without specific
19 * prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: rfcomm_upper.c,v 1.12 2009/11/22 19:09:16 mbalmer Exp $");
37 #include <sys/param.h>
38 #include <sys/kernel.h>
41 #include <sys/socketvar.h>
42 #include <sys/systm.h>
44 #include <netbt/bluetooth.h>
45 #include <netbt/hci.h>
46 #include <netbt/l2cap.h>
47 #include <netbt/rfcomm.h>
49 /****************************************************************************
51 * RFCOMM DLC - Upper Protocol API
53 * Currently the only 'Port Emulation Entity' is the RFCOMM socket code
54 * but it is should be possible to provide a pseudo-device for a direct
59 * rfcomm_attach(handle, proto, upper)
61 * attach a new RFCOMM DLC to handle, populate with reasonable defaults
64 rfcomm_attach(struct rfcomm_dlc
**handle
,
65 const struct btproto
*proto
, void *upper
)
67 struct rfcomm_dlc
*dlc
;
69 KASSERT(handle
!= NULL
);
70 KASSERT(proto
!= NULL
);
71 KASSERT(upper
!= NULL
);
73 dlc
= malloc(sizeof(struct rfcomm_dlc
), M_BLUETOOTH
, M_NOWAIT
| M_ZERO
);
77 dlc
->rd_state
= RFCOMM_DLC_CLOSED
;
78 dlc
->rd_mtu
= rfcomm_mtu_default
;
80 dlc
->rd_proto
= proto
;
81 dlc
->rd_upper
= upper
;
83 dlc
->rd_laddr
.bt_len
= sizeof(struct sockaddr_bt
);
84 dlc
->rd_laddr
.bt_family
= AF_BLUETOOTH
;
85 dlc
->rd_laddr
.bt_psm
= L2CAP_PSM_RFCOMM
;
87 dlc
->rd_raddr
.bt_len
= sizeof(struct sockaddr_bt
);
88 dlc
->rd_raddr
.bt_family
= AF_BLUETOOTH
;
89 dlc
->rd_raddr
.bt_psm
= L2CAP_PSM_RFCOMM
;
91 dlc
->rd_lmodem
= RFCOMM_MSC_RTC
| RFCOMM_MSC_RTR
| RFCOMM_MSC_DV
;
93 callout_init(&dlc
->rd_timeout
, 0);
94 callout_setfunc(&dlc
->rd_timeout
, rfcomm_dlc_timeout
, dlc
);
101 * rfcomm_bind(dlc, sockaddr)
103 * bind DLC to local address
106 rfcomm_bind(struct rfcomm_dlc
*dlc
, struct sockaddr_bt
*addr
)
109 if (dlc
->rd_state
!= RFCOMM_DLC_CLOSED
)
112 memcpy(&dlc
->rd_laddr
, addr
, sizeof(struct sockaddr_bt
));
117 * rfcomm_sockaddr(dlc, sockaddr)
119 * return local address
122 rfcomm_sockaddr(struct rfcomm_dlc
*dlc
, struct sockaddr_bt
*addr
)
125 memcpy(addr
, &dlc
->rd_laddr
, sizeof(struct sockaddr_bt
));
130 * rfcomm_connect(dlc, sockaddr)
132 * Initiate connection of RFCOMM DLC to remote address.
135 rfcomm_connect(struct rfcomm_dlc
*dlc
, struct sockaddr_bt
*dest
)
137 struct rfcomm_session
*rs
;
140 if (dlc
->rd_state
!= RFCOMM_DLC_CLOSED
)
143 memcpy(&dlc
->rd_raddr
, dest
, sizeof(struct sockaddr_bt
));
145 if (dlc
->rd_raddr
.bt_channel
< RFCOMM_CHANNEL_MIN
146 || dlc
->rd_raddr
.bt_channel
> RFCOMM_CHANNEL_MAX
147 || bdaddr_any(&dlc
->rd_raddr
.bt_bdaddr
))
150 if (dlc
->rd_raddr
.bt_psm
== L2CAP_PSM_ANY
)
151 dlc
->rd_raddr
.bt_psm
= L2CAP_PSM_RFCOMM
;
152 else if (dlc
->rd_raddr
.bt_psm
!= L2CAP_PSM_RFCOMM
153 && (dlc
->rd_raddr
.bt_psm
< 0x1001
154 || L2CAP_PSM_INVALID(dlc
->rd_raddr
.bt_psm
)))
158 * We are allowed only one RFCOMM session between any 2 Bluetooth
159 * devices, so see if there is a session already otherwise create
160 * one and set it connecting.
162 rs
= rfcomm_session_lookup(&dlc
->rd_laddr
, &dlc
->rd_raddr
);
164 rs
= rfcomm_session_alloc(&rfcomm_session_active
,
169 rs
->rs_flags
|= RFCOMM_SESSION_INITIATOR
;
170 rs
->rs_state
= RFCOMM_SESSION_WAIT_CONNECT
;
172 err
= l2cap_connect(rs
->rs_l2cap
, &dlc
->rd_raddr
);
174 rfcomm_session_free(rs
);
179 * This session will start up automatically when its
180 * L2CAP channel is connected.
185 dlc
->rd_dlci
= RFCOMM_MKDLCI(IS_INITIATOR(rs
) ? 0:1, dest
->bt_channel
);
186 if (rfcomm_dlc_lookup(rs
, dlc
->rd_dlci
))
189 l2cap_sockaddr(rs
->rs_l2cap
, &dlc
->rd_laddr
);
192 * attach the DLC to the session and start it off
194 dlc
->rd_session
= rs
;
195 dlc
->rd_state
= RFCOMM_DLC_WAIT_SESSION
;
196 LIST_INSERT_HEAD(&rs
->rs_dlcs
, dlc
, rd_next
);
198 if (rs
->rs_state
== RFCOMM_SESSION_OPEN
)
199 err
= rfcomm_dlc_connect(dlc
);
205 * rfcomm_peeraddr(dlc, sockaddr)
207 * return remote address
210 rfcomm_peeraddr(struct rfcomm_dlc
*dlc
, struct sockaddr_bt
*addr
)
213 memcpy(addr
, &dlc
->rd_raddr
, sizeof(struct sockaddr_bt
));
218 * rfcomm_disconnect(dlc, linger)
220 * disconnect RFCOMM DLC
223 rfcomm_disconnect(struct rfcomm_dlc
*dlc
, int linger
)
225 struct rfcomm_session
*rs
= dlc
->rd_session
;
228 KASSERT(dlc
!= NULL
);
230 switch (dlc
->rd_state
) {
231 case RFCOMM_DLC_CLOSED
:
232 case RFCOMM_DLC_LISTEN
:
235 case RFCOMM_DLC_WAIT_SEND_UA
:
236 err
= rfcomm_session_send_frame(rs
,
237 RFCOMM_FRAME_DM
, dlc
->rd_dlci
);
240 case RFCOMM_DLC_WAIT_SESSION
:
241 case RFCOMM_DLC_WAIT_CONNECT
:
242 case RFCOMM_DLC_WAIT_SEND_SABM
:
243 rfcomm_dlc_close(dlc
, 0);
246 case RFCOMM_DLC_OPEN
:
247 if (dlc
->rd_txbuf
!= NULL
&& linger
!= 0) {
248 dlc
->rd_flags
|= RFCOMM_DLC_SHUTDOWN
;
252 /* else fall through */
253 case RFCOMM_DLC_WAIT_RECV_UA
:
254 dlc
->rd_state
= RFCOMM_DLC_WAIT_DISCONNECT
;
255 err
= rfcomm_session_send_frame(rs
, RFCOMM_FRAME_DISC
,
257 callout_schedule(&dlc
->rd_timeout
, rfcomm_ack_timeout
* hz
);
260 case RFCOMM_DLC_WAIT_DISCONNECT
:
265 UNKNOWN(dlc
->rd_state
);
273 * rfcomm_detach(handle)
275 * detach RFCOMM DLC from handle
278 rfcomm_detach(struct rfcomm_dlc
**handle
)
280 struct rfcomm_dlc
*dlc
= *handle
;
282 if (dlc
->rd_state
!= RFCOMM_DLC_CLOSED
)
283 rfcomm_dlc_close(dlc
, 0);
285 if (dlc
->rd_txbuf
!= NULL
) {
286 m_freem(dlc
->rd_txbuf
);
287 dlc
->rd_txbuf
= NULL
;
290 dlc
->rd_upper
= NULL
;
294 * If callout is invoking we can't free the DLC so
295 * mark it and let the callout release it.
297 if (callout_invoking(&dlc
->rd_timeout
))
298 dlc
->rd_flags
|= RFCOMM_DLC_DETACH
;
300 callout_destroy(&dlc
->rd_timeout
);
301 free(dlc
, M_BLUETOOTH
);
310 * This DLC is a listener. We look for an existing listening session
311 * with a matching address to attach to or else create a new one on
312 * the listeners list. If the ANY channel is given, allocate the first
313 * available for the session.
316 rfcomm_listen(struct rfcomm_dlc
*dlc
)
318 struct rfcomm_session
*rs
;
319 struct rfcomm_dlc
*used
;
320 struct sockaddr_bt addr
;
323 if (dlc
->rd_state
!= RFCOMM_DLC_CLOSED
)
326 if (dlc
->rd_laddr
.bt_channel
!= RFCOMM_CHANNEL_ANY
327 && (dlc
->rd_laddr
.bt_channel
< RFCOMM_CHANNEL_MIN
328 || dlc
->rd_laddr
.bt_channel
> RFCOMM_CHANNEL_MAX
))
329 return EADDRNOTAVAIL
;
331 if (dlc
->rd_laddr
.bt_psm
== L2CAP_PSM_ANY
)
332 dlc
->rd_laddr
.bt_psm
= L2CAP_PSM_RFCOMM
;
333 else if (dlc
->rd_laddr
.bt_psm
!= L2CAP_PSM_RFCOMM
334 && (dlc
->rd_laddr
.bt_psm
< 0x1001
335 || L2CAP_PSM_INVALID(dlc
->rd_laddr
.bt_psm
)))
336 return EADDRNOTAVAIL
;
338 LIST_FOREACH(rs
, &rfcomm_session_listen
, rs_next
) {
339 l2cap_sockaddr(rs
->rs_l2cap
, &addr
);
341 if (addr
.bt_psm
!= dlc
->rd_laddr
.bt_psm
)
344 if (bdaddr_same(&dlc
->rd_laddr
.bt_bdaddr
, &addr
.bt_bdaddr
))
349 rs
= rfcomm_session_alloc(&rfcomm_session_listen
,
354 rs
->rs_state
= RFCOMM_SESSION_LISTEN
;
356 err
= l2cap_listen(rs
->rs_l2cap
);
358 rfcomm_session_free(rs
);
363 if (dlc
->rd_laddr
.bt_channel
== RFCOMM_CHANNEL_ANY
) {
364 channel
= RFCOMM_CHANNEL_MIN
;
365 used
= LIST_FIRST(&rs
->rs_dlcs
);
367 while (used
!= NULL
) {
368 if (used
->rd_laddr
.bt_channel
== channel
) {
369 if (channel
++ == RFCOMM_CHANNEL_MAX
)
370 return EADDRNOTAVAIL
;
372 used
= LIST_FIRST(&rs
->rs_dlcs
);
374 used
= LIST_NEXT(used
, rd_next
);
378 dlc
->rd_laddr
.bt_channel
= channel
;
381 dlc
->rd_session
= rs
;
382 dlc
->rd_state
= RFCOMM_DLC_LISTEN
;
383 LIST_INSERT_HEAD(&rs
->rs_dlcs
, dlc
, rd_next
);
389 * rfcomm_send(dlc, mbuf)
391 * Output data on DLC. This is streamed data, so we add it
392 * to our buffer and start the DLC, which will assemble
393 * packets and send them if it can.
396 rfcomm_send(struct rfcomm_dlc
*dlc
, struct mbuf
*m
)
399 if (dlc
->rd_txbuf
!= NULL
) {
400 dlc
->rd_txbuf
->m_pkthdr
.len
+= m
->m_pkthdr
.len
;
401 m_cat(dlc
->rd_txbuf
, m
);
406 if (dlc
->rd_state
== RFCOMM_DLC_OPEN
)
407 rfcomm_dlc_start(dlc
);
413 * rfcomm_rcvd(dlc, space)
415 * Indicate space now available in receive buffer
417 * This should be used to give an initial value of the receive buffer
418 * size when the DLC is attached and anytime data is cleared from the
422 rfcomm_rcvd(struct rfcomm_dlc
*dlc
, size_t space
)
425 KASSERT(dlc
!= NULL
);
427 dlc
->rd_rxsize
= space
;
430 * if we are using credit based flow control, we may
431 * want to send some credits..
433 if (dlc
->rd_state
== RFCOMM_DLC_OPEN
434 && (dlc
->rd_session
->rs_flags
& RFCOMM_SESSION_CFC
))
435 rfcomm_dlc_start(dlc
);
441 * rfcomm_setopt(dlc, sopt)
446 rfcomm_setopt(struct rfcomm_dlc
*dlc
, const struct sockopt
*sopt
)
451 switch (sopt
->sopt_name
) {
453 err
= sockopt_get(sopt
, &mtu
, sizeof(mtu
));
457 if (mtu
< RFCOMM_MTU_MIN
|| mtu
> RFCOMM_MTU_MAX
)
459 else if (dlc
->rd_state
== RFCOMM_DLC_CLOSED
)
467 err
= sockopt_getint(sopt
, &mode
);
471 mode
&= (RFCOMM_LM_SECURE
| RFCOMM_LM_ENCRYPT
| RFCOMM_LM_AUTH
);
473 if (mode
& RFCOMM_LM_SECURE
)
474 mode
|= RFCOMM_LM_ENCRYPT
;
476 if (mode
& RFCOMM_LM_ENCRYPT
)
477 mode
|= RFCOMM_LM_AUTH
;
481 if (dlc
->rd_state
== RFCOMM_DLC_OPEN
)
482 err
= rfcomm_dlc_setmode(dlc
);
494 * rfcomm_getopt(dlc, sopt)
499 rfcomm_getopt(struct rfcomm_dlc
*dlc
, struct sockopt
*sopt
)
501 struct rfcomm_fc_info fc
;
503 switch (sopt
->sopt_name
) {
505 return sockopt_set(sopt
, &dlc
->rd_mtu
, sizeof(uint16_t));
507 case SO_RFCOMM_FC_INFO
:
508 memset(&fc
, 0, sizeof(fc
));
509 fc
.lmodem
= dlc
->rd_lmodem
;
510 fc
.rmodem
= dlc
->rd_rmodem
;
511 fc
.tx_cred
= max(dlc
->rd_txcred
, 0xff);
512 fc
.rx_cred
= max(dlc
->rd_rxcred
, 0xff);
514 && (dlc
->rd_session
->rs_flags
& RFCOMM_SESSION_CFC
))
517 return sockopt_set(sopt
, &fc
, sizeof(fc
));
520 return sockopt_setint(sopt
, dlc
->rd_mode
);