diff options
author | Eric Lapuyade <eric.lapuyade@intel.com> | 2012-04-10 13:43:08 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-04-12 15:10:36 -0400 |
commit | 0efbf7fb308d0c6f8419922850a2d0b45d4d4401 (patch) | |
tree | 8da2599939bbd05b874e4dbbe646785a600ab4a9 /Documentation/nfc | |
parent | eb738fe535ae8e44402c372ecc1321eee0552a09 (diff) |
NFC: Add HCI documentation
Signed-off-by: Eric Lapuyade <eric.lapuyade@intel.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'Documentation/nfc')
-rw-r--r-- | Documentation/nfc/nfc-hci.txt | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/Documentation/nfc/nfc-hci.txt b/Documentation/nfc/nfc-hci.txt new file mode 100644 index 000000000000..216b7254fcc3 --- /dev/null +++ b/Documentation/nfc/nfc-hci.txt | |||
@@ -0,0 +1,155 @@ | |||
1 | HCI backend for NFC Core | ||
2 | |||
3 | Author: Eric Lapuyade, Samuel Ortiz | ||
4 | Contact: eric.lapuyade@intel.com, samuel.ortiz@intel.com | ||
5 | |||
6 | General | ||
7 | ------- | ||
8 | |||
9 | The HCI layer implements much of the ETSI TS 102 622 V10.2.0 specification. It | ||
10 | enables easy writing of HCI-based NFC drivers. The HCI layer runs as an NFC Core | ||
11 | backend, implementing an abstract nfc device and translating NFC Core API | ||
12 | to HCI commands and events. | ||
13 | |||
14 | HCI | ||
15 | --- | ||
16 | |||
17 | HCI registers as an nfc device with NFC Core. Requests coming from userspace are | ||
18 | routed through netlink sockets to NFC Core and then to HCI. From this point, | ||
19 | they are translated in a sequence of HCI commands sent to the HCI layer in the | ||
20 | host controller (the chip). The sending context blocks while waiting for the | ||
21 | response to arrive. | ||
22 | HCI events can also be received from the host controller. They will be handled | ||
23 | and a translation will be forwarded to NFC Core as needed. | ||
24 | HCI uses 2 execution contexts: | ||
25 | - one if for executing commands : nfc_hci_msg_tx_work(). Only one command | ||
26 | can be executing at any given moment. | ||
27 | - one if for dispatching received events and responses : nfc_hci_msg_rx_work() | ||
28 | |||
29 | HCI Session initialization: | ||
30 | --------------------------- | ||
31 | |||
32 | The Session initialization is an HCI standard which must unfortunately | ||
33 | support proprietary gates. This is the reason why the driver will pass a list | ||
34 | of proprietary gates that must be part of the session. HCI will ensure all | ||
35 | those gates have pipes connected when the hci device is set up. | ||
36 | |||
37 | HCI Gates and Pipes | ||
38 | ------------------- | ||
39 | |||
40 | A gate defines the 'port' where some service can be found. In order to access | ||
41 | a service, one must create a pipe to that gate and open it. In this | ||
42 | implementation, pipes are totally hidden. The public API only knows gates. | ||
43 | This is consistent with the driver need to send commands to proprietary gates | ||
44 | without knowing the pipe connected to it. | ||
45 | |||
46 | Driver interface | ||
47 | ---------------- | ||
48 | |||
49 | A driver would normally register itself with HCI and provide the following | ||
50 | entry points: | ||
51 | |||
52 | struct nfc_hci_ops { | ||
53 | int (*open)(struct nfc_hci_dev *hdev); | ||
54 | void (*close)(struct nfc_hci_dev *hdev); | ||
55 | int (*xmit)(struct nfc_hci_dev *hdev, struct sk_buff *skb); | ||
56 | int (*start_poll)(struct nfc_hci_dev *hdev, u32 protocols); | ||
57 | int (*target_from_gate)(struct nfc_hci_dev *hdev, u8 gate, | ||
58 | struct nfc_target *target); | ||
59 | }; | ||
60 | |||
61 | open() and close() shall turn the hardware on and off. xmit() shall simply | ||
62 | write a frame to the chip. start_poll() is an optional entrypoint that shall | ||
63 | set the hardware in polling mode. This must be implemented only if the hardware | ||
64 | uses proprietary gates or a mechanism slightly different from the HCI standard. | ||
65 | target_from_gate() is another optional entrypoint to return the protocols | ||
66 | corresponding to a proprietary gate. | ||
67 | |||
68 | On the rx path, the driver is responsible to push incoming HCP frames to HCI | ||
69 | using nfc_hci_recv_frame(). HCI will take care of re-aggregation and handling | ||
70 | This must be done from a context that can sleep. | ||
71 | |||
72 | SHDLC | ||
73 | ----- | ||
74 | |||
75 | Most chips use shdlc to ensure integrity and delivery ordering of the HCP | ||
76 | frames between the host controller (the chip) and hosts (entities connected | ||
77 | to the chip, like the cpu). In order to simplify writing the driver, an shdlc | ||
78 | layer is available for use by the driver. | ||
79 | When used, the driver actually registers with shdlc, and shdlc will register | ||
80 | with HCI. HCI sees shdlc as the driver and thus send its HCP frames | ||
81 | through shdlc->xmit. | ||
82 | SHDLC adds a new execution context (nfc_shdlc_sm_work()) to run its state | ||
83 | machine and handle both its rx and tx path. | ||
84 | |||
85 | Included Drivers | ||
86 | ---------------- | ||
87 | |||
88 | An HCI based driver for an NXP PN544, connected through I2C bus, and using | ||
89 | shdlc is included. | ||
90 | |||
91 | Execution Contexts | ||
92 | ------------------ | ||
93 | |||
94 | The execution contexts are the following: | ||
95 | - IRQ handler (IRQH): | ||
96 | fast, cannot sleep. stores incoming frames into an shdlc rx queue | ||
97 | |||
98 | - SHDLC State Machine worker (SMW) | ||
99 | handles shdlc rx & tx queues. Dispatches HCI cmd responses. | ||
100 | |||
101 | - HCI Tx Cmd worker (MSGTXWQ) | ||
102 | Serialize execution of HCI commands. Complete execution in case of resp timeout. | ||
103 | |||
104 | - HCI Rx worker (MSGRXWQ) | ||
105 | Dispatches incoming HCI commands or events. | ||
106 | |||
107 | - Syscall context from a userspace call (SYSCALL) | ||
108 | Any entrypoint in HCI called from NFC Core | ||
109 | |||
110 | Workflow executing an HCI command (using shdlc) | ||
111 | ----------------------------------------------- | ||
112 | |||
113 | Executing an HCI command can easily be performed synchronously using the | ||
114 | following API: | ||
115 | |||
116 | int nfc_hci_send_cmd (struct nfc_hci_dev *hdev, u8 gate, u8 cmd, | ||
117 | const u8 *param, size_t param_len, struct sk_buff **skb) | ||
118 | |||
119 | The API must be invoked from a context that can sleep. Most of the time, this | ||
120 | will be the syscall context. skb will return the result that was received in | ||
121 | the response. | ||
122 | |||
123 | Internally, execution is asynchronous. So all this API does is to enqueue the | ||
124 | HCI command, setup a local wait queue on stack, and wait_event() for completion. | ||
125 | The wait is not interruptible because it is guaranteed that the command will | ||
126 | complete after some short timeout anyway. | ||
127 | |||
128 | MSGTXWQ context will then be scheduled and invoke nfc_hci_msg_tx_work(). | ||
129 | This function will dequeue the next pending command and send its HCP fragments | ||
130 | to the lower layer which happens to be shdlc. It will then start a timer to be | ||
131 | able to complete the command with a timeout error if no response arrive. | ||
132 | |||
133 | SMW context gets scheduled and invokes nfc_shdlc_sm_work(). This function | ||
134 | handles shdlc framing in and out. It uses the driver xmit to send frames and | ||
135 | receives incoming frames in an skb queue filled from the driver IRQ handler. | ||
136 | SHDLC I(nformation) frames payload are HCP fragments. They are agregated to | ||
137 | form complete HCI frames, which can be a response, command, or event. | ||
138 | |||
139 | HCI Responses are dispatched immediately from this context to unblock | ||
140 | waiting command execution. Reponse processing involves invoking the completion | ||
141 | callback that was provided by nfc_hci_msg_tx_work() when it sent the command. | ||
142 | The completion callback will then wake the syscall context. | ||
143 | |||
144 | Workflow receiving an HCI event or command | ||
145 | ------------------------------------------ | ||
146 | |||
147 | HCI commands or events are not dispatched from SMW context. Instead, they are | ||
148 | queued to HCI rx_queue and will be dispatched from HCI rx worker | ||
149 | context (MSGRXWQ). This is done this way to allow a cmd or event handler | ||
150 | to also execute other commands (for example, handling the | ||
151 | NFC_HCI_EVT_TARGET_DISCOVERED event from PN544 requires to issue an | ||
152 | ANY_GET_PARAMETER to the reader A gate to get information on the target | ||
153 | that was discovered). | ||
154 | |||
155 | Typically, such an event will be propagated to NFC Core from MSGRXWQ context. | ||