参考:
WIN10+VFP9调试,有些函数或命令VFP6不支持,要自己写相应的功能函数。
**
** 枚举USB设备获取USB序列号
**
CLEAR
#DEFINE GENERIC_WRITE 0x40000000
#DEFINE FILE_SHARE_WRITE 0x00000002
#DEFINE OPEN_EXISTING 3
#DEFINE INVALID_HANDLE_VALUE -1
#DEFINE BUFFER_SIZE 2048
#DEFINE FILE_DEVICE_USB 0x00000022
#DEFINE HCD_GET_DRIVERKEY_NAME 265
#DEFINE HCD_GET_ROOT_HUB_NAME 258
#DEFINE USB_GET_NODE_INFORMATION 258
#DEFINE USB_GET_NODE_CONNECTION_INFORMATION 259
#DEFINE USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION 260
#DEFINE USB_GET_NODE_CONNECTION_NAME 261
#DEFINE METHOD_BUFFERED 0
#DEFINE FILE_ANY_ACCESS 0
#DEFINE IOCTL_GET_HCD_DRIVERKEY_NAME CTL_CODE(FILE_DEVICE_USB,;
HCD_GET_DRIVERKEY_NAME,;
METHOD_BUFFERED,;
FILE_ANY_ACCESS)
#DEFINE IOCTL_USB_GET_ROOT_HUB_NAME CTL_CODE(FILE_DEVICE_USB,;
HCD_GET_ROOT_HUB_NAME,;
METHOD_BUFFERED,;
FILE_ANY_ACCESS)
#DEFINE IOCTL_USB_GET_NODE_INFORMATION CTL_CODE(FILE_DEVICE_USB,;
USB_GET_NODE_INFORMATION,;
METHOD_BUFFERED,;
FILE_ANY_ACCESS)
#DEFINE IOCTL_USB_GET_NODE_CONNECTION_INFORMATION CTL_CODE(FILE_DEVICE_USB,;
USB_GET_NODE_CONNECTION_INFORMATION,;
METHOD_BUFFERED,;
FILE_ANY_ACCESS)
#DEFINE IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION CTL_CODE(FILE_DEVICE_USB,;
USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,;
METHOD_BUFFERED,;
FILE_ANY_ACCESS)
#DEFINE IOCTL_USB_GET_NODE_CONNECTION_NAME CTL_CODE(FILE_DEVICE_USB,;
USB_GET_NODE_CONNECTION_NAME,;
METHOD_BUFFERED,;
FILE_ANY_ACCESS)
#DEFINE USB_STRING_DESCRIPTOR_TYPE 0x03
DECLARE LONG CreateFile IN Kernel32 STRING@, LONG, LONG, STRING@, LONG, LONG, LONG
DECLARE LONG CloseHandle IN Kernel32 LONG
DECLARE LONG DeviceIoControl IN Kernel32 LONG, LONG, STRING@, LONG, STRING@, LONG, LONG@, LONG
DECLARE LONG GetSystemDefaultLangID IN Kernel32
CREATE CURSOR dt (Property C(10), Value C(50))
EnumUsbDevice()
GO TOP
BROWSE
CLEAR DLLS
RETURN
FUNCTION CTL_CODE(DeviceType, Function, Method, Access)
* #define CTL_CODE(DeviceType, Function, Method, Access) (
* ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)
* )
RETURN BITOR(BITLSHIFT(DeviceType, 16), BITLSHIFT(Access, 14), BITLSHIFT(Function, 2), Method)
ENDFUNC
FUNCTION EnumUsbDevice()
LOCAL i, hHCD, szHCDPath, szHUBName
FOR i = 0 TO 9 && 假定最多有10个主控
szHCDPath = "\\.\HCD" + TRANSFORM(i)
hHCD = CreateFile(@szHCDPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0)
IF hHCD == INVALID_HANDLE_VALUE
EXIT
ENDIF
szHUBName = GetHUBName(hHCD)
IF !ISNULL(szHUBName)
GetHUB(szHUBName) && 取集线器数据
ENDIF
CloseHandle(hHCD)
ENDFOR
ENDFUNC
FUNCTION GetHUB(szHUBName)
LOCAL i, hHUB, szHUBPath, szBuffer, dwReturnedSize, dbPorts
szHUBPath = "\\.\" + szHUBName
hHUB = CreateFile(@szHUBPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0)
IF hHUB != INVALID_HANDLE_VALUE
szBuffer = REPLICATE(0h00, BUFFER_SIZE)
dwReturnedSize = 0
IF DeviceIoControl(hHUB,;
IOCTL_USB_GET_NODE_INFORMATION,;
@szBuffer, BUFFER_SIZE,;
@szBuffer, BUFFER_SIZE,;
@dwReturnedSize,;
0) != 0
* USB_NODE_INFORMATION 结构
* 端口数,dbPports = szBuffer->u.HubInformation.HubDescriptor.bNumberOfPorts
dbPorts = CTOBIN(SUBSTR(szBuffer, 7, 1), "1RS")
FOR i = 1 TO dbPorts
GetHUBPort(hHUB, i) && 取各端口数据
ENDFOR
ENDIF
CloseHandle(hHUB)
ENDIF
ENDFUNC
FUNCTION GetHUBPort(hHUB, dbPortIndex)
LOCAL szBuffer, dwReturnedSize, ddConnectionIndex
LOCAL iManufacturer, iProduct, iSerialNumber, idVendor, idProduct, bcdDevice
LOCAL DeviceIsHub, ConnectionStatus
* USB_NODE_CONNECTION_INFORMATION 结构
* 端口号,szBuffer->ConnectionIndex = dbPortIndex
szBuffer = BINTOC(dbPortIndex, "4RS") + REPLICATE(0h00, BUFFER_SIZE - 4)
dwReturnedSize = 0
IF DeviceIoControl(hHUB,;
IOCTL_USB_GET_NODE_CONNECTION_INFORMATION,;
@szBuffer, BUFFER_SIZE,;
@szBuffer, BUFFER_SIZE,;
@dwReturnedSize,;
0) != 0
ddConnectionIndex = CTOBIN(LEFT(szBuffer, 4), "4RS")
IF ddConnectionIndex > 0
* 集线器标志,szBuffer->DeviceIsHub
DeviceIsHub = CTOBIN(SUBSTR(szBuffer, 25, 1), "1RS")
IF DeviceIsHub == 1 && 是集线器
szBuffer = BINTOC(dbPortIndex, "4RS") + REPLICATE(0h00, BUFFER_SIZE - 4)
dwReturnedSize = 0
IF DeviceIoControl(hHUB,;
IOCTL_USB_GET_NODE_CONNECTION_NAME,;
@szBuffer, BUFFER_SIZE,;
@szBuffer, BUFFER_SIZE,;
@dwReturnedSize,;
0) != 0
szBuffer = RTRIM(STRCONV(SUBSTR(szBuffer, 9, dwReturnedSize - 8), 6), 0h00, " ")
GetHUB(szBuffer) && 遍历集线器
ENDIF
ELSE
* szBuffer->ConnectionStatus
ConnectionStatus = CTOBIN(SUBSTR(szBuffer, 32, 1), "1RS")
IF ConnectionStatus == 1
* USB_NODE_CONNECTION_INFORMATION 结构
idVendor = CTOBIN(SUBSTR(szBuffer, 13, 2) + 0h0000, "4RS")
idProduct = CTOBIN(SUBSTR(szBuffer, 15, 2) + 0h0000, "4RS")
bcdDevice = CTOBIN(SUBSTR(szBuffer, 17, 2) + 0h0000, "4RS")
INSERT INTO dt VALUES ("供应商ID", IIF(idVendor > 0, TRANSFORM(idVendor), "NULL"))
INSERT INTO dt VALUES (" 产品ID", IIF(idProduct > 0, TRANSFORM(idProduct), "NULL"))
INSERT INTO dt VALUES ("设备编码", IIF(bcdDevice > 0, TRANSFORM(bcdDevice), "NULL"))
* iManufacturer、iProduct 和 iSerialNumber 域指向一个串描述符,
* 该串描述符用人类可读的语言描述设备生产厂商、产品和序列号。
iManufacturer = CTOBIN(SUBSTR(szBuffer, 19, 1), "1RS")
iProduct = CTOBIN(SUBSTR(szBuffer, 20, 1), "1RS")
iSerialNumber = CTOBIN(SUBSTR(szBuffer, 21, 1), "1RS")
INSERT INTO dt VALUES ("厂商描述", GetStringDescriptor(hHUB, ddConnectionIndex, iManufacturer))
INSERT INTO dt VALUES ("产品描述", GetStringDescriptor(hHUB, ddConnectionIndex, iProduct))
INSERT INTO dt VALUES (" 序列号", GetStringDescriptor(hHUB, ddConnectionIndex, iSerialNumber))
INSERT INTO dt VALUES ("", "")
ENDIF
ENDIF
ENDIF
ENDIF
ENDFUNC
FUNCTION GetHCDDriverKeyName(hHCD)
LOCAL szBuffer, dwReturnedSize
szBuffer = REPLICATE(0h00, BUFFER_SIZE)
dwReturnedSize = 0
IF DeviceIoControl(hHCD,;
IOCTL_GET_HCD_DRIVERKEY_NAME,;
@szBuffer, BUFFER_SIZE,;
@szBuffer, BUFFER_SIZE,;
@dwReturnedSize,;
0) != 0
szBuffer = STRCONV(SUBSTR(szBuffer, 5, dwReturnedSize - 4), 6)
RETURN RTRIM(szBuffer, 0h00, " ")
ENDIF
RETURN NULL
ENDFUNC
FUNCTION GetHUBName(hHostController)
LOCAL szBuffer, dwReturnedSize
szBuffer = REPLICATE(0h00, BUFFER_SIZE)
dwReturnedSize = 0
IF DeviceIoControl(hHostController,;
IOCTL_USB_GET_ROOT_HUB_NAME,;
@szBuffer, BUFFER_SIZE,;
@szBuffer, BUFFER_SIZE,;
@dwReturnedSize,;
0) != 0
szBuffer = STRCONV(SUBSTR(szBuffer, 5, dwReturnedSize - 4), 6)
RETURN RTRIM(szBuffer, 0h00, " ")
ENDIF
RETURN NULL
ENDFUNC
FUNCTION GetStringDescriptor(hHUB, dbConnectionIndex, dbDescriptorIndex)
LOCAL szBuffer, dwReturnedSize, dbLength, dbDescriptorType
IF (dbConnectionIndex < 1) OR (dbDescriptorIndex < 1)
RETURN "NULL"
ENDIF
* szBuffer->ConnectionIndex = ConnectionIndex
* szBuffer->SetupPacket.wValue = (USB_STRING_DESCRIPTOR_TYPE << 8) | DescriptorIndex
* szBuffer->SetupPacket.wIndex = GetSystemDefaultLangID()
* szBuffer->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST))
* sizeof(USB_DESCRIPTOR_REQUEST) = 12
szBuffer = BINTOC(dbConnectionIndex, "4RS") + 0h0000;
+ BINTOC(BITOR(BITLSHIFT(USB_STRING_DESCRIPTOR_TYPE, 8), dbDescriptorIndex), "2RS");
+ BINTOC(0, "2RS");
+ BINTOC(BUFFER_SIZE - 12, "2RS") + REPLICATE(0h00, BUFFER_SIZE - 12)
dwReturnedSize = 0
IF DeviceIoControl(hHUB,;
IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,;
@szBuffer, BUFFER_SIZE,;
@szBuffer, BUFFER_SIZE,;
@dwReturnedSize,;
0) != 0
* USB_STRING_DESCRIPTOR 结构
dbLength = CTOBIN(SUBSTR(szBuffer, 13, 1), "1RS")
dbDescriptorType = CTOBIN(SUBSTR(szBuffer, 14, 1), "1RS")
IF (dwReturnedSize > 1) AND (dbLength == dwReturnedSize - 12);
AND (dbDescriptorType == USB_STRING_DESCRIPTOR_TYPE);
AND (dbLength % 2 == 0)
RETURN RTRIM(STRCONV(SUBSTR(szBuffer, 15, dbLength), 6), 0h00, " ")
ELSE
RETURN "NULL"
ENDIF
ENDIF
RETURN "NULL"
ENDFUNC