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

📄 usb_task.c

📁 ATMEL公司AT89C51SND1为主控制器MP3源代码
💻 C
字号:
/*C**************************************************************************
* NAME:         usb_task.c
*----------------------------------------------------------------------------
* Copyright (c) 2003 Atmel.
*----------------------------------------------------------------------------
* RELEASE:      snd1c-refd-nf-4_0_3
* REVISION:     1.16
*----------------------------------------------------------------------------
* PURPOSE: 
* This file contains the USB task and attached routines
*
* NOTES:
* Global Variables:
*   - gl_sbc_wr_protect:  write protect flag for SCSI disk
*****************************************************************************/

/*_____ I N C L U D E S ____________________________________________________*/

#include "config.h"                         /* system configuration */
#include "lib_mcu\usb\usb_drv.h"            /* usb driver definition */
#include "lib_mcu\kbd\kbd_drv.h"            /* Keyboard driver definition */
#include "lib_mcu\clock\clock.h"            /* clock definition */
#include "lib_mcu\wdt\wdt_drv.h"
#include "modules\display\disp.h"           /* display definition */
#include "modules\mode\mode_task.h"         /* mode task definition */
#include "modules\mem\hard.h"               /* low level function definition */
#include "lib_storage\sbc.h"                /* SBC commands definition */
#include "usb_task.h"                       /* usb task definition */


/*_____ M A C R O S ________________________________________________________*/


/*_____ D E F I N I T I O N ________________________________________________*/

extern  bdata   bit     gl_sbc_wr_protect;  /* mass storage write protected */

static  bdata   bit     disconnected;
static  idata   Byte    dCBWTag[4];

static  bdata   bit     no_data_phase;

static  bdata   bit     ms_multiple_drive;  /* TRUE: multiple drive support */

static  idata   Byte    usb_resume_counter;

bdata   bit     bmCBWFlag7;                 /* Data OUT (0) or Data In (1) */
bdata   bit     status_ready;
data    Byte    status;
data    Uint32  dCBWDataTransferLength;     /* usb data message length */
bdata   bit     rx_bank;


/*_____ D E C L A R A T I O N ______________________________________________*/

#if MEM_CHIP_TYPE != CHIP_NONE
  extern  void    Sbc_chip_init (void);     /* chip memory SCSI driver init */
  extern  void    Sbc_command_chip (void);  /* chip memory SCSI command browser */
#endif
#if MEM_CARD_TYPE != CARD_NONE
  extern  void    Sbc_card_init (void);     /* card memory SCSI driver init */
  extern  void    Sbc_command_card (void);  /* card memory SCSI command browser */
#endif

static  void usb_mass_storage_cbw (void);
static  void usb_mass_storage_csw (void);


/*F**************************************************************************
* NAME: usb_task_init
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
*   USB task initialization
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE: 
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_task_init (void)
{
  disconnected = 0;
  clock_usb_init();                         /* for suspend detection */
  usb_init();
}


/*F**************************************************************************
* NAME: usb_task
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
*   USB task
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*   In order to avoid spurious connection, resume is done after the resume
*   event has been detected at least #USB_WAIT_NB_RESUME times.
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_task (void)
{
  if (Usb_suspend())                        /* -- if suspend flag -- */
  {
    if (disconnected == 0)
    {
      disconnected = 1;
      clock_disable();
      mode_exit_download();
      usb_resume_counter = USB_WAIT_NB_RESUME;
    }

    if (Usb_resume())                       /* check if resume */
    {
      if (usb_resume_counter == 0)
      {
        mode_set_download();
        clock_usb_init();
        print_mode_mass();                    /* display mass storage icon */
        print_screen(MASS_SCREEN);            /* display storage screen */
        disconnected = 0;
        Usb_clear_SPINT();
        Usb_clear_WUPCPU();
        Usb_clear_SOFINT();
      }
      else
      {
        Usb_clear_WUPCPU();
        Usb_clear_SOFINT();
        usb_resume_counter--;
      }
    }
  }
  else
  {
    if (Usb_reset())                        /* if end of reset */
    {
      Usb_enable_SPINT();                   /* Suspend interrupt enable */
      disconnected = 0;
      Usb_clear_rx_bank();
      Usb_clear_WUPCPU();
      Usb_clear_SPINT();
      Usb_clear_EORINT();
      ms_multiple_drive = FALSE;            /* multiple disk support init */
      gl_sbc_wr_protect = Kbd_key_locked(); /* set write protect flag */
      Sbc_chip_init();                      /* on-board memory SCSI driver init */
      Sbc_card_init();                      /* card memory SCSI driver init */


    }

    if (UEPINT != 0)                        /* new command */
    {
      Usb_select_ep(EP_CONTROL);
      if (Usb_setup_received())
      {
        usb_enumeration_process();
      }
      Usb_select_ep(EP_OUT);
      if (Usb_rx_complete())
      { 
        gl_sbc_wr_protect = Kbd_key_locked(); /* set write protect flag */
        Usb_enable_int();
        usb_mass_storage_cbw();
        usb_mass_storage_csw();
        Usb_disable_int();
      }
    }
  }
}


