All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFCv2 0/6] Draft Software/Virtual AMP80211
@ 2012-04-24 13:17 Andrei Emeltchenko
  2012-04-24 13:17 ` [RFCv2 1/6] mac80211: softamp: Adds Bluetooth Software AMP Andrei Emeltchenko
                   ` (5 more replies)
  0 siblings, 6 replies; 12+ messages in thread
From: Andrei Emeltchenko @ 2012-04-24 13:17 UTC (permalink / raw)
  To: linux-bluetooth, linux-wireless

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

RFC for Software / Virtual _DRAFT_ implementation of Bluetooth High Speed
by using wireless driver. Currently it can be used for testing Bluetooth
A2MP protocol.

Changes:
	RFCv2: Process basic HCI commands and basic data traffic; added skeleton
	for Netlink comms, took comments from reviewers.
	RFCv1: Initial release.

TODO:
	Change names from vamp to <softamp|bt_softamp|etc>

Main ideas:
 - Use existing wireless infrastructure nl80211, mac80211.
 - Use virtual interface of type NL80211_IFTYPE_BLUETOOTH_AMP. Then all
drivers supporting virtual interface should work.

After modifying iw it will be enabled by adding new virtual interface.

# iw phy <physical device> interface add vamp type vamp
# iw dev
phy#0
	Interface vamp
		ifindex 6
		type Virtual AMP
...
# hciconfig 
hci1:	Type: AMP  Bus: VIRTUAL
	BD Address: 00:00:00:00:00:00  ACL MTU: 0:0  SCO MTU: 0:0
	DOWN 
	RX bytes:0 acl:0 sco:0 events:0 errors:0
	TX bytes:0 acl:0 sco:0 commands:0 errors:0
...

Andrei Emeltchenko (6):
  mac80211: softamp: Adds Bluetooth Software AMP
  mac80211: softamp: Adds build config option
  hwsim: Adds support for BT SOFTAMP for testing
  mac80211: softamp: Handle assoc request
  mac80211: softamp: Netlink interface to softamp
  mac80211: softamp: Handle data traffic

 drivers/net/wireless/mac80211_hwsim.c |    3 +-
 include/linux/ieee80211.h             |   13 +
 include/linux/nl80211.h               |    1 +
 net/mac80211/Kconfig                  |    9 +
 net/mac80211/Makefile                 |    2 +
 net/mac80211/ieee80211_i.h            |    5 +
 net/mac80211/iface.c                  |    9 +
 net/mac80211/rx.c                     |    4 +
 net/mac80211/sta_info.h               |    4 +
 net/mac80211/util.c                   |    1 +
 net/mac80211/virtual_amp.c            |  675 +++++++++++++++++++++++++++++++++
 net/mac80211/virtual_amp.h            |   96 +++++
 12 files changed, 821 insertions(+), 1 deletion(-)
 create mode 100644 net/mac80211/virtual_amp.c
 create mode 100644 net/mac80211/virtual_amp.h

-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [RFCv2 1/6] mac80211: softamp: Adds Bluetooth Software AMP
  2012-04-24 13:17 [RFCv2 0/6] Draft Software/Virtual AMP80211 Andrei Emeltchenko
