linux-wireless.vger.kernel.org archive mirror
 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).