From 1c970f1a493371aaa68f9227a8c3c395c5112fac Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Wed, 12 Sep 2012 17:59:39 -0400 Subject: Initial NFC HAL for NCI controllers. Bug: 7123942 Change-Id: Ic64aa6477f2eb65b489b3be5d49ad21ccce63e2d --- include/hardware/nfc.h | 192 +++++++++++++++++++++++++++++++++++++- modules/Android.mk | 2 +- modules/nfc-nci/Android.mk | 25 +++++ modules/nfc-nci/nfc_nci_example.c | 119 +++++++++++++++++++++++ modules/nfc/Android.mk | 2 +- modules/nfc/nfc_hw_example.c | 71 -------------- modules/nfc/nfc_pn544_example.c | 71 ++++++++++++++ 7 files changed, 406 insertions(+), 76 deletions(-) create mode 100644 modules/nfc-nci/Android.mk create mode 100644 modules/nfc-nci/nfc_nci_example.c delete mode 100644 modules/nfc/nfc_hw_example.c create mode 100644 modules/nfc/nfc_pn544_example.c diff --git a/include/hardware/nfc.h b/include/hardware/nfc.h index 74b3cfb..31410fb 100644 --- a/include/hardware/nfc.h +++ b/include/hardware/nfc.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 The Android Open Source Project + * Copyright (C) 2011, 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,6 @@ * limitations under the License. */ - #ifndef ANDROID_NFC_HAL_INTERFACE_H #define ANDROID_NFC_HAL_INTERFACE_H @@ -27,11 +26,198 @@ __BEGIN_DECLS -#define NFC_HARDWARE_MODULE_ID "nfc" + +/* NFC device HAL for NCI-based NFC controllers. + * + * This HAL allows NCI silicon vendors to make use + * of the core NCI stack in Android for their own silicon. + * + * The responibilities of the NCI HAL implementation + * are as follows: + * + * - Implement the transport to the NFC controller + * - Implement each of the HAL methods specified below as applicable to their silicon + * - Pass up received NCI messages from the controller to the stack + * + * A simplified timeline of NCI HAL method calls: + * 1) Core NCI stack calls open() + * 2) Core NCI stack executes CORE_RESET and CORE_INIT through calls to write() + * 3) Core NCI stack calls core_initialized() to allow HAL to do post-init configuration + * 4) Core NCI stack calls pre_discover() to allow HAL to prepare for RF discovery + * 5) Core NCI stack starts discovery through calls to write() + * 6) Core NCI stack stops discovery through calls to write() (e.g. screen turns off) + * 7) Core NCI stack calls pre_discover() to prepare for RF discovery (e.g. screen turned back on) + * 8) Core NCI stack starts discovery through calls to write() + * ... + * ... + * 9) Core NCI stack calls close() + */ +#define NFC_NCI_HARDWARE_MODULE_ID "nfc_nci" +#define NFC_NCI_CONTROLLER "nci" + +/* + * nfc_nci_module_t should contain module-specific parameters + */ +typedef struct nfc_nci_module_t { + struct hw_module_t common; +} nfc_nci_module_t; + +/* + * HAL events that can be passed back to the stack + */ +typedef uint8_t nfc_event_t; + +enum { + HAL_NFC_OPEN_CPLT_EVT = 0x00, + HAL_NFC_CLOSE_CPLT_EVT = 0x01, + HAL_NFC_POST_INIT_CPLT_EVT = 0x02, + HAL_NFC_NCI_RX_EVT = 0x03, + HAL_NFC_PRE_DISCOVER_CPLT_EVT = 0x04, + HAL_NFC_REQUEST_CONTROL_EVT = 0x05, + HAL_NFC_RELEASE_CONTROL_EVT = 0x06, + HAL_NFC_ERROR_EVT = 0x07 +}; + +/* + * Allowed status return values for each of the HAL methods + */ +typedef uint8_t nfc_status_t; + +enum { + HAL_NFC_STATUS_OK = 0x00, + HAL_NFC_STATUS_FAILED = 0x01, + HAL_NFC_STATUS_ERR_TRANSPORT = 0x02, + HAL_NFC_STATUS_ERR_CMD_TIMEOUT = 0x03, + HAL_NFC_STATUS_REFUSED = 0x04 +}; + +/* + * nfc_rx_data + * Struct used to pass received NCI packets up to the stack + */ +typedef struct nfc_rx_data { + uint16_t len; + uint8_t *p_data; +} nfc_rx_data_t; /* + */ +typedef union +{ + nfc_status_t status; + nfc_rx_data_t nci_rx; +} nfc_event_data_t; + +/* + * The callback passed in from the NFC stack that the HAL + * can use to pass events back to the stack. + */ +typedef void (nfc_stack_callback_t) (nfc_event_t event, nfc_event_data_t* p_data); + +/* nfc_nci_device_t starts with a hw_device_t struct, + * followed by device-specific methods and members. + * + * All methods in the NCI HAL are asynchronous. + */ +typedef struct nfc_nci_device { + struct hw_device_t common; + /* + * (*open)() Opens the NFC controller device and performs initialization. + * This may include patch download and other vendor-specific initialization. + * + * If open completes successfully, the controller should be ready to perform + * NCI initialization - ie accept CORE_RESET and subsequent commands through + * the write() call. + * + * If open() returns 0, the NCI stack will wait for a HAL_NFC_OPEN_CPLT_EVT + * before continuing. + * + * If open() returns any other value, the NCI stack will stop. + * + */ + int (*open)(const struct nfc_nci_device *p_dev, nfc_stack_callback_t *p_cback); + + /* + * (*write)() Performs an NCI write. + * + * This method may queue writes and return immediately. The only + * requirement is that the writes are executed in order. + */ + int (*write)(const struct nfc_nci_device *p_dev, uint16_t data_len, const uint8_t *p_data); + + /* + * (*core_initialized)() is called after the CORE_INIT_RSP is received from the NFCC. + * At this time, the HAL can do any chip-specific configuration. + * + * If core_initialized() returns 0, the NCI stack will wait for a HAL_NFC_POST_INIT_CPLT_EVT + * before continuing. + * + * If core_initialized() returns any other value, the NCI stack will continue + * immediately. + */ + int (*core_initialized)(const struct nfc_nci_device *p_dev, uint8_t* p_core_init_rsp_params); + + /* + * (*pre_discover)() Is called every time before starting RF discovery. + * It is a good place to do vendor-specific configuration that must be + * performed every time RF discovery is about to be started. + * + * If pre_discover() returns 0, the NCI stack will wait for a HAL_NFC_PRE_DISCOVER_CPLT_EVT + * before continuing. + * + * If pre_discover() returns any other value, the NCI stack will start + * RF discovery immediately. + */ + int (*pre_discover)(const struct nfc_nci_device *p_dev); + + /* + * (*close)() Closed the NFC controller. Should free all resources. + */ + int (*close)(const struct nfc_nci_device *p_dev); + + /* + * (*control_granted)() Grant HAL the exclusive control to send NCI commands. + * Called in response to HAL_REQUEST_CONTROL_EVT. + * Must only be called when there are no NCI commands pending. + * HAL_RELEASE_CONTROL_EVT will notify when HAL no longer needs exclusive control. + */ + int (*control_granted)(const struct nfc_nci_device *p_dev); + + /* + * (*power_cycle)() Restart controller by power cyle; + * HAL_OPEN_CPLT_EVT will notify when operation is complete. + */ + int (*power_cycle)(const struct nfc_nci_device *p_dev); +} nfc_nci_device_t; + +/* + * Convenience methods that the NFC stack can use to open + * and close an NCI device + */ +static inline int nfc_nci_open(const struct hw_module_t* module, + nfc_nci_device_t** dev) { + return module->methods->open(module, NFC_NCI_CONTROLLER, + (struct hw_device_t**) dev); +} + +static inline int nfc_nci_close(nfc_nci_device_t* dev) { + return dev->common.close(&dev->common); +} +/* + * End NFC NCI HAL + */ + +/* + * This is a limited NFC HAL for NXP PN544-based devices. + * This HAL as Android is moving to + * an NCI-based NFC stack. + * + * All NCI-based NFC controllers should use the NFC-NCI + * HAL instead. * Begin PN544 specific HAL */ +#define NFC_HARDWARE_MODULE_ID "nfc" + #define NFC_PN544_CONTROLLER "pn544" typedef struct nfc_module_t { diff --git a/modules/Android.mk b/modules/Android.mk index 3f410c1..faa8bb3 100644 --- a/modules/Android.mk +++ b/modules/Android.mk @@ -1,2 +1,2 @@ -hardware_modules := gralloc hwcomposer audio nfc local_time power usbaudio audio_remote_submix +hardware_modules := gralloc hwcomposer audio nfc nfc-nci local_time power usbaudio audio_remote_submix include $(call all-named-subdir-makefiles,$(hardware_modules)) diff --git a/modules/nfc-nci/Android.mk b/modules/nfc-nci/Android.mk new file mode 100644 index 0000000..97262ef --- /dev/null +++ b/modules/nfc-nci/Android.mk @@ -0,0 +1,25 @@ +# Copyright (C) 2011 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := nfc_nci.default +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_SRC_FILES := nfc_nci_example.c +LOCAL_SHARED_LIBRARIES := liblog libcutils +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/modules/nfc-nci/nfc_nci_example.c b/modules/nfc-nci/nfc_nci_example.c new file mode 100644 index 0000000..01914f0 --- /dev/null +++ b/modules/nfc-nci/nfc_nci_example.c @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include + +#include +#include +#include + + +/* + * NCI HAL method implementations. These must be overriden + */ +static int hal_open(const struct nfc_nci_device *dev, + nfc_stack_callback_t *p_cback) { + ALOGE("NFC-NCI HAL: %s", __FUNCTION__); + return 0; +} + +static int hal_write(const struct nfc_nci_device *dev, + uint16_t data_len, const uint8_t *p_data) { + ALOGE("NFC-NCI HAL: %s", __FUNCTION__); + return 0; +} + +static int hal_core_initialized(const struct nfc_nci_device *dev, + uint8_t* p_core_init_rsp_params) { + ALOGE("NFC-NCI HAL: %s", __FUNCTION__); + return 0; +} + +static int hal_pre_discover(const struct nfc_nci_device *dev) { + ALOGE("NFC-NCI HAL: %s", __FUNCTION__); + return 0; +} + +static int hal_close(const struct nfc_nci_device *dev) { + ALOGE("NFC-NCI HAL: %s", __FUNCTION__); + return 0; +} + +static int hal_control_granted (const struct nfc_nci_device *p_dev) +{ + ALOGE("NFC-NCI HAL: %s", __FUNCTION__); + return 0; +} + + +static int hal_power_cycle (const struct nfc_nci_device *p_dev) +{ + ALOGE("NFC-NCI HAL: %s", __FUNCTION__); + return 0; +} + +/* + * Generic device handling below - can generally be left unchanged. + */ +/* Close an opened nfc device instance */ +static int nfc_close(hw_device_t *dev) { + free(dev); + return 0; +} + +static int nfc_open(const hw_module_t* module, const char* name, + hw_device_t** device) { + if (strcmp(name, NFC_NCI_CONTROLLER) == 0) { + nfc_nci_device_t *dev = calloc(1, sizeof(nfc_nci_device_t)); + + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = 0x00010000; // [31:16] major, [15:0] minor + dev->common.module = (struct hw_module_t*) module; + dev->common.close = nfc_close; + + // NCI HAL method pointers + dev->open = hal_open; + dev->write = hal_write; + dev->core_initialized = hal_core_initialized; + dev->pre_discover = hal_pre_discover; + dev->close = hal_close; + dev->control_granted = hal_control_granted; + dev->power_cycle = hal_power_cycle; + + *device = (hw_device_t*) dev; + + return 0; + } else { + return -EINVAL; + } +} + + +static struct hw_module_methods_t nfc_module_methods = { + .open = nfc_open, +}; + +struct nfc_nci_module_t HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .module_api_version = 0x0100, // [15:8] major, [7:0] minor (1.0) + .hal_api_version = 0x00, // 0 is only valid value + .id = NFC_NCI_HARDWARE_MODULE_ID, + .name = "Default NFC NCI HW HAL", + .author = "The Android Open Source Project", + .methods = &nfc_module_methods, + }, +}; diff --git a/modules/nfc/Android.mk b/modules/nfc/Android.mk index d541b21..429fb43 100644 --- a/modules/nfc/Android.mk +++ b/modules/nfc/Android.mk @@ -18,7 +18,7 @@ include $(CLEAR_VARS) LOCAL_MODULE := nfc.default LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw -LOCAL_SRC_FILES := nfc_hw_example.c +LOCAL_SRC_FILES := nfc_pn544_example.c LOCAL_SHARED_LIBRARIES := liblog libcutils LOCAL_MODULE_TAGS := optional diff --git a/modules/nfc/nfc_hw_example.c b/modules/nfc/nfc_hw_example.c deleted file mode 100644 index 54c9c56..0000000 --- a/modules/nfc/nfc_hw_example.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include -#include - -#include -#include - -/* Close an opened pn544 device instance */ -static int pn544_close(hw_device_t *dev) { - free(dev); - return 0; -} - -/* - * Generic device handling - */ -static int nfc_open(const hw_module_t* module, const char* name, - hw_device_t** device) { - if (strcmp(name, NFC_PN544_CONTROLLER) == 0) { - nfc_pn544_device_t *dev = calloc(1, sizeof(nfc_pn544_device_t)); - - dev->common.tag = HARDWARE_DEVICE_TAG; - dev->common.version = 0; - dev->common.module = (struct hw_module_t*) module; - dev->common.close = pn544_close; - - /* Example settings */ - dev->num_eeprom_settings = 0; - dev->eeprom_settings = NULL; - dev->linktype = PN544_LINK_TYPE_INVALID; - dev->device_node = NULL; - dev->enable_i2c_workaround = 0; - dev->i2c_device_address = 0; - - *device = (hw_device_t*) dev; - return 0; - } else { - return -EINVAL; - } -} - - -static struct hw_module_methods_t nfc_module_methods = { - .open = nfc_open, -}; - -struct nfc_module_t HAL_MODULE_INFO_SYM = { - .common = { - .tag = HARDWARE_MODULE_TAG, - .version_major = 1, - .version_minor = 0, - .id = NFC_HARDWARE_MODULE_ID, - .name = "Default NFC HW HAL", - .author = "The Android Open Source Project", - .methods = &nfc_module_methods, - }, -}; diff --git a/modules/nfc/nfc_pn544_example.c b/modules/nfc/nfc_pn544_example.c new file mode 100644 index 0000000..54c9c56 --- /dev/null +++ b/modules/nfc/nfc_pn544_example.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include + +#include +#include + +/* Close an opened pn544 device instance */ +static int pn544_close(hw_device_t *dev) { + free(dev); + return 0; +} + +/* + * Generic device handling + */ +static int nfc_open(const hw_module_t* module, const char* name, + hw_device_t** device) { + if (strcmp(name, NFC_PN544_CONTROLLER) == 0) { + nfc_pn544_device_t *dev = calloc(1, sizeof(nfc_pn544_device_t)); + + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = 0; + dev->common.module = (struct hw_module_t*) module; + dev->common.close = pn544_close; + + /* Example settings */ + dev->num_eeprom_settings = 0; + dev->eeprom_settings = NULL; + dev->linktype = PN544_LINK_TYPE_INVALID; + dev->device_node = NULL; + dev->enable_i2c_workaround = 0; + dev->i2c_device_address = 0; + + *device = (hw_device_t*) dev; + return 0; + } else { + return -EINVAL; + } +} + + +static struct hw_module_methods_t nfc_module_methods = { + .open = nfc_open, +}; + +struct nfc_module_t HAL_MODULE_INFO_SYM = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .version_major = 1, + .version_minor = 0, + .id = NFC_HARDWARE_MODULE_ID, + .name = "Default NFC HW HAL", + .author = "The Android Open Source Project", + .methods = &nfc_module_methods, + }, +}; -- cgit v1.1