chardev.c 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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_TTY] = "vdev.tty",
  23. [CHAR_DEV_STYPE_END] = "",
  24. };
  25. /**
  26. * @brief 为不同类型的字符设备分配的管理信息结构体
  27. *
  28. */
  29. static struct chardev_manage_info_t
  30. {
  31. mutex_t lock; // 操作互斥锁
  32. int count;
  33. } chardev_manage_info[CHAR_DEV_STYPE_END + 1];
  34. /**
  35. * @brief 在devfs中注册字符设备(该函数只应被devfs调用)
  36. *
  37. * @param private_info inode私有信息
  38. * @param target_dentry 返回的dentry的指针
  39. * @return int 错误码
  40. */
  41. int __devfs_chardev_register(struct devfs_private_inode_info_t *private_info, struct vfs_dir_entry_t **target_dentry)
  42. {
  43. // 检测subtype是否合法
  44. if (private_info->sub_type <= CHAR_DEV_STYPE_START || private_info->sub_type >= CHAR_DEV_STYPE_END)
  45. return -EINVAL;
  46. mutex_lock(&chardev_manage_info[private_info->sub_type].lock);
  47. // 拷贝名称
  48. char devname[64] = {0};
  49. strcpy(devname, chardev_name_prefix[private_info->sub_type]);
  50. char *ptr = devname + strlen(chardev_name_prefix[private_info->sub_type]);
  51. sprintk(ptr, "%d", chardev_manage_info[private_info->sub_type].count);
  52. int namelen = strlen(devname);
  53. struct vfs_dir_entry_t *dentry = vfs_alloc_dentry(namelen + 1);
  54. __devfs_fill_dentry(dentry, devname);
  55. __devfs_fill_inode(dentry, vfs_alloc_inode(), VFS_IF_DEVICE, private_info);
  56. // 将dentry挂载到char文件夹下
  57. __devfs_dentry_bind_parent(chardev_folder_dentry, dentry);
  58. ++chardev_manage_info[private_info->sub_type].count;
  59. mutex_unlock(&chardev_manage_info[private_info->sub_type].lock);
  60. *target_dentry = dentry;
  61. return 0;
  62. }
  63. /**
  64. * @brief 初始化chardev管理机制
  65. *
  66. */
  67. void __devfs_chardev_init()
  68. {
  69. // 初始化管理信息结构体
  70. for (int i = CHAR_DEV_STYPE_START + 1; i < CHAR_DEV_STYPE_END; ++i)
  71. {
  72. mutex_init(&chardev_manage_info[i].lock);
  73. chardev_manage_info[i].count = 0;
  74. }
  75. vfs_mkdir("/dev/char", 0, false);
  76. // 获取char dev的dentry
  77. chardev_folder_dentry = __devfs_find_dir(devfs_root_dentry, "char");
  78. }