public inbox for linux-bluetooth@vger.kernel.org
 help / color / mirror / Atom feed
From: Andrey Jivsov <bluetooth@brainhub.org>
To: BlueZ users <bluez-users@lists.sourceforge.net>
Subject: Re: [Bluez-users] Microsoft IntelliMouse with kernel 2.6.1 and patch-2.6.18-mh1 is broken (fix provided)
Date: Wed, 27 Sep 2006 01:26:09 -0700	[thread overview]
Message-ID: <451A35A1.6020309@brainhub.org> (raw)
In-Reply-To: <1159343538.22162.11.camel@localhost>

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

Hi Marcel, here is the patch against linux-2.6.18-mh1 to fix 
IntelliMouse. That's the best range of changes I have time to provide: 
somewhere in these changes IntelliMouse was broken. I believe this 
happened between patch-2.6.15-mh2 and linux-2.6.18-mh1. While there are 
a lot of changes in these 17 files, but most of them are variable 
renames. I hope this helps you to narrow down the issue.

[ Does sending compressed patched works? Trying uncompressed first. ]

[-- Attachment #2: patch-2.6.18-2-mh1aj.diff --]
[-- Type: text/x-patch, Size: 91953 bytes --]

diff -ur --exclude-from=kernel-diff-exclude.txt linux-2.6.18-mh1/drivers/bluetooth/bfusb.c linux-2.6.18-my-bt/drivers/bluetooth/bfusb.c
--- linux-2.6.18-mh1/drivers/bluetooth/bfusb.c	2006-09-23 19:59:12.000000000 -0700
+++ linux-2.6.18-my-bt/drivers/bluetooth/bfusb.c	2006-09-23 22:53:14.000000000 -0700
@@ -2,7 +2,7 @@
  *
  *  AVM BlueFRITZ! USB driver
  *
- *  Copyright (C) 2003-2006  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2003  Marcel Holtmann <marcel@holtmann.org>
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -59,6 +59,7 @@
 
 MODULE_DEVICE_TABLE(usb, bfusb_table);
 
+
 #define BFUSB_MAX_BLOCK_SIZE	256
 
 #define BFUSB_BLOCK_TIMEOUT	3000
@@ -69,7 +70,7 @@
 #define BFUSB_MAX_BULK_TX	2
 #define BFUSB_MAX_BULK_RX	2
 
-struct bfusb_data {
+struct bfusb {
 	struct hci_dev		*hdev;
 
 	unsigned long		state;
@@ -91,136 +92,137 @@
 	struct sk_buff_head	completed_q;
 };
 
-struct bfusb_data_scb {
+struct bfusb_scb {
 	struct urb *urb;
 };
 
 static void bfusb_tx_complete(struct urb *urb, struct pt_regs *regs);
 static void bfusb_rx_complete(struct urb *urb, struct pt_regs *regs);
 
-static struct urb *bfusb_get_completed(struct bfusb_data *data)
+static struct urb *bfusb_get_completed(struct bfusb *bfusb)
 {
 	struct sk_buff *skb;
 	struct urb *urb = NULL;
 
-	BT_DBG("bfusb %p", data);
+	BT_DBG("bfusb %p", bfusb);
 
-	skb = skb_dequeue(&data->completed_q);
+	skb = skb_dequeue(&bfusb->completed_q);
 	if (skb) {
-		urb = ((struct bfusb_data_scb *) skb->cb)->urb;
+		urb = ((struct bfusb_scb *) skb->cb)->urb;
 		kfree_skb(skb);
 	}
 
 	return urb;
 }
 
-static void bfusb_unlink_urbs(struct bfusb_data *data)
+static void bfusb_unlink_urbs(struct bfusb *bfusb)
 {
 	struct sk_buff *skb;
 	struct urb *urb;
 
-	BT_DBG("bfusb %p", data);
+	BT_DBG("bfusb %p", bfusb);
 
-	while ((skb = skb_dequeue(&data->pending_q))) {
-		urb = ((struct bfusb_data_scb *) skb->cb)->urb;
+	while ((skb = skb_dequeue(&bfusb->pending_q))) {
+		urb = ((struct bfusb_scb *) skb->cb)->urb;
 		usb_kill_urb(urb);
-		skb_queue_tail(&data->completed_q, skb);
+		skb_queue_tail(&bfusb->completed_q, skb);
 	}
 
-	while ((urb = bfusb_get_completed(data)))
+	while ((urb = bfusb_get_completed(bfusb)))
 		usb_free_urb(urb);
 }
 
-static int bfusb_send_bulk(struct bfusb_data *data, struct sk_buff *skb)
+
+static int bfusb_send_bulk(struct bfusb *bfusb, struct sk_buff *skb)
 {
-	struct bfusb_data_scb *scb = (void *) skb->cb;
-	struct urb *urb = bfusb_get_completed(data);
+	struct bfusb_scb *scb = (void *) skb->cb;
+	struct urb *urb = bfusb_get_completed(bfusb);
 	int err, pipe;
 
-	BT_DBG("bfusb %p skb %p len %d", data, skb, skb->len);
+	BT_DBG("bfusb %p skb %p len %d", bfusb, skb, skb->len);
 
 	if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC)))
 		return -ENOMEM;
 
-	pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep);
+	pipe = usb_sndbulkpipe(bfusb->udev, bfusb->bulk_out_ep);
 
-	usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, skb->len,
+	usb_fill_bulk_urb(urb, bfusb->udev, pipe, skb->data, skb->len,
 			bfusb_tx_complete, skb);
 
 	scb->urb = urb;
 
-	skb_queue_tail(&data->pending_q, skb);
+	skb_queue_tail(&bfusb->pending_q, skb);
 
 	err = usb_submit_urb(urb, GFP_ATOMIC);
 	if (err) {
 		BT_ERR("%s bulk tx submit failed urb %p err %d", 
-					data->hdev->name, urb, err);
-		skb_unlink(skb, &data->pending_q);
+					bfusb->hdev->name, urb, err);
+		skb_unlink(skb, &bfusb->pending_q);
 		usb_free_urb(urb);
 	} else
-		atomic_inc(&data->pending_tx);
+		atomic_inc(&bfusb->pending_tx);
 
 	return err;
 }
 
-static void bfusb_tx_wakeup(struct bfusb_data *data)
+static void bfusb_tx_wakeup(struct bfusb *bfusb)
 {
 	struct sk_buff *skb;
 
-	BT_DBG("bfusb %p", data);
+	BT_DBG("bfusb %p", bfusb);
 
-	if (test_and_set_bit(BFUSB_TX_PROCESS, &data->state)) {
-		set_bit(BFUSB_TX_WAKEUP, &data->state);
+	if (test_and_set_bit(BFUSB_TX_PROCESS, &bfusb->state)) {
+		set_bit(BFUSB_TX_WAKEUP, &bfusb->state);
 		return;
 	}
 
 	do {
-		clear_bit(BFUSB_TX_WAKEUP, &data->state);
+		clear_bit(BFUSB_TX_WAKEUP, &bfusb->state);
 
-		while ((atomic_read(&data->pending_tx) < BFUSB_MAX_BULK_TX) &&
-				(skb = skb_dequeue(&data->transmit_q))) {
-			if (bfusb_send_bulk(data, skb) < 0) {
-				skb_queue_head(&data->transmit_q, skb);
+		while ((atomic_read(&bfusb->pending_tx) < BFUSB_MAX_BULK_TX) &&
+				(skb = skb_dequeue(&bfusb->transmit_q))) {
+			if (bfusb_send_bulk(bfusb, skb) < 0) {
+				skb_queue_head(&bfusb->transmit_q, skb);
 				break;
 			}
 		}
 
-	} while (test_bit(BFUSB_TX_WAKEUP, &data->state));
+	} while (test_bit(BFUSB_TX_WAKEUP, &bfusb->state));
 
-	clear_bit(BFUSB_TX_PROCESS, &data->state);
+	clear_bit(BFUSB_TX_PROCESS, &bfusb->state);
 }
 
 static void bfusb_tx_complete(struct urb *urb, struct pt_regs *regs)
 {
 	struct sk_buff *skb = (struct sk_buff *) urb->context;
-	struct bfusb_data *data = (struct bfusb_data *) skb->dev;
+	struct bfusb *bfusb = (struct bfusb *) skb->dev;
 
-	BT_DBG("bfusb %p urb %p skb %p len %d", data, urb, skb, skb->len);
+	BT_DBG("bfusb %p urb %p skb %p len %d", bfusb, urb, skb, skb->len);
 
-	atomic_dec(&data->pending_tx);
+	atomic_dec(&bfusb->pending_tx);
 
-	if (!test_bit(HCI_RUNNING, &data->hdev->flags))
+	if (!test_bit(HCI_RUNNING, &bfusb->hdev->flags))
 		return;
 
 	if (!urb->status)
-		data->hdev->stat.byte_tx += skb->len;
+		bfusb->hdev->stat.byte_tx += skb->len;
 	else
-		data->hdev->stat.err_tx++;
+		bfusb->hdev->stat.err_tx++;
 
-	read_lock(&data->lock);
+	read_lock(&bfusb->lock);
 
-	skb_unlink(skb, &data->pending_q);
-	skb_queue_tail(&data->completed_q, skb);
+	skb_unlink(skb, &bfusb->pending_q);
+	skb_queue_tail(&bfusb->completed_q, skb);
 
-	bfusb_tx_wakeup(data);
+	bfusb_tx_wakeup(bfusb);
 
-	read_unlock(&data->lock);
+	read_unlock(&bfusb->lock);
 }
 
 
-static int bfusb_rx_submit(struct bfusb_data *data, struct urb *urb)
+static int bfusb_rx_submit(struct bfusb *bfusb, struct urb *urb)
 {
-	struct bfusb_data_scb *scb;
+	struct bfusb_scb *scb;
 	struct sk_buff *skb;
 	int err, pipe, size = HCI_MAX_FRAME_SIZE + 32;
 
@@ -229,29 +231,28 @@
 	if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC)))
 		return -ENOMEM;
 
-	skb = bt_skb_alloc(size, GFP_ATOMIC);
-	if (!skb) {
+	if (!(skb = bt_skb_alloc(size, GFP_ATOMIC))) {
 		usb_free_urb(urb);
 		return -ENOMEM;
 	}
 
-	skb->dev = (void *) data;
+	skb->dev = (void *) bfusb;
 
-	scb = (struct bfusb_data_scb *) skb->cb;
+	scb = (struct bfusb_scb *) skb->cb;
 	scb->urb = urb;
 
-	pipe = usb_rcvbulkpipe(data->udev, data->bulk_in_ep);
+	pipe = usb_rcvbulkpipe(bfusb->udev, bfusb->bulk_in_ep);
 
-	usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, size,
+	usb_fill_bulk_urb(urb, bfusb->udev, pipe, skb->data, size,
 			bfusb_rx_complete, skb);
 
-	skb_queue_tail(&data->pending_q, skb);
+	skb_queue_tail(&bfusb->pending_q, skb);
 
 	err = usb_submit_urb(urb, GFP_ATOMIC);
 	if (err) {
 		BT_ERR("%s bulk rx submit failed urb %p err %d",
-					data->hdev->name, urb, err);
-		skb_unlink(skb, &data->pending_q);
+					bfusb->hdev->name, urb, err);
+		skb_unlink(skb, &bfusb->pending_q);
 		kfree_skb(skb);
 		usb_free_urb(urb);
 	}
@@ -259,15 +260,15 @@
 	return err;
 }
 
-static inline int bfusb_recv_block(struct bfusb_data *data, int hdr, unsigned char *buf, int len)
+static inline int bfusb_recv_block(struct bfusb *bfusb, int hdr, unsigned char *data, int len)
 {
-	BT_DBG("bfusb %p hdr 0x%02x data %p len %d", data, hdr, buf, len);
+	BT_DBG("bfusb %p hdr 0x%02x data %p len %d", bfusb, hdr, data, len);
 
 	if (hdr & 0x10) {
-		BT_ERR("%s error in block", data->hdev->name);
-		if (data->reassembly)
-			kfree_skb(data->reassembly);
-		data->reassembly = NULL;
+		BT_ERR("%s error in block", bfusb->hdev->name);
+		if (bfusb->reassembly)
+			kfree_skb(bfusb->reassembly);
+		bfusb->reassembly = NULL;
 		return -EIO;
 	}
 
@@ -276,46 +277,46 @@
 		unsigned char pkt_type;
 		int pkt_len = 0;
 
-		if (data->reassembly) {
-			BT_ERR("%s unexpected start block", data->hdev->name);
-			kfree_skb(data->reassembly);
-			data->reassembly = NULL;
+		if (bfusb->reassembly) {
+			BT_ERR("%s unexpected start block", bfusb->hdev->name);
+			kfree_skb(bfusb->reassembly);
+			bfusb->reassembly = NULL;
 		}
 
 		if (len < 1) {
-			BT_ERR("%s no packet type found", data->hdev->name);
+			BT_ERR("%s no packet type found", bfusb->hdev->name);
 			return -EPROTO;
 		}
 
-		pkt_type = *buf++; len--;
+		pkt_type = *data++; len--;
 
 		switch (pkt_type) {
 		case HCI_EVENT_PKT:
 			if (len >= HCI_EVENT_HDR_SIZE) {
-				struct hci_event_hdr *hdr = (struct hci_event_hdr *) buf;
+				struct hci_event_hdr *hdr = (struct hci_event_hdr *) data;
 				pkt_len = HCI_EVENT_HDR_SIZE + hdr->plen;
 			} else {
-				BT_ERR("%s event block is too short", data->hdev->name);
+				BT_ERR("%s event block is too short", bfusb->hdev->name);
 				return -EILSEQ;
 			}
 			break;
 
 		case HCI_ACLDATA_PKT:
 			if (len >= HCI_ACL_HDR_SIZE) {
-				struct hci_acl_hdr *hdr = (struct hci_acl_hdr *) buf;
+				struct hci_acl_hdr *hdr = (struct hci_acl_hdr *) data;
 				pkt_len = HCI_ACL_HDR_SIZE + __le16_to_cpu(hdr->dlen);
 			} else {
-				BT_ERR("%s data block is too short", data->hdev->name);
+				BT_ERR("%s data block is too short", bfusb->hdev->name);
 				return -EILSEQ;
 			}
 			break;
 
 		case HCI_SCODATA_PKT:
 			if (len >= HCI_SCO_HDR_SIZE) {
-				struct hci_sco_hdr *hdr = (struct hci_sco_hdr *) buf;
+				struct hci_sco_hdr *hdr = (struct hci_sco_hdr *) data;
 				pkt_len = HCI_SCO_HDR_SIZE + hdr->dlen;
 			} else {
-				BT_ERR("%s audio block is too short", data->hdev->name);
+				BT_ERR("%s audio block is too short", bfusb->hdev->name);
 				return -EILSEQ;
 			}
 			break;
@@ -323,27 +324,27 @@
 
 		skb = bt_skb_alloc(pkt_len, GFP_ATOMIC);
 		if (!skb) {
-			BT_ERR("%s no memory for the packet", data->hdev->name);
+			BT_ERR("%s no memory for the packet", bfusb->hdev->name);
 			return -ENOMEM;
 		}
 
-		skb->dev = (void *) data->hdev;
+		skb->dev = (void *) bfusb->hdev;
 		bt_cb(skb)->pkt_type = pkt_type;
 
-		data->reassembly = skb;
+		bfusb->reassembly = skb;
 	} else {
-		if (!data->reassembly) {
-			BT_ERR("%s unexpected continuation block", data->hdev->name);
+		if (!bfusb->reassembly) {
+			BT_ERR("%s unexpected continuation block", bfusb->hdev->name);
 			return -EIO;
 		}
 	}
 
 	if (len > 0)
-		memcpy(skb_put(data->reassembly, len), buf, len);
+		memcpy(skb_put(bfusb->reassembly, len), data, len);
 
 	if (hdr & 0x08) {
-		hci_recv_frame(data->reassembly);
-		data->reassembly = NULL;
+		hci_recv_frame(bfusb->reassembly);
+		bfusb->reassembly = NULL;
 	}
 
 	return 0;
@@ -352,22 +353,22 @@
 static void bfusb_rx_complete(struct urb *urb, struct pt_regs *regs)
 {
 	struct sk_buff *skb = (struct sk_buff *) urb->context;
-	struct bfusb_data *data = (struct bfusb_data *) skb->dev;
+	struct bfusb *bfusb = (struct bfusb *) skb->dev;
 	unsigned char *buf = urb->transfer_buffer;
 	int count = urb->actual_length;
 	int err, hdr, len;
 
 	BT_DBG("bfusb %p urb %p skb %p len %d", bfusb, urb, skb, skb->len);
 
-	read_lock(&data->lock);
+	read_lock(&bfusb->lock);
 
-	if (!test_bit(HCI_RUNNING, &data->hdev->flags))
+	if (!test_bit(HCI_RUNNING, &bfusb->hdev->flags))
 		goto unlock;
 
 	if (urb->status || !count)
 		goto resubmit;
 
-	data->hdev->stat.byte_rx += count;
+	bfusb->hdev->stat.byte_rx += count;
 
 	skb_put(skb, count);
 
@@ -386,89 +387,90 @@
 
 		if (count < len) {
 			BT_ERR("%s block extends over URB buffer ranges",
-					data->hdev->name);
+					bfusb->hdev->name);
 		}
 
 		if ((hdr & 0xe1) == 0xc1)
-			bfusb_recv_block(data, hdr, buf, len);
+			bfusb_recv_block(bfusb, hdr, buf, len);
 
 		count -= len;
 		buf   += len;
 	}
 
-	skb_unlink(skb, &data->pending_q);
+	skb_unlink(skb, &bfusb->pending_q);
 	kfree_skb(skb);
 
-	bfusb_rx_submit(data, urb);
+	bfusb_rx_submit(bfusb, urb);
 
-	read_unlock(&data->lock);
+	read_unlock(&bfusb->lock);
 
 	return;
 
 resubmit:
-	urb->dev = data->udev;
+	urb->dev = bfusb->udev;
 
 	err = usb_submit_urb(urb, GFP_ATOMIC);
 	if (err) {
 		BT_ERR("%s bulk resubmit failed urb %p err %d",
-					data->hdev->name, urb, err);
+					bfusb->hdev->name, urb, err);
 	}
 
 unlock:
-	read_unlock(&data->lock);
+	read_unlock(&bfusb->lock);
 }
 
