Beispiel #1
0
static size_t
usbFormatLogSetupPacket (char *buffer, size_t size, const void *data) {
  const UsbSetupPacket *setup = data;
  size_t length;
  STR_BEGIN(buffer, size);

  STR_PRINTF("setup packet: Typ:%02X Req:%02X Val:%04X Idx:%04X Len:%04X",
             setup->bRequestType, setup->bRequest,
             getLittleEndian16(setup->wValue),
             getLittleEndian16(setup->wIndex),
             getLittleEndian16(setup->wLength));

  length = STR_LENGTH;
  STR_END;
  return length;
}
Beispiel #2
0
int
usbGetLanguage (
  UsbDevice *device,
  uint16_t *language,
  int timeout
) {
  UsbDescriptor descriptor;
  ssize_t size = usbGetDescriptor(device, UsbDescriptorType_String,
                              0, 0, &descriptor, timeout);

  if (size != -1) {
    if (size >= 4) {
      *language = getLittleEndian16(descriptor.string.wData[0]);
      logMessage(LOG_CATEGORY(USB_IO), "USB language: %02X", *language);
      return 1;
    } else {
      logMessage(LOG_ERR, "USB language code string too short: %"PRIssize, size);
      errno = EIO;
    }
  } else {
    logMessage(LOG_ERR, "USB language code string read error");
  }

  return 0;
}
Beispiel #3
0
static int
usbReadHostDeviceDescriptor (UsbHostDevice *host) {
  int ok = 0;
  int file = -1;
  int sysfs = 0;

  if (file == -1) {
    if (host->sysfsPath) {
      char *path;

      if ((path = makePath(host->sysfsPath, "descriptors"))) {
        if ((file = open(path, O_RDONLY)) != -1) {
          sysfs = 1;
        }

        free(path);
      }
    }
  }

  if (file == -1) {
    file = open(host->usbfsPath, O_RDONLY);
  }

  if (file != -1) {
    int count = read(file, &host->usbDescriptor, UsbDescriptorSize_Device);

    if (count == -1) {
      logSystemError("USB device descriptor read");
    } else if (count != UsbDescriptorSize_Device) {
      logMessage(LOG_ERR, "USB short device descriptor: %d", count);
    } else {
      ok = 1;

      if (!sysfs) {
        host->usbDescriptor.bcdUSB = getLittleEndian16(host->usbDescriptor.bcdUSB);
        host->usbDescriptor.idVendor = getLittleEndian16(host->usbDescriptor.idVendor);
        host->usbDescriptor.idProduct = getLittleEndian16(host->usbDescriptor.idProduct);
        host->usbDescriptor.bcdDevice = getLittleEndian16(host->usbDescriptor.bcdDevice);
      }
    }

    close(file);
  }

  return ok;
}
Beispiel #4
0
const UsbConfigurationDescriptor *
usbConfigurationDescriptor (
  UsbDevice *device
) {
  if (!device->configuration) {
    unsigned char current;

    if (device->descriptor.bNumConfigurations < 2) {
      current = 1;
    } else if (!usbGetConfiguration(device, &current)) {
      current = 0;
    }

    if (current) {
      UsbDescriptor descriptor;
      unsigned char number;

      for (number=0; number<device->descriptor.bNumConfigurations; number++) {
        int size = usbGetDescriptor(device, UsbDescriptorType_Configuration,
                                    number, 0, &descriptor, 1000);
        if (size == -1) {
          logMessage(LOG_WARNING, "USB configuration descriptor not readable: %d", number);
        } else if (descriptor.configuration.bConfigurationValue == current) {
          break;
        }
      }

      if (number < device->descriptor.bNumConfigurations) {
        int length = getLittleEndian16(descriptor.configuration.wTotalLength);
        UsbDescriptor *descriptors;

        if ((descriptors = malloc(length))) {
          ssize_t size;

          if (length > sizeof(descriptor)) {
            size = usbControlRead(device, UsbControlRecipient_Device, UsbControlType_Standard,
                                  UsbStandardRequest_GetDescriptor,
                                  (UsbDescriptorType_Configuration << 8) | number,
                                  0, descriptors, length, 1000);
          } else {
            memcpy(descriptors, &descriptor, (size = length));
          }

          if (size != -1) {
            device->configuration = &descriptors->configuration;
          } else {
            free(descriptors);
          }
        } else {
          logSystemError("USB configuration descriptor allocate");
        }
      } else {
        logMessage(LOG_ERR, "USB configuration descriptor not found: %d", current);
      }
    }
  }

  return device->configuration;
}
Beispiel #5
0
UsbEndpoint *
usbGetEndpoint (UsbDevice *device, unsigned char endpointAddress) {
  UsbEndpoint *endpoint;
  const UsbEndpointDescriptor *descriptor;

  if ((endpoint = findItem(device->endpoints, usbTestEndpoint, &endpointAddress))) return endpoint;

  if ((descriptor = usbEndpointDescriptor(device, endpointAddress))) {
    {
      const char *direction;
      const char *transfer;

      switch (USB_ENDPOINT_DIRECTION(descriptor)) {
        default:                            direction = "?";   break;
        case UsbEndpointDirection_Input:  direction = "in";  break;
        case UsbEndpointDirection_Output: direction = "out"; break;
      }

      switch (USB_ENDPOINT_TRANSFER(descriptor)) {
        default:                                transfer = "?";   break;
        case UsbEndpointTransfer_Control:     transfer = "ctl"; break;
        case UsbEndpointTransfer_Isochronous: transfer = "iso"; break;
        case UsbEndpointTransfer_Bulk:        transfer = "blk"; break;
        case UsbEndpointTransfer_Interrupt:   transfer = "int"; break;
      }

      logMessage(LOG_DEBUG, "USB: ept=%02X dir=%s xfr=%s pkt=%d ivl=%dms",
                 descriptor->bEndpointAddress, direction, transfer,
                 getLittleEndian16(descriptor->wMaxPacketSize),
                 descriptor->bInterval);
    }

    if ((endpoint = malloc(sizeof(*endpoint)))) {
      memset(endpoint, 0, sizeof(*endpoint));
      endpoint->device = device;
      endpoint->descriptor = descriptor;

      switch (USB_ENDPOINT_DIRECTION(endpoint->descriptor)) {
        case UsbEndpointDirection_Input:
          endpoint->direction.input.pending = NULL;
          endpoint->direction.input.completed = NULL;
          endpoint->direction.input.buffer = NULL;
          endpoint->direction.input.length = 0;
          endpoint->direction.input.asynchronous = 0;
          break;
      }

      endpoint->extension = NULL;
      if (usbAllocateEndpointExtension(endpoint)) {
        if (enqueueItem(device->endpoints, endpoint)) return endpoint;
        usbDeallocateEndpointExtension(endpoint->extension);
      }

      free(endpoint);
    }
  }

  return NULL;
}
Beispiel #6
0
ssize_t
usbControlTransfer (
  UsbDevice *device,
  uint8_t direction,
  uint8_t recipient,
  uint8_t type,
  uint8_t request,
  uint16_t value,
  uint16_t index,
  void *buffer,
  uint16_t length,
  int timeout
) {
  UsbDeviceExtension *devx = device->extension;
  UsbSetupPacket setup;
  int result;

  usbMakeSetupPacket(&setup, direction, recipient, type, request, value, index, length);

  if (direction == UsbControlDirection_Output) {
    if (length) logBytes(LOG_CATEGORY(USB_IO), "control output", buffer, length);
  }

  result = usb_control_msg(devx->handle, setup.bRequestType, setup.bRequest,
                           getLittleEndian16(setup.wValue),
                           getLittleEndian16(setup.wIndex), buffer,
                           getLittleEndian16(setup.wLength), timeout);

  if (result >= 0) {
    if (direction == UsbControlDirection_Input) {
      logBytes(LOG_CATEGORY(USB_IO), "control input", buffer, result);
    }

    return result;
  }

  errno = -result;
  logSystemError("USB control transfer");
  return -1;
}
Beispiel #7
0
char *
usbDecodeString (const UsbStringDescriptor *descriptor) {
  int count = (descriptor->bLength - 2) / sizeof(descriptor->wData[0]);
  char *string = malloc(count+1);
  if (string) {
    string[count] = 0;
    while (count--) {
      uint16_t character = getLittleEndian16(descriptor->wData[count]);
      if (character & 0XFF00) character = '?';
      string[count] = character;
    }
  } else {
    logSystemError("USB string allocate");
  }
  return string;
}
Beispiel #8
0
int
usbGetLanguage (
  UsbDevice *device,
  uint16_t *language,
  int timeout
) {
  UsbDescriptor descriptor;
  int size = usbGetDescriptor(device, UsbDescriptorType_String,
                              0, 0, &descriptor, timeout);
  if (size != -1) {
    if (size >= 4) {
      *language = getLittleEndian16(descriptor.string.wData[0]);
      logMessage(LOG_DEBUG, "USB Language: %02X", *language);
      return 1;
    }
    errno = EIO;
  }
  return 0;
}
Beispiel #9
0
int
usbNextDescriptor (
  UsbDevice *device,
  const UsbDescriptor **descriptor
) {
  if (*descriptor) {
    const UsbDescriptor *next = (UsbDescriptor *)&(*descriptor)->bytes[(*descriptor)->header.bLength];
    const UsbDescriptor *first = (UsbDescriptor *)device->configuration;
    unsigned int length = getLittleEndian16(first->configuration.wTotalLength);
    if ((&next->bytes[0] - &first->bytes[0]) >= length) return 0;
    if ((&next->bytes[next->header.bLength] - &first->bytes[0]) > length) return 0;
    *descriptor = next;
  } else if (usbConfigurationDescriptor(device)) {
    *descriptor = (UsbDescriptor *)device->configuration;
  } else {
    return 0;
  }
  return 1;
}
Beispiel #10
0
ssize_t
usbHidGetItems (
  UsbDevice *device,
  unsigned char interface,
  unsigned char number,
  unsigned char **items,
  int timeout
) {
  const UsbHidDescriptor *hid = usbHidDescriptor(device);

  if (hid) {
    if (number < hid->bNumDescriptors) {
      const UsbClassDescriptor *descriptor = &hid->descriptors[number];
      uint16_t length = getLittleEndian16(descriptor->wDescriptorLength);
      void *buffer = malloc(length);

      if (buffer) {
        ssize_t result = usbControlRead(device,
                                        UsbControlRecipient_Interface, UsbControlType_Standard,
                                        UsbStandardRequest_GetDescriptor,
                                        (descriptor->bDescriptorType << 8) | interface,
                                        number, buffer, length, timeout);

        if (result != -1) {
          *items = buffer;
          return result;
        }

        free(buffer);
      } else {
        logMallocError();
      }
    } else {
      logMessage(LOG_WARNING, "USB report descriptor not found: %u[%u]",
                 interface, number);
    }
  }

  return -1;
}
Beispiel #11
0
char *
usbDecodeString (const UsbStringDescriptor *descriptor) {
  size_t count = (descriptor->bLength - 2) / sizeof(descriptor->wData[0]);
  char buffer[(count * UTF8_LEN_MAX) + 1];

  const uint16_t *source = descriptor->wData;
  const uint16_t *end = source + count;
  char *target = buffer;

  while (source < end) {
    size_t length = convertWcharToUtf8(getLittleEndian16(*source++), target);

    target += length;
  }
  *target = 0;

  {
    char *string = strdup(buffer);

    if (!string) logMallocError();
    return string;
  }
}
Beispiel #12
0
static wchar_t *
getUsbString (BrailleDisplay *brl, uint8_t request) {
  UsbDescriptor descriptor;

  if (askResource(brl, request, 0, 0, descriptor.bytes, sizeof(descriptor.bytes))) {
    size_t count = (descriptor.string.bLength - 2) / sizeof(descriptor.string.wData[0]);
    wchar_t *string = malloc((count + 1) * sizeof(*string));

    if (string) {
      string[count] = 0;

      while (count) {
        count -= 1;
        string[count] = getLittleEndian16(descriptor.string.wData[count]);
      }

      return string;
    } else {
      logMallocError();
    }
  }

  return NULL;
}
Beispiel #13
0
UsbDevice *
usbFindDevice (UsbDeviceChooser *chooser, UsbChooseChannelData *data) {
  UsbDevice *device = NULL;
  int result;

  {
    static int initialized = 0;
    if (!initialized) {
      usb_init();
      initialized = 1;
    }
  }

  if ((result = usb_find_busses()) >= 0) {
    if ((result = usb_find_devices()) >= 0) {
      struct usb_bus *bus = usb_get_busses();

      if (bus) {
        struct usb_bus *bus0 = bus;

        do {
          struct usb_device *dev = bus->devices;

          if (dev) {
            struct usb_device *dev0 = dev;

            do {
              UsbDeviceExtension *devx;

              if ((devx = malloc(sizeof(*devx)))) {
                if ((devx->handle = usb_open(dev))) {
                  if ((device = usbTestDevice(devx, chooser, data))) return device;

                  usb_close(devx->handle);
                } else {
                  logMessage(LOG_ERR, "USB open error: vendor=%X product=%X",
                             getLittleEndian16(dev->descriptor.idVendor),
                             getLittleEndian16(dev->descriptor.idProduct));
                }

                free(devx);
              } else {
                logSystemError("USB device extension allocate");
              }

              if ((dev = dev->next) == dev0) dev = NULL;
            } while (dev);
          }

          if ((bus = bus->next) == bus0) bus = NULL;
        } while (bus);
      }
    } else {
      errno = -result;
      logSystemError("USB devices find");
    }
  } else {
    errno = -result;
    logSystemError("USB busses find");
  }

  return device;
}
Beispiel #14
0
UsbEndpoint *
usbGetEndpoint (UsbDevice *device, unsigned char endpointAddress) {
  UsbEndpoint *endpoint;
  const UsbEndpointDescriptor *descriptor;

  if ((endpoint = findItem(device->endpoints, usbTestEndpoint, &endpointAddress))) return endpoint;

  if ((descriptor = usbEndpointDescriptor(device, endpointAddress))) {
    {
      const char *direction;
      const char *transfer;

      switch (USB_ENDPOINT_DIRECTION(descriptor)) {
        default:                          direction = "?";   break;
        case UsbEndpointDirection_Input:  direction = "in";  break;
        case UsbEndpointDirection_Output: direction = "out"; break;
      }

      switch (USB_ENDPOINT_TRANSFER(descriptor)) {
        default:                              transfer = "?";   break;
        case UsbEndpointTransfer_Control:     transfer = "ctl"; break;
        case UsbEndpointTransfer_Isochronous: transfer = "iso"; break;
        case UsbEndpointTransfer_Bulk:        transfer = "blk"; break;
        case UsbEndpointTransfer_Interrupt:   transfer = "int"; break;
      }

      logMessage(LOG_CATEGORY(USB_IO), "ept=%02X dir=%s xfr=%s pkt=%d ivl=%dms",
                 descriptor->bEndpointAddress, direction, transfer,
                 getLittleEndian16(descriptor->wMaxPacketSize),
                 descriptor->bInterval);
    }

    if ((endpoint = malloc(sizeof(*endpoint)))) {
      memset(endpoint, 0, sizeof(*endpoint));
      endpoint->device = device;
      endpoint->descriptor = descriptor;
      endpoint->extension = NULL;
      endpoint->prepare = NULL;

      switch (USB_ENDPOINT_DIRECTION(endpoint->descriptor)) {
        case UsbEndpointDirection_Input:
          endpoint->direction.input.pending.requests = NULL;
          endpoint->direction.input.pending.alarm = NULL;
          endpoint->direction.input.pending.delay = 0;

          endpoint->direction.input.completed.request = NULL;
          endpoint->direction.input.completed.buffer = NULL;
          endpoint->direction.input.completed.length = 0;

          endpoint->direction.input.pipe.input = INVALID_FILE_DESCRIPTOR;
          endpoint->direction.input.pipe.output = INVALID_FILE_DESCRIPTOR;
          endpoint->direction.input.pipe.monitor = NULL;
          endpoint->direction.input.pipe.error = 0;

          break;
      }

      if (usbAllocateEndpointExtension(endpoint)) {
        if (enqueueItem(device->endpoints, endpoint)) {
          if (device->disableEndpointReset) {
            logMessage(LOG_CATEGORY(USB_IO), "endpoint reset disabled");
          } else {
            usbClearHalt(device, endpoint->descriptor->bEndpointAddress);
          }

          if (!endpoint->prepare || endpoint->prepare(endpoint)) return endpoint;
          deleteItem(device->endpoints, endpoint);
        }

        usbDeallocateEndpointExtension(endpoint->extension);
        usbDestroyInputPipe(endpoint);
      }

      free(endpoint);
    }
  }

  return NULL;
}
Beispiel #15
0
int
usbVerifyProductIdentifier (const UsbDeviceDescriptor *descriptor, uint16_t identifier) {
  if (!identifier) return 1;
  return identifier == getLittleEndian16(descriptor->idProduct);
}