maa: make common.h header to replace maa.h header to simplify includes
[contrib/mraa.git] / src / maa.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 "maa_internal.h"
32 #include "intel_galileo_rev_d.h"
33 #include "gpio.h"
34 #include "version.h"
35
36 //static maa_pininfo_t* pindata;
37 static maa_board_t* plat = NULL;
38
39 const char *
40 maa_get_version()
41 {
42     return gVERSION;
43 }
44
45 #ifdef SWIG
46 maa_result_t
47 maa_init()
48 #else
49 maa_result_t __attribute__((constructor))
50 maa_init()
51 #endif
52 {
53     /** Once more board definitions have been added,
54      *  A method for detecting them will need to be devised.
55      */
56     if (plat != NULL) {
57         return MAA_ERROR_PLATFORM_ALREADY_INITIALISED;
58     }
59 #ifdef SWIGPYTHON
60     // Initialise python threads, this allows use to grab the GIL when we are
61     // required to do so
62     Py_InitializeEx(0);
63     PyEval_InitThreads();
64 #endif
65     plat = maa_intel_galileo_rev_d();
66     return MAA_SUCCESS;
67 }
68
69 int
70 maa_set_priority(const unsigned int priority)
71 {
72     struct sched_param sched_s;
73
74     memset(&sched_s, 0, sizeof(struct sched_param));
75     if (priority > sched_get_priority_max(SCHED_RR)) {
76         sched_s.sched_priority = sched_get_priority_max(SCHED_RR);
77     }
78     else {
79         sched_s.sched_priority = priority;
80     }
81
82     return sched_setscheduler(0, SCHED_RR, &sched_s);
83 }
84
85 static maa_result_t
86 maa_setup_mux_mapped(maa_pin_t meta)
87 {
88     int mi;
89     for (mi = 0; mi < meta.mux_total; mi++) {
90         maa_gpio_context mux_i;
91         mux_i = maa_gpio_init_raw(meta.mux[mi].pin);
92         if (mux_i == NULL)
93             return MAA_ERROR_INVALID_HANDLE;
94         if (maa_gpio_dir(mux_i, MAA_GPIO_OUT) != MAA_SUCCESS)
95             return MAA_ERROR_INVALID_RESOURCE;
96         if (maa_gpio_write(mux_i, meta.mux[mi].value) != MAA_SUCCESS)
97             return MAA_ERROR_INVALID_RESOURCE;
98     }
99     return MAA_SUCCESS;
100 }
101
102 unsigned int
103 maa_setup_gpio(int pin)
104 {
105     if (plat == NULL)
106         return -1;
107
108     if (pin < 0 || pin > plat->phy_pin_count)
109         return -1;
110
111     if(plat->pins[pin].capabilites.gpio != 1)
112       return -1;
113
114     if (plat->pins[pin].gpio.mux_total > 0)
115        if (maa_setup_mux_mapped(plat->pins[pin].gpio) != MAA_SUCCESS)
116             return -1;
117     return plat->pins[pin].gpio.pinmap;
118 }
119
120 unsigned int
121 maa_setup_aio(int aio)
122 {
123     if (plat == NULL)
124         return -3;
125
126     if (aio < 0 || aio > plat->aio_count)
127         return -1;
128
129     int pin = aio + plat->gpio_count;
130
131     if (plat->pins[pin].capabilites.aio != 1)
132       return -1;
133
134     if (plat->pins[pin].aio.mux_total > 0)
135        if (maa_setup_mux_mapped(plat->pins[pin].aio) != MAA_SUCCESS)
136             return -1;
137     return plat->pins[pin].aio.pinmap;
138 }
139
140 unsigned int
141 maa_setup_i2c(int bus)
142 {
143     if (plat == NULL)
144         return -3;
145
146     if (plat->i2c_bus_count >! 0) {
147         fprintf(stderr, "No i2c buses defined in platform");
148         return -1;
149     }
150     if (bus >= plat->i2c_bus_count) {
151         fprintf(stderr, "Above i2c bus count");
152         return -1;
153     }
154
155     int pos = plat->i2c_bus[bus].sda;
156     if (plat->pins[pos].i2c.mux_total > 0)
157         if (maa_setup_mux_mapped(plat->pins[pos].i2c) != MAA_SUCCESS)
158              return -2;
159
160     pos = plat->i2c_bus[bus].scl;
161     if (plat->pins[pos].i2c.mux_total > 0)
162         if (maa_setup_mux_mapped(plat->pins[pos].i2c) != MAA_SUCCESS)
163              return -2;
164
165     return plat->i2c_bus[bus].bus_id;
166 }
167
168 maa_spi_bus_t*
169 maa_setup_spi(int bus)
170 {
171     if (plat == NULL)
172         return NULL;
173
174     if (plat->spi_bus_count >! 0) {
175         fprintf(stderr, "No spi buses defined in platform");
176         return NULL;
177     }
178     if (bus >= plat->spi_bus_count) {
179         fprintf(stderr, "Above spi bus count");
180         return NULL;
181     }
182
183     int pos = plat->spi_bus[bus].sclk;
184     if (plat->pins[pos].spi.mux_total > 0)
185         if (maa_setup_mux_mapped(plat->pins[pos].spi) != MAA_SUCCESS)
186              return NULL;
187
188     pos = plat->spi_bus[bus].mosi;
189     if (plat->pins[pos].spi.mux_total > 0)
190         if (maa_setup_mux_mapped(plat->pins[pos].spi) != MAA_SUCCESS)
191              return NULL;
192
193     pos = plat->spi_bus[bus].miso;
194     if (plat->pins[pos].spi.mux_total > 0)
195         if (maa_setup_mux_mapped(plat->pins[pos].spi) != MAA_SUCCESS)
196              return NULL;
197
198     maa_spi_bus_t *spi = &(plat->spi_bus[bus]);
199     return spi;
200 }
201
202 maa_pin_t*
203 maa_setup_pwm(int pin)
204 {
205     if (plat == NULL)
206         return NULL;
207
208     if (plat->pins[pin].capabilites.pwm != 1)
209         return NULL;
210
211     if (plat->pins[pin].capabilites.gpio == 1) {
212         maa_gpio_context mux_i;
213         mux_i = maa_gpio_init_raw(plat->pins[pin].gpio.pinmap);
214         if (mux_i == NULL)
215             return NULL;
216         if (maa_gpio_dir(mux_i, MAA_GPIO_OUT) != MAA_SUCCESS)
217             return NULL;
218         // Current REV D quirk. //TODO GEN 2
219         if (maa_gpio_write(mux_i, 1) != MAA_SUCCESS)
220             return NULL;
221         if (maa_gpio_close(mux_i) != MAA_SUCCESS)
222             return NULL;
223     }
224
225     if (plat->pins[pin].pwm.mux_total > 0)
226        if (maa_setup_mux_mapped(plat->pins[pin].pwm) != MAA_SUCCESS)
227             return NULL;
228
229     maa_pin_t *ret;
230     ret = (maa_pin_t*) malloc(sizeof(maa_pin_t));
231     ret->pinmap = plat->pins[pin].pwm.pinmap;
232     ret->parent_id = plat->pins[pin].pwm.parent_id;
233     return ret;
234 }
235
236 void
237 maa_result_print(maa_result_t result)
238 {
239     switch (result) {
240         case MAA_SUCCESS: fprintf(stderr, "MAA: SUCCESS\n");
241                           break;
242         case MAA_ERROR_FEATURE_NOT_IMPLEMENTED:
243                           fprintf(stderr, "MAA: Feature not implemented.\n");
244                           break;
245         case MAA_ERROR_FEATURE_NOT_SUPPORTED:
246                           fprintf(stderr, "MAA: Feature not supported by Hardware.\n");
247                           break;
248         case MAA_ERROR_INVALID_VERBOSITY_LEVEL:
249                           fprintf(stderr, "MAA: Invalid verbosity level.\n");
250                           break;
251         case MAA_ERROR_INVALID_PARAMETER:
252                           fprintf(stderr, "MAA: Invalid parameter.\n");
253                           break;
254         case MAA_ERROR_INVALID_HANDLE:
255                           fprintf(stderr, "MAA: Invalid Handle.\n");
256                           break;
257         case MAA_ERROR_NO_RESOURCES:
258                           fprintf(stderr, "MAA: No resources.\n");
259                           break;
260         case MAA_ERROR_INVALID_RESOURCE:
261                           fprintf(stderr, "MAA: Invalid resource.\n");
262                           break;
263         case MAA_ERROR_INVALID_QUEUE_TYPE:
264                           fprintf(stderr, "MAA: Invalid Queue Type.\n");
265                           break;
266         case MAA_ERROR_NO_DATA_AVAILABLE:
267                           fprintf(stderr, "MAA: No Data available.\n");
268                           break;
269         case MAA_ERROR_INVALID_PLATFORM:
270                           fprintf(stderr, "MAA: Platform not recognised.\n");
271                           break;
272         case MAA_ERROR_PLATFORM_NOT_INITIALISED:
273                           fprintf(stderr, "MAA: Platform not initialised.\n");
274                           break;
275         case MAA_ERROR_PLATFORM_ALREADY_INITIALISED:
276                           fprintf(stderr, "MAA: Platform already initialised.\n");
277                           break;
278         case MAA_ERROR_UNSPECIFIED:
279                           fprintf(stderr, "MAA: Unspecified Error.\n");
280                           break;
281         default:     fprintf(stderr, "MAA: Unrecognised error.\n");
282                           break;
283     }
284 }
285
286 maa_boolean_t
287 maa_pin_mode_test(int pin, maa_pinmodes_t mode)
288 {
289     if (plat == NULL) {
290         maa_init();
291         if (plat == NULL)
292             return 0;
293     }
294     if (pin > plat->phy_pin_count || pin < 0)
295         return 0;
296
297     switch(mode) {
298         case MAA_PIN_VALID:
299             if (plat->pins[pin].capabilites.valid == 1)
300                 return 1;
301             break;
302         case MAA_PIN_GPIO:
303             if (plat->pins[pin].capabilites.gpio ==1)
304                 return 1;
305             break;
306         case MAA_PIN_PWM:
307             if (plat->pins[pin].capabilites.pwm ==1)
308                 return 1;
309             break;
310         case MAA_PIN_FAST_GPIO:
311             if (plat->pins[pin].capabilites.fast_gpio ==1)
312                 return 1;
313             break;
314         case MAA_PIN_SPI:
315             if (plat->pins[pin].capabilites.spi ==1)
316                 return 1;
317             break;
318         case MAA_PIN_I2C:
319             if (plat->pins[pin].capabilites.i2c ==1)
320                 return 1;
321             break;
322         case MAA_PIN_AIO:
323             if (pin < plat->aio_count)
324                 pin = pin + plat->gpio_count;
325             if (plat->pins[pin].capabilites.aio ==1)
326                 return 1;
327             break;
328         default: break;
329     }
330     return 0;
331 }
332
333 maa_mmap_pin_t*
334 maa_setup_mmap_gpio(int pin)
335 {
336     if (plat == NULL)
337         return NULL;
338
339     if (plat->pins[pin].capabilites.fast_gpio != 1)
340         return NULL;
341
342     if (plat->pins[pin].mmap.gpio.mux_total > 0)
343        if (maa_setup_mux_mapped(plat->pins[pin].mmap.gpio) != MAA_SUCCESS)
344             return NULL;
345
346     if (maa_setup_mux_mapped(plat->pins[pin].mmap.gpio) != MAA_SUCCESS)
347             return NULL;
348     maa_mmap_pin_t *ret = &(plat->pins[pin].mmap);
349     return ret;
350 }