Author: mmlr Date: 2011-06-05 02:40:19 +0200 (Sun, 05 Jun 2011) New Revision: 41925 Changeset: https://dev.haiku-os.org/changeset/41925 Modified: haiku/trunk/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp haiku/trunk/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.cpp haiku/trunk/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.h Log: * 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. Modified: haiku/trunk/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp 2011-06-05 00:34:03 UTC (rev 41924) +++ haiku/trunk/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp 2011-06-05 00:40:19 UTC (rev 41925) @@ -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 @@ { 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; } } Modified: haiku/trunk/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.cpp 2011-06-05 00:34:03 UTC (rev 41924) +++ haiku/trunk/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.cpp 2011-06-05 00:40:19 UTC (rev 41925) @@ -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 @@ } -#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 Modified: haiku/trunk/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.h =================================================================== --- haiku/trunk/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.h 2011-06-05 00:34:03 UTC (rev 41924) +++ haiku/trunk/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.h 2011-06-05 00:40:19 UTC (rev 41925) @@ -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[];