高通G-sensor-1

本系列导航:

linux驱动由浅入深系列:高通sensor架构实例分析之一(整体概览+AP侧代码分析)

linux驱动由浅入深系列:高通sensor架构实例分析之二(adsp驱动代码结构)
Linux驱动由浅入深系列:高通sensor架构例分析之三(adsp上报数据详解、校准流程详解)


最初的时候芯片厂家对sensor的处理和对待其它外设一样都是直接挂在processor上,sensor的驱动也和其他linux或android的驱动一样,生成对应的设备节点给上层提供数据(关于此类linux基础驱动的知识,可以参考本博客其他博文)。但后来这一切发生了变化,最主要的原因就是功耗。Sensor希望自己能够一直处于工作状态下,如计步器等应用场景。这样如果sensor还挂在主processor上(这时候处理器就分多核啦)势必影响待机功耗。因此各个芯片厂推出了各自的方案,如sensor-hub等等。高通在MSM8960之后就将sensor的处理塞到了一个单独的音频dsp中了(MSM8953中这个dsp叫作aDSP),这样待机时主处理器休眠降低功耗,由这个aDSP在处理音频数据的间隙捎带着就能把sensor的数据处理了^^。下面以MSM8953为例分析一下其结构。

 

高通sensor软件架构

首先来看一下高通sensor处理的软件框图:


1,  框图上半部分是应用处理器,下半部分是aDSP。

2,  aDSP中包含了log接口,电源管理,sensor算法库,sensor校准,各个sensor的管理模块。最后一个是直接挂载各个传感器的(Prox、Press、Mag、Gyro、Acc),软件中的主要部分叫作SMGR。[上图文字怎么乱了,补充一张^-^]


3,  在应用处理器中,软件接口中不再有每个sensor的设备节点了。那有的是什么呢,只有Sensor1 API Socket Remoting Layer层对应的API接口。这个接口是本文的重点,下文详细解释。

4,  那么aDSP与应用处理器之间用什么机制进行通信呢?图中可以看到一个叫QMI的东西,就是它了,这个高通基于共享内存机制开发的多核间通信技术,在应用处理器侧和aDSP侧都有相应的库已经完成了底层实现。之后有机会分析一下这种号称最为有效的多核间通信技术。

5,  应用处理器侧还有些乱七八糟的蓝色框,这部分是运行在应用处理器侧的sensor算法、校准相关的东西。这是些只会在非待机模式运行的算法,就适合放在这个地方了。

 

android中sensor架构

在android中sensor的架构图如下:


在Sensor1 API Socket Remoting Layer层的基础上转换成了android的Framwork层就可以被APP调用了,目前我们先以linux 应用程序的直接调用Sensor1 API Socket Remoting Layer层接口为例进行演示。


高通sensor测试工具

高通为sensor的测试提供了默认的工具,代码位于:

vendor\qcom\proprietary\sensors\dsps\test\src\sns_dsps_tc0001.c

vendor\qcom\proprietary\sensors\dsps\test\src\sns_cm_test.cpp

编译后生成对应的bin文件:

1,sns_dsps_tc0001用来查看当前系统挂载的sensor的相关信息:



2,sns_cm_test用来获取对应sensor_id的传感器数据:



Sensor的API接口:

1,

sensor1_error_e sensor1_open(sensor1_handle_s**hndl, sensor1_notify_data_cb_t data_cbf,  intptr_t cb_data );

hndl

Opaque handle used to identify this client

data_cbf

Pointer to the client’s callback function to process received data

cb_data

This data is set by the client and will be passed unmodified as a
parameter to the callback function

2,

typedef void (*sensor1_notify_data_cb_t) (uint32 cb_data, sensor1_msg_header_s* msg_hdr,  sensor1_msg_type_e msg_type, void *msg_ptr);

cb_data

Unmodified value passed in when the callback was registered in
sensor1_open()

msg_hdr

Message header defining the message

msg_type

Type of message

msg_ptr

Pointer to the QMI-based message; these messages are defined in their
respective service header files; client shall free this pointer via
sensor1_free_msg_buf()

3,

sensor1_error_e sensor1_close(sensor1_handle_s* hndl );

hndl

Opaque handle used to identify this client


4,

sensor1_error_e sensor1_write(sensor1_handle_s* hndl, sensor1_msg_header_s* msg_hdr, void *msg_ptr);

hndl

Opaque handle to identify this client

msg_hdr

Message header defining the message

msg_ptr

Pointer to the QMI-based request message; these messages are defined
in their respective service header files; memory pointed to shall be
allocated by sensor1_alloc_msg_buf()


5,

sensor1_error_e sensor1_writeable(sensor1_handle_s* hndl, sensor1_write_cb_t cbf, intptr_t cb_data, uint32_t service_number );

hndl

Opaque handle to identify this client

cbf

Pointer to the client’s callback function

cb_data

This data is set by the client and will be passed unmodified as a
parameter to the callback function

service_number

Client callback function will be called when it is possible that this
Service ID can accept new requests via sensor1_write


6,

typedef void (*sensor1_write_cb_t) (intptr_t cb_data, uint32_t service_number);

cb_data

Unmodified value passed in when the callback was registered in
sensor1_writable()

service_number

Service ID to which this callback refers


7,

sensor1_error_e sensor1_alloc_msg_buf(sensor1_handle_s* hndl,  uint16_t size,  void **buffer );

hndl

Opaque handle to identify this client

size

Size of the message structure

buffer

Address of a pointer to the memory address where the message should be
placed


8,

sensor1_error_e sensor1_free_msg_buf(sensor1_handle_s* hndl,  void* msg_buf );

hndl

Opaque handle to identify this client

msg_buf

Buffer to free



sns_cm_test.cpp代码实例