+
 static int bfusb_open(struct hci_dev *hdev)
 {
-	struct bfusb_data *data = hdev->driver_data;
+	struct bfusb *bfusb = (struct bfusb *) hdev->driver_data;
 	unsigned long flags;
 	int i, err;
 
-	BT_DBG("hdev %p bfusb %p", hdev, data);
+	BT_DBG("hdev %p bfusb %p", hdev, bfusb);
 
 	if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
 		return 0;
 
-	write_lock_irqsave(&data->lock, flags);
+	write_lock_irqsave(&bfusb->lock, flags);
 
-	err = bfusb_rx_submit(data, NULL);
+	err = bfusb_rx_submit(bfusb, NULL);
 	if (!err) {
 		for (i = 1; i < BFUSB_MAX_BULK_RX; i++)
-			bfusb_rx_submit(data, NULL);
+			bfusb_rx_submit(bfusb, NULL);
 	} else {
 		clear_bit(HCI_RUNNING, &hdev->flags);
 	}
 
-	write_unlock_irqrestore(&data->lock, flags);
+	write_unlock_irqrestore(&bfusb->lock, flags);
 
 	return err;
 }
 
 static int bfusb_flush(struct hci_dev *hdev)
 {
-	struct bfusb_data *data = hdev->driver_data;
+	struct bfusb *bfusb = (struct bfusb *) hdev->driver_data;
 
-	BT_DBG("hdev %p bfusb %p", hdev, data);
+	BT_DBG("hdev %p bfusb %p", hdev, bfusb);
 
-	skb_queue_purge(&data->transmit_q);
+	skb_queue_purge(&bfusb->transmit_q);
 
 	return 0;
 }
 
 static int bfusb_close(struct hci_dev *hdev)
 {
-	struct bfusb_data *data = hdev->driver_data;
+	struct bfusb *bfusb = (struct bfusb *) hdev->driver_data;
 	unsigned long flags;
 
-	BT_DBG("hdev %p bfusb %p", hdev, data);
+	BT_DBG("hdev %p bfusb %p", hdev, bfusb);
 
 	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
 		return 0;
 
-	write_lock_irqsave(&data->lock, flags);
-	write_unlock_irqrestore(&data->lock, flags);
+	write_lock_irqsave(&bfusb->lock, flags);
+	write_unlock_irqrestore(&bfusb->lock, flags);
 
-	bfusb_unlink_urbs(data);
+	bfusb_unlink_urbs(bfusb);
 	bfusb_flush(hdev);
 
 	return 0;
@@ -477,7 +479,7 @@
 static int bfusb_send_frame(struct sk_buff *skb)
 {
 	struct hci_dev *hdev = (struct hci_dev *) skb->dev;
-	struct bfusb_data *data;
+	struct bfusb *bfusb;
 	struct sk_buff *nskb;
 	unsigned char buf[3];
 	int sent = 0, size, count;
@@ -492,7 +494,7 @@
 	if (!test_bit(HCI_RUNNING, &hdev->flags))
 		return -EBUSY;
 
-	data = hdev->driver_data;
+	bfusb = (struct bfusb *) hdev->driver_data;
 
 	switch (bt_cb(skb)->pkt_type) {
 	case HCI_COMMAND_PKT:
@@ -512,13 +514,12 @@
 	count = skb->len;
 
 	/* Max HCI frame size seems to be 1511 + 1 */
-	nskb = bt_skb_alloc(count + 32, GFP_ATOMIC);
-	if (!nskb) {
+	if (!(nskb = bt_skb_alloc(count + 32, GFP_ATOMIC))) {
 		BT_ERR("Can't allocate memory for new packet");
 		return -ENOMEM;
 	}
 
-	nskb->dev = (void *) data;
+	nskb->dev = (void *) bfusb;
 
 	while (count) {
 		size = min_t(uint, count, BFUSB_MAX_BLOCK_SIZE);
@@ -535,18 +536,18 @@
 	}
 
 	/* Don't send frame with multiple size of bulk max packet */
-	if ((nskb->len % data->bulk_pkt_size) == 0) {
+	if ((nskb->len % bfusb->bulk_pkt_size) == 0) {
 		buf[0] = 0xdd;
 		buf[1] = 0x00;
 		memcpy(skb_put(nskb, 2), buf, 2);
 	}
 
-	read_lock(&data->lock);
+	read_lock(&bfusb->lock);
 
-	skb_queue_tail(&data->transmit_q, nskb);
-	bfusb_tx_wakeup(data);
+	skb_queue_tail(&bfusb->transmit_q, nskb);
+	bfusb_tx_wakeup(bfusb);
 
-	read_unlock(&data->lock);
+	read_unlock(&bfusb->lock);
 
 	kfree_skb(skb);
 
@@ -555,11 +556,11 @@
 
 static void bfusb_destruct(struct hci_dev *hdev)
 {
-	struct bfusb_data *data = hdev->driver_data;
+	struct bfusb *bfusb = (struct bfusb *) hdev->driver_data;
 
-	BT_DBG("hdev %p bfusb %p", hdev, data);
+	BT_DBG("hdev %p bfusb %p", hdev, bfusb);
 
-	kfree(data);
+	kfree(bfusb);
 }
 
 static int bfusb_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
@@ -567,24 +568,25 @@
 	return -ENOIOCTLCMD;
 }
 
-static int bfusb_load_firmware(struct bfusb_data *data, unsigned char *firmware, int count)
+
+static int bfusb_load_firmware(struct bfusb *bfusb, unsigned char *firmware, int count)
 {
 	unsigned char *buf;
 	int err, pipe, len, size, sent = 0;
 
-	BT_DBG("bfusb %p udev %p", data, data->udev);
+	BT_DBG("bfusb %p udev %p", bfusb, bfusb->udev);
 
 	BT_INFO("BlueFRITZ! USB loading firmware");
 
-	pipe = usb_sndctrlpipe(data->udev, 0);
+	pipe = usb_sndctrlpipe(bfusb->udev, 0);
 
-	if (usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
+	if (usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION,
 				0, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT) < 0) {
 		BT_ERR("Can't change to loading configuration");
 		return -EBUSY;
 	}
 
-	data->udev->toggle[0] = data->udev->toggle[1] = 0;
+	bfusb->udev->toggle[0] = bfusb->udev->toggle[1] = 0;
 
 	buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_ATOMIC);
 	if (!buf) {
@@ -592,14 +594,14 @@
 		return -ENOMEM;
 	}
 
-	pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep);
+	pipe = usb_sndbulkpipe(bfusb->udev, bfusb->bulk_out_ep);
 
 	while (count) {
 		size = min_t(uint, count, BFUSB_MAX_BLOCK_SIZE + 3);
 
 		memcpy(buf, firmware + sent, size);
 
-		err = usb_bulk_msg(data->udev, pipe, buf, size,
+		err = usb_bulk_msg(bfusb->udev, pipe, buf, size,
 					&len, BFUSB_BLOCK_TIMEOUT);
 
 		if (err || (len != size)) {
@@ -611,23 +613,21 @@
 		count -= size;
 	}
 
-	err = usb_bulk_msg(data->udev, pipe, NULL, 0,
-					&len, BFUSB_BLOCK_TIMEOUT);
-	if (err < 0) {
+	if ((err = usb_bulk_msg(bfusb->udev, pipe, NULL, 0,
+				&len, BFUSB_BLOCK_TIMEOUT)) < 0) {
 		BT_ERR("Error in null packet request");
 		goto error;
 	}
 
-	pipe = usb_sndctrlpipe(data->udev, 0);
+	pipe = usb_sndctrlpipe(bfusb->udev, 0);
 
-	err = usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
-				0, 2, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
-	if (err < 0) {
+        if ((err = usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION,
+				0, 2, 0, NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) {
 		BT_ERR("Can't change to running configuration");
 		goto error;
 	}
 
-	data->udev->toggle[0] = data->udev->toggle[1] = 0;
+	bfusb->udev->toggle[0] = bfusb->udev->toggle[1] = 0;
 
 	BT_INFO("BlueFRITZ! USB device ready");
 
@@ -637,9 +637,9 @@
 error:
 	kfree(buf);
 
-	pipe = usb_sndctrlpipe(data->udev, 0);
+	pipe = usb_sndctrlpipe(bfusb->udev, 0);
 
-	usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
+	usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION,
 				0, 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
 
 	return err;
@@ -652,7 +652,7 @@
 	struct usb_host_endpoint *bulk_out_ep;
 	struct usb_host_endpoint *bulk_in_ep;
 	struct hci_dev *hdev;
-	struct bfusb_data *data;
+	struct bfusb *bfusb;
 
 	BT_DBG("intf %p id %p", intf, id);
 
@@ -672,24 +672,23 @@
 	}
 
 	/* Initialize control structure and load firmware */
-	data = kzalloc(sizeof(struct bfusb_data), GFP_KERNEL);
-	if (!data) {
+	if (!(bfusb = kzalloc(sizeof(struct bfusb), GFP_KERNEL))) {
 		BT_ERR("Can't allocate memory for control structure");
 		goto done;
 	}
 
-	data->udev = udev;
-	data->bulk_in_ep    = bulk_in_ep->desc.bEndpointAddress;
-	data->bulk_out_ep   = bulk_out_ep->desc.bEndpointAddress;
-	data->bulk_pkt_size = le16_to_cpu(bulk_out_ep->desc.wMaxPacketSize);
-
-	rwlock_init(&data->lock);
-
-	data->reassembly = NULL;
-
-	skb_queue_head_init(&data->transmit_q);
-	skb_queue_head_init(&data->pending_q);
-	skb_queue_head_init(&data->completed_q);
+	bfusb->udev = udev;
+	bfusb->bulk_in_ep    = bulk_in_ep->desc.bEndpointAddress;
+	bfusb->bulk_out_ep   = bulk_out_ep->desc.bEndpointAddress;
+	bfusb->bulk_pkt_size = le16_to_cpu(bulk_out_ep->desc.wMaxPacketSize);
+
+	rwlock_init(&bfusb->lock);
+
+	bfusb->reassembly = NULL;
+
+	skb_queue_head_init(&bfusb->transmit_q);
+	skb_queue_head_init(&bfusb->pending_q);
+	skb_queue_head_init(&bfusb->completed_q);
 
 	if (request_firmware(&firmware, "bfubase.frm", &udev->dev) < 0) {
 		BT_ERR("Firmware request failed");
@@ -698,7 +697,7 @@
 
 	BT_DBG("firmware data %p size %d", firmware->data, firmware->size);
 
-	if (bfusb_load_firmware(data, firmware->data, firmware->size) < 0) {
+	if (bfusb_load_firmware(bfusb, firmware->data, firmware->size) < 0) {
 		BT_ERR("Firmware loading failed");
 		goto release;
 	}
@@ -712,10 +711,10 @@
 		goto error;
 	}
 
-	data->hdev = hdev;
+	bfusb->hdev = hdev;
 
 	hdev->type = HCI_USB;
-	hdev->driver_data = data;
+	hdev->driver_data = bfusb;
 	SET_HCIDEV_DEV(hdev, &intf->dev);
 
 	hdev->open     = bfusb_open;
@@ -733,7 +732,7 @@
 		goto error;
 	}
 
-	usb_set_intfdata(intf, data);
+	usb_set_intfdata(intf, bfusb);
 
 	return 0;
 
@@ -741,7 +740,7 @@
 	release_firmware(firmware);
 
 error:
-	kfree(data);
+	kfree(bfusb);
 
 done:
 	return -EIO;
@@ -749,8 +748,8 @@
 
 static void bfusb_disconnect(struct usb_interface *intf)
 {
-	struct bfusb_data *data = usb_get_intfdata(intf);
-	struct hci_dev *hdev = data->hdev;
+	struct bfusb *bfusb = usb_get_intfdata(intf);
+	struct hci_dev *hdev = bfusb->hdev;
 
 	BT_DBG("intf %p", intf);
 
@@ -780,8 +779,7 @@
 
 	BT_INFO("BlueFRITZ! USB driver ver %s", VERSION);
 
-	err = usb_register(&bfusb_driver);
-	if (err < 0)
+	if ((err = usb_register(&bfusb_driver)) < 0)
 		BT_ERR("Failed to register BlueFRITZ! USB driver");
 
 	return err;
diff -ur --exclude-from=kernel-diff-exclude.txt linux-2.6.18-mh1/drivers/bluetooth/hci_ldisc.c linux-2.6.18-my-bt/drivers/bluetooth/hci_ldisc.c
--- linux-2.6.18-mh1/drivers/bluetooth/hci_ldisc.c	2006-09-23 19:59:12.000000000 -0700
+++ linux-2.6.18-my-bt/drivers/bluetooth/hci_ldisc.c	2006-09-23 22:53:14.000000000 -0700
@@ -241,11 +241,15 @@
 
 static void hci_uart_destruct(struct hci_dev *hdev)
 {
+	struct hci_uart *hu;
+
 	if (!hdev)
 		return;
 
 	BT_DBG("%s", hdev->name);
-	kfree(hdev->driver_data);
+
+	hu = (struct hci_uart *) hdev->driver_data;
+	kfree(hu);
 }
 
 /* ------ LDISC part ------ */
@@ -268,7 +272,7 @@
 		return -EEXIST;
 
 	if (!(hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL))) {
-		BT_ERR("Can't allocate control structure");
+		BT_ERR("Can't allocate controll structure");
 		return -ENFILE;
 	}
 
@@ -356,7 +360,7 @@
  *     
  * Return Value:    None
  */
-static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
+static void hci_uart_tty_receive(struct tty_struct *tty, const __u8 *data, char *flags, int count)
 {
 	struct hci_uart *hu = (void *)tty->disc_data;
 
@@ -371,8 +375,7 @@
 	hu->hdev->stat.byte_rx += count;
 	spin_unlock(&hu->rx_lock);
 
-	if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
-					tty->driver->unthrottle)
+	if (test_and_clear_bit(TTY_THROTTLED,&tty->flags) && tty->driver->unthrottle)
 		tty->driver->unthrottle(tty);
 }
 
diff -ur --exclude-from=kernel-diff-exclude.txt linux-2.6.18-mh1/drivers/bluetooth/hci_usb.c linux-2.6.18-my-bt/drivers/bluetooth/hci_usb.c
--- linux-2.6.18-mh1/drivers/bluetooth/hci_usb.c	2006-09-23 19:59:11.000000000 -0700
+++ linux-2.6.18-my-bt/drivers/bluetooth/hci_usb.c	2006-09-23 22:53:13.000000000 -0700
@@ -96,9 +96,6 @@
 	/* Ericsson with non-standard id */
 	{ USB_DEVICE(0x0bdb, 0x1002) },
 
-	/* Canyon CN-BTU1 with HID interfaces */
-	{ USB_DEVICE(0x0c10, 0x0000), .driver_info = HCI_RESET },
-
 	{ }	/* Terminating entry */
 };
 
diff -ur --exclude-from=kernel-diff-exclude.txt linux-2.6.18-mh1/drivers/bluetooth/hci_vhci.c linux-2.6.18-my-bt/drivers/bluetooth/hci_vhci.c
--- linux-2.6.18-mh1/drivers/bluetooth/hci_vhci.c	2006-09-23 19:59:12.000000000 -0700
+++ linux-2.6.18-my-bt/drivers/bluetooth/hci_vhci.c	2006-09-23 22:53:14.000000000 -0700
@@ -2,9 +2,9 @@
  *
  *  Bluetooth virtual HCI driver
  *
- *  Copyright (C) 2000-2001  Qualcomm Incorporated
- *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
- *  Copyright (C) 2004-2006  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2000-2001 Qualcomm Incorporated
+ *  Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
+ *  Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -72,21 +72,21 @@
 
 static int vhci_close_dev(struct hci_dev *hdev)
 {
-	struct vhci_data *data = hdev->driver_data;
+	struct vhci_data *vhci = hdev->driver_data;
 
 	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
 		return 0;
 
-	skb_queue_purge(&data->readq);
+	skb_queue_purge(&vhci->readq);
 
 	return 0;
 }
 
 static int vhci_flush(struct hci_dev *hdev)
 {
-	struct vhci_data *data = hdev->driver_data;
+	struct vhci_data *vhci = hdev->driver_data;
 
-	skb_queue_purge(&data->readq);
+	skb_queue_purge(&vhci->readq);
 
 	return 0;
 }
@@ -94,7 +94,7 @@
 static int vhci_send_frame(struct sk_buff *skb)
 {
 	struct hci_dev* hdev = (struct hci_dev *) skb->dev;
-	struct vhci_data *data;
+	struct vhci_data *vhci;
 
 	if (!hdev) {
 		BT_ERR("Frame for unknown HCI device (hdev=NULL)");
@@ -104,15 +104,15 @@
 	if (!test_bit(HCI_RUNNING, &hdev->flags))
 		return -EBUSY;
 
-	data = hdev->driver_data;
+	vhci = hdev->driver_data;
 
 	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
-	skb_queue_tail(&data->readq, skb);
+	skb_queue_tail(&vhci->readq, skb);
 
-	if (data->flags & VHCI_FASYNC)
-		kill_fasync(&data->fasync, SIGIO, POLL_IN);
+	if (vhci->flags & VHCI_FASYNC)
+		kill_fasync(&vhci->fasync, SIGIO, POLL_IN);
 
-	wake_up_interruptible(&data->read_wait);
+	wake_up_interruptible(&vhci->read_wait);
 
 	return 0;
 }
@@ -122,7 +122,7 @@
 	kfree(hdev->driver_data);
 }
 
-static inline ssize_t vhci_get_user(struct vhci_data *data,
+static inline ssize_t vhci_get_user(struct vhci_data *vhci,
 					const char __user *buf, size_t count)
 {
 	struct sk_buff *skb;
@@ -139,7 +139,7 @@
 		return -EFAULT;
 	}
 
-	skb->dev = (void *) data->hdev;
+	skb->dev = (void *) vhci->hdev;
 	bt_cb(skb)->pkt_type = *((__u8 *) skb->data);
 	skb_pull(skb, 1);
 
@@ -148,7 +148,7 @@
 	return count;
 }
 
-static inline ssize_t vhci_put_user(struct vhci_data *data,
+static inline ssize_t vhci_put_user(struct vhci_data *vhci,
 			struct sk_buff *skb, char __user *buf, int count)
 {
 	char __user *ptr = buf;
@@ -161,43 +161,42 @@
 
 	total += len;
 
-	data->hdev->stat.byte_tx += len;
+	vhci->hdev->stat.byte_tx += len;
 
 	switch (bt_cb(skb)->pkt_type) {
 	case HCI_COMMAND_PKT:
-		data->hdev->stat.cmd_tx++;
+		vhci->hdev->stat.cmd_tx++;
 		break;
 
 	case HCI_ACLDATA_PKT:
-		data->hdev->stat.acl_tx++;
+		vhci->hdev->stat.acl_tx++;
 		break;
 
 	case HCI_SCODATA_PKT:
-		data->hdev->stat.cmd_tx++;
+		vhci->hdev->stat.cmd_tx++;
 		break;
 	};
 
 	return total;
 }
 
-static loff_t vhci_llseek(struct file *file, loff_t offset, int origin)
+static loff_t vhci_llseek(struct file * file, loff_t offset, int origin)
 {
 	return -ESPIPE;
 }
 
-static ssize_t vhci_read(struct file *file,
-				char __user *buf, size_t count, loff_t *pos)
+static ssize_t vhci_read(struct file * file, char __user * buf, size_t count, loff_t *pos)
 {
 	DECLARE_WAITQUEUE(wait, current);
-	struct vhci_data *data = file->private_data;
+	struct vhci_data *vhci = file->private_data;
 	struct sk_buff *skb;
 	ssize_t ret = 0;
 
-	add_wait_queue(&data->read_wait, &wait);
+	add_wait_queue(&vhci->read_wait, &wait);
 	while (count) {
 		set_current_state(TASK_INTERRUPTIBLE);
 
-		skb = skb_dequeue(&data->readq);
+		skb = skb_dequeue(&vhci->readq);
 		if (!skb) {
 			if (file->f_flags & O_NONBLOCK) {
 				ret = -EAGAIN;
@@ -214,7 +213,7 @@
 		}
 
 		if (access_ok(VERIFY_WRITE, buf, count))
-			ret = vhci_put_user(data, skb, buf, count);
+			ret = vhci_put_user(vhci, skb, buf, count);
 		else
 			ret = -EFAULT;
 
@@ -222,7 +221,7 @@
 		break;
 	}
 	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&data->read_wait, &wait);
+	remove_wait_queue(&vhci->read_wait, &wait);
 
 	return ret;
 }
@@ -230,21 +229,21 @@
 static ssize_t vhci_write(struct file *file,
 			const char __user *buf, size_t count, loff_t *pos)
 {
-	struct vhci_data *data = file->private_data;
+	struct vhci_data *vhci = file->private_data;
 
 	if (!access_ok(VERIFY_READ, buf, count))
 		return -EFAULT;
 
-	return vhci_get_user(data, buf, count);
+	return vhci_get_user(vhci, buf, count);
 }
 
 static unsigned int vhci_poll(struct file *file, poll_table *wait)
 {
-	struct vhci_data *data = file->private_data;
+	struct vhci_data *vhci = file->private_data;
 
-	poll_wait(file, &data->read_wait, wait);
+	poll_wait(file, &vhci->read_wait, wait);
 
-	if (!skb_queue_empty(&data->readq))
+	if (!skb_queue_empty(&vhci->readq))
 		return POLLIN | POLLRDNORM;
 
 	return POLLOUT | POLLWRNORM;
@@ -258,26 +257,26 @@
 
 static int vhci_open(struct inode *inode, struct file *file)
 {
-	struct vhci_data *data;
+	struct vhci_data *vhci;
 	struct hci_dev *hdev;
 
-	data = kzalloc(sizeof(struct vhci_data), GFP_KERNEL);
-	if (!data)
+	vhci = kzalloc(sizeof(struct vhci_data), GFP_KERNEL);
+	if (!vhci)
 		return -ENOMEM;
 
-	skb_queue_head_init(&data->readq);
-	init_waitqueue_head(&data->read_wait);
+	skb_queue_head_init(&vhci->readq);
+	init_waitqueue_head(&vhci->read_wait);
 
 	hdev = hci_alloc_dev();
 	if (!hdev) {
-		kfree(data);
+		kfree(vhci);
 		return -ENOMEM;
 	}
 
-	data->hdev = hdev;
+	vhci->hdev = hdev;
 
-	hdev->type = HCI_VIRTUAL;
-	hdev->driver_data = data;
+	hdev->type = HCI_VHCI;
+	hdev->driver_data = vhci;
 
 	hdev->open     = vhci_open_dev;
 	hdev->close    = vhci_close_dev;
@@ -289,20 +288,20 @@
 
 	if (hci_register_dev(hdev) < 0) {
 		BT_ERR("Can't register HCI device");
-		kfree(data);
+		kfree(vhci);
 		hci_free_dev(hdev);
 		return -EBUSY;
 	}
 
-	file->private_data = data;
+	file->private_data = vhci;
 
 	return nonseekable_open(inode, file);
 }
 
 static int vhci_release(struct inode *inode, struct file *file)
 {
-	struct vhci_data *data = file->private_data;
-	struct hci_dev *hdev = data->hdev;
+	struct vhci_data *vhci = file->private_data;
+	struct hci_dev *hdev = vhci->hdev;
 
 	if (hci_unregister_dev(hdev) < 0) {
 		BT_ERR("Can't unregister HCI device %s", hdev->name);
@@ -317,17 +316,17 @@
 
 static int vhci_fasync(int fd, struct file *file, int on)
 {
-	struct vhci_data *data = file->private_data;
+	struct vhci_data *vhci = file->private_data;
 	int err;
 
-	err = fasync_helper(fd, file, on, &data->fasync);
+	err = fasync_helper(fd, file, on, &vhci->fasync);
 	if (err < 0)
 		return err;
 
 	if (on)
-		data->flags |= VHCI_FASYNC;
+		vhci->flags |= VHCI_FASYNC;
 	else
-		data->flags &= ~VHCI_FASYNC;
+		vhci->flags &= ~VHCI_FASYNC;
 
 	return 0;
 }

diff -ur --exclude-from=kernel-diff-exclude.txt linux-2.6.18-mh1/include/net/bluetooth/hci_core.h linux-2.6.18-my-bt/include/net/bluetooth/hci_core.h
--- linux-2.6.18-mh1/include/net/bluetooth/hci_core.h	2006-09-23 20:00:59.000000000 -0700
+++ linux-2.6.18-my-bt/include/net/bluetooth/hci_core.h	2006-09-23 22:54:33.000000000 -0700
@@ -165,10 +165,6 @@
 	struct timer_list disc_timer;
 	struct timer_list idle_timer;
 
-	struct work_struct work;
-
-	struct device	dev;
-
 	struct hci_dev	*hdev;
 	void		*l2cap_data;
 	void		*sco_data;
@@ -416,8 +412,6 @@
 
 int hci_register_sysfs(struct hci_dev *hdev);
 void hci_unregister_sysfs(struct hci_dev *hdev);
-void hci_conn_add_sysfs(struct hci_conn *conn);
-void hci_conn_del_sysfs(struct hci_conn *conn);
 
 #define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->parent = (pdev))
 
diff -ur --exclude-from=kernel-diff-exclude.txt linux-2.6.18-mh1/include/net/bluetooth/hci.h linux-2.6.18-my-bt/include/net/bluetooth/hci.h
--- linux-2.6.18-mh1/include/net/bluetooth/hci.h	2006-09-23 20:00:59.000000000 -0700
+++ linux-2.6.18-my-bt/include/net/bluetooth/hci.h	2006-09-23 22:54:33.000000000 -0700
@@ -44,13 +44,12 @@
 #define HCI_NOTIFY_VOICE_SETTING	3
 
 /* HCI device types */
-#define HCI_VIRTUAL	0
+#define HCI_VHCI	0
 #define HCI_USB		1
 #define HCI_PCCARD	2
 #define HCI_UART	3
 #define HCI_RS232	4
 #define HCI_PCI		5
-#define HCI_SDIO	6
 
 /* HCI device quirks */
 enum {
@@ -340,8 +339,6 @@
 
 #define OCF_INQUIRY_CANCEL	0x0002
 
-#define OCF_EXIT_PERIODIC_INQ	0x0004
-
 #define OCF_LINK_KEY_REPLY	0x000B
 struct hci_cp_link_key_reply {
 	bdaddr_t bdaddr;
diff -ur --exclude-from=kernel-diff-exclude.txt linux-2.6.18-mh1/include/net/bluetooth/l2cap.h linux-2.6.18-my-bt/include/net/bluetooth/l2cap.h
--- linux-2.6.18-mh1/include/net/bluetooth/l2cap.h	2006-09-23 20:00:59.000000000 -0700
+++ linux-2.6.18-my-bt/include/net/bluetooth/l2cap.h	2006-09-23 23:00:22.000000000 -0700
@@ -27,19 +27,7 @@
 
 /* L2CAP defaults */
 #define L2CAP_DEFAULT_MTU	672
-#define L2CAP_MIN_MTU		48
 #define L2CAP_DEFAULT_FLUSH_TO	0xFFFF
-#define L2CAP_DEFAULT_TXW 	32
-#define L2CAP_MIN_TXW		1
-#define L2CAP_MAX_TXW		32
-#define L2CAP_DEFAULT_MAXT 	32
-#define L2CAP_DEFAULT_RETTO 	1000
-#define L2CAP_DEFAULT_MONTO 	1000
-#define L2CAP_DEFAULT_MPS 	65531
-#define L2CAP_MAX_MPS		65531
-
-/* maximum possible options for one request/response */
-#define L2CAP_MAX_OPTS 		128
 
 #define L2CAP_CONN_TIMEOUT	(HZ * 40)
 
@@ -59,10 +47,6 @@
 	__u8  mode;
 };
 
-#define L2CAP_MODE_BASIC	0x00
-#define L2CAP_MODE_RET		0x01
-#define L2CAP_MODE_FLOW		0x02
-
 #define L2CAP_CONNINFO	0x02
 struct l2cap_conninfo {
 	__u16 hci_handle;
@@ -106,14 +90,8 @@
 
 struct l2cap_cmd_rej {
 	__le16     reason;
-	__le16     data[0];
 } __attribute__ ((packed));
 
-/* command reject reasons */
-#define L2CAP_CMD_NOT_UNDERSTOOD 	0x0000
-#define L2CAP_MTU_EXCEEDED 		0x0001
-#define L2CAP_INVALID_CID 		0x0002
-
 struct l2cap_conn_req {
 	__le16     psm;
 	__le16     scid;
@@ -151,10 +129,8 @@
 	__u8       data[0];
 } __attribute__ ((packed));
 
-#define L2CAP_CONF_SUCCESS	0x0000
-#define L2CAP_CONF_UNACCEPT	0x0001
-#define L2CAP_CONF_REJ		0x0002
-#define L2CAP_CONF_UNKNOWN	0x0003
+#define L2CAP_CONF_SUCCESS	0x00
+#define L2CAP_CONF_UNACCEPT	0x01
 
 struct l2cap_conf_opt {
 	__u8       type;
@@ -170,15 +146,6 @@
 
 #define L2CAP_CONF_MAX_SIZE	22
 
-struct l2cap_conf_rfc {
-	__u8	mode;
-	__u8	txw;
-	__u8	maxt;
-	__le16	ret_to;
-	__le16	mon_to;
-	__le16	mps;
-} __attribute__ ((packed));
-
 struct l2cap_disconn_req {
 	__le16     dcid;
 	__le16     scid;
@@ -191,6 +158,7 @@
 
 struct l2cap_info_req {
 	__le16      type;
+	__u8        data[0];
 } __attribute__ ((packed));
 
 struct l2cap_info_rsp {
@@ -200,17 +168,12 @@
 } __attribute__ ((packed));
 
 /* info type */
-#define L2CAP_IT_CL_MTU		0x0001
-#define L2CAP_IT_FEAT_MASK	0x0002
-
-/* bits for extended features */
-#define L2CAP_EXT_FCM		0x0001
-#define L2CAP_EXT_RTM		0x0002
-#define L2CAP_EXT_QOS		0x0004
+#define L2CAP_IT_CL_MTU     0x0001
+#define L2CAP_IT_FEAT_MASK  0x0002
 
 /* info result */
-#define L2CAP_IR_SUCCESS	0x0000
-#define L2CAP_IR_NOTSUPP	0x0001
+#define L2CAP_IR_SUCCESS    0x0000
+#define L2CAP_IR_NOTSUPP    0x0001
 
 /* ----- L2CAP connections ----- */
 struct l2cap_chan_list {
@@ -250,103 +213,24 @@
 	__u16		imtu;
 	__u16		omtu;
 	__u16		flush_to;
-	__u8		mode;
 
 	__u32		link_mode;
-	/* connectionless MTU size from info response */
-	__u16		info_mtu;
-	/* extended feature mask from info response */
-	__u32		info_ext;
 
-	/* bitmask for current config state */
-	__u16		conf_state;
+	__u8		conf_state;
 	__u8		conf_retry;
 	__u16		conf_mtu;
 
-	/* Configuration Request RFC Options */
-	__u8		conf_mode;
-	__u8		conf_txw;
-	__u8		conf_maxt;
-	__u16		conf_ret_to;
-	__u16		conf_mon_to;
-	__u16		conf_mps;
-
-	/* incoming RFC Options */
-	__u8		itxw;
-	__u8		imaxt;
-	__u16		iret_to;
-	__u16		imon_to;
-	__u16		imps;
-
-	/* outgoing RFC Options */
-	__u8		otxw;
-	__u8		omaxt;
-	__u16		oret_to;
-	__u16		omon_to;
-	__u16		omps;
-
-	/* flow control mode */
-	__u8		tx_seq;
-	__u8		next_txseq;
-	__u8		exp_ackseq;
-	__u8		req_seq;
-	__u8		exp_txseq;
-	__u8		buffer_seq;
-	__u16		sdu_len;
-	struct sk_buff	*sdu;
-
-	__u32			tx_queue_frames;
-	struct sk_buff_head 	tx_queue;
-
 	__u8		ident;
 
-	struct timer_list	ret_timer;
-	struct timer_list	mon_timer;
 	struct l2cap_conn	*conn;
 	struct sock		*next_c;
 	struct sock		*prev_c;
 };
 
-#define L2CAP_CONF_MAX_RETRIES	2
-
-/* different conf_states */
-#define L2CAP_INFO_REQ_SENT 	0x01
-#define L2CAP_CONF_REQ_SENT 	0x02
-#define L2CAP_CONF_INPUT_DONE	0x04
-#define L2CAP_CONF_OUTPUT_DONE	0x08
-#define L2CAP_CONF_UNACCEPT_MTU	0x10
-#define L2CAP_CONF_UNACCEPT_RFC	0x20
-#define L2CAP_INFO_INPUT_DONE	0x40
-
-/* RFC definitions */
-#define L2CAP_MAX_DATA_LEN	65531
-#define L2CAP_CONTROL_SIZE	2
-#define L2CAP_FCS_SIZE		2
-#define L2CAP_SFRAME_SIZE	8
-
-#define L2CAP_SAR_UNSEGMENTED	0x0000
-#define L2CAP_SAR_START		0x4000
-#define L2CAP_SAR_END		0x8000
-#define L2CAP_SAR_CONTINUE	0xC000
-#define L2CAP_SAR_MASK		0xC000
-#define L2CAP_TXSEQ_MASK	0x007E
-#define L2CAP_REQSEQ_MASK	0x3F00
-
-#define L2CAP_GET_TXSEQ(control)	((__le16_to_cpu(control) \
-			& L2CAP_TXSEQ_MASK) >> 1)
-#define L2CAP_GET_REQSEQ(control)	((__le16_to_cpu(control) \
-			& L2CAP_REQSEQ_MASK) >> 8)
-#define L2CAP_GET_SAR(control)		(__le16_to_cpu(control) & L2CAP_SAR_MASK)
-
-#define L2CAP_SET_TXSEQ(control, txseq) 	control = \
-			(__cpu_to_le16((txseq  << 1) & L2CAP_TXSEQ_MASK)) | \
-			(__cpu_to_le16(control) & ~L2CAP_TXSEQ_MASK)
-#define L2CAP_SET_REQSEQ(control, reqseq) 	control = \
-			(__cpu_to_le16((reqseq << 8) & L2CAP_REQSEQ_MASK)) | \
-			(__cpu_to_le16(control) & ~L2CAP_REQSEQ_MASK)
-#define L2CAP_SET_SAR(control, sar) 		control = \
-			(__cpu_to_le16(sar & L2CAP_SAR_MASK)) |           \
-			(__cpu_to_le16(control) & ~L2CAP_SAR_MASK)
+#define L2CAP_CONF_REQ_SENT    0x01
+#define L2CAP_CONF_INPUT_DONE  0x02
+#define L2CAP_CONF_OUTPUT_DONE 0x04
+#define L2CAP_CONF_MAX_RETRIES 2
 
 void l2cap_load(void);
 
diff -ur --exclude-from=kernel-diff-exclude.txt linux-2.6.18-mh1/Makefile linux-2.6.18-my-bt/Makefile
--- linux-2.6.18-mh1/Makefile	2006-09-23 19:55:32.000000000 -0700
+++ linux-2.6.18-my-bt/Makefile	2006-09-24 00:24:58.000000000 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 18
-EXTRAVERSION = -mh1
+EXTRAVERSION = -mh1aj
 NAME=Avast! A bilge rat!
 
 # *DOCUMENTATION*
diff -ur --exclude-from=kernel-diff-exclude.txt linux-2.6.18-mh1/net/bluetooth/bnep/bnep.h linux-2.6.18-my-bt/net/bluetooth/bnep/bnep.h
--- linux-2.6.18-mh1/net/bluetooth/bnep/bnep.h	2006-09-23 19:56:07.000000000 -0700
+++ linux-2.6.18-my-bt/net/bluetooth/bnep/bnep.h	2006-09-23 23:00:22.000000000 -0700
@@ -86,29 +86,29 @@
 #define BNEP_EXT_HEADER	 0x80
 
 struct bnep_setup_conn_req {
-	__u8  type;
-	__u8  ctrl;
-	__u8  uuid_size;
-	__u8  service[0];
+	__u8   type;
+	__u8   ctrl;
+	__u8   uuid_size;
+	__u8   service[0];
 } __attribute__((packed));
 
 struct bnep_set_filter_req {
-	__u8  type;
-	__u8  ctrl;
-	__u16 len;
-	__u8  list[0];
+	__u8   type;
+	__u8   ctrl;
+	__le16 len;
+	__u8   list[0];
 } __attribute__((packed));
 
 struct bnep_control_rsp {
-	__u8  type;
-	__u8  ctrl;
-	__u16 resp;
+	__u8   type;
+	__u8   ctrl;
+	__le16 resp;
 } __attribute__((packed));
 
 struct bnep_ext_hdr {
-	__u8  type;
-	__u8  len;
-	__u8  data[0];
+	__u8   type;
+	__u8   len;
+	__u8   data[0];
 } __attribute__((packed));
 
 /* BNEP ioctl defines */
diff -ur --exclude-from=kernel-diff-exclude.txt linux-2.6.18-mh1/net/bluetooth/bnep/core.c linux-2.6.18-my-bt/net/bluetooth/bnep/core.c
--- linux-2.6.18-mh1/net/bluetooth/bnep/core.c	2006-09-23 19:56:06.000000000 -0700
+++ linux-2.6.18-my-bt/net/bluetooth/bnep/core.c	2006-09-23 22:46:43.000000000 -0700
@@ -51,7 +51,6 @@
 #include <asm/unaligned.h>
 
 #include <net/bluetooth/bluetooth.h>
-#include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
 
 #include "bnep.h"
@@ -516,26 +515,6 @@
 	return 0;
 }
 
-static struct device *bnep_get_device(struct bnep_session *session)
-{
-	bdaddr_t *src = &bt_sk(session->sock->sk)->src;
-	bdaddr_t *dst = &bt_sk(session->sock->sk)->dst;
-	struct hci_dev *hdev;
-	struct hci_conn *conn;
-
-	hdev = hci_get_route(dst, src);
-	if (!hdev)
-		return NULL;
-
-	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
-	if (!conn)
-		return NULL;
-
-	hci_dev_put(hdev);
-
-	return &conn->dev;
-}
-
 int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
 {
 	struct net_device *dev;
@@ -555,6 +534,7 @@
 	if (!dev)
 		return -ENOMEM;
 
+
 	down_write(&bnep_session_sem);
 
 	ss = __bnep_get_session(dst);
@@ -571,7 +551,7 @@
 	memcpy(s->eh.h_source, &dst, ETH_ALEN);
 	memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN);
 
-	s->dev   = dev;
+	s->dev = dev;
 	s->sock  = sock;
 	s->role  = req->role;
 	s->state = BT_CONNECTED;
@@ -588,8 +568,6 @@
 	bnep_set_default_proto_filter(s);
 #endif
 
-	SET_NETDEV_DEV(dev, bnep_get_device(s));
-
 	err = register_netdev(dev);
 	if (err) {
 		goto failed;
diff -ur --exclude-from=kernel-diff-exclude.txt linux-2.6.18-mh1/net/bluetooth/hci_conn.c linux-2.6.18-my-bt/net/bluetooth/hci_conn.c
--- linux-2.6.18-mh1/net/bluetooth/hci_conn.c	2006-09-23 19:56:08.000000000 -0700
+++ linux-2.6.18-my-bt/net/bluetooth/hci_conn.c	2006-09-23 22:46:43.000000000 -0700
@@ -179,8 +179,6 @@
 	if (hdev->notify)
 		hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
 
-	hci_conn_add_sysfs(conn);
-
 	tasklet_enable(&hdev->tx_task);
 
 	return conn;
@@ -213,8 +211,6 @@
 
 	tasklet_disable(&hdev->tx_task);
 
-	hci_conn_del_sysfs(conn);
-
 	hci_conn_hash_del(hdev, conn);
 	if (hdev->notify)
 		hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
@@ -225,9 +221,7 @@
 
 	hci_dev_put(hdev);
 
-	/* will free via device release */
-	put_device(&conn->dev);
-
+	kfree(conn);
 	return 0;
 }
 
diff -ur --exclude-from=kernel-diff-exclude.txt linux-2.6.18-mh1/net/bluetooth/hci_core.c linux-2.6.18-my-bt/net/bluetooth/hci_core.c
--- linux-2.6.18-mh1/net/bluetooth/hci_core.c	2006-09-23 19:56:07.000000000 -0700
+++ linux-2.6.18-my-bt/net/bluetooth/hci_core.c	2006-09-23 22:46:43.000000000 -0700
@@ -850,7 +850,7 @@
 	hdev->pkt_type  = (HCI_DM1 | HCI_DH1 | HCI_HV1);
 	hdev->link_mode = (HCI_LM_ACCEPT);
 
-	hdev->idle_timeout = HCI_IDLE_TIMEOUT;
+	hdev->idle_timeout = 0;
 	hdev->sniff_max_interval = 800;
 	hdev->sniff_min_interval = 80;
 
diff -ur --exclude-from=kernel-diff-exclude.txt linux-2.6.18-mh1/net/bluetooth/hci_event.c linux-2.6.18-my-bt/net/bluetooth/hci_event.c
--- linux-2.6.18-mh1/net/bluetooth/hci_event.c	2006-09-23 19:56:06.000000000 -0700
+++ linux-2.6.18-my-bt/net/bluetooth/hci_event.c	2006-09-23 22:46:43.000000000 -0700
@@ -62,7 +62,6 @@
 
 	switch (ocf) {
 	case OCF_INQUIRY_CANCEL:
-	case OCF_EXIT_PERIODIC_INQ:
 		status = *((__u8 *) skb->data);
 
 		if (status) {
diff -ur --exclude-from=kernel-diff-exclude.txt linux-2.6.18-mh1/net/bluetooth/hci_sysfs.c linux-2.6.18-my-bt/net/bluetooth/hci_sysfs.c
--- linux-2.6.18-mh1/net/bluetooth/hci_sysfs.c	2006-09-23 19:56:06.000000000 -0700
+++ linux-2.6.18-my-bt/net/bluetooth/hci_sysfs.c	2006-09-23 22:46:43.000000000 -0700
@@ -13,32 +13,16 @@
 #define BT_DBG(D...)
 #endif
 
-static inline char *typetostr(int type)
+static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
 {
-	switch (type) {
-	case HCI_VIRTUAL:
-		return "VIRTUAL";
-	case HCI_USB:
-		return "USB";
-	case HCI_PCCARD:
-		return "PCCARD";
-	case HCI_UART:
-		return "UART";
-	case HCI_RS232:
-		return "RS232";
-	case HCI_PCI:
-		return "PCI";
-	case HCI_SDIO:
-		return "SDIO";
-	default:
-		return "UNKNOWN";
-	}
+	struct hci_dev *hdev = dev_get_drvdata(dev);
+	return sprintf(buf, "%s\n", hdev->name);
 }
 
 static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct hci_dev *hdev = dev_get_drvdata(dev);
-	return sprintf(buf, "%s\n", typetostr(hdev->type));
+	return sprintf(buf, "%d\n", hdev->type);
 }
 
 static ssize_t show_address(struct device *dev, struct device_attribute *attr, char *buf)
@@ -49,6 +33,12 @@
 	return sprintf(buf, "%s\n", batostr(&bdaddr));
 }
 
+static ssize_t show_flags(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct hci_dev *hdev = dev_get_drvdata(dev);
+	return sprintf(buf, "0x%lx\n", hdev->flags);
+}
+
 static ssize_t show_inquiry_cache(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct hci_dev *hdev = dev_get_drvdata(dev);
@@ -151,8 +141,10 @@
 	return count;
 }
 
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
 static DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
+static DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL);
 static DEVICE_ATTR(inquiry_cache, S_IRUGO, show_inquiry_cache, NULL);
 
 static DEVICE_ATTR(idle_timeout, S_IRUGO | S_IWUSR,
@@ -163,8 +155,10 @@
 				show_sniff_min_interval, store_sniff_min_interval);
 
 static struct device_attribute *bt_attrs[] = {
+	&dev_attr_name,
 	&dev_attr_type,
 	&dev_attr_address,
+	&dev_attr_flags,
 	&dev_attr_inquiry_cache,
 	&dev_attr_idle_timeout,
 	&dev_attr_sniff_max_interval,
@@ -172,32 +166,6 @@
 	NULL
 };
 
-static ssize_t show_conn_type(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct hci_conn *conn = dev_get_drvdata(dev);
-	return sprintf(buf, "%s\n", conn->type == ACL_LINK ? "ACL" : "SCO");
-}
-
-static ssize_t show_conn_address(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct hci_conn *conn = dev_get_drvdata(dev);
-	bdaddr_t bdaddr;
-	baswap(&bdaddr, &conn->dst);
-	return sprintf(buf, "%s\n", batostr(&bdaddr));
-}
-
-#define CONN_ATTR(_name,_mode,_show,_store) \
-struct device_attribute conn_attr_##_name = __ATTR(_name,_mode,_show,_store)
-
-static CONN_ATTR(type, S_IRUGO, show_conn_type, NULL);
-static CONN_ATTR(address, S_IRUGO, show_conn_address, NULL);
-
-static struct device_attribute *conn_attrs[] = {
-	&conn_attr_type,
-	&conn_attr_address,
-	NULL
-};
-
 struct class *bt_class = NULL;
 EXPORT_SYMBOL_GPL(bt_class);
 
@@ -209,57 +177,8 @@
 
 static void bt_release(struct device *dev)
 {
-	void *data = dev_get_drvdata(dev);
-	kfree(data);
-}
-
-static void add_conn(void *data)
-{
-	struct hci_conn *conn = data;
-	int i;
-
-	device_register(&conn->dev);
-
-	for (i = 0; conn_attrs[i]; i++)
-		device_create_file(&conn->dev, conn_attrs[i]);
-}
-
-void hci_conn_add_sysfs(struct hci_conn *conn)
-{
-	struct hci_dev *hdev = conn->hdev;
-	bdaddr_t *ba = &conn->dst;
-
-	BT_DBG("conn %p", conn);
-
-	conn->dev.parent  = &hdev->dev;
-	conn->dev.release = bt_release;
-
-	snprintf(conn->dev.bus_id, BUS_ID_SIZE,
-			"%s%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
-			conn->type == ACL_LINK ? "acl" : "sco",
-			ba->b[5], ba->b[4], ba->b[3],
-			ba->b[2], ba->b[1], ba->b[0]);
-
-	dev_set_drvdata(&conn->dev, conn);
-
-	INIT_WORK(&conn->work, add_conn, (void *) conn);
-
-	schedule_work(&conn->work);
-}
-
-static void del_conn(void *data)
-{
-	struct hci_conn *conn = data;
-	device_del(&conn->dev);
-}
-
-void hci_conn_del_sysfs(struct hci_conn *conn)
-{
-	BT_DBG("conn %p", conn);
-
-	INIT_WORK(&conn->work, del_conn, (void *) conn);
-
-	schedule_work(&conn->work);
+	struct hci_dev *hdev = dev_get_drvdata(dev);
+	kfree(hdev);
 }
 
 int hci_register_sysfs(struct hci_dev *hdev)
@@ -295,9 +214,11 @@
 
 void hci_unregister_sysfs(struct hci_dev *hdev)
 {
+	struct device *dev = &hdev->dev;
+
 	BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
 
-	device_del(&hdev->dev);
+	device_del(dev);
 }
 
 int __init bt_sysfs_init(void)
diff -ur --exclude-from=kernel-diff-exclude.txt linux-2.6.18-mh1/net/bluetooth/hidp/core.c linux-2.6.18-my-bt/net/bluetooth/hidp/core.c
--- linux-2.6.18-mh1/net/bluetooth/hidp/core.c	2006-09-23 19:56:07.000000000 -0700
+++ linux-2.6.18-my-bt/net/bluetooth/hidp/core.c	2006-09-23 23:00:22.000000000 -0700
@@ -41,7 +41,6 @@
 #include "hid.h"
 
 #include <net/bluetooth/bluetooth.h>
-#include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
 
 #include "hidp.h"
@@ -573,26 +572,6 @@
 	return 0;
 }
 
-static struct device *hidp_get_device(struct hidp_session *session)
-{
-	bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
-	bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
-	struct hci_dev *hdev;
-	struct hci_conn *conn;
-
-	hdev = hci_get_route(dst, src);
-	if (!hdev)
-		return NULL;
-
-	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
-	if (!conn)
-		return NULL;
-
-	hci_dev_put(hdev);
-
-	return &conn->dev;
-}
-
 static inline void hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req)
 {
 	struct input_dev *input = session->input;
@@ -631,8 +610,6 @@
 		input->relbit[0] |= BIT(REL_WHEEL);
 	}
 
-	input->cdev.dev = hidp_get_device(session);
-
 	input->event = hidp_input_event;
 
 	input_register_device(input);
@@ -660,8 +637,6 @@
 	strncpy(hid->phys, batostr(&src), 64);
 	strncpy(hid->uniq, batostr(&dst), 64);
 
-	hid->dev = hidp_get_device(session);
-
 	hid->send = hid_send_report;
 
 	hid_register_device(hid);
diff -ur --exclude-from=kernel-diff-exclude.txt linux-2.6.18-mh1/net/bluetooth/l2cap.c linux-2.6.18-my-bt/net/bluetooth/l2cap.c
--- linux-2.6.18-mh1/net/bluetooth/l2cap.c	2006-09-23 19:56:08.000000000 -0700
+++ linux-2.6.18-my-bt/net/bluetooth/l2cap.c	2006-09-23 23:00:22.000000000 -0700
@@ -40,20 +40,16 @@
 #include <linux/skbuff.h>
 #include <linux/list.h>
 #include <linux/device.h>
-#include <linux/crc16.h>
 #include <net/sock.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
-#include <asm/bitops.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
 
-#define CONFIG_BT_L2CAP_DEBUG
-
 #ifndef CONFIG_BT_L2CAP_DEBUG
 #undef  BT_DBG
 #define BT_DBG(D...)
@@ -70,8 +66,6 @@
 static void __l2cap_sock_close(struct sock *sk, int reason);
 static void l2cap_sock_close(struct sock *sk);
 static void l2cap_sock_kill(struct sock *sk);
-static inline int l2cap_do_send_rfc(struct sock *sk);
-static int l2cap_send_sframe(struct sock *sk, u8 reqseq);
 
 static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
 				u8 code, u8 ident, u16 dlen, void *data);
@@ -110,52 +104,6 @@
 	sk->sk_timer.data = (unsigned long)sk;
 }
 
-static void l2cap_start_ret_timer(struct sock *sk, u16 timeout)
-{
-	BT_DBG("sk %p timeout %d", sk, timeout);
-	if (timeout <= jiffies) return;
-	mod_timer(&l2cap_pi(sk)->ret_timer, timeout);
-}
-
-static void l2cap_start_mon_timer(struct sock *sk, u16 timeout)
-{
-	BT_DBG("sk %p timeout %d", sk, timeout);
-	if (timeout <= jiffies) return;
-	mod_timer(&l2cap_pi(sk)->mon_timer, timeout);
-}
-
-static void l2cap_retransmission_timer(unsigned long data)
-{
-	struct sock *sk = (struct sock *) data;
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-
-	BT_DBG("sk %p", sk);
-
-	pi->exp_ackseq = (pi->exp_ackseq + 1) % 64;
-	if (pi->exp_ackseq == pi->next_txseq) {
-		l2cap_start_mon_timer(sk, pi->imon_to * HZ / 1000);
-	} else {
-		l2cap_start_ret_timer(sk, pi->iret_to * HZ / 1000);
-		
-		lock_sock(sk);
-		if (sk->sk_state == BT_CONNECTED)
-			l2cap_do_send_rfc(sk);
-		release_sock(sk);
-	}
-}
-
-static void l2cap_monitor_timer(unsigned long data)
-{
-	struct sock *sk = (struct sock *) data;
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-
-	BT_DBG("sk %p", sk);
-
-	l2cap_send_sframe(sk, pi->exp_txseq);
-
-	l2cap_start_mon_timer(sk, pi->imon_to * HZ / 1000);
-}
-
 /* ---- L2CAP channels ---- */
 static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
 {
@@ -410,7 +358,8 @@
 	struct sock *sk;
 	struct hlist_node *node;
 	sk_for_each(sk, node, &l2cap_sk_list.head)
-		if (l2cap_pi(sk)->sport == psm && !bacmp(&bt_sk(sk)->src, src))
+		if (l2cap_pi(sk)->sport == (__le16 __force) psm &&
+				!bacmp(&bt_sk(sk)->src, src))
 			goto found;
 	sk = NULL;
 found:
@@ -429,7 +378,7 @@
 		if (state && sk->sk_state != state)
 			continue;
 
-		if (l2cap_pi(sk)->psm == psm) {
+		if (l2cap_pi(sk)->psm == (__le16 __force) psm) {
 			/* Exact match. */
 			if (!bacmp(&bt_sk(sk)->src, src))
 				break;
@@ -551,38 +500,16 @@
 		sk->sk_type = parent->sk_type;
 		pi->imtu = l2cap_pi(parent)->imtu;
 		pi->omtu = l2cap_pi(parent)->omtu;
-		pi->mode = l2cap_pi(parent)->mode;
 		pi->link_mode = l2cap_pi(parent)->link_mode;
 	} else {
 		pi->imtu = L2CAP_DEFAULT_MTU;
 		pi->omtu = 0;
-		pi->mode = L2CAP_MODE_BASIC;
 		pi->link_mode = 0;
 	}
 
 	/* Default config options */
 	pi->conf_mtu = L2CAP_DEFAULT_MTU;
 	pi->flush_to = L2CAP_DEFAULT_FLUSH_TO;
-	pi->conf_mode = L2CAP_MODE_FLOW;
-	pi->conf_txw = L2CAP_DEFAULT_TXW;
-	pi->conf_maxt = L2CAP_DEFAULT_MAXT;
-	pi->conf_ret_to = L2CAP_DEFAULT_RETTO;
-	pi->conf_mon_to = L2CAP_DEFAULT_MONTO;
-	pi->conf_mps = L2CAP_DEFAULT_MPS;
-
-	pi->next_txseq = 0;
-	pi->exp_ackseq = 0;
-
-	skb_queue_head_init(&pi->tx_queue);
-	pi->tx_queue_frames = 0;
-
-	init_timer(&l2cap_pi(sk)->ret_timer);
-	l2cap_pi(sk)->ret_timer.function = l2cap_retransmission_timer;
-	l2cap_pi(sk)->ret_timer.data = (unsigned long)l2cap_pi(sk);
-
-	init_timer(&l2cap_pi(sk)->mon_timer);
-	l2cap_pi(sk)->mon_timer.function = l2cap_monitor_timer;
-	l2cap_pi(sk)->mon_timer.data = (unsigned long)l2cap_pi(sk);
 }
 
 static struct proto l2cap_proto = {
@@ -666,8 +593,8 @@
 	} else {
 		/* Save source address */
 		bacpy(&bt_sk(sk)->src, &la->l2_bdaddr);
-		l2cap_pi(sk)->psm   = la->l2_psm;
-		l2cap_pi(sk)->sport = la->l2_psm;
+		l2cap_pi(sk)->psm   = (__le16 __force) la->l2_psm;
+		l2cap_pi(sk)->sport = (__le16 __force) la->l2_psm;
 		sk->sk_state = BT_BOUND;
 	}
 
@@ -779,7 +706,7 @@
 
 	/* Set destination address and psm */
 	bacpy(&bt_sk(sk)->dst, &la->l2_bdaddr);
-	l2cap_pi(sk)->psm = la->l2_psm;
+	l2cap_pi(sk)->psm = (__le16 __force) la->l2_psm;
 
 	if ((err = l2cap_do_connect(sk)))
 		goto done;
@@ -908,7 +835,7 @@
 	else
 		bacpy(&la->l2_bdaddr, &bt_sk(sk)->src);
 
-	la->l2_psm = l2cap_pi(sk)->psm;
+	la->l2_psm = (unsigned short __force) l2cap_pi(sk)->psm;
 	return 0;
 }
 
@@ -940,7 +867,7 @@
 	lh->len = __cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
 
 	if (sk->sk_type == SOCK_DGRAM)
-		put_unaligned(l2cap_pi(sk)->psm, (u16 *) skb_put(skb, 2));
+		put_unaligned(l2cap_pi(sk)->psm, (__le16 *) skb_put(skb, 2));
 
 	if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) {
 		err = -EFAULT;
@@ -980,164 +907,6 @@
 	return err;
 }
 
-static inline int l2cap_do_send_rfc(struct sock *sk)
-{
-	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	struct sk_buff *skb;
-	int err = 0;
-	u8 occupied;
-	
-	occupied = (pi->next_txseq - pi->exp_ackseq + 64) % 64;
-
-	BT_DBG("sk %p occ %d frames %d", sk, occupied, pi->tx_queue_frames);
-
-	/* no frames in TxQueue */
-	if (!pi->tx_queue_frames)
-		return -1;
-	
-	if (pi->otxw <= occupied)
-		return -1;
-
-	while ((pi->tx_queue_frames > 0) && (pi->otxw > occupied)) {
-		skb = skb_dequeue(&pi->tx_queue);
-		if (skb == NULL) {
-			goto fail;
-		}
-		if ((err = hci_send_acl(conn->hcon, skb, 0)) < 0)
-			goto fail;
-
-		pi->tx_queue_frames--;
-		occupied++;
-	}
-
-	return 0;
-
-fail:
-	kfree(skb);
-	return -1;
-}
-
-static int l2cap_segment_sdu(struct sock *sk, struct msghdr *msg, int len)
-{
-	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-	struct sk_buff *skb;
-	int err, hlen, count, sent = 0;
-	struct l2cap_hdr *lh;
-	u16 control = 0, fcs, sar;
-
-	BT_DBG("sk %p len %d", sk, len);
-
-	/* length, cid, control, fcs */
-	hlen = L2CAP_HDR_SIZE + 4;
-
-	/* count reflects the size of the information payload field */
-	count = min_t(unsigned int, (conn->mtu - hlen), len);
-
-	/* one single frame */
-	if (len == count) {
-		skb = bt_skb_send_alloc(sk, hlen + len,
-				msg->msg_flags & MSG_DONTWAIT, &err);
-		if (!skb)
-			return err;
-
-		/* Create L2CAP header */
-		lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
-		lh->cid = __cpu_to_le16(l2cap_pi(sk)->dcid);
-		lh->len = __cpu_to_le16(len + 4);
-
-		L2CAP_SET_SAR(control, L2CAP_SAR_UNSEGMENTED);
-		L2CAP_SET_TXSEQ(control, l2cap_pi(sk)->next_txseq);
-		L2CAP_SET_REQSEQ(control, l2cap_pi(sk)->exp_txseq);
-
-		put_unaligned(__cpu_to_le16(control), (u16 *) skb_put(skb, 2));
-
-		if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
-			err = -EFAULT;
-			goto fail;
-		}
-
-		/* calculate fcs over information payload plus
-		 * len, cid and control fields */
-		fcs = crc16(0, skb->data, len + 6);
-
-		put_unaligned(__cpu_to_le16(fcs), (u16 *) skb_put(skb, 2));
-
-		l2cap_pi(sk)->next_txseq = (l2cap_pi(sk)->next_txseq + 1) % 64;
-			
-		skb_queue_tail(&l2cap_pi(sk)->tx_queue, skb);
-		l2cap_pi(sk)->tx_queue_frames++;
-
-		sent = len;
-
-		goto out;
-	}
-
-	sar = L2CAP_SAR_START;
-	hlen  += 2;
-	count -= 2;
-
-	/* build segmented i-frames */
-	while (len) {
-		skb = bt_skb_send_alloc(sk, hlen + count,
-				msg->msg_flags & MSG_DONTWAIT, &err);
-		if (!skb)
-			return err;
-
-		/* Create L2CAP header */
-		lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
-		lh->cid = __cpu_to_le16(l2cap_pi(sk)->dcid);
-		lh->len = __cpu_to_le16(count + hlen - L2CAP_HDR_SIZE);
-
-		/* Control and SDU len field */
-		L2CAP_SET_SAR(control, sar);
-		L2CAP_SET_TXSEQ(control, l2cap_pi(sk)->next_txseq);
-		L2CAP_SET_REQSEQ(control, l2cap_pi(sk)->exp_txseq);
-
-		put_unaligned(__cpu_to_le16(control), (u16 *) skb_put(skb, 2));
-
-		if (sar == L2CAP_SAR_START)
-			put_unaligned(__cpu_to_le16(len), (u16 *) skb_put(skb, 2));
-
-		/* Information payload */
-		if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) {
-			err = -EFAULT;
-			goto fail;
-		}
-
-		/* calculate fcs over information payload plus
-		 * len, cid and control fields (plus sdu len if present) */
-		fcs = crc16(0, skb->data, hlen + count);
-
-		put_unaligned(__cpu_to_le16(fcs), (u16 *) skb_put(skb, 2));
-
-		l2cap_pi(sk)->next_txseq = (l2cap_pi(sk)->next_txseq + 1) % 64;
-			
-		skb_queue_tail(&l2cap_pi(sk)->tx_queue, skb);
-		l2cap_pi(sk)->tx_queue_frames++;
-
-		sent += count;
-		len  -= count;
-
-		if (sar == L2CAP_SAR_START) {
-			hlen  -= 2;
-			count += 2;
-		}
-		
-		if (len <= count)
-			sar = L2CAP_SAR_END;
-		else
-			sar = L2CAP_SAR_CONTINUE;
-	}
-
-out:
-	return sent;
-
-fail:
-	kfree_skb(skb);
-	return err;
-}
-
 static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
 {
 	struct sock *sk = sock->sk;
@@ -1158,22 +927,11 @@
 
 	lock_sock(sk);
 
-	if (!(sk->sk_state == BT_CONNECTED)) {
-		err = -ENOTCONN;
-		goto out;
-	}
-
-	if (l2cap_pi(sk)->mode == L2CAP_MODE_FLOW) {
-		err = l2cap_segment_sdu(sk, msg, len);
-		if (err < 0)
-			goto out;
-		if (l2cap_do_send_rfc(sk) < 0)
-			err = -1;
-	} else {
+	if (sk->sk_state == BT_CONNECTED)
 		err = l2cap_do_send(sk, msg, len);
-	}
+	else
+		err = -ENOTCONN;
 
-out:
 	release_sock(sk);
 	return err;
 }
@@ -1237,7 +995,7 @@
 		opts.imtu     = l2cap_pi(sk)->imtu;
 		opts.omtu     = l2cap_pi(sk)->omtu;
 		opts.flush_to = l2cap_pi(sk)->flush_to;
-		opts.mode     = l2cap_pi(sk)->mode;
+		opts.mode     = 0x00;
 
 		len = min_t(unsigned int, len, sizeof(opts));
 		if (copy_to_user(optval, (char *) &opts, len))
@@ -1469,207 +1227,102 @@
 	return NULL;
 }
 
