chardev.c 2.6 KB

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