电子产品量产工具(输入系统)

所学来自百问网

目录

1.输入系统

2. 数据结构的抽象

3. 底层的管理

4. 触摸屏编程

5. 触摸屏单元测试

6. 网络输入编程

7. 客户端

8. 网络单元测试

9. 综合测试


1.输入系统

2. 数据结构的抽象

input_manager.h:该文件对触摸屏和网络输入设备进行数据结构的抽象

#ifndef _INPUT_MANAGER_H
#define _INPUT_MANAGER_H
​
#include <sys/time.h>
​
#ifndef NULL
#define NULL (void *)0
#endif
​
#define INPUT_TYPE_TOUCH 1  // 触摸屏
#define INPUT_TYPE_NET 2    // 网络
​
// 表示事件本身
typedef struct InputEvent{
    // 结构体 表时间
    struct timeval tTime;
    int iType; // 表示的是触摸屏还是网络数据
    // 触摸屏数据
    int iX;
    int iY;
    int iPressure;
    // 存储网络数据
    char str[1024];
}InputEvent,*PInputEvent;
​
// 表输入设备
typedef struct InputDevice{
    // 设备名字 表示那种设备
    char *name;
    // 获取输入设备数据
    int (*GetInputEvent)(PInputEvent ptInputEvent);
    // 输入设备初始化函数和退出函数
    int (*DeviceInit)(void);
    int (*DeviceExit)(void);
    // 链表 可支持多个设备
    struct InputDevice *ptNext;
}InputDevice,*PInputDevice;
​
void RegisterInputDevice(PInputDevice ptInputDev);
void InputInit(void);
int GetInputEvent(PInputEvent ptInputEvent);
void InputDeviceInit(void);
​
#endif

3. 底层的管理

input_manager.c:此文件作为上层app和底层驱动的中间层,通过环形缓存区对设备数据进行存储,每个设备创建线程对环形缓冲区进行操作,读写锁和条件变量保证了线程同步

/* 此文件作为上层app和底层驱动的中间层,即中间件*/
​
#include <input_manager.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <semaphore.h>
#include <string.h>
static PInputDevice g_InputDevs = NULL;
​
// 初始化读写锁
static pthread_mutex_t g_tMutex = PTHREAD_MUTEX_INITIALIZER;
// 初始化条件变量
static pthread_cond_t g_tConVar = PTHREAD_COND_INITIALIZER;
​
/* start of 实现环形buffer */
#define BUFFER_LEN 20
static int g_iRead = 0;
static int g_iWrite = 0;
static InputEvent g_atInputEvents[BUFFER_LEN];
​
// 判断环形缓存区是否满
static int isInputBufferFull(void)
{   
    // 判断条件 下一个写位置等于读位置
    return (g_iRead == ((g_iWrite + 1) % BUFFER_LEN));
}
​
// 判断环形缓存区是否空
static int isInputBufferEmpty(void)
{
    // 判断条件 写位置等于读位置
    return (g_iRead == g_iWrite);
}
​
// 往环形buffer里面加数据
static void PutInputEventToBuffer(PInputEvent ptInputEvent)
{
    if(!isInputBufferFull())
    {
        g_atInputEvents[g_iWrite] = *ptInputEvent;
        g_iWrite = (g_iWrite + 1) % BUFFER_LEN;
    }
}
​
// 往环形buffer获取数据
static int GetInputEventFromBuffer(PInputEvent ptInputEvent)
{
    if(!isInputBufferEmpty())
    {
        *ptInputEvent = g_atInputEvents[g_iRead] ;
        g_iRead = (g_iRead + 1) % BUFFER_LEN;
        return 1;
    }else
        return 0;
}
​
/* end of 实现环形buffer */
// 将设备加入链表
void RegisterInputDevice(PInputDevice ptInputDev)
{
    ptInputDev->ptNext = g_InputDevs;
    g_InputDevs = ptInputDev;
}
​
// 上层app 注册设备
void InputInit(void)
{
    //注册触摸屏设备
    extern void TouchscreenRegister(void);
    TouchscreenRegister();
​
    //注册网络输入设备
    extern void NetinputRegister(void);
    NetinputRegister();
}
​
static void *input_recv_thread_func(void *data)
{
    PInputDevice ptInputDev = (PInputDevice)data;
    InputEvent tEvent;
    int ret;
    while(1)
    {   
        // 读数据
        ret = ptInputDev->GetInputEvent(&tEvent);
        if(!ret)
        {
            // 保存数据
            pthread_mutex_lock(&g_tMutex);
            PutInputEventToBuffer(&tEvent); //将数据存入环形缓存区
            // 唤醒等待数据的线程
            pthread_cond_signal(&g_tConVar);
            pthread_mutex_unlock(&g_tMutex);
        }
    }
    return NULL;
}
​
// 底层设备驱动 选择设备
void InputDeviceInit(void)
{
    int ret;
    pthread_t pid;
    // 初始化每个设备 创建线程
    PInputDevice ptTmp = g_InputDevs;// 指向链表头
    while(ptTmp) // 设备存在
    {
        // 初始化设备
        ret = ptTmp->DeviceInit();
        // 创建线程
        if(ret == 0)
        {
            ret = pthread_create(&pid,NULL,input_recv_thread_func,ptTmp);
        }
        // 指向下一个链表
        ptTmp = ptTmp->ptNext;
    }
​
}
​
// 获取APP的数据
int GetInputEvent(PInputEvent ptInputEvent)
{
    InputEvent tEvent;
    int ret;
    // 无数据则休眠 否则返回数据
    pthread_mutex_lock(&g_tMutex); // 上锁
    if(GetInputEventFromBuffer(&tEvent))
    {
        *ptInputEvent = tEvent;
        pthread_mutex_unlock(&g_tMutex); // 解锁
        return 0;
    }else
    {
        pthread_cond_wait(&g_tConVar,&g_tMutex); //等待
        if(GetInputEventFromBuffer(&tEvent))
        {
            *ptInputEvent = tEvent;
            ret = 0;
        }else
        {
            ret = -1;
        }
        pthread_mutex_unlock(&g_tMutex);
    }
    return ret;
}

