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 9db4753d23..a7c9a7bf2a 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp +++ b/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp @@ -39,24 +39,29 @@ HIDDevice::HIDDevice(usb_device device, const usb_configuration_info *config, { uint8 *reportDescriptor = NULL; size_t descriptorLength = 0; - bool isQuirky = false; + 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 - for (int32 i = 0; i < sQuirkyDeviceCount; i++) { - usb_hid_quirky_device &quirky = sQuirkyDevices[i]; + 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) { - reportDescriptor = (uint8 *)quirky.fixed_descriptor; - descriptorLength = quirky.descriptor_length; - isQuirky = true; - break; + + quirkyInit = quirky.init_function; + if (quirky.fixed_descriptor != NULL) { + reportDescriptor = (uint8 *)quirky.fixed_descriptor; + descriptorLength = quirky.descriptor_length; + hasFixedDescriptor = true; + break; + } } } - if (!isQuirky) { + if (!hasFixedDescriptor) { // conforming device, read HID and report descriptors descriptorLength = sizeof(usb_hid_descriptor); usb_hid_descriptor *hidDescriptor @@ -122,7 +127,7 @@ HIDDevice::HIDDevice(usb_device device, const usb_configuration_info *config, status_t result = fParser.ParseReportDescriptor(reportDescriptor, descriptorLength); - if (!isQuirky) + if (!hasFixedDescriptor) free(reportDescriptor); if (result != B_OK) { @@ -166,6 +171,12 @@ HIDDevice::HIDDevice(usb_device device, const usb_configuration_info *config, return; } + if (quirkyInit != NULL) { + fStatus = quirkyInit(device, config, interfaceIndex); + if (fStatus != B_OK) + return; + } + ProtocolHandler::AddHandlers(*this, fProtocolHandlerList, fProtocolHandlerCount); fStatus = B_OK; diff --git a/src/add-ons/kernel/drivers/input/usb_hid/Jamfile b/src/add-ons/kernel/drivers/input/usb_hid/Jamfile index bdccce7c81..913ccd2ea1 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/Jamfile +++ b/src/add-ons/kernel/drivers/input/usb_hid/Jamfile @@ -16,6 +16,8 @@ KernelAddon usb_hid : HIDReport.cpp HIDReportItem.cpp + QuirkyDevices.cpp + ProtocolHandler.cpp JoystickProtocolHandler.cpp diff --git a/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.cpp b/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.cpp new file mode 100644 index 0000000000..8e45e7b2e0 --- /dev/null +++ b/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.cpp @@ -0,0 +1,40 @@ +/* + * Copyright 2011 Michael Lotz + * Distributed under the terms of the MIT license. + */ + + +#include "QuirkyDevices.h" + +#include + +#include + + +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"); + uint8 dummy[18]; + status_t result = gUSBModule->send_request(device, USB_REQTYPE_INTERFACE_IN + | USB_REQTYPE_CLASS, B_USB_REQUEST_HID_GET_REPORT, 0x03f2 /* ? */, + interfaceIndex, sizeof(dummy), dummy, NULL); + if (result != B_OK) { + TRACE_ALWAYS("failed to set operational mode: %s\n", strerror(result)); + } + + return result; +} + + +#define ADD_QUIRKY_DEVICE(vendorID, productID, descriptor, init) \ + { vendorID, productID, sizeof(descriptor), descriptor, init } + +usb_hid_quirky_device gQuirkyDevices[] = { + // Sony SIXAXIS controller (PS3) needs a GET_REPORT to become operational + ADD_QUIRKY_DEVICE(0x054c, 0x0268, NULL, sixaxis_init), +}; + +int32 gQuirkyDeviceCount + = sizeof(gQuirkyDevices) / sizeof(gQuirkyDevices[0]); 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 fe7c251b85..181c10bf80 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.h +++ b/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.h @@ -5,23 +5,20 @@ #ifndef USB_HID_QUIRKY_DEVICES #define USB_HID_QUIRKY_DEVICES -static uint8 sDescriptorExample[] = { 0x00, 0x00 }; +#include "Driver.h" + +typedef status_t (*quirky_init_function)(usb_device device, + const usb_configuration_info *config, size_t interfaceIndex); struct usb_hid_quirky_device { - uint16 vendor_id; - uint16 product_id; - size_t descriptor_length; - const uint8 * fixed_descriptor; + uint16 vendor_id; + uint16 product_id; + size_t descriptor_length; + const uint8 * fixed_descriptor; + quirky_init_function init_function; }; -#define ADD_QUIRKY_DEVICE(vendorID, productID, descriptor) \ - { vendorID, productID, sizeof(descriptor), descriptor } - -static usb_hid_quirky_device sQuirkyDevices[] = { - ADD_QUIRKY_DEVICE(0xffff, 0xffff, sDescriptorExample) -}; - -static int32 sQuirkyDeviceCount - = sizeof(sQuirkyDevices) / sizeof(sQuirkyDevices[0]); +extern usb_hid_quirky_device gQuirkyDevices[]; +extern int32 gQuirkyDeviceCount; #endif // USB_HID_QUIRKY_DEVICES