linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [Bluez-devel] RFC : H4 and BCSP proto unification
@ 2006-05-02 20:20 matthieu castet
  2006-05-29 19:05 ` matthieu castet
  2006-06-05 14:10 ` Marcel Holtmann
  0 siblings, 2 replies; 3+ messages in thread
From: matthieu castet @ 2006-05-02 20:20 UTC (permalink / raw)
  To: bluez-devel

[-- Attachment #1: Type: text/plain, Size: 536 bytes --]

Hi,

this patch is an attempt to share H4 and BCSP proto for other drivers
than hci_uart.

hci_h4.c and hci_bcsp.c where expecting a hci_uart structure, I define a
more generic one. I need to add a tx_wakeup function for BCSP.

I also added 1 operation henqueue that queue a skb in the head of the
skb list for driver that can't send all the skb data in one operation.

This is far from perfect (I don't like the hci_dev pointer duplication,
...) and untested for hci_uart driver.

Any comments will be appreciated.

Thanks,

Matthieu


[-- Attachment #2: bt_proto_stack.diff --]
[-- Type: text/plain, Size: 22701 bytes --]

diff -ur linux.old/drivers/bluetooth/Kconfig linux/drivers/bluetooth/Kconfig
--- linux.old/drivers/bluetooth/Kconfig	2006-04-22 23:28:15.000000000 +0200
+++ linux/drivers/bluetooth/Kconfig	2006-04-29 22:20:10.000000000 +0200
@@ -36,7 +36,6 @@
 
 config BT_HCIUART_H4
 	bool "UART (H4) protocol support"
-	depends on BT_HCIUART
 	help
 	  UART (H4) is serial protocol for communication between Bluetooth 
 	  device and host. This protocol is required for most Bluetooth devices 
@@ -46,7 +45,6 @@
 
 config BT_HCIUART_BCSP
 	bool "BCSP protocol support"
-	depends on BT_HCIUART
 	help
 	  BCSP (BlueCore Serial Protocol) is serial protocol for communication 
 	  between Bluetooth device and host. This protocol is required for non
@@ -134,6 +132,7 @@
 config BT_HCIBTUART
 	tristate "HCI UART (PC Card) device driver"
 	depends on PCMCIA
+	select BT_HCIUART_H4
 	help
 	  Bluetooth HCI UART (PC Card) driver.
 	  This driver provides support for Bluetooth PCMCIA devices with
diff -ur linux.old/drivers/bluetooth/Makefile linux/drivers/bluetooth/Makefile
--- linux.old/drivers/bluetooth/Makefile	2005-10-28 02:02:08.000000000 +0200
+++ linux/drivers/bluetooth/Makefile	2006-04-29 22:20:10.000000000 +0200
@@ -12,8 +12,8 @@
 obj-$(CONFIG_BT_HCIBT3C)	+= bt3c_cs.o
 obj-$(CONFIG_BT_HCIBLUECARD)	+= bluecard_cs.o
 obj-$(CONFIG_BT_HCIBTUART)	+= btuart_cs.o
+obj-$(CONFIG_BT_HCIUART_H4)	+= hci_h4.o
+obj-$(CONFIG_BT_HCIUART_BCSP)	+= hci_bcsp.o
 
 hci_uart-y				:= hci_ldisc.o
-hci_uart-$(CONFIG_BT_HCIUART_H4)	+= hci_h4.o
-hci_uart-$(CONFIG_BT_HCIUART_BCSP)	+= hci_bcsp.o
 hci_uart-objs				:= $(hci_uart-y)
diff -ur linux.old/drivers/bluetooth/btuart_cs.c linux/drivers/bluetooth/btuart_cs.c
--- linux.old/drivers/bluetooth/btuart_cs.c	2006-04-22 23:28:41.000000000 +0200
+++ linux/drivers/bluetooth/btuart_cs.c	2006-04-29 22:20:10.000000000 +0200
@@ -53,6 +53,7 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
+#include "hci_uart.h"
 
 
 /* ======================== Module parameters ======================== */
@@ -75,12 +76,9 @@
 
 	spinlock_t lock;	/* For serializing operations */
 
-	struct sk_buff_head txq;
 	unsigned long tx_state;
 
-	unsigned long rx_state;
-	unsigned long rx_count;
-	struct sk_buff *rx_skb;
+	struct hci_uart_proto proto;
 } btuart_info_t;
 
 
@@ -155,7 +153,7 @@
 		if (!(info->link.state & DEV_PRESENT))
 			return;
 
-		if (!(skb = skb_dequeue(&(info->txq))))
+		if (!(skb = info->proto.p->dequeue(&info->proto)))
 			break;
 
 		/* Send frame */
@@ -166,7 +164,7 @@
 			kfree_skb(skb);
 		} else {
 			skb_pull(skb, len);
-			skb_queue_head(&(info->txq), skb);
+			info->proto.p->henqueue(&info->proto, skb);
 		}
 
 		info->hdev->stat.byte_tx += len;
