USB bulkTransfer между планшетом Android и камерой
Я хотел бы обмениваться данными/командами между камерой и планшетным устройством Android с помощью функции bulkTransfer
. Я написал это действие, но метод bulkTransfer
возвращает -1
(статус ошибки). Почему он возвращает ошибку?
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));
}
}
Ответы
Ответ 1
Я подозреваю, что вы неправильно просматриваете интерфейс и конечную точку.
см. объяснение ниже.
Предложение: проверьте, если конечная точка, если она действительна, и попытайтесь сопоставить ее с дескриптором устройства.
интерфейс может иметь несколько настроек.
AFAIK, для камеры они должны быть тремя альтернативными настройками для интерфейса камеры.
- Zero Bandwidth - нет конечных точек внутри - возможно, альтернативная настройка 0
- Изохронный (если камера поддерживает его) - изохронная конечная точка внутри
- Массовая - основная конечная точка внутри < - место вашего интереса.
(Я не знаю настоящую спецификацию USB-камеры, но это должно быть применимо ко всему потоковому протоколу через USB (как я вижу в Audio Class))
Вам нужно выполнить поиск дополнительной альтернативной настройки, а затем выполнить связь с конечной точкой внутри нее.
Ответ 2
Я думаю, что эта функция не проходит правильную конечную точку
int status = connection.bulkTransfer(endpoint, getEvent,
getEvent.length, TIMEOUT);
который исходит от
UsbInterface intf = device.getInterface(0);
UsbEndpoint endpoint = intf.getEndpoint(0);
возможно интерфейс USB не правильный. Пожалуйста, проверьте, правильно ли указан индекс 0.
Ответ 3
Проверьте направление конечной точки USB. Я сталкивался с некоторыми устройствами, где USB_DIR_OUT был USB_DIR_IN, а USB_DIR_IN был USB_DIR_OUT, и это вызывало некоторые проблемы.
Ответ 4
Несколько вещей, которые выглядят неправильно в предоставленном коде: a) Сначала необходимо выполнить запрос OpenSession
с идентификатором транзакции 0, b) Увеличить идентификаторы транзакции, c) Считать из USB_DIR_IN
.
Насколько я понимаю, первый запрос должен открыть сеанс для камеры, только после этого вы можете использовать запросы GetEvent
. Кроме того, вам нужно увеличить идентификаторы транзакций и использовать только идентификатор 0 для OpenSession
. Ниже приведена цитата из спецификации PTP, которую я нашел для камер Nikon.
TransactionID - это непрерывные последовательности в числовом порядке, начиная с 0x00000001. TransactionID, используемый для операции OpenSession, должен быть 0x00000000.
Я открыл приложение Android для камеры для приложений Nikon и Canon на своем Github. Код несколько лет. Вам будет нелегко его скомпилировать, но PTP-код может быть хорошим справочным материалом.