stuff
This commit is contained in:
commit
bed7488a9c
|
@ -0,0 +1,6 @@
|
||||||
|
*.bin
|
||||||
|
*.bak
|
||||||
|
*.rom
|
||||||
|
fx3tool
|
||||||
|
*.img
|
||||||
|
*.txt
|
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
default: all
|
||||||
|
|
||||||
|
all: fx3tool
|
||||||
|
|
||||||
|
fx3tool: cyusb.h download_fx3.cpp libcyusb.cpp
|
||||||
|
$(CXX) -o "$@" $^ -lusb-1.0
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@$(RM) -v fx3tool
|
||||||
|
|
||||||
|
.PHONY: all default clean
|
|
@ -0,0 +1,8 @@
|
||||||
|
# fx3tool
|
||||||
|
|
||||||
|
Download and upload code and query the status of a Cypress FX3 in USB
|
||||||
|
bootloader mode. Built on top of Cypress' own code, so license is LGPL v2.1
|
||||||
|
|
||||||
|
## Planned
|
||||||
|
|
||||||
|
* Converter from ELF to FX3-IMG and back.
|
|
@ -0,0 +1,455 @@
|
||||||
|
#ifndef __CYUSB_H
|
||||||
|
#define __CYUSB_H
|
||||||
|
|
||||||
|
/*********************************************************************************\
|
||||||
|
* This is the main header file for the cyusb suite for Linux/Mac, called cyusb.h *
|
||||||
|
* *
|
||||||
|
* Author : V. Radhakrishnan ( rk@atr-labs.com ) *
|
||||||
|
* License : LGPL Ver 2.1 *
|
||||||
|
* Copyright : Cypress Semiconductors Inc. / ATR-LABS *
|
||||||
|
* Date written : March 12, 2012 *
|
||||||
|
* Modification Notes : *
|
||||||
|
* 1. Cypress Semiconductor, January 23, 2013 *
|
||||||
|
* Added function documentation. *
|
||||||
|
* Added new constant to specify number of device ID entries. *
|
||||||
|
* *
|
||||||
|
\********************************************************************************/
|
||||||
|
|
||||||
|
#include <libusb-1.0/libusb.h>
|
||||||
|
|
||||||
|
typedef struct libusb_device cyusb_device;
|
||||||
|
typedef struct libusb_device_handle cyusb_handle;
|
||||||
|
|
||||||
|
/* This is the maximum number of 'devices of interest' we are willing to store as default. */
|
||||||
|
/* These are the maximum number of devices we will communicate with simultaneously */
|
||||||
|
#define MAXDEVICES 10
|
||||||
|
|
||||||
|
/* This is the maximum number of VID/PID pairs that this library will consider. This limits
|
||||||
|
the number of valid VID/PID entries in the configuration file.
|
||||||
|
*/
|
||||||
|
#define MAX_ID_PAIRS 100
|
||||||
|
|
||||||
|
/* This is the maximum length for the description string for a device in the configuration
|
||||||
|
file. If the actual string in the file is longer, only the first MAX_STR_LEN characters
|
||||||
|
will be considered.
|
||||||
|
*/
|
||||||
|
#define MAX_STR_LEN 30
|
||||||
|
|
||||||
|
struct cydev {
|
||||||
|
cyusb_device *dev; /* as above ... */
|
||||||
|
cyusb_handle *handle; /* as above ... */
|
||||||
|
unsigned short vid; /* Vendor ID */
|
||||||
|
unsigned short pid; /* Product ID */
|
||||||
|
unsigned char is_open; /* When device is opened, val = 1 */
|
||||||
|
unsigned char busnum; /* The bus number of this device */
|
||||||
|
unsigned char devaddr; /* The device address*/
|
||||||
|
unsigned char filler; /* Padding to make struct = 16 bytes */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Function prototypes */
|
||||||
|
|
||||||
|
/*******************************************************************************************
|
||||||
|
Prototype : int cyusb_error(int err);
|
||||||
|
Description : Print out a verbose message corresponding to an error code, to the stderr
|
||||||
|
stream.
|
||||||
|
Parameters :
|
||||||
|
int err : Error code
|
||||||
|
Return Value : none
|
||||||
|
*******************************************************************************************/
|
||||||
|
extern void cyusb_error(int err);
|
||||||
|
|
||||||
|
/*******************************************************************************************
|
||||||
|
Prototype : int cyusb_open(void);
|
||||||
|
Description : This initializes the underlying libusb library, populates the cydev[]
|
||||||
|
array, and returns the number of devices of interest detected. A
|
||||||
|
'device of interest' is a device which appears in the /etc/cyusb.conf file.
|
||||||
|
Parameters : None
|
||||||
|
Return Value : Returns an integer, equal to number of devices of interest detected.
|
||||||
|
*******************************************************************************************/
|
||||||
|
extern int cyusb_open(void);
|
||||||
|
|
||||||
|
/*******************************************************************************************
|
||||||
|
Prototype : int cyusb_open(unsigned short vid, unsigned short pid);
|
||||||
|
Description : This is an overloaded function that populates the cydev[] array with
|
||||||
|
just one device that matches the provided vendor ID and Product ID.
|
||||||
|
This function is only useful if you know in advance that there is only
|
||||||
|
one device with the given VID and PID attached to the host system.
|
||||||
|
Parameters :
|
||||||
|
unsigned short vid : Vendor ID
|
||||||
|
unsigned short pid : Product ID
|
||||||
|
Return Value : Returns 1 if a device of interest exists, else returns 0.
|
||||||
|
*******************************************************************************************/
|
||||||
|
extern int cyusb_open(unsigned short vid, unsigned short pid);
|
||||||
|
|
||||||
|
/*******************************************************************************************
|
||||||
|
Prototype : cyusb_handle * cyusb_gethandle(int index);
|
||||||
|
Description : This function returns a libusb_device_handle given an index from the cydev[] array.
|
||||||
|
Parameters :
|
||||||
|
int index : Equal to the index in the cydev[] array that gets populated
|
||||||
|
during the cyusb_open() call described above.
|
||||||
|
Return Value : Returns the pointer to a struct of type cyusb_handle, also called as
|
||||||
|
libusb_device_handle.
|
||||||
|
*******************************************************************************************/
|
||||||
|
extern cyusb_handle * cyusb_gethandle(int index);
|
||||||
|
|
||||||
|
/*******************************************************************************************
|
||||||
|
Prototype : unsigned short cyusb_getvendor(cyusb_handle *);
|
||||||
|
Description : This function returns a 16-bit value corresponding to the vendor ID given
|
||||||
|
a device's handle.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *handle : Pointer to a struct of type cyusb_handle.
|
||||||
|
Return Value : Returns the 16-bit unique vendor ID of the given device.
|
||||||
|
*******************************************************************************************/
|
||||||
|
extern unsigned short cyusb_getvendor(cyusb_handle *);
|
||||||
|
|
||||||
|
/*******************************************************************************************
|
||||||
|
Prototype : unsigned short cyusb_getproduct(cyusb_handle *);
|
||||||
|
Description : This function returns a 16-bit value corresponding to the device ID given
|
||||||
|
a device's handle.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *handle : Pointer to a struct of type cyusb_handle.
|
||||||
|
Return Value : Returns the 16-bit product ID of the given device.
|
||||||
|
*******************************************************************************************/
|
||||||
|
extern unsigned short cyusb_getproduct(cyusb_handle *);
|
||||||
|
|
||||||
|
/*******************************************************************************************
|
||||||
|
Prototype : void cyusb_close(void);
|
||||||
|
Description : This function closes the libusb library and releases memory allocated to cydev[].
|
||||||
|
Parameters : none.
|
||||||
|
Return Value : none.
|
||||||
|
*******************************************************************************************/
|
||||||
|
extern void cyusb_close(void);
|
||||||
|
|
||||||
|
/*******************************************************************************************
|
||||||
|
Prototype : int cyusb_get_busnumber(cyusb_handle * handle);
|
||||||
|
Description : This function returns the Bus Number pertaining to a given device handle.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *handle : The libusb device handle
|
||||||
|
Return Value : An integer value corresponding to the Bus Number on which the device resides.
|
||||||
|
This is also the same value present in the cydev[] array.
|
||||||
|
*******************************************************************************************/
|
||||||
|
extern int cyusb_get_busnumber(cyusb_handle *);
|
||||||
|
|
||||||
|
/*******************************************************************************************
|
||||||
|
Prototype : int cyusb_get_devaddr(cyusb_handle * handle);
|
||||||
|
Description : This function returns the device address pertaining to a given device handle
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *handle : The libusb device handle
|
||||||
|
Return Value : An integer value corresponding to the device address (between 1 and 127).
|
||||||
|
This is also the same value present in the cydev[] array.
|
||||||
|
*******************************************************************************************/
|
||||||
|
extern int cyusb_get_devaddr(cyusb_handle *);
|
||||||
|
|
||||||
|
/*******************************************************************************************
|
||||||
|
Prototype : int cyusb_get_max_packet_size(cyusb_handle * handle,unsigned char endpoint);
|
||||||
|
Description : This function returns the max packet size that an endpoint can handle, without
|
||||||
|
taking into account high-bandwidth capabiity. It is therefore only useful
|
||||||
|
for Bulk, not Isochronous endpoints.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *handle : The libusb device handle
|
||||||
|
unsigned char endpoint : The endpoint number
|
||||||
|
Return Value : Max packet size in bytes for the endpoint.
|
||||||
|
*******************************************************************************************/
|
||||||
|
extern int cyusb_get_max_packet_size(cyusb_handle *, unsigned char endpoint);
|
||||||
|
|
||||||
|
/*******************************************************************************************
|
||||||
|
Prototype : int cyusb_get_max_iso_packet_size(cyusb_handle * handle,unsigned char endpoint);
|
||||||
|
Description : This function returns the max packet size that an isochronous endpoint can
|
||||||
|
handle, after considering multiple transactions per microframe if present.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *handle : The libusb device handle
|
||||||
|
unsigned char endpoint : The endpoint number
|
||||||
|
Return Value : Maximum amount of data that an isochronous endpoint can transfer per
|
||||||
|
microframe.
|
||||||
|
*******************************************************************************************/
|
||||||
|
extern int cyusb_get_max_iso_packet_size(cyusb_handle *, unsigned char endpoint);
|
||||||
|
|
||||||
|
/*******************************************************************************************
|
||||||
|
Prototype : int cyusb_get_configuration(cyusb_handle * handle,int *config);
|
||||||
|
Description : This function determines the bConfiguration value of the active configuration.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *handle : The libusb device handle
|
||||||
|
int * config : Address of an integer variable that will store the
|
||||||
|
currently active configuration number.
|
||||||
|
Return Value : 0 on success, or an appropriate LIBUSB_ERROR
|
||||||
|
*******************************************************************************************/
|
||||||
|
extern int cyusb_get_configuration(cyusb_handle *, int *config);
|
||||||
|
|
||||||
|
/*******************************************************************************************
|
||||||
|
Prototype : int cyusb_set_configuration(cyusb_handle * handle,int config);
|
||||||
|
Description : This function sets the device's active configuration (standard request).
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *handle : The libusb device handle
|
||||||
|
int config : Configuration number required to be made active.
|
||||||
|
Return Value : 0 on success, or an appropriate LIBUSB_ERROR
|
||||||
|
*******************************************************************************************/
|
||||||
|
extern int cyusb_set_configuration(cyusb_handle *, int config);
|
||||||
|
|
||||||
|
/*******************************************************************************************
|
||||||
|
Prototype : int cyusb_claim_interface(cyusb_handle * handle,int interface);
|
||||||
|
Description : This function claims an interface for a given device handle.
|
||||||
|
You must claim an interface before performing I/O operations on the device.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *handle : The libusb device handle
|
||||||
|
int interface : The bInterfaceNumber of the interface you wish to claim.
|
||||||
|
Return Value : 0 on success, or an appropriate LIBUSB_ERROR
|
||||||
|
*******************************************************************************************/
|
||||||
|
extern int cyusb_claim_interface(cyusb_handle *, int interface);
|
||||||
|
|
||||||
|
/*********************************************************************************************
|
||||||
|
Prototype : int cyusb_release_interface(cyusb_handle * handle,int interface);
|
||||||
|
Description : This function releases an interface previously claimed for a given device handle.
|
||||||
|
You must release all claimed interfaces before closing a device handle.
|
||||||
|
This is a blocking funcion, where a standard SET_INTERFACE control request is
|
||||||
|
sent to the device, resetting interface state to the first alternate setting.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *handle : The libusb device handle
|
||||||
|
int interface : The bInterfaceNumber of the interface you wish to release
|
||||||
|
Return Value : 0 on success, or an appropriate LIBUSB_ERROR
|
||||||
|
*********************************************************************************************/
|
||||||
|
extern int cyusb_release_interface(cyusb_handle *, int interface);
|
||||||
|
|
||||||
|
/*******************************************************************************************
|
||||||
|
Prototype : int cyusb_set_interface_alt_setting(cyusb_handle * handle,
|
||||||
|
int interface,int altsetting);
|
||||||
|
Description : This function activates an alternate setting for an interface.
|
||||||
|
The interface itself must have been previously claimed using
|
||||||
|
cyusb_claim_interface. This is a blocking funcion, where a standard
|
||||||
|
control request is sent to the device.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *handle : The libusb device handle
|
||||||
|
int interface : The bInterfaceNumber of the interface you wish to set,
|
||||||
|
int altsetting : The bAlternateSetting number to activate
|
||||||
|
Return Value : 0 on success, or an appropriate LIBUSB_ERROR
|
||||||
|
*****************************************************************************************/
|
||||||
|
extern int cyusb_set_interface_alt_setting(cyusb_handle *, int interface, int altsetting);
|
||||||
|
|
||||||
|
/*******************************************************************************************
|
||||||
|
Prototype : int cyusb_clear_halt(cyusb_handle * handle, unsigned char endpoint);
|
||||||
|
Description : This function clears a halt condition on an endpoint.
|
||||||
|
Endpoints with a halt condition are unable to send/receive data unless
|
||||||
|
the condition is specifically cleared by the Host.
|
||||||
|
This is a blocking funcion.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *handle : The libusb device handle
|
||||||
|
unsigned char endpoint : The endpoint for which the clear request is sent.
|
||||||
|
Return Value : 0 on success, or an appropriate LIBUSB_ERROR
|
||||||
|
*****************************************************************************************/
|
||||||
|
extern int cyusb_clear_halt(cyusb_handle *, unsigned char endpoint);
|
||||||
|
|
||||||
|
/******************************************************************************************
|
||||||
|
Prototype : int cyusb_reset_device(cyusb_handle * handle);
|
||||||
|
Description : This function performs a USB port reset to the device.
|
||||||
|
This is a blocking funcion.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *handle : The libusb device handle
|
||||||
|
Return Value : 0 on success, or an appropriate LIBUSB_ERROR
|
||||||
|
*****************************************************************************************/
|
||||||
|
extern int cyusb_reset_device(cyusb_handle *);
|
||||||
|
|
||||||
|
/******************************************************************************************
|
||||||
|
Prototype : int cyusb_kernel_driver_active(cyusb_handle * handle, int interface);
|
||||||
|
Description : This function returns whether a kernel driver has already claimed an
|
||||||
|
interface. If a kernel driver is active and has claimed an interface,
|
||||||
|
cyusb cannot perform I/O operations on that interface unless the interface
|
||||||
|
is first released.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *handle : The libusb device handle
|
||||||
|
int interface : The interface which you are testing.
|
||||||
|
Return Value : 0 if no kernel driver is active, 1 if a kernel driver is active;
|
||||||
|
LIBUSB error code in case of error.
|
||||||
|
*****************************************************************************************/
|
||||||
|
extern int cyusb_kernel_driver_active(cyusb_handle *, int interface);
|
||||||
|
|
||||||
|
/******************************************************************************************
|
||||||
|
Prototype : int cyusb_detach_kernel_driver(cyusb_handle * handle, int interface);
|
||||||
|
Description : This function detaches a kernel mode driver in order for cyusb to claim
|
||||||
|
the interface. If a kernel driver is active and has claimed an interface,
|
||||||
|
cyusb cannot perform I/O operations on that interface unless the interface
|
||||||
|
is first released.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *handle : The libusb device handle
|
||||||
|
int interface : The interface which you want to be detached.
|
||||||
|
Return Value : 0 on success, or an appropriate LIBUSB_ERROR.
|
||||||
|
*****************************************************************************************/
|
||||||
|
extern int cyusb_detach_kernel_driver(cyusb_handle *, int interface);
|
||||||
|
|
||||||
|
/******************************************************************************************
|
||||||
|
Prototype : int cyusb_attach_kernel_driver(cyusb_handle * handle, int interface);
|
||||||
|
Description : This function reattaches a kernel mode driver which was previously detached.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *handle : The libusb device handle
|
||||||
|
int interface : The interface which you want to be reattached.
|
||||||
|
Return Value : 0 on success, or an appropriate LIBUSB_ERROR.
|
||||||
|
*****************************************************************************************/
|
||||||
|
extern int cyusb_attach_kernel_driver(cyusb_handle *, int interface);
|
||||||
|
|
||||||
|
/******************************************************************************************
|
||||||
|
Prototype : int cyusb_get_device_descriptot(cyusb_handle * handle,
|
||||||
|
struct libusb_device_descriptor *);
|
||||||
|
Description : This function returns the usb device descriptor for the given device.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *handle : The libusb device handle
|
||||||
|
struct libusb_device_descriptor *desc : Address of a device_desc structure
|
||||||
|
Return Value : 0 on success, or an appropriate LIBUSB_ERROR.
|
||||||
|
*****************************************************************************************/
|
||||||
|
extern int cyusb_get_device_descriptor(cyusb_handle *, struct libusb_device_descriptor *desc);
|
||||||
|
|
||||||
|
/******************************************************************************************
|
||||||
|
Prototype : int cyusb_get_active_config_descriptor(cyusb_handle * handle,
|
||||||
|
struct libusb_config_descriptor **);
|
||||||
|
Description : This function returns the usb configuration descriptor for the given device.
|
||||||
|
The descriptor structure must be freed with cyusb_free_config_descriptor()
|
||||||
|
explained below.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *handle : The libusb device handle
|
||||||
|
struct libusb_configuration_descriptor **desc : Address of a config_descriptor
|
||||||
|
Return Value : 0 on success, or an appropriate LIBUSB_ERROR.
|
||||||
|
******************************************************************************************/
|
||||||
|
extern int cyusb_get_active_config_descriptor(cyusb_handle *, struct libusb_config_descriptor **config);
|
||||||
|
|
||||||
|
/*****************************************************************************************
|
||||||
|
Prototype : int cyusb_get_config_descriptor(cyusb_handle * handle, unsigned char index,
|
||||||
|
struct libusb_config_descriptor **);
|
||||||
|
Description : This function returns the usb configuration descriptor with the specified
|
||||||
|
index for the given device. The descriptor structure must be freed using
|
||||||
|
the cyusb_free_config_descriptor() call later.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *handle : The libusb device handle
|
||||||
|
unsigned char index : Index of configuration you wish to retrieve.
|
||||||
|
struct libusb_configuration_descriptor **desc : Address of a config_descriptor
|
||||||
|
Return Value : 0 on success, or an appropriate LIBUSB_ERROR.
|
||||||
|
*****************************************************************************************/
|
||||||
|
extern int cyusb_get_config_descriptor(cyusb_handle *, unsigned char index, struct libusb_config_descriptor **config);
|
||||||
|
|
||||||
|
/*****************************************************************************************
|
||||||
|
Prototype : void cyusb_free_config_descriptor(struct libusb_config_descriptor *);
|
||||||
|
Description : Frees the configuration descriptor obtained earlier.
|
||||||
|
Parameters :
|
||||||
|
struct libusb_config_descriptor *config : The config descriptor you wish to free.
|
||||||
|
Return Value : NIL.
|
||||||
|
*****************************************************************************************/
|
||||||
|
extern void cyusb_free_config_descriptor(struct libusb_config_descriptor *config);
|
||||||
|
|
||||||
|
/*****************************************************************************************
|
||||||
|
Prototype : void cyusb_control_transfer(cyusb_handle *h, unsigned char bmRequestType,
|
||||||
|
unsigned char bRequest, unsigned short wValue, unsigned short wIndex,
|
||||||
|
unsigned char *data, unsigned short wLength, unsigned int timeout);
|
||||||
|
Description : Performs a USB Control Transfer. Please note that this is a generic transfer
|
||||||
|
function which can be used for READ (IN) and WRITE (OUT) data transfers, as
|
||||||
|
well as transfers with no data. The direction bit (MSB) in the bmRequestType
|
||||||
|
parameter should be set in the case of READ requests, and cleared in the case
|
||||||
|
of WRITE requests.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *h : Device handle
|
||||||
|
unsigned char bmRequestType : The request type field for the setup packet
|
||||||
|
unsigned char bRequest : The request field of the setup packet
|
||||||
|
unsigned short wValue : The value field of the setup packet
|
||||||
|
unsigned short wIndex : The index field of the setup packet
|
||||||
|
unsigned char *data : Data Buffer ( for input or output )
|
||||||
|
unsigned short wLength : The length field of the setup packet.
|
||||||
|
unsigned int timeout : Timeout in milliseconds. 0 means no Timeout.
|
||||||
|
Return Value : 0 on success, or an appropriate LIBUSB_ERROR.
|
||||||
|
****************************************************************************************/
|
||||||
|
extern int cyusb_control_transfer(cyusb_handle *h, unsigned char bmRequestType, unsigned char bRequest,
|
||||||
|
unsigned short wValue, unsigned short wIndex, unsigned char *data, unsigned short wLength,
|
||||||
|
unsigned int timeout);
|
||||||
|
|
||||||
|
/*****************************************************************************************
|
||||||
|
Prototype : void cyusb_control_read(cyusb_handle *h, unsigned char bmRequestType,
|
||||||
|
unsigned char bRequest, unsigned short wValue, unsigned short wIndex,
|
||||||
|
unsigned char *data, unsigned short wLength, unsigned int timeout);
|
||||||
|
Description : Performs a USB control transfer including a READ (IN) data phase. Please
|
||||||
|
note that it is not advisable to use this function with wLength=0, because
|
||||||
|
most USB hosts/devices do not handle this case properly.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *h : Device handle
|
||||||
|
unsigned char bmRequestType : The request type field for the setup packet
|
||||||
|
unsigned char bRequest : The request field of the setup packet
|
||||||
|
unsigned short wValue : The value field of the setup packet
|
||||||
|
unsigned short wIndex : The index field of the setup packet
|
||||||
|
unsigned char *data : Data Buffer ( for input or output )
|
||||||
|
unsigned short wLength : The length field of the setup packet.
|
||||||
|
unsigned int timeout : Timeout in milliseconds. 0 means no Timeout.
|
||||||
|
Return Value : 0 on success, or an appropriate LIBUSB_ERROR.
|
||||||
|
****************************************************************************************/
|
||||||
|
extern int cyusb_control_read(cyusb_handle *h, unsigned char bmRequestType, unsigned char bRequest,
|
||||||
|
unsigned short wValue, unsigned short wIndex, unsigned char *data, unsigned short wLength,
|
||||||
|
unsigned int timeout);
|
||||||
|
|
||||||
|
/*****************************************************************************************
|
||||||
|
Prototype : void cyusb_control_write(cyusb_handle *h, unsigned char bmRequestType,
|
||||||
|
unsigned char bRequest, unsigned short wValue, unsigned short wIndex,
|
||||||
|
unsigned char *data, unsigned short wLength, unsigned int timeout);
|
||||||
|
Description : Performs a USB control transfer including a WRITE (OUT) data phase.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *h : Device handle
|
||||||
|
unsigned char bmRequestType : The request type field for the setup packet
|
||||||
|
unsigned char bRequest : The request field of the setup packet
|
||||||
|
unsigned short wValue : The value field of the setup packet
|
||||||
|
unsigned short wIndex : The index field of the setup packet
|
||||||
|
unsigned char *data : Data Buffer ( for input or output )
|
||||||
|
unsigned short wLength : The length field of the setup packet.
|
||||||
|
unsigned int timeout : Timeout in milliseconds. 0 means no Timeout.
|
||||||
|
Return Value : 0 on success, or an appropriate LIBUSB_ERROR.
|
||||||
|
****************************************************************************************/
|
||||||
|
extern int cyusb_control_write(cyusb_handle *h, unsigned char bmRequestType, unsigned char bRequest,
|
||||||
|
unsigned short wValue, unsigned short wIndex, unsigned char *data, unsigned short wLength,
|
||||||
|
unsigned int timeout);
|
||||||
|
|
||||||
|
/****************************************************************************************
|
||||||
|
Prototype : void cyusb_bulk_transfer(cyusb_handle *h, unsigned char endpoint,
|
||||||
|
unsigned char *data, int length, int *transferred, int timeout);
|
||||||
|
Description : Performs a USB Bulk Transfer.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *h : Device handle
|
||||||
|
unsigned char endpoint : Address of endpoint to comunicate with
|
||||||
|
unsigned char *data : Data Buffer ( for input or output )
|
||||||
|
unsigned short wLength : The length field of the data buffer for read or write
|
||||||
|
int * transferred : Output location of bytes actually transferred
|
||||||
|
unsigned int timeout : Timeout in milliseconds. 0 means no Timeout.
|
||||||
|
Return Value : 0 on success, or an appropriate LIBUSB_ERROR.
|
||||||
|
****************************************************************************************/
|
||||||
|
extern int cyusb_bulk_transfer(cyusb_handle *h, unsigned char endpoint, unsigned char *data,
|
||||||
|
int length, int *transferred, int timeout);
|
||||||
|
|
||||||
|
/****************************************************************************************
|
||||||
|
Prototype : void cyusb_interrupt_transfer(cyusb_handle *h, unsigned char endpoint,
|
||||||
|
unsigned char *data, int length, int *transferred, int timeout);
|
||||||
|
Description : Performs a USB Interrupt Transfer.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *h : Device handle
|
||||||
|
unsigned char endpoint : Address of endpoint to comunicate with
|
||||||
|
unsigned char *data : Data Buffer ( for input or output )
|
||||||
|
unsigned short wLength : The length field of the data buffer for read or write
|
||||||
|
int * transferred : Output location of bytes actually transferred
|
||||||
|
unsigned int timeout : Timeout in milliseconds. 0 means no Timeout.
|
||||||
|
Return Value : 0 on success, or an appropriate LIBUSB_ERROR.
|
||||||
|
****************************************************************************************/
|
||||||
|
extern int cyusb_interrupt_transfer(cyusb_handle *h, unsigned char endpoint, unsigned char *data,
|
||||||
|
int length, int *transferred, unsigned int timeout);
|
||||||
|
|
||||||
|
/****************************************************************************************
|
||||||
|
Prototype : void cyusb_download_fx2(cyusb_handle *h, char *filename,
|
||||||
|
unsigned char vendor_command);
|
||||||
|
Description : Performs firmware download on FX2.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *h : Device handle
|
||||||
|
char * filename : Path where the firmware file is stored
|
||||||
|
unsigned char vendor_command : Vendor command that needs to be passed during download
|
||||||
|
Return Value : 0 on success, or an appropriate LIBUSB_ERROR.
|
||||||
|
****************************************************************************************/
|
||||||
|
extern int cyusb_download_fx2(cyusb_handle *h, char *filename, unsigned char vendor_command);
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************************
|
||||||
|
Prototype : void cyusb_download_fx3(cyusb_handle *h, char *filename);
|
||||||
|
Description : Performs firmware download on FX3.
|
||||||
|
Parameters :
|
||||||
|
cyusb_handle *h : Device handle
|
||||||
|
char *filename : Path where the firmware file is stored
|
||||||
|
Return Value : 0 on success, or an appropriate LIBUSB_ERROR.
|
||||||
|
***************************************************************************************/
|
||||||
|
extern int cyusb_download_fx3(cyusb_handle *h, char *filename);
|
||||||
|
|
||||||
|
#endif /* __CYUSB_H */
|
|
@ -0,0 +1,850 @@
|
||||||
|
/*
|
||||||
|
* Filename : download_fx3.cpp
|
||||||
|
* Description : Downloads FX3 firmware to RAM, I2C EEPROM or SPI Flash.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <libusb-1.0/libusb.h>
|
||||||
|
#include "cyusb.h"
|
||||||
|
|
||||||
|
#define FLASHPROG_VID (0x04b4) // USB VID for the FX3 flash programmer.
|
||||||
|
|
||||||
|
#define MAX_FWIMG_SIZE (512 * 1024) // Maximum size of the firmware binary.
|
||||||
|
#define MAX_WRITE_SIZE (2 * 1024) // Max. size of data that can be written through one vendor command.
|
||||||
|
|
||||||
|
#define I2C_PAGE_SIZE (64) // Page size for I2C EEPROM.
|
||||||
|
#define I2C_SLAVE_SIZE (64 * 1024) // Max. size of data that can fit on one EEPROM address.
|
||||||
|
|
||||||
|
#define SPI_PAGE_SIZE (256) // Page size for SPI flash memory.
|
||||||
|
#define SPI_SECTOR_SIZE (64 * 1024) // Sector size for SPI flash memory.
|
||||||
|
|
||||||
|
#define VENDORCMD_TIMEOUT (5000) // Timeout (in milliseconds) for each vendor command.
|
||||||
|
#define GETHANDLE_TIMEOUT (5) // Timeout (in seconds) for getting a FX3 flash programmer handle.
|
||||||
|
|
||||||
|
/* Utility macros. */
|
||||||
|
#define ROUND_UP(n,v) ((((n) + ((v) - 1)) / (v)) * (v)) // Round n upto a multiple of v.
|
||||||
|
#define GET_LSW(v) ((unsigned short)((v) & 0xFFFF)) // Get Least Significant Word part of an integer.
|
||||||
|
#define GET_MSW(v) ((unsigned short)((v) >> 16)) // Get Most Significant Word part of an integer.
|
||||||
|
|
||||||
|
/* Enumeration representing the FX3 firmware target. */
|
||||||
|
typedef enum {
|
||||||
|
FW_TARGET_NONE = 0, // Invalid value
|
||||||
|
FW_TARGET_RAM, // Program to device RAM
|
||||||
|
FW_TARGET_I2C, // Program to I2C EEPROM
|
||||||
|
FW_TARGET_SPI // Program to SPI Flash
|
||||||
|
} fx3_fw_target;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FW_ACTION_NONE = 0,
|
||||||
|
FW_ACTION_STATUS,
|
||||||
|
FW_ACTION_LOAD,
|
||||||
|
FW_ACTION_READ,
|
||||||
|
FW_ACTION_ERASE
|
||||||
|
} fx3_ldr_action;
|
||||||
|
|
||||||
|
/* Array representing physical size of EEPROM corresponding to each size encoding. */
|
||||||
|
const int i2c_eeprom_size[] =
|
||||||
|
{
|
||||||
|
1024, // bImageCtl[2:0] = 'b000
|
||||||
|
2048, // bImageCtl[2:0] = 'b001
|
||||||
|
4096, // bImageCtl[2:0] = 'b010
|
||||||
|
8192, // bImageCtl[2:0] = 'b011
|
||||||
|
16384, // bImageCtl[2:0] = 'b100
|
||||||
|
32768, // bImageCtl[2:0] = 'b101
|
||||||
|
65536, // bImageCtl[2:0] = 'b110
|
||||||
|
131072 // bImageCtl[2:0] = 'b111
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
fx3_ram_read (
|
||||||
|
cyusb_handle *h,
|
||||||
|
unsigned char *buf,
|
||||||
|
unsigned int ramAddress,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
int index = 0;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
size = (len > MAX_WRITE_SIZE) ? MAX_WRITE_SIZE : len;
|
||||||
|
r = cyusb_control_transfer (h, 0xC0, 0xA0, GET_LSW(ramAddress), GET_MSW(ramAddress),
|
||||||
|
&buf[index], size, VENDORCMD_TIMEOUT);
|
||||||
|
if (r != size) {
|
||||||
|
fprintf (stderr, "Error: Vendor read from FX3 RAM failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ramAddress += size;
|
||||||
|
index += size;
|
||||||
|
len -= size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
fx3_ram_write (
|
||||||
|
cyusb_handle *h,
|
||||||
|
unsigned char *buf,
|
||||||
|
unsigned int ramAddress,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
int index = 0;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
size = (len > MAX_WRITE_SIZE) ? MAX_WRITE_SIZE : len;
|
||||||
|
r = cyusb_control_transfer (h, 0x40, 0xA0, GET_LSW(ramAddress), GET_MSW(ramAddress),
|
||||||
|
&buf[index], size, VENDORCMD_TIMEOUT);
|
||||||
|
if (r != size) {
|
||||||
|
fprintf (stderr, "Error: Vendor write to FX3 RAM failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ramAddress += size;
|
||||||
|
index += size;
|
||||||
|
len -= size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read the firmware image from the file into a buffer. */
|
||||||
|
static int
|
||||||
|
read_firmware_image (
|
||||||
|
const char *filename,
|
||||||
|
unsigned char *buf,
|
||||||
|
int *romsize,
|
||||||
|
int *filesize)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int nbr;
|
||||||
|
struct stat filestat;
|
||||||
|
|
||||||
|
if (stat (filename, &filestat) != 0) {
|
||||||
|
fprintf (stderr, "Error: Failed to stat file %s\n", filename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the file size does not exceed our limits.
|
||||||
|
*filesize = filestat.st_size;
|
||||||
|
if (*filesize > MAX_FWIMG_SIZE) {
|
||||||
|
fprintf (stderr, "Error: File size exceeds maximum firmware image size\n");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = open (filename, O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
fprintf (stderr, "Error: File not found\n");
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
nbr = read (fd, buf, 2); /* Read first 2 bytes, must be equal to 'CY' */
|
||||||
|
if (strncmp ((char *)buf,"CY",2)) {
|
||||||
|
fprintf (stderr, "Error: Image does not have 'CY' at start.\n");
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
nbr = read (fd, buf, 1); /* Read 1 byte. bImageCTL */
|
||||||
|
if (buf[0] & 0x01) {
|
||||||
|
fprintf (stderr, "Error: Image does not contain executable code\n");
|
||||||
|
return -5;
|
||||||
|
}
|
||||||
|
if (romsize != 0)
|
||||||
|
*romsize = i2c_eeprom_size[(buf[0] >> 1) & 0x07];
|
||||||
|
|
||||||
|
nbr = read (fd, buf, 1); /* Read 1 byte. bImageType */
|
||||||
|
if (!(buf[0] == 0xB0)) {
|
||||||
|
fprintf (stderr, "Error: Not a normal FW binary with checksum\n");
|
||||||
|
return -6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the complete firmware binary into a local buffer.
|
||||||
|
lseek (fd, 0, SEEK_SET);
|
||||||
|
nbr = read (fd, buf, *filesize);
|
||||||
|
|
||||||
|
close (fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
fx3_usbboot_download (
|
||||||
|
cyusb_handle *h,
|
||||||
|
const char *filename)
|
||||||
|
{
|
||||||
|
unsigned char *fwBuf;
|
||||||
|
unsigned int *data_p;
|
||||||
|
unsigned int i, checksum;
|
||||||
|
unsigned int address, length;
|
||||||
|
int r, index, filesize;
|
||||||
|
|
||||||
|
fwBuf = (unsigned char *)calloc (1, MAX_FWIMG_SIZE);
|
||||||
|
if (fwBuf == 0) {
|
||||||
|
fprintf (stderr, "Error: Failed to allocate buffer to store firmware binary\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the firmware image into the local RAM buffer.
|
||||||
|
r = read_firmware_image (filename, fwBuf, NULL, &filesize);
|
||||||
|
if (r != 0) {
|
||||||
|
fprintf (stderr, "Error: Failed to read firmware file %s\n", filename);
|
||||||
|
free (fwBuf);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run through each section of code, and use vendor commands to download them to RAM.
|
||||||
|
index = 4;
|
||||||
|
checksum = 0;
|
||||||
|
while (index < filesize) {
|
||||||
|
data_p = (unsigned int *)(fwBuf + index);
|
||||||
|
length = data_p[0];
|
||||||
|
address = data_p[1];
|
||||||
|
if (length != 0) {
|
||||||
|
for (i = 0; i < length; i++)
|
||||||
|
checksum += data_p[2 + i];
|
||||||
|
r = fx3_ram_write (h, fwBuf + index + 8, address, length * 4);
|
||||||
|
if (r != 0) {
|
||||||
|
fprintf (stderr, "Error: Failed to download data to FX3 RAM\n");
|
||||||
|
free (fwBuf);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (checksum != data_p[2]) {
|
||||||
|
fprintf (stderr, "Error: Checksum error in firmware binary\n");
|
||||||
|
free (fwBuf);
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = cyusb_control_transfer (h, 0x40, 0xA0, GET_LSW(address), GET_MSW(address), NULL,
|
||||||
|
0, VENDORCMD_TIMEOUT);
|
||||||
|
if (r != 0)
|
||||||
|
printf ("Info: Ignored error in control transfer: %d\n", r);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
index += (8 + length * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
free (fwBuf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the current device handle corresponds to the FX3 flash programmer. */
|
||||||
|
static int check_fx3_flashprog (cyusb_handle *handle)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
char local[8];
|
||||||
|
|
||||||
|
r = cyusb_control_transfer (handle, 0xC0, 0xB0, 0, 0, (unsigned char *)local, 8, VENDORCMD_TIMEOUT);
|
||||||
|
if ((r != 8) || (strncasecmp (local, "FX3PROG", 7) != 0)) {
|
||||||
|
printf ("Info: Current device is not the FX3 flash programmer\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("Info: Found FX3 flash programmer\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the handle to the FX3 flash programmer device, if found. */
|
||||||
|
static int
|
||||||
|
get_fx3_prog_handle (
|
||||||
|
cyusb_handle **h)
|
||||||
|
{
|
||||||
|
char *progfile_p, *tmp;
|
||||||
|
cyusb_handle *handle;
|
||||||
|
int i, j, r;
|
||||||
|
struct stat filestat;
|
||||||
|
|
||||||
|
handle = *h;
|
||||||
|
r = check_fx3_flashprog (handle);
|
||||||
|
if (r == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
printf ("Info: Trying to download flash programmer to RAM\n");
|
||||||
|
|
||||||
|
tmp = getenv ("CYUSB_ROOT");
|
||||||
|
if (tmp != NULL) {
|
||||||
|
i = strlen (tmp);
|
||||||
|
progfile_p = (char *)malloc (i + 32);
|
||||||
|
strcpy (progfile_p, tmp);
|
||||||
|
strcat (progfile_p, "/fx3_images/cyfxflashprog.img");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
progfile_p = (char *)malloc (32);
|
||||||
|
strcpy (progfile_p, "fx3_images/cyfxflashprog.img");
|
||||||
|
}
|
||||||
|
|
||||||
|
r = stat (progfile_p, &filestat);
|
||||||
|
if (r != 0) {
|
||||||
|
fprintf (stderr, "Error: Failed to find cyfxflashprog.img file\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = fx3_usbboot_download (handle, progfile_p);
|
||||||
|
free (progfile_p);
|
||||||
|
if (r != 0) {
|
||||||
|
fprintf (stderr, "Error: Failed to download flash prog utility\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cyusb_close ();
|
||||||
|
*h = NULL;
|
||||||
|
|
||||||
|
// Now wait for the flash programmer to enumerate, and get a handle to it.
|
||||||
|
for (j = 0; j < GETHANDLE_TIMEOUT; j++) {
|
||||||
|
sleep (1);
|
||||||
|
r = cyusb_open ();
|
||||||
|
if (r > 0) {
|
||||||
|
for (i = 0; i < r; i++) {
|
||||||
|
handle = cyusb_gethandle (i);
|
||||||
|
if (cyusb_getvendor (handle) == FLASHPROG_VID) {
|
||||||
|
r = check_fx3_flashprog (handle);
|
||||||
|
if (r == 0) {
|
||||||
|
printf ("Info: Got handle to FX3 flash programmer\n");
|
||||||
|
*h = handle;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("cyusb close\n");
|
||||||
|
cyusb_close ();
|
||||||
|
printf("cyusb closeD!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf (stderr, "Error: Failed to get handle to flash programmer\n");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fx3_init_progimg(cyusb_handle* h) {
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
r = get_fx3_prog_handle(&h);
|
||||||
|
if (r != 0) {
|
||||||
|
fprintf (stderr, "Error: FX3 flash programmer not found\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
fx3_i2c_write (
|
||||||
|
cyusb_handle *h,
|
||||||
|
unsigned char *buf,
|
||||||
|
int devAddr,
|
||||||
|
int start,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
int index = start;
|
||||||
|
unsigned short address = 0;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
size = (len > MAX_WRITE_SIZE) ? MAX_WRITE_SIZE : len;
|
||||||
|
r = cyusb_control_transfer (h, 0x40, 0xBA, devAddr, address, &buf[index], size, VENDORCMD_TIMEOUT);
|
||||||
|
if (r != size) {
|
||||||
|
fprintf (stderr, "Error: I2C write failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
address += size ;
|
||||||
|
index += size;
|
||||||
|
len -= size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Function to read I2C data and compare against the expected value. */
|
||||||
|
static int
|
||||||
|
fx3_i2c_read (
|
||||||
|
cyusb_handle *h,
|
||||||
|
uint8_t* dst,
|
||||||
|
int devAddr,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
int index = 0;
|
||||||
|
unsigned short address = 0;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
size = (len > MAX_WRITE_SIZE) ? MAX_WRITE_SIZE : len;
|
||||||
|
r = cyusb_control_transfer (h, 0xC0, 0xBB, devAddr, address, dst, size, VENDORCMD_TIMEOUT);
|
||||||
|
if (r != size) {
|
||||||
|
fprintf (stderr, "Error: I2C read failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
address += size;
|
||||||
|
index += size;
|
||||||
|
len -= size;
|
||||||
|
dst += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Function to read I2C data and compare against the expected value. */
|
||||||
|
static int
|
||||||
|
fx3_i2c_read_verify (
|
||||||
|
cyusb_handle *h,
|
||||||
|
unsigned char *expData,
|
||||||
|
int devAddr,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
int index = 0;
|
||||||
|
unsigned short address = 0;
|
||||||
|
int size;
|
||||||
|
unsigned char tmpBuf[MAX_WRITE_SIZE];
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
size = (len > MAX_WRITE_SIZE) ? MAX_WRITE_SIZE : len;
|
||||||
|
r = cyusb_control_transfer (h, 0xC0, 0xBB, devAddr, address, tmpBuf, size, VENDORCMD_TIMEOUT);
|
||||||
|
if (r != size) {
|
||||||
|
fprintf (stderr, "Error: I2C read failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp (expData + index, tmpBuf, size) != 0) {
|
||||||
|
fprintf (stderr, "Error: Failed to read expected data from I2C EEPROM\n");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
address += size ;
|
||||||
|
index += size;
|
||||||
|
len -= size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
fx3_i2cboot_download (
|
||||||
|
cyusb_handle *h,
|
||||||
|
const char *filename)
|
||||||
|
{
|
||||||
|
int romsize, size;
|
||||||
|
int address = 0, offset = 0;
|
||||||
|
int r, filesize;
|
||||||
|
unsigned char *fwBuf = 0;
|
||||||
|
|
||||||
|
// Check if we have a handle to the FX3 flash programmer.
|
||||||
|
r = get_fx3_prog_handle (&h);
|
||||||
|
if (r != 0) {
|
||||||
|
fprintf (stderr, "Error: FX3 flash programmer not found\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate memory for holding the firmware binary.
|
||||||
|
fwBuf = (unsigned char *)calloc (1, MAX_FWIMG_SIZE);
|
||||||
|
|
||||||
|
if (read_firmware_image (filename, fwBuf, &romsize, &filesize)) {
|
||||||
|
fprintf (stderr, "Error: File %s does not contain valid FX3 firmware image\n", filename);
|
||||||
|
free (fwBuf);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("Info: Writing firmware image to I2C EEPROM\n");
|
||||||
|
|
||||||
|
filesize = ROUND_UP(filesize, I2C_PAGE_SIZE);
|
||||||
|
while (filesize != 0) {
|
||||||
|
|
||||||
|
size = (filesize <= romsize) ? filesize : romsize;
|
||||||
|
if (size > I2C_SLAVE_SIZE) {
|
||||||
|
r = fx3_i2c_write (h, fwBuf, address, offset, I2C_SLAVE_SIZE);
|
||||||
|
if (r == 0) {
|
||||||
|
r = fx3_i2c_read_verify (h, fwBuf + offset, address, I2C_SLAVE_SIZE);
|
||||||
|
if (r != 0) {
|
||||||
|
fprintf (stderr, "Error: Read-verify from I2C EEPROM failed\n");
|
||||||
|
free (fwBuf);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = fx3_i2c_write (h, fwBuf, address + 4, offset + I2C_SLAVE_SIZE, size - I2C_SLAVE_SIZE);
|
||||||
|
if (r == 0) {
|
||||||
|
r = fx3_i2c_read_verify (h, fwBuf + offset + I2C_SLAVE_SIZE,
|
||||||
|
address + 4, size - I2C_SLAVE_SIZE);
|
||||||
|
if (r != 0) {
|
||||||
|
fprintf (stderr, "Error: Read-verify from I2C EEPROM failed\n");
|
||||||
|
free (fwBuf);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r = fx3_i2c_write (h, fwBuf, address, offset, size);
|
||||||
|
if (r == 0) {
|
||||||
|
r = fx3_i2c_read_verify (h, fwBuf + offset, address, size);
|
||||||
|
if (r != 0) {
|
||||||
|
fprintf (stderr, "Error: Read-verify from I2C EEPROM failed\n");
|
||||||
|
free (fwBuf);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r != 0) {
|
||||||
|
fprintf (stderr, "Error: Write to I2C EEPROM failed\n");
|
||||||
|
free (fwBuf);
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move to the next slave address. */
|
||||||
|
offset += size;
|
||||||
|
filesize -= size;
|
||||||
|
address++;
|
||||||
|
}
|
||||||
|
|
||||||
|
free (fwBuf);
|
||||||
|
printf ("Info: I2C programming completed\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
fx3_spi_read (
|
||||||
|
cyusb_handle *h,
|
||||||
|
unsigned char *buf,
|
||||||
|
int offset,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
int index = 0;
|
||||||
|
int size;
|
||||||
|
unsigned short page_address = offset / SPI_PAGE_SIZE;
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
size = (len > MAX_WRITE_SIZE) ? MAX_WRITE_SIZE : len;
|
||||||
|
r = cyusb_control_transfer (h, 0xC0, 0xC2, 0, page_address, &buf[index], size, VENDORCMD_TIMEOUT); // TODO: C3? C1?
|
||||||
|
if (r != size) {
|
||||||
|
fprintf (stderr, "Error: Read from SPI flash failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
index += size;
|
||||||
|
len -= size;
|
||||||
|
page_address += (size / SPI_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
fx3_spi_write (
|
||||||
|
cyusb_handle *h,
|
||||||
|
unsigned char *buf,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
int index = 0;
|
||||||
|
int size;
|
||||||
|
unsigned short page_address = 0;
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
size = (len > MAX_WRITE_SIZE) ? MAX_WRITE_SIZE : len;
|
||||||
|
r = cyusb_control_transfer (h, 0x40, 0xC2, 0, page_address, &buf[index], size, VENDORCMD_TIMEOUT);
|
||||||
|
if (r != size) {
|
||||||
|
fprintf (stderr, "Error: Write to SPI flash failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
index += size;
|
||||||
|
len -= size;
|
||||||
|
page_address += (size / SPI_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
fx3_spi_erase_sector (
|
||||||
|
cyusb_handle *h,
|
||||||
|
unsigned short nsector)
|
||||||
|
{
|
||||||
|
unsigned char stat;
|
||||||
|
int timeout = 10;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = cyusb_control_transfer (h, 0x40, 0xC4, 1, nsector, NULL, 0, VENDORCMD_TIMEOUT);
|
||||||
|
if (r != 0) {
|
||||||
|
fprintf (stderr, "Error: SPI sector erase failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the SPI flash to become ready again.
|
||||||
|
do {
|
||||||
|
r = cyusb_control_transfer (h, 0xC0, 0xC4, 0, 0, &stat, 1, VENDORCMD_TIMEOUT);
|
||||||
|
if (r != 1) {
|
||||||
|
fprintf (stderr, "Error: SPI status read failed\n");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
sleep (1);
|
||||||
|
timeout--;
|
||||||
|
} while ((stat != 0) && (timeout > 0));
|
||||||
|
|
||||||
|
if (stat != 0) {
|
||||||
|
fprintf (stderr, "Error: Timed out on SPI status read\n");
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("Info: Erased sector %d of SPI flash\n", nsector);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
fx3_spiboot_download (
|
||||||
|
cyusb_handle *h,
|
||||||
|
const char *filename)
|
||||||
|
{
|
||||||
|
unsigned char *fwBuf;
|
||||||
|
int r, i, filesize;
|
||||||
|
|
||||||
|
// Check if we have a handle to the FX3 flash programmer.
|
||||||
|
r = get_fx3_prog_handle (&h);
|
||||||
|
if (r != 0) {
|
||||||
|
fprintf (stderr, "Error: FX3 flash programmer not found\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate memory for holding the firmware binary.
|
||||||
|
fwBuf = (unsigned char *)calloc (1, MAX_FWIMG_SIZE);
|
||||||
|
if (fwBuf == 0) {
|
||||||
|
fprintf (stderr, "Error: Failed to allocate buffer to store firmware binary\n");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read_firmware_image (filename, fwBuf, NULL, &filesize)) {
|
||||||
|
fprintf (stderr, "Error: File %s does not contain valid FX3 firmware image\n", filename);
|
||||||
|
free (fwBuf);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
filesize = ROUND_UP(filesize, SPI_PAGE_SIZE);
|
||||||
|
|
||||||
|
// Erase as many SPI sectors as are required to hold the firmware binary.
|
||||||
|
for (i = 0; i < ((filesize + SPI_SECTOR_SIZE - 1) / SPI_SECTOR_SIZE); i++) {
|
||||||
|
r = fx3_spi_erase_sector (h, i);
|
||||||
|
if (r != 0) {
|
||||||
|
fprintf (stderr, "Error: Failed to erase SPI flash\n");
|
||||||
|
free (fwBuf);
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r = fx3_spi_write (h, fwBuf, filesize);
|
||||||
|
if (r != 0) {
|
||||||
|
fprintf (stderr, "Error: SPI write failed\n");
|
||||||
|
} else {
|
||||||
|
printf ("Info: SPI flash programming completed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
free (fwBuf);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
print_usage_info (
|
||||||
|
const char *arg0)
|
||||||
|
{
|
||||||
|
printf ("%s: FX3 firmware programmer\n\n", arg0);
|
||||||
|
printf ("Usage:\n");
|
||||||
|
printf ("\t%s -h: Print this help message\n\n", arg0);
|
||||||
|
printf ("\t%s-a status: display device status\n", arg0);
|
||||||
|
printf ("\t%s-a load -t <target> -i <img filename>: Program firmware binary from <img filename> to <target>\n", arg0);
|
||||||
|
printf ("\t\t\twhere <target> is one of:\n");
|
||||||
|
printf ("\t\t\t\t\"RAM\": Program to FX3 RAM\n");
|
||||||
|
printf ("\t\t\t\t\"I2C\": Program to I2C EEPROM\n");
|
||||||
|
printf ("\t\t\t\t\"SPI\": Program to SPI FLASH\n");
|
||||||
|
printf ("\t%s-a read -t <target> -i <filename> -o <offset> -l <length>: read data from <target> into <filename> at the specified offset and length (in bytes)\n", arg0);
|
||||||
|
printf ("\t%s-a erase -t <target> -o <offset>: erase sector #<offset> from <target>\n", arg0);
|
||||||
|
printf ("\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main (
|
||||||
|
int argc,
|
||||||
|
char **argv)
|
||||||
|
{
|
||||||
|
char *filename = NULL;
|
||||||
|
char *tgt_str = NULL;
|
||||||
|
fx3_fw_target tgt = FW_TARGET_NONE;
|
||||||
|
fx3_ldr_action act = FW_ACTION_NONE;
|
||||||
|
long offset = -1, length = -1;
|
||||||
|
|
||||||
|
/* Parse command line arguments. */
|
||||||
|
for (int i = 1; i < argc; i++) {
|
||||||
|
if ((strcasecmp (argv[i], "-h") == 0) || (strcasecmp (argv[i], "--help") == 0)) {
|
||||||
|
print_usage_info (argv[0]);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
if ((strcasecmp (argv[i], "-t") == 0) || (strcasecmp (argv[i], "--target") == 0)) {
|
||||||
|
if (argc > (i + 1)) {
|
||||||
|
tgt_str = argv[i + 1];
|
||||||
|
if (strcasecmp (argv[i + 1], "ram") == 0)
|
||||||
|
tgt = FW_TARGET_RAM;
|
||||||
|
if (strcasecmp (argv[i + 1], "i2c") == 0)
|
||||||
|
tgt = FW_TARGET_I2C;
|
||||||
|
if (strcasecmp (argv[i + 1], "spi") == 0)
|
||||||
|
tgt = FW_TARGET_SPI;
|
||||||
|
if (tgt == FW_TARGET_NONE) {
|
||||||
|
fprintf (stderr, "Error: Unknown target %s\n", argv[i + 1]);
|
||||||
|
print_usage_info (argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
} else if (!strcmp(argv[i], "-a")) {
|
||||||
|
if (argc > i + 1) {
|
||||||
|
const char* acts = argv[i+1];
|
||||||
|
if (!strcasecmp(acts, "status")) act = FW_ACTION_STATUS;
|
||||||
|
if (!strcasecmp(acts, "load")) act = FW_ACTION_LOAD;
|
||||||
|
if (!strcasecmp(acts, "read")) act = FW_ACTION_READ;
|
||||||
|
if (!strcasecmp(acts, "erase")) act = FW_ACTION_ERASE;
|
||||||
|
if (act == FW_ACTION_NONE) {
|
||||||
|
fprintf(stderr, "Error: unknown action '%s'\n", acts);
|
||||||
|
print_usage_info(argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
} else if ((strcmp (argv[i], "-i") == 0) || (strcmp (argv[i], "--image") == 0)) {
|
||||||
|
if (argc > (i + 1))
|
||||||
|
filename = argv[i + 1];
|
||||||
|
i++;
|
||||||
|
} else if (!strcmp(argv[i], "-o")) {
|
||||||
|
if (argc > i + 1)
|
||||||
|
if (sscanf(argv[i+1], "%li", &offset) != 1)
|
||||||
|
offset = -1;
|
||||||
|
++i;
|
||||||
|
} else if (!strcmp(argv[i], "-l")) {
|
||||||
|
if (argc > i + 1)
|
||||||
|
if (sscanf(argv[i+1], "%li", &length) != 1)
|
||||||
|
length = -1;
|
||||||
|
++i;
|
||||||
|
} else {
|
||||||
|
fprintf (stderr, "Error: Unknown parameter %s\n", argv[i]);
|
||||||
|
print_usage_info (argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int r = cyusb_open ();
|
||||||
|
if (r < 0) {
|
||||||
|
fprintf (stderr, "Error opening library\n");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
else if (r == 0) {
|
||||||
|
fprintf (stderr, "Error: No FX3 device found\n");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
else if (r > 1) {
|
||||||
|
fprintf (stderr, "Error: More than one Cypress device found\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cyusb_handle *h = cyusb_gethandle (0);
|
||||||
|
|
||||||
|
switch (act) {
|
||||||
|
case FW_ACTION_STATUS:
|
||||||
|
r = check_fx3_flashprog(h);
|
||||||
|
break;
|
||||||
|
case FW_ACTION_LOAD:
|
||||||
|
if ((filename == NULL) || (tgt == FW_TARGET_NONE)) {
|
||||||
|
fprintf (stderr, "Error: Firmware binary or target not specified\n");
|
||||||
|
print_usage_info (argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (tgt) {
|
||||||
|
case FW_TARGET_RAM:
|
||||||
|
r = fx3_usbboot_download (h, filename);
|
||||||
|
break;
|
||||||
|
case FW_TARGET_I2C:
|
||||||
|
r = fx3_i2cboot_download (h, filename);
|
||||||
|
break;
|
||||||
|
case FW_TARGET_SPI:
|
||||||
|
r = fx3_spiboot_download (h, filename);
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FW_ACTION_READ: {
|
||||||
|
if ((filename == NULL) || (tgt == FW_TARGET_NONE)) {
|
||||||
|
fprintf (stderr, "Error: Firmware binary or target not specified\n");
|
||||||
|
print_usage_info (argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length <= 0 || offset == -1) {
|
||||||
|
fprintf(stderr, "Error: need an offset and length (both in bytes) specified.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
uint8_t *databuf = (uint8_t*)calloc(1, length);
|
||||||
|
|
||||||
|
switch (tgt) {
|
||||||
|
case FW_TARGET_RAM:
|
||||||
|
r = fx3_ram_read(h, databuf, offset, length);
|
||||||
|
break;
|
||||||
|
case FW_TARGET_I2C:
|
||||||
|
r = fx3_init_progimg(h);
|
||||||
|
printf("progimg done\n");
|
||||||
|
if (r == 0) r = fx3_i2c_read(h, databuf, offset, length);
|
||||||
|
printf("read done\n");
|
||||||
|
break;
|
||||||
|
case FW_TARGET_SPI:
|
||||||
|
r = fx3_init_progimg(h);
|
||||||
|
if (r == 0) r = fx3_spi_read(h, databuf, offset, length);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
r = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r == 0) {
|
||||||
|
FILE* rf = fopen(filename, "wb");
|
||||||
|
fwrite(databuf, 1, length, rf);
|
||||||
|
fclose(rf);
|
||||||
|
}
|
||||||
|
free(databuf);
|
||||||
|
} break;
|
||||||
|
case FW_ACTION_ERASE:
|
||||||
|
if ((tgt == FW_TARGET_NONE)) {
|
||||||
|
fprintf (stderr, "Error: Target not specified\n");
|
||||||
|
print_usage_info (argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset <= 0) {
|
||||||
|
fprintf(stderr, "Error: need an offset (in sectors) specified.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (tgt) {
|
||||||
|
case FW_TARGET_SPI:
|
||||||
|
r = fx3_init_progimg(h);
|
||||||
|
if (r == 0) r = fx3_spi_erase_sector(h, offset);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Info: target does not support erasing\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r != 0) {
|
||||||
|
fprintf (stderr, "Error: FX3 firmware programming failed\n");
|
||||||
|
return 3;
|
||||||
|
} else {
|
||||||
|
printf ("FX3 firmware programming to %s completed\n", tgt_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,918 @@
|
||||||
|
/*******************************************************************************\
|
||||||
|
* Program Name : libcyusb.cpp *
|
||||||
|
* Author : V. Radhakrishnan ( rk@atr-labs.com ) *
|
||||||
|
* License : LGPL Ver 2.1 *
|
||||||
|
* Copyright : Cypress Semiconductors Inc. / ATR-LABS *
|
||||||
|
* Date written : March 12, 2012 *
|
||||||
|
* Modification Notes : *
|
||||||
|
* *
|
||||||
|
* This program is the main library for all cyusb applications to use. *
|
||||||
|
* This is a thin wrapper around libusb *
|
||||||
|
\*******************************************************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <libusb-1.0/libusb.h>
|
||||||
|
#include "cyusb.h"
|
||||||
|
|
||||||
|
/* Maximum length of a string read from the Configuration file (/etc/cyusb.conf) for the library. */
|
||||||
|
#define MAX_CFG_LINE_LENGTH (120)
|
||||||
|
|
||||||
|
/* Maximum length for a filename. */
|
||||||
|
#define MAX_FILEPATH_LENGTH (256)
|
||||||
|
|
||||||
|
/* Maximum size of EZ-USB FX3 firmware binary. Limited by amount of RAM available. */
|
||||||
|
#define FX3_MAX_FW_SIZE (524288)
|
||||||
|
|
||||||
|
static struct cydev cydev[MAXDEVICES]; /* List of devices of interest that are connected. */
|
||||||
|
static int nid; /* Number of Interesting Devices. */
|
||||||
|
static libusb_device **list; /* libusb device list used by the cyusb library. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
struct VPD
|
||||||
|
Used to store information about the devices of interest listed in /etc/cyusb.conf
|
||||||
|
*/
|
||||||
|
struct VPD {
|
||||||
|
unsigned short vid; /* USB Vendor ID. */
|
||||||
|
unsigned short pid; /* USB Product ID. */
|
||||||
|
char desc[MAX_STR_LEN]; /* Device description. */
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct VPD vpd[MAX_ID_PAIRS]; /* Known device database. */
|
||||||
|
static int maxdevices; /* Number of devices in the vpd database. */
|
||||||
|
static unsigned int checksum = 0; /* Checksum calculated on the Cypress firmware binary. */
|
||||||
|
|
||||||
|
/* The following variables are used by the cyusb_linux application. */
|
||||||
|
char pidfile[MAX_FILEPATH_LENGTH]; /* Full path to the PID file specified in /etc/cyusb.conf */
|
||||||
|
char logfile[MAX_FILEPATH_LENGTH]; /* Full path to the LOG file specified in /etc/cyusb.conf */
|
||||||
|
int logfd; /* File descriptor for the LOG file. */
|
||||||
|
int pidfd; /* File descriptor for the PID file. */
|
||||||
|
|
||||||
|
/* isempty:
|
||||||
|
Check if the first L characters of the string buf are white-space characters.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
isempty (
|
||||||
|
char *buf,
|
||||||
|
int L)
|
||||||
|
{
|
||||||
|
bool flag = true;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < L; ++i ) {
|
||||||
|
if ( (buf[i] != ' ') && ( buf[i] != '\t' ) ) {
|
||||||
|
flag = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse_configfile:
|
||||||
|
Parse the /etc/cyusb.conf file and get the list of USB devices of interest.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
parse_configfile (
|
||||||
|
void)
|
||||||
|
{
|
||||||
|
FILE *inp;
|
||||||
|
char buf[MAX_CFG_LINE_LENGTH];
|
||||||
|
char *cp1, *cp2, *cp3;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
inp = fopen("/etc/cyusb.conf", "r");
|
||||||
|
if (inp == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memset(buf,'\0',MAX_CFG_LINE_LENGTH);
|
||||||
|
while ( fgets(buf,MAX_CFG_LINE_LENGTH,inp) ) {
|
||||||
|
if ( buf[0] == '#' ) /* Any line starting with a # is a comment */
|
||||||
|
continue;
|
||||||
|
if ( buf[0] == '\n' )
|
||||||
|
continue;
|
||||||
|
if ( isempty(buf,strlen(buf)) ) /* Any blank line is also ignored */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
cp1 = strtok(buf," =\t\n");
|
||||||
|
if ( !strcmp(cp1,"LogFile") ) {
|
||||||
|
cp2 = strtok(NULL," \t\n");
|
||||||
|
strcpy(logfile,cp2);
|
||||||
|
}
|
||||||
|
else if ( !strcmp(cp1,"PIDFile") ) {
|
||||||
|
cp2 = strtok(NULL," \t\n");
|
||||||
|
strcpy(pidfile,cp2);
|
||||||
|
}
|
||||||
|
else if ( !strcmp(cp1,"<VPD>") ) {
|
||||||
|
while ( fgets(buf,MAX_CFG_LINE_LENGTH,inp) ) {
|
||||||
|
if ( buf[0] == '#' ) /* Any line starting with a # is a comment */
|
||||||
|
continue;
|
||||||
|
if ( buf[0] == '\n' )
|
||||||
|
continue;
|
||||||
|
if ( isempty(buf,strlen(buf)) ) /* Any blank line is also ignored */
|
||||||
|
continue;
|
||||||
|
if ( maxdevices == (MAX_ID_PAIRS - 1) )
|
||||||
|
continue;
|
||||||
|
cp1 = strtok(buf," \t\n");
|
||||||
|
if ( !strcmp(cp1,"</VPD>") )
|
||||||
|
break;
|
||||||
|
cp2 = strtok(NULL, " \t");
|
||||||
|
cp3 = strtok(NULL, " \t\n");
|
||||||
|
|
||||||
|
vpd[maxdevices].vid = strtol(cp1,NULL,16);
|
||||||
|
vpd[maxdevices].pid = strtol(cp2,NULL,16);
|
||||||
|
strncpy(vpd[maxdevices].desc,cp3,MAX_STR_LEN);
|
||||||
|
vpd[maxdevices].desc[MAX_STR_LEN - 1] = '\0'; /* Make sure of NULL-termination. */
|
||||||
|
|
||||||
|
++maxdevices;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("Error in config file /etc/cyusb.conf: %s \n",buf);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(inp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* device_is_of_interest:
|
||||||
|
Check whether the current USB device is among the devices of interest.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
device_is_of_interest (
|
||||||
|
cyusb_device *d)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int found = 0;
|
||||||
|
struct libusb_device_descriptor desc;
|
||||||
|
int vid;
|
||||||
|
int pid;
|
||||||
|
|
||||||
|
libusb_get_device_descriptor(d, &desc);
|
||||||
|
vid = desc.idProduct;
|
||||||
|
pid = desc.idProduct;
|
||||||
|
|
||||||
|
for ( i = 0; i < maxdevices; ++i ) {
|
||||||
|
if ( (vpd[i].vid == desc.idVendor) && (vpd[i].pid == desc.idProduct) ) {
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_getvendor:
|
||||||
|
Get the Vendor ID for the current USB device.
|
||||||
|
*/
|
||||||
|
unsigned short
|
||||||
|
cyusb_getvendor (
|
||||||
|
cyusb_handle *h)
|
||||||
|
{
|
||||||
|
struct libusb_device_descriptor d;
|
||||||
|
cyusb_get_device_descriptor(h, &d);
|
||||||
|
return d.idVendor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_getproduct:
|
||||||
|
Get the Product ID for the current USB device.
|
||||||
|
*/
|
||||||
|
unsigned short
|
||||||
|
cyusb_getproduct (
|
||||||
|
cyusb_handle *h)
|
||||||
|
{
|
||||||
|
struct libusb_device_descriptor d;
|
||||||
|
cyusb_get_device_descriptor(h, &d);
|
||||||
|
return d.idProduct;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* renumerate:
|
||||||
|
Get handles to and store information about all USB devices of interest.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
renumerate (
|
||||||
|
void)
|
||||||
|
{
|
||||||
|
cyusb_device *dev = NULL;
|
||||||
|
cyusb_handle *handle = NULL;
|
||||||
|
int numdev;
|
||||||
|
int found = 0;
|
||||||
|
int i;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
numdev = libusb_get_device_list(NULL, &list);
|
||||||
|
if ( numdev < 0 ) {
|
||||||
|
printf("Library: Error in enumerating devices...\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
nid = 0;
|
||||||
|
for ( i = 0; i < numdev; ++i ) {
|
||||||
|
cyusb_device *tdev = list[i];
|
||||||
|
if ( device_is_of_interest(tdev) ) {
|
||||||
|
cydev[nid].dev = tdev;
|
||||||
|
r = libusb_open(tdev, &cydev[nid].handle);
|
||||||
|
if ( r ) {
|
||||||
|
printf("Error in opening device\n");
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
handle = cydev[nid].handle;
|
||||||
|
|
||||||
|
cydev[nid].vid = cyusb_getvendor(handle);
|
||||||
|
cydev[nid].pid = cyusb_getproduct(handle);
|
||||||
|
cydev[nid].is_open = 1;
|
||||||
|
cydev[nid].busnum = cyusb_get_busnumber(handle);
|
||||||
|
cydev[nid].devaddr = cyusb_get_devaddr(handle);
|
||||||
|
++nid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_open:
|
||||||
|
Opens handles to all USB devices of interest, and returns their count.
|
||||||
|
*/
|
||||||
|
int cyusb_open (
|
||||||
|
void)
|
||||||
|
{
|
||||||
|
int fd1;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
fd1 = open("/etc/cyusb.conf", O_RDONLY);
|
||||||
|
if ( fd1 < 0 ) {
|
||||||
|
printf("/etc/cyusb.conf file not found. Exiting\n");
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
close(fd1);
|
||||||
|
parse_configfile(); /* Parse the file and store information inside exported data structures */
|
||||||
|
}
|
||||||
|
|
||||||
|
r = libusb_init(NULL);
|
||||||
|
if (r) {
|
||||||
|
printf("Error in initializing libusb library...\n");
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get list of USB devices of interest. */
|
||||||
|
r = renumerate();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_open:
|
||||||
|
Open a handle to the USB device with specified vid/pid.
|
||||||
|
*/
|
||||||
|
int cyusb_open (
|
||||||
|
unsigned short vid,
|
||||||
|
unsigned short pid)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
cyusb_handle *h = NULL;
|
||||||
|
|
||||||
|
r = libusb_init(NULL);
|
||||||
|
if (r) {
|
||||||
|
printf("Error in initializing libusb library...\n");
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
h = libusb_open_device_with_vid_pid(NULL, vid, pid);
|
||||||
|
if ( !h ) {
|
||||||
|
printf("Device not found\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
cydev[0].dev = libusb_get_device(h);
|
||||||
|
cydev[0].handle = h;
|
||||||
|
cydev[0].vid = cyusb_getvendor(h);
|
||||||
|
cydev[0].pid = cyusb_getproduct(h);
|
||||||
|
cydev[0].is_open = 1;
|
||||||
|
cydev[0].busnum = cyusb_get_busnumber(h);
|
||||||
|
cydev[0].devaddr = cyusb_get_devaddr(h);
|
||||||
|
nid = 1;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_error:
|
||||||
|
Print verbose information about the error returned by the cyusb API. These are essentially descriptions of
|
||||||
|
status values defined as part of the libusb library.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
cyusb_error (
|
||||||
|
int err)
|
||||||
|
{
|
||||||
|
switch (err)
|
||||||
|
{
|
||||||
|
case -1:
|
||||||
|
fprintf(stderr, "Input/output error\n");
|
||||||
|
break;
|
||||||
|
case -2:
|
||||||
|
fprintf(stderr, "Invalid parameter\n");
|
||||||
|
break;
|
||||||
|
case -3:
|
||||||
|
fprintf(stderr, "Access denied (insufficient permissions)\n");
|
||||||
|
break;
|
||||||
|
case -4:
|
||||||
|
fprintf(stderr, "No such device. Disconnected...?\n");
|
||||||
|
break;
|
||||||
|
case -5:
|
||||||
|
fprintf(stderr, "Entity not found\n");
|
||||||
|
break;
|
||||||
|
case -6:
|
||||||
|
fprintf(stderr, "Resource busy\n");
|
||||||
|
break;
|
||||||
|
case -7:
|
||||||
|
fprintf(stderr, "Operation timed out\n");
|
||||||
|
break;
|
||||||
|
case -8:
|
||||||
|
fprintf(stderr, "Overflow\n");
|
||||||
|
break;
|
||||||
|
case -9:
|
||||||
|
fprintf(stderr, "Pipe error\n");
|
||||||
|
break;
|
||||||
|
case -10:
|
||||||
|
fprintf(stderr, "System call interrupted, ( due to signal ? )\n");
|
||||||
|
break;
|
||||||
|
case -11:
|
||||||
|
fprintf(stderr, "Insufficient memory\n");
|
||||||
|
break;
|
||||||
|
case -12:
|
||||||
|
fprintf(stderr, "Operation not supported/implemented\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Unknown internal error\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_gethandle:
|
||||||
|
Get a handle to the USB device with specified index.
|
||||||
|
*/
|
||||||
|
cyusb_handle *
|
||||||
|
cyusb_gethandle (
|
||||||
|
int index)
|
||||||
|
{
|
||||||
|
return cydev[index].handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_close:
|
||||||
|
Close all device handles and de-initialize the libusb library.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
cyusb_close (
|
||||||
|
void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for ( i = 0; i < nid; ++i ) {
|
||||||
|
libusb_close(cydev[i].handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
libusb_free_device_list(list, 1);
|
||||||
|
libusb_exit(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_get_busnumber:
|
||||||
|
Get USB bus number on which the specified device is connected.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_get_busnumber (
|
||||||
|
cyusb_handle *h)
|
||||||
|
{
|
||||||
|
cyusb_device *tdev = libusb_get_device(h);
|
||||||
|
return libusb_get_bus_number( tdev );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_get_devaddr:
|
||||||
|
Get USB device address assigned to the specified device.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_get_devaddr (
|
||||||
|
cyusb_handle *h)
|
||||||
|
{
|
||||||
|
cyusb_device *tdev = libusb_get_device(h);
|
||||||
|
return libusb_get_device_address( tdev );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_get_max_packet_size:
|
||||||
|
Get the max packet size for the specified USB endpoint.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_get_max_packet_size (
|
||||||
|
cyusb_handle *h,
|
||||||
|
unsigned char endpoint)
|
||||||
|
{
|
||||||
|
cyusb_device *tdev = libusb_get_device(h);
|
||||||
|
return ( libusb_get_max_packet_size(tdev, endpoint) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_get_max_iso_packet_size:
|
||||||
|
Calculate the maximum packet size which a specific isochronous endpoint is capable of sending or
|
||||||
|
receiving in the duration of 1 microframe.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_get_max_iso_packet_size (
|
||||||
|
cyusb_handle *h,
|
||||||
|
unsigned char endpoint)
|
||||||
|
{
|
||||||
|
cyusb_device *tdev = libusb_get_device(h);
|
||||||
|
return ( libusb_get_max_iso_packet_size(tdev, endpoint) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_get_configuration:
|
||||||
|
Get the id of the active configuration on the specified USB device.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_get_configuration (
|
||||||
|
cyusb_handle *h,
|
||||||
|
int *config)
|
||||||
|
{
|
||||||
|
return ( libusb_get_configuration(h, config) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_set_configuration:
|
||||||
|
Set the active configuration for the specified USB device.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_set_configuration (
|
||||||
|
cyusb_handle *h,
|
||||||
|
int config)
|
||||||
|
{
|
||||||
|
return ( libusb_set_configuration(h, config) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_claim_interface:
|
||||||
|
Claim the specified USB device interface, so that cyusb/libusb APIs can be used for transfers on the
|
||||||
|
corresponding endpoints.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_claim_interface (
|
||||||
|
cyusb_handle *h,
|
||||||
|
int interface)
|
||||||
|
{
|
||||||
|
return ( libusb_claim_interface(h, interface) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_release_interface:
|
||||||
|
Release an interface previously claimed using cyusb_claim_interface.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_release_interface (
|
||||||
|
cyusb_handle *h,
|
||||||
|
int interface)
|
||||||
|
{
|
||||||
|
return ( libusb_release_interface(h, interface) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_set_interface_alt_setting:
|
||||||
|
Select the alternate setting for the specified USB device and interface.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_set_interface_alt_setting (
|
||||||
|
cyusb_handle *h,
|
||||||
|
int interface,
|
||||||
|
int altsetting)
|
||||||
|
{
|
||||||
|
return ( libusb_set_interface_alt_setting(h, interface, altsetting) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_clear_halt:
|
||||||
|
Clear the STALL or HALT condition on the specified endpoint.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_clear_halt (
|
||||||
|
cyusb_handle *h,
|
||||||
|
unsigned char endpoint)
|
||||||
|
{
|
||||||
|
return ( libusb_clear_halt(h, endpoint) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_reset_device:
|
||||||
|
Perform a USB port reset to re-initialize the specified USB device.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_reset_device (
|
||||||
|
cyusb_handle *h)
|
||||||
|
{
|
||||||
|
return ( libusb_reset_device(h) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_kernel_driver_active:
|
||||||
|
Check whether a Kernel driver is currently bound to the specified USB device and interface. The cyusb/libusb
|
||||||
|
APIs cannot be used on an interface while a kernel driver is active.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_kernel_driver_active (
|
||||||
|
cyusb_handle *h,
|
||||||
|
int interface)
|
||||||
|
{
|
||||||
|
return ( libusb_kernel_driver_active(h, interface) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_detach_kernel_driver:
|
||||||
|
Detach the kernel driver from the specified USB device and interface, so that the APIs can be used.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_detach_kernel_driver (
|
||||||
|
cyusb_handle *h,
|
||||||
|
int interface)
|
||||||
|
{
|
||||||
|
return ( libusb_detach_kernel_driver(h, interface) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_attach_kernel_driver:
|
||||||
|
Re-attach the kernel driver from the specified USB device and interface.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_attach_kernel_driver (
|
||||||
|
cyusb_handle *h,
|
||||||
|
int interface)
|
||||||
|
{
|
||||||
|
return ( libusb_attach_kernel_driver(h, interface) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_get_device_descriptor:
|
||||||
|
Get the device descriptor for the specified USB device.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_get_device_descriptor (
|
||||||
|
cyusb_handle *h,
|
||||||
|
struct libusb_device_descriptor *desc)
|
||||||
|
{
|
||||||
|
cyusb_device *tdev = libusb_get_device(h);
|
||||||
|
return ( libusb_get_device_descriptor(tdev, desc ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_get_active_config_descriptor:
|
||||||
|
Get the active configuration descriptor for the specified USB device.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_get_active_config_descriptor (
|
||||||
|
cyusb_handle *h,
|
||||||
|
struct libusb_config_descriptor **config)
|
||||||
|
{
|
||||||
|
cyusb_device *tdev = libusb_get_device(h);
|
||||||
|
return ( libusb_get_active_config_descriptor(tdev, config) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_get_config_descriptor:
|
||||||
|
Get the configuration descriptor at index config_index, for the specified USB device.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_get_config_descriptor (
|
||||||
|
cyusb_handle *h,
|
||||||
|
unsigned char config_index,
|
||||||
|
struct libusb_config_descriptor **config)
|
||||||
|
{
|
||||||
|
cyusb_device *tdev = libusb_get_device(h);
|
||||||
|
return ( libusb_get_config_descriptor(tdev, config_index, config) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_get_config_descriptor_by_value:
|
||||||
|
Get the configuration descriptor with value bConfigurationValue for the specified USB device.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_get_config_descriptor_by_value (
|
||||||
|
cyusb_handle *h,
|
||||||
|
unsigned char bConfigurationValue,
|
||||||
|
struct usb_config_descriptor **config)
|
||||||
|
{
|
||||||
|
cyusb_device *tdev = libusb_get_device(h);
|
||||||
|
return ( libusb_get_config_descriptor_by_value(tdev, bConfigurationValue,
|
||||||
|
(struct libusb_config_descriptor **)config) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_free_config_descriptor:
|
||||||
|
Free the configuration descriptor structure after it has been used.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
cyusb_free_config_descriptor (
|
||||||
|
struct libusb_config_descriptor *config)
|
||||||
|
{
|
||||||
|
libusb_free_config_descriptor( (libusb_config_descriptor *)config );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_get_string_descriptor_ascii:
|
||||||
|
Get the specified USB string descriptor in the format of an ASCII string.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_get_string_descriptor_ascii (
|
||||||
|
cyusb_handle *h,
|
||||||
|
unsigned char index,
|
||||||
|
unsigned char *data,
|
||||||
|
int length)
|
||||||
|
{
|
||||||
|
cyusb_device *tdev = libusb_get_device(h);
|
||||||
|
return ( libusb_get_string_descriptor_ascii(h, index, data, length) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_get_descriptor:
|
||||||
|
Get a USB descriptor given the type and index.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_get_descriptor (
|
||||||
|
cyusb_handle *h,
|
||||||
|
unsigned char desc_type,
|
||||||
|
unsigned char desc_index,
|
||||||
|
unsigned char *data,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
return ( libusb_get_descriptor(h, desc_type, desc_index, data, len) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_get_string_descriptor:
|
||||||
|
Get the USB string descriptor with the specified index.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_get_string_descriptor (
|
||||||
|
cyusb_handle *h,
|
||||||
|
unsigned char desc_index,
|
||||||
|
unsigned short langid,
|
||||||
|
unsigned char *data,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
return ( libusb_get_string_descriptor(h, desc_index, langid, data, len) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_control_transfer:
|
||||||
|
Perform the desired USB control transfer (can be read or write based on the bmRequestType value).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_control_transfer (
|
||||||
|
cyusb_handle *h,
|
||||||
|
unsigned char bmRequestType,
|
||||||
|
unsigned char bRequest,
|
||||||
|
unsigned short wValue,
|
||||||
|
unsigned short wIndex,
|
||||||
|
unsigned char *data,
|
||||||
|
unsigned short wLength,
|
||||||
|
unsigned int timeout)
|
||||||
|
{
|
||||||
|
return ( libusb_control_transfer(h, bmRequestType, bRequest, wValue, wIndex, data, wLength, timeout) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_control_read:
|
||||||
|
Perform a read transfer on the USB control endpoint.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_control_read (
|
||||||
|
cyusb_handle *h,
|
||||||
|
unsigned char bmRequestType,
|
||||||
|
unsigned char bRequest,
|
||||||
|
unsigned short wValue,
|
||||||
|
unsigned short wIndex,
|
||||||
|
unsigned char *data,
|
||||||
|
unsigned short wLength,
|
||||||
|
unsigned int timeout)
|
||||||
|
{
|
||||||
|
/* Set the direction bit to indicate a read transfer. */
|
||||||
|
return ( libusb_control_transfer(h, bmRequestType | 0x80, bRequest, wValue, wIndex, data, wLength, timeout) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_control_write:
|
||||||
|
Perform a write transfer on the USB control endpoint. This can be a zero byte (no data) transfer as well.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_control_write (
|
||||||
|
cyusb_handle *h,
|
||||||
|
unsigned char bmRequestType,
|
||||||
|
unsigned char bRequest,
|
||||||
|
unsigned short wValue,
|
||||||
|
unsigned short wIndex,
|
||||||
|
unsigned char *data,
|
||||||
|
unsigned short wLength,
|
||||||
|
unsigned int timeout)
|
||||||
|
{
|
||||||
|
/* Clear the direction bit to indicate a write transfer. */
|
||||||
|
return ( libusb_control_transfer(h, bmRequestType & 0x7F, bRequest, wValue, wIndex, data, wLength, timeout) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_bulk_transfer:
|
||||||
|
Perform a data transfer on a USB Bulk endpoint.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_bulk_transfer (
|
||||||
|
cyusb_handle *h,
|
||||||
|
unsigned char endpoint,
|
||||||
|
unsigned char *data,
|
||||||
|
int length,
|
||||||
|
int *transferred,
|
||||||
|
int timeout)
|
||||||
|
{
|
||||||
|
return ( libusb_bulk_transfer(h, endpoint, data, length, transferred, timeout) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_interrupt_transfer:
|
||||||
|
Perform a data transfer on a USB interrupt endpoint.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_interrupt_transfer (
|
||||||
|
cyusb_handle *h,
|
||||||
|
unsigned char endpoint,
|
||||||
|
unsigned char *data,
|
||||||
|
int length,
|
||||||
|
int *transferred,
|
||||||
|
unsigned int timeout)
|
||||||
|
{
|
||||||
|
return ( libusb_interrupt_transfer(h, endpoint, data, length, transferred, timeout) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_download_fx2:
|
||||||
|
Download firmware to the Cypress FX2/FX2LP device using USB vendor commands.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_download_fx2 (
|
||||||
|
cyusb_handle *h,
|
||||||
|
char *filename,
|
||||||
|
unsigned char vendor_command)
|
||||||
|
{
|
||||||
|
FILE *fp = NULL;
|
||||||
|
char buf[256];
|
||||||
|
char tbuf1[3];
|
||||||
|
char tbuf2[5];
|
||||||
|
char tbuf3[3];
|
||||||
|
unsigned char reset = 0;
|
||||||
|
int r;
|
||||||
|
int count = 0;
|
||||||
|
unsigned char num_bytes = 0;
|
||||||
|
unsigned short address = 0;
|
||||||
|
unsigned char *dbuf = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
fp = fopen(filename, "r" );
|
||||||
|
tbuf1[2] ='\0';
|
||||||
|
tbuf2[4] = '\0';
|
||||||
|
tbuf3[2] = '\0';
|
||||||
|
|
||||||
|
/* Place the FX2/FX2LP CPU in reset, so that the vendor commands can be handled by the device. */
|
||||||
|
reset = 1;
|
||||||
|
r = cyusb_control_transfer(h, 0x40, 0xA0, 0xE600, 0x00, &reset, 0x01, 1000);
|
||||||
|
if ( !r ) {
|
||||||
|
printf("Error in control_transfer\n");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
sleep(1);
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
|
||||||
|
while ( fgets(buf, 256, fp) != NULL ) {
|
||||||
|
if ( buf[8] == '1' )
|
||||||
|
break;
|
||||||
|
strncpy(tbuf1,buf+1,2);
|
||||||
|
num_bytes = strtoul(tbuf1,NULL,16);
|
||||||
|
strncpy(tbuf2,buf+3,4);
|
||||||
|
address = strtoul(tbuf2,NULL,16);
|
||||||
|
dbuf = (unsigned char *)malloc(num_bytes);
|
||||||
|
for ( i = 0; i < num_bytes; ++i ) {
|
||||||
|
strncpy(tbuf3,&buf[9+i*2],2);
|
||||||
|
dbuf[i] = strtoul(tbuf3,NULL,16);
|
||||||
|
}
|
||||||
|
|
||||||
|
r = cyusb_control_transfer(h, 0x40, vendor_command, address, 0x00, dbuf, num_bytes, 1000);
|
||||||
|
if ( !r ) {
|
||||||
|
printf("Error in control_transfer\n");
|
||||||
|
free(dbuf);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
count += num_bytes;
|
||||||
|
free(dbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Total bytes downloaded = %d\n", count);
|
||||||
|
sleep(1);
|
||||||
|
|
||||||
|
/* Bring the CPU out of reset to run the newly loaded firmware. */
|
||||||
|
reset = 0;
|
||||||
|
r = cyusb_control_transfer(h, 0x40, 0xA0, 0xE600, 0x00, &reset, 0x01, 1000);
|
||||||
|
fclose(fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* control_transfer:
|
||||||
|
Internal function that issues the vendor command that incrementally loads firmware segments to the
|
||||||
|
Cypress FX3 device RAM.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
control_transfer (
|
||||||
|
cyusb_handle *h,
|
||||||
|
unsigned int address,
|
||||||
|
unsigned char *dbuf,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
int r;
|
||||||
|
int b;
|
||||||
|
unsigned int *pint;
|
||||||
|
int index;
|
||||||
|
|
||||||
|
int balance = len;
|
||||||
|
pint = (unsigned int *)dbuf;
|
||||||
|
|
||||||
|
index = 0;
|
||||||
|
while ( balance > 0 ) {
|
||||||
|
if ( balance > 4096 )
|
||||||
|
b = 4096;
|
||||||
|
else b = balance;
|
||||||
|
r = cyusb_control_transfer (h, 0x40, 0xA0, ( address & 0x0000ffff ), address >> 16,
|
||||||
|
&dbuf[index], b, 1000);
|
||||||
|
if ( r != b ) {
|
||||||
|
printf("Error in control_transfer\n");
|
||||||
|
}
|
||||||
|
address += b ;
|
||||||
|
balance -= b;
|
||||||
|
index += b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the firmware checksum as the download is being performed. */
|
||||||
|
for ( j = 0; j < len/4; ++j )
|
||||||
|
checksum += pint[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cyusb_download_fx3:
|
||||||
|
Download a firmware binary the Cypress FX3 device RAM.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
cyusb_download_fx3 (
|
||||||
|
cyusb_handle *h,
|
||||||
|
const char *filename)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
unsigned char buf[FX3_MAX_FW_SIZE];
|
||||||
|
int nbr;
|
||||||
|
int dlen;
|
||||||
|
int count;
|
||||||
|
unsigned int *pdbuf = NULL;
|
||||||
|
unsigned int address;
|
||||||
|
unsigned int *pint;
|
||||||
|
unsigned int program_entry;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
fd = open(filename, O_RDONLY);
|
||||||
|
if ( fd < 0 ) {
|
||||||
|
printf("File not found\n");
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf("File successfully opened\n");
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
checksum = 0;
|
||||||
|
nbr = read(fd, buf, 2); /* Read first 2 bytes, must be equal to 'CY' */
|
||||||
|
if ( strncmp((char *)buf,"CY",2) ) {
|
||||||
|
printf("Image does not have 'CY' at start. aborting\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
nbr = read(fd, buf, 1); /* Read 1 byte. bImageCTL */
|
||||||
|
if ( buf[0] & 0x01 ) {
|
||||||
|
printf("Image does not contain executable code\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
nbr = read(fd, buf, 1); /* Read 1 byte. bImageType */
|
||||||
|
if ( !(buf[0] == 0xB0) ) {
|
||||||
|
printf("Not a normal FW binary with checksum\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
nbr = read(fd, buf, 4); /* Read Length of section 1,2,3, ... */
|
||||||
|
pdbuf = (unsigned int *)buf;
|
||||||
|
dlen = *pdbuf;
|
||||||
|
nbr = read(fd,buf,4); /* Read Address of section 1,2,3,... */
|
||||||
|
pint = (unsigned int *)buf;
|
||||||
|
address = *pint;
|
||||||
|
if ( dlen != 0 ) {
|
||||||
|
nbr = read(fd, buf, dlen*4); /* Read data bytes */
|
||||||
|
control_transfer(h, address, buf, dlen*4);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
program_entry = address;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nbr = read(fd, buf, 4); /* Read checksum */
|
||||||
|
pdbuf = (unsigned int *)buf;
|
||||||
|
if ( *pdbuf != checksum ) {
|
||||||
|
printf("Error in checksum\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
r = cyusb_control_transfer(h, 0x40, 0xA0, (program_entry & 0x0000ffff ) , program_entry >> 16, NULL, 0, 1000);
|
||||||
|
if ( r ) {
|
||||||
|
printf("Ignored error in control_transfer: %d\n", r);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*[]*/
|
||||||
|
|
Loading…
Reference in New Issue