@@ -180,7 +178,8 @@
 static void btuart_receive(btuart_info_t *info)
 {
 	unsigned int iobase;
-	int boguscount = 0;
+	int len = 0;
+	char data [16];
 
 	if (!info) {
 		BT_ERR("Unknown device");
@@ -190,102 +189,15 @@
 	iobase = info->link.io.BasePort1;
 
 	do {
-		info->hdev->stat.byte_rx++;
-
-		/* Allocate packet */
-		if (info->rx_skb == NULL) {
-			info->rx_state = RECV_WAIT_PACKET_TYPE;
-			info->rx_count = 0;
-			if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
-				BT_ERR("Can't allocate mem for new packet");
-				return;
-			}
-		}
-
-		if (info->rx_state == RECV_WAIT_PACKET_TYPE) {
-
-			info->rx_skb->dev = (void *) info->hdev;
-			bt_cb(info->rx_skb)->pkt_type = inb(iobase + UART_RX);
-
-			switch (bt_cb(info->rx_skb)->pkt_type) {
-
-			case HCI_EVENT_PKT:
-				info->rx_state = RECV_WAIT_EVENT_HEADER;
-				info->rx_count = HCI_EVENT_HDR_SIZE;
-				break;
-
-			case HCI_ACLDATA_PKT:
-				info->rx_state = RECV_WAIT_ACL_HEADER;
-				info->rx_count = HCI_ACL_HDR_SIZE;
-				break;
-
-			case HCI_SCODATA_PKT:
-				info->rx_state = RECV_WAIT_SCO_HEADER;
-				info->rx_count = HCI_SCO_HDR_SIZE;
-				break;
-
-			default:
-				/* Unknown packet */
-				BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
-				info->hdev->stat.err_rx++;
-				clear_bit(HCI_RUNNING, &(info->hdev->flags));
-
-				kfree_skb(info->rx_skb);
-				info->rx_skb = NULL;
-				break;
-
-			}
-
-		} else {
-
-			*skb_put(info->rx_skb, 1) = inb(iobase + UART_RX);
-			info->rx_count--;
-
-			if (info->rx_count == 0) {
-
-				int dlen;
-				struct hci_event_hdr *eh;
-				struct hci_acl_hdr *ah;
-				struct hci_sco_hdr *sh;
-
-
-				switch (info->rx_state) {
-
-				case RECV_WAIT_EVENT_HEADER:
-					eh = (struct hci_event_hdr *)(info->rx_skb->data);
-					info->rx_state = RECV_WAIT_DATA;
-					info->rx_count = eh->plen;
-					break;
-
-				case RECV_WAIT_ACL_HEADER:
-					ah = (struct hci_acl_hdr *)(info->rx_skb->data);
-					dlen = __le16_to_cpu(ah->dlen);
-					info->rx_state = RECV_WAIT_DATA;
-					info->rx_count = dlen;
-					break;
-
-				case RECV_WAIT_SCO_HEADER:
-					sh = (struct hci_sco_hdr *)(info->rx_skb->data);
-					info->rx_state = RECV_WAIT_DATA;
-					info->rx_count = sh->dlen;
-					break;
-
-				case RECV_WAIT_DATA:
-					hci_recv_frame(info->rx_skb);
-					info->rx_skb = NULL;
-					break;
-
-				}
-
-			}
-
-		}
-
+		data[len] = inb(iobase + UART_RX);
+		
 		/* Make sure we don't stay here too long */
-		if (boguscount++ > 16)
+		if (len++ > 16)
 			break;
 
 	} while (inb(iobase + UART_LSR) & UART_LSR_DR);
+	info->hdev->stat.byte_rx += len;
+	info->proto.p->recv(&info->proto, data, len);
 }
 
 
