2012-10-31 6 views
10

Tak więc zaimplementowałem interfejs Android USB Accessory API, dzięki któremu mogę podłączyć mój telefon do mojego laptopa z systemem Linux i umieścić telefon w trybie USB Accessory. Wtedy mogę uzyskać dostęp do akcesorium, otworzyć go i zacząć czytać do niego. Mój kod wygląda prawie identycznie jak w przykładzie z the documentation. Główną różnicą jest to, że używam oddzielnych metod odczytu i zapisu i uzyskuję do nich dostęp poprzez JNI z natywnego kodu.Czytanie z Android USB Akcesoria rzuca ENODEV IOException

Oto, gdzie to staje się interesujące. Po pomyślnym odczytaniu/zapisaniu przez sekundę lub dwie, transfer hurtowy z mojego laptopa zaczyna podawać błędy limitu czasu, a następnie wywołanie odczytu do Akcesorium USB w Androidzie wywołuje wyjątek IOException z kodem błędu ENODEV. Dzieje się tak, gdy kabel jest nadal podłączony, a UsbManager nadal wyświetla listę akcesoriów na liście i nadal mam na to pozwolenie.

Aby dodać do dziwności tego, odkryłem, że jeśli sypię 100ms w pętli do odczytu, problem w zasadzie znika (choć zdarza się to przy okazji). Spanie w tym miejscu nie jest tylko koszmarem, ale wprowadza niedopuszczalne opóźnienie w mojej aplikacji. Im niższy czas snu, tym mniej skuteczny jest sęk, do miejsca, w którym jest nieskuteczny po 10 ms czasu snu.

Przesyłam około 20-30 kb/s danych w czasie rzeczywistym przy użyciu transmisji zbiorczych (ale nie w czasie rzeczywistym, że przesyłanie zbiorcze nie wystarcza), a rozmiar transferu wynosi od 50 do 800 bajtów na około 20 -30 Hz. Czy to może być ograniczenie USB? Nie mam z tym wiele doświadczeń, więc zasadniczo traktuję go tak samo jak gniazdo sieciowe. Czy powinienem umieszczać w kolejce mniejsze wiadomości i wysyłać je razem w rzadszych, ale większych transferach? Czy występuje problem z niewielkimi transferami masowymi o wysokiej częstotliwości? Przyjrzę się temu, ale w gruncie rzeczy łapię się za słomkami.

Sprzęt:

  • Laptop działa Ubuntu 10.04 i korzystania libusb 1.0.0.
  • Telefon to Galaxy Nexus S z systemem Android 4.1.2.

Odpowiedz

6

Tak więc, chociaż nadal nie rozumiem wszystkiego, co się dzieje, wdrożenie systemu podwójnego buforowania naprawiło mój problem.

Odkryłem, że czytanie aplikacji Java na Androida przy pełnej prędkości nie miało żadnych problemów z problemem ENODEV, co doprowadziło mnie do wniosku, że Java Native Interface był źródłem moich problemów.

Poprzednio czytałem z UsbAccessory bezpośrednio z metod wywoływanych z JNI w sposób głosowania. Coś w związku z przejściem z natywnego kodu na Javę, a następnie z Java do natywnego jądra Androida najwyraźniej sprawiło, że wszystko stało się zrzędliwe.

Moja poprawka polegała na odczytywaniu/zapisywaniu w UsbAccessory wątków tylko Java (bez wywołań JNI), a następnie buforowaniu danych do odczytu/zapisu z metod wywoływanych przez JNI.

Wydaje się działać jak urok. Wcześniej bardzo konsekwentnie uzyskiwałem limity czasu wysyłania po stronie akcesoriów, a następnie w końcu IOExeception od strony Androida, jak to opisano powyżej, a teraz nie mam żadnych limitów czasu, żadnych wyjątków IOE. Wciąż jestem trochę ciekaw, co dokładnie powoduje takie zachowanie, ale podejrzewam, że wymaga to silnego JNI Kung-fu, aby to zrozumieć.

Powiązane problemy