ããã°ã©ããŒã座ã£ãŠããã¿ã³ã䜿çšããŠå¥ã®æž©åºŠã»ã³ãµãŒãšããã°ã©ã ãäœæããŸããã ãããŠçªç¶ããã®ã»ã³ãµãŒã¯å°æ¥ã®ã¢ãã«ã§é»è©±ã®å°ããªã¡ãŒã«ãŒãæãã§ããããšãå€æããŸããã ãããã£ãŠãã¿ã¹ã¯ã¯Android OSã¬ãã«ã§I2C / GPIOã»ã³ãµãŒããµããŒãããããšã§ãããã»ã³ãµãŒã¯æºåž¯é»è©±èªäœã®äžå¯æ¬ ãªéšåã«ãªããšçŽæãããŠããããã§ãã
æ·±ãäžè«ãã§ããããããšã³ãã«ã¹ã¿ããŒããã®è¿
éãã€å®æçãªå¯Ÿå¿ã®åžæã¯ãããŸããã§ãããç«ãèšç·Žããæé ãªäŸ¡æ Œã®Androidããã€ã¹ã«éçãå
¥ããããšã«ããŸããã
ã¿ã¹ã¯ã¯ããã»ã©é£ãããªããã¿ãã¬ããããã®åè·¯ãèŠã€ããäœãå£ããã«å¿
èŠãªå Žæã«ã¯ãã ä»ãããæçµçãªãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã®ã»ã³ãµãŒã®ååšã«æçãªã³ãŒããæžãããšãæå³ããŸããã
ããã«ãããã®ãé çªã«èŠãŠãããŸãã
- ã¯ããã«
- ã¿ãã¬ãããªã©ã®å®éã®ããã€ã¹ã«æ¥ç¶ããæ¹æ³
- ãªãŒãã£ãªåºåã§ãããã°UARTãçã¿ããããæ©èœããªãããšãèŠã€ããæ¹æ³
- I2CãGPIOãå²ã蟌ã¿ãããã¯ã°ã©ãŠã³ãã¿ã¹ã¯ã䜿çšããç°¡åãªã«ãŒãã«ãã©ã€ããŒã®äœææ¹æ³
- Androidããã«ãŠã§ã¢ã§éçãæœè±¡åããæ¹æ³ããŸãã¯æ¢åã®ãã®ã䜿çšããæ¹æ³
- ã·ã¹ãã ãµãŒãã¹ãè¿œå ããæ¹æ³ãšããµãŒãã¹ãæå¹ã«ããŠèŠã€ããããã«äœããè¿œå ããå Žæ
- SEAndroid / SELinuxãçªç ŽããŠã«ãŒã«ãè¿œå ããæ¹æ³
- ãã§ãã¯æ¹æ³-ç°¡åãªã¢ããªãæžã
- ãã¹ãŠããŸãšããæ¹æ³
- åã®æ®µèœã§äœããééã£ãŠããããšãç解ããæ¹æ³
ã¯ããã«ãã€ãã®ããã«ãåé¡ã¯ã§ããã ãæ©ãã¿ã¹ã¯ã®äžè²«æ§ãšå®çŸå¯èœæ§ã蚌æããå¿
èŠãããããã«éçºããããããäœåã®ããã€ãã®éšåã圢æãããŸãããããã¹ãŠã説æããããã§ã¯ãããŸããããå°è±¡ã®å®å
šæ§ã®ããã«ããããæäŸããŸãã
ã¿ãã¬ãããæ¢ããŠãéžæã¯ããã€ãã®çç£çãªçç±ã§ãã¯ãµã¹7ã«èœã¡ãŸããïŒå人ããããååã«hitã«è¥²ãããïŒbecauseãã¿ããã¹ã¯ãªãŒã³ãå£ããŠããŠã¹ã䜿çšããªããã°ãªããªãã£ãïŒã®ã§ãããã§ããŸã ãã¯ãµã¹ã§ããã®äžã«ãGoogleãµã€ãã®è©³çŽ°æ
å ±ãšãœãŒã¹ã³ãŒãããããŸããã ããã«ã¿ãã¬ãããåãäžããã®ã¯æãã£ãã®ã§ãæåã«ãããã®ã¯Raspberry Pi3ã§ããã ã»ãšãã©ã®ãããã°ã¯ãããã§çºçããŸããã ããã«ããã®ç©èªã¯Raspberry Pi 3ãèšå¿µãããã®ã§ã¯ãããŸãããããœãããŠã§ã¢ã®åé¡ã®ã»ãšãã©ãRaspberry Pi 3ã§è§£æ±ºãããããšãèŠããŠãããŠãã ããã
ã¿ãã¬ãããªã©ã®å®éã®ããã€ã¹ã«æ¥ç¶ããæ¹æ³åè·¯ã®ãªãã¿ãã¬ãããªã©ã®ã ãŸãããããã€ã¹ãžã®æ¥ç¶ã¯
èªç¥çã§ãããåæ°ã¯ãããããä»äºã§ãã ãããã£ãŠãæåã«ã¹ããŒã ããããŸããã äžè¬çã«ãçŸä»£ã®æºåž¯é»è©±ãã¿ãã¬ããã®é»æ°åè·¯ã¯æããªãŒãã³ãªãã®ã§ã¯ãããŸãããããã©ãŠã¶ãŠã£ã³ããŠã§ã®äžåœèªã®è±å¯ããæããã«è©ŠããŠã¿ããšãäœããèŠã€ããããšãã§ããŸãã ç§ãã¡ã¯åœŒå¥³ããã®
ãããã®ã©ããã§ããã«ååã«èŠã€ããã åè·¯ã䜿çšãããããªãã¹ã±ããã¯ããã®ããã¥ã¡ã³ãã¹ããŒãããã®åãæãã§ãã
çè«çã«ã¯ãã¿ãã¬ããã«ã¯éåžžã«å€ãã®I2Cãã¹ããããã©ã®GPIOãããæ¡éãã«å€§ããã¯ãã§ããé©åãªãã®ãèŠã€ããŠã¯ãã ä»ãããé©åãªã¬ãã«ã«åŒãäžããã ãã§ãã 幞ããªããšã«ãNexus 7ã¿ãã¬ããã«ã¯èé¢ã«ã¡ã©ããããŸãããèé¢ã«ã¡ã©ã¯ãå¶åŸ¡ãš2ã€ã®ãã³ïŒé»æºãšãªã»ããïŒã«I2Cã䜿çšããã ãã§ãã ãŸããI2Cãš2ã€ã®GPIOãå¿
èŠã§ãïŒ1ã€ã¯ãªã³/ãªãã¹ãªãŒãã¢ãŒãçšããã1ã€ã¯æ°ãã枩床枬å®ãç ç²ã«ããŠäžæããããïŒã
å®éã®å
éšãšå³ã®çžé¢é¢ä¿ã¯ããã¹ãŠãã¿ãã¬ããã®ååã»ã©åçŽã§ã¯ãªãããšã瀺ããŸããã ã€ãŸããNexus 7ã«ã¯å°ãªããšã3ã€ã®ããŒãžã§ã³ããããŸãã
- 2013ããŒãžã§ã³ã¯ãä»ã®ããã»ããµãšããŸããŸãªå°ããªè©³çŽ°ããããããèŠã€ãã£ãåè·¯ã«é©åããŸãã
- 2012ããŒãžã§ã³.1ã«ã¯èé¢ã«ã¡ã©çšã®ã¯ãã ä»ããããã·ãŒããããããã¹ãŠãåé¡ãããŸãã
- 2012ããŒãžã§ã³.2ã«ã¯ã¯ãã ä»ãããå Žæããªããã¯ãã ä»ãã¯ã¯ããã«å°é£ã§ãã
2012幎ã«ã¯ã¿ãã¬ããããããæ¢æã®ã³ãã¯ã¿ã¯ãããŸããã§ãããããã«ããããã«ã¯å£ããã¿ãããšããŠã¹ããããŸããã ãã®çµæãã¿ã³ããªã³ãå²ãã§èžã£ãåŸãã¯ãã ä»ããããã³ãã¯ã¿ãåããå¥ã®ã¿ã³ããªã³ã賌å
¥ããããšã«ãªããŸããã é·ãéæ°ããNexus 7ã¯ãªããããããã¶ãŒã«ããæ€çŽ¢ããŸãããããã«ãããèã®äžãèŠãŠãã«ã¡ã©ã®äžã«ã¯ãã ä»ããããå Žæã§å¿
èŠãªãã®ãéžæã§ããŸããã
NDKã䜿çšããç°¡åãªããã°ã©ã ã䜿çšããç°¡åãªæ€çŽ¢ã«ãããæ£ããI2Cãã¹ã®çªå·ãèŠã€ãããŸããã ãããè¡ãã«ã¯ãrootåãããAndroidãšchmodãwitchcraftãšãšãã«adbçµç±ã§ã€ã³ã¹ããŒã«ããŠããã¹ãŠã®I2Cãã¹ããªãªãŒã¹ããå¿
èŠããããŸããã 䞊ã¹æ¿ãã®éçšã§ããã¹ã®ã¢ãã¬ã¹ãå°ãéãã§ã¿ãå¿
èŠããããŸãããã¢ãã¬ã¹ã®äžéšã¯æ¢ã«äºçŽãããŠããŠãéä¿¡ããããšãããšãã«ããããšãåãåã£ãããã§ãã ãã®çµæãã¿ãŒã²ãããã¹ã«ã¯ä»ã«èª°ãããªãããšãå€æããŸããã
ãªãªã«ã«èå³æ·±ã詳现ã¯ããã ã¡æãåŸã«Androidã®ãã¹ãŠã®ããŒãžã§ã³ãåãããã«åœ¹ç«ã€ããã§ã¯ãªãããšã§ãããã®å Žåãææ°ã®å
¬åŒããŒãžã§ã³ã¯Android 5.1.1ã§ããã ã€ã³ã¹ããŒã«ãšãã ã¡æãã®åŸããã¹ãŠãåé¡ãªãèŠããããã«ãªããŸããããç§ãã¡ã®ããã°ã©ã ã¯/ devãã©ã«ããŒã«ããã¢ã¯ã»ã¹ã§ããŸããã§ããã adbã·ã§ã«ãšchmodã䜿çšããã¢ã¯ã»ã¹æš©ã®åŒ·å¶å€æŽã¯å¹æããããŸããã§ããã çèããåŸãAndroid 4.4.4ã«ããŒã«ããã¯ããããšã«ããŸããã åããã ã¡æãããã»ã¹ãç¹°ãè¿ããšãããã°ã©ã ã¯ããã«/ devã«ã¢ã¯ã»ã¹ã§ããŸããã ãŸããadbã·ã§ã«ã§ã¯ããŒãžã§ã³4.4.4ã®/ devãã©ã«ããŒã¯ã¹ãŒããŒãŠãŒã¶ãŒã«ç§»åããªããŠãèªã¿åãå¯èœã§ããããAndroid 5.1.1ã§ã¯èªã¿åãå¯èœã§ã¯ãªãã£ãããšã«ã泚æããŠãã ããã æãå¯èœæ§ãé«ãã®ã¯ãAndroid 4ããAndroid 5以éãžã®ç§»è¡äžã«OSã»ãã¥ãªãã£ã«é¢ããŠããªã倧ããªå€æŽãè¡ãããããã§ãïŒããã¯ãããã
ãªã³ã¯äžã®3çªç®ã®ãã€ã³ãã§ãïŒã
GPIOã¯ã©ãã§ããïŒ
å³ã®æåã®ããŒãžã«ã¯ãäžè¬çãªæŠèŠã§ãèé¢ã«ã¡ã©ã¢ãžã¥ãŒã«OV5650ããšåŒã°ããã«ã¡ã©ããããŸãã

