mraa.c: do not check return value of mraa_gpio_dir when used on muxes
[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 #define DEBUG
32
33 #include "mraa_internal.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
48 mraa_set_log_level(int level)
49 {
50     if (level <= 7 && level >= 0) {
51         setlogmask(LOG_UPTO(level));
52         return MRAA_SUCCESS;
53     }
54     return MRAA_ERROR_INVALID_PARAMETER;
55 }
56
57 mraa_result_t __attribute__((constructor))
58 mraa_init()
59 {
60     if (plat != NULL) {
61         return MRAA_ERROR_PLATFORM_ALREADY_INITIALISED;
62     }
63
64 #ifdef DEBUG
65     setlogmask(LOG_UPTO(LOG_DEBUG));
66 #else
67     setlogmask(LOG_UPTO(LOG_NOTICE));
68 #endif
69
70     openlog("libmraa", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
71     syslog(LOG_DEBUG, "libmraa initialised by user %d", getuid());
72
73 #ifdef SWIGPYTHON
74     // Initialise python threads, this allows use to grab the GIL when we are
75     // required to do so
76     Py_InitializeEx(0);
77     PyEval_InitThreads();
78 #endif
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 #ifdef X86PLAT
83     // Use runtime x86 platform detection
84     platform_type = mraa_x86_platform();
85 #elif ARMPLAT
86     // Use runtime ARM platform detection
87     platform_type = mraa_arm_platform();
88 #else
89     #error mraa_ARCH NOTHING
90 #endif
91
92     if (plat == NULL) {
93         printf("mraa: FATAL error, failed to initialise platform\n");
94         return MRAA_ERROR_PLATFORM_NOT_INITIALISED;
95     }
96     syslog(LOG_INFO, "libmraa initialised for platform %d", platform_type);
97     return MRAA_SUCCESS;
98 }
99
100 void
101 mraa_deinit()
102 {
103     free(plat->pins);
104     free(plat);
105     closelog();
106 }
107
108 int
109 mraa_set_priority(const unsigned int priority)
110 {
111     struct sched_param sched_s;
112
113     memset(&sched_s, 0, sizeof(struct sched_param));
114     if (priority > sched_get_priority_max(SCHED_RR)) {
115         sched_s.sched_priority = sched_get_priority_max(SCHED_RR);
116     }
117     else {
118         sched_s.sched_priority = priority;
119     }
120
121     return sched_setscheduler(0, SCHED_RR, &sched_s);
122 }
123
124 mraa_result_t
125 mraa_setup_mux_mapped(mraa_pin_t meta)
126 {
127     int mi;
128
129     for (mi = 0; mi < meta.mux_total; mi++) {
130         mraa_gpio_context mux_i;
131         mux_i = mraa_gpio_init_raw(meta.mux[mi].pin);
132         if (mux_i == NULL) {
133             return MRAA_ERROR_INVALID_HANDLE;
134         }
135         // this function will sometimes fail, however this is not critical as
136         // long as the write succeeds - Test case galileo gen2 pin2
137         mraa_gpio_dir(mux_i, MRAA_GPIO_OUT);
138
139         if (mraa_gpio_write(mux_i, meta.mux[mi].value) != MRAA_SUCCESS) {
140             mraa_gpio_close(mux_i);
141             return MRAA_ERROR_INVALID_RESOURCE;
142         }
143         mraa_gpio_close(mux_i);
144     }
145
146     return MRAA_SUCCESS;
147 }
148
149 void
150 mraa_result_print(mraa_result_t result)
151 {
152     switch (result) {
153         case MRAA_SUCCESS:
154             fprintf(stdout, "MRAA: SUCCESS\n");
155             break;
156         case MRAA_ERROR_FEATURE_NOT_IMPLEMENTED:
157             fprintf(stdout, "MRAA: Feature not implemented.\n");
158             break;
159         case MRAA_ERROR_FEATURE_NOT_SUPPORTED:
160             fprintf(stdout, "MRAA: Feature not supported by Hardware.\n");
161             break;
162         case MRAA_ERROR_INVALID_VERBOSITY_LEVEL:
163             fprintf(stdout, "MRAA: Invalid verbosity level.\n");
164             break;
165         case MRAA_ERROR_INVALID_PARAMETER:
166             fprintf(stdout, "MRAA: Invalid parameter.\n");
167             break;
168         case MRAA_ERROR_INVALID_HANDLE:
169             fprintf(stdout, "MRAA: Invalid Handle.\n");
170             break;
171         case MRAA_ERROR_NO_RESOURCES:
172             fprintf(stdout, "MRAA: No resources.\n");
173             break;
174         case MRAA_ERROR_INVALID_RESOURCE:
175             fprintf(stdout, "MRAA: Invalid resource.\n");
176             break;
177         case MRAA_ERROR_INVALID_QUEUE_TYPE:
178             fprintf(stdout, "MRAA: Invalid Queue Type.\n");
179             break;
180         case MRAA_ERROR_NO_DATA_AVAILABLE:
181             fprintf(stdout, "MRAA: No Data available.\n");
182             break;
183         case MRAA_ERROR_INVALID_PLATFORM:
184             fprintf(stdout, "MRAA: Platform not recognised.\n");
185             break;
186         case MRAA_ERROR_PLATFORM_NOT_INITIALISED:
187             fprintf(stdout, "MRAA: Platform not initialised.\n");
188             break;
189         case MRAA_ERROR_PLATFORM_ALREADY_INITIALISED:
190             fprintf(stdout, "MRAA: Platform already initialised.\n");
191             break;
192         case MRAA_ERROR_UNSPECIFIED:
193             fprintf(stdout, "MRAA: Unspecified Error.\n");
194             break;
195         default:
196             fprintf(stdout, "MRAA: Unrecognised error.\n");
197             break;
198     }
199 }
200
201 mraa_boolean_t
202 mraa_pin_mode_test(int pin, mraa_pinmodes_t mode)
203 {
204     if (plat == NULL) {
205         mraa_init();
206         if (plat == NULL)
207             return 0;
208     }
209     if (pin > plat->phy_pin_count || pin < 0)
210         return 0;
211
212     switch(mode) {
213         case MRAA_PIN_VALID:
214             if (plat->pins[pin].capabilites.valid == 1)
215                 return 1;
216             break;
217         case MRAA_PIN_GPIO:
218             if (plat->pins[pin].capabilites.gpio ==1)
219                 return 1;
220             break;
221         case MRAA_PIN_PWM:
222             if (plat->pins[pin].capabilites.pwm ==1)
223                 return 1;
224             break;
225         case MRAA_PIN_FAST_GPIO:
226             if (plat->pins[pin].capabilites.fast_gpio ==1)
227                 return 1;
228             break;
229         case MRAA_PIN_SPI:
230             if (plat->pins[pin].capabilites.spi ==1)
231                 return 1;
232             break;
233         case MRAA_PIN_I2C:
234             if (plat->pins[pin].capabilites.i2c ==1)
235                 return 1;
236             break;
237         case MRAA_PIN_AIO:
238             if (pin < plat->aio_count)
239                 pin = pin + plat->gpio_count;
240             if (plat->pins[pin].capabilites.aio ==1)
241                 return 1;
242             break;
243         default: break;
244     }
245     return 0;
246 }
247
248 mraa_platform_t mraa_get_platform_type()
249 {
250     return platform_type;
251 }
252
253 unsigned int
254 mraa_adc_raw_bits()
255 {
256     if (plat == NULL)
257         return 0;
258
259     if (plat->aio_count == 0)
260         return 0;
261
262     return plat->adc_raw;
263 }
264
265 unsigned int
266 mraa_adc_supported_bits()
267 {
268     if (plat == NULL)
269         return 0;
270
271     if (plat->aio_count == 0)
272         return 0;
273
274     return plat->adc_supported;
275 }
276
277 mraa_result_t
278 mraa_setup_uart(int index)
279 {
280     if (plat == NULL)
281         return MRAA_ERROR_PLATFORM_NOT_INITIALISED;
282
283     if (plat->uart_dev_count == 0)
284         return MRAA_ERROR_FEATURE_NOT_SUPPORTED;
285
286     if (plat->uart_dev_count <= index)
287         return MRAA_ERROR_NO_RESOURCES;
288
289     int pos = plat->uart_dev[index].rx;
290     if (pos >= 0) {
291         if (plat->pins[pos].uart.mux_total > 0)
292             if (mraa_setup_mux_mapped(plat->pins[pos].uart) != MRAA_SUCCESS)
293                 return MRAA_ERROR_INVALID_RESOURCE;
294     }
295
296     if (pos >= 0) {
297         pos = plat->uart_dev[index].tx;
298         if (plat->pins[pos].uart.mux_total > 0)
299             if (mraa_setup_mux_mapped(plat->pins[pos].uart) != MRAA_SUCCESS)
300                 return MRAA_ERROR_INVALID_RESOURCE;
301     }
302
303     return MRAA_SUCCESS;
304 }
305
306 char*
307 mraa_get_platform_name()
308 {
309     if (plat == NULL)
310         return "Unknown";
311     return plat->platform_name;
312 }