GPIO設備文件的實現

基於UNIX一切皆文件的哲學,SylixOS中也會把GPIO抽象爲設備文件,即/dev/gpiofd 目錄下的數字編號的文件,應用層通過訪問設備文件的方式即可操作GPIO。

實現這些函數要用到的主要接口有:

設備文件驅動接口
GPIO Drv接口
select接口
中斷系統接口

註冊驅動和設備

/*********************************************************************************************************
  驅動程序全局變量
*********************************************************************************************************/
static INT              _G_iGpiofdDrvNum = PX_ERROR;
static LW_GPIOFD_DEV    _G_gpiofddev;
static LW_OBJECT_HANDLE _G_hGpiofdSelMutex;
/*********************************************************************************************************
** 函數名稱: API_GpiofdDrvInstall
** 功能描述: 安裝 gpiofd 設備驅動程序
** 輸 入  : NONE
** 輸 出  : 驅動是否安裝成功
*********************************************************************************************************/
LW_API  
INT  API_GpiofdDrvInstall (VOID)
{
    if (_G_iGpiofdDrvNum <= 0) {
        _G_iGpiofdDrvNum  = iosDrvInstall(LW_NULL,
                                          LW_NULL,
                                          _gpiofdOpen,
                                          _gpiofdClose,
                                          _gpiofdRead,
                                          _gpiofdWrite,
                                          _gpiofdIoctl);
        DRIVER_LICENSE(_G_iGpiofdDrvNum,     "GPL->Ver 2.0");
        DRIVER_AUTHOR(_G_iGpiofdDrvNum,      "Han.hui");
        DRIVER_DESCRIPTION(_G_iGpiofdDrvNum, "gpiofd driver.");
    }
    
    if (_G_hGpiofdSelMutex == LW_OBJECT_HANDLE_INVALID) {
        _G_hGpiofdSelMutex =  API_SemaphoreMCreate("gpiofdsel_lock", 
                                                   LW_PRIO_DEF_CEILING, 
                                                   LW_OPTION_WAIT_PRIORITY | LW_OPTION_DELETE_SAFE |
                                                   LW_OPTION_INHERIT_PRIORITY | LW_OPTION_OBJECT_GLOBAL,
                                                   LW_NULL);
    }
    
    return  ((_G_iGpiofdDrvNum == (PX_ERROR)) ? (PX_ERROR) : (ERROR_NONE));
}
/*********************************************************************************************************
** 函數名稱: API_GpiofdDevCreate
** 功能描述: 安裝 gpiofd 設備
** 輸 入  : NONE
** 輸 出  : 設備是否創建成功
*********************************************************************************************************/
LW_API  
INT  API_GpiofdDevCreate (VOID)
{
    if (_G_iGpiofdDrvNum <= 0) {
        _DebugHandle(__ERRORMESSAGE_LEVEL, "no driver.\r\n");
        _ErrorHandle(ERROR_IO_NO_DRIVER);
        return  (PX_ERROR);
    }
    
    if (iosDevAddEx(&_G_gpiofddev.GD_devhdrHdr,
                    LW_GPIOFD_DEV_PATH, 
                    _G_iGpiofdDrvNum, 
                    DT_DIR) != ERROR_NONE) {
        return  (PX_ERROR);
    }
    
    return  (ERROR_NONE);
}
  • API_GpiofdDrvInstall 函數會註冊一個gpiofd driver驅動,驅動中需要實現5個底層的標準文件操作函數。
  • API_GpiofdDevCreate 函數會註冊一個/dev/gpiofd設備文件夾,訪問該文件夾時會調用gpiofd driver驅動。
  • 系統會自動調用上面兩個函數,此時文件系統中就已經具備/dev/gpiofd設備文件夾,但要訪問這個文件夾還是要必須實現驅動中回調的那5個底層的標準文件操作函數。

實現標準回調函數

_gpiofdOpen, _gpiofdClose, _gpiofdRead,_gpiofdWrite, _gpiofdIoctl 這5個回調函數是實現虛擬文件系統驅動所必須的,其接口參數也是標準的。

