📄 dfu.cpp
字号:
/**************************************************************************//* *//* Copyright (c) 1999-2000 by Atmel Corporation *//* *//* This software is copyrighted by and is the sole property of Atmel *//* Corporation. All rights, title, ownership, or other interests *//* in the software remain the property of Atmel Corporation. This *//* software may only be used in accordance with the corresponding *//* license agreement. Any un-authorized use, duplication, transmission, *//* distribution, or disclosure of this software is expressly forbidden. *//* *//* This Copyright notice may not be removed or modified without prior *//* written consent of Atmel Corporation. *//* *//* Atmel Corporation, Inc. reserves the right to modify this software *//* without notice. *//* *//* Atmel Corporation. *//* 2325 Orchard Parkway literature@atmel.com *//* San Jose, CA 95131 http://www.atmel.com *//* *//**************************************************************************//**************************************************************************//**************************************************************************//** *//** FastVNET (USB) NDIS Miniport Driver *//** *//** Functions for the DFU *//** *//** *//**************************************************************************//**************************************************************************/#include "stdafx.h"
#include "dfu.h"
/**************************************************************************/#define CLASS_REQUEST_IN 0xA1#define CLASS_REQUEST_OUT 0x21#define INTERFACE_VENDOR_REQUEST_OUT
#define USBD_TRANSFER_DIRECTION_IN (1 << 7)
#define URB_FUNCTION_CLASS_INTERFACE (1 << 5)/**************************************************************************/#define CLASS_OR_VENDOR_REQUEST_DFU_DETACH 0#define CLASS_OR_VENDOR_REQUEST_DFU_DNLOAD 1#define CLASS_OR_VENDOR_REQUEST_DFU_UPLOAD 2#define CLASS_OR_VENDOR_REQUEST_DFU_GETSTATUS 3#define CLASS_OR_VENDOR_REQUEST_DFU_CLRSTATUS 4#define CLASS_OR_VENDOR_REQUEST_DFU_GETSTATE 5#define CLASS_OR_VENDOR_REQUEST_DFU_ABORT 6/**************************************************************************/#define STATE_appIDLE 0#define STATE_appDETACH 1#define STATE_dfuIDLE 2#define STATE_dfuDNLOAD_SYNC 3#define STATE_dfuDNBUSY 4#define STATE_dfuDNLOAD_IDLE 5#define STATE_dfuMANIFEST_SYNC 6#define STATE_dfuMANIFEST 7#define STATE_dfuMANIFEST_WAIT_RESET 8#define STATE_dfuUPLOAD_IDLE 9#define STATE_dfuERROR 10/**************************************************************************/#define ACK 0x55
/**************************************************************************/
#define DFU_PACKETSIZE 1024
/*---------------------------*/
/* USB Setup Data */
/*---------------------------*/
typedef struct {
char bmRequestType; /* Characteristics of request */
char bRequest; /* Specific request */
short wValue; /* Word-sized field */
short wIndex; /* Word-sized field; used to pass an index or an offset */
short wLength; /* Number of bytes to transfert */
} SetupData;
typedef char StatusData;
BOOL UsbBuildVendorRequest(
IN PPIPE pPipe,
IN USHORT Function,
IN ULONG TransferFlags,
IN UCHAR ReservedBits,
IN UCHAR Request,
IN USHORT Value,
IN USHORT Index,
IN PVOID buffer,
IN ULONG bufferLength
)
{
SetupData setupData;
// Reset to 0 the setup packet
memset(&setupData, 0, sizeof(setupData));
// Initialize the setup packet
setupData.bmRequestType = (UCHAR) (Function | TransferFlags);
setupData.bRequest = Request;
setupData.wValue = Value;
setupData.wIndex = Index;
setupData.wLength = (USHORT) bufferLength;
// Send the setup packet
pPipe->write(pPipe->handle, &setupData, sizeof(setupData));
/*
// Wait for an acknowledge
if ( !pPipe->read(pPipe->handle, &statusData, sizeof(statusData)) )
return FALSE;
// Check the acknowledge
if (statusData != ACK) {
SetLastError(ERROR_STATUS_NOT_ACKED);
return FALSE;
}
*/
// Receive data requested
if ( TransferFlags & USBD_TRANSFER_DIRECTION_IN ) {
// Read data
if ( !pPipe->read(pPipe->handle, buffer, bufferLength) )
return FALSE;
/*
// Send an acknowledge
statusData = ACK;
if ( !pPipe->write(pPipe->handle, &statusData, sizeof(statusData)) )
return FALSE;
*/
}
// or Send data
else {
// Write data and wait for an acknowledge
if ( !pPipe->write(pPipe->handle, buffer, bufferLength) )
return FALSE;
/*
// Wait for an acknowledge
if ( !pPipe->read(pPipe->handle, &statusData, sizeof(statusData)) )
return FALSE;
if (statusData != ACK) {
SetLastError(ERROR_STATUS_NOT_ACKED);
return FALSE;
}
*/
}
return TRUE;
}
/**************************************************************************//* *//* GetDFUState *//* *//**************************************************************************/BOOL GetDFUState(IN PPIPE pPipe, PUCHAR DFUState){ BOOL ntStatus = UsbBuildVendorRequest(
pPipe, //URB_FUNCTION_VENDOR_INTERFACE, URB_FUNCTION_CLASS_INTERFACE, USBD_TRANSFER_DIRECTION_IN, //INTERFACE_VENDOR_REQUEST_IN, CLASS_REQUEST_IN, CLASS_OR_VENDOR_REQUEST_DFU_GETSTATE, 0, 0, DFUState, 1); return ntStatus;}/**************************************************************************//* *//* GetDFUStatus *//* *//**************************************************************************/BOOL GetDFUStatus(IN PPIPE pPipe, PUCHAR DFUStatus){ BOOL ntStatus = UsbBuildVendorRequest(
pPipe, //URB_FUNCTION_VENDOR_INTERFACE, URB_FUNCTION_CLASS_INTERFACE, USBD_TRANSFER_DIRECTION_IN, //INTERFACE_VENDOR_REQUEST_IN, CLASS_REQUEST_IN, CLASS_OR_VENDOR_REQUEST_DFU_GETSTATUS, 0, 0, DFUStatus, 6); return ntStatus;}/**************************************************************************//* *//* WriteFWBlock *//* *//**************************************************************************/BOOL WriteFWBlock(
IN PPIPE pPipe, IN PVOID pBuffer, IN ULONG bufferLength){ BOOL ntStatus = UsbBuildVendorRequest(
pPipe, //URB_FUNCTION_VENDOR_INTERFACE, URB_FUNCTION_CLASS_INTERFACE, 0, //INTERFACE_VENDOR_REQUEST_OUT, CLASS_REQUEST_OUT, CLASS_OR_VENDOR_REQUEST_DFU_DNLOAD, 0, 0, pBuffer, bufferLength); return ntStatus;}/**************************************************************************//* *//* ReadFWBlock *//* *//**************************************************************************/BOOL ReadFWBlock(
IN PPIPE pPipe, IN PVOID pBuffer, IN ULONG bufferLength){ BOOL ntStatus = UsbBuildVendorRequest(
pPipe, //URB_FUNCTION_VENDOR_INTERFACE, URB_FUNCTION_CLASS_INTERFACE, 0, //INTERFACE_VENDOR_REQUEST_OUT, CLASS_REQUEST_IN, CLASS_OR_VENDOR_REQUEST_DFU_UPLOAD, 0, 0, pBuffer, bufferLength); return ntStatus;}/**************************************************************************//* *//* DFUDetach *//* *//**************************************************************************/BOOL DFUDetach(
IN PPIPE pPipe){ BOOL ntStatus = UsbBuildVendorRequest(
pPipe, URB_FUNCTION_CLASS_INTERFACE, 0, CLASS_REQUEST_OUT, CLASS_OR_VENDOR_REQUEST_DFU_DETACH, 0, // 1000, 0, NULL, 0); return ntStatus;}/**************************************************************************//* *//* *//* DownloadUploadFirmware *//* *//* Suppose that the pipe has been opened previously *//**************************************************************************/BOOLEAN DownloadUploadFirmware( IN PPIPE pPipe,
IN PVOID pBuffer,
IN ULONG bufferLength, IN BOOLEAN Read){ BOOLEAN status = TRUE; BOOLEAN NeedDFUState = TRUE; BOOLEAN IsDone = FALSE; UCHAR DfuStatusBuffer[6]; UCHAR DfuState = 0; ULONG DfuTimeout = 0; BOOL readProcessed = FALSE; if ( (!pBuffer) && (bufferLength == 0) ) { // could be NULL for 0-len request
SetLastError(ERROR_BUFFER_EMPTY);
return FALSE; }
do { if (NeedDFUState) { status = GetDFUState(pPipe, &DfuState); if(!status) { return status; } NeedDFUState = FALSE; } switch (DfuState) { case STATE_dfuDNLOAD_SYNC : //DBG_MSG(DBG_DFU, ("STATE_dfuDNLOAD_SYNC\n")); if (GetDFUStatus(pPipe, DfuStatusBuffer)) { DfuState = DfuStatusBuffer[4]; DfuTimeout = 0; DfuTimeout = (ULONG)(DfuStatusBuffer[3]<<16); DfuTimeout |= (ULONG)(DfuStatusBuffer[2]<<8); DfuTimeout |= (ULONG)(DfuStatusBuffer[1]); NeedDFUState = FALSE; } //DBG_MSG(DBG_DFU, ("STATE_dfuDNLOAD_SYNC SUCCEDED %x\n", DfuState)); break; case STATE_dfuDNBUSY : //DBG_MSG(DBG_DFU, ("STATE_dfuDNBUSY\n")); NeedDFUState = TRUE; Sleep (DfuTimeout); break; case STATE_dfuDNLOAD_IDLE : //DBG_MSG(DBG_DFU, ("STATE_dfuDNLOAD_IDLE\n")); status = WriteFWBlock(pPipe, NULL, 0);
NeedDFUState = TRUE; break; case STATE_dfuIDLE : //DBG_MSG(DBG_DFU, ("STATE_dfuIDLE\n")); if (!Read)
status = WriteFWBlock(pPipe, pBuffer, bufferLength);
else
status = ReadFWBlock(pPipe, pBuffer, bufferLength);
NeedDFUState = TRUE; break; case STATE_dfuMANIFEST_SYNC : //DBG_MSG(DBG_DFU, ("STATE_dfuMANIFEST_SYNC\n")); status = GetDFUStatus(pPipe, DfuStatusBuffer); if (status) { DfuState = DfuStatusBuffer[4]; DfuTimeout = 0; DfuTimeout = (ULONG)(DfuStatusBuffer[3]<<16); DfuTimeout |= (ULONG)(DfuStatusBuffer[2]<<8); DfuTimeout |= (ULONG)(DfuStatusBuffer[1]); NeedDFUState = FALSE; Sleep(DfuTimeout); } break; case STATE_dfuMANIFEST : //DBG_MSG(DBG_DFU, ("STATE_dfuMANIFEST\n")); IsDone = TRUE; break; case STATE_dfuMANIFEST_WAIT_RESET : //DBG_MSG(DBG_DFU, ("STATE_dfuMANIFEST_WAIT_RESET\n")); status = ReadFWBlock(pPipe, NULL, 0); IsDone = TRUE; break; case STATE_dfuUPLOAD_IDLE : //DBG_MSG(DBG_DFU, ("STATE_dfuMANIFEST_WAIT_RESET\n")); break; case STATE_dfuERROR : //DBG_MSG(DBG_ERROR, ("DFU ERROR STATE\n")); status = FALSE; break; default : //DBG_MSG(DBG_DFU, ("DFU UNKNOWN STATE\n")); status = FALSE; break; } } while (!IsDone && status); return status;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -