Sensors HAL 1.0

ממשק ה-HAL של חיישנים, שמוצהר ב-sensors.h, מייצג את הממשק בין המסגרת של Android לבין התוכנה הספציפית לחומרה. חובה להגדיר כל פונקציה של הטמעת HAL שהוצהר בחיישנים. הפונקציות העיקריות הן:

  • get_sensors_list – הפונקציה מחזירה רשימה של כל החיישנים.
  • activate – הפעלה או עצירה של החיישן.
  • batch – הגדרת הפרמטרים של החיישן, כמו תדירות דגימה ומקסימום זמן אחזור של הדיווח.
  • setDelay – בשימוש רק בגרסה 1.0 של HAL. מגדיר את תדירות הדגימה של לחיישן מסוים.
  • flush - שנקה את ערך ה-FIFO של החיישן שצוין ודיווח על השלמת שטיפה לאחר ביצוע הפעולה הזו.
  • poll – הפונקציה מחזירה את אירועי החיישן הזמינים.

ההטמעה חייבת להיות בטוחה לשרשור ולאפשר להפעיל את הפונקציות האלה משרשוריים שונים.

הממשק מגדיר גם כמה סוגים שבהם נעשה שימוש בפונקציות האלה. הסוגים העיקריים הם:

  • sensors_module_t
  • sensors_poll_device_t
  • sensor_t
  • sensors_event_t

בנוסף לקטעים הבאים, מידע נוסף על הסוגים האלה זמין בקובץ sensors.h.

get_sensors_list(list)

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

רשימת החיישנים שהוטמעו על ידי HAL. מידע על הגדרות החיישנים זמין בכתובת sensor_t.

הסדר שבו החיישנים מופיעים ברשימה הוא הסדר שבו החיישנים ידווחו לאפליקציות. בדרך כלל החיישנים הבסיסיים מופיעים קודם, ואחריהם החיישנים המשולבים.

אם כמה חיישנים משתפים את אותו סוג חיישן ואת אותו מאפיין התעוררות, החיישן הראשון ברשימה נקרא 'חיישן ברירת המחדל'. זהו הערך שמוחזר על ידי getDefaultSensor(int sensorType, bool wakeUp).

הפונקציה הזו מחזירה את מספר החיישנים ברשימה.

activate(sensor, true/false)

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

המתג מפעיל או משבית את החיישן.

sensor_handle היא נקודת האחיזה של החיישן להפעלה/השבתה. הידית של חיישן מוגדרת לפי השדה handle במבנה sensor_t שלו.

כדי להפעיל את החיישן, מגדירים את enabled כ-1. כדי להשבית אותו, מגדירים אותו כ-0.

חיישנים מסוג 'ירייה אחת' משביתים את עצמם באופן אוטומטי לאחר קבלת אירוע, אבל עדיין צריך לאשר את השבתתם באמצעות קריאה ל-activate(..., enabled=0).

חיישנים שאי אפשר להוציא ממצב שינה אף פעם לא מונעים מה-SoC לעבור למצב השעיה. ש היא, HAL לא יוכל להחזיק נעילה חלקית של מצב שינה מטעם האפליקציות.

חיישני התעוררות, כשהם שולחים אירועים באופן רציף, יכולים למנוע מה-SoC לעבור למצב השהיה, אבל אם אין צורך לשלוח אירוע, צריך לשחרר את נעילת ההתעוררות החלקית.

אם הערך של enabled הוא 1 והחיישן כבר מופעל, הפונקציה הזו לא פועלת ומצליחה.

אם הערך של enabled הוא 0 והחיישן כבר מושבת, הפונקציה לא פועלת ומצליחה.

הפונקציה מחזירה 0 אם הפעולה בוצעה בהצלחה, ומספר שגיאה שלילי אחרת.

אצווה(חיישן, דגלים, תקופת דגימה, זמן אחזור מקסימלי של דוח)

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

