Chinaunix

标题: MAC中如何访问usb 设备 [打印本页]

作者: shagpg2008    时间: 2007-05-31 15:07
标题: MAC中如何访问usb 设备
在MAC中, 访问设备是用IOKit这个通讯层, 可我就是在找到设备,打开接口的时候失败。
err = (*intf)->USBIterfaceOpen(intf);  //err 返回0xe00002c5, 是“The device is already ope
                                                           //n with exclusive access (0xe00002c5).”

我查了好多进程的信息,也没有发现哪个进程占用了这个设备。
这个在MAC中如何访问USB设备呢? 不能象UNIX一样访问,是因为我现在没有找到对应的 /dev/xxx.
谢谢!!
作者: sinoman    时间: 2007-05-31 15:40
是什么USB设备,你要做什么,没头没尾的,只给出一个返回的错误值,怎么回答你呢?
作者: shagpg2008    时间: 2007-05-31 16:20
访问U盘, 下面是源码: U盘的vid是0x10d6, pid:0x1100. 这个是MAC上面的一个例子在 /Developer/Example/IOKit/usb/USBSimple Example.


#include <stdio.h>
#include <mach/mach.h>
#include <CoreFoundation/CFNumber.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOCFPlugIn.h>
#include <IOKit/usb/IOUSBLib.h>

mach_port_t         masterPort = 0;                                // requires <mach/mach.h>
char                        outBuf[8096];
char                        inBuf[8096];

void
MyCallBackFunction(void *dummy, IOReturn result, void *arg0)
{
        //  UInt8        inPipeRef = (UInt32)dummy;
   
    printf("MyCallbackfunction: %d, %d, %d\n", (int)dummy, (int)result, (int)arg0);
    CFRunLoopStop(CFRunLoopGetCurrent());
}


void transferData(IOUSBInterfaceInterface **intf, UInt8 inPipeRef, UInt8 outPipeRef)
{
    IOReturn                        err;
    CFRunLoopSourceRef                cfSource;
    int                                i;
   
    err = (*intf)->CreateInterfaceAsyncEventSource(intf, &cfSource);
    if (err)
    {
        printf("transferData: unable to create event source, err = %08x\n", err);
        return;
    }
    CFRunLoopAddSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);
    for (i=0; i < 12; i++)
        outBuf[i] = 'R';
    err = (*intf)->WritePipeAsync(intf, outPipeRef, outBuf, 12, (IOAsyncCallback1)MyCallBackFunction, (void*)(UInt32)inPipeRef);
    if (err)
    {
        printf("transferData: WritePipeAsyncFailed, err = %08x\n", err);
        CFRunLoopRemoveSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);
        return;
    }
    printf("transferData: calling CFRunLoopRun\n");
    CFRunLoopRun();
    printf("transferData: returned from  CFRunLoopRun\n");
    CFRunLoopRemoveSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);
}


void dealWithPipes(IOUSBInterfaceInterface **intf, UInt8 numPipes)
{
    int                                        i;
    IOReturn                                err;                       
    UInt8                                inPipeRef = 0;
    UInt8                                outPipeRef = 0;
    UInt8                                direction, number, transferType, interval;
    UInt16                                maxPacketSize;
   
    // pipes are one based, since zero is the default control pipe
    for (i=1; i <= numPipes; i++)
    {
        err = (*intf)->GetPipeProperties(intf, i, &direction, &number, &transferType, &maxPacketSize, &interval);
        if (err)
        {
            printf("dealWithPipes: unable to get pipe properties for pipe %d, err = %08x\n", i, err);
            return;
        }
        if (transferType != kUSBBulk)
        {
            printf("dealWithPipes: skipping pipe %d because it is not a bulk pipe\n", i);
            continue;
        }
        if ((direction == kUSBIn) && !inPipeRef)
        {
            printf("dealWithPipes: grabbing BULK IN pipe index %d, number %d\n",i, number);
            inPipeRef = i;
        }
        if ((direction == kUSBOut) && !outPipeRef)
        {
            printf("dealWithPipes: grabbing BULK OUT pipe index %d, number %d\n", i, number);
            outPipeRef = i;
        }
    }
//    if (inPipeRef && outPipeRef)
//        transferData(intf, inPipeRef, outPipeRef);
}

//#include <IOBlockStorageDevice.h>
void dealWithInterface(io_service_t usbInterfaceRef)
{
    IOReturn                                        err;
    IOCFPlugInInterface                 **iodev = NULL;                // requires <IOKit/IOCFPlugIn.h>
    IOUSBInterfaceInterface         **intf;
    SInt32                                                score;
    UInt8                                                numPipes;
        UInt8                                                interfaceClass;
        UInt8                                                interfaceSubClass;


    err = IOCreatePlugInInterfaceForService(usbInterfaceRef, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, &iodev, &score);
        err = IOObjectRelease(usbInterfaceRef);
    if (err || !iodev)
    {
                printf("dealWithInterface: unable to create plugin. ret = %08x, iodev = %p\n", err, iodev);
                return;
    }
    err = (*iodev)->QueryInterface(iodev, CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID)&intf);
        err = IODestroyPlugInInterface(iodev);                                // done with this
        //err = (*iodev)->Release(iodev);
    if (err || !intf)
    {
                printf("dealWithInterface: unable to create a device interface. ret = %08x, intf = %p\n", err, intf);
                return;
    }
       
        //doLockUnlockMedia(1);
        /*err = (*intf)->USBInterfaceClose(intf);
        if (err)
    {
                printf("dealWithInterface: unable to close interface. ret = %08x\n", err);
                return;
    }
        */
        err = (*intf)->GetInterfaceClass(intf, &interfaceClass);
        err = (*intf)->GetInterfaceSubClass(intf, &interfaceSubClass);
       
    err = (*intf)->USBInterfaceOpen(intf);                                                         //就是在这里出错的。
    if (err != kIOReturnSuccess)
    {
                printf("dealWithInterface: unable to open interface. ret = %08x\n", err);
                (void)(*intf)->Release(intf);
                return;
    }
    err = (*intf)->GetNumEndpoints(intf, &numPipes);
    if (err)
    {
                printf("dealWithInterface: unable to get number of endpoints. ret = %08x\n", err);
                (*intf)->USBInterfaceClose(intf);
                (*intf)->Release(intf);
                return;
    }
       
    printf("dealWithInterface: found %d pipes\n", numPipes);
    if (numPipes == 0)
    {
                // try alternate setting 1
                err = (*intf)->SetAlternateInterface(intf, 1);
                if (err)
                {
                        printf("dealWithInterface: unable to set alternate interface 1. ret = %08x\n", err);
                        (*intf)->USBInterfaceClose(intf);
                        (*intf)->Release(intf);
                        return;
                }
                err = (*intf)->GetNumEndpoints(intf, &numPipes);
                if (err)
                {
                        printf("dealWithInterface: unable to get number of endpoints - alt setting 1. ret = %08x\n", err);
                        (*intf)->USBInterfaceClose(intf);
                        (*intf)->Release(intf);
                        return;
                }
                numPipes = 13;                  // workaround. GetNumEndpoints does not work after SetAlternateInterface
    }
   
    if (numPipes)
        dealWithPipes(intf, numPipes);
       
    err = (*intf)->USBInterfaceClose(intf);
    if (err)
    {
                printf("dealWithInterface: unable to close interface. ret = %08x\n", err);
                return;
    }
    err = (*intf)->Release(intf);
    if (err)
    {
                printf("dealWithInterface: unable to release interface. ret = %08x\n", err);
                return;
    }
}


