zoukankan      html  css  js  c++  java
  • 耳机驱动程序上报

    上报设备

    1. headset :听筒mic
    2. headphone:听筒没有mic
    3. Lineout:声音输出没有mic

    上报方式

    1. 输入子系统:
      • 可上报输入事件
      • 上报开关事件
    2. switch state:uevent

    编写输入系统驱动

    1. 分配input_dev;
    2. 设置:
      1. 能产生哪类事件:EV_SW
      2. 能产生EV_SW中的哪些事件
        • headset
        • headphone
        • Lineout
    3. 注册input_dev
    4. 硬件相关(中断程序)
      • 上报插入事件
      • 上报拔出事件
    #include <linux/module.h>
    #include <linux/types.h>
    #include <linux/init.h>
    #include <linux/device.h>
    #include <linux/fs.h>
    #include <linux/err.h>
    #include <linux/switch.h>
    #include <linux/input.h>
    
    static struct input_dev *g_virtual_input;
    
    static ssize_t input_test_store(struct device *dev,
    				     struct device_attribute *attr,
    				     const char *buf, size_t count)
    {
    	long code;
    	long val;
    	char *endp;
    
    	/* 如果字符串前面含有非数字, simple_strtol不能处理 */
    	while ((*buf == ' ') || (*buf == '	'))
    		buf++;
    
    	code = simple_strtol(buf, &endp, 0);
    
    	/* 如果字符串前面含有非数字, simple_strtol不能处理 */
    	while ((*endp == ' ') || (*endp == '	'))
    		endp++;
    	val  = simple_strtol(endp, NULL, 0);
    
    	printk("emulate to report EV_SW: 0x%x 0x%x
    ", code, val);
    	input_event(g_virtual_input, EV_SW, code, val);
    	input_sync(g_virtual_input);
    
    	return count;
    }
    
    static DEVICE_ATTR(test_input, S_IRUGO | S_IWUSR, NULL, input_test_store);
    
    static int register_input_device_for_jack(void)
    {
    	int err;
    	
    	/* 分配input_dev */
    	g_virtual_input = input_allocate_device();
    
    	/* 设置 */
    	/* 2.1 能产生哪类事件 */
    	set_bit(EV_SYN, g_virtual_input->evbit);
    	set_bit(EV_SW, g_virtual_input->evbit);
    
    
    	/* 2.2 能产生这类事件中的哪些 */
    	/* headset = 听筒 + MIC = SW_HEADPHONE_INSERT + SW_MICROPHONE_INSERT
    	 *    同时上报 SW_HEADPHONE_INSERT 和 SW_MICROPHONE_INSERT, 就表示headset
    	 *    为了简化, 对于android系统只上报SW_MICROPHONE_INSERT也表示headset
    	 */
    	set_bit(SW_HEADPHONE_INSERT, g_virtual_input->swbit);
    	set_bit(SW_MICROPHONE_INSERT, g_virtual_input->swbit);
    	set_bit(SW_LINEOUT_INSERT, g_virtual_input->swbit);
    
    	/* 2.3 这些事件的范围 */
    
    	g_virtual_input->name = "alsa_switch"; /* 不重要 */
    
    	/* 注册 */
    	err = input_register_device(g_virtual_input);
    	if (err) {
    		input_free_device(g_virtual_input);	
    		printk("input_register_device for virtual jack err!
    ");
    		return err;
    	}
    
    	/* 创建/sys/class/input/inputX/test_input文件
    	 *   可以执行类似下面的命令来模拟耳麦的动作:  
    	 *       触发上报headset插入: echo 4 1 > /sys/class/input/inputX/test_input  
    	 *       触发上报headset取下: echo 4 0 > /sys/class/input/inputX/test_input  
    	 */
    	err = device_create_file(&g_virtual_input->dev, &dev_attr_test_input);
    	if (err) {
    		printk("device_create_file for test_input err!
    ");
    		input_unregister_device(g_virtual_input);
    		input_free_device(g_virtual_input); 
    		return err;
    	}
    
    	return 0;
    }
    
    static void unregister_input_device_for_jack(void)
    {
    	device_remove_file(&g_virtual_input->dev, &dev_attr_test_input);
    
    	input_unregister_device(g_virtual_input);
    	input_free_device(g_virtual_input);	
    }
    
    
    /**************************************************************************************************************/
    
    static struct switch_dev g_virtual_switch;
    
    static ssize_t state_test_store(struct device *dev,
    				     struct device_attribute *attr,
    				     const char *buf, size_t count)
    {
    	long val;
    
    	val = simple_strtol(buf, NULL, 0);
    
    	printk("emulate to report swtich state: 0x%x
    ", val);
    	switch_set_state(&g_virtual_switch, val);
    
    	return count;
    }
    
    static DEVICE_ATTR(test_state, S_IRUGO | S_IWUSR, NULL, state_test_store);
    
    static int register_switch_device_for_jack(void)
    {
    	int err;
    	
    	g_virtual_switch.name = "h2w";
    	err = switch_dev_register(&g_virtual_switch);
    	if (err) {
    		printk("switch_dev_register h2w err!
    ");
    		return err;
    	}
    
    	/* 创建/sys/class/switch/h2w/test_state文件
    	 *   可以执行类似下面的命令来模拟耳麦的动作:  
    	 *       触发上报headset插入: echo 1 > /sys/class/switch/h2w/test_state
    	 *       触发上报headset取下: echo 0 > /sys/class/switch/h2w/test_state
    	 */
    	err = device_create_file(g_virtual_switch.dev, &dev_attr_test_state);
    	if (err) {
    		printk("device_create_file test err!
    ");
    		switch_dev_unregister(&g_virtual_switch);
    		return err;
    	}
    
    	return 0;
    }
    
    static void unregister_switch_device_for_jack(void)
    {
    	device_remove_file(g_virtual_switch.dev, &dev_attr_test_state);
    	switch_dev_unregister(&g_virtual_switch);
    }
    
    /**************************************************************************************************************/
    
    static int __init virtual_jack_init(void)
    {
    	int err;
    	
    	err = register_input_device_for_jack();
    	err = register_switch_device_for_jack();
    	
    	return 0;
    }
    
    static void __exit virtual_jack_exit(void)
    {
    	unregister_input_device_for_jack();
    	unregister_switch_device_for_jack();
    }
    
    module_init(virtual_jack_init);
    module_exit(virtual_jack_exit);
    
    MODULE_AUTHOR("weidongshan@qq.com");
    MODULE_DESCRIPTION("Virutal jack driver for sound card");
    MODULE_LICENSE("GPL");
    

  • 相关阅读:
    剑指Offer-30.连续子数组的最大和(C++/Java)
    剑指Offer-29.最小的K个数(C++/Java)
    UVA 1616 Caravan Robbers 商队抢劫者(二分)
    UVA 10570 Meeting with Aliens 外星人聚会
    UVA 11093 Just Finish it up 环形跑道 (贪心)
    UVA 12673 Erratic Expansion 奇怪的气球膨胀 (递推)
    UVA 10954 Add All 全部相加 (Huffman编码)
    UVA 714 Copying Books 抄书 (二分)
    UVALive 3523 Knights of the Round Table 圆桌骑士 (无向图点双连通分量)
    codeforecs Gym 100286B Blind Walk
  • 原文地址:https://www.cnblogs.com/linhaostudy/p/9704255.html
Copyright © 2011-2022 走看看