⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb.c

📁 基于s3c2440的U盘读写程序
💻 C
📖 第 1 页 / 共 3 页
字号:

/*
 *
 * Most of this source has been derived from the Linux USB
 * project:
 * (C) Copyright Linus Torvalds 1999
 * (C) Copyright Johannes Erdfelt 1999-2001
 * (C) Copyright Andreas Gal 1999
 * (C) Copyright Gregory P. Smith 1999
 * (C) Copyright Deti Fliegl 1999 (new USB architecture)
 * (C) Copyright Randy Dunlap 2000
 * (C) Copyright David Brownell 2000 (kernel hotplug, usb_device_id)
 * (C) Copyright Yggdrasil Computing, Inc. 2000
 *     (usb_device_id matching changes by Adam J. Richter)
 *
 * Adapted for U-Boot:
 * (C) Copyright 2001 Denis Peter, MPL AG Switzerland
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * 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
 *
 */
/*
 * How it works:
 *
 * Since this is a bootloader, the devices will not be automatic
 * (re)configured on hotplug, but after a restart of the USB the
 * device should work.
 *
 * For each transfer (except "Interrupt") we wait for completion.
 */
//#include <common.h>
//#include <command.h>
//#include <asm/processor.h>
//#include <linux/ctype.h>
#include "usb.h"
#include "base.h"
#include "s3c2410.h"

//#undef USB_DEBUG
#define  USB_DEBUG
#ifdef	USB_DEBUG
#define	USB_PRINTF s_UartPrint
#else
#define USB_PRINTF()
#endif
#define USB_BUFSIZ	512
static struct usb_device usb_dev[USB_MAX_DEVICE];
static int dev_index;
static int running;
static int asynch_allowed;
static struct devrequest setup_packet;
//extern void hc_interrupt_irq (void);
/**********************************************************************
 * some forward declerations...
 */
void usb_scan_devices(void);
int   usb_hub_probe(struct usb_device *dev, int ifnum);
void usb_hub_reset(void);
void udelay (unsigned long usec)
{
    unsigned long j,i;
    //for(i=0;i<50;i++);   
    j=usec/1000;
    for(i=0;i<j;i++)
    {
        rINTMSK |= (1<<13);
        rTCON &= ~(0x0f<<16);  //stop timer3
        rSRCPND = (1<<13);		   
        rTCNTB3 = 2028;         //1ms=2028
        rTCMPB3=0;
        rTCON &= ~(0x0f<<16);   //STOP TIMER 3
        rTCON |= (0x02<<16); // AUTOLOAD=0 update=1
        rTCON &= ~(1<<17);   //CLEAR MANUAL UPDATE BIT
        rTCON |= (1<<16);    //START
        while((rSRCPND & (1<<13))==0);
        rSRCPND = (1<<13);	
    }
}


/***********************************************************************
 * wait_ms
 */
void __inline wait_ms(unsigned long ms)
{
    while(ms-->0)
    udelay(1000);
}


void TestWaitMs(void)
{
    int i,j;
    s_UartPrint("Test Wait Ms... Any Key to Start...\n");
    s_getkey();
    j=0;
    for(i=0;i<120;i++)
    {
        s_UartPrint("j=%d sec\n",j);
        wait_ms(1000);  
        j++;
    }
}


/***************************************************************************
 * Init USB Device
 */
int usb_init(void)
{
    int result;
    //s_SetIRQHandler(INT_USBH,hc_interrupt_irq );
    running=0;
    dev_index=0;
    asynch_allowed=1;
    usb_hub_reset();
    /* init low_level USB */
    //s_UartPrint("USB:   ");
    result = usb_lowlevel_init();
    /* if lowlevel init is OK, scan the bus for devices i.e. search HUBs and configure them */
    if(result==0) 
    {
        
        running=1;
        usb_scan_devices();
        return 0;
    }
    else 
    {
        s_UartPrint("Error, couldn't init Lowlevel part\n");
        return -1;
    }
}


/******************************************************************************
 * Stop USB this stops the LowLevel Part and deregisters USB devices.
 */
int usb_stop(void)
{
    asynch_allowed=1;
	
    usb_hub_reset();
    return usb_lowlevel_stop();
}


/*
 * disables the asynch behaviour of the control message. This is used for data
 * transfers that uses the exclusiv access to the control and bulk messages.
 */