@ 2012-04-24 13:17 ` Andrei Emeltchenko
  2012-05-07 11:41   ` Johannes Berg
  2012-04-24 13:17 ` [RFCv2 2/6] mac80211: softamp: Adds build config option Andrei Emeltchenko
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Andrei Emeltchenko @ 2012-04-24 13:17 UTC (permalink / raw)
  To: linux-bluetooth, linux-wireless

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Add new interface type BLUETOOTH_SOFTAMP which emulates Bluetooth AMP
Controller. AMP is Alternate MAC/PHYs Controller for Bluetooth subsystem.
When an AMP is common between the two devices, the Bluetooth system
provides mechanisms for moving data traffic from BR/EDR Controller to
an AMP Controller.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/linux/nl80211.h    |    1 +
 net/mac80211/ieee80211_i.h |    5 +
 net/mac80211/iface.c       |    9 ++
 net/mac80211/util.c        |    1 +
 net/mac80211/virtual_amp.c |  341 ++++++++++++++++++++++++++++++++++++++++++++
 net/mac80211/virtual_amp.h |   37 +++++
 6 files changed, 394 insertions(+)
 create mode 100644 net/mac80211/virtual_amp.c
 create mode 100644 net/mac80211/virtual_amp.h

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index e474f6e..ed1bf6d 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1546,6 +1546,7 @@ enum nl80211_iftype {
 	NL80211_IFTYPE_MESH_POINT,
 	NL80211_IFTYPE_P2P_CLIENT,
 	NL80211_IFTYPE_P2P_GO,
+	NL80211_IFTYPE_BLUETOOTH_SOFTAMP,
 
 	/* keep last */
 	NUM_NL80211_IFTYPES,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d9798a3..1e0af56 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -602,6 +602,10 @@ struct ieee80211_if_mesh {
 	} security;
 };
 
+struct ieee80211_if_bt_softamp {
+	struct hci_dev *hdev;
+};
+
 #ifdef CONFIG_MAC80211_MESH
 #define IEEE80211_IFSTA_MESH_CTR_INC(msh, name)	\
 	do { (msh)->mshstats.name++; } while (0)
@@ -716,6 +720,7 @@ struct ieee80211_sub_if_data {
 		struct ieee80211_if_managed mgd;
 		struct ieee80211_if_ibss ibss;
 		struct ieee80211_if_mesh mesh;
+		struct ieee80211_if_bt_softamp softamp;
 		u32 mntr_flags;
 	} u;
 
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 96f8773..b92d8e3 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -25,6 +25,7 @@
 #include "driver-ops.h"
 #include "wme.h"
 #include "rate.h"
+#include "virtual_amp.h"
 
 /**
  * DOC: Interface list locking
@@ -211,6 +212,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
 	case NL80211_IFTYPE_STATION:
 	case NL80211_IFTYPE_MONITOR:
 	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_BLUETOOTH_SOFTAMP:
 		/* no special treatment */
 		break;
 	case NL80211_IFTYPE_UNSPECIFIED:
@@ -898,6 +900,9 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
 	case NL80211_IFTYPE_WDS:
 	case NL80211_IFTYPE_AP_VLAN:
 		break;
+	case NL80211_IFTYPE_BLUETOOTH_SOFTAMP:
+		ieee80211_vamp_setup_sdata(sdata);
+		break;
 	case NL80211_IFTYPE_UNSPECIFIED:
 	case NUM_NL80211_IFTYPES:
 		BUG();
@@ -914,6 +919,10 @@ static void ieee80211_clean_sdata(struct ieee80211_sub_if_data *sdata)
 		mesh_path_flush_by_iface(sdata);
 		break;
 
+	case NL80211_IFTYPE_BLUETOOTH_SOFTAMP:
+		ieee80211_vamp_clean_sdata(sdata);
+		break;
+
 	default:
 		break;
 	}
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 32f7a3b..8b7b40a 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1290,6 +1290,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 			ieee80211_bss_info_change_notify(sdata, changed);
 			break;
 		case NL80211_IFTYPE_WDS:
+		case NL80211_IFTYPE_BLUETOOTH_SOFTAMP:
 			break;
 		case NL80211_IFTYPE_AP_VLAN:
 		case NL80211_IFTYPE_MONITOR:
diff --git a/net/mac80211/virtual_amp.c b/net/mac80211/virtual_amp.c
new file mode 100644
index 0000000..3c81fda
--- /dev/null
+++ b/net/mac80211/virtual_amp.c
@@ -0,0 +1,341 @@
+/*
+ * Virtual/Software AMP 80211 BT Controller. AMP is Alternate MAC/PHYs
+ * Controller for Bluetooth subsystem. When an AMP is common between the
+ * two devices, the Bluetooth system provides mechanisms for moving data
+ * traffic from BR/EDR Controller to an AMP Controller.
+ *
+ * Copyright 2012 Intel Corp.
+ *
+ * Written by andrei.emeltchenko@intel.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.
+ */
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/l2cap.h>
+#include "virtual_amp.h"
+
+static int vamp_open_dev(struct hci_dev *hdev)
+{
+	BT_DBG("%s", hdev->name);
+
+	set_bit(HCI_RUNNING, &hdev->flags);
+
+	return 0;
+}
+
+static int vamp_close_dev(struct hci_dev *hdev)
+{
+	struct vamp_data *data = hci_get_drvdata(hdev);
+
+	BT_DBG("%s", hdev->name);
+
+	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
+		return 0;
+
+	skb_queue_purge(&data->txq);
+
+	return 0;
+}
+
+static int vamp_send_frame(struct sk_buff *skb)
+{
+	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
+	struct vamp_data *data;
+
+	BT_DBG("%s", hdev->name);
+
+	if (!hdev) {
+		BT_ERR("Frame for unknown HCI device (hdev=NULL)");
+		return -ENODEV;
+	}
+
+	if (!test_bit(HCI_RUNNING, &hdev->flags))
+		return -EBUSY;
+
+	data = hci_get_drvdata(hdev);
+
+	skb_queue_tail(&data->txq, skb);
+
+	schedule_work(&data->work);
+
+	return 0;
+}
+
+static int vamp_flush(struct hci_dev *hdev)
+{
+	struct vamp_data *data = hci_get_drvdata(hdev);
+
+	BT_DBG("%s", hdev->name);
+
+	skb_queue_purge(&data->txq);
+
+	return 0;
+}
+
+static struct sk_buff *__hci_alloc_evt(size_t plen, __u8 evt_type)
+{
+	size_t len = HCI_EVENT_HDR_SIZE + plen;
+	struct hci_event_hdr *hdr;
+	struct sk_buff *skb;
+
+	skb = bt_skb_alloc(len, GFP_KERNEL);
+	if (!skb) {
+		BT_ERR("No memory for HCI event");
+		return NULL;
+	}
+
+	hdr = (struct hci_event_hdr *) skb_put(skb, HCI_EVENT_HDR_SIZE);
+	hdr->evt = evt_type;
+	hdr->plen = plen;
+
+	return skb;
+}
+
+static int hci_send_evt_cmplt(struct hci_dev *hdev, __u16 opcode, __u32 plen,
+			      void *param)
+{
+	struct hci_ev_cmd_complete *hdr_cmplt;
+	struct sk_buff *skb;
+
+	skb = __hci_alloc_evt(plen + sizeof(*hdr_cmplt), HCI_EV_CMD_COMPLETE);
+	if (!skb)
+		return -ENOMEM;
+
+	hdr_cmplt = (struct hci_ev_cmd_complete *) skb_put(skb,
+							   sizeof(*hdr_cmplt));
+	hdr_cmplt->ncmd = 1;
+	hdr_cmplt->opcode = cpu_to_le16(opcode);
+
+	if (plen)
+		memcpy(skb_put(skb, plen), param, plen);
+
+	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
+	skb->dev = (void *) hdev;
+
+	return hci_recv_frame(skb);
+}
+
+/* Process HCI command packets */
+static void vamp_cmd_read_bd_addr(struct vamp_data *data, struct sk_buff *skb)
+{
+	struct hci_rp_read_bd_addr rp;
+	struct hci_dev *hdev = data->hdev;
+	struct ieee80211_sub_if_data *sdata = data->sdata;
+
+	rp.status = 0;
+
+	/* Use vif address as BT address */
+	baswap(&rp.bdaddr, (bdaddr_t *) sdata->vif.addr);
+
+	BT_DBG("Read BDADDR %pM", sdata->vif.addr);
+
+	hci_send_evt_cmplt(hdev, HCI_OP_READ_BD_ADDR, sizeof(rp), &rp);
+}
+
+static void vamp_cmd_read_local_version(struct vamp_data *data,
+					struct sk_buff *skb)
+{
+	struct hci_rp_read_local_version rp;
+	struct hci_dev *hdev = data->hdev;
+
+	BT_DBG("%s", hdev->name);
+
+	rp.status = 0x00;
+
+	rp.hci_ver = 0x06;
+	rp.hci_rev = cpu_to_le16(0x0000);
+	rp.lmp_ver = 0x06;
+
+	/* Not Assigned */
+	rp.manufacturer = cpu_to_le16(0xffff);
+	rp.lmp_subver = cpu_to_le16(0x0000);
+
+	hci_send_evt_cmplt(hdev, HCI_OP_READ_LOCAL_VERSION, sizeof(rp), &rp);
+}
+
+static void vamp_cmd_read_local_amp_info(struct vamp_data *data,
+					 struct sk_buff *skb)
+{
+	struct hci_dev *hdev = data->hdev;
+	struct hci_rp_read_local_amp_info rp;
+
+	memset(&rp, 0, sizeof(rp));
+
+	rp.status = 0x00;
+
+	/* BT only */
+	rp.amp_status = 0x01;
+	rp.max_pdu = cpu_to_le32(L2CAP_DEFAULT_MTU);
+	rp.amp_type = HCI_AMP;
+	rp.max_assoc_size = cpu_to_le16(HCI_MAX_ACL_SIZE);
+	/* No flushing at all */
+	rp.max_flush_to = cpu_to_le32(0xFFFFFFFF);
+	rp.be_flush_to = cpu_to_le32(0xFFFFFFFF);
+
+	hci_send_evt_cmplt(hdev, HCI_OP_READ_LOCAL_AMP_INFO, sizeof(rp), &rp);
+}
+
+static void vamp_cmd_reset(struct vamp_data *data, struct sk_buff *skb)
+{
+	struct hci_dev *hdev = data->hdev;
+	u8 status;
+
+	BT_DBG("Reset %s", hdev->name);
+
+	hci_send_evt_cmplt(hdev, HCI_OP_RESET, sizeof(status), &status);
+}
+
+static void vamp_command_packet(struct vamp_data *data, struct sk_buff *skb)
+{
+	struct hci_command_hdr *hdr = (void *) skb->data;
+	__u16 opcode = le16_to_cpu(hdr->opcode);
+
+	/* Check packet size */
+	if (skb->len < sizeof(*hdr) || skb->len != hdr->plen + sizeof(*hdr))
+		goto drop;
+
+	BT_DBG("%s opcode 0x%x", data->hdev->name, opcode);
+
+	skb_pull(skb, HCI_COMMAND_HDR_SIZE);
+
+	switch (opcode) {
+	case HCI_OP_READ_BD_ADDR:
+		vamp_cmd_read_bd_addr(data, skb);
+		break;
+
+	case HCI_OP_READ_LOCAL_VERSION:
+		vamp_cmd_read_local_version(data, skb);
+		break;
+
+	case HCI_OP_READ_LOCAL_AMP_INFO:
+		vamp_cmd_read_local_amp_info(data, skb);
+		break;
+
+	case HCI_OP_RESET:
+		vamp_cmd_reset(data, skb);
+		break;
+
+	default:
+		break;
+	}
+
+drop:
+	kfree_skb(skb);
+}
+
+static void vamp_acldata_packet(struct vamp_data *data, struct sk_buff *skb)
+{
+	struct hci_acl_hdr *hdr = (void *) skb->data;
+	__u16 handle, flags;
+
+	if (skb->len < sizeof(*hdr))
+		goto drop;
+
+	skb_pull(skb, HCI_ACL_HDR_SIZE);
+
+	handle = __le16_to_cpu(hdr->handle);
+	flags  = hci_flags(handle);
+	handle = hci_handle(handle);
+
+	BT_DBG("%s len %d handle 0x%x flags 0x%x", data->hdev->name, skb->len,
+	       handle, flags);
+
+	/* Send data through WIFI */
+
+drop:
+	kfree_skb(skb);
+}
+
+static void vamp_work(struct work_struct *work)
+{
+	struct vamp_data *data = container_of(work, struct vamp_data, work);
+	struct sk_buff *skb;
+
+	BT_DBG("%s", data->hdev->name);
+
+	while ((skb = skb_dequeue(&data->txq))) {
+		/* Process frame */
+		switch (bt_cb(skb)->pkt_type) {
+		case HCI_COMMAND_PKT:
+			vamp_command_packet(data, skb);
+			break;
+
+		case HCI_ACLDATA_PKT:
+			vamp_acldata_packet(data, skb);
+			break;
+
+		default:
+			BT_ERR("Unknown frame type %d", bt_cb(skb)->pkt_type);
+			kfree_skb(skb);
+			break;
+		}
+
+	}
+}
+
+static int virtual_amp_init(struct ieee80211_sub_if_data *sdata)
+{
+	struct hci_dev *hdev;
+	struct vamp_data *data;
+
+	data = kzalloc(sizeof(struct vamp_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	hdev = hci_alloc_dev();
+	if (!hdev) {
+		kfree(data);
+		return -ENOMEM;
+	}
+
+	skb_queue_head_init(&data->txq);
+
+	INIT_WORK(&data->work, vamp_work);
+
+	data->hdev = hdev;
+	data->sdata = sdata;
+
+	hdev->bus = HCI_VIRTUAL;
+	hci_set_drvdata(hdev, data);
+
+	hdev->dev_type = HCI_AMP;
+
+	hdev->open     = vamp_open_dev;
+	hdev->close    = vamp_close_dev;
+	hdev->flush    = vamp_flush;
+	hdev->send     = vamp_send_frame;
+
+	if (hci_register_dev(hdev) < 0) {
+		BT_ERR("Can't register HCI device");
+		kfree(data);
+		hci_free_dev(hdev);
+		return -EBUSY;
+	}
+
+	sdata->u.softamp.hdev = hdev;
+
+	return 0;
+}
+
+void ieee80211_vamp_setup_sdata(struct ieee80211_sub_if_data *sdata)
+{
+	virtual_amp_init(sdata);
+
+	pr_info("Created virtual AMP device %s", sdata->u.softamp.hdev->name);
+}
+
+void ieee80211_vamp_clean_sdata(struct ieee80211_sub_if_data *sdata)
+{
+	struct hci_dev *hdev = sdata->u.softamp.hdev;
+	struct vamp_data *data = hci_get_drvdata(hdev);
+
+	pr_info("Clean up virtual AMP device %s", hdev->name);
+
+	hci_unregister_dev(hdev);
+	hci_free_dev(hdev);
+	kfree(data);
+}
diff --git a/net/mac80211/virtual_amp.h b/net/mac80211/virtual_amp.h
new file mode 100644
index 0000000..e45f58b
--- /dev/null
+++ b/net/mac80211/virtual_amp.h
@@ -0,0 +1,37 @@
+/*
+ * Virtual / Software AMP 80211 BT Controller header
+ *
+ * Copyright 2012 Intel Corp.
+ *
+ * Written by andrei.emeltchenko@intel.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.
+ */
+
+#include "ieee80211_i.h"
+
+#ifdef CONFIG_MAC80211_BLUETOOTH_SOFTAMP
+
+void ieee80211_vamp_setup_sdata(struct ieee80211_sub_if_data *sdata);
+void ieee80211_vamp_clean_sdata(struct ieee80211_sub_if_data *sdata);
+
+struct vamp_data {
+	struct hci_dev *hdev;
+	struct ieee80211_sub_if_data *sdata;
+	unsigned long flags;
+
+	struct work_struct work;
+	struct sk_buff_head txq;
+};
+
+#else /* CONFIG_MAC80211_BLUETOOTH_SOFTAMP */
+
+static inline void
+ieee80211_vamp_setup_sdata(struct ieee80211_sub_if_data *sdata) {}
+
+static inline void
+ieee80211_vamp_clean_sdata(struct ieee80211_sub_if_data *sdata) {}
+
+#endif /* CONFIG_MAC80211_BLUETOOTH_SOFTAMP */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [RFCv2 2/6] mac80211: softamp: Adds build config option
  2012-04-24 13:17 [RFCv2 0/6] Draft Software/Virtual AMP80211 Andrei Emeltchenko
  2012-04-24 13:17 ` [RFCv2 1/6] mac80211: softamp: Adds Bluetooth Software AMP Andrei Emeltchenko
