Unified · Split
| @@ -17,10 +17,12 @@ HCI · 16 unmodified lines | ||
| 17 | 17 | HCI registers as an nfc device with NFC Core. Requests coming from userspace are |
| 18 | 18 | routed through netlink sockets to NFC Core and then to HCI. From this point, |
| 19 | 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. | |
| 20 | +host controller (the chip). Commands can be executed synchronously (the sending | |
| 21 | +context blocks waiting for response) or asynchronously (the response is returned | |
| 22 | +from HCI Rx context). | |
| 22 | 23 | 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 | +and a translation will be forwarded to NFC Core as needed. There are hooks to | |
| 25 | +let the HCI driver handle proprietary events or override standard behavior. | |
| 24 | 26 | HCI uses 2 execution contexts: |
| 25 | 27 | - one for executing commands : nfc_hci_msg_tx_work(). Only one command |
| 26 | 28 | can be executing at any given moment. |
| @@ -33,6 +35,8 @@ The Session initialization is an HCI standard which must unfortunately · 6 unmodified lines | ||
| 33 | 35 | support proprietary gates. This is the reason why the driver will pass a list |
| 34 | 36 | of proprietary gates that must be part of the session. HCI will ensure all |
| 35 | 37 | those gates have pipes connected when the hci device is set up. |
| 38 | +In case the chip supports pre-opened gates and pseudo-static pipes, the driver | |
| 39 | +can pass that information to HCI core. | |
| 36 | 40 | |
| 37 | 41 | HCI Gates and Pipes |
| 38 | 42 | ------------------- |
| @@ -46,6 +50,13 @@ without knowing the pipe connected to it. · 7 unmodified lines | ||
| 46 | 50 | Driver interface |
| 47 | 51 | ---------------- |
| 48 | 52 | |
| 53 | +A driver is generally written in two parts : the physical link management and | |
| 54 | +the HCI management. This makes it easier to maintain a driver for a chip that | |
| 55 | +can be connected using various phy (i2c, spi, ...) | |
| 56 | + | |
| 57 | +HCI Management | |
| 58 | +-------------- | |
| 59 | + | |
| 49 | 60 | A driver would normally register itself with HCI and provide the following |
| 50 | 61 | entry points: |
| 51 | 62 | |
| @@ -53,58 +64,113 @@ struct nfc_hci_ops { · 1 unmodified line | ||
| 53 | 64 | int (*open)(struct nfc_hci_dev *hdev); |
| 54 | 65 | void (*close)(struct nfc_hci_dev *hdev); |
| 55 | 66 | int (*hci_ready) (struct nfc_hci_dev *hdev); |
| 56 | − int (*xmit)(struct nfc_hci_dev *hdev, struct sk_buff *skb); | |
| 57 | − int (*start_poll)(struct nfc_hci_dev *hdev, u32 protocols); | |
| 58 | − int (*target_from_gate)(struct nfc_hci_dev *hdev, u8 gate, | |
| 59 | − struct nfc_target *target); | |
| 67 | + int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb); | |
| 68 | + int (*start_poll) (struct nfc_hci_dev *hdev, | |
| 69 | + u32 im_protocols, u32 tm_protocols); | |
| 70 | + int (*dep_link_up)(struct nfc_hci_dev *hdev, struct nfc_target *target, | |
| 71 | + u8 comm_mode, u8 *gb, size_t gb_len); | |
| 72 | + int (*dep_link_down)(struct nfc_hci_dev *hdev); | |
| 73 | + int (*target_from_gate) (struct nfc_hci_dev *hdev, u8 gate, | |
| 74 | + struct nfc_target *target); | |
| 60 | 75 | int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate, |
| 61 | 76 | struct nfc_target *target); |
| 62 | − int (*data_exchange) (struct nfc_hci_dev *hdev, | |
| 63 | − struct nfc_target *target, | |
| 64 | − struct sk_buff *skb, struct sk_buff **res_skb); | |
| 77 | + int (*im_transceive) (struct nfc_hci_dev *hdev, | |
| 78 | + struct nfc_target *target, struct sk_buff *skb, | |
| 79 | + data_exchange_cb_t cb, void *cb_context); | |
| 80 | + int (*tm_send)(struct nfc_hci_dev *hdev, struct sk_buff *skb); | |
| 65 | 81 | int (*check_presence)(struct nfc_hci_dev *hdev, |
| 66 | 82 | struct nfc_target *target); |
| 83 | + int (*event_received)(struct nfc_hci_dev *hdev, u8 gate, u8 event, | |
| 84 | + struct sk_buff *skb); | |
| 67 | 85 | }; |
| 68 | 86 | |
| 69 | 87 | - open() and close() shall turn the hardware on and off. |
| 70 | 88 | - hci_ready() is an optional entry point that is called right after the hci |
| 71 | 89 | session has been set up. The driver can use it to do additional initialization |
| 72 | 90 | that must be performed using HCI commands. |
| 73 | −- xmit() shall simply write a frame to the chip. | |
| 91 | +- xmit() shall simply write a frame to the physical link. | |
| 74 | 92 | - start_poll() is an optional entrypoint that shall set the hardware in polling |
| 75 | 93 | mode. This must be implemented only if the hardware uses proprietary gates or a |
| 76 | 94 | mechanism slightly different from the HCI standard. |
| 95 | +- dep_link_up() is called after a p2p target has been detected, to finish | |
| 96 | +the p2p connection setup with hardware parameters that need to be passed back | |
| 97 | +to nfc core. | |
| 98 | +- dep_link_down() is called to bring the p2p link down. | |
| 77 | 99 | - target_from_gate() is an optional entrypoint to return the nfc protocols |
| 78 | 100 | corresponding to a proprietary gate. |
| 79 | 101 | - complete_target_discovered() is an optional entry point to let the driver |
| 80 | 102 | perform additional proprietary processing necessary to auto activate the |
| 81 | 103 | discovered target. |
| 82 | −- data_exchange() must be implemented by the driver if proprietary HCI commands | |
| 104 | +- im_transceive() must be implemented by the driver if proprietary HCI commands | |
| 83 | 105 | are required to send data to the tag. Some tag types will require custom |
| 84 | 106 | commands, others can be written to using the standard HCI commands. The driver |
| 85 | 107 | can check the tag type and either do proprietary processing, or return 1 to ask |
| 86 | −for standard processing. | |
| 108 | +for standard processing. The data exchange command itself must be sent | |
| 109 | +asynchronously. | |
| 110 | +- tm_send() is called to send data in the case of a p2p connection | |
| 87 | 111 | - check_presence() is an optional entry point that will be called regularly |
| 88 | 112 | by the core to check that an activated tag is still in the field. If this is |
| 89 | 113 | not implemented, the core will not be able to push tag_lost events to the user |
| 90 | 114 | space |
| 115 | +- event_received() is called to handle an event coming from the chip. Driver | |
| 116 | +can handle the event or return 1 to let HCI attempt standard processing. | |
| 91 | 117 | |
| 92 | 118 | On the rx path, the driver is responsible to push incoming HCP frames to HCI |
| 93 | 119 | using nfc_hci_recv_frame(). HCI will take care of re-aggregation and handling |
| 94 | 120 | This must be done from a context that can sleep. |
| 95 | 121 | |
| 96 | −SHDLC | |
| 97 | −----- | |
| 122 | +PHY Management | |
| 123 | +-------------- | |
| 124 | + | |
| 125 | +The physical link (i2c, ...) management is defined by the following struture: | |
| 126 | + | |
| 127 | +struct nfc_phy_ops { | |
| 128 | + int (*write)(void *dev_id, struct sk_buff *skb); | |
| 129 | + int (*enable)(void *dev_id); | |
| 130 | + void (*disable)(void *dev_id); | |
| 131 | +}; | |
| 132 | + | |
| 133 | +enable(): turn the phy on (power on), make it ready to transfer data | |
| 134 | +disable(): turn the phy off | |
| 135 | +write(): Send a data frame to the chip. Note that to enable higher | |
| 136 | +layers such as an llc to store the frame for re-emission, this function must | |
| 137 | +not alter the skb. It must also not return a positive result (return 0 for | |
| 138 | +success, negative for failure). | |
| 139 | + | |
| 140 | +Data coming from the chip shall be sent directly to nfc_hci_recv_frame(). | |
| 141 | + | |
| 142 | +LLC | |
| 143 | +--- | |
| 144 | + | |
| 145 | +Communication between the CPU and the chip often requires some link layer | |
| 146 | +protocol. Those are isolated as modules managed by the HCI layer. There are | |
| 147 | +currently two modules : nop (raw transfert) and shdlc. | |
| 148 | +A new llc must implement the following functions: | |
| 149 | + | |
| 150 | +struct nfc_llc_ops { | |
| 151 | + void *(*init) (struct nfc_hci_dev *hdev, xmit_to_drv_t xmit_to_drv, | |
| 152 | + rcv_to_hci_t rcv_to_hci, int tx_headroom, | |
| 153 | + int tx_tailroom, int *rx_headroom, int *rx_tailroom, | |
| 154 | + llc_failure_t llc_failure); | |
| 155 | + void (*deinit) (struct nfc_llc *llc); | |
| 156 | + int (*start) (struct nfc_llc *llc); | |
| 157 | + int (*stop) (struct nfc_llc *llc); | |
| 158 | + void (*rcv_from_drv) (struct nfc_llc *llc, struct sk_buff *skb); | |
| 159 | + int (*xmit_from_hci) (struct nfc_llc *llc, struct sk_buff *skb); | |
| 160 | +}; | |
| 161 | + | |
| 162 | +- init() : allocate and init your private storage | |
| 163 | +- deinit() : cleanup | |
| 164 | +- start() : establish the logical connection | |
| 165 | +- stop () : terminate the logical connection | |
| 166 | +- rcv_from_drv() : handle data coming from the chip, going to HCI | |
| 167 | +- xmit_from_hci() : handle data sent by HCI, going to the chip | |
| 98 | 168 | |
| 99 | −Most chips use shdlc to ensure integrity and delivery ordering of the HCP | |
| 100 | −frames between the host controller (the chip) and hosts (entities connected | |
| 101 | −to the chip, like the cpu). In order to simplify writing the driver, an shdlc | |
| 102 | −layer is available for use by the driver. | |
| 103 | −When used, the driver actually registers with shdlc, and shdlc will register | |
| 104 | −with HCI. HCI sees shdlc as the driver and thus send its HCP frames | |
| 105 | −through shdlc->xmit. | |
| 106 | −SHDLC adds a new execution context (nfc_shdlc_sm_work()) to run its state | |
| 107 | −machine and handle both its rx and tx path. | |
| 169 | +The llc must be registered with nfc before it can be used. Do that by | |
| 170 | +calling nfc_llc_register(const char *name, struct nfc_llc_ops *ops); | |
| 171 | + | |
| 172 | +Again, note that the llc does not handle the physical link. It is thus very | |
| 173 | +easy to mix any physical link with any llc for a given chip driver. | |
| 108 | 174 | |
| 109 | 175 | Included Drivers |
| 110 | 176 | ---------------- |
| @@ -117,10 +183,12 @@ Execution Contexts · 6 unmodified lines | ||
| 117 | 183 | |
| 118 | 184 | The execution contexts are the following: |
| 119 | 185 | - IRQ handler (IRQH): |
| 120 | −fast, cannot sleep. stores incoming frames into an shdlc rx queue | |
| 186 | +fast, cannot sleep. sends incoming frames to HCI where they are passed to | |
| 187 | +the current llc. In case of shdlc, the frame is queued in shdlc rx queue. | |
| 121 | 188 | |
| 122 | 189 | - SHDLC State Machine worker (SMW) |
| 123 | −handles shdlc rx & tx queues. Dispatches HCI cmd responses. | |
| 190 | +Only when llc_shdlc is used: handles shdlc rx & tx queues. | |
| 191 | +Dispatches HCI cmd responses. | |
| 124 | 192 | |
| 125 | 193 | - HCI Tx Cmd worker (MSGTXWQ) |
| 126 | 194 | Serializes execution of HCI commands. Completes execution in case of response |
| @@ -166,6 +234,15 @@ waiting command execution. Response processing involves invoking the completion · 39 unmodified lines | ||
| 166 | 234 | callback that was provided by nfc_hci_msg_tx_work() when it sent the command. |
| 167 | 235 | The completion callback will then wake the syscall context. |
| 168 | 236 | |
| 237 | +It is also possible to execute the command asynchronously using this API: | |
| 238 | + | |
| 239 | +static int nfc_hci_execute_cmd_async(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, | |
| 240 | + const u8 *param, size_t param_len, | |
| 241 | + data_exchange_cb_t cb, void *cb_context) | |
| 242 | + | |
| 243 | +The workflow is the same, except that the API call returns immediately, and | |
| 244 | +the callback will be called with the result from the SMW context. | |
| 245 | + | |
| 169 | 246 | Workflow receiving an HCI event or command |
| 170 | 247 | ------------------------------------------ |
| 171 | 248 | |