// Path: public-java/io/iamcontent-usb/src/main/java/com/iamcontent/io/usb/EasedUsbDevice.java
// public static EasedUsbDevice eased(UsbDevice device) {
// 	if (device instanceof EasyUsbDevice) 
// 		return (EasedUsbDevice) device;
// 	else
// 		return new EasedUsbDevice(device);
// }
// 
// Path: public-java/devices/iamcontent-pololu-servo-controllers/src/main/java/com/iamcontent/device/controller/pololu/maestro/MaestroCardType.java
// public enum MaestroCardType {
// 	
// 	MICRO_MAESTRO_6(6),
// 	MINI_MAESTRO_12(12),
// 	MINI_MAESTRO_18(18),
// 	MINI_MAESTRO_24(24);
// 	
// 	private final int channelCount;
// 
// 	private MaestroCardType(int channelCount) {
// 		this.channelCount = channelCount;
// 	}
// 
// 	public int channelCount() {
// 		return channelCount;
// 	}
// }
// 
// Path: public-java/devices/iamcontent-pololu-servo-controllers/src/main/java/com/iamcontent/device/controller/pololu/maestro/PololuMaestroServoCard.java
// public interface PololuMaestroServoCard {
// 
// 	interface State {
// 		short getPosition(short channel);
// 	}
// 	
// 	void setPosition(short channel, short position);
// 	void setSpeed(short channel, short speed);
// 	void setAcceleration(short channel, short acceleration);
// 
// 	short getPosition(short channel);
// 	State getState();
// 	
// 	MaestroCardType getType();
// 
// }
// 
// Path: public-java/io/iamcontent-usb/src/main/java/com/iamcontent/io/usb/EasyUsbDevice.java
// @SuppressWarnings("rawtypes")
// public interface EasyUsbDevice extends UsbDevice {
// 	String getManufacturerString();
// 
// 	String getSerialNumberString();
// 
// 	String getProductString();
// 
// 	UsbStringDescriptor getUsbStringDescriptor(byte index);
// 
// 	String getString(byte index);
// 
// 	void syncSubmit(UsbControlIrp irp);
// 
// 	void asyncSubmit(UsbControlIrp irp);
// 
// 	void syncSubmit(List list);
// 
// 	void asyncSubmit(List list);
// }