/*********************************************************************************************************
** 函數名稱: _gpiofdOpen
** 功能描述: 打開 gpiofd 設備
** 輸 入  : pgpiofddev       gpiofd 設備
**           pcName           名稱
**           iFlags           方式
**           iMode            方法
** 輸 出  : ERROR
*********************************************************************************************************/
static LONG  _gpiofdOpen (PLW_GPIOFD_DEV pgpiofddev, 
                          PCHAR          pcName,
                          INT            iFlags, 
                          INT            iMode)
{
#define GPIO_IS_ROOT(gpio)  ((gpio) == __ARCH_UINT_MAX)

    PLW_GPIOFD_FILE  pgpiofdfil;
    UINT             uiGpio;
    PCHAR            pcTemp;
    ULONG            ulGpioLibFlags;

    if (pcName == LW_NULL) {
        _DebugHandle(__ERRORMESSAGE_LEVEL, "device name invalidate.\r\n");
        _ErrorHandle(ERROR_IO_NO_DEVICE_NAME_IN_PATH);
        return  (PX_ERROR);
    
    } else {
        if (iFlags & O_CREAT) {
            _ErrorHandle(ERROR_IO_FILE_EXIST);
            return  (PX_ERROR);
        }
        
        if (*pcName == PX_DIVIDER) {
            pcName++;
        }
        
        for (pcTemp = pcName; *pcTemp != PX_EOS; pcTemp++) {
            if (!lib_isdigit(*pcTemp)) {
                _ErrorHandle(ENOENT);
                return  (PX_ERROR);
            }
        }
        
        if (pcName[0] == PX_EOS) {
            uiGpio = __ARCH_UINT_MAX;
        
        } else {
            uiGpio = lib_atoi(pcName);
            if (API_GpioRequest(uiGpio, "gpiofd")) {
                return  (PX_ERROR);
            }
        }
        
        pgpiofdfil = (PLW_GPIOFD_FILE)__SHEAP_ALLOC(sizeof(LW_GPIOFD_FILE));
        if (!pgpiofdfil) {
            _DebugHandle(__ERRORMESSAGE_LEVEL, "system low memory.\r\n");
            _ErrorHandle(ERROR_SYSTEM_LOW_MEMORY);
            return  (PX_ERROR);
        }
        
        pgpiofdfil->GF_iFlag  = iFlags;
        pgpiofdfil->GF_uiGpio = uiGpio;
        pgpiofdfil->GF_ulIrq  = LW_VECTOR_INVALID;
        
        API_GpioGetFlags(pgpiofdfil->GF_uiGpio, &ulGpioLibFlags);
        
        if (ulGpioLibFlags & LW_GPIODF_IS_OUT) {
            pgpiofdfil->GF_iGpioFlags = GPIO_FLAG_DIR_OUT;
        } else {
            pgpiofdfil->GF_iGpioFlags = GPIO_FLAG_DIR_IN;
        }
        
        if (ulGpioLibFlags & LW_GPIODF_TRIG_FALL) {
            pgpiofdfil->GF_iGpioFlags |= GPIO_FLAG_TRIG_FALL;
        }
        
        if (ulGpioLibFlags & LW_GPIODF_TRIG_RISE) {
            pgpiofdfil->GF_iGpioFlags |= GPIO_FLAG_TRIG_RISE;
        }
        
        if (ulGpioLibFlags & LW_GPIODF_TRIG_LEVEL) {
            pgpiofdfil->GF_iGpioFlags |= GPIO_FLAG_TRIG_LEVEL;
        }
        
        if (ulGpioLibFlags & LW_GPIODF_OPEN_DRAIN) {
            pgpiofdfil->GF_iGpioFlags |= GPIO_FLAG_OPEN_DRAIN;
        }
        
        if (ulGpioLibFlags & LW_GPIODF_OPEN_SOURCE) {
            pgpiofdfil->GF_iGpioFlags |= GPIO_FLAG_OPEN_SOURCE;
        }
        
        lib_bzero(&pgpiofdfil->GF_selwulist, sizeof(LW_SEL_WAKEUPLIST));
        pgpiofdfil->GF_selwulist.SELWUL_hListLock = _G_hGpiofdSelMutex;
        
        LW_DEV_INC_USE_COUNT(&_G_gpiofddev.GD_devhdrHdr);
        
        return  ((LONG)pgpiofdfil);
    }
}
/*********************************************************************************************************
** 函數名稱: _gpiofdClose
** 功能描述: 關閉 gpiofd 文件
** 輸 入  : pgpiofdfil        gpiofd 文件
** 輸 出  : ERROR
*********************************************************************************************************/
static INT  _gpiofdClose (PLW_GPIOFD_FILE  pgpiofdfil)
{
    if (pgpiofdfil) {
        SEL_WAKE_UP_TERM(&pgpiofdfil->GF_selwulist);
        
        LW_DEV_DEC_USE_COUNT(&_G_gpiofddev.GD_devhdrHdr);
        
        if (!GPIO_IS_ROOT(pgpiofdfil->GF_uiGpio)) {
            API_GpioFree(pgpiofdfil->GF_uiGpio);
            
            if (pgpiofdfil->GF_ulIrq != LW_VECTOR_INVALID) {
                API_InterVectorDisableEx(pgpiofdfil->GF_ulIrq, 1);
                API_InterVectorDisconnect(pgpiofdfil->GF_ulIrq, (PINT_SVR_ROUTINE)_gpiofdIsr,
                                          (PVOID)pgpiofdfil);
            }
        }
        
        __SHEAP_FREE(pgpiofdfil);
        
        return  (ERROR_NONE);
    
    } else {
        return  (PX_ERROR);
    }
}
/*********************************************************************************************************
** 函數名稱: _gpiofdRead
** 功能描述: 讀 gpiofd 設備
** 輸 入  : pgpiofdfil       gpiofd 文件
**           pcBuffer         接收緩衝區
**           stMaxBytes       接收緩衝區大小
** 輸 出  : 讀取字節數
*********************************************************************************************************/
static ssize_t  _gpiofdRead (PLW_GPIOFD_FILE pgpiofdfil, 
                             PCHAR           pcBuffer, 
                             size_t          stMaxBytes)
{
    INT  iValue;

    if (!pcBuffer) {
        _ErrorHandle(EINVAL);
        return  (PX_ERROR);
    }
    
    if (!stMaxBytes) {
        return  (0);
    }

    if (GPIO_IS_ROOT(pgpiofdfil->GF_uiGpio)) {
        _ErrorHandle(EISDIR);
        return  (PX_ERROR);
    }

    iValue = API_GpioGetValue(pgpiofdfil->GF_uiGpio);
    if (iValue < 0) {
        return  (iValue);
    }
    
    *pcBuffer = (CHAR)iValue;
    return  (1);
}
/*********************************************************************************************************
** 函數名稱: _gpiofdWrite
** 功能描述: 寫 gpiofd 設備
** 輸 入  : pgpiofdfil       gpiofd 文件
**           pcBuffer         將要寫入的數據指針
**           stNBytes         寫入數據大小
** 輸 出  : 寫入字節數
*********************************************************************************************************/
static ssize_t  _gpiofdWrite (PLW_GPIOFD_FILE pgpiofdfil, 
                              PCHAR           pcBuffer, 
                              size_t          stNBytes)
{
    if (!pcBuffer) {
        _ErrorHandle(EINVAL);
        return  (PX_ERROR);
    }
    
    if (!stNBytes) {
        return  (0);
    }

    if (GPIO_IS_ROOT(pgpiofdfil->GF_uiGpio)) {
        _ErrorHandle(EISDIR);
        return  (PX_ERROR);
    }
    
    API_GpioSetValue(pgpiofdfil->GF_uiGpio, *pcBuffer);
    return  (1);
}
/*********************************************************************************************************
** 函數名稱: _gpiofdIoctl
** 功能描述: 控制 gpiofd 文件
** 輸 入  : pgpiofdfil       gpiofd 文件
**           iRequest         功能
**           lArg             參數
** 輸 出  : ERROR
*********************************************************************************************************/
static INT  _gpiofdIoctl (PLW_GPIOFD_FILE pgpiofdfil, 
                          INT             iRequest, 
                          LONG            lArg)
{
    struct stat         *pstatGet;
    struct statfs       *pstatfsGet;
    PLW_SEL_WAKEUPNODE   pselwunNode;
    
    switch (iRequest) {
    
    case FIONBIO:
        if (*(INT *)lArg) {
            pgpiofdfil->GF_iFlag |= O_NONBLOCK;
        } else {
            pgpiofdfil->GF_iFlag &= ~O_NONBLOCK;
        }
        break;
        
    case FIOFSTATGET:
        pstatGet = (struct stat *)lArg;
        if (pstatGet) {
            pstatGet->st_dev = LW_DEV_MAKE_STDEV(&_G_gpiofddev.GD_devhdrHdr);
            if (GPIO_IS_ROOT(pgpiofdfil->GF_uiGpio)) {
                pstatGet->st_ino  = (ino_t)0;
                pstatGet->st_mode = 0666 | S_IFDIR;
                pstatGet->st_size = 0;
                pstatGet->st_blksize = 1;
                pstatGet->st_blocks  = 0;
            
            } else {
                pstatGet->st_ino  = (ino_t)pgpiofdfil->GF_uiGpio;
                pstatGet->st_mode = 0666 | S_IFCHR;
                pstatGet->st_size = 1;
                pstatGet->st_blksize = 1;
                pstatGet->st_blocks  = 1;
            }
            pstatGet->st_nlink    = 1;
            pstatGet->st_uid      = 0;
            pstatGet->st_gid      = 0;
            pstatGet->st_rdev     = 1;
            pstatGet->st_atime    = API_RootFsTime(LW_NULL);
            pstatGet->st_mtime    = API_RootFsTime(LW_NULL);
            pstatGet->st_ctime    = API_RootFsTime(LW_NULL);
        } else {
            _ErrorHandle(EINVAL);
            return  (PX_ERROR);
        }
        break;
        
    case FIOFSTATFSGET:
        pstatfsGet = (struct statfs *)lArg;
        if (pstatfsGet) {
            pstatfsGet->f_type   = 0;
            pstatfsGet->f_bsize  = 0;
            pstatfsGet->f_blocks = 1;
            pstatfsGet->f_bfree  = 0;
            pstatfsGet->f_bavail = 1;
            
            pstatfsGet->f_files  = LW_CFG_MAX_GPIOS;
            pstatfsGet->f_ffree  = 0;
            
#if LW_CFG_CPU_WORD_LENGHT == 64
            pstatfsGet->f_fsid.val[0] = (int32_t)((addr_t)&_G_gpiofddev >> 32);
            pstatfsGet->f_fsid.val[1] = (int32_t)((addr_t)&_G_gpiofddev & 0xffffffff);
#else
            pstatfsGet->f_fsid.val[0] = (int32_t)&_G_gpiofddev;
            pstatfsGet->f_fsid.val[1] = 0;
#endif
            
            pstatfsGet->f_flag    = 0;
            pstatfsGet->f_namelen = PATH_MAX;
        } else {
            _ErrorHandle(EINVAL);
            return  (PX_ERROR);
        }
        break;
        
    case FIOREADDIR:
        return  (_gpiofdReadDir(pgpiofdfil, (DIR *)lArg));
        
    case GPIO_CMD_SET_FLAGS:
        return  (_gpiofdSetFlags(pgpiofdfil, (INT)lArg));
        
    case GPIO_CMD_GET_FLAGS:
        return  (_gpiofdGetFlags(pgpiofdfil, (INT *)lArg));
        
    case FIOSELECT:
        pselwunNode = (PLW_SEL_WAKEUPNODE)lArg;
        return  (_gpiofdSelect(pgpiofdfil, pselwunNode));
        
    case FIOUNSELECT:
        pselwunNode = (PLW_SEL_WAKEUPNODE)lArg;
        return  (_gpiofdUnselect(pgpiofdfil, pselwunNode));
        
    case FIOFSTYPE:
        *(PCHAR *)lArg = "GPIO FileSystem";
        return  (ERROR_NONE);
    
    default:
        _ErrorHandle(ERROR_IO_UNKNOWN_REQUEST);
        return  (PX_ERROR);
    }
    
    return  (ERROR_NONE);
}

