尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Android学习15 -- LED点灯(Ver1)
一定会写的。。。//2024061 简介之前留言了一定会写所以还是抽时间把这个弄了。因为这次用的高通的板子IO输出是1.8V无法驱动一个真实的LED所以用的迷你示波器看波形。然后这次用的版本是userdebug所以自启动selinux这些也都没有弄算是简化版的简化版。2 DriverDTS/* user-led bring-up patch (temporary; see neo-aliso-sg2-idp.user-led.patch.dtsi) */ /* ---- 2) Custom user LED platform device on GPIO 19 ---- */ tlmm { user_led_default: user-led-default { mux { pins gpio19; function gpio; }; config { pins gpio19; drive-strength 2; bias-disable; output-low; }; }; }; soc { user_led: user-led { compatible vendor,user-led; label user_led; led-gpios tlmm 19 0; /* GPIO 19, active high */ pinctrl-names default; pinctrl-0 user_led_default; status okay; }; };代码// SPDX-License-Identifier: GPL-2.0-only /* * user_led_driver.c - Custom platform driver to control a user LED via GPIO * * Exposes a sysfs brightness attribute under its platform device: * echo 1 .../user-led/brightness (turn LED on) * echo 0 .../user-led/brightness (turn LED off) * * Device tree node expected (see user-led.dtsi): * user_led { * compatible vendor,user-led; * led-gpios tlmm 19 0; // GPIO 19 (placeholder, per user) * label user_led; * }; * * Build: KLEAF ddk_module (see BUILD.bazel) */ #include linux/module.h #include linux/platform_device.h #include linux/of.h #include linux/gpio/consumer.h #include linux/sysfs.h #include linux/device.h #include linux/err.h #include linux/mutex.h #include linux/slab.h #define DRIVER_NAME user-led #define DRIVER_DESC User LED GPIO platform driver struct user_led_dev { struct device *dev; struct gpio_desc *led_gpio; struct mutex lock; int brightness; }; /* -------------------- sysfs attribute -------------------- */ static ssize_t brightness_show(struct device *dev, struct device_attribute *attr, char *buf) { struct user_led_dev *led dev_get_drvdata(dev); return sysfs_emit(buf, %d\n, led-brightness); } static ssize_t brightness_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct user_led_dev *led dev_get_drvdata(dev); unsigned long value; int ret; ret kstrtoul(buf, 0, value); if (ret) return ret; if (value 1) return -EINVAL; mutex_lock(led-lock); gpiod_set_value_cansleep(led-led_gpio, value); led-brightness value; mutex_unlock(led-lock); return count; } static DEVICE_ATTR_RW(brightness); static struct attribute *user_led_attrs[] { dev_attr_brightness.attr, NULL, }; static struct attribute_group user_led_group { .attrs user_led_attrs, }; /* -------------------- platform driver -------------------- */ static int user_led_probe(struct platform_device *pdev) { struct device *dev pdev-dev; struct user_led_dev *led; int ret; led devm_kzalloc(dev, sizeof(*led), GFP_KERNEL); if (!led) return -ENOMEM; led-dev dev; mutex_init(led-lock); dev_set_drvdata(dev, led); /* * GPIO number comes from DTS led-gpios (currently tlmm 19 0). * The flags (0 active high, GPIO_ACTIVE_LOW active low) are taken * from DTS too, so the driver works for either polarity. */ led-led_gpio devm_gpiod_get(dev, led, GPIOD_OUT_LOW); if (IS_ERR(led-led_gpio)) { ret PTR_ERR(led-led_gpio); dev_err(dev, failed to get led-gpios: %d\n, ret); return ret; } gpiod_set_consumer_name(led-led_gpio, user-led); led-brightness 0; /* Create the sysfs brightness attribute under the platform device. */ ret devm_device_add_group(dev, user_led_group); if (ret) { dev_err(dev, failed to create sysfs group: %d\n, ret); return ret; } dev_info(dev, user LED driver probed, GPIO active-%s\n, gpiod_is_active_low(led-led_gpio) ? low : high); return 0; } static int user_led_remove(struct platform_device *pdev) { struct user_led_dev *led dev_get_drvdata(pdev-dev); if (led-led_gpio) gpiod_set_value_cansleep(led-led_gpio, 0); return 0; } static const struct of_device_id user_led_of_match[] { { .compatible vendor,user-led }, { } }; MODULE_DEVICE_TABLE(of, user_led_of_match); static struct platform_driver user_led_driver { .probe user_led_probe, .remove user_led_remove, .driver { .name DRIVER_NAME, .of_match_table user_led_of_match, }, }; module_platform_driver(user_led_driver); MODULE_LICENSE(GPL); MODULE_AUTHOR(Your Name); MODULE_DESCRIPTION(DRIVER_DESC);此时可以先在命令行下面观察执行结果3 App核心就是控制那个节点。package com.example.userled import android.os.Bundle import android.widget.Button import android.widget.TextView import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File /** * Control App for the user LED. * * Writes 1/0 to the driver sysfs brightness node via root (su): * /sys/devices/.../user-led/brightness * * NOTE: The exact sysfs path depends on the platform device naming. * On Qualcomm platforms the node usually appears under /sys/devices/platform/ * or /sys/bus/platform/devices/. A robust way is to find it by reading the * label file, or use the fixed path if known. We locate it dynamically: * find /sys/devices -name brightness -path *user-led* */ class MainActivity : AppCompatActivity() { private val ledBrightnessPath /sys/devices/platform/soc/soc:user-led/brightness private lateinit var statusText: TextView private lateinit var btnOn: Button private lateinit var btnOff: Button private lateinit var btnFind: Button private val scope CoroutineScope(Dispatchers.Main) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) statusText findViewById(R.id.statusText) btnOn findViewById(R.id.btnOn) btnOff findViewById(R.id.btnOff) btnFind findViewById(R.id.btnFind) btnOn.setOnClickListener { setLed(1) } btnOff.setOnClickListener { setLed(0) } btnFind.setOnClickListener { findLedPath() } } override fun onDestroy() { super.onDestroy() RootHelper.release() } private fun setLed(value: Int) { scope.launch { val result withContext(Dispatchers.IO) { writeLed(value) } val (ok, message) result if (ok) { statusText.text LED ${if (value 1) ON else OFF} $ledBrightnessPath } else { statusText.text Failed: $message toast(message) } } } private fun findLedPath() { scope.launch { val path withContext(Dispatchers.IO) { locateLedBrightness() } if (path ! null) { statusText.text Found: $path toast(Found: $path) } else { statusText.text Not found (driver not loaded / not probed) toast(LED sysfs node not found) } } } /** Locates the brightness node for the user-led device. */ private fun locateLedBrightness(): String? { val node File(ledBrightnessPath) return ledBrightnessPath.takeIf { node.exists() } } private fun writeLed(value: Int): PairBoolean, String { val node File(ledBrightnessPath) if (!node.exists()) return false to LED driver node not found if (!node.canWrite()) return false to LED node is not writable return try { node.writeText(value.toString()) true to ledBrightnessPath } catch (e: Exception) { false to Write failed: ${e.message ?: e.javaClass.simpleName} } } private fun toast(msg: String) { Toast.makeText(this, msg, Toast.LENGTH_SHORT).show() } }UI
RELATED

相关推荐

深度学习最强 GitHub 仓库盘点:Top 200 开源项目榜单

深度学习最强 GitHub 仓库盘点:Top 200 开源项目榜单

深度学习最强 GitHub 仓库盘点:Top 200 开源项目榜单 【免费下载链接】Top-Deep-Learning Top 200 deep learning Github repositories sorted by the number of stars. 项目地址: https://gitcode.com/gh_mirrors/to/Top-Deep-Learning 想学深度学习&#…

📅 2026/9/17 14:43:36
企业数据出境场景安全评估

企业数据出境场景安全评估

一、数据出境场景1、数据提供给境外公司2、数据供境外公司、人员查询、访问等3、境外公司使用境内公司提供的服务,存储数据至境内(数据入境)二、评估流程1、判定是否达到《数据出境安全评估办法》规定开展数据出境评估要求根据《数据出境安全…

📅 2026/9/12 5:14:19
n8n工作流自动化零基础实战:从本地部署到生产落地的完整指南

n8n工作流自动化零基础实战:从本地部署到生产落地的完整指南

n8n工作流自动化零基础实战:从本地部署到生产落地的完整指南 【免费下载链接】n8n Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400 integrations. 项目地址: https://…

📅 2026/10/6 9:23:53
MORE NEWS

更多资讯

📰

SNL编译器实战:从词法分析到x86汇编生成

简介:这是一份面向编译原理课程学习者与C/C开发者实践的SNL语言编译器完整源码工程,聚焦词法分析、语法分析与语义分析三大核心环节,可用于课程设计、实验验证或编译器原理深度理解。资源包含231个文件,主体为C/C源码(…

📰

稀疏视频生成如何突破视觉语言导航的盲区:让机器人学会预知转角

我是一个长期泡在具身智能和视觉语言导航(Vision-Language Navigation,下称VLN)方向的研究者,最近看到一篇标题为"Sparse Video Generation Propels Real-World Beyond-the-View Vision-Language Navigation"的工作&…

📰

照片级风格迁移实战:从一眼假到以假乱真的技术解析

1. 从“一眼假”到“以假乱真”:照片级风格迁移到底在做什么第一次接触风格迁移是在一个图像处理的小项目里,当时想把一张普通风景照转成油画质感,用的是最基础的Gram矩阵方法。结果出来之后,朋友看了一眼说:“这不就是…

📰

Python+OpenCV答题卡识别判分系统:从拍照到成绩单的完整实现

简介:这份资源是面向高校学生与开发者的计算机视觉实战项目包,对应毕业设计、课程设计及论文选题场景,核心解决答题卡自动识别与判分问题。系统以Python为开发语言,采用Django搭建Web服务端,借助OpenCV完成图像预处理、…

📰

K8s LoadBalancer原理与排障:从Service到Pod的七层流量路径

1. 这不是“加个Service就完事”的 LoadBalancer:K8s里最常被误解的网络组件很多人第一次在K8s里配LoadBalancer类型Service时,心里想的是:“不就是把type: ClusterIP改成type: LoadBalancer,等几分钟,云平台自动给个公…

📰

自研TinyML专用开发板:从硬件设计到低功耗部署的完整实践

去年年底我在搞一个离线关键词唤醒的小项目,目标很朴素:一块电池、一个麦克风、一个MCU,能稳定识别三到五个唤醒词,待机电流控制在微安级。一开始我也没多想,直接用手边一块通用开发板开搞。结果越做越不对劲——板子四…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