Czujniki HAL 1.0

Interfejs Sensors HAL, zadeklarowany w sensors.h , reprezentuje interfejs pomiędzy platformą Android a oprogramowaniem specyficznym dla sprzętu. Implementacja HAL musi definiować każdą funkcję zadeklarowaną w sensors.h. Główne funkcje to:

  • get_sensors_list - Zwraca listę wszystkich czujników.
  • activate - Uruchamia lub zatrzymuje czujnik.
  • batch — ustawia parametry czujnika, takie jak częstotliwość próbkowania i maksymalne opóźnienie raportowania.
  • setDelay — używany tylko w wersji HAL 1.0. Ustawia częstotliwość próbkowania dla danego czujnika.
  • flush - Opróżnia FIFO określonego czujnika i zgłasza zdarzenie zakończenia płukania, gdy zostanie to wykonane.
  • poll - Zwraca dostępne zdarzenia czujnika.

Implementacja musi być bezpieczna dla wątków i umożliwiać wywoływanie tych funkcji z różnych wątków.

Interfejs definiuje także kilka typów używanych przez te funkcje. Główne typy to:

  • sensors_module_t
  • sensors_poll_device_t
  • sensor_t
  • sensors_event_t

Oprócz poniższych sekcji, zobacz czujniki.h, aby uzyskać więcej informacji na temat tych typów.

get_sensors_list(lista)

int (*get_sensors_list)(struct sensors_module_t* module, struct sensor_t
  const** list);

Zawiera listę czujników zaimplementowanych przez warstwę HAL. Zobacz sensor_t , aby uzyskać szczegółowe informacje na temat definicji czujników.

Kolejność, w jakiej czujniki pojawiają się na liście, jest kolejnością, w jakiej czujniki będą raportowane do aplikacji. Zwykle najpierw pojawiają się czujniki podstawowe, a następnie czujniki złożone.

Jeśli kilka czujników ma ten sam typ czujnika i tę samą właściwość budzenia, pierwszy na liście nazywany jest czujnikiem „domyślnym”. Jest to wartość zwrócona przez getDefaultSensor(int sensorType, bool wakeUp) .

Funkcja ta zwraca liczbę czujników na liście.

aktywuj (czujnik, prawda/fałsz)

int (*activate)(struct sensors_poll_device_t *dev, int sensor_handle, int
  enabled);

Aktywuje lub dezaktywuje czujnik.

sensor_handle to uchwyt czujnika do aktywacji/dezaktywacji. Uchwyt czujnika jest zdefiniowany przez pole handle jego struktury sensor_t .

enabled jest ustawiony na 1, aby włączyć lub 0, aby wyłączyć czujnik.

Czujniki jednorazowe dezaktywują się automatycznie po odebraniu zdarzenia i nadal muszą zaakceptować dezaktywację poprzez wywołanie, aby activate(..., enabled=0) .

Czujniki niewybudzające nigdy nie uniemożliwiają przejścia SoC w tryb wstrzymania; oznacza to, że warstwa HAL nie będzie utrzymywać częściowej blokady uśpienia w imieniu aplikacji.

Czujniki budzenia, gdy dostarczają zdarzenia w sposób ciągły, mogą zapobiec przejściu SoC w tryb zawieszenia, ale jeśli nie ma potrzeby dostarczania żadnego zdarzenia, należy zwolnić częściową blokadę wybudzenia.

Jeśli enabled jest 1 i czujnik jest już aktywowany, ta funkcja nie działa i kończy się powodzeniem.

Jeśli enabled wynosi 0, a czujnik jest już dezaktywowany, funkcja ta nie działa i zakończy się pomyślnie.

Ta funkcja zwraca 0 w przypadku powodzenia i ujemną liczbę błędów w przeciwnym razie.

partia (czujnik, flagi, okres próbkowania, maksymalne opóźnienie raportu)

int (*batch)(
     struct sensors_poll_device_1* dev,
     int sensor_handle,
     int flags,
     int64_t sampling_period_ns,
     int64_t max_report_latency_ns);

Ustawia parametry czujnika, w tym częstotliwość próbkowania i maksymalne opóźnienie raportu . Tę funkcję można wywołać, gdy czujnik jest aktywny, w takim przypadku nie może powodować utraty pomiarów czujnika: Przejście z jednej częstotliwości próbkowania na drugą nie może spowodować utraty zdarzeń, podobnie jak przejście z wysokiego maksymalnego opóźnienia raportu na niskie maksymalne opóźnienie raportu.

sensor_handle to uchwyt czujnika do skonfigurowania.

flags są obecnie nieużywane.

sampling_period_ns to okres próbkowania, w którym czujnik powinien działać, w nanosekundach. Aby uzyskać więcej informacji, zobacz sampling_period_ns .

