Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Communications with Serial & USB Ports
Message
General information
Forum:
Visual FoxPro
Category:
Coding, syntax & commands
Environment versions
Visual FoxPro:
VFP 9 SP1
OS:
Windows XP SP2
Network:
Windows NT
Database:
MS SQL Server
Miscellaneous
Thread ID:
01143504
Message ID:
01176865
Views:
71
I was working on this not long ago but I haven't been able to take the time to work on it recently. I plan to though. If you get it working (reading from/writing to USB ports) I'd be interested. Here is where I left off:

CreateFile WriteFile ReadFile with USB Port Message #1162598

For accurate tests, you need a USB device that accepts data and sends data based on the data sent.

Also, I have some code which determines the devices on a system (I was muddling my way through it all and so the code is really a jamble and reflects my multiple attempts at different methods). I have more example code I will try to find later which may get you started (Unless someone has already worked this out?) NOTE: I was working specifically with a RW420 with a card reader attached so some of the ids are specific to that device. You will need to get the information for your specific device to use some of the methods.
CLEAR
CLOSE ALL
CLEAR ALL

IF !FILE('testusb.dbf')
	CREATE TABLE testusb (cvalue c(250))
ELSE
	USE testusb
ENDIF

*!*	#define IOCTL_USBPRINT_VENDOR_SET_COMMAND CTL_CODE(FILE_DEVICE_UNKNOWN,
*!*	                                                     14,
*!*	                                                     METHOD_BUFFERED,
*!*	                                                     FILE_ANY_ACCESS)
*#define IOCTL_USBPRINT_VENDOR_GET_COMMAND CTL_CODE(FILE_DEVICE_UNKNOWN,
 *                                                    15,
 *                                                    METHOD_BUFFERED,
 *                                                    FILE_ANY_ACCESS)
*CTL_CODE = DeviceType * 65536 + Function * 4 + Method + Access * 16384

#define FILE_DEVICE_UNKNOWN             0x00000022
#define METHOD_BUFFERED                 0
#define FILE_ANY_ACCESS                 0
#DEFINE GET_SERIAL_NUMBER               1575952
#DEFINE VENDOR_GET                      222964
#DEFINE VENDOR_SET                      222960

*Serial Number
*!*	24 * 65536 + 772 * 4 + 0 + 0 * 16384
*!*	24 * 65536 + 772 * 4
*!* (24*65536) + (772*4) 
*!*  1572864 + 3088
*!*	= 1575952, or 0x00180C10

*Vendor Get Command
*!*	34 * 65536 + 15 * 4 + 0 + 0 * 16384
*!*	34 * 65536 + 15 * 4
*!* (34*65536) + (15*4) 
*!*  222904 + 60
*!*	= 222964, or 0x00366F4

*Vendor Set Command
*!*	34 * 65536 + 14 * 4 + 0 + 0 * 16384
*!*	34 * 65536 + 14 * 4
*!* (34*65536) + (14*4) 
*!*  222904 + 56
*!*	= 222960, or 0x00366F0


CLEAR
*#DEFINE IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER   0x0304
*CTL_CODE(IOCTL_STORAGE_BASE, 0x0304, METHOD_BUFFERED, FILE_ANY_ACCESS)
*#define CTL_CODE( DeviceType, Function, Method, Access ) (                 \
*    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \

#DEFINE GENERIC_READ                0x80000000
#DEFINE GENERIC_WRITE               0x40000000
#DEFINE FILE_SHARE_READ             1			&& 0x00000001
#DEFINE FILE_SHARE_WRITE            2			&& 0x00000002
#DEFINE OPEN_ALWAYS                 4
#DEFINE OPEN_EXISTING               3
#DEFINE CREATE_ALWAYS               2
#DEFINE CREATE_NEW                  1
#DEFINE TRUNCATE_EXISTING           5
#DEFINE FILE_ATTRIBUTE_NORMAL       0x80	&&  0x00000080
#DEFINE FILE_FLAG_SEQUENTIAL_SCAN   0x08000000  
#DEFINE FILE_FLAG_OVERLAPPED        0x40000000
#DEFINE FILE_FLAG_WRITE_THROUGH		0x80000000
#DEFINE FILE_FLAG_RANDOM_ACCESS		0x10000000

#DEFINE MAX_PATH                255
#DEFINE ERROR_NO_MORE_ITEMS     259
#DEFINE ERROR_GEN_FAILURE        31  && device is not responding
#DEFINE ERROR_WRITE_FAULT        29  && cannot write to specified device
#DEFINE ERROR_READ_FAULT         30  && cannot read from specified device
#DEFINE ERROR_OUT_OF_PAPER       28  && printer is out of paper
#DEFINE ERROR_NOT_SUPPORTED      50  && The request is not supported
#DEFINE INVALID_HANDLE_VALUE     -1

#DEFINE GUID_Size  16
#DEFINE SP_DEVICE_INTERFACE_DATA_Size  28
#DEFINE SP_DEVICE_INTERFACE_DETAIL_DATA_Size  5
#DEFINE ERROR_INSUFFICIENT_BUFFER			122
#DEFINE ERROR_NO_MORE_ITEMS					259
#DEFINE INVALID_HANDLE_VALUE				-1

#DEFINE SPDRP_ADDRESS						0x001C
#DEFINE SPDRP_BUSTYPEGUID					0x0013
#DEFINE SPDRP_CAPABILITIES					0x000F
#DEFINE SPDRP_CHARACTERISTICS				0x001B
#DEFINE SPDRP_CLASS							0x0007
#DEFINE SPDRP_CLASSGUID						0x0008
#DEFINE SPDRP_COMPATIBLEIDS					0x0002
#DEFINE SPDRP_CONFIGFLAGS					0x000A
#DEFINE SPDRP_DEVICE_POWER_DATA				0x000E
#DEFINE SPDRP_DEVICEDESC					0x0000
#DEFINE SPDRP_DEVTYPE						0x0019
#DEFINE SPDRP_DRIVER						0x0009
#DEFINE SPDRP_ENUMERATOR_NAME				0x0016
#DEFINE SPDRP_FRIENDLYNAME					0x000C
#DEFINE SPDRP_HARDWAREID					0x0001
#DEFINE SPDRP_LOCATION_INFORMATION			0x000D
#DEFINE SPDRP_LOWERFILTERS					0x0012
#DEFINE SPDRP_MFG							0x000B
#DEFINE SPDRP_PHYSICAL_DEVICE_OBJECT_NAME	0x000E
#DEFINE SPDRP_REMOVAL_POLICY				0x001F
#DEFINE SPDRP_REMOVAL_POLICY_HW_DEFAULT		0x0020
#DEFINE SPDRP_REMOVAL_POLICY_OVERRIDE		0x0021
#DEFINE SPDRP_SECURITY						0x0017
#DEFINE SPDRP_SECURITY_SDS					0x0018
#DEFINE SPDRP_SERVICE						0x0004
#DEFINE SPDRP_UI_NUMBER						0x0010
#DEFINE SPDRP_UI_NUMBER_DESC_FORMAT			0x001E
#DEFINE SPDRP_UPPERFILTERS					0x0011

#DEFINE INVALID_HANDLE_VALUE		-1
#DEFINE ERROR_NO_MORE_ITEMS        259
#DEFINE ERROR_INVALID_PARAMETER     87
#DEFINE ERROR_INVALID_FLAGS       1004
#DEFINE ERROR_INSUFFICIENT_BUFFER  122
#DEFINE DIGCF_INTERFACEDEVICE       16           && 0x00000010  All devices which expose interfaces
#DEFINE DIGCF_PRESENT                2           && 0x00000002  All installed devices present currently
#DEFINE DIGCF_ALLCLASSES             4			 &&             All installed devices
#DEFINE DIGCF_PROFILE                8			 &&             All devices part of current hardware profile
#DEFINE DIGCF_DEVICEINTERFACE   0x0010           && 0x00000010  All devices which expose interfaces

