swig: add unexport() calls to be used by destructors in object api
[contrib/mraa.git] / src / gpio / gpio.c
1 /*
2  * Author: Thomas Ingleby <thomas.c.ingleby@intel.com>
3  * Copyright (c) 2014 Intel Corporation.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24
25 #include <stdlib.h>
26 #include <fcntl.h>
27 #include <stdio.h>
28 #include <unistd.h>
29
30 #include "gpio.h"
31
32 static int
33 maa_gpio_get_valfp(maa_gpio_context *dev)
34 {
35     char bu[64];
36     sprintf(bu, "/sys/class/gpio/gpio%d/value", dev->pin);
37
38     if ((dev->value_fp = fopen(bu, "r+b")) == NULL) {
39         return 1;
40     }
41     return 0;
42 }
43
44 maa_gpio_context*
45 maa_gpio_init(int pin)
46 {
47     int pinm = maa_check_gpio(pin);
48     if (pinm < 0)
49         return NULL;
50     return maa_gpio_init_raw(pinm);
51 }
52
53 maa_gpio_context*
54 maa_gpio_init_raw(int pin)
55 {
56     if(pin < 0)
57         return NULL;
58     FILE *export_f;
59     maa_gpio_context* dev = (maa_gpio_context*) malloc(sizeof(maa_gpio_context));
60
61     if ((export_f = fopen("/sys/class/gpio/export", "w")) == NULL) {
62         fprintf(stderr, "Failed to open export for writing!\n");
63         return NULL;
64     } else {
65         fprintf(export_f, "%d", pin);
66         fclose(export_f);
67     }
68     dev->pin = pin;
69     return dev;
70 }
71
72 maa_result_t
73 maa_gpio_mode(maa_gpio_context *dev, gpio_mode_t mode)
74 {
75     if (dev->value_fp != NULL) {
76          dev->value_fp = NULL;
77     }
78     char filepath[64];
79     snprintf(filepath, 64, "/sys/class/gpio/gpio%d/drive", dev->pin);
80
81     FILE *drive;
82     if ((drive = fopen(filepath, "w")) == NULL) {
83         fprintf(stderr, "Failed to open drive for writing!\n");
84         return MAA_ERROR_INVALID_RESOURCE;
85     }
86     switch(mode) {
87         case MAA_GPIO_STRONG:
88             fprintf(drive, "strong");
89             break;
90         case MAA_GPIO_PULLUP:
91             fprintf(drive, "pullup");
92             break;
93         case MAA_GPIO_PULLDOWN:
94             fprintf(drive, "pulldown");
95             break;
96         case MAA_GPIO_HIZ:
97             fprintf(drive, "hiz");
98             break;
99         default:
100             fclose(drive);
101             return MAA_ERROR_FEATURE_NOT_IMPLEMENTED;
102             break;
103     }
104     fclose(drive);
105     dev->value_fp = NULL;
106     return MAA_SUCCESS;
107 }
108
109 maa_result_t
110 maa_gpio_dir(maa_gpio_context *dev, gpio_dir_t dir)
111 {
112     if (dev == NULL)
113         return MAA_ERROR_INVALID_HANDLE;
114     if (dev->value_fp != NULL) {
115          dev->value_fp = NULL;
116     }
117     char filepath[64];
118     snprintf(filepath, 64, "/sys/class/gpio/gpio%d/direction", dev->pin);
119
120     FILE *direction;
121     if ((direction = fopen(filepath, "w")) == NULL) {
122         fprintf(stderr, "Failed to open direction for writing!\n");
123         return MAA_ERROR_INVALID_RESOURCE;
124     }
125     switch(dir) {
126         case MAA_GPIO_OUT:
127             fprintf(direction, "out");
128             break;
129         case MAA_GPIO_IN:
130             fprintf(direction, "in");
131             break;
132         default:
133             fclose(direction);
134             return MAA_ERROR_FEATURE_NOT_IMPLEMENTED;
135             break;
136     }
137     fclose(direction);
138     dev->value_fp = NULL;
139     return MAA_SUCCESS;
140 }
141
142 int
143 maa_gpio_read(maa_gpio_context *dev)
144 {
145     if (dev->value_fp == NULL) {
146         maa_gpio_get_valfp(dev);
147     }
148     fseek(dev->value_fp, SEEK_SET, 0);
149     char buffer[2];
150     fread(buffer, 2, 1, dev->value_fp);
151     fseek(dev->value_fp, SEEK_SET, 0);
152     return atoi(buffer);
153 }
154
155 maa_result_t
156 maa_gpio_write(maa_gpio_context *dev, int value)
157 {
158     if (dev->value_fp == NULL) {
159         maa_gpio_get_valfp(dev);
160     }
161     if (fseek(dev->value_fp, SEEK_SET, 0) != 0) {
162         return MAA_ERROR_INVALID_RESOURCE;
163     }
164     fprintf(dev->value_fp, "%d", value);
165     if (fseek(dev->value_fp, SEEK_SET, 0) != 0) {
166         return MAA_ERROR_INVALID_RESOURCE;
167     }
168     if (ferror(dev->value_fp) != 0)
169         return MAA_ERROR_INVALID_RESOURCE;
170     return MAA_SUCCESS;
171 }
172
173 maa_result_t
174 maa_gpio_unexport(maa_gpio_context *dev)
175 {
176     FILE *unexport_f;
177
178     if ((unexport_f = fopen("/sys/class/gpio/unexport", "w")) == NULL) {
179         fprintf(stderr, "Failed to open unexport for writing!\n");
180         return MAA_ERROR_INVALID_RESOURCE;
181     }
182     fprintf(unexport_f, "%d", dev->pin);
183     fclose(unexport_f);
184     if (ferror(dev->value_fp) != 0)
185         return MAA_ERROR_INVALID_RESOURCE;
186 }
187
188 maa_result_t
189 maa_gpio_close(maa_gpio_context *dev)
190 {
191     maa_gpio_unexport(dev);
192     free(dev);
193     return MAA_SUCCESS;
194 }