tima_uevent.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * TIMA Uevent Support
  3. *
  4. */
  5. #include <asm/uaccess.h>
  6. #include <linux/list.h>
  7. #include <linux/device.h>
  8. #include <linux/kernel.h>
  9. #include <linux/kobject.h>
  10. #include <linux/module.h>
  11. #include <linux/miscdevice.h>
  12. #include <linux/slab.h>
  13. #include <linux/syscalls.h>
  14. #include "tima_uevent.h"
  15. // Forward declaration
  16. struct inode;
  17. // Global declaration
  18. static DEFINE_MUTEX(tima_uevent_mutex);
  19. static struct class *tima_uevent_class;
  20. struct device *tima_uevent_dev;
  21. EXPORT_SYMBOL_GPL(tima_uevent_dev);
  22. static LIST_HEAD(tima_uevent_list);
  23. static DEFINE_SPINLOCK(tima_uevent_list_lock);
  24. static ssize_t show_tima_uevent(struct device *dev,
  25. struct device_attribute *attr, char *buf)
  26. {
  27. if (!dev)
  28. return -ENODEV;
  29. // TODO: extract TIMA uevent from the uevent list
  30. return sprintf(buf, "%s\n", "TIMA uevent data");
  31. }
  32. static DEVICE_ATTR(name, S_IRUGO, show_tima_uevent, NULL);
  33. static int
  34. tima_uevent_release(struct inode *inode, struct file *file)
  35. {
  36. printk(KERN_WARNING
  37. "%s TIMA uevent driver is released.",
  38. __func__);
  39. module_put(THIS_MODULE);
  40. return 0;
  41. }
  42. static bool
  43. tima_uevent_validate(void)
  44. {
  45. printk(KERN_ERR
  46. "Validate caller (%s)",
  47. current->comm);
  48. return true;
  49. }
  50. static ssize_t
  51. tima_uevent_read(struct file *filp, char __user *buff,
  52. size_t len, loff_t * offset)
  53. {
  54. char tima_uevent[80] = "TIMA uevent read";
  55. char *data;
  56. int size = strlen(tima_uevent);
  57. int retval = 0;
  58. if ( !tima_uevent_validate() ) {
  59. printk(KERN_ERR
  60. "%s invalid request.\n",
  61. __func__);
  62. return -EPERM;
  63. }
  64. data = kzalloc(sizeof(tima_uevent), GFP_KERNEL);
  65. if (!data) {
  66. printk(KERN_ERR
  67. "%s out of memory.\n",
  68. __func__);
  69. return -ENOMEM;
  70. }
  71. spin_lock(&tima_uevent_list_lock);
  72. snprintf(data, size, "%c%s", size - 2, tima_uevent);
  73. if ( copy_to_user(buff, data, size) ) {
  74. retval = -EFAULT;
  75. goto out;
  76. }
  77. out:
  78. spin_unlock(&tima_uevent_list_lock);
  79. kfree(data);
  80. if (retval) {
  81. return retval;
  82. } else {
  83. return size;
  84. }
  85. }
  86. static ssize_t
  87. tima_uevent_write(struct file *filp, const char __user *buff,
  88. size_t len, loff_t * off)
  89. {
  90. int retval = 0;
  91. char *req;
  92. if ( !tima_uevent_validate() ) {
  93. printk(KERN_ERR
  94. "%s invalid request.\n",
  95. __func__);
  96. return -EPERM;
  97. }
  98. req = kzalloc(256, GFP_KERNEL);
  99. if (!req) {
  100. printk(KERN_ERR
  101. "%s out of memory.\n",
  102. __func__);
  103. return -ENOMEM;
  104. }
  105. /* Copy from user with truncation. */
  106. if ( copy_from_user(req, buff, min((size_t)256, len)) ) {
  107. printk(KERN_ERR
  108. "%s copy_from_user failed.\n",
  109. __func__);
  110. retval = -EFAULT;
  111. goto out;
  112. }
  113. /* Terminate the request string if it has been truncated. */
  114. if (len > 255)
  115. req[255] = '\0';
  116. printk(KERN_DEBUG "%s TIMA uevent request (%s).\n", __func__, req);
  117. out:
  118. kfree(req);
  119. return retval;
  120. }
  121. static struct file_operations tima_uevent_fops = {
  122. .owner = THIS_MODULE,
  123. .read = tima_uevent_read,
  124. .write = tima_uevent_write,
  125. .release = tima_uevent_release
  126. };
  127. struct miscdevice tima_uevent_mdev = {
  128. .minor = MISC_DYNAMIC_MINOR,
  129. .name = TIMA_UEVENT_DEV,
  130. .fops = &tima_uevent_fops,
  131. };
  132. static int __init tima_uevent_init(void)
  133. {
  134. int retval = 0;
  135. retval = misc_register(&tima_uevent_mdev);
  136. if (retval)
  137. goto out;
  138. printk(KERN_ALERT "%s\n", __func__);
  139. tima_uevent_class = class_create(THIS_MODULE, "tima");
  140. if (IS_ERR(tima_uevent_class)) {
  141. retval = PTR_ERR(tima_uevent_class);
  142. goto error;
  143. }
  144. tima_uevent_dev = device_create(tima_uevent_class,
  145. NULL /* parent */, 0 /* dev_t */, NULL /* drvdata */,
  146. TIMA_UEVENT_DEV);
  147. if (IS_ERR(tima_uevent_dev)) {
  148. retval = PTR_ERR(tima_uevent_dev);
  149. goto error_destroy;
  150. }
  151. /* register this tima device with the driver core */
  152. retval = device_create_file(tima_uevent_dev, &dev_attr_name);
  153. if (retval)
  154. goto error_destroy;
  155. printk(KERN_DEBUG "TIMA uevent driver (%s) is initialized.\n", TIMA_UEVENT_DEV);
  156. return 0;
  157. error_destroy:
  158. kfree(tima_uevent_dev);
  159. device_destroy(tima_uevent_class, 0);
  160. error:
  161. misc_deregister(&tima_uevent_mdev);
  162. out:
  163. printk(KERN_ERR "%s: TIMA uevent driver initialization failed\n", __FILE__);
  164. return retval;
  165. }
  166. static void __exit tima_uevent_exit (void)
  167. {
  168. class_destroy(tima_uevent_class);
  169. printk(KERN_ALERT "%s\n", __func__);
  170. }
  171. MODULE_AUTHOR("Ken Chen, geng.c@sta.samsung.com");
  172. MODULE_DESCRIPTION("TIMA uevent driver");
  173. MODULE_VERSION("0.1");
  174. module_init(tima_uevent_init);
  175. module_exit(tima_uevent_exit);
  176. /* char *envp[2]; */
  177. /* env[0] = data */
  178. /* env[1] = NULL */
  179. /* kobject_uevent_env(&tima_uevent_dev->kobj, KOBJ_CHANGE, envp); */