FFBM 的设计于实现

来源:互联网 发布:javascript 输入 编辑:程序博客网 时间:2024/04/29 07:30
  • 简单说来就是关机工模,为了厂测的工具。就是简单的测试手机硬件和基本的功能。本着学习的态度,来把这个小应用写写。
    这个应用是在fastmmi文件夹下,总体是c/c++的实现。秉承了面向对象的设计理念,模块间的解耦高,独立性强。适用于LINUX嵌入式的开发理念。
    步入正题:
    主模块:孵化以下的模块,构建公共通信总服务器。
    视图模块:miniui
    控制模块:串口指令,TP输入指令,
    单元模型模块:工作单位如:测试蓝牙,WIFI,sensor,gps.
    进程间通信的方式:socket接口 UNIX套接字。
    下面是较为详细的说明:
    int main(int argc, char **argv) {
    signal(SIGCHLD, exit_handler); 安装信号处理线程退出
    int ret = -1;

init(); 使能mmi唤醒锁,初始化g_sem_exit
g_msg_sem g_sem_accept_ready 三个信号量,和g_cur_layout_mutex 线程锁,窗口初始化,初始化功能hash_map表。

get_lcd_resolution();                           lcd_resolution  720p

mkdirs(MMI_BASE_DIR); mkdir “/cache/FTM_AP/” chmod 777

ret = init_config(MMI_CONFIG); 初始化配置文件
load_config 读取每个测试项文件的功能测试到hashmap中和list中
if(ret < 0)
return -1;

init_controller(); 初始化一个DIAG DEBUG
module_info

restore_result(g_res_file);restore_result(g_res_sensor_file);  读取以前的测试信息文件restore_result_pcba(g_res_pcba_file);restore_result_mmi_runin(g_res_mmi_runin_file);restore_result(g_res_mmi_audio_file);

initTestFlag(); 读取mmi 和 pcba的测试状态

initSensorTestFlag();
initAudioTestFlag();
nitMmiFullTestFlag();

build_main_ui(); 构建ui

start_threads(); 创建线程
input_waiting_thread 输入等待线程
init_input();初始化
ev_init(input_callback,)回调函数:获 取按键状态,创建runable list
sem_post(&g_sem_runable);发送信号量
ev_wait(-1);循环等待
ev_dispatch(); 按键派发
input_handle_thread 输入执行线程
sem_wait(&g_sem_runable); 等待信号量
cb(mod);
runnable_list.clear();
draw_thread 绘图线程
sem_wait(&g_sem_draw);等待信号量
acquire_cur_layout();获取当前的布局
clear_screen(); 清屏
draw_buttons(lay);draw 按键
draw_textviews(lay);
draw_listviews(lay);
draw_points(lay);
release_cur_layout();
gr_flip(); 刷新显示内容
server_accepting_thread 服务接收线程
create_socket(MMI_SOCKET); 创建sock
listen(sockfd, 8); 监听
sem_post(&g_sem_accept_ready); 发送信号量
accept();获取client的fd
module_set_fd; 安装fd 到msg的module中
get_module_by_name 通过msg.msg确定 类型通过msg.module确认module_name
返回mod 数据体
g_clients.push_back(mi);添加到list

msg_waiting_thread 消息等待线程
Select();监视 client fd
recv(fd, msg, sizeof(msg_t), MSG_WAITALL));
获取msg 管理client_fd
enqueue_msg(&g_msg_queue, msg);
添加msg 到全局的Queue List中
sem_post(&g_msg_sem); 发送信号量

msg_handle_thread 消息处理线程
sem_wait(&g_msg_sem);等待信号量
dequeue_msg(&g_msg_queue, &msg);
queue->queue.front();取出第一个元素
queue->queue.pop_front();删除第一个元素
Mod=get_module_by_name(msg->module,NULL);获取module——info
Switch
case CMD_CTRL:

launch_controller();launch_clients();/*Start Background Test */if(is_autostart())    start_all(true);write_file("/sys/class/leds/wled-backlight/brightness", "255");sem_wait(&g_sem_exit);write_file(WAKE_UNLOCK, "mmi");

out:sem_close(&g_sem_exit);
return 0;
}

