1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * 4 * Generic Bluetooth HCI UART driver 5 * 6 * Copyright (C) 2015-2018 Intel Corporation 7 */ 8 9 #include <asm/unaligned.h> 10 11 struct h4_recv_pkt { 12 u8 type; /* Packet type */ 13 u8 hlen; /* Header length */ 14 u8 loff; /* Data length offset in header */ 15 u8 lsize; /* Data length field size */ 16 u16 maxlen; /* Max overall packet length */ 17 int (*recv)(struct hci_dev *hdev, struct sk_buff *skb); 18 }; 19 20 #define H4_RECV_ACL \ 21 .type = HCI_ACLDATA_PKT, \ 22 .hlen = HCI_ACL_HDR_SIZE, \ 23 .loff = 2, \ 24 .lsize = 2, \ 25 .maxlen = HCI_MAX_FRAME_SIZE \ 26 27 #define H4_RECV_SCO \ 28 .type = HCI_SCODATA_PKT, \ 29 .hlen = HCI_SCO_HDR_SIZE, \ 30 .loff = 2, \ 31 .lsize = 1, \ 32 .maxlen = HCI_MAX_SCO_SIZE 33 34 #define H4_RECV_EVENT \ 35 .type = HCI_EVENT_PKT, \ 36 .hlen = HCI_EVENT_HDR_SIZE, \ 37 .loff = 1, \ 38 .lsize = 1, \ 39 .maxlen = HCI_MAX_EVENT_SIZE 40 41 static inline struct sk_buff *h4_recv_buf(struct hci_dev *hdev, 42 struct sk_buff *skb, 43 const unsigned char *buffer, 44 int count, 45 const struct h4_recv_pkt *pkts, 46 int pkts_count) 47 { 48 /* Check for error from previous call */ 49 if (IS_ERR(skb)) 50 skb = NULL; 51 52 while (count) { 53 int i, len; 54 55 if (!skb) { 56 for (i = 0; i < pkts_count; i++) { 57 if (buffer[0] != (&pkts[i])->type) 58 continue; 59 60 skb = bt_skb_alloc((&pkts[i])->maxlen, 61 GFP_ATOMIC); 62 if (!skb) 63 return ERR_PTR(-ENOMEM); 64 65 hci_skb_pkt_type(skb) = (&pkts[i])->type; 66 hci_skb_expect(skb) = (&pkts[i])->hlen; 67 break; 68 } 69 70 /* Check for invalid packet type */ 71 if (!skb) 72 return ERR_PTR(-EILSEQ); 73 74 count -= 1; 75 buffer += 1; 76 } 77 78 len = min_t(uint, hci_skb_expect(skb) - skb->len, count); 79 skb_put_data(skb, buffer, len); 80 81 count -= len; 82 buffer += len; 83 84 /* Check for partial packet */ 85 if (skb->len < hci_skb_expect(skb)) 86 continue; 87 88 for (i = 0; i < pkts_count; i++) { 89 if (hci_skb_pkt_type(skb) == (&pkts[i])->type) 90 break; 91 } 92 93 if (i >= pkts_count) { 94 kfree_skb(skb); 95 return ERR_PTR(-EILSEQ); 96 } 97 98 if (skb->len == (&pkts[i])->hlen) { 99 u16 dlen; 100 101 switch ((&pkts[i])->lsize) { 102 case 0: 103 /* No variable data length */ 104 dlen = 0; 105 break; 106 case 1: 107 /* Single octet variable length */ 108 dlen = skb->data[(&pkts[i])->loff]; 109 hci_skb_expect(skb) += dlen; 110 111 if (skb_tailroom(skb) < dlen) { 112 kfree_skb(skb); 113 return ERR_PTR(-EMSGSIZE); 114 } 115 break; 116 case 2: 117 /* Double octet variable length */ 118 dlen = get_unaligned_le16(skb->data + 119 (&pkts[i])->loff); 120 hci_skb_expect(skb) += dlen; 121 122 if (skb_tailroom(skb) < dlen) { 123 kfree_skb(skb); 124 return ERR_PTR(-EMSGSIZE); 125 } 126 break; 127 default: 128 /* Unsupported variable length */ 129 kfree_skb(skb); 130 return ERR_PTR(-EILSEQ); 131 } 132 133 if (!dlen) { 134 /* No more data, complete frame */ 135 (&pkts[i])->recv(hdev, skb); 136 skb = NULL; 137 } 138 } else { 139 /* Complete frame */ 140 (&pkts[i])->recv(hdev, skb); 141 skb = NULL; 142 } 143 } 144 145 return skb; 146 } 147