[BACK]Return to sco_socket.c CVS log [TXT][DIR] Up to [local] / sys / netbt

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