@@ -404,7 +316,7 @@
 	btuart_info_t *info = (btuart_info_t *)(hdev->driver_data);
 
 	/* Drop TX queue */
-	skb_queue_purge(&(info->txq));
+	info->proto.p->flush(&info->proto);
 
 	return 0;
 }
@@ -453,9 +365,7 @@
 		break;
 	};
 
-	/* Prepend skb with frame type */
-	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
-	skb_queue_tail(&(info->txq), skb);
+	info->proto.p->enqueue(&info->proto, skb);
 
 	btuart_write_wakeup(info);
 
@@ -486,12 +396,6 @@
 
 	spin_lock_init(&(info->lock));
 
-	skb_queue_head_init(&(info->txq));
-
-	info->rx_state = RECV_WAIT_PACKET_TYPE;
-	info->rx_count = 0;
-	info->rx_skb = NULL;
-
 	/* Initialize HCI device */
 	hdev = hci_alloc_dev();
 	if (!hdev) {
@@ -499,6 +403,9 @@
 		return -ENOMEM;
 	}
 
+	info->proto.p = h4_init();
+	info->proto.p->open(&info->proto, hdev);
+
 	info->hdev = hdev;
 
 	hdev->type = HCI_PCCARD;
@@ -558,6 +465,8 @@
 
 	btuart_hci_close(hdev);
 
+	info->proto.p->close(&info->proto);
+
 	spin_lock_irqsave(&(info->lock), flags);
 
 	/* Reset UART */
diff -ur linux.old/drivers/bluetooth/hci_bcsp.c linux/drivers/bluetooth/hci_bcsp.c
--- linux.old/drivers/bluetooth/hci_bcsp.c	2006-04-22 23:28:41.000000000 +0200
+++ linux/drivers/bluetooth/hci_bcsp.c	2006-04-29 22:21:48.000000000 +0200
@@ -173,9 +173,9 @@
 	}
 }
 
-static int bcsp_enqueue(struct hci_uart *hu, struct sk_buff *skb)
+static int bcsp_enqueue(struct hci_uart_proto *proto, struct sk_buff *skb)
 {
-	struct bcsp_struct *bcsp = hu->priv;
+	struct bcsp_struct *bcsp = proto->priv;
 
 	if (skb->len > 0xFFF) {
 		BT_ERR("Packet too long");
@@ -202,6 +202,12 @@
 	return 0;
 }
 
+static int bcsp_henqueue(struct hci_uart_proto *proto, struct sk_buff *skb)
+{
+	 BT_ERR("bcsp_enqueue : not implemented");
+	 return -ENOENT;
+}
+
 static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
 		int len, int pkt_type)
 {
@@ -307,9 +313,9 @@
 }
 
 /* This is a rewrite of pkt_avail in ABCSP */
-static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)
+static struct sk_buff *bcsp_dequeue(struct hci_uart_proto *proto)
 {
-	struct bcsp_struct *bcsp = hu->priv;
+	struct bcsp_struct *bcsp = proto->priv;
 	unsigned long flags;
 	struct sk_buff *skb;
 	
@@ -363,9 +369,9 @@
 	return NULL;
 }
 
-static int bcsp_flush(struct hci_uart *hu)
+static int bcsp_flush(struct hci_uart_proto *proto)
 {
-	BT_DBG("hu %p", hu);
+	BT_DBG("proto %p", proto);
 	return 0;
 }
 
@@ -417,9 +423,9 @@
 /* Handle BCSP link-establishment packets. When we
    detect a "sync" packet, symptom that the BT module has reset,
    we do nothing :) (yet) */
-static void bcsp_handle_le_pkt(struct hci_uart *hu)
+static void bcsp_handle_le_pkt(struct hci_uart_proto *proto)
 {
-	struct bcsp_struct *bcsp = hu->priv;
+	struct bcsp_struct *bcsp = proto->priv;
 	u8 conf_pkt[4]     = { 0xad, 0xef, 0xac, 0xed };
 	u8 conf_rsp_pkt[4] = { 0xde, 0xad, 0xd0, 0xd0 };
 	u8 sync_pkt[4]     = { 0xda, 0xdc, 0xed, 0xed };
@@ -436,7 +442,7 @@
 		bt_cb(nskb)->pkt_type = BCSP_LE_PKT;
 
 		skb_queue_head(&bcsp->unrel, nskb);
-		hci_uart_tx_wakeup(hu);
+		proto->tx_wakeup(proto->tx_wakeup_data);
 	}
 	/* Spot "sync" pkts. If we find one...disaster! */
 	else if (bcsp->rx_skb->data[1] >> 4 == 4 && bcsp->rx_skb->data[2] == 0 &&
@@ -494,9 +500,9 @@
 	}
 }
 
