1
0

dht11.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /*
  2. * dht11.c - Using GPIO to read temperature and humidity from DHT11 sensor.
  3. */
  4. #include <linux/cdev.h>
  5. #include <linux/delay.h>
  6. #include <linux/device.h>
  7. #include <linux/fs.h>
  8. #include <linux/gpio.h>
  9. #include <linux/init.h>
  10. #include <linux/module.h>
  11. #include <linux/printk.h>
  12. #include <linux/types.h>
  13. #include <linux/uaccess.h>
  14. #include <linux/version.h>
  15. #include <asm/errno.h>
  16. #define GPIO_PIN_4 575
  17. #define DEVICE_NAME "dht11"
  18. #define DEVICE_CNT 1
  19. static char msg[64];
  20. struct dht11_dev {
  21. dev_t dev_num;
  22. int major_num, minor_num;
  23. struct cdev cdev;
  24. struct class *cls;
  25. struct device *dev;
  26. };
  27. static struct dht11_dev dht11_device;
  28. /* Define GPIOs for LEDs.
  29. * TODO: According to the requirements, search /sys/kernel/debug/gpio to
  30. * find the corresponding GPIO location.
  31. */
  32. static struct gpio dht11[] = { { GPIO_PIN_4, GPIOF_OUT_INIT_HIGH, "Signal" } };
  33. static int dht11_read_data(void)
  34. {
  35. int timeout;
  36. uint8_t sensor_data[5] = { 0 };
  37. uint8_t i, j;
  38. gpio_set_value(dht11[0].gpio, 0);
  39. mdelay(20);
  40. gpio_set_value(dht11[0].gpio, 1);
  41. udelay(30);
  42. gpio_direction_input(dht11[0].gpio);
  43. udelay(2);
  44. timeout = 300;
  45. while (gpio_get_value(dht11[0].gpio) && timeout--)
  46. udelay(1);
  47. if (timeout == -1)
  48. return -ETIMEDOUT;
  49. timeout = 300;
  50. while (!gpio_get_value(dht11[0].gpio) && timeout--)
  51. udelay(1);
  52. if (timeout == -1)
  53. return -ETIMEDOUT;
  54. timeout = 300;
  55. while (gpio_get_value(dht11[0].gpio) && timeout--)
  56. udelay(1);
  57. if (timeout == -1)
  58. return -ETIMEDOUT;
  59. for (j = 0; j < 5; j++) {
  60. uint8_t byte = 0;
  61. for (i = 0; i < 8; i++) {
  62. timeout = 300;
  63. while (gpio_get_value(dht11[0].gpio) && timeout--)
  64. udelay(1);
  65. if (timeout == -1)
  66. return -ETIMEDOUT;
  67. timeout = 300;
  68. while (!gpio_get_value(dht11[0].gpio) && timeout--)
  69. udelay(1);
  70. if (timeout == -1)
  71. return -ETIMEDOUT;
  72. udelay(50);
  73. byte <<= 1;
  74. if (gpio_get_value(dht11[0].gpio))
  75. byte |= 0x01;
  76. }
  77. sensor_data[j] = byte;
  78. }
  79. if (sensor_data[4] != (uint8_t)(sensor_data[0] + sensor_data[1] +
  80. sensor_data[2] + sensor_data[3]))
  81. return -EIO;
  82. gpio_direction_output(dht11[0].gpio, 1);
  83. sprintf(msg, "Humidity: %d%%\nTemperature: %d deg C\n", sensor_data[0],
  84. sensor_data[2]);
  85. return 0;
  86. }
  87. static int device_open(struct inode *inode, struct file *file)
  88. {
  89. int ret, retry;
  90. for (retry = 0; retry < 5; ++retry) {
  91. ret = dht11_read_data();
  92. if (ret == 0)
  93. return 0;
  94. msleep(10);
  95. }
  96. gpio_direction_output(dht11[0].gpio, 1);
  97. return ret;
  98. }
  99. static int device_release(struct inode *inode, struct file *file)
  100. {
  101. return 0;
  102. }
  103. static ssize_t device_read(struct file *filp, char __user *buffer,
  104. size_t length, loff_t *offset)
  105. {
  106. int msg_len = strlen(msg);
  107. if (*offset >= msg_len)
  108. return 0;
  109. size_t remain = msg_len - *offset;
  110. size_t bytes_read = min(length, remain);
  111. if (copy_to_user(buffer, msg + *offset, bytes_read))
  112. return -EFAULT;
  113. *offset += bytes_read;
  114. return bytes_read;
  115. }
  116. static struct file_operations fops = {
  117. #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
  118. .owner = THIS_MODULE,
  119. #endif
  120. .open = device_open,
  121. .release = device_release,
  122. .read = device_read
  123. };
  124. /* Initialize the module - Register the character device */
  125. static int __init dht11_init(void)
  126. {
  127. int ret = 0;
  128. /* Determine whether dynamic allocation of the device number is needed. */
  129. if (dht11_device.major_num) {
  130. dht11_device.dev_num =
  131. MKDEV(dht11_device.major_num, dht11_device.minor_num);
  132. ret = register_chrdev_region(dht11_device.dev_num, DEVICE_CNT,
  133. DEVICE_NAME);
  134. } else {
  135. ret = alloc_chrdev_region(&dht11_device.dev_num, 0, DEVICE_CNT,
  136. DEVICE_NAME);
  137. }
  138. /* Negative values signify an error */
  139. if (ret < 0) {
  140. pr_alert("Failed to register character device, error: %d\n", ret);
  141. return ret;
  142. }
  143. pr_info("Major = %d, Minor = %d\n", MAJOR(dht11_device.dev_num),
  144. MINOR(dht11_device.dev_num));
  145. /* Prevents module unloading while operations are in use */
  146. #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0)
  147. dht11_device.cdev.owner = THIS_MODULE;
  148. #endif
  149. cdev_init(&dht11_device.cdev, &fops);
  150. ret = cdev_add(&dht11_device.cdev, dht11_device.dev_num, 1);
  151. if (ret) {
  152. pr_err("Failed to add the device to the system\n");
  153. goto fail1;
  154. }
  155. #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0)
  156. dht11_device.cls = class_create(DEVICE_NAME);
  157. #else
  158. dht11_device.cls = class_create(THIS_MODULE, DEVICE_NAME);
  159. #endif
  160. if (IS_ERR(dht11_device.cls)) {
  161. pr_err("Failed to create class for device\n");
  162. ret = PTR_ERR(dht11_device.cls);
  163. goto fail2;
  164. }
  165. dht11_device.dev = device_create(dht11_device.cls, NULL,
  166. dht11_device.dev_num, NULL, DEVICE_NAME);
  167. if (IS_ERR(dht11_device.dev)) {
  168. pr_err("Failed to create the device file\n");
  169. ret = PTR_ERR(dht11_device.dev);
  170. goto fail3;
  171. }
  172. pr_info("Device created on /dev/%s\n", DEVICE_NAME);
  173. ret = gpio_request(dht11[0].gpio, dht11[0].label);
  174. if (ret) {
  175. pr_err("Unable to request GPIOs for dht11: %d\n", ret);
  176. goto fail4;
  177. }
  178. ret = gpio_direction_output(dht11[0].gpio, 1);
  179. if (ret) {
  180. pr_err("Failed to set GPIO %d direction\n", dht11[0].gpio);
  181. goto fail5;
  182. }
  183. return 0;
  184. fail5:
  185. gpio_free(dht11[0].gpio);
  186. fail4:
  187. device_destroy(dht11_device.cls, dht11_device.dev_num);
  188. fail3:
  189. class_destroy(dht11_device.cls);
  190. fail2:
  191. cdev_del(&dht11_device.cdev);
  192. fail1:
  193. unregister_chrdev_region(dht11_device.dev_num, DEVICE_CNT);
  194. return ret;
  195. }
  196. static void __exit dht11_exit(void)
  197. {
  198. gpio_set_value(dht11[0].gpio, 0);
  199. gpio_free(dht11[0].gpio);
  200. device_destroy(dht11_device.cls, dht11_device.dev_num);
  201. class_destroy(dht11_device.cls);
  202. cdev_del(&dht11_device.cdev);
  203. unregister_chrdev_region(dht11_device.dev_num, DEVICE_CNT);
  204. }
  205. module_init(dht11_init);
  206. module_exit(dht11_exit);
  207. MODULE_LICENSE("GPL");