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

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: putting libgps version string into anon namespace 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"
15
16 COMPILE_ASSERT(GPSD_API_MAJOR_VERSION == 5, GPSD_API_version_is_not_5);
13 17
14 namespace { 18 namespace {
15 // Attempts to load dynamic library named |lib| and initialize the required 19 const char kLibGpsName[] = "libgps.so.20";
16 // function pointers according to |mode|. Returns ownership a new instance 20 } // namespace
17 // of the library loader class, or NULL on failure. 21
18 // TODO(joth): This is a hang-over from when we dynamically two different 22 LibGps::LibGps(void* dl_handle,
19 // versions of libgps and chose between them. Now we could remove at least one 23 gps_open_fn gps_open,
20 // layer of wrapper class and directly #include gps.h in this cc file. 24 gps_close_fn gps_close,
21 // See http://crbug.com/98132 and http://crbug.com/99177 25 gps_read_fn gps_read)
22 LibGpsLibraryWrapper* TryToOpen(const char* lib) { 26 : dl_handle_(dl_handle),
23 void* dl_handle = dlopen(lib, RTLD_LAZY); 27 gps_open_(gps_open),
28 gps_close_(gps_close),
29 gps_read_(gps_read),
30 gps_data_(new gps_data_t),
31 is_open_(false) {
32 DCHECK(gps_open_);
33 DCHECK(gps_close_);
34 DCHECK(gps_read_);
35 }
36
37 LibGps::~LibGps() {
38 Stop();
39 if (dl_handle_) {
40 const int err = dlclose(dl_handle_);
41 DCHECK_EQ(0, err) << "Error closing dl handle: " << err;
42 }
43 }
44
45 LibGps* LibGps::New() {
46 void* dl_handle = dlopen(kLibGpsName, RTLD_LAZY);
24 if (!dl_handle) { 47 if (!dl_handle) {
25 VLOG(1) << "Could not open " << lib << ": " << dlerror(); 48 DLOG(WARNING) << "Could not open " << kLibGpsName << ": " << dlerror();
26 return NULL; 49 return NULL;
27 } 50 }
28 VLOG(1) << "Loaded " << lib; 51
52 DLOG(INFO) << "Loaded " << kLibGpsName;
29 53
30 #define DECLARE_FN_POINTER(function) \ 54 #define DECLARE_FN_POINTER(function) \
31 LibGpsLibraryWrapper::function##_fn function; \ 55 function##_fn function = reinterpret_cast<function##_fn>( \
32 function = reinterpret_cast<LibGpsLibraryWrapper::function##_fn>( \
33 dlsym(dl_handle, #function)); \ 56 dlsym(dl_handle, #function)); \
34 if (!function) { \ 57 if (!function) { \
35 LOG(WARNING) << "libgps " << #function << " error: " << dlerror(); \ 58 DLOG(WARNING) << "libgps " << #function << " error: " << dlerror(); \
36 dlclose(dl_handle); \ 59 dlclose(dl_handle); \
37 return NULL; \ 60 return NULL; \
38 } 61 }
39 DECLARE_FN_POINTER(gps_open); 62 DECLARE_FN_POINTER(gps_open);
40 DECLARE_FN_POINTER(gps_close); 63 DECLARE_FN_POINTER(gps_close);
41 DECLARE_FN_POINTER(gps_poll); 64 DECLARE_FN_POINTER(gps_read);
42 DECLARE_FN_POINTER(gps_stream); 65 // We don't use gps_shm_read() directly, just to make sure that libgps has
43 DECLARE_FN_POINTER(gps_waiting); 66 // the shared memory support.
67 typedef int (*gps_shm_read_fn)(struct gps_data_t*);
68 DECLARE_FN_POINTER(gps_shm_read);
44 #undef DECLARE_FN_POINTER 69 #undef DECLARE_FN_POINTER
45 70
46 return new LibGpsLibraryWrapper(dl_handle, 71 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 } 72 }
73 73
74 bool LibGps::Start() { 74 bool LibGps::Start() {
75 if (library().is_open()) 75 if (is_open_)
76 return true; 76 return true;
77
78 #if defined(OS_CHROMEOS)
77 errno = 0; 79 errno = 0;
78 static int fail_count = 0; 80 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. 81 // See gps.h NL_NOxxx for definition of gps_open() error numbers.
81 LOG_IF(WARNING, 0 == fail_count++) << "gps_open() failed: " << errno; 82 DLOG(WARNING) << "gps_open() failed " << errno;
82 return false; 83 return false;
83 } 84 }
84 fail_count = 0; 85 #else // drop the support for desktop linux for now
85 if (!StartStreaming()) { 86 DLOG(WARNING) << "LibGps is only supported on ChromeOS";
86 VLOG(1) << "StartStreaming failed"; 87 return false;
87 library().close(); 88 #endif
88 return false; 89
89 } 90 is_open_ = true;
90 return true; 91 return true;
91 } 92 }
92
93 void LibGps::Stop() { 93 void LibGps::Stop() {
94 library().close(); 94 if (is_open_)
95 gps_close_(gps_data_.get());
96 is_open_ = false;
95 } 97 }
96 98
97 bool LibGps::Poll() { 99 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); 100 DCHECK(position);
113 position->error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; 101 position->error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
114 if (!library().is_open()) { 102 if (!is_open_) {
115 position->error_message = "No gpsd connection"; 103 DLOG(WARNING) << "No gpsd connection";
116 return false; 104 position->error_message = "No gpsd connection";
105 return false;
117 } 106 }
107
108 if (gps_read_(gps_data_.get()) < 0) {
109 DLOG(WARNING) << "gps_read() fails";
110 position->error_message = "gps_read() fails";
111 return false;
112 }
113
118 if (!GetPositionIfFixed(position)) { 114 if (!GetPositionIfFixed(position)) {
119 position->error_message = last_error_; 115 DLOG(WARNING) << "No fixed position";
120 return false; 116 position->error_message = "No fixed position";
117 return false;
121 } 118 }
119
122 position->error_code = Geoposition::ERROR_CODE_NONE; 120 position->error_code = Geoposition::ERROR_CODE_NONE;
123 position->timestamp = base::Time::Now(); 121 position->timestamp = base::Time::Now();
124 if (!position->IsValidFix()) { 122 if (!position->IsValidFix()) {
125 // GetPositionIfFixed returned true, yet we've not got a valid fix. 123 // GetPositionIfFixed returned true, yet we've not got a valid fix.
126 // This shouldn't happen; something went wrong in the conversion. 124 // This shouldn't happen; something went wrong in the conversion.
127 NOTREACHED() << "Invalid position from GetPositionIfFixed: lat,long " 125 NOTREACHED() << "Invalid position from GetPositionIfFixed: lat,long "
128 << position->latitude << "," << position->longitude 126 << position->latitude << "," << position->longitude
129 << " accuracy " << position->accuracy << " time " 127 << " accuracy " << position->accuracy << " time "
130 << position->timestamp.ToDoubleT(); 128 << position->timestamp.ToDoubleT();
131 position->error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; 129 position->error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
132 position->error_message = "Bad fix from gps"; 130 position->error_message = "Bad fix from gps";
133 return false; 131 return false;
134 } 132 }
135 return true; 133 return true;
136 } 134 }
137 135
138 LibGpsLibraryWrapper::LibGpsLibraryWrapper(void* dl_handle, 136 bool LibGps::GetPositionIfFixed(Geoposition* position) {
139 gps_open_fn gps_open, 137 DCHECK(position);
140 gps_close_fn gps_close, 138 if (gps_data_->status == STATUS_NO_FIX) {
141 gps_poll_fn gps_poll, 139 DVLOG(2) << "Status_NO_FIX";
142 gps_stream_fn gps_stream, 140 return false;
143 gps_waiting_fn gps_waiting) 141 }
144 : dl_handle_(dl_handle), 142
145 gps_open_(gps_open), 143 if (isnan(gps_data_->fix.latitude) || isnan(gps_data_->fix.longitude)) {
146 gps_close_(gps_close), 144 DVLOG(2) << "No valid lat/lon value";
147 gps_poll_(gps_poll), 145 return false;
148 gps_stream_(gps_stream), 146 }
149 gps_waiting_(gps_waiting), 147
150 gps_data_(NULL) { 148 position->latitude = gps_data_->fix.latitude;
149 position->longitude = gps_data_->fix.longitude;
150
151 if (!isnan(gps_data_->fix.epx) && !isnan(gps_data_->fix.epy)) {
152 position->accuracy = std::max(gps_data_->fix.epx, gps_data_->fix.epy);
153 } else if (isnan(gps_data_->fix.epx) && !isnan(gps_data_->fix.epy)) {
154 position->accuracy = gps_data_->fix.epy;
155 } else if (!isnan(gps_data_->fix.epx) && isnan(gps_data_->fix.epy)) {
156 position->accuracy = gps_data_->fix.epx;
157 } else {
158 // TODO(joth): Fixme. This is a workaround for http://crbug.com/99326
159 DVLOG(2) << "libgps reported accuracy NaN, forcing to zero";
160 position->accuracy = 0;
161 }
162
163 if (gps_data_->fix.mode == MODE_3D && !isnan(gps_data_->fix.altitude)) {
164 position->altitude = gps_data_->fix.altitude;
165 if (!isnan(gps_data_->fix.epv))
166 position->altitude_accuracy = gps_data_->fix.epv;
167 }
168
169 if (!isnan(gps_data_->fix.track))
170 position->heading = gps_data_->fix.track;
171 if (!isnan(gps_data_->fix.speed))
172 position->speed = gps_data_->fix.speed;
173 return true;
151 } 174 }
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