当前位置: 首页 > news >正文

网站建设的职责seo就业指导

网站建设的职责,seo就业指导,网页设计课程速成班,备案中心查网站往期内容 本专栏往期内容: input子系统的框架和重要数据结构详解-CSDN博客input device和input handler的注册以及匹配过程解析-CSDN博客input device和input handler的注册以及匹配过程解析-CSDN博客编写一个简单的Iinput_dev框架-CSDN博客GPIO按键驱动分析与使用&…

往期内容

本专栏往期内容:

  1. input子系统的框架和重要数据结构详解-CSDN博客
  2. input device和input handler的注册以及匹配过程解析-CSDN博客
  3. input device和input handler的注册以及匹配过程解析-CSDN博客
  4. 编写一个简单的Iinput_dev框架-CSDN博客
  5. GPIO按键驱动分析与使用:input_dev层-CSDN博客

I2C子系统专栏:

  1. 专栏地址:IIC子系统_憧憬一下的博客-CSDN博客
  2. 具体芯片的IIC控制器驱动程序分析:i2c-imx.c-CSDN博客
    – 末篇,有往期内容观看顺序

总线和设备树专栏:

  1. 专栏地址:总线和设备树_憧憬一下的博客-CSDN博客
  2. 设备树与 Linux 内核设备驱动模型的整合-CSDN博客
    – 末篇,有往期内容观看顺序


目录

  • 往期内容
  • 前言
  • 1. 驱动程序框架
  • 2. 设备树示例
  • 3. 驱动程序分析
    • 3.1 分配/设置/注册input_dev
    • 3.2 注册中断处理函数
    • 3.3 中断处理函数分析
  • 4.编写

前言

  • Linux 4.x内核

    • Documentation\devicetree\bindings\input\touchscreen\goodix.txt
    • drivers/input/touchscreen/gt9xx/gt9xx.c 📎gt9xx.c
  • 设备树

    • IMX6ULL:Linux-4.9.88/arch/arm/boot/dts/100ask_imx6ull-14x14.dts

本节主要讲解内核中提供的gt9xx.c,来看看是如何通过input子系统来实现一个IIC协议的传输,之后在此基础上编写一个简单的input子系统的IIC驱动

1. 驱动程序框架

img

2. 设备树示例

&i2c2 {gt9xx@5d {compatible = "goodix,gt9xx";reg = <0x5d>;status = "okay";interrupt-parent = <&gpio1>;interrupts = <5 IRQ_TYPE_EDGE_FALLING>;pinctrl-names = "default";pinctrl-0 = <&pinctrl_tsc_reset &pinctrl_touchscreen_int>;/*pinctrl-1 = <&pinctrl_tsc_irq>;*//*pinctrl-names = "default", "int-output-low", "int-output-high", "int-input";pinctrl-0 = <&ts_int_default>;pinctrl-1 = <&ts_int_output_low>;pinctrl-2 = <&ts_int_output_high>;pinctrl-3 = <&ts_int_input>;*/reset-gpios = <&gpio5 2 GPIO_ACTIVE_LOW>;irq-gpios = <&gpio1 5 IRQ_TYPE_EDGE_FALLING>;irq-flags = <2>;                /*1:rising 2: falling*/touchscreen-max-id = <5>;touchscreen-size-x = <800>;touchscreen-size-y = <480>;touchscreen-max-w = <1024>;touchscreen-max-p = <1024>;/*touchscreen-key-map = <172>, <158>;*/ /*KEY_HOMEPAGE, KEY_BACK*/goodix,type-a-report = <0>;goodix,driver-send-cfg = <0>;goodix,create-wr-node = <1>;goodix,wakeup-with-reset = <0>;goodix,resume-in-workqueue = <0>;goodix,int-sync = <0>;goodix,swap-x2y = <0>;goodix,esd-protect = <0>;goodix,pen-suppress-finger = <0>;goodix,auto-update = <0>;goodix,auto-update-cfg = <0>;goodix,power-off-sleep = <0>;/* ...... */};
};	

