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

📄 upsd3400_usb_app.c

📁 uPSD34xx Disk driver
💻 C
📖 第 1 页 / 共 3 页
字号:
  USEL     = OUTDIR | UMSC_OUT_ENDPOINT;     // Select EP OUT

/* dCBWSignature:
  Signature that helps identify this data packet as a CBW. The signature field
  shall contain the value 43425355h (little endian), indicating a CBW.*/
  if((USB_FIFO[0]==0x55) && (USB_FIFO[1]==0x53) &&
  (USB_FIFO[2]==0x42) && (USB_FIFO[3]==0x43))
   {
/* dCBWTag:
    A Command Block Tag sent by the host. The device shall echo the contents of
    this field back to the host in the dCSWTag field of the associated CSW. The
    dCSWTag positively associates a CSW with the corresponding CBW.*/
    *((uchar *)&gdwCBWTag+3) = USB_FIFO[4];  // LSB first
    *((uchar *)&gdwCBWTag+2) = USB_FIFO[5];
    *((uchar *)&gdwCBWTag+1) = USB_FIFO[6];
    *((uchar *)&gdwCBWTag+0) = USB_FIFO[7];
/* dCBWDataTransferLength:
    The number of bytes of data that the host expects to transfer on the Bulk-In
    or Bulk-Out endpoint (as indicated by the Direction bit) during the execution
    of this command. If this field is zero, the device and the host shall transfer
    no data between the CBW and the associated CSW, and the device shall ignore
    the value of the Direction bit in bmCBWFlags.*/
    *((uchar *)&gdwCBWDataTransferLength+3) = USB_FIFO[ 8];           // LSB first
    *((uchar *)&gdwCBWDataTransferLength+2) = USB_FIFO[ 9];
    *((uchar *)&gdwCBWDataTransferLength+1) = USB_FIFO[10];
    *((uchar *)&gdwCBWDataTransferLength+0) = USB_FIFO[11];
/* bmCBWFlags:
    The bits of this field are defined as follows:
    Bit 7 Direction - the device shall ignore this bit if the dCBWDataTransferLength
    field is zero, otherwise:
    0 = Data-Out from host to the device, 1 = Data-In from the device to the host.
    Bit 6 Obsolete. The host shall set this bit to zero.
    Bits 5..0 Reserved - the host shall set these bits to zero.*/
    gbCBWFlags = USB_FIFO[12];
/* bCBWLUN:
    The device Logical Unit Number (LUN) to which the command block is being sent.
    For devices that support multiple LUNs, the host shall place into this field
    the LUN to which this command block is addressed. Otherwise, the host shall
    set this field to zero. */
    gbCBWLUN  = USB_FIFO[13];
/* bCBWCBLength:
    The valid length of the CBWCB in bytes. This defines the valid length of the
    command block. The only legal values are 1 through 16 (01h through 10h). All
    other values are reserved. */
    gbCBWCBLength = USB_FIFO[14];

    if (gbCBWCBLength>16)
     {
      gbCBWCBLength = 16;
     }
/* CBWCB:
    The command block to be executed by the device. The device shall interpret
    the first bCBWCBLength bytes in this field as a command block as defined by
    the command set identified by bInterfaceSubClass. If the command set supported
    by the device uses command blocks of fewer than 16 (10h) bytes in
    length, the significant bytes shall be transferred first, beginning with the
    byte at offset 15 (Fh). The device shall ignore the content of the CBWCB field
    past the byte at offset (15 + bCBWCBLength - 1).
    */
    for(i = 0; i<gbCBWCBLength; i++)
     {
      gbCBWCB[i] = USB_FIFO[15+i];
     }

    UCON |= EPFIFO_BSY;



    gbCSWStatus     = PASS;                  // default CSW Status
    gbBulkPipeStage = BS_DATA_PHASE;

    if (gbCBWCBLength>0)
     {
/* Now decode the CBWCB; the command block to be executed by the device. */
      switch (gbCBWCB[0])
       {
        case OP_READ10:
         {
          DoReadWrite();
          break;
         }

        case OP_WRITE10:
         {
          DoReadWrite();
          break;
         }

        case OP_TEST_UNIT_READY:
         {
/* This is called by WinXP typ. every 1 second to check the unit */
/* default: all OK */
          ReturnCSW();                       // return status
          break;
         }

        case OP_REQUEST_SENSE:
         {
          OnRequestSense();
          break;
         }

        case OP_INQUIRY:
         {
          OnInquiry();
          break;
         }

        case OP_MODE_SENSE10:
         {
          OnModeSense10();
          break;
         }

        case OP_MODE_SELECT10:
         {
          OnModeSelect10();
          break;
         }


        case OP_MODE_SENSE6:
         {
          OnModeSense6();
          break;
         }

        case OP_MODE_SELECT6:
         {
          OnModeSelect6();
          break;
         }


        case OP_READ_CAPACITY:
         {
          DoReadCapacity();
          break;
         }

        case OP_READ_FORMAT_CAPACITIES:
         {
          DoReadFormatCapacity();
          break;
         }


        case OP_MEDIA_REMOVEAL:
         {
          gbCSWStatus = FAIL;
          ReturnCSW();                       // return status
          break;
         }

        case OP_VERIFY:
         {
          gbCSWStatus = FAIL;              //implement your own checking mechanism
          ReturnCSW();                       // return status
          break;
         }

        default:
         {
          gbCSWStatus = FAIL;
          STALL_EP1();                       // unknown command
          gbBulkPipeStage = BS_CSW_PHASE;
          break;
         }
       }
     }
    else
     {
      ReturnCSW();                           // no command, return status
     }

   }
  else
   {
    gbCSWStatus = FAIL;
    STALL_EP1();                             // unknown command block type, STALL
    gbBulkPipeStage = BS_CBW_PHASE;
   }
 }

