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/hci_ioctl.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: hci_ioctl.c,v 1.7 2007/11/28 20:16:12 plunky Exp $     */
    2 
    3 /*-
    4  * Copyright (c) 2005 Iain Hibbert.
    5  * Copyright (c) 2006 Itronix Inc.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. The name of Itronix Inc. may not be used to endorse
   17  *    or promote products derived from this software without specific
   18  *    prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
   24  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   25  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   26  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   27  * ON ANY THEORY OF LIABILITY, WHETHER IN
   28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   30  * POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __KERNEL_RCSID(0, "$NetBSD: hci_ioctl.c,v 1.7 2007/11/28 20:16:12 plunky Exp $");
   35 
   36 #include <sys/param.h>
   37 #include <sys/domain.h>
   38 #include <sys/ioctl.h>
   39 #include <sys/kauth.h>
   40 #include <sys/kernel.h>
   41 #include <sys/mbuf.h>
   42 #include <sys/proc.h>
   43 #include <sys/systm.h>
   44 
   45 #include <netbt/bluetooth.h>
   46 #include <netbt/hci.h>
   47 #include <netbt/l2cap.h>
   48 #include <netbt/rfcomm.h>
   49 
   50 #ifdef BLUETOOTH_DEBUG
   51 #define BDADDR(bd)      (bd).b[5], (bd).b[4], (bd).b[3],        \
   52                         (bd).b[2], (bd).b[1], (bd).b[0]
   53 
   54 static void
   55 hci_dump(void)
   56 {
   57         struct hci_unit *unit;
   58         struct hci_link *link;
   59         struct l2cap_channel *chan;
   60         struct rfcomm_session *rs;
   61         struct rfcomm_dlc *dlc;
   62 
   63         uprintf("HCI:\n");
   64         SIMPLEQ_FOREACH(unit, &hci_unit_list, hci_next) {
   65                 uprintf("UNIT %s: flags 0x%4.4x, "
   66                         "num_cmd=%d, num_acl=%d, num_sco=%d\n",
   67                         device_xname(unit->hci_dev), unit->hci_flags,
   68                         unit->hci_num_cmd_pkts,
   69                         unit->hci_num_acl_pkts,
   70                         unit->hci_num_sco_pkts);
   71                 TAILQ_FOREACH(link, &unit->hci_links, hl_next) {
   72                         uprintf("+HANDLE #%d: %s "
   73                             "raddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
   74                             "state %d, refcnt %d\n",
   75                             link->hl_handle,
   76                             (link->hl_type == HCI_LINK_ACL ? "ACL":"SCO"),
   77                             BDADDR(link->hl_bdaddr),
   78                             link->hl_state, link->hl_refcnt);
   79                 }
   80         }
   81 
   82         uprintf("L2CAP:\n");
   83         LIST_FOREACH(chan, &l2cap_active_list, lc_ncid) {
   84                 uprintf("CID #%d state %d, psm=0x%4.4x, "
   85                     "laddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
   86                     "raddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
   87                     chan->lc_lcid, chan->lc_state, chan->lc_raddr.bt_psm,
   88                     BDADDR(chan->lc_laddr.bt_bdaddr),
   89                     BDADDR(chan->lc_raddr.bt_bdaddr));
   90         }
   91 
   92         LIST_FOREACH(chan, &l2cap_listen_list, lc_ncid) {
   93                 uprintf("LISTEN psm=0x%4.4x, "
   94                     "laddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
   95                     chan->lc_laddr.bt_psm,
   96                     BDADDR(chan->lc_laddr.bt_bdaddr));
   97         }
   98 
   99         uprintf("RFCOMM:\n");
  100         LIST_FOREACH(rs, &rfcomm_session_active, rs_next) {
  101                 chan = rs->rs_l2cap;
  102                 uprintf("SESSION: state=%d, flags=0x%4.4x, psm 0x%4.4x "
  103                     "laddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
  104                     "raddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
  105                     rs->rs_state, rs->rs_flags, chan->lc_raddr.bt_psm,
  106                     BDADDR(chan->lc_laddr.bt_bdaddr),
  107                     BDADDR(chan->lc_raddr.bt_bdaddr));
  108                 LIST_FOREACH(dlc, &rs->rs_dlcs, rd_next) {
  109                         uprintf("+DLC channel=%d, dlci=%d, "
  110                             "state=%d, flags=0x%4.4x, rxcred=%d, rxsize=%ld, "
  111                             "txcred=%d, pending=%d, txqlen=%d\n",
  112                             dlc->rd_raddr.bt_channel, dlc->rd_dlci,
  113                             dlc->rd_state, dlc->rd_flags,
  114                             dlc->rd_rxcred, (unsigned long)dlc->rd_rxsize,
  115                             dlc->rd_txcred, dlc->rd_pending,
  116                             (dlc->rd_txbuf ? dlc->rd_txbuf->m_pkthdr.len : 0));
  117                 }
  118         }
  119 
  120         LIST_FOREACH(rs, &rfcomm_session_listen, rs_next) {
  121                 chan = rs->rs_l2cap;
  122                 uprintf("LISTEN: psm 0x%4.4x, "
  123                     "laddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
  124                     chan->lc_laddr.bt_psm,
  125                     BDADDR(chan->lc_laddr.bt_bdaddr));
  126                 LIST_FOREACH(dlc, &rs->rs_dlcs, rd_next)
  127                         uprintf("+DLC channel=%d\n", dlc->rd_laddr.bt_channel);
  128         }
  129 }
  130 
  131 #undef BDADDR
  132 #endif
  133 
  134 int
  135 hci_ioctl(unsigned long cmd, void *data, struct lwp *l)
  136 {
  137         struct btreq *btr = data;
  138         struct hci_unit *unit;
  139         int err = 0;
  140 
  141         DPRINTFN(1, "cmd %#lx\n", cmd);
  142 
  143         switch(cmd) {
  144 #ifdef BLUETOOTH_DEBUG
  145         case SIOCBTDUMP:
  146                 hci_dump();
  147                 return 0;
  148 #endif
  149         /*
  150          * Get unit info based on address rather than name
  151          */
  152         case SIOCGBTINFOA:
  153                 unit = hci_unit_lookup(&btr->btr_bdaddr);
  154                 if (unit == NULL)
  155                         return ENXIO;
  156 
  157                 break;
  158 
  159         /*
  160          * The remaining ioctl's all use the same btreq structure and
  161          * index on the name of the device, so we look that up first.
  162          */
  163         case SIOCNBTINFO:
  164                 /* empty name means give the first unit */
  165                 if (btr->btr_name[0] == '\0') {
  166                         unit = NULL;
  167                         break;
  168                 }
  169 
  170                 /* else fall through and look it up */
  171         case SIOCGBTINFO:
  172         case SIOCSBTFLAGS:
  173         case SIOCSBTPOLICY:
  174         case SIOCSBTPTYPE:
  175         case SIOCGBTSTATS:
  176         case SIOCZBTSTATS:
  177         case SIOCSBTSCOMTU:
  178                 SIMPLEQ_FOREACH(unit, &hci_unit_list, hci_next) {
  179                         if (strncmp(device_xname(unit->hci_dev),
  180                             btr->btr_name, HCI_DEVNAME_SIZE) == 0)
  181                                 break;
  182                 }
  183 
  184                 if (unit == NULL)
  185                         return ENXIO;
  186 
  187                 break;
  188 
  189         default:        /* not one of mine */
  190                 return EPASSTHROUGH;
  191         }
  192 
  193         switch(cmd) {
  194         case SIOCNBTINFO:       /* get next info */
  195                 if (unit)
  196                         unit = SIMPLEQ_NEXT(unit, hci_next);
  197                 else
  198                         unit = SIMPLEQ_FIRST(&hci_unit_list);
  199 
  200                 if (unit == NULL) {
  201                         err = ENXIO;
  202                         break;
  203                 }
  204 
  205                 /* and fall through to */
  206         case SIOCGBTINFO:       /* get unit info */
  207         case SIOCGBTINFOA:      /* get info by address */
  208                 memset(btr, 0, sizeof(struct btreq));
  209                 strlcpy(btr->btr_name, device_xname(unit->hci_dev), HCI_DEVNAME_SIZE);
  210                 bdaddr_copy(&btr->btr_bdaddr, &unit->hci_bdaddr);
  211 
  212                 btr->btr_flags = unit->hci_flags;
  213 
  214                 btr->btr_num_cmd = unit->hci_num_cmd_pkts;
  215                 btr->btr_num_acl = unit->hci_num_acl_pkts;
  216                 btr->btr_num_sco = unit->hci_num_sco_pkts;
  217                 btr->btr_acl_mtu = unit->hci_max_acl_size;
  218                 btr->btr_sco_mtu = unit->hci_max_sco_size;
  219 
  220                 btr->btr_packet_type = unit->hci_packet_type;
  221                 btr->btr_link_policy = unit->hci_link_policy;
  222                 break;
  223 
  224         case SIOCSBTFLAGS:      /* set unit flags (privileged) */
  225                 err = kauth_authorize_generic(l->l_cred,
  226                     KAUTH_GENERIC_ISSUSER, NULL);
  227                 if (err)
  228                         break;
  229 
  230                 if ((unit->hci_flags & BTF_UP)
  231                     && (btr->btr_flags & BTF_UP) == 0) {
  232                         hci_disable(unit);
  233                         unit->hci_flags &= ~BTF_UP;
  234                 }
  235 
  236                 unit->hci_flags |= (btr->btr_flags & BTF_INIT);
  237 
  238                 if ((unit->hci_flags & BTF_UP) == 0
  239                     && (btr->btr_flags & BTF_UP)) {
  240                         err = hci_enable(unit);
  241                         if (err)
  242                                 break;
  243 
  244                         unit->hci_flags |= BTF_UP;
  245                 }
  246 
  247                 btr->btr_flags = unit->hci_flags;
  248                 break;
  249 
  250         case SIOCSBTPOLICY:     /* set unit link policy (privileged) */
  251                 err = kauth_authorize_generic(l->l_cred,
  252                     KAUTH_GENERIC_ISSUSER, NULL);
  253                 if (err)
  254                         break;
  255 
  256                 unit->hci_link_policy = btr->btr_link_policy;
  257                 unit->hci_link_policy &= unit->hci_lmp_mask;
  258                 btr->btr_link_policy = unit->hci_link_policy;
  259                 break;
  260 
  261         case SIOCSBTPTYPE:      /* set unit packet types (privileged) */
  262                 err = kauth_authorize_generic(l->l_cred,
  263                     KAUTH_GENERIC_ISSUSER, NULL);
  264                 if (err)
  265                         break;
  266 
  267                 unit->hci_packet_type = btr->btr_packet_type;
  268                 unit->hci_packet_type &= unit->hci_acl_mask;
  269                 btr->btr_packet_type = unit->hci_packet_type;
  270                 break;
  271 
  272         case SIOCGBTSTATS:      /* get unit statistics */
  273                 (*unit->hci_if->get_stats)(unit->hci_dev, &btr->btr_stats, 0);
  274                 break;
  275 
  276         case SIOCZBTSTATS:      /* get & reset unit statistics */
  277                 err = kauth_authorize_generic(l->l_cred,
  278                     KAUTH_GENERIC_ISSUSER, NULL);
  279                 if (err)
  280                         break;
  281 
  282                 (*unit->hci_if->get_stats)(unit->hci_dev, &btr->btr_stats, 1);
  283                 break;
  284 
  285         case SIOCSBTSCOMTU:     /* set sco_mtu value for unit */
  286                 /*
  287                  * This is a temporary ioctl and may not be supported
  288                  * in the future. The need is that if SCO packets are
  289                  * sent to USB bluetooth controllers that are not an
  290                  * integer number of frame sizes, the USB bus locks up.
  291                  */
  292                 err = kauth_authorize_generic(l->l_cred,
  293                     KAUTH_GENERIC_ISSUSER, NULL);
  294                 if (err)
  295                         break;
  296 
  297                 unit->hci_max_sco_size = btr->btr_sco_mtu;
  298                 break;
  299 
  300         default:
  301                 err = EFAULT;
  302                 break;
  303         }
  304 
  305         return err;
  306 }

Cache object: 2f452a7d3a891e9399352eb37d148d86


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