]>
Commit | Line | Data |
---|---|---|
1ccea77e | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
8b8d2e08 EL |
2 | /* |
3 | * Copyright (C) 2012 Intel Corporation. All rights reserved. | |
8b8d2e08 EL |
4 | */ |
5 | ||
6 | #define pr_fmt(fmt) "hci: %s: " fmt, __func__ | |
7 | ||
8 | #include <linux/init.h> | |
9 | #include <linux/kernel.h> | |
10 | #include <linux/module.h> | |
11 | ||
12 | #include <net/nfc/hci.h> | |
13 | ||
14 | #include "hci.h" | |
15 | ||
16 | /* | |
17 | * Payload is the HCP message data only. Instruction will be prepended. | |
18 | * Guarantees that cb will be called upon completion or timeout delay | |
19 | * counted from the moment the cmd is sent to the transport. | |
20 | */ | |
21 | int nfc_hci_hcp_message_tx(struct nfc_hci_dev *hdev, u8 pipe, | |
22 | u8 type, u8 instruction, | |
23 | const u8 *payload, size_t payload_len, | |
b5faa648 | 24 | data_exchange_cb_t cb, void *cb_context, |
8b8d2e08 EL |
25 | unsigned long completion_delay) |
26 | { | |
27 | struct nfc_dev *ndev = hdev->ndev; | |
28 | struct hci_msg *cmd; | |
29 | const u8 *ptr = payload; | |
30 | int hci_len, err; | |
31 | bool firstfrag = true; | |
32 | ||
33 | cmd = kzalloc(sizeof(struct hci_msg), GFP_KERNEL); | |
34 | if (cmd == NULL) | |
35 | return -ENOMEM; | |
36 | ||
37 | INIT_LIST_HEAD(&cmd->msg_l); | |
38 | skb_queue_head_init(&cmd->msg_frags); | |
39 | cmd->wait_response = (type == NFC_HCI_HCP_COMMAND) ? true : false; | |
40 | cmd->cb = cb; | |
b5faa648 | 41 | cmd->cb_context = cb_context; |
8b8d2e08 EL |
42 | cmd->completion_delay = completion_delay; |
43 | ||
44 | hci_len = payload_len + 1; | |
45 | while (hci_len > 0) { | |
46 | struct sk_buff *skb; | |
47 | int skb_len, data_link_len; | |
48 | struct hcp_packet *packet; | |
49 | ||
50 | if (NFC_HCI_HCP_PACKET_HEADER_LEN + hci_len <= | |
51 | hdev->max_data_link_payload) | |
52 | data_link_len = hci_len; | |
53 | else | |
54 | data_link_len = hdev->max_data_link_payload - | |
55 | NFC_HCI_HCP_PACKET_HEADER_LEN; | |
56 | ||
57 | skb_len = ndev->tx_headroom + NFC_HCI_HCP_PACKET_HEADER_LEN + | |
58 | data_link_len + ndev->tx_tailroom; | |
59 | hci_len -= data_link_len; | |
60 | ||
61 | skb = alloc_skb(skb_len, GFP_KERNEL); | |
62 | if (skb == NULL) { | |
63 | err = -ENOMEM; | |
64 | goto out_skb_err; | |
65 | } | |
66 | skb_reserve(skb, ndev->tx_headroom); | |
67 | ||
68 | skb_put(skb, NFC_HCI_HCP_PACKET_HEADER_LEN + data_link_len); | |
69 | ||
70 | /* Only the last fragment will have the cb bit set to 1 */ | |
71 | packet = (struct hcp_packet *)skb->data; | |
72 | packet->header = pipe; | |
73 | if (firstfrag) { | |
74 | firstfrag = false; | |
75 | packet->message.header = HCP_HEADER(type, instruction); | |
76 | if (ptr) { | |
77 | memcpy(packet->message.data, ptr, | |
78 | data_link_len - 1); | |
79 | ptr += data_link_len - 1; | |
80 | } | |
81 | } else { | |
82 | memcpy(&packet->message, ptr, data_link_len); | |
83 | ptr += data_link_len; | |
84 | } | |
85 | ||
86 | /* This is the last fragment, set the cb bit */ | |
87 | if (hci_len == 0) | |
88 | packet->header |= ~NFC_HCI_FRAGMENT; | |
89 | ||
90 | skb_queue_tail(&cmd->msg_frags, skb); | |
91 | } | |
92 | ||
93 | mutex_lock(&hdev->msg_tx_mutex); | |
f0c91038 EL |
94 | |
95 | if (hdev->shutting_down) { | |
96 | err = -ESHUTDOWN; | |
97 | mutex_unlock(&hdev->msg_tx_mutex); | |
98 | goto out_skb_err; | |
99 | } | |
100 | ||
f8bf65bf | 101 | list_add_tail(&cmd->msg_l, &hdev->msg_tx_queue); |
8b8d2e08 EL |
102 | mutex_unlock(&hdev->msg_tx_mutex); |
103 | ||
916082b0 | 104 | schedule_work(&hdev->msg_tx_work); |
8b8d2e08 EL |
105 | |
106 | return 0; | |
107 | ||
108 | out_skb_err: | |
109 | skb_queue_purge(&cmd->msg_frags); | |
110 | kfree(cmd); | |
111 | ||
112 | return err; | |
113 | } | |
114 | ||
8b8d2e08 EL |
115 | /* |
116 | * Receive hcp message for pipe, with type and cmd. | |
117 | * skb contains optional message data only. | |
118 | */ | |
119 | void nfc_hci_hcp_message_rx(struct nfc_hci_dev *hdev, u8 pipe, u8 type, | |
120 | u8 instruction, struct sk_buff *skb) | |
121 | { | |
122 | switch (type) { | |
123 | case NFC_HCI_HCP_RESPONSE: | |
124 | nfc_hci_resp_received(hdev, instruction, skb); | |
125 | break; | |
126 | case NFC_HCI_HCP_COMMAND: | |
127 | nfc_hci_cmd_received(hdev, pipe, instruction, skb); | |
128 | break; | |
129 | case NFC_HCI_HCP_EVENT: | |
130 | nfc_hci_event_received(hdev, pipe, instruction, skb); | |
131 | break; | |
132 | default: | |
133 | pr_err("UNKNOWN MSG Type %d, instruction=%d\n", | |
134 | type, instruction); | |
135 | kfree_skb(skb); | |
136 | break; | |
137 | } | |
138 | } |