מגדירה את הפרמטרים של החיישן, כולל תדירות הדגימה וגם מספר דוח מקסימלי זמן אחזור. ניתן לקרוא לפונקציה הזו בזמן שהחיישן מופעל, במקרה כזה, אסור שהמדידות של החיישן יאבדו: מתדירות דגימה אחת לשנייה לא יכולה לגרום לאובדן אירועים, וגם לא יכולה מעבר מזמן אחזור מקסימלי גבוה של דוח לדוח מקסימלי נמוך זמן אחזור.

sensor_handle הוא נקודת האחיזה של החיישן שרוצים להגדיר.

flags לא בשימוש כרגע.

sampling_period_ns הוא תקופת הדגימה שבה החיישן אמור לפעול תוך ננו-שניות. ראו sampling_period_ns פרטים נוספים.

max_report_latency_ns הוא משך הזמן המקסימלי שבו אירועים יכולים להיות עיכוב לפני דיווח באמצעות HAL, בננו-שניות. הצגת max_report_latency_ns לפרטים נוספים.

הפונקציה מחזירה 0 אם הפעולה בוצעה בהצלחה, ומספר שגיאה שלילי אחרת.

setDelay(חיישן, תקופת דגימה)

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

אחרי גרסה 1.0 של HAL, הפונקציה הזו יצאה משימוש ואף פעם לא מתבצעת קריאה שלה. במקום זאת, הפונקציה batch נקראת כדי להגדיר את הפרמטר sampling_period_ns.

בגרסה 1.0 של HAL נעשה שימוש ב-setDelay במקום באצווה כדי להגדיר את sampling_period_ns.

Flush(sensor)

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

מוסיפים אירוע של סיום שטיפה לסוף ה-FIFO של החומרה עבור החיישן שצוין ומנקים את ה-FIFO. האירועים האלה נשלחים כרגיל (כלומר, כאילו פג תוקף זמן האחזור המקסימלי לדיווח) ומוסרים מה-FIFO.

הניקוי מתבצע באופן אסינכרוני (כלומר, הפונקציה הזו חייבת לחזור מיד). אם בהטמעה נעשה שימוש ב-FIFO אחד לכמה חיישנים, ה-FIFO ואירוע 'הניקוי' יתווסף רק לחיישן שצוין.

אם לחיישן שצוין אין FIFO (לא ניתן להשתמש במאגר), או אם ה-FIFO היה ריק בזמן הקריאה, flush עדיין צריך להצליח ולשלוח אירוע של סיום שטיפה לחיישן הזה. הכלל הזה חל על כל החיישנים האחרים מחיישנים במודל אחד.

כשפונים ל-flush, גם אם אירוע שטיפה כבר נמצא ב-FIFO של החיישן הזה, צריך ליצור אירוע נוסף ולהוסיף אותו לסוף ה-FIFO, וגם צריך לבצע שטיפה של ה-FIFO. מספר הflush הקריאות חייבות להיות שווה למספר האירועים מסוג 'רצף רצף' שנוצרו.

flush לא רלוונטי לחיישנים מסוג one-shot. אם sensor_handle מתייחס לחיישן מסוג one-shot, flush חייב להחזיר את הערך -EINVAL ולא ליצור אירוע של שטיפה מלאה של המטא-נתונים.

הפונקציה הזו מחזירה 0 אם הפעולה בוצעה בהצלחה, -EINVAL אם החיישן שצוין הוא חיישן חד-פעמי או לא הופעל, ומספר שגיאה שלילי במקרים אחרים.

poll()

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

מחזירה מערך של נתוני חיישנים על ידי מילוי הארגומנט data. הפונקציה הזו חייבת לחסום עד שהאירועים יהיו זמינים. הפעולה הזו תחזיר את מספר האירועים שנקראו או מספר שגיאה שלילי במקרה של שגיאה.

מספר האירועים שהוחזרו ב-data חייב להיות שווה ל- או קטן מ- את הארגומנט count. הפונקציה הזו אף פעם לא תחזיר 0 (אין אירוע).

