Bluetooth: Create a unique mgmt error code hierarchy
The management protocol uses a single byte for error codes (aka command status). In some places this value is directly copied from HCI and in other a POSIX error number is used. This makes it impossible for user-space to uniquily decipher the meaning of an error. To solve this issue a new mgmt-specific set of error codes is added along with a conversion table for HCI status values. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
This commit is contained in:
parent
8680570b0c
commit
ca69b7957b
@ -23,6 +23,23 @@
|
|||||||
|
|
||||||
#define MGMT_INDEX_NONE 0xFFFF
|
#define MGMT_INDEX_NONE 0xFFFF
|
||||||
|
|
||||||
|
#define MGMT_STATUS_SUCCESS 0x00
|
||||||
|
#define MGMT_STATUS_UNKNOWN_COMMAND 0x01
|
||||||
|
#define MGMT_STATUS_NOT_CONNECTED 0x02
|
||||||
|
#define MGMT_STATUS_FAILED 0x03
|
||||||
|
#define MGMT_STATUS_CONNECT_FAILED 0x04
|
||||||
|
#define MGMT_STATUS_AUTH_FAILED 0x05
|
||||||
|
#define MGMT_STATUS_NOT_PAIRED 0x06
|
||||||
|
#define MGMT_STATUS_NO_RESOURCES 0x07
|
||||||
|
#define MGMT_STATUS_TIMEOUT 0x08
|
||||||
|
#define MGMT_STATUS_ALREADY_CONNECTED 0x09
|
||||||
|
#define MGMT_STATUS_BUSY 0x0a
|
||||||
|
#define MGMT_STATUS_REJECTED 0x0b
|
||||||
|
#define MGMT_STATUS_NOT_SUPPORTED 0x0c
|
||||||
|
#define MGMT_STATUS_INVALID_PARAMS 0x0d
|
||||||
|
#define MGMT_STATUS_DISCONNECTED 0x0e
|
||||||
|
#define MGMT_STATUS_NOT_POWERED 0x0f
|
||||||
|
|
||||||
struct mgmt_hdr {
|
struct mgmt_hdr {
|
||||||
__le16 opcode;
|
__le16 opcode;
|
||||||
__le16 index;
|
__le16 index;
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
/* Bluetooth HCI Management interface */
|
/* Bluetooth HCI Management interface */
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
|
|
||||||
@ -43,6 +44,79 @@ struct pending_cmd {
|
|||||||
void *user_data;
|
void *user_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* HCI to MGMT error code conversion table */
|
||||||
|
static u8 mgmt_status_table[] = {
|
||||||
|
MGMT_STATUS_SUCCESS,
|
||||||
|
MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
|
||||||
|
MGMT_STATUS_NOT_CONNECTED, /* No Connection */
|
||||||
|
MGMT_STATUS_FAILED, /* Hardware Failure */
|
||||||
|
MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
|
||||||
|
MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
|
||||||
|
MGMT_STATUS_NOT_PAIRED, /* PIN or Key Missing */
|
||||||
|
MGMT_STATUS_NO_RESOURCES, /* Memory Full */
|
||||||
|
MGMT_STATUS_TIMEOUT, /* Connection Timeout */
|
||||||
|
MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
|
||||||
|
MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
|
||||||
|
MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
|
||||||
|
MGMT_STATUS_BUSY, /* Command Disallowed */
|
||||||
|
MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
|
||||||
|
MGMT_STATUS_REJECTED, /* Rejected Security */
|
||||||
|
MGMT_STATUS_REJECTED, /* Rejected Personal */
|
||||||
|
MGMT_STATUS_TIMEOUT, /* Host Timeout */
|
||||||
|
MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
|
||||||
|
MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
|
||||||
|
MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
|
||||||
|
MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
|
||||||
|
MGMT_STATUS_DISCONNECTED, /* OE Power Off */
|
||||||
|
MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
|
||||||
|
MGMT_STATUS_BUSY, /* Repeated Attempts */
|
||||||
|
MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
|
||||||
|
MGMT_STATUS_FAILED, /* Unknown LMP PDU */
|
||||||
|
MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
|
||||||
|
MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
|
||||||
|
MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
|
||||||
|
MGMT_STATUS_REJECTED, /* Air Mode Rejected */
|
||||||
|
MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
|
||||||
|
MGMT_STATUS_FAILED, /* Unspecified Error */
|
||||||
|
MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
|
||||||
|
MGMT_STATUS_FAILED, /* Role Change Not Allowed */
|
||||||
|
MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
|
||||||
|
MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
|
||||||
|
MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
|
||||||
|
MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
|
||||||
|
MGMT_STATUS_FAILED, /* Unit Link Key Used */
|
||||||
|
MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
|
||||||
|
MGMT_STATUS_TIMEOUT, /* Instant Passed */
|
||||||
|
MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
|
||||||
|
MGMT_STATUS_FAILED, /* Transaction Collision */
|
||||||
|
MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
|
||||||
|
MGMT_STATUS_REJECTED, /* QoS Rejected */
|
||||||
|
MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
|
||||||
|
MGMT_STATUS_REJECTED, /* Insufficient Security */
|
||||||
|
MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
|
||||||
|
MGMT_STATUS_BUSY, /* Role Switch Pending */
|
||||||
|
MGMT_STATUS_FAILED, /* Slot Violation */
|
||||||
|
MGMT_STATUS_FAILED, /* Role Switch Failed */
|
||||||
|
MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
|
||||||
|
MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
|
||||||
|
MGMT_STATUS_BUSY, /* Host Busy Pairing */
|
||||||
|
MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
|
||||||
|
MGMT_STATUS_BUSY, /* Controller Busy */
|
||||||
|
MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
|
||||||
|
MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
|
||||||
|
MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
|
||||||
|
MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
|
||||||
|
MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
|
||||||
|
};
|
||||||
|
|
||||||
|
static u8 mgmt_status(u8 hci_status)
|
||||||
|
{
|
||||||
|
if (hci_status < ARRAY_SIZE(mgmt_status_table))
|
||||||
|
return mgmt_status_table[hci_status];
|
||||||
|
|
||||||
|
return MGMT_STATUS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
|
static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
@ -177,7 +251,8 @@ static int read_controller_info(struct sock *sk, u16 index)
|
|||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_READ_INFO, ENODEV);
|
return cmd_status(sk, index, MGMT_OP_READ_INFO,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->flags))
|
if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->flags))
|
||||||
cancel_delayed_work_sync(&hdev->power_off);
|
cancel_delayed_work_sync(&hdev->power_off);
|
||||||
@ -311,11 +386,13 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
|
|||||||
BT_DBG("request for hci%u", index);
|
BT_DBG("request for hci%u", index);
|
||||||
|
|
||||||
if (len != sizeof(*cp))
|
if (len != sizeof(*cp))
|
||||||
return cmd_status(sk, index, MGMT_OP_SET_POWERED, EINVAL);
|
return cmd_status(sk, index, MGMT_OP_SET_POWERED,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_SET_POWERED, ENODEV);
|
return cmd_status(sk, index, MGMT_OP_SET_POWERED,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
@ -326,7 +403,8 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
|
if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
|
||||||
err = cmd_status(sk, index, MGMT_OP_SET_POWERED, EBUSY);
|
err = cmd_status(sk, index, MGMT_OP_SET_POWERED,
|
||||||
|
MGMT_STATUS_BUSY);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,22 +441,26 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
|
|||||||
BT_DBG("request for hci%u", index);
|
BT_DBG("request for hci%u", index);
|
||||||
|
|
||||||
if (len != sizeof(*cp))
|
if (len != sizeof(*cp))
|
||||||
return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EINVAL);
|
return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENODEV);
|
return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
if (!test_bit(HCI_UP, &hdev->flags)) {
|
if (!test_bit(HCI_UP, &hdev->flags)) {
|
||||||
err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENETDOWN);
|
err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
|
||||||
|
MGMT_STATUS_NOT_POWERED);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
|
if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
|
||||||
mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
|
mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
|
||||||
err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EBUSY);
|
err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE,
|
||||||
|
MGMT_STATUS_BUSY);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,22 +512,26 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
|
|||||||
BT_DBG("request for hci%u", index);
|
BT_DBG("request for hci%u", index);
|
||||||
|
|
||||||
if (len != sizeof(*cp))
|
if (len != sizeof(*cp))
|
||||||
return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EINVAL);
|
return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENODEV);
|
return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
if (!test_bit(HCI_UP, &hdev->flags)) {
|
if (!test_bit(HCI_UP, &hdev->flags)) {
|
||||||
err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENETDOWN);
|
err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE,
|
||||||
|
MGMT_STATUS_NOT_POWERED);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
|
if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
|
||||||
mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
|
mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
|
||||||
err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EBUSY);
|
err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE,
|
||||||
|
MGMT_STATUS_BUSY);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -518,11 +604,13 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data,
|
|||||||
BT_DBG("request for hci%u", index);
|
BT_DBG("request for hci%u", index);
|
||||||
|
|
||||||
if (len != sizeof(*cp))
|
if (len != sizeof(*cp))
|
||||||
return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, EINVAL);
|
return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, ENODEV);
|
return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
@ -731,11 +819,13 @@ static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
|
|||||||
BT_DBG("request for hci%u", index);
|
BT_DBG("request for hci%u", index);
|
||||||
|
|
||||||
if (len != sizeof(*cp))
|
if (len != sizeof(*cp))
|
||||||
return cmd_status(sk, index, MGMT_OP_ADD_UUID, EINVAL);
|
return cmd_status(sk, index, MGMT_OP_ADD_UUID,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_ADD_UUID, ENODEV);
|
return cmd_status(sk, index, MGMT_OP_ADD_UUID,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
@ -780,11 +870,13 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
|
|||||||
BT_DBG("request for hci%u", index);
|
BT_DBG("request for hci%u", index);
|
||||||
|
|
||||||
if (len != sizeof(*cp))
|
if (len != sizeof(*cp))
|
||||||
return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, EINVAL);
|
return cmd_status(sk, index, MGMT_OP_REMOVE_UUID,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENODEV);
|
return cmd_status(sk, index, MGMT_OP_REMOVE_UUID,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
@ -806,7 +898,8 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (found == 0) {
|
if (found == 0) {
|
||||||
err = cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENOENT);
|
err = cmd_status(sk, index, MGMT_OP_REMOVE_UUID,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -839,11 +932,13 @@ static int set_dev_class(struct sock *sk, u16 index, unsigned char *data,
|
|||||||
BT_DBG("request for hci%u", index);
|
BT_DBG("request for hci%u", index);
|
||||||
|
|
||||||
if (len != sizeof(*cp))
|
if (len != sizeof(*cp))
|
||||||
return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, EINVAL);
|
return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, ENODEV);
|
return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
@ -871,11 +966,13 @@ static int set_service_cache(struct sock *sk, u16 index, unsigned char *data,
|
|||||||
cp = (void *) data;
|
cp = (void *) data;
|
||||||
|
|
||||||
if (len != sizeof(*cp))
|
if (len != sizeof(*cp))
|
||||||
return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, EINVAL);
|
return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, ENODEV);
|
return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
@ -915,7 +1012,8 @@ static int load_link_keys(struct sock *sk, u16 index, unsigned char *data,
|
|||||||
cp = (void *) data;
|
cp = (void *) data;
|
||||||
|
|
||||||
if (len < sizeof(*cp))
|
if (len < sizeof(*cp))
|
||||||
return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS, EINVAL);
|
return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
key_count = get_unaligned_le16(&cp->key_count);
|
key_count = get_unaligned_le16(&cp->key_count);
|
||||||
|
|
||||||
@ -924,12 +1022,14 @@ static int load_link_keys(struct sock *sk, u16 index, unsigned char *data,
|
|||||||
if (expected_len != len) {
|
if (expected_len != len) {
|
||||||
BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
|
BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
|
||||||
len, expected_len);
|
len, expected_len);
|
||||||
return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS, EINVAL);
|
return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
}
|
}
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS, ENODEV);
|
return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys,
|
BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys,
|
||||||
key_count);
|
key_count);
|
||||||
@ -972,20 +1072,25 @@ static int remove_keys(struct sock *sk, u16 index, unsigned char *data,
|
|||||||
cp = (void *) data;
|
cp = (void *) data;
|
||||||
|
|
||||||
if (len != sizeof(*cp))
|
if (len != sizeof(*cp))
|
||||||
return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS, EINVAL);
|
return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS, ENODEV);
|
return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
memset(&rp, 0, sizeof(rp));
|
memset(&rp, 0, sizeof(rp));
|
||||||
bacpy(&rp.bdaddr, &cp->bdaddr);
|
bacpy(&rp.bdaddr, &cp->bdaddr);
|
||||||
|
rp.status = MGMT_STATUS_FAILED;
|
||||||
|
|
||||||
err = hci_remove_link_key(hdev, &cp->bdaddr);
|
err = hci_remove_link_key(hdev, &cp->bdaddr);
|
||||||
if (err < 0)
|
if (err < 0) {
|
||||||
|
rp.status = MGMT_STATUS_NOT_PAIRED;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
if (!test_bit(HCI_UP, &hdev->flags) || !cp->disconnect) {
|
if (!test_bit(HCI_UP, &hdev->flags) || !cp->disconnect) {
|
||||||
err = cmd_complete(sk, index, MGMT_OP_REMOVE_KEYS, &rp,
|
err = cmd_complete(sk, index, MGMT_OP_REMOVE_KEYS, &rp,
|
||||||
@ -1013,11 +1118,9 @@ static int remove_keys(struct sock *sk, u16 index, unsigned char *data,
|
|||||||
mgmt_pending_remove(cmd);
|
mgmt_pending_remove(cmd);
|
||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
if (err < 0) {
|
if (err < 0)
|
||||||
rp.status = -err;
|
|
||||||
err = cmd_complete(sk, index, MGMT_OP_REMOVE_KEYS, &rp,
|
err = cmd_complete(sk, index, MGMT_OP_REMOVE_KEYS, &rp,
|
||||||
sizeof(rp));
|
sizeof(rp));
|
||||||
}
|
|
||||||
hci_dev_unlock_bh(hdev);
|
hci_dev_unlock_bh(hdev);
|
||||||
hci_dev_put(hdev);
|
hci_dev_put(hdev);
|
||||||
|
|
||||||
@ -1038,21 +1141,25 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
|
|||||||
cp = (void *) data;
|
cp = (void *) data;
|
||||||
|
|
||||||
if (len != sizeof(*cp))
|
if (len != sizeof(*cp))
|
||||||
return cmd_status(sk, index, MGMT_OP_DISCONNECT, EINVAL);
|
return cmd_status(sk, index, MGMT_OP_DISCONNECT,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_DISCONNECT, ENODEV);
|
return cmd_status(sk, index, MGMT_OP_DISCONNECT,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
if (!test_bit(HCI_UP, &hdev->flags)) {
|
if (!test_bit(HCI_UP, &hdev->flags)) {
|
||||||
err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENETDOWN);
|
err = cmd_status(sk, index, MGMT_OP_DISCONNECT,
|
||||||
|
MGMT_STATUS_NOT_POWERED);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
|
if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
|
||||||
err = cmd_status(sk, index, MGMT_OP_DISCONNECT, EBUSY);
|
err = cmd_status(sk, index, MGMT_OP_DISCONNECT,
|
||||||
|
MGMT_STATUS_BUSY);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1061,7 +1168,8 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
|
|||||||
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr);
|
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr);
|
||||||
|
|
||||||
if (!conn) {
|
if (!conn) {
|
||||||
err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENOTCONN);
|
err = cmd_status(sk, index, MGMT_OP_DISCONNECT,
|
||||||
|
MGMT_STATUS_NOT_CONNECTED);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1118,7 +1226,8 @@ static int get_connections(struct sock *sk, u16 index)
|
|||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS, ENODEV);
|
return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
@ -1192,22 +1301,26 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
|
|||||||
cp = (void *) data;
|
cp = (void *) data;
|
||||||
|
|
||||||
if (len != sizeof(*cp))
|
if (len != sizeof(*cp))
|
||||||
return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, EINVAL);
|
return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENODEV);
|
return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
if (!test_bit(HCI_UP, &hdev->flags)) {
|
if (!test_bit(HCI_UP, &hdev->flags)) {
|
||||||
err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENETDOWN);
|
err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
|
||||||
|
MGMT_STATUS_NOT_POWERED);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
|
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
|
||||||
if (!conn) {
|
if (!conn) {
|
||||||
err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENOTCONN);
|
err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
|
||||||
|
MGMT_STATUS_NOT_CONNECTED);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1219,7 +1332,7 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
|
|||||||
err = send_pin_code_neg_reply(sk, index, hdev, &ncp);
|
err = send_pin_code_neg_reply(sk, index, hdev, &ncp);
|
||||||
if (err >= 0)
|
if (err >= 0)
|
||||||
err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
|
err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
|
||||||
EINVAL);
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
@ -1258,18 +1371,18 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
|
|||||||
|
|
||||||
if (len != sizeof(*cp))
|
if (len != sizeof(*cp))
|
||||||
return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
|
return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
|
||||||
EINVAL);
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
|
return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
|
||||||
ENODEV);
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
if (!test_bit(HCI_UP, &hdev->flags)) {
|
if (!test_bit(HCI_UP, &hdev->flags)) {
|
||||||
err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
|
err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
|
||||||
ENETDOWN);
|
MGMT_STATUS_NOT_POWERED);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1293,11 +1406,13 @@ static int set_io_capability(struct sock *sk, u16 index, unsigned char *data,
|
|||||||
cp = (void *) data;
|
cp = (void *) data;
|
||||||
|
|
||||||
if (len != sizeof(*cp))
|
if (len != sizeof(*cp))
|
||||||
return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, EINVAL);
|
return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, ENODEV);
|
return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
@ -1379,11 +1494,13 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
|
|||||||
cp = (void *) data;
|
cp = (void *) data;
|
||||||
|
|
||||||
if (len != sizeof(*cp))
|
if (len != sizeof(*cp))
|
||||||
return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EINVAL);
|
return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, ENODEV);
|
return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
@ -1468,11 +1585,13 @@ static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (len != sizeof(*cp))
|
if (len != sizeof(*cp))
|
||||||
return cmd_status(sk, index, mgmt_op, EINVAL);
|
return cmd_status(sk, index, mgmt_op,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, mgmt_op, ENODEV);
|
return cmd_status(sk, index, mgmt_op,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
@ -1510,11 +1629,13 @@ static int set_local_name(struct sock *sk, u16 index, unsigned char *data,
|
|||||||
BT_DBG("");
|
BT_DBG("");
|
||||||
|
|
||||||
if (len != sizeof(*mgmt_cp))
|
if (len != sizeof(*mgmt_cp))
|
||||||
return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, EINVAL);
|
return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, ENODEV);
|
return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
@ -1548,24 +1669,25 @@ static int read_local_oob_data(struct sock *sk, u16 index)
|
|||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
|
return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
|
||||||
ENODEV);
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
if (!test_bit(HCI_UP, &hdev->flags)) {
|
if (!test_bit(HCI_UP, &hdev->flags)) {
|
||||||
err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
|
err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
|
||||||
ENETDOWN);
|
MGMT_STATUS_NOT_POWERED);
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
|
if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) {
|
||||||
err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
|
err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
|
||||||
EOPNOTSUPP);
|
MGMT_STATUS_NOT_SUPPORTED);
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
|
if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
|
||||||
err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, EBUSY);
|
err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA,
|
||||||
|
MGMT_STATUS_BUSY);
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1597,19 +1719,20 @@ static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data,
|
|||||||
|
|
||||||
if (len != sizeof(*cp))
|
if (len != sizeof(*cp))
|
||||||
return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
|
return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
|
||||||
EINVAL);
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
|
return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
|
||||||
ENODEV);
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash,
|
err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash,
|
||||||
cp->randomizer);
|
cp->randomizer);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
err = cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, -err);
|
err = cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA,
|
||||||
|
MGMT_STATUS_FAILED);
|
||||||
else
|
else
|
||||||
err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL,
|
err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL,
|
||||||
0);
|
0);
|
||||||
@ -1631,19 +1754,19 @@ static int remove_remote_oob_data(struct sock *sk, u16 index,
|
|||||||
|
|
||||||
if (len != sizeof(*cp))
|
if (len != sizeof(*cp))
|
||||||
return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
|
return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
|
||||||
EINVAL);
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
|
return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
|
||||||
ENODEV);
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
err = hci_remove_remote_oob_data(hdev, &cp->bdaddr);
|
err = hci_remove_remote_oob_data(hdev, &cp->bdaddr);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
err = cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
|
err = cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
|
||||||
-err);
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
else
|
else
|
||||||
err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
|
err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
@ -1664,12 +1787,14 @@ static int start_discovery(struct sock *sk, u16 index)
|
|||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, ENODEV);
|
return cmd_status(sk, index, MGMT_OP_START_DISCOVERY,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
if (!test_bit(HCI_UP, &hdev->flags)) {
|
if (!test_bit(HCI_UP, &hdev->flags)) {
|
||||||
err = cmd_status(sk, index, MGMT_OP_START_DISCOVERY, ENETDOWN);
|
err = cmd_status(sk, index, MGMT_OP_START_DISCOVERY,
|
||||||
|
MGMT_STATUS_NOT_POWERED);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1700,7 +1825,8 @@ static int stop_discovery(struct sock *sk, u16 index)
|
|||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, ENODEV);
|
return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
@ -1732,18 +1858,19 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data,
|
|||||||
|
|
||||||
if (len != sizeof(*cp))
|
if (len != sizeof(*cp))
|
||||||
return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
|
return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
|
||||||
EINVAL);
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
|
return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
|
||||||
ENODEV);
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
err = hci_blacklist_add(hdev, &cp->bdaddr);
|
err = hci_blacklist_add(hdev, &cp->bdaddr);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
err = cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, -err);
|
err = cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
|
||||||
|
MGMT_STATUS_FAILED);
|
||||||
else
|
else
|
||||||
err = cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE,
|
err = cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE,
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
@ -1765,19 +1892,20 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
|
|||||||
|
|
||||||
if (len != sizeof(*cp))
|
if (len != sizeof(*cp))
|
||||||
return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
|
return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
|
||||||
EINVAL);
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
|
return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
|
||||||
ENODEV);
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock_bh(hdev);
|
hci_dev_lock_bh(hdev);
|
||||||
|
|
||||||
err = hci_blacklist_del(hdev, &cp->bdaddr);
|
err = hci_blacklist_del(hdev, &cp->bdaddr);
|
||||||
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
err = cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE, -err);
|
err = cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
|
||||||
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
else
|
else
|
||||||
err = cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE,
|
err = cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE,
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
@ -1801,12 +1929,12 @@ static int set_fast_connectable(struct sock *sk, u16 index,
|
|||||||
|
|
||||||
if (len != sizeof(*cp))
|
if (len != sizeof(*cp))
|
||||||
return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
|
return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
|
||||||
EINVAL);
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hdev = hci_dev_get(index);
|
hdev = hci_dev_get(index);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
|
return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
|
||||||
ENODEV);
|
MGMT_STATUS_INVALID_PARAMS);
|
||||||
|
|
||||||
hci_dev_lock(hdev);
|
hci_dev_lock(hdev);
|
||||||
|
|
||||||
@ -1824,14 +1952,14 @@ static int set_fast_connectable(struct sock *sk, u16 index,
|
|||||||
sizeof(acp), &acp);
|
sizeof(acp), &acp);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
|
err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
|
||||||
-err);
|
MGMT_STATUS_FAILED);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
|
err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
|
err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE,
|
||||||
-err);
|
MGMT_STATUS_FAILED);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1970,7 +2098,8 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BT_DBG("Unknown op %u", opcode);
|
BT_DBG("Unknown op %u", opcode);
|
||||||
err = cmd_status(sk, index, opcode, 0x01);
|
err = cmd_status(sk, index, opcode,
|
||||||
|
MGMT_STATUS_UNKNOWN_COMMAND);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2093,13 +2222,15 @@ int mgmt_connectable(struct hci_dev *hdev, u8 connectable)
|
|||||||
|
|
||||||
int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
|
int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
|
||||||
{
|
{
|
||||||
|
u8 mgmt_err = mgmt_status(status);
|
||||||
|
|
||||||
if (scan & SCAN_PAGE)
|
if (scan & SCAN_PAGE)
|
||||||
mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
|
mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
|
||||||
cmd_status_rsp, &status);
|
cmd_status_rsp, &mgmt_err);
|
||||||
|
|
||||||
if (scan & SCAN_INQUIRY)
|
if (scan & SCAN_INQUIRY)
|
||||||
mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
|
mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
|
||||||
cmd_status_rsp, &status);
|
cmd_status_rsp, &mgmt_err);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2190,6 +2321,7 @@ int mgmt_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
|||||||
int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status)
|
int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status)
|
||||||
{
|
{
|
||||||
struct pending_cmd *cmd;
|
struct pending_cmd *cmd;
|
||||||
|
u8 mgmt_err = mgmt_status(status);
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
|
cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
|
||||||
@ -2206,7 +2338,7 @@ int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status)
|
|||||||
&rp, sizeof(rp));
|
&rp, sizeof(rp));
|
||||||
} else
|
} else
|
||||||
err = cmd_status(cmd->sk, hdev->id, MGMT_OP_DISCONNECT,
|
err = cmd_status(cmd->sk, hdev->id, MGMT_OP_DISCONNECT,
|
||||||
status);
|
mgmt_err);
|
||||||
|
|
||||||
mgmt_pending_remove(cmd);
|
mgmt_pending_remove(cmd);
|
||||||
|
|
||||||
@ -2220,7 +2352,7 @@ int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
|||||||
|
|
||||||
bacpy(&ev.addr.bdaddr, bdaddr);
|
bacpy(&ev.addr.bdaddr, bdaddr);
|
||||||
ev.addr.type = link_to_mgmt(link_type, addr_type);
|
ev.addr.type = link_to_mgmt(link_type, addr_type);
|
||||||
ev.status = status;
|
ev.status = mgmt_status(status);
|
||||||
|
|
||||||
return mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
|
return mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
|
||||||
}
|
}
|
||||||
@ -2248,7 +2380,7 @@ int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
bacpy(&rp.bdaddr, bdaddr);
|
bacpy(&rp.bdaddr, bdaddr);
|
||||||
rp.status = status;
|
rp.status = mgmt_status(status);
|
||||||
|
|
||||||
err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY, &rp,
|
err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY, &rp,
|
||||||
sizeof(rp));
|
sizeof(rp));
|
||||||
@ -2270,7 +2402,7 @@ int mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
bacpy(&rp.bdaddr, bdaddr);
|
bacpy(&rp.bdaddr, bdaddr);
|
||||||
rp.status = status;
|
rp.status = mgmt_status(status);
|
||||||
|
|
||||||
err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY, &rp,
|
err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY, &rp,
|
||||||
sizeof(rp));
|
sizeof(rp));
|
||||||
@ -2307,7 +2439,7 @@ static int confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
bacpy(&rp.bdaddr, bdaddr);
|
bacpy(&rp.bdaddr, bdaddr);
|
||||||
rp.status = status;
|
rp.status = mgmt_status(status);
|
||||||
err = cmd_complete(cmd->sk, hdev->id, opcode, &rp, sizeof(rp));
|
err = cmd_complete(cmd->sk, hdev->id, opcode, &rp, sizeof(rp));
|
||||||
|
|
||||||
mgmt_pending_remove(cmd);
|
mgmt_pending_remove(cmd);
|
||||||
@ -2318,14 +2450,14 @@ static int confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|||||||
int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
||||||
u8 status)
|
u8 status)
|
||||||
{
|
{
|
||||||
return confirm_reply_complete(hdev, bdaddr, status,
|
return confirm_reply_complete(hdev, bdaddr, mgmt_status(status),
|
||||||
MGMT_OP_USER_CONFIRM_REPLY);
|
MGMT_OP_USER_CONFIRM_REPLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev,
|
int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev,
|
||||||
bdaddr_t *bdaddr, u8 status)
|
bdaddr_t *bdaddr, u8 status)
|
||||||
{
|
{
|
||||||
return confirm_reply_complete(hdev, bdaddr, status,
|
return confirm_reply_complete(hdev, bdaddr, mgmt_status(status),
|
||||||
MGMT_OP_USER_CONFIRM_NEG_REPLY);
|
MGMT_OP_USER_CONFIRM_NEG_REPLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2334,7 +2466,7 @@ int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status)
|
|||||||
struct mgmt_ev_auth_failed ev;
|
struct mgmt_ev_auth_failed ev;
|
||||||
|
|
||||||
bacpy(&ev.bdaddr, bdaddr);
|
bacpy(&ev.bdaddr, bdaddr);
|
||||||
ev.status = status;
|
ev.status = mgmt_status(status);
|
||||||
|
|
||||||
return mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
|
return mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
|
||||||
}
|
}
|
||||||
@ -2354,7 +2486,7 @@ int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
|
|||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
|
err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
|
||||||
EIO);
|
mgmt_status(status));
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2389,7 +2521,8 @@ int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
|
|||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
err = cmd_status(cmd->sk, hdev->id,
|
err = cmd_status(cmd->sk, hdev->id,
|
||||||
MGMT_OP_READ_LOCAL_OOB_DATA, EIO);
|
MGMT_OP_READ_LOCAL_OOB_DATA,
|
||||||
|
mgmt_status(status));
|
||||||
} else {
|
} else {
|
||||||
struct mgmt_rp_read_local_oob_data rp;
|
struct mgmt_rp_read_local_oob_data rp;
|
||||||
|
|
||||||
@ -2447,7 +2580,7 @@ int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
|
|||||||
if (!cmd)
|
if (!cmd)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
err = cmd_status(cmd->sk, hdev->id, cmd->opcode, status);
|
err = cmd_status(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status));
|
||||||
mgmt_pending_remove(cmd);
|
mgmt_pending_remove(cmd);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user