實現支撐函數

實現上面的標準回調函數時,還會調用一些支撐函數。

/*********************************************************************************************************
** 函數名稱: _gpiofdReadDir
** 功能描述: 讀 gpiofd 目錄
** 輸 入  : pgpiofdfil       gpiofd 文件
**           pdir             當前偏移量上的文件信息
** 輸 出  : ERROR
*********************************************************************************************************/
static INT  _gpiofdReadDir (PLW_GPIOFD_FILE pgpiofdfil, DIR  *pdir)
{
    if (!pdir) {
        _ErrorHandle(EINVAL);
        return  (PX_ERROR);
    }
    
    if (!GPIO_IS_ROOT(pgpiofdfil->GF_uiGpio)) {
        _ErrorHandle(ENOTDIR);
        return  (PX_ERROR);
    }
    
    while (pdir->dir_pos < LW_CFG_MAX_GPIOS) {
        if (API_GpioHasDrv((UINT)pdir->dir_pos)) {
            snprintf(pdir->dir_dirent.d_name, NAME_MAX + 1, "%ld", pdir->dir_pos);
            lib_strlcpy(pdir->dir_dirent.d_shortname, 
                        pdir->dir_dirent.d_name, 
                        sizeof(pdir->dir_dirent.d_shortname));
            pdir->dir_dirent.d_type = DT_CHR;
            pdir->dir_pos++;
            return  (ERROR_NONE);
        
        } else {
            pdir->dir_pos++;
        }
    }
    
    _ErrorHandle(ENOENT);
    return  (PX_ERROR);
}
/*********************************************************************************************************
** 函數名稱: _gpiofdIsr
** 功能描述: gpiofd 文件中斷服務程序
** 輸 入  : pgpiofdfil       gpiofd 文件
**           iFlags           gpiofd 屬性標誌
** 輸 出  : ERROR
*********************************************************************************************************/
static irqreturn_t  _gpiofdIsr (PLW_GPIOFD_FILE pgpiofdfil)
{
    irqreturn_t irqret;
    
    irqret = API_GpioSvrIrq(pgpiofdfil->GF_uiGpio);
    if (LW_IRQ_RETVAL(irqret)) {
        SEL_WAKE_UP_ALL(&pgpiofdfil->GF_selwulist, SELREAD);
        API_GpioClearIrq(pgpiofdfil->GF_uiGpio);
    }

    return  (irqret);
}
/*********************************************************************************************************
** 函數名稱: _gpiofdSetFlagsIrq
** 功能描述: 設置 gpiofd 文件中斷屬性標誌
** 輸 入  : pgpiofdfil       gpiofd 文件
**           iFlags           gpiofd 屬性標誌
** 輸 出  : ERROR
*********************************************************************************************************/
static INT  _gpiofdSetFlagsIrq (PLW_GPIOFD_FILE pgpiofdfil, INT  iFlags)
{
    BOOL   bIsLevel;
    UINT   uiType;
    ULONG  ulIrq;
    
    if (iFlags & GPIO_FLAG_TRIG_LEVEL) {
        bIsLevel = LW_TRUE;
    
    } else {
        bIsLevel = LW_FALSE;
    }
    
    if ((iFlags & GPIO_FLAG_IRQ_T2) == GPIO_FLAG_IRQ_T2) {
        uiType = 2;
    
    } else if ((iFlags & GPIO_FLAG_IRQ_T0) == GPIO_FLAG_IRQ_T0) {
        uiType = 0;
    
    } else if ((iFlags & GPIO_FLAG_IRQ_T1) == GPIO_FLAG_IRQ_T1) {
        uiType = 1;
    
    } else {
        _ErrorHandle(EINVAL);
        return  (PX_ERROR);
    }
    
    ulIrq = API_GpioGetIrq(pgpiofdfil->GF_uiGpio, bIsLevel, uiType);
    if (ulIrq == LW_VECTOR_INVALID) {
        return  (PX_ERROR);
    }
    
    API_InterVectorConnect(ulIrq, (PINT_SVR_ROUTINE)_gpiofdIsr,
                           (PVOID)pgpiofdfil, "gpiofd_isr");
    
    pgpiofdfil->GF_ulIrq = API_GpioSetupIrq(pgpiofdfil->GF_uiGpio, bIsLevel, uiType);
    if (pgpiofdfil->GF_ulIrq == LW_VECTOR_INVALID) {
        API_InterVectorDisconnect(pgpiofdfil->GF_ulIrq, 
                                  (PINT_SVR_ROUTINE)_gpiofdIsr, (PVOID)pgpiofdfil);
        return  (PX_ERROR);
    }
    
    API_InterVectorEnable(pgpiofdfil->GF_ulIrq);
    
    return  (ERROR_NONE);
}
/*********************************************************************************************************
** 函數名稱: _gpiofdSetFlagsOrg
** 功能描述: 設置 gpiofd 文件普通屬性標誌
** 輸 入  : pgpiofdfil       gpiofd 文件
**           iFlags           gpiofd 屬性標誌
** 輸 出  : ERROR
*********************************************************************************************************/
static INT  _gpiofdSetFlagsOrg (PLW_GPIOFD_FILE pgpiofdfil, INT  iFlags)
{
    if (iFlags & GPIO_FLAG_DIR_IN) {
        if (API_GpioDirectionInput(pgpiofdfil->GF_uiGpio) < 0) {
            return  (PX_ERROR);
        }
    
    } else {
        if (API_GpioDirectionOutput(pgpiofdfil->GF_uiGpio, 
                                    ((iFlags & GPIO_FLAG_INIT_HIGH) ? 1 : 0)) < 0) {
            return  (PX_ERROR);
        }
    }
    
    if (iFlags & GPIO_FLAG_OPEN_DRAIN) {
        API_GpioOpenDrain(pgpiofdfil->GF_uiGpio, LW_TRUE);
    
    } else {
        API_GpioOpenDrain(pgpiofdfil->GF_uiGpio, LW_FALSE);
    }
    
    if (iFlags & GPIO_FLAG_OPEN_SOURCE) {
        API_GpioOpenSource(pgpiofdfil->GF_uiGpio, LW_TRUE);
    
    } else {
        API_GpioOpenSource(pgpiofdfil->GF_uiGpio, LW_FALSE);
    }
    
    if (pgpiofdfil->GF_ulIrq != LW_VECTOR_INVALID) {
        API_InterVectorDisableEx(pgpiofdfil->GF_ulIrq, 1);
        API_InterVectorDisconnect(pgpiofdfil->GF_ulIrq, (PINT_SVR_ROUTINE)_gpiofdIsr, (PVOID)pgpiofdfil);
        pgpiofdfil->GF_ulIrq = LW_VECTOR_INVALID;
    }
    
    return  (ERROR_NONE);
}
/*********************************************************************************************************
** 函數名稱: _gpiofdSetFlags
** 功能描述: 設置 gpiofd 文件屬性標誌
** 輸 入  : pgpiofdfil       gpiofd 文件
**           iFlags           gpiofd 屬性標誌
** 輸 出  : ERROR
*********************************************************************************************************/
static INT  _gpiofdSetFlags (PLW_GPIOFD_FILE pgpiofdfil, INT  iFlags)
{
    INT  iError = ERROR_NONE;

    if (GPIO_IS_ROOT(pgpiofdfil->GF_uiGpio)) {
        _ErrorHandle(EISDIR);
        return  (PX_ERROR);
    }
    
    if (iFlags & GPIO_FLAG_PULL_UP) {
        iError = API_GpioSetPull(pgpiofdfil->GF_uiGpio, 1);
    
    } else if (iFlags & GPIO_FLAG_PULL_DOWN) {
        iError = API_GpioSetPull(pgpiofdfil->GF_uiGpio, 2);
    
    } else if (iFlags & GPIO_FLAG_PULL_DISABLE) {
        iError = API_GpioSetPull(pgpiofdfil->GF_uiGpio, 0);
    }
    
    if (iError < ERROR_NONE) {
        return  (PX_ERROR);
    }

    if (iFlags & GPIO_FLAG_IRQ) {
        iError = _gpiofdSetFlagsIrq(pgpiofdfil, iFlags);
    
    } else {
        iError = _gpiofdSetFlagsOrg(pgpiofdfil, iFlags);
    }
    
    if (iError == ERROR_NONE) {
        pgpiofdfil->GF_iGpioFlags = iFlags;
    }
    
    return  (iError);
}
/*********************************************************************************************************
** 函數名稱: _gpiofdGetFlags
** 功能描述: 獲取 gpiofd 文件屬性標誌
** 輸 入  : pgpiofdfil       gpiofd 文件
**           piFlags          gpiofd 屬性標誌
** 輸 出  : ERROR
*********************************************************************************************************/
static INT  _gpiofdGetFlags (PLW_GPIOFD_FILE pgpiofdfil, INT  *piFlags)
{
    if (GPIO_IS_ROOT(pgpiofdfil->GF_uiGpio)) {
        _ErrorHandle(EISDIR);
        return  (PX_ERROR);
    }
    
    if (piFlags) {
        *piFlags = pgpiofdfil->GF_iGpioFlags;
    }
    
    return  (ERROR_NONE);
}
/*********************************************************************************************************
** 函數名稱: _gpiofdSelect
** 功能描述: gpiofd FIOSELECT
** 輸 入  : pgpiofdfil       gpiofd 文件
**           pselwunNode      select 節點
** 輸 出  : ERROR
*********************************************************************************************************/
static INT  _gpiofdSelect (PLW_GPIOFD_FILE  pgpiofdfil, PLW_SEL_WAKEUPNODE   pselwunNode)
{
    if (GPIO_IS_ROOT(pgpiofdfil->GF_uiGpio)) {
        _ErrorHandle(EISDIR);
        return  (PX_ERROR);
    }
    
    SEL_WAKE_NODE_ADD(&pgpiofdfil->GF_selwulist, pselwunNode);
    
    switch (pselwunNode->SELWUN_seltypType) {
    
    case SELREAD:
        if (!(pgpiofdfil->GF_iGpioFlags & GPIO_FLAG_IRQ)) {
            SEL_WAKE_UP(pselwunNode);
        }
        break;
        
    case SELWRITE:
        SEL_WAKE_UP(pselwunNode);
        break;
        
    case SELEXCEPT:
        break;
    }
    
    return  (ERROR_NONE);
}
/*********************************************************************************************************
** 函數名稱: _gpiofdUnselect
** 功能描述: gpiofd FIOUNSELECT
** 輸 入  : pgpiofdfil       gpiofd 文件
**           pselwunNode      select 節點
** 輸 出  : ERROR
*********************************************************************************************************/
static INT  _gpiofdUnselect (PLW_GPIOFD_FILE  pgpiofdfil, PLW_SEL_WAKEUPNODE   pselwunNode)
{
    if (GPIO_IS_ROOT(pgpiofdfil->GF_uiGpio)) {
        _ErrorHandle(EISDIR);
        return  (PX_ERROR);
    }

    SEL_WAKE_NODE_DELETE(&pgpiofdfil->GF_selwulist, pselwunNode);
    return  (ERROR_NONE);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章