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

📄 callback.c

📁 YLP270的Windows CE5.0 bsp源码。
💻 C
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name:

    callback.c

Abstract:

    This file implements the PCMCIA model device driver client callback
    functions.  This is provided as a sample to platform writers and is
    expected to be able to be used without modification on most (if not
    all) hardware platforms.

Functions:

    FindEventName()
    EnqueueEvent()
    DequeueEvent()
    ShouldCallback()
    CallbackOne()
    CallbackType()
    CallbackAll()
    CallbackSockets()
    CallClient()
    CallbackThread()

Notes:


--*/

#include <windows.h>
#include <types.h>
#include <excpt.h>
#include <cardserv.h>
#include <sockserv.h>
#include <linklist.h>
#include <pcmcia.h>
#include <extern.h>

UINT CallbackThread(UINT Nothing);

#ifdef DEBUG
//
// Debug data and function for callback thread
//
#define LAST_EVENT_CODE ((CARD_EVENT) -1)

typedef struct _EVENT_NAME_TBL {
    CARD_EVENT EventCode;
    LPTSTR    pEventName;
} EVENT_NAME_TBL, *PEVENT_NAME_TBL;

//
// Table of callback event codes and their names.
// NOTE: The names with ! at the end are not expected.
//
EVENT_NAME_TBL v_EventNames[] = {
    { CE_BATTERY_DEAD,          TEXT("CE_BATTERY_DEAD") },
    { CE_BATTERY_LOW,           TEXT("CE_BATTERY_LOW") },
    { CE_CARD_LOCK,             TEXT("CE_CARD_LOCK") },
    { CE_CARD_READY,            TEXT("CE_CARD_READY") },
    { CE_CARD_REMOVAL,          TEXT("CE_CARD_REMOVAL") },
    { CE_CARD_UNLOCK,           TEXT("CE_CARD_UNLOCK") },
    { CE_EJECTION_COMPLETE,     TEXT("CE_EJECTION_COMPLETE!") },
    { CE_EJECTION_REQUEST,      TEXT("CE_EJECTION_REQUEST!") },
    { CE_INSERTION_COMPLETE,    TEXT("CE_INSERTION_COMPLETE!") },
    { CE_INSERTION_REQUEST,     TEXT("CE_INSERTION_REQUEST!") },
    { CE_PM_RESUME,             TEXT("CE_PM_RESUME") },
    { CE_PM_SUSPEND,            TEXT("CE_PM_SUSPEND!") },
    { CE_EXCLUSIVE_COMPLETE,    TEXT("CE_EXCLUSIVE_COMPLETE") },
    { CE_EXCLUSIVE_REQUEST,     TEXT("CE_EXCLUSIVE_REQUEST") },
    { CE_RESET_PHYSICAL,        TEXT("CE_RESET_PHYSICAL") },
    { CE_RESET_REQUEST,         TEXT("CE_RESET_REQUEST") },
    { CE_CARD_RESET,            TEXT("CE_CARD_RESET") },
    { CE_MTD_REQUEST,           TEXT("CE_MTD_REQUEST!") },
    { CE_CLIENT_INFO,           TEXT("CE_CLIENT_INFO!") },
    { CE_TIMER_EXPIRED,         TEXT("CE_TIMER_EXPIRED!") },
    { CE_SS_UPDATED,            TEXT("CE_SS_UPDATED!") },
    { CE_WRITE_PROTECT,         TEXT("CE_WRITE_PROTECT") },
    { CE_CARD_INSERTION,        TEXT("CE_CARD_INSERTION") },
    { CE_RESET_COMPLETE,        TEXT("CE_RESET_COMPLETE") },
    { CE_ERASE_COMPLETE,        TEXT("CE_ERASE_COMPLETE!") },
    { CE_REGISTRATION_COMPLETE, TEXT("CE_REGISTRATION_COMPLETE") },
    { CE_STATUS_CHANGE_INTERRUPT, TEXT("CE_STATUS_CHANGE_INTERRUPT") },
    { CE_CARDSERV_LOAD,         TEXT("CE_CARDSERV_LOAD") },
    { CE_CARDSERV_UNLOAD,       TEXT("CE_CARDSERV_UNLOAD") },
    { LAST_EVENT_CODE,          TEXT("Unknown Event!") },
};

LPTSTR
FindEventName(
    CARD_EVENT EventCode
    )
{
    PEVENT_NAME_TBL pEvent = v_EventNames;

    while (pEvent->EventCode != LAST_EVENT_CODE) {
        if (pEvent->EventCode == EventCode) {
            return pEvent->pEventName;
        }
        pEvent++;
    }
    return pEvent->pEventName;
}