void dealWithDevice(io_service_t usbDeviceRef)
{
    IOReturn                                                err;
    IOCFPlugInInterface                                **iodev;                // requires <IOKit/IOCFPlugIn.h>
    IOUSBDeviceInterface                        **dev;
    SInt32                                                        score;
    UInt8                                                        numConf;
    IOUSBConfigurationDescriptorPtr        confDesc;
    IOUSBFindInterfaceRequest                interfaceRequest;
    io_iterator_t                                        iterator;
    io_service_t                                        usbInterfaceRef;
   
    err = IOCreatePlugInInterfaceForService(usbDeviceRef, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &iodev, &score);
    if (err || !iodev)
    {
                printf("dealWithDevice: unable to create plugin. ret = %08x, iodev = %p\n", err, iodev);
                return;
    }
       

    err = (*iodev)->QueryInterface(iodev, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID)&dev);
        IODestroyPlugInInterface(iodev);                                // done with this

    if (err || !dev)
    {
                printf("dealWithDevice: unable to create a device interface. ret = %08x, dev = %p\n", err, dev);
                return;
    }
       
        err = (*dev)->ResetDevice(dev);//(*iodev)->

       
    err = (*dev)->USBDeviceOpen(dev);
    if (err)
    {
                printf("dealWithDevice: unable to open device. ret = %08x\n", err);
                return;
    }       
       
        if (err)
    {
                printf("dealWithDevice: unable to reset device. ret = %08x\n", err);
                //return;
    }
   
        err = (*dev)->GetNumberOfConfigurations(dev, &numConf);
    if (err || !numConf)
    {
                printf("dealWithDevice: unable to obtain the number of configurations. ret = %08x\n", err);
        (*dev)->USBDeviceClose(dev);
        (*dev)->Release(dev);
                return;
    }
    printf("dealWithDevice: found %d configurations\n", numConf);
    err = (*dev)->GetConfigurationDescriptorPtr(dev, 0, &confDesc);                        // get the first config desc (index 0)
    if (err)
    {
                printf("dealWithDevice:unable to get config descriptor for index 0\n");
        (*dev)->USBDeviceClose(dev);
        (*dev)->Release(dev);
                return;
    }/*
    err = (*dev)->SetConfiguration(dev, confDesc->bConfigurationValue);
    if (err)
    {
                printf("dealWithDevice: unable to set the configuration\n");
        (*dev)->USBDeviceClose(dev);
        (*dev)->Release(dev);
                return;
    }*/
   
    interfaceRequest.bInterfaceClass = kIOUSBFindInterfaceDontCare;                // requested class
    interfaceRequest.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;                // requested subclass
    interfaceRequest.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;                // requested protocol
    interfaceRequest.bAlternateSetting = kIOUSBFindInterfaceDontCare;                // requested alt setting
   
    err = (*dev)->CreateInterfaceIterator(dev, &interfaceRequest, &iterator);
    if (err)
    {
                printf("dealWithDevice: unable to create interface iterator\n");
        (*dev)->USBDeviceClose(dev);
        (*dev)->Release(dev);
                return;
    }
   
    while ( (usbInterfaceRef = IOIteratorNext(iterator)) )
    {
                printf("found interface: %p\n", (void*)usbInterfaceRef);
                dealWithInterface(usbInterfaceRef);
                //IOObjectRelease(usbInterfaceRef);                                // no longer need this reference
    }
   
    IOObjectRelease(iterator);
    iterator = 0;

    err = (*dev)->USBDeviceClose(dev);
    if (err)
    {
                printf("dealWithDevice: error closing device - %08x\n", err);
                (*dev)->Release(dev);
                return;
    }
    err = (*dev)->Release(dev);
    if (err)
    {
                printf("dealWithDevice: error releasing device - %08x\n", err);
                return;
    }
}