max_report_latency_ns to maksymalny czas, o który zdarzenia mogą być opóźnione przed zgłoszeniem przez warstwę HAL, w nanosekundach. Więcej szczegółów znajdziesz w akapicie dotyczącym max_report_latency_ns .

Ta funkcja zwraca 0 w przypadku powodzenia i ujemną liczbę błędów w przeciwnym razie.

setDelay(czujnik, okres próbkowania)

int (*setDelay)(
     struct sensors_poll_device_t *dev,
     int sensor_handle,
     int64_t sampling_period_ns);

Po wersji HAL 1.0 ta funkcja jest przestarzała i nigdy nie jest wywoływana. Zamiast tego wywoływana jest funkcja batch w celu ustawienia parametru sampling_period_ns .

W wersji HAL 1.0 zamiast wsadu użyto metody setDelay do ustawienia sampling_period_ns .

spłukiwanie (czujnik)

int (*flush)(struct sensors_poll_device_1* dev, int sensor_handle);

Dodaj zdarzenie zakończenia spłukiwania na końcu sprzętowego FIFO dla określonego czujnika i opróżnij FIFO; zdarzenia te są dostarczane w zwykły sposób (tj. tak, jakby upłynął maksymalny czas oczekiwania na raportowanie) i usuwane z FIFO.

Spłukiwanie odbywa się asynchronicznie (tzn.: ta funkcja musi natychmiast zwrócić). Jeśli implementacja wykorzystuje pojedyncze FIFO dla kilku czujników, to FIFO jest opróżniane i zdarzenie zakończenia płukania jest dodawane tylko dla określonego czujnika.

Jeśli określony czujnik nie ma FIFO (nie jest możliwe buforowanie) lub jeśli FIFO było puste w momencie wywołania, flush musi mimo to zakończyć się sukcesem i wysłać zdarzenie zakończenia opróżniania dla tego czujnika. Dotyczy to wszystkich czujników innych niż czujniki jednorazowe.

Kiedy wywoływane jest flush , nawet jeśli zdarzenie płukania znajduje się już w FIFO dla tego czujnika, należy utworzyć dodatkowe zdarzenie i dodać je na końcu FIFO, a FIFO musi zostać opróżnione. Liczba wywołań flush musi być równa liczbie utworzonych zdarzeń zakończenia opróżniania.

flush nie dotyczy czujników jednorazowych ; jeśli sensor_handle odnosi się do czujnika jednorazowego, flush musi zwrócić -EINVAL i nie generować żadnego zdarzenia metadanych zakończenia opróżniania.

Ta funkcja zwraca 0 w przypadku powodzenia, -EINVAL , jeśli określony czujnik jest czujnikiem jednorazowym lub nie został włączony, a w przeciwnym razie ujemną liczbę błędów.

głosowanie()

int (*poll)(struct sensors_poll_device_t *dev, sensors_event_t* data, int
  count);

Zwraca tablicę danych czujnika poprzez wypełnienie argumentu data . Ta funkcja musi być blokowana do czasu udostępnienia zdarzeń. Zwróci liczbę zdarzeń odczytanych w przypadku powodzenia lub ujemną liczbę błędów w przypadku błędu.

Liczba zdarzeń zwróconych w data musi być mniejsza lub równa argumentowi count . Ta funkcja nigdy nie powinna zwracać 0 (brak zdarzenia).

Sekwencja połączeń

Po uruchomieniu urządzenia wywoływana jest funkcja get_sensors_list .

Kiedy czujnik zostanie aktywowany, zostanie wywołana funkcja batch z żądanymi parametrami, po której activate(..., enable=1) .

Należy zauważyć, że w wersji HAL 1_0 kolejność była odwrotna: najpierw wywołano activate , a następnie set_delay .

Gdy żądana charakterystyka czujnika zmienia się w trakcie jego aktywacji, wywoływana jest funkcja batch .

flush można wywołać w dowolnym momencie, nawet na nieaktywnych czujnikach (w takim przypadku musi zwrócić -EINVAL )

Gdy czujnik zostanie dezaktywowany, zostanie wywołana activate(..., enable=0) .

Równolegle do tych wywołań funkcja poll będzie wielokrotnie wywoływana w celu żądania danych. poll można wywołać nawet wtedy, gdy nie są aktywowane żadne czujniki.

moduł_czujników_t

sensors_module_t to typ używany do tworzenia modułu sprzętowego Androida dla czujników. Implementacja HAL musi definiować obiekt HAL_MODULE_INFO_SYM tego typu, aby udostępnić funkcję get_sensors_list . Więcej informacji można znaleźć w definicji sensors_module_t w Sensors.h oraz w definicji hw_module_t .

czujniki_poll_device_t / czujniki_poll_device_1_t

sensors_poll_device_1_t zawiera resztę metod zdefiniowanych powyżej: activate , batch , flush i poll . Jego common pole (typu hw_device_t ) definiuje numer wersji warstwy HAL.

