Annotation of sys/netbt/sco_socket.c, Revision 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