diff --git a/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp b/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp index a7c9a7bf2a..8fc93ffdef 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp +++ b/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp @@ -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; } } diff --git a/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.cpp b/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.cpp index 8e45e7b2e0..528094e336 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.cpp +++ b/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.cpp @@ -6,16 +6,20 @@ #include "QuirkyDevices.h" +#include "HIDWriter.h" + #include #include -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 diff --git a/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.h b/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.h index 181c10bf80..d7f90b86c1 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.h +++ b/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.h @@ -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[];