void DFU_controlTransfer(CONTROL_TRANSFER *control)
{
	// 0x20 is CLASS request
	// 0x01 is INTERFACE target
	// MSBit is transfer direction
	if ((control->setup.bmRequestType & 0x7F) == 0x21)
	{
		switch(control->setup.bRequest)
		{
			case DFU_DETACH:
				// shouldn't happen, we're already in DFU mode
				break;
			case DFU_DNLOAD:
				DFU_Download(control);
				break;
			case DFU_UPLOAD:
				DFU_Upload(control);
				break;
			case DFU_GETSTATUS:
				DFU_GetStatus(control);
				break;
			case DFU_CLRSTATUS:
				DFU_ClearStatus(control);
				break;
			case DFU_GETSTATE:
				DFU_GetState(control);
				break;
			case DFU_ABORT:
				DFU_Abort(control);
				break;
		}
	}
}
/**
  * @brief  USBD_DFU_Setup
  *         Handle the DFU specific requests
  * @param  pdev: instance
  * @param  req: usb requests
  * @retval status
  */
static uint8_t  USBD_DFU_Setup (USBD_HandleTypeDef *pdev, 
                                USBD_SetupReqTypedef *req)
{
  uint8_t *pbuf = 0;
  uint16_t len = 0;
  uint8_t ret = USBD_OK;
  USBD_DFU_HandleTypeDef   *hdfu;
  
  hdfu = pdev->pClassData;
  
  switch (req->bmRequest & USB_REQ_TYPE_MASK)
  {
  case USB_REQ_TYPE_CLASS :  
    switch (req->bRequest)
    {
    case DFU_DNLOAD:
      DFU_Download(pdev, req);
      break;
      
    case DFU_UPLOAD:
      DFU_Upload(pdev, req);   
      break;
      
    case DFU_GETSTATUS:
      DFU_GetStatus(pdev);
      break;
      
    case DFU_CLRSTATUS:
      DFU_ClearStatus(pdev);
      break;      
      
    case DFU_GETSTATE:
      DFU_GetState(pdev);
      break;  
      
    case DFU_ABORT:
      DFU_Abort(pdev);
      break;
      
    case DFU_DETACH:
      DFU_Detach(pdev, req);
      break;
      
      
    default:
      USBD_CtlError (pdev, req);
      ret = USBD_FAIL; 
    }
    break;
    
  case USB_REQ_TYPE_STANDARD:
    switch (req->bRequest)
    {
    case USB_REQ_GET_DESCRIPTOR: 
      if( (req->wValue >> 8) == DFU_DESCRIPTOR_TYPE)
      {
        pbuf = USBD_DFU_CfgDesc + (9 * (USBD_DFU_MAX_ITF_NUM + 1));
        len = MIN(USB_DFU_DESC_SIZ , req->wLength);
      }
      
      USBD_CtlSendData (pdev, 
                        pbuf,
                        len);
      break;
      
    case USB_REQ_GET_INTERFACE :
      USBD_CtlSendData (pdev,
                        (uint8_t *)&hdfu->alt_setting,
                        1);
      break;
      
    case USB_REQ_SET_INTERFACE :
      if ((uint8_t)(req->wValue) < USBD_DFU_MAX_ITF_NUM)
      {
        hdfu->alt_setting = (uint8_t)(req->wValue);
      }
      else
      {
        /* Call the error management function (command will be nacked */
        USBD_CtlError (pdev, req);
        ret = USBD_FAIL;  
      }
      break;
      
    default:
      USBD_CtlError (pdev, req);
      ret = USBD_FAIL;     
    }
  }
  return ret;
}