| /****************************************************************************** |
| * $Id: main.c 580 2012-03-29 09:56:21Z yamada.rj $ |
| ****************************************************************************** |
| * |
| * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #include "AKFS_Common.h" |
| #include "AKFS_Compass.h" |
| #include "AKFS_Disp.h" |
| #include "AKFS_FileIO.h" |
| #include "AKFS_Measure.h" |
| #include "AKFS_APIs.h" |
| |
| #ifndef WIN32 |
| #include <sched.h> |
| #include <pthread.h> |
| #include <linux/input.h> |
| #endif |
| |
| #define ERROR_INITDEVICE (-1) |
| #define ERROR_OPTPARSE (-2) |
| #define ERROR_SELF_TEST (-3) |
| #define ERROR_READ_FUSE (-4) |
| #define ERROR_INIT (-5) |
| #define ERROR_GETOPEN_STAT (-6) |
| #define ERROR_STARTCLONE (-7) |
| #define ERROR_GETCLOSE_STAT (-8) |
| |
| /* Global variable. See AKFS_Common.h file. */ |
| int g_stopRequest = 0; |
| int g_opmode = 0; |
| int g_dbgzone = 0; |
| int g_mainQuit = AKD_FALSE; |
| |
| /* Static variable. */ |
| static pthread_t s_thread; /*!< Thread handle */ |
| |
| /*! |
| A thread function which is raised when measurement is started. |
| @param[in] args This parameter is not used currently. |
| */ |
| static void* thread_main(void* args) |
| { |
| AKFS_MeasureLoop(); |
| return ((void*)0); |
| } |
| |
| /*! |
| Signal handler. This should be used only in DEBUG mode. |
| @param[in] sig Event |
| */ |
| static void signal_handler(int sig) |
| { |
| if (sig == SIGINT) { |
| ALOGE("SIGINT signal"); |
| g_stopRequest = 1; |
| g_mainQuit = AKD_TRUE; |
| } |
| } |
| |
| /*! |
| Starts new thread. |
| @return If this function succeeds, the return value is 1. Otherwise, |
| the return value is 0. |
| */ |
| static int startClone(void) |
| { |
| pthread_attr_t attr; |
| |
| pthread_attr_init(&attr); |
| g_stopRequest = 0; |
| if (pthread_create(&s_thread, &attr, thread_main, NULL) == 0) { |
| return 1; |
| } else { |
| return 0; |
| } |
| } |
| |
| /*! |
| This function parse the option. |
| @retval 1 Parse succeeds. |
| @retval 0 Parse failed. |
| @param[in] argc Argument count |
| @param[in] argv Argument vector |
| @param[out] layout_patno |
| */ |
| int OptParse( |
| int argc, |
| char* argv[], |
| AKFS_PATNO* layout_patno) |
| { |
| #ifdef WIN32 |
| /* Static */ |
| #if defined(AKFS_WIN32_PAT1) |
| *layout_patno = PAT1; |
| #elif defined(AKFS_WIN32_PAT2) |
| *layout_patno = PAT2; |
| #elif defined(AKFS_WIN32_PAT3) |
| *layout_patno = PAT3; |
| #elif defined(AKFS_WIN32_PAT4) |
| *layout_patno = PAT4; |
| #elif defined(AKFS_WIN32_PAT5) |
| *layout_patno = PAT5; |
| #else |
| *layout_patno = PAT1; |
| #endif |
| g_opmode = OPMODE_CONSOLE; |
| /*g_opmode = 0;*/ |
| g_dbgzone = AKMDATA_LOOP | AKMDATA_TEST; |
| #else |
| int opt; |
| char optVal; |
| |
| *layout_patno = PAT_INVALID; |
| |
| while ((opt = getopt(argc, argv, "sm:z:")) != -1) { |
| switch(opt){ |
| case 'm': |
| optVal = (char)(optarg[0] - '0'); |
| if ((PAT1 <= optVal) && (optVal <= PAT8)) { |
| *layout_patno = (AKFS_PATNO)optVal; |
| AKMDEBUG(DBG_LEVEL2, "%s: Layout=%d\n", __FUNCTION__, optVal); |
| } |
| break; |
| case 's': |
| g_opmode |= OPMODE_CONSOLE; |
| break; |
| case 'z': |
| /* If error detected, hopefully 0 is returned. */ |
| errno = 0; |
| g_dbgzone = (int)strtol(optarg, (char**)NULL, 0); |
| AKMDEBUG(DBG_LEVEL2, "%s: Dbg Zone=%d\n", __FUNCTION__, g_dbgzone); |
| break; |
| default: |
| ALOGE("%s: Invalid argument", argv[0]); |
| return 0; |
| } |
| } |
| |
| /* If layout is not specified with argument, get parameter from driver */ |
| if (*layout_patno == PAT_INVALID) { |
| int16_t n; |
| if (AKD_GetLayout(&n) == AKM_SUCCESS) { |
| if ((PAT1 <= n) && (n <= PAT8)) { |
| *layout_patno = (AKFS_PATNO)n; |
| } |
| } |
| } |
| /* Error */ |
| if (*layout_patno == PAT_INVALID) { |
| ALOGE("No layout is specified."); |
| return 0; |
| } |
| #endif |
| |
| return 1; |
| } |
| |
| void ConsoleMode(void) |
| { |
| /*** Console Mode *********************************************/ |
| while (AKD_TRUE) { |
| /* Select operation */ |
| switch (Menu_Main()) { |
| case MODE_SelfTest: |
| AKFS_SelfTest(); |
| break; |
| case MODE_Measure: |
| /* Reset flag */ |
| g_stopRequest = 0; |
| /* Measurement routine */ |
| AKFS_MeasureLoop(); |
| break; |
| |
| case MODE_Quit: |
| return; |
| |
| default: |
| AKMDEBUG(DBG_LEVEL0, "Unknown operation mode.\n"); |
| break; |
| } |
| } |
| } |
| |
| int main(int argc, char **argv) |
| { |
| int retValue = 0; |
| AKFS_PATNO pat; |
| uint8 regs[3]; |
| |
| /* Show the version info of this software. */ |
| Disp_StartMessage(); |
| |
| #if ENABLE_AKMDEBUG |
| /* Register signal handler */ |
| signal(SIGINT, signal_handler); |
| #endif |
| |
| /* Open device driver */ |
| if(AKD_InitDevice() != AKD_SUCCESS) { |
| retValue = ERROR_INITDEVICE; |
| goto MAIN_QUIT; |
| } |
| |
| /* Parse command-line options */ |
| /* This function calls device driver function to get layout */ |
| if (OptParse(argc, argv, &pat) == 0) { |
| retValue = ERROR_OPTPARSE; |
| goto MAIN_QUIT; |
| } |
| |
| /* Self Test */ |
| if (g_opmode & OPMODE_FST){ |
| if (AKFS_SelfTest() != AKD_SUCCESS) { |
| retValue = ERROR_SELF_TEST; |
| goto MAIN_QUIT; |
| } |
| } |
| |
| /* OK, then start */ |
| if (AKFS_ReadAK8975FUSEROM(regs) != AKM_SUCCESS) { |
| retValue = ERROR_READ_FUSE; |
| goto MAIN_QUIT; |
| } |
| |
| /* Initialize library. */ |
| if (AKFS_Init(pat, regs) != AKM_SUCCESS) { |
| retValue = ERROR_INIT; |
| goto MAIN_QUIT; |
| } |
| |
| /* Start console mode */ |
| if (g_opmode & OPMODE_CONSOLE) { |
| ConsoleMode(); |
| goto MAIN_QUIT; |
| } |
| |
| /*** Start Daemon ********************************************/ |
| while (g_mainQuit == AKD_FALSE) { |
| int st = 0; |
| /* Wait until device driver is opened. */ |
| if (AKD_GetOpenStatus(&st) != AKD_SUCCESS) { |
| retValue = ERROR_GETOPEN_STAT; |
| goto MAIN_QUIT; |
| } |
| if (st == 0) { |
| ALOGI("Suspended."); |
| } else { |
| ALOGI("Compass Opened."); |
| /* Reset flag */ |
| g_stopRequest = 0; |
| /* Start measurement thread. */ |
| if (startClone() == 0) { |
| retValue = ERROR_STARTCLONE; |
| goto MAIN_QUIT; |
| } |
| |
| /* Wait until device driver is closed. */ |
| if (AKD_GetCloseStatus(&st) != AKD_SUCCESS) { |
| retValue = ERROR_GETCLOSE_STAT; |
| g_mainQuit = AKD_TRUE; |
| } |
| /* Wait thread completion. */ |
| g_stopRequest = 1; |
| pthread_join(s_thread, NULL); |
| ALOGI("Compass Closed."); |
| } |
| } |
| |
| MAIN_QUIT: |
| |
| /* Release library */ |
| AKFS_Release(); |
| /* Close device driver. */ |
| AKD_DeinitDevice(); |
| /* Show the last message. */ |
| Disp_EndMessage(retValue); |
| |
| return retValue; |
| } |
| |
| |