1 /****************************************************************************** 2 * $Id: main.c 580 2012-03-29 09:56:21Z yamada.rj $ 3 ****************************************************************************** 4 * 5 * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19 #include "AKFS_Common.h" 20 #include "AKFS_Compass.h" 21 #include "AKFS_Disp.h" 22 #include "AKFS_FileIO.h" 23 #include "AKFS_Measure.h" 24 #include "AKFS_APIs.h" 25 26 #ifndef WIN32 27 #include <sched.h> 28 #include <pthread.h> 29 #include <linux/input.h> 30 #endif 31 32 #define ERROR_INITDEVICE (-1) 33 #define ERROR_OPTPARSE (-2) 34 #define ERROR_SELF_TEST (-3) 35 #define ERROR_READ_FUSE (-4) 36 #define ERROR_INIT (-5) 37 #define ERROR_GETOPEN_STAT (-6) 38 #define ERROR_STARTCLONE (-7) 39 #define ERROR_GETCLOSE_STAT (-8) 40 41 /* Global variable. See AKFS_Common.h file. */ 42 int g_stopRequest = 0; 43 int g_opmode = 0; 44 int g_dbgzone = 0; 45 int g_mainQuit = AKD_FALSE; 46 47 /* Static variable. */ 48 static pthread_t s_thread; /*!< Thread handle */ 49 50 /*! 51 A thread function which is raised when measurement is started. 52 @param[in] args This parameter is not used currently. 53 */ 54 static void* thread_main(void* args) 55 { 56 AKFS_MeasureLoop(); 57 return ((void*)0); 58 } 59 60 /*! 61 Signal handler. This should be used only in DEBUG mode. 62 @param[in] sig Event 63 */ 64 static void signal_handler(int sig) 65 { 66 if (sig == SIGINT) { 67 ALOGE("SIGINT signal"); 68 g_stopRequest = 1; 69 g_mainQuit = AKD_TRUE; 70 } 71 } 72 73 /*! 74 Starts new thread. 75 @return If this function succeeds, the return value is 1. Otherwise, 76 the return value is 0. 77 */ 78 static int startClone(void) 79 { 80 pthread_attr_t attr; 81 82 pthread_attr_init(&attr); 83 g_stopRequest = 0; 84 if (pthread_create(&s_thread, &attr, thread_main, NULL) == 0) { 85 return 1; 86 } else { 87 return 0; 88 } 89 } 90 91 /*! 92 This function parse the option. 93 @retval 1 Parse succeeds. 94 @retval 0 Parse failed. 95 @param[in] argc Argument count 96 @param[in] argv Argument vector 97 @param[out] layout_patno 98 */ 99 int OptParse( 100 int argc, 101 char* argv[], 102 AKFS_PATNO* layout_patno) 103 { 104 #ifdef WIN32 105 /* Static */ 106 #if defined(AKFS_WIN32_PAT1) 107 *layout_patno = PAT1; 108 #elif defined(AKFS_WIN32_PAT2) 109 *layout_patno = PAT2; 110 #elif defined(AKFS_WIN32_PAT3) 111 *layout_patno = PAT3; 112 #elif defined(AKFS_WIN32_PAT4) 113 *layout_patno = PAT4; 114 #elif defined(AKFS_WIN32_PAT5) 115 *layout_patno = PAT5; 116 #else 117 *layout_patno = PAT1; 118 #endif 119 g_opmode = OPMODE_CONSOLE; 120 /*g_opmode = 0;*/ 121 g_dbgzone = AKMDATA_LOOP | AKMDATA_TEST; 122 #else 123 int opt; 124 char optVal; 125 126 *layout_patno = PAT_INVALID; 127 128 while ((opt = getopt(argc, argv, "sm:z:")) != -1) { 129 switch(opt){ 130 case 'm': 131 optVal = (char)(optarg[0] - '0'); 132 if ((PAT1 <= optVal) && (optVal <= PAT8)) { 133 *layout_patno = (AKFS_PATNO)optVal; 134 AKMDEBUG(DBG_LEVEL2, "%s: Layout=%d\n", __FUNCTION__, optVal); 135 } 136 break; 137 case 's': 138 g_opmode |= OPMODE_CONSOLE; 139 break; 140 case 'z': 141 /* If error detected, hopefully 0 is returned. */ 142 errno = 0; 143 g_dbgzone = (int)strtol(optarg, (char**)NULL, 0); 144 AKMDEBUG(DBG_LEVEL2, "%s: Dbg Zone=%d\n", __FUNCTION__, g_dbgzone); 145 break; 146 default: 147 ALOGE("%s: Invalid argument", argv[0]); 148 return 0; 149 } 150 } 151 152 /* If layout is not specified with argument, get parameter from driver */ 153 if (*layout_patno == PAT_INVALID) { 154 int16_t n; 155 if (AKD_GetLayout(&n) == AKM_SUCCESS) { 156 if ((PAT1 <= n) && (n <= PAT8)) { 157 *layout_patno = (AKFS_PATNO)n; 158 } 159 } 160 } 161 /* Error */ 162 if (*layout_patno == PAT_INVALID) { 163 ALOGE("No layout is specified."); 164 return 0; 165 } 166 #endif 167 168 return 1; 169 } 170 171 void ConsoleMode(void) 172 { 173 /*** Console Mode *********************************************/ 174 while (AKD_TRUE) { 175 /* Select operation */ 176 switch (Menu_Main()) { 177 case MODE_SelfTest: 178 AKFS_SelfTest(); 179 break; 180 case MODE_Measure: 181 /* Reset flag */ 182 g_stopRequest = 0; 183 /* Measurement routine */ 184 AKFS_MeasureLoop(); 185 break; 186 187 case MODE_Quit: 188 return; 189 190 default: 191 AKMDEBUG(DBG_LEVEL0, "Unknown operation mode.\n"); 192 break; 193 } 194 } 195 } 196 197 int main(int argc, char **argv) 198 { 199 int retValue = 0; 200 AKFS_PATNO pat; 201 uint8 regs[3]; 202 203 /* Show the version info of this software. */ 204 Disp_StartMessage(); 205 206 #if ENABLE_AKMDEBUG 207 /* Register signal handler */ 208 signal(SIGINT, signal_handler); 209 #endif 210 211 /* Open device driver */ 212 if(AKD_InitDevice() != AKD_SUCCESS) { 213 retValue = ERROR_INITDEVICE; 214 goto MAIN_QUIT; 215 } 216 217 /* Parse command-line options */ 218 /* This function calls device driver function to get layout */ 219 if (OptParse(argc, argv, &pat) == 0) { 220 retValue = ERROR_OPTPARSE; 221 goto MAIN_QUIT; 222 } 223 224 /* Self Test */ 225 if (g_opmode & OPMODE_FST){ 226 if (AKFS_SelfTest() != AKD_SUCCESS) { 227 retValue = ERROR_SELF_TEST; 228 goto MAIN_QUIT; 229 } 230 } 231 232 /* OK, then start */ 233 if (AKFS_ReadAK8975FUSEROM(regs) != AKM_SUCCESS) { 234 retValue = ERROR_READ_FUSE; 235 goto MAIN_QUIT; 236 } 237 238 /* Initialize library. */ 239 if (AKFS_Init(pat, regs) != AKM_SUCCESS) { 240 retValue = ERROR_INIT; 241 goto MAIN_QUIT; 242 } 243 244 /* Start console mode */ 245 if (g_opmode & OPMODE_CONSOLE) { 246 ConsoleMode(); 247 goto MAIN_QUIT; 248 } 249 250 /*** Start Daemon ********************************************/ 251 while (g_mainQuit == AKD_FALSE) { 252 int st = 0; 253 /* Wait until device driver is opened. */ 254 if (AKD_GetOpenStatus(&st) != AKD_SUCCESS) { 255 retValue = ERROR_GETOPEN_STAT; 256 goto MAIN_QUIT; 257 } 258 if (st == 0) { 259 ALOGI("Suspended."); 260 } else { 261 ALOGI("Compass Opened."); 262 /* Reset flag */ 263 g_stopRequest = 0; 264 /* Start measurement thread. */ 265 if (startClone() == 0) { 266 retValue = ERROR_STARTCLONE; 267 goto MAIN_QUIT; 268 } 269 270 /* Wait until device driver is closed. */ 271 if (AKD_GetCloseStatus(&st) != AKD_SUCCESS) { 272 retValue = ERROR_GETCLOSE_STAT; 273 g_mainQuit = AKD_TRUE; 274 } 275 /* Wait thread completion. */ 276 g_stopRequest = 1; 277 pthread_join(s_thread, NULL); 278 ALOGI("Compass Closed."); 279 } 280 } 281 282 MAIN_QUIT: 283 284 /* Release library */ 285 AKFS_Release(); 286 /* Close device driver. */ 287 AKD_DeinitDevice(); 288 /* Show the last message. */ 289 Disp_EndMessage(retValue); 290 291 return retValue; 292 } 293 294 295