1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "sync_clock.h" 18 19 #include <asm/byteorder.h> 20 #include <errno.h> 21 #include <fcntl.h> 22 #include <inttypes.h> 23 #include <linux/usbdevice_fs.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <sys/inotify.h> 28 #include <sys/ioctl.h> 29 #include <sys/time.h> 30 #include <time.h> 31 #include <unistd.h> 32 33 34 #ifdef __ANDROID__ 35 #include <android/log.h> 36 #define LOGD(...) __android_log_print(ANDROID_LOG_VERBOSE, "ClockSyncNative", __VA_ARGS__) 37 #else 38 #define LOGD(...) printf(__VA_ARGS__) 39 #endif 40 41 42 // How many times to repeat the 1..9 digit sequence it's a tradeoff between 43 // precision and how long it takes. 44 // TODO: investigate better combination of constants for repeats and wait times 45 const int kSyncRepeats = 7; 46 const int kMillion = 1000000; 47 48 49 /** 50 uptimeMicros() - returns microseconds elapsed since boot. 51 Same time as Android's SystemClock.uptimeMillis() but in microseconds. 52 53 Adapted from Android: 54 platform/system/core/libutils/Timers.cpp 55 platform/system/core/include/utils/Timers.h 56 57 See: 58 http://developer.android.com/reference/android/os/SystemClock.html 59 https://android.googlesource.com/platform/system/core/+/master/libutils/Timers.cpp 60 */ 61 int64_t uptimeMicros() { 62 struct timespec ts; 63 clock_gettime(CLOCK_MONOTONIC, &ts); 64 return ((int64_t)ts.tv_sec) * kMillion + ts.tv_nsec / 1000; 65 } 66 67 68 // Sleeps us microseconds 69 int microsleep(int us) { 70 struct timespec ts; 71 ts.tv_sec = us / kMillion; 72 us %= kMillion; 73 ts.tv_nsec = us*1000; 74 return nanosleep(&ts, NULL); 75 } 76 77 78 // *********************** Generic USB functions ******************************* 79 80 static int send_char_async(int fd, int endpoint, char msg, char * label) { 81 // TODO: Do we really need a buffer longer than 1 char here? 82 char buffer[256] = {0}; 83 buffer[0] = msg; 84 int length = 1; 85 86 // TODO: free() the memory used for URBs. 87 // Circular buffer of URBs? Cleanup at the end of clock sync? 88 // Several may be used simultaneously, no signal when done. 89 struct usbdevfs_urb *urb = calloc(1, sizeof(struct usbdevfs_urb)); 90 memset(urb, 0, sizeof(struct usbdevfs_urb)); 91 92 int res; 93 urb->status = -1; 94 urb->buffer = buffer; 95 urb->buffer_length = length; 96 urb->endpoint = endpoint; 97 urb->type = USBDEVFS_URB_TYPE_BULK; 98 urb->usercontext = label; // This is hackish 99 do { 100 res = ioctl(fd, USBDEVFS_SUBMITURB, urb); 101 } while((res < 0) && (errno == EINTR)); 102 return res; 103 } 104 105 106 // Send or read using USBDEVFS_BULK. Allows to set a timeout. 107 static int bulk_talk(int fd, int endpoint, char * buffer, int length) { 108 // Set some reasonable timeout. 20ms is plenty time for most transfers but 109 // short enough to fail quickly if all transfers and retries fail with 110 // timeout. 111 const int kTimeoutMs = 20; 112 struct usbdevfs_bulktransfer ctrl; 113 // TODO: need to limit request size to avoid EINVAL 114 115 ctrl.ep = endpoint; 116 ctrl.len = length; 117 ctrl.data = buffer; 118 ctrl.timeout = kTimeoutMs; 119 int ret = ioctl(fd, USBDEVFS_BULK, &ctrl); 120 return ret; 121 } 122 123 124 /******************************************************************************* 125 * Clock sync specific stuff below. 126 * Most data is stored in the clock_connection struct variable. 127 */ 128 129 // Send a single character to the remote in a blocking mode 130 int send_cmd(struct clock_connection *clk, char cmd) { 131 return bulk_talk(clk->fd, clk->endpoint_out, &cmd, 1); 132 } 133 134 // Schedule a single character to be sent to the remote - async. 135 int send_async(struct clock_connection *clk, char cmd) { 136 return send_char_async(clk->fd, clk->endpoint_out, cmd, NULL); 137 } 138 139 140 int bulk_read(struct clock_connection *clk) { 141 memset(clk->buffer, 0, sizeof(clk->buffer)); 142 int ret = bulk_talk(clk->fd, clk->endpoint_in, clk->buffer, sizeof(clk->buffer)); 143 return ret; 144 } 145 146 // microseconds elapsed since clk->t_base 147 int micros(struct clock_connection *clk) { 148 return uptimeMicros() - clk->t_base; 149 } 150 151 // Clear all incoming data that's already waiting somewhere in kernel buffers 152 // and discard it. 153 void flush_incoming(struct clock_connection *clk) { 154 // When bulk_read times out errno = ETIMEDOUT=110, retval =-1 155 // should we check for this? 156 157 while(bulk_read(clk) >= 0) { 158 // TODO: fail nicely if waiting too long to avoid hangs 159 } 160 } 161 162 // Ask the remote to send its timestamps 163 // for the digits previously sent to it. 164 void read_remote_timestamps(struct clock_connection *clk, int * times_remote) { 165 int i; 166 int t_remote; 167 // Go over the digits [1, 2 ... 9] 168 for (i = 0; i < 9; i++) { 169 char digit = i + '1'; 170 send_cmd(clk, CMD_SYNC_READOUT); 171 bulk_read(clk); 172 if (clk->buffer[0] != digit) { 173 LOGD("Error, bad reply for R%d: %s", i+1, clk->buffer); 174 } 175 // The reply string looks like digit + space + timestamp 176 // Offset by 2 to ignore the digit and the space 177 t_remote = atoi(clk->buffer + 2); 178 times_remote[i] = t_remote; 179 } 180 } 181 182 183 // Preliminary rough sync with a single message - CMD_SYNC_ZERO = 'Z'. 184 // This is not strictly necessary but greatly simplifies debugging 185 // by removing the need to look at very long numbers. 186 void zero_remote(struct clock_connection *clk) { 187 flush_incoming(clk); 188 clk->t_base = uptimeMicros(); 189 send_cmd(clk, CMD_SYNC_ZERO); 190 bulk_read(clk); // TODO, make sure we got 'z' 191 clk->maxE = micros(clk); 192 clk->minE = 0; 193 194 LOGD("Sent a 'Z', reply '%c' in %d us\n", clk->buffer[0], clk->maxE); 195 } 196 197 198 199 void improve_minE(struct clock_connection *clk) { 200 int times_local_sent[9] = {0}; 201 int times_remote_received[9] = {0}; 202 203 // Set sleep time as 1/kSleepTimeDivider of the current bounds interval, 204 // but never less or more than k(Min/Max)SleepUs. All pretty random 205 // numbers that could use some tuning and may behave differently on 206 // different devices. 207 const int kMaxSleepUs = 700; 208 const int kMinSleepUs = 70; 209 const int kSleepTimeDivider = 10; 210 int minE = clk->minE; 211 int sleep_time = (clk->maxE - minE) / kSleepTimeDivider; 212 if(sleep_time > kMaxSleepUs) sleep_time = kMaxSleepUs; 213 if(sleep_time < kMinSleepUs) sleep_time = kMinSleepUs; 214 215 flush_incoming(clk); 216 // Send digits to remote side 217 int i; 218 for (i = 0; i < 9; i++) { 219 char c = i + '1'; 220 times_local_sent[i] = micros(clk); 221 send_async(clk, c); 222 microsleep(sleep_time); 223 } 224 225 // Read out receive times from the other side 226 read_remote_timestamps(clk, times_remote_received); 227 228 // Do stats 229 for (i = 0; i < 9; i++) { 230 int tls = times_local_sent[i]; 231 int trr = times_remote_received[i]; 232 233 int dt; 234 235 // Look at outgoing digits 236 dt = tls - trr; 237 if (tls != 0 && trr != 0 && dt > minE) { 238 minE = dt; 239 } 240 241 } 242 243 clk->minE = minE; 244 245 LOGD("E is between %d and %d us, sleep_time=%d\n", clk->minE, clk->maxE, sleep_time); 246 } 247 248 void improve_maxE(struct clock_connection *clk) { 249 int times_remote_sent[9] = {0}; 250 int times_local_received[9] = {0}; 251 252 // Tell the remote to send us digits with delays 253 // TODO: try tuning / configuring the delay time on remote side 254 send_async(clk, CMD_SYNC_SEND); 255 256 // Read and timestamp the incoming digits, they may arrive out of order. 257 // TODO: Try he same with USBDEVFS_REAPURB, it might be faster 258 int i; 259 for (i = 0; i < 9; ++i) { 260 int retval = bulk_read(clk); 261 // TODO: deal with retval = (bytes returned) > 1. shouldn't happen. 262 // Can it happen on some devices? 263 int t_local = micros(clk); 264 int digit = atoi(clk->buffer); 265 if (digit <=0 || digit > 9) { 266 LOGD("Error, bad incoming digit: %s\n", clk->buffer); 267 } 268 times_local_received[digit-1] = t_local; 269 } 270 271 // Flush whatever came after the digits. As of this writing, it's usually 272 // a single linefeed character. 273 flush_incoming(clk); 274 // Read out the remote timestamps of when the digits were sent 275 read_remote_timestamps(clk, times_remote_sent); 276 277 // Do stats 278 int maxE = clk->maxE; 279 for (i = 0; i < 9; i++) { 280 int trs = times_remote_sent[i]; 281 int tlr = times_local_received[i]; 282 int dt = tlr - trs; 283 if (tlr != 0 && trs != 0 && dt < maxE) { 284 maxE = dt; 285 } 286 } 287 288 clk->maxE = maxE; 289 290 LOGD("E is between %d and %d us\n", clk->minE, clk->maxE); 291 } 292 293 294 void improve_bounds(struct clock_connection *clk) { 295 improve_minE(clk); 296 improve_maxE(clk); 297 } 298 299 // get minE and maxE again after some time to check for clock drift 300 void update_bounds(struct clock_connection *clk) { 301 // Reset the bounds to some unrealistically large numbers 302 int i; 303 clk->minE = -1e7; 304 clk->maxE = 1e7; 305 // Talk to remote to get bounds on minE and maxE 306 for (i=0; i < kSyncRepeats; i++) { 307 improve_bounds(clk); 308 } 309 } 310 311 void sync_clocks(struct clock_connection *clk) { 312 // Send CMD_SYNC_ZERO to remote for rough initial sync 313 zero_remote(clk); 314 315 int rep; 316 for (rep=0; rep < kSyncRepeats; rep++) { 317 improve_bounds(clk); 318 } 319 320 // Shift the base time to set minE = 0 321 clk->t_base += clk->minE; 322 clk->maxE -= clk->minE; 323 clk->minE = 0; 324 LOGD("Base time shifted for zero minE\n"); 325 } 326 327 328