Listusb: add parsing AudioControl and AudioStreaming

* Added support for parsing Class Specific Audio Control Interface
  descriptors (as in USB Audio 1 specification);
* Added support for parsing Class Specific Audio Streaming Interface
  descriptors and Endpoints (as in USB Audio 1 specification);
* Implements #10238 request.

- GCI 2013
This commit is contained in:
Ezo
2013-12-01 22:54:39 +01:00
committed by Siarzhuk Zharski
parent 491bbe7797
commit ccfb80f995
+806 -30
View File
@@ -8,10 +8,12 @@
#include <Directory.h>
#include <Entry.h>
#include <MediaDefs.h>
#include <Path.h>
#include <String.h>
#include <USBKit.h>
#include <stdio.h>
#include <usb/USB_audio.h>
#include "usbspec_private.h"
#include "usb-utils.h"
@@ -61,11 +63,785 @@ ClassName(int classNumber) {
}
return "Unknown";
};
}
void
DumpDescriptorData(const usb_generic_descriptor* descriptor)
{
printf(" Type ............. 0x%02x\n",
descriptor->descriptor_type);
printf(" Data ............. ");
// len includes len and descriptor_type field
for (int32 i = 0; i < descriptor->length - 2; i++)
printf("%02x ", descriptor->data[i]);
printf("\n");
}
void
DumpAudioCSInterfaceDescriptorHeader(
const usb_audiocontrol_header_descriptor* descriptor)
{
printf(" Subtype ........... 0x%02x (Header)\n",
descriptor->descriptor_subtype);
printf(" bcdADC Release date 0x%04x\n",
descriptor->bcd_release_no);
printf(" Total Length ...... %u\n",
descriptor->r1.total_length);
printf(" Interfaces ........ ");
for (uint8 i = 0; i < descriptor->r1.in_collection; i++)
printf("%u, ", descriptor->r1.interface_numbers[i]);
printf("\n");
}
void
DumpChannelConfig(uint32 wChannelConfig)
{
struct _Entry {
const char* name;
uint32 mask;
} aClusters[] = {
{ "Front .......... ", B_CHANNEL_LEFT | B_CHANNEL_RIGHT
| B_CHANNEL_CENTER },
{ "L.F.E .......... ", B_CHANNEL_SUB },
{ "Back ........... ", B_CHANNEL_REARLEFT | B_CHANNEL_REARRIGHT
| B_CHANNEL_BACK_CENTER },
{ "Center ......... ", B_CHANNEL_FRONT_LEFT_CENTER
| B_CHANNEL_FRONT_RIGHT_CENTER },
{ "Side ........... ", B_CHANNEL_SIDE_LEFT | B_CHANNEL_SIDE_RIGHT },
{ "Top ............ ", B_CHANNEL_TOP_CENTER },
{ "Top Front ...... ", B_CHANNEL_TOP_FRONT_LEFT
| B_CHANNEL_TOP_FRONT_CENTER | B_CHANNEL_TOP_FRONT_RIGHT },
{ "Top Back ....... ", B_CHANNEL_TOP_BACK_LEFT
| B_CHANNEL_TOP_BACK_CENTER | B_CHANNEL_TOP_BACK_RIGHT }
};
struct _Entry aChannels[] = {
{ "Left", B_CHANNEL_LEFT | B_CHANNEL_FRONT_LEFT_CENTER
| B_CHANNEL_REARLEFT | B_CHANNEL_SIDE_LEFT | B_CHANNEL_TOP_BACK_LEFT
| B_CHANNEL_TOP_FRONT_LEFT },
{ "Right", B_CHANNEL_FRONT_RIGHT_CENTER | B_CHANNEL_TOP_FRONT_RIGHT
| B_CHANNEL_REARRIGHT | B_CHANNEL_RIGHT | B_CHANNEL_SIDE_RIGHT
| B_CHANNEL_TOP_BACK_RIGHT },
{ "Center", B_CHANNEL_BACK_CENTER | B_CHANNEL_CENTER
| B_CHANNEL_TOP_BACK_CENTER | B_CHANNEL_TOP_CENTER
| B_CHANNEL_TOP_FRONT_CENTER },
{ "L.F.E.", B_CHANNEL_SUB }
};
for (size_t i = 0; i < sizeof(aClusters) / sizeof(aClusters[0]); i++) {
uint32 mask = aClusters[i].mask & wChannelConfig;
if (mask != 0) {
printf(" %s", aClusters[i].name);
for (size_t j = 0; j < sizeof(aChannels) / sizeof(aChannels[0]); j++)
if ((aChannels[j].mask & mask) != 0)
printf("%s ", aChannels[j].name);
printf("\n");
}
}
}
const char*
TerminalTypeName(uint16 terminalType)
{
switch (terminalType) {
case USB_AUDIO_UNDEFINED_USB_IO:
return "USB Undefined";
case USB_AUDIO_STREAMING_USB_IO:
return "USB Streaming";
case USB_AUDIO_VENDOR_USB_IO:
return "USB vendor specific";
case USB_AUDIO_UNDEFINED_IN:
return "Undefined";
case USB_AUDIO_MICROPHONE_IN:
return "Microphone";
case USB_AUDIO_DESKTOPMIC_IN:
return "Desktop microphone";
case USB_AUDIO_PERSONALMIC_IN:
return "Personal microphone";
case USB_AUDIO_OMNI_MIC_IN:
return "Omni-directional microphone";
case USB_AUDIO_MICS_ARRAY_IN:
return "Microphone array";
case USB_AUDIO_PROC_MICS_ARRAY_IN:
return "Processing microphone array";
case USB_AUDIO_LINE_CONNECTOR_IO:
return "Line I/O";
case USB_AUDIO_SPDIF_INTERFACE_IO:
return "S/PDIF";
case USB_AUDIO_UNDEFINED_OUT:
return "Undefined";
case USB_AUDIO_SPEAKER_OUT:
return "Speaker";
case USB_AUDIO_HEAD_PHONES_OUT:
return "Headphones";
case USB_AUDIO_HMD_AUDIO_OUT:
return "Head Mounted Display Audio";
case USB_AUDIO_DESKTOP_SPEAKER:
return "Desktop speaker";
case USB_AUDIO_ROOM_SPEAKER:
return "Room speaker";
case USB_AUDIO_COMM_SPEAKER:
return "Communication speaker";
case USB_AUDIO_LFE_SPEAKER:
return "Low frequency effects speaker";
default:
return "Unknown";
}
}
void
DumpAudioCSInterfaceDescriptorInputTerminal(
const usb_audio_input_terminal_descriptor* descriptor)
{
printf(" Subtype ........... 0x%02x (Input Terminal)\n",
descriptor->descriptor_subtype);
printf(" Terminal ID ....... %u\n",
descriptor->terminal_id);
printf(" Terminal Type ..... 0x%04x (%s)\n",
descriptor->terminal_type,
TerminalTypeName(descriptor->terminal_type));
printf(" Associated Terminal %u\n",
descriptor->assoc_terminal);
printf(" Nr Channels ....... %u\n",
descriptor->r1.num_channels);
printf(" Channel Config .... 0x%x\n",
descriptor->r1.channel_config);
DumpChannelConfig(descriptor->r1.channel_config);
printf(" Channel Names ..... %u\n",
descriptor->r1.channel_names);
printf(" Terminal .......... %u\n",
descriptor->r1.terminal);
}
void
DumpAudioCSInterfaceDescriptorOutputTerminal(
const usb_audio_output_terminal_descriptor* descriptor)
{
printf(" Subtype ........... 0x%02x (Output Terminal)\n",
descriptor->descriptor_subtype);
printf(" Terminal ID ....... %u\n",
descriptor->terminal_id);
printf(" Terminal Type ..... 0x%04x (%s)\n",
descriptor->terminal_type,
TerminalTypeName(descriptor->terminal_type));
printf(" Associated Terminal %u\n",
descriptor->assoc_terminal);
printf(" Source ID ......... %u\n",
descriptor->source_id);
printf(" Terminal .......... %u\n",
descriptor->r1.terminal);
}
void
DumpAudioCSInterfaceDescriptorMixerUnit(
const usb_audio_mixer_unit_descriptor* descriptor)
{
printf(" Subtype ........... 0x%02x (Mixer Unit)\n",
descriptor->descriptor_subtype);
printf(" Unit ID ........... %u\n",
descriptor->unit_id);
printf(" Source IDs ........ ");
for (uint8 i = 0; i < descriptor->num_input_pins; i++)
printf("%u, ", descriptor->input_pins[i]);
printf("\n");
usb_audio_output_channels_descriptor_r1* channels
= (usb_audio_output_channels_descriptor_r1*)
&descriptor->input_pins[descriptor->num_input_pins];
printf(" Channels .......... %u\n",
channels->num_output_pins);
printf(" Channel Config .... 0x%x\n",
channels->channel_config);
DumpChannelConfig(channels->channel_config);
printf(" Channel Names ..... %u\n",
channels->channel_names);
usb_generic_descriptor* generic = (usb_generic_descriptor*)descriptor;
uint8 idx = 7 + descriptor->num_input_pins;
printf(" Bitmap Control .... 0x");
for (uint i = 1; idx < descriptor->length - 3; idx++, i++)
printf("%02x ", (uint8)generic->data[idx]);
printf("\n");
printf(" Mixer ............. %u\n",
generic->data[generic->length - 3]);
}
void
DumpAudioCSInterfaceDescriptorSelectorUnit(
const usb_audio_selector_unit_descriptor* descriptor)
{
printf(" Subtype ........... 0x%02x (Selector Unit)\n",
descriptor->descriptor_subtype);
printf(" Unit ID ........... %u\n",
descriptor->unit_id);
printf(" Source IDs ........ ");
for (uint8 i = 0; i < descriptor->num_input_pins; i++)
printf("%u, ", descriptor->input_pins[i]);
printf("\n");
usb_generic_descriptor* generic = (usb_generic_descriptor*)descriptor;
printf(" Selector .......... %u\n",
(uint8)generic->data[descriptor->num_input_pins + 2]);
}
void
DumpBMAControl(uint8 channel, uint32 bma)
{
const char* BMAControls[] = {
"Mute",
"Volume",
"Bass",
"Mid",
"Treble",
"Graphic Equalizer",
"Automatic Gain",
"Delay",
"Bass Boost",
"Loudness"
};
if (bma == 0)
return;
if (channel == 0)
printf(" Master Channel . ");
else
printf(" Channel %u ...... ", channel);
int mask = 1;
for (uint8 i = 0;
i < sizeof(BMAControls) / sizeof(BMAControls[0]); i++, mask <<= 1)
if (bma & mask)
printf("%s ", BMAControls[i]);
printf("\n");
}
void
DumpAudioCSInterfaceDescriptorFeatureUnit(
const usb_audio_feature_unit_descriptor* descriptor)
{
printf(" Subtype ........... 0x%02x (Feature Unit)\n",
descriptor->descriptor_subtype);
printf(" Unit ID ........... %u\n",
descriptor->unit_id);
printf(" Source ID ......... %u\n",
descriptor->source_id);
printf(" Control Size ...... %u\n",
descriptor->r1.control_size);
uint8 channels = (descriptor->length - 6) / descriptor->r1.control_size;
for (uint8 i = 0; i < channels; i++) {
switch (descriptor->r1.control_size) {
case 1:
DumpBMAControl(i, descriptor->r1.bma_controls[i]);
break;
case 2:
DumpBMAControl(i, *(uint16*)&descriptor->r1.bma_controls[i * 2]);
break;
case 4:
DumpBMAControl(i, *(uint32*)&descriptor->r1.bma_controls[i * 4]);
break;
default:
printf(" BMA Channel %u ... ", i);
for (uint8 j = 0; j < descriptor->r1.control_size; j++)
printf("%02x ", descriptor->r1.bma_controls[i + j]);
break;
}
}
usb_generic_descriptor* generic = (usb_generic_descriptor*)descriptor;
printf(" Feature ........... %u\n",
(uint8)generic->data[descriptor->length - 3]);
}
void
DumpAudioCSInterfaceDescriptorAssociated(
const usb_generic_descriptor* descriptor)
{
printf(" Subtype ........... 0x%02x (Associate Interface)\n",
(uint8)descriptor->data[0]);
printf(" Interface ......... %u\n",
(uint8)descriptor->data[1]);
printf(" Data .............. ");
for (uint8 i = 0; i < descriptor->length - 2; i++)
printf("%02x ", descriptor->data[i]);
}
void
DumpAudioControlCSInterfaceDescriptor(const usb_generic_descriptor* descriptor)
{
uint8 descriptorSubtype = descriptor->data[0];
switch (descriptorSubtype) {
case USB_AUDIO_AC_HEADER:
DumpAudioCSInterfaceDescriptorHeader(
(usb_audiocontrol_header_descriptor*)descriptor);
break;
case USB_AUDIO_AC_INPUT_TERMINAL:
DumpAudioCSInterfaceDescriptorInputTerminal(
(usb_audio_input_terminal_descriptor*)descriptor);
break;
case USB_AUDIO_AC_OUTPUT_TERMINAL:
DumpAudioCSInterfaceDescriptorOutputTerminal(
(usb_audio_output_terminal_descriptor*)descriptor);
break;
case USB_AUDIO_AC_MIXER_UNIT:
DumpAudioCSInterfaceDescriptorMixerUnit(
(usb_audio_mixer_unit_descriptor*)descriptor);
break;
case USB_AUDIO_AC_SELECTOR_UNIT:
DumpAudioCSInterfaceDescriptorSelectorUnit(
(usb_audio_selector_unit_descriptor*)descriptor);
break;
case USB_AUDIO_AC_FEATURE_UNIT:
DumpAudioCSInterfaceDescriptorFeatureUnit(
(usb_audio_feature_unit_descriptor*)descriptor);
break;
case USB_AUDIO_AC_EXTENSION_UNIT:
DumpAudioCSInterfaceDescriptorAssociated(descriptor);
break;
default:
DumpDescriptorData(descriptor);
}
}
void
DumpGeneralASInterfaceDescriptor(
const usb_audio_streaming_interface_descriptor* descriptor)
{
printf(" Subtype ........... %u (AS_GENERAL)\n",
descriptor->descriptor_subtype);
printf(" Terminal link ..... %u\n",
descriptor->terminal_link);
printf(" Delay ............. %u\n",
descriptor->r1.delay);
printf(" Format tag ........ %u\n",
descriptor->r1.format_tag);
}
uint32
GetSamplingFrequency(const usb_audio_sampling_freq& freq)
{
return freq.bytes[0] | freq.bytes[1] << 8 | freq.bytes[2] << 16;
}
void
DumpSamplingFrequencies(uint8 type, const usb_audio_sampling_freq* freqs)
{
if (type > 0) {
printf(" Sampling Freq ..... ");
for (uint8 i = 0; i < type; i++)
printf("%lu, ", GetSamplingFrequency(freqs[i]));
printf("\n");
} else
printf(" Sampling Freq ..... %lu to %lu\n",
GetSamplingFrequency(freqs[0]), GetSamplingFrequency(freqs[1]));
}
void
DumpASFormatTypeI(const usb_audio_format_descriptor* descriptor)
{
printf(" Subtype ........... %u (FORMAT_TYPE)\n",
descriptor->descriptor_subtype);
printf(" Format Type ....... %u (FORMAT_TYPE_I)\n",
descriptor->format_type);
printf(" Channels .......... %u\n",
descriptor->typeI.nr_channels);
printf(" Subframe size ..... %u\n",
descriptor->typeI.subframe_size);
printf(" Bit resoultion .... %u\n",
descriptor->typeI.bit_resolution);
DumpSamplingFrequencies(descriptor->typeI.sam_freq_type,
descriptor->typeI.sam_freqs);
}
void
DumpASFormatTypeIII(const usb_audio_format_descriptor* descriptor)
{
printf(" Subtype ........... %u (FORMAT_TYPE)\n",
descriptor->descriptor_subtype);
printf(" Format Type ....... %u (FORMAT_TYPE_III)\n",
descriptor->format_type);
printf(" Channels .......... %u\n",
descriptor->typeIII.nr_channels);
printf(" Subframe size ..... %u\n",
descriptor->typeIII.subframe_size);
printf(" Bit resoultion .... %u\n",
descriptor->typeIII.bit_resolution);
DumpSamplingFrequencies(descriptor->typeIII.sam_freq_type,
descriptor->typeIII.sam_freqs);
}
void
DumpASFormatTypeII(const usb_audio_format_descriptor* descriptor)
{
printf(" Subtype ........... %u (FORMAT_TYPE)\n",
descriptor->descriptor_subtype);
printf(" Format Type ....... %u (FORMAT_TYPE_II)\n",
descriptor->format_type);
printf(" Max Bitrate ....... %u\n",
descriptor->typeII.max_bit_rate);
printf(" Samples per Frame . %u\n",
descriptor->typeII.samples_per_frame);
DumpSamplingFrequencies(descriptor->typeII.sam_freq_type,
descriptor->typeII.sam_freqs);
}
void
DumpASFmtType(const usb_audio_format_descriptor* descriptor)
{
uint8 format = descriptor->format_type;
switch (format) {
case USB_AUDIO_FORMAT_TYPE_I:
DumpASFormatTypeI(descriptor);
break;
case USB_AUDIO_FORMAT_TYPE_II:
DumpASFormatTypeII(descriptor);
break;
case USB_AUDIO_FORMAT_TYPE_III:
DumpASFormatTypeIII(descriptor);
break;
default:
DumpDescriptorData((usb_generic_descriptor*)descriptor);
break;
}
}
void
DumpMPEGCapabilities(uint16 capabilities)
{
const char* MPEGCapabilities[] = {
"Layer I",
"Layer II",
"Layer III",
"MPEG-1 only",
"MPEG-1 dual-channel",
"MPEG-2 second stereo",
"MPEG-2 7.1 channel augumentation",
"Adaptive multi-channel predicion"
};
uint16 mask = 1;
for (uint8 i = 0;
i < sizeof(MPEGCapabilities) / sizeof(MPEGCapabilities[0]); i++) {
if (capabilities & mask)
printf(" %s\n", MPEGCapabilities[i]);
mask <<= 1;
}
mask = 0x300; // bits 8 and 9
uint16 multilingualSupport = (capabilities & mask) >> 8;
switch (multilingualSupport) {
case 0:
printf(" No Multilingual support\n");
break;
case 1:
printf(" Supported at Fs\n");
break;
case 3:
printf(" Supported at Fs and 1/2Fs\n");
break;
default:
break;
}
}
void
DumpMPEGFeatures(uint8 features)
{
uint8 mask = 0x30; // bits 4 and 5
uint8 dynRangeControl = (features & mask) >> 4;
switch (dynRangeControl) {
case 0:
printf(" Not supported\n");
break;
case 1:
printf(" Supported, not scaleable\n");
break;
case 2:
printf(" Scaleable, common boost, "
"cut scaling value\n");
break;
case 3:
printf(" Scaleable, separate boost, "
"cut scaling value\n");
default:
break;
}
}
void
DumpASFmtSpecificMPEG(const usb_generic_descriptor* descriptor)
{
printf(" Subtype ........... %u (FORMAT_SPECIFIC)\n",
descriptor->data[0]);
printf(" Format Tag ........ %u\n",
*(uint16*)&descriptor->data[1]);
printf(" MPEG Capabilities . %u\n",
*(uint16*)&descriptor->data[3]);
DumpMPEGCapabilities(*(uint16*)&descriptor->data[3]);
printf(" MPEG Features ..... %u\n",
descriptor->data[5]);
DumpMPEGFeatures(descriptor->data[5]);
}
void
DumpAC_3Features(uint8 features)
{
const char* featuresStr[] = {
"RF mode",
"Line mode",
"Custom0 mode",
"Custom1 mode"
};
uint8 mask = 1;
for (uint8 i = 0; i < sizeof(featuresStr) / sizeof(const char*); i++) {
if (features & mask)
printf(" %s\n", featuresStr[i]);
mask <<= 1;
}
mask = 0x30; // bits 4 and 5
uint8 dynRangeControl = (features & mask) >> 4;
switch (dynRangeControl) {
case 0:
printf(" Not supported\n");
break;
case 1:
printf(" Supported, not scaleable\n");
break;
case 2:
printf(" Scaleable, common boost, "
"cut scaling value\n");
case 3:
printf(" Scaleable, separate boost, "
"cut scaling value\n");
default:
break;
}
}
void
DumpASFmtSpecificAC_3(const usb_generic_descriptor* descriptor)
{
printf(" Subtype ........... %u (FORMAT_TYPE)\n",
descriptor->data[0]);
printf(" Format Tag ........ %u\n",
*(uint16*)&descriptor->data[1]);
printf(" BSID .............. %lx\n",
*(uint32*)&descriptor->data[2]);
printf(" AC3 Features ...... %u\n",
descriptor->data[6]);
DumpAC_3Features(descriptor->data[6]);
}
void
DumpASFmtSpecific(const usb_generic_descriptor* descriptor)
{
enum {
TYPE_II_UNDEFINED = 0x1000,
MPEG = 0x1001,
AC_3 = 0x1002
};
uint16 formatTag = *(uint16*)&descriptor->data[1];
switch (formatTag) {
case MPEG:
DumpASFmtSpecificMPEG(descriptor);
break;
case AC_3:
DumpASFmtSpecificAC_3(descriptor);
break;
default:
DumpDescriptorData(descriptor);
break;
}
}
void
DumpAudioStreamCSInterfaceDescriptor(const usb_generic_descriptor* descriptor)
{
uint8 subtype = descriptor->data[0];
switch (subtype) {
case USB_AUDIO_AS_GENERAL:
DumpGeneralASInterfaceDescriptor(
(usb_audio_streaming_interface_descriptor*)descriptor);
break;
case USB_AUDIO_AS_FORMAT_TYPE:
DumpASFmtType(
(usb_audio_format_descriptor*)descriptor);
break;
case USB_AUDIO_AS_FORMAT_SPECIFIC:
DumpASFmtSpecific(descriptor);
break;
default:
DumpDescriptorData(descriptor);
break;
}
}
void
DumpAudioStreamCSEndpointDescriptor(
const usb_audio_streaming_endpoint_descriptor* descriptor)
{
printf(" Ttype ............. 0x%02x (CS_ENDPOINT)\n",
descriptor->descriptor_type);
printf(" Subtype ........... 0x%02x (EP_GENERAL)\n",
descriptor->descriptor_subtype);
printf(" Attributes ........ 0x%02x ",
descriptor->attributes);
const char* attributes[] = {
"Sampling Frequency",
"Pitch",
"", "", "", "", "",
"Max Packet Only"
};
uint8 mask = 1;
for (uint8 i = 0; i < sizeof(attributes) / sizeof(attributes[0]); i++) {
if ((descriptor->attributes & mask) != 0)
printf("%s ", attributes[i]);
mask <<= 1;
}
printf("\n");
const char* aUnits[] = {
"Undefined",
"Milliseconds",
"Decoded PCM samples",
"Unknown (%u)"
};
const char* units = descriptor->lock_delay_units > 4
? aUnits[4] : aUnits[descriptor->lock_delay_units];
printf(" Lock Delay Units .. %u (%s)\n",
descriptor->lock_delay_units, units);
printf(" Lock Delay ........ %u\n",
descriptor->lock_delay);
}
void
DumpAudioStreamInterfaceDescriptor(const usb_interface_descriptor* descriptor)
{
printf(" Type .............. %u (INTERFACE)\n",
descriptor->descriptor_type);
printf(" Interface ........... %u\n",
descriptor->interface_number);
printf(" Alternate setting ... %u\n",
descriptor->alternate_setting);
printf(" Endpoints ........... %u\n",
descriptor->num_endpoints);
printf(" Interface class ..... %u (AUDIO)\n",
descriptor->interface_class);
printf(" Interface subclass .. %u (AUDIO_STREAMING)\n",
descriptor->interface_subclass);
printf(" Interface ........... %u\n",
descriptor->interface);
}
void
DumpAudioDescriptor(const usb_generic_descriptor* descriptor, int subclass)
{
const uint8 USB_AUDIO_INTERFACE = 0x04;
switch (subclass) {
case USB_AUDIO_INTERFACE_AUDIOCONTROL_SUBCLASS:
switch (descriptor->descriptor_type) {
case USB_AUDIO_CS_INTERFACE:
DumpAudioControlCSInterfaceDescriptor(descriptor);
break;
default:
DumpDescriptorData(descriptor);
break;
}
break;
case USB_AUDIO_INTERFACE_AUDIOSTREAMING_SUBCLASS:
switch (descriptor->descriptor_type) {
case USB_AUDIO_INTERFACE:
DumpAudioStreamInterfaceDescriptor(
(const usb_interface_descriptor*)descriptor);
break;
case USB_AUDIO_CS_INTERFACE:
DumpAudioStreamCSInterfaceDescriptor(descriptor);
break;
case USB_AUDIO_CS_ENDPOINT:
DumpAudioStreamCSEndpointDescriptor(
(const usb_audio_streaming_endpoint_descriptor*)descriptor);
break;
default:
DumpDescriptorData(descriptor);
break;
}
break;
}
}
void
DumpDescriptor(const usb_generic_descriptor* descriptor,
int classNum, int subclass)
{
switch (classNum) {
case USB_AUDIO_DEVICE_CLASS:
DumpAudioDescriptor(descriptor, subclass);
break;
default:
DumpDescriptorData(descriptor);
break;
}
}
static void
DumpInterface(const BUSBInterface *interface)
DumpInterface(const BUSBInterface* interface)
{
if (!interface)
return;
@@ -80,7 +856,7 @@ DumpInterface(const BUSBInterface *interface)
interface->InterfaceString());
for (uint32 i = 0; i < interface->CountEndpoints(); i++) {
const BUSBEndpoint *endpoint = interface->EndpointAt(i);
const BUSBEndpoint* endpoint = interface->EndpointAt(i);
if (!endpoint)
continue;
@@ -99,29 +875,24 @@ DumpInterface(const BUSBInterface *interface)
else if (endpoint->IsInterrupt())
printf(" Type ............. Interrupt\n");
if(endpoint->IsInput())
if (endpoint->IsInput())
printf(" Direction ........ Input\n");
else
printf(" Direction ........ Output\n");
}
char buffer[256];
usb_descriptor *generic = (usb_descriptor *)buffer;
for (uint32 i = 0; interface->OtherDescriptorAt(i, generic, 256) == B_OK; i++) {
usb_descriptor* generic = (usb_descriptor*)buffer;
for (uint32 i = 0;
interface->OtherDescriptorAt(i, generic, 256) == B_OK; i++) {
printf(" [Descriptor %lu]\n", i);
printf(" Type ............. 0x%02x\n",
generic->generic.descriptor_type);
printf(" Data ............. ");
// the length includes the length and descriptor_type field
for(int32 j = 0; j < generic->generic.length - 2; j++)
printf("%02x ", generic->generic.data[j]);
printf("\n");
DumpDescriptor(&generic->generic, interface->Class(), interface->Subclass());
}
}
static void
DumpConfiguration(const BUSBConfiguration *configuration)
DumpConfiguration(const BUSBConfiguration* configuration)
{
if (!configuration)
return;
@@ -130,10 +901,10 @@ DumpConfiguration(const BUSBConfiguration *configuration)
configuration->ConfigurationString());
for (uint32 i = 0; i < configuration->CountInterfaces(); i++) {
printf(" [Interface %lu]\n", i);
const BUSBInterface *interface = configuration->InterfaceAt(i);
const BUSBInterface* interface = configuration->InterfaceAt(i);
for (uint32 j = 0; j < interface->CountAlternates(); j++) {
const BUSBInterface *alternate = interface->AlternateAt(j);
const BUSBInterface* alternate = interface->AlternateAt(j);
printf(" [Alternate %lu%s]\n", j,
j == interface->AlternateIndex() ? " active" : "");
DumpInterface(alternate);
@@ -143,9 +914,10 @@ DumpConfiguration(const BUSBConfiguration *configuration)
static void
DumpInfo(BUSBDevice &device, bool verbose)
DumpInfo(BUSBDevice& device, bool verbose)
{
const char *vendorName = NULL, *deviceName = NULL;
const char* vendorName = NULL;
const char* deviceName = NULL;
usb_get_vendor_info(device.VendorID(), &vendorName);
usb_get_device_info(device.VendorID(), device.ProductID(), &deviceName);
@@ -186,7 +958,7 @@ DumpInfo(BUSBDevice &device, bool verbose)
usb_hub_descriptor hubDescriptor;
size_t size = device.GetDescriptor(USB_DESCRIPTOR_HUB, 0, 0,
(void *)&hubDescriptor, sizeof(usb_hub_descriptor));
(void*)&hubDescriptor, sizeof(usb_hub_descriptor));
if (size == sizeof(usb_hub_descriptor)) {
printf(" Hub ports count......... %d\n", hubDescriptor.num_ports);
printf(" Hub Controller Current.. %dmA\n", hubDescriptor.max_power);
@@ -195,7 +967,7 @@ DumpInfo(BUSBDevice &device, bool verbose)
usb_port_status portStatus;
size_t actualLength = device.ControlTransfer(USB_REQTYPE_CLASS
| USB_REQTYPE_OTHER_IN, USB_REQUEST_GET_STATUS, 0,
index, sizeof(portStatus), (void *)&portStatus);
index, sizeof(portStatus), (void*)&portStatus);
if (actualLength != sizeof(portStatus))
continue;
printf(" Port %d status....... %04x.%04x%s%s%s%s%s%s%s%s%s\n",
@@ -206,8 +978,8 @@ DumpInfo(BUSBDevice &device, bool verbose)
portStatus.status & PORT_STATUS_OVER_CURRENT ? " Overcurrent": "",
portStatus.status & PORT_STATUS_RESET ? " Reset": "",
portStatus.status & PORT_STATUS_POWER ? " Power": "",
portStatus.status & PORT_STATUS_CONNECTION ?
(portStatus.status & PORT_STATUS_LOW_SPEED ? " Lowspeed"
portStatus.status & PORT_STATUS_CONNECTION
? (portStatus.status & PORT_STATUS_LOW_SPEED ? " Lowspeed"
: (portStatus.status & PORT_STATUS_HIGH_SPEED ? " Highspeed"
: " Fullspeed")) : "",
portStatus.status & PORT_STATUS_TEST ? " Test": "",
@@ -224,13 +996,15 @@ public:
{
}
virtual status_t DeviceAdded(BUSBDevice *device)
virtual status_t DeviceAdded(BUSBDevice* device)
{
DumpInfo(*device, fVerbose);
return B_OK;
}
virtual void DeviceRemoved(BUSBDevice *device)
virtual void DeviceRemoved(BUSBDevice* device)
{
}
@@ -239,8 +1013,9 @@ private:
};
int
main(int argc, char *argv[])
main(int argc, char* argv[])
{
bool verbose = false;
BString devname = "";
@@ -250,13 +1025,14 @@ main(int argc, char *argv[])
verbose = true;
else {
printf("Usage: listusb [-v] [device]\n\n");
printf("-v: Show more detailed information including interfaces, configurations, etc.\n\n");
printf("If a device is not specified, all devices found on the bus will be listed\n");
printf("-v: Show more detailed information including "
"interfaces, configurations, etc.\n\n");
printf("If a device is not specified, "
"all devices found on the bus will be listed\n");
return 1;
}
} else {
} else
devname = argv[i];
}
}
if (devname.Length() > 0) {
@@ -272,7 +1048,7 @@ main(int argc, char *argv[])
DumpRoster roster(verbose);
roster.Start();
roster.Stop();
}
}
return 0;
}