Linux Audio

Check our new training course

Loading...
v6.8
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * WWAN device simulator for WWAN framework testing.
  4 *
  5 * Copyright (c) 2021, Sergey Ryazanov <ryazanov.s.a@gmail.com>
  6 */
  7
  8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  9
 10#include <linux/kernel.h>
 11#include <linux/module.h>
 12#include <linux/slab.h>
 13#include <linux/device.h>
 14#include <linux/spinlock.h>
 15#include <linux/list.h>
 16#include <linux/skbuff.h>
 17#include <linux/netdevice.h>
 18#include <linux/wwan.h>
 19#include <linux/debugfs.h>
 20#include <linux/workqueue.h>
 21
 22#include <net/arp.h>
 23
 24static int wwan_hwsim_devsnum = 2;
 25module_param_named(devices, wwan_hwsim_devsnum, int, 0444);
 26MODULE_PARM_DESC(devices, "Number of simulated devices");
 27
 28static struct class *wwan_hwsim_class;
 29
 30static struct dentry *wwan_hwsim_debugfs_topdir;
 31static struct dentry *wwan_hwsim_debugfs_devcreate;
 32
 33static DEFINE_SPINLOCK(wwan_hwsim_devs_lock);
 34static LIST_HEAD(wwan_hwsim_devs);
 35static unsigned int wwan_hwsim_dev_idx;
 36static struct workqueue_struct *wwan_wq;
 37
 38struct wwan_hwsim_dev {
 39	struct list_head list;
 40	unsigned int id;
 41	struct device dev;
 42	struct work_struct del_work;
 43	struct dentry *debugfs_topdir;
 44	struct dentry *debugfs_portcreate;
 45	spinlock_t ports_lock;	/* Serialize ports creation/deletion */
 46	unsigned int port_idx;
 47	struct list_head ports;
 48};
 49
 50struct wwan_hwsim_port {
 51	struct list_head list;
 52	unsigned int id;
 53	struct wwan_hwsim_dev *dev;
 54	struct wwan_port *wwan;
 55	struct work_struct del_work;
 56	struct dentry *debugfs_topdir;
 57	enum {			/* AT command parser state */
 58		AT_PARSER_WAIT_A,
 59		AT_PARSER_WAIT_T,
 60		AT_PARSER_WAIT_TERM,
 61		AT_PARSER_SKIP_LINE,
 62	} pstate;
 63};
 64
 65static const struct file_operations wwan_hwsim_debugfs_portdestroy_fops;
 66static const struct file_operations wwan_hwsim_debugfs_portcreate_fops;
 67static const struct file_operations wwan_hwsim_debugfs_devdestroy_fops;
 68static void wwan_hwsim_port_del_work(struct work_struct *work);
 69static void wwan_hwsim_dev_del_work(struct work_struct *work);
 70
 71static netdev_tx_t wwan_hwsim_netdev_xmit(struct sk_buff *skb,
 72					  struct net_device *ndev)
 73{
 74	ndev->stats.tx_packets++;
 75	ndev->stats.tx_bytes += skb->len;
 76	consume_skb(skb);
 77	return NETDEV_TX_OK;
 78}
 79
 80static const struct net_device_ops wwan_hwsim_netdev_ops = {
 81	.ndo_start_xmit = wwan_hwsim_netdev_xmit,
 82};
 83
 84static void wwan_hwsim_netdev_setup(struct net_device *ndev)
 85{
 86	ndev->netdev_ops = &wwan_hwsim_netdev_ops;
 87	ndev->needs_free_netdev = true;
 88
 89	ndev->mtu = ETH_DATA_LEN;
 90	ndev->min_mtu = ETH_MIN_MTU;
 91	ndev->max_mtu = ETH_MAX_MTU;
 92
 93	ndev->type = ARPHRD_NONE;
 94	ndev->flags = IFF_POINTOPOINT | IFF_NOARP;
 95}
 96
 97static const struct wwan_ops wwan_hwsim_wwan_rtnl_ops = {
 98	.priv_size = 0,			/* No private data */
 99	.setup = wwan_hwsim_netdev_setup,
100};
101
102static int wwan_hwsim_port_start(struct wwan_port *wport)
103{
104	struct wwan_hwsim_port *port = wwan_port_get_drvdata(wport);
105
106	port->pstate = AT_PARSER_WAIT_A;
107
108	return 0;
109}
110
111static void wwan_hwsim_port_stop(struct wwan_port *wport)
112{
113}
114
115/* Implements a minimalistic AT commands parser that echo input back and
116 * reply with 'OK' to each input command. See AT command protocol details in the
117 * ITU-T V.250 recomendations document.
118 *
119 * Be aware that this processor is not fully V.250 compliant.
120 */
121static int wwan_hwsim_port_tx(struct wwan_port *wport, struct sk_buff *in)
122{
123	struct wwan_hwsim_port *port = wwan_port_get_drvdata(wport);
124	struct sk_buff *out;
125	int i, n, s;
126
127	/* Estimate a max possible number of commands by counting the number of
128	 * termination chars (S3 param, CR by default). And then allocate the
129	 * output buffer that will be enough to fit the echo and result codes of
130	 * all commands.
131	 */
132	for (i = 0, n = 0; i < in->len; ++i)
133		if (in->data[i] == '\r')
134			n++;
135	n = in->len + n * (2 + 2 + 2);	/* Output buffer size */
136	out = alloc_skb(n, GFP_KERNEL);
137	if (!out)
138		return -ENOMEM;
139
140	for (i = 0, s = 0; i < in->len; ++i) {
141		char c = in->data[i];
142
143		if (port->pstate == AT_PARSER_WAIT_A) {
144			if (c == 'A' || c == 'a')
145				port->pstate = AT_PARSER_WAIT_T;
146			else if (c != '\n')	/* Ignore formating char */
147				port->pstate = AT_PARSER_SKIP_LINE;
148		} else if (port->pstate == AT_PARSER_WAIT_T) {
149			if (c == 'T' || c == 't')
150				port->pstate = AT_PARSER_WAIT_TERM;
151			else
152				port->pstate = AT_PARSER_SKIP_LINE;
153		} else if (port->pstate == AT_PARSER_WAIT_TERM) {
154			if (c != '\r')
155				continue;
156			/* Consume the trailing formatting char as well */
157			if ((i + 1) < in->len && in->data[i + 1] == '\n')
158				i++;
159			n = i - s + 1;
160			skb_put_data(out, &in->data[s], n);/* Echo */
161			skb_put_data(out, "\r\nOK\r\n", 6);
162			s = i + 1;
163			port->pstate = AT_PARSER_WAIT_A;
164		} else if (port->pstate == AT_PARSER_SKIP_LINE) {
165			if (c != '\r')
166				continue;
167			port->pstate = AT_PARSER_WAIT_A;
168		}
169	}
170
171	if (i > s) {
172		/* Echo the processed portion of a not yet completed command */
173		n = i - s;
174		skb_put_data(out, &in->data[s], n);
175	}
176
177	consume_skb(in);
178
179	wwan_port_rx(wport, out);
180
181	return 0;
182}
183
184static const struct wwan_port_ops wwan_hwsim_port_ops = {
185	.start = wwan_hwsim_port_start,
186	.stop = wwan_hwsim_port_stop,
187	.tx = wwan_hwsim_port_tx,
188};
189
190static struct wwan_hwsim_port *wwan_hwsim_port_new(struct wwan_hwsim_dev *dev)
191{
192	struct wwan_hwsim_port *port;
193	char name[0x10];
194	int err;
195
196	port = kzalloc(sizeof(*port), GFP_KERNEL);
197	if (!port)
198		return ERR_PTR(-ENOMEM);
199
200	port->dev = dev;
201
202	spin_lock(&dev->ports_lock);
203	port->id = dev->port_idx++;
204	spin_unlock(&dev->ports_lock);
205
206	port->wwan = wwan_create_port(&dev->dev, WWAN_PORT_AT,
207				      &wwan_hwsim_port_ops,
208				      NULL, port);
209	if (IS_ERR(port->wwan)) {
210		err = PTR_ERR(port->wwan);
211		goto err_free_port;
212	}
213
214	INIT_WORK(&port->del_work, wwan_hwsim_port_del_work);
215
216	snprintf(name, sizeof(name), "port%u", port->id);
217	port->debugfs_topdir = debugfs_create_dir(name, dev->debugfs_topdir);
218	debugfs_create_file("destroy", 0200, port->debugfs_topdir, port,
219			    &wwan_hwsim_debugfs_portdestroy_fops);
220
221	return port;
222
223err_free_port:
224	kfree(port);
225
226	return ERR_PTR(err);
227}
228
229static void wwan_hwsim_port_del(struct wwan_hwsim_port *port)
230{
231	debugfs_remove(port->debugfs_topdir);
232
233	/* Make sure that there is no pending deletion work */
234	if (current_work() != &port->del_work)
235		cancel_work_sync(&port->del_work);
236
237	wwan_remove_port(port->wwan);
238	kfree(port);
239}
240
241static void wwan_hwsim_port_del_work(struct work_struct *work)
242{
243	struct wwan_hwsim_port *port =
244				container_of(work, typeof(*port), del_work);
245	struct wwan_hwsim_dev *dev = port->dev;
246
247	spin_lock(&dev->ports_lock);
248	if (list_empty(&port->list)) {
249		/* Someone else deleting port at the moment */
250		spin_unlock(&dev->ports_lock);
251		return;
252	}
253	list_del_init(&port->list);
254	spin_unlock(&dev->ports_lock);
255
256	wwan_hwsim_port_del(port);
257}
258
259static void wwan_hwsim_dev_release(struct device *sysdev)
260{
261	struct wwan_hwsim_dev *dev = container_of(sysdev, typeof(*dev), dev);
262
263	kfree(dev);
264}
265
266static struct wwan_hwsim_dev *wwan_hwsim_dev_new(void)
267{
268	struct wwan_hwsim_dev *dev;
269	int err;
270
271	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
272	if (!dev)
273		return ERR_PTR(-ENOMEM);
274
275	spin_lock(&wwan_hwsim_devs_lock);
276	dev->id = wwan_hwsim_dev_idx++;
277	spin_unlock(&wwan_hwsim_devs_lock);
278
279	dev->dev.release = wwan_hwsim_dev_release;
280	dev->dev.class = wwan_hwsim_class;
281	dev_set_name(&dev->dev, "hwsim%u", dev->id);
282
283	spin_lock_init(&dev->ports_lock);
284	INIT_LIST_HEAD(&dev->ports);
285
286	err = device_register(&dev->dev);
287	if (err)
288		goto err_free_dev;
289
290	INIT_WORK(&dev->del_work, wwan_hwsim_dev_del_work);
291
292	err = wwan_register_ops(&dev->dev, &wwan_hwsim_wwan_rtnl_ops, dev, 1);
293	if (err)
294		goto err_unreg_dev;
295
296	dev->debugfs_topdir = debugfs_create_dir(dev_name(&dev->dev),
297						 wwan_hwsim_debugfs_topdir);
298	debugfs_create_file("destroy", 0200, dev->debugfs_topdir, dev,
299			    &wwan_hwsim_debugfs_devdestroy_fops);
300	dev->debugfs_portcreate =
301		debugfs_create_file("portcreate", 0200,
302				    dev->debugfs_topdir, dev,
303				    &wwan_hwsim_debugfs_portcreate_fops);
304
305	return dev;
306
307err_unreg_dev:
308	device_unregister(&dev->dev);
309	/* Memory will be freed in the device release callback */
310
311	return ERR_PTR(err);
312
313err_free_dev:
314	put_device(&dev->dev);
315
316	return ERR_PTR(err);
317}
318
319static void wwan_hwsim_dev_del(struct wwan_hwsim_dev *dev)
320{
321	debugfs_remove(dev->debugfs_portcreate);	/* Avoid new ports */
322
323	spin_lock(&dev->ports_lock);
324	while (!list_empty(&dev->ports)) {
325		struct wwan_hwsim_port *port;
326
327		port = list_first_entry(&dev->ports, struct wwan_hwsim_port,
328					list);
329		list_del_init(&port->list);
330		spin_unlock(&dev->ports_lock);
331		wwan_hwsim_port_del(port);
332		spin_lock(&dev->ports_lock);
333	}
334	spin_unlock(&dev->ports_lock);
335
336	debugfs_remove(dev->debugfs_topdir);
337
338	/* This will remove all child netdev(s) */
339	wwan_unregister_ops(&dev->dev);
340
341	/* Make sure that there is no pending deletion work */
342	if (current_work() != &dev->del_work)
343		cancel_work_sync(&dev->del_work);
344
345	device_unregister(&dev->dev);
346	/* Memory will be freed in the device release callback */
347}
348
349static void wwan_hwsim_dev_del_work(struct work_struct *work)
350{
351	struct wwan_hwsim_dev *dev = container_of(work, typeof(*dev), del_work);
352
353	spin_lock(&wwan_hwsim_devs_lock);
354	if (list_empty(&dev->list)) {
355		/* Someone else deleting device at the moment */
356		spin_unlock(&wwan_hwsim_devs_lock);
357		return;
358	}
359	list_del_init(&dev->list);
360	spin_unlock(&wwan_hwsim_devs_lock);
361
362	wwan_hwsim_dev_del(dev);
363}
364
365static ssize_t wwan_hwsim_debugfs_portdestroy_write(struct file *file,
366						    const char __user *usrbuf,
367						    size_t count, loff_t *ppos)
368{
369	struct wwan_hwsim_port *port = file->private_data;
370
371	/* We can not delete port here since it will cause a deadlock due to
372	 * waiting this callback to finish in the debugfs_remove() call. So,
373	 * use workqueue.
374	 */
375	queue_work(wwan_wq, &port->del_work);
376
377	return count;
378}
379
380static const struct file_operations wwan_hwsim_debugfs_portdestroy_fops = {
381	.write = wwan_hwsim_debugfs_portdestroy_write,
382	.open = simple_open,
383	.llseek = noop_llseek,
384};
385
386static ssize_t wwan_hwsim_debugfs_portcreate_write(struct file *file,
387						   const char __user *usrbuf,
388						   size_t count, loff_t *ppos)
389{
390	struct wwan_hwsim_dev *dev = file->private_data;
391	struct wwan_hwsim_port *port;
392
393	port = wwan_hwsim_port_new(dev);
394	if (IS_ERR(port))
395		return PTR_ERR(port);
396
397	spin_lock(&dev->ports_lock);
398	list_add_tail(&port->list, &dev->ports);
399	spin_unlock(&dev->ports_lock);
400
401	return count;
402}
403
404static const struct file_operations wwan_hwsim_debugfs_portcreate_fops = {
405	.write = wwan_hwsim_debugfs_portcreate_write,
406	.open = simple_open,
407	.llseek = noop_llseek,
408};
409
410static ssize_t wwan_hwsim_debugfs_devdestroy_write(struct file *file,
411						   const char __user *usrbuf,
412						   size_t count, loff_t *ppos)
413{
414	struct wwan_hwsim_dev *dev = file->private_data;
415
416	/* We can not delete device here since it will cause a deadlock due to
417	 * waiting this callback to finish in the debugfs_remove() call. So,
418	 * use workqueue.
419	 */
420	queue_work(wwan_wq, &dev->del_work);
421
422	return count;
423}
424
425static const struct file_operations wwan_hwsim_debugfs_devdestroy_fops = {
426	.write = wwan_hwsim_debugfs_devdestroy_write,
427	.open = simple_open,
428	.llseek = noop_llseek,
429};
430
431static ssize_t wwan_hwsim_debugfs_devcreate_write(struct file *file,
432						  const char __user *usrbuf,
433						  size_t count, loff_t *ppos)
434{
435	struct wwan_hwsim_dev *dev;
436
437	dev = wwan_hwsim_dev_new();
438	if (IS_ERR(dev))
439		return PTR_ERR(dev);
440
441	spin_lock(&wwan_hwsim_devs_lock);
442	list_add_tail(&dev->list, &wwan_hwsim_devs);
443	spin_unlock(&wwan_hwsim_devs_lock);
444
445	return count;
446}
447
448static const struct file_operations wwan_hwsim_debugfs_devcreate_fops = {
449	.write = wwan_hwsim_debugfs_devcreate_write,
450	.open = simple_open,
451	.llseek = noop_llseek,
452};
453
454static int __init wwan_hwsim_init_devs(void)
455{
456	struct wwan_hwsim_dev *dev;
457	int i, j;
458
459	for (i = 0; i < wwan_hwsim_devsnum; ++i) {
460		dev = wwan_hwsim_dev_new();
461		if (IS_ERR(dev))
462			return PTR_ERR(dev);
463
464		spin_lock(&wwan_hwsim_devs_lock);
465		list_add_tail(&dev->list, &wwan_hwsim_devs);
466		spin_unlock(&wwan_hwsim_devs_lock);
467
468		/* Create a couple of ports per each device to accelerate
469		 * the simulator readiness time.
470		 */
471		for (j = 0; j < 2; ++j) {
472			struct wwan_hwsim_port *port;
473
474			port = wwan_hwsim_port_new(dev);
475			if (IS_ERR(port))
476				return PTR_ERR(port);
477
478			spin_lock(&dev->ports_lock);
479			list_add_tail(&port->list, &dev->ports);
480			spin_unlock(&dev->ports_lock);
481		}
482	}
483
484	return 0;
485}
486
487static void wwan_hwsim_free_devs(void)
488{
489	struct wwan_hwsim_dev *dev;
490
491	spin_lock(&wwan_hwsim_devs_lock);
492	while (!list_empty(&wwan_hwsim_devs)) {
493		dev = list_first_entry(&wwan_hwsim_devs, struct wwan_hwsim_dev,
494				       list);
495		list_del_init(&dev->list);
496		spin_unlock(&wwan_hwsim_devs_lock);
497		wwan_hwsim_dev_del(dev);
498		spin_lock(&wwan_hwsim_devs_lock);
499	}
500	spin_unlock(&wwan_hwsim_devs_lock);
501}
502
503static int __init wwan_hwsim_init(void)
504{
505	int err;
506
507	if (wwan_hwsim_devsnum < 0 || wwan_hwsim_devsnum > 128)
508		return -EINVAL;
509
510	wwan_wq = alloc_workqueue("wwan_wq", 0, 0);
511	if (!wwan_wq)
512		return -ENOMEM;
513
514	wwan_hwsim_class = class_create("wwan_hwsim");
515	if (IS_ERR(wwan_hwsim_class)) {
516		err = PTR_ERR(wwan_hwsim_class);
517		goto err_wq_destroy;
518	}
519
520	wwan_hwsim_debugfs_topdir = debugfs_create_dir("wwan_hwsim", NULL);
521	wwan_hwsim_debugfs_devcreate =
522			debugfs_create_file("devcreate", 0200,
523					    wwan_hwsim_debugfs_topdir, NULL,
524					    &wwan_hwsim_debugfs_devcreate_fops);
525
526	err = wwan_hwsim_init_devs();
527	if (err)
528		goto err_clean_devs;
529
530	return 0;
531
532err_clean_devs:
533	debugfs_remove(wwan_hwsim_debugfs_devcreate);	/* Avoid new devs */
534	wwan_hwsim_free_devs();
535	flush_workqueue(wwan_wq);	/* Wait deletion works completion */
536	debugfs_remove(wwan_hwsim_debugfs_topdir);
537	class_destroy(wwan_hwsim_class);
538err_wq_destroy:
539	destroy_workqueue(wwan_wq);
540
541	return err;
542}
543
544static void __exit wwan_hwsim_exit(void)
545{
546	debugfs_remove(wwan_hwsim_debugfs_devcreate);	/* Avoid new devs */
547	wwan_hwsim_free_devs();
548	flush_workqueue(wwan_wq);	/* Wait deletion works completion */
549	debugfs_remove(wwan_hwsim_debugfs_topdir);
550	class_destroy(wwan_hwsim_class);
551	destroy_workqueue(wwan_wq);
552}
553
554module_init(wwan_hwsim_init);
555module_exit(wwan_hwsim_exit);
556
557MODULE_AUTHOR("Sergey Ryazanov");
558MODULE_DESCRIPTION("Device simulator for WWAN framework");
559MODULE_LICENSE("GPL");
v5.14.15
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * WWAN device simulator for WWAN framework testing.
  4 *
  5 * Copyright (c) 2021, Sergey Ryazanov <ryazanov.s.a@gmail.com>
  6 */
  7
  8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  9
 10#include <linux/kernel.h>
 11#include <linux/module.h>
 12#include <linux/slab.h>
 13#include <linux/device.h>
 14#include <linux/spinlock.h>
 15#include <linux/list.h>
 16#include <linux/skbuff.h>
 17#include <linux/netdevice.h>
 18#include <linux/wwan.h>
 19#include <linux/debugfs.h>
 20#include <linux/workqueue.h>
 21
 22#include <net/arp.h>
 23
 24static int wwan_hwsim_devsnum = 2;
 25module_param_named(devices, wwan_hwsim_devsnum, int, 0444);
 26MODULE_PARM_DESC(devices, "Number of simulated devices");
 27
 28static struct class *wwan_hwsim_class;
 29
 30static struct dentry *wwan_hwsim_debugfs_topdir;
 31static struct dentry *wwan_hwsim_debugfs_devcreate;
 32
 33static DEFINE_SPINLOCK(wwan_hwsim_devs_lock);
 34static LIST_HEAD(wwan_hwsim_devs);
 35static unsigned int wwan_hwsim_dev_idx;
 
 36
 37struct wwan_hwsim_dev {
 38	struct list_head list;
 39	unsigned int id;
 40	struct device dev;
 41	struct work_struct del_work;
 42	struct dentry *debugfs_topdir;
 43	struct dentry *debugfs_portcreate;
 44	spinlock_t ports_lock;	/* Serialize ports creation/deletion */
 45	unsigned int port_idx;
 46	struct list_head ports;
 47};
 48
 49struct wwan_hwsim_port {
 50	struct list_head list;
 51	unsigned int id;
 52	struct wwan_hwsim_dev *dev;
 53	struct wwan_port *wwan;
 54	struct work_struct del_work;
 55	struct dentry *debugfs_topdir;
 56	enum {			/* AT command parser state */
 57		AT_PARSER_WAIT_A,
 58		AT_PARSER_WAIT_T,
 59		AT_PARSER_WAIT_TERM,
 60		AT_PARSER_SKIP_LINE,
 61	} pstate;
 62};
 63
 64static const struct file_operations wwan_hwsim_debugfs_portdestroy_fops;
 65static const struct file_operations wwan_hwsim_debugfs_portcreate_fops;
 66static const struct file_operations wwan_hwsim_debugfs_devdestroy_fops;
 67static void wwan_hwsim_port_del_work(struct work_struct *work);
 68static void wwan_hwsim_dev_del_work(struct work_struct *work);
 69
 70static netdev_tx_t wwan_hwsim_netdev_xmit(struct sk_buff *skb,
 71					  struct net_device *ndev)
 72{
 73	ndev->stats.tx_packets++;
 74	ndev->stats.tx_bytes += skb->len;
 75	consume_skb(skb);
 76	return NETDEV_TX_OK;
 77}
 78
 79static const struct net_device_ops wwan_hwsim_netdev_ops = {
 80	.ndo_start_xmit = wwan_hwsim_netdev_xmit,
 81};
 82
 83static void wwan_hwsim_netdev_setup(struct net_device *ndev)
 84{
 85	ndev->netdev_ops = &wwan_hwsim_netdev_ops;
 86	ndev->needs_free_netdev = true;
 87
 88	ndev->mtu = ETH_DATA_LEN;
 89	ndev->min_mtu = ETH_MIN_MTU;
 90	ndev->max_mtu = ETH_MAX_MTU;
 91
 92	ndev->type = ARPHRD_NONE;
 93	ndev->flags = IFF_POINTOPOINT | IFF_NOARP;
 94}
 95
 96static const struct wwan_ops wwan_hwsim_wwan_rtnl_ops = {
 97	.priv_size = 0,			/* No private data */
 98	.setup = wwan_hwsim_netdev_setup,
 99};
100
101static int wwan_hwsim_port_start(struct wwan_port *wport)
102{
103	struct wwan_hwsim_port *port = wwan_port_get_drvdata(wport);
104
105	port->pstate = AT_PARSER_WAIT_A;
106
107	return 0;
108}
109
110static void wwan_hwsim_port_stop(struct wwan_port *wport)
111{
112}
113
114/* Implements a minimalistic AT commands parser that echo input back and
115 * reply with 'OK' to each input command. See AT command protocol details in the
116 * ITU-T V.250 recomendations document.
117 *
118 * Be aware that this processor is not fully V.250 compliant.
119 */
120static int wwan_hwsim_port_tx(struct wwan_port *wport, struct sk_buff *in)
121{
122	struct wwan_hwsim_port *port = wwan_port_get_drvdata(wport);
123	struct sk_buff *out;
124	int i, n, s;
125
126	/* Estimate a max possible number of commands by counting the number of
127	 * termination chars (S3 param, CR by default). And then allocate the
128	 * output buffer that will be enough to fit the echo and result codes of
129	 * all commands.
130	 */
131	for (i = 0, n = 0; i < in->len; ++i)
132		if (in->data[i] == '\r')
133			n++;
134	n = in->len + n * (2 + 2 + 2);	/* Output buffer size */
135	out = alloc_skb(n, GFP_KERNEL);
136	if (!out)
137		return -ENOMEM;
138
139	for (i = 0, s = 0; i < in->len; ++i) {
140		char c = in->data[i];
141
142		if (port->pstate == AT_PARSER_WAIT_A) {
143			if (c == 'A' || c == 'a')
144				port->pstate = AT_PARSER_WAIT_T;
145			else if (c != '\n')	/* Ignore formating char */
146				port->pstate = AT_PARSER_SKIP_LINE;
147		} else if (port->pstate == AT_PARSER_WAIT_T) {
148			if (c == 'T' || c == 't')
149				port->pstate = AT_PARSER_WAIT_TERM;
150			else
151				port->pstate = AT_PARSER_SKIP_LINE;
152		} else if (port->pstate == AT_PARSER_WAIT_TERM) {
153			if (c != '\r')
154				continue;
155			/* Consume the trailing formatting char as well */
156			if ((i + 1) < in->len && in->data[i + 1] == '\n')
157				i++;
158			n = i - s + 1;
159			memcpy(skb_put(out, n), &in->data[s], n);/* Echo */
160			memcpy(skb_put(out, 6), "\r\nOK\r\n", 6);
161			s = i + 1;
162			port->pstate = AT_PARSER_WAIT_A;
163		} else if (port->pstate == AT_PARSER_SKIP_LINE) {
164			if (c != '\r')
165				continue;
166			port->pstate = AT_PARSER_WAIT_A;
167		}
168	}
169
170	if (i > s) {
171		/* Echo the processed portion of a not yet completed command */
172		n = i - s;
173		memcpy(skb_put(out, n), &in->data[s], n);
174	}
175
176	consume_skb(in);
177
178	wwan_port_rx(wport, out);
179
180	return 0;
181}
182
183static const struct wwan_port_ops wwan_hwsim_port_ops = {
184	.start = wwan_hwsim_port_start,
185	.stop = wwan_hwsim_port_stop,
186	.tx = wwan_hwsim_port_tx,
187};
188
189static struct wwan_hwsim_port *wwan_hwsim_port_new(struct wwan_hwsim_dev *dev)
190{
191	struct wwan_hwsim_port *port;
192	char name[0x10];
193	int err;
194
195	port = kzalloc(sizeof(*port), GFP_KERNEL);
196	if (!port)
197		return ERR_PTR(-ENOMEM);
198
199	port->dev = dev;
200
201	spin_lock(&dev->ports_lock);
202	port->id = dev->port_idx++;
203	spin_unlock(&dev->ports_lock);
204
205	port->wwan = wwan_create_port(&dev->dev, WWAN_PORT_AT,
206				      &wwan_hwsim_port_ops,
207				      port);
208	if (IS_ERR(port->wwan)) {
209		err = PTR_ERR(port->wwan);
210		goto err_free_port;
211	}
212
213	INIT_WORK(&port->del_work, wwan_hwsim_port_del_work);
214
215	snprintf(name, sizeof(name), "port%u", port->id);
216	port->debugfs_topdir = debugfs_create_dir(name, dev->debugfs_topdir);
217	debugfs_create_file("destroy", 0200, port->debugfs_topdir, port,
218			    &wwan_hwsim_debugfs_portdestroy_fops);
219
220	return port;
221
222err_free_port:
223	kfree(port);
224
225	return ERR_PTR(err);
226}
227
228static void wwan_hwsim_port_del(struct wwan_hwsim_port *port)
229{
230	debugfs_remove(port->debugfs_topdir);
231
232	/* Make sure that there is no pending deletion work */
233	if (current_work() != &port->del_work)
234		cancel_work_sync(&port->del_work);
235
236	wwan_remove_port(port->wwan);
237	kfree(port);
238}
239
240static void wwan_hwsim_port_del_work(struct work_struct *work)
241{
242	struct wwan_hwsim_port *port =
243				container_of(work, typeof(*port), del_work);
244	struct wwan_hwsim_dev *dev = port->dev;
245
246	spin_lock(&dev->ports_lock);
247	if (list_empty(&port->list)) {
248		/* Someone else deleting port at the moment */
249		spin_unlock(&dev->ports_lock);
250		return;
251	}
252	list_del_init(&port->list);
253	spin_unlock(&dev->ports_lock);
254
255	wwan_hwsim_port_del(port);
256}
257
258static void wwan_hwsim_dev_release(struct device *sysdev)
259{
260	struct wwan_hwsim_dev *dev = container_of(sysdev, typeof(*dev), dev);
261
262	kfree(dev);
263}
264
265static struct wwan_hwsim_dev *wwan_hwsim_dev_new(void)
266{
267	struct wwan_hwsim_dev *dev;
268	int err;
269
270	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
271	if (!dev)
272		return ERR_PTR(-ENOMEM);
273
274	spin_lock(&wwan_hwsim_devs_lock);
275	dev->id = wwan_hwsim_dev_idx++;
276	spin_unlock(&wwan_hwsim_devs_lock);
277
278	dev->dev.release = wwan_hwsim_dev_release;
279	dev->dev.class = wwan_hwsim_class;
280	dev_set_name(&dev->dev, "hwsim%u", dev->id);
281
282	spin_lock_init(&dev->ports_lock);
283	INIT_LIST_HEAD(&dev->ports);
284
285	err = device_register(&dev->dev);
286	if (err)
287		goto err_free_dev;
288
289	INIT_WORK(&dev->del_work, wwan_hwsim_dev_del_work);
290
291	err = wwan_register_ops(&dev->dev, &wwan_hwsim_wwan_rtnl_ops, dev, 1);
292	if (err)
293		goto err_unreg_dev;
294
295	dev->debugfs_topdir = debugfs_create_dir(dev_name(&dev->dev),
296						 wwan_hwsim_debugfs_topdir);
297	debugfs_create_file("destroy", 0200, dev->debugfs_topdir, dev,
298			    &wwan_hwsim_debugfs_devdestroy_fops);
299	dev->debugfs_portcreate =
300		debugfs_create_file("portcreate", 0200,
301				    dev->debugfs_topdir, dev,
302				    &wwan_hwsim_debugfs_portcreate_fops);
303
304	return dev;
305
306err_unreg_dev:
307	device_unregister(&dev->dev);
308	/* Memory will be freed in the device release callback */
309
310	return ERR_PTR(err);
311
312err_free_dev:
313	kfree(dev);
314
315	return ERR_PTR(err);
316}
317
318static void wwan_hwsim_dev_del(struct wwan_hwsim_dev *dev)
319{
320	debugfs_remove(dev->debugfs_portcreate);	/* Avoid new ports */
321
322	spin_lock(&dev->ports_lock);
323	while (!list_empty(&dev->ports)) {
324		struct wwan_hwsim_port *port;
325
326		port = list_first_entry(&dev->ports, struct wwan_hwsim_port,
327					list);
328		list_del_init(&port->list);
329		spin_unlock(&dev->ports_lock);
330		wwan_hwsim_port_del(port);
331		spin_lock(&dev->ports_lock);
332	}
333	spin_unlock(&dev->ports_lock);
334
335	debugfs_remove(dev->debugfs_topdir);
336
337	/* This will remove all child netdev(s) */
338	wwan_unregister_ops(&dev->dev);
339
340	/* Make sure that there is no pending deletion work */
341	if (current_work() != &dev->del_work)
342		cancel_work_sync(&dev->del_work);
343
344	device_unregister(&dev->dev);
345	/* Memory will be freed in the device release callback */
346}
347
348static void wwan_hwsim_dev_del_work(struct work_struct *work)
349{
350	struct wwan_hwsim_dev *dev = container_of(work, typeof(*dev), del_work);
351
352	spin_lock(&wwan_hwsim_devs_lock);
353	if (list_empty(&dev->list)) {
354		/* Someone else deleting device at the moment */
355		spin_unlock(&wwan_hwsim_devs_lock);
356		return;
357	}
358	list_del_init(&dev->list);
359	spin_unlock(&wwan_hwsim_devs_lock);
360
361	wwan_hwsim_dev_del(dev);
362}
363
364static ssize_t wwan_hwsim_debugfs_portdestroy_write(struct file *file,
365						    const char __user *usrbuf,
366						    size_t count, loff_t *ppos)
367{
368	struct wwan_hwsim_port *port = file->private_data;
369
370	/* We can not delete port here since it will cause a deadlock due to
371	 * waiting this callback to finish in the debugfs_remove() call. So,
372	 * use workqueue.
373	 */
374	schedule_work(&port->del_work);
375
376	return count;
377}
378
379static const struct file_operations wwan_hwsim_debugfs_portdestroy_fops = {
380	.write = wwan_hwsim_debugfs_portdestroy_write,
381	.open = simple_open,
382	.llseek = noop_llseek,
383};
384
385static ssize_t wwan_hwsim_debugfs_portcreate_write(struct file *file,
386						   const char __user *usrbuf,
387						   size_t count, loff_t *ppos)
388{
389	struct wwan_hwsim_dev *dev = file->private_data;
390	struct wwan_hwsim_port *port;
391
392	port = wwan_hwsim_port_new(dev);
393	if (IS_ERR(port))
394		return PTR_ERR(port);
395
396	spin_lock(&dev->ports_lock);
397	list_add_tail(&port->list, &dev->ports);
398	spin_unlock(&dev->ports_lock);
399
400	return count;
401}
402
403static const struct file_operations wwan_hwsim_debugfs_portcreate_fops = {
404	.write = wwan_hwsim_debugfs_portcreate_write,
405	.open = simple_open,
406	.llseek = noop_llseek,
407};
408
409static ssize_t wwan_hwsim_debugfs_devdestroy_write(struct file *file,
410						   const char __user *usrbuf,
411						   size_t count, loff_t *ppos)
412{
413	struct wwan_hwsim_dev *dev = file->private_data;
414
415	/* We can not delete device here since it will cause a deadlock due to
416	 * waiting this callback to finish in the debugfs_remove() call. So,
417	 * use workqueue.
418	 */
419	schedule_work(&dev->del_work);
420
421	return count;
422}
423
424static const struct file_operations wwan_hwsim_debugfs_devdestroy_fops = {
425	.write = wwan_hwsim_debugfs_devdestroy_write,
426	.open = simple_open,
427	.llseek = noop_llseek,
428};
429
430static ssize_t wwan_hwsim_debugfs_devcreate_write(struct file *file,
431						  const char __user *usrbuf,
432						  size_t count, loff_t *ppos)
433{
434	struct wwan_hwsim_dev *dev;
435
436	dev = wwan_hwsim_dev_new();
437	if (IS_ERR(dev))
438		return PTR_ERR(dev);
439
440	spin_lock(&wwan_hwsim_devs_lock);
441	list_add_tail(&dev->list, &wwan_hwsim_devs);
442	spin_unlock(&wwan_hwsim_devs_lock);
443
444	return count;
445}
446
447static const struct file_operations wwan_hwsim_debugfs_devcreate_fops = {
448	.write = wwan_hwsim_debugfs_devcreate_write,
449	.open = simple_open,
450	.llseek = noop_llseek,
451};
452
453static int __init wwan_hwsim_init_devs(void)
454{
455	struct wwan_hwsim_dev *dev;
456	int i, j;
457
458	for (i = 0; i < wwan_hwsim_devsnum; ++i) {
459		dev = wwan_hwsim_dev_new();
460		if (IS_ERR(dev))
461			return PTR_ERR(dev);
462
463		spin_lock(&wwan_hwsim_devs_lock);
464		list_add_tail(&dev->list, &wwan_hwsim_devs);
465		spin_unlock(&wwan_hwsim_devs_lock);
466
467		/* Create a couple of ports per each device to accelerate
468		 * the simulator readiness time.
469		 */
470		for (j = 0; j < 2; ++j) {
471			struct wwan_hwsim_port *port;
472
473			port = wwan_hwsim_port_new(dev);
474			if (IS_ERR(port))
475				return PTR_ERR(port);
476
477			spin_lock(&dev->ports_lock);
478			list_add_tail(&port->list, &dev->ports);
479			spin_unlock(&dev->ports_lock);
480		}
481	}
482
483	return 0;
484}
485
486static void wwan_hwsim_free_devs(void)
487{
488	struct wwan_hwsim_dev *dev;
489
490	spin_lock(&wwan_hwsim_devs_lock);
491	while (!list_empty(&wwan_hwsim_devs)) {
492		dev = list_first_entry(&wwan_hwsim_devs, struct wwan_hwsim_dev,
493				       list);
494		list_del_init(&dev->list);
495		spin_unlock(&wwan_hwsim_devs_lock);
496		wwan_hwsim_dev_del(dev);
497		spin_lock(&wwan_hwsim_devs_lock);
498	}
499	spin_unlock(&wwan_hwsim_devs_lock);
500}
501
502static int __init wwan_hwsim_init(void)
503{
504	int err;
505
506	if (wwan_hwsim_devsnum < 0 || wwan_hwsim_devsnum > 128)
507		return -EINVAL;
508
509	wwan_hwsim_class = class_create(THIS_MODULE, "wwan_hwsim");
510	if (IS_ERR(wwan_hwsim_class))
511		return PTR_ERR(wwan_hwsim_class);
 
 
 
 
 
 
512
513	wwan_hwsim_debugfs_topdir = debugfs_create_dir("wwan_hwsim", NULL);
514	wwan_hwsim_debugfs_devcreate =
515			debugfs_create_file("devcreate", 0200,
516					    wwan_hwsim_debugfs_topdir, NULL,
517					    &wwan_hwsim_debugfs_devcreate_fops);
518
519	err = wwan_hwsim_init_devs();
520	if (err)
521		goto err_clean_devs;
522
523	return 0;
524
525err_clean_devs:
 
526	wwan_hwsim_free_devs();
 
527	debugfs_remove(wwan_hwsim_debugfs_topdir);
528	class_destroy(wwan_hwsim_class);
 
 
529
530	return err;
531}
532
533static void __exit wwan_hwsim_exit(void)
534{
535	debugfs_remove(wwan_hwsim_debugfs_devcreate);	/* Avoid new devs */
536	wwan_hwsim_free_devs();
537	flush_scheduled_work();		/* Wait deletion works completion */
538	debugfs_remove(wwan_hwsim_debugfs_topdir);
539	class_destroy(wwan_hwsim_class);
 
540}
541
542module_init(wwan_hwsim_init);
543module_exit(wwan_hwsim_exit);
544
545MODULE_AUTHOR("Sergey Ryazanov");
546MODULE_DESCRIPTION("Device simulator for WWAN framework");
547MODULE_LICENSE("GPL");