这段设备树(Device Tree)定义配置了一个基于 I2C 总线的 Goodix GT9xx 系列触摸屏设备,设备地址为 0x5d

1. 节点和基础属性

&i2c2 {gt9xx@5d {compatible = "goodix,gt9xx";reg = <0x5d>;
  • &i2c2:指向 I2C 总线控制器的节点,这意味着该设备挂载在 I2C 总线 2 上。
  • gt9xx@5d:表示该触摸屏设备的 I2C 地址为 0x5d
  • compatible = "goodix,gt9xx";:指定设备兼容字符串,匹配 Goodix 的 GT9xx 系列触摸屏设备驱动程序。
  • reg = <0x5d>;:设备的 I2C 地址,定义为 0x5d

2. 中断与引脚控制配置

        status = "okay";interrupt-parent = <&gpio1>;interrupts = <5 IRQ_TYPE_EDGE_FALLING>;pinctrl-names = "default";pinctrl-0 = <&pinctrl_tsc_reset &pinctrl_touchscreen_int>;
  • status = "okay";:设备状态,标记为启用。
  • interrupt-parent = <&gpio1>;:指定中断的父节点为 gpio1,即 GPIO 控制器 1。
  • interrupts = <5 IRQ_TYPE_EDGE_FALLING>;:中断配置,使用 GPIO1 控制器的第 5 个引脚,触发模式为下降沿触发(IRQ_TYPE_EDGE_FALLING)。
  • pinctrl-names pinctrl-0:配置引脚控制器,pinctrl-names 指定了配置的名字,pinctrl-0 则定义了相关引脚配置(pinctrl_tsc_resetpinctrl_touchscreen_int),用于触摸屏重置和中断引脚初始化。

3. GPIO 和中断标志

        reset-gpios = <&gpio5 2 GPIO_ACTIVE_LOW>;irq-gpios = <&gpio1 5 IRQ_TYPE_EDGE_FALLING>;irq-flags = <2>; 
  • reset-gpios = <&gpio5 2 GPIO_ACTIVE_LOW>;:触摸屏的复位引脚定义在 gpio5 的第 2 引脚,信号低电平有效。
  • irq-gpios = <&gpio1 5 IRQ_TYPE_EDGE_FALLING>;:触摸屏的中断引脚配置为 gpio1 控制器的第 5 引脚,设置为下降沿触发。
  • irq-flags = <2>;:中断触发标志,2 表示下降沿触发。

4. 触摸屏参数

        touchscreen-max-id = <5>;touchscreen-size-x = <800>;touchscreen-size-y = <480>;touchscreen-max-w = <1024>;touchscreen-max-p = <1024>;
  • touchscreen-max-id = <5>;:最大触摸点数为 5,表示最多支持 5 个手指的多点触控。
  • touchscreen-size-x touchscreen-size-y:触摸屏 X、Y 轴的分辨率,分别为 800 和 480。
  • touchscreen-max-w touchscreen-max-p:触控宽度和压力的最大值,均为 1024。

5. Goodix 驱动特性

        goodix,type-a-report = <0>;goodix,driver-send-cfg = <0>;goodix,create-wr-node = <1>;goodix,wakeup-with-reset = <0>;goodix,resume-in-workqueue = <0>;goodix,int-sync = <0>;goodix,swap-x2y = <0>;goodix,esd-protect = <0>;goodix,pen-suppress-finger = <0>;goodix,auto-update = <0>;goodix,auto-update-cfg = <0>;goodix,power-off-sleep = <0>;
  • Goodix 特定属性goodix,xxx 属性定义了一些特性和行为,例如:

    • goodix,type-a-reportgoodix,driver-send-cfg:控制是否启用 A 类型报告和驱动是否发送配置信息。
    • goodix,create-wr-node:创建 WR(写)节点的标志。
    • goodix,wakeup-with-resetgoodix,power-off-sleep:控制唤醒和电源管理的行为。
    • 其他 Goodix 触摸屏特性配置,按需要启用或禁用。

这些属性通过设备树配置,使系统能够正确初始化并管理触摸屏设备。

3. 驱动程序分析

gt9xx.c

3.1 分配/设置/注册input_dev

img

gtp_proberet = gtp_request_input_dev(ts);ts->input_dev = input_allocate_device();......ret = input_register_device(ts->input_dev);ret = gtp_request_irq(ts);	

3.2 注册中断处理函数

img

ret = request_threaded_irq(ts->client->irq, NULL,gtp_irq_handler,ts->pdata->irq_flags | IRQF_ONESHOT,ts->client->name,ts);

3.3 中断处理函数分析

通过I2C函数( 2c_tansfer)读取数据、上报数据。

img

static irqreturn_t gtp_irq_handler(int irq, void *dev_id)
{struct goodix_ts_data *ts = dev_id;gtp_work_func(ts);return IRQ_HANDLED;
}static void gtp_work_func(struct goodix_ts_data *ts)
{u8 point_state = 0;  // 保存触摸点的状态u8 key_value = 0;    // 保存按键的状态s32 i = 0;           // 循环变量,用于迭代按键事件s32 ret = -1;        // 函数调用返回值static u8 pre_key;   // 保存上一次的按键值,用于识别按键变化struct goodix_point_t points[GTP_MAX_TOUCH_ID]; // 存储触摸点信息// 检查是否正在执行复位操作,若是,则退出函数if (test_bit(PANEL_RESETTING, &ts->flags))return;// 检查工作线程是否启用,若未启用,则退出函数if (!test_bit(WORK_THREAD_ENABLED, &ts->flags))return;// 手势事件处理,检测滑动唤醒功能是否启用,且设备是否处于休眠模式if (ts->pdata->slide_wakeup && test_bit(DOZE_MODE, &ts->flags)) {// 调用手势处理函数 gtp_gesture_handlerret = gtp_gesture_handler(ts);if (ret) {// 若处理失败,记录错误日志dev_err(&ts->client->dev,"Failed handler gesture event %d\n", ret);}return;  // 处理完成后退出函数}// 获取触摸点的状态及按键状态-----------1)point_state = gtp_get_points(ts, points, &key_value); if (!point_state) {// 若未检测到有效的触摸点,记录调试日志dev_dbg(&ts->client->dev, "Invalid finger points\n");return;  // 没有有效触摸点,直接返回}// 处理触摸按键事件if (key_value & 0xf0 || pre_key & 0xf0) {  // 判断是否有按键事件// 处理手写笔的按键switch (key_value) {case 0x40: // 两个按键都按下input_report_key(ts->input_dev, GTP_PEN_BUTTON1, 1);input_report_key(ts->input_dev, GTP_PEN_BUTTON2, 1);break;case 0x10: // 按下第一个按键input_report_key(ts->input_dev, GTP_PEN_BUTTON1, 1);input_report_key(ts->input_dev, GTP_PEN_BUTTON2, 0);dev_dbg(&ts->client->dev, "pen button1 down\n");break;case 0x20: // 按下第二个按键input_report_key(ts->input_dev, GTP_PEN_BUTTON1, 0);input_report_key(ts->input_dev, GTP_PEN_BUTTON2, 1);break;default: // 没有按键按下,恢复初始状态input_report_key(ts->input_dev, GTP_PEN_BUTTON1, 0);input_report_key(ts->input_dev, GTP_PEN_BUTTON2, 0);dev_dbg(&ts->client->dev, "button1 up\n");break;}input_sync(ts->input_dev); // 同步输入事件pre_key = key_value;       // 更新上次按键状态} else if (key_value & 0x0f || pre_key & 0x0f) {  // 判断是否有面板按键事件// 遍历所有按键,检测是否有按键状态发生变化for (i = 0; i < ts->pdata->key_nums; i++) {if ((pre_key | key_value) & (0x01 << i))input_report_key(ts->input_dev,ts->pdata->key_map[i],     // 具体按键映射key_value & (0x01 << i));  // 按键状态}input_sync(ts->input_dev); // 同步输入事件pre_key = key_value;       // 更新上次按键状态}// 选择不同的报告格式进行触摸点的处理if (!ts->pdata->type_a_report)gtp_mt_slot_report(ts, point_state & 0x0f, points);  // Slot方式----------------------(2)elsegtp_type_a_report(ts, point_state & 0x0f, points);   // Type A方式
}

(1)point_state = gtp_get_points(ts, points, &key_value); : 从 I2C 总线上读取触摸点的数据和触摸状态。提取坐标、压力值、工具类型等信息,若需要则交换 X/Y 坐标。 将手写笔和普通触摸点区分,按需要调整触摸点数据。完成数据读取后,通过发送结束命令结束当前触摸事件。 ret = gtp_i2c_read(ts->client, point_data, 12); //这里内部就调用到了i2c_transfer发起传输

static u8 gtp_get_points(struct goodix_ts_data *ts,struct goodix_point_t *points,u8 *key_value)
{int ret;                // 保存 I2C 传输返回状态int i;                  // 循环变量u8 *coor_data = NULL;   // 指向触摸坐标数据的指针u8 finger_state = 0;    // 保存手指状态信息u8 touch_num = 0;       // 保存当前触摸点的数量u8 end_cmd[3] = {       // 用于向触摸屏发送 "结束" 命令GTP_READ_COOR_ADDR >> 8,GTP_READ_COOR_ADDR & 0xFF,0};u8 point_data[2 + 1 + 8 * GTP_MAX_TOUCH_ID + 1] = {  // 存储触摸点的数据GTP_READ_COOR_ADDR >> 8,GTP_READ_COOR_ADDR & 0xFF};// 读取触摸点的坐标数据ret = gtp_i2c_read(ts->client, point_data, 12);   //这里内部就调用到了i2c_transfer发起传输if (ret < 0) {dev_err(&ts->client->dev, "I2C transfer error. errno:%d\n ", ret);return 0;  // 读取失败返回0}finger_state = point_data[GTP_ADDR_LENGTH];  // 获取触摸屏状态if (finger_state == 0x00)                    // 若无触摸点return 0;// 获取触摸点数量(低 4 位表示触摸点数量)touch_num = finger_state & 0x0f;// 检查触摸状态是否合法,如超出最大触摸数或没有触摸if ((finger_state & MASK_BIT_8) == 0 || touch_num > ts->pdata->max_touch_id) {dev_err(&ts->client->dev, "Invalid touch state: 0x%x", finger_state);finger_state = 0;  // 若非法则重置触摸状态goto exit_get_point;  // 跳转到退出点}// 若有多个触摸点,则读取后续触摸点数据if (touch_num > 1) {u8 buf[8 * GTP_MAX_TOUCH_ID] = {(GTP_READ_COOR_ADDR + 10) >> 8,(GTP_READ_COOR_ADDR + 10) & 0xff};ret = gtp_i2c_read(ts->client, buf, 2 + 8 * (touch_num - 1));if (ret < 0) {dev_err(&ts->client->dev, "I2C error. %d\n", ret);finger_state = 0;goto exit_get_point;}memcpy(&point_data[12], &buf[2], 8 * (touch_num - 1));}// 触摸按键事件,低 4 位标识按键事件*key_value = point_data[3 + 8 * touch_num];// 初始化触摸点信息数组memset(points, 0, sizeof(*points) * GTP_MAX_TOUCH_ID);for (i = 0; i < touch_num; i++) {coor_data = &point_data[i * 8 + 3];  // 获取触摸点的坐标数据points[i].id = coor_data[0];         // 触摸点 IDpoints[i].x = coor_data[1] | (coor_data[2] << 8);  // 触摸点的 X 坐标points[i].y = coor_data[3] | (coor_data[4] << 8);  // 触摸点的 Y 坐标points[i].w = coor_data[5] | (coor_data[6] << 8);  // 触摸点的宽度points[i].p = coor_data[5] | (coor_data[6] << 8);  // 压力值// 判断是否需要交换 X/Y 坐标if (ts->pdata->swap_x2y)GTP_SWAP(points[i].x, points[i].y);dev_dbg(&ts->client->dev, "[%d][%d %d %d]\n", points[i].id, points[i].x, points[i].y, points[i].p);// 判断是否为手写笔触摸点if (points[i].id & 0x80) {points[i].tool_type = GTP_TOOL_PEN;points[i].id = 10;  // 手写笔 ID 固定为 10if (ts->pdata->pen_suppress_finger) {points[0] = points[i];memset(++points, 0, sizeof(*points) * (GTP_MAX_TOUCH_ID - 1));finger_state &= 0xf0;finger_state |= 0x01;  // 设置第一个触摸点为手写笔break;}} else {points[i].tool_type = GTP_TOOL_FINGER;}}exit_get_point:// 若未处于 RAW 数据模式,写入结束命令以结束当前触摸事件if (!test_bit(RAW_DATA_MODE, &ts->flags)) {ret = gtp_i2c_write(ts->client, end_cmd, 3);if (ret < 0)dev_info(&ts->client->dev, "I2C write end_cmd error!");}return finger_state;  // 返回触摸屏状态
}

(2)gtp_irq_handler中你的gtp_mt_slot_report(ts, point_state & 0x0f, points); // Slot方式

  • 函数主要负责报告多点触控的触摸点状态,包括其位置、工具类型和压力等。
  • 使用位图(cur_touchpre_touch)跟踪当前和先前的触摸 ID,从而确定哪些触摸点是新触摸、哪些是结束触摸。
static void gtp_mt_slot_report(struct goodix_ts_data *ts, u8 touch_num, struct goodix_point_t *points)
{int i; // 循环变量u16 cur_touch = 0; // 当前触摸 ID 位图static u16 pre_touch; // 上一帧的触摸 ID 位图static u8 pre_pen_id; // 上一次触摸的笔 ID// 遍历每个可能的触摸点,最大触摸 ID 由 ts->pdata->max_touch_id 决定for (i = 0; i < ts->pdata->max_touch_id; i++) {// 检查当前触摸点是否有效if (touch_num && i == points->id) {// 设置当前触摸点的槽(slot)input_mt_slot(ts->input_dev, points->id);// 判断工具类型if (points->tool_type == GTP_TOOL_PEN) {// 如果是笔工具,报告笔的状态为真input_mt_report_slot_state(ts->input_dev, MT_TOOL_PEN, true);pre_pen_id = points->id; // 更新上一次的笔 ID} else {// 否则为手指工具,报告状态为真input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);}// 报告触摸点的 X 坐标input_report_abs(ts->input_dev, ABS_MT_POSITION_X, points->x);// 报告触摸点的 Y 坐标input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, points->y);// 报告触摸点的宽度input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, points->w);// 报告触摸点的压力input_report_abs(ts->input_dev, ABS_MT_PRESSURE, points->p);// 更新当前触摸 ID 位图cur_touch |= 0x01 << points->id;points++; // 移动到下一个触摸点} // 如果在上一帧中这个槽是活跃的else if (pre_touch & (0x01 << i)) {// 设置当前槽为 iinput_mt_slot(ts->input_dev, i);// 检查上次是否是笔 IDif (pre_pen_id == i) {// 如果是笔,报告笔的状态为假input_mt_report_slot_state(ts->input_dev, MT_TOOL_PEN, false);/* 有效的 ID 应小于 10,所以将 ID 设置为 0xff * 来表示无效状态*/pre_pen_id = 0xff; // 重置笔 ID} else {// 否则报告手指状态为假input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);}}}// 更新上一帧的触摸 ID 位图为当前帧pre_touch = cur_touch;// 同步当前的触摸帧input_mt_sync_frame(ts->input_dev);// 同步输入设备状态input_sync(ts->input_dev);
}
gtp_irq_handlergtp_work_func(ts);point_state = gtp_get_points(ts, points, &key_value);gtp_i2c_readi2c_transfergtp_mt_slot_report(ts, point_state & 0x0f, points);input_mt_slotinput_mt_report_slot_stateinput_report_abs

有所疑问可以先看:

I2C相关结构体讲解:i2c_adapter、i2c_algorithm、i2c_msg-CSDN博客

编写一个简单的Iinput_dev框架-CSDN博客

4.编写

这里主要是参考📎gpio_keys.c,但思路其实和上面介绍的差不多,设置Input_dev并注册、配置事件类型和支持的事件、请求中断注册中断等。

#define TOUCHSCREEN_POLL_TIME_MS 10 // 定义轮询时间,单位为毫秒// 定义模拟触摸屏硬件数据结构
struct qemu_ts_con {volatile unsigned int pressure; // 触摸压力,0表示未触摸,非0表示触摸volatile unsigned int x;        // 触摸X坐标volatile unsigned int y;        // 触摸Y坐标volatile unsigned int clean;    // 清除标志
};// 全局变量定义
static struct input_dev *g_input_dev;  // 输入设备
static int g_irq;                      // 中断号
static struct qemu_ts_con *ts_con;     // 指向模拟触摸屏的结构体
struct timer_list ts_timer;            // 定时器,用于轮询触摸状态// 定时器回调函数,用于定期轮询触摸状态
static void ts_irq_timer(unsigned long _data)
{// 如果检测到触摸事件if (ts_con->pressure) {// 报告触摸位置input_event(g_input_dev, EV_ABS, ABS_X, ts_con->x);input_event(g_input_dev, EV_ABS, ABS_Y, ts_con->y);input_sync(g_input_dev);// 重新启动定时器mod_timer(&ts_timer, jiffies + msecs_to_jiffies(TOUCHSCREEN_POLL_TIME_MS));}
}// 中断服务函数,触发触摸事件处理
static irqreturn_t input_dev_demo_isr(int irq, void *dev_id)
{// 如果有触摸事件发生if (ts_con->pressure) {// 报告触摸位置和触摸按键状态input_event(g_input_dev, EV_ABS, ABS_X, ts_con->x);input_event(g_input_dev, EV_ABS, ABS_Y, ts_con->y);input_event(g_input_dev, EV_KEY, BTN_TOUCH, 1);input_sync(g_input_dev);// 启动定时器继续监控触摸状态mod_timer(&ts_timer, jiffies + msecs_to_jiffies(TOUCHSCREEN_POLL_TIME_MS));} else {// 如果没有触摸,报告触摸键松开input_event(g_input_dev, EV_KEY, BTN_TOUCH, 0);input_sync(g_input_dev);}return IRQ_HANDLED;
}// 设备初始化函数,负责资源分配和设备注册
static int input_dev_demo_probe(struct platform_device *pdev)
{struct device *dev = &pdev->dev;int error;struct resource *io;int gpio;printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);// 获取GPIO编号gpio = of_get_gpio(pdev->dev.of_node, 0);// 分配并初始化input_dev结构体g_input_dev = devm_input_allocate_device(dev);if (!g_input_dev)return -ENOMEM;// 配置input_dev的基础信息g_input_dev->name = "input_dev_demo";g_input_dev->phys = "input_dev_demo";g_input_dev->dev.parent = dev;g_input_dev->id.bustype = BUS_HOST;g_input_dev->id.vendor = 0x0001;g_input_dev->id.product = 0x0001;g_input_dev->id.version = 0x0100;// 配置事件类型和支持的事件__set_bit(EV_KEY, g_input_dev->evbit);__set_bit(EV_ABS, g_input_dev->evbit);__set_bit(INPUT_PROP_DIRECT, g_input_dev->propbit);__set_bit(BTN_TOUCH, g_input_dev->keybit);__set_bit(ABS_X, g_input_dev->absbit);__set_bit(ABS_Y, g_input_dev->absbit);// 配置触摸屏的绝对坐标范围input_set_abs_params(g_input_dev, ABS_X, 0, 0xffff, 0, 0);input_set_abs_params(g_input_dev, ABS_Y, 0, 0xffff, 0, 0);// 注册input_deverror = input_register_device(g_input_dev);if (error)return error;// 获取硬件寄存器的I/O资源并映射io = platform_get_resource(pdev, IORESOURCE_MEM, 0);ts_con = ioremap(io->start, resource_size(io));// 获取并请求GPIO的中断号g_irq = gpio_to_irq(gpio);error = request_irq(g_irq, input_dev_demo_isr, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "input_dev_demo_irq", NULL);if (error)return error;// 初始化定时器setup_timer(&ts_timer, ts_irq_timer, (unsigned long)NULL);return 0;
}// 设备卸载函数,释放资源
static int input_dev_demo_remove(struct platform_device *pdev)
{del_timer_sync(&ts_timer);       // 停止定时器iounmap(ts_con);                 // 取消内存映射free_irq(g_irq, NULL);           // 释放中断input_unregister_device(g_input_dev); // 注销设备return 0;
}// 设备树匹配表
static const struct of_device_id input_dev_demo_of_match[] = {{ .compatible = "100ask,input_dev_demo", },{ },
};// 平台驱动结构体定义
static struct platform_driver input_dev_demo_driver = {.probe  = input_dev_demo_probe,.remove = input_dev_demo_remove,.driver = {.name = "input_dev_demo",.of_match_table = input_dev_demo_of_match,}
};// 模块初始化函数
static int __init input_dev_demo_init(void)
{printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);return platform_driver_register(&input_dev_demo_driver);
}// 模块退出函数
static void __exit input_dev_demo_exit(void)
{platform_driver_unregister(&input_dev_demo_driver);
}module_init(input_dev_demo_init);
module_exit(input_dev_demo_exit);MODULE_LICENSE("GPL");
http://www.hrbkazy.com/news/11184.html

