When configfs support is added it will be possible to add an unconfigured
interface to the system. This patch adds an interface to u_ether which
makes it possible to create a struct eth_dev filled with default values,
an interface which makes it possible to fill the struct with useful values,
and an interface which makes it possible to read the values set.

Signed-off-by: Andrzej Pietrasiewicz <andrze...@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.p...@samsung.com>
---
 drivers/usb/gadget/u_ether.c |  173 ++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/gadget/u_ether.h |  101 ++++++++++++++++++++++++
 2 files changed, 274 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index de9d84f..f9b17c8 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -719,6 +719,24 @@ static int get_ether_addr(const char *str, u8 *dev_addr)
        return 1;
 }
 
+static int get_ether_addr_str(u8 dev_addr[ETH_ALEN], char *str, int len)
+{
+       char *s;
+
+       if (len < 16)
+               return -EINVAL;
+
+       hex_dump_to_buffer(dev_addr, ETH_ALEN, 16, 1, str, 20, false);
+       s = str;
+       while (*s) {
+               if (*s == ' ')
+                       *s = ':';
+               s++;
+       }
+
+       return strlen(str);
+}
+
 static const struct net_device_ops eth_netdev_ops = {
        .ndo_open               = eth_open,
        .ndo_stop               = eth_stop,
@@ -812,6 +830,161 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g,
 }
 EXPORT_SYMBOL(gether_setup_name);
 
