explan_libgpsd_core.c.xml 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. <sect1 id="libgpsd_core.c"><title><filename>libgpsd_core.c</filename></title>
  2. <informaltable frame='all' pgwide='1'>
  3. <tgroup cols='2'>
  4. <colspec colname='c1'></colspec>
  5. <colspec colname='c2'></colspec>
  6. <spanspec spanname='s1' namest='c1' nameend='c2'></spanspec>
  7. <!-- Not documented: gpsd_ppsmonitor() -->
  8. <thead>
  9. <row>
  10. <entry>Functions:-</entry><entry>Direct access to GPSes on serial or USB devices.</entry>
  11. </row>
  12. </thead>
  13. <tfoot>
  14. <row>
  15. <entry spanname='s1' align='left'>Notes based mostly on code as of Mon Apr 5 21:38:06 2010 -040.</entry>
  16. </row>
  17. </tfoot>
  18. <tbody>
  19. <row>
  20. <entry><function>void gpsd_log(int errlevel, const struct errout_t, const char *fmt, ... )</function></entry>
  21. <entry><para>This code is used for error reporting, but is dependant
  22. on SQUELCH_DISABLE so that embedded systems (for example) are not
  23. burdened with unnecessary noise. The first thing to check is if the
  24. error level offered is high enough to be of interest (controlled by
  25. the debug level we are running at).</para><para>If we are
  26. interested, the first step is to protect the code with a mutex if we
  27. are using the 1PPS input.</para><para>Now we build a message buffer
  28. which has a fixed header (<quote>gpsd: </quote>) and the incoming
  29. data. The output buffer is prepared (load the start with a NULL) and
  30. then the input buffer is scanned, byte-by-byte, up to its
  31. terminating NULL. The scanned data is transferred on the fly to the
  32. output buffer subject to the following tests:-</para><para>If the
  33. character is printable, it passes through unchanged.</para><para>If
  34. it is a space and either of the next two bytes is NULL it will also
  35. pass through unchanged.</para><para>In any other case, it is copied
  36. across as a hexadecimal string like
  37. <quote>x09</quote>.</para><para>The completed output buffer is then
  38. either sent to the system logger if we are in background mode
  39. (daemon) or to the stderr file if we are in foreground
  40. mode.</para></entry>
  41. </row>
  42. <row>
  43. <entry><function>int gpsd_switch_driver(struct gps_device_t *session, char* typename)</function></entry>
  44. <entry><para>Test if the function is called with the same name as
  45. the active driver.</para><para>If it is, test if the driver has a
  46. configurator function and is able to be reconfigured. A good result
  47. here will call the driver event hook with type 'driver_switch', and
  48. return a 0.</para><para>For an entry with a different driver name,
  49. scan all available drivers to see if the wanted one is there. An
  50. unmatched name exits, returning 0.</para><para>If we got a match,
  51. get the baudrate for the device with
  52. <function>gpsd_assert_sync()</function>, probe for the subtype if we
  53. have one.</para><para>If the device has a configurator and is
  54. reconfigurable, trigger the configurator.</para><para>Return a 1 to
  55. indicate a device switch.</para></entry>
  56. </row>
  57. <row>
  58. <entry><function>void gpsd_init(struct gps_device_t *session, struct gps_context_t *context, const char *device)</function></entry>
  59. <entry><para>Copy the device name to the session data structure,
  60. initialise important data fields and call
  61. <function>gpsd_tty_init()</function>,
  62. <function>gpsd_zero_satellites()</function> and
  63. <function>packet_reset()</function>.</para></entry>
  64. </row>
  65. <row>
  66. <entry><function>void gpsd_deactivate(struct gps_device_t *session)</function></entry>
  67. <entry><para>All actions below, except the last one are conditional
  68. on the <function>ntpd</function> interface being compiled
  69. in.</para><para>Release the <function>ntpd</function> resources,
  70. including the 1PPS resources if they are active.</para><para>If the
  71. device has a revert function, trigger it.</para><para>If it has an
  72. NMEA mode switcher, invoke it.</para><para>If it has a wrapup
  73. routine, invoke it.</para><para>Finally, close the
  74. device.</para></entry>
  75. </row>
  76. <row>
  77. <entry><function>static void *gpsd_ppsmonitor(void *arg)</function></entry>
  78. <entry><para>An <function>ioctl()</function> call is made which
  79. returns either 0 if the status of the port changed, or an
  80. error.</para><para>If we got a change, we read the modem control
  81. bits and extract the 1PPS information.</para><para>We check the
  82. returned value and see if it has changed recently. A counter of 10
  83. unchanged events will disable further testing.</para><para>If we are
  84. still hanging in there, we now see if we already have had more than
  85. 4 good fixes, otherwise we can't trust the 1PPS.</para><para>We then
  86. finally test the pulse duration. If it is either a genuine 1PPS or a
  87. 2Hz square wave, we call
  88. <function>ntpshm_pps()</function>.</para><para>Short or long PPS
  89. pulses are dropped with an error report.</para></entry>
  90. </row>
  91. <row>
  92. <entry><function>int gpsd_activate(struct gps_device_t *session, bool reconfigurable)</function></entry>
  93. <entry><para>If the devicename matches an NTRIP or DGNSS URI, hand
  94. off to special code for opening a socket to that source over the
  95. network.</para><para>Try and open the device, returning -1 if we
  96. fail.</para><para>Probe all possible drivers to see if one
  97. recognises the device.</para><para>Set some fundamental data to a
  98. clean value.</para><para>Handle the initialisation of NTP and 1PPS
  99. functions if needed.</para><para>If we did succeed in probing some
  100. device type, try and get the subtype.</para><para>If we need to do
  101. so, we now configure the device.</para><para>Finally, signal success
  102. by returning the file descriptor given by the device open
  103. call.</para></entry>
  104. </row>
  105. <row>
  106. <entry><function>void gpsd_error_model(struct gps_device_t *session, struct gps_fix_t *fix, struct gps_fix_t *oldfix)</function></entry>
  107. <entry><para>Check we have a 2D fix (or better) and if the gps
  108. didn't provide an eph value, use the HDOP to calculate one or fail
  109. to NAN.</para><para>Do the same with epv/VDOP if we have a 3D or
  110. better fix.</para><para>Do the same with
  111. epe/PDOP.</para><para>Consider speed error; check if we have two
  112. fixes with differing timestamps and use their times and eph values
  113. to calculate the speed.</para><para>If we have two valid 3D fixes,
  114. we can calculate the climb/sink rate.</para><para>Finally, just
  115. before exiting, save this fix as the old fix for the next comparison
  116. round.</para></entry>
  117. </row>
  118. <row>
  119. <entry><function>gps_mask_t gpsd_poll(struct gps_device_t *session)</function></entry>
  120. <entry><para>Make a call to <function>gps_clear_fix()</function> to
  121. prepare the newdata structure to receive data from an incoming
  122. packet.</para><para>Check if we know the device type. If we do,
  123. stash the count of of characters we are able to get from
  124. it.</para><para>If the read has given a full packet, we can call the
  125. subtype probing method, if the device supports it.</para><para>If we
  126. don't know the device type, try and figure out what it is, exiting
  127. if we can't.</para><para>Make some checks if the device is offline
  128. or the packet is incomplete, using the stashed count of characters
  129. and the full packet indicator.</para><para>If a full packet is
  130. available, we try to get the fix data and update the main data
  131. structure. We also compute the DOPs so we can fill them in if they
  132. are not included in the gps device output.</para><para>Mopst of the
  133. possible driver events are called from somewhere in
  134. here.</para></entry>
  135. </row>
  136. <row>
  137. <entry><function>void gpsd_wrap(struct gps_device_t *session)</function></entry>
  138. <entry><para>Simple call to
  139. <function>gpsd_deactivate(session)</function>.</para></entry>
  140. </row>
  141. <row>
  142. <entry><function>void gpsd_zero_satellites(struct gps_data_t *out)</function></entry>
  143. <entry><para>Zero the status data for all satellites.</para></entry>
  144. </row>
  145. </tbody>
  146. </tgroup>
  147. </informaltable>
  148. </sect1>