linux/drivers/bluetooth/hci_h4.c
<<
>>
Prefs
   1/*
   2 *
   3 *  Bluetooth HCI UART driver
   4 *
   5 *  Copyright (C) 2000-2001  Qualcomm Incorporated
   6 *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
   7 *  Copyright (C) 2004-2005  Marcel Holtmann <marcel@holtmann.org>
   8 *
   9 *
  10 *  This program is free software; you can redistribute it and/or modify
  11 *  it under the terms of the GNU General Public License as published by
  12 *  the Free Software Foundation; either version 2 of the License, or
  13 *  (at your option) any later version.
  14 *
  15 *  This program is distributed in the hope that it will be useful,
  16 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 *  GNU General Public License for more details.
  19 *
  20 *  You should have received a copy of the GNU General Public License
  21 *  along with this program; if not, write to the Free Software
  22 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  23 *
  24 */
  25
  26#include <linux/module.h>
  27
  28#include <linux/kernel.h>
  29#include <linux/init.h>
  30#include <linux/types.h>
  31#include <linux/fcntl.h>
  32#include <linux/interrupt.h>
  33#include <linux/ptrace.h>
  34#include <linux/poll.h>
  35
  36#include <linux/slab.h>
  37#include <linux/tty.h>
  38#include <linux/errno.h>
  39#include <linux/string.h>
  40#include <linux/signal.h>
  41#include <linux/ioctl.h>
  42#include <linux/skbuff.h>
  43
  44#include <net/bluetooth/bluetooth.h>
  45#include <net/bluetooth/hci_core.h>
  46
  47#include "hci_uart.h"
  48
  49#define VERSION "1.2"
  50
  51struct h4_struct {
  52        unsigned long rx_state;
  53        unsigned long rx_count;
  54        struct sk_buff *rx_skb;
  55        struct sk_buff_head txq;
  56};
  57
  58/* H4 receiver States */
  59#define H4_W4_PACKET_TYPE       0
  60#define H4_W4_EVENT_HDR         1
  61#define H4_W4_ACL_HDR           2
  62#define H4_W4_SCO_HDR           3
  63#define H4_W4_DATA              4
  64
  65/* Initialize protocol */
  66static int h4_open(struct hci_uart *hu)
  67{
  68        struct h4_struct *h4;
  69
  70        BT_DBG("hu %p", hu);
  71
  72        h4 = kzalloc(sizeof(*h4), GFP_KERNEL);
  73        if (!h4)
  74                return -ENOMEM;
  75
  76        skb_queue_head_init(&h4->txq);
  77
  78        hu->priv = h4;
  79        return 0;
  80}
  81
  82/* Flush protocol data */
  83static int h4_flush(struct hci_uart *hu)
  84{
  85        struct h4_struct *h4 = hu->priv;
  86
  87        BT_DBG("hu %p", hu);
  88
  89        skb_queue_purge(&h4->txq);
  90
  91        return 0;
  92}
  93
  94/* Close protocol */
  95static int h4_close(struct hci_uart *hu)
  96{
  97        struct h4_struct *h4 = hu->priv;
  98
  99        hu->priv = NULL;
 100
 101        BT_DBG("hu %p", hu);
 102
 103        skb_queue_purge(&h4->txq);
 104
 105        kfree_skb(h4->rx_skb);
 106
 107        hu->priv = NULL;
 108        kfree(h4);
 109
 110        return 0;
 111}
 112
 113/* Enqueue frame for transmittion (padding, crc, etc) */
 114static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb)
 115{
 116        struct h4_struct *h4 = hu->priv;
 117
 118        BT_DBG("hu %p skb %p", hu, skb);
 119
 120        /* Prepend skb with frame type */
 121        memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
 122        skb_queue_tail(&h4->txq, skb);
 123
 124        return 0;
 125}
 126
 127static inline int h4_check_data_len(struct h4_struct *h4, int len)
 128{
 129        int room = skb_tailroom(h4->rx_skb);
 130
 131        BT_DBG("len %d room %d", len, room);
 132
 133        if (!len) {
 134                hci_recv_frame(h4->rx_skb);
 135        } else if (len > room) {
 136                BT_ERR("Data length is too large");
 137                kfree_skb(h4->rx_skb);
 138        } else {
 139                h4->rx_state = H4_W4_DATA;
 140                h4->rx_count = len;
 141                return len;
 142        }
 143
 144        h4->rx_state = H4_W4_PACKET_TYPE;
 145        h4->rx_skb   = NULL;
 146        h4->rx_count = 0;
 147
 148        return 0;
 149}
 150
 151/* Recv data */
 152static int h4_recv(struct hci_uart *hu, void *data, int count)
 153{
 154        int ret;
 155
 156        ret = hci_recv_stream_fragment(hu->hdev, data, count);
 157        if (ret < 0) {
 158                BT_ERR("Frame Reassembly Failed");
 159                return ret;
 160        }
 161
 162        return count;
 163}
 164
 165static struct sk_buff *h4_dequeue(struct hci_uart *hu)
 166{
 167        struct h4_struct *h4 = hu->priv;
 168        return skb_dequeue(&h4->txq);
 169}
 170
 171static struct hci_uart_proto h4p = {
 172        .id             = HCI_UART_H4,
 173        .open           = h4_open,
 174        .close          = h4_close,
 175        .recv           = h4_recv,
 176        .enqueue        = h4_enqueue,
 177        .dequeue        = h4_dequeue,
 178        .flush          = h4_flush,
 179};
 180
 181int __init h4_init(void)
 182{
 183        int err = hci_uart_register_proto(&h4p);
 184
 185        if (!err)
 186                BT_INFO("HCI H4 protocol initialized");
 187        else
 188                BT_ERR("HCI H4 protocol registration failed");
 189
 190        return err;
 191}
 192
 193int __exit h4_deinit(void)
 194{
 195        return hci_uart_unregister_proto(&h4p);
 196}
 197
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.