有了上面的api接口介绍,来看一下sns_cm_test.cpp中对其使用就比较清晰了:

  1. void parent_notify_data_cb( intptr_t data,  
  2.                             sensor1_msg_header_s *msg_hdr_ptr,  
  3.                             sensor1_msg_type_e msg_type,  
  4.                             voidvoid *msg_ptr )  
  5. {  
  6. #ifdef SNS_LA  
  7.   struct timespec now;  
  8.   static int i = 0;  
  9. #endif /* SNS_LA */  
  10.   ifNULL == msg_hdr_ptr ) {  
  11.     //printf(“\ncm_test: received NULL msg_hdr_ptr!\n”);  
  12.   } else {  
  13.     /* 
  14.     printf(“cm_test: hdr.service_number: %u\n\thdr.msg_id: %d\n\t” 
  15.            “hdr.msg_type: %d\n\thdr.msg_size: %d\n\thdr.txn_id: %d\n”, 
  16.            msg_hdr_ptr->service_number, 
  17.            msg_hdr_ptr->msg_id, 
  18.            msg_type, 
  19.            msg_hdr_ptr->msg_size, 
  20.            msg_hdr_ptr->txn_id ); 
  21.     */  
  22.     //printf(“*”);  
  23.     fflush(NULL);  
  24.   }  
  25.   
  26.   if( msg_type == SENSOR1_MSG_TYPE_RESP ) {  
  27.     //printf(“cm_test: received RESP\n”);  
  28.     pthread_mutex_lock( &my_mutex );  
  29.     my_predicate = 1;  
  30.     pthread_cond_signal( &my_cond );  
  31.     pthread_mutex_unlock( &my_mutex );  
  32.   } else if( msg_type == SENSOR1_MSG_TYPE_IND ) {  
  33.     //printf(“cm_test: received IND\n”);  
  34.     sns_smgr_periodic_report_ind_msg_v01 *ind_ptr = (sns_smgr_periodic_report_ind_msg_v01*)msg_ptr;  
  35.     uint32_t item_len = ind_ptr->Item_len;  
  36.     uint8_t id = ind_ptr->Item[0].SensorId;  
  37.     uint8_t type = ind_ptr->Item[0].DataType;  
  38.     uint8_t flag = ind_ptr->Item[0].ItemFlags;  
  39.     uint8_t quality = ind_ptr->Item[0].ItemQuality;  
  40.     int32_t *data = ind_ptr->Item[0].ItemData;  
  41.     printf(”ID=%d,Type=%d,Val=%d,%d,%d”id, type, data[0], data[1], data[2]);  
  42.     if (quality != SNS_SMGR_ITEM_QUALITY_FILTERED_V01)  
  43.       printf(”   Quality=%d,Flag=%d\n”, quality, flag);  
  44.     printf(”\n”);  
  45.   
  46.     if (item_len == 2) {  
  47.       id = ind_ptr->Item[1].SensorId;  
  48.       type = ind_ptr->Item[1].DataType;  
  49.       flag = ind_ptr->Item[1].ItemFlags;  
  50.       quality = ind_ptr->Item[1].ItemQuality;  
  51.       data = ind_ptr->Item[1].ItemData;  
  52.       printf(”ID=%d,Type=%d,Val=%d,%d,%d”id, type, data[0], data[1], data[2]);  
  53.       if (quality != SNS_SMGR_ITEM_QUALITY_FILTERED_V01)  
  54.         printf(”   Quality=%d,Flag=%d\n”, quality, flag);  
  55.       printf(”\n”);  
  56.     }  
  57.   } else if( msg_type == SENSOR1_MSG_TYPE_BROKEN_PIPE ) {  
  58.     printf(”\ncm_test: received BROKEN_PIPE!!!\n”);  
  59.   } else if( msg_type == SENSOR1_MSG_TYPE_RETRY_OPEN ) {  
  60.     printf(”\ncm_test: received RETRY_OPEN!!!\n”);  
  61.     error = sensor1_open( (sensor1_handle_s **)data,  
  62.                           parent_notify_data_cb,  
  63.                           (intptr_t)((sensor1_handle_s **)data) );  
  64.     if( SENSOR1_SUCCESS != error ) {  
  65.       printf(”\ncm_test: retry opened failed with %d\n”, error);  
  66.     } else {  
  67.       pthread_mutex_lock( &my_mutex );  
  68.       my_predicate = 4;  
  69.       pthread_cond_signal( &my_cond );  
  70.       pthread_mutex_unlock( &my_mutex );  
  71.     }  
  72.   } else {  
  73.     printf(”\ncm_test: received INVALID MSG type!!!\n”);  
  74.   }  
  75. #if defined(SNS_LA) && defined(SNS_LATENCY_MEASUREMENT)  
  76.   if( ((i % 10) == 0) &&  
  77.       msg_type == SENSOR1_MSG_TYPE_IND &&  
  78.       msg_hdr_ptr != NULL &&  
  79.       msg_hdr_ptr->msg_id == SNS_SMGR_REPORT_IND_V01 ) {  
  80.     int64_t delta;  
  81.     sns_smgr_periodic_report_ind_msg_v01 *rpt = msg_ptr;  
  82.   
  83.     get_dsps_clk_offset();  
  84.   
  85.     clock_gettime( CLOCK_REALTIME, &now);  
  86.     delta = ( (int64_t)now.tv_sec*1000000LL  
  87.               - (int64_t)dsps_clk_offset_usec  
  88.               + (int64_t)now.tv_nsec/1000LL  
  89.               - (int64_t)DSPS_TICK_TIME_USEC(rpt->Item[0].TimeStamp) );  
  90.   
  91.     printf(”Message one-way delay usec: %” PRId64 “\n”, delta);  
  92.     printf(”msg delay usec using ticks: %u\n”, dsps_clk_ticks - rpt->Item[0].TimeStamp );  
  93.   }  
  94.   i++;  
  95. #endif /* SNS_LA && SNS_LATENCY_MEASUREMENT */  
  96.   ifNULL != msg_ptr ) {  
  97.     sensor1_free_msg_buf( *((sensor1_handle_s**)data), msg_ptr );  
  98.   }  
  99. }  
  100.   
  101. void write_cb( intptr_t cb_data,  
  102.                uint32_t service_id )  
  103. {  
  104.   if( WRITABLE_DATA != (uintptr_t)cb_data ) {  
  105.     printf( ”\ncm_test: write_cb with wrong data %x\n”, (int)cb_data );  
  106.   }  
  107.   printf( ”\ncm_test: write_cb data\n” );  
  108.   pthread_mutex_lock( &my_mutex );  
  109.   my_predicate = 2;  
  110.   pthread_cond_signal( &my_cond );  
  111.   pthread_mutex_unlock( &my_mutex );  
  112. }  
  113.   
  114. void test_writable( sensor1_handle_s *hndl )  
  115. {  
  116.   printf(”Testing writable\n”);  
  117.   error = sensor1_writable( hndl,  
  118.                             write_cb,  
  119.                             WRITABLE_DATA,  
  120.                             (intptr_t)12 );  
  121.   if( SENSOR1_SUCCESS != error ) {  
  122.     printf(”\ncm_test: sensor1_writable returned %d\n”, error);  
  123.     exit(error);  
  124.   }  
  125.   // Make sure we get a response  
  126.   pthread_mutex_lock( &my_mutex );  
  127.   error = SENSOR1_SUCCESS;  
  128.   clock_gettime( CLOCK_REALTIME, &ts );  
  129.   while( my_predicate != 2 && error == SENSOR1_SUCCESS ) {  
  130.     ts.tv_sec += 1// wait 1 nsecond  
  131.     error = (sensor1_error_e)pthread_cond_timedwait( &my_cond, &my_mutex, &ts );  
  132.   }  
  133.   my_predicate = 0;  
  134.   pthread_mutex_unlock( &my_mutex );  
  135.   if( SENSOR1_SUCCESS != error ) {  
  136.     printf(”\nError while waiting for writable callback %d\n”, error);  
  137.     exit(error);  
  138.   } else {  
  139.     printf(”\nGot writable callback\n”);  
  140.   }  
  141.   
  142. }  
  143.   
  144. void test_write( sensor1_handle_s *hndl )  
  145. {  
  146.   printf(”Testing write\n”);  
  147.   error = sensor1_write( hndl,  
  148.                          &msg_hdr,  
  149.                          smgr_req );  
  150.   
  151.   if( SENSOR1_SUCCESS != error ) {  
  152.     printf(”\ncm_test: sensor1_write returned %d\n”, error);  
  153.     if( SENSOR1_EWOULDBLOCK != error ) {  
  154.       exit(error);  
  155.     }  
  156.   }  
  157.   // Make sure we get a response  
  158.   error = SENSOR1_SUCCESS;  
  159.   pthread_mutex_lock( &my_mutex );  
  160.   clock_gettime( CLOCK_REALTIME, &ts );  
  161.   while( my_predicate != 1 && error == SENSOR1_SUCCESS ) {  
  162.     ts.tv_sec += 100000000// wait 100msec  
  163.     error = (sensor1_error_e)pthread_cond_timedwait( &my_cond, &my_mutex, &ts );  
  164.   }  
  165.   my_predicate = 0;  
  166.   pthread_mutex_unlock( &my_mutex );  
  167.   if( SENSOR1_SUCCESS != error ) {  
  168.     printf(”\nError while waiting for response message %d\n”, error);  
  169.     exit(error);  
  170.   } else {  
  171.     printf(”\nGot response to message\n”);  
  172.   }  
  173. }  
  174.   
  175. void test_cancel( sensor1_handle_s *hndl )  
  176. {  
  177.   printf(”\nTesting cancel\n”);  
  178.   msg_hdr.service_number = SNS_SMGR_SVC_ID_V01;  
  179.   msg_hdr.msg_id = SNS_SMGR_CANCEL_REQ_V01;  
  180.   msg_hdr.msg_size = 0;  
  181.   msg_hdr.txn_id = 5;  
  182.   
  183.   error = sensor1_write( hndl,  
  184.                          &msg_hdr,  
  185.                          NULL );  
  186.   
  187.   if( SENSOR1_SUCCESS != error ) {  
  188.     printf(”\ncm_test: sensor1_write returned %d\n”, error);  
  189.     if( SENSOR1_EWOULDBLOCK != error ) {  
  190.       //exit(error);  
  191.     }  
  192.   }  
  193.   // Make sure we get a response  
  194.   error = SENSOR1_SUCCESS;  
  195.   pthread_mutex_lock( &my_mutex );  
  196.   clock_gettime( CLOCK_REALTIME, &ts );  
  197.   while( my_predicate != 1 && error == 0 ) {  
  198.     ts.tv_nsec += 100000000// wait 100msec  
  199.     error = (sensor1_error_e)pthread_cond_timedwait( &my_cond, &my_mutex, &ts );  
  200.   }  
  201.   my_predicate = 0;  
  202.   pthread_mutex_unlock( &my_mutex );  
  203.   if( SENSOR1_SUCCESS != error ) {  
  204.     printf(”\nError while waiting for response message %d\n”, error);  
  205.     //exit(error);  
  206.   } else {  
  207.     printf(”\nGot response to cancel\n”);  
  208.   }  
  209. }  
  210.   
  211. void test_invalid_writes( sensor1_handle_s *hndl)  
  212. {  
  213.   printf(”Testing write with NULL sensor handle\n”);  
  214.   error = sensor1_write( (sensor1_handle_s*)NULL,  
  215.                          &msg_hdr,  
  216.                          smgr_req );  
  217.   
  218.   if( SENSOR1_SUCCESS == error ) {  
  219.     printf(”\ncm_test: sensor1_write succeeded on NULL handle!\n”);  
  220.     if( SENSOR1_EWOULDBLOCK != error ) {  
  221.       exit(2);  
  222.     }  
  223.   }  
  224.   
  225.   printf(”Testing write with BAD sensor handle\n”);  
  226.   error = sensor1_write( (sensor1_handle_s*)0xBADADD,  
  227.                          &msg_hdr,  
  228.                          smgr_req );  
  229.   
  230.   if( SENSOR1_SUCCESS == error ) {  
  231.     printf(”\ncm_test: sensor1_write succeeded on bad handle!\n”);  
  232.     exit(2);  
  233.   }  
  234. }  
  235.   
  236. void test_open( sensor1_handle_s **hndl_ptr )  
  237. {  
  238.   printf(”Testing open\n”);  
  239.   error = sensor1_open( hndl_ptr,  
  240.                         parent_notify_data_cb,  
  241.                         (intptr_t)hndl_ptr );  
  242.   
  243.   if( SENSOR1_EWOULDBLOCK == error ) {  
  244.     printf(”\ncm_test: sensor1_open returned EWOULDBLOCK. Waiting 60 sec for sensor availability\n”);  
  245.     pthread_mutex_lock( &my_mutex );  
  246.     error = SENSOR1_SUCCESS;  
  247.     clock_gettime( CLOCK_REALTIME, &ts );  
  248.     while( my_predicate != 4 && error == 0 ) {  
  249.       ts.tv_sec += 60// wait 60 seconds  
  250.       error = (sensor1_error_e)pthread_cond_timedwait( &my_cond, &my_mutex, &ts );  
  251.     }  
  252.     if( my_predicate &= 4 ) {  
  253.       printf(”sensor1 now available\n”);  
  254.     } else {  
  255.       printf(”error waiting for sensor1\n”);  
  256.       exit(1);  
  257.     }  
  258.     my_predicate = 0;  
  259.     pthread_mutex_unlock( &my_mutex );  
  260.   } else if( SENSOR1_SUCCESS != error ) {  
  261.     printf(”\ncm_test: sensor1_open returned %d\n”, error);  
  262.     exit(error);  
  263.   }  
  264. }  
  265.   
  266. void test_alloc( sensor1_handle_s *hndl)  
  267. {  
  268.   printf(”Testing alloc\n”);  
  269.   error = sensor1_alloc_msg_buf( hndl,  
  270.                                  sizeof(sns_smgr_periodic_report_req_msg_v01),  
  271.                                  (void**)&smgr_req );  
  272.   if( SENSOR1_SUCCESS != error ) {  
  273.     printf(”\ncm_test: sensor1_alloc_msg_buf returned %d\n”, error);  
  274.     exit(error);  
  275.   }  
  276.   smgr_req->ReportId = 0;  
  277.   smgr_req->Action = SNS_SMGR_REPORT_ACTION_ADD_V01;  
  278.   smgr_req->ReportRate = 30// 30 Hz – 33 ms  
  279.   smgr_req->BufferFactor = 1;  
  280.   smgr_req->Item_len = 1;  
  281.   smgr_req->Item[0].SensorId = SNS_SMGR_ID_ACCEL_V01;  
  282.   smgr_req->Item[0].DataType = SNS_SMGR_DATA_TYPE_PRIMARY_V01;  
  283.   smgr_req->Item[0].Sensitivity = 0// Default  
  284.   smgr_req->Item[0].Decimation = SNS_SMGR_DECIMATION_FILTER_V01;  
  285.   smgr_req->Item[0].MinSampleRate = 0;  
  286.   smgr_req->Item[0].StationaryOption = SNS_SMGR_REST_OPTION_NO_REPORT_V01;  
  287.   smgr_req->Item[0].DoThresholdTest = 0;  
  288.   smgr_req->Item[0].ThresholdOutsideMinMax = 0;  
  289.   smgr_req->Item[0].ThresholdDelta = 0;  
  290.   smgr_req->Item[0].ThresholdAllAxes = 0;  
  291.   smgr_req->Item[0].ThresholdMinMax[0] = 0;  
  292.   smgr_req->Item[0].ThresholdMinMax[1] = 0;  
  293. }  
  294.   
  295. void test_delete( sensor1_handle_s *hndl )  
  296. {  
  297.   test_alloc( hndl );  
  298.   smgr_req->Action = SNS_SMGR_REPORT_ACTION_DELETE_V01;  
  299.   printf(”Testing delete\n”);  
  300.   error = sensor1_write( hndl,  
  301.                          &msg_hdr,  
  302.                          smgr_req );  
  303.   
  304.   if( SENSOR1_SUCCESS != error ) {  
  305.     printf(”\ncm_test: sensor1_write returned %d\n”, error);  
  306.     if( SENSOR1_EWOULDBLOCK != error ) {  
  307.       exit(error);  
  308.     }  
  309.   }  
  310.   // Make sure we get a response  
  311.   error = SENSOR1_SUCCESS;  
  312.   pthread_mutex_lock( &my_mutex );  
  313.   clock_gettime( CLOCK_REALTIME, &ts );  
  314.   while( my_predicate != 1 && error == 0 ) {  
  315.     ts.tv_sec += 100000000// wait 100msec  
  316.     error = (sensor1_error_e)pthread_cond_timedwait( &my_cond, &my_mutex, &ts );  
  317.   }  
  318.   my_predicate = 0;  
  319.   pthread_mutex_unlock( &my_mutex );  
  320.   if0 != error ) {  
  321.     printf(”\nError while waiting for response message %d\n”, error);  
  322.     exit(error);  
  323.   } else {  
  324.     printf(”\nGot response to message\n”);  
  325.   }  
  326. }  
  327.   
  328. void test_close( sensor1_handle_s *hndl )  
  329. {  
  330.   printf(”Testing close\n”);  
  331.   error = sensor1_close( hndl );  
  332.   if( SENSOR1_SUCCESS != error ) {  
  333.     printf(”\ncm_test: sensor1_close returned %d\n”, error);  
  334.     exit(error);  
  335.   }  
  336. }  
  337.   
  338. void init( void )  
  339. {  
  340.   
  341.   sensor1_init();  
  342.   
  343.   msg_hdr.service_number = SNS_SMGR_SVC_ID_V01;  
  344.   msg_hdr.msg_id = SNS_SMGR_REPORT_REQ_V01;  
  345.   msg_hdr.msg_size = sizeof(sns_smgr_periodic_report_req_msg_v01);  
  346.   msg_hdr.txn_id = 123;  
  347.   
  348.   pthread_mutex_init( &my_mutex, NULL );  
  349.   pthread_cond_init( &my_cond, NULL );  
  350.   
  351. #ifdef SNS_LA  
  352.   dsps_fd = open(”/dev/msm_dsps”, O_RDONLY );  
  353.   if( dsps_fd == -1 ) {  
  354.     //perror(“open(/dev/msm_dsps, O_RDONLY): ”);  
  355.   }  
  356.   
  357.   get_dsps_clk_offset();  
  358. #endif /* SNS_LA */  
  359. }  
  360.   
  361. int main( int argc, charchar * const argv[])  
  362. {  
  363.   sensor1_handle_s *hndl1;  
  364.   int               rate = 30;  
  365.   int               duration = 1;  
  366.   int               sensor_id =  SNS_SMGR_ID_ACCEL_V01;  
  367.   int               data_type = SNS_SMGR_DATA_TYPE_PRIMARY_V01;  
  368.   int               opt;  
  369.   struct timespec ts_mono, ts_real, ts_boot_start, ts_boot_end, ts_boot;  
  370.   uint64_t        elapsed_realtime;  
  371.   
  372.   //  socketpair( AF_UNIX, SOCK_SEQPACKET, 0, socket_pair );  
  373.   
  374.   while( (opt = getopt(argc, argv, “r:h:d:s:t:” ))!= -1 ) {  
  375.     switch(opt) {  
  376.       case ‘r’:  
  377.         rate = atoi(optarg);  
  378.         break;  
  379.       case ‘h’:  
  380.         dsps_clk_rate = atoi(optarg);  
  381.         break;  
  382.       case ‘d’:  
  383.         duration = atoi(optarg);  
  384.         break;  
  385.       case ’s’:  
  386.         sensor_id = atoi(optarg);  
  387.         break;  
  388.       case ‘t’:  
  389.         data_type = atoi(optarg);  
  390.         break;  
  391.       case ‘?’:  
  392.         fprintf(stderr, usage_fmt, argv[0]);  
  393.         exit(0);  
  394.       default:  
  395.         break;  
  396.     }  
  397.   }  
  398.   
  399.   clock_gettime( CLOCK_MONOTONIC, &ts_mono );  
  400.   clock_gettime( CLOCK_BOOTTIME, &ts_boot_start );  
  401.   elapsed_realtime = android::elapsedRealtimeNano();  
  402.   clock_gettime( CLOCK_BOOTTIME, &ts_boot_end );  
  403.   
  404.   ts_boot.tv_sec = (ts_boot_start.tv_sec + ts_boot_end.tv_sec) / 2;  
  405.   ts_boot.tv_nsec = (ts_boot_start.tv_nsec + ts_boot_end.tv_nsec) / 2;  
  406.   
  407.   clock_gettime( CLOCK_REALTIME, &ts_real );  
  408.   printf(”mono: %ld.%ld\nboot: %ld.%ld\nreal: %ld.%ld\n”,  
  409.          ts_mono.tv_sec,ts_mono.tv_nsec,  
  410.          ts_boot.tv_sec,ts_boot.tv_nsec,  
  411.          ts_real.tv_sec,ts_real.tv_nsec );  
  412.   printf(”\nmono: %lld\nboot: %lld\nreal: %lld\n”,  
  413.          ((uint64_t)ts_mono.tv_sec * 1000000000) + ts_mono.tv_nsec,  
  414.          ((uint64_t)ts_boot.tv_sec * 1000000000) + ts_boot.tv_nsec,  
  415.          ((uint64_t)ts_real.tv_sec * 1000000000) + ts_real.tv_nsec );  
  416.   printf(”\nelapsedRealtimeNano: %lld\n”, elapsed_realtime );  
  417.   printf(”Elapsed Realtime - clock_boottime: %lld\n”,  
  418.          ((uint64_t)ts_boot.tv_sec * 1000000000) + ts_boot.tv_nsec - elapsed_realtime );  
  419.   init();  
  420.   
  421.   test_open( &hndl1 );  
  422.   test_alloc( hndl1 );  
  423.   test_writable( hndl1 );  
  424.   printf(”Setting report rate to %d\n”, rate);  
  425.   smgr_req->ReportRate = rate;  
  426.   printf(”Asking sensor data with id %d\n”, sensor_id);  
  427.   
  428.   if ( (data_type == 0) || (data_type == 1) )  
  429.   {  
  430.     smgr_req->Item[0].SensorId = sensor_id;  
  431.     smgr_req->Item[0].DataType = data_type;  
  432.   } else {  
  433.     // request for both primary and secondary  
  434.     smgr_req->Item_len = 2;  
  435.     smgr_req->Item[0].SensorId = sensor_id;  
  436.     smgr_req->Item[0].DataType = SNS_SMGR_DATA_TYPE_PRIMARY_V01;  
  437.     smgr_req->Item[1].SensorId = sensor_id;  
  438.     smgr_req->Item[1].DataType = SNS_SMGR_DATA_TYPE_SECONDARY_V01;  
  439.     smgr_req->Item[1].Sensitivity = 0// Default  
  440.     smgr_req->Item[1].Decimation = SNS_SMGR_DECIMATION_FILTER_V01;  
  441.     smgr_req->Item[1].MinSampleRate = 0;  
  442.     smgr_req->Item[1].StationaryOption = SNS_SMGR_REST_OPTION_NO_REPORT_V01;  
  443.     smgr_req->Item[1].DoThresholdTest = 0;  
  444.     smgr_req->Item[1].ThresholdOutsideMinMax = 0;  
  445.     smgr_req->Item[1].ThresholdDelta = 0;  
  446.     smgr_req->Item[1].ThresholdAllAxes = 0;  
  447.     smgr_req->Item[1].ThresholdMinMax[0] = 0;  
  448.     smgr_req->Item[1].ThresholdMinMax[1] = 0;  
  449.   }  
  450.   
  451.   test_write( hndl1 );  
  452.   printf(”returned from test_write\n”);  
  453.   
  454.   while (duration == 0) {  
  455.     // wait forever  
  456.     sleep(1);  
  457.   }  
  458.   sleep(duration);  
  459.   test_delete( hndl1 );  
  460.   
  461.   test_invalid_writes( hndl1 );  
  462.   sleep(2);  
  463.   
  464.   usleep(100);  
  465.   test_cancel( hndl1 );  
  466.   sleep(5);  
  467.   printf(”Parent calling close\n”);  
  468.   test_close( hndl1 );  
  469.   printf(”Parent close returned\n”);  
  470.   
  471.   wait(NULL);  
  472.   printf(”All tests passed\n”);  
  473.   
  474.   return 0;  
  475. }  