void usb_disable_asynch(int disable)
{
    asynch_allowed=!disable;
}


/*-------------------------------------------------------------------
 * Message wrappers.
 *
 */
/*
 * submits an Interrupt Message
 */
int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe,
void *buffer,int transfer_len, int interval)
{
    return submit_int_msg(dev,pipe,buffer,transfer_len,interval);
}


/*
 * submits a control message and waits for comletion (at least timeout * 1ms)
 * If timeout is 0, we don't wait for completion (used as example to set and
 * clear keyboards LEDs). For data transfers, (storage transfers) we don't
 * allow control messages with 0 timeout, by previousely resetting the flag
 * asynch_allowed (usb_disable_asynch(1)).
 * returns the transfered length if OK or -1 if error. The transfered length
 * and the current status are stored in the dev->act_len and dev->status.
 */
int usb_control_msg(struct usb_device *dev, unsigned int pipe,
unsigned char request, unsigned char requesttype,
unsigned short value, unsigned short index,
void *data, unsigned short size, int timeout)
{
    //s_UartPrint("asynch_allowed=%d",asynch_allowed);
    if((timeout==0)&&(!asynch_allowed)) /* request for a asynch control pipe is not allowed */
    return -1;
    /* set setup command */
    setup_packet.requesttype = requesttype;
    setup_packet.request = request;
    setup_packet.value = swap_16(value);
    setup_packet.index = swap_16(index);
    setup_packet.length = swap_16(size);
    USB_PRINTF("usb_control_msg: request: 0x%X, requesttype: 0x%X\nvalue 0x%X index 0x%X length 0x%X pipe 0x%X \n",
    request,requesttype,value,index,size,pipe);
    dev->status=USB_ST_NOT_PROC; /*not yet processed */
    submit_control_msg(dev,pipe,data,size,&setup_packet);
    if(timeout==0) 
    {
        return (int)size;
    }
    while(timeout--) 
    {
        if(!((volatile unsigned long)dev->status & USB_ST_NOT_PROC))
        break;
        wait_ms(1);
    }
    if(dev->status==0)
    return dev->act_len;
    else 
    {
        return -1;
    }
}


/*-------------------------------------------------------------------
 * submits bulk message, and waits for completion. returns 0 if Ok or
 * -1 if Error.
 * synchronous behavior
 */
int usb_bulk_msg(struct usb_device *dev, unsigned int pipe,
void *data, int len, int *actual_length, int timeout)
{
    if (len < 0)
    return -1;
    dev->status=USB_ST_NOT_PROC; /*not yet processed */
    submit_bulk_msg(dev,pipe,data,len);
    while(timeout--) 
    {
        if(!((volatile unsigned long)dev->status & USB_ST_NOT_PROC))
        break;
        wait_ms(1);
    }
    *actual_length=dev->act_len;
    if(dev->status==0)
    return 0;
    else
    return -1;
}


/*-------------------------------------------------------------------
 * Max Packet stuff
 */
/*
 * returns the max packet size, depending on the pipe direction and
 * the configurations values
 */
int usb_maxpacket(struct usb_device *dev,unsigned long pipe)
{
    if((pipe & USB_DIR_IN)==0) /* direction is out -> use emaxpacket out */
    return(dev->epmaxpacketout[((pipe>>15) & 0xf)]);
    else
    return(dev->epmaxpacketin[((pipe>>15) & 0xf)]);
}


/*
 * set the max packed value of all endpoints in the given configuration
 */
int usb_set_maxpacket(struct usb_device *dev)
{
    int i,ii,b;
    struct usb_endpoint_descriptor *ep;
    for(i=0; i<dev->config.bNumInterfaces;i++) 
    {
        for(ii=0; ii<dev->config.if_desc[i].bNumEndpoints; ii++) 
        {
            ep=&dev->config.if_desc[i].ep_desc[ii];
            b=ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
            if((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)==USB_ENDPOINT_XFER_CONTROL) 
            {
                /* Control => bidirectional */
                dev->epmaxpacketout[b] = ep->wMaxPacketSize;
                dev->epmaxpacketin [b] = ep->wMaxPacketSize;
                USB_PRINTF("##Control EP epmaxpacketout/in[%d] = %d\n",b,dev->epmaxpacketin[b]);
            }
            else 
            {
                if ((ep->bEndpointAddress & 0x80)==0) 
                {
                    /* OUT Endpoint */
                    if(ep->wMaxPacketSize > dev->epmaxpacketout[b]) 
                    {
                        dev->epmaxpacketout[b] = ep->wMaxPacketSize;
                        USB_PRINTF("##EP epmaxpacketout[%d] = %d\n",b,dev->epmaxpacketout[b]);
                    }
                }
                else  
                {
                    /* IN Endpoint */
                    if(ep->wMaxPacketSize > dev->epmaxpacketin[b]) 
                    {
                        dev->epmaxpacketin[b] = ep->wMaxPacketSize;
                        USB_PRINTF("##EP epmaxpacketin[%d] = %d\n",b,dev->epmaxpacketin[b]);
                    }
                } 
                /* if out */
            } 
            /* if control */
        } 
        /* for each endpoint */
    }
    return 0;
}


