usbh_fs.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * Copyright (c) 2024, sakumisu
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <nuttx/fs/fs.h>
  7. #include "usbh_core.h"
  8. #include "usbh_msc.h"
  9. #ifndef CONFIG_FS_FAT
  10. #error "CONFIG_FS_FAT must be enabled"
  11. #endif
  12. #ifdef CONFIG_ARCH_DCACHE
  13. #ifndef CONFIG_FAT_DMAMEMORY
  14. #error "USBH MSC requires CONFIG_FAT_DMAMEMORY"
  15. #endif
  16. #endif
  17. #define DEV_FORMAT "/dev/sd%c"
  18. static int nuttx_errorcode(int error)
  19. {
  20. int err = 0;
  21. switch (error) {
  22. case -USB_ERR_NOMEM:
  23. err = -EIO;
  24. break;
  25. case -USB_ERR_INVAL:
  26. err = -EINVAL;
  27. break;
  28. case -USB_ERR_NODEV:
  29. err = -ENODEV;
  30. break;
  31. case -USB_ERR_NOTCONN:
  32. err = -ENOTCONN;
  33. break;
  34. case -USB_ERR_NOTSUPP:
  35. err = -EIO;
  36. break;
  37. case -USB_ERR_BUSY:
  38. err = -EBUSY;
  39. break;
  40. case -USB_ERR_RANGE:
  41. err = -ERANGE;
  42. break;
  43. case -USB_ERR_STALL:
  44. err = -EPERM;
  45. break;
  46. case -USB_ERR_NAK:
  47. err = -EAGAIN;
  48. break;
  49. case -USB_ERR_DT:
  50. err = -EIO;
  51. break;
  52. case -USB_ERR_IO:
  53. err = -EIO;
  54. break;
  55. case -USB_ERR_SHUTDOWN:
  56. err = -ESHUTDOWN;
  57. break;
  58. case -USB_ERR_TIMEOUT:
  59. err = -ETIMEDOUT;
  60. break;
  61. default:
  62. break;
  63. }
  64. return err;
  65. }
  66. static int usbhost_open(FAR struct inode *inode);
  67. static int usbhost_close(FAR struct inode *inode);
  68. static ssize_t usbhost_read(FAR struct inode *inode, unsigned char *buffer,
  69. blkcnt_t startsector, unsigned int nsectors);
  70. static ssize_t usbhost_write(FAR struct inode *inode,
  71. FAR const unsigned char *buffer,
  72. blkcnt_t startsector, unsigned int nsectors);
  73. static int usbhost_geometry(FAR struct inode *inode,
  74. FAR struct geometry *geometry);
  75. static int usbhost_ioctl(FAR struct inode *inode, int cmd, unsigned long arg);
  76. /* Block driver operations. This is the interface exposed to NuttX by the
  77. * class that permits it to behave like a block driver.
  78. */
  79. static const struct block_operations g_bops = {
  80. usbhost_open, /* open */
  81. usbhost_close, /* close */
  82. usbhost_read, /* read */
  83. usbhost_write, /* write */
  84. usbhost_geometry, /* geometry */
  85. usbhost_ioctl /* ioctl */
  86. };
  87. static int usbhost_open(FAR struct inode *inode)
  88. {
  89. struct usbh_msc *msc_class;
  90. DEBUGASSERT(inode->i_private);
  91. msc_class = (struct usbh_msc *)inode->i_private;
  92. if (usbh_msc_scsi_init(msc_class) < 0) {
  93. return -ENODEV;
  94. }
  95. return OK;
  96. }
  97. static int usbhost_close(FAR struct inode *inode)
  98. {
  99. DEBUGASSERT(inode->i_private);
  100. return 0;
  101. }
  102. static ssize_t usbhost_read(FAR struct inode *inode, unsigned char *buffer,
  103. blkcnt_t startsector, unsigned int nsectors)
  104. {
  105. struct usbh_msc *msc_class;
  106. int ret;
  107. DEBUGASSERT(inode->i_private);
  108. msc_class = (struct usbh_msc *)inode->i_private;
  109. ret = usbh_msc_scsi_read10(msc_class, startsector, (uint8_t *)buffer, nsectors);
  110. if (ret < 0) {
  111. return nuttx_errorcode(ret);
  112. } else {
  113. #if defined(CONFIG_ARCH_DCACHE) && !defined(CONFIG_USB_DCACHE_ENABLE)
  114. up_invalidate_dcache((uintptr_t)buffer, (uintptr_t)(buffer + nsectors * msc_class->blocksize));
  115. #endif
  116. return nsectors;
  117. }
  118. }
  119. static ssize_t usbhost_write(FAR struct inode *inode,
  120. FAR const unsigned char *buffer,
  121. blkcnt_t startsector, unsigned int nsectors)
  122. {
  123. struct usbh_msc *msc_class;
  124. int ret;
  125. DEBUGASSERT(inode->i_private);
  126. msc_class = (struct usbh_msc *)inode->i_private;
  127. #if defined(CONFIG_ARCH_DCACHE) && !defined(CONFIG_USB_DCACHE_ENABLE)
  128. up_clean_dcache((uintptr_t)buffer, (uintptr_t)(buffer + nsectors * msc_class->blocksize));
  129. #endif
  130. ret = usbh_msc_scsi_write10(msc_class, startsector, (uint8_t *)buffer, nsectors);
  131. if (ret < 0) {
  132. return nuttx_errorcode(ret);
  133. } else {
  134. return nsectors;
  135. }
  136. }
  137. static int usbhost_geometry(FAR struct inode *inode,
  138. FAR struct geometry *geometry)
  139. {
  140. struct usbh_msc *msc_class;
  141. DEBUGASSERT(inode->i_private);
  142. msc_class = (struct usbh_msc *)inode->i_private;
  143. if (msc_class->hport && msc_class->hport->connected) {
  144. memset(geometry, 0, sizeof(*geometry));
  145. geometry->geo_available = true;
  146. geometry->geo_mediachanged = false;
  147. geometry->geo_writeenabled = true;
  148. geometry->geo_nsectors = msc_class->blocknum;
  149. geometry->geo_sectorsize = msc_class->blocksize;
  150. USB_LOG_DBG("nsectors: %ld, sectorsize: %ld\n",
  151. geometry->geo_nsectors, geometry->geo_sectorsize);
  152. return OK;
  153. } else {
  154. return -ENODEV;
  155. }
  156. return 0;
  157. }
  158. static int usbhost_ioctl(FAR struct inode *inode, int cmd, unsigned long arg)
  159. {
  160. struct usbh_msc *msc_class;
  161. DEBUGASSERT(inode->i_private);
  162. msc_class = (struct usbh_msc *)inode->i_private;
  163. if (msc_class->hport && msc_class->hport->connected) {
  164. return -ENOTTY;
  165. } else {
  166. return -ENODEV;
  167. }
  168. return 0;
  169. }
  170. void usbh_msc_run(struct usbh_msc *msc_class)
  171. {
  172. char devname[32];
  173. snprintf(devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
  174. register_blockdriver(devname, &g_bops, 0, msc_class);
  175. }
  176. void usbh_msc_stop(struct usbh_msc *msc_class)
  177. {
  178. char devname[32];
  179. snprintf(devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
  180. unregister_blockdriver(devname);
  181. }