chardev.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. #include "chardev.h"
  2. #include "internal.h"
  3. #include <filesystem/VFS/VFS.h>
  4. #include <common/mutex.h>
  5. #include <common/stdlib.h>
  6. #include <common/string.h>
  7. #include <common/printk.h>
  8. static struct vfs_dir_entry_t *chardev_folder_dentry = NULL;
  9. extern struct vfs_dir_entry_t *devfs_root_dentry;
  10. /**
  11. * @brief 字符设备名称前缀
  12. *
  13. */
  14. static char chardev_name_prefix[CHAR_DEV_STYPE_END + 1][32] = {
  15. [CHAR_DEV_STYPE_START] = "",
  16. [CHAR_DEV_STYPE_PS2_KEYBOARD] = "ps2.kb",
  17. [CHAR_DEV_STYPE_PS2_MOUSE] = "ps2.mse",
  18. [CHAR_DEV_STYPE_USB_MOUSE] = "usb.mse",
  19. [CHAR_DEV_STYPE_USB_KEYBOARD] = "usb.kb",
  20. [CHAR_DEV_STYPE_BLUETOOTH_MOUSE] = "bt.mse",
  21. [CHAR_DEV_STYPE_BLUETOOTH_KEYBOARD] = "bt.kb",
  22. [CHAR_DEV_STYPE_END] = "",
  23. };
  24. /**
  25. * @brief 为不同类型的字符设备分配的管理信息结构体
  26. *
  27. */
  28. static struct chardev_manage_info_t
  29. {
  30. mutex_t lock; // 操作互斥锁
  31. int count;
  32. } chardev_manage_info[CHAR_DEV_STYPE_END + 1];
  33. /**
  34. * @brief 在devfs中注册字符设备(该函数只应被devfs调用)
  35. *
  36. * @param private_info inode私有信息
  37. * @param target_dentry 返回的dentry的指针
  38. * @return int 错误码
  39. */
  40. int __devfs_chardev_register(struct devfs_private_inode_info_t *private_info, struct vfs_dir_entry_t **target_dentry)
  41. {
  42. // 检测subtype是否合法
  43. if (private_info->sub_type <= CHAR_DEV_STYPE_START || private_info->sub_type >= CHAR_DEV_STYPE_END)
  44. return -EINVAL;
  45. mutex_lock(&chardev_manage_info[private_info->sub_type].lock);
  46. // 拷贝名称
  47. char devname[64] = {0};
  48. strcpy(devname, chardev_name_prefix[private_info->sub_type]);
  49. char *ptr = devname + strlen(chardev_name_prefix[private_info->sub_type]);
  50. sprintk(ptr, "%d", chardev_manage_info[private_info->sub_type].count);
  51. int namelen = strlen(devname);
  52. struct vfs_dir_entry_t *dentry = vfs_alloc_dentry(namelen + 1);
  53. __devfs_fill_dentry(dentry, devname);
  54. __devfs_fill_inode(dentry, vfs_alloc_inode(), VFS_IF_DEVICE, private_info);
  55. // 将dentry挂载到char文件夹下
  56. __devfs_dentry_bind_parent(chardev_folder_dentry, dentry);
  57. ++chardev_manage_info[private_info->sub_type].count;
  58. mutex_unlock(&chardev_manage_info[private_info->sub_type].lock);
  59. *target_dentry = dentry;
  60. return 0;
  61. }
  62. /**
  63. * @brief 初始化chardev管理机制
  64. *
  65. */
  66. void __devfs_chardev_init()
  67. {
  68. // 初始化管理信息结构体
  69. for (int i = CHAR_DEV_STYPE_START + 1; i < CHAR_DEV_STYPE_END; ++i)
  70. {
  71. mutex_init(&chardev_manage_info[i].lock);
  72. chardev_manage_info[i].count = 0;
  73. }
  74. vfs_mkdir("/dev/char", 0, false);
  75. // 获取char dev的dentry
  76. chardev_folder_dentry = __devfs_find_dir(devfs_root_dentry, "char");
  77. }