pn80t gpio: wire up the gpio toggle
This change connects the interface targeted
APDU:
0xff 0xe0 0x00 0x00
to the nq-nci platform to allow the inBootloader
gpio to be toggled (cleared).
Test: works with the new kernel
echo -e 'ffe00000 9000' | strace -e ioctl ese-replay nq-nci # shows ioctl
applet or kernel state not toggling.
Bug: 37159008
Change-Id: I4526be8901b512bd289ddf10c6cda26f9ecdf506
diff --git a/libese-hw/nxp/include/ese/hw/nxp/pn80t/platform.h b/libese-hw/nxp/include/ese/hw/nxp/pn80t/platform.h
index 8dad425..9596cba 100644
--- a/libese-hw/nxp/include/ese/hw/nxp/pn80t/platform.h
+++ b/libese-hw/nxp/include/ese/hw/nxp/pn80t/platform.h
@@ -42,6 +42,8 @@
pn80t_platform_toggle_t *const toggle_ven; /* NFC_VEN */
/* Optional: enables eSE power control via |toggle_reset|. 1 = on, 0 = off */
pn80t_platform_toggle_t *const toggle_power_req; /* SVDD_PWR_REQ */
+ /* Optional: toggles the in bootloader gpio */
+ pn80t_platform_toggle_t *const toggle_bootloader; /* CLEAR_N */
/* Required: provides a usleep() equivalent. */
pn80t_platform_wait_t *const wait;
};
diff --git a/libese-hw/nxp/pn80t/common.c b/libese-hw/nxp/pn80t/common.c
index 5ea20a1..9a52454 100644
--- a/libese-hw/nxp/pn80t/common.c
+++ b/libese-hw/nxp/pn80t/common.c
@@ -213,17 +213,20 @@
struct EseSgBuffer *rx_buf,
uint32_t rx_len) {
/* Catch proprietary, host-targeted calls FF XX 00 00 */
+ const struct Pn80tPlatform *platform = ese->ops->opts;
static const uint32_t kCommandLength = 4;
static const uint8_t kResetCommand = 0x01;
static const uint8_t kGpioToggleCommand = 0xe0;
static const uint8_t kCooldownCommand = 0xe1;
uint8_t buf[kCommandLength + 1];
uint8_t ok[2] = {0x90, 0x00};
+ struct NxpState *ns = NXP_PN80T_STATE(ese);
/* Over-copy by one to make sure the command length matches. */
if (ese_sg_to_buf(tx_buf, tx_len, 0, sizeof(buf), buf) != kCommandLength) {
return 0;
}
- if (buf[0] != 0xff || buf[2] != 0x00 || buf[3] != 0x00) {
+ /* Let 3 change as an argument. */
+ if (buf[0] != 0xff || buf[2] != 0x00) {
return 0;
}
switch (buf[1]) {
@@ -236,8 +239,19 @@
return ese_sg_from_buf(rx_buf, rx_len, 0, sizeof(ok), ok);
case kGpioToggleCommand:
ALOGI("interface command received: gpio toggle");
- /* TODO - need kernel support first. */
- return 0;
+ if (platform->toggle_bootloader) {
+ int ret = platform->toggle_bootloader(ns->handle, buf[3]);
+ if (ret) {
+ /* Grab the bottom two bytes. */
+ ok[0] = (ret >> 8) & 0xff;
+ ok[1] = ret & 0xff;
+ }
+ } else {
+ /* Not found. */
+ ok[0] = 0x6a;
+ ok[1] = 0x82;
+ }
+ return ese_sg_from_buf(rx_buf, rx_len, 0, sizeof(ok), ok);
case kCooldownCommand:
ALOGI("interface command received: cooldown");
uint8_t reply[6] = {0, 0, 0, 0, 0x90, 0x00};
diff --git a/libese-hw/nxp/pn80t/linux_spidev.c b/libese-hw/nxp/pn80t/linux_spidev.c
index d4ac386..8b3c502 100644
--- a/libese-hw/nxp/pn80t/linux_spidev.c
+++ b/libese-hw/nxp/pn80t/linux_spidev.c
@@ -239,6 +239,7 @@
.toggle_reset = &platform_toggle_reset,
.toggle_ven = &platform_toggle_ven,
.toggle_power_req = &platform_toggle_power_req,
+ .toggle_bootloader = NULL,
.wait = &platform_wait,
};
diff --git a/libese-hw/nxp/pn80t/nq_nci.c b/libese-hw/nxp/pn80t/nq_nci.c
index 58a1777..60b7464 100644
--- a/libese-hw/nxp/pn80t/nq_nci.c
+++ b/libese-hw/nxp/pn80t/nq_nci.c
@@ -53,6 +53,7 @@
/* From kernel/drivers/nfc/nq-nci.h */
#define ESE_SET_PWR _IOW(0xE9, 0x02, unsigned int)
#define ESE_GET_PWR _IOR(0xE9, 0x03, unsigned int)
+#define ESE_CLEAR_GPIO _IOW(0xE9, 0x11, unsigned int)
static const char kDevicePath[] = "/dev/pn81a";
@@ -60,6 +61,11 @@
int fd;
};
+int platform_toggle_bootloader(void *blob, int val) {
+ const struct PlatformHandle *handle = blob;
+ return ioctl(handle->fd, ESE_CLEAR_GPIO, val);
+}
+
int platform_toggle_reset(void *blob, int val) {
const struct PlatformHandle *handle = blob;
/* 0=power and 1=no power in the kernel. */
@@ -171,6 +177,7 @@
.toggle_reset = &platform_toggle_reset,
.toggle_ven = NULL,
.toggle_power_req = NULL,
+ .toggle_bootloader = &platform_toggle_bootloader,
.wait = &platform_wait,
};