1*bb7e3611SHeiko Stuebner // SPDX-License-Identifier: GPL-2.0-only 2*bb7e3611SHeiko Stuebner 3*bb7e3611SHeiko Stuebner /* 4*bb7e3611SHeiko Stuebner * Driver for input events on QNAP-MCUs 5*bb7e3611SHeiko Stuebner * 6*bb7e3611SHeiko Stuebner * Copyright (C) 2024 Heiko Stuebner <heiko@sntech.de> 7*bb7e3611SHeiko Stuebner */ 8*bb7e3611SHeiko Stuebner 9*bb7e3611SHeiko Stuebner #include <linux/input.h> 10*bb7e3611SHeiko Stuebner #include <linux/mfd/qnap-mcu.h> 11*bb7e3611SHeiko Stuebner #include <linux/module.h> 12*bb7e3611SHeiko Stuebner #include <linux/platform_device.h> 13*bb7e3611SHeiko Stuebner #include <linux/slab.h> 14*bb7e3611SHeiko Stuebner #include <uapi/linux/input-event-codes.h> 15*bb7e3611SHeiko Stuebner 16*bb7e3611SHeiko Stuebner /* 17*bb7e3611SHeiko Stuebner * The power-key needs to be pressed for a while to create an event, 18*bb7e3611SHeiko Stuebner * so there is no use for overly frequent polling. 19*bb7e3611SHeiko Stuebner */ 20*bb7e3611SHeiko Stuebner #define POLL_INTERVAL 500 21*bb7e3611SHeiko Stuebner 22*bb7e3611SHeiko Stuebner struct qnap_mcu_input_dev { 23*bb7e3611SHeiko Stuebner struct input_dev *input; 24*bb7e3611SHeiko Stuebner struct qnap_mcu *mcu; 25*bb7e3611SHeiko Stuebner struct device *dev; 26*bb7e3611SHeiko Stuebner 27*bb7e3611SHeiko Stuebner struct work_struct beep_work; 28*bb7e3611SHeiko Stuebner int beep_type; 29*bb7e3611SHeiko Stuebner }; 30*bb7e3611SHeiko Stuebner 31*bb7e3611SHeiko Stuebner static void qnap_mcu_input_poll(struct input_dev *input) 32*bb7e3611SHeiko Stuebner { 33*bb7e3611SHeiko Stuebner struct qnap_mcu_input_dev *idev = input_get_drvdata(input); 34*bb7e3611SHeiko Stuebner static const u8 cmd[] = { '@', 'C', 'V' }; 35*bb7e3611SHeiko Stuebner u8 reply[4]; 36*bb7e3611SHeiko Stuebner int state, ret; 37*bb7e3611SHeiko Stuebner 38*bb7e3611SHeiko Stuebner /* poll the power button */ 39*bb7e3611SHeiko Stuebner ret = qnap_mcu_exec(idev->mcu, cmd, sizeof(cmd), reply, sizeof(reply)); 40*bb7e3611SHeiko Stuebner if (ret) 41*bb7e3611SHeiko Stuebner return; 42*bb7e3611SHeiko Stuebner 43*bb7e3611SHeiko Stuebner /* First bytes must mirror the sent command */ 44*bb7e3611SHeiko Stuebner if (memcmp(cmd, reply, sizeof(cmd))) { 45*bb7e3611SHeiko Stuebner dev_err(idev->dev, "malformed data received\n"); 46*bb7e3611SHeiko Stuebner return; 47*bb7e3611SHeiko Stuebner } 48*bb7e3611SHeiko Stuebner 49*bb7e3611SHeiko Stuebner state = reply[3] - 0x30; 50*bb7e3611SHeiko Stuebner input_event(input, EV_KEY, KEY_POWER, state); 51*bb7e3611SHeiko Stuebner input_sync(input); 52*bb7e3611SHeiko Stuebner } 53*bb7e3611SHeiko Stuebner 54*bb7e3611SHeiko Stuebner static void qnap_mcu_input_beeper_work(struct work_struct *work) 55*bb7e3611SHeiko Stuebner { 56*bb7e3611SHeiko Stuebner struct qnap_mcu_input_dev *idev = 57*bb7e3611SHeiko Stuebner container_of(work, struct qnap_mcu_input_dev, beep_work); 58*bb7e3611SHeiko Stuebner const u8 cmd[] = { '@', 'C', (idev->beep_type == SND_TONE) ? '3' : '2' }; 59*bb7e3611SHeiko Stuebner 60*bb7e3611SHeiko Stuebner qnap_mcu_exec_with_ack(idev->mcu, cmd, sizeof(cmd)); 61*bb7e3611SHeiko Stuebner } 62*bb7e3611SHeiko Stuebner 63*bb7e3611SHeiko Stuebner static int qnap_mcu_input_event(struct input_dev *input, unsigned int type, 64*bb7e3611SHeiko Stuebner unsigned int code, int value) 65*bb7e3611SHeiko Stuebner { 66*bb7e3611SHeiko Stuebner struct qnap_mcu_input_dev *idev = input_get_drvdata(input); 67*bb7e3611SHeiko Stuebner 68*bb7e3611SHeiko Stuebner if (type != EV_SND || (code != SND_BELL && code != SND_TONE)) 69*bb7e3611SHeiko Stuebner return -EOPNOTSUPP; 70*bb7e3611SHeiko Stuebner 71*bb7e3611SHeiko Stuebner if (value < 0) 72*bb7e3611SHeiko Stuebner return -EINVAL; 73*bb7e3611SHeiko Stuebner 74*bb7e3611SHeiko Stuebner /* beep runtime is determined by the MCU */ 75*bb7e3611SHeiko Stuebner if (value == 0) 76*bb7e3611SHeiko Stuebner return 0; 77*bb7e3611SHeiko Stuebner 78*bb7e3611SHeiko Stuebner /* Schedule work to actually turn the beeper on */ 79*bb7e3611SHeiko Stuebner idev->beep_type = code; 80*bb7e3611SHeiko Stuebner schedule_work(&idev->beep_work); 81*bb7e3611SHeiko Stuebner 82*bb7e3611SHeiko Stuebner return 0; 83*bb7e3611SHeiko Stuebner } 84*bb7e3611SHeiko Stuebner 85*bb7e3611SHeiko Stuebner static void qnap_mcu_input_close(struct input_dev *input) 86*bb7e3611SHeiko Stuebner { 87*bb7e3611SHeiko Stuebner struct qnap_mcu_input_dev *idev = input_get_drvdata(input); 88*bb7e3611SHeiko Stuebner 89*bb7e3611SHeiko Stuebner cancel_work_sync(&idev->beep_work); 90*bb7e3611SHeiko Stuebner } 91*bb7e3611SHeiko Stuebner 92*bb7e3611SHeiko Stuebner static int qnap_mcu_input_probe(struct platform_device *pdev) 93*bb7e3611SHeiko Stuebner { 94*bb7e3611SHeiko Stuebner struct qnap_mcu *mcu = dev_get_drvdata(pdev->dev.parent); 95*bb7e3611SHeiko Stuebner struct qnap_mcu_input_dev *idev; 96*bb7e3611SHeiko Stuebner struct device *dev = &pdev->dev; 97*bb7e3611SHeiko Stuebner struct input_dev *input; 98*bb7e3611SHeiko Stuebner int ret; 99*bb7e3611SHeiko Stuebner 100*bb7e3611SHeiko Stuebner idev = devm_kzalloc(dev, sizeof(*idev), GFP_KERNEL); 101*bb7e3611SHeiko Stuebner if (!idev) 102*bb7e3611SHeiko Stuebner return -ENOMEM; 103*bb7e3611SHeiko Stuebner 104*bb7e3611SHeiko Stuebner input = devm_input_allocate_device(dev); 105*bb7e3611SHeiko Stuebner if (!input) 106*bb7e3611SHeiko Stuebner return dev_err_probe(dev, -ENOMEM, "no memory for input device\n"); 107*bb7e3611SHeiko Stuebner 108*bb7e3611SHeiko Stuebner idev->input = input; 109*bb7e3611SHeiko Stuebner idev->dev = dev; 110*bb7e3611SHeiko Stuebner idev->mcu = mcu; 111*bb7e3611SHeiko Stuebner 112*bb7e3611SHeiko Stuebner input_set_drvdata(input, idev); 113*bb7e3611SHeiko Stuebner 114*bb7e3611SHeiko Stuebner input->name = "qnap-mcu"; 115*bb7e3611SHeiko Stuebner input->phys = "qnap-mcu-input/input0"; 116*bb7e3611SHeiko Stuebner input->id.bustype = BUS_HOST; 117*bb7e3611SHeiko Stuebner input->id.vendor = 0x0001; 118*bb7e3611SHeiko Stuebner input->id.product = 0x0001; 119*bb7e3611SHeiko Stuebner input->id.version = 0x0100; 120*bb7e3611SHeiko Stuebner input->event = qnap_mcu_input_event; 121*bb7e3611SHeiko Stuebner input->close = qnap_mcu_input_close; 122*bb7e3611SHeiko Stuebner 123*bb7e3611SHeiko Stuebner input_set_capability(input, EV_KEY, KEY_POWER); 124*bb7e3611SHeiko Stuebner input_set_capability(input, EV_SND, SND_BELL); 125*bb7e3611SHeiko Stuebner input_set_capability(input, EV_SND, SND_TONE); 126*bb7e3611SHeiko Stuebner 127*bb7e3611SHeiko Stuebner INIT_WORK(&idev->beep_work, qnap_mcu_input_beeper_work); 128*bb7e3611SHeiko Stuebner 129*bb7e3611SHeiko Stuebner ret = input_setup_polling(input, qnap_mcu_input_poll); 130*bb7e3611SHeiko Stuebner if (ret) 131*bb7e3611SHeiko Stuebner return dev_err_probe(dev, ret, "unable to set up polling\n"); 132*bb7e3611SHeiko Stuebner 133*bb7e3611SHeiko Stuebner input_set_poll_interval(input, POLL_INTERVAL); 134*bb7e3611SHeiko Stuebner 135*bb7e3611SHeiko Stuebner ret = input_register_device(input); 136*bb7e3611SHeiko Stuebner if (ret) 137*bb7e3611SHeiko Stuebner return dev_err_probe(dev, ret, "unable to register input device\n"); 138*bb7e3611SHeiko Stuebner 139*bb7e3611SHeiko Stuebner return 0; 140*bb7e3611SHeiko Stuebner } 141*bb7e3611SHeiko Stuebner 142*bb7e3611SHeiko Stuebner static struct platform_driver qnap_mcu_input_driver = { 143*bb7e3611SHeiko Stuebner .probe = qnap_mcu_input_probe, 144*bb7e3611SHeiko Stuebner .driver = { 145*bb7e3611SHeiko Stuebner .name = "qnap-mcu-input", 146*bb7e3611SHeiko Stuebner }, 147*bb7e3611SHeiko Stuebner }; 148*bb7e3611SHeiko Stuebner module_platform_driver(qnap_mcu_input_driver); 149*bb7e3611SHeiko Stuebner 150*bb7e3611SHeiko Stuebner MODULE_ALIAS("platform:qnap-mcu-input"); 151*bb7e3611SHeiko Stuebner MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>"); 152*bb7e3611SHeiko Stuebner MODULE_DESCRIPTION("QNAP MCU input driver"); 153*bb7e3611SHeiko Stuebner MODULE_LICENSE("GPL"); 154