1 /* $DragonFly: src/sys/netbt/rfcomm_upper.c,v 1.3 2008/06/20 20:52:29 aggelos Exp $ */
2 /* $OpenBSD: src/sys/netbt/rfcomm_upper.c,v 1.4 2008/02/24 21:34:48 uwe Exp $ */
3 /* $NetBSD: rfcomm_upper.c,v 1.10 2007/11/20 20:25:57 plunky Exp $ */
6 * Copyright (c) 2006 Itronix Inc.
9 * Written by Iain Hibbert for Itronix Inc.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of Itronix Inc. may not be used to endorse
20 * or promote products derived from this software without specific
21 * prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
36 #include <sys/param.h>
37 #include <sys/kernel.h>
40 #include <sys/systm.h>
41 #include <sys/socketvar.h>
43 #include <netbt/bluetooth.h>
44 #include <netbt/hci.h>
45 #include <netbt/l2cap.h>
46 #include <netbt/rfcomm.h>
48 /****************************************************************************
50 * RFCOMM DLC - Upper Protocol API
52 * Currently the only 'Port Emulation Entity' is the RFCOMM socket code
53 * but it is should be possible to provide a pseudo-device for a direct
58 * rfcomm_attach(handle, proto, upper)
60 * attach a new RFCOMM DLC to handle, populate with reasonable defaults
63 rfcomm_attach(struct rfcomm_dlc
**handle
,
64 const struct btproto
*proto
, void *upper
)
66 struct rfcomm_dlc
*dlc
;
68 KKASSERT(handle
!= NULL
);
69 KKASSERT(proto
!= NULL
);
70 KKASSERT(upper
!= NULL
);
72 dlc
= kmalloc(sizeof(*dlc
), M_BLUETOOTH
, M_NOWAIT
| M_ZERO
);
76 dlc
->rd_state
= RFCOMM_DLC_CLOSED
;
77 dlc
->rd_mtu
= rfcomm_mtu_default
;
79 dlc
->rd_proto
= proto
;
80 dlc
->rd_upper
= upper
;
82 dlc
->rd_laddr
.bt_len
= sizeof(struct sockaddr_bt
);
83 dlc
->rd_laddr
.bt_family
= AF_BLUETOOTH
;
84 dlc
->rd_laddr
.bt_psm
= L2CAP_PSM_RFCOMM
;
86 dlc
->rd_raddr
.bt_len
= sizeof(struct sockaddr_bt
);
87 dlc
->rd_raddr
.bt_family
= AF_BLUETOOTH
;
88 dlc
->rd_raddr
.bt_psm
= L2CAP_PSM_RFCOMM
;
90 dlc
->rd_lmodem
= RFCOMM_MSC_RTC
| RFCOMM_MSC_RTR
| RFCOMM_MSC_DV
;
92 callout_init(&dlc
->rd_timeout
);
99 * rfcomm_bind(dlc, sockaddr)
101 * bind DLC to local address
104 rfcomm_bind(struct rfcomm_dlc
*dlc
, struct sockaddr_bt
*addr
)
107 memcpy(&dlc
->rd_laddr
, addr
, sizeof(struct sockaddr_bt
));
112 * rfcomm_sockaddr(dlc, sockaddr)
114 * return local address
117 rfcomm_sockaddr(struct rfcomm_dlc
*dlc
, struct sockaddr_bt
*addr
)
120 memcpy(addr
, &dlc
->rd_laddr
, sizeof(struct sockaddr_bt
));
125 * rfcomm_connect(dlc, sockaddr)
127 * Initiate connection of RFCOMM DLC to remote address.
130 rfcomm_connect(struct rfcomm_dlc
*dlc
, struct sockaddr_bt
*dest
)
132 struct rfcomm_session
*rs
;
135 if (dlc
->rd_state
!= RFCOMM_DLC_CLOSED
)
138 memcpy(&dlc
->rd_raddr
, dest
, sizeof(struct sockaddr_bt
));
140 if (dlc
->rd_raddr
.bt_channel
< RFCOMM_CHANNEL_MIN
141 || dlc
->rd_raddr
.bt_channel
> RFCOMM_CHANNEL_MAX
142 || bdaddr_any(&dlc
->rd_raddr
.bt_bdaddr
))
145 if (dlc
->rd_raddr
.bt_psm
== L2CAP_PSM_ANY
)
146 dlc
->rd_raddr
.bt_psm
= L2CAP_PSM_RFCOMM
;
147 else if (dlc
->rd_raddr
.bt_psm
!= L2CAP_PSM_RFCOMM
148 && (dlc
->rd_raddr
.bt_psm
< 0x1001
149 || L2CAP_PSM_INVALID(dlc
->rd_raddr
.bt_psm
)))
153 * We are allowed only one RFCOMM session between any 2 Bluetooth
154 * devices, so see if there is a session already otherwise create
155 * one and set it connecting.
157 rs
= rfcomm_session_lookup(&dlc
->rd_laddr
, &dlc
->rd_raddr
);
159 rs
= rfcomm_session_alloc(&rfcomm_session_active
,
164 rs
->rs_flags
|= RFCOMM_SESSION_INITIATOR
;
165 rs
->rs_state
= RFCOMM_SESSION_WAIT_CONNECT
;
167 err
= l2cap_connect(rs
->rs_l2cap
, &dlc
->rd_raddr
);
169 rfcomm_session_free(rs
);
174 * This session will start up automatically when its
175 * L2CAP channel is connected.
180 dlc
->rd_dlci
= RFCOMM_MKDLCI(IS_INITIATOR(rs
) ? 0:1, dest
->bt_channel
);
181 if (rfcomm_dlc_lookup(rs
, dlc
->rd_dlci
))
184 l2cap_sockaddr(rs
->rs_l2cap
, &dlc
->rd_laddr
);
187 * attach the DLC to the session and start it off
189 dlc
->rd_session
= rs
;
190 dlc
->rd_state
= RFCOMM_DLC_WAIT_SESSION
;
191 LIST_INSERT_HEAD(&rs
->rs_dlcs
, dlc
, rd_next
);
193 if (rs
->rs_state
== RFCOMM_SESSION_OPEN
)
194 err
= rfcomm_dlc_connect(dlc
);
200 * rfcomm_peeraddr(dlc, sockaddr)
202 * return remote address
205 rfcomm_peeraddr(struct rfcomm_dlc
*dlc
, struct sockaddr_bt
*addr
)
208 memcpy(addr
, &dlc
->rd_raddr
, sizeof(struct sockaddr_bt
));
213 * rfcomm_disconnect(dlc, linger)
215 * disconnect RFCOMM DLC
218 rfcomm_disconnect(struct rfcomm_dlc
*dlc
, int linger
)
220 struct rfcomm_session
*rs
= dlc
->rd_session
;
223 KKASSERT(dlc
!= NULL
);
225 switch (dlc
->rd_state
) {
226 case RFCOMM_DLC_CLOSED
:
227 case RFCOMM_DLC_LISTEN
:
230 case RFCOMM_DLC_WAIT_SEND_UA
:
231 err
= rfcomm_session_send_frame(rs
,
232 RFCOMM_FRAME_DM
, dlc
->rd_dlci
);
235 case RFCOMM_DLC_WAIT_SESSION
:
236 case RFCOMM_DLC_WAIT_CONNECT
:
237 case RFCOMM_DLC_WAIT_SEND_SABM
:
238 rfcomm_dlc_close(dlc
, 0);
241 case RFCOMM_DLC_OPEN
:
242 if (dlc
->rd_txbuf
!= NULL
&& linger
!= 0) {
243 dlc
->rd_flags
|= RFCOMM_DLC_SHUTDOWN
;
247 /* else fall through */
248 case RFCOMM_DLC_WAIT_RECV_UA
:
249 dlc
->rd_state
= RFCOMM_DLC_WAIT_DISCONNECT
;
250 err
= rfcomm_session_send_frame(rs
, RFCOMM_FRAME_DISC
,
252 callout_reset(&dlc
->rd_timeout
, rfcomm_ack_timeout
* hz
,
253 rfcomm_dlc_timeout
, dlc
);
256 case RFCOMM_DLC_WAIT_DISCONNECT
:
261 UNKNOWN(dlc
->rd_state
);
269 * rfcomm_detach(handle)
271 * detach RFCOMM DLC from handle
274 rfcomm_detach(struct rfcomm_dlc
**handle
)
276 struct rfcomm_dlc
*dlc
= *handle
;
278 if (dlc
->rd_state
!= RFCOMM_DLC_CLOSED
)
279 rfcomm_dlc_close(dlc
, 0);
281 if (dlc
->rd_txbuf
!= NULL
) {
282 m_freem(dlc
->rd_txbuf
);
283 dlc
->rd_txbuf
= NULL
;
286 dlc
->rd_upper
= NULL
;
290 * If callout is invoking we can't free the DLC so
291 * mark it and let the callout release it.
293 if (callout_active(&dlc
->rd_timeout
))
294 dlc
->rd_flags
|= RFCOMM_DLC_DETACH
;
296 kfree(dlc
, M_BLUETOOTH
);
304 * This DLC is a listener. We look for an existing listening session
305 * with a matching address to attach to or else create a new one on
306 * the listeners list. If the ANY channel is given, allocate the first
307 * available for the session.
310 rfcomm_listen(struct rfcomm_dlc
*dlc
)
312 struct rfcomm_session
*rs
;
313 struct rfcomm_dlc
*used
;
314 struct sockaddr_bt addr
;
317 if (dlc
->rd_state
!= RFCOMM_DLC_CLOSED
)
320 if (dlc
->rd_laddr
.bt_channel
!= RFCOMM_CHANNEL_ANY
321 && (dlc
->rd_laddr
.bt_channel
< RFCOMM_CHANNEL_MIN
322 || dlc
->rd_laddr
.bt_channel
> RFCOMM_CHANNEL_MAX
))
323 return EADDRNOTAVAIL
;
325 if (dlc
->rd_laddr
.bt_psm
== L2CAP_PSM_ANY
)
326 dlc
->rd_laddr
.bt_psm
= L2CAP_PSM_RFCOMM
;
327 else if (dlc
->rd_laddr
.bt_psm
!= L2CAP_PSM_RFCOMM
328 && (dlc
->rd_laddr
.bt_psm
< 0x1001
329 || L2CAP_PSM_INVALID(dlc
->rd_laddr
.bt_psm
)))
330 return EADDRNOTAVAIL
;
332 LIST_FOREACH(rs
, &rfcomm_session_listen
, rs_next
) {
333 l2cap_sockaddr(rs
->rs_l2cap
, &addr
);
335 if (addr
.bt_psm
!= dlc
->rd_laddr
.bt_psm
)
338 if (bdaddr_same(&dlc
->rd_laddr
.bt_bdaddr
, &addr
.bt_bdaddr
))
343 rs
= rfcomm_session_alloc(&rfcomm_session_listen
,
348 rs
->rs_state
= RFCOMM_SESSION_LISTEN
;
350 err
= l2cap_listen(rs
->rs_l2cap
);
352 rfcomm_session_free(rs
);
357 if (dlc
->rd_laddr
.bt_channel
== RFCOMM_CHANNEL_ANY
) {
358 channel
= RFCOMM_CHANNEL_MIN
;
359 used
= LIST_FIRST(&rs
->rs_dlcs
);
361 while (used
!= NULL
) {
362 if (used
->rd_laddr
.bt_channel
== channel
) {
363 if (channel
++ == RFCOMM_CHANNEL_MAX
)
364 return EADDRNOTAVAIL
;
366 used
= LIST_FIRST(&rs
->rs_dlcs
);
368 used
= LIST_NEXT(used
, rd_next
);
372 dlc
->rd_laddr
.bt_channel
= channel
;
375 dlc
->rd_session
= rs
;
376 dlc
->rd_state
= RFCOMM_DLC_LISTEN
;
377 LIST_INSERT_HEAD(&rs
->rs_dlcs
, dlc
, rd_next
);
383 * rfcomm_send(dlc, mbuf)
385 * Output data on DLC. This is streamed data, so we add it
386 * to our buffer and start the DLC, which will assemble
387 * packets and send them if it can.
390 rfcomm_send(struct rfcomm_dlc
*dlc
, struct mbuf
*m
)
393 if (dlc
->rd_txbuf
!= NULL
) {
394 dlc
->rd_txbuf
->m_pkthdr
.len
+= m
->m_pkthdr
.len
;
395 m_cat(dlc
->rd_txbuf
, m
);
400 if (dlc
->rd_state
== RFCOMM_DLC_OPEN
)
401 rfcomm_dlc_start(dlc
);
407 * rfcomm_rcvd(dlc, space)
409 * Indicate space now available in receive buffer
411 * This should be used to give an initial value of the receive buffer
412 * size when the DLC is attached and anytime data is cleared from the
416 rfcomm_rcvd(struct rfcomm_dlc
*dlc
, size_t space
)
419 KKASSERT(dlc
!= NULL
);
421 dlc
->rd_rxsize
= space
;
424 * if we are using credit based flow control, we may
425 * want to send some credits..
427 if (dlc
->rd_state
== RFCOMM_DLC_OPEN
428 && (dlc
->rd_session
->rs_flags
& RFCOMM_SESSION_CFC
))
429 rfcomm_dlc_start(dlc
);
435 * rfcomm_setopt(dlc, option, addr)
440 rfcomm_setopt(struct rfcomm_dlc
*dlc
, int opt
, void *addr
)
447 mtu
= *(uint16_t *)addr
;
448 if (mtu
< RFCOMM_MTU_MIN
|| mtu
> RFCOMM_MTU_MAX
)
450 else if (dlc
->rd_state
== RFCOMM_DLC_CLOSED
)
459 mode
&= (RFCOMM_LM_SECURE
| RFCOMM_LM_ENCRYPT
| RFCOMM_LM_AUTH
);
461 if (mode
& RFCOMM_LM_SECURE
)
462 mode
|= RFCOMM_LM_ENCRYPT
;
464 if (mode
& RFCOMM_LM_ENCRYPT
)
465 mode
|= RFCOMM_LM_AUTH
;
469 if (dlc
->rd_state
== RFCOMM_DLC_OPEN
)
470 err
= rfcomm_dlc_setmode(dlc
);
483 rfcomm_setopt2(struct rfcomm_dlc
*dlc
, int opt
, struct socket
*so
,
484 struct sockopt
*sopt
)
491 err
= soopt_to_kbuf(sopt
, &mtu
, sizeof(uint16_t),
495 if (mtu
< RFCOMM_MTU_MIN
|| mtu
> RFCOMM_MTU_MAX
)
497 else if (dlc
->rd_state
== RFCOMM_DLC_CLOSED
)
505 err
= soopt_to_kbuf(sopt
, &mode
, sizeof(int), sizeof(int));
508 mode
&= (RFCOMM_LM_SECURE
| RFCOMM_LM_ENCRYPT
| RFCOMM_LM_AUTH
);
510 if (mode
& RFCOMM_LM_SECURE
)
511 mode
|= RFCOMM_LM_ENCRYPT
;
513 if (mode
& RFCOMM_LM_ENCRYPT
)
514 mode
|= RFCOMM_LM_AUTH
;
518 if (dlc
->rd_state
== RFCOMM_DLC_OPEN
)
519 err
= rfcomm_dlc_setmode(dlc
);
531 * rfcomm_getopt(dlc, option, addr)
536 rfcomm_getopt(struct rfcomm_dlc
*dlc
, int opt
, void *addr
)
538 struct rfcomm_fc_info
*fc
;
542 *(uint16_t *)addr
= dlc
->rd_mtu
;
543 return sizeof(uint16_t);
545 case SO_RFCOMM_FC_INFO
:
547 memset(fc
, 0, sizeof(*fc
));
548 fc
->lmodem
= dlc
->rd_lmodem
;
549 fc
->rmodem
= dlc
->rd_rmodem
;
550 fc
->tx_cred
= max(dlc
->rd_txcred
, 0xff);
551 fc
->rx_cred
= max(dlc
->rd_rxcred
, 0xff);
553 && (dlc
->rd_session
->rs_flags
& RFCOMM_SESSION_CFC
))
559 *(int *)addr
= dlc
->rd_mode
;