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

📄 usb.c

📁 看到最近大家都关心 usbhost 的实现, 论坛上能找到的代码仅是一些简单的 demo , 完整的源码级的协议层是找不到的 我就贡献一把, 将我前一段时间移植成功的 USBHost 代码奉上 注
💻 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 <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "..\hardware\LPC2468.h"  /* 24xx Peripheral Registers */
#include "..\rtxOS\rtl.h"
#include "usb.h"


#define USB_PRINTF(fmt,args...)

void os_dly_waitms(unsigned int ms);

#define USB_BUFSIZ  512
struct usb_device usb_dev[USB_MAX_DEVICE];
static int asynch_allowed;
static struct devrequest setup_packet;
char usb_started; /* flag for the started/stopped USB status */
int usb_get_port_status(struct usb_device *dev, int port, void *data);
void usb_hub_port_connect_change(struct usb_device *dev, int port);
int usb_clear_port_feature(struct usb_device *dev, int port, int feature);
static void usb_hub_power_on(struct usb_hub_device *hub);

static struct usb_hub_device hub_dev[USB_MAX_HUB];
static int usb_hub_index;

/**********************************************************************
 * some forward declerations...
 */
void usb_scan_devices(void);
int  usb_hub_probe(struct usb_device *dev, int ifnum);
void usb_hub_reset(void);
int usb_stor_exists(void);

unsigned char get_usb_state( void )
{unsigned char state = 0;
    if(! usb_stor_exists()) 
    { state |= (1<<2);  }
    
    return state;
}

void usb_device_clear_all( void )
{unsigned char i;
    /* New Device %d\n",dev_index); */
    for(i=0; i<USB_MAX_DEVICE; i++)
    { memset(&usb_dev[i], 0, sizeof(struct usb_device));
    }
}
/***************************************************************************
 * Init USB Device
 */
int usb_init(void)
{
    int result;
    //s_SetIRQHandler(INT_USBH,hc_interrupt_irq );    
    usb_device_clear_all();
    asynch_allowed = 1;
    usb_hub_reset();
    
    /* init low_level 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) 
    { usb_scan_devices();
      usb_started = 1;
      return 0;
    }
    else
    { usb_started = 0;
      return -1;    /* Error, couldn't init Lowlevel part\n" */
    }
}

int usb_scan(void)
{
struct usb_port_status portsts;
unsigned short portstatus, portchange;
struct usb_device *dev;
struct usb_hub_device *hub;
unsigned char i, hi;
unsigned char bchange = 0;
    if(usb_started == 0) return 0;
    if(usb_hub_index == 0) return 0;

    for(hi=0; hi<usb_hub_index; hi++) 
    { hub = &hub_dev[hi];
      dev = hub->pusb_dev;
  
      for (i = 0; i < dev->maxchild; i++) 
      { if(usb_get_port_status(dev, i + 1, &portsts) < 0) 
        { continue;   /* get_port_status failed! */
        }
        portstatus = swap_16(portsts.wPortStatus);
        portchange = swap_16(portsts.wPortChange);
        
        /* Port %d Status %X Change %X\n",i+1,portstatus,portchange); */
        
        if (portchange & USB_PORT_STAT_C_CONNECTION) 
        { bchange = 1;
          usb_hub_port_connect_change(dev, i);
        }
        
        if (portchange & USB_PORT_STAT_C_ENABLE) 
        { 
          usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE);
          /* EM interference sometimes causes bad shielded USB devices to
                 * be shutdown by the hub, this hack enables them again.
                 * Works at least with mouse driver */
          if (!(portstatus & USB_PORT_STAT_ENABLE) &&
              (portstatus & USB_PORT_STAT_CONNECTION) && (dev->children[i])) 
          { bchange = 1;
            usb_hub_port_connect_change(dev, i);
          }
        }
  
        if (portstatus & USB_PORT_STAT_SUSPEND) 
        { 
          usb_clear_port_feature(dev, i + 1,  USB_PORT_FEAT_SUSPEND);
        }
        
        if (portchange & USB_PORT_STAT_C_OVERCURRENT) 
        { 
          usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_OVER_CURRENT);
          usb_hub_power_on(hub);
        }
        
        if (portchange & USB_PORT_STAT_C_RESET) 
        { 
          usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET);
        }
      } 
    }
    if(usb_started == 0) return 0;
    if(usb_hub_index == 0) return 0;
    return bchange;
}
/******************************************************************************
 * Stop USB this stops the LowLevel Part and deregisters USB devices.
 */
int usb_stop(void)
{
    asynch_allowed = 1;
    usb_started = 0;
    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)
{
    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);
    
    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(!(dev->status & USB_ST_NOT_PROC))
      { break;  }
      os_dly_waitms(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(!(dev->status & USB_ST_NOT_PROC))
      { break;  }
      os_dly_waitms(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;
        }
        else 
        { if((ep->bEndpointAddress & 0x80) == 0) 
          { /* OUT Endpoint */
            if(ep->wMaxPacketSize > dev->epmaxpacketout[b]) 
            { dev->epmaxpacketout[b] = ep->wMaxPacketSize;  }
          }
          else  
          { /* IN Endpoint */
            if(ep->wMaxPacketSize > dev->epmaxpacketin[b]) 
            { dev->epmaxpacketin[b] = ep->wMaxPacketSize;   }
          } 
          /* 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, curr_if_num;
//unsigned char *ch;

  ifno = -1;
  epno = -1;
  curr_if_num = -1;

  dev->configno = cfgno;
  head = (struct usb_descriptor_header *) &buffer[0];
  if(head->bDescriptorType != USB_DT_CONFIG) {
    printf(" 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:
        if(((struct usb_interface_descriptor *) &buffer[index])->
          bInterfaceNumber != curr_if_num) {
          /* this is a new interface, copy new desc */
          ifno = dev->config.no_of_if;
          dev->config.no_of_if++;
          memcpy(&dev->config.if_desc[ifno],
            &buffer[index], buffer[index]);
          dev->config.if_desc[ifno].no_of_ep = 0;
          dev->config.if_desc[ifno].num_altsetting = 1;
          curr_if_num = dev->config.if_desc[ifno].bInterfaceNumber;
        } else {
          /* found alternate setting for the interface */
          dev->config.if_desc[ifno].num_altsetting++;
        }
        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; }
        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);

⌨️ 快捷键说明

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