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

Cache object: 78208178a35829db08e31563ae595508


[ 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.