* Make the quirky device mechanism a bit more useful by allowing an init

function that is triggered before the protocol handlers are added.
* Use the quirky device mechanism to support the Sony SIXAXIS controller (the
  PS3 one). It requires a specific get_report to become operational. Note that
  you still have to push the PS button to enable it after plugging in. Note also
  that only the two analog sticks are reported as axis, the analog values of the
  buttons as well as the motion sensors aren't described by the HID descriptor
  and therefore aren't accessible. The digital button states (on/off only) work
  however. A fixed descriptor could possibly be crafted to support the missing
  features later on though.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41902 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2011-06-04 12:47:02 +00:00
parent 84cb679caa
commit 6e53f9a990
4 changed files with 73 additions and 23 deletions
@@ -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;
@@ -16,6 +16,8 @@ KernelAddon usb_hid :
HIDReport.cpp
HIDReportItem.cpp
QuirkyDevices.cpp
ProtocolHandler.cpp
JoystickProtocolHandler.cpp
@@ -0,0 +1,40 @@
/*
* Copyright 2011 Michael Lotz <[email protected]>
* Distributed under the terms of the MIT license.
*/
#include "QuirkyDevices.h"
#include <string.h>
#include <usb/USB_hid.h>
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]);
@@ -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