/*
* $Id$
*
* Copyright (C) 2003-2015 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.driver.block.usb.storage.scsi;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.nio.ByteBuffer;
import org.jnode.driver.Device;
import org.jnode.driver.DeviceAlreadyRegisteredException;
import org.jnode.driver.DeviceManager;
import org.jnode.driver.Driver;
import org.jnode.driver.DriverException;
import org.jnode.driver.RemovableDeviceAPI;
import org.jnode.driver.block.FSBlockAlignmentSupport;
import org.jnode.driver.block.FSBlockDeviceAPI;
import org.jnode.driver.block.usb.storage.USBStorageConstants;
import org.jnode.driver.block.usb.storage.USBStorageSCSIHostDriver.USBStorageSCSIDevice;
import org.jnode.driver.bus.scsi.SCSIDevice;
import org.jnode.driver.bus.scsi.SCSIDeviceAPI;
import org.jnode.driver.bus.scsi.SCSIException;
import org.jnode.driver.bus.scsi.SCSIHostControllerAPI;
import org.jnode.driver.bus.scsi.cdb.mmc.CapacityData;
import org.jnode.driver.bus.scsi.cdb.mmc.MMCUtils;
import org.jnode.driver.bus.usb.USBPipeListener;
import org.jnode.driver.bus.usb.USBRequest;
import org.jnode.partitions.PartitionTableEntry;
import org.jnode.util.TimeoutException;
public class USBStorageSCSIDriver extends Driver
implements FSBlockDeviceAPI, RemovableDeviceAPI, SCSIHostControllerAPI, USBPipeListener, USBStorageConstants {
/** */
private final FSBlockAlignmentSupport blockAlignment;
/** */
private boolean locked;
/** */
private CapacityData capacity;
/** */
private boolean changed;
/** */
// private final ResourceManager rm;
public USBStorageSCSIDriver() {
this.blockAlignment = new FSBlockAlignmentSupport(this, 2048);
}
@Override
protected void startDevice() throws DriverException {
final Device dev = getDevice();
// Rename the device
try {
final DeviceManager dm = dev.getManager();
synchronized (dm) {
dm.rename(dev, "sg", true);
}
} catch (DeviceAlreadyRegisteredException ex) {
throw new DriverException(ex);
}
this.locked = false;
this.changed = true;
this.capacity = null;
this.blockAlignment.setAlignment(2048);
dev.registerAPI(RemovableDeviceAPI.class, this);
dev.registerAPI(FSBlockDeviceAPI.class, blockAlignment);
}
@Override
protected void stopDevice() throws DriverException {
try {
unlock();
} catch (IOException ex) {
throw new DriverException(ex);
} finally {
final SCSIDevice dev = (SCSIDevice) getDevice();
dev.unregisterAPI(RemovableDeviceAPI.class);
dev.unregisterAPI(FSBlockDeviceAPI.class);
dev.unregisterAPI(SCSIDeviceAPI.class);
}
}
public int getSectorSize() throws IOException {
processChanged();
return capacity.getBlockLength();
}
public PartitionTableEntry getPartitionTableEntry() {
// TODO Auto-generated method stub
return null;
}
public long getLength() throws IOException {
processChanged();
return capacity.getBlockLength() & capacity.getLogicalBlockAddress();
}
public void read(long devOffset, ByteBuffer dest) throws IOException {
processChanged();
if (capacity == null) {
throw new IOException("No medium");
}
}
public void write(long devOffset, ByteBuffer src) throws IOException {
// TODO Auto-generated method stub
}
public void flush() throws IOException {
// TODO Auto-generated method stub
}
public void requestCompleted(USBRequest request) {
// TODO Auto-generated method stub
}
public void requestFailed(USBRequest request) {
// TODO Auto-generated method stub
}
/**
* Unlock the device.
*
* @throws IOException
*/
public synchronized void unlock() throws IOException {
if (!locked) {
final SCSIDevice dev = (SCSIDevice) getDevice();
try {
MMCUtils.setMediaRemoval(dev, false, false);
} catch (SCSIException ex) {
final IOException ioe = new IOException();
ioe.initCause(ex);
throw ioe;
} catch (TimeoutException ex) {
final IOException ioe = new IOException();
ioe.initCause(ex);
throw ioe;
} catch (InterruptedException ex) {
throw new InterruptedIOException();
}
locked = false;
}
}
private void processChanged() throws IOException {
if (changed) {
this.capacity = null;
final USBStorageSCSIDevice dev = (USBStorageSCSIDevice) getDevice();
try {
// Gets the capacity.
this.capacity = MMCUtils.readCapacity(dev);
this.blockAlignment.setAlignment(capacity.getBlockLength());
} catch (SCSIException ex) {
final IOException ioe = new IOException();
ioe.initCause(ex);
throw ioe;
} catch (TimeoutException ex) {
final IOException ioe = new IOException();
ioe.initCause(ex);
throw ioe;
} catch (InterruptedException ex) {
throw new InterruptedIOException();
}
changed = false;
}
}
public boolean canLock() {
return true;
}
/**
* It's a removable device.
*/
public boolean canEject() {
return true;
}
public void lock() throws IOException {
// TODO Auto-generated method stub
}
public boolean isLocked() {
return locked;
}
public void eject() throws IOException {
// TODO Auto-generated method stub
}
@Override
public void load() throws IOException {
//To change body of implemented methods use File | Settings | File Templates.
}
}