blob: bf4588ad5958a440b1f4dc778042698b1658e2d7 [file] [log] [blame]
/*
* Copyright 2014 Google Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <assert.h>
#include <endian.h>
#include <stdint.h>
#include <stdio.h>
#include <usb/usb.h>
#include "base/init_funcs.h"
#include "drivers/bus/usb/usb.h"
#include "drivers/net/net.h"
#include "drivers/net/mii.h"
#include "drivers/net/usb_eth.h"
int usb_eth_read_reg(UsbDev *dev, uint8_t request, uint16_t value,
uint16_t index, uint16_t length, void *data)
{
UsbDevReq dev_req;
dev_req.req_recp = UsbDevRecp;
dev_req.req_type = UsbVendorType;
dev_req.data_dir = UsbDeviceToHost;
dev_req.bRequest = request;
dev_req.wValue = value;
dev_req.wIndex = index;
dev_req.wLength = length;
return (dev->controller->control(dev, UsbDirIn, sizeof(dev_req),
&dev_req, dev_req.wLength,
(uint8_t *)data) < 0);
}
int usb_eth_write_reg(UsbDev *dev, uint8_t request, uint16_t value,
uint16_t index, uint16_t length, void *data)
{
UsbDevReq dev_req;
dev_req.req_recp = UsbDevRecp;
dev_req.req_type = UsbVendorType;
dev_req.data_dir = UsbHostToDevice;
dev_req.bRequest = request;
dev_req.wValue = value;
dev_req.wIndex = index;
dev_req.wLength = length;
return (dev->controller->control(dev, UsbDirOut, sizeof(dev_req),
&dev_req, dev_req.wLength,
(uint8_t *)data) < 0);
}
int usb_eth_init_endpoints(UsbDev *dev, UsbEndpoint **in, int in_idx,
UsbEndpoint **out, int out_idx)
{
*in = &dev->endpoints[in_idx];
*out = &dev->endpoints[out_idx];
if (dev->num_endp < in_idx || dev->num_endp < out_idx ||
(*in)->type != UsbEndpTypeBulk || (*out)->type != UsbEndpTypeBulk ||
(*in)->direction != UsbDirIn || (*out)->direction != UsbDirOut) {
printf("Problem with the endpoints.\n");
return 1;
}
return 0;
}
ListNode usb_eth_drivers;
static NetDevice *usb_eth_net_device;
static int usb_eth_probe(GenericUsbDevice *dev)
{
UsbDeviceDescriptor *dd = dev->dev->descriptor;
UsbEthDevice *eth_dev;
list_for_each(eth_dev, usb_eth_drivers, list_node) {
for (int i = 0; i < eth_dev->num_supported_ids; i++) {
if (dd->idVendor == eth_dev->supported_ids[i].vendor &&
dd->idProduct == eth_dev->supported_ids[i].product) {
usb_eth_net_device = &eth_dev->net_dev;
eth_dev->gen_dev = dev;
if (eth_dev->init(dev))
break;
net_add_device(usb_eth_net_device);
return 1;
}
}
}
return 0;
}
static void usb_eth_remove(GenericUsbDevice *dev)
{
net_remove_device(usb_eth_net_device);
free(dev->dev_data);
}
static GenericUsbDriver usb_eth_driver = {
.probe = &usb_eth_probe,
.remove = &usb_eth_remove,
};
static void usb_net_poller(struct NetPoller *poller)
{
dc_usb_initialize();
usb_poll();
}
static NetPoller net_poller = {
.poll = usb_net_poller
};
static int usb_eth_driver_register(void)
{
list_insert_after(&usb_eth_driver.list_node,
&generic_usb_drivers);
list_insert_after(&net_poller.list_node, &net_pollers);
return 0;
}
INIT_FUNC(usb_eth_driver_register);