Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 237320
b: refs/heads/master
c: 1aff6f0
h: refs/heads/master
v: v3
  • Loading branch information
Johan Hedberg authored and Gustavo F. Padovan committed Feb 8, 2011
1 parent ec2f1fc commit b13dafe
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d5859e22cd40b73164b3e5d8d5d796f96edcc6af
refs/heads/master: 1aff6f09491f454d4cd9f405c783fa5e9d3168a0
1 change: 1 addition & 0 deletions trunk/include/net/bluetooth/hci.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ enum {
HCI_AUTO_OFF,
HCI_MGMT,
HCI_PAIRABLE,
HCI_SERVICE_CACHE,
};

/* HCI ioctl defines */
Expand Down
3 changes: 3 additions & 0 deletions trunk/include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ struct bdaddr_list {
struct bt_uuid {
struct list_head list;
u8 uuid[16];
u8 svc_hint;
};

#define NUM_REASSEMBLY 4
Expand All @@ -86,6 +87,8 @@ struct hci_dev {
bdaddr_t bdaddr;
__u8 dev_name[248];
__u8 dev_class[3];
__u8 major_class;
__u8 minor_class;
__u8 features[8];
__u8 commands[64];
__u8 ssp_mode;
Expand Down
14 changes: 14 additions & 0 deletions trunk/include/net/bluetooth/mgmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ struct mgmt_mode {
struct mgmt_cp_add_uuid {
__le16 index;
__u8 uuid[16];
__u8 svc_hint;
} __packed;

#define MGMT_OP_REMOVE_UUID 0x000A
Expand All @@ -84,6 +85,19 @@ struct mgmt_cp_remove_uuid {
__u8 uuid[16];
} __packed;

#define MGMT_OP_SET_DEV_CLASS 0x000B
struct mgmt_cp_set_dev_class {
__le16 index;
__u8 major;
__u8 minor;
} __packed;

#define MGMT_OP_SET_SERVICE_CACHE 0x000C
struct mgmt_cp_set_service_cache {
__le16 index;
__u8 enable;
} __packed;

#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
Expand Down
121 changes: 118 additions & 3 deletions trunk/net/bluetooth/mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ static int set_pairable(struct sock *sk, unsigned char *data, u16 len)
return err;
}

static int uuid_rsp(struct sock *sk, u16 opcode, u16 index)
static int index_rsp(struct sock *sk, u16 opcode, u16 index)
{
struct mgmt_hdr *hdr;
struct mgmt_ev_cmd_complete *ev;
Expand All @@ -596,6 +596,39 @@ static int uuid_rsp(struct sock *sk, u16 opcode, u16 index)
return 0;
}

static u8 get_service_classes(struct hci_dev *hdev)
{
struct list_head *p;
u8 val = 0;

list_for_each(p, &hdev->uuids) {
struct bt_uuid *uuid = list_entry(p, struct bt_uuid, list);

val |= uuid->svc_hint;
}

return val;
}

static int update_class(struct hci_dev *hdev)
{
u8 cod[3];

BT_DBG("%s", hdev->name);

if (test_bit(HCI_SERVICE_CACHE, &hdev->flags))
return 0;

cod[0] = hdev->minor_class;
cod[1] = hdev->major_class;
cod[2] = get_service_classes(hdev);

if (memcmp(cod, hdev->dev_class, 3) == 0)
return 0;

return hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
}

static int add_uuid(struct sock *sk, unsigned char *data, u16 len)
{
struct mgmt_cp_add_uuid *cp;
Expand All @@ -622,10 +655,15 @@ static int add_uuid(struct sock *sk, unsigned char *data, u16 len)
}

memcpy(uuid->uuid, cp->uuid, 16);
uuid->svc_hint = cp->svc_hint;

list_add(&uuid->list, &hdev->uuids);

err = uuid_rsp(sk, MGMT_OP_ADD_UUID, dev_id);
err = update_class(hdev);
if (err < 0)
goto failed;

err = index_rsp(sk, MGMT_OP_ADD_UUID, dev_id);

failed:
hci_dev_unlock_bh(hdev);
Expand Down Expand Up @@ -676,7 +714,11 @@ static int remove_uuid(struct sock *sk, unsigned char *data, u16 len)
goto unlock;
}

err = uuid_rsp(sk, MGMT_OP_REMOVE_UUID, dev_id);
err = update_class(hdev);
if (err < 0)
goto unlock;

err = index_rsp(sk, MGMT_OP_REMOVE_UUID, dev_id);

unlock:
hci_dev_unlock_bh(hdev);
Expand All @@ -685,6 +727,73 @@ static int remove_uuid(struct sock *sk, unsigned char *data, u16 len)
return err;
}

static int set_dev_class(struct sock *sk, unsigned char *data, u16 len)
{
struct hci_dev *hdev;
struct mgmt_cp_set_dev_class *cp;
u16 dev_id;
int err;

cp = (void *) data;
dev_id = get_unaligned_le16(&cp->index);

BT_DBG("request for hci%u", dev_id);

hdev = hci_dev_get(dev_id);
if (!hdev)
return cmd_status(sk, MGMT_OP_SET_DEV_CLASS, ENODEV);

hci_dev_lock_bh(hdev);

hdev->major_class = cp->major;
hdev->minor_class = cp->minor;

err = update_class(hdev);

if (err == 0)
err = index_rsp(sk, MGMT_OP_SET_DEV_CLASS, dev_id);

hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);

return err;
}

static int set_service_cache(struct sock *sk, unsigned char *data, u16 len)
{
struct hci_dev *hdev;
struct mgmt_cp_set_service_cache *cp;
u16 dev_id;
int err;

cp = (void *) data;
dev_id = get_unaligned_le16(&cp->index);

hdev = hci_dev_get(dev_id);
if (!hdev)
return cmd_status(sk, MGMT_OP_SET_SERVICE_CACHE, ENODEV);

hci_dev_lock_bh(hdev);

BT_DBG("hci%u enable %d", dev_id, cp->enable);

if (cp->enable) {
set_bit(HCI_SERVICE_CACHE, &hdev->flags);
err = 0;
} else {
clear_bit(HCI_SERVICE_CACHE, &hdev->flags);
err = update_class(hdev);
}

if (err == 0)
err = index_rsp(sk, MGMT_OP_SET_SERVICE_CACHE, dev_id);

hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);

return err;
}

int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
{
unsigned char *buf;
Expand Down Expand Up @@ -743,6 +852,12 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
case MGMT_OP_REMOVE_UUID:
err = remove_uuid(sk, buf + sizeof(*hdr), len);
break;
case MGMT_OP_SET_DEV_CLASS:
err = set_dev_class(sk, buf + sizeof(*hdr), len);
break;
case MGMT_OP_SET_SERVICE_CACHE:
err = set_service_cache(sk, buf + sizeof(*hdr), len);
break;
default:
BT_DBG("Unknown op %u", opcode);
err = cmd_status(sk, opcode, 0x01);
Expand Down

0 comments on commit b13dafe

Please sign in to comment.