Devices: Extract USB descriptors
Shows most of the USB attributes by extracting the values in the internal USB tree. This is meant to display the same information as listusb -v. Changes: - Added FindDevicePath in DeviceUSB.cpp to map the device to their hardware path - Added USBTree in DeviceUSB.cpp that goes through the configurations, interfaces, alternates and endpoints of USB devices to set new attributes - Linked the path found in FindDevicePath to a BUSBDevice object, that is called in USBTree to start the extraction Change-Id: I9fd314767dc856b3cc603346d88be438699429d9 Reviewed-on: https://review.haiku-os.org/c/haiku/+/11071 Tested-by: Commit checker robot <[email protected]> Reviewed-by: Kacper Kasper <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
5bec7e6ebd
commit
3a517423b0
@@ -13,6 +13,10 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <Catalog.h>
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
#include <Path.h>
|
||||
#include <USBKit.h>
|
||||
#include <bus/USB.h>
|
||||
|
||||
#undef B_TRANSLATION_CONTEXT
|
||||
@@ -24,6 +28,24 @@ extern "C" {
|
||||
}
|
||||
|
||||
|
||||
#define USB_SELF_POWERED 0x40
|
||||
#define USB_REMOTE_WAKEUP 0x20
|
||||
|
||||
|
||||
static uint8
|
||||
MajorVersion(uint16 version)
|
||||
{
|
||||
return version >> 8;
|
||||
}
|
||||
|
||||
|
||||
static uint8
|
||||
MinorVersion(uint16 version)
|
||||
{
|
||||
return version & 0xff;
|
||||
}
|
||||
|
||||
|
||||
DeviceUSB::DeviceUSB(Device* parent)
|
||||
:
|
||||
Device(parent),
|
||||
@@ -47,6 +69,162 @@ static BString ToHex(uint16 num)
|
||||
}
|
||||
|
||||
|
||||
static BString
|
||||
FindDevicePath(const char* currentPath, uint16 vendor, uint16 product)
|
||||
{
|
||||
BDirectory dir(currentPath);
|
||||
if (dir.InitCheck() != B_OK)
|
||||
return "";
|
||||
|
||||
BEntry entry;
|
||||
while (dir.GetNextEntry(&entry) == B_OK) {
|
||||
BPath pathObj;
|
||||
entry.GetPath(&pathObj);
|
||||
|
||||
if (BString(pathObj.Leaf()) == "hub")
|
||||
continue;
|
||||
|
||||
if (entry.IsDirectory()) {
|
||||
BString result = FindDevicePath(pathObj.Path(), vendor, product);
|
||||
if (result != "")
|
||||
return result;
|
||||
} else {
|
||||
BUSBDevice testDevice(pathObj.Path());
|
||||
if (testDevice.InitCheck() == B_OK && testDevice.VendorID() == vendor
|
||||
&& testDevice.ProductID() == product) {
|
||||
|
||||
return BString(pathObj.Path());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
BuildUSBTree(BUSBDevice& device, DeviceUSB* node)
|
||||
{
|
||||
node->SetAttribute("usb/path", device.Location());
|
||||
if (device.ManufacturerString())
|
||||
node->SetAttribute("usb/manufacturer", device.ManufacturerString());
|
||||
if (device.ProductString())
|
||||
node->SetAttribute("usb/product", device.ProductString());
|
||||
if (device.SerialNumberString())
|
||||
node->SetAttribute("usb/serial_number", device.SerialNumberString());
|
||||
|
||||
BString usbVersion;
|
||||
usbVersion.SetToFormat(B_TRANSLATE("%d.%d"),
|
||||
MajorVersion(device.USBVersion()),
|
||||
MinorVersion(device.USBVersion()));
|
||||
node->SetAttribute("usb/version", usbVersion);
|
||||
|
||||
for (uint32 i = 0; i < device.CountConfigurations(); i++) {
|
||||
const BUSBConfiguration* config = device.ConfigurationAt(i);
|
||||
if (!config)
|
||||
continue;
|
||||
|
||||
BString confPath;
|
||||
confPath << "usb/config/" << i;
|
||||
|
||||
BString powerValue;
|
||||
powerValue.SetToFormat(B_TRANSLATE("%d mA"), config->Descriptor()->max_power * 2);
|
||||
node->SetAttribute(BString(confPath) << "/max_power", powerValue);
|
||||
|
||||
uint8 attr = config->Descriptor()->attributes;
|
||||
if (attr & USB_SELF_POWERED)
|
||||
node->SetAttribute(BString(confPath) << "/self_powered", "true");
|
||||
if (attr & USB_REMOTE_WAKEUP)
|
||||
node->SetAttribute(BString(confPath) << "/remote_wakeup", "true");
|
||||
|
||||
if (config->ConfigurationString())
|
||||
node->SetAttribute(BString(confPath) << "/name", config->ConfigurationString());
|
||||
|
||||
for (uint32 j = 0; j < config->CountInterfaces(); j++) {
|
||||
const BUSBInterface* interface = config->InterfaceAt(j);
|
||||
if (!interface)
|
||||
continue;
|
||||
|
||||
BString intfPath;
|
||||
intfPath << confPath << "/interface/" << j;
|
||||
|
||||
for (uint32 k = 0; k < interface->CountAlternates(); k++) {
|
||||
const BUSBInterface* alt = interface->AlternateAt(k);
|
||||
if (!alt)
|
||||
continue;
|
||||
|
||||
BString altPath;
|
||||
altPath << intfPath << "/alt/" << k;
|
||||
|
||||
if (k == interface->AlternateIndex())
|
||||
node->SetAttribute(BString(altPath) << "/active", "true");
|
||||
|
||||
char classInfo[128];
|
||||
usb_get_class_info(alt->Class(), alt->Subclass(), alt->Protocol(), classInfo,
|
||||
sizeof(classInfo));
|
||||
|
||||
BString classVal;
|
||||
classVal.SetToFormat(B_TRANSLATE("0x%02x, Sub: 0x%02x (%s)"), alt->Class(),
|
||||
alt->Subclass(), classInfo);
|
||||
|
||||
node->SetAttribute(BString(altPath) << "/class_info", classVal);
|
||||
|
||||
if (alt->InterfaceString())
|
||||
node->SetAttribute(BString(altPath) << "/name", alt->InterfaceString());
|
||||
|
||||
for (uint32 e = 0; e < alt->CountEndpoints(); e++) {
|
||||
const BUSBEndpoint* endpoint = alt->EndpointAt(e);
|
||||
if (!endpoint)
|
||||
continue;
|
||||
|
||||
BString endpointPath;
|
||||
endpointPath << altPath << "/endpoint/" << e;
|
||||
|
||||
const usb_endpoint_descriptor* endpointDesc = endpoint->Descriptor();
|
||||
|
||||
BString endpointAddress;
|
||||
endpointAddress.SetToFormat(B_TRANSLATE("0x%02x (%s)"),
|
||||
endpointDesc->endpoint_address,
|
||||
(endpointDesc->endpoint_address & USB_ENDPOINT_ADDR_DIR_MASK)
|
||||
== USB_ENDPOINT_ADDR_DIR_IN
|
||||
? B_TRANSLATE("IN")
|
||||
: B_TRANSLATE("OUT"));
|
||||
node->SetAttribute(BString(endpointPath) << "/address", endpointAddress);
|
||||
|
||||
const char* type = B_TRANSLATE("Unknown");
|
||||
switch (endpointDesc->attributes & USB_ENDPOINT_ATTR_MASK) {
|
||||
case USB_ENDPOINT_ATTR_CONTROL:
|
||||
type = B_TRANSLATE("Control");
|
||||
break;
|
||||
case USB_ENDPOINT_ATTR_ISOCHRONOUS:
|
||||
type = B_TRANSLATE("Isochronous");
|
||||
break;
|
||||
case USB_ENDPOINT_ATTR_BULK:
|
||||
type = B_TRANSLATE("Bulk");
|
||||
break;
|
||||
case USB_ENDPOINT_ATTR_INTERRUPT:
|
||||
type = B_TRANSLATE("Interrupt");
|
||||
break;
|
||||
}
|
||||
node->SetAttribute(BString(endpointPath) << "/type", type);
|
||||
|
||||
BString maxPacket;
|
||||
maxPacket << endpointDesc->max_packet_size;
|
||||
node->SetAttribute(BString(endpointPath) << "/max_packet_size", maxPacket);
|
||||
|
||||
if ((endpointDesc->attributes & USB_ENDPOINT_ATTR_MASK)
|
||||
== USB_ENDPOINT_ATTR_INTERRUPT) {
|
||||
BString interval;
|
||||
interval.SetToFormat(B_TRANSLATE("%u ms"), endpointDesc->interval);
|
||||
node->SetAttribute(BString(endpointPath) << "/interval", interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DeviceUSB::InitFromAttributes()
|
||||
{
|
||||
@@ -91,13 +269,6 @@ DeviceUSB::InitFromAttributes()
|
||||
|
||||
SetAttribute(B_TRANSLATE("Device name"), deviceLabel);
|
||||
SetAttribute(B_TRANSLATE("Manufacturer"), manufacturerLabel);
|
||||
#if 0
|
||||
// These are a source of confusion for users, leading them to think there
|
||||
// is no driver for their device. Until we can display something useful,
|
||||
// let's not show the lines at all.
|
||||
SetAttribute(B_TRANSLATE("Driver used"), B_TRANSLATE("Not implemented"));
|
||||
SetAttribute(B_TRANSLATE("Device paths"), B_TRANSLATE("Not implemented"));
|
||||
#endif
|
||||
SetAttribute(B_TRANSLATE("Class info"), classInfo);
|
||||
switch (fClassBaseId) {
|
||||
case 0x1:
|
||||
@@ -124,4 +295,13 @@ DeviceUSB::InitFromAttributes()
|
||||
BString outlineName;
|
||||
outlineName << manufacturerLabel << " " << deviceLabel;
|
||||
SetText(outlineName.String());
|
||||
|
||||
// Fetch USB attributes
|
||||
BString path = FindDevicePath("/dev/bus/usb/", fVendorId, fDeviceId);
|
||||
|
||||
if (path.Length() > 0) {
|
||||
BUSBDevice device(path.String());
|
||||
if (device.InitCheck() == B_OK)
|
||||
BuildUSBTree(device, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ Application Devices :
|
||||
DeviceUSB.cpp
|
||||
Device.cpp
|
||||
PropertyList.cpp
|
||||
: be libcolumnlistview.a tracker [ TargetLibsupc++ ]
|
||||
: be device libcolumnlistview.a tracker [ TargetLibsupc++ ]
|
||||
[ TargetLibstdc++ ] localestub
|
||||
: Devices.rdef
|
||||
;
|
||||
|
||||
Reference in New Issue
Block a user