czujnik_t

sensor_t reprezentuje czujnik Androida . Oto niektóre z jego ważnych pól:

nazwa: widoczny dla użytkownika ciąg znaków reprezentujący czujnik. Ten ciąg często zawiera nazwę części podstawowego czujnika, typ czujnika i informację, czy jest to czujnik wybudzenia. Na przykład „Akcelerometr LIS2HH12”, „Nieskalibrowany żyroskop MAX21000”, „Barometr budzenia BMP280”, „Wektor rotacji gry MPU6515”

handle: Liczba całkowita używana do odniesienia się do czujnika podczas rejestracji do niego lub generowania z niego zdarzeń.

type: Typ czujnika. Zobacz wyjaśnienie typu czujnika w artykule Czym są czujniki Androida? aby uzyskać więcej informacji, zobacz Typy czujników, aby zapoznać się z oficjalnymi typami czujników. W przypadku nieoficjalnych typów czujników type musi zaczynać się od SENSOR_TYPE_DEVICE_PRIVATE_BASE

stringType: typ czujnika jako ciąg. Jeśli czujnik ma oficjalny typ, ustaw go na SENSOR_STRING_TYPE_* . Jeśli czujnik ma typ specyficzny dla producenta, stringType musi zaczynać się od odwrotnej nazwy domeny producenta. Na przykład czujnik (powiedzmy detektor jednorożca) zdefiniowany przez zespół Cool-product w Fictional-Company może używać stringType=”com.fictional_company.cool_product.unicorn_detector” . stringType służy do jednoznacznej identyfikacji nieoficjalnych typów czujników. Więcej informacji na temat typów i typów ciągów można znaleźć w pliku Sensors.h .

wymaganePermission: ciąg reprezentujący uprawnienia, jakie muszą posiadać aplikacje, aby zobaczyć czujnik, zarejestrować się w nim i otrzymać jego dane. Pusty ciąg znaków oznacza, że ​​aplikacje nie wymagają żadnych uprawnień dostępu do tego czujnika. Niektóre typy czujników, takie jak czujnik tętna, mają obowiązkowe requiredPermission . Wszystkie czujniki dostarczające wrażliwych informacji użytkownika (takich jak tętno) muszą być chronione zezwoleniem.

flags: Flagi dla tego czujnika, definiujące tryb raportowania czujnika oraz to, czy czujnik jest czujnikiem wybudzenia, czy nie. Na przykład czujnik jednorazowego wybudzenia będzie miał flags = SENSOR_FLAG_ONE_SHOT_MODE | SENSOR_FLAG_WAKE_UP . Bity flagi, które nie są używane w bieżącej wersji HAL, muszą pozostać równe 0.

maxRange: Maksymalna wartość, jaką czujnik może zgłosić, w tej samej jednostce, co wartości raportowane. Czujnik musi być w stanie raportować wartości bez nasycenia w granicach [-maxRange; maxRange] . Należy pamiętać, że oznacza to, że całkowity zasięg czujnika w sensie ogólnym wynosi 2*maxRange . Gdy czujnik zgłasza wartości w kilku osiach, zakres dotyczy każdej osi. Na przykład akcelerometr „+/- 2g” zgłosi maxRange = 2*9.81 = 2g .

rozdzielczość: Najmniejsza różnica wartości, jaką może zmierzyć czujnik. Zwykle obliczany na podstawie maxRange i liczby bitów w pomiarze.

moc: Koszt zasilania czujnika w miliamperach. Jest to prawie zawsze więcej niż zużycie energii podane w arkuszu danych podstawowego czujnika. Więcej szczegółów można znaleźć w części Czujniki podstawowe != czujniki fizyczne oraz w części Proces pomiaru mocy, aby uzyskać szczegółowe informacje na temat pomiaru zużycia energii przez czujnik. Jeżeli pobór mocy czujnika zależy od tego, czy urządzenie się porusza, pobór mocy podczas ruchu jest podawany w polu power .

minDelay: W przypadku czujników ciągłych okres próbkowania w mikrosekundach odpowiadający największej szybkości obsługiwanej przez czujnik. Aby uzyskać szczegółowe informacje na temat sposobu użycia tej wartości, zobacz sampling_period_ns . Pamiętaj, że minDelay jest wyrażane w mikrosekundach, a sampling_period_ns w nanosekundach. W przypadku czujników typu on-change i specjalnego trybu raportowania, jeśli nie określono inaczej, minDelay musi wynosić 0. W przypadku czujników jednorazowych musi wynosić -1.

