hook: add spi init hooks
[contrib/mraa.git] / src / spi / spi.c
1 /*
2  * Author: Thomas Ingleby <thomas.c.ingleby@intel.com>
3  * Copyright (c) 2014 Intel Corporation.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/ioctl.h>
28 #include <linux/spi/spidev.h>
29 #include <stdio.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32
33 #include "spi.h"
34 #include "mraa_internal.h"
35
36 #define MAX_SIZE 64
37 #define SPI_MAX_LENGTH 4096
38
39 /**
40  * A structure representing the SPI device
41  */
42 struct _spi {
43     /*@{*/
44     int devfd; /**< File descriptor to SPI Device */
45     int mode; /**< Spi mode see spidev.h */
46     int clock; /**< clock to run transactions at */
47     mraa_boolean_t lsb; /**< least significant bit mode */
48     unsigned int bpw; /**< Bits per word */
49     /*@}*/
50 };
51
52 mraa_spi_context
53 mraa_spi_init(int bus)
54 {
55     if (advance_func->spi_init_pre != NULL) {
56         if (advance_func->spi_init_pre(bus) != MRAA_SUCCESS)
57             return NULL;
58     }
59
60     mraa_spi_bus_t *spi = mraa_setup_spi(bus);
61     if(bus < 0) {
62         fprintf(stderr, "Failed. SPI platform Error\n");
63         return NULL;
64     }
65     mraa_spi_context dev = (mraa_spi_context) malloc(sizeof(struct _spi));
66     memset(dev, 0, sizeof(struct _spi));
67
68     char path[MAX_SIZE];
69     sprintf(path, "/dev/spidev%u.%u", spi->bus_id, spi->slave_s);
70
71     dev->devfd = open(path, O_RDWR);
72     if (dev->devfd < 0) {
73         fprintf(stderr, "Failed opening SPI Device. bus:%s\n", path);
74         free(dev);
75         return NULL;
76     }
77     dev->bpw = 8;
78     dev->clock = 4000000;
79     dev->lsb = 0;
80     dev->mode = 0;
81
82     if (advance_func->spi_init_post != NULL) {
83         mraa_result_t ret = advance_func->spi_init_post(dev);
84         if (ret != MRAA_SUCCESS) {
85             free(dev);
86             return NULL;
87         }
88     }
89
90     return dev;
91 }
92
93 mraa_result_t
94 mraa_spi_mode(mraa_spi_context dev, mraa_spi_mode_t mode)
95 {
96     uint8_t spi_mode = 0;
97     switch (mode) {
98         case MRAA_SPI_MODE0:
99             spi_mode = SPI_MODE_0;
100             break;
101         case MRAA_SPI_MODE1:
102             spi_mode = SPI_MODE_1;
103             break;
104         case MRAA_SPI_MODE2:
105             spi_mode = SPI_MODE_2;
106             break;
107         case MRAA_SPI_MODE3:
108             spi_mode = SPI_MODE_3;
109             break;
110         default:
111             spi_mode = SPI_MODE_0;
112             break;
113     }
114
115     if (ioctl (dev->devfd, SPI_IOC_WR_MODE, &spi_mode) < 0) {
116         fprintf(stderr, "Failed to set spi mode\n");
117         return MRAA_ERROR_INVALID_RESOURCE;
118     }
119
120     dev->mode = spi_mode;
121     return MRAA_SUCCESS;
122 }
123
124 mraa_result_t
125 mraa_spi_frequency(mraa_spi_context dev, int hz)
126 {
127     dev->clock = hz;
128     return MRAA_SUCCESS;
129 }
130
131 mraa_result_t
132 mraa_spi_lsbmode(mraa_spi_context dev, mraa_boolean_t lsb)
133 {
134     uint8_t lsb_mode = 0;
135     if (lsb == 1) {
136         lsb_mode = 1;
137     }
138     if (ioctl (dev->devfd, SPI_IOC_WR_LSB_FIRST, &lsb_mode) < 0) {
139         fprintf(stderr, "Failed to set bit order\n");
140         return MRAA_ERROR_INVALID_RESOURCE;
141     }
142     dev->lsb = lsb;
143     return MRAA_SUCCESS;
144 }
145
146 mraa_result_t
147 mraa_spi_bit_per_word(mraa_spi_context dev, unsigned int bits)
148 {
149     dev->bpw = bits;
150     return MRAA_SUCCESS;
151 }
152
153 uint8_t
154 mraa_spi_write(mraa_spi_context dev, uint8_t data)
155 {
156     struct spi_ioc_transfer msg;
157     memset(&msg, 0, sizeof(msg));
158
159     uint16_t length = 1;
160
161     uint8_t recv = 0;
162     msg.tx_buf = (unsigned long) &data;
163     msg.rx_buf = (unsigned long) &recv;
164     msg.speed_hz = dev->clock;
165     msg.bits_per_word = dev->bpw;
166     msg.delay_usecs = 0;
167     msg.len = length;
168     if (ioctl(dev->devfd, SPI_IOC_MESSAGE(1), &msg) < 0) {
169         fprintf(stderr, "Failed to perform dev transfer\n");
170         return -1;
171     }
172     return recv;
173 }
174
175 uint8_t*
176 mraa_spi_write_buf(mraa_spi_context dev, uint8_t* data, int length)
177 {
178     struct spi_ioc_transfer msg;
179     memset(&msg, 0, sizeof(msg));
180
181     uint8_t* recv = malloc(sizeof(uint8_t) * length);
182
183     msg.tx_buf = (unsigned long) data;
184     msg.rx_buf = (unsigned long) recv;
185     msg.speed_hz = dev->clock;
186     msg.bits_per_word = dev->bpw;
187     msg.delay_usecs = 0;
188     msg.len = length;
189     if (ioctl(dev->devfd, SPI_IOC_MESSAGE(1), &msg) < 0) {
190         fprintf(stderr, "Failed to perform dev transfer\n");
191         return NULL;
192     }
193     return recv;
194 }
195
196 mraa_result_t
197 mraa_spi_stop(mraa_spi_context dev)
198 {
199     close(dev->devfd);
200     free(dev);
201     return MRAA_SUCCESS;
202 }