/* * Copyright (c) 2011-2023, Shanghai Real-Thread Electronic Technology Co.,Ltd * * Change Logs: * Date Author Notes * 2020-12-18 quanzhao the first version */ #include #include #include static struct rt_device random_dev; static unsigned long seed; static rt_uint16_t calc_random(void) { seed = 214013L * seed + 2531011L; return (seed >> 16) & 0x7FFF; /* return bits 16~30 */ } static rt_ssize_t random_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) { rt_uint16_t rand; ssize_t ret = 0; while (size >= sizeof(rand)) { /* update rand */ rand = calc_random(); *(rt_uint16_t *)buffer = rand; buffer = (char *)buffer + sizeof(rand); ret += sizeof(rand); size -= sizeof(rand); } if (size) { rand = calc_random(); memcpy(buffer, &rand, size); ret += size; } return ret; } static rt_ssize_t random_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) { ssize_t ret = sizeof(seed); rt_memcpy(&seed, buffer, ret); return ret; } static rt_err_t random_control(rt_device_t dev, int cmd, void *args) { return RT_EOK; } #ifdef RT_USING_DEVICE_OPS const static struct rt_device_ops random_ops = { RT_NULL, RT_NULL, RT_NULL, random_read, random_write, random_control }; #endif int random_device_init(void) { static rt_bool_t init_ok = RT_FALSE; if (init_ok) { return 0; } RT_ASSERT(!rt_device_find("random")); random_dev.type = RT_Device_Class_Miscellaneous; #ifdef RT_USING_DEVICE_OPS random_dev.ops = &random_ops; #else random_dev.init = RT_NULL; random_dev.open = RT_NULL; random_dev.close = RT_NULL; random_dev.read = random_read; random_dev.write = random_write; random_dev.control = random_control; #endif /* no private */ random_dev.user_data = RT_NULL; rt_device_register(&random_dev, "random", RT_DEVICE_FLAG_RDWR); init_ok = RT_TRUE; return 0; } INIT_DEVICE_EXPORT(random_device_init); static struct rt_device urandom_dev; static unsigned long useed; static rt_uint16_t calc_urandom(void) { useed = 214013L * useed + 2531011L; return (useed >> 16) & 0x7FFF; /* return bits 16~30 */ } static rt_ssize_t random_uread(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) { rt_uint16_t rand; ssize_t ret = 0; while (size >= sizeof(rand)) { /* update rand */ rand = calc_urandom(); *(rt_uint16_t *)buffer = rand; buffer = (char *)buffer + sizeof(rand); ret += sizeof(rand); size -= sizeof(rand); } if (size) { rand = calc_urandom(); memcpy(buffer, &rand, size); ret += size; } return ret; } static rt_ssize_t random_uwrite(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) { ssize_t ret = sizeof(useed); rt_memcpy(&useed, buffer, ret); return ret; } static rt_err_t random_ucontrol(rt_device_t dev, int cmd, void *args) { return RT_EOK; } #ifdef RT_USING_DEVICE_OPS const static struct rt_device_ops urandom_ops = { RT_NULL, RT_NULL, RT_NULL, random_uread, random_uwrite, random_ucontrol }; #endif int urandom_device_init(void) { static rt_bool_t init_ok = RT_FALSE; if (init_ok) { return 0; } RT_ASSERT(!rt_device_find("urandom")); urandom_dev.type = RT_Device_Class_Miscellaneous; #ifdef RT_USING_DEVICE_OPS urandom_dev.ops = &urandom_ops; #else urandom_dev.init = RT_NULL; urandom_dev.open = RT_NULL; urandom_dev.close = RT_NULL; urandom_dev.read = random_uread; urandom_dev.write = random_uwrite; urandom_dev.control = random_ucontrol; #endif /* no private */ urandom_dev.user_data = RT_NULL; rt_device_register(&urandom_dev, "urandom", RT_DEVICE_FLAG_RDWR); init_ok = RT_TRUE; return 0; } INIT_DEVICE_EXPORT(urandom_device_init);