-/**
- * l2cap_check_conf_opt - checks an incoming option for valid parameters
- * @sk: corresponding socket
- * @option: option that's parameters will be checked
- * @return: result code for this request's option
- *
- * All parameters of a particular option from an incoming request will be
- * checked. The result code for this option (e.g. L2CAP_CONF_UNACCEPT) is
- * returned.
- */
-static inline int l2cap_check_conf_opt(struct sock *sk, int option)
+static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
 {
-	int result = L2CAP_CONF_SUCCESS;
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	struct l2cap_conf_opt *opt = *ptr;
+	int len;
+
+	len = L2CAP_CONF_OPT_SIZE + opt->len;
+	*ptr += len;
 
-	switch (option) {
-	case L2CAP_CONF_MTU:
-		if (pi->conf_mtu < L2CAP_MIN_MTU)
-			result = L2CAP_CONF_UNACCEPT;
+	*type = opt->type;
+	*olen = opt->len;
+
+	switch (opt->len) {
+	case 1:
+		*val = *((__u8 *) opt->val);
 		break;
-	case L2CAP_CONF_FLUSH_TO:
+
+	case 2:
+		*val = __le16_to_cpu(*((__le16 *) opt->val));
 		break;
-	case L2CAP_CONF_QOS:
+
+	case 4:
+		*val = __le32_to_cpu(*((__le32 *) opt->val));
 		break;
-	case L2CAP_CONF_RFC:
-		if (pi->conf_mode == L2CAP_MODE_BASIC) {
-			pi->mode = L2CAP_MODE_BASIC;
-			break;
-		}
-		/* Retransmission Mode not supported yet */
-		if (pi->conf_mode != L2CAP_MODE_FLOW) {
-			pi->conf_mode = L2CAP_MODE_FLOW;
-			result = L2CAP_CONF_UNACCEPT;
-		}
-		if (pi->conf_txw < 1 || pi->conf_txw > 32) {
-			pi->conf_txw = 32;
-			result = L2CAP_CONF_UNACCEPT;
-		}
-		if (pi->conf_maxt < 1) {
-			pi->conf_maxt = 8;
-			result = L2CAP_CONF_UNACCEPT;
-		}
-		if (pi->conf_ret_to < 100) {
-			pi->conf_ret_to = 1000;
-			result = L2CAP_CONF_UNACCEPT;
-		}
-		if (pi->conf_mon_to < 100) {
-			pi->conf_mon_to = 1000;
-			result = L2CAP_CONF_UNACCEPT;
-		}
+
+	default:
+		*val = (unsigned long) opt->val;
 		break;
 	}
 
-	return result;
+	BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
+	return len;
 }
 
-/**
- * l2cap_parse_conf_req - parses a configuration request packet for options
- * @sk: corresponding socket structure
- * @data: conf request data that consists of type, length and option data
- * @len: length of the whole configuration request packet
- * @result: array (128 Bytes) of collected result codes
- *
- * Parses a configuration request that may contain multiple configuration
- * options. Sets the appropriate configuration request parameters from the
- * remote peer if all options are valid and understood. Rejects them if
- * they are malformed and prepares an unknown status for options that we
- * do not support yet.
- */
-static inline void l2cap_parse_conf_req(struct sock *sk, void *data, u16 len, u8 *result)
+static inline void l2cap_parse_conf_req(struct sock *sk, void *data, u16 len)
 {
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	int type, hint;
-	u8 *ptr = data;
-	/* bit flag to avoid multiple examination of already parsed options */
-	unsigned long options = 0;
+	int type, hint, olen; 
+	unsigned long val;
+	void *ptr = data;
 
 	BT_DBG("sk %p len %d", sk, len);
 
-	memset(result, 255, L2CAP_MAX_OPTS);
-
-	/* result[0] stays 255 for an empty request */
-	if (len != 0)
-		result[0] = L2CAP_CONF_SUCCESS;
-
 	while (len >= L2CAP_CONF_OPT_SIZE) {
-		u8 req_len = *(u8 *)(ptr + 1);
-
-		/* bail out if req length > packet length */
-		if (len < req_len) return;
-
-		len -= req_len + 2;
-		type = *(u8 *)(ptr + 0);
+		len -= l2cap_get_conf_opt(&ptr, &type, &olen, &val);
 
 		hint  = type & 0x80;
 		type &= 0x7f;
 
 		switch (type) {
-		case 0:
-			result[0] = L2CAP_CONF_REJ;
-			break;
 		case L2CAP_CONF_MTU:
-			if (test_bit(L2CAP_CONF_MTU, &options))
-				break;
-			if (req_len != 2) {
-				result[0] = L2CAP_CONF_REJ;
-				break;
-			}
-			pi->conf_mtu = __le16_to_cpup((__le16 *)(ptr + 2));
-			set_bit(L2CAP_CONF_MTU, &options);
-			result[L2CAP_CONF_MTU] = l2cap_check_conf_opt(sk, L2CAP_CONF_MTU);
-			if (result[L2CAP_CONF_MTU] == L2CAP_CONF_UNACCEPT)
-				result[0] = L2CAP_CONF_UNACCEPT;
-
+			l2cap_pi(sk)->conf_mtu = val;
 			break;
 
 		case L2CAP_CONF_FLUSH_TO:
-			if (test_bit(L2CAP_CONF_FLUSH_TO, &options))
-				break;
-			if (req_len != 2) {
-				result[0] = L2CAP_CONF_REJ;
-				break;
-			}
-			pi->flush_to = __le16_to_cpup((__le16 *)(ptr + 2));
-			set_bit(L2CAP_CONF_FLUSH_TO, &options);
-			result[L2CAP_CONF_FLUSH_TO] = l2cap_check_conf_opt(sk, L2CAP_CONF_FLUSH_TO);
-			if (result[L2CAP_CONF_FLUSH_TO] == L2CAP_CONF_UNACCEPT)
-				result[0] = L2CAP_CONF_UNACCEPT;
-
+			l2cap_pi(sk)->flush_to = val;
 			break;
 
-		case L2CAP_CONF_RFC:
-			if (test_bit(L2CAP_CONF_RFC, &options))
-				break;
-			if (req_len != 9) {
-				result[0] = L2CAP_CONF_REJ;
-				break;
-			}
-			pi->conf_mode = *(__u8 *)(ptr + 2);
-			pi->conf_txw  = *(__u8 *)(ptr + 3);
-			pi->conf_maxt = *(__u8 *)(ptr + 4);
-			pi->conf_ret_to = __le16_to_cpup((__le16 *)(ptr + 5));
-			pi->conf_mon_to = __le16_to_cpup((__le16 *)(ptr + 7));
-			pi->conf_mps    = __le16_to_cpup((__le16 *)(ptr + 9));
-			set_bit(L2CAP_CONF_RFC, &options);
-			result[L2CAP_CONF_RFC] = l2cap_check_conf_opt(sk, L2CAP_CONF_RFC);
-			if (result[L2CAP_CONF_RFC] == L2CAP_CONF_UNACCEPT)
-				result[0] = L2CAP_CONF_UNACCEPT;
-
+		case L2CAP_CONF_QOS:
 			break;
 
 		default:
-			result[0] = L2CAP_CONF_UNKNOWN;
-			result[type] = L2CAP_CONF_UNKNOWN;
-			/* TODO: hints are not supported yet */
 			if (hint)
 				break;
-		}
 
-		/* go to start of (possible) next request */
-		ptr += req_len + L2CAP_CONF_OPT_SIZE;
+			/* FIXME: Reject unknown option */
+			break;
+		}
 	}
 }
 