/*F**************************************************************************
* NAME: usb_mass_storage_cbw
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
*   Command Block Wrapper management
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_mass_storage_cbw (void)
{
bit cbw_error;

  cbw_error = FALSE;
  Usb_select_ep(EP_OUT);
  if (0x55 != Usb_read_byte()) 
  {
    cbw_error = TRUE;
  }
  if (0x53 != Usb_read_byte()) 
  {
    cbw_error = TRUE;
  }
  if (0x42 != Usb_read_byte()) 
  {
    cbw_error = TRUE;
  }
  if (0x43 != Usb_read_byte())              /* check if dCBWSignature is correct */
  {
    cbw_error = TRUE;
  }
            
  dCBWTag[0] = Usb_read_byte();             /* Store Tag to be repeated in CSW */
  dCBWTag[1] = Usb_read_byte();
  dCBWTag[2] = Usb_read_byte();
  dCBWTag[3] = Usb_read_byte();
  ((Byte*)&dCBWDataTransferLength)[3] = Usb_read_byte();
  ((Byte*)&dCBWDataTransferLength)[2] = Usb_read_byte();
  ((Byte*)&dCBWDataTransferLength)[1] = Usb_read_byte();
  ((Byte*)&dCBWDataTransferLength)[0] = Usb_read_byte();
  if (Usb_read_byte() != 0x00)              /* store bmCBWFlags.bit7 */
  {
    Usb_CBWFlag_in();
    if (cbw_error)
    {
      Usb_clear_RXOUT_PP();
      Usb_select_ep(EP_IN);
      Usb_set_STALLRQ();
      return;
    }
  }
  else
  {
    Usb_CBWFlag_out();
    if (cbw_error)
    {
      Usb_clear_RXOUT_PP();
      Usb_set_STALLRQ();
      return;
    }
  }

  if (ms_multiple_drive)
  { /* multiple drive supported */
    if (Usb_read_byte() == 0)
    { /* LUN = 0 */
      ACC = Usb_read_byte();                /* dummy CBWCBLength read */
      Usb_clear_no_data_phase();
      Sbc_command_chip();
    }
    else
    { /* LUN = 1 */
      ACC = Usb_read_byte();                /* dummy CBWCBLength read */
      Usb_clear_no_data_phase();
      Sbc_command_card();
    }
  }
  else
  { /* only 1 drive supported */
    ACC = Usb_read_byte();                  /* dummy LUN read */
    ACC = Usb_read_byte();                  /* dummy CBWCBLength read */
    Usb_clear_no_data_phase();

    if (gl_memory == MEM_CHIP)
    { /* on-board memory */
      Sbc_command_chip();
    }
    else
    { /* memory card */
      Sbc_command_card();
    }
  }
}


/*F**************************************************************************
* NAME: usb_mass_storage_csw
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
*   Command Status Wrapper management
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*
* REQUIREMENTS: 
*****************************************************************************/
void usb_mass_storage_csw (void)
{
  Usb_select_ep(EP_IN);
  while (Usb_STALL_requested())
  {
    Usb_select_ep(EP_CONTROL);
    if (Usb_setup_received())
    {
      usb_enumeration_process();
    }
    Usb_select_ep(EP_IN);
  }

  Usb_select_ep(EP_OUT);
  while (Usb_STALL_requested())
  {
    Usb_select_ep(EP_CONTROL);
    if (Usb_setup_received())
    {
      usb_enumeration_process();
    }
    Usb_select_ep(EP_OUT);
  }

  Usb_clear_no_data_phase();
  Usb_clear_status_ready();
  Usb_select_ep(EP_IN);
  Usb_write_byte(0x55);
  Usb_write_byte(0x53);
  Usb_write_byte(0x42);
  Usb_write_byte(0x53);

  Usb_write_byte(dCBWTag[0]);
  Usb_write_byte(dCBWTag[1]);
  Usb_write_byte(dCBWTag[2]);
  Usb_write_byte(dCBWTag[3]);
  Usb_write_byte(((Byte*)&dCBWDataTransferLength)[3]);
  Usb_write_byte(((Byte*)&dCBWDataTransferLength)[2]);
  Usb_write_byte(((Byte*)&dCBWDataTransferLength)[1]);
  Usb_write_byte(((Byte*)&dCBWDataTransferLength)[0]);
  Usb_write_byte(status);
  Usb_set_TXRDY();

  Usb_select_ep(EP_IN);
  while (!Usb_tx_complete());
  Usb_clear_TXCMPL();
}


/*F**************************************************************************
* NAME: usb_mass_storage_reset
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
*   This function handles the mass storage reset command
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_mass_storage_reset (void)
{
  Usb_clear_RXSETUP();
  Usb_set_TXRDY();
  while (!(Usb_tx_complete()));
  Usb_clear_TXCMPL();
}


/*F**************************************************************************
* NAME: usb_mass_storage_get_lun
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
*   This function returns the mass storage class specific Logical Unit Number.
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_mass_storage_get_lun (void)
{
  Usb_clear_RXSETUP();
  Usb_set_DIR();
  Usb_write_byte(MS_MAX_LUN);
  Usb_set_TXRDY();
  while (!(Usb_tx_complete()));
  Usb_clear_TXCMPL();
  while (!(Usb_rx_complete()));
  Usb_clear_RXOUT();
  Usb_clear_DIR();
#if (MS_MAX_LUN != 0)
  ms_multiple_drive = TRUE;                 /* multiple disk support */
  print_screen(MASS_SCREEN_NO_MEM);         /* memory icon off */
#endif
}


/*F**************************************************************************
* NAME: usb_it_suspend
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE:
*   USB suspend interrupt function -> reset
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*   IRQ_USB defined in extsnd1.h
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
Interrupt (usb_it_suspend(void), IRQ_USB) 
{
  if (Usb_suspend())
  {
    Wdt_enable(0);
    while (1);
  }
}

⌨️ 快捷键说明

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