spi: if platform has one spidev, defaults to it.
[contrib/mraa.git] / src / mraa.c
1 /*
2  * Author: Brendan Le Foll <brendan.le.foll@intel.com>
3  * Author: Thomas Ingleby <thomas.c.ingleby@intel.com>
4  * Copyright (c) 2014 Intel Corporation.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25
26 #include <stddef.h>
27 #include <stdlib.h>
28 #include <sched.h>
29 #include <string.h>
30
31 #include "mraa_internal.h"
32 #include "intel_galileo_rev_d.h"
33 #include "intel_galileo_rev_g.h"
34 #include "gpio.h"
35 #include "version.h"
36
37 mraa_board_t* plat = NULL;
38 static mraa_platform_t platform_type = MRAA_UNKNOWN_PLATFORM;
39 mraa_adv_func_t* advance_func;
40
41 const char *
42 mraa_get_version()
43 {
44     return gVERSION;
45 }
46
47 mraa_result_t __attribute__((constructor))
48 mraa_init()
49 {
50     /** Once more board definitions have been added,
51      *  A method for detecting them will need to be devised.
52      */
53     if (plat != NULL) {
54         return MRAA_ERROR_PLATFORM_ALREADY_INITIALISED;
55     }
56 #ifdef SWIGPYTHON
57     // Initialise python threads, this allows use to grab the GIL when we are
58     // required to do so
59     Py_InitializeEx(0);
60     PyEval_InitThreads();
61 #endif
62     // detect a galileo gen2 board
63     char *line = NULL;
64     // let getline allocate memory for *line
65     size_t len = 0;
66     FILE *fh = fopen("/sys/devices/virtual/dmi/id/board_name", "r");
67     if (fh != NULL) {
68         if (getline(&line, &len, fh) != -1) {
69             if (strncmp(line, "GalileoGen2", 10) == 0) {
70                 platform_type = MRAA_INTEL_GALILEO_GEN2;
71             } else {
72                 platform_type = MRAA_INTEL_GALILEO_GEN1;
73             }
74             free(line);
75         }
76         fclose(fh);
77     }
78
79     advance_func = (mraa_adv_func_t*) malloc(sizeof(mraa_adv_func_t));
80     memset(advance_func, 0, sizeof(mraa_adv_func_t));
81
82     switch(platform_type) {
83         case MRAA_INTEL_GALILEO_GEN2:
84             plat = mraa_intel_galileo_gen2();
85             break;
86         case MRAA_INTEL_GALILEO_GEN1:
87             plat = mraa_intel_galileo_rev_d();
88             break;
89         default:
90             plat = mraa_intel_galileo_rev_d();
91             fprintf(stderr, "Platform not found, initialising MRAA_INTEL_GALILEO_GEN1\n");
92     }
93
94     return MRAA_SUCCESS;
95 }
96
97 void
98 mraa_deinit()
99 {
100     free(plat->pins);
101     free(plat);
102 }
103
104 int
105 mraa_set_priority(const unsigned int priority)
106 {
107     struct sched_param sched_s;
108
109     memset(&sched_s, 0, sizeof(struct sched_param));
110     if (priority > sched_get_priority_max(SCHED_RR)) {
111         sched_s.sched_priority = sched_get_priority_max(SCHED_RR);
112     }
113     else {
114         sched_s.sched_priority = priority;
115     }
116
117     return sched_setscheduler(0, SCHED_RR, &sched_s);
118 }
119
120 static mraa_result_t
121 mraa_setup_mux_mapped(mraa_pin_t meta)
122 {
123     int mi;
124     for (mi = 0; mi < meta.mux_total; mi++) {
125         mraa_gpio_context mux_i;
126         mux_i = mraa_gpio_init_raw(meta.mux[mi].pin);
127         if (mux_i == NULL)
128             return MRAA_ERROR_INVALID_HANDLE;
129         mraa_gpio_dir(mux_i, MRAA_GPIO_OUT);
130         if (mraa_gpio_write(mux_i, meta.mux[mi].value) != MRAA_SUCCESS)
131             return MRAA_ERROR_INVALID_RESOURCE;
132     }
133     return MRAA_SUCCESS;
134 }
135
136 unsigned int
137 mraa_setup_gpio(int pin)
138 {
139     if (plat == NULL)
140         return -1;
141
142     if (pin < 0 || pin > plat->phy_pin_count)
143         return -1;
144
145     if(plat->pins[pin].capabilites.gpio != 1)
146       return -1;
147
148     if (plat->pins[pin].gpio.mux_total > 0)
149        if (mraa_setup_mux_mapped(plat->pins[pin].gpio) != MRAA_SUCCESS)
150             return -1;
151     return plat->pins[pin].gpio.pinmap;
152 }
153
154 unsigned int
155 mraa_setup_aio(int aio)
156 {
157     if (plat == NULL)
158         return -3;
159
160     if (aio < 0 || aio > plat->aio_count)
161         return -1;
162
163     int pin = aio + plat->gpio_count;
164
165     if (plat->pins[pin].capabilites.aio != 1)
166       return -1;
167
168     if (plat->pins[pin].aio.mux_total > 0)
169        if (mraa_setup_mux_mapped(plat->pins[pin].aio) != MRAA_SUCCESS)
170             return -1;
171     return plat->pins[pin].aio.pinmap;
172 }
173
174 unsigned int
175 mraa_setup_i2c(int bus)
176 {
177     if (plat == NULL)
178         return -3;
179
180     if (plat->i2c_bus_count >! 0) {
181         fprintf(stderr, "No i2c buses defined in platform");
182         return -1;
183     }
184     if (bus >= plat->i2c_bus_count) {
185         fprintf(stderr, "Above i2c bus count");
186         return -1;
187     }
188
189     int pos = plat->i2c_bus[bus].sda;
190     if (plat->pins[pos].i2c.mux_total > 0)
191         if (mraa_setup_mux_mapped(plat->pins[pos].i2c) != MRAA_SUCCESS)
192              return -2;
193
194     pos = plat->i2c_bus[bus].scl;
195     if (plat->pins[pos].i2c.mux_total > 0)
196         if (mraa_setup_mux_mapped(plat->pins[pos].i2c) != MRAA_SUCCESS)
197              return -2;
198
199     return plat->i2c_bus[bus].bus_id;
200 }
201
202 mraa_spi_bus_t*
203 mraa_setup_spi(int bus)
204 {
205     if (plat == NULL)
206         return NULL;
207
208     if (plat->spi_bus_count >! 0) {
209         fprintf(stderr, "No spi buses defined in platform");
210         return NULL;
211     }
212     if (plat->spi_bus_count == 1) {
213         bus = plat->def_spi_bus;
214     }
215     if (bus >= plat->spi_bus_count) {
216         fprintf(stderr, "Above spi bus count");
217         return NULL;
218     }
219
220     int pos = plat->spi_bus[bus].sclk;
221     if (plat->pins[pos].spi.mux_total > 0)
222         if (mraa_setup_mux_mapped(plat->pins[pos].spi) != MRAA_SUCCESS)
223              return NULL;
224
225     pos = plat->spi_bus[bus].mosi;
226     if (plat->pins[pos].spi.mux_total > 0)
227         if (mraa_setup_mux_mapped(plat->pins[pos].spi) != MRAA_SUCCESS)
228              return NULL;
229
230     pos = plat->spi_bus[bus].miso;
231     if (plat->pins[pos].spi.mux_total > 0)
232         if (mraa_setup_mux_mapped(plat->pins[pos].spi) != MRAA_SUCCESS)
233              return NULL;
234
235     mraa_spi_bus_t *spi = &(plat->spi_bus[bus]);
236     return spi;
237 }
238
239 mraa_pin_t*
240 mraa_setup_pwm(int pin)
241 {
242     if (plat == NULL)
243         return NULL;
244
245     if (plat->pins[pin].capabilites.pwm != 1)
246         return NULL;
247
248     if (plat->pins[pin].capabilites.gpio == 1) {
249         mraa_gpio_context mux_i;
250         mux_i = mraa_gpio_init_raw(plat->pins[pin].gpio.pinmap);
251         if (mux_i == NULL)
252             return NULL;
253         if (mraa_gpio_dir(mux_i, MRAA_GPIO_OUT) != MRAA_SUCCESS)
254             return NULL;
255         // Current REV D quirk. //TODO GEN 2
256         if (mraa_gpio_write(mux_i, 1) != MRAA_SUCCESS)
257             return NULL;
258         if (mraa_gpio_close(mux_i) != MRAA_SUCCESS)
259             return NULL;
260     }
261
262     if (plat->pins[pin].pwm.mux_total > 0)
263        if (mraa_setup_mux_mapped(plat->pins[pin].pwm) != MRAA_SUCCESS)
264             return NULL;
265
266     mraa_pin_t *ret;
267     ret = (mraa_pin_t*) malloc(sizeof(mraa_pin_t));
268     ret->pinmap = plat->pins[pin].pwm.pinmap;
269     ret->parent_id = plat->pins[pin].pwm.parent_id;
270     return ret;
271 }
272
273 void
274 mraa_result_print(mraa_result_t result)
275 {
276     switch (result) {
277         case MRAA_SUCCESS: fprintf(stderr, "MRAA: SUCCESS\n");
278                           break;
279         case MRAA_ERROR_FEATURE_NOT_IMPLEMENTED:
280                           fprintf(stderr, "MRAA: Feature not implemented.\n");
281                           break;
282         case MRAA_ERROR_FEATURE_NOT_SUPPORTED:
283                           fprintf(stderr, "MRAA: Feature not supported by Hardware.\n");
284                           break;
285         case MRAA_ERROR_INVALID_VERBOSITY_LEVEL:
286                           fprintf(stderr, "MRAA: Invalid verbosity level.\n");
287                           break;
288         case MRAA_ERROR_INVALID_PARAMETER:
289                           fprintf(stderr, "MRAA: Invalid parameter.\n");
290                           break;
291         case MRAA_ERROR_INVALID_HANDLE:
292                           fprintf(stderr, "MRAA: Invalid Handle.\n");
293                           break;
294         case MRAA_ERROR_NO_RESOURCES:
295                           fprintf(stderr, "MRAA: No resources.\n");
296                           break;
297         case MRAA_ERROR_INVALID_RESOURCE:
298                           fprintf(stderr, "MRAA: Invalid resource.\n");
299                           break;
300         case MRAA_ERROR_INVALID_QUEUE_TYPE:
301                           fprintf(stderr, "MRAA: Invalid Queue Type.\n");
302                           break;
303         case MRAA_ERROR_NO_DATA_AVAILABLE:
304                           fprintf(stderr, "MRAA: No Data available.\n");
305                           break;
306         case MRAA_ERROR_INVALID_PLATFORM:
307                           fprintf(stderr, "MRAA: Platform not recognised.\n");
308                           break;
309         case MRAA_ERROR_PLATFORM_NOT_INITIALISED:
310                           fprintf(stderr, "MRAA: Platform not initialised.\n");
311                           break;
312         case MRAA_ERROR_PLATFORM_ALREADY_INITIALISED:
313                           fprintf(stderr, "MRAA: Platform already initialised.\n");
314                           break;
315         case MRAA_ERROR_UNSPECIFIED:
316                           fprintf(stderr, "MRAA: Unspecified Error.\n");
317                           break;
318         default:     fprintf(stderr, "MRAA: Unrecognised error.\n");
319                           break;
320     }
321 }
322
323 mraa_boolean_t
324 mraa_pin_mode_test(int pin, mraa_pinmodes_t mode)
325 {
326     if (plat == NULL) {
327         mraa_init();
328         if (plat == NULL)
329             return 0;
330     }
331     if (pin > plat->phy_pin_count || pin < 0)
332         return 0;
333
334     switch(mode) {
335         case MRAA_PIN_VALID:
336             if (plat->pins[pin].capabilites.valid == 1)
337                 return 1;
338             break;
339         case MRAA_PIN_GPIO:
340             if (plat->pins[pin].capabilites.gpio ==1)
341                 return 1;
342             break;
343         case MRAA_PIN_PWM:
344             if (plat->pins[pin].capabilites.pwm ==1)
345                 return 1;
346             break;
347         case MRAA_PIN_FAST_GPIO:
348             if (plat->pins[pin].capabilites.fast_gpio ==1)
349                 return 1;
350             break;
351         case MRAA_PIN_SPI:
352             if (plat->pins[pin].capabilites.spi ==1)
353                 return 1;
354             break;
355         case MRAA_PIN_I2C:
356             if (plat->pins[pin].capabilites.i2c ==1)
357                 return 1;
358             break;
359         case MRAA_PIN_AIO:
360             if (pin < plat->aio_count)
361                 pin = pin + plat->gpio_count;
362             if (plat->pins[pin].capabilites.aio ==1)
363                 return 1;
364             break;
365         default: break;
366     }
367     return 0;
368 }
369
370 mraa_mmap_pin_t*
371 mraa_setup_mmap_gpio(int pin)
372 {
373     if (plat == NULL)
374         return NULL;
375
376     if (plat->pins[pin].capabilites.fast_gpio != 1)
377         return NULL;
378
379     if (plat->pins[pin].mmap.gpio.mux_total > 0)
380        if (mraa_setup_mux_mapped(plat->pins[pin].mmap.gpio) != MRAA_SUCCESS)
381             return NULL;
382
383     if (mraa_setup_mux_mapped(plat->pins[pin].mmap.gpio) != MRAA_SUCCESS)
384             return NULL;
385     mraa_mmap_pin_t *ret = &(plat->pins[pin].mmap);
386     return ret;
387 }
388
389 mraa_platform_t mraa_get_platform_type()
390 {
391     return platform_type;
392 }
393
394 unsigned int
395 mraa_adc_raw_bits()
396 {
397     if (plat == NULL)
398         return 0;
399
400     if (plat->aio_count == 0)
401         return 0;
402
403     return plat->adc_raw;
404 }
405
406 unsigned int
407 mraa_adc_supported_bits()
408 {
409     if (plat == NULL)
410         return 0;
411
412     if (plat->aio_count == 0)
413         return 0;
414
415     return plat->adc_supported;
416 }
417
418 mraa_result_t
419 mraa_setup_uart(int index)
420 {
421     if (plat == NULL)
422         return MRAA_ERROR_PLATFORM_NOT_INITIALISED;
423
424     if (plat->uart_dev_count == 0)
425         return MRAA_ERROR_FEATURE_NOT_SUPPORTED;
426
427     if (plat->uart_dev_count <= index)
428         return MRAA_ERROR_NO_RESOURCES;
429
430     int pos = plat->uart_dev[index].rx;
431     if (pos >= 0) {
432         if (plat->pins[pos].uart.mux_total > 0)
433             if (mraa_setup_mux_mapped(plat->pins[pos].uart) != MRAA_SUCCESS)
434                 return MRAA_ERROR_INVALID_RESOURCE;
435     }
436
437     if (pos >= 0) {
438         pos = plat->uart_dev[index].tx;
439         if (plat->pins[pos].uart.mux_total > 0)
440             if (mraa_setup_mux_mapped(plat->pins[pos].uart) != MRAA_SUCCESS)
441                 return MRAA_ERROR_INVALID_RESOURCE;
442     }
443
444     return MRAA_SUCCESS;
445 }