package de.uniluebeck.itm.wsn.drivers.telosb; import com.google.common.util.concurrent.TimeLimiter; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; import de.uniluebeck.itm.wsn.drivers.core.exception.FlashEraseFailedException; import de.uniluebeck.itm.wsn.drivers.core.operation.EraseFlashOperation; import de.uniluebeck.itm.wsn.drivers.core.operation.OperationListener; import de.uniluebeck.itm.wsn.drivers.core.operation.TimeLimitedOperation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nullable; public class TelosbEraseFlashOperation extends TimeLimitedOperation<Void> implements EraseFlashOperation { private static final Logger log = LoggerFactory.getLogger(TelosbEraseFlashOperation.class); private final BSLTelosb bsl; @Inject public TelosbEraseFlashOperation(final TimeLimiter timeLimiter, final BSLTelosb bsl, @Assisted final long timeoutMillis, @Assisted @Nullable final OperationListener<Void> operationCallback) { super(timeLimiter, timeoutMillis, operationCallback); this.bsl = bsl; } @Override protected Void callInternal() throws Exception { byte[] reply; if (bsl == null) { throw new NullPointerException("No connection to device (bsl is null)."); } if (log.isDebugEnabled()) { log.debug("eraseFlash() (mass erase)"); } // invoke boot loader if (!bsl.invokeBSL()) { throw new FlashEraseFailedException("Mass erase failed: failed to invoke boot loader"); } try { // send bsl command 'mass erase' bsl.sendBSLCommand(BSLTelosb.CMD_MASSERASE, 0xFF00, 0xA506, null, false); // receive bsl reply reply = bsl.receiveBSLReply(); } catch (Exception e) { throw new FlashEraseFailedException("Mass erase failed: " + e); } if ((reply[0] & 0xff) == BSLTelosb.DATA_NACK) { throw new FlashEraseFailedException("Mass erase failed: received NACK"); } else if (reply.length > 1) { throw new FlashEraseFailedException( "Mass erase failed: received unexpected response of length " + reply.length ); } // transmit default password to unlock protected commands after mass // erase try { if (!bsl.transmitPassword(null, false)) { log.warn( "Received no ACK for password transmission after mass erase. Protected commands are still locked." ); } } catch (Exception e) { throw new FlashEraseFailedException("Error transmitting default password after mass erase: " + e); } return null; } }