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 25static 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 */ 35int16_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 */ 53void 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 */ 76int16_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 */ 127int16_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 */ 175int16_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 */ 200void 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 */ 213int 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 */ 228int 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 */ 248int16_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 */ 269int16_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 */ 285int16_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. */ 304int16_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