DWORD g_Reentry;  // used to debug CallbackThread
#endif // DEBUG

//
// StartCallbacks - function to invoke the CallbackThread
//
VOID StartCallbacks(VOID)
{
    DEBUGCHK(v_CallbackEvent != NULL);
    SetEvent(v_CallbackEvent);
}


//
// Put a CALLBACK_STRUCT at the end of the callback queue.
//
VOID
EnqueueEvent(
    PCALLBACK_STRUCT pEvent
    )
{
    EnterCriticalSection(&v_CallbackCrit);

    pEvent->Next = NULL;

    //
    // Link the event structure at the tail of the list
    //
    if (v_CallbackTail == NULL) {    // empty list?
        v_CallbackHead = pEvent;
        v_CallbackTail = pEvent;
    } else {
        v_CallbackTail->Next = pEvent;
        v_CallbackTail = pEvent;
    }
    DEBUGMSG(ZONE_CALLBACK,
        (TEXT("PCMCIA:Enqueued %s for client 0x%x, socket %d, function %d\r\n"),
        FindEventName(pEvent->MajorEvent), pEvent->pDestClient,
        pEvent->hSock.uSocket, pEvent->hSock.uFunction));

    EnterCriticalSection(&v_BatteryCrit);
    if (v_hBatteryThread[pEvent->hSock.uSocket] != 0) {
        if (v_hGwesEvent == NULL ||
            WaitForSingleObject(v_hGwesEvent, INFINITE) != WAIT_OBJECT_0 ||
            (NULL == v_pfnPostThreadMessageW) || !v_pfnPostThreadMessageW(
            v_hBatteryThread[pEvent->hSock.uSocket],
            WM_QUIT, 0, 0)) {
            DEBUGMSG(ZONE_WARNING|ZONE_CALLBACK|ZONE_INIT,
                (TEXT("PCMCIA:EnqueueEvent:PostThreadMessage Failed (%d)\r\n"),
                    GetLastError()));
        }
        v_fBattery[pEvent->hSock.uSocket] = FALSE;
        v_hBatteryThread[pEvent->hSock.uSocket] = 0;
    }
    LeaveCriticalSection(&v_BatteryCrit);

    LeaveCriticalSection(&v_CallbackCrit);
}   // EnqueueEvent


//
// Remove the first CALLBACK_STRUCT from the callback queue
//
PCALLBACK_STRUCT
DequeueEvent(VOID)
{
    PCALLBACK_STRUCT pEvent;
    DWORD dwStatus;

    // wait for an event to arrive
    do {
        EnterCriticalSection(&v_CallbackCrit);
        pEvent = v_CallbackHead;
        LeaveCriticalSection(&v_CallbackCrit);
        if(pEvent == NULL) {
            dwStatus = WaitForSingleObject(v_CallbackEvent, INFINITE);
            DEBUGCHK(dwStatus == WAIT_OBJECT_0);
            dwStatus = dwStatus;        // avoid compiler warning about unused variable
        }
    } while(pEvent == NULL);

    EnterCriticalSection(&v_CallbackCrit);

    pEvent = v_CallbackHead;
    if (pEvent) {
        v_CallbackHead = pEvent->Next;
        if (v_CallbackHead == NULL) {
            v_CallbackTail = NULL;
        }
        DEBUGMSG(ZONE_CALLBACK,
            (TEXT("PCMCIA:Dequeued %s for client 0x%x, socket %d, function %d\r\n"),
            FindEventName(pEvent->MajorEvent), pEvent->pDestClient,
            pEvent->hSock.uSocket, pEvent->hSock.uFunction));
    }
#ifdef DEBUG
    if (v_CallbackHead == NULL) {
       if (v_CallbackTail != NULL) {
            DEBUGMSG(1|ZONE_ERROR|ZONE_CALLBACK,
                (TEXT("PCMCIA:v_CallbackHead=0 but v_CallbackTail = 0x%x\r\n"),
                v_CallbackTail));
       }
    }
    if (v_CallbackTail == NULL) {
       if (v_CallbackHead != NULL) {
            DEBUGMSG(1|ZONE_ERROR|ZONE_CALLBACK,
                (TEXT("PCMCIA:v_CallbackTail=0 but v_CallbackHead = 0x%x\r\n"),
                v_CallbackHead));
       }
    }
#endif

    LeaveCriticalSection(&v_CallbackCrit);

    return pEvent;
}   // DequeueEvent


