本系列导航:
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 |
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 |
→ | 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 |
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 |
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 |
→ | service_number | Client callback function will be called when it is possible that this |
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 |
→ | 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 |
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中对其使用就比较清晰了:
- void parent_notify_data_cb( intptr_t data,
- sensor1_msg_header_s *msg_hdr_ptr,
- sensor1_msg_type_e msg_type,
- voidvoid *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, charchar * 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;
- }
![](http://static.blog.csdn.net/images/save_snippets.png)
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;
}