⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 callback.c

📁 YLP270的Windows CE5.0 bsp源码。
💻 C
📖 第 1 页 / 共 3 页
字号:
PCALLBACK_STRUCT
CallbackType(
    CARD_EVENT MajorEvent,
    CARD_EVENT SubEvent,
    PCLIENT_DRIVER pReqClient,
    CARD_SOCKET_HANDLE hSock,
    UINT fFlags,
    UINT DriverType
    )
{
    PCLIENT_DRIVER pClient;
    PCALLBACK_STRUCT pLast;
    PCALLBACK_STRUCT pEvent;
    UINT8 StartFunction, EndFunction;

    pLast = NULL;

    //
    // Check if a notification is needed for all functions
    //
    if (fFlags & CALLBACK_FLAG_ALL_FUNCTIONS) {
        StartFunction = 0;
        EndFunction = v_Sockets[hSock.uSocket].cFunctions;
        //
        // If the user had previously disabled the PC card, we still want a
        // CE_CARD_REMOVAL message after standby.  This check covers that case.
        //
        if (EndFunction == 0) {
            EndFunction = 1;
        }
    } else {
        StartFunction = hSock.uFunction;
        EndFunction = hSock.uFunction + 1;
    }

    //
    // Callback all clients of the specified type.
    //
    EnterCriticalSection(&v_ClientCrit);
    pClient = (PCLIENT_DRIVER)v_ClientList.Flink;
    while (pClient != (PCLIENT_DRIVER)&v_ClientList) {
        if (pClient->Parms.fAttributes & DriverType) {
            for (hSock.uFunction = StartFunction;
                 hSock.uFunction < EndFunction;
                 hSock.uFunction++) {
                if (ShouldCallback(pClient, MajorEvent, SubEvent, hSock)) {
                    pEvent = alloc(sizeof(CALLBACK_STRUCT));
                    if (pEvent) {
                        pEvent->MajorEvent  = MajorEvent;
                        pEvent->SubEvent    = SubEvent;
                        pEvent->pReqClient  = (pReqClient == NULL) ? NULL : pReqClient->hClient;
                        pEvent->pDestClient = (pClient == NULL) ? NULL : pClient->hClient;
                        pEvent->hSock      = hSock;
                        pEvent->fFlags      = fFlags;
                        EnqueueEvent(pEvent);
                        pLast = pEvent;
                    }
                }
            }
        }
        pClient = (PCLIENT_DRIVER)pClient->List.Flink;
    }
    LeaveCriticalSection(&v_ClientCrit);
    return pLast;
}   // CallbackType


//
// Broadcast a card event message to all registered clients in the order
// specified by the PCMCIA standard.
//
STATUS
CallbackAll(
    CARD_EVENT MajorEvent,
    CARD_EVENT SubEvent,
    PCLIENT_DRIVER pReqClient,
    CARD_SOCKET_HANDLE hSock,
    UINT fFlags
    )
{
    UINT fDriverType;
    PCALLBACK_STRUCT pLast;
    PCALLBACK_STRUCT pCurr;

    pLast = NULL;

    //
    // The following for loop relies on the fact that CLIENT_ATTR_IO_DRIVER,
    // CLIENT_ATTR_MTD_DRIVER and CLIENT_ATTR_MEM_DRIVER are one right shift
    // different from each other.  This conveniently results in the PCMCIA
    // specified client type order for callbacks.
    //
    // NOTE: I/O driver clients were linked in reverse order by
    // CardRegisterClient
    //
    EnterCriticalSection(&v_CallbackCrit);
    for (fDriverType = CLIENT_ATTR_IO_DRIVER; fDriverType; fDriverType >>= 1) {
        if (pCurr = CallbackType(
                        MajorEvent,
                        SubEvent,
                        pReqClient,
                        hSock,
                        fFlags,
                        fDriverType)) {
            pLast = pCurr;
        }
    }
    if (pLast) {
        pLast->fFlags |= CALLBACK_FLAG_LAST;
    }
    LeaveCriticalSection(&v_CallbackCrit);
    if (pLast) {
        StartCallbacks();
    }
    return CERR_SUCCESS;
}   // CallbackAll