-/**
- * l2cap_add_conf_opt - adds a configuration option to a rsp or req
- * @ptr: pointer to location where all options are finally stored
- * @data: data for one option (type, len, and all parameters)
- * @type: option type
- * @len: option length
- *
- * Adds a complete configuration parameter option to a configuration
- * response or a configuration request
- */
-static void l2cap_add_conf_opt(void **ptr, void *data, u8 type, u8 len)
+static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
 {
 	struct l2cap_conf_opt *opt = *ptr;
 
-	BT_DBG("type 0x%2.2x len %d", type, len);
+	BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
 
 	opt->type = type;
 	opt->len  = len;
 
-	switch (type) {
-	case L2CAP_CONF_MTU:
-		*((__le16 *) opt->val) = cpu_to_le16(*(__le16 *) data);
+	switch (len) {
+	case 1:
+		*((__u8 *) opt->val)  = val;
 		break;
-	case L2CAP_CONF_RFC: {
-		struct l2cap_conf_rfc *tmp = (struct l2cap_conf_rfc *) data;
-		struct l2cap_conf_rfc *rfc = (struct l2cap_conf_rfc *) opt->val;
-		rfc->mode   = tmp->mode;
-		rfc->txw    = tmp->txw;
-		rfc->maxt   = tmp->maxt;
-		rfc->ret_to = tmp->ret_to;
-		rfc->mon_to = tmp->mon_to;
-		rfc->mps    = tmp->mps;
+
+	case 2:
+		*((__le16 *) opt->val) = __cpu_to_le16(val);
+		break;
+
+	case 4:
+		*((__le32 *) opt->val) = __cpu_to_le32(val);
+		break;
+
+	default:
+		memcpy(opt->val, (void *) val, len);
 		break;
-	}
 	}
 
-	/* increase pointer for next (possible) option */
 	*ptr += L2CAP_CONF_OPT_SIZE + len;
 }
 
@@ -1677,193 +1330,59 @@
 {
 	struct l2cap_pinfo *pi = l2cap_pi(sk);
 	struct l2cap_conf_req *req = data;
-	void *opts = req->data;
+	void *ptr = req->data;
 
 	BT_DBG("sk %p", sk);
 
-	if ((pi->conf_state & L2CAP_CONF_UNACCEPT_MTU) ||
-			(pi->imtu != L2CAP_DEFAULT_MTU)) {
-		l2cap_add_conf_opt(&opts, &(pi->conf_mtu), L2CAP_CONF_MTU, 2);
-		/* clear bit in conf_state */
-		pi->conf_state &= (~L2CAP_CONF_UNACCEPT_MTU);
-	}
-
-	/* either we got unacceptable rfc options in former response
-	 * or we discovered support for rfc in an information request */
-	if ((pi->conf_state & L2CAP_CONF_UNACCEPT_RFC) ||
-			(pi->info_ext & L2CAP_EXT_FCM)) {
-		struct l2cap_conf_rfc rfc;
-		rfc.mode = pi->conf_mode;
-		rfc.txw  = pi->conf_txw;
-		rfc.maxt = pi->conf_maxt;
-		rfc.ret_to = pi->conf_ret_to;
-		rfc.mon_to = pi->conf_mon_to;
-		rfc.mps = pi->conf_mps;
-		l2cap_add_conf_opt(&opts, &(pi->conf_mtu), L2CAP_CONF_MTU, 2);
-		l2cap_add_conf_opt(&opts, &rfc, L2CAP_CONF_RFC, 9);
-		/* clear bit in conf_state */
-		pi->conf_state &= (~L2CAP_CONF_UNACCEPT_RFC);
-	}
+	if (pi->imtu != L2CAP_DEFAULT_MTU)
+		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
+
+	/* FIXME: Need actual value of the flush timeout */
+	//if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
+	//   l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, pi->flush_to);
 
 	req->dcid  = __cpu_to_le16(pi->dcid);
 	req->flags = __cpu_to_le16(0);
 
-	return opts - data;
+	return ptr - data;
 }
 
-/**
- * l2cap_build_conf_rsp - builds a configuration response
- * @sk: corresponding socket
- * @data: data portion of rsp packet (scid, flags, result, config)
- * @complete: indicates whether C flag is set (0 == incomplete)
- * @result: pointer to collected result codes of result[128]
- *
- * Building a configuration response on base of the collected result codes.
- * The fundamental result code result[0] delegates the action that is taken.
- * For each result[i] that is set appropriately the response packet will be
- * built.
- * Returns the length of the data field in octets of the command only (does
- * not cover the Code, Identifier, and Length field): scid + flags + result +
- * configuration options.
- */
-static int l2cap_build_conf_rsp(struct sock *sk, void *data, int complete, u8 *result)
+static inline int l2cap_conf_output(struct sock *sk, void **ptr)
 {
-	struct l2cap_conf_rsp *rsp = data;
 	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	void *opts = rsp->data;
-	u16 flags = 0;
-	int i, len = 0;
-
-	BT_DBG("sk %p complete %d", sk, complete);
+	int result = 0;
 
-	switch (result[0]) {
-	/* 255 represents the case for an empty request */
-	case 255:
+	/* Configure output options and let the other side know
+	 * which ones we don't like. */
+	if (pi->conf_mtu < pi->omtu) {
+		l2cap_add_conf_opt(ptr, L2CAP_CONF_MTU, 2, pi->omtu);
+		result = L2CAP_CONF_UNACCEPT;
+	} else {
 		pi->omtu = pi->conf_mtu;
-		result[0] = L2CAP_CONF_SUCCESS;
-		break;
-
-	case L2CAP_CONF_SUCCESS:
-		for (i = 1; i < L2CAP_MAX_OPTS; ++i) {
-			if (result[i] == L2CAP_CONF_SUCCESS) {
-				switch (i) {
-				case L2CAP_CONF_MTU:
-					pi->omtu = pi->conf_mtu;
-					len = 2;
-					l2cap_add_conf_opt(&opts, &(pi->omtu), i, len);
-					break;
-				case L2CAP_CONF_RFC: {
-					struct l2cap_conf_rfc params;
-					struct l2cap_conf_rfc *rfc = &params;
-					pi->mode = pi->conf_mode;
-					pi->otxw  = pi->conf_txw;
-					pi->omaxt = pi->conf_maxt;
-					pi->oret_to = pi->conf_ret_to;
-					pi->omon_to = pi->conf_mon_to;
-					pi->omps = pi->conf_mps;
-					len = 9;
-					rfc->mode = pi->mode;
-					rfc->txw  = pi->otxw;
-					rfc->maxt = pi->omaxt;
-					rfc->ret_to = pi->oret_to;
-					rfc->mon_to = pi->omon_to;
-					rfc->mps = pi->omps;
-					l2cap_add_conf_opt(&opts, rfc, i, len);
-					break;
-				}
-				}
-			}
-		}
-		break;
-
-	case L2CAP_CONF_UNACCEPT:
-		for (i = 1; i < L2CAP_MAX_OPTS; ++i) {
-			if (result[i] == L2CAP_CONF_UNACCEPT) {
-				switch (i) {
-				case L2CAP_CONF_MTU: {
-					__le16 mtu = L2CAP_DEFAULT_MTU;
-					len = 2;
-					l2cap_add_conf_opt(&opts, &mtu, i, len);
-					break;
-				}
-				case L2CAP_CONF_RFC: {
-					struct l2cap_conf_rfc params;
-					struct l2cap_conf_rfc *rfc = &params;
-					rfc->mode = pi->conf_mode;
-					rfc->txw  = pi->conf_txw;
-					rfc->maxt = pi->conf_maxt;
-					rfc->ret_to = pi->conf_ret_to;
-					rfc->mon_to = pi->conf_mon_to;
-					rfc->mps = pi->conf_mps;
-					len = 9;
-					l2cap_add_conf_opt(&opts, rfc, i, len);
-					break;
-				}
-				}
-			}
-		}
-		break;
-
-	case L2CAP_CONF_REJ:
-		/* send plain reject response */
-		l2cap_add_conf_opt(&opts, NULL, 0, 0);
-		break;
-
-	case L2CAP_CONF_UNKNOWN:
-		for (i = 1; i < L2CAP_MAX_OPTS; ++i) {
-			if (result[i] == L2CAP_CONF_UNKNOWN) {
-				l2cap_add_conf_opt(&opts, NULL, i, 0);
-			}
-		}
-		break;
 	}
 
-	rsp->scid   = __cpu_to_le16(l2cap_pi(sk)->dcid);
-	rsp->result = __cpu_to_le16(result[0] == 255 ? 0 : result[0]);
-	rsp->flags  = __cpu_to_le16(flags);
-
-	/* return length of actual data */
-	return opts - data;
-}
-
-static int l2cap_build_info_req(void *data)
-{
-	struct l2cap_info_req *info = data;
-	u8 len = 2;
-
-	info->type = __cpu_to_le16(L2CAP_IT_FEAT_MASK);
-
-	return len;
+	BT_DBG("sk %p result %d", sk, result);
+	return result;
 }
 
-static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+static int l2cap_build_conf_rsp(struct sock *sk, void *data, int *result)
 {
-	struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
-	u16 reason;
-	u8 len; /* depends on reason code */
-	__le16 *ptr = rej->data;
+	struct l2cap_conf_rsp *rsp = data;
+	void *ptr = rsp->data;
+	u16 flags = 0;
 
-	reason = __le16_to_cpu(rej->reason);
+	BT_DBG("sk %p complete %d", sk, result ? 1 : 0);
 
-	BT_DBG("reason 0x%4.4x", reason);
+	if (result)
+		*result = l2cap_conf_output(sk, &ptr);
+	else
+		flags = 0x0001;
 
-	switch (reason) {
-	case L2CAP_CMD_NOT_UNDERSTOOD:
-		len = 0;
-		break;
-	case L2CAP_MTU_EXCEEDED:
-		len = 2;
-		BT_DBG("max acceptable signalling MTU 0x%02X", ptr[0]);
-		break;
-	case L2CAP_INVALID_CID:
-		len = 4;
-		BT_DBG("invalid channel 0x%04X 0x%04X", ptr[0], ptr[1]);
-		break;
-	default:
-		return reason;
-	}
+	rsp->scid   = __cpu_to_le16(l2cap_pi(sk)->dcid);
+	rsp->result = __cpu_to_le16(result ? *result : 0);
+	rsp->flags  = __cpu_to_le16(flags);
 
-	return 0;
+	return ptr - data;
 }
 
 static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
@@ -1875,12 +1394,12 @@
 	int result = 0, status = 0;
 
 	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
-	u16 psm  = req->psm;
+	__le16 psm  = req->psm;
 
 	BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
 
 	/* Check if we have socket listening on psm */
-	parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
+	parent = l2cap_get_sock_by_psm(BT_LISTEN, (u16 __force) psm, conn->src);
 	if (!parent) {
 		result = L2CAP_CR_BAD_PSM;
 		goto sendresp;
@@ -1959,7 +1478,7 @@
 	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
 	u16 scid, dcid, result, status;
 	struct sock *sk;
-	u16 info;
+	u8 req[128];
 
 	scid   = __le16_to_cpu(rsp->scid);
 	dcid   = __le16_to_cpu(rsp->dcid);
@@ -1979,12 +1498,12 @@
 	switch (result) {
 	case L2CAP_CR_SUCCESS:
 		sk->sk_state = BT_CONFIG;
-		l2cap_pi(sk)->ident = l2cap_get_ident(conn);
+		l2cap_pi(sk)->ident = 0;
 		l2cap_pi(sk)->dcid = dcid;
-		/* send information request first */
-		l2cap_pi(sk)->conf_state |= L2CAP_INFO_REQ_SENT;
-		l2cap_send_cmd(conn, l2cap_pi(sk)->ident, L2CAP_INFO_REQ,
-					l2cap_build_info_req(&info), &info);
+		l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
+
+		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
+					l2cap_build_conf_req(sk, req), req);
 		break;
 
 	case L2CAP_CR_PEND:
@@ -2002,13 +1521,10 @@
 static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
 {
 	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
-	u16 dcid, flags;
-	u8 rsp[128];
+	u16 dcid, flags, cmd_len = __le16_to_cpu(cmd->len);
+	u8 rsp[64];
 	struct sock *sk;
-	/* collected result codes for theor. max 128 possible options
-	 * result[0] indicates the general result code for all options */
-	u8 result[L2CAP_MAX_OPTS];
-	int temp_len;
+	int result;
 
 	dcid  = __le16_to_cpu(req->dcid);
 	flags = __le16_to_cpu(req->flags);
@@ -2018,41 +1534,32 @@
 	if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid)))
 		return -ENOENT;
 
-	l2cap_parse_conf_req(sk, req->data, cmd->len - sizeof(*req), result);
+	l2cap_parse_conf_req(sk, req->data, cmd_len - sizeof(*req));
 
 	if (flags & 0x0001) {
 		/* Incomplete config. Send empty response. */
 		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
-				l2cap_build_conf_rsp(sk, rsp, 0, NULL), rsp);
+				l2cap_build_conf_rsp(sk, rsp, NULL), rsp);
 		goto unlock;
 	}
 
 	/* Complete config. */
-	temp_len = l2cap_build_conf_rsp(sk, rsp, 1, result);
 	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
-			temp_len, rsp);
+			l2cap_build_conf_rsp(sk, rsp, &result), rsp);
 
-	if (result[0])
+	if (result)
 		goto unlock;
 
 	/* Output config done */
 	l2cap_pi(sk)->conf_state |= L2CAP_CONF_OUTPUT_DONE;
-	l2cap_pi(sk)->ident = l2cap_get_ident(conn);
 
 	if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
 		sk->sk_state = BT_CONNECTED;
 		l2cap_chan_ready(sk);
-	} /* don't send conf req if we still await an information rsp */
-	else if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
-		  (l2cap_pi(sk)->conf_state & L2CAP_INFO_INPUT_DONE)) {
-		u8 req[128];
-		l2cap_send_cmd(conn, l2cap_pi(sk)->ident, L2CAP_CONF_REQ,
+	} else if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
+		u8 req[64];
+		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
 					l2cap_build_conf_req(sk, req), req);
-	} /* send information request */
-	else {
-		u16 info;
-		l2cap_send_cmd(conn, l2cap_pi(sk)->ident, L2CAP_INFO_REQ,
-					l2cap_build_info_req(&info), &info);
 	}
 
 unlock:
@@ -2062,14 +1569,9 @@
 
 static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
 {
-	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *) data;
-	u16 scid, flags, result, len;
+	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
+	u16 scid, flags, result;
 	struct sock *sk;
-	struct l2cap_pinfo *pi;
-	u8 type;
-	u8 *ptr = rsp->data;
-	/* length of all options in config data field */
-	len = __le16_to_cpu(cmd->len) - sizeof(*rsp);
 
 	scid   = __le16_to_cpu(rsp->scid);
 	flags  = __le16_to_cpu(rsp->flags);
@@ -2079,96 +1581,23 @@
 
 	if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, scid)))
 		return 0;
-	pi = l2cap_pi(sk);
 
 	switch (result) {
 	case L2CAP_CONF_SUCCESS:
-		while (len >= L2CAP_CONF_OPT_SIZE) {
-			u8 rsp_len = *(u8 *)(ptr + 1);
-			/* bail out if rsp len > packet len */
-			if (len < rsp_len) return 0;
-
-			len -= rsp_len + 2;
-			type = *(u8 *)(ptr + 0);
-
-			switch (type) {
-			case L2CAP_CONF_MTU:
-				pi->imtu = *(__le16 *)(ptr + 2);
-				break;
-			case L2CAP_CONF_RFC:
-				pi->mode = *(u8 *)(ptr + 2);
-				pi->itxw  = *(u8 *)(ptr + 3);
-				pi->imaxt = *(u8 *)(ptr + 4);
-				pi->iret_to = __le16_to_cpup((__le16 *)(ptr + 5));
-				pi->imon_to = __le16_to_cpup((__le16 *)(ptr + 7));
-				pi->imps    = __le16_to_cpup((__le16 *)(ptr + 9));
-				break;
-			}
-
-			/* go to start of (possible) next request */
-			ptr += rsp_len + L2CAP_CONF_OPT_SIZE;
-		}
 		break;
 
-	case L2CAP_CONF_UNACCEPT: {
-		u8 req[128];
-		while (len >= L2CAP_CONF_OPT_SIZE) {
-			u8 rsp_len = *(u8 *)(ptr + 1);
-			/* bail out if rsp len > packet len */
-			if (len < rsp_len) return 0;
-
-			len -= rsp_len + 2;
-			type = *(u8 *)(ptr + 0);
-
-			switch (type) {
-			case L2CAP_CONF_MTU:
-				pi->conf_mtu = *(__le16 *)(ptr + 2);
-				/* add MTU option to new request */
-				pi->conf_state |= L2CAP_CONF_UNACCEPT_MTU;
-				break;
-			case L2CAP_CONF_RFC:
-				pi->conf_mode = *(u8 *)(ptr + 2);
-				pi->conf_txw  = *(u8 *)(ptr + 3);
-				pi->conf_maxt = *(u8 *)(ptr + 4);
-				pi->conf_ret_to = __le16_to_cpup((__le16 *)(ptr + 5));
-				pi->conf_mon_to = __le16_to_cpup((__le16 *)(ptr + 7));
-				pi->conf_mps    = __le16_to_cpup((__le16 *)(ptr + 9));
-				/* add RFC option to new request */
-				pi->conf_state |= L2CAP_CONF_UNACCEPT_RFC;
-				break;
-			}
-
-			/* go to start of (possible) next request */
-			ptr += rsp_len + L2CAP_CONF_OPT_SIZE;
-		}
-		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-				l2cap_build_conf_req(sk, req), req);
-		goto done;
-	}
-
-	case L2CAP_CONF_UNKNOWN: {
-		u8 req[128];
-		while (len >= L2CAP_CONF_OPT_SIZE) {
-			u8 rsp_len = *(u8 *)(ptr + 1);
-			/* bail out if rsp len > packet len */
-			if (len < rsp_len) return 0;
-
-			len -= rsp_len + 2;
-			type = *(u8 *)(ptr + 0);
-
-			switch (type) {
-			case L2CAP_CONF_RFC:
-				pi->conf_mode = L2CAP_MODE_BASIC;
-				break;
-			}
-
-			/* go to start of (possible) next request */
-			ptr += rsp_len + L2CAP_CONF_OPT_SIZE;
+	case L2CAP_CONF_UNACCEPT:
+		if (++l2cap_pi(sk)->conf_retry < L2CAP_CONF_MAX_RETRIES) {
+			char req[128];
+			/* It does not make sense to adjust L2CAP parameters
+			 * that are currently defined in the spec. We simply
+			 * resend config request that we sent earlier. It is
+			 * stupid, but it helps qualification testing which
+			 * expects at least some response from us. */
+			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
+						l2cap_build_conf_req(sk, req), req);
+			goto done;
 		}
-		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-				l2cap_build_conf_req(sk, req), req);
-		goto done;
-	}
 
 	default: 
 		sk->sk_state = BT_DISCONN;
@@ -2253,8 +1682,6 @@
 {
 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
 	struct l2cap_info_rsp rsp;
-	/* length of data field in information response */
-	u8 len_data;
 	u16 type;
 
 	type = __le16_to_cpu(req->type);
@@ -2262,26 +1689,8 @@
 	BT_DBG("type 0x%4.4x", type);
 
 	rsp.type   = __cpu_to_le16(type);
-	switch (type) {
-	case L2CAP_IT_CL_MTU:
-		len_data = 2;
-		rsp.result = __cpu_to_le16(L2CAP_IR_SUCCESS);
-		*(__le16 *)(rsp.data) = __cpu_to_le16(L2CAP_DEFAULT_MTU);
-		break;
-	case L2CAP_IT_FEAT_MASK:
-		len_data = 4;
-		rsp.result = __cpu_to_le16(L2CAP_IR_SUCCESS);
-		/* currently only Flow Control Mode supported */
-		*(__le32 *)(rsp.data) = __cpu_to_le32(L2CAP_EXT_FCM);
-		break;
-	default:
-		len_data = 0;
-		rsp.result = __cpu_to_le16(L2CAP_IR_NOTSUPP);
-		break;
-	}
-
-	/* send information response */
-	l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp) + len_data, &rsp);
+	rsp.result = __cpu_to_le16(L2CAP_IR_NOTSUPP);
+	l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), &rsp);
 
 	return 0;
 }
@@ -2290,40 +1699,11 @@
 {
 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
 	u16 type, result;
-	struct sock *sk;
-	u8 req[128];
-	u8 *ptr = rsp->data;
 
 	type   = __le16_to_cpu(rsp->type);
 	result = __le16_to_cpu(rsp->result);
 
-	BT_DBG("type 0x%4.4x result 0x%2.2x ident %d", type, result, cmd->ident);
-
-	if (!(sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident)))
-		return 0;
-
-	if (result == L2CAP_IR_SUCCESS) {
-		switch (type) {
-		case L2CAP_IT_CL_MTU:
-			l2cap_pi(sk)->info_mtu = __le16_to_cpup((__le16 *) ptr);
-			break;
-		case L2CAP_IT_FEAT_MASK:
-			if (*ptr & L2CAP_EXT_FCM)
-				l2cap_pi(sk)->info_ext |= L2CAP_EXT_FCM;
-			break;
-		}
-	} else {
-		l2cap_pi(sk)->conf_mode = L2CAP_MODE_BASIC;
-	}
-
-	l2cap_pi(sk)->conf_state |= L2CAP_INFO_INPUT_DONE;
-
-	/* build configuration request */
-	l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
-	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-			l2cap_build_conf_req(sk, req), req);
-
-	bh_unlock_sock(sk);
+	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
 
 	return 0;
 }
