2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
23 #include <sys/types.h>
26 #include "peripheral_io.h"
30 FEATURE("http://tizen.org/feature/peripheral_io.adc")
32 /* Path format for device file */
33 #define DEV_PATH_BASE(device, channel) ("/sys/bus/iio/devices/iio:device" device "/in_voltage" channel "_raw")
34 #define DEV_PATH_FMT_MAX_SIZE sizeof(DEV_PATH_BASE(MAX_d_FMT, MAX_d_FMT))
35 #define DEV_PATH_FMT DEV_PATH_BASE("%d", "%d")
37 #define ADC_BUFFER_MAX 64
40 * @brief Internal struct for adc context
42 struct _peripheral_adc_s {
46 static inline void cleanup_handlep(peripheral_adc_h *handle)
48 if (*handle != NULL) {
49 close_fd((*handle)->fd);
55 * @brief Initializes adc pin and creates adc handle.
57 int peripheral_adc_open(int device, int channel, peripheral_adc_h *adc)
59 RETVM_IF(!__is_feature_supported(), PERIPHERAL_ERROR_NOT_SUPPORTED, "ADC feature is not supported");
60 RETVM_IF(adc == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "Invalid adc handle");
61 RETVM_IF(device < 0, PERIPHERAL_ERROR_INVALID_PARAMETER, "Invalid adc device number");
62 RETVM_IF(channel < 0, PERIPHERAL_ERROR_INVALID_PARAMETER, "Invalid adc channel number");
64 __attribute__ ((cleanup(cleanup_handlep))) peripheral_adc_h handle = (peripheral_adc_h)calloc(1, sizeof *handle);
66 _E("Failed to allocate peripheral_adc_h");
67 return PERIPHERAL_ERROR_OUT_OF_MEMORY;
70 /* space for /sys/bus/iio/devices/iio:device%d/in_voltage%d_raw */
71 char path[DEV_PATH_FMT_MAX_SIZE] = {0, };
73 snprintf(path, sizeof path, DEV_PATH_FMT, device, channel);
74 handle->fd = open(path, O_RDONLY | O_CLOEXEC);
75 CHECK_ERROR(handle->fd < 0);
77 int ret = PERIPHERAL_ERROR_NONE;
78 TRY_FLOCK(ret, handle->fd, LOCK_EX | LOCK_NB, "device : %d, channel : 0x%x", device, channel);
79 CHECK_ERROR(ret != PERIPHERAL_ERROR_NONE);
84 return PERIPHERAL_ERROR_NONE;
88 * @brief Releases the adc handle.
90 int peripheral_adc_close(peripheral_adc_h adc)
92 RETVM_IF(!__is_feature_supported(), PERIPHERAL_ERROR_NOT_SUPPORTED, "ADC feature is not supported");
93 RETVM_IF(adc == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "adc handle is NULL");
95 cleanup_handlep(&adc);
97 return PERIPHERAL_ERROR_NONE;
101 * @brief Reads value of the adc.
103 int peripheral_adc_read(peripheral_adc_h adc, uint32_t *value)
105 RETVM_IF(!__is_feature_supported(), PERIPHERAL_ERROR_NOT_SUPPORTED, "ADC feature is not supported");
106 RETVM_IF(adc == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "adc handle is NULL");
107 RETVM_IF(value == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "adc read value is invalid");
110 char adc_buf[ADC_BUFFER_MAX] = {0, };
112 ret = pread(adc->fd, &adc_buf, ADC_BUFFER_MAX, 0);
113 CHECK_ERROR(ret <= 0);
115 ret = sscanf(adc_buf, "%" SCNu32, value);
117 _E("Error: unable to read adc value: %m\n");
118 return PERIPHERAL_ERROR_IO_ERROR;
121 return PERIPHERAL_ERROR_NONE;