Android从驱动到app,以LED控制系统简单示例

在这里插入图片描述

以下实现一个简单的 LED 控制系统,包括驱动程序、HAL 层和 Framework 层的代码示例。
我们将使用 AIDL 来定义应用程序与 Framework 层之间的接口,并使用 Binder 机制在 Framework 层与 HAL 层之间进行通信。(仅简单示例,便于理解代码开发流程,不保证能运行)

1. LED 驱动程序

创建一个名为 led_driver.c 的文件,内容如下:

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>

#define DEVICE_NAME "led"
#define CLASS_NAME "led_class"

static int major;
static struct class *led_class;
static struct cdev led_cdev;
static bool led_on = false;

static int led_open(struct inode *inode, struct file *file) {
    printk(KERN_INFO "led: Device opened\n");
    return 0;
}

static int led_release(struct inode *inode, struct file *file) {
    printk(KERN_INFO "led: Device closed\n");
    return 0;
}

static ssize_t led_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) {
    char status = led_on ? '1' : '0';
    if (copy_to_user(buf, &status, 1)) {
        return -EFAULT;
    }
    printk(KERN_INFO "led: Read %c\n", status);
    return 1;
}

static ssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) {
    char command;
    if (copy_from_user(&command, buf, 1)) {
        return -EFAULT;
    }
    if (command == '1') {
        led_on = true;
        printk(KERN_INFO "led: LED turned on\n");
    } else if (command == '0') {
        led_on = false;
        printk(KERN_INFO "led: LED turned off\n");
    } else {
        return -EINVAL;
    }
    return count;
}

static struct file_operations fops = {
    .owner = THIS_MODULE,
    .open = led_open,
    .release = led_release,
    .read = led_read,
    .write = led_write,
};

static int __init led_init(void) {
    dev_t dev;
    int result;

    result = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
    if (result < 0) {
        printk(KERN_WARNING "led: Can't get major number\n");
        return result;
    }

    major = MAJOR(dev);
    cdev_init(&led_cdev, &fops);
    led_cdev.owner = THIS_MODULE;
    result = cdev_add(&led_cdev, dev, 1);
    if (result) {
        printk(KERN_NOTICE "led: Error %d adding led", result);
        unregister_chrdev_region(dev, 1);
        return result;
    }

    led_class = class_create(THIS_MODULE, CLASS_NAME);
    if (IS_ERR(led_class)) {
        cdev_del(&led_cdev);
        unregister_chrdev_region(dev, 1);
        return PTR_ERR(led_class);
    }

    device_create(led_class, NULL, dev, NULL, DEVICE_NAME);

    printk(KERN_INFO "led: Registered with major number %d\n", major);
    return 0;
}

static void __exit led_exit(void) {
    dev_t dev = MKDEV(major, 0);

    device_destroy(led_class, dev);
    class_destroy(led_class);
    cdev_del(&led_cdev);
    unregister_chrdev_region(dev, 1);

    printk(KERN_INFO "led: Unregistered\n");
}

