diff options
| author | Manuel Traut <manut@mecka.net> | 2013-01-16 20:50:58 +0100 |
|---|---|---|
| committer | Manuel Traut <manut@mecka.net> | 2013-01-16 20:50:58 +0100 |
| commit | 7ad35373a45f151c3a25cfabeb529bc04aecb580 (patch) | |
| tree | bba5319df6a4cb286f6ecb78efce9b30daf98924 | |
| parent | 33a7f9331cbce18c5f706ed614cbd7c04ef7a9da (diff) | |
io: generic_gpio - add input observation
inputs needs to be monitored for change.
this patch implements input monitoring based on a poll of the
sys/class/gpio/gpioX/value file
if raising, falling or both edges should be monitored can be configured
in the conf file.
Signed-off-by: Manuel Traut <manut@mecka.net>
| -rw-r--r-- | io/bin/generic_gpio/generic_gpio.cpp | 160 | ||||
| -rw-r--r-- | io/bin/generic_gpio/gpio.conf | 13 | ||||
| -rw-r--r-- | io/lib/distrio_io.h | 5 |
3 files changed, 150 insertions, 28 deletions
diff --git a/io/bin/generic_gpio/generic_gpio.cpp b/io/bin/generic_gpio/generic_gpio.cpp index f0e2145..cdf69f2 100644 --- a/io/bin/generic_gpio/generic_gpio.cpp +++ b/io/bin/generic_gpio/generic_gpio.cpp @@ -5,7 +5,11 @@ #include <ace/Task.h> #include <iostream> +#include <map> +#include <string> + #include <gpio.h> +#include <poll.h> #include "ini.h" @@ -18,25 +22,33 @@ static void err (const char *s) class GPIO : public Distrio_Digital_i { public: - GPIO (int _id, std::string name, ::Distrio::Direction dir) : - Distrio_Digital_i (name, dir) { - int ret = -1; - if (dir == ::Distrio::OUTPUT) - ret = gpio_open_dir (&p, _id, GPIO_OUT); - if (dir == ::Distrio::INPUT) - ret = gpio_open_dir (&p, _id, GPIO_IN); - if (ret) { - id(-1); - err ("open gpio failed\n"); - } else - id(0); + GPIO (std::string name, ::Distrio::Direction dir, gpio_pin _p) : + Distrio_Digital_i (name, dir) { p = _p; } + + int update_input (void) { + gpio_value v; + int ret = gpio_get_value (&p, &v); + + if (ret) { + std::cerr << "update gpio " << io_name << " failed: " << ret << std::endl; + return -1; + } + + update_timestamp (); + + if (val) + raise (); + else + fall (); } ::Distrio::Error *set () { if (gpio_set_value (&p, GPIO_HIGH)) - return distrio_error - (Distrio::E_NOTSUPPORTED, Distrio::L_NORMAL, MODULE_ID, "set gpio failed"); + return distrio_error (Distrio::E_NOTSUPPORTED, + Distrio::L_NORMAL, + MODULE_ID, + "set gpio failed"); update_timestamp (); val = 1; @@ -48,8 +60,10 @@ class GPIO : public Distrio_Digital_i { ::Distrio::Error *reset () { if (gpio_set_value (&p, GPIO_LOW)) - return distrio_error - (Distrio::E_NOTSUPPORTED, Distrio::L_NORMAL, MODULE_ID, "reset gpio failed"); + return distrio_error (Distrio::E_NOTSUPPORTED, + Distrio::L_NORMAL, + MODULE_ID, + "reset gpio failed"); update_timestamp (); val = 0; @@ -66,12 +80,56 @@ class GPIO : public Distrio_Digital_i { gpio_pin p; }; +class Input_observer : public ACE_Task < ACE_MT_SYNCH > { + public: + Input_observer (std::map <int, GPIO *> _input_list) { + input_list = _input_list; + } + ~Input_observer () { } + private: + std::map <int, GPIO *> input_list; + int svc (void) { + struct pollfd *fds = (struct pollfd *) + malloc (input_list.size () * sizeof (struct pollfd)); + int fd_cnt = 0; + + for (std::map <int, GPIO *> :: iterator it = input_list.begin (); + it != input_list.end (); + it++) + { + fds[fd_cnt].fd = it->first; + fds[fd_cnt].events = POLLPRI | POLLERR; + } + + while (1) { + int pos = 0; + int ret = poll (fds, input_list.size (), -1); + + while (ret > 0) { + if (fds [pos].revents) { + if (fds [pos].revents & POLLPRI) + input_list[pos]->update_input (); + ret--; + } + pos++; + if (pos > input_list.size ()) { + std::cerr << "fatal error in poll checker" << std::endl; + abort (); + } + } + } + } +}; ACE_TMAIN (int argc, ACE_TCHAR *argv[]) { int ret = 0, num = 0, i = 0; - std::list<GPIO *> io_list; - dictionary *d = _iniparser_load (GPIO_CONFIG); + std::map<int, GPIO *> input_list; + std::list<GPIO *> output_list; + Input_observer *obs; + dictionary *d; + + d = _iniparser_load (GPIO_CONFIG); if (!d) { err ("load inifile failed\n"); @@ -92,15 +150,20 @@ ACE_TMAIN (int argc, ACE_TCHAR *argv[]) return -EINVAL; for (i = 0; i < num; i++) { + GPIO *g; + gpio_pin p; ::Distrio::Direction dir; char tmp [255]; - char *name = _iniparser_getsecname (d, i); int id; + int rising = 0, falling = 0; + int ret = -1; char *direction; + char *name = _iniparser_getsecname (d, i); + sprintf (tmp, "%s:id", name); id = _iniparser_getint (d, tmp, -1); sprintf (tmp, "%s:direction", name); - direction = _iniparser_getstring (d, tmp, "unknown"); + direction = _iniparser_getstring (d, tmp, (char *) "unknown"); if (strcmp (direction, "in") == 0) dir = ::Distrio::INPUT; @@ -108,28 +171,73 @@ ACE_TMAIN (int argc, ACE_TCHAR *argv[]) dir = ::Distrio::OUTPUT; std::cout << " new gpio: " << id << ": " << name << std::endl; - GPIO *g = new GPIO (id, std::string (name), dir); - if (g->id () == -1) { - err ("create gpio object failed - hw error?\n"); - delete g; + if (dir == ::Distrio::OUTPUT) + ret = gpio_open_dir (&p, id, GPIO_OUT); + if (dir == ::Distrio::INPUT) + ret = gpio_open_dir (&p, id, GPIO_IN); + + if (ret) { + std::cerr << "open gpio: " << id << ": " << name << "failed" << std::endl; continue; } + if (dir == ::Distrio::INPUT) { + sprintf (tmp, "%s:rising", name); + rising = _iniparser_getint (d, tmp, -1); + sprintf (tmp, "%s:falling", name); + falling = _iniparser_getint (d, tmp, -1); + + if (((rising == -1) && (falling == -1)) || (!rising && !falling)) { + std::cout << "gpio: " << id << ": " << name; + std::cout << "no edge defined."; + std::cout << "events will be emitted on rising and falling edge"; + ret = gpio_enable_irq (&p, GPIO_BOTH); + } + else if (rising && falling) + ret = gpio_enable_irq (&p, GPIO_BOTH); + else if (rising) + ret = gpio_enable_irq (&p, GPIO_RISING); + else if (falling) + ret = gpio_enable_irq (&p, GPIO_FALLING); + else { + std::cerr << "gpio: " << id << ": " << name; + std::cerr << "no edge defined - gpio will be skipped." << std::endl; + continue; + } + + if (ret) { + std::cerr << "gpio: " << id << ": " << name; + std::cerr << "enable irq failed - gpio will be skipped." << std::endl; + continue; + } + } + + g = new GPIO (std::string (name), dir, p); + if (register_digital (g)) { err ("register gpio object at the manager failed\n"); delete g; continue; } + + if (dir == ::Distrio::INPUT) { + int fd = gpio_get_fd (&p); + input_list[fd] = g; + } else + output_list.push_back (g); + std::cout << "registered gpio " << name <<" with id: " << g->id () << std::endl; - io_list.push_back (g); } _iniparser_freedict (d); + obs = new Input_observer (input_list); + join_orb (); out: - /* io_list.erase (); */ + /* input_list.erase (); */ + /* output_list.erase (); */ return ret; } diff --git a/io/bin/generic_gpio/gpio.conf b/io/bin/generic_gpio/gpio.conf index 44068de..df70859 100644 --- a/io/bin/generic_gpio/gpio.conf +++ b/io/bin/generic_gpio/gpio.conf @@ -9,3 +9,16 @@ [keyboard] id = 272; direction = in; + rising = 1; + falling = 1; + +[button1] + id = 150; + direction = in; + rising = 1; + +[button2] + id = 151; + direction = in; + rising = 0; + falling = 1; diff --git a/io/lib/distrio_io.h b/io/lib/distrio_io.h index 997e305..d32dd7e 100644 --- a/io/lib/distrio_io.h +++ b/io/lib/distrio_io.h @@ -99,9 +99,9 @@ public: protected: ::CORBA::Long val; + std::string io_name; private: - std::string io_name; ::CORBA::Long io_id; std::list<Distrio::Device_ptr> cb_list_rise; std::list<Distrio::Device_ptr> cb_list_fall; @@ -164,8 +164,9 @@ public: virtual void id ( ::CORBA::Long id); -private: +protected: std::string io_name; +private: ::Distrio::Direction dir; ::CORBA::Long io_id; }; |
