diff options
author | David S. Miller <davem@davemloft.net> | 2015-01-29 01:49:55 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-01-29 01:49:55 -0500 |
commit | b8f8be3f043d6dba7d6c3426e4597d2ebf5a3547 (patch) | |
tree | 8f2b80088b24b7c5fb0aba4c6b3b45b5ca4a2bb2 | |
parent | ff660f75be36e6db75d45dc742a4a468c5a9c20d (diff) | |
parent | 0a5942c8e1480db4b8ee7a8d643e4945ef2f8fed (diff) |
Merge tag 'nfc-next-3.20-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/nfc-next
NFC: 3.20 first pull request
This is the first NFC pull request for 3.20.
With this one we have:
- Secure element support for the ST Micro st21nfca driver. This depends
on a few HCI internal changes in order for example to support more
than one secure element per controller.
- ACPI support for NXP's pn544 HCI driver. This controller is found on
many x86 SoCs and is typically enumerated on the ACPI bus there.
- A few st21nfca and st21nfcb fixes.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | Documentation/devicetree/bindings/net/nfc/st21nfca.txt | 11 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/net/nfc/st21nfcb.txt | 4 | ||||
-rw-r--r-- | drivers/nfc/microread/microread.c | 3 | ||||
-rw-r--r-- | drivers/nfc/pn544/i2c.c | 133 | ||||
-rw-r--r-- | drivers/nfc/pn544/pn544.c | 3 | ||||
-rw-r--r-- | drivers/nfc/st21nfca/Makefile | 2 | ||||
-rw-r--r-- | drivers/nfc/st21nfca/i2c.c | 23 | ||||
-rw-r--r-- | drivers/nfc/st21nfca/st21nfca.c | 186 | ||||
-rw-r--r-- | drivers/nfc/st21nfca/st21nfca.h | 21 | ||||
-rw-r--r-- | drivers/nfc/st21nfca/st21nfca_se.c | 390 | ||||
-rw-r--r-- | drivers/nfc/st21nfca/st21nfca_se.h | 63 | ||||
-rw-r--r-- | drivers/nfc/st21nfcb/i2c.c | 19 | ||||
-rw-r--r-- | drivers/nfc/st21nfcb/ndlc.c | 3 | ||||
-rw-r--r-- | include/linux/platform_data/st21nfca.h | 2 | ||||
-rw-r--r-- | include/linux/platform_data/st21nfcb.h | 4 | ||||
-rw-r--r-- | include/net/nfc/hci.h | 25 | ||||
-rw-r--r-- | net/nfc/core.c | 2 | ||||
-rw-r--r-- | net/nfc/hci/command.c | 23 | ||||
-rw-r--r-- | net/nfc/hci/core.c | 97 | ||||
-rw-r--r-- | net/nfc/hci/hci.h | 10 | ||||
-rw-r--r-- | net/nfc/hci/hcp.c | 11 |
21 files changed, 886 insertions, 149 deletions
diff --git a/Documentation/devicetree/bindings/net/nfc/st21nfca.txt b/Documentation/devicetree/bindings/net/nfc/st21nfca.txt index e4faa2e8dfeb..7bb2e213d6f9 100644 --- a/Documentation/devicetree/bindings/net/nfc/st21nfca.txt +++ b/Documentation/devicetree/bindings/net/nfc/st21nfca.txt | |||
@@ -1,7 +1,7 @@ | |||
1 | * STMicroelectronics SAS. ST21NFCA NFC Controller | 1 | * STMicroelectronics SAS. ST21NFCA NFC Controller |
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible: Should be "st,st21nfca_i2c". | 4 | - compatible: Should be "st,st21nfca-i2c". |
5 | - clock-frequency: I²C work frequency. | 5 | - clock-frequency: I²C work frequency. |
6 | - reg: address on the bus | 6 | - reg: address on the bus |
7 | - interrupt-parent: phandle for the interrupt gpio controller | 7 | - interrupt-parent: phandle for the interrupt gpio controller |
@@ -11,6 +11,10 @@ Required properties: | |||
11 | Optional SoC Specific Properties: | 11 | Optional SoC Specific Properties: |
12 | - pinctrl-names: Contains only one value - "default". | 12 | - pinctrl-names: Contains only one value - "default". |
13 | - pintctrl-0: Specifies the pin control groups used for this controller. | 13 | - pintctrl-0: Specifies the pin control groups used for this controller. |
14 | - ese-present: Specifies that an ese is physically connected to the nfc | ||
15 | controller. | ||
16 | - uicc-present: Specifies that the uicc swp signal can be physically | ||
17 | connected to the nfc controller. | ||
14 | 18 | ||
15 | Example (for ARM-based BeagleBoard xM with ST21NFCA on I2C2): | 19 | Example (for ARM-based BeagleBoard xM with ST21NFCA on I2C2): |
16 | 20 | ||
@@ -20,7 +24,7 @@ Example (for ARM-based BeagleBoard xM with ST21NFCA on I2C2): | |||
20 | 24 | ||
21 | st21nfca: st21nfca@1 { | 25 | st21nfca: st21nfca@1 { |
22 | 26 | ||
23 | compatible = "st,st21nfca_i2c"; | 27 | compatible = "st,st21nfca-i2c"; |
24 | 28 | ||
25 | reg = <0x01>; | 29 | reg = <0x01>; |
26 | clock-frequency = <400000>; | 30 | clock-frequency = <400000>; |
@@ -29,5 +33,8 @@ Example (for ARM-based BeagleBoard xM with ST21NFCA on I2C2): | |||
29 | interrupts = <2 IRQ_TYPE_LEVEL_LOW>; | 33 | interrupts = <2 IRQ_TYPE_LEVEL_LOW>; |
30 | 34 | ||
31 | enable-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>; | 35 | enable-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>; |
36 | |||
37 | ese-present; | ||
38 | uicc-present; | ||
32 | }; | 39 | }; |
33 | }; | 40 | }; |
diff --git a/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt b/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt index 9005608cbbd1..bb237072dbe9 100644 --- a/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt +++ b/Documentation/devicetree/bindings/net/nfc/st21nfcb.txt | |||
@@ -1,7 +1,7 @@ | |||
1 | * STMicroelectronics SAS. ST21NFCB NFC Controller | 1 | * STMicroelectronics SAS. ST21NFCB NFC Controller |
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible: Should be "st,st21nfcb_i2c". | 4 | - compatible: Should be "st,st21nfcb-i2c". |
5 | - clock-frequency: I²C work frequency. | 5 | - clock-frequency: I²C work frequency. |
6 | - reg: address on the bus | 6 | - reg: address on the bus |
7 | - interrupt-parent: phandle for the interrupt gpio controller | 7 | - interrupt-parent: phandle for the interrupt gpio controller |
@@ -20,7 +20,7 @@ Example (for ARM-based BeagleBoard xM with ST21NFCB on I2C2): | |||
20 | 20 | ||
21 | st21nfcb: st21nfcb@8 { | 21 | st21nfcb: st21nfcb@8 { |
22 | 22 | ||
23 | compatible = "st,st21nfcb_i2c"; | 23 | compatible = "st,st21nfcb-i2c"; |
24 | 24 | ||
25 | reg = <0x08>; | 25 | reg = <0x08>; |
26 | clock-frequency = <400000>; | 26 | clock-frequency = <400000>; |
diff --git a/drivers/nfc/microread/microread.c b/drivers/nfc/microread/microread.c index 963a4a5dc88e..f454dc68cc03 100644 --- a/drivers/nfc/microread/microread.c +++ b/drivers/nfc/microread/microread.c | |||
@@ -557,10 +557,11 @@ exit: | |||
557 | pr_err("Failed to handle discovered target err=%d\n", r); | 557 | pr_err("Failed to handle discovered target err=%d\n", r); |
558 | } | 558 | } |
559 | 559 | ||
560 | static int microread_event_received(struct nfc_hci_dev *hdev, u8 gate, | 560 | static int microread_event_received(struct nfc_hci_dev *hdev, u8 pipe, |
561 | u8 event, struct sk_buff *skb) | 561 | u8 event, struct sk_buff *skb) |
562 | { | 562 | { |
563 | int r; | 563 | int r; |
564 | u8 gate = hdev->pipes[pipe].gate; | ||
564 | u8 mode; | 565 | u8 mode; |
565 | 566 | ||
566 | pr_info("Microread received event 0x%x to gate 0x%x\n", event, gate); | 567 | pr_info("Microread received event 0x%x to gate 0x%x\n", event, gate); |
diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c index fc02e8d6a193..cdde745b96bd 100644 --- a/drivers/nfc/pn544/i2c.c +++ b/drivers/nfc/pn544/i2c.c | |||
@@ -24,11 +24,13 @@ | |||
24 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
25 | #include <linux/of_gpio.h> | 25 | #include <linux/of_gpio.h> |
26 | #include <linux/of_irq.h> | 26 | #include <linux/of_irq.h> |
27 | #include <linux/acpi.h> | ||
27 | #include <linux/miscdevice.h> | 28 | #include <linux/miscdevice.h> |
28 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
29 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
30 | #include <linux/nfc.h> | 31 | #include <linux/nfc.h> |
31 | #include <linux/firmware.h> | 32 | #include <linux/firmware.h> |
33 | #include <linux/gpio/consumer.h> | ||
32 | #include <linux/platform_data/pn544.h> | 34 | #include <linux/platform_data/pn544.h> |
33 | #include <asm/unaligned.h> | 35 | #include <asm/unaligned.h> |
34 | 36 | ||
@@ -41,6 +43,11 @@ | |||
41 | #define PN544_I2C_FRAME_HEADROOM 1 | 43 | #define PN544_I2C_FRAME_HEADROOM 1 |
42 | #define PN544_I2C_FRAME_TAILROOM 2 | 44 | #define PN544_I2C_FRAME_TAILROOM 2 |
43 | 45 | ||
46 | /* GPIO names */ | ||
47 | #define PN544_GPIO_NAME_IRQ "pn544_irq" | ||
48 | #define PN544_GPIO_NAME_FW "pn544_fw" | ||
49 | #define PN544_GPIO_NAME_EN "pn544_en" | ||
50 | |||
44 | /* framing in HCI mode */ | 51 | /* framing in HCI mode */ |
45 | #define PN544_HCI_I2C_LLC_LEN 1 | 52 | #define PN544_HCI_I2C_LLC_LEN 1 |
46 | #define PN544_HCI_I2C_LLC_CRC 2 | 53 | #define PN544_HCI_I2C_LLC_CRC 2 |
@@ -58,6 +65,13 @@ static struct i2c_device_id pn544_hci_i2c_id_table[] = { | |||
58 | 65 | ||
59 | MODULE_DEVICE_TABLE(i2c, pn544_hci_i2c_id_table); | 66 | MODULE_DEVICE_TABLE(i2c, pn544_hci_i2c_id_table); |
60 | 67 | ||
68 | static const struct acpi_device_id pn544_hci_i2c_acpi_match[] = { | ||
69 | {"NXP5440", 0}, | ||
70 | {} | ||
71 | }; | ||
72 | |||
73 | MODULE_DEVICE_TABLE(acpi, pn544_hci_i2c_acpi_match); | ||
74 | |||
61 | #define PN544_HCI_I2C_DRIVER_NAME "pn544_hci_i2c" | 75 | #define PN544_HCI_I2C_DRIVER_NAME "pn544_hci_i2c" |
62 | 76 | ||
63 | /* | 77 | /* |
@@ -195,18 +209,19 @@ static void pn544_hci_i2c_platform_init(struct pn544_i2c_phy *phy) | |||
195 | nfc_info(&phy->i2c_dev->dev, "Detecting nfc_en polarity\n"); | 209 | nfc_info(&phy->i2c_dev->dev, "Detecting nfc_en polarity\n"); |
196 | 210 | ||
197 | /* Disable fw download */ | 211 | /* Disable fw download */ |
198 | gpio_set_value(phy->gpio_fw, 0); | 212 | gpio_set_value_cansleep(phy->gpio_fw, 0); |
199 | 213 | ||
200 | for (polarity = 0; polarity < 2; polarity++) { | 214 | for (polarity = 0; polarity < 2; polarity++) { |
201 | phy->en_polarity = polarity; | 215 | phy->en_polarity = polarity; |
202 | retry = 3; | 216 | retry = 3; |
203 | while (retry--) { | 217 | while (retry--) { |
204 | /* power off */ | 218 | /* power off */ |
205 | gpio_set_value(phy->gpio_en, !phy->en_polarity); | 219 | gpio_set_value_cansleep(phy->gpio_en, |
220 | !phy->en_polarity); | ||
206 | usleep_range(10000, 15000); | 221 | usleep_range(10000, 15000); |
207 | 222 | ||
208 | /* power on */ | 223 | /* power on */ |
209 | gpio_set_value(phy->gpio_en, phy->en_polarity); | 224 | gpio_set_value_cansleep(phy->gpio_en, phy->en_polarity); |
210 | usleep_range(10000, 15000); | 225 | usleep_range(10000, 15000); |
211 | 226 | ||
212 | /* send reset */ | 227 | /* send reset */ |
@@ -225,13 +240,14 @@ static void pn544_hci_i2c_platform_init(struct pn544_i2c_phy *phy) | |||
225 | "Could not detect nfc_en polarity, fallback to active high\n"); | 240 | "Could not detect nfc_en polarity, fallback to active high\n"); |
226 | 241 | ||
227 | out: | 242 | out: |
228 | gpio_set_value(phy->gpio_en, !phy->en_polarity); | 243 | gpio_set_value_cansleep(phy->gpio_en, !phy->en_polarity); |
229 | } | 244 | } |
230 | 245 | ||
231 | static void pn544_hci_i2c_enable_mode(struct pn544_i2c_phy *phy, int run_mode) | 246 | static void pn544_hci_i2c_enable_mode(struct pn544_i2c_phy *phy, int run_mode) |
232 | { | 247 | { |
233 | gpio_set_value(phy->gpio_fw, run_mode == PN544_FW_MODE ? 1 : 0); | 248 | gpio_set_value_cansleep(phy->gpio_fw, |
234 | gpio_set_value(phy->gpio_en, phy->en_polarity); | 249 | run_mode == PN544_FW_MODE ? 1 : 0); |
250 | gpio_set_value_cansleep(phy->gpio_en, phy->en_polarity); | ||
235 | usleep_range(10000, 15000); | 251 | usleep_range(10000, 15000); |
236 | 252 | ||
237 | phy->run_mode = run_mode; | 253 | phy->run_mode = run_mode; |
@@ -254,14 +270,14 @@ static void pn544_hci_i2c_disable(void *phy_id) | |||
254 | { | 270 | { |
255 | struct pn544_i2c_phy *phy = phy_id; | 271 | struct pn544_i2c_phy *phy = phy_id; |
256 | 272 | ||
257 | gpio_set_value(phy->gpio_fw, 0); | 273 | gpio_set_value_cansleep(phy->gpio_fw, 0); |
258 | gpio_set_value(phy->gpio_en, !phy->en_polarity); | 274 | gpio_set_value_cansleep(phy->gpio_en, !phy->en_polarity); |
259 | usleep_range(10000, 15000); | 275 | usleep_range(10000, 15000); |
260 | 276 | ||
261 | gpio_set_value(phy->gpio_en, phy->en_polarity); | 277 | gpio_set_value_cansleep(phy->gpio_en, phy->en_polarity); |
262 | usleep_range(10000, 15000); | 278 | usleep_range(10000, 15000); |
263 | 279 | ||
264 | gpio_set_value(phy->gpio_en, !phy->en_polarity); | 280 | gpio_set_value_cansleep(phy->gpio_en, !phy->en_polarity); |
265 | usleep_range(10000, 15000); | 281 | usleep_range(10000, 15000); |
266 | 282 | ||
267 | phy->powered = 0; | 283 | phy->powered = 0; |
@@ -859,6 +875,90 @@ exit_state_wait_secure_write_answer: | |||
859 | } | 875 | } |
860 | } | 876 | } |
861 | 877 | ||
878 | static int pn544_hci_i2c_acpi_request_resources(struct i2c_client *client) | ||
879 | { | ||
880 | struct pn544_i2c_phy *phy = i2c_get_clientdata(client); | ||
881 | const struct acpi_device_id *id; | ||
882 | struct gpio_desc *gpiod_en, *gpiod_irq, *gpiod_fw; | ||
883 | struct device *dev; | ||
884 | int ret; | ||
885 | |||
886 | if (!client) | ||
887 | return -EINVAL; | ||
888 | |||
889 | dev = &client->dev; | ||
890 | |||
891 | /* Match the struct device against a given list of ACPI IDs */ | ||
892 | id = acpi_match_device(dev->driver->acpi_match_table, dev); | ||
893 | |||
894 | if (!id) | ||
895 | return -ENODEV; | ||
896 | |||
897 | /* Get EN GPIO from ACPI */ | ||
898 | gpiod_en = devm_gpiod_get_index(dev, PN544_GPIO_NAME_EN, 1); | ||
899 | if (IS_ERR(gpiod_en)) { | ||
900 | nfc_err(dev, | ||
901 | "Unable to get EN GPIO\n"); | ||
902 | return -ENODEV; | ||
903 | } | ||
904 | |||
905 | phy->gpio_en = desc_to_gpio(gpiod_en); | ||
906 | |||
907 | /* Configuration EN GPIO */ | ||
908 | ret = gpiod_direction_output(gpiod_en, 0); | ||
909 | if (ret) { | ||
910 | nfc_err(dev, "Fail EN pin direction\n"); | ||
911 | return ret; | ||
912 | } | ||
913 | |||
914 | /* Get FW GPIO from ACPI */ | ||
915 | gpiod_fw = devm_gpiod_get_index(dev, PN544_GPIO_NAME_FW, 2); | ||
916 | if (IS_ERR(gpiod_fw)) { | ||
917 | nfc_err(dev, | ||
918 | "Unable to get FW GPIO\n"); | ||
919 | return -ENODEV; | ||
920 | } | ||
921 | |||
922 | phy->gpio_fw = desc_to_gpio(gpiod_fw); | ||
923 | |||
924 | /* Configuration FW GPIO */ | ||
925 | ret = gpiod_direction_output(gpiod_fw, 0); | ||
926 | if (ret) { | ||
927 | nfc_err(dev, "Fail FW pin direction\n"); | ||
928 | return ret; | ||
929 | } | ||
930 | |||
931 | /* Get IRQ GPIO */ | ||
932 | gpiod_irq = devm_gpiod_get_index(dev, PN544_GPIO_NAME_IRQ, 0); | ||
933 | if (IS_ERR(gpiod_irq)) { | ||
934 | nfc_err(dev, | ||
935 | "Unable to get IRQ GPIO\n"); | ||
936 | return -ENODEV; | ||
937 | } | ||
938 | |||
939 | phy->gpio_irq = desc_to_gpio(gpiod_irq); | ||
940 | |||
941 | /* Configure IRQ GPIO */ | ||
942 | ret = gpiod_direction_input(gpiod_irq); | ||
943 | if (ret) { | ||
944 | nfc_err(dev, "Fail IRQ pin direction\n"); | ||
945 | return ret; | ||
946 | } | ||
947 | |||
948 | /* Map the pin to an IRQ */ | ||
949 | ret = gpiod_to_irq(gpiod_irq); | ||
950 | if (ret < 0) { | ||
951 | nfc_err(dev, "Fail pin IRQ mapping\n"); | ||
952 | return ret; | ||
953 | } | ||
954 | |||
955 | nfc_info(dev, "GPIO resource, no:%d irq:%d\n", | ||
956 | desc_to_gpio(gpiod_irq), ret); | ||
957 | client->irq = ret; | ||
958 | |||
959 | return 0; | ||
960 | } | ||
961 | |||
862 | #ifdef CONFIG_OF | 962 | #ifdef CONFIG_OF |
863 | 963 | ||
864 | static int pn544_hci_i2c_of_request_resources(struct i2c_client *client) | 964 | static int pn544_hci_i2c_of_request_resources(struct i2c_client *client) |
@@ -884,7 +984,7 @@ static int pn544_hci_i2c_of_request_resources(struct i2c_client *client) | |||
884 | phy->gpio_en = ret; | 984 | phy->gpio_en = ret; |
885 | 985 | ||
886 | /* Configuration of EN GPIO */ | 986 | /* Configuration of EN GPIO */ |
887 | ret = gpio_request(phy->gpio_en, "pn544_en"); | 987 | ret = gpio_request(phy->gpio_en, PN544_GPIO_NAME_EN); |
888 | if (ret) { | 988 | if (ret) { |
889 | nfc_err(&client->dev, "Fail EN pin\n"); | 989 | nfc_err(&client->dev, "Fail EN pin\n"); |
890 | goto err_dt; | 990 | goto err_dt; |
@@ -906,7 +1006,7 @@ static int pn544_hci_i2c_of_request_resources(struct i2c_client *client) | |||
906 | phy->gpio_fw = ret; | 1006 | phy->gpio_fw = ret; |
907 | 1007 | ||
908 | /* Configuration of FW GPIO */ | 1008 | /* Configuration of FW GPIO */ |
909 | ret = gpio_request(phy->gpio_fw, "pn544_fw"); | 1009 | ret = gpio_request(phy->gpio_fw, PN544_GPIO_NAME_FW); |
910 | if (ret) { | 1010 | if (ret) { |
911 | nfc_err(&client->dev, "Fail FW pin\n"); | 1011 | nfc_err(&client->dev, "Fail FW pin\n"); |
912 | goto err_gpio_en; | 1012 | goto err_gpio_en; |
@@ -1001,6 +1101,14 @@ static int pn544_hci_i2c_probe(struct i2c_client *client, | |||
1001 | phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE); | 1101 | phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE); |
1002 | phy->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET); | 1102 | phy->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET); |
1003 | phy->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ); | 1103 | phy->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ); |
1104 | /* Using ACPI */ | ||
1105 | } else if (ACPI_HANDLE(&client->dev)) { | ||
1106 | r = pn544_hci_i2c_acpi_request_resources(client); | ||
1107 | if (r) { | ||
1108 | nfc_err(&client->dev, | ||
1109 | "Cannot get ACPI data\n"); | ||
1110 | return r; | ||
1111 | } | ||
1004 | } else { | 1112 | } else { |
1005 | nfc_err(&client->dev, "No platform data\n"); | 1113 | nfc_err(&client->dev, "No platform data\n"); |
1006 | return -EINVAL; | 1114 | return -EINVAL; |
@@ -1080,6 +1188,7 @@ static struct i2c_driver pn544_hci_i2c_driver = { | |||
1080 | .name = PN544_HCI_I2C_DRIVER_NAME, | 1188 | .name = PN544_HCI_I2C_DRIVER_NAME, |
1081 | .owner = THIS_MODULE, | 1189 | .owner = THIS_MODULE, |
1082 | .of_match_table = of_match_ptr(of_pn544_i2c_match), | 1190 | .of_match_table = of_match_ptr(of_pn544_i2c_match), |
1191 | .acpi_match_table = ACPI_PTR(pn544_hci_i2c_acpi_match), | ||
1083 | }, | 1192 | }, |
1084 | .probe = pn544_hci_i2c_probe, | 1193 | .probe = pn544_hci_i2c_probe, |
1085 | .id_table = pn544_hci_i2c_id_table, | 1194 | .id_table = pn544_hci_i2c_id_table, |
diff --git a/drivers/nfc/pn544/pn544.c b/drivers/nfc/pn544/pn544.c index 9c8051d20cea..12e819ddf17a 100644 --- a/drivers/nfc/pn544/pn544.c +++ b/drivers/nfc/pn544/pn544.c | |||
@@ -724,10 +724,11 @@ static int pn544_hci_check_presence(struct nfc_hci_dev *hdev, | |||
724 | * <= 0: driver handled the event, skb consumed | 724 | * <= 0: driver handled the event, skb consumed |
725 | * 1: driver does not handle the event, please do standard processing | 725 | * 1: driver does not handle the event, please do standard processing |
726 | */ | 726 | */ |
727 | static int pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, u8 event, | 727 | static int pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, |
728 | struct sk_buff *skb) | 728 | struct sk_buff *skb) |
729 | { | 729 | { |
730 | struct sk_buff *rgb_skb = NULL; | 730 | struct sk_buff *rgb_skb = NULL; |
731 | u8 gate = hdev->pipes[pipe].gate; | ||
731 | int r; | 732 | int r; |
732 | 733 | ||
733 | pr_debug("hci event %d\n", event); | 734 | pr_debug("hci event %d\n", event); |
diff --git a/drivers/nfc/st21nfca/Makefile b/drivers/nfc/st21nfca/Makefile index 7d688f97aa27..97edab4bbdf8 100644 --- a/drivers/nfc/st21nfca/Makefile +++ b/drivers/nfc/st21nfca/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for ST21NFCA HCI based NFC driver | 2 | # Makefile for ST21NFCA HCI based NFC driver |
3 | # | 3 | # |
4 | 4 | ||
5 | st21nfca_hci-objs = st21nfca.o st21nfca_dep.o | 5 | st21nfca_hci-objs = st21nfca.o st21nfca_dep.o st21nfca_se.o |
6 | obj-$(CONFIG_NFC_ST21NFCA) += st21nfca_hci.o | 6 | obj-$(CONFIG_NFC_ST21NFCA) += st21nfca_hci.o |
7 | 7 | ||
8 | st21nfca_i2c-objs = i2c.o | 8 | st21nfca_i2c-objs = i2c.o |
diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c index 05722085a59f..a32143951616 100644 --- a/drivers/nfc/st21nfca/i2c.c +++ b/drivers/nfc/st21nfca/i2c.c | |||
@@ -74,6 +74,8 @@ struct st21nfca_i2c_phy { | |||
74 | unsigned int gpio_ena; | 74 | unsigned int gpio_ena; |
75 | unsigned int irq_polarity; | 75 | unsigned int irq_polarity; |
76 | 76 | ||
77 | struct st21nfca_se_status se_status; | ||
78 | |||
77 | struct sk_buff *pending_skb; | 79 | struct sk_buff *pending_skb; |
78 | int current_read_len; | 80 | int current_read_len; |
79 | /* | 81 | /* |
@@ -537,6 +539,11 @@ static int st21nfca_hci_i2c_of_request_resources(struct i2c_client *client) | |||
537 | 539 | ||
538 | phy->irq_polarity = irq_get_trigger_type(client->irq); | 540 | phy->irq_polarity = irq_get_trigger_type(client->irq); |
539 | 541 | ||
542 | phy->se_status.is_ese_present = | ||
543 | of_property_read_bool(pp, "ese-present"); | ||
544 | phy->se_status.is_uicc_present = | ||
545 | of_property_read_bool(pp, "uicc-present"); | ||
546 | |||
540 | return 0; | 547 | return 0; |
541 | } | 548 | } |
542 | #else | 549 | #else |
@@ -571,6 +578,9 @@ static int st21nfca_hci_i2c_request_resources(struct i2c_client *client) | |||
571 | } | 578 | } |
572 | } | 579 | } |
573 | 580 | ||
581 | phy->se_status.is_ese_present = pdata->is_ese_present; | ||
582 | phy->se_status.is_uicc_present = pdata->is_uicc_present; | ||
583 | |||
574 | return 0; | 584 | return 0; |
575 | } | 585 | } |
576 | 586 | ||
@@ -591,11 +601,8 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client, | |||
591 | 601 | ||
592 | phy = devm_kzalloc(&client->dev, sizeof(struct st21nfca_i2c_phy), | 602 | phy = devm_kzalloc(&client->dev, sizeof(struct st21nfca_i2c_phy), |
593 | GFP_KERNEL); | 603 | GFP_KERNEL); |
594 | if (!phy) { | 604 | if (!phy) |
595 | nfc_err(&client->dev, | ||
596 | "Cannot allocate memory for st21nfca i2c phy.\n"); | ||
597 | return -ENOMEM; | 605 | return -ENOMEM; |
598 | } | ||
599 | 606 | ||
600 | phy->i2c_dev = client; | 607 | phy->i2c_dev = client; |
601 | phy->pending_skb = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE * 2, GFP_KERNEL); | 608 | phy->pending_skb = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE * 2, GFP_KERNEL); |
@@ -641,8 +648,11 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client, | |||
641 | } | 648 | } |
642 | 649 | ||
643 | return st21nfca_hci_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME, | 650 | return st21nfca_hci_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME, |
644 | ST21NFCA_FRAME_HEADROOM, ST21NFCA_FRAME_TAILROOM, | 651 | ST21NFCA_FRAME_HEADROOM, |
645 | ST21NFCA_HCI_LLC_MAX_PAYLOAD, &phy->hdev); | 652 | ST21NFCA_FRAME_TAILROOM, |
653 | ST21NFCA_HCI_LLC_MAX_PAYLOAD, | ||
654 | &phy->hdev, | ||
655 | &phy->se_status); | ||
646 | } | 656 | } |
647 | 657 | ||
648 | static int st21nfca_hci_i2c_remove(struct i2c_client *client) | 658 | static int st21nfca_hci_i2c_remove(struct i2c_client *client) |
@@ -661,6 +671,7 @@ static int st21nfca_hci_i2c_remove(struct i2c_client *client) | |||
661 | 671 | ||
662 | #ifdef CONFIG_OF | 672 | #ifdef CONFIG_OF |
663 | static const struct of_device_id of_st21nfca_i2c_match[] = { | 673 | static const struct of_device_id of_st21nfca_i2c_match[] = { |
674 | { .compatible = "st,st21nfca-i2c", }, | ||
664 | { .compatible = "st,st21nfca_i2c", }, | 675 | { .compatible = "st,st21nfca_i2c", }, |
665 | {} | 676 | {} |
666 | }; | 677 | }; |
diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c index f2596c8d68b0..24d3d240d5f4 100644 --- a/drivers/nfc/st21nfca/st21nfca.c +++ b/drivers/nfc/st21nfca/st21nfca.c | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | #include "st21nfca.h" | 24 | #include "st21nfca.h" |
25 | #include "st21nfca_dep.h" | 25 | #include "st21nfca_dep.h" |
26 | #include "st21nfca_se.h" | ||
26 | 27 | ||
27 | #define DRIVER_DESC "HCI NFC driver for ST21NFCA" | 28 | #define DRIVER_DESC "HCI NFC driver for ST21NFCA" |
28 | 29 | ||
@@ -62,7 +63,6 @@ | |||
62 | #define ST21NFCA_RF_CARD_F_DATARATE 0x08 | 63 | #define ST21NFCA_RF_CARD_F_DATARATE 0x08 |
63 | #define ST21NFCA_RF_CARD_F_DATARATE_212_424 0x01 | 64 | #define ST21NFCA_RF_CARD_F_DATARATE_212_424 0x01 |
64 | 65 | ||
65 | #define ST21NFCA_DEVICE_MGNT_GATE 0x01 | ||
66 | #define ST21NFCA_DEVICE_MGNT_PIPE 0x02 | 66 | #define ST21NFCA_DEVICE_MGNT_PIPE 0x02 |
67 | 67 | ||
68 | #define ST21NFCA_DM_GETINFO 0x13 | 68 | #define ST21NFCA_DM_GETINFO 0x13 |
@@ -78,6 +78,11 @@ | |||
78 | 78 | ||
79 | #define ST21NFCA_NFC_MODE 0x03 /* NFC_MODE parameter*/ | 79 | #define ST21NFCA_NFC_MODE 0x03 /* NFC_MODE parameter*/ |
80 | 80 | ||
81 | #define ST21NFCA_EVT_HOT_PLUG 0x03 | ||
82 | #define ST21NFCA_EVT_HOT_PLUG_IS_INHIBITED(x) (x->data[0] & 0x80) | ||
83 | |||
84 | #define ST21NFCA_SE_TO_PIPES 2000 | ||
85 | |||
81 | static DECLARE_BITMAP(dev_mask, ST21NFCA_NUM_DEVICES); | 86 | static DECLARE_BITMAP(dev_mask, ST21NFCA_NUM_DEVICES); |
82 | 87 | ||
83 | static struct nfc_hci_gate st21nfca_gates[] = { | 88 | static struct nfc_hci_gate st21nfca_gates[] = { |
@@ -92,6 +97,10 @@ static struct nfc_hci_gate st21nfca_gates[] = { | |||
92 | {ST21NFCA_RF_READER_14443_3_A_GATE, NFC_HCI_INVALID_PIPE}, | 97 | {ST21NFCA_RF_READER_14443_3_A_GATE, NFC_HCI_INVALID_PIPE}, |
93 | {ST21NFCA_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE}, | 98 | {ST21NFCA_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE}, |
94 | {ST21NFCA_RF_CARD_F_GATE, NFC_HCI_INVALID_PIPE}, | 99 | {ST21NFCA_RF_CARD_F_GATE, NFC_HCI_INVALID_PIPE}, |
100 | |||
101 | /* Secure element pipes are created by secure element host */ | ||
102 | {ST21NFCA_CONNECTIVITY_GATE, NFC_HCI_DO_NOT_CREATE_PIPE}, | ||
103 | {ST21NFCA_APDU_READER_GATE, NFC_HCI_DO_NOT_CREATE_PIPE}, | ||
95 | }; | 104 | }; |
96 | 105 | ||
97 | struct st21nfca_pipe_info { | 106 | struct st21nfca_pipe_info { |
@@ -118,18 +127,6 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev) | |||
118 | NFC_HCI_TERMINAL_HOST_ID, 0 | 127 | NFC_HCI_TERMINAL_HOST_ID, 0 |
119 | }; | 128 | }; |
120 | 129 | ||
121 | skb_pipe_list = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE, GFP_KERNEL); | ||
122 | if (!skb_pipe_list) { | ||
123 | r = -ENOMEM; | ||
124 | goto free_list; | ||
125 | } | ||
126 | |||
127 | skb_pipe_info = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE, GFP_KERNEL); | ||
128 | if (!skb_pipe_info) { | ||
129 | r = -ENOMEM; | ||
130 | goto free_info; | ||
131 | } | ||
132 | |||
133 | /* On ST21NFCA device pipes number are dynamics | 130 | /* On ST21NFCA device pipes number are dynamics |
134 | * A maximum of 16 pipes can be created at the same time | 131 | * A maximum of 16 pipes can be created at the same time |
135 | * If pipes are already created, hci_dev_up will fail. | 132 | * If pipes are already created, hci_dev_up will fail. |
@@ -148,7 +145,8 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev) | |||
148 | * Pipe can be closed and need to be open. | 145 | * Pipe can be closed and need to be open. |
149 | */ | 146 | */ |
150 | r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, | 147 | r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, |
151 | ST21NFCA_DEVICE_MGNT_GATE, ST21NFCA_DEVICE_MGNT_PIPE); | 148 | ST21NFCA_DEVICE_MGNT_GATE, |
149 | ST21NFCA_DEVICE_MGNT_PIPE); | ||
152 | if (r < 0) | 150 | if (r < 0) |
153 | goto free_info; | 151 | goto free_info; |
154 | 152 | ||
@@ -179,17 +177,28 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev) | |||
179 | * - destination gid (1byte) | 177 | * - destination gid (1byte) |
180 | */ | 178 | */ |
181 | info = (struct st21nfca_pipe_info *) skb_pipe_info->data; | 179 | info = (struct st21nfca_pipe_info *) skb_pipe_info->data; |
180 | if (info->dst_gate_id == ST21NFCA_APDU_READER_GATE && | ||
181 | info->src_host_id != ST21NFCA_ESE_HOST_ID) { | ||
182 | pr_err("Unexpected apdu_reader pipe on host %x\n", | ||
183 | info->src_host_id); | ||
184 | continue; | ||
185 | } | ||
186 | |||
182 | for (j = 0; (j < ARRAY_SIZE(st21nfca_gates)) && | 187 | for (j = 0; (j < ARRAY_SIZE(st21nfca_gates)) && |
183 | (st21nfca_gates[j].gate != info->dst_gate_id); | 188 | (st21nfca_gates[j].gate != info->dst_gate_id) ; j++) |
184 | j++) | ||
185 | ; | 189 | ; |
186 | 190 | ||
187 | if (j < ARRAY_SIZE(st21nfca_gates) && | 191 | if (j < ARRAY_SIZE(st21nfca_gates) && |
188 | st21nfca_gates[j].gate == info->dst_gate_id && | 192 | st21nfca_gates[j].gate == info->dst_gate_id && |
189 | ST21NFCA_DM_IS_PIPE_OPEN(info->pipe_state)) { | 193 | ST21NFCA_DM_IS_PIPE_OPEN(info->pipe_state)) { |
190 | st21nfca_gates[j].pipe = pipe_info[2]; | 194 | st21nfca_gates[j].pipe = pipe_info[2]; |
195 | |||
191 | hdev->gate2pipe[st21nfca_gates[j].gate] = | 196 | hdev->gate2pipe[st21nfca_gates[j].gate] = |
192 | st21nfca_gates[j].pipe; | 197 | st21nfca_gates[j].pipe; |
198 | hdev->pipes[st21nfca_gates[j].pipe].gate = | ||
199 | st21nfca_gates[j].gate; | ||
200 | hdev->pipes[st21nfca_gates[j].pipe].dest_host = | ||
201 | info->src_host_id; | ||
193 | } | 202 | } |
194 | } | 203 | } |
195 | 204 | ||
@@ -199,7 +208,7 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev) | |||
199 | */ | 208 | */ |
200 | if (skb_pipe_list->len + 3 < ARRAY_SIZE(st21nfca_gates)) { | 209 | if (skb_pipe_list->len + 3 < ARRAY_SIZE(st21nfca_gates)) { |
201 | for (i = skb_pipe_list->len + 3; | 210 | for (i = skb_pipe_list->len + 3; |
202 | i < ARRAY_SIZE(st21nfca_gates); i++) { | 211 | i < ARRAY_SIZE(st21nfca_gates) - 2; i++) { |
203 | r = nfc_hci_connect_gate(hdev, | 212 | r = nfc_hci_connect_gate(hdev, |
204 | NFC_HCI_HOST_CONTROLLER_ID, | 213 | NFC_HCI_HOST_CONTROLLER_ID, |
205 | st21nfca_gates[i].gate, | 214 | st21nfca_gates[i].gate, |
@@ -212,7 +221,6 @@ static int st21nfca_hci_load_session(struct nfc_hci_dev *hdev) | |||
212 | memcpy(hdev->init_data.gates, st21nfca_gates, sizeof(st21nfca_gates)); | 221 | memcpy(hdev->init_data.gates, st21nfca_gates, sizeof(st21nfca_gates)); |
213 | free_info: | 222 | free_info: |
214 | kfree_skb(skb_pipe_info); | 223 | kfree_skb(skb_pipe_info); |
215 | free_list: | ||
216 | kfree_skb(skb_pipe_list); | 224 | kfree_skb(skb_pipe_list); |
217 | return r; | 225 | return r; |
218 | } | 226 | } |
@@ -257,16 +265,33 @@ out: | |||
257 | 265 | ||
258 | static int st21nfca_hci_ready(struct nfc_hci_dev *hdev) | 266 | static int st21nfca_hci_ready(struct nfc_hci_dev *hdev) |
259 | { | 267 | { |
268 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
260 | struct sk_buff *skb; | 269 | struct sk_buff *skb; |
261 | 270 | ||
262 | u8 param; | 271 | u8 param; |
272 | u8 white_list[2]; | ||
273 | int wl_size = 0; | ||
263 | int r; | 274 | int r; |
264 | 275 | ||
265 | param = NFC_HCI_UICC_HOST_ID; | 276 | if (info->se_status->is_ese_present && |
266 | r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE, | 277 | info->se_status->is_uicc_present) { |
267 | NFC_HCI_ADMIN_WHITELIST, ¶m, 1); | 278 | white_list[wl_size++] = NFC_HCI_UICC_HOST_ID; |
268 | if (r < 0) | 279 | white_list[wl_size++] = ST21NFCA_ESE_HOST_ID; |
269 | return r; | 280 | } else if (!info->se_status->is_ese_present && |
281 | info->se_status->is_uicc_present) { | ||
282 | white_list[wl_size++] = NFC_HCI_UICC_HOST_ID; | ||
283 | } else if (info->se_status->is_ese_present && | ||
284 | !info->se_status->is_uicc_present) { | ||
285 | white_list[wl_size++] = ST21NFCA_ESE_HOST_ID; | ||
286 | } | ||
287 | |||
288 | if (wl_size) { | ||
289 | r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE, | ||
290 | NFC_HCI_ADMIN_WHITELIST, | ||
291 | (u8 *) &white_list, wl_size); | ||
292 | if (r < 0) | ||
293 | return r; | ||
294 | } | ||
270 | 295 | ||
271 | /* Set NFC_MODE in device management gate to enable */ | 296 | /* Set NFC_MODE in device management gate to enable */ |
272 | r = nfc_hci_get_param(hdev, ST21NFCA_DEVICE_MGNT_GATE, | 297 | r = nfc_hci_get_param(hdev, ST21NFCA_DEVICE_MGNT_GATE, |
@@ -274,8 +299,9 @@ static int st21nfca_hci_ready(struct nfc_hci_dev *hdev) | |||
274 | if (r < 0) | 299 | if (r < 0) |
275 | return r; | 300 | return r; |
276 | 301 | ||
277 | if (skb->data[0] == 0) { | 302 | param = skb->data[0]; |
278 | kfree_skb(skb); | 303 | kfree_skb(skb); |
304 | if (param == 0) { | ||
279 | param = 1; | 305 | param = 1; |
280 | 306 | ||
281 | r = nfc_hci_set_param(hdev, ST21NFCA_DEVICE_MGNT_GATE, | 307 | r = nfc_hci_set_param(hdev, ST21NFCA_DEVICE_MGNT_GATE, |
@@ -417,9 +443,12 @@ static int st21nfca_hci_start_poll(struct nfc_hci_dev *hdev, | |||
417 | r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE, | 443 | r = nfc_hci_set_param(hdev, ST21NFCA_RF_CARD_F_GATE, |
418 | ST21NFCA_RF_CARD_F_DATARATE, | 444 | ST21NFCA_RF_CARD_F_DATARATE, |
419 | param, 1); | 445 | param, 1); |
420 | if (r < 0) | 446 | if (r < 0) { |
447 | kfree_skb(datarate_skb); | ||
421 | return r; | 448 | return r; |
449 | } | ||
422 | } | 450 | } |
451 | kfree_skb(datarate_skb); | ||
423 | 452 | ||
424 | /* | 453 | /* |
425 | * Configure sens_res | 454 | * Configure sens_res |
@@ -673,15 +702,15 @@ static int st21nfca_hci_complete_target_discovered(struct nfc_hci_dev *hdev, | |||
673 | struct nfc_target *target) | 702 | struct nfc_target *target) |
674 | { | 703 | { |
675 | int r; | 704 | int r; |
676 | struct sk_buff *nfcid2_skb = NULL, *nfcid1_skb; | 705 | struct sk_buff *nfcid_skb = NULL; |
677 | 706 | ||
678 | if (gate == ST21NFCA_RF_READER_F_GATE) { | 707 | if (gate == ST21NFCA_RF_READER_F_GATE) { |
679 | r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_F_GATE, | 708 | r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_F_GATE, |
680 | ST21NFCA_RF_READER_F_NFCID2, &nfcid2_skb); | 709 | ST21NFCA_RF_READER_F_NFCID2, &nfcid_skb); |
681 | if (r < 0) | 710 | if (r < 0) |
682 | goto exit; | 711 | goto exit; |
683 | 712 | ||
684 | if (nfcid2_skb->len > NFC_SENSF_RES_MAXSIZE) { | 713 | if (nfcid_skb->len > NFC_SENSF_RES_MAXSIZE) { |
685 | r = -EPROTO; | 714 | r = -EPROTO; |
686 | goto exit; | 715 | goto exit; |
687 | } | 716 | } |
@@ -693,11 +722,11 @@ static int st21nfca_hci_complete_target_discovered(struct nfc_hci_dev *hdev, | |||
693 | * - After the reception of SEL_RES with NFCIP-1 compliant bit | 722 | * - After the reception of SEL_RES with NFCIP-1 compliant bit |
694 | * set for type A frame NFCID1 will be updated | 723 | * set for type A frame NFCID1 will be updated |
695 | */ | 724 | */ |
696 | if (nfcid2_skb->len > 0) { | 725 | if (nfcid_skb->len > 0) { |
697 | /* P2P in type F */ | 726 | /* P2P in type F */ |
698 | memcpy(target->sensf_res, nfcid2_skb->data, | 727 | memcpy(target->sensf_res, nfcid_skb->data, |
699 | nfcid2_skb->len); | 728 | nfcid_skb->len); |
700 | target->sensf_res_len = nfcid2_skb->len; | 729 | target->sensf_res_len = nfcid_skb->len; |
701 | /* NFC Forum Digital Protocol Table 44 */ | 730 | /* NFC Forum Digital Protocol Table 44 */ |
702 | if (target->sensf_res[0] == 0x01 && | 731 | if (target->sensf_res[0] == 0x01 && |
703 | target->sensf_res[1] == 0xfe) | 732 | target->sensf_res[1] == 0xfe) |
@@ -707,27 +736,28 @@ static int st21nfca_hci_complete_target_discovered(struct nfc_hci_dev *hdev, | |||
707 | target->supported_protocols = | 736 | target->supported_protocols = |
708 | NFC_PROTO_FELICA_MASK; | 737 | NFC_PROTO_FELICA_MASK; |
709 | } else { | 738 | } else { |
739 | kfree_skb(nfcid_skb); | ||
710 | /* P2P in type A */ | 740 | /* P2P in type A */ |
711 | r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_F_GATE, | 741 | r = nfc_hci_get_param(hdev, ST21NFCA_RF_READER_F_GATE, |
712 | ST21NFCA_RF_READER_F_NFCID1, | 742 | ST21NFCA_RF_READER_F_NFCID1, |
713 | &nfcid1_skb); | 743 | &nfcid_skb); |
714 | if (r < 0) | 744 | if (r < 0) |
715 | goto exit; | 745 | goto exit; |
716 | 746 | ||
717 | if (nfcid1_skb->len > NFC_NFCID1_MAXSIZE) { | 747 | if (nfcid_skb->len > NFC_NFCID1_MAXSIZE) { |
718 | r = -EPROTO; | 748 | r = -EPROTO; |
719 | goto exit; | 749 | goto exit; |
720 | } | 750 | } |
721 | memcpy(target->sensf_res, nfcid1_skb->data, | 751 | memcpy(target->sensf_res, nfcid_skb->data, |
722 | nfcid1_skb->len); | 752 | nfcid_skb->len); |
723 | target->sensf_res_len = nfcid1_skb->len; | 753 | target->sensf_res_len = nfcid_skb->len; |
724 | target->supported_protocols = NFC_PROTO_NFC_DEP_MASK; | 754 | target->supported_protocols = NFC_PROTO_NFC_DEP_MASK; |
725 | } | 755 | } |
726 | target->hci_reader_gate = ST21NFCA_RF_READER_F_GATE; | 756 | target->hci_reader_gate = ST21NFCA_RF_READER_F_GATE; |
727 | } | 757 | } |
728 | r = 1; | 758 | r = 1; |
729 | exit: | 759 | exit: |
730 | kfree_skb(nfcid2_skb); | 760 | kfree_skb(nfcid_skb); |
731 | return r; | 761 | return r; |
732 | } | 762 | } |
733 | 763 | ||
@@ -829,24 +859,82 @@ static int st21nfca_hci_check_presence(struct nfc_hci_dev *hdev, | |||
829 | } | 859 | } |
830 | } | 860 | } |
831 | 861 | ||
862 | static void st21nfca_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, | ||
863 | struct sk_buff *skb) | ||
864 | { | ||
865 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
866 | u8 gate = hdev->pipes[pipe].gate; | ||
867 | |||
868 | pr_debug("cmd: %x\n", cmd); | ||
869 | |||
870 | switch (cmd) { | ||
871 | case NFC_HCI_ANY_OPEN_PIPE: | ||
872 | if (gate != ST21NFCA_APDU_READER_GATE && | ||
873 | hdev->pipes[pipe].dest_host != NFC_HCI_UICC_HOST_ID) | ||
874 | info->se_info.count_pipes++; | ||
875 | |||
876 | if (info->se_info.count_pipes == info->se_info.expected_pipes) { | ||
877 | del_timer_sync(&info->se_info.se_active_timer); | ||
878 | info->se_info.se_active = false; | ||
879 | info->se_info.count_pipes = 0; | ||
880 | complete(&info->se_info.req_completion); | ||
881 | } | ||
882 | break; | ||
883 | } | ||
884 | } | ||
885 | |||
886 | static int st21nfca_admin_event_received(struct nfc_hci_dev *hdev, u8 event, | ||
887 | struct sk_buff *skb) | ||
888 | { | ||
889 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
890 | |||
891 | pr_debug("admin event: %x\n", event); | ||
892 | |||
893 | switch (event) { | ||
894 | case ST21NFCA_EVT_HOT_PLUG: | ||
895 | if (info->se_info.se_active) { | ||
896 | if (!ST21NFCA_EVT_HOT_PLUG_IS_INHIBITED(skb)) { | ||
897 | del_timer_sync(&info->se_info.se_active_timer); | ||
898 | info->se_info.se_active = false; | ||
899 | complete(&info->se_info.req_completion); | ||
900 | } else { | ||
901 | mod_timer(&info->se_info.se_active_timer, | ||
902 | jiffies + | ||
903 | msecs_to_jiffies(ST21NFCA_SE_TO_PIPES)); | ||
904 | } | ||
905 | } | ||
906 | break; | ||
907 | } | ||
908 | kfree_skb(skb); | ||
909 | return 0; | ||
910 | } | ||
911 | |||
832 | /* | 912 | /* |
833 | * Returns: | 913 | * Returns: |
834 | * <= 0: driver handled the event, skb consumed | 914 | * <= 0: driver handled the event, skb consumed |
835 | * 1: driver does not handle the event, please do standard processing | 915 | * 1: driver does not handle the event, please do standard processing |
836 | */ | 916 | */ |
837 | static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, | 917 | static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, |
838 | u8 event, struct sk_buff *skb) | 918 | u8 event, struct sk_buff *skb) |
839 | { | 919 | { |
920 | u8 gate = hdev->pipes[pipe].gate; | ||
921 | u8 host = hdev->pipes[pipe].dest_host; | ||
922 | |||
840 | pr_debug("hci event: %d gate: %x\n", event, gate); | 923 | pr_debug("hci event: %d gate: %x\n", event, gate); |
841 | 924 | ||
842 | switch (gate) { | 925 | switch (gate) { |
926 | case NFC_HCI_ADMIN_GATE: | ||
927 | return st21nfca_admin_event_received(hdev, event, skb); | ||
843 | case ST21NFCA_RF_CARD_F_GATE: | 928 | case ST21NFCA_RF_CARD_F_GATE: |
844 | return st21nfca_dep_event_received(hdev, event, skb); | 929 | return st21nfca_dep_event_received(hdev, event, skb); |
930 | case ST21NFCA_CONNECTIVITY_GATE: | ||
931 | return st21nfca_connectivity_event_received(hdev, host, | ||
932 | event, skb); | ||
933 | case ST21NFCA_APDU_READER_GATE: | ||
934 | return st21nfca_apdu_reader_event_received(hdev, event, skb); | ||
845 | default: | 935 | default: |
846 | return 1; | 936 | return 1; |
847 | } | 937 | } |
848 | kfree_skb(skb); | ||
849 | return 0; | ||
850 | } | 938 | } |
851 | 939 | ||
852 | static struct nfc_hci_ops st21nfca_hci_ops = { | 940 | static struct nfc_hci_ops st21nfca_hci_ops = { |
@@ -865,11 +953,17 @@ static struct nfc_hci_ops st21nfca_hci_ops = { | |||
865 | .tm_send = st21nfca_hci_tm_send, | 953 | .tm_send = st21nfca_hci_tm_send, |
866 | .check_presence = st21nfca_hci_check_presence, | 954 | .check_presence = st21nfca_hci_check_presence, |
867 | .event_received = st21nfca_hci_event_received, | 955 | .event_received = st21nfca_hci_event_received, |
956 | .cmd_received = st21nfca_hci_cmd_received, | ||
957 | .discover_se = st21nfca_hci_discover_se, | ||
958 | .enable_se = st21nfca_hci_enable_se, | ||
959 | .disable_se = st21nfca_hci_disable_se, | ||
960 | .se_io = st21nfca_hci_se_io, | ||
868 | }; | 961 | }; |
869 | 962 | ||
870 | int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, | 963 | int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, |
871 | char *llc_name, int phy_headroom, int phy_tailroom, | 964 | char *llc_name, int phy_headroom, int phy_tailroom, |
872 | int phy_payload, struct nfc_hci_dev **hdev) | 965 | int phy_payload, struct nfc_hci_dev **hdev, |
966 | struct st21nfca_se_status *se_status) | ||
873 | { | 967 | { |
874 | struct st21nfca_hci_info *info; | 968 | struct st21nfca_hci_info *info; |
875 | int r = 0; | 969 | int r = 0; |
@@ -929,6 +1023,8 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, | |||
929 | goto err_alloc_hdev; | 1023 | goto err_alloc_hdev; |
930 | } | 1024 | } |
931 | 1025 | ||
1026 | info->se_status = se_status; | ||
1027 | |||
932 | nfc_hci_set_clientdata(info->hdev, info); | 1028 | nfc_hci_set_clientdata(info->hdev, info); |
933 | 1029 | ||
934 | r = nfc_hci_register_device(info->hdev); | 1030 | r = nfc_hci_register_device(info->hdev); |
@@ -937,6 +1033,7 @@ int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, | |||
937 | 1033 | ||
938 | *hdev = info->hdev; | 1034 | *hdev = info->hdev; |
939 | st21nfca_dep_init(info->hdev); | 1035 | st21nfca_dep_init(info->hdev); |
1036 | st21nfca_se_init(info->hdev); | ||
940 | 1037 | ||
941 | return 0; | 1038 | return 0; |
942 | 1039 | ||
@@ -955,6 +1052,7 @@ void st21nfca_hci_remove(struct nfc_hci_dev *hdev) | |||
955 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | 1052 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); |
956 | 1053 | ||
957 | st21nfca_dep_deinit(hdev); | 1054 | st21nfca_dep_deinit(hdev); |
1055 | st21nfca_se_deinit(hdev); | ||
958 | nfc_hci_unregister_device(hdev); | 1056 | nfc_hci_unregister_device(hdev); |
959 | nfc_hci_free_device(hdev); | 1057 | nfc_hci_free_device(hdev); |
960 | kfree(info); | 1058 | kfree(info); |
diff --git a/drivers/nfc/st21nfca/st21nfca.h b/drivers/nfc/st21nfca/st21nfca.h index 7c2a85292230..15a78d330a9f 100644 --- a/drivers/nfc/st21nfca/st21nfca.h +++ b/drivers/nfc/st21nfca/st21nfca.h | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <net/nfc/hci.h> | 20 | #include <net/nfc/hci.h> |
21 | 21 | ||
22 | #include "st21nfca_dep.h" | 22 | #include "st21nfca_dep.h" |
23 | #include "st21nfca_se.h" | ||
23 | 24 | ||
24 | #define HCI_MODE 0 | 25 | #define HCI_MODE 0 |
25 | 26 | ||
@@ -51,9 +52,15 @@ | |||
51 | 52 | ||
52 | #define ST21NFCA_NUM_DEVICES 256 | 53 | #define ST21NFCA_NUM_DEVICES 256 |
53 | 54 | ||
55 | struct st21nfca_se_status { | ||
56 | bool is_ese_present; | ||
57 | bool is_uicc_present; | ||
58 | }; | ||
59 | |||
54 | int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, | 60 | int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, |
55 | char *llc_name, int phy_headroom, int phy_tailroom, | 61 | char *llc_name, int phy_headroom, int phy_tailroom, |
56 | int phy_payload, struct nfc_hci_dev **hdev); | 62 | int phy_payload, struct nfc_hci_dev **hdev, |
63 | struct st21nfca_se_status *se_status); | ||
57 | void st21nfca_hci_remove(struct nfc_hci_dev *hdev); | 64 | void st21nfca_hci_remove(struct nfc_hci_dev *hdev); |
58 | 65 | ||
59 | enum st21nfca_state { | 66 | enum st21nfca_state { |
@@ -66,6 +73,7 @@ struct st21nfca_hci_info { | |||
66 | void *phy_id; | 73 | void *phy_id; |
67 | 74 | ||
68 | struct nfc_hci_dev *hdev; | 75 | struct nfc_hci_dev *hdev; |
76 | struct st21nfca_se_status *se_status; | ||
69 | 77 | ||
70 | enum st21nfca_state state; | 78 | enum st21nfca_state state; |
71 | 79 | ||
@@ -76,13 +84,16 @@ struct st21nfca_hci_info { | |||
76 | void *async_cb_context; | 84 | void *async_cb_context; |
77 | 85 | ||
78 | struct st21nfca_dep_info dep_info; | 86 | struct st21nfca_dep_info dep_info; |
87 | struct st21nfca_se_info se_info; | ||
79 | }; | 88 | }; |
80 | 89 | ||
81 | /* Reader RF commands */ | 90 | /* Reader RF commands */ |
82 | #define ST21NFCA_WR_XCHG_DATA 0x10 | 91 | #define ST21NFCA_WR_XCHG_DATA 0x10 |
83 | |||
84 | #define ST21NFCA_RF_READER_F_GATE 0x14 | ||
85 | 92 | ||
86 | #define ST21NFCA_RF_CARD_F_GATE 0x24 | 93 | #define ST21NFCA_DEVICE_MGNT_GATE 0x01 |
94 | #define ST21NFCA_RF_READER_F_GATE 0x14 | ||
95 | #define ST21NFCA_RF_CARD_F_GATE 0x24 | ||
96 | #define ST21NFCA_APDU_READER_GATE 0xf0 | ||
97 | #define ST21NFCA_CONNECTIVITY_GATE 0x41 | ||
87 | 98 | ||
88 | #endif /* __LOCAL_ST21NFCA_H_ */ | 99 | #endif /* __LOCAL_ST21NFCA_H_ */ |
diff --git a/drivers/nfc/st21nfca/st21nfca_se.c b/drivers/nfc/st21nfca/st21nfca_se.c new file mode 100644 index 000000000000..9b93d3904ab5 --- /dev/null +++ b/drivers/nfc/st21nfca/st21nfca_se.c | |||
@@ -0,0 +1,390 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #include <net/nfc/hci.h> | ||
18 | |||
19 | #include "st21nfca.h" | ||
20 | #include "st21nfca_se.h" | ||
21 | |||
22 | #define ST21NFCA_EVT_UICC_ACTIVATE 0x10 | ||
23 | #define ST21NFCA_EVT_UICC_DEACTIVATE 0x13 | ||
24 | #define ST21NFCA_EVT_SE_HARD_RESET 0x20 | ||
25 | #define ST21NFCA_EVT_SE_SOFT_RESET 0x11 | ||
26 | #define ST21NFCA_EVT_SE_END_OF_APDU_TRANSFER 0x21 | ||
27 | #define ST21NFCA_EVT_SE_ACTIVATE 0x22 | ||
28 | #define ST21NFCA_EVT_SE_DEACTIVATE 0x23 | ||
29 | |||
30 | #define ST21NFCA_EVT_TRANSMIT_DATA 0x10 | ||
31 | #define ST21NFCA_EVT_WTX_REQUEST 0x11 | ||
32 | |||
33 | #define ST21NFCA_EVT_CONNECTIVITY 0x10 | ||
34 | #define ST21NFCA_EVT_TRANSACTION 0x12 | ||
35 | |||
36 | #define ST21NFCA_ESE_HOST_ID 0xc0 | ||
37 | |||
38 | #define ST21NFCA_SE_TO_HOT_PLUG 1000 | ||
39 | /* Connectivity pipe only */ | ||
40 | #define ST21NFCA_SE_COUNT_PIPE_UICC 0x01 | ||
41 | /* Connectivity + APDU Reader pipe */ | ||
42 | #define ST21NFCA_SE_COUNT_PIPE_EMBEDDED 0x02 | ||
43 | |||
44 | #define ST21NFCA_SE_MODE_OFF 0x00 | ||
45 | #define ST21NFCA_SE_MODE_ON 0x01 | ||
46 | |||
47 | #define ST21NFCA_PARAM_ATR 0x01 | ||
48 | #define ST21NFCA_ATR_DEFAULT_BWI 0x04 | ||
49 | |||
50 | /* | ||
51 | * WT = 2^BWI/10[s], convert into msecs and add a secure | ||
52 | * room by increasing by 2 this timeout | ||
53 | */ | ||
54 | #define ST21NFCA_BWI_TO_TIMEOUT(x) ((1 << x) * 200) | ||
55 | #define ST21NFCA_ATR_GET_Y_FROM_TD(x) (x >> 4) | ||
56 | |||
57 | /* If TA is present bit 0 is set */ | ||
58 | #define ST21NFCA_ATR_TA_PRESENT(x) (x & 0x01) | ||
59 | /* If TB is present bit 1 is set */ | ||
60 | #define ST21NFCA_ATR_TB_PRESENT(x) (x & 0x02) | ||
61 | |||
62 | static u8 st21nfca_se_get_bwi(struct nfc_hci_dev *hdev) | ||
63 | { | ||
64 | int i; | ||
65 | u8 td; | ||
66 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
67 | |||
68 | /* Bits 8 to 5 of the first TB for T=1 encode BWI from zero to nine */ | ||
69 | for (i = 1; i < ST21NFCA_ESE_MAX_LENGTH; i++) { | ||
70 | td = ST21NFCA_ATR_GET_Y_FROM_TD(info->se_info.atr[i]); | ||
71 | if (ST21NFCA_ATR_TA_PRESENT(td)) | ||
72 | i++; | ||
73 | if (ST21NFCA_ATR_TB_PRESENT(td)) { | ||
74 | i++; | ||
75 | return info->se_info.atr[i] >> 4; | ||
76 | } | ||
77 | } | ||
78 | return ST21NFCA_ATR_DEFAULT_BWI; | ||
79 | } | ||
80 | |||
81 | static void st21nfca_se_get_atr(struct nfc_hci_dev *hdev) | ||
82 | { | ||
83 | int r; | ||
84 | struct sk_buff *skb; | ||
85 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
86 | |||
87 | r = nfc_hci_get_param(hdev, ST21NFCA_APDU_READER_GATE, | ||
88 | ST21NFCA_PARAM_ATR, &skb); | ||
89 | if (r < 0) | ||
90 | return; | ||
91 | |||
92 | if (skb->len <= ST21NFCA_ESE_MAX_LENGTH) { | ||
93 | memcpy(info->se_info.atr, skb->data, skb->len); | ||
94 | info->se_info.wt_timeout = | ||
95 | ST21NFCA_BWI_TO_TIMEOUT(st21nfca_se_get_bwi(hdev)); | ||
96 | } | ||
97 | kfree_skb(skb); | ||
98 | } | ||
99 | |||
100 | static int st21nfca_hci_control_se(struct nfc_hci_dev *hdev, u32 se_idx, | ||
101 | u8 state) | ||
102 | { | ||
103 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
104 | int r; | ||
105 | struct sk_buff *sk_host_list; | ||
106 | u8 se_event, host_id; | ||
107 | |||
108 | switch (se_idx) { | ||
109 | case NFC_HCI_UICC_HOST_ID: | ||
110 | se_event = (state == ST21NFCA_SE_MODE_ON ? | ||
111 | ST21NFCA_EVT_UICC_ACTIVATE : | ||
112 | ST21NFCA_EVT_UICC_DEACTIVATE); | ||
113 | |||
114 | info->se_info.count_pipes = 0; | ||
115 | info->se_info.expected_pipes = ST21NFCA_SE_COUNT_PIPE_UICC; | ||
116 | break; | ||
117 | case ST21NFCA_ESE_HOST_ID: | ||
118 | se_event = (state == ST21NFCA_SE_MODE_ON ? | ||
119 | ST21NFCA_EVT_SE_ACTIVATE : | ||
120 | ST21NFCA_EVT_SE_DEACTIVATE); | ||
121 | |||
122 | info->se_info.count_pipes = 0; | ||
123 | info->se_info.expected_pipes = ST21NFCA_SE_COUNT_PIPE_EMBEDDED; | ||
124 | break; | ||
125 | default: | ||
126 | return -EINVAL; | ||
127 | } | ||
128 | |||
129 | /* | ||
130 | * Wait for an EVT_HOT_PLUG in order to | ||
131 | * retrieve a relevant host list. | ||
132 | */ | ||
133 | reinit_completion(&info->se_info.req_completion); | ||
134 | r = nfc_hci_send_event(hdev, ST21NFCA_DEVICE_MGNT_GATE, se_event, | ||
135 | NULL, 0); | ||
136 | if (r < 0) | ||
137 | return r; | ||
138 | |||
139 | mod_timer(&info->se_info.se_active_timer, jiffies + | ||
140 | msecs_to_jiffies(ST21NFCA_SE_TO_HOT_PLUG)); | ||
141 | info->se_info.se_active = true; | ||
142 | |||
143 | /* Ignore return value and check in any case the host_list */ | ||
144 | wait_for_completion_interruptible(&info->se_info.req_completion); | ||
145 | |||
146 | r = nfc_hci_get_param(hdev, NFC_HCI_ADMIN_GATE, | ||
147 | NFC_HCI_ADMIN_HOST_LIST, | ||
148 | &sk_host_list); | ||
149 | if (r < 0) | ||
150 | return r; | ||
151 | |||
152 | host_id = sk_host_list->data[sk_host_list->len - 1]; | ||
153 | kfree_skb(sk_host_list); | ||
154 | |||
155 | if (state == ST21NFCA_SE_MODE_ON && host_id == se_idx) | ||
156 | return se_idx; | ||
157 | else if (state == ST21NFCA_SE_MODE_OFF && host_id != se_idx) | ||
158 | return se_idx; | ||
159 | |||
160 | return -1; | ||
161 | } | ||
162 | |||
163 | int st21nfca_hci_discover_se(struct nfc_hci_dev *hdev) | ||
164 | { | ||
165 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
166 | int se_count = 0; | ||
167 | |||
168 | if (info->se_status->is_uicc_present) { | ||
169 | nfc_add_se(hdev->ndev, NFC_HCI_UICC_HOST_ID, NFC_SE_UICC); | ||
170 | se_count++; | ||
171 | } | ||
172 | |||
173 | if (info->se_status->is_ese_present) { | ||
174 | nfc_add_se(hdev->ndev, ST21NFCA_ESE_HOST_ID, NFC_SE_EMBEDDED); | ||
175 | se_count++; | ||
176 | } | ||
177 | |||
178 | return !se_count; | ||
179 | } | ||
180 | EXPORT_SYMBOL(st21nfca_hci_discover_se); | ||
181 | |||
182 | int st21nfca_hci_enable_se(struct nfc_hci_dev *hdev, u32 se_idx) | ||
183 | { | ||
184 | int r; | ||
185 | |||
186 | /* | ||
187 | * According to upper layer, se_idx == NFC_SE_UICC when | ||
188 | * info->se_status->is_uicc_enable is true should never happen. | ||
189 | * Same for eSE. | ||
190 | */ | ||
191 | r = st21nfca_hci_control_se(hdev, se_idx, ST21NFCA_SE_MODE_ON); | ||
192 | |||
193 | if (r == ST21NFCA_ESE_HOST_ID) { | ||
194 | st21nfca_se_get_atr(hdev); | ||
195 | r = nfc_hci_send_event(hdev, ST21NFCA_APDU_READER_GATE, | ||
196 | ST21NFCA_EVT_SE_SOFT_RESET, NULL, 0); | ||
197 | if (r < 0) | ||
198 | return r; | ||
199 | } else if (r < 0) { | ||
200 | /* | ||
201 | * The activation tentative failed, the secure element | ||
202 | * is not connected. Remove from the list. | ||
203 | */ | ||
204 | nfc_remove_se(hdev->ndev, se_idx); | ||
205 | return r; | ||
206 | } | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | EXPORT_SYMBOL(st21nfca_hci_enable_se); | ||
211 | |||
212 | int st21nfca_hci_disable_se(struct nfc_hci_dev *hdev, u32 se_idx) | ||
213 | { | ||
214 | int r; | ||
215 | |||
216 | /* | ||
217 | * According to upper layer, se_idx == NFC_SE_UICC when | ||
218 | * info->se_status->is_uicc_enable is true should never happen | ||
219 | * Same for eSE. | ||
220 | */ | ||
221 | r = st21nfca_hci_control_se(hdev, se_idx, ST21NFCA_SE_MODE_OFF); | ||
222 | if (r < 0) | ||
223 | return r; | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | EXPORT_SYMBOL(st21nfca_hci_disable_se); | ||
228 | |||
229 | int st21nfca_hci_se_io(struct nfc_hci_dev *hdev, u32 se_idx, | ||
230 | u8 *apdu, size_t apdu_length, | ||
231 | se_io_cb_t cb, void *cb_context) | ||
232 | { | ||
233 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
234 | |||
235 | pr_debug("se_io %x\n", se_idx); | ||
236 | |||
237 | switch (se_idx) { | ||
238 | case ST21NFCA_ESE_HOST_ID: | ||
239 | info->se_info.cb = cb; | ||
240 | info->se_info.cb_context = cb_context; | ||
241 | mod_timer(&info->se_info.bwi_timer, jiffies + | ||
242 | msecs_to_jiffies(info->se_info.wt_timeout)); | ||
243 | info->se_info.bwi_active = true; | ||
244 | return nfc_hci_send_event(hdev, ST21NFCA_APDU_READER_GATE, | ||
245 | ST21NFCA_EVT_TRANSMIT_DATA, | ||
246 | apdu, apdu_length); | ||
247 | default: | ||
248 | return -ENODEV; | ||
249 | } | ||
250 | } | ||
251 | EXPORT_SYMBOL(st21nfca_hci_se_io); | ||
252 | |||
253 | static void st21nfca_se_wt_timeout(unsigned long data) | ||
254 | { | ||
255 | /* | ||
256 | * No answer from the secure element | ||
257 | * within the defined timeout. | ||
258 | * Let's send a reset request as recovery procedure. | ||
259 | * According to the situation, we first try to send a software reset | ||
260 | * to the secure element. If the next command is still not | ||
261 | * answering in time, we send to the CLF a secure element hardware | ||
262 | * reset request. | ||
263 | */ | ||
264 | /* hardware reset managed through VCC_UICC_OUT power supply */ | ||
265 | u8 param = 0x01; | ||
266 | struct st21nfca_hci_info *info = (struct st21nfca_hci_info *) data; | ||
267 | |||
268 | pr_debug("\n"); | ||
269 | |||
270 | info->se_info.bwi_active = false; | ||
271 | |||
272 | if (!info->se_info.xch_error) { | ||
273 | info->se_info.xch_error = true; | ||
274 | nfc_hci_send_event(info->hdev, ST21NFCA_APDU_READER_GATE, | ||
275 | ST21NFCA_EVT_SE_SOFT_RESET, NULL, 0); | ||
276 | } else { | ||
277 | info->se_info.xch_error = false; | ||
278 | nfc_hci_send_event(info->hdev, ST21NFCA_DEVICE_MGNT_GATE, | ||
279 | ST21NFCA_EVT_SE_HARD_RESET, ¶m, 1); | ||
280 | } | ||
281 | info->se_info.cb(info->se_info.cb_context, NULL, 0, -ETIME); | ||
282 | } | ||
283 | |||
284 | static void st21nfca_se_activation_timeout(unsigned long data) | ||
285 | { | ||
286 | struct st21nfca_hci_info *info = (struct st21nfca_hci_info *) data; | ||
287 | |||
288 | pr_debug("\n"); | ||
289 | |||
290 | info->se_info.se_active = false; | ||
291 | |||
292 | complete(&info->se_info.req_completion); | ||
293 | } | ||
294 | |||
295 | /* | ||
296 | * Returns: | ||
297 | * <= 0: driver handled the event, skb consumed | ||
298 | * 1: driver does not handle the event, please do standard processing | ||
299 | */ | ||
300 | int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host, | ||
301 | u8 event, struct sk_buff *skb) | ||
302 | { | ||
303 | int r = 0; | ||
304 | |||
305 | pr_debug("connectivity gate event: %x\n", event); | ||
306 | |||
307 | switch (event) { | ||
308 | case ST21NFCA_EVT_CONNECTIVITY: | ||
309 | break; | ||
310 | case ST21NFCA_EVT_TRANSACTION: | ||
311 | break; | ||
312 | default: | ||
313 | return 1; | ||
314 | } | ||
315 | kfree_skb(skb); | ||
316 | return r; | ||
317 | } | ||
318 | EXPORT_SYMBOL(st21nfca_connectivity_event_received); | ||
319 | |||
320 | int st21nfca_apdu_reader_event_received(struct nfc_hci_dev *hdev, | ||
321 | u8 event, struct sk_buff *skb) | ||
322 | { | ||
323 | int r = 0; | ||
324 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
325 | |||
326 | pr_debug("apdu reader gate event: %x\n", event); | ||
327 | |||
328 | switch (event) { | ||
329 | case ST21NFCA_EVT_TRANSMIT_DATA: | ||
330 | del_timer_sync(&info->se_info.bwi_timer); | ||
331 | info->se_info.bwi_active = false; | ||
332 | r = nfc_hci_send_event(hdev, ST21NFCA_DEVICE_MGNT_GATE, | ||
333 | ST21NFCA_EVT_SE_END_OF_APDU_TRANSFER, NULL, 0); | ||
334 | if (r < 0) | ||
335 | goto exit; | ||
336 | |||
337 | info->se_info.cb(info->se_info.cb_context, | ||
338 | skb->data, skb->len, 0); | ||
339 | break; | ||
340 | case ST21NFCA_EVT_WTX_REQUEST: | ||
341 | mod_timer(&info->se_info.bwi_timer, jiffies + | ||
342 | msecs_to_jiffies(info->se_info.wt_timeout)); | ||
343 | break; | ||
344 | } | ||
345 | |||
346 | exit: | ||
347 | kfree_skb(skb); | ||
348 | return r; | ||
349 | } | ||
350 | EXPORT_SYMBOL(st21nfca_apdu_reader_event_received); | ||
351 | |||
352 | void st21nfca_se_init(struct nfc_hci_dev *hdev) | ||
353 | { | ||
354 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
355 | |||
356 | init_completion(&info->se_info.req_completion); | ||
357 | /* initialize timers */ | ||
358 | init_timer(&info->se_info.bwi_timer); | ||
359 | info->se_info.bwi_timer.data = (unsigned long)info; | ||
360 | info->se_info.bwi_timer.function = st21nfca_se_wt_timeout; | ||
361 | info->se_info.bwi_active = false; | ||
362 | |||
363 | init_timer(&info->se_info.se_active_timer); | ||
364 | info->se_info.se_active_timer.data = (unsigned long)info; | ||
365 | info->se_info.se_active_timer.function = st21nfca_se_activation_timeout; | ||
366 | info->se_info.se_active = false; | ||
367 | |||
368 | info->se_info.count_pipes = 0; | ||
369 | info->se_info.expected_pipes = 0; | ||
370 | |||
371 | info->se_info.xch_error = false; | ||
372 | |||
373 | info->se_info.wt_timeout = | ||
374 | ST21NFCA_BWI_TO_TIMEOUT(ST21NFCA_ATR_DEFAULT_BWI); | ||
375 | } | ||
376 | EXPORT_SYMBOL(st21nfca_se_init); | ||
377 | |||
378 | void st21nfca_se_deinit(struct nfc_hci_dev *hdev) | ||
379 | { | ||
380 | struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev); | ||
381 | |||
382 | if (info->se_info.bwi_active) | ||
383 | del_timer_sync(&info->se_info.bwi_timer); | ||
384 | if (info->se_info.se_active) | ||
385 | del_timer_sync(&info->se_info.se_active_timer); | ||
386 | |||
387 | info->se_info.bwi_active = false; | ||
388 | info->se_info.se_active = false; | ||
389 | } | ||
390 | EXPORT_SYMBOL(st21nfca_se_deinit); | ||
diff --git a/drivers/nfc/st21nfca/st21nfca_se.h b/drivers/nfc/st21nfca/st21nfca_se.h new file mode 100644 index 000000000000..b172cfcaeb90 --- /dev/null +++ b/drivers/nfc/st21nfca/st21nfca_se.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #ifndef __ST21NFCA_SE_H | ||
18 | #define __ST21NFCA_SE_H | ||
19 | |||
20 | #include <linux/skbuff.h> | ||
21 | #include <linux/workqueue.h> | ||
22 | |||
23 | /* | ||
24 | * ref ISO7816-3 chap 8.1. the initial character TS is followed by a | ||
25 | * sequence of at most 32 characters. | ||
26 | */ | ||
27 | #define ST21NFCA_ESE_MAX_LENGTH 33 | ||
28 | #define ST21NFCA_ESE_HOST_ID 0xc0 | ||
29 | |||
30 | struct st21nfca_se_info { | ||
31 | u8 atr[ST21NFCA_ESE_MAX_LENGTH]; | ||
32 | struct completion req_completion; | ||
33 | |||
34 | struct timer_list bwi_timer; | ||
35 | int wt_timeout; /* in msecs */ | ||
36 | bool bwi_active; | ||
37 | |||
38 | struct timer_list se_active_timer; | ||
39 | bool se_active; | ||
40 | int expected_pipes; | ||
41 | int count_pipes; | ||
42 | |||
43 | bool xch_error; | ||
44 | |||
45 | se_io_cb_t cb; | ||
46 | void *cb_context; | ||
47 | }; | ||
48 | |||
49 | int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host, | ||
50 | u8 event, struct sk_buff *skb); | ||
51 | int st21nfca_apdu_reader_event_received(struct nfc_hci_dev *hdev, | ||
52 | u8 event, struct sk_buff *skb); | ||
53 | |||
54 | int st21nfca_hci_discover_se(struct nfc_hci_dev *hdev); | ||
55 | int st21nfca_hci_enable_se(struct nfc_hci_dev *hdev, u32 se_idx); | ||
56 | int st21nfca_hci_disable_se(struct nfc_hci_dev *hdev, u32 se_idx); | ||
57 | int st21nfca_hci_se_io(struct nfc_hci_dev *hdev, u32 se_idx, | ||
58 | u8 *apdu, size_t apdu_length, | ||
59 | se_io_cb_t cb, void *cb_context); | ||
60 | |||
61 | void st21nfca_se_init(struct nfc_hci_dev *hdev); | ||
62 | void st21nfca_se_deinit(struct nfc_hci_dev *hdev); | ||
63 | #endif /* __ST21NFCA_SE_H */ | ||
diff --git a/drivers/nfc/st21nfcb/i2c.c b/drivers/nfc/st21nfcb/i2c.c index 01ba865863ee..eb886932d972 100644 --- a/drivers/nfc/st21nfcb/i2c.c +++ b/drivers/nfc/st21nfcb/i2c.c | |||
@@ -199,7 +199,7 @@ static irqreturn_t st21nfcb_nci_irq_thread_fn(int irq, void *phy_id) | |||
199 | struct sk_buff *skb = NULL; | 199 | struct sk_buff *skb = NULL; |
200 | int r; | 200 | int r; |
201 | 201 | ||
202 | if (!phy || irq != phy->i2c_dev->irq) { | 202 | if (!phy || !phy->ndlc || irq != phy->i2c_dev->irq) { |
203 | WARN_ON_ONCE(1); | 203 | WARN_ON_ONCE(1); |
204 | return IRQ_NONE; | 204 | return IRQ_NONE; |
205 | } | 205 | } |
@@ -343,18 +343,22 @@ static int st21nfcb_nci_i2c_probe(struct i2c_client *client, | |||
343 | return -ENODEV; | 343 | return -ENODEV; |
344 | } | 344 | } |
345 | 345 | ||
346 | r = ndlc_probe(phy, &i2c_phy_ops, &client->dev, | ||
347 | ST21NFCB_FRAME_HEADROOM, ST21NFCB_FRAME_TAILROOM, | ||
348 | &phy->ndlc); | ||
349 | if (r < 0) { | ||
350 | nfc_err(&client->dev, "Unable to register ndlc layer\n"); | ||
351 | return r; | ||
352 | } | ||
353 | |||
346 | r = devm_request_threaded_irq(&client->dev, client->irq, NULL, | 354 | r = devm_request_threaded_irq(&client->dev, client->irq, NULL, |
347 | st21nfcb_nci_irq_thread_fn, | 355 | st21nfcb_nci_irq_thread_fn, |
348 | phy->irq_polarity | IRQF_ONESHOT, | 356 | phy->irq_polarity | IRQF_ONESHOT, |
349 | ST21NFCB_NCI_DRIVER_NAME, phy); | 357 | ST21NFCB_NCI_DRIVER_NAME, phy); |
350 | if (r < 0) { | 358 | if (r < 0) |
351 | nfc_err(&client->dev, "Unable to register IRQ handler\n"); | 359 | nfc_err(&client->dev, "Unable to register IRQ handler\n"); |
352 | return r; | ||
353 | } | ||
354 | 360 | ||
355 | return ndlc_probe(phy, &i2c_phy_ops, &client->dev, | 361 | return r; |
356 | ST21NFCB_FRAME_HEADROOM, ST21NFCB_FRAME_TAILROOM, | ||
357 | &phy->ndlc); | ||
358 | } | 362 | } |
359 | 363 | ||
360 | static int st21nfcb_nci_i2c_remove(struct i2c_client *client) | 364 | static int st21nfcb_nci_i2c_remove(struct i2c_client *client) |
@@ -373,6 +377,7 @@ static int st21nfcb_nci_i2c_remove(struct i2c_client *client) | |||
373 | 377 | ||
374 | #ifdef CONFIG_OF | 378 | #ifdef CONFIG_OF |
375 | static const struct of_device_id of_st21nfcb_i2c_match[] = { | 379 | static const struct of_device_id of_st21nfcb_i2c_match[] = { |
380 | { .compatible = "st,st21nfcb-i2c", }, | ||
376 | { .compatible = "st,st21nfcb_i2c", }, | 381 | { .compatible = "st,st21nfcb_i2c", }, |
377 | {} | 382 | {} |
378 | }; | 383 | }; |
diff --git a/drivers/nfc/st21nfcb/ndlc.c b/drivers/nfc/st21nfcb/ndlc.c index bac50e805f1d..5fbf59d2138c 100644 --- a/drivers/nfc/st21nfcb/ndlc.c +++ b/drivers/nfc/st21nfcb/ndlc.c | |||
@@ -138,7 +138,7 @@ static void llt_ndlc_requeue_data_pending(struct llt_ndlc *ndlc) | |||
138 | default: | 138 | default: |
139 | pr_err("UNKNOWN Packet Control Byte=%d\n", pcb); | 139 | pr_err("UNKNOWN Packet Control Byte=%d\n", pcb); |
140 | kfree_skb(skb); | 140 | kfree_skb(skb); |
141 | break; | 141 | continue; |
142 | } | 142 | } |
143 | skb_queue_head(&ndlc->send_q, skb); | 143 | skb_queue_head(&ndlc->send_q, skb); |
144 | } | 144 | } |
@@ -297,6 +297,5 @@ void ndlc_remove(struct llt_ndlc *ndlc) | |||
297 | skb_queue_purge(&ndlc->send_q); | 297 | skb_queue_purge(&ndlc->send_q); |
298 | 298 | ||
299 | st21nfcb_nci_remove(ndlc->ndev); | 299 | st21nfcb_nci_remove(ndlc->ndev); |
300 | kfree(ndlc); | ||
301 | } | 300 | } |
302 | EXPORT_SYMBOL(ndlc_remove); | 301 | EXPORT_SYMBOL(ndlc_remove); |
diff --git a/include/linux/platform_data/st21nfca.h b/include/linux/platform_data/st21nfca.h index 5087fff96d86..cc2bdafb0c69 100644 --- a/include/linux/platform_data/st21nfca.h +++ b/include/linux/platform_data/st21nfca.h | |||
@@ -26,6 +26,8 @@ | |||
26 | struct st21nfca_nfc_platform_data { | 26 | struct st21nfca_nfc_platform_data { |
27 | unsigned int gpio_ena; | 27 | unsigned int gpio_ena; |
28 | unsigned int irq_polarity; | 28 | unsigned int irq_polarity; |
29 | bool is_ese_present; | ||
30 | bool is_uicc_present; | ||
29 | }; | 31 | }; |
30 | 32 | ||
31 | #endif /* _ST21NFCA_HCI_H_ */ | 33 | #endif /* _ST21NFCA_HCI_H_ */ |
diff --git a/include/linux/platform_data/st21nfcb.h b/include/linux/platform_data/st21nfcb.h index c3b432f5b63e..b023373d9874 100644 --- a/include/linux/platform_data/st21nfcb.h +++ b/include/linux/platform_data/st21nfcb.h | |||
@@ -19,8 +19,6 @@ | |||
19 | #ifndef _ST21NFCB_NCI_H_ | 19 | #ifndef _ST21NFCB_NCI_H_ |
20 | #define _ST21NFCB_NCI_H_ | 20 | #define _ST21NFCB_NCI_H_ |
21 | 21 | ||
22 | #include <linux/i2c.h> | ||
23 | |||
24 | #define ST21NFCB_NCI_DRIVER_NAME "st21nfcb_nci" | 22 | #define ST21NFCB_NCI_DRIVER_NAME "st21nfcb_nci" |
25 | 23 | ||
26 | struct st21nfcb_nfc_platform_data { | 24 | struct st21nfcb_nfc_platform_data { |
@@ -28,4 +26,4 @@ struct st21nfcb_nfc_platform_data { | |||
28 | unsigned int irq_polarity; | 26 | unsigned int irq_polarity; |
29 | }; | 27 | }; |
30 | 28 | ||
31 | #endif /* _ST21NFCA_HCI_H_ */ | 29 | #endif /* _ST21NFCB_NCI_H_ */ |
diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h index 14bd0e1c47fa..ab672b537dd4 100644 --- a/include/net/nfc/hci.h +++ b/include/net/nfc/hci.h | |||
@@ -51,8 +51,10 @@ struct nfc_hci_ops { | |||
51 | int (*tm_send)(struct nfc_hci_dev *hdev, struct sk_buff *skb); | 51 | int (*tm_send)(struct nfc_hci_dev *hdev, struct sk_buff *skb); |
52 | int (*check_presence)(struct nfc_hci_dev *hdev, | 52 | int (*check_presence)(struct nfc_hci_dev *hdev, |
53 | struct nfc_target *target); | 53 | struct nfc_target *target); |
54 | int (*event_received)(struct nfc_hci_dev *hdev, u8 gate, u8 event, | 54 | int (*event_received)(struct nfc_hci_dev *hdev, u8 pipe, u8 event, |
55 | struct sk_buff *skb); | 55 | struct sk_buff *skb); |
56 | void (*cmd_received)(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, | ||
57 | struct sk_buff *skb); | ||
56 | int (*fw_download)(struct nfc_hci_dev *hdev, const char *firmware_name); | 58 | int (*fw_download)(struct nfc_hci_dev *hdev, const char *firmware_name); |
57 | int (*discover_se)(struct nfc_hci_dev *dev); | 59 | int (*discover_se)(struct nfc_hci_dev *dev); |
58 | int (*enable_se)(struct nfc_hci_dev *dev, u32 se_idx); | 60 | int (*enable_se)(struct nfc_hci_dev *dev, u32 se_idx); |
@@ -63,8 +65,10 @@ struct nfc_hci_ops { | |||
63 | }; | 65 | }; |
64 | 66 | ||
65 | /* Pipes */ | 67 | /* Pipes */ |
66 | #define NFC_HCI_INVALID_PIPE 0x80 | ||
67 | #define NFC_HCI_DO_NOT_CREATE_PIPE 0x81 | 68 | #define NFC_HCI_DO_NOT_CREATE_PIPE 0x81 |
69 | #define NFC_HCI_INVALID_PIPE 0x80 | ||
70 | #define NFC_HCI_INVALID_GATE 0xFF | ||
71 | #define NFC_HCI_INVALID_HOST 0x80 | ||
68 | #define NFC_HCI_LINK_MGMT_PIPE 0x00 | 72 | #define NFC_HCI_LINK_MGMT_PIPE 0x00 |
69 | #define NFC_HCI_ADMIN_PIPE 0x01 | 73 | #define NFC_HCI_ADMIN_PIPE 0x01 |
70 | 74 | ||
@@ -73,7 +77,13 @@ struct nfc_hci_gate { | |||
73 | u8 pipe; | 77 | u8 pipe; |
74 | }; | 78 | }; |
75 | 79 | ||
80 | struct nfc_hci_pipe { | ||
81 | u8 gate; | ||
82 | u8 dest_host; | ||
83 | }; | ||
84 | |||
76 | #define NFC_HCI_MAX_CUSTOM_GATES 50 | 85 | #define NFC_HCI_MAX_CUSTOM_GATES 50 |
86 | #define NFC_HCI_MAX_PIPES 127 | ||
77 | struct nfc_hci_init_data { | 87 | struct nfc_hci_init_data { |
78 | u8 gate_count; | 88 | u8 gate_count; |
79 | struct nfc_hci_gate gates[NFC_HCI_MAX_CUSTOM_GATES]; | 89 | struct nfc_hci_gate gates[NFC_HCI_MAX_CUSTOM_GATES]; |
@@ -125,6 +135,7 @@ struct nfc_hci_dev { | |||
125 | void *clientdata; | 135 | void *clientdata; |
126 | 136 | ||
127 | u8 gate2pipe[NFC_HCI_MAX_GATES]; | 137 | u8 gate2pipe[NFC_HCI_MAX_GATES]; |
138 | struct nfc_hci_pipe pipes[NFC_HCI_MAX_PIPES]; | ||
128 | 139 | ||
129 | u8 sw_romlib; | 140 | u8 sw_romlib; |
130 | u8 sw_patch; | 141 | u8 sw_patch; |
@@ -167,6 +178,8 @@ void *nfc_hci_get_clientdata(struct nfc_hci_dev *hdev); | |||
167 | void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err); | 178 | void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err); |
168 | 179 | ||
169 | int nfc_hci_result_to_errno(u8 result); | 180 | int nfc_hci_result_to_errno(u8 result); |
181 | void nfc_hci_reset_pipes(struct nfc_hci_dev *dev); | ||
182 | void nfc_hci_reset_pipes_per_host(struct nfc_hci_dev *hdev, u8 host); | ||
170 | 183 | ||
171 | /* Host IDs */ | 184 | /* Host IDs */ |
172 | #define NFC_HCI_HOST_CONTROLLER_ID 0x00 | 185 | #define NFC_HCI_HOST_CONTROLLER_ID 0x00 |
@@ -219,6 +232,12 @@ int nfc_hci_result_to_errno(u8 result); | |||
219 | #define NFC_HCI_EVT_POST_DATA 0x02 | 232 | #define NFC_HCI_EVT_POST_DATA 0x02 |
220 | #define NFC_HCI_EVT_HOT_PLUG 0x03 | 233 | #define NFC_HCI_EVT_HOT_PLUG 0x03 |
221 | 234 | ||
235 | /* Generic commands */ | ||
236 | #define NFC_HCI_ANY_SET_PARAMETER 0x01 | ||
237 | #define NFC_HCI_ANY_GET_PARAMETER 0x02 | ||
238 | #define NFC_HCI_ANY_OPEN_PIPE 0x03 | ||
239 | #define NFC_HCI_ANY_CLOSE_PIPE 0x04 | ||
240 | |||
222 | /* Reader RF gates events */ | 241 | /* Reader RF gates events */ |
223 | #define NFC_HCI_EVT_READER_REQUESTED 0x10 | 242 | #define NFC_HCI_EVT_READER_REQUESTED 0x10 |
224 | #define NFC_HCI_EVT_END_OPERATION 0x11 | 243 | #define NFC_HCI_EVT_END_OPERATION 0x11 |
@@ -249,8 +268,6 @@ int nfc_hci_send_cmd(struct nfc_hci_dev *hdev, u8 gate, u8 cmd, | |||
249 | int nfc_hci_send_cmd_async(struct nfc_hci_dev *hdev, u8 gate, u8 cmd, | 268 | int nfc_hci_send_cmd_async(struct nfc_hci_dev *hdev, u8 gate, u8 cmd, |
250 | const u8 *param, size_t param_len, | 269 | const u8 *param, size_t param_len, |
251 | data_exchange_cb_t cb, void *cb_context); | 270 | data_exchange_cb_t cb, void *cb_context); |
252 | int nfc_hci_send_response(struct nfc_hci_dev *hdev, u8 gate, u8 response, | ||
253 | const u8 *param, size_t param_len); | ||
254 | int nfc_hci_send_event(struct nfc_hci_dev *hdev, u8 gate, u8 event, | 271 | int nfc_hci_send_event(struct nfc_hci_dev *hdev, u8 gate, u8 event, |
255 | const u8 *param, size_t param_len); | 272 | const u8 *param, size_t param_len); |
256 | int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate); | 273 | int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate); |
diff --git a/net/nfc/core.c b/net/nfc/core.c index 819b87702b70..7f1b6351755c 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
@@ -555,7 +555,6 @@ EXPORT_SYMBOL(nfc_find_se); | |||
555 | 555 | ||
556 | int nfc_enable_se(struct nfc_dev *dev, u32 se_idx) | 556 | int nfc_enable_se(struct nfc_dev *dev, u32 se_idx) |
557 | { | 557 | { |
558 | |||
559 | struct nfc_se *se; | 558 | struct nfc_se *se; |
560 | int rc; | 559 | int rc; |
561 | 560 | ||
@@ -605,7 +604,6 @@ error: | |||
605 | 604 | ||
606 | int nfc_disable_se(struct nfc_dev *dev, u32 se_idx) | 605 | int nfc_disable_se(struct nfc_dev *dev, u32 se_idx) |
607 | { | 606 | { |
608 | |||
609 | struct nfc_se *se; | 607 | struct nfc_se *se; |
610 | int rc; | 608 | int rc; |
611 | 609 | ||
diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c index 91df487aa0a9..844673cb7c18 100644 --- a/net/nfc/hci/command.c +++ b/net/nfc/hci/command.c | |||
@@ -116,23 +116,6 @@ int nfc_hci_send_event(struct nfc_hci_dev *hdev, u8 gate, u8 event, | |||
116 | } | 116 | } |
117 | EXPORT_SYMBOL(nfc_hci_send_event); | 117 | EXPORT_SYMBOL(nfc_hci_send_event); |
118 | 118 | ||
119 | int nfc_hci_send_response(struct nfc_hci_dev *hdev, u8 gate, u8 response, | ||
120 | const u8 *param, size_t param_len) | ||
121 | { | ||
122 | u8 pipe; | ||
123 | |||
124 | pr_debug("\n"); | ||
125 | |||
126 | pipe = hdev->gate2pipe[gate]; | ||
127 | if (pipe == NFC_HCI_INVALID_PIPE) | ||
128 | return -EADDRNOTAVAIL; | ||
129 | |||
130 | return nfc_hci_hcp_message_tx(hdev, pipe, NFC_HCI_HCP_RESPONSE, | ||
131 | response, param, param_len, NULL, NULL, | ||
132 | 0); | ||
133 | } | ||
134 | EXPORT_SYMBOL(nfc_hci_send_response); | ||
135 | |||
136 | /* | 119 | /* |
137 | * Execute an hci command sent to gate. | 120 | * Execute an hci command sent to gate. |
138 | * skb will contain response data if success. skb can be NULL if you are not | 121 | * skb will contain response data if success. skb can be NULL if you are not |
@@ -331,7 +314,7 @@ int nfc_hci_disconnect_all_gates(struct nfc_hci_dev *hdev) | |||
331 | if (r < 0) | 314 | if (r < 0) |
332 | return r; | 315 | return r; |
333 | 316 | ||
334 | memset(hdev->gate2pipe, NFC_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe)); | 317 | nfc_hci_reset_pipes(hdev); |
335 | 318 | ||
336 | return 0; | 319 | return 0; |
337 | } | 320 | } |
@@ -345,7 +328,7 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate, | |||
345 | 328 | ||
346 | pr_debug("\n"); | 329 | pr_debug("\n"); |
347 | 330 | ||
348 | if (hdev->gate2pipe[dest_gate] == NFC_HCI_DO_NOT_CREATE_PIPE) | 331 | if (pipe == NFC_HCI_DO_NOT_CREATE_PIPE) |
349 | return 0; | 332 | return 0; |
350 | 333 | ||
351 | if (hdev->gate2pipe[dest_gate] != NFC_HCI_INVALID_PIPE) | 334 | if (hdev->gate2pipe[dest_gate] != NFC_HCI_INVALID_PIPE) |
@@ -380,6 +363,8 @@ open_pipe: | |||
380 | return r; | 363 | return r; |
381 | } | 364 | } |
382 | 365 | ||
366 | hdev->pipes[pipe].gate = dest_gate; | ||
367 | hdev->pipes[pipe].dest_host = dest_host; | ||
383 | hdev->gate2pipe[dest_gate] = pipe; | 368 | hdev->gate2pipe[dest_gate] = pipe; |
384 | 369 | ||
385 | return 0; | 370 | return 0; |
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index ef50e7716c4a..6e061da2258a 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c | |||
@@ -46,6 +46,32 @@ int nfc_hci_result_to_errno(u8 result) | |||
46 | } | 46 | } |
47 | EXPORT_SYMBOL(nfc_hci_result_to_errno); | 47 | EXPORT_SYMBOL(nfc_hci_result_to_errno); |
48 | 48 | ||
49 | void nfc_hci_reset_pipes(struct nfc_hci_dev *hdev) | ||
50 | { | ||
51 | int i = 0; | ||
52 | |||
53 | for (i = 0; i < NFC_HCI_MAX_PIPES; i++) { | ||
54 | hdev->pipes[i].gate = NFC_HCI_INVALID_GATE; | ||
55 | hdev->pipes[i].dest_host = NFC_HCI_INVALID_HOST; | ||
56 | } | ||
57 | memset(hdev->gate2pipe, NFC_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe)); | ||
58 | } | ||
59 | EXPORT_SYMBOL(nfc_hci_reset_pipes); | ||
60 | |||
61 | void nfc_hci_reset_pipes_per_host(struct nfc_hci_dev *hdev, u8 host) | ||
62 | { | ||
63 | int i = 0; | ||
64 | |||
65 | for (i = 0; i < NFC_HCI_MAX_PIPES; i++) { | ||
66 | if (hdev->pipes[i].dest_host != host) | ||
67 | continue; | ||
68 | |||
69 | hdev->pipes[i].gate = NFC_HCI_INVALID_GATE; | ||
70 | hdev->pipes[i].dest_host = NFC_HCI_INVALID_HOST; | ||
71 | } | ||
72 | } | ||
73 | EXPORT_SYMBOL(nfc_hci_reset_pipes_per_host); | ||
74 | |||
49 | static void nfc_hci_msg_tx_work(struct work_struct *work) | 75 | static void nfc_hci_msg_tx_work(struct work_struct *work) |
50 | { | 76 | { |
51 | struct nfc_hci_dev *hdev = container_of(work, struct nfc_hci_dev, | 77 | struct nfc_hci_dev *hdev = container_of(work, struct nfc_hci_dev, |
@@ -167,48 +193,69 @@ exit: | |||
167 | void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, | 193 | void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, |
168 | struct sk_buff *skb) | 194 | struct sk_buff *skb) |
169 | { | 195 | { |
170 | int r = 0; | 196 | u8 gate = hdev->pipes[pipe].gate; |
171 | u8 gate = nfc_hci_pipe2gate(hdev, pipe); | 197 | u8 status = NFC_HCI_ANY_OK; |
172 | u8 local_gate, new_pipe; | 198 | struct hci_create_pipe_resp *create_info; |
173 | u8 gate_opened = 0x00; | 199 | struct hci_delete_pipe_noti *delete_info; |
200 | struct hci_all_pipe_cleared_noti *cleared_info; | ||
174 | 201 | ||
175 | pr_debug("from gate %x pipe %x cmd %x\n", gate, pipe, cmd); | 202 | pr_debug("from gate %x pipe %x cmd %x\n", gate, pipe, cmd); |
176 | 203 | ||
177 | switch (cmd) { | 204 | switch (cmd) { |
178 | case NFC_HCI_ADM_NOTIFY_PIPE_CREATED: | 205 | case NFC_HCI_ADM_NOTIFY_PIPE_CREATED: |
179 | if (skb->len != 5) { | 206 | if (skb->len != 5) { |
180 | r = -EPROTO; | 207 | status = NFC_HCI_ANY_E_NOK; |
181 | break; | 208 | goto exit; |
182 | } | 209 | } |
210 | create_info = (struct hci_create_pipe_resp *)skb->data; | ||
183 | 211 | ||
184 | local_gate = skb->data[3]; | 212 | /* Save the new created pipe and bind with local gate, |
185 | new_pipe = skb->data[4]; | ||
186 | nfc_hci_send_response(hdev, gate, NFC_HCI_ANY_OK, NULL, 0); | ||
187 | |||
188 | /* save the new created pipe and bind with local gate, | ||
189 | * the description for skb->data[3] is destination gate id | 213 | * the description for skb->data[3] is destination gate id |
190 | * but since we received this cmd from host controller, we | 214 | * but since we received this cmd from host controller, we |
191 | * are the destination and it is our local gate | 215 | * are the destination and it is our local gate |
192 | */ | 216 | */ |
193 | hdev->gate2pipe[local_gate] = new_pipe; | 217 | hdev->gate2pipe[create_info->dest_gate] = create_info->pipe; |
218 | hdev->pipes[create_info->pipe].gate = create_info->dest_gate; | ||
219 | hdev->pipes[create_info->pipe].dest_host = | ||
220 | create_info->src_host; | ||
194 | break; | 221 | break; |
195 | case NFC_HCI_ANY_OPEN_PIPE: | 222 | case NFC_HCI_ANY_OPEN_PIPE: |
196 | /* if the pipe is already created, we allow remote host to | 223 | if (gate == NFC_HCI_INVALID_GATE) { |
197 | * open it | 224 | status = NFC_HCI_ANY_E_NOK; |
198 | */ | 225 | goto exit; |
199 | if (gate != 0xff) | 226 | } |
200 | nfc_hci_send_response(hdev, gate, NFC_HCI_ANY_OK, | 227 | break; |
201 | &gate_opened, 1); | 228 | case NFC_HCI_ADM_NOTIFY_PIPE_DELETED: |
229 | if (skb->len != 1) { | ||
230 | status = NFC_HCI_ANY_E_NOK; | ||
231 | goto exit; | ||
232 | } | ||
233 | delete_info = (struct hci_delete_pipe_noti *)skb->data; | ||
234 | |||
235 | hdev->pipes[delete_info->pipe].gate = NFC_HCI_INVALID_GATE; | ||
236 | hdev->pipes[delete_info->pipe].dest_host = NFC_HCI_INVALID_HOST; | ||
202 | break; | 237 | break; |
203 | case NFC_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED: | 238 | case NFC_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED: |
204 | nfc_hci_send_response(hdev, gate, NFC_HCI_ANY_OK, NULL, 0); | 239 | if (skb->len != 1) { |
240 | status = NFC_HCI_ANY_E_NOK; | ||
241 | goto exit; | ||
242 | } | ||
243 | cleared_info = (struct hci_all_pipe_cleared_noti *)skb->data; | ||
244 | |||
245 | nfc_hci_reset_pipes_per_host(hdev, cleared_info->host); | ||
205 | break; | 246 | break; |
206 | default: | 247 | default: |
207 | pr_info("Discarded unknown cmd %x to gate %x\n", cmd, gate); | 248 | pr_info("Discarded unknown cmd %x to gate %x\n", cmd, gate); |
208 | r = -EINVAL; | ||
209 | break; | 249 | break; |
210 | } | 250 | } |
211 | 251 | ||
252 | if (hdev->ops->cmd_received) | ||
253 | hdev->ops->cmd_received(hdev, pipe, cmd, skb); | ||
254 | |||
255 | exit: | ||
256 | nfc_hci_hcp_message_tx(hdev, pipe, NFC_HCI_HCP_RESPONSE, | ||
257 | status, NULL, 0, NULL, NULL, 0); | ||
258 | |||
212 | kfree_skb(skb); | 259 | kfree_skb(skb); |
213 | } | 260 | } |
214 | 261 | ||
@@ -330,15 +377,15 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, | |||
330 | struct sk_buff *skb) | 377 | struct sk_buff *skb) |
331 | { | 378 | { |
332 | int r = 0; | 379 | int r = 0; |
333 | u8 gate = nfc_hci_pipe2gate(hdev, pipe); | 380 | u8 gate = hdev->pipes[pipe].gate; |
334 | 381 | ||
335 | if (gate == 0xff) { | 382 | if (gate == NFC_HCI_INVALID_GATE) { |
336 | pr_err("Discarded event %x to unopened pipe %x\n", event, pipe); | 383 | pr_err("Discarded event %x to unopened pipe %x\n", event, pipe); |
337 | goto exit; | 384 | goto exit; |
338 | } | 385 | } |
339 | 386 | ||
340 | if (hdev->ops->event_received) { | 387 | if (hdev->ops->event_received) { |
341 | r = hdev->ops->event_received(hdev, gate, event, skb); | 388 | r = hdev->ops->event_received(hdev, pipe, event, skb); |
342 | if (r <= 0) | 389 | if (r <= 0) |
343 | goto exit_noskb; | 390 | goto exit_noskb; |
344 | } | 391 | } |
@@ -573,7 +620,7 @@ static int hci_dev_down(struct nfc_dev *nfc_dev) | |||
573 | if (hdev->ops->close) | 620 | if (hdev->ops->close) |
574 | hdev->ops->close(hdev); | 621 | hdev->ops->close(hdev); |
575 | 622 | ||
576 | memset(hdev->gate2pipe, NFC_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe)); | 623 | nfc_hci_reset_pipes(hdev); |
577 | 624 | ||
578 | return 0; | 625 | return 0; |
579 | } | 626 | } |
@@ -932,7 +979,7 @@ struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, | |||
932 | 979 | ||
933 | nfc_set_drvdata(hdev->ndev, hdev); | 980 | nfc_set_drvdata(hdev->ndev, hdev); |
934 | 981 | ||
935 | memset(hdev->gate2pipe, NFC_HCI_INVALID_PIPE, sizeof(hdev->gate2pipe)); | 982 | nfc_hci_reset_pipes(hdev); |
936 | 983 | ||
937 | hdev->quirks = quirks; | 984 | hdev->quirks = quirks; |
938 | 985 | ||
diff --git a/net/nfc/hci/hci.h b/net/nfc/hci/hci.h index c3d2e2c1394c..ab4c8e80b1ad 100644 --- a/net/nfc/hci/hci.h +++ b/net/nfc/hci/hci.h | |||
@@ -65,6 +65,14 @@ struct hci_create_pipe_resp { | |||
65 | u8 pipe; | 65 | u8 pipe; |
66 | } __packed; | 66 | } __packed; |
67 | 67 | ||
68 | struct hci_delete_pipe_noti { | ||
69 | u8 pipe; | ||
70 | } __packed; | ||
71 | |||
72 | struct hci_all_pipe_cleared_noti { | ||
73 | u8 host; | ||
74 | } __packed; | ||
75 | |||
68 | #define NFC_HCI_FRAGMENT 0x7f | 76 | #define NFC_HCI_FRAGMENT 0x7f |
69 | 77 | ||
70 | #define HCP_HEADER(type, instr) ((((type) & 0x03) << 6) | ((instr) & 0x3f)) | 78 | #define HCP_HEADER(type, instr) ((((type) & 0x03) << 6) | ((instr) & 0x3f)) |
@@ -77,8 +85,6 @@ int nfc_hci_hcp_message_tx(struct nfc_hci_dev *hdev, u8 pipe, | |||
77 | data_exchange_cb_t cb, void *cb_context, | 85 | data_exchange_cb_t cb, void *cb_context, |
78 | unsigned long completion_delay); | 86 | unsigned long completion_delay); |
79 | 87 | ||
80 | u8 nfc_hci_pipe2gate(struct nfc_hci_dev *hdev, u8 pipe); | ||
81 | |||
82 | void nfc_hci_hcp_message_rx(struct nfc_hci_dev *hdev, u8 pipe, u8 type, | 88 | void nfc_hci_hcp_message_rx(struct nfc_hci_dev *hdev, u8 pipe, u8 type, |
83 | u8 instruction, struct sk_buff *skb); | 89 | u8 instruction, struct sk_buff *skb); |
84 | 90 | ||
diff --git a/net/nfc/hci/hcp.c b/net/nfc/hci/hcp.c index e9de1514656e..1fe725d66085 100644 --- a/net/nfc/hci/hcp.c +++ b/net/nfc/hci/hcp.c | |||
@@ -124,17 +124,6 @@ out_skb_err: | |||
124 | return err; | 124 | return err; |
125 | } | 125 | } |
126 | 126 | ||
127 | u8 nfc_hci_pipe2gate(struct nfc_hci_dev *hdev, u8 pipe) | ||
128 | { | ||
129 | int gate; | ||
130 | |||
131 | for (gate = 0; gate < NFC_HCI_MAX_GATES; gate++) | ||
132 | if (hdev->gate2pipe[gate] == pipe) | ||
133 | return gate; | ||
134 | |||
135 | return 0xff; | ||
136 | } | ||
137 | |||
138 | /* | 127 | /* |
139 | * Receive hcp message for pipe, with type and cmd. | 128 | * Receive hcp message for pipe, with type and cmd. |
140 | * skb contains optional message data only. | 129 | * skb contains optional message data only. |