中科微北斗HAL层代码学习

中科微北斗HAL层代码学习

1.功能:在GpsLocationProvider类构建时调用class_init_native(),根据加载gps.default.so(也就是中科微的HAL层)
从串口读北斗芯片NMEA数据,并解析再提供给GpsLocationProvider.

//GpsLocationProvider类装载时执行静态语句块,静态语句块和静态变量时平级,先定义先执行
GpsLocationProvider.java(frameworks\base\services\java\com\android\server\location)
static {
    class_init_native();    
}

com_android_server_location_GpsLocationProvider.cpp (frameworks\base\services\jni)
static JNINativeMethod sMethods[] = {
     /* name, signature, funcPtr */
    {"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},   //JNI和JAVA函数方法对应表
    ....省略
}

static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
    int err;
    hw_module_t* module;
    
    err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);    //加载gps.default.so
    if (err == 0) {
        hw_device_t* device;
        err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);    //执行HAL的open函数
        if (err == 0) {
            gps_device_t* gps_device = (gps_device_t *)device;
            sGpsInterface = gps_device->get_gps_interface(gps_device);   //得到HAL层接口。Java调用JNI接口在调用HAL接口
        }
    }
    ....省略
}

1.socket 通信和epoll多个I/O并发操作处理

static void gps_state_init( GpsState*  state)
{
    state->control[0] = -1;   //在这里control[0]负责发送
    state->control[1] = -1;   //control[1]负责接收

/*********************************************************************************************************************
socketpair()函数用于创建一对无名的、相互连接的套接子。
如果函数成功,则返回0,创建好的套接字分别是sv[0]和sv[1];否则返回-1,错误码保存于errno中。
基本用法:
1. 这对套接字可以用于全双工通信,每一个套接字既可以读也可以写。例如,可以往sv[0]中写,从sv[1]中读;或者从sv[1]中写,从sv[0]中读;
2. 如果往一个套接字(如sv[0])中写入后,再从该套接字读时会阻塞,只能在另一个套接字中(sv[1])上读成功;
*********************************************************************************************************************/
    if ( socketpair( AF_LOCAL, SOCK_STREAM, 0, state->control ) < 0 ) {    //创建两个套件字,用两个套接字直接通信
        D("could not create thread control socket pair: %s", strerror(errno));
        goto Fail;
    }
    ....省略
}

实例1:

static int epoll_register( int  epoll_fd, int  fd )
{
    struct epoll_event  ev;
    int                 ret, flags;

    /* important: make the fd non-blocking */
    flags = fcntl(fd, F_GETFL);
    fcntl(fd, F_SETFL, flags | O_NONBLOCK);    //添加I/O非阻塞操作,不管读到没有读到,都会马上返回释放端口

    ev.events  = EPOLLIN;    //触发事件的条件,有可读,比如北斗芯片往串口里写数据,串口有数据可读,就会触发事件
    ev.data.fd = fd;
    do {
        ret = epoll_ctl( epoll_fd, EPOLL_CTL_ADD, fd, &ev );   //把文件描述符添加到epoll队列中进行管理
    } while (ret < 0 && errno == EINTR);
    return ret;
}
static void gps_state_thread( void*  arg )
{
    int  epoll_fd   = epoll_create(2);    //创建两个epoll
    int  control_fd = state->control[1];  //control[1]负责接收control[0]消息

    // register control file descriptors for polling
    epoll_register( epoll_fd, control_fd );     //把>control[1]添加到epoll进行管理,见实例1
    epoll_register( epoll_fd, gps_fd );         //把串口设备的文件描述符添加到epoll进行管理,见实例1

    // now loop
    for (;;) {
        struct epoll_event   events[2];
        int                  ne, nevents;

        //没有事件产生就在这阻塞,可以同时处理两个文件事件并发,等待EPOLLIN事件
        nevents = epoll_wait( epoll_fd, events, 2, -1 ); 
        if (nevents < 0) {
            if (errno != EINTR)
                D("epoll_wait() unexpected error: %s", strerror(errno));
                continue;
            }
        #if NMEA_DEBUG
            D("gps thread received %d events", nevents);
        #endif
            for (ne = 0; ne < nevents; ne++) {
                if ((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0) {
                    D("EPOLLERR or EPOLLHUP after epoll_wait() !?");
                    return;
                }
                if ((events[ne].events & EPOLLIN) != 0) {     //两个文件I/O有数据可读
                    int  fd = events[ne].data.fd;

                    if (fd == control_fd)                  //socket control[1]套接字事件
                    {
                        ....省略
                    } else if (fd == gps_fd) {            //串口设备的事件
                        ....省略
                    }
                }
            ....省略
        }
    }

socket操作:

static void gps_state_start( GpsState*  s )
{
    char  cmd = CMD_START;
    int   ret;

    do {
        ret=write( s->control[0], &cmd, 1 );   //写cmd到control[0],epoll检测control[1]
    }
    while (ret < 0 && errno == EINTR);

    ....省略
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值