/*******************************************************************************
 * Parse the config, located in buffer, and fills the dev->config structure.
 * Note that all little/big endian swapping are done automatically.
 */
int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno)
{
    struct usb_descriptor_header *head;
    int index,ifno,epno;
    ifno=-1;
    epno=-1;
    dev->configno=cfgno;
    head =(struct usb_descriptor_header *)&buffer[0];
    if(head->bDescriptorType!=USB_DT_CONFIG) 
    {
        s_UartPrint(" ERROR: NOT USB_CONFIG_DESC %x\n",head->bDescriptorType);
        return -1;
    }
    memcpy(&dev->config,buffer,buffer[0]);
    dev->config.wTotalLength=swap_16(dev->config.wTotalLength);
    dev->config.no_of_if=0;
    index=dev->config.bLength;
    /* Ok the first entry must be a configuration entry, now process the others */
    head=(struct usb_descriptor_header *)&buffer[index];
    while(index+1 < dev->config.wTotalLength) 
    {
        switch(head->bDescriptorType) 
        {
        case USB_DT_INTERFACE:
            ifno=dev->config.no_of_if;
            dev->config.no_of_if++; /* found an interface desc, increase numbers */
            memcpy(&dev->config.if_desc[ifno],&buffer[index],buffer[index]); /* copy new desc */
            dev->config.if_desc[ifno].no_of_ep=0;
            break;
        case USB_DT_ENDPOINT:
            epno=dev->config.if_desc[ifno].no_of_ep;
            dev->config.if_desc[ifno].no_of_ep++; /* found an endpoint */
            memcpy(&dev->config.if_desc[ifno].ep_desc[epno],&buffer[index],buffer[index]);
            dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize
            =swap_16(dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize);
            USB_PRINTF("if %d, ep %d\n",ifno,epno);
            break;
        default:
            if(head->bLength==0)
            return 1;
            USB_PRINTF("unknown Description Type : %x\n",head->bDescriptorType);
            {
                int i;
                unsigned char *ch;
                ch=(unsigned char *)head;
                for(i=0;i<head->bLength; i++)
                USB_PRINTF("%02X ",*ch++);
                USB_PRINTF("\n\n\n");
            }
            break;
        }
        index+=head->bLength;
        head=(struct usb_descriptor_header *)&buffer[index];
    }
    return 1;
}


/***********************************************************************
 * Clears an endpoint
 * endp: endpoint number in bits 0-3;
 * direction flag in bit 7 (1 = IN, 0 = OUT)
 */
int usb_clear_halt(struct usb_device *dev, int pipe)
{
    int result;
    int endp = usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7);
    result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
    USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, USB_CNTL_TIMEOUT * 3);
    /* don't clear if failed */
    if (result < 0)
    return result;
    /*
    	 * NOTE: we do not get status and verify reset was successful
    	 * as some devices are reported to lock up upon this check..
    	 */
    usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
    /* toggle is reset on clear */
    usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
    return 0;
}


/**********************************************************************
 * get_descriptor type
 */
int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size)
{
    int res;
    res = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
    USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
    (type << 8) + index, 0,
    buf, size, USB_CNTL_TIMEOUT);
    return res;
}


/**********************************************************************
 * gets configuration cfgno and store it in the buffer
 */
int usb_get_configuration_no(struct usb_device *dev,unsigned char *buffer,int cfgno)
{
    int result;
    unsigned int tmp;
    struct usb_config_descriptor *config;
    config=(struct usb_config_descriptor *)&buffer[0];
    result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -