Android Switch驱动的耳机检测
在 Android 中添加了一个 switch 驱动,用于监测一些开关的变化,例如:HDMI、耳机的插拔检测之类的。
驱动源码存在内核源码的 drivers/switch 中,目录下有两个主要文件:switch_class.c 和switch_gpio.c,在 switch_class.c 中创建了 switch 设备类
static int create_switch_class(void)
实现了设备注册
int switch_dev_register(struct switch_dev *sdev)
在这个函数中,会创建两个文件,一个是保存状态的文件,一个是保存名称的文件,其中状态就开关量的表现,在这个文件中还有一个改变状态的方法
ret = device_create_file(sdev->dev, &dev_attr_state);if (ret < 0)goto err_create_file_1;ret = device_create_file(sdev->dev, &dev_attr_name);if (ret < 0)goto err_create_file_2;
这个 switch_gpio.c 文件中,就是实现了一个由 GPIO 变化来触发的 switch 动作,当设备匹配上时,会注册一个 GPIO 中断,在中断处理函数中,可以看到它会先获取gpio的值,然后设置switch的状态
static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
{struct gpio_switch_data *switch_data =(struct gpio_switch_data *)dev_id;schedule_work(&switch_data->work);return IRQ_HANDLED;
}
static void gpio_switch_work(struct work_struct *work)
{int state;struct gpio_switch_data *data =container_of(work, struct gpio_switch_data, work);state = gpio_get_value(data->gpio);switch_set_state(&data->sdev, state);gpio_set_value(AUDIO_SWITCH_GPIO_NUM, (state ? AUDIO_SWITCH_OFF : AUDIO_SWITCH_ON));
}
这里要注意的是,这个GPIO中断注册的时候默认选择的是低电平触发,如果是检测耳机接入,恰好耳机接入后会将 gpio 电平直接拉低,这时中断就会一直触发,可能会导致系统死机,如果遇到这种场景可将触发条件改成边沿触发就可以了。
@@ -112,7 +112,7 @@ static int gpio_switch_probe(struct platform_device *pdev)}ret = request_irq(switch_data->irq, gpio_irq_handler,
- IRQF_TRIGGER_LOW, pdev->name, switch_data);
+ (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING), pdev->name, switch_data);if (ret < 0)goto err_request_irq;
下面代码实现耳机检测的功能,注册了一个 h2w 的 switch 驱动
#include <linux/module.h>
#include <linux/switch.h>
#include <linux/platform_device.h>#define H2W_SWITCH_GPIO_NUM 22static struct gpio_switch_platform_data pdata = {.name = "h2w",.gpio = H2W_SWITCH_GPIO_NUM,.name_on = "1",.name_off = "0",.state_on = "1",.state_off = "0",
};static struct platform_device h2w_switch_dev = {.name = "switch-gpio",.dev = {.platform_data = &pdata,},
};static int __init h2w_switch_init(void) {return platform_device_register(&h2w_switch_dev);
}static void __exit h2w_switch_exit(void) {platform_device_unregister(&h2w_switch_dev);
}module_init(h2w_switch_init);
module_exit(h2w_switch_exit);
为什么命名为 h2w ?
原因是 Android 已经给铺好路了,Android 有一个 有线访问管理 机制
frameworks/base/services/core/java/com/android/server/WiredAccessoryManager.java,这里默认就定义了三种类型设备访问并进行管理,其中包括h2w、usb、hdmi,h2w 就是指的有线耳机。
private List<UEventInfo> makeObservedUEventList() {List<UEventInfo> retVal = new ArrayList<UEventInfo>();UEventInfo uei;// Monitor h2wif (!mUseDevInputEventForAudioJack) {uei = new UEventInfo(NAME_H2W, BIT_HEADSET, BIT_HEADSET_NO_MIC, BIT_LINEOUT);if (uei.checkSwitchExists()) {retVal.add(uei);} else {Slog.w(TAG, "This kernel does not have wired headset support");}}// Monitor USBuei = new UEventInfo(NAME_USB_AUDIO, BIT_USB_HEADSET_ANLG, BIT_USB_HEADSET_DGTL, 0);if (uei.checkSwitchExists()) {retVal.add(uei);} else {Slog.w(TAG, "This kernel does not have usb audio support");}// Monitor HDMI//// If the kernel has support for the "hdmi_audio" switch, use that. It will be// signalled only when the HDMI driver has a video mode configured, and the downstream// sink indicates support for audio in its EDID.//// If the kernel does not have an "hdmi_audio" switch, just fall back on the older// "hdmi" switch instead.uei = new UEventInfo(NAME_HDMI_AUDIO, BIT_HDMI_AUDIO, 0, 0);if (uei.checkSwitchExists()) {retVal.add(uei);} else {uei = new UEventInfo(NAME_HDMI, BIT_HDMI_AUDIO, 0, 0);if (uei.checkSwitchExists()) {retVal.add(uei);} else {Slog.w(TAG, "This kernel does not have HDMI audio support");}}return retVal;
}
关于这个 有线访问管理 是如何得知这个设备的,在我们设置设置这个 switch 状态的时候可以看到,它同时发送了一个 uevent 消息,然后被上层接收后进行处理。
kobject_uevent_env(&sdev->dev->kobj, KOBJ_CHANGE, envp);
有线访问管理机制 就会告知 AudioManager 设备状态的改变
mAudioManager.setWiredDeviceConnectionState(outDevice, state, "", headsetName);
Android Switch驱动的耳机检测相关推荐
- Android 耳机检测原理介绍
前言 欢迎大家我分享和推荐好用的代码段~~ 声明 欢迎转载,但请保留文章原始出处: CSDN:http://www.csdn.net ...
- android switch模块
Android新增了一个switch处理模块,但是没有说明其具体用途,这里将对该模块进行详细的分析.switch是Android引进的一个新驱动,用于检测一些开关量.比如检测耳机插入和USB设备插入等 ...
- 解决Eclipse、Android Studio ADT AVD不能检测到手机
解决Eclipse.Android Studio ADT AVD不能检测到手机 Android开发时,经常会使用Eclipse或者Android Studio开发工具,在使用真机调试App ...
- Android 图形驱动初始化
从应用程序的角度看 OpenGL 图形系统的接口,主要包括两大部分,一部分是 EGL,它为 OpenGL 渲染准备环境:另一部分是 OpenGL,它执行图形渲染.通过这些接口构造渲染环境,并执行渲染的 ...
- android lcd驱动框架,LCD驱动及Framebuffer相关(转载)
LCD驱动及Framebuffer相关 (2012-11-20 17:04) 标签:&nBSP; lcd驱动 framebuffer io内存 分类: Android驱动模块相关 内容提 ...
- Android 图形驱动初始化(二十三)
从应用程序的角度看 OpenGL 图形系统的接口,主要包括两大部分,一部分是 EGL,它为 OpenGL 渲染准备环境:另一部分是 OpenGL,它执行图形渲染.通过这些接口构造渲染环境,并执行渲染的 ...
- android audiorecord插上耳机录音由dmic切换到耳机录音
板子上带有一个dmic,和一个adc,不插耳机时audiorecord默认将打开dmic录音,插上耳机时自动切换到耳机录音. 这个场景是手机上太常见了,由于是tv和盒子的芯片,默认没有对这种场景的支持 ...
- Android 性能优化(62)---存检测、卡顿优化、耗电优化、APK瘦身——详解篇
Android 性能优化,内存检测.卡顿优化.耗电优化.APK瘦身--详解篇 自2008年智能时代开始,Android操作系统一路高歌,10年智能机发展之路,如今 Android 9.0 代号P 都 ...
- android 设备驱动
驱动概述 说到 android 驱动是离不开 Linux 驱动的.Android 内核采用的是 Linux2.6 内核 (最近Linux 3.3 已经包含了一些 Android 代码).但 Andro ...
最新文章
- 排序算法三:插入排序
- html5实践开发教程,HTML5基础与实践教程
- python生成条形码
- __dopostback
- DELETE_FAILED_INTERNAL_ERROR Error while Installing APK
- 开源 java CMS - FreeCMS2.7 单位管理
- ae合成复制脚本_【脚本】AE脚本精选系列 | 合成复制脚本 True Comp Duplicator v3.9.7...
- 淘宝网打开很慢、特别慢的完美解决方法
- Java可以做什么工作
- 【清华大学】操作系统 陈渝——Part7 进程/线程 管理
- 河南大学计算机科学与技术中外合作,河南大学中外合作办学怎么样
- 如何使用Flashfxp上传下载文件
- js引用本地json文件
- LeGO-LOAM资料整理
- 把日期横杠转化为斜杠
- 【学堂上新】Unity UGUI 渲染 3D 对象详解
- 目前住院病人主要由护士护理,这样做不仅需要大量护士,而且由于不能随时观察危重病人的病情变化,还可能会延误抢救时机。某医院打算开发一个以计算机为中心的监护系统,试写出问题定义并且分析开发这个系统的可行性
- HDU2188——悼念512汶川大地震遇难同胞——选拔志愿者(Bash Game巴士博弈)(我去,名字肿么这么长)
- kindeditor上传本地图片的问题
- matlab获取晶粒边界,晶粒边界