0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0009
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/slab.h>
0013 #include <linux/device.h>
0014 #include <linux/spinlock.h>
0015 #include <linux/list.h>
0016 #include <linux/skbuff.h>
0017 #include <linux/netdevice.h>
0018 #include <linux/wwan.h>
0019 #include <linux/debugfs.h>
0020 #include <linux/workqueue.h>
0021
0022 #include <net/arp.h>
0023
0024 static int wwan_hwsim_devsnum = 2;
0025 module_param_named(devices, wwan_hwsim_devsnum, int, 0444);
0026 MODULE_PARM_DESC(devices, "Number of simulated devices");
0027
0028 static struct class *wwan_hwsim_class;
0029
0030 static struct dentry *wwan_hwsim_debugfs_topdir;
0031 static struct dentry *wwan_hwsim_debugfs_devcreate;
0032
0033 static DEFINE_SPINLOCK(wwan_hwsim_devs_lock);
0034 static LIST_HEAD(wwan_hwsim_devs);
0035 static unsigned int wwan_hwsim_dev_idx;
0036 static struct workqueue_struct *wwan_wq;
0037
0038 struct wwan_hwsim_dev {
0039 struct list_head list;
0040 unsigned int id;
0041 struct device dev;
0042 struct work_struct del_work;
0043 struct dentry *debugfs_topdir;
0044 struct dentry *debugfs_portcreate;
0045 spinlock_t ports_lock;
0046 unsigned int port_idx;
0047 struct list_head ports;
0048 };
0049
0050 struct wwan_hwsim_port {
0051 struct list_head list;
0052 unsigned int id;
0053 struct wwan_hwsim_dev *dev;
0054 struct wwan_port *wwan;
0055 struct work_struct del_work;
0056 struct dentry *debugfs_topdir;
0057 enum {
0058 AT_PARSER_WAIT_A,
0059 AT_PARSER_WAIT_T,
0060 AT_PARSER_WAIT_TERM,
0061 AT_PARSER_SKIP_LINE,
0062 } pstate;
0063 };
0064
0065 static const struct file_operations wwan_hwsim_debugfs_portdestroy_fops;
0066 static const struct file_operations wwan_hwsim_debugfs_portcreate_fops;
0067 static const struct file_operations wwan_hwsim_debugfs_devdestroy_fops;
0068 static void wwan_hwsim_port_del_work(struct work_struct *work);
0069 static void wwan_hwsim_dev_del_work(struct work_struct *work);
0070
0071 static netdev_tx_t wwan_hwsim_netdev_xmit(struct sk_buff *skb,
0072 struct net_device *ndev)
0073 {
0074 ndev->stats.tx_packets++;
0075 ndev->stats.tx_bytes += skb->len;
0076 consume_skb(skb);
0077 return NETDEV_TX_OK;
0078 }
0079
0080 static const struct net_device_ops wwan_hwsim_netdev_ops = {
0081 .ndo_start_xmit = wwan_hwsim_netdev_xmit,
0082 };
0083
0084 static void wwan_hwsim_netdev_setup(struct net_device *ndev)
0085 {
0086 ndev->netdev_ops = &wwan_hwsim_netdev_ops;
0087 ndev->needs_free_netdev = true;
0088
0089 ndev->mtu = ETH_DATA_LEN;
0090 ndev->min_mtu = ETH_MIN_MTU;
0091 ndev->max_mtu = ETH_MAX_MTU;
0092
0093 ndev->type = ARPHRD_NONE;
0094 ndev->flags = IFF_POINTOPOINT | IFF_NOARP;
0095 }
0096
0097 static const struct wwan_ops wwan_hwsim_wwan_rtnl_ops = {
0098 .priv_size = 0,
0099 .setup = wwan_hwsim_netdev_setup,
0100 };
0101
0102 static int wwan_hwsim_port_start(struct wwan_port *wport)
0103 {
0104 struct wwan_hwsim_port *port = wwan_port_get_drvdata(wport);
0105
0106 port->pstate = AT_PARSER_WAIT_A;
0107
0108 return 0;
0109 }
0110
0111 static void wwan_hwsim_port_stop(struct wwan_port *wport)
0112 {
0113 }
0114
0115
0116
0117
0118
0119
0120
0121 static int wwan_hwsim_port_tx(struct wwan_port *wport, struct sk_buff *in)
0122 {
0123 struct wwan_hwsim_port *port = wwan_port_get_drvdata(wport);
0124 struct sk_buff *out;
0125 int i, n, s;
0126
0127
0128
0129
0130
0131
0132 for (i = 0, n = 0; i < in->len; ++i)
0133 if (in->data[i] == '\r')
0134 n++;
0135 n = in->len + n * (2 + 2 + 2);
0136 out = alloc_skb(n, GFP_KERNEL);
0137 if (!out)
0138 return -ENOMEM;
0139
0140 for (i = 0, s = 0; i < in->len; ++i) {
0141 char c = in->data[i];
0142
0143 if (port->pstate == AT_PARSER_WAIT_A) {
0144 if (c == 'A' || c == 'a')
0145 port->pstate = AT_PARSER_WAIT_T;
0146 else if (c != '\n')
0147 port->pstate = AT_PARSER_SKIP_LINE;
0148 } else if (port->pstate == AT_PARSER_WAIT_T) {
0149 if (c == 'T' || c == 't')
0150 port->pstate = AT_PARSER_WAIT_TERM;
0151 else
0152 port->pstate = AT_PARSER_SKIP_LINE;
0153 } else if (port->pstate == AT_PARSER_WAIT_TERM) {
0154 if (c != '\r')
0155 continue;
0156
0157 if ((i + 1) < in->len && in->data[i + 1] == '\n')
0158 i++;
0159 n = i - s + 1;
0160 memcpy(skb_put(out, n), &in->data[s], n);
0161 memcpy(skb_put(out, 6), "\r\nOK\r\n", 6);
0162 s = i + 1;
0163 port->pstate = AT_PARSER_WAIT_A;
0164 } else if (port->pstate == AT_PARSER_SKIP_LINE) {
0165 if (c != '\r')
0166 continue;
0167 port->pstate = AT_PARSER_WAIT_A;
0168 }
0169 }
0170
0171 if (i > s) {
0172
0173 n = i - s;
0174 memcpy(skb_put(out, n), &in->data[s], n);
0175 }
0176
0177 consume_skb(in);
0178
0179 wwan_port_rx(wport, out);
0180
0181 return 0;
0182 }
0183
0184 static const struct wwan_port_ops wwan_hwsim_port_ops = {
0185 .start = wwan_hwsim_port_start,
0186 .stop = wwan_hwsim_port_stop,
0187 .tx = wwan_hwsim_port_tx,
0188 };
0189
0190 static struct wwan_hwsim_port *wwan_hwsim_port_new(struct wwan_hwsim_dev *dev)
0191 {
0192 struct wwan_hwsim_port *port;
0193 char name[0x10];
0194 int err;
0195
0196 port = kzalloc(sizeof(*port), GFP_KERNEL);
0197 if (!port)
0198 return ERR_PTR(-ENOMEM);
0199
0200 port->dev = dev;
0201
0202 spin_lock(&dev->ports_lock);
0203 port->id = dev->port_idx++;
0204 spin_unlock(&dev->ports_lock);
0205
0206 port->wwan = wwan_create_port(&dev->dev, WWAN_PORT_AT,
0207 &wwan_hwsim_port_ops,
0208 port);
0209 if (IS_ERR(port->wwan)) {
0210 err = PTR_ERR(port->wwan);
0211 goto err_free_port;
0212 }
0213
0214 INIT_WORK(&port->del_work, wwan_hwsim_port_del_work);
0215
0216 snprintf(name, sizeof(name), "port%u", port->id);
0217 port->debugfs_topdir = debugfs_create_dir(name, dev->debugfs_topdir);
0218 debugfs_create_file("destroy", 0200, port->debugfs_topdir, port,
0219 &wwan_hwsim_debugfs_portdestroy_fops);
0220
0221 return port;
0222
0223 err_free_port:
0224 kfree(port);
0225
0226 return ERR_PTR(err);
0227 }
0228
0229 static void wwan_hwsim_port_del(struct wwan_hwsim_port *port)
0230 {
0231 debugfs_remove(port->debugfs_topdir);
0232
0233
0234 if (current_work() != &port->del_work)
0235 cancel_work_sync(&port->del_work);
0236
0237 wwan_remove_port(port->wwan);
0238 kfree(port);
0239 }
0240
0241 static void wwan_hwsim_port_del_work(struct work_struct *work)
0242 {
0243 struct wwan_hwsim_port *port =
0244 container_of(work, typeof(*port), del_work);
0245 struct wwan_hwsim_dev *dev = port->dev;
0246
0247 spin_lock(&dev->ports_lock);
0248 if (list_empty(&port->list)) {
0249
0250 spin_unlock(&dev->ports_lock);
0251 return;
0252 }
0253 list_del_init(&port->list);
0254 spin_unlock(&dev->ports_lock);
0255
0256 wwan_hwsim_port_del(port);
0257 }
0258
0259 static void wwan_hwsim_dev_release(struct device *sysdev)
0260 {
0261 struct wwan_hwsim_dev *dev = container_of(sysdev, typeof(*dev), dev);
0262
0263 kfree(dev);
0264 }
0265
0266 static struct wwan_hwsim_dev *wwan_hwsim_dev_new(void)
0267 {
0268 struct wwan_hwsim_dev *dev;
0269 int err;
0270
0271 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
0272 if (!dev)
0273 return ERR_PTR(-ENOMEM);
0274
0275 spin_lock(&wwan_hwsim_devs_lock);
0276 dev->id = wwan_hwsim_dev_idx++;
0277 spin_unlock(&wwan_hwsim_devs_lock);
0278
0279 dev->dev.release = wwan_hwsim_dev_release;
0280 dev->dev.class = wwan_hwsim_class;
0281 dev_set_name(&dev->dev, "hwsim%u", dev->id);
0282
0283 spin_lock_init(&dev->ports_lock);
0284 INIT_LIST_HEAD(&dev->ports);
0285
0286 err = device_register(&dev->dev);
0287 if (err)
0288 goto err_free_dev;
0289
0290 INIT_WORK(&dev->del_work, wwan_hwsim_dev_del_work);
0291
0292 err = wwan_register_ops(&dev->dev, &wwan_hwsim_wwan_rtnl_ops, dev, 1);
0293 if (err)
0294 goto err_unreg_dev;
0295
0296 dev->debugfs_topdir = debugfs_create_dir(dev_name(&dev->dev),
0297 wwan_hwsim_debugfs_topdir);
0298 debugfs_create_file("destroy", 0200, dev->debugfs_topdir, dev,
0299 &wwan_hwsim_debugfs_devdestroy_fops);
0300 dev->debugfs_portcreate =
0301 debugfs_create_file("portcreate", 0200,
0302 dev->debugfs_topdir, dev,
0303 &wwan_hwsim_debugfs_portcreate_fops);
0304
0305 return dev;
0306
0307 err_unreg_dev:
0308 device_unregister(&dev->dev);
0309
0310
0311 return ERR_PTR(err);
0312
0313 err_free_dev:
0314 kfree(dev);
0315
0316 return ERR_PTR(err);
0317 }
0318
0319 static void wwan_hwsim_dev_del(struct wwan_hwsim_dev *dev)
0320 {
0321 debugfs_remove(dev->debugfs_portcreate);
0322
0323 spin_lock(&dev->ports_lock);
0324 while (!list_empty(&dev->ports)) {
0325 struct wwan_hwsim_port *port;
0326
0327 port = list_first_entry(&dev->ports, struct wwan_hwsim_port,
0328 list);
0329 list_del_init(&port->list);
0330 spin_unlock(&dev->ports_lock);
0331 wwan_hwsim_port_del(port);
0332 spin_lock(&dev->ports_lock);
0333 }
0334 spin_unlock(&dev->ports_lock);
0335
0336 debugfs_remove(dev->debugfs_topdir);
0337
0338
0339 wwan_unregister_ops(&dev->dev);
0340
0341
0342 if (current_work() != &dev->del_work)
0343 cancel_work_sync(&dev->del_work);
0344
0345 device_unregister(&dev->dev);
0346
0347 }
0348
0349 static void wwan_hwsim_dev_del_work(struct work_struct *work)
0350 {
0351 struct wwan_hwsim_dev *dev = container_of(work, typeof(*dev), del_work);
0352
0353 spin_lock(&wwan_hwsim_devs_lock);
0354 if (list_empty(&dev->list)) {
0355
0356 spin_unlock(&wwan_hwsim_devs_lock);
0357 return;
0358 }
0359 list_del_init(&dev->list);
0360 spin_unlock(&wwan_hwsim_devs_lock);
0361
0362 wwan_hwsim_dev_del(dev);
0363 }
0364
0365 static ssize_t wwan_hwsim_debugfs_portdestroy_write(struct file *file,
0366 const char __user *usrbuf,
0367 size_t count, loff_t *ppos)
0368 {
0369 struct wwan_hwsim_port *port = file->private_data;
0370
0371
0372
0373
0374
0375 queue_work(wwan_wq, &port->del_work);
0376
0377 return count;
0378 }
0379
0380 static const struct file_operations wwan_hwsim_debugfs_portdestroy_fops = {
0381 .write = wwan_hwsim_debugfs_portdestroy_write,
0382 .open = simple_open,
0383 .llseek = noop_llseek,
0384 };
0385
0386 static ssize_t wwan_hwsim_debugfs_portcreate_write(struct file *file,
0387 const char __user *usrbuf,
0388 size_t count, loff_t *ppos)
0389 {
0390 struct wwan_hwsim_dev *dev = file->private_data;
0391 struct wwan_hwsim_port *port;
0392
0393 port = wwan_hwsim_port_new(dev);
0394 if (IS_ERR(port))
0395 return PTR_ERR(port);
0396
0397 spin_lock(&dev->ports_lock);
0398 list_add_tail(&port->list, &dev->ports);
0399 spin_unlock(&dev->ports_lock);
0400
0401 return count;
0402 }
0403
0404 static const struct file_operations wwan_hwsim_debugfs_portcreate_fops = {
0405 .write = wwan_hwsim_debugfs_portcreate_write,
0406 .open = simple_open,
0407 .llseek = noop_llseek,
0408 };
0409
0410 static ssize_t wwan_hwsim_debugfs_devdestroy_write(struct file *file,
0411 const char __user *usrbuf,
0412 size_t count, loff_t *ppos)
0413 {
0414 struct wwan_hwsim_dev *dev = file->private_data;
0415
0416
0417
0418
0419
0420 queue_work(wwan_wq, &dev->del_work);
0421
0422 return count;
0423 }
0424
0425 static const struct file_operations wwan_hwsim_debugfs_devdestroy_fops = {
0426 .write = wwan_hwsim_debugfs_devdestroy_write,
0427 .open = simple_open,
0428 .llseek = noop_llseek,
0429 };
0430
0431 static ssize_t wwan_hwsim_debugfs_devcreate_write(struct file *file,
0432 const char __user *usrbuf,
0433 size_t count, loff_t *ppos)
0434 {
0435 struct wwan_hwsim_dev *dev;
0436
0437 dev = wwan_hwsim_dev_new();
0438 if (IS_ERR(dev))
0439 return PTR_ERR(dev);
0440
0441 spin_lock(&wwan_hwsim_devs_lock);
0442 list_add_tail(&dev->list, &wwan_hwsim_devs);
0443 spin_unlock(&wwan_hwsim_devs_lock);
0444
0445 return count;
0446 }
0447
0448 static const struct file_operations wwan_hwsim_debugfs_devcreate_fops = {
0449 .write = wwan_hwsim_debugfs_devcreate_write,
0450 .open = simple_open,
0451 .llseek = noop_llseek,
0452 };
0453
0454 static int __init wwan_hwsim_init_devs(void)
0455 {
0456 struct wwan_hwsim_dev *dev;
0457 int i, j;
0458
0459 for (i = 0; i < wwan_hwsim_devsnum; ++i) {
0460 dev = wwan_hwsim_dev_new();
0461 if (IS_ERR(dev))
0462 return PTR_ERR(dev);
0463
0464 spin_lock(&wwan_hwsim_devs_lock);
0465 list_add_tail(&dev->list, &wwan_hwsim_devs);
0466 spin_unlock(&wwan_hwsim_devs_lock);
0467
0468
0469
0470
0471 for (j = 0; j < 2; ++j) {
0472 struct wwan_hwsim_port *port;
0473
0474 port = wwan_hwsim_port_new(dev);
0475 if (IS_ERR(port))
0476 return PTR_ERR(port);
0477
0478 spin_lock(&dev->ports_lock);
0479 list_add_tail(&port->list, &dev->ports);
0480 spin_unlock(&dev->ports_lock);
0481 }
0482 }
0483
0484 return 0;
0485 }
0486
0487 static void wwan_hwsim_free_devs(void)
0488 {
0489 struct wwan_hwsim_dev *dev;
0490
0491 spin_lock(&wwan_hwsim_devs_lock);
0492 while (!list_empty(&wwan_hwsim_devs)) {
0493 dev = list_first_entry(&wwan_hwsim_devs, struct wwan_hwsim_dev,
0494 list);
0495 list_del_init(&dev->list);
0496 spin_unlock(&wwan_hwsim_devs_lock);
0497 wwan_hwsim_dev_del(dev);
0498 spin_lock(&wwan_hwsim_devs_lock);
0499 }
0500 spin_unlock(&wwan_hwsim_devs_lock);
0501 }
0502
0503 static int __init wwan_hwsim_init(void)
0504 {
0505 int err;
0506
0507 if (wwan_hwsim_devsnum < 0 || wwan_hwsim_devsnum > 128)
0508 return -EINVAL;
0509
0510 wwan_wq = alloc_workqueue("wwan_wq", 0, 0);
0511 if (!wwan_wq)
0512 return -ENOMEM;
0513
0514 wwan_hwsim_class = class_create(THIS_MODULE, "wwan_hwsim");
0515 if (IS_ERR(wwan_hwsim_class)) {
0516 err = PTR_ERR(wwan_hwsim_class);
0517 goto err_wq_destroy;
0518 }
0519
0520 wwan_hwsim_debugfs_topdir = debugfs_create_dir("wwan_hwsim", NULL);
0521 wwan_hwsim_debugfs_devcreate =
0522 debugfs_create_file("devcreate", 0200,
0523 wwan_hwsim_debugfs_topdir, NULL,
0524 &wwan_hwsim_debugfs_devcreate_fops);
0525
0526 err = wwan_hwsim_init_devs();
0527 if (err)
0528 goto err_clean_devs;
0529
0530 return 0;
0531
0532 err_clean_devs:
0533 debugfs_remove(wwan_hwsim_debugfs_devcreate);
0534 wwan_hwsim_free_devs();
0535 flush_workqueue(wwan_wq);
0536 debugfs_remove(wwan_hwsim_debugfs_topdir);
0537 class_destroy(wwan_hwsim_class);
0538 err_wq_destroy:
0539 destroy_workqueue(wwan_wq);
0540
0541 return err;
0542 }
0543
0544 static void __exit wwan_hwsim_exit(void)
0545 {
0546 debugfs_remove(wwan_hwsim_debugfs_devcreate);
0547 wwan_hwsim_free_devs();
0548 flush_workqueue(wwan_wq);
0549 debugfs_remove(wwan_hwsim_debugfs_topdir);
0550 class_destroy(wwan_hwsim_class);
0551 destroy_workqueue(wwan_wq);
0552 }
0553
0554 module_init(wwan_hwsim_init);
0555 module_exit(wwan_hwsim_exit);
0556
0557 MODULE_AUTHOR("Sergey Ryazanov");
0558 MODULE_DESCRIPTION("Device simulator for WWAN framework");
0559 MODULE_LICENSE("GPL");