usb_osal_nuttx.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. /*
  2. * Copyright (c) 2024, sakumisu
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "usb_osal.h"
  7. #include "usb_errno.h"
  8. #include <nuttx/config.h>
  9. #include <stddef.h>
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include <assert.h>
  14. #include <debug.h>
  15. #include <pthread.h>
  16. #include <fcntl.h>
  17. #include <unistd.h>
  18. #include <sys/time.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #include <nuttx/kmalloc.h>
  22. #include <nuttx/mqueue.h>
  23. #include <nuttx/spinlock.h>
  24. #include <nuttx/irq.h>
  25. #include <nuttx/kthread.h>
  26. #include <nuttx/wdog.h>
  27. #include <nuttx/wqueue.h>
  28. #include <nuttx/semaphore.h>
  29. #include <nuttx/sched.h>
  30. #include <nuttx/signal.h>
  31. struct mq_adpt {
  32. struct file mq; /* Message queue handle */
  33. uint32_t msgsize; /* Message size */
  34. char name[16]; /* Message queue name */
  35. };
  36. struct timer_adpt {
  37. struct usb_osal_timer timer;
  38. struct wdog_s wdog;
  39. };
  40. usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args)
  41. {
  42. int pid;
  43. char *argv[2];
  44. char arg1[32];
  45. snprintf(arg1, 16, "%p", args);
  46. argv[0] = arg1;
  47. argv[1] = NULL;
  48. pid = kthread_create(name, CONFIG_SCHED_HPWORKPRIORITY - prio, stack_size, (void *)entry,
  49. argv);
  50. if (pid > 0) {
  51. return (usb_osal_thread_t)pid;
  52. } else {
  53. return NULL;
  54. }
  55. }
  56. void usb_osal_thread_delete(usb_osal_thread_t thread)
  57. {
  58. pid_t pid = (pid_t)((uintptr_t)thread);
  59. kthread_delete(pid);
  60. }
  61. usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count)
  62. {
  63. int ret;
  64. sem_t *sem;
  65. int tmp;
  66. tmp = sizeof(sem_t);
  67. sem = kmm_malloc(tmp);
  68. if (!sem) {
  69. //printf("ERROR: Failed to alloc %d memory\n", tmp);
  70. return NULL;
  71. }
  72. ret = nxsem_init(sem, 0, initial_count);
  73. if (ret) {
  74. //printf("ERROR: Failed to initialize sem error=%d\n", ret);
  75. kmm_free(sem);
  76. return NULL;
  77. }
  78. return (usb_osal_sem_t)sem;
  79. }
  80. void usb_osal_sem_delete(usb_osal_sem_t sem)
  81. {
  82. sem_t *__sem = (sem_t *)sem;
  83. nxsem_destroy(__sem);
  84. kmm_free(__sem);
  85. }
  86. int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout)
  87. {
  88. int ret;
  89. sem_t *__sem = (sem_t *)sem;
  90. if (timeout == 0xffffffff) {
  91. ret = nxsem_wait(__sem);
  92. } else {
  93. ret = nxsem_tickwait(__sem, MSEC2TICK(timeout));
  94. }
  95. if (ret) {
  96. return -USB_ERR_TIMEOUT;
  97. } else {
  98. return 0;
  99. }
  100. }
  101. int usb_osal_sem_give(usb_osal_sem_t sem)
  102. {
  103. int ret;
  104. sem_t *__sem = (sem_t *)sem;
  105. ret = nxsem_post(__sem);
  106. if (ret) {
  107. return -USB_ERR_INVAL;
  108. } else {
  109. return 0;
  110. }
  111. }
  112. void usb_osal_sem_reset(usb_osal_sem_t sem)
  113. {
  114. nxsem_reset((sem_t *)sem, 0);
  115. }
  116. usb_osal_mutex_t usb_osal_mutex_create(void)
  117. {
  118. int ret;
  119. mutex_t *mutex;
  120. int tmp;
  121. tmp = sizeof(mutex_t);
  122. mutex = kmm_malloc(tmp);
  123. if (!mutex) {
  124. //printf("ERROR: Failed to alloc %d memory\n", tmp);
  125. return NULL;
  126. }
  127. ret = nxmutex_init(mutex);
  128. if (ret) {
  129. //printf("ERROR: Failed to initialize mutex error=%d\n", ret);
  130. kmm_free(mutex);
  131. return NULL;
  132. }
  133. return (usb_osal_mutex_t)mutex;
  134. }
  135. void usb_osal_mutex_delete(usb_osal_mutex_t mutex)
  136. {
  137. mutex_t *__mutex = (mutex_t *)mutex;
  138. nxmutex_destroy(__mutex);
  139. kmm_free(__mutex);
  140. }
  141. int usb_osal_mutex_take(usb_osal_mutex_t mutex)
  142. {
  143. int ret;
  144. mutex_t *__mutex = (mutex_t *)mutex;
  145. ret = nxmutex_lock(__mutex);
  146. if (ret) {
  147. return -USB_ERR_INVAL;
  148. } else {
  149. return 0;
  150. }
  151. }
  152. int usb_osal_mutex_give(usb_osal_mutex_t mutex)
  153. {
  154. int ret;
  155. mutex_t *__mutex = (mutex_t *)mutex;
  156. ret = nxmutex_unlock(__mutex);
  157. if (ret) {
  158. return -USB_ERR_INVAL;
  159. } else {
  160. return 0;
  161. }
  162. }
  163. usb_osal_mq_t usb_osal_mq_create(uint32_t max_msgs)
  164. {
  165. struct mq_attr attr;
  166. struct mq_adpt *mq_adpt;
  167. int ret;
  168. mq_adpt = (struct mq_adpt *)kmm_malloc(sizeof(struct mq_adpt));
  169. if (!mq_adpt) {
  170. //printf("ERROR: Failed to kmm_malloc\n");
  171. return NULL;
  172. }
  173. snprintf(mq_adpt->name, sizeof(mq_adpt->name),
  174. "/tmp/%p", mq_adpt);
  175. attr.mq_maxmsg = max_msgs;
  176. attr.mq_msgsize = sizeof(uintptr_t);
  177. attr.mq_curmsgs = 0;
  178. attr.mq_flags = 0;
  179. ret = file_mq_open(&mq_adpt->mq, mq_adpt->name,
  180. O_RDWR | O_CREAT, 0644, &attr);
  181. if (ret < 0) {
  182. //printf("ERROR: Failed to create mqueue\n");
  183. kmm_free(mq_adpt);
  184. return NULL;
  185. }
  186. mq_adpt->msgsize = sizeof(uintptr_t);
  187. return (usb_osal_mq_t)mq_adpt;
  188. }
  189. void usb_osal_mq_delete(usb_osal_mq_t mq)
  190. {
  191. struct mq_adpt *mq_adpt = (struct mq_adpt *)mq;
  192. file_mq_close(&mq_adpt->mq);
  193. file_mq_unlink(mq_adpt->name);
  194. kmm_free(mq_adpt);
  195. }
  196. int usb_osal_mq_send(usb_osal_mq_t mq, uintptr_t addr)
  197. {
  198. struct mq_adpt *mq_adpt = (struct mq_adpt *)mq;
  199. int ret;
  200. /* send mq from isr, do not use timeout*/
  201. ret = file_mq_send(&mq_adpt->mq, (const char *)&addr, mq_adpt->msgsize, 0);
  202. if (ret < 0) {
  203. return -USB_ERR_INVAL;
  204. } else {
  205. return 0;
  206. }
  207. }
  208. static void msec2spec(struct timespec *timespec, uint32_t ticks)
  209. {
  210. uint32_t tmp;
  211. tmp = TICK2SEC(ticks);
  212. timespec->tv_sec += tmp;
  213. ticks -= SEC2TICK(tmp);
  214. tmp = TICK2NSEC(ticks);
  215. timespec->tv_nsec += tmp;
  216. }
  217. int usb_osal_mq_recv(usb_osal_mq_t mq, uintptr_t *addr, uint32_t timeout)
  218. {
  219. struct mq_adpt *mq_adpt = (struct mq_adpt *)mq;
  220. struct timespec __timeout;
  221. int ret;
  222. if (timeout == 0xffffffff)
  223. return file_mq_receive(&mq_adpt->mq, (char *)addr, mq_adpt->msgsize, 0);
  224. else {
  225. ret = clock_gettime(CLOCK_REALTIME, &__timeout);
  226. if (ret < 0) {
  227. //printf("ERROR: Failed to get time\n");
  228. return -USB_ERR_INVAL;
  229. }
  230. if (timeout) {
  231. msec2spec(&__timeout, timeout);
  232. }
  233. return file_mq_timedreceive(&mq_adpt->mq,
  234. (char *)addr,
  235. mq_adpt->msgsize,
  236. 0,
  237. &__timeout);
  238. }
  239. }
  240. static void os_timer_callback(wdparm_t arg)
  241. {
  242. struct timer_adpt *timer;
  243. timer = (struct timer_adpt *)arg;
  244. if (timer->timer.handler) {
  245. timer->timer.handler(timer->timer.argument);
  246. }
  247. if (timer->timer.is_period) {
  248. wd_start(&timer->wdog, timer->timer.ticks, os_timer_callback, arg);
  249. }
  250. }
  251. struct usb_osal_timer *usb_osal_timer_create(const char *name, uint32_t timeout_ms, usb_timer_handler_t handler, void *argument, bool is_period)
  252. {
  253. struct timer_adpt *timer = kmm_malloc(sizeof(struct timer_adpt));
  254. (void)name;
  255. if (!timer) {
  256. return NULL;
  257. }
  258. memset((void *)timer, 0, sizeof(struct timer_adpt));
  259. timer->timer.handler = handler;
  260. timer->timer.argument = argument;
  261. timer->timer.ticks = MSEC2TICK(timeout_ms);
  262. timer->timer.is_period = is_period;
  263. return (struct usb_osal_timer *)timer;
  264. }
  265. void usb_osal_timer_delete(struct usb_osal_timer *timer)
  266. {
  267. struct timer_adpt *__timer = (struct timer_adpt *)timer;
  268. wd_cancel(&__timer->wdog);
  269. kmm_free(__timer);
  270. }
  271. void usb_osal_timer_start(struct usb_osal_timer *timer)
  272. {
  273. struct timer_adpt *__timer = (struct timer_adpt *)timer;
  274. wd_start(&__timer->wdog, __timer->timer.ticks, os_timer_callback, (wdparm_t)__timer);
  275. }
  276. void usb_osal_timer_stop(struct usb_osal_timer *timer)
  277. {
  278. struct timer_adpt *__timer = (struct timer_adpt *)timer;
  279. wd_cancel(&__timer->wdog);
  280. }
  281. size_t usb_osal_enter_critical_section(void)
  282. {
  283. irqstate_t flags;
  284. flags = enter_critical_section();
  285. return (size_t)flags;
  286. }
  287. void usb_osal_leave_critical_section(size_t flag)
  288. {
  289. leave_critical_section(flag);
  290. }
  291. void usb_osal_msleep(uint32_t delay)
  292. {
  293. useconds_t usec = delay * 1000;
  294. nxsig_usleep(usec);
  295. }
  296. void *usb_osal_malloc(size_t size)
  297. {
  298. return kmm_malloc(size);
  299. }
  300. void usb_osal_free(void *ptr)
  301. {
  302. kmm_free(ptr);
  303. }