Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Gör följande för att konfigurera WIA-drivrutinen för att rapportera avbrottshändelser på rätt sätt:
Ange Capabilities=0x31 i enhetens INF-fil. (Mer information finns i INF-filer för WIA-enheter .)
Rapportera STI_GENCAP_NOTIFICATIONS och STI_USD_GENCAP_NATIVE_PUSHSUPPORT i metoden IStiUSD::GetCapabilities .
Rapportera alla händelser som stöds i metoden IWiaMiniDrv::d rvGetCapabilities .
Cachelagra och använd händelsehandtaget som skickades i metoden IStiUSD::SetNotificationHandle . Det här är händelsehandtaget som enheten signalerar, eller som WIA-minidrivern signalerar direkt med SetEvent (beskrivs i Microsoft Windows SDK-dokumentationen). Det är i den här metoden som du initierar väntetillståndet för WIA-enheten.
Rapportera rätt händelseinformationssvar i metoden IStiUSD::GetNotificationData .
Följande två exempel visar hur du konfigurerar enheten för avbrott med implementeringar av metoderna IWiaMiniDrv::d rvGetCapabilities och IStiUSD::SetNotificationHandle .
Notera Det är viktigt att använda överlappade I/O-anrop med alla aktiviteter som involverar kärnlägesdrivrutinerna. Detta ger rätt tidsgränser och annullering av enhetsbegäranden.
Förklaring av implementeringen av IWiaMiniDrv::drvGetCapabilities
WIA-tjänsten anropar metoden IWiaMiniDrv::drvGetCapabilities för att hämta WIA-enhetsstödda händelser och kommandon. WIA-drivrutinen bör först titta på den inkommande lFlags-parametern för att avgöra vilken begäran den ska besvara.
WIA-drivrutinen bör allokera minne (som ska användas av WIA-drivrutinen och frigöras av den) för att innehålla en matris med WIA_DEV_CAP_DRV strukturer. I anropet till IWiaMiniDrv::drvGetCapabilities skickar du en pekare till den minnesplats som innehåller adressen för WIA-drivrutinsallokerat minne i parametern ppCapabilities.
Not WIA-tjänsten frigör inte det här minnet. Det är viktigt att WIA-drivrutinen hanterar det allokerade minnet.
I följande exempel visas en implementering av metoden IWiaMiniDrv::d rvGetCapabilities .
HRESULT _stdcall CWIADevice::drvGetCapabilities(
BYTE *pWiasContext,
LONG lFlags,
LONG *pcelt,
WIA_DEV_CAP_DRV **ppCapabilities,
LONG *plDevErrVal)
{
//
// If the caller did not pass in the correct parameters,
// then fail the call and return E_INVALIDARG.
//
if (!pWiasContext) {
//
// The WIA service may pass in a NULL for the pWiasContext.
// This is expected because there is a case where no item
// was created at the time the event was fired.
//
}
if (!plDevErrVal) {
return E_INVALIDARG;
}
if (!pcelt) {
return E_INVALIDARG;
}
if (!ppCapabilities) {
return E_INVALIDARG;
}
*plDevErrVal = 0;
HRESULT hr = S_OK;
LONG lNumberOfCommands = 1;
LONG lNumberOfEvents = 2;
//
// initialize WIA driver capabilities ARRAY
// a member WIA_DEV_CAP_DRV m_Capabilities[3] variable
// This memory should live with the WIA minidriver.
// A pointer to this structure is given to the WIA service using
// ppCapabilities. Do not delete this memory until
// the WIA minidriver has been unloaded.
//
// This ARRAY should only be initialized once.
// The Descriptions and Names should be read from the proper
// string resource. These string values should be localized in
// multiple languages because an application will be use them to
// be displayed to the user.
//
// Command #1
m_Capabilities[0].wszDescription = L"Synchronize Command";
m_Capabilities[0].wszName = L"Synchronize";
m_Capabilities[0].guid = (GUID*)&WIA_CMD_SYNCHRONIZE;
m_Capabilities[0].lFlags = 0;
m_Capabilities[0].wszIcon = WIA_ICON_SYNCHRONIZE;
// Event #1
m_Capabilities[1].wszDescription = L"Scan Button";
m_Capabilities[1].wszName = L"Scan";
m_Capabilities[1].guid = (GUID*)&WIA_EVENT_SCAN_IMAGE;
m_Capabilities[1].lFlags = WIA_NOTIFICATION_EVENT | WIA_ACTION_EVENT;
m_Capabilities[1].wszIcon = WIA_ICON_SCAN_BUTTON_PRESS;
// Event #2
m_Capabilities[2].wszDescription = L"Copy Button";
m_Capabilities[2].wszName = L"Copy";
m_Capabilities[2].guid = (GUID*)&WIA_EVENT_SCAN_PRINT_IMAGE;
m_Capabilities[2].lFlags = WIA_NOTIFICATION_EVENT | WIA_ACTION_EVENT;
m_Capabilities[2].wszIcon = WIA_ICON_SCAN_BUTTON_PRESS;
//
// Return depends on flags. Flags specify whether we should return
// commands, events, or both.
//
//
switch (lFlags) {
case WIA_DEVICE_COMMANDS:
//
// report commands only
//
*pcelt = lNumberOfCommands;
*ppCapabilities = &m_Capabilities[0];
break;
case WIA_DEVICE_EVENTS:
//
// report events only
//
*pcelt = lNumberOfEvents;
*ppCapabilities = &m_Capabilities[1]; // start at the first event in the ARRAY
break;
case (WIA_DEVICE_COMMANDS | WIA_DEVICE_EVENTS):
//
// report both events and commands
//
*pcelt = (lNumberOfCommands + lNumberOfEvents);
*ppCapabilities = &m_Capabilities[0];
break;
default:
//
// invalid request
//
hr = E_INVALIDARG;
break;
}
return hr;
}
Metoden IStiUSD::SetNotificationHandle anropas av WIA-tjänsten eller internt av den här drivrutinen för att starta eller stoppa händelsemeddelanden. WIA-tjänsten skickar ett giltigt handtag som skapats med CreateEvent (beskrivs i Microsoft Windows SDK-dokumentationen) som anger att WIA-drivrutinen ska signalera den här handtaget när en händelse inträffar i maskinvaran.
NULL kan skickas till metoden IStiUSD::SetNotificationHandle . NULL anger att WIA-minidrivern ska stoppa all aktivitet på enheten och avsluta alla väntoperationer för händelser.
I följande exempel visas en implementering av metoden IStiUSD::SetNotificationHandle .
STDMETHODIMP CWIADevice::SetNotificationHandle(HANDLE hEvent)
{
HRESULT hr = S_OK;
if (hEvent && (hEvent != INVALID_HANDLE_VALUE)) {
//
// A valid handle indicates that we are asked to start our "wait"
// for device interrupt events
//
//
// reset last event GUID to GUID_NULL
//
m_guidLastEvent = GUID_NULL;
//
// clear EventOverlapped structure
//
memset(&m_EventOverlapped,0,sizeof(m_EventOverlapped));
//
// fill overlapped hEvent member with the event passed in by
// the WIA service. This handle will be automatically signaled
// when an event is triggered at the hardware level.
//
m_EventOverlapped.hEvent = hEvent;
//
// clear event data buffer. This is the buffer that will be used
// to determine what event was signaled from the device.
//
memset(m_EventData,0,sizeof(m_EventData));
//
// use the following call for interrupt events on your device
//
DWORD dwError = 0;
BOOL bResult = DeviceIoControl( m_hDeviceDataHandle,
IOCTL_WAIT_ON_DEVICE_EVENT,
NULL,
0,
&m_EventData,
sizeof(m_EventData),
&dwError,
&m_EventOverlapped );
if (bResult) {
hr = S_OK;
} else {
hr = HRESULT_FROM_WIN32(::GetLastError());
}
} else {
//
// stop any hardware waiting events here, the WIA service has
// notified us to stop all hardware event waiting
//
//
// Stop hardware interrupt events. This will stop all activity on
// the device. Since DeviceIOControl was used with OVERLAPPED i/o
// functionality the CancelIo() can be used to stop all kernel
// mode activity.
//
if(m_hDeviceDataHandle){
if(!CancelIo(m_hDeviceDataHandle)){
//
// canceling of the IO failed, call GetLastError() here to determine the cause.
//
LONG lError = ::GetLastError();
}
}
}
return hr;
}
När WIA-minimejeln eller en WIA-enhet har identifierat och signalerat en händelse anropar WIA-tjänsten metoden IStiUSD::GetNotificationData . Det är i denna metod som WIA-minidrivrutinen ska rapportera information om händelsen som inträffade.
WIA-tjänsten anropar metoden IStiUSD::GetNotificationData för att få information om en händelse som just har signalerats. Metoden IStiUSD::GetNotificationData kan anropas som ett resultat av en av två händelseåtgärder.
IStiUSD::GetStatus rapporterade att det var en väntande händelse genom att ange flaggan STI_EVENTHANDLING_PENDING i STI_DEVICE_STATUS-strukturen .
HEvent-referensen som skickades in av IStiUSD::SetNotificationHandle signalerades av maskinvaran eller genom att anropa SetEvent (beskrivs i Microsoft Windows SDK-dokumentationen).
WIA-drivrutinen ansvarar för att fylla i STINOTIFY-strukturen
I följande exempel visas en implementering av metoden IStiUSD::GetNotificationData .
STDMETHODIMP CWIADevice::GetNotificationData( LPSTINOTIFY pBuffer )
{
//
// If the caller did not pass in the correct parameters,
// then fail the call with E_INVALIDARG.
//
if(!pBuffer){
return E_INVALIDARG;
}
GUID guidEvent = GUID_NULL;
DWORD dwBytesRet = 0;
BOOL bResult = GetOverlappedResult(m_hDeviceDataHandle, &m_EventOverlapped, &dwBytesRet, FALSE );
if (bResult) {
//
// read the m_EventData buffer to determine the proper event.
// set guidEvent to the proper event GUID
// set guidEvent to GUID_NULL when an event has
// not happened that you are concerned with
//
if(m_EventData[0] == DEVICE_SCAN_BUTTON_PRESSED) {
guidEvent = WIA_EVENT_SCAN_IMAGE;
} else {
guidEvent = GUID_NULL;
}
}
//
// If the event was triggered, then fill in the STINOTIFY structure
// with the proper event information
//
if (guidEvent != GUID_NULL) {
memset(pBuffer,0,sizeof(STINOTIFY));
pBuffer->dwSize = sizeof(STINOTIFY);
pBuffer->guidNotificationCode = guidEvent;
} else {
return STIERR_NOEVENTS;
}
return S_OK;
}
Avbrottshändelser kan när som helst stoppas genom att NULL skickas som händelsehanterare. Minidrivrutinen bör tolka detta som en signal för att stoppa alla väntetillstånd på hårdvaruenheten.
Metoden IWiaMiniDrv::d rvNotifyPnpEvent kan ta emot energisparhändelser som påverkar händelseväntetillståndet.
WIA-tjänsten anropar metoden IWiaMiniDrv::d rvNotifyPnpEvent och skickar en WIA_EVENT_POWER_SUSPEND händelse när systemet ska försätts i viloläge. Om det här anropet inträffar kanske enheten redan är ur sitt väntetillstånd. Sömnlägen utlöser automatiskt kernellägesdrivrutiner för att avsluta väntetillståndet så att systemet kan gå in i detta avstängda tillstånd. När systemet återupptas från sitt viloläge skickar WIA-tjänsten händelsen WIA_EVENT_POWER_RESUME. För närvarande måste WIA-minidriver återupprätta väntetillståndet för avbrottshändelse. Mer information om vilolägen finns i System Power States and Device Power States (System Power States and Device Power States).
Vi rekommenderar att WIA-minidrivrutinen cachelagrar händelsehandtaget som inledningsvis skickades till IStiUSD::SetNotificationHandle-metoden så att det kan återanvändas när systemet vaknar från viloläge eller internvila.
WIA-tjänsten anropar inte metoden IStiUSD::SetNotificationHandle när systemet har återupptagits. Vi rekommenderar att minidrivrutinen anropar sin IStiUSD::SetNotificationHandle-metod genom att skicka det cachelagrade händelsehandtaget.
WIA-tjänsten anropar metoden IWiaMiniDrv::d rvNotifyPnpEvent när systemhändelser inträffar. WIA-drivrutinen bör kontrollera pEventGUID-parametern för att avgöra vilken händelse som bearbetas.
Några vanliga händelser som måste bearbetas är:
WIA_EVENT_POWER_SUSPEND
Systemet försätts i paus-/viloläge.
WIA_EVENT_POWER_RESUME
Systemet vaknar upp från paus-/viloläge.
WIA-drivrutinen ska återställa alla väntetillstånd för händelseavbrott efter att ha återvänt från ett uppehåll. Detta säkerställer att händelserna fortfarande fungerar när systemet aktiveras.
I följande exempel visas en implementering av metoden IWiaMiniDrv::d rvNotifyPnpEvent .
HRESULT _stdcall CWIADevice::drvNotifyPnpEvent(
const GUID *pEventGUID,
BSTR bstrDeviceID,
ULONG ulReserved)
{
//
// If the caller did not pass in the correct parameters,
// then fail the call with E_INVALIDARG.
//
if ((!pEventGUID)||(!bstrDeviceID)) {
return E_INVALIDARG;
}
HRESULT hr = S_OK;
if(*pEventGUID == WIA_EVENT_POWER_SUSPEND) {
//
// disable any driver activity to make sure we properly
// shut down (the driver is not being unloaded, just disabled)
//
} else if(*pEventGUID == WIA_EVENT_POWER_RESUME) {
//
// reestablish any event notifications to make sure we properly
// set up any event waiting status using the WIA service supplied
// event handle
//
if(m_EventOverlapped.hEvent) {
//
// call ourselves with the cached EVENT handle given to
// the WIA driver by the WIA service.
//
SetNotificationHandle(m_EventOverlapped.hEvent);
}
}
return hr;
}