רצף שיחות

כשהמכשיר מופעל, מתבצעת קריאה ל-get_sensors_list.

כשהחיישן מופעל, תתבצע קריאה לפונקציה batch באמצעות הפרמטרים המבוקשים, ואחריהם activate(..., enable=1).

שימו לב שבגרסה 1_0 של HAL, הסדר היה הפוך: activate הופעל קודם, ואחריו set_delay.

כשהמאפיינים המבוקשים של חיישן משתנים בזמן שהוא מופעל, מתבצעת קריאה לפונקציה batch.

אפשר להתקשר אל flush בכל שלב, גם באמצעות חיישנים לא פעילים (במקרה כזה) היא חייבת להחזיר -EINVAL)

כשחיישן מושבת, מתבצעת קריאה ל-activate(..., enable=0).

במקביל לקריאות האלה, הפונקציה poll תופעל שוב ושוב כדי לבקש נתונים. אפשר להתקשר אל poll גם אם לא הופעלו חיישנים.

חיישנים_Module_t

sensors_module_t הוא הסוג שמשמש ליצירת מודול החומרה של Android לחיישנים. כשמטמיעים את ה-HAL, חייבים להגדיר אובייקט HAL_MODULE_INFO_SYM מהסוג הזה כדי לחשוף את הפונקציה get_sensors_list. לצפייה הגדרה של sensors_module_t ב-sensors.h וההגדרה של hw_module_t אפשר לקבל מידע נוסף.

sensors_poll_device_t / sensors_poll_device_1_t

sensors_poll_device_1_t מכיל את שאר השיטות שהוגדרו למעלה: activate,‏ batch,‏ flush וגם poll. שדה common שלו (מסוג hw_device_t) מגדיר את מספר הגרסה של HAL.

חיישן_t

sensor_t מייצג Android חיישן. הנה כמה מהשדות החשובים בו:

name: מחרוזת שגלויה למשתמש ומייצגת את החיישן. המחרוזת הזו מכילה לרוב את שם החלק של החיישן הבסיסי, את סוג החיישן ואת העובדה שהוא חיישן התעוררות. לדוגמה, 'LIS2HH12 Accelerometer',‏ 'MAX21000 Uncalibrated Gyroscope',‏ 'BMP280 Wake-up Barometer',‏ 'MPU6515 Game Rotation Vector'

handle: המספר השלם שמשמש להפניה לחיישן כשרוצים להירשם אליו או ליצור ממנו אירועים.

type: סוג החיישן. הצגת הסבר על החיישן מקלידים מהם חיישני Android? לקבלת פרטים נוספים, וקוראים את המאמר סוגי חיישנים עבור סוגי חיישנים רשמיים. עבור סוגי חיישנים לא רשמיים, type חייב להתחיל ב-SENSOR_TYPE_DEVICE_PRIVATE_BASE

stringType: סוג החיישן כמחרוזת. אם לסוג החיישן יש סוג רשמי, מגדירים אותו כ-SENSOR_STRING_TYPE_*. כשלחיישן יש סוג ספציפי ליצרן, השדה stringType חייב להתחיל בשם הדומיין ההפוך של היצרן. לדוגמה, חיישן מזהה חד-קרן) שהוגדר על ידי צוות מוצר מגניב חברה בדיונית יכולה להשתמש stringType=”com.fictional_company.cool_product.unicorn_detector”. stringType משמש לזיהוי ייחודי של חיישנים לא רשמיים שונים. למידע נוסף על סוגי מחרוזות וסוגים אחרים, אפשר לעיין בקובץ sensors.h.

requiredPermission: מחרוזת שמייצגת את ההרשאה שצריכה להיות לאפליקציות כדי לראות את החיישן, להירשם אליו ולקבל את הנתונים שלו. אם מופיעה מחרוזת ריקה, פירוש הדבר הוא שאפליקציות לא דורשות הרשאות כדי לגשת לחיישן הזה. לחלק מסוגי החיישנים, כמו מוניטור קצב הלב, יש חובה requiredPermission. כל החיישנים מספקים מידע רגיש על נתוני המשתמש (כמו דופק) הרשאה.

