RaspberrPi project source code
Guo Wenxue
5 days ago f7889e2ceddbc3e15ea4b5377d831f4432169f76
commit | author | age
e30a4c 1 /*********************************************************************************
GW 2  *      Copyright:  (C) 2019 LingYun IoT System Studio
3  *                  All rights reserved.
4  *
5  *       Filename:  gpio.c
6  *    Description:  This file is GPIO input/output functions
7  *
8  *        Version:  1.0.0(2019年06月24日)
9  *         Author:  Guo Wenxue <guowenxue@gmail.com>
10  *      ChangeLog:  1, Release initial version on "2019年06月24日 23时46分47秒"
11  *
12  ********************************************************************************/
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <fcntl.h>
18 #include <dirent.h>
19 #include <string.h>
20 #include <time.h>
21 #include <errno.h>
22
23 #include "logger.h"
24 #include "util_proc.h"
25 #include "gpio.h"
26
27 #define RPI_GPIONAME        "gpiochip0"
28
29 static struct gpiod_chip    *s_chip;
30 static gpio_t               *s_gpio = NULL;
31
32 int gpio_init(gpio_t *gpio)
33 {
34     int                 i;
35     int                 rv;
36
37     s_gpio = gpio;
38
39     if( !gpio )
40     {
41         log_error("Invalid input arguments $gpio\n");
42         return -1;
43     }
44
45
46     if( !gpio->incnt && !gpio->outcnt )
47     {
48         log_warn("WARNNING: No GPIO pins configured\n");
49         return 0;
50     }
51
52     /*  gpiod open chip */
53     s_chip = gpiod_chip_open_by_name(RPI_GPIONAME);
54     if( !s_chip )
55     {
56         log_error("gpiod open chip failure, maybe you need running as root\n");
57         return -2;
58     }
59     log_info("gpiod initialise open chip ok\n");
60
61
62     /*  gpiod request all output pins */
63     for(i=0; i<gpio->outcnt; i++)
64     {
65         gpio->output[i].line = gpiod_chip_get_line(s_chip, gpio->output[i].pin);
66         if( !gpio->output[i].line )
67         {
68             log_error("gpiod get line for '%s' pin[#%d] failure\n", gpio->output[i].name, gpio->output[i].pin );
69             return -2;
70         }
71
72         if( gpiod_line_request_output(gpio->output[i].line, gpio->output[i].name, !gpio->output[i].active_level) < 0 )
73         {
74             log_error("gpiod request '%s' pin[#%d] output failure: %s\n", gpio->output[i].name, gpio->output[i].pin, strerror(errno));
75         }
76         else
77         {
78             log_info("gpiod request '%s' pin[#%d] output ok\n", gpio->output[i].name, gpio->output[i].pin);
79         }
80     }
81
82
83     /*  gpiod request all input pins */
84     for(i=0; i<gpio->incnt; i++)
85     {
86         gpio->input[i].line = gpiod_chip_get_line(s_chip, gpio->input[i].pin);
87         if( !gpio->input[i].line )
88         {
89             log_error("gpiod get line for '%s' pin[#%d] failure\n", gpio->input[i].name, gpio->input[i].pin );
90             return -2;
91         }
92
93         if( gpio->output[i].active_level )
94             rv = gpiod_line_request_rising_edge_events(gpio->input[i].line, gpio->input[i].name) ;
95         else
96             rv = gpiod_line_request_falling_edge_events(gpio->input[i].line, gpio->input[i].name) ;
97
98         if( rv < 0 )
99         {
100             log_error("gpiod request '%s' pin[#%d] event edge [%s] failure: %s\n",
101                     gpio->input[i].name, gpio->input[i].pin, gpio->output[i].active_level?"rising":"falling", strerror(errno));
102         }
103         else
104         {
105             log_info("gpiod request '%s' pin[#%d] event edge [%s] ok\n",
106                     gpio->input[i].name, gpio->input[i].pin, gpio->output[i].active_level?"rising":"falling");
107         }
108     }
109
110     return 0;
111 }
112
113
114 void gpio_term(void)
115 {
116     int              i;
117
118     log_info("start teriminated GPIO\n");
119
120     if( !s_gpio->incnt && !s_gpio->outcnt )
121     {
122         return ;
123     }
124
125
126     for(i=0; i<s_gpio->outcnt; i++)
127     {
128         gpiod_line_release(s_gpio->output[i].line);
129     }
130
131
132     for(i=0; i<s_gpio->incnt; i++)
133     {
134         gpiod_line_release(s_gpio->input[i].line);
135     }
136
137     gpiod_chip_close(s_chip);
138 }
139
140 void gpio_out(char *name, char *cmd)
141 {
142     int              i;
143     int              found = 0;
144
145     for( i=0; i<s_gpio->outcnt; i++ )
146     {
147         if( !strncasecmp(s_gpio->output[i].name, name, strlen(name)))
148         {
149             found = 1;
150             break;
151         }
152     }
153
154     if( !found )
155     {
156         log_error("GPIO output for '%s' pin not found\n", name);
157         return ;
158     }
159
160     if( strstr(cmd, "on") )
161     {
162         gpiod_line_set_value(s_gpio->output[i].line, s_gpio->output[i].active_level);
163     }
164     else if( strstr(cmd, "off") )
165     {
166         gpiod_line_set_value(s_gpio->output[i].line, !s_gpio->output[i].active_level);
167     }
168
169     return ;
170 }
171
172
173 void *light_on_worker(void *arg)
174 {
175     int                      i;
176     int                      found = 0;
177     char                    *name = (char *)arg;
178     gpio_info_t             *gpiout;
179
180     if( !name )
181     {
182         log_error("Invalid input arugment\n");
183         return NULL;
184     }
185
186     if( s_gpio->light_intval <= 0 )
187     {
188         log_error("Invalid light_intval value[%d] in configure file\n", s_gpio->light_intval);
189         return NULL;
190     }
191
192     for(i=0; i<s_gpio->outcnt; i++)
193     {
194         if( strstr(s_gpio->output[i].name, name) )
195         {
196             gpiout = &(s_gpio->output[i]);
197             found = 1;
198         }
199     }
200
201     if( !found )
202     {
203         log_error("Light '%s' not found\n", name);
204         return NULL;
205     }
206
207     log_info("Trun on %s for [%d] seconds\n", gpiout->name, s_gpio->light_intval);
208
209     gpio_out(gpiout->name, "on");
210     sleep(s_gpio->light_intval);
211     gpio_out(gpiout->name, "off");
212
213     return NULL;
214 }
215
216 /* Return value: 0(LOW): Nobody detected, !0: indoor or hallway detected */
217 int infrared_detect(void)
218 {
219     int                      i;
220     int                      rv = 0;
221     int                      res = 0;
222
223     struct gpiod_line_event  ev;
224     struct gpiod_line_bulk   bulk, event_bulk;
225     struct gpiod_line       *line;
226
227     int                      num_lines = 0;
228
229
230     gpiod_line_bulk_init(&bulk);
231
232     for(i=0; i<s_gpio->incnt; i++)
233     {
234         if( strstr(s_gpio->input[i].name, "infrared"))
235         {
236             gpiod_line_bulk_add(&bulk, s_gpio->input[i].line);
237             num_lines ++;
238         }
239     }
240
241     if( !num_lines )
242     {
243         log_error("No infrared detect gpiod lines found\n");
244         return 0;
245     }
246
247     log_debug("infrared start detect event now...\n");
248     rv = gpiod_line_event_wait_bulk(&bulk, NULL, &event_bulk);
249     if( rv <= 0 )
250     {
251         log_error("infrared gpiod line wait[%s] event failure!\n", s_gpio->input[i].name);
252         return 0;
253     }
254
255     for (i=0; i<num_lines; i++)
256     {
257         line = gpiod_line_bulk_get_line(&event_bulk, 0);
258
259         /* must call this function to  clear the event  */
260         rv = gpiod_line_event_read(line, &ev);
261         if( rv < 0)
262         {
263             log_error("gpiod_line_event_read get failure\n");
264             break;
265         }
266
267         for(i=0; i<s_gpio->incnt; i++)
268         {
269             if(line == s_gpio->input[i].line)
270             {
271                 if( s_gpio->input[i].active_level != gpiod_line_get_value(line) )
272                 {
f7889e 273                     //log_debug("infrared '%s' detect get wrong power level\n", s_gpio->input[i].name);
e30a4c 274                     continue;
GW 275                 }
276
277                 if( strstr(s_gpio->input[i].name, "indoor") )
278                 {
279                     log_debug("indoor infrared gpiod wait get event.\n", s_gpio->input[i].name);
280                     res |= FLAG_INFRARED_INDOOR;
281                 }
282                 else if( strstr(s_gpio->input[i].name, "hallway") )
283                 {
284                     log_debug("hallway infrared gpiod wait get event.\n", s_gpio->input[i].name);
285                     res |= FLAG_INFRARED_HALLWAY;
286                 }
287             }
288         }
289     }
290
291     return res;
292 }
293
294