# HG changeset patch # User Florian Pose # Date 1255621133 -7200 # Node ID 26ac1c6111007a0f25b75f6d131971ef0edb015b # Parent 49430a3fe73df54b5b65b773c91fe69aa002b063 Sending via generic device works. diff -r 49430a3fe73d -r 26ac1c611100 devices/generic.c --- a/devices/generic.c Tue Oct 13 17:56:32 2009 +0200 +++ b/devices/generic.c Thu Oct 15 17:38:53 2009 +0200 @@ -45,6 +45,8 @@ #define PFX "ec_generic: " +#define ETH_P_ETHERCAT 0x88A4 + /*****************************************************************************/ int __init ec_gen_init_module(void); @@ -66,9 +68,7 @@ typedef struct { struct list_head list; struct net_device *netdev; -#if 0 - struct net_device *real_netdev; -#endif + struct socket *socket; ec_device_t *ecdev; } ec_gen_device_t; @@ -130,9 +130,7 @@ char null = 0x00; dev->ecdev = NULL; -#if 0 - dev->real_netdev = real_netdev; -#endif + dev->socket = NULL; dev->netdev = alloc_netdev(sizeof(ec_gen_device_t *), &null, ether_setup); if (!dev->netdev) { @@ -158,25 +156,69 @@ ecdev_close(dev->ecdev); ecdev_withdraw(dev->ecdev); } + if (dev->socket) { + sock_release(dev->socket); + } free_netdev(dev->netdev); } /*****************************************************************************/ +/** Creates a network socket. + */ +int ec_gen_device_create_socket( + ec_gen_device_t *dev, + struct net_device *real_netdev + ) +{ + int ret; + struct sockaddr_ll sa; + + ret = sock_create_kern(PF_PACKET, SOCK_RAW, htons(ETH_P_ETHERCAT), &dev->socket); + if (ret) { + printk(KERN_ERR PFX "Failed to create socket.\n"); + return ret; + } + + printk(KERN_ERR PFX "Binding socket to interface %i (%s).\n", + real_netdev->ifindex, real_netdev->name); + + memset(&sa, 0x00, sizeof(sa)); + sa.sll_family = AF_PACKET; + sa.sll_protocol = htons(ETH_P_ETHERCAT); + sa.sll_ifindex = real_netdev->ifindex; + ret = kernel_bind(dev->socket, (struct sockaddr *) &sa, sizeof(sa)); + if (ret) { + printk(KERN_ERR PFX "Failed to bind() socket to interface.\n"); + sock_release(dev->socket); + dev->socket = NULL; + return ret; + } + + return 0; +} + +/*****************************************************************************/ + /** Offer generic device to master. */ int ec_gen_device_offer( - ec_gen_device_t *dev + ec_gen_device_t *dev, + struct net_device *real_netdev ) { int ret = 0; dev->ecdev = ecdev_offer(dev->netdev, ec_gen_poll, THIS_MODULE); if (dev->ecdev) { - if (ecdev_open(dev->ecdev)) { + if (ec_gen_device_create_socket(dev, real_netdev)) { + ecdev_withdraw(dev->ecdev); + dev->ecdev = NULL; + } else if (ecdev_open(dev->ecdev)) { ecdev_withdraw(dev->ecdev); dev->ecdev = NULL; } else { + ecdev_set_link(dev->ecdev, 1); // FIXME ret = 1; } } @@ -192,17 +234,7 @@ ec_gen_device_t *dev ) { - int ret = 0; - -#if 0 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) - ret = dev->real_netdev->netdev_ops->ndo_open(dev->real_netdev); -#else - ret = dev->real_netdev->open(dev->real_netdev); -#endif -#endif - - return ret; + return 0; } /*****************************************************************************/ @@ -213,17 +245,7 @@ ec_gen_device_t *dev ) { - int ret = 0; - -#if 0 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) - ret = dev->real_netdev->netdev_ops->ndo_stop(dev->real_netdev); -#else - ret = dev->real_netdev->stop(dev->real_netdev); -#endif -#endif - - return ret; + return 0; } /*****************************************************************************/ @@ -233,7 +255,18 @@ struct sk_buff *skb ) { - return 0; + struct msghdr msg; + struct kvec iov; + size_t len = skb->len; + int ret; + + iov.iov_base = skb->data; + iov.iov_len = len; + memset(&msg, 0, sizeof(msg)); + + ret = kernel_sendmsg(dev->socket, &msg, &iov, 1, len); + + return ret == len ? NETDEV_TX_OK : NETDEV_TX_BUSY; } /*****************************************************************************/ @@ -258,7 +291,7 @@ return ret; } - if (ec_gen_device_offer(gendev)) { + if (ec_gen_device_offer(gendev, netdev)) { list_add_tail(&gendev->list, &generic_devices); } else { ec_gen_device_clear(gendev);