Marcel, Here is the modified netlink patch. Let me know what needs to be changed. -Alok.
From 52e109b77150a9e29d8861794a2dde2b99a94cc8 Mon Sep 17 00:00:00 2001 From: Alok Barsode <alokbarsode@xxxxxxxxx> Date: Wed, 14 Jan 2009 18:34:55 +0530 Subject: [PATCH] Adding netlink support to bluetooth. Adding files netlink.c and netlink.h to net/bluetooth for netlink support. Adding support for DEVUP. Redefining hci_req_lock to use down_trylock Signed-off-by: Alok Barsode <alokbarsode@xxxxxxxxx> --- include/net/bluetooth/bluetooth.h | 3 + include/net/bluetooth/hci_core.h | 4 +- net/bluetooth/Makefile | 2 +- net/bluetooth/af_bluetooth.c | 6 ++ net/bluetooth/hci_core.c | 6 ++ net/bluetooth/netlink.c | 168 +++++++++++++++++++++++++++++++++++++ net/bluetooth/netlink.h | 28 ++++++ 7 files changed, 215 insertions(+), 2 deletions(-) create mode 100644 net/bluetooth/netlink.c create mode 100644 net/bluetooth/netlink.h diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 624da4d..ac5e40e 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -189,4 +189,7 @@ extern void bt_sysfs_cleanup(void); extern struct class *bt_class; +extern int bluetooth_netlink_init(void); +extern void bluetooth_netlink_cleanup(void); + #endif /* __BLUETOOTH_H */ diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 4b14972..744146e 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -675,9 +675,11 @@ struct hci_sec_filter { #define HCI_REQ_PEND 1 #define HCI_REQ_CANCELED 2 -#define hci_req_lock(d) down(&d->req_lock) +#define hci_req_lock(d) down_trylock(&d->req_lock) #define hci_req_unlock(d) up(&d->req_lock) void hci_req_complete(struct hci_dev *hdev, int result); +/* FIXME: This is temporarily added to export __hci_request and hci_init_req */ +int hci_init_request(struct hci_dev *hdev); #endif /* __HCI_CORE_H */ diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile index d1e433f..f014d48 100644 --- a/net/bluetooth/Makefile +++ b/net/bluetooth/Makefile @@ -10,4 +10,4 @@ obj-$(CONFIG_BT_BNEP) += bnep/ obj-$(CONFIG_BT_CMTP) += cmtp/ obj-$(CONFIG_BT_HIDP) += hidp/ -bluetooth-objs := af_bluetooth.o hci_core.o hci_conn.o hci_event.o hci_sock.o hci_sysfs.o lib.o +bluetooth-objs := af_bluetooth.o hci_core.o hci_conn.o hci_event.o hci_sock.o hci_sysfs.o lib.o netlink.o diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 744ed3f..b778a0e 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -425,6 +425,10 @@ static int __init bt_init(void) if (err < 0) return err; + err = bluetooth_netlink_init(); + if (err < 0) + return err; + err = sock_register(&bt_sock_family_ops); if (err < 0) { bt_sysfs_cleanup(); @@ -445,6 +449,8 @@ static void __exit bt_exit(void) sock_unregister(PF_BLUETOOTH); bt_sysfs_cleanup(); + + bluetooth_netlink_cleanup(); } subsys_initcall(bt_init); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index ba78cc1..2a8fb7a 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -251,6 +251,12 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt) hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); } +int hci_init_request(struct hci_dev *hdev) +{ + return __hci_request(hdev, hci_init_req, 0, + msecs_to_jiffies(HCI_INIT_TIMEOUT)); +} + static void hci_scan_req(struct hci_dev *hdev, unsigned long opt) { __u8 scan = opt; diff --git a/net/bluetooth/netlink.c b/net/bluetooth/netlink.c new file mode 100644 index 0000000..dc9fb20 --- /dev/null +++ b/net/bluetooth/netlink.c @@ -0,0 +1,168 @@ +/* + * This is the netlink-based bluetooth interface. + * + * Copyright 2008 Alok Barsode <alok.barsode@xxxxxxxxxx> + */ + +#include <asm/system.h> +#include <asm/uaccess.h> +#include <asm/unaligned.h> + +#include <net/genetlink.h> +#include <linux/module.h> +#include <linux/kernel.h> + +#include <net/bluetooth/bluetooth.h> +#include <net/bluetooth/hci_core.h> + +#include "netlink.h" + +/* family definition */ +static struct genl_family bluetooth_fam = { + .id = GENL_ID_GENERATE, + .hdrsize = 0, + .name = "bluetooth", + .version = VERSION, + .maxattr = ATTR_MAX +}; + +static struct nla_policy bluetooth_policy[ATTR_MAX + 1] = { + [DEVID] = { .type = NLA_U16 }, + [FLAG] = { .type = NLA_U16 }, +}; + +static int bluetooth_devup(struct sk_buff *skb, struct genl_info *info) +{ + int ret=0; + __u16 dev; + void *hdr; + struct sk_buff *msg; + struct hci_dev *hdev; + + if (!info->attrs[DEVID]) + return -EINVAL; + + dev = nla_get_u16(info->attrs[DEVID]); + + msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + + if (!msg) + return -ENOBUFS; + + hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &bluetooth_fam, 0, DEVUP); + + if (hdr == NULL){ + nlmsg_free(msg); + return -ENOBUFS; + } + + if (!(hdev = hci_dev_get(dev))){ + nlmsg_free(msg); + return -ENODEV; + } + + printk("%s %p", hdev->name, hdev); + + if (hci_req_lock(hdev)) { + ret = -EBUSY; + goto done; + } + + if (test_bit(HCI_UP, &hdev->flags)) { + ret = -EALREADY; + goto done; + } + + if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) + set_bit(HCI_RAW, &hdev->flags); + + if (hdev->open(hdev)) { + ret = -EIO; + goto done; + } + + NLA_PUT_U16(msg, DEVID, dev); + + if (!test_bit(HCI_RAW, &hdev->flags)) { + atomic_set(&hdev->cmd_cnt, 1); + set_bit(HCI_INIT, &hdev->flags); + + //__hci_request(hdev, hci_init_req, 0, HZ); + ret = hci_init_request(hdev); + + clear_bit(HCI_INIT, &hdev->flags); + } + + if (!ret) { + hci_dev_hold(hdev); + set_bit(HCI_UP, &hdev->flags); + NLA_PUT_U16(msg, FLAG, HCI_DEV_UP); + } else { + /* Init failed, cleanup */ + tasklet_kill(&hdev->rx_task); + tasklet_kill(&hdev->tx_task); + tasklet_kill(&hdev->cmd_task); + + skb_queue_purge(&hdev->cmd_q); + skb_queue_purge(&hdev->rx_q); + + if (hdev->flush) + hdev->flush(hdev); + + if (hdev->sent_cmd) { + kfree_skb(hdev->sent_cmd); + hdev->sent_cmd = NULL; + } + + hdev->close(hdev); + hdev->flags = 0; + NLA_PUT_U16(msg, FLAG, HCI_DEV_DOWN); + } + + genlmsg_end(msg, hdr); + done: + hci_req_unlock(hdev); + hci_dev_put(hdev); + if (ret < 0) + return ret; + + return genlmsg_unicast(msg, info->snd_pid); + + nla_put_failure: + genlmsg_cancel(msg, hdr); + return -EMSGSIZE; +} + +static struct genl_ops bluetooth_ops = { + .cmd = DEVUP, + .policy = bluetooth_policy, + .doit = bluetooth_devup, + .flags = GENL_ADMIN_PERM, + .dumpit = NULL, +}; + + +/* initialisation/exit functions */ +int __init bluetooth_netlink_init(void) +{ + int err; + + err = genl_register_family(&bluetooth_fam); + if (err) + return err; + + err = genl_register_ops(&bluetooth_fam, &bluetooth_ops); + if (err) + goto err_out; + + return 0; + +err_out: + genl_unregister_family(&bluetooth_fam); + return err; +} + +void bluetooth_netlink_cleanup(void) +{ + genl_unregister_family(&bluetooth_fam); +} diff --git a/net/bluetooth/netlink.h b/net/bluetooth/netlink.h new file mode 100644 index 0000000..0484bb4 --- /dev/null +++ b/net/bluetooth/netlink.h @@ -0,0 +1,28 @@ +/* + * This is the netlink-based bluetooth interface. + * + * Copyright 2008 Alok Barsode <alok.barsode@xxxxxxxxxx> + */ +#ifndef __NETLINK_H +#define __NETLINK_H + +#define VERSION 1 + +enum bluetooth_attr { + ATTR_UNSPEC, + DEVID, + FLAG, + /* Add attributes here */ + __ATTR_MAX, + ATTR_MAX = __ATTR_MAX - 1 +}; + +enum bluetooth_cmds { + CMD_UNSPEC, + DEVUP, + /* Add command here */ + __CMD_MAX, + CMD_MAX = __CMD_MAX - 1 +}; + +#endif /* __NETLINK_H */ -- 1.5.6.3