linux/drivers/input/joystick/psxpad-spi.c
<<
>>
Prefs
   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 */
  43static 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 */
  49static 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 */
  53static 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 */
  57static const u8 PSX_CMD_ENABLE_MOTOR[]  = {
  58        0x80, 0xB2, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF
  59};
  60
  61struct 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
  73static 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
  94static 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
 133static 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
 140static 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
 157static 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
 176static void psxpad_control_motor(struct psxpad *pad,
 177                                 bool motor1enable, bool motor2enable)
 178{
 179}
 180
 181static void psxpad_set_motor_level(struct psxpad *pad,
 182                                   u8 motor1level, u8 motor2level)
 183{
 184}
 185
 186static inline int psxpad_spi_init_ff(struct psxpad *pad)
 187{
 188        return 0;
 189}
 190#endif  /* CONFIG_JOYSTICK_PSXPAD_SPI_FF */
 191
 192static 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
 199static 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
 206static 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
 284static 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
 370static 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
 380static SIMPLE_DEV_PM_OPS(psxpad_spi_pm, psxpad_spi_suspend, NULL);
 381
 382static const struct spi_device_id psxpad_spi_id[] = {
 383        { "psxpad-spi", 0 },
 384        { }
 385};
 386MODULE_DEVICE_TABLE(spi, psxpad_spi_id);
 387
 388static 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
 397module_spi_driver(psxpad_spi_driver);
 398
 399MODULE_AUTHOR("Tomohiro Yoshidomi <sylph23k@gmail.com>");
 400MODULE_DESCRIPTION("PlayStation 1/2 joypads via SPI interface Driver");
 401MODULE_LICENSE("GPL");
 402