@@ -2333,6 +1713,7 @@
 	u8 *data = skb->data;
 	int len = skb->len;
 	struct l2cap_cmd_hdr cmd;
+	u16 cmd_len;
 	int err = 0;
 
 	l2cap_raw_recv(conn, skb);
@@ -2342,18 +1723,18 @@
 		data += L2CAP_CMD_HDR_SIZE;
 		len  -= L2CAP_CMD_HDR_SIZE;
 
-		cmd.len = __le16_to_cpu(cmd.len);
+		cmd_len = __le16_to_cpu(cmd.len);
 
-		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd.len, cmd.ident);
+		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident);
 
-		if (cmd.len > len || !cmd.ident) {
+		if (cmd_len > len || !cmd.ident) {
 			BT_DBG("corrupted command");
 			break;
 		}
 
 		switch (cmd.code) {
 		case L2CAP_COMMAND_REJ:
-			err = l2cap_command_rej(conn, &cmd, data);
+			/* FIXME: We should process this */
 			break;
 
 		case L2CAP_CONN_REQ:
@@ -2381,7 +1762,7 @@
 			break;
 
 		case L2CAP_ECHO_REQ:
-			l2cap_send_cmd(conn, cmd.ident, L2CAP_ECHO_RSP, cmd.len, data);
+			l2cap_send_cmd(conn, cmd.ident, L2CAP_ECHO_RSP, cmd_len, data);
 			break;
 
 		case L2CAP_ECHO_RSP:
@@ -2410,245 +1791,13 @@
 			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
 		}
 
-		data += cmd.len;
-		len  -= cmd.len;
+		data += cmd_len;
+		len  -= cmd_len;
 	}
 
 	kfree_skb(skb);
 }
 
-static int l2cap_send_sframe(struct sock *sk, u8 reqseq)
-{
-	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-	struct sk_buff *skb = NULL;
-	struct l2cap_hdr *lh;
-	__le16 *control, *fcs;
-	int err = 0;
-
-	BT_DBG("sk %p reqseq %d", sk, reqseq);
-
-	skb = bt_skb_send_alloc(sk, L2CAP_SFRAME_SIZE, MSG_DONTWAIT, &err);
-	if (!skb)
-		return err;
-
-	/* Create L2CAP header */
-	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
-	lh->cid = __cpu_to_le16(l2cap_pi(sk)->dcid);
-	lh->len = __cpu_to_le16(4);
-	
-	/* Create control field */
-	control  = (__le16 *) skb_put(skb, 2);
-	*control = __cpu_to_le16((reqseq << 8) | 1);
-
-	fcs  = (__le16 *) skb_put(skb, 2);
-	*fcs = __cpu_to_le16(crc16(0, skb->data, 6));
-
-	if ((err = hci_send_acl(conn->hcon, skb, 0)) < 0)
-		goto fail;
-
-	l2cap_start_mon_timer(sk, l2cap_pi(sk)->imon_to * HZ / 1000);
-
-	return err;
-
-fail:
-	kfree_skb(skb);
-	return err;
-}
-
-static int l2cap_invalid_frame_detection(struct sock *sk, struct sk_buff *skb)
-{
-	int err = 0;
-	u16 len, cid, control, sdu_len, fcs;
-
-	/* value of length field in frame */
-	len = get_unaligned((u16 *) skb->data);
-	cid = get_unaligned((u16 *) (skb->data + 2));
-
-	if (len != (skb->len - L2CAP_HDR_SIZE))
-		err = -1;
-
-	/* contains an unknown (reserved) cid */
-	if (cid < 0x003F)
-		err = -2;
-
-	/* contains an fcs error */
-	fcs = get_unaligned((u16 *) (skb->tail - 2));
-	if (unlikely(fcs != crc16(0, skb->data, skb->len - 2)))
-		err = -3;
-
-	/* contains a length > max possible mps */
-	if (len > L2CAP_MAX_DATA_LEN)
-		err = -4;
-
-	control = get_unaligned((u16 *) (skb->data + L2CAP_HDR_SIZE));
-	sdu_len = get_unaligned((u16 *) (skb->data + L2CAP_HDR_SIZE + L2CAP_CONTROL_SIZE));
-
-	if (control & 0x01) {
-		/* s-frame with length != 4 */
-		if (len != 4) err = -8;
-	} else {
-		/* i-frame that has fewer than 8 octets */
-		if (skb->len < 8)
-			err = -5;
-		if ((L2CAP_SAR_MASK & control) == L2CAP_SAR_START) {
-			/* contains a length > max possible mps (with SAR) */
-			if (len > L2CAP_MAX_DATA_LEN - 2)
-				err = -4;
-			/* i-frame with SAR=01 with < 10 octets */
-			if (skb->len < 10)
-				err = -6;
-			/* requested sdu len is bigger than configured mps */
-			if (sdu_len > l2cap_pi(sk)->imps)
-				err = -7;
-		}
-	}
-
-	BT_DBG("err %d", err);
-
-	return err;
-}
-
-static int l2cap_process_txseq(struct sock *sk, struct sk_buff *skb, u16 control)
-{
-	int err = 0;
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	u8 txseq = L2CAP_GET_TXSEQ(control);
-
-	if (txseq == pi->exp_txseq) {
-		pi->exp_txseq = (pi->exp_txseq + 1) % 64;
-	} else if (((txseq - pi->buffer_seq + 64) % 64) < pi->itxw) {
-		/* out-of-sequence i-frame */
-		pi->exp_txseq = (txseq + 1) % 64;
-	} else if ((txseq >= pi->buffer_seq) && (txseq <= pi->exp_txseq - 1)) {
-		/* duplicated i-frame */
-		err = -1;
-	} else {
-		/* invalid txseq */
-		err = -2;
-	}
-
-	BT_DBG("err %d", err);
-
-	return err;
-}
-
-static int l2cap_process_reqseq(struct sock *sk, struct sk_buff *skb, u16 control)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	u8 reqseq = L2CAP_GET_REQSEQ(control);
-
-	BT_DBG("sk %p reqseq %d", sk, reqseq);
-
-	/* accept only i-frame or s-frame with S bits set to 00 (RR) */
-	if (!(((control & 0x01) == 0x00) || ((control & 0x0F) == 0x01)))
-		return -1;
-
-	/* reqseq sequence error */
-	if (!((reqseq - pi->exp_ackseq + 64) % 64 <=
-	      (pi->next_txseq - pi->exp_ackseq + 64) % 64)) {
-		/* close channel -> send disconnect request */
-		struct l2cap_disconn_req req;
-		struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-		sk->sk_state = BT_DISCONN;
-		sk->sk_err   = ECONNRESET;
-		l2cap_sock_set_timer(sk, HZ * 5);
-		req.dcid = __cpu_to_le16(l2cap_pi(sk)->dcid);
-		req.scid = __cpu_to_le16(l2cap_pi(sk)->scid);
-		l2cap_send_cmd(conn, l2cap_get_ident(conn),
-				L2CAP_DISCONN_REQ, sizeof(req), &req);
-		return -2;
-	}
-
-	pi->exp_ackseq = reqseq;
-
-	/*
-	if (reqseq != pi->next_txseq)
-		l2cap_start_ret_timer(sk, pi->iret_to * HZ / 1000);
-	else
-		l2cap_start_mon_timer(sk, pi->imon_to * HZ / 1000);
-	*/
-	/* FIXME: transmit any I-Frames awaiting transmission */
-
-	return 0;
-}
-
-static int l2cap_reassembly(struct sock *sk, struct sk_buff *skb, u16 control)
-{
-	u16 sdu_len = 0;
-
-	BT_DBG("sk %p control %04X", sk, control);
-
-	/* remove header, control and fcs from i-frame */
-	skb_pull(skb, L2CAP_HDR_SIZE + L2CAP_CONTROL_SIZE);
-	skb_trim(skb, skb->len - L2CAP_FCS_SIZE);
-
-	switch (L2CAP_GET_SAR(control)) {
-	case L2CAP_SAR_UNSEGMENTED:
-		l2cap_pi(sk)->buffer_seq = l2cap_pi(sk)->exp_txseq;
-		if (sock_queue_rcv_skb(sk, skb))
-			return -1;
-		if (l2cap_send_sframe(sk, l2cap_pi(sk)->buffer_seq))
-			return -6;
-		break;
-		
-	case L2CAP_SAR_START:
-		sdu_len = get_unaligned((u16 *) skb->data);
-		/* remove sdu len field */
-		skb_pull(skb, 2);
-
-		/* in case a SAR_END frame got lost make sure to free the
-		 * allocated buffer space of the last sdu */
-		kfree_skb(l2cap_pi(sk)->sdu);
-		l2cap_pi(sk)->sdu = NULL;
-		l2cap_pi(sk)->sdu_len = 0;
-			
-		/* allocate skb for complete new sdu */
-		if (!(l2cap_pi(sk)->sdu = bt_skb_alloc(sdu_len, GFP_ATOMIC)))
-			return -2;
-
-		memcpy(skb_put(l2cap_pi(sk)->sdu, skb->len), skb->data, skb->len);
-		l2cap_pi(sk)->sdu_len = sdu_len - skb->len;
-		l2cap_pi(sk)->buffer_seq = l2cap_pi(sk)->exp_txseq;
-		if (l2cap_send_sframe(sk, l2cap_pi(sk)->buffer_seq))
-			return -6;
-		break;
-		
-	default:
-		/* continuation or end of sdu frame */
-		if (!l2cap_pi(sk)->sdu_len) {
-			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
-			return -3;
-		}
-
-		if (skb->len > l2cap_pi(sk)->sdu_len) {
-			BT_ERR("Fragment is too long (len %d, expected %d)",
-					skb->len, l2cap_pi(sk)->sdu_len);
-			kfree_skb(l2cap_pi(sk)->sdu);
-			l2cap_pi(sk)->sdu = NULL;
-			l2cap_pi(sk)->sdu_len = 0;
-			return -4;
-		}
-
-		memcpy(skb_put(l2cap_pi(sk)->sdu, skb->len), skb->data, skb->len);
-		l2cap_pi(sk)->sdu_len -= skb->len;
-		l2cap_pi(sk)->buffer_seq = l2cap_pi(sk)->exp_txseq;
-		if (l2cap_send_sframe(sk, l2cap_pi(sk)->buffer_seq))
-			return -6;
-
-		/* last frame for sdu */
-		if ((L2CAP_GET_SAR(control) == L2CAP_SAR_END) && 
-				(l2cap_pi(sk)->sdu_len == 0)) {
-			if (sock_queue_rcv_skb(sk, l2cap_pi(sk)->sdu))
-				return -1;
-			kfree_skb(l2cap_pi(sk)->sdu);
-			l2cap_pi(sk)->sdu = NULL;
-			l2cap_pi(sk)->sdu_len = 0;
-		}
-	}
-
-	return 0;
-}
-
 static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
 {
 	struct sock *sk;
@@ -2659,44 +1808,19 @@
 		goto drop;
 	}
 
-	BT_DBG("sk %p len %d mode 0x%02X", sk, skb->len, l2cap_pi(sk)->mode);
+	BT_DBG("sk %p, len %d", sk, skb->len);
 
 	if (sk->sk_state != BT_CONNECTED)
 		goto drop;
 
-	/* s-frame or i-frame */
-	if (l2cap_pi(sk)->mode == L2CAP_MODE_FLOW) {
-		u16 control;
-
-		if (l2cap_invalid_frame_detection(sk, skb))
-			goto drop;
-
-		control = get_unaligned((u16 *) (skb->data + L2CAP_HDR_SIZE));
-
-		if (control & 0x01) {
-			/* process s-frame */
-			if (l2cap_process_reqseq(sk, skb, control))
-				goto drop;
-		} else {
-			/* process i-frame */
-			if (l2cap_process_txseq(sk, skb, control))
-				goto drop;
-			if (l2cap_process_reqseq(sk, skb, control))
-				goto drop;
-			if (l2cap_reassembly(sk, skb, control))
-				goto drop;
-		}
-
-		goto done;
-	}
-
-	skb_pull(skb, L2CAP_HDR_SIZE);
-
-	/* b-frame with too large information payload */
 	if (l2cap_pi(sk)->imtu < skb->len)
 		goto drop;
 
-	/* ordinary b-frame */
+	/* If socket recv buffers overflows we drop data here
+	 * which is *bad* because L2CAP has to be reliable.
+	 * But we don't have any other choice. L2CAP doesn't
+	 * provide flow control mechanism. */
+
 	if (!sock_queue_rcv_skb(sk, skb))
 		goto done;
 
@@ -2742,6 +1866,7 @@
 	struct l2cap_hdr *lh = (void *) skb->data;
 	u16 cid, psm, len;
 
+	skb_pull(skb, L2CAP_HDR_SIZE);
 	cid = __le16_to_cpu(lh->cid);
 	len = __le16_to_cpu(lh->len);
 
@@ -2749,12 +1874,10 @@
 
 	switch (cid) {
 	case 0x0001:
-		skb_pull(skb, L2CAP_HDR_SIZE);
 		l2cap_sig_channel(conn, skb);
 		break;
 
 	case 0x0002:
-		skb_pull(skb, L2CAP_HDR_SIZE);
 		psm = get_unaligned((u16 *) skb->data);
 		skb_pull(skb, 2);
 		l2cap_conless_channel(conn, psm, skb);
diff -ur --exclude-from=kernel-diff-exclude.txt linux-2.6.18-mh1/net/bluetooth/rfcomm/tty.c linux-2.6.18-my-bt/net/bluetooth/rfcomm/tty.c
--- linux-2.6.18-mh1/net/bluetooth/rfcomm/tty.c	2006-09-23 19:56:08.000000000 -0700
+++ linux-2.6.18-my-bt/net/bluetooth/rfcomm/tty.c	2006-09-23 22:46:43.000000000 -0700
@@ -38,7 +38,6 @@
 #include <linux/skbuff.h>
 
 #include <net/bluetooth/bluetooth.h>
-#include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/rfcomm.h>
 
 #ifndef CONFIG_BT_RFCOMM_DEBUG
@@ -162,24 +161,6 @@
 	return dev;
 }
 
-static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
-{
-	struct hci_dev *hdev;
-	struct hci_conn *conn;
-
-	hdev = hci_get_route(&dev->dst, &dev->src);
-	if (!hdev)
-		return NULL;
-
-	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst);
-	if (!conn)
-		return NULL;
-
-	hci_dev_put(hdev);
-
-	return &conn->dev;
-}
-
 static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
 {
 	struct rfcomm_dev *dev;
@@ -263,7 +244,7 @@
 		return err;
 	}
 
-	tty_register_device(rfcomm_tty_driver, dev->id, rfcomm_get_device(dev));
+	tty_register_device(rfcomm_tty_driver, dev->id, NULL);
 
 	return dev->id;
 }


[-- Attachment #3: Type: text/plain, Size: 348 bytes --]

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

[-- Attachment #4: Type: text/plain, Size: 164 bytes --]

_______________________________________________
Bluez-users mailing list
Bluez-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-users

  reply	other threads:[~2006-09-27  8:26 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-09-27  6:29 [Bluez-users] Microsoft IntelliMouse with kernel 2.6.18 and patch-2.6.18-mh1 is broken (fix provided) Andrey Jivsov
2006-09-27  7:52 ` Marcel Holtmann
2006-09-27  8:26   ` Andrey Jivsov [this message]
2006-09-29 11:52     ` [Bluez-users] Microsoft IntelliMouse with kernel 2.6.1 " Marcel Holtmann
2006-09-29 17:58       ` Andrey Jivsov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=451A35A1.6020309@brainhub.org \
    --to=bluetooth@brainhub.org \
    --cc=bluez-users@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox