获取locationid,pid,vid 唯一的标识具体如下:
IDE:XCode Version 10.1 (10B61)
依赖库:IOKit.framework
语言:Objective-C
需要注意的:IOUSBDeviceInterface500这个接口需要根据具体的macOS版本决定,最新版系统使用老接口如:IOUSBDeviceInterface 就会读取不到usb设备
参考博文:https://blog.csdn.net/u011533780/article/details/79718386
对应demo:https://github.com/FlowWaterMe/checkUsb
usb读取类:
usb.h:
#ifndef Global_USB_h
#define Global_USB_h
UInt32 GetUsbLocation(long vid,long pid);
int CheckUsbDevice(long vid,long pid);
long HexToLong(const char *stringValue);
const char *ToHex(uint16_t tmpid);
int CheckUsbDeviceInPort(long vid,long pid,int port);
char* GetUsbSerialNumber(long vid,long pid);
char *GetUsbVersion(long vid,long pid);
unsigned int CheckUSBHID(unsigned short vendor_id, unsigned short product_id,unsigned int locationid,int itimeout);
void ScanUSB(void *refCon, io_iterator_t iterator);
NSMutableArray* GetUSBDeviceListByDeviceName(NSString *devName);
#endif
#include <iostream>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOMessage.h>
#include <IOKit/IOCFPlugIn.h>
#include <IOKit/usb/IOUSBLib.h>
#import <Cocoa/Cocoa.h>
#define kMyVendorID 0x9011 //0x0424//1351
#define kMyProductID 0x2514 //0x2514//8193
#define FT4232_VID 0x0403
#define FT4232_PID 0x6011
#define TG_CMD_BUFFER_LEN 64
BOOL bScanAllDevice = TRUE;
typedef struct MyPrivateData {
io_object_t notification;
IOUSBDeviceInterface **deviceInterface;
CFStringRef deviceName;
UInt32 locationID;
} MyPrivateData;
static IONotificationPortRef gNotifyPort;
static io_iterator_t gAddedIter;
#define kDeviceName @"device_name"
#define kLocationID @"location_id"
struct Context {
BOOL bScanAlldevice;
NSMutableArray * arrDevList;
};
//================================================================================================
//
// DeviceNotification
//
// This routine will get called whenever any kIOGeneralInterest notification happens. We are
// interested in the kIOMessageServiceIsTerminated message so that's what we look for. Other
// messages are defined in IOMessage.h.
//
//================================================================================================
void DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument)
{
kern_return_t kr;
MyPrivateData *privateDataRef = (MyPrivateData *) refCon;
if (messageType == kIOMessageServiceIsTerminated) {
fprintf(stderr, "Device removed.\n");
// Dump our private data to stderr just to see what it looks like.
fprintf(stderr, "privateDataRef->deviceName: ");
CFShow(privateDataRef->deviceName);
fprintf(stderr, "privateDataRef->locationID: 0x%x.\n\n", (unsigned int)privateDataRef->locationID);
// Free the data we're no longer using now that the device is going away
CFRelease(privateDataRef->deviceName);
if (privateDataRef->deviceInterface) {
kr = (*privateDataRef->deviceInterface)->Release(privateDataRef->deviceInterface);
}
kr = IOObjectRelease(privateDataRef->notification);
free(privateDataRef);
}
}
//================================================================================================
//
// DeviceAdded
//
// This routine is the callback for our IOServiceAddMatchingNotification. When we get called
// we will look at all the devices that were added and we will:
//
// 1. Create some private data to relate to each device (in this case we use the service's name
// and the location ID of the device
// 2. Submit an IOServiceAddInterestNotification of type kIOGeneralInterest for this device,
// using the refCon field to store a pointer to our private data. When we get called with
// this interest notification, we can grab the refCon and access our private data.
//
//================================================================================================
UInt32 usbAddress=0;
char serialnumber[128];
char USBVersion[128];
static bool getUSBVersion(io_service_t hidDevice,io_name_t version)
{
kern_return_t result;
CFMutableDictionaryRef hidProperties = 0;
result = IORegistryEntryCreateCFProperties(hidDevice, &hidProperties, kCFAllocatorSystemDefault, kNilOptions);
if ((result == KERN_SUCCESS) && hidProperties)
{
CFNumberRef versionRef = (CFNumberRef)CFDictionaryGetValue(hidProperties, CFSTR("bcdDevice"));
if (versionRef)
{
int ver=0;
CFNumberGetValue(versionRef, kCFNumberIntType, &ver);
CFRelease(versionRef);
int h=ver/0x100;
int w=ver%0x100;
sprintf(version, "%x.%02x",h,w);
return true;
}
}
return false;
}
//add for get usb serial number
static void getStringDescriptor(IOUSBDeviceInterface182 **deviceInterface,
uint8_t index,
io_name_t stringBuffer)
{
io_name_t buffer;
memset(stringBuffer, 0, 128);
IOUSBDevRequest request = {
.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice),
.bRequest = kUSBRqGetDescriptor,
.wValue = static_cast<UInt16>((kUSBStringDesc << 8) | index),
.wIndex = 0x409,
.wLength = sizeof(buffer),
.pData = buffer
};
kern_return_t result;
result = (*deviceInterface)->DeviceRequest(deviceInterface, &request);
if (result != KERN_SUCCESS) {
return;
}
uint32_t count = 0;
for (uint32_t j = 2; j < request.wLenDone; j += 2) {
stringBuffer[count++] = buffer[j];
}
stringBuffer[count] = '\0';
}
static void getUDID(io_service_t device, io_name_t udidBuffer)
{
kern_return_t result;
SInt32 score;
IOCFPlugInInterface **plugin = NULL;
result = IOCreatePlugInInterfaceForService(device,
kIOUSBDeviceUserClientTypeID,
kIOCFPlugInInterfaceID,
&plugin,
&score);
if (result != KERN_SUCCESS) {
return;
}
IOUSBDeviceInterface182 **deviceInterface = NULL;
result = (*plugin)->QueryInterface(plugin,
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID182),
(void **)&deviceInterface);
if (result != KERN_SUCCESS) {
IODestroyPlugInInterface(plugin);
return;
}
IODestroyPlugInInterface(plugin);
UInt8 index;
(*deviceInterface)->USBGetSerialNumberStringIndex(deviceInterface, &index);
getStringDescriptor(deviceInterface, index, udidBuffer);
}
long HexToLong(const char*stringValue)
{
Byte pbuf[TG_CMD_BUFFER_LEN];
bzero(pbuf, TG_CMD_BUFFER_LEN);
char *pdata = (char *)stringValue;
long len = strlen(pdata);
memcpy(pbuf, pdata, len);
int offset = 0;
long result = 0;
int temp = 0;
while(pbuf[offset] !=