1 Star 0 Fork 0

wmdng/winusb

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
setup.go 7.43 KB
一键复制 编辑 原始数据 按行查看 历史
wmdng 提交于 2024-11-04 15:23 +08:00 . add instanceID scan
package winusb
import (
"fmt"
"strings"
"syscall"
"unsafe"
)
type SetupDi struct {
setupapi *syscall.DLL
setupDiGetClassDevs *syscall.Proc
setupDiDestroyDeviceInfoList *syscall.Proc
setupDiEnumDeviceInfo *syscall.Proc
setupDiGetDeviceInstanceId *syscall.Proc
setupDiEnumDeviceInterfaces *syscall.Proc
setupDiGetDeviceInterfaceDetail *syscall.Proc
}
func NewSetupDi() (* SetupDi, error) {
var sdi SetupDi
sdll, err := syscall.LoadDLL( "SetupAPI.dll" )
if err != nil {
return nil, err
}
sdi.setupapi = sdll
sdi.setupDiGetClassDevs, err = sdll.FindProc( "SetupDiGetClassDevsW" )
if err != nil {
return nil, err
}
sdi.setupDiDestroyDeviceInfoList, err = sdll.FindProc( "SetupDiDestroyDeviceInfoList" )
if err != nil {
return nil, err
}
sdi.setupDiEnumDeviceInfo, err = sdll.FindProc( "SetupDiEnumDeviceInfo" )
if err != nil {
return nil, err
}
sdi.setupDiGetDeviceInstanceId, err = sdll.FindProc( "SetupDiGetDeviceInstanceIdW" )
if err != nil {
return nil, err
}
sdi.setupDiEnumDeviceInterfaces, err = sdll.FindProc( "SetupDiEnumDeviceInterfaces" )
if err != nil {
return nil, err
}
sdi.setupDiGetDeviceInterfaceDetail, err = sdll.FindProc( "SetupDiGetDeviceInterfaceDetailW" )
if err != nil {
return nil, err
}
return &sdi, nil
}
type SP_DEVICE_INTERFACE_DATA struct {
cbsiz uint32
guid syscall.GUID
flags uint32
rsved uintptr
}
func (sdi * SetupDi)GetDetailPath( hdi uintptr, did uintptr ) (string, error) {
var bret uintptr
var reqlen uint32
bret, _, err := sdi.setupDiGetDeviceInterfaceDetail.Call( hdi, did, 0, 0, uintptr( unsafe.Pointer(&reqlen)), 0 )
if bret != 0 {
// 结果必须是 false.
return "", syscall.ERROR_OPERATION_ABORTED
}
if eno, ok := err.(syscall.Errno); ok {
if eno != syscall.ERROR_INSUFFICIENT_BUFFER {
fmt.Println( "eno =", uint32(eno) )
return "", err
}
} else {
return "", err
}
//
tary := make( []uint16, (reqlen/2 + 1) )
tary[0] = 8;
tary[1] = 0;
bret, _, err = sdi.setupDiGetDeviceInterfaceDetail.Call( hdi, did, uintptr( unsafe.Pointer(&tary[0])), uintptr(reqlen), uintptr( unsafe.Pointer(&reqlen)), 0 )
if bret == 0 {
return "", err
}
//
upth := syscall.UTF16ToString( tary[2:] )
return upth, nil
}
func (sdi * SetupDi)ScanUsbDev( vid uint16, pid uint16 ) (string, error) {
var bret uintptr
var sdid SP_DEVICE_INTERFACE_DATA
var patn string
patn = fmt.Sprintf( "\\\\?\\usb#vid_%04x&pid_%04x#", vid, pid )
// GUID_DEVINTERFACE_USB_DEVICE
ugid := syscall.GUID{ Data1: 0xa5dcbf10, Data2:0x6530, Data3 :0x11d2, Data4: [8]byte{ 0x90, 0x1f, 0x00, 0xc0, 0x4f, 0xb9, 0x51, 0xed } }
// DIGCF_PRESENT = 0x00000002
// DIGCF_DEVICEINTERFACE 0x00000010
hdi, _, err := sdi.setupDiGetClassDevs.Call( uintptr( unsafe.Pointer(&ugid) ), 0, 0, uintptr(0x12) )
if hdi == uintptr( syscall.InvalidHandle ) {
return "", err
}
defer sdi.setupDiDestroyDeviceInfoList.Call( hdi )
//
for i:=0; i<256; i++ {
sdid.cbsiz = uint32( unsafe.Sizeof(sdid) )
bret, _, err = sdi.setupDiEnumDeviceInterfaces.Call( hdi, 0, uintptr( unsafe.Pointer(&ugid) ), uintptr(i), uintptr( unsafe.Pointer(&sdid)) )
if bret == 0 {
// fmt.Println( "index =", i )
return "", err
}
upth, err := sdi.GetDetailPath( hdi, uintptr( unsafe.Pointer(&sdid) ) )
if err != nil {
return "", err
}
//
if strings.HasPrefix( upth, patn ) {
return upth, nil
}
}
return "", syscall.ERROR_NOT_FOUND
}
type SP_DEVINFO_DATA struct {
cbSize uint32
clsGuid syscall.GUID
devInst uint32
rsvd uintptr
}
func (sdi * SetupDi)GetInstanceID( hdi uintptr, sdd uintptr ) (string, error) {
var bret uintptr
var reqlen uint32
bret, _, err := sdi.setupDiGetDeviceInstanceId.Call( hdi, sdd, 0, 0, uintptr( unsafe.Pointer(&reqlen)) )
if bret != 0 {
// 结果必须是 false.
return "", syscall.ERROR_OPERATION_ABORTED
}
if eno, ok := err.(syscall.Errno); ok {
if eno != syscall.ERROR_INSUFFICIENT_BUFFER {
fmt.Println( "eno =", uint32(eno) )
return "", err
}
} else {
return "", err
}
//
tary := make( []uint16, (reqlen + 1) )
bret, _, err = sdi.setupDiGetDeviceInstanceId.Call( hdi, sdd, uintptr( unsafe.Pointer(&tary[0])), uintptr(reqlen + 1), 0 )
if bret == 0 {
return "", err
}
//
upth := syscall.UTF16ToString( tary[:] )
return upth, nil
}
/*
port, serial, ???
*/
func (sdi * SetupDi)EnumUsbDev( vid uint16, pid uint16 ) ([]string, error) {
var bret uintptr
var sdd SP_DEVINFO_DATA
var patn string
var rult []string
// USB\VID_0BDA&PID_4853
patn = fmt.Sprintf( "USB\\VID_%04X&PID_%04X\\", vid, pid )
// GUID_DEVINTERFACE_USB_DEVICE
ugid := syscall.GUID{ Data1: 0xa5dcbf10, Data2:0x6530, Data3 :0x11d2, Data4: [8]byte{ 0x90, 0x1f, 0x00, 0xc0, 0x4f, 0xb9, 0x51, 0xed } }
// DIGCF_PRESENT = 0x00000002
// DIGCF_DEVICEINTERFACE 0x00000010
hdi, _, err := sdi.setupDiGetClassDevs.Call( uintptr( unsafe.Pointer(&ugid) ), 0, 0, uintptr(0x12) )
if hdi == uintptr( syscall.InvalidHandle ) {
return nil, err
}
defer sdi.setupDiDestroyDeviceInfoList.Call( hdi )
//
for i:=0; i<256; i++ {
sdd.cbSize = uint32( unsafe.Sizeof(sdd) )
bret, _, err = sdi.setupDiEnumDeviceInfo.Call( hdi, uintptr(i), uintptr( unsafe.Pointer(&sdd)) )
if bret == 0 {
if erid, ok := err.(syscall.Errno); ok {
// ERROR_NO_MORE_ITEMS, 259(0x103)
if uintptr(erid) == 259 {
return rult, nil
}
}
return nil, err
}
//
isid, err := sdi.GetInstanceID( hdi, uintptr( unsafe.Pointer(&sdd)) )
if err != nil {
return nil, err
}
// filter by pid.
if !strings.HasPrefix( isid, patn ) {
continue
}
//
rult = append( rult, isid )
// fmt.Printf( "%v: %s\n", i, isid )
}
return rult, nil
}
/*
使用 InstanceID 查找 SP_DEVINFO_DATA.
再使用 SP_DEVINFO_DATA 来获取 DetailPath.
*/
func (sdi * SetupDi)TransFullPath( insid string ) (string, error) {
var bret uintptr
var sdd SP_DEVINFO_DATA
var sdid SP_DEVICE_INTERFACE_DATA
// GUID_DEVINTERFACE_USB_DEVICE
ugid := syscall.GUID{ Data1: 0xa5dcbf10, Data2:0x6530, Data3 :0x11d2, Data4: [8]byte{ 0x90, 0x1f, 0x00, 0xc0, 0x4f, 0xb9, 0x51, 0xed } }
// DIGCF_PRESENT = 0x00000002
// DIGCF_DEVICEINTERFACE 0x00000010
hdi, _, err := sdi.setupDiGetClassDevs.Call( uintptr( unsafe.Pointer(&ugid) ), 0, 0, uintptr(0x12) )
if hdi == uintptr( syscall.InvalidHandle ) {
return "", err
}
defer sdi.setupDiDestroyDeviceInfoList.Call( hdi )
//
for i:=0; i<256; i++ {
sdd.cbSize = uint32( unsafe.Sizeof(sdd) )
bret, _, err = sdi.setupDiEnumDeviceInfo.Call( hdi, uintptr(i), uintptr( unsafe.Pointer(&sdd)) )
if bret == 0 {
return "", err
}
//
isid, err := sdi.GetInstanceID( hdi, uintptr( unsafe.Pointer(&sdd)) )
if err != nil {
return "", err
}
//
if isid == insid {
break
}
}
//
sdid.cbsiz = uint32( unsafe.Sizeof(sdid) )
bret, _, err = sdi.setupDiEnumDeviceInterfaces.Call( hdi, uintptr( unsafe.Pointer(&sdd)), uintptr( unsafe.Pointer(&ugid) ), uintptr(0), uintptr( unsafe.Pointer(&sdid)) )
if bret == 0 {
// fmt.Println( "index =", i )
return "", err
}
upth, err := sdi.GetDetailPath( hdi, uintptr( unsafe.Pointer(&sdid) ) )
if err != nil {
return "", err
}
return upth, nil
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/wmdng/winusb.git
git@gitee.com:wmdng/winusb.git
wmdng
winusb
winusb
f5a7ab33d64f

搜索帮助