1296d9f0e52240e20c1f87509b4dc07cbfa884cb
[platform/core/api/peripheral-io.git] / src / interface / peripheral_interface_spi.c
1 /*
2  * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <sys/ioctl.h>
24 #include <linux/spi/spidev.h>
25
26 #include "peripheral_interface_spi.h"
27 #include "peripheral_common.h"
28 #include "peripheral_internal.h"
29
30 #define SYSFS_SPI_DIR "/dev/spidev"
31 #define SYSFS_SPI_BUFSIZ "/sys/module/spidev/parameters/bufsiz"
32 #define SPI_BUFFER_MAX 64
33 #define MAX_ERR_LEN 255
34
35 int peripheral_interface_spi_close(peripheral_spi_h spi)
36 {
37         int status;
38
39         _D("fd : %d", spi->fd);
40         RETVM_IF(spi->fd < 0, -EINVAL, "Invalid fd");
41
42         status = close(spi->fd);
43         if (status < 0) {
44                 char errmsg[MAX_ERR_LEN];
45                 strerror_r(errno, errmsg, MAX_ERR_LEN);
46                 _E("Failed to close fd : %d", spi->fd);
47                 return -EIO;
48         }
49
50         return 0;
51 }
52
53 int peripheral_interface_spi_set_mode(peripheral_spi_h spi, unsigned char mode)
54 {
55         int status;
56
57         _D("fd : %d, mode : %d", spi->fd, mode);
58         RETVM_IF(spi->fd < 0, -EINVAL, "Invalid fd");
59
60         status = ioctl(spi->fd, SPI_IOC_WR_MODE, &mode);
61         if (status < 0) {
62                 char errmsg[MAX_ERR_LEN];
63                 strerror_r(errno, errmsg, MAX_ERR_LEN);
64                 _E("Failed to set mode(%d) : %s", mode, errmsg);
65                 return -EIO;
66         }
67
68         return 0;
69 }
70
71 int peripheral_interface_spi_set_bit_order(peripheral_spi_h spi, unsigned char lsb)
72 {
73         int status;
74
75         _D("fd : %d, lsb : %d", spi->fd, lsb);
76         RETVM_IF(spi->fd < 0, -EINVAL, "Invalid fd");
77
78         status = ioctl(spi->fd, SPI_IOC_WR_LSB_FIRST, &lsb);
79         if (status < 0) {
80                 char errmsg[MAX_ERR_LEN];
81                 strerror_r(errno, errmsg, MAX_ERR_LEN);
82                 _E("Failed to set lsb first(%d), fd : %d, errmsg : %s", lsb, spi->fd, errmsg);
83                 return -EIO;
84         }
85
86         return 0;
87 }
88
89 int peripheral_interface_spi_set_bits_per_word(peripheral_spi_h spi, unsigned char bits)
90 {
91         int status;
92
93         _D("fd : %d, bits : %d", spi->fd, bits);
94         RETVM_IF(spi->fd < 0, -EINVAL, "Invalid fd");
95
96         status = ioctl(spi->fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
97         if (status < 0) {
98                 char errmsg[MAX_ERR_LEN];
99                 strerror_r(errno, errmsg, MAX_ERR_LEN);
100                 _E("Failed to set bits(%d), fd : %d, errmsg : %s", bits, spi->fd, errmsg);
101                 return -EIO;
102         }
103
104         return 0;
105 }
106
107 int peripheral_interface_spi_set_frequency(peripheral_spi_h spi, unsigned int freq)
108 {
109         int status;
110
111         _D("fd : %d, freq : %d", spi->fd, freq);
112         RETVM_IF(spi->fd < 0, -EINVAL, "Invalid fd");
113
114         status = ioctl(spi->fd, SPI_IOC_WR_MAX_SPEED_HZ, &freq);
115         if (status < 0) {
116                 char errmsg[MAX_ERR_LEN];
117                 strerror_r(errno, errmsg, MAX_ERR_LEN);
118                 _E("Failed to set frequency(%d), fd : %d, errmsg : %s", freq, spi->fd, errmsg);
119                 return -EIO;
120         }
121
122         return 0;
123 }
124
125 int peripheral_interface_spi_read(peripheral_spi_h spi, unsigned char *rxbuf, int length)
126 {
127         int status;
128         struct spi_ioc_transfer xfer;
129
130         RETVM_IF(spi->fd < 0, -EINVAL, "Invalid fd : %d", spi->fd);
131
132         memset(&xfer, 0, sizeof(struct spi_ioc_transfer));
133         xfer.rx_buf = (unsigned long)rxbuf;
134         xfer.len = length;
135
136         status = ioctl(spi->fd, SPI_IOC_MESSAGE(1), &xfer);
137         if (status < 0) {
138                 char errmsg[MAX_ERR_LEN];
139                 strerror_r(errno, errmsg, MAX_ERR_LEN);
140                 _E("Failed to read data, fd : %d, length : %d, errmsg : %s", spi->fd, length, errmsg);
141                 return -EIO;
142         }
143
144         return 0;
145 }
146
147 int peripheral_interface_spi_write(peripheral_spi_h spi, unsigned char *txbuf, int length)
148 {
149         int status;
150         struct spi_ioc_transfer xfer;
151
152         RETVM_IF(spi->fd < 0, -EINVAL, "Invalid fd : %d", spi->fd);
153
154         memset(&xfer, 0, sizeof(struct spi_ioc_transfer));
155         xfer.tx_buf = (unsigned long)txbuf;
156         xfer.len = length;
157
158         status = ioctl(spi->fd, SPI_IOC_MESSAGE(1), &xfer);
159         if (status < 0) {
160                 char errmsg[MAX_ERR_LEN];
161                 strerror_r(errno, errmsg, MAX_ERR_LEN);
162                 _E("Failed to write data(%d) : %s", length, errmsg);
163                 return -EIO;
164         }
165
166         return 0;
167 }
168
169 int peripheral_interface_spi_transfer(peripheral_spi_h spi, unsigned char *txbuf, unsigned char *rxbuf, int length)
170 {
171         int status;
172         struct spi_ioc_transfer xfer;
173
174         RETVM_IF(spi->fd < 0, -EINVAL, "Invalid fd : %d", spi->fd);
175
176         if (!txbuf || !rxbuf || length < 0) return -EINVAL;
177
178         memset(&xfer, 0, sizeof(xfer));
179         xfer.tx_buf = (unsigned long)txbuf;
180         xfer.rx_buf = (unsigned long)rxbuf;
181         xfer.len = length;
182
183         status = ioctl(spi->fd, SPI_IOC_MESSAGE(1), &xfer);
184         if (status < 0) {
185                 char errmsg[MAX_ERR_LEN];
186                 strerror_r(errno, errmsg, MAX_ERR_LEN);
187                 _E("Failed to exchange data(%d) : %s", length, errmsg);
188                 return -EIO;
189         }
190
191         return 0;
192 }