关于Mac获取usb设备pid,vid,locationID的使用

本文介绍如何在Mac上通过Objective-C获取USB设备的PID、VID和LocationID。当USB设备名称因重新插拔而变化时,这些标识用于设备配置和通信。在Xcode 8.3以上环境中,引入IOKit.framework,创建checkusb工程,编写usb.h和usb.mm文件实现相关功能。详细代码可在GitHub找到。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

获取usb设备的pid, vid, locationid.

大家知道usb设备都有pid,vid,locationid,当USB设备连接电脑时,如果设备名字重新插拔后变化,那么无法获取,就得重新配置信息,然后进行通信。为此写了个程序来获取locationid,pid,vid 每个设备都有唯一的标识,所以具体情况如下:

  • 编辑环境xcode8.3以上
  • 调用的库文件IOKit.framework
  • 语言object-c

打开xcode,新建工程文件名checkusb.
添加IOkit.framework文件。
新建usb.h,usb.mm用来编写获取的vid,pid的方法模块
在xib 布局界面;
然后编辑如下代码:
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

usb.mm 部分代码

//
//  loopdelegate.h
//  checkUsb
//
//  Created by Young on 11/30/17.
//  Copyright © 2017 com.HY. All rights reserved.
//

#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) {
       
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值