דגלים: סימונים עבור חיישן זה, המגדירים את מצב הדיווח של החיישן החיישן הוא חיישן התעוררות או לא. לדוגמה: חיישן התעוררות בפעולה אחת יהיה flags = SENSOR_FLAG_ONE_SHOT_MODE | SENSOR_FLAG_WAKE_UP. הקטעים של הדגל שלא נעשה בו שימוש בגרסת ה-HAL הנוכחית חייב להיות שווה ל-0.

maxRange: הערך המקסימלי שהחיישן יכול לדווח, באותה יחידה שבה מדווחים הערכים. החיישן יכול לדווח על ערכים בלי רוויה בתוך [-maxRange; maxRange]. חשוב לשים לב שהמשמעות היא שהטווח הכולל של במשמעות הגנרית, 2*maxRange. כשהחיישן מדווח על ערכים מעל כמה צירים, הטווח חל על כל ציר. לדוגמה, מד תאוצה עם טווח של +/- 2g ידווח על maxRange = 2*9.81 = 2g.

רזולוציה: ההבדל הקטן ביותר בערך שהחיישן יכול למדוד. בדרך כלל מחושב על סמך maxRange ומספר הביטים במדידה.

הספק: עלות החשמל של הפעלת החיישן, באלפיות השנייה. המדד הזה כמעט תמיד גבוה מצריכת החשמל שדווחה של החיישן הבסיסי. ראו חיישני בסיס != פיזי חיישנים לפרטים נוספים ולמידע על מדידת עוצמה תהליך לפרטים על האופן שבו ניתן למדוד את צריכת החשמל של חיישן. אם צריכת החשמל של החיישן תלויה בתנועה של המכשיר, צריכת החשמל בזמן התנועה היא זו שמדווחת בשדה power.

minDelay: בחיישנים רציפים, תקופת הדגימה מיקרו-שניות, בהתאם לקצב המהיר ביותר שנתמך בחיישן. ראו sampling_period_ns פרטים על אופן השימוש בערך הזה. חשוב לזכור ש-minDelay מופיע ביחידות מיקרו-שנייה, ואילו sampling_period_ns מופיע ביחידות ננו-שנייה. בחיישנים של דיווח בזמן שינוי ובדיווח מיוחד, אלא אם צוין אחרת, הערך של minDelay חייב להיות 0. לחיישנים במבט אחד, חייב להיות 1-.

maxDelay: בחיישנים רצויים בחיישנים שמנטרים שינויים, תקופת הדגימה, במיקרו-שניות, בהתאם לשיעור האיטי ביותר שהחיישן תומך בו. ראו sampling_period_ns פרטים על אופן השימוש בערך הזה. חשוב לזכור ש-maxDelay מופיע ביחידות מיקרו-שנייה, ואילו sampling_period_ns מופיע ביחידות ננו-שנייה. לחיישנים מיוחדים ולחיישנים חד-פעמיים, maxDelay חייב להיות 0.

fifoReserveEventCount: מספר האירועים ששמורים לחיישן הזה FIFO לחומרה. אם יש FIFO ייעודי לחיישן הזה, fifoReservedEventCount הוא הגודל של ה-FIFO הייעודי הזה. אם ה-FIFO הוא משותף עם חיישנים אחרים, fifoReservedEventCount הוא הגודל של החלק ה-FIFO ששמור לאותו חיישן. ברוב מערכות FIFO המשותפות, ובמצב למערכות שאין להן FIFO לחומרה, הערך הזה הוא 0.

