1 /* 2 * PlayStation 1/2 joypads via SPI interface Driver 3 * 4 * Copyright (C) 2017 Tomohiro Yoshidomi <sylph23k@gmail.com> 5 * Licensed under the GPL-2 or later. 6 * 7 * PlayStation 1/2 joypad's plug (not socket) 8 * 123 456 789 9 * (...|...|...) 10 * 11 * 1: DAT -> MISO (pullup with 1k owm to 3.3V) 12 * 2: CMD -> MOSI 13 * 3: 9V (for motor, if not use N.C.) 14 * 4: GND 15 * 5: 3.3V 16 * 6: Attention -> CS(SS) 17 * 7: SCK -> SCK 18 * 8: N.C. 19 * 9: ACK -> N.C. 20 */ 21 22 #include <linux/kernel.h> 23 #include <linux/device.h> 24 #include <linux/input.h> 25 #include <linux/input-polldev.h> 26 #include <linux/module.h> 27 #include <linux/spi/spi.h> 28 #include <linux/types.h> 29 #include <linux/pm.h> 30 #include <linux/pm_runtime.h> 31 32 #define REVERSE_BIT(x) ((((x) & 0x80) >> 7) | (((x) & 0x40) >> 5) | \ 33 (((x) & 0x20) >> 3) | (((x) & 0x10) >> 1) | (((x) & 0x08) << 1) | \ 34 (((x) & 0x04) << 3) | (((x) & 0x02) << 5) | (((x) & 0x01) << 7)) 35 36 /* PlayStation 1/2 joypad command and response are LSBFIRST. */ 37 38 /* 39 * 0x01, 0x42, 0x00, 0x00, 0x00, 40 * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 41 * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 42 */ 43 static const u8 PSX_CMD_POLL[] = { 44 0x80, 0x42, 0x00, 0x00, 0x00, 45 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 46 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 47 }; 48 /* 0x01, 0x43, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 */ 49 static const u8 PSX_CMD_ENTER_CFG[] = { 50 0x80, 0xC2, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 51 }; 52 /* 0x01, 0x43, 0x00, 0x00, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A */ 53 static const u8 PSX_CMD_EXIT_CFG[] = { 54 0x80, 0xC2, 0x00, 0x00, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A 55 }; 56 /* 0x01, 0x4D, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF */ 57 static const u8 PSX_CMD_ENABLE_MOTOR[] = { 58 0x80, 0xB2, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF 59 }; 60 61 struct psxpad { 62 struct spi_device *spi; 63 struct input_polled_dev *pdev; 64 char phys[0x20]; 65 bool motor1enable; 66 bool motor2enable; 67 u8 motor1level; 68 u8 motor2level; 69 u8 sendbuf[0x20] ____cacheline_aligned; 70 u8 response[sizeof(PSX_CMD_POLL)] ____cacheline_aligned; 71 }; 72 73 static int psxpad_command(struct psxpad *pad, const u8 sendcmdlen) 74 { 75 struct spi_transfer xfers = { 76 .tx_buf = pad->sendbuf, 77 .rx_buf = pad->response, 78 .len = sendcmdlen, 79 }; 80 int err; 81 82 err = spi_sync_transfer(pad->spi, &xfers, 1); 83 if (err) { 84 dev_err(&pad->spi->dev, 85 "%s: failed to SPI xfers mode: %d\n", 86 __func__, err); 87 return err; 88 } 89 90 return 0; 91 } 92 93 #ifdef CONFIG_JOYSTICK_PSXPAD_SPI_FF 94 static void psxpad_control_motor(struct psxpad *pad, 95 bool motor1enable, bool motor2enable) 96 { 97 int err; 98 99 pad->motor1enable = motor1enable; 100 pad->motor2enable = motor2enable; 101 102 memcpy(pad->sendbuf, PSX_CMD_ENTER_CFG, sizeof(PSX_CMD_ENTER_CFG)); 103 err = psxpad_command(pad, sizeof(PSX_CMD_ENTER_CFG)); 104 if (err) { 105 dev_err(&pad->spi->dev, 106 "%s: failed to enter config mode: %d\n", 107 __func__, err); 108 return; 109 } 110 111 memcpy(pad->sendbuf, PSX_CMD_ENABLE_MOTOR, 112 sizeof(PSX_CMD_ENABLE_MOTOR)); 113 pad->sendbuf[3] = pad->motor1enable ? 0x00 : 0xFF; 114 pad->sendbuf[4] = pad->motor2enable ? 0x80 : 0xFF; 115 err = psxpad_command(pad, sizeof(PSX_CMD_ENABLE_MOTOR)); 116 if (err) { 117 dev_err(&pad->spi->dev, 118 "%s: failed to enable motor mode: %d\n", 119 __func__, err); 120 return; 121 } 122 123 memcpy(pad->sendbuf, PSX_CMD_EXIT_CFG, sizeof(PSX_CMD_EXIT_CFG)); 124 err = psxpad_command(pad, sizeof(PSX_CMD_EXIT_CFG)); 125 if (err) { 126 dev_err(&pad->spi->dev, 127 "%s: failed to exit config mode: %d\n", 128 __func__, err); 129 return; 130 } 131 } 132 133 static void psxpad_set_motor_level(struct psxpad *pad, 134 u8 motor1level, u8 motor2level) 135 { 136 pad->motor1level = motor1level ? 0xFF : 0x00; 137 pad->motor2level = REVERSE_BIT(motor2level); 138 } 139 140 static int psxpad_spi_play_effect(struct input_dev *idev, 141 void *data, struct ff_effect *effect) 142 { 143 struct input_polled_dev *pdev = input_get_drvdata(idev); 144 struct psxpad *pad = pdev->private; 145 146 switch (effect->type) { 147 case FF_RUMBLE: 148 psxpad_set_motor_level(pad, 149 (effect->u.rumble.weak_magnitude >> 8) & 0xFFU, 150 (effect->u.rumble.strong_magnitude >> 8) & 0xFFU); 151 break; 152 } 153 154 return 0; 155 } 156 157 static int psxpad_spi_init_ff(struct psxpad *pad) 158 { 159 int err; 160 161 input_set_capability(pad->pdev->input, EV_FF, FF_RUMBLE); 162 163 err = input_ff_create_memless(pad->pdev->input, NULL, 164 psxpad_spi_play_effect); 165 if (err) { 166 dev_err(&pad->spi->dev, 167 "input_ff_create_memless() failed: %d\n", err); 168 return err; 169 } 170 171 return 0; 172 } 173 174 #else /* CONFIG_JOYSTICK_PSXPAD_SPI_FF */ 175 176 static void psxpad_control_motor(struct psxpad *pad, 177 bool motor1enable, bool motor2enable) 178 { 179 } 180 181 static void psxpad_set_motor_level(struct psxpad *pad, 182 u8 motor1level, u8 motor2level) 183 { 184 } 185 186 static inline int psxpad_spi_init_ff(struct psxpad *pad) 187 { 188 return 0; 189 } 190 #endif /* CONFIG_JOYSTICK_PSXPAD_SPI_FF */ 191 192 static void psxpad_spi_poll_open(struct input_polled_dev *pdev) 193 { 194 struct psxpad *pad = pdev->private; 195 196 pm_runtime_get_sync(&pad->spi->dev); 197 } 198 199 static void psxpad_spi_poll_close(struct input_polled_dev *pdev) 200 { 201 struct psxpad *pad = pdev->private; 202 203 pm_runtime_put_sync(&pad->spi->dev); 204 } 205 206 static void psxpad_spi_poll(struct input_polled_dev *pdev) 207 { 208 struct psxpad *pad = pdev->private; 209 struct input_dev *input = pdev->input; 210 u8 b_rsp3, b_rsp4; 211 int err; 212 213 psxpad_control_motor(pad, true, true); 214 215 memcpy(pad->sendbuf, PSX_CMD_POLL, sizeof(PSX_CMD_POLL)); 216 pad->sendbuf[3] = pad->motor1enable ? pad->motor1level : 0x00; 217 pad->sendbuf[4] = pad->motor2enable ? pad->motor2level : 0x00; 218 err = psxpad_command(pad, sizeof(PSX_CMD_POLL)); 219 if (err) { 220 dev_err(&pad->spi->dev, 221 "%s: poll command failed mode: %d\n", __func__, err); 222 return; 223 } 224 225 switch (pad->response[1]) { 226 case 0xCE: /* 0x73 : analog 1 */ 227 /* button data is inverted */ 228 b_rsp3 = ~pad->response[3]; 229 b_rsp4 = ~pad->response[4]; 230 231 input_report_abs(input, ABS_X, REVERSE_BIT(pad->response[7])); 232 input_report_abs(input, ABS_Y, REVERSE_BIT(pad->response[8])); 233 input_report_abs(input, ABS_RX, REVERSE_BIT(pad->response[5])); 234 input_report_abs(input, ABS_RY, REVERSE_BIT(pad->response[6])); 235 input_report_key(input, BTN_DPAD_UP, b_rsp3 & BIT(3)); 236 input_report_key(input, BTN_DPAD_DOWN, b_rsp3 & BIT(1)); 237 input_report_key(input, BTN_DPAD_LEFT, b_rsp3 & BIT(0)); 238 input_report_key(input, BTN_DPAD_RIGHT, b_rsp3 & BIT(2)); 239 input_report_key(input, BTN_X, b_rsp4 & BIT(3)); 240 input_report_key(input, BTN_A, b_rsp4 & BIT(2)); 241 input_report_key(input, BTN_B, b_rsp4 & BIT(1)); 242 input_report_key(input, BTN_Y, b_rsp4 & BIT(0)); 243 input_report_key(input, BTN_TL, b_rsp4 & BIT(5)); 244 input_report_key(input, BTN_TR, b_rsp4 & BIT(4)); 245 input_report_key(input, BTN_TL2, b_rsp4 & BIT(7)); 246 input_report_key(input, BTN_TR2, b_rsp4 & BIT(6)); 247 input_report_key(input, BTN_THUMBL, b_rsp3 & BIT(6)); 248 input_report_key(input, BTN_THUMBR, b_rsp3 & BIT(5)); 249 input_report_key(input, BTN_SELECT, b_rsp3 & BIT(7)); 250 input_report_key(input, BTN_START, b_rsp3 & BIT(4)); 251 break; 252 253 case 0x82: /* 0x41 : digital */ 254 /* button data is inverted */ 255 b_rsp3 = ~pad->response[3]; 256 b_rsp4 = ~pad->response[4]; 257 258 input_report_abs(input, ABS_X, 0x80); 259 input_report_abs(input, ABS_Y, 0x80); 260 input_report_abs(input, ABS_RX, 0x80); 261 input_report_abs(input, ABS_RY, 0x80); 262 input_report_key(input, BTN_DPAD_UP, b_rsp3 & BIT(3)); 263 input_report_key(input, BTN_DPAD_DOWN, b_rsp3 & BIT(1)); 264 input_report_key(input, BTN_DPAD_LEFT, b_rsp3 & BIT(0)); 265 input_report_key(input, BTN_DPAD_RIGHT, b_rsp3 & BIT(2)); 266 input_report_key(input, BTN_X, b_rsp4 & BIT(3)); 267 input_report_key(input, BTN_A, b_rsp4 & BIT(2)); 268 input_report_key(input, BTN_B, b_rsp4 & BIT(1)); 269 input_report_key(input, BTN_Y, b_rsp4 & BIT(0)); 270 input_report_key(input, BTN_TL, b_rsp4 & BIT(5)); 271 input_report_key(input, BTN_TR, b_rsp4 & BIT(4)); 272 input_report_key(input, BTN_TL2, b_rsp4 & BIT(7)); 273 input_report_key(input, BTN_TR2, b_rsp4 & BIT(6)); 274 input_report_key(input, BTN_THUMBL, false); 275 input_report_key(input, BTN_THUMBR, false); 276 input_report_key(input, BTN_SELECT, b_rsp3 & BIT(7)); 277 input_report_key(input, BTN_START, b_rsp3 & BIT(4)); 278 break; 279 } 280 281 input_sync(input); 282 } 283 284 static int psxpad_spi_probe(struct spi_device *spi) 285 { 286 struct psxpad *pad; 287 struct input_polled_dev *pdev; 288 struct input_dev *idev; 289 int err; 290 291 pad = devm_kzalloc(&spi->dev, sizeof(struct psxpad), GFP_KERNEL); 292 if (!pad) 293 return -ENOMEM; 294 295 pdev = input_allocate_polled_device(); 296 if (!pdev) { 297 dev_err(&spi->dev, "failed to allocate input device\n"); 298 return -ENOMEM; 299 } 300 301 /* input poll device settings */ 302 pad->pdev = pdev; 303 pad->spi = spi; 304 305 pdev->private = pad; 306 pdev->open = psxpad_spi_poll_open; 307 pdev->close = psxpad_spi_poll_close; 308 pdev->poll = psxpad_spi_poll; 309 /* poll interval is about 60fps */ 310 pdev->poll_interval = 16; 311 pdev->poll_interval_min = 8; 312 pdev->poll_interval_max = 32; 313 314 /* input device settings */ 315 idev = pdev->input; 316 idev->name = "PlayStation 1/2 joypad"; 317 snprintf(pad->phys, sizeof(pad->phys), "%s/input", dev_name(&spi->dev)); 318 idev->id.bustype = BUS_SPI; 319 320 /* key/value map settings */ 321 input_set_abs_params(idev, ABS_X, 0, 255, 0, 0); 322 input_set_abs_params(idev, ABS_Y, 0, 255, 0, 0); 323 input_set_abs_params(idev, ABS_RX, 0, 255, 0, 0); 324 input_set_abs_params(idev, ABS_RY, 0, 255, 0, 0); 325 input_set_capability(idev, EV_KEY, BTN_DPAD_UP); 326 input_set_capability(idev, EV_KEY, BTN_DPAD_DOWN); 327 input_set_capability(idev, EV_KEY, BTN_DPAD_LEFT); 328 input_set_capability(idev, EV_KEY, BTN_DPAD_RIGHT); 329 input_set_capability(idev, EV_KEY, BTN_A); 330 input_set_capability(idev, EV_KEY, BTN_B); 331 input_set_capability(idev, EV_KEY, BTN_X); 332 input_set_capability(idev, EV_KEY, BTN_Y); 333 input_set_capability(idev, EV_KEY, BTN_TL); 334 input_set_capability(idev, EV_KEY, BTN_TR); 335 input_set_capability(idev, EV_KEY, BTN_TL2); 336 input_set_capability(idev, EV_KEY, BTN_TR2); 337 input_set_capability(idev, EV_KEY, BTN_THUMBL); 338 input_set_capability(idev, EV_KEY, BTN_THUMBR); 339 input_set_capability(idev, EV_KEY, BTN_SELECT); 340 input_set_capability(idev, EV_KEY, BTN_START); 341 342 err = psxpad_spi_init_ff(pad); 343 if (err) 344 return err; 345 346 /* SPI settings */ 347 spi->mode = SPI_MODE_3; 348 spi->bits_per_word = 8; 349 /* (PlayStation 1/2 joypad might be possible works 250kHz/500kHz) */ 350 spi->master->min_speed_hz = 125000; 351 spi->master->max_speed_hz = 125000; 352 spi_setup(spi); 353 354 /* pad settings */ 355 psxpad_set_motor_level(pad, 0, 0); 356 357 /* register input poll device */ 358 err = input_register_polled_device(pdev); 359 if (err) { 360 dev_err(&spi->dev, 361 "failed to register input poll device: %d\n", err); 362 return err; 363 } 364 365 pm_runtime_enable(&spi->dev); 366 367 return 0; 368 } 369 370 static int __maybe_unused psxpad_spi_suspend(struct device *dev) 371 { 372 struct spi_device *spi = to_spi_device(dev); 373 struct psxpad *pad = spi_get_drvdata(spi); 374 375 psxpad_set_motor_level(pad, 0, 0); 376 377 return 0; 378 } 379 380 static SIMPLE_DEV_PM_OPS(psxpad_spi_pm, psxpad_spi_suspend, NULL); 381 382 static const struct spi_device_id psxpad_spi_id[] = { 383 { "psxpad-spi", 0 }, 384 { } 385 }; 386 MODULE_DEVICE_TABLE(spi, psxpad_spi_id); 387 388 static struct spi_driver psxpad_spi_driver = { 389 .driver = { 390 .name = "psxpad-spi", 391 .pm = &psxpad_spi_pm, 392 }, 393 .id_table = psxpad_spi_id, 394 .probe = psxpad_spi_probe, 395 }; 396 397 module_spi_driver(psxpad_spi_driver); 398 399 MODULE_AUTHOR("Tomohiro Yoshidomi <sylph23k@gmail.com>"); 400 MODULE_DESCRIPTION("PlayStation 1/2 joypads via SPI interface Driver"); 401 MODULE_LICENSE("GPL"); 402