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

📄 dfu.c

📁 openmoko host system dfu-util
💻 C
字号:
/* * dfu-programmer * * $Id: dfu.c,v 1.3 2006/06/20 06:28:04 schmidtw Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include <stdio.h>#include <usb.h>#include "dfu.h"/* DFU commands */#define DFU_DETACH      0#define DFU_DNLOAD      1#define DFU_UPLOAD      2#define DFU_GETSTATUS   3#define DFU_CLRSTATUS   4#define DFU_GETSTATE    5#define DFU_ABORT       6#define INVALID_DFU_TIMEOUT -1static int dfu_timeout = INVALID_DFU_TIMEOUT;static unsigned short transaction = 0;static int dfu_debug_level = 0;void dfu_init( const int timeout ){    if( timeout > 0 ) {        dfu_timeout = timeout;    } else {        if( 0 != dfu_debug_level )            fprintf( stderr, "dfu_init: Invalid timeout value.\n" );    }}static int dfu_verify_init( const char *function ){    if( INVALID_DFU_TIMEOUT == dfu_timeout ) {        if( 0 != dfu_debug_level )            fprintf( stderr,                     "%s: dfu system not property initialized.\n",                     function );        return -1;    }    return 0;}void dfu_debug( const int level ){    dfu_debug_level = level;}/* *  DFU_DETACH Request (DFU Spec 1.0, Section 5.1) * *  device    - the usb_dev_handle to communicate with *  interface - the interface to communicate with *  timeout   - the timeout in ms the USB device should wait for a pending *              USB reset before giving up and terminating the operation * *  returns 0 or < 0 on error */int dfu_detach( struct usb_dev_handle *device,                const unsigned short interface,                const unsigned short timeout ){    if( 0 != dfu_verify_init(__FUNCTION__) )        return -1;    return usb_control_msg( device,        /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,        /* bRequest      */ DFU_DETACH,        /* wValue        */ timeout,        /* wIndex        */ interface,        /* Data          */ NULL,        /* wLength       */ 0,                            dfu_timeout );}/* *  DFU_DNLOAD Request (DFU Spec 1.0, Section 6.1.1) * *  device    - the usb_dev_handle to communicate with *  interface - the interface to communicate with *  length    - the total number of bytes to transfer to the USB *              device - must be less than wTransferSize *  data      - the data to transfer * *  returns the number of bytes written or < 0 on error */int dfu_download( struct usb_dev_handle *device,                  const unsigned short interface,                  const unsigned short length,                  char* data ){    int status;    if( 0 != dfu_verify_init(__FUNCTION__) )        return -1;    /* Sanity checks */    if( (0 != length) && (NULL == data) ) {        if( 0 != dfu_debug_level )            fprintf( stderr,                     "%s: data was NULL, but length != 0\n",                     __FUNCTION__ );        return -1;    }    if( (0 == length) && (NULL != data) ) {        if( 0 != dfu_debug_level )            fprintf( stderr,                     "%s: data was not NULL, but length == 0\n",                     __FUNCTION__ );        return -2;    }    status = usb_control_msg( device,          /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,          /* bRequest      */ DFU_DNLOAD,          /* wValue        */ transaction++,          /* wIndex        */ interface,          /* Data          */ data,          /* wLength       */ length,                              dfu_timeout );    if( status < 0 ) {        fprintf( stderr, "%s error %d\n", __FUNCTION__, status );    }    return status;}/* *  DFU_UPLOAD Request (DFU Spec 1.0, Section 6.2) * *  device    - the usb_dev_handle to communicate with *  interface - the interface to communicate with *  length    - the maximum number of bytes to receive from the USB *              device - must be less than wTransferSize *  data      - the buffer to put the received data in * *  returns the number of bytes received or < 0 on error */int dfu_upload( struct usb_dev_handle *device,                const unsigned short interface,                const unsigned short length,                char* data ){    int status;    if( 0 != dfu_verify_init(__FUNCTION__) )        return -1;    /* Sanity checks */    if( (0 == length) || (NULL == data) ) {        if( 0 != dfu_debug_level )            fprintf( stderr,                     "%s: data was NULL, or length is 0\n",                     __FUNCTION__ );        return -1;    }    status = usb_control_msg( device,          /* bmRequestType */ USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,          /* bRequest      */ DFU_UPLOAD,          /* wValue        */ transaction++,          /* wIndex        */ interface,          /* Data          */ data,          /* wLength       */ length,                              dfu_timeout );    if( status < 0 ) {        fprintf( stderr, "%s error %d\n", __FUNCTION__, status );    }    return status;}/* *  DFU_GETSTATUS Request (DFU Spec 1.0, Section 6.1.2) * *  device    - the usb_dev_handle to communicate with *  interface - the interface to communicate with *  status    - the data structure to be populated with the results * *  return the number of bytes read in or < 0 on an error */int dfu_get_status( struct usb_dev_handle *device,                    const unsigned short interface,                    struct dfu_status *status ){    char buffer[6];    int result;    if( 0 != dfu_verify_init(__FUNCTION__) )        return -1;    /* Initialize the status data structure */    status->bStatus       = DFU_STATUS_ERROR_UNKNOWN;    status->bwPollTimeout = 0;    status->bState        = STATE_DFU_ERROR;    status->iString       = 0;    result = usb_control_msg( device,          /* bmRequestType */ USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,          /* bRequest      */ DFU_GETSTATUS,          /* wValue        */ 0,          /* wIndex        */ interface,          /* Data          */ buffer,          /* wLength       */ 6,                              dfu_timeout );    if( 6 == result ) {        status->bStatus = buffer[0];        status->bwPollTimeout = ((0xff & buffer[3]) << 16) |                                ((0xff & buffer[2]) << 8)  |                                (0xff & buffer[1]);        status->bState  = buffer[4];        status->iString = buffer[5];    }    return result;}/* *  DFU_CLRSTATUS Request (DFU Spec 1.0, Section 6.1.3) * *  device    - the usb_dev_handle to communicate with *  interface - the interface to communicate with * *  return 0 or < 0 on an error */int dfu_clear_status( struct usb_dev_handle *device,                      const unsigned short interface ){    if( 0 != dfu_verify_init(__FUNCTION__) )        return -1;    return usb_control_msg( device,        /* bmRequestType */ USB_ENDPOINT_OUT| USB_TYPE_CLASS | USB_RECIP_INTERFACE,        /* bRequest      */ DFU_CLRSTATUS,        /* wValue        */ 0,        /* wIndex        */ interface,        /* Data          */ NULL,        /* wLength       */ 0,                            dfu_timeout );}/* *  DFU_GETSTATE Request (DFU Spec 1.0, Section 6.1.5) * *  device    - the usb_dev_handle to communicate with *  interface - the interface to communicate with *  length    - the maximum number of bytes to receive from the USB *              device - must be less than wTransferSize *  data      - the buffer to put the received data in * *  returns the state or < 0 on error */int dfu_get_state( struct usb_dev_handle *device,                   const unsigned short interface ){    int result;    char buffer[1];    if( 0 != dfu_verify_init(__FUNCTION__) )        return -1;    result = usb_control_msg( device,          /* bmRequestType */ USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,          /* bRequest      */ DFU_GETSTATE,          /* wValue        */ 0,          /* wIndex        */ interface,          /* Data          */ buffer,          /* wLength       */ 1,                              dfu_timeout );    /* Return the error if there is one. */    if( result < 1 ) {        return result;    }    /* Return the state. */    return buffer[0];}/* *  DFU_ABORT Request (DFU Spec 1.0, Section 6.1.4) * *  device    - the usb_dev_handle to communicate with *  interface - the interface to communicate with * *  returns 0 or < 0 on an error */int dfu_abort( struct usb_dev_handle *device,               const unsigned short interface ){    if( 0 != dfu_verify_init(__FUNCTION__) )        return -1;    return usb_control_msg( device,        /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,        /* bRequest      */ DFU_ABORT,        /* wValue        */ 0,        /* wIndex        */ interface,        /* Data          */ NULL,        /* wLength       */ 0,                            dfu_timeout );}char* dfu_state_to_string( int state ){    char *message = NULL;    switch( state ) {        case STATE_APP_IDLE:            message = "appIDLE";            break;        case STATE_APP_DETACH:            message = "appDETACH";            break;        case STATE_DFU_IDLE:            message = "dfuIDLE";            break;        case STATE_DFU_DOWNLOAD_SYNC:            message = "dfuDNLOAD-SYNC";            break;        case STATE_DFU_DOWNLOAD_BUSY:            message = "dfuDNBUSY";            break;        case STATE_DFU_DOWNLOAD_IDLE:            message = "dfuDNLOAD-IDLE";            break;        case STATE_DFU_MANIFEST_SYNC:            message = "dfuMANIFEST-SYNC";            break;        case STATE_DFU_MANIFEST:            message = "dfuMANIFEST";            break;        case STATE_DFU_MANIFEST_WAIT_RESET:            message = "dfuMANIFEST-WAIT-RESET";            break;        case STATE_DFU_UPLOAD_IDLE:            message = "dfuUPLOAD-IDLE";            break;        case STATE_DFU_ERROR:            message = "dfuERROR";            break;    }    return message;}/* Chapter 6.1.2 */static const char *dfu_status_names[] = {	[DFU_STATUS_OK]			= "No error condition is present",	[DFU_STATUS_errTARGET]		= 		"File is not targeted for use by this device",	[DFU_STATUS_errFILE]		=		"File is for this device but fails some vendor-specific test",	[DFU_STATUS_errWRITE]		=		"Device is unable to write memory",	[DFU_STATUS_errERASE]		=		"Memory erase function failed",	[DFU_STATUS_errCHECK_ERASED]	=		"Memory erase check failed",	[DFU_STATUS_errPROG]		=		"Program memory function failed",	[DFU_STATUS_errVERIFY]		=		"Programmed emmory failed verification",	[DFU_STATUS_errADDRESS]		=		"Cannot program memory due to received address that is out of range",	[DFU_STATUS_errNOTDONE]		=		"Received DFU_DNLOAD with wLength = 0, but device does not think that it has all data yet",	[DFU_STATUS_errFIRMWARE]	=		"Device's firmware is corrupt. It cannot return to run-time (non-DFU) operations",	[DFU_STATUS_errVENDOR]		=		"iString indicates a vendor specific error",	[DFU_STATUS_errUSBR]		=		"Device detected unexpected USB reset signalling",	[DFU_STATUS_errPOR]		=		"Device detected unexpected power on reset",	[DFU_STATUS_errUNKNOWN]		=		"Something went wrong, but the device does not know what it was",	[DFU_STATUS_errSTALLEDPKT]	=		"Device stalled an unexpected request",};const char *dfu_status_to_string(int status){	if (status > DFU_STATUS_errSTALLEDPKT)		return "INVALID";	return dfu_status_names[status];}

⌨️ 快捷键说明

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