int usb_os_open(usb_dev_handle *dev) { int i; struct bsd_usb_dev_handle_info *info; char ctlpath[PATH_MAX + 1]; info = malloc(sizeof(struct bsd_usb_dev_handle_info)); if (!info) USB_ERROR(-ENOMEM); dev->impl_info = info; #ifdef __FreeBSD_kernel__ snprintf(ctlpath, PATH_MAX, "%s", dev->device->filename); #else snprintf(ctlpath, PATH_MAX, "%s.00", dev->device->filename); #endif dev->fd = open(ctlpath, O_RDWR); if (dev->fd < 0) { dev->fd = open(ctlpath, O_RDONLY); if (dev->fd < 0) { free(info); USB_ERROR_STR(-errno, "failed to open %s: %s", ctlpath, strerror(errno)); } } /* Mark the endpoints as not yet open */ for (i = 0; i < USB_MAX_ENDPOINTS; i++) info->ep_fd[i] = -1; return 0; }
EFI_STATUS UsbRemoveDevice ( IN USB_DEVICE *Device ) /*++ Routine Description: Remove the device and all its children from the bus. Arguments: Device - The device to remove Returns: EFI_SUCCESS - The device is removed --*/ { USB_BUS *Bus; USB_DEVICE *Child; EFI_STATUS Status; UINT8 Index; Bus = Device->Bus; // // Remove all the devices on its downstream ports. Search from devices[1]. // Devices[0] is the root hub. // for (Index = 1; Index < USB_MAX_DEVICES; Index++) { Child = Bus->Devices[Index]; if ((Child == NULL) || (Child->ParentAddr != Device->Address)) { continue; } Status = UsbRemoveDevice (Child); if (EFI_ERROR (Status)) { USB_ERROR (("UsbRemoveDevice: failed to remove child, ignore error\n")); Bus->Devices[Index] = NULL; } } UsbRemoveConfig (Device); USB_DEBUG (("UsbRemoveDevice: device %d removed\n", Device->Address)); Bus->Devices[Device->Address] = NULL; UsbFreeDevice (Device); return EFI_SUCCESS; }
int usb_os_find_busses(struct usb_bus **busses) { struct usb_bus *fbus = NULL; DIR *dir; struct dirent *entry; dir = opendir(usb_path); if (!dir) USB_ERROR_STR(-errno, "couldn't opendir(%s): %s", usb_path, strerror(errno)); while ((entry = readdir(dir)) != NULL) { struct usb_bus *bus; /* Skip anything starting with a . */ if (entry->d_name[0] == '.') continue; if (!strchr("0123456789", entry->d_name[strlen(entry->d_name) - 1])) { if (usb_debug >= 2) fprintf(stderr, "usb_os_find_busses: Skipping non bus directory %s\n", entry->d_name); continue; } bus = malloc(sizeof(*bus)); if (!bus) USB_ERROR(-ENOMEM); memset((void *)bus, 0, sizeof(*bus)); strncpy(bus->dirname, entry->d_name, sizeof(bus->dirname) - 1); bus->dirname[sizeof(bus->dirname) - 1] = 0; LIST_ADD(fbus, bus); if (usb_debug >= 2) fprintf(stderr, "usb_os_find_busses: Found %s\n", bus->dirname); } closedir(dir); *busses = fbus; return 0; }
int usb_set_altinterface(usb_dev_handle *dev, int alternate) { int ret; struct usb_setinterface setintf; if (dev->interface < 0) USB_ERROR(-EINVAL); setintf.interface = dev->interface; setintf.altsetting = alternate; ret = ioctl(dev->fd, IOCTL_USB_SETINTF, &setintf); if (ret < 0) USB_ERROR_STR(-errno, "could not set alt intf %d/%d: %s", dev->interface, alternate, strerror(errno)); dev->altsetting = alternate; return 0; }
int usb_set_altinterface(usb_dev_handle *dev, int alternate) { int ret; struct usb_alt_interface intf; if (dev->interface < 0) USB_ERROR(-EINVAL); intf.uai_interface_index = dev->interface; intf.uai_alt_no = alternate; ret = ioctl(dev->fd, USB_SET_ALTINTERFACE, &intf); if (ret < 0) USB_ERROR_STR(-errno, "could not set alt intf %d/%d: %s", dev->interface, alternate, strerror(errno)); dev->altsetting = alternate; return 0; }
int usb_os_find_busses(struct usb_bus **busses) { struct usb_bus *fbus = NULL; int controller; int fd; char buf[20]; for (controller = 0; controller < MAX_CONTROLLERS; controller++) { struct usb_bus *bus; snprintf(buf, sizeof(buf) - 1, "/dev/usb%d", controller); fd = open(buf, O_RDWR); if (fd < 0) { if (usb_debug >= 2) if (errno != ENXIO && errno != ENOENT) fprintf(stderr, "usb_os_find_busses: can't open %s: %s\n", buf, strerror(errno)); continue; } close(fd); bus = malloc(sizeof(*bus)); if (!bus) USB_ERROR(-ENOMEM); memset((void *)bus, 0, sizeof(*bus)); strncpy(bus->dirname, buf, sizeof(bus->dirname) - 1); bus->dirname[sizeof(bus->dirname) - 1] = 0; LIST_ADD(fbus, bus); if (usb_debug >= 2) fprintf(stderr, "usb_os_find_busses: Found %s\n", bus->dirname); } *busses = fbus; return 0; }
int usb_os_find_devices(struct usb_bus *bus, struct usb_device **devices) { struct usb_device *fdev = NULL; DIR *dir; struct dirent *entry; char dirpath[PATH_MAX + 1]; snprintf(dirpath, PATH_MAX, "%s/%s", usb_path, bus->dirname); dir = opendir(dirpath); if (!dir) USB_ERROR_STR(-errno, "couldn't opendir(%s): %s", dirpath, strerror(errno)); while ((entry = readdir(dir)) != NULL) { unsigned char device_desc[DEVICE_DESC_LENGTH]; char filename[PATH_MAX + 1]; struct usb_device *dev; struct usb_connectinfo connectinfo; int i, fd, ret; /* Skip anything starting with a . */ if (entry->d_name[0] == '.') continue; dev = malloc(sizeof(*dev)); if (!dev) USB_ERROR(-ENOMEM); memset((void *)dev, 0, sizeof(*dev)); dev->bus = bus; strncpy(dev->filename, entry->d_name, sizeof(dev->filename) - 1); dev->filename[sizeof(dev->filename) - 1] = 0; snprintf(filename, sizeof(filename) - 1, "%s/%s", dirpath, entry->d_name); fd = open(filename, O_RDWR); if (fd < 0) { fd = open(filename, O_RDONLY); if (fd < 0) { if (usb_debug >= 2) fprintf(stderr, "usb_os_find_devices: Couldn't open %s\n", filename); free(dev); continue; } } /* Get the device number */ ret = ioctl(fd, IOCTL_USB_CONNECTINFO, &connectinfo); if (ret < 0) { if (usb_debug) fprintf(stderr, "usb_os_find_devices: couldn't get connect info\n"); } else dev->devnum = connectinfo.devnum; ret = read(fd, (void *)device_desc, DEVICE_DESC_LENGTH); if (ret < 0) { if (usb_debug) fprintf(stderr, "usb_os_find_devices: Couldn't read descriptor\n"); free(dev); goto err; } /* * Linux kernel converts the words in this descriptor to CPU endian, so * we use the undocumented W character for usb_parse_descriptor() that * doesn't convert endianess when parsing the descriptor */ usb_parse_descriptor(device_desc, "bbWbbbbWWWbbbb", &dev->descriptor); LIST_ADD(fdev, dev); if (usb_debug >= 2) fprintf(stderr, "usb_os_find_devices: Found %s on %s\n", dev->filename, bus->dirname); /* Now try to fetch the rest of the descriptors */ if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) /* Silent since we'll try again later */ goto err; if (dev->descriptor.bNumConfigurations < 1) /* Silent since we'll try again later */ goto err; dev->config = (struct usb_config_descriptor *)malloc(dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor)); if (!dev->config) /* Silent since we'll try again later */ goto err; memset(dev->config, 0, dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor)); for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { unsigned char buffer[8], *bigbuffer; struct usb_config_descriptor config; /* Get the first 8 bytes so we can figure out what the total length is */ ret = read(fd, (void *)buffer, 8); if (ret < 8) { if (usb_debug >= 1) { if (ret < 0) fprintf(stderr, "Unable to get descriptor (%d)\n", ret); else fprintf(stderr, "Config descriptor too short (expected %d, got %d)\n", 8, ret); } goto err; } usb_parse_descriptor(buffer, "bbw", &config); bigbuffer = malloc(config.wTotalLength); if (!bigbuffer) { if (usb_debug >= 1) fprintf(stderr, "Unable to allocate memory for descriptors\n"); goto err; } /* Read the rest of the config descriptor */ memcpy(bigbuffer, buffer, 8); ret = read(fd, (void *)(bigbuffer + 8), config.wTotalLength - 8); if (ret < config.wTotalLength - 8) { if (usb_debug >= 1) { if (ret < 0) fprintf(stderr, "Unable to get descriptor (%d)\n", ret); else fprintf(stderr, "Config descriptor too short (expected %d, got %d)\n", config.wTotalLength, ret); } free(bigbuffer); goto err; } ret = usb_parse_configuration(&dev->config[i], bigbuffer); if (usb_debug >= 2) { if (ret > 0) fprintf(stderr, "Descriptor data still left\n"); else if (ret < 0) fprintf(stderr, "Unable to parse descriptors\n"); } free(bigbuffer); } err: close(fd); } closedir(dir); *devices = fdev; return 0; }
STATIC EFI_STATUS UsbEnumeratePort ( IN USB_INTERFACE *HubIf, IN UINT8 Port ) /*++ Routine Description: Process the events on the port. Arguments: HubIf - The HUB that has the device connected Port - The port index of the hub (started with zero) Returns: EFI_SUCCESS - The device is enumerated (added or removed) EFI_OUT_OF_RESOURCES - Failed to allocate resource for the device Others - Failed to enumerate the device --*/ { USB_HUB_API *HubApi; USB_DEVICE *Child; EFI_USB_PORT_STATUS PortState; EFI_STATUS Status; Child = NULL; HubApi = HubIf->HubApi; // // Host learns of the new device by polling the hub for port changes. // Status = HubApi->GetPortStatus (HubIf, Port, &PortState); if (EFI_ERROR (Status)) { USB_ERROR (("UsbEnumeratePort: failed to get state of port %d\n", Port)); return Status; } if (PortState.PortChangeStatus == 0) { return EFI_SUCCESS; } USB_DEBUG (("UsbEnumeratePort: port %d state - %x, change - %x\n", Port, PortState.PortStatus, PortState.PortChangeStatus)); // // This driver only process two kinds of events now: over current and // connect/disconnect. Other three events are: ENABLE, SUSPEND, RESET. // ENABLE/RESET is used to reset port. SUSPEND isn't supported. // if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_OVERCURRENT)) { if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_OVERCURRENT)) { // // Case1: // Both OverCurrent and OverCurrentChange set, means over current occurs, // which probably is caused by short circuit. It has to wait system hardware // to perform recovery. // USB_DEBUG (("UsbEnumeratePort: Critical Over Current\n", Port)); return EFI_DEVICE_ERROR; } // // Case2: // Only OverCurrentChange set, means system has been recoveried from // over current. As a result, all ports are nearly power-off, so // it's necessary to detach and enumerate all ports again. // USB_DEBUG (("UsbEnumeratePort: 2.0 Device Recovery Over Current\n", Port)); } if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_ENABLE)) { // // Case3: // 1.1 roothub port reg doesn't reflect over-current state, while its counterpart // on 2.0 roothub does. When over-current has influence on 1.1 device, the port // would be disabled, so it's also necessary to detach and enumerate again. // USB_DEBUG (("UsbEnumeratePort: 1.1 Device Recovery Over Current\n", Port)); } if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_CONNECTION)) { // // Case4: // Device connected or disconnected normally. // USB_DEBUG (("UsbEnumeratePort: Device Connect/Discount Normally\n", Port)); } // // Following as the above cases, it's safety to remove and create again. // Child = UsbFindChild (HubIf, Port); if (Child != NULL) { USB_DEBUG (("UsbEnumeratePort: device at port %d removed from system\n", Port)); UsbRemoveDevice (Child); } if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_CONNECTION)) { // // Now, new device connected, enumerate and configure the device // USB_DEBUG (("UsbEnumeratePort: new device connected at port %d\n", Port)); Status = UsbEnumerateNewDev (HubIf, Port); } else { USB_DEBUG (("UsbEnumeratePort: device disconnected event on port %d\n", Port)); } HubApi->ClearPortChange (HubIf, Port); return Status; }
STATIC EFI_STATUS UsbEnumerateNewDev ( IN USB_INTERFACE *HubIf, IN UINT8 Port ) /*++ Routine Description: Enumerate and configure the new device on the port of this HUB interface. Arguments: HubIf - The HUB that has the device connected Port - The port index of the hub (started with zero) Returns: EFI_SUCCESS - The device is enumerated (added or removed) EFI_OUT_OF_RESOURCES - Failed to allocate resource for the device Others - Failed to enumerate the device --*/ { USB_BUS *Bus; USB_HUB_API *HubApi; USB_DEVICE *Child; USB_DEVICE *Parent; EFI_USB_PORT_STATUS PortState; UINT8 Address; UINT8 Config; EFI_STATUS Status; Address = USB_MAX_DEVICES; Parent = HubIf->Device; Bus = Parent->Bus; HubApi = HubIf->HubApi; gBS->Stall (USB_WAIT_PORT_STABLE_STALL); // // Hub resets the device for at least 10 milliseconds. // Host learns device speed. If device is of low/full speed // and the hub is a EHCI root hub, ResetPort will release // the device to its companion UHCI and return an error. // Status = HubApi->ResetPort (HubIf, Port); if (EFI_ERROR (Status)) { USB_ERROR (("UsbEnumerateNewDev: failed to reset port %d - %r\n", Port, Status)); return Status; } USB_DEBUG (("UsbEnumerateNewDev: hub port %d is reset\n", Port)); Child = UsbCreateDevice (HubIf, Port); if (Child == NULL) { return EFI_OUT_OF_RESOURCES; } // // OK, now identify the device speed. After reset, hub // fully knows the actual device speed. // Status = HubApi->GetPortStatus (HubIf, Port, &PortState); if (EFI_ERROR (Status)) { USB_ERROR (("UsbEnumerateNewDev: failed to get speed of port %d\n", Port)); goto ON_ERROR; } if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_LOW_SPEED)) { Child->Speed = EFI_USB_SPEED_LOW; } else if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_HIGH_SPEED)) { Child->Speed = EFI_USB_SPEED_HIGH; } else { Child->Speed = EFI_USB_SPEED_FULL; } USB_DEBUG (("UsbEnumerateNewDev: device is of %d speed\n", Child->Speed)); if (Child->Speed != EFI_USB_SPEED_HIGH) { // // If the child isn't a high speed device, it is necessary to // set the transaction translator. Port TT is 1-based. // This is quite simple: // 1. if parent is of high speed, then parent is our translator // 2. otherwise use parent's translator. // if (Parent->Speed == EFI_USB_SPEED_HIGH) { Child->Translator.TranslatorHubAddress = Parent->Address; Child->Translator.TranslatorPortNumber = Port + 1; } else { Child->Translator = Parent->Translator; } USB_DEBUG (("UsbEnumerateNewDev: device uses translator (%d, %d)\n", Child->Translator.TranslatorHubAddress, Child->Translator.TranslatorPortNumber)); } // // After port is reset, hub establishes a signal path between // the device and host (DEFALUT state). Device¡¯s registers are // reset, use default address 0 (host enumerates one device at // a time) , and ready to respond to control transfer at EP 0. // // // Host sends a Get_Descriptor request to learn the max packet // size of default pipe (only part of the device¡¯s descriptor). // Status = UsbGetMaxPacketSize0 (Child); if (EFI_ERROR (Status)) { USB_ERROR (("UsbEnumerateNewDev: failed to get max packet for EP 0 - %r\n", Status)); goto ON_ERROR; } USB_DEBUG (("UsbEnumerateNewDev: max packet size for EP 0 is %d\n", Child->MaxPacket0)); // // Host assigns an address to the device. Device completes the // status stage with default address, then switches to new address. // ADDRESS state. Address zero is reserved for root hub. // for (Address = 1; Address < USB_MAX_DEVICES; Address++) { if (Bus->Devices[Address] == NULL) { break; } } if (Address == USB_MAX_DEVICES) { USB_ERROR (("UsbEnumerateNewDev: address pool is full for port %d\n", Port)); Status = EFI_ACCESS_DENIED; goto ON_ERROR; } Bus->Devices[Address] = Child; Status = UsbSetAddress (Child, Address); Child->Address = Address; if (EFI_ERROR (Status)) { USB_ERROR (("UsbEnumerateNewDev: failed to set device address - %r\n", Status)); goto ON_ERROR; } gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL); USB_DEBUG (("UsbEnumerateNewDev: device is now ADDRESSED at %d\n", Address)); // // Host learns about the device¡¯s abilities by requesting device's // entire descriptions. // Status = UsbBuildDescTable (Child); if (EFI_ERROR (Status)) { USB_ERROR (("UsbEnumerateNewDev: failed to build descriptor table - %r\n", Status)); goto ON_ERROR; } // // Select a default configuration: UEFI must set the configuration // before the driver can connect to the device. // Config = Child->DevDesc->Configs[0]->Desc.ConfigurationValue; Status = UsbSetConfig (Child, Config); if (EFI_ERROR (Status)) { USB_ERROR (("UsbEnumerateNewDev: failed to set configure %d - %r\n", Config, Status)); goto ON_ERROR; } USB_DEBUG (("UsbEnumerateNewDev: device %d is now in CONFIGED state\n", Address)); // // Host assigns and loads a device driver. // Status = UsbSelectConfig (Child, Config); if (EFI_ERROR (Status)) { USB_ERROR (("UsbEnumerateNewDev: failed to create interfaces - %r\n", Status)); goto ON_ERROR; } return EFI_SUCCESS; ON_ERROR: if (Address != USB_MAX_DEVICES) { Bus->Devices[Address] = NULL; } if (Child != NULL) { UsbFreeDevice (Child); } return Status; }
EFI_STATUS UsbSelectConfig ( IN USB_DEVICE *Device, IN UINT8 ConfigValue ) /*++ Routine Description: Select a new configuration for the device. Each device may support several configurations. Arguments: Device - The device to select configuration ConfigValue - The index of the configuration ( != 0) Returns: EFI_NOT_FOUND - There is no configuration with the index EFI_OUT_OF_RESOURCES - Failed to allocate resource EFI_SUCCESS - The configuration is selected. --*/ { USB_DEVICE_DESC *DevDesc; USB_CONFIG_DESC *ConfigDesc; USB_INTERFACE_DESC *IfDesc; USB_INTERFACE *UsbIf; EFI_STATUS Status; UINT8 Index; // // Locate the active config, then set the device's pointer // DevDesc = Device->DevDesc; ConfigDesc = NULL; for (Index = 0; Index < DevDesc->Desc.NumConfigurations; Index++) { ConfigDesc = DevDesc->Configs[Index]; if (ConfigDesc->Desc.ConfigurationValue == ConfigValue) { break; } } if (Index == DevDesc->Desc.NumConfigurations) { return EFI_NOT_FOUND; } Device->ActiveConfig = ConfigDesc; USB_DEBUG (("UsbSelectConfig: config %d selected for device %d\n", ConfigValue, Device->Address)); // // Create interfaces for each USB interface descriptor. // for (Index = 0; Index < ConfigDesc->Desc.NumInterfaces; Index++) { // // First select the default interface setting, and reset // the endpoint toggles to zero for its endpoints. // IfDesc = ConfigDesc->Interfaces[Index]; UsbSelectSetting (IfDesc, IfDesc->Settings[0]->Desc.AlternateSetting); // // Create a USB_INTERFACE and install USB_IO and other protocols // UsbIf = UsbCreateInterface (Device, ConfigDesc->Interfaces[Index]); if (UsbIf == NULL) { return EFI_OUT_OF_RESOURCES; } Device->Interfaces[Index] = UsbIf; // // Connect the device to drivers, if it failed, ignore // the error. Don't let the unsupported interfaces to block // the supported interfaces. // Status = UsbConnectDriver (UsbIf); if (EFI_ERROR (Status)) { USB_ERROR (("UsbSelectConfig: failed to connect driver %r, ignored\n", Status)); } } Device->NumOfInterface = Index; return EFI_SUCCESS; }
STATIC USB_INTERFACE * UsbCreateInterface ( IN USB_DEVICE *Device, IN USB_INTERFACE_DESC *IfDesc ) /*++ Routine Description: Create an interface for the descriptor IfDesc. Each device's configuration can have several interfaces. Arguments: Device - The device has the interface descriptor IfDesc - The interface descriptor Returns: The created USB interface for the descriptor, or NULL. --*/ { USB_DEVICE_PATH UsbNode; USB_INTERFACE *UsbIf; USB_INTERFACE *HubIf; EFI_STATUS Status; UsbIf = EfiLibAllocateZeroPool (sizeof (USB_INTERFACE)); if (UsbIf == NULL) { return NULL; } UsbIf->Signature = USB_INTERFACE_SIGNATURE; UsbIf->Device = Device; UsbIf->IfDesc = IfDesc; UsbIf->IfSetting = IfDesc->Settings[IfDesc->ActiveIndex]; UsbIf->UsbIo = mUsbIoProtocol; // // Install protocols for USBIO and device path // UsbNode.Header.Type = MESSAGING_DEVICE_PATH; UsbNode.Header.SubType = MSG_USB_DP; UsbNode.ParentPortNumber = Device->ParentPort; UsbNode.InterfaceNumber = UsbIf->IfSetting->Desc.InterfaceNumber; SetDevicePathNodeLength (&UsbNode.Header, sizeof (UsbNode)); HubIf = Device->ParentIf; ASSERT (HubIf != NULL); UsbIf->DevicePath = EfiAppendDevicePathNode (HubIf->DevicePath, &UsbNode.Header); if (UsbIf->DevicePath == NULL) { USB_ERROR (("UsbCreateInterface: failed to create device path\n")); Status = EFI_OUT_OF_RESOURCES; goto ON_ERROR; } Status = gBS->InstallMultipleProtocolInterfaces ( &UsbIf->Handle, &gEfiDevicePathProtocolGuid, UsbIf->DevicePath, &gEfiUsbIoProtocolGuid, &UsbIf->UsbIo, NULL ); if (EFI_ERROR (Status)) { USB_ERROR (("UsbCreateInterface: failed to install UsbIo - %r\n", Status)); goto ON_ERROR; } // // Open USB Host Controller Protocol by Child // Status = UsbOpenHostProtoByChild (Device->Bus, UsbIf->Handle); if (EFI_ERROR (Status)) { gBS->UninstallMultipleProtocolInterfaces ( &UsbIf->Handle, &gEfiDevicePathProtocolGuid, UsbIf->DevicePath, &gEfiUsbIoProtocolGuid, &UsbIf->UsbIo, NULL ); USB_ERROR (("UsbCreateInterface: failed to open host for child - %r\n", Status)); goto ON_ERROR; } return UsbIf; ON_ERROR: if (UsbIf->DevicePath) { gBS->FreePool (UsbIf->DevicePath); } gBS->FreePool (UsbIf); return NULL; }
int usb_os_find_devices(struct usb_bus *bus, struct usb_device **devices) { struct usb_device *fdev = NULL; int cfd, dfd; int device; cfd = open(bus->dirname, O_RDONLY); if (cfd < 0) USB_ERROR_STR(-errno, "couldn't open(%s): %s", bus->dirname, strerror(errno)); for (device = 1; device < USB_MAX_DEVICES; device++) { struct usb_device_info di; struct usb_device *dev; unsigned char device_desc[DEVICE_DESC_LENGTH]; char buf[20]; di.udi_addr = device; if (ioctl(cfd, USB_DEVICEINFO, &di) < 0) continue; /* There's a device; is it one we should mess with? */ if (strncmp(di.udi_devnames[0], "ugen", 4) != 0) /* best not to play with things we don't understand */ continue; #ifdef __FreeBSD_kernel__ snprintf(buf, sizeof(buf) - 1, "/dev/%s", di.udi_devnames[0]); #else snprintf(buf, sizeof(buf) - 1, "/dev/%s.00", di.udi_devnames[0]); #endif /* Open its control endpoint */ dfd = open(buf, O_RDONLY); if (dfd < 0) { if (usb_debug >= 2) fprintf(stderr, "usb_os_find_devices: couldn't open device %s: %s\n", buf, strerror(errno)); continue; } dev = malloc(sizeof(*dev)); if (!dev) USB_ERROR(-ENOMEM); memset((void *)dev, 0, sizeof(*dev)); dev->bus = bus; /* we need to report the device name as /dev/ugenx NOT /dev/ugenx.00 * This seemed easier than having 2 variables... */ #if (__NetBSD__ || __OpenBSD__) snprintf(buf, sizeof(buf) - 1, "/dev/%s", di.udi_devnames[0]); #endif strncpy(dev->filename, buf, sizeof(dev->filename) - 1); dev->filename[sizeof(dev->filename) - 1] = 0; if (ioctl(dfd, USB_GET_DEVICE_DESC, device_desc) < 0) USB_ERROR_STR(-errno, "couldn't get device descriptor for %s: %s", buf, strerror(errno)); close(dfd); usb_parse_descriptor(device_desc, "bbwbbbbwwwbbbb", &dev->descriptor); LIST_ADD(fdev, dev); if (usb_debug >= 2) fprintf(stderr, "usb_os_find_devices: Found %s on %s\n", dev->filename, bus->dirname); } close(cfd); *devices = fdev; return 0; }