📄 usb-eth.c
字号:
/*
* usb.c : Ethernet-over-USB for BLOB
*
* Copyright (c) 2003, Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifdef HAVE_CONFIG_H
# include <blob/config.h>
#endif
#include <blob/arch.h>
#include <blob/types.h>
#include <blob/serial.h>
#include <blob/util.h>
#include <blob/init.h>
#include <pxa_usb.h>
#include <net.h>
/* USB eth MAC address */
unsigned char eth_mac_addr[6] = {0x0, 0x0, 0x0, 0x0, 0xf, 0xe};
static int usb_rsize=64;
static int usb_wsize=64;
static struct mybuf* cur_tx_buf;
static struct mybuf* next_tx_buf;
static struct mybuf* rx_buf;
#define MIN(a,b) ((a)<(b) ? (a): (b))
#define ETHERNET_VENDOR_ID 0x8086
#define ETHERNET_PRODUCT_ID 0x7d3
static void usb_eth_send_callback(int flag, int size)
{
/* FIXME: assert cur_tx_buf */
if( cur_tx_buf ) {
cur_tx_buf->len = 0;
cur_tx_buf = 0;
}
else {
SerialOutputString("Oops: cur_tx_buf is NULL \n");
return;
}
if( next_tx_buf ) {
cur_tx_buf = next_tx_buf;
next_tx_buf = 0;
ep1_send(cur_tx_buf->buf, cur_tx_buf->len, usb_eth_send_callback);
}
}
static void usb_eth_recv_callback(int flag, int size)
{
int done=1;
//SerialOutputString("in usb_eth_recv_callback\n");
if( flag != 0 ) return;
/* end-of-packet */
if(size == usb_rsize) {
done = 0;
}
rx_buf->len += size;
if( !done ) {
if(rx_buf->len >= (BUFSZ-usb_rsize)) {
SerialOutputString("Out of buffer\n");
return;
}
ep2_recv(rx_buf->buf+rx_buf->len, MIN(BUFSZ-rx_buf->len, usb_rsize), usb_eth_recv_callback);
return;
}
/*
SerialOutputDec(rx_buf->len);
SerialOutputString(" bytes recved\n");
*/
/* let's handle this */
net_rx();
/* reset buffer */
rx_buf->len = 0;
memset(rx_buf->buf, 0, BUFSZ );
ep2_recv(rx_buf->buf, usb_rsize, usb_eth_recv_callback);
return;
}
int eth_xmit(struct mybuf *out)
{
if( out->len < usb_wsize ) {
out->len = usb_wsize + 1;
}
else if ( 0 == (out->len % usb_wsize) ) {
out->len ++;
}
if( cur_tx_buf ) {
if ( next_tx_buf ) {
SerialOutputString("Droping\n");
return;
} else next_tx_buf = out;
}
else {
cur_tx_buf = out;
ep1_send(out->buf, out->len , usb_eth_send_callback);
}
return 0;
}
void usb_driver_reset()
{
desc_t * pdesc = pxa_usb_get_descriptor_ptr();
config_desc_t *cfg;
intf_desc_t *intf;
ep_desc_t *ep;
/* setup device descriptor */
pdesc->dev.idVendor = ETHERNET_VENDOR_ID;
pdesc->dev.idProduct = ETHERNET_PRODUCT_ID;
pdesc->dev.bNumConfigurations = 1;
cfg = (config_desc_t*) (pdesc->cdb);
cfg->bLength = sizeof( config_desc_t );
cfg->bDescriptorType = USB_DESC_CONFIG;
cfg->wTotalLength = make_word_c( sizeof(config_desc_t) +
sizeof(intf_desc_t) * 1+
sizeof(ep_desc_t) * 2);
cfg->bNumInterfaces = 1;
cfg->bConfigurationValue = 1;
cfg->iConfiguration = 0;
cfg->bmAttributes = USB_CONFIG_BUSPOWERED;
cfg->MaxPower = USB_POWER( 500 );
intf = (intf_desc_t *) ( cfg + 1);
intf->bLength = sizeof( intf_desc_t );
intf->bDescriptorType = USB_DESC_INTERFACE;
intf->bInterfaceNumber = 0;
intf->bAlternateSetting = 0;
intf->bNumEndpoints = 2;
intf->bInterfaceClass = 0xFF;
intf->bInterfaceSubClass = 0;
intf->bInterfaceProtocol = 0;
intf->iInterface = 0;
ep = (ep_desc_t *) (intf + 1);
ep[0].bLength = sizeof( ep_desc_t );
ep[0].bDescriptorType = USB_DESC_ENDPOINT;
ep[0].bEndpointAddress = USB_EP_ADDRESS( 1, USB_IN );
ep[0].bmAttributes = USB_EP_BULK;
ep[0].wMaxPacketSize = make_word( 64 );
ep[0].bInterval = 0;
ep[1].bLength = sizeof( ep_desc_t );
ep[1].bDescriptorType = USB_DESC_ENDPOINT;
ep[1].bEndpointAddress = USB_EP_ADDRESS( 2, USB_OUT );
ep[1].bmAttributes = USB_EP_BULK;
ep[1].wMaxPacketSize = make_word( 64 );
ep[1].bInterval = 0;
/* resetting */
net_reset();
rx_buf = bget(0);
rx_buf->len = 0;
cur_tx_buf = 0;
next_tx_buf = 0;
ep2_recv(rx_buf->buf, usb_rsize, usb_eth_recv_callback);
}
int eth_rx()
{
if ( ICPR & 0x800 ) {
udc_int_hndlr(0x11, 0);
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -