root/netbt/sco_socket.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sco_usrreq
  2. sco_ctloutput
  3. sco_connecting
  4. sco_connected
  5. sco_disconnected
  6. sco_newconn
  7. sco_complete
  8. sco_linkmode
  9. sco_input

    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 }

/* [<][>][^][v][top][bottom][index][help] */