Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * PlayStation 1/2 joypads via SPI interface Driver
0004  *
0005  * Copyright (C) 2017 Tomohiro Yoshidomi <sylph23k@gmail.com>
0006  *
0007  * PlayStation 1/2 joypad's plug (not socket)
0008  *  123 456 789
0009  * (...|...|...)
0010  *
0011  * 1: DAT -> MISO (pullup with 1k owm to 3.3V)
0012  * 2: CMD -> MOSI
0013  * 3: 9V (for motor, if not use N.C.)
0014  * 4: GND
0015  * 5: 3.3V
0016  * 6: Attention -> CS(SS)
0017  * 7: SCK -> SCK
0018  * 8: N.C.
0019  * 9: ACK -> N.C.
0020  */
0021 
0022 #include <linux/kernel.h>
0023 #include <linux/device.h>
0024 #include <linux/input.h>
0025 #include <linux/module.h>
0026 #include <linux/spi/spi.h>
0027 #include <linux/types.h>
0028 #include <linux/pm.h>
0029 #include <linux/pm_runtime.h>
0030 
0031 #define REVERSE_BIT(x) ((((x) & 0x80) >> 7) | (((x) & 0x40) >> 5) | \
0032     (((x) & 0x20) >> 3) | (((x) & 0x10) >> 1) | (((x) & 0x08) << 1) | \
0033     (((x) & 0x04) << 3) | (((x) & 0x02) << 5) | (((x) & 0x01) << 7))
0034 
0035 /* PlayStation 1/2 joypad command and response are LSBFIRST. */
0036 
0037 /*
0038  *  0x01, 0x42, 0x00, 0x00, 0x00,
0039  *  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0040  *  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0041  */
0042 static const u8 PSX_CMD_POLL[] = {
0043     0x80, 0x42, 0x00, 0x00, 0x00,
0044     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0045     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0046 };
0047 /*  0x01, 0x43, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 */
0048 static const u8 PSX_CMD_ENTER_CFG[] = {
0049     0x80, 0xC2, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00
0050 };
0051 /*  0x01, 0x43, 0x00, 0x00, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A */
0052 static const u8 PSX_CMD_EXIT_CFG[] = {
0053     0x80, 0xC2, 0x00, 0x00, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A
0054 };
0055 /*  0x01, 0x4D, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF */
0056 static const u8 PSX_CMD_ENABLE_MOTOR[]  = {
0057     0x80, 0xB2, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF
0058 };
0059 
0060 struct psxpad {
0061     struct spi_device *spi;
0062     struct input_dev *idev;
0063     char phys[0x20];
0064     bool motor1enable;
0065     bool motor2enable;
0066     u8 motor1level;
0067     u8 motor2level;
0068     u8 sendbuf[0x20] ____cacheline_aligned;
0069     u8 response[sizeof(PSX_CMD_POLL)] ____cacheline_aligned;
0070 };
0071 
0072 static int psxpad_command(struct psxpad *pad, const u8 sendcmdlen)
0073 {
0074     struct spi_transfer xfers = {
0075         .tx_buf     = pad->sendbuf,
0076         .rx_buf     = pad->response,
0077         .len        = sendcmdlen,
0078     };
0079     int err;
0080 
0081     err = spi_sync_transfer(pad->spi, &xfers, 1);
0082     if (err) {
0083         dev_err(&pad->spi->dev,
0084             "%s: failed to SPI xfers mode: %d\n",
0085             __func__, err);
0086         return err;
0087     }
0088 
0089     return 0;
0090 }
0091 
0092 #ifdef CONFIG_JOYSTICK_PSXPAD_SPI_FF
0093 static void psxpad_control_motor(struct psxpad *pad,
0094                  bool motor1enable, bool motor2enable)
0095 {
0096     int err;
0097 
0098     pad->motor1enable = motor1enable;
0099     pad->motor2enable = motor2enable;
0100 
0101     memcpy(pad->sendbuf, PSX_CMD_ENTER_CFG, sizeof(PSX_CMD_ENTER_CFG));
0102     err = psxpad_command(pad, sizeof(PSX_CMD_ENTER_CFG));
0103     if (err) {
0104         dev_err(&pad->spi->dev,
0105             "%s: failed to enter config mode: %d\n",
0106             __func__, err);
0107         return;
0108     }
0109 
0110     memcpy(pad->sendbuf, PSX_CMD_ENABLE_MOTOR,
0111            sizeof(PSX_CMD_ENABLE_MOTOR));
0112     pad->sendbuf[3] = pad->motor1enable ? 0x00 : 0xFF;
0113     pad->sendbuf[4] = pad->motor2enable ? 0x80 : 0xFF;
0114     err = psxpad_command(pad, sizeof(PSX_CMD_ENABLE_MOTOR));
0115     if (err) {
0116         dev_err(&pad->spi->dev,
0117             "%s: failed to enable motor mode: %d\n",
0118             __func__, err);
0119         return;
0120     }
0121 
0122     memcpy(pad->sendbuf, PSX_CMD_EXIT_CFG, sizeof(PSX_CMD_EXIT_CFG));
0123     err = psxpad_command(pad, sizeof(PSX_CMD_EXIT_CFG));
0124     if (err) {
0125         dev_err(&pad->spi->dev,
0126             "%s: failed to exit config mode: %d\n",
0127             __func__, err);
0128         return;
0129     }
0130 }
0131 
0132 static void psxpad_set_motor_level(struct psxpad *pad,
0133                    u8 motor1level, u8 motor2level)
0134 {
0135     pad->motor1level = motor1level ? 0xFF : 0x00;
0136     pad->motor2level = REVERSE_BIT(motor2level);
0137 }
0138 
0139 static int psxpad_spi_play_effect(struct input_dev *idev,
0140                   void *data, struct ff_effect *effect)
0141 {
0142     struct psxpad *pad = input_get_drvdata(idev);
0143 
0144     switch (effect->type) {
0145     case FF_RUMBLE:
0146         psxpad_set_motor_level(pad,
0147             (effect->u.rumble.weak_magnitude >> 8) & 0xFFU,
0148             (effect->u.rumble.strong_magnitude >> 8) & 0xFFU);
0149         break;
0150     }
0151 
0152     return 0;
0153 }
0154 
0155 static int psxpad_spi_init_ff(struct psxpad *pad)
0156 {
0157     int err;
0158 
0159     input_set_capability(pad->idev, EV_FF, FF_RUMBLE);
0160 
0161     err = input_ff_create_memless(pad->idev, NULL, psxpad_spi_play_effect);
0162     if (err) {
0163         dev_err(&pad->spi->dev,
0164             "input_ff_create_memless() failed: %d\n", err);
0165         return err;
0166     }
0167 
0168     return 0;
0169 }
0170 
0171 #else   /* CONFIG_JOYSTICK_PSXPAD_SPI_FF */
0172 
0173 static void psxpad_control_motor(struct psxpad *pad,
0174                  bool motor1enable, bool motor2enable)
0175 {
0176 }
0177 
0178 static void psxpad_set_motor_level(struct psxpad *pad,
0179                    u8 motor1level, u8 motor2level)
0180 {
0181 }
0182 
0183 static inline int psxpad_spi_init_ff(struct psxpad *pad)
0184 {
0185     return 0;
0186 }
0187 #endif  /* CONFIG_JOYSTICK_PSXPAD_SPI_FF */
0188 
0189 static int psxpad_spi_poll_open(struct input_dev *input)
0190 {
0191     struct psxpad *pad = input_get_drvdata(input);
0192 
0193     pm_runtime_get_sync(&pad->spi->dev);
0194 
0195     return 0;
0196 }
0197 
0198 static void psxpad_spi_poll_close(struct input_dev *input)
0199 {
0200     struct psxpad *pad = input_get_drvdata(input);
0201 
0202     pm_runtime_put_sync(&pad->spi->dev);
0203 }
0204 
0205 static void psxpad_spi_poll(struct input_dev *input)
0206 {
0207     struct psxpad *pad = input_get_drvdata(input);
0208     u8 b_rsp3, b_rsp4;
0209     int err;
0210 
0211     psxpad_control_motor(pad, true, true);
0212 
0213     memcpy(pad->sendbuf, PSX_CMD_POLL, sizeof(PSX_CMD_POLL));
0214     pad->sendbuf[3] = pad->motor1enable ? pad->motor1level : 0x00;
0215     pad->sendbuf[4] = pad->motor2enable ? pad->motor2level : 0x00;
0216     err = psxpad_command(pad, sizeof(PSX_CMD_POLL));
0217     if (err) {
0218         dev_err(&pad->spi->dev,
0219             "%s: poll command failed mode: %d\n", __func__, err);
0220         return;
0221     }
0222 
0223     switch (pad->response[1]) {
0224     case 0xCE:  /* 0x73 : analog 1 */
0225         /* button data is inverted */
0226         b_rsp3 = ~pad->response[3];
0227         b_rsp4 = ~pad->response[4];
0228 
0229         input_report_abs(input, ABS_X, REVERSE_BIT(pad->response[7]));
0230         input_report_abs(input, ABS_Y, REVERSE_BIT(pad->response[8]));
0231         input_report_abs(input, ABS_RX, REVERSE_BIT(pad->response[5]));
0232         input_report_abs(input, ABS_RY, REVERSE_BIT(pad->response[6]));
0233         input_report_key(input, BTN_DPAD_UP, b_rsp3 & BIT(3));
0234         input_report_key(input, BTN_DPAD_DOWN, b_rsp3 & BIT(1));
0235         input_report_key(input, BTN_DPAD_LEFT, b_rsp3 & BIT(0));
0236         input_report_key(input, BTN_DPAD_RIGHT, b_rsp3 & BIT(2));
0237         input_report_key(input, BTN_X, b_rsp4 & BIT(3));
0238         input_report_key(input, BTN_A, b_rsp4 & BIT(2));
0239         input_report_key(input, BTN_B, b_rsp4 & BIT(1));
0240         input_report_key(input, BTN_Y, b_rsp4 & BIT(0));
0241         input_report_key(input, BTN_TL, b_rsp4 & BIT(5));
0242         input_report_key(input, BTN_TR, b_rsp4 & BIT(4));
0243         input_report_key(input, BTN_TL2, b_rsp4 & BIT(7));
0244         input_report_key(input, BTN_TR2, b_rsp4 & BIT(6));
0245         input_report_key(input, BTN_THUMBL, b_rsp3 & BIT(6));
0246         input_report_key(input, BTN_THUMBR, b_rsp3 & BIT(5));
0247         input_report_key(input, BTN_SELECT, b_rsp3 & BIT(7));
0248         input_report_key(input, BTN_START, b_rsp3 & BIT(4));
0249         break;
0250 
0251     case 0x82:  /* 0x41 : digital */
0252         /* button data is inverted */
0253         b_rsp3 = ~pad->response[3];
0254         b_rsp4 = ~pad->response[4];
0255 
0256         input_report_abs(input, ABS_X, 0x80);
0257         input_report_abs(input, ABS_Y, 0x80);
0258         input_report_abs(input, ABS_RX, 0x80);
0259         input_report_abs(input, ABS_RY, 0x80);
0260         input_report_key(input, BTN_DPAD_UP, b_rsp3 & BIT(3));
0261         input_report_key(input, BTN_DPAD_DOWN, b_rsp3 & BIT(1));
0262         input_report_key(input, BTN_DPAD_LEFT, b_rsp3 & BIT(0));
0263         input_report_key(input, BTN_DPAD_RIGHT, b_rsp3 & BIT(2));
0264         input_report_key(input, BTN_X, b_rsp4 & BIT(3));
0265         input_report_key(input, BTN_A, b_rsp4 & BIT(2));
0266         input_report_key(input, BTN_B, b_rsp4 & BIT(1));
0267         input_report_key(input, BTN_Y, b_rsp4 & BIT(0));
0268         input_report_key(input, BTN_TL, b_rsp4 & BIT(5));
0269         input_report_key(input, BTN_TR, b_rsp4 & BIT(4));
0270         input_report_key(input, BTN_TL2, b_rsp4 & BIT(7));
0271         input_report_key(input, BTN_TR2, b_rsp4 & BIT(6));
0272         input_report_key(input, BTN_THUMBL, false);
0273         input_report_key(input, BTN_THUMBR, false);
0274         input_report_key(input, BTN_SELECT, b_rsp3 & BIT(7));
0275         input_report_key(input, BTN_START, b_rsp3 & BIT(4));
0276         break;
0277     }
0278 
0279     input_sync(input);
0280 }
0281 
0282 static int psxpad_spi_probe(struct spi_device *spi)
0283 {
0284     struct psxpad *pad;
0285     struct input_dev *idev;
0286     int err;
0287 
0288     pad = devm_kzalloc(&spi->dev, sizeof(struct psxpad), GFP_KERNEL);
0289     if (!pad)
0290         return -ENOMEM;
0291 
0292     idev = devm_input_allocate_device(&spi->dev);
0293     if (!idev) {
0294         dev_err(&spi->dev, "failed to allocate input device\n");
0295         return -ENOMEM;
0296     }
0297 
0298     /* input poll device settings */
0299     pad->idev = idev;
0300     pad->spi = spi;
0301 
0302     /* input device settings */
0303     input_set_drvdata(idev, pad);
0304 
0305     idev->name = "PlayStation 1/2 joypad";
0306     snprintf(pad->phys, sizeof(pad->phys), "%s/input", dev_name(&spi->dev));
0307     idev->id.bustype = BUS_SPI;
0308 
0309     idev->open = psxpad_spi_poll_open;
0310     idev->close = psxpad_spi_poll_close;
0311 
0312     /* key/value map settings */
0313     input_set_abs_params(idev, ABS_X, 0, 255, 0, 0);
0314     input_set_abs_params(idev, ABS_Y, 0, 255, 0, 0);
0315     input_set_abs_params(idev, ABS_RX, 0, 255, 0, 0);
0316     input_set_abs_params(idev, ABS_RY, 0, 255, 0, 0);
0317     input_set_capability(idev, EV_KEY, BTN_DPAD_UP);
0318     input_set_capability(idev, EV_KEY, BTN_DPAD_DOWN);
0319     input_set_capability(idev, EV_KEY, BTN_DPAD_LEFT);
0320     input_set_capability(idev, EV_KEY, BTN_DPAD_RIGHT);
0321     input_set_capability(idev, EV_KEY, BTN_A);
0322     input_set_capability(idev, EV_KEY, BTN_B);
0323     input_set_capability(idev, EV_KEY, BTN_X);
0324     input_set_capability(idev, EV_KEY, BTN_Y);
0325     input_set_capability(idev, EV_KEY, BTN_TL);
0326     input_set_capability(idev, EV_KEY, BTN_TR);
0327     input_set_capability(idev, EV_KEY, BTN_TL2);
0328     input_set_capability(idev, EV_KEY, BTN_TR2);
0329     input_set_capability(idev, EV_KEY, BTN_THUMBL);
0330     input_set_capability(idev, EV_KEY, BTN_THUMBR);
0331     input_set_capability(idev, EV_KEY, BTN_SELECT);
0332     input_set_capability(idev, EV_KEY, BTN_START);
0333 
0334     err = psxpad_spi_init_ff(pad);
0335     if (err)
0336         return err;
0337 
0338     /* SPI settings */
0339     spi->mode = SPI_MODE_3;
0340     spi->bits_per_word = 8;
0341     /* (PlayStation 1/2 joypad might be possible works 250kHz/500kHz) */
0342     spi->master->min_speed_hz = 125000;
0343     spi->master->max_speed_hz = 125000;
0344     spi_setup(spi);
0345 
0346     /* pad settings */
0347     psxpad_set_motor_level(pad, 0, 0);
0348 
0349 
0350     err = input_setup_polling(idev, psxpad_spi_poll);
0351     if (err) {
0352         dev_err(&spi->dev, "failed to set up polling: %d\n", err);
0353         return err;
0354     }
0355 
0356     /* poll interval is about 60fps */
0357     input_set_poll_interval(idev, 16);
0358     input_set_min_poll_interval(idev, 8);
0359     input_set_max_poll_interval(idev, 32);
0360 
0361     /* register input poll device */
0362     err = input_register_device(idev);
0363     if (err) {
0364         dev_err(&spi->dev,
0365             "failed to register input device: %d\n", err);
0366         return err;
0367     }
0368 
0369     pm_runtime_enable(&spi->dev);
0370 
0371     return 0;
0372 }
0373 
0374 static int __maybe_unused psxpad_spi_suspend(struct device *dev)
0375 {
0376     struct spi_device *spi = to_spi_device(dev);
0377     struct psxpad *pad = spi_get_drvdata(spi);
0378 
0379     psxpad_set_motor_level(pad, 0, 0);
0380 
0381     return 0;
0382 }
0383 
0384 static SIMPLE_DEV_PM_OPS(psxpad_spi_pm, psxpad_spi_suspend, NULL);
0385 
0386 static const struct spi_device_id psxpad_spi_id[] = {
0387     { "psxpad-spi", 0 },
0388     { }
0389 };
0390 MODULE_DEVICE_TABLE(spi, psxpad_spi_id);
0391 
0392 static struct spi_driver psxpad_spi_driver = {
0393     .driver = {
0394         .name = "psxpad-spi",
0395         .pm = &psxpad_spi_pm,
0396     },
0397     .id_table = psxpad_spi_id,
0398     .probe   = psxpad_spi_probe,
0399 };
0400 
0401 module_spi_driver(psxpad_spi_driver);
0402 
0403 MODULE_AUTHOR("Tomohiro Yoshidomi <sylph23k@gmail.com>");
0404 MODULE_DESCRIPTION("PlayStation 1/2 joypads via SPI interface Driver");
0405 MODULE_LICENSE("GPL");