@ 2012-04-24 13:17 ` Andrei Emeltchenko
  2012-04-24 13:17 ` [RFCv2 3/6] hwsim: Adds support for BT SOFTAMP for testing Andrei Emeltchenko
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Andrei Emeltchenko @ 2012-04-24 13:17 UTC (permalink / raw)
  To: linux-bluetooth, linux-wireless

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>


Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 net/mac80211/Kconfig  |    9 +++++++++
 net/mac80211/Makefile |    2 ++
 2 files changed, 11 insertions(+)

diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 96ddb72..661b679 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -67,6 +67,15 @@ config MAC80211_RC_DEFAULT_MINSTREL
 
 endchoice
 
+config MAC80211_BLUETOOTH_SOFTAMP
+	bool "Bluetooth Soft AMP80211 device"
+	depends on BT
+	---help---
+	  Enable Bluetooth Virtual / Software AMP 80211 controller.
+	  When AMP is common between two devices data may be routed
+	  through fast 80211 connection from standard Bluetooth BR/EDR
+	  connection.
+
 config MAC80211_RC_DEFAULT
 	string
 	default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL && MAC80211_RC_MINSTREL_HT
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index 1be7a45..ff0131e 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -40,6 +40,8 @@ mac80211-$(CONFIG_MAC80211_MESH) += \
 	mesh_plink.o \
 	mesh_hwmp.o
 