//
// Perform an insertion callback to a newly registered client
// for all sockets in the system.
//
STATUS
CallbackSockets(
    PCLIENT_DRIVER pClient
    )
{
    PLOG_SOCKET pLsock;
    PCALLBACK_STRUCT pEvent;
    PCALLBACK_STRUCT pLast;
    CARD_SOCKET_HANDLE hSock;
    int i;

    if (pClient->CallBackFn == NULL) {
        return CERR_SUCCESS;
    }

    pLast = NULL;

    //
    // If both of these options are clear, then don't send any callbacks.
    //
    if ((pClient->Parms.fAttributes &
        (CLIENT_ATTR_NOTIFY_SHARED|CLIENT_ATTR_NOTIFY_EXCLUSIVE)) == 0) {
        goto cbs_complete;
    }

    EnterCriticalSection(&v_CallbackCrit);
    //
    // See if this client wants any callbacks.  If so, then he gets a
    // CE_CARD_INSERTION for every socket/function available and then a
    // CE_REGISTRATION_COMPLETE.
    //
    EnterCriticalSection(&v_SocketCrit);
    for (i = 0; i < v_cSockets; i++) {
        if (IsCardInserted(i)) {
            for (pLsock = v_Sockets[i].pLsock; pLsock; pLsock = pLsock->Next) {
                pEvent = alloc(sizeof(CALLBACK_STRUCT));
                if (pEvent) {
                    pEvent->MajorEvent  = CE_REGISTRATION_COMPLETE;
                    pEvent->SubEvent    = CE_CARD_INSERTION;
                    pEvent->pDestClient = (pClient == NULL) ? NULL : pClient->hClient;
                    pEvent->pReqClient  = (pClient == NULL) ? NULL : pClient->hClient;
                    pEvent->hSock      = pLsock->hSock;
                    pEvent->fFlags      = 0;
                    EnqueueEvent(pEvent);
                    pLast = pEvent;
                }
            }
        }
    }
    LeaveCriticalSection(&v_SocketCrit);

    if (pLast) {
        pLast->fFlags |= CALLBACK_FLAG_LAST;
    }
    LeaveCriticalSection(&v_CallbackCrit);
    if (pLast) {
        StartCallbacks();
    }

cbs_complete:
    if (pLast == NULL) {
        hSock.uSocket = 0;
        hSock.uFunction = 0;
        //
        // If no insertion callbacks were made, then send CE_REGISTRATION_COMPLETE
        // otherwise CallbackThread will send a CE_REGISTRATION_COMPLETE after
        // the last CE_CARD_INSERTION message.
        //
        CallbackOne(
            CE_REGISTRATION_COMPLETE,
            CE_REGISTRATION_COMPLETE,
            pClient,
            hSock);
    }

    return CERR_SUCCESS;
}   // CallbackSockets


//
// Call client driver's status callback function in a protected manner.
//
// Returns the return code from the client driver.
// If an exception is taken, then CERR_SUCCESS is returned.
//
STATUS
CallClient(
    CLIENT_CALLBACK CallBackFn,
    CARD_EVENT Event,
    CARD_SOCKET_HANDLE hSock,
    PCARD_EVENT_PARMS pParms,
    PCLIENT_DRIVER pClient
    )
{
    STATUS status;

    DEBUGMSG(ZONE_CALLBACK, (TEXT("PCMCIA:CallClient entered\r\n")));

    status = CERR_SUCCESS;
    try {
        if (CallBackFn != NULL) {
            status = (CallBackFn)(Event, hSock, pParms);
        } else {
            DEBUGMSG(ZONE_CALLBACK, (TEXT("PCMCIA:CallClient - CallBackFn == NULL\r\n")));
        }
    } except (GetExceptionCode() == STATUS_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        DEBUGMSG(ZONE_CALLBACK|ZONE_WARNING,
            (TEXT("PCMCIA:CallClient: Client's callback hit an exception!\r\n")));
        if (IsValidClient(pClient))
            CardDeregisterClient(pClient->hClient);
    }
    DEBUGMSG(ZONE_CALLBACK, (TEXT("PCMCIA:CallClient done\r\n")));
    return status;
}   // CallClient

