2 * Copyright (c) 2006 Itronix Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of Itronix Inc. may not be used to endorse
14 * or promote products derived from this software without specific
15 * prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
29 * $OpenBSD: sco_socket.c,v 1.1 2007/06/01 02:46:12 uwe Exp $
30 * $NetBSD: sco_socket.c,v 1.9 2007/04/21 06:15:23 plunky Exp $
33 /* load symbolic names */
34 #ifdef BLUETOOTH_DEBUG
39 #include <sys/param.h>
40 #include <sys/domain.h>
41 #include <sys/kernel.h>
44 #include <sys/protosw.h>
45 #include <sys/socket.h>
46 #include <sys/socketvar.h>
47 #include <sys/systm.h>
50 #include <sys/msgport2.h>
52 #include <netbt/bluetooth.h>
53 #include <netbt/hci.h>
54 #include <netbt/sco.h>
56 /*******************************************************************************
58 * SCO SOCK_SEQPACKET sockets - low latency audio data
61 static void sco_connecting(void *);
62 static void sco_connected(void *);
63 static void sco_disconnected(void *, int);
64 static void *sco_newconn(void *, struct sockaddr_bt
*, struct sockaddr_bt
*);
65 static void sco_complete(void *, int);
66 static void sco_linkmode(void *, int);
67 static void sco_input(void *, struct mbuf
*);
69 static const struct btproto sco_proto
= {
79 int sco_sendspace
= 4096;
80 int sco_recvspace
= 4096;
83 * get/set socket options
86 sco_ctloutput(netmsg_t msg
)
88 struct socket
*so
= msg
->ctloutput
.base
.nm_so
;
89 struct sockopt
*sopt
= msg
->ctloutput
.nm_sopt
;
90 struct sco_pcb
*pcb
= (struct sco_pcb
*)so
->so_pcb
;
94 #ifdef notyet /* XXX */
95 DPRINTFN(2, "req %s\n", prcorequests
[req
]);
103 if (sopt
->sopt_level
!= BTPROTO_SCO
) {
108 switch(sopt
->sopt_dir
) {
110 m
= m_get(M_WAITOK
, MT_DATA
);
111 m
->m_len
= sco_getopt(pcb
, sopt
->sopt_name
, mtod(m
, uint8_t *));
118 /* XXX There are possible memory leaks (Griffin) */
119 soopt_from_kbuf(sopt
, mtod(m
, void *), m
->m_len
);
123 m
= m_get(M_WAITOK
, MT_DATA
);
125 err
= soopt_to_kbuf(sopt
, mtod(m
,void*), m
->m_len
, m
->m_len
);
133 err
= sco_setopt(pcb
, sopt
->sopt_name
, mtod(m
, uint8_t *));
142 lwkt_replymsg(&msg
->ctloutput
.base
.lmsg
, err
);
145 /*****************************************************************************
147 * SCO Protocol socket callbacks
151 sco_connecting(void *arg
)
153 struct socket
*so
= arg
;
155 DPRINTF("Connecting\n");
160 sco_connected(void *arg
)
162 struct socket
*so
= arg
;
164 DPRINTF("Connected\n");
169 sco_disconnected(void *arg
, int err
)
171 struct socket
*so
= arg
;
173 DPRINTF("Disconnected (%d)\n", err
);
176 soisdisconnected(so
);
180 sco_newconn(void *arg
, struct sockaddr_bt
*laddr
,
181 struct sockaddr_bt
*raddr
)
183 struct socket
*so
= arg
;
185 DPRINTF("New Connection\n");
186 so
= sonewconn(so
, 0);
195 sco_complete(void *arg
, int num
)
197 struct socket
*so
= arg
;
200 sbdroprecord(&so
->so_snd
.sb
);
206 sco_linkmode(void *arg
, int mode
)
211 sco_input(void *arg
, struct mbuf
*m
)
213 struct socket
*so
= arg
;
216 * since this data is time sensitive, if the buffer
217 * is full we just dump data until the latest one
221 while (m
->m_pkthdr
.len
> sbspace(&so
->so_rcv
))
222 sbdroprecord(&so
->so_rcv
.sb
);
224 DPRINTFN(10, "received %d bytes\n", m
->m_pkthdr
.len
);
226 sbappendrecord(&so
->so_rcv
.sb
, m
);
231 * Implementation of usrreqs.
234 sco_sdetach(netmsg_t msg
)
236 struct socket
*so
= msg
->detach
.base
.nm_so
;
239 error
= sco_detach((struct sco_pcb
**)&so
->so_pcb
);
240 lwkt_replymsg(&msg
->detach
.base
.lmsg
, error
);
244 * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
245 * will sofree() it when we return.
248 sco_sabort (netmsg_t msg
)
250 struct socket
*so
= msg
->abort
.base
.nm_so
;
251 struct sco_pcb
*pcb
= (struct sco_pcb
*)so
->so_pcb
;
253 sco_disconnect(pcb
, 0);
254 soisdisconnected(so
);
256 /* msg invalid now */
260 sco_sdisconnect (netmsg_t msg
)
262 struct socket
*so
= msg
->abort
.base
.nm_so
;
263 struct sco_pcb
*pcb
= (struct sco_pcb
*)so
->so_pcb
;
266 soisdisconnecting(so
);
268 error
= sco_disconnect(pcb
, so
->so_linger
);
269 lwkt_replymsg(&msg
->disconnect
.base
.lmsg
, error
);
273 sco_sattach(netmsg_t msg
)
275 struct socket
*so
= msg
->attach
.base
.nm_so
;
276 struct sco_pcb
*pcb
= (struct sco_pcb
*)so
->so_pcb
;
282 error
= soreserve(so
, sco_sendspace
, sco_recvspace
,NULL
);
284 error
= sco_attach((struct sco_pcb
**)&so
->so_pcb
,
288 lwkt_replymsg(&msg
->attach
.base
.lmsg
, error
);
292 sco_sbind(netmsg_t msg
)
294 struct socket
*so
= msg
->bind
.base
.nm_so
;
295 struct sockaddr
*nam
= msg
->bind
.nm_nam
;
296 struct sco_pcb
*pcb
= (struct sco_pcb
*)so
->so_pcb
;
297 struct sockaddr_bt
*sa
;
300 KKASSERT(nam
!= NULL
);
301 sa
= (struct sockaddr_bt
*)nam
;
303 if (sa
->bt_len
!= sizeof(struct sockaddr_bt
)) {
305 } else if (sa
->bt_family
!= AF_BLUETOOTH
) {
306 error
= EAFNOSUPPORT
;
308 error
= sco_bind(pcb
, sa
);
310 lwkt_replymsg(&msg
->bind
.base
.lmsg
, error
);
314 sco_sconnect(netmsg_t msg
)
316 struct socket
*so
= msg
->connect
.base
.nm_so
;
317 struct sockaddr
*nam
= msg
->connect
.nm_nam
;
318 struct sco_pcb
*pcb
= (struct sco_pcb
*)so
->so_pcb
;
319 struct sockaddr_bt
*sa
;
322 KKASSERT(nam
!= NULL
);
323 sa
= (struct sockaddr_bt
*)nam
;
325 if (sa
->bt_len
!= sizeof(struct sockaddr_bt
)) {
327 } else if (sa
->bt_family
!= AF_BLUETOOTH
) {
328 error
= EAFNOSUPPORT
;
331 error
= sco_connect(pcb
, sa
);
333 lwkt_replymsg(&msg
->connect
.base
.lmsg
, error
);
337 sco_speeraddr(netmsg_t msg
)
339 struct socket
*so
= msg
->peeraddr
.base
.nm_so
;
340 struct sockaddr
**nam
= msg
->peeraddr
.nm_nam
;
341 struct sco_pcb
*pcb
= (struct sco_pcb
*)so
->so_pcb
;
342 struct sockaddr_bt
*sa
, ssa
;
346 bzero(sa
, sizeof *sa
);
347 sa
->bt_len
= sizeof(struct sockaddr_bt
);
348 sa
->bt_family
= AF_BLUETOOTH
;
349 error
= sco_peeraddr(pcb
, sa
);
350 *nam
= dup_sockaddr((struct sockaddr
*)sa
);
351 lwkt_replymsg(&msg
->peeraddr
.base
.lmsg
, error
);
355 sco_ssockaddr(netmsg_t msg
)
357 struct socket
*so
= msg
->sockaddr
.base
.nm_so
;
358 struct sockaddr
**nam
= msg
->sockaddr
.nm_nam
;
359 struct sco_pcb
*pcb
= (struct sco_pcb
*)so
->so_pcb
;
360 struct sockaddr_bt
*sa
, ssa
;
364 bzero(sa
, sizeof *sa
);
365 sa
->bt_len
= sizeof(struct sockaddr_bt
);
366 sa
->bt_family
= AF_BLUETOOTH
;
367 error
= sco_sockaddr(pcb
, sa
);
368 *nam
= dup_sockaddr((struct sockaddr
*)sa
);
370 lwkt_replymsg(&msg
->sockaddr
.base
.lmsg
, error
);
374 sco_sshutdown(netmsg_t msg
)
376 socantsendmore(msg
->shutdown
.base
.nm_so
);
377 lwkt_replymsg(&msg
->shutdown
.base
.lmsg
, 0);
381 sco_ssend(netmsg_t msg
)
383 struct socket
*so
= msg
->send
.base
.nm_so
;
384 struct mbuf
*m
= msg
->send
.nm_m
;
385 struct mbuf
*control
= msg
->send
.nm_control
;
386 struct sco_pcb
*pcb
= (struct sco_pcb
*)so
->so_pcb
;
391 if (m
->m_pkthdr
.len
== 0)
394 if (m
->m_pkthdr
.len
> pcb
->sp_mtu
) {
399 m0
= m_copym(m
, 0, M_COPYALL
, M_NOWAIT
);
405 /* no use for that */
411 sbappendrecord(&so
->so_snd
.sb
, m
);
412 error
= sco_send(pcb
, m0
);
419 lwkt_replymsg(&msg
->send
.base
.lmsg
, error
);
423 sco_saccept(netmsg_t msg
)
425 struct socket
*so
= msg
->accept
.base
.nm_so
;
426 struct sockaddr
**nam
= msg
->accept
.nm_nam
;
427 struct sco_pcb
*pcb
= (struct sco_pcb
*)so
->so_pcb
;
428 struct sockaddr_bt
*sa
, ssa
;
432 bzero(sa
, sizeof *sa
);
433 sa
->bt_len
= sizeof(struct sockaddr_bt
);
434 sa
->bt_family
= AF_BLUETOOTH
;
435 error
= sco_peeraddr(pcb
, sa
);
436 *nam
= dup_sockaddr((struct sockaddr
*)sa
);
438 lwkt_replymsg(&msg
->accept
.base
.lmsg
, error
);
442 sco_slisten(netmsg_t msg
)
444 struct socket
*so
= msg
->listen
.base
.nm_so
;
445 struct sco_pcb
*pcb
= (struct sco_pcb
*)so
->so_pcb
;
448 error
= sco_listen(pcb
);
449 lwkt_replymsg(&msg
->accept
.base
.lmsg
, error
);
452 struct pr_usrreqs sco_usrreqs
= {
453 .pru_abort
= sco_sabort
,
454 .pru_accept
= sco_saccept
,
455 .pru_attach
= sco_sattach
,
456 .pru_bind
= sco_sbind
,
457 .pru_connect
= sco_sconnect
,
458 .pru_connect2
= pr_generic_notsupp
,
459 .pru_control
= pr_generic_notsupp
,
460 .pru_detach
= sco_sdetach
,
461 .pru_disconnect
= sco_sdisconnect
,
462 .pru_listen
= sco_slisten
,
463 .pru_peeraddr
= sco_speeraddr
,
464 .pru_rcvd
= pr_generic_notsupp
,
465 .pru_rcvoob
= pr_generic_notsupp
,
466 .pru_send
= sco_ssend
,
467 .pru_sense
= pru_sense_null
,
468 .pru_shutdown
= sco_sshutdown
,
469 .pru_sockaddr
= sco_ssockaddr
,
470 .pru_sosend
= sosend
,
471 .pru_soreceive
= soreceive