2022-09-15 23:09:15 +08:00

88 lines
2.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "chardev.h"
#include "internal.h"
#include <filesystem/VFS/VFS.h>
#include <common/mutex.h>
#include <common/stdlib.h>
#include <common/string.h>
#include <common/printk.h>
static struct vfs_dir_entry_t *chardev_folder_dentry = NULL;
extern struct vfs_dir_entry_t *devfs_root_dentry;
/**
* @brief 字符设备名称前缀
*
*/
static char chardev_name_prefix[CHAR_DEV_STYPE_END + 1][32] = {
[CHAR_DEV_STYPE_START] = "",
[CHAR_DEV_STYPE_PS2_KEYBOARD] = "ps2.kb",
[CHAR_DEV_STYPE_PS2_MOUSE] = "ps2.mse",
[CHAR_DEV_STYPE_USB_MOUSE] = "usb.mse",
[CHAR_DEV_STYPE_USB_KEYBOARD] = "usb.kb",
[CHAR_DEV_STYPE_BLUETOOTH_MOUSE] = "bt.mse",
[CHAR_DEV_STYPE_BLUETOOTH_KEYBOARD] = "bt.kb",
[CHAR_DEV_STYPE_TTY] = "vdev.tty",
[CHAR_DEV_STYPE_END] = "",
};
/**
* @brief 为不同类型的字符设备分配的管理信息结构体
*
*/
static struct chardev_manage_info_t
{
mutex_t lock; // 操作互斥锁
int count;
} chardev_manage_info[CHAR_DEV_STYPE_END + 1];
/**
* @brief 在devfs中注册字符设备该函数只应被devfs调用
*
* @param private_info inode私有信息
* @param target_dentry 返回的dentry的指针
* @return int 错误码
*/
int __devfs_chardev_register(struct devfs_private_inode_info_t *private_info, struct vfs_dir_entry_t **target_dentry)
{
// 检测subtype是否合法
if (private_info->sub_type <= CHAR_DEV_STYPE_START || private_info->sub_type >= CHAR_DEV_STYPE_END)
return -EINVAL;
mutex_lock(&chardev_manage_info[private_info->sub_type].lock);
// 拷贝名称
char devname[64] = {0};
strcpy(devname, chardev_name_prefix[private_info->sub_type]);
char *ptr = devname + strlen(chardev_name_prefix[private_info->sub_type]);
sprintk(ptr, "%d", chardev_manage_info[private_info->sub_type].count);
int namelen = strlen(devname);
struct vfs_dir_entry_t *dentry = vfs_alloc_dentry(namelen + 1);
__devfs_fill_dentry(dentry, devname);
__devfs_fill_inode(dentry, vfs_alloc_inode(), VFS_IF_DEVICE, private_info);
// 将dentry挂载到char文件夹下
__devfs_dentry_bind_parent(chardev_folder_dentry, dentry);
++chardev_manage_info[private_info->sub_type].count;
mutex_unlock(&chardev_manage_info[private_info->sub_type].lock);
*target_dentry = dentry;
return 0;
}
/**
* @brief 初始化chardev管理机制
*
*/
void __devfs_chardev_init()
{
// 初始化管理信息结构体
for (int i = CHAR_DEV_STYPE_START + 1; i < CHAR_DEV_STYPE_END; ++i)
{
mutex_init(&chardev_manage_info[i].lock);
chardev_manage_info[i].count = 0;
}
vfs_mkdir("/dev/char", 0, false);
// 获取char dev的dentry
chardev_folder_dentry = __devfs_find_dir(devfs_root_dentry, "char");
}