drvmain.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. #include <linux/version.h>
  2. #include <linux/init.h>
  3. #include <linux/kernel.h> // printk()
  4. #include <linux/module.h> // THIS_MODULE
  5. #include <linux/kobject.h> // struct kobject
  6. #include <linux/timer.h>
  7. #include <linux/errno.h> // error codes
  8. #include <linux/sysfs.h>
  9. #include <linux/syscalls.h>
  10. #include <linux/workqueue.h>
  11. #include <asm/ioctls.h>
  12. #include <linux/spi/spidev.h>
  13. #include "kfile.h"
  14. #include "kspi.h"
  15. #include "sfsattrib.h"
  16. #define _TIMER_INTERVAL (jiffies + 3 * HZ)
  17. /////////////////////////////////////////////////////////////////////////////
  18. MODULE_LICENSE("Dual BSD/GPL");
  19. MODULE_AUTHOR("GfA");
  20. /////////////////////////////////////////////////////////////////////////////
  21. #define _SPI_DEVICE "/dev/spidev1.0"
  22. static void work_queue_func(struct work_struct *work);
  23. static struct kobject *g_pKoGfa = NULL, *g_pKoTiva = NULL;
  24. /////////////////////////////////////////////////////////////////////////////
  25. // timer
  26. static struct workqueue_struct *g_pwq = NULL;
  27. static DECLARE_WORK(g_wo, work_queue_func);
  28. static volatile bool g_bTimerRunning = false;
  29. static struct timer_list g_jiq_timer;
  30. static void OnJigTimer(unsigned long ptr)
  31. {
  32. // printk(KERN_ALERT "%s, Ctx: \"%s\"-(%d)\n", __FUNCTION__, current->comm, current->pid);
  33. queue_work(g_pwq, &g_wo);
  34. }
  35. /////////////////////////////////////////////////////////////////////////////
  36. // work queue
  37. // sysfs_notify
  38. // https://stackoverflow.com/questions/16367623/using-the-linux-sysfs-notify-call
  39. //
  40. static void work_queue_func(struct work_struct *work)
  41. {
  42. TIVA_ADC tadc;
  43. struct file *pfSpiDev = NULL;
  44. uint8_t mode = SPI_MODE_3;
  45. uint8_t bits = 8;
  46. uint32_t speed = 1000000;
  47. unsigned long start = jiffies;
  48. // printk(KERN_ALERT "%s, Ctx: \"%s\"-(%d)\n", __FUNCTION__, current->comm, current->pid);
  49. // CmdGetFirmwareVersion(pfSpiDev, &g_hw, &g_sw);
  50. // sysfs_notify(g_pKoTiva, NULL, "firmware");
  51. if((pfSpiDev = kf_open(_SPI_DEVICE, O_RDWR, 0)))
  52. {
  53. if(kf_ioctl(pfSpiDev, SPI_IOC_WR_MODE, (unsigned long)&mode) < 0)
  54. {
  55. printk(KERN_ALERT "can't set spi mode\n");
  56. // break;
  57. }
  58. if(kf_ioctl(pfSpiDev, SPI_IOC_RD_MODE, (unsigned long)&mode) < 0)
  59. {
  60. printk(KERN_ALERT "can't get spi mode\n");
  61. // break;
  62. }
  63. /////////////////////////////////////////////////////////////////////
  64. if(kf_ioctl(pfSpiDev, SPI_IOC_WR_BITS_PER_WORD, (unsigned long)&bits) < 0)
  65. {
  66. printk(KERN_ALERT "can't set bits per word\n");
  67. // break;
  68. }
  69. if(kf_ioctl(pfSpiDev, SPI_IOC_RD_BITS_PER_WORD, (unsigned long)&bits) < 0)
  70. {
  71. printk(KERN_ALERT "can't get bits per word\n");
  72. // break;
  73. }
  74. /////////////////////////////////////////////////////////////////////
  75. if(kf_ioctl(pfSpiDev, SPI_IOC_WR_MAX_SPEED_HZ, (unsigned long)&speed) < 0)
  76. {
  77. printk(KERN_ALERT "can't set max speed hz\n");
  78. // break;
  79. }
  80. if(kf_ioctl(pfSpiDev, SPI_IOC_RD_MAX_SPEED_HZ, (unsigned long)&speed) < 0)
  81. {
  82. printk(KERN_ALERT "can't get max speed hz\n");
  83. // break;
  84. }
  85. if(CmdGetADC(pfSpiDev, &tadc) == 0)
  86. {
  87. if(g_tadc.UVers != tadc.UVers)
  88. {
  89. g_tadc.UVers = tadc.UVers;
  90. sysfs_notify(g_pKoTiva, NULL, "UVers");
  91. // printk(KERN_ALERT "Update UVers.\n");
  92. }
  93. if(g_tadc.UBatV3 != tadc.UBatV3)
  94. {
  95. g_tadc.UBatV3 = tadc.UBatV3;
  96. sysfs_notify(g_pKoTiva, NULL, "UBatV3");
  97. // printk(KERN_ALERT "Update UBatV3.\n");
  98. }
  99. if(g_tadc.Temp != tadc.Temp)
  100. {
  101. g_tadc.Temp = tadc.Temp;
  102. sysfs_notify(g_pKoTiva, NULL, "Temp");
  103. // printk(KERN_ALERT "Update Temp.\n");
  104. }
  105. if(g_tadc.UV5Vsys != tadc.UV5Vsys)
  106. {
  107. g_tadc.UV5Vsys = tadc.UV5Vsys;
  108. sysfs_notify(g_pKoTiva, NULL, "UV5Vsys");
  109. // printk(KERN_ALERT "Update UV5Vsys.\n");
  110. }
  111. if(g_tadc.UV3V6Bat != tadc.UV3V6Bat)
  112. {
  113. g_tadc.UV3V6Bat = tadc.UV3V6Bat;
  114. sysfs_notify(g_pKoTiva, NULL, "UV3V6Bat");
  115. // printk(KERN_ALERT "Update UV3V6Bat.\n");
  116. }
  117. if(g_tadc.TempTIVA != tadc.TempTIVA)
  118. {
  119. g_tadc.TempTIVA = tadc.TempTIVA;
  120. sysfs_notify(g_pKoTiva, NULL, "TempTIVA");
  121. // printk(KERN_ALERT "Update TempTIVA.\n");
  122. }
  123. }
  124. kf_close(pfSpiDev);
  125. }
  126. else
  127. {
  128. printk(KERN_ALERT "file_open failed\n");
  129. }
  130. if(g_bTimerRunning)
  131. {
  132. mod_timer(&g_jiq_timer, _TIMER_INTERVAL);
  133. }
  134. printk(KERN_ALERT "Worker pass jiffies: %lu\n", ((long)jiffies - (long)start));
  135. }
  136. /////////////////////////////////////////////////////////////////////////////
  137. static int drv_init(void)
  138. {
  139. /////////////////////////////////////////////////////////////////////////
  140. do
  141. {
  142. if(!(g_pKoGfa = kobject_create_and_add("gfa", NULL)))
  143. {
  144. printk(KERN_ALERT "kobject_create_and_add failed\n");
  145. break;
  146. }
  147. if(!(g_pKoTiva = kobject_create_and_add("tiva", g_pKoGfa)))
  148. {
  149. printk(KERN_ALERT "kobject_create_and_add failed\n");
  150. break;
  151. }
  152. /////////////////////////////////////////////////////////////////////
  153. if(sysfs_create_file(g_pKoTiva, &g_tivaFirmwareAtt.attr))
  154. {
  155. printk(KERN_ALERT "sysfs_create_file failed\n");
  156. break;
  157. }
  158. if(sysfs_create_file(g_pKoTiva, &g_tivaUVersAtt.attr))
  159. {
  160. printk(KERN_ALERT "sysfs_create_file failed\n");
  161. break;
  162. }
  163. if(sysfs_create_file(g_pKoTiva, &g_tivaUBatV3Att.attr))
  164. {
  165. printk(KERN_ALERT "sysfs_create_file failed\n");
  166. break;
  167. }
  168. if(sysfs_create_file(g_pKoTiva, &g_tivaTempAtt.attr))
  169. {
  170. printk(KERN_ALERT "sysfs_create_file failed\n");
  171. break;
  172. }
  173. if(sysfs_create_file(g_pKoTiva, &g_tivaUV5VsysAtt.attr))
  174. {
  175. printk(KERN_ALERT "sysfs_create_file failed\n");
  176. break;
  177. }
  178. if(sysfs_create_file(g_pKoTiva, &g_tivaUV3V6BatAtt.attr))
  179. {
  180. printk(KERN_ALERT "sysfs_create_file failed\n");
  181. break;
  182. }
  183. if(sysfs_create_file(g_pKoTiva, &g_tivaTempTIVAAtt.attr))
  184. {
  185. printk(KERN_ALERT "sysfs_create_file failed\n");
  186. break;
  187. }
  188. /////////////////////////////////////////////////////////////////////
  189. if(!(g_pwq = create_workqueue("GfaWrk")))
  190. {
  191. printk(KERN_ALERT "create_workqueue failed!\n");
  192. break;
  193. }
  194. /////////////////////////////////////////////////////////////////////
  195. init_timer(&g_jiq_timer);
  196. g_jiq_timer.function = OnJigTimer;
  197. g_jiq_timer.data = 0;
  198. g_jiq_timer.expires = _TIMER_INTERVAL;
  199. add_timer(&g_jiq_timer);
  200. g_bTimerRunning = true;
  201. /////////////////////////////////////////////////////////////////////
  202. if(!queue_work(g_pwq, &g_wo))
  203. {
  204. printk(KERN_ALERT "queue_work failed\n");
  205. break;
  206. }
  207. /////////////////////////////////////////////////////////////////////
  208. printk(KERN_ALERT "%s, Ctx: \"%s\"-(%d)\n", __FUNCTION__, current->comm, current->pid);
  209. return 0;
  210. }
  211. while(0);
  212. /////////////////////////////////////////////////////////////////////////
  213. if(g_bTimerRunning)
  214. {
  215. g_bTimerRunning = false;
  216. del_timer_sync(&g_jiq_timer);
  217. }
  218. if(g_pwq)
  219. destroy_workqueue(g_pwq);
  220. if(g_pKoTiva)
  221. {
  222. sysfs_remove_file(g_pKoTiva, &g_tivaFirmwareAtt.attr);
  223. sysfs_remove_file(g_pKoTiva, &g_tivaUVersAtt.attr);
  224. sysfs_remove_file(g_pKoTiva, &g_tivaUBatV3Att.attr);
  225. sysfs_remove_file(g_pKoTiva, &g_tivaTempAtt.attr);
  226. sysfs_remove_file(g_pKoTiva, &g_tivaUV5VsysAtt.attr);
  227. sysfs_remove_file(g_pKoTiva, &g_tivaUV3V6BatAtt.attr);
  228. sysfs_remove_file(g_pKoTiva, &g_tivaTempTIVAAtt.attr);
  229. kobject_put(g_pKoTiva);
  230. g_pKoTiva = NULL;
  231. }
  232. if(g_pKoGfa)
  233. {
  234. kobject_put(g_pKoGfa);
  235. g_pKoGfa = NULL;
  236. }
  237. return -ENOMEM;
  238. }
  239. /////////////////////////////////////////////////////////////////////////////
  240. static void drv_exit(void)
  241. {
  242. g_bTimerRunning = false;
  243. del_timer_sync(&g_jiq_timer);
  244. if(g_pwq)
  245. destroy_workqueue(g_pwq);
  246. if(g_pKoTiva)
  247. {
  248. sysfs_remove_file(g_pKoTiva, &g_tivaFirmwareAtt.attr);
  249. sysfs_remove_file(g_pKoTiva, &g_tivaUVersAtt.attr);
  250. sysfs_remove_file(g_pKoTiva, &g_tivaUBatV3Att.attr);
  251. sysfs_remove_file(g_pKoTiva, &g_tivaTempAtt.attr);
  252. sysfs_remove_file(g_pKoTiva, &g_tivaUV5VsysAtt.attr);
  253. sysfs_remove_file(g_pKoTiva, &g_tivaUV3V6BatAtt.attr);
  254. sysfs_remove_file(g_pKoTiva, &g_tivaTempTIVAAtt.attr);
  255. kobject_put(g_pKoTiva);
  256. }
  257. if(g_pKoGfa)
  258. kobject_put(g_pKoGfa);
  259. printk(KERN_ALERT "%s, Ctx: \"%s\"-(%d)\n", __FUNCTION__, current->comm, current->pid);
  260. }
  261. /////////////////////////////////////////////////////////////////////////////
  262. module_init(drv_init);
  263. module_exit(drv_exit);