+mac80211-$(CONFIG_MAC80211_BLUETOOTH_SOFTAMP) += virtual_amp.o
+
 mac80211-$(CONFIG_PM) += pm.o
 
 CFLAGS_driver-trace.o := -I$(src)
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [RFCv2 3/6] hwsim: Adds support for BT SOFTAMP for testing
  2012-04-24 13:17 [RFCv2 0/6] Draft Software/Virtual AMP80211 Andrei Emeltchenko
  2012-04-24 13:17 ` [RFCv2 1/6] mac80211: softamp: Adds Bluetooth Software AMP Andrei Emeltchenko
  2012-04-24 13:17 ` [RFCv2 2/6] mac80211: softamp: Adds build config option Andrei Emeltchenko
@ 2012-04-24 13:17 ` Andrei Emeltchenko
  2012-04-24 13:17 ` [RFCv2 4/6] mac80211: softamp: Handle assoc request Andrei Emeltchenko
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Andrei Emeltchenko @ 2012-04-24 13:17 UTC (permalink / raw)
  To: linux-bluetooth, linux-wireless

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>


Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 drivers/net/wireless/mac80211_hwsim.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index b7ce6a6..bff3699 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -1783,7 +1783,8 @@ static int __init init_mac80211_hwsim(void)
 			BIT(NL80211_IFTYPE_P2P_CLIENT) |
 			BIT(NL80211_IFTYPE_P2P_GO) |
 			BIT(NL80211_IFTYPE_ADHOC) |
-			BIT(NL80211_IFTYPE_MESH_POINT);
+			BIT(NL80211_IFTYPE_MESH_POINT) |
+			BIT(NL80211_IFTYPE_BLUETOOTH_SOFTAMP);
 
 		hw->flags = IEEE80211_HW_MFP_CAPABLE |
 			    IEEE80211_HW_SIGNAL_DBM |
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [RFCv2 4/6] mac80211: softamp: Handle assoc request
  2012-04-24 13:17 [RFCv2 0/6] Draft Software/Virtual AMP80211 Andrei Emeltchenko
                   ` (2 preceding siblings ...)
  2012-04-24 13:17 ` [RFCv2 3/6] hwsim: Adds support for BT SOFTAMP for testing Andrei Emeltchenko
@ 2012-04-24 13:17 ` Andrei Emeltchenko
  2012-05-07 11:42   ` Johannes Berg
  2012-04-24 13:17 ` [RFCv2 5/6] mac80211: softamp: Netlink interface to softamp Andrei Emeltchenko
  2012-04-24 13:17 ` [RFCv2 6/6] mac80211: softamp: Handle data traffic Andrei Emeltchenko
  5 siblings, 1 reply; 12+ messages in thread
From: Andrei Emeltchenko @ 2012-04-24 13:17 UTC (permalink / raw)
  To: linux-bluetooth, linux-wireless

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Handle AMP assoc request.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 net/mac80211/virtual_amp.c |  138 ++++++++++++++++++++++++++++++++++++++++++++
 net/mac80211/virtual_amp.h |   20 +++++++
 2 files changed, 158 insertions(+)

diff --git a/net/mac80211/virtual_amp.c b/net/mac80211/virtual_amp.c
index 3c81fda..19e5530 100644
--- a/net/mac80211/virtual_amp.c
+++ b/net/mac80211/virtual_amp.c
@@ -179,6 +179,140 @@ static void vamp_cmd_read_local_amp_info(struct vamp_data *data,
 	hci_send_evt_cmplt(hdev, HCI_OP_READ_LOCAL_AMP_INFO, sizeof(rp), &rp);
 }
 
