无法要求USB接口与C +的libusb在Mac OS X [英] Unable to claim USB interface with C + libusb on Mac OS X

查看:1620
本文介绍了无法要求USB接口与C +的libusb在Mac OS X的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个复合USB + CDC设备我使用PIC32单片机建造,我试图连接到该设备,并从我的Mac发送一些数据疾病预防控制中心的数据接口端点。

I've got a compound USB + CDC device I built using a PIC32 microcontroller, and I'm trying to connect to the device and send some data to the CDC data interface endpoint from my Mac.

我知道了电路的工作原理100%,因为设备寄存器既作为HID摇杆,我能够连接到使用终端ZOC在设备上/dev/tty.usbmodemfa132。我可以 ZOC 发送命令,看看我的MCU应对这些命令由电路上闪烁的LED灯的一些

I know the circuit works 100%, as the device registers as both a HID joystick, and I'm able to connect to the device using Zoc terminal, on /dev/tty.usbmodemfa132. I can send commands with Zoc, and see my MCU responding to these commands by blinking some LEDs on the circuit.

我在Mac OS X上运行的小牛本,但与类似的例子同样的问题,我放弃了,几个星期前在山狮。

I'm running this on Mac OS X Mavericks, but had the same problem with a similar example I gave up on, a few weeks ago on Mountain Lion.

我的code看起来像如下:

My code looks like follows:

// Includes -----------------------------------------------------------------------------------------------------------
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <libusb-1.0/libusb.h>
#include <unistd.h>

// Defines ------------------------------------------------------------------------------------------------------------
#define VID 0x04d8
#define PID 0x005e
#define CDC_DATA_INTERFACE_ID 2

// Function Declarations ----------------------------------------------------------------------------------------------
void print_device(libusb_device *device);
void send(libusb_context *usb_context, uint16_t vid, uint16_t pid);

// Function Definitions -----------------------------------------------------------------------------------------------

/**
 * main
 */
int main(int argc, char **argv)
{
    libusb_device **usb_devices = NULL;
    libusb_context *usb_context = NULL;
    ssize_t device_count = 0;
    bool debug_enabled = false;
    int c;

    // Collect command line attributes
    while ( (c = getopt(argc, argv, "d")) != -1) {
        switch (c) {
            case 'd':
                debug_enabled = true;
                break;
        }
    }

    // Initialize USB context
    int result = libusb_init(&usb_context);
    if(result < 0) {
        printf("Unable to initialise libusb!");
        return EXIT_FAILURE;
    }

    // Turn debug mode on/off
    if(debug_enabled) {
        libusb_set_debug(usb_context, 3);
    }

    // Get USB device list
    device_count = libusb_get_device_list(usb_context, &usb_devices);
    if(device_count < 0) {
        puts("Unable to retrieve USB device list!");
    }

    // Iterate and print devices
    puts("VID    PID     Manufacturer Name\n------ ------ -------------------");
    for (int i = 0; i < device_count; i++) {
        print_device(usb_devices[i]);
    }

    // Attempt to send data
    send(usb_context, VID, PID);

    // Cleanup and exit
    libusb_free_device_list(usb_devices, 1);
    libusb_exit(usb_context);
    return EXIT_SUCCESS;
}

/**
 * print_device
 */
void print_device(libusb_device *device)
{
    struct libusb_device_descriptor device_descriptor;
    struct libusb_device_handle *device_handle = NULL;

    // Get USB device descriptor
    int result = libusb_get_device_descriptor(device, &device_descriptor);
    if (result < 0) {
        printf("Failed to get device descriptor!");
    }

    // Only print our devices
    if(VID == device_descriptor.idVendor && PID == device_descriptor.idProduct) {
        // Print VID & PID
        printf("0x%04x 0x%04x", device_descriptor.idVendor, device_descriptor.idProduct);
    } else {
        return;
    }

    // Attempt to open the device
    int open_result = libusb_open(device, &device_handle);
    if (open_result < 0) {
        libusb_close(device_handle);
        return;
    }

    // Print the device manufacturer string
    char manufacturer[256] = " ";
    if (device_descriptor.iManufacturer) {
        libusb_get_string_descriptor_ascii(device_handle, device_descriptor.iManufacturer,
            (unsigned char *)manufacturer, sizeof(manufacturer));
        printf(" %s", manufacturer);
    }

    puts("");

    libusb_close(device_handle);
}

/**
 * send
 */