-static void bcsp_complete_rx_pkt(struct hci_uart *hu)
+static void bcsp_complete_rx_pkt(struct hci_uart_proto *proto)
 {
-	struct bcsp_struct *bcsp = hu->priv;
+	struct bcsp_struct *bcsp = proto->priv;
 	int pass_up;
 
 	if (bcsp->rx_skb->data[0] & 0x80) {	/* reliable pkt */
@@ -506,7 +512,7 @@
 		bcsp->txack_req    = 1;
 
 		/* If needed, transmit an ack pkt */
-		hci_uart_tx_wakeup(hu);
+		proto->tx_wakeup(proto->tx_wakeup_data);
 	}
 
 	bcsp->rxack = (bcsp->rx_skb->data[0] >> 3) & 0x07;
@@ -526,7 +532,7 @@
 		pass_up = 1;
 	} else if ((bcsp->rx_skb->data[1] & 0x0f) == 1 &&
 			!(bcsp->rx_skb->data[0] & 0x80)) {
-		bcsp_handle_le_pkt(hu);
+		bcsp_handle_le_pkt(proto);
 		pass_up = 0;
 	} else
 		pass_up = 0;
@@ -568,13 +574,13 @@
 }
 
 /* Recv data */
-static int bcsp_recv(struct hci_uart *hu, void *data, int count)
+static int bcsp_recv(struct hci_uart_proto *proto, void *data, int count)
 {
-	struct bcsp_struct *bcsp = hu->priv;
+	struct bcsp_struct *bcsp = proto->priv;
 	register unsigned char *ptr;
 
-	BT_DBG("hu %p count %d rx_state %d rx_count %ld", 
-		hu, count, bcsp->rx_state, bcsp->rx_count);
+	BT_DBG("proto %p count %d rx_state %d rx_count %ld", 
+		proto, count, bcsp->rx_state, bcsp->rx_count);
 
 	ptr = data;
 	while (count) {
@@ -621,7 +627,7 @@
 				bcsp->rx_state = BCSP_W4_CRC;
 				bcsp->rx_count = 2;
 			} else
-				bcsp_complete_rx_pkt(hu);
+				bcsp_complete_rx_pkt(proto);
 			continue;
 
 		case BCSP_W4_CRC:
@@ -640,7 +646,7 @@
 				continue;
 			}
 			skb_trim(bcsp->rx_skb, bcsp->rx_skb->len - 2);
-			bcsp_complete_rx_pkt(hu);
+			bcsp_complete_rx_pkt(proto);
 			continue;
 
 		case BCSP_W4_PKT_DELIMITER:
@@ -678,7 +684,7 @@
 					bcsp->rx_count = 0;
 					return 0;
 				}
-				bcsp->rx_skb->dev = (void *) hu->hdev;
+				bcsp->rx_skb->dev = (void *) proto->hdev;
 				break;
 			}
 			break;
@@ -690,12 +696,12 @@
 	/* Arrange to retransmit all messages in the relq. */
 static void bcsp_timed_event(unsigned long arg)
 {
-	struct hci_uart *hu = (struct hci_uart *) arg;
-	struct bcsp_struct *bcsp = hu->priv;
+	struct hci_uart_proto *proto = (struct hci_uart_proto *) arg;
+	struct bcsp_struct *bcsp = proto->priv;
 	struct sk_buff *skb;
 	unsigned long flags;
 
-	BT_DBG("hu %p retransmitting %u pkts", hu, bcsp->unack.qlen);
+	BT_DBG("proto %p retransmitting %u pkts", proto, bcsp->unack.qlen);
 
 	spin_lock_irqsave(&bcsp->unack.lock, flags);
 
@@ -706,27 +712,31 @@
 
 	spin_unlock_irqrestore(&bcsp->unack.lock, flags);
 
-	hci_uart_tx_wakeup(hu);
+	proto->tx_wakeup(proto->tx_wakeup_data);
 }
 