void parent_notify_data_cb( intptr_t data,
                            sensor1_msg_header_s *msg_hdr_ptr,
                            sensor1_msg_type_e msg_type,
                            void *msg_ptr )
{




ifdef SNS_LA

struct timespec now;
static int i = 0;

endif /* SNS_LA */

if( NULL == msg_hdr_ptr ) {
//printf("\ncm_test: received NULL msg_hdr_ptr!\n");
} else {
/*
printf("cm_test: hdr.service_number: %u\n\thdr.msg_id: %d\n\t"
"hdr.msg_type: %d\n\thdr.msg_size: %d\n\thdr.txn_id: %d\n",
msg_hdr_ptr->service_number,
msg_hdr_ptr->msg_id,
msg_type,
msg_hdr_ptr->msg_size,
msg_hdr_ptr->txn_id );
*/
//printf("*");
fflush(NULL);
}

if( msg_type == SENSOR1_MSG_TYPE_RESP ) {
//printf("cm_test: received RESP\n");
pthread_mutex_lock( &my_mutex );
my_predicate = 1;
pthread_cond_signal( &my_cond );
pthread_mutex_unlock( &my_mutex );
} else if( msg_type == SENSOR1_MSG_TYPE_IND ) {
//printf("cm_test: received IND\n");
sns_smgr_periodic_report_ind_msg_v01 ind_ptr = (sns_smgr_periodic_report_ind_msg_v01)msg_ptr;
uint32_t item_len = ind_ptr->Item_len;
uint8_t id = ind_ptr->Item[0].SensorId;
uint8_t type = ind_ptr->Item[0].DataType;
uint8_t flag = ind_ptr->Item[0].ItemFlags;
uint8_t quality = ind_ptr->Item[0].ItemQuality;
int32_t *data = ind_ptr->Item[0].ItemData;
printf("ID=%d,Type=%d,Val=%d,%d,%d", id, type, data[0], data[1], data[2]);
if (quality != SNS_SMGR_ITEM_QUALITY_FILTERED_V01)
printf(" Quality=%d,Flag=%d\n", quality, flag);
printf("\n");

if (item_len == 2) {
  id = ind_ptr->Item[1].SensorId;
  type = ind_ptr->Item[1].DataType;
  flag = ind_ptr->Item[1].ItemFlags;
  quality = ind_ptr->Item[1].ItemQuality;
  data = ind_ptr->Item[1].ItemData;
  printf("ID=%d,Type=%d,Val=%d,%d,%d", id, type, data[0], data[1], data[2]);
  if (quality != SNS_SMGR_ITEM_QUALITY_FILTERED_V01)
    printf("   Quality=%d,Flag=%d\n", quality, flag);
  printf("\n");
}

} else if( msg_type == SENSOR1_MSG_TYPE_BROKEN_PIPE ) {
printf(“\ncm_test: received BROKEN_PIPE!!!\n”);
} else if( msg_type == SENSOR1_MSG_TYPE_RETRY_OPEN ) {
printf(“\ncm_test: received RETRY_OPEN!!!\n”);
error = sensor1_open( (sensor1_handle_s **)data,
parent_notify_data_cb,
(intptr_t)((sensor1_handle_s **)data) );
if( SENSOR1_SUCCESS != error ) {
printf(“\ncm_test: retry opened failed with %d\n”, error);
} else {
pthread_mutex_lock( &my_mutex );
my_predicate = 4;
pthread_cond_signal( &my_cond );
pthread_mutex_unlock( &my_mutex );
}
} else {
printf(“\ncm_test: received INVALID MSG type!!!\n”);
}

if defined(SNS_LA) && defined(SNS_LATENCY_MEASUREMENT)

if( ((i % 10) == 0) &&
msg_type == SENSOR1_MSG_TYPE_IND &&
msg_hdr_ptr != NULL &&
msg_hdr_ptr->msg_id == SNS_SMGR_REPORT_IND_V01 ) {
int64_t delta;
sns_smgr_periodic_report_ind_msg_v01 *rpt = msg_ptr;

get_dsps_clk_offset();

clock_gettime( CLOCK_REALTIME, &now);
delta = ( (int64_t)now.tv_sec*1000000LL
          - (int64_t)dsps_clk_offset_usec
          + (int64_t)now.tv_nsec/1000LL
          - (int64_t)DSPS_TICK_TIME_USEC(rpt->Item[0].TimeStamp) );

printf("Message one-way delay usec: %" PRId64 "\n", delta);
printf("msg delay usec using ticks: %u\n", dsps_clk_ticks - rpt->Item[0].TimeStamp );

}
i++;

endif /* SNS_LA && SNS_LATENCY_MEASUREMENT */

if( NULL != msg_ptr ) {
sensor1_free_msg_buf( ((sensor1_handle_s*)data), msg_ptr );
}
}

