c2bd2a0cb1d39dc2c431f77197b499edd03991d9
[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 #include <pwd.h>
31 #include <glob.h>
32
33
34 #include "mraa_internal.h"
35 #include "gpio.h"
36 #include "version.h"
37
38 mraa_board_t* plat = NULL;
39 static mraa_platform_t platform_type = MRAA_UNKNOWN_PLATFORM;
40 mraa_adv_func_t* advance_func;
41
42 const char *
43 mraa_get_version()
44 {
45     return gVERSION;
46 }
47
48 mraa_result_t
49 mraa_set_log_level(int level)
50 {
51     if (level <= 7 && level >= 0) {
52         setlogmask(LOG_UPTO(level));
53         return MRAA_SUCCESS;
54     }
55     return MRAA_ERROR_INVALID_PARAMETER;
56 }
57
58 #if (defined SWIGPYTHON) || (defined SWIG)
59 mraa_result_t
60 #else
61 mraa_result_t __attribute__((constructor))
62 #endif
63 mraa_init()
64 {
65     if (plat != NULL) {
66         return MRAA_ERROR_PLATFORM_ALREADY_INITIALISED;
67     }
68
69     uid_t proc_euid = geteuid();
70     struct passwd *proc_user = getpwuid(proc_euid);
71
72 #ifdef DEBUG
73     setlogmask(LOG_UPTO(LOG_DEBUG));
74 #else
75     setlogmask(LOG_UPTO(LOG_NOTICE));
76 #endif
77
78     openlog("libmraa", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
79     syslog(LOG_NOTICE,
80            "libmraa version %s initialised by user '%s' with EUID %d",
81            mraa_get_version(),
82            (proc_user != NULL) ? proc_user->pw_name : "<unknown>",
83            proc_euid);
84
85 #ifdef SWIGPYTHON
86     // Initialise python threads, this allows use to grab the GIL when we are
87     // required to do so
88     Py_InitializeEx(0);
89     PyEval_InitThreads();
90 #endif
91     advance_func = (mraa_adv_func_t*) malloc(sizeof(mraa_adv_func_t));
92     memset(advance_func, 0, sizeof(mraa_adv_func_t));
93
94 #ifdef X86PLAT
95     // Use runtime x86 platform detection
96     platform_type = mraa_x86_platform();
97 #elif ARMPLAT
98     // Use runtime ARM platform detection
99     platform_type = mraa_arm_platform();
100 #else
101     #error mraa_ARCH NOTHING
102 #endif
103
104     if (plat == NULL) {
105         printf("mraa: FATAL error, failed to initialise platform\n");
106         return MRAA_ERROR_PLATFORM_NOT_INITIALISED;
107     }
108
109     syslog(LOG_INFO,
110            "libmraa initialised for platform '%s' of type %d",
111            mraa_get_platform_name(),
112            platform_type);
113     return MRAA_SUCCESS;
114 }
115
116 void
117 mraa_deinit()
118 {
119     if (plat != NULL) {
120         if (plat->pins != NULL) {
121             free(plat->pins);
122         }
123         free(plat);
124     }
125     closelog();
126 }
127
128 int
129 mraa_set_priority(const unsigned int priority)
130 {
131     struct sched_param sched_s;
132
133     memset(&sched_s, 0, sizeof(struct sched_param));
134     if (priority > sched_get_priority_max(SCHED_RR)) {
135         sched_s.sched_priority = sched_get_priority_max(SCHED_RR);
136     }
137     else {
138         sched_s.sched_priority = priority;
139     }
140
141     return sched_setscheduler(0, SCHED_RR, &sched_s);
142 }
143
144 mraa_result_t
145 mraa_setup_mux_mapped(mraa_pin_t meta)
146 {
147     int mi;
148
149     for (mi = 0; mi < meta.mux_total; mi++) {
150         mraa_gpio_context mux_i;
151         mux_i = mraa_gpio_init_raw(meta.mux[mi].pin);
152         if (mux_i == NULL) {
153             return MRAA_ERROR_INVALID_HANDLE;
154         }
155         // this function will sometimes fail, however this is not critical as
156         // long as the write succeeds - Test case galileo gen2 pin2
157         mraa_gpio_dir(mux_i, MRAA_GPIO_OUT);
158         mraa_gpio_owner(mux_i, 0);
159
160         if (mraa_gpio_write(mux_i, meta.mux[mi].value) != MRAA_SUCCESS) {
161             mraa_gpio_close(mux_i);
162             return MRAA_ERROR_INVALID_RESOURCE;
163         }
164         mraa_gpio_close(mux_i);
165     }
166
167     return MRAA_SUCCESS;
168 }
169
170 void
171 mraa_result_print(mraa_result_t result)
172 {
173     switch (result) {
174         case MRAA_SUCCESS:
175             fprintf(stdout, "MRAA: SUCCESS\n");
176             break;
177         case MRAA_ERROR_FEATURE_NOT_IMPLEMENTED:
178             fprintf(stdout, "MRAA: Feature not implemented.\n");
179             break;
180         case MRAA_ERROR_FEATURE_NOT_SUPPORTED:
181             fprintf(stdout, "MRAA: Feature not supported by Hardware.\n");
182             break;
183         case MRAA_ERROR_INVALID_VERBOSITY_LEVEL:
184             fprintf(stdout, "MRAA: Invalid verbosity level.\n");
185             break;
186         case MRAA_ERROR_INVALID_PARAMETER:
187             fprintf(stdout, "MRAA: Invalid parameter.\n");
188             break;
189         case MRAA_ERROR_INVALID_HANDLE:
190             fprintf(stdout, "MRAA: Invalid Handle.\n");
191             break;
192         case MRAA_ERROR_NO_RESOURCES:
193             fprintf(stdout, "MRAA: No resources.\n");
194             break;
195         case MRAA_ERROR_INVALID_RESOURCE:
196             fprintf(stdout, "MRAA: Invalid resource.\n");
197             break;
198         case MRAA_ERROR_INVALID_QUEUE_TYPE:
199             fprintf(stdout, "MRAA: Invalid Queue Type.\n");
200             break;
201         case MRAA_ERROR_NO_DATA_AVAILABLE:
202             fprintf(stdout, "MRAA: No Data available.\n");
203             break;
204         case MRAA_ERROR_INVALID_PLATFORM:
205             fprintf(stdout, "MRAA: Platform not recognised.\n");
206             break;
207         case MRAA_ERROR_PLATFORM_NOT_INITIALISED:
208             fprintf(stdout, "MRAA: Platform not initialised.\n");
209             break;
210         case MRAA_ERROR_PLATFORM_ALREADY_INITIALISED:
211             fprintf(stdout, "MRAA: Platform already initialised.\n");
212             break;
213         case MRAA_ERROR_UNSPECIFIED:
214             fprintf(stdout, "MRAA: Unspecified Error.\n");
215             break;
216         default:
217             fprintf(stdout, "MRAA: Unrecognised error.\n");
218             break;
219     }
220 }
221
222 mraa_boolean_t
223 mraa_pin_mode_test(int pin, mraa_pinmodes_t mode)
224 {
225     if (plat == NULL) {
226         mraa_init();
227         if (plat == NULL)
228             return 0;
229     }
230     if (pin > (plat->phy_pin_count -1) || pin < 0)
231         return 0;
232
233     switch(mode) {
234         case MRAA_PIN_VALID:
235             if (plat->pins[pin].capabilites.valid == 1)
236                 return 1;
237             break;
238         case MRAA_PIN_GPIO:
239             if (plat->pins[pin].capabilites.gpio ==1)
240                 return 1;
241             break;
242         case MRAA_PIN_PWM:
243             if (plat->pins[pin].capabilites.pwm ==1)
244                 return 1;
245             break;
246         case MRAA_PIN_FAST_GPIO:
247             if (plat->pins[pin].capabilites.fast_gpio ==1)
248                 return 1;
249             break;
250         case MRAA_PIN_SPI:
251             if (plat->pins[pin].capabilites.spi ==1)
252                 return 1;
253             break;
254         case MRAA_PIN_I2C:
255             if (plat->pins[pin].capabilites.i2c ==1)
256                 return 1;
257             break;
258         case MRAA_PIN_AIO:
259             if (plat->pins[pin].capabilites.aio ==1)
260                 return 1;
261             break;
262         case MRAA_PIN_UART:
263             if (plat->pins[pin].capabilites.uart == 1)
264                 return 1;
265             break;
266         default:
267             syslog(LOG_NOTICE, "requested pinmode invalid");
268             break;
269     }
270     return 0;
271 }
272
273 mraa_platform_t mraa_get_platform_type()
274 {
275     return platform_type;
276 }
277
278 unsigned int
279 mraa_adc_raw_bits()
280 {
281     if (plat == NULL)
282         return 0;
283
284     if (plat->aio_count == 0)
285         return 0;
286
287     return plat->adc_raw;
288 }
289
290 unsigned int
291 mraa_adc_supported_bits()
292 {
293     if (plat == NULL)
294         return 0;
295
296     if (plat->aio_count == 0)
297         return 0;
298
299     return plat->adc_supported;
300 }
301
302 char*
303 mraa_get_platform_name()
304 {
305     if (plat == NULL) {
306         return NULL;
307     }
308     return (char*) plat->platform_name;
309 }
310
311 unsigned int
312 mraa_get_pin_count()
313 {
314     if (plat == NULL) {
315         return 0;
316     }
317     return plat->phy_pin_count;
318 }
319
320 mraa_boolean_t
321 mraa_file_exist(char *filename) {
322     glob_t results;
323     results.gl_pathc = 0;
324     glob(filename, 0, NULL, &results);
325     int file_found = results.gl_pathc == 1;
326     globfree(&results);
327     return file_found;
328 }
329
330 char*
331 mraa_get_pin_name(int pin)
332 {
333     if (plat == NULL) {
334         return NULL;
335     }
336     if (pin > (plat->phy_pin_count -1) || pin < 0)
337         return NULL;
338     return (char*) plat->pins[pin].name;
339 }
340
341 char*
342 mraa_file_unglob(char *filename) {
343     glob_t results;
344     char *res = NULL;
345     results.gl_pathc = 0;
346     glob(filename, 0, NULL, &results);
347     if (results.gl_pathc == 1)
348         res = strdup(results.gl_pathv[0]);
349     globfree(&results);
350     return res;
351 }
352
353 mraa_boolean_t
354 mraa_link_targets(char *filename,char *targetname) {
355     int size = 100;
356     int nchars = 0;
357     char *buffer = NULL;
358     while (nchars == 0)
359     {
360         buffer = (char *) realloc(buffer,size);
361         if (buffer == NULL)
362             return 0;
363         nchars = readlink(filename,buffer,size);
364         if (nchars < 0 ) {
365             free(buffer);
366             return 0;
367         }
368         if (nchars >= size) {
369             size *=2;
370             nchars=0;
371         }
372     }
373     if (strstr(buffer,targetname)) {
374         free(buffer);
375         return 1;
376     }
377     else {
378         free(buffer);
379         return 0;
380     }
381 }