Android系统硬件抽象层原理与实现之GPS

作者:朱克锋

转载请注明出处:http://blog.csdn.net/linux_zkf/article/details/7493129

 

Android系统硬件抽象层原理与实现之GPS

本文我将系统分析一下GPS HAL的实现,GPS大家都很熟悉,原理就不再介绍了。

GPSandroid系统中的结构如图

 

GOS APP

 

ANDROID LOCATION

 

GPS JNI

 

GPS HAL

 

GPS DRIVER

 

接下来我们来看看GPS HAL的实现

GPS硬件设备驱动程序通常是串口驱动程序,将GPS连接上应用处理器的某个串口后,就可以打开该节点进行写操作,对GPS写入数据或命令,而读操作一般获取到的就是标准的NMEA数据,NMEA数据下面会有简单介绍。

 

android系统中,GPS HAL代码在

hardware/libhardware_legacy/wifi/gps

hardware/libhardware_legacy/include/libhardware_legacy/gps.h

 

gps.h中定义了各种信息,其主要部分如下:

GPS 的标准结构体,里面定义的关于操作GPS的方法指针

 

typedef struct {

   /** set to sizeof(GpsInterface) */

   size_t          size;

   /**

    * Opens the interface and provides the callback routines

    * to the implemenation of this interface.

    */

   int   (*init)( GpsCallbacks* callbacks );

 

   /** Starts navigating. */

   int   (*start)( void );

 

   /** Stops navigating. */

   int   (*stop)( void );

 

   /** Closes the interface. */

   void  (*cleanup)( void );

 

   /** Injects the current time. */

   int   (*inject_time)(GpsUtcTime time, int64_t timeReference,

                        int uncertainty);

 

   /** Injects current location from another location provider

    *  (typically cell ID).

    *  latitude and longitude are measured in degrees

    *  expected accuracy is measured in meters

    */

   int  (*inject_location)(double latitude, double longitude, float accuracy);

 

   /**

    * Specifies that the next call to start will not use the

    * information defined in the flags. GPS_DELETE_ALL is passed for

    * a cold start.

    */

   void  (*delete_aiding_data)(GpsAidingData flags);

 

   /**

    * min_interval represents the time between fixes in milliseconds.

    * preferred_accuracy represents the requested fix accuracy in meters.

    * preferred_time represents the requested time to first fix in milliseconds.

    */

   int   (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence,

           uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time);

 

   /** Get a pointer to extension information. */

   const void* (*get_extension)(const char* name);

} GpsInterface;

 

这些是GPS的回调函数,是GPS的硬件抽象层获取信息的主要手段,通常在读取到底层数据并分析完成后调用上报信息给上层。

 

/** Callback with location information.

 * Can only be called from a thread created by create_thread_cb.

 */

typedef void (* gps_location_callback)(GpsLocation* location);

 

/** Callback with status information.

 * Can only be called from a thread created by create_thread_cb.

 */

typedef void (* gps_status_callback)(GpsStatus* status);

 

/** Callback with SV status information.

 * Can only be called from a thread created by create_thread_cb.

 */

typedef void (* gps_sv_status_callback)(GpsSvStatus* sv_info);

 

/** Callback for reporting NMEA sentences.

 * Can only be called from a thread created by create_thread_cb.

 */

typedef void (* gps_nmea_callback)(GpsUtcTime timestamp, const char* nmea, int length);

 

/** Callback to inform framework of the GPS engine's capabilities.

 * Capability parameter is a bit field of GPS_CAPABILITY_* flags.

 */

typedef void (* gps_set_capabilities)(uint32_t capabilities);

 

/** Callback utility for acquiring the GPS wakelock.

 * This can be used to prevent the CPU from suspending while handling GPS events.

 */

typedef void (* gps_acquire_wakelock)();

 

/** Callback utility for releasing the GPS wakelock. */

typedef void (* gps_release_wakelock)();

 

/** Callback for creating a thread that can call into the Java framework code.

 * This must be used to create any threads that report events up to the framework.

 */

typedef pthread_t (* gps_create_thread)(const char* name, void (*start)(void *), void* arg);

 

GpsCallbacks通过调用初始化方法(GpsInterface 的init方法)注册到HAL,共HAL调用

 

/** GPS callback structure. */

typedef struct {

   /** set to sizeof(GpsCallbacks) */

   size_t      size;

   gps_location_callback location_cb;

   gps_status_callback status_cb;

   gps_sv_status_callback sv_status_cb;

   gps_nmea_callback nmea_cb;

   gps_set_capabilities set_capabilities_cb;

   gps_acquire_wakelock acquire_wakelock_cb;

   gps_release_wakelock release_wakelock_cb;

   gps_create_thread create_thread_cb;

} GpsCallbacks;

 

