android平台驱动开发(二)--设备属性节点的创建

news/2024/11/23 1:37:37/

驱动开发

如何创建设备属性节点


文章目录

  • 驱动开发
  • 前言
  • 一、代码添加
  • 二、编译
  • 三、 验证
  • 总结


前言

最简单的设备属性节点


一、代码添加

在AU_LINUX_ANDROID_LA.VENDOR.1.0\kernel_platform\msm-kernel\drivers\misc\目录下新建test_device.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <asm/io.h>
#include <linux/platform_device.h>
#include <linux/ioport.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>static char  test_flag[32]="0";static ssize_t test_mode_show(struct device *dev,struct device_attribute *attr,char *buf)
{  printk("xxxxx xxx %s,%d: buf: %s test_flag:%s\n",__func__,__LINE__,buf,test_flag);return sprintf(buf, "%s\n",test_flag);
}static ssize_t test_mode_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count)
{ sprintf(test_flag, "%s",buf);printk("xxxxx %s,%d: buf: %s \n",__func__,__LINE__,buf); return count;
}static DEVICE_ATTR(xxx_test_mode,0644, test_mode_show, test_mode_store);static int test_driver_probe(struct platform_device *pdev)
{int ret; int force_gpio;struct device_node *np = pdev->dev.of_node;printk("xxxxx %s,%d: Enter\n",__func__,__LINE__);force_gpio = of_get_named_gpio(np,"qcom,gpio-force-download", 0);if(gpio_is_valid(force_gpio)){ret = gpio_request(force_gpio, "qcom-force-9008-gpio");gpio_export(force_gpio,0);}ret = device_create_file(&pdev->dev, &dev_attr_xxx_test_mode); if (ret < 0){  printk("xxxxx create files fail\n"); return ret;}  return 0;
}static int test_driver_remove(struct platform_device *pdev)
{ printk("xxxxx %s,%d: Enter\n",__func__,__LINE__);device_remove_file(&pdev->dev, &dev_attr_xxx_test_mode); return 0;
}static const struct of_device_id of_xxx_test_mode_match[] = {{ .compatible = "xxx-force-usb-boot", },{},
};static struct platform_driver test_driver ={ .probe = test_driver_probe, .remove = test_driver_remove, .driver = {.name = "xxx-test-mode", .owner  = THIS_MODULE,.of_match_table = of_match_ptr(of_xxx_test_mode_match),},
};static int test_driver_init(void)
{ printk("xxxxx %s,%d: Enter\n",__func__,__LINE__);return platform_driver_register(&test_driver);
}static void test_driver_exit(void)
{ printk("xxxxx %s,%d: Enter\n",__func__,__LINE__);platform_driver_unregister(&test_driver); return;
}module_init(test_driver_init);
module_exit(test_driver_exit);MODULE_AUTHOR("zh@testsmart.com");
MODULE_DESCRIPTION("test Smart Hardware Verion driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:test-mode-driver");

kernel_platform/qcom/proprietary/devicetree/qcom/cape-mtp.dtsi

&soc {gpio_keys {compatible = "gpio-keys";label = "gpio-keys";pinctrl-names = "default";pinctrl-0 = <&key_vol_up_default>,<&gpio_keys_active>;vol_up {label = "volume_up";gpios = <&pm8350_gpios 6 GPIO_ACTIVE_LOW>;linux,input-type = <1>;linux,code = <KEY_VOLUMEUP>;gpio-key,wakeup;debounce-interval = <15>;linux,can-disable;};home {label = "home";gpios = <&tlmm 46 GPIO_ACTIVE_LOW>;linux,input-type = <1>;linux,code = <KEY_HOME>;debounce-interval = <15>;gpio-key,wakeup;linux,can-disable;};vol_down {label = "volume_down";gpios = <&tlmm 19 GPIO_ACTIVE_LOW>;linux,input-type = <1>;linux,code = <KEY_VOLUMEDOWN>;gpio-key,wakeup;debounce-interval = <15>;linux,can-disable;};};+xxx-force-usb {+        compatible = "xxx-force-usb-boot";+       qcom,gpio-force-download = <&tlmm 47 0x2002>;+};};

修改misc目录下的Makefile
AU_LINUX_ANDROID_LA.VENDOR.1.0\kernel_platform\msm-kernel\drivers\misc\Makefile

+obj-m	+= test_device.o

注:obj-m最好是以宏控的方式控制,当然也可以以obj-y的方式编译进内核,后续详细介绍

二、编译

以骁龙8 gen1 plus平台为例
在AU_LINUX_ANDROID_LA.VENDOR.1.0目录下执行:

xxxx@u99:~/AU_LINUX_ANDROID_LA.VENDOR.1.0$bash kernel_platform/qcom/proprietary/prebuilt_HY11/vendorsetup.shxxxx@u99:~/AU_LINUX_ANDROID_LA.VENDOR.1.0$cd kernel_platform/xxxx@u99:~/AU_LINUX_ANDROID_LA.VENDOR.1.0/kernel_platform$BUILD_CONFIG=./common/build.config.msm.waipio ./build/all-variants.sh "./build/build.sh"

如上编译完成后AU_LINUX_ANDROID_LA.VENDOR.1.0\kernel_platform\out\msm-waipio-waipio-consolidate\dist\目录下会生成hello_world.ko;push到设备中验证即可。

三、 验证

adb push AU_LINUX_ANDROID_LA.VENDOR.1.0\kernel_platform\out\msm-waipio-waipio-consolidate\dist\test_device.ko /vendor_dlkm/lib/modules/

adb push AU_LINUX_ANDROID_LA.VENDOR.1.0\kernel_platform\out\msm-waipio-waipio-consolidate\dist\test_device.ko /vendor/lib/modules/

taro:/ # insmod vendor/lib/modules/test_device.ko
taro:/ # dmesg |grep xxx
[ 6455.143660] xxxxx test_driver_exit,96: Enter
[ 6455.143738] xxxxx test_driver_remove,66: Enter
[ 6467.130438] xxxxx test_driver_init,89: Enter
[ 6467.131992] xxxxx test_driver_probe,46: Enter
taro:/ # 
130|taro:/ # cat sys/devices/platform/soc/soc:xxx-force-usb/xxx_test_mode
0
taro:/ # echo 1 > sys/devices/platform/soc/soc:xxx-force-usb/xxx_test_mode
taro:/ # echo 1 > sys/devices/platform/soc/soc:xxx-force-usb/xxx_test_mode
taro:/ # cat sys/devices/platform/soc/soc:xxx-force-usb/xxx_test_mode
1taro:/ # dmesg |grep xxx
[ 6455.143660] xxxxx test_driver_exit,96: Enter
[ 6455.143738] xxxxx test_driver_remove,66: Enter
[ 6467.130438] xxxxx test_driver_init,89: Enter
[ 6467.131992] xxxxx test_driver_probe,46: Enter
[ 6486.875923] xxxxx xxx test_mode_show,24: buf:  test_flag:0
[ 6491.227092] xxxxx test_mode_store,33: buf: 1\x0a
[ 6493.537732] xxxxx test_mode_store,33: buf: 1\x0a
[ 6495.128476] xxxxx xxx test_mode_show,24: buf:  test_flag:1\x0a
taro:/ #

总结

这里是设备属性节点的添加,添加设备树的目的是为了申请gpio47,这样在开机后sys/class/gpio目录下就可以看到gpio348(SM8475平台的gpio偏移是301),以供厂测使用。关机时,此gpio拉高就可以进9008,即FORCE_USB_BOOT功能。
kernel_platform/common/arch/arm64/configs/consolidate.fragment
需要打开宏控,sys/class/gpio


+CONFIG_GPIO_SYSFS=y

关于设备节点有几种比较方式:

static ssize_t xxx_store(struct kobject *dev, struct kobj_attribute *attr, const char *buf, size_t count)
{int value = 0;if (num != sscanf(buf, "%d\n", &value)){pr_err("mcu_wake>>>%s: num=%d!=1,regaddr=%d\n", __func__, num, value);return -1;}if((value==1)||(value==0)){if(value==1) {}else {}}else{pr_err("%s\n",__func__);}return count;
}
==========static ssize_t mode_show(struct device *dev, struct device_attribute *attr,char *buf)
{struct dwc3_msm *mdwc = dev_get_drvdata(dev);if (mdwc->vbus_active)return snprintf(buf, PAGE_SIZE, "peripheral\n");if (mdwc->id_state == DWC3_ID_GROUND)return snprintf(buf, PAGE_SIZE, "host\n");return snprintf(buf, PAGE_SIZE, "none\n");
}static ssize_t mode_store(struct device *dev, struct device_attribute *attr,const char *buf, size_t count)
{struct dwc3_msm *mdwc = dev_get_drvdata(dev);if (sysfs_streq(buf, "peripheral")) {mdwc->vbus_active = true;mdwc->id_state = DWC3_ID_FLOAT;} else if (sysfs_streq(buf, "host")) {mdwc->vbus_active = false;mdwc->id_state = DWC3_ID_GROUND;} else {mdwc->vbus_active = false;mdwc->id_state = DWC3_ID_FLOAT;}dwc3_ext_event_notify(mdwc);return count;
}
==============static ssize_t usb_compliance_mode_show(struct device *dev,struct device_attribute *attr, char *buf)
{struct dwc3_msm *mdwc = dev_get_drvdata(dev);return snprintf(buf, PAGE_SIZE, "%c\n",mdwc->usb_compliance_mode ? 'Y' : 'N');
}static ssize_t usb_compliance_mode_store(struct device *dev,struct device_attribute *attr, const char *buf, size_t count)
{int ret = 0;struct dwc3_msm *mdwc = dev_get_drvdata(dev);ret = strtobool(buf, &mdwc->usb_compliance_mode);if (ret)return ret;return count;
}
=====================
static ssize_t dbg_state_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count)
{struct sdhci_host *host = dev_get_drvdata(dev);struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);bool v;if (!capable(CAP_SYS_ADMIN))return -EACCES;if (kstrtobool(buf, &v))return -EINVAL;msm_host->dbg_en = v;return count;
}=========
static ssize_t gtp_dofwupdate_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count)
{struct goodix_ts_data *ts = dev_get_drvdata(dev);char update_file_name[FW_NAME_MAX_LEN];int retval;if (count > FW_NAME_MAX_LEN) {dev_info(&ts->client->dev, "FW filename is too long\n");retval = -EINVAL;goto exit;}strlcpy(update_file_name, buf, count);ts->force_update = true;retval = gup_update_proc(update_file_name);if (retval == FAIL)dev_err(&ts->client->dev, "Fail to update GTP firmware.\n");elsedev_info(&ts->client->dev, "Update success\n");return count;exit:

http://www.ppmy.cn/news/371049.html

相关文章

android平台驱动开发(一)

驱动开发 hello world 文章目录 驱动开发前言一、代码添加二、编译三、 验证总结 前言 最简单的hello world 驱动 一、代码添加 在AU_LINUX_ANDROID_LA.VENDOR.1.0\kernel_platform\msm-kernel\drivers\misc\目录下新建hello_world文件夹 并创建hello_world.c #include <…

android平台驱动开发(三)--设备类节点实现重启功能

驱动开发 如何创建设备类属性节点 文章目录 驱动开发前言一、代码添加二、编译三、 验证总结 前言 最简单的设备属性累节点创建以及实现底层的重启功能 一、代码添加 在AU_LINUX_ANDROID_LA.VENDOR.1.0\kernel_platform\msm-kernel\drivers\misc\目录下新建test_reboot.c #…

PostgreSQL 15:新特性预告

PostgreSQL 15 版本正在开发中&#xff0c;不远的将来就会与大家见面&#xff0c;所以是时候看看未来的一些新功能吧&#xff01; 1.删除public 模式的创建权限 直到今天&#xff0c;使用 PostgreSQL 14&#xff0c;每个人都可以默认写入public 模式。使用 PostgreSQL 15&…

python中文编码与处理详解(个人认为比较全面详细了)

注意&#xff1a;本文只是针对 python 2&#xff0c;在 python 3 中&#xff0c;编码方式与处理技巧有些许变化&#xff0c;具体请参考&#xff1a; Python 2 与 Python 3 的差异对比&#xff1a; http://my.oschina.net/leejun2005/blog/173553 一、使用中文字符 在pytho…

python unicode编码转换中文_python unicode转中文及转换默认编码

原博文 2016-11-16 22:20 − 一、   在爬虫抓取网页信息时常需要将类似"\u4eba\u751f\u82e6\u77ed\uff0cpy\u662f\u5cb8"转换为中文,实际上这是unicode的中文编码。可用以下方法转换: 1、 1 >>> s = u\u4eba\u751f\u82e6\u77ed... 相关推荐 2019-12…

Linux下安装JDK 及 OpenJDK的卸载

今日发现我Linux系统中安装的JDK是1.8的版本&#xff0c;但是在查询时候竟然是1.7的版本&#xff0c;因为我目前从事大数据方向的开发&#xff0c;这对于当前很多流行的技术不是很友好&#xff0c;故解决此问题&#xff0c;也让各位同仁不必再为此烦恼。 1、查询JDK版本 [roo…

centos7 搭建oracle11g rac

一、部分理论 RAC&#xff0c;全称real application clusters&#xff0c; 译为“实时应用集群”&#xff0c;是Oracle新版数据库中采用的一项新技术&#xff0c;是高可用性的一-种&#xff0c;也是Oracle 数据库支持网格计算环境的核心技术。 ●VIP -虚拟IP地址(Virtual IP)。…

移动端页面px布局适配方案(viewport)

通过 <meta name"viewport"> 给视口设置固定的宽度&#xff0c;浏览器对页面自动缩放来实现页面的适配效果 可配合移动端手机网页适配iPad与折叠屏设备实现多平台兼容 简单描述下实现原理&#xff1a; 浏览器的宽度与取决于 <meta name"viewport"…