Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  *
0004  *  Generic Bluetooth HCI UART driver
0005  *
0006  *  Copyright (C) 2015-2018  Intel Corporation
0007  */
0008 
0009 #include <asm/unaligned.h>
0010 
0011 struct h4_recv_pkt {
0012     u8  type;   /* Packet type */
0013     u8  hlen;   /* Header length */
0014     u8  loff;   /* Data length offset in header */
0015     u8  lsize;  /* Data length field size */
0016     u16 maxlen; /* Max overall packet length */
0017     int (*recv)(struct hci_dev *hdev, struct sk_buff *skb);
0018 };
0019 
0020 #define H4_RECV_ACL \
0021     .type = HCI_ACLDATA_PKT, \
0022     .hlen = HCI_ACL_HDR_SIZE, \
0023     .loff = 2, \
0024     .lsize = 2, \
0025     .maxlen = HCI_MAX_FRAME_SIZE \
0026 
0027 #define H4_RECV_SCO \
0028     .type = HCI_SCODATA_PKT, \
0029     .hlen = HCI_SCO_HDR_SIZE, \
0030     .loff = 2, \
0031     .lsize = 1, \
0032     .maxlen = HCI_MAX_SCO_SIZE
0033 
0034 #define H4_RECV_EVENT \
0035     .type = HCI_EVENT_PKT, \
0036     .hlen = HCI_EVENT_HDR_SIZE, \
0037     .loff = 1, \
0038     .lsize = 1, \
0039     .maxlen = HCI_MAX_EVENT_SIZE
0040 
0041 static inline struct sk_buff *h4_recv_buf(struct hci_dev *hdev,
0042                       struct sk_buff *skb,
0043                       const unsigned char *buffer,
0044                       int count,
0045                       const struct h4_recv_pkt *pkts,
0046                       int pkts_count)
0047 {
0048     /* Check for error from previous call */
0049     if (IS_ERR(skb))
0050         skb = NULL;
0051 
0052     while (count) {
0053         int i, len;
0054 
0055         if (!skb) {
0056             for (i = 0; i < pkts_count; i++) {
0057                 if (buffer[0] != (&pkts[i])->type)
0058                     continue;
0059 
0060                 skb = bt_skb_alloc((&pkts[i])->maxlen,
0061                            GFP_ATOMIC);
0062                 if (!skb)
0063                     return ERR_PTR(-ENOMEM);
0064 
0065                 hci_skb_pkt_type(skb) = (&pkts[i])->type;
0066                 hci_skb_expect(skb) = (&pkts[i])->hlen;
0067                 break;
0068             }
0069 
0070             /* Check for invalid packet type */
0071             if (!skb)
0072                 return ERR_PTR(-EILSEQ);
0073 
0074             count -= 1;
0075             buffer += 1;
0076         }
0077 
0078         len = min_t(uint, hci_skb_expect(skb) - skb->len, count);
0079         skb_put_data(skb, buffer, len);
0080 
0081         count -= len;
0082         buffer += len;
0083 
0084         /* Check for partial packet */
0085         if (skb->len < hci_skb_expect(skb))
0086             continue;
0087 
0088         for (i = 0; i < pkts_count; i++) {
0089             if (hci_skb_pkt_type(skb) == (&pkts[i])->type)
0090                 break;
0091         }
0092 
0093         if (i >= pkts_count) {
0094             kfree_skb(skb);
0095             return ERR_PTR(-EILSEQ);
0096         }
0097 
0098         if (skb->len == (&pkts[i])->hlen) {
0099             u16 dlen;
0100 
0101             switch ((&pkts[i])->lsize) {
0102             case 0:
0103                 /* No variable data length */
0104                 dlen = 0;
0105                 break;
0106             case 1:
0107                 /* Single octet variable length */
0108                 dlen = skb->data[(&pkts[i])->loff];
0109                 hci_skb_expect(skb) += dlen;
0110 
0111                 if (skb_tailroom(skb) < dlen) {
0112                     kfree_skb(skb);
0113                     return ERR_PTR(-EMSGSIZE);
0114                 }
0115                 break;
0116             case 2:
0117                 /* Double octet variable length */
0118                 dlen = get_unaligned_le16(skb->data +
0119                               (&pkts[i])->loff);
0120                 hci_skb_expect(skb) += dlen;
0121 
0122                 if (skb_tailroom(skb) < dlen) {
0123                     kfree_skb(skb);
0124                     return ERR_PTR(-EMSGSIZE);
0125                 }
0126                 break;
0127             default:
0128                 /* Unsupported variable length */
0129                 kfree_skb(skb);
0130                 return ERR_PTR(-EILSEQ);
0131             }
0132 
0133             if (!dlen) {
0134                 /* No more data, complete frame */
0135                 (&pkts[i])->recv(hdev, skb);
0136                 skb = NULL;
0137             }
0138         } else {
0139             /* Complete frame */
0140             (&pkts[i])->recv(hdev, skb);
0141             skb = NULL;
0142         }
0143     }
0144 
0145     return skb;
0146 }