rt_random.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * Copyright (c) 2011-2023, Shanghai Real-Thread Electronic Technology Co.,Ltd
  3. *
  4. * Change Logs:
  5. * Date Author Notes
  6. * 2020-12-18 quanzhao the first version
  7. */
  8. #include <time.h>
  9. #include <string.h>
  10. #include <rtthread.h>
  11. static struct rt_device random_dev;
  12. static unsigned long seed;
  13. static rt_uint16_t calc_random(void)
  14. {
  15. seed = 214013L * seed + 2531011L;
  16. return (seed >> 16) & 0x7FFF; /* return bits 16~30 */
  17. }
  18. static rt_ssize_t random_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  19. {
  20. rt_uint16_t rand = calc_random();
  21. ssize_t ret = sizeof(rand);
  22. rt_memcpy(buffer, &rand, ret);
  23. return ret;
  24. }
  25. static rt_ssize_t random_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  26. {
  27. ssize_t ret = sizeof(seed);
  28. rt_memcpy(&seed, buffer, ret);
  29. return ret;
  30. }
  31. static rt_err_t random_control(rt_device_t dev, int cmd, void *args)
  32. {
  33. return RT_EOK;
  34. }
  35. #ifdef RT_USING_DEVICE_OPS
  36. const static struct rt_device_ops random_ops =
  37. {
  38. RT_NULL,
  39. RT_NULL,
  40. RT_NULL,
  41. random_read,
  42. random_write,
  43. random_control
  44. };
  45. #endif
  46. int random_device_init(void)
  47. {
  48. static rt_bool_t init_ok = RT_FALSE;
  49. if (init_ok)
  50. {
  51. return 0;
  52. }
  53. RT_ASSERT(!rt_device_find("random"));
  54. random_dev.type = RT_Device_Class_Miscellaneous;
  55. #ifdef RT_USING_DEVICE_OPS
  56. random_dev.ops = &random_ops;
  57. #else
  58. random_dev.init = RT_NULL;
  59. random_dev.open = RT_NULL;
  60. random_dev.close = RT_NULL;
  61. random_dev.read = random_read;
  62. random_dev.write = random_write;
  63. random_dev.control = random_control;
  64. #endif
  65. /* no private */
  66. random_dev.user_data = RT_NULL;
  67. rt_device_register(&random_dev, "random", RT_DEVICE_FLAG_RDWR);
  68. init_ok = RT_TRUE;
  69. return 0;
  70. }
  71. INIT_DEVICE_EXPORT(random_device_init);
  72. static struct rt_device urandom_dev;
  73. static unsigned long useed;
  74. static rt_uint16_t calc_urandom(void)
  75. {
  76. useed = 214013L * useed + 2531011L;
  77. return (useed >> 16) & 0x7FFF; /* return bits 16~30 */
  78. }
  79. static rt_ssize_t random_uread(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  80. {
  81. rt_uint16_t rand = calc_urandom();
  82. ssize_t ret = sizeof(rand);
  83. rt_memcpy(buffer, &rand, ret);
  84. return ret;
  85. }
  86. static rt_ssize_t random_uwrite(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  87. {
  88. ssize_t ret = sizeof(useed);
  89. rt_memcpy(&useed, buffer, ret);
  90. return ret;
  91. }
  92. static rt_err_t random_ucontrol(rt_device_t dev, int cmd, void *args)
  93. {
  94. return RT_EOK;
  95. }
  96. #ifdef RT_USING_DEVICE_OPS
  97. const static struct rt_device_ops urandom_ops =
  98. {
  99. RT_NULL,
  100. RT_NULL,
  101. RT_NULL,
  102. random_uread,
  103. random_uwrite,
  104. random_ucontrol
  105. };
  106. #endif
  107. int urandom_device_init(void)
  108. {
  109. static rt_bool_t init_ok = RT_FALSE;
  110. if (init_ok)
  111. {
  112. return 0;
  113. }
  114. RT_ASSERT(!rt_device_find("urandom"));
  115. urandom_dev.type = RT_Device_Class_Miscellaneous;
  116. #ifdef RT_USING_DEVICE_OPS
  117. urandom_dev.ops = &urandom_ops;
  118. #else
  119. urandom_dev.init = RT_NULL;
  120. urandom_dev.open = RT_NULL;
  121. urandom_dev.close = RT_NULL;
  122. urandom_dev.read = random_uread;
  123. urandom_dev.write = random_uwrite;
  124. urandom_dev.control = random_ucontrol;
  125. #endif
  126. /* no private */
  127. urandom_dev.user_data = RT_NULL;
  128. rt_device_register(&urandom_dev, "urandom", RT_DEVICE_FLAG_RDWR);
  129. init_ok = RT_TRUE;
  130. return 0;
  131. }
  132. INIT_DEVICE_EXPORT(urandom_device_init);