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

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

1.1     ! nbrk        1: /*     $OpenBSD: hci_event.c,v 1.5 2007/06/19 08:12:35 uwe Exp $       */
        !             2: /*     $NetBSD: hci_event.c,v 1.6 2007/04/21 06:15:23 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/malloc.h>
        !            39: #include <sys/mbuf.h>
        !            40: #include <sys/proc.h>
        !            41: #include <sys/systm.h>
        !            42:
        !            43: #include <netbt/bluetooth.h>
        !            44: #include <netbt/hci.h>
        !            45: #include <netbt/sco.h>
        !            46:
        !            47: static void hci_event_inquiry_result(struct hci_unit *, struct mbuf *);
        !            48: static void hci_event_command_status(struct hci_unit *, struct mbuf *);
        !            49: static void hci_event_command_compl(struct hci_unit *, struct mbuf *);
        !            50: static void hci_event_con_compl(struct hci_unit *, struct mbuf *);
        !            51: static void hci_event_discon_compl(struct hci_unit *, struct mbuf *);
        !            52: static void hci_event_con_req(struct hci_unit *, struct mbuf *);
        !            53: static void hci_event_num_compl_pkts(struct hci_unit *, struct mbuf *);
        !            54: static void hci_event_auth_compl(struct hci_unit *, struct mbuf *);
        !            55: static void hci_event_encryption_change(struct hci_unit *, struct mbuf *);
        !            56: static void hci_event_change_con_link_key_compl(struct hci_unit *, struct mbuf *);
        !            57: static void hci_cmd_read_bdaddr(struct hci_unit *, struct mbuf *);
        !            58: static void hci_cmd_read_buffer_size(struct hci_unit *, struct mbuf *);
        !            59: static void hci_cmd_read_local_features(struct hci_unit *, struct mbuf *);
        !            60: static void hci_cmd_reset(struct hci_unit *, struct mbuf *);
        !            61:
        !            62: #ifdef BLUETOOTH_DEBUG
        !            63: int bluetooth_debug = 0;
        !            64:
        !            65: static const char *hci_eventnames[] = {
        !            66: /* 0x00 */ "NULL",
        !            67: /* 0x01 */ "INQUIRY COMPLETE",
        !            68: /* 0x02 */ "INQUIRY RESULT",
        !            69: /* 0x03 */ "CONN COMPLETE",
        !            70: /* 0x04 */ "CONN REQ",
        !            71: /* 0x05 */ "DISCONN COMPLETE",
        !            72: /* 0x06 */ "AUTH COMPLETE",
        !            73: /* 0x07 */ "REMOTE NAME REQ COMPLETE",
        !            74: /* 0x08 */ "ENCRYPTION CHANGE",
        !            75: /* 0x09 */ "CHANGE CONN LINK KEY COMPLETE",
        !            76: /* 0x0a */ "MASTER LINK KEY COMPLETE",
        !            77: /* 0x0b */ "READ REMOTE FEATURES COMPLETE",
        !            78: /* 0x0c */ "READ REMOTE VERSION INFO COMPLETE",
        !            79: /* 0x0d */ "QoS SETUP COMPLETE",
        !            80: /* 0x0e */ "COMMAND COMPLETE",
        !            81: /* 0x0f */ "COMMAND STATUS",
        !            82: /* 0x10 */ "HARDWARE ERROR",
        !            83: /* 0x11 */ "FLUSH OCCUR",
        !            84: /* 0x12 */ "ROLE CHANGE",
        !            85: /* 0x13 */ "NUM COMPLETED PACKETS",
        !            86: /* 0x14 */ "MODE CHANGE",
        !            87: /* 0x15 */ "RETURN LINK KEYS",
        !            88: /* 0x16 */ "PIN CODE REQ",
        !            89: /* 0x17 */ "LINK KEY REQ",
        !            90: /* 0x18 */ "LINK KEY NOTIFICATION",
        !            91: /* 0x19 */ "LOOPBACK COMMAND",
        !            92: /* 0x1a */ "DATA BUFFER OVERFLOW",
        !            93: /* 0x1b */ "MAX SLOT CHANGE",
        !            94: /* 0x1c */ "READ CLOCK OFFSET COMPLETE",
        !            95: /* 0x1d */ "CONN PKT TYPE CHANGED",
        !            96: /* 0x1e */ "QOS VIOLATION",
        !            97: /* 0x1f */ "PAGE SCAN MODE CHANGE",
        !            98: /* 0x20 */ "PAGE SCAN REP MODE CHANGE",
        !            99: /* 0x21 */ "FLOW SPECIFICATION COMPLETE",
        !           100: /* 0x22 */ "RSSI RESULT",
        !           101: /* 0x23 */ "READ REMOTE EXT FEATURES"
        !           102: };
        !           103:
        !           104: static const char *
        !           105: hci_eventstr(unsigned int event)
        !           106: {
        !           107:
        !           108:        if (event < (sizeof(hci_eventnames) / sizeof(*hci_eventnames)))
        !           109:                return hci_eventnames[event];
        !           110:
        !           111:        switch (event) {
        !           112:        case HCI_EVENT_SCO_CON_COMPL:   /* 0x2c */
        !           113:                return "SCO CON COMPLETE";
        !           114:
        !           115:        case HCI_EVENT_SCO_CON_CHANGED: /* 0x2d */
        !           116:                return "SCO CON CHANGED";
        !           117:
        !           118:        case HCI_EVENT_BT_LOGO:         /* 0xfe */
        !           119:                return "BT_LOGO";
        !           120:
        !           121:        case HCI_EVENT_VENDOR:          /* 0xff */
        !           122:                return "VENDOR";
        !           123:        }
        !           124:
        !           125:        return "UNRECOGNISED";
        !           126: }
        !           127: #endif /* BLUETOOTH_DEBUG */
        !           128:
        !           129: /*
        !           130:  * process HCI Events
        !           131:  *
        !           132:  * We will free the mbuf at the end, no need for any sub
        !           133:  * functions to handle that. We kind of assume that the
        !           134:  * device sends us valid events.
        !           135:  * XXX "kind of"? This needs to be fixed.
        !           136:  */
        !           137: void
        !           138: hci_event(struct mbuf *m, struct hci_unit *unit)
        !           139: {
        !           140:        hci_event_hdr_t hdr;
        !           141:
        !           142:        KASSERT(m->m_flags & M_PKTHDR);
        !           143:
        !           144:        KASSERT(m->m_pkthdr.len >= sizeof(hdr));
        !           145:        m_copydata(m, 0, sizeof(hdr), (caddr_t)&hdr);
        !           146:        m_adj(m, sizeof(hdr));
        !           147:
        !           148:        KASSERT(hdr.type == HCI_EVENT_PKT);
        !           149:
        !           150:        DPRINTFN(1, "(%s) event %s\n", unit->hci_devname, hci_eventstr(hdr.event));
        !           151:
        !           152:        switch(hdr.event) {
        !           153:        case HCI_EVENT_COMMAND_STATUS:
        !           154:                hci_event_command_status(unit, m);
        !           155:                break;
        !           156:
        !           157:        case HCI_EVENT_COMMAND_COMPL:
        !           158:                hci_event_command_compl(unit, m);
        !           159:                break;
        !           160:
        !           161:        case HCI_EVENT_NUM_COMPL_PKTS:
        !           162:                hci_event_num_compl_pkts(unit, m);
        !           163:                break;
        !           164:
        !           165:        case HCI_EVENT_INQUIRY_RESULT:
        !           166:                hci_event_inquiry_result(unit, m);
        !           167:                break;
        !           168:
        !           169:        case HCI_EVENT_CON_COMPL:
        !           170:                hci_event_con_compl(unit, m);
        !           171:                break;
        !           172:
        !           173:        case HCI_EVENT_DISCON_COMPL:
        !           174:                hci_event_discon_compl(unit, m);
        !           175:                break;
        !           176:
        !           177:        case HCI_EVENT_CON_REQ:
        !           178:                hci_event_con_req(unit, m);
        !           179:                break;
        !           180:
        !           181:        case HCI_EVENT_AUTH_COMPL:
        !           182:                hci_event_auth_compl(unit, m);
        !           183:                break;
        !           184:
        !           185:        case HCI_EVENT_ENCRYPTION_CHANGE:
        !           186:                hci_event_encryption_change(unit, m);
        !           187:                break;
        !           188:
        !           189:        case HCI_EVENT_CHANGE_CON_LINK_KEY_COMPL:
        !           190:                hci_event_change_con_link_key_compl(unit, m);
        !           191:                break;
        !           192:
        !           193:        case HCI_EVENT_SCO_CON_COMPL:
        !           194:        case HCI_EVENT_INQUIRY_COMPL:
        !           195:        case HCI_EVENT_REMOTE_NAME_REQ_COMPL:
        !           196:        case HCI_EVENT_MASTER_LINK_KEY_COMPL:
        !           197:        case HCI_EVENT_READ_REMOTE_FEATURES_COMPL:
        !           198:        case HCI_EVENT_READ_REMOTE_VER_INFO_COMPL:
        !           199:        case HCI_EVENT_QOS_SETUP_COMPL:
        !           200:        case HCI_EVENT_HARDWARE_ERROR:
        !           201:        case HCI_EVENT_FLUSH_OCCUR:
        !           202:        case HCI_EVENT_ROLE_CHANGE:
        !           203:        case HCI_EVENT_MODE_CHANGE:
        !           204:        case HCI_EVENT_RETURN_LINK_KEYS:
        !           205:        case HCI_EVENT_PIN_CODE_REQ:
        !           206:        case HCI_EVENT_LINK_KEY_REQ:
        !           207:        case HCI_EVENT_LINK_KEY_NOTIFICATION:
        !           208:        case HCI_EVENT_LOOPBACK_COMMAND:
        !           209:        case HCI_EVENT_DATA_BUFFER_OVERFLOW:
        !           210:        case HCI_EVENT_MAX_SLOT_CHANGE:
        !           211:        case HCI_EVENT_READ_CLOCK_OFFSET_COMPL:
        !           212:        case HCI_EVENT_CON_PKT_TYPE_CHANGED:
        !           213:        case HCI_EVENT_QOS_VIOLATION:
        !           214:        case HCI_EVENT_PAGE_SCAN_MODE_CHANGE:
        !           215:        case HCI_EVENT_PAGE_SCAN_REP_MODE_CHANGE:
        !           216:        case HCI_EVENT_FLOW_SPECIFICATION_COMPL:
        !           217:        case HCI_EVENT_RSSI_RESULT:
        !           218:        case HCI_EVENT_READ_REMOTE_EXTENDED_FEATURES:
        !           219:        case HCI_EVENT_SCO_CON_CHANGED:
        !           220:        case HCI_EVENT_BT_LOGO:
        !           221:        case HCI_EVENT_VENDOR:
        !           222:                break;
        !           223:
        !           224:        default:
        !           225:                UNKNOWN(hdr.event);
        !           226:                break;
        !           227:        }
        !           228:
        !           229:        m_freem(m);
        !           230: }
        !           231:
        !           232: /*
        !           233:  * Command Status
        !           234:  *
        !           235:  * Update our record of num_cmd_pkts then post-process any pending commands
        !           236:  * and optionally restart cmd output on the unit.
        !           237:  */
        !           238: static void
        !           239: hci_event_command_status(struct hci_unit *unit, struct mbuf *m)
        !           240: {
        !           241:        hci_command_status_ep ep;
        !           242:        struct hci_link *link;
        !           243:
        !           244:        KASSERT(m->m_pkthdr.len >= sizeof(ep));
        !           245:        m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
        !           246:        m_adj(m, sizeof(ep));
        !           247:
        !           248:        DPRINTFN(1, "(%s) opcode (%03x|%04x) status = 0x%x num_cmd_pkts = %d\n",
        !           249:                unit->hci_devname,
        !           250:                HCI_OGF(letoh16(ep.opcode)), HCI_OCF(letoh16(ep.opcode)),
        !           251:                ep.status,
        !           252:                ep.num_cmd_pkts);
        !           253:
        !           254:        unit->hci_num_cmd_pkts = ep.num_cmd_pkts;
        !           255:
        !           256:        /*
        !           257:         * post processing of pending commands
        !           258:         */
        !           259:        switch(letoh16(ep.opcode)) {
        !           260:        case HCI_CMD_CREATE_CON:
        !           261:                switch (ep.status) {
        !           262:                case 0x12:      /* Invalid HCI command parameters */
        !           263:                        DPRINTF("(%s) Invalid HCI command parameters\n",
        !           264:                            unit->hci_devname);
        !           265:                        while ((link = hci_link_lookup_state(unit,
        !           266:                            HCI_LINK_ACL, HCI_LINK_WAIT_CONNECT)) != NULL)
        !           267:                                hci_link_free(link, ECONNABORTED);
        !           268:                        break;
        !           269:                }
        !           270:                break;
        !           271:        default:
        !           272:                break;
        !           273:        }
        !           274:
        !           275:        while (unit->hci_num_cmd_pkts > 0 && !IF_IS_EMPTY(&unit->hci_cmdwait)) {
        !           276:                IF_DEQUEUE(&unit->hci_cmdwait, m);
        !           277:                hci_output_cmd(unit, m);
        !           278:        }
        !           279: }
        !           280:
        !           281: /*
        !           282:  * Command Complete
        !           283:  *
        !           284:  * Update our record of num_cmd_pkts then handle the completed command,
        !           285:  * and optionally restart cmd output on the unit.
        !           286:  */
        !           287: static void
        !           288: hci_event_command_compl(struct hci_unit *unit, struct mbuf *m)
        !           289: {
        !           290:        hci_command_compl_ep ep;
        !           291:
        !           292:        KASSERT(m->m_pkthdr.len >= sizeof(ep));
        !           293:        m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
        !           294:        m_adj(m, sizeof(ep));
        !           295:
        !           296:        DPRINTFN(1, "(%s) opcode (%03x|%04x) num_cmd_pkts = %d\n",
        !           297:                unit->hci_devname,
        !           298:                HCI_OGF(letoh16(ep.opcode)), HCI_OCF(letoh16(ep.opcode)),
        !           299:                ep.num_cmd_pkts);
        !           300:
        !           301:        unit->hci_num_cmd_pkts = ep.num_cmd_pkts;
        !           302:
        !           303:        /*
        !           304:         * post processing of completed commands
        !           305:         */
        !           306:        switch(letoh16(ep.opcode)) {
        !           307:        case HCI_CMD_READ_BDADDR:
        !           308:                hci_cmd_read_bdaddr(unit, m);
        !           309:                break;
        !           310:
        !           311:        case HCI_CMD_READ_BUFFER_SIZE:
        !           312:                hci_cmd_read_buffer_size(unit, m);
        !           313:                break;
        !           314:
        !           315:        case HCI_CMD_READ_LOCAL_FEATURES:
        !           316:                hci_cmd_read_local_features(unit, m);
        !           317:                break;
        !           318:
        !           319:        case HCI_CMD_RESET:
        !           320:                hci_cmd_reset(unit, m);
        !           321:                break;
        !           322:
        !           323:        default:
        !           324:                break;
        !           325:        }
        !           326:
        !           327:        while (unit->hci_num_cmd_pkts > 0 && !IF_IS_EMPTY(&unit->hci_cmdwait)) {
        !           328:                IF_DEQUEUE(&unit->hci_cmdwait, m);
        !           329:                hci_output_cmd(unit, m);
        !           330:        }
        !           331: }
        !           332:
        !           333: /*
        !           334:  * Number of Completed Packets
        !           335:  *
        !           336:  * This is sent periodically by the Controller telling us how many
        !           337:  * buffers are now freed up and which handle was using them. From
        !           338:  * this we determine which type of buffer it was and add the qty
        !           339:  * back into the relevant packet counter, then restart output on
        !           340:  * links that have halted.
        !           341:  */
        !           342: static void
        !           343: hci_event_num_compl_pkts(struct hci_unit *unit, struct mbuf *m)
        !           344: {
        !           345:        hci_num_compl_pkts_ep ep;
        !           346:        struct hci_link *link, *next;
        !           347:        uint16_t handle, num;
        !           348:        int num_acl = 0, num_sco = 0;
        !           349:
        !           350:        KASSERT(m->m_pkthdr.len >= sizeof(ep));
        !           351:        m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
        !           352:        m_adj(m, sizeof(ep));
        !           353:
        !           354:        while (ep.num_con_handles--) {
        !           355:                m_copydata(m, 0, sizeof(handle), (caddr_t)&handle);
        !           356:                m_adj(m, sizeof(handle));
        !           357:                handle = letoh16(handle);
        !           358:
        !           359:                m_copydata(m, 0, sizeof(num), (caddr_t)&num);
        !           360:                m_adj(m, sizeof(num));
        !           361:                num = letoh16(num);
        !           362:
        !           363:                link = hci_link_lookup_handle(unit, handle);
        !           364:                if (link) {
        !           365:                        if (link->hl_type == HCI_LINK_ACL) {
        !           366:                                num_acl += num;
        !           367:                                hci_acl_complete(link, num);
        !           368:                        } else {
        !           369:                                num_sco += num;
        !           370:                                hci_sco_complete(link, num);
        !           371:                        }
        !           372:                } else {
        !           373:                        /* XXX need to issue Read_Buffer_Size or Reset? */
        !           374:                        printf("%s: unknown handle %d! "
        !           375:                                "(losing track of %d packet buffer%s)\n",
        !           376:                                unit->hci_devname, handle,
        !           377:                                num, (num == 1 ? "" : "s"));
        !           378:                }
        !           379:        }
        !           380:
        !           381:        /*
        !           382:         * Move up any queued packets. When a link has sent data, it will move
        !           383:         * to the back of the queue - technically then if a link had something
        !           384:         * to send and there were still buffers available it could get started
        !           385:         * twice but it seemed more important to to handle higher loads fairly
        !           386:         * than worry about wasting cycles when we are not busy.
        !           387:         */
        !           388:
        !           389:        unit->hci_num_acl_pkts += num_acl;
        !           390:        unit->hci_num_sco_pkts += num_sco;
        !           391:
        !           392:        link = TAILQ_FIRST(&unit->hci_links);
        !           393:        while (link && (unit->hci_num_acl_pkts > 0 || unit->hci_num_sco_pkts > 0)) {
        !           394:                next = TAILQ_NEXT(link, hl_next);
        !           395:
        !           396:                if (link->hl_type == HCI_LINK_ACL) {
        !           397:                        if (unit->hci_num_acl_pkts > 0 && link->hl_txqlen > 0)
        !           398:                                hci_acl_start(link);
        !           399:                } else {
        !           400:                        if (unit->hci_num_sco_pkts > 0 && link->hl_txqlen > 0)
        !           401:                                hci_sco_start(link);
        !           402:                }
        !           403:
        !           404:                link = next;
        !           405:        }
        !           406: }
        !           407:
        !           408: /*
        !           409:  * Inquiry Result
        !           410:  *
        !           411:  * keep a note of devices seen, so we know which unit to use
        !           412:  * on outgoing connections
        !           413:  */
        !           414: static void
        !           415: hci_event_inquiry_result(struct hci_unit *unit, struct mbuf *m)
        !           416: {
        !           417:        hci_inquiry_result_ep ep;
        !           418:        struct hci_memo *memo;
        !           419:        bdaddr_t bdaddr;
        !           420:
        !           421:        KASSERT(m->m_pkthdr.len >= sizeof(ep));
        !           422:        m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
        !           423:        m_adj(m, sizeof(ep));
        !           424:
        !           425:        DPRINTFN(1, "%d response%s\n", ep.num_responses,
        !           426:                                (ep.num_responses == 1 ? "" : "s"));
        !           427:
        !           428:        while(ep.num_responses--) {
        !           429:                m_copydata(m, 0, sizeof(bdaddr_t), (caddr_t)&bdaddr);
        !           430:
        !           431:                DPRINTFN(1, "bdaddr %02x:%02x:%02x:%02x:%02x:%02x\n",
        !           432:                        bdaddr.b[5], bdaddr.b[4], bdaddr.b[3],
        !           433:                        bdaddr.b[2], bdaddr.b[1], bdaddr.b[0]);
        !           434:
        !           435:                memo = hci_memo_find(unit, &bdaddr);
        !           436:                if (memo == NULL) {
        !           437:                        memo = malloc(sizeof(struct hci_memo),
        !           438:                                M_BLUETOOTH, M_NOWAIT);
        !           439:                        if (memo == NULL) {
        !           440:                                DPRINTFN(0, "out of memo memory!\n");
        !           441:                                break;
        !           442:                        }
        !           443:                        bzero(memo, sizeof *memo);
        !           444:
        !           445:                        LIST_INSERT_HEAD(&unit->hci_memos, memo, next);
        !           446:                }
        !           447:
        !           448:                microtime(&memo->time);
        !           449:                m_copydata(m, 0, sizeof(hci_inquiry_response),
        !           450:                        (caddr_t)&memo->response);
        !           451:                m_adj(m, sizeof(hci_inquiry_response));
        !           452:
        !           453:                memo->response.clock_offset =
        !           454:                    letoh16(memo->response.clock_offset);
        !           455:        }
        !           456: }
        !           457:
        !           458: /*
        !           459:  * Connection Complete
        !           460:  *
        !           461:  * Sent to us when a connection is made. If there is no link
        !           462:  * structure already allocated for this, we must have changed
        !           463:  * our mind, so just disconnect.
        !           464:  */
        !           465: static void
        !           466: hci_event_con_compl(struct hci_unit *unit, struct mbuf *m)
        !           467: {
        !           468:        hci_con_compl_ep ep;
        !           469:        hci_write_link_policy_settings_cp cp;
        !           470:        struct hci_link *link;
        !           471:        int err;
        !           472:
        !           473:        KASSERT(m->m_pkthdr.len >= sizeof(ep));
        !           474:        m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
        !           475:        m_adj(m, sizeof(ep));
        !           476:
        !           477:        DPRINTFN(1, "(%s) %s connection complete for "
        !           478:                "%02x:%02x:%02x:%02x:%02x:%02x status %#x\n",
        !           479:                unit->hci_devname,
        !           480:                (ep.link_type == HCI_LINK_ACL ? "ACL" : "SCO"),
        !           481:                ep.bdaddr.b[5], ep.bdaddr.b[4], ep.bdaddr.b[3],
        !           482:                ep.bdaddr.b[2], ep.bdaddr.b[1], ep.bdaddr.b[0],
        !           483:                ep.status);
        !           484:
        !           485:        link = hci_link_lookup_bdaddr(unit, &ep.bdaddr, ep.link_type);
        !           486:
        !           487:        if (ep.status) {
        !           488:                if (link != NULL) {
        !           489:                        switch (ep.status) {
        !           490:                        case 0x04: /* "Page Timeout" */
        !           491:                                err = EHOSTDOWN;
        !           492:                                break;
        !           493:
        !           494:                        case 0x08: /* "Connection Timed Out" */
        !           495:                        case 0x10: /* "Connection Accept Timeout Exceeded" */
        !           496:                                err = ETIMEDOUT;
        !           497:                                break;
        !           498:
        !           499:                        case 0x16: /* "Connection Terminated by Local Host" */
        !           500:                                err = 0;
        !           501:                                break;
        !           502:
        !           503:                        default:
        !           504:                                err = ECONNREFUSED;
        !           505:                                break;
        !           506:                        }
        !           507:
        !           508:                        hci_link_free(link, err);
        !           509:                }
        !           510:
        !           511:                return;
        !           512:        }
        !           513:
        !           514:        if (link == NULL) {
        !           515:                hci_discon_cp dp;
        !           516:
        !           517:                dp.con_handle = ep.con_handle;
        !           518:                dp.reason = 0x13; /* "Remote User Terminated Connection" */
        !           519:
        !           520:                hci_send_cmd(unit, HCI_CMD_DISCONNECT, &dp, sizeof(dp));
        !           521:                return;
        !           522:        }
        !           523:
        !           524:        /* XXX could check auth_enable here */
        !           525:
        !           526:        if (ep.encryption_mode)
        !           527:                link->hl_flags |= (HCI_LINK_AUTH | HCI_LINK_ENCRYPT);
        !           528:
        !           529:        link->hl_state = HCI_LINK_OPEN;
        !           530:        link->hl_handle = HCI_CON_HANDLE(letoh16(ep.con_handle));
        !           531:
        !           532:        if (ep.link_type == HCI_LINK_ACL) {
        !           533:                cp.con_handle = ep.con_handle;
        !           534:                cp.settings = htole16(unit->hci_link_policy);
        !           535:                err = hci_send_cmd(unit, HCI_CMD_WRITE_LINK_POLICY_SETTINGS,
        !           536:                                                &cp, sizeof(cp));
        !           537:                if (err)
        !           538:                        printf("%s: Warning, could not write link policy\n",
        !           539:                                unit->hci_devname);
        !           540:
        !           541:                err = hci_acl_setmode(link);
        !           542:                if (err == EINPROGRESS)
        !           543:                        return;
        !           544:
        !           545:                hci_acl_linkmode(link);
        !           546:        } else {
        !           547:                (*link->hl_sco->sp_proto->connected)(link->hl_sco->sp_upper);
        !           548:        }
        !           549: }
        !           550:
        !           551: /*
        !           552:  * Disconnection Complete
        !           553:  *
        !           554:  * This is sent in response to a disconnection request, but also if
        !           555:  * the remote device goes out of range.
        !           556:  */
        !           557: static void
        !           558: hci_event_discon_compl(struct hci_unit *unit, struct mbuf *m)
        !           559: {
        !           560:        hci_discon_compl_ep ep;
        !           561:        struct hci_link *link;
        !           562:
        !           563:        KASSERT(m->m_pkthdr.len >= sizeof(ep));
        !           564:        m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
        !           565:        m_adj(m, sizeof(ep));
        !           566:
        !           567:        ep.con_handle = letoh16(ep.con_handle);
        !           568:
        !           569:        DPRINTFN(1, "handle #%d, status=0x%x\n", ep.con_handle, ep.status);
        !           570:
        !           571:        link = hci_link_lookup_handle(unit, HCI_CON_HANDLE(ep.con_handle));
        !           572:        if (link)
        !           573:                hci_link_free(link, ENOENT); /* XXX NetBSD used ENOLINK here */
        !           574: }
        !           575:
        !           576: /*
        !           577:  * Connect Request
        !           578:  *
        !           579:  * We check upstream for appropriate listeners and accept connections
        !           580:  * that are wanted.
        !           581:  */
        !           582: static void
        !           583: hci_event_con_req(struct hci_unit *unit, struct mbuf *m)
        !           584: {
        !           585:        hci_con_req_ep ep;
        !           586:        hci_accept_con_cp ap;
        !           587:        hci_reject_con_cp rp;
        !           588:        struct hci_link *link;
        !           589:
        !           590:        KASSERT(m->m_pkthdr.len >= sizeof(ep));
        !           591:        m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
        !           592:        m_adj(m, sizeof(ep));
        !           593:
        !           594:        DPRINTFN(1, "bdaddr %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
        !           595:                "class %2.2x%2.2x%2.2x type %s\n",
        !           596:                ep.bdaddr.b[5], ep.bdaddr.b[4], ep.bdaddr.b[3],
        !           597:                ep.bdaddr.b[2], ep.bdaddr.b[1], ep.bdaddr.b[0],
        !           598:                ep.uclass[0], ep.uclass[1], ep.uclass[2],
        !           599:                ep.link_type == HCI_LINK_ACL ? "ACL" : "SCO");
        !           600:
        !           601:        if (ep.link_type == HCI_LINK_ACL)
        !           602:                link = hci_acl_newconn(unit, &ep.bdaddr);
        !           603:        else
        !           604:                link = hci_sco_newconn(unit, &ep.bdaddr);
        !           605:
        !           606:        if (link == NULL) {
        !           607:                memset(&rp, 0, sizeof(rp));
        !           608:                bdaddr_copy(&rp.bdaddr, &ep.bdaddr);
        !           609:                rp.reason = 0x0f;       /* Unacceptable BD_ADDR */
        !           610:
        !           611:                hci_send_cmd(unit, HCI_CMD_REJECT_CON, &rp, sizeof(rp));
        !           612:        } else {
        !           613:                memset(&ap, 0, sizeof(ap));
        !           614:                bdaddr_copy(&ap.bdaddr, &ep.bdaddr);
        !           615:                if (unit->hci_link_policy & HCI_LINK_POLICY_ENABLE_ROLE_SWITCH)
        !           616:                        ap.role = HCI_ROLE_MASTER;
        !           617:                else
        !           618:                        ap.role = HCI_ROLE_SLAVE;
        !           619:
        !           620:                hci_send_cmd(unit, HCI_CMD_ACCEPT_CON, &ap, sizeof(ap));
        !           621:        }
        !           622: }
        !           623:
        !           624: /*
        !           625:  * Auth Complete
        !           626:  *
        !           627:  * Authentication has been completed on an ACL link. We can notify the
        !           628:  * upper layer protocols unless further mode changes are pending.
        !           629:  */
        !           630: static void
        !           631: hci_event_auth_compl(struct hci_unit *unit, struct mbuf *m)
        !           632: {
        !           633:        hci_auth_compl_ep ep;
        !           634:        struct hci_link *link;
        !           635:        int err;
        !           636:
        !           637:        KASSERT(m->m_pkthdr.len >= sizeof(ep));
        !           638:        m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
        !           639:        m_adj(m, sizeof(ep));
        !           640:
        !           641:        ep.con_handle = HCI_CON_HANDLE(letoh16(ep.con_handle));
        !           642:
        !           643:        DPRINTFN(1, "handle #%d, status=0x%x\n", ep.con_handle, ep.status);
        !           644:
        !           645:        link = hci_link_lookup_handle(unit, ep.con_handle);
        !           646:        if (link == NULL || link->hl_type != HCI_LINK_ACL)
        !           647:                return;
        !           648:
        !           649:        if (ep.status == 0) {
        !           650:                link->hl_flags |= HCI_LINK_AUTH;
        !           651:
        !           652:                if (link->hl_state == HCI_LINK_WAIT_AUTH)
        !           653:                        link->hl_state = HCI_LINK_OPEN;
        !           654:
        !           655:                err = hci_acl_setmode(link);
        !           656:                if (err == EINPROGRESS)
        !           657:                        return;
        !           658:        }
        !           659:
        !           660:        hci_acl_linkmode(link);
        !           661: }
        !           662:
        !           663: /*
        !           664:  * Encryption Change
        !           665:  *
        !           666:  * The encryption status has changed. Basically, we note the change
        !           667:  * then notify the upper layer protocol unless further mode changes
        !           668:  * are pending.
        !           669:  * Note that if encryption gets disabled when it has been requested,
        !           670:  * we will attempt to enable it again.. (its a feature not a bug :)
        !           671:  */
        !           672: static void
        !           673: hci_event_encryption_change(struct hci_unit *unit, struct mbuf *m)
        !           674: {
        !           675:        hci_encryption_change_ep ep;
        !           676:        struct hci_link *link;
        !           677:        int err;
        !           678:
        !           679:        KASSERT(m->m_pkthdr.len >= sizeof(ep));
        !           680:        m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
        !           681:        m_adj(m, sizeof(ep));
        !           682:
        !           683:        ep.con_handle = HCI_CON_HANDLE(letoh16(ep.con_handle));
        !           684:
        !           685:        DPRINTFN(1, "handle #%d, status=0x%x, encryption_enable=0x%x\n",
        !           686:                 ep.con_handle, ep.status, ep.encryption_enable);
        !           687:
        !           688:        link = hci_link_lookup_handle(unit, ep.con_handle);
        !           689:        if (link == NULL || link->hl_type != HCI_LINK_ACL)
        !           690:                return;
        !           691:
        !           692:        if (ep.status == 0) {
        !           693:                if (ep.encryption_enable == 0)
        !           694:                        link->hl_flags &= ~HCI_LINK_ENCRYPT;
        !           695:                else
        !           696:                        link->hl_flags |= (HCI_LINK_AUTH | HCI_LINK_ENCRYPT);
        !           697:
        !           698:                if (link->hl_state == HCI_LINK_WAIT_ENCRYPT)
        !           699:                        link->hl_state = HCI_LINK_OPEN;
        !           700:
        !           701:                err = hci_acl_setmode(link);
        !           702:                if (err == EINPROGRESS)
        !           703:                        return;
        !           704:        }
        !           705:
        !           706:        hci_acl_linkmode(link);
        !           707: }
        !           708:
        !           709: /*
        !           710:  * Change Connection Link Key Complete
        !           711:  *
        !           712:  * Link keys are handled in userland but if we are waiting to secure
        !           713:  * this link, we should notify the upper protocols. A SECURE request
        !           714:  * only needs a single key change, so we can cancel the request.
        !           715:  */
        !           716: static void
        !           717: hci_event_change_con_link_key_compl(struct hci_unit *unit, struct mbuf *m)
        !           718: {
        !           719:        hci_change_con_link_key_compl_ep ep;
        !           720:        struct hci_link *link;
        !           721:        int err;
        !           722:
        !           723:        KASSERT(m->m_pkthdr.len >= sizeof(ep));
        !           724:        m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
        !           725:        m_adj(m, sizeof(ep));
        !           726:
        !           727:        ep.con_handle = HCI_CON_HANDLE(letoh16(ep.con_handle));
        !           728:
        !           729:        DPRINTFN(1, "handle #%d, status=0x%x\n", ep.con_handle, ep.status);
        !           730:
        !           731:        link = hci_link_lookup_handle(unit, ep.con_handle);
        !           732:        if (link == NULL || link->hl_type != HCI_LINK_ACL)
        !           733:                return;
        !           734:
        !           735:        link->hl_flags &= ~HCI_LINK_SECURE_REQ;
        !           736:
        !           737:        if (ep.status == 0) {
        !           738:                link->hl_flags |= (HCI_LINK_AUTH | HCI_LINK_SECURE);
        !           739:
        !           740:                if (link->hl_state == HCI_LINK_WAIT_SECURE)
        !           741:                        link->hl_state = HCI_LINK_OPEN;
        !           742:
        !           743:                err = hci_acl_setmode(link);
        !           744:                if (err == EINPROGRESS)
        !           745:                        return;
        !           746:        }
        !           747:
        !           748:        hci_acl_linkmode(link);
        !           749: }
        !           750:
        !           751: /*
        !           752:  * process results of read_bdaddr command_complete event
        !           753:  */
        !           754: static void
        !           755: hci_cmd_read_bdaddr(struct hci_unit *unit, struct mbuf *m)
        !           756: {
        !           757:        hci_read_bdaddr_rp rp;
        !           758:        int s;
        !           759:
        !           760:        KASSERT(m->m_pkthdr.len >= sizeof(rp));
        !           761:        m_copydata(m, 0, sizeof(rp), (caddr_t)&rp);
        !           762:        m_adj(m, sizeof(rp));
        !           763:
        !           764:        if (rp.status > 0)
        !           765:                return;
        !           766:
        !           767:        if ((unit->hci_flags & BTF_INIT_BDADDR) == 0)
        !           768:                return;
        !           769:
        !           770:        bdaddr_copy(&unit->hci_bdaddr, &rp.bdaddr);
        !           771:
        !           772:        s = splraiseipl(unit->hci_ipl);
        !           773:        unit->hci_flags &= ~BTF_INIT_BDADDR;
        !           774:        splx(s);
        !           775:
        !           776:        wakeup(unit);
        !           777: }
        !           778:
        !           779: /*
        !           780:  * process results of read_buffer_size command_complete event
        !           781:  */
        !           782: static void
        !           783: hci_cmd_read_buffer_size(struct hci_unit *unit, struct mbuf *m)
        !           784: {
        !           785:        hci_read_buffer_size_rp rp;
        !           786:        int s;
        !           787:
        !           788:        KASSERT(m->m_pkthdr.len >= sizeof(rp));
        !           789:        m_copydata(m, 0, sizeof(rp), (caddr_t)&rp);
        !           790:        m_adj(m, sizeof(rp));
        !           791:
        !           792:        if (rp.status > 0)
        !           793:                return;
        !           794:
        !           795:        if ((unit->hci_flags & BTF_INIT_BUFFER_SIZE) == 0)
        !           796:                return;
        !           797:
        !           798:        unit->hci_max_acl_size = letoh16(rp.max_acl_size);
        !           799:        unit->hci_num_acl_pkts = letoh16(rp.num_acl_pkts);
        !           800:        unit->hci_max_sco_size = rp.max_sco_size;
        !           801:        unit->hci_num_sco_pkts = letoh16(rp.num_sco_pkts);
        !           802:
        !           803:        s = splraiseipl(unit->hci_ipl);
        !           804:        unit->hci_flags &= ~BTF_INIT_BUFFER_SIZE;
        !           805:        splx(s);
        !           806:
        !           807:        wakeup(unit);
        !           808: }
        !           809:
        !           810: /*
        !           811:  * process results of read_local_features command_complete event
        !           812:  */
        !           813: static void
        !           814: hci_cmd_read_local_features(struct hci_unit *unit, struct mbuf *m)
        !           815: {
        !           816:        hci_read_local_features_rp rp;
        !           817:        int s;
        !           818:
        !           819:        KASSERT(m->m_pkthdr.len >= sizeof(rp));
        !           820:        m_copydata(m, 0, sizeof(rp), (caddr_t)&rp);
        !           821:        m_adj(m, sizeof(rp));
        !           822:
        !           823:        if (rp.status > 0)
        !           824:                return;
        !           825:
        !           826:        if ((unit->hci_flags & BTF_INIT_FEATURES) == 0)
        !           827:                return;
        !           828:
        !           829:        unit->hci_lmp_mask = 0;
        !           830:
        !           831:        if (rp.features[0] & HCI_LMP_ROLE_SWITCH)
        !           832:                unit->hci_lmp_mask |= HCI_LINK_POLICY_ENABLE_ROLE_SWITCH;
        !           833:
        !           834:        if (rp.features[0] & HCI_LMP_HOLD_MODE)
        !           835:                unit->hci_lmp_mask |= HCI_LINK_POLICY_ENABLE_HOLD_MODE;
        !           836:
        !           837:        if (rp.features[0] & HCI_LMP_SNIFF_MODE)
        !           838:                unit->hci_lmp_mask |= HCI_LINK_POLICY_ENABLE_SNIFF_MODE;
        !           839:
        !           840:        if (rp.features[1] & HCI_LMP_PARK_MODE)
        !           841:                unit->hci_lmp_mask |= HCI_LINK_POLICY_ENABLE_PARK_MODE;
        !           842:
        !           843:        /* ACL packet mask */
        !           844:        unit->hci_acl_mask = HCI_PKT_DM1 | HCI_PKT_DH1;
        !           845:
        !           846:        if (rp.features[0] & HCI_LMP_3SLOT)
        !           847:                unit->hci_acl_mask |= HCI_PKT_DM3 | HCI_PKT_DH3;
        !           848:
        !           849:        if (rp.features[0] & HCI_LMP_5SLOT)
        !           850:                unit->hci_acl_mask |= HCI_PKT_DM5 | HCI_PKT_DH5;
        !           851:
        !           852:        if ((rp.features[3] & HCI_LMP_EDR_ACL_2MBPS) == 0)
        !           853:                unit->hci_acl_mask |= HCI_PKT_2MBPS_DH1
        !           854:                                    | HCI_PKT_2MBPS_DH3
        !           855:                                    | HCI_PKT_2MBPS_DH5;
        !           856:
        !           857:        if ((rp.features[3] & HCI_LMP_EDR_ACL_3MBPS) == 0)
        !           858:                unit->hci_acl_mask |= HCI_PKT_3MBPS_DH1
        !           859:                                    | HCI_PKT_3MBPS_DH3
        !           860:                                    | HCI_PKT_3MBPS_DH5;
        !           861:
        !           862:        if ((rp.features[4] & HCI_LMP_3SLOT_EDR_ACL) == 0)
        !           863:                unit->hci_acl_mask |= HCI_PKT_2MBPS_DH3
        !           864:                                    | HCI_PKT_3MBPS_DH3;
        !           865:
        !           866:        if ((rp.features[5] & HCI_LMP_5SLOT_EDR_ACL) == 0)
        !           867:                unit->hci_acl_mask |= HCI_PKT_2MBPS_DH5
        !           868:                                    | HCI_PKT_3MBPS_DH5;
        !           869:
        !           870:        unit->hci_packet_type = unit->hci_acl_mask;
        !           871:
        !           872:        /* SCO packet mask */
        !           873:        unit->hci_sco_mask = 0;
        !           874:        if (rp.features[1] & HCI_LMP_SCO_LINK)
        !           875:                unit->hci_sco_mask |= HCI_PKT_HV1;
        !           876:
        !           877:        if (rp.features[1] & HCI_LMP_HV2_PKT)
        !           878:                unit->hci_sco_mask |= HCI_PKT_HV2;
        !           879:
        !           880:        if (rp.features[1] & HCI_LMP_HV3_PKT)
        !           881:                unit->hci_sco_mask |= HCI_PKT_HV3;
        !           882:
        !           883:        if (rp.features[3] & HCI_LMP_EV3_PKT)
        !           884:                unit->hci_sco_mask |= HCI_PKT_EV3;
        !           885:
        !           886:        if (rp.features[4] & HCI_LMP_EV4_PKT)
        !           887:                unit->hci_sco_mask |= HCI_PKT_EV4;
        !           888:
        !           889:        if (rp.features[4] & HCI_LMP_EV5_PKT)
        !           890:                unit->hci_sco_mask |= HCI_PKT_EV5;
        !           891:
        !           892:        /* XXX what do 2MBPS/3MBPS/3SLOT eSCO mean? */
        !           893:
        !           894:        s = splraiseipl(unit->hci_ipl);
        !           895:        unit->hci_flags &= ~BTF_INIT_FEATURES;
        !           896:        splx(s);
        !           897:
        !           898:        wakeup(unit);
        !           899:
        !           900:        DPRINTFN(1, "%s: lmp_mask %4.4x, acl_mask %4.4x, sco_mask %4.4x\n",
        !           901:                unit->hci_devname, unit->hci_lmp_mask,
        !           902:                unit->hci_acl_mask, unit->hci_sco_mask);
        !           903: }
        !           904:
        !           905: /*
        !           906:  * process results of reset command_complete event
        !           907:  *
        !           908:  * This has killed all the connections, so close down anything we have left,
        !           909:  * and reinitialise the unit.
        !           910:  */
        !           911: static void
        !           912: hci_cmd_reset(struct hci_unit *unit, struct mbuf *m)
        !           913: {
        !           914:        hci_reset_rp rp;
        !           915:        struct hci_link *link, *next;
        !           916:        int acl;
        !           917:
        !           918:        KASSERT(m->m_pkthdr.len >= sizeof(rp));
        !           919:        m_copydata(m, 0, sizeof(rp), (caddr_t)&rp);
        !           920:        m_adj(m, sizeof(rp));
        !           921:
        !           922:        if (rp.status != 0)
        !           923:                return;
        !           924:
        !           925:        /*
        !           926:         * release SCO links first, since they may be holding
        !           927:         * an ACL link reference.
        !           928:         */
        !           929:        for (acl = 0 ; acl < 2 ; acl++) {
        !           930:                next = TAILQ_FIRST(&unit->hci_links);
        !           931:                while ((link = next) != NULL) {
        !           932:                        next = TAILQ_NEXT(link, hl_next);
        !           933:                        if (acl || link->hl_type != HCI_LINK_ACL)
        !           934:                                hci_link_free(link, ECONNABORTED);
        !           935:                }
        !           936:        }
        !           937:
        !           938:        unit->hci_num_acl_pkts = 0;
        !           939:        unit->hci_num_sco_pkts = 0;
        !           940:
        !           941:        if (hci_send_cmd(unit, HCI_CMD_READ_BDADDR, NULL, 0))
        !           942:                return;
        !           943:
        !           944:        if (hci_send_cmd(unit, HCI_CMD_READ_BUFFER_SIZE, NULL, 0))
        !           945:                return;
        !           946:
        !           947:        if (hci_send_cmd(unit, HCI_CMD_READ_LOCAL_FEATURES, NULL, 0))
        !           948:                return;
        !           949: }

CVSweb