openharmony在标准系统上适配NFC驱动
一、背景说明 本文主要以标准系统上对NFC的驱动加载流程进行的通用介绍。以下是一种通用的驱动适配方法,在适配前先以小熊派芯片,在liteos上进行基本的nfc_example.c的功能使用,然后结合标准系统的驱动适配流程进行HDF层的适配说明,过程供参考。 二、适配思路 1、NFC组件服务架构图2、上层引用目录 /foundation/communication/nfc ├── interfa
一、背景说明
本文主要以标准系统上对NFC的驱动加载流程进行的通用介绍。以下是一种通用的驱动适配方法,在适配前先以小熊派芯片,在liteos上进行基本的nfc_example.c的功能使用,然后结合标准系统的驱动适配流程进行HDF层的适配说明,过程供参考。
二、适配思路
1、NFC组件服务架构图

2、上层引用目录
/foundation/communication/nfc ├── interfaces # 接口 │ └── inner_api # 系统内部件间接口 ├── frameworks # 框架层接口 │ └── js # JS API的实现 │ └── napi # 通过napi封装的JS接口代码实现 ├── services # NFC服务进程的实现 ├── test # 测试代码 ├── BUILD.gn # 编译入口 └── bundle.json # 部件描述文件
services中通过调用HDI接口,比如:
ErrCode NfcTagServiceImpl::WriteNdefTag(std::string data)
{
if (!PermissionTools::IsGranted(OHOS::NFC::TAG_PERMISSION)) {
HILOGE("NfcTagServiceImpl:WriteNdefTag() IsGranted failed!");
return NFC_FAILED;
}
if (NfcTagHdiAdapter::GetInstance().WriteNdefTag(data) == 0) {
return NFC_SUCCESS;
}
return NFC_FAILED;
}
3、驱动加载
1)先在.\drivers\hdf_core\framework\model下新建nfc/driver/src文件夹,添加nfc_driver.c,加载驱动
openharmony
|--------\drivers\hdf_core\framework\model\nfc\driver\src
|-------------------------------------------------------------└──nfc_driver.c
添加驱动加载:
static struct HdfDriverEntry g_nfcinterfaceDriverEntry = {
.moduleVersion = 1,
.moduleName = "nfc_driver",
.Bind = HdfNfcInterfaceDriverBind,
.Init = HdfNfcInterfaceDriverInit,
.Release = HdfNfcInterfaceDriverRelease,
};
通过HDF模块初始化:
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
HDF_INIT(g_nfcinterfaceDriverEntry);
#ifdef __cplusplus
}
添加基本的HdfNfcInterfaceDriverBind、HdfNfcInterfaceDriverInit、HdfNfcInterfaceDriverRelease接口实现:
struct HdfNfcInterfaceHost {
struct IDeviceIoService ioservice;
OHOS::sptr<OHOS::IRemoteObject> stub;
};////////---------------
//HdfNfcInterfaceDriverBind驱动服务绑定到HDF
static int HdfNfcInterfaceDriverBind(struct HdfDeviceObject *deviceObject)
{
HDF_LOGI("HdfNfcInterfaceDriverBind enter");
auto *hdfNfcInterfaceHost = new (std::nothrow) HdfNfcInterfaceHost;
if (hdfNfcInterfaceHost == nullptr) {
HDF_LOGE("HdfNfcInterfaceDriverBind, failed to create HdfNfcInterfaceDriverBind Object!");
return HDF_FAILURE;
}
hdfNfcInterfaceHost->ioservice.Dispatch = NfcInterfaceDriverDispatch;
hdfNfcInterfaceHost->ioservice.Open = nullptr;
hdfNfcInterfaceHost->ioservice.Release = nullptr;
auto serviceImpl = INfcInterface::Get(true);
if (serviceImpl == nullptr) {
HDF_LOGE("HdfNfcInterfaceDriverBind, failed to get of implement service");
delete hdfNfcInterfaceHost;
return HDF_FAILURE;
}
hdfNfcInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl,
INfcInterface::GetDescriptor());
if (hdfNfcInterfaceHost->stub == nullptr) {
HDF_LOGE("HdfNfcInterfaceDriverBind, failed to get stub object");
delete hdfNfcInterfaceHost;
return HDF_FAILURE;
}
deviceObject->service = &hdfNfcInterfaceHost->ioservice;
HDF_LOGI("HdfNfcInterfaceDriverBind Success");
return HDF_SUCCESS;
}
static int32_t NfcInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data,
struct HdfSBuf *reply)
{
auto *hdfNfcInterfaceHost =
CONTAINER_OF(client->device->service, struct HdfNfcInterfaceHost, ioservice);
OHOS::MessageParcel *dataParcel = nullptr;
OHOS::MessageParcel *replyParcel = nullptr;
OHOS::MessageOption option;
if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) {
HDF_LOGE("NfcInterfaceDriverDispatc, invalid data sbuf object to dispatch");
return HDF_ERR_INVALID_PARAM;
}
if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) {
HDF_LOGE("NfcInterfaceDriverDispatch, invalid reply sbuf object to dispatch");
return HDF_ERR_INVALID_PARAM;
}
return hdfNfcInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option);
}
//HdfNfcInterfaceDriverInit驱动初始化
static int HdfNfcInterfaceDriverInit(struct HdfDeviceObject *deviceObject)
{
HDF_LOGI("HdfNfcInterfaceDriverInit enter");
return HDF_SUCCESS;
}
//HdfNfcInterfaceDriverRelease
static void HdfNfcInterfaceDriverRelease(struct HdfDeviceObject *deviceObject)
{
HDF_LOGI("HdfNfcInterfaceDriverRelease enter");
if (deviceObject->service == nullptr) {
HDF_LOGE("HdfNfcInterfaceDriverRelease not initted");
return;
}
auto *hdfNfcInterfaceHost =
CONTAINER_OF(deviceObject->service, struct HdfNfcInterfaceHost, ioservice);
delete hdfNfcInterfaceHost;
HDF_LOGI("HdfNfcInterfaceDriverRelease Success");
}
2)同级目录添加接口引用文件
添加nfc_impl.h和对应的cpp文件,供接口调用
//nfc_impl.h
namespace OHOS {
namespace HDI {
namespace Nfc {
namespace V1_0 {
class NfcImpl : public INfcInterface {
public:
virtual ~NfcImpl() {}
int32_t Open(const sptr<INfcCallback> &callbackObj, NfcStatus &status) override;
int32_t CoreInitialized(const std::vector<uint8_t> &data, NfcStatus &status) override;
int32_t Prediscover(NfcStatus &status) override;
int32_t Write(const std::vector<uint8_t> &data, NfcStatus &status) override;
int32_t ControlGranted(NfcStatus &status) override;
int32_t PowerCycle(NfcStatus &status) override;
int32_t Close(NfcStatus &status) override;
int32_t Ioctl(NfcCommand cmd, const std::vector<uint8_t> &data, NfcStatus &status) override;
private:
NfcVendorAdaptions adaptor_;
};
} // V1_0
} // Nfc
} // HDI
} // OHOS
cpp接口实现:
//nfc_impl.cpp
namespace OHOS {
namespace HDI {
namespace Nfc {
namespace V1_0 {
static sptr<V1_0::INfcCallback> g_callbackV1_0 = nullptr;
static void EventCallback(unsigned char event, unsigned char status)
{
if (g_callbackV1_0 != nullptr) {
g_callbackV1_0->OnEvent((NfcEvent)event, (NfcStatus)status);
}
}
static void DataCallback(uint16_t len, uint8_t *data)
{
if (g_callbackV1_0 != nullptr) {
std::vector<uint8_t> vec(data, data + len / sizeof(uint8_t));
g_callbackV1_0->OnData(vec);
}
}
extern "C" INfcInterface *NfcInterfaceImplGetInstance(void)
{
using OHOS::HDI::Nfc::V1_0::NfcImpl;
NfcImpl *service = new (std::nothrow) NfcImpl();
if (service == nullptr) {
return nullptr;
}
return service;
}
int32_t NfcImpl::Open(const sptr<INfcCallback> &callbackObj, NfcStatus &status)
{
if (callbackObj == nullptr) {
HDF_LOGE("Open, callback is nullptr!");
return HDF_ERR_INVALID_PARAM;
}
g_callbackV1_0 = callbackObj;
int ret = adaptor_.VendorOpen(EventCallback, DataCallback);
if (ret == 0) {
status = NfcStatus::OK;
return HDF_SUCCESS;
}
status = NfcStatus::FAILED;
return HDF_FAILURE;
}
int32_t NfcImpl::CoreInitialized(const std::vector<uint8_t> &data, NfcStatus &status)
{
if (data.empty()) {
HDF_LOGE("CoreInitialized, data is nullptr!");
return HDF_ERR_INVALID_PARAM;
}
int ret = adaptor_.VendorCoreInitialized(data.size(), (uint8_t *)&data[0]);
if (ret == 0) {
status = NfcStatus::OK;
return HDF_SUCCESS;
}
status = NfcStatus::FAILED;
return HDF_FAILURE;
}
int32_t NfcImpl::Prediscover(NfcStatus &status)
{
int ret = adaptor_.VendorPrediscover();
if (ret == 0) {
status = NfcStatus::OK;
return HDF_SUCCESS;
}
status = NfcStatus::FAILED;
return HDF_FAILURE;
}
int32_t NfcImpl::Write(const std::vector<uint8_t> &data, NfcStatus &status)
{
if (data.empty()) {
HDF_LOGE("Write, data is nullptr!");
return HDF_ERR_INVALID_PARAM;
}
int ret = adaptor_.VendorWrite(data.size(), (uint8_t *)&data[0]);
if (ret == 0) {
status = NfcStatus::OK;
return HDF_SUCCESS;
}
status = NfcStatus::FAILED;
return HDF_FAILURE;
}
int32_t NfcImpl::ControlGranted(NfcStatus &status)
{
int ret = adaptor_.VendorControlGranted();
if (ret == 0) {
status = NfcStatus::OK;
return HDF_SUCCESS;
}
status = NfcStatus::FAILED;
return HDF_FAILURE;
}
int32_t NfcImpl::PowerCycle(NfcStatus &status)
{
int ret = adaptor_.VendorPowerCycle();
if (ret == 0) {
status = NfcStatus::OK;
return HDF_SUCCESS;
}
status = NfcStatus::FAILED;
return HDF_FAILURE;
}
int32_t NfcImpl::Close(NfcStatus &status)
{
g_callbackV1_0 = nullptr;
int ret = adaptor_.VendorClose(true);
if (ret == 0) {
status = NfcStatus::OK;
return HDF_SUCCESS;
}
status = NfcStatus::FAILED;
return HDF_FAILURE;
}
int32_t NfcImpl::Ioctl(NfcCommand cmd, const std::vector<uint8_t> &data, NfcStatus &status)
{
if (data.empty()) {
HDF_LOGE("Ioctl, data is nullptr!");
return HDF_ERR_INVALID_PARAM;
}
int ret = adaptor_.VendorIoctl(data.size(), (uint8_t *)&data[0]);
if (ret == 0) {
status = NfcStatus::OK;
return HDF_SUCCESS;
}
status = NfcStatus::FAILED;
return HDF_FAILURE;
}
} // V1_0
} // Nfc
} // HDI
} // OHOS
//该层对外接口也可不提供,直接在添加驱动时,进行接口调用。比如在HdfNfcInterfaceDriverInit驱动初始化时,先定义与驱动配置nfc_config.hcs中对应的结构g_nfcCfg,示例:
struct DeviceResourceIface *devIface = NULL;
devIface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
//获取驱动配置信息
if (devIface->GetUint32(deviceObject,"nfc_version",&g_nfcCfg.nfcVersion),0 != HDF_SUCCESS) {
g_nfcCfg.nfcVersion = 0;
HDF_LOGE("%s:Get nfc_version is fail!");
}
4、Mekefile及Kconfig文件编写
在.\drivers\hdf_core\adapter\khdf\linux\model目录下新建nfc文件夹,添加Kconfig文件
config DRIVERS_HDF_NFC bool "Enable HDF nfc driver" default n depends on DRIVERS_HDF help Answer Y to enable HDF nfc driver.
在上面nfc目录下添加Makefile文件
LIGHT_ROOT_DIR = ../../../../../../framework/model/nfc/driver obj-$(CONFIG_DRIVERS_HDF_NFC) += \ $(LIGHT_ROOT_DIR)/src/nfc_driver.o ccflags-y +=--I$(srctree)/drivers/hdf/framework/include/core \ -I$(srctree)/drivers/hdf/framework/core/common/include/host \ -I$(srctree)/drivers/hdf/framework/include/utils \ -I$(srctree)/drivers/hdf/framework/include/osal \ -I$(srctree)/drivers/hdf/framework/include/platform \ -I$(srctree)/drivers/hdf/framework/include/config \ -I$(srctree)/drivers/hdf/framework/core/host/include \ -I$(srctree)/drivers/hdf/framework/core/shared/include \ -I$(srctree)/drivers/hdf/framework/utils/include \ -I$(srctree)/drivers/hdf/khdf/osal/include \ -I$(srctree)/bounds_checking_function/include
将新建的Makefile及Kconfig添加到外层的对应文件中,路径如下:
//.\drivers\hdf_core\adapter\khdf\linux\Kconfig; source "drivers/hdf/khdf/model/nfc/Kconfig"
//.\drivers\hdf_core\adapter\khdf\linux\Makefile; obj-$(CONFIG_DRIVERS_HDF_NFC) += model/nfc/
5、配置硬件属性
//.\vendor\hihope\rk3568\hdf_config\khdf\device_info\device_info.hcs,示例供参考:
root {
device_info {
.........
.........
nfc :: host {
hostName = "nfc_host";
device_nfc :: device {
device0 :: deviceNode { //设备的某个具体节点配置信息
policy = 2; //驱动服务发布策略
priority = 100; //驱动启动优先级
permission = 0644; //驱动按需加载字段
moduleName = "nfc_driver"; //驱动名称,需和驱动入口的moduleName一致
serviceName = "nfc_service"; //驱动
deviceMatchAttr = "nfc_config"
}
}
}
.........
.........
}
}
6、配置私有属性
在.\vendor\hihope\rk3568\hdf_config\khdf目录下新建nfc文件夹,然后再nfc下添加nfc_config.hcs文件,添加私有属性。示例供参考:
root {
nfc_config {
match_attr = "nfc_config";//该字段必须和evice_info.hcs中deviceMatchAttr的值一致
nfc_version = 1.0;//版本信息
gpio_sda = 0;//复用I2C_SDA的管脚号
gpio_scl = 1;//复用I2C_SCL的管脚号
.........
.........
}
}
在hdf.hcs文件添加编译:
//.\vendor\hihope\rk3568\hdf_config\khdf\hdf.hcs #include "nfc/nfc_config.hcs"
7、参考资料
1、https://gitee.com/openharmony/vendor_hisilicon/tree/master/hispark_pegasus/demo/nfc_demo
2、https://gitee.com/openharmony/drivers_peripheral/tree/OpenHarmony-4.0-Beta1/connected_nfc_tag
更多推荐

所有评论(0)