Files linux-2.4.19-rmk6-pxa1-hh-virginal/drivers/net/wireless/bin_to_h and linux-2.4.19-rmk6-pxa1-hh/drivers/net/wireless/bin_to_h differ
diff -Nurd -x CVS -x .cvsignore linux-2.4.19-rmk6-pxa1-hh-virginal/include/net/bluetooth/hci_core.h linux-2.4.19-rmk6-pxa1-hh/include/net/bluetooth/hci_core.h
--- linux-2.4.19-rmk6-pxa1-hh-virginal/include/net/bluetooth/hci_core.h	2004-04-10 17:20:34.000000000 -0700
+++ linux-2.4.19-rmk6-pxa1-hh/include/net/bluetooth/hci_core.h	2005-05-24 12:29:37.067379877 -0700
@@ -322,6 +322,7 @@
 int hci_dev_close(__u16 dev);
 int hci_dev_reset(__u16 dev);
 int hci_dev_reset_stat(__u16 dev);
+int hci_reset_dev(struct hci_dev *hdev);
 int hci_dev_cmd(unsigned int cmd, unsigned long arg);
 int hci_get_dev_list(unsigned long arg);
 int hci_get_dev_info(unsigned long arg);
diff -Nurd -x CVS -x .cvsignore linux-2.4.19-rmk6-pxa1-hh-virginal/include/net/bluetooth/hci.h linux-2.4.19-rmk6-pxa1-hh/include/net/bluetooth/hci.h
--- linux-2.4.19-rmk6-pxa1-hh-virginal/include/net/bluetooth/hci.h	2005-05-24 14:09:25.792336436 -0700
+++ linux-2.4.19-rmk6-pxa1-hh/include/net/bluetooth/hci.h	2005-05-24 12:37:11.674558975 -0700
@@ -610,6 +610,11 @@
 } __attribute__ ((packed)) evt_read_remote_version_complete;
 #define EVT_READ_REMOTE_VERSION_COMPLETE_SIZE 8
 
+#define EVT_HARDWARE_ERROR 0x10
+typedef struct {
+	__u8    hwcode;
+} __attribute__ ((packed)) hci_ev_hardware_error;
+
 /* Internal events generated by BlueZ stack */
 #define EVT_STACK_INTERNAL	0xfd
 typedef struct {
Files linux-2.4.19-rmk6-pxa1-hh-virginal/lib/gen_crc32table and linux-2.4.19-rmk6-pxa1-hh/lib/gen_crc32table differ
diff -Nurd -x CVS -x .cvsignore linux-2.4.19-rmk6-pxa1-hh-virginal/net/bluetooth/hci_core.c linux-2.4.19-rmk6-pxa1-hh/net/bluetooth/hci_core.c
--- linux-2.4.19-rmk6-pxa1-hh-virginal/net/bluetooth/hci_core.c	2004-04-10 17:20:33.000000000 -0700
+++ linux-2.4.19-rmk6-pxa1-hh/net/bluetooth/hci_core.c	2005-05-24 12:34:51.395569713 -0700
@@ -642,6 +642,76 @@
 	return ret;
 }
 
+int hci_reset_dev(struct hci_dev *hdev)
+{
+	int ret = 0;
+	__u8 mode = 0;
+
+	hci_req_cancel(hdev, ENODEV);
+	hci_req_lock(hdev);
+
+	/* Disable RX and TX tasks */
+	tasklet_disable(&hdev->rx_task);
+	tasklet_disable(&hdev->tx_task);
+
+	/* Flush connection hash */
+	hci_dev_lock_bh(hdev);
+	hci_conn_hash_flush(hdev);
+	hci_dev_unlock_bh(hdev);
+
+	/* Flush driver */
+	if (hdev->flush)
+		hdev->flush(hdev);
+
+	/* Disable cmd task */
+	tasklet_disable(&hdev->cmd_task);
+
+	/* Drop queues */
+	skb_queue_purge(&hdev->rx_q);
+	skb_queue_purge(&hdev->cmd_q);
+	skb_queue_purge(&hdev->raw_q);
+
+	/* Reset command counter */
+	atomic_set(&hdev->cmd_cnt, 1);
+
+	/* Drop last sent command */
+	if (hdev->sent_cmd) {
+		kfree_skb(hdev->sent_cmd);
+		hdev->sent_cmd = NULL;
+	}
+
+	/* Send reset command */
+	hci_send_cmd(hdev, OGF_HOST_CTL, OCF_RESET, 0, NULL);
+
+	/* Reset ACL and SCO counters */
+	hdev->acl_cnt = hdev->acl_pkts;
+	hdev->sco_cnt = hdev->sco_pkts;
+
+	/* Restore device flags and state */
+	if (test_bit(HCI_ISCAN, &hdev->flags))
+		mode |= SCAN_INQUIRY;
+	if (test_bit(HCI_PSCAN, &hdev->flags))
+		mode |= SCAN_PAGE;
+	hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 1, &mode);
+
+	mode = test_bit(HCI_AUTH, &hdev->flags) ? AUTH_ENABLED : AUTH_DISABLED;
+	hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_AUTH_ENABLE, 1, &mode);
+
+	mode = test_bit(HCI_ENCRYPT, &hdev->flags) ? ENCRYPT_P2P : ENCRYPT_DISABLED;
+	hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_ENCRYPT_MODE, 1, &mode);
+
+	clear_bit(HCI_INQUIRY, &hdev->flags);
+
+	/* Enable tasks */
+	tasklet_enable(&hdev->rx_task);
+	tasklet_enable(&hdev->tx_task);
+	tasklet_enable(&hdev->cmd_task);
+
+	hci_req_unlock(hdev);
+
+	return ret;
+}
+
 int hci_dev_cmd(unsigned int cmd, unsigned long arg)
 {
 	struct hci_dev *hdev;
diff -Nurd -x CVS -x .cvsignore linux-2.4.19-rmk6-pxa1-hh-virginal/net/bluetooth/hci_event.c linux-2.4.19-rmk6-pxa1-hh/net/bluetooth/hci_event.c
--- linux-2.4.19-rmk6-pxa1-hh-virginal/net/bluetooth/hci_event.c	2005-05-24 14:09:25.265411579 -0700
+++ linux-2.4.19-rmk6-pxa1-hh/net/bluetooth/hci_event.c	2005-05-24 12:38:42.168648392 -0700
@@ -747,6 +747,20 @@
 	hci_dev_unlock(hdev);
 }
 
+/* Hardware Error */
+static inline void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct hci_ev_hardware_error *ev = (struct hci_ev_hardware_error *) skb->data;
+
+	BT_ERR("%s hardware error event", hdev->name);
+
+	/* Perform recovery procedure if the transport is UART */
+	if (hdev->type == HCI_UART) {
+		BT_ERR("%s performing H4 synchronization recovery procedure", hdev->name);
+		hci_reset_dev(hdev);
+	}
+}
+
 void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	hci_event_hdr *he = (hci_event_hdr *) skb->data;
@@ -799,6 +813,10 @@
 		hci_encrypt_change_evt(hdev, skb);
 		break;
 
+	case EVT_HARDWARE_ERROR:
+		hci_hardware_error_evt(hdev, skb);
+		break;
+
 	case EVT_CMD_STATUS:
 		cs = (evt_cmd_status *) skb->data;
 		skb_pull(skb, EVT_CMD_STATUS_SIZE);