module_init(led_init);
module_exit(led_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple LED driver");
MODULE_VERSION("1.0");

2. HAL 层代码

HAL 层代码需要实现一个标准的 HAL 接口,并通过 hw_device_t 结构体与驱动进行交互。

PS:关于HAL层的知识,老罗的《Android系统源代码情景分析》第二章有详细介绍:
这篇写得很详细:
第二章 硬件抽象层

2.1. 定义 HAL 接口

首先,我们定义一个 HAL 接口文件,用于描述 HAL 层提供的服务。创建一个名为 led_hal.h 的文件,内容如下:

#ifndef ANDROID_LED_HAL_H
#define ANDROID_LED_HAL_H

#include <hardware/hardware.h>

__BEGIN_DECLS

#define LED_HARDWARE_MODULE_ID "led"

struct led_device_t {
    struct hw_device_t common;
    int (*set_on)(struct led_device_t* dev);
    int (*set_off)(struct led_device_t* dev);
    int (*get_state)(struct led_device_t* dev, int* state);
};

__END_DECLS

#endif // ANDROID_LED_HAL_H
2.2. 实现 HAL 模块

接下来,我们实现 HAL 模块。创建一个名为 led_hal.cpp 的文件,内容如下:

#include <hardware/hardware.h>
#include <hardware/led_hal.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>

#define LED_DEVICE "/dev/led"

static int led_set_on(struct led_device_t* dev) {
    int fd = open(LED_DEVICE, O_WRONLY);
    if (fd < 0) {
        return -errno;
    }
    write(fd, "1", 1);
    close(fd);
    return 0;
}

static int led_set_off(struct led_device_t* dev) {
    int fd = open(LED_DEVICE, O_WRONLY);
    if (fd < 0) {
        return -errno;
    }
    write(fd, "0", 1);
    close(fd);
    return 0;
}

static int led_get_state(struct led_device_t* dev, int* state) {
    int fd = open(LED_DEVICE, O_RDONLY);
    if (fd < 0) {
        return -errno;
    }
    char status;
    read(fd, &status, 1);
    close(fd);
    *state = (status == '1') ? 1 : 0;
    return 0;
}

static int led_close(hw_device_t* device) {
    free(device);
    return 0;
}

static int led_open(const hw_module_t* module, const char* id, hw_device_t** device) {
    if (strcmp(id, LED_HARDWARE_MODULE_ID) != 0) {
        return -EINVAL;
    }

    led_device_t* dev = (led_device_t*)malloc(sizeof(led_device_t));
    if (!dev) {
        return -ENOMEM;
    }

    memset(dev, 0, sizeof(led_device_t));
    dev->common.tag = HARDWARE_DEVICE_TAG;
    dev->common.version = 0;
    dev->common.module = (hw_module_t*)module;
    dev->common.close = led_close;
    dev->set_on = led_set_on;
    dev->set_off = led_set_off;
    dev->get_state = led_get_state;

    *device = (hw_device_t*)dev;
    return 0;
}

static struct hw_module_methods_t led_module_methods = {
    .open = led_open,
};

extern "C" {
    struct led_module_t HAL_MODULE_INFO_SYM = {
        .common = {
            .tag = HARDWARE_MODULE_TAG,
            .version_major = 1,
            .version_minor = 0,
            .id = LED_HARDWARE_MODULE_ID,
            .name = "LED HAL",
            .author = "Your Name",
            .methods = &led_module_methods,
        },
    };
}

3. Framework 层代码

接下来,我们实现 Framework 层代码。假设我们使用 Java 实现 Framework 层,并使用 Binder 机制进行通信。

3.1. 定义 AIDL 接口

创建一个名为 ILedService.aidl 的文件,内容如下:

package com.example.ledservice;

interface ILedService {
    void turnOn();
    void turnOff();
    boolean isOn();
}
3.2. 实现 Framework 层代码

创建一个名为 LedService.java 的文件,内容如下:

package com.example.ledservice;

import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;

public class LedService extends ILedService.Stub {
    private static final String TAG = "LedService";
    private ILedService mLedHal;

    public LedService() {
        mLedHal = ILedService.Stub.asInterface(ServiceManager.getService("ledhal"));
    }

    @Override
    public void turnOn() throws RemoteException {
        if (mLedHal != null) {
            mLedHal.turnOn();
        } else {
            Log.e(TAG, "LED HAL service not available");
        }
    }

    @Override
    public void turnOff() throws RemoteException {
        if (mLedHal != null) {
            mLedHal.turnOff();
        } else {
            Log.e(TAG, "LED HAL service not available");
        }
    }

    @Override
    public boolean isOn() throws RemoteException {
        if (mLedHal != null) {
            return mLedHal.isOn();
        } else {
            Log.e(TAG, "LED HAL service not available");
            return false;
        }
    }
}

4. 测试应用程序

最后,我们编写一个简单的 Android 应用程序,通过 AIDL 接口与 Framework 层进行通信,测试 LED 控制功能。

4.1. 创建 MainActivity.java
package com.example.ledapp;

import android.app.Activity;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.example.ledservice.ILedService;

public class MainActivity extends Activity {
    private ILedService mLedService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        IBinder binder = ServiceManager.getService("ledservice");
        mLedService = ILedService.Stub.asInterface(binder);

        Button turnOnButton = findViewById(R.id.turn_on_button);
        Button turnOffButton = findViewById(R.id.turn_off_button);
        Button checkStatusButton = findViewById(R.id.check_status_button);

        turnOnButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    mLedService.turnOn();
                    Toast.makeText(MainActivity.this, "LED turned on", Toast.LENGTH_SHORT).show();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });

        turnOffButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    mLedService.turnOff();
                    Toast.makeText(MainActivity.this, "LED turned off", Toast.LENGTH_SHORT).show();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });

        checkStatusButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    boolean isOn = mLedService.isOn();
                    Toast.makeText(MainActivity.this, "LED is " + (isOn ? "on" : "off"), Toast.LENGTH_SHORT).show();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}
4.2. 创建 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <Button
        android:id="@+id/turn_on_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Turn On LED" />

    <Button
        android:id="@+id/turn_off_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Turn Off LED" />

    <Button
        android:id="@+id/check_status_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Check LED Status" />
</LinearLayout>

总结

通过以上步骤,我们实现了一个完整的 LED 控制系统,包括驱动程序、HAL 层和 Framework 层的代码示例。应用程序通过 AIDL 接口与 Framework 层进行通信,Framework 层通过 Binder 机制与 HAL 层进行通信,HAL 层通过 hw_device_t 结构体与内核驱动程序进行通信,从而实现对 LED 的控制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值