void write_cb( intptr_t cb_data,
uint32_t service_id )
{
if( WRITABLE_DATA != (uintptr_t)cb_data ) {
printf( “\ncm_test: write_cb with wrong data %x\n”, (int)cb_data );
}
printf( “\ncm_test: write_cb data\n” );
pthread_mutex_lock( &my_mutex );
my_predicate = 2;
pthread_cond_signal( &my_cond );
pthread_mutex_unlock( &my_mutex );
}

void test_writable( sensor1_handle_s *hndl )
{
printf(“Testing writable\n”);
error = sensor1_writable( hndl,
write_cb,
WRITABLE_DATA,
(intptr_t)12 );
if( SENSOR1_SUCCESS != error ) {
printf(“\ncm_test: sensor1_writable returned %d\n”, error);
exit(error);
}
// Make sure we get a response
pthread_mutex_lock( &my_mutex );
error = SENSOR1_SUCCESS;
clock_gettime( CLOCK_REALTIME, &ts );
while( my_predicate != 2 && error == SENSOR1_SUCCESS ) {
ts.tv_sec += 1; // wait 1 nsecond
error = (sensor1_error_e)pthread_cond_timedwait( &my_cond, &my_mutex, &ts );
}
my_predicate = 0;
pthread_mutex_unlock( &my_mutex );
if( SENSOR1_SUCCESS != error ) {
printf(“\nError while waiting for writable callback %d\n”, error);
exit(error);
} else {
printf(“\nGot writable callback\n”);
}

}

