2024-04-28 06:49:01 -07:00
|
|
|
/* tui/main.c
|
|
|
|
*
|
|
|
|
* Samsung TUI HW Handler driver.
|
|
|
|
*
|
|
|
|
* Copyright (c) 2015 Samsung Electronics
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/cdev.h>
|
|
|
|
#include <linux/delay.h>
|
|
|
|
#include <linux/device.h>
|
|
|
|
#include <linux/fs.h>
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/ioctl.h>
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/moduleparam.h>
|
|
|
|
#include <linux/slab.h>
|
|
|
|
#include <linux/uaccess.h>
|
2024-04-28 06:51:13 -07:00
|
|
|
#include <linux/version.h>
|
2024-04-28 06:49:01 -07:00
|
|
|
#include <linux/workqueue.h>
|
2024-04-28 06:51:13 -07:00
|
|
|
#include <linux/platform_device.h>
|
|
|
|
#include "linux/of.h"
|
|
|
|
#include "linux/miscdevice.h"
|
|
|
|
#include <linux/dma-mapping.h>
|
|
|
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
|
|
|
|
#include <linux/dma-map-ops.h>
|
|
|
|
#endif
|
2024-04-28 06:49:01 -07:00
|
|
|
|
|
|
|
#include "stui_core.h"
|
|
|
|
#include "stui_hal.h"
|
|
|
|
#include "stui_inf.h"
|
|
|
|
#include "stui_ioctl.h"
|
2024-04-28 06:51:13 -07:00
|
|
|
#ifdef CONFIG_SAMSUNG_TUI_LOWLEVEL
|
|
|
|
#include "iwd_agent.h"
|
|
|
|
#endif /* CONFIG_SAMSUNG_TUI_LOWLEVEL */
|
2024-04-28 06:49:01 -07:00
|
|
|
|
|
|
|
static DEFINE_MUTEX(stui_mode_mutex);
|
2024-04-28 06:51:13 -07:00
|
|
|
struct device* (dev_tui) = NULL;
|
|
|
|
struct miscdevice tui;
|
2024-04-28 06:49:01 -07:00
|
|
|
|
|
|
|
static void stui_wq_func(struct work_struct *param)
|
|
|
|
{
|
|
|
|
struct delayed_work *wq = container_of(param, struct delayed_work, work);
|
2024-04-28 06:51:13 -07:00
|
|
|
pr_debug(TUIHW_LOG_TAG " %s >>\n", __func__);
|
2024-04-28 06:49:01 -07:00
|
|
|
mutex_lock(&stui_mode_mutex);
|
2024-04-28 06:51:13 -07:00
|
|
|
stui_close_touch();
|
|
|
|
stui_close_display();
|
2024-04-28 06:49:01 -07:00
|
|
|
kfree(wq);
|
|
|
|
mutex_unlock(&stui_mode_mutex);
|
2024-04-28 06:51:13 -07:00
|
|
|
pr_debug(TUIHW_LOG_TAG " %s <<\n", __func__);
|
2024-04-28 06:49:01 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static int stui_open(struct inode *inode, struct file *filp)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
2024-04-28 06:51:13 -07:00
|
|
|
pr_debug(TUIHW_LOG_TAG " %s >>\n", __func__);
|
2024-04-28 06:49:01 -07:00
|
|
|
mutex_lock(&stui_mode_mutex);
|
|
|
|
filp->private_data = NULL;
|
|
|
|
if (stui_get_mode() & STUI_MODE_ALL) {
|
|
|
|
ret = -EBUSY;
|
2024-04-28 06:51:13 -07:00
|
|
|
pr_err(TUIHW_LOG_TAG " Device is busy\n");
|
2024-04-28 06:49:01 -07:00
|
|
|
}
|
|
|
|
mutex_unlock(&stui_mode_mutex);
|
2024-04-28 06:51:13 -07:00
|
|
|
pr_debug(TUIHW_LOG_TAG " %s <<\n", __func__);
|
2024-04-28 06:49:01 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int stui_release(struct inode *inode, struct file *filp)
|
|
|
|
{
|
|
|
|
struct delayed_work *work;
|
2024-04-28 06:51:13 -07:00
|
|
|
pr_debug(TUIHW_LOG_TAG " %s >>\n", __func__);
|
2024-04-28 06:49:01 -07:00
|
|
|
mutex_lock(&stui_mode_mutex);
|
|
|
|
if ((stui_get_mode() & STUI_MODE_ALL) && filp->private_data) {
|
2024-04-28 06:51:13 -07:00
|
|
|
pr_err(TUIHW_LOG_TAG " Device close while TUI session is active\n");
|
2024-04-28 06:49:01 -07:00
|
|
|
work = kmalloc(sizeof(struct delayed_work), GFP_KERNEL);
|
|
|
|
if (!work) {
|
|
|
|
mutex_unlock(&stui_mode_mutex);
|
2024-04-28 06:51:13 -07:00
|
|
|
pr_err(TUIHW_LOG_TAG " %s memory allocation error\n", __func__);
|
2024-04-28 06:49:01 -07:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
INIT_DELAYED_WORK(work, stui_wq_func);
|
|
|
|
schedule_delayed_work(work, msecs_to_jiffies(4000));
|
|
|
|
}
|
|
|
|
mutex_unlock(&stui_mode_mutex);
|
2024-04-28 06:51:13 -07:00
|
|
|
pr_debug(TUIHW_LOG_TAG " %s <<\n", __func__);
|
2024-04-28 06:49:01 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-04-28 06:51:13 -07:00
|
|
|
static long stui_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
|
2024-04-28 06:49:01 -07:00
|
|
|
{
|
|
|
|
long ret;
|
2024-04-28 06:51:13 -07:00
|
|
|
pr_debug(TUIHW_LOG_TAG " %s >>\n", __func__);
|
2024-04-28 06:49:01 -07:00
|
|
|
mutex_lock(&stui_mode_mutex);
|
|
|
|
ret = stui_process_cmd(f, cmd, arg);
|
2024-04-28 06:51:13 -07:00
|
|
|
if (stui_get_mode() & STUI_MODE_ALL)
|
2024-04-28 06:49:01 -07:00
|
|
|
f->private_data = (void *)1UL;
|
2024-04-28 06:51:13 -07:00
|
|
|
else
|
2024-04-28 06:49:01 -07:00
|
|
|
f->private_data = (void *)0UL;
|
|
|
|
mutex_unlock(&stui_mode_mutex);
|
2024-04-28 06:51:13 -07:00
|
|
|
pr_debug(TUIHW_LOG_TAG " %s << ret=%d\n", __func__, ret);
|
2024-04-28 06:49:01 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2024-04-28 06:51:13 -07:00
|
|
|
static int teegris_tui_probe(struct platform_device *pdev)
|
|
|
|
{
|
|
|
|
(void)pdev;
|
|
|
|
|
|
|
|
#ifdef CONFIG_ARCH_EXYNOS
|
|
|
|
dev_tui = &pdev->dev;
|
|
|
|
#if !defined(CONFIG_SOC_S5E9925) && !defined(CONFIG_SOC_S5E8825)
|
|
|
|
arch_setup_dma_ops(&pdev->dev, 0x0ULL, 1ULL << 36, NULL, false);
|
|
|
|
#endif
|
|
|
|
pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
|
|
|
|
dma_set_mask(&pdev->dev, DMA_BIT_MASK(36));
|
|
|
|
#endif /* CONFIG_ARCH_EXYNOS */
|
|
|
|
pr_debug(TUIHW_LOG_TAG " TUI probe done.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CONFIG_ARCH_EXYNOS
|
|
|
|
static const struct of_device_id teegris_tui_of_match_table[] = {
|
|
|
|
{ .compatible = "samsung,exynos-tui", },
|
|
|
|
{ },
|
|
|
|
};
|
|
|
|
#endif /* CONFIG_ARCH_EXYNOS */
|
|
|
|
|
|
|
|
static struct platform_driver teegris_tui_driver = {
|
|
|
|
.probe = teegris_tui_probe,
|
|
|
|
.driver = {
|
|
|
|
.name = "tui",
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
#ifdef CONFIG_ARCH_EXYNOS
|
|
|
|
.of_match_table = teegris_tui_of_match_table,
|
|
|
|
#endif /* CONFIG_ARCH_EXYNOS */
|
|
|
|
}
|
2024-04-28 06:49:01 -07:00
|
|
|
};
|
|
|
|
|
2024-04-28 06:51:13 -07:00
|
|
|
static int __init teegris_tui_init(void)
|
2024-04-28 06:49:01 -07:00
|
|
|
{
|
2024-04-28 06:51:13 -07:00
|
|
|
int ret;
|
2024-04-28 06:49:01 -07:00
|
|
|
|
2024-04-28 06:51:13 -07:00
|
|
|
pr_info(TUIHW_LOG_TAG " =============== Running TEEgris TUI ===============");
|
2024-04-28 06:49:01 -07:00
|
|
|
|
2024-04-28 06:51:13 -07:00
|
|
|
ret = misc_register(&tui);
|
|
|
|
if (ret) {
|
|
|
|
pr_err(TUIHW_LOG_TAG " tui can't register misc on minor=%d\n",
|
|
|
|
MISC_DYNAMIC_MINOR);
|
|
|
|
return ret;
|
2024-04-28 06:49:01 -07:00
|
|
|
}
|
|
|
|
|
2024-04-28 06:51:13 -07:00
|
|
|
#ifdef CONFIG_SAMSUNG_TUI_LOWLEVEL
|
|
|
|
__init_iwd_agent();
|
|
|
|
init_iwd_agent();
|
|
|
|
#endif /* CONFIG_SAMSUNG_TUI_LOWLEVEL */
|
2024-04-28 06:49:01 -07:00
|
|
|
|
2024-04-28 06:51:13 -07:00
|
|
|
return platform_driver_register(&teegris_tui_driver);
|
2024-04-28 06:49:01 -07:00
|
|
|
}
|
|
|
|
|
2024-04-28 06:51:13 -07:00
|
|
|
static void __exit teegris_tui_exit(void)
|
2024-04-28 06:49:01 -07:00
|
|
|
{
|
2024-04-28 06:51:13 -07:00
|
|
|
pr_info(TUIHW_LOG_TAG " Unloading teegris tui module.");
|
|
|
|
#ifdef CONFIG_SAMSUNG_TUI_LOWLEVEL
|
|
|
|
uninit_iwd_agent();
|
|
|
|
__uninit_iwd_agent();
|
|
|
|
#endif /* CONFIG_SAMSUNG_TUI_LOWLEVEL */
|
|
|
|
misc_deregister(&tui);
|
|
|
|
platform_driver_unregister(&teegris_tui_driver);
|
2024-04-28 06:49:01 -07:00
|
|
|
}
|
|
|
|
|
2024-04-28 06:51:13 -07:00
|
|
|
static const struct file_operations tui_fops = {
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
.unlocked_ioctl = stui_ioctl,
|
|
|
|
#ifdef CONFIG_COMPAT
|
|
|
|
.compat_ioctl = stui_ioctl,
|
|
|
|
#endif
|
|
|
|
.open = stui_open,
|
|
|
|
.release = stui_release,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct miscdevice tui = {
|
|
|
|
.minor = MISC_DYNAMIC_MINOR,
|
|
|
|
.name = STUI_DEV_NAME,
|
|
|
|
.fops = &tui_fops,
|
|
|
|
};
|
|
|
|
|
|
|
|
module_init(teegris_tui_init);
|
|
|
|
module_exit(teegris_tui_exit);
|
|
|
|
|
|
|
|
MODULE_AUTHOR("TUI Teegris");
|
|
|
|
MODULE_LICENSE("GPL v2");
|
|
|
|
MODULE_DESCRIPTION("TEEGRIS TUI");
|