2323 */
2424public class DFUDevice {
2525
26- private final UsbDevice usbDevice_ ;
27- private final int interfaceNumber_ ;
28- private final int transferSize_ ;
29- private final Version dfuVersion_ ;
26+ private final UsbDevice usbDevice ;
27+ private final int interfaceNumber ;
28+ private final int transferSize ;
29+ private final Version dfuVersion ;
3030
31- private List <Segment > segments_ ;
31+ private List <Segment > segments ;
3232
3333 /**
3434 * Gets all connected DFU devices
@@ -89,73 +89,76 @@ public static int getDFUInterfaceNumber(UsbDevice device) {
8989 * @param usbDevice the USB device
9090 */
9191 public DFUDevice (UsbDevice usbDevice ) {
92- usbDevice_ = usbDevice ;
93- interfaceNumber_ = getDFUInterfaceNumber (usbDevice );
92+ this . usbDevice = usbDevice ;
93+ interfaceNumber = getDFUInterfaceNumber (usbDevice );
9494
9595 var configDesc = usbDevice .getConfigurationDescriptor ();
9696 int offset = getDFUDescriptorOffset (configDesc );
9797 assert offset > 0 ;
9898
99- transferSize_ = getInt16 (configDesc , offset + 5 );
100- dfuVersion_ = new Version (getInt16 (configDesc , offset + 7 ));
99+ transferSize = getInt16 (configDesc , offset + 5 );
100+ dfuVersion = new Version (getInt16 (configDesc , offset + 7 ));
101101 }
102102
103103 /**
104104 * Gets the DFU protocol version.
105105 * @return the protocol version
106106 */
107- public Version dfuVersion () {
108- return dfuVersion_ ;
107+ public Version getDfuVersion () {
108+ return dfuVersion ;
109109 }
110110
111111 /**
112112 * Gets the device serial number.
113113 * @return the serial number
114114 */
115- public String serialNumber () {
116- return usbDevice_ .getSerialNumber ();
115+ public String getSerialNumber () {
116+ return usbDevice .getSerialNumber ();
117117 }
118118
119119 /**
120120 * Opens the DFU device for communication.
121121 */
122122 public void open () {
123- usbDevice_ .open ();
124- usbDevice_ .claimInterface (interfaceNumber_ );
125- segments_ = Segment .getSegments (usbDevice_ , interfaceNumber_ );
123+ usbDevice .open ();
124+ usbDevice .claimInterface (interfaceNumber );
125+ segments = Segment .getSegments (usbDevice , interfaceNumber );
126126 clearErrorIfNeeded ();
127127 }
128128
129129 /**
130130 * Closes the DFU device.
131131 */
132132 public void close () {
133- usbDevice_ .close ();
133+ usbDevice .close ();
134134 }
135135
136136 /**
137137 * Clears an error status.
138138 */
139139 public void clearStatus () {
140- var setup = new UsbControlTransfer ( CLASS , INTERFACE , DFURequest .CLEAR_STATUS . value () , 0 , interfaceNumber_ );
141- usbDevice_ .controlTransferOut (setup , null );
140+ var transfer = createDfuControlTransfer ( DFURequest .CLEAR_STATUS , 0 );
141+ usbDevice .controlTransferOut (transfer , null );
142142 }
143143
144144 /**
145145 * Aborts the download mode.
146146 */
147147 public void abort () {
148- var setup = new UsbControlTransfer ( CLASS , INTERFACE , DFURequest .ABORT . value () , 0 , interfaceNumber_ );
149- usbDevice_ .controlTransferOut (setup , null );
148+ var transfer = createDfuControlTransfer ( DFURequest .ABORT , 0 );
149+ usbDevice .controlTransferOut (transfer , null );
150150 }
151151
152152 /**
153153 * Gets the full DFU status
154154 * @return the status
155155 */
156156 public DFUStatus getStatus () {
157- var setup = new UsbControlTransfer (CLASS , INTERFACE , DFURequest .GET_STATUS .value (), 0 , interfaceNumber_ );
158- return DFUStatus .fromBytes (usbDevice_ .controlTransferIn (setup , 6 ));
157+ var transfer = createDfuControlTransfer (DFURequest .GET_STATUS , 0 );
158+ var response = usbDevice .controlTransferIn (transfer , 6 );
159+ if (response .length != 6 )
160+ throw new DFUException ("Invalid response from GET_STATUS request" );
161+ return DFUStatus .fromBytes (response );
159162 }
160163
161164 /**
@@ -168,7 +171,6 @@ public byte[] read(int address, int length) {
168171 expectState (DeviceState .DFU_IDLE , DeviceState .DFU_DNLOAD_IDLE );
169172 setAddress (address );
170173 exitDownloadMode ();
171-
172174 expectState (DeviceState .DFU_IDLE , DeviceState .DFU_UPLOAD_IDLE );
173175
174176 var result = new byte [length ];
@@ -177,17 +179,28 @@ public byte[] read(int address, int length) {
177179 int offset = 0 ;
178180 int blockNum = 2 ;
179181 while (offset < length ) {
180- int chunkSize = Math .min (transferSize_ , length - offset );
181- var setup = new UsbControlTransfer ( CLASS , INTERFACE , DFURequest .UPLOAD . value () , blockNum , interfaceNumber_ );
182- var chunk = usbDevice_ .controlTransferIn (setup , chunkSize );
182+ int chunkSize = Math .min (transferSize , length - offset );
183+ var transfer = createDfuControlTransfer ( DFURequest .UPLOAD , blockNum );
184+ var chunk = usbDevice .controlTransferIn (transfer , chunkSize );
183185 System .arraycopy (chunk , 0 , result , offset , chunkSize );
184186 offset += chunkSize ;
185187 blockNum += 1 ;
186188 }
187189
188- // request zero lenght chunk to exit out of upload mode
189- var setup = new UsbControlTransfer (CLASS , INTERFACE , DFURequest .UPLOAD .value (), blockNum , interfaceNumber_ );
190- usbDevice_ .controlTransferIn (setup , 0 );
190+ // request zero length chunk to exit out of upload mode
191+ var transfer = createDfuControlTransfer (DFURequest .UPLOAD , blockNum );
192+ usbDevice .controlTransferIn (transfer , 0 );
193+
194+ DFUStatus status ;
195+ try {
196+ status = getStatus ();
197+ } catch (DFUException e ) {
198+ // Device might respond with an empty response; try again
199+ status = getStatus ();
200+ }
201+
202+ if (status .state () != DeviceState .DFU_IDLE )
203+ throw new DFUException ("Unexpected state after exiting from upload mode" );
191204
192205 return result ;
193206 }
@@ -201,13 +214,13 @@ public void verify(byte[] firmware) {
201214 public void download (byte [] firmware ) {
202215 int length = firmware .length ;
203216
204- // validate start and end address exist and are writable
217+ // validate that start and end address exist and are writable
205218 int startAddress = STM32 .FLASH_BASE_ADDRESS ;
206219 var firstPage = getWritablePage (startAddress );
207220 getWritablePage (startAddress + length );
208221
209- usbDevice_ .selectAlternateSetting (interfaceNumber_ , firstPage .segment ().altSetting ());
210- System .out .printf ("Target memory segment: %s%n" , firstPage .segment ().name ());
222+ usbDevice .selectAlternateSetting (interfaceNumber , firstPage .segment ().getAltSetting ());
223+ System .out .printf ("Target memory segment: %s%n" , firstPage .segment ().getName ());
211224
212225 // erase if needed
213226 if (firstPage .isErasable ())
@@ -219,14 +232,14 @@ public void download(byte[] firmware) {
219232 int offset = 0 ;
220233 int transaction = 2 ;
221234 while (offset < length ) {
222- int chunkSize = Math .min (length - offset , transferSize_ );
235+ int chunkSize = Math .min (length - offset , transferSize );
223236
224237 byte [] chunk = new byte [chunkSize ];
225238 System .arraycopy (firmware , offset , chunk , 0 , chunkSize );
226239
227240 System .out .printf ("Writing data at 0x%x (size 0x%x)%n" , startAddress + offset , chunkSize );
228- var setup = new UsbControlTransfer ( CLASS , INTERFACE , DFURequest .DOWNLOAD . value () , transaction , interfaceNumber_ );
229- usbDevice_ .controlTransferOut (setup , chunk );
241+ var transfer = createDfuControlTransfer ( DFURequest .DOWNLOAD , transaction );
242+ usbDevice .controlTransferOut (transfer , chunk );
230243
231244 finishDownloadCommand ("writing data" );
232245
@@ -243,7 +256,7 @@ public void download(byte[] firmware) {
243256 * Only applicable to erasable sector, i.e. flash memory.
244257 * </p>
245258 * <p>
246- * Only entire pages can be erase . If start and end address to not fall onto
259+ * Only entire pages can be erased . If start and end address to not fall onto
247260 * page boundaries, this method will extend the range to be erased.
248261 * </p>
249262 * @param startAddress the start address of the range
@@ -261,28 +274,28 @@ public void erase(int startAddress, int length) {
261274
262275 System .out .printf ("Erasing page at 0x%x (size 0x%x)%n" , page .startAddress (), page .pageSize ());
263276 erasePage (page .startAddress ());
264- startAddress = page .endAddress ();
277+ startAddress = page .getEndAddress ();
265278 }
266279 }
267280
268281 public void erasePage (int address ) {
269- execDownloadCommandWithAddress ((byte ) 0x41 , "erasing page" , address );
282+ executeSpecialCommand ((byte ) 0x41 , "erasing page" , address );
270283 }
271284
272285 public void setAddress (int address ) {
273- execDownloadCommandWithAddress ((byte ) 0x21 , "setting address" , address );
286+ executeSpecialCommand ((byte ) 0x21 , "setting address" , address );
274287 }
275288
276- private void execDownloadCommandWithAddress (byte command , String action , int address ) {
277- var setup = new UsbControlTransfer ( CLASS , INTERFACE , DFURequest .DOWNLOAD . value () , 0 , interfaceNumber_ );
289+ private void executeSpecialCommand (byte command , String action , int address ) {
290+ var transfer = createDfuControlTransfer ( DFURequest .DOWNLOAD , 0 );
278291 var data = new byte [] {
279292 command ,
280293 (byte ) address ,
281294 (byte ) (address >> 8 ),
282295 (byte ) (address >> 16 ),
283296 (byte ) (address >> 24 )
284297 };
285- usbDevice_ .controlTransferOut (setup , data );
298+ usbDevice .controlTransferOut (transfer , data );
286299
287300 finishDownloadCommand (action );
288301 }
@@ -311,7 +324,7 @@ private Page getWritablePage(int address) {
311324 }
312325
313326 private Page findPage (int address ) {
314- return Segment .findPage (segments_ , address );
327+ return Segment .findPage (segments , address );
315328 }
316329
317330 private void exitDownloadMode () {
@@ -327,8 +340,8 @@ private void exitDownloadMode() {
327340 public void startApplication () {
328341 expectState (DeviceState .DFU_IDLE , DeviceState .DFU_DNLOAD_IDLE );
329342
330- var setup = new UsbControlTransfer ( CLASS , INTERFACE , DFURequest .DOWNLOAD . value (), 2 , interfaceNumber_ );
331- usbDevice_ .controlTransferOut (setup , null );
343+ var transfer = createDfuControlTransfer ( DFURequest .DOWNLOAD , 0 );
344+ usbDevice .controlTransferOut (transfer , null );
332345
333346 var status = getStatus ();
334347 if (status .state () != DeviceState .DFU_MANIFEST )
@@ -365,4 +378,9 @@ private static void sleep(int millis) {
365378 throw new DFUException ("Sleep failed" , e );
366379 }
367380 }
381+
382+ private UsbControlTransfer createDfuControlTransfer (DFURequest request , int value ) {
383+ return new UsbControlTransfer (CLASS , INTERFACE , request .ordinal (), value , interfaceNumber );
384+ }
385+
368386}
0 commit comments