+struct net_device *gether_setup_name_default(const char *netname,
+                                            u8 ethaddr[ETH_ALEN])
+{
+       struct net_device       *net;
+       struct eth_dev          *dev;
+       int                     status;
+
+       net = alloc_etherdev(sizeof(*dev));
+       if (!net)
+               return ERR_PTR(-ENOMEM);
+
+       dev = netdev_priv(net);
+       spin_lock_init(&dev->lock);
+       spin_lock_init(&dev->req_lock);
+       INIT_WORK(&dev->work, eth_work);
+       INIT_LIST_HEAD(&dev->tx_reqs);
+       INIT_LIST_HEAD(&dev->rx_reqs);
+
+       skb_queue_head_init(&dev->rx_frames);
+
+       /* network device setup */
+       dev->net = net;
+       dev->qmult = QMULT_DEFAULT;
+       snprintf(net->name, sizeof(net->name), "%s%%d", netname);
+       dev->parent_dev = gadget_sysfs_root;
+
+       eth_random_addr(net->dev_addr);
+       dev_warn(dev->parent_dev, "using random %s ethernet address\n", "self");
+       eth_random_addr(dev->host_mac);
+       dev_warn(dev->parent_dev, "using random %s ethernet address\n", "host");
+
+       if (ethaddr)
+               memcpy(ethaddr, dev->host_mac, ETH_ALEN);
+
+       net->netdev_ops = &eth_netdev_ops;
+
+       SET_ETHTOOL_OPS(net, &ops);
+
+       SET_NETDEV_DEV(net, dev->parent_dev);
+       SET_NETDEV_DEVTYPE(net, &gadget_type);
+
+       status = register_netdev(net);
+       if (status < 0) {
+               dev_dbg(dev->parent_dev, "register_netdev failed, %d\n",
+                       status);
+               free_netdev(net);
+               dev = ERR_PTR(status);
+       } else {
+               INFO(dev, "MAC %pM\n", net->dev_addr);
+               INFO(dev, "HOST MAC %pM\n", dev->host_mac);
+
+               /* two kinds of host-initiated state changes:
+                *  - iff DATA transfer is active, carrier is "on"
+                *  - tx queueing enabled if open *and* carrier is "on"
+                */
+               netif_carrier_off(net);
+       }
+
+       return net;
+}
+EXPORT_SYMBOL(gether_setup_name_default);
+
+void gether_set_gadget(struct net_device *net, struct usb_gadget *g)
+{
+       struct eth_dev *dev;
+
+       dev = netdev_priv(net);
+       dev->gadget = g;
+}
+EXPORT_SYMBOL(gether_set_gadget);
+
+int gether_set_dev_addr(struct net_device *net, const char *dev_addr)
+{
+       struct eth_dev *dev;
+       struct sockaddr sa;
+       u8 ethaddr[ETH_ALEN];
+       int status;
+
+       dev = netdev_priv(net);
+
+       if (get_ether_addr(dev_addr, ethaddr))
+               dev_warn(dev->parent_dev,
+                       "using random %s ethernet address\n", "self");
+
+       sa.sa_family = net->type;
+       memcpy(sa.sa_data, ethaddr, ETH_ALEN);
+       rtnl_lock();
+       status = dev_set_mac_address(net, &sa);
+       rtnl_unlock();
+       if (status) {
+               dev_warn(dev->parent_dev,
+                       "cannot set self ethernet address: %d\n", status);
+               return status;
+       }
+
+       return 0;
+
+}
+EXPORT_SYMBOL(gether_set_dev_addr);
+
+int gether_get_dev_addr(struct net_device *net, char *dev_addr, int len)
+{
+       return get_ether_addr_str(net->dev_addr, dev_addr, len);
+}
+EXPORT_SYMBOL(gether_get_dev_addr);
+
+void gether_set_host_addr(struct net_device *net, const char *host_addr,
+                          u8 hostaddr[ETH_ALEN])
+{
+       struct eth_dev *dev;
+
+       dev = netdev_priv(net);
+       if (get_ether_addr(host_addr, dev->host_mac))
+               dev_warn(dev->parent_dev,
+                       "using random %s ethernet address\n", "host");
+
+       if (hostaddr)
+               memcpy(hostaddr, dev->host_mac, ETH_ALEN);
+}
+EXPORT_SYMBOL(gether_set_host_addr);
+
+int gether_get_host_addr(struct net_device *net, char *host_addr, int len)
+{
+       struct eth_dev *dev;
+
+       dev = netdev_priv(net);
+       return get_ether_addr_str(dev->host_mac, host_addr, len);
+}
+EXPORT_SYMBOL(gether_get_host_addr);
+
+void gether_set_qmult(struct net_device *net, unsigned qmult)
+{
+       struct eth_dev *dev;
+
+       dev = netdev_priv(net);
+       dev->qmult = qmult;
+}
+EXPORT_SYMBOL(gether_set_qmult);
+
+unsigned gether_get_qmult(struct net_device *net)
+{
+       struct eth_dev *dev;
+
+       dev = netdev_priv(net);
+       return dev->qmult;
+}
+EXPORT_SYMBOL(gether_get_qmult);
+
+int gether_get_ifname(struct net_device *net, char *name, int len)
+{
+       strlcpy(name, net->name, len);
+       return strlen(name);
+}
+EXPORT_SYMBOL(gether_get_ifname);
+
 /**
  * gether_cleanup - remove Ethernet-over-USB device
  * Context: may sleep
diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h
index 465b859..76a0058 100644
--- a/drivers/usb/gadget/u_ether.h
+++ b/drivers/usb/gadget/u_ether.h
@@ -97,6 +97,107 @@ static inline struct eth_dev *gether_setup(struct 
usb_gadget *g,
        return gether_setup_name(g, dev_addr, host_addr, ethaddr, qmult, "usb");
 }
 
+/*
+ * variant of gether_setup_default that allows customizing
+ * network device name
+ */
+struct net_device *gether_setup_name_default(const char *netname,
+                                            u8 ethaddr[ETH_ALEN]);
+
+/* gether_setup_default - initialize one ethernet-over-usb link
+ * Context: may sleep
+ *
+ * This sets up the single network link that may be exported by a
+ * gadget driver using this framework.  The link layer addresses
+ * are set to random values.
+ *
+ * Returns negative errno, or zero on success
+ */
+static inline struct net_device *gether_setup_default(u8 ethaddr[ETH_ALEN])
+{
+       return gether_setup_name_default("usb", ethaddr);
+}
+
+/**
+ * gether_set_gadget - initialize one ethernet-over-usb link with a gadget
+ * @net: device representing this link
+ * @g: the gadget to initialize with
+ *
+ * This associates one ethernet-over-usb link with a gadget.
+ */
+void gether_set_gadget(struct net_device *net, struct usb_gadget *g);
+
+/**
+ * gether_set_dev_addr - initialize an ethernet-over-usb link with eth address
+ * @net: device representing this link
+ * @dev_addr: eth address of this device
+ *
+ * This sets the device-side Ethernet address of this ethernet-over-usb link.
+ */
+int gether_set_dev_addr(struct net_device *net, const char *dev_addr);
+
+/**
+ * gether_get_dev_addr - get an ethernet-over-usb link eth address
+ * @net: device representing this link
+ * @dev_addr: place to store device's eth address
+ * @len: length of the @dev_addr buffer
+ *
+ * This gets the device-side Ethernet address of this ethernet-over-usb link.
+ * Returns zero on success, else negative errno.
+ */
+int gether_get_dev_addr(struct net_device *net, char *dev_addr, int len);
+
+/**
+ * gether_set_host_addr - initialize an ethernet-over-usb link with host 
address
+ * @net: device representing this link
+ * @host_addr: eth address of the host
+ * @hostaddr: place to copy the resulting host address to
+ *
+ * This sets the host-side Ethernet address of this ethernet-over-usb link.
+ */
+void gether_set_host_addr(struct net_device *net, const char *host_addr,
+                         u8 hostaddr[ETH_ALEN]);
+
+/**
+ * gether_get_host_addr - get an ethernet-over-usb link host address
+ * @net: device representing this link
+ * @host_addr: place to store eth address of the host
+ * @len: length of the @host_addr buffer
+ *
+ * This gets the host-side Ethernet address of this ethernet-over-usb link.
+ * Returns zero on success, else negative errno.
+ */
+int gether_get_host_addr(struct net_device *net, char *host_addr, int len);
+
+/**
+ * gether_set_qmult - initialize an ethernet-over-usb link with a multiplier
+ * @net: device representing this link
+ * @qmult: queue multiplier
+ *
+ * This sets the queue length multiplier of this ethernet-over-usb link.
+ * For higher speeds use longer queues.
+ */
+void gether_set_qmult(struct net_device *net, unsigned qmult);
+
+/**
+ * gether_get_qmult - get an ethernet-over-usb link multiplier
+ * @net: device representing this link
+ *
+ * This gets the queue length multiplier of this ethernet-over-usb link.
+ */
+unsigned gether_get_qmult(struct net_device *net);
+
+/**
+ * gether_get_ifname - get an ethernet-over-usb link interface name
+ * @net: device representing this link
+ * @name: place to store the interface name
+ * @len: length of the @name buffer
+ *
+ * This gets the interface name of this ethernet-over-usb link.
+ * Returns zero on success, else negative errno.
+ */
+int gether_get_ifname(struct net_device *net, char *name, int len);
+
 void gether_cleanup(struct eth_dev *dev);
 
 /* connect/disconnect is handled by individual functions */
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to