usbhost_cdcacm.c 83 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813
  1. /****************************************************************************
  2. * drivers/usbhost/usbhost_cdcacm.c
  3. *
  4. * Copyright (C) 2015-2016 Gregory Nutt. All rights reserved.
  5. * Author: Gregory Nutt <gnutt@nuttx.org>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. * 3. Neither the name NuttX nor the names of its contributors may be
  19. * used to endorse or promote products derived from this software
  20. * without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  25. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  26. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  27. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  28. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  29. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  30. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  32. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  33. * POSSIBILITY OF SUCH DAMAGE.
  34. *
  35. ****************************************************************************/
  36. /****************************************************************************
  37. * Included Files
  38. ****************************************************************************/
  39. #include <nuttx/config.h>
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include <unistd.h>
  44. #include <semaphore.h>
  45. #include <assert.h>
  46. #include <errno.h>
  47. #include <debug.h>
  48. #include <nuttx/irq.h>
  49. #include <nuttx/kmalloc.h>
  50. #include <nuttx/arch.h>
  51. #include <nuttx/wqueue.h>
  52. #include <nuttx/clock.h>
  53. #include <nuttx/serial/serial.h>
  54. #include <nuttx/usb/usb.h>
  55. #include <nuttx/usb/usbhost.h>
  56. #include <nuttx/usb/cdc.h>
  57. #include <nuttx/usb/cdcacm.h>
  58. #include <nuttx/usb/usbhost_devaddr.h>
  59. #ifdef CONFIG_USBHOST_CDCACM
  60. /****************************************************************************
  61. * Pre-processor Definitions
  62. ****************************************************************************/
  63. /* Configuration ************************************************************/
  64. #ifndef CONFIG_USBHOST
  65. # warning USB host support not enabled (CONFIG_USBHOST)
  66. #endif
  67. #ifdef CONFIG_USBHOST_BULK_DISABLE
  68. # warning USB bulk endpoint support is disabled (CONFIG_USBHOST_BULK_DISABLE)
  69. #endif
  70. #ifdef CONFIG_USBHOST_INT_DISABLE
  71. # warning USB interrupt endpoint support is disabled (CONFIG_USBHOST_INT_DISABLE)
  72. #endif
  73. #if !defined(CONFIG_SCHED_WORKQUEUE)
  74. # warning Worker thread support is required (CONFIG_SCHED_WORKQUEUE)
  75. #else
  76. # ifndef CONFIG_SCHED_HPWORK
  77. # warning High priority work thread support is required (CONFIG_SCHED_HPWORK)
  78. # endif
  79. # ifndef CONFIG_SCHED_LPWORK
  80. # warning Low priority work thread support is required (CONFIG_SCHED_LPWORK)
  81. # endif
  82. # if CONFIG_SCHED_LPNTHREADS < 2
  83. # warning Multiple low priority work threads recommended for performance (CONFIG_SCHED_LPNTHREADS > 1)
  84. # endif
  85. #endif
  86. #ifndef CONFIG_USBHOST_ASYNCH
  87. # warning Asynchronous transfer support is required (CONFIG_USBHOST_ASYNCH)
  88. #endif
  89. #ifndef CONFIG_SERIAL_REMOVABLE
  90. # warning Removable serial device support is required (CONFIG_SERIAL_REMOVABLE)
  91. #endif
  92. #ifdef CONFIG_USBHOST_CDCACM_NTDELAY
  93. # define USBHOST_CDCACM_NTDELAY MSEC2TICK(CONFIG_USBHOST_CDCACM_NTDELAY)
  94. #else
  95. # define USBHOST_CDCACM_NTDELAY MSEC2TICK(200)
  96. #endif
  97. #ifdef CONFIG_USBHOST_CDCACM_RXDELAY
  98. # define USBHOST_CDCACM_RXDELAY MSEC2TICK(CONFIG_USBHOST_CDCACM_RXDELAY)
  99. #else
  100. # define USBHOST_CDCACM_RXDELAY MSEC2TICK(200)
  101. #endif
  102. #ifdef CONFIG_USBHOST_CDCACM_TXDELAY
  103. # define USBHOST_CDCACM_TXDELAY MSEC2TICK(CONFIG_USBHOST_CDCACM_TXDELAY)
  104. #else
  105. # define USBHOST_CDCACM_TXDELAY MSEC2TICK(200)
  106. #endif
  107. /* Supported protocol */
  108. #define HAVE_CLASS_REQUESTS 1
  109. #define HAVE_INTIN_ENDPOINT 1
  110. #define HAVE_CTRL_INTERFACE 1
  111. #if defined(CONFIG_USBHOST_CDCACM_REDUCED)
  112. # undef CONFIG_USBHOST_CDCACM_BULKONLY
  113. # undef CONFIG_USBHOST_CDCACM_COMPLIANT
  114. # undef HAVE_INTIN_ENDPOINT
  115. #elif defined(CONFIG_USBHOST_CDCACM_BULKONLY)
  116. # undef CONFIG_USBHOST_CDCACM_COMPLIANT
  117. # undef HAVE_CLASS_REQUESTS
  118. # undef HAVE_INTIN_ENDPOINT
  119. # undef HAVE_CTRL_INTERFACE
  120. #endif
  121. /* If the create() method is called by the USB host device driver from an
  122. * interrupt handler, then it will be unable to call kmm_malloc() in order to
  123. * allocate a new class instance. If the create() method is called from the
  124. * interrupt level, then class instances must be pre-allocated.
  125. */
  126. #ifndef CONFIG_USBHOST_CDCACM_NPREALLOC
  127. # define CONFIG_USBHOST_CDCACM_NPREALLOC 0
  128. #endif
  129. #if CONFIG_USBHOST_CDCACM_NPREALLOC > 32
  130. # error Currently limited to 32 devices /dev/ttyACM[n]
  131. #endif
  132. #ifndef CONFIG_USBHOST_CDCACM_RXBUFSIZE
  133. # define CONFIG_USBHOST_CDCACM_RXBUFSIZE 128
  134. #endif
  135. #ifndef CONFIG_USBHOST_CDCACM_TXBUFSIZE
  136. # define CONFIG_USBHOST_CDCACM_TXBUFSIZE 128
  137. #endif
  138. /* Initial line coding */
  139. #ifndef CONFIG_USBHOST_CDCACM_BAUD
  140. # define CONFIG_USBHOST_CDCACM_BAUD 115200
  141. #endif
  142. #ifndef CONFIG_USBHOST_CDCACM_PARITY
  143. # define CONFIG_USBHOST_CDCACM_PARITY 0
  144. #endif
  145. #ifndef CONFIG_USBHOST_CDCACM_BITS
  146. # define CONFIG_USBHOST_CDCACM_BITS 8
  147. #endif
  148. #ifndef CONFIG_USBHOST_CDCACM_2STOP
  149. # define CONFIG_USBHOST_CDCACM_2STOP 0
  150. #endif
  151. /* Driver support ***********************************************************/
  152. /* This format is used to construct the /dev/sd[n] device driver path. It
  153. * defined here so that it will be used consistently in all places.
  154. */
  155. #define DEV_FORMAT "/dev/ttyACM%d"
  156. #define DEV_NAMELEN 16
  157. #define MAX_NOTIFICATION 32
  158. /* Used in usbhost_connect() */
  159. #define USBHOST_DATAIF_FOUND 0x01 /* Data interface found */
  160. #define USBHOST_BULKIN_FOUND 0x02 /* Bulk IN interface found */
  161. #define USBHOST_BULKOUT_FOUND 0x04 /* Bulk OUT interface found */
  162. #if defined(CONFIG_USBHOST_CDCACM_BULKONLY)
  163. # define USBHOST_MINFOUND 0x07 /* Minimum things needed */
  164. # define USBHOST_ALLFOUND 0x07 /* All configuration things */
  165. #elif defined(CONFIG_USBHOST_CDCACM_REDUCED)
  166. # define USBHOST_CTRLIF_FOUND 0x08 /* Control interface found */
  167. # define USBHOST_MINFOUND 0x07 /* Minimum things needed */
  168. # define USBHOST_HAVE_CTRLIF 0x08 /* Needed for control interface */
  169. # define USBHOST_ALLFOUND 0x0f /* All configuration things */
  170. #else
  171. # define USBHOST_CTRLIF_FOUND 0x08 /* Control interface found */
  172. # define USBHOST_INTIN_FOUND 0x10 /* Interrupt IN interface found */
  173. # define USBHOST_MINFOUND 0x07 /* Minimum things needed */
  174. # define USBHOST_HAVE_CTRLIF 0x18 /* Needed for control interface */
  175. # define USBHOST_ALLFOUND 0x1f /* All configuration things */
  176. #endif
  177. #define USBHOST_MAX_CREFS INT16_MAX /* Max cref count before signed overflow */
  178. /****************************************************************************
  179. * Private Types
  180. ****************************************************************************/
  181. /* This structure contains the internal, private state of the USB host
  182. * CDC/ACM class.
  183. */
  184. struct usbhost_cdcacm_s
  185. {
  186. /* This is the externally visible portion of the state. The usbclass must
  187. * the first element of the structure. It is then cast compatible with
  188. * struct usbhost_cdcacm_s.
  189. */
  190. struct usbhost_class_s usbclass;
  191. /* This is the standard of the lower-half serial interface. It is not
  192. * the first element of the structure, but includes a pointer back to the
  193. * the beginning of this structure.
  194. */
  195. struct uart_dev_s uartdev;
  196. /* The remainder of the fields are provide to the CDC/ACM class */
  197. volatile bool disconnected; /* TRUE: Device has been disconnected */
  198. bool stop2; /* True: 2 stop bits (for line coding) */
  199. bool dsr; /* State of transmission carrier */
  200. bool dcd; /* State of receiver carrier detection */
  201. bool txena; /* True: TX "interrupts" enabled */
  202. bool rxena; /* True: RX "interrupts" enabled */
  203. #ifdef CONFIG_SERIAL_IFLOWCONTROL
  204. bool iflow; /* True: Input flow control (RTS) enabled */
  205. bool rts; /* True: Input flow control is in effect */
  206. #endif
  207. #ifdef CONFIG_SERIAL_OFLOWCONTROL
  208. bool oflow; /* True: Output flow control (CTS) enabled */
  209. #endif
  210. uint8_t minor; /* Minor number identifying the /dev/ttyACM[n] device */
  211. uint8_t dataif; /* Data interface number */
  212. #ifdef HAVE_CTRL_INTERFACE
  213. uint8_t ctrlif; /* Control interface number */
  214. #endif
  215. uint8_t nbits; /* Number of bits (for line encoding) */
  216. uint8_t parity; /* Parity (for line encoding) */
  217. uint16_t pktsize; /* Allocated size of transfer buffers */
  218. uint16_t nrxbytes; /* Number of bytes in the RX packet buffer */
  219. uint16_t rxndx; /* Index to the next byte in the RX packet buffer */
  220. int16_t crefs; /* Reference count on the driver instance */
  221. int16_t nbytes; /* The number of bytes actually transferred */
  222. sem_t exclsem; /* Used to maintain mutual exclusive access */
  223. struct work_s ntwork; /* For asynchronous notification work */
  224. struct work_s rxwork; /* For RX packet work */
  225. struct work_s txwork; /* For TX packet work */
  226. FAR uint8_t *ctrlreq; /* Allocated ctrl request structure */
  227. FAR uint8_t *linecode; /* The allocated buffer for line encoding */
  228. FAR uint8_t *notification; /* The allocated buffer for async notifications */
  229. FAR uint8_t *inbuf; /* Allocated RX buffer for the Bulk IN endpoint */
  230. FAR uint8_t *outbuf; /* Allocated TX buffer for the Bulk OUT endpoint */
  231. uint32_t baud; /* Current baud for line coding */
  232. usbhost_ep_t bulkin; /* Bulk IN endpoint */
  233. usbhost_ep_t bulkout; /* Bulk OUT endpoint */
  234. #ifdef HAVE_INTIN_ENDPOINT
  235. usbhost_ep_t intin; /* Interrupt IN endpoint (optional) */
  236. #endif
  237. /* This is the serial data buffer */
  238. char rxbuffer[CONFIG_USBHOST_CDCACM_RXBUFSIZE];
  239. char txbuffer[CONFIG_USBHOST_CDCACM_TXBUFSIZE];
  240. };
  241. /* This is how struct usbhost_cdcacm_s looks to the free list logic */
  242. struct usbhost_freestate_s
  243. {
  244. FAR struct usbhost_freestate_s *flink;
  245. };
  246. /****************************************************************************
  247. * Private Function Prototypes
  248. ****************************************************************************/
  249. /* Semaphores */
  250. static void usbhost_takesem(sem_t *sem);
  251. #define usbhost_givesem(s) sem_post(s);
  252. /* Memory allocation services */
  253. static FAR struct usbhost_cdcacm_s *usbhost_allocclass(void);
  254. static void usbhost_freeclass(FAR struct usbhost_cdcacm_s *usbclass);
  255. /* Device name management */
  256. static int usbhost_devno_alloc(FAR struct usbhost_cdcacm_s *priv);
  257. static void usbhost_devno_free(FAR struct usbhost_cdcacm_s *priv);
  258. static inline void usbhost_mkdevname(FAR struct usbhost_cdcacm_s *priv,
  259. FAR char *devname);
  260. /* CDC/ACM request helpers */
  261. #ifdef HAVE_CTRL_INTERFACE
  262. static int usbhost_linecoding_send(FAR struct usbhost_cdcacm_s *priv);
  263. #ifdef HAVE_INTIN_ENDPOINT
  264. static void usbhost_notification_work(FAR void *arg);
  265. static void usbhost_notification_callback(FAR void *arg, ssize_t nbytes);
  266. #endif
  267. #endif
  268. /* UART buffer data transfer */
  269. static void usbhost_txdata_work(FAR void *arg);
  270. static void usbhost_rxdata_work(FAR void *arg);
  271. /* Worker thread actions */
  272. static void usbhost_destroy(FAR void *arg);
  273. /* Helpers for usbhost_connect() */
  274. static int usbhost_cfgdesc(FAR struct usbhost_cdcacm_s *priv,
  275. FAR const uint8_t *configdesc, int desclen);
  276. /* (Little Endian) Data helpers */
  277. static inline uint16_t usbhost_getle16(const uint8_t *val);
  278. static inline uint16_t usbhost_getbe16(const uint8_t *val);
  279. static inline void usbhost_putle16(uint8_t *dest, uint16_t val);
  280. #ifdef HAVE_CTRL_INTERFACE
  281. static void usbhost_putle32(uint8_t *dest, uint32_t val);
  282. #endif
  283. /* Transfer descriptor memory management */
  284. static int usbhost_alloc_buffers(FAR struct usbhost_cdcacm_s *priv);
  285. static void usbhost_free_buffers(FAR struct usbhost_cdcacm_s *priv);
  286. /* struct usbhost_registry_s methods */
  287. static struct usbhost_class_s *usbhost_create(
  288. FAR struct usbhost_hubport_s *hport,
  289. FAR const struct usbhost_id_s *id);
  290. /* struct usbhost_class_s methods */
  291. static int usbhost_connect(FAR struct usbhost_class_s *usbclass,
  292. FAR const uint8_t *configdesc, int desclen);
  293. static int usbhost_disconnected(FAR struct usbhost_class_s *usbclass);
  294. /* Serial driver lower-half interfaces */
  295. static int usbhost_setup(FAR struct uart_dev_s *uartdev);
  296. static void usbhost_shutdown(FAR struct uart_dev_s *uartdev);
  297. static int usbhost_attach(FAR struct uart_dev_s *uartdev);
  298. static void usbhost_detach(FAR struct uart_dev_s *uartdev);
  299. static int usbhost_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
  300. static void usbhost_rxint(FAR struct uart_dev_s *uartdev, bool enable);
  301. static bool usbhost_rxavailable(FAR struct uart_dev_s *uartdev);
  302. #ifdef CONFIG_SERIAL_IFLOWCONTROL
  303. static bool usbhost_rxflowcontrol(FAR struct uart_dev_s *uartdev,
  304. unsigned int nbuffered, bool upper);
  305. #endif
  306. static void usbhost_txint(FAR struct uart_dev_s *uartdev, bool enable);
  307. static bool usbhost_txready(FAR struct uart_dev_s *uartdev);
  308. static bool usbhost_txempty(FAR struct uart_dev_s *uartdev);
  309. /****************************************************************************
  310. * Private Data
  311. ****************************************************************************/
  312. /* This structure provides the registry entry ID information that will be
  313. * used to associate the USB host CDC/ACM class to a connected USB
  314. * device.
  315. */
  316. static const const struct usbhost_id_s g_id[2] =
  317. {
  318. {
  319. USB_CLASS_CDC, /* base */
  320. CDC_SUBCLASS_NONE, /* subclass */
  321. CDC_PROTO_NONE, /* proto */
  322. 0, /* vid */
  323. 0 /* pid */
  324. },
  325. {
  326. USB_CLASS_CDC, /* base */
  327. CDC_SUBCLASS_ACM, /* subclass */
  328. CDC_PROTO_ATM, /* proto */
  329. 0, /* vid */
  330. 0 /* pid */
  331. }
  332. };
  333. /* This is the USB host CDC/ACM class's registry entry */
  334. static struct usbhost_registry_s g_cdcacm =
  335. {
  336. NULL, /* flink */
  337. usbhost_create, /* create */
  338. 2, /* nids */
  339. &g_id[0] /* id[] */
  340. };
  341. /* Serial driver lower half interface */
  342. static const struct uart_ops_s g_uart_ops =
  343. {
  344. usbhost_setup, /* setup */
  345. usbhost_shutdown, /* shutdown */
  346. usbhost_attach, /* attach */
  347. usbhost_detach, /* detach */
  348. usbhost_ioctl, /* ioctl */
  349. NULL , /* receive */
  350. usbhost_rxint, /* rxinit */
  351. usbhost_rxavailable, /* rxavailable */
  352. #ifdef CONFIG_SERIAL_IFLOWCONTROL
  353. usbhost_rxflowcontrol, /* rxflowcontrol */
  354. #endif
  355. NULL, /* send */
  356. usbhost_txint, /* txinit */
  357. usbhost_txready, /* txready */
  358. usbhost_txempty /* txempty */
  359. };
  360. /* This is an array of pre-allocated USB host CDC/ACM class instances */
  361. #if CONFIG_USBHOST_CDCACM_NPREALLOC > 0
  362. static struct usbhost_cdcacm_s g_prealloc[CONFIG_USBHOST_CDCACM_NPREALLOC];
  363. #endif
  364. /* This is a list of free, pre-allocated USB host CDC/ACM class instances */
  365. #if CONFIG_USBHOST_CDCACM_NPREALLOC > 0
  366. static FAR struct usbhost_freestate_s *g_freelist;
  367. #endif
  368. /* This is a bitmap that is used to allocate device minor numbers /dev/ttyACM[n]. */
  369. static uint32_t g_devinuse;
  370. /****************************************************************************
  371. * Private Functions
  372. ****************************************************************************/
  373. /****************************************************************************
  374. * Name: usbhost_takesem
  375. *
  376. * Description:
  377. * This is just a wrapper to handle the annoying behavior of semaphore
  378. * waits that return due to the receipt of a signal.
  379. *
  380. ****************************************************************************/
  381. static void usbhost_takesem(sem_t *sem)
  382. {
  383. /* Take the semaphore (perhaps waiting) */
  384. while (sem_wait(sem) != 0)
  385. {
  386. /* The only case that an error should occur here is if the wait was
  387. * awakened by a signal.
  388. */
  389. ASSERT(errno == EINTR);
  390. }
  391. }
  392. /****************************************************************************
  393. * Name: usbhost_allocclass
  394. *
  395. * Description:
  396. * This is really part of the logic that implements the create() method
  397. * of struct usbhost_registry_s. This function allocates memory for one
  398. * new class instance.
  399. *
  400. * Input Parameters:
  401. * None
  402. *
  403. * Returned Value:
  404. * On success, this function will return a non-NULL instance of struct
  405. * usbhost_class_s. NULL is returned on failure; this function will
  406. * will fail only if there are insufficient resources to create another
  407. * USB host class instance.
  408. *
  409. ****************************************************************************/
  410. #if CONFIG_USBHOST_CDCACM_NPREALLOC > 0
  411. static FAR struct usbhost_cdcacm_s *usbhost_allocclass(void)
  412. {
  413. FAR struct usbhost_freestate_s *entry;
  414. irqstate_t flags;
  415. /* We may be executing from an interrupt handler so we need to take one of
  416. * our pre-allocated class instances from the free list.
  417. */
  418. flags = enter_critical_section();
  419. entry = g_freelist;
  420. if (entry)
  421. {
  422. g_freelist = entry->flink;
  423. }
  424. leave_critical_section(flags);
  425. uinfo("Allocated: %p\n", entry);
  426. return (FAR struct usbhost_cdcacm_s *)entry;
  427. }
  428. #else
  429. static FAR struct usbhost_cdcacm_s *usbhost_allocclass(void)
  430. {
  431. FAR struct usbhost_cdcacm_s *priv;
  432. /* We are not executing from an interrupt handler so we can just call
  433. * kmm_malloc() to get memory for the class instance.
  434. */
  435. DEBUGASSERT(!up_interrupt_context());
  436. priv = (FAR struct usbhost_cdcacm_s *)kmm_malloc(sizeof(struct usbhost_cdcacm_s));
  437. uinfo("Allocated: %p\n", priv);
  438. return priv;
  439. }
  440. #endif
  441. /****************************************************************************
  442. * Name: usbhost_freeclass
  443. *
  444. * Description:
  445. * Free a class instance previously allocated by usbhost_allocclass().
  446. *
  447. * Input Parameters:
  448. * usbclass - A reference to the class instance to be freed.
  449. *
  450. * Returned Value:
  451. * None
  452. *
  453. ****************************************************************************/
  454. #if CONFIG_USBHOST_CDCACM_NPREALLOC > 0
  455. static void usbhost_freeclass(FAR struct usbhost_cdcacm_s *usbclass)
  456. {
  457. FAR struct usbhost_freestate_s *entry = (FAR struct usbhost_freestate_s *)usbclass;
  458. irqstate_t flags;
  459. DEBUGASSERT(entry != NULL);
  460. uinfo("Freeing: %p\n", entry);
  461. /* Just put the pre-allocated class structure back on the freelist */
  462. flags = enter_critical_section();
  463. entry->flink = g_freelist;
  464. g_freelist = entry;
  465. leave_critical_section(flags);
  466. }
  467. #else
  468. static void usbhost_freeclass(FAR struct usbhost_cdcacm_s *usbclass)
  469. {
  470. DEBUGASSERT(usbclass != NULL);
  471. /* Free the class instance (calling sched_kfree() in case we are executing
  472. * from an interrupt handler.
  473. */
  474. uinfo("Freeing: %p\n", usbclass);
  475. sched_kfree(usbclass);
  476. }
  477. #endif
  478. /****************************************************************************
  479. * Name: usbhost_devno_alloc
  480. *
  481. * Description:
  482. * Allocate a unique /dev/ttyACM[n] minor number in the range 0-31.
  483. *
  484. ****************************************************************************/
  485. static int usbhost_devno_alloc(FAR struct usbhost_cdcacm_s *priv)
  486. {
  487. irqstate_t flags;
  488. int devno;
  489. flags = enter_critical_section();
  490. for (devno = 0; devno < 32; devno++)
  491. {
  492. uint32_t bitno = 1 << devno;
  493. if ((g_devinuse & bitno) == 0)
  494. {
  495. g_devinuse |= bitno;
  496. priv->minor = devno;
  497. leave_critical_section(flags);
  498. return OK;
  499. }
  500. }
  501. leave_critical_section(flags);
  502. return -EMFILE;
  503. }
  504. /****************************************************************************
  505. * Name: usbhost_devno_free
  506. *
  507. * Description:
  508. * Free a /dev/ttyACM[n] minor number so that it can be used.
  509. *
  510. ****************************************************************************/
  511. static void usbhost_devno_free(FAR struct usbhost_cdcacm_s *priv)
  512. {
  513. int devno = priv->minor;
  514. if (devno >= 0 && devno < 32)
  515. {
  516. irqstate_t flags = enter_critical_section();
  517. g_devinuse &= ~(1 << devno);
  518. leave_critical_section(flags);
  519. }
  520. }
  521. /****************************************************************************
  522. * Name: usbhost_mkdevname
  523. *
  524. * Description:
  525. * Format a /dev/ttyACM[n] device name given a minor number.
  526. *
  527. ****************************************************************************/
  528. static inline void usbhost_mkdevname(FAR struct usbhost_cdcacm_s *priv,
  529. FAR char *devname)
  530. {
  531. (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, priv->minor);
  532. }
  533. /****************************************************************************
  534. * Name: usbhost_linecoding_send
  535. *
  536. * Description:
  537. * Format and send the on EP0.
  538. *
  539. * Input Parameters:
  540. * arg - A reference to the class instance to be destroyed.
  541. *
  542. * Returned Value:
  543. * None
  544. *
  545. ****************************************************************************/
  546. #ifdef HAVE_CTRL_INTERFACE
  547. static int usbhost_linecoding_send(FAR struct usbhost_cdcacm_s *priv)
  548. {
  549. FAR struct usbhost_hubport_s *hport;
  550. FAR struct cdc_linecoding_s *linecode;
  551. FAR struct usb_ctrlreq_s *ctrlreq;
  552. int ret;
  553. hport = priv->usbclass.hport;
  554. DEBUGASSERT(hport);
  555. /* Initialize the line coding structure */
  556. linecode = (FAR struct cdc_linecoding_s *)priv->linecode;
  557. usbhost_putle32(linecode->baud, priv->baud);
  558. linecode->stop = (priv->stop2) ? 2 : 0;
  559. linecode->parity = priv->parity;
  560. linecode->nbits = priv->nbits;
  561. /* Initialize the control request */
  562. ctrlreq = (FAR struct usb_ctrlreq_s *)priv->ctrlreq;
  563. ctrlreq->type = USB_DIR_OUT | USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE;
  564. ctrlreq->req = ACM_SET_LINE_CODING;
  565. usbhost_putle16(ctrlreq->value, 0);
  566. usbhost_putle16(ctrlreq->index, priv->ctrlif);
  567. usbhost_putle16(ctrlreq->len, SIZEOF_CDC_LINECODING);
  568. /* And send the request */
  569. ret = DRVR_CTRLOUT(hport->drvr, hport->ep0, ctrlreq, priv->linecode);
  570. if (ret < 0)
  571. {
  572. uerr("ERROR: DRVR_CTRLOUT failed: %d\n", ret);
  573. }
  574. return ret;
  575. }
  576. #endif
  577. /****************************************************************************
  578. * Name: usbhost_notification_work
  579. *
  580. * Description:
  581. * Handle receipt of an asynchronous notification from the CDC/ACM device
  582. *
  583. * Input Parameters:
  584. * arg - The argument provided with the asynchronous I/O was setup
  585. *
  586. * Returned Value:
  587. * None
  588. *
  589. * Assumptions:
  590. * Probably called from an interrupt handler.
  591. *
  592. ****************************************************************************/
  593. #ifdef HAVE_INTIN_ENDPOINT
  594. static void usbhost_notification_work(FAR void *arg)
  595. {
  596. FAR struct usbhost_cdcacm_s *priv;
  597. FAR struct usbhost_hubport_s *hport;
  598. FAR struct cdc_notification_s *inmsg;
  599. uint16_t value;
  600. uint16_t index;
  601. uint16_t len;
  602. int ret;
  603. priv = (FAR struct usbhost_cdcacm_s *)arg;
  604. DEBUGASSERT(priv);
  605. hport = priv->usbclass.hport;
  606. DEBUGASSERT(hport);
  607. /* Are we still connected? */
  608. if (!priv->disconnected && priv->intin)
  609. {
  610. /* Yes.. Was an interrupt IN message received correctly? */
  611. if (priv->nbytes >= 0)
  612. {
  613. /* Yes.. decode the notification */
  614. inmsg = (FAR struct cdc_notification_s *)priv->notification;
  615. value = usbhost_getle16(inmsg->value);
  616. index = usbhost_getle16(inmsg->index);
  617. len = usbhost_getle16(inmsg->len);
  618. uinfo("type: %02x notification: %02x value: %04x index: %04x len: %04x\n",
  619. inmsg->type, inmsg->notification, value, index, len);
  620. /* We care only about the SerialState notification */
  621. if ((inmsg->type == (USB_REQ_DIR_IN | USB_REQ_TYPE_CLASS |
  622. USB_REQ_RECIPIENT_INTERFACE)) &&
  623. (inmsg->notification == ACM_SERIAL_STATE) &&
  624. (value == 0) &&
  625. (index == priv->ctrlif) &&
  626. (len == 2))
  627. {
  628. uint16_t state = usbhost_getle16(inmsg->data);
  629. /* And we care only about the state of the DCD and DSR in the
  630. * the notification.
  631. */
  632. priv->dcd = ((state & CDC_UART_RXCARRIER) != 0);
  633. priv->dsr = ((state & CDC_UART_TXCARRIER) != 0);
  634. uinfo("ACM_SERIAL_STATE: DCD=%d DSR=%d\n",
  635. priv->dcd, priv->dsr);
  636. }
  637. }
  638. /* Setup to receive the next line status change event */
  639. ret = DRVR_ASYNCH(hport->drvr, priv->intin,
  640. (FAR uint8_t *)priv->notification,
  641. MAX_NOTIFICATION, usbhost_notification_callback,
  642. priv);
  643. if (ret < 0)
  644. {
  645. uerr("ERROR: DRVR_ASYNCH failed: %d\n", ret);
  646. }
  647. }
  648. }
  649. #endif
  650. /****************************************************************************
  651. * Name: usbhost_notification_callback
  652. *
  653. * Description:
  654. * Handle receipt of line status from the CDC/ACM device
  655. *
  656. * Input Parameters:
  657. * arg - The argument provided with the asynchronous I/O was setup
  658. * nbytes - The number of bytes actually transferred (or a negated errno
  659. * value;
  660. *
  661. * Returned Value:
  662. * None
  663. *
  664. * Assumptions:
  665. * Probably called from an interrupt handler.
  666. *
  667. ****************************************************************************/
  668. #ifdef HAVE_INTIN_ENDPOINT
  669. static void usbhost_notification_callback(FAR void *arg, ssize_t nbytes)
  670. {
  671. FAR struct usbhost_cdcacm_s *priv = (FAR struct usbhost_cdcacm_s *)arg;
  672. uint32_t delay = 0;
  673. DEBUGASSERT(priv);
  674. /* Are we still connected? */
  675. if (!priv->disconnected)
  676. {
  677. /* Check for a failure. On higher end host controllers, the
  678. * asynchronous transfer will pend until data is available (OHCI and
  679. * EHCI). On lower end host controllers (like STM32 and EFM32), the
  680. * transfer will fail immediately when the device NAKs the first
  681. * attempted interrupt IN transfer (with nbytes == -EAGAIN). In that
  682. * case (or in the case of other errors), we must fall back to
  683. * polling.
  684. */
  685. DEBUGASSERT(nbytes >= INT16_MIN && nbytes <= INT16_MAX);
  686. priv->nbytes = (int16_t)nbytes;
  687. if (nbytes < 0)
  688. {
  689. /* This debug output is good to know, but really a nuisance for
  690. * those configurations where we have to fall back to polling.
  691. * FIX: Don't output the message is the result is -EAGAIN.
  692. */
  693. #if defined(CONFIG_DEBUG_USB) && !defined(CONFIG_DEBUG_INFO)
  694. if (nbytes != -EAGAIN)
  695. #endif
  696. {
  697. uerr("ERROR: Transfer failed: %d\n", nbytes);
  698. }
  699. /* We don't know the nature of the failure, but we need to do all
  700. * that we can do to avoid a CPU hog error loop.
  701. *
  702. * Use the low-priority work queue and delay polling for the next
  703. * event. We want to use as little CPU bandwidth as possible in
  704. * this case.
  705. */
  706. delay = USBHOST_CDCACM_NTDELAY;
  707. }
  708. /* Make sure that the work structure available. There is a remote
  709. * chance that this may collide with a device disconnection event.
  710. */
  711. if (work_available(&priv->ntwork))
  712. {
  713. (void)work_queue(HPWORK, &priv->ntwork,
  714. (worker_t)usbhost_notification_work,
  715. priv, delay);
  716. }
  717. }
  718. }
  719. #endif
  720. /************************************************************************************
  721. * UART buffer data transfer
  722. ************************************************************************************/
  723. /****************************************************************************
  724. * Name: usbhost_txdata_work
  725. *
  726. * Description:
  727. * Send more OUT data to the attached CDC/ACM device.
  728. *
  729. * Input Parameters:
  730. * arg - A reference to the CDC/ACM class private data
  731. *
  732. * Returned Value:
  733. * None
  734. *
  735. ****************************************************************************/
  736. static void usbhost_txdata_work(FAR void *arg)
  737. {
  738. FAR struct usbhost_cdcacm_s *priv;
  739. FAR struct usbhost_hubport_s *hport;
  740. FAR struct uart_dev_s *uartdev;
  741. FAR struct uart_buffer_s *txbuf;
  742. ssize_t nwritten;
  743. int txndx;
  744. int txtail;
  745. int ret;
  746. priv = (FAR struct usbhost_cdcacm_s *)arg;
  747. DEBUGASSERT(priv);
  748. hport = priv->usbclass.hport;
  749. DEBUGASSERT(hport);
  750. uartdev = &priv->uartdev;
  751. txbuf = &uartdev->xmit;
  752. /* Do nothing if TX transmission is disabled */
  753. if (!priv->txena)
  754. {
  755. /* Terminate the work now *without* rescheduling */
  756. return;
  757. }
  758. /* Loop until The UART TX buffer is empty (or we become disconnected) */
  759. txtail = txbuf->tail;
  760. txndx = 0;
  761. while (txtail != txbuf->head && priv->txena && !priv->disconnected)
  762. {
  763. /* Copy data from the UART TX buffer until either 1) the UART TX
  764. * buffer has been emptied, or 2) the Bulk OUT buffer is full.
  765. */
  766. txndx = 0;
  767. while (txtail != txbuf->head && txndx < priv->pktsize)
  768. {
  769. /* Copy the next byte */
  770. priv->outbuf[txndx] = txbuf->buffer[txtail];
  771. /* Increment counters and indices */
  772. txndx++;
  773. if (++txtail >= txbuf->size)
  774. {
  775. txtail = 0;
  776. }
  777. }
  778. /* Save the updated tail pointer so that it cannot be sent again */
  779. txbuf->tail = txtail;
  780. /* Bytes were removed from the TX buffer. Inform any waiters that
  781. * there is space available in the TX buffer.
  782. */
  783. uart_datasent(uartdev);
  784. /* Send the filled TX buffer to the CDC/ACM device */
  785. nwritten = DRVR_TRANSFER(hport->drvr, priv->bulkout,
  786. priv->outbuf, txndx);
  787. if (nwritten < 0)
  788. {
  789. /* The most likely reason for a failure is that CDC/ACM device
  790. * NAK'ed our packet OR that the device has been disconnected.
  791. *
  792. * Just break out of the loop, rescheduling the work (unless
  793. * the device is disconnected).
  794. */
  795. uerr("ERROR: DRVR_TRANSFER for packet failed: %d\n", (int)nwritten);
  796. break;
  797. }
  798. }
  799. /* We get here because: 1) the UART TX buffer is empty and there is
  800. * nothing more to send, 2) the CDC/ACM device was not ready to accept our
  801. * data, or the device is no longer available.
  802. *
  803. * If the last packet sent was and even multiple of the packet size, then
  804. * we need to send a zero length packet (ZLP).
  805. */
  806. if (txndx == priv->pktsize && !priv->disconnected)
  807. {
  808. /* Send the ZLP to the CDC/ACM device */
  809. nwritten = DRVR_TRANSFER(hport->drvr, priv->bulkout,
  810. priv->outbuf, 0);
  811. if (nwritten < 0)
  812. {
  813. /* The most likely reason for a failure is that CDC/ACM device
  814. * NAK'ed our packet.
  815. */
  816. uerr("ERROR: DRVR_TRANSFER for ZLP failed: %d\n", (int)nwritten);
  817. }
  818. }
  819. /* Check again if TX reception is enabled and that the device is still
  820. * connected. These states could have changed since we started the
  821. * transfer.
  822. */
  823. if (priv->txena && !priv->disconnected)
  824. {
  825. /* Schedule TX data work to occur after a delay. */
  826. ret = work_queue(LPWORK, &priv->txwork, usbhost_txdata_work, priv,
  827. USBHOST_CDCACM_TXDELAY);
  828. DEBUGASSERT(ret >= 0);
  829. UNUSED(ret);
  830. }
  831. }
  832. /****************************************************************************
  833. * Name: usbhost_rxdata_work
  834. *
  835. * Description:
  836. * Get more IN data from the attached CDC/ACM device.
  837. *
  838. * Input Parameters:
  839. * arg - A reference to the CDC/ACM class private data
  840. *
  841. * Returned Value:
  842. * None
  843. *
  844. ****************************************************************************/
  845. static void usbhost_rxdata_work(FAR void *arg)
  846. {
  847. FAR struct usbhost_cdcacm_s *priv;
  848. FAR struct usbhost_hubport_s *hport;
  849. FAR struct uart_dev_s *uartdev;
  850. FAR struct uart_buffer_s *rxbuf;
  851. ssize_t nread;
  852. int nxfrd;
  853. int nexthead;
  854. int rxndx;
  855. int ret;
  856. priv = (FAR struct usbhost_cdcacm_s *)arg;
  857. DEBUGASSERT(priv);
  858. hport = priv->usbclass.hport;
  859. DEBUGASSERT(hport);
  860. uartdev = &priv->uartdev;
  861. rxbuf = &uartdev->recv;
  862. /* Get the index in the RX packet buffer where we will take the first
  863. * byte of data.
  864. */
  865. rxndx = priv->rxndx;
  866. nxfrd = 0;
  867. /* Get the index to the value of the UART RX buffer head AFTER the
  868. * first character has been stored. We need to know this in order
  869. * to test if the UART RX buffer is full.
  870. */
  871. nexthead = rxbuf->head + 1;
  872. if (nexthead >= rxbuf->size)
  873. {
  874. nexthead = 0;
  875. }
  876. /* Loop until either:
  877. *
  878. * 1. The UART RX buffer is full
  879. * 2. There is no more data available from the CDC/ACM device
  880. * 3. RX rec
  881. */
  882. #ifdef CONFIG_SERIAL_IFLOWCONTROL
  883. while (priv->rxena && priv->rts && !priv->disconnected)
  884. #else
  885. while (priv->rxena && !priv->disconnected)
  886. #endif
  887. {
  888. /* Stop now if there is no room for another character in the RX buffer. */
  889. if (nexthead == rxbuf->tail)
  890. {
  891. /* Break out of the loop, rescheduling the work */
  892. break;
  893. }
  894. /* Do we have any buffer RX data to transfer? */
  895. if (priv->nrxbytes < 1)
  896. {
  897. /* No.. Read more data from the CDC/ACM device */
  898. nread = DRVR_TRANSFER(hport->drvr, priv->bulkin,
  899. priv->inbuf, priv->pktsize);
  900. if (nread < 0)
  901. {
  902. /* The most likely reason for a failure is that the has no
  903. * data available now and NAK'ed the IN token OR that the
  904. * transfer was cancelled because the device was disconnected.
  905. *
  906. * Just break out of the loop, rescheduling the work (if the
  907. * device was not disconnected.
  908. */
  909. uerr("ERROR: DRVR_TRANSFER for packet failed: %d\n", (int)nread);
  910. break;
  911. }
  912. /* Save the number of bytes read. This might be zero if
  913. * a Zero Length Packet (ZLP) is received. The ZLP is
  914. * part of the bulk transfer protocol, but otherwise of
  915. * no interest to us.
  916. */
  917. priv->nrxbytes = (uint16_t)nread;
  918. rxndx = 0;
  919. /* Ignore ZLPs */
  920. if (nread == 0)
  921. {
  922. continue;
  923. }
  924. }
  925. /* Transfer one byte from the RX packet buffer into UART RX buffer */
  926. rxbuf->buffer[rxbuf->head] = priv->inbuf[rxndx];
  927. nxfrd++;
  928. /* Save the updated indices */
  929. rxbuf->head = nexthead;
  930. priv->rxndx = rxndx;
  931. /* Update the head point for for the next pass through the loop
  932. * handling. If nexthead incremented to rxbuf->tail, then the
  933. * RX buffer will and we will exit the loop at the top.
  934. */
  935. if (++nexthead >= rxbuf->size)
  936. {
  937. nexthead = 0;
  938. }
  939. /* Increment the index in the USB IN packet buffer. If the
  940. * index becomes equal to the number of bytes in the buffer, then
  941. * we have consumed all of the RX data.
  942. */
  943. if (++rxndx >= priv->nrxbytes)
  944. {
  945. /* In that case set the number of bytes in the buffer to zero.
  946. * This will force re-reading on the next time through the loop.
  947. */
  948. priv->nrxbytes = 0;
  949. priv->rxndx = 0;
  950. /* Inform any waiters there there is new incoming data available. */
  951. uart_datareceived(uartdev);
  952. nxfrd = 0;
  953. }
  954. }
  955. /* We break out to here: 1) the UART RX buffer is full, 2) the CDC/ACM
  956. * device is not ready to provide us with more serial data, or 3) the
  957. * device has been disconnected.
  958. *
  959. * Check if the device is still available: RX enabled, no RX flow
  960. * control in effect, and that the device is not disconnected. These
  961. * states could have changed since we started the transfer.
  962. */
  963. #ifdef CONFIG_SERIAL_IFLOWCONTROL
  964. if (priv->rxena && priv->rts && work_available(&priv->rxwork) && !priv->disconnected)
  965. #else
  966. if (priv->rxena && work_available(&priv->rxwork) && !priv->disconnected)
  967. #endif
  968. {
  969. /* Schedule RX data reception work to occur after a delay. This will
  970. * affect our responsive in certain cases. The delayed work, however,
  971. * will be cancelled and replaced with immediate work when the upper
  972. * layer demands more data.
  973. */
  974. ret = work_queue(LPWORK, &priv->rxwork, usbhost_rxdata_work, priv,
  975. USBHOST_CDCACM_RXDELAY);
  976. DEBUGASSERT(ret >= 0);
  977. UNUSED(ret);
  978. }
  979. /* If any bytes were added to the buffer, inform any waiters there there
  980. * is new incoming data available.
  981. */
  982. if (nxfrd)
  983. {
  984. uart_datareceived(uartdev);
  985. }
  986. }
  987. /****************************************************************************
  988. * Name: usbhost_destroy
  989. *
  990. * Description:
  991. * The USB CDC/ACM device has been disconnected and the reference count
  992. * on the USB host class instance has gone to 1.. Time to destroy the USB
  993. * host class instance.
  994. *
  995. * Input Parameters:
  996. * arg - A reference to the class instance to be destroyed.
  997. *
  998. * Returned Value:
  999. * None
  1000. *
  1001. ****************************************************************************/
  1002. static void usbhost_destroy(FAR void *arg)
  1003. {
  1004. FAR struct usbhost_cdcacm_s *priv = (FAR struct usbhost_cdcacm_s *)arg;
  1005. FAR struct usbhost_hubport_s *hport;
  1006. char devname[DEV_NAMELEN];
  1007. DEBUGASSERT(priv != NULL && priv->usbclass.hport != NULL);
  1008. hport = priv->usbclass.hport;
  1009. uinfo("crefs: %d\n", priv->crefs);
  1010. /* Unregister the serial lower half driver */
  1011. usbhost_mkdevname(priv, devname);
  1012. #warning Missing logic
  1013. /* Release the device name used by this connection */
  1014. usbhost_devno_free(priv);
  1015. /* Free the allocated endpoints */
  1016. if (priv->bulkout)
  1017. {
  1018. DRVR_EPFREE(hport->drvr, priv->bulkout);
  1019. }
  1020. if (priv->bulkin)
  1021. {
  1022. DRVR_EPFREE(hport->drvr, priv->bulkin);
  1023. }
  1024. #ifdef HAVE_INTIN_ENDPOINT
  1025. if (priv->intin)
  1026. {
  1027. DRVR_EPFREE(hport->drvr, priv->intin);
  1028. }
  1029. #endif
  1030. /* Free any transfer buffers */
  1031. usbhost_free_buffers(priv);
  1032. /* Destroy the semaphores */
  1033. sem_destroy(&priv->exclsem);
  1034. /* Disconnect the USB host device */
  1035. DRVR_DISCONNECT(hport->drvr, hport);
  1036. /* Free the function address assigned to this device */
  1037. usbhost_devaddr_destroy(hport, hport->funcaddr);
  1038. hport->funcaddr = 0;
  1039. /* And free the class instance. */
  1040. usbhost_freeclass(priv);
  1041. }
  1042. /****************************************************************************
  1043. * Name: usbhost_cfgdesc
  1044. *
  1045. * Description:
  1046. * This function implements the connect() method of struct
  1047. * usbhost_class_s. This method is a callback into the class
  1048. * implementation. It is used to provide the device's configuration
  1049. * descriptor to the class so that the class may initialize properly
  1050. *
  1051. * Input Parameters:
  1052. * priv - The USB host class instance.
  1053. * configdesc - A pointer to a uint8_t buffer container the configuration
  1054. * descriptor.
  1055. * desclen - The length in bytes of the configuration descriptor.
  1056. *
  1057. * Returned Value:
  1058. * On success, zero (OK) is returned. On a failure, a negated errno value is
  1059. * returned indicating the nature of the failure
  1060. *
  1061. * Assumptions:
  1062. * This function will *not* be called from an interrupt handler.
  1063. *
  1064. ****************************************************************************/
  1065. static int usbhost_cfgdesc(FAR struct usbhost_cdcacm_s *priv,
  1066. FAR const uint8_t *configdesc, int desclen)
  1067. {
  1068. FAR struct usbhost_hubport_s *hport;
  1069. FAR struct usb_cfgdesc_s *cfgdesc;
  1070. FAR struct usb_desc_s *desc;
  1071. FAR struct usbhost_epdesc_s bindesc;
  1072. FAR struct usbhost_epdesc_s boutdesc;
  1073. FAR struct usbhost_epdesc_s iindesc;
  1074. int remaining;
  1075. uint8_t found = 0;
  1076. uint8_t currif = 0;
  1077. int ret;
  1078. DEBUGASSERT(priv != NULL && priv->usbclass.hport &&
  1079. configdesc != NULL && desclen >= sizeof(struct usb_cfgdesc_s));
  1080. hport = priv->usbclass.hport;
  1081. /* Keep the compiler from complaining about uninitialized variables */
  1082. memset(&bindesc, 0, sizeof(struct usbhost_epdesc_s));
  1083. memset(&boutdesc, 0, sizeof(struct usbhost_epdesc_s));
  1084. memset(&iindesc, 0, sizeof(struct usbhost_epdesc_s));
  1085. /* Verify that we were passed a configuration descriptor */
  1086. cfgdesc = (FAR struct usb_cfgdesc_s *)configdesc;
  1087. if (cfgdesc->type != USB_DESC_TYPE_CONFIG)
  1088. {
  1089. return -EINVAL;
  1090. }
  1091. /* Get the total length of the configuration descriptor (little endian).
  1092. * It might be a good check to get the number of interfaces here too.
  1093. */
  1094. remaining = (int)usbhost_getle16(cfgdesc->totallen);
  1095. /* Skip to the next entry descriptor */
  1096. configdesc += cfgdesc->len;
  1097. remaining -= cfgdesc->len;
  1098. /* Loop where there are more descriptors to examine */
  1099. while (remaining >= sizeof(struct usb_desc_s))
  1100. {
  1101. /* What is the next descriptor? */
  1102. desc = (FAR struct usb_desc_s *)configdesc;
  1103. switch (desc->type)
  1104. {
  1105. /* Interface descriptor. The CDC/ACM device may include two
  1106. * interfaces:
  1107. *
  1108. * 1) A data interface which consists of two endpoints (bulk in +
  1109. * bulk out) and
  1110. * 2) A control interface which consists of one interrupt in
  1111. * endpoint.
  1112. */
  1113. case USB_DESC_TYPE_INTERFACE:
  1114. {
  1115. FAR struct usb_ifdesc_s *ifdesc = (FAR struct usb_ifdesc_s *)configdesc;
  1116. uinfo("Interface descriptor: class: %d subclass: %d proto: %d\n",
  1117. ifdesc->classid, ifdesc->subclass, ifdesc->protocol);
  1118. DEBUGASSERT(remaining >= USB_SIZEOF_IFDESC);
  1119. /* Check for the CDC/ACM data interface */
  1120. if (ifdesc->classid == USB_CLASS_CDC_DATA &&
  1121. (found & USBHOST_DATAIF_FOUND) == 0)
  1122. {
  1123. /* Save the data interface number and mark that the data
  1124. * interface found has been found.
  1125. */
  1126. priv->dataif = ifdesc->ifno;
  1127. found |= USBHOST_DATAIF_FOUND;
  1128. currif = USBHOST_DATAIF_FOUND;
  1129. }
  1130. #ifdef HAVE_CTRL_INTERFACE
  1131. else if (ifdesc->classid == USB_CLASS_CDC &&
  1132. (found & USBHOST_CTRLIF_FOUND) == 0)
  1133. {
  1134. /* Otherwise, tentatively assume that this is the control
  1135. * interface.
  1136. */
  1137. priv->ctrlif = ifdesc->ifno;
  1138. currif = USBHOST_CTRLIF_FOUND;
  1139. }
  1140. #endif
  1141. else
  1142. {
  1143. /* Its something else */
  1144. currif = 0;
  1145. }
  1146. }
  1147. break;
  1148. /* Endpoint descriptor. We expect two bulk endpoints, an IN and an
  1149. * OUT.
  1150. */
  1151. case USB_DESC_TYPE_ENDPOINT:
  1152. {
  1153. FAR struct usb_epdesc_s *epdesc = (FAR struct usb_epdesc_s *)configdesc;
  1154. uinfo("Endpoint descriptor: currif: %02x attr: %02x\n",
  1155. currif, epdesc->attr);
  1156. DEBUGASSERT(remaining >= USB_SIZEOF_EPDESC);
  1157. /* Check for a bulk endpoint. */
  1158. if (currif == USBHOST_DATAIF_FOUND &&
  1159. (epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) == USB_EP_ATTR_XFER_BULK)
  1160. {
  1161. /* Yes.. it is a bulk endpoint. IN or OUT? */
  1162. if (USB_ISEPOUT(epdesc->addr))
  1163. {
  1164. /* It is an OUT bulk endpoint. There should be only one
  1165. * bulk OUT endpoint.
  1166. */
  1167. if ((found & USBHOST_BULKOUT_FOUND) != 0)
  1168. {
  1169. /* Oops.. more than one endpoint. We don't know
  1170. * what to do with this.
  1171. */
  1172. return -EINVAL;
  1173. }
  1174. found |= USBHOST_BULKOUT_FOUND;
  1175. /* Save the bulk OUT endpoint information */
  1176. boutdesc.hport = hport;
  1177. boutdesc.addr = epdesc->addr & USB_EP_ADDR_NUMBER_MASK;
  1178. boutdesc.in = false;
  1179. boutdesc.xfrtype = USB_EP_ATTR_XFER_BULK;
  1180. boutdesc.interval = epdesc->interval;
  1181. boutdesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize);
  1182. uinfo("Bulk OUT EP addr:%d mxpacketsize:%d\n",
  1183. boutdesc.addr, boutdesc.mxpacketsize);
  1184. }
  1185. else
  1186. {
  1187. /* It is an IN bulk endpoint. There should be only one
  1188. * bulk IN endpoint.
  1189. */
  1190. if ((found & USBHOST_BULKIN_FOUND) != 0)
  1191. {
  1192. /* Oops.. more than one endpoint. We don't know
  1193. * what to do with this.
  1194. */
  1195. return -EINVAL;
  1196. }
  1197. found |= USBHOST_BULKIN_FOUND;
  1198. /* Save the bulk IN endpoint information */
  1199. bindesc.hport = hport;
  1200. bindesc.addr = epdesc->addr & USB_EP_ADDR_NUMBER_MASK;
  1201. bindesc.in = 1;
  1202. bindesc.xfrtype = USB_EP_ATTR_XFER_BULK;
  1203. bindesc.interval = epdesc->interval;
  1204. bindesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize);
  1205. uinfo("Bulk IN EP addr:%d mxpacketsize:%d\n",
  1206. bindesc.addr, bindesc.mxpacketsize);
  1207. }
  1208. }
  1209. #ifdef HAVE_CTRL_INTERFACE
  1210. /* Check for an interrupt IN endpoint. */
  1211. else if (currif == USBHOST_CTRLIF_FOUND &&
  1212. (epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) == USB_EP_ATTR_XFER_INT)
  1213. {
  1214. /* Yes.. it is a interrupt endpoint. IN or OUT? */
  1215. if (USB_ISEPIN(epdesc->addr))
  1216. {
  1217. #ifdef HAVE_INTIN_ENDPOINT
  1218. /* It is an IN interrupt endpoint. There should be only one
  1219. * interrupt IN endpoint.
  1220. */
  1221. if ((found & USBHOST_INTIN_FOUND) != 0)
  1222. {
  1223. /* Oops.. more than one. We don't know what to do
  1224. * with this.
  1225. */
  1226. return -EINVAL;
  1227. }
  1228. /* Let's pick this interface as the one and only control
  1229. * interface.
  1230. */
  1231. found |= (USBHOST_CTRLIF_FOUND | USBHOST_INTIN_FOUND);
  1232. /* Save the bulk OUT endpoint information */
  1233. iindesc.hport = hport;
  1234. iindesc.addr = epdesc->addr & USB_EP_ADDR_NUMBER_MASK;
  1235. iindesc.in = false;
  1236. iindesc.xfrtype = USB_EP_ATTR_XFER_INT;
  1237. iindesc.interval = epdesc->interval;
  1238. iindesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize);
  1239. uinfo("Interrupt IN EP addr:%d mxpacketsize:%d\n",
  1240. boutdesc.addr, boutdesc.mxpacketsize);
  1241. #else
  1242. found |= USBHOST_CTRLIF_FOUND;
  1243. #endif
  1244. }
  1245. }
  1246. #endif
  1247. }
  1248. break;
  1249. /* Other descriptors are just ignored for now */
  1250. default:
  1251. break;
  1252. }
  1253. /* If we found everything we need with this interface, then break out
  1254. * of the loop early.
  1255. */
  1256. if (found == USBHOST_ALLFOUND)
  1257. {
  1258. break;
  1259. }
  1260. /* Increment the address of the next descriptor */
  1261. configdesc += desc->len;
  1262. remaining -= desc->len;
  1263. }
  1264. /* Sanity checking... did we find all of things that we needed for the
  1265. * basic CDC/ACM data itnerface? NOTE: that the Control interface with
  1266. * the Interrupt IN endpoint is optional.
  1267. */
  1268. if ((found & USBHOST_MINFOUND) != USBHOST_MINFOUND)
  1269. {
  1270. uerr("ERROR: Found DATA IF:%s BULK IN:%s BULK OUT:%s\n",
  1271. (found & USBHOST_DATAIF_FOUND) != 0 ? "YES" : "NO",
  1272. (found & USBHOST_BULKIN_FOUND) != 0 ? "YES" : "NO",
  1273. (found & USBHOST_BULKOUT_FOUND) != 0 ? "YES" : "NO");
  1274. return -EINVAL;
  1275. }
  1276. /* We are good... Allocate the endpoints */
  1277. ret = DRVR_EPALLOC(hport->drvr, &boutdesc, &priv->bulkout);
  1278. if (ret < 0)
  1279. {
  1280. uerr("ERROR: Failed to allocate Bulk OUT endpoint\n");
  1281. return ret;
  1282. }
  1283. ret = DRVR_EPALLOC(hport->drvr, &bindesc, &priv->bulkin);
  1284. if (ret < 0)
  1285. {
  1286. uerr("ERROR: Failed to allocate Bulk IN endpoint\n");
  1287. (void)DRVR_EPFREE(hport->drvr, priv->bulkout);
  1288. return ret;
  1289. }
  1290. #ifdef HAVE_INTIN_ENDPOINT
  1291. /* The control interface with interrupt IN endpoint is optional */
  1292. if ((found & USBHOST_HAVE_CTRLIF) == USBHOST_HAVE_CTRLIF)
  1293. {
  1294. ret = DRVR_EPALLOC(hport->drvr, &iindesc, &priv->intin);
  1295. if (ret < 0)
  1296. {
  1297. uerr("ERROR: Failed to allocate Interrupt IN endpoint\n");
  1298. priv->intin = NULL;
  1299. }
  1300. }
  1301. #endif
  1302. uinfo("Endpoints allocated\n");
  1303. return OK;
  1304. }
  1305. /****************************************************************************
  1306. * Name: usbhost_getle16
  1307. *
  1308. * Description:
  1309. * Get a (possibly unaligned) 16-bit little endian value.
  1310. *
  1311. * Input Parameters:
  1312. * val - A pointer to the first byte of the little endian value.
  1313. *
  1314. * Returned Value:
  1315. * A uint16_t representing the whole 16-bit integer value
  1316. *
  1317. ****************************************************************************/
  1318. static inline uint16_t usbhost_getle16(const uint8_t *val)
  1319. {
  1320. return (uint16_t)val[1] << 8 | (uint16_t)val[0];
  1321. }
  1322. /****************************************************************************
  1323. * Name: usbhost_getbe16
  1324. *
  1325. * Description:
  1326. * Get a (possibly unaligned) 16-bit big endian value.
  1327. *
  1328. * Input Parameters:
  1329. * val - A pointer to the first byte of the big endian value.
  1330. *
  1331. * Returned Value:
  1332. * A uint16_t representing the whole 16-bit integer value
  1333. *
  1334. ****************************************************************************/
  1335. static inline uint16_t usbhost_getbe16(const uint8_t *val)
  1336. {
  1337. return (uint16_t)val[0] << 8 | (uint16_t)val[1];
  1338. }
  1339. /****************************************************************************
  1340. * Name: usbhost_putle16
  1341. *
  1342. * Description:
  1343. * Put a (possibly unaligned) 16-bit little endian value.
  1344. *
  1345. * Input Parameters:
  1346. * dest - A pointer to the first byte to save the little endian value.
  1347. * val - The 16-bit value to be saved.
  1348. *
  1349. * Returned Value:
  1350. * None
  1351. *
  1352. ****************************************************************************/
  1353. static void usbhost_putle16(uint8_t *dest, uint16_t val)
  1354. {
  1355. dest[0] = val & 0xff; /* Little endian means LS byte first in byte stream */
  1356. dest[1] = val >> 8;
  1357. }
  1358. /****************************************************************************
  1359. * Name: usbhost_putle32
  1360. *
  1361. * Description:
  1362. * Put a (possibly unaligned) 32-bit little endian value.
  1363. *
  1364. * Input Parameters:
  1365. * dest - A pointer to the first byte to save the little endian value.
  1366. * val - The 32-bit value to be saved.
  1367. *
  1368. * Returned Value:
  1369. * None
  1370. *
  1371. ****************************************************************************/
  1372. #ifdef HAVE_CTRL_INTERFACE
  1373. static void usbhost_putle32(uint8_t *dest, uint32_t val)
  1374. {
  1375. /* Little endian means LS halfword first in byte stream */
  1376. usbhost_putle16(dest, (uint16_t)(val & 0xffff));
  1377. usbhost_putle16(dest+2, (uint16_t)(val >> 16));
  1378. }
  1379. #endif
  1380. /****************************************************************************
  1381. * Name: usbhost_alloc_buffers
  1382. *
  1383. * Description:
  1384. * Allocate transfer buffer memory.
  1385. *
  1386. * Input Parameters:
  1387. * priv - A reference to the class instance.
  1388. *
  1389. * Returned Value:
  1390. * On sucess, zero (OK) is returned. On failure, an negated errno value
  1391. * is returned to indicate the nature of the failure.
  1392. *
  1393. ****************************************************************************/
  1394. static int usbhost_alloc_buffers(FAR struct usbhost_cdcacm_s *priv)
  1395. {
  1396. FAR struct usbhost_hubport_s *hport;
  1397. size_t maxlen;
  1398. int ret;
  1399. DEBUGASSERT(priv != NULL && priv->usbclass.hport != NULL &&
  1400. priv->linecode == NULL);
  1401. hport = priv->usbclass.hport;
  1402. /* Allocate memory for control requests */
  1403. ret = DRVR_ALLOC(hport->drvr, (FAR uint8_t **)&priv->ctrlreq, &maxlen);
  1404. if (ret < 0)
  1405. {
  1406. uerr("ERROR: DRVR_ALLOC of ctrlreq failed: %d\n", ret);
  1407. goto errout;
  1408. }
  1409. DEBUGASSERT(maxlen >= sizeof(struct usb_ctrlreq_s));
  1410. /* Allocate buffer for sending line coding data. */
  1411. ret = DRVR_IOALLOC(hport->drvr, &priv->linecode,
  1412. sizeof(struct cdc_linecoding_s));
  1413. if (ret < 0)
  1414. {
  1415. uerr("ERROR: DRVR_IOALLOC of line coding failed: %d (%d bytes)\n",
  1416. ret, sizeof(struct cdc_linecoding_s));
  1417. goto errout;
  1418. }
  1419. #ifdef HAVE_INTIN_ENDPOINT
  1420. /* Allocate (optional) buffer for receiving line status data. */
  1421. if (priv->intin)
  1422. {
  1423. ret = DRVR_IOALLOC(hport->drvr, &priv->notification, MAX_NOTIFICATION);
  1424. if (ret < 0)
  1425. {
  1426. uerr("ERROR: DRVR_IOALLOC of line status failed: %d (%d bytes)\n",
  1427. ret, MAX_NOTIFICATION);
  1428. goto errout;
  1429. }
  1430. }
  1431. #endif
  1432. /* Set the size of Bulk IN and OUT buffers to the max packet size */
  1433. priv->pktsize = (hport->speed == USB_SPEED_HIGH) ? 512 : 64;
  1434. /* Allocate a RX buffer for Bulk IN transfers */
  1435. ret = DRVR_IOALLOC(hport->drvr, &priv->inbuf, priv->pktsize);
  1436. if (ret < 0)
  1437. {
  1438. uerr("ERROR: DRVR_IOALLOC of Bulk IN buffer failed: %d (%d bytes)\n",
  1439. ret, priv->pktsize);
  1440. goto errout;
  1441. }
  1442. /* Allocate a TX buffer for Bulk IN transfers */
  1443. ret = DRVR_IOALLOC(hport->drvr, &priv->outbuf, priv->pktsize);
  1444. if (ret < 0)
  1445. {
  1446. uerr("ERROR: DRVR_IOALLOC of Bulk OUT buffer failed: %d (%d bytes)\n",
  1447. ret, priv->pktsize);
  1448. goto errout;
  1449. }
  1450. return OK;
  1451. errout:
  1452. usbhost_free_buffers(priv);
  1453. return ret;
  1454. }
  1455. /****************************************************************************
  1456. * Name: usbhost_free_buffers
  1457. *
  1458. * Description:
  1459. * Free transfer buffer memory.
  1460. *
  1461. * Input Parameters:
  1462. * priv - A reference to the class instance.
  1463. *
  1464. * Returned Value:
  1465. * None
  1466. *
  1467. ****************************************************************************/
  1468. static void usbhost_free_buffers(FAR struct usbhost_cdcacm_s *priv)
  1469. {
  1470. FAR struct usbhost_hubport_s *hport;
  1471. DEBUGASSERT(priv != NULL && priv->usbclass.hport != NULL);
  1472. hport = priv->usbclass.hport;
  1473. if (priv->ctrlreq)
  1474. {
  1475. (void)DRVR_FREE(hport->drvr, priv->ctrlreq);
  1476. }
  1477. if (priv->linecode)
  1478. {
  1479. (void)DRVR_IOFREE(hport->drvr, priv->linecode);
  1480. }
  1481. if (priv->notification)
  1482. {
  1483. (void)DRVR_IOFREE(hport->drvr, priv->notification);
  1484. }
  1485. if (priv->inbuf)
  1486. {
  1487. (void)DRVR_IOFREE(hport->drvr, priv->inbuf);
  1488. }
  1489. if (priv->outbuf)
  1490. {
  1491. (void)DRVR_IOFREE(hport->drvr, priv->outbuf);
  1492. }
  1493. priv->pktsize = 0;
  1494. priv->ctrlreq = NULL;
  1495. priv->linecode = NULL;
  1496. priv->notification = NULL;
  1497. priv->inbuf = NULL;
  1498. priv->outbuf = NULL;
  1499. }
  1500. /****************************************************************************
  1501. * struct usbhost_registry_s methods
  1502. ****************************************************************************/
  1503. /****************************************************************************
  1504. * Name: usbhost_create
  1505. *
  1506. * Description:
  1507. * This function implements the create() method of struct usbhost_registry_s.
  1508. * The create() method is a callback into the class implementation. It is
  1509. * used to (1) create a new instance of the USB host class state and to (2)
  1510. * bind a USB host driver "session" to the class instance. Use of this
  1511. * create() method will support environments where there may be multiple
  1512. * USB ports and multiple USB devices simultaneously connected.
  1513. *
  1514. * Input Parameters:
  1515. * hport - The hub port that manages the new class instance.
  1516. * id - In the case where the device supports multiple base classes,
  1517. * subclasses, or protocols, this specifies which to configure for.
  1518. *
  1519. * Returned Value:
  1520. * On success, this function will return a non-NULL instance of struct
  1521. * usbhost_class_s that can be used by the USB host driver to communicate
  1522. * with the USB host class. NULL is returned on failure; this function
  1523. * will fail only if the hport input parameter is NULL or if there are
  1524. * insufficient resources to create another USB host class instance.
  1525. *
  1526. ****************************************************************************/
  1527. static FAR struct usbhost_class_s *
  1528. usbhost_create(FAR struct usbhost_hubport_s *hport,
  1529. FAR const struct usbhost_id_s *id)
  1530. {
  1531. FAR struct usbhost_cdcacm_s *priv;
  1532. FAR struct uart_dev_s *uartdev;
  1533. /* Allocate a USB host CDC/ACM class instance */
  1534. priv = usbhost_allocclass();
  1535. if (priv)
  1536. {
  1537. /* Initialize the allocated CDC/ACM class instance */
  1538. memset(priv, 0, sizeof(struct usbhost_cdcacm_s));
  1539. /* Assign a device number to this class instance */
  1540. if (usbhost_devno_alloc(priv) == OK)
  1541. {
  1542. /* Initialize class method function pointers */
  1543. priv->usbclass.hport = hport;
  1544. priv->usbclass.connect = usbhost_connect;
  1545. priv->usbclass.disconnected = usbhost_disconnected;
  1546. /* The initial reference count is 1... One reference is held by the driver */
  1547. priv->crefs = 1;
  1548. /* Initialize semaphores (this works okay in the interrupt context) */
  1549. sem_init(&priv->exclsem, 0, 1);
  1550. /* Set up the serial lower-half interface */
  1551. uartdev = &priv->uartdev;
  1552. uartdev->recv.size = CONFIG_USBHOST_CDCACM_RXBUFSIZE;
  1553. uartdev->recv.buffer = priv->rxbuffer;
  1554. uartdev->xmit.size = CONFIG_USBHOST_CDCACM_TXBUFSIZE;
  1555. uartdev->xmit.buffer = priv->txbuffer;
  1556. uartdev->ops = &g_uart_ops;
  1557. uartdev->priv = priv;
  1558. /* Set up the initial line status */
  1559. priv->baud = CONFIG_USBHOST_CDCACM_BAUD;
  1560. priv->nbits = CONFIG_USBHOST_CDCACM_BITS;
  1561. priv->parity = CONFIG_USBHOST_CDCACM_PARITY;
  1562. priv->stop2 = CONFIG_USBHOST_CDCACM_2STOP;
  1563. #ifdef CONFIG_SERIAL_IFLOWCONTROL
  1564. priv->rts = true;
  1565. #endif
  1566. /* Return the instance of the USB CDC/ACM class */
  1567. return &priv->usbclass;
  1568. }
  1569. }
  1570. /* An error occurred. Free the allocation and return NULL on all failures */
  1571. if (priv)
  1572. {
  1573. usbhost_freeclass(priv);
  1574. }
  1575. return NULL;
  1576. }
  1577. /****************************************************************************
  1578. * struct usbhost_class_s methods
  1579. ****************************************************************************/
  1580. /****************************************************************************
  1581. * Name: usbhost_connect
  1582. *
  1583. * Description:
  1584. * This function implements the connect() method of struct
  1585. * usbhost_class_s. This method is a callback into the class
  1586. * implementation. It is used to provide the device's configuration
  1587. * descriptor to the class so that the class may initialize properly
  1588. *
  1589. * Input Parameters:
  1590. * usbclass - The USB host class entry previously obtained from a call to
  1591. * create().
  1592. * configdesc - A pointer to a uint8_t buffer container the configuration
  1593. * descriptor.
  1594. * desclen - The length in bytes of the configuration descriptor.
  1595. *
  1596. * Returned Value:
  1597. * On success, zero (OK) is returned. On a failure, a negated errno value is
  1598. * returned indicating the nature of the failure
  1599. *
  1600. * NOTE that the class instance remains valid upon return with a failure. It is
  1601. * the responsibility of the higher level enumeration logic to call
  1602. * CLASS_DISCONNECTED to free up the class driver resources.
  1603. *
  1604. * Assumptions:
  1605. * - This function will *not* be called from an interrupt handler.
  1606. * - If this function returns an error, the USB host controller driver
  1607. * must call to DISCONNECTED method to recover from the error
  1608. *
  1609. ****************************************************************************/
  1610. static int usbhost_connect(FAR struct usbhost_class_s *usbclass,
  1611. FAR const uint8_t *configdesc, int desclen)
  1612. {
  1613. FAR struct usbhost_cdcacm_s *priv = (FAR struct usbhost_cdcacm_s *)usbclass;
  1614. #ifdef HAVE_INTIN_ENDPOINT
  1615. FAR struct usbhost_hubport_s *hport;
  1616. #endif
  1617. char devname[DEV_NAMELEN];
  1618. int ret;
  1619. DEBUGASSERT(priv != NULL &&
  1620. configdesc != NULL &&
  1621. desclen >= sizeof(struct usb_cfgdesc_s));
  1622. #ifdef HAVE_INTIN_ENDPOINT
  1623. hport = priv->usbclass.hport;
  1624. DEBUGASSERT(hport);
  1625. #endif
  1626. /* Get exclusive access to the device structure */
  1627. usbhost_takesem(&priv->exclsem);
  1628. /* Increment the reference count. This will prevent usbhost_destroy() from
  1629. * being called asynchronously if the device is removed.
  1630. */
  1631. priv->crefs++;
  1632. DEBUGASSERT(priv->crefs == 2);
  1633. /* Parse the configuration descriptor to get the bulk I/O endpoints */
  1634. ret = usbhost_cfgdesc(priv, configdesc, desclen);
  1635. if (ret < 0)
  1636. {
  1637. uerr("ERROR: usbhost_cfgdesc() failed: %d\n", ret);
  1638. goto errout;
  1639. }
  1640. /* Set aside a transfer buffer for exclusive use by the CDC/ACM driver */
  1641. ret = usbhost_alloc_buffers(priv);
  1642. if (ret < 0)
  1643. {
  1644. uerr("ERROR: Failed to allocate transfer buffer\n");
  1645. goto errout;
  1646. }
  1647. #ifdef HAVE_CTRL_INTERFACE
  1648. /* Send the initial line encoding */
  1649. ret = usbhost_linecoding_send(priv);
  1650. if (ret < 0)
  1651. {
  1652. uerr("ERROR: usbhost_linecoding_send() failed: %d\n", ret);
  1653. }
  1654. #endif
  1655. /* Register the lower half serial instance with the upper half serial
  1656. * driver */
  1657. usbhost_mkdevname(priv, devname);
  1658. uinfo("Register device: %s\n", devname);
  1659. ret = uart_register(devname, &priv->uartdev);
  1660. if (ret < 0)
  1661. {
  1662. uerr("ERROR: uart_register() failed: %d\n", ret);
  1663. goto errout;
  1664. }
  1665. #ifdef HAVE_INTIN_ENDPOINT
  1666. /* Do we have an interrupt IN endpoint? */
  1667. if (priv->intin)
  1668. {
  1669. /* Begin monitoring of port status change events */
  1670. uinfo("Start notification monitoring\n");
  1671. ret = DRVR_ASYNCH(hport->drvr, priv->intin,
  1672. (FAR uint8_t *)priv->notification,
  1673. MAX_NOTIFICATION, usbhost_notification_callback,
  1674. priv);
  1675. if (ret < 0)
  1676. {
  1677. uerr("ERROR: DRVR_ASYNCH failed: %d\n", ret);
  1678. }
  1679. }
  1680. #endif
  1681. errout:
  1682. /* Decrement the reference count. We incremented the reference count
  1683. * above so that usbhost_destroy() could not be called. We now have to
  1684. * be concerned about asynchronous modification of crefs because the
  1685. * serial driver has been registered.
  1686. */
  1687. DEBUGASSERT(priv->crefs >= 2);
  1688. priv->crefs--;
  1689. /* Release the semaphore... there is a race condition here.
  1690. * Decrementing the reference count and releasing the semaphore
  1691. * allows usbhost_destroy() to execute (on the worker thread);
  1692. * the class driver instance could get destroyed before we are
  1693. * ready to handle it!
  1694. */
  1695. usbhost_givesem(&priv->exclsem);
  1696. return ret;
  1697. }
  1698. /****************************************************************************
  1699. * Name: usbhost_disconnected
  1700. *
  1701. * Description:
  1702. * This function implements the disconnected() method of struct
  1703. * usbhost_class_s. This method is a callback into the class
  1704. * implementation. It is used to inform the class that the USB device has
  1705. * been disconnected.
  1706. *
  1707. * Input Parameters:
  1708. * usbclass - The USB host class entry previously obtained from a call to
  1709. * create().
  1710. *
  1711. * Returned Value:
  1712. * On success, zero (OK) is returned. On a failure, a negated errno value
  1713. * is returned indicating the nature of the failure
  1714. *
  1715. * Assumptions:
  1716. * This function may be called from an interrupt handler.
  1717. *
  1718. ****************************************************************************/
  1719. static int usbhost_disconnected(struct usbhost_class_s *usbclass)
  1720. {
  1721. FAR struct usbhost_cdcacm_s *priv = (FAR struct usbhost_cdcacm_s *)usbclass;
  1722. FAR struct usbhost_hubport_s *hport;
  1723. irqstate_t flags;
  1724. int ret;
  1725. DEBUGASSERT(priv != NULL && priv->usbclass.hport != NULL);
  1726. hport = priv->usbclass.hport;
  1727. /* Set an indication to any users of the CDC/ACM device that the device
  1728. * is no longer available.
  1729. */
  1730. flags = enter_critical_section();
  1731. priv->disconnected = true;
  1732. /* Let the upper half driver know that serial device is no longer
  1733. * connected.
  1734. */
  1735. uart_connected(&priv->uartdev, false);
  1736. /* Cancel any ongoing Bulk transfers */
  1737. ret = DRVR_CANCEL(hport->drvr, priv->bulkin);
  1738. if (ret < 0)
  1739. {
  1740. uerr("ERROR: Bulk IN DRVR_CANCEL failed: %d\n", ret);
  1741. }
  1742. ret = DRVR_CANCEL(hport->drvr, priv->bulkout);
  1743. if (ret < 0)
  1744. {
  1745. uerr("ERROR: Bulk OUT DRVR_CANCEL failed: %d\n", ret);
  1746. }
  1747. #ifdef HAVE_INTIN_ENDPOINT
  1748. /* Cancel any pending asynchronous I/O */
  1749. if (priv->intin)
  1750. {
  1751. int ret = DRVR_CANCEL(hport->drvr, priv->intin);
  1752. if (ret < 0)
  1753. {
  1754. uerr("ERROR: Interrupt IN DRVR_CANCEL failed: %d\n", ret);
  1755. }
  1756. }
  1757. #endif
  1758. /* Now check the number of references on the class instance. If it is one,
  1759. * then we can free the class instance now. Otherwise, we will have to
  1760. * wait until the holders of the references free them by closing the
  1761. * serial driver.
  1762. */
  1763. uinfo("crefs: %d\n", priv->crefs);
  1764. if (priv->crefs == 1)
  1765. {
  1766. /* Destroy the class instance. If we are executing from an interrupt
  1767. * handler, then defer the destruction to the worker thread.
  1768. * Otherwise, destroy the instance now.
  1769. */
  1770. if (up_interrupt_context())
  1771. {
  1772. /* Destroy the instance on the worker thread. */
  1773. uinfo("Queuing destruction: worker %p->%p\n",
  1774. priv->ntwork.worker, usbhost_destroy);
  1775. DEBUGASSERT(work_available(&priv->ntwork));
  1776. (void)work_queue(HPWORK, &priv->ntwork, usbhost_destroy, priv, 0);
  1777. }
  1778. else
  1779. {
  1780. /* Do the work now */
  1781. usbhost_destroy(priv);
  1782. }
  1783. }
  1784. leave_critical_section(flags);
  1785. return OK;
  1786. }
  1787. /****************************************************************************
  1788. * Serial Lower-Half Interfaces
  1789. ****************************************************************************/
  1790. /****************************************************************************
  1791. * Name: usbhost_setup
  1792. *
  1793. * Description:
  1794. * Configure the USART baud, bits, parity, etc. This method is called the
  1795. * first time that the serial port is opened.
  1796. *
  1797. ****************************************************************************/
  1798. static int usbhost_setup(FAR struct uart_dev_s *uartdev)
  1799. {
  1800. FAR struct usbhost_cdcacm_s *priv;
  1801. irqstate_t flags;
  1802. int ret;
  1803. uinfo("Entry\n");
  1804. DEBUGASSERT(uartdev && uartdev->priv);
  1805. priv = (FAR struct usbhost_cdcacm_s *)uartdev->priv;
  1806. /* Make sure that we have exclusive access to the private data structure */
  1807. DEBUGASSERT(priv->crefs > 0 && priv->crefs < USBHOST_MAX_CREFS);
  1808. usbhost_takesem(&priv->exclsem);
  1809. /* Check if the CDC/ACM device is still connected. We need to disable
  1810. * interrupts momentarily to assure that there are no asynchronous
  1811. * isconnect events.
  1812. */
  1813. flags = enter_critical_section();
  1814. if (priv->disconnected)
  1815. {
  1816. /* No... the block driver is no longer bound to the class. That means that
  1817. * the USB CDC/ACM device is no longer connected. Refuse any further
  1818. * attempts to open the driver.
  1819. */
  1820. ret = -ENODEV;
  1821. }
  1822. else
  1823. {
  1824. /* Otherwise, just increment the reference count on the driver */
  1825. priv->crefs++;
  1826. ret = OK;
  1827. }
  1828. leave_critical_section(flags);
  1829. usbhost_givesem(&priv->exclsem);
  1830. return ret;
  1831. }
  1832. /****************************************************************************
  1833. * Name: usbhost_shutdown
  1834. *
  1835. * Description:
  1836. * Disable the USART. This method is called when the serial
  1837. * port is closed
  1838. *
  1839. ****************************************************************************/
  1840. static void usbhost_shutdown(FAR struct uart_dev_s *uartdev)
  1841. {
  1842. FAR struct usbhost_cdcacm_s *priv;
  1843. irqstate_t flags;
  1844. uinfo("Entry\n");
  1845. DEBUGASSERT(uartdev && uartdev->priv);
  1846. priv = (FAR struct usbhost_cdcacm_s *)uartdev->priv;
  1847. /* Decrement the reference count on the block driver */
  1848. DEBUGASSERT(priv->crefs > 1);
  1849. usbhost_takesem(&priv->exclsem);
  1850. priv->crefs--;
  1851. /* Release the semaphore. The following operations when crefs == 1 are
  1852. * safe because we know that there is no outstanding open references to
  1853. * the block driver.
  1854. */
  1855. usbhost_givesem(&priv->exclsem);
  1856. /* We need to disable interrupts momentarily to assure that there are
  1857. * no asynchronous disconnect events.
  1858. */
  1859. flags = enter_critical_section();
  1860. /* Check if the USB CDC/ACM device is still connected. If the
  1861. * CDC/ACM device is not connected and the reference count just
  1862. * decremented to one, then unregister the block driver and free
  1863. * the class instance.
  1864. */
  1865. if (priv->crefs <= 1 && priv->disconnected)
  1866. {
  1867. /* Destroy the class instance */
  1868. DEBUGASSERT(priv->crefs == 1);
  1869. usbhost_destroy(priv);
  1870. }
  1871. leave_critical_section(flags);
  1872. }
  1873. /****************************************************************************
  1874. * Name: usbhost_attach
  1875. *
  1876. * Description:
  1877. * Configure the USART to operation in interrupt driven mode. This method is
  1878. * called when the serial port is opened. Normally, this is just after the
  1879. * the setup() method is called, however, the serial console may operate in
  1880. * a non-interrupt driven mode during the boot phase.
  1881. *
  1882. * RX and TX interrupts are not enabled when by the attach method (unless the
  1883. * hardware supports multiple levels of interrupt enabling). The RX and TX
  1884. * interrupts are not enabled until the txint() and rxint() methods are called.
  1885. *
  1886. ****************************************************************************/
  1887. static int usbhost_attach(FAR struct uart_dev_s *uartdev)
  1888. {
  1889. return OK;
  1890. }
  1891. /****************************************************************************
  1892. * Name: usbhost_detach
  1893. *
  1894. * Description:
  1895. * Detach USART interrupts. This method is called when the serial port is
  1896. * closed normally just before the shutdown method is called. The exception
  1897. * is the serial console which is never shutdown.
  1898. *
  1899. ****************************************************************************/
  1900. static void usbhost_detach(FAR struct uart_dev_s *uartdev)
  1901. {
  1902. }
  1903. /****************************************************************************
  1904. * Name: usbhost_ioctl
  1905. *
  1906. * Description:
  1907. * All ioctl calls will be routed through this method
  1908. *
  1909. ****************************************************************************/
  1910. static int usbhost_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
  1911. {
  1912. struct inode *inode;
  1913. struct usbhost_cdcacm_s *priv;
  1914. int ret;
  1915. uinfo("Entry\n");
  1916. DEBUGASSERT(filep && filep->f_inode);
  1917. inode = filep->f_inode;
  1918. DEBUGASSERT(inode && inode->i_private);
  1919. priv = (FAR struct usbhost_cdcacm_s *)inode->i_private;
  1920. /* Check if the CDC/ACM device is still connected */
  1921. if (priv->disconnected)
  1922. {
  1923. /* No... the serial device has been disconnecgted. Refuse to process
  1924. * any ioctl commands.
  1925. */
  1926. ret = -ENODEV;
  1927. }
  1928. else
  1929. {
  1930. /* Process the IOCTL by command */
  1931. usbhost_takesem(&priv->exclsem);
  1932. switch (cmd)
  1933. {
  1934. #ifdef CONFIG_SERIAL_TIOCSERGSTRUCT
  1935. case TIOCSERGSTRUCT:
  1936. {
  1937. FAR struct usbhost_cdcacm_s *user =
  1938. (FAR struct usbhost_cdcacm_s *)arg;
  1939. if (!user)
  1940. {
  1941. ret = -EINVAL;
  1942. }
  1943. else
  1944. {
  1945. memcpy(user, uartdev, sizeof(struct usbhost_cdcacm_s));
  1946. }
  1947. }
  1948. break;
  1949. #endif
  1950. #ifdef CONFIG_SERIAL_TERMIOS
  1951. case TCGETS:
  1952. {
  1953. FAR struct termios *termiosp = (FAR struct termios *)arg;
  1954. if (!termiosp)
  1955. {
  1956. ret = -EINVAL;
  1957. break;
  1958. }
  1959. cfsetispeed(termiosp, priv->baud);
  1960. termiosp->c_cflag =
  1961. ((priv->parity != 0) ? PARENB : 0) |
  1962. ((priv->parity == 1) ? PARODD : 0) |
  1963. ((priv->stop2) ? CSTOPB : 0)
  1964. #ifdef CONFIG_SERIAL_OFLOWCONTROL
  1965. | ((priv->oflow) ? CCTS_OFLOW : 0)
  1966. #endif
  1967. #ifdef CONFIG_SERIAL_IFLOWCONTROL
  1968. | ((priv->iflow) ? CRTS_IFLOW : 0)
  1969. #endif
  1970. ;
  1971. switch (priv->bits)
  1972. {
  1973. case 5:
  1974. termiosp->c_cflag |= CS5;
  1975. break;
  1976. case 6:
  1977. termiosp->c_cflag |= CS6;
  1978. break;
  1979. case 7:
  1980. termiosp->c_cflag |= CS7;
  1981. break;
  1982. default: /* 16-bits? */
  1983. case 8:
  1984. termiosp->c_cflag |= CS8;
  1985. break;
  1986. }
  1987. }
  1988. break;
  1989. case TCSETS:
  1990. {
  1991. FAR struct termios *termiosp = (FAR struct termios *)arg;
  1992. #ifdef CONFIG_SERIAL_IFLOWCONTROL
  1993. bool iflow;
  1994. #endif
  1995. if (!termiosp)
  1996. {
  1997. ret = -EINVAL;
  1998. break;
  1999. }
  2000. if (termiosp->c_cflag & PARENB)
  2001. {
  2002. priv->parity = (termiosp->c_cflag & PARODD) ? 1 : 2;
  2003. }
  2004. else
  2005. {
  2006. priv->parity = 0;
  2007. }
  2008. priv->stopbits2 = (termiosp->c_cflag & CSTOPB) != 0;
  2009. #ifdef CONFIG_SERIAL_OFLOWCONTROL
  2010. priv->oflow = (termiosp->c_cflag & CCTS_OFLOW) != 0;
  2011. #endif
  2012. #ifdef CONFIG_SERIAL_IFLOWCONTROL
  2013. iflow = priv->iflow;
  2014. priv->iflow = (termiosp->c_cflag & CRTS_IFLOW) != 0;
  2015. #endif
  2016. switch (termiosp->c_flag & CSIZE)
  2017. {
  2018. case C5:
  2019. priv->bits = 5;
  2020. break;
  2021. case C6:
  2022. priv->bits = 6;
  2023. break;
  2024. case C7:
  2025. priv->bits = 7;
  2026. break;
  2027. default:
  2028. case C8:
  2029. priv->bits = 8;
  2030. break;
  2031. }
  2032. /* Note that only cfgetispeed is used because we have knowledge
  2033. * that only one speed is supported.
  2034. */
  2035. priv->baud = cfgetispeed(termiosp);
  2036. #ifdef CONFIG_SERIAL_IFLOWCONTROL
  2037. /* Set RTS if input flow control changed */
  2038. if (iflow != !priv->iflow)
  2039. {
  2040. priv->rts = true;
  2041. }
  2042. #endif
  2043. #ifdef HAVE_CTRL_INTERFACE
  2044. /* Effect the changes immediately - note that we do not implement
  2045. * TCSADRAIN / TCSAFLUSH
  2046. */
  2047. ret = usbhost_linecoding_send(priv);
  2048. #endif
  2049. }
  2050. break;
  2051. #endif /* CONFIG_SERIAL_TERMIOS */
  2052. #ifdef CONFIG_USBHOST_CDCACM_BREAKS
  2053. case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */
  2054. {
  2055. #warning Missing logic
  2056. }
  2057. break;
  2058. case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */
  2059. {
  2060. #warning Missing logic
  2061. }
  2062. break;
  2063. #endif
  2064. default:
  2065. ret = -ENOTTY;
  2066. break;
  2067. }
  2068. usbhost_givesem(&priv->exclsem);
  2069. }
  2070. return ret;
  2071. }
  2072. /****************************************************************************
  2073. * Name: usbhost_rxint
  2074. *
  2075. * Description:
  2076. * Call to enable or disable RX interrupts
  2077. *
  2078. ****************************************************************************/
  2079. static void usbhost_rxint(FAR struct uart_dev_s *uartdev, bool enable)
  2080. {
  2081. FAR struct usbhost_cdcacm_s *priv;
  2082. int ret;
  2083. DEBUGASSERT(uartdev && uartdev->priv);
  2084. priv = (FAR struct usbhost_cdcacm_s *)uartdev->priv;
  2085. /* Are we enabling or disabling RX reception? */
  2086. if (enable && !priv->rxena)
  2087. {
  2088. /* Cancel any pending, delayed RX data reception work */
  2089. (void)work_cancel(LPWORK, &priv->rxwork);
  2090. /* Restart immediate RX data reception work (unless RX flow control
  2091. * is in* effect.
  2092. */
  2093. #ifdef CONFIG_SERIAL_IFLOWCONTROL
  2094. if (priv->rts)
  2095. #endif
  2096. {
  2097. ret = work_queue(LPWORK, &priv->rxwork,
  2098. usbhost_rxdata_work, priv, 0);
  2099. DEBUGASSERT(ret >= 0);
  2100. UNUSED(ret);
  2101. }
  2102. }
  2103. else if (!enable && priv->rxena)
  2104. {
  2105. /* Cancel any pending RX data reception work */
  2106. (void)work_cancel(LPWORK, &priv->rxwork);
  2107. }
  2108. /* Save the new RX enable state */
  2109. priv->rxena = enable;
  2110. }
  2111. /****************************************************************************
  2112. * Name: usbhost_rxavailable
  2113. *
  2114. * Description:
  2115. * Return true if the receive buffer is not empty
  2116. *
  2117. ****************************************************************************/
  2118. static bool usbhost_rxavailable(FAR struct uart_dev_s *uartdev)
  2119. {
  2120. FAR struct usbhost_cdcacm_s *priv;
  2121. DEBUGASSERT(uartdev && uartdev->priv);
  2122. priv = (FAR struct usbhost_cdcacm_s *)uartdev->priv;
  2123. return (priv->nrxbytes > 0);
  2124. }
  2125. /****************************************************************************
  2126. * Name: usbhost_rxflowcontrol
  2127. *
  2128. * Description:
  2129. * Called when Rx buffer is full (or exceeds configured watermark levels
  2130. * if CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS is defined).
  2131. * Return true if UART activated RX flow control to block more incoming
  2132. * data
  2133. *
  2134. * Input parameters:
  2135. * uartdev - UART device instance
  2136. * nbuffered - the number of characters currently buffered
  2137. * (if CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS is
  2138. * not defined the value will be 0 for an empty buffer or the
  2139. * defined buffer size for a full buffer)
  2140. * upper - true indicates the upper watermark was crossed where
  2141. * false indicates the lower watermark has been crossed
  2142. *
  2143. * Returned Value:
  2144. * true if RX flow control activated.
  2145. *
  2146. ****************************************************************************/
  2147. #ifdef CONFIG_SERIAL_IFLOWCONTROL
  2148. static bool usbhost_rxflowcontrol(FAR struct uart_dev_s *uartdev,
  2149. unsigned int nbuffered, bool upper)
  2150. {
  2151. FAR struct usbhost_cdcacm_s *priv;
  2152. bool newrts;
  2153. int ret;
  2154. DEBUGASSERT(uartdev && uartdev->priv);
  2155. priv = (FAR struct usbhost_cdcacm_s *)uartdev->priv
  2156. /* Is RX flow control enabled? */
  2157. if (!priv->iflow)
  2158. {
  2159. /* Now.. make sure that RTS is set */
  2160. priv->rts = true;
  2161. return false;
  2162. }
  2163. /* Are we enabling or disabling RX flow control? */
  2164. if (priv->rts && upper)
  2165. {
  2166. /* RX flow control is not in effect (RTS is true) but we have just
  2167. * crossed the upper threshold, meaning that we should now clear
  2168. * RTS.
  2169. */
  2170. priv->rts = false;
  2171. /* Cancel any pending RX data reception work */
  2172. (void)work_cancel(LPWORK, &priv->rxwork)
  2173. return true;
  2174. }
  2175. else if (!priv->rts && !upper)
  2176. {
  2177. /* RX flow control is in effect (RTS is false) and we have just
  2178. * crossed the lower threshold, meaning that we should now set
  2179. * RTS.
  2180. */
  2181. priv->rts = true;
  2182. /* Restart RX data reception work flow unless RX reception is
  2183. * disabled.
  2184. */
  2185. if (priv->rxena && work_available(&priv->rxwork))
  2186. {
  2187. ret = work_queue(LPWORK, &priv->rxwork,
  2188. usbhost_rxdata_work, priv, 0);
  2189. DEBUGASSERT(ret >= 0);
  2190. UNUSED(ret);
  2191. }
  2192. return false;
  2193. }
  2194. }
  2195. #endif
  2196. /****************************************************************************
  2197. * Name: usbhost_txint
  2198. *
  2199. * Description:
  2200. * Call to enable or disable TX interrupts
  2201. *
  2202. ****************************************************************************/
  2203. static void usbhost_txint(FAR struct uart_dev_s *uartdev, bool enable)
  2204. {
  2205. FAR struct usbhost_cdcacm_s *priv;
  2206. int ret;
  2207. DEBUGASSERT(uartdev && uartdev->priv);
  2208. priv = (FAR struct usbhost_cdcacm_s *)uartdev->priv;
  2209. /* Are we enabling or disabling TX transmission? */
  2210. if (enable && !priv->txena)
  2211. {
  2212. /* Cancel any pending, delayed TX data transmission work */
  2213. (void)work_cancel(LPWORK, &priv->txwork);
  2214. /* Restart immediate TX data transmission work */
  2215. ret = work_queue(LPWORK, &priv->txwork,
  2216. usbhost_txdata_work, priv, 0);
  2217. DEBUGASSERT(ret >= 0);
  2218. UNUSED(ret);
  2219. }
  2220. else if (!enable && priv->txena)
  2221. {
  2222. /* Cancel any pending TX data transmission work */
  2223. (void)work_cancel(LPWORK, &priv->txwork);
  2224. }
  2225. /* Save the new RX enable state */
  2226. priv->txena = enable;
  2227. }
  2228. /****************************************************************************
  2229. * Name: usbhost_txready
  2230. *
  2231. * Description:
  2232. * Return true if the transmit data register is not full.
  2233. *
  2234. ****************************************************************************/
  2235. static bool usbhost_txready(FAR struct uart_dev_s *uartdev)
  2236. {
  2237. return true;
  2238. }
  2239. /****************************************************************************
  2240. * Name: usbhost_txempty
  2241. *
  2242. * Description:
  2243. * Return true if the transmit data buffer is empty
  2244. *
  2245. ****************************************************************************/
  2246. static bool usbhost_txempty(FAR struct uart_dev_s *uartdev)
  2247. {
  2248. return true;
  2249. }
  2250. /****************************************************************************
  2251. * Public Functions
  2252. ****************************************************************************/
  2253. /****************************************************************************
  2254. * Name: usbhost_cdcacm_initialize
  2255. *
  2256. * Description:
  2257. * Initialize the USB host CDC/ACM class. This function should be called
  2258. * be platform-specific code in order to initialize and register support
  2259. * for the USB host CDC/ACM class.
  2260. *
  2261. * Input Parameters:
  2262. * None
  2263. *
  2264. * Returned Value:
  2265. * On success this function will return zero (OK); A negated errno value
  2266. * will be returned on failure.
  2267. *
  2268. ****************************************************************************/
  2269. int usbhost_cdcacm_initialize(void)
  2270. {
  2271. /* If we have been configured to use pre-allocated CDC/ACM class instances,
  2272. * then place all of the pre-allocated USB host CDC/ACM class instances
  2273. * into a free list.
  2274. */
  2275. #if CONFIG_USBHOST_CDCACM_NPREALLOC > 0
  2276. FAR struct usbhost_freestate_s *entry;
  2277. int i;
  2278. g_freelist = NULL;
  2279. for (i = 0; i < CONFIG_USBHOST_CDCACM_NPREALLOC; i++)
  2280. {
  2281. entry = (FAR struct usbhost_freestate_s *)&g_prealloc[i];
  2282. entry->flink = g_freelist;
  2283. g_freelist = entry;
  2284. }
  2285. #endif
  2286. /* Advertise our availability to support (certain) CDC/ACM devices */
  2287. return usbhost_registerclass(&g_cdcacm);
  2288. }
  2289. #endif /* CONFIG_USBHOST_CDCACM */