Commit de514416 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo

Merge master.kernel.org:/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6

parents 8ed57590 245dc3d1
...@@ -55,14 +55,6 @@ config BT_HCIUART_BCSP ...@@ -55,14 +55,6 @@ config BT_HCIUART_BCSP
Say Y here to compile support for HCI BCSP protocol. Say Y here to compile support for HCI BCSP protocol.
config BT_HCIUART_BCSP_TXCRC
bool "Transmit CRC with every BCSP packet"
depends on BT_HCIUART_BCSP
help
If you say Y here, a 16-bit CRC checksum will be transmitted along with
every BCSP (BlueCore Serial Protocol) packet sent to the Bluetooth chip.
This increases reliability, but slightly reduces efficiency.
config BT_HCIBCM203X config BT_HCIBCM203X
tristate "HCI BCM203x USB driver" tristate "HCI BCM203x USB driver"
depends on USB depends on USB
......
...@@ -550,6 +550,9 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id * ...@@ -550,6 +550,9 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
if (ignore) if (ignore)
return -ENODEV; return -ENODEV;
if (intf->cur_altsetting->desc.bInterfaceNumber > 0)
return -ENODEV;
data = kmalloc(sizeof(*data), GFP_KERNEL); data = kmalloc(sizeof(*data), GFP_KERNEL);
if (!data) { if (!data) {
BT_ERR("Can't allocate data structure"); BT_ERR("Can't allocate data structure");
......
/*
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.c,v 1.2 2002/09/26 05:05:14 maxk Exp $ *
* Bluetooth HCI UART driver
*
* Copyright (C) 2002-2003 Fabrizio Gennari <fabrizio.gennari@philips.com>
* Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/ */
#define VERSION "0.2"
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -52,16 +44,56 @@ ...@@ -52,16 +44,56 @@
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
#include "hci_uart.h" #include "hci_uart.h"
#include "hci_bcsp.h"
#ifndef CONFIG_BT_HCIUART_DEBUG #ifndef CONFIG_BT_HCIUART_DEBUG
#undef BT_DBG #undef BT_DBG
#define BT_DBG( A... ) #define BT_DBG( A... )
#endif #endif
#define VERSION "0.3"
static int txcrc = 1;
static int hciextn = 1; static int hciextn = 1;
#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;
u8 use_crc;
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;
};
/* ---- BCSP CRC calculation ---- */ /* ---- BCSP CRC calculation ---- */
/* Table for calculating CRC for polynomial 0x1021, LSB processed first, /* Table for calculating CRC for polynomial 0x1021, LSB processed first,
...@@ -111,6 +143,7 @@ static u16 bcsp_crc_reverse(u16 crc) ...@@ -111,6 +143,7 @@ static u16 bcsp_crc_reverse(u16 crc)
rev |= (crc & 1); rev |= (crc & 1);
crc = crc >> 1; crc = crc >> 1;
} }
return (rev); return (rev);
} }
...@@ -119,6 +152,7 @@ static u16 bcsp_crc_reverse(u16 crc) ...@@ -119,6 +152,7 @@ static u16 bcsp_crc_reverse(u16 crc)
static void bcsp_slip_msgdelim(struct sk_buff *skb) static void bcsp_slip_msgdelim(struct sk_buff *skb)
{ {
const char pkt_delim = 0xc0; const char pkt_delim = 0xc0;
memcpy(skb_put(skb, 1), &pkt_delim, 1); memcpy(skb_put(skb, 1), &pkt_delim, 1);
} }
...@@ -173,11 +207,8 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data, ...@@ -173,11 +207,8 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
{ {
struct sk_buff *nskb; struct sk_buff *nskb;
u8 hdr[4], chan; u8 hdr[4], chan;
int rel, i;
#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
u16 BCSP_CRC_INIT(bcsp_txmsg_crc); u16 BCSP_CRC_INIT(bcsp_txmsg_crc);
#endif int rel, i;
switch (pkt_type) { switch (pkt_type) {
case HCI_ACLDATA_PKT: case HCI_ACLDATA_PKT:
...@@ -240,9 +271,9 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data, ...@@ -240,9 +271,9 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
BT_DBG("Sending packet with seqno %u", bcsp->msgq_txseq); BT_DBG("Sending packet with seqno %u", bcsp->msgq_txseq);
bcsp->msgq_txseq = ++(bcsp->msgq_txseq) & 0x07; bcsp->msgq_txseq = ++(bcsp->msgq_txseq) & 0x07;
} }
#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
hdr[0] |= 0x40; if (bcsp->use_crc)
#endif hdr[0] |= 0x40;
hdr[1] = ((len << 4) & 0xff) | chan; hdr[1] = ((len << 4) & 0xff) | chan;
hdr[2] = len >> 4; hdr[2] = len >> 4;
...@@ -251,25 +282,25 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data, ...@@ -251,25 +282,25 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
/* Put BCSP header */ /* Put BCSP header */
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
bcsp_slip_one_byte(nskb, hdr[i]); bcsp_slip_one_byte(nskb, hdr[i]);
#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
bcsp_crc_update(&bcsp_txmsg_crc, hdr[i]); if (bcsp->use_crc)
#endif bcsp_crc_update(&bcsp_txmsg_crc, hdr[i]);
} }
/* Put payload */ /* Put payload */
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
bcsp_slip_one_byte(nskb, data[i]); bcsp_slip_one_byte(nskb, data[i]);
#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
bcsp_crc_update(&bcsp_txmsg_crc, data[i]); if (bcsp->use_crc)
#endif bcsp_crc_update(&bcsp_txmsg_crc, data[i]);
} }
#ifdef CONFIG_BT_HCIUART_BCSP_TXCRC
/* Put CRC */ /* Put CRC */
bcsp_txmsg_crc = bcsp_crc_reverse(bcsp_txmsg_crc); if (bcsp->use_crc) {
bcsp_slip_one_byte(nskb, (u8) ((bcsp_txmsg_crc >> 8) & 0x00ff)); bcsp_txmsg_crc = bcsp_crc_reverse(bcsp_txmsg_crc);
bcsp_slip_one_byte(nskb, (u8) (bcsp_txmsg_crc & 0x00ff)); bcsp_slip_one_byte(nskb, (u8) ((bcsp_txmsg_crc >> 8) & 0x00ff));
#endif bcsp_slip_one_byte(nskb, (u8) (bcsp_txmsg_crc & 0x00ff));
}
bcsp_slip_msgdelim(nskb); bcsp_slip_msgdelim(nskb);
return nskb; return nskb;
...@@ -317,7 +348,6 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu) ...@@ -317,7 +348,6 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu)
spin_unlock_irqrestore(&bcsp->unack.lock, flags); spin_unlock_irqrestore(&bcsp->unack.lock, flags);
/* We could not send a reliable packet, either because there are /* We could not send a reliable packet, either because there are
none or because there are too many unack'ed pkts. Did we receive none or because there are too many unack'ed pkts. Did we receive
any packets we have not acknowledged yet ? */ any packets we have not acknowledged yet ? */
...@@ -363,7 +393,7 @@ static void bcsp_pkt_cull(struct bcsp_struct *bcsp) ...@@ -363,7 +393,7 @@ static void bcsp_pkt_cull(struct bcsp_struct *bcsp)
BT_ERR("Peer acked invalid packet"); BT_ERR("Peer acked invalid packet");
BT_DBG("Removing %u pkts out of %u, up to seqno %u", BT_DBG("Removing %u pkts out of %u, up to seqno %u",
pkts_to_be_removed, bcsp->unack.qlen, (seqno - 1) & 0x07); pkts_to_be_removed, bcsp->unack.qlen, (seqno - 1) & 0x07);
for (i = 0, skb = ((struct sk_buff *) &bcsp->unack)->next; i < pkts_to_be_removed for (i = 0, skb = ((struct sk_buff *) &bcsp->unack)->next; i < pkts_to_be_removed
&& skb != (struct sk_buff *) &bcsp->unack; i++) { && skb != (struct sk_buff *) &bcsp->unack; i++) {
...@@ -374,8 +404,10 @@ static void bcsp_pkt_cull(struct bcsp_struct *bcsp) ...@@ -374,8 +404,10 @@ static void bcsp_pkt_cull(struct bcsp_struct *bcsp)
kfree_skb(skb); kfree_skb(skb);
skb = nskb; skb = nskb;
} }
if (bcsp->unack.qlen == 0) if (bcsp->unack.qlen == 0)
del_timer(&bcsp->tbcsp); del_timer(&bcsp->tbcsp);
spin_unlock_irqrestore(&bcsp->unack.lock, flags); spin_unlock_irqrestore(&bcsp->unack.lock, flags);
if (i != pkts_to_be_removed) if (i != pkts_to_be_removed)
...@@ -530,6 +562,7 @@ static inline void bcsp_complete_rx_pkt(struct hci_uart *hu) ...@@ -530,6 +562,7 @@ static inline void bcsp_complete_rx_pkt(struct hci_uart *hu)
hci_recv_frame(bcsp->rx_skb); hci_recv_frame(bcsp->rx_skb);
} }
bcsp->rx_state = BCSP_W4_PKT_DELIMITER; bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
bcsp->rx_skb = NULL; bcsp->rx_skb = NULL;
} }
...@@ -598,8 +631,8 @@ static int bcsp_recv(struct hci_uart *hu, void *data, int count) ...@@ -598,8 +631,8 @@ static int bcsp_recv(struct hci_uart *hu, void *data, int count)
BT_ERR ("Checksum failed: computed %04x received %04x", BT_ERR ("Checksum failed: computed %04x received %04x",
bcsp_crc_reverse(bcsp->message_crc), bcsp_crc_reverse(bcsp->message_crc),
(bcsp->rx_skb-> data[bcsp->rx_skb->len - 2] << 8) + (bcsp->rx_skb-> data[bcsp->rx_skb->len - 2] << 8) +
bcsp->rx_skb->data[bcsp->rx_skb->len - 1]); bcsp->rx_skb->data[bcsp->rx_skb->len - 1]);
kfree_skb(bcsp->rx_skb); kfree_skb(bcsp->rx_skb);
bcsp->rx_state = BCSP_W4_PKT_DELIMITER; bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
...@@ -633,7 +666,7 @@ static int bcsp_recv(struct hci_uart *hu, void *data, int count) ...@@ -633,7 +666,7 @@ static int bcsp_recv(struct hci_uart *hu, void *data, int count)
bcsp->rx_count = 4; bcsp->rx_count = 4;
bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC; bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC;
BCSP_CRC_INIT(bcsp->message_crc); BCSP_CRC_INIT(bcsp->message_crc);
/* Do not increment ptr or decrement count /* Do not increment ptr or decrement count
* Allocate packet. Max len of a BCSP pkt= * Allocate packet. Max len of a BCSP pkt=
* 0xFFF (payload) +4 (header) +2 (crc) */ * 0xFFF (payload) +4 (header) +2 (crc) */
...@@ -698,6 +731,9 @@ static int bcsp_open(struct hci_uart *hu) ...@@ -698,6 +731,9 @@ static int bcsp_open(struct hci_uart *hu)
bcsp->rx_state = BCSP_W4_PKT_DELIMITER; bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
if (txcrc)
bcsp->use_crc = 1;
return 0; return 0;
} }
...@@ -718,18 +754,19 @@ static int bcsp_close(struct hci_uart *hu) ...@@ -718,18 +754,19 @@ static int bcsp_close(struct hci_uart *hu)
} }
static struct hci_uart_proto bcsp = { static struct hci_uart_proto bcsp = {
.id = HCI_UART_BCSP, .id = HCI_UART_BCSP,
.open = bcsp_open, .open = bcsp_open,
.close = bcsp_close, .close = bcsp_close,
.enqueue = bcsp_enqueue, .enqueue = bcsp_enqueue,
.dequeue = bcsp_dequeue, .dequeue = bcsp_dequeue,
.recv = bcsp_recv, .recv = bcsp_recv,
.flush = bcsp_flush .flush = bcsp_flush
}; };
int bcsp_init(void) int bcsp_init(void)
{ {
int err = hci_uart_register_proto(&bcsp); int err = hci_uart_register_proto(&bcsp);
if (!err) if (!err)
BT_INFO("HCI BCSP protocol initialized"); BT_INFO("HCI BCSP protocol initialized");
else else
...@@ -743,5 +780,8 @@ int bcsp_deinit(void) ...@@ -743,5 +780,8 @@ int bcsp_deinit(void)
return hci_uart_unregister_proto(&bcsp); return hci_uart_unregister_proto(&bcsp);
} }
module_param(txcrc, bool, 0644);
MODULE_PARM_DESC(txcrc, "Transmit CRC with every BCSP packet");
module_param(hciextn, bool, 0644); module_param(hciextn, bool, 0644);
MODULE_PARM_DESC(hciextn, "Convert HCI Extensions into BCSP packets"); MODULE_PARM_DESC(hciextn, "Convert HCI Extensions into BCSP packets");
/*
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__ */
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.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.
*/
/* /*
* Bluetooth HCI UART(H4) protocol.
* *
* $Id: hci_h4.c,v 1.3 2002/09/09 01:17:32 maxk Exp $ * Bluetooth HCI UART driver
*
* 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
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/ */
#define VERSION "1.2"
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -51,24 +45,41 @@ ...@@ -51,24 +45,41 @@
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
#include "hci_uart.h" #include "hci_uart.h"
#include "hci_h4.h"
#ifndef CONFIG_BT_HCIUART_DEBUG #ifndef CONFIG_BT_HCIUART_DEBUG
#undef BT_DBG #undef BT_DBG
#define BT_DBG( A... ) #define BT_DBG( A... )
#endif #endif
#define VERSION "1.2"
struct h4_struct {
unsigned long rx_state;
unsigned long rx_count;
struct sk_buff *rx_skb;
struct sk_buff_head txq;
};
/* H4 receiver States */
#define H4_W4_PACKET_TYPE 0
#define H4_W4_EVENT_HDR 1
#define H4_W4_ACL_HDR 2
#define H4_W4_SCO_HDR 3
#define H4_W4_DATA 4
/* Initialize protocol */ /* Initialize protocol */
static int h4_open(struct hci_uart *hu) static int h4_open(struct hci_uart *hu)
{ {
struct h4_struct *h4; struct h4_struct *h4;
BT_DBG("hu %p", hu); 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));
skb_queue_head_init(&h4->txq); skb_queue_head_init(&h4->txq);
...@@ -83,7 +94,9 @@ static int h4_flush(struct hci_uart *hu) ...@@ -83,7 +94,9 @@ static int h4_flush(struct hci_uart *hu)
struct h4_struct *h4 = hu->priv; struct h4_struct *h4 = hu->priv;
BT_DBG("hu %p", hu); BT_DBG("hu %p", hu);
skb_queue_purge(&h4->txq); skb_queue_purge(&h4->txq);
return 0; return 0;
} }
...@@ -91,16 +104,19 @@ static int h4_flush(struct hci_uart *hu) ...@@ -91,16 +104,19 @@ static int h4_flush(struct hci_uart *hu)
static int h4_close(struct hci_uart *hu) static int h4_close(struct hci_uart *hu)
{ {
struct h4_struct *h4 = hu->priv; struct h4_struct *h4 = hu->priv;
hu->priv = NULL; hu->priv = NULL;
BT_DBG("hu %p", hu); BT_DBG("hu %p", hu);
skb_queue_purge(&h4->txq); 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; hu->priv = NULL;
kfree(h4); kfree(h4);
return 0; return 0;
} }
...@@ -114,6 +130,7 @@ static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb) ...@@ -114,6 +130,7 @@ static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb)
/* Prepend skb with frame type */ /* Prepend skb with frame type */
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
skb_queue_tail(&h4->txq, skb); skb_queue_tail(&h4->txq, skb);
return 0; return 0;
} }
...@@ -122,6 +139,7 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len) ...@@ -122,6 +139,7 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len)
register int room = skb_tailroom(h4->rx_skb); register int room = skb_tailroom(h4->rx_skb);
BT_DBG("len %d room %d", len, room); BT_DBG("len %d room %d", len, room);
if (!len) { if (!len) {
hci_recv_frame(h4->rx_skb); hci_recv_frame(h4->rx_skb);
} else if (len > room) { } else if (len > room) {
...@@ -136,6 +154,7 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len) ...@@ -136,6 +154,7 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len)
h4->rx_state = H4_W4_PACKET_TYPE; h4->rx_state = H4_W4_PACKET_TYPE;
h4->rx_skb = NULL; h4->rx_skb = NULL;
h4->rx_count = 0; h4->rx_count = 0;
return 0; return 0;
} }
...@@ -228,6 +247,7 @@ static int h4_recv(struct hci_uart *hu, void *data, int count) ...@@ -228,6 +247,7 @@ static int h4_recv(struct hci_uart *hu, void *data, int count)
ptr++; count--; ptr++; count--;
continue; continue;
}; };
ptr++; count--; ptr++; count--;
/* Allocate packet */ /* Allocate packet */
...@@ -238,9 +258,11 @@ static int h4_recv(struct hci_uart *hu, void *data, int count) ...@@ -238,9 +258,11 @@ static int h4_recv(struct hci_uart *hu, void *data, int count)
h4->rx_count = 0; h4->rx_count = 0;
return 0; return 0;
} }
h4->rx_skb->dev = (void *) hu->hdev; h4->rx_skb->dev = (void *) hu->hdev;
bt_cb(h4->rx_skb)->pkt_type = type; bt_cb(h4->rx_skb)->pkt_type = type;
} }
return count; return count;
} }
...@@ -251,23 +273,24 @@ static struct sk_buff *h4_dequeue(struct hci_uart *hu) ...@@ -251,23 +273,24 @@ static struct sk_buff *h4_dequeue(struct hci_uart *hu)
} }
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,
.recv = h4_recv, .recv = h4_recv,
.enqueue = h4_enqueue, .enqueue = h4_enqueue,
.dequeue = h4_dequeue, .dequeue = h4_dequeue,
.flush = h4_flush, .flush = h4_flush,
}; };
int h4_init(void) int h4_init(void)
{ {
int err = hci_uart_register_proto(&h4p); int err = hci_uart_register_proto(&h4p);
if (!err) if (!err)
BT_INFO("HCI H4 protocol initialized"); BT_INFO("HCI H4 protocol initialized");
else else
BT_ERR("HCI H4 protocol registration failed"); BT_ERR("HCI H4 protocol registration failed");
return err; return err;
} }
......
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.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_h4.h,v 1.2 2002/09/09 01:17:32 maxk Exp $
*/
#ifdef __KERNEL__
struct h4_struct {
unsigned long rx_state;
unsigned long rx_count;
struct sk_buff *rx_skb;
struct sk_buff_head txq;
};
/* H4 receiver States */
#define H4_W4_PACKET_TYPE 0
#define H4_W4_EVENT_HDR 1
#define H4_W4_ACL_HDR 2
#define H4_W4_SCO_HDR 3
#define H4_W4_DATA 4
#endif /* __KERNEL__ */
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.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.
*/
/* /*
* Bluetooth HCI UART driver.
* *
* $Id: hci_ldisc.c,v 1.5 2002/10/02 18:37:20 maxk Exp $ * Bluetooth HCI UART driver
*
* 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
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/ */
#define VERSION "2.1"
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -59,6 +53,8 @@ ...@@ -59,6 +53,8 @@
#define BT_DBG( A... ) #define BT_DBG( A... )
#endif #endif
#define VERSION "2.2"
static int reset = 0; static int reset = 0;
static struct hci_uart_proto *hup[HCI_UART_MAX_PROTO]; static struct hci_uart_proto *hup[HCI_UART_MAX_PROTO];
...@@ -72,6 +68,7 @@ int hci_uart_register_proto(struct hci_uart_proto *p) ...@@ -72,6 +68,7 @@ int hci_uart_register_proto(struct hci_uart_proto *p)
return -EEXIST; return -EEXIST;
hup[p->id] = p; hup[p->id] = p;
return 0; return 0;
} }
...@@ -84,6 +81,7 @@ int hci_uart_unregister_proto(struct hci_uart_proto *p) ...@@ -84,6 +81,7 @@ int hci_uart_unregister_proto(struct hci_uart_proto *p)
return -EINVAL; return -EINVAL;
hup[p->id] = NULL; hup[p->id] = NULL;
return 0; return 0;
} }
...@@ -91,13 +89,14 @@ static struct hci_uart_proto *hci_uart_get_proto(unsigned int id) ...@@ -91,13 +89,14 @@ static struct hci_uart_proto *hci_uart_get_proto(unsigned int id)
{ {
if (id >= HCI_UART_MAX_PROTO) if (id >= HCI_UART_MAX_PROTO)
return NULL; return NULL;
return hup[id]; return hup[id];
} }
static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type) static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type)
{ {
struct hci_dev *hdev = hu->hdev; struct hci_dev *hdev = hu->hdev;
/* Update HCI stat counters */ /* Update HCI stat counters */
switch (pkt_type) { switch (pkt_type) {
case HCI_COMMAND_PKT: case HCI_COMMAND_PKT:
...@@ -117,10 +116,12 @@ static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type) ...@@ -117,10 +116,12 @@ static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type)
static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu) static inline struct sk_buff *hci_uart_dequeue(struct hci_uart *hu)
{ {
struct sk_buff *skb = hu->tx_skb; struct sk_buff *skb = hu->tx_skb;
if (!skb) if (!skb)
skb = hu->proto->dequeue(hu); skb = hu->proto->dequeue(hu);
else else
hu->tx_skb = NULL; hu->tx_skb = NULL;
return skb; return skb;
} }
...@@ -129,7 +130,7 @@ int hci_uart_tx_wakeup(struct hci_uart *hu) ...@@ -129,7 +130,7 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
struct tty_struct *tty = hu->tty; struct tty_struct *tty = hu->tty;
struct hci_dev *hdev = hu->hdev; struct hci_dev *hdev = hu->hdev;
struct sk_buff *skb; struct sk_buff *skb;
if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) { if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) {
set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state); set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
return 0; return 0;
...@@ -142,7 +143,7 @@ int hci_uart_tx_wakeup(struct hci_uart *hu) ...@@ -142,7 +143,7 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
while ((skb = hci_uart_dequeue(hu))) { while ((skb = hci_uart_dequeue(hu))) {
int len; int len;
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
len = tty->driver->write(tty, skb->data, skb->len); len = tty->driver->write(tty, skb->data, skb->len);
hdev->stat.byte_tx += len; hdev->stat.byte_tx += len;
...@@ -152,11 +153,11 @@ int hci_uart_tx_wakeup(struct hci_uart *hu) ...@@ -152,11 +153,11 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
hu->tx_skb = skb; hu->tx_skb = skb;
break; break;
} }
hci_uart_tx_complete(hu, bt_cb(skb)->pkt_type); hci_uart_tx_complete(hu, bt_cb(skb)->pkt_type);
kfree_skb(skb); kfree_skb(skb);
} }
if (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state)) if (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state))
goto restart; goto restart;
...@@ -173,6 +174,7 @@ static int hci_uart_open(struct hci_dev *hdev) ...@@ -173,6 +174,7 @@ static int hci_uart_open(struct hci_dev *hdev)
/* Nothing to do for UART driver */ /* Nothing to do for UART driver */
set_bit(HCI_RUNNING, &hdev->flags); set_bit(HCI_RUNNING, &hdev->flags);
return 0; return 0;
} }
...@@ -234,6 +236,7 @@ static int hci_uart_send_frame(struct sk_buff *skb) ...@@ -234,6 +236,7 @@ static int hci_uart_send_frame(struct sk_buff *skb)
hu->proto->enqueue(hu, skb); hu->proto->enqueue(hu, skb);
hci_uart_tx_wakeup(hu); hci_uart_tx_wakeup(hu);
return 0; return 0;
} }
...@@ -241,7 +244,8 @@ static void hci_uart_destruct(struct hci_dev *hdev) ...@@ -241,7 +244,8 @@ static void hci_uart_destruct(struct hci_dev *hdev)
{ {
struct hci_uart *hu; struct hci_uart *hu;
if (!hdev) return; if (!hdev)
return;
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
...@@ -272,6 +276,7 @@ static int hci_uart_tty_open(struct tty_struct *tty) ...@@ -272,6 +276,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
BT_ERR("Can't allocate controll structure"); BT_ERR("Can't allocate controll structure");
return -ENFILE; return -ENFILE;
} }
memset(hu, 0, sizeof(struct hci_uart)); memset(hu, 0, sizeof(struct hci_uart));
tty->disc_data = hu; tty->disc_data = hu;
...@@ -280,8 +285,10 @@ static int hci_uart_tty_open(struct tty_struct *tty) ...@@ -280,8 +285,10 @@ static int hci_uart_tty_open(struct tty_struct *tty)
spin_lock_init(&hu->rx_lock); spin_lock_init(&hu->rx_lock);
/* Flush any pending characters in the driver and line discipline. */ /* Flush any pending characters in the driver and line discipline. */
/* FIXME: why is this needed. Note don't use ldisc_ref here as the /* FIXME: why is this needed. Note don't use ldisc_ref here as the
open path is before the ldisc is referencable */ open path is before the ldisc is referencable */
if (tty->ldisc.flush_buffer) if (tty->ldisc.flush_buffer)
tty->ldisc.flush_buffer(tty); tty->ldisc.flush_buffer(tty);
...@@ -372,13 +379,13 @@ static int hci_uart_tty_room (struct tty_struct *tty) ...@@ -372,13 +379,13 @@ static int hci_uart_tty_room (struct tty_struct *tty)
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; struct hci_uart *hu = (void *)tty->disc_data;
if (!hu || tty != hu->tty) if (!hu || tty != hu->tty)
return; return;
if (!test_bit(HCI_UART_PROTO_SET, &hu->flags)) if (!test_bit(HCI_UART_PROTO_SET, &hu->flags))
return; return;
spin_lock(&hu->rx_lock); spin_lock(&hu->rx_lock);
hu->proto->recv(hu, (void *) data, count); hu->proto->recv(hu, (void *) data, count);
hu->hdev->stat.byte_rx += count; hu->hdev->stat.byte_rx += count;
...@@ -429,8 +436,8 @@ static int hci_uart_register_dev(struct hci_uart *hu) ...@@ -429,8 +436,8 @@ static int hci_uart_register_dev(struct hci_uart *hu)
static int hci_uart_set_proto(struct hci_uart *hu, int id) static int hci_uart_set_proto(struct hci_uart *hu, int id)
{ {
struct hci_uart_proto *p; struct hci_uart_proto *p;
int err; int err;
p = hci_uart_get_proto(id); p = hci_uart_get_proto(id);
if (!p) if (!p)
return -EPROTONOSUPPORT; return -EPROTONOSUPPORT;
...@@ -446,6 +453,7 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id) ...@@ -446,6 +453,7 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id)
p->close(hu); p->close(hu);
return err; return err;
} }
return 0; return 0;
} }
...@@ -463,7 +471,7 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id) ...@@ -463,7 +471,7 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id)
* Return Value: Command dependent * Return Value: Command dependent
*/ */
static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file, static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
struct hci_uart *hu = (void *)tty->disc_data; struct hci_uart *hu = (void *)tty->disc_data;
int err = 0; int err = 0;
...@@ -483,14 +491,14 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file, ...@@ -483,14 +491,14 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
return err; return err;
} }
tty->low_latency = 1; tty->low_latency = 1;
} else } else
return -EBUSY; return -EBUSY;
case HCIUARTGETPROTO: case HCIUARTGETPROTO:
if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
return hu->proto->id; return hu->proto->id;
return -EUNATCH; return -EUNATCH;
default: default:
err = n_tty_ioctl(tty, file, cmd, arg); err = n_tty_ioctl(tty, file, cmd, arg);
break; break;
...@@ -502,28 +510,24 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file, ...@@ -502,28 +510,24 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
/* /*
* We don't provide read/write/poll interface for user space. * We don't provide read/write/poll interface for user space.
*/ */
static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file, unsigned char __user *buf, size_t nr) static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file,
unsigned char __user *buf, size_t nr)
{ {
return 0; return 0;
} }
static ssize_t hci_uart_tty_write(struct tty_struct *tty, struct file *file, const unsigned char *data, size_t count)
static ssize_t hci_uart_tty_write(struct tty_struct *tty, struct file *file,
const unsigned char *data, size_t count)
{ {
return 0; return 0;
} }
static unsigned int hci_uart_tty_poll(struct tty_struct *tty, struct file *filp, poll_table *wait)
static unsigned int hci_uart_tty_poll(struct tty_struct *tty,
struct file *filp, poll_table *wait)
{ {
return 0; return 0;
} }
#ifdef CONFIG_BT_HCIUART_H4
int h4_init(void);
int h4_deinit(void);
#endif
#ifdef CONFIG_BT_HCIUART_BCSP
int bcsp_init(void);
int bcsp_deinit(void);
#endif
static int __init hci_uart_init(void) static int __init hci_uart_init(void)
{ {
static struct tty_ldisc hci_uart_ldisc; static struct tty_ldisc hci_uart_ldisc;
...@@ -534,18 +538,18 @@ static int __init hci_uart_init(void) ...@@ -534,18 +538,18 @@ static int __init hci_uart_init(void)
/* Register the tty discipline */ /* Register the tty discipline */
memset(&hci_uart_ldisc, 0, sizeof (hci_uart_ldisc)); memset(&hci_uart_ldisc, 0, sizeof (hci_uart_ldisc));
hci_uart_ldisc.magic = TTY_LDISC_MAGIC; hci_uart_ldisc.magic = TTY_LDISC_MAGIC;
hci_uart_ldisc.name = "n_hci"; hci_uart_ldisc.name = "n_hci";
hci_uart_ldisc.open = hci_uart_tty_open; hci_uart_ldisc.open = hci_uart_tty_open;
hci_uart_ldisc.close = hci_uart_tty_close; hci_uart_ldisc.close = hci_uart_tty_close;
hci_uart_ldisc.read = hci_uart_tty_read; hci_uart_ldisc.read = hci_uart_tty_read;
hci_uart_ldisc.write = hci_uart_tty_write; hci_uart_ldisc.write = hci_uart_tty_write;
hci_uart_ldisc.ioctl = hci_uart_tty_ioctl; hci_uart_ldisc.ioctl = hci_uart_tty_ioctl;
hci_uart_ldisc.poll = hci_uart_tty_poll; hci_uart_ldisc.poll = hci_uart_tty_poll;
hci_uart_ldisc.receive_room= hci_uart_tty_room; hci_uart_ldisc.receive_room = hci_uart_tty_room;
hci_uart_ldisc.receive_buf = hci_uart_tty_receive; hci_uart_ldisc.receive_buf = hci_uart_tty_receive;
hci_uart_ldisc.write_wakeup= hci_uart_tty_wakeup; hci_uart_ldisc.write_wakeup = hci_uart_tty_wakeup;
hci_uart_ldisc.owner = THIS_MODULE; hci_uart_ldisc.owner = THIS_MODULE;
if ((err = tty_register_ldisc(N_HCI, &hci_uart_ldisc))) { if ((err = tty_register_ldisc(N_HCI, &hci_uart_ldisc))) {
BT_ERR("HCI line discipline registration failed. (%d)", err); BT_ERR("HCI line discipline registration failed. (%d)", err);
......
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.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_uart.h,v 1.2 2002/09/09 01:17:32 maxk Exp $ *
* Bluetooth HCI UART driver
*
* 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
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/ */
#ifndef N_HCI #ifndef N_HCI
#define N_HCI 15 #define N_HCI 15
#endif #endif
...@@ -42,7 +39,6 @@ ...@@ -42,7 +39,6 @@
#define HCI_UART_3WIRE 2 #define HCI_UART_3WIRE 2
#define HCI_UART_H4DS 3 #define HCI_UART_H4DS 3
#ifdef __KERNEL__
struct hci_uart; struct hci_uart;
struct hci_uart_proto { struct hci_uart_proto {
...@@ -56,27 +52,35 @@ struct hci_uart_proto { ...@@ -56,27 +52,35 @@ struct hci_uart_proto {
}; };
struct hci_uart { 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;
struct hci_uart_proto *proto; struct hci_uart_proto *proto;
void *priv; void *priv;
struct sk_buff *tx_skb; struct sk_buff *tx_skb;
unsigned long tx_state; unsigned long tx_state;
spinlock_t rx_lock; spinlock_t rx_lock;
}; };
/* HCI_UART flag bits */ /* HCI_UART flag bits */
#define HCI_UART_PROTO_SET 0 #define HCI_UART_PROTO_SET 0
/* TX states */ /* TX states */
#define HCI_UART_SENDING 1 #define HCI_UART_SENDING 1
#define HCI_UART_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); int hci_uart_tx_wakeup(struct hci_uart *hu);
#endif /* __KERNEL__ */ #ifdef CONFIG_BT_HCIUART_H4
int h4_init(void);
int h4_deinit(void);
#endif
#ifdef CONFIG_BT_HCIUART_BCSP
int bcsp_init(void);
int bcsp_deinit(void);
#endif
...@@ -171,4 +171,10 @@ static inline int skb_frags_no(struct sk_buff *skb) ...@@ -171,4 +171,10 @@ static inline int skb_frags_no(struct sk_buff *skb)
int bt_err(__u16 code); int bt_err(__u16 code);
extern int hci_sock_init(void);
extern int hci_sock_cleanup(void);
extern int bt_sysfs_init(void);
extern void bt_sysfs_cleanup(void);
#endif /* __BLUETOOTH_H */ #endif /* __BLUETOOTH_H */
...@@ -275,9 +275,6 @@ static inline void rfcomm_session_hold(struct rfcomm_session *s) ...@@ -275,9 +275,6 @@ static inline void rfcomm_session_hold(struct rfcomm_session *s)
atomic_inc(&s->refcnt); atomic_inc(&s->refcnt);
} }
/* ---- RFCOMM chechsum ---- */
extern u8 rfcomm_crc_table[];
/* ---- RFCOMM sockets ---- */ /* ---- RFCOMM sockets ---- */
struct sockaddr_rc { struct sockaddr_rc {
sa_family_t rc_family; sa_family_t rc_family;
......
...@@ -308,12 +308,6 @@ static struct net_proto_family bt_sock_family_ops = { ...@@ -308,12 +308,6 @@ static struct net_proto_family bt_sock_family_ops = {
.create = bt_sock_create, .create = bt_sock_create,
}; };
extern int hci_sock_init(void);
extern int hci_sock_cleanup(void);
extern int bt_sysfs_init(void);
extern int bt_sysfs_cleanup(void);
static int __init bt_init(void) static int __init bt_init(void)
{ {
BT_INFO("Core ver %s", VERSION); BT_INFO("Core ver %s", VERSION);
......
...@@ -87,7 +87,7 @@ int hci_unregister_notifier(struct notifier_block *nb) ...@@ -87,7 +87,7 @@ int hci_unregister_notifier(struct notifier_block *nb)
return notifier_chain_unregister(&hci_notifier, nb); return notifier_chain_unregister(&hci_notifier, nb);
} }
void hci_notify(struct hci_dev *hdev, int event) static void hci_notify(struct hci_dev *hdev, int event)
{ {
notifier_call_chain(&hci_notifier, event, hdev); notifier_call_chain(&hci_notifier, event, hdev);
} }
...@@ -1347,7 +1347,7 @@ static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -1347,7 +1347,7 @@ static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
kfree_skb(skb); kfree_skb(skb);
} }
void hci_rx_task(unsigned long arg) static void hci_rx_task(unsigned long arg)
{ {
struct hci_dev *hdev = (struct hci_dev *) arg; struct hci_dev *hdev = (struct hci_dev *) arg;
struct sk_buff *skb; struct sk_buff *skb;
......
...@@ -66,20 +66,20 @@ static struct hci_sec_filter hci_sec_filter = { ...@@ -66,20 +66,20 @@ static struct hci_sec_filter hci_sec_filter = {
/* Packet types */ /* Packet types */
0x10, 0x10,
/* Events */ /* Events */
{ 0x1000d9fe, 0x0000300c }, { 0x1000d9fe, 0x0000b00c },
/* Commands */ /* Commands */
{ {
{ 0x0 }, { 0x0 },
/* OGF_LINK_CTL */ /* OGF_LINK_CTL */
{ 0xbe000006, 0x00000001, 0x0000, 0x00 }, { 0xbe000006, 0x00000001, 0x000000, 0x00 },
/* OGF_LINK_POLICY */ /* OGF_LINK_POLICY */
{ 0x00005200, 0x00000000, 0x0000, 0x00 }, { 0x00005200, 0x00000000, 0x000000, 0x00 },
/* OGF_HOST_CTL */ /* OGF_HOST_CTL */
{ 0xaab00200, 0x2b402aaa, 0x0154, 0x00 }, { 0xaab00200, 0x2b402aaa, 0x020154, 0x00 },
/* OGF_INFO_PARAM */ /* OGF_INFO_PARAM */
{ 0x000002be, 0x00000000, 0x0000, 0x00 }, { 0x000002be, 0x00000000, 0x000000, 0x00 },
/* OGF_STATUS_PARAM */ /* OGF_STATUS_PARAM */
{ 0x000000ea, 0x00000000, 0x0000, 0x00 } { 0x000000ea, 0x00000000, 0x000000, 0x00 }
} }
}; };
......
...@@ -4,5 +4,5 @@ ...@@ -4,5 +4,5 @@
obj-$(CONFIG_BT_RFCOMM) += rfcomm.o obj-$(CONFIG_BT_RFCOMM) += rfcomm.o
rfcomm-y := core.o sock.o crc.o rfcomm-y := core.o sock.o
rfcomm-$(CONFIG_BT_RFCOMM_TTY) += tty.o rfcomm-$(CONFIG_BT_RFCOMM_TTY) += tty.o
...@@ -133,6 +133,49 @@ static inline void rfcomm_session_put(struct rfcomm_session *s) ...@@ -133,6 +133,49 @@ static inline void rfcomm_session_put(struct rfcomm_session *s)
/* ---- RFCOMM FCS computation ---- */ /* ---- RFCOMM FCS computation ---- */
/* reversed, 8-bit, poly=0x07 */
static unsigned char rfcomm_crc_table[256] = {
0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
};
/* CRC on 2 bytes */ /* CRC on 2 bytes */
#define __crc(data) (rfcomm_crc_table[rfcomm_crc_table[0xff ^ data[0]] ^ data[1]]) #define __crc(data) (rfcomm_crc_table[rfcomm_crc_table[0xff ^ data[0]] ^ data[1]])
......
/*
RFCOMM implementation for Linux Bluetooth stack (BlueZ).
Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
Copyright (C) 2002 Marcel Holtmann <marcel@holtmann.org>
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.
*/
/*
* RFCOMM FCS calculation.
*
* $Id: crc.c,v 1.2 2002/09/21 09:54:32 holtmann Exp $
*/
/* reversed, 8-bit, poly=0x07 */
unsigned char rfcomm_crc_table[256] = {
0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
};
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