The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netbt/sco_socket.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: sco_socket.c,v 1.11 2008/08/06 15:01:24 plunky Exp $   */
    2 
    3 /*-
    4  * Copyright (c) 2006 Itronix Inc.
    5  * All rights reserved.
    6  *
    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.
   18  *
   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.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __KERNEL_RCSID(0, "$NetBSD: sco_socket.c,v 1.11 2008/08/06 15:01:24 plunky Exp $");
   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, struct lwp *l)
  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         DPRINTFN(2, "%s\n", prurequests[req]);
  107 
  108         switch(req) {
  109         case PRU_CONTROL:
  110                 return EOPNOTSUPP;
  111 
  112         case PRU_PURGEIF:
  113                 return EOPNOTSUPP;
  114 
  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);
  120                 }
  121                 KASSERT(solocked(up));
  122                 if (pcb)
  123                         return EINVAL;
  124                 err = soreserve(up, sco_sendspace, sco_recvspace);
  125                 if (err)
  126                         return err;
  127 
  128                 return sco_attach((struct sco_pcb **)&up->so_pcb,
  129                                         &sco_proto, up);
  130         }
  131 
  132         /* anything after here *requires* a pcb */
  133         if (pcb == NULL) {
  134                 err = EINVAL;
  135                 goto release;
  136         }
  137 
  138         switch(req) {
  139         case PRU_DISCONNECT:
  140                 soisdisconnecting(up);
  141                 return sco_disconnect(pcb, up->so_linger);
  142 
  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);
  149 
  150         case PRU_BIND:
  151                 KASSERT(nam != NULL);
  152                 sa = mtod(nam, struct sockaddr_bt *);
  153 
  154                 if (sa->bt_len != sizeof(struct sockaddr_bt))
  155                         return EINVAL;
  156 
  157                 if (sa->bt_family != AF_BLUETOOTH)
  158                         return EAFNOSUPPORT;
  159 
  160                 return sco_bind(pcb, sa);
  161 
  162         case PRU_CONNECT:
  163                 KASSERT(nam != NULL);
  164                 sa = mtod(nam, struct sockaddr_bt *);
  165 
  166                 if (sa->bt_len != sizeof(struct sockaddr_bt))
  167                         return EINVAL;
  168 
  169                 if (sa->bt_family != AF_BLUETOOTH)
  170                         return EAFNOSUPPORT;
  171 
  172                 soisconnecting(up);
  173                 return sco_connect(pcb, sa);
  174 
  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);
  180 
  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);
  186 
  187         case PRU_SHUTDOWN:
  188                 socantsendmore(up);
  189                 break;
  190 
  191         case PRU_SEND:
  192                 KASSERT(m != NULL);
  193                 if (m->m_pkthdr.len == 0)
  194                         break;
  195 
  196                 if (m->m_pkthdr.len > pcb->sp_mtu) {
  197                         err = EMSGSIZE;
  198                         break;
  199                 }
  200 
  201                 m0 = m_copypacket(m, M_DONTWAIT);
  202                 if (m0 == NULL) {
  203                         err = ENOMEM;
  204                         break;
  205                 }
  206 
  207                 if (ctl) /* no use for that */
  208                         m_freem(ctl);
  209 
  210                 sbappendrecord(&up->so_snd, m);
  211                 return sco_send(pcb, m0);
  212 
  213         case PRU_SENSE:
  214                 return 0;               /* (no sense - Doh!) */
  215 
  216         case PRU_RCVD:
  217         case PRU_RCVOOB:
  218                 return EOPNOTSUPP;      /* (no release) */
  219 
  220         case PRU_LISTEN:
  221                 return sco_listen(pcb);
  222 
  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);
  228 
  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;
  237 
  238         default:
  239                 UNKNOWN(req);
  240                 err = EOPNOTSUPP;
  241                 break;
  242         }
  243 
  244 release:
  245         if (m) m_freem(m);
  246         if (ctl) m_freem(ctl);
  247         return err;
  248 }
  249 
  250 /*
  251  * get/set socket options
  252  */
  253 int
  254 sco_ctloutput(int req, struct socket *so, struct sockopt *sopt)
  255 {
  256         struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
  257         int err = 0;
  258 
  259         DPRINTFN(2, "req %s\n", prcorequests[req]);
  260 
  261         if (pcb == NULL)
  262                 return EINVAL;
  263 
  264         if (sopt->sopt_level != BTPROTO_SCO)
  265                 return ENOPROTOOPT;
  266 
  267         switch(req) {
  268         case PRCO_GETOPT:
  269                 err = sco_getopt(pcb, sopt);
  270                 break;
  271 
  272         case PRCO_SETOPT:
  273                 err = sco_setopt(pcb, sopt);
  274                 break;
  275 
  276         default:
  277                 err = ENOPROTOOPT;
  278                 break;
  279         }
  280 
  281         return err;
  282 }
  283 
  284 /*****************************************************************************
  285  *
  286  *      SCO Protocol socket callbacks
  287  *
  288  */
  289 static void
  290 sco_connecting(void *arg)
  291 {
  292         struct socket *so = arg;
  293 
  294         DPRINTF("Connecting\n");
  295         soisconnecting(so);
  296 }
  297 
  298 static void
  299 sco_connected(void *arg)
  300 {
  301         struct socket *so = arg;
  302 
  303         DPRINTF("Connected\n");
  304         soisconnected(so);
  305 }
  306 
  307 static void
  308 sco_disconnected(void *arg, int err)
  309 {
  310         struct socket *so = arg;
  311 
  312         DPRINTF("Disconnected (%d)\n", err);
  313 
  314         so->so_error = err;
  315         soisdisconnected(so);
  316 }
  317 
  318 static void *
  319 sco_newconn(void *arg, struct sockaddr_bt *laddr,
  320     struct sockaddr_bt *raddr)
  321 {
  322         struct socket *so = arg;
  323 
  324         DPRINTF("New Connection\n");
  325         so = sonewconn(so, 0);
  326         if (so == NULL)
  327                 return NULL;
  328 
  329         soisconnecting(so);
  330         return so->so_pcb;
  331 }
  332 
  333 static void
  334 sco_complete(void *arg, int num)
  335 {
  336         struct socket *so = arg;
  337 
  338         while (num-- > 0)
  339                 sbdroprecord(&so->so_snd);
  340 
  341         sowwakeup(so);
  342 }
  343 
  344 static void
  345 sco_linkmode(void *arg, int mode)
  346 {
  347 }
  348 
  349 static void
  350 sco_input(void *arg, struct mbuf *m)
  351 {
  352         struct socket *so = arg;
  353 
  354         /*
  355          * since this data is time sensitive, if the buffer
  356          * is full we just dump data until the latest one
  357          * will fit.
  358          */
  359 
  360         while (m->m_pkthdr.len > sbspace(&so->so_rcv))
  361                 sbdroprecord(&so->so_rcv);
  362 
  363         DPRINTFN(10, "received %d bytes\n", m->m_pkthdr.len);
  364 
  365         sbappendrecord(&so->so_rcv, m);
  366         sorwakeup(so);
  367 }

Cache object: 7ae0a9773f2a476b847cc6e04a8a0d27


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.