void test_write( sensor1_handle_s *hndl )
{
printf(“Testing write\n”);
error = sensor1_write( hndl,
&msg_hdr,
smgr_req );

if( SENSOR1_SUCCESS != error ) {
printf(“\ncm_test: sensor1_write returned %d\n”, error);
if( SENSOR1_EWOULDBLOCK != error ) {
exit(error);
}
}
// Make sure we get a response
error = SENSOR1_SUCCESS;
pthread_mutex_lock( &my_mutex );
clock_gettime( CLOCK_REALTIME, &ts );
while( my_predicate != 1 && error == SENSOR1_SUCCESS ) {
ts.tv_sec += 100000000; // wait 100msec
error = (sensor1_error_e)pthread_cond_timedwait( &my_cond, &my_mutex, &ts );
}
my_predicate = 0;
pthread_mutex_unlock( &my_mutex );
if( SENSOR1_SUCCESS != error ) {
printf(“\nError while waiting for response message %d\n”, error);
exit(error);
} else {
printf(“\nGot response to message\n”);
}
}

void test_cancel( sensor1_handle_s *hndl )
{
printf(“\nTesting cancel\n”);
msg_hdr.service_number = SNS_SMGR_SVC_ID_V01;
msg_hdr.msg_id = SNS_SMGR_CANCEL_REQ_V01;
msg_hdr.msg_size = 0;
msg_hdr.txn_id = 5;

error = sensor1_write( hndl,
&msg_hdr,
NULL );

if( SENSOR1_SUCCESS != error ) {
printf(“\ncm_test: sensor1_write returned %d\n”, error);
if( SENSOR1_EWOULDBLOCK != error ) {
//exit(error);
}
}
// Make sure we get a response
error = SENSOR1_SUCCESS;
pthread_mutex_lock( &my_mutex );
clock_gettime( CLOCK_REALTIME, &ts );
while( my_predicate != 1 && error == 0 ) {
ts.tv_nsec += 100000000; // wait 100msec
error = (sensor1_error_e)pthread_cond_timedwait( &my_cond, &my_mutex, &ts );
}
my_predicate = 0;
pthread_mutex_unlock( &my_mutex );
if( SENSOR1_SUCCESS != error ) {
printf(“\nError while waiting for response message %d\n”, error);
//exit(error);
} else {
printf(“\nGot response to cancel\n”);
}
}

void test_invalid_writes( sensor1_handle_s *hndl)
{
printf(“Testing write with NULL sensor handle\n”);
error = sensor1_write( (sensor1_handle_s*)NULL,
&msg_hdr,
smgr_req );

if( SENSOR1_SUCCESS == error ) {
printf(“\ncm_test: sensor1_write succeeded on NULL handle!\n”);
if( SENSOR1_EWOULDBLOCK != error ) {
exit(2);
}
}

printf(“Testing write with BAD sensor handle\n”);
error = sensor1_write( (sensor1_handle_s*)0xBADADD,
&msg_hdr,
smgr_req );

if( SENSOR1_SUCCESS == error ) {
printf(“\ncm_test: sensor1_write succeeded on bad handle!\n”);
exit(2);
}
}

void test_open( sensor1_handle_s **hndl_ptr )
{
printf(“Testing open\n”);
error = sensor1_open( hndl_ptr,
parent_notify_data_cb,
(intptr_t)hndl_ptr );

if( SENSOR1_EWOULDBLOCK == error ) {
printf(“\ncm_test: sensor1_open returned EWOULDBLOCK. Waiting 60 sec for sensor availability\n”);
pthread_mutex_lock( &my_mutex );
error = SENSOR1_SUCCESS;
clock_gettime( CLOCK_REALTIME, &ts );
while( my_predicate != 4 && error == 0 ) {
ts.tv_sec += 60; // wait 60 seconds
error = (sensor1_error_e)pthread_cond_timedwait( &my_cond, &my_mutex, &ts );
}
if( my_predicate &= 4 ) {
printf(“sensor1 now available\n”);
} else {
printf(“error waiting for sensor1\n”);
exit(1);
}
my_predicate = 0;
pthread_mutex_unlock( &my_mutex );
} else if( SENSOR1_SUCCESS != error ) {
printf(“\ncm_test: sensor1_open returned %d\n”, error);
exit(error);
}
}

