Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(150)

Side by Side Diff: content/browser/geolocation/libgps_wrapper_linux.cc

Issue 8463022: Make chrome communicate with gpsd through libgps/shared memory (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: addressing joth@ 's comments Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/browser/geolocation/libgps_wrapper_linux.h ('k') | content/content_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/geolocation/libgps_wrapper_linux.h" 5 #include "content/browser/geolocation/libgps_wrapper_linux.h"
6 6
7 #include <math.h>
7 #include <dlfcn.h> 8 #include <dlfcn.h>
8 #include <errno.h> 9 #include <errno.h>
9 10
10 #include "base/logging.h" 11 #include "base/logging.h"
11 #include "base/stringprintf.h" 12 #include "base/stringprintf.h"
12 #include "content/common/geoposition.h" 13 #include "content/common/geoposition.h"
14 #include "third_party/gpsd/release-3.1/gps.h"
13 15
14 namespace { 16 COMPILE_ASSERT(GPSD_API_MAJOR_VERSION == 5, GPSD_API_version_is_not_5);
15 // Attempts to load dynamic library named |lib| and initialize the required 17 const char LIBGPS_VERSION[] = "libgps.so.20";
joth 2011/11/11 21:24:17 write this is: namespace { const char kLibGpsName
Yufeng Shen (Slow to review) 2011/11/11 21:35:03 Done.
16 // function pointers according to |mode|. Returns ownership a new instance 18
17 // of the library loader class, or NULL on failure. 19 LibGps::LibGps(void* dl_handle,
18 // TODO(joth): This is a hang-over from when we dynamically two different 20 gps_open_fn gps_open,
19 // versions of libgps and chose between them. Now we could remove at least one 21 gps_close_fn gps_close,
20 // layer of wrapper class and directly #include gps.h in this cc file. 22 gps_read_fn gps_read)
21 // See http://crbug.com/98132 and http://crbug.com/99177 23 : dl_handle_(dl_handle),
22 LibGpsLibraryWrapper* TryToOpen(const char* lib) { 24 gps_open_(gps_open),
23 void* dl_handle = dlopen(lib, RTLD_LAZY); 25 gps_close_(gps_close),
26 gps_read_(gps_read),
27 gps_data_(new gps_data_t),
28 is_open_(false) {
29 DCHECK(gps_open_);
30 DCHECK(gps_close_);
31 DCHECK(gps_read_);
32 }
33
34 LibGps::~LibGps() {
35 Stop();
36 if (dl_handle_) {
37 const int err = dlclose(dl_handle_);
38 DCHECK_EQ(0, err) << "Error closing dl handle: " << err;
39 }
40 }
41
42 LibGps* LibGps::New() {
43 void* dl_handle = dlopen(LIBGPS_VERSION, RTLD_LAZY);
24 if (!dl_handle) { 44 if (!dl_handle) {
25 VLOG(1) << "Could not open " << lib << ": " << dlerror(); 45 DLOG(WARNING) << "Could not open " << LIBGPS_VERSION << ": " << dlerror();
26 return NULL; 46 return NULL;
27 } 47 }
28 VLOG(1) << "Loaded " << lib; 48
49 DLOG(INFO) << "Loaded " << LIBGPS_VERSION;
29 50
30 #define DECLARE_FN_POINTER(function) \ 51 #define DECLARE_FN_POINTER(function) \
31 LibGpsLibraryWrapper::function##_fn function; \ 52 function##_fn function = reinterpret_cast<function##_fn>( \
32 function = reinterpret_cast<LibGpsLibraryWrapper::function##_fn>( \
33 dlsym(dl_handle, #function)); \ 53 dlsym(dl_handle, #function)); \
34 if (!function) { \ 54 if (!function) { \
35 LOG(WARNING) << "libgps " << #function << " error: " << dlerror(); \ 55 DLOG(WARNING) << "libgps " << #function << " error: " << dlerror(); \
36 dlclose(dl_handle); \ 56 dlclose(dl_handle); \
37 return NULL; \ 57 return NULL; \
38 } 58 }
39 DECLARE_FN_POINTER(gps_open); 59 DECLARE_FN_POINTER(gps_open);
40 DECLARE_FN_POINTER(gps_close); 60 DECLARE_FN_POINTER(gps_close);
41 DECLARE_FN_POINTER(gps_poll); 61 DECLARE_FN_POINTER(gps_read);
42 DECLARE_FN_POINTER(gps_stream); 62 // We don't use gps_shm_read() directly, just to make sure that libgps has
43 DECLARE_FN_POINTER(gps_waiting); 63 // the shared memory support.
64 typedef int (*gps_shm_read_fn)(struct gps_data_t*);
65 DECLARE_FN_POINTER(gps_shm_read);
44 #undef DECLARE_FN_POINTER 66 #undef DECLARE_FN_POINTER
45 67
46 return new LibGpsLibraryWrapper(dl_handle, 68 return new LibGps(dl_handle, gps_open, gps_close, gps_read);
47 gps_open,
48 gps_close,
49 gps_poll,
50 gps_stream,
51 gps_waiting);
52 }
53 } // namespace
54
55 LibGps::LibGps(LibGpsLibraryWrapper* dl_wrapper)
56 : library_(dl_wrapper) {
57 DCHECK(dl_wrapper != NULL);
58 }
59
60 LibGps::~LibGps() {
61 }
62
63 LibGps* LibGps::New() {
64 LibGpsLibraryWrapper* wrapper;
65 wrapper = TryToOpen("libgps.so.19");
66 if (wrapper)
67 return NewV294(wrapper);
68 wrapper = TryToOpen("libgps.so");
69 if (wrapper)
70 return NewV294(wrapper);
71 return NULL;
72 } 69 }
73 70
74 bool LibGps::Start() { 71 bool LibGps::Start() {
75 if (library().is_open()) 72 if (is_open_)
76 return true; 73 return true;
74
75 #if defined(OS_CHROMEOS)
77 errno = 0; 76 errno = 0;
78 static int fail_count = 0; 77 if (gps_open_(GPSD_SHARED_MEMORY, 0, gps_data_.get()) != 0) {
79 if (!library().open(NULL, NULL)) {
80 // See gps.h NL_NOxxx for definition of gps_open() error numbers. 78 // See gps.h NL_NOxxx for definition of gps_open() error numbers.
81 LOG_IF(WARNING, 0 == fail_count++) << "gps_open() failed: " << errno; 79 DLOG(WARNING) << "gps_open() failed " << errno;
82 return false; 80 return false;
83 } 81 }
84 fail_count = 0; 82 #else // drop the support for desktop linux for now
85 if (!StartStreaming()) { 83 DLOG(WARNING) << "LibGps is only supported on ChromeOS";
86 VLOG(1) << "StartStreaming failed"; 84 return false;
87 library().close(); 85 #endif
88 return false; 86
89 } 87 is_open_ = true;
90 return true; 88 return true;
91 } 89 }
92
93 void LibGps::Stop() { 90 void LibGps::Stop() {
94 library().close(); 91 if (is_open_)
92 gps_close_(gps_data_.get());
93 is_open_ = false;
95 } 94 }
96 95
97 bool LibGps::Poll() { 96 bool LibGps::Read(Geoposition* position) {
98 last_error_ = "no data received from gpsd";
99 while (DataWaiting()) {
100 int error = library().poll();
101 if (error) {
102 last_error_ = base::StringPrintf("poll() returned %d", error);
103 Stop();
104 return false;
105 }
106 last_error_.clear();
107 }
108 return last_error_.empty();
109 }
110
111 bool LibGps::GetPosition(Geoposition* position) {
112 DCHECK(position); 97 DCHECK(position);
113 position->error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; 98 position->error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
114 if (!library().is_open()) { 99 if (!is_open_) {
115 position->error_message = "No gpsd connection"; 100 DLOG(WARNING) << "No gpsd connection";
116 return false; 101 position->error_message = "No gpsd connection";
102 return false;
117 } 103 }
104
105 if (gps_read_(gps_data_.get()) < 0) {
106 DLOG(WARNING) << "gps_read() fails";
107 position->error_message = "gps_read() fails";
108 return false;
109 }
110
118 if (!GetPositionIfFixed(position)) { 111 if (!GetPositionIfFixed(position)) {
119 position->error_message = last_error_; 112 DLOG(WARNING) << "No fixed position";
120 return false; 113 position->error_message = "No fixed position";
114 return false;
121 } 115 }
116
122 position->error_code = Geoposition::ERROR_CODE_NONE; 117 position->error_code = Geoposition::ERROR_CODE_NONE;
123 position->timestamp = base::Time::Now(); 118 position->timestamp = base::Time::Now();
124 if (!position->IsValidFix()) { 119 if (!position->IsValidFix()) {
125 // GetPositionIfFixed returned true, yet we've not got a valid fix. 120 // GetPositionIfFixed returned true, yet we've not got a valid fix.
126 // This shouldn't happen; something went wrong in the conversion. 121 // This shouldn't happen; something went wrong in the conversion.
127 NOTREACHED() << "Invalid position from GetPositionIfFixed: lat,long " 122 NOTREACHED() << "Invalid position from GetPositionIfFixed: lat,long "
128 << position->latitude << "," << position->longitude 123 << position->latitude << "," << position->longitude
129 << " accuracy " << position->accuracy << " time " 124 << " accuracy " << position->accuracy << " time "
130 << position->timestamp.ToDoubleT(); 125 << position->timestamp.ToDoubleT();
131 position->error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; 126 position->error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
132 position->error_message = "Bad fix from gps"; 127 position->error_message = "Bad fix from gps";
133 return false; 128 return false;
134 } 129 }
135 return true; 130 return true;
136 } 131 }
137 132
138 LibGpsLibraryWrapper::LibGpsLibraryWrapper(void* dl_handle, 133 bool LibGps::GetPositionIfFixed(Geoposition* position) {
139 gps_open_fn gps_open, 134 DCHECK(position);
140 gps_close_fn gps_close, 135 if (gps_data_->status == STATUS_NO_FIX) {
141 gps_poll_fn gps_poll, 136 DVLOG(2) << "Status_NO_FIX";
142 gps_stream_fn gps_stream, 137 return false;
143 gps_waiting_fn gps_waiting) 138 }
144 : dl_handle_(dl_handle), 139
145 gps_open_(gps_open), 140 if (isnan(gps_data_->fix.latitude) || isnan(gps_data_->fix.longitude)) {
146 gps_close_(gps_close), 141 DVLOG(2) << "No valid lat/lon value";
147 gps_poll_(gps_poll), 142 return false;
148 gps_stream_(gps_stream), 143 }
149 gps_waiting_(gps_waiting), 144
150 gps_data_(NULL) { 145 position->latitude = gps_data_->fix.latitude;
146 position->longitude = gps_data_->fix.longitude;
147
148 if (!isnan(gps_data_->fix.epx) && !isnan(gps_data_->fix.epy)) {
149 position->accuracy = std::max(gps_data_->fix.epx, gps_data_->fix.epy);
150 } else if (isnan(gps_data_->fix.epx) && !isnan(gps_data_->fix.epy)) {
151 position->accuracy = gps_data_->fix.epy;
152 } else if (!isnan(gps_data_->fix.epx) && isnan(gps_data_->fix.epy)) {
153 position->accuracy = gps_data_->fix.epx;
154 } else {
155 // TODO(joth): Fixme. This is a workaround for http://crbug.com/99326
156 DVLOG(2) << "libgps reported accuracy NaN, forcing to zero";
157 position->accuracy = 0;
158 }
159
160 if (gps_data_->fix.mode == MODE_3D && !isnan(gps_data_->fix.altitude)) {
161 position->altitude = gps_data_->fix.altitude;
162 if (!isnan(gps_data_->fix.epv))
163 position->altitude_accuracy = gps_data_->fix.epv;
164 }
165
166 if (!isnan(gps_data_->fix.track))
167 position->heading = gps_data_->fix.track;
168 if (!isnan(gps_data_->fix.speed))
169 position->speed = gps_data_->fix.speed;
170 return true;
151 } 171 }
152
153 LibGpsLibraryWrapper::~LibGpsLibraryWrapper() {
154 close();
155 if (dl_handle_) {
156 const int err = dlclose(dl_handle_);
157 CHECK_EQ(0, err) << "Error closing dl handle: " << err;
158 }
159 }
160
161 bool LibGpsLibraryWrapper::open(const char* host, const char* port) {
162 DCHECK(!gps_data_) << "libgps already opened";
163 DCHECK(gps_open_);
164 gps_data_ = gps_open_(host, port);
165 return is_open();
166 }
167
168 void LibGpsLibraryWrapper::close() {
169 if (is_open()) {
170 DCHECK(gps_close_);
171 gps_close_(gps_data_);
172 gps_data_ = NULL;
173 }
174 }
175
176 int LibGpsLibraryWrapper::poll() {
177 DCHECK(is_open());
178 DCHECK(gps_poll_);
179 return gps_poll_(gps_data_);
180 }
181
182 int LibGpsLibraryWrapper::stream(int flags) {
183 DCHECK(is_open());
184 DCHECK(gps_stream_);
185 return gps_stream_(gps_data_, flags, NULL);
186 }
187
188 bool LibGpsLibraryWrapper::waiting() {
189 DCHECK(is_open());
190 DCHECK(gps_waiting_);
191 return gps_waiting_(gps_data_);
192 }
193
194 const gps_data_t& LibGpsLibraryWrapper::data() const {
195 DCHECK(is_open());
196 return *gps_data_;
197 }
198
199 bool LibGpsLibraryWrapper::is_open() const {
200 return gps_data_ != NULL;
201 }
OLDNEW
« no previous file with comments | « content/browser/geolocation/libgps_wrapper_linux.h ('k') | content/content_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698