2012-06-04 2 views
13

Я пишу программное обеспечение для обмена данными между таблетки (Motorola Xoom с Android версии 4.0.3 и ядра версии 2.6.39.4) и периферийным устройством с помощью USB Host API предоставленный Android. Я использую только два типа связи:Android USB Host API: объем передачи размер буфера

  • управления: controlTransfer(int requestType, int request, int value, int index, byte[] buffer, int length, int timeout)
  • насыпной: bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int length, int timeout)

передача управления работает нормально, но у меня есть проблема с объемной передачи. Я могу использовать только 32768 в качестве размера буфера для функции bulkTransfer. Нельзя использовать меньше или больше. Я знаю, что больше не могу использовать из-за предела буферной трубы (размер: 32769 байт).

Это периферийное устройство передает данные, которые неправильно считываются функцией bulkTranfer. Я полагаю, что некоторые данные потеряны.

Я нахожу это: In Linux If a process attempts to read from an empty pipe (buffer), then read(2) will block until data is available. If a process attempts to write to a full pipe , then write(2) blocks until sufficient data has been read from the pipe to allow the write to complete.

И основано на том, что мое объяснение проблемы заключается в том, что некоторые данные не записываются трубы (буфер) из-за блокировки флага сделанные записи (2) функции. Я прав? Если это правда, я могу изменить буфер буфера.

  1. Моим первым решением этой проблемы является больший буфер. For kernel >= 2.6.35, you can change the size of a pipe with fcntl(fd, F_SETPIPE_SZ, size), но как я могу найти fd (файловый дескриптор) для USB-трубки?
  2. Второй вариант заключается в использовании ulimit -p SIZE, но параметр p для моего ядра не для трубы, а для процесса.

Кто-нибудь сталкивался с той же проблемой, какие-либо решения?

+0

использование массового перевода, я также столкнулся с проблемой потери данных. смотря на это. Я сообщу вам, как только я найду причину. продолжайте обновлять статус. – yokks

+0

ОК, спасибо за информацию. – syntagma

+0

http://android.serverbox.ch/?p=370 можете ли вы пройти этот разговор? здесь представлена ​​одна логика для обработки входящих данных. надеюсь, это поможет вам. – yokks

ответ

2

Вы должны получить анализатор данных USB, Im, используя этот один: http://www.ellisys.com/products/usbex200/index.php

Используя что-то вроде этого действительно помогло мне, когда я делал тот же тип вещи, что я обнаружил, что вы должны были сделать некоторый тип цикла while.

Для моего устройства у меня был 64 байта данных, поступающих в пакетах для меня, пакет будет два байта управления и 62 для данных, поэтому для моей передачи, я должен был сделать что-то вроде

StringBuilder sb = new StringBuilder(); 
while(bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int length, int timeout) > 2){ 
    for(int i = 2; i < buffer.length(); i++){ 
     sb.append((char) buffer[i]); 
    } 
} 

что-то долго эти строки работали хорошо для меня, у меня была точно такая же проблема, и именно так я ее исправил. У меня есть дополнительная информация, если вам это нужно. Просто комментарий :). Я знаю, что это было очень неприятно для меня. Я использую Acer Iconia A500 с Android 4.0.3 Кстати


Transferring larger amounts of data USB

Transferring data USB

+0

У меня таких нет устройства. Я использовал только USBlyzer для проверки передачи между устройством и платформой Windows.Я не получаю никаких управляющих данных в bulkTransfer и, вероятно, максимальный размер пакета составляет 512 байт. Есть ли у вас предложения? – syntagma

0

Согласно AN232B-04_DataLatencyFlow.pdf, управление потоком необходимо для высоких скоростей передачи данных:

настоятельно рекомендуется, что управление потоком используется, потому что это невозможно гарантировать, что драйвер FTDI будет всегда планироваться.

Вы пытались использовать одну из опций управления потоком (RTS/CTS, DTR/DSR, XON/XOFF) для синхронизации данных?

+0

Я не пытался контролировать поток. Я не должен использовать такое решение, потому что это вызовет дополнительную задержку. Я проанализировал перенос usb между устройством и платформой Windows, и нет управления потоком. – syntagma

+0

@REACHUS: Моя ситуация похожа: чтение из FTDI прекрасно работает на моем Linux-боксе, но теряет данные на планшете Android. Поскольку я делаю около 400 кбит/с непрерывной передачи данных (запись звука через USB), я подозреваю, что, возможно, комбинация аппаратного обеспечения/ядра/драйвера планшета неверно работает при высоких скоростях передачи данных. Как и вы, я знаю, что в моем случае Linux контроль потока не выполняется, но, возможно, на Android все по-другому, поэтому рекомендация. – gfour

1

Согласно тому же .pdf Gfour публикуемую, я нашел этот абзац там:.

«Размер пакета будет влиять на производительность и зависит от скорости передачи данных для очень высокой скорости, самый большой пакет размер. Для приложений реального времени, которые передают аудиоданные при 115200 бод, например, желателен наименьший возможный пакет, в противном случае устройство будет поддерживать одновременно 4 тыс. данных, что может дать эффект " jerky ', если размер запроса USB слишком велик, а скорость передачи данных слишком низкая (относительно). "

Я столкнулся с ситуацией, подобной SmartLemon с последовательным устройством FTDI, поэтому я недавно искал способы ее устранения. Это потребует от меня в значительной степени написать свои собственные функции с нуля, а раньше я использовал библиотеку.

Однако, похоже, что в вашем случае вы можете попробовать использовать самый низкий размер буфера bulkTransfer вместо съемки для самого большого. Возможно, вы уже пробовали это, но, возможно, нет. Я вижу, что вы говорите, что 32768 - это единственный размер, но, возможно, вы имели в виду только макс. Кажется странным, что он допускает только один конкретный размер.

-1

Вы можете попробовать это для выпуска передачи Bulk

byte[] buffer = new byte[4096]; 

      StringBuilder strIN = new StringBuilder(); 

      if (conn.bulkTransfer(epIN, buffer, 4096, 500) >= 0) { 
       for (int i = 2; i < 4096; i++) { 
        if (buffer[i] != 0) { 
         strIN.append((char) buffer[i]); 

         textReceiveDataInfo.append(strIN + "\n"); 
        } else { 
         l(strIN); 
         break; 
        } 
       } 

      } 
1

UsbEndpoint объект Андроида SDK, обеспечивает getMaxPacketSize() метод, позволяющий проверить, что подходит для вашего устройства. Как правило, максимально допустимый размер пакета составляет 64 байта для USB-устройств «Full-Speed» и 512 для «высокоскоростных» устройств - гораздо меньше, чем 32 768, которые вы пытаетесь выполнить. Возможно, вы путаете базовый размер пакета USB с протоколом более высокого уровня?