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.38 2019/01/28 12:53:01 martin 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.38 2019/01/28 12:53:01 martin 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 static int
   82 sco_attach(struct socket *so, int proto)
   83 {
   84         int error;
   85 
   86         KASSERT(so->so_pcb == NULL);
   87 
   88         if (so->so_lock == NULL) {
   89                 mutex_obj_hold(bt_lock);
   90                 so->so_lock = bt_lock;
   91                 solock(so);
   92         }
   93         KASSERT(solocked(so));
   94 
   95         error = soreserve(so, sco_sendspace, sco_recvspace);
   96         if (error) {
   97                 return error;
   98         }
   99         return sco_attach_pcb((struct sco_pcb **)&so->so_pcb, &sco_proto, so);
  100 }
  101 
  102 static void
  103 sco_detach(struct socket *so)
  104 {
  105         KASSERT(so->so_pcb != NULL);
  106         sco_detach_pcb((struct sco_pcb **)&so->so_pcb);
  107         KASSERT(so->so_pcb == NULL);
  108 }
  109 
  110 static int
  111 sco_accept(struct socket *so, struct sockaddr *nam)
  112 {
  113         struct sco_pcb *pcb = so->so_pcb;
  114 
  115         KASSERT(solocked(so));
  116         KASSERT(nam != NULL);
  117 
  118         if (pcb == NULL)
  119                 return EINVAL;
  120 
  121         return sco_peeraddr_pcb(pcb, (struct sockaddr_bt *)nam);
  122 }
  123 
  124 static int
  125 sco_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
  126 {
  127         struct sco_pcb *pcb = so->so_pcb;
  128         struct sockaddr_bt *sa = (struct sockaddr_bt *)nam;
  129 
  130         KASSERT(solocked(so));
  131         KASSERT(nam != NULL);
  132 
  133         if (pcb == NULL)
  134                 return EINVAL;
  135 
  136         if (sa->bt_len != sizeof(struct sockaddr_bt))
  137                 return EINVAL;
  138 
  139         if (sa->bt_family != AF_BLUETOOTH)
  140                 return EAFNOSUPPORT;
  141 
  142         return sco_bind_pcb(pcb, sa);
  143 }
  144 
  145 static int
  146 sco_listen(struct socket *so, struct lwp *l)
  147 {
  148         struct sco_pcb *pcb = so->so_pcb;
  149 
  150         KASSERT(solocked(so));
  151 
  152         if (pcb == NULL)
  153                 return EINVAL;
  154 
  155         return sco_listen_pcb(pcb);
  156 }
  157 
  158 static int
  159 sco_connect(struct socket *so, struct sockaddr *nam, struct lwp *l)
  160 {
  161         struct sco_pcb *pcb = so->so_pcb;
  162         struct sockaddr_bt *sa = (struct sockaddr_bt *)nam;
  163 
  164         KASSERT(solocked(so));
  165         KASSERT(nam != NULL);
  166 
  167         if (pcb == NULL)
  168                 return EINVAL;
  169 
  170         if (sa->bt_len != sizeof(struct sockaddr_bt))
  171                 return EINVAL;
  172 
  173         if (sa->bt_family != AF_BLUETOOTH)
  174                 return EAFNOSUPPORT;
  175 
  176         soisconnecting(so);
  177         return sco_connect_pcb(pcb, sa);
  178 }
  179 
  180 static int
  181 sco_connect2(struct socket *so, struct socket *so2)
  182 {
  183         struct sco_pcb *pcb = so->so_pcb;
  184 
  185         KASSERT(solocked(so));
  186 
  187         if (pcb == NULL)
  188                 return EINVAL;
  189 
  190         return EOPNOTSUPP;
  191 }
  192 
  193 static int
  194 sco_disconnect(struct socket *so)
  195 {
  196         struct sco_pcb *pcb = so->so_pcb;
  197 
  198         KASSERT(solocked(so));
  199 
  200         if (pcb == NULL)
  201                 return EINVAL;
  202 
  203         soisdisconnecting(so);
  204         return sco_disconnect_pcb(pcb, so->so_linger);
  205 }
  206 
  207 static int
  208 sco_shutdown(struct socket *so)
  209 {
  210         KASSERT(solocked(so));
  211 
  212         socantsendmore(so);
  213         return 0;
  214 }
  215 
  216 static int
  217 sco_abort(struct socket *so)
  218 {
  219         struct sco_pcb *pcb = so->so_pcb;
  220 
  221         KASSERT(solocked(so));
  222 
  223         if (pcb == NULL)
  224                 return EINVAL;
  225 
  226         sco_disconnect_pcb(pcb, 0);
  227         soisdisconnected(so);
  228         sco_detach(so);
  229         return 0;
  230 }
  231 
  232 static int
  233 sco_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
  234 {
  235         return EOPNOTSUPP;
  236 }
  237 
  238 static int
  239 sco_stat(struct socket *so, struct stat *ub)
  240 {
  241         KASSERT(solocked(so));
  242 
  243         return 0;
  244 }
  245 
  246 static int
  247 sco_peeraddr(struct socket *so, struct sockaddr *nam)
  248 {
  249         struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
  250 
  251         KASSERT(solocked(so));
  252         KASSERT(pcb != NULL);
  253         KASSERT(nam != NULL);
  254 
  255         return sco_peeraddr_pcb(pcb, (struct sockaddr_bt *)nam);
  256 }
  257 
  258 static int
  259 sco_sockaddr(struct socket *so, struct sockaddr *nam)
  260 {
  261         struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
  262 
  263         KASSERT(solocked(so));
  264         KASSERT(pcb != NULL);
  265         KASSERT(nam != NULL);
  266 
  267         return sco_sockaddr_pcb(pcb, (struct sockaddr_bt *)nam);
  268 }
  269 
  270 static int
  271 sco_rcvd(struct socket *so, int flags, struct lwp *l)
  272 {
  273         KASSERT(solocked(so));
  274 
  275         return EOPNOTSUPP;
  276 }
  277 
  278 static int
  279 sco_recvoob(struct socket *so, struct mbuf *m, int flags)
  280 {
  281         KASSERT(solocked(so));
  282 
  283         return EOPNOTSUPP;
  284 }
  285 
  286 static int
  287 sco_send(struct socket *so, struct mbuf *m, struct sockaddr *nam,
  288     struct mbuf *control, struct lwp *l)
  289 {
  290         struct sco_pcb *pcb = so->so_pcb;
  291         int err = 0;
  292         struct mbuf *m0;
  293 
  294         KASSERT(solocked(so));
  295         KASSERT(m != NULL);
  296 
  297         if (control) /* no use for that */
  298                 m_freem(control);
  299 
  300         if (pcb == NULL) {
  301                 err = EINVAL;
  302                 goto release;
  303         }
  304 
  305         if (m->m_pkthdr.len == 0)
  306                 goto release;
  307 
  308         if (m->m_pkthdr.len > pcb->sp_mtu) {
  309                 err = EMSGSIZE;
  310                 goto release;
  311         }
  312 
  313         m0 = m_copypacket(m, M_DONTWAIT);
  314         if (m0 == NULL) {
  315                 err = ENOMEM;
  316                 goto release;
  317         }
  318 
  319         sbappendrecord(&so->so_snd, m);
  320         return sco_send_pcb(pcb, m0);
  321 
  322 release:
  323         m_freem(m);
  324         return err;
  325 }
  326 
  327 static int
  328 sco_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
  329 {
  330         KASSERT(solocked(so));
  331 
  332         m_freem(m);
  333         m_freem(control);
  334 
  335         return EOPNOTSUPP;
  336 }
  337 
  338 static int
  339 sco_purgeif(struct socket *so, struct ifnet *ifp)
  340 {
  341 
  342         return EOPNOTSUPP;
  343 }
  344 
  345 /*
  346  * get/set socket options
  347  */
  348 int
  349 sco_ctloutput(int req, struct socket *so, struct sockopt *sopt)
  350 {
  351         struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
  352         int err = 0;
  353 
  354         DPRINTFN(2, "req %s\n", prcorequests[req]);
  355 
  356         if (pcb == NULL)
  357                 return EINVAL;
  358 
  359         if (sopt->sopt_level != BTPROTO_SCO)
  360                 return ENOPROTOOPT;
  361 
  362         switch(req) {
  363         case PRCO_GETOPT:
  364                 err = sco_getopt(pcb, sopt);
  365                 break;
  366 
  367         case PRCO_SETOPT:
  368                 err = sco_setopt(pcb, sopt);
  369                 break;
  370 
  371         default:
  372                 err = ENOPROTOOPT;
  373                 break;
  374         }
  375 
  376         return err;
  377 }
  378 
  379 /*****************************************************************************
  380  *
  381  *      SCO Protocol socket callbacks
  382  *
  383  */
  384 static void
  385 sco_connecting(void *arg)
  386 {
  387         struct socket *so = arg;
  388 
  389         DPRINTF("Connecting\n");
  390         soisconnecting(so);
  391 }
  392 
  393 static void
  394 sco_connected(void *arg)
  395 {
  396         struct socket *so = arg;
  397 
  398         DPRINTF("Connected\n");
  399         soisconnected(so);
  400 }
  401 
  402 static void
  403 sco_disconnected(void *arg, int err)
  404 {
  405         struct socket *so = arg;
  406 
  407         DPRINTF("Disconnected (%d)\n", err);
  408 
  409         so->so_error = err;
  410         soisdisconnected(so);
  411 }
  412 
  413 static void *
  414 sco_newconn(void *arg, struct sockaddr_bt *laddr,
  415     struct sockaddr_bt *raddr)
  416 {
  417         struct socket *so = arg;
  418 
  419         DPRINTF("New Connection\n");
  420         so = sonewconn(so, false);
  421         if (so == NULL)
  422                 return NULL;
  423 
  424         soisconnecting(so);
  425         return so->so_pcb;
  426 }
  427 
  428 static void
  429 sco_complete(void *arg, int num)
  430 {
  431         struct socket *so = arg;
  432 
  433         while (num-- > 0)
  434                 sbdroprecord(&so->so_snd);
  435 
  436         sowwakeup(so);
  437 }
  438 
  439 static void
  440 sco_linkmode(void *arg, int mode)
  441 {
  442 }
  443 
  444 static void
  445 sco_input(void *arg, struct mbuf *m)
  446 {
  447         struct socket *so = arg;
  448 
  449         /*
  450          * since this data is time sensitive, if the buffer
  451          * is full we just dump data until the latest one
  452          * will fit.
  453          */
  454 
  455         while (m->m_pkthdr.len > sbspace(&so->so_rcv))
  456                 sbdroprecord(&so->so_rcv);
  457 
  458         DPRINTFN(10, "received %d bytes\n", m->m_pkthdr.len);
  459 
  460         sbappendrecord(&so->so_rcv, m);
  461         sorwakeup(so);
  462 }
  463 
  464 PR_WRAP_USRREQS(sco)
  465 
  466 #define sco_attach              sco_attach_wrapper
  467 #define sco_detach              sco_detach_wrapper
  468 #define sco_accept              sco_accept_wrapper
  469 #define sco_bind                sco_bind_wrapper
  470 #define sco_listen              sco_listen_wrapper
  471 #define sco_connect             sco_connect_wrapper
  472 #define sco_connect2            sco_connect2_wrapper
  473 #define sco_disconnect          sco_disconnect_wrapper
  474 #define sco_shutdown            sco_shutdown_wrapper
  475 #define sco_abort               sco_abort_wrapper
  476 #define sco_ioctl               sco_ioctl_wrapper
  477 #define sco_stat                sco_stat_wrapper
  478 #define sco_peeraddr            sco_peeraddr_wrapper
  479 #define sco_sockaddr            sco_sockaddr_wrapper
  480 #define sco_rcvd                sco_rcvd_wrapper
  481 #define sco_recvoob             sco_recvoob_wrapper
  482 #define sco_send                sco_send_wrapper
  483 #define sco_sendoob             sco_sendoob_wrapper
  484 #define sco_purgeif             sco_purgeif_wrapper
  485 
  486 const struct pr_usrreqs sco_usrreqs = {
  487         .pr_attach      = sco_attach,
  488         .pr_detach      = sco_detach,
  489         .pr_accept      = sco_accept,
  490         .pr_bind        = sco_bind,
  491         .pr_listen      = sco_listen,
  492         .pr_connect     = sco_connect,
  493         .pr_connect2    = sco_connect2,
  494         .pr_disconnect  = sco_disconnect,
  495         .pr_shutdown    = sco_shutdown,
  496         .pr_abort       = sco_abort,
  497         .pr_ioctl       = sco_ioctl,
  498         .pr_stat        = sco_stat,
  499         .pr_peeraddr    = sco_peeraddr,
  500         .pr_sockaddr    = sco_sockaddr,
  501         .pr_rcvd        = sco_rcvd,
  502         .pr_recvoob     = sco_recvoob,
  503         .pr_send        = sco_send,
  504         .pr_sendoob     = sco_sendoob,
  505         .pr_purgeif     = sco_purgeif,
  506 };

Cache object: 0c68d56bf4ebde6a41b7821802d34f34


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