// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2013-2019 TRUSTONIC LIMITED * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include #include #include #include #include #include "tlcTui.h" #include "tui-hal.h" #include "build_tag.h" /* Static variables */ static struct cdev tui_cdev; struct device* (dev_tlc_tui) = NULL; /* Function pointer */ int (*fptr_get_fd)(u32 buff_id) = NULL; static long tui_ioctl(struct file *f, unsigned int cmd, unsigned long arg) { int ret = -ENOTTY; int __user *uarg = (int __user *)arg; if (_IOC_TYPE(cmd) != TUI_IO_MAGIC) return -EINVAL; tui_dev_devel("t-base-tui module: ioctl 0x%x", cmd); switch (cmd) { case TUI_IO_SET_RESOLUTION: /* TLC_TUI_CMD_SET_RESOLUTION is for specific platforms * that rely on onConfigurationChanged to set resolution * it has no effect on Trustonic reference implementation. */ tui_dev_devel("TLC_TUI_CMD_SET_RESOLUTION"); /* NOT IMPLEMENTED */ ret = 0; break; case TUI_IO_NOTIFY: tui_dev_devel("TUI_IO_NOTIFY"); if (tlc_notify_event(arg)) ret = 0; else ret = -EFAULT; break; case TUI_IO_WAITCMD: { struct tlc_tui_command_t tui_cmd = {0}; tui_dev_devel("TUI_IO_WAITCMD"); ret = tlc_wait_cmd(&tui_cmd); if (ret) { tui_dev_err(ret, "%d tlc_wait_cmd returned", __LINE__); return ret; } /* Write command id to user */ tui_dev_devel("IOCTL: sending command %d to user.", tui_cmd.id); if (copy_to_user(uarg, &tui_cmd, sizeof( struct tlc_tui_command_t))) ret = -EFAULT; else ret = 0; break; } case TUI_IO_ACK: { struct tlc_tui_response_t rsp_id; tui_dev_devel("TUI_IO_ACK"); /* Read user response */ if (copy_from_user(&rsp_id, uarg, sizeof(rsp_id))) ret = -EFAULT; else ret = 0; tui_dev_devel("IOCTL: User completed command %d.", rsp_id.id); ret = tlc_ack_cmd(&rsp_id); if (ret) return ret; break; } case TUI_IO_INIT_DRIVER: { tui_dev_devel("TUI_IO_INIT_DRIVER"); ret = tlc_init_driver(); if (ret) { tui_dev_err(ret, "%d tlc_init_driver() failed", __LINE__); return ret; } break; } /* Ioclt that allows to get buffer info from DrTui */ case TUI_IO_GET_BUFFER_INFO: { tui_dev_devel("TUI_IO_GET_BUFFER_INFO"); /* Get all buffer info received from DrTui through the dci */ struct tlc_tui_ioctl_buffer_info buff_info; get_buffer_info(&buff_info); /* Fill in return struct */ if (copy_to_user(uarg, &buff_info, sizeof(buff_info))) ret = -EFAULT; else ret = 0; break; } /* Ioclt that allows to get the ion buffer f */ case TUI_IO_GET_ION_FD: { tui_dev_devel("TUI_IO_GET_ION_FD"); /* Get the back buffer id (in the dci, from DrTui) */ u32 buff_id = dci->buff_id; /* Get the fd of the ion buffer */ struct tlc_tui_ioctl_ion_t ion; if (fptr_get_fd) ion.buffer_fd = (*fptr_get_fd)(buff_id); /* Fill in return struct */ if (copy_to_user(uarg, &ion, sizeof(ion))) { ret = -EFAULT; break; } ret = 0; break; } default: ret = -ENOTTY; tui_dev_err(ret, "%d Unknown ioctl (%u)!", __LINE__, cmd); return ret; } return ret; } atomic_t fileopened; static int tui_open(struct inode *inode, struct file *file) { tui_dev_devel("TUI file opened"); atomic_inc(&fileopened); return 0; } static int tui_release(struct inode *inode, struct file *file) { tui_dev_devel("TUI file closed"); if (atomic_dec_and_test(&fileopened)) tlc_notify_event(NOT_TUI_CANCEL_EVENT); return 0; } static const struct file_operations tui_fops = { .owner = THIS_MODULE, .unlocked_ioctl = tui_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = tui_ioctl, #endif .open = tui_open, .release = tui_release, }; /*--------------------------------------------------------------------------- */ static struct device_driver tui_driver = { .name = "Trustonic" }; struct device tui_dev = { .driver = &tui_driver }; static int __init tlc_tui_init(void) { dev_set_name(&tui_dev, "TUI"); tui_dev_info("Loading t-base-tui module."); tui_dev_devel("=============== Running TUI Kernel TLC ==============="); tui_dev_info("%s", MOBICORE_COMPONENT_BUILD_TAG); dev_t devno; int err; static struct class *tui_class; atomic_set(&fileopened, 0); err = alloc_chrdev_region(&devno, 0, 1, TUI_DEV_NAME); if (err) { tui_dev_err(err, "Unable to allocate Trusted UI device number"); return err; } cdev_init(&tui_cdev, &tui_fops); tui_cdev.owner = THIS_MODULE; /* tui_cdev.ops = &tui_fops; */ err = cdev_add(&tui_cdev, devno, 1); if (err) { tui_dev_err(err, "Unable to add Trusted UI char device"); unregister_chrdev_region(devno, 1); return err; } tui_class = class_create(THIS_MODULE, "tui_cls"); dev_tlc_tui = device_create(tui_class, NULL, devno, NULL, TUI_DEV_NAME); if (IS_ERR(dev_tlc_tui)) return PTR_ERR(dev_tlc_tui); if (!hal_tui_init()) return -EPERM; return 0; } static void __exit tlc_tui_exit(void) { tui_dev_devel("Unloading t-base-tui module."); unregister_chrdev_region(tui_cdev.dev, 1); cdev_del(&tui_cdev); hal_tui_exit(); } module_init(tlc_tui_init); module_exit(tlc_tui_exit); MODULE_AUTHOR("Trustonic Limited"); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Kinibi TUI");