fifoMaxEventCount: המספר המקסימלי של אירועים שיכולים להיות מאוחסנים ביחידות ה-FIFO של החיישן הזה. הערך הזה תמיד גדול מ-fifoReservedEventCount או שווה לו. הערך הזה משמש להערכה של האופן שבו מהירות ה-FIFO תתמלא במהירות במהלך הרישום לחיישן בתנאי שלא הופעלו חיישנים אחרים. במערכות שאין להן FIFO של החומרה, fifoMaxEventCount הוא 0. לפרטים נוספים, ראו אצווה.

בחיישני סוג רשמי, חלק מהשדות נכתבים מחדש על ידי המסגרת. לדוגמה, חיישנים של מד תאוצה חייבים לפעול במצב דיווח רציף, ומוניטורים של קצב הלב חייבים להיות מוגנים באמצעות ההרשאה SENSOR_PERMISSION_BODY_SENSORS.

sensors_event_t

אירועי חיישנים שנוצרים על ידי חיישני Android ומדווחים באמצעות פונקציית הסקר הם מתוך type sensors_event_t. הנה כמה דוגמאות שדות חשובים ב-sensors_event_t:

גרסה: חייבת להיות sizeof(struct sensors_event_t)

sensor: נקודת האחיזה של החיישן שיצר את האירוע, לפי ההגדרה של sensor_t.handle.

type: סוג החיישן של החיישן שיצר את האירוע, כפי שמוגדר על ידי sensor_t.type.

timestamp: חותמת הזמן של האירוע בננו-שניות. זו השעה שבה התרחש אירוע (בוצע שלב, או שבוצעה מדידה של מד תאוצה), לא השעה שבה דווח על האירוע. חובה לסנכרן את timestamp עם בשעון elapsedRealtimeNano, ובמקרה של חיישנים רציפים, הרעידות חייב להיות קטן. לפעמים צריך לסנן את חותמות הזמן כדי לעמוד בדרישות של CDD, כי שימוש רק בזמן ההפרעה של SoC כדי להגדיר את חותמות הזמן גורם לתנודות גבוהות מדי, ושימוש רק בזמן של צ'יפ החיישן כדי להגדיר את חותמות הזמן עלול לגרום לניתוק הסנכרון עם השעון elapsedRealtimeNano, כי שעון החיישן נע.

data ושדות חופפים: הערכים שנמדדים באמצעות באמצעות חיישן. המשמעות והיחידות של השדות האלה ספציפיות לכל סוג חיישן. לתיאור של סוגי החיישנים השונים, אפשר לעיין בקטע sensors.h שדות נתונים. עבור חיישנים מסוימים, יש דיווח גם על רמת הדיוק של התוצאות כחלק מהנתונים, באמצעות שדה status. בשדה הזה בלבד של סוגי החיישנים שנבחרו, ומופיעים בשכבת ה-SDK ערך הדיוק. לגבי החיישנים האלה, העובדה שצריך להגדיר את שדה הסטטוס מופיעה בהגדרה של סוג החיישן.

אירועים שהושלמו של מטא-נתונים

הסוג של אירועי מטא-נתונים זהה לזה של אירועי חיישנים רגילים: sensors_event_meta_data_t = sensors_event_t הם מוחזרים יחד עם אירועים אחרים של חיישנים באמצעות סקרים. הם כוללים את השדות הבאים:

גרסה: חייבת להיות META_DATA_VERSION

type: חייב להיות SENSOR_TYPE_META_DATA

sensor,‏ reserved ו-timestamp: חייבים להיות 0

meta_data.what: מכיל את סוג המטא-נתונים של האירוע הזה. כרגע יש סוג מטא-נתונים חוקי אחד: META_DATA_FLUSH_COMPLETE.

אירועי META_DATA_FLUSH_COMPLETE מייצגים את השלמת תהליך השדרוג החיישן FIFO. כשהערך הוא meta_data.what=META_DATA_FLUSH_COMPLETE, meta_data.sensor צריך להיות מוגדר לנקודת האחיזה של החיישן שהתרוקן. הם נוצרים רק כשמתבצעת קריאה ל-flush באחד מהחיישנים. צפייה בקטע שעוסק ב- את הפונקציה flush.