unsigned char USB_ISR_Counter;               // incremented every USB INT event

void UsbIsr(void) interrupt USB_VECTOR using 2
/******************************************************************************
 Function   : void UsbIsr()
 Parameters : none
 Description: USB interrupt service routine.
 Note:        Do not modify this routine !!!
 ******************************************************************************/
 {
  UCTL |= VISIBLE;                           // enable USB FIFO mapping in XDATA

  if (RSTF)
   {
    OnUsbReset();                            // USB Reset int

    UIE1  |= UMSC_MASK_IN_ENDPOINT;          //Enable EP0 IN INT
    UIE2  |= UMSC_MASK_OUT_ENDPOINT;         //Enable EP0 OUT INT

    USEL   = OUTDIR | UMSC_OUT_ENDPOINT;     //Select EP OUT
    UCON   = ENABLE_FIFO | EPFIFO_BSY;

    USEL   = INDIR | UMSC_IN_ENDPOINT;       //Select EP IN
    UCON   = ENABLE_FIFO;

    UIF1 = 0;
    UIF2 = 0;
    UIF3 = 0;
    UIF0 = 0;
    RSTF = 0;
    SUSPNDF = 0;

    if (UCON & TOGGLE)                       //only silicon revision #0
     {
      USIZE = 0;                            //send an empty packet to reach DATA=0
     }

    USTA = 0;                                //silicon revision #0
    UADDR = 0;                         //Reset device address, silicon revision #0

    gbBulkPipeStage = BS_CBW_PHASE;

   }

/* IN packets servicing, invoked when TuPSD+ sent an ACKed packet to a host */
  if (INF)
   {
    if (UIF1 & IN0F)                         // EP0 IN
     {
      UIF1 &= ~IN0F;
      TransmitEP0();
      if (usbState == US_ADDRESSED)     // DEVICE ADDRESS change after SET_ADDRESS
       {
        UADDR    = setupPacket.wValue.lo;    //device address
        usbState = US_DEFAULT;
       }
     }
    if (UIF1 & UMSC_MASK_IN_ENDPOINT)        // EP IN
     {
      switch (gbBulkPipeStage)
       {
        case BS_DATA_PHASE:
         {
          UIF1 &= ~UMSC_MASK_IN_ENDPOINT;
          ReadBufferFromFlash();
          break;
         }
        case BS_CBW_PHASE:
         {
                                             //UIF1 &= ~UMSC_MASK_IN_ENDPOINT;
          break;
         }
        case BS_CSW_PHASE:                   // DATA phase finished, preparing CSW
         {
          UIF1 &= ~UMSC_MASK_IN_ENDPOINT;
          ReturnCSW();
          break;
         }
        case BS_CSW_DONE_PHASE:              //CSW sent, IN FIFO became empty
         {
          UIF1 &= ~UMSC_MASK_IN_ENDPOINT;
          gbBulkPipeStage = BS_CBW_PHASE;    //CBW
          break;
         }
       }
     }
/*
    if (UIF1 & IN2F)                         //EP2 IN
    {
    UIF1 &= ~IN2F;                         // User code area
    }

    if (UIF1 & IN3F)                         //EP3 IN
    {
    UIF1 &= ~IN3F;                         // User code area
    }

    if (UIF1 & IN4F)                         //EP4 IN
    {
    UIF1 &= ~IN4F;                         // User code area
    }
    */
   }

/* OUT packets servicing,invoked when TuPSD+ receives an OUT packet from a host*/
  if (OUTF)
   {
    if (UIF2 & OUT0F)                        // EP0 OUT
     {
      UIF2 &= ~OUT0F;
      if (USTA & SETUP)
       {
        ReadSetupPacket();
        OnSetupPacket();
        if (usbState == US_CONFIGURED)
         {
          USEL  = INDIR | UMSC_IN_ENDPOINT;  //Select EP IN
          if (UCON & TOGGLE)                 //only silicon revision #0
           {
            USIZE = 0;                      //send an empty packet to reach DATA=0
           }
//    UCON &= ~TOGGLE;                       //clear toggle
          USEL  = OUTDIR | UMSC_OUT_ENDPOINT;//Select EP OUT
//    UCON &= ~TOGGLE;                       //clear toggle
         }
       }
      else
       {
       }
      gbBulkPipeStage = BS_CBW_PHASE;
     }

/*
    if (UIF2 & OUT1F)                        // EP1 OUT
    {
    UIF2 &= ~OUT1F;                        // User code area
    }

    if (UIF2 & OUT2F)                        // EP2 OUT
    {
    UIF2 &= ~OUT2F;                        // User code area
    }
    */

    if (UIF2 & UMSC_MASK_OUT_ENDPOINT)       // EP3 OUT
     {
      switch (gbBulkPipeStage)
       {
        case BS_CBW_PHASE:                   // Command received
         {
          UIF2 &= ~UMSC_MASK_OUT_ENDPOINT;
          CheckReceiveCBW();
          break;
         }
        case BS_DATA_PHASE:                  // Data block received
         {
          UIF2 &= ~UMSC_MASK_OUT_ENDPOINT;
          WriteBufferToFlash();
          break;
         }
        case BS_CSW_PHASE:
         {
          break;
         }
        case BS_CSW_DONE_PHASE:
         {
          break;
         }
       }

     }
/*
    if (UIF2 & OUT4F)                        // EP4 OUT
    {
    UIF2 &= ~OUT4F;                        // User code area
    }
    */
   }

  if (SUSPNDF)
   {
    if (RESUMF)
     {
      UIE0     |=  SUSPENDIE;
      UIE0     &= ~RESUMEIE;
      OnUsbResume();                         // resume int
      RESUMF  = 0;
      SUSPNDF = 0;
      gbBulkPipeStage = BS_CBW_PHASE;
                                             // only for DK3420
      ET0   = 1;                             // enable timer 0 interrupt
     }
    else
     {
      UIE0     |=  RESUMEIE;
      UIE0     &= ~SUSPENDIE;
      OnUsbSuspend();                        // suspend int
      gbBulkPipeStage = BS_CBW_PHASE;
                                             // only for DK3420
      ET0       = 0;                         // disable timer 0 interrupt
      P4_0      = 1;                         // GREEN LED OFF
      UPSD_xreg.DATAOUT_D = 255;             // RED LED OFF
     }
   }

  UCTL  &= ~VISIBLE;                         // Disable USB FIFO mapping in XDATA
  USB_ISR_Counter++;                         // USB activity indicator

 }

/* *************************************************************************
  ***                                                                      ***
  **                         *** End of File ***                            **
  ***                                                                      ***
  *************************************************************************  */

⌨️ 快捷键说明

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