maxDelay: W przypadku czujników ciągłych i zmiennych okres próbkowania w mikrosekundach odpowiadający najwolniejszej szybkości obsługiwanej przez czujnik. Aby uzyskać szczegółowe informacje na temat sposobu użycia tej wartości, zobacz sampling_period_ns . Uważaj, że maxDelay jest wyrażane w mikrosekundach, podczas gdy sampling_period_ns jest w nanosekundach. W przypadku czujników specjalnych i jednorazowych maxDelay musi wynosić 0.

fifoReservedEventCount: Liczba zdarzeń zarezerwowanych dla tego czujnika w sprzętowym FIFO. Jeśli dla tego czujnika istnieje dedykowane FIFO, wówczas fifoReservedEventCount jest rozmiarem tego dedykowanego FIFO. Jeśli FIFO jest współdzielone z innymi czujnikami, fifoReservedEventCount to rozmiar części FIFO zarezerwowanej dla tego czujnika. W większości systemów ze współdzielonym FIFO oraz w systemach, które nie mają sprzętowego FIFO, ta wartość wynosi 0.

fifoMaxEventCount: Maksymalna liczba zdarzeń, które mogą być przechowywane w FIFO dla tego czujnika. Wartość ta jest zawsze większa lub równa fifoReservedEventCount . Wartość ta służy do oszacowania, jak szybko FIFO zostanie zapełnione podczas rejestracji w czujniku z określoną szybkością, zakładając, że nie są aktywowane żadne inne czujniki. W systemach, które nie mają sprzętowego FIFO, fifoMaxEventCount wynosi 0. Więcej szczegółów można znaleźć w sekcji Batchowanie .

W przypadku czujników z oficjalnym typem czujnika, niektóre pola są nadpisywane przez framework. Na przykład czujniki akcelerometru muszą mieć tryb ciągłego raportowania, a monitory tętna muszą być chronione uprawnieniem SENSOR_PERMISSION_BODY_SENSORS .

czujniki_zdarzenie_t

Zdarzenia czujników generowane przez czujniki Androida i zgłaszane za pośrednictwem funkcji ankietytype sensors_event_t . Oto kilka ważnych pól sensors_event_t :

wersja: Musi mieć sizeof(struct sensors_event_t)

sensor: uchwyt czujnika, który wygenerował zdarzenie, zgodnie z definicją sensor_t.handle .

type: typ czujnika, który wygenerował zdarzenie, zgodnie z definicją sensor_t.type .

timestamp: Znacznik czasu zdarzenia w nanosekundach. Jest to godzina wystąpienia zdarzenia (wykonano krok lub dokonano pomiaru akcelerometrem), a nie godzina zgłoszenia zdarzenia. timestamp musi być zsynchronizowany z elapsedRealtimeNano zegarem RealtimeNano, a w przypadku czujników ciągłych jitter musi być niewielki. Filtrowanie znaczników czasu jest czasami konieczne, aby spełnić wymagania CDD, ponieważ użycie wyłącznie czasu przerwania SoC do ustawienia znaczników czasu powoduje zbyt duże wahania, a użycie wyłącznie czasu chipa czujnika do ustawienia znaczników czasu może spowodować desynchronizację z elapsedRealtimeNano zegara RealtimeNano, ponieważ zegar czujnika dryfuje.

dane i nakładające się pola: Wartości zmierzone przez czujnik. Znaczenie i jednostki tych pól są specyficzne dla każdego typu czujnika. Opis pól danych można znaleźć w pliku Sensors.h oraz w definicji różnych typów Sensorów . W przypadku niektórych czujników dokładność odczytów jest również podawana jako część danych w polu status . To pole jest przepuszczane tylko dla wybranych typów czujników i pojawia się w warstwie SDK jako wartość dokładności. W przypadku tych czujników fakt, że pole stanu musi zostać ustawione, jest podany w definicji typu czujnika .

Zdarzenia zakończone opróżnianiem metadanych

Zdarzenia metadanych mają ten sam typ, co zwykłe zdarzenia czujnika: sensors_event_meta_data_t = sensors_event_t . Są one zwracane wraz z innymi zdarzeniami czujnika poprzez ankietę. Posiadają następujące pola:

wersja: musi to być META_DATA_VERSION

typ: Musi to być SENSOR_TYPE_META_DATA

czujnik, zarezerwowany i sygnatura czasowa : musi wynosić 0

meta_data.what: zawiera typ metadanych dla tego zdarzenia. Obecnie istnieje jeden prawidłowy typ metadanych: META_DATA_FLUSH_COMPLETE .

Zdarzenia META_DATA_FLUSH_COMPLETE reprezentują zakończenie płukania czujnika FIFO. Kiedy meta_data.what=META_DATA_FLUSH_COMPLETE , meta_data.sensor musi być ustawiony na uchwyt czujnika, który został przepłukany. Są generowane wtedy i tylko wtedy, gdy na czujniku zostanie wywołane flush . Więcej informacji można znaleźć w rozdziale dotyczącym funkcji spłukiwania .