@@ -54,7 +54,7 @@ SR_PRIV int ezusb_reset(struct libusb_device_handle *hdl, int set_clear)
5454
5555SR_PRIV int ezusb_install_firmware (struct sr_context * ctx ,
5656 libusb_device_handle * hdl ,
57- const char * name )
57+ const char * name , gboolean fx3 )
5858{
5959 unsigned char * firmware ;
6060 size_t length , offset , chunksize ;
@@ -64,39 +64,82 @@ SR_PRIV int ezusb_install_firmware(struct sr_context *ctx,
6464 * which holds the firmware offset, is only 16 bit wide.
6565 */
6666 firmware = sr_resource_load (ctx , SR_RESOURCE_FIRMWARE ,
67- name , & length , 1 << 16 );
67+ name , & length , ( fx3 ? 536 << 10 : 1 << 16 ) );
6868 if (!firmware )
6969 return SR_ERR ;
7070
7171 sr_info ("Uploading firmware '%s'." , name );
7272
7373 result = SR_OK ;
7474 offset = 0 ;
75- while (offset < length ) {
76- chunksize = MIN (length - offset , FW_CHUNKSIZE );
77-
78- ret = libusb_control_transfer (hdl , LIBUSB_REQUEST_TYPE_VENDOR |
79- LIBUSB_ENDPOINT_OUT , 0xa0 , offset ,
80- 0x0000 , firmware + offset ,
81- chunksize , 100 );
82- if (ret < 0 ) {
83- sr_err ("Unable to send firmware to device: %s." ,
84- libusb_error_name (ret ));
75+ if (fx3 ) {
76+ if (length < 4 ||
77+ firmware [0 ] != 'C' || firmware [1 ] != 'Y' ||
78+ firmware [3 ] != 0xb0 ) {
79+ sr_err ("Invalid signature on firmware" );
8580 g_free (firmware );
8681 return SR_ERR ;
8782 }
88- sr_info ("Uploaded %zu bytes." , chunksize );
89- offset += chunksize ;
83+ offset = 4 ;
84+ }
85+ while (offset < length ) {
86+ size_t addr , sublength , suboffset ;
87+
88+ if (fx3 ) {
89+ if (offset + 4 == length ) {
90+ /* Skip checksum */
91+ offset += 4 ;
92+ break ;
93+ }
94+ if (length < offset + 8 ) {
95+ break ;
96+ }
97+ sublength = RL32 (firmware + offset ) << 2 ;
98+ offset += 4 ;
99+ addr = RL32 (firmware + offset );
100+ offset += 4 ;
101+ if (sublength > length - offset ) {
102+ break ;
103+ }
104+ } else {
105+ sublength = length - offset ;
106+ addr = 0 ;
107+ }
108+ suboffset = 0 ;
109+
110+ do {
111+ chunksize = MIN (sublength - suboffset , FW_CHUNKSIZE );
112+
113+ ret = libusb_control_transfer (hdl , LIBUSB_REQUEST_TYPE_VENDOR |
114+ LIBUSB_ENDPOINT_OUT , 0xa0 , (addr + suboffset ) & 0xffff ,
115+ (addr + suboffset ) >> 16 , firmware + offset + suboffset ,
116+ chunksize , 100 );
117+ if (ret < 0 ) {
118+ sr_err ("Unable to send firmware to device: %s." ,
119+ libusb_error_name (ret ));
120+ g_free (firmware );
121+ return SR_ERR ;
122+ }
123+ sr_info ("Uploaded %zu bytes." , chunksize );
124+ suboffset += chunksize ;
125+ } while (suboffset < sublength );
126+
127+ offset += sublength ;
90128 }
91129 g_free (firmware );
92130
131+ if (offset < length ) {
132+ sr_err ("Firmware file is truncated." );
133+ return SR_ERR ;
134+ }
135+
93136 sr_info ("Firmware upload done." );
94137
95138 return result ;
96139}
97140
98141SR_PRIV int ezusb_upload_firmware (struct sr_context * ctx , libusb_device * dev ,
99- int configuration , const char * name )
142+ int configuration , const char * name , gboolean fx3 )
100143{
101144 struct libusb_device_handle * hdl ;
102145 int ret ;
@@ -129,13 +172,13 @@ SR_PRIV int ezusb_upload_firmware(struct sr_context *ctx, libusb_device *dev,
129172 return SR_ERR ;
130173 }
131174
132- if ((ezusb_reset (hdl , 1 )) < 0 )
175+ if (! fx3 && (ezusb_reset (hdl , 1 )) < 0 )
133176 return SR_ERR ;
134177
135- if (ezusb_install_firmware (ctx , hdl , name ) < 0 )
178+ if (ezusb_install_firmware (ctx , hdl , name , fx3 ) < 0 )
136179 return SR_ERR ;
137180
138- if ((ezusb_reset (hdl , 0 )) < 0 )
181+ if (! fx3 && (ezusb_reset (hdl , 0 )) < 0 )
139182 return SR_ERR ;
140183
141184 libusb_close (hdl );
0 commit comments