目录
1 Imx-3stack-wm8994.c中注册耳机侦测中断函数
2 Imx-3stack-wm8994.c中耳机侦测插入拔出所发出的给用户层的信息
3 UEventObservr.java中注册抽象类UEventOberver
1 Imx-3stack-wm8994.c中注册耳机侦测中断函数
static int __devinit imx_3stack_wm8994_probe(struct platform_device *pdev)
{
struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
struct imx_3stack_priv *priv = &card_priv;
struct snd_soc_dai *wm8994_cpu_dai = 0;
struct wm8994 *wm8994 = plat->priv;
int ret = 0;
priv->pdev = pdev;
priv->wm8994 = wm8994;
gpio_activate_audio_ports();
imx_3stack_init_dam(plat->src_port, plat->ext_port);
if (plat->src_port == 2)
wm8994_cpu_dai = imx_ssi_dai[2];
else if (plat->src_port == 1)
wm8994_cpu_dai = imx_ssi_dai[0];
else if (plat->src_port == 7)
wm8994_cpu_dai = imx_ssi_dai[4];
imx_3stack_dai[0].cpu_dai = wm8994_cpu_dai;
/* get mxc_audio_platform_data for pcm */
imx_3stack_dai[0].cpu_dai->dev = &pdev->dev;
imx_3stack_dai[1].cpu_dai->dev = &pdev->dev;
imx_3stack_dai[2].cpu_dai->dev = &pdev->dev;
ret = driver_create_file(pdev->dev.driver, &driver_attr_headphone);
if (ret < 0) {
pr_err("%s:failed to create driver_attr_headphone\n", __func__);
goto sysfs_err;
}
ret = -EINVAL;
if (plat->init && plat->init())
goto err_plat_init;
priv->sysclk = plat->sysclk;
if (plat->hp_status())
ret = request_irq(plat->hp_irq,
imx_headphone_detect_handler,
IRQ_TYPE_EDGE_FALLING, pdev->name, priv);
else
ret = request_irq(plat->hp_irq,
imx_headphone_detect_handler,
IRQ_TYPE_EDGE_RISING, pdev->name, priv);
if (ret < 0) {
pr_err("%s: request irq failed\n", __func__);
goto err_card_reg;
}
return 0;
err_card_reg:
if (plat->finit)
plat->finit();
err_plat_init:
driver_remove_file(pdev->dev.driver, &driver_attr_headphone);
sysfs_err:
return ret;
}
2 Imx-3stack-wm8994.c中耳机侦测插入拔出所发出的给用户层的信息
static void headphone_detect_handler(struct work_struct *work)
{
struct imx_3stack_priv *priv = &card_priv;
struct platform_device *pdev = priv->pdev;
struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
int hp_status;
char *envp[3];
char *buf;
int mic_status;
sysfs_notify(&pdev->dev.kobj, NULL, "headphone");
hp_status = plat->hp_status();
if (jack.status & SND_JACK_MICROPHONE)
mic_status = 1;
else
mic_status = 0;
/* setup a message for userspace headphone in */
buf = kmalloc(32, GFP_ATOMIC);
if (!buf) {
pr_err("%s kmalloc failed\n", __func__);
return;
}
//拼凑出的envp,以方便上层对此数据的判断,到底是什么设备被侦测到
if (hp_status == 1 && mic_status == 1) {
envp[0] = "NAME=headset";
snprintf(buf, 32, "STATE=%d", 1);
} else if (hp_status == 1 && mic_status == 0) {
envp[0] = "NAME=headphone";
snprintf(buf, 32, "STATE=%d", 2);
} else {
envp[0] = "NAME=headphone";
snprintf(buf, 32, "STATE=%d", 0);
}
envp[1] = buf;
envp[2] = NULL;
//耳机侦测插入拔出所发出的给用户层的信息
kobject_uevent_env(&pdev->dev.kobj, KOBJ_CHANGE, envp);
kfree(buf);
if (hp_status)
set_irq_type(plat->hp_irq, IRQ_TYPE_EDGE_FALLING);
else
set_irq_type(plat->hp_irq, IRQ_TYPE_EDGE_RISING);
enable_irq(plat->hp_irq);
}
static DECLARE_DELAYED_WORK(hp_event, headphone_detect_handler);
static irqreturn_t imx_headphone_detect_handler(int irq, void *data)
{
disable_irq_nosync(irq);
schedule_delayed_work(&hp_event, msecs_to_jiffies(200));
return IRQ_HANDLED;
}
3 UEventObservr.java中注册抽象类UEventOberver
/**
* UEventObserver is an abstract class that receives UEvent's from the kernel.<p>
*
* Subclass UEventObserver, implementing onUEvent(UEvent event), then call
* startObserving() with a match string. The UEvent thread will then call your
* onUEvent() method when a UEvent occurs that contains your match string.<p>
*
* Call stopObserving() to stop receiving UEvent's.<p>
*
* There is only one UEvent thread per process, even if that process has
* multiple UEventObserver subclass instances. The UEvent thread starts when
* the startObserving() is called for the first time in that process. Once
* started the UEvent thread will not stop (although it can stop notifying
* UEventObserver's via stopObserving()).<p>
*
* @hide
*/
UEventObserver是一个用来从kenerl中接收UEvent的抽象类
public abstract class UEventObserver {
private static final String TAG = UEventObserver.class.getSimpleName();
/**
* Representation of a UEvent.
*/
static public class UEvent {
// collection of key=value pairs parsed from the uevent message
public HashMap<String,String> mMap = new HashMap<String,String>();
//通过bufferStr字符串拼凑得到对应的UEvent对象
public UEvent(String message) {
int offset = 0;
int length = message.length();
while (offset < length) {
int equals = message.indexOf('=', offset);
int at = message.indexOf(0, offset);
if (at < 0) break;
if (equals > offset && equals < at) {
// key is before the equals sign, and value is after
mMap.put(message.substring(offset, equals),
message.substring(equals + 1, at));
}
offset = at + 1;
}
}
public String get(String key) {
return mMap.get(key);
}
public String get(String key, String defaultValue) {
String result = mMap.get(key);
return (result == null ? defaultValue : result);
}
//此方法为子类提供接口处理
public String toString() {
return mMap.toString();
}
}
private static UEventThread sThread;
private static boolean sThreadStarted = false;
private static class UEventThread extends Thread {
/** Many to many mapping of string match to observer.
* Multimap would be better, but not available in android, so use
* an ArrayList where even elements are the String match and odd
* elements the corresponding UEventObserver observer */
private ArrayList<Object> mObservers = new ArrayList<Object>();
UEventThread() {
super("UEventObserver");
}
public void run() {
native_setup();
byte[] buffer = new byte[1024];
int len;
while (true) {
len = next_event(buffer);
if (len > 0) {
//由buffer拼凑bufferStr字符串,即由字符数组转换成String类型
String bufferStr = new String(buffer, 0, len); // easier to search a String
synchronized (mObservers) {
for (int i = 0; i < mObservers.size(); i += 2) {
if (bufferStr.indexOf((String)mObservers.get(i)) != -1) {
//在UEvent的构造函数中构造从kernel中得到的上报的event所组成的字符串
((UEventObserver)mObservers.get(i+1))
.onUEvent(new UEvent(bufferStr));
}
}
}
}
}
}
public void addObserver(String match, UEventObserver observer) {
synchronized(mObservers) {
mObservers.add(match);
mObservers.add(observer);
}
}
/** Removes every key/value pair where value=observer from mObservers */
public void removeObserver(UEventObserver observer) {
synchronized(mObservers) {
boolean found = true;
while (found) {
found = false;
for (int i = 0; i < mObservers.size(); i += 2) {
if (mObservers.get(i+1) == observer) {
mObservers.remove(i+1);
mObservers.remove(i);
found = true;
break;
}
}
}
}
}
}
private static native void native_setup();
private static native int next_event(byte[] buffer);
private static final synchronized void ensureThreadStarted() {
if (sThreadStarted == false) {
sThread = new UEventThread();
sThread.start();
sThreadStarted = true;
}
}
/**
* Begin observation of UEvent's.<p>
* This method will cause the UEvent thread to start if this is the first
* invocation of startObserving in this process.<p>
* Once called, the UEvent thread will call onUEvent() when an incoming
* UEvent matches the specified string.<p>
* This method can be called multiple times to register multiple matches.
* Only one call to stopObserving is required even with multiple registered
* matches.
* @param match A substring of the UEvent to match. Use "" to match all
* UEvent's
*/
public final synchronized void startObserving(String match) {
ensureThreadStarted();
sThread.addObserver(match, this);
}
/**
* End observation of UEvent's.<p>
* This process's UEvent thread will never call onUEvent() on this
* UEventObserver after this call. Repeated calls have no effect.
*/
public final synchronized void stopObserving() {
sThread.removeObserver(this);
}
/**
* Subclasses of UEventObserver should override this method to handle
* UEvents.
*/
public abstract void onUEvent(UEvent event);
protected void finalize() throws Throwable {
try {
stopObserving();
} finally {
super.finalize();
}
}
}