• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (c) 2023 Huawei Device Co., Ltd.
4  *
5  * Description: Bluetooth virtual network device used in
6  * the NewIP over Bluetooth communication scenario.
7  *
8  * Author: Yang Yanjun <yangyanjun@huawei.com>
9  *
10  * Data: 2023-03-14
11  */
12 
13 #ifndef _BTDEV_H_
14 #define _BTDEV_H_
15 
16 #include <linux/skbuff.h>
17 #include <linux/list.h>
18 #include <linux/errno.h>
19 #include <linux/netdevice.h>
20 #include <linux/etherdevice.h>
21 #include <linux/kernel.h>
22 #include <linux/types.h>
23 #include <linux/fcntl.h>
24 #include <linux/ioport.h>
25 #include <linux/in.h>
26 #include <linux/slab.h>
27 #include <linux/spinlock.h>
28 #include <linux/string.h>
29 #include <linux/bitops.h>
30 #include <linux/delay.h>
31 #include <linux/ip.h>
32 #include <linux/init.h>
33 #include <linux/module.h>
34 #include <linux/miscdevice.h>
35 #include <linux/fs.h>
36 #include <linux/cdev.h>
37 #include <linux/poll.h>
38 #include <linux/proc_fs.h>
39 #include <linux/seq_file.h>
40 #include <linux/ktime.h>
41 #include <linux/rtnetlink.h>
42 #include <linux/libfdt_env.h>
43 
44 /* must include btdev_user.h first before any macro definition */
45 #include "btdev_user.h"
46 
47 #define OK 0
48 #define TRUE 1
49 #define FALSE 0
50 #define DELAY_100_MS 100
51 #define MACADDR_LEN (2 * ETH_ALEN)
52 
53 #define BT_DEV_MAJOR 125
54 #define BT_DEV_MINOR 0
55 #define BT_RING_BUFFER_SIZE 4096
56 #define STRTOLL_BASE 10
57 #define BT_DEV_ID_OFFSET (sizeof(BT_DEV_PATH_PREFIX) - 1)
58 #define BT_STATISTIC_KTIME_MAX ULONG_MAX
59 #define NEWIP_TYPE_SIZE 2 /* newip type eadd */
60 #define BT_MAX_MTU 65535
61 #define UNKNOWN_NAME "unknown"
62 
63 /**
64  * ring buffer
65  */
66 struct bt_ring {
67 	u32 head;
68 	u32 tail;
69 	u32 size;
70 	void **data;
71 };
72 
73 /**
74  * one char device
75  */
76 struct bt_cdev {
77 	struct cdev *cdev;
78 	struct class *bt_class;
79 	char dev_filename[IFNAMSIZ];
80 };
81 
82 struct bt_mng_file {
83 	struct bt_cdev *bt_cdev;
84 	atomic_t open_limit;
85 };
86 
87 struct bt_io_file {
88 	struct bt_cdev *bt_cdev;
89 	atomic_t read_open_limit;
90 	atomic_t write_open_limit;
91 };
92 
93 /**
94  * virnet list
95  */
96 struct bt_table {
97 	struct list_head head;
98 	struct mutex tbl_lock; // lock for table
99 	u32 num;
100 };
101 
102 /**
103  * bt virnet state
104  */
105 enum bt_virnet_state {
106 	BT_VIRNET_STATE_CREATED,
107 	BT_VIRNET_STATE_CONNECTED,
108 	BT_VIRNET_STATE_DISCONNECTED,
109 	BT_VIRNET_STATE_DISABLED,
110 	BT_VIRNET_STATE_DELETED,
111 	BT_VIRNET_STAET_NUM
112 };
113 
114 /**
115  * one virnet device
116  */
117 struct bt_virnet {
118 	struct bt_ring *tx_ring;
119 	struct bt_io_file *io_file;
120 	struct net_device *ndev;
121 	struct list_head virnet_entry;
122 	enum bt_virnet_state state;
123 	struct semaphore sem;
124 	wait_queue_head_t rx_queue;
125 };
126 
127 /**
128  * instance of the module
129  */
130 struct bt_drv {
131 	struct bt_table *devices_table;
132 	struct bt_mng_file *mng_file;
133 	struct bt_io_file **io_files;
134 	u32 bitmap;
135 	struct mutex bitmap_lock; // lock for bitmap
136 	struct class *bt_class;
137 };
138 
139 /**
140  * state to string
141  */
142 static const char *g_bt_virnet_state_rep[BT_VIRNET_STAET_NUM] = {
143 	"CREATED",
144 	"CONNECTED",
145 	"DISCONNECTED",
146 	"DISABLED",
147 	"ENABLED"};
148 
149 /**
150  * inline functions
151  */
bt_get_unused_id(u32 bitmap)152 static inline int bt_get_unused_id(u32 bitmap)
153 {
154 	int i;
155 
156 	for (i = 0; i < BT_VIRNET_MAX_NUM + 1; ++i) {
157 		if (!(bitmap & (1 << i)))
158 			return i;
159 	}
160 	return -1; // all used
161 }
162 
bt_set_bit(u32 * bitmap,u32 idx)163 static inline void bt_set_bit(u32 *bitmap, u32 idx)
164 {
165 	if (bitmap && idx <= BT_VIRNET_MAX_NUM)
166 		*bitmap |= (1 << idx);
167 }
168 
bt_clear_bit(u32 * bitmap,u32 idx)169 static inline void bt_clear_bit(u32 *bitmap, u32 idx)
170 {
171 	if (bitmap && idx <= BT_VIRNET_MAX_NUM)
172 		*bitmap &= ~(1 << idx);
173 }
174 
175 #define set_state(vn, st) bt_virnet_set_state(vn, st)
bt_virnet_set_state(struct bt_virnet * vn,enum bt_virnet_state state)176 static inline void bt_virnet_set_state(struct bt_virnet *vn,
177 				       enum bt_virnet_state state)
178 {
179 	vn->state = state;
180 }
181 
bt_virnet_get_cdev(const struct bt_virnet * vn)182 static inline const struct cdev *bt_virnet_get_cdev(const struct bt_virnet *vn)
183 {
184 	if (unlikely(!vn->io_file) || unlikely(!vn->io_file->bt_cdev))
185 		return NULL;
186 
187 	return vn->io_file->bt_cdev->cdev;
188 }
189 
bt_virnet_get_cdev_number(const struct bt_virnet * vn,dev_t * number)190 static inline const int bt_virnet_get_cdev_number(const struct bt_virnet *vn, dev_t *number)
191 {
192 	if (unlikely(!vn->io_file) || unlikely(!vn->io_file->bt_cdev) ||
193 	    unlikely(!vn->io_file->bt_cdev->cdev) || unlikely(!number))
194 		return -EINVAL;
195 
196 	*number = vn->io_file->bt_cdev->cdev->dev;
197 	return OK;
198 }
199 
bt_virnet_get_cdev_name(const struct bt_virnet * vn)200 static inline const char *bt_virnet_get_cdev_name(const struct bt_virnet *vn)
201 {
202 	if (unlikely(!vn->io_file) || unlikely(!vn->io_file->bt_cdev) ||
203 	    unlikely(!vn->io_file->bt_cdev->dev_filename))
204 		return UNKNOWN_NAME;
205 
206 	return vn->io_file->bt_cdev->dev_filename;
207 }
208 
bt_virnet_get_ndev(const struct bt_virnet * vn)209 static inline struct net_device *bt_virnet_get_ndev(const struct bt_virnet *vn)
210 {
211 	return vn->ndev;
212 }
213 
bt_virnet_get_ndev_name(const struct bt_virnet * vn)214 static inline const char *bt_virnet_get_ndev_name(const struct bt_virnet *vn)
215 {
216 	if (unlikely(!vn->ndev) || unlikely(!vn->ndev->name))
217 		return UNKNOWN_NAME;
218 
219 	return vn->ndev->name;
220 }
221 
bt_virnet_get_state_rep(const struct bt_virnet * vn)222 static inline const char *bt_virnet_get_state_rep(const struct bt_virnet *vn)
223 {
224 	return g_bt_virnet_state_rep[vn->state];
225 }
226 
bt_get_total_device(const struct bt_drv * drv)227 static inline int bt_get_total_device(const struct bt_drv *drv)
228 {
229 	if (unlikely(!drv->devices_table))
230 		return -EINVAL;
231 
232 	return drv->devices_table->num;
233 }
234 
bt_virnet_get_ring_packets(const struct bt_virnet * vn)235 static inline int bt_virnet_get_ring_packets(const struct bt_virnet *vn)
236 {
237 	int packets = 0;
238 
239 	if (unlikely(!vn->tx_ring) || unlikely(!vn->tx_ring->head) ||
240 	    unlikely(!vn->tx_ring->tail))
241 		return 0;
242 
243 	packets = vn->tx_ring->head - vn->tx_ring->tail;
244 	if (unlikely(packets < 0))
245 		packets += BT_RING_BUFFER_SIZE;
246 
247 	return packets;
248 }
249 
250 static struct bt_table *bt_table_init(void);
251 static int bt_table_add_device(struct bt_table *tbl, struct bt_virnet *vn);
252 static void bt_table_remove_device(struct bt_table *tbl, struct bt_virnet *vn);
253 static int bt_table_delete_all(struct bt_drv *drv);
254 static struct bt_virnet *bt_table_find(struct bt_table *tbl, const char *ifa_name);
255 static void bt_table_destroy(struct bt_drv *drv);
256 static void bt_delete_io_files(struct bt_drv *bt_mng);
257 static struct bt_io_file **bt_create_io_files(void);
258 
259 static struct bt_ring *bt_ring_create(void);
260 static int bt_ring_is_empty(const struct bt_ring *ring);
261 static int bt_ring_is_full(const struct bt_ring *ring);
262 static void *bt_ring_current(struct bt_ring *ring);
263 static void bt_ring_produce(struct bt_ring *ring, void *data);
264 static void bt_ring_consume(struct bt_ring *ring);
265 static void bt_ring_destroy(struct bt_ring *ring);
266 
267 static int bt_virnet_produce_data(struct bt_virnet *dev, void *data);
268 static struct bt_virnet *bt_virnet_create(struct bt_drv *bt_mng, u32 id);
269 static void bt_virnet_destroy(struct bt_virnet *vnet);
270 
271 #endif
272