//
// Function to figure out whether to send a CE_PM_RESUME and send it when
// appropriate
//
void
CallbackPmResume(void)
{
    BOOL bPmResume;
    UINT uSocket;
    CARD_SOCKET_HANDLE hSock;

    bPmResume = TRUE;
    for (uSocket = 0; uSocket < (UINT8)v_cSockets; uSocket++) {
        if ((v_Sockets[uSocket].PowerState != POWER_ON) ||
            (v_Sockets[uSocket].fFlags & PHYS_SOCK_FLAG_RESUMING)) {
            bPmResume = FALSE;
            break;
        }
    }

    if (bPmResume) {
    //
    // At this point all the insertion notices have been queued for any
    // cards that were in the device after a resume. Now indicate a
    // CE_PM_RESUME which device.exe will use as a signal to notify the
    // filesystem that it's safe to do pc card I/O.
    //
        DEBUGMSG(ZONE_POWER, (TEXT("PCMCIA:CallbackPmResume sending CE_PM_RESUME\r\n")));
        hSock.uSocket = 0;
        hSock.uFunction = 0;
        CallbackAll(
            CE_PM_RESUME,
            CE_PM_RESUME,
            NULL,
            hSock,
            0);
    }
}   // CallbackPmResume


//
// CheckForUnload - look for a CE_CARDSERV_UNLOAD on socket
//

BOOL
CheckForUnload(
    UINT8 uSocket
    )
{
    BOOL bRet = FALSE;
    PCALLBACK_STRUCT pEvent, pPrev;

    EnterCriticalSection(&v_CallbackCrit);
    pPrev = NULL;
    for (pEvent = v_CallbackHead; pEvent != NULL; pEvent = pEvent->Next) {
        if (pEvent->MajorEvent == CE_CARDSERV_UNLOAD &&
            pEvent->hSock.uSocket == uSocket) {

            DEBUGMSG(ZONE_CALLBACK, (TEXT("CE_CARDSERV_LOAD/CE_CARDSERV_UNLOAD found on socket %d\r\n"), uSocket));

            // Dequeue and discard the CE_CARDSERV_UNLOAD
            if (pPrev != NULL) {
                pPrev->Next = pEvent->Next;
            } else {
                v_CallbackHead = pEvent->Next;
            }
            if (v_CallbackTail == pEvent) {
                v_CallbackTail = pPrev;
            }

            free(pEvent);

            // Signal that unload was found, so that CE_CARDSERV_LOAD can be aborted
            bRet = TRUE;
            break;
        }
        pPrev = pEvent;
    }
    LeaveCriticalSection(&v_CallbackCrit);

    return bRet;
}


//
// Callback Thread - pull CALLBACK_STRUCTs off the callback queue and callback
// the specified client.  Perform any special processing for multi-stage
// callback sequences.
//
UINT
CallbackThread(
    UINT Nothing
    )
{
    STATUS status;
    CARD_EVENT_PARMS Parms;
    PCALLBACK_STRUCT pEvent;
    BOOL fCallAll, bUnloadDriver;
    CARD_EVENT NextEvent;
    PDCARD_SOCKET_STATE State;
    PCLIENT_DRIVER pClient;
    PLOG_SOCKET pLsock;
    UINT i;

    
#ifdef DEBUG
    LPTSTR MajorName;
    LPTSTR SubName;
#endif

    DEBUGMSG(ZONE_CALLBACK,
        (TEXT("PCMCIA:CallbackThread: entered %d\r\n"), ++g_Reentry));

    while ((pEvent = DequeueEvent()) != NULL) {
        // Handle special operations (these don't involve real callbacks
        // but they need to be serialized on the callback thread).
        switch (pEvent->MajorEvent) {
            case CE_CARDSERV_LOAD:
                if (!(v_Sockets[pEvent->hSock.uSocket].fFlags & PHYS_SOCK_FLAG_RESETTING)) {
                    if (!CheckForUnload(pEvent->hSock.uSocket)) {
                        // allow PCMCIA CD signals to settle (and user time to fully insert card)
                        Sleep(750);
                        if (!CheckForUnload(pEvent->hSock.uSocket)) {
                            CardServLoadDriver(pEvent->hSock.uSocket);
                        }
                    }
                } else {
                    // Since CardServLoadDriver will not be doing insertion callbacks, do them here.
                    CallbackAll(CE_CARD_INSERTION, CE_CARD_INSERTION, NULL, pEvent->hSock, CALLBACK_FLAG_ALL_FUNCTIONS);
                }
                v_Sockets[pEvent->hSock.uSocket].fFlags &= ~PHYS_SOCK_FLAG_RESETTING;
                goto cbt_next1;
            case CE_CARDSERV_UNLOAD:
                bUnloadDriver = ((v_Sockets[pEvent->hSock.uSocket].pLsock == NULL) ||
                                 !(v_Sockets[pEvent->hSock.uSocket].fFlags & PHYS_SOCK_FLAG_RESUMING));

                // Check if all functions do not want to be unloaded
                if (!bUnloadDriver) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -