Home | History | Annotate | Download | only in akmdfs
      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