var index = 0 val descriptorTypes = mapOf( 0x01.toByte() to "DEVICE", 0x02.toByte() to "CONFIG", 0x04.toByte() to "INTERFACE", 0x05.toByte() to "ENDPOINT", )
while (index < desc.size) { descriptorTypes[desc[index + 1]]?.let { val indent = " ".repeat(desc[index + 1].toInt()) Log.d(TAG, "${indent}$it") } index += desc[index] }
structlibusb_device_descriptor { /** Size of this descriptor (in bytes) */ uint8_t bLength;
/** Descriptor type. Will have value * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE LIBUSB_DT_DEVICE in this * context. */ uint8_t bDescriptorType;
/** USB specification release number in binary-coded decimal. A value of * 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1, etc. */ uint16_t bcdUSB;
/** USB-IF class code for the device. See \ref libusb_class_code. */ uint8_t bDeviceClass;
/** USB-IF subclass code for the device, qualified by the bDeviceClass * value */ uint8_t bDeviceSubClass;
/** USB-IF protocol code for the device, qualified by the bDeviceClass and * bDeviceSubClass values */ uint8_t bDeviceProtocol;
/** Maximum packet size for endpoint 0 */ uint8_t bMaxPacketSize0;
/** USB-IF vendor ID */ uint16_t idVendor;
/** USB-IF product ID */ uint16_t idProduct;
/** Device release number in binary-coded decimal */ uint16_t bcdDevice;
/** Index of string descriptor describing manufacturer */ uint8_t iManufacturer;
/** Index of string descriptor describing product */ uint8_t iProduct;
/** Index of string descriptor containing device serial number */ uint8_t iSerialNumber;
/** Number of possible configurations */ uint8_t bNumConfigurations; };
staticintparse_interface(libusb_context *ctx, struct libusb_interface *usb_interface, constuint8_t *buffer, int size) { ... begin = buffer;
/* Skip over any interface, class or vendor descriptors */ while (size >= DESC_HEADER_LENGTH) { ... /* If we find another "proper" descriptor then we're done */ if (header->bDescriptorType == LIBUSB_DT_INTERFACE || header->bDescriptorType == LIBUSB_DT_ENDPOINT || header->bDescriptorType == LIBUSB_DT_CONFIG || header->bDescriptorType == LIBUSB_DT_DEVICE) break;
/* Copy any unknown descriptors into a storage area for */ /* drivers to later parse */ ptrdiff_t len = buffer - begin; if (len > 0) { void *extra = malloc((size_t)len); ... memcpy(extra, begin, (size_t)len); ifp->extra = extra; ifp->extra_length = (int)len; } ... }
uvc_error_t uvc_parse_vc(uvc_device_t *dev, uvc_device_info_t *info, constunsignedchar *block, size_t block_size) { int descriptor_subtype; uvc_error_t ret = UVC_SUCCESS;
UVC_ENTER();
if (block[1] != LIBUSB_DT_CS_INTERFACE/*36*/) { // not a CS_INTERFACE descriptor?? UVC_EXIT(UVC_SUCCESS); return UVC_SUCCESS; // UVC_ERROR_INVALID_DEVICE; }
descriptor_subtype = block[2];
switch (descriptor_subtype) { case UVC_VC_HEADER: ret = uvc_parse_vc_header(dev, info, block, block_size); break; case UVC_VC_INPUT_TERMINAL: ret = uvc_parse_vc_input_terminal(dev, info, block, block_size); break; case UVC_VC_OUTPUT_TERMINAL: break; case UVC_VC_SELECTOR_UNIT: break; case UVC_VC_PROCESSING_UNIT: ret = uvc_parse_vc_processing_unit(dev, info, block, block_size); break; case UVC_VC_EXTENSION_UNIT: ret = uvc_parse_vc_extension_unit(dev, info, block, block_size); break; default: LOGW("UVC_ERROR_INVALID_DEVICE:descriptor_subtype=0x%02x", descriptor_subtype); ret = UVC_ERROR_INVALID_DEVICE; }
// 然后发送控制指令获取PanTilt绝对值 val buff = ByteArray(8) val index = getPanTiltControlIndex(connection) val value = CT_PANTILT_ABSOLUTE_CONTROL.shl(8) connection.controlTransfer(CONTROL_REQ_TYPE_GET, UVC_GET_CUR, value, index, buff, buff.size, 100)
// buff前四个byte组合起来是pan值 // buff后四个byte组合起来是tilt值 val pan = bytes[0].toUByte().toInt().shl(0) or bytes[1].toUByte().toInt().shl(8) or bytes[2].toUByte().toInt().shl(16) or bytes[3].toUByte().toInt().shl(24)
val tilt = bytes[4].toUByte().toInt().shl(0) or bytes[5].toUByte().toInt().shl(8) or bytes[6].toUByte().toInt().shl(16) or bytes[7].toUByte().toInt().shl(24)
val USB_DESC_TYPE_INTERFACE_LEN = 9.toByte() val USB_DESC_TYPE_INTERFACE = 0x04.toByte() val USB_DESC_TYPE_CS_INTERFACE = 0x24.toByte() val USB_DESC_SUB_TYPE_VC_INPUT_TERMINAL = 0x02.toByte() val USB_SUBCLASS_VIDEO_CONTROL = 0x01
privatefungetPanTiltControlIndex(connection: UsbDeviceConnection): Int { val desc = connection.rawDescriptors ?: return -1