void test_alloc( sensor1_handle_s *hndl)
{
printf(“Testing alloc\n”);
error = sensor1_alloc_msg_buf( hndl,
sizeof(sns_smgr_periodic_report_req_msg_v01),
(void**)&smgr_req );
if( SENSOR1_SUCCESS != error ) {
printf(“\ncm_test: sensor1_alloc_msg_buf returned %d\n”, error);
exit(error);
}
smgr_req->ReportId = 0;
smgr_req->Action = SNS_SMGR_REPORT_ACTION_ADD_V01;
smgr_req->ReportRate = 30; // 30 Hz – 33 ms
smgr_req->BufferFactor = 1;
smgr_req->Item_len = 1;
smgr_req->Item[0].SensorId = SNS_SMGR_ID_ACCEL_V01;
smgr_req->Item[0].DataType = SNS_SMGR_DATA_TYPE_PRIMARY_V01;
smgr_req->Item[0].Sensitivity = 0; // Default
smgr_req->Item[0].Decimation = SNS_SMGR_DECIMATION_FILTER_V01;
smgr_req->Item[0].MinSampleRate = 0;
smgr_req->Item[0].StationaryOption = SNS_SMGR_REST_OPTION_NO_REPORT_V01;
smgr_req->Item[0].DoThresholdTest = 0;
smgr_req->Item[0].ThresholdOutsideMinMax = 0;
smgr_req->Item[0].ThresholdDelta = 0;
smgr_req->Item[0].ThresholdAllAxes = 0;
smgr_req->Item[0].ThresholdMinMax[0] = 0;
smgr_req->Item[0].ThresholdMinMax[1] = 0;
}

void test_delete( sensor1_handle_s *hndl )
{
test_alloc( hndl );
smgr_req->Action = SNS_SMGR_REPORT_ACTION_DELETE_V01;
printf(“Testing delete\n”);
error = sensor1_write( hndl,
&msg_hdr,
smgr_req );

if( SENSOR1_SUCCESS != error ) {
printf(“\ncm_test: sensor1_write returned %d\n”, error);
if( SENSOR1_EWOULDBLOCK != error ) {
exit(error);
}
}
// Make sure we get a response
error = SENSOR1_SUCCESS;
pthread_mutex_lock( &my_mutex );
clock_gettime( CLOCK_REALTIME, &ts );
while( my_predicate != 1 && error == 0 ) {
ts.tv_sec += 100000000; // wait 100msec
error = (sensor1_error_e)pthread_cond_timedwait( &my_cond, &my_mutex, &ts );
}
my_predicate = 0;
pthread_mutex_unlock( &my_mutex );
if( 0 != error ) {
printf(“\nError while waiting for response message %d\n”, error);
exit(error);
} else {
printf(“\nGot response to message\n”);
}
}

