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 /*-
    2  * Copyright (c) 2006 Itronix Inc.
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. The name of Itronix Inc. may not be used to endorse
   14  *    or promote products derived from this software without specific
   15  *    prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
   21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   24  * ON ANY THEORY OF LIABILITY, WHETHER IN
   25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   27  * POSSIBILITY OF SUCH DAMAGE.
   28  *
   29  * $OpenBSD: sco_socket.c,v 1.1 2007/06/01 02:46:12 uwe Exp $
   30  * $NetBSD: sco_socket.c,v 1.9 2007/04/21 06:15:23 plunky Exp $
   31  */
   32 
   33 /* load symbolic names */
   34 #ifdef BLUETOOTH_DEBUG
   35 #define PRUREQUESTS
   36 #define PRCOREQUESTS
   37 #endif
   38 
   39 #include <sys/param.h>
   40 #include <sys/domain.h>
   41 #include <sys/kernel.h>
   42 #include <sys/mbuf.h>
   43 #include <sys/proc.h>
   44 #include <sys/protosw.h>
   45 #include <sys/socket.h>
   46 #include <sys/socketvar.h>
   47 #include <sys/systm.h>
   48 #include <sys/bus.h>
   49 
   50 #include <sys/msgport2.h>
   51 
   52 #include <netbt/bluetooth.h>
   53 #include <netbt/hci.h>
   54 #include <netbt/sco.h>
   55 
   56 /*******************************************************************************
   57  *
   58  * SCO SOCK_SEQPACKET sockets - low latency audio data
   59  */
   60 
   61 static void sco_connecting(void *);
   62 static void sco_connected(void *);
   63 static void sco_disconnected(void *, int);
   64 static void *sco_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *);
   65 static void sco_complete(void *, int);
   66 static void sco_linkmode(void *, int);
   67 static void sco_input(void *, struct mbuf *);
   68 
   69 static const struct btproto sco_proto = {
   70         sco_connecting,
   71         sco_connected,
   72         sco_disconnected,
   73         sco_newconn,
   74         sco_complete,
   75         sco_linkmode,
   76         sco_input,
   77 };
   78 
   79 int sco_sendspace = 4096;
   80 int sco_recvspace = 4096;
   81 
   82 /*
   83  * get/set socket options
   84  */
   85 void
   86 sco_ctloutput(netmsg_t msg)
   87 {
   88         struct socket *so = msg->ctloutput.base.nm_so;
   89         struct sockopt *sopt = msg->ctloutput.nm_sopt;
   90         struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
   91         struct mbuf *m;
   92         int err = 0;
   93 
   94 #ifdef notyet                   /* XXX */
   95         DPRINTFN(2, "req %s\n", prcorequests[req]);
   96 #endif
   97 
   98         if (pcb == NULL) {
   99                 err = EINVAL;
  100                 goto out;
  101         }
  102 
  103         if (sopt->sopt_level != BTPROTO_SCO) {
  104                 err = ENOPROTOOPT;
  105                 goto out;
  106         }
  107 
  108         switch(sopt->sopt_dir) {
  109         case PRCO_GETOPT:
  110                 m = m_get(MB_WAIT, MT_DATA);
  111                 m->m_len = sco_getopt(pcb, sopt->sopt_name, mtod(m, uint8_t *));
  112                 if (m->m_len == 0) {
  113                         m_freem(m);
  114                         m = NULL;
  115                         err = ENOPROTOOPT;
  116                 }
  117                 /* *opt = m; */
  118                 /* XXX There are possible memory leaks (Griffin) */
  119                 soopt_from_kbuf(sopt, mtod(m, void *), m->m_len);
  120                 break;
  121 
  122         case PRCO_SETOPT:
  123                 m = m_get(M_WAITOK, MT_DATA);
  124                 KKASSERT(m != NULL);
  125                 err = soopt_to_kbuf(sopt, mtod(m,void*), m->m_len, m->m_len); 
  126 
  127                 if (m->m_len == 0) {
  128                         m_freem(m);
  129                         m = NULL;
  130                         err = EIO;
  131                 }
  132 
  133                 err = sco_setopt(pcb, sopt->sopt_name, mtod(m, uint8_t *));
  134                 m_freem(m);
  135                 break;
  136 
  137         default:
  138                 err = ENOPROTOOPT;
  139                 break;
  140         }
  141 out:
  142         lwkt_replymsg(&msg->ctloutput.base.lmsg, err);
  143 }
  144 
  145 /*****************************************************************************
  146  *
  147  *      SCO Protocol socket callbacks
  148  *
  149  */
  150 static void
  151 sco_connecting(void *arg)
  152 {
  153         struct socket *so = arg;
  154 
  155         DPRINTF("Connecting\n");
  156         soisconnecting(so);
  157 }
  158 
  159 static void
  160 sco_connected(void *arg)
  161 {
  162         struct socket *so = arg;
  163 
  164         DPRINTF("Connected\n");
  165         soisconnected(so);
  166 }
  167 
  168 static void
  169 sco_disconnected(void *arg, int err)
  170 {
  171         struct socket *so = arg;
  172 
  173         DPRINTF("Disconnected (%d)\n", err);
  174 
  175         so->so_error = err;
  176         soisdisconnected(so);
  177 }
  178 
  179 static void *
  180 sco_newconn(void *arg, struct sockaddr_bt *laddr,
  181     struct sockaddr_bt *raddr)
  182 {
  183         struct socket *so = arg;
  184 
  185         DPRINTF("New Connection\n");
  186         so = sonewconn(so, 0);
  187         if (so == NULL)
  188                 return NULL;
  189 
  190         soisconnecting(so);
  191         return so->so_pcb;
  192 }
  193 
  194 static void
  195 sco_complete(void *arg, int num)
  196 {
  197         struct socket *so = arg;
  198 
  199         while (num-- > 0)
  200                 sbdroprecord(&so->so_snd.sb);
  201 
  202         sowwakeup(so);
  203 }
  204 
  205 static void
  206 sco_linkmode(void *arg, int mode)
  207 {
  208 }
  209 
  210 static void
  211 sco_input(void *arg, struct mbuf *m)
  212 {
  213         struct socket *so = arg;
  214 
  215         /*
  216          * since this data is time sensitive, if the buffer
  217          * is full we just dump data until the latest one
  218          * will fit.
  219          */
  220 
  221         while (m->m_pkthdr.len > sbspace(&so->so_rcv))
  222                 sbdroprecord(&so->so_rcv.sb);
  223 
  224         DPRINTFN(10, "received %d bytes\n", m->m_pkthdr.len);
  225 
  226         sbappendrecord(&so->so_rcv.sb, m);
  227         sorwakeup(so);
  228 }
  229 
  230 /*
  231  * Implementation of usrreqs.
  232  */
  233 static void
  234 sco_sdetach(netmsg_t msg)
  235 {
  236         struct socket *so = msg->detach.base.nm_so;
  237         int error;
  238 
  239         error = sco_detach((struct sco_pcb **)&so->so_pcb);
  240         lwkt_replymsg(&msg->detach.base.lmsg, error);
  241 }
  242 
  243 /*
  244  * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
  245  *       will sofree() it when we return.
  246  */
  247 static void
  248 sco_sabort (netmsg_t msg)
  249 {
  250         struct socket *so = msg->abort.base.nm_so;
  251         struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
  252 
  253         sco_disconnect(pcb, 0);
  254         soisdisconnected(so);
  255         sco_sdetach(msg);
  256         /* msg invalid now */
  257 }
  258 
  259 static void
  260 sco_sdisconnect (netmsg_t msg)
  261 {
  262         struct socket *so = msg->abort.base.nm_so;
  263         struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
  264         int error;
  265 
  266         soisdisconnecting(so);
  267 
  268         error = sco_disconnect(pcb, so->so_linger);
  269         lwkt_replymsg(&msg->disconnect.base.lmsg, error);
  270 }
  271 
  272 static void
  273 sco_sattach(netmsg_t msg)
  274 {
  275         struct socket *so = msg->attach.base.nm_so;
  276         struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
  277         int error;
  278 
  279         if (pcb) {
  280                 error = EINVAL;
  281         } else {
  282                 error = soreserve(so, sco_sendspace, sco_recvspace,NULL);
  283                 if (error == 0) {
  284                         error = sco_attach((struct sco_pcb **)&so->so_pcb,
  285                                            &sco_proto, so);
  286                 }
  287         }
  288         lwkt_replymsg(&msg->attach.base.lmsg, error);
  289 }
  290 
  291 static void
  292 sco_sbind(netmsg_t msg)
  293 {
  294         struct socket *so = msg->bind.base.nm_so;
  295         struct sockaddr *nam = msg->bind.nm_nam;
  296         struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
  297         struct sockaddr_bt *sa;
  298         int error;
  299 
  300         KKASSERT(nam != NULL);
  301         sa = (struct sockaddr_bt *)nam;
  302 
  303         if (sa->bt_len != sizeof(struct sockaddr_bt)) {
  304                 error = EINVAL;
  305         } else if (sa->bt_family != AF_BLUETOOTH) {
  306                 error = EAFNOSUPPORT;
  307         } else {
  308                 error = sco_bind(pcb, sa);
  309         }
  310         lwkt_replymsg(&msg->bind.base.lmsg, error);
  311 }
  312 
  313 static void
  314 sco_sconnect(netmsg_t msg)
  315 {
  316         struct socket *so = msg->connect.base.nm_so;
  317         struct sockaddr *nam = msg->connect.nm_nam;
  318         struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
  319         struct sockaddr_bt *sa;
  320         int error;
  321 
  322         KKASSERT(nam != NULL);
  323         sa = (struct sockaddr_bt *)nam;
  324 
  325         if (sa->bt_len != sizeof(struct sockaddr_bt)) {
  326                 error = EINVAL;
  327         } else if (sa->bt_family != AF_BLUETOOTH) {
  328                 error = EAFNOSUPPORT;
  329         } else {
  330                 soisconnecting(so);
  331                 error = sco_connect(pcb, sa);
  332         }
  333         lwkt_replymsg(&msg->connect.base.lmsg, error);
  334 }
  335 
  336 static void
  337 sco_speeraddr(netmsg_t msg)
  338 {
  339         struct socket *so = msg->peeraddr.base.nm_so;
  340         struct sockaddr **nam = msg->peeraddr.nm_nam;
  341         struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
  342         struct sockaddr_bt *sa, ssa;
  343         int error;
  344 
  345         sa = &ssa;
  346         bzero(sa, sizeof *sa);
  347         sa->bt_len = sizeof(struct sockaddr_bt);
  348         sa->bt_family = AF_BLUETOOTH;
  349         error = sco_peeraddr(pcb, sa);
  350         *nam = dup_sockaddr((struct sockaddr *)sa);
  351         lwkt_replymsg(&msg->peeraddr.base.lmsg, error);
  352 }
  353 
  354 static void
  355 sco_ssockaddr(netmsg_t msg)
  356 {
  357         struct socket *so = msg->sockaddr.base.nm_so;
  358         struct sockaddr **nam = msg->sockaddr.nm_nam;
  359         struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
  360         struct sockaddr_bt *sa, ssa;
  361         int error;
  362 
  363         sa = &ssa;
  364         bzero(sa, sizeof *sa);
  365         sa->bt_len = sizeof(struct sockaddr_bt);
  366         sa->bt_family = AF_BLUETOOTH;
  367         error = sco_sockaddr(pcb, sa);
  368         *nam = dup_sockaddr((struct sockaddr *)sa);
  369 
  370         lwkt_replymsg(&msg->sockaddr.base.lmsg, error);
  371 }
  372 
  373 static void
  374 sco_sshutdown(netmsg_t msg)
  375 {
  376         socantsendmore(msg->shutdown.base.nm_so);
  377         lwkt_replymsg(&msg->shutdown.base.lmsg, 0);
  378 }
  379 
  380 static void
  381 sco_ssend(netmsg_t msg)
  382 {
  383         struct socket *so = msg->send.base.nm_so;
  384         struct mbuf *m = msg->send.nm_m;
  385         struct mbuf *control = msg->send.nm_control;
  386         struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
  387         struct mbuf *m0;
  388         int error = 0;
  389 
  390         KKASSERT(m != NULL);
  391         if (m->m_pkthdr.len == 0)
  392                 goto out;
  393 
  394         if (m->m_pkthdr.len > pcb->sp_mtu) {
  395                 error = EMSGSIZE;
  396                 goto out;
  397         }
  398 
  399         m0 = m_copym(m, 0, M_COPYALL, MB_DONTWAIT);
  400         if (m0 == NULL) {
  401                 error = ENOMEM;
  402                 goto out;
  403         }
  404 
  405         /* no use for that */
  406         if (control) {
  407                 m_freem(control);
  408                 control = NULL;
  409         }
  410 
  411         sbappendrecord(&so->so_snd.sb, m);
  412         error = sco_send(pcb, m0);
  413         m = NULL;
  414 out:
  415         if (m)
  416                 m_freem(m);
  417         if (control)
  418                 m_freem(control);
  419         lwkt_replymsg(&msg->send.base.lmsg, error);
  420 }
  421 
  422 static void
  423 sco_saccept(netmsg_t msg)
  424 {
  425         struct socket *so = msg->accept.base.nm_so;
  426         struct sockaddr **nam = msg->accept.nm_nam;
  427         struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
  428         struct sockaddr_bt *sa, ssa;
  429         int error;
  430 
  431         sa = &ssa;
  432         bzero(sa, sizeof *sa);
  433         sa->bt_len = sizeof(struct sockaddr_bt);
  434         sa->bt_family = AF_BLUETOOTH;
  435         error = sco_peeraddr(pcb, sa);
  436         *nam = dup_sockaddr((struct sockaddr *)sa);
  437 
  438         lwkt_replymsg(&msg->accept.base.lmsg, error);
  439 }
  440 
  441 static void
  442 sco_slisten(netmsg_t msg)
  443 {
  444         struct socket *so = msg->listen.base.nm_so;
  445         struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb;
  446         int error;
  447 
  448         error = sco_listen(pcb);
  449         lwkt_replymsg(&msg->accept.base.lmsg, error);
  450 }
  451 
  452 struct pr_usrreqs sco_usrreqs = {
  453         .pru_abort = sco_sabort,
  454         .pru_accept = sco_saccept,
  455         .pru_attach = sco_sattach,
  456         .pru_bind = sco_sbind,
  457         .pru_connect = sco_sconnect,
  458         .pru_connect2 = pr_generic_notsupp,
  459         .pru_control = pr_generic_notsupp,
  460         .pru_detach = sco_sdetach,
  461         .pru_disconnect = sco_sdisconnect,
  462         .pru_listen = sco_slisten,
  463         .pru_peeraddr = sco_speeraddr,
  464         .pru_rcvd = pr_generic_notsupp,
  465         .pru_rcvoob = pr_generic_notsupp,
  466         .pru_send = sco_ssend,
  467         .pru_sense = pru_sense_null,
  468         .pru_shutdown = sco_sshutdown,
  469         .pru_sockaddr = sco_ssockaddr,
  470         .pru_sosend = sosend,
  471         .pru_soreceive = soreceive
  472 };

Cache object: 535093ac337209825c955809706fe62f


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