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
HCI UART (H4) protocol support
CONFIG_BLUEZ_HCIUART_H4
UART (H4) is serial protocol for communication between Bluetooth
device and host. This protocol is required for most UART based
Bluetooth device (including PCMCIA and CF).
device and host. This protocol is required for most Bluetooth devices
with UART interface, including PCMCIA and CF cards.
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
CONFIG_BLUEZ_HCIUSB
Bluetooth HCI USB driver.
......
......@@ -9,6 +9,7 @@ fi
dep_tristate 'HCI UART driver' CONFIG_BLUEZ_HCIUART $CONFIG_BLUEZ
if [ "$CONFIG_BLUEZ_HCIUART" != "n" ]; then
bool ' UART (H4) protocol support' CONFIG_BLUEZ_HCIUART_H4
bool ' BCSP protocol support' CONFIG_BLUEZ_HCIUART_BCSP
fi
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
hci_uart-y := hci_ldisc.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)
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 @@
/*
* 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/module.h>
......@@ -64,63 +64,61 @@
#endif
/* Initialize protocol */
static int h4_open(struct n_hci *n_hci)
static int h4_open(struct hci_uart *hu)
{
struct h4_struct *h4;
BT_DBG("n_hci %p", n_hci);
BT_DBG("hu %p", hu);
h4 = kmalloc(sizeof(*h4), GFP_ATOMIC);
if (!h4)
return -ENOMEM;
memset(h4, 0, sizeof(*h4));
n_hci->priv = h4;
skb_queue_head_init(&h4->txq);
hu->priv = h4;
return 0;
}
/* 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;
}
/* 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;
n_hci->priv = NULL;
struct h4_struct *h4 = hu->priv;
hu->priv = NULL;
BT_DBG("n_hci %p", n_hci);
BT_DBG("hu %p", hu);
skb_queue_purge(&h4->txq);
if (h4->rx_skb)
kfree_skb(h4->rx_skb);
hu->priv = NULL;
kfree(h4);
return 0;
}
/* Send data */
static int h4_send(struct n_hci *n_hci, void *data, int len)
/* Enqueue frame for transmittion (padding, crc, etc) */
static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb)
{
struct tty_struct *tty = n_hci->tty;
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);
}
struct h4_struct *h4 = hu->priv;
/* Init frame before queueing (padding, crc, etc) */
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);
BT_DBG("hu %p skb %p", hu, skb);
/* Prepend skb with frame type */
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)
......@@ -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);
hci_recv_frame(h4->rx_skb);
} else if (len > room) {
BT_ERR("Data length is to large");
BT_ERR("Data length is too large");
kfree_skb(h4->rx_skb);
} else {
h4->rx_state = H4_W4_DATA;
......@@ -147,16 +145,17 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len)
}
/* 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;
hci_event_hdr *eh;
hci_acl_hdr *ah;
hci_sco_hdr *sh;
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;
while (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);
continue;
};
}
}
/* H4_W4_PACKET_TYPE */
......@@ -232,7 +231,7 @@ static int h4_recv(struct n_hci *n_hci, void *data, int count)
default:
BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr);
n_hci->hdev.stat.err_rx++;
hu->hdev.stat.err_rx++;
ptr++; count--;
continue;
};
......@@ -246,20 +245,26 @@ static int h4_recv(struct n_hci *n_hci, void *data, int count)
h4->rx_count = 0;
return 0;
}
h4->rx_skb->dev = (void *) &n_hci->hdev;
h4->rx_skb->dev = (void *) &hu->hdev;
h4->rx_skb->pkt_type = type;
}
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 = {
.id = HCI_UART_H4,
.open = h4_open,
.close = h4_close,
.send = h4_send,
.recv = h4_recv,
.preq = h4_preq,
.flush = h4_flush,
.id = HCI_UART_H4,
.open = h4_open,
.close = h4_close,
.recv = h4_recv,
.enqueue = h4_enqueue,
.dequeue = h4_dequeue,
.flush = h4_flush,
};
int h4_init(void)
......
......@@ -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__
......@@ -31,6 +31,7 @@ struct h4_struct {
unsigned long rx_state;
unsigned long rx_count;
struct sk_buff *rx_skb;
struct sk_buff_head txq;
};
/* H4 receiver States */
......
This diff is collapsed.
......@@ -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
#endif
......@@ -42,19 +42,19 @@
#define HCI_UART_NCSP 2
#ifdef __KERNEL__
struct n_hci;
struct hci_uart;
struct hci_uart_proto {
unsigned int id;
int (*open)(struct n_hci *n_hci);
int (*recv)(struct n_hci *n_hci, void *data, int len);
int (*send)(struct n_hci *n_hci, void *data, int len);
int (*close)(struct n_hci *n_hci);
int (*flush)(struct n_hci *n_hci);
struct sk_buff* (*preq)(struct n_hci *n_hci, struct sk_buff *skb);
int (*open)(struct hci_uart *hu);
int (*close)(struct hci_uart *hu);
int (*flush)(struct hci_uart *hu);
int (*recv)(struct hci_uart *hu, void *data, int len);
int (*enqueue)(struct hci_uart *hu, struct sk_buff *skb);
struct sk_buff *(*dequeue)(struct hci_uart *hu);
};
struct n_hci {
struct hci_uart {
struct tty_struct *tty;
struct hci_dev hdev;
unsigned long flags;
......@@ -62,19 +62,20 @@ struct n_hci {
struct hci_uart_proto *proto;
void *priv;
struct sk_buff_head txq;
unsigned long tx_state;
spinlock_t rx_lock;
struct sk_buff *tx_skb;
unsigned long tx_state;
spinlock_t rx_lock;
};
/* N_HCI flag bits */
#define N_HCI_PROTO_SET 0x00
/* HCI_UART flag bits */
#define HCI_UART_PROTO_SET 0x00
/* TX states */
#define N_HCI_SENDING 1
#define N_HCI_TX_WAKEUP 2
#define HCI_UART_SENDING 1
#define HCI_UART_TX_WAKEUP 2
int hci_uart_register_proto(struct hci_uart_proto *p);
int hci_uart_unregister_proto(struct hci_uart_proto *p);
int hci_uart_tx_wakeup(struct hci_uart *hu);
#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