case CMD_RUN:
handle_run(msg, mod);
!strcmp(msg->subcmd, SUBCMD_MMI mmi test
!strcmp(msg->subcmd, SUBCMD_PCBA pcba test
update_button_status(lay);
invalidate(); 刷新

case CMD_CTRL:
handle_ctr_msg(msg, mod);
parse_parameter(msg->msg, params); 将msg.msg 转化成hashmap

!strcmp(msg->subcmd, “runcase”) ; 区分测试项
build_test_menu(TEST_MENU_MMI_TEST);
创建相应的menu如 PCBA MMI
do_ctrl_runcase(&resp, params[“case_name”]);
if(!strcmp(“GSENSOR”, module_name.c_str())) 区分测试内容
strcpy(g_ata_sensor_item, module_name.c_str()); 赋值全局变量
module_name = “GSENSOR”; 赋值测试项
module_info *mod = NULL; 定义module数据指针
mod = g_modules_map[ module_name]; 通过module_name获取对应的数据结构
lay = switch_cur_layout_locked(lay, mod); 切换界面
acquire_cur_layout();
pthread_mutex_lock(&g_cur_layout_mutex);
g_cur_layout = lay;
g_cur_layout->module = mod; 填充测试内容的界面
release_cur_layout();
pthread_mutex_unlock(&g_cur_layout_mutex);
initial_screen(mod); 添加测试内容的特性如 display文本颜色等
module_exec_pcba(mod); 测试的实际的动作
invalidate(); 更新UI
sem_post(&g_sem_draw);
resp->result = SUCCESS; 执行状态 完成

void module_exec_pcba(module_info * mod)
is_local_module(mod); 遍历list表是否是本地的module
True
launch_local_module
False
run_sensor_test_spec(mod);
send_run_extra(mod, subcmd); 发送对应的cmd给模块
send_cmd(mod, CMD_RUN, subcmd);
ret = send_msg(sock, &msg);
ret = write(fd, msg, sizeof(msg_t)); 发送给agent_main.cpp

分析agent_main.cpp
ret = load_module(lib_path, &g_module); 加载 module 库

g_module->cb_print = print_msg; 初始化回调功能 发送给mmi.cpp进行显示操作
msg.cmd = CMD_PRINT; send_msg(g_sock, &msg);

g_module->cb_client_control_server = client_control_server; 初始化回调功能
处理来自mmi.cpp运行响应
msg.cmd = CMD_CLIENT_CONTROL_SERVER; send_msg(g_sock, &msg);

g_sock = connect_server(MMI_SOCKET); 建立于服务端的链接

ret = g_module->methods->module_init(g_module, module_params); 模块的初始module_init
err = hw_get_module(SENSORS_HARDWARE_MODULE_ID, (hw_module_t const **) &hal_mod); 获取库的hw_module_t
err = sensors_open_ext(&hal_mod->common, &device);
dev_count = hal_mod->get_sensors_list(hal_mod, &sensor_list);
获取sensorlist 保存在sensor_list
err = device->activate((sensors_poll_device_t *) device, sensor_list[i].handle, 0);
使能特定的传感器

ret = pthread_create(&pid_wait, NULL, msg_waiting_thread, &g_sock);
创建一个消息获取线程
recv_size = recv(sock, msg, sizeof(msg_t), MSG_WAITALL)) sock 接收mmi.cpp 的msg
enqueue_msg(&g_msg_queue, msg); 添加msg到list < msg_t * >中
sem_post(&g_msg_sem); 发送信号量

ret = pthread_create(&pid_handle, NULL, msg_handle_thread, NULL);
处理消息的线程
sem_wait(&g_msg_sem); 等待信号量
dequeue_msg(&g_msg_queue, &msg); 把msg从链表中删除
ret = pthread_create(&ptid, NULL, msg_process_thread, msg); 创建一个线程处理
Switch 处理不同的case
case CMD_RUN:
ret = handle_run(g_module, preq, &resp);
parse_parameter(req->msg, params)通过输入参数 获取模块
ret = module->methods->module_run(module, req->subcmd, params);

Sensor.cpp

Module_run :

if(!strcmp(cmd, SUBCMD_MMI))
ret = module_run_mmi(module, params);
else if(!strcmp(cmd, SUBCMD_PCBA))
ret = module_run_pcba(module, params);
else if(!strcmp(cmd, subcmd_calibration))
ret = module_run_calibration(module, params);
module_run_calibration sensors模块校准
获取sensor_type,
对应的处理校准
ret = gsensor_calibration();
gs_fd= open(“/dev/gsensor”, O_RDONLY); 打开设备
ioctl(gs_fd, GS_GET_RAW_DATA_FOR_CALI, &gs_cali);
驱动层 bma2x2.c
case GS_GET_RAW_DATA_FOR_CALI:
bma2x2_read_accel_xyz(data->bma2x2_client,data->sensor_type, &acc);
rawdata.x = acc.x;
rawdata.y = acc.y;
rawdata.z = acc.z;
rawdata.offset = 1024;
if (copy_to_user(argp, &rawdata, sizeof(rawdata))) {
return -EFAULT;
}
break;
获取x-y-z 的值
ioctl(gs_fd, GS_FAC_CAL);
case GS_FAC_CAL:
if( bma2xx_offset_fast_cali(0,0,1)==0)
break;
gsensor_calibration_nv_write() 写NV 值
ioctl(gs_fd, GS_REC_DATA_FOR_PER, &gs_sum2); 获取data
close(gs_fd); 关闭设备节点

返回结果 ret
在 agent_main.cpp中返回校验结果
send_msg(g_sock, &resp);
在test的状态下
module_run_pcba(const mmi_module_t * module, hash_map < string, string > &params)
get_sensor_data(cur_sensor_type, &event);获取sensor的数据

print_event(&event, module,false);
设置显示信息 和 要保存的信息
mod->cb_print(cur_module_name, SUBCMD_MMI, print_buf, strlen(print_buf), PRINT_DATA);
这是一个回调的函数
发送给server既(MMI.cpp)
Serverd端显和保存

总结:
关机工模测试是一个用来测试各种sensor,tp,audio,camera,等,硬件和驱动接口是否正常的一个应用。
流程:
通过按键输入和电脑端口命令,来测试不同的功能,大致的流程是一样的,
获取msg 这个msg的数据结构包括,module的name,sumcmd(子命令),等
通过不同的module_name和命令执行相应的操作,
Mmi作为服务端负责数据的处理,解析按键的动作和端口命令,发送给连接上来的客户端,让客户端(agent.mmi)处理。代理端通过load不同的实现库(如sensor)来将msg发给具体的模块来处理获取数据或操作设备节点,
其中module_init将调用hal层的sensors 的open方法等.Module_run将完成测试的内容,返回测试结果到服务端,显示保存结果。

0 0
原创粉丝点击