void test_close( sensor1_handle_s *hndl )
{
printf(“Testing close\n”);
error = sensor1_close( hndl );
if( SENSOR1_SUCCESS != error ) {
printf(“\ncm_test: sensor1_close returned %d\n”, error);
exit(error);
}
}

void init( void )
{

sensor1_init();

msg_hdr.service_number = SNS_SMGR_SVC_ID_V01;
msg_hdr.msg_id = SNS_SMGR_REPORT_REQ_V01;
msg_hdr.msg_size = sizeof(sns_smgr_periodic_report_req_msg_v01);
msg_hdr.txn_id = 123;

pthread_mutex_init( &my_mutex, NULL );
pthread_cond_init( &my_cond, NULL );

ifdef SNS_LA

dsps_fd = open(“/dev/msm_dsps”, O_RDONLY );
if( dsps_fd == -1 ) {
//perror(“open(/dev/msm_dsps, O_RDONLY): “);
}

get_dsps_clk_offset();

endif /* SNS_LA */

}

int main( int argc, char * const argv[])
{
sensor1_handle_s *hndl1;
int rate = 30;
int duration = 1;
int sensor_id = SNS_SMGR_ID_ACCEL_V01;
int data_type = SNS_SMGR_DATA_TYPE_PRIMARY_V01;
int opt;
struct timespec ts_mono, ts_real, ts_boot_start, ts_boot_end, ts_boot;
uint64_t elapsed_realtime;

// socketpair( AF_UNIX, SOCK_SEQPACKET, 0, socket_pair );

while( (opt = getopt(argc, argv, “r:h:d:s:t:” ))!= -1 ) {
switch(opt) {
case ‘r’:
rate = atoi(optarg);
break;
case ‘h’:
dsps_clk_rate = atoi(optarg);
break;
case ‘d’:
duration = atoi(optarg);
break;
case ‘s’:
sensor_id = atoi(optarg);
break;
case ‘t’:
data_type = atoi(optarg);
break;
case ‘?’:
fprintf(stderr, usage_fmt, argv[0]);
exit(0);
default:
break;
}
}

clock_gettime( CLOCK_MONOTONIC, &ts_mono );
clock_gettime( CLOCK_BOOTTIME, &ts_boot_start );
elapsed_realtime = android::elapsedRealtimeNano();
clock_gettime( CLOCK_BOOTTIME, &ts_boot_end );

ts_boot.tv_sec = (ts_boot_start.tv_sec + ts_boot_end.tv_sec) / 2;
ts_boot.tv_nsec = (ts_boot_start.tv_nsec + ts_boot_end.tv_nsec) / 2;

clock_gettime( CLOCK_REALTIME, &ts_real );
printf(“mono: %ld.%ld\nboot: %ld.%ld\nreal: %ld.%ld\n”,
ts_mono.tv_sec,ts_mono.tv_nsec,
ts_boot.tv_sec,ts_boot.tv_nsec,
ts_real.tv_sec,ts_real.tv_nsec );
printf(“\nmono: %lld\nboot: %lld\nreal: %lld\n”,
((uint64_t)ts_mono.tv_sec * 1000000000) + ts_mono.tv_nsec,
((uint64_t)ts_boot.tv_sec * 1000000000) + ts_boot.tv_nsec,
((uint64_t)ts_real.tv_sec * 1000000000) + ts_real.tv_nsec );
printf(“\nelapsedRealtimeNano: %lld\n”, elapsed_realtime );
printf(“Elapsed Realtime - clock_boottime: %lld\n”,
((uint64_t)ts_boot.tv_sec * 1000000000) + ts_boot.tv_nsec - elapsed_realtime );
init();

test_open( &hndl1 );
test_alloc( hndl1 );
test_writable( hndl1 );
printf(“Setting report rate to %d\n”, rate);
smgr_req->ReportRate = rate;
printf(“Asking sensor data with id %d\n”, sensor_id);

if ( (data_type == 0) || (data_type == 1) )
{
smgr_req->Item[0].SensorId = sensor_id;
smgr_req->Item[0].DataType = data_type;
} else {
// request for both primary and secondary
smgr_req->Item_len = 2;
smgr_req->Item[0].SensorId = sensor_id;
smgr_req->Item[0].DataType = SNS_SMGR_DATA_TYPE_PRIMARY_V01;
smgr_req->Item[1].SensorId = sensor_id;
smgr_req->Item[1].DataType = SNS_SMGR_DATA_TYPE_SECONDARY_V01;
smgr_req->Item[1].Sensitivity = 0; // Default
smgr_req->Item[1].Decimation = SNS_SMGR_DECIMATION_FILTER_V01;
smgr_req->Item[1].MinSampleRate = 0;
smgr_req->Item[1].StationaryOption = SNS_SMGR_REST_OPTION_NO_REPORT_V01;
smgr_req->Item[1].DoThresholdTest = 0;
smgr_req->Item[1].ThresholdOutsideMinMax = 0;
smgr_req->Item[1].ThresholdDelta = 0;
smgr_req->Item[1].ThresholdAllAxes = 0;
smgr_req->Item[1].ThresholdMinMax[0] = 0;
smgr_req->Item[1].ThresholdMinMax[1] = 0;
}

test_write( hndl1 );
printf(“returned from test_write\n”);

while (duration == 0) {
// wait forever
sleep(1);
}
sleep(duration);
test_delete( hndl1 );

test_invalid_writes( hndl1 );
sleep(2);

usleep(100);
test_cancel( hndl1 );
sleep(5);
printf(“Parent calling close\n”);
test_close( hndl1 );
printf(“Parent close returned\n”);

wait(NULL);
printf(“All tests passed\n”);

return 0;
}




  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值