b7d3ef0b962fb5314e4ae6a1245b9211d1bbe219
[platform/upstream/iotjs.git] / tools / src / platform / iotjs_module_spi-linux-general.inl.h
1 /* Copyright 2016-present Samsung Electronics Co., Ltd. and other contributors
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #ifndef IOTJS_MODULE_SPI_LINUX_GENERAL_INL_H
17 #define IOTJS_MODULE_SPI_LINUX_GENERAL_INL_H
18
19
20 #include <uv.h>
21 #include <linux/spi/spidev.h>
22 #include <sys/ioctl.h>
23
24 #include "iotjs_def.h"
25 #include "iotjs_systemio-linux.h"
26 #include "module/iotjs_module_buffer.h"
27 #include "module/iotjs_module_spi.h"
28
29 #define ADC_DEVICE_PATH_FORMAT "/dev/spidev%d.%d"
30 #define ADC_DEVICE_PATH_BUFFER_SIZE 16
31
32
33 static bool iotjs_spi_set_configuration(iotjs_spi_t* spi) {
34   IOTJS_VALIDATED_STRUCT_METHOD(iotjs_spi_t, spi);
35
36   int fd = _this->device_fd;
37   if (fd < 0) {
38     return false;
39   }
40
41   uint8_t data;
42
43   switch (_this->mode) {
44     case kSpiMode_0:
45       data = SPI_MODE_0;
46       break;
47     case kSpiMode_1:
48       data = SPI_MODE_1;
49       break;
50     case kSpiMode_2:
51       data = SPI_MODE_2;
52       break;
53     case kSpiMode_3:
54       data = SPI_MODE_3;
55       break;
56     default:
57       data = SPI_MODE_0;
58   }
59   if (_this->loopback) {
60     data |= SPI_LOOP;
61   }
62
63   if (_this->chip_select == kSpiCsHigh) {
64     data |= SPI_CS_HIGH;
65   }
66
67   if (ioctl(fd, SPI_IOC_WR_MODE, &_this->mode) < 0) {
68     return false;
69   }
70
71
72   if (_this->bit_order == kSpiOrderLsb) {
73     data = 1;
74     if (ioctl(fd, SPI_IOC_WR_LSB_FIRST, &data) < 0) {
75       return false;
76     }
77   }
78
79   if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &_this->bits_per_word) < 0) {
80     return false;
81   }
82
83   if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &_this->max_speed) < 0) {
84     return false;
85   }
86
87   DDLOG(
88       "SPI Options \n mode: %d\n chipSelect: %d\n bitOrder: %d\n "
89       "maxSpeed: %d\n bitPerWord: %d\n loopback: %d",
90       _this->mode, _this->chip_select, _this->bit_order, _this->max_speed,
91       _this->bits_per_word, _this->loopback);
92
93   return true;
94 }
95
96
97 bool iotjs_spi_transfer(iotjs_spi_t* spi) {
98   IOTJS_VALIDATED_STRUCT_METHOD(iotjs_spi_t, spi);
99
100   struct spi_ioc_transfer data = {.tx_buf = (unsigned long)_this->tx_buf_data,
101                                   .rx_buf = (unsigned long)_this->rx_buf_data,
102                                   .len = _this->buf_len,
103                                   .speed_hz = _this->max_speed,
104                                   .bits_per_word = _this->bits_per_word,
105                                   .delay_usecs = 0 };
106
107   // Transfer data
108   int err = ioctl(_this->device_fd, SPI_IOC_MESSAGE(1), &data);
109   if (err < 1) {
110     DDLOG("%s - transfer failed: %d", __func__, err);
111     return false;
112   }
113
114   return true;
115 }
116
117
118 bool iotjs_spi_close(iotjs_spi_t* spi) {
119   IOTJS_VALIDATED_STRUCT_METHOD(iotjs_spi_t, spi);
120
121   if (_this->device_fd >= 0) {
122     const iotjs_environment_t* env = iotjs_environment_get();
123     uv_loop_t* loop = iotjs_environment_loop(env);
124     uv_fs_t fs_close_req;
125
126     int err = uv_fs_close(loop, &fs_close_req, _this->device_fd, NULL);
127     uv_fs_req_cleanup(&fs_close_req);
128     if (err < 0) {
129       DDLOG("%s - close failed: %d", __func__, err);
130       return false;
131     }
132     _this->device_fd = -1;
133   }
134
135   return true;
136 }
137
138
139 void iotjs_spi_open_worker(uv_work_t* work_req) {
140   SPI_WORKER_INIT;
141   IOTJS_VALIDATED_STRUCT_METHOD(iotjs_spi_t, spi);
142
143   const char* device_path = iotjs_string_data(&_this->device);
144   if (iotjs_systemio_check_path(device_path)) {
145     // Open file
146     const iotjs_environment_t* env = iotjs_environment_get();
147     uv_loop_t* loop = iotjs_environment_loop(env);
148
149     uv_fs_t open_req;
150     int result = uv_fs_open(loop, &open_req, device_path, O_RDONLY, 0666, NULL);
151     uv_fs_req_cleanup(&open_req);
152     if (result < 0) {
153       req_data->result = false;
154     }
155     _this->device_fd = open_req.result;
156
157     // Set options
158     if (!iotjs_spi_set_configuration(spi)) {
159       req_data->result = false;
160       return;
161     }
162     req_data->result = true;
163   } else {
164     req_data->result = false;
165   }
166 }
167
168
169 #endif /* IOTJS_MODULE_SPI_LINUX_GENERAL_INL_H */