1 /* 2 * Copyright 2011 Michael Lotz <mmlr@mlotz.ch> 3 * Distributed under the terms of the MIT license. 4 */ 5 6 7 #include "QuirkyDevices.h" 8 9 #include "HIDWriter.h" 10 11 #include <string.h> 12 13 #include <usb/USB_hid.h> 14 15 16 static status_t 17 sixaxis_init(usb_device device, const usb_configuration_info *config, 18 size_t interfaceIndex) 19 { 20 TRACE_ALWAYS("found SIXAXIS controller, putting it in operational mode\n"); 21 22 // an extra get_report is required for the SIXAXIS to become operational 23 uint8 dummy[18]; 24 status_t result = gUSBModule->send_request(device, USB_REQTYPE_INTERFACE_IN 25 | USB_REQTYPE_CLASS, B_USB_REQUEST_HID_GET_REPORT, 0x03f2 /* ? */, 26 interfaceIndex, sizeof(dummy), dummy, NULL); 27 if (result != B_OK) { 28 TRACE_ALWAYS("failed to set operational mode: %s\n", strerror(result)); 29 } 30 31 return result; 32 } 33 34 35 static status_t 36 sixaxis_build_descriptor(HIDWriter &writer) 37 { 38 writer.BeginCollection(COLLECTION_APPLICATION, 39 B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_JOYSTICK); 40 41 main_item_data_converter converter; 42 converter.flat_data = 0; // defaults 43 converter.main_data.array_variable = 1; 44 converter.main_data.no_preferred = 1; 45 46 writer.SetReportID(1); 47 48 // unknown / padding 49 writer.DefineInputPadding(1, 8); 50 51 // digital button state on/off 52 writer.DefineInputData(19, 1, converter.main_data, 0, 1, 53 B_HID_USAGE_PAGE_BUTTON, 1); 54 55 // padding to 32 bit boundary 56 writer.DefineInputPadding(13, 1); 57 58 // left analog stick 59 writer.DefineInputData(1, 8, converter.main_data, 0, 255, 60 B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_X); 61 writer.DefineInputData(1, 8, converter.main_data, 0, 255, 62 B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_Y); 63 64 // right analog stick 65 writer.DefineInputData(1, 8, converter.main_data, 0, 255, 66 B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_X); 67 writer.DefineInputData(1, 8, converter.main_data, 0, 255, 68 B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_Y); 69 70 // unknown / padding 71 writer.DefineInputPadding(4, 8); 72 73 // pressure sensitive button states 74 writer.DefineInputData(12, 8, converter.main_data, 0, 255, 75 B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_VNO, B_HID_UID_GD_VNO); 76 77 // unknown / padding / operation mode / battery status / connection ... 78 writer.DefineInputPadding(15, 8); 79 80 // accelerometer x, y and z 81 writer.DefineInputData(3, 16, converter.main_data, 0, UINT16_MAX, 82 B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_VX); 83 84 // gyroscope 85 writer.DefineInputData(1, 16, converter.main_data, 0, UINT16_MAX, 86 B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_VBRZ); 87 88 return writer.EndCollection(); 89 } 90 91 92 static status_t 93 xbox360_build_descriptor(HIDWriter &writer) 94 { 95 writer.BeginCollection(COLLECTION_APPLICATION, 96 B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_JOYSTICK); 97 98 main_item_data_converter converter; 99 converter.flat_data = 0; // defaults 100 converter.main_data.array_variable = 1; 101 converter.main_data.no_preferred = 1; 102 103 // unknown / padding / byte count 104 writer.DefineInputPadding(2, 8); 105 106 // dpad / buttons 107 writer.DefineInputData(11, 1, converter.main_data, 0, 1, 108 B_HID_USAGE_PAGE_BUTTON, 1); 109 writer.DefineInputPadding(1, 1); 110 writer.DefineInputData(4, 1, converter.main_data, 0, 1, 111 B_HID_USAGE_PAGE_BUTTON, 12); 112 113 // triggers 114 writer.DefineInputData(1, 8, converter.main_data, 0, 255, 115 B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_Z); 116 writer.DefineInputData(1, 8, converter.main_data, 0, 255, 117 B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_RZ); 118 119 // sticks 120 writer.DefineInputData(2, 16, converter.main_data, -32768, 32767, 121 B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_X); 122 writer.DefineInputData(2, 16, converter.main_data, -32768, 32767, 123 B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_X); 124 125 // unknown / padding 126 writer.DefineInputPadding(6, 8); 127 128 return writer.EndCollection(); 129 } 130 131 132 usb_hid_quirky_device gQuirkyDevices[] = { 133 { 134 // The Sony SIXAXIS controller (PS3) needs a GET_REPORT to become 135 // operational which we do in sixaxis_init. Also the normal report 136 // descriptor doesn't contain items for the motion sensing data 137 // and pressure sensitive buttons, so we constrcut a new report 138 // descriptor that includes those extra items. 139 0x054c, 0x0268, USB_INTERFACE_CLASS_HID, 0, 0, 140 sixaxis_init, sixaxis_build_descriptor 141 }, 142 143 { 144 // XBOX 360 controllers aren't really HID (marked vendor specific). 145 // They therefore don't provide a HID/report descriptor either. The 146 // input stream is HID-like enough though. We therefore claim support 147 // and build a report descriptor of our own. 148 0, 0, 0xff /* vendor specific */, 0x5d /* XBOX controller */, 0x01, 149 NULL, xbox360_build_descriptor 150 } 151 }; 152 153 int32 gQuirkyDeviceCount 154 = sizeof(gQuirkyDevices) / sizeof(gQuirkyDevices[0]); 155