Home | History | Annotate | Download | only in akmdfs
      1 /******************************************************************************
      2  * $Id: AK8975Driver.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 <fcntl.h>
     20 #include "AKFS_Common.h"
     21 #include "AK8975Driver.h"
     22 
     23 #define MSENSOR_NAME		"/dev/akm8975_dev"
     24 
     25 static int s_fdDev = -1;
     26 
     27 /*!
     28  Open device driver.
     29  This function opens both device drivers of magnetic sensor and acceleration
     30  sensor. Additionally, some initial hardware settings are done, such as
     31  measurement range, built-in filter function and etc.
     32  @return If this function succeeds, the return value is #AKD_SUCCESS.
     33  Otherwise the return value is #AKD_FAIL.
     34  */
     35 int16_t AKD_InitDevice(void)
     36 {
     37 	if (s_fdDev < 0) {
     38 		/* Open magnetic sensor's device driver. */
     39 		if ((s_fdDev = open(MSENSOR_NAME, O_RDWR)) < 0) {
     40 			AKMERROR_STR("open");
     41 			return AKD_FAIL;
     42 		}
     43 	}
     44 
     45 	return AKD_SUCCESS;
     46 }
     47 
     48 /*!
     49  Close device driver.
     50  This function closes both device drivers of magnetic sensor and acceleration
     51  sensor.
     52  */
     53 void AKD_DeinitDevice(void)
     54 {
     55 	if (s_fdDev >= 0) {
     56 		close(s_fdDev);
     57 		s_fdDev = -1;
     58 	}
     59 }
     60 
     61 /*!
     62  Writes data to a register of the AK8975.  When more than one byte of data is
     63  specified, the data is written in contiguous locations starting at an address
     64  specified in \a address.
     65  @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
     66  the return value is #AKD_FAIL.
     67  @param[in] address Specify the address of a register in which data is to be
     68  written.
     69  @param[in] data Specify data to write or a pointer to a data array containing
     70  the data.  When specifying more than one byte of data, specify the starting
     71  address of the array.
     72  @param[in] numberOfBytesToWrite Specify the number of bytes that make up the
     73  data to write.  When a pointer to an array is specified in data, this argument
     74  equals the number of elements of the array.
     75  */
     76 int16_t AKD_TxData(
     77 				const BYTE address,
     78 				const BYTE * data,
     79 				const uint16_t numberOfBytesToWrite)
     80 {
     81 	int i;
     82 	char buf[RWBUF_SIZE];
     83 
     84 	if (s_fdDev < 0) {
     85 		ALOGE("%s: Device file is not opened.", __FUNCTION__);
     86 		return AKD_FAIL;
     87 	}
     88 	if (numberOfBytesToWrite > (RWBUF_SIZE-2)) {
     89 		ALOGE("%s: Tx size is too large.", __FUNCTION__);
     90 		return AKD_FAIL;
     91 	}
     92 
     93 	buf[0] = numberOfBytesToWrite + 1;
     94 	buf[1] = address;
     95 
     96 	for (i = 0; i < numberOfBytesToWrite; i++) {
     97 		buf[i + 2] = data[i];
     98 	}
     99 	if (ioctl(s_fdDev, ECS_IOCTL_WRITE, buf) < 0) {
    100 		AKMERROR_STR("ioctl");
    101 		return AKD_FAIL;
    102 	} else {
    103 
    104 #if ENABLE_AKMDEBUG
    105 		AKMDATA(AKMDATA_DRV, "addr(HEX)=%02x data(HEX)=", address);
    106 		for (i = 0; i < numberOfBytesToWrite; i++) {
    107 			AKMDATA(AKMDATA_DRV, " %02x", data[i]);
    108 		}
    109 		AKMDATA(AKMDATA_DRV, "\n");
    110 #endif
    111 		return AKD_SUCCESS;
    112 	}
    113 }
    114 
    115 /*!
    116  Acquires data from a register or the EEPROM of the AK8975.
    117  @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
    118  the return value is #AKD_FAIL.
    119  @param[in] address Specify the address of a register from which data is to be
    120  read.
    121  @param[out] data Specify a pointer to a data array which the read data are
    122  stored.
    123  @param[in] numberOfBytesToRead Specify the number of bytes that make up the
    124  data to read.  When a pointer to an array is specified in data, this argument
    125  equals the number of elements of the array.
    126  */
    127 int16_t AKD_RxData(
    128 				const BYTE address,
    129 				BYTE * data,
    130 				const uint16_t numberOfBytesToRead)
    131 {
    132 	int i;
    133 	char buf[RWBUF_SIZE];
    134 
    135 	memset(data, 0, numberOfBytesToRead);
    136 
    137 	if (s_fdDev < 0) {
    138 		ALOGE("%s: Device file is not opened.", __FUNCTION__);
    139 		return AKD_FAIL;
    140 	}
    141 	if (numberOfBytesToRead > (RWBUF_SIZE-1)) {
    142 		ALOGE("%s: Rx size is too large.", __FUNCTION__);
    143 		return AKD_FAIL;
    144 	}
    145 
    146 	buf[0] = numberOfBytesToRead;
    147 	buf[1] = address;
    148 
    149 	if (ioctl(s_fdDev, ECS_IOCTL_READ, buf) < 0) {
    150 		AKMERROR_STR("ioctl");
    151 		return AKD_FAIL;
    152 	} else {
    153 		for (i = 0; i < numberOfBytesToRead; i++) {
    154 			data[i] = buf[i + 1];
    155 		}
    156 #if ENABLE_AKMDEBUG
    157 		AKMDATA(AKMDATA_DRV, "addr(HEX)=%02x len=%d data(HEX)=",
    158 				address, numberOfBytesToRead);
    159 		for (i = 0; i < numberOfBytesToRead; i++) {
    160 			AKMDATA(AKMDATA_DRV, " %02x", data[i]);
    161 		}
    162 		AKMDATA(AKMDATA_DRV, "\n");
    163 #endif
    164 		return AKD_SUCCESS;
    165 	}
    166 }
    167 
    168 /*!
    169  Acquire magnetic data from AK8975. If measurement is not done, this function
    170  waits until measurement completion.
    171  @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
    172  the return value is #AKD_FAIL.
    173  @param[out] data A magnetic data array. The size should be larger than #SENSOR_DATA_SIZE.
    174  */
    175 int16_t AKD_GetMagneticData(BYTE data[SENSOR_DATA_SIZE])
    176 {
    177 	memset(data, 0, SENSOR_DATA_SIZE);
    178 
    179 	if (s_fdDev < 0) {
    180 		ALOGE("%s: Device file is not opened.", __FUNCTION__);
    181 		return AKD_FAIL;
    182 	}
    183 
    184 	if (ioctl(s_fdDev, ECS_IOCTL_GETDATA, data) < 0) {
    185 		AKMERROR_STR("ioctl");
    186 		return AKD_FAIL;
    187 	}
    188 
    189 	AKMDATA(AKMDATA_DRV,
    190 		"bdata(HEX)= %02x %02x %02x %02x %02x %02x %02x %02x\n",
    191 		data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
    192 
    193 	return AKD_SUCCESS;
    194 }
    195 
    196 /*!
    197  Set calculated data to device driver.
    198  @param[in] buf The order of input data depends on driver's specification.
    199  */
    200 void AKD_SetYPR(const int buf[YPR_DATA_SIZE])
    201 {
    202 	if (s_fdDev < 0) {
    203 		ALOGE("%s: Device file is not opened.", __FUNCTION__);
    204 	} else {
    205 		if (ioctl(s_fdDev, ECS_IOCTL_SET_YPR, buf) < 0) {
    206 			AKMERROR_STR("ioctl");
    207 		}
    208 	}
    209 }
    210 
    211 /*!
    212  */
    213 int AKD_GetOpenStatus(int* status)
    214 {
    215 	if (s_fdDev < 0) {
    216 		ALOGE("%s: Device file is not opened.", __FUNCTION__);
    217 		return AKD_FAIL;
    218 	}
    219 	if (ioctl(s_fdDev, ECS_IOCTL_GET_OPEN_STATUS, status) < 0) {
    220 		AKMERROR_STR("ioctl");
    221 		return AKD_FAIL;
    222 	}
    223 	return AKD_SUCCESS;
    224 }
    225 
    226 /*!
    227  */
    228 int AKD_GetCloseStatus(int* status)
    229 {
    230 	if (s_fdDev < 0) {
    231 		ALOGE("%s: Device file is not opened.", __FUNCTION__);
    232 		return AKD_FAIL;
    233 	}
    234 	if (ioctl(s_fdDev, ECS_IOCTL_GET_CLOSE_STATUS, status) < 0) {
    235 		AKMERROR_STR("ioctl");
    236 		return AKD_FAIL;
    237 	}
    238 	return AKD_SUCCESS;
    239 }
    240 
    241 /*!
    242  Set AK8975 to the specific mode.
    243  @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
    244  the return value is #AKD_FAIL.
    245  @param[in] mode This value should be one of the AK8975_Mode which is defined in
    246  akm8975.h file.
    247  */
    248 int16_t AKD_SetMode(const BYTE mode)
    249 {
    250 	if (s_fdDev < 0) {
    251 		ALOGE("%s: Device file is not opened.", __FUNCTION__);
    252 		return AKD_FAIL;
    253 	}
    254 
    255 	if (ioctl(s_fdDev, ECS_IOCTL_SET_MODE, &mode) < 0) {
    256 		AKMERROR_STR("ioctl");
    257 		return AKD_FAIL;
    258 	}
    259 
    260 	return AKD_SUCCESS;
    261 }
    262 
    263 /*!
    264  Acquire delay
    265  @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
    266  the return value is #AKD_FAIL.
    267  @param[out] delay A delay in nanosecond.
    268  */
    269 int16_t AKD_GetDelay(int64_t delay[AKM_NUM_SENSORS])
    270 {
    271 	if (s_fdDev < 0) {
    272 		ALOGE("%s: Device file is not opened.\n", __FUNCTION__);
    273 		return AKD_FAIL;
    274 	}
    275 	if (ioctl(s_fdDev, ECS_IOCTL_GET_DELAY, delay) < 0) {
    276 		AKMERROR_STR("ioctl");
    277 		return AKD_FAIL;
    278 	}
    279 	return AKD_SUCCESS;
    280 }
    281 
    282 /*!
    283  Get layout information from device driver, i.e. platform data.
    284  */
    285 int16_t AKD_GetLayout(int16_t* layout)
    286 {
    287 	char tmp;
    288 
    289 	if (s_fdDev < 0) {
    290 		ALOGE("%s: Device file is not opened.", __FUNCTION__);
    291 		return AKD_FAIL;
    292 	}
    293 
    294 	if (ioctl(s_fdDev, ECS_IOCTL_GET_LAYOUT, &tmp) < 0) {
    295 		AKMERROR_STR("ioctl");
    296 		return AKD_FAIL;
    297 	}
    298 
    299 	*layout = tmp;
    300 	return AKD_SUCCESS;
    301 }
    302 
    303 /* Get acceleration data. */
    304 int16_t AKD_GetAccelerationData(int16_t data[3])
    305 {
    306 	if (s_fdDev < 0) {
    307 		ALOGE("%s: Device file is not opened.", __FUNCTION__);
    308 		return AKD_FAIL;
    309 	}
    310 	if (ioctl(s_fdDev, ECS_IOCTL_GET_ACCEL, data) < 0) {
    311 		AKMERROR_STR("ioctl");
    312 		return AKD_FAIL;
    313 	}
    314 
    315 	AKMDATA(AKMDATA_DRV, "%s: acc=%d, %d, %d\n",
    316 			__FUNCTION__, data[0], data[1], data[2]);
    317 
    318 	return AKD_SUCCESS;
    319 }
    320