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  */
thread_main(void * args)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  */
signal_handler(int sig)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  */
startClone(void)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  */
OptParse(int argc,char * argv[],AKFS_PATNO * layout_patno)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 
ConsoleMode(void)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 
main(int argc,char ** argv)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