//
// Check if the specified client wants this type of event.
//
// Return: TRUE  => client wants this callback
//         FALSE => don't callback client for this event
BOOL
ShouldCallback(
    PCLIENT_DRIVER pClient,
    CARD_EVENT MajorEvent,
    CARD_EVENT EventCode,
    CARD_SOCKET_HANDLE hSock
    )
{
    UINT    EventMask;
    PEVENT_ATTR pAttr;
    PCLIENT_SOCKET pCsock;
    PCALLBACK_STRUCT pEvent;

    if (pClient == NULL) {
        // This is an internal operation and does not generate a true callback.
        return TRUE;
    }

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

    pAttr = (PEVENT_ATTR)v_EventMap;
    EventMask = (UINT) -1;    // Default is that he gets it.

    //
    // Find the EventMask associated with this EventCode
    //
    while (pAttr->EventCode != (UINT16)-1) {
        if (pAttr->EventCode == EventCode) {
            EventMask = pAttr->EventMask;
            break;
        }
        pAttr++;
    }

    //
    // Check the socket specific eventmask
    //
    if ((pCsock = I_FindClientSocket(hSock, pClient)) != NULL) {

        //
        // Check the socket event mask - if we're dealing with a CE_PM_RESUME
        // (global event) try the global event mask as well
        //
        if (!(pCsock->fEventMask & EventMask) && EventCode != CE_PM_RESUME) {
            DEBUGMSG(ZONE_CALLBACK,
                (TEXT("PCMCIA:ShouldCallback - Client 0x%x doesn't want a %s event\r\n"),
                pClient->hClient, FindEventName(EventCode)));
            return FALSE;
        }
    }

    //
    // Check the global event mask
    //
    if (!(pClient->Parms.fEventMask & EventMask)) {
        DEBUGMSG(ZONE_CALLBACK,
            (TEXT("PCMCIA:ShouldCallback - Client 0x%x doesn't want a %s event\r\n"),
            pClient->hClient, FindEventName(EventCode)));
        return FALSE;
    }

    //
    // There should be at most only one CE_PM_RESUME per client.
    //
    EnterCriticalSection(&v_CallbackCrit);
    pEvent = v_CallbackHead;
    while (pEvent) {
        if ((EventCode == CE_PM_RESUME) &&
            (pEvent->MajorEvent == CE_PM_RESUME) &&
            (pEvent->pDestClient == pClient->hClient)) {
            LeaveCriticalSection(&v_CallbackCrit);
            DEBUGMSG(ZONE_CALLBACK,
              (TEXT("PCMCIA:ShouldCallback - Client already getting CE_PM_RESUME\r\n")));
            return FALSE;
        } else if ((pEvent->MajorEvent      == MajorEvent) &&
                   (pEvent->SubEvent        == EventCode) &&
                   (pEvent->hSock.uSocket   == hSock.uSocket) &&
                   (pEvent->hSock.uFunction == hSock.uFunction) &&
                   (pEvent->pReqClient      == ((pClient == NULL) ? NULL : pClient->hClient)) &&
                   (pEvent->pDestClient     == ((pClient == NULL) ? NULL : pClient->hClient))) {
            LeaveCriticalSection(&v_CallbackCrit);
            DEBUGMSG(ZONE_CALLBACK,
              (TEXT("PCMCIA:ShouldCallback - Stopped duplicate %s\r\n"),
              FindEventName(EventCode)));
            return FALSE;
        }
        pEvent = pEvent->Next;
    }
    LeaveCriticalSection(&v_CallbackCrit);

    return TRUE;
}   // ShouldCallback


//
// Allocate and queue a CALLBACK_STRUCT for the specified client.
//
PCALLBACK_STRUCT
CallbackOne(
    CARD_EVENT MajorEvent,
    CARD_EVENT SubEvent,
    PCLIENT_DRIVER pReqClient,
    CARD_SOCKET_HANDLE hSock
    )
{
    PCALLBACK_STRUCT pEvent;

    if (!ShouldCallback(pReqClient, MajorEvent, SubEvent, hSock)) {
        return NULL;
    }

    pEvent = alloc(sizeof(CALLBACK_STRUCT));
    if (pEvent) {
        pEvent->MajorEvent = MajorEvent;
        pEvent->SubEvent = SubEvent;
        pEvent->pDestClient = (pReqClient == NULL) ? NULL : pReqClient->hClient;
        pEvent->pReqClient = (pReqClient == NULL) ? NULL : pReqClient->hClient;
        pEvent->hSock = hSock;
        pEvent->fFlags = CALLBACK_FLAG_LAST;
        EnqueueEvent(pEvent);
        StartCallbacks();
        return pEvent;
    }
    return NULL;
}   // CallbackOne


//
// Callback all clients of the specified type.
//
// NOTE: The caller of this function must own v_CallbackCrit
//

⌨️ 快捷键说明

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