00001 #include <stdlib.h>
00002 #include <stdio.h>
00003 #include <errno.h>
00004 #include <sys/fcntl.h>
00005 #include <sys/file.h>
00006 #include <poll.h>
00007 #include <unistd.h>
00008 #include <sstream>
00009
00010 #include "FCam/Event.h"
00011 #include "FCam/Time.h"
00012
00013 #include "ButtonListener.h"
00014 #include "../Debug.h"
00015
00016
00017
00018
00019 namespace FCam {
00020 namespace N900 {
00021
00022 void *button_listener_thread_(void *arg) {
00023 ButtonListener *b = (ButtonListener *)arg;
00024 b->run();
00025 pthread_exit(NULL);
00026 return NULL;
00027 }
00028
00029 ButtonListener *ButtonListener::instance() {
00030
00031
00032
00033
00034
00035
00036
00037
00038 static ButtonListener _instance;
00039 return &_instance;
00040 }
00041
00042 ButtonListener::ButtonListener() : stop(false) {
00043 pthread_attr_t attr;
00044 struct sched_param param;
00045
00046
00047
00048 param.sched_priority = sched_get_priority_max(SCHED_OTHER);
00049
00050 pthread_attr_init(&attr);
00051
00052 if ((errno =
00053 -(pthread_attr_setschedparam(&attr, ¶m) ||
00054 pthread_attr_setschedpolicy(&attr, SCHED_OTHER) ||
00055 pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) ||
00056 pthread_create(&thread, &attr, button_listener_thread_, this)))) {
00057 error(Event::InternalError, "Error creating button listener thread");
00058 }
00059
00060 }
00061
00062 ButtonListener::~ButtonListener() {
00063 stop = true;
00064 pthread_join(thread, NULL);
00065 }
00066
00067 void ButtonListener::run() {
00068
00069
00070
00071
00072
00073 if (!fork()) {
00074 dprintf(2, "Killing camera-ui using dsmetool\n");
00075
00076 close(STDOUT_FILENO);
00077 close(STDERR_FILENO);
00078 execl("/usr/sbin/dsmetool",
00079 "/usr/sbin/dsmetool",
00080 "-k", "/usr/bin/camera-ui",
00081 (char *)NULL);
00082 exit(0);
00083 }
00084
00085 if (!fork()) {
00086
00087
00088
00089 usleep(100000);
00090 dprintf(2, "Killing camera-ui using killall\n");
00091 close(STDOUT_FILENO);
00092 close(STDERR_FILENO);
00093 execl("/usr/bin/killall", "/usr/bin/killall", "camera-ui", (char *)NULL);
00094 exit(0);
00095 }
00096
00097
00098
00099
00100
00101 int lockFD = open("/tmp/fcam.lock", O_RDWR | O_CREAT);
00102 int ret = flock(lockFD, LOCK_EX | LOCK_NB);
00103 if (ret == EWOULDBLOCK) {
00104
00105
00106
00107
00108 return;
00109 }
00110
00111 if (!fork()) {
00112
00113
00114
00115
00116 setpgrp();
00117
00118 close(lockFD);
00119
00120 flock(open("/tmp/fcam.lock", O_RDWR | O_CREAT), LOCK_EX);
00121
00122 dprintf(2, "Respawning camera-ui");
00123 close(STDOUT_FILENO);
00124 close(STDERR_FILENO);
00125 execl("/usr/sbin/dsmetool",
00126 "/usr/sbin/dsmetool",
00127 "-U", "user",
00128 "-o", "/usr/bin/camera-ui",
00129 (char *)NULL);
00130 }
00131
00132 const int BUTTONS = 4;
00133
00134 const char *fnames[BUTTONS] = {"/sys/devices/platform/gpio-switch/cam_shutter/state",
00135 "/sys/devices/platform/gpio-switch/cam_focus/state",
00136 "/sys/devices/platform/gpio-switch/cam_launch/state",
00137 "/sys/devices/platform/gpio-switch/slide/state"};
00138
00139 char buf[81];
00140
00141 bool state[BUTTONS];
00142
00143 int event[BUTTONS*2] = {Event::N900LensOpened,
00144 Event::N900LensClosed,
00145 Event::FocusPressed,
00146 Event::FocusReleased,
00147 Event::ShutterPressed,
00148 Event::ShutterReleased,
00149 Event::N900SlideOpened,
00150 Event::N900SlideClosed};
00151
00152 std::string descriptions[BUTTONS*2] = {"Lens cover opened",
00153 "Lens cover closed",
00154 "Focus button pressed",
00155 "Focus button released",
00156 "Shutter button pressed",
00157 "Shutter button released",
00158 "Keyboard slide opened",
00159 "Keyboard slide closed"};
00160
00161
00162 int rval;
00163 struct pollfd fds[BUTTONS];
00164 for (int i = 0; i < BUTTONS; i++) {
00165 fds[i].fd = open(fnames[i], O_RDONLY);
00166 fds[i].events = POLLPRI;
00167 fds[i].revents = 0;
00168 }
00169
00170
00171 for (int i = 0; i < BUTTONS; i++) {
00172 rval = read(fds[i].fd, &buf, 80);
00173 buf[rval] = 0;
00174 switch (buf[0]) {
00175 case 'c':
00176 case 'i':
00177 state[i] = false;
00178 break;
00179 case 'o':
00180 case 'a':
00181 state[i] = true;
00182 break;
00183 default:
00184 error(Event::InternalError, "ButtonListener: Unknown state: %s", buf);
00185 }
00186 }
00187
00188 while (!stop) {
00189
00190 rval = poll(fds, BUTTONS, 1000);
00191 if (rval == -1) {
00192
00193 dprintf(2, "ButtonListener: poll failed");
00194
00195 continue;
00196 }
00197 if (rval == 0) continue;
00198
00199 for (int i = 0; i < BUTTONS; i++) {
00200 if (fds[i].revents & POLLPRI) {
00201 close(fds[i].fd);
00202 fds[i].fd = open(fnames[i], O_RDONLY, 0);
00203 rval = read(fds[i].fd, &buf, 80);
00204 buf[rval] = 0;
00205 switch (buf[0]) {
00206 case 'c':
00207 case 'i':
00208 if (state[i] != false) {
00209 state[i] = false;
00210 postEvent(event[i*2+1], 0, descriptions[i*2+1]);
00211 }
00212 break;
00213 case 'o':
00214 case 'a':
00215 if (state[i] != true) {
00216 state[i] = true;
00217 postEvent(event[i*2], 0, descriptions[i*2]);
00218 }
00219 break;
00220 default:
00221 error(Event::InternalError, "ButtonListener: Unknown state: %s", buf);
00222 }
00223 }
00224 }
00225 }
00226
00227 dprintf(2, "Button listener shutting down\n");
00228
00229 for (int i = 0; i < BUTTONS; i++) {
00230 close(fds[i].fd);
00231 }
00232 close(lockFD);
00233 }
00234 }
00235 }
00236
00237