usbh_dfs.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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 RT_USING_DFS_ELMFAT
  12. #error "RT_USING_DFS_ELMFAT must be enabled to use USB mass storage device"
  13. #endif
  14. #ifndef CONFIG_USB_DFS_MOUNT_POINT
  15. #define CONFIG_USB_DFS_MOUNT_POINT "/"
  16. #endif
  17. static rt_err_t rt_udisk_init(rt_device_t dev)
  18. {
  19. struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data;
  20. if (usbh_msc_scsi_init(msc_class) < 0) {
  21. return -RT_ERROR;
  22. }
  23. return RT_EOK;
  24. }
  25. static ssize_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void *buffer,
  26. rt_size_t size)
  27. {
  28. struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data;
  29. int ret;
  30. rt_uint8_t *align_buf;
  31. align_buf = (rt_uint8_t *)buffer;
  32. #ifdef CONFIG_USB_DCACHE_ENABLE
  33. if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
  34. align_buf = rt_malloc_align(size * msc_class->blocksize, CONFIG_USB_ALIGN_SIZE);
  35. if (!align_buf) {
  36. rt_kprintf("msc get align buf failed\n");
  37. return 0;
  38. }
  39. } else {
  40. }
  41. #endif
  42. ret = usbh_msc_scsi_read10(msc_class, pos, (uint8_t *)align_buf, size);
  43. if (ret < 0) {
  44. rt_kprintf("usb mass_storage read failed\n");
  45. return 0;
  46. }
  47. #ifdef CONFIG_USB_DCACHE_ENABLE
  48. if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
  49. usb_memcpy(buffer, align_buf, size * msc_class->blocksize);
  50. rt_free_align(align_buf);
  51. }
  52. #endif
  53. return size;
  54. }
  55. static ssize_t rt_udisk_write(rt_device_t dev, rt_off_t pos, const void *buffer,
  56. rt_size_t size)
  57. {
  58. struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data;
  59. int ret;
  60. rt_uint8_t *align_buf;
  61. align_buf = (rt_uint8_t *)buffer;
  62. #ifdef CONFIG_USB_DCACHE_ENABLE
  63. if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
  64. align_buf = rt_malloc_align(size * msc_class->blocksize, CONFIG_USB_ALIGN_SIZE);
  65. if (!align_buf) {
  66. rt_kprintf("msc get align buf failed\n");
  67. return 0;
  68. }
  69. usb_memcpy(align_buf, buffer, size * msc_class->blocksize);
  70. }
  71. #endif
  72. ret = usbh_msc_scsi_write10(msc_class, pos, (uint8_t *)align_buf, size);
  73. if (ret < 0) {
  74. rt_kprintf("usb mass_storage write failed\n");
  75. return 0;
  76. }
  77. #ifdef CONFIG_USB_DCACHE_ENABLE
  78. if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
  79. rt_free_align(align_buf);
  80. }
  81. #endif
  82. return size;
  83. }
  84. static rt_err_t rt_udisk_control(rt_device_t dev, int cmd, void *args)
  85. {
  86. /* check parameter */
  87. RT_ASSERT(dev != RT_NULL);
  88. struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data;
  89. if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME) {
  90. struct rt_device_blk_geometry *geometry;
  91. geometry = (struct rt_device_blk_geometry *)args;
  92. if (geometry == RT_NULL)
  93. return -RT_ERROR;
  94. geometry->bytes_per_sector = msc_class->blocksize;
  95. geometry->block_size = msc_class->blocksize;
  96. geometry->sector_count = msc_class->blocknum;
  97. }
  98. return RT_EOK;
  99. }
  100. #ifdef RT_USING_DEVICE_OPS
  101. const static struct rt_device_ops udisk_device_ops = {
  102. rt_udisk_init,
  103. RT_NULL,
  104. RT_NULL,
  105. rt_udisk_read,
  106. rt_udisk_write,
  107. rt_udisk_control
  108. };
  109. #endif
  110. static void usbh_msc_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
  111. {
  112. struct usbh_msc *msc_class = (struct usbh_msc *)CONFIG_USB_OSAL_THREAD_GET_ARGV;
  113. char name[CONFIG_USBHOST_DEV_NAMELEN];
  114. char mount_point[CONFIG_USBHOST_DEV_NAMELEN];
  115. int ret;
  116. snprintf(name, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
  117. snprintf(mount_point, CONFIG_USBHOST_DEV_NAMELEN, CONFIG_USB_DFS_MOUNT_POINT, msc_class->sdchar);
  118. ret = dfs_mount(name, mount_point, "elm", 0, 0);
  119. if (ret == 0) {
  120. rt_kprintf("udisk: %s mount successfully\n", name);
  121. } else {
  122. rt_kprintf("udisk: %s mount failed, ret = %d\n", name, ret);
  123. }
  124. usb_osal_thread_delete(NULL);
  125. }
  126. void usbh_msc_run(struct usbh_msc *msc_class)
  127. {
  128. struct rt_device *dev;
  129. char name[CONFIG_USBHOST_DEV_NAMELEN];
  130. dev = rt_malloc(sizeof(struct rt_device));
  131. memset(dev, 0, sizeof(struct rt_device));
  132. snprintf(name, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
  133. dev->type = RT_Device_Class_Block;
  134. #ifdef RT_USING_DEVICE_OPS
  135. dev->ops = &udisk_device_ops;
  136. #else
  137. dev->init = rt_udisk_init;
  138. dev->read = rt_udisk_read;
  139. dev->write = rt_udisk_write;
  140. dev->control = rt_udisk_control;
  141. #endif
  142. dev->user_data = msc_class;
  143. rt_device_register(dev, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
  144. usb_osal_thread_create("usbh_msc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_msc_thread, msc_class);
  145. }
  146. void usbh_msc_stop(struct usbh_msc *msc_class)
  147. {
  148. struct rt_device *dev;
  149. char name[CONFIG_USBHOST_DEV_NAMELEN];
  150. char mount_point[CONFIG_USBHOST_DEV_NAMELEN];
  151. snprintf(name, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
  152. snprintf(mount_point, CONFIG_USBHOST_DEV_NAMELEN, CONFIG_USB_DFS_MOUNT_POINT, msc_class->sdchar);
  153. dfs_unmount(mount_point);
  154. dev = rt_device_find(name);
  155. if (dev) {
  156. rt_device_unregister(dev);
  157. rt_free(dev);
  158. }
  159. }