-static int bcsp_open(struct hci_uart *hu)
+static int bcsp_open(struct hci_uart_proto *proto, struct hci_dev *hdev)
 {
 	struct bcsp_struct *bcsp;
 
-	BT_DBG("hu %p", hu);
+	BT_DBG("proto %p", proto);
+
+	if (!proto->tx_wakeup || !proto->tx_wakeup_data)
+		return -EINVAL;
 
 	bcsp = kzalloc(sizeof(*bcsp), GFP_ATOMIC);
 	if (!bcsp)
 		return -ENOMEM;
 
-	hu->priv = bcsp;
+	proto->priv = bcsp;
+	proto->hdev = hdev;
 	skb_queue_head_init(&bcsp->unack);
 	skb_queue_head_init(&bcsp->rel);
 	skb_queue_head_init(&bcsp->unrel);
 
 	init_timer(&bcsp->tbcsp);
 	bcsp->tbcsp.function = bcsp_timed_event;
-	bcsp->tbcsp.data     = (u_long) hu;
+	bcsp->tbcsp.data     = (u_long) proto;
 
 	bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
 
@@ -736,12 +746,12 @@
 	return 0;
 }
 
-static int bcsp_close(struct hci_uart *hu)
+static int bcsp_close(struct hci_uart_proto *proto)
 {
-	struct bcsp_struct *bcsp = hu->priv;
-	hu->priv = NULL;
+	struct bcsp_struct *bcsp = proto->priv;
+	proto->priv = NULL;
 
-	BT_DBG("hu %p", hu);
+	BT_DBG("proto %p", proto);
 
 	skb_queue_purge(&bcsp->unack);
 	skb_queue_purge(&bcsp->rel);
@@ -752,32 +762,23 @@
 	return 0;
 }
 
-static struct hci_uart_proto bcsp = {
+static struct hci_uart_proto_op bcsp = {
 	.id		= HCI_UART_BCSP,
 	.open		= bcsp_open,
 	.close		= bcsp_close,
 	.enqueue	= bcsp_enqueue,
+	.henqueue	= bcsp_henqueue,
 	.dequeue	= bcsp_dequeue,
 	.recv		= bcsp_recv,
 	.flush		= bcsp_flush
 };
 
-int bcsp_init(void)
+struct hci_uart_proto_op *bcsp_init(void)
 {
-	int err = hci_uart_register_proto(&bcsp);
-
-	if (!err)
-		BT_INFO("HCI BCSP protocol initialized");
-	else
-		BT_ERR("HCI BCSP protocol registration failed");
-
-	return err;
+	return &bcsp;
 }
 
-int bcsp_deinit(void)
-{
-	return hci_uart_unregister_proto(&bcsp);
-}
+EXPORT_SYMBOL_GPL(bcsp_init);
 
 module_param(txcrc, bool, 0644);
 MODULE_PARM_DESC(txcrc, "Transmit CRC with every BCSP packet");
diff -ur linux.old/drivers/bluetooth/hci_h4.c linux/drivers/bluetooth/hci_h4.c
--- linux.old/drivers/bluetooth/hci_h4.c	2006-04-22 23:28:15.000000000 +0200
+++ linux/drivers/bluetooth/hci_h4.c	2006-04-29 22:33:24.000000000 +0200
@@ -70,11 +70,11 @@
 #define H4_W4_DATA		4
 
 /* Initialize protocol */
-static int h4_open(struct hci_uart *hu)
+static int h4_open(struct hci_uart_proto *proto, struct hci_dev *hdev)
 {
 	struct h4_struct *h4;
 
-	BT_DBG("hu %p", hu);
+	BT_DBG("proto %p", proto);
 
 	h4 = kzalloc(sizeof(*h4), GFP_ATOMIC);
 	if (!h4)
@@ -82,16 +82,17 @@
 
 	skb_queue_head_init(&h4->txq);
 
-	hu->priv = h4;
+	proto->priv = h4;
+	proto->hdev = hdev;
 	return 0;
 }
 
 /* Flush protocol data */
-static int h4_flush(struct hci_uart *hu)
+static int h4_flush(struct hci_uart_proto *proto)
 {
-	struct h4_struct *h4 = hu->priv;
+	struct h4_struct *h4 = proto->priv;
 
-	BT_DBG("hu %p", hu);
+	BT_DBG("proto %p", proto);
 
 	skb_queue_purge(&h4->txq);
 
@@ -99,31 +100,31 @@
 }
 
 /* Close protocol */
-static int h4_close(struct hci_uart *hu)
+static int h4_close(struct hci_uart_proto *proto)
 {
-	struct h4_struct *h4 = hu->priv;
+	struct h4_struct *h4 = proto->priv;
 
-	hu->priv = NULL;
+	proto->priv = NULL;
 
-	BT_DBG("hu %p", hu);
+	BT_DBG("proto %p", proto);
 
 	skb_queue_purge(&h4->txq);
 
 	if (h4->rx_skb)
 		kfree_skb(h4->rx_skb);
 
-	hu->priv = NULL;
+	proto->priv = NULL;
 	kfree(h4);
 
 	return 0;
 }
 
 /* Enqueue frame for transmittion (padding, crc, etc) */
-static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb)
+static int h4_enqueue(struct hci_uart_proto *proto, struct sk_buff *skb)
 {
-	struct h4_struct *h4 = hu->priv;
+	struct h4_struct *h4 = proto->priv;
 
-	BT_DBG("hu %p skb %p", hu, skb);
+	BT_DBG("proto %p skb %p", proto, skb);
 
 	/* Prepend skb with frame type */
 	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
@@ -132,6 +133,17 @@
 	return 0;
 }
 
