📄 usb_task.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 + -