• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

src/N900/ButtonListener.cpp

00001 #include <stdlib.h>
00002 #include <stdio.h>
00003 #include <errno.h>
00004 #include <sys/fcntl.h>
00005 #include <poll.h>
00006 #include <unistd.h>
00007 #include <sstream>
00008 
00009 #include "FCam/Event.h" 
00010 #include "FCam/Time.h" 
00011 
00012 #include "ButtonListener.h"
00013 #include "../Debug.h"
00014 
00015 
00016 
00017 
00018 namespace FCam { 
00019     namespace N900 {
00020 
00021         void *button_listener_thread_(void *arg) {
00022             ButtonListener *b = (ButtonListener *)arg;
00023             b->run();    
00024             pthread_exit(NULL);
00025             return NULL;
00026         }
00027         
00028         ButtonListener *ButtonListener::instance() {
00029             if (!_instance) {
00030                 _instance = new ButtonListener;
00031             }
00032             return _instance;
00033         }
00034         
00035         ButtonListener::ButtonListener() : stop(false) {
00036             pthread_attr_t attr;
00037             struct sched_param param;
00038             
00039             // make the thread
00040             
00041             param.sched_priority = sched_get_priority_max(SCHED_OTHER);            
00042             
00043             pthread_attr_init(&attr);
00044             
00045             if ((errno =
00046                  -(pthread_attr_setschedparam(&attr, &param) ||
00047                    pthread_attr_setschedpolicy(&attr, SCHED_OTHER) ||
00048                    pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) ||
00049                    pthread_create(&thread, &attr, button_listener_thread_, this)))) {
00050                 error(Event::InternalError, "Error creating button listener thread");
00051             }
00052 
00053         }
00054 
00055         ButtonListener::~ButtonListener() {
00056             stop = true;
00057             pthread_join(thread, NULL);
00058         }
00059 
00060         void ButtonListener::run() {
00061             // TODO: The below is a horrible hack to prevent the built-in
00062             // camera program from stealing shutter press events. I really
00063             // wish there was a better way to do this.
00064             
00065             // kill the built-in camera program if it was launched at boot
00066             if (!fork()) {
00067                 dprintf(2, "Killing camera-ui using dsmetool\n");
00068                 // suppress output
00069                 close(STDOUT_FILENO);
00070                 close(STDERR_FILENO);
00071                 execl("/usr/sbin/dsmetool",
00072                       "/usr/sbin/dsmetool",
00073                       "-k", "/usr/bin/camera-ui",
00074                       (char *)NULL);
00075                 exit(0);
00076             }
00077             
00078             if (!fork()) {
00079                 // Give the dsmetool a chance to do it's thing                
00080                 usleep(100000);
00081                 dprintf(2, "Killing camera-ui using killall\n");
00082                 // suppress output
00083                 close(STDOUT_FILENO);
00084                 close(STDERR_FILENO);
00085                 execl("/usr/bin/killall", "/usr/bin/killall", "camera-ui", (char *)NULL);
00086                 exit(0);
00087             }
00088             
00089             const int BUTTONS = 4;
00090 
00091             const char *fnames[BUTTONS] = {"/sys/devices/platform/gpio-switch/cam_shutter/state",
00092                                            "/sys/devices/platform/gpio-switch/cam_focus/state",
00093                                            "/sys/devices/platform/gpio-switch/cam_launch/state",
00094                                            "/sys/devices/platform/gpio-switch/slide/state"};
00095                                                
00096             char buf[81];
00097 
00098             bool state[BUTTONS];
00099 
00100             int event[BUTTONS*2] = {Event::N900LensOpened,
00101                                     Event::N900LensClosed,
00102                                     Event::FocusPressed,
00103                                     Event::FocusReleased,
00104                                     Event::ShutterPressed,
00105                                     Event::ShutterReleased,
00106                                     Event::N900SlideOpened,
00107                                     Event::N900SlideClosed};
00108 
00109             std::string descriptions[BUTTONS*2] = {"Lens cover opened",
00110                                                    "Lens cover closed",
00111                                                    "Focus button pressed",
00112                                                    "Focus button released",
00113                                                    "Shutter button pressed",
00114                                                    "Shutter button released",
00115                                                    "Keyboard slide opened",
00116                                                    "Keyboard slide closed"};
00117 
00118             // open all the devices
00119             int rval;
00120             struct pollfd fds[BUTTONS];
00121             for (int i = 0; i < BUTTONS; i++) {
00122                 fds[i].fd = open(fnames[i], O_RDONLY);
00123                 fds[i].events = POLLPRI;
00124                 fds[i].revents = 0;
00125             }
00126 
00127             // read the initial state
00128             for (int i = 0; i < BUTTONS; i++) {
00129                 rval = read(fds[i].fd, &buf, 80);
00130                 buf[rval] = 0;
00131                 switch (buf[0]) {
00132                 case 'c': // closed
00133                 case 'i': // inactive
00134                     state[i] = false;
00135                     break;
00136                 case 'o': // open
00137                 case 'a': // active
00138                     state[i] = true;
00139                     break;
00140                 default:                    
00141                     error(Event::InternalError, "ButtonListener: Unknown state: %s", buf);
00142                 }
00143             }            
00144 
00145             while (!stop) {               
00146                 // wait for a change
00147                 rval = poll(fds, BUTTONS, 1000);
00148                 if (rval == -1) {
00149                     // this fails once on load, not sure why
00150                     dprintf(2, "ButtonListener: poll failed");
00151                     //error(Event::InternalError, "ButtonListener: poll failed");
00152                     continue;
00153                 }
00154                 if (rval == 0) continue; // timeout
00155 
00156                 for (int i = 0; i < BUTTONS; i++) {
00157                     if (fds[i].revents & POLLPRI) {
00158                         close(fds[i].fd);
00159                         fds[i].fd = open(fnames[i], O_RDONLY, 0);
00160                         rval = read(fds[i].fd, &buf, 80);
00161                         buf[rval] = 0;
00162                         switch (buf[0]) {
00163                         case 'c': // closed
00164                         case 'i': // inactive
00165                             if (state[i] != false) {
00166                                 state[i] = false;
00167                                 postEvent(event[i*2+1], 0, descriptions[i*2+1]);
00168                             }
00169                             break;
00170                         case 'o': // open
00171                         case 'a': // active
00172                             if (state[i] != true) {
00173                                 state[i] = true;
00174                                 postEvent(event[i*2], 0, descriptions[i*2]);
00175                             }
00176                             break;
00177                         default:
00178                             error(Event::InternalError, "ButtonListener: Unknown state: %s", buf);
00179                         }
00180                     }
00181                 }                
00182             }
00183 
00184             dprintf(2, "Button listener shutting down\n");
00185 
00186             for (int i = 0; i < BUTTONS; i++) {
00187                 close(fds[i].fd);
00188             }
00189             
00190             // restart the built-in camera program
00191             if (!fork()) {
00192                 // on success, this function never returns
00193                 execl("/usr/sbin/dsmetool", 
00194                       "/usr/sbin/dsmetool", 
00195                       "-U", "user", 
00196                       "-o", "/usr/bin/camera-ui", 
00197                       (char *)NULL);
00198                 // it returned, so there was a failure
00199                 error(Event::InternalError, "Error restarting camera-ui");
00200                 exit(0);
00201             }
00202         }
00203 
00204         ButtonListener *ButtonListener::_instance = NULL;
00205     }
00206 }
00207 
00208 

Generated on Thu Jul 15 2010 17:51:28 for FCam by  doxygen 1.7.1