]> Git Repo - esp-hosted.git/blob - host/linux/host_driver/esp32/esp_serial.c
control path platform init function added. stress test code added.
[esp-hosted.git] / host / linux / host_driver / esp32 / esp_serial.c
1 /*
2  * Espressif Systems Wireless LAN device driver
3  *
4  * Copyright (C) 2015-2021 Espressif Systems (Shanghai) PTE LTD
5  *
6  * This software file (the "File") is distributed by Espressif Systems (Shanghai)
7  * PTE LTD under the terms of the GNU General Public License Version 2, June 1991
8  * (the "License").  You may use, redistribute and/or modify this File in
9  * accordance with the terms and conditions of the License, a copy of which
10  * is available by writing to the Free Software Foundation, Inc.,
11  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13  *
14  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
17  * this warranty disclaimer.
18  */
19
20 #include <linux/init.h>
21 #include <linux/module.h>
22 #include <linux/kernel.h>
23 #include <linux/delay.h>
24 #include <linux/cdev.h>
25 #include <linux/fs.h>
26 #include <linux/kthread.h>
27 #include <linux/delay.h>
28 #include <linux/slab.h>
29
30 #include "esp.h"
31 #include "esp_rb.h"
32 #include "esp_api.h"
33
34 #define ESP_SERIAL_MAJOR        221
35 #define ESP_SERIAL_MINOR_MAX    2
36 #define ESP_RX_RB_SIZE  4096
37
38 //#define ESP_SERIAL_TEST
39
40
41 static struct esp_serial_devs {
42         struct cdev cdev;
43         int dev_index;
44         esp_rb_t rb;
45         void *priv;
46         struct mutex lock;
47 } devs[ESP_SERIAL_MINOR_MAX];
48
49 static ssize_t esp_serial_read(struct file *file, char __user *user_buffer, size_t size, loff_t *offset)
50 {
51         struct esp_serial_devs *dev = NULL;
52         ssize_t ret_size = 0;
53         dev = (struct esp_serial_devs *) file->private_data;
54         ret_size = esp_rb_read_by_user(&dev->rb, user_buffer, size, !(file->f_flags & O_NONBLOCK));
55         if (ret_size == 0) {
56                 return -EAGAIN;
57         }
58         return ret_size;
59 }
60
61 static ssize_t esp_serial_write(struct file *file, const char __user *user_buffer, size_t size, loff_t * offset)
62 {
63         struct esp_payload_header *hdr = NULL;
64         u8 *tx_buf = NULL;
65         struct esp_serial_devs *dev = NULL;
66         struct sk_buff * tx_skb = NULL;
67         int ret = 0;
68         size_t total_len = 0;
69
70         dev = (struct esp_serial_devs *) file->private_data;
71         total_len = size + sizeof(struct esp_payload_header);
72
73         tx_skb = esp_alloc_skb(total_len);
74         if (!tx_skb) {
75                 printk (KERN_ERR "%s: SKB alloc failed\n", __func__);
76                 return -ENOMEM;
77         }
78
79         tx_buf = skb_put(tx_skb, total_len);
80
81         hdr = (struct esp_payload_header *) tx_buf;
82
83         memset (hdr, 0, sizeof(struct esp_payload_header));
84
85         hdr->if_type = ESP_SERIAL_IF;
86         hdr->if_num = dev->dev_index;
87         hdr->len = cpu_to_le16(size);
88         hdr->offset = cpu_to_le16(sizeof(struct esp_payload_header));
89
90         ret = copy_from_user(tx_buf + hdr->offset, user_buffer, size);
91         if (ret) {
92                 dev_kfree_skb(tx_skb);
93                 printk(KERN_ERR "%s, Error copying buffer to send serial data\n", __func__);
94                 return -EFAULT;
95         }
96
97         ret = esp_send_packet(dev->priv, tx_skb);
98         if (ret) {
99                 printk (KERN_ERR "%s: Failed to transmit data\n", __func__);
100         }
101
102         return size;
103 }
104
105 static long esp_serial_ioctl (struct file *file, unsigned int cmd, unsigned long arg)
106 {
107         printk(KERN_INFO "%s IOCTL %d\n", __func__, cmd);
108         return 0;
109 }
110
111 static int esp_serial_open(struct inode *inode, struct file *file)
112 {
113         struct esp_serial_devs *devs = NULL;
114
115         devs = container_of(inode->i_cdev, struct esp_serial_devs, cdev);
116         file->private_data = devs;
117
118         return 0;
119 }
120
121 static unsigned int esp_serial_poll(struct file *file, poll_table *wait)
122 {
123     struct esp_serial_devs *dev = (struct esp_serial_devs *)file->private_data;
124     unsigned int mask = 0;
125
126     mutex_lock(&dev->lock);
127     poll_wait(file, &dev->rb.wq,  wait);
128
129     if (dev->rb.rp != dev->rb.wp) {
130         mask |= (POLLIN | POLLRDNORM) ;   /* readable */
131     }
132     if (get_free_space(&dev->rb)) {
133         mask |= (POLLOUT | POLLWRNORM) ;  /* writable */
134     }
135
136     mutex_unlock(&dev->lock);
137     return mask;
138 }
139
140 const struct file_operations esp_serial_fops = {
141         .owner = THIS_MODULE,
142         .open = esp_serial_open,
143         .read = esp_serial_read,
144         .write = esp_serial_write,
145         .unlocked_ioctl = esp_serial_ioctl,
146         .poll = esp_serial_poll
147 };
148
149 int esp_serial_data_received(int dev_index, const char *data, size_t len)
150 {
151         int ret = 0;
152         size_t ret_len = 0;
153         if (dev_index >= ESP_SERIAL_MINOR_MAX) {
154                 return -EINVAL;
155         }
156
157         while (ret_len != len) {
158                 ret = esp_rb_write_by_kernel(&devs[dev_index].rb,
159                                 data+ret_len, (len-ret_len));
160                 if (ret <= 0) {
161                         break;
162                 }
163                 ret_len += ret;
164         }
165         if (ret_len != len) {
166                 printk(KERN_ERR "%s, RB full, no space to receive. Dropping packet",__func__);
167         }
168
169         return ret_len;
170 }
171
172 #ifdef ESP_SERIAL_TEST
173 static int thread_fn(void *unused)
174 {
175         int i = 100;
176
177         while(i--) {
178                 esp_rb_write_by_kernel(&devs[0].rb, "alphabetagamma", 14);
179                 ssleep(1);
180         }
181         printk(KERN_INFO "%s, Thread stopping\n", __func__);
182         do_exit(0);
183         return 0;
184 }
185 #endif
186
187 int esp_serial_init(void *priv)
188 {
189         int err = 0, i = 0;
190
191         err = register_chrdev_region(MKDEV(ESP_SERIAL_MAJOR, 0), ESP_SERIAL_MINOR_MAX, "esp_serial_driver");
192         if (err) {
193                 printk(KERN_ERR "%s, Error registering chrdev region %d\n", __func__, err);
194                 return -1;
195         }
196
197         for (i = 0; i < ESP_SERIAL_MINOR_MAX; i++) {
198                 cdev_init(&devs[i].cdev, &esp_serial_fops);
199                 devs[i].dev_index = i;
200                 cdev_add(&devs[i].cdev, MKDEV(ESP_SERIAL_MAJOR, i), 1);
201                 esp_rb_init(&devs[i].rb, ESP_RX_RB_SIZE);
202                 devs[i].priv = priv;
203                 mutex_init(&devs[i].lock);
204         }
205
206 #ifdef ESP_SERIAL_TEST
207         kthread_run(thread_fn, NULL, "esptest-thread");
208 #endif
209         return 0;
210 }
211
212 void esp_serial_cleanup(void)
213 {
214         int i = 0;
215         for (i = 0; i < ESP_SERIAL_MINOR_MAX; i++) {
216                 cdev_del(&devs[i].cdev);
217                 esp_rb_cleanup(&devs[i].rb);
218                 mutex_destroy(&devs[i].lock);
219         }
220         unregister_chrdev_region(MKDEV(ESP_SERIAL_MAJOR, 0), ESP_SERIAL_MINOR_MAX);
221         return;
222 }
This page took 0.036805 seconds and 4 git commands to generate.