1166d2f6aSOhad Ben-Cohen /* 2166d2f6aSOhad Ben-Cohen * Texas Instruments' Bluetooth HCILL UART protocol 3166d2f6aSOhad Ben-Cohen * 4166d2f6aSOhad Ben-Cohen * HCILL (HCI Low Level) is a Texas Instruments' power management 5166d2f6aSOhad Ben-Cohen * protocol extension to H4. 6166d2f6aSOhad Ben-Cohen * 7166d2f6aSOhad Ben-Cohen * Copyright (C) 2007 Texas Instruments, Inc. 8166d2f6aSOhad Ben-Cohen * 9166d2f6aSOhad Ben-Cohen * Written by Ohad Ben-Cohen <ohad@bencohen.org> 10166d2f6aSOhad Ben-Cohen * 11166d2f6aSOhad Ben-Cohen * Acknowledgements: 12166d2f6aSOhad Ben-Cohen * This file is based on hci_h4.c, which was written 13166d2f6aSOhad Ben-Cohen * by Maxim Krasnyansky and Marcel Holtmann. 14166d2f6aSOhad Ben-Cohen * 15166d2f6aSOhad Ben-Cohen * This program is free software; you can redistribute it and/or modify 16166d2f6aSOhad Ben-Cohen * it under the terms of the GNU General Public License version 2 17166d2f6aSOhad Ben-Cohen * as published by the Free Software Foundation 18166d2f6aSOhad Ben-Cohen * 19166d2f6aSOhad Ben-Cohen * This program is distributed in the hope that it will be useful, 20166d2f6aSOhad Ben-Cohen * but WITHOUT ANY WARRANTY; without even the implied warranty of 21166d2f6aSOhad Ben-Cohen * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22166d2f6aSOhad Ben-Cohen * GNU General Public License for more details. 23166d2f6aSOhad Ben-Cohen * 24166d2f6aSOhad Ben-Cohen * You should have received a copy of the GNU General Public License 25166d2f6aSOhad Ben-Cohen * along with this program; if not, write to the Free Software 26166d2f6aSOhad Ben-Cohen * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27166d2f6aSOhad Ben-Cohen * 28166d2f6aSOhad Ben-Cohen */ 29166d2f6aSOhad Ben-Cohen 30166d2f6aSOhad Ben-Cohen #include <linux/module.h> 31166d2f6aSOhad Ben-Cohen #include <linux/kernel.h> 32166d2f6aSOhad Ben-Cohen 33166d2f6aSOhad Ben-Cohen #include <linux/init.h> 34166d2f6aSOhad Ben-Cohen #include <linux/sched.h> 35166d2f6aSOhad Ben-Cohen #include <linux/types.h> 36166d2f6aSOhad Ben-Cohen #include <linux/fcntl.h> 37166d2f6aSOhad Ben-Cohen #include <linux/interrupt.h> 38166d2f6aSOhad Ben-Cohen #include <linux/ptrace.h> 39166d2f6aSOhad Ben-Cohen #include <linux/poll.h> 40166d2f6aSOhad Ben-Cohen 41166d2f6aSOhad Ben-Cohen #include <linux/slab.h> 42166d2f6aSOhad Ben-Cohen #include <linux/tty.h> 43166d2f6aSOhad Ben-Cohen #include <linux/errno.h> 44166d2f6aSOhad Ben-Cohen #include <linux/string.h> 45166d2f6aSOhad Ben-Cohen #include <linux/signal.h> 46166d2f6aSOhad Ben-Cohen #include <linux/ioctl.h> 47166d2f6aSOhad Ben-Cohen #include <linux/skbuff.h> 48166d2f6aSOhad Ben-Cohen 49166d2f6aSOhad Ben-Cohen #include <net/bluetooth/bluetooth.h> 50166d2f6aSOhad Ben-Cohen #include <net/bluetooth/hci_core.h> 51166d2f6aSOhad Ben-Cohen 52166d2f6aSOhad Ben-Cohen #include "hci_uart.h" 53166d2f6aSOhad Ben-Cohen 54166d2f6aSOhad Ben-Cohen /* HCILL commands */ 55166d2f6aSOhad Ben-Cohen #define HCILL_GO_TO_SLEEP_IND 0x30 56166d2f6aSOhad Ben-Cohen #define HCILL_GO_TO_SLEEP_ACK 0x31 57166d2f6aSOhad Ben-Cohen #define HCILL_WAKE_UP_IND 0x32 58166d2f6aSOhad Ben-Cohen #define HCILL_WAKE_UP_ACK 0x33 59166d2f6aSOhad Ben-Cohen 60166d2f6aSOhad Ben-Cohen /* HCILL receiver States */ 61166d2f6aSOhad Ben-Cohen #define HCILL_W4_PACKET_TYPE 0 62166d2f6aSOhad Ben-Cohen #define HCILL_W4_EVENT_HDR 1 63166d2f6aSOhad Ben-Cohen #define HCILL_W4_ACL_HDR 2 64166d2f6aSOhad Ben-Cohen #define HCILL_W4_SCO_HDR 3 65166d2f6aSOhad Ben-Cohen #define HCILL_W4_DATA 4 66166d2f6aSOhad Ben-Cohen 67166d2f6aSOhad Ben-Cohen /* HCILL states */ 68166d2f6aSOhad Ben-Cohen enum hcill_states_e { 69166d2f6aSOhad Ben-Cohen HCILL_ASLEEP, 70166d2f6aSOhad Ben-Cohen HCILL_ASLEEP_TO_AWAKE, 71166d2f6aSOhad Ben-Cohen HCILL_AWAKE, 72166d2f6aSOhad Ben-Cohen HCILL_AWAKE_TO_ASLEEP 73166d2f6aSOhad Ben-Cohen }; 74166d2f6aSOhad Ben-Cohen 75166d2f6aSOhad Ben-Cohen struct hcill_cmd { 76166d2f6aSOhad Ben-Cohen u8 cmd; 7781ca405aSGustavo F. Padovan } __packed; 78166d2f6aSOhad Ben-Cohen 79166d2f6aSOhad Ben-Cohen struct ll_struct { 80166d2f6aSOhad Ben-Cohen unsigned long rx_state; 81166d2f6aSOhad Ben-Cohen unsigned long rx_count; 82166d2f6aSOhad Ben-Cohen struct sk_buff *rx_skb; 83166d2f6aSOhad Ben-Cohen struct sk_buff_head txq; 84166d2f6aSOhad Ben-Cohen spinlock_t hcill_lock; /* HCILL state lock */ 85166d2f6aSOhad Ben-Cohen unsigned long hcill_state; /* HCILL power state */ 86166d2f6aSOhad Ben-Cohen struct sk_buff_head tx_wait_q; /* HCILL wait queue */ 87166d2f6aSOhad Ben-Cohen }; 88166d2f6aSOhad Ben-Cohen 89166d2f6aSOhad Ben-Cohen /* 90166d2f6aSOhad Ben-Cohen * Builds and sends an HCILL command packet. 91166d2f6aSOhad Ben-Cohen * These are very simple packets with only 1 cmd byte 92166d2f6aSOhad Ben-Cohen */ 93166d2f6aSOhad Ben-Cohen static int send_hcill_cmd(u8 cmd, struct hci_uart *hu) 94166d2f6aSOhad Ben-Cohen { 95166d2f6aSOhad Ben-Cohen int err = 0; 96166d2f6aSOhad Ben-Cohen struct sk_buff *skb = NULL; 97166d2f6aSOhad Ben-Cohen struct ll_struct *ll = hu->priv; 98166d2f6aSOhad Ben-Cohen struct hcill_cmd *hcill_packet; 99166d2f6aSOhad Ben-Cohen 100166d2f6aSOhad Ben-Cohen BT_DBG("hu %p cmd 0x%x", hu, cmd); 101166d2f6aSOhad Ben-Cohen 102166d2f6aSOhad Ben-Cohen /* allocate packet */ 103166d2f6aSOhad Ben-Cohen skb = bt_skb_alloc(1, GFP_ATOMIC); 104166d2f6aSOhad Ben-Cohen if (!skb) { 105166d2f6aSOhad Ben-Cohen BT_ERR("cannot allocate memory for HCILL packet"); 106166d2f6aSOhad Ben-Cohen err = -ENOMEM; 107166d2f6aSOhad Ben-Cohen goto out; 108166d2f6aSOhad Ben-Cohen } 109166d2f6aSOhad Ben-Cohen 110166d2f6aSOhad Ben-Cohen /* prepare packet */ 111166d2f6aSOhad Ben-Cohen hcill_packet = (struct hcill_cmd *) skb_put(skb, 1); 112166d2f6aSOhad Ben-Cohen hcill_packet->cmd = cmd; 113166d2f6aSOhad Ben-Cohen skb->dev = (void *) hu->hdev; 114166d2f6aSOhad Ben-Cohen 115166d2f6aSOhad Ben-Cohen /* send packet */ 116166d2f6aSOhad Ben-Cohen skb_queue_tail(&ll->txq, skb); 117166d2f6aSOhad Ben-Cohen out: 118166d2f6aSOhad Ben-Cohen return err; 119166d2f6aSOhad Ben-Cohen } 120166d2f6aSOhad Ben-Cohen 121166d2f6aSOhad Ben-Cohen /* Initialize protocol */ 122166d2f6aSOhad Ben-Cohen static int ll_open(struct hci_uart *hu) 123166d2f6aSOhad Ben-Cohen { 124166d2f6aSOhad Ben-Cohen struct ll_struct *ll; 125166d2f6aSOhad Ben-Cohen 126166d2f6aSOhad Ben-Cohen BT_DBG("hu %p", hu); 127166d2f6aSOhad Ben-Cohen 128*9eb648c3SDavid Herrmann ll = kzalloc(sizeof(*ll), GFP_KERNEL); 129166d2f6aSOhad Ben-Cohen if (!ll) 130166d2f6aSOhad Ben-Cohen return -ENOMEM; 131166d2f6aSOhad Ben-Cohen 132166d2f6aSOhad Ben-Cohen skb_queue_head_init(&ll->txq); 133166d2f6aSOhad Ben-Cohen skb_queue_head_init(&ll->tx_wait_q); 134166d2f6aSOhad Ben-Cohen spin_lock_init(&ll->hcill_lock); 135166d2f6aSOhad Ben-Cohen 136166d2f6aSOhad Ben-Cohen ll->hcill_state = HCILL_AWAKE; 137166d2f6aSOhad Ben-Cohen 138166d2f6aSOhad Ben-Cohen hu->priv = ll; 139166d2f6aSOhad Ben-Cohen 140166d2f6aSOhad Ben-Cohen return 0; 141166d2f6aSOhad Ben-Cohen } 142166d2f6aSOhad Ben-Cohen 143166d2f6aSOhad Ben-Cohen /* Flush protocol data */ 144166d2f6aSOhad Ben-Cohen static int ll_flush(struct hci_uart *hu) 145166d2f6aSOhad Ben-Cohen { 146166d2f6aSOhad Ben-Cohen struct ll_struct *ll = hu->priv; 147166d2f6aSOhad Ben-Cohen 148166d2f6aSOhad Ben-Cohen BT_DBG("hu %p", hu); 149166d2f6aSOhad Ben-Cohen 150166d2f6aSOhad Ben-Cohen skb_queue_purge(&ll->tx_wait_q); 151166d2f6aSOhad Ben-Cohen skb_queue_purge(&ll->txq); 152166d2f6aSOhad Ben-Cohen 153166d2f6aSOhad Ben-Cohen return 0; 154166d2f6aSOhad Ben-Cohen } 155166d2f6aSOhad Ben-Cohen 156166d2f6aSOhad Ben-Cohen /* Close protocol */ 157166d2f6aSOhad Ben-Cohen static int ll_close(struct hci_uart *hu) 158166d2f6aSOhad Ben-Cohen { 159166d2f6aSOhad Ben-Cohen struct ll_struct *ll = hu->priv; 160166d2f6aSOhad Ben-Cohen 161166d2f6aSOhad Ben-Cohen BT_DBG("hu %p", hu); 162166d2f6aSOhad Ben-Cohen 163166d2f6aSOhad Ben-Cohen skb_queue_purge(&ll->tx_wait_q); 164166d2f6aSOhad Ben-Cohen skb_queue_purge(&ll->txq); 165166d2f6aSOhad Ben-Cohen 166166d2f6aSOhad Ben-Cohen kfree_skb(ll->rx_skb); 167166d2f6aSOhad Ben-Cohen 168166d2f6aSOhad Ben-Cohen hu->priv = NULL; 169166d2f6aSOhad Ben-Cohen 170166d2f6aSOhad Ben-Cohen kfree(ll); 171166d2f6aSOhad Ben-Cohen 172166d2f6aSOhad Ben-Cohen return 0; 173166d2f6aSOhad Ben-Cohen } 174166d2f6aSOhad Ben-Cohen 175166d2f6aSOhad Ben-Cohen /* 176166d2f6aSOhad Ben-Cohen * internal function, which does common work of the device wake up process: 177166d2f6aSOhad Ben-Cohen * 1. places all pending packets (waiting in tx_wait_q list) in txq list. 178166d2f6aSOhad Ben-Cohen * 2. changes internal state to HCILL_AWAKE. 179166d2f6aSOhad Ben-Cohen * Note: assumes that hcill_lock spinlock is taken, 180166d2f6aSOhad Ben-Cohen * shouldn't be called otherwise! 181166d2f6aSOhad Ben-Cohen */ 182166d2f6aSOhad Ben-Cohen static void __ll_do_awake(struct ll_struct *ll) 183166d2f6aSOhad Ben-Cohen { 184166d2f6aSOhad Ben-Cohen struct sk_buff *skb = NULL; 185166d2f6aSOhad Ben-Cohen 186166d2f6aSOhad Ben-Cohen while ((skb = skb_dequeue(&ll->tx_wait_q))) 187166d2f6aSOhad Ben-Cohen skb_queue_tail(&ll->txq, skb); 188166d2f6aSOhad Ben-Cohen 189166d2f6aSOhad Ben-Cohen ll->hcill_state = HCILL_AWAKE; 190166d2f6aSOhad Ben-Cohen } 191166d2f6aSOhad Ben-Cohen 192166d2f6aSOhad Ben-Cohen /* 193166d2f6aSOhad Ben-Cohen * Called upon a wake-up-indication from the device 194166d2f6aSOhad Ben-Cohen */ 195166d2f6aSOhad Ben-Cohen static void ll_device_want_to_wakeup(struct hci_uart *hu) 196166d2f6aSOhad Ben-Cohen { 197166d2f6aSOhad Ben-Cohen unsigned long flags; 198166d2f6aSOhad Ben-Cohen struct ll_struct *ll = hu->priv; 199166d2f6aSOhad Ben-Cohen 200166d2f6aSOhad Ben-Cohen BT_DBG("hu %p", hu); 201166d2f6aSOhad Ben-Cohen 202166d2f6aSOhad Ben-Cohen /* lock hcill state */ 203166d2f6aSOhad Ben-Cohen spin_lock_irqsave(&ll->hcill_lock, flags); 204166d2f6aSOhad Ben-Cohen 205166d2f6aSOhad Ben-Cohen switch (ll->hcill_state) { 2065c548226SOhad Ben-Cohen case HCILL_ASLEEP_TO_AWAKE: 2075c548226SOhad Ben-Cohen /* 2085c548226SOhad Ben-Cohen * This state means that both the host and the BRF chip 2095c548226SOhad Ben-Cohen * have simultaneously sent a wake-up-indication packet. 21025985edcSLucas De Marchi * Traditionally, in this case, receiving a wake-up-indication 2115c548226SOhad Ben-Cohen * was enough and an additional wake-up-ack wasn't needed. 2125c548226SOhad Ben-Cohen * This has changed with the BRF6350, which does require an 2135c548226SOhad Ben-Cohen * explicit wake-up-ack. Other BRF versions, which do not 2145c548226SOhad Ben-Cohen * require an explicit ack here, do accept it, thus it is 2155c548226SOhad Ben-Cohen * perfectly safe to always send one. 2165c548226SOhad Ben-Cohen */ 2175c548226SOhad Ben-Cohen BT_DBG("dual wake-up-indication"); 2185c548226SOhad Ben-Cohen /* deliberate fall-through - do not add break */ 219166d2f6aSOhad Ben-Cohen case HCILL_ASLEEP: 220166d2f6aSOhad Ben-Cohen /* acknowledge device wake up */ 221166d2f6aSOhad Ben-Cohen if (send_hcill_cmd(HCILL_WAKE_UP_ACK, hu) < 0) { 222166d2f6aSOhad Ben-Cohen BT_ERR("cannot acknowledge device wake up"); 223166d2f6aSOhad Ben-Cohen goto out; 224166d2f6aSOhad Ben-Cohen } 225166d2f6aSOhad Ben-Cohen break; 226166d2f6aSOhad Ben-Cohen default: 2275c548226SOhad Ben-Cohen /* any other state is illegal */ 228166d2f6aSOhad Ben-Cohen BT_ERR("received HCILL_WAKE_UP_IND in state %ld", ll->hcill_state); 229166d2f6aSOhad Ben-Cohen break; 230166d2f6aSOhad Ben-Cohen } 231166d2f6aSOhad Ben-Cohen 232166d2f6aSOhad Ben-Cohen /* send pending packets and change state to HCILL_AWAKE */ 233166d2f6aSOhad Ben-Cohen __ll_do_awake(ll); 234166d2f6aSOhad Ben-Cohen 235166d2f6aSOhad Ben-Cohen out: 236166d2f6aSOhad Ben-Cohen spin_unlock_irqrestore(&ll->hcill_lock, flags); 237166d2f6aSOhad Ben-Cohen 238166d2f6aSOhad Ben-Cohen /* actually send the packets */ 239166d2f6aSOhad Ben-Cohen hci_uart_tx_wakeup(hu); 240166d2f6aSOhad Ben-Cohen } 241166d2f6aSOhad Ben-Cohen 242166d2f6aSOhad Ben-Cohen /* 243166d2f6aSOhad Ben-Cohen * Called upon a sleep-indication from the device 244166d2f6aSOhad Ben-Cohen */ 245166d2f6aSOhad Ben-Cohen static void ll_device_want_to_sleep(struct hci_uart *hu) 246166d2f6aSOhad Ben-Cohen { 247166d2f6aSOhad Ben-Cohen unsigned long flags; 248166d2f6aSOhad Ben-Cohen struct ll_struct *ll = hu->priv; 249166d2f6aSOhad Ben-Cohen 250166d2f6aSOhad Ben-Cohen BT_DBG("hu %p", hu); 251166d2f6aSOhad Ben-Cohen 252166d2f6aSOhad Ben-Cohen /* lock hcill state */ 253166d2f6aSOhad Ben-Cohen spin_lock_irqsave(&ll->hcill_lock, flags); 254166d2f6aSOhad Ben-Cohen 255166d2f6aSOhad Ben-Cohen /* sanity check */ 256166d2f6aSOhad Ben-Cohen if (ll->hcill_state != HCILL_AWAKE) 257166d2f6aSOhad Ben-Cohen BT_ERR("ERR: HCILL_GO_TO_SLEEP_IND in state %ld", ll->hcill_state); 258166d2f6aSOhad Ben-Cohen 259166d2f6aSOhad Ben-Cohen /* acknowledge device sleep */ 260166d2f6aSOhad Ben-Cohen if (send_hcill_cmd(HCILL_GO_TO_SLEEP_ACK, hu) < 0) { 261166d2f6aSOhad Ben-Cohen BT_ERR("cannot acknowledge device sleep"); 262166d2f6aSOhad Ben-Cohen goto out; 263166d2f6aSOhad Ben-Cohen } 264166d2f6aSOhad Ben-Cohen 265166d2f6aSOhad Ben-Cohen /* update state */ 266166d2f6aSOhad Ben-Cohen ll->hcill_state = HCILL_ASLEEP; 267166d2f6aSOhad Ben-Cohen 268166d2f6aSOhad Ben-Cohen out: 269166d2f6aSOhad Ben-Cohen spin_unlock_irqrestore(&ll->hcill_lock, flags); 270166d2f6aSOhad Ben-Cohen 271166d2f6aSOhad Ben-Cohen /* actually send the sleep ack packet */ 272166d2f6aSOhad Ben-Cohen hci_uart_tx_wakeup(hu); 273166d2f6aSOhad Ben-Cohen } 274166d2f6aSOhad Ben-Cohen 275166d2f6aSOhad Ben-Cohen /* 276166d2f6aSOhad Ben-Cohen * Called upon wake-up-acknowledgement from the device 277166d2f6aSOhad Ben-Cohen */ 278166d2f6aSOhad Ben-Cohen static void ll_device_woke_up(struct hci_uart *hu) 279166d2f6aSOhad Ben-Cohen { 280166d2f6aSOhad Ben-Cohen unsigned long flags; 281166d2f6aSOhad Ben-Cohen struct ll_struct *ll = hu->priv; 282166d2f6aSOhad Ben-Cohen 283166d2f6aSOhad Ben-Cohen BT_DBG("hu %p", hu); 284166d2f6aSOhad Ben-Cohen 285166d2f6aSOhad Ben-Cohen /* lock hcill state */ 286166d2f6aSOhad Ben-Cohen spin_lock_irqsave(&ll->hcill_lock, flags); 287166d2f6aSOhad Ben-Cohen 288166d2f6aSOhad Ben-Cohen /* sanity check */ 289166d2f6aSOhad Ben-Cohen if (ll->hcill_state != HCILL_ASLEEP_TO_AWAKE) 290166d2f6aSOhad Ben-Cohen BT_ERR("received HCILL_WAKE_UP_ACK in state %ld", ll->hcill_state); 291166d2f6aSOhad Ben-Cohen 292166d2f6aSOhad Ben-Cohen /* send pending packets and change state to HCILL_AWAKE */ 293166d2f6aSOhad Ben-Cohen __ll_do_awake(ll); 294166d2f6aSOhad Ben-Cohen 295166d2f6aSOhad Ben-Cohen spin_unlock_irqrestore(&ll->hcill_lock, flags); 296166d2f6aSOhad Ben-Cohen 297166d2f6aSOhad Ben-Cohen /* actually send the packets */ 298166d2f6aSOhad Ben-Cohen hci_uart_tx_wakeup(hu); 299166d2f6aSOhad Ben-Cohen } 300166d2f6aSOhad Ben-Cohen 301166d2f6aSOhad Ben-Cohen /* Enqueue frame for transmittion (padding, crc, etc) */ 302166d2f6aSOhad Ben-Cohen /* may be called from two simultaneous tasklets */ 303166d2f6aSOhad Ben-Cohen static int ll_enqueue(struct hci_uart *hu, struct sk_buff *skb) 304166d2f6aSOhad Ben-Cohen { 305166d2f6aSOhad Ben-Cohen unsigned long flags = 0; 306166d2f6aSOhad Ben-Cohen struct ll_struct *ll = hu->priv; 307166d2f6aSOhad Ben-Cohen 308166d2f6aSOhad Ben-Cohen BT_DBG("hu %p skb %p", hu, skb); 309166d2f6aSOhad Ben-Cohen 310166d2f6aSOhad Ben-Cohen /* Prepend skb with frame type */ 311166d2f6aSOhad Ben-Cohen memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); 312166d2f6aSOhad Ben-Cohen 313166d2f6aSOhad Ben-Cohen /* lock hcill state */ 314166d2f6aSOhad Ben-Cohen spin_lock_irqsave(&ll->hcill_lock, flags); 315166d2f6aSOhad Ben-Cohen 316166d2f6aSOhad Ben-Cohen /* act according to current state */ 317166d2f6aSOhad Ben-Cohen switch (ll->hcill_state) { 318166d2f6aSOhad Ben-Cohen case HCILL_AWAKE: 319166d2f6aSOhad Ben-Cohen BT_DBG("device awake, sending normally"); 320166d2f6aSOhad Ben-Cohen skb_queue_tail(&ll->txq, skb); 321166d2f6aSOhad Ben-Cohen break; 322166d2f6aSOhad Ben-Cohen case HCILL_ASLEEP: 323166d2f6aSOhad Ben-Cohen BT_DBG("device asleep, waking up and queueing packet"); 324166d2f6aSOhad Ben-Cohen /* save packet for later */ 325166d2f6aSOhad Ben-Cohen skb_queue_tail(&ll->tx_wait_q, skb); 326166d2f6aSOhad Ben-Cohen /* awake device */ 327166d2f6aSOhad Ben-Cohen if (send_hcill_cmd(HCILL_WAKE_UP_IND, hu) < 0) { 328166d2f6aSOhad Ben-Cohen BT_ERR("cannot wake up device"); 329166d2f6aSOhad Ben-Cohen break; 330166d2f6aSOhad Ben-Cohen } 331166d2f6aSOhad Ben-Cohen ll->hcill_state = HCILL_ASLEEP_TO_AWAKE; 332166d2f6aSOhad Ben-Cohen break; 333166d2f6aSOhad Ben-Cohen case HCILL_ASLEEP_TO_AWAKE: 334166d2f6aSOhad Ben-Cohen BT_DBG("device waking up, queueing packet"); 335166d2f6aSOhad Ben-Cohen /* transient state; just keep packet for later */ 336166d2f6aSOhad Ben-Cohen skb_queue_tail(&ll->tx_wait_q, skb); 337166d2f6aSOhad Ben-Cohen break; 338166d2f6aSOhad Ben-Cohen default: 339166d2f6aSOhad Ben-Cohen BT_ERR("illegal hcill state: %ld (losing packet)", ll->hcill_state); 340166d2f6aSOhad Ben-Cohen kfree_skb(skb); 341166d2f6aSOhad Ben-Cohen break; 342166d2f6aSOhad Ben-Cohen } 343166d2f6aSOhad Ben-Cohen 344166d2f6aSOhad Ben-Cohen spin_unlock_irqrestore(&ll->hcill_lock, flags); 345166d2f6aSOhad Ben-Cohen 346166d2f6aSOhad Ben-Cohen return 0; 347166d2f6aSOhad Ben-Cohen } 348166d2f6aSOhad Ben-Cohen 349166d2f6aSOhad Ben-Cohen static inline int ll_check_data_len(struct ll_struct *ll, int len) 350166d2f6aSOhad Ben-Cohen { 351166d2f6aSOhad Ben-Cohen register int room = skb_tailroom(ll->rx_skb); 352166d2f6aSOhad Ben-Cohen 353166d2f6aSOhad Ben-Cohen BT_DBG("len %d room %d", len, room); 354166d2f6aSOhad Ben-Cohen 355166d2f6aSOhad Ben-Cohen if (!len) { 356166d2f6aSOhad Ben-Cohen hci_recv_frame(ll->rx_skb); 357166d2f6aSOhad Ben-Cohen } else if (len > room) { 358166d2f6aSOhad Ben-Cohen BT_ERR("Data length is too large"); 359166d2f6aSOhad Ben-Cohen kfree_skb(ll->rx_skb); 360166d2f6aSOhad Ben-Cohen } else { 361166d2f6aSOhad Ben-Cohen ll->rx_state = HCILL_W4_DATA; 362166d2f6aSOhad Ben-Cohen ll->rx_count = len; 363166d2f6aSOhad Ben-Cohen return len; 364166d2f6aSOhad Ben-Cohen } 365166d2f6aSOhad Ben-Cohen 366166d2f6aSOhad Ben-Cohen ll->rx_state = HCILL_W4_PACKET_TYPE; 367166d2f6aSOhad Ben-Cohen ll->rx_skb = NULL; 368166d2f6aSOhad Ben-Cohen ll->rx_count = 0; 369166d2f6aSOhad Ben-Cohen 370166d2f6aSOhad Ben-Cohen return 0; 371166d2f6aSOhad Ben-Cohen } 372166d2f6aSOhad Ben-Cohen 373166d2f6aSOhad Ben-Cohen /* Recv data */ 374166d2f6aSOhad Ben-Cohen static int ll_recv(struct hci_uart *hu, void *data, int count) 375166d2f6aSOhad Ben-Cohen { 376166d2f6aSOhad Ben-Cohen struct ll_struct *ll = hu->priv; 377166d2f6aSOhad Ben-Cohen register char *ptr; 378166d2f6aSOhad Ben-Cohen struct hci_event_hdr *eh; 379166d2f6aSOhad Ben-Cohen struct hci_acl_hdr *ah; 380166d2f6aSOhad Ben-Cohen struct hci_sco_hdr *sh; 381166d2f6aSOhad Ben-Cohen register int len, type, dlen; 382166d2f6aSOhad Ben-Cohen 383166d2f6aSOhad Ben-Cohen BT_DBG("hu %p count %d rx_state %ld rx_count %ld", hu, count, ll->rx_state, ll->rx_count); 384166d2f6aSOhad Ben-Cohen 385166d2f6aSOhad Ben-Cohen ptr = data; 386166d2f6aSOhad Ben-Cohen while (count) { 387166d2f6aSOhad Ben-Cohen if (ll->rx_count) { 388166d2f6aSOhad Ben-Cohen len = min_t(unsigned int, ll->rx_count, count); 389166d2f6aSOhad Ben-Cohen memcpy(skb_put(ll->rx_skb, len), ptr, len); 390166d2f6aSOhad Ben-Cohen ll->rx_count -= len; count -= len; ptr += len; 391166d2f6aSOhad Ben-Cohen 392166d2f6aSOhad Ben-Cohen if (ll->rx_count) 393166d2f6aSOhad Ben-Cohen continue; 394166d2f6aSOhad Ben-Cohen 395166d2f6aSOhad Ben-Cohen switch (ll->rx_state) { 396166d2f6aSOhad Ben-Cohen case HCILL_W4_DATA: 397166d2f6aSOhad Ben-Cohen BT_DBG("Complete data"); 398166d2f6aSOhad Ben-Cohen hci_recv_frame(ll->rx_skb); 399166d2f6aSOhad Ben-Cohen 400166d2f6aSOhad Ben-Cohen ll->rx_state = HCILL_W4_PACKET_TYPE; 401166d2f6aSOhad Ben-Cohen ll->rx_skb = NULL; 402166d2f6aSOhad Ben-Cohen continue; 403166d2f6aSOhad Ben-Cohen 404166d2f6aSOhad Ben-Cohen case HCILL_W4_EVENT_HDR: 405acce90d6SGustavo F. Padovan eh = hci_event_hdr(ll->rx_skb); 406166d2f6aSOhad Ben-Cohen 407166d2f6aSOhad Ben-Cohen BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen); 408166d2f6aSOhad Ben-Cohen 409166d2f6aSOhad Ben-Cohen ll_check_data_len(ll, eh->plen); 410166d2f6aSOhad Ben-Cohen continue; 411166d2f6aSOhad Ben-Cohen 412166d2f6aSOhad Ben-Cohen case HCILL_W4_ACL_HDR: 413acce90d6SGustavo F. Padovan ah = hci_acl_hdr(ll->rx_skb); 414166d2f6aSOhad Ben-Cohen dlen = __le16_to_cpu(ah->dlen); 415166d2f6aSOhad Ben-Cohen 416166d2f6aSOhad Ben-Cohen BT_DBG("ACL header: dlen %d", dlen); 417166d2f6aSOhad Ben-Cohen 418166d2f6aSOhad Ben-Cohen ll_check_data_len(ll, dlen); 419166d2f6aSOhad Ben-Cohen continue; 420166d2f6aSOhad Ben-Cohen 421166d2f6aSOhad Ben-Cohen case HCILL_W4_SCO_HDR: 422acce90d6SGustavo F. Padovan sh = hci_sco_hdr(ll->rx_skb); 423166d2f6aSOhad Ben-Cohen 424166d2f6aSOhad Ben-Cohen BT_DBG("SCO header: dlen %d", sh->dlen); 425166d2f6aSOhad Ben-Cohen 426166d2f6aSOhad Ben-Cohen ll_check_data_len(ll, sh->dlen); 427166d2f6aSOhad Ben-Cohen continue; 428166d2f6aSOhad Ben-Cohen } 429166d2f6aSOhad Ben-Cohen } 430166d2f6aSOhad Ben-Cohen 431166d2f6aSOhad Ben-Cohen /* HCILL_W4_PACKET_TYPE */ 432166d2f6aSOhad Ben-Cohen switch (*ptr) { 433166d2f6aSOhad Ben-Cohen case HCI_EVENT_PKT: 434166d2f6aSOhad Ben-Cohen BT_DBG("Event packet"); 435166d2f6aSOhad Ben-Cohen ll->rx_state = HCILL_W4_EVENT_HDR; 436166d2f6aSOhad Ben-Cohen ll->rx_count = HCI_EVENT_HDR_SIZE; 437166d2f6aSOhad Ben-Cohen type = HCI_EVENT_PKT; 438166d2f6aSOhad Ben-Cohen break; 439166d2f6aSOhad Ben-Cohen 440166d2f6aSOhad Ben-Cohen case HCI_ACLDATA_PKT: 441166d2f6aSOhad Ben-Cohen BT_DBG("ACL packet"); 442166d2f6aSOhad Ben-Cohen ll->rx_state = HCILL_W4_ACL_HDR; 443166d2f6aSOhad Ben-Cohen ll->rx_count = HCI_ACL_HDR_SIZE; 444166d2f6aSOhad Ben-Cohen type = HCI_ACLDATA_PKT; 445166d2f6aSOhad Ben-Cohen break; 446166d2f6aSOhad Ben-Cohen 447166d2f6aSOhad Ben-Cohen case HCI_SCODATA_PKT: 448166d2f6aSOhad Ben-Cohen BT_DBG("SCO packet"); 449166d2f6aSOhad Ben-Cohen ll->rx_state = HCILL_W4_SCO_HDR; 450166d2f6aSOhad Ben-Cohen ll->rx_count = HCI_SCO_HDR_SIZE; 451166d2f6aSOhad Ben-Cohen type = HCI_SCODATA_PKT; 452166d2f6aSOhad Ben-Cohen break; 453166d2f6aSOhad Ben-Cohen 454166d2f6aSOhad Ben-Cohen /* HCILL signals */ 455166d2f6aSOhad Ben-Cohen case HCILL_GO_TO_SLEEP_IND: 456166d2f6aSOhad Ben-Cohen BT_DBG("HCILL_GO_TO_SLEEP_IND packet"); 457166d2f6aSOhad Ben-Cohen ll_device_want_to_sleep(hu); 458166d2f6aSOhad Ben-Cohen ptr++; count--; 459166d2f6aSOhad Ben-Cohen continue; 460166d2f6aSOhad Ben-Cohen 461166d2f6aSOhad Ben-Cohen case HCILL_GO_TO_SLEEP_ACK: 462166d2f6aSOhad Ben-Cohen /* shouldn't happen */ 463166d2f6aSOhad Ben-Cohen BT_ERR("received HCILL_GO_TO_SLEEP_ACK (in state %ld)", ll->hcill_state); 464166d2f6aSOhad Ben-Cohen ptr++; count--; 465166d2f6aSOhad Ben-Cohen continue; 466166d2f6aSOhad Ben-Cohen 467166d2f6aSOhad Ben-Cohen case HCILL_WAKE_UP_IND: 468166d2f6aSOhad Ben-Cohen BT_DBG("HCILL_WAKE_UP_IND packet"); 469166d2f6aSOhad Ben-Cohen ll_device_want_to_wakeup(hu); 470166d2f6aSOhad Ben-Cohen ptr++; count--; 471166d2f6aSOhad Ben-Cohen continue; 472166d2f6aSOhad Ben-Cohen 473166d2f6aSOhad Ben-Cohen case HCILL_WAKE_UP_ACK: 474166d2f6aSOhad Ben-Cohen BT_DBG("HCILL_WAKE_UP_ACK packet"); 475166d2f6aSOhad Ben-Cohen ll_device_woke_up(hu); 476166d2f6aSOhad Ben-Cohen ptr++; count--; 477166d2f6aSOhad Ben-Cohen continue; 478166d2f6aSOhad Ben-Cohen 479166d2f6aSOhad Ben-Cohen default: 480166d2f6aSOhad Ben-Cohen BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr); 481166d2f6aSOhad Ben-Cohen hu->hdev->stat.err_rx++; 482166d2f6aSOhad Ben-Cohen ptr++; count--; 483166d2f6aSOhad Ben-Cohen continue; 484166d2f6aSOhad Ben-Cohen }; 485166d2f6aSOhad Ben-Cohen 486166d2f6aSOhad Ben-Cohen ptr++; count--; 487166d2f6aSOhad Ben-Cohen 488166d2f6aSOhad Ben-Cohen /* Allocate packet */ 489166d2f6aSOhad Ben-Cohen ll->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); 490166d2f6aSOhad Ben-Cohen if (!ll->rx_skb) { 491166d2f6aSOhad Ben-Cohen BT_ERR("Can't allocate mem for new packet"); 492166d2f6aSOhad Ben-Cohen ll->rx_state = HCILL_W4_PACKET_TYPE; 493166d2f6aSOhad Ben-Cohen ll->rx_count = 0; 494fe1aff71SGustavo F. Padovan return -ENOMEM; 495166d2f6aSOhad Ben-Cohen } 496166d2f6aSOhad Ben-Cohen 497166d2f6aSOhad Ben-Cohen ll->rx_skb->dev = (void *) hu->hdev; 498166d2f6aSOhad Ben-Cohen bt_cb(ll->rx_skb)->pkt_type = type; 499166d2f6aSOhad Ben-Cohen } 500166d2f6aSOhad Ben-Cohen 501166d2f6aSOhad Ben-Cohen return count; 502166d2f6aSOhad Ben-Cohen } 503166d2f6aSOhad Ben-Cohen 504166d2f6aSOhad Ben-Cohen static struct sk_buff *ll_dequeue(struct hci_uart *hu) 505166d2f6aSOhad Ben-Cohen { 506166d2f6aSOhad Ben-Cohen struct ll_struct *ll = hu->priv; 507166d2f6aSOhad Ben-Cohen return skb_dequeue(&ll->txq); 508166d2f6aSOhad Ben-Cohen } 509166d2f6aSOhad Ben-Cohen 510166d2f6aSOhad Ben-Cohen static struct hci_uart_proto llp = { 511166d2f6aSOhad Ben-Cohen .id = HCI_UART_LL, 512166d2f6aSOhad Ben-Cohen .open = ll_open, 513166d2f6aSOhad Ben-Cohen .close = ll_close, 514166d2f6aSOhad Ben-Cohen .recv = ll_recv, 515166d2f6aSOhad Ben-Cohen .enqueue = ll_enqueue, 516166d2f6aSOhad Ben-Cohen .dequeue = ll_dequeue, 517166d2f6aSOhad Ben-Cohen .flush = ll_flush, 518166d2f6aSOhad Ben-Cohen }; 519166d2f6aSOhad Ben-Cohen 520f2b94bb9SGustavo F. Padovan int __init ll_init(void) 521166d2f6aSOhad Ben-Cohen { 522166d2f6aSOhad Ben-Cohen int err = hci_uart_register_proto(&llp); 523166d2f6aSOhad Ben-Cohen 524166d2f6aSOhad Ben-Cohen if (!err) 525166d2f6aSOhad Ben-Cohen BT_INFO("HCILL protocol initialized"); 526166d2f6aSOhad Ben-Cohen else 527166d2f6aSOhad Ben-Cohen BT_ERR("HCILL protocol registration failed"); 528166d2f6aSOhad Ben-Cohen 529166d2f6aSOhad Ben-Cohen return err; 530166d2f6aSOhad Ben-Cohen } 531166d2f6aSOhad Ben-Cohen 532f2b94bb9SGustavo F. Padovan int __exit ll_deinit(void) 533166d2f6aSOhad Ben-Cohen { 534166d2f6aSOhad Ben-Cohen return hci_uart_unregister_proto(&llp); 535166d2f6aSOhad Ben-Cohen } 536