• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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