+/* Add Type-Length-Value to buffer */
+static u16 tlv_add(u8 *msg, u8 type, u16 len, u8 *val)
+{
+	struct tlv *tlvmsg = (struct tlv *) msg;
+
+	tlvmsg->type = type;
+	tlvmsg->len = cpu_to_le16(len);
+
+	memcpy(tlvmsg->val, val, len);
+
+	return len + sizeof(*tlvmsg);
+}
+
+static void vamp_cmd_read_local_amp_assoc(struct vamp_data *data,
+					  struct sk_buff *skb)
+{
+	struct hci_dev *hdev = data->hdev;
+	struct ieee80211_sub_if_data *sdata = data->sdata;
+	struct hci_cp_read_local_amp_assoc *cp = (void *) skb->data;
+	struct hci_rp_read_local_amp_assoc *rp;
+	struct softamp_pref_chans pref_chans = {
+		.country_code = { 'X', 'X', 'X' }
+	};
+	enum ieee80211_band band;
+	int buf_len = 0, triplet_size;
+	u8 num_triplet = 0;
+
+	char buf[670];
+	char mac[ETH_ALEN];
+
+	char pal_cap[] = { 0x00, 0x00, 0x00, 0x00 };
+	char pal_ver[] = {
+		0x01 /*PAL version*/,
+		0x00, 0x01 /* PAL company ID*/,
+		0x00, 0x01 /* PAL sub version */
+	};
+
+	BT_DBG("%s", hdev->name);
+
+	memcpy(mac, sdata->vif.addr, ETH_ALEN);
+
+	/* Add wireless MAC address */
+	buf_len += tlv_add(buf, SOFTAMP_MAC_ADDR_TYPE, sizeof(mac), mac);
+
+	/* Add PAL capacities */
+	buf_len += tlv_add(buf + buf_len, SOFTAMP_PAL_CAP_TYPE,
+			   sizeof(pal_cap), pal_cap);
+
+	/* Add PAL version info */
+	buf_len += tlv_add(buf + buf_len, SOFTAMP_PAL_VER_INFO,
+			   sizeof(pal_ver), pal_ver);
+
+	/* Add Preffered Channel list */
+	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+		struct ieee80211_supported_band *sband;
+		struct ieee80211_country_ie_triplet *t;
+		u8 flag = 0, first_chan = 0, prev_chan = 0, max_power = 0;
+		u8 j, chan_num = 0, num_parsed_chans = 0;
+
+		sband = sdata->wdev.wiphy->bands[band];
+
+		for (j = 0; j < sband->n_channels; j++) {
+			struct ieee80211_channel *ch = &sband->channels[j];
+
+			if (ch->flags & IEEE80211_CHAN_DISABLED)
+				continue;
+
+			chan_num = ieee80211_frequency_to_channel(
+					ch->center_freq);
+
+			if (!flag) {
+				/* First channel in a range */
+				flag = 1;
+				first_chan = chan_num;
+				prev_chan = first_chan;
+				max_power = ch->max_power;
+				num_parsed_chans = 1;
+
+				continue;
+			}
+
+			if (chan_num == prev_chan + 1 &&
+			    ch->max_power == max_power) {
+				prev_chan++;
+				num_parsed_chans++;
+			} else {
+				/* Add channel previous triplet*/
+				t = &pref_chans.triplets[num_triplet];
+
+				t->chans.first_channel = first_chan;
+				t->chans.num_channels = num_parsed_chans;
+				t->chans.max_power = max_power;
+				num_triplet++;
+
+				first_chan = chan_num;
+				prev_chan = first_chan;
+				max_power = ch->max_power;
+				num_parsed_chans = 1;
+			}
+		}
+
+		/* Add whole range */
+		if (flag && num_parsed_chans != 1) {
+			t = &pref_chans.triplets[num_triplet];
+
+			t->chans.first_channel = first_chan;
+			t->chans.num_channels = num_parsed_chans;
+			t->chans.max_power = max_power;
+			num_triplet++;
+		}
+	}
+
+	triplet_size = num_triplet *
+		sizeof(struct ieee80211_country_ie_triplet) +
+		IEEE80211_COUNTRY_STRING_LEN;
+
+	buf_len += tlv_add(buf + buf_len, SOFTAMP_PREF_CHANLIST_TYPE,
+			   triplet_size, (u8 *) &pref_chans);
+
+	rp = kzalloc(sizeof(*rp) + buf_len, GFP_KERNEL);
+	if (!rp)
+		return;
+
+	rp->status = 0;
+	rp->handle = cp->handle;
+	rp->rem_len = cpu_to_le16(buf_len);
+
+	memcpy(rp->frag, buf, buf_len);
+	hci_send_evt_cmplt(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC,
+			   buf_len + sizeof(*rp), rp);
+
+	kfree(rp);
+}
+
 static void vamp_cmd_reset(struct vamp_data *data, struct sk_buff *skb)
 {
 	struct hci_dev *hdev = data->hdev;
@@ -215,6 +349,10 @@ static void vamp_command_packet(struct vamp_data *data, struct sk_buff *skb)
 		vamp_cmd_read_local_amp_info(data, skb);
 		break;
 
+	case HCI_OP_READ_LOCAL_AMP_ASSOC:
+		vamp_cmd_read_local_amp_assoc(data, skb);
+		break;
+
 	case HCI_OP_RESET:
 		vamp_cmd_reset(data, skb);
 		break;
diff --git a/net/mac80211/virtual_amp.h b/net/mac80211/virtual_amp.h
index e45f58b..3717530 100644
--- a/net/mac80211/virtual_amp.h
+++ b/net/mac80211/virtual_amp.h
@@ -14,6 +14,26 @@
 
 #ifdef CONFIG_MAC80211_BLUETOOTH_SOFTAMP
 
+#define SOFTAMP_MAC_ADDR_TYPE		1
+#define SOFTAMP_PREF_CHANLIST_TYPE	2
+#define SOFTAMP_CONNECTED_CHAN		3
+#define SOFTAMP_PAL_CAP_TYPE		4
+#define SOFTAMP_PAL_VER_INFO		5
+
+/* Data types related to ASSOC data */
+struct tlv {
+	__u8 type;
+	__u16 len;
+	__u8 val[0];
+} __packed;
+
+#define MAX_11D_TRIPLETS        83
+
+struct softamp_pref_chans {
+	__u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
+	struct ieee80211_country_ie_triplet triplets[MAX_11D_TRIPLETS];
+} __packed;
+
 void ieee80211_vamp_setup_sdata(struct ieee80211_sub_if_data *sdata);
 void ieee80211_vamp_clean_sdata(struct ieee80211_sub_if_data *sdata);
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [RFCv2 5/6] mac80211: softamp: Netlink interface to softamp
  2012-04-24 13:17 [RFCv2 0/6] Draft Software/Virtual AMP80211 Andrei Emeltchenko
                   ` (3 preceding siblings ...)
  2012-04-24 13:17 ` [RFCv2 4/6] mac80211: softamp: Handle assoc request Andrei Emeltchenko
@ 2012-04-24 13:17 ` Andrei Emeltchenko
  2012-05-07 11:42   ` Johannes Berg
  2012-04-24 13:17 ` [RFCv2 6/6] mac80211: softamp: Handle data traffic Andrei Emeltchenko
  5 siblings, 1 reply; 12+ messages in thread
From: Andrei Emeltchenko @ 2012-04-24 13:17 UTC (permalink / raw)
  To: linux-bluetooth, linux-wireless

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Adds basic netlink interface. Those packets which are not handled in
softamp will be sent via netlink for processing in user space.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 net/mac80211/virtual_amp.c |   67 ++++++++++++++++++++++++++++++++++++++++++++
 net/mac80211/virtual_amp.h |   20 +++++++++++++
 2 files changed, 87 insertions(+)

diff --git a/net/mac80211/virtual_amp.c b/net/mac80211/virtual_amp.c
index 19e5530..62ebb50 100644
--- a/net/mac80211/virtual_amp.c
+++ b/net/mac80211/virtual_amp.c
@@ -323,6 +323,72 @@ static void vamp_cmd_reset(struct vamp_data *data, struct sk_buff *skb)
 	hci_send_evt_cmplt(hdev, HCI_OP_RESET, sizeof(status), &status);
 }
 
+static struct nla_policy softamp_policy[__NL80211_CMD_SOFTAMP_LAST] = {
+	[NL80211_CMD_SOFTAMP_HCI_EVENT] = { .type = NLA_BINARY,
+					    .len = IEEE80211_MAX_DATA_LEN },
+};
+
+static int softamp_hci_event_nl(struct sk_buff *skb, struct genl_info *info)
+{
+	const u8 *frame;
+	size_t frame_len;
+
+	if (!info->attrs[NL80211_ATTR_FRAME])
+		return -EINVAL;
+
+	frame = nla_data(info->attrs[NL80211_ATTR_FRAME]);
+	frame_len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
+
+	/* Handle NL event */
+
+	return 0;
+}
+
+/* Generic Netlink operations array */
+static struct genl_ops softamp_ops[] = {
+	{
+		.cmd = NL80211_CMD_SOFTAMP_HCI_EVENT,
+		.policy = softamp_policy,
+		.doit = softamp_hci_event_nl,
+		.flags = GENL_ADMIN_PERM,
+	},
+};
+
+void softamp_hci_cmd_nl(struct vamp_data *data, struct sk_buff *skb)
+{
+	struct cfg80211_registered_device *rdev;
+	struct hci_dev *hdev = data->hdev;
+	struct sk_buff *msg;
+	void *hdr;
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg)
+		return;
+
+	hdr = genlmsg_put(msg, 0, 0, &softamp_fam, 0,
+			  NL80211_CMD_SOFTAMP_HCI_EVENT);
+	if (!hdr) {
+		nlmsg_free(msg);
+		return;
+	}
+
+	rdev = wiphy_to_dev(data->sdata->wdev.wiphy);
+
+	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+	NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, (unsigned long) hdev->id);
+	NLA_PUT(msg, NL80211_ATTR_FRAME, skb->len, skb->data);
+
+	if (genlmsg_end(msg, hdr) < 0) {
+		nlmsg_free(msg);
+		return;
+	}
+
+	genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, data->nlpid);
+
+nla_put_failure:
+	BT_ERR("%s", hdev->name);
+}
+
 static void vamp_command_packet(struct vamp_data *data, struct sk_buff *skb)
 {
 	struct hci_command_hdr *hdr = (void *) skb->data;
@@ -358,6 +424,7 @@ static void vamp_command_packet(struct vamp_data *data, struct sk_buff *skb)
 		break;
 
 	default:
+		softamp_hci_cmd_nl(data, skb);
 		break;
 	}
 
diff --git a/net/mac80211/virtual_amp.h b/net/mac80211/virtual_amp.h
index 3717530..a353ac3 100644
--- a/net/mac80211/virtual_amp.h
+++ b/net/mac80211/virtual_amp.h
@@ -10,7 +10,11 @@
  * published by the Free Software Foundation.
  */
 
+#include <net/cfg80211.h>
+#include <net/mac80211.h>
+
 #include "ieee80211_i.h"
+#include "../wireless/core.h"
 
 #ifdef CONFIG_MAC80211_BLUETOOTH_SOFTAMP
 
@@ -41,11 +45,27 @@ struct vamp_data {
 	struct hci_dev *hdev;
 	struct ieee80211_sub_if_data *sdata;
 	unsigned long flags;
+	__u32 nlpid;
 
 	struct work_struct work;
 	struct sk_buff_head txq;
 };
 
+/* Netlink */
+enum {
+	NL80211_CMD_SOFTAMP_HCI_EVENT,
+	__NL80211_CMD_SOFTAMP_LAST,
+};
+
+/* Soft AMP netlinf family */
+static struct genl_family softamp_fam = {
+	.id = GENL_ID_GENERATE,
+	.hdrsize = 0,
+	.name = "Soft AMP",
+	.version = 1,
+	.maxattr = __NL80211_CMD_SOFTAMP_LAST,
+};
+
 #else /* CONFIG_MAC80211_BLUETOOTH_SOFTAMP */
 
 static inline void
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [RFCv2 6/6] mac80211: softamp: Handle data traffic
  2012-04-24 13:17 [RFCv2 0/6] Draft Software/Virtual AMP80211 Andrei Emeltchenko
                   ` (4 preceding siblings ...)
  2012-04-24 13:17 ` [RFCv2 5/6] mac80211: softamp: Netlink interface to softamp Andrei Emeltchenko
@ 2012-04-24 13:17 ` Andrei Emeltchenko
  5 siblings, 0 replies; 12+ messages in thread
From: Andrei Emeltchenko @ 2012-04-24 13:17 UTC (permalink / raw)
  To: linux-bluetooth, linux-wireless

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Adds handling for data traffic. The patch is partly based on patch:
"mac80211: BT3 AMP support".

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
 include/linux/ieee80211.h  |   13 +++++
 net/mac80211/rx.c          |    4 ++
 net/mac80211/sta_info.h    |    4 ++
 net/mac80211/virtual_amp.c |  131 +++++++++++++++++++++++++++++++++++++++++++-
 net/mac80211/virtual_amp.h |   19 +++++++
 5 files changed, 170 insertions(+), 1 deletion(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 210e2c3..f19728e 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -184,6 +184,19 @@ struct ieee80211_qos_hdr {
 	__le16 qos_ctrl;
 } __attribute__ ((packed));
 
+#define P80211_OUI_LEN 3
+
+struct ieee80211_llc_snap_hdr {
+	/* LLC */
+	u8 dsap;   /* always 0xAA */
+	u8 ssap;   /* always 0xAA */
+	u8 ctrl;   /* always 0x03 */
+
+	/* SNAP */
+	u8 oui[P80211_OUI_LEN];    /* organizational universal id */
+	__be16 proto;
+} __attribute__ ((packed));
+
 /**
  * ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set
  * @fc: frame control bytes in little-endian byteorder
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index bcfe8c7..760d20c 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -30,6 +30,7 @@
 #include "tkip.h"
 #include "wme.h"
 #include "rate.h"
+#include "virtual_amp.h"
 
 /*
  * monitor mode reception
@@ -1767,6 +1768,9 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
 				skb = NULL;
 			}
 		}
+	} else if (ieee80211_vif_is_softamp(&sdata->vif)) {
+		ieee80211_softamp_receive_skb(sdata, rx->skb, rx->sta);
+		return;
 	}
 
 	if (skb) {
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index ab05768..47ed9f0 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -362,6 +362,10 @@ struct sta_info {
 	} debugfs;
 #endif
 
+#ifdef CONFIG_MAC80211_BLUETOOTH_SOFTAMP
+	u16 hci_handle;
+#endif
+
 	unsigned int lost_packets;
 	unsigned int beacon_loss_count;
 
diff --git a/net/mac80211/virtual_amp.c b/net/mac80211/virtual_amp.c
index 62ebb50..6d2ffef 100644
--- a/net/mac80211/virtual_amp.c
+++ b/net/mac80211/virtual_amp.c
@@ -432,14 +432,137 @@ drop:
 	kfree_skb(skb);
 }
 
+void ieee80211_softamp_receive_skb(struct ieee80211_sub_if_data *sdata,
+				   struct sk_buff *skb, struct sta_info *sta)
+{
+	struct ethhdr *hdr = (void *) skb->data;
+	struct ieee80211_llc_snap_hdr *snap_hdr;
+	struct hci_acl_hdr *acl_hdr;
+	int min_hdr = sizeof(*hdr) + sizeof(*snap_hdr);
+	u16 proto;
+
+	if (!sta)
+		goto drop;
+
+	if (skb->len < min_hdr)
+		goto drop;
+
+	if (compare_ether_addr(sta->sta.addr, hdr->h_source) ||
+	    compare_ether_addr(sdata->vif.addr, hdr->h_dest))
+		goto drop;
+
+	skb_pull(skb, sizeof(*hdr));
+
+	snap_hdr = (void *) skb->data;
+	if (snap_hdr->dsap != 0xAA || snap_hdr->ssap != 0xAA ||
+	     snap_hdr->ctrl != 0x03 || snap_hdr->oui[0] != 0x00 ||
+	     snap_hdr->oui[1] != 0x19 || snap_hdr->oui[2] != 0x58)
+		goto drop;
+
+	skb_pull(skb, sizeof(*snap_hdr));
+
+	proto = ntohs(snap_hdr->proto);
+	switch (proto) {
+	case SOFTAMP_ACL_DATA:
+		acl_hdr = (void *) skb_push(skb, sizeof(*acl_hdr));
+		acl_hdr->handle = 0;
+		acl_hdr->dlen = cpu_to_le16(skb->len - sizeof(*acl_hdr));
+		memset(skb->cb, 0, sizeof(skb->cb));
+		bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
+		skb->dev = (void *)sdata->u.softamp.hdev;
+		hci_recv_frame(skb);
+		break;
+	}
+
+drop:
+	kfree_skb(skb);
+}
+
+static struct sta_info *find_sta_for_hndl(struct ieee80211_sub_if_data *sdata,
+					  u16 handle)
+{
+	struct sta_info *sta;
+
+	list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
+		if (sta->sdata != sdata)
+			continue;
+		if (sta->hci_handle == handle)
+			return sta;
+	}
+
+	return NULL;
+}
+
+static void softamp_xmit_sta(struct ieee80211_sub_if_data *sdata,
+			     struct sk_buff *skb, struct sta_info *sta,
+			     u16 proto)
+{
+	struct ieee80211_tx_info *info;
+	struct ieee80211_hdr *hdr;
+	struct ieee80211_llc_snap_hdr *snap_hdr;
+	struct sk_buff *nskb;
+	u16 fc;
+	__le16 *qos;
+
+	fc = IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS |
+	     IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
+
+	nskb = skb_copy_expand(skb, sizeof(*hdr) + sizeof(*snap_hdr) +
+			       sizeof(*qos), 0, GFP_ATOMIC);
+	kfree_skb(skb);
+
+	if (!nskb)
+		return;
+
+	skb = nskb;
+
+	snap_hdr = (void *) skb_push(skb, sizeof(*snap_hdr));
+
+	/* 802.11 AMP LLC/SNAP encapsulation. All fields except proto
+	   are hardcoded in Bluetooth Core Specification v4.0 */
+	snap_hdr->dsap = 0xAA;
+	snap_hdr->ssap = 0xAA;
+	snap_hdr->ctrl = 0x03;
+	snap_hdr->oui[0] = 0x00;
+	snap_hdr->oui[1] = 0x19;
+	snap_hdr->oui[2] = 0x58;
+
+	/* Apparently this is __be */
+	snap_hdr->proto = htons(proto);
+
+	/* QoS */
+	if (test_sta_flag(sta, WLAN_STA_WME) && sdata->local->hw.queues >= 4) {
+		fc |= IEEE80211_STYPE_QOS_DATA;
+		qos = (void *)skb_push(skb, sizeof(*qos));
+		*qos = 0;
+	}
+
+	hdr = (void *) skb_put(skb, sizeof(*hdr));
+	memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN);
+	memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
+	memcpy(hdr->addr3, sta->sta.addr, ETH_ALEN);
+	memcpy(hdr->addr4, sdata->vif.addr, ETH_ALEN);
+	hdr->frame_control = cpu_to_le16(fc);
+
+	info = IEEE80211_SKB_CB(skb);
+	memset(info, 0, sizeof(*info));
+
+	ieee80211_tx_skb(sdata, skb);
+}
+
 static void vamp_acldata_packet(struct vamp_data *data, struct sk_buff *skb)
 {
 	struct hci_acl_hdr *hdr = (void *) skb->data;
+	struct ieee80211_sub_if_data *sdata = data->sdata;
+	struct sta_info *sta;
 	__u16 handle, flags;
 
 	if (skb->len < sizeof(*hdr))
 		goto drop;
 
+	if (skb->len != sizeof(*hdr) + le16_to_cpu(hdr->dlen))
+		goto drop;
+
 	skb_pull(skb, HCI_ACL_HDR_SIZE);
 
 	handle = __le16_to_cpu(hdr->handle);
@@ -449,7 +572,13 @@ static void vamp_acldata_packet(struct vamp_data *data, struct sk_buff *skb)
 	BT_DBG("%s len %d handle 0x%x flags 0x%x", data->hdev->name, skb->len,
 	       handle, flags);
 
-	/* Send data through WIFI */
+	rcu_read_lock();
+
+	sta = find_sta_for_hndl(sdata, handle);
+	if (sta)
+		softamp_xmit_sta(sdata, skb, sta, 1);
+
+	rcu_read_unlock();
 
 drop:
 	kfree_skb(skb);
diff --git a/net/mac80211/virtual_amp.h b/net/mac80211/virtual_amp.h
index a353ac3..d55da78 100644
--- a/net/mac80211/virtual_amp.h
+++ b/net/mac80211/virtual_amp.h
@@ -24,6 +24,13 @@
 #define SOFTAMP_PAL_CAP_TYPE		4
 #define SOFTAMP_PAL_VER_INFO		5
 
+/* Protocol identifiers for LLC/SNAP hdr */
+#define SOFTAMP_ACL_DATA		1
+#define SOFTAMP_ACTIVITY_REPORT		2
+#define SOFTAMP_SECURITY_FRAME		3
+#define SOFTAMP_LINK_SUPERVISION_REQ	4
+#define SOFTAMP_LINK_SUPERVISION_REPLY	5
+
 /* Data types related to ASSOC data */
 struct tlv {
 	__u8 type;
@@ -40,6 +47,8 @@ struct softamp_pref_chans {
 
 void ieee80211_vamp_setup_sdata(struct ieee80211_sub_if_data *sdata);
 void ieee80211_vamp_clean_sdata(struct ieee80211_sub_if_data *sdata);
+void ieee80211_softamp_receive_skb(struct ieee80211_sub_if_data *sdata,
+				   struct sk_buff *skb, struct sta_info *sta);
 
 struct vamp_data {
 	struct hci_dev *hdev;
@@ -74,4 +83,14 @@ ieee80211_vamp_setup_sdata(struct ieee80211_sub_if_data *sdata) {}
 static inline void
 ieee80211_vamp_clean_sdata(struct ieee80211_sub_if_data *sdata) {}
 
+static inline void
+ieee80211_softamp_receive_skb(struct ieee80211_sub_if_data *sdata,
+			      struct sk_buff *skb, struct sta_info *sta)
+{}
+
 #endif /* CONFIG_MAC80211_BLUETOOTH_SOFTAMP */
+
+static inline bool ieee80211_vif_is_softamp(struct ieee80211_vif *vif)
+{
+	return vif->type == NL80211_IFTYPE_BLUETOOTH_SOFTAMP;
+}
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [RFCv2 1/6] mac80211: softamp: Adds Bluetooth Software AMP
  2012-04-24 13:17 ` [RFCv2 1/6] mac80211: softamp: Adds Bluetooth Software AMP Andrei Emeltchenko
@ 2012-05-07 11:41   ` Johannes Berg
  2012-05-07 11:56     ` Andrei Emeltchenko
  0 siblings, 1 reply; 12+ messages in thread
From: Johannes Berg @ 2012-05-07 11:41 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth, linux-wireless

On Tue, 2012-04-24 at 16:17 +0300, Andrei Emeltchenko wrote:

> --- a/include/linux/nl80211.h
> +++ b/include/linux/nl80211.h
> @@ -1546,6 +1546,7 @@ enum nl80211_iftype {
>  	NL80211_IFTYPE_MESH_POINT,
>  	NL80211_IFTYPE_P2P_CLIENT,
>  	NL80211_IFTYPE_P2P_GO,
> +	NL80211_IFTYPE_BLUETOOTH_SOFTAMP,

That should probably be a separate patch also updating cfg80211 (and
maybe mac80211) where needed (at least to suppress the warnings you
saw). Also documentation is needed.

> @@ -211,6 +212,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
>  	case NL80211_IFTYPE_STATION:
>  	case NL80211_IFTYPE_MONITOR:
>  	case NL80211_IFTYPE_ADHOC:
> +	case NL80211_IFTYPE_BLUETOOTH_SOFTAMP:
>  		/* no special treatment */
>  		break;

You should never be able to come here with this interface type -- maybe
make it a warning or something.

> +static int vamp_send_frame(struct sk_buff *skb)
> +{
> +	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
> +	struct vamp_data *data;
> +
> +	BT_DBG("%s", hdev->name);
> +
> +	if (!hdev) {
> +		BT_ERR("Frame for unknown HCI device (hdev=NULL)");
> +		return -ENODEV;
> +	}
> +
> +	if (!test_bit(HCI_RUNNING, &hdev->flags))
> +		return -EBUSY;
> +
> +	data = hci_get_drvdata(hdev);
> +
> +	skb_queue_tail(&data->txq, skb);
> +
> +	schedule_work(&data->work);

I don't understand the need for the asynchronous handling.

johannes


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFCv2 4/6] mac80211: softamp: Handle assoc request
  2012-04-24 13:17 ` [RFCv2 4/6] mac80211: softamp: Handle assoc request Andrei Emeltchenko
@ 2012-05-07 11:42   ` Johannes Berg
  0 siblings, 0 replies; 12+ messages in thread
From: Johannes Berg @ 2012-05-07 11:42 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth, linux-wireless

On Tue, 2012-04-24 at 16:17 +0300, Andrei Emeltchenko wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> 
> Handle AMP assoc request.

This needs knowledge about channel preferences etc. I think it should be
done in wpa_supplicant.

johannes


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFCv2 5/6] mac80211: softamp: Netlink interface to softamp
  2012-04-24 13:17 ` [RFCv2 5/6] mac80211: softamp: Netlink interface to softamp Andrei Emeltchenko
@ 2012-05-07 11:42   ` Johannes Berg
  0 siblings, 0 replies; 12+ messages in thread
From: Johannes Berg @ 2012-05-07 11:42 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth, linux-wireless

On Tue, 2012-04-24 at 16:17 +0300, Andrei Emeltchenko wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
> 
> Adds basic netlink interface. Those packets which are not handled in
> softamp will be sent via netlink for processing in user space.

You must be kidding -- we have nl80211.

johannes


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFCv2 1/6] mac80211: softamp: Adds Bluetooth Software AMP
  2012-05-07 11:41   ` Johannes Berg
@ 2012-05-07 11:56     ` Andrei Emeltchenko
  2012-05-07 11:59       ` Johannes Berg
  0 siblings, 1 reply; 12+ messages in thread
From: Andrei Emeltchenko @ 2012-05-07 11:56 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-bluetooth, linux-wireless

Hi Johannes,

On Mon, May 07, 2012 at 01:41:19PM +0200, Johannes Berg wrote:
> On Tue, 2012-04-24 at 16:17 +0300, Andrei Emeltchenko wrote:
> 
> > --- a/include/linux/nl80211.h
> > +++ b/include/linux/nl80211.h
> > @@ -1546,6 +1546,7 @@ enum nl80211_iftype {
> >  	NL80211_IFTYPE_MESH_POINT,
> >  	NL80211_IFTYPE_P2P_CLIENT,
> >  	NL80211_IFTYPE_P2P_GO,
> > +	NL80211_IFTYPE_BLUETOOTH_SOFTAMP,
> 
> That should probably be a separate patch also updating cfg80211 (and
> maybe mac80211) where needed (at least to suppress the warnings you
> saw). Also documentation is needed.
> 
> > @@ -211,6 +212,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
> >  	case NL80211_IFTYPE_STATION:
> >  	case NL80211_IFTYPE_MONITOR:
> >  	case NL80211_IFTYPE_ADHOC:
> > +	case NL80211_IFTYPE_BLUETOOTH_SOFTAMP:
> >  		/* no special treatment */
> >  		break;
> 
> You should never be able to come here with this interface type -- maybe
> make it a warning or something.
> 
> > +static int vamp_send_frame(struct sk_buff *skb)
> > +{
> > +	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
> > +	struct vamp_data *data;
> > +
> > +	BT_DBG("%s", hdev->name);
> > +
> > +	if (!hdev) {
> > +		BT_ERR("Frame for unknown HCI device (hdev=NULL)");
> > +		return -ENODEV;
> > +	}
> > +
> > +	if (!test_bit(HCI_RUNNING, &hdev->flags))
> > +		return -EBUSY;
> > +
> > +	data = hci_get_drvdata(hdev);
> > +
> > +	skb_queue_tail(&data->txq, skb);
> > +
> > +	schedule_work(&data->work);
> 
> I don't understand the need for the asynchronous handling.

This is standard way for hci dev. Can be changed so that skb is handled
right here.

Best regards 
Andrei Emeltchenko 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [RFCv2 1/6] mac80211: softamp: Adds Bluetooth Software AMP
  2012-05-07 11:56     ` Andrei Emeltchenko
@ 2012-05-07 11:59       ` Johannes Berg
  0 siblings, 0 replies; 12+ messages in thread
From: Johannes Berg @ 2012-05-07 11:59 UTC (permalink / raw)
  To: Andrei Emeltchenko; +Cc: linux-bluetooth, linux-wireless

On Mon, 2012-05-07 at 14:56 +0300, Andrei Emeltchenko wrote:
> Hi Johannes,
> 
> On Mon, May 07, 2012 at 01:41:19PM +0200, Johannes Berg wrote:
> > On Tue, 2012-04-24 at 16:17 +0300, Andrei Emeltchenko wrote:
> > 
> > > --- a/include/linux/nl80211.h
> > > +++ b/include/linux/nl80211.h
> > > @@ -1546,6 +1546,7 @@ enum nl80211_iftype {
> > >  	NL80211_IFTYPE_MESH_POINT,
> > >  	NL80211_IFTYPE_P2P_CLIENT,
> > >  	NL80211_IFTYPE_P2P_GO,
> > > +	NL80211_IFTYPE_BLUETOOTH_SOFTAMP,
> > 
> > That should probably be a separate patch also updating cfg80211 (and
> > maybe mac80211) where needed (at least to suppress the warnings you
> > saw). Also documentation is needed.
> > 
> > > @@ -211,6 +212,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
> > >  	case NL80211_IFTYPE_STATION:
> > >  	case NL80211_IFTYPE_MONITOR:
> > >  	case NL80211_IFTYPE_ADHOC:
> > > +	case NL80211_IFTYPE_BLUETOOTH_SOFTAMP:
> > >  		/* no special treatment */
> > >  		break;
> > 
> > You should never be able to come here with this interface type -- maybe
> > make it a warning or something.
> > 
> > > +static int vamp_send_frame(struct sk_buff *skb)
> > > +{
> > > +	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
> > > +	struct vamp_data *data;
> > > +
> > > +	BT_DBG("%s", hdev->name);
> > > +
> > > +	if (!hdev) {
> > > +		BT_ERR("Frame for unknown HCI device (hdev=NULL)");
> > > +		return -ENODEV;
> > > +	}
> > > +
> > > +	if (!test_bit(HCI_RUNNING, &hdev->flags))
> > > +		return -EBUSY;
> > > +
> > > +	data = hci_get_drvdata(hdev);
> > > +
> > > +	skb_queue_tail(&data->txq, skb);
> > > +
> > > +	schedule_work(&data->work);
> > 
> > I don't understand the need for the asynchronous handling.
> 
> This is standard way for hci dev. Can be changed so that skb is handled
> right here.

"standard" doesn't explain why it's needed though, and I don't think it
is needed here.

johannes


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2012-05-07 11:59 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-24 13:17 [RFCv2 0/6] Draft Software/Virtual AMP80211 Andrei Emeltchenko
2012-04-24 13:17 ` [RFCv2 1/6] mac80211: softamp: Adds Bluetooth Software AMP Andrei Emeltchenko
2012-05-07 11:41   ` Johannes Berg
2012-05-07 11:56     ` Andrei Emeltchenko
2012-05-07 11:59       ` Johannes Berg
2012-04-24 13:17 ` [RFCv2 2/6] mac80211: softamp: Adds build config option Andrei Emeltchenko
2012-04-24 13:17 ` [RFCv2 3/6] hwsim: Adds support for BT SOFTAMP for testing Andrei Emeltchenko
2012-04-24 13:17 ` [RFCv2 4/6] mac80211: softamp: Handle assoc request Andrei Emeltchenko
2012-05-07 11:42   ` Johannes Berg
2012-04-24 13:17 ` [RFCv2 5/6] mac80211: softamp: Netlink interface to softamp Andrei Emeltchenko
2012-05-07 11:42   ` Johannes Berg
2012-04-24 13:17 ` [RFCv2 6/6] mac80211: softamp: Handle data traffic Andrei Emeltchenko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.