Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / netbt / sco_socket.c
blob82c71b8996e0c517ded940e1928e028030824fc5
1 /* $NetBSD: sco_socket.c,v 1.10 2008/04/24 11:38:37 ad Exp $ */
3 /*-
4 * Copyright (c) 2006 Itronix Inc.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of Itronix Inc. may not be used to endorse
16 * or promote products derived from this software without specific
17 * prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: sco_socket.c,v 1.10 2008/04/24 11:38:37 ad Exp $");
35 /* load symbolic names */
36 #ifdef BLUETOOTH_DEBUG
37 #define PRUREQUESTS
38 #define PRCOREQUESTS
39 #endif
41 #include <sys/param.h>
42 #include <sys/domain.h>
43 #include <sys/kernel.h>
44 #include <sys/mbuf.h>
45 #include <sys/proc.h>
46 #include <sys/protosw.h>
47 #include <sys/socket.h>
48 #include <sys/socketvar.h>
49 #include <sys/systm.h>
51 #include <netbt/bluetooth.h>
52 #include <netbt/hci.h>
53 #include <netbt/sco.h>
55 /*******************************************************************************
57 * SCO SOCK_SEQPACKET sockets - low latency audio data
60 static void sco_connecting(void *);
61 static void sco_connected(void *);
62 static void sco_disconnected(void *, int);
63 static void *sco_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *);
64 static void sco_complete(void *, int);
65 static void sco_linkmode(void *, int);
66 static void sco_input(void *, struct mbuf *);
68 static const struct btproto sco_proto = {
69 sco_connecting,
70 sco_connected,
71 sco_disconnected,
72 sco_newconn,
73 sco_complete,
74 sco_linkmode,
75 sco_input,
78 int sco_sendspace = 4096;
79 int sco_recvspace = 4096;
82 * User Request.
83 * up is socket
84 * m is either
85 * optional mbuf chain containing message
86 * ioctl command (PRU_CONTROL)
87 * nam is either
88 * optional mbuf chain containing an address
89 * ioctl data (PRU_CONTROL)
90 * optionally, protocol number (PRU_ATTACH)
91 * ctl is optional mbuf chain containing socket options
92 * l is pointer to process requesting action (if any)
94 * we are responsible for disposing of m and ctl if
95 * they are mbuf chains
97 int
98 sco_usrreq(struct socket *up, int req, struct mbuf *m,
99 struct mbuf *nam, struct mbuf *ctl, struct lwp *l)
101 struct sco_pcb *pcb = (struct sco_pcb *)up->so_pcb;
102 struct sockaddr_bt *sa;
103 struct mbuf *m0;
104 int err = 0;
106 DPRINTFN(2, "%s\n", prurequests[req]);
108 switch(req) {
109 case PRU_CONTROL:
110 return EOPNOTSUPP;
112 case PRU_PURGEIF:
113 return EOPNOTSUPP;
115 case PRU_ATTACH:
116 if (up->so_lock == NULL) {
117 mutex_obj_hold(bt_lock);
118 up->so_lock = bt_lock;
119 solock(up);
121 KASSERT(solocked(up));
122 if (pcb)
123 return EINVAL;
124 err = soreserve(up, sco_sendspace, sco_recvspace);
125 if (err)
126 return err;
128 return sco_attach((struct sco_pcb **)&up->so_pcb,
129 &sco_proto, up);
132 /* anything after here *requires* a pcb */
133 if (pcb == NULL) {
134 err = EINVAL;
135 goto release;
138 switch(req) {
139 case PRU_DISCONNECT:
140 soisdisconnecting(up);
141 return sco_disconnect(pcb, up->so_linger);
143 case PRU_ABORT:
144 sco_disconnect(pcb, 0);
145 soisdisconnected(up);
146 /* fall through to */
147 case PRU_DETACH:
148 return sco_detach((struct sco_pcb **)&up->so_pcb);
150 case PRU_BIND:
151 KASSERT(nam != NULL);
152 sa = mtod(nam, struct sockaddr_bt *);
154 if (sa->bt_len != sizeof(struct sockaddr_bt))
155 return EINVAL;
157 if (sa->bt_family != AF_BLUETOOTH)
158 return EAFNOSUPPORT;
160 return sco_bind(pcb, sa);
162 case PRU_CONNECT:
163 KASSERT(nam != NULL);
164 sa = mtod(nam, struct sockaddr_bt *);
166 if (sa->bt_len != sizeof(struct sockaddr_bt))
167 return EINVAL;
169 if (sa->bt_family != AF_BLUETOOTH)
170 return EAFNOSUPPORT;
172 soisconnecting(up);
173 return sco_connect(pcb, sa);
175 case PRU_PEERADDR:
176 KASSERT(nam != NULL);
177 sa = mtod(nam, struct sockaddr_bt *);
178 nam->m_len = sizeof(struct sockaddr_bt);
179 return sco_peeraddr(pcb, sa);
181 case PRU_SOCKADDR:
182 KASSERT(nam != NULL);
183 sa = mtod(nam, struct sockaddr_bt *);
184 nam->m_len = sizeof(struct sockaddr_bt);
185 return sco_sockaddr(pcb, sa);
187 case PRU_SHUTDOWN:
188 socantsendmore(up);
189 break;
191 case PRU_SEND:
192 KASSERT(m != NULL);
193 if (m->m_pkthdr.len == 0)
194 break;
196 if (m->m_pkthdr.len > pcb->sp_mtu) {
197 err = EMSGSIZE;
198 break;
201 m0 = m_copypacket(m, M_DONTWAIT);
202 if (m0 == NULL) {
203 err = ENOMEM;
204 break;
207 if (ctl) /* no use for that */
208 m_freem(ctl);
210 sbappendrecord(&up->so_snd, m);
211 return sco_send(pcb, m0);
213 case PRU_SENSE:
214 return 0; /* (no sense - Doh!) */
216 case PRU_RCVD:
217 case PRU_RCVOOB:
218 return EOPNOTSUPP; /* (no release) */
220 case PRU_LISTEN:
221 return sco_listen(pcb);
223 case PRU_ACCEPT:
224 KASSERT(nam != NULL);
225 sa = mtod(nam, struct sockaddr_bt *);
226 nam->m_len = sizeof(struct sockaddr_bt);
227 return sco_peeraddr(pcb, sa);
229 case PRU_CONNECT2:
230 case PRU_SENDOOB:
231 case PRU_FASTTIMO:
232 case PRU_SLOWTIMO:
233 case PRU_PROTORCV:
234 case PRU_PROTOSEND:
235 err = EOPNOTSUPP;
236 break;
238 default:
239 UNKNOWN(req);
240 err = EOPNOTSUPP;
241 break;
244 release:
245 if (m) m_freem(m);
246 if (ctl) m_freem(ctl);
247 return err;
251 * get/set socket options
254 sco_ctloutput(int req, struct socket *so, struct sockopt *sopt)
256 struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
257 int err = 0;
259 DPRINTFN(2, "req %s\n", prcorequests[req]);
261 if (pcb == NULL)
262 return EINVAL;
264 if (sopt->sopt_level != BTPROTO_SCO)
265 return ENOPROTOOPT;
267 switch(req) {
268 case PRCO_GETOPT:
269 err = sco_getopt(pcb, sopt);
270 break;
272 case PRCO_SETOPT:
273 err = sco_setopt(pcb, sopt);
274 break;
276 default:
277 err = ENOPROTOOPT;
278 break;
281 return err;
284 /*****************************************************************************
286 * SCO Protocol socket callbacks
289 static void
290 sco_connecting(void *arg)
292 struct socket *so = arg;
294 DPRINTF("Connecting\n");
295 soisconnecting(so);
298 static void
299 sco_connected(void *arg)
301 struct socket *so = arg;
303 DPRINTF("Connected\n");
304 soisconnected(so);
307 static void
308 sco_disconnected(void *arg, int err)
310 struct socket *so = arg;
312 DPRINTF("Disconnected (%d)\n", err);
314 so->so_error = err;
315 soisdisconnected(so);
318 static void *
319 sco_newconn(void *arg, struct sockaddr_bt *laddr,
320 struct sockaddr_bt *raddr)
322 struct socket *so = arg;
324 DPRINTF("New Connection\n");
325 so = sonewconn(so, 0);
326 if (so == NULL)
327 return NULL;
329 soisconnecting(so);
330 return so->so_pcb;
333 static void
334 sco_complete(void *arg, int num)
336 struct socket *so = arg;
338 while (num-- > 0)
339 sbdroprecord(&so->so_snd);
341 sowwakeup(so);
344 static void
345 sco_linkmode(void *arg, int mode)
349 static void
350 sco_input(void *arg, struct mbuf *m)
352 struct socket *so = arg;
355 * since this data is time sensitive, if the buffer
356 * is full we just dump data until the latest one
357 * will fit.
360 while (m->m_pkthdr.len > sbspace(&so->so_rcv))
361 sbdroprecord(&so->so_rcv);
363 DPRINTFN(10, "received %d bytes\n", m->m_pkthdr.len);
365 sbappendrecord(&so->so_rcv, m);
366 sorwakeup(so);