Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Development Usb Transfer

I am fairly new to Android Development and i have recently been exploring Usb Host.

Would anyone be able to tell me how to use Bulk Transfer so that i can see what an external camera sees but instead show it on my tablet?

Camera : Canon Powershot A1300 Tablet : Iconia A200

I have looked around stack overflow and some other forums but have not yet been able to find a good explanation on how to use Bulk Transfer or what constants to use as parameters for retrieving certain data.

I am able to see the endpoints and set up a connection with the external camera but I do not know where to go from here.

Any help is deeply appreciated.

like image 638
dave sunderland Avatar asked Dec 21 '12 21:12

dave sunderland


1 Answers

The USB Host APIs in Android are fairly thin, by which I mean once you have gone beyond enumerating the interfaces/endpoints and creating a connection it doesn't do much more to assist you. You are then in the realm of communicating with raw USB data transfers, the format of which depend on the device class your camera represents. Your request is somewhat a can of worms, so I will do my best to provide helpful resources.

Unfortunately, storage and media devices are not the simplest device classes to interpret, so it may be difficult if you are just getting your feet wet on USB in general. The best advice I can give is to take a look at the device class specs for the interface class your camera reports (most are either Mass Storage or MTP), which can be found here: http://www.usb.org/developers/devclass_docs

The spec document will enumerate the commands you need to use to communicate with the device. I would also recommend checking out USB In a Nutshell, which does a great job of pointing out how USB requests are constructed in general, which can help you map what you see in a the spec docs to the parameters found in the methods of UsbDeviceConnection: http://www.beyondlogic.org/usbnutshell/usb1.shtml

There will likely be a handful of control commands you need to send to "endpoint 0" initially to set up the camera, and then the remaining transfers will likely take place over the bulk endpoints.

In Android terms, control requests can only be sent synchronously using UsbDeviceConnection.controlTransfer(), meaning this method blocks until the transfer is complete. The parameters that fill in this method are found in the spec docs for your device class.

Requests on bulk endpoints can be sent synchronously via UsbDeviceConnection.bulkTransfer() OR asynchronously using a UsbRequest instance. With UsbRequest you can queue a transfer and then later check back (via UsbDeviceConnection.requestWait()) for the results.

I have some examples on my Github page in using the host APIs to do some basic interrupt and control transfers to get information like device descriptors. Perhaps some of that will be helpful to you as well: https://github.com/devunwired/accessory-samples


With regards to your question about the USB example code:

The request made in this code is just a generic "Get Configuration Descriptor" request that all USB devices must respond to (it's a core command, not class-specific). In fact, its the request where the Android APIs get the information you can query for interfaces and endpoints. The field values come from the Core USB Specification (this command specifically is defined at section 9.4.3 and 9.6.3 in the 3.0 spec): http://www.usb.org/developers/docs/ or a more helpful description you can find from USB in a Nutshell, which has a little more discussion: http://www.beyondlogic.org/usbnutshell/usb5.shtml#ConfigurationDescriptors

The length is somewhat arbitrary, this tells the driver how many bytes to read or write. Most USB host drivers will first query the device descriptor, which includes a field telling the host the Max Packet Size the device supports, and then will use that size as the length for future requests. A full-featured driver would probably make this command and then check the length bytes first (the wTotalLength field of the descriptor) to see if the buffer was large enough, and modify/resend if not. In the example, I just chose 64 for simplicity because that is the "maximum" Max Packet Size the protocol defines as supportable.

Again, then making requests of the specific data your device has to offer, those commands will be found in the specific class document, not the core specification.

like image 57
devunwired Avatar answered Sep 27 '22 18:09

devunwired