|
@@ -24,6 +24,10 @@
|
|
|
#include "gadget_chips.h"
|
|
|
#include "rndis.h"
|
|
|
|
|
|
+#include <dm.h>
|
|
|
+#include <dm/uclass-internal.h>
|
|
|
+#include <dm/device-internal.h>
|
|
|
+
|
|
|
#define USB_NET_NAME "usb_ether"
|
|
|
|
|
|
#define atomic_read
|
|
@@ -101,6 +105,9 @@ struct eth_dev {
|
|
|
struct usb_gadget *gadget;
|
|
|
struct usb_request *req; /* for control responses */
|
|
|
struct usb_request *stat_req; /* for cdc & rndis status */
|
|
|
+#ifdef CONFIG_DM_USB
|
|
|
+ struct udevice *usb_udev;
|
|
|
+#endif
|
|
|
|
|
|
u8 config;
|
|
|
struct usb_ep *in_ep, *out_ep, *status_ep;
|
|
@@ -134,9 +141,14 @@ struct eth_dev {
|
|
|
*/
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
-static struct eth_dev l_ethdev;
|
|
|
-static struct eth_device l_netdev;
|
|
|
-static struct usb_gadget_driver eth_driver;
|
|
|
+struct ether_priv {
|
|
|
+ struct eth_dev ethdev;
|
|
|
+ struct eth_device netdev;
|
|
|
+ struct usb_gadget_driver eth_driver;
|
|
|
+};
|
|
|
+
|
|
|
+struct ether_priv eth_priv;
|
|
|
+struct ether_priv *l_priv = ð_priv;
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
|
@@ -1135,7 +1147,7 @@ static void eth_status_complete(struct usb_ep *ep, struct usb_request *req)
|
|
|
event->bNotificationType, value);
|
|
|
if (event->bNotificationType ==
|
|
|
USB_CDC_NOTIFY_SPEED_CHANGE) {
|
|
|
- l_ethdev.network_started = 1;
|
|
|
+ dev->network_started = 1;
|
|
|
printf("USB network up!\n");
|
|
|
}
|
|
|
}
|
|
@@ -1323,7 +1335,7 @@ eth_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
|
|
|
* that network is working. So we signalize it
|
|
|
* here.
|
|
|
*/
|
|
|
- l_ethdev.network_started = 1;
|
|
|
+ dev->network_started = 1;
|
|
|
debug("USB network up!\n");
|
|
|
goto done_set_intf;
|
|
|
}
|
|
@@ -1823,10 +1835,10 @@ static void rndis_control_ack_complete(struct usb_ep *ep,
|
|
|
debug("rndis control ack complete --> %d, %d/%d\n",
|
|
|
req->status, req->actual, req->length);
|
|
|
|
|
|
- if (!l_ethdev.network_started) {
|
|
|
+ if (!dev->network_started) {
|
|
|
if (rndis_get_state(dev->rndis_config)
|
|
|
== RNDIS_DATA_INITIALIZED) {
|
|
|
- l_ethdev.network_started = 1;
|
|
|
+ dev->network_started = 1;
|
|
|
printf("USB RNDIS network up!\n");
|
|
|
}
|
|
|
}
|
|
@@ -1841,7 +1853,8 @@ static char rndis_resp_buf[8] __attribute__((aligned(sizeof(__le32))));
|
|
|
|
|
|
static int rndis_control_ack(struct eth_device *net)
|
|
|
{
|
|
|
- struct eth_dev *dev = &l_ethdev;
|
|
|
+ struct ether_priv *priv = (struct ether_priv *)net->priv;
|
|
|
+ struct eth_dev *dev = &priv->ethdev;
|
|
|
int length;
|
|
|
struct usb_request *resp = dev->stat_req;
|
|
|
|
|
@@ -1982,7 +1995,7 @@ static int get_ether_addr(const char *str, u8 *dev_addr)
|
|
|
|
|
|
static int eth_bind(struct usb_gadget *gadget)
|
|
|
{
|
|
|
- struct eth_dev *dev = &l_ethdev;
|
|
|
+ struct eth_dev *dev = &l_priv->ethdev;
|
|
|
u8 cdc = 1, zlp = 1, rndis = 1;
|
|
|
struct usb_ep *in_ep, *out_ep, *status_ep = NULL;
|
|
|
int status = -ENOMEM;
|
|
@@ -2175,7 +2188,7 @@ autoconf_fail:
|
|
|
|
|
|
|
|
|
/* network device setup */
|
|
|
- dev->net = &l_netdev;
|
|
|
+ dev->net = &l_priv->netdev;
|
|
|
|
|
|
dev->cdc = cdc;
|
|
|
dev->zlp = zlp;
|
|
@@ -2303,19 +2316,39 @@ fail:
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
|
|
-static int usb_eth_init(struct eth_device *netdev, bd_t *bd)
|
|
|
+#ifdef CONFIG_DM_USB
|
|
|
+int dm_usb_init(struct eth_dev *e_dev)
|
|
|
{
|
|
|
- struct eth_dev *dev = &l_ethdev;
|
|
|
+ struct udevice *dev = NULL;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &dev);
|
|
|
+ if (!dev || ret) {
|
|
|
+ error("No USB device found\n");
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
+
|
|
|
+ e_dev->usb_udev = dev;
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+static int _usb_eth_init(struct ether_priv *priv)
|
|
|
+{
|
|
|
+ struct eth_dev *dev = &priv->ethdev;
|
|
|
struct usb_gadget *gadget;
|
|
|
unsigned long ts;
|
|
|
unsigned long timeout = USB_CONNECT_TIMEOUT;
|
|
|
|
|
|
- if (!netdev) {
|
|
|
- error("received NULL ptr");
|
|
|
- goto fail;
|
|
|
+#ifdef CONFIG_DM_USB
|
|
|
+ if (dm_usb_init(dev)) {
|
|
|
+ error("USB ether not found\n");
|
|
|
+ return -ENODEV;
|
|
|
}
|
|
|
-
|
|
|
+#else
|
|
|
board_usb_init(0, USB_INIT_DEVICE);
|
|
|
+#endif
|
|
|
|
|
|
/* Configure default mac-addresses for the USB ethernet device */
|
|
|
#ifdef CONFIG_USBNET_DEV_ADDR
|
|
@@ -2342,7 +2375,15 @@ static int usb_eth_init(struct eth_device *netdev, bd_t *bd)
|
|
|
goto fail;
|
|
|
}
|
|
|
|
|
|
- if (usb_gadget_register_driver(ð_driver) < 0)
|
|
|
+ priv->eth_driver.speed = DEVSPEED;
|
|
|
+ priv->eth_driver.bind = eth_bind;
|
|
|
+ priv->eth_driver.unbind = eth_unbind;
|
|
|
+ priv->eth_driver.setup = eth_setup;
|
|
|
+ priv->eth_driver.reset = eth_disconnect;
|
|
|
+ priv->eth_driver.disconnect = eth_disconnect;
|
|
|
+ priv->eth_driver.suspend = eth_suspend;
|
|
|
+ priv->eth_driver.resume = eth_resume;
|
|
|
+ if (usb_gadget_register_driver(&priv->eth_driver) < 0)
|
|
|
goto fail;
|
|
|
|
|
|
dev->network_started = 0;
|
|
@@ -2357,7 +2398,7 @@ static int usb_eth_init(struct eth_device *netdev, bd_t *bd)
|
|
|
timeout = simple_strtoul(getenv("cdc_connect_timeout"),
|
|
|
NULL, 10) * CONFIG_SYS_HZ;
|
|
|
ts = get_timer(0);
|
|
|
- while (!l_ethdev.network_started) {
|
|
|
+ while (!dev->network_started) {
|
|
|
/* Handle control-c and timeouts */
|
|
|
if (ctrlc() || (get_timer(ts) > timeout)) {
|
|
|
error("The remote end did not respond in time.");
|
|
@@ -2373,11 +2414,11 @@ fail:
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
-static int usb_eth_send(struct eth_device *netdev, void *packet, int length)
|
|
|
+static int _usb_eth_send(struct ether_priv *priv, void *packet, int length)
|
|
|
{
|
|
|
int retval;
|
|
|
void *rndis_pkt = NULL;
|
|
|
- struct eth_dev *dev = &l_ethdev;
|
|
|
+ struct eth_dev *dev = &priv->ethdev;
|
|
|
struct usb_request *req = dev->tx_req;
|
|
|
unsigned long ts;
|
|
|
unsigned long timeout = USB_CONNECT_TIMEOUT;
|
|
@@ -2442,34 +2483,16 @@ drop:
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
-static int usb_eth_recv(struct eth_device *netdev)
|
|
|
+static int _usb_eth_recv(struct ether_priv *priv)
|
|
|
{
|
|
|
- struct eth_dev *dev = &l_ethdev;
|
|
|
-
|
|
|
usb_gadget_handle_interrupts(0);
|
|
|
|
|
|
- if (packet_received) {
|
|
|
- debug("%s: packet received\n", __func__);
|
|
|
- if (dev->rx_req) {
|
|
|
- net_process_received_packet(net_rx_packets[0],
|
|
|
- dev->rx_req->length);
|
|
|
- packet_received = 0;
|
|
|
-
|
|
|
- rx_submit(dev, dev->rx_req, 0);
|
|
|
- } else
|
|
|
- error("dev->rx_req invalid");
|
|
|
- }
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-void usb_eth_halt(struct eth_device *netdev)
|
|
|
+void _usb_eth_halt(struct ether_priv *priv)
|
|
|
{
|
|
|
- struct eth_dev *dev = &l_ethdev;
|
|
|
-
|
|
|
- if (!netdev) {
|
|
|
- error("received NULL ptr");
|
|
|
- return;
|
|
|
- }
|
|
|
+ struct eth_dev *dev = &priv->ethdev;
|
|
|
|
|
|
/* If the gadget not registered, simple return */
|
|
|
if (!dev->gadget)
|
|
@@ -2496,27 +2519,65 @@ void usb_eth_halt(struct eth_device *netdev)
|
|
|
dev->network_started = 0;
|
|
|
}
|
|
|
|
|
|
- usb_gadget_unregister_driver(ð_driver);
|
|
|
+ usb_gadget_unregister_driver(&priv->eth_driver);
|
|
|
+#ifdef CONFIG_DM_USB
|
|
|
+ device_remove(dev->usb_udev);
|
|
|
+#else
|
|
|
board_usb_cleanup(0, USB_INIT_DEVICE);
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+static int usb_eth_init(struct eth_device *netdev, bd_t *bd)
|
|
|
+{
|
|
|
+ struct ether_priv *priv = (struct ether_priv *)netdev->priv;
|
|
|
+
|
|
|
+ return _usb_eth_init(priv);
|
|
|
}
|
|
|
|
|
|
-static struct usb_gadget_driver eth_driver = {
|
|
|
- .speed = DEVSPEED,
|
|
|
+static int usb_eth_send(struct eth_device *netdev, void *packet, int length)
|
|
|
+{
|
|
|
+ struct ether_priv *priv = (struct ether_priv *)netdev->priv;
|
|
|
|
|
|
- .bind = eth_bind,
|
|
|
- .unbind = eth_unbind,
|
|
|
+ return _usb_eth_send(priv, packet, length);
|
|
|
+}
|
|
|
|
|
|
- .setup = eth_setup,
|
|
|
- .reset = eth_disconnect,
|
|
|
- .disconnect = eth_disconnect,
|
|
|
+static int usb_eth_recv(struct eth_device *netdev)
|
|
|
+{
|
|
|
+ struct ether_priv *priv = (struct ether_priv *)netdev->priv;
|
|
|
+ struct eth_dev *dev = &priv->ethdev;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = _usb_eth_recv(priv);
|
|
|
+ if (ret) {
|
|
|
+ error("error packet receive\n");
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
|
|
|
- .suspend = eth_suspend,
|
|
|
- .resume = eth_resume,
|
|
|
-};
|
|
|
+ if (!packet_received)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (dev->rx_req) {
|
|
|
+ net_process_received_packet(net_rx_packets[0],
|
|
|
+ dev->rx_req->length);
|
|
|
+ } else {
|
|
|
+ error("dev->rx_req invalid");
|
|
|
+ }
|
|
|
+ packet_received = 0;
|
|
|
+ rx_submit(dev, dev->rx_req, 0);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+void usb_eth_halt(struct eth_device *netdev)
|
|
|
+{
|
|
|
+ struct ether_priv *priv = (struct ether_priv *)netdev->priv;
|
|
|
+
|
|
|
+ _usb_eth_halt(priv);
|
|
|
+}
|
|
|
|
|
|
int usb_eth_initialize(bd_t *bi)
|
|
|
{
|
|
|
- struct eth_device *netdev = &l_netdev;
|
|
|
+ struct eth_device *netdev = &l_priv->netdev;
|
|
|
|
|
|
strlcpy(netdev->name, USB_NET_NAME, sizeof(netdev->name));
|
|
|
|
|
@@ -2524,6 +2585,7 @@ int usb_eth_initialize(bd_t *bi)
|
|
|
netdev->send = usb_eth_send;
|
|
|
netdev->recv = usb_eth_recv;
|
|
|
netdev->halt = usb_eth_halt;
|
|
|
+ netdev->priv = l_priv;
|
|
|
|
|
|
#ifdef CONFIG_MCAST_TFTP
|
|
|
#error not supported
|