usbmsc.c 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778
  1. /****************************************************************************
  2. * drivers/usbdev/usbmsc.c
  3. *
  4. * Copyright (C) 2008-2012 Gregory Nutt. All rights reserved.
  5. * Author: Gregory Nutt <gnutt@nuttx.org>
  6. *
  7. * Mass storage class device. Bulk-only with SCSI subclass.
  8. *
  9. * References:
  10. * "Universal Serial Bus Mass Storage Class, Specification Overview,"
  11. * Revision 1.2, USB Implementer's Forum, June 23, 2003.
  12. *
  13. * "Universal Serial Bus Mass Storage Class, Bulk-Only Transport,"
  14. * Revision 1.0, USB Implementer's Forum, September 31, 1999.
  15. *
  16. * "SCSI Primary Commands - 3 (SPC-3)," American National Standard
  17. * for Information Technology, May 4, 2005
  18. *
  19. * "SCSI Primary Commands - 4 (SPC-4)," American National Standard
  20. * for Information Technology, July 19, 2008
  21. *
  22. * "SCSI Block Commands -2 (SBC-2)," American National Standard
  23. * for Information Technology, November 13, 2004
  24. *
  25. * "SCSI Multimedia Commands - 3 (MMC-3)," American National Standard
  26. * for Information Technology, November 12, 2001
  27. *
  28. * Redistribution and use in source and binary forms, with or without
  29. * modification, are permitted provided that the following conditions
  30. * are met:
  31. *
  32. * 1. Redistributions of source code must retain the above copyright
  33. * notice, this list of conditions and the following disclaimer.
  34. * 2. Redistributions in binary form must reproduce the above copyright
  35. * notice, this list of conditions and the following disclaimer in
  36. * the documentation and/or other materials provided with the
  37. * distribution.
  38. * 3. Neither the name NuttX nor the names of its contributors may be
  39. * used to endorse or promote products derived from this software
  40. * without specific prior written permission.
  41. *
  42. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  43. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  44. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  45. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  46. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  47. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  48. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  49. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  50. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  51. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  52. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  53. * POSSIBILITY OF SUCH DAMAGE.
  54. *
  55. ****************************************************************************/
  56. /****************************************************************************
  57. * Included Files
  58. ****************************************************************************/
  59. #include <nuttx/config.h>
  60. #include <sys/types.h>
  61. #include <stdint.h>
  62. #include <stdbool.h>
  63. #include <stdio.h>
  64. #include <stdlib.h>
  65. #include <unistd.h>
  66. #include <pthread.h>
  67. #include <string.h>
  68. #include <errno.h>
  69. #include <queue.h>
  70. #include <debug.h>
  71. #include <nuttx/kmalloc.h>
  72. #include <nuttx/arch.h>
  73. #include <nuttx/fs/fs.h>
  74. #include <nuttx/usb/usb.h>
  75. #include <nuttx/usb/storage.h>
  76. #include <nuttx/usb/usbdev.h>
  77. #include <nuttx/usb/usbdev_trace.h>
  78. #include "usbmsc.h"
  79. #ifdef CONFIG_USBMSC_COMPOSITE
  80. # include <nuttx/usb/composite.h>
  81. # include "composite.h"
  82. #endif
  83. /****************************************************************************
  84. * Pre-processor Definitions
  85. ****************************************************************************/
  86. /****************************************************************************
  87. * Private Types
  88. ****************************************************************************/
  89. /* The internal version of the class driver */
  90. struct usbmsc_driver_s
  91. {
  92. struct usbdevclass_driver_s drvr;
  93. FAR struct usbmsc_dev_s *dev;
  94. };
  95. /* This is what is allocated */
  96. struct usbmsc_alloc_s
  97. {
  98. struct usbmsc_dev_s dev;
  99. struct usbmsc_driver_s drvr;
  100. };
  101. /****************************************************************************
  102. * Private Function Prototypes
  103. ****************************************************************************/
  104. /* Class Driver Support *****************************************************/
  105. static void usbmsc_ep0incomplete(FAR struct usbdev_ep_s *ep,
  106. FAR struct usbdev_req_s *req);
  107. static struct usbdev_req_s *usbmsc_allocreq(FAR struct usbdev_ep_s *ep,
  108. uint16_t len);
  109. static void usbmsc_freereq(FAR struct usbdev_ep_s *ep,
  110. FAR struct usbdev_req_s *req);
  111. /* Class Driver Operations (most at interrupt level) ************************/
  112. static int usbmsc_bind(FAR struct usbdevclass_driver_s *driver,
  113. FAR struct usbdev_s *dev);
  114. static void usbmsc_unbind(FAR struct usbdevclass_driver_s *driver,
  115. FAR struct usbdev_s *dev);
  116. static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
  117. FAR struct usbdev_s *dev,
  118. FAR const struct usb_ctrlreq_s *ctrl, FAR uint8_t *dataout,
  119. size_t outlen);
  120. static void usbmsc_disconnect(FAR struct usbdevclass_driver_s *driver,
  121. FAR struct usbdev_s *dev);
  122. /* Initialization/Uninitialization ******************************************/
  123. static void usbmsc_lununinitialize(struct usbmsc_lun_s *lun);
  124. #ifdef CONFIG_USBMSC_COMPOSITE
  125. static int usbmsc_exportluns(FAR void *handle);
  126. #endif
  127. /****************************************************************************
  128. * Private Data
  129. ****************************************************************************/
  130. /* Driver operations ********************************************************/
  131. static struct usbdevclass_driverops_s g_driverops =
  132. {
  133. usbmsc_bind, /* bind */
  134. usbmsc_unbind, /* unbind */
  135. usbmsc_setup, /* setup */
  136. usbmsc_disconnect, /* disconnect */
  137. NULL, /* suspend */
  138. NULL /* resume */
  139. };
  140. /****************************************************************************
  141. * Public Data
  142. ****************************************************************************/
  143. /****************************************************************************
  144. * Private Functions
  145. ****************************************************************************/
  146. /****************************************************************************
  147. * Class Driver Support
  148. ****************************************************************************/
  149. /****************************************************************************
  150. * Name: usbmsc_ep0incomplete
  151. *
  152. * Description:
  153. * Handle completion of EP0 control operations
  154. *
  155. ****************************************************************************/
  156. static void usbmsc_ep0incomplete(FAR struct usbdev_ep_s *ep,
  157. FAR struct usbdev_req_s *req)
  158. {
  159. if (req->result || req->xfrd != req->len)
  160. {
  161. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_REQRESULT),
  162. (uint16_t)-req->result);
  163. }
  164. }
  165. /****************************************************************************
  166. * Name: usbmsc_allocreq
  167. *
  168. * Description:
  169. * Allocate a request instance along with its buffer
  170. *
  171. ****************************************************************************/
  172. static struct usbdev_req_s *usbmsc_allocreq(FAR struct usbdev_ep_s *ep,
  173. uint16_t len)
  174. {
  175. FAR struct usbdev_req_s *req;
  176. req = EP_ALLOCREQ(ep);
  177. if (req != NULL)
  178. {
  179. req->len = len;
  180. req->buf = EP_ALLOCBUFFER(ep, len);
  181. if (!req->buf)
  182. {
  183. EP_FREEREQ(ep, req);
  184. req = NULL;
  185. }
  186. }
  187. return req;
  188. }
  189. /****************************************************************************
  190. * Name: usbmsc_freereq
  191. *
  192. * Description:
  193. * Free a request instance along with its buffer
  194. *
  195. ****************************************************************************/
  196. static void usbmsc_freereq(FAR struct usbdev_ep_s *ep, struct usbdev_req_s *req)
  197. {
  198. if (ep != NULL && req != NULL)
  199. {
  200. if (req->buf != NULL)
  201. {
  202. EP_FREEBUFFER(ep, req->buf);
  203. }
  204. EP_FREEREQ(ep, req);
  205. }
  206. }
  207. /****************************************************************************
  208. * Class Driver Interfaces
  209. ****************************************************************************/
  210. /****************************************************************************
  211. * Name: usbmsc_bind
  212. *
  213. * Description:
  214. * Invoked when the driver is bound to a USB device driver
  215. *
  216. ****************************************************************************/
  217. static int usbmsc_bind(FAR struct usbdevclass_driver_s *driver,
  218. FAR struct usbdev_s *dev)
  219. {
  220. FAR struct usbmsc_dev_s *priv = ((FAR struct usbmsc_driver_s*)driver)->dev;
  221. FAR struct usbmsc_req_s *reqcontainer;
  222. irqstate_t flags;
  223. int ret = OK;
  224. int i;
  225. usbtrace(TRACE_CLASSBIND, 0);
  226. /* Bind the structures */
  227. priv->usbdev = dev;
  228. /* Save the reference to our private data structure in EP0 so that it
  229. * can be recovered in ep0 completion events (Unless we are part of
  230. * a composite device and, in that case, the composite device owns
  231. * EP0).
  232. */
  233. #ifndef CONFIG_USBMSC_COMPOSITE
  234. dev->ep0->priv = priv;
  235. #endif
  236. /* The configured EP0 size should match the reported EP0 size. We could
  237. * easily adapt to the reported EP0 size, but then we could not use the
  238. * const, canned descriptors.
  239. */
  240. DEBUGASSERT(CONFIG_USBMSC_EP0MAXPACKET == dev->ep0->maxpacket);
  241. /* Preallocate control request */
  242. priv->ctrlreq = usbmsc_allocreq(dev->ep0, USBMSC_MXDESCLEN);
  243. if (priv->ctrlreq == NULL)
  244. {
  245. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_ALLOCCTRLREQ), 0);
  246. ret = -ENOMEM;
  247. goto errout;
  248. }
  249. priv->ctrlreq->callback = usbmsc_ep0incomplete;
  250. /* Pre-allocate all endpoints... the endpoints will not be functional
  251. * until the SET CONFIGURATION request is processed in usbmsc_setconfig.
  252. * This is done here because there may be calls to kmalloc and the SET
  253. * CONFIGURATION processing probably occurrs within interrupt handling
  254. * logic where kmalloc calls will fail.
  255. */
  256. /* Pre-allocate the IN bulk endpoint */
  257. priv->epbulkin = DEV_ALLOCEP(dev, USBMSC_EPINBULK_ADDR, true, USB_EP_ATTR_XFER_BULK);
  258. if (!priv->epbulkin)
  259. {
  260. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EPBULKINALLOCFAIL), 0);
  261. ret = -ENODEV;
  262. goto errout;
  263. }
  264. priv->epbulkin->priv = priv;
  265. /* Pre-allocate the OUT bulk endpoint */
  266. priv->epbulkout = DEV_ALLOCEP(dev, USBMSC_EPOUTBULK_ADDR, false, USB_EP_ATTR_XFER_BULK);
  267. if (!priv->epbulkout)
  268. {
  269. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EPBULKOUTALLOCFAIL), 0);
  270. ret = -ENODEV;
  271. goto errout;
  272. }
  273. priv->epbulkout->priv = priv;
  274. /* Pre-allocate read requests */
  275. for (i = 0; i < CONFIG_USBMSC_NRDREQS; i++)
  276. {
  277. reqcontainer = &priv->rdreqs[i];
  278. reqcontainer->req = usbmsc_allocreq(priv->epbulkout, CONFIG_USBMSC_BULKOUTREQLEN);
  279. if (reqcontainer->req == NULL)
  280. {
  281. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_RDALLOCREQ),
  282. (uint16_t)-ret);
  283. ret = -ENOMEM;
  284. goto errout;
  285. }
  286. reqcontainer->req->priv = reqcontainer;
  287. reqcontainer->req->callback = usbmsc_rdcomplete;
  288. }
  289. /* Pre-allocate write request containers and put in a free list */
  290. for (i = 0; i < CONFIG_USBMSC_NWRREQS; i++)
  291. {
  292. reqcontainer = &priv->wrreqs[i];
  293. reqcontainer->req = usbmsc_allocreq(priv->epbulkin, CONFIG_USBMSC_BULKINREQLEN);
  294. if (reqcontainer->req == NULL)
  295. {
  296. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRALLOCREQ),
  297. (uint16_t)-ret);
  298. ret = -ENOMEM;
  299. goto errout;
  300. }
  301. reqcontainer->req->priv = reqcontainer;
  302. reqcontainer->req->callback = usbmsc_wrcomplete;
  303. flags = irqsave();
  304. sq_addlast((sq_entry_t*)reqcontainer, &priv->wrreqlist);
  305. irqrestore(flags);
  306. }
  307. /* Report if we are selfpowered (unless we are part of a composite device) */
  308. #ifndef CONFIG_USBMSC_COMPOSITE
  309. #ifdef CONFIG_USBDEV_SELFPOWERED
  310. DEV_SETSELFPOWERED(dev);
  311. #endif
  312. /* And pull-up the data line for the soft connect function (unless we are
  313. * part of a composite device)
  314. */
  315. DEV_CONNECT(dev);
  316. #endif
  317. return OK;
  318. errout:
  319. usbmsc_unbind(driver, dev);
  320. return ret;
  321. }
  322. /****************************************************************************
  323. * Name: usbmsc_unbind
  324. *
  325. * Description:
  326. * Invoked when the driver is unbound from a USB device driver
  327. *
  328. ****************************************************************************/
  329. static void usbmsc_unbind(FAR struct usbdevclass_driver_s *driver,
  330. FAR struct usbdev_s *dev)
  331. {
  332. FAR struct usbmsc_dev_s *priv;
  333. FAR struct usbmsc_req_s *reqcontainer;
  334. irqstate_t flags;
  335. int i;
  336. usbtrace(TRACE_CLASSUNBIND, 0);
  337. #ifdef CONFIG_DEBUG
  338. if (!driver || !dev || !dev->ep0)
  339. {
  340. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_UNBINDINVALIDARGS), 0);
  341. return;
  342. }
  343. #endif
  344. /* Extract reference to private data */
  345. priv = ((FAR struct usbmsc_driver_s*)driver)->dev;
  346. #ifdef CONFIG_DEBUG
  347. if (!priv)
  348. {
  349. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EP0NOTBOUND1), 0);
  350. return;
  351. }
  352. #endif
  353. /* The worker thread should have already been stopped by the
  354. * driver un-initialize logic.
  355. */
  356. DEBUGASSERT(priv->thstate == USBMSC_STATE_TERMINATED);
  357. /* Make sure that we are not already unbound */
  358. if (priv != NULL)
  359. {
  360. /* Make sure that the endpoints have been unconfigured. If
  361. * we were terminated gracefully, then the configuration should
  362. * already have been reset. If not, then calling usbmsc_resetconfig
  363. * should cause the endpoints to immediately terminate all
  364. * transfers and return the requests to us (with result == -ESHUTDOWN)
  365. */
  366. usbmsc_resetconfig(priv);
  367. up_mdelay(50);
  368. /* Free the pre-allocated control request */
  369. if (priv->ctrlreq != NULL)
  370. {
  371. usbmsc_freereq(dev->ep0, priv->ctrlreq);
  372. priv->ctrlreq = NULL;
  373. }
  374. /* Free pre-allocated read requests (which should all have
  375. * been returned to the free list at this time -- we don't check)
  376. */
  377. for (i = 0; i < CONFIG_USBMSC_NRDREQS; i++)
  378. {
  379. reqcontainer = &priv->rdreqs[i];
  380. if (reqcontainer->req)
  381. {
  382. usbmsc_freereq(priv->epbulkout, reqcontainer->req);
  383. reqcontainer->req = NULL;
  384. }
  385. }
  386. /* Free the bulk OUT endpoint */
  387. if (priv->epbulkout)
  388. {
  389. DEV_FREEEP(dev, priv->epbulkout);
  390. priv->epbulkout = NULL;
  391. }
  392. /* Free write requests that are not in use (which should be all
  393. * of them
  394. */
  395. flags = irqsave();
  396. while (!sq_empty(&priv->wrreqlist))
  397. {
  398. reqcontainer = (struct usbmsc_req_s *)sq_remfirst(&priv->wrreqlist);
  399. if (reqcontainer->req != NULL)
  400. {
  401. usbmsc_freereq(priv->epbulkin, reqcontainer->req);
  402. }
  403. }
  404. /* Free the bulk IN endpoint */
  405. if (priv->epbulkin)
  406. {
  407. DEV_FREEEP(dev, priv->epbulkin);
  408. priv->epbulkin = NULL;
  409. }
  410. irqrestore(flags);
  411. }
  412. }
  413. /****************************************************************************
  414. * Name: usbmsc_setup
  415. *
  416. * Description:
  417. * Invoked for ep0 control requests. This function probably executes
  418. * in the context of an interrupt handler.
  419. *
  420. ****************************************************************************/
  421. static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
  422. FAR struct usbdev_s *dev,
  423. FAR const struct usb_ctrlreq_s *ctrl,
  424. FAR uint8_t *dataout, size_t outlen)
  425. {
  426. FAR struct usbmsc_dev_s *priv;
  427. FAR struct usbdev_req_s *ctrlreq;
  428. uint16_t value;
  429. uint16_t index;
  430. uint16_t len;
  431. int ret = -EOPNOTSUPP;
  432. #ifdef CONFIG_DEBUG
  433. if (!driver || !dev || !dev->ep0 || !ctrl)
  434. {
  435. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_SETUPINVALIDARGS), 0);
  436. return -EIO;
  437. }
  438. #endif
  439. /* Extract reference to private data */
  440. usbtrace(TRACE_CLASSSETUP, ctrl->req);
  441. priv = ((FAR struct usbmsc_driver_s *)driver)->dev;
  442. #ifdef CONFIG_DEBUG
  443. if (!priv || !priv->ctrlreq)
  444. {
  445. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EP0NOTBOUND2), 0);
  446. return -ENODEV;
  447. }
  448. #endif
  449. ctrlreq = priv->ctrlreq;
  450. /* Extract the little-endian 16-bit values to host order */
  451. value = GETUINT16(ctrl->value);
  452. index = GETUINT16(ctrl->index);
  453. len = GETUINT16(ctrl->len);
  454. uvdbg("type=%02x req=%02x value=%04x index=%04x len=%04x\n",
  455. ctrl->type, ctrl->req, value, index, len);
  456. if ((ctrl->type & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_STANDARD)
  457. {
  458. /**********************************************************************
  459. * Standard Requests
  460. **********************************************************************/
  461. switch (ctrl->req)
  462. {
  463. case USB_REQ_GETDESCRIPTOR:
  464. {
  465. /* The value field specifies the descriptor type in the MS byte and the
  466. * descriptor index in the LS byte (order is little endian)
  467. */
  468. switch (ctrl->value[1])
  469. {
  470. /* If the mass storage device is used in as part of a composite
  471. * device, then the device descriptor is is provided by logic
  472. * in the composite device implementation.
  473. */
  474. #ifndef CONFIG_USBMSC_COMPOSITE
  475. case USB_DESC_TYPE_DEVICE:
  476. {
  477. ret = USB_SIZEOF_DEVDESC;
  478. memcpy(ctrlreq->buf, usbmsc_getdevdesc(), ret);
  479. }
  480. break;
  481. #endif
  482. /* If the mass storage device is used in as part of a composite device,
  483. * then the device qualifier descriptor is provided by logic in the
  484. * composite device implementation.
  485. */
  486. #if !defined(CONFIG_USBMSC_COMPOSITE) && defined(CONFIG_USBDEV_DUALSPEED)
  487. case USB_DESC_TYPE_DEVICEQUALIFIER:
  488. {
  489. ret = USB_SIZEOF_QUALDESC;
  490. memcpy(ctrlreq->buf, usbmsc_getqualdesc(), ret);
  491. }
  492. break;
  493. case USB_DESC_TYPE_OTHERSPEEDCONFIG:
  494. #endif
  495. /* If the mass storage device is used in as part of a composite device,
  496. * then the configuration descriptor is provided by logic in the
  497. * composite device implementation.
  498. */
  499. #ifndef CONFIG_USBMSC_COMPOSITE
  500. case USB_DESC_TYPE_CONFIG:
  501. {
  502. #ifdef CONFIG_USBDEV_DUALSPEED
  503. ret = usbmsc_mkcfgdesc(ctrlreq->buf, dev->speed, ctrl->value[1]);
  504. #else
  505. ret = usbmsc_mkcfgdesc(ctrlreq->buf);
  506. #endif
  507. }
  508. break;
  509. #endif
  510. /* If the mass storage device is used in as part of a composite device,
  511. * then the language string descriptor is provided by logic in the
  512. * composite device implementation.
  513. */
  514. #ifndef CONFIG_USBMSC_COMPOSITE
  515. case USB_DESC_TYPE_STRING:
  516. {
  517. /* index == language code. */
  518. ret = usbmsc_mkstrdesc(ctrl->value[0], (struct usb_strdesc_s *)ctrlreq->buf);
  519. }
  520. break;
  521. #endif
  522. default:
  523. {
  524. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_GETUNKNOWNDESC), value);
  525. }
  526. break;
  527. }
  528. }
  529. break;
  530. case USB_REQ_SETCONFIGURATION:
  531. {
  532. if (ctrl->type == 0)
  533. {
  534. /* Signal the worker thread to instantiate the new configuration */
  535. priv->theventset |= USBMSC_EVENT_CFGCHANGE;
  536. priv->thvalue = value;
  537. pthread_cond_signal(&priv->cond);
  538. /* Return here... the response will be provided later by the
  539. * worker thread.
  540. */
  541. return OK;
  542. }
  543. }
  544. break;
  545. /* If the mass storage device is used in as part of a composite device,
  546. * then the overall composite class configuration is managed by logic
  547. * in the composite device implementation.
  548. */
  549. #ifndef CONFIG_USBMSC_COMPOSITE
  550. case USB_REQ_GETCONFIGURATION:
  551. {
  552. if (ctrl->type == USB_DIR_IN)
  553. {
  554. ctrlreq->buf[0] = priv->config;
  555. ret = 1;
  556. }
  557. }
  558. break;
  559. #endif
  560. case USB_REQ_SETINTERFACE:
  561. {
  562. if (ctrl->type == USB_REQ_RECIPIENT_INTERFACE)
  563. {
  564. if (priv->config == USBMSC_CONFIGID &&
  565. index == USBMSC_INTERFACEID &&
  566. value == USBMSC_ALTINTERFACEID)
  567. {
  568. /* Signal to instantiate the interface change */
  569. priv->theventset |= USBMSC_EVENT_IFCHANGE;
  570. pthread_cond_signal(&priv->cond);
  571. /* Return here... the response will be provided later by the
  572. * worker thread.
  573. */
  574. return OK;
  575. }
  576. }
  577. }
  578. break;
  579. case USB_REQ_GETINTERFACE:
  580. {
  581. if (ctrl->type == (USB_DIR_IN|USB_REQ_RECIPIENT_INTERFACE) &&
  582. priv->config == USBMSC_CONFIGIDNONE)
  583. {
  584. if (index != USBMSC_INTERFACEID)
  585. {
  586. ret = -EDOM;
  587. }
  588. else
  589. {
  590. ctrlreq->buf[0] = USBMSC_ALTINTERFACEID;
  591. ret = 1;
  592. }
  593. }
  594. }
  595. break;
  596. default:
  597. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_UNSUPPORTEDSTDREQ), ctrl->req);
  598. break;
  599. }
  600. }
  601. else if ((ctrl->type & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_CLASS)
  602. {
  603. /**********************************************************************
  604. * Bulk-Only Mass Storage Class Requests
  605. **********************************************************************/
  606. /* Verify that we are configured */
  607. if (!priv->config)
  608. {
  609. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_NOTCONFIGURED), 0);
  610. return ret;
  611. }
  612. switch (ctrl->req)
  613. {
  614. case USBMSC_REQ_MSRESET: /* Reset mass storage device and interface */
  615. {
  616. if (ctrl->type == USBMSC_TYPE_SETUPOUT && value == 0 && len == 0)
  617. {
  618. /* Only one interface is supported */
  619. if (index != USBMSC_INTERFACEID)
  620. {
  621. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_MSRESETNDX), index);
  622. ret = -EDOM;
  623. }
  624. else
  625. {
  626. /* Signal to stop the current operation and reinitialize state */
  627. priv->theventset |= USBMSC_EVENT_RESET;
  628. pthread_cond_signal(&priv->cond);
  629. /* Return here... the response will be provided later by the
  630. * worker thread.
  631. */
  632. return OK;
  633. }
  634. }
  635. }
  636. break;
  637. case USBMSC_REQ_GETMAXLUN: /* Return number LUNs supported */
  638. {
  639. if (ctrl->type == USBMSC_TYPE_SETUPIN && value == 0 && len == 1)
  640. {
  641. /* Only one interface is supported */
  642. if (index != USBMSC_INTERFACEID)
  643. {
  644. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_GETMAXLUNNDX), index);
  645. ret = -EDOM;
  646. }
  647. else
  648. {
  649. ctrlreq->buf[0] = priv->nluns - 1;
  650. ret = 1;
  651. }
  652. }
  653. }
  654. break;
  655. default:
  656. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_BADREQUEST), ctrl->req);
  657. break;
  658. }
  659. }
  660. else
  661. {
  662. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_UNSUPPORTEDTYPE), ctrl->type);
  663. }
  664. /* Respond to the setup command if data was returned. On an error return
  665. * value (ret < 0), the USB driver will stall EP0.
  666. */
  667. if (ret >= 0)
  668. {
  669. /* Configure the response */
  670. ctrlreq->len = MIN(len, ret);
  671. ctrlreq->flags = USBDEV_REQFLAGS_NULLPKT;
  672. /* Send the response -- either directly to the USB controller or
  673. * indirectly in the case where this class is a member of a composite
  674. * device.
  675. */
  676. #ifndef CONFIG_USBMSC_COMPOSITE
  677. ret = EP_SUBMIT(dev->ep0, ctrlreq);
  678. #else
  679. ret = composite_ep0submit(driver, dev, ctrlreq);
  680. #endif
  681. if (ret < 0)
  682. {
  683. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EPRESPQ), (uint16_t)-ret);
  684. #if 0 /* Not necessary */
  685. ctrlreq->result = OK;
  686. usbmsc_ep0incomplete(dev->ep0, ctrlreq);
  687. #endif
  688. }
  689. }
  690. return ret;
  691. }
  692. /****************************************************************************
  693. * Name: usbmsc_disconnect
  694. *
  695. * Description:
  696. * Invoked after all transfers have been stopped, when the host is
  697. * disconnected. This function is probably called from the context of an
  698. * interrupt handler.
  699. *
  700. ****************************************************************************/
  701. static void usbmsc_disconnect(FAR struct usbdevclass_driver_s *driver,
  702. FAR struct usbdev_s *dev)
  703. {
  704. struct usbmsc_dev_s *priv;
  705. irqstate_t flags;
  706. usbtrace(TRACE_CLASSDISCONNECT, 0);
  707. #ifdef CONFIG_DEBUG
  708. if (!driver || !dev || !dev->ep0)
  709. {
  710. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_DISCONNECTINVALIDARGS), 0);
  711. return;
  712. }
  713. #endif
  714. /* Extract reference to private data */
  715. priv = ((FAR struct usbmsc_driver_s *)driver)->dev;
  716. #ifdef CONFIG_DEBUG
  717. if (!priv)
  718. {
  719. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EP0NOTBOUND3), 0);
  720. return;
  721. }
  722. #endif
  723. /* Reset the configuration */
  724. flags = irqsave();
  725. usbmsc_resetconfig(priv);
  726. /* Signal the worker thread */
  727. priv->theventset |= USBMSC_EVENT_DISCONNECT;
  728. pthread_cond_signal(&priv->cond);
  729. irqrestore(flags);
  730. /* Perform the soft connect function so that we will we can be
  731. * re-enumerated (unless we are part of a composite device)
  732. */
  733. #ifndef CONFIG_USBMSC_COMPOSITE
  734. DEV_CONNECT(dev);
  735. #endif
  736. }
  737. /****************************************************************************
  738. * Initialization/Un-Initialization
  739. ****************************************************************************/
  740. /****************************************************************************
  741. * Name: usbmsc_lununinitialize
  742. ****************************************************************************/
  743. static void usbmsc_lununinitialize(struct usbmsc_lun_s *lun)
  744. {
  745. /* Has a block driver has been bound to the LUN? */
  746. if (lun->inode)
  747. {
  748. /* Close the block driver */
  749. (void)close_blockdriver(lun->inode);
  750. }
  751. memset(lun, 0, sizeof(struct usbmsc_lun_s *));
  752. }
  753. /****************************************************************************
  754. * Public Functions
  755. ****************************************************************************/
  756. /****************************************************************************
  757. * Internal Interfaces
  758. ****************************************************************************/
  759. /****************************************************************************
  760. * Name: usbmsc_setconfig
  761. *
  762. * Description:
  763. * Set the device configuration by allocating and configuring endpoints and
  764. * by allocating and queuing read and write requests.
  765. *
  766. ****************************************************************************/
  767. int usbmsc_setconfig(FAR struct usbmsc_dev_s *priv, uint8_t config)
  768. {
  769. FAR struct usbmsc_req_s *privreq;
  770. FAR struct usbdev_req_s *req;
  771. #ifdef CONFIG_USBDEV_DUALSPEED
  772. FAR const struct usb_epdesc_s *epdesc;
  773. bool hispeed = (priv->usbdev->speed == USB_SPEED_HIGH);
  774. uint16_t bulkmxpacket;
  775. #endif
  776. int i;
  777. int ret = 0;
  778. #if CONFIG_DEBUG
  779. if (priv == NULL)
  780. {
  781. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_SETCONFIGINVALIDARGS), 0);
  782. return -EIO;
  783. }
  784. #endif
  785. if (config == priv->config)
  786. {
  787. /* Already configured -- Do nothing */
  788. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_ALREADYCONFIGURED), 0);
  789. return OK;
  790. }
  791. /* Discard the previous configuration data */
  792. usbmsc_resetconfig(priv);
  793. /* Was this a request to simply discard the current configuration? */
  794. if (config == USBMSC_CONFIGIDNONE)
  795. {
  796. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CONFIGNONE), 0);
  797. return OK;
  798. }
  799. /* We only accept one configuration */
  800. if (config != USBMSC_CONFIGID)
  801. {
  802. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CONFIGIDBAD), 0);
  803. return -EINVAL;
  804. }
  805. /* Configure the IN bulk endpoint */
  806. #ifdef CONFIG_USBDEV_DUALSPEED
  807. bulkmxpacket = USBMSC_BULKMAXPACKET(hispeed);
  808. epdesc = USBMSC_EPBULKINDESC(hispeed);
  809. ret = EP_CONFIGURE(priv->epbulkin, epdesc, false);
  810. #else
  811. ret = EP_CONFIGURE(priv->epbulkin,
  812. usbmsc_getepdesc(USBMSC_EPFSBULKIN), false);
  813. #endif
  814. if (ret < 0)
  815. {
  816. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EPBULKINCONFIGFAIL), 0);
  817. goto errout;
  818. }
  819. priv->epbulkin->priv = priv;
  820. /* Configure the OUT bulk endpoint */
  821. #ifdef CONFIG_USBDEV_DUALSPEED
  822. epdesc = USBMSC_EPBULKOUTDESC(hispeed);
  823. ret = EP_CONFIGURE(priv->epbulkout, epdesc, true);
  824. #else
  825. ret = EP_CONFIGURE(priv->epbulkout,
  826. usbmsc_getepdesc(USBMSC_EPFSBULKOUT), true);
  827. #endif
  828. if (ret < 0)
  829. {
  830. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EPBULKOUTCONFIGFAIL), 0);
  831. goto errout;
  832. }
  833. priv->epbulkout->priv = priv;
  834. /* Queue read requests in the bulk OUT endpoint */
  835. for (i = 0; i < CONFIG_USBMSC_NRDREQS; i++)
  836. {
  837. privreq = &priv->rdreqs[i];
  838. req = privreq->req;
  839. req->len = CONFIG_USBMSC_BULKOUTREQLEN;
  840. req->priv = privreq;
  841. req->callback = usbmsc_rdcomplete;
  842. ret = EP_SUBMIT(priv->epbulkout, req);
  843. if (ret < 0)
  844. {
  845. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_RDSUBMIT), (uint16_t)-ret);
  846. goto errout;
  847. }
  848. }
  849. priv->config = config;
  850. return OK;
  851. errout:
  852. usbmsc_resetconfig(priv);
  853. return ret;
  854. }
  855. /****************************************************************************
  856. * Name: usbmsc_resetconfig
  857. *
  858. * Description:
  859. * Mark the device as not configured and disable all endpoints.
  860. *
  861. ****************************************************************************/
  862. void usbmsc_resetconfig(FAR struct usbmsc_dev_s *priv)
  863. {
  864. /* Are we configured? */
  865. if (priv->config != USBMSC_CONFIGIDNONE)
  866. {
  867. /* Yes.. but not anymore */
  868. priv->config = USBMSC_CONFIGIDNONE;
  869. /* Disable endpoints. This should force completion of all pending
  870. * transfers.
  871. */
  872. EP_DISABLE(priv->epbulkin);
  873. EP_DISABLE(priv->epbulkout);
  874. }
  875. }
  876. /****************************************************************************
  877. * Name: usbmsc_wrcomplete
  878. *
  879. * Description:
  880. * Handle completion of write request. This function probably executes
  881. * in the context of an interrupt handler.
  882. *
  883. ****************************************************************************/
  884. void usbmsc_wrcomplete(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req)
  885. {
  886. FAR struct usbmsc_dev_s *priv;
  887. FAR struct usbmsc_req_s *privreq;
  888. irqstate_t flags;
  889. /* Sanity check */
  890. #ifdef CONFIG_DEBUG
  891. if (!ep || !ep->priv || !req || !req->priv)
  892. {
  893. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRCOMPLETEINVALIDARGS), 0);
  894. return;
  895. }
  896. #endif
  897. /* Extract references to private data */
  898. priv = (FAR struct usbmsc_dev_s*)ep->priv;
  899. privreq = (FAR struct usbmsc_req_s *)req->priv;
  900. /* Return the write request to the free list */
  901. flags = irqsave();
  902. sq_addlast((sq_entry_t*)privreq, &priv->wrreqlist);
  903. irqrestore(flags);
  904. /* Process the received data unless this is some unusual condition */
  905. switch (req->result)
  906. {
  907. case OK: /* Normal completion */
  908. usbtrace(TRACE_CLASSWRCOMPLETE, req->xfrd);
  909. break;
  910. case -ESHUTDOWN: /* Disconnection */
  911. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRSHUTDOWN), 0);
  912. break;
  913. default: /* Some other error occurred */
  914. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRUNEXPECTED),
  915. (uint16_t)-req->result);
  916. break;
  917. };
  918. /* Inform the worker thread that a write request has been returned */
  919. priv->theventset |= USBMSC_EVENT_WRCOMPLETE;
  920. pthread_cond_signal(&priv->cond);
  921. }
  922. /****************************************************************************
  923. * Name: usbmsc_rdcomplete
  924. *
  925. * Description:
  926. * Handle completion of read request on the bulk OUT endpoint. This
  927. * is handled like the receipt of serial data on the "UART"
  928. *
  929. ****************************************************************************/
  930. void usbmsc_rdcomplete(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req)
  931. {
  932. FAR struct usbmsc_dev_s *priv;
  933. FAR struct usbmsc_req_s *privreq;
  934. irqstate_t flags;
  935. int ret;
  936. /* Sanity check */
  937. #ifdef CONFIG_DEBUG
  938. if (!ep || !ep->priv || !req || !req->priv)
  939. {
  940. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_RDCOMPLETEINVALIDARGS), 0);
  941. return;
  942. }
  943. #endif
  944. /* Extract references to private data */
  945. priv = (FAR struct usbmsc_dev_s*)ep->priv;
  946. privreq = (FAR struct usbmsc_req_s *)req->priv;
  947. /* Process the received data unless this is some unusual condition */
  948. switch (req->result)
  949. {
  950. case 0: /* Normal completion */
  951. {
  952. usbtrace(TRACE_CLASSRDCOMPLETE, req->xfrd);
  953. /* Add the filled read request from the rdreqlist */
  954. flags = irqsave();
  955. sq_addlast((sq_entry_t*)privreq, &priv->rdreqlist);
  956. irqrestore(flags);
  957. /* Signal the worker thread that there is received data to be processed */
  958. priv->theventset |= USBMSC_EVENT_RDCOMPLETE;
  959. pthread_cond_signal(&priv->cond);
  960. }
  961. break;
  962. case -ESHUTDOWN: /* Disconnection */
  963. {
  964. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_RDSHUTDOWN), 0);
  965. /* Drop the read request... it will be cleaned up later */
  966. }
  967. break;
  968. default: /* Some other error occurred */
  969. {
  970. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_RDUNEXPECTED),
  971. (uint16_t)-req->result);
  972. /* Return the read request to the bulk out endpoint for re-filling */
  973. req = privreq->req;
  974. req->priv = privreq;
  975. req->callback = usbmsc_rdcomplete;
  976. ret = EP_SUBMIT(priv->epbulkout, req);
  977. if (ret != OK)
  978. {
  979. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_RDCOMPLETERDSUBMIT),
  980. (uint16_t)-ret);
  981. }
  982. }
  983. break;
  984. }
  985. }
  986. /****************************************************************************
  987. * Name: usbmsc_deferredresponse
  988. *
  989. * Description:
  990. * Some EP0 setup request cannot be responded to immediately becuase they
  991. * require some asynchronous action from the SCSI worker thread. This
  992. * function is provided for the SCSI thread to make that deferred response.
  993. * The specific requests that require this deferred response are:
  994. *
  995. * 1. USB_REQ_SETCONFIGURATION,
  996. * 2. USB_REQ_SETINTERFACE, or
  997. * 3. USBMSC_REQ_MSRESET
  998. *
  999. * In all cases, the success reponse is a zero-length packet; the failure
  1000. * response is an EP0 stall.
  1001. *
  1002. * Input parameters:
  1003. * priv - Private state structure for this USB storage instance
  1004. * stall - true is the action failed and a stall is required
  1005. *
  1006. ****************************************************************************/
  1007. void usbmsc_deferredresponse(FAR struct usbmsc_dev_s *priv, bool failed)
  1008. {
  1009. FAR struct usbdev_s *dev;
  1010. FAR struct usbdev_req_s *ctrlreq;
  1011. int ret;
  1012. #ifdef CONFIG_DEBUG
  1013. if (!priv || !priv->usbdev || !priv->ctrlreq)
  1014. {
  1015. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_DEFERREDRESPINVALIDARGS), 0);
  1016. return;
  1017. }
  1018. #endif
  1019. dev = priv->usbdev;
  1020. ctrlreq = priv->ctrlreq;
  1021. /* If no error occurs, respond to the deferred setup command with a null
  1022. * packet.
  1023. */
  1024. if (!failed)
  1025. {
  1026. ctrlreq->len = 0;
  1027. ctrlreq->flags = USBDEV_REQFLAGS_NULLPKT;
  1028. ret = EP_SUBMIT(dev->ep0, ctrlreq);
  1029. if (ret < 0)
  1030. {
  1031. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_DEFERREDRESPSUBMIT),
  1032. (uint16_t)-ret);
  1033. #if 0 /* Not necessary */
  1034. ctrlreq->result = OK;
  1035. usbmsc_ep0incomplete(dev->ep0, ctrlreq);
  1036. #endif
  1037. }
  1038. }
  1039. else
  1040. {
  1041. /* On a failure, the USB driver will stall. */
  1042. usbtrace(TRACE_DEVERROR(USBMSC_TRACEERR_DEFERREDRESPSTALLED), 0);
  1043. EP_STALL(dev->ep0);
  1044. }
  1045. }
  1046. /****************************************************************************
  1047. * User Interfaces
  1048. ****************************************************************************/
  1049. /****************************************************************************
  1050. * Name: usbmsc_configure
  1051. *
  1052. * Description:
  1053. * One-time initialization of the USB storage driver. The initialization
  1054. * sequence is as follows:
  1055. *
  1056. * 1. Call usbmsc_configure to perform one-time initialization specifying
  1057. * the number of luns.
  1058. * 2. Call usbmsc_bindlun to configure each supported LUN
  1059. * 3. Call usbmsc_exportluns when all LUNs are configured
  1060. *
  1061. * Input Parameters:
  1062. * nluns - the number of LUNs that will be registered
  1063. * handle - Location to return a handle that is used in other API calls.
  1064. *
  1065. * Returned Value:
  1066. * 0 on success; a negated errno on failure
  1067. *
  1068. ****************************************************************************/
  1069. int usbmsc_configure(unsigned int nluns, void **handle)
  1070. {
  1071. FAR struct usbmsc_alloc_s *alloc;
  1072. FAR struct usbmsc_dev_s *priv;
  1073. FAR struct usbmsc_driver_s *drvr;
  1074. int ret;
  1075. #ifdef CONFIG_DEBUG
  1076. if (nluns > 15)
  1077. {
  1078. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_TOOMANYLUNS), 0);
  1079. return -EDOM;
  1080. }
  1081. #endif
  1082. /* Allocate the structures needed */
  1083. alloc = (FAR struct usbmsc_alloc_s*)kmalloc(sizeof(struct usbmsc_alloc_s));
  1084. if (!alloc)
  1085. {
  1086. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_ALLOCDEVSTRUCT), 0);
  1087. return -ENOMEM;
  1088. }
  1089. /* Initialize the USB storage driver structure */
  1090. priv = &alloc->dev;
  1091. memset(priv, 0, sizeof(struct usbmsc_dev_s));
  1092. pthread_mutex_init(&priv->mutex, NULL);
  1093. pthread_cond_init(&priv->cond, NULL);
  1094. sq_init(&priv->wrreqlist);
  1095. priv->nluns = nluns;
  1096. /* Allocate the LUN table */
  1097. priv->luntab = (struct usbmsc_lun_s*)kmalloc(priv->nluns*sizeof(struct usbmsc_lun_s));
  1098. if (!priv->luntab)
  1099. {
  1100. ret = -ENOMEM;
  1101. goto errout;
  1102. }
  1103. memset(priv->luntab, 0, priv->nluns * sizeof(struct usbmsc_lun_s));
  1104. /* Initialize the USB class driver structure */
  1105. drvr = &alloc->drvr;
  1106. #ifdef CONFIG_USBDEV_DUALSPEED
  1107. drvr->drvr.speed = USB_SPEED_HIGH;
  1108. #else
  1109. drvr->drvr.speed = USB_SPEED_FULL;
  1110. #endif
  1111. drvr->drvr.ops = &g_driverops;
  1112. drvr->dev = priv;
  1113. /* Return the handle and success */
  1114. *handle = (FAR void*)alloc;
  1115. return OK;
  1116. errout:
  1117. usbmsc_uninitialize(alloc);
  1118. return ret;
  1119. }
  1120. /****************************************************************************
  1121. * Name: usbmsc_bindlun
  1122. *
  1123. * Description:
  1124. * Bind the block driver specified by drvrpath to a USB storage LUN.
  1125. *
  1126. * Input Parameters:
  1127. * handle - The handle returned by a previous call to usbmsc_configure().
  1128. * drvrpath - the full path to the block driver
  1129. * startsector - A sector offset into the block driver to the start of the
  1130. * partition on drvrpath (0 if no partitions)
  1131. * nsectors - The number of sectors in the partition (if 0, all sectors
  1132. * to the end of the media will be exported).
  1133. * lunno - the LUN to bind to
  1134. *
  1135. * Returned Value:
  1136. * 0 on success; a negated errno on failure.
  1137. *
  1138. ****************************************************************************/
  1139. int usbmsc_bindlun(FAR void *handle, FAR const char *drvrpath,
  1140. unsigned int lunno, off_t startsector, size_t nsectors,
  1141. bool readonly)
  1142. {
  1143. FAR struct usbmsc_alloc_s *alloc = (FAR struct usbmsc_alloc_s *)handle;
  1144. FAR struct usbmsc_dev_s *priv;
  1145. FAR struct usbmsc_lun_s *lun;
  1146. FAR struct inode *inode;
  1147. struct geometry geo;
  1148. int ret;
  1149. #ifdef CONFIG_DEBUG
  1150. if (!alloc || !drvrpath || startsector < 0 || nsectors < 0)
  1151. {
  1152. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_BINLUNINVALIDARGS1), 0);
  1153. return -EINVAL;
  1154. }
  1155. #endif
  1156. priv = &alloc->dev;
  1157. #ifdef CONFIG_DEBUG
  1158. if (!priv->luntab)
  1159. {
  1160. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_INTERNALCONFUSION1), 0);
  1161. return -EIO;
  1162. }
  1163. if (lunno > priv->nluns)
  1164. {
  1165. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_BINDLUNINVALIDARGS2), 0);
  1166. return -EINVAL;
  1167. }
  1168. #endif
  1169. lun = &priv->luntab[lunno];
  1170. #ifdef CONFIG_DEBUG
  1171. if (lun->inode != NULL)
  1172. {
  1173. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_LUNALREADYBOUND), 0);
  1174. return -EBUSY;
  1175. }
  1176. #endif
  1177. /* Open the block driver */
  1178. ret = open_blockdriver(drvrpath, 0, &inode);
  1179. if (ret < 0)
  1180. {
  1181. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_BLKDRVEOPEN), 0);
  1182. return ret;
  1183. }
  1184. /* Get the drive geometry */
  1185. if (!inode || !inode->u.i_bops || !inode->u.i_bops->geometry ||
  1186. inode->u.i_bops->geometry(inode, &geo) != OK || !geo.geo_available)
  1187. {
  1188. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_NOGEOMETRY), 0);
  1189. return -ENODEV;
  1190. }
  1191. /* Verify that the partition parameters are valid */
  1192. if (startsector >= geo.geo_nsectors)
  1193. {
  1194. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_BINDLUNINVALIDARGS3), 0);
  1195. return -EDOM;
  1196. }
  1197. else if (nsectors == 0)
  1198. {
  1199. nsectors = geo.geo_nsectors - startsector;
  1200. }
  1201. else if (startsector + nsectors >= geo.geo_nsectors)
  1202. {
  1203. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_BINDLUNINVALIDARGS4), 0);
  1204. return -EDOM;
  1205. }
  1206. /* Initialize the LUN structure */
  1207. memset(lun, 0, sizeof(struct usbmsc_lun_s *));
  1208. /* Allocate an I/O buffer big enough to hold one hardware sector. SCSI commands
  1209. * are processed one at a time so all LUNs may share a single I/O buffer. The
  1210. * I/O buffer will be allocated so that is it as large as the largest block
  1211. * device sector size
  1212. */
  1213. if (!priv->iobuffer)
  1214. {
  1215. priv->iobuffer = (uint8_t*)kmalloc(geo.geo_sectorsize);
  1216. if (!priv->iobuffer)
  1217. {
  1218. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_ALLOCIOBUFFER), geo.geo_sectorsize);
  1219. return -ENOMEM;
  1220. }
  1221. priv->iosize = geo.geo_sectorsize;
  1222. }
  1223. else if (priv->iosize < geo.geo_sectorsize)
  1224. {
  1225. void *tmp;
  1226. tmp = (uint8_t*)krealloc(priv->iobuffer, geo.geo_sectorsize);
  1227. if (!tmp)
  1228. {
  1229. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_REALLOCIOBUFFER), geo.geo_sectorsize);
  1230. return -ENOMEM;
  1231. }
  1232. priv->iobuffer = (uint8_t*)tmp;
  1233. priv->iosize = geo.geo_sectorsize;
  1234. }
  1235. lun->inode = inode;
  1236. lun->startsector = startsector;
  1237. lun->nsectors = nsectors;
  1238. lun->sectorsize = geo.geo_sectorsize;
  1239. /* If the driver does not support the write method, then this is read-only */
  1240. if (!inode->u.i_bops->write)
  1241. {
  1242. lun->readonly = true;
  1243. }
  1244. return OK;
  1245. }
  1246. /****************************************************************************
  1247. * Name: usbmsc_unbindlun
  1248. *
  1249. * Description:
  1250. * Un-bind the block driver for the specified LUN
  1251. *
  1252. * Input Parameters:
  1253. * handle - The handle returned by a previous call to usbmsc_configure().
  1254. * lun - the LUN to unbind from
  1255. *
  1256. * Returned Value:
  1257. * 0 on success; a negated errno on failure.
  1258. *
  1259. ****************************************************************************/
  1260. int usbmsc_unbindlun(FAR void *handle, unsigned int lunno)
  1261. {
  1262. FAR struct usbmsc_alloc_s *alloc = (FAR struct usbmsc_alloc_s *)handle;
  1263. FAR struct usbmsc_dev_s *priv;
  1264. FAR struct usbmsc_lun_s *lun;
  1265. int ret;
  1266. #ifdef CONFIG_DEBUG
  1267. if (!alloc)
  1268. {
  1269. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_UNBINDLUNINVALIDARGS1), 0);
  1270. return -EINVAL;
  1271. }
  1272. #endif
  1273. priv = &alloc->dev;
  1274. #ifdef CONFIG_DEBUG
  1275. if (!priv->luntab)
  1276. {
  1277. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_INTERNALCONFUSION2), 0);
  1278. return -EIO;
  1279. }
  1280. if (lunno > priv->nluns)
  1281. {
  1282. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_UNBINDLUNINVALIDARGS2), 0);
  1283. return -EINVAL;
  1284. }
  1285. #endif
  1286. lun = &priv->luntab[lunno];
  1287. pthread_mutex_lock(&priv->mutex);
  1288. #ifdef CONFIG_DEBUG
  1289. if (lun->inode == NULL)
  1290. {
  1291. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_LUNNOTBOUND), 0);
  1292. ret = -EBUSY;
  1293. }
  1294. else
  1295. #endif
  1296. {
  1297. /* Close the block driver */
  1298. usbmsc_lununinitialize(lun);
  1299. ret = OK;
  1300. }
  1301. pthread_mutex_unlock(&priv->mutex);
  1302. return ret;
  1303. }
  1304. /****************************************************************************
  1305. * Name: usbmsc_exportluns
  1306. *
  1307. * Description:
  1308. * After all of the LUNs have been bound, this function may be called
  1309. * in order to export those LUNs in the USB storage device.
  1310. *
  1311. * Input Parameters:
  1312. * handle - The handle returned by a previous call to usbmsc_configure().
  1313. *
  1314. * Returned Value:
  1315. * 0 on success; a negated errno on failure
  1316. *
  1317. ****************************************************************************/
  1318. #ifdef CONFIG_USBMSC_COMPOSITE
  1319. static
  1320. #endif
  1321. int usbmsc_exportluns(FAR void *handle)
  1322. {
  1323. FAR struct usbmsc_alloc_s *alloc = (FAR struct usbmsc_alloc_s *)handle;
  1324. FAR struct usbmsc_dev_s *priv;
  1325. FAR struct usbmsc_driver_s *drvr;
  1326. irqstate_t flags;
  1327. #ifdef SDCC
  1328. pthread_attr_t attr;
  1329. #endif
  1330. int ret;
  1331. #ifdef CONFIG_DEBUG
  1332. if (!alloc)
  1333. {
  1334. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EXPORTLUNSINVALIDARGS), 0);
  1335. return -ENXIO;
  1336. }
  1337. #endif
  1338. priv = &alloc->dev;
  1339. drvr = &alloc->drvr;
  1340. /* Start the worker thread */
  1341. pthread_mutex_lock(&priv->mutex);
  1342. priv->thstate = USBMSC_STATE_NOTSTARTED;
  1343. priv->theventset = USBMSC_EVENT_NOEVENTS;
  1344. #ifdef SDCC
  1345. (void)pthread_attr_init(&attr);
  1346. ret = pthread_create(&priv->thread, &attr, usbmsc_workerthread, (pthread_addr_t)priv);
  1347. #else
  1348. ret = pthread_create(&priv->thread, NULL, usbmsc_workerthread, (pthread_addr_t)priv);
  1349. #endif
  1350. if (ret != OK)
  1351. {
  1352. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_THREADCREATE), (uint16_t)-ret);
  1353. goto errout_with_mutex;
  1354. }
  1355. /* Register the USB storage class driver (unless we are part of a composite device) */
  1356. #ifndef CONFIG_USBMSC_COMPOSITE
  1357. ret = usbdev_register(&drvr->drvr);
  1358. if (ret != OK)
  1359. {
  1360. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_DEVREGISTER), (uint16_t)-ret);
  1361. goto errout_with_mutex;
  1362. }
  1363. #endif
  1364. /* Signal to start the thread */
  1365. flags = irqsave();
  1366. priv->theventset |= USBMSC_EVENT_READY;
  1367. pthread_cond_signal(&priv->cond);
  1368. irqrestore(flags);
  1369. errout_with_mutex:
  1370. pthread_mutex_unlock(&priv->mutex);
  1371. return ret;
  1372. }
  1373. /****************************************************************************
  1374. * Name: usbmsc_classobject
  1375. *
  1376. * Description:
  1377. * Register USB mass storage device and return the class object.
  1378. *
  1379. * Input Parameters:
  1380. * classdev - The location to return the CDC serial class' device
  1381. * instance.
  1382. *
  1383. * Returned Value:
  1384. * 0 on success; a negated errno on failure
  1385. *
  1386. ****************************************************************************/
  1387. #ifdef CONFIG_USBMSC_COMPOSITE
  1388. int usbmsc_classobject(FAR void *handle,
  1389. FAR struct usbdevclass_driver_s **classdev)
  1390. {
  1391. FAR struct usbmsc_alloc_s *alloc = (FAR struct usbmsc_alloc_s *)handle;
  1392. int ret;
  1393. DEBUGASSERT(handle && classdev);
  1394. /* Export the LUNs as with the "standalone" USB mass storage driver, but
  1395. * don't register the class instance with the USB device infrastructure.
  1396. */
  1397. ret = usbmsc_exportluns(handle);
  1398. if (ret == OK)
  1399. {
  1400. /* On sucess, return an (typed) instance of the class instance */
  1401. *classdev = &alloc->drvr.drvr;
  1402. }
  1403. return ret;
  1404. }
  1405. #endif
  1406. /****************************************************************************
  1407. * Name: usbmsc_uninitialize
  1408. *
  1409. * Description:
  1410. * Un-initialize the USB storage class driver
  1411. *
  1412. * Input Parameters:
  1413. * handle - The handle returned by a previous call to usbmsc_configure().
  1414. *
  1415. * Returned Value:
  1416. * None
  1417. *
  1418. ****************************************************************************/
  1419. void usbmsc_uninitialize(FAR void *handle)
  1420. {
  1421. FAR struct usbmsc_alloc_s *alloc = (FAR struct usbmsc_alloc_s *)handle;
  1422. FAR struct usbmsc_dev_s *priv;
  1423. irqstate_t flags;
  1424. #ifdef SDCC
  1425. pthread_addr_t result1, result2;
  1426. pthread_attr_t attr;
  1427. #endif
  1428. void *value;
  1429. int i;
  1430. #ifdef CONFIG_DEBUG
  1431. if (!handle)
  1432. {
  1433. usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_UNINITIALIZEINVALIDARGS), 0);
  1434. return;
  1435. }
  1436. #endif
  1437. priv = &alloc->dev;
  1438. /* If the thread hasn't already exitted, tell it to exit now */
  1439. if (priv->thstate != USBMSC_STATE_NOTSTARTED)
  1440. {
  1441. /* The thread was started.. Is it still running? */
  1442. pthread_mutex_lock(&priv->mutex);
  1443. if (priv->thstate != USBMSC_STATE_TERMINATED)
  1444. {
  1445. /* Yes.. Ask the thread to stop */
  1446. flags = irqsave();
  1447. priv->theventset |= USBMSC_EVENT_TERMINATEREQUEST;
  1448. pthread_cond_signal(&priv->cond);
  1449. irqrestore(flags);
  1450. }
  1451. pthread_mutex_unlock(&priv->mutex);
  1452. /* Wait for the thread to exit. This is necessary even if the
  1453. * thread has already exitted in order to collect the join
  1454. * garbage
  1455. */
  1456. (void)pthread_join(priv->thread, &value);
  1457. }
  1458. priv->thread = 0;
  1459. /* Unregister the driver (unless we are a part of a composite device */
  1460. #ifndef CONFIG_USBMSC_COMPOSITE
  1461. usbdev_unregister(&alloc->drvr.drvr);
  1462. #endif
  1463. /* Uninitialize and release the LUNs */
  1464. for (i = 0; i < priv->nluns; ++i)
  1465. {
  1466. usbmsc_lununinitialize(&priv->luntab[i]);
  1467. }
  1468. kfree(priv->luntab);
  1469. /* Release the I/O buffer */
  1470. if (priv->iobuffer)
  1471. {
  1472. kfree(priv->iobuffer);
  1473. }
  1474. /* Uninitialize and release the driver structure */
  1475. pthread_mutex_destroy(&priv->mutex);
  1476. pthread_cond_destroy(&priv->cond);
  1477. kfree(priv);
  1478. }