Sync Bluetooth stack with NetBSD.
[dragonfly.git] / sys / netbt / rfcomm_socket.c
blobff119c0581756339d9100df529ad883326b3e6f4
1 /* $DragonFly: src/sys/netbt/rfcomm_socket.c,v 1.2 2008/03/18 13:41:42 hasso 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 $ */
5 /*-
6 * Copyright (c) 2006 Itronix Inc.
7 * All rights reserved.
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
13 * are met:
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
38 #define PRUREQUESTS
39 #define PRCOREQUESTS
40 #endif
42 #include <sys/param.h>
43 #include <sys/domain.h>
44 #include <sys/kernel.h>
45 #include <sys/mbuf.h>
46 #include <sys/proc.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 = {
72 rfcomm_connecting,
73 rfcomm_connected,
74 rfcomm_disconnected,
75 rfcomm_newconn,
76 rfcomm_complete,
77 rfcomm_linkmode,
78 rfcomm_input,
81 /* sysctl variables */
82 int rfcomm_sendspace = 4096;
83 int rfcomm_recvspace = 4096;
86 * rfcomm_ctloutput(request, socket, level, optname, opt)
89 int
90 rfcomm_ctloutput(struct socket *so, struct sockopt *sopt)
92 struct rfcomm_dlc *pcb = (struct rfcomm_dlc *) so->so_pcb;
93 struct mbuf *m;
94 int err = 0;
96 #ifdef notyet /* XXX */
97 DPRINTFN(2, "%s\n", prcorequests[sopt->sopt_dir]);
98 #endif
100 if (pcb == NULL)
101 return EINVAL;
103 if (sopt->sopt_level != BTPROTO_RFCOMM)
104 return ENOPROTOOPT;
106 switch(sopt->sopt_dir) {
107 case PRCO_GETOPT:
108 m = m_get(M_WAITOK, MT_DATA);
109 crit_enter();
110 m->m_len = rfcomm_getopt(pcb, sopt->sopt_name, mtod(m, void *));
111 crit_exit();
112 if (m->m_len == 0) {
113 m_freem(m);
114 m = NULL;
115 err = ENOPROTOOPT;
117 err = sooptcopyout(sopt, mtod(m, void *), m->m_len);
118 break;
120 case PRCO_SETOPT:
121 err = rfcomm_setopt2(pcb, sopt->sopt_name, so, sopt);
123 break;
125 default:
126 err = ENOPROTOOPT;
127 break;
130 return err;
133 /**********************************************************************
135 * RFCOMM callbacks
138 static void
139 rfcomm_connecting(void *arg)
141 /* struct socket *so = arg; */
143 KKASSERT(arg != NULL);
144 DPRINTF("Connecting\n");
147 static void
148 rfcomm_connected(void *arg)
150 struct socket *so = arg;
152 KKASSERT(so != NULL);
153 DPRINTF("Connected\n");
154 soisconnected(so);
157 static void
158 rfcomm_disconnected(void *arg, int err)
160 struct socket *so = arg;
162 KKASSERT(so != NULL);
163 DPRINTF("Disconnected\n");
165 so->so_error = err;
166 soisdisconnected(so);
169 static void *
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);
177 if (so == NULL)
178 return NULL;
180 soisconnecting(so);
182 return so->so_pcb;
186 * rfcomm_complete(rfcomm_dlc, length)
188 * length bytes are sent and may be removed from socket buffer
190 static void
191 rfcomm_complete(void *arg, int length)
193 struct socket *so = arg;
195 sbdrop(&so->so_snd.sb, length);
196 sowwakeup(so);
200 * rfcomm_linkmode(rfcomm_dlc, new)
202 * link mode change notification.
204 static void
205 rfcomm_linkmode(void *arg, int new)
207 struct socket *so = arg;
208 int mode;
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)
225 static void
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);
235 m_freem(m);
236 return;
239 DPRINTFN(10, "received %d bytes\n", m->m_pkthdr.len);
241 sbappendstream(&so->so_rcv.sb, m);
242 sorwakeup(so);
246 * Implementation of usrreqs.
248 static int
249 rfcomm_sdetach(struct socket *so)
251 return rfcomm_detach((struct rfcomm_dlc **)&so->so_pcb);
254 static int
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);
264 static int
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);
273 static int
274 rfcomm_scontrol (struct socket *so, u_long cmd, caddr_t data,
275 struct ifnet *ifp, struct thread *td)
277 return EPASSTHROUGH;
280 static int
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;
286 int err=0;
287 if (pcb != NULL)
288 return EINVAL;
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);
295 if (err)
296 return err;
298 err = rfcomm_attach((struct rfcomm_dlc **)&so->so_pcb,
299 &rfcomm_proto, so);
300 if (err)
301 return err;
303 err = rfcomm_rcvd(so->so_pcb, sbspace(&so->so_rcv));
304 if (err) {
305 rfcomm_detach((struct rfcomm_dlc **)&so->so_pcb);
306 return err;
309 return 0;
312 static int
313 rfcomm_sbind (struct socket *so, struct sockaddr *nam,
314 struct thread *td)
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))
323 return EINVAL;
325 if (sa->bt_family != AF_BLUETOOTH)
326 return EAFNOSUPPORT;
328 return rfcomm_bind(pcb, sa);
331 static int
332 rfcomm_sconnect (struct socket *so, struct sockaddr *nam,
333 struct thread *td)
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))
342 return EINVAL;
344 if (sa->bt_family != AF_BLUETOOTH)
345 return EAFNOSUPPORT;
347 soisconnecting(so);
348 return rfcomm_connect(pcb, sa);
351 static int
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;
356 int e;
358 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);
364 return (e);
367 static int
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;
372 int e;
374 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);
380 return (e);
383 static int
384 rfcomm_sshutdown (struct socket *so)
386 socantsendmore(so);
387 return 0;
390 static int
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;
395 struct mbuf *m0;
397 KKASSERT(m != NULL);
399 if (control) /* no use for that */
400 m_freem(control);
402 m0 = m_copym(m, 0, M_COPYALL, MB_DONTWAIT);
403 if (m0 == NULL)
404 return ENOMEM;
406 sbappendstream(&so->so_snd.sb, m);
408 return rfcomm_send(pcb, m0);
411 static int
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;
416 int e;
418 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);
424 return (e);
427 static int
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);
434 static int
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,
461 .pru_sopoll = sopoll