diff options
author | Andre Guedes <andre.guedes@openbossa.org> | 2014-02-26 18:21:54 -0500 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2014-02-26 22:41:35 -0500 |
commit | 7d474e06ef8ee3941a4a0dcb824b8e3006f25d3e (patch) | |
tree | d2c971199d38062092f9c10a65f0f8e983fc9509 /net/bluetooth/hci_core.c | |
parent | 5b906a84a5b3458d810a9faab74783525f4a84d7 (diff) |
Bluetooth: Add le_auto_conn file on debugfs
This patch adds to debugfs the le_auto_conn file. This file will be
used to test LE auto connection infrastructure.
This file accept writes in the following format:
"add <address> <address_type> [auto_connect]"
"del <address> <address_type>"
"clr"
The <address type> values are:
* 0 for public address
* 1 for random address
The [auto_connect] values are (for more details see struct hci_
conn_params):
* 0 for disabled (default)
* 1 for always
* 2 for link loss
So for instance, if you want the kernel autonomously establishes
connections with device AA:BB:CC:DD:EE:FF (public address) every
time the device enters in connectable mode (starts advertising),
you should run the command:
$ echo "add AA:BB:CC:DD:EE:FF 0 1" > /sys/kernel/debug/bluetooth/hci0/le_auto_conn
To delete the connection parameters for that device, run the command:
$ echo "del AA:BB:CC:DD:EE:FF 0" > /sys/kernel/debug/bluetooth/hci0/le_auto_conn
To clear the connection parameters list, run the command:
$ echo "clr" > /sys/kernel/debug/bluetooth/hci0/le_auto_conn
Finally. to get the list of connection parameters configured in kernel,
read the le_auto_conn file:
$ cat /sys/kernel/debug/bluetooth/hci0/le_auto_conn
This file is created only if LE is enabled.
Signed-off-by: Andre Guedes <andre.guedes@openbossa.org>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/hci_core.c')
-rw-r--r-- | net/bluetooth/hci_core.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 6d83ca040970..0b96f20238d8 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -896,6 +896,115 @@ static const struct file_operations lowpan_debugfs_fops = { | |||
896 | .llseek = default_llseek, | 896 | .llseek = default_llseek, |
897 | }; | 897 | }; |
898 | 898 | ||
899 | static int le_auto_conn_show(struct seq_file *sf, void *ptr) | ||
900 | { | ||
901 | struct hci_dev *hdev = sf->private; | ||
902 | struct hci_conn_params *p; | ||
903 | |||
904 | hci_dev_lock(hdev); | ||
905 | |||
906 | list_for_each_entry(p, &hdev->le_conn_params, list) { | ||
907 | seq_printf(sf, "%pMR %u %u\n", &p->addr, p->addr_type, | ||
908 | p->auto_connect); | ||
909 | } | ||
910 | |||
911 | hci_dev_unlock(hdev); | ||
912 | |||
913 | return 0; | ||
914 | } | ||
915 | |||
916 | static int le_auto_conn_open(struct inode *inode, struct file *file) | ||
917 | { | ||
918 | return single_open(file, le_auto_conn_show, inode->i_private); | ||
919 | } | ||
920 | |||
921 | static ssize_t le_auto_conn_write(struct file *file, const char __user *data, | ||
922 | size_t count, loff_t *offset) | ||
923 | { | ||
924 | struct seq_file *sf = file->private_data; | ||
925 | struct hci_dev *hdev = sf->private; | ||
926 | u8 auto_connect = 0; | ||
927 | bdaddr_t addr; | ||
928 | u8 addr_type; | ||
929 | char *buf; | ||
930 | int err = 0; | ||
931 | int n; | ||
932 | |||
933 | /* Don't allow partial write */ | ||
934 | if (*offset != 0) | ||
935 | return -EINVAL; | ||
936 | |||
937 | if (count < 3) | ||
938 | return -EINVAL; | ||
939 | |||
940 | buf = kzalloc(count, GFP_KERNEL); | ||
941 | if (!buf) | ||
942 | return -ENOMEM; | ||
943 | |||
944 | if (copy_from_user(buf, data, count)) { | ||
945 | err = -EFAULT; | ||
946 | goto done; | ||
947 | } | ||
948 | |||
949 | if (memcmp(buf, "add", 3) == 0) { | ||
950 | n = sscanf(&buf[4], "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu %hhu", | ||
951 | &addr.b[5], &addr.b[4], &addr.b[3], &addr.b[2], | ||
952 | &addr.b[1], &addr.b[0], &addr_type, | ||
953 | &auto_connect); | ||
954 | |||
955 | if (n < 7) { | ||
956 | err = -EINVAL; | ||
957 | goto done; | ||
958 | } | ||
959 | |||
960 | hci_dev_lock(hdev); | ||
961 | err = hci_conn_params_add(hdev, &addr, addr_type, auto_connect, | ||
962 | hdev->le_conn_min_interval, | ||
963 | hdev->le_conn_max_interval); | ||
964 | hci_dev_unlock(hdev); | ||
965 | |||
966 | if (err) | ||
967 | goto done; | ||
968 | } else if (memcmp(buf, "del", 3) == 0) { | ||
969 | n = sscanf(&buf[4], "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu", | ||
970 | &addr.b[5], &addr.b[4], &addr.b[3], &addr.b[2], | ||
971 | &addr.b[1], &addr.b[0], &addr_type); | ||
972 | |||
973 | if (n < 7) { | ||
974 | err = -EINVAL; | ||
975 | goto done; | ||
976 | } | ||
977 | |||
978 | hci_dev_lock(hdev); | ||
979 | hci_conn_params_del(hdev, &addr, addr_type); | ||
980 | hci_dev_unlock(hdev); | ||
981 | } else if (memcmp(buf, "clr", 3) == 0) { | ||
982 | hci_dev_lock(hdev); | ||
983 | hci_conn_params_clear(hdev); | ||
984 | hci_pend_le_conns_clear(hdev); | ||
985 | hci_update_background_scan(hdev); | ||
986 | hci_dev_unlock(hdev); | ||
987 | } else { | ||
988 | err = -EINVAL; | ||
989 | } | ||
990 | |||
991 | done: | ||
992 | kfree(buf); | ||
993 | |||
994 | if (err) | ||
995 | return err; | ||
996 | else | ||
997 | return count; | ||
998 | } | ||
999 | |||
1000 | static const struct file_operations le_auto_conn_fops = { | ||
1001 | .open = le_auto_conn_open, | ||
1002 | .read = seq_read, | ||
1003 | .write = le_auto_conn_write, | ||
1004 | .llseek = seq_lseek, | ||
1005 | .release = single_release, | ||
1006 | }; | ||
1007 | |||
899 | /* ---- HCI requests ---- */ | 1008 | /* ---- HCI requests ---- */ |
900 | 1009 | ||
901 | static void hci_req_sync_complete(struct hci_dev *hdev, u8 result) | 1010 | static void hci_req_sync_complete(struct hci_dev *hdev, u8 result) |
@@ -1694,6 +1803,8 @@ static int __hci_init(struct hci_dev *hdev) | |||
1694 | hdev, &adv_channel_map_fops); | 1803 | hdev, &adv_channel_map_fops); |
1695 | debugfs_create_file("6lowpan", 0644, hdev->debugfs, hdev, | 1804 | debugfs_create_file("6lowpan", 0644, hdev->debugfs, hdev, |
1696 | &lowpan_debugfs_fops); | 1805 | &lowpan_debugfs_fops); |
1806 | debugfs_create_file("le_auto_conn", 0644, hdev->debugfs, hdev, | ||
1807 | &le_auto_conn_fops); | ||
1697 | } | 1808 | } |
1698 | 1809 | ||
1699 | return 0; | 1810 | return 0; |