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/l2cap_upper.c

Version: -  FREEBSD  -  FREEBSD11  -  FREEBSD10  -  FREEBSD9  -  FREEBSD92  -  FREEBSD91  -  FREEBSD90  -  FREEBSD8  -  FREEBSD82  -  FREEBSD81  -  FREEBSD80  -  FREEBSD7  -  FREEBSD74  -  FREEBSD73  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: l2cap_upper.c,v 1.3 2008/11/22 04:42:58 uwe Exp $     */
    2 /*      $NetBSD: l2cap_upper.c,v 1.9 2008/08/06 15:01:24 plunky Exp $   */
    3 
    4 /*-
    5  * Copyright (c) 2005 Iain Hibbert.
    6  * Copyright (c) 2006 Itronix Inc.
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. The name of Itronix Inc. may not be used to endorse
   18  *    or promote products derived from this software without specific
   19  *    prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
   25  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   28  * ON ANY THEORY OF LIABILITY, WHETHER IN
   29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   31  * POSSIBILITY OF SUCH DAMAGE.
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 
   36 #include <sys/param.h>
   37 #include <sys/kernel.h>
   38 #include <sys/mbuf.h>
   39 #include <sys/proc.h>
   40 #include <sys/queue.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/l2cap.h>
   48 
   49 /*******************************************************************************
   50  *
   51  *      L2CAP Channel - Upper Protocol API
   52  */
   53 
   54 /*
   55  * l2cap_attach(handle, btproto, upper)
   56  *
   57  *      attach new l2cap_channel to handle, populate
   58  *      with reasonable defaults
   59  */
   60 int
   61 l2cap_attach(struct l2cap_channel **handle,
   62                 const struct btproto *proto, void *upper)
   63 {
   64         struct l2cap_channel *chan;
   65 
   66         KASSERT(handle != NULL);
   67         KASSERT(proto != NULL);
   68         KASSERT(upper != NULL);
   69 
   70         chan = malloc(sizeof(*chan), M_BLUETOOTH, M_NOWAIT | M_ZERO);
   71         if (chan == NULL)
   72                 return ENOMEM;
   73 
   74         chan->lc_proto = proto;
   75         chan->lc_upper = upper;
   76 
   77         chan->lc_state = L2CAP_CLOSED;
   78 
   79         chan->lc_lcid = L2CAP_NULL_CID;
   80         chan->lc_rcid = L2CAP_NULL_CID;
   81 
   82         chan->lc_laddr.bt_len = sizeof(struct sockaddr_bt);
   83         chan->lc_laddr.bt_family = AF_BLUETOOTH;
   84         chan->lc_laddr.bt_psm = L2CAP_PSM_ANY;
   85 
   86         chan->lc_raddr.bt_len = sizeof(struct sockaddr_bt);
   87         chan->lc_raddr.bt_family = AF_BLUETOOTH;
   88         chan->lc_raddr.bt_psm = L2CAP_PSM_ANY;
   89 
   90         chan->lc_imtu = L2CAP_MTU_DEFAULT;
   91         chan->lc_omtu = L2CAP_MTU_DEFAULT;
   92         chan->lc_flush = L2CAP_FLUSH_TIMO_DEFAULT;
   93 
   94         memcpy(&chan->lc_iqos, &l2cap_default_qos, sizeof(l2cap_qos_t));
   95         memcpy(&chan->lc_oqos, &l2cap_default_qos, sizeof(l2cap_qos_t));
   96 
   97         *handle = chan;
   98         return 0;
   99 }
  100 
  101 /*
  102  * l2cap_bind(l2cap_channel, sockaddr)
  103  *
  104  *      set local address of channel
  105  */
  106 int
  107 l2cap_bind(struct l2cap_channel *chan, struct sockaddr_bt *addr)
  108 {
  109 
  110         memcpy(&chan->lc_laddr, addr, sizeof(struct sockaddr_bt));
  111         return 0;
  112 }
  113 
  114 /*
  115  * l2cap_sockaddr(l2cap_channel, sockaddr)
  116  *
  117  *      get local address of channel
  118  */
  119 int
  120 l2cap_sockaddr(struct l2cap_channel *chan, struct sockaddr_bt *addr)
  121 {
  122 
  123         memcpy(addr, &chan->lc_laddr, sizeof(struct sockaddr_bt));
  124         return 0;
  125 }
  126 
  127 /*
  128  * l2cap_connect(l2cap_channel, sockaddr)
  129  *
  130  *      Initiate a connection to destination. This corresponds to
  131  *      "Open Channel Request" in the L2CAP specification and will
  132  *      result in one of the following:
  133  *
  134  *              proto->connected(upper)
  135  *              proto->disconnected(upper, error)
  136  *
  137  *      and, optionally
  138  *              proto->connecting(upper)
  139  */
  140 int
  141 l2cap_connect(struct l2cap_channel *chan, struct sockaddr_bt *dest)
  142 {
  143         struct hci_unit *unit;
  144         int err;
  145 
  146         memcpy(&chan->lc_raddr, dest, sizeof(struct sockaddr_bt));
  147 
  148         if (L2CAP_PSM_INVALID(chan->lc_raddr.bt_psm))
  149                 return EINVAL;
  150 
  151         if (bdaddr_any(&chan->lc_raddr.bt_bdaddr))
  152                 return EDESTADDRREQ;
  153 
  154         /* set local address if it needs setting */
  155         if (bdaddr_any(&chan->lc_laddr.bt_bdaddr)) {
  156                 err = hci_route_lookup(&chan->lc_laddr.bt_bdaddr,
  157                                         &chan->lc_raddr.bt_bdaddr);
  158                 if (err)
  159                         return err;
  160         }
  161 
  162         unit = hci_unit_lookup(&chan->lc_laddr.bt_bdaddr);
  163         if (unit == NULL)
  164                 return EHOSTUNREACH;
  165 
  166         /* attach to active list */
  167         err = l2cap_cid_alloc(chan);
  168         if (err)
  169                 return err;
  170 
  171         /* open link to remote device */
  172         chan->lc_link = hci_acl_open(unit, &chan->lc_raddr.bt_bdaddr);
  173         if (chan->lc_link == NULL)
  174                 return EHOSTUNREACH;
  175 
  176         /* set the link mode */
  177         err = l2cap_setmode(chan);
  178         if (err == EINPROGRESS) {
  179                 chan->lc_state = L2CAP_WAIT_SEND_CONNECT_REQ;
  180                 (*chan->lc_proto->connecting)(chan->lc_upper);
  181                 return 0;
  182         }
  183         if (err)
  184                 goto fail;
  185 
  186         /*
  187          * We can queue a connect request now even though the link may
  188          * not yet be open; Our mode setting is assured, and the queue
  189          * will be started automatically at the right time.
  190          */
  191         chan->lc_state = L2CAP_WAIT_RECV_CONNECT_RSP;
  192         err = l2cap_send_connect_req(chan);
  193         if (err)
  194                 goto fail;
  195 
  196         return 0;
  197 
  198 fail:
  199         chan->lc_state = L2CAP_CLOSED;
  200         hci_acl_close(chan->lc_link, err);
  201         chan->lc_link = NULL;
  202         return err;
  203 }
  204 
  205 /*
  206  * l2cap_peeraddr(l2cap_channel, sockaddr)
  207  *
  208  *      get remote address of channel
  209  */
  210 int
  211 l2cap_peeraddr(struct l2cap_channel *chan, struct sockaddr_bt *addr)
  212 {
  213 
  214         memcpy(addr, &chan->lc_raddr, sizeof(struct sockaddr_bt));
  215         return 0;
  216 }
  217 
  218 /*
  219  * l2cap_disconnect(l2cap_channel, linger)
  220  *
  221  *      Initiate L2CAP disconnection. This corresponds to
  222  *      "Close Channel Request" in the L2CAP specification
  223  *      and will result in a call to
  224  *
  225  *              proto->disconnected(upper, error)
  226  *
  227  *      when the disconnection is complete. If linger is set,
  228  *      the call will not be made until data has flushed from
  229  *      the queue.
  230  */
  231 int
  232 l2cap_disconnect(struct l2cap_channel *chan, int linger)
  233 {
  234         int err = 0;
  235 
  236         if (chan->lc_state == L2CAP_CLOSED
  237             || chan->lc_state == L2CAP_WAIT_DISCONNECT)
  238                 return EINVAL;
  239 
  240         chan->lc_flags |= L2CAP_SHUTDOWN;
  241 
  242         /*
  243          * no need to do anything unless the queue is empty or
  244          * we are not lingering..
  245          */
  246         if ((IF_IS_EMPTY(&chan->lc_txq) && chan->lc_pending == 0)
  247             || linger == 0) {
  248                 chan->lc_state = L2CAP_WAIT_DISCONNECT;
  249                 err = l2cap_send_disconnect_req(chan);
  250                 if (err)
  251                         l2cap_close(chan, err);
  252         }
  253         return err;
  254 }
  255 
  256 /*
  257  * l2cap_detach(handle)
  258  *
  259  *      Detach l2cap channel from handle & close it down
  260  */
  261 int
  262 l2cap_detach(struct l2cap_channel **handle)
  263 {
  264         struct l2cap_channel *chan;
  265 
  266         chan = *handle;
  267         *handle = NULL;
  268 
  269         if (chan->lc_state != L2CAP_CLOSED)
  270                 l2cap_close(chan, 0);
  271 
  272         if (chan->lc_lcid != L2CAP_NULL_CID) {
  273                 LIST_REMOVE(chan, lc_ncid);
  274                 chan->lc_lcid = L2CAP_NULL_CID;
  275         }
  276 
  277         IF_PURGE(&chan->lc_txq);
  278 
  279         /*
  280          * Could implement some kind of delayed expunge to make sure that the
  281          * CID is really dead before it becomes available for reuse?
  282          */
  283 
  284         free(chan, M_BLUETOOTH);
  285         return 0;
  286 }
  287 
  288 /*
  289  * l2cap_listen(l2cap_channel)
  290  *
  291  *      Use this channel as a listening post (until detached). This will
  292  *      result in calls to:
  293  *
  294  *              proto->newconn(upper, laddr, raddr)
  295  *
  296  *      for incoming connections matching the psm and local address of the
  297  *      channel (NULL psm/address are permitted and match any protocol/device).
  298  *
  299  *      The upper layer should create and return a new channel.
  300  *
  301  *      You cannot use this channel for anything else subsequent to this call
  302  */
  303 int
  304 l2cap_listen(struct l2cap_channel *chan)
  305 {
  306         struct l2cap_channel *used, *prev = NULL;
  307 
  308         if (chan->lc_lcid != L2CAP_NULL_CID)
  309                 return EINVAL;
  310 
  311         if (chan->lc_laddr.bt_psm != L2CAP_PSM_ANY
  312             && L2CAP_PSM_INVALID(chan->lc_laddr.bt_psm))
  313                 return EADDRNOTAVAIL;
  314 
  315         /*
  316          * This CID is irrelevant, as the channel is not stored on the active
  317          * list and the socket code does not allow operations on listening
  318          * sockets, but we set it so the detach code knows to LIST_REMOVE the
  319          * channel.
  320          */
  321         chan->lc_lcid = L2CAP_SIGNAL_CID;
  322 
  323         /*
  324          * The list of listening channels is stored in an order such that new
  325          * listeners dont usurp current listeners, but that specific listening
  326          * takes precedence over promiscuous, and the connect request code can
  327          * easily use the first matching entry.
  328          */
  329         LIST_FOREACH(used, &l2cap_listen_list, lc_ncid) {
  330                 if (used->lc_laddr.bt_psm < chan->lc_laddr.bt_psm)
  331                         break;
  332 
  333                 if (used->lc_laddr.bt_psm == chan->lc_laddr.bt_psm
  334                         && bdaddr_any(&used->lc_laddr.bt_bdaddr)
  335                         && !bdaddr_any(&chan->lc_laddr.bt_bdaddr))
  336                         break;
  337 
  338                 prev = used;
  339         }
  340 
  341         if (prev == NULL)
  342                 LIST_INSERT_HEAD(&l2cap_listen_list, chan, lc_ncid);
  343         else
  344                 LIST_INSERT_AFTER(prev, chan, lc_ncid);
  345 
  346         return 0;
  347 }
  348 
  349 /*
  350  * l2cap_send(l2cap_channel, mbuf)
  351  *
  352  *      Output SDU on channel described by channel. This corresponds
  353  *      to "Send Data Request" in the L2CAP specification. The upper
  354  *      layer will be notified when SDU's have completed sending by a
  355  *      call to:
  356  *
  357  *              proto->complete(upper, n)
  358  *
  359  *      (currently n == 1)
  360  *
  361  *      Note: I'm not sure how this will work out, but I think that
  362  *      if outgoing Retransmission Mode or Flow Control Mode is
  363  *      negotiated then this call will not be made until the SDU has
  364  *      been acknowleged by the peer L2CAP entity. For 'Best Effort'
  365  *      it will be made when the packet has cleared the controller
  366  *      buffers.
  367  *
  368  *      We only support Basic mode so far, so encapsulate with a
  369  *      B-Frame header and start sending if we are not already
  370  */
  371 int
  372 l2cap_send(struct l2cap_channel *chan, struct mbuf *m)
  373 {
  374         l2cap_hdr_t *hdr;
  375         int plen;
  376 
  377         if (chan->lc_state == L2CAP_CLOSED) {
  378                 m_freem(m);
  379                 return ENOTCONN;
  380         }
  381 
  382         plen = m->m_pkthdr.len;
  383 
  384         DPRINTFN(5, "send %d bytes on CID #%d (pending = %d)\n",
  385                 plen, chan->lc_lcid, chan->lc_pending);
  386 
  387         /* Encapsulate with B-Frame */
  388         M_PREPEND(m, sizeof(l2cap_hdr_t), M_DONTWAIT);
  389         if (m == NULL)
  390                 return ENOMEM;
  391 
  392         hdr = mtod(m, l2cap_hdr_t *);
  393         hdr->length = htole16(plen);
  394         hdr->dcid = htole16(chan->lc_rcid);
  395 
  396         /* Queue it on our list */
  397         IF_ENQUEUE(&chan->lc_txq, m);
  398 
  399         /* If we are not sending, then start doing so */
  400         if (chan->lc_pending == 0)
  401                 return l2cap_start(chan);
  402 
  403         return 0;
  404 }
  405 
  406 /*
  407  * l2cap_setopt(l2cap_channel, opt, addr)
  408  *
  409  *      Apply configuration options to channel. This corresponds to
  410  *      "Configure Channel Request" in the L2CAP specification.
  411  *
  412  *      for SO_L2CAP_LM, the settings will take effect when the
  413  *      channel is established. If the channel is already open,
  414  *      a call to
  415  *              proto->linkmode(upper, new)
  416  *
  417  *      will be made when the change is complete.
  418  */
  419 int
  420 l2cap_setopt(struct l2cap_channel *chan, int opt, void *addr)
  421 {
  422         int mode, err = 0;
  423         uint16_t mtu;
  424 
  425         switch (opt) {
  426         case SO_L2CAP_IMTU:     /* set Incoming MTU */
  427                 mtu = *(uint16_t *)addr;
  428                 if (mtu < L2CAP_MTU_MINIMUM)
  429                         err = EINVAL;
  430                 else if (chan->lc_state == L2CAP_CLOSED)
  431                         chan->lc_imtu = mtu;
  432                 else
  433                         err = EBUSY;
  434 
  435                 break;
  436 
  437         case SO_L2CAP_LM:       /* set link mode */
  438                 mode = *(int *)addr;
  439                 mode &= (L2CAP_LM_SECURE | L2CAP_LM_ENCRYPT | L2CAP_LM_AUTH);
  440 
  441                 if (mode & L2CAP_LM_SECURE)
  442                         mode |= L2CAP_LM_ENCRYPT;
  443 
  444                 if (mode & L2CAP_LM_ENCRYPT)
  445                         mode |= L2CAP_LM_AUTH;
  446 
  447                 chan->lc_mode = mode;
  448 
  449                 if (chan->lc_state == L2CAP_OPEN)
  450                         err = l2cap_setmode(chan);
  451 
  452                 break;
  453 
  454         case SO_L2CAP_OQOS:     /* set Outgoing QoS flow spec */
  455         case SO_L2CAP_FLUSH:    /* set Outgoing Flush Timeout */
  456         default:
  457                 err = ENOPROTOOPT;
  458                 break;
  459         }
  460 
  461         return err;
  462 }
  463 
  464 /*
  465  * l2cap_getopt(l2cap_channel, opt, addr)
  466  *
  467  *      Return configuration parameters.
  468  */
  469 int
  470 l2cap_getopt(struct l2cap_channel *chan, int opt, void *addr)
  471 {
  472 
  473         switch (opt) {
  474         case SO_L2CAP_IMTU:     /* get Incoming MTU */
  475                 *(uint16_t *)addr = chan->lc_imtu;
  476                 return sizeof(uint16_t);
  477 
  478         case SO_L2CAP_OMTU:     /* get Outgoing MTU */
  479                 *(uint16_t *)addr = chan->lc_omtu;
  480                 return sizeof(uint16_t);
  481 
  482         case SO_L2CAP_IQOS:     /* get Incoming QoS flow spec */
  483                 memcpy(addr, &chan->lc_iqos, sizeof(l2cap_qos_t));
  484                 return sizeof(l2cap_qos_t);
  485 
  486         case SO_L2CAP_OQOS:     /* get Outgoing QoS flow spec */
  487                 memcpy(addr, &chan->lc_oqos, sizeof(l2cap_qos_t));
  488                 return sizeof(l2cap_qos_t);
  489 
  490         case SO_L2CAP_FLUSH:    /* get Flush Timeout */
  491                 *(uint16_t *)addr = chan->lc_flush;
  492                 return sizeof(uint16_t);
  493 
  494         case SO_L2CAP_LM:       /* get link mode */
  495                 *(int *)addr = chan->lc_mode;
  496                 return sizeof(int);
  497 
  498         default:
  499                 break;
  500         }
  501 
  502         return 0;
  503 }

Cache object: 3aeb4aa18bd8c7ac59dbb1e8896679ab


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