1 /* $DragonFly: src/sys/netbt/rfcomm_socket.c,v 1.3 2008/06/20 20:52:29 aggelos Exp $ */
2 /* $OpenBSD: src/sys/netbt/rfcomm_socket.c,v 1.2 2008/02/24 21:34:48 uwe Exp $ */
3 /* $NetBSD: rfcomm_socket.c,v 1.8 2007/10/15 18:04:34 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 /* load symbolic names */
37 #ifdef BLUETOOTH_DEBUG
42 #include <sys/param.h>
43 #include <sys/domain.h>
44 #include <sys/kernel.h>
47 #include <sys/protosw.h>
48 #include <sys/socket.h>
49 #include <sys/socketvar.h>
50 #include <sys/systm.h>
51 #include <vm/vm_zone.h>
53 #include <netbt/bluetooth.h>
54 #include <netbt/hci.h> /* XXX for EPASSTHROUGH */
55 #include <netbt/rfcomm.h>
57 /****************************************************************************
59 * RFCOMM SOCK_STREAM Sockets - serial line emulation
63 static void rfcomm_connecting(void *);
64 static void rfcomm_connected(void *);
65 static void rfcomm_disconnected(void *, int);
66 static void *rfcomm_newconn(void *, struct sockaddr_bt
*, struct sockaddr_bt
*);
67 static void rfcomm_complete(void *, int);
68 static void rfcomm_linkmode(void *, int);
69 static void rfcomm_input(void *, struct mbuf
*);
71 static const struct btproto rfcomm_proto
= {
81 /* sysctl variables */
82 int rfcomm_sendspace
= 4096;
83 int rfcomm_recvspace
= 4096;
86 * rfcomm_ctloutput(request, socket, level, optname, opt)
90 rfcomm_ctloutput(struct socket
*so
, struct sockopt
*sopt
)
92 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
96 #ifdef notyet /* XXX */
97 DPRINTFN(2, "%s\n", prcorequests
[sopt
->sopt_dir
]);
103 if (sopt
->sopt_level
!= BTPROTO_RFCOMM
)
106 switch(sopt
->sopt_dir
) {
108 m
= m_get(M_WAITOK
, MT_DATA
);
110 m
->m_len
= rfcomm_getopt(pcb
, sopt
->sopt_name
, mtod(m
, void *));
117 soopt_from_kbuf(sopt
, mtod(m
, void *), m
->m_len
);
121 err
= rfcomm_setopt2(pcb
, sopt
->sopt_name
, so
, sopt
);
133 /**********************************************************************
139 rfcomm_connecting(void *arg
)
141 /* struct socket *so = arg; */
143 KKASSERT(arg
!= NULL
);
144 DPRINTF("Connecting\n");
148 rfcomm_connected(void *arg
)
150 struct socket
*so
= arg
;
152 KKASSERT(so
!= NULL
);
153 DPRINTF("Connected\n");
158 rfcomm_disconnected(void *arg
, int err
)
160 struct socket
*so
= arg
;
162 KKASSERT(so
!= NULL
);
163 DPRINTF("Disconnected\n");
166 soisdisconnected(so
);
170 rfcomm_newconn(void *arg
, struct sockaddr_bt
*laddr
,
171 struct sockaddr_bt
*raddr
)
173 struct socket
*so
= arg
;
175 DPRINTF("New Connection\n");
176 so
= sonewconn(so
, 0);
186 * rfcomm_complete(rfcomm_dlc, length)
188 * length bytes are sent and may be removed from socket buffer
191 rfcomm_complete(void *arg
, int length
)
193 struct socket
*so
= arg
;
195 sbdrop(&so
->so_snd
.sb
, length
);
200 * rfcomm_linkmode(rfcomm_dlc, new)
202 * link mode change notification.
205 rfcomm_linkmode(void *arg
, int new)
207 struct socket
*so
= arg
;
210 DPRINTF("auth %s, encrypt %s, secure %s\n",
211 (new & RFCOMM_LM_AUTH
? "on" : "off"),
212 (new & RFCOMM_LM_ENCRYPT
? "on" : "off"),
213 (new & RFCOMM_LM_SECURE
? "on" : "off"));
215 (void)rfcomm_getopt(so
->so_pcb
, SO_RFCOMM_LM
, &mode
);
216 if (((mode
& RFCOMM_LM_AUTH
) && !(new & RFCOMM_LM_AUTH
))
217 || ((mode
& RFCOMM_LM_ENCRYPT
) && !(new & RFCOMM_LM_ENCRYPT
))
218 || ((mode
& RFCOMM_LM_SECURE
) && !(new & RFCOMM_LM_SECURE
)))
219 rfcomm_disconnect(so
->so_pcb
, 0);
223 * rfcomm_input(rfcomm_dlc, mbuf)
226 rfcomm_input(void *arg
, struct mbuf
*m
)
228 struct socket
*so
= arg
;
230 KKASSERT(so
!= NULL
);
232 if (m
->m_pkthdr
.len
> sbspace(&so
->so_rcv
)) {
233 kprintf("%s: %d bytes dropped (socket buffer full)\n",
234 __func__
, m
->m_pkthdr
.len
);
239 DPRINTFN(10, "received %d bytes\n", m
->m_pkthdr
.len
);
241 sbappendstream(&so
->so_rcv
.sb
, m
);
246 * Implementation of usrreqs.
249 rfcomm_sdetach(struct socket
*so
)
251 return rfcomm_detach((struct rfcomm_dlc
**)&so
->so_pcb
);
255 rfcomm_sabort (struct socket
*so
)
257 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
259 rfcomm_disconnect(pcb
, 0);
260 soisdisconnected(so
);
261 return rfcomm_sdetach(so
);
265 rfcomm_sdisconnect (struct socket
*so
)
267 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
269 soisdisconnecting(so
);
270 return rfcomm_disconnect(pcb
, so
->so_linger
);
274 rfcomm_scontrol (struct socket
*so
, u_long cmd
, caddr_t data
,
275 struct ifnet
*ifp
, struct thread
*td
)
281 rfcomm_sattach (struct socket
*so
, int proto
,
282 struct pru_attach_info
*ai
)
284 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
291 * Since we have nothing to add, we attach the DLC
292 * structure directly to our PCB pointer.
294 err
= soreserve(so
, rfcomm_sendspace
, rfcomm_recvspace
, NULL
);
298 err
= rfcomm_attach((struct rfcomm_dlc
**)&so
->so_pcb
,
303 err
= rfcomm_rcvd(so
->so_pcb
, sbspace(&so
->so_rcv
));
305 rfcomm_detach((struct rfcomm_dlc
**)&so
->so_pcb
);
313 rfcomm_sbind (struct socket
*so
, struct sockaddr
*nam
,
316 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
317 struct sockaddr_bt
*sa
;
319 KKASSERT(nam
!= NULL
);
320 sa
= (struct sockaddr_bt
*)nam
;
322 if (sa
->bt_len
!= sizeof(struct sockaddr_bt
))
325 if (sa
->bt_family
!= AF_BLUETOOTH
)
328 return rfcomm_bind(pcb
, sa
);
332 rfcomm_sconnect (struct socket
*so
, struct sockaddr
*nam
,
335 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
336 struct sockaddr_bt
*sa
;
338 KKASSERT(nam
!= NULL
);
339 sa
= (struct sockaddr_bt
*)nam
;
341 if (sa
->bt_len
!= sizeof(struct sockaddr_bt
))
344 if (sa
->bt_family
!= AF_BLUETOOTH
)
348 return rfcomm_connect(pcb
, sa
);
352 rfcomm_speeraddr (struct socket
*so
, struct sockaddr
**nam
)
354 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
355 struct sockaddr_bt
*sa
, ssa
;
359 bzero(sa
, sizeof *sa
);
360 sa
->bt_len
= sizeof(struct sockaddr_bt
);
361 sa
->bt_family
= AF_BLUETOOTH
;
362 e
= rfcomm_peeraddr(pcb
, sa
);;
363 *nam
= dup_sockaddr((struct sockaddr
*)sa
);
368 rfcomm_ssockaddr (struct socket
*so
, struct sockaddr
**nam
)
370 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
371 struct sockaddr_bt
*sa
, ssa
;
375 bzero(sa
, sizeof *sa
);
376 sa
->bt_len
= sizeof(struct sockaddr_bt
);
377 sa
->bt_family
= AF_BLUETOOTH
;
378 e
= rfcomm_sockaddr(pcb
, sa
);;
379 *nam
= dup_sockaddr((struct sockaddr
*)sa
);
384 rfcomm_sshutdown (struct socket
*so
)
391 rfcomm_ssend (struct socket
*so
, int flags
, struct mbuf
*m
,
392 struct sockaddr
*addr
, struct mbuf
*control
, struct thread
*td
)
394 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
399 if (control
) /* no use for that */
402 m0
= m_copym(m
, 0, M_COPYALL
, MB_DONTWAIT
);
406 sbappendstream(&so
->so_snd
.sb
, m
);
408 return rfcomm_send(pcb
, m0
);
412 rfcomm_saccept(struct socket
*so
, struct sockaddr
**nam
)
414 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
415 struct sockaddr_bt
*sa
, ssa
;
419 bzero(sa
, sizeof *sa
);
420 sa
->bt_len
= sizeof(struct sockaddr_bt
);
421 sa
->bt_family
= AF_BLUETOOTH
;
422 e
= rfcomm_peeraddr(pcb
, sa
);;
423 *nam
= dup_sockaddr((struct sockaddr
*)sa
);
428 rfcomm_slisten(struct socket
*so
, struct thread
*td
)
430 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
431 return rfcomm_listen(pcb
);
435 rfcomm_srcvd(struct socket
*so
, int flags
)
437 struct rfcomm_dlc
*pcb
= (struct rfcomm_dlc
*) so
->so_pcb
;
438 return rfcomm_rcvd(pcb
, sbspace(&so
->so_rcv
));
441 struct pr_usrreqs rfcomm_usrreqs
= {
442 .pru_abort
= rfcomm_sabort
,
443 .pru_accept
= rfcomm_saccept
,
444 .pru_attach
= rfcomm_sattach
,
445 .pru_bind
= rfcomm_sbind
,
446 .pru_connect
= rfcomm_sconnect
,
447 .pru_connect2
= pru_connect2_notsupp
,
448 .pru_control
= rfcomm_scontrol
,
449 .pru_detach
= rfcomm_sdetach
,
450 .pru_disconnect
= rfcomm_sdisconnect
,
451 .pru_listen
= rfcomm_slisten
,
452 .pru_peeraddr
= rfcomm_speeraddr
,
453 .pru_rcvd
= rfcomm_srcvd
,
454 .pru_rcvoob
= pru_rcvoob_notsupp
,
455 .pru_send
= rfcomm_ssend
,
456 .pru_sense
= pru_sense_null
,
457 .pru_shutdown
= rfcomm_sshutdown
,
458 .pru_sockaddr
= rfcomm_ssockaddr
,
459 .pru_sosend
= sosend
,
460 .pru_soreceive
= soreceive
,