+/* Enqueue frame for transmittion (padding, crc, etc) */
+static int h4_henqueue(struct hci_uart_proto *proto, struct sk_buff *skb)
+{
+	struct h4_struct *h4 = proto->priv;
+
+	BT_DBG("proto %p skb %p", proto, skb);
+
+	skb_queue_head(&h4->txq, skb);
+	return 0;
+}
+
 static inline int h4_check_data_len(struct h4_struct *h4, int len)
 {
 	register int room = skb_tailroom(h4->rx_skb);
@@ -157,17 +169,17 @@
 }
 
 /* Recv data */
-static int h4_recv(struct hci_uart *hu, void *data, int count)
+static int h4_recv(struct hci_uart_proto *proto, void *data, int count)
 {
-	struct h4_struct *h4 = hu->priv;
+	struct h4_struct *h4 = proto->priv;
 	register char *ptr;
 	struct hci_event_hdr *eh;
 	struct hci_acl_hdr   *ah;
 	struct hci_sco_hdr   *sh;
 	register int len, type, dlen;
 
-	BT_DBG("hu %p count %d rx_state %ld rx_count %ld", 
-			hu, count, h4->rx_state, h4->rx_count);
+	BT_DBG("proto %p count %d rx_state %ld rx_count %ld", 
+			proto, count, h4->rx_state, h4->rx_count);
 
 	ptr = data;
 	while (count) {
@@ -241,7 +253,7 @@
 
 		default:
 			BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr);
-			hu->hdev->stat.err_rx++;
+			proto->hdev->stat.err_rx++;
 			ptr++; count--;
 			continue;
 		};
@@ -257,16 +269,16 @@
 			return 0;
 		}
 
-		h4->rx_skb->dev = (void *) hu->hdev;
+		h4->rx_skb->dev = (void *) proto->hdev;
 		bt_cb(h4->rx_skb)->pkt_type = type;
 	}
 
 	return count;
 }
 
-static struct sk_buff *h4_dequeue(struct hci_uart *hu)
+static struct sk_buff *h4_dequeue(struct hci_uart_proto *proto)
 {
-	struct h4_struct *h4 = hu->priv;
+	struct h4_struct *h4 = proto->priv;
 	return skb_dequeue(&h4->txq);
 }
 
@@ -276,23 +288,14 @@
 	.close		= h4_close,
 	.recv		= h4_recv,
 	.enqueue	= h4_enqueue,
+	.henqueue	= h4_henqueue,
 	.dequeue	= h4_dequeue,
 	.flush		= h4_flush,
 };
 
-int h4_init(void)
+struct hci_uart_proto_op *h4_init(void)
 {
-	int err = hci_uart_register_proto(&h4p);
-
-	if (!err)
-		BT_INFO("HCI H4 protocol initialized");
-	else
-		BT_ERR("HCI H4 protocol registration failed");
-
-	return err;
+	return &h4p;
 }
 
