/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED.
*/
/* Bluetooth HCI event handling. */
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/fcntl.h>
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/interrupt.h>
#include <linux/notifier.h>
#include <net/sock.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#ifndef CONFIG_BT_HCI_CORE_DEBUG
#undef BT_DBG
#define BT_DBG(D...)
#endif
/* Handle HCI Event packets */
/* Command Complete OGF LINK_CTL */
static void hci_cc_link_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb)
{
__u8 status;
BT_DBG("%s ocf 0x%x", hdev->name, ocf);
switch (ocf) {
case OCF_INQUIRY_CANCEL:
status = *((__u8 *) skb->data);
if (status) {
BT_DBG("%s Inquiry cancel error: status 0x%x", hdev->name, status);
} else {
clear_bit(HCI_INQUIRY, &hdev->flags);
hci_req_complete(hdev, status);
}
break;
default:
BT_DBG("%s Command complete: ogf LINK_CTL ocf %x", hdev->name, ocf);
break;
}
}
/* Command Complete OGF LINK_POLICY */
static void hci_cc_link_policy(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb)
{
struct hci_conn *conn;
struct hci_rp_role_discovery *rd;
BT_DBG("%s ocf 0x%x", hdev->name, ocf);
switch (ocf) {
case OCF_ROLE_DISCOVERY:
rd = (void *) skb->data;
if (rd->status)
break;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rd->handle));
if (conn) {
if (rd->role)
conn->link_mode &= ~HCI_LM_MASTER;
else
conn->link_mode |= HCI_LM_MASTER;
}
hci_dev_unlock(hdev);
break;
default:
BT_DBG("%s: Command complete: ogf LINK_POLICY ocf %x",
hdev->name, ocf);
break;
}
}
/* Command Complete OGF HOST_CTL */
static void hci_cc_host_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb)
{
__u8 status, param;
__u16 setting;
struct hci_rp_read_voice_setting *vs;
void *sent;
BT_DBG("%s ocf 0x%x", hdev->name, ocf);
switch (ocf) {
case OCF_RESET:
status = *((__u8 *) skb->data);
hci_req_complete(hdev, status);
break;
case OCF_SET_EVENT_FLT:
status = *((__u8 *) skb->data);
if (status) {
BT_DBG("%s SET_EVENT_FLT failed %d", hdev->name, status);
} else {
BT_DBG("%s SET_EVENT_FLT succeseful", hdev->name);
}
break;
case OCF_WRITE_AUTH_ENABLE:
sent = hci_sent_cmd_data(hdev, OGF_HOST_CTL, OCF_WRITE_AUTH_ENABLE);
if (!sent)
break;
status = *((__u8 *) skb->data);
param = *((__u8 *) sent);
if (!status) {
if (param == AUTH_ENABLED)
set_bit(HCI_AUTH, &hdev->flags);
else
clear_bit(HCI_AUTH, &hdev->flags);
}
hci_req_complete(hdev, status);
break;
case OCF_WRITE_ENCRYPT_MODE:
sent = hci_sent_cmd_data(hdev, OGF_HOST_CTL, OCF_WRITE_ENCRYPT_MODE);
if (!sent)
break;
status = *((__u8 *