Commit 0d453bba authored by Maksim Krasnyanskiy's avatar Maksim Krasnyanskiy Committed by Maksim Krasnyanskiy

Syncup HCI UART driver with 2.4.x.

New improved UART proto interface.
Support for BCSP protocol.
parent 4523ef76
...@@ -12,11 +12,20 @@ CONFIG_BLUEZ_HCIUART ...@@ -12,11 +12,20 @@ CONFIG_BLUEZ_HCIUART
HCI UART (H4) protocol support HCI UART (H4) protocol support
CONFIG_BLUEZ_HCIUART_H4 CONFIG_BLUEZ_HCIUART_H4
UART (H4) is serial protocol for communication between Bluetooth UART (H4) is serial protocol for communication between Bluetooth
device and host. This protocol is required for most UART based device and host. This protocol is required for most Bluetooth devices
Bluetooth device (including PCMCIA and CF). with UART interface, including PCMCIA and CF cards.
Say Y here to compile support for HCI UART (H4) protocol. Say Y here to compile support for HCI UART (H4) protocol.
HCI BCSP protocol support
CONFIG_BLUEZ_HCIUART_BCSP
BCSP (BlueCore Serial Protocol) is serial protocol for communication
between Bluetooth device and host. This protocol is required for non
USB Bluetooth devices based on CSR BlueCore chip, including PCMCIA and
CF cards.
Say Y here to compile support for HCI BCSP protocol.
HCI USB driver HCI USB driver
CONFIG_BLUEZ_HCIUSB CONFIG_BLUEZ_HCIUSB
Bluetooth HCI USB driver. Bluetooth HCI USB driver.
......
...@@ -9,6 +9,7 @@ fi ...@@ -9,6 +9,7 @@ fi
dep_tristate 'HCI UART driver' CONFIG_BLUEZ_HCIUART $CONFIG_BLUEZ dep_tristate 'HCI UART driver' CONFIG_BLUEZ_HCIUART $CONFIG_BLUEZ
if [ "$CONFIG_BLUEZ_HCIUART" != "n" ]; then if [ "$CONFIG_BLUEZ_HCIUART" != "n" ]; then
bool ' UART (H4) protocol support' CONFIG_BLUEZ_HCIUART_H4 bool ' UART (H4) protocol support' CONFIG_BLUEZ_HCIUART_H4
bool ' BCSP protocol support' CONFIG_BLUEZ_HCIUART_BCSP
fi fi
dep_tristate 'HCI DTL1 (PC Card) driver' CONFIG_BLUEZ_HCIDTL1 $CONFIG_PCMCIA $CONFIG_BLUEZ dep_tristate 'HCI DTL1 (PC Card) driver' CONFIG_BLUEZ_HCIDTL1 $CONFIG_PCMCIA $CONFIG_BLUEZ
......
...@@ -11,6 +11,7 @@ obj-$(CONFIG_BLUEZ_HCIBLUECARD) += bluecard_cs.o ...@@ -11,6 +11,7 @@ obj-$(CONFIG_BLUEZ_HCIBLUECARD) += bluecard_cs.o
hci_uart-y := hci_ldisc.o hci_uart-y := hci_ldisc.o
hci_uart-$(CONFIG_BLUEZ_HCIUART_H4) += hci_h4.o hci_uart-$(CONFIG_BLUEZ_HCIUART_H4) += hci_h4.o
hci_uart-$(CONFIG_BLUEZ_HCIUART_BCSP) += hci_bcsp.o
hci_uart-objs := $(hci_uart-y) hci_uart-objs := $(hci_uart-y)
include $(TOPDIR)/Rules.make include $(TOPDIR)/Rules.make
This diff is collapsed.
/*
BlueCore Serial Protocol (BCSP) for Linux Bluetooth stack (BlueZ).
Copyright 2002 by Fabrizio Gennari <fabrizio.gennari@philips.com>
Based on
hci_h4.c by Maxim Krasnyansky <maxk@qualcomm.com>
ABCSP by Carl Orsborn <cjo@csr.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation;
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED.
*/
/*
* $Id: hci_bcsp.h,v 1.2 2002/09/26 05:05:14 maxk Exp $
*/
#ifndef __HCI_BCSP_H__
#define __HCI_BCSP_H__
#define BCSP_TXWINSIZE 4
#define BCSP_ACK_PKT 0x05
#define BCSP_LE_PKT 0x06
struct bcsp_struct {
struct sk_buff_head unack; /* Unack'ed packets queue */
struct sk_buff_head rel; /* Reliable packets queue */
struct sk_buff_head unrel; /* Unreliable packets queue */
unsigned long rx_count;
struct sk_buff *rx_skb;
u8 rxseq_txack; /* rxseq == txack. */
u8 rxack; /* Last packet sent by us that the peer ack'ed */
struct timer_list tbcsp;
enum {
BCSP_W4_PKT_DELIMITER,
BCSP_W4_PKT_START,
BCSP_W4_BCSP_HDR,
BCSP_W4_DATA,
BCSP_W4_CRC
} rx_state;
enum {
BCSP_ESCSTATE_NOESC,
BCSP_ESCSTATE_ESC
} rx_esc_state;
u16 message_crc;
u8 txack_req; /* Do we need to send ack's to the peer? */
/* Reliable packet sequence number - used to assign seq to each rel pkt. */
u8 msgq_txseq;
};
#endif /* __HCI_BCSP_H__ */
...@@ -25,9 +25,9 @@ ...@@ -25,9 +25,9 @@
/* /*
* BlueZ HCI UART(H4) protocol. * BlueZ HCI UART(H4) protocol.
* *
* $Id: hci_h4.c,v 1.2 2002/04/17 17:37:20 maxk Exp $ * $Id: hci_h4.c,v 1.3 2002/09/09 01:17:32 maxk Exp $
*/ */
#define VERSION "1.1" #define VERSION "1.2"
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -64,63 +64,61 @@ ...@@ -64,63 +64,61 @@
#endif #endif
/* Initialize protocol */ /* Initialize protocol */
static int h4_open(struct n_hci *n_hci) static int h4_open(struct hci_uart *hu)
{ {
struct h4_struct *h4; struct h4_struct *h4;
BT_DBG("n_hci %p", n_hci); BT_DBG("hu %p", hu);
h4 = kmalloc(sizeof(*h4), GFP_ATOMIC); h4 = kmalloc(sizeof(*h4), GFP_ATOMIC);
if (!h4) if (!h4)
return -ENOMEM; return -ENOMEM;
memset(h4, 0, sizeof(*h4)); memset(h4, 0, sizeof(*h4));
n_hci->priv = h4; skb_queue_head_init(&h4->txq);
hu->priv = h4;
return 0; return 0;
} }
/* Flush protocol data */ /* Flush protocol data */
static int h4_flush(struct n_hci *n_hci) static int h4_flush(struct hci_uart *hu)
{ {
BT_DBG("n_hci %p", n_hci); struct h4_struct *h4 = hu->priv;
BT_DBG("hu %p", hu);
skb_queue_purge(&h4->txq);
return 0; return 0;
} }
/* Close protocol */ /* Close protocol */
static int h4_close(struct n_hci *n_hci) static int h4_close(struct hci_uart *hu)
{ {
struct h4_struct *h4 = n_hci->priv; struct h4_struct *h4 = hu->priv;
n_hci->priv = NULL; hu->priv = NULL;
BT_DBG("n_hci %p", n_hci); BT_DBG("hu %p", hu);
skb_queue_purge(&h4->txq);
if (h4->rx_skb) if (h4->rx_skb)
kfree_skb(h4->rx_skb); kfree_skb(h4->rx_skb);
hu->priv = NULL;
kfree(h4); kfree(h4);
return 0; return 0;
} }
/* Send data */ /* Enqueue frame for transmittion (padding, crc, etc) */
static int h4_send(struct n_hci *n_hci, void *data, int len) static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb)
{ {
struct tty_struct *tty = n_hci->tty; struct h4_struct *h4 = hu->priv;
BT_DBG("n_hci %p len %d", n_hci, len);
/* Send frame to TTY driver */
tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
return tty->driver.write(tty, 0, data, len);
}
/* Init frame before queueing (padding, crc, etc) */ BT_DBG("hu %p skb %p", hu, skb);
static struct sk_buff* h4_preq(struct n_hci *n_hci, struct sk_buff *skb)
{
BT_DBG("n_hci %p skb %p", n_hci, skb);
/* Prepend skb with frame type */ /* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &skb->pkt_type, 1); memcpy(skb_push(skb, 1), &skb->pkt_type, 1);
return skb; skb_queue_tail(&h4->txq, skb);
return 0;
} }
static inline int h4_check_data_len(struct h4_struct *h4, int len) static inline int h4_check_data_len(struct h4_struct *h4, int len)
...@@ -132,7 +130,7 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len) ...@@ -132,7 +130,7 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len)
BT_DMP(h4->rx_skb->data, h4->rx_skb->len); BT_DMP(h4->rx_skb->data, h4->rx_skb->len);
hci_recv_frame(h4->rx_skb); hci_recv_frame(h4->rx_skb);
} else if (len > room) { } else if (len > room) {
BT_ERR("Data length is to large"); BT_ERR("Data length is too large");
kfree_skb(h4->rx_skb); kfree_skb(h4->rx_skb);
} else { } else {
h4->rx_state = H4_W4_DATA; h4->rx_state = H4_W4_DATA;
...@@ -147,16 +145,17 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len) ...@@ -147,16 +145,17 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len)
} }
/* Recv data */ /* Recv data */
static int h4_recv(struct n_hci *n_hci, void *data, int count) static int h4_recv(struct hci_uart *hu, void *data, int count)
{ {
struct h4_struct *h4 = n_hci->priv; struct h4_struct *h4 = hu->priv;
register char *ptr; register char *ptr;
hci_event_hdr *eh; hci_event_hdr *eh;
hci_acl_hdr *ah; hci_acl_hdr *ah;
hci_sco_hdr *sh; hci_sco_hdr *sh;
register int len, type, dlen; register int len, type, dlen;
BT_DBG("n_hci %p count %d rx_state %ld rx_count %ld", n_hci, count, h4->rx_state, h4->rx_count); BT_DBG("hu %p count %d rx_state %ld rx_count %ld",
hu, count, h4->rx_state, h4->rx_count);
ptr = data; ptr = data;
while (count) { while (count) {
...@@ -204,7 +203,7 @@ static int h4_recv(struct n_hci *n_hci, void *data, int count) ...@@ -204,7 +203,7 @@ static int h4_recv(struct n_hci *n_hci, void *data, int count)
h4_check_data_len(h4, sh->dlen); h4_check_data_len(h4, sh->dlen);
continue; continue;
}; }
} }
/* H4_W4_PACKET_TYPE */ /* H4_W4_PACKET_TYPE */
...@@ -232,7 +231,7 @@ static int h4_recv(struct n_hci *n_hci, void *data, int count) ...@@ -232,7 +231,7 @@ static int h4_recv(struct n_hci *n_hci, void *data, int count)
default: default:
BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr); BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr);
n_hci->hdev.stat.err_rx++; hu->hdev.stat.err_rx++;
ptr++; count--; ptr++; count--;
continue; continue;
}; };
...@@ -246,20 +245,26 @@ static int h4_recv(struct n_hci *n_hci, void *data, int count) ...@@ -246,20 +245,26 @@ static int h4_recv(struct n_hci *n_hci, void *data, int count)
h4->rx_count = 0; h4->rx_count = 0;
return 0; return 0;
} }
h4->rx_skb->dev = (void *) &n_hci->hdev; h4->rx_skb->dev = (void *) &hu->hdev;
h4->rx_skb->pkt_type = type; h4->rx_skb->pkt_type = type;
} }
return count; return count;
} }
static struct sk_buff *h4_dequeue(struct hci_uart *hu)
{
struct h4_struct *h4 = hu->priv;
return skb_dequeue(&h4->txq);
}
static struct hci_uart_proto h4p = { static struct hci_uart_proto h4p = {
.id = HCI_UART_H4, .id = HCI_UART_H4,
.open = h4_open, .open = h4_open,
.close = h4_close, .close = h4_close,
.send = h4_send, .recv = h4_recv,
.recv = h4_recv, .enqueue = h4_enqueue,
.preq = h4_preq, .dequeue = h4_dequeue,
.flush = h4_flush, .flush = h4_flush,
}; };
int h4_init(void) int h4_init(void)
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
*/ */
/* /*
* $Id: hci_h4.h,v 1.1.1.1 2002/03/08 21:03:15 maxk Exp $ * $Id: hci_h4.h,v 1.2 2002/09/09 01:17:32 maxk Exp $
*/ */
#ifdef __KERNEL__ #ifdef __KERNEL__
...@@ -31,6 +31,7 @@ struct h4_struct { ...@@ -31,6 +31,7 @@ struct h4_struct {
unsigned long rx_state; unsigned long rx_state;
unsigned long rx_count; unsigned long rx_count;
struct sk_buff *rx_skb; struct sk_buff *rx_skb;
struct sk_buff_head txq;
}; };
/* H4 receiver States */ /* H4 receiver States */
......
This diff is collapsed.
...@@ -23,10 +23,10 @@ ...@@ -23,10 +23,10 @@
*/ */
/* /*
* $Id: hci_uart.h,v 1.1.1.1 2002/03/08 21:03:15 maxk Exp $ * $Id: hci_uart.h,v 1.2 2002/09/09 01:17:32 maxk Exp $
*/ */
#ifndef N_HCI #ifndef N_HCI
#define N_HCI 15 #define N_HCI 15
#endif #endif
...@@ -42,19 +42,19 @@ ...@@ -42,19 +42,19 @@
#define HCI_UART_NCSP 2 #define HCI_UART_NCSP 2
#ifdef __KERNEL__ #ifdef __KERNEL__
struct n_hci; struct hci_uart;
struct hci_uart_proto { struct hci_uart_proto {
unsigned int id; unsigned int id;
int (*open)(struct n_hci *n_hci); int (*open)(struct hci_uart *hu);
int (*recv)(struct n_hci *n_hci, void *data, int len); int (*close)(struct hci_uart *hu);
int (*send)(struct n_hci *n_hci, void *data, int len); int (*flush)(struct hci_uart *hu);
int (*close)(struct n_hci *n_hci); int (*recv)(struct hci_uart *hu, void *data, int len);
int (*flush)(struct n_hci *n_hci); int (*enqueue)(struct hci_uart *hu, struct sk_buff *skb);
struct sk_buff* (*preq)(struct n_hci *n_hci, struct sk_buff *skb); struct sk_buff *(*dequeue)(struct hci_uart *hu);
}; };
struct n_hci { struct hci_uart {
struct tty_struct *tty; struct tty_struct *tty;
struct hci_dev hdev; struct hci_dev hdev;
unsigned long flags; unsigned long flags;
...@@ -62,19 +62,20 @@ struct n_hci { ...@@ -62,19 +62,20 @@ struct n_hci {
struct hci_uart_proto *proto; struct hci_uart_proto *proto;
void *priv; void *priv;
struct sk_buff_head txq; struct sk_buff *tx_skb;
unsigned long tx_state; unsigned long tx_state;
spinlock_t rx_lock; spinlock_t rx_lock;
}; };
/* N_HCI flag bits */ /* HCI_UART flag bits */
#define N_HCI_PROTO_SET 0x00 #define HCI_UART_PROTO_SET 0x00
/* TX states */ /* TX states */
#define N_HCI_SENDING 1 #define HCI_UART_SENDING 1
#define N_HCI_TX_WAKEUP 2 #define HCI_UART_TX_WAKEUP 2
int hci_uart_register_proto(struct hci_uart_proto *p); int hci_uart_register_proto(struct hci_uart_proto *p);
int hci_uart_unregister_proto(struct hci_uart_proto *p); int hci_uart_unregister_proto(struct hci_uart_proto *p);
int hci_uart_tx_wakeup(struct hci_uart *hu);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment