class="hide-preCode-box">
  1. 实例化MIPI CSI控制器对象

完成驱动入口注册之后,最后一步就是以核心层MipiCsiCntlr对象的初始化为核心,实现HdfDriverEntry成员函数(Bind,Init,Release)。

MipiCsiCntlr对象的初始化包括驱动适配者自定义结构体(用于传递参数和数据)和实例化MipiCsiCntlr成员MipiCsiCntlrMethod(让用户可以通过接口来调用驱动底层函数)。

从驱动的角度看,自定义结构体是参数和数据的载体,一般来说,config文件中的数值也会用来初始化结构体成员,本例的mipicsi器件属性在源文件中,故基本成员结构与MipiCsiCntlr无太大差异。

        typedef struct {
            // 数据类型:8/10/12/14/16位
            DataType inputDataType;
            // MIPI波分复用模式
            MipiWdrMode wdrMode;
            // laneId: -1 - 禁用 
            short laneId[MIPI_LANE_NUM];

            union {
                // 用于 HI_MIPI_WDR_MODE_DT
                short dataType[WDR_VC_NUM];
            };
        } MipiDevAttr;

        typedef struct {
            // 设备号
            uint8_t devno;
            // 输入模式: MIPI/LVDS/SUBLVDS/HISPI/DC
            InputMode inputMode;
            MipiDataRate dataRate;
            // MIPI Rx设备裁剪区域(与原始传感器输入图像大小相对应)
            ImgRect imgRect;

            union {
                MipiDevAttr mipiAttr;
                LvdsDevAttr lvdsAttr;
            };
        } ComboDevAttr;

        // MipiCsiCntlr是核心层控制器结构体,其中的成员在Init函数中会被赋值。
        struct MipiCsiCntlr {
            // 当驱动程序绑定到HDF框架时,将发送此控制器提供的服务。
            struct IDeviceIoService service;
            // 当驱动程序绑定到HDF框架时,将传入设备端指针。
            struct HdfDeviceObject *device;
            // 设备号
            unsigned int devNo;
            // 控制器提供的所有接口
            struct MipiCsiCntlrMethod *ops;
            // 对于控制器调试的所有接口,如果未实现驱动程序,则需要null。
            struct MipiCsiCntlrDebugMethod *debugs;
            // 控制器上下文参数变量
            MipiDevCtx ctx;
            // 访问控制器上下文参数变量时锁定
            OsalSpinlock ctxLock;
            // 操作控制器时锁定方法
            struct OsalMutex lock;
            // 匿名数据指针,用于存储csi设备结构。
            void *priv;
        };
        c
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">

说明:
其他成员在Init函数中初始化。

        static struct MipiCsiCntlrMethod g_method = {
            .setComboDevAttr = Hi35xxSetComboDevAttr,
            .setPhyCmvmode = Hi35xxSetPhyCmvmode,
            .setExtDataType = Hi35xxSetExtDataType,
            .setHsMode = Hi35xxSetHsMode,
            .enableClock = Hi35xxEnableClock,
            .disableClock = Hi35xxDisableClock,
            .resetRx = Hi35xxResetRx,
            .unresetRx = Hi35xxUnresetRx,
            .enableSensorClock = Hi35xxEnableSensorClock,
            .disableSensorClock = Hi35xxDisableSensorClock,
            .resetSensor = Hi35xxResetSensor,
            .unresetSensor = Hi35xxUnresetSensor
        };
        c
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

入参:

HdfDeviceObject是整个驱动对外暴露的接口参数,具备HCS配置文件的信息。

返回值:

HDF_STATUS相关状态 (表3为部分展示,如需使用其他状态,可参考//drivers/hdf_core/interfaces/inner_api/utils/hdf_base.h中HDF_STATUS的定义)。

表 3 HDF_STATUS相关状态说明

class="table-box">
状态(值)问题描述
HDF_ERR_INVALID_OBJECT控制器对象非法
HDF_ERR_MALLOC_FAIL内存分配失败
HDF_ERR_IOI/O 错误
HDF_SUCCESS初始化成功
HDF_FAILURE初始化失败

函数说明:

MipiCsiCntlrMethod的实例化对象的挂载,调用MipiCsiRegisterCntlr,以及其他驱动适配者自定义初始化操作。

        static int32_t Hi35xxMipiCsiInit(struct HdfDeviceObject *device)
        {
            int32_t ret;

            HDF_LOGI("%s: enter!", __func__);
            g_mipiCsi.priv = NULL;                             // g_mipiTx是定义的全局变量
                                                               // static struct MipiCsiCntlr g_mipiCsi = {
                                                               //     .devNo = 0
                                                               // };
            g_mipiCsi.ops = &g_method;                         // MipiCsiCntlrMethod的实例化对象的挂载
        #ifdef CONFIG_HI_PROC_SHOW_SUPPORT
            g_mipiCsi.debugs = &g_debugMethod;
        #endif
            ret = MipiCsiRegisterCntlr(&g_mipiCsi, device);    // 【必要】调用核心层函数和g_mipiTx初始化核心层全局变量
            if (ret != HDF_SUCCESS) {
                HDF_LOGE("%s: [MipiCsiRegisterCntlr] failed!", __func__);
                return ret;
            }

            ret = MipiRxDrvInit();                             // 【必要】驱动适配者对设备的初始化,形式不限。
            if (ret != HDF_SUCCESS) {
                HDF_LOGE("%s: [MipiRxDrvInit] failed.", __func__);
                return ret;
            }
        #ifdef MIPICSI_VFS_SUPPORT
            ret = MipiCsiDevModuleInit(g_mipiCsi.devNo);
            if (ret != HDF_SUCCESS) {
                HDF_LOGE("%s: [MipiCsiDevModuleInit] failed!", __func__);
                return ret;
            }
        #endif

            OsalSpinInit(&g_mipiCsi.ctxLock);
            HDF_LOGI("%s: load mipi csi driver success!", __func__);

            return ret;
        }

        // mipi_csi_core.c核心层
        int32_t MipiCsiRegisterCntlr(struct MipiCsiCntlr *cntlr, struct HdfDeviceObject *device)
        {
            ......
            // 定义的全局变量:static struct MipiCsiHandle g_mipiCsihandle[MAX_CNTLR_CNT];
            if (g_mipiCsihandle[cntlr->devNo].cntlr == NULL) {
                (void)OsalMutexInit(&g_mipiCsihandle[cntlr->devNo].lock);
                (void)OsalMutexInit(&(cntlr->lock));

                g_mipiCsihandle[cntlr->devNo].cntlr = cntlr;   // 初始化MipiCsiHandle成员
                g_mipiCsihandle[cntlr->devNo].priv = NULL;
                cntlr->device = device;                        // 使HdfDeviceObject与MipiCsiHandle可以相互转化的前提
                device->service = &(cntlr->service);           // 使HdfDeviceObject与MipiCsiHandle可以相互转化的前提
                cntlr->priv = NULL;
                HDF_LOGI("%s: success.", __func__);

                return HDF_SUCCESS;
            }

            HDF_LOGE("%s: cntlr already exists.", __func__);
            return HDF_FAILURE;
        }
        c
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">

入参:

HdfDeviceObject是整个驱动对外暴露的接口参数,具备HCS配置文件的信息。

返回值:

函数说明:

该函数需要在驱动入口结构体中赋值给Release接口,当HDF框架调用Init函数初始化驱动失败时,可以调用Release释放驱动资源,该函数中需包含释放内存和删除控制器等操作。

说明:
所有强制转换获取相应对象的操作前提是在Init函数中具备对应赋值的操作。

        static void Hi35xxMipiCsiRelease(struct HdfDeviceObject *device)
        {
            struct MipiCsiCntlr *cntlr = NULL;
            ......
            cntlr = MipiCsiCntlrFromDevice(device);     // 这里有HdfDeviceObject到MipiCsiCntlr的强制转化
                                                        // return (device == NULL) ? NULL : (struct MipiCsiCntlr *)device->service;
            ......

            OsalSpinDestroy(&cntlr->ctxLock);
        #ifdef MIPICSI_VFS_SUPPORT
            MipiCsiDevModuleExit(cntlr->devNo);
        #endif
            MipiRxDrvExit();                            // 【必要】对设备所占资源的释放
            MipiCsiUnregisterCntlr(&g_mipiCsi);         // 空函数
            g_mipiCsi.priv = NULL;

            HDF_LOGI("%s: unload mipi csi driver success!", __func__);
        }
        c
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">
  1. 驱动调试

【可选】针对新增驱动程序,建议验证驱动基本功能,例如挂载后的信息反馈。

如果大家想更加深入的学习 OpenHarmony(鸿蒙南向) 开发的全栈内容,不妨可以参考以下相关学习文档进行学习,助你快速提升自己:

OpenHarmony 开发环境搭建:https://qr18.cn/CgxrRy

《OpenHarmony源码解析》:https://qr18.cn/CgxrRy

系统架构分析:https://qr18.cn/CgxrRy

OpenHarmony 设备开发学习手册:https://qr18.cn/CgxrRy

在这里插入图片描述

OpenHarmony面试题(内含参考答案):https://qr18.cn/CgxrRy

写在最后

data-report-view="{"mod":"1585297308_001","spm":"1001.2101.3001.6548","dest":"https://blog.csdn.net/maniuT/article/details/141026071","extend1":"pc","ab":"new"}">> id="blogExtensionBox" style="width:400px;margin:auto;margin-top:12px" class="blog-extension-box"> class="blog_extension blog_extension_type2" id="blog_extension"> class="extension_official" data-report-click="{"spm":"1001.2101.3001.6471"}" data-report-view="{"spm":"1001.2101.3001.6471"}"> class="blog_extension_card_left"> class="blog_extension_card_cont"> 鸿蒙开发学习资料领取!!! class="blog_extension_card_cont_r"> 微信名片
注:本文转载自blog.csdn.net的沧海一笑-dj的文章"https://blog.csdn.net/dengjin20104042056/article/details/99411418"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接

评论记录:

未查询到任何数据!