void send(libusb_context *usb_context, uint16_t vid, uint16_t pid)
{
    libusb_device_handle *device_handle;
    device_handle = libusb_open_device_with_vid_pid(usb_context, vid, pid);

    if (device_handle == NULL) {
        puts("Unable to open device by VID & PID!");
        return;
    }
    puts("Device successfully opened");

    unsigned char *data = (unsigned char *)"test";

    if (libusb_kernel_driver_active(device_handle, CDC_DATA_INTERFACE_ID)) {
        puts("Kernel driver active");
        if (libusb_detach_kernel_driver(device_handle, CDC_DATA_INTERFACE_ID)) {
            puts("Kernel driver detached");
        }
    } else {
        puts("Kernel driver doesn't appear to be active");
    }

    int result = libusb_claim_interface(device_handle, CDC_DATA_INTERFACE_ID);
    if (result < 0) {
        puts("Unable to claim interface!");
        libusb_close(device_handle);
        return;
    }
    puts("Interface claimed");

    int written = 0;
    result = libusb_bulk_transfer(device_handle, (3 | LIBUSB_ENDPOINT_OUT), data, 4, &written, 0);
    if (result == 0 && written == 4) {
        puts("Send success");
    } else {
        puts("Send failed!");
    }

    result = libusb_release_interface(device_handle, CDC_DATA_INTERFACE_ID);
    if (result != 0) {
        puts("Unable to release interface!");
    }

    libusb_close(device_handle);
}

我收到以下错误的输出:

I'm getting the following error output:

libusb: 0.828223 error [darwin_open] USBDeviceOpen: another process has device opened for exclusive access
libusb: 0.828241 info [darwin_open] device open for access
Device successfully opened
Kernel driver doesn't appear to be active
libusb: 0.828641 error [darwin_claim_interface] USBInterfaceOpen: another process has device opened for exclusive access
Unable to claim interface!
libusb: 0.828766 info [event_thread_main] thread exiting

有没有一种方法,我可以从其他过程释放出USB设备,释放它,所以我可以申请吗?

Is there a way I can release the USB device from the other process, freeing it up so I can claim it?

有没有我可以连接到/dev/tty.usbmodemfa132发送和接收数据到CDC接口的USB设备上的另一种方式?

Is there an alternative way I can connect to /dev/tty.usbmodemfa132 to send and receive data to the CDC interface on the USB device?

这是另一种或许libusb的?

An alternative to libusb perhaps?

推荐答案

这是正确的。虽然libusb的似乎是在Linux的无所不能,你不能使用它,因为该接口已经由AppleUSBCDCACM驱动程序支持连接到Mac OS X上一个USB接口CDC

That's right. While libusb seems to be all-powerful in Linux, you cannot use it to connect to a USB CDC interface on Mac OS X because that interface is already claimed by the AppleUSBCDCACM driver.

你应该做的是使用的人连接到串行端口的标准方式。因为你不必担心端点和批量传输和等这样会比较容易。下面是一些例子跨平台的C code我写了一个连接到一个COM端口读写一些数据(的来源)。它使用标准功能打开

What you should do is use the standard way that people connect to serial ports. This will be easier because you don't have to worry about endpoints and bulk transfers and such. Here is some example cross-platform C code I wrote for one of our CDC-based products that connects to a COM port to read and write some data (source). It uses the standard functions open, read, and write.

// Uses POSIX functions to send and receive data from a Maestro.
// NOTE: You must change the 'const char * device' line below.

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

#ifdef _WIN32
#define O_NOCTTY 0
#else
#include <termios.h>
#endif

// Gets the position of a Maestro channel.
// See the "Serial Servo Commands" section of the user's guide.
int maestroGetPosition(int fd, unsigned char channel)
{
  unsigned char command[] = {0x90, channel};
  if(write(fd, command, sizeof(command)) == -1)
  {
    perror("error writing");
    return -1;
  }

  unsigned char response[2];
  if(read(fd,response,2) != 2)
  {
    perror("error reading");
    return -1;
  }

  return response[0] + 256*response[1];
}

// Sets the target of a Maestro channel.
// See the "Serial Servo Commands" section of the user's guide.
// The units of 'target' are quarter-microseconds.
int maestroSetTarget(int fd, unsigned char channel, unsigned short target)
{
  unsigned char command[] = {0x84, channel, target & 0x7F, target >> 7 & 0x7F};
  if (write(fd, command, sizeof(command)) == -1)
  {
    perror("error writing");
    return -1;
  }
  return 0;
}

int main()
{
  // Open the Maestro's virtual COM port.
  const char * device = "\\\\.\\USBSER000";  // Windows, "\\\\.\\COM6" also works
  //const char * device = "/dev/ttyACM0";  // Linux
  //const char * device = "/dev/cu.usbmodem00034567"; // Mac OS X
  int fd = open(device, O_RDWR | O_NOCTTY);
  if (fd == -1)
  {
    perror(device);
    return 1;
  }

#ifndef _WIN32
  struct termios options;
  tcgetattr(fd, &options);
  options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
  options.c_oflag &= ~(ONLCR | OCRNL);
  tcsetattr(fd, TCSANOW, &options);
#endif

  int position = maestroGetPosition(fd, 0);
  printf("Current position is %d.\n", position); 

  int target = (position < 6000) ? 7000 : 5000;
  printf("Setting target to %d (%d us).\n", target, target/4);
  maestroSetTarget(fd, 0, target);

  close(fd);
  return 0;
}

这篇关于无法要求USB接口与C +的libusb在Mac OS X的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