import com.iamcontent.device.controller.pololu.maestro.PololuMaestroServoCard;
import com.iamcontent.io.usb.EasyUsbDevice;
import static com.iamcontent.io.usb.EasedUsbDevice.eased;
import static java.util.stream.Collectors.joining;
import static javax.usb.UsbConst.REQUESTTYPE_DIRECTION_IN;
import static javax.usb.UsbConst.REQUESTTYPE_DIRECTION_OUT;
import static javax.usb.UsbConst.REQUESTTYPE_TYPE_VENDOR;
import java.io.Serializable;
import java.util.stream.IntStream;
import javax.usb.UsbControlIrp;
import javax.usb.UsbDevice;
import com.iamcontent.device.controller.pololu.maestro.MaestroCardType;

		this.inRequestCode = inRequestCode;
		this.offsetOfFirstServoStatusBlock = offsetOfFirstServoStatusBlock;
		this.dataIn = new byte[offsetOfFirstServoStatusBlock + sizeOfAllServoStatusBlocks()];
	}

	@Override
	public void setPosition(short channel, short position) {
		device.syncSubmit(outRequest(REQUEST_SET_TARGET, chan(channel), position));
	}

	@Override
	public void setSpeed(short channel, short speed) {
		device.syncSubmit(outRequest(REQUEST_SET_SERVO_VARIABLE, chan(channel), speed));
	}
	
	@Override
	public void setAcceleration(short channel, short acceleration) {
		final int accelerationFlag = 0x80;
		device.syncSubmit(outRequest(REQUEST_SET_SERVO_VARIABLE, (short)(chan(channel) | accelerationFlag), acceleration));
	}
	
	@Override
	public short getPosition(short channel) {
		return getState().getPosition(chan(channel));
	}
	
	@Override
	public State getState() {
		final UsbControlIrp request = inRequest(inRequestCode);
		device.syncSubmit(request);

// Path: public-java/io/iamcontent-usb/src/main/java/com/iamcontent/io/usb/EasedUsbDevice.java
// public static EasedUsbDevice eased(UsbDevice device) {
// 	if (device instanceof EasyUsbDevice) 
// 		return (EasedUsbDevice) device;
// 	else
// 		return new EasedUsbDevice(device);
// }
// 
// Path: public-java/devices/iamcontent-pololu-servo-controllers/src/main/java/com/iamcontent/device/controller/pololu/maestro/MaestroCardType.java
// public enum MaestroCardType {
// 	
// 	MICRO_MAESTRO_6(6),
// 	MINI_MAESTRO_12(12),
// 	MINI_MAESTRO_18(18),
// 	MINI_MAESTRO_24(24);
// 	
// 	private final int channelCount;
// 
// 	private MaestroCardType(int channelCount) {
// 		this.channelCount = channelCount;
// 	}
// 
// 	public int channelCount() {
// 		return channelCount;
// 	}
// }
// 
// Path: public-java/devices/iamcontent-pololu-servo-controllers/src/main/java/com/iamcontent/device/controller/pololu/maestro/PololuMaestroServoCard.java
// public interface PololuMaestroServoCard {
// 
// 	interface State {
// 		short getPosition(short channel);
// 	}
// 	
// 	void setPosition(short channel, short position);
// 	void setSpeed(short channel, short speed);
// 	void setAcceleration(short channel, short acceleration);
// 
// 	short getPosition(short channel);
// 	State getState();
// 	
// 	MaestroCardType getType();
// 
// }
// 
// Path: public-java/io/iamcontent-usb/src/main/java/com/iamcontent/io/usb/EasyUsbDevice.java
// @SuppressWarnings("rawtypes")
// public interface EasyUsbDevice extends UsbDevice {
// 	String getManufacturerString();
// 
// 	String getSerialNumberString();
// 
// 	String getProductString();
// 
// 	UsbStringDescriptor getUsbStringDescriptor(byte index);
// 
// 	String getString(byte index);
// 
// 	void syncSubmit(UsbControlIrp irp);
// 
// 	void asyncSubmit(UsbControlIrp irp);
// 
// 	void syncSubmit(List list);
// 
// 	void asyncSubmit(List list);
// }


// Path: public-java/devices/iamcontent-pololu-servo-controllers/src/main/java/com/iamcontent/device/controller/pololu/maestro/usb/AbstractUsbPololuMaestroServoCard.java
import com.iamcontent.device.controller.pololu.maestro.PololuMaestroServoCard;
import com.iamcontent.io.usb.EasyUsbDevice;
import static com.iamcontent.io.usb.EasedUsbDevice.eased;
import static java.util.stream.Collectors.joining;
import static javax.usb.UsbConst.REQUESTTYPE_DIRECTION_IN;
import static javax.usb.UsbConst.REQUESTTYPE_DIRECTION_OUT;
import static javax.usb.UsbConst.REQUESTTYPE_TYPE_VENDOR;
import java.io.Serializable;
import java.util.stream.IntStream;
import javax.usb.UsbControlIrp;
import javax.usb.UsbDevice;
import com.iamcontent.device.controller.pololu.maestro.MaestroCardType;

		this.inRequestCode = inRequestCode;
		this.offsetOfFirstServoStatusBlock = offsetOfFirstServoStatusBlock;
		this.dataIn = new byte[offsetOfFirstServoStatusBlock + sizeOfAllServoStatusBlocks()];
	}

	@Override
	public void setPosition(short channel, short position) {
		device.syncSubmit(outRequest(REQUEST_SET_TARGET, chan(channel), position));
	}

	@Override
	public void setSpeed(short channel, short speed) {
		device.syncSubmit(outRequest(REQUEST_SET_SERVO_VARIABLE, chan(channel), speed));
	}
	
	@Override
	public void setAcceleration(short channel, short acceleration) {
		final int accelerationFlag = 0x80;
		device.syncSubmit(outRequest(REQUEST_SET_SERVO_VARIABLE, (short)(chan(channel) | accelerationFlag), acceleration));
	}
	
	@Override
	public short getPosition(short channel) {
		return getState().getPosition(chan(channel));
	}
	
	@Override
	public State getState() {
		final UsbControlIrp request = inRequest(inRequestCode);
		device.syncSubmit(request);

		return new PololuState(request.getData());