-int h4_deinit(void)
-{
-	return hci_uart_unregister_proto(&h4p);
-}
+EXPORT_SYMBOL_GPL(h4_init);
diff -ur linux.old/drivers/bluetooth/hci_ldisc.c linux/drivers/bluetooth/hci_ldisc.c
--- linux.old/drivers/bluetooth/hci_ldisc.c	2006-04-22 23:28:41.000000000 +0200
+++ linux/drivers/bluetooth/hci_ldisc.c	2006-04-29 22:20:10.000000000 +0200
@@ -57,9 +57,9 @@
 
 static int reset = 0;
 
-static struct hci_uart_proto *hup[HCI_UART_MAX_PROTO];
+static struct hci_uart_proto_op *hup[HCI_UART_MAX_PROTO];
 
-int hci_uart_register_proto(struct hci_uart_proto *p)
+int hci_uart_register_proto(struct hci_uart_proto_op *p)
 {
 	if (p->id >= HCI_UART_MAX_PROTO)
 		return -EINVAL;
@@ -72,20 +72,7 @@
 	return 0;
 }
 
-int hci_uart_unregister_proto(struct hci_uart_proto *p)
-{
-	if (p->id >= HCI_UART_MAX_PROTO)
-		return -EINVAL;
-
-	if (!hup[p->id])
-		return -EINVAL;
-
-	hup[p->id] = NULL;
-
-	return 0;
-}
-
-static struct hci_uart_proto *hci_uart_get_proto(unsigned int id)
+static struct hci_uart_proto_op *hci_uart_get_proto(unsigned int id)
 {
 	if (id >= HCI_UART_MAX_PROTO)
 		return NULL;
@@ -118,7 +105,7 @@
 	struct sk_buff *skb = hu->tx_skb;
 
 	if (!skb)
-		skb = hu->proto->dequeue(hu);
+		skb = hu->proto.p->dequeue(&hu->proto);
 	else
 		hu->tx_skb = NULL;
 
@@ -196,7 +183,7 @@
 		tty->driver->flush_buffer(tty);
 
 	if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
-		hu->proto->flush(hu);
+		hu->proto.p->flush(&hu->proto);
 
 	return 0;
 }
@@ -233,7 +220,7 @@
 
 	BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
 
-	hu->proto->enqueue(hu, skb);
+	hu->proto.p->enqueue(&hu->proto, skb);
 
 	hci_uart_tx_wakeup(hu);
 
@@ -316,7 +303,7 @@
 		hci_uart_close(hdev);
 
 		if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
-			hu->proto->close(hu);
+			hu->proto.p->close(&hu->proto);
 			hci_unregister_dev(hdev);
 			hci_free_dev(hdev);
 		}
@@ -372,7 +359,7 @@
 		return;
 
 	spin_lock(&hu->rx_lock);
-	hu->proto->recv(hu, (void *) data, count);
+	hu->proto.p->recv(&hu->proto, (void *) data, count);
 	hu->hdev->stat.byte_rx += count;
 	spin_unlock(&hu->rx_lock);
 
@@ -383,6 +370,7 @@
 static int hci_uart_register_dev(struct hci_uart *hu)
 {
 	struct hci_dev *hdev;
+	int err;	
 
 	BT_DBG("");
 
@@ -393,6 +381,10 @@
 		return -ENOMEM;
 	}
 
+	err = hu->proto.p->open(&hu->proto, hdev);
+	if (err)
+		return err;
+
 	hu->hdev = hdev;
 
 	hdev->type = HCI_UART;
@@ -420,22 +412,20 @@
 
 static int hci_uart_set_proto(struct hci_uart *hu, int id)
 {
-	struct hci_uart_proto *p;
+	struct hci_uart_proto_op *p;
 	int err;
 
 	p = hci_uart_get_proto(id);
 	if (!p)
 		return -EPROTONOSUPPORT;
 
-	err = p->open(hu);
-	if (err)
-		return err;
-
-	hu->proto = p;
+ 	hu->proto.p = p;
+ 	hu->proto.tx_wakeup_data = hu;;
+ 	hu->proto.tx_wakeup = (int (*)(void *)) hci_uart_tx_wakeup;
 
 	err = hci_uart_register_dev(hu);
 	if (err) {
-		p->close(hu);
+		hu->proto.p->close(&hu->proto);
 		return err;
 	}
 
@@ -481,7 +471,7 @@
 
 	case HCIUARTGETPROTO:
 		if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
-			return hu->proto->id;
+			return hu->proto.p->id;
 		return -EUNATCH;
 
 	default:
@@ -541,12 +531,12 @@
 	}
 
 #ifdef CONFIG_BT_HCIUART_H4
-	h4_init();
+	hci_uart_register_proto(h4_init());
 #endif
 #ifdef CONFIG_BT_HCIUART_BCSP
-	bcsp_init();
+	hci_uart_register_proto(bcsp_init());
 #endif
-	
+
 	return 0;
 }
 
@@ -554,13 +544,6 @@
 {
 	int err;
 
-#ifdef CONFIG_BT_HCIUART_H4
-	h4_deinit();
-#endif
-#ifdef CONFIG_BT_HCIUART_BCSP
-	bcsp_deinit();
-#endif
-
 	/* Release tty registration of line discipline */
 	if ((err = tty_unregister_ldisc(N_HCI)))
 		BT_ERR("Can't unregister HCI line discipline (%d)", err);
diff -ur linux.old/drivers/bluetooth/hci_uart.h linux/drivers/bluetooth/hci_uart.h
--- linux.old/drivers/bluetooth/hci_uart.h	2006-04-22 23:28:15.000000000 +0200
+++ linux/drivers/bluetooth/hci_uart.h	2006-04-29 22:20:10.000000000 +0200
@@ -41,14 +41,26 @@
 
 struct hci_uart;
 
+struct hci_uart_proto_op;
+
 struct hci_uart_proto {
+	struct hci_uart_proto_op *p;
+	void               *priv;
+
+	struct hci_dev     *hdev;
+	int (*tx_wakeup) (void *data);
+	void *tx_wakeup_data;
+};
+
+struct hci_uart_proto_op {
 	unsigned int id;
-	int (*open)(struct hci_uart *hu);
-	int (*close)(struct hci_uart *hu);
-	int (*flush)(struct hci_uart *hu);
-	int (*recv)(struct hci_uart *hu, void *data, int len);
-	int (*enqueue)(struct hci_uart *hu, struct sk_buff *skb);
-	struct sk_buff *(*dequeue)(struct hci_uart *hu);
+	int (*open)(struct hci_uart_proto *proto, struct hci_dev *hdev);
+	int (*close)(struct hci_uart_proto *proto);
+	int (*flush)(struct hci_uart_proto *proto);
+	int (*recv)(struct hci_uart_proto *proto, void *data, int len);
+	int (*enqueue)(struct hci_uart_proto *proto, struct sk_buff *skb);
+	int (*henqueue)(struct hci_uart_proto *proto, struct sk_buff *skb);
+	struct sk_buff *(*dequeue)(struct hci_uart_proto *proto);
 };
 
 struct hci_uart {
@@ -57,7 +69,6 @@
 	unsigned long		flags;
 
 	struct hci_uart_proto	*proto;
-	void			*priv;
 
 	struct sk_buff		*tx_skb;
 	unsigned long		tx_state;
@@ -71,16 +82,12 @@
 #define HCI_UART_SENDING	1
 #define HCI_UART_TX_WAKEUP	2
 
-int hci_uart_register_proto(struct hci_uart_proto *p);
-int hci_uart_unregister_proto(struct hci_uart_proto *p);
-int hci_uart_tx_wakeup(struct hci_uart *hu);
+int hci_uart_register_proto(struct hci_uart_proto_op *p);
 
 #ifdef CONFIG_BT_HCIUART_H4
-int h4_init(void);
-int h4_deinit(void);
+struct hci_uart_proto_op *h4_init(void);
 #endif
 
 #ifdef CONFIG_BT_HCIUART_BCSP
-int bcsp_init(void);
-int bcsp_deinit(void);
+struct hci_uart_proto_op *bcsp_init(void);
 #endif

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

end of thread, other threads:[~2006-06-05 14:10 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-05-02 20:20 [Bluez-devel] RFC : H4 and BCSP proto unification matthieu castet
2006-05-29 19:05 ` matthieu castet
2006-06-05 14:10 ` Marcel Holtmann

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).