* Reimplement the descriptor patching mechanism for quirky devices by a function

to build a new descriptor using a HIDWriter. This way a completely new
  descriptor can be built on the fly or a fixed already patched blob can be
  written to the writer if desired.
* Implemented writing a new report descriptor for Sony SIXAXIS controllers. The
  descriptor also includes the pressure sensitive button states (exposed as 12
  axes) and the accelerometers/gyroscope (exposed as another 4 axes). While the
  motion sensing data is now available (and fun to look at), the usefulness is
  fairly limited, as the values are not scaled/transformed in any way. It might
  be possible to generically do such transformations using unit descriptions,
  but those are not implemented yet.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41925 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2011-06-05 00:40:19 +00:00
parent 517851a173
commit d3260cdb5f
3 changed files with 75 additions and 12 deletions

View File

@ -10,6 +10,7 @@
#include "Driver.h"
#include "HIDDevice.h"
#include "HIDReport.h"
#include "HIDWriter.h"
#include "ProtocolHandler.h"
#include "QuirkyDevices.h"
@ -39,25 +40,29 @@ HIDDevice::HIDDevice(usb_device device, const usb_configuration_info *config,
{
uint8 *reportDescriptor = NULL;
size_t descriptorLength = 0;
quirky_init_function quirkyInit = NULL;
bool hasFixedDescriptor = false;
const usb_device_descriptor *deviceDescriptor
= gUSBModule->get_device_descriptor(device);
// check for quirky devices first and don't bother in that case
HIDWriter descriptorWriter;
bool hasFixedDescriptor = false;
quirky_init_function quirkyInit = NULL;
for (int32 i = 0; i < gQuirkyDeviceCount; i++) {
usb_hid_quirky_device &quirky = gQuirkyDevices[i];
if (deviceDescriptor->vendor_id == quirky.vendor_id
&& deviceDescriptor->product_id == quirky.product_id) {
quirkyInit = quirky.init_function;
if (quirky.fixed_descriptor != NULL) {
reportDescriptor = (uint8 *)quirky.fixed_descriptor;
descriptorLength = quirky.descriptor_length;
if (quirky.build_descriptor != NULL
&& quirky.build_descriptor(descriptorWriter) == B_OK) {
reportDescriptor = (uint8 *)descriptorWriter.Buffer();
descriptorLength = descriptorWriter.BufferLength();
hasFixedDescriptor = true;
break;
}
break;
}
}

View File

@ -6,16 +6,20 @@
#include "QuirkyDevices.h"
#include "HIDWriter.h"
#include <string.h>
#include <usb/USB_hid.h>
status_t
static status_t
sixaxis_init(usb_device device, const usb_configuration_info *config,
size_t interfaceIndex)
{
TRACE_ALWAYS("found SIXAXIS controller, putting it in operational mode\n");
// an extra get_report is required for the SIXAXIS to become operational
uint8 dummy[18];
status_t result = gUSBModule->send_request(device, USB_REQTYPE_INTERFACE_IN
| USB_REQTYPE_CLASS, B_USB_REQUEST_HID_GET_REPORT, 0x03f2 /* ? */,
@ -28,12 +32,64 @@ sixaxis_init(usb_device device, const usb_configuration_info *config,
}
#define ADD_QUIRKY_DEVICE(vendorID, productID, descriptor, init) \
{ vendorID, productID, sizeof(descriptor), descriptor, init }
static status_t
sixaxis_build_descriptor(HIDWriter &writer)
{
writer.BeginCollection(COLLECTION_APPLICATION,
B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_JOYSTICK);
main_item_data_converter converter;
converter.flat_data = 0; // defaults
converter.main_data.array_variable = 1;
converter.main_data.no_preferred = 1;
// unknown / padding
writer.DefineInputPadding(1, 1, 8);
// digital button state on/off
writer.DefineInputData(1, 19, 1, converter.main_data, 0, 1,
B_HID_USAGE_PAGE_BUTTON, 1);
// padding to 32 bit boundary
writer.DefineInputPadding(1, 13, 1);
// left analog stick
writer.DefineInputData(1, 1, 8, converter.main_data, 0, 255,
B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_X);
writer.DefineInputData(1, 1, 8, converter.main_data, 0, 255,
B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_Y);
// right analog stick
writer.DefineInputData(1, 1, 8, converter.main_data, 0, 255,
B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_X);
writer.DefineInputData(1, 1, 8, converter.main_data, 0, 255,
B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_Y);
// unknown / padding
writer.DefineInputPadding(1, 4, 8);
// pressure sensitive button states
writer.DefineInputData(1, 12, 8, converter.main_data, 0, 255,
B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_VNO, B_HID_UID_GD_VNO);
// unknown / padding / operation mode / battery status / connection ...
writer.DefineInputPadding(1, 15, 8);
// accelerometer x, y and z
writer.DefineInputData(1, 3, 16, converter.main_data, 0, UINT16_MAX,
B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_VX);
// gyroscope
writer.DefineInputData(1, 1, 16, converter.main_data, 0, UINT16_MAX,
B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_VBRZ);
return writer.EndCollection();
}
usb_hid_quirky_device gQuirkyDevices[] = {
// Sony SIXAXIS controller (PS3) needs a GET_REPORT to become operational
ADD_QUIRKY_DEVICE(0x054c, 0x0268, NULL, sixaxis_init),
{ 0x054c, 0x0268, sixaxis_init, sixaxis_build_descriptor }
};
int32 gQuirkyDeviceCount

View File

@ -7,15 +7,17 @@
#include "Driver.h"
class HIDWriter;
typedef status_t (*quirky_init_function)(usb_device device,
const usb_configuration_info *config, size_t interfaceIndex);
typedef status_t (*quirky_build_descriptor)(HIDWriter &writer);
struct usb_hid_quirky_device {
uint16 vendor_id;
uint16 product_id;
size_t descriptor_length;
const uint8 * fixed_descriptor;
quirky_init_function init_function;
quirky_build_descriptor build_descriptor;
};
extern usb_hid_quirky_device gQuirkyDevices[];