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 */
AKD_InitDevice(void)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 */
AKD_DeinitDevice(void)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 */
AKD_TxData(const BYTE address,const BYTE * data,const uint16_t numberOfBytesToWrite)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 */
AKD_RxData(const BYTE address,BYTE * data,const uint16_t numberOfBytesToRead)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 */
AKD_GetMagneticData(BYTE data[SENSOR_DATA_SIZE])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 */
AKD_SetYPR(const int buf[YPR_DATA_SIZE])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 */
AKD_GetOpenStatus(int * status)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 */
AKD_GetCloseStatus(int * status)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 */
AKD_SetMode(const BYTE mode)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 */
AKD_GetDelay(int64_t delay[AKM_NUM_SENSORS])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 */
AKD_GetLayout(int16_t * layout)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. */
AKD_GetAccelerationData(int16_t data[3])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