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.4 2006/09/11 22:12:39 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.4 2006/09/11 22:12:39 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         printf("HCI:\n");
   64         SIMPLEQ_FOREACH(unit, &hci_unit_list, hci_next) {
   65                 printf("UNIT %s: flags 0x%4.4x, "
   66                         "num_cmd=%d, num_acl=%d, num_sco=%d\n",
   67                         unit->hci_devname, 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                         printf("+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         printf("L2CAP:\n");
   83         LIST_FOREACH(chan, &l2cap_active_list, lc_ncid) {
   84                 printf("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                 printf("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         printf("RFCOMM:\n");
  100         LIST_FOREACH(rs, &rfcomm_session_active, rs_next) {
  101                 chan = rs->rs_l2cap;
  102                 printf("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                         printf("+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                 printf("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                         printf("+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 s, 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(unit->hci_devname, btr->btr_name,
  180                             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, unit->hci_devname, 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, &l->l_acflag);
  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                 s = splraiseipl(unit->hci_ipl);
  237                 unit->hci_flags |= (btr->btr_flags & BTF_INIT);
  238                 splx(s);
  239 
  240                 if ((unit->hci_flags & BTF_UP) == 0
  241                     && (btr->btr_flags & BTF_UP)) {
  242                         err = hci_enable(unit);
  243                         if (err)
  244                                 break;
  245 
  246                         s = splraiseipl(unit->hci_ipl);
  247                         unit->hci_flags |= BTF_UP;
  248                         splx(s);
  249                 }
  250 
  251                 btr->btr_flags = unit->hci_flags;
  252                 break;
  253 
  254         case SIOCSBTPOLICY:     /* set unit link policy (privileged) */
  255                 err = kauth_authorize_generic(l->l_cred,
  256                     KAUTH_GENERIC_ISSUSER, &l->l_acflag);
  257                 if (err)
  258                         break;
  259 
  260                 unit->hci_link_policy = btr->btr_link_policy;
  261                 unit->hci_link_policy &= unit->hci_lmp_mask;
  262                 btr->btr_link_policy = unit->hci_link_policy;
  263                 break;
  264 
  265         case SIOCSBTPTYPE:      /* set unit packet types (privileged) */
  266                 err = kauth_authorize_generic(l->l_cred,
  267                     KAUTH_GENERIC_ISSUSER, &l->l_acflag);
  268                 if (err)
  269                         break;
  270 
  271                 unit->hci_packet_type = btr->btr_packet_type;
  272                 unit->hci_packet_type &= unit->hci_acl_mask;
  273                 btr->btr_packet_type = unit->hci_packet_type;
  274                 break;
  275 
  276         case SIOCGBTSTATS:      /* get unit statistics */
  277                 s = splraiseipl(unit->hci_ipl);
  278                 memcpy(&btr->btr_stats, &unit->hci_stats,
  279                         sizeof(struct bt_stats));
  280                 splx(s);
  281                 break;
  282 
  283         case SIOCZBTSTATS:      /* get & reset unit statistics */
  284                 err = kauth_authorize_generic(l->l_cred,
  285                     KAUTH_GENERIC_ISSUSER, &l->l_acflag);
  286                 if (err)
  287                         break;
  288 
  289                 s = splraiseipl(unit->hci_ipl);
  290                 memcpy(&btr->btr_stats, &unit->hci_stats,
  291                         sizeof(struct bt_stats));
  292                 memset(&unit->hci_stats, 0, sizeof(struct bt_stats));
  293                 splx(s);
  294 
  295                 break;
  296 
  297         case SIOCSBTSCOMTU:     /* set sco_mtu value for unit */
  298                 /*
  299                  * This is a temporary ioctl and may not be supported
  300                  * in the future. The need is that if SCO packets are
  301                  * sent to USB bluetooth controllers that are not an
  302                  * integer number of frame sizes, the USB bus locks up.
  303                  */
  304                 err = kauth_authorize_generic(l->l_cred,
  305                     KAUTH_GENERIC_ISSUSER, &l->l_acflag);
  306                 if (err)
  307                         break;
  308 
  309                 unit->hci_max_sco_size = btr->btr_sco_mtu;
  310                 break;
  311 
  312         default:
  313                 err = EFAULT;
  314                 break;
  315         }
  316 
  317         return err;
  318 }

Cache object: a51df93b4ec9f6e0f8c47fa889b034bc


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