Table of Contents
- 1. WebApp Directory structure
- 2. Sample App
- 3. Dreamhost servers
- 4. Offline
- 5. Crazy Maik
- 6. Actions and Commands
- 7. session fragment
- 8. Network
- 9. functionality
- 10. printing
- 11. HitiPPR_GetPrinterInfo
- 12. PrintingPhotoUtility
- 13. Network Discovery
- 14. update yii apps
- 15. ACT I. Scene I. Verona. A...
- 16. Scene II. A Street.
- 17. Scene III. Capulet's house.
- 18. Scene IV. A street.
- 19. Scene V. Capulet's house.
- 20. PROLOGUE
- 21. ACT II. Scene I. A lane b...
- 22. Scene II. Capulet's orchard.
- 23. Scene III. Friar Laurence...
- 24. Scene IV. A street.
- 25. Scene V. Capulet's orchard.
- 26. Scene VI. Friar Laurence'...
- 27. ACT III. Scene I. A publi...
- 28. Scene II. Capulet's orchard.
- 29. Scene III. Friar Laurence...
- 30. Scene IV. Capulet's house
- 31. Scene V. Capulet's orchard.
- 32. ACT IV. Scene I. Friar La...
- 33. Scene II. Capulet's house.
- 34. Scene III. Juliet's chamber.
- 35. Scene IV. Capulet's house.
- 36. Scene V. Juliet's chamber.
- 37. ACT V. Scene I. Mantua. A...
- 38. Scene II. Verona. Friar L...
Crazy Maik
The USB camera controller functionality was taken from Crazy Maik's Remote Your Camera App. This App uses standard Android functionality to implement a USB bus controller. There are no dependencies on external libraries.
Android USB Bus controller is well documented, even if scantly explained. The most relevant section details USB host mode.
worker thread
In onCreate()
, a USB Manager is started on a separate thread:
ptp = PtpService.Singleton.getInstance(this);
which starts a new PtpUsbService()
, which in turn calls the standard Android functionality:
this.usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE)
Discovering which devices are present on the USB bus is done by PtpUsbService.initialize()
which also calls PtpUsbService.connect()
. Here either a Canon or Nikon camera
is started
if (device.getVendorId() == PtpConstants.CanonVendorId) {
PtpUsbConnection connection = new PtpUsbConnection(usbManager.openDevice(device), in, out, device.getVendorId(), device.getProductId());
camera = new EosCamera(connection, listener, new WorkerNotifier(context));
}
else if (device.getVendorId() == PtpConstants.NikonVendorId) {
PtpUsbConnection connection = new PtpUsbConnection(usbManager.openDevice(device), in, out, device.getVendorId(), device.getProductId());
camera = new NikonCamera(connection, listener, new WorkerNotifier(context));
}
Both EosCamera
and NikonCamera
extend from PtpCamera
. The constructors for both camera classes call
super(connection, listener, workerListener);
The worker thread which listens to the USB Bus and fetches commands from a queue to set them on the bus, is part of said PtpCamera
class. This class has WorkerThread()
as an inner class. The constructor for PtpCamera()
is:
public PtpCamera(PtpUsbConnection connection, CameraListener listener, WorkerListener workerListener) {
this.connection = connection;
this.listener = listener;
this.workerListener = workerListener;
this.pictureSampleSize = 2;
state = State.Starting;
vendorId = connection.getVendorId();
productId = connection.getProductId();
queue.add(new GetDeviceInfoCommand(this));
openSession();
workerThread.start();
}
}
The last command start and indefinite while (true)
loop
private class WorkerThread extends Thread implements IO
Android executes the WorkerThread.run()
method as a thread in the background. The run()
method contains the indefinite loop. Here is a sanitized version of it:
while (true) {
synchronized (this) {
// allow the loop to be cancel from the outside with workerThread.stop = true;
if (stop) {
break;
}
}
// periodically check the queue for events:
if (lastEventCheck + AppConfig.EVENTCHECK_PERIOD < System.currentTimeMillis()) {
lastEventCheck = System.currentTimeMillis();
PtpCamera.this.queueEventCheck();
}
// see if there is an action (= command) to put on the USB bus:
PtpAction action = null;
try {
action = queue.poll(1000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Log.i(TAG, "InterruptedException " + e.getMessage());
}
// If there is an action in the queue:
if (action != null) {
action.exec(this);
}
}
This details how the USB Bus is managed. We will now investigate how action.exec(this)
communicates actions (=commands) from the App to the USB device (= camera).
