Annotation of sys/netbt/sco_socket.c, Revision 1.1.1.1
1.1 nbrk 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 $ */
3:
4: /*-
5: * Copyright (c) 2006 Itronix Inc.
6: * All rights reserved.
7: *
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.
19: *
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.
31: */
32:
33: #include <sys/cdefs.h>
34:
35: /* load symbolic names */
36: #ifdef BLUETOOTH_DEBUG
37: #define PRUREQUESTS
38: #define PRCOREQUESTS
39: #endif
40:
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>
50:
51: #include <netbt/bluetooth.h>
52: #include <netbt/hci.h>
53: #include <netbt/sco.h>
54:
55: /*******************************************************************************
56: *
57: * SCO SOCK_SEQPACKET sockets - low latency audio data
58: */
59:
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 *);
67:
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,
76: };
77:
78: int sco_sendspace = 4096;
79: int sco_recvspace = 4096;
80:
81: /*
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)
93: *
94: * we are responsible for disposing of m and ctl if
95: * they are mbuf chains
96: */
97: int
98: sco_usrreq(struct socket *up, int req, struct mbuf *m,
99: struct mbuf *nam, struct mbuf *ctl)
100: {
101: struct sco_pcb *pcb = (struct sco_pcb *)up->so_pcb;
102: struct sockaddr_bt *sa;
103: struct mbuf *m0;
104: int err = 0;
105:
106: #ifdef notyet /* XXX */
107: DPRINTFN(2, "%s\n", prurequests[req]);
108: #endif
109:
110: switch(req) {
111: case PRU_CONTROL:
112: return EOPNOTSUPP;
113:
114: #ifdef notyet /* XXX */
115: case PRU_PURGEIF:
116: return EOPNOTSUPP;
117: #endif
118:
119: case PRU_ATTACH:
120: if (pcb)
121: return EINVAL;
122:
123: err = soreserve(up, sco_sendspace, sco_recvspace);
124: if (err)
125: return err;
126:
127: return sco_attach((struct sco_pcb **)&up->so_pcb,
128: &sco_proto, up);
129: }
130:
131: /* anything after here *requires* a pcb */
132: if (pcb == NULL) {
133: err = EINVAL;
134: goto release;
135: }
136:
137: switch(req) {
138: case PRU_DISCONNECT:
139: soisdisconnecting(up);
140: return sco_disconnect(pcb, up->so_linger);
141:
142: case PRU_ABORT:
143: sco_disconnect(pcb, 0);
144: soisdisconnected(up);
145: /* fall through to */
146: case PRU_DETACH:
147: return sco_detach((struct sco_pcb **)&up->so_pcb);
148:
149: case PRU_BIND:
150: KASSERT(nam != NULL);
151: sa = mtod(nam, struct sockaddr_bt *);
152:
153: if (sa->bt_len != sizeof(struct sockaddr_bt))
154: return EINVAL;
155:
156: if (sa->bt_family != AF_BLUETOOTH)
157: return EAFNOSUPPORT;
158:
159: return sco_bind(pcb, sa);
160:
161: case PRU_CONNECT:
162: KASSERT(nam != NULL);
163: sa = mtod(nam, struct sockaddr_bt *);
164:
165: if (sa->bt_len != sizeof(struct sockaddr_bt))
166: return EINVAL;
167:
168: if (sa->bt_family != AF_BLUETOOTH)
169: return EAFNOSUPPORT;
170:
171: soisconnecting(up);
172: return sco_connect(pcb, sa);
173:
174: case PRU_PEERADDR:
175: KASSERT(nam != NULL);
176: sa = mtod(nam, struct sockaddr_bt *);
177: nam->m_len = sizeof(struct sockaddr_bt);
178: return sco_peeraddr(pcb, sa);
179:
180: case PRU_SOCKADDR:
181: KASSERT(nam != NULL);
182: sa = mtod(nam, struct sockaddr_bt *);
183: nam->m_len = sizeof(struct sockaddr_bt);
184: return sco_sockaddr(pcb, sa);
185:
186: case PRU_SHUTDOWN:
187: socantsendmore(up);
188: break;
189:
190: case PRU_SEND:
191: KASSERT(m != NULL);
192: if (m->m_pkthdr.len == 0)
193: break;
194:
195: if (m->m_pkthdr.len > pcb->sp_mtu) {
196: err = EMSGSIZE;
197: break;
198: }
199:
200: m0 = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
201: if (m0 == NULL) {
202: err = ENOMEM;
203: break;
204: }
205:
206: if (ctl) /* no use for that */
207: m_freem(ctl);
208:
209: sbappendrecord(&up->so_snd, m);
210: return sco_send(pcb, m0);
211:
212: case PRU_SENSE:
213: return 0; /* (no sense - Doh!) */
214:
215: case PRU_RCVD:
216: case PRU_RCVOOB:
217: return EOPNOTSUPP; /* (no release) */
218:
219: case PRU_LISTEN:
220: return sco_listen(pcb);
221:
222: case PRU_ACCEPT:
223: KASSERT(nam != NULL);
224: sa = mtod(nam, struct sockaddr_bt *);
225: nam->m_len = sizeof(struct sockaddr_bt);
226: return sco_peeraddr(pcb, sa);
227:
228: case PRU_CONNECT2:
229: case PRU_SENDOOB:
230: case PRU_FASTTIMO:
231: case PRU_SLOWTIMO:
232: case PRU_PROTORCV:
233: case PRU_PROTOSEND:
234: err = EOPNOTSUPP;
235: break;
236:
237: default:
238: UNKNOWN(req);
239: err = EOPNOTSUPP;
240: break;
241: }
242:
243: release:
244: if (m) m_freem(m);
245: if (ctl) m_freem(ctl);
246: return err;
247: }
248:
249: /*
250: * get/set socket options
251: */
252: int
253: sco_ctloutput(int req, struct socket *so, int level,
254: int optname, struct mbuf **opt)
255: {
256: struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
257: struct mbuf *m;
258: int err = 0;
259:
260: #ifdef notyet /* XXX */
261: DPRINTFN(2, "req %s\n", prcorequests[req]);
262: #endif
263:
264: if (pcb == NULL)
265: return EINVAL;
266:
267: if (level != BTPROTO_SCO)
268: return ENOPROTOOPT;
269:
270: switch(req) {
271: case PRCO_GETOPT:
272: m = m_get(M_WAIT, MT_SOOPTS);
273: m->m_len = sco_getopt(pcb, optname, mtod(m, uint8_t *));
274: if (m->m_len == 0) {
275: m_freem(m);
276: m = NULL;
277: err = ENOPROTOOPT;
278: }
279: *opt = m;
280: break;
281:
282: case PRCO_SETOPT:
283: m = *opt;
284: KASSERT(m != NULL);
285: err = sco_setopt(pcb, optname, mtod(m, uint8_t *));
286: m_freem(m);
287: break;
288:
289: default:
290: err = ENOPROTOOPT;
291: break;
292: }
293:
294: return err;
295: }
296:
297: /*****************************************************************************
298: *
299: * SCO Protocol socket callbacks
300: *
301: */
302: static void
303: sco_connecting(void *arg)
304: {
305: struct socket *so = arg;
306:
307: DPRINTF("Connecting\n");
308: soisconnecting(so);
309: }
310:
311: static void
312: sco_connected(void *arg)
313: {
314: struct socket *so = arg;
315:
316: DPRINTF("Connected\n");
317: soisconnected(so);
318: }
319:
320: static void
321: sco_disconnected(void *arg, int err)
322: {
323: struct socket *so = arg;
324:
325: DPRINTF("Disconnected (%d)\n", err);
326:
327: so->so_error = err;
328: soisdisconnected(so);
329: }
330:
331: static void *
332: sco_newconn(void *arg, struct sockaddr_bt *laddr,
333: struct sockaddr_bt *raddr)
334: {
335: struct socket *so = arg;
336:
337: DPRINTF("New Connection\n");
338: so = sonewconn(so, 0);
339: if (so == NULL)
340: return NULL;
341:
342: soisconnecting(so);
343: return so->so_pcb;
344: }
345:
346: static void
347: sco_complete(void *arg, int num)
348: {
349: struct socket *so = arg;
350:
351: while (num-- > 0)
352: sbdroprecord(&so->so_snd);
353:
354: sowwakeup(so);
355: }
356:
357: static void
358: sco_linkmode(void *arg, int mode)
359: {
360: }
361:
362: static void
363: sco_input(void *arg, struct mbuf *m)
364: {
365: struct socket *so = arg;
366:
367: /*
368: * since this data is time sensitive, if the buffer
369: * is full we just dump data until the latest one
370: * will fit.
371: */
372:
373: while (m->m_pkthdr.len > sbspace(&so->so_rcv))
374: sbdroprecord(&so->so_rcv);
375:
376: DPRINTFN(10, "received %d bytes\n", m->m_pkthdr.len);
377:
378: sbappendrecord(&so->so_rcv, m);
379: sorwakeup(so);
380: }
CVSweb