aboutsummaryrefslogtreecommitdiff
path: root/drivers/nfc
diff options
context:
space:
mode:
authorArron Wang <arron.wang@intel.com>2013-08-23 16:01:58 +0800
committerSamuel Ortiz <sameo@linux.intel.com>2013-09-25 01:35:38 +0200
commit5faba2fdf9819ebebd6d1a1cef70fddb0518cd08 (patch)
treeb9d52b453da916f760424af305df68b029847ace /drivers/nfc
parentb75ff5e84bb6c2d43a8ec39b240c80f0543821f0 (diff)
NFC: pn544: Add SE discover operation
For the SWP secure element, we send the proprietary SELF_TEST_SWP command and check the response. For the WI secure element, we simply try to switch to the default embedded SE mode. If that works, it means we have an embedded SE. Signed-off-by: Arron Wang <arron.wang@intel.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/nfc')
-rw-r--r--drivers/nfc/pn544/pn544.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/nfc/pn544/pn544.c b/drivers/nfc/pn544/pn544.c
index 078e62feba17..727f312e05d2 100644
--- a/drivers/nfc/pn544/pn544.c
+++ b/drivers/nfc/pn544/pn544.c
@@ -41,6 +41,7 @@ enum pn544_state {
/* Proprietary commands */
#define PN544_WRITE 0x3f
+#define PN544_TEST_SWP 0x21
/* Proprietary gates, events, commands and registers */
@@ -83,12 +84,14 @@ enum pn544_state {
#define PN544_SWP_MGMT_GATE 0xA0
#define PN544_NFC_WI_MGMT_GATE 0xA1
+#define PN544_NFC_ESE_DEFAULT_MODE 0x01
#define PN544_HCI_EVT_SND_DATA 0x01
#define PN544_HCI_EVT_ACTIVATED 0x02
#define PN544_HCI_EVT_DEACTIVATED 0x03
#define PN544_HCI_EVT_RCV_DATA 0x04
#define PN544_HCI_EVT_CONTINUE_MI 0x05
+#define PN544_HCI_EVT_SWITCH_MODE 0x03
#define PN544_HCI_CMD_ATTREQUEST 0x12
#define PN544_HCI_CMD_CONTINUE_ACTIVATION 0x13
@@ -792,6 +795,32 @@ static int pn544_hci_fw_download(struct nfc_hci_dev *hdev,
return info->fw_download(info->phy_id, firmware_name);
}
+static int pn544_hci_discover_se(struct nfc_hci_dev *hdev)
+{
+ u32 se_idx = 0;
+ u8 ese_mode = 0x01; /* Default mode */
+ struct sk_buff *res_skb;
+ int r;
+
+ r = nfc_hci_send_cmd(hdev, PN544_SYS_MGMT_GATE, PN544_TEST_SWP,
+ NULL, 0, &res_skb);
+
+ if (r == 0) {
+ if (res_skb->len == 2 && res_skb->data[0] == 0x00)
+ nfc_add_se(hdev->ndev, se_idx++, NFC_SE_UICC);
+
+ kfree_skb(res_skb);
+ }
+
+ r = nfc_hci_send_event(hdev, PN544_NFC_WI_MGMT_GATE,
+ PN544_HCI_EVT_SWITCH_MODE,
+ &ese_mode, 1);
+ if (r == 0)
+ nfc_add_se(hdev->ndev, se_idx++, NFC_SE_EMBEDDED);
+
+ return !se_idx;
+}
+
static struct nfc_hci_ops pn544_hci_ops = {
.open = pn544_hci_open,
.close = pn544_hci_close,
@@ -807,6 +836,7 @@ static struct nfc_hci_ops pn544_hci_ops = {
.check_presence = pn544_hci_check_presence,
.event_received = pn544_hci_event_received,
.fw_download = pn544_hci_fw_download,
+ .discover_se = pn544_hci_discover_se,
};
int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name,