Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
SPI.cxx
Go to the documentation of this file.
1
34#ifndef _DEFAULT_SOURCE
35#define _DEFAULT_SOURCE
36#endif
37
38#include <cstdint>
39#include <fcntl.h>
40#include "Devtab.hxx"
41#include "SPI.hxx"
42
48__attribute__((optimize("-O3")))
49int SPI::transfer_messages(struct spi_ioc_transfer *msgs, int num)
50{
51 //HASSERT(num > 0);
52
53 int count = 0;
54 int result;
55
56 lock_.lock();
57 bus_lock();
58 for (int i = 0; i < num; ++i, ++msgs)
59 {
60 count += msgs->len;
61 csAssert();
62 result = transfer(msgs);
63 if (UNLIKELY(result < 0))
64 {
65 /* something bad happened, reset the bus and bail */
66 csDeassert();
67 bus_unlock();
68 lock_.unlock();
69 return result;
70 }
71 if (msgs->cs_change)
72 {
73 if (UNLIKELY(msgs->delay_usec))
74 {
75 usleep(msgs->delay_usec);
76 }
77 csDeassert();
78 }
79 }
80 bus_unlock();
81 lock_.unlock();
82
83 return count;
84}
85
92__attribute__((optimize("-O3")))
93ssize_t SPI::read(File *file, void *buf, size_t count)
94{
95 int result;
96
97 if ((file->flags & O_ACCMODE) == O_WRONLY)
98 {
99 return -EBADF;
100 }
101
102 struct spi_ioc_transfer msg;
103 msg.tx_buf = 0;
104 msg.rx_buf = (uint64_t)buf;
105 msg.len = count;
106 msg.speed_hz = speedHz;
107 msg.delay_usec = 0;
108 msg.bits_per_word = bitsPerWord;
109 msg.cs_change = true;
110
111 lock_.lock();
112 bus_lock();
113 csAssert();
114 result = transfer(&msg);
115 csDeassert();
116 bus_unlock();
117 lock_.unlock();
118
119 return result;
120}
121
128__attribute__((optimize("-O3")))
129ssize_t SPI::write(File *file, const void *buf, size_t count)
130{
131 int result;
132
133 if ((file->flags & O_ACCMODE) == O_RDONLY)
134 {
135 return -EBADF;
136 }
137
138 struct spi_ioc_transfer msg;
139 msg.tx_buf = (uint64_t)buf;
140 msg.rx_buf = 0;
141 msg.len = count;
142 msg.speed_hz = speedHz;
143 msg.delay_usec = 0;
144 msg.bits_per_word = bitsPerWord;
145 msg.cs_change = true;
146
147 lock_.lock();
148 bus_lock();
149 csAssert();
150 result = transfer(&msg);
151 csDeassert();
152 bus_unlock();
153 lock_.unlock();
154
155 return result;
156}
157
164__attribute__((optimize("-O3")))
165int SPI::ioctl(File *file, unsigned long int key, unsigned long data)
166{
167 HASSERT(IOC_TYPE(key) == SPI_IOC_MAGIC);
168
169 if (IOC_NR(key) == 0)
170 {
171 /* message transfer */
172 struct spi_ioc_transfer *msgs = (struct spi_ioc_transfer*)data;
173 int result = transfer_messages(msgs, IOC_SIZE(key) /
174 sizeof(struct spi_ioc_transfer));
175 if (result < 0)
176 {
177 return result;
178 }
179 return 0;
180 }
181 switch (key)
182 {
183 default:
184 return -EINVAL;
185 case SPI_IOC_GET_OBJECT_REFERENCE:
186 {
187 SPI **self = (SPI**)data;
188 *self = this;
189 return 0;
190 }
191 case SPI_IOC_RD_MODE:
192 {
193 uint8_t *m = (uint8_t*)data;
194 *m = mode;
195 break;
196 }
197 case SPI_IOC_WR_MODE:
198 {
199 uint8_t *m = (uint8_t*)data;
200 HASSERT(*m <= SPI_MODE_3);
201 mode = *m;
202 break;
203 }
204 case SPI_IOC_RD_LSB_FIRST:
205 {
206 uint8_t *lsbf = (uint8_t*)data;
207 *lsbf = lsbFirst;
208 break;
209 }
210 case SPI_IOC_WR_LSB_FIRST:
211 {
212 uint8_t *lsbf = (uint8_t*)data;
213 lsbFirst = *lsbf;
214 break;
215 }
216 case SPI_IOC_RD_BITS_PER_WORD:
217 {
218 uint8_t *bpw = (uint8_t*)data;
219 *bpw = bitsPerWord;
220 break;
221 }
222 case SPI_IOC_WR_BITS_PER_WORD:
223 {
224 uint8_t *bpw = (uint8_t*)data;
225 bitsPerWord = *bpw;
226 break;
227 }
228 case SPI_IOC_RD_MAX_SPEED_HZ:
229 {
230 uint32_t *hz = (uint32_t*)data;
231 *hz = speedHz;
232 break;
233 }
234 case SPI_IOC_WR_MAX_SPEED_HZ:
235 {
236 uint32_t *hz = (uint32_t*)data;
237 speedHz = *hz;
238 break;
239 }
240 }
241
242 lock_.lock();
243 bus_lock();
244 int result = update_configuration();
245 lock_.unlock();
246 bus_unlock();
247
248 return result;
249}
250
int ioctl(int fd, unsigned long int key,...)
Request and ioctl transaction.
Definition Fileio.cxx:452
Private data for an SPI device.
Definition SPI.hxx:53
#define IOC_SIZE(_num)
Decode ioctl size.
#define IOC_TYPE(_num)
Decode ioctl type.
#define IOC_NR(_num)
Decode ioctl number.
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
Definition macros.h:138
File information.
Definition Devtab.hxx:52