LOCAL ls_GUID, m.ln_Pointer
PRIVATE iLoop, llOnce, lnRW420, lnRW420ID, lcSendValue, lcReceiveValue
lnRW420 = .F.			&& RW420 Printer found
lnRW420ID = 0			&& if greater than zero, this is our printer to write data to
iLoop = 0
llOnce = .F.
lcSendValue = SPACE(255)
lcReceiveValue = SPACE(255)

DECLARE LONG GetLastError IN Kernel32

DECLARE LONG CloseHandle IN Kernel32 LONG hObject

DECLARE LONG CreateFile IN Kernel32 ;
	STRING cFileName, LONG dwDesiredAccess, LONG dwShareMode, ;
	STRING @ lpSecurityAttributes, LONG dwCreationDisposition, ;
	LONG dwFlagsAndAttributes, LONG hTemplateFile

DECLARE INTEGER WriteFile IN kernel32; 
    INTEGER   UsbHandle,; 
    STRING   lpBuffer,; 
    INTEGER   lnumbytes,; 
    INTEGER @ BytesWritten,; 
    INTEGER   lpOverlapped 

DECLARE HidD_GetHidGuid IN HID ;
	STRING @ O_sHidGuid

DECLARE LONG HidD_GetProductString IN HID ;
	LONG hHidDeviceObject, STRING @ O_cBuffer, LONG nBufferLength

DECLARE LONG HidD_GetAttributes IN HID ;
	LONG hHidDeviceObject, STRING @ _cBuffer, LONG nBufferLength
		
DECLARE LONG SetupDiDestroyDeviceInfoList IN SetupAPI ;
	LONG hDeviceInfoSet

DECLARE LONG SetupDiGetClassDevs IN SetupAPI ;
	STRING @ sGUID, STRING Enumerator, LONG nhWnd, LONG nFlags

DECLARE LONG SetupDiEnumDeviceInterfaces IN SetupAPI ;
	LONG hDeviceInfo, STRING @ sDeviceInfoData, ;
	STRING @ sInterfaceClassGuid, LONG MemberIndex, ;
	STRING @ O_sDeviceInterfaceData

DECLARE LONG SetupDiGetDeviceInterfaceDetail IN SetupAPI ;
	LONG hDeviceInfo, STRING @ sDeviceInterfaceData, ;
	STRING @ O_sDeviceInterfaceDetailData, LONG DeviceInterfaceDetailDataSize, ;
	LONG @ O_nRequiredSize, STRING @ O_sDeviceInfoData

DECLARE INTEGER SetupDiEnumDeviceInfo IN setupapi;
	INTEGER DeviceInfoSet,;
	INTEGER MemberIndex,;
	STRING @DeviceInfoData

DECLARE INTEGER SetupDiGetDeviceRegistryProperty IN setupapi;
	INTEGER DeviceInfoSet,;
	STRING @DeviceInfoData,;
	INTEGER _Property,;
	STRING @PropertyRegDataType,;
	STRING @PropertyBuffer,;
	INTEGER PropertyBufferSize,;
	STRING @RequiredSize

DECLARE INTEGER ReadFile IN kernel32;
	INTEGER hFile,;
	STRING  @lpBuffer,;
	INTEGER nNumberOfBytesToRead,;
	INTEGER @lpNumberOfBytesRead,;
	STRING lpOverlapped	

DECLARE INTEGER FormatMessage IN kernel32; 
    INTEGER dwFlags, INTEGER lpSource, INTEGER dwMessageId,; 
    INTEGER dwLanguageId, INTEGER @lpBuffer,; 
    INTEGER nSize, INTEGER Arguments 

DECLARE RtlMoveMemory IN kernel32 As CopyMemory; 
    STRING @Destination, INTEGER Source, INTEGER nLength 

DECLARE INTEGER DeviceIoControl IN kernel32 ;
	INTEGER hDevice,;
	INTEGER dwIoControlCode,;
	STRING @ lpInBuffer,;
	INTEGER nInBufferSize,;
	STRING @ lpOutBuffer,;
	INTEGER nOutBufferSize,;
	INTEGER lpBytesReturned,;
	STRING @ lpOverlapped

* ADD GetQueuedCompletionStatus()
*----------------------------------------------------------------------------------------------------
*--Main Program
*----------------------------------------------------------------------------------------------------

PUBLIC devicearray					&& Used for storing all device information from registry
DIMENSION devicearray(1,10)
FOR i = 1 TO ALEN(devicearray,2)
	devicearray(1,i) = []
	devicearray(1,1) = 0
ENDFOR
lc_Guid = SPACE( GUID_Size )		&& Guid variable
*HidD_GetHidGuid( @ls_HidGuid )		&& Get the device interface GUID for the the HIDClass devices

*--Device Classes and Device Interface Classes (Device Interface Class needed for SetupDiEnumDeviceInterfaces()
*  GUID_DEVCLASS_HIDCLASS, 0x745A17A0, 0x74D3, 0x11D0, 0xB6, 0xFE, 0x00, 0xA0, 0xC9, 0x0F, 0x57, 0xDA
#DEFINE GUID_DEVCLASS_HIDCLASS ;
	CHR(0xA0) + CHR(0x17) + CHR(0x5A) + CHR(0x74) + ;
	CHR(0xD3) + CHR(0x74) + CHR(0xD0) + CHR(0x11) + ;
	CHR(0xB6) + CHR(0xFE) + CHR(0x00) + CHR(0xA0) + ;
	CHR(0xC9) + CHR(0x0F) + CHR(0x57) + CHR(0xDA)
*!* GUID_DEVCLASS_PRINTER, 0x4D36E979, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18
*!* [{4D36E979-E325-11CE-BFC1-08002BE10318}]
#DEFINE GUID_DEVCLASS_PRINTER ;
	CHR(0x79) + CHR(0xE9) + CHR(0x36) + CHR(0x4D) + ;
	CHR(0xE3) + CHR(0x25) + CHR(0x11) + CHR(0xCE) + ;
	CHR(0xBF) + CHR(0xC1) + CHR(0x08) + CHR(0x00) + ;
	CHR(0x2B) + CHR(0xE1) + CHR(0x03) + CHR(0x18)
*!* GUID_DEVCLASS_DISKDRIVE, 0x4d36e967L, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18
#DEFINE GUID_DEVCLASS_DISKDRIVE ;
	CHR(0x67) + CHR(0xE9) + CHR(0x36) + CHR(0x4D) + ;
	CHR(0x25) + CHR(0xE3) + ;
	CHR(0xCE) + CHR(0x11) + ;
	CHR(0xBF) + CHR(0xC1) + CHR(0x08) + CHR(0x00) + CHR(0x2B) + CHR(0xE1) + CHR(0x03) + CHR(0x18)
*!* GUID_DEVCLASS_USB, 0x36FC9E60, 0xC465, 0x11CF, 0x80, 0x56, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 )
* [{36FC9E60-C465-11CF-8056-444553540000}]
#DEFINE GUID_DEVCLASS_USB ;
	CHR(0x60) + CHR(0x9E) + CHR(0xFC) + CHR(0x36) + ;
	CHR(0x65) + CHR(0xC4) + ;
	CHR(0xCF) + CHR(0x11) + ;
	CHR(0x80) + CHR(0x56) + CHR(0x44) + CHR(0x45) + CHR(0x53) + CHR(0x54) + CHR(0x00) + CHR(0x00)
*GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED
#DEFINE GUID_DEVINTERFACE_USB_DEVICE ;
	CHR(0x10) + CHR(0xBF) + CHR(0xDC) + CHR(0xA5) + ;
	CHR(0x30) + CHR(0x65) + ;
	CHR(0xD2) + CHR(0x11) + ;
	CHR(0x90) + CHR(0x1F) + CHR(0x00) + CHR(0xC0) + CHR(0x4F) + CHR(0xB9) + CHR(0x51) + CHR(0xED)
* A5DCBF10-6530-11D2-901F-00C04FB951ED */
*!*	RW420:
*!*	USB\Vid_0a5f&Pid_003e&Rev_0001
*!*	USB\Vid_0a5f&Pid_003e
*HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses\{28d78fad-5a12-11d1-ae5b-0000f803a8c2}
*{28d78fad-5a12-11d1-ae5b-0000f803a8c2
#DEFINE GUID_DEVINTERFACE_USB_PRINT ;
	CHR(0xad) + CHR(0x8f) + CHR(0xd7) + CHR(0x28) + ;
	CHR(0x12) + CHR(0x5a) + ;
	CHR(0xd1) + CHR(0x11) + ;
	CHR(0xae) + CHR(0x5b) + CHR(0x00) + CHR(0x00) + CHR(0xf8) + CHR(0x03) + CHR(0xa8) + CHR(0xc2)

*--Store the device guid we want to use to lc_Guid for use
*lc_Guid = GUID_DEVINTERFACE_USB_DEVICE
lc_Guid = GUID_DEVINTERFACE_USB_PRINT
*lc_Guid = GUID_DEVCLASS_PRINTER

IF !EMPTY( lc_Guid )
*	cFlags = DIGCF_PRESENT + DIGCF_DEVICEINTERFACE	&&  all classes present that expose interfaces
*	cFlags =  DIGCF_ALLCLASSES
*^^TCH
	cFlags = DIGCF_DEVICEINTERFACE
		DO WHILE .T.	&& a loop not really need for this test but here for later
		lldestroy = .F.
		*--Retrieve a device information set that contains all the devices of a specified class
		*--The Class is determined by the interface class guid passed in lc_Guid
		m.ln_Pointer =  SetupDiGetClassDevs(@lc_Guid, 0, 0, cFlags)
		IF TYPE('m.ln_Pointer') <> "N" .OR. m.ln_Pointer = INVALID_HANDLE_VALUE
			? [SetupDiGetClassDevs FAILED]
			EXIT
		ENDIF
		lldestroy = .T.
		lndeviceinfoset = m.ln_pointer
		IF (m.ln_Pointer != INVALID_HANDLE_VALUE)
			CLEAR
			? [Pointer: ]+ALLTRIM(STR(m.ln_pointer))
			EnumerateDevices( m.ln_Pointer, lc_Guid )
			*--Destroy the device information list and free all associated memory
			IF SetupDiDestroyDeviceInfoList( m.ln_Pointer ) <> 0
				lldestroy = .F.
			ENDIF
			EXIT
		ELSE
			EXIT
		ENDIF
	ENDDO
ENDIF
IF lldestroy
	*--Cleanup
	*--Destroy the device information list and free all associated memory
	?'=================================================='
	?'Cleaning Up...'
	DECLARE INTEGER SetupDiDestroyDeviceInfoList IN setupapi;
		INTEGER DeviceInfoSet
	llokay = SetupDiDestroyDeviceInfoList(m.ln_Pointer)
	?'        Releasing the handle - SetupDiDestroyDeviceInfoList Result: '
	?? llokay
	?'        Last Error: '
	?? GetLastError()
ENDIF
IF !llOnce
	?"***********************************************************"
	?" Error Using SetupDiEnumDeviceInterfaces ---------->>>>>>>>"
	?"***********************************************************"
ENDIF
CLEAR DLLS
RETURN


*********************************************************************************
** Procedures
*********************************************************************************

*********************************************************************************
PROCEDURE EnumerateDevices( th_DevInfo, ts_Guid )
	*********************************************************************************
	LOCAL ls_DiData, ls_DiDetailData, lh_Device
	LOCAL ln_Error, ln_Index, ln_ReqSize, ln_Error1
	LOCAL lc_DeviceName, lw_Buffer, lc_Buffer

	STORE 0 TO ln_Error, ln_Error1, ln_Index, ln_ReqSize
	ls_DiData = PADR( BINTOC( SP_DEVICE_INTERFACE_DATA_Size, '4rs' ), ;
		SP_DEVICE_INTERFACE_DATA_Size, CHR(0) )

	m.lnRetVal  = -1	&& SetupDiEnumDeviceInterfaces
	m.lnRetVal2 = -1	&& SetupDiEnumDeviceInfo
	iLoop = 0

	DO WHILE (m.lnRetVal <> 0 .OR. m.lnRetVal2 <> 0 .or. ln_Error != ERROR_NO_MORE_ITEMS)

		*-- Use SetupDiEnumDeviceInfo function to return a SP_DEVINFO_DATA structure
		*-- that specifies a device information element in a device information set. 

		m.lcDeviceInfoData = PADR(BINTOC(28, [4RS]), 4, CHR(0)) + REPLICATE(CHR(0), 24)
		m.lndeviceinfoset = th_DevInfo
		m.lnRetVal2 = SetupDiEnumDeviceInfo( ;
			th_DevInfo, ;
			iLoop, ;
			@m.lcDeviceInfoData)

		ln_Error = GetLastError()
		
		IF m.lnRetVal2 = 0 .and. ln_Error = ERROR_NO_MORE_ITEMS
			EXIT
		ENDIF
		
		lifoundit = .F.
		iLoop = iLoop + 1
		llrw420 = .F.
		llInterface = .F.
		
		IF m.lnRetVal2 <> 0
		
			*--Retrieve the specified device property from the registry
			lifoundit = .T.
			m.lnx = iLoop - 1
			DIMENSION devicearray(iLoop,10)

			&&& extract the interface data here ... (CTOBIN, SUBSTR)
			devicearray(m.iLoop,1) = m.lnx
			?[->Device: ], ALLTRIM(STR(m.lnx))
			m.lcDeviceProperty = GetRegistryProperty(m.lndeviceinfoset, m.lcDeviceInfoData, SPDRP_CLASS)
			IF ! ("ERROR" $ m.lcDeviceProperty)
				?[Property:], [CLASS: ], m.lcDeviceProperty
			ENDIF
			devicearray(m.iLoop,2) = m.lcDeviceProperty

			m.lcDeviceProperty = GetRegistryProperty(m.lndeviceinfoset, m.lcDeviceInfoData, SPDRP_DEVICEDESC)
			IF ! ("ERROR" $ m.lcDeviceProperty)
				?[Property:], [DEVICE DESC: ], m.lcDeviceProperty
			ENDIF
			devicearray(m.iLoop,3) = m.lcDeviceProperty
			IF TYPE('m.lcDeviceProperty') = "C" .and. "USB PRINT" $ UPPER(m.lcDeviceProperty)
				lnRW420 = .T.
				lnRW420ID = m.lnx
			ENDIF
			m.lcDeviceProperty = GetRegistryProperty(m.lndeviceinfoset, m.lcDeviceInfoData, SPDRP_ENUMERATOR_NAME)
			IF ! ("ERROR" $ m.lcDeviceProperty)
				?[Property:], [ENUMERATOR_NAME: ], m.lcDeviceProperty
			ENDIF
			devicearray(m.iLoop,4) = m.lcDeviceProperty
			IF TYPE('m.lcDeviceProperty') = "C" .and. ('USB' $ m.lcDeviceProperty .or. UPPER(ALLTRIM(m.lcDeviceProperty)) == "USB")
				*--Use the USB Interface GUID to get the device interface details
				ts_Guid = GUID_DEVINTERFACE_USB_DEVICE
			ENDIF

			m.lcDeviceProperty = GetRegistryProperty(m.lndeviceinfoset, m.lcDeviceInfoData, SPDRP_FRIENDLYNAME)
			IF ! ("ERROR" $ m.lcDeviceProperty)
				?[Property:], [FRIENDLYNAME: ], m.lcDeviceProperty
			ENDIF
			devicearray(m.iLoop,5) = m.lcDeviceProperty

			m.lcDeviceProperty = GetRegistryProperty(m.lndeviceinfoset, m.lcDeviceInfoData, SPDRP_HARDWAREID)
			IF ! ("ERROR" $ m.lcDeviceProperty)
				?[Property:], [HARDWAREID: ], m.lcDeviceProperty
			ENDIF
			devicearray(m.iLoop,6) = m.lcDeviceProperty
			IF TYPE('m.lcDeviceProperty') = "C" .and. "0a5f&pid_003e" $ LOWER(m.lcDeviceProperty)
				llrw420 = .T.	&& Printer
				lnRW420 = .T.
				lnRW420ID = m.lnx
			ENDIF
			IF TYPE('m.lcDeviceProperty') = "C" .and. "ZEBRA_RW_420" $ UPPER(m.lcDeviceProperty)
				llrw420 = .T.	&& USB
				lnRW420 = .T.
				lnRW420ID = m.lnx
			ENDIF			

			m.lcDeviceProperty = GetRegistryProperty(m.lndeviceinfoset, m.lcDeviceInfoData, SPDRP_MFG)
			IF ! ("ERROR" $ m.lcDeviceProperty)
				?[Property:], [MFG: ], m.lcDeviceProperty
			ENDIF
			devicearray(m.iLoop,7) = m.lcDeviceProperty

			m.lcDeviceProperty = GetRegistryProperty(m.lndeviceinfoset, m.lcDeviceInfoData, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME)
			IF ! ("ERROR" $ m.lcDeviceProperty)
				?[Property:], [PHYSICAL_DEVICE_OBJECT_NAME: ], m.lcDeviceProperty
			ENDIF
			devicearray(m.iLoop,8) = m.lcDeviceProperty

			m.lcDeviceProperty = GetRegistryProperty(m.lndeviceinfoset, m.lcDeviceInfoData, SPDRP_DEVTYPE	)
			IF ! ("ERROR" $ m.lcDeviceProperty)
				?[Property:], [DEV TYPE: ], m.lcDeviceProperty
			ENDIF
			devicearray(m.iLoop,9) = m.lcDeviceProperty

			m.lcDeviceProperty = GetRegistryProperty(m.lndeviceinfoset, m.lcDeviceInfoData, SPDRP_CLASSGUID)
			IF ! ("ERROR" $ m.lcDeviceProperty)
				?[Property:], [CLASS GUID: ], m.lcDeviceProperty
			ENDIF
			devicearray(m.iLoop,10) = m.lcDeviceProperty
			IF TYPE('m.lcDeviceProperty') = "C" .and. UPPER(ALLTRIM(m.lcDeviceProperty)) = [{36FC9E60-C465-11CF-8056-444553540000}]
				*--USB
				ts_Guid = GUID_DEVINTERFACE_USB_DEVICE
			ENDIF


			*!*				?"*****************************************************"
			*!*				?" Success using SetupDiGetDeviceRegistryProperty"
			*!*				?"*****************************************************"

		ELSE
			?" NO data from SetupDiEnumDeviceInfo or SetupDiGetDeviceRegistryProperty"
		ENDIF

*^^Tch
		lc_TName = [\\?\usb#Vid_0a5f&Pid_003e#XXRC06-21-5631#{28d78fad-5a12-11d1-ae5b-0000f803a8c2}]
		=getvaluesfromdevice(lc_TName)
		?usbinfo(lc_TName)

		*--Retrieve a context structure for a device interface of the device information set
		*--Each call returns information about one device interface. 
		*--Call repeatedly to get information about several interfaces exposed by one or more devices

		m.lnRetVal = SetupDiEnumDeviceInterfaces( th_DevInfo, 0, ts_Guid, ln_Index, @ls_DiData )

		IF m.lnRetVal == 0

			ln_Error1 = GetLastError()
			IF (ln_Error1 != ERROR_NO_MORE_ITEMS)
				ShowError( ln_Error1, ln_Index, 'SetupDiEnumDeviceInterfaces()' )
			ELSE
				IF llOnce
					? [ No More Devices from SetupDiEnumDeviceInterfaces]
				ELSE
					? [ No Devices from SetupDiEnumDeviceInterfaces]
				ENDIF
			ENDIF

			IF llrw420 .and. lnRW420ID > 0

				FOR icheckitems = 2 TO 10

					IF icheckitems > ALEN(devicearray,2)
						EXIT
					ENDIF
					lc_deviceName = devicearray(m.iLoop,icheckitems)
					IF TYPE('lc_DeviceName') = "N"
						lc_DeviceName = ALLTRIM(STR(lc_DeviceName))
					ELSE
						IF TYPE('lc_DeviceName') <> "C"
							lc_DeviceName = ''
						ENDIF
						lc_DeviceName = ALLTRIM(lc_devicename)
					ENDIF
					lc_DeviceName = STRTRAN(lc_DeviceName,CHR(0),'')
					? [Trying: ],ALLTRIM(STR(icheckitems))+[ of 10 ], lc_DeviceName
					
					lh_Device =	CreateFile(lc_DeviceName, ; 
						      GENERIC_READ + GENERIC_WRITE ,; 
						      FILE_SHARE_READ + FILE_SHARE_WRITE, 0, OPEN_ALWAYS,; 
							  FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, 0) 
			
					IF (lh_Device != INVALID_HANDLE_VALUE)	&& Can use DeviceIoControl From Lh_Device also
						lw_Buffer = SPACE( MAX_PATH )
						*--Is it a HID? Get Attributes - Deal with this later
						IF (HidD_GetAttributes( lh_Device, @lw_Buffer, MAX_PATH ) == 1)
							lc_Buffer = STRTRAN(lw_buffer,CHR(0),'')
							? 'Information: ' + lc_Buffer
						ELSE
							? [No HID Information]
						ENDIF
						*--Is it a HID? Get Product Name - Deal with this later
						lw_Buffer = SPACE( MAX_PATH )
						IF (HidD_GetProductString( lh_Device, @lw_Buffer, MAX_PATH ) == 1)
							lc_Buffer = MakeANSI( lw_Buffer )
							? 'Product Name: ' + lc_Buffer
						ENDIF
						IF lnRW420 .and. lnRW420ID > 0
							*--Will DeviceIoControl Work?
								
		
							lcSendValue = [! U1 MCR 80 T1 T2] + +CHR(10)+CHR(13)
							lnWritten = 0
							IF WriteFile(lh_Device, lcSendValue, LEN(lcSendValue),@lnWritten,0) <> 0 && 0 is failure
								lnRW420 = .F.
								lnRW420ID = 0
								lcReadBuffer = REPLICATE(" ",MAX_PATH)
								lnBytesReturned = 0
								lnCounter2 = 0
								DO WHILE lnBytesReturned == 0
									lncounter2 = lncounter2 + 1
									IF ReadFile(lh_Device, @lcReadBuffer, LEN(lcReadBuffer), @lnBytesReturned, NULL) <> 0
										lncounter = 0
										DO WHILE lncounter < 50
											lncounter = lncounter + 1
											DOEVENTS
											IF !EMPTY(MakeANSI(lcReadBuffer))
												? MakeANSI(lcReadBuffer)
											ENDIF
										ENDDO
										* ADD GetQueuedCompletionStatus()
									ENDIF
									IF lncounter2 = 100
										EXIT
									ENDIF
								ENDDO
							ENDIF
						ENDIF
						CloseHandle( lh_Device )
					ELSE
						ShowError( GetLastError(), ln_Index, 'CreateFile()' )
					ENDIF

				ENDFOR
			
			ENDIF	&& Only try if RW420 found
			
			IF lifoundit
				ln_Index = ln_Index + 1
				LOOP
				EXIT
			ENDIF

		ELSE

			llOnce = .T.	&& SetupDiEnumDeviceInterfaces worked at least once

			*--Retrieve detailed information about a specified device interface
			*--1. Get the required buffer size and Call SetupDiGetDeviceInterfaceDetail 
			*--   with a NULL DeviceInterfaceDetailData pointer,
			*--   a DeviceInterfaceDetailDataSize of zero, and a valid RequiredSize parameter. 
			*--   In response to such a call, this function fails, GetLastError returns ERROR_INSUFFICIENT_BUFFER, 
			*--   and the RequiredSize parameter receives the required buffer size. 
			*--2. Allocate an appropriately sized buffer and call the function again to get the interface details. 

			*--1. First Call to get the required buffer size (ln_ReqSize)
			SetupDiGetDeviceInterfaceDetail( th_DevInfo, ls_DiData, ;
				0, 0, @ln_ReqSize, 0 )
			ls_DiDetailData = PADR( BINTOC( SP_DEVICE_INTERFACE_DETAIL_DATA_Size, '4rs' ), ;
				ln_ReqSize, CHR(0) )
			*--2.  Second Call with buffer sized
			ln_Result = SetupDiGetDeviceInterfaceDetail( th_DevInfo, ls_DiData, ;
				@ls_DiDetailData, ln_ReqSize, @ln_ReqSize, 0 )

			IF (ln_Result == 1)
				lc_DeviceName = SUBSTR( ls_DiDetailData, 5 )
				ln_Pos = AT( CHR(0), lc_DeviceName )
				IF (ln_Pos > 0)
					lc_DeviceName = LEFT( lc_DeviceName, ln_Pos - 1 )
				ENDIF
*!*					IF "0a5f&pid_003e" $ LOWER(lc_DeviceName)
*!*						=MESSAGEBOX('This is RW420 Printer.')
*!*					ENDIF
				
				?[Device Name: ],lc_DeviceName	&& Device Name from buffer returned from SetupDiGetDeviceInterfaceDetail()
				IF USED('TESTUSB')
					select testusb
					APPEND BLANK
					REPLACE cvalue WITH lc_DeviceName
				ENDIF
					
				=getvaluesfromdevice(lc_DeviceName)
				?usbinfo(lc_TName)

				*--Create a file, file stream, directory, physical disk, volume, console buffer, tape drive
				*--communications resource, mailslot, or named pipe.  CreateFile returns a handle to access
				*--the object.
*!*					lh_Device = CreateFile(lc_DeviceName, GENERIC_READ + GENERIC_WRITE, FILE_SHARE_READ + FILE_SHARE_WRITE, ;
*!*					         0, OPEN_ALWAYS, ;
*!*					         FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, 0)
				*lh_Device = CreateFile( lc_DeviceName, 0x80000000, 0x1, 0, 3, 0x20000000, 0 )
				lh_Device =	CreateFile(lc_DeviceName, ; 
						      GENERIC_READ + GENERIC_WRITE ,; 
						      FILE_SHARE_READ + FILE_SHARE_WRITE, 0, OPEN_ALWAYS,; 
							  FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, 0) 

				IF (lh_Device != INVALID_HANDLE_VALUE)	&& Can use DeviceIoControl From Lh_Device also
					lw_Buffer = SPACE( MAX_PATH )
					*--Is it a HID? Get Attributes - Deal with this later
					IF (HidD_GetAttributes( lh_Device, @lw_Buffer, MAX_PATH ) == 1)
						lc_Buffer = STRTRAN(lw_buffer,CHR(0),'')
						? 'Information: ' + lc_Buffer
					ELSE
						? [No HID Information]
					ENDIF
					*--Is it a HID? Get Product Name - Deal with this later
					lw_Buffer = SPACE( MAX_PATH )
					IF (HidD_GetProductString( lh_Device, @lw_Buffer, MAX_PATH ) == 1)
						lc_Buffer = MakeANSI( lw_Buffer )
						? 'Product Name: ' + lc_Buffer
					ENDIF
					IF lnRW420 .and. lnRW420ID > 0
						*--Will DeviceIoControl Work?
							
	
						lcSendValue = [! U1 MCR 80 T1 T2] + +CHR(10)+CHR(13)
						lnWritten = 0
						IF WriteFile(lh_Device, lcSendValue, LEN(lcSendValue),@lnWritten,0) <> 0 && 0 is failure
							lnRW420 = .F.
							lnRW420ID = 0
							lcReadBuffer = REPLICATE(" ",MAX_PATH)
							lnBytesReturned = 0
*!*								IF ReadFile(lh_Device, @lcReadBuffer, LEN(lcReadBuffer), @lnBytesReturned, 0) <> 0
*!*									lncounter = 0
*!*									DO WHILE lncounter < 50
*!*										lncounter = lncounter + 1
*!*										DOEVENTS
*!*										IF !EMPTY(MakeANSI(lcReadBuffer))
*!*											? MakeANSI(lcReadBuffer)
*!*										ENDIF
*!*									ENDDO
*!*									* ADD GetQueuedCompletionStatus()
*!*								ENDIF
								lnCounter2 = 0
								DO WHILE lnBytesReturned == 0
									lncounter2 = lncounter2 + 1
									IF ReadFile(lh_Device, @lcReadBuffer, LEN(lcReadBuffer), @lnBytesReturned, null) <> 0
										lncounter = 0
										DO WHILE lncounter < 50
											lncounter = lncounter + 1
											DOEVENTS
											IF !EMPTY(MakeANSI(lcReadBuffer))
												? lcReadBuffer
												? MakeANSI(lcReadBuffer)
											ENDIF
										ENDDO
										* ADD GetQueuedCompletionStatus()
									ENDIF
									IF lncounter2 = 100
										EXIT
									ENDIF
								ENDDO

						ENDIF
					ENDIF
					CloseHandle( lh_Device )
				ELSE
					ShowError( GetLastError(), ln_Index, 'CreateFile()' )
				ENDIF
			ELSE
				ShowError( GetLastError(), ln_Index, 'SetupDiGetDeviceInterfaceDetail()' )
			ENDIF
			ln_Index = ln_Index + 1
			?"*****************************************************"
		ENDIF
	ENDDO
ENDPROC
RETURN


*********************************************************************************
PROCEDURE ShowError( tn_Error, tn_Index, tc_Message )
	*********************************************************************************

	? tc_Message + ' ERROR !!'
	DO CASE
		CASE tn_Error = ERROR_GEN_FAILURE
			? [The Device is not responding.]
		CASE tn_Error = ERROR_WRITE_FAULT
			? [Cannot write to the device]
		CASE tn_Error = ERROR_READ_FAULT
			? [Cannot read from device]
		CASE tn_Error = ERROR_OUT_OF_PAPER
			? [Printer is out of paper]
		CASE tn_Error = ERROR_NOT_SUPPORTED
			? [Request is not supported by this device]
		OTHERWISE
			? [Error code:]+ALLTRIM(STR(tn_Error))
	ENDCASE
	IF (VARTYPE( tn_Index ) == 'N')
		? 'Member index:', ALLTRIM(STR(tn_Index))
	ENDIF
ENDPROC


*********************************************************************************
PROCEDURE MakeANSI( tw_String )
	*********************************************************************************
	LOCAL lc_String, ln_Pos

	RETURN STRTRAN(tw_String,CHR(0),'')
	
	lc_String = STRCONV( STRCONV( tw_String, 6 ), 2 )
	ln_Pos = AT( CHR(0), lc_String )
	IF (ln_Pos > 0)
		lc_String = LEFT( lc_String, ln_Pos - 1 )
	ENDIF

	RETURN lc_String
ENDPROC

*********************************************************************************
PROCEDURE GetRegistryProperty && courtesy Carlos Alotti
	*********************************************************************************

	LPARAMETERS tnDeviceInfoSet, tcDeviceInfoData, tnProperty

	LOCAL lnRetVal, lcPropertyBuffer, lcRequiredSize

	m.lcPropertyBuffer = SPACE(0)
	m.lcRequiredSize = SPACE(4)
	m.PropertyRegDataType = SPACE(4)

	*!*	"The SetupDiGetDeviceRegistryProperty function retrieves the specified device property."
	*!* We don't know the size of the required string buffer for the property until we call the
	*!* function, so we first call it with a null string to get the required buffer size, then
	*!* we call again with the proper buffer size

	m.lnRetVal = SetupDiGetDeviceRegistryProperty( ;
		m.tnDeviceInfoSet, ;
		@m.tcDeviceInfoData, ;
		m.tnProperty, ;
		@m.PropertyRegDataType, ;
		@m.lcPropertyBuffer, ;
		LEN(m.lcPropertyBuffer), ;
		@m.lcRequiredSize)

	IF m.lnRetVal = 0 AND GetLastError() = ERROR_INSUFFICIENT_BUFFER THEN
		m.lcPropertyBuffer = SPACE(CTOBIN(m.lcRequiredSize, [4RS]))

		m.lnRetVal = SetupDiGetDeviceRegistryProperty( ;
			m.tnDeviceInfoSet, ;
			@m.tcDeviceInfoData, ;
			m.tnProperty, ;
			0, ;
			@m.lcPropertyBuffer, ;
			LEN(m.lcPropertyBuffer), ;
			@m.lcRequiredSize)
	ENDIF

	IF m.lnRetVal = 0 THEN
		*		? [SetupDiGetDeviceRegistryProperty ERROR]
		*m.lcPropertyBuffer = [SetupDiGetDeviceRegistryProperty ERROR]
		m.lcPropertyBuffer = []
	ELSE
		m.lcPropertyBuffer = LEFT(m.lcPropertyBuffer, AT(CHR(0), m.lcPropertyBuffer) - 1)
	ENDIF

	RETURN m.lcPropertyBuffer



*********************************************************************************
FUNCTION getvaluesfromdevice (tc_DeviceName)
	*********************************************************************************

IF VARTYPE(tc_DeviceName) <> "C"
	RETURN ''
ENDIF
IF ! [0a5f&pid_003e] $ LOWER(tc_DeviceName)
*	RETURN
ENDIF
lh_Device =	CreateFile(tc_devicename, ; 
   GENERIC_READ + GENERIC_WRITE ,; 
   FILE_SHARE_READ + FILE_SHARE_WRITE, 0, OPEN_ALWAYS,; 
   FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, 0) 
			
*!*	DECLARE INTEGER DeviceIoControl IN kernel32 ;
*!*		INTEGER hDevice,;
*!*		INTEGER dwIoControlCode,;
*!*		STRING @ lpInBuffer,;
*!*		INTEGER nInBufferSize,;
*!*		STRING @ lpOutBuffer,;
*!*		INTEGER nOutBufferSize,;
*!*		INTEGER lpBytesReturned,;
*!*		STRING @ lpOverlapped
*!*		
*!*	hDevice 
*!*	[in] Handle to the device on which the operation is to be performed.
*!*	dwIoControlCode 
*!*	[in] Control code for the operation.
*!*	lpInBuffer 
*!*	[in] Pointer to the input buffer that contains the data required to perform the operation.
*!*	nInBufferSize 
*!*	[in] Size of the input buffer, in bytes.
*!*	lpOutBuffer 
*!*	[out] Pointer to the output buffer that is to receive the data returned by the operation.
*!*	nOutBufferSize 
*!*	[in] Size of the output buffer, in bytes. 
*!*	lpBytesReturned 
*!*	[out] Pointer to a variable that receives the size of the data stored in the output buffer, in bytes.
*!*	lpOverlapped 
*!*	[in] Pointer to an OVERLAPPED structure.

*^^tch
IF lh_Device !=INVALID_HANDLE_VALUE

*!*	#define FILE_DEVICE_UNKNOWN             0x00000022
*!*	#define METHOD_BUFFERED                 0
*!*	#define FILE_ANY_ACCESS                 0
*!*	#DEFINE GET_SERIAL_NUMBER               1575952
*!*	#DEFINE VENDOR_GET                      222964
*!*	#DEFINE VENDOR_SET                      222960

	m.sci = REPLICATE(CHR(0),1024)
	m.sco = REPLICATE(CHR(0),1024)
	m.ret_buffersize = 0
	m.otv = DeviceIoControl( lh_Device,;
		GET_SERIAL_NUMBER,@m.sci,LEN(sci),@m.sco,LEN(sco),;
		@m.ret_buffersize,0)
	? [DeviceIoControl Response: ],m.otv
	IF !EMPTY(m.otv)
		set STEP on
	ENDIF

	*--Send the command
	lcSendValue = [! U1 MCR 80 T1 T2] + +CHR(10)+CHR(13)
	*m.sci = REPLICATE(CHR(0),1024)
	m.sci = lcSendValue
	m.sco = REPLICATE(CHR(0),1024)
	m.ret_buffersize = 0
	m.otv = DeviceIoControl( lh_Device,;
		VENDOR_SET,@m.sci,LEN(sci),@m.sco,LEN(sco),;
		@m.ret_buffersize,0)
	? [DeviceIoControl Response: ],m.otv
	IF !EMPTY(m.otv)
		set STEP on
	ENDIF

	*--Receive the data
	m.sci = REPLICATE(CHR(0),1024)
	m.sco = REPLICATE(CHR(0),1024)
	m.ret_buffersize = 0
	m.otv = DeviceIoControl( lh_Device,;
		VENDOR_GET,@m.sci,LEN(sci),@m.sco,LEN(sco),;
		@m.ret_buffersize,0)
	? [DeviceIoControl Response: ],m.otv
	IF !EMPTY(m.otv)
		set STEP on
	ENDIF

ENDIF
	
IF (lh_Device != INVALID_HANDLE_VALUE)	&& Can use DeviceIoControl From Lh_Device also
		lw_Buffer = SPACE( MAX_PATH )
		*--Is it a HID? Get Attributes - Deal with this later
		lcSendValue = [! U1 MCR 80 T1 T2] + +CHR(10)+CHR(13)
		lnWritten = 0
		IF WriteFile(lh_Device, lcSendValue, LEN(lcSendValue),@lnWritten,0) <> 0 && 0 is failure
			lcReadBuffer = REPLICATE(" ",MAX_PATH)
			lnBytesReturned = 0
			lnloopit = 0
			CloseHandle( lh_Device )

			lh_Device =	CreateFile(tc_devicename, ; 
			   GENERIC_READ + GENERIC_WRITE ,; 
			   FILE_SHARE_READ + FILE_SHARE_WRITE, 0, OPEN_ALWAYS,; 
			   FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, 0) 

			IF (lh_Device != INVALID_HANDLE_VALUE)	&& Can use DeviceIoControl From Lh_Device also
				DO WHILE .T. 
					*--Send and Receive the data
					m.sci = [! U1 MCR 80 T1 T2] + +CHR(10)+CHR(13)
					m.sco = REPLICATE(CHR(0),1024)
					m.ret_buffersize = 0
					m.otv = DeviceIoControl( lh_Device,;
						VENDOR_GET,@m.sci,LEN(sci),@m.sco,LEN(sco),;
						@m.ret_buffersize,0)
					? [DeviceIoControl Response: ],m.otv
					IF !EMPTY(m.otv)
						set STEP on
					ENDIF
					=ReadFile(lh_Device, @lcReadBuffer, LEN(lcReadBuffer), @lnBytesReturned, null) 
					EXIT
				ENDDO
				CloseHandle( lh_Device )
			ENDIF

			IF !EMPTY(lcReadBuffer) .or. !EMPTY(MakeANSI(lcReadBuffer))

				? [Read Buffer: ], lcReadBuffer
				IF !EMPTY(MakeANSI(lcReadBuffer))
					? MakeANSI(lcReadBuffer)
				ENDIF

			ELSE

				? [No ReadFile]

			ENDIF

		ELSE

			? [No WriteFile]

		ENDIF
*		CloseHandle( lh_Device )
ELSE
	ShowError( GetLastError(), 0, 'CreateFile()' )
ENDIF

RETURN

*********************************************************************************
FUNCTION GetLongInt(Lo, Hi) 
*********************************************************************************
#DEFINE MAX_DWORD 0x100000000 
    IF VARTYPE(m.Lo)="C" 
        Lo = buf2dword(m.Lo) 
    ENDIF 
    IF VARTYPE(m.Hi) = "C" 
        Hi = buf2dword(m.Hi) 
    ENDIF 
RETURN m.Hi * MAX_DWORD + m.Lo 

*********************************************************************************
FUNCTION buf2dword(lcBuffer) 
*********************************************************************************
RETURN Asc(SUBSTR(lcBuffer, 1,1)) + ; 
    BitLShift(Asc(SUBSTR(lcBuffer, 2,1)),  8) +; 
    BitLShift(Asc(SUBSTR(lcBuffer, 3,1)), 16) +; 
    BitLShift(Asc(SUBSTR(lcBuffer, 4,1)), 24) 

*************************************************
**************************************************************************************
* These values are for future use
*!*		00000000  -  7B 34 44 33 36 45 39 37 39 2D 45 33 32 35 2D 31  -  {4D36E979-E325-1
*!*		00000010  -  31 43 45 2D 42 46 43 31 2D 30 38 30 30 32 42 45  -  1CE-BFC1-08002BE
*!*		00000020  -  31 30 33 31 38 7D 00                             -  10318}.
*!*		{4D36E979-E325-11CE-BFC1-08002BE10318}

*!*		/* f18a0e88-c30c-11d0-8815-00a0c906bed8 */
*!*		DEFINE_GUID(GUID_DEVINTERFACE_USB_HUB,    0xf18a0e88, 0xc30c, 0x11d0, 0x88, 0x15, 0x00, \
*!*		0xA0, 0xC9, 0x06, 0xbe, 0xd8);

*!*		/* A5DCBF10-6530-11D2-901F-00C04FB951ED */
*!*		DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, \
*!*		0xC0, 0x4F, 0xB9, 0x51, 0xED);

*!*		/* 3ABF6F2D-71C4-462a-8A92-1E6861E6AF27 */
*!*		DEFINE_GUID(GUID_DEVINTERFACE_USB_HOST_CONTROLLER, 0x3abf6f2d, 0x71c4, 0x462a, 0x8a, 0x92, 0x1e, \
*!*		0x68, 0x61, 0xe6, 0xaf, 0x27);

*!*		/* 4E623B20-CB14-11D1-B331-00A0C959BBD2 */
*!*		DEFINE_GUID(GUID_USB_WMI_STD_DATA, 0x4E623B20L, 0xCB14, 0x11D1, 0xB3, 0x31, 0x00,\
*!*		0xA0, 0xC9, 0x59, 0xBB, 0xD2);

*!*		/* 4E623B20-CB14-11D1-B331-00A0C959BBD2 */
*!*		DEFINE_GUID(GUID_USB_WMI_STD_NOTIFICATION, 0x4E623B20L, 0xCB14, 0x11D1, 0xB3, 0x31, 0x00,\
*!*		0xA0, 0xC9, 0x59, 0xBB, 0xD2);


FUNCTION usbinfo (tcDevicetoInfo)

IF VARTYPE(tcDevicetoInfo) <> "C"
	return ''
ENDIF

DECLARE INTEGER CloseHandle IN kernel32 INTEGER hObject
DECLARE INTEGER CreateFile IN kernel32 STRING lpFileName, INTEGER dwDesiredAccess, INTEGER dwShareMode, ;
    INTEGER lpSecurityAttributes, INTEGER dwCreationDisposition, INTEGER dwFlagsAndAttributes, ;
    INTEGER hTemplateFile

DECLARE INTEGER DeviceIoControl IN kernel32 INTEGER hDevice, INTEGER dwIoControlCode, STRING @lpInBuffer, ;
    LONG nInBufferSize, STRING @lpOutBuffer, LONG nOutBufferSize, INTEGER @lpBytesReturned, ;
    INTEGER lpOverlapped

DECLARE INTEGER GetLogicalDriveStrings IN Win32API INTEGER buflen, STRING @buf

DECLARE INTEGER GetDriveType IN kernel32 ;
    STRING nDrive

DECLARE INTEGER GetVolumeInformation IN Win32API ;
    STRING lpRootPathName, STRING @lpVolumeNameBuffer, ;
    INTEGER nVolumeNameSize, LONG @lpVolumeSerialNumber, ;
    INTEGER @lpMaximumComponentLength, INTEGER @lpFileSystemFlags, ;
    STRING @lpFileSystemNameBuffer, INTEGER nFileSystemNameSize

    m.vnb=REPLICATE(CHR(0),64)
    m.vnbs=64
    m.vsn=0
    m.mcl=0
    m.fsf=0
    m.fsnb=REPLICATE(CHR(0),10)
    m.fsnbs=10

*    handle = CreateFile(tcDevicetoInfo, 0xC0000000, 3,0, 3, 0, 0)
	handle = CreateFile(tcDevicetoInfo, ; 
			      GENERIC_READ + GENERIC_WRITE ,; 
			      FILE_SHARE_READ + FILE_SHARE_WRITE, 0, OPEN_ALWAYS,; 
				  FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, 0) 
    m.sn=""
    m.model=""
    m.rev=""
    
    IF handle <> -1
        m.sci=""
        m.sci=m.sci+CHR(0)+CHR(2)+CHR(0)+CHR(0)
        m.sci=m.sci+CHR(0)
        m.sci=m.sci+CHR(1)
        m.sci=m.sci+CHR(1)
        m.sci=m.sci+CHR(0)
        m.sci=m.sci+CHR(0)
        m.sci=m.sci+CHR(0xA0)
        m.sci=m.sci+CHR(0xEC)
        m.sci=m.sci+CHR(0)
        m.sci=m.sci+CHR(0)
        m.sci=m.sci+REPL(CHR(0),499)
        m.sco=REPLICATE(CHR(0),2048)
        m.ret_buffersize=0
        m.otv=DeviceIoControl(handle, 0x7C088, @m.sci, LEN(sci), @m.sco, LEN(sco),@m.ret_buffersize, 0)
        CloseHandle(handle)
        IF m.otv<>0
            m.sn=CHRTRAN(ALLT(conv21(SUBSTR(m.sco,37,20))),CHR(0),"")
            m.rev=CHRTRAN(ALLT(conv21(SUBSTR(m.sco,63,8))),CHR(0),"")
            m.model=CHRTRAN(ALLT(conv21(SUBSTR(m.sco,71,40))),CHR(0),"")
        ENDIF
    ENDIF
    IF EMPTY(m.sn)
 	    m.sn=""
 *   	handle = CreateFile(tcDevicetoInfo, 0xC0000000, 3,0, 3, 0, 0)
 		handle = CreateFile(tcDevicetoInfo, ; 
			      GENERIC_READ + GENERIC_WRITE ,; 
			      FILE_SHARE_READ + FILE_SHARE_WRITE, 0, OPEN_ALWAYS,; 
				  FILE_ATTRIBUTE_NORMAL + FILE_FLAG_SEQUENTIAL_SCAN, 0) 
       IF handle <> -1
            m.sn=""
            m.model=""
            m.rev=""
            m.sci=REPLICATE(CHR(0),1024)
            m.sco=REPLICATE(CHR(0),1024)
            m.ret_buffersize=0
            m.otv=DeviceIoControl(handle, 0x2D1400, @m.sci, LEN(sci), @m.sco,LEN(sco), @m.ret_buffersize, 0)
            CloseHandle(handle)
            IF m.otv<>0
                m.pos0=ASC(SUBSTR(m.sco,13,1))
                m.pos1=ASC(SUBSTR(m.sco,17,1))
                IF m.pos0>0
                    m.pos1=m.pos0
                ENDIF
                m.pos2=ASC(SUBSTR(m.sco,21,1))
                m.pos3=ASC(SUBSTR(m.sco,25,1))
                m.model=SUBSTR(m.sco,m.pos1+1,m.pos2-m.pos1)
                m.pos4=AT(CHR(0),m.model)
                IF m.pos4>0
                    m.model=ALLT(CHRTRAN(m.model,CHR(0),""))
                ENDIF
                IF m.pos3>m.pos2
                    m.rev=SUBSTR(m.sco,m.pos2+1,m.pos3-m.pos2)
                ELSE
                    m.rev=SUBSTR(m.sco,m.pos2+1)
                ENDIF
                m.pos4=AT(CHR(0),m.rev)
                IF m.pos4>0
                    m.rev=ALLT(LEFT(m.rev,m.pos4-1))
                ENDIF
                IF m.pos3>0
                    m.pos3=m.pos3+1
                    m.sco1=SUBSTR(m.sco, m.pos3,40) m.sco1=ALLT(m.sco1)
                    m.sn=""
                    m.pos3=1
                    FOR m.j=1 TO 20
                        m.ch1=CHR(EVAL("0x"+ALLT(SUBSTR(m.sco1,m.pos3,2))))
                        m.pos3=m.pos3+2
                        m.ch2=CHR(EVAL("0x"+ALLT(SUBSTR(m.sco1,m.pos3,2))))
                        m.pos3=m.pos3+2
                        m.sn=m.sn+m.ch2+m.ch1
                    ENDFOR
                    m.sn=ALLT(CHRTRAN(m.sn,CHR(0),""))
                ELSE
                    m.sn=""
                ENDIF
            ENDIF
        ENDIF
    ENDIF
    m.str1=''
    lcinfo = m.str1
    lcinfo = lcinfo + CHR(13)
    IF TYPE('m.vsn') = "N"
    	m.vsn = ALLTRIM(STR(m.vsn))
    ENDIF
    lcinfo = lcinfo + "VolSN: " + STRTRAN(m.vsn,CHR(0),'') + CHR(13)
    lcinfo = lcinfo + "Type: "+ STRTRAN(m.fsnb,CHR(0),"") + CHR(13)
    lcinfo = lcinfo + "Model: " + STRTRAN(m.model,CHR(0),'') + CHR(13)
    lcinfo = lcinfo + "Revision: " + STRTRAN(m.rev,CHR(0),'') + CHR(13)
    lcinfo = lcinfo + "Serial #: " + STRTRAN(m.sn,CHR(0),'')
	?STRTRAN(lcinfo,CHR(13),CHR(10))
	IF !EMPTY(m.sn) .or. !EMPTY(m.rev) .or. !EMPTY(m.model) .or. !EMPTY(m.vsn) .or. !EMPTY(m.fsnb)
		MESSAGEBOX(lcinfo)
	ENDIF
RETURN
	
FUNCTION conv21
    LPARAMETERS m.str
    IF LEN(m.str)%2=1
        m.str=m.str+" "
    ENDIF
    LOCAL m.i, m.str2
    m.str2=""
    FOR m.i=1 TO LEN(m.str)
        m.str2=m.str2+SUBSTR(m.str,m.i+IIF(m.i%2=0,-1,1),1)
    NEXT
    RETURN m.str2
>>OK
>>i will send the form for you .
>>please wait
>>
>>>Reza,
>>>
>>>I replied to Robert's email at first accidentally...
>>>
>>>I am struggling with the same thing that Robert was corresponding with you about and wonder if I might ask for your assistance to in the form of some sample code.
>>>
>>>
>>>
>>>>Dear Robert,
>>>>I sent a sample for you in your email.please check them.
>>>>I must say this to you that jimtest form is from my dear friend Jim Livermore Member #010843
>>>>He help me till i can read weight from scale .
>>>>Another form i found from google search. perhaps in unvirsalthread! its good form.
>>>>
>>>>
>>>>>James,
>>>>>
>>>>>Thanks ... this looks exactly like what I'm looking for ... I've only used ActiveX controls a few times so the code examples will help a lot.
>>>>>
>>>>>Thanks again,
>>>>>Robert Wright
>>>>>
>>>>>>MSCOMM is an activex controls that comes with foxpro. Go to tools->options->controls and select ActiveX controls. You need to then check the Microsoft >Communications Control. Now you can drop that control onto a form.
>>>>>
>>>>>>Looks like your application will have to be looking for data all the time. >There are events on the control that checks for data.
>>>>>
>>>>>>Re: MSComm Documentation Message #705364
>>>>>
>>>>>>James,
>>>>>>
>>>>>>Each PC will has an electronic scale attached to either the serial port or USB port. When a package is placed on the scale, the scale then sends the communication via the ports to the PC. This is a setup used by UPS for sending weights to their software program. However, we need to make some changes in our database based on the weights of the pacakages before the UPS software creates the shipping label so I'd like to do it using a FoxPro application.
>>>>>>
>>>>>>What's MSCOMM?
>>>>>>
>>>>>>Thanks
>>>>>>Robert
>>>>>>
>>>>>>>You can use mscomm to do that using a serial port. Are you going to have to >request the data or is it going to be a steady feed?
>>>>>>
>>>>>>>I've just been asked to develop an application that will need to pull weights from a scale via a serial port and/or USB port. Can someone tell me were I can find some info how to read data through serial & USB ports using VFP?
>>>>>>>
>>>>>>>Thanks,
>>>>>>>Robert
>
>Reza
>
>Any chance you could send a copy of the form to me at colin@colin-northway.com?
>
>Thanks very much
>
>Colin
.·*´¨)
.·`TCH
(..·*

010000110101001101101000011000010111001001110000010011110111001001000010011101010111001101110100
"When the debate is lost, slander becomes the tool of the loser." - Socrates
Vita contingit, Vive cum eo. (Life Happens, Live With it.)
"Life is not measured by the number of breaths we take, but by the moments that take our breath away." -- author unknown
"De omnibus dubitandum"
Previous
Reply
Map
View

Click here to load this message in the networking platform