294 lines
6.5 KiB
C
294 lines
6.5 KiB
C
/******************************************************************************
|
|
* $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;
|
|
}
|
|
|
|
|