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\n");
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
00140 char buf[81];
00141
00142 bool state[BUTTONS];
00143
00144 int event[BUTTONS*2] = {Event::N900LensOpened,
00145 Event::N900LensClosed,
00146 Event::FocusPressed,
00147 Event::FocusReleased,
00148 Event::ShutterPressed,
00149 Event::ShutterReleased,
00150 Event::N900SlideOpened,
00151 Event::N900SlideClosed
00152 };
00153
00154 std::string descriptions[BUTTONS*2] = {"Lens cover opened",
00155 "Lens cover closed",
00156 "Focus button pressed",
00157 "Focus button released",
00158 "Shutter button pressed",
00159 "Shutter button released",
00160 "Keyboard slide opened",
00161 "Keyboard slide closed"
00162 };
00163
00164
00165 int rval;
00166 struct pollfd fds[BUTTONS];
00167 for (int i = 0; i < BUTTONS; i++) {
00168 fds[i].fd = open(fnames[i], O_RDONLY);
00169 fds[i].events = POLLPRI;
00170 fds[i].revents = 0;
00171 }
00172
00173
00174 for (int i = 0; i < BUTTONS; i++) {
00175 rval = read(fds[i].fd, &buf, 80);
00176 buf[rval] = 0;
00177 switch (buf[0]) {
00178 case 'c':
00179 case 'i':
00180 state[i] = false;
00181 break;
00182 case 'o':
00183 case 'a':
00184 state[i] = true;
00185 break;
00186 default:
00187 error(Event::InternalError, "ButtonListener: Unknown state: %s", buf);
00188 }
00189 }
00190
00191 while (!stop) {
00192
00193 rval = poll(fds, BUTTONS, 1000);
00194 if (rval == -1) {
00195
00196 dprintf(2, "ButtonListener: poll failed\n");
00197
00198 continue;
00199 }
00200 if (rval == 0) { continue; }
00201
00202 for (int i = 0; i < BUTTONS; i++) {
00203 if (fds[i].revents & POLLPRI) {
00204 close(fds[i].fd);
00205 fds[i].fd = open(fnames[i], O_RDONLY, 0);
00206 rval = read(fds[i].fd, &buf, 80);
00207 buf[rval] = 0;
00208 switch (buf[0]) {
00209 case 'c':
00210 case 'i':
00211 if (state[i] != false) {
00212 state[i] = false;
00213 postEvent(event[i*2+1], 0, descriptions[i*2+1]);
00214 }
00215 break;
00216 case 'o':
00217 case 'a':
00218 if (state[i] != true) {
00219 state[i] = true;
00220 postEvent(event[i*2], 0, descriptions[i*2]);
00221 }
00222 break;
00223 default:
00224 error(Event::InternalError, "ButtonListener: Unknown state: %s", buf);
00225 }
00226 }
00227 }
00228 }
00229
00230 dprintf(2, "Button listener shutting down\n");
00231
00232 for (int i = 0; i < BUTTONS; i++) {
00233 close(fds[i].fd);
00234 }
00235 close(lockFD);
00236 }
00237 }
00238 }
00239
00240