4. 触摸屏编程

#include <input_manager.h>
#include <tslib.h> //使用tslib库
#include <stdio.h>
​
static struct tsdev *g_ts;
// 获取触摸屏事件
static int TouchscreenGetInputEvent(PInputEvent ptInputEvent)
{
    struct ts_sample samp;
    int ret;
    ret = ts_read(g_ts,&samp,1);
    if(ret != 1)
        return -1;
​
    ptInputEvent->iType = INPUT_TYPE_TOUCH; //表示触摸屏
    ptInputEvent->iX = samp.x;
    ptInputEvent->iY = samp.y;
    ptInputEvent->iPressure = samp.pressure;
    ptInputEvent->tTime = samp.tv;
    return 0;
}
// 对触摸屏进行初始化 
static int TouchscreenDeviceInit(void)
{
    g_ts = ts_setup(NULL, 0);
    if (!g_ts)
    {
        printf("ts_setup err\n");
        return -1;
    }
    return 0;
}
// 释放资源
static int TouchscreenDeviceExit(void)
{
    ts_close(g_ts);
    return 0;
}
// 抽象的实现
static InputDevice g_tTouchscreenDev ={
    .name = "touchscreen",
    .GetInputEvent = TouchscreenGetInputEvent,
    .DeviceInit = TouchscreenDeviceInit,
    .DeviceExit = TouchscreenDeviceExit,
};
// 注册设备
void TouchscreenRegister(void)
{
    RegisterInputDevice(&g_tTouchscreenDev);
}

5. 触摸屏单元测试

int main(int argc, char * * argv)
{
    InputEvent event;
    int ret;
    g_tTouchscreenDev.DeviceInit();
​
    while(1)
    {
        ret = g_tTouchscreenDev.GetInputEvent(&event);
        if(ret){
            printf("GetInputEvent err\n");
            return -1;
        }else{
            printf("Type: %d\n",event.iType);
            printf("iX: %d\n",event.iX);
            printf("iY: %d\n",event.iY);
            printf("iPressure: %d\n",event.iPressure);
        }
    }
    return 0;
}

6. 网络输入编程

net_input.c:该文件主要是对网络编程服务端进行实现,同时对设备进行初始化

