Expand usb_raw ioctl to support retrieving full usb configuration descriptor from userland, not only the header part.

I try to keep UBSConfiguration binary compatibility, but proofreading is welcome.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42812 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Philippe Houdoin
2011-10-09 15:15:15 +00:00
parent 13cb2a2930
commit d41559757e
4 changed files with 62 additions and 13 deletions
+2 -1
View File
@@ -204,7 +204,8 @@ friend class BUSBDevice;
mutable char * fConfigurationString; mutable char * fConfigurationString;
uint32 fReserved[10]; usb_configuration_descriptor* fFullDescriptor;
uint32 fReserved[9];
}; };
+18 -5
View File
@@ -300,23 +300,36 @@ usb_raw_ioctl(void *cookie, uint32 op, void *buffer, size_t length)
} }
case B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR: case B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR:
case B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR_ETC:
{ {
if (length < sizeof(command->config)) if (length < sizeof(command->config))
return B_BUFFER_OVERFLOW; return B_BUFFER_OVERFLOW;
size_t descriptorLength = sizeof(usb_configuration_descriptor);
if (op == B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR_ETC) {
if (length < sizeof(command->config_etc))
return B_BUFFER_OVERFLOW;
descriptorLength = command->config_etc.length;
}
const usb_configuration_info *configurationInfo = const usb_configuration_info *configurationInfo =
usb_raw_get_configuration(device, command->config.config_index, usb_raw_get_configuration(device, command->config.config_index,
&command->config.status); &command->config.status);
if (configurationInfo == NULL) if (configurationInfo == NULL)
return B_OK; return B_OK;
if (user_memcpy(command->config.descriptor, const usb_configuration_descriptor* descriptor
configurationInfo->descr, = configurationInfo->descr;
sizeof(usb_configuration_descriptor)) != B_OK) { if (user_memcpy(command->config.descriptor, descriptor,
min_c(descriptorLength, descriptor->total_length)) != B_OK) {
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
} }
if (op == B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR_ETC
command->config.status = B_USB_RAW_STATUS_SUCCESS; && descriptor->total_length > descriptorLength)
command->config.status = B_USB_RAW_STATUS_NO_MEMORY;
else
command->config.status = B_USB_RAW_STATUS_SUCCESS;
return B_OK; return B_OK;
} }
+9 -1
View File
@@ -22,10 +22,11 @@ typedef enum {
B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR, B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR,
B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT, B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT,
B_USB_RAW_COMMAND_GET_ACTIVE_ALT_INTERFACE_INDEX, B_USB_RAW_COMMAND_GET_ACTIVE_ALT_INTERFACE_INDEX,
B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR_ETC,
B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR_ETC, B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR_ETC,
B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR_ETC, B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR_ETC,
B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR_ETC, B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR_ETC,
B_USB_RAW_COMMAND_SET_CONFIGURATION = 0x3000, B_USB_RAW_COMMAND_SET_CONFIGURATION = 0x3000,
B_USB_RAW_COMMAND_SET_FEATURE, B_USB_RAW_COMMAND_SET_FEATURE,
B_USB_RAW_COMMAND_CLEAR_FEATURE, B_USB_RAW_COMMAND_CLEAR_FEATURE,
@@ -74,6 +75,13 @@ typedef union {
uint32 config_index; uint32 config_index;
} config; } config;
struct {
status_t status;
usb_configuration_descriptor *descriptor;
uint32 config_index;
size_t length;
} config_etc;
struct { struct {
status_t status; status_t status;
uint32 alternate_info; uint32 alternate_info;
+33 -6
View File
@@ -8,9 +8,12 @@
#include <USBKit.h> #include <USBKit.h>
#include <usb_raw.h> #include <usb_raw.h>
#include <unistd.h>
#include <string.h>
#include <new> #include <new>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
BUSBConfiguration::BUSBConfiguration(BUSBDevice *device, uint32 index, int rawFD) BUSBConfiguration::BUSBConfiguration(BUSBDevice *device, uint32 index, int rawFD)
@@ -18,14 +21,36 @@ BUSBConfiguration::BUSBConfiguration(BUSBDevice *device, uint32 index, int rawFD
fIndex(index), fIndex(index),
fRawFD(rawFD), fRawFD(rawFD),
fInterfaces(NULL), fInterfaces(NULL),
fConfigurationString(NULL) fConfigurationString(NULL),
fFullDescriptor(NULL)
{ {
usb_raw_command command; usb_raw_command command;
command.config.descriptor = &fDescriptor; command.config.descriptor = &fDescriptor;
command.config.config_index = fIndex; command.config.config_index = fIndex;
if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR, &command,
sizeof(command)) || command.config.status != B_USB_RAW_STATUS_SUCCESS) if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR,
&command, sizeof(command))
|| command.config.status != B_USB_RAW_STATUS_SUCCESS) {
memset(&fDescriptor, 0, sizeof(fDescriptor)); memset(&fDescriptor, 0, sizeof(fDescriptor));
} else {
// Got the descriptor header, retrieve the whole descriptor
size_t length = fDescriptor.total_length;
fFullDescriptor = (usb_configuration_descriptor*)malloc(length);
if (fFullDescriptor != NULL) {
command.config_etc.descriptor = fFullDescriptor;
command.config_etc.config_index = fIndex;
command.config_etc.length = length;
if (ioctl(fRawFD, B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR_ETC,
&command, sizeof(command))
|| command.config_etc.status != B_USB_RAW_STATUS_SUCCESS) {
free(fFullDescriptor);
fFullDescriptor = NULL;
}
}
}
fInterfaces = new(std::nothrow) BUSBInterface *[ fInterfaces = new(std::nothrow) BUSBInterface *[
fDescriptor.number_interfaces]; fDescriptor.number_interfaces];
@@ -41,6 +66,8 @@ BUSBConfiguration::BUSBConfiguration(BUSBDevice *device, uint32 index, int rawFD
BUSBConfiguration::~BUSBConfiguration() BUSBConfiguration::~BUSBConfiguration()
{ {
free(fFullDescriptor);
delete[] fConfigurationString; delete[] fConfigurationString;
if (fInterfaces != NULL) { if (fInterfaces != NULL) {
for (int32 i = 0; i < fDescriptor.number_interfaces; i++) for (int32 i = 0; i < fDescriptor.number_interfaces; i++)
@@ -85,7 +112,7 @@ BUSBConfiguration::ConfigurationString() const
const usb_configuration_descriptor * const usb_configuration_descriptor *
BUSBConfiguration::Descriptor() const BUSBConfiguration::Descriptor() const
{ {
return &fDescriptor; return (fFullDescriptor != NULL) ? fFullDescriptor : &fDescriptor;
} }