Hi Damjan,
Damjan Jovanovic wrote:
I've started working on implementing STI functionality in Wine. STI is a Windows 98/2000 "Still Image" capture system, and I'm doing it to get my scanner working in Linux.
Fantastic!
- STI has kernel mode components to deal USB / SCSI /
serial / parallel ports. Is there any attempt to bring kernel mode support into Wine (ReactOS/Wine merger?) any time soon? If not, should I implement USB support using libusb in user-space?
I think that STI support should be done using the Video4Linux API and/or the SANE library. You shouldn't need to think about whether a device is a USB device, attached to a parallel port, serial port or anything like that. Let the kernel deal with abstraction of the hardware if possible... can the Linux kernel already talk to your scanner?
- Either way, changes need to be made to
CreateFile(), CloseHandle(), DeviceIoControl(), ReadFile() and WriteFile() to accomodate this. What's the best way to do this? Do I need to change the Wine server, or just Wine's KERNEL32.DLL and/or NT*.DLL equivalents?
I don't think you should try to implement scanner support at the driver level. The first step is to figure out how your device accesses the scanner, and write a test program that uses the same interface, and can read a simple image from it in Windows. AFAIK, STI devices are accessed though sti.StiCreateInstanceA/W() which returns an IStillImageA/W interface.
- Anyone wanna help out?
Sure. I'm willing to help you build a frame for you to build your code in. I've attached an IDL file for STI that I created a while back. I don't think it compiles any more, but I should be able to fix it up and get it submitted.
Mike
/* * Copyright (C) 2004 Mike McCormack * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
import "oaidl.idl";
/* encoding neutral interfaces */ /*struct STIDEVICE; typedef struct STIDEVICE* PSTIDEVICE ; struct IStillImage; struct STI; typedef struct STI *PSTI;
struct STI_DEVICE_INFORMATIONW; struct STIDEVICEW;
typedef struct IStillImageW IStillImageW,*PSTIW; typedef struct STIDEVICEW* PSTIDEVICEW; typedef struct STI_DEVICE_INFORMATIONW *PSTI_DEVICE_INFORMATIONW;
struct STIDEVICEA;
typedef struct IStillImageA IStillImageA,*PSTIA; typedef struct STIDEVICEA* PSTIDEVICEA; typedef struct STI_DEVICE_INFORMATIONA *PSTI_DEVICE_INFORMATIONA;
HRESULT WINAPI StiCreateInstanceA(HINSTANCE hinst, DWORD ver, PSTIA *ppSti, void **punk); HRESULT WINAPI StiCreateInstanceW(HINSTANCE hinst, DWORD ver, PSTIW *ppSti, void **punk); */
typedef struct _STI_DEV_CAPS { DWORD dwGeneric; } STI_DEV_CAPS, *PSTI_DEV_CAPS;
typedef struct _STI_DEVICE_STATUS { DWORD dwSize; DWORD StatusMask; DWORD dwOnlineState; DWORD dwHardwareStatusCode; DWORD dwEventHandlingState; DWORD dwPollingInterval; } STI_DEVICE_STATUS, *PSTI_DEVICE_STATUS;
typedef struct _ERROR_INFOA { DWORD dwSize; DWORD dwGenericError; DWORD dwVendorError; CHAR szExtendedErrorText[255]; } STI_ERROR_INFOA, *PSTI_ERROR_INFOA;
typedef struct _ERROR_INFOW { DWORD dwSize; DWORD dwGenericError; DWORD dwVendorError; WCHAR szExtendedErrorText[255]; } STI_ERROR_INFOW, *PSTI_ERROR_INFOW;
typedef struct _STI_DIAGA { DWORD dwSize; DWORD dwBasicDiagCode; DWORD dwVendorDiagCode; DWORD dwStatusMask; STI_ERROR_INFOA sErrorInfo; } STI_DIAGA, *LPSTI_DIAGA;
typedef struct _STI_DIAGW { DWORD dwSize; DWORD dwBasicDiagCode; DWORD dwVendorDiagCode; DWORD dwStatusMask; STI_ERROR_INFOW sErrorInfo; } STI_DIAGW, *LPSTI_DIAGW;
[ object, uuid(6CFA5A80-2DC8-11D0-90EA-00AA0060F86C), pointer_default(unique) ] interface IStiDevice : IUnknown { HRESULT Initialize(HINSTANCE hinst, LPCWSTR pwszDeviceName, DWORD dwVersion, DWORD dwMode); HRESULT GetCapabilities(PSTI_DEV_CAPS pDevCaps); HRESULT GetStatus(PSTI_DEVICE_STATUS pDevStatus); HRESULT DeviceReset(); HRESULT Diagnostic(LPSTI_DIAG pBuffer); HRESULT Escape(STI_RAW_CONTROL EscapeFunction, LPVOID lpInData, DWORD cbInDataSize, LPVOID pOutData, DWORD dwOutDataSize, LPDWORD pdwActualData); HRESULT GetLastError(LPDWORD pdwLastDeviceError); HRESULT LockDevice(DWORD dwTimeOut); HRESULT UnLockDevice(); HRESULT RawReadData(LPVOID lpBuffer, LPDWORD lpdwNumberOfBytes, LPOVERLAPPED lpOverlapped); HRESULT RawWriteData(LPVOID lpBuffer, DWORD nNumberOfBytes, LPOVERLAPPED lpOverlapped); HRESULT RawReadCommand(LPVOID lpBuffer, LPDWORD lpdwNumberOfBytes, LPOVERLAPPED lpOverlapped); HRESULT RawWriteCommand(LPVOID lpBuffer, DWORD nNumberOfBytes, LPOVERLAPPED lpOverlapped); HRESULT Subscribe(LPSTISUBSCRIBE lpSubscribe); HRESULT GetLastNotificationData(LPSTINOTIFY lpNotify); HRESULT UnSubscribe(); HRESULT GetLastErrorInfo(STI_ERROR_INFO *pLastErrorInfo); }
/***************************************************************************** * IStillImageW */ [ object, uuid(641BD880-2DC8-11D0-90EA-00AA0060F86C), pointer_default(unique) ] interface IStillImageW : IUnknown { HRESULT Initialize(HINSTANCE hinst, DWORD dwVersion); HRESULT GetDeviceList(DWORD dwType, DWORD dwFlags, DWORD *pdwItemsReturned, LPVOID* ppBuffer); HRESULT GetDeviceInfo(LPWSTR pwszDeviceName, LPVOID* ppBuffer); HRESULT CreateDevice(LPWSTR pwszDeviceName, DWORD dwMode, PSTIDEVICE* pDevice, LPUNKNOWN* punkOuter); HRESULT GetDeviceValue(LPWSTR pwszDeviceName, LPWSTR pValueName, LPDWORD pType, LPBYTE pData, LPDWORD cbData); HRESULT SetDeviceValue(LPWSTR pwszDeviceName, LPWSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData); HRESULT GetSTILaunchInformation(LPWSTR pwszDeviceName, LPDWORD pdwEventCode, LPWSTR pwszEventName); HRESULT RegisterLaunchApplication(LPWSTR pwszAppName, LPWSTR pwszCommandLine); HRESULT UnregisterLaunchApplication(LPWSTR pwszAppName); HRESULT EnableHwNotifications(LPCWSTR pwszDeviceName, BOOL bNewState); HRESULT GetHwNotificationState(LPCWSTR pwszDeviceName, BOOL* pbCurrentState); HRESULT RefreshDeviceBus(LPCWSTR pwszDeviceName); HRESULT LaunchApplicationForDevice(LPWSTR pwszDeviceName, LPWSTR pwszAppName, LPSTINOTIFY pStiNotify); HRESULT SetupDeviceParameters(PSTI_DEVICE_INFORMATIONW); HRESULT WriteToErrorLog(DWORD dwMessageType, LPCWSTR pszMessage); }
/***************************************************************************** * IStillImageA */ [ object, uuid(A7B1F740-1D7F-11D1-ACA9-00A02438AD48), pointer_default(unique) ] interface IStillImageA : IUnknown { HRESULT Initialize(HINSTANCE hinst, DWORD dwVersion); HRESULT GetDeviceList(DWORD dwType, DWORD dwFlags, DWORD *pdwItemsReturned, LPVOID* ppBuffer); HRESULT GetDeviceInfo(LPSTR pwszDeviceName, LPVOID* ppBuffer); HRESULT CreateDevice(LPSTR pwszDeviceName, DWORD dwMode, PSTIDEVICE* pDevice, LPUNKNOWN* punkOuter); HRESULT GetDeviceValue(LPSTR pwszDeviceName, LPSTR pValueName, LPDWORD pType, LPBYTE pData, LPDWORD cbData); HRESULT SetDeviceValue(LPSTR pwszDeviceName, LPSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData); HRESULT GetSTILaunchInformation(LPSTR pwszDeviceName, LPDWORD pdwEventCode, LPSTR pwszEventName); HRESULT RegisterLaunchApplication(LPSTR pwszAppName, LPSTR pwszCommandLine); HRESULT UnregisterLaunchApplication(LPSTR pwszAppName); HRESULT EnableHwNotifications(LPCSTR pwszDeviceName, BOOL bNewState); HRESULT GetHwNotificationState(LPCSTR pwszDeviceName, BOOL* pbCurrentState); HRESULT RefreshDeviceBus(LPWSTR pwszDeviceName); HRESULT LaunchApplicationForDevice(LPSTR pwszDeviceName, LPSTR pwszAppName, LPSTINOTIFY pStiNotify); HRESULT SetupDeviceParameters(PSTI_DEVICE_INFORMATIONA); HRESULT WriteToErrorLog(DWORD dwMessageType, LPCSTR pszMessage); }