Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Aby prawidłowo skonfigurować sterownik WIA w celu zgłaszania zdarzeń przerwania, wykonaj następujące czynności:
Ustaw Capabilities=0x31 w pliku INF urządzenia. (Aby uzyskać szczegółowe informacje, zobacz pliki INF dla urządzeń WIA).
Raport STI_GENCAP_NOTIFICATIONS i STI_USD_GENCAP_NATIVE_PUSHSUPPORT w metodzie IStiUSD::GetCapabilities.
Zgłoś wszystkie obsługiwane zdarzenia w metodzie IWiaMiniDrv::drvGetCapabilities.
Buforuj i użyj dojścia zdarzeń przekazanego w metodzie IStiUSD::SetNotificationHandle. Jest to obsługa zdarzeń sygnałów urządzenia lub sygnałów minidriver WIA bezpośrednio przy użyciu SetEvent (opisanej w dokumentacji zestawu Microsoft Windows SDK). To w tej metodzie inicjujesz stan oczekiwania urządzenia WIA.
Zgłoś prawidłową odpowiedź na informacje o zdarzeniach w metodzie IStiUSD::GetNotificationData.
W poniższych dwóch przykładach przedstawiają konfigurowanie urządzenia dla przerwań z implementacjami metod IWiaMiniDrv::drvGetCapabilities oraz IStiUSD::SetNotificationHandle.
Uwaga Ważne jest, aby używać nakładających się wywołań we/wy ze wszystkimi działaniami obejmującymi sterowniki trybu jądra. Umożliwia to prawidłowe obsługiwanie limitów czasu i anulowanie żądań związanych z urządzeniami.
Wyjaśnienie implementacji IWiaMiniDrv::drvGetCapabilities
Usługa WIA wywołuje metodę IWiaMiniDrv::drvGetCapabilities, aby uzyskać zdarzenia i polecenia obsługiwane przez urządzenie WIA. Sterownik WIA powinien najpierw przyjrzeć się przychodzącemu parametru lFlags, aby określić, na które żądanie powinien odpowiedzieć.
Sterownik WIA powinien przydzielić pamięć (do użycia i zwolnienia przez sterownik WIA), aby zawierała tablicę struktur WIA_DEV_CAP_DRV. W wywołaniu IWiaMiniDrv::drvGetCapabilities, przekaż wskaźnik na lokalizację pamięci, która zawiera adres pamięci przydzielonej przez sterownik WIA, w parametrze ppCapabilities.
Uwaga usługa WIA nie zwolni tej pamięci. Ważne jest, aby sterownik WIA zarządza przydzieloną pamięcią.
Poniższy przykład przedstawia implementację metody IWiaMiniDrv::drvGetCapabilities.
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;
}
Metoda IStiUSD::SetNotificationHandle jest wywoływana przez usługę WIA lub wewnętrznie przez ten sterownik w celu uruchamiania lub zatrzymywania powiadomień o zdarzeniach. Usługa WIA przekaże prawidłowy uchwyt utworzony przy użyciu CreateEvent (opisanej w dokumentacji zestawu MICROSOFT Windows SDK), wskazując, że sterownik WIA ma zasygnalizować ten uchwyt, gdy wystąpi zdarzenie na sprzęcie.
NULL można przekazać do metody IStiUSD::SetNotificationHandle. null wskazuje, że minidriver WIA ma zatrzymać wszystkie działania urządzenia i zakończyć wszystkie operacje oczekiwania na zdarzenia.
Poniższy przykład przedstawia implementację metody 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;
}
Gdy minidriver WIA lub urządzenie WIA wykryło i zasygnalizowało zdarzenie, usługa WIA wywołuje metodę IStiUSD::GetNotificationData. W tej metodzie minidriver WIA powinien zgłosić szczegóły zdarzenia, które wystąpiło.
Usługa WIA wywołuje metodę IStiUSD::GetNotificationData, aby uzyskać informacje o zdarzeniu, które zostało właśnie zasygnalizowane. Metoda IStiUSD::GetNotificationData może być wywoływana w wyniku jednej z dwóch operacji zdarzenia.
IStiUSD::GetStatus poinformował, że wystąpiło zdarzenie oczekujące, ustawiając flagę STI_EVENTHANDLING_PENDING w strukturze STI_DEVICE_STATUS.
Dojście hEvent przekazane przez IStiUSD::SetNotificationHandle zostało zasygnalizowane przez sprzęt lub przez wywołanie SetEvent (opisane w dokumentacji zestawu Microsoft Windows SDK).
Sterownik WIA odpowiada za wypełnienie struktury STINOTIFY.
Poniższy przykład przedstawia implementację metody 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;
}
Zdarzenia przerwania można zatrzymać w dowolnym momencie, przekazując null jako dojście zdarzenia. Minidriver powinien interpretować to jako sygnał, aby zatrzymać wszystkie stany oczekiwania na urządzeniu sprzętowym.
Metoda IWiaMiniDrv::drvNotifyPnpEvent może odbierać zdarzenia zarządzania energią, które wpływają na stan oczekiwania zdarzenia.
Usługa WIA wywołuje metodę IWiaMiniDrv::drvNotifyPnpEvent i wysyła zdarzenie WIA_EVENT_POWER_SUSPEND, gdy system ma zostać umieszczony w stanie uśpienia. Jeśli to wywołanie wystąpi, urządzenie może już nie być w stanie oczekiwania. Stany uśpienia automatycznie wyzwalają sterowniki trybu jądra, aby opuścić dowolny stan oczekiwania i umożliwić systemowi przejście do tego stanu zredukowanego zużycia energii. Po wznowieniu działania systemu ze stanu uśpienia usługa WIA wysyła zdarzenie WIA_EVENT_POWER_RESUME. W tej chwili minidriver WIA musi przywrócić stan oczekiwania na zdarzenie przerwania. Aby uzyskać więcej informacji na temat stanów uśpienia, zobacz System Power States i Device Power States.
Zaleca się, aby minidriver WIA buforował dojście zdarzenia początkowo przekazane do metody IStiUSD::SetNotificationHandle, aby można było je ponownie użyć, gdy system wznawia działanie po uśpieniu lub hibernacji.
usługi WIA nie wywołać metody IStiUSD::SetNotificationHandle po wznowieniu systemu. Zaleca się, aby minidriver wywołał swoją metodę IStiUSD::SetNotificationHandle, przekazując zbuforowany uchwyt zdarzenia.
Usługa WIA wywołuje metodę IWiaMiniDrv::drvNotifyPnpEvent, gdy występują zdarzenia systemowe. Sterownik WIA powinien sprawdzić parametr pEventGUID, aby określić, które zdarzenie jest przetwarzane.
Niektóre typowe zdarzenia, które należy przetworzyć, to:
WIA_EVENT_POWER_SUSPEND
System przechodzi w tryb wstrzymania/uśpienia.
WIA_EVENT_POWER_RESUME
System budzi się z trybu wstrzymania/uśpienia.
Sterownik WIA powinien przywrócić wszystkie stany oczekiwania przerwania zdarzeń po powrocie z zawieszenia. Gwarantuje to, że zdarzenia będą wciąż funkcjonować po wznowieniu systemu.
Poniższy przykład przedstawia implementację metody IWiaMiniDrv::drvNotifyPnpEvent.
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;
}