【问题标题】:USB bulkTransfer between Android tablet and cameraAndroid 平板电脑和相机之间的 USB 批量传输
【发布时间】:2012-12-08 13:39:14
【问题描述】:

我想使用 bulkTransfer 函数在相机和 Android 平板设备之间交换数据/命令。我写了这个Activity,但是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));
    }

}

【问题讨论】:

  • 设备是否被正确枚举?您不能对位于端点 0 的设备执行批量传输;只控制传输。因此,您需要将设备分配给适当的端点地址。

标签: java android usb android-camera


【解决方案1】:

我认为这个函数没有传递正确的端点

int status = connection.bulkTransfer(endpoint, getEvent,
                                     getEvent.length, TIMEOUT);

来自

UsbInterface intf = device.getInterface(0);
UsbEndpoint endpoint = intf.getEndpoint(0);

可能是 USB 接口不正确。请检查索引0参数是否正确。

【讨论】:

    【解决方案2】:

    检查 USB 端点方向。我遇到了一些 USB_DIR_OUT 是 USB_DIR_IN 而 USB_DIR_IN 是 USB_DIR_OUT 的设备,这会导致一些问题。

    【讨论】:

      【解决方案3】:

      提供的代码中有一些看起来错误的地方:a) 需要首先使用事务 id 0 完成 OpenSession 请求,b) 增加事务 id,c) 从 USB_DIR_IN 读取。

      我的理解是第一个请求应该打开一个会话到相机,只有在这之后你才能使用GetEvent请求。此外,您需要增加事务 id 并且仅将 id 0 用于OpenSession。下面引用了我为尼康相机找到的 PTP 规范。

      TransactionID 是从 0x00000001 开始按数字顺序排列的连续序列。用于 OpenSession 操作的 TransactionID 应为 0x00000000。

      我在Github 上为 Nikon 和 Canon 应用程序开源了一个 Android 相机应用程序。该代码已有几年历史了。您将很难编译它,但 PTP 代码可能是一个很好的参考。

      【讨论】:

        【解决方案4】:

        我怀疑您没有正确搜索接口和端点。

        请参阅下面的说明。

        建议:测试端点是否有效,并尝试与设备描述符匹配。


        一个界面可以有多个设置。

        AFAIK,对于相机,它们应该是相机界面的三个备用设置。

        • 零带宽 -- 内部没有端点 -- 很可能是备用设置 0
        • 等时(如果相机支持)- 内部等时端点
        • 批量 -- 内部批量端点

        (我不知道实际的 USB 摄像头规格,但这应该适用于 USB 上的所有流媒体协议(如我在音频类中看到的))

        您需要搜索批量备用设置,然后在其中的端点上进行通信。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-08-15
          • 2017-02-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多