[BACK]Return to hci_ioctl.c CVS log [TXT][DIR] Up to [local] / sys / netbt

Annotation of sys/netbt/hci_ioctl.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: hci_ioctl.c,v 1.1 2007/06/01 02:46:11 uwe Exp $       */
        !             2: /*     $NetBSD: hci_ioctl.c,v 1.5 2007/01/04 19:07:03 elad 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/domain.h>
        !            38: #include <sys/ioctl.h>
        !            39: #include <sys/kernel.h>
        !            40: #include <sys/mbuf.h>
        !            41: #include <sys/proc.h>
        !            42: #include <sys/systm.h>
        !            43:
        !            44: #include <netbt/bluetooth.h>
        !            45: #include <netbt/hci.h>
        !            46: #include <netbt/l2cap.h>
        !            47: #include <netbt/rfcomm.h>
        !            48:
        !            49: #ifdef BLUETOOTH_DEBUG
        !            50: #define BDADDR(bd)     (bd).b[5], (bd).b[4], (bd).b[3],        \
        !            51:                        (bd).b[2], (bd).b[1], (bd).b[0]
        !            52:
        !            53: static void
        !            54: hci_dump(void)
        !            55: {
        !            56:        struct hci_unit *unit;
        !            57:        struct hci_link *link;
        !            58:        struct l2cap_channel *chan;
        !            59:        struct rfcomm_session *rs;
        !            60:        struct rfcomm_dlc *dlc;
        !            61:
        !            62:        printf("HCI:\n");
        !            63:        TAILQ_FOREACH(unit, &hci_unit_list, hci_next) {
        !            64:                printf("UNIT %s: flags 0x%4.4x, "
        !            65:                        "num_cmd=%d, num_acl=%d, num_sco=%d\n",
        !            66:                        unit->hci_devname, unit->hci_flags,
        !            67:                        unit->hci_num_cmd_pkts,
        !            68:                        unit->hci_num_acl_pkts,
        !            69:                        unit->hci_num_sco_pkts);
        !            70:                TAILQ_FOREACH(link, &unit->hci_links, hl_next) {
        !            71:                        printf("+HANDLE #%d: %s "
        !            72:                            "raddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
        !            73:                            "state %d, refcnt %d\n",
        !            74:                            link->hl_handle,
        !            75:                            (link->hl_type == HCI_LINK_ACL ? "ACL":"SCO"),
        !            76:                            BDADDR(link->hl_bdaddr),
        !            77:                            link->hl_state, link->hl_refcnt);
        !            78:                }
        !            79:        }
        !            80:
        !            81:        printf("L2CAP:\n");
        !            82:        LIST_FOREACH(chan, &l2cap_active_list, lc_ncid) {
        !            83:                printf("CID #%d state %d, psm=0x%4.4x, "
        !            84:                    "laddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
        !            85:                    "raddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
        !            86:                    chan->lc_lcid, chan->lc_state, chan->lc_raddr.bt_psm,
        !            87:                    BDADDR(chan->lc_laddr.bt_bdaddr),
        !            88:                    BDADDR(chan->lc_raddr.bt_bdaddr));
        !            89:        }
        !            90:
        !            91:        LIST_FOREACH(chan, &l2cap_listen_list, lc_ncid) {
        !            92:                printf("LISTEN psm=0x%4.4x, "
        !            93:                    "laddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
        !            94:                    chan->lc_laddr.bt_psm,
        !            95:                    BDADDR(chan->lc_laddr.bt_bdaddr));
        !            96:        }
        !            97:
        !            98:        printf("RFCOMM:\n");
        !            99:        LIST_FOREACH(rs, &rfcomm_session_active, rs_next) {
        !           100:                chan = rs->rs_l2cap;
        !           101:                printf("SESSION: state=%d, flags=0x%4.4x, psm 0x%4.4x "
        !           102:                    "laddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
        !           103:                    "raddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
        !           104:                    rs->rs_state, rs->rs_flags, chan->lc_raddr.bt_psm,
        !           105:                    BDADDR(chan->lc_laddr.bt_bdaddr),
        !           106:                    BDADDR(chan->lc_raddr.bt_bdaddr));
        !           107:                LIST_FOREACH(dlc, &rs->rs_dlcs, rd_next) {
        !           108:                        printf("+DLC channel=%d, dlci=%d, "
        !           109:                            "state=%d, flags=0x%4.4x, rxcred=%d, rxsize=%ld, "
        !           110:                            "txcred=%d, pending=%d, txqlen=%d\n",
        !           111:                            dlc->rd_raddr.bt_channel, dlc->rd_dlci,
        !           112:                            dlc->rd_state, dlc->rd_flags,
        !           113:                            dlc->rd_rxcred, (unsigned long)dlc->rd_rxsize,
        !           114:                            dlc->rd_txcred, dlc->rd_pending,
        !           115:                            (dlc->rd_txbuf ? dlc->rd_txbuf->m_pkthdr.len : 0));
        !           116:                }
        !           117:        }
        !           118:
        !           119:        LIST_FOREACH(rs, &rfcomm_session_listen, rs_next) {
        !           120:                chan = rs->rs_l2cap;
        !           121:                printf("LISTEN: psm 0x%4.4x, "
        !           122:                    "laddr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
        !           123:                    chan->lc_laddr.bt_psm,
        !           124:                    BDADDR(chan->lc_laddr.bt_bdaddr));
        !           125:                LIST_FOREACH(dlc, &rs->rs_dlcs, rd_next)
        !           126:                        printf("+DLC channel=%d\n", dlc->rd_laddr.bt_channel);
        !           127:        }
        !           128: }
        !           129:
        !           130: #undef BDADDR
        !           131: #endif
        !           132:
        !           133: int
        !           134: hci_ioctl(unsigned long cmd, void *data, struct proc *p)
        !           135: {
        !           136:        struct btreq *btr = data;
        !           137:        struct hci_unit *unit;
        !           138:        int s, err = 0;
        !           139:
        !           140:        DPRINTFN(1, "cmd %#lx\n", cmd);
        !           141:
        !           142:        switch(cmd) {
        !           143: #ifdef BLUETOOTH_DEBUG
        !           144:        case SIOCBTDUMP:
        !           145:                hci_dump();
        !           146:                return 0;
        !           147: #endif
        !           148:        /*
        !           149:         * Get unit info based on address rather than name
        !           150:         */
        !           151:        case SIOCGBTINFOA:
        !           152:                unit = hci_unit_lookup(&btr->btr_bdaddr);
        !           153:                if (unit == NULL)
        !           154:                        return ENXIO;
        !           155:
        !           156:                break;
        !           157:
        !           158:        /*
        !           159:         * The remaining ioctl's all use the same btreq structure and
        !           160:         * index on the name of the device, so we look that up first.
        !           161:         */
        !           162:        case SIOCNBTINFO:
        !           163:                /* empty name means give the first unit */
        !           164:                if (btr->btr_name[0] == '\0') {
        !           165:                        unit = NULL;
        !           166:                        break;
        !           167:                }
        !           168:
        !           169:                /* else fall through and look it up */
        !           170:        case SIOCGBTINFO:
        !           171:        case SIOCSBTFLAGS:
        !           172:        case SIOCSBTPOLICY:
        !           173:        case SIOCSBTPTYPE:
        !           174:        case SIOCGBTSTATS:
        !           175:        case SIOCZBTSTATS:
        !           176:        case SIOCSBTSCOMTU:
        !           177:                TAILQ_FOREACH(unit, &hci_unit_list, hci_next) {
        !           178:                        if (strncmp(unit->hci_devname, btr->btr_name,
        !           179:                            HCI_DEVNAME_SIZE) == 0)
        !           180:                                break;
        !           181:                }
        !           182:
        !           183:                if (unit == NULL)
        !           184:                        return ENXIO;
        !           185:
        !           186:                break;
        !           187:
        !           188:        default:        /* not one of mine */
        !           189:                return EPASSTHROUGH;
        !           190:        }
        !           191:
        !           192:        switch(cmd) {
        !           193:        case SIOCNBTINFO:       /* get next info */
        !           194:                if (unit)
        !           195:                        unit = TAILQ_NEXT(unit, hci_next);
        !           196:                else
        !           197:                        unit = TAILQ_FIRST(&hci_unit_list);
        !           198:
        !           199:                if (unit == NULL) {
        !           200:                        err = ENXIO;
        !           201:                        break;
        !           202:                }
        !           203:
        !           204:                /* and fall through to */
        !           205:        case SIOCGBTINFO:       /* get unit info */
        !           206:        case SIOCGBTINFOA:      /* get info by address */
        !           207:                memset(btr, 0, sizeof(struct btreq));
        !           208:                strlcpy(btr->btr_name, unit->hci_devname, HCI_DEVNAME_SIZE);
        !           209:                bdaddr_copy(&btr->btr_bdaddr, &unit->hci_bdaddr);
        !           210:
        !           211:                btr->btr_flags = unit->hci_flags;
        !           212:
        !           213:                btr->btr_num_cmd = unit->hci_num_cmd_pkts;
        !           214:                btr->btr_num_acl = unit->hci_num_acl_pkts;
        !           215:                btr->btr_num_sco = unit->hci_num_sco_pkts;
        !           216:                btr->btr_acl_mtu = unit->hci_max_acl_size;
        !           217:                btr->btr_sco_mtu = unit->hci_max_sco_size;
        !           218:
        !           219:                btr->btr_packet_type = unit->hci_packet_type;
        !           220:                btr->btr_link_policy = unit->hci_link_policy;
        !           221:                break;
        !           222:
        !           223:        case SIOCSBTFLAGS:      /* set unit flags (privileged) */
        !           224:                err = suser(p, 0);
        !           225:                if (err)
        !           226:                        break;
        !           227:
        !           228:                if ((unit->hci_flags & BTF_UP)
        !           229:                    && (btr->btr_flags & BTF_UP) == 0) {
        !           230:                        hci_disable(unit);
        !           231:                        unit->hci_flags &= ~BTF_UP;
        !           232:                }
        !           233:
        !           234:                s = splraiseipl(unit->hci_ipl);
        !           235:                unit->hci_flags |= (btr->btr_flags & BTF_INIT);
        !           236:                splx(s);
        !           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:                        s = splraiseipl(unit->hci_ipl);
        !           245:                        unit->hci_flags |= BTF_UP;
        !           246:                        splx(s);
        !           247:                }
        !           248:
        !           249:                btr->btr_flags = unit->hci_flags;
        !           250:                break;
        !           251:
        !           252:        case SIOCSBTPOLICY:     /* set unit link policy (privileged) */
        !           253:                err = suser(p, 0);
        !           254:                if (err)
        !           255:                        break;
        !           256:
        !           257:                unit->hci_link_policy = btr->btr_link_policy;
        !           258:                unit->hci_link_policy &= unit->hci_lmp_mask;
        !           259:                btr->btr_link_policy = unit->hci_link_policy;
        !           260:                break;
        !           261:
        !           262:        case SIOCSBTPTYPE:      /* set unit packet types (privileged) */
        !           263:                err = suser(p, 0);
        !           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:                s = splraiseipl(unit->hci_ipl);
        !           274:                memcpy(&btr->btr_stats, &unit->hci_stats,
        !           275:                        sizeof(struct bt_stats));
        !           276:                splx(s);
        !           277:                break;
        !           278:
        !           279:        case SIOCZBTSTATS:      /* get & reset unit statistics */
        !           280:                err = suser(p, 0);
        !           281:                if (err)
        !           282:                        break;
        !           283:
        !           284:                s = splraiseipl(unit->hci_ipl);
        !           285:                memcpy(&btr->btr_stats, &unit->hci_stats,
        !           286:                        sizeof(struct bt_stats));
        !           287:                memset(&unit->hci_stats, 0, sizeof(struct bt_stats));
        !           288:                splx(s);
        !           289:
        !           290:                break;
        !           291:
        !           292:        case SIOCSBTSCOMTU:     /* set sco_mtu value for unit */
        !           293:                /*
        !           294:                 * This is a temporary ioctl and may not be supported
        !           295:                 * in the future. The need is that if SCO packets are
        !           296:                 * sent to USB bluetooth controllers that are not an
        !           297:                 * integer number of frame sizes, the USB bus locks up.
        !           298:                 */
        !           299:                err = suser(p, 0);
        !           300:                if (err)
        !           301:                        break;
        !           302:
        !           303:                unit->hci_max_sco_size = btr->btr_sco_mtu;
        !           304:                break;
        !           305:
        !           306:        default:
        !           307:                err = EFAULT;
        !           308:                break;
        !           309:        }
        !           310:
        !           311:        return err;
        !           312: }

CVSweb