text: /**
    ******************************************************************************
    * @file    usb_prop.c
    * @author  MCD Application Team
    * @version V4.1.0
    * @date    26-May-2017
    * @brief   All processings related to DFU demo
    ******************************************************************************
    * @attention
    *
    * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
    *
    * Redistribution and use in source and binary forms, with or without modification,
    * are permitted provided that the following conditions are met:
    *   1. Redistributions of source code must retain the above copyright notice,
    *      this list of conditions and the following disclaimer.
    *   2. Redistributions in binary form must reproduce the above copyright notice,
    *      this list of conditions and the following disclaimer in the documentation
    *      and/or other materials provided with the distribution.
    *   3. Neither the name of STMicroelectronics nor the names of its contributors
    *      may be used to endorse or promote products derived from this software
    *      without specific prior written permission.
    *
    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
    * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    *
    ******************************************************************************
    */
  
  
  /* Includes ------------------------------------------------------------------*/
  #include "usb_lib.h"
  #include "hw_config.h"
  #include "usb_conf.h"
  #include "usb_prop.h"
  #include "usb_desc.h"
  #include "usb_pwr.h"
  #include "dfu_mal.h"
  
  /* Private typedef -----------------------------------------------------------*/
  /* Private define ------------------------------------------------------------*/
  /* Private macro -------------------------------------------------------------*/
  /* Private variables ---------------------------------------------------------*/
  uint32_t wBlockNum = 0, wlength = 0;
  uint32_t Manifest_State = Manifest_complete;
  uint32_t Pointer = ApplicationAddress;  /* Base Address to Erase, Program or Read */
  
  DEVICE Device_Table =
    {
      EP_NUM,
      1
    };
  
  DEVICE_PROP Device_Property =
    {
      DFU_init,
      DFU_Reset,
      DFU_Status_In,
      DFU_Status_Out,
      DFU_Data_Setup,
      DFU_NoData_Setup,
      DFU_Get_Interface_Setting,
      DFU_GetDeviceDescriptor,
      DFU_GetConfigDescriptor,
      DFU_GetStringDescriptor,
      0,                    /*DFU_EP0Buffer*/
      bMaxPacketSize0       /*Max Packet size*/
    };
  
  USER_STANDARD_REQUESTS User_Standard_Requests =
    {
      DFU_GetConfiguration,
      DFU_SetConfiguration,
      DFU_GetInterface,
      DFU_SetInterface,
      DFU_GetStatus,
      DFU_ClearFeature,
      DFU_SetEndPointFeature,
      DFU_SetDeviceFeature,
      DFU_SetDeviceAddress
    };
  
  ONE_DESCRIPTOR Device_Descriptor =
    {
      (uint8_t*)DFU_DeviceDescriptor,
      DFU_SIZ_DEVICE_DESC
    };
  
  ONE_DESCRIPTOR Config_Descriptor =
    {
      (uint8_t*)DFU_ConfigDescriptor,
      DFU_SIZ_CONFIG_DESC
    };
  #ifdef USE_STM3210E_EVAL
   ONE_DESCRIPTOR DFU_String_Descriptor[7] =
  #elif defined(USE_STM3210B_EVAL) 
   ONE_DESCRIPTOR DFU_String_Descriptor[6] =
  #elif defined(USE_STM32L152_EVAL) || defined(USE_STM32L152D_EVAL) ||defined(USE_STM32373C_EVAL) ||defined(USE_STM32303C_EVAL) ||defined(USE_NUCLEO) 
   ONE_DESCRIPTOR DFU_String_Descriptor[5] =
  #endif /* USE_STM3210E_EVAL */
    {
      {       (uint8_t*)DFU_StringLangId,          DFU_SIZ_STRING_LANGID       },
      {       (uint8_t*)DFU_StringVendor,          DFU_SIZ_STRING_VENDOR       },
      {       (uint8_t*)DFU_StringProduct,         DFU_SIZ_STRING_PRODUCT      },
      {       (uint8_t*)DFU_StringSerial,          DFU_SIZ_STRING_SERIAL       },
      {       (uint8_t*)DFU_StringInterface0,      DFU_SIZ_STRING_INTERFACE0   }
  #ifdef USE_STM3210B_EVAL
      ,
      {       (uint8_t*)DFU_StringInterface1,      DFU_SIZ_STRING_INTERFACE1   }
  #endif /* USE_STM3210B_EVAL */
  #ifdef USE_STM3210E_EVAL 
      ,
      {       (uint8_t*)DFU_StringInterface1,      DFU_SIZ_STRING_INTERFACE1   },
      {       (uint8_t*)DFU_StringInterface2_1,    DFU_SIZ_STRING_INTERFACE2   }    
  #endif /* USE_STM3210E_EVAL */
    };
  
  /* Extern variables ----------------------------------------------------------*/
  extern  uint8_t DeviceState ;
  extern  uint8_t DeviceStatus[6];
  
  /* Private function prototypes -----------------------------------------------*/
  /* Private functions ---------------------------------------------------------*/
  
  /*******************************************************************************
  * Function Name  : DFU_init.
  * Description    : DFU init routine.
  * Input          : None.
  * Output         : None.
  * Return         : None.
  *******************************************************************************/
  void DFU_init(void)
  {
    DEVICE_INFO *pInfo = &Device_Info;
  
    /* Update the serial number string descriptor with the data from the unique ID*/
    Get_SerialNum();
  
    pInfo->Current_Configuration = 0;
  
    /* Connect the device */
    PowerOn();
  
    /* Perform basic device initialization operations */
    USB_SIL_Init();
  
    /* Enable USB interrupts */
    USB_Interrupts_Config();
  
    bDeviceState = UNCONNECTED;
  }
  
  /*******************************************************************************
  * Function Name  : DFU_Reset.
  * Description    : DFU reset routine
  * Input          : None.
  * Output         : None.
  * Return         : None.
  *******************************************************************************/
  void DFU_Reset(void)
  {
    /* Set DFU_DEVICE as not configured */
    Device_Info.Current_Configuration = 0;
  
    /* Current Feature initialization */
    pInformation->Current_Feature = DFU_ConfigDescriptor[7];
  
    _SetBTABLE(BTABLE_ADDRESS);
  
    /* Initialize Endpoint 0 */
    _SetEPType(ENDP0, EP_CONTROL);
    _SetEPTxStatus(ENDP0, EP_TX_NAK);
    _SetEPRxAddr(ENDP0, ENDP0_RXADDR);
    SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);
    _SetEPTxAddr(ENDP0, ENDP0_TXADDR);
    SetEPTxCount(ENDP0, Device_Property.MaxPacketSize);
    Clear_Status_Out(ENDP0);
    SetEPRxValid(ENDP0);
  
    /* Set this device to response on default address */
    SetDeviceAddress(0);
  
    /* Set the new control state of the device to Attached */
    bDeviceState = ATTACHED;
  }
  /*******************************************************************************
  * Function Name  : DFU_SetConfiguration.
  * Description    : Update the device state to configured.
  * Input          : None.
  * Output         : None.
  * Return         : None.
  *******************************************************************************/
  void DFU_SetConfiguration(void)
  {
    DEVICE_INFO *pInfo = &Device_Info;
  
    if (pInfo->Current_Configuration != 0)
    {
      /* Device configured */
      bDeviceState = CONFIGURED;
    }
  }
  /*******************************************************************************
  * Function Name  : DFU_SetConfiguration.
  * Description    : Update the device state to addressed.
  * Input          : None.
  * Output         : None.
  * Return         : None.
  *******************************************************************************/
  void DFU_SetDeviceAddress (void)
  {
    bDeviceState = ADDRESSED;
  }
  /*******************************************************************************
  * Function Name  : DFU_Status_In.
  * Description    : DFU status IN routine.
  * Input          : None.
  * Output         : None.
  * Return         : None.
  *******************************************************************************/
  void DFU_Status_In(void)
  {}
  
  /*******************************************************************************
  * Function Name  : DFU_Status_Out.
  * Description    : DFU status OUT routine.
  * Input          : None.
  * Output         : None.
  * Return         : None.
  *******************************************************************************/
  void DFU_Status_Out (void)
  {
    DEVICE_INFO *pInfo = &Device_Info;
    uint32_t Addr;
  
    if (pInfo->USBbRequest == DFU_GETSTATUS)
    {
      if (DeviceState == STATE_dfuDNBUSY)
      {
        if (wBlockNum == 0)   /* Decode the Special Command*/
        {
          if ((MAL_Buffer[0] ==  CMD_GETCOMMANDS) && (wlength == 1))
          {}
          else if  (( MAL_Buffer[0] ==  CMD_SETADDRESSPOINTER ) && (wlength == 5))
          {
            Pointer  = MAL_Buffer[1];
            Pointer += MAL_Buffer[2] << 8;
            Pointer += MAL_Buffer[3] << 16;
            Pointer += MAL_Buffer[4] << 24;
          }
          else if (( MAL_Buffer[0] ==  CMD_ERASE ) && (wlength == 5))
          {
            Pointer  = MAL_Buffer[1];
            Pointer += MAL_Buffer[2] << 8;
            Pointer += MAL_Buffer[3] << 16;
            Pointer += MAL_Buffer[4] << 24;
            MAL_Erase(Pointer);
          }
        }
  
        else if (wBlockNum > 1)  // Download Command
        {
          Addr = ((wBlockNum - 2) * wTransferSize) + Pointer;
          MAL_Write(Addr, wlength);
        }
        wlength = 0;
        wBlockNum = 0;
  
        DeviceState =  STATE_dfuDNLOAD_SYNC;
        DeviceStatus[4] = DeviceState;
        DeviceStatus[1] = 0;
        DeviceStatus[2] = 0;
        DeviceStatus[3] = 0;
        return;
      }
      else if (DeviceState == STATE_dfuMANIFEST)/* Manifestation in progress*/
      {
        DFU_write_crc();
        return;
      }
    }
    return;
  }
  
  /*******************************************************************************
  * Function Name  : DFU_Data_Setup.
  * Description    : Handle the data class specific requests.
  * Input          : RequestNb.
  * Output         : None.
  * Return         : USB_SUCCESS or USB_UNSUPPORT.
  *******************************************************************************/
  RESULT DFU_Data_Setup(uint8_t RequestNo)
  {
    uint8_t *(*CopyRoutine)(uint16_t);
    CopyRoutine = NULL;
  
    if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
    {
      if (RequestNo == DFU_UPLOAD && (DeviceState == STATE_dfuIDLE
                                      || DeviceState == STATE_dfuUPLOAD_IDLE ))
      {
        CopyRoutine = UPLOAD;
      }
      else if (RequestNo == DFU_DNLOAD && (DeviceState == STATE_dfuIDLE
                                           || DeviceState == STATE_dfuDNLOAD_IDLE))
      {
        DeviceState = STATE_dfuDNLOAD_SYNC;
        CopyRoutine = DNLOAD;
      }
      else if (RequestNo == DFU_GETSTATE)
      {
        CopyRoutine = GETSTATE;
      }
      else if (RequestNo == DFU_GETSTATUS)
      {
        CopyRoutine = GETSTATUS;
      }
      else
      {
        return USB_UNSUPPORT;
      }
    }
    else
    {
      return USB_UNSUPPORT;
    }
  
    if (CopyRoutine == NULL)
    {
      return USB_UNSUPPORT;
    }
  
    pInformation->Ctrl_Info.CopyData = CopyRoutine;
    pInformation->Ctrl_Info.Usb_wOffset = 0;
    (*CopyRoutine)(0);
  
    return USB_SUCCESS;
  }
  
  /*******************************************************************************
  * Function Name  : DFU_NoData_Setup.
  * Description    : Handle the No data class specific requests.
  * Input          : Request Nb.
  * Output         : None.
  * Return         : USB_SUCCESS or USB_UNSUPPORT.
  *******************************************************************************/
  RESULT DFU_NoData_Setup(uint8_t RequestNo)
  {
  
    if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
    {
      /*DFU_NDLOAD*/
      if (RequestNo == DFU_DNLOAD)
      {
        /* End of DNLOAD operation*/
        if (DeviceState == STATE_dfuDNLOAD_IDLE || DeviceState == STATE_dfuIDLE )
        {
          Manifest_State = Manifest_In_Progress;
          DeviceState = STATE_dfuMANIFEST_SYNC;
          DeviceStatus[1] = 0;
          DeviceStatus[2] = 0;
          DeviceStatus[3] = 0;
          DeviceStatus[4] = DeviceState;
          return USB_SUCCESS;
        }
      }
      /*DFU_UPLOAD*/
      else if (RequestNo == DFU_UPLOAD)
      {
        DeviceState = STATE_dfuIDLE;
        DeviceStatus[1] = 0;
        DeviceStatus[2] = 0;
        DeviceStatus[3] = 0;
        DeviceStatus[4] = DeviceState;
        return USB_SUCCESS;
      }
  
      /*DFU_CLRSTATUS*/
      else if (RequestNo == DFU_CLRSTATUS)
      {
  
        if (DeviceState == STATE_dfuERROR)
        {
          DeviceState = STATE_dfuIDLE;
          DeviceStatus[0] = STATUS_OK;/*bStatus*/
          DeviceStatus[1] = 0;
          DeviceStatus[2] = 0;
          DeviceStatus[3] = 0; /*bwPollTimeout=0ms*/
          DeviceStatus[4] = DeviceState;/*bState*/
          DeviceStatus[5] = 0;/*iString*/
        }
        else
        {   /*State Error*/
          DeviceState = STATE_dfuERROR;
          DeviceStatus[0] = STATUS_ERRUNKNOWN;/*bStatus*/
          DeviceStatus[1] = 0;
          DeviceStatus[2] = 0;
          DeviceStatus[3] = 0; /*bwPollTimeout=0ms*/
          DeviceStatus[4] = DeviceState;/*bState*/
          DeviceStatus[5] = 0;/*iString*/
        }
        return USB_SUCCESS;
      }
      /*DFU_ABORT*/
      else if (RequestNo == DFU_ABORT)
      {
        if (DeviceState == STATE_dfuIDLE || DeviceState == STATE_dfuDNLOAD_SYNC
            || DeviceState == STATE_dfuDNLOAD_IDLE || DeviceState == STATE_dfuMANIFEST_SYNC
            || DeviceState == STATE_dfuUPLOAD_IDLE )
        {
          DeviceState = STATE_dfuIDLE;
          DeviceStatus[0] = STATUS_OK;
          DeviceStatus[1] = 0;
          DeviceStatus[2] = 0;
          DeviceStatus[3] = 0; /*bwPollTimeout=0ms*/
          DeviceStatus[4] = DeviceState;
          DeviceStatus[5] = 0; /*iString*/
          wBlockNum = 0;
          wlength = 0;
        }
        return USB_SUCCESS;
      }
    }
  
  
    return USB_UNSUPPORT;
  
  } /* End of DFU_NoData_Setup */
  
  /*******************************************************************************
  * Function Name  : DFU_GetDeviceDescriptor.
  * Description    : Gets the device descriptor.
  * Input          : Length.
  * Output         : None.
  * Return         : The address of the device descriptor.
  *******************************************************************************/
  uint8_t *DFU_GetDeviceDescriptor(uint16_t Length)
  {
    return Standard_GetDescriptorData(Length, &Device_Descriptor);
  }
  
  /*******************************************************************************
  * Function Name  : DFU_GetConfigDescriptor.
  * Description    : Gets the configuration descriptor.
  * Input          : Length.
  * Output         : None.
  * Return         : The address of the configuration descriptor.
  *******************************************************************************/
  uint8_t *DFU_GetConfigDescriptor(uint16_t Length)
  {
    return Standard_GetDescriptorData (Length, &Config_Descriptor);
  }
  
  /*******************************************************************************
  * Function Name  : DFU_GetStringDescriptor.
  * Description    : Gets the string descriptors according to the needed index.
  * Input          : Length.
  * Output         : None.
  * Return         : The address of the string descriptors.
  *******************************************************************************/
  uint8_t *DFU_GetStringDescriptor(uint16_t Length)
  {
    uint8_t wValue0 = pInformation->USBwValue0;
  
    if (wValue0 >= 8)
    {
      return NULL;
    }
    else
    {
      return Standard_GetDescriptorData(Length, &DFU_String_Descriptor[wValue0]);
    }
  }
  
  /*******************************************************************************
  * Function Name  : DFU_Get_Interface_Setting.
  * Description    : tests the interface and the alternate setting according to the
  *                  supported one.
  * Input          : - Interface : interface number.
  *                  - AlternateSetting : Alternate Setting number.
  * Output         : None.
  * Return         : USB_SUCCESS or USB_UNSUPPORT.
  *******************************************************************************/
  RESULT DFU_Get_Interface_Setting(uint8_t Interface, uint8_t AlternateSetting)
  {
    if (AlternateSetting > 3)
    {
      return USB_UNSUPPORT;   /* In this application we don't have more than 3 AlternateSettings */
    }
    else if (Interface > 2)
    {
      return USB_UNSUPPORT; /* In this application we have only 1 interfaces */
    }
  
    return USB_SUCCESS;
  }
  
  /*******************************************************************************
  * Function Name  : UPLOAD
  * Description    : Upload routine.
  * Input          : Length.
  * Output         : None.
  * Return         : Pointer to data.
  *******************************************************************************/
  uint8_t *UPLOAD(uint16_t Length)
  {
    DEVICE_INFO *pInfo = &Device_Info;
    uint8_t B1, B0;
    uint16_t offset, returned;
    uint8_t *Phy_Addr = NULL;
    uint32_t Addr = 0;
  
    B0 = pInfo->USBwValues.bw.bb0;
    B1 = pInfo->USBwValues.bw.bb1;
    wBlockNum = (uint16_t)B1;
    wBlockNum = wBlockNum * 0x100;
    wBlockNum += (uint16_t)B0; /* wBlockNum value updated*/
  
    B0 = pInfo->USBwLengths.bw.bb0;
    B1 =  pInfo->USBwLengths.bw.bb1;
    wlength = (uint16_t)B0;
    wlength = wlength * 0x100;
    wlength += (uint16_t)B1; /* wlength value updated*/
  
    offset = pInformation->Ctrl_Info.Usb_wOffset;
  
    if (wBlockNum == 0)  /* Get Command */
    {
      if (wlength > 3)
      {
        DeviceState = STATE_dfuIDLE ;
      }
      else
      {
        DeviceState = STATE_dfuUPLOAD_IDLE;
      }
  
      DeviceStatus[4] = DeviceState;
      DeviceStatus[1] = 0;
      DeviceStatus[2] = 0;
      DeviceStatus[3] = 0;
  
      MAL_Buffer[0] = CMD_GETCOMMANDS;
      MAL_Buffer[1] = CMD_SETADDRESSPOINTER;
      MAL_Buffer[2] = CMD_ERASE;
  
      if (Length == 0)
      {
        pInformation->Ctrl_Info.Usb_wLength = 3 ;
        return NULL;
      }
  
      return(&MAL_Buffer[0]);
    }
    else if (wBlockNum > 1)
    {
      DeviceState = STATE_dfuUPLOAD_IDLE ;
      DeviceStatus[4] = DeviceState;
      DeviceStatus[1] = 0;
      DeviceStatus[2] = 0;
      DeviceStatus[3] = 0;
      Addr = ((wBlockNum - 2) * wTransferSize) + Pointer;  /* Change is Accelerated*/
  
      Phy_Addr = MAL_Read(Addr, wlength);
      returned = wlength - offset;
  
      if (Length == 0)
      {
        pInformation->Ctrl_Info.Usb_wLength = returned ;
        return NULL;
      }
      return(Phy_Addr + offset);
    }
    else  /* unsupported wBlockNum */
    {
      DeviceState = STATUS_ERRSTALLEDPKT;
      DeviceStatus[4] = DeviceState;
      DeviceStatus[1] = 0;
      DeviceStatus[2] = 0;
      DeviceStatus[3] = 0;
  
      return NULL;
    }
  }
  
  /*******************************************************************************
  * Function Name  : DNLOAD
  * Description    : Download routine.
  * Input          : Length.
  * Output         : None.
  * Return         : Pointer to data.
  *******************************************************************************/
  uint8_t *DNLOAD (uint16_t Length)
  {
    DEVICE_INFO             *pInfo = &Device_Info;
    uint8_t         B1, B0;
    uint16_t          offset, returned;
  
    B0 = pInfo->USBwValues.bw.bb0;
    B1 = pInfo->USBwValues.bw.bb1;
    wBlockNum = (uint16_t)B1;
    wBlockNum = wBlockNum * 0x100;
    wBlockNum += (uint16_t)B0;
    B0 = pInfo->USBwLengths.bw.bb0;
    B1 =  pInfo->USBwLengths.bw.bb1;
    wlength = (uint16_t)B0;
    wlength = wlength * 0x100;
    wlength += (uint16_t)B1;
  
    offset = pInfo->Ctrl_Info.Usb_wOffset;
  
    DeviceState = STATE_dfuDNLOAD_SYNC;
    DeviceStatus[4] = DeviceState;
  
    returned = wlength - offset;
  
    if (Length == 0)
    {
      pInformation->Ctrl_Info.Usb_wLength = returned ;
      return NULL;
    }
  
    return((uint8_t*)MAL_Buffer + offset);
  }
  
  /*******************************************************************************
  * Function Name  : GETSTATE.
  * Description    : Get State request routine.
  * Input          : Length.
  * Output         : None.
  * Return         : Pointer to data.
  *******************************************************************************/
  uint8_t *GETSTATE(uint16_t Length)
  {
    if (Length == 0)
    {
      pInformation->Ctrl_Info.Usb_wLength = 1 ;
      return NULL;
    }
    else
      return(&DeviceState);
  }
  
  /*******************************************************************************
  * Function Name  : GETSTATUS.
  * Description    : Get Status request routine.
  * Input          : Length.
  * Output         : None.
  * Return         : Pointer to data.
  *******************************************************************************/
  uint8_t *GETSTATUS(uint16_t Length)
  {
    switch (DeviceState)
    {
      case   STATE_dfuDNLOAD_SYNC:
        if (wlength != 0)
        {
          DeviceState = STATE_dfuDNBUSY;
          DeviceStatus[4] = DeviceState;
          if ((wBlockNum == 0) && (MAL_Buffer[0] == CMD_ERASE))
          {
            MAL_GetStatus(Pointer, 0, DeviceStatus);
          }
          else
          {
            MAL_GetStatus(Pointer, 1, DeviceStatus);
          }
        }
        else  /* (wlength==0)*/
        {
          DeviceState = STATE_dfuDNLOAD_IDLE;
          DeviceStatus[4] = DeviceState;
          DeviceStatus[1] = 0;
          DeviceStatus[2] = 0;
          DeviceStatus[3] = 0;
  
        }
        break;
      case   STATE_dfuMANIFEST_SYNC :
        if (Manifest_State == Manifest_In_Progress)
        {
          DeviceState = STATE_dfuMANIFEST;
          DeviceStatus[4] = DeviceState;
          DeviceStatus[1] = 1;             /*bwPollTimeout = 1ms*/
          DeviceStatus[2] = 0;
          DeviceStatus[3] = 0;
          //break;
        }
        else if (Manifest_State == Manifest_complete && Config_Descriptor.Descriptor[20]
                 & 0x04)
        {
          DeviceState = STATE_dfuIDLE;
          DeviceStatus[4] = DeviceState;
          DeviceStatus[1] = 0;
          DeviceStatus[2] = 0;
          DeviceStatus[3] = 0;
          //break;
        }
        break;
      default :
        break;
    }
  
    if (Length == 0)
    {
      pInformation->Ctrl_Info.Usb_wLength = 6 ;
      return NULL;
    }
    else
      return(&(DeviceStatus[0]));
  }
  
  /*******************************************************************************
  * Function Name  : DFU_write_crc.
  * Description    : DFU Write CRC routine.
  * Input          : None.
  * Output         : None.
  * Return         : None.
  *******************************************************************************/
  void DFU_write_crc(void)
  {
    Manifest_State = Manifest_complete;
  
    if (Config_Descriptor.Descriptor[20] & 0x04)
    {
      DeviceState = STATE_dfuMANIFEST_SYNC;
      DeviceStatus[4] = DeviceState;
      DeviceStatus[1] = 0;
      DeviceStatus[2] = 0;
      DeviceStatus[3] = 0;
      return;
    }
    else
    {
      DeviceState = STATE_dfuMANIFEST_WAIT_RESET;
      DeviceStatus[4] = DeviceState;
      DeviceStatus[1] = 0;
      DeviceStatus[2] = 0;
      DeviceStatus[3] = 0;
  
      Reset_Device();
  
      return;
    }
  }
  
  /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
  