GpsLocation中是解析后的详细信息,可以直接提供给android框架使用,其中解析后包括:经度、纬度、速度、方向、精确度、时间戳等等

 

/** Represents a location. */

typedef struct {

   /** set to sizeof(GpsLocation) */

   size_t          size;

   /** Contains GpsLocationFlags bits. */

   uint16_t        flags;

   /** Represents latitude in degrees. */

   double          latitude;

   /** Represents longitude in degrees. */

   double          longitude;

   /** Represents altitude in meters above the WGS 84 reference

    * ellipsoid. */

   double          altitude;

   /** Represents speed in meters per second. */

   float           speed;

   /** Represents heading in degrees. */

   float           bearing;

   /** Represents expected accuracy in meters. */

   float           accuracy;

   /** Timestamp for the location fix. */

   GpsUtcTime      timestamp;

} GpsLocation;

 

在gps.c中定义了获取GPS接口的方法,通过一些宏定义来选择

 

const GpsInterface*gps_get_interface()
{
    if (sGpsInterface == NULL)
         gps_find_hardware();
    return sGpsInterface;
}

 

static voidgps_find_hardware( void )
{
#ifdef HAVE_QEMU_GPS_HARDWARE
    if (qemu_check()) {
        sGpsInterface = gps_get_qemu_interface();
        if (sGpsInterface) {
            LOGD("using QEMU GPS Hardware emulation\n");
            return;
        }
    }
#endif
#ifdef HAVE_GPS_HARDWARE
    sGpsInterface = gps_get_hardware_interface();
#endif
    if (!sGpsInterface)
        LOGD("no GPS hardware on this device\n");
}

 

在模拟器中如下所示

 

const GpsInterface* gps_get_qemu_interface()
{
    return &qemuGpsInterface;
}

static const GpsInterface qemuGpsInterface = {
    qemu_gps_init,
    qemu_gps_start,
    qemu_gps_stop,
    qemu_gps_cleanup,
    qemu_gps_inject_time,
    qemu_gps_inject_location,
    qemu_gps_delete_aiding_data,
    qemu_gps_set_position_mode,
    qemu_gps_get_extension,
};

对于GPS来说首先需要初始化,然后对GPS数据建立一套“获取解析上报”的机制,初始化完成以后一般都会开启一个poll线程,对GPS端口进行轮询,获取NMEA数据,获取导数据后进行解析,目的是将数据转换位框架层可以识别的结构信息,在参考代码中有很多种实现,基本上就是文本解析,然后填充上报数据结构 

 

最后简单解释一下NMEA数据结构

NMEA"National Marine Electronics Association"(国际海洋电子协会)缩写,同时也是数据传输标准工业协会,在这里,实际上应为NMEA 0183。它是一套定义接收机输出的标准信息,有几种不同的格式,每种都是独立相关的ASCII格式,逗点隔开数据流,数据流长度从30-100字符不等,通常以每秒间隔选择输出,最常用的格式为"GGA",它包含了定位时间,纬度,经度,高度,定位所用的卫星数,DOP,差分状态和校正时段等,其他的有速度,跟踪,日期等。NMEA实际上已成为所有的GPS接收机和最通用的数据输出格式,同时它也被用于与GPS接收机接口的大多数的软件包里

说明:NMEA0183格式以“$”开始,常用语句有GPGGAGPVTGGPRMC

这里一GPRMC为例简单分析一下

$GPRMC,121252.000,A,3958.3032,N,11629.6046,E,15.15,359.95,070306,,,A*54

<1> UTC时间,hhmmss(时分秒)格式 <2> 定位状态,A=有效定位,V=无效定位 <3> 纬度ddmm.mmmm(度分)格式(前面的0也将被传输) <4> 纬度半球N(北半球)或S(南半球) <5> 经度dddmm.mmmm(度分)格式(前面的0也将被传输) <6> 经度半球E(东经)或W(西经) <7> 地面速率(000.0~999.9节,前面的0也将被传输) <8> 地面航向(000.0~359.9度,以真北为参考基准,前面的0也将被传输) <9> UTC日期,ddmmyy(日月年)格式 <10> 磁偏角(000.0~180.0度,前面的0也将被传输) <11> 磁偏角方向,E(东)或W(西) <12> 模式指示(仅NMEA0183 3.00版本输出,A=自主定位,D=差分,E=估算,N=数据无效)

你可能感兴趣的:(thread,数据结构,android,callback,interface,extension)