Blame view
drivers/hid/hid-sony.c
85.9 KB
bd28ce008 HID: move sony qu... |
1 |
/* |
077147a30 HID: sony: Update... |
2 |
* HID driver for Sony / PS2 / PS3 / PS4 BD devices. |
bd28ce008 HID: move sony qu... |
3 4 5 6 |
* * Copyright (c) 1999 Andreas Gal * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc |
bd28ce008 HID: move sony qu... |
7 |
* Copyright (c) 2008 Jiri Slaby |
078328da5 HID: fold ps3remo... |
8 9 |
* Copyright (c) 2012 David Dillow <dave@thedillows.org> * Copyright (c) 2006-2013 Jiri Kosina |
f04d51404 HID: driver for P... |
10 |
* Copyright (c) 2013 Colin Leitner <colin.leitner@gmail.com> |
c4425c8f2 HID: sony: Update... |
11 |
* Copyright (c) 2014-2016 Frank Praznik <frank.praznik@gmail.com> |
bd28ce008 HID: move sony qu... |
12 13 14 15 16 17 18 19 |
*/ /* * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. */ |
ad142b9e4 HID: sony: Fix mu... |
20 21 |
/* * NOTE: in order for the Sony PS3 BD Remote Control to be found by |
078328da5 HID: fold ps3remo... |
22 23 24 25 26 |
* 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. */ |
bd28ce008 HID: move sony qu... |
27 28 29 |
#include <linux/device.h> #include <linux/hid.h> #include <linux/module.h> |
5a0e3ad6a include cleanup: ... |
30 |
#include <linux/slab.h> |
40e32ee6e HID: sony: fix le... |
31 |
#include <linux/leds.h> |
d902f4724 HID: sony: add ba... |
32 33 |
#include <linux/power_supply.h> #include <linux/spinlock.h> |
d2d782fcc HID: sony: Preven... |
34 |
#include <linux/list.h> |
8025087ac HID: sony: Initia... |
35 |
#include <linux/idr.h> |
e56062305 HID: sony: add ou... |
36 |
#include <linux/input/mt.h> |
49b9ca6c6 HID: sony: Perfor... |
37 38 |
#include <linux/crc32.h> #include <asm/unaligned.h> |
bd28ce008 HID: move sony qu... |
39 40 |
#include "hid-ids.h" |
6c79c18c9 HID: sony: Fix sp... |
41 42 43 44 45 |
#define VAIO_RDESC_CONSTANT BIT(0) #define SIXAXIS_CONTROLLER_USB BIT(1) #define SIXAXIS_CONTROLLER_BT BIT(2) #define BUZZ_CONTROLLER BIT(3) #define PS3REMOTE BIT(4) |
8ab1676b6 HID: sony: Use se... |
46 47 |
#define DUALSHOCK4_CONTROLLER_USB BIT(5) #define DUALSHOCK4_CONTROLLER_BT BIT(6) |
35f436c31 HID: sony: Treat ... |
48 49 50 51 52 53 54 |
#define DUALSHOCK4_DONGLE BIT(7) #define MOTION_CONTROLLER_USB BIT(8) #define MOTION_CONTROLLER_BT BIT(9) #define NAVIGATION_CONTROLLER_USB BIT(10) #define NAVIGATION_CONTROLLER_BT BIT(11) #define SINO_LITE_CONTROLLER BIT(12) #define FUTUREMAX_DANCE_MAT BIT(13) |
cc6e0bbb4 HID: Add support ... |
55 |
|
fee4e2d52 HID: sony: Enable... |
56 |
#define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT) |
b3bca326f HID: sony: Add qu... |
57 |
#define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT) |
4545ee0a7 HID: hid-sony: Na... |
58 59 |
#define NAVIGATION_CONTROLLER (NAVIGATION_CONTROLLER_USB |\ NAVIGATION_CONTROLLER_BT) |
68330d83c HID: sony: Add co... |
60 |
#define DUALSHOCK4_CONTROLLER (DUALSHOCK4_CONTROLLER_USB |\ |
35f436c31 HID: sony: Treat ... |
61 62 |
DUALSHOCK4_CONTROLLER_BT | \ DUALSHOCK4_DONGLE) |
fee4e2d52 HID: sony: Enable... |
63 |
#define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\ |
4545ee0a7 HID: hid-sony: Na... |
64 65 |
DUALSHOCK4_CONTROLLER | MOTION_CONTROLLER |\ NAVIGATION_CONTROLLER) |
12e9a6d72 HID: sony: Add su... |
66 |
#define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\ |
4545ee0a7 HID: hid-sony: Na... |
67 |
MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER) |
c5e0c1c49 HID: sony: Add su... |
68 69 |
#define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\ MOTION_CONTROLLER) |
0f3982308 HID: sony: Relax ... |
70 71 |
#define SONY_BT_DEVICE (SIXAXIS_CONTROLLER_BT | DUALSHOCK4_CONTROLLER_BT |\ MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER_BT) |
60781cf48 HID: sony: Add LE... |
72 73 |
#define MAX_LEDS 4 |
0a286ef27 HID: sony: Add LE... |
74 |
|
e57a67da6 HID: hid-sony: fi... |
75 |
|
c5e0c1c49 HID: sony: Add su... |
76 |
/* PS/3 Motion controller */ |
1adf904e9 HID: sony: unders... |
77 |
static u8 motion_rdesc[] = { |
c5e0c1c49 HID: sony: Add su... |
78 79 80 81 82 |
0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x04, /* Usage (Joystick), */ 0xA1, 0x01, /* Collection (Application), */ 0xA1, 0x02, /* Collection (Logical), */ 0x85, 0x01, /* Report ID (1), */ |
c5e0c1c49 HID: sony: Add su... |
83 |
0x75, 0x01, /* Report Size (1), */ |
8b2513c31 HID: sony: PS Mov... |
84 |
0x95, 0x15, /* Report Count (21), */ |
c5e0c1c49 HID: sony: Add su... |
85 86 87 88 89 90 |
0x15, 0x00, /* Logical Minimum (0), */ 0x25, 0x01, /* Logical Maximum (1), */ 0x35, 0x00, /* Physical Minimum (0), */ 0x45, 0x01, /* Physical Maximum (1), */ 0x05, 0x09, /* Usage Page (Button), */ 0x19, 0x01, /* Usage Minimum (01h), */ |
8b2513c31 HID: sony: PS Mov... |
91 92 93 |
0x29, 0x15, /* Usage Maximum (15h), */ 0x81, 0x02, /* Input (Variable), * Buttons */ 0x95, 0x0B, /* Report Count (11), */ |
c5e0c1c49 HID: sony: Add su... |
94 |
0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ |
8b2513c31 HID: sony: PS Mov... |
95 |
0x81, 0x03, /* Input (Constant, Variable), * Padding */ |
c5e0c1c49 HID: sony: Add su... |
96 97 98 |
0x15, 0x00, /* Logical Minimum (0), */ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 0x05, 0x01, /* Usage Page (Desktop), */ |
c5e0c1c49 HID: sony: Add su... |
99 100 |
0xA1, 0x00, /* Collection (Physical), */ 0x75, 0x08, /* Report Size (8), */ |
8b2513c31 HID: sony: PS Mov... |
101 |
0x95, 0x01, /* Report Count (1), */ |
c5e0c1c49 HID: sony: Add su... |
102 103 104 |
0x35, 0x00, /* Physical Minimum (0), */ 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 0x09, 0x30, /* Usage (X), */ |
8b2513c31 HID: sony: PS Mov... |
105 |
0x81, 0x02, /* Input (Variable), * Trigger */ |
c5e0c1c49 HID: sony: Add su... |
106 |
0xC0, /* End Collection, */ |
8b2513c31 HID: sony: PS Mov... |
107 108 109 |
0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 0x75, 0x08, /* Report Size (8), */ 0x95, 0x07, /* Report Count (7), * skip 7 bytes */ |
c5e0c1c49 HID: sony: Add su... |
110 |
0x81, 0x02, /* Input (Variable), */ |
8b2513c31 HID: sony: PS Mov... |
111 |
0x05, 0x01, /* Usage Page (Desktop), */ |
c5e0c1c49 HID: sony: Add su... |
112 |
0x75, 0x10, /* Report Size (16), */ |
8b2513c31 HID: sony: PS Mov... |
113 114 115 116 117 118 119 120 121 122 123 |
0x46, 0xFF, 0xFF, /* Physical Maximum (65535), */ 0x27, 0xFF, 0xFF, 0x00, 0x00, /* Logical Maximum (65535), */ 0x95, 0x03, /* Report Count (3), * 3x Accels */ 0x09, 0x33, /* Usage (rX), */ 0x09, 0x34, /* Usage (rY), */ 0x09, 0x35, /* Usage (rZ), */ 0x81, 0x02, /* Input (Variable), */ 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 0x95, 0x03, /* Report Count (3), * Skip Accels 2nd frame */ 0x81, 0x02, /* Input (Variable), */ 0x05, 0x01, /* Usage Page (Desktop), */ |
c5e0c1c49 HID: sony: Add su... |
124 |
0x09, 0x01, /* Usage (Pointer), */ |
8b2513c31 HID: sony: PS Mov... |
125 126 127 128 |
0x95, 0x03, /* Report Count (3), * 3x Gyros */ 0x81, 0x02, /* Input (Variable), */ 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 0x95, 0x03, /* Report Count (3), * Skip Gyros 2nd frame */ |
c5e0c1c49 HID: sony: Add su... |
129 |
0x81, 0x02, /* Input (Variable), */ |
8b2513c31 HID: sony: PS Mov... |
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
0x75, 0x0C, /* Report Size (12), */ 0x46, 0xFF, 0x0F, /* Physical Maximum (4095), */ 0x26, 0xFF, 0x0F, /* Logical Maximum (4095), */ 0x95, 0x04, /* Report Count (4), * Skip Temp and Magnetometers */ 0x81, 0x02, /* Input (Variable), */ 0x75, 0x08, /* Report Size (8), */ 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 0x95, 0x06, /* Report Count (6), * Skip Timestamp and Extension Bytes */ 0x81, 0x02, /* Input (Variable), */ 0x75, 0x08, /* Report Size (8), */ 0x95, 0x30, /* Report Count (48), */ 0x09, 0x01, /* Usage (Pointer), */ 0x91, 0x02, /* Output (Variable), */ 0x75, 0x08, /* Report Size (8), */ 0x95, 0x30, /* Report Count (48), */ 0x09, 0x01, /* Usage (Pointer), */ 0xB1, 0x02, /* Feature (Variable), */ |
c5e0c1c49 HID: sony: Add su... |
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
0xC0, /* End Collection, */ 0xA1, 0x02, /* Collection (Logical), */ 0x85, 0x02, /* Report ID (2), */ 0x75, 0x08, /* Report Size (8), */ 0x95, 0x30, /* Report Count (48), */ 0x09, 0x01, /* Usage (Pointer), */ 0xB1, 0x02, /* Feature (Variable), */ 0xC0, /* End Collection, */ 0xA1, 0x02, /* Collection (Logical), */ 0x85, 0xEE, /* Report ID (238), */ 0x75, 0x08, /* Report Size (8), */ 0x95, 0x30, /* Report Count (48), */ 0x09, 0x01, /* Usage (Pointer), */ 0xB1, 0x02, /* Feature (Variable), */ 0xC0, /* End Collection, */ 0xA1, 0x02, /* Collection (Logical), */ 0x85, 0xEF, /* Report ID (239), */ 0x75, 0x08, /* Report Size (8), */ 0x95, 0x30, /* Report Count (48), */ 0x09, 0x01, /* Usage (Pointer), */ 0xB1, 0x02, /* Feature (Variable), */ 0xC0, /* End Collection, */ 0xC0 /* End Collection */ }; |
1adf904e9 HID: sony: unders... |
172 |
static u8 ps3remote_rdesc[] = { |
078328da5 HID: fold ps3remo... |
173 174 175 176 177 178 |
0x05, 0x01, /* GUsagePage Generic Desktop */ 0x09, 0x05, /* LUsage 0x05 [Game Pad] */ 0xA1, 0x01, /* MCollection Application (mouse, keyboard) */ /* Use collection 1 for joypad buttons */ 0xA1, 0x02, /* MCollection Logical (interrelated data) */ |
ef916ef5e HID: sony: fix so... |
179 180 181 182 |
/* * Ignore the 1st byte, maybe it is used for a controller * number but it's not needed for correct operation */ |
078328da5 HID: fold ps3remo... |
183 184 185 |
0x75, 0x08, /* GReportSize 0x08 [8] */ 0x95, 0x01, /* GReportCount 0x01 [1] */ 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ |
ef916ef5e HID: sony: fix so... |
186 187 188 189 |
/* * Bytes from 2nd to 4th are a bitmap for joypad buttons, for these * buttons multiple keypresses are allowed */ |
078328da5 HID: fold ps3remo... |
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
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) */ /* 5th byte is used for remote control buttons */ 0x05, 0x09, /* GUsagePage Button */ 0x18, /* LUsageMinimum [No button pressed] */ 0x29, 0xFE, /* LUsageMaximum 0xFE [Button 254] */ 0x14, /* GLogicalMinimum [0] */ 0x26, 0xFE, 0x00, /* GLogicalMaximum 0x00FE [254] */ 0x75, 0x08, /* GReportSize 0x08 [8] */ 0x95, 0x01, /* GReportCount 0x01 [1] */ 0x80, /* MInput */ |
ef916ef5e HID: sony: fix so... |
213 214 215 216 |
/* * Ignore bytes from 6th to 11th, 6th to 10th are always constant at * 0xff and 11th is for press indication */ |
078328da5 HID: fold ps3remo... |
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
0x75, 0x08, /* GReportSize 0x08 [8] */ 0x95, 0x06, /* GReportCount 0x06 [6] */ 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ /* 12th byte is for battery strength */ 0x05, 0x06, /* GUsagePage Generic Device Controls */ 0x09, 0x20, /* LUsage 0x20 [Battery Strength] */ 0x14, /* GLogicalMinimum [0] */ 0x25, 0x05, /* GLogicalMaximum 0x05 [5] */ 0x75, 0x08, /* GReportSize 0x08 [8] */ 0x95, 0x01, /* GReportCount 0x01 [1] */ 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ 0xC0, /* MEndCollection */ 0xC0 /* MEndCollection [Game Pad] */ }; static const unsigned int ps3remote_keymap_joypad_buttons[] = { [0x01] = KEY_SELECT, [0x02] = BTN_THUMBL, /* L3 */ [0x03] = BTN_THUMBR, /* R3 */ [0x04] = BTN_START, [0x05] = KEY_UP, [0x06] = KEY_RIGHT, [0x07] = KEY_DOWN, [0x08] = KEY_LEFT, [0x09] = BTN_TL2, /* L2 */ [0x0a] = BTN_TR2, /* R2 */ [0x0b] = BTN_TL, /* L1 */ [0x0c] = BTN_TR, /* R1 */ [0x0d] = KEY_OPTION, /* options/triangle */ [0x0e] = KEY_BACK, /* back/circle */ [0x0f] = BTN_0, /* cross */ [0x10] = KEY_SCREEN, /* view/square */ [0x11] = KEY_HOMEPAGE, /* PS button */ [0x14] = KEY_ENTER, }; static const unsigned int ps3remote_keymap_remote_buttons[] = { [0x00] = KEY_1, [0x01] = KEY_2, [0x02] = KEY_3, [0x03] = KEY_4, [0x04] = KEY_5, [0x05] = KEY_6, [0x06] = KEY_7, [0x07] = KEY_8, [0x08] = KEY_9, [0x09] = KEY_0, [0x0e] = KEY_ESC, /* return */ [0x0f] = KEY_CLEAR, [0x16] = KEY_EJECTCD, [0x1a] = KEY_MENU, /* top menu */ [0x28] = KEY_TIME, [0x30] = KEY_PREVIOUS, [0x31] = KEY_NEXT, [0x32] = KEY_PLAY, [0x33] = KEY_REWIND, /* scan back */ [0x34] = KEY_FORWARD, /* scan forward */ [0x38] = KEY_STOP, [0x39] = KEY_PAUSE, [0x40] = KEY_CONTEXT_MENU, /* pop up/menu */ [0x60] = KEY_FRAMEBACK, /* slow/step back */ [0x61] = KEY_FRAMEFORWARD, /* slow/step forward */ [0x63] = KEY_SUBTITLE, [0x64] = KEY_AUDIO, [0x65] = KEY_ANGLE, [0x70] = KEY_INFO, /* display */ [0x80] = KEY_BLUE, [0x81] = KEY_RED, [0x82] = KEY_GREEN, [0x83] = KEY_YELLOW, }; |
f04d51404 HID: driver for P... |
290 |
static const unsigned int buzz_keymap[] = { |
ad142b9e4 HID: sony: Fix mu... |
291 292 |
/* * The controller has 4 remote buzzers, each with one LED and 5 |
f04d51404 HID: driver for P... |
293 |
* buttons. |
09593e388 HID: sony: fix er... |
294 |
* |
f04d51404 HID: driver for P... |
295 296 297 298 299 300 301 302 303 304 305 306 307 |
* 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 */ |
09593e388 HID: sony: fix er... |
308 309 310 311 312 313 314 315 316 |
[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, |
f04d51404 HID: driver for P... |
317 318 319 320 321 322 323 324 325 326 327 328 |
[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, }; |
b8f0970d2 HID: sony: Improv... |
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 |
/* The Navigation controller is a partial DS3 and uses the same HID report * and hence the same keymap indices, however not not all axes/buttons * are physically present. We use the same axis and button mapping as * the DS3, which uses the Linux gamepad spec. */ static const unsigned int 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. */ static const unsigned int 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 */ }; |
e19a267b9 HID: sony: DS3 co... |
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 |
static const unsigned int sixaxis_absmap[] = { [0x30] = ABS_X, [0x31] = ABS_Y, [0x32] = ABS_RX, /* right stick X */ [0x35] = ABS_RY, /* right stick Y */ }; static const unsigned int sixaxis_keymap[] = { [0x01] = BTN_SELECT, /* Select */ [0x02] = BTN_THUMBL, /* L3 */ [0x03] = BTN_THUMBR, /* R3 */ [0x04] = BTN_START, /* 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] = BTN_TR2, /* R2 */ [0x0b] = BTN_TL, /* L1 */ [0x0c] = BTN_TR, /* R1 */ [0x0d] = BTN_NORTH, /* Triangle */ [0x0e] = BTN_EAST, /* Circle */ [0x0f] = BTN_SOUTH, /* Cross */ [0x10] = BTN_WEST, /* Square */ [0x11] = BTN_MODE, /* PS */ }; |
9131f8cc2 HID: sony: Comply... |
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 |
static const unsigned int ds4_absmap[] = { [0x30] = ABS_X, [0x31] = ABS_Y, [0x32] = ABS_RX, /* right stick X */ [0x33] = ABS_Z, /* L2 */ [0x34] = ABS_RZ, /* R2 */ [0x35] = ABS_RY, /* right stick Y */ }; static const unsigned int ds4_keymap[] = { [0x1] = BTN_WEST, /* Square */ [0x2] = BTN_SOUTH, /* Cross */ [0x3] = BTN_EAST, /* Circle */ [0x4] = BTN_NORTH, /* Triangle */ [0x5] = BTN_TL, /* L1 */ [0x6] = BTN_TR, /* R1 */ [0x7] = BTN_TL2, /* L2 */ [0x8] = BTN_TR2, /* R2 */ [0x9] = BTN_SELECT, /* Share */ [0xa] = BTN_START, /* Options */ [0xb] = BTN_THUMBL, /* L3 */ [0xc] = BTN_THUMBR, /* R3 */ [0xd] = BTN_MODE, /* PS */ }; |
d03ae2e10 HID: sony: Remove... |
412 413 414 415 |
static const struct {int x; int y; } ds4_hat_mapping[] = { {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, 0} }; |
9131f8cc2 HID: sony: Comply... |
416 |
|
d902f4724 HID: sony: add ba... |
417 418 419 420 421 422 |
static enum power_supply_property sony_battery_props[] = { POWER_SUPPLY_PROP_PRESENT, POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_SCOPE, POWER_SUPPLY_PROP_STATUS, }; |
55d3b664d HID: sony: Use a ... |
423 |
struct sixaxis_led { |
1adf904e9 HID: sony: unders... |
424 425 426 427 428 |
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%) */ |
55d3b664d HID: sony: Use a ... |
429 430 431 |
} __packed; struct sixaxis_rumble { |
1adf904e9 HID: sony: unders... |
432 433 434 435 436 |
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 */ |
55d3b664d HID: sony: Use a ... |
437 438 439 |
} __packed; struct sixaxis_output_report { |
1adf904e9 HID: sony: unders... |
440 |
u8 report_id; |
55d3b664d HID: sony: Use a ... |
441 |
struct sixaxis_rumble rumble; |
1adf904e9 HID: sony: unders... |
442 443 |
u8 padding[4]; u8 leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */ |
55d3b664d HID: sony: Use a ... |
444 445 446 447 448 449 |
struct sixaxis_led led[4]; /* LEDx at (4 - x) */ struct sixaxis_led _reserved; /* LED5, not actually soldered */ } __packed; union sixaxis_output_report_01 { struct sixaxis_output_report data; |
1adf904e9 HID: sony: unders... |
450 |
u8 buf[36]; |
55d3b664d HID: sony: Use a ... |
451 |
}; |
c5e0c1c49 HID: sony: Add su... |
452 453 454 455 456 457 |
struct motion_output_report_02 { u8 type, zero; u8 r, g, b; u8 zero2; u8 rumble; }; |
2c159de05 HID: sony: Adjust... |
458 |
#define DS4_FEATURE_REPORT_0x02_SIZE 37 |
55a07d62d HID: sony: Calibr... |
459 |
#define DS4_FEATURE_REPORT_0x05_SIZE 41 |
2c159de05 HID: sony: Adjust... |
460 |
#define DS4_FEATURE_REPORT_0x81_SIZE 7 |
49b9ca6c6 HID: sony: Perfor... |
461 |
#define DS4_INPUT_REPORT_0x11_SIZE 78 |
2c159de05 HID: sony: Adjust... |
462 463 |
#define DS4_OUTPUT_REPORT_0x05_SIZE 32 #define DS4_OUTPUT_REPORT_0x11_SIZE 78 |
29b691a89 HID: sony: Use th... |
464 |
#define SIXAXIS_REPORT_0xF2_SIZE 17 |
a85d67b54 HID: sony: Don't ... |
465 |
#define SIXAXIS_REPORT_0xF5_SIZE 8 |
41d2d4253 HID: sony: PS3 Mo... |
466 |
#define MOTION_REPORT_0x02_SIZE 49 |
9b2b5c9a7 HID: sony: Use ke... |
467 |
|
cdc1c0215 HID: sony: Handle... |
468 469 470 |
/* Offsets relative to USB input report (0x1). Bluetooth (0x11) requires an * additional +2. */ |
d03ae2e10 HID: sony: Remove... |
471 |
#define DS4_INPUT_REPORT_AXIS_OFFSET 1 |
ac797b95f HID: sony: Make t... |
472 |
#define DS4_INPUT_REPORT_BUTTON_OFFSET 5 |
80786eb9a HID: sony: Report... |
473 |
#define DS4_INPUT_REPORT_TIMESTAMP_OFFSET 10 |
227c011b2 HID: sony: Report... |
474 |
#define DS4_INPUT_REPORT_GYRO_X_OFFSET 13 |
cdc1c0215 HID: sony: Handle... |
475 476 |
#define DS4_INPUT_REPORT_BATTERY_OFFSET 30 #define DS4_INPUT_REPORT_TOUCHPAD_OFFSET 33 |
510c8b7c1 HID: sony: Expose... |
477 |
#define SENSOR_SUFFIX " Motion Sensors" |
ac797b95f HID: sony: Make t... |
478 |
#define DS4_TOUCHPAD_SUFFIX " Touchpad" |
77b499e73 HID: sony: Make D... |
479 480 481 |
/* Default to 4ms poll interval, which is same as USB (not adjustable). */ #define DS4_BT_DEFAULT_POLL_INTERVAL_MS 4 #define DS4_BT_MAX_POLL_INTERVAL_MS 62 |
55a07d62d HID: sony: Calibr... |
482 483 |
#define DS4_GYRO_RES_PER_DEG_S 1024 #define DS4_ACC_RES_PER_G 8192 |
510c8b7c1 HID: sony: Expose... |
484 485 |
#define SIXAXIS_INPUT_REPORT_ACC_X_OFFSET 41 #define SIXAXIS_ACC_RES_PER_G 113 |
8b402c929 HID: sony: initia... |
486 |
static DEFINE_SPINLOCK(sony_dev_list_lock); |
d2d782fcc HID: sony: Preven... |
487 |
static LIST_HEAD(sony_device_list); |
8025087ac HID: sony: Initia... |
488 |
static DEFINE_IDA(sony_device_id_allocator); |
d2d782fcc HID: sony: Preven... |
489 |
|
55a07d62d HID: sony: Calibr... |
490 491 492 493 494 495 496 497 498 499 500 |
/* Used for calibration of DS4 accelerometer and gyro. */ struct ds4_calibration_data { int abs_code; short bias; /* Calibration requires scaling against a sensitivity value, which is a * float. Store sensitivity as a fraction to limit floating point * calculations until final calibration. */ int sens_numer; int sens_denom; }; |
f2f47c385 HID: sony: Suppor... |
501 502 503 504 505 506 |
enum ds4_dongle_state { DONGLE_DISCONNECTED, DONGLE_CALIBRATING, DONGLE_CONNECTED, DONGLE_DISABLED }; |
b53227360 HID: sony: Make w... |
507 |
enum sony_worker { |
f2f47c385 HID: sony: Suppor... |
508 509 |
SONY_WORKER_STATE, SONY_WORKER_HOTPLUG |
b53227360 HID: sony: Make w... |
510 |
}; |
cc6e0bbb4 HID: Add support ... |
511 |
struct sony_sc { |
d902f4724 HID: sony: add ba... |
512 |
spinlock_t lock; |
d2d782fcc HID: sony: Preven... |
513 |
struct list_head list_node; |
0a286ef27 HID: sony: Add LE... |
514 |
struct hid_device *hdev; |
ac797b95f HID: sony: Make t... |
515 |
struct input_dev *touchpad; |
227c011b2 HID: sony: Report... |
516 |
struct input_dev *sensor_dev; |
60781cf48 HID: sony: Add LE... |
517 |
struct led_classdev *leds[MAX_LEDS]; |
cc6e0bbb4 HID: Add support ... |
518 |
unsigned long quirks; |
f2f47c385 HID: sony: Suppor... |
519 |
struct work_struct hotplug_worker; |
0a286ef27 HID: sony: Add LE... |
520 |
struct work_struct state_worker; |
09593e388 HID: sony: fix er... |
521 |
void (*send_output_report)(struct sony_sc *); |
297d716f6 power_supply: Cha... |
522 523 |
struct power_supply *battery; struct power_supply_desc battery_desc; |
8025087ac HID: sony: Initia... |
524 |
int device_id; |
1adf904e9 HID: sony: unders... |
525 |
u8 *output_report_dmabuf; |
f04d51404 HID: driver for P... |
526 |
|
9f323b681 HID: sony: Send F... |
527 |
#ifdef CONFIG_SONY_FF |
1adf904e9 HID: sony: unders... |
528 529 |
u8 left; u8 right; |
9f323b681 HID: sony: Send F... |
530 |
#endif |
1adf904e9 HID: sony: unders... |
531 |
u8 mac_address[6]; |
f2f47c385 HID: sony: Suppor... |
532 |
u8 hotplug_worker_initialized; |
b53227360 HID: sony: Make w... |
533 |
u8 state_worker_initialized; |
2a2429327 HID: sony: Defer ... |
534 |
u8 defer_initialization; |
1adf904e9 HID: sony: unders... |
535 536 537 538 |
u8 cable_state; u8 battery_charging; u8 battery_capacity; u8 led_state[MAX_LEDS]; |
1adf904e9 HID: sony: unders... |
539 540 541 |
u8 led_delay_on[MAX_LEDS]; u8 led_delay_off[MAX_LEDS]; u8 led_count; |
80786eb9a HID: sony: Report... |
542 543 544 545 |
bool timestamp_initialized; u16 prev_timestamp; unsigned int timestamp_us; |
77b499e73 HID: sony: Make D... |
546 |
u8 ds4_bt_poll_interval; |
f2f47c385 HID: sony: Suppor... |
547 |
enum ds4_dongle_state ds4_dongle_state; |
55a07d62d HID: sony: Calibr... |
548 549 |
/* DS4 calibration data */ struct ds4_calibration_data ds4_calib_data[6]; |
cc6e0bbb4 HID: Add support ... |
550 |
}; |
405182c24 HID: sony: Ignore... |
551 |
static void sony_set_leds(struct sony_sc *sc); |
b53227360 HID: sony: Make w... |
552 553 |
static inline void sony_schedule_work(struct sony_sc *sc, enum sony_worker which) |
2a2429327 HID: sony: Defer ... |
554 |
{ |
b53227360 HID: sony: Make w... |
555 556 557 558 |
switch (which) { case SONY_WORKER_STATE: if (!sc->defer_initialization) schedule_work(&sc->state_worker); |
f2f47c385 HID: sony: Suppor... |
559 560 561 562 563 |
break; case SONY_WORKER_HOTPLUG: if (sc->hotplug_worker_initialized) schedule_work(&sc->hotplug_worker); break; |
b53227360 HID: sony: Make w... |
564 |
} |
2a2429327 HID: sony: Defer ... |
565 |
} |
77b499e73 HID: sony: Make D... |
566 567 568 |
static ssize_t ds4_show_poll_interval(struct device *dev, struct device_attribute *attr, char *buf) |
c607fb8d6 HID: sony: Always... |
569 |
{ |
77b499e73 HID: sony: Make D... |
570 571 572 573 574 |
struct hid_device *hdev = to_hid_device(dev); struct sony_sc *sc = hid_get_drvdata(hdev); return snprintf(buf, PAGE_SIZE, "%i ", sc->ds4_bt_poll_interval); |
c607fb8d6 HID: sony: Always... |
575 |
} |
77b499e73 HID: sony: Make D... |
576 577 578 |
static ssize_t ds4_store_poll_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
c5e0c1c49 HID: sony: Add su... |
579 |
{ |
77b499e73 HID: sony: Make D... |
580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 |
struct hid_device *hdev = to_hid_device(dev); struct sony_sc *sc = hid_get_drvdata(hdev); unsigned long flags; u8 interval; if (kstrtou8(buf, 0, &interval)) return -EINVAL; if (interval > DS4_BT_MAX_POLL_INTERVAL_MS) return -EINVAL; spin_lock_irqsave(&sc->lock, flags); sc->ds4_bt_poll_interval = interval; spin_unlock_irqrestore(&sc->lock, flags); sony_schedule_work(sc, SONY_WORKER_STATE); return count; |
c5e0c1c49 HID: sony: Add su... |
598 |
} |
77b499e73 HID: sony: Make D... |
599 600 |
static DEVICE_ATTR(bt_poll_interval, 0644, ds4_show_poll_interval, ds4_store_poll_interval); |
c5e0c1c49 HID: sony: Add su... |
601 |
static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc, |
b2723eb73 HID: hid-sony: Fi... |
602 603 |
unsigned int *rsize) { |
c5e0c1c49 HID: sony: Add su... |
604 605 |
*rsize = sizeof(motion_rdesc); return motion_rdesc; |
b2723eb73 HID: hid-sony: Fi... |
606 |
} |
1adf904e9 HID: sony: unders... |
607 |
static u8 *ps3remote_fixup(struct hid_device *hdev, u8 *rdesc, |
078328da5 HID: fold ps3remo... |
608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 |
unsigned int *rsize) { *rsize = sizeof(ps3remote_rdesc); return ps3remote_rdesc; } static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { unsigned int key = usage->hid & HID_USAGE; if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) return -1; switch (usage->collection_index) { case 1: if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons)) return -1; key = ps3remote_keymap_joypad_buttons[key]; if (!key) return -1; break; case 2: if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons)) return -1; key = ps3remote_keymap_remote_buttons[key]; if (!key) return -1; break; default: return -1; } hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); return 1; } |
b8f0970d2 HID: sony: Improv... |
647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 |
static int navigation_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) { unsigned int key = usage->hid & HID_USAGE; if (key >= ARRAY_SIZE(sixaxis_keymap)) return -1; key = navigation_keymap[key]; if (!key) return -1; hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); return 1; } else if (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; } hid_map_usage_clear(hi, usage, bit, max, EV_ABS, usage->hid & 0xf); return 1; } else if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK) { unsigned int abs = usage->hid & HID_USAGE; if (abs >= ARRAY_SIZE(navigation_absmap)) return -1; abs = navigation_absmap[abs]; hid_map_usage_clear(hi, usage, bit, max, EV_ABS, abs); return 1; } return -1; } |
e19a267b9 HID: sony: DS3 co... |
693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 |
static int sixaxis_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) { unsigned int key = usage->hid & HID_USAGE; if (key >= ARRAY_SIZE(sixaxis_keymap)) return -1; key = sixaxis_keymap[key]; hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); return 1; } else if (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; } hid_map_usage_clear(hi, usage, bit, max, EV_ABS, usage->hid & 0xf); return 1; } else if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK) { unsigned int abs = usage->hid & HID_USAGE; if (abs >= ARRAY_SIZE(sixaxis_absmap)) return -1; abs = sixaxis_absmap[abs]; hid_map_usage_clear(hi, usage, bit, max, EV_ABS, abs); return 1; } return -1; } |
9131f8cc2 HID: sony: Comply... |
740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 |
static int ds4_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) { unsigned int key = usage->hid & HID_USAGE; if (key >= ARRAY_SIZE(ds4_keymap)) return -1; key = ds4_keymap[key]; hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); return 1; } else if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK) { unsigned int abs = usage->hid & HID_USAGE; /* Let the HID parser deal with the HAT. */ if (usage->hid == HID_GD_HATSWITCH) return 0; if (abs >= ARRAY_SIZE(ds4_absmap)) return -1; abs = ds4_absmap[abs]; hid_map_usage_clear(hi, usage, bit, max, EV_ABS, abs); return 1; } return 0; } |
1adf904e9 HID: sony: unders... |
770 |
static u8 *sony_report_fixup(struct hid_device *hdev, u8 *rdesc, |
73e4008dd HID: allow resizi... |
771 |
unsigned int *rsize) |
cc6e0bbb4 HID: Add support ... |
772 773 |
{ struct sony_sc *sc = hid_get_drvdata(hdev); |
4ba1eeeb6 HID: sony: disabl... |
774 |
if (sc->quirks & (SINO_LITE_CONTROLLER | FUTUREMAX_DANCE_MAT)) |
74500cc85 HID: sony: Add ny... |
775 |
return rdesc; |
99d249021 HID: clean up qui... |
776 777 778 779 780 781 782 783 784 785 786 |
/* * 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) { |
a46491841 HID: add support ... |
787 788 |
hid_info(hdev, "Fixing up Sony RF Receiver report descriptor "); |
99d249021 HID: clean up qui... |
789 |
/* input: data, variable, relative */ |
cc6e0bbb4 HID: Add support ... |
790 791 |
rdesc[55] = 0x06; } |
61ab44beb HID: hid-sony: am... |
792 |
|
c5e0c1c49 HID: sony: Add su... |
793 794 |
if (sc->quirks & MOTION_CONTROLLER) return motion_fixup(hdev, rdesc, rsize); |
078328da5 HID: fold ps3remo... |
795 796 |
if (sc->quirks & PS3REMOTE) return ps3remote_fixup(hdev, rdesc, rsize); |
73e4008dd HID: allow resizi... |
797 |
return rdesc; |
cc6e0bbb4 HID: Add support ... |
798 |
} |
1adf904e9 HID: sony: unders... |
799 |
static void sixaxis_parse_report(struct sony_sc *sc, u8 *rd, int size) |
d902f4724 HID: sony: add ba... |
800 |
{ |
1adf904e9 HID: sony: unders... |
801 |
static const u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 }; |
d902f4724 HID: sony: add ba... |
802 |
unsigned long flags; |
12e9a6d72 HID: sony: Add su... |
803 |
int offset; |
1adf904e9 HID: sony: unders... |
804 |
u8 cable_state, battery_capacity, battery_charging; |
d902f4724 HID: sony: add ba... |
805 |
|
ad142b9e4 HID: sony: Fix mu... |
806 807 |
/* * The sixaxis is charging if the battery value is 0xee |
d902f4724 HID: sony: add ba... |
808 809 810 811 |
* 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. */ |
12e9a6d72 HID: sony: Add su... |
812 813 814 |
offset = (sc->quirks & MOTION_CONTROLLER) ? 12 : 30; if (rd[offset] >= 0xee) { |
d902f4724 HID: sony: add ba... |
815 |
battery_capacity = 100; |
12e9a6d72 HID: sony: Add su... |
816 |
battery_charging = !(rd[offset] & 0x01); |
9fddd74a2 HID: sony: Set th... |
817 |
cable_state = 1; |
d902f4724 HID: sony: add ba... |
818 |
} else { |
1adf904e9 HID: sony: unders... |
819 |
u8 index = rd[offset] <= 5 ? rd[offset] : 5; |
ac3c9a940 HID: sony: Perfor... |
820 |
battery_capacity = sixaxis_battery_capacity[index]; |
d902f4724 HID: sony: add ba... |
821 |
battery_charging = 0; |
9fddd74a2 HID: sony: Set th... |
822 |
cable_state = 0; |
d902f4724 HID: sony: add ba... |
823 |
} |
d902f4724 HID: sony: add ba... |
824 825 826 827 828 829 |
spin_lock_irqsave(&sc->lock, flags); sc->cable_state = cable_state; sc->battery_capacity = battery_capacity; sc->battery_charging = battery_charging; spin_unlock_irqrestore(&sc->lock, flags); |
510c8b7c1 HID: sony: Expose... |
830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 |
if (sc->quirks & SIXAXIS_CONTROLLER) { int val; offset = SIXAXIS_INPUT_REPORT_ACC_X_OFFSET; val = ((rd[offset+1] << 8) | rd[offset]) - 511; input_report_abs(sc->sensor_dev, ABS_X, val); /* Y and Z are swapped and inversed */ val = 511 - ((rd[offset+5] << 8) | rd[offset+4]); input_report_abs(sc->sensor_dev, ABS_Y, val); val = 511 - ((rd[offset+3] << 8) | rd[offset+2]); input_report_abs(sc->sensor_dev, ABS_Z, val); input_sync(sc->sensor_dev); } |
d902f4724 HID: sony: add ba... |
847 |
} |
1adf904e9 HID: sony: unders... |
848 |
static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size) |
d902f4724 HID: sony: add ba... |
849 |
{ |
d03ae2e10 HID: sony: Remove... |
850 851 852 |
struct hid_input *hidinput = list_entry(sc->hdev->inputs.next, struct hid_input, list); struct input_dev *input_dev = hidinput->input; |
d902f4724 HID: sony: add ba... |
853 |
unsigned long flags; |
cdc1c0215 HID: sony: Handle... |
854 |
int n, m, offset, num_touch_data, max_touch_data; |
1adf904e9 HID: sony: unders... |
855 |
u8 cable_state, battery_capacity, battery_charging; |
80786eb9a HID: sony: Report... |
856 |
u16 timestamp; |
d902f4724 HID: sony: add ba... |
857 |
|
cdc1c0215 HID: sony: Handle... |
858 |
/* When using Bluetooth the header is 2 bytes longer, so skip these. */ |
35f436c31 HID: sony: Treat ... |
859 |
int data_offset = (sc->quirks & DUALSHOCK4_CONTROLLER_BT) ? 2 : 0; |
6c5f860d3 HID: sony: Add Du... |
860 |
|
ac797b95f HID: sony: Make t... |
861 862 863 |
/* Second bit of third button byte is for the touchpad button. */ offset = data_offset + DS4_INPUT_REPORT_BUTTON_OFFSET; input_report_key(sc->touchpad, BTN_LEFT, rd[offset+2] & 0x2); |
ad142b9e4 HID: sony: Fix mu... |
864 |
/* |
d03ae2e10 HID: sony: Remove... |
865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 |
* The default behavior of the Dualshock 4 is to send reports using * report type 1 when running over Bluetooth. However, when feature * report 2 is requested during the controller initialization it starts * sending input reports in report 17. Since report 17 is undefined * in the default HID descriptor, the HID layer won't generate events. * While it is possible (and this was done before) to fixup the HID * descriptor to add this mapping, it was better to do this manually. * The reason is there were various pieces software both open and closed * source, relying on the descriptors to be the same across various * operating systems. If the descriptors wouldn't match some * applications e.g. games on Wine would not be able to function due * to different descriptors, which such applications are not parsing. */ if (rd[0] == 17) { int value; offset = data_offset + DS4_INPUT_REPORT_AXIS_OFFSET; input_report_abs(input_dev, ABS_X, rd[offset]); input_report_abs(input_dev, ABS_Y, rd[offset+1]); input_report_abs(input_dev, ABS_RX, rd[offset+2]); input_report_abs(input_dev, ABS_RY, rd[offset+3]); value = rd[offset+4] & 0xf; if (value > 7) value = 8; /* Center 0, 0 */ input_report_abs(input_dev, ABS_HAT0X, ds4_hat_mapping[value].x); input_report_abs(input_dev, ABS_HAT0Y, ds4_hat_mapping[value].y); input_report_key(input_dev, BTN_WEST, rd[offset+4] & 0x10); input_report_key(input_dev, BTN_SOUTH, rd[offset+4] & 0x20); input_report_key(input_dev, BTN_EAST, rd[offset+4] & 0x40); input_report_key(input_dev, BTN_NORTH, rd[offset+4] & 0x80); input_report_key(input_dev, BTN_TL, rd[offset+5] & 0x1); input_report_key(input_dev, BTN_TR, rd[offset+5] & 0x2); input_report_key(input_dev, BTN_TL2, rd[offset+5] & 0x4); input_report_key(input_dev, BTN_TR2, rd[offset+5] & 0x8); input_report_key(input_dev, BTN_SELECT, rd[offset+5] & 0x10); input_report_key(input_dev, BTN_START, rd[offset+5] & 0x20); input_report_key(input_dev, BTN_THUMBL, rd[offset+5] & 0x40); input_report_key(input_dev, BTN_THUMBR, rd[offset+5] & 0x80); input_report_key(input_dev, BTN_MODE, rd[offset+6] & 0x1); input_report_abs(input_dev, ABS_Z, rd[offset+7]); input_report_abs(input_dev, ABS_RZ, rd[offset+8]); input_sync(input_dev); } |
80786eb9a HID: sony: Report... |
914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 |
/* Convert timestamp (in 5.33us unit) to timestamp_us */ offset = data_offset + DS4_INPUT_REPORT_TIMESTAMP_OFFSET; timestamp = get_unaligned_le16(&rd[offset]); if (!sc->timestamp_initialized) { sc->timestamp_us = ((unsigned int)timestamp * 16) / 3; sc->timestamp_initialized = true; } else { u16 delta; if (sc->prev_timestamp > timestamp) delta = (U16_MAX - sc->prev_timestamp + timestamp + 1); else delta = timestamp - sc->prev_timestamp; sc->timestamp_us += (delta * 16) / 3; } sc->prev_timestamp = timestamp; input_event(sc->sensor_dev, EV_MSC, MSC_TIMESTAMP, sc->timestamp_us); |
227c011b2 HID: sony: Report... |
931 |
offset = data_offset + DS4_INPUT_REPORT_GYRO_X_OFFSET; |
55a07d62d HID: sony: Calibr... |
932 933 934 935 936 937 938 939 940 941 942 943 944 |
for (n = 0; n < 6; n++) { /* Store data in int for more precision during mult_frac. */ int raw_data = (short)((rd[offset+1] << 8) | rd[offset]); struct ds4_calibration_data *calib = &sc->ds4_calib_data[n]; /* High precision is needed during calibration, but the * calibrated values are within 32-bit. * Note: we swap numerator 'x' and 'numer' in mult_frac for * precision reasons so we don't need 64-bit. */ int calib_data = mult_frac(calib->sens_numer, raw_data - calib->bias, calib->sens_denom); |
227c011b2 HID: sony: Report... |
945 |
|
55a07d62d HID: sony: Calibr... |
946 947 |
input_report_abs(sc->sensor_dev, calib->abs_code, calib_data); offset += 2; |
227c011b2 HID: sony: Report... |
948 949 |
} input_sync(sc->sensor_dev); |
ad142b9e4 HID: sony: Fix mu... |
950 |
/* |
cdc1c0215 HID: sony: Handle... |
951 |
* The lower 4 bits of byte 30 (or 32 for BT) contain the battery level |
d902f4724 HID: sony: add ba... |
952 953 |
* and the 5th bit contains the USB cable state. */ |
cdc1c0215 HID: sony: Handle... |
954 |
offset = data_offset + DS4_INPUT_REPORT_BATTERY_OFFSET; |
6c5f860d3 HID: sony: Add Du... |
955 956 |
cable_state = (rd[offset] >> 4) & 0x01; battery_capacity = rd[offset] & 0x0F; |
d902f4724 HID: sony: add ba... |
957 |
|
ad142b9e4 HID: sony: Fix mu... |
958 959 |
/* * When a USB power source is connected the battery level ranges from |
6c5f860d3 HID: sony: Add Du... |
960 961 |
* 0 to 10, and when running on battery power it ranges from 0 to 9. * A battery level above 10 when plugged in means charge completed. |
d902f4724 HID: sony: add ba... |
962 |
*/ |
6c5f860d3 HID: sony: Add Du... |
963 |
if (!cable_state || battery_capacity > 10) |
d902f4724 HID: sony: add ba... |
964 965 966 |
battery_charging = 0; else battery_charging = 1; |
6c5f860d3 HID: sony: Add Du... |
967 968 |
if (!cable_state) battery_capacity++; |
d902f4724 HID: sony: add ba... |
969 |
if (battery_capacity > 10) |
6c5f860d3 HID: sony: Add Du... |
970 |
battery_capacity = 10; |
d902f4724 HID: sony: add ba... |
971 972 973 974 975 976 977 |
battery_capacity *= 10; spin_lock_irqsave(&sc->lock, flags); sc->cable_state = cable_state; sc->battery_capacity = battery_capacity; sc->battery_charging = battery_charging; spin_unlock_irqrestore(&sc->lock, flags); |
e56062305 HID: sony: add ou... |
978 |
|
ad142b9e4 HID: sony: Fix mu... |
979 |
/* |
cdc1c0215 HID: sony: Handle... |
980 981 982 983 |
* The Dualshock 4 multi-touch trackpad data starts at offset 33 on USB * and 35 on Bluetooth. * The first byte indicates the number of touch data in the report. * Trackpad data starts 2 bytes later (e.g. 35 for USB). |
e56062305 HID: sony: add ou... |
984 |
*/ |
cdc1c0215 HID: sony: Handle... |
985 |
offset = data_offset + DS4_INPUT_REPORT_TOUCHPAD_OFFSET; |
35f436c31 HID: sony: Treat ... |
986 |
max_touch_data = (sc->quirks & DUALSHOCK4_CONTROLLER_BT) ? 4 : 3; |
cdc1c0215 HID: sony: Handle... |
987 988 989 990 991 |
if (rd[offset] > 0 && rd[offset] <= max_touch_data) num_touch_data = rd[offset]; else num_touch_data = 1; offset += 1; |
e56062305 HID: sony: add ou... |
992 |
|
cdc1c0215 HID: sony: Handle... |
993 994 995 |
for (m = 0; m < num_touch_data; m++) { /* Skip past timestamp */ offset += 1; |
e56062305 HID: sony: add ou... |
996 |
|
cdc1c0215 HID: sony: Handle... |
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 |
/* * The first 7 bits of the first byte is a counter and bit 8 is * a touch indicator that is 0 when pressed and 1 when not * pressed. * The next 3 bytes are two 12 bit touch coordinates, X and Y. * The data for the second touch is in the same format and * immediately follows the data for the first. */ for (n = 0; n < 2; n++) { u16 x, y; bool active; x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8); y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4); active = !(rd[offset] >> 7); |
ac797b95f HID: sony: Make t... |
1013 1014 |
input_mt_slot(sc->touchpad, n); input_mt_report_slot_state(sc->touchpad, MT_TOOL_FINGER, active); |
cdc1c0215 HID: sony: Handle... |
1015 1016 |
if (active) { |
ac797b95f HID: sony: Make t... |
1017 1018 |
input_report_abs(sc->touchpad, ABS_MT_POSITION_X, x); input_report_abs(sc->touchpad, ABS_MT_POSITION_Y, y); |
cdc1c0215 HID: sony: Handle... |
1019 1020 1021 1022 |
} offset += 4; } |
ac797b95f HID: sony: Make t... |
1023 1024 |
input_mt_sync_frame(sc->touchpad); input_sync(sc->touchpad); |
e56062305 HID: sony: add ou... |
1025 |
} |
d902f4724 HID: sony: add ba... |
1026 |
} |
c9e4d8775 HID: hid-sony: fi... |
1027 |
static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, |
1adf904e9 HID: sony: unders... |
1028 |
u8 *rd, int size) |
c9e4d8775 HID: hid-sony: fi... |
1029 1030 |
{ struct sony_sc *sc = hid_get_drvdata(hdev); |
ad142b9e4 HID: sony: Fix mu... |
1031 1032 |
/* * Sixaxis HID report has acclerometers/gyro with MSByte first, this |
c9e4d8775 HID: hid-sony: fi... |
1033 1034 |
* has to be BYTE_SWAPPED before passing up to joystick interface */ |
fee4e2d52 HID: sony: Enable... |
1035 |
if ((sc->quirks & SIXAXIS_CONTROLLER) && rd[0] == 0x01 && size == 49) { |
8f5f0bc27 HID: sony: Drop i... |
1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 |
/* * 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; |
c9e4d8775 HID: hid-sony: fi... |
1046 1047 1048 1049 |
swap(rd[41], rd[42]); swap(rd[43], rd[44]); swap(rd[45], rd[46]); swap(rd[47], rd[48]); |
d902f4724 HID: sony: add ba... |
1050 1051 |
sixaxis_parse_report(sc, rd, size); |
12e9a6d72 HID: sony: Add su... |
1052 1053 |
} else if ((sc->quirks & MOTION_CONTROLLER_BT) && rd[0] == 0x01 && size == 49) { sixaxis_parse_report(sc, rd, size); |
4545ee0a7 HID: hid-sony: Na... |
1054 1055 1056 |
} else if ((sc->quirks & NAVIGATION_CONTROLLER) && rd[0] == 0x01 && size == 49) { sixaxis_parse_report(sc, rd, size); |
35f436c31 HID: sony: Treat ... |
1057 1058 1059 1060 1061 1062 1063 1064 1065 |
} else if ((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 && size == 64) { dualshock4_parse_report(sc, rd, size); } else if (((sc->quirks & DUALSHOCK4_CONTROLLER_BT) && rd[0] == 0x11 && size == 78)) { /* CRC check */ u8 bthdr = 0xA1; u32 crc; u32 report_crc; |
49b9ca6c6 HID: sony: Perfor... |
1066 |
|
35f436c31 HID: sony: Treat ... |
1067 1068 1069 1070 1071 1072 1073 1074 |
crc = crc32_le(0xFFFFFFFF, &bthdr, 1); crc = ~crc32_le(crc, rd, DS4_INPUT_REPORT_0x11_SIZE-4); report_crc = get_unaligned_le32(&rd[DS4_INPUT_REPORT_0x11_SIZE-4]); if (crc != report_crc) { hid_dbg(sc->hdev, "DualShock 4 input report's CRC check failed, received crc 0x%0x != 0x%0x ", report_crc, crc); return -EILSEQ; |
49b9ca6c6 HID: sony: Perfor... |
1075 |
} |
405182c24 HID: sony: Ignore... |
1076 |
|
35f436c31 HID: sony: Treat ... |
1077 1078 1079 |
dualshock4_parse_report(sc, rd, size); } else if ((sc->quirks & DUALSHOCK4_DONGLE) && rd[0] == 0x01 && size == 64) { |
f2f47c385 HID: sony: Suppor... |
1080 1081 |
unsigned long flags; enum ds4_dongle_state dongle_state; |
405182c24 HID: sony: Ignore... |
1082 1083 1084 1085 1086 |
/* * In the case of a DS4 USB dongle, bit[2] of byte 31 indicates * if a DS4 is actually connected (indicated by '0'). * For non-dongle, this bit is always 0 (connected). */ |
35f436c31 HID: sony: Treat ... |
1087 |
bool connected = (rd[31] & 0x04) ? false : true; |
f2f47c385 HID: sony: Suppor... |
1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 |
spin_lock_irqsave(&sc->lock, flags); dongle_state = sc->ds4_dongle_state; spin_unlock_irqrestore(&sc->lock, flags); /* * The dongle always sends input reports even when no * DS4 is attached. When a DS4 is connected, we need to * obtain calibration data before we can use it. * The code below tracks dongle state and kicks of * calibration when needed and only allows us to process * input if a DS4 is actually connected. */ if (dongle_state == DONGLE_DISCONNECTED && connected) { |
35f436c31 HID: sony: Treat ... |
1101 1102 1103 |
hid_info(sc->hdev, "DualShock 4 USB dongle: controller connected "); sony_set_leds(sc); |
f2f47c385 HID: sony: Suppor... |
1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 |
spin_lock_irqsave(&sc->lock, flags); sc->ds4_dongle_state = DONGLE_CALIBRATING; spin_unlock_irqrestore(&sc->lock, flags); sony_schedule_work(sc, SONY_WORKER_HOTPLUG); /* Don't process the report since we don't have * calibration data, but let hidraw have it anyway. */ return 0; } else if ((dongle_state == DONGLE_CONNECTED || dongle_state == DONGLE_DISABLED) && !connected) { |
35f436c31 HID: sony: Treat ... |
1117 1118 |
hid_info(sc->hdev, "DualShock 4 USB dongle: controller disconnected "); |
f2f47c385 HID: sony: Suppor... |
1119 1120 1121 1122 |
spin_lock_irqsave(&sc->lock, flags); sc->ds4_dongle_state = DONGLE_DISCONNECTED; spin_unlock_irqrestore(&sc->lock, flags); |
35f436c31 HID: sony: Treat ... |
1123 1124 |
/* Return 0, so hidraw can get the report. */ return 0; |
f2f47c385 HID: sony: Suppor... |
1125 1126 1127 |
} else if (dongle_state == DONGLE_CALIBRATING || dongle_state == DONGLE_DISABLED || dongle_state == DONGLE_DISCONNECTED) { |
35f436c31 HID: sony: Treat ... |
1128 1129 |
/* Return 0, so hidraw can get the report. */ return 0; |
405182c24 HID: sony: Ignore... |
1130 |
} |
d902f4724 HID: sony: add ba... |
1131 |
dualshock4_parse_report(sc, rd, size); |
c9e4d8775 HID: hid-sony: fi... |
1132 |
} |
2a2429327 HID: sony: Defer ... |
1133 1134 |
if (sc->defer_initialization) { sc->defer_initialization = 0; |
b53227360 HID: sony: Make w... |
1135 |
sony_schedule_work(sc, SONY_WORKER_STATE); |
2a2429327 HID: sony: Defer ... |
1136 |
} |
c9e4d8775 HID: hid-sony: fi... |
1137 1138 |
return 0; } |
f04d51404 HID: driver for P... |
1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 |
static int sony_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { struct sony_sc *sc = hid_get_drvdata(hdev); if (sc->quirks & BUZZ_CONTROLLER) { unsigned int key = usage->hid & HID_USAGE; if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) return -1; switch (usage->collection_index) { case 1: if (key >= ARRAY_SIZE(buzz_keymap)) return -1; key = buzz_keymap[key]; if (!key) return -1; break; default: return -1; } hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); return 1; } |
078328da5 HID: fold ps3remo... |
1167 1168 |
if (sc->quirks & PS3REMOTE) return ps3remote_mapping(hdev, hi, field, usage, bit, max); |
b8f0970d2 HID: sony: Improv... |
1169 1170 |
if (sc->quirks & NAVIGATION_CONTROLLER) return navigation_mapping(hdev, hi, field, usage, bit, max); |
e19a267b9 HID: sony: DS3 co... |
1171 1172 |
if (sc->quirks & SIXAXIS_CONTROLLER) return sixaxis_mapping(hdev, hi, field, usage, bit, max); |
9131f8cc2 HID: sony: Comply... |
1173 1174 1175 |
if (sc->quirks & DUALSHOCK4_CONTROLLER) return ds4_mapping(hdev, hi, field, usage, bit, max); |
e19a267b9 HID: sony: DS3 co... |
1176 |
|
6f4980182 HID: sony: fix HI... |
1177 1178 |
/* Let hid-core decide for the others */ return 0; |
f04d51404 HID: driver for P... |
1179 |
} |
ac797b95f HID: sony: Make t... |
1180 |
static int sony_register_touchpad(struct sony_sc *sc, int touch_count, |
ce8efc3b5 HID: sony: Set to... |
1181 1182 |
int w, int h) { |
ac797b95f HID: sony: Make t... |
1183 1184 |
size_t name_sz; char *name; |
ce8efc3b5 HID: sony: Set to... |
1185 |
int ret; |
ac797b95f HID: sony: Make t... |
1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 |
sc->touchpad = input_allocate_device(); if (!sc->touchpad) return -ENOMEM; input_set_drvdata(sc->touchpad, sc); sc->touchpad->dev.parent = &sc->hdev->dev; sc->touchpad->phys = sc->hdev->phys; sc->touchpad->uniq = sc->hdev->uniq; sc->touchpad->id.bustype = sc->hdev->bus; sc->touchpad->id.vendor = sc->hdev->vendor; sc->touchpad->id.product = sc->hdev->product; sc->touchpad->id.version = sc->hdev->version; /* 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(DS4_TOUCHPAD_SUFFIX); name = kzalloc(name_sz, GFP_KERNEL); if (!name) { ret = -ENOMEM; goto err; } snprintf(name, name_sz, "%s" DS4_TOUCHPAD_SUFFIX, sc->hdev->name); sc->touchpad->name = name; |
b9f7d245e HID: sony: Mark D... |
1210 |
ret = input_mt_init_slots(sc->touchpad, touch_count, INPUT_MT_POINTER); |
ce8efc3b5 HID: sony: Set to... |
1211 |
if (ret < 0) |
ac797b95f HID: sony: Make t... |
1212 1213 1214 1215 1216 1217 |
goto err; /* 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); |
ce8efc3b5 HID: sony: Set to... |
1218 |
|
ac797b95f HID: sony: Make t... |
1219 1220 1221 1222 1223 1224 |
input_set_abs_params(sc->touchpad, ABS_MT_POSITION_X, 0, w, 0, 0); input_set_abs_params(sc->touchpad, ABS_MT_POSITION_Y, 0, h, 0, 0); ret = input_register_device(sc->touchpad); if (ret < 0) goto err; |
ce8efc3b5 HID: sony: Set to... |
1225 1226 |
return 0; |
ac797b95f HID: sony: Make t... |
1227 1228 1229 1230 1231 1232 1233 1234 1235 |
err: kfree(sc->touchpad->name); sc->touchpad->name = NULL; input_free_device(sc->touchpad); sc->touchpad = NULL; return ret; |
ce8efc3b5 HID: sony: Set to... |
1236 |
} |
ac797b95f HID: sony: Make t... |
1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 |
static void sony_unregister_touchpad(struct sony_sc *sc) { if (!sc->touchpad) return; kfree(sc->touchpad->name); sc->touchpad->name = NULL; input_unregister_device(sc->touchpad); sc->touchpad = NULL; } |
ce8efc3b5 HID: sony: Set to... |
1248 |
|
227c011b2 HID: sony: Report... |
1249 1250 1251 1252 1253 |
static int sony_register_sensors(struct sony_sc *sc) { size_t name_sz; char *name; int ret; |
55a07d62d HID: sony: Calibr... |
1254 |
int range; |
227c011b2 HID: sony: Report... |
1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 |
sc->sensor_dev = input_allocate_device(); if (!sc->sensor_dev) return -ENOMEM; input_set_drvdata(sc->sensor_dev, sc); sc->sensor_dev->dev.parent = &sc->hdev->dev; sc->sensor_dev->phys = sc->hdev->phys; sc->sensor_dev->uniq = sc->hdev->uniq; sc->sensor_dev->id.bustype = sc->hdev->bus; sc->sensor_dev->id.vendor = sc->hdev->vendor; sc->sensor_dev->id.product = sc->hdev->product; sc->sensor_dev->id.version = sc->hdev->version; /* Append a suffix to the controller name as there are various * DS4 compatible non-Sony devices with different names. */ |
510c8b7c1 HID: sony: Expose... |
1272 |
name_sz = strlen(sc->hdev->name) + sizeof(SENSOR_SUFFIX); |
227c011b2 HID: sony: Report... |
1273 1274 1275 1276 1277 |
name = kzalloc(name_sz, GFP_KERNEL); if (!name) { ret = -ENOMEM; goto err; } |
510c8b7c1 HID: sony: Expose... |
1278 |
snprintf(name, name_sz, "%s" SENSOR_SUFFIX, sc->hdev->name); |
227c011b2 HID: sony: Report... |
1279 |
sc->sensor_dev->name = name; |
510c8b7c1 HID: sony: Expose... |
1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 |
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); } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { range = DS4_ACC_RES_PER_G*4; input_set_abs_params(sc->sensor_dev, ABS_X, -range, range, 16, 0); input_set_abs_params(sc->sensor_dev, ABS_Y, -range, range, 16, 0); input_set_abs_params(sc->sensor_dev, ABS_Z, -range, range, 16, 0); input_abs_set_res(sc->sensor_dev, ABS_X, DS4_ACC_RES_PER_G); input_abs_set_res(sc->sensor_dev, ABS_Y, DS4_ACC_RES_PER_G); input_abs_set_res(sc->sensor_dev, ABS_Z, DS4_ACC_RES_PER_G); range = DS4_GYRO_RES_PER_DEG_S*2048; input_set_abs_params(sc->sensor_dev, ABS_RX, -range, range, 16, 0); input_set_abs_params(sc->sensor_dev, ABS_RY, -range, range, 16, 0); input_set_abs_params(sc->sensor_dev, ABS_RZ, -range, range, 16, 0); input_abs_set_res(sc->sensor_dev, ABS_RX, DS4_GYRO_RES_PER_DEG_S); input_abs_set_res(sc->sensor_dev, ABS_RY, DS4_GYRO_RES_PER_DEG_S); input_abs_set_res(sc->sensor_dev, ABS_RZ, DS4_GYRO_RES_PER_DEG_S); __set_bit(EV_MSC, sc->sensor_dev->evbit); __set_bit(MSC_TIMESTAMP, sc->sensor_dev->mscbit); } |
227c011b2 HID: sony: Report... |
1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 |
__set_bit(INPUT_PROP_ACCELEROMETER, sc->sensor_dev->propbit); ret = input_register_device(sc->sensor_dev); if (ret < 0) goto err; return 0; err: kfree(sc->sensor_dev->name); sc->sensor_dev->name = NULL; input_free_device(sc->sensor_dev); sc->sensor_dev = NULL; return ret; } static void sony_unregister_sensors(struct sony_sc *sc) { if (!sc->sensor_dev) return; kfree(sc->sensor_dev->name); sc->sensor_dev->name = NULL; input_unregister_device(sc->sensor_dev); sc->sensor_dev = NULL; } |
5710fabf3 HID: hid-sony.c: ... |
1342 |
/* |
bd28ce008 HID: move sony qu... |
1343 1344 1345 1346 |
* 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. */ |
816651a7d HID: sony: Apply ... |
1347 |
static int sixaxis_set_operational_usb(struct hid_device *hdev) |
bd28ce008 HID: move sony qu... |
1348 |
{ |
a85d67b54 HID: sony: Don't ... |
1349 1350 |
const int buf_size = max(SIXAXIS_REPORT_0xF2_SIZE, SIXAXIS_REPORT_0xF5_SIZE); |
1adf904e9 HID: sony: unders... |
1351 |
u8 *buf; |
bd28ce008 HID: move sony qu... |
1352 |
int ret; |
bd28ce008 HID: move sony qu... |
1353 |
|
2e701a359 HID: sony: Coding... |
1354 |
buf = kmalloc(buf_size, GFP_KERNEL); |
bd28ce008 HID: move sony qu... |
1355 1356 |
if (!buf) return -ENOMEM; |
a85d67b54 HID: sony: Don't ... |
1357 1358 |
ret = hid_hw_raw_request(hdev, 0xf2, buf, SIXAXIS_REPORT_0xF2_SIZE, HID_FEATURE_REPORT, HID_REQ_GET_REPORT); |
a7de9b867 HID: sony: Enable... |
1359 1360 1361 1362 1363 |
if (ret < 0) { hid_err(hdev, "can't set operational mode: step 1 "); goto out; } |
f204828a1 HID: sony: use hi... |
1364 |
|
a7de9b867 HID: sony: Enable... |
1365 1366 1367 1368 |
/* * Some compatible controllers like the Speedlink Strike FX and * Gasia need another query plus an USB interrupt to get operational. */ |
a85d67b54 HID: sony: Don't ... |
1369 1370 |
ret = hid_hw_raw_request(hdev, 0xf5, buf, SIXAXIS_REPORT_0xF5_SIZE, HID_FEATURE_REPORT, HID_REQ_GET_REPORT); |
a7de9b867 HID: sony: Enable... |
1371 1372 1373 1374 1375 |
if (ret < 0) { hid_err(hdev, "can't set operational mode: step 2 "); goto out; } |
f204828a1 HID: sony: use hi... |
1376 |
|
a7de9b867 HID: sony: Enable... |
1377 |
ret = hid_hw_output_report(hdev, buf, 1); |
19f4c2ba8 HID: sony: do not... |
1378 1379 1380 1381 1382 |
if (ret < 0) { hid_info(hdev, "can't set operational mode: step 3, ignoring "); ret = 0; } |
bd28ce008 HID: move sony qu... |
1383 |
|
a7de9b867 HID: sony: Enable... |
1384 |
out: |
bd28ce008 HID: move sony qu... |
1385 1386 1387 1388 |
kfree(buf); return ret; } |
816651a7d HID: sony: Apply ... |
1389 |
static int sixaxis_set_operational_bt(struct hid_device *hdev) |
f9ce7c283 HID: Enable Sixax... |
1390 |
{ |
1adf904e9 HID: sony: unders... |
1391 1392 |
static const u8 report[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; u8 *buf; |
9b2b5c9a7 HID: sony: Use ke... |
1393 1394 1395 1396 1397 1398 1399 |
int ret; buf = kmemdup(report, sizeof(report), GFP_KERNEL); if (!buf) return -ENOMEM; ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(report), |
b0dd72aaf HID: replace hid_... |
1400 |
HID_FEATURE_REPORT, HID_REQ_SET_REPORT); |
9b2b5c9a7 HID: sony: Use ke... |
1401 1402 1403 1404 |
kfree(buf); return ret; |
f9ce7c283 HID: Enable Sixax... |
1405 |
} |
ad142b9e4 HID: sony: Fix mu... |
1406 |
/* |
55a07d62d HID: sony: Calibr... |
1407 1408 |
* Request DS4 calibration data for the motion sensors. * For Bluetooth this also affects the operating mode (see below). |
68330d83c HID: sony: Add co... |
1409 |
*/ |
55a07d62d HID: sony: Calibr... |
1410 |
static int dualshock4_get_calibration_data(struct sony_sc *sc) |
68330d83c HID: sony: Add co... |
1411 |
{ |
1adf904e9 HID: sony: unders... |
1412 |
u8 *buf; |
9b2b5c9a7 HID: sony: Use ke... |
1413 |
int ret; |
55a07d62d HID: sony: Calibr... |
1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 |
short gyro_pitch_bias, gyro_pitch_plus, gyro_pitch_minus; short gyro_yaw_bias, gyro_yaw_plus, gyro_yaw_minus; short gyro_roll_bias, gyro_roll_plus, gyro_roll_minus; short gyro_speed_plus, gyro_speed_minus; short acc_x_plus, acc_x_minus; short acc_y_plus, acc_y_minus; short acc_z_plus, acc_z_minus; int speed_2x; int range_2g; /* For Bluetooth we use a different request, which supports CRC. * Note: in Bluetooth mode feature report 0x02 also changes the state * of the controller, so that it sends input reports of type 0x11. */ |
35f436c31 HID: sony: Treat ... |
1428 |
if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) { |
55a07d62d HID: sony: Calibr... |
1429 1430 1431 |
buf = kmalloc(DS4_FEATURE_REPORT_0x02_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; |
68330d83c HID: sony: Add co... |
1432 |
|
55a07d62d HID: sony: Calibr... |
1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 |
ret = hid_hw_raw_request(sc->hdev, 0x02, buf, DS4_FEATURE_REPORT_0x02_SIZE, HID_FEATURE_REPORT, HID_REQ_GET_REPORT); if (ret < 0) goto err_stop; } else { u8 bthdr = 0xA3; u32 crc; u32 report_crc; int retries; |
9b2b5c9a7 HID: sony: Use ke... |
1444 |
|
55a07d62d HID: sony: Calibr... |
1445 1446 1447 |
buf = kmalloc(DS4_FEATURE_REPORT_0x05_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; |
9b2b5c9a7 HID: sony: Use ke... |
1448 |
|
55a07d62d HID: sony: Calibr... |
1449 1450 1451 1452 1453 1454 1455 |
for (retries = 0; retries < 3; retries++) { ret = hid_hw_raw_request(sc->hdev, 0x05, buf, DS4_FEATURE_REPORT_0x05_SIZE, HID_FEATURE_REPORT, HID_REQ_GET_REPORT); if (ret < 0) goto err_stop; |
9b2b5c9a7 HID: sony: Use ke... |
1456 |
|
55a07d62d HID: sony: Calibr... |
1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 |
/* CRC check */ crc = crc32_le(0xFFFFFFFF, &bthdr, 1); crc = ~crc32_le(crc, buf, DS4_FEATURE_REPORT_0x05_SIZE-4); report_crc = get_unaligned_le32(&buf[DS4_FEATURE_REPORT_0x05_SIZE-4]); if (crc != report_crc) { hid_warn(sc->hdev, "DualShock 4 calibration report's CRC check failed, received crc 0x%0x != 0x%0x ", report_crc, crc); if (retries < 2) { hid_warn(sc->hdev, "Retrying DualShock 4 get calibration report request "); continue; } else { ret = -EILSEQ; goto err_stop; } } else { break; } } } |
9b2b5c9a7 HID: sony: Use ke... |
1478 |
|
55a07d62d HID: sony: Calibr... |
1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 |
gyro_pitch_bias = get_unaligned_le16(&buf[1]); gyro_yaw_bias = get_unaligned_le16(&buf[3]); gyro_roll_bias = get_unaligned_le16(&buf[5]); if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { gyro_pitch_plus = get_unaligned_le16(&buf[7]); gyro_pitch_minus = get_unaligned_le16(&buf[9]); gyro_yaw_plus = get_unaligned_le16(&buf[11]); gyro_yaw_minus = get_unaligned_le16(&buf[13]); gyro_roll_plus = get_unaligned_le16(&buf[15]); gyro_roll_minus = get_unaligned_le16(&buf[17]); } else { |
35f436c31 HID: sony: Treat ... |
1490 |
/* BT + Dongle */ |
55a07d62d HID: sony: Calibr... |
1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 |
gyro_pitch_plus = get_unaligned_le16(&buf[7]); gyro_yaw_plus = get_unaligned_le16(&buf[9]); gyro_roll_plus = get_unaligned_le16(&buf[11]); gyro_pitch_minus = get_unaligned_le16(&buf[13]); gyro_yaw_minus = get_unaligned_le16(&buf[15]); gyro_roll_minus = get_unaligned_le16(&buf[17]); } gyro_speed_plus = get_unaligned_le16(&buf[19]); gyro_speed_minus = get_unaligned_le16(&buf[21]); acc_x_plus = get_unaligned_le16(&buf[23]); acc_x_minus = get_unaligned_le16(&buf[25]); acc_y_plus = get_unaligned_le16(&buf[27]); acc_y_minus = get_unaligned_le16(&buf[29]); acc_z_plus = get_unaligned_le16(&buf[31]); acc_z_minus = get_unaligned_le16(&buf[33]); /* Set gyroscope calibration and normalization parameters. * Data values will be normalized to 1/DS4_GYRO_RES_PER_DEG_S degree/s. */ speed_2x = (gyro_speed_plus + gyro_speed_minus); sc->ds4_calib_data[0].abs_code = ABS_RX; sc->ds4_calib_data[0].bias = gyro_pitch_bias; sc->ds4_calib_data[0].sens_numer = speed_2x*DS4_GYRO_RES_PER_DEG_S; sc->ds4_calib_data[0].sens_denom = gyro_pitch_plus - gyro_pitch_minus; sc->ds4_calib_data[1].abs_code = ABS_RY; sc->ds4_calib_data[1].bias = gyro_yaw_bias; sc->ds4_calib_data[1].sens_numer = speed_2x*DS4_GYRO_RES_PER_DEG_S; sc->ds4_calib_data[1].sens_denom = gyro_yaw_plus - gyro_yaw_minus; sc->ds4_calib_data[2].abs_code = ABS_RZ; sc->ds4_calib_data[2].bias = gyro_roll_bias; sc->ds4_calib_data[2].sens_numer = speed_2x*DS4_GYRO_RES_PER_DEG_S; sc->ds4_calib_data[2].sens_denom = gyro_roll_plus - gyro_roll_minus; /* Set accelerometer calibration and normalization parameters. * Data values will be normalized to 1/DS4_ACC_RES_PER_G G. */ range_2g = acc_x_plus - acc_x_minus; sc->ds4_calib_data[3].abs_code = ABS_X; sc->ds4_calib_data[3].bias = acc_x_plus - range_2g / 2; sc->ds4_calib_data[3].sens_numer = 2*DS4_ACC_RES_PER_G; sc->ds4_calib_data[3].sens_denom = range_2g; range_2g = acc_y_plus - acc_y_minus; sc->ds4_calib_data[4].abs_code = ABS_Y; sc->ds4_calib_data[4].bias = acc_y_plus - range_2g / 2; sc->ds4_calib_data[4].sens_numer = 2*DS4_ACC_RES_PER_G; sc->ds4_calib_data[4].sens_denom = range_2g; range_2g = acc_z_plus - acc_z_minus; sc->ds4_calib_data[5].abs_code = ABS_Z; sc->ds4_calib_data[5].bias = acc_z_plus - range_2g / 2; sc->ds4_calib_data[5].sens_numer = 2*DS4_ACC_RES_PER_G; sc->ds4_calib_data[5].sens_denom = range_2g; err_stop: kfree(buf); |
9b2b5c9a7 HID: sony: Use ke... |
1549 |
return ret; |
f9ce7c283 HID: Enable Sixax... |
1550 |
} |
f2f47c385 HID: sony: Suppor... |
1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 |
static void dualshock4_calibration_work(struct work_struct *work) { struct sony_sc *sc = container_of(work, struct sony_sc, hotplug_worker); unsigned long flags; enum ds4_dongle_state dongle_state; int ret; ret = dualshock4_get_calibration_data(sc); if (ret < 0) { /* This call is very unlikely to fail for the dongle. When it * fails we are probably in a very bad state, so mark the * dongle as disabled. We will re-enable the dongle if a new * DS4 hotplug is detect from sony_raw_event as any issues * are likely resolved then (the dongle is quite stupid). */ hid_err(sc->hdev, "DualShock 4 USB dongle: calibration failed, disabling device "); dongle_state = DONGLE_DISABLED; } else { hid_info(sc->hdev, "DualShock 4 USB dongle: calibration completed "); dongle_state = DONGLE_CONNECTED; } spin_lock_irqsave(&sc->lock, flags); sc->ds4_dongle_state = dongle_state; spin_unlock_irqrestore(&sc->lock, flags); } |
221399b36 HID: sony: Simpli... |
1579 |
static void sixaxis_set_leds_from_id(struct sony_sc *sc) |
8025087ac HID: sony: Initia... |
1580 |
{ |
1adf904e9 HID: sony: unders... |
1581 |
static const u8 sixaxis_leds[10][4] = { |
8025087ac HID: sony: Initia... |
1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 |
{ 0x01, 0x00, 0x00, 0x00 }, { 0x00, 0x01, 0x00, 0x00 }, { 0x00, 0x00, 0x01, 0x00 }, { 0x00, 0x00, 0x00, 0x01 }, { 0x01, 0x00, 0x00, 0x01 }, { 0x00, 0x01, 0x00, 0x01 }, { 0x00, 0x00, 0x01, 0x01 }, { 0x01, 0x00, 0x01, 0x01 }, { 0x00, 0x01, 0x01, 0x01 }, { 0x01, 0x01, 0x01, 0x01 } }; |
221399b36 HID: sony: Simpli... |
1593 1594 1595 |
int id = sc->device_id; BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(sixaxis_leds[0])); |
8025087ac HID: sony: Initia... |
1596 1597 1598 1599 1600 |
if (id < 0) return; id %= 10; |
221399b36 HID: sony: Simpli... |
1601 |
memcpy(sc->led_state, sixaxis_leds[id], sizeof(sixaxis_leds[id])); |
8025087ac HID: sony: Initia... |
1602 |
} |
221399b36 HID: sony: Simpli... |
1603 |
static void dualshock4_set_leds_from_id(struct sony_sc *sc) |
8025087ac HID: sony: Initia... |
1604 1605 |
{ /* The first 4 color/index entries match what the PS4 assigns */ |
1adf904e9 HID: sony: unders... |
1606 |
static const u8 color_code[7][3] = { |
39254a13d HID: sony: DS4 us... |
1607 1608 1609 1610 |
/* Blue */ { 0x00, 0x00, 0x40 }, /* Red */ { 0x40, 0x00, 0x00 }, /* Green */ { 0x00, 0x40, 0x00 }, /* Pink */ { 0x20, 0x00, 0x20 }, |
8025087ac HID: sony: Initia... |
1611 1612 1613 1614 |
/* Orange */ { 0x02, 0x01, 0x00 }, /* Teal */ { 0x00, 0x01, 0x01 }, /* White */ { 0x01, 0x01, 0x01 } }; |
221399b36 HID: sony: Simpli... |
1615 1616 1617 |
int id = sc->device_id; BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(color_code[0])); |
8025087ac HID: sony: Initia... |
1618 1619 1620 1621 1622 |
if (id < 0) return; id %= 7; |
221399b36 HID: sony: Simpli... |
1623 |
memcpy(sc->led_state, color_code[id], sizeof(color_code[id])); |
8025087ac HID: sony: Initia... |
1624 |
} |
221399b36 HID: sony: Simpli... |
1625 |
static void buzz_set_leds(struct sony_sc *sc) |
f04d51404 HID: driver for P... |
1626 |
{ |
221399b36 HID: sony: Simpli... |
1627 |
struct hid_device *hdev = sc->hdev; |
f04d51404 HID: driver for P... |
1628 1629 1630 1631 |
struct list_head *report_list = &hdev->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); |
1adf904e9 HID: sony: unders... |
1632 |
s32 *value = report->field[0]->value; |
f04d51404 HID: driver for P... |
1633 |
|
221399b36 HID: sony: Simpli... |
1634 |
BUILD_BUG_ON(MAX_LEDS < 4); |
f04d51404 HID: driver for P... |
1635 |
value[0] = 0x00; |
221399b36 HID: sony: Simpli... |
1636 1637 1638 1639 |
value[1] = sc->led_state[0] ? 0xff : 0x00; value[2] = sc->led_state[1] ? 0xff : 0x00; value[3] = sc->led_state[2] ? 0xff : 0x00; value[4] = sc->led_state[3] ? 0xff : 0x00; |
f04d51404 HID: driver for P... |
1640 1641 1642 1643 |
value[5] = 0x00; value[6] = 0x00; hid_hw_request(hdev, report, HID_REQ_SET_REPORT); } |
221399b36 HID: sony: Simpli... |
1644 |
static void sony_set_leds(struct sony_sc *sc) |
0a286ef27 HID: sony: Add LE... |
1645 |
{ |
221399b36 HID: sony: Simpli... |
1646 |
if (!(sc->quirks & BUZZ_CONTROLLER)) |
b53227360 HID: sony: Make w... |
1647 |
sony_schedule_work(sc, SONY_WORKER_STATE); |
221399b36 HID: sony: Simpli... |
1648 1649 |
else buzz_set_leds(sc); |
0a286ef27 HID: sony: Add LE... |
1650 |
} |
c53825190 HID: sony: Rename... |
1651 |
static void sony_led_set_brightness(struct led_classdev *led, |
f04d51404 HID: driver for P... |
1652 1653 1654 |
enum led_brightness value) { struct device *dev = led->dev->parent; |
ee79a8f84 HID: use to_hid_d... |
1655 |
struct hid_device *hdev = to_hid_device(dev); |
f04d51404 HID: driver for P... |
1656 |
struct sony_sc *drv_data; |
f04d51404 HID: driver for P... |
1657 1658 |
int n; |
b3ed458c1 HID: sony: Add bl... |
1659 |
int force_update; |
f04d51404 HID: driver for P... |
1660 1661 |
drv_data = hid_get_drvdata(hdev); |
2251b85f3 HID: sony: Move L... |
1662 |
if (!drv_data) { |
f04d51404 HID: driver for P... |
1663 1664 1665 1666 |
hid_err(hdev, "No device data "); return; } |
f04d51404 HID: driver for P... |
1667 |
|
b3ed458c1 HID: sony: Add bl... |
1668 1669 1670 1671 1672 1673 1674 1675 |
/* * 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); |
60781cf48 HID: sony: Add LE... |
1676 |
for (n = 0; n < drv_data->led_count; n++) { |
b3ed458c1 HID: sony: Add bl... |
1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 |
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; |
221399b36 HID: sony: Simpli... |
1687 |
sony_set_leds(drv_data); |
f04d51404 HID: driver for P... |
1688 1689 1690 1691 |
break; } } } |
c53825190 HID: sony: Rename... |
1692 |
static enum led_brightness sony_led_get_brightness(struct led_classdev *led) |
f04d51404 HID: driver for P... |
1693 1694 |
{ struct device *dev = led->dev->parent; |
ee79a8f84 HID: use to_hid_d... |
1695 |
struct hid_device *hdev = to_hid_device(dev); |
f04d51404 HID: driver for P... |
1696 |
struct sony_sc *drv_data; |
f04d51404 HID: driver for P... |
1697 1698 |
int n; |
f04d51404 HID: driver for P... |
1699 1700 |
drv_data = hid_get_drvdata(hdev); |
2251b85f3 HID: sony: Move L... |
1701 |
if (!drv_data) { |
f04d51404 HID: driver for P... |
1702 1703 1704 1705 |
hid_err(hdev, "No device data "); return LED_OFF; } |
f04d51404 HID: driver for P... |
1706 |
|
60781cf48 HID: sony: Add LE... |
1707 |
for (n = 0; n < drv_data->led_count; n++) { |
7db7504a4 HID: hid-sony: re... |
1708 1709 |
if (led == drv_data->leds[n]) return drv_data->led_state[n]; |
f04d51404 HID: driver for P... |
1710 |
} |
7db7504a4 HID: hid-sony: re... |
1711 |
return LED_OFF; |
f04d51404 HID: driver for P... |
1712 |
} |
f04d51404 HID: driver for P... |
1713 |
|
b3ed458c1 HID: sony: Add bl... |
1714 1715 1716 1717 |
static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on, unsigned long *delay_off) { struct device *dev = led->dev->parent; |
ee79a8f84 HID: use to_hid_d... |
1718 |
struct hid_device *hdev = to_hid_device(dev); |
b3ed458c1 HID: sony: Add bl... |
1719 1720 |
struct sony_sc *drv_data = hid_get_drvdata(hdev); int n; |
1adf904e9 HID: sony: unders... |
1721 |
u8 new_on, new_off; |
b3ed458c1 HID: sony: Add bl... |
1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 |
if (!drv_data) { hid_err(hdev, "No device data "); return -EINVAL; } /* Max delay is 255 deciseconds or 2550 milliseconds */ if (*delay_on > 2550) *delay_on = 2550; if (*delay_off > 2550) *delay_off = 2550; /* Blink at 1 Hz if both values are zero */ if (!*delay_on && !*delay_off) *delay_on = *delay_off = 500; new_on = *delay_on / 10; new_off = *delay_off / 10; for (n = 0; n < drv_data->led_count; n++) { if (led == drv_data->leds[n]) break; } /* This LED is not registered on this device */ if (n >= drv_data->led_count) return -EINVAL; /* Don't schedule work if the values didn't change */ if (new_on != drv_data->led_delay_on[n] || new_off != drv_data->led_delay_off[n]) { drv_data->led_delay_on[n] = new_on; drv_data->led_delay_off[n] = new_off; |
b53227360 HID: sony: Make w... |
1756 |
sony_schedule_work(drv_data, SONY_WORKER_STATE); |
b3ed458c1 HID: sony: Add bl... |
1757 1758 1759 1760 |
} return 0; } |
fa57a8107 HID: sony: Conver... |
1761 |
static void sony_leds_remove(struct sony_sc *sc) |
0a286ef27 HID: sony: Add LE... |
1762 |
{ |
0a286ef27 HID: sony: Add LE... |
1763 1764 |
struct led_classdev *led; int n; |
fa57a8107 HID: sony: Conver... |
1765 |
BUG_ON(!(sc->quirks & SONY_LED_SUPPORT)); |
0a286ef27 HID: sony: Add LE... |
1766 |
|
fa57a8107 HID: sony: Conver... |
1767 1768 1769 |
for (n = 0; n < sc->led_count; n++) { led = sc->leds[n]; sc->leds[n] = NULL; |
0a286ef27 HID: sony: Add LE... |
1770 1771 1772 1773 1774 |
if (!led) continue; led_classdev_unregister(led); kfree(led); } |
60781cf48 HID: sony: Add LE... |
1775 |
|
fa57a8107 HID: sony: Conver... |
1776 |
sc->led_count = 0; |
0a286ef27 HID: sony: Add LE... |
1777 |
} |
fa57a8107 HID: sony: Conver... |
1778 |
static int sony_leds_init(struct sony_sc *sc) |
f04d51404 HID: driver for P... |
1779 |
{ |
fa57a8107 HID: sony: Conver... |
1780 |
struct hid_device *hdev = sc->hdev; |
40e32ee6e HID: sony: fix le... |
1781 |
int n, ret = 0; |
b3ed458c1 HID: sony: Add bl... |
1782 |
int use_ds4_names; |
40e32ee6e HID: sony: fix le... |
1783 1784 1785 |
struct led_classdev *led; size_t name_sz; char *name; |
0a286ef27 HID: sony: Add LE... |
1786 1787 |
size_t name_len; const char *name_fmt; |
b3ed458c1 HID: sony: Add bl... |
1788 1789 |
static const char * const ds4_name_str[] = { "red", "green", "blue", "global" }; |
1adf904e9 HID: sony: unders... |
1790 1791 |
u8 max_brightness[MAX_LEDS] = { [0 ... (MAX_LEDS - 1)] = 1 }; u8 use_hw_blink[MAX_LEDS] = { 0 }; |
f04d51404 HID: driver for P... |
1792 |
|
fa57a8107 HID: sony: Conver... |
1793 |
BUG_ON(!(sc->quirks & SONY_LED_SUPPORT)); |
0a286ef27 HID: sony: Add LE... |
1794 |
|
fa57a8107 HID: sony: Conver... |
1795 1796 |
if (sc->quirks & BUZZ_CONTROLLER) { sc->led_count = 4; |
b3ed458c1 HID: sony: Add bl... |
1797 |
use_ds4_names = 0; |
0a286ef27 HID: sony: Add LE... |
1798 1799 1800 1801 1802 |
name_len = strlen("::buzz#"); name_fmt = "%s::buzz%d"; /* Validate expected report characteristics. */ if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7)) return -ENODEV; |
fa57a8107 HID: sony: Conver... |
1803 |
} else if (sc->quirks & DUALSHOCK4_CONTROLLER) { |
221399b36 HID: sony: Simpli... |
1804 1805 |
dualshock4_set_leds_from_id(sc); sc->led_state[3] = 1; |
b3ed458c1 HID: sony: Add bl... |
1806 1807 1808 1809 |
sc->led_count = 4; memset(max_brightness, 255, 3); use_hw_blink[3] = 1; use_ds4_names = 1; |
61ebca937 HID: sony: Use co... |
1810 1811 |
name_len = 0; name_fmt = "%s:%s"; |
c5e0c1c49 HID: sony: Add su... |
1812 1813 1814 1815 1816 1817 |
} else if (sc->quirks & MOTION_CONTROLLER) { sc->led_count = 3; memset(max_brightness, 255, 3); use_ds4_names = 1; name_len = 0; name_fmt = "%s:%s"; |
4545ee0a7 HID: hid-sony: Na... |
1818 |
} else if (sc->quirks & NAVIGATION_CONTROLLER) { |
1adf904e9 HID: sony: unders... |
1819 |
static const u8 navigation_leds[4] = {0x01, 0x00, 0x00, 0x00}; |
4545ee0a7 HID: hid-sony: Na... |
1820 1821 1822 1823 1824 1825 1826 |
memcpy(sc->led_state, navigation_leds, sizeof(navigation_leds)); sc->led_count = 1; memset(use_hw_blink, 1, 4); use_ds4_names = 0; name_len = strlen("::sony#"); name_fmt = "%s::sony%d"; |
60781cf48 HID: sony: Add LE... |
1827 |
} else { |
221399b36 HID: sony: Simpli... |
1828 |
sixaxis_set_leds_from_id(sc); |
fa57a8107 HID: sony: Conver... |
1829 |
sc->led_count = 4; |
b3ed458c1 HID: sony: Add bl... |
1830 1831 |
memset(use_hw_blink, 1, 4); use_ds4_names = 0; |
61ebca937 HID: sony: Use co... |
1832 1833 |
name_len = strlen("::sony#"); name_fmt = "%s::sony%d"; |
60781cf48 HID: sony: Add LE... |
1834 |
} |
ad142b9e4 HID: sony: Fix mu... |
1835 1836 |
/* * Clear LEDs as we have no way of reading their initial state. This is |
f04d51404 HID: driver for P... |
1837 |
* only relevant if the driver is loaded after somebody actively set the |
ad142b9e4 HID: sony: Fix mu... |
1838 1839 |
* LEDs to on */ |
221399b36 HID: sony: Simpli... |
1840 |
sony_set_leds(sc); |
f04d51404 HID: driver for P... |
1841 |
|
0a286ef27 HID: sony: Add LE... |
1842 |
name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1; |
f04d51404 HID: driver for P... |
1843 |
|
fa57a8107 HID: sony: Conver... |
1844 |
for (n = 0; n < sc->led_count; n++) { |
61ebca937 HID: sony: Use co... |
1845 |
|
b3ed458c1 HID: sony: Add bl... |
1846 1847 |
if (use_ds4_names) name_sz = strlen(dev_name(&hdev->dev)) + strlen(ds4_name_str[n]) + 2; |
61ebca937 HID: sony: Use co... |
1848 |
|
40e32ee6e HID: sony: fix le... |
1849 1850 1851 1852 |
led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL); if (!led) { hid_err(hdev, "Couldn't allocate memory for LED %d ", n); |
8cd5fcda2 HID: sony: fix er... |
1853 |
ret = -ENOMEM; |
40e32ee6e HID: sony: fix le... |
1854 1855 |
goto error_leds; } |
f04d51404 HID: driver for P... |
1856 |
|
40e32ee6e HID: sony: fix le... |
1857 |
name = (void *)(&led[1]); |
b3ed458c1 HID: sony: Add bl... |
1858 1859 1860 |
if (use_ds4_names) snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), ds4_name_str[n]); |
61ebca937 HID: sony: Use co... |
1861 1862 |
else snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1); |
40e32ee6e HID: sony: fix le... |
1863 |
led->name = name; |
221399b36 HID: sony: Simpli... |
1864 |
led->brightness = sc->led_state[n]; |
b3ed458c1 HID: sony: Add bl... |
1865 |
led->max_brightness = max_brightness[n]; |
765a1077c HID: sony: Use LE... |
1866 |
led->flags = LED_CORE_SUSPENDRESUME; |
c53825190 HID: sony: Rename... |
1867 1868 |
led->brightness_get = sony_led_get_brightness; led->brightness_set = sony_led_set_brightness; |
f04d51404 HID: driver for P... |
1869 |
|
b3ed458c1 HID: sony: Add bl... |
1870 1871 |
if (use_hw_blink[n]) led->blink_set = sony_led_blink_set; |
8025087ac HID: sony: Initia... |
1872 |
sc->leds[n] = led; |
8cd5fcda2 HID: sony: fix er... |
1873 1874 |
ret = led_classdev_register(&hdev->dev, led); if (ret) { |
40e32ee6e HID: sony: fix le... |
1875 1876 |
hid_err(hdev, "Failed to register LED %d ", n); |
8025087ac HID: sony: Initia... |
1877 |
sc->leds[n] = NULL; |
40e32ee6e HID: sony: fix le... |
1878 1879 |
kfree(led); goto error_leds; |
f04d51404 HID: driver for P... |
1880 1881 |
} } |
f04d51404 HID: driver for P... |
1882 1883 |
return ret; |
f04d51404 HID: driver for P... |
1884 |
error_leds: |
fa57a8107 HID: sony: Conver... |
1885 |
sony_leds_remove(sc); |
f04d51404 HID: driver for P... |
1886 |
|
f04d51404 HID: driver for P... |
1887 |
return ret; |
f04d51404 HID: driver for P... |
1888 |
} |
d8aaccda7 HID: sony: Refact... |
1889 |
static void sixaxis_send_output_report(struct sony_sc *sc) |
a08c22c0d HID: sony: Add fo... |
1890 |
{ |
9b2b5c9a7 HID: sony: Use ke... |
1891 |
static const union sixaxis_output_report_01 default_report = { |
55d3b664d HID: sony: Use a ... |
1892 1893 |
.buf = { 0x01, |
ad07b7a6c HID: sony: Fixup ... |
1894 |
0x01, 0xff, 0x00, 0xff, 0x00, |
55d3b664d HID: sony: Use a ... |
1895 1896 1897 1898 1899 1900 1901 |
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x27, 0x10, 0x00, 0x32, 0xff, 0x27, 0x10, 0x00, 0x32, 0xff, 0x27, 0x10, 0x00, 0x32, 0xff, 0x27, 0x10, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00 } |
a08c22c0d HID: sony: Add fo... |
1902 |
}; |
9b2b5c9a7 HID: sony: Use ke... |
1903 1904 1905 1906 1907 1908 |
struct sixaxis_output_report *report = (struct sixaxis_output_report *)sc->output_report_dmabuf; int n; /* Initialize the report with default values */ memcpy(report, &default_report, sizeof(struct sixaxis_output_report)); |
9f323b681 HID: sony: Send F... |
1909 |
|
0a286ef27 HID: sony: Add LE... |
1910 |
#ifdef CONFIG_SONY_FF |
9b2b5c9a7 HID: sony: Use ke... |
1911 1912 |
report->rumble.right_motor_on = sc->right ? 1 : 0; report->rumble.left_motor_force = sc->left; |
0a286ef27 HID: sony: Add LE... |
1913 |
#endif |
9b2b5c9a7 HID: sony: Use ke... |
1914 1915 1916 1917 |
report->leds_bitmap |= sc->led_state[0] << 1; report->leds_bitmap |= sc->led_state[1] << 2; report->leds_bitmap |= sc->led_state[2] << 3; report->leds_bitmap |= sc->led_state[3] << 4; |
9f323b681 HID: sony: Send F... |
1918 |
|
88f6576fa HID: hid-sony - a... |
1919 |
/* Set flag for all leds off, required for 3rd party INTEC controller */ |
9b2b5c9a7 HID: sony: Use ke... |
1920 1921 |
if ((report->leds_bitmap & 0x1E) == 0) report->leds_bitmap |= 0x20; |
88f6576fa HID: hid-sony - a... |
1922 |
|
b3ed458c1 HID: sony: Add bl... |
1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 |
/* * 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]) { |
9b2b5c9a7 HID: sony: Use ke... |
1934 1935 |
report->led[3 - n].duty_off = sc->led_delay_off[n]; report->led[3 - n].duty_on = sc->led_delay_on[n]; |
b3ed458c1 HID: sony: Add bl... |
1936 1937 |
} } |
1adf904e9 HID: sony: unders... |
1938 |
hid_hw_raw_request(sc->hdev, report->report_id, (u8 *)report, |
9b2b5c9a7 HID: sony: Use ke... |
1939 1940 |
sizeof(struct sixaxis_output_report), HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); |
9f323b681 HID: sony: Send F... |
1941 |
} |
d8aaccda7 HID: sony: Refact... |
1942 |
static void dualshock4_send_output_report(struct sony_sc *sc) |
0bd88dd3d HID: sony: Add fo... |
1943 |
{ |
0da8ea658 HID: sony: Use st... |
1944 |
struct hid_device *hdev = sc->hdev; |
1adf904e9 HID: sony: unders... |
1945 |
u8 *buf = sc->output_report_dmabuf; |
48220237b HID: sony: Use lo... |
1946 |
int offset; |
c4425c8f2 HID: sony: Update... |
1947 |
/* |
77b499e73 HID: sony: Make D... |
1948 1949 1950 1951 1952 1953 1954 |
* NOTE: The lower 6 bits of buf[1] field of the Bluetooth report * control the interval at which Dualshock 4 reports data: * 0x00 - 1ms * 0x01 - 1ms * 0x02 - 2ms * 0x3E - 62ms * 0x3F - disabled |
c4425c8f2 HID: sony: Update... |
1955 |
*/ |
35f436c31 HID: sony: Treat ... |
1956 |
if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) { |
2c159de05 HID: sony: Adjust... |
1957 |
memset(buf, 0, DS4_OUTPUT_REPORT_0x05_SIZE); |
fdcf105d3 HID: sony: Add Du... |
1958 |
buf[0] = 0x05; |
5caceb069 HID: sony: Set pr... |
1959 |
buf[1] = 0x07; /* blink + LEDs + motor */ |
fdcf105d3 HID: sony: Add Du... |
1960 1961 |
offset = 4; } else { |
2c159de05 HID: sony: Adjust... |
1962 |
memset(buf, 0, DS4_OUTPUT_REPORT_0x11_SIZE); |
fdcf105d3 HID: sony: Add Du... |
1963 |
buf[0] = 0x11; |
77b499e73 HID: sony: Make D... |
1964 |
buf[1] = 0xC0 /* HID + CRC */ | sc->ds4_bt_poll_interval; |
5caceb069 HID: sony: Set pr... |
1965 |
buf[3] = 0x07; /* blink + LEDs + motor */ |
fdcf105d3 HID: sony: Add Du... |
1966 1967 |
offset = 6; } |
0bd88dd3d HID: sony: Add fo... |
1968 1969 |
#ifdef CONFIG_SONY_FF |
48220237b HID: sony: Use lo... |
1970 1971 1972 1973 |
buf[offset++] = sc->right; buf[offset++] = sc->left; #else offset += 2; |
0bd88dd3d HID: sony: Add fo... |
1974 |
#endif |
b3ed458c1 HID: sony: Add bl... |
1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 |
/* LED 3 is the global control */ if (sc->led_state[3]) { buf[offset++] = sc->led_state[0]; buf[offset++] = sc->led_state[1]; buf[offset++] = sc->led_state[2]; } else { offset += 3; } /* If both delay values are zero the DualShock 4 disables blinking. */ buf[offset++] = sc->led_delay_on[3]; buf[offset++] = sc->led_delay_off[3]; |
60781cf48 HID: sony: Add LE... |
1987 |
|
35f436c31 HID: sony: Treat ... |
1988 |
if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) |
2c159de05 HID: sony: Adjust... |
1989 |
hid_hw_output_report(hdev, buf, DS4_OUTPUT_REPORT_0x05_SIZE); |
e7ef53adb HID: sony: Send d... |
1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 |
else { /* CRC generation */ u8 bthdr = 0xA2; u32 crc; crc = crc32_le(0xFFFFFFFF, &bthdr, 1); crc = ~crc32_le(crc, buf, DS4_OUTPUT_REPORT_0x11_SIZE-4); put_unaligned_le32(crc, &buf[74]); hid_hw_output_report(hdev, buf, DS4_OUTPUT_REPORT_0x11_SIZE); } |
0bd88dd3d HID: sony: Add fo... |
2000 |
} |
d8aaccda7 HID: sony: Refact... |
2001 |
static void motion_send_output_report(struct sony_sc *sc) |
c5e0c1c49 HID: sony: Add su... |
2002 |
{ |
c5e0c1c49 HID: sony: Add su... |
2003 2004 2005 |
struct hid_device *hdev = sc->hdev; struct motion_output_report_02 *report = (struct motion_output_report_02 *)sc->output_report_dmabuf; |
41d2d4253 HID: sony: PS3 Mo... |
2006 |
memset(report, 0, MOTION_REPORT_0x02_SIZE); |
c5e0c1c49 HID: sony: Add su... |
2007 2008 2009 2010 2011 2012 2013 2014 2015 |
report->type = 0x02; /* set leds */ report->r = sc->led_state[0]; report->g = sc->led_state[1]; report->b = sc->led_state[2]; #ifdef CONFIG_SONY_FF report->rumble = max(sc->right, sc->left); #endif |
1adf904e9 HID: sony: unders... |
2016 |
hid_hw_output_report(hdev, (u8 *)report, MOTION_REPORT_0x02_SIZE); |
c5e0c1c49 HID: sony: Add su... |
2017 |
} |
decd946c9 HID: sony: Save a... |
2018 2019 2020 2021 2022 |
static inline void sony_send_output_report(struct sony_sc *sc) { if (sc->send_output_report) sc->send_output_report(sc); } |
d8aaccda7 HID: sony: Refact... |
2023 2024 2025 |
static void sony_state_worker(struct work_struct *work) { struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); |
ef916ef5e HID: sony: fix so... |
2026 |
|
d8aaccda7 HID: sony: Refact... |
2027 2028 |
sc->send_output_report(sc); } |
9b2b5c9a7 HID: sony: Use ke... |
2029 2030 |
static int sony_allocate_output_report(struct sony_sc *sc) { |
4545ee0a7 HID: hid-sony: Na... |
2031 2032 |
if ((sc->quirks & SIXAXIS_CONTROLLER) || (sc->quirks & NAVIGATION_CONTROLLER)) |
9b2b5c9a7 HID: sony: Use ke... |
2033 2034 2035 2036 |
sc->output_report_dmabuf = kmalloc(sizeof(union sixaxis_output_report_01), GFP_KERNEL); else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) |
2c159de05 HID: sony: Adjust... |
2037 |
sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x11_SIZE, |
9b2b5c9a7 HID: sony: Use ke... |
2038 |
GFP_KERNEL); |
35f436c31 HID: sony: Treat ... |
2039 |
else if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) |
2c159de05 HID: sony: Adjust... |
2040 |
sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x05_SIZE, |
9b2b5c9a7 HID: sony: Use ke... |
2041 |
GFP_KERNEL); |
c5e0c1c49 HID: sony: Add su... |
2042 |
else if (sc->quirks & MOTION_CONTROLLER) |
41d2d4253 HID: sony: PS3 Mo... |
2043 2044 |
sc->output_report_dmabuf = kmalloc(MOTION_REPORT_0x02_SIZE, GFP_KERNEL); |
9b2b5c9a7 HID: sony: Use ke... |
2045 2046 2047 2048 2049 2050 2051 2052 |
else return 0; if (!sc->output_report_dmabuf) return -ENOMEM; return 0; } |
0a286ef27 HID: sony: Add LE... |
2053 |
#ifdef CONFIG_SONY_FF |
9f323b681 HID: sony: Send F... |
2054 2055 2056 |
static int sony_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect) { |
a08c22c0d HID: sony: Add fo... |
2057 |
struct hid_device *hid = input_get_drvdata(dev); |
9f323b681 HID: sony: Send F... |
2058 |
struct sony_sc *sc = hid_get_drvdata(hid); |
a08c22c0d HID: sony: Add fo... |
2059 2060 2061 |
if (effect->type != FF_RUMBLE) return 0; |
9f323b681 HID: sony: Send F... |
2062 |
sc->left = effect->u.rumble.strong_magnitude / 256; |
0bd88dd3d HID: sony: Add fo... |
2063 |
sc->right = effect->u.rumble.weak_magnitude / 256; |
a08c22c0d HID: sony: Add fo... |
2064 |
|
b53227360 HID: sony: Make w... |
2065 |
sony_schedule_work(sc, SONY_WORKER_STATE); |
9f323b681 HID: sony: Send F... |
2066 |
return 0; |
a08c22c0d HID: sony: Add fo... |
2067 |
} |
fa57a8107 HID: sony: Conver... |
2068 |
static int sony_init_ff(struct sony_sc *sc) |
a08c22c0d HID: sony: Add fo... |
2069 |
{ |
fa57a8107 HID: sony: Conver... |
2070 |
struct hid_input *hidinput = list_entry(sc->hdev->inputs.next, |
a08c22c0d HID: sony: Add fo... |
2071 2072 2073 2074 2075 2076 2077 2078 |
struct hid_input, list); struct input_dev *input_dev = hidinput->input; input_set_capability(input_dev, EV_FF, FF_RUMBLE); return input_ff_create_memless(input_dev, NULL, sony_play_effect); } #else |
fa57a8107 HID: sony: Conver... |
2079 |
static int sony_init_ff(struct sony_sc *sc) |
a08c22c0d HID: sony: Add fo... |
2080 2081 2082 |
{ return 0; } |
9f323b681 HID: sony: Send F... |
2083 |
|
a08c22c0d HID: sony: Add fo... |
2084 |
#endif |
d902f4724 HID: sony: add ba... |
2085 2086 2087 2088 |
static int sony_battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { |
297d716f6 power_supply: Cha... |
2089 |
struct sony_sc *sc = power_supply_get_drvdata(psy); |
d902f4724 HID: sony: add ba... |
2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 |
unsigned long flags; int ret = 0; u8 battery_charging, battery_capacity, cable_state; spin_lock_irqsave(&sc->lock, flags); battery_charging = sc->battery_charging; battery_capacity = sc->battery_capacity; cable_state = sc->cable_state; spin_unlock_irqrestore(&sc->lock, flags); switch (psp) { case POWER_SUPPLY_PROP_PRESENT: val->intval = 1; break; case POWER_SUPPLY_PROP_SCOPE: val->intval = POWER_SUPPLY_SCOPE_DEVICE; break; case POWER_SUPPLY_PROP_CAPACITY: val->intval = battery_capacity; break; case POWER_SUPPLY_PROP_STATUS: if (battery_charging) val->intval = POWER_SUPPLY_STATUS_CHARGING; else if (battery_capacity == 100 && cable_state) val->intval = POWER_SUPPLY_STATUS_FULL; else val->intval = POWER_SUPPLY_STATUS_DISCHARGING; break; default: ret = -EINVAL; break; } return ret; |
9f323b681 HID: sony: Send F... |
2124 |
} |
0f3982308 HID: sony: Relax ... |
2125 |
static int sony_battery_probe(struct sony_sc *sc, int append_dev_id) |
c4e1ddf26 HID: sony: Cache ... |
2126 |
{ |
0f3982308 HID: sony: Relax ... |
2127 2128 2129 |
const char *battery_str_fmt = append_dev_id ? "sony_controller_battery_%pMR_%i" : "sony_controller_battery_%pMR"; |
297d716f6 power_supply: Cha... |
2130 |
struct power_supply_config psy_cfg = { .drv_data = sc, }; |
c4e1ddf26 HID: sony: Cache ... |
2131 |
struct hid_device *hdev = sc->hdev; |
d902f4724 HID: sony: add ba... |
2132 |
int ret; |
c4e1ddf26 HID: sony: Cache ... |
2133 |
|
ad142b9e4 HID: sony: Fix mu... |
2134 2135 |
/* * Set the default battery level to 100% to avoid low battery warnings |
d9a293a95 HID: sony: Set in... |
2136 2137 2138 |
* if the battery is polled before the first device report is received. */ sc->battery_capacity = 100; |
297d716f6 power_supply: Cha... |
2139 2140 2141 2142 2143 |
sc->battery_desc.properties = sony_battery_props; sc->battery_desc.num_properties = ARRAY_SIZE(sony_battery_props); sc->battery_desc.get_property = sony_battery_get_property; sc->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY; sc->battery_desc.use_for_apm = 0; |
0f3982308 HID: sony: Relax ... |
2144 2145 |
sc->battery_desc.name = kasprintf(GFP_KERNEL, battery_str_fmt, sc->mac_address, sc->device_id); |
297d716f6 power_supply: Cha... |
2146 |
if (!sc->battery_desc.name) |
d902f4724 HID: sony: add ba... |
2147 |
return -ENOMEM; |
c4e1ddf26 HID: sony: Cache ... |
2148 |
|
297d716f6 power_supply: Cha... |
2149 2150 2151 2152 |
sc->battery = power_supply_register(&hdev->dev, &sc->battery_desc, &psy_cfg); if (IS_ERR(sc->battery)) { ret = PTR_ERR(sc->battery); |
d902f4724 HID: sony: add ba... |
2153 2154 2155 2156 |
hid_err(hdev, "Unable to register battery device "); goto err_free; } |
c4e1ddf26 HID: sony: Cache ... |
2157 |
|
297d716f6 power_supply: Cha... |
2158 |
power_supply_powers(sc->battery, &hdev->dev); |
a08c22c0d HID: sony: Add fo... |
2159 |
return 0; |
d902f4724 HID: sony: add ba... |
2160 2161 |
err_free: |
297d716f6 power_supply: Cha... |
2162 2163 |
kfree(sc->battery_desc.name); sc->battery_desc.name = NULL; |
d902f4724 HID: sony: add ba... |
2164 |
return ret; |
a08c22c0d HID: sony: Add fo... |
2165 |
} |
9f323b681 HID: sony: Send F... |
2166 |
|
d902f4724 HID: sony: add ba... |
2167 |
static void sony_battery_remove(struct sony_sc *sc) |
9f323b681 HID: sony: Send F... |
2168 |
{ |
297d716f6 power_supply: Cha... |
2169 |
if (!sc->battery_desc.name) |
d902f4724 HID: sony: add ba... |
2170 |
return; |
297d716f6 power_supply: Cha... |
2171 2172 2173 |
power_supply_unregister(sc->battery); kfree(sc->battery_desc.name); sc->battery_desc.name = NULL; |
9f323b681 HID: sony: Send F... |
2174 |
} |
a08c22c0d HID: sony: Add fo... |
2175 |
|
d2d782fcc HID: sony: Preven... |
2176 2177 2178 2179 2180 |
/* * 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. |
0f3982308 HID: sony: Relax ... |
2181 2182 2183 2184 2185 |
* * 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. |
d2d782fcc HID: sony: Preven... |
2186 |
*/ |
0f3982308 HID: sony: Relax ... |
2187 2188 2189 2190 2191 2192 2193 2194 |
static inline int sony_compare_connection_type(struct sony_sc *sc0, struct sony_sc *sc1) { const int sc0_not_bt = !(sc0->quirks & SONY_BT_DEVICE); const int sc1_not_bt = !(sc1->quirks & SONY_BT_DEVICE); return sc0_not_bt == sc1_not_bt; } |
d2d782fcc HID: sony: Preven... |
2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 |
static int sony_check_add_dev_list(struct sony_sc *sc) { struct sony_sc *entry; unsigned long flags; int ret; spin_lock_irqsave(&sony_dev_list_lock, flags); list_for_each_entry(entry, &sony_device_list, list_node) { ret = memcmp(sc->mac_address, entry->mac_address, sizeof(sc->mac_address)); if (!ret) { |
0f3982308 HID: sony: Relax ... |
2207 2208 2209 2210 2211 2212 2213 |
if (sony_compare_connection_type(sc, entry)) { ret = 1; } else { ret = -EEXIST; hid_info(sc->hdev, "controller with MAC address %pMR already connected ", |
d2d782fcc HID: sony: Preven... |
2214 |
sc->mac_address); |
0f3982308 HID: sony: Relax ... |
2215 |
} |
d2d782fcc HID: sony: Preven... |
2216 |
goto unlock; |
c4e1ddf26 HID: sony: Cache ... |
2217 2218 |
} } |
d2d782fcc HID: sony: Preven... |
2219 2220 |
ret = 0; list_add(&(sc->list_node), &sony_device_list); |
c4e1ddf26 HID: sony: Cache ... |
2221 |
|
d2d782fcc HID: sony: Preven... |
2222 2223 2224 2225 2226 2227 2228 2229 |
unlock: spin_unlock_irqrestore(&sony_dev_list_lock, flags); return ret; } static void sony_remove_dev_list(struct sony_sc *sc) { unsigned long flags; |
c4e1ddf26 HID: sony: Cache ... |
2230 |
|
d2d782fcc HID: sony: Preven... |
2231 2232 2233 2234 2235 |
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); } |
c4e1ddf26 HID: sony: Cache ... |
2236 |
} |
d2d782fcc HID: sony: Preven... |
2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 |
static int 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; } static int sony_check_add(struct sony_sc *sc) { |
1adf904e9 HID: sony: unders... |
2259 |
u8 *buf = NULL; |
d2d782fcc HID: sony: Preven... |
2260 2261 2262 |
int n, ret; if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) || |
12e9a6d72 HID: sony: Add su... |
2263 |
(sc->quirks & MOTION_CONTROLLER_BT) || |
4545ee0a7 HID: hid-sony: Na... |
2264 |
(sc->quirks & NAVIGATION_CONTROLLER_BT) || |
d2d782fcc HID: sony: Preven... |
2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 |
(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 "); return 0; } |
35f436c31 HID: sony: Treat ... |
2277 |
} else if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) { |
2c159de05 HID: sony: Adjust... |
2278 |
buf = kmalloc(DS4_FEATURE_REPORT_0x81_SIZE, GFP_KERNEL); |
9b2b5c9a7 HID: sony: Use ke... |
2279 2280 |
if (!buf) return -ENOMEM; |
d2d782fcc HID: sony: Preven... |
2281 2282 2283 2284 2285 2286 |
/* * The MAC address of a DS4 controller connected via USB can be * retrieved with feature report 0x81. The address begins at * offset 1. */ |
9b2b5c9a7 HID: sony: Use ke... |
2287 |
ret = hid_hw_raw_request(sc->hdev, 0x81, buf, |
2c159de05 HID: sony: Adjust... |
2288 |
DS4_FEATURE_REPORT_0x81_SIZE, HID_FEATURE_REPORT, |
9b2b5c9a7 HID: sony: Use ke... |
2289 |
HID_REQ_GET_REPORT); |
d2d782fcc HID: sony: Preven... |
2290 |
|
2c159de05 HID: sony: Adjust... |
2291 |
if (ret != DS4_FEATURE_REPORT_0x81_SIZE) { |
d2d782fcc HID: sony: Preven... |
2292 2293 |
hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address "); |
9b2b5c9a7 HID: sony: Use ke... |
2294 2295 |
ret = ret < 0 ? ret : -EINVAL; goto out_free; |
d2d782fcc HID: sony: Preven... |
2296 2297 2298 |
} memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address)); |
c70d5f70c HID: sony: Use DS... |
2299 2300 2301 2302 2303 2304 |
snprintf(sc->hdev->uniq, sizeof(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]); |
4545ee0a7 HID: hid-sony: Na... |
2305 2306 |
} else if ((sc->quirks & SIXAXIS_CONTROLLER_USB) || (sc->quirks & NAVIGATION_CONTROLLER_USB)) { |
9b2b5c9a7 HID: sony: Use ke... |
2307 2308 2309 |
buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; |
d2d782fcc HID: sony: Preven... |
2310 2311 2312 2313 2314 2315 |
/* * The MAC address of a Sixaxis controller connected via USB can * be retrieved with feature report 0xf2. The address begins at * offset 4. */ |
9b2b5c9a7 HID: sony: Use ke... |
2316 2317 2318 |
ret = hid_hw_raw_request(sc->hdev, 0xf2, buf, SIXAXIS_REPORT_0xF2_SIZE, HID_FEATURE_REPORT, HID_REQ_GET_REPORT); |
d2d782fcc HID: sony: Preven... |
2319 |
|
9b2b5c9a7 HID: sony: Use ke... |
2320 |
if (ret != SIXAXIS_REPORT_0xF2_SIZE) { |
d2d782fcc HID: sony: Preven... |
2321 2322 |
hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address "); |
9b2b5c9a7 HID: sony: Use ke... |
2323 2324 |
ret = ret < 0 ? ret : -EINVAL; goto out_free; |
d2d782fcc HID: sony: Preven... |
2325 2326 2327 2328 2329 2330 2331 2332 |
} /* * 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]; |
5a144be39 HID: sony: Use DS... |
2333 2334 2335 2336 2337 2338 |
snprintf(sc->hdev->uniq, sizeof(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]); |
d2d782fcc HID: sony: Preven... |
2339 2340 2341 |
} else { return 0; } |
9b2b5c9a7 HID: sony: Use ke... |
2342 2343 2344 2345 2346 2347 2348 |
ret = sony_check_add_dev_list(sc); out_free: kfree(buf); return ret; |
d2d782fcc HID: sony: Preven... |
2349 |
} |
8025087ac HID: sony: Initia... |
2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 |
static int sony_set_device_id(struct sony_sc *sc) { int ret; /* * Only DualShock 4 or Sixaxis controllers get an id. * All others are set to -1. */ if ((sc->quirks & SIXAXIS_CONTROLLER) || (sc->quirks & DUALSHOCK4_CONTROLLER)) { ret = ida_simple_get(&sony_device_id_allocator, 0, 0, GFP_KERNEL); if (ret < 0) { sc->device_id = -1; return ret; } sc->device_id = ret; } else { sc->device_id = -1; } return 0; } static void sony_release_device_id(struct sony_sc *sc) { if (sc->device_id >= 0) { ida_simple_remove(&sony_device_id_allocator, sc->device_id); sc->device_id = -1; } } |
d8aaccda7 HID: sony: Refact... |
2381 |
static inline void sony_init_output_report(struct sony_sc *sc, |
09593e388 HID: sony: fix er... |
2382 |
void (*send_output_report)(struct sony_sc *)) |
462620474 HID: sony: Use in... |
2383 |
{ |
d8aaccda7 HID: sony: Refact... |
2384 |
sc->send_output_report = send_output_report; |
b53227360 HID: sony: Make w... |
2385 |
if (!sc->state_worker_initialized) |
d8aaccda7 HID: sony: Refact... |
2386 |
INIT_WORK(&sc->state_worker, sony_state_worker); |
462620474 HID: sony: Use in... |
2387 |
|
b53227360 HID: sony: Make w... |
2388 |
sc->state_worker_initialized = 1; |
462620474 HID: sony: Use in... |
2389 2390 2391 2392 |
} static inline void sony_cancel_work_sync(struct sony_sc *sc) { |
f2f47c385 HID: sony: Suppor... |
2393 2394 |
if (sc->hotplug_worker_initialized) cancel_work_sync(&sc->hotplug_worker); |
b53227360 HID: sony: Make w... |
2395 |
if (sc->state_worker_initialized) |
462620474 HID: sony: Use in... |
2396 2397 |
cancel_work_sync(&sc->state_worker); } |
d2d782fcc HID: sony: Preven... |
2398 |
|
77b499e73 HID: sony: Make D... |
2399 |
|
e1bc84d00 HID: sony: Fix ra... |
2400 2401 |
static int sony_input_configured(struct hid_device *hdev, struct hid_input *hidinput) |
bd28ce008 HID: move sony qu... |
2402 |
{ |
e1bc84d00 HID: sony: Fix ra... |
2403 |
struct sony_sc *sc = hid_get_drvdata(hdev); |
0f3982308 HID: sony: Relax ... |
2404 |
int append_dev_id; |
e1bc84d00 HID: sony: Fix ra... |
2405 |
int ret; |
bd28ce008 HID: move sony qu... |
2406 |
|
131a8a9a5 HID: sony: Preven... |
2407 |
ret = sony_set_device_id(sc); |
9b2b5c9a7 HID: sony: Use ke... |
2408 |
if (ret < 0) { |
131a8a9a5 HID: sony: Preven... |
2409 2410 |
hid_err(hdev, "failed to allocate the device id "); |
9b2b5c9a7 HID: sony: Use ke... |
2411 2412 |
goto err_stop; } |
df848bc05 HID: sony: Perfor... |
2413 2414 2415 |
ret = append_dev_id = sony_check_add(sc); if (ret < 0) goto err_stop; |
131a8a9a5 HID: sony: Preven... |
2416 |
ret = sony_allocate_output_report(sc); |
8025087ac HID: sony: Initia... |
2417 |
if (ret < 0) { |
131a8a9a5 HID: sony: Preven... |
2418 2419 |
hid_err(hdev, "failed to allocate the output report buffer "); |
8025087ac HID: sony: Initia... |
2420 2421 |
goto err_stop; } |
510c8b7c1 HID: sony: Expose... |
2422 |
if (sc->quirks & NAVIGATION_CONTROLLER_USB) { |
e534a9352 HID: sony: do not... |
2423 2424 2425 2426 2427 2428 2429 2430 2431 |
/* * 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! |
2a2429327 HID: sony: Defer ... |
2432 2433 2434 2435 2436 2437 |
* * 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. |
e534a9352 HID: sony: do not... |
2438 2439 2440 |
*/ hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID; |
2a2429327 HID: sony: Defer ... |
2441 |
sc->defer_initialization = 1; |
80ecc48c0 HID: sony: Print ... |
2442 |
|
816651a7d HID: sony: Apply ... |
2443 |
ret = sixaxis_set_operational_usb(hdev); |
80ecc48c0 HID: sony: Print ... |
2444 2445 2446 2447 2448 |
if (ret < 0) { hid_err(hdev, "Failed to set controller into operational mode "); goto err_stop; } |
d8aaccda7 HID: sony: Refact... |
2449 |
sony_init_output_report(sc, sixaxis_send_output_report); |
510c8b7c1 HID: sony: Expose... |
2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 |
} else if (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 "); goto err_stop; } |
d8aaccda7 HID: sony: Refact... |
2463 |
sony_init_output_report(sc, sixaxis_send_output_report); |
510c8b7c1 HID: sony: Expose... |
2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 |
} else if (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 "); goto err_stop; } ret = sony_register_sensors(sc); if (ret) { hid_err(sc->hdev, "Unable to initialize motion sensors: %d ", ret); goto err_stop; } sony_init_output_report(sc, sixaxis_send_output_report); } else if (sc->quirks & SIXAXIS_CONTROLLER_BT) { |
2078b9bb2 HID: sony: Set th... |
2492 2493 2494 2495 2496 |
/* * The Sixaxis wants output reports sent on the ctrl endpoint * when connected via Bluetooth. */ hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; |
80ecc48c0 HID: sony: Print ... |
2497 |
|
816651a7d HID: sony: Apply ... |
2498 |
ret = sixaxis_set_operational_bt(hdev); |
80ecc48c0 HID: sony: Print ... |
2499 2500 2501 2502 2503 |
if (ret < 0) { hid_err(hdev, "Failed to set controller into operational mode "); goto err_stop; } |
510c8b7c1 HID: sony: Expose... |
2504 2505 2506 2507 2508 2509 2510 |
ret = sony_register_sensors(sc); if (ret) { hid_err(sc->hdev, "Unable to initialize motion sensors: %d ", ret); goto err_stop; } |
d8aaccda7 HID: sony: Refact... |
2511 |
sony_init_output_report(sc, sixaxis_send_output_report); |
fee4e2d52 HID: sony: Enable... |
2512 |
} else if (sc->quirks & DUALSHOCK4_CONTROLLER) { |
55a07d62d HID: sony: Calibr... |
2513 2514 2515 2516 2517 |
ret = dualshock4_get_calibration_data(sc); if (ret < 0) { hid_err(hdev, "Failed to get calibration data from Dualshock 4 "); goto err_stop; |
68330d83c HID: sony: Add co... |
2518 |
} |
c4e1ddf26 HID: sony: Cache ... |
2519 |
|
e1bc84d00 HID: sony: Fix ra... |
2520 2521 2522 2523 |
/* * The Dualshock 4 touchpad supports 2 touches and has a * resolution of 1920x942 (44.86 dots/mm). */ |
ac797b95f HID: sony: Make t... |
2524 |
ret = sony_register_touchpad(sc, 2, 1920, 942); |
e1bc84d00 HID: sony: Fix ra... |
2525 2526 2527 2528 2529 |
if (ret) { hid_err(sc->hdev, "Unable to initialize multi-touch slots: %d ", ret); |
2b6579d4a HID: sony: Fix er... |
2530 |
goto err_stop; |
e1bc84d00 HID: sony: Fix ra... |
2531 |
} |
227c011b2 HID: sony: Report... |
2532 2533 2534 2535 2536 2537 2538 |
ret = sony_register_sensors(sc); if (ret) { hid_err(sc->hdev, "Unable to initialize motion sensors: %d ", ret); goto err_stop; } |
77b499e73 HID: sony: Make D... |
2539 2540 2541 2542 2543 2544 2545 2546 2547 |
if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { sc->ds4_bt_poll_interval = DS4_BT_DEFAULT_POLL_INTERVAL_MS; ret = device_create_file(&sc->hdev->dev, &dev_attr_bt_poll_interval); if (ret) hid_warn(sc->hdev, "can't create sysfs bt_poll_interval attribute err: %d ", ret); } |
f2f47c385 HID: sony: Suppor... |
2548 2549 2550 2551 2552 |
if (sc->quirks & DUALSHOCK4_DONGLE) { INIT_WORK(&sc->hotplug_worker, dualshock4_calibration_work); sc->hotplug_worker_initialized = 1; sc->ds4_dongle_state = DONGLE_DISCONNECTED; } |
d8aaccda7 HID: sony: Refact... |
2553 |
sony_init_output_report(sc, dualshock4_send_output_report); |
c5e0c1c49 HID: sony: Add su... |
2554 |
} else if (sc->quirks & MOTION_CONTROLLER) { |
d8aaccda7 HID: sony: Refact... |
2555 |
sony_init_output_report(sc, motion_send_output_report); |
0bd88dd3d HID: sony: Add fo... |
2556 2557 2558 |
} else { ret = 0; } |
f9ce7c283 HID: Enable Sixax... |
2559 |
|
0a286ef27 HID: sony: Add LE... |
2560 |
if (sc->quirks & SONY_LED_SUPPORT) { |
fa57a8107 HID: sony: Conver... |
2561 |
ret = sony_leds_init(sc); |
0a286ef27 HID: sony: Add LE... |
2562 2563 2564 |
if (ret < 0) goto err_stop; } |
d902f4724 HID: sony: add ba... |
2565 |
if (sc->quirks & SONY_BATTERY_SUPPORT) { |
0f3982308 HID: sony: Relax ... |
2566 |
ret = sony_battery_probe(sc, append_dev_id); |
d902f4724 HID: sony: add ba... |
2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 |
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 "); goto err_stop; } } |
c8de9dbb3 HID: sony: Fix wo... |
2578 |
if (sc->quirks & SONY_FF_SUPPORT) { |
fa57a8107 HID: sony: Conver... |
2579 |
ret = sony_init_ff(sc); |
c8de9dbb3 HID: sony: Fix wo... |
2580 2581 |
if (ret < 0) goto err_close; |
5f5750d2e HID: sony: Fix wo... |
2582 |
} |
a08c22c0d HID: sony: Add fo... |
2583 |
|
bd28ce008 HID: move sony qu... |
2584 |
return 0; |
d902f4724 HID: sony: add ba... |
2585 2586 |
err_close: hid_hw_close(hdev); |
bd28ce008 HID: move sony qu... |
2587 |
err_stop: |
77b499e73 HID: sony: Make D... |
2588 2589 2590 2591 2592 2593 |
/* Piggy back on the default ds4_bt_ poll_interval to determine * if we need to remove the file as we don't know for sure if we * executed that logic. */ if (sc->ds4_bt_poll_interval) device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval); |
0a286ef27 HID: sony: Add LE... |
2594 |
if (sc->quirks & SONY_LED_SUPPORT) |
fa57a8107 HID: sony: Conver... |
2595 |
sony_leds_remove(sc); |
d902f4724 HID: sony: add ba... |
2596 2597 |
if (sc->quirks & SONY_BATTERY_SUPPORT) sony_battery_remove(sc); |
a687c5765 HID: sony: Fix in... |
2598 2599 |
if (sc->touchpad) sony_unregister_touchpad(sc); |
a676bdc42 HID: sony: Make s... |
2600 2601 |
if (sc->sensor_dev) sony_unregister_sensors(sc); |
462620474 HID: sony: Use in... |
2602 |
sony_cancel_work_sync(sc); |
9b2b5c9a7 HID: sony: Use ke... |
2603 |
kfree(sc->output_report_dmabuf); |
d2d782fcc HID: sony: Preven... |
2604 |
sony_remove_dev_list(sc); |
8025087ac HID: sony: Initia... |
2605 |
sony_release_device_id(sc); |
bd28ce008 HID: move sony qu... |
2606 |
hid_hw_stop(hdev); |
bd28ce008 HID: move sony qu... |
2607 2608 |
return ret; } |
e1bc84d00 HID: sony: Fix ra... |
2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 |
static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) { int ret; unsigned long quirks = id->driver_data; struct sony_sc *sc; unsigned int connect_mask = HID_CONNECT_DEFAULT; if (!strcmp(hdev->name, "FutureMax Dance Mat")) quirks |= FUTUREMAX_DANCE_MAT; sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL); if (sc == NULL) { hid_err(hdev, "can't alloc sony descriptor "); return -ENOMEM; } spin_lock_init(&sc->lock); sc->quirks = quirks; hid_set_drvdata(hdev, sc); sc->hdev = hdev; ret = hid_parse(hdev); if (ret) { hid_err(hdev, "parse failed "); return ret; } if (sc->quirks & VAIO_RDESC_CONSTANT) connect_mask |= HID_CONNECT_HIDDEV_FORCE; else if (sc->quirks & SIXAXIS_CONTROLLER) connect_mask |= HID_CONNECT_HIDDEV_FORCE; |
e19a267b9 HID: sony: DS3 co... |
2643 |
/* Patch the hw version on DS3/4 compatible devices, so applications can |
9131f8cc2 HID: sony: Comply... |
2644 2645 2646 2647 2648 |
* 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. */ |
e19a267b9 HID: sony: DS3 co... |
2649 |
if (sc->quirks & (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER)) |
9131f8cc2 HID: sony: Comply... |
2650 |
hdev->version |= 0x8000; |
e1bc84d00 HID: sony: Fix ra... |
2651 2652 2653 2654 2655 2656 |
ret = hid_hw_start(hdev, connect_mask); if (ret) { hid_err(hdev, "hw start failed "); return ret; } |
4f967f6d7 HID: sony: Fix me... |
2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 |
/* 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 "); return -ENODEV; } |
e1bc84d00 HID: sony: Fix ra... |
2670 2671 |
return ret; } |
cc6e0bbb4 HID: Add support ... |
2672 2673 |
static void sony_remove(struct hid_device *hdev) { |
f04d51404 HID: driver for P... |
2674 |
struct sony_sc *sc = hid_get_drvdata(hdev); |
ac797b95f HID: sony: Make t... |
2675 |
hid_hw_close(hdev); |
0a286ef27 HID: sony: Add LE... |
2676 |
if (sc->quirks & SONY_LED_SUPPORT) |
fa57a8107 HID: sony: Conver... |
2677 |
sony_leds_remove(sc); |
f04d51404 HID: driver for P... |
2678 |
|
ac797b95f HID: sony: Make t... |
2679 |
if (sc->quirks & SONY_BATTERY_SUPPORT) |
d902f4724 HID: sony: add ba... |
2680 |
sony_battery_remove(sc); |
ac797b95f HID: sony: Make t... |
2681 2682 2683 |
if (sc->touchpad) sony_unregister_touchpad(sc); |
d902f4724 HID: sony: add ba... |
2684 |
|
227c011b2 HID: sony: Report... |
2685 2686 |
if (sc->sensor_dev) sony_unregister_sensors(sc); |
77b499e73 HID: sony: Make D... |
2687 2688 |
if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval); |
462620474 HID: sony: Use in... |
2689 |
sony_cancel_work_sync(sc); |
9f323b681 HID: sony: Send F... |
2690 |
|
9b2b5c9a7 HID: sony: Use ke... |
2691 |
kfree(sc->output_report_dmabuf); |
d2d782fcc HID: sony: Preven... |
2692 |
sony_remove_dev_list(sc); |
9f323b681 HID: sony: Send F... |
2693 |
|
8025087ac HID: sony: Initia... |
2694 |
sony_release_device_id(sc); |
cc6e0bbb4 HID: Add support ... |
2695 |
hid_hw_stop(hdev); |
cc6e0bbb4 HID: Add support ... |
2696 |
} |
decd946c9 HID: sony: Save a... |
2697 2698 2699 2700 |
#ifdef CONFIG_PM static int sony_suspend(struct hid_device *hdev, pm_message_t message) { |
decd946c9 HID: sony: Save a... |
2701 |
#ifdef CONFIG_SONY_FF |
decd946c9 HID: sony: Save a... |
2702 |
|
765a1077c HID: sony: Use LE... |
2703 2704 2705 |
/* On suspend stop any running force-feedback events */ if (SONY_FF_SUPPORT) { struct sony_sc *sc = hid_get_drvdata(hdev); |
decd946c9 HID: sony: Save a... |
2706 |
|
765a1077c HID: sony: Use LE... |
2707 |
sc->left = sc->right = 0; |
decd946c9 HID: sony: Save a... |
2708 2709 |
sony_send_output_report(sc); } |
765a1077c HID: sony: Use LE... |
2710 |
#endif |
decd946c9 HID: sony: Save a... |
2711 2712 2713 2714 2715 |
return 0; } static int sony_resume(struct hid_device *hdev) { |
765a1077c HID: sony: Use LE... |
2716 |
struct sony_sc *sc = hid_get_drvdata(hdev); |
decd946c9 HID: sony: Save a... |
2717 |
|
765a1077c HID: sony: Use LE... |
2718 2719 2720 2721 2722 2723 2724 2725 |
/* * 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; |
decd946c9 HID: sony: Save a... |
2726 2727 2728 2729 2730 2731 |
} return 0; } #endif |
bd28ce008 HID: move sony qu... |
2732 |
static const struct hid_device_id sony_devices[] = { |
816651a7d HID: sony: Apply ... |
2733 2734 |
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), .driver_data = SIXAXIS_CONTROLLER_USB }, |
35dca5b4a HID: add support ... |
2735 |
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER), |
4545ee0a7 HID: hid-sony: Na... |
2736 |
.driver_data = NAVIGATION_CONTROLLER_USB }, |
6eabaaa09 HID: hid-sony: Ad... |
2737 |
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER), |
4545ee0a7 HID: hid-sony: Na... |
2738 |
.driver_data = NAVIGATION_CONTROLLER_BT }, |
c5e0c1c49 HID: sony: Add su... |
2739 |
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER), |
b3bca326f HID: sony: Add qu... |
2740 |
.driver_data = MOTION_CONTROLLER_USB }, |
a4afa8544 HID: sony: Suppor... |
2741 |
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER), |
b3bca326f HID: sony: Add qu... |
2742 |
.driver_data = MOTION_CONTROLLER_BT }, |
816651a7d HID: sony: Apply ... |
2743 2744 |
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), .driver_data = SIXAXIS_CONTROLLER_BT }, |
cc6e0bbb4 HID: Add support ... |
2745 2746 |
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE), .driver_data = VAIO_RDESC_CONSTANT }, |
a46491841 HID: add support ... |
2747 2748 |
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE), .driver_data = VAIO_RDESC_CONSTANT }, |
ef916ef5e HID: sony: fix so... |
2749 2750 2751 2752 |
/* * Wired Buzz Controller. Reported as Sony Hub from its USB ID and as * Logitech joystick from the device descriptor. */ |
f04d51404 HID: driver for P... |
2753 2754 2755 2756 |
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER), .driver_data = BUZZ_CONTROLLER }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER), .driver_data = BUZZ_CONTROLLER }, |
078328da5 HID: fold ps3remo... |
2757 2758 2759 2760 2761 2762 |
/* PS3 BD Remote Control */ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE), .driver_data = PS3REMOTE }, /* Logitech Harmony Adapter for PS3 */ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3), .driver_data = PS3REMOTE }, |
68a49e51a HID: sony: Add su... |
2763 2764 2765 |
/* SMK-Link PS3 BD Remote Control */ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE), .driver_data = PS3REMOTE }, |
0bd88dd3d HID: sony: Add fo... |
2766 2767 |
/* Sony Dualshock 4 controllers for PS4 */ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), |
8ab1676b6 HID: sony: Use se... |
2768 |
.driver_data = DUALSHOCK4_CONTROLLER_USB }, |
0bd88dd3d HID: sony: Add fo... |
2769 |
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), |
8ab1676b6 HID: sony: Use se... |
2770 |
.driver_data = DUALSHOCK4_CONTROLLER_BT }, |
cf1015d65 HID: sony: Update... |
2771 2772 2773 2774 |
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2), .driver_data = DUALSHOCK4_CONTROLLER_USB }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2), .driver_data = DUALSHOCK4_CONTROLLER_BT }, |
de66a1a04 HID: sony: Suppor... |
2775 |
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE), |
35f436c31 HID: sony: Treat ... |
2776 |
.driver_data = DUALSHOCK4_DONGLE }, |
74500cc85 HID: sony: Add ny... |
2777 2778 2779 |
/* Nyko Core Controller for PS3 */ { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER), .driver_data = SIXAXIS_CONTROLLER_USB | SINO_LITE_CONTROLLER }, |
bd28ce008 HID: move sony qu... |
2780 2781 2782 2783 2784 |
{ } }; MODULE_DEVICE_TABLE(hid, sony_devices); static struct hid_driver sony_driver = { |
ce8efc3b5 HID: sony: Set to... |
2785 2786 2787 2788 2789 2790 2791 |
.name = "sony", .id_table = sony_devices, .input_mapping = sony_mapping, .input_configured = sony_input_configured, .probe = sony_probe, .remove = sony_remove, .report_fixup = sony_report_fixup, |
decd946c9 HID: sony: Save a... |
2792 2793 2794 2795 2796 2797 2798 |
.raw_event = sony_raw_event, #ifdef CONFIG_PM .suspend = sony_suspend, .resume = sony_resume, .reset_resume = sony_resume, #endif |
bd28ce008 HID: move sony qu... |
2799 |
}; |
8025087ac HID: sony: Initia... |
2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 |
static int __init sony_init(void) { dbg_hid("Sony:%s ", __func__); return hid_register_driver(&sony_driver); } static void __exit sony_exit(void) { dbg_hid("Sony:%s ", __func__); |
8025087ac HID: sony: Initia... |
2813 |
hid_unregister_driver(&sony_driver); |
6c40065fc HID: sony: Fix a ... |
2814 |
ida_destroy(&sony_device_id_allocator); |
8025087ac HID: sony: Initia... |
2815 2816 2817 |
} module_init(sony_init); module_exit(sony_exit); |
bd28ce008 HID: move sony qu... |
2818 |
|
bd28ce008 HID: move sony qu... |
2819 |
MODULE_LICENSE("GPL"); |