mraa.c: check already initialised before anything else in mraa_init
[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     for (mi = 0; mi < meta.mux_total; mi++) {
129         mraa_gpio_context mux_i;
130         mux_i = mraa_gpio_init_raw(meta.mux[mi].pin);
131         if (mux_i == NULL)
132             return MRAA_ERROR_INVALID_HANDLE;
133         mraa_gpio_dir(mux_i, MRAA_GPIO_OUT);
134         if (mraa_gpio_write(mux_i, meta.mux[mi].value) != MRAA_SUCCESS)
135             return MRAA_ERROR_INVALID_RESOURCE;
136     }
137     return MRAA_SUCCESS;
138 }
139
140 void
141 mraa_result_print(mraa_result_t result)
142 {
143     switch (result) {
144         case MRAA_SUCCESS:
145             fprintf(stdout, "MRAA: SUCCESS\n");
146             break;
147         case MRAA_ERROR_FEATURE_NOT_IMPLEMENTED:
148             fprintf(stdout, "MRAA: Feature not implemented.\n");
149             break;
150         case MRAA_ERROR_FEATURE_NOT_SUPPORTED:
151             fprintf(stdout, "MRAA: Feature not supported by Hardware.\n");
152             break;
153         case MRAA_ERROR_INVALID_VERBOSITY_LEVEL:
154             fprintf(stdout, "MRAA: Invalid verbosity level.\n");
155             break;
156         case MRAA_ERROR_INVALID_PARAMETER:
157             fprintf(stdout, "MRAA: Invalid parameter.\n");
158             break;
159         case MRAA_ERROR_INVALID_HANDLE:
160             fprintf(stdout, "MRAA: Invalid Handle.\n");
161             break;
162         case MRAA_ERROR_NO_RESOURCES:
163             fprintf(stdout, "MRAA: No resources.\n");
164             break;
165         case MRAA_ERROR_INVALID_RESOURCE:
166             fprintf(stdout, "MRAA: Invalid resource.\n");
167             break;
168         case MRAA_ERROR_INVALID_QUEUE_TYPE:
169             fprintf(stdout, "MRAA: Invalid Queue Type.\n");
170             break;
171         case MRAA_ERROR_NO_DATA_AVAILABLE:
172             fprintf(stdout, "MRAA: No Data available.\n");
173             break;
174         case MRAA_ERROR_INVALID_PLATFORM:
175             fprintf(stdout, "MRAA: Platform not recognised.\n");
176             break;
177         case MRAA_ERROR_PLATFORM_NOT_INITIALISED:
178             fprintf(stdout, "MRAA: Platform not initialised.\n");
179             break;
180         case MRAA_ERROR_PLATFORM_ALREADY_INITIALISED:
181             fprintf(stdout, "MRAA: Platform already initialised.\n");
182             break;
183         case MRAA_ERROR_UNSPECIFIED:
184             fprintf(stdout, "MRAA: Unspecified Error.\n");
185             break;
186         default:
187             fprintf(stdout, "MRAA: Unrecognised error.\n");
188             break;
189     }
190 }
191
192 mraa_boolean_t
193 mraa_pin_mode_test(int pin, mraa_pinmodes_t mode)
194 {
195     if (plat == NULL) {
196         mraa_init();
197         if (plat == NULL)
198             return 0;
199     }
200     if (pin > plat->phy_pin_count || pin < 0)
201         return 0;
202
203     switch(mode) {
204         case MRAA_PIN_VALID:
205             if (plat->pins[pin].capabilites.valid == 1)
206                 return 1;
207             break;
208         case MRAA_PIN_GPIO:
209             if (plat->pins[pin].capabilites.gpio ==1)
210                 return 1;
211             break;
212         case MRAA_PIN_PWM:
213             if (plat->pins[pin].capabilites.pwm ==1)
214                 return 1;
215             break;
216         case MRAA_PIN_FAST_GPIO:
217             if (plat->pins[pin].capabilites.fast_gpio ==1)
218                 return 1;
219             break;
220         case MRAA_PIN_SPI:
221             if (plat->pins[pin].capabilites.spi ==1)
222                 return 1;
223             break;
224         case MRAA_PIN_I2C:
225             if (plat->pins[pin].capabilites.i2c ==1)
226                 return 1;
227             break;
228         case MRAA_PIN_AIO:
229             if (pin < plat->aio_count)
230                 pin = pin + plat->gpio_count;
231             if (plat->pins[pin].capabilites.aio ==1)
232                 return 1;
233             break;
234         default: break;
235     }
236     return 0;
237 }
238
239 mraa_platform_t mraa_get_platform_type()
240 {
241     return platform_type;
242 }
243
244 unsigned int
245 mraa_adc_raw_bits()
246 {
247     if (plat == NULL)
248         return 0;
249
250     if (plat->aio_count == 0)
251         return 0;
252
253     return plat->adc_raw;
254 }
255
256 unsigned int
257 mraa_adc_supported_bits()
258 {
259     if (plat == NULL)
260         return 0;
261
262     if (plat->aio_count == 0)
263         return 0;
264
265     return plat->adc_supported;
266 }
267
268 mraa_result_t
269 mraa_setup_uart(int index)
270 {
271     if (plat == NULL)
272         return MRAA_ERROR_PLATFORM_NOT_INITIALISED;
273
274     if (plat->uart_dev_count == 0)
275         return MRAA_ERROR_FEATURE_NOT_SUPPORTED;
276
277     if (plat->uart_dev_count <= index)
278         return MRAA_ERROR_NO_RESOURCES;
279
280     int pos = plat->uart_dev[index].rx;
281     if (pos >= 0) {
282         if (plat->pins[pos].uart.mux_total > 0)
283             if (mraa_setup_mux_mapped(plat->pins[pos].uart) != MRAA_SUCCESS)
284                 return MRAA_ERROR_INVALID_RESOURCE;
285     }
286
287     if (pos >= 0) {
288         pos = plat->uart_dev[index].tx;
289         if (plat->pins[pos].uart.mux_total > 0)
290             if (mraa_setup_mux_mapped(plat->pins[pos].uart) != MRAA_SUCCESS)
291                 return MRAA_ERROR_INVALID_RESOURCE;
292     }
293
294     return MRAA_SUCCESS;
295 }
296
297 char*
298 mraa_get_platform_name()
299 {
300     if (plat == NULL)
301         return "Unknown";
302     return plat->platform_name;
303 }