diff options
Diffstat (limited to 'libsensors/akmdfs/AK8975Driver.c')
-rw-r--r-- | libsensors/akmdfs/AK8975Driver.c | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/libsensors/akmdfs/AK8975Driver.c b/libsensors/akmdfs/AK8975Driver.c new file mode 100644 index 0000000..003c8d2 --- /dev/null +++ b/libsensors/akmdfs/AK8975Driver.c @@ -0,0 +1,318 @@ +/****************************************************************************** + * + * 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 <fcntl.h> +#include "AKFS_Common.h" +#include "AK8975Driver.h" + +#define MSENSOR_NAME "/dev/akm8975_dev" + +static int s_fdDev = -1; + +/*! + Open device driver. + This function opens both device drivers of magnetic sensor and acceleration + sensor. Additionally, some initial hardware settings are done, such as + measurement range, built-in filter function and etc. + @return If this function succeeds, the return value is #AKD_SUCCESS. + Otherwise the return value is #AKD_FAIL. + */ +int16_t AKD_InitDevice(void) +{ + if (s_fdDev < 0) { + /* Open magnetic sensor's device driver. */ + if ((s_fdDev = open(MSENSOR_NAME, O_RDWR)) < 0) { + AKMERROR_STR("open"); + return AKD_FAIL; + } + } + + return AKD_SUCCESS; +} + +/*! + Close device driver. + This function closes both device drivers of magnetic sensor and acceleration + sensor. + */ +void AKD_DeinitDevice(void) +{ + if (s_fdDev >= 0) { + close(s_fdDev); + s_fdDev = -1; + } +} + +/*! + Writes data to a register of the AK8975. When more than one byte of data is + specified, the data is written in contiguous locations starting at an address + specified in \a address. + @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise + the return value is #AKD_FAIL. + @param[in] address Specify the address of a register in which data is to be + written. + @param[in] data Specify data to write or a pointer to a data array containing + the data. When specifying more than one byte of data, specify the starting + address of the array. + @param[in] numberOfBytesToWrite Specify the number of bytes that make up the + data to write. When a pointer to an array is specified in data, this argument + equals the number of elements of the array. + */ +int16_t AKD_TxData( + const BYTE address, + const BYTE * data, + const uint16_t numberOfBytesToWrite) +{ + int i; + char buf[RWBUF_SIZE]; + + if (s_fdDev < 0) { + ALOGE("%s: Device file is not opened.", __FUNCTION__); + return AKD_FAIL; + } + if (numberOfBytesToWrite > (RWBUF_SIZE-2)) { + ALOGE("%s: Tx size is too large.", __FUNCTION__); + return AKD_FAIL; + } + + buf[0] = numberOfBytesToWrite + 1; + buf[1] = address; + + for (i = 0; i < numberOfBytesToWrite; i++) { + buf[i + 2] = data[i]; + } + if (ioctl(s_fdDev, ECS_IOCTL_WRITE, buf) < 0) { + AKMERROR_STR("ioctl"); + return AKD_FAIL; + } else { + +#if ENABLE_AKMDEBUG + AKMDATA(AKMDATA_DRV, "addr(HEX)=%02x data(HEX)=", address); + for (i = 0; i < numberOfBytesToWrite; i++) { + AKMDATA(AKMDATA_DRV, " %02x", data[i]); + } + AKMDATA(AKMDATA_DRV, "\n"); +#endif + return AKD_SUCCESS; + } +} + +/*! + Acquires data from a register or the EEPROM of the AK8975. + @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise + the return value is #AKD_FAIL. + @param[in] address Specify the address of a register from which data is to be + read. + @param[out] data Specify a pointer to a data array which the read data are + stored. + @param[in] numberOfBytesToRead Specify the number of bytes that make up the + data to read. When a pointer to an array is specified in data, this argument + equals the number of elements of the array. + */ +int16_t AKD_RxData( + const BYTE address, + BYTE * data, + const uint16_t numberOfBytesToRead) +{ + int i; + char buf[RWBUF_SIZE]; + + memset(data, 0, numberOfBytesToRead); + + if (s_fdDev < 0) { + ALOGE("%s: Device file is not opened.", __FUNCTION__); + return AKD_FAIL; + } + if (numberOfBytesToRead > (RWBUF_SIZE-1)) { + ALOGE("%s: Rx size is too large.", __FUNCTION__); + return AKD_FAIL; + } + + buf[0] = numberOfBytesToRead; + buf[1] = address; + + if (ioctl(s_fdDev, ECS_IOCTL_READ, buf) < 0) { + AKMERROR_STR("ioctl"); + return AKD_FAIL; + } else { + for (i = 0; i < numberOfBytesToRead; i++) { + data[i] = buf[i + 1]; + } +#if ENABLE_AKMDEBUG + AKMDATA(AKMDATA_DRV, "addr(HEX)=%02x len=%d data(HEX)=", + address, numberOfBytesToRead); + for (i = 0; i < numberOfBytesToRead; i++) { + AKMDATA(AKMDATA_DRV, " %02x", data[i]); + } + AKMDATA(AKMDATA_DRV, "\n"); +#endif + return AKD_SUCCESS; + } +} + +/*! + Acquire magnetic data from AK8975. If measurement is not done, this function + waits until measurement completion. + @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise + the return value is #AKD_FAIL. + @param[out] data A magnetic data array. The size should be larger than #SENSOR_DATA_SIZE. + */ +int16_t AKD_GetMagneticData(BYTE data[SENSOR_DATA_SIZE]) +{ + memset(data, 0, SENSOR_DATA_SIZE); + + if (s_fdDev < 0) { + ALOGE("%s: Device file is not opened.", __FUNCTION__); + return AKD_FAIL; + } + + if (ioctl(s_fdDev, ECS_IOCTL_GETDATA, data) < 0) { + AKMERROR_STR("ioctl"); + return AKD_FAIL; + } + + AKMDATA(AKMDATA_DRV, + "bdata(HEX)= %02x %02x %02x %02x %02x %02x %02x %02x\n", + data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]); + + return AKD_SUCCESS; +} + +/*! + Set calculated data to device driver. + @param[in] buf The order of input data depends on driver's specification. + */ +void AKD_SetYPR(const int buf[YPR_DATA_SIZE]) +{ + if (s_fdDev < 0) { + ALOGE("%s: Device file is not opened.", __FUNCTION__); + } else { + if (ioctl(s_fdDev, ECS_IOCTL_SET_YPR, buf) < 0) { + AKMERROR_STR("ioctl"); + } + } +} + +/*! + */ +int AKD_GetOpenStatus(int* status) +{ + if (s_fdDev < 0) { + ALOGE("%s: Device file is not opened.", __FUNCTION__); + return AKD_FAIL; + } + if (ioctl(s_fdDev, ECS_IOCTL_GET_OPEN_STATUS, status) < 0) { + AKMERROR_STR("ioctl"); + return AKD_FAIL; + } + return AKD_SUCCESS; +} + +/*! + */ +int AKD_GetCloseStatus(int* status) +{ + if (s_fdDev < 0) { + ALOGE("%s: Device file is not opened.", __FUNCTION__); + return AKD_FAIL; + } + if (ioctl(s_fdDev, ECS_IOCTL_GET_CLOSE_STATUS, status) < 0) { + AKMERROR_STR("ioctl"); + return AKD_FAIL; + } + return AKD_SUCCESS; +} + +/*! + Set AK8975 to the specific mode. + @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise + the return value is #AKD_FAIL. + @param[in] mode This value should be one of the AK8975_Mode which is defined in + akm8975.h file. + */ +int16_t AKD_SetMode(const BYTE mode) +{ + if (s_fdDev < 0) { + ALOGE("%s: Device file is not opened.", __FUNCTION__); + return AKD_FAIL; + } + + if (ioctl(s_fdDev, ECS_IOCTL_SET_MODE, &mode) < 0) { + AKMERROR_STR("ioctl"); + return AKD_FAIL; + } + + return AKD_SUCCESS; +} + +/*! + Acquire delay + @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise + the return value is #AKD_FAIL. + @param[out] delay A delay in nanosecond. + */ +int16_t AKD_GetDelay(int64_t delay[AKM_NUM_SENSORS]) +{ + if (s_fdDev < 0) { + ALOGE("%s: Device file is not opened.\n", __FUNCTION__); + return AKD_FAIL; + } + if (ioctl(s_fdDev, ECS_IOCTL_GET_DELAY, delay) < 0) { + AKMERROR_STR("ioctl"); + return AKD_FAIL; + } + return AKD_SUCCESS; +} + +/*! + Get layout information from device driver, i.e. platform data. + */ +int16_t AKD_GetLayout(int16_t* layout) +{ + char tmp; + + if (s_fdDev < 0) { + ALOGE("%s: Device file is not opened.", __FUNCTION__); + return AKD_FAIL; + } + + if (ioctl(s_fdDev, ECS_IOCTL_GET_LAYOUT, &tmp) < 0) { + AKMERROR_STR("ioctl"); + return AKD_FAIL; + } + + *layout = tmp; + return AKD_SUCCESS; +} + +/* Get acceleration data. */ +int16_t AKD_GetAccelerationData(int16_t data[3]) +{ + if (s_fdDev < 0) { + ALOGE("%s: Device file is not opened.", __FUNCTION__); + return AKD_FAIL; + } + if (ioctl(s_fdDev, ECS_IOCTL_GET_ACCEL, data) < 0) { + AKMERROR_STR("ioctl"); + return AKD_FAIL; + } + + AKMDATA(AKMDATA_DRV, "%s: acc=%d, %d, %d\n", + __FUNCTION__, data[0], data[1], data[2]); + + return AKD_SUCCESS; +} |