/* * NOTE: in order for the Sony PS3 BD Remote Control to be found by * a Bluetooth host, the key combination Start+Enter has to be kept pressed * for about 7 seconds with the Bluetooth Host Controller in discovering mode. * * There will be no PIN request from the device.
*/
/* The PS3/Wii U dongles require a poke every 10 seconds, but the PS4 * requires one every 8 seconds. Using 8 seconds for all for simplicity.
*/ #define GHL_GUITAR_POKE_INTERVAL 8 /* In seconds */ #define GUITAR_TILT_USAGE 44
/* Magic data taken from GHLtarUtility: * https://github.com/ghlre/GHLtarUtility/blob/master/PS3Guitar.cs * Note: The Wii U and PS3 dongles happen to share the same!
*/ staticconstchar ghl_ps3wiiu_magic_data[] = {
0x02, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* Magic data for the PS4 dongles sniffed with a USB protocol * analyzer.
*/ staticconstchar ghl_ps4_magic_data[] = {
0x30, 0x02, 0x08, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* Use collection 1 for joypad buttons */
0xA1, 0x02, /* MCollection Logical (interrelated data) */
/* * Ignore the 1st byte, maybe it is used for a controller * number but it's not needed for correct operation
*/
0x75, 0x08, /* GReportSize 0x08 [8] */
0x95, 0x01, /* GReportCount 0x01 [1] */
0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */
/* * Bytes from 2nd to 4th are a bitmap for joypad buttons, for these * buttons multiple keypresses are allowed
*/
0x05, 0x09, /* GUsagePage Button */
0x19, 0x01, /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */
0x29, 0x18, /* LUsageMaximum 0x18 [Button 24] */
0x14, /* GLogicalMinimum [0] */
0x25, 0x01, /* GLogicalMaximum 0x01 [1] */
0x75, 0x01, /* GReportSize 0x01 [1] */
0x95, 0x18, /* GReportCount 0x18 [24] */
0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */
0xC0, /* MEndCollection */
/* Use collection 2 for remote control buttons */
0xA1, 0x02, /* MCollection Logical (interrelated data) */
staticconstunsignedint buzz_keymap[] = { /* * The controller has 4 remote buzzers, each with one LED and 5 * buttons. * * We use the mapping chosen by the controller, which is: * * Key Offset * ------------------- * Buzz 1 * Blue 5 * Orange 4 * Green 3 * Yellow 2 * * So, for example, the orange button on the third buzzer is mapped to * BTN_TRIGGER_HAPPY14
*/
[1] = BTN_TRIGGER_HAPPY1,
[2] = BTN_TRIGGER_HAPPY2,
[3] = BTN_TRIGGER_HAPPY3,
[4] = BTN_TRIGGER_HAPPY4,
[5] = BTN_TRIGGER_HAPPY5,
[6] = BTN_TRIGGER_HAPPY6,
[7] = BTN_TRIGGER_HAPPY7,
[8] = BTN_TRIGGER_HAPPY8,
[9] = BTN_TRIGGER_HAPPY9,
[10] = BTN_TRIGGER_HAPPY10,
[11] = BTN_TRIGGER_HAPPY11,
[12] = BTN_TRIGGER_HAPPY12,
[13] = BTN_TRIGGER_HAPPY13,
[14] = BTN_TRIGGER_HAPPY14,
[15] = BTN_TRIGGER_HAPPY15,
[16] = BTN_TRIGGER_HAPPY16,
[17] = BTN_TRIGGER_HAPPY17,
[18] = BTN_TRIGGER_HAPPY18,
[19] = BTN_TRIGGER_HAPPY19,
[20] = BTN_TRIGGER_HAPPY20,
};
/* The Navigation controller is a partial DS3 and uses the same HID report * and hence the same keymap indices, however not all axes/buttons * are physically present. We use the same axis and button mapping as * the DS3, which uses the Linux gamepad spec.
*/ staticconstunsignedint navigation_absmap[] = {
[0x30] = ABS_X,
[0x31] = ABS_Y,
[0x33] = ABS_Z, /* L2 */
};
/* Buttons not physically available on the device, but still available * in the reports are explicitly set to 0 for documentation purposes.
*/ staticconstunsignedint navigation_keymap[] = {
[0x01] = 0, /* Select */
[0x02] = BTN_THUMBL, /* L3 */
[0x03] = 0, /* R3 */
[0x04] = 0, /* Start */
[0x05] = BTN_DPAD_UP, /* Up */
[0x06] = BTN_DPAD_RIGHT, /* Right */
[0x07] = BTN_DPAD_DOWN, /* Down */
[0x08] = BTN_DPAD_LEFT, /* Left */
[0x09] = BTN_TL2, /* L2 */
[0x0a] = 0, /* R2 */
[0x0b] = BTN_TL, /* L1 */
[0x0c] = 0, /* R1 */
[0x0d] = BTN_NORTH, /* Triangle */
[0x0e] = BTN_EAST, /* Circle */
[0x0f] = BTN_SOUTH, /* Cross */
[0x10] = BTN_WEST, /* Square */
[0x11] = BTN_MODE, /* PS */
};
staticconstunsignedint sixaxis_absmap[] = {
[0x30] = ABS_X,
[0x31] = ABS_Y,
[0x32] = ABS_RX, /* right stick X */
[0x35] = ABS_RY, /* right stick Y */
};
struct sixaxis_led {
u8 time_enabled; /* the total time the led is active (0xff means forever) */
u8 duty_length; /* how long a cycle is in deciseconds (0 means "really fast") */
u8 enabled;
u8 duty_off; /* % of duty_length the led is off (0xff means 100%) */
u8 duty_on; /* % of duty_length the led is on (0xff mean 100%) */
} __packed;
struct sixaxis_rumble {
u8 padding;
u8 right_duration; /* Right motor duration (0xff means forever) */
u8 right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */
u8 left_duration; /* Left motor duration (0xff means forever) */
u8 left_motor_force; /* left (large) motor, supports force values from 0 to 255 */
} __packed;
key = navigation_keymap[key]; if (!key) return -1;
hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); return 1;
} elseif (usage->hid == HID_GD_POINTER) { /* See comment in sixaxis_mapping, basically the L2 (and R2) * triggers are reported through GD Pointer. * In addition we ignore any analog button 'axes' and only * support digital buttons.
*/ switch (usage->usage_index) { case 8: /* L2 */
usage->hid = HID_GD_Z; break; default: return -1;
}
key = sixaxis_keymap[key];
hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); return 1;
} elseif (usage->hid == HID_GD_POINTER) { /* The DS3 provides analog values for most buttons and even * for HAT axes through GD Pointer. L2 and R2 are reported * among these as well instead of as GD Z / RZ. Remap L2 * and R2 and ignore other analog 'button axes' as there is * no good way for reporting them.
*/ switch (usage->usage_index) { case 8: /* L2 */
usage->hid = HID_GD_Z; break; case 9: /* R2 */
usage->hid = HID_GD_RZ; break; default: return -1;
}
if (sc->quirks & (SINO_LITE_CONTROLLER | FUTUREMAX_DANCE_MAT)) return rdesc;
/* * Some Sony RF receivers wrongly declare the mouse pointer as a * a constant non-data variable.
*/ if ((sc->quirks & VAIO_RDESC_CONSTANT) && *rsize >= 56 && /* usage page: generic desktop controls */ /* rdesc[0] == 0x05 && rdesc[1] == 0x01 && */ /* usage: mouse */
rdesc[2] == 0x09 && rdesc[3] == 0x02 && /* input (usage page for x,y axes): constant, variable, relative */
rdesc[54] == 0x81 && rdesc[55] == 0x07) {
hid_info(hdev, "Fixing up Sony RF Receiver report descriptor\n"); /* input: data, variable, relative */
rdesc[55] = 0x06;
}
if (sc->quirks & MOTION_CONTROLLER) return motion_fixup(hdev, rdesc, rsize);
if (sc->quirks & PS3REMOTE) return ps3remote_fixup(hdev, rdesc, rsize);
/* * Some knock-off USB dongles incorrectly report their button count * as 13 instead of 16 causing three non-functional buttons.
*/ if ((sc->quirks & SIXAXIS_CONTROLLER_USB) && *rsize >= 45 && /* Report Count (13) */
rdesc[23] == 0x95 && rdesc[24] == 0x0D && /* Usage Maximum (13) */
rdesc[37] == 0x29 && rdesc[38] == 0x0D && /* Report Count (3) */
rdesc[43] == 0x95 && rdesc[44] == 0x03) {
hid_info(hdev, "Fixing up USB dongle report descriptor\n");
rdesc[24] = 0x10;
rdesc[38] = 0x10;
rdesc[44] = 0x00;
}
return rdesc;
}
staticvoid sixaxis_parse_report(struct sony_sc *sc, u8 *rd, int size)
{ staticconst u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 }; unsignedlong flags; int offset;
u8 battery_capacity; int battery_status;
/* * The sixaxis is charging if the battery value is 0xee * and it is fully charged if the value is 0xef. * It does not report the actual level while charging so it * is set to 100% while charging is in progress.
*/
offset = (sc->quirks & MOTION_CONTROLLER) ? 12 : 30;
staticvoid nsg_mrxu_parse_report(struct sony_sc *sc, u8 *rd, int size)
{ int n, offset, relx, rely;
u8 active;
/* * The NSG-MRxU multi-touch trackpad data starts at offset 1 and * the touch-related data starts at offset 2. * For the first byte, bit 0 is set when touchpad button is pressed. * Bit 2 is set when a touch is active and the drag (Fn) key is pressed. * This drag key is mapped to BTN_LEFT. It is operational only when a * touch point is active. * Bit 4 is set when only the first touch point is active. * Bit 6 is set when only the second touch point is active. * Bits 5 and 7 are set when both touch points are active. * The next 3 bytes are two 12 bit X/Y coordinates for the first touch. * The following byte, offset 5, has the touch width and length. * Bits 0-4=X (width), bits 5-7=Y (length). * A signed relative X coordinate is at offset 6. * The bytes at offset 7-9 are the second touch X/Y coordinates. * Offset 10 has the second touch width and length. * Offset 11 has the relative Y coordinate.
*/
offset = 1;
for (n = 0; n < 2; n++) {
u16 x, y;
u8 contactx, contacty;
x = rd[offset] | ((rd[offset+1] & 0x0F) << 8);
y = ((rd[offset+1] & 0xF0) >> 4) | (rd[offset+2] << 4);
input_mt_slot(sc->touchpad, n);
input_mt_report_slot_state(sc->touchpad, MT_TOOL_FINGER, active & 0x03);
if (active & 0x03) {
contactx = rd[offset+3] & 0x0F;
contacty = rd[offset+3] >> 4;
input_report_abs(sc->touchpad, ABS_MT_TOUCH_MAJOR,
max(contactx, contacty));
input_report_abs(sc->touchpad, ABS_MT_TOUCH_MINOR,
min(contactx, contacty));
input_report_abs(sc->touchpad, ABS_MT_ORIENTATION,
(bool) (contactx > contacty));
input_report_abs(sc->touchpad, ABS_MT_POSITION_X, x);
input_report_abs(sc->touchpad, ABS_MT_POSITION_Y,
NSG_MRXU_MAX_Y - y); /* * The relative coordinates belong to the first touch * point, when present, or to the second touch point * when the first is not active.
*/ if ((n == 0) || ((n == 1) && (active & 0x01))) {
input_report_rel(sc->touchpad, REL_X, relx);
input_report_rel(sc->touchpad, REL_Y, rely);
}
}
/* * Sixaxis HID report has acclerometers/gyro with MSByte first, this * has to be BYTE_SWAPPED before passing up to joystick interface
*/ if ((sc->quirks & SIXAXIS_CONTROLLER) && rd[0] == 0x01 && size == 49) { /* * When connected via Bluetooth the Sixaxis occasionally sends * a report with the second byte 0xff and the rest zeroed. * * This report does not reflect the actual state of the * controller must be ignored to avoid generating false input * events.
*/ if (rd[1] == 0xff) return -EINVAL;
/* Let hid-core decide for the others */ return 0;
}
staticint sony_register_touchpad(struct sony_sc *sc, int touch_count, int w, int h, int touch_major, int touch_minor, int orientation)
{
size_t name_sz; char *name; int ret;
sc->touchpad = devm_input_allocate_device(&sc->hdev->dev); if (!sc->touchpad) return -ENOMEM;
/* This suffix was originally apended when hid-sony also * supported DS4 devices. The DS4 was implemented using multiple * evdev nodes and hence had the need to separete them out using * a suffix. Other devices which were added later like Sony TV remotes * inhirited this suffix.
*/
name_sz = strlen(sc->hdev->name) + sizeof(TOUCHPAD_SUFFIX);
name = devm_kzalloc(&sc->hdev->dev, name_sz, GFP_KERNEL); if (!name) return -ENOMEM;
snprintf(name, name_sz, "%s" TOUCHPAD_SUFFIX, sc->hdev->name);
sc->touchpad->name = name;
/* We map the button underneath the touchpad to BTN_LEFT. */
__set_bit(EV_KEY, sc->touchpad->evbit);
__set_bit(BTN_LEFT, sc->touchpad->keybit);
__set_bit(INPUT_PROP_BUTTONPAD, sc->touchpad->propbit);
/* Append a suffix to the controller name as there are various * DS4 compatible non-Sony devices with different names.
*/
name_sz = strlen(sc->hdev->name) + sizeof(SENSOR_SUFFIX);
name = devm_kzalloc(&sc->hdev->dev, name_sz, GFP_KERNEL); if (!name) return -ENOMEM;
snprintf(name, name_sz, "%s" SENSOR_SUFFIX, sc->hdev->name);
sc->sensor_dev->name = name;
if (sc->quirks & SIXAXIS_CONTROLLER) { /* For the DS3 we only support the accelerometer, which works * quite well even without calibration. The device also has * a 1-axis gyro, but it is very difficult to manage from within * the driver even to get data, the sensor is inaccurate and * the behavior is very different between hardware revisions.
*/
input_set_abs_params(sc->sensor_dev, ABS_X, -512, 511, 4, 0);
input_set_abs_params(sc->sensor_dev, ABS_Y, -512, 511, 4, 0);
input_set_abs_params(sc->sensor_dev, ABS_Z, -512, 511, 4, 0);
input_abs_set_res(sc->sensor_dev, ABS_X, SIXAXIS_ACC_RES_PER_G);
input_abs_set_res(sc->sensor_dev, ABS_Y, SIXAXIS_ACC_RES_PER_G);
input_abs_set_res(sc->sensor_dev, ABS_Z, SIXAXIS_ACC_RES_PER_G);
}
ret = input_register_device(sc->sensor_dev); if (ret < 0) return ret;
return 0;
}
/* * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller * to "operational". Without this, the ps3 controller will not report any * events.
*/ staticint sixaxis_set_operational_usb(struct hid_device *hdev)
{ struct sony_sc *sc = hid_get_drvdata(hdev); constint buf_size =
max(SIXAXIS_REPORT_0xF2_SIZE, SIXAXIS_REPORT_0xF5_SIZE);
u8 *buf; int ret;
buf = kmalloc(buf_size, GFP_KERNEL); if (!buf) return -ENOMEM;
ret = hid_hw_raw_request(hdev, 0xf2, buf, SIXAXIS_REPORT_0xF2_SIZE,
HID_FEATURE_REPORT, HID_REQ_GET_REPORT); if (ret < 0) {
hid_err(hdev, "can't set operational mode: step 1\n"); goto out;
}
/* * Some compatible controllers like the Speedlink Strike FX and * Gasia need another query plus an USB interrupt to get operational.
*/
ret = hid_hw_raw_request(hdev, 0xf5, buf, SIXAXIS_REPORT_0xF5_SIZE,
HID_FEATURE_REPORT, HID_REQ_GET_REPORT); if (ret < 0) {
hid_err(hdev, "can't set operational mode: step 2\n"); goto out;
}
/* * But the USB interrupt would cause SHANWAN controllers to * start rumbling non-stop, so skip step 3 for these controllers.
*/ if (sc->quirks & SHANWAN_GAMEPAD) goto out;
ret = hid_hw_output_report(hdev, buf, 1); if (ret < 0) {
hid_info(hdev, "can't set operational mode: step 3, ignoring\n");
ret = 0;
}
drv_data = hid_get_drvdata(hdev); if (!drv_data) {
hid_err(hdev, "No device data\n"); return;
}
/* * The Sixaxis on USB will override any LED settings sent to it * and keep flashing all of the LEDs until the PS button is pressed. * Updates, even if redundant, must be always be sent to the * controller to avoid having to toggle the state of an LED just to * stop the flashing later on.
*/
force_update = !!(drv_data->quirks & SIXAXIS_CONTROLLER_USB);
for (n = 0; n < drv_data->led_count; n++) { if (led == drv_data->leds[n] && (force_update ||
(value != drv_data->led_state[n] ||
drv_data->led_delay_on[n] ||
drv_data->led_delay_off[n]))) {
drv_data->led_state[n] = value;
/* Setting the brightness stops the blinking */
drv_data->led_delay_on[n] = 0;
drv_data->led_delay_off[n] = 0;
/* * Clear LEDs as we have no way of reading their initial state. This is * only relevant if the driver is loaded after somebody actively set the * LEDs to on
*/
sony_set_leds(sc);
/* Set flag for all leds off, required for 3rd party INTEC controller */ if ((report->leds_bitmap & 0x1E) == 0)
report->leds_bitmap |= 0x20;
/* * The LEDs in the report are indexed in reverse order to their * corresponding light on the controller. * Index 0 = LED 4, index 1 = LED 3, etc... * * In the case of both delay values being zero (blinking disabled) the * default report values should be used or the controller LED will be * always off.
*/ for (n = 0; n < 4; n++) { if (sc->led_delay_on[n] || sc->led_delay_off[n]) {
report->led[3 - n].duty_off = sc->led_delay_off[n];
report->led[3 - n].duty_on = sc->led_delay_on[n];
}
}
/* * Set the default battery level to 100% to avoid low battery warnings * if the battery is polled before the first device report is received.
*/
sc->battery_capacity = 100;
/* * If a controller is plugged in via USB while already connected via Bluetooth * it will show up as two devices. A global list of connected controllers and * their MAC addresses is maintained to ensure that a device is only connected * once. * * Some USB-only devices masquerade as Sixaxis controllers and all have the * same dummy Bluetooth address, so a comparison of the connection type is * required. Devices are only rejected in the case where two devices have * matching Bluetooth addresses on different bus types.
*/ staticinlineint sony_compare_connection_type(struct sony_sc *sc0, struct sony_sc *sc1)
{ constint sc0_not_bt = !(sc0->quirks & SONY_BT_DEVICE); constint sc1_not_bt = !(sc1->quirks & SONY_BT_DEVICE);
if (sc->list_node.next) {
spin_lock_irqsave(&sony_dev_list_lock, flags);
list_del(&(sc->list_node));
spin_unlock_irqrestore(&sony_dev_list_lock, flags);
}
}
staticint sony_get_bt_devaddr(struct sony_sc *sc)
{ int ret;
/* HIDP stores the device MAC address as a string in the uniq field. */
ret = strlen(sc->hdev->uniq); if (ret != 17) return -EINVAL;
ret = sscanf(sc->hdev->uniq, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
&sc->mac_address[5], &sc->mac_address[4], &sc->mac_address[3],
&sc->mac_address[2], &sc->mac_address[1], &sc->mac_address[0]);
if (ret != 6) return -EINVAL;
return 0;
}
staticint sony_check_add(struct sony_sc *sc)
{
u8 *buf = NULL; int n, ret;
if ((sc->quirks & MOTION_CONTROLLER_BT) ||
(sc->quirks & NAVIGATION_CONTROLLER_BT) ||
(sc->quirks & SIXAXIS_CONTROLLER_BT)) { /* * sony_get_bt_devaddr() attempts to parse the Bluetooth MAC * address from the uniq string where HIDP stores it. * As uniq cannot be guaranteed to be a MAC address in all cases * a failure of this function should not prevent the connection.
*/ if (sony_get_bt_devaddr(sc) < 0) {
hid_warn(sc->hdev, "UNIQ does not contain a MAC address; duplicate check skipped\n"); return 0;
}
} elseif ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
(sc->quirks & NAVIGATION_CONTROLLER_USB)) {
buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM;
/* * The MAC address of a Sixaxis controller connected via USB can * be retrieved with feature report 0xf2. The address begins at * offset 4.
*/
ret = hid_hw_raw_request(sc->hdev, 0xf2, buf,
SIXAXIS_REPORT_0xF2_SIZE, HID_FEATURE_REPORT,
HID_REQ_GET_REPORT);
if (ret != SIXAXIS_REPORT_0xF2_SIZE) {
hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n");
ret = ret < 0 ? ret : -EINVAL; goto out_free;
}
/* * The Sixaxis device MAC in the report is big-endian and must * be byte-swapped.
*/ for (n = 0; n < 6; n++)
sc->mac_address[5-n] = buf[4+n];
staticint sony_set_device_id(struct sony_sc *sc)
{ int ret;
/* * Only Sixaxis controllers get an id. * All others are set to -1.
*/ if (sc->quirks & SIXAXIS_CONTROLLER) {
ret = ida_alloc(&sony_device_id_allocator, GFP_KERNEL); if (ret < 0) {
sc->device_id = -1; return ret;
}
sc->device_id = ret;
} else {
sc->device_id = -1;
}
staticint sony_input_configured(struct hid_device *hdev, struct hid_input *hidinput)
{ struct sony_sc *sc = hid_get_drvdata(hdev); int append_dev_id; int ret;
ret = sony_set_device_id(sc); if (ret < 0) {
hid_err(hdev, "failed to allocate the device id\n"); goto err_stop;
}
ret = append_dev_id = sony_check_add(sc); if (ret < 0) goto err_stop;
ret = sony_allocate_output_report(sc); if (ret < 0) {
hid_err(hdev, "failed to allocate the output report buffer\n"); goto err_stop;
}
if (sc->quirks & NAVIGATION_CONTROLLER_USB) { /* * The Sony Sixaxis does not handle HID Output Reports on the * Interrupt EP like it could, so we need to force HID Output * Reports to use HID_REQ_SET_REPORT on the Control EP. * * There is also another issue about HID Output Reports via USB, * the Sixaxis does not want the report_id as part of the data * packet, so we have to discard buf[0] when sending the actual * control message, even for numbered reports, humpf! * * Additionally, the Sixaxis on USB isn't properly initialized * until the PS logo button is pressed and as such won't retain * any state set by an output report, so the initial * configuration report is deferred until the first input * report arrives.
*/
hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID;
sc->defer_initialization = 1;
ret = sixaxis_set_operational_usb(hdev); if (ret < 0) {
hid_err(hdev, "Failed to set controller into operational mode\n"); goto err_stop;
}
sony_init_output_report(sc, sixaxis_send_output_report);
} elseif (sc->quirks & NAVIGATION_CONTROLLER_BT) { /* * The Navigation controller wants output reports sent on the ctrl * endpoint when connected via Bluetooth.
*/
hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
ret = sixaxis_set_operational_bt(hdev); if (ret < 0) {
hid_err(hdev, "Failed to set controller into operational mode\n"); goto err_stop;
}
sony_init_output_report(sc, sixaxis_send_output_report);
} elseif (sc->quirks & SIXAXIS_CONTROLLER_USB) { /* * The Sony Sixaxis does not handle HID Output Reports on the * Interrupt EP and the device only becomes active when the * PS button is pressed. See comment for Navigation controller * above for more details.
*/
hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID;
sc->defer_initialization = 1;
ret = sixaxis_set_operational_usb(hdev); if (ret < 0) {
hid_err(hdev, "Failed to set controller into operational mode\n"); goto err_stop;
}
ret = sony_register_sensors(sc); if (ret) {
hid_err(sc->hdev, "Unable to initialize motion sensors: %d\n", ret); goto err_stop;
}
sony_init_output_report(sc, sixaxis_send_output_report);
} elseif (sc->quirks & SIXAXIS_CONTROLLER_BT) { /* * The Sixaxis wants output reports sent on the ctrl endpoint * when connected via Bluetooth.
*/
hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
ret = sixaxis_set_operational_bt(hdev); if (ret < 0) {
hid_err(hdev, "Failed to set controller into operational mode\n"); goto err_stop;
}
ret = sony_register_sensors(sc); if (ret) {
hid_err(sc->hdev, "Unable to initialize motion sensors: %d\n", ret); goto err_stop;
}
sony_init_output_report(sc, sixaxis_send_output_report);
} elseif (sc->quirks & NSG_MRXU_REMOTE) { /* * The NSG-MRxU touchpad supports 2 touches and has a * resolution of 1667x1868
*/
ret = sony_register_touchpad(sc, 2,
NSG_MRXU_MAX_X, NSG_MRXU_MAX_Y, 15, 15, 1); if (ret) {
hid_err(sc->hdev, "Unable to initialize multi-touch slots: %d\n",
ret); goto err_stop;
}
if (sc->quirks & SONY_LED_SUPPORT) {
ret = sony_leds_init(sc); if (ret < 0) goto err_stop;
}
if (sc->quirks & SONY_BATTERY_SUPPORT) {
ret = sony_battery_probe(sc, append_dev_id); if (ret < 0) goto err_stop;
/* Open the device to receive reports with battery info */
ret = hid_hw_open(hdev); if (ret < 0) {
hid_err(hdev, "hw open failed\n"); goto err_stop;
}
}
if (sc->quirks & SONY_FF_SUPPORT) {
ret = sony_init_ff(sc); if (ret < 0) goto err_close;
}
/* Patch the hw version on DS3 compatible devices, so applications can * distinguish between the default HID mappings and the mappings defined * by the Linux game controller spec. This is important for the SDL2 * library, which has a game controller database, which uses device ids * in combination with version as a key.
*/ if (sc->quirks & SIXAXIS_CONTROLLER)
hdev->version |= 0x8000;
ret = hid_hw_start(hdev, connect_mask); if (ret) {
hid_err(hdev, "hw start failed\n"); return ret;
}
/* sony_input_configured can fail, but this doesn't result * in hid_hw_start failures (intended). Check whether * the HID layer claimed the device else fail. * We don't know the actual reason for the failure, most * likely it is due to EEXIST in case of double connection * of USB and Bluetooth, but could have been due to ENOMEM * or other reasons as well.
*/ if (!(hdev->claimed & HID_CLAIMED_INPUT)) {
hid_err(hdev, "failed to claim input\n");
ret = -ENODEV; goto err;
}
if (sc->quirks & (GHL_GUITAR_PS3WIIU | GHL_GUITAR_PS4)) { if (!hid_is_usb(hdev)) {
ret = -EINVAL; goto err;
}
/* * The Sixaxis and navigation controllers on USB need to be * reinitialized on resume or they won't behave properly.
*/ if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
(sc->quirks & NAVIGATION_CONTROLLER_USB)) {
sixaxis_set_operational_usb(sc->hdev);
sc->defer_initialization = 1;
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.73Bemerkung:
Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.