wbsio(4): support W83687THF (0x85); hw mon is already supported by lm(4) as W83627THF...
[dragonfly.git] / sys / netbt / sco_socket.c
blob527ac92c3629dd9fccc1528b4df03ee402759a62
1 /* $OpenBSD: sco_socket.c,v 1.1 2007/06/01 02:46:12 uwe Exp $ */
2 /* $NetBSD: sco_socket.c,v 1.9 2007/04/21 06:15:23 plunky Exp $ */
4 /*-
5 * Copyright (c) 2006 Itronix Inc.
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of Itronix Inc. may not be used to endorse
17 * or promote products derived from this software without specific
18 * prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
33 /* load symbolic names */
34 #ifdef BLUETOOTH_DEBUG
35 #define PRUREQUESTS
36 #define PRCOREQUESTS
37 #endif
39 #include <sys/param.h>
40 #include <sys/domain.h>
41 #include <sys/kernel.h>
42 #include <sys/mbuf.h>
43 #include <sys/proc.h>
44 #include <sys/protosw.h>
45 #include <sys/socket.h>
46 #include <sys/socketvar.h>
47 #include <sys/systm.h>
48 #include <sys/bus.h>
50 #include <netbt/bluetooth.h>
51 #include <netbt/hci.h>
52 #include <netbt/sco.h>
54 /*******************************************************************************
56 * SCO SOCK_SEQPACKET sockets - low latency audio data
59 static void sco_connecting(void *);
60 static void sco_connected(void *);
61 static void sco_disconnected(void *, int);
62 static void *sco_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *);
63 static void sco_complete(void *, int);
64 static void sco_linkmode(void *, int);
65 static void sco_input(void *, struct mbuf *);
67 static const struct btproto sco_proto = {
68 sco_connecting,
69 sco_connected,
70 sco_disconnected,
71 sco_newconn,
72 sco_complete,
73 sco_linkmode,
74 sco_input,
77 int sco_sendspace = 4096;
78 int sco_recvspace = 4096;
81 * get/set socket options
83 int
84 sco_ctloutput(struct socket *so, struct sockopt *sopt)
86 struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
87 struct mbuf *m;
88 int err = 0;
90 #ifdef notyet /* XXX */
91 DPRINTFN(2, "req %s\n", prcorequests[req]);
92 #endif
94 if (pcb == NULL)
95 return EINVAL;
97 if (sopt->sopt_level != BTPROTO_SCO)
98 return ENOPROTOOPT;
100 switch(sopt->sopt_dir) {
101 case PRCO_GETOPT:
102 m = m_get(MB_WAIT, MT_DATA);
103 m->m_len = sco_getopt(pcb, sopt->sopt_name, mtod(m, uint8_t *));
104 if (m->m_len == 0) {
105 m_freem(m);
106 m = NULL;
107 err = ENOPROTOOPT;
109 /* *opt = m; */
110 /* XXX There are possible memory leaks (Griffin) */
111 soopt_from_kbuf(sopt, mtod(m, void *), m->m_len);
112 break;
114 case PRCO_SETOPT:
115 m = m_get(M_WAITOK, MT_DATA);
116 KKASSERT(m != NULL);
117 err = soopt_to_kbuf(sopt, mtod(m,void*), m->m_len, m->m_len);
119 if (m->m_len == 0) {
120 m_freem(m);
121 m = NULL;
122 err = EIO;
125 err = sco_setopt(pcb, sopt->sopt_name, mtod(m, uint8_t *));
126 m_freem(m);
127 break;
129 default:
130 err = ENOPROTOOPT;
131 break;
134 return err;
137 /*****************************************************************************
139 * SCO Protocol socket callbacks
142 static void
143 sco_connecting(void *arg)
145 struct socket *so = arg;
147 DPRINTF("Connecting\n");
148 soisconnecting(so);
151 static void
152 sco_connected(void *arg)
154 struct socket *so = arg;
156 DPRINTF("Connected\n");
157 soisconnected(so);
160 static void
161 sco_disconnected(void *arg, int err)
163 struct socket *so = arg;
165 DPRINTF("Disconnected (%d)\n", err);
167 so->so_error = err;
168 soisdisconnected(so);
171 static void *
172 sco_newconn(void *arg, struct sockaddr_bt *laddr,
173 struct sockaddr_bt *raddr)
175 struct socket *so = arg;
177 DPRINTF("New Connection\n");
178 so = sonewconn(so, 0);
179 if (so == NULL)
180 return NULL;
182 soisconnecting(so);
183 return so->so_pcb;
186 static void
187 sco_complete(void *arg, int num)
189 struct socket *so = arg;
191 while (num-- > 0)
192 sbdroprecord(&so->so_snd.sb);
194 sowwakeup(so);
197 static void
198 sco_linkmode(void *arg, int mode)
202 static void
203 sco_input(void *arg, struct mbuf *m)
205 struct socket *so = arg;
208 * since this data is time sensitive, if the buffer
209 * is full we just dump data until the latest one
210 * will fit.
213 while (m->m_pkthdr.len > sbspace(&so->so_rcv))
214 sbdroprecord(&so->so_rcv.sb);
216 DPRINTFN(10, "received %d bytes\n", m->m_pkthdr.len);
218 sbappendrecord(&so->so_rcv.sb, m);
219 sorwakeup(so);
223 * Implementation of usrreqs.
225 static int
226 sco_sdetach(struct socket *so)
228 return sco_detach((struct sco_pcb **)&so->so_pcb);
231 static int
232 sco_sabort (struct socket *so)
234 struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
236 sco_disconnect(pcb, 0);
237 soisdisconnected(so);
239 return sco_sdetach(so);
242 static int
243 sco_sdisconnect (struct socket *so)
245 struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
247 soisdisconnecting(so);
249 return sco_disconnect(pcb, so->so_linger);
252 static int
253 sco_sattach (struct socket *so, int proto,
254 struct pru_attach_info *ai)
256 struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
257 int err=0;
259 if (pcb)
260 return EINVAL;
262 err = soreserve(so, sco_sendspace, sco_recvspace,NULL);
263 if (err)
264 return err;
266 return sco_attach((struct sco_pcb **)&so->so_pcb,
267 &sco_proto, so);
270 static int
271 sco_sbind (struct socket *so, struct sockaddr *nam,
272 struct thread *td)
274 struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
275 struct sockaddr_bt *sa;
277 KKASSERT(nam != NULL);
278 sa = (struct sockaddr_bt *)nam;
280 if (sa->bt_len != sizeof(struct sockaddr_bt))
281 return EINVAL;
283 if (sa->bt_family != AF_BLUETOOTH)
284 return EAFNOSUPPORT;
286 return sco_bind(pcb, sa);
289 static int
290 sco_sconnect (struct socket *so, struct sockaddr *nam,
291 struct thread *td)
293 struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
294 struct sockaddr_bt *sa;
296 KKASSERT(nam != NULL);
297 sa = (struct sockaddr_bt *)nam;
299 if (sa->bt_len != sizeof(struct sockaddr_bt))
300 return EINVAL;
302 if (sa->bt_family != AF_BLUETOOTH)
303 return EAFNOSUPPORT;
305 soisconnecting(so);
306 return sco_connect(pcb, sa);
309 static int
310 sco_speeraddr (struct socket *so, struct sockaddr **nam)
312 struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
313 struct sockaddr_bt *sa, ssa;
314 int e;
316 sa = &ssa;
317 bzero(sa, sizeof *sa);
318 sa->bt_len = sizeof(struct sockaddr_bt);
319 sa->bt_family = AF_BLUETOOTH;
320 e = sco_peeraddr(pcb, sa);
321 *nam = dup_sockaddr((struct sockaddr *)sa);
323 return (e);
326 static int
327 sco_ssockaddr (struct socket *so, struct sockaddr **nam)
329 struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
330 struct sockaddr_bt *sa, ssa;
331 int e;
333 sa = &ssa;
334 bzero(sa, sizeof *sa);
335 sa->bt_len = sizeof(struct sockaddr_bt);
336 sa->bt_family = AF_BLUETOOTH;
337 e = sco_sockaddr(pcb, sa);
338 *nam = dup_sockaddr((struct sockaddr *)sa);
340 return (e);
343 static int
344 sco_sshutdown (struct socket *so)
346 socantsendmore(so);
347 return 0;
350 static int
351 sco_ssend (struct socket *so, int flags, struct mbuf *m,
352 struct sockaddr *addr, struct mbuf *control, struct thread *td)
354 struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
355 struct mbuf *m0;
356 int err = 0;
358 KKASSERT(m != NULL);
359 if (m->m_pkthdr.len == 0)
360 goto error;
362 if (m->m_pkthdr.len > pcb->sp_mtu) {
363 err = EMSGSIZE;
364 goto error;
367 m0 = m_copym(m, 0, M_COPYALL, MB_DONTWAIT);
368 if (m0 == NULL) {
369 err = ENOMEM;
370 goto error;
373 if (control) /* no use for that */
374 m_freem(control);
376 sbappendrecord(&so->so_snd.sb, m);
377 return sco_send(pcb, m0);
379 error:
380 if (m) m_freem(m);
381 if (control) m_freem(control);
382 return err;
385 static int
386 sco_saccept(struct socket *so, struct sockaddr **nam)
388 struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
389 struct sockaddr_bt *sa, ssa;
390 int e;
392 sa = &ssa;
393 bzero(sa, sizeof *sa);
394 sa->bt_len = sizeof(struct sockaddr_bt);
395 sa->bt_family = AF_BLUETOOTH;
396 e = sco_peeraddr(pcb, sa);
397 *nam = dup_sockaddr((struct sockaddr *)sa);
399 return (e);
402 static int
403 sco_slisten(struct socket *so, struct thread *td)
405 struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
406 return sco_listen(pcb);
410 struct pr_usrreqs sco_usrreqs = {
411 .pru_abort = sco_sabort,
412 .pru_accept = sco_saccept,
413 .pru_attach = sco_sattach,
414 .pru_bind = sco_sbind,
415 .pru_connect = sco_sconnect,
416 .pru_connect2 = pru_connect2_notsupp,
417 .pru_control = pru_control_notsupp,
418 .pru_detach = sco_sdetach,
419 .pru_disconnect = sco_sdisconnect,
420 .pru_listen = sco_slisten,
421 .pru_peeraddr = sco_speeraddr,
422 .pru_rcvd = pru_rcvd_notsupp,
423 .pru_rcvoob = pru_rcvoob_notsupp,
424 .pru_send = sco_ssend,
425 .pru_sense = pru_sense_null,
426 .pru_shutdown = sco_sshutdown,
427 .pru_sockaddr = sco_ssockaddr,
428 .pru_sosend = sosend,
429 .pru_soreceive = soreceive,
430 .pru_sopoll = sopoll