int main (int argc, const char * argv[])
{
    kern_return_t                        err;
    CFMutableDictionaryRef         matchingDictionary = 0;                // requires <IOKit/IOKitLib.h>
    SInt32                                        idVendor = 0x10d6;//0x1403;//1351;
    SInt32                                        idProduct = 0x1100;//0x0001;//8193;
    CFNumberRef                                numberRef;
    io_iterator_t                        iterator = 0;
    io_service_t                        usbDeviceRef;
   
    err = IOMasterPort(MACH_PORT_NULL, &masterPort);                               
    if (err)
    {
        printf("USBSimpleExample: could not create master port, err = %08x\n", err);
        return err;
    }
        //kIOUSBDeviceClassNam = 08;
    matchingDictionary = IOServiceMatching(kIOUSBDeviceClassName);        // requires <IOKit/usb/IOUSBLib.h>
    if (!matchingDictionary)
    {
        printf("USBSimpleExample: could not create matching dictionary\n");
        return -1;
    }
    numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &idVendor);
    if (!numberRef)
    {
        printf("USBSimpleExample: could not create CFNumberRef for vendor\n");
        return -1;
    }
       
        //kUSBVendorID = 1403;
    CFDictionaryAddValue(matchingDictionary, CFSTR(kUSBVendorID), numberRef);
    CFRelease(numberRef);
    numberRef = 0;
    numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &idProduct);
    if (!numberRef)
    {
        printf("USBSimpleExample: could not create CFNumberRef for product\n");
        return -1;
    }
       
        //kUSBProductID = 0001;
    CFDictionaryAddValue(matchingDictionary, CFSTR(kUSBProductID), numberRef);
    CFRelease(numberRef);
    numberRef = 0;
   
    err = IOServiceGetMatchingServices(masterPort, matchingDictionary, &iterator);
    matchingDictionary = 0;                        // this was consumed by the above call
   
    while ( (usbDeviceRef = IOIteratorNext(iterator)) )
    {
                printf("Found device %p\n", (void*)usbDeviceRef);
                dealWithDevice(usbDeviceRef);
                IOObjectRelease(usbDeviceRef);                        // no longer need this reference
    }
   
    IOObjectRelease(iterator);
    iterator = 0;
   
    mach_port_deallocate(mach_task_self(), masterPort);
    return 0;
}
作者: shagpg2008    时间: 2007-05-31 16:25
就是不知道可不可以象UNIX那样,只访问文件就可以了。 通过IOKit还是很有难度的。恳请哪位大侠指教。谢谢
作者: gordonstysty    时间: 2007-06-01 14:28
什么设备?
作者: gordonstysty    时间: 2007-06-01 14:31
interface的open是独占的,hid、mass storage设备插入后相应的interface会被
系统open,不清楚你这个属于哪种情况
作者: gordonstysty    时间: 2007-06-01 14:32
:),sigh,我看贴不仔细~~;
U盘不能用你这种方式访问的,能说说你想干啥么?
作者: shagpg2008    时间: 2007-06-02 09:05
是一个mass storage设备, 我们在windows里面就可以直接用createFile访问的。可在MAC OX中找不到descriptor,也就无法访问了。
作者: gordonstysty    时间: 2007-06-04 13:08
你在windows下是createfile的string是什么?
你这样做的目的是什么呢?read data?
作者: shagpg2008    时间: 2007-06-05 10:09
createFile的string是“\\\\.\\A:”, 在windows2000以上。

这个USB设备不全是一个U盘,它里面有个单片机,我只是通过USB线来和单片机通信。通过USB线发送自定义的命令让单片机执行。我们有很多的交互过程,所以即有读也有写。我现在知道的是USB是个标准的。看MAC的本机信息象是一个HID设备。谢谢你的顶力相助。
作者: shagpg2008    时间: 2007-06-05 10:47
在windows的资源管理器上面,标明是mass storage device。呵呵
作者: gordonstysty    时间: 2007-06-05 10:49
A:是盘符?
设备是multi-interface?
那你只open另外的interface就好了,不要open mass storage的那个interface就好了
作者: shagpg2008    时间: 2007-06-05 11:12
A: 不应该是盘符。 不过我也不理解是什么东西。设备插进去以后,在windows下有一个不确定的盘符,比如G盘,在我的系统。
我在mac下获取了一下endpoint的个数,是2个。访问不了,说是interface没有打开。
作者: shagpg2008    时间: 2007-06-05 11:13
就一个interface, 我试过。
作者: gordonstysty    时间: 2007-06-05 17:39
full device descritpor贴来看下吧
作者: shagpg2008    时间: 2007-06-06 09:26
Flash Disk:

  版本:        1.10
  总线功率 (mA):        500
  速度:        最大 12 Mb/秒
  制造商:        USB
  产品 ID:        0x0001
  厂商 ID:        0x1403
