usbh_dfs.c 5.1 KB

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