11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 30372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann * Bluetooth HCI UART driver 40372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann * 50372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann * Copyright (C) 2000-2001 Qualcomm Incorporated 60372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com> 70372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org> 80372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann * 90372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann * 100372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann * This program is free software; you can redistribute it and/or modify 110372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann * it under the terms of the GNU General Public License as published by 120372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann * the Free Software Foundation; either version 2 of the License, or 130372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann * (at your option) any later version. 140372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann * 150372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann * This program is distributed in the hope that it will be useful, 160372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann * but WITHOUT ANY WARRANTY; without even the implied warranty of 170372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 180372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann * GNU General Public License for more details. 190372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann * 200372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann * You should have received a copy of the GNU General Public License 210372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann * along with this program; if not, write to the Free Software 220372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 230372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann * 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fcntl.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ptrace.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/poll.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/signal.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioctl.h> 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h> 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/bluetooth/bluetooth.h> 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/bluetooth/hci_core.h> 460372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "hci_uart.h" 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 490372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann#define VERSION "1.2" 500372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann 510372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmannstruct h4_struct { 520372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann unsigned long rx_state; 530372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann unsigned long rx_count; 540372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann struct sk_buff *rx_skb; 550372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann struct sk_buff_head txq; 560372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann}; 570372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann 580372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann/* H4 receiver States */ 590372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann#define H4_W4_PACKET_TYPE 0 600372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann#define H4_W4_EVENT_HDR 1 610372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann#define H4_W4_ACL_HDR 2 620372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann#define H4_W4_SCO_HDR 3 630372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann#define H4_W4_DATA 4 640372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Initialize protocol */ 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int h4_open(struct hci_uart *hu) 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct h4_struct *h4; 690372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("hu %p", hu); 710372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann 72fdcd1661a6b22e3ac429759627d2b4d68f77d64aDavid Herrmann h4 = kzalloc(sizeof(*h4), GFP_KERNEL); 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!h4) 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 750372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_head_init(&h4->txq); 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hu->priv = h4; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Flush protocol data */ 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int h4_flush(struct hci_uart *hu) 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct h4_struct *h4 = hu->priv; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("hu %p", hu); 880372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_purge(&h4->txq); 900372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Close protocol */ 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int h4_close(struct hci_uart *hu) 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct h4_struct *h4 = hu->priv; 980372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hu->priv = NULL; 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("hu %p", hu); 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_purge(&h4->txq); 1040372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann 105b1fb06830dc870d862f7f80e276130c0ab84d59fWei Yongjun kfree_skb(h4->rx_skb); 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hu->priv = NULL; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(h4); 1090372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Enqueue frame for transmittion (padding, crc, etc) */ 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb) 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct h4_struct *h4 = hu->priv; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("hu %p skb %p", hu, skb); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Prepend skb with frame type */ 1210d48d93947dd9ea21c5cdc76a8581b06a4a39281Marcel Holtmann memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_tail(&h4->txq, skb); 1230372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int h4_check_data_len(struct h4_struct *h4, int len) 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds register int room = skb_tailroom(h4->rx_skb); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("len %d room %d", len, room); 1320372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!len) { 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hci_recv_frame(h4->rx_skb); 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (len > room) { 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_ERR("Data length is too large"); 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree_skb(h4->rx_skb); 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h4->rx_state = H4_W4_DATA; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h4->rx_count = len; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return len; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h4->rx_state = H4_W4_PACKET_TYPE; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h4->rx_skb = NULL; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h4->rx_count = 0; 1470372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Recv data */ 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int h4_recv(struct hci_uart *hu, void *data, int count) 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 154b86ed368f1f0b19de1918c57e4b056e73d5613a0Gustavo F. Padovan int ret; 155b86ed368f1f0b19de1918c57e4b056e73d5613a0Gustavo F. Padovan 156b86ed368f1f0b19de1918c57e4b056e73d5613a0Gustavo F. Padovan ret = hci_recv_stream_fragment(hu->hdev, data, count); 157b86ed368f1f0b19de1918c57e4b056e73d5613a0Gustavo F. Padovan if (ret < 0) { 158e9da101f6d0c9a8fda9f78a80365ba2a9f75603fGustavo F. Padovan BT_ERR("Frame Reassembly Failed"); 159b86ed368f1f0b19de1918c57e4b056e73d5613a0Gustavo F. Padovan return ret; 160b86ed368f1f0b19de1918c57e4b056e73d5613a0Gustavo F. Padovan } 1610372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sk_buff *h4_dequeue(struct hci_uart *hu) 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct h4_struct *h4 = hu->priv; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return skb_dequeue(&h4->txq); 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct hci_uart_proto h4p = { 1720372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann .id = HCI_UART_H4, 1730372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann .open = h4_open, 1740372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann .close = h4_close, 1750372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann .recv = h4_recv, 1760372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann .enqueue = h4_enqueue, 1770372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann .dequeue = h4_dequeue, 1780372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann .flush = h4_flush, 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1800372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann 181f2b94bb9e0b8bd048331a6e9d616e918f4bcbd97Gustavo F. Padovanint __init h4_init(void) 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = hci_uart_register_proto(&h4p); 1840372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!err) 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_INFO("HCI H4 protocol initialized"); 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_ERR("HCI H4 protocol registration failed"); 1890372a6627f862f90a2c43772befeecef508cfd7bMarcel Holtmann 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 193f2b94bb9e0b8bd048331a6e9d616e918f4bcbd97Gustavo F. Padovanint __exit h4_deinit(void) 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return hci_uart_unregister_proto(&h4p); 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 197