Reputation: 988
I would like to exchange data/commands between a camera and an Android tablet device using the bulkTransfer
function. I wrote this Activity, but the method bulkTransfer
returns -1
(error status). Why does it return the error?
public class MainActivity extends Activity {
private TextView text;
private int TIMEOUT = 1000;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.txt);
usbTest();
}
private void usbTest() {
UsbDevice device = (UsbDevice) getIntent().getParcelableExtra(
UsbManager.EXTRA_DEVICE);
if (device == null)
text.setText("device null");
else
text.setText("device not null");
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
text.setText(text.getText() + "\nDevices connected: "
+ deviceList.values().size());
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while (deviceIterator.hasNext()) {
device = deviceIterator.next();
text.setText(text.getText() + "\nDevice name: "
+ device.getDeviceName());
text.setText(text.getText() + "\nDevice protocol: "
+ device.getDeviceProtocol());
text.setText(text.getText() + "\nDevice id: "
+ device.getDeviceId());
text.setText(text.getText() + "\nDevice product id: "
+ device.getProductId());
text.setText(text.getText() + "\nDevice vendor id: "
+ device.getVendorId());
text.setText(text.getText() + "\nDevice class: "
+ device.getDeviceClass());
text.setText(text.getText() + "\nDevice subclass: "
+ device.getDeviceSubclass());
text.setText(text.getText() + "\nDevice interface count: "
+ device.getInterfaceCount());
text.setText(text.getText() + "\n\n");
}
// communicate with device
UsbInterface intf = device.getInterface(0);
UsbEndpoint endpoint = intf.getEndpoint(0);
UsbDeviceConnection connection = manager.openDevice(device);
connection.claimInterface(intf, true);
for (int i = 0; i < intf.getEndpointCount(); i++) {
UsbEndpoint ep = intf.getEndpoint(i);
if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
endpoint = ep;
text.setText("Found: "+i);
}
}
}
// byte[] opensession = { 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,
// 0x10,
// 0x00, 0x00, 0x00, 0x00 };
// connection.bulkTransfer(endpoint, opensession, opensession.length,
// TIMEOUT);
byte[] getEvent = { 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, toByte(0xC7),
toByte(0x90), 0x00, 0x00, 0x00, 0x00 };
int status = connection.bulkTransfer(endpoint, getEvent,
getEvent.length, TIMEOUT);
//text.setText("Status: " + status);
byte[] capture = { 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0E, 0x10,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00 };
connection.bulkTransfer(endpoint, capture, capture.length, TIMEOUT);
// teminate communication
BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
UsbDevice device = (UsbDevice) intent
.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (device != null) {
// call your method that cleans up and closes
// communication with the device
}
}
}
};
}
public static byte toByte(int c) {
return (byte) (c <= 0x7f ? c : ((c % 0x80) - 0x80));
}
}
Upvotes: 42
Views: 2849
Reputation: 3539
A few things that looks wrong in the provided code: a) An OpenSession
request need to be done first with transaction id 0, b) Increment the transaction ids, c) Read from USB_DIR_IN
.
My understanding is that the first request should open a session to the camera, only after this you can use GetEvent
requests. Furthermore, you need to increment the transaction ids and only use id 0 for OpenSession
. Below a quote from a PTP spec I found for Nikon cameras.
TransactionIDs are continuous sequences in numerical order starting from 0x00000001. The TransactionID used for the OpenSession operation shall be 0x00000000.
I open-sourced an Android camera app for Nikon and Canon apps on my Github. The code is a few years old. You will have a hard time to compile it, but the PTP code might be a good reference.
Upvotes: 1
Reputation: 147
Check usb endpoint direction. I've encountered some devices where USB_DIR_OUT was USB_DIR_IN and USB_DIR_IN was USB_DIR_OUT and it was causing some issues.
Upvotes: 1
Reputation: 91
I think this function is not passing the correct endpoint
int status = connection.bulkTransfer(endpoint, getEvent,
getEvent.length, TIMEOUT);
which is coming from
UsbInterface intf = device.getInterface(0);
UsbEndpoint endpoint = intf.getEndpoint(0);
maybe the USB interface is not correct. Please check if index 0 parameter is correct.
Upvotes: 1
Reputation: 553
I suspect you are not correctly searching for interface and endpoint.
see explanation below.
Suggestion: test if the endpoint if it is valid and try to match it with device descriptor.
a interface can have multiple setting.
AFAIK, for camera, their should be three alternate setting for the camera interface.
(I dont know the actual USB camera specification but, this should be applicable to all streaming protocol over USB (as i see in Audio Class))
You need to search for the bulk alternate setting and then perform communication on the endpoint inside it.
Upvotes: 0