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

可以做宣传海报的网站台州seo服务

可以做宣传海报的网站,台州seo服务,兰州产品营销网站建设,wordpress主题加密前言最近需要将之前的一些驱动接口转为安卓标准接口#xff0c;方便上层应用或者第三方应用去适配。这篇文章先从简单的马达框架入手进行讲解。正文整个马达框架比较简单#xff0c;安卓官方已经帮我们实现了framework到HAL层#xff0c;我们需要实现的就只有驱动层。这篇文… 前言最近需要将之前的一些驱动接口转为安卓标准接口方便上层应用或者第三方应用去适配。这篇文章先从简单的马达框架入手进行讲解。正文整个马达框架比较简单安卓官方已经帮我们实现了framework到HAL层我们需要实现的就只有驱动层。这篇文章我们梳理一下从上层到底层怎么流程。1、APP层import android.os.Vibrator; import android.widget.ToggleButton;public class MainActivity extends Activity { Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);private Vibrator vibratornull; vibrator(Vibrator)this.getSystemService(VIBRATOR_SERVICE); toggleButton1(ToggleButton)findViewById(R.id.toggleButton1); /*短震动*/ toggleButton1.setOnCheckedChangeListener(new ToggleButton.OnCheckedChangeListener() {Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if(isChecked){Log.i(TAG,toggleButton1 enter vibrator.vibrate); //设置震动周期第二个参数为 -1表示只震动一次 vibrator.vibrate(new long[]{1000, 10, 100, 1000},-1); }else{ //取消震动Log.i(TAG,toggleButton1 enter vibrator.cancel()); vibrator.cancel(); } } }); } }上面展示了一个最简单的马达震动应用代码获得服务后即可调用接口进行驱动。2、framework层代码路径frameworks\base\services\core\java\com\android\server\VibratorService.java   Override // Binder callpublic void vibrate(int uid, String opPkg, VibrationEffect effect, int usageHint,IBinder token) {Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, vibrate);try {if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)! PackageManager.PERMISSION_GRANTED) {throw new SecurityException(Requires VIBRATE permission);}if (token null) {Slog.e(TAG, token must not be null);return;}verifyIncomingUid(uid);if (!verifyVibrationEffect(effect)) {return;}// If our current vibration is longer than the new vibration and is the same amplitude,// then just let the current one finish.synchronized (mLock) {if (effect instanceof VibrationEffect.OneShot mCurrentVibration ! null mCurrentVibration.effect instanceof VibrationEffect.OneShot) {VibrationEffect.OneShot newOneShot (VibrationEffect.OneShot) effect;VibrationEffect.OneShot currentOneShot (VibrationEffect.OneShot) mCurrentVibration.effect;if (mCurrentVibration.hasTimeoutLongerThan(newOneShot.getDuration()) newOneShot.getAmplitude() currentOneShot.getAmplitude()) {if (DEBUG) {Slog.d(TAG,Ignoring incoming vibration in favor of current vibration);}return;}}// If the current vibration is repeating and the incoming one is non-repeating,// then ignore the non-repeating vibration. This is so that we dont cancel// vibrations that are meant to grab the attention of the user, like ringtones and// alarms, in favor of one-shot vibrations that are likely quite short.if (!isRepeatingVibration(effect) mCurrentVibration ! null isRepeatingVibration(mCurrentVibration.effect)) {if (DEBUG) {Slog.d(TAG, Ignoring incoming vibration in favor of alarm vibration);}return;}Vibration vib new Vibration(token, effect, usageHint, uid, opPkg);linkVibration(vib);long ident Binder.clearCallingIdentity();try {doCancelVibrateLocked();startVibrationLocked(vib);addToPreviousVibrationsLocked(vib);} finally {Binder.restoreCallingIdentity(ident);}}} finally {Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);}}接口里面会判断一下权限根据应用层传递的不同effect值有不同的震动效果。然后就调用到JNI层调用顺序大概如下startVibrationLocked startVibrationInnerLocked doVibratorOn vibratorOn3、JNI层代码路径frameworks\base\services\core\jni\com_android_server_VibratorService.cppstatic void vibratorOn(JNIEnv* /* env */, jobject /* clazz */, jlong timeout_ms) {Status retStatus halCall(V1_0::IVibrator::on, timeout_ms).withDefault(Status::UNKNOWN_ERROR);if (retStatus ! Status::OK) {ALOGE(vibratorOn command failed (% PRIu32 )., static_castuint32_t(retStatus));} }static void vibratorOff(JNIEnv* /* env */, jobject /* clazz */) {Status retStatus halCall(V1_0::IVibrator::off).withDefault(Status::UNKNOWN_ERROR);if (retStatus ! Status::OK) {ALOGE(vibratorOff command failed (% PRIu32 )., static_castuint32_t(retStatus));} }static const JNINativeMethod method_table[] {{ vibratorExists, ()Z, (void*)vibratorExists },{ vibratorInit, ()V, (void*)vibratorInit },{ vibratorOn, (J)V, (void*)vibratorOn },{ vibratorOff, ()V, (void*)vibratorOff },{ vibratorSupportsAmplitudeControl, ()Z, (void*)vibratorSupportsAmplitudeControl},{ vibratorSetAmplitude, (I)V, (void*)vibratorSetAmplitude},{ vibratorPerformEffect, (JJ)J, (void*)vibratorPerformEffect} };int register_android_server_VibratorService(JNIEnv *env) {return jniRegisterNativeMethods(env, com/android/server/VibratorService,method_table, NELEM(method_table)); }以马达的On和off为例会调用到HAL层的on和off方法。4、HIDL层代码路径hardware\interfaces\vibrator\1.0\default\Vibrator.cppReturnStatus Vibrator::on(uint32_t timeout_ms) {int32_t ret mDevice-vibrator_on(mDevice, timeout_ms);if (ret ! 0) {ALOGE(on command failed : %s, strerror(-ret));return Status::UNKNOWN_ERROR;}return Status::OK; }ReturnStatus Vibrator::off() {int32_t ret mDevice-vibrator_off(mDevice);if (ret ! 0) {ALOGE(off command failed : %s, strerror(-ret));return Status::UNKNOWN_ERROR;}return Status::OK; }HIDL层是较新的安卓版本才引入的是连接HAL层和JNI层的桥梁。5、HAL层代码路径hardware\libhardware\modules\vibrator\vibrator.cstatic const char THE_DEVICE[] /sys/class/timed_output/vibrator/enable;static int sendit(unsigned int timeout_ms) {char value[TIMEOUT_STR_LEN]; /* large enough for millions of years */snprintf(value, sizeof(value), %u, timeout_ms);return write_value(THE_DEVICE, value); }static int vibra_on(vibrator_device_t* vibradev __unused, unsigned int timeout_ms) {/* constant on, up to maximum allowed time */return sendit(timeout_ms); }static int vibra_off(vibrator_device_t* vibradev __unused) {return sendit(0); }static int vibra_open(const hw_module_t* module, const char* id __unused,hw_device_t** device __unused) {bool use_led;if (vibra_exists()) {ALOGD(Vibrator using timed_output);use_led false;} else if (vibra_led_exists()) {ALOGD(Vibrator using LED trigger);use_led true;} else {ALOGE(Vibrator device does not exist. Cannot start vibrator);return -ENODEV;}vibrator_device_t *vibradev calloc(1, sizeof(vibrator_device_t));if (!vibradev) {ALOGE(Can not allocate memory for the vibrator device);return -ENOMEM;}vibradev-common.tag HARDWARE_DEVICE_TAG;vibradev-common.module (hw_module_t *) module;vibradev-common.version HARDWARE_DEVICE_API_VERSION(1,0);vibradev-common.close vibra_close;if (use_led) {vibradev-vibrator_on vibra_led_on;vibradev-vibrator_off vibra_led_off;} else {vibradev-vibrator_on vibra_on;vibradev-vibrator_off vibra_off;}*device (hw_device_t *) vibradev;return 0; }其实开启和关闭马达的工作很简单就是往节点/sys/class/timed_output/vibrator/enable写入震动时间所以可以想得到驱动层只需要提供一个节点供上层操作就好。6、驱动层 马达的驱动是基于kernel提供的timed_output框架完成的代码路径kernel-4.4\drivers\staging\android\timed_output.c代码比较简单提供接口给驱动在/sys/class/timed_output/路径下面建立自己的节点并提供节点的device attribute的操作接口当我们写节点的时候就会调用到enable_store函数并调用注册驱动的enable函数。static struct class *timed_output_class;static ssize_t enable_store(struct device *dev, struct device_attribute *attr,const char *buf, size_t size) { struct timed_output_dev *tdev dev_get_drvdata(dev); int value; int rc;rc kstrtoint(buf, 0, value); if (rc ! 0) return -EINVAL;tdev-enable(tdev, value);return size; } static DEVICE_ATTR_RW(enable);static struct attribute *timed_output_attrs[] { dev_attr_enable.attr, NULL, }; ATTRIBUTE_GROUPS(timed_output);static int create_timed_output_class(void) { if (!timed_output_class) { timed_output_class class_create(THIS_MODULE, timed_output); if (IS_ERR(timed_output_class)) return PTR_ERR(timed_output_class); atomic_set(device_count, 0); timed_output_class-dev_groups timed_output_groups; }return 0; }int timed_output_dev_register(struct timed_output_dev *tdev) { int ret;if (!tdev || !tdev-name || !tdev-enable || !tdev-get_time) return -EINVAL;ret create_timed_output_class(); if (ret 0) return ret;tdev-index atomic_inc_return(device_count); tdev-dev device_create(timed_output_class, NULL, MKDEV(0, tdev-index), NULL, %s, tdev-name); if (IS_ERR(tdev-dev)) return PTR_ERR(tdev-dev);dev_set_drvdata(tdev-dev, tdev); tdev-state 0; return 0; } 现在我们看一下基于上面框架书写的马达驱动static void vibrator_off(void) { gpio_direction_output(gpio, !en_value);       wake_unlock(vibdata.wklock); //震动关闭就可以释放 wake_lock锁         }void motor_enable(struct timed_output_dev *sdev,int value) { mutex_lock(vibdata.lock); //关键代码段,同一时间只允许一个线程执行/* cancelprevious timer and set GPIO according to value */ hrtimer_cancel(vibdata.timer); //当先前定时器完成后 关闭这个定时器 cancel_work_sync(vibdata.work); //当上次震动完成后 关闭这次动作 if(value) { wake_lock(vibdata.wklock); //开始震动打开wake lock锁不允许休眠 gpio_direction_output(gpio, en_value);if(value 0) { if(value MAX_TIMEOUT) value MAX_TIMEOUT; hrtimer_start(vibdata.timer,ktime_set(value / 1000, (value % 1000) * 1000000),HRTIMER_MODE_REL); } } else vibrator_off();mutex_unlock(vibdata.lock); }struct timed_output_dev motot_driver { .name vibrator, //注意这个名字,由于HAL层里面的设备为///sys/class/timed_output/vibrator/enable//因此这个名字必须为vibrator .enable motor_enable, .get_time get_time, };static enum hrtimer_restart vibrator_timer_func(struct hrtimer *timer) //定时器结束时候的回调函数 { schedule_work(vibdata.work); //定时器完成了 执行work队列回调函数来关闭电机 return HRTIMER_NORESTART; } static void vibrator_work(struct work_struct *work) { vibrator_off(); }static int motor_probe(struct platform_device *pdev) { struct device_node *node pdev-dev.of_node; enum of_gpio_flags flags; int ret 0;hrtimer_init(vibdata.timer,CLOCK_MONOTONIC, HRTIMER_MODE_REL); vibdata.timer.function vibrator_timer_func; INIT_WORK(vibdata.work,vibrator_work);...rettimed_output_dev_register(motot_driver); if (ret 0) goto err_to_dev_reg; return 0;err_to_dev_reg: mutex_destroy(vibdata.lock); wake_lock_destroy(vibdata.wklock);printk(vibrator   err!:%d\n,ret); return ret;}1、 驱动接收上层传递过来的是震动时长单位为毫秒。在驱动里注册一个定时器定时器倒计时到期后会唤醒注册的工作队列最终会执行vibrator_work()函数去关闭马达震动。2、调用timed_output框架提供的timed_output_dev_register()接口将我们的马达驱动注册进系统这里的关键就是我们需要自定义struct timed_output_dev结构体填充enable和get_time函数。enable函数用来开启马达的震动void motor_enable(struct timed_output_dev *sdev,int value) { mutex_lock(vibdata.lock); //关键代码段,同一时间只允许一个线程执行/* cancelprevious timer and set GPIO according to value */ hrtimer_cancel(vibdata.timer); //当先前定时器完成后 关闭这个定时器 cancel_work_sync(vibdata.work); //当上次震动完成后 关闭这次动作 if(value) { wake_lock(vibdata.wklock); //开始震动打开wake lock锁不允许休眠 gpio_direction_output(gpio, en_value);if(value 0) { if(value MAX_TIMEOUT) value MAX_TIMEOUT; hrtimer_start(vibdata.timer,ktime_set(value / 1000, (value % 1000) * 1000000),HRTIMER_MODE_REL); } } else vibrator_off();mutex_unlock(vibdata.lock); }开启震动的操作也很简单只是写一下GPIO然后重新开启定时器倒计时的时间就是写入节点的值到时间再把马达关闭就好。参考链接https://blog.csdn.net/qq_34211365/article/details/105556842嵌入式Linux微信扫描二维码关注我的公众号
http://www.zqtcl.cn/news/399381/

相关文章:

  • 山东省住房与建设厅网站首页有名的wordpress主题商
  • 常州市金坛区网站建设毕业设计代做淘宝好还是网站好
  • 品牌网站建设营销型网站设计网站整合方案
  • 网站开发设计师网站代理什么意思
  • 网站层级关系邯郸品牌商标vi设计策划公司
  • 网站开发产品需求说明小网站代码
  • 苏州网站推广排名网站建设方案范文8篇
  • 自己做考试题目网站广州番禺区美食攻略
  • 广州做网站如何如何制作一个网页
  • 网站定制开发收费标准是多少网站代码优化方案
  • 制作卡牌的网站深圳正规煤气公司
  • 手表网站哪家好网站用图片
  • 群辉nas 做网站wordpress linux 中文
  • 平面设计素材网站排名巩义网站建设方案表
  • 延庆网站制作搜索引擎优化的基础是什么
  • 管理手机网站商城网站备案流程
  • 怀化买房网站网站广告js代码添加
  • 做网站 帮别人卖服务器wordpress主题多页面
  • 代理游戏网站潍坊市建设工程管理处网站
  • 大同推广型网站建设网站规划建设与管理维护第二版答案
  • 做网站需要代码吗户外媒体网站建设免费
  • 做什么网站国外做图标网站
  • 网站建设技术部职责门户网站工作总结
  • 用个人电脑做服务器建网站急切网头像在线制作图片
  • 企业网站制作教程浙江省住房和城乡建设厅网站
  • 一个网络空间如何做两个网站哪个网站兼职做设计比较好
  • jquery代码做的网站免费搭建网站模板
  • 铁路建设监理协会官方网站邯郸市网
  • 马鞍山集团网站建设客流分析系统公司
  • 淘客网站怎么做啊抖音怎么挂小程序赚钱