usbh_dfs.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. * Copyright (c) 2024, sakumisu
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "usbh_core.h"
  7. #include "usbh_msc.h"
  8. #include "rtthread.h"
  9. #include <dfs_fs.h>
  10. #define DEV_FORMAT "/dev/sd%c"
  11. #ifndef CONFIG_USB_DFS_MOUNT_POINT
  12. #define CONFIG_USB_DFS_MOUNT_POINT "/"
  13. #endif
  14. #if defined(SOC_SERIES_STM32H7) || defined(SOC_SERIES_STM32F7) || \
  15. defined(SOC_HPM5000) || defined(SOC_HPM6000) || defined(SOC_HPM6E00) || defined(BSP_USING_BL61X)
  16. #ifndef RT_USING_CACHE
  17. #error usbh msc must enable RT_USING_CACHE in this chip
  18. #endif
  19. #if RT_ALIGN_SIZE != 32 && RT_ALIGN_SIZE != 64
  20. #error usbh msc must set cache line to 32 or 64
  21. #endif
  22. #endif
  23. #if defined(BSP_USING_BL61X)
  24. #include "bflb_l1c.h"
  25. void rt_hw_cpu_dcache_ops(int ops, void *addr, int size)
  26. {
  27. if (ops == RT_HW_CACHE_FLUSH) {
  28. bflb_l1c_dcache_clean_range(addr, size);
  29. } else {
  30. bflb_l1c_dcache_invalidate_range(addr, size);
  31. }
  32. }
  33. #endif
  34. USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t msc_sector[512];
  35. static rt_err_t rt_udisk_init(rt_device_t dev)
  36. {
  37. struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data;
  38. if (usbh_msc_scsi_init(msc_class) < 0) {
  39. return -RT_ERROR;
  40. }
  41. return RT_EOK;
  42. }
  43. static ssize_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void *buffer,
  44. rt_size_t size)
  45. {
  46. struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data;
  47. int ret;
  48. #ifdef RT_USING_CACHE
  49. rt_uint32_t *align_buf;
  50. if ((uint32_t)buffer & (RT_ALIGN_SIZE - 1)) {
  51. align_buf = rt_malloc_align(size * msc_class->blocksize, RT_ALIGN_SIZE);
  52. if (!align_buf) {
  53. rt_kprintf("msc get align buf failed\n");
  54. return 0;
  55. }
  56. } else {
  57. align_buf = (rt_uint32_t *)buffer;
  58. }
  59. ret = usbh_msc_scsi_read10(msc_class, pos, (uint8_t *)align_buf, size);
  60. if (ret < 0) {
  61. rt_kprintf("usb mass_storage read failed\n");
  62. return 0;
  63. }
  64. rt_hw_cpu_dcache_ops(RT_HW_CACHE_INVALIDATE, align_buf, size * msc_class->blocksize);
  65. if ((uint32_t)buffer & (RT_ALIGN_SIZE - 1)) {
  66. rt_memcpy(buffer, align_buf, size * msc_class->blocksize);
  67. rt_free_align(align_buf);
  68. }
  69. #else
  70. ret = usbh_msc_scsi_read10(msc_class, pos, buffer, size);
  71. if (ret < 0) {
  72. rt_kprintf("usb mass_storage read failed\n");
  73. return 0;
  74. }
  75. #endif
  76. return size;
  77. }
  78. static ssize_t rt_udisk_write(rt_device_t dev, rt_off_t pos, const void *buffer,
  79. rt_size_t size)
  80. {
  81. struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data;
  82. int ret;
  83. #ifdef RT_USING_CACHE
  84. rt_uint32_t *align_buf;
  85. if ((uint32_t)buffer & (RT_ALIGN_SIZE - 1)) {
  86. align_buf = rt_malloc_align(size * msc_class->blocksize, RT_ALIGN_SIZE);
  87. if (!align_buf) {
  88. rt_kprintf("msc get align buf failed\n");
  89. return 0;
  90. }
  91. rt_memcpy(align_buf, buffer, size * msc_class->blocksize);
  92. } else {
  93. align_buf = (rt_uint32_t *)buffer;
  94. }
  95. rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, align_buf, size * msc_class->blocksize);
  96. ret = usbh_msc_scsi_write10(msc_class, pos, (uint8_t *)align_buf, size);
  97. if (ret < 0) {
  98. rt_kprintf("usb mass_storage write failed\n");
  99. return 0;
  100. }
  101. if ((uint32_t)buffer & (RT_ALIGN_SIZE - 1)) {
  102. rt_free_align(align_buf);
  103. }
  104. #else
  105. ret = usbh_msc_scsi_write10(msc_class, pos, buffer, size);
  106. if (ret < 0) {
  107. rt_kprintf("usb mass_storage write failed\n");
  108. return 0;
  109. }
  110. #endif
  111. return size;
  112. }
  113. static rt_err_t rt_udisk_control(rt_device_t dev, int cmd, void *args)
  114. {
  115. /* check parameter */
  116. RT_ASSERT(dev != RT_NULL);
  117. struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data;
  118. if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME) {
  119. struct rt_device_blk_geometry *geometry;
  120. geometry = (struct rt_device_blk_geometry *)args;
  121. if (geometry == RT_NULL)
  122. return -RT_ERROR;
  123. geometry->bytes_per_sector = msc_class->blocksize;
  124. geometry->block_size = msc_class->blocksize;
  125. geometry->sector_count = msc_class->blocknum;
  126. }
  127. return RT_EOK;
  128. }
  129. #ifdef RT_USING_DEVICE_OPS
  130. const static struct rt_device_ops udisk_device_ops = {
  131. rt_udisk_init,
  132. RT_NULL,
  133. RT_NULL,
  134. rt_udisk_read,
  135. rt_udisk_write,
  136. rt_udisk_control
  137. };
  138. #endif
  139. static void usbh_msc_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
  140. {
  141. struct usbh_msc *msc_class = (struct usbh_msc *)CONFIG_USB_OSAL_THREAD_GET_ARGV;
  142. char name[CONFIG_USBHOST_DEV_NAMELEN];
  143. char mount_point[CONFIG_USBHOST_DEV_NAMELEN];
  144. int ret;
  145. snprintf(name, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
  146. snprintf(mount_point, CONFIG_USBHOST_DEV_NAMELEN, CONFIG_USB_DFS_MOUNT_POINT, msc_class->sdchar);
  147. ret = dfs_mount(name, mount_point, "elm", 0, 0);
  148. if (ret == 0) {
  149. rt_kprintf("udisk: %s mount successfully\n", name);
  150. } else {
  151. rt_kprintf("udisk: %s mount failed, ret = %d\n", name, ret);
  152. }
  153. usb_osal_thread_delete(NULL);
  154. }
  155. void usbh_msc_run(struct usbh_msc *msc_class)
  156. {
  157. struct rt_device *dev;
  158. char name[CONFIG_USBHOST_DEV_NAMELEN];
  159. dev = rt_malloc(sizeof(struct rt_device));
  160. memset(dev, 0, sizeof(struct rt_device));
  161. snprintf(name, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
  162. dev->type = RT_Device_Class_Block;
  163. #ifdef RT_USING_DEVICE_OPS
  164. dev->ops = &udisk_device_ops;
  165. #else
  166. dev->init = rt_udisk_init;
  167. dev->read = rt_udisk_read;
  168. dev->write = rt_udisk_write;
  169. dev->control = rt_udisk_control;
  170. #endif
  171. dev->user_data = msc_class;
  172. rt_device_register(dev, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
  173. usb_osal_thread_create("usbh_msc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_msc_thread, msc_class);
  174. }
  175. void usbh_msc_stop(struct usbh_msc *msc_class)
  176. {
  177. struct rt_device *dev;
  178. char name[CONFIG_USBHOST_DEV_NAMELEN];
  179. char mount_point[CONFIG_USBHOST_DEV_NAMELEN];
  180. snprintf(name, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
  181. snprintf(mount_point, CONFIG_USBHOST_DEV_NAMELEN, CONFIG_USB_DFS_MOUNT_POINT, msc_class->sdchar);
  182. dfs_unmount(mount_point);
  183. dev = rt_device_find(name);
  184. if (dev) {
  185. rt_device_unregister(dev);
  186. rt_free(dev);
  187. }
  188. }