作者: shagpg2008    时间: 2007-06-06 09:27
The up is in MAC OS X
作者: gordonstysty    时间: 2007-06-06 15:11
这个一点用也没有
Tyy USB Probe
作者: shagpg2008    时间: 2007-06-06 16:39
USB Probe  ?? 我没有用过,也没有搞过USB方面的开发,不知道代表什么???
作者: gordonstysty    时间: 2007-06-06 19:50
USBView用过没?
USB Probe是mac上查看usb设备的一个工具,xcode的目录下找找看
作者: shagpg2008    时间: 2007-06-09 10:15
Device Descriptor:
bcdUSB:             0x0110
bDeviceClass:         0x00
bDeviceSubClass:      0x00
bDeviceProtocol:      0x00
bMaxPacketSize0:      0x08 (
idVendor:           0x1403
idProduct:          0x0001
bcdDevice:          0x0110
iManufacturer:        0x01
iProduct:             0x02
iSerialNumber:        0x00
bNumConfigurations:   0x01

ConnectionStatus: DeviceConnected
Current Config Value: 0x01
Device Bus Speed:     Full
Device Address:       0x01
Open Pipes:              2

Endpoint Descriptor:
bEndpointAddress:     0x81
Transfer Type:        Bulk
wMaxPacketSize:     0x0040 (64)
bInterval:            0x00

Endpoint Descriptor:
bEndpointAddress:     0x02
Transfer Type:        Bulk
wMaxPacketSize:     0x0040 (64)
bInterval:            0x00
作者: gordonstysty    时间: 2007-06-10 20:16
bDeviceClass:         0x00
bDeviceSubClass:      0x00
bDeviceProtocol:      0x00

从这几个数值看,设备不是mass storage class的。你那段代码没问题。
作者: shagpg2008    时间: 2007-06-11 09:29
可是我用windows的资源管理器看的话,是这样的:
bDeviceClass:            0x08
bDeviceSubClass:      0x06
bDeviceProtocol:        0x50

是不是说我的那段代码不能用在应用程序里面,而用编译到系统内核里面去?
作者: shagpg2008    时间: 2007-06-11 09:39
那我又通过什么接口和设备进行通信呢?? 现在不知道这个设备的device file。 谢谢。
作者: shagpg2008    时间: 2007-06-13 09:10
??????
作者: sinoman    时间: 2007-06-13 14:06
原帖由 shagpg2008 于 2007-6-5 10:09 发表
createFile的string是“\\\\.\\A:”, 在windows2000以上。

这个USB设备不全是一个U盘,它里面有个单片机,我只是通过USB线来和单片机通信。通过USB线发送自定义的命令让单片机执行。我们有很多的交互过程,所 ...


你和单片机通信去管什么MASS STORAGE? 设备描述符,配置描述符号, 报告描述符,你先把这些问题搞通再分析问题。 这么多内容你多没说清楚你想做什么?
作者: shagpg2008    时间: 2007-06-16 14:26
。。。。。。。。。。。。。。。。
作者: yoyo3280    时间: 2007-09-13 19:45
标题: 如何想一個USB Mass Storage設備發消息
我也有同樣的問題:想向一個USB Mass Storage device 發送消息,但使用系統提供的sample:USBSimple Example時,在SetConfiguratiion()時會使系統將U盤推出,如果刪除這一行代碼,會在下面的USBInerfaceOpen()時會返回0xe00002c5 (-536870203)的錯誤(The device is already open with exclusive access )。如何想一個USB Mass Storage設備發消息呢? 急!急!急!
作者: xuxulong    时间: 2012-05-06 20:36
目前这个问题有人解决了吗?我也遇到了同样的问题,u盘的设备接口不能打开。而且设备文件/dev/disk1也无法打开。
open("/dev/disk1",O_RDWR | O_NONBLOCK)出现"Resource busy";
将U盘用命令卸载"diskutil umnount /dev/disk1s1", 再open("/dev/disk1",O_RDWR | O_NONBLOCK),则出现"Operation timed out";ioctl()出现“Inappropriate ioctl for device(25)”
作者: fu20    时间: 2012-05-11 00:49
哈哈,有意思。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2