视频流分析 四

该博客主要介绍了Linux驱动程序中如何实现耳机插入和拔出的中断处理,以及如何通过内核事件通知用户空间。在`imx-3stack-wm8994.c`中注册了耳机状态检测中断,并在中断处理函数中根据耳机状态发送不同的信息到用户空间。用户空间的`UEventObserver`类用于接收并处理这些事件,触发相应的回调。通过对内核中断和用户空间事件的结合,实现了硬件状态与用户应用之间的通信。
摘要由CSDN通过智能技术生成

目录

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();
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值