15d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
25d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * QEMU Bluetooth HCI logic.
35d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
45d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Copyright (C) 2007 OpenMoko, Inc.
55d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Copyright (C) 2008 Andrzej Zaborowski  <balrog@zabor.org>
65d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
75d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * This program is free software; you can redistribute it and/or
85d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * modify it under the terms of the GNU General Public License as
95d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * published by the Free Software Foundation; either version 2 of
105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * the License, or (at your option) any later version.
115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * This program is distributed in the hope that it will be useful,
135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * but WITHOUT ANY WARRANTY; without even the implied warranty of
145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * GNU General Public License for more details.
165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * You should have received a copy of the GNU General Public License
18a7fb77d6eca56e61e94f62e7deb4120b60b1e919David 'Digit' Turner * along with this program; if not, see <http://www.gnu.org/licenses/>.
195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-common.h"
225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-timer.h"
235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "usb.h"
245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "net.h"
255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "bt.h"
265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct bt_hci_s {
285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t *(*evt_packet)(void *opaque);
295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    void (*evt_submit)(void *opaque, int len);
305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    void *opaque;
315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t evt_buf[256];
325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t acl_buf[4096];
345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int acl_len;
355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint16_t asb_handle;
375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint16_t psb_handle;
385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int last_cmd;	/* Note: Always little-endian */
405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_device_s *conn_req_host;
425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct {
445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int inquire;
455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int periodic;
465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int responses_left;
475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int responses;
485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        QEMUTimer *inquiry_done;
495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        QEMUTimer *inquiry_next;
505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int inquiry_length;
515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int inquiry_period;
525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int inquiry_mode;
535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define HCI_HANDLE_OFFSET	0x20
555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define HCI_HANDLES_MAX		0x10
565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        struct bt_hci_master_link_s {
575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            struct bt_link_s *link;
585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            void (*lmp_acl_data)(struct bt_link_s *link,
595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            const uint8_t *data, int start, int len);
605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            QEMUTimer *acl_mode_timer;
615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } handle[HCI_HANDLES_MAX];
625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        uint32_t role_bmp;
635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int last_handle;
645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int connecting;
655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdaddr_t awaiting_bdaddr[HCI_HANDLES_MAX];
665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } lm;
675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t event_mask[8];
695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint16_t voice_setting;	/* Notw: Always little-endian */
705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint16_t conn_accept_tout;
715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUTimer *conn_accept_timer;
725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct HCIInfo info;
745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_device_s device;
755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner};
765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define DEFAULT_RSSI_DBM	20
785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define hci_from_info(ptr)	container_of((ptr), struct bt_hci_s, info)
805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define hci_from_device(ptr)	container_of((ptr), struct bt_hci_s, device)
815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct bt_hci_link_s {
835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_link_s btlink;
845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint16_t handle;	/* Local */
855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner};
865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* LMP layer emulation */
885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if 0
895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_submit_lmp(struct bt_device_s *bt, int length, uint8_t *data)
905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int resp, resplen, error, op, tr;
925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t respdata[17];
935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (length < 1)
955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tr = *data & 1;
985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    op = *(data ++) >> 1;
995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    resp = LMP_ACCEPTED;
1005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    resplen = 2;
1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    respdata[1] = op;
1025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    error = 0;
1035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    length --;
1045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (op >= 0x7c) {	/* Extended opcode */
1065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        op |= *(data ++) << 8;
1075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        resp = LMP_ACCEPTED_EXT;
1085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        resplen = 4;
1095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        respdata[0] = op >> 8;
1105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        respdata[1] = op & 0xff;
1115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        length --;
1125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
1135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    switch (op) {
1155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_ACCEPTED:
1165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* data[0]	Op code
1175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         */
1185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (length < 1) {
1195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
1205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto not_accepted;
1215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
1225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        resp = 0;
1235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
1245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_ACCEPTED_EXT:
1265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* data[0]	Escape op code
1275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         * data[1]	Extended op code
1285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         */
1295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (length < 2) {
1305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
1315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto not_accepted;
1325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
1335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        resp = 0;
1345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
1355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_NOT_ACCEPTED:
1375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* data[0]	Op code
1385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         * data[1]	Error code
1395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         */
1405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (length < 2) {
1415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
1425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto not_accepted;
1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
1445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        resp = 0;
1455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
1465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_NOT_ACCEPTED_EXT:
1485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* data[0]	Op code
1495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         * data[1]	Extended op code
1505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         * data[2]	Error code
1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         */
1525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (length < 3) {
1535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
1545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto not_accepted;
1555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
1565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        resp = 0;
1575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
1585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_HOST_CONNECTION_REQ:
1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_SETUP_COMPLETE:
1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        resp = LMP_SETUP_COMPLETE;
1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        resplen = 1;
1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt->setup = 1;
1665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
1675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_DETACH:
1695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* data[0]	Error code
1705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         */
1715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (length < 1) {
1725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
1735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto not_accepted;
1745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
1755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt->setup = 0;
1765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        resp = 0;
1775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
1785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_SUPERVISION_TIMEOUT:
1805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* data[0,1]	Supervision timeout
1815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         */
1825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (length < 2) {
1835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
1845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto not_accepted;
1855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
1865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        resp = 0;
1875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
1885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_QUALITY_OF_SERVICE:
1905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        resp = 0;
1915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Fall through */
1925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_QOS_REQ:
1935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* data[0,1]	Poll interval
1945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         * data[2]	N(BC)
1955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         */
1965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (length < 3) {
1975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
1985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto not_accepted;
1995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
2005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
2015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_MAX_SLOT:
2035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        resp = 0;
2045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Fall through */
2055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_MAX_SLOT_REQ:
2065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* data[0]	Max slots
2075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         */
2085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (length < 1) {
2095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
2105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto not_accepted;
2115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
2125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
2135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_AU_RAND:
2155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_IN_RAND:
2165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_COMB_KEY:
2175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* data[0-15]	Random number
2185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         */
2195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (length < 16) {
2205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
2215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto not_accepted;
2225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
2235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (op == LMP_AU_RAND) {
2245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (bt->key_present) {
2255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                resp = LMP_SRES;
2265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                resplen = 5;
2275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* XXX: [Part H] Section 6.1 on page 801 */
2285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            } else {
2295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                error = HCI_PIN_OR_KEY_MISSING;
2305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                goto not_accepted;
2315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
2325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else if (op == LMP_IN_RAND) {
2335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            error = HCI_PAIRING_NOT_ALLOWED;
2345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto not_accepted;
2355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
2365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* XXX: [Part H] Section 3.2 on page 779 */
2375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            resp = LMP_UNIT_KEY;
2385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            resplen = 17;
2395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            memcpy(respdata + 1, bt->key, 16);
2405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            error = HCI_UNIT_LINK_KEY_USED;
2425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto not_accepted;
2435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
2445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
2455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_UNIT_KEY:
2475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* data[0-15]	Key
2485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         */
2495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (length < 16) {
2505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
2515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto not_accepted;
2525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
2535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        memcpy(bt->key, data, 16);
2545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt->key_present = 1;
2555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
2565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_SRES:
2585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* data[0-3]	Authentication response
2595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         */
2605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (length < 4) {
2615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
2625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto not_accepted;
2635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
2645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
2655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_CLKOFFSET_REQ:
2675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        resp = LMP_CLKOFFSET_RES;
2685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        resplen = 3;
2695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        respdata[1] = 0x33;
2705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        respdata[2] = 0x33;
2715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
2725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_CLKOFFSET_RES:
2745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* data[0,1]	Clock offset
2755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         * (Slave to master only)
2765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         */
2775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (length < 2) {
2785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
2795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto not_accepted;
2805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
2815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
2825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_VERSION_REQ:
2845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_VERSION_RES:
2855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* data[0]	VersNr
2865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         * data[1,2]	CompId
2875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         * data[3,4]	SubVersNr
2885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         */
2895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (length < 5) {
2905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
2915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto not_accepted;
2925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
2935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (op == LMP_VERSION_REQ) {
2945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            resp = LMP_VERSION_RES;
2955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            resplen = 6;
2965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            respdata[1] = 0x20;
2975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            respdata[2] = 0xff;
2985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            respdata[3] = 0xff;
2995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            respdata[4] = 0xff;
3005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            respdata[5] = 0xff;
3015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else
3025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            resp = 0;
3035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
3045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_FEATURES_REQ:
3065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_FEATURES_RES:
3075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* data[0-7]	Features
3085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         */
3095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (length < 8) {
3105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
3115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto not_accepted;
3125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
3135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (op == LMP_FEATURES_REQ) {
3145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            resp = LMP_FEATURES_RES;
3155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            resplen = 9;
3165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            respdata[1] = (bt->lmp_caps >> 0) & 0xff;
3175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            respdata[2] = (bt->lmp_caps >> 8) & 0xff;
3185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            respdata[3] = (bt->lmp_caps >> 16) & 0xff;
3195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            respdata[4] = (bt->lmp_caps >> 24) & 0xff;
3205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            respdata[5] = (bt->lmp_caps >> 32) & 0xff;
3215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            respdata[6] = (bt->lmp_caps >> 40) & 0xff;
3225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            respdata[7] = (bt->lmp_caps >> 48) & 0xff;
3235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            respdata[8] = (bt->lmp_caps >> 56) & 0xff;
3245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else
3255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            resp = 0;
3265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
3275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_NAME_REQ:
3295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* data[0]	Name offset
3305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         */
3315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (length < 1) {
3325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
3335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto not_accepted;
3345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
3355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        resp = LMP_NAME_RES;
3365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        resplen = 17;
3375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        respdata[1] = data[0];
3385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        respdata[2] = strlen(bt->lmp_name);
3395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        memset(respdata + 3, 0x00, 14);
3405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (respdata[2] > respdata[1])
3415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            memcpy(respdata + 3, bt->lmp_name + respdata[1],
3425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            respdata[2] - respdata[1]);
3435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
3445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LMP_NAME_RES:
3465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* data[0]	Name offset
3475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         * data[1]	Name length
3485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         * data[2-15]	Name fragment
3495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         */
3505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (length < 16) {
3515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
3525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto not_accepted;
3535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
3545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        resp = 0;
3555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
3565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    default:
3585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        error = HCI_UNKNOWN_LMP_PDU;
3595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Fall through */
3605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    not_accepted:
3615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (op >> 8) {
3625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            resp = LMP_NOT_ACCEPTED_EXT;
3635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            resplen = 5;
3645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            respdata[0] = op >> 8;
3655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            respdata[1] = op & 0xff;
3665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            respdata[2] = error;
3675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
3685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            resp = LMP_NOT_ACCEPTED;
3695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            resplen = 3;
3705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            respdata[0] = op & 0xff;
3715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            respdata[1] = error;
3725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
3735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
3745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (resp == 0)
3765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
3775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (resp >> 8) {
3795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        respdata[0] = resp >> 8;
3805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        respdata[1] = resp & 0xff;
3815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else
3825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        respdata[0] = resp & 0xff;
3835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    respdata[0] <<= 1;
3855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    respdata[0] |= tr;
3865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
3875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_submit_raw_acl(struct bt_piconet_s *net, int length, uint8_t *data)
3895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
3905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_device_s *slave;
3915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (length < 1)
3925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
3935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    slave = 0;
3955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if 0
3965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    slave = net->slave;
3975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
3985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    switch (data[0] & 3) {
4005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LLID_ACLC:
4015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_submit_lmp(slave, length - 1, data + 1);
4025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
4035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LLID_ACLU_START:
4045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if 0
4055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_sumbit_l2cap(slave, length - 1, data + 1, (data[0] >> 2) & 1);
4065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        breka;
4075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
4085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    default:
4095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case LLID_ACLU_CONT:
4105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
4115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
4125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
4145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* HCI layer emulation */
4165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Note: we could ignore endiannes because unswapped handles will still
4185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * be valid as connection identifiers for the guest - they don't have to
4195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * be continuously allocated.  We do it though, to preserve similar
4205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * behaviour between hosts.  Some things, like the BD_ADDR cannot be
4215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * preserved though (for example if a real hci is used).  */
42220894ae3fa98f82da925fbeb72e616eef509758aDavid 'Digit' Turner#ifdef HOST_WORDS_BIGENDIAN
4235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# define HNDL(raw)	bswap16(raw)
4245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
4255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner# define HNDL(raw)	(raw)
4265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
4275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic const uint8_t bt_event_reserved_mask[8] = {
4295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    0xff, 0x9f, 0xfb, 0xff, 0x07, 0x18, 0x00, 0x00,
4305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner};
4315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline uint8_t *bt_hci_event_start(struct bt_hci_s *hci,
4335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                int evt, int len)
4345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t *packet, mask;
4365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int mask_byte;
4375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (len > 255) {
4395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "%s: HCI event params too long (%ib)\n",
4405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        __FUNCTION__, len);
4415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        exit(-1);
4425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
4435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    mask_byte = (evt - 1) >> 3;
4455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    mask = 1 << ((evt - 1) & 3);
4465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (mask & bt_event_reserved_mask[mask_byte] & ~hci->event_mask[mask_byte])
4475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
4485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    packet = hci->evt_packet(hci->opaque);
4505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    packet[0] = evt;
4515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    packet[1] = len;
4525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return &packet[2];
4545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void bt_hci_event(struct bt_hci_s *hci, int evt,
4575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                void *params, int len)
4585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t *packet = bt_hci_event_start(hci, evt, len);
4605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!packet)
4625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
4635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (len)
4655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        memcpy(packet, params, len);
4665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->evt_submit(hci->opaque, len + 2);
4685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void bt_hci_event_status(struct bt_hci_s *hci, int status)
4715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    evt_cmd_status params = {
4735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status	= status,
4745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .ncmd	= 1,
4755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .opcode	= hci->last_cmd,
4765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
4775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event(hci, EVT_CMD_STATUS, &params, EVT_CMD_STATUS_SIZE);
4795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void bt_hci_event_complete(struct bt_hci_s *hci,
4825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                void *ret, int len)
4835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t *packet = bt_hci_event_start(hci, EVT_CMD_COMPLETE,
4855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    len + EVT_CMD_COMPLETE_SIZE);
4865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    evt_cmd_complete *params = (evt_cmd_complete *) packet;
4875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!packet)
4895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
4905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params->ncmd	= 1;
4925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params->opcode	= hci->last_cmd;
4935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (len)
4945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        memcpy(&packet[EVT_CMD_COMPLETE_SIZE], ret, len);
4955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->evt_submit(hci->opaque, len + EVT_CMD_COMPLETE_SIZE + 2);
4975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_inquiry_done(void *opaque)
5005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_s *hci = (struct bt_hci_s *) opaque;
5025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t status = HCI_SUCCESS;
5035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!hci->lm.periodic)
5055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->lm.inquire = 0;
5065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* The specification is inconsistent about this one.  Page 565 reads
5085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * "The event parameters of Inquiry Complete event will have a summary
5095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * of the result from the Inquiry process, which reports the number of
5105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * nearby Bluetooth devices that responded [so hci->responses].", but
5115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * Event Parameters (see page 729) has only Status.  */
5125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event(hci, EVT_INQUIRY_COMPLETE, &status, 1);
5135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_inquiry_result_standard(struct bt_hci_s *hci,
5165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                struct bt_device_s *slave)
5175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    inquiry_info params = {
5195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .num_responses		= 1,
5205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .bdaddr			= BAINIT(&slave->bd_addr),
5215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .pscan_rep_mode		= 0x00,	/* R0 */
5225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .pscan_period_mode	= 0x00,	/* P0 - deprecated */
5235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .pscan_mode		= 0x00,	/* Standard scan - deprecated */
5245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .dev_class[0]		= slave->class[0],
5255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .dev_class[1]		= slave->class[1],
5265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .dev_class[2]		= slave->class[2],
5275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* TODO: return the clkoff *differenece* */
5285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .clock_offset		= slave->clkoff,	/* Note: no swapping */
5295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
5305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event(hci, EVT_INQUIRY_RESULT, &params, INQUIRY_INFO_SIZE);
5325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_inquiry_result_with_rssi(struct bt_hci_s *hci,
5355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                struct bt_device_s *slave)
5365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    inquiry_info_with_rssi params = {
5385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .num_responses		= 1,
5395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .bdaddr			= BAINIT(&slave->bd_addr),
5405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .pscan_rep_mode		= 0x00,	/* R0 */
5415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .pscan_period_mode	= 0x00,	/* P0 - deprecated */
5425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .dev_class[0]		= slave->class[0],
5435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .dev_class[1]		= slave->class[1],
5445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .dev_class[2]		= slave->class[2],
5455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* TODO: return the clkoff *differenece* */
5465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .clock_offset		= slave->clkoff,	/* Note: no swapping */
5475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .rssi			= DEFAULT_RSSI_DBM,
5485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
5495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event(hci, EVT_INQUIRY_RESULT_WITH_RSSI,
5515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    &params, INQUIRY_INFO_WITH_RSSI_SIZE);
5525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_inquiry_result(struct bt_hci_s *hci,
5555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                struct bt_device_s *slave)
5565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!slave->inquiry_scan || !hci->lm.responses_left)
5585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
5595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->lm.responses_left --;
5615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->lm.responses ++;
5625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    switch (hci->lm.inquiry_mode) {
5645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case 0x00:
5655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_inquiry_result_standard(hci, slave);
5665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
5675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case 0x01:
5685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_inquiry_result_with_rssi(hci, slave);
5695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
5705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    default:
5715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "%s: bad inquiry mode %02x\n", __FUNCTION__,
5725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        hci->lm.inquiry_mode);
5735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        exit(-1);
5745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
5755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_mod_timer_1280ms(QEMUTimer *timer, int period)
5785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5795973c775c853e26f684de58ad28c267281aaffd6David 'Digit' Turner    qemu_mod_timer(timer, qemu_get_clock_ns(vm_clock) +
580a7fb77d6eca56e61e94f62e7deb4120b60b1e919David 'Digit' Turner                   muldiv64(period << 7, get_ticks_per_sec(), 100));
5815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
5825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_inquiry_start(struct bt_hci_s *hci, int length)
5845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
5855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_device_s *slave;
5865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->lm.inquiry_length = length;
5885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (slave = hci->device.net->slave; slave; slave = slave->next)
5895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Don't uncover ourselves.  */
5905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (slave != &hci->device)
5915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_inquiry_result(hci, slave);
5925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* TODO: register for a callback on a new device's addition to the
5945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * scatternet so that if it's added before inquiry_length expires,
5955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * an Inquiry Result is generated immediately.  Alternatively re-loop
5965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * through the devices on the inquiry_length expiration and report
5975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * devices not seen before.  */
5985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (hci->lm.responses_left)
5995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_mod_timer_1280ms(hci->lm.inquiry_done, hci->lm.inquiry_length);
6005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else
6015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_inquiry_done(hci);
6025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (hci->lm.periodic)
6045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_mod_timer_1280ms(hci->lm.inquiry_next, hci->lm.inquiry_period);
6055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_inquiry_next(void *opaque)
6085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_s *hci = (struct bt_hci_s *) opaque;
6105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->lm.responses_left += hci->lm.responses;
6125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->lm.responses = 0;
6135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_inquiry_start(hci,  hci->lm.inquiry_length);
6145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline int bt_hci_handle_bad(struct bt_hci_s *hci, uint16_t handle)
6175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return !(handle & HCI_HANDLE_OFFSET) ||
6195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            handle >= (HCI_HANDLE_OFFSET | HCI_HANDLES_MAX) ||
6205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            !hci->lm.handle[handle & ~HCI_HANDLE_OFFSET].link;
6215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline int bt_hci_role_master(struct bt_hci_s *hci, uint16_t handle)
6245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return !!(hci->lm.role_bmp & (1 << (handle & ~HCI_HANDLE_OFFSET)));
6265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline struct bt_device_s *bt_hci_remote_dev(struct bt_hci_s *hci,
6295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                uint16_t handle)
6305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_link_s *link = hci->lm.handle[handle & ~HCI_HANDLE_OFFSET].link;
6325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return bt_hci_role_master(hci, handle) ? link->slave : link->host;
6345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_mode_tick(void *opaque);
6375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_lmp_link_establish(struct bt_hci_s *hci,
6385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                struct bt_link_s *link, int master)
6395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->lm.handle[hci->lm.last_handle].link = link;
6415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (master) {
6435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* We are the master side of an ACL link */
6445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->lm.role_bmp |= 1 << hci->lm.last_handle;
6455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->lm.handle[hci->lm.last_handle].lmp_acl_data =
6475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                link->slave->lmp_acl_data;
6485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
6495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* We are the slave side of an ACL link */
6505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->lm.role_bmp &= ~(1 << hci->lm.last_handle);
6515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->lm.handle[hci->lm.last_handle].lmp_acl_data =
6535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                link->host->lmp_acl_resp;
6545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
6555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Mode */
6575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (master) {
6585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        link->acl_mode = acl_active;
6595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->lm.handle[hci->lm.last_handle].acl_mode_timer =
6605973c775c853e26f684de58ad28c267281aaffd6David 'Digit' Turner                qemu_new_timer_ns(vm_clock, bt_hci_mode_tick, link);
6615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
6625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_lmp_link_teardown(struct bt_hci_s *hci, uint16_t handle)
6655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    handle &= ~HCI_HANDLE_OFFSET;
6675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->lm.handle[handle].link = NULL;
6685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bt_hci_role_master(hci, handle)) {
6705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_del_timer(hci->lm.handle[handle].acl_mode_timer);
6715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_free_timer(hci->lm.handle[handle].acl_mode_timer);
6725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
6735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int bt_hci_connect(struct bt_hci_s *hci, bdaddr_t *bdaddr)
6765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_device_s *slave;
6785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_link_s link;
6795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (slave = hci->device.net->slave; slave; slave = slave->next)
6815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (slave->page_scan && !bacmp(&slave->bd_addr, bdaddr))
6825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
6835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!slave || slave == &hci->device)
6845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENODEV;
6855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bacpy(&hci->lm.awaiting_bdaddr[hci->lm.connecting ++], &slave->bd_addr);
6875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    link.slave = slave;
6895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    link.host = &hci->device;
6905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    link.slave->lmp_connection_request(&link);	/* Always last */
6915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
6935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_connection_reject(struct bt_hci_s *hci,
6965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                struct bt_device_s *host, uint8_t because)
6975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_link_s link = {
6995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .slave	= &hci->device,
7005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .host	= host,
7015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Rest uninitialised */
7025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
7035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    host->reject_reason = because;
7055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    host->lmp_connection_complete(&link);
7065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
7075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_connection_reject_event(struct bt_hci_s *hci,
7095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                bdaddr_t *bdaddr)
7105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
7115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    evt_conn_complete params;
7125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.status	= HCI_NO_CONNECTION;
7145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.handle	= 0;
7155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bacpy(&params.bdaddr, bdaddr);
7165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.link_type	= ACL_LINK;
7175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.encr_mode	= 0x00;		/* Encryption not required */
7185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event(hci, EVT_CONN_COMPLETE, &params, EVT_CONN_COMPLETE_SIZE);
7195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
7205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_connection_accept(struct bt_hci_s *hci,
7225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                struct bt_device_s *host)
7235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
7245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_link_s *link = qemu_mallocz(sizeof(struct bt_hci_link_s));
7255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    evt_conn_complete params;
7265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint16_t handle;
7275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t status = HCI_SUCCESS;
7285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int tries = HCI_HANDLES_MAX;
7295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Make a connection handle */
7315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    do {
7325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        while (hci->lm.handle[++ hci->lm.last_handle].link && -- tries)
7335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            hci->lm.last_handle &= HCI_HANDLES_MAX - 1;
7345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        handle = hci->lm.last_handle | HCI_HANDLE_OFFSET;
7355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } while ((handle == hci->asb_handle || handle == hci->psb_handle) &&
7365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tries);
7375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!tries) {
7395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_free(link);
7405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_connection_reject(hci, host, HCI_REJECTED_LIMITED_RESOURCES);
7415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        status = HCI_NO_CONNECTION;
7425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto complete;
7435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
7445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    link->btlink.slave	= &hci->device;
7465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    link->btlink.host	= host;
7475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    link->handle = handle;
7485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Link established */
7505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_lmp_link_establish(hci, &link->btlink, 0);
7515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnercomplete:
7535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.status	= status;
7545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.handle	= HNDL(handle);
7555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bacpy(&params.bdaddr, &host->bd_addr);
7565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.link_type	= ACL_LINK;
7575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.encr_mode	= 0x00;		/* Encryption not required */
7585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event(hci, EVT_CONN_COMPLETE, &params, EVT_CONN_COMPLETE_SIZE);
7595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Neets to be done at the very end because it can trigger a (nested)
7615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * disconnected, in case the other and had cancelled the request
7625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * locally.  */
7635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (status == HCI_SUCCESS) {
7645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        host->reject_reason = 0;
7655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        host->lmp_connection_complete(&link->btlink);
7665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
7675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
7685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_lmp_connection_request(struct bt_link_s *link)
7705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
7715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_s *hci = hci_from_device(link->slave);
7725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    evt_conn_request params;
7735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (hci->conn_req_host) {
7755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_connection_reject(hci, link->host,
7765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                 HCI_REJECTED_LIMITED_RESOURCES);
7775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
7785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
7795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->conn_req_host = link->host;
7805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* TODO: if masked and auto-accept, then auto-accept,
7815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * if masked and not auto-accept, then auto-reject */
7825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* TODO: kick the hci->conn_accept_timer, timeout after
7835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * hci->conn_accept_tout * 0.625 msec */
7845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bacpy(&params.bdaddr, &link->host->bd_addr);
7865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    memcpy(&params.dev_class, &link->host->class, sizeof(params.dev_class));
7875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.link_type	= ACL_LINK;
7885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event(hci, EVT_CONN_REQUEST, &params, EVT_CONN_REQUEST_SIZE);
7895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return;
7905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
7915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_conn_accept_timeout(void *opaque)
7935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
7945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_s *hci = (struct bt_hci_s *) opaque;
7955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!hci->conn_req_host)
7975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Already accepted or rejected.  If the other end cancelled the
7985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         * connection request then we still have to reject or accept it
7995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         * and then we'll get a disconnect.  */
8005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
8015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* TODO */
8035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Remove from the list of devices which we wanted to connect to and
8065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * are awaiting a response from.  If the callback sees a response from
8075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * a device which is not on the list it will assume it's a connection
8085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * that's been cancelled by the host in the meantime and immediately
8095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * try to detach the link and send a Connection Complete.  */
8105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int bt_hci_lmp_connection_ready(struct bt_hci_s *hci,
8115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                bdaddr_t *bdaddr)
8125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
8135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int i;
8145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (i = 0; i < hci->lm.connecting; i ++)
8165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!bacmp(&hci->lm.awaiting_bdaddr[i], bdaddr)) {
8175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (i < -- hci->lm.connecting)
8185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                bacpy(&hci->lm.awaiting_bdaddr[i],
8195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                &hci->lm.awaiting_bdaddr[hci->lm.connecting]);
8205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return 0;
8215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
8225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 1;
8245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_lmp_connection_complete(struct bt_link_s *link)
8275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
8285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_s *hci = hci_from_device(link->host);
8295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    evt_conn_complete params;
8305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint16_t handle;
8315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint8_t status = HCI_SUCCESS;
8325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int tries = HCI_HANDLES_MAX;
8335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bt_hci_lmp_connection_ready(hci, &link->slave->bd_addr)) {
8355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!hci->device.reject_reason)
8365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            link->slave->lmp_disconnect_slave(link);
8375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        handle = 0;
8385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        status = HCI_NO_CONNECTION;
8395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto complete;
8405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
8415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (hci->device.reject_reason) {
8435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        handle = 0;
8445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        status = hci->device.reject_reason;
8455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto complete;
8465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
8475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Make a connection handle */
8495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    do {
8505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        while (hci->lm.handle[++ hci->lm.last_handle].link && -- tries)
8515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            hci->lm.last_handle &= HCI_HANDLES_MAX - 1;
8525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        handle = hci->lm.last_handle | HCI_HANDLE_OFFSET;
8535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } while ((handle == hci->asb_handle || handle == hci->psb_handle) &&
8545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tries);
8555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!tries) {
8575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        link->slave->lmp_disconnect_slave(link);
8585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        status = HCI_NO_CONNECTION;
8595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto complete;
8605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
8615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Link established */
8635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    link->handle = handle;
8645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_lmp_link_establish(hci, link, 1);
8655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnercomplete:
8675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.status	= status;
8685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.handle	= HNDL(handle);
8695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.link_type	= ACL_LINK;
8705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bacpy(&params.bdaddr, &link->slave->bd_addr);
8715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.encr_mode	= 0x00;		/* Encryption not required */
8725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event(hci, EVT_CONN_COMPLETE, &params, EVT_CONN_COMPLETE_SIZE);
8735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
8745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_disconnect(struct bt_hci_s *hci,
8765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                uint16_t handle, int reason)
8775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
8785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_link_s *btlink =
8795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            hci->lm.handle[handle & ~HCI_HANDLE_OFFSET].link;
8805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_link_s *link;
8815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    evt_disconn_complete params;
8825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bt_hci_role_master(hci, handle)) {
8845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        btlink->slave->reject_reason = reason;
8855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        btlink->slave->lmp_disconnect_slave(btlink);
8865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* The link pointer is invalid from now on */
8875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto complete;
8895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
8905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    btlink->host->reject_reason = reason;
8925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    btlink->host->lmp_disconnect_master(btlink);
8935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* We are the slave, we get to clean this burden */
8955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    link = (struct bt_hci_link_s *) btlink;
8965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free(link);
8975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnercomplete:
8995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_lmp_link_teardown(hci, handle);
9005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.status	= HCI_SUCCESS;
9025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.handle	= HNDL(handle);
9035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.reason	= HCI_CONNECTION_TERMINATED;
9045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event(hci, EVT_DISCONN_COMPLETE,
9055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    &params, EVT_DISCONN_COMPLETE_SIZE);
9065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
9075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* TODO: use only one function */
9095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_lmp_disconnect_host(struct bt_link_s *link)
9105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
9115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_s *hci = hci_from_device(link->host);
9125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint16_t handle = link->handle;
9135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    evt_disconn_complete params;
9145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_lmp_link_teardown(hci, handle);
9165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.status	= HCI_SUCCESS;
9185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.handle	= HNDL(handle);
9195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.reason	= hci->device.reject_reason;
9205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event(hci, EVT_DISCONN_COMPLETE,
9215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    &params, EVT_DISCONN_COMPLETE_SIZE);
9225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
9235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_lmp_disconnect_slave(struct bt_link_s *btlink)
9255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
9265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_link_s *link = (struct bt_hci_link_s *) btlink;
9275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_s *hci = hci_from_device(btlink->slave);
9285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint16_t handle = link->handle;
9295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    evt_disconn_complete params;
9305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free(link);
9325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_lmp_link_teardown(hci, handle);
9345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.status	= HCI_SUCCESS;
9365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.handle	= HNDL(handle);
9375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.reason	= hci->device.reject_reason;
9385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event(hci, EVT_DISCONN_COMPLETE,
9395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    &params, EVT_DISCONN_COMPLETE_SIZE);
9405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
9415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int bt_hci_name_req(struct bt_hci_s *hci, bdaddr_t *bdaddr)
9435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
9445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_device_s *slave;
9455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    evt_remote_name_req_complete params;
9465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int len;
9475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (slave = hci->device.net->slave; slave; slave = slave->next)
9495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (slave->page_scan && !bacmp(&slave->bd_addr, bdaddr))
9505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
9515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!slave)
9525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENODEV;
9535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_status(hci, HCI_SUCCESS);
9555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.status       = HCI_SUCCESS;
9575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bacpy(&params.bdaddr, &slave->bd_addr);
9585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    len = snprintf(params.name, sizeof(params.name),
9595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    "%s", slave->lmp_name ?: "");
9605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    memset(params.name + len, 0, sizeof(params.name) - len);
9615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event(hci, EVT_REMOTE_NAME_REQ_COMPLETE,
9625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    &params, EVT_REMOTE_NAME_REQ_COMPLETE_SIZE);
9635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
9655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
9665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int bt_hci_features_req(struct bt_hci_s *hci, uint16_t handle)
9685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
9695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_device_s *slave;
9705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    evt_read_remote_features_complete params;
9715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bt_hci_handle_bad(hci, handle))
9735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENODEV;
9745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    slave = bt_hci_remote_dev(hci, handle);
9765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_status(hci, HCI_SUCCESS);
9785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.status	= HCI_SUCCESS;
9805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.handle	= HNDL(handle);
9815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.features[0]	= (slave->lmp_caps >>  0) & 0xff;
9825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.features[1]	= (slave->lmp_caps >>  8) & 0xff;
9835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.features[2]	= (slave->lmp_caps >> 16) & 0xff;
9845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.features[3]	= (slave->lmp_caps >> 24) & 0xff;
9855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.features[4]	= (slave->lmp_caps >> 32) & 0xff;
9865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.features[5]	= (slave->lmp_caps >> 40) & 0xff;
9875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.features[6]	= (slave->lmp_caps >> 48) & 0xff;
9885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.features[7]	= (slave->lmp_caps >> 56) & 0xff;
9895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event(hci, EVT_READ_REMOTE_FEATURES_COMPLETE,
9905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    &params, EVT_READ_REMOTE_FEATURES_COMPLETE_SIZE);
9915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
9935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
9945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int bt_hci_version_req(struct bt_hci_s *hci, uint16_t handle)
9965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
9975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    evt_read_remote_version_complete params;
9985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bt_hci_handle_bad(hci, handle))
10005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENODEV;
10015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1002a25351325187eb8eff8b9b090acd8f2d7684c6ffDavid Turner    bt_hci_remote_dev(hci, handle);
10035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_status(hci, HCI_SUCCESS);
10055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.status	= HCI_SUCCESS;
10075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.handle	= HNDL(handle);
10085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.lmp_ver	= 0x03;
10095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.manufacturer	= cpu_to_le16(0xa000);
10105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.lmp_subver	= cpu_to_le16(0xa607);
10115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event(hci, EVT_READ_REMOTE_VERSION_COMPLETE,
10125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    &params, EVT_READ_REMOTE_VERSION_COMPLETE_SIZE);
10135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
10155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int bt_hci_clkoffset_req(struct bt_hci_s *hci, uint16_t handle)
10185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
10195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_device_s *slave;
10205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    evt_read_clock_offset_complete params;
10215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bt_hci_handle_bad(hci, handle))
10235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENODEV;
10245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    slave = bt_hci_remote_dev(hci, handle);
10265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_status(hci, HCI_SUCCESS);
10285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.status	= HCI_SUCCESS;
10305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.handle	= HNDL(handle);
10315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* TODO: return the clkoff *differenece* */
10325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.clock_offset	= slave->clkoff;	/* Note: no swapping */
10335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event(hci, EVT_READ_CLOCK_OFFSET_COMPLETE,
10345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    &params, EVT_READ_CLOCK_OFFSET_COMPLETE_SIZE);
10355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
10375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_event_mode(struct bt_hci_s *hci, struct bt_link_s *link,
10405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                uint16_t handle)
10415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
10425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    evt_mode_change params = {
10435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status		= HCI_SUCCESS,
10445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .handle		= HNDL(handle),
10455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .mode		= link->acl_mode,
10465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .interval	= cpu_to_le16(link->acl_interval),
10475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
10485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event(hci, EVT_MODE_CHANGE, &params, EVT_MODE_CHANGE_SIZE);
10505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_lmp_mode_change_master(struct bt_hci_s *hci,
10535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                struct bt_link_s *link, int mode, uint16_t interval)
10545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
10555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    link->acl_mode = mode;
10565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    link->acl_interval = interval;
10575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_mode(hci, link, link->handle);
10595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    link->slave->lmp_mode_change(link);
10615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_lmp_mode_change_slave(struct bt_link_s *btlink)
10645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
10655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_link_s *link = (struct bt_hci_link_s *) btlink;
10665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_s *hci = hci_from_device(btlink->slave);
10675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_mode(hci, btlink, link->handle);
10695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int bt_hci_mode_change(struct bt_hci_s *hci, uint16_t handle,
10725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                int interval, int mode)
10735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
10745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_master_link_s *link;
10755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bt_hci_handle_bad(hci, handle) || !bt_hci_role_master(hci, handle))
10775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENODEV;
10785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    link = &hci->lm.handle[handle & ~HCI_HANDLE_OFFSET];
10805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (link->link->acl_mode != acl_active) {
10815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_status(hci, HCI_COMMAND_DISALLOWED);
10825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 0;
10835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
10845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_status(hci, HCI_SUCCESS);
10865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10875973c775c853e26f684de58ad28c267281aaffd6David 'Digit' Turner    qemu_mod_timer(link->acl_mode_timer, qemu_get_clock_ns(vm_clock) +
1088a7fb77d6eca56e61e94f62e7deb4120b60b1e919David 'Digit' Turner                   muldiv64(interval * 625, get_ticks_per_sec(), 1000000));
10895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_lmp_mode_change_master(hci, link->link, mode, interval);
10905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
10925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
10935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int bt_hci_mode_cancel(struct bt_hci_s *hci, uint16_t handle, int mode)
10955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
10965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_master_link_s *link;
10975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
10985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bt_hci_handle_bad(hci, handle) || !bt_hci_role_master(hci, handle))
10995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENODEV;
11005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    link = &hci->lm.handle[handle & ~HCI_HANDLE_OFFSET];
11025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (link->link->acl_mode != mode) {
11035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_status(hci, HCI_COMMAND_DISALLOWED);
11045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return 0;
11065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
11075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_status(hci, HCI_SUCCESS);
11095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_del_timer(link->acl_mode_timer);
11115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_lmp_mode_change_master(hci, link->link, acl_active, 0);
11125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
11145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
11155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_mode_tick(void *opaque)
11175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
11185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_link_s *link = opaque;
11195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_s *hci = hci_from_device(link->host);
11205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_lmp_mode_change_master(hci, link, acl_active, 0);
11225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
11235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_reset(struct bt_hci_s *hci)
11255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
11265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->acl_len = 0;
11275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->last_cmd = 0;
11285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->lm.connecting = 0;
11295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->event_mask[0] = 0xff;
11315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->event_mask[1] = 0xff;
11325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->event_mask[2] = 0xff;
11335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->event_mask[3] = 0xff;
11345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->event_mask[4] = 0xff;
11355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->event_mask[5] = 0x1f;
11365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->event_mask[6] = 0x00;
11375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->event_mask[7] = 0x00;
11385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->device.inquiry_scan = 0;
11395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->device.page_scan = 0;
11405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (hci->device.lmp_name)
11415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_free((void *) hci->device.lmp_name);
11425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->device.lmp_name = NULL;
11435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->device.class[0] = 0x00;
11445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->device.class[1] = 0x00;
11455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->device.class[2] = 0x00;
11465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->voice_setting = 0x0000;
11475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->conn_accept_tout = 0x1f40;
11485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->lm.inquiry_mode = 0x00;
11495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->psb_handle = 0x000;
11515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->asb_handle = 0x000;
11525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* XXX: qemu_del_timer(sl->acl_mode_timer); for all links */
11545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_del_timer(hci->lm.inquiry_done);
11555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_del_timer(hci->lm.inquiry_next);
11565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_del_timer(hci->conn_accept_timer);
11575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
11585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_read_local_version_rp(struct bt_hci_s *hci)
11605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
11615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    read_local_version_rp lv = {
11625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status		= HCI_SUCCESS,
11635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .hci_ver	= 0x03,
11645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .hci_rev	= cpu_to_le16(0xa607),
11655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .lmp_ver	= 0x03,
11665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .manufacturer	= cpu_to_le16(0xa000),
11675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .lmp_subver	= cpu_to_le16(0xa607),
11685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
11695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_complete(hci, &lv, READ_LOCAL_VERSION_RP_SIZE);
11715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
11725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_read_local_commands_rp(struct bt_hci_s *hci)
11745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
11755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    read_local_commands_rp lc = {
11765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status		= HCI_SUCCESS,
11775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .commands	= {
11785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* Keep updated! */
11795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* Also, keep in sync with hci->device.lmp_caps in bt_new_hci */
11805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            0xbf, 0x80, 0xf9, 0x03, 0xb2, 0xc0, 0x03, 0xc3,
11815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            0x00, 0x0f, 0x80, 0x00, 0xc0, 0x00, 0xe8, 0x13,
11825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        },
11895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
11905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_complete(hci, &lc, READ_LOCAL_COMMANDS_RP_SIZE);
11925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
11935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
11945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_read_local_features_rp(struct bt_hci_s *hci)
11955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
11965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    read_local_features_rp lf = {
11975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status		= HCI_SUCCESS,
11985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .features	= {
11995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            (hci->device.lmp_caps >>  0) & 0xff,
12005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            (hci->device.lmp_caps >>  8) & 0xff,
12015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            (hci->device.lmp_caps >> 16) & 0xff,
12025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            (hci->device.lmp_caps >> 24) & 0xff,
12035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            (hci->device.lmp_caps >> 32) & 0xff,
12045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            (hci->device.lmp_caps >> 40) & 0xff,
12055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            (hci->device.lmp_caps >> 48) & 0xff,
12065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            (hci->device.lmp_caps >> 56) & 0xff,
12075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        },
12085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
12095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_complete(hci, &lf, READ_LOCAL_FEATURES_RP_SIZE);
12115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
12125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_read_local_ext_features_rp(struct bt_hci_s *hci, int page)
12145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
12155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    read_local_ext_features_rp lef = {
12165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status		= HCI_SUCCESS,
12175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .page_num	= page,
12185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .max_page_num	= 0x00,
12195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .features	= {
12205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* Keep updated! */
12215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            0x5f, 0x35, 0x85, 0x7e, 0x9b, 0x19, 0x00, 0x80,
12225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        },
12235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
12245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (page)
12255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        memset(lef.features, 0, sizeof(lef.features));
12265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_complete(hci, &lef, READ_LOCAL_EXT_FEATURES_RP_SIZE);
12285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
12295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_read_buffer_size_rp(struct bt_hci_s *hci)
12315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
12325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    read_buffer_size_rp bs = {
12335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* This can be made configurable, for one standard USB dongle HCI
12345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         * the four values are cpu_to_le16(0x0180), 0x40,
12355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         * cpu_to_le16(0x0008), cpu_to_le16(0x0008).  */
12365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status		= HCI_SUCCESS,
12375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .acl_mtu	= cpu_to_le16(0x0200),
12385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .sco_mtu	= 0,
12395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .acl_max_pkt	= cpu_to_le16(0x0001),
12405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .sco_max_pkt	= cpu_to_le16(0x0000),
12415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
12425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_complete(hci, &bs, READ_BUFFER_SIZE_RP_SIZE);
12445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
12455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Deprecated in V2.0 (page 661) */
12475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_read_country_code_rp(struct bt_hci_s *hci)
12485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
12495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    read_country_code_rp cc ={
12505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status		= HCI_SUCCESS,
12515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .country_code	= 0x00,	/* North America & Europe^1 and Japan */
12525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
12535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_complete(hci, &cc, READ_COUNTRY_CODE_RP_SIZE);
12555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* ^1. Except France, sorry */
12575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
12585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_read_bd_addr_rp(struct bt_hci_s *hci)
12605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
12615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    read_bd_addr_rp ba = {
12625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status = HCI_SUCCESS,
12635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .bdaddr = BAINIT(&hci->device.bd_addr),
12645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
12655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_complete(hci, &ba, READ_BD_ADDR_RP_SIZE);
12675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
12685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int bt_hci_link_quality_rp(struct bt_hci_s *hci, uint16_t handle)
12705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
12715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    read_link_quality_rp lq = {
12725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status		= HCI_SUCCESS,
12735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .handle		= HNDL(handle),
12745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .link_quality	= 0xff,
12755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
12765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bt_hci_handle_bad(hci, handle))
12785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        lq.status = HCI_NO_CONNECTION;
12795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_complete(hci, &lq, READ_LINK_QUALITY_RP_SIZE);
12815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
12825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
12835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Generate a Command Complete event with only the Status parameter */
12855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void bt_hci_event_complete_status(struct bt_hci_s *hci,
12865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                uint8_t status)
12875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
12885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_complete(hci, &status, 1);
12895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
12905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void bt_hci_event_complete_conn_cancel(struct bt_hci_s *hci,
12925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                uint8_t status, bdaddr_t *bd_addr)
12935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
12945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    create_conn_cancel_rp params = {
12955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status = status,
12965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .bdaddr = BAINIT(bd_addr),
12975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
12985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_complete(hci, &params, CREATE_CONN_CANCEL_RP_SIZE);
13005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
13015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void bt_hci_event_auth_complete(struct bt_hci_s *hci,
13035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                uint16_t handle)
13045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
13055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    evt_auth_complete params = {
13065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status = HCI_SUCCESS,
13075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .handle = HNDL(handle),
13085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
13095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event(hci, EVT_AUTH_COMPLETE, &params, EVT_AUTH_COMPLETE_SIZE);
13115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
13125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void bt_hci_event_encrypt_change(struct bt_hci_s *hci,
13145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                uint16_t handle, uint8_t mode)
13155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
13165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    evt_encrypt_change params = {
13175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status		= HCI_SUCCESS,
13185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .handle		= HNDL(handle),
13195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .encrypt	= mode,
13205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
13215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event(hci, EVT_ENCRYPT_CHANGE, &params, EVT_ENCRYPT_CHANGE_SIZE);
13235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
13245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void bt_hci_event_complete_name_cancel(struct bt_hci_s *hci,
13265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                bdaddr_t *bd_addr)
13275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
13285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    remote_name_req_cancel_rp params = {
13295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status = HCI_INVALID_PARAMETERS,
13305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .bdaddr = BAINIT(bd_addr),
13315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
13325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_complete(hci, &params, REMOTE_NAME_REQ_CANCEL_RP_SIZE);
13345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
13355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void bt_hci_event_read_remote_ext_features(struct bt_hci_s *hci,
13375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                uint16_t handle)
13385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
13395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    evt_read_remote_ext_features_complete params = {
13405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status = HCI_UNSUPPORTED_FEATURE,
13415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .handle = HNDL(handle),
13425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Rest uninitialised */
13435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
13445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event(hci, EVT_READ_REMOTE_EXT_FEATURES_COMPLETE,
13465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    &params, EVT_READ_REMOTE_EXT_FEATURES_COMPLETE_SIZE);
13475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
13485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void bt_hci_event_complete_lmp_handle(struct bt_hci_s *hci,
13505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                uint16_t handle)
13515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
13525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    read_lmp_handle_rp params = {
13535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status		= HCI_NO_CONNECTION,
13545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .handle		= HNDL(handle),
13555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .reserved	= 0,
13565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Rest uninitialised */
13575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
13585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_complete(hci, &params, READ_LMP_HANDLE_RP_SIZE);
13605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
13615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void bt_hci_event_complete_role_discovery(struct bt_hci_s *hci,
13635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                int status, uint16_t handle, int master)
13645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
13655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    role_discovery_rp params = {
13665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status		= status,
13675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .handle		= HNDL(handle),
13685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .role		= master ? 0x00 : 0x01,
13695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
13705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_complete(hci, &params, ROLE_DISCOVERY_RP_SIZE);
13725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
13735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void bt_hci_event_complete_flush(struct bt_hci_s *hci,
13755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                int status, uint16_t handle)
13765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
13775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    flush_rp params = {
13785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status		= status,
13795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .handle		= HNDL(handle),
13805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
13815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_complete(hci, &params, FLUSH_RP_SIZE);
13835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
13845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void bt_hci_event_complete_read_local_name(struct bt_hci_s *hci)
13865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
13875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    read_local_name_rp params;
13885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.status = HCI_SUCCESS;
13895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    memset(params.name, 0, sizeof(params.name));
13905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (hci->device.lmp_name)
13915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        strncpy(params.name, hci->device.lmp_name, sizeof(params.name));
13925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_complete(hci, &params, READ_LOCAL_NAME_RP_SIZE);
13945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
13955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
13965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void bt_hci_event_complete_read_conn_accept_timeout(
13975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                struct bt_hci_s *hci)
13985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
13995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    read_conn_accept_timeout_rp params = {
14005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status		= HCI_SUCCESS,
14015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .timeout	= cpu_to_le16(hci->conn_accept_tout),
14025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
14035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_complete(hci, &params, READ_CONN_ACCEPT_TIMEOUT_RP_SIZE);
14055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
14065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void bt_hci_event_complete_read_scan_enable(struct bt_hci_s *hci)
14085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
14095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    read_scan_enable_rp params = {
14105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status = HCI_SUCCESS,
14115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .enable =
14125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                (hci->device.inquiry_scan ? SCAN_INQUIRY : 0) |
14135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                (hci->device.page_scan ? SCAN_PAGE : 0),
14145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
14155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_complete(hci, &params, READ_SCAN_ENABLE_RP_SIZE);
14175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
14185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void bt_hci_event_complete_read_local_class(struct bt_hci_s *hci)
14205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
14215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    read_class_of_dev_rp params;
14225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params.status = HCI_SUCCESS;
14245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    memcpy(params.dev_class, hci->device.class, sizeof(params.dev_class));
14255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_complete(hci, &params, READ_CLASS_OF_DEV_RP_SIZE);
14275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
14285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void bt_hci_event_complete_voice_setting(struct bt_hci_s *hci)
14305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
14315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    read_voice_setting_rp params = {
14325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status		= HCI_SUCCESS,
14335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .voice_setting	= hci->voice_setting,	/* Note: no swapping */
14345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
14355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_complete(hci, &params, READ_VOICE_SETTING_RP_SIZE);
14375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
14385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void bt_hci_event_complete_read_inquiry_mode(
14405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                struct bt_hci_s *hci)
14415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
14425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    read_inquiry_mode_rp params = {
14435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .status		= HCI_SUCCESS,
14445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        .mode		= hci->lm.inquiry_mode,
14455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    };
14465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_complete(hci, &params, READ_INQUIRY_MODE_RP_SIZE);
14485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
14495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void bt_hci_event_num_comp_pkts(struct bt_hci_s *hci,
14515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                uint16_t handle, int packets)
14525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
14535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint16_t buf[EVT_NUM_COMP_PKTS_SIZE(1) / 2 + 1];
14545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    evt_num_comp_pkts *params = (void *) ((uint8_t *) buf + 1);
14555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params->num_hndl			= 1;
14575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params->connection->handle		= HNDL(handle);
14585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    params->connection->num_packets	= cpu_to_le16(packets);
14595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event(hci, EVT_NUM_COMP_PKTS, params, EVT_NUM_COMP_PKTS_SIZE(1));
14615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
14625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_submit_hci(struct HCIInfo *info,
14645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                const uint8_t *data, int length)
14655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
14665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_s *hci = hci_from_info(info);
14675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint16_t cmd;
14685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int paramlen, i;
14695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (length < HCI_COMMAND_HDR_SIZE)
14715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto short_hci;
14725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    memcpy(&hci->last_cmd, data, 2);
14745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cmd = (data[1] << 8) | data[0];
14765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    paramlen = data[2];
14775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (cmd_opcode_ogf(cmd) == 0 || cmd_opcode_ocf(cmd) == 0)	/* NOP */
14785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
14795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    data += HCI_COMMAND_HDR_SIZE;
14815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    length -= HCI_COMMAND_HDR_SIZE;
14825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (paramlen > length)
14845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
14855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define PARAM(cmd, param)	(((cmd##_cp *) data)->param)
14875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define PARAM16(cmd, param)	le16_to_cpup(&PARAM(cmd, param))
14885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define PARAMHANDLE(cmd)	HNDL(PARAM(cmd, handle))
14895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define LENGTH_CHECK(cmd)	if (length < sizeof(cmd##_cp)) goto short_hci
14905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Note: the supported commands bitmask in bt_hci_read_local_commands_rp
14915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * needs to be updated every time a command is implemented here!  */
14925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    switch (cmd) {
14935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_CTL, OCF_INQUIRY):
14945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(inquiry);
14955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
14965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (PARAM(inquiry, length) < 1) {
14975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_complete_status(hci, HCI_INVALID_PARAMETERS);
14985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
14995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
15005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->lm.inquire = 1;
15025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->lm.periodic = 0;
15035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->lm.responses_left = PARAM(inquiry, num_rsp) ?: INT_MAX;
15045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->lm.responses = 0;
15055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_status(hci, HCI_SUCCESS);
15065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_inquiry_start(hci, PARAM(inquiry, length));
15075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
15085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_CTL, OCF_INQUIRY_CANCEL):
15105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!hci->lm.inquire || hci->lm.periodic) {
15115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            fprintf(stderr, "%s: Inquiry Cancel should only be issued after "
15125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            "the Inquiry command has been issued, a Command "
15135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            "Status event has been received for the Inquiry "
15145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            "command, and before the Inquiry Complete event "
15155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            "occurs", __FUNCTION__);
15165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_complete_status(hci, HCI_COMMAND_DISALLOWED);
15175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
15185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
15195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->lm.inquire = 0;
15215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_del_timer(hci->lm.inquiry_done);
15225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_complete_status(hci, HCI_SUCCESS);
15235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
15245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_CTL, OCF_PERIODIC_INQUIRY):
15265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(periodic_inquiry);
15275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!(PARAM(periodic_inquiry, length) <
15295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                PARAM16(periodic_inquiry, min_period) &&
15305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                PARAM16(periodic_inquiry, min_period) <
15315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                PARAM16(periodic_inquiry, max_period)) ||
15325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        PARAM(periodic_inquiry, length) < 1 ||
15335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        PARAM16(periodic_inquiry, min_period) < 2 ||
15345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        PARAM16(periodic_inquiry, max_period) < 3) {
15355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_complete_status(hci, HCI_INVALID_PARAMETERS);
15365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
15375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
15385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->lm.inquire = 1;
15405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->lm.periodic = 1;
15415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->lm.responses_left = PARAM(periodic_inquiry, num_rsp);
15425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->lm.responses = 0;
15435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->lm.inquiry_period = PARAM16(periodic_inquiry, max_period);
15445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_complete_status(hci, HCI_SUCCESS);
15455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_inquiry_start(hci, PARAM(periodic_inquiry, length));
15465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
15475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_CTL, OCF_EXIT_PERIODIC_INQUIRY):
15495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!hci->lm.inquire || !hci->lm.periodic) {
15505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            fprintf(stderr, "%s: Inquiry Cancel should only be issued after "
15515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            "the Inquiry command has been issued, a Command "
15525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            "Status event has been received for the Inquiry "
15535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            "command, and before the Inquiry Complete event "
15545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            "occurs", __FUNCTION__);
15555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_complete_status(hci, HCI_COMMAND_DISALLOWED);
15565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
15575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
15585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->lm.inquire = 0;
15595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_del_timer(hci->lm.inquiry_done);
15605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_del_timer(hci->lm.inquiry_next);
15615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_complete_status(hci, HCI_SUCCESS);
15625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
15635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_CTL, OCF_CREATE_CONN):
15655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(create_conn);
15665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (hci->lm.connecting >= HCI_HANDLES_MAX) {
15685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_status(hci, HCI_REJECTED_LIMITED_RESOURCES);
15695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
15705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
15715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_status(hci, HCI_SUCCESS);
15725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bt_hci_connect(hci, &PARAM(create_conn, bdaddr)))
15745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_connection_reject_event(hci, &PARAM(create_conn, bdaddr));
15755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
15765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_CTL, OCF_DISCONNECT):
15785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(disconnect);
15795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bt_hci_handle_bad(hci, PARAMHANDLE(disconnect))) {
15815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_status(hci, HCI_NO_CONNECTION);
15825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
15835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
15845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_status(hci, HCI_SUCCESS);
15865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_disconnect(hci, PARAMHANDLE(disconnect),
15875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        PARAM(disconnect, reason));
15885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
15895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_CTL, OCF_CREATE_CONN_CANCEL):
15915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(create_conn_cancel);
15925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
15935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bt_hci_lmp_connection_ready(hci,
15945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                &PARAM(create_conn_cancel, bdaddr))) {
15955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            for (i = 0; i < HCI_HANDLES_MAX; i ++)
15965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (bt_hci_role_master(hci, i) && hci->lm.handle[i].link &&
15975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                !bacmp(&hci->lm.handle[i].link->slave->bd_addr,
15985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                        &PARAM(create_conn_cancel, bdaddr)))
15995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   break;
16005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_complete_conn_cancel(hci, i < HCI_HANDLES_MAX ?
16025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            HCI_ACL_CONNECTION_EXISTS : HCI_NO_CONNECTION,
16035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            &PARAM(create_conn_cancel, bdaddr));
16045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else
16055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_complete_conn_cancel(hci, HCI_SUCCESS,
16065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            &PARAM(create_conn_cancel, bdaddr));
16075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
16085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_CTL, OCF_ACCEPT_CONN_REQ):
16105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(accept_conn_req);
16115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!hci->conn_req_host ||
16135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        bacmp(&PARAM(accept_conn_req, bdaddr),
16145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                &hci->conn_req_host->bd_addr)) {
16155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_status(hci, HCI_INVALID_PARAMETERS);
16165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
16175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
16185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_status(hci, HCI_SUCCESS);
16205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_connection_accept(hci, hci->conn_req_host);
16215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->conn_req_host = NULL;
16225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
16235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_CTL, OCF_REJECT_CONN_REQ):
16255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(reject_conn_req);
16265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!hci->conn_req_host ||
16285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        bacmp(&PARAM(reject_conn_req, bdaddr),
16295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                &hci->conn_req_host->bd_addr)) {
16305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_status(hci, HCI_INVALID_PARAMETERS);
16315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
16325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
16335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_status(hci, HCI_SUCCESS);
16355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_connection_reject(hci, hci->conn_req_host,
16365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        PARAM(reject_conn_req, reason));
16375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_connection_reject_event(hci, &hci->conn_req_host->bd_addr);
16385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->conn_req_host = NULL;
16395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
16405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_CTL, OCF_AUTH_REQUESTED):
16425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(auth_requested);
16435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bt_hci_handle_bad(hci, PARAMHANDLE(auth_requested)))
16455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_status(hci, HCI_NO_CONNECTION);
16465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        else {
16475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_status(hci, HCI_SUCCESS);
16485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_auth_complete(hci, PARAMHANDLE(auth_requested));
16495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
16505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
16515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_CTL, OCF_SET_CONN_ENCRYPT):
16535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(set_conn_encrypt);
16545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bt_hci_handle_bad(hci, PARAMHANDLE(set_conn_encrypt)))
16565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_status(hci, HCI_NO_CONNECTION);
16575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        else {
16585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_status(hci, HCI_SUCCESS);
16595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_encrypt_change(hci,
16605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            PARAMHANDLE(set_conn_encrypt),
16615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            PARAM(set_conn_encrypt, encrypt));
16625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
16635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
16645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_CTL, OCF_REMOTE_NAME_REQ):
16665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(remote_name_req);
16675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bt_hci_name_req(hci, &PARAM(remote_name_req, bdaddr)))
16695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_status(hci, HCI_NO_CONNECTION);
16705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
16715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_CTL, OCF_REMOTE_NAME_REQ_CANCEL):
16735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(remote_name_req_cancel);
16745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_complete_name_cancel(hci,
16765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        &PARAM(remote_name_req_cancel, bdaddr));
16775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
16785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_CTL, OCF_READ_REMOTE_FEATURES):
16805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(read_remote_features);
16815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bt_hci_features_req(hci, PARAMHANDLE(read_remote_features)))
16835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_status(hci, HCI_NO_CONNECTION);
16845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
16855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_CTL, OCF_READ_REMOTE_EXT_FEATURES):
16875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(read_remote_ext_features);
16885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bt_hci_handle_bad(hci, PARAMHANDLE(read_remote_ext_features)))
16905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_status(hci, HCI_NO_CONNECTION);
16915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        else {
16925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_status(hci, HCI_SUCCESS);
16935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_read_remote_ext_features(hci,
16945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            PARAMHANDLE(read_remote_ext_features));
16955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
16965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
16975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
16985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_CTL, OCF_READ_REMOTE_VERSION):
16995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(read_remote_version);
17005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bt_hci_version_req(hci, PARAMHANDLE(read_remote_version)))
17025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_status(hci, HCI_NO_CONNECTION);
17035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
17045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_CTL, OCF_READ_CLOCK_OFFSET):
17065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(read_clock_offset);
17075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bt_hci_clkoffset_req(hci, PARAMHANDLE(read_clock_offset)))
17095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_status(hci, HCI_NO_CONNECTION);
17105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
17115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_CTL, OCF_READ_LMP_HANDLE):
17135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(read_lmp_handle);
17145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* TODO: */
17165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_complete_lmp_handle(hci, PARAMHANDLE(read_lmp_handle));
17175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
17185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_POLICY, OCF_HOLD_MODE):
17205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(hold_mode);
17215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (PARAM16(hold_mode, min_interval) >
17235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        PARAM16(hold_mode, max_interval) ||
17245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        PARAM16(hold_mode, min_interval) < 0x0002 ||
17255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        PARAM16(hold_mode, max_interval) > 0xff00 ||
17265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        (PARAM16(hold_mode, min_interval) & 1) ||
17275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        (PARAM16(hold_mode, max_interval) & 1)) {
17285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_status(hci, HCI_INVALID_PARAMETERS);
17295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
17305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
17315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bt_hci_mode_change(hci, PARAMHANDLE(hold_mode),
17335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                PARAM16(hold_mode, max_interval),
17345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                acl_hold))
17355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_status(hci, HCI_NO_CONNECTION);
17365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
17375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_POLICY, OCF_PARK_MODE):
17395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(park_mode);
17405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (PARAM16(park_mode, min_interval) >
17425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        PARAM16(park_mode, max_interval) ||
17435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        PARAM16(park_mode, min_interval) < 0x000e ||
17445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        (PARAM16(park_mode, min_interval) & 1) ||
17455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        (PARAM16(park_mode, max_interval) & 1)) {
17465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_status(hci, HCI_INVALID_PARAMETERS);
17475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
17485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
17495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bt_hci_mode_change(hci, PARAMHANDLE(park_mode),
17515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                PARAM16(park_mode, max_interval),
17525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                acl_parked))
17535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_status(hci, HCI_NO_CONNECTION);
17545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
17555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_POLICY, OCF_EXIT_PARK_MODE):
17575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(exit_park_mode);
17585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bt_hci_mode_cancel(hci, PARAMHANDLE(exit_park_mode),
17605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                acl_parked))
17615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_status(hci, HCI_NO_CONNECTION);
17625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
17635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_LINK_POLICY, OCF_ROLE_DISCOVERY):
17655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(role_discovery);
17665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bt_hci_handle_bad(hci, PARAMHANDLE(role_discovery)))
17685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_complete_role_discovery(hci,
17695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            HCI_NO_CONNECTION, PARAMHANDLE(role_discovery), 0);
17705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        else
17715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_complete_role_discovery(hci,
17725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            HCI_SUCCESS, PARAMHANDLE(role_discovery),
17735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            bt_hci_role_master(hci,
17745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                    PARAMHANDLE(role_discovery)));
17755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
17765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_HOST_CTL, OCF_SET_EVENT_MASK):
17785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(set_event_mask);
17795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        memcpy(hci->event_mask, PARAM(set_event_mask, mask), 8);
17815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_complete_status(hci, HCI_SUCCESS);
17825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
17835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_HOST_CTL, OCF_RESET):
17855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_reset(hci);
17865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_status(hci, HCI_SUCCESS);
17875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
17885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_HOST_CTL, OCF_SET_EVENT_FLT):
17905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (length >= 1 && PARAM(set_event_flt, flt_type) == FLT_CLEAR_ALL)
17915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* No length check */;
17925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        else
17935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            LENGTH_CHECK(set_event_flt);
17945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Filters are not implemented */
17965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_complete_status(hci, HCI_SUCCESS);
17975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
17985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
17995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_HOST_CTL, OCF_FLUSH):
18005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(flush);
18015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bt_hci_handle_bad(hci, PARAMHANDLE(flush)))
18035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_complete_flush(hci,
18045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            HCI_NO_CONNECTION, PARAMHANDLE(flush));
18055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        else {
18065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* TODO: ordering? */
18075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event(hci, EVT_FLUSH_OCCURRED,
18085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            &PARAM(flush, handle),
18095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            EVT_FLUSH_OCCURRED_SIZE);
18105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_complete_flush(hci,
18115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            HCI_SUCCESS, PARAMHANDLE(flush));
18125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
18135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
18145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_HOST_CTL, OCF_CHANGE_LOCAL_NAME):
18165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(change_local_name);
18175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (hci->device.lmp_name)
18195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            qemu_free((void *) hci->device.lmp_name);
18205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->device.lmp_name = qemu_strndup(PARAM(change_local_name, name),
18215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        sizeof(PARAM(change_local_name, name)));
18225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_complete_status(hci, HCI_SUCCESS);
18235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
18245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_LOCAL_NAME):
18265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_complete_read_local_name(hci);
18275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
18285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_CONN_ACCEPT_TIMEOUT):
18305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_complete_read_conn_accept_timeout(hci);
18315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
18325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_CONN_ACCEPT_TIMEOUT):
18345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* TODO */
18355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(write_conn_accept_timeout);
18365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (PARAM16(write_conn_accept_timeout, timeout) < 0x0001 ||
18385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        PARAM16(write_conn_accept_timeout, timeout) > 0xb540) {
18395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_complete_status(hci, HCI_INVALID_PARAMETERS);
18405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
18415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
18425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->conn_accept_tout = PARAM16(write_conn_accept_timeout, timeout);
18445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_complete_status(hci, HCI_SUCCESS);
18455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
18465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_SCAN_ENABLE):
18485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_complete_read_scan_enable(hci);
18495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
18505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE):
18525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(write_scan_enable);
18535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* TODO: check that the remaining bits are all 0 */
18555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->device.inquiry_scan =
18565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                !!(PARAM(write_scan_enable, scan_enable) & SCAN_INQUIRY);
18575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->device.page_scan =
18585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                !!(PARAM(write_scan_enable, scan_enable) & SCAN_PAGE);
18595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_complete_status(hci, HCI_SUCCESS);
18605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
18615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_CLASS_OF_DEV):
18635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_complete_read_local_class(hci);
18645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
18655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV):
18675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(write_class_of_dev);
18685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        memcpy(hci->device.class, PARAM(write_class_of_dev, dev_class),
18705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        sizeof(PARAM(write_class_of_dev, dev_class)));
18715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_complete_status(hci, HCI_SUCCESS);
18725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
18735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_VOICE_SETTING):
18755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_complete_voice_setting(hci);
18765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
18775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_VOICE_SETTING):
18795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(write_voice_setting);
18805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->voice_setting = PARAM(write_voice_setting, voice_setting);
18825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_complete_status(hci, HCI_SUCCESS);
18835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
18845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_HOST_CTL, OCF_HOST_NUMBER_OF_COMPLETED_PACKETS):
18865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (length < data[0] * 2 + 1)
18875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto short_hci;
18885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        for (i = 0; i < data[0]; i ++)
18905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (bt_hci_handle_bad(hci,
18915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                    data[i * 2 + 1] | (data[i * 2 + 2] << 8)))
18925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                bt_hci_event_complete_status(hci, HCI_INVALID_PARAMETERS);
18935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
18945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
18955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_INQUIRY_MODE):
18965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Only if (local_features[3] & 0x40) && (local_commands[12] & 0x40)
18975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         * else
18985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         *     goto unknown_command */
18995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_complete_read_inquiry_mode(hci);
19005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
19015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_INQUIRY_MODE):
19035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Only if (local_features[3] & 0x40) && (local_commands[12] & 0x80)
19045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         * else
19055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         *     goto unknown_command */
19065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(write_inquiry_mode);
19075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (PARAM(write_inquiry_mode, mode) > 0x01) {
19095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_event_complete_status(hci, HCI_INVALID_PARAMETERS);
19105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
19115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
19125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        hci->lm.inquiry_mode = PARAM(write_inquiry_mode, mode);
19145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_complete_status(hci, HCI_SUCCESS);
19155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
19165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_LOCAL_VERSION):
19185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_read_local_version_rp(hci);
19195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
19205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_LOCAL_COMMANDS):
19225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_read_local_commands_rp(hci);
19235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
19245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_LOCAL_FEATURES):
19265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_read_local_features_rp(hci);
19275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
19285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_LOCAL_EXT_FEATURES):
19305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(read_local_ext_features);
19315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_read_local_ext_features_rp(hci,
19335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        PARAM(read_local_ext_features, page_num));
19345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
19355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_BUFFER_SIZE):
19375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_read_buffer_size_rp(hci);
19385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
19395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_COUNTRY_CODE):
19415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_read_country_code_rp(hci);
19425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
19435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_BD_ADDR):
19455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_read_bd_addr_rp(hci);
19465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
19475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case cmd_opcode_pack(OGF_STATUS_PARAM, OCF_READ_LINK_QUALITY):
19495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        LENGTH_CHECK(read_link_quality);
19505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_link_quality_rp(hci, PARAMHANDLE(read_link_quality));
19525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
19535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    default:
19555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_status(hci, HCI_UNKNOWN_COMMAND);
19565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
19575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    short_hci:
19595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "%s: HCI packet too short (%iB)\n",
19605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        __FUNCTION__, length);
19615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_event_status(hci, HCI_INVALID_PARAMETERS);
19625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        break;
19635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
19645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
19655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* We could perform fragmentation here, we can't do "recombination" because
19675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * at this layer the length of the payload is not know ahead, so we only
19685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * know that a packet contained the last fragment of the SDU when the next
19695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * SDU starts.  */
19705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void bt_hci_lmp_acl_data(struct bt_hci_s *hci, uint16_t handle,
19715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                const uint8_t *data, int start, int len)
19725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
19735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct hci_acl_hdr *pkt = (void *) hci->acl_buf;
19745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* TODO: packet flags */
19765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* TODO: avoid memcpy'ing */
19775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (len + HCI_ACL_HDR_SIZE > sizeof(hci->acl_buf)) {
19795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "%s: can't take ACL packets %i bytes long\n",
19805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        __FUNCTION__, len);
19815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
19825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
19835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    memcpy(hci->acl_buf + HCI_ACL_HDR_SIZE, data, len);
19845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    pkt->handle = cpu_to_le16(
19865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    acl_handle_pack(handle, start ? ACL_START : ACL_CONT));
19875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    pkt->dlen = cpu_to_le16(len);
19885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->info.acl_recv(hci->info.opaque,
19895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    hci->acl_buf, len + HCI_ACL_HDR_SIZE);
19905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
19915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_lmp_acl_data_slave(struct bt_link_s *btlink,
19935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                const uint8_t *data, int start, int len)
19945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
19955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_link_s *link = (struct bt_hci_link_s *) btlink;
19965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
19975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_lmp_acl_data(hci_from_device(btlink->slave),
19985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    link->handle, data, start, len);
19995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
20005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_lmp_acl_data_host(struct bt_link_s *link,
20025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                const uint8_t *data, int start, int len)
20035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
20045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_lmp_acl_data(hci_from_device(link->host),
20055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    link->handle, data, start, len);
20065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
20075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_submit_acl(struct HCIInfo *info,
20095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                const uint8_t *data, int length)
20105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
20115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_s *hci = hci_from_info(info);
20125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint16_t handle;
20135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int datalen, flags;
20145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_link_s *link;
20155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (length < HCI_ACL_HDR_SIZE) {
20175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "%s: ACL packet too short (%iB)\n",
20185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        __FUNCTION__, length);
20195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
20205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
20215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    handle = acl_handle((data[1] << 8) | data[0]);
20235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    flags = acl_flags((data[1] << 8) | data[0]);
20245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    datalen = (data[3] << 8) | data[2];
20255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    data += HCI_ACL_HDR_SIZE;
20265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    length -= HCI_ACL_HDR_SIZE;
20275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bt_hci_handle_bad(hci, handle)) {
20295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "%s: invalid ACL handle %03x\n",
20305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        __FUNCTION__, handle);
20315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* TODO: signal an error */
20325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
20335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
20345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    handle &= ~HCI_HANDLE_OFFSET;
20355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (datalen > length) {
20375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "%s: ACL packet too short (%iB < %iB)\n",
20385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        __FUNCTION__, length, datalen);
20395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
20405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
20415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    link = hci->lm.handle[handle].link;
20435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if ((flags & ~3) == ACL_ACTIVE_BCAST) {
20455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!hci->asb_handle)
20465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            hci->asb_handle = handle;
20475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        else if (handle != hci->asb_handle) {
20485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            fprintf(stderr, "%s: Bad handle %03x in Active Slave Broadcast\n",
20495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            __FUNCTION__, handle);
20505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* TODO: signal an error */
20515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return;
20525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
20535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* TODO */
20555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
20565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if ((flags & ~3) == ACL_PICO_BCAST) {
20585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!hci->psb_handle)
20595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            hci->psb_handle = handle;
20605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        else if (handle != hci->psb_handle) {
20615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            fprintf(stderr, "%s: Bad handle %03x in Parked Slave Broadcast\n",
20625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            __FUNCTION__, handle);
20635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* TODO: signal an error */
20645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return;
20655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
20665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* TODO */
20685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
20695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* TODO: increase counter and send EVT_NUM_COMP_PKTS */
20715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_event_num_comp_pkts(hci, handle | HCI_HANDLE_OFFSET, 1);
20725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Do this last as it can trigger further events even in this HCI */
20745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    hci->lm.handle[handle].lmp_acl_data(link, data,
20755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    (flags & 3) == ACL_START, length);
20765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
20775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_submit_sco(struct HCIInfo *info,
20795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                const uint8_t *data, int length)
20805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
20815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_s *hci = hci_from_info(info);
20825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint16_t handle;
20835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int datalen;
20845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (length < 3)
20865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
20875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    handle = acl_handle((data[1] << 8) | data[0]);
20895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    datalen = data[2];
20905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    length -= 3;
20915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bt_hci_handle_bad(hci, handle)) {
20935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "%s: invalid SCO handle %03x\n",
20945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        __FUNCTION__, handle);
20955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
20965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
20975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
20985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (datalen > length) {
20995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "%s: SCO packet too short (%iB < %iB)\n",
21005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        __FUNCTION__, length, datalen);
21015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
21025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
21035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* TODO */
21055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* TODO: increase counter and send EVT_NUM_COMP_PKTS if synchronous
21075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * Flow Control is enabled.
21085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * (See Read/Write_Synchronous_Flow_Control_Enable on page 513 and
21095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * page 514.)  */
21105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
21115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic uint8_t *bt_hci_evt_packet(void *opaque)
21135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
21145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* TODO: allocate a packet from upper layer */
21155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_s *s = opaque;
21165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return s->evt_buf;
21185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
21195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_evt_submit(void *opaque, int len)
21215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
21225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* TODO: notify upper layer */
21235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_s *s = opaque;
21245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->info.evt_recv(s->info.opaque, s->evt_buf, len);
21265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
21275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int bt_hci_bdaddr_set(struct HCIInfo *info, const uint8_t *bd_addr)
21295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
21305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_s *hci = hci_from_info(info);
21315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bacpy(&hci->device.bd_addr, (const bdaddr_t *) bd_addr);
21335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 0;
21345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
21355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_done(struct HCIInfo *info);
21375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_destroy(struct bt_device_s *dev)
21385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
21395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_s *hci = hci_from_device(dev);
21405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_done(&hci->info);
21425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
21435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct HCIInfo *bt_new_hci(struct bt_scatternet_s *net)
21455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
21465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_s *s = qemu_mallocz(sizeof(struct bt_hci_s));
21475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21485973c775c853e26f684de58ad28c267281aaffd6David 'Digit' Turner    s->lm.inquiry_done = qemu_new_timer_ns(vm_clock, bt_hci_inquiry_done, s);
21495973c775c853e26f684de58ad28c267281aaffd6David 'Digit' Turner    s->lm.inquiry_next = qemu_new_timer_ns(vm_clock, bt_hci_inquiry_next, s);
21505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->conn_accept_timer =
21515973c775c853e26f684de58ad28c267281aaffd6David 'Digit' Turner            qemu_new_timer_ns(vm_clock, bt_hci_conn_accept_timeout, s);
21525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->evt_packet = bt_hci_evt_packet;
21545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->evt_submit = bt_hci_evt_submit;
21555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->opaque = s;
21565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_device_init(&s->device, net);
21585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->device.lmp_connection_request = bt_hci_lmp_connection_request;
21595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->device.lmp_connection_complete = bt_hci_lmp_connection_complete;
21605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->device.lmp_disconnect_master = bt_hci_lmp_disconnect_host;
21615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->device.lmp_disconnect_slave = bt_hci_lmp_disconnect_slave;
21625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->device.lmp_acl_data = bt_hci_lmp_acl_data_slave;
21635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->device.lmp_acl_resp = bt_hci_lmp_acl_data_host;
21645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->device.lmp_mode_change = bt_hci_lmp_mode_change_slave;
21655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Keep updated! */
21675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Also keep in sync with supported commands bitmask in
21685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * bt_hci_read_local_commands_rp */
21695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->device.lmp_caps = 0x8000199b7e85355fll;
21705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_hci_reset(s);
21725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->info.cmd_send = bt_submit_hci;
21745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->info.sco_send = bt_submit_sco;
21755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->info.acl_send = bt_submit_acl;
21765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->info.bdaddr_set = bt_hci_bdaddr_set;
21775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->device.handle_destroy = bt_hci_destroy;
21795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return &s->info;
21815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
21825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void bt_hci_done(struct HCIInfo *info)
21845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
21855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct bt_hci_s *hci = hci_from_info(info);
21865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int handle;
21875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bt_device_done(&hci->device);
21895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (hci->device.lmp_name)
21915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_free((void *) hci->device.lmp_name);
21925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
21935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Be gentle and send DISCONNECT to all connected peers and those
21945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * currently waiting for us to accept or reject a connection request.
21955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * This frees the links.  */
21965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (hci->conn_req_host) {
21975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bt_hci_connection_reject(hci,
21985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                 hci->conn_req_host, HCI_OE_POWER_OFF);
21995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return;
22005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
22015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
22025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    for (handle = HCI_HANDLE_OFFSET;
22035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    handle < (HCI_HANDLE_OFFSET | HCI_HANDLES_MAX); handle ++)
22045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (!bt_hci_handle_bad(hci, handle))
22055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bt_hci_disconnect(hci, handle, HCI_OE_POWER_OFF);
22065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
22075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* TODO: this is not enough actually, there may be slaves from whom
22085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * we have requested a connection who will soon (or not) respond with
22095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * an accept or a reject, so we should also check if hci->lm.connecting
22105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * is non-zero and if so, avoid freeing the hci but otherwise disappear
22115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * from all qemu social life (e.g. stop scanning and request to be
22125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * removed from s->device.net) and arrange for
22135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * s->device.lmp_connection_complete to free the remaining bits once
22145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * hci->lm.awaiting_bdaddr[] is empty.  */
22155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
22165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free_timer(hci->lm.inquiry_done);
22175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free_timer(hci->lm.inquiry_next);
22185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free_timer(hci->conn_accept_timer);
22195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
22205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_free(hci);
22215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2222