#include <input_manager.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
​
#define SERVER_PORT 8888
static int g_iSocketServer;
​
static int NetinputGetInputEvent(PInputEvent ptInputEvent)
{
    struct sockaddr_in tSocketClientAddr;
    int iRecvLen;
    char aRecvBuf[1000];
    unsigned int iAddrLen;
    iAddrLen = sizeof(struct sockaddr);
    // 接收客户端数据
    iRecvLen = recvfrom(g_iSocketServer, aRecvBuf, 999, 0, (struct sockaddr *)&tSocketClientAddr, &iAddrLen);
    if (iRecvLen > 0)
    {
        aRecvBuf[iRecvLen] = '\0';
        //printf("Get Msg From %s : %s\n", inet_ntoa(tSocketClientAddr.sin_addr), ucRecvBuf);
        ptInputEvent->iType = INPUT_TYPE_NET;
        gettimeofday(&ptInputEvent->tTime, NULL);
        strncpy(ptInputEvent->str,aRecvBuf,1000);
        ptInputEvent->str[999] = '\0';
        return 0;
    }else{
        return -1;
    }
    return 0;
}
// 网络设备初始化
static int NetinputDeviceInit(void)
{
​
    struct sockaddr_in tSocketServerAddr;
    int iRet;
    // 创建套接字
    g_iSocketServer = socket(AF_INET, SOCK_DGRAM, 0);
    if (-1 == g_iSocketServer)
    {
        printf("socket error!\n");
        return -1;
    }
​
    tSocketServerAddr.sin_family      = AF_INET;
    tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */
    tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
    memset(tSocketServerAddr.sin_zero, 0, 8);
    // 绑定端口和IP
    iRet = bind(g_iSocketServer, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));
    if (-1 == iRet)
    {
        printf("bind error!\n");
        return -1;
    }
​
    return 0;
}
// 释放资源
static int NetinputDeviceExit(void)
{
    close(g_iSocketServer);
    return 0;
}
// 抽象的实现
static InputDevice g_tNetinputDev ={
    .name = "touchscreen",
    .GetInputEvent = NetinputGetInputEvent,
    .DeviceInit = NetinputDeviceInit,
    .DeviceExit = NetinputDeviceExit,
};
// 网络设备注册
void NetinputRegister(void)
{
    RegisterInputDevice(&g_tNetinputDev);
}

7. 客户端

clinet.c:对客户端的编写

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
​
/* socket
 * connect
 * send/recv
 */
​
#define SERVER_PORT 8888
​
int main(int argc, char **argv)
{
    int iSocketClient;
    struct sockaddr_in tSocketServerAddr;
    
    int iRet;
    int iSendLen;
    int iAddrLen;
​
    if (argc != 3)
    {
        printf("Usage:\n");
        printf("%s <server_ip> <str>\n", argv[0]);
        return -1;
    }
​
    iSocketClient = socket(AF_INET, SOCK_DGRAM, 0);
​
    tSocketServerAddr.sin_family      = AF_INET;
    tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */
    //tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
    if (0 == inet_aton(argv[1], &tSocketServerAddr.sin_addr))
    {
        printf("invalid server_ip\n");
        return -1;
    }
    memset(tSocketServerAddr.sin_zero, 0, 8);
​
#if 0
    iRet = connect(iSocketClient, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));    
    if (-1 == iRet)
    {
        printf("connect error!\n");
        return -1;
    }
#endif
​
    iAddrLen = sizeof(struct sockaddr);
    iSendLen = sendto(iSocketClient, argv[2], strlen(argv[2]), 0,
                      (const struct sockaddr *)&tSocketServerAddr, iAddrLen);
​
    close(iSocketClient);
    
    return 0;
}

8. 网络单元测试

int main(int argc, char * * argv)
{
    InputEvent event;
    int ret;
    g_tNetinputDev.DeviceInit();
​
    while(1)
    {
        ret = g_tNetinputDev.GetInputEvent(&event);
        if(ret){
            printf("GetInputEvent err\n");
            return -1;
        }else{
            printf("Type: %d\n",event.iType);
            printf("str: %s\n",event.str);
        }
    }
    return 0;
}

9. 综合测试

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
​
#include <input_manager.h>
​
int main(int argc, char **argv)
{
    int ret;
    InputEvent event;
    
    InputInit();
    InputDeviceInit();
​
    while (1)
    {
        printf("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
        ret = GetInputEvent(&event);
​
        if (ret) {
            printf("GetInputEvent err!\n");
            return -1;
        }
        else
        {
            if (event.iType == INPUT_TYPE_TOUCH)
            {
                printf("Type      : %d\n", event.iType);
                printf("iX        : %d\n", event.iX);
                printf("iY        : %d\n", event.iY);
                printf("iPressure : %d\n", event.iPressure);
            }
            else if (event.iType == INPUT_TYPE_NET)
            {
                printf("Type      : %d\n", event.iType);
                printf("str       : %s\n", event.str);
            }
        }
    }
    return 0;   
}

点击屏幕

获取网络信息

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值