相关文章:

  • led网站建设方案模板南宁优化推广服务
  • 做网站网页维护 手机App 开发网站推广常用方法
  • 咖啡豆网站模板营销软文800字范文
  • 静态网站开发课程网沧州网络推广外包公司
  • 电信100m光纤做网站最新的即时比分
  • wordpress静态博客主题seo站长之家
  • 高端建站网站的下载百度app到桌面
  • 深圳建设工程招投标网站谷歌推广开户多少费用
  • 我的网站怎么转网页呢网络舆情分析师
  • 智能软件开发方向怎么样网站优化推广软件
  • 网站建设网址深圳百度快速排名提升
  • wordpress单机版安徽网络关键词优化
  • 重庆市城市建设综合开发办网站成都最新疫情
  • 做宽带销售网站域名服务器ip地址查询
  • 做企业网站用drupal7志鸿优化设计电子版
  • 网站首页怎么设计国际新闻界
  • 响应式网站建设必推全网天下网络推广的具体方式
  • 公司网站建设 宁波网络营销优化培训
  • 树莓派可以做网站的服务器吗seo技巧与技术
  • 电子商务网站建设流程重庆关键词优化软件
  • 简述网站建设的主要内容厦门关键词排名优化
  • 做网站优化有什么途径网页分析工具
  • wordpress 3 企业主题淘宝seo搜索引擎原理
  • 做直销网站公司谷歌推广和seo
  • 无极ip求好用的seo软件
  • 上市企业网站建设百度seo如何优化关键词
  • 网站开发包括网站过程seo搜索引擎优化关键词
  • 哪个网站可以做视频外链如何推广seo
  • 网站开发说明最好用的搜索神器
  • 做网站数据需求分析建立一个国外的网站