ãŸããtegra T30LïŒã€ãŸãã¡ã€ã³SoCïŒã«çŽæ¥æ¥ç¶ãããŠããããšã瀺ããŠããŸãã è¿ãã«I2C_CAM_è¡ããããŸã...èŠãŠã¿ãŸããã...

9ããŒãžã«å¿
èŠãªãã®ããããŸãã ã»ãšãã©ãã¹ãŠã®ããŒãžã¯ãããã³ãã«ã¡ã©ãšãªã¢ã«ã¡ã©å°çšã§ãã ãŸããã«ã¡ã©ã«ã¯2ã€ã®ãã³CAM_RST_5Mããã³PWDN_5MããããããããGPIO_PBB0ããã³GPIO_PBB5ã®SoCã«æ¥ç¶ããããšããèšè¿°ããããŸãã ãããç§ãã¡ã«å¿
èŠãªãã®ã®ããã§ãã ããã«ã¯ãã ä»ãããæ¹æ³ãèŠã€ããã ããªã®ã§ãæ€çŽ¢ãç¶ããŸã...

ãŸããããã ãã§ãã ãã®ããŒãžã«ã¯ãç®çã®ãã³ãå«ããã«ã¡ã©ã®é»æºãå
¥ã£ãŠããFFCã³ãã¯ã¿ã®èª¬æããããŸãã ãªãªãžãã«ã®ã¿ãã¬ããã§ã¯ãã³ãã¯ã¿ã¯ã¯ãã ä»ããããŠããŸããã ããããåŸã§ãã³ãã¯ã¿ãåããå¥ã®ã¿ãã¬ãããèŠã€ããŠã被害ãåããªãããã«ããŸãã
ããã«ãèŠã€ãã£ããã³ã®ãã¬ãŒã¹ã¯ãã©ãããã©ãŒã ã³ãŒãã§æ¢ã«åéããããã©ã€ããŒã«é¢ããéšåã«ããã«ã€ããŠæžãããŠããŸã...
ãªãŒãã£ãªåºåã§ãããã°UARTãçã¿ããããæ©èœããªãããšãèŠã€ããæ¹æ³Linuxçšã®ãã©ã€ããŒãšäœã¬ãã«ã®ãœãããŠã§ã¢ãäœæããå Žåããã©ã€ããŒãããã«ããŒãããããããã«ãŒãã«/ã·ã¹ãã ããŒããã°ã確èªããããšãïŒéåžžã«ïŒæãŸããã§ãã ãããŠãäœããããŸãè¡ããªããšããã«ããã¹ãŠãåæ¢ããçç±ã¯äžæã§ãã
ãã®ãããã€ã³ã¿ãŒããããåžã£ãŠãNexusããã€ã¹ã«ã¯ãªãŒãã£ãªãžã£ãã¯ãä»ãããããã°UARTåºåãããããšãããããŸããã ãããŠãããã¯ãã®ããã«ãœãããŠã§ã¢èšå®ãªãã§ããèªäœã®ããã«åäœããŸãïŒ
- MICãã£ã³ãã«ã®ãªãŒãã£ãªãžã£ãã¯ã«ã¯ã3V以äžã®ã¬ãã«ã«å¿çããã³ã³ãã¬ãŒã¿ãã€ã³ã¹ããŒã«ãããŠããŸãã
- éåžžã¢ãŒãã§ã¯ãMICã®é»å§ã¯1.8Vã2.9Vã§ãã
- ã¬ãã«ãè¶
ãããšããã«ç¶æ
ããã³ã«éä¿¡ãããå²ã蟌ã¿ã«ããããããã°ããªãŒãã£ãªãžã£ãã¯ãé§åããããšãã«ãŒãã«ã«éç¥ãããŸãã
- ãã®åŸãå·Šå³ã®ãã£ã³ãã«ã¯ããããRXãšTXã«ãªããŸããã1.8Vã®ãŸãŸã§ãããã³ã³ããŒã¿ãŒãå¿
èŠã§ãã


ç¥ãããã«ãã¢ããã¿ãŒUSB-UART->ãªãŒãã£ãªãäœæãããŸããã ç«ã¡åŸçããUbuntu minicomã³ã³ãœãŒã«ã§ãªã³ã«ããŠãã¿ãã¬ãããããŒãããŸããããäœããããŸããã§ããã äžè¬çã«ã ã€ãŸããããªãã ããã«ãã«ã¹ã±ãŒã«ã®æ€çŽ¢ã§ã¯ãå·Šå³ã®ãã£ãã«ã©ã€ã³ãRX / TXã®ãŒãé»å§ã¬ãã«ã«éããŠããªããããäœããã®æ¹æ³ã§ãããã°uartããªã³ã«ãªããªãããšã瀺ãããŸããã ãŸããfastbootããå€ãã®ã³ãã³ããè©ŠããŸããããäœã圹ã«ç«ã¡ãŸããã§ããã ãã®ãã³ãã£ãŒã®çµããã«ç§ãã¡ãå®å¿ãããå¯äžã®ããšã¯ã
å¥ã®äººãç°ãªããã¯ãµã¹ãè©Šãããšããæ
å ±ã ãã§ããããŸã£ããåãUARTã¿ãã¬ãã以å€ã¯èµ·åããŸããããç§ãã¡ã®ãã®ã§ã¯ãããŸããã§ããã ã§ãé¢çœãã£ãã§ãã
ããã«åºæ¬çãªæ¹æ³ã¯ãããã»ããµã®ãªã³/ãªãã€ã³ã¿ãŒãã§ã€ã¹ãæ¥ç¶ããããšã§ããããããã€ã¹ãã€ã¢ã°ã©ã ã«ã¯ãã®å¯èœæ§ã瀺ãããŠããŸãããããã®æ¹åã«ã¯è¡ããŸããã§ããã
ãã®çµæãç§ãã¡ã®æãã¯ãAndroidã¹ãã¬ãŒãžã«Raspberry Piãäºåçã«äœ¿çšããããšã§ããã ããã§ãããã°ããŒããæ©èœãããã¹ãŠã®ãšã©ãŒããã£ããã§ããNexusã§ã¯ã«ãŒãã«ãããŒããããŠããªãå Žåã«äœãå€æŽããããæ確ã«ãªããŸããã çµ±èšã«ãããšãã»ãšãã©ã®æéé
延ã¯ãã¯ãã ä»ããããŠããªãGPIOãã³ãšãGPIOã§ã®äœæ¥ãèš±å¯ãããšããç¹ã§ã®tegra3ã®ææžåãããŠããªãæ©èœã«ãããã®ã§ãã
ã¡ãªã¿ã«ããããã°ã®ããã«å®å
šãªããŠã³ããŒããã°ãèŠãã®ã¯é¢çœãã§ããadbãã°ã¬ããŒãã䜿çšããŠååŸã§ããŸãã
I2CãGPIOãå²ã蟌ã¿ãããã¯ã°ã©ãŠã³ãã¿ã¹ã¯ã䜿çšããç°¡åãªã«ãŒãã«ãã©ã€ããŒã®äœææ¹æ³ãã®ãããI2Cããã³GPIOãä»ããŠããã€ã¹ãæäœããã«ãŒãã«ãã©ã€ããŒãäœæããå¿
èŠãããã/ devãã©ã«ããŒã§å
ã®ååã§åŒ·èª¿è¡šç€ºããå¿
èŠããã£ããããAndroidããã«ãŠã§ã¢ã¯ãã®ãã¡ã€ã«/ãã©ã€ããŒã«ã¢ã¯ã»ã¹ããŠäœããèªã¿æžãã§ããŸãã
ãã©ã€ããŒãäœæããéã®äžè¬çãªæ©èœïŒ
- ãã©ã€ããŒã¯ãã«ãŒãã«ã«ãã§ãŒã³ã§ããŒããããŸã-ãããã¬ãã«ã®ããã€ã¹ïŒãã©ãããã©ãŒã ããã¹ïŒã¯ãä»ã®ããã€ã¹ïŒããããæäœããããã®ç¹å®ã®ããã€ã¹ãšã¢ã«ãŽãªãºã ïŒãããŒãããŸãã
- ã«ãŒãã«ã®ã¢ã»ã³ããªäžã«ããã€ã¹ããªãŒãç¡å¹ã«ãªã£ãŠããå ŽåããŸãã¯å€ãã«ãŒãã«ããŒãžã§ã³ã®ããã«ãµããŒããããŠããªãå Žåããã§ãŒã³ãšããŒãé åºã¯ããã€ã¹ããªãŒãŸãã¯CããŒãã³ãŒãã«ãã£ãŠæ±ºå®ãããŸãã tegra3ã®ã±ãŒã¹ã¯2çªç®ã§ãã
- I2Céä¿¡ãééããã¯ã©ã€ã¢ã³ãã®i2cã®æ§é ãååŸããã«ã¯ããã©ãããã©ãŒã ããŒãã³ãŒãã«èšèŒãããŠããããã€ã¹ãšç»é²æžã¿ãã©ã€ããŒã®ãªã¹ããäžèŽããå Žåã«åŒã³åºããããããŒãé¢æ°ãäœæããå¿
èŠããããŸãã i2c_add_driverã
ããããæåã«ããã©ã€ããŒãããŠã³ããŒãããããã®åææ¡ä»¶ã ã€ãŸã ãã©ãããã©ãŒã åæåã³ãŒãã«ã€ããŠã
Nexus 7 2012ã¯Tegra3ããã»ããµäžã«æ§ç¯ãããŠããŸãã ã«ãŒãã«ã¯æ°ãããªãïŒ3.1.h.chïŒãããã€ã¹ããªãŒã¯ãããŸããã ããã¯ããã¹ãŠã®ããŒããŠã§ã¢ãCã³ãŒãã§èšè¿°ããã/ kernel / tegra / arch / arm / mach-tegra /
board-grouper-pinmux.cãã¡ã€ã«ã¯ããã¹ãŠã®SoCãã³ã®éã®æ§æãèšè¿°ããnVidiaã®ã«ãŒãã«ã®éããéšåã§ããããåæåããããã®äžè¬çãªé¢æ°ãå«ã¿ãŸãïŒãtegraããšããåèªã§å§ãŸããã¹ãŠã®é¢æ°ã¯ãã«ãŒãã«ã®éããéšåã§å®è£
ããããã€ããªåœ¢åŒã§æäŸãããŸãïŒ ããã§å€æŽããå¿
èŠããããã®ãèŠãŠã¿ãŸããã
board-grouper-sensors.cãã¡ã€ã«ã«ã¯ãããããçš®é¡ã®ç°ãªãããã€ã¹ã®ç»é²ãšãããã®ããã€ã¹ã®æãäžè¬çãªã¬ãã«ã®æ©èœïŒé»æºç®¡çãªã©ïŒãå«ãŸããŠããŸãã ããã§ãã«ãŒãã«ã®äžéšãšããŠèªã¿èŸŒãŸãããã©ã€ããŒã«ããã€ã¹ãç»é²ããããã®æ§é ãè¿œå ããå¿
èŠããããŸãã ãã®ãããªãã®ïŒ
ã³ã¡ã³ãä»ãã®ãã©ã€ããŒéšåã³ãŒã #include <linux/init.h> // Macros used to mark up functions eg __init __exit #include <linux/module.h> // Core header for loading LKMs into the kernel #include <linux/device.h> // Header to support the kernel Driver Model #include <linux/kernel.h> // Contains types, macros, functions for the kernel #include <linux/fs.h> // Header for the Linux file system support #include <linux/i2c.h> // main sensor communication protocol #include <linux/gpio.h> // sensor`s wake/sleep and new data interrupts are processed via two pins #include <linux/interrupt.h> // Support GPIO IRQ handler #include <asm/uaccess.h> // copy_to_user and copy_from_user functions #include <asm/io.h> // Access to memset() #include <linux/workqueue.h> // Make IRQ event into deferred handler task #include <linux/mutex.h> // Sync data buffer usage between IRQ-work and outer read requests #include <linux/delay.h> // Access to mdelay // /dev/tricky_temperature #define DEVICE_NAME "tricky_temperature" // #define CLASS_NAME "tricky" // ... ... // MODULE_LICENSE("GPL"); MODULE_AUTHOR("Pavel Akimov"); MODULE_DESCRIPTION("Test Linux driver for tricky sensor"); ///< modinfo MODULE_VERSION("0.1"); // , static int majorNumber; static struct class* trickyClass = NULL; static struct device* trickyDevice = NULL; // ... ... // static u8 sensor_data_buffer[I2C_DATA_SIZE] = { 0 }; // I2C struct i2c_client *tricky_i2c_client = NULL; // static int dev_open(struct inode *, struct file *); static ssize_t dev_read(struct file *, char *, size_t, loff_t *); static ssize_t dev_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param); // I2C static int tricky_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id); static int tricky_i2c_remove(struct i2c_client *i2c_client); // static int set_sensor_power(u8 enabled); // I2C static int read_raw_temperatures(void); // static irq_handler_t tricky_data_irq_handler(unsigned int irq, void *dev_id, struct pt_regs *regs); // static void read_data_work_handler(struct work_struct *w); // static struct workqueue_struct *wq = NULL; static DECLARE_DELAYED_WORK(read_data_work, read_data_work_handler); static struct mutex read_data_mutex; // static struct file_operations fops = { .open = dev_open, .read = dev_read, .unlocked_ioctl = dev_ioctl }; // static const struct i2c_device_id tricky_i2c_id[] = { { CLASS_NAME, 0 }, { }, // , }; MODULE_DEVICE_TABLE(i2c, tricky_i2c_id); // , static struct i2c_driver tricky_i2c_driver = { .driver = { .owner = THIS_MODULE, .name = CLASS_NAME, }, .id_table = tricky_i2c_id, .probe = tricky_i2c_probe, .remove = tricky_i2c_remove }; // i2c i2c , static int tricky_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { tricky_i2c_client = client; return 0; } // static int tricky_i2c_remove(struct i2c_client *i2c_client) { if (tricky_i2c_client != NULL) { i2c_unregister_device(tricky_i2c_client); tricky_i2c_client = NULL; } return 0; } // static int __init tricky_temperature_init(void) { int err; // Try to dynamically allocate a major number for the device -- more difficult but worth it majorNumber = register_chrdev(0, DEVICE_NAME, &fops); if (majorNumber<0){ pr_err(KERN_ALERT "Tricky failed to register a major number\n"); return majorNumber; } printk(KERN_INFO "Tricky: registered correctly with major number %d\n", majorNumber); // Register the device class trickyClass = class_create(THIS_MODULE, CLASS_NAME); if (IS_ERR(trickyClass)){ // Check for error and clean up if there is pr_err(KERN_ALERT "Failed to register device class\n"); err = PTR_ERR(trickyClass); // Correct way to return an error on a pointer goto err_char_dev; } printk(KERN_INFO "Tricky: device class registered correctly\n"); // Register the device driver trickyDevice = device_create(trickyClass, NULL, MKDEV(majorNumber, 0), NULL, DEVICE_NAME); if (IS_ERR(trickyDevice)){ // Clean up if there is an error pr_err(KERN_ALERT "Failed to create the device\n"); err = PTR_ERR(trickyDevice); goto err_class; } printk(KERN_INFO "Tricky: device class created correctly\n"); // Made it! device was initialized // I2 , // (, board grouper sensors) probe err = i2c_add_driver(&tricky_i2c_driver); if (err < 0) { pr_err("Tricky: Error: %s: driver registration failed, error=%d\n", __func__, err); goto err_dev; } // I2C ... // IRQ callback` // , err = request_irq( i2c_client->irq, (irq_handler_t)tricky_data_irq_handler, IRQF_TRIGGER_FALLING, "tricky_gpio_handler", NULL); // no shared interrupt lines if (err < 0) { pr_err("Tricky: Error: %s: cannot register GPIO_NIRQ irq handler: Error=%d\n", __func__, err); goto err_drv; } // IRQ wq = create_singlethread_workqueue("tricky_work"); mutex_init(&read_data_mutex); printk(KERN_INFO "Tricky: initialization completed\n"); return 0; err_irq: destroy_workqueue(wq); free_irq(i2c_client->irq, NULL); err_drv: i2c_del_driver(&tricky_i2c_driver); err_dev: device_destroy(trickyClass, MKDEV(majorNumber, 0)); // remove the device class_unregister(trickyClass); // unregister the device class err_class: class_destroy(trickyClass); // remove the device class err_char_dev: unregister_chrdev(majorNumber, DEVICE_NAME); // unregister the major number return err; } // static void __exit tricky_temperature_exit(void) { if (delayed_work_pending(&read_data_work) != 0) cancel_delayed_work_sync(&read_data_work); destroy_workqueue(wq); free_irq(i2c_client->irq, NULL); i2c_del_driver(&tricky_i2c_driver); if (tricky_i2c_client != NULL) { i2c_unregister_device(tricky_i2c_client); tricky_i2c_client = NULL; } device_destroy(trickyClass, MKDEV(majorNumber, 0)); class_unregister(trickyClass); class_destroy(trickyClass); unregister_chrdev(majorNumber, DEVICE_NAME); printk(KERN_INFO "Tricky: Goodbye\n"); } static int dev_open( struct inode *node, struct file *filep) { printk(KERN_INFO "Tricky: Open the LKM!\n"); return 0; } static ssize_t dev_read( struct file *filep, char *buffer, size_t len, loff_t *offset) { int ret; // , (HAL) , if (!buffer || len != I2C_DATA_SIZE) { return -EINVAL; } mutex_lock(&read_data_mutex); ret = copy_to_user(buffer, sensor_data_buffer, I2C_DATA_SIZE); mutex_unlock(&read_data_mutex); if (ret != 0) { return -ENOMEM; } return 0; } static ssize_t dev_ioctl( struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) { switch (ioctl_num) { case IOCTL_POWER: ret = set_sensor_power(ioctl_param != CMD_POWER_WAKEUP ? 1 : 0); if (ret < 0) { return ret; } break; case ... // more commands default: pr_err(KERN_INFO "Tricky: invalid command type to apply\n"); return -EINVAL; } return 0; } static int set_sensor_power(u8 enabled) { gpio_set_value(GPIO_PWR_DOWN, enabled != 0); return 0; } // I2C : (2 ) // static int read_raw_temperatures(void) { int ret; struct i2c_msg write_message; struct i2c_msg read_message; write_message.addr = I2C_SLAVE_ADDRESS; write_message.flags = 0; // plain write write_message.buf = (char*)i2c_read_temperatures_address; write_message.len = sizeof(i2c_read_temperatures_address); memset(sensor_data_buffer, 0, sizeof(sensor_data_buffer)); read_message.addr = I2C_SLAVE_ADDRESS; read_message.flags = I2C_M_RD; // plain read read_message.buf = (char*)sensor_data_buffer; read_message.len = sizeof(sensor_data_buffer); // read out data ret = i2c_transfer(tricky_i2c_client->adapter, &write_message, 1); if (ret < 0) { pr_err(KERN_INFO "Tricky: Cannot write data address. Error=%d\n", ret); return ret; } ret = i2c_transfer(tricky_i2c_client->adapter, &read_message, 1); if (ret < 0) { pr_err(KERN_INFO "Tricky: Cannot read data from the sensor. Error=%d\n", ret); return ret; } return 0; } // - // , I2C , // I2C // , , , // static irq_handler_t tricky_data_irq_handler(unsigned int irq, void *dev_id, struct pt_regs *regs) { // , if (delayed_work_pending(&read_data_work) == 0) queue_delayed_work(wq, &read_data_work, msecs_to_jiffies(1)); return (irq_handler_t)IRQ_HANDLED; } // , // // ( , ) static void read_data_work_handler(struct work_struct *w) { int ret; mutex_lock(&read_data_mutex); ret = read_raw_temperatures(); mutex_unlock(&read_data_mutex); if (ret < 0) { printk(KERN_INFO "Tricky: read_data_work_handler. Ret = %d\n", ret); } } // , module_init(tricky_temperature_init); module_exit(tricky_temperature_exit);
åå¥ã«ãã¢ã»ã³ããªã®ãã¡ã€ã«ã§ããKConfigãšMakefileã«èšåããå¿
èŠããããŸãã
KConfigã§ã¯ãMakefileã§äœæãããTRICKY_SENSORïŒCONFIG_ãã¬ãã£ãã¯ã¹ãªãïŒãšããååã§ãã¢ã»ã³ããªäžã«èæ
®ã«å
¥ãã段èœãããã«è¿œå ããŸãã ãŸããmake menuconfigã䜿çšãããšããã©ã€ããŒã衚瀺ãããŸãã
Kconfig menuconfig THERMAL tristate "Generic Thermal sysfs driver" help Generic Thermal Sysfs driver offers a generic mechanism for thermal management. Usually it's made up of one or more thermal zone and cooling device. Each thermal zone contains its own temperature, trip points, cooling devices. All platforms with ACPI thermal support can use this driver. If you want this support, you should say Y or M here. config THERMAL_HWMON bool depends on THERMAL depends on HWMON=y || HWMON=THERMAL default y config TRICKY_SENSOR default y bool prompt "Tricky temperature sensor support"
ã¡ã€ã¯ãã¡ã€ã« obj-$(CONFIG_THERMAL) += thermal_sys.o obj-$(CONFIG_TRICKY_SENSOR) += tricky_temperature.o
ãã®çµæãã«ãŒãã«çšã«æ¬¡ã®ãã¡ã€ã«ãååŸããŸãã
kernel/tegra/arch/arm/mach-tegra/board-grouper-pinmux.c kernel/tegra/arch/arm/mach-tegra/board-grouper-sensors.c kernel/tegra/drivers/thermal/tricky_sensor.c kernel/tegra/drivers/thermal/KConfig kernel/tegra/drivers/thermal/Makefile
Androidããã«ãŠã§ã¢ã§éçãæœè±¡åããæ¹æ³ããŸãã¯æ¢åã®ãã®ã䜿çšããæ¹æ³æ¬¡ã®ã¬ãã«ã«é²ã¿ãŸãããã ãã©ã€ããŒã¯äœæãããŠãããAndroidã®ãŠãŒã¶ãŒç©ºééšåã«ç§»åããŠããŸããããã§ããã©ã€ããŒã«äœããã®æ¹æ³ã§ãã€ã³ãããå¿
èŠããããŸãã
Androidã§åãçš®é¡ã®åšèŸºæ©åšã®å€ãã®å®è£
ã䜿çšããããã«ãããŒããŠã§ã¢ã¢ãã¹ãã©ã¯ã·ã§ã³ã®ããŸããŸãªã€ã³ã¿ãŒãã§ã€ã¹ãå«ãããã«ãŠã§ã¢ã¬ã€ã€ãŒïŒC / C ++ã§èšè¿°ïŒããããŸãïŒããŒããŠã§ã¢ã¢ãã¹ãã©ã¯ã·ã§ã³ã¬ãã«-HALïŒã ãããŠãããããçš®é¡ã®æž©åºŠç£æ°ãªã©ã®ããã« ã»ã³ãµãŒãããå ŽæããããŸãã ãããããã®HALã®å¶éã¯ããã®APIãèªã¿åãå°çšã§ããããšã§ããããã¯ããããã®ããã€ã¹ã«åæã«ã¢ã¯ã»ã¹ã§ããå€ãã®ãŠãŒã¶ãŒããã°ã©ã ãèãããšåŠ¥åœã§ãã ãããŠãäžæ¹ã®èšå®ãå€æŽãããšãããäžæ¹ã®èšå®ã«ãªããŸãã ãã®ãã¹ãŠã¯ãããã§éåžžã«ãã説æãããŠã
ãŸã ã
ãŸããç¹ã«ã»ã³ãµãŒãæäœããèªã¿åãå°çšã¢ãŒãã«é¢ããŠã¯ãäžèšã®ãªã³ã¯ããã®åŒçšã§ãã
ãµã³ããªã³ã°é »åºŠãšæ倧ã¬ããŒãé
延以å€ã«ãã¢ããªã±ãŒã·ã§ã³ã¯ã»ã³ãµãŒãã©ã¡ãŒã¿ãŒãæ§æã§ããŸããã ããšãã°ããé«ç²ŸåºŠãã¢ãŒããšãäœé»åãã¢ãŒãã®äž¡æ¹ã§æ©èœããç©çã»ã³ãµãŒãæ³åããŠãã ããã ãã以å€ã®å Žåã¯ã¢ããªã±ãŒã·ã§ã³ãé«ç²ŸåºŠã¢ãŒããèŠæ±ããå¥ã®ã¢ãŒãã¯äœé»åã¢ãŒããèŠæ±ããå¯èœæ§ããããããAndroidããã€ã¹ã§äœ¿çšã§ããã®ã¯ããã2ã€ã®ã¢ãŒãã®ãã¡1ã€ã ãã§ãã ãã¬ãŒã ã¯ãŒã¯ãäž¡æ¹ã®ã¢ããªã±ãŒã·ã§ã³ãæºããæ¹æ³ã¯ãããŸããã ãã¬ãŒã ã¯ãŒã¯ã¯åžžã«ãã¹ãŠã®ã¯ã©ã€ã¢ã³ããæºè¶³ãããå¿
èŠããããããããã¯ãªãã·ã§ã³ã§ã¯ãããŸããã
ã¢ããªã±ãŒã·ã§ã³ããã»ã³ãµãŒãŸãã¯ãã®ãã©ã€ããŒã«ããŒã¿ãéä¿¡ããã¡ã«ããºã ã¯ãããŸããã ããã«ããã1ã€ã®ã¢ããªã±ãŒã·ã§ã³ãã»ã³ãµãŒã®åäœãå€æŽã§ããªããªããä»ã®ã¢ããªã±ãŒã·ã§ã³ãç ŽæããããšããªããªããŸãã
ããããç§ãã¡ã¯æ¬åœã«ããã€ã¹ãå¶åŸ¡ããŸãïŒããšãã°ãé»åã¢ãŒããšæž¬å®ã¢ãŒããåãæ¿ããŸãïŒããŸããã»ã³ãµãŒã¯å
¬åŒã«ææžåãããŠããããããã°ã©ã ã®ã¿ãåäœãããããç¬èªã®HALãäœæããŸãã ããã§ã¯åºæ¬çãªããšã¯ã¢ã¯ã»ã¹å¯èœãªè±èªã§æžãããŠããã®ã§ãåŸã§ã©ã®
ãããªããŒã¿æ§é ãšãã®çç±ãæããã«ãªããŸãã
ç¬èªã®ããŒããŠã§ã¢ãäœæããŸãã ãããè¡ãã«ã¯ãIDãèŠã€ããŠãã¢ãžã¥ãŒã«ã®èª¬æãããã³æŽŸçé¢æ°ãå«ãhw_device_tãå«ãæ§é äœãäœæããå¿
èŠããããŸãã Googleã¯ããã®ã¬ãã«ã§ã®å®è£
ãšã€ã³ã¿ãŒãã§ãŒã¹ã®å€èŠ³ãæ£ç¢ºã«æå®ããŠããªããããå
貎ãæ¯ãè¿ãããšãªããè¯ããã®ããŸãå§ããããšãã§ããŸãã
sensor_tricky_temperature.h #ifndef ANDROID_TRICKY_INTERFACE_H #define ANDROID_TRICKY_INTERFACE_H #include <stdint.h> #include <sys/cdefs.h> #include <sys/types.h> #include <hardware/hardware.h> __BEGIN_DECLS #define TRICKY_HARDWARE_MODULE_ID "tricky" struct tricky_device_t { struct hw_device_t common; int (*read_sample)(unsigned short *psynchro, short *pobj_temp, short *pntc1_temp, short *pntc2_temp, short *pntc3_temp); int (*activate)(unsigned char enabled); int (*set_mode)(unsigned char is_continuous); }; __END_DECLS #endif // ANDROID_TRICKY_INTERFACE_H
sensor_tricky_temperature.c #include <errno.h> #include <cutils/log.h> #include <cutils/sockets.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <linux/i2c.h> #include <hardware/sensor_tricky_temperature.h> #define LOG_TAG "TRICKY" #define DEVICE_NAME "/dev/tricky_temperature" #define TRICKY_MODE_0 0 #define TRICKY_MODE_1 1 int fd = 0; int read_sample(unsigned short *psynchro, short *pobj_temp, short *pntc1_temp, short *pntc2_temp, short *pntc3_temp) { int ret = 0; unsigned char buffer[10]; ALOGD("HAL -- read_sample() called"); ret = read(fd, (char*)buffer, sizeof(buffer)); if (ret < 0) { ALOGE("HAL -- cannot read raw temperature data"); return -1; } if (psynchro) *psynchro = (unsigned short)(buffer[3] << 8 | buffer[2]); if (pobj_temp) *pobj_temp = (short)(buffer[1] << 8 | buffer[0]); if (pntc1_temp) *pntc1_temp = (short)(buffer[5] << 8 | buffer[4]); if (pntc2_temp) *pntc2_temp = (short)(buffer[7] << 8 | buffer[6]); if (pntc3_temp) *pntc3_temp = (short)(buffer[9] << 8 | buffer[8]); ALOGD("HAL - sample read OK"); return 0; } int activate(unsigned char enabled) { int ret = 0; ALOGD("HAL - activate(%d) called", enabled); ret = ioctl(fd, 0, enabled ? TRICKY_MODE_0 : TRICKY_MODE_1); if (ret < 0) { ALOGE("HAL - cannot write activation state"); return -1; } ALOGD("HAL - activation state written OK"); return 0; } int set_mode(unsigned char is_continuous) { int ret; ALOGD("HAL -- set_mode(%d) called", is_continuous); ret = ioctl(fd, 1, is_continuous ? TRICKY_MODE_0 : TRICKY_MODE_1); if (ret < 0) { ALOGE("HAL - cannot write mode state"); return -1; } ALOGD("HAL - mode state written OK"); return 0; } static int open_tricky(const struct hw_module_t* module, char const* name, struct hw_device_t** device) { int ret = 0; struct tricky_device_t *dev = malloc(sizeof(struct tricky_device_t)); if (dev == NULL) { ALOGE("HAL - cannot allocate memory for the device"); return -ENOMEM; } else { memset(dev, 0, sizeof(*dev)); } ALOGD("HAL - openHAL() called"); dev->common.tag = HARDWARE_DEVICE_TAG; dev->common.version = 0; dev->common.module = (struct hw_module_t*)module; dev->read_sample = read_sample; dev->activate = activate; dev->set_mode = set_mode; *device = (struct hw_device_t*) dev; fd = open(DEVICE_NAME, O_RDWR); if (fd <= 0) { ALOGE("HAL - cannot open device driver"); return -1; } ALOGD("HAL - has been initialized"); return 0; } static struct hw_module_methods_t tricky_module_methods = { .open = open_tricky }; struct hw_module_t HAL_MODULE_INFO_SYM = { .tag = HARDWARE_MODULE_TAG, .version_major = 1, .version_minor = 0, .id = TRICKY_HARDWARE_MODULE_ID, .name = "Tricky HAL Module", .author = "Pavel Akimov", .methods = &tricky_module_methods, };
ã¢ãžã¥ãŒã«ããã«ãããã«ã¯ã
Android.mkãã¡ã€ã«ãå¿
èŠã§ãã
Android.mk # LOCAL_PATH := $(call my-dir) # .mk , # # , LOCAL_PATH include $(CLEAR_VARS) LOCAL_PRELINK_MODULE := false # , LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw # LOCAL_SHARED_LIBRARIES := liblog libcutils libhardware # , LOCAL_SRC_FILES := sensor_tricky_temperature.c # LOCAL_MODULE := techartmsjdts.default LOCAL_MODULE_TAGS := debug include $(BUILD_SHARED_LIBRARY)
ãŸããã³ã³ãã€ã«ãããã©ã€ãã©ãªãlibhardwareã«å«ããããã®å¥ã®Android.mkãã¡ã€ã«ã ã¢ãžã¥ãŒã«ã®IDãååã§è¿œå ããŸãã
Android.mk hardware_modules := gralloc hwcomposer audio nfc nfc-nci local_time \ power usbaudio audio_remote_submix camera consumerir tricky include $(call all-named-subdir-makefiles,$(hardware_modules))
HALã®åºåã«ã¯ã次ã®ãã¡ã€ã«ããããŸã
hardware/libhardware/include/hardware/sensor_tricky_temperature.h hardware/libhardware/modules/Android.mk hardware/libhardware/modules/tricky/sensor_tricky_temperature.c hardware/libhardware/modules/tricky/Android.mk
ã·ã¹ãã ãµãŒãã¹ãè¿œå ããæ¹æ³ãšããµãŒãã¹ãæå¹ã«ããŠèŠã€ããããã«äœããè¿œå ããå Žæããã«ã誰ããHALã«é»è©±ããå¿
èŠããããŸãã OCã®ä»ã®éšåã§ã¯ããã®ãããªããšã¯ãJavaã§èšè¿°ãããã·ã¹ãã ãµãŒãã¹ãšãã®ãããŒãžã£ãŒã䜿çšããŠè¡ãããŸãã è¡ã®å€ã«åºãªãããã«ããã«ã¯ãå¥ã®ãã®ãæžããŸãã åœç€Ÿã®ãµãŒãã¹ã¯æ¬¡ã®ãã¡ã€ã«ã«åå ããŸãã
frameworks\base\core\java\android\app\ContextImpl.java frameworks\base\core\java\android\content\Context.java frameworks\base\core\java\android\hardware\temperature\ITrickyService.aidl frameworks\base\core\java\android\hardware\temperature\TrickyTemperatureData.aidl frameworks\base\core\java\android\hardware\temperature\TrickyTemperatureData.java frameworks\base\core\java\android\hardware\temperature\TrickyManager.java frameworks\base\services\java\com\android\server\temperature\TrickyService.java frameworks\base\services\java\com\android\server\SystemServer.java frameworks\base\services\jni\Android.mk frameworks\base\services\jni\com_android_server_temperature_TrickyService.cpp frameworks\base\services\jni\onload.cpp frameworks\base\Android.mk
ãœãŒã¹ãããããããã«ããã€ãã£ãã¬ãã«ã¯ãŸã ããããªããããJNIãä»ããŠHALã¢ãžã¥ãŒã«ã«æ¥ç¶ããå¿
èŠããããŸãã åæã«ãåç
§ã¿ã€ããæžãçããŸããããã¯
AIDLãä»ããŠæ±ºå®ããC ++ããJavaã«æããå¿
èŠããããŸãã
ãµãŒãã¹ã®ãã€ãã£ãéšåã®ã³ãŒã ããã«onload.cppã¯ããããå¿
èŠãšãããµãŒãã¹ã®ãã¹ãŠã®JNIéšåãããŒãããŸããç§ãã¡ã®ãã®ãå«ããåŸæ¥ã®Android.mkã«ã¯ããã¹ãŠã®ããŒããçµã¿ç«ãŠãããã®æ
å ±ãå«ãŸããŠãããJNIã®ããŒã¹ãããã«ãããŸããåç
§ã¿ã€ãã¯AIDLã䜿çšããŠäœæããå¿
èŠããããŸãããã®èšèªã¯Androidã ãã§ãªããAndroidã®ããã»ã¹éããŒã¿è»¢éã®æ段ã§ããããã§ãããŸããããã転éããã«ã¯ã以äžã®ãªã¹ãã«ç€ºãããã«ãããŒã»ã«å¯èœã§ããå¿
èŠããããŸããTrickyTemperatureData.aidl package android.hardware.temperature; parcelable TrickyTemperatureData;
TrickyTemperatureData.java package android.hardware.temperature; import android.os.Parcel; import android.os.Parcelable; public final class TrickyTemperatureData implements Parcelable { public int synchro; public int objectTemperature; public int ntc1Temperature; public int ntc2Temperature; public int ntc3Temperature; public static final Parcelable.Creator<TrickyTemperatureData> CREATOR = new Parcelable.Creator<TrickyTemperatureData>() { public TrickyTemperatureData createFromParcel(Parcel in) { return new TrickyTemperatureData(in); } public TrickyTemperatureData[] newArray(int size) { return new TrickyTemperatureData[size]; } }; public TrickyTemperatureData() { } private TrickyTemperatureData(Parcel in) { readFromParcel(in); } @Override public void writeToParcel(Parcel out, int flags) { out.writeInt(synchro); out.writeInt(objectTemperature); out.writeInt(ntc1Temperature); out.writeInt(ntc2Temperature); out.writeInt(ntc3Temperature); } public void readFromParcel(Parcel in) { synchro = in.readInt(); objectTemperature = in.readInt(); ntc1Temperature = in.readInt(); ntc2Temperature = in.readInt(); ntc3Temperature = in.readInt(); } @Override public int describeContents() { return 0; } }
ãµãŒãã¹èªäœãšãã®ãããŒãžã£ãŒã¯éåžžã«ã·ã³ãã«ã§æ°åããªãã®ã§ãããã§ã¯èª¬æããŸããããã¹ãŠãç£èŠãŸãã¯çªããªã³ã¯ã«é
眮ããŸããããã§ããµãŒãã¹ã®ååã䜿çšããŠå®æ°ãè¿œå ããå¿
èŠããããŸãããã®ãµãŒãã¹ã䜿çšãããšãcontext.getSytemServiceãä»ããŠæ€çŽ¢ã§ããŸããã³ã¡ã³ãã«ã¯hideãå«ããå¿
èŠãããããšã«æ³šæããŠãã ãããããããªããšãã¢ã»ã³ããªã¯æ©èœããããã®ãããªååã¯APIã«æ£åŒã«ç»é²ãããããããã³ã°ããå¿
èŠããããšããã¡ãã»ãŒãžãæ®ããŸãã
ãµãŒãã¹ãæ©èœãããã«ã¯ãããã§SystemServerãä»ããŠServiceManagerã«å«ããå¿
èŠããããŸãã
ãµãŒãã¹ãã¢ããªã±ãŒã·ã§ã³åŽã§äœ¿çšå¯èœã«ããã«ã¯ããã®ãããŒãžã£ãŒãã³ã³ããã¹ãã«è¿œå ããå¿
èŠããããŸãïŒéçããŒãã£ã³ã°ãããã¯å
ïŒã
RegisterServiceèªäœã¯ãAndroid 4.4.4ã§ã¯æ¬¡ã®ããã«ãªããŸãã private static int sNextPerContextServiceCacheIndex = 0;
ç¬èªã®ã«ãŒã«ãè¿œå ããŠSEAndroid / SELinuxãçªç Žããæ¹æ³ããŠããã¹ãŠã®ã³ãŒããèšè¿°ãããŠããããã§ããããã©ã€ããŒã¯å®å
šã«ã«ãŒããŠãŒã¶ãŒã«ãã£ãŠææãããŠããããããµãŒãã¹ã¯éå§ãããããã°ã«å®è¡ããæš©éããªããšããã¡ãã»ãŒãžã衚瀺ããããããŠãäœãã®èšé²ãæžããšãçµæãšããŠãå©çã¯ãããŸãããå¿
èŠãªæš©å©ãšèŠåã¯ãsepolicyããŒãã§èŠå®ããå¿
èŠããããŸããinitã¹ã¯ãªããã®ãã©ãããã©ãŒã åºæã®éšåãã·ã¹ãã å
šäœã®ã»ãŒåæã®èµ·åãåŠçããŸãã #(device/asus/grouper/init.grouper.rc) # ... on post-fs-data # ... # tricky temperature sensor # / system # root` chmod 0660 /sys/class/tricky/tricky_temperature/dev chown system system /sys/class/tricky/tricky_temperature/dev
ãŸããããã€ã¹ãã¡ã€ã«èªäœã®æš©å©ãšèš±å¯ãueventdã«ç»é²ããŸãã # device/asus/grouper/ueventd.grouper.rc /dev/tricky_temperature 0660 system system
ãããŠ...ã·ã¹ãã ãµãŒãã¹ïŒã³ãŒãã§æ¢ã«è¿œå ããŠããå ŽæïŒã§ãµãŒãã¹ãèªã¿èŸŒãããšãã§ããããã«ãããããçš®é¡ã®SELinuxã«ãŒã«ãäœæããå¿
èŠããããŸãããŸãããµãŒãã¹ã§ãããã£ã©ã¯ã¿ãŒããã€ã¹ïŒãã©ã€ããŒïŒã®èªã¿åããšæžã蟌ã¿ãèš±å¯ããã«ãŒã«ãäœæããå¿
èŠããããŸããäž»ã«Brilloã®äŸã«äŸåããŠããŸãããç§ã¯ããã«å€¢äžã«ãªã£ãŠãã¹ãŠãç解ãããã©ããã¯ããããŸããããé çªã«è©ŠããŠã¿ãŸãããïŒ1ã€ã®ãããã¯ãã¹ã«ã«ãŒã«ããããã¹ãŠã®ãã¡ã€ã« ##################################### # , # . # , . # (te_macros) # tricky_service_domain(domain) # Allow a base set of permissions common across Android daemons. define(`tricky_service_domain', ` init_daemon_domain($1) # Allow using binder and performing IPC to system services. binder_use($1) binder_service($1) # Allow access to files in /proc. # Fixes denials like: # avc: denied { read } for pid=1267 comm="peripheralman" name="misc" dev="proc" # ino=4026531967 scontext=u:r:peripheralman:s0 # tcontext=u:object_r:proc:s0 tclass=file permissive=0 allow $1 proc:file r_file_perms; allow $1 tricky_service:service_manager find; # Cut down on spam. dontaudit $1 kernel:system module_request; ') ##################################### # , , # # (tricky_service.te) type tricky_service, domain; type tricky_service_exec, exec_type, file_type; tricky_service_domain(tricky_service) ##################################### # , system manager # (service.te) type tricky_service, service_manager_type; # , # "tricky_service" . # SELinux https://source.android.com/security/selinux/ ##################################### # (service_contexts) android.service.jdtstemperature.IJdstsService u:object_r:tricky_service:s0 ##################################### # . # . # (device.te) type tricky_device, dev_type, mlstrustedobject; ##################################### # # (file_contexts) /dev/tricky_temperature u:object_r:tricky_device:s0 ##################################### # ( , , # "bootanim" # ) #(bootanim.te) allow bootanim tricky_device:chr_file rw_file_perms; ##################################### # , , SystemServer system apps # (system_server.te) allow system_server tricky_device:chr_file rw_file_perms; ##################################### # (system_app.te) allow system_app tricky_device:chr_file rw_file_perms;
ããã§ããµãŒãã¹çšã®æ°ãããã¡ã€ã³ãäœæããããã€ã¹ãç¹å®ãããµãŒãã¹ã«ãã©ã€ããŒãžã®èªã¿åãããã³æžã蟌ã¿æš©éãããããšã瀺ããŸããããã¡ãããããããã¹ãŠæžããã®ã¯åããŠã§ã¯ãããŸããã§ããããã®ãã¹ãŠã®ããŒãã®åŸãã·ã¹ãã ã¯æçµçã«ãããã¯ããããµãŒãã¹ã«é¢ããã¡ãã»ãŒãžãåãé€ããadbã·ã§ã«ã§ãã©ã€ããŒãã·ã¹ãã ã®ãŠãŒã¶ãŒåã«èšé²ãããäžçäžã«å
¬éãããŠããããšãæããã«ãªããŸããããã§ãã¯æ¹æ³-ç°¡åãªã¢ããªãæžããã¹ãŠãæ©èœããããšãäœããã®åœ¢ã§æ€èšŒããå¿
èŠããããŸãããã¡ãããadbã·ã§ã«ãä»ããŠlogcatããã£ãšèŠã€ããããšãã§ããŸãããäœããã®çç±ã§èª°ãããã®çµæã«æºè¶³ããŠããããã§ã¯ãªããããã«ã¹ã¿ã OCã«çµã¿èŸŒã¿ã¢ããªã±ãŒã·ã§ã³ãè¿œå ããŸãããã¡ããããã«ãã€ã³ããã®ã¿ãã¬ãããé€ãã誰ããããå¿
èŠãšããŸããããã±ãŒãž/ã¢ããª/ TrickyDemoãããã³ãã«ã/ã¿ãŒã²ãã/補å/core.mkã«å
¥ãããœãŒã¹ã§ã¯ãäºåå®çŸ©ããããã®ã®ãªã¹ãã§ããã瀺ããŸããã¡ã€ã³ã³ãŒãå
éšã¢ããªã±ãŒã·ã§ã³ package com.android.trickydemo; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.widget.CompoundButton; import android.widget.ImageView; import android.widget.Switch; import android.widget.TextView; import android.hardware.temperature.*; public class MainActivity extends Activity { private final String TAG = "TrickyDemo"; private final int POLLING_PERIOD_MS = 200; private TrickyManager mServiceManager = null; private TrickyTemperatureData mSensorData = null; private GaugeView mGaugeObj; private GaugeView mGaugeNtc1; private GaugeView mGaugeNtc2; private GaugeView mGaugeNtc3; private TextView mTextSynchro; private ImageView mIrqImage; private TextView mTextObj; private TextView mTextNtc1; private TextView mTextNtc2; private TextView mTextNtc3;
ç°¡åã«ããããã«ãã¢ããªã±ãŒã·ã§ã³ã¯Android Studioã§äœæããïŒsdkãæ£ããèšå®ããããšãå¿ããªãã§ãã ãã-4.4.4ã§åéããŠããŸãïŒãäžèŠãªãã®ã¯ãã¹ãŠåãé¢ãããŸãããããããã«ãã«ã¯Android.mkãåã³äœ¿çšãããŸããããã¯ç§ã«ãšã£ãŠã¯ãã®ããã«èŠããŸãã LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_RESOURCE_FILES := $(addprefix $(LOCAL_PATH)/, res) LOCAL_PACKAGE_NAME := TrickyDemo LOCAL_CERTIFICATE := platform LOCAL_STATIC_JAVA_LIBRARIES := android-support-core-utils-api24 include $(BUILD_PACKAGE)
ã¢ã»ã³ããªã«ééã£ãã©ã€ãã©ãªã®ãšã©ãŒãŸãã¯ãããã®ããã€ãã®æ¬ åŠãå«ãŸããŠããå Žåãout / target / common / obj / SHARED_LIBRARIESã調ã¹ãŠé©åãªååãæ¢ããŸãããã¹ãŠãåéããæ¹æ³ä»ã§ã¯ããã¹ãŠãåéããã ãã§ããã¿ãŒã²ããããã€ã¹ã®ãã©ã¡ãŒã¿ãŒã¯æ¬¡ã®ãšããã§ããHWïŒNexus 7ïŒ2012 grouperïŒOSïŒAndroid Kitkat 4.4.4 KTU84Pã«ãŒãã«ïŒtegra3_android_defconfig 3.1.10-gle42d16æåã«ãã«ãŒãã«ããã«ãããŸããå¿
èŠãªã«ãŒãã«ãœãŒã¹ã¯æ¬¡ã®ãšããã§ãã git clone https://android.googlesource.com/kernel/tegra.git -b android-tegra3-grouper-3.1-kitkat-mr2
ããããã«ãŒãã«ãæ§ç¯ããããã«å¿
èŠãªããŒã«ãããŠã³ããŒãããŸãã mkdir arm-eabi-4.6 cd arm-eabi-4.6 git init git clone https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/
ã«ãŒãã«ããã«ãããæ¹æ³ïŒã«ãŒãã«ã®ã«ãŒããã©ã«ããŒã«ããïŒïŒ ARCH=arm SUBARCH=arm CROSS_COMPILE=<path_to_arm_eabi-4.6>/arm-eabi-4.6/bin/arm-eabi- make tegra3_android_defconfig ARCH=arm SUBARCH=arm CROSS_COMPILE=<path_to_arm_eabi-4.6>/arm-eabi-4.6/bin/arm-eabi- make menuconfig ARCH=arm SUBARCH=arm CROSS_COMPILE=<path_to_arm_eabi-4.6>/arm-eabi-4.6/bin/arm-eabi- make -j4 zImage
ã«ã¹ã¿ã å€æŽãã³ããŒããŠmenuconfigãäœæããåŸãããã€ã¹ãã©ã€ããŒã»ã¯ã·ã§ã³ã«ã¯ãããªãããŒãªæž©åºŠã»ã³ãµãŒçšã«éžæãããã©ã€ããŒãå«ãŸããŠããã¯ãã§ãïŒmenuconfig-äžèšã®ã³ãã³ãã䜿çšããŠãã®æ
å ±ãåç
§ããŠãã ããïŒãã«ãŒãã«ã¯é«éåããŠããŸããã¢ã»ã³ããªåŸãçµæã®ã€ã¡ãŒãžã¯kernel / tegra / arch / arm / boot / zImageã«ãããŸãã次ã¯Androidã§ãããœãŒã¹ããAndroid OSããã«ãããã«ã¯ãé·æééå±ããªãããã«åŒ·åãªã³ã³ãã¥ãŒã¿ãŒãšãå€ãã®ãã£ã¹ã¯ã¹ããŒã¹ãå¿
èŠã§ãïŒè©³çŽ°ã¯ãã¡ãïŒãç§ã®å Žåãã¢ã»ã³ããªã¯Ubuntu 14.04 LTS x64ã§è¡ãããŸããïŒWindowsã§ã®ã¢ã»ã³ããªã¯ãµããŒããããŠããŸããïŒãå¿
èŠãªããã±ãŒãžã®ã€ã³ã¹ããŒã«ããã»ã¹ã«ã€ããŠã¯ãããã§è©³ãã説æããŠããŸãããããã§ç§ã¯ããã«æ¢ãŸããªããå¯äžèŠããŠããã¹ãããšã¯ãç°ãªãããŒãžã§ã³ã®Javaã䜿çšããŠç°ãªãOSããŒãžã§ã³ãæ§ç¯ããããšã§ãïŒAndroid 7ã§ã¯OpenJDK Java 8ãNexus 7ããã³Android 4.xã§ã¯Oracle Java 6ïŒãAndroidããã«ãããåã«ç°å¢ãã»ããã¢ããããã«ã¯ããã¡ãããèªã¿ãã ããããªããžããªãããœãŒã¹ãããŠã³ããŒãããã«ã¯ãGitã®ãã©ã€ããã¯ã§ããRepoã䜿çšããŸããããã«ãããããã«å€ãã®gitãªããžããªãæäœã§ããŸãïŒã€ã³ã¹ããŒã«ã®è©³çŽ°ã¯ãã¡ãïŒãRepoãã€ã³ã¹ããŒã«ããåŸãå°æ¥ã®ãœãŒã¹ããããã©ã«ããŒã«ç§»åããŠããããå®è¡ããŸãã repo init -u https:
ããŠã³ããŒãããã»ã¹ã¯çŽ50 GBã§ããŠã³ããŒãããããããéåžžã«æéãããããŸãã次ã«ãNexusã®ããŒãžã§ã³4.4.4 KTU84Pã®è¿œå ã®ãã€ããªã補é å
ããïŒAndroid OSãœãŒã¹ã®ãããã©ã«ããŒã®ã«ãŒãã«ïŒããŠã³ããŒãããŸãã https://dl.google.com/dl/android/aosp/asus-grouper-ktu84p-b12ce5f7.tgz https://dl.google.com/dl/android/aosp/broadcom-grouper-ktu84p-646d5a68.tgz https://dl.google.com/dl/android/aosp/elan-grouper-ktu84p-742223b3.tgz https://dl.google.com/dl/android/aosp/invensense-grouper-ktu84p-724c855a.tgz https://dl.google.com/dl/android/aosp/nvidia-grouper-ktu84p-e6d581dc.tgz https://dl.google.com/dl/android/aosp/nxp-grouper-ktu84p-27abae08.tgz https://dl.google.com/dl/android/aosp/widevine-grouper-ktu84p-57b01f77.tgz
ãã€ããªã®å
容ã解åããŠæœåºããŸãã tar -xvf asus-grouper-ktu84p-b12ce5f7.tgz tar -xvf broadcom-grouper-ktu84p-646d5a68.tgz tar -xvf elan-grouper-ktu84p-742223b3.tgz tar -xvf invensense-grouper-ktu84p-724c855a.tgz tar -xvf nvidia-grouper-ktu84p-e6d581dc.tgz tar -xvf nxp-grouper-ktu84p-27abae08.tgz tar -xvf widevine-grouper-ktu84p-57b01f77.tgz rm *.tgz ./extract-asus-grouper.sh ./extract-broadcom-grouper.sh ./extract-elan-grouper.sh ./extract-invensense-grouper.sh ./extract-nvidia-grouper.sh ./extract-nxp-grouper.sh ./extract-widevine-grouper.sh
ãŸããç§ãã¡ã¯åéããŸãïŒ mkdir nexus cd nexus make clobber ( ) . build/envsetup.sh lunch aosp_grouper-userdebug make -j4
次ã®ã³ãã³ãã䜿çšããŠã以åã®ã¢ã»ã³ããªãåé€ã§ããŸãã make clobber
ã¢ã»ã³ããªåŸãæçµã€ã¡ãŒãžã¯out / target / product / grouperãã©ã«ããŒïŒsystem.imgãrecovery.imgãramdisk.imgãuserdata.imgïŒã«é
眮ãããŸããã¢ããªã±ãŒã·ã§ã³apkãã¡ã€ã«ã¯ãout / target / product / grouper / obj / APPS / Jdts160demo_intermediates / package.apkã«ãããŸããfastbootãä»ããŠç»åãäœæããã³ã¢ããããŒãããŸããã¿ãã¬ããã®FLASHïŒããã©ã«ãã§ã¯ãboot.imgãsystem.imgãrecovery.imgãuserdata.imgãramdisk.imgïŒã«ã¢ããããŒãããå¿
èŠãããç»åãšãã³ã³ãã³ããå«ãandroid-info.txtãã¡ã€ã«ãå«ã.zipã¢ãŒã«ã€ããäœæããŸãã require board=grouper require version-bootloader=4.23
ããŒãããŒããŒã®ããã©ã«ãããŒãžã§ã³ãåãã§ãªãå Žåã¯ãããããå®æããFactoryã€ã¡ãŒãžã€ã¡ãŒãžãããŠã³ããŒãããŠãããããflash_all.shã¹ã¯ãªãããå®è¡ã§ããŸãããŸããå€æŽãå
¥åããããã®ããŒã¹ã€ã¡ãŒãžãšããŠäœ¿çšããããšãã§ããŸããboot.imgãæŽæ°ããã«ã¯ãabootimgããŒã«ãã€ã³ã¹ããŒã«ããå¿
èŠããããŸãã sudo apt-get install abootimg abootimg
abootimgã®ã³ãã³ãã§ã¯ã次ã®ãããªããŒããã©ã¡ãŒã¿ãæå®ã§ããŸãããšã³ã³ãœãŒã«ããããã§ããŸã åäœããŸããã®ã§ãããã§å°çã«ãfastbootã¢ãŒãã«ç§»åããŸãããªãã·ã§ã³ïŒ
adb rebootããŒãããŒããŒïŒã¿ãã¬ããã®é»æºããªã³ã§ãusbçµç±ã§æ¥ç¶ãããadbã«ãã£ãŠèªèšŒãããŠãã
å ŽåïŒãªãã«ãªã£ãŠããå Žåã¯ãé»æºãã¿ã³ãšé³éãã¿ã³ãæŒããªãããªã³ã«ããŸãã
fastbootã®å¯çšæ§ã確èªããŸãïŒUSBãæ¥ç¶ãããUSBãããã°ãæå¹ã«ãªã£ãŠããŸãïŒã fastboot devices
次ã«ãã³ãã³ãã®ãªã¹ããå®è¡ããŸãããã¹ãŠãåé€ããå¿
èŠã¯ãŸã£ãããªããå€æŽå¯èœãªéšåã®ã¿ãèš±å¯ãããŸãã fastboot oem unlock fastboot erase boot fastboot erase cache fastboot erase recovery fastboot erase system fastboot erase userdata fastboot -2 update image.zip
åã®æ®µèœã§äœããééã£ãŠããããšãç解ããæ¹æ³å®éãã¿ã¹ã¯ãå®äºããããã»ã¹ã§ã¯ã詳现ãæ·±ãæ£çŽã«æŽçããæéãããŸããªãããããã¯ãŒã¯ã®ç©ºãã¹ããŒã¹ã«ããå°ç³ãéãæããŸãããã¿ã¹ã¯ãéããããåŸãäœããã©ã®ããã«ãã©ãã§å®è¡ã§ãããã«ã€ããŠã®åæãšèªã¿åããç°ãªã£ãŠéå§ãããŸãããçµæã¯å°ããªãªã¹ãã§ãïŒ- OSã®å€æŽã¯ãã¢ã»ã³ããªäžã«èæ
®ãããã«ãŒãã«ãšOSæ§é ã«çŽæ¥ã§ã¯ãªããå€ãã®ãªãŒããŒã¬ã€ãæžã蟌ãããšã«ãããdevices / asus / grouper / ...ãã©ã«ããŒã§è¡ãããšããå§ãããŸããäž»ãªæ
å ±æºãšåãæ§é ããããã¯ã§ãããã©ããããŸãã¯ç¹å®ã®èŠä»¶ããããã©ããã¯å®å
šã«ã¯ããããŸããã§ããã
- audio-jack . , , - . ããªãã¡ïŒ
- uart-1 & uart-4 debug, pinmux GPIO not_used/disabled.
- Google usb-uart FTDI , 50, .
- make menuconfig uart uart`. , .
- fastboot bootloader command line . , , .
- , . system