1*07eb96a5SMarcel Holtmann /* 2*07eb96a5SMarcel Holtmann * 3*07eb96a5SMarcel Holtmann * Generic Bluetooth HCI UART driver 4*07eb96a5SMarcel Holtmann * 5*07eb96a5SMarcel Holtmann * Copyright (C) 2015-2018 Intel Corporation 6*07eb96a5SMarcel Holtmann * 7*07eb96a5SMarcel Holtmann * 8*07eb96a5SMarcel Holtmann * This program is free software; you can redistribute it and/or modify 9*07eb96a5SMarcel Holtmann * it under the terms of the GNU General Public License as published by 10*07eb96a5SMarcel Holtmann * the Free Software Foundation; either version 2 of the License, or 11*07eb96a5SMarcel Holtmann * (at your option) any later version. 12*07eb96a5SMarcel Holtmann * 13*07eb96a5SMarcel Holtmann * This program is distributed in the hope that it will be useful, 14*07eb96a5SMarcel Holtmann * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*07eb96a5SMarcel Holtmann * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*07eb96a5SMarcel Holtmann * GNU General Public License for more details. 17*07eb96a5SMarcel Holtmann * 18*07eb96a5SMarcel Holtmann * You should have received a copy of the GNU General Public License 19*07eb96a5SMarcel Holtmann * along with this program; if not, write to the Free Software 20*07eb96a5SMarcel Holtmann * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21*07eb96a5SMarcel Holtmann * 22*07eb96a5SMarcel Holtmann */ 23*07eb96a5SMarcel Holtmann 24*07eb96a5SMarcel Holtmann #include <asm/unaligned.h> 25*07eb96a5SMarcel Holtmann 26*07eb96a5SMarcel Holtmann struct h4_recv_pkt { 27*07eb96a5SMarcel Holtmann u8 type; /* Packet type */ 28*07eb96a5SMarcel Holtmann u8 hlen; /* Header length */ 29*07eb96a5SMarcel Holtmann u8 loff; /* Data length offset in header */ 30*07eb96a5SMarcel Holtmann u8 lsize; /* Data length field size */ 31*07eb96a5SMarcel Holtmann u16 maxlen; /* Max overall packet length */ 32*07eb96a5SMarcel Holtmann int (*recv)(struct hci_dev *hdev, struct sk_buff *skb); 33*07eb96a5SMarcel Holtmann }; 34*07eb96a5SMarcel Holtmann 35*07eb96a5SMarcel Holtmann #define H4_RECV_ACL \ 36*07eb96a5SMarcel Holtmann .type = HCI_ACLDATA_PKT, \ 37*07eb96a5SMarcel Holtmann .hlen = HCI_ACL_HDR_SIZE, \ 38*07eb96a5SMarcel Holtmann .loff = 2, \ 39*07eb96a5SMarcel Holtmann .lsize = 2, \ 40*07eb96a5SMarcel Holtmann .maxlen = HCI_MAX_FRAME_SIZE \ 41*07eb96a5SMarcel Holtmann 42*07eb96a5SMarcel Holtmann #define H4_RECV_SCO \ 43*07eb96a5SMarcel Holtmann .type = HCI_SCODATA_PKT, \ 44*07eb96a5SMarcel Holtmann .hlen = HCI_SCO_HDR_SIZE, \ 45*07eb96a5SMarcel Holtmann .loff = 2, \ 46*07eb96a5SMarcel Holtmann .lsize = 1, \ 47*07eb96a5SMarcel Holtmann .maxlen = HCI_MAX_SCO_SIZE 48*07eb96a5SMarcel Holtmann 49*07eb96a5SMarcel Holtmann #define H4_RECV_EVENT \ 50*07eb96a5SMarcel Holtmann .type = HCI_EVENT_PKT, \ 51*07eb96a5SMarcel Holtmann .hlen = HCI_EVENT_HDR_SIZE, \ 52*07eb96a5SMarcel Holtmann .loff = 1, \ 53*07eb96a5SMarcel Holtmann .lsize = 1, \ 54*07eb96a5SMarcel Holtmann .maxlen = HCI_MAX_EVENT_SIZE 55*07eb96a5SMarcel Holtmann 56*07eb96a5SMarcel Holtmann static inline struct sk_buff *h4_recv_buf(struct hci_dev *hdev, 57*07eb96a5SMarcel Holtmann struct sk_buff *skb, 58*07eb96a5SMarcel Holtmann const unsigned char *buffer, 59*07eb96a5SMarcel Holtmann int count, 60*07eb96a5SMarcel Holtmann const struct h4_recv_pkt *pkts, 61*07eb96a5SMarcel Holtmann int pkts_count) 62*07eb96a5SMarcel Holtmann { 63*07eb96a5SMarcel Holtmann while (count) { 64*07eb96a5SMarcel Holtmann int i, len; 65*07eb96a5SMarcel Holtmann 66*07eb96a5SMarcel Holtmann if (!count) 67*07eb96a5SMarcel Holtmann break; 68*07eb96a5SMarcel Holtmann 69*07eb96a5SMarcel Holtmann if (!skb) { 70*07eb96a5SMarcel Holtmann for (i = 0; i < pkts_count; i++) { 71*07eb96a5SMarcel Holtmann if (buffer[0] != (&pkts[i])->type) 72*07eb96a5SMarcel Holtmann continue; 73*07eb96a5SMarcel Holtmann 74*07eb96a5SMarcel Holtmann skb = bt_skb_alloc((&pkts[i])->maxlen, 75*07eb96a5SMarcel Holtmann GFP_ATOMIC); 76*07eb96a5SMarcel Holtmann if (!skb) 77*07eb96a5SMarcel Holtmann return ERR_PTR(-ENOMEM); 78*07eb96a5SMarcel Holtmann 79*07eb96a5SMarcel Holtmann hci_skb_pkt_type(skb) = (&pkts[i])->type; 80*07eb96a5SMarcel Holtmann hci_skb_expect(skb) = (&pkts[i])->hlen; 81*07eb96a5SMarcel Holtmann break; 82*07eb96a5SMarcel Holtmann } 83*07eb96a5SMarcel Holtmann 84*07eb96a5SMarcel Holtmann /* Check for invalid packet type */ 85*07eb96a5SMarcel Holtmann if (!skb) 86*07eb96a5SMarcel Holtmann return ERR_PTR(-EILSEQ); 87*07eb96a5SMarcel Holtmann 88*07eb96a5SMarcel Holtmann count -= 1; 89*07eb96a5SMarcel Holtmann buffer += 1; 90*07eb96a5SMarcel Holtmann } 91*07eb96a5SMarcel Holtmann 92*07eb96a5SMarcel Holtmann len = min_t(uint, hci_skb_expect(skb) - skb->len, count); 93*07eb96a5SMarcel Holtmann skb_put_data(skb, buffer, len); 94*07eb96a5SMarcel Holtmann 95*07eb96a5SMarcel Holtmann count -= len; 96*07eb96a5SMarcel Holtmann buffer += len; 97*07eb96a5SMarcel Holtmann 98*07eb96a5SMarcel Holtmann /* Check for partial packet */ 99*07eb96a5SMarcel Holtmann if (skb->len < hci_skb_expect(skb)) 100*07eb96a5SMarcel Holtmann continue; 101*07eb96a5SMarcel Holtmann 102*07eb96a5SMarcel Holtmann for (i = 0; i < pkts_count; i++) { 103*07eb96a5SMarcel Holtmann if (hci_skb_pkt_type(skb) == (&pkts[i])->type) 104*07eb96a5SMarcel Holtmann break; 105*07eb96a5SMarcel Holtmann } 106*07eb96a5SMarcel Holtmann 107*07eb96a5SMarcel Holtmann if (i >= pkts_count) { 108*07eb96a5SMarcel Holtmann kfree_skb(skb); 109*07eb96a5SMarcel Holtmann return ERR_PTR(-EILSEQ); 110*07eb96a5SMarcel Holtmann } 111*07eb96a5SMarcel Holtmann 112*07eb96a5SMarcel Holtmann if (skb->len == (&pkts[i])->hlen) { 113*07eb96a5SMarcel Holtmann u16 dlen; 114*07eb96a5SMarcel Holtmann 115*07eb96a5SMarcel Holtmann switch ((&pkts[i])->lsize) { 116*07eb96a5SMarcel Holtmann case 0: 117*07eb96a5SMarcel Holtmann /* No variable data length */ 118*07eb96a5SMarcel Holtmann dlen = 0; 119*07eb96a5SMarcel Holtmann break; 120*07eb96a5SMarcel Holtmann case 1: 121*07eb96a5SMarcel Holtmann /* Single octet variable length */ 122*07eb96a5SMarcel Holtmann dlen = skb->data[(&pkts[i])->loff]; 123*07eb96a5SMarcel Holtmann hci_skb_expect(skb) += dlen; 124*07eb96a5SMarcel Holtmann 125*07eb96a5SMarcel Holtmann if (skb_tailroom(skb) < dlen) { 126*07eb96a5SMarcel Holtmann kfree_skb(skb); 127*07eb96a5SMarcel Holtmann return ERR_PTR(-EMSGSIZE); 128*07eb96a5SMarcel Holtmann } 129*07eb96a5SMarcel Holtmann break; 130*07eb96a5SMarcel Holtmann case 2: 131*07eb96a5SMarcel Holtmann /* Double octet variable length */ 132*07eb96a5SMarcel Holtmann dlen = get_unaligned_le16(skb->data + 133*07eb96a5SMarcel Holtmann (&pkts[i])->loff); 134*07eb96a5SMarcel Holtmann hci_skb_expect(skb) += dlen; 135*07eb96a5SMarcel Holtmann 136*07eb96a5SMarcel Holtmann if (skb_tailroom(skb) < dlen) { 137*07eb96a5SMarcel Holtmann kfree_skb(skb); 138*07eb96a5SMarcel Holtmann return ERR_PTR(-EMSGSIZE); 139*07eb96a5SMarcel Holtmann } 140*07eb96a5SMarcel Holtmann break; 141*07eb96a5SMarcel Holtmann default: 142*07eb96a5SMarcel Holtmann /* Unsupported variable length */ 143*07eb96a5SMarcel Holtmann kfree_skb(skb); 144*07eb96a5SMarcel Holtmann return ERR_PTR(-EILSEQ); 145*07eb96a5SMarcel Holtmann } 146*07eb96a5SMarcel Holtmann 147*07eb96a5SMarcel Holtmann if (!dlen) { 148*07eb96a5SMarcel Holtmann /* No more data, complete frame */ 149*07eb96a5SMarcel Holtmann (&pkts[i])->recv(hdev, skb); 150*07eb96a5SMarcel Holtmann skb = NULL; 151*07eb96a5SMarcel Holtmann } 152*07eb96a5SMarcel Holtmann } else { 153*07eb96a5SMarcel Holtmann /* Complete frame */ 154*07eb96a5SMarcel Holtmann (&pkts[i])->recv(hdev, skb); 155*07eb96a5SMarcel Holtmann skb = NULL; 156*07eb96a5SMarcel Holtmann } 157*07eb96a5SMarcel Holtmann } 158*07eb96a5SMarcel Holtmann 159*07eb96a5SMarcel Holtmann return skb; 160*07eb96a5SMarcel Holtmann } 161