1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18 #include "oal_chr.h"
19 #include "oam_ext_if.h"
20 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
21 #include "linux/miscdevice.h"
22 #include "oal_wait.h"
23 #include "oal_mutex.h"
24 #endif
25
26
27 #ifdef __cplusplus
28 #if __cplusplus
29 extern "C" {
30 #endif
31 #endif
32
33 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
34 hi_wifi_driver_event g_driver_event = UNKNOWN;
35 static atomic_t g_hisi_chardev_available = ATOMIC_INIT(1);
36 #define DEVNAME "hisi_wifi"
37 static hi_u8 g_driver_exit = HI_FALSE;
38 oal_wait_queue_head_stru g_read_wait_queue;
39 #define DEV_EXIT 0
40
hisi_sched_event(hi_wifi_driver_event event)41 hi_u32 hisi_sched_event(hi_wifi_driver_event event)
42 {
43 if (atomic_read(&g_hisi_chardev_available) != 0) {
44 oam_warning_log0(0, OAM_SF_ANY, "device is not open!\n");
45 return HI_FAIL;
46 }
47 g_driver_event = event;
48 hi_wait_queue_wake_up_interrupt(&g_read_wait_queue);
49 return HI_SUCCESS;
50 }
51
hisi_read(struct file * file,char __user * buffer,size_t length,loff_t * offset)52 static ssize_t hisi_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)
53 {
54 ssize_t copied = 0;
55 if (length < sizeof(hi_wifi_driver_event)) {
56 oam_warning_log0(0, OAM_SF_ANY, "hisi_read parameter error\n");
57 return -EINVAL;
58 }
59
60 hi_wait_event_interruptible(g_read_wait_queue, (g_driver_event != UNKNOWN || g_driver_exit == HI_TRUE));
61
62 if (g_driver_exit) {
63 return -EINVAL;
64 }
65
66 copied = sizeof(hi_wifi_driver_event);
67 copied -= copy_to_user(buffer, (hi_u8 *)&g_driver_event, copied);
68 g_driver_event = UNKNOWN;
69 return copied;
70 }
71
hisi_release(struct inode * inode,struct file * file)72 static int hisi_release(struct inode *inode, struct file *file)
73 {
74 printk("hisi_release\n");
75 atomic_inc(&g_hisi_chardev_available);
76 return 0;
77 }
78
hisi_ioctl(struct file * filp,unsigned int command,unsigned long arg)79 static long hisi_ioctl(struct file *filp, unsigned int command, unsigned long arg)
80 {
81 int ret = 0;
82 switch (command) {
83 case DEV_EXIT: {
84 g_driver_exit = HI_TRUE;
85 hi_wait_queue_wake_up_interrupt(&g_read_wait_queue);
86 break;
87 }
88 default:
89 ret = -EINVAL;
90 break;
91 }
92 return ret;
93 }
94
hisi_open(struct inode * inode,struct file * file)95 static int hisi_open(struct inode *inode, struct file *file)
96 {
97 int err = 0;
98 if (!atomic_dec_and_test(&g_hisi_chardev_available)) {
99 err = -EBUSY;
100 }
101
102 if (err) {
103 atomic_inc(&g_hisi_chardev_available);
104 }
105 hi_wait_queue_init_head(&g_read_wait_queue);
106 g_driver_exit = HI_FALSE;
107 return err;
108 }
109
110 static struct file_operations hisi_fops = {
111 .owner = THIS_MODULE,
112 .read = hisi_read,
113 .open = hisi_open,
114 .unlocked_ioctl = hisi_ioctl,
115 .release = hisi_release,
116 };
117
118 static struct miscdevice hisi_device = {
119 .minor = MISC_DYNAMIC_MINOR,
120 .name = DEVNAME,
121 .fops = &hisi_fops,
122 .nodename = DEVNAME
123 };
124
oal_register_ioctl(hi_void)125 hi_u32 oal_register_ioctl(hi_void)
126 {
127 if (misc_register(&hisi_device)) {
128 return HI_FAIL;
129 }
130 return HI_SUCCESS;
131 }
132
133 #else
134 static hi_wifi_driver_event_cb g_fuc_callback = HI_NULL;
135
136 hi_u32 hisi_sched_event(hi_wifi_driver_event event)
137 {
138 if (g_fuc_callback == HI_NULL) {
139 return HI_FAIL;
140 }
141 return g_fuc_callback(event);
142 }
143
144 hi_u32 oal_register_ioctl(hi_wifi_driver_event_cb event_cb)
145 {
146 g_fuc_callback = event_cb;
147 return HI_SUCCESS;
148 }
149 #endif
150
oal_unregister_ioctl(hi_void)151 hi_void oal_unregister_ioctl(hi_void)
152 {
153 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
154 misc_deregister(&hisi_device);
155 #else
156 g_fuc_callback = HI_NULL;
157 #endif
158 }
159
160 #ifdef __cplusplus
161 #if __cplusplus
162 }
163 #endif
164 #endif
165