usbhost_xboxcontroller.c 69 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228
  1. /****************************************************************************
  2. * drivers/usbhost/usbhost_xboxcontroller.c
  3. *
  4. * Copyright (C) 2016 Gregory Nutt. All rights reserved.
  5. * Authors: Gregory Nutt <gnutt@nuttx.org>
  6. * Brian Webb <webbbn@gmail.com>
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  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 <semaphore.h>
  44. #include <assert.h>
  45. #include <errno.h>
  46. #include <debug.h>
  47. #include <fcntl.h>
  48. #include <nuttx/irq.h>
  49. #include <nuttx/kmalloc.h>
  50. #include <nuttx/kthread.h>
  51. #include <nuttx/fs/fs.h>
  52. #include <nuttx/arch.h>
  53. #include <nuttx/wqueue.h>
  54. #include <nuttx/usb/usb.h>
  55. #include <nuttx/usb/usbhost.h>
  56. #include <nuttx/input/xbox-controller.h>
  57. /****************************************************************************
  58. * Pre-processor Definitions
  59. ****************************************************************************/
  60. /* Configuration ************************************************************/
  61. #ifndef CONFIG_SCHED_WORKQUEUE
  62. # warning "Worker thread support is required (CONFIG_SCHED_WORKQUEUE)"
  63. #endif
  64. #ifndef CONFIG_XBOXCONTROLLER_DEFPRIO
  65. # define CONFIG_XBOXCONTROLLER_DEFPRIO 50
  66. #endif
  67. #ifndef CONFIG_XBOXCONTROLLER_STACKSIZE
  68. # define CONFIG_XBOXCONTROLLER_STACKSIZE 1024
  69. #endif
  70. #ifndef CONFIG_XBOXCONTROLLER_NPOLLWAITERS
  71. # define CONFIG_XBOXCONTROLLER_NPOLLWAITERS 2
  72. #endif
  73. /* Driver support ***********************************************************/
  74. /* This format is used to construct the /dev/xbox[n] device driver path. It
  75. * defined here so that it will be used consistently in all places.
  76. */
  77. #define DEV_FORMAT "/dev/xbox%c"
  78. #define DEV_NAMELEN 11
  79. /* Used in usbhost_cfgdesc() */
  80. #define USBHOST_IFFOUND 0x01
  81. #define USBHOST_EPINFOUND 0x02 /* Required interrupt IN EP descriptor found */
  82. #define USBHOST_EPOUTFOUND 0x04 /* Required interrupt OUT EP descriptor found */
  83. #define USBHOST_ALLFOUND 0x07
  84. #define USBHOST_MAX_CREFS 0x7fff
  85. /* Received message types */
  86. #define USBHOST_WAITING_CONNECTION 0x02
  87. #define USBHOST_GUIDE_BUTTON_STATUS 0x07
  88. #define USBHOST_BUTTON_DATA 0x20
  89. /* Button definitions */
  90. #define XBOX_BUTTON_GUIDE_INDEX 4
  91. #define XBOX_BUTTON_SYNC_INDEX 4
  92. #define XBOX_BUTTON_SYNC_MASK (1 << 0)
  93. #define XBOX_BUTTON_START_INDEX 4
  94. #define XBOX_BUTTON_START_MASK (1 << 2)
  95. #define XBOX_BUTTON_BACK_INDEX 4
  96. #define XBOX_BUTTON_BACK_MASK (1 << 3)
  97. #define XBOX_BUTTON_A_INDEX 4
  98. #define XBOX_BUTTON_A_MASK (1 << 4)
  99. #define XBOX_BUTTON_B_INDEX 4
  100. #define XBOX_BUTTON_B_MASK (1 << 5)
  101. #define XBOX_BUTTON_X_INDEX 4
  102. #define XBOX_BUTTON_X_MASK (1 << 6)
  103. #define XBOX_BUTTON_Y_INDEX 4
  104. #define XBOX_BUTTON_Y_MASK (1 << 7)
  105. #define XBOX_BUTTON_DPAD_UP_INDEX 5
  106. #define XBOX_BUTTON_DPAD_UP_MASK (1 << 0)
  107. #define XBOX_BUTTON_DPAD_DOWN_INDEX 5
  108. #define XBOX_BUTTON_DPAD_DOWN_MASK (1 << 1)
  109. #define XBOX_BUTTON_DPAD_LEFT_INDEX 5
  110. #define XBOX_BUTTON_DPAD_LEFT_MASK (1 << 2)
  111. #define XBOX_BUTTON_DPAD_RIGHT_INDEX 5
  112. #define XBOX_BUTTON_DPAD_RIGHT_MASK (1 << 3)
  113. #define XBOX_BUTTON_BUMPER_LEFT_INDEX 5
  114. #define XBOX_BUTTON_BUMPER_LEFT_MASK (1 << 4)
  115. #define XBOX_BUTTON_BUMPER_RIGHT_INDEX 5
  116. #define XBOX_BUTTON_BUMPER_RIGHT_MASK (1 << 5)
  117. #define XBOX_BUTTON_STICK_LEFT_INDEX 5
  118. #define XBOX_BUTTON_STICK_LEFT_MASK (1 << 6)
  119. #define XBOX_BUTTON_STICK_RIGHT_INDEX 5
  120. #define XBOX_BUTTON_STICK_RIGHT_MASK (1 << 7)
  121. #define XBOX_BUTTON_TRIGGER_LEFT 3
  122. #define XBOX_BUTTON_TRIGGER_RIGHT 4
  123. #define XBOX_BUTTON_STICK_LEFT_X 5
  124. #define XBOX_BUTTON_STICK_LEFT_Y 6
  125. #define XBOX_BUTTON_STICK_RIGHT_X 7
  126. #define XBOX_BUTTON_STICK_RIGHT_Y 8
  127. #define XBOX_BUTTON_SET(buffer, index, mask) \
  128. ((((buffer)[(index)] & (mask)) != 0) ? true : false);
  129. /****************************************************************************
  130. * Private Types
  131. ****************************************************************************/
  132. /* This structure contains the internal, private state of the USB host class
  133. * driver.
  134. */
  135. struct usbhost_state_s
  136. {
  137. /* This is the externally visible portion of the state */
  138. struct usbhost_class_s usbclass;
  139. /* The remainder of the fields are provide to the class driver */
  140. char devchar; /* Character identifying the /dev/xbox[n] device */
  141. volatile bool disconnected; /* TRUE: Device has been disconnected */
  142. volatile bool polling; /* TRUE: Poll thread is running */
  143. volatile bool open; /* TRUE: The controller device is open */
  144. volatile bool valid; /* TRUE: New sample data is available */
  145. volatile bool initialized; /* TRUE: The initialization packet has been sent */
  146. uint8_t ifno; /* Interface number */
  147. uint8_t nwaiters; /* Number of threads waiting for controller data */
  148. sem_t waitsem; /* Used to wait for controller data */
  149. int16_t crefs; /* Reference count on the driver instance */
  150. sem_t exclsem; /* Used to maintain mutual exclusive access */
  151. struct work_s work; /* For interacting with the worker thread */
  152. FAR uint8_t *tbuffer; /* The allocated transfer buffer */
  153. FAR uint8_t obuffer[20]; /* The fixed output transfer buffer */
  154. size_t tbuflen; /* Size of the allocated transfer buffer */
  155. usbhost_ep_t epin; /* IN endpoint */
  156. usbhost_ep_t epout; /* OUT endpoint */
  157. pid_t pollpid; /* PID of the poll task */
  158. size_t out_seq_num; /* The sequence number for outgoing packets */
  159. struct xbox_controller_buttonstate_s rpt; /* The latest report out of the controller. */
  160. };
  161. /****************************************************************************
  162. * Private Function Prototypes
  163. ****************************************************************************/
  164. /* Semaphores */
  165. static void usbhost_takesem(sem_t *sem);
  166. #define usbhost_givesem(s) sem_post(s);
  167. /* Memory allocation services */
  168. static inline FAR struct usbhost_state_s *usbhost_allocclass(void);
  169. static inline void usbhost_freeclass(FAR struct usbhost_state_s *usbclass);
  170. /* Device name management */
  171. static int usbhost_allocdevno(FAR struct usbhost_state_s *priv);
  172. static void usbhost_freedevno(FAR struct usbhost_state_s *priv);
  173. static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv,
  174. FAR char *devname);
  175. /* Worker thread actions */
  176. static void usbhost_destroy(FAR void *arg);
  177. static void usbhost_notify(FAR struct usbhost_state_s *priv);
  178. static int usbhost_xboxcontroller_poll(int argc, char *argv[]);
  179. /* Helpers for usbhost_connect() */
  180. static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv,
  181. FAR const uint8_t *configdesc,
  182. int desclen);
  183. static inline int usbhost_devinit(FAR struct usbhost_state_s *priv);
  184. /* (Little Endian) Data helpers */
  185. static inline uint16_t usbhost_getle16(const uint8_t *val);
  186. static inline void usbhost_putle16(uint8_t *dest, uint16_t val);
  187. static inline uint32_t usbhost_getle32(const uint8_t *val);
  188. #if 0 /* Not used */
  189. static void usbhost_putle32(uint8_t *dest, uint32_t val);
  190. #endif
  191. /* Transfer descriptor memory management */
  192. static inline int usbhost_talloc(FAR struct usbhost_state_s *priv);
  193. static inline int usbhost_tfree(FAR struct usbhost_state_s *priv);
  194. /* struct usbhost_registry_s methods */
  195. static struct usbhost_class_s *usbhost_create(FAR struct usbhost_hubport_s *hport,
  196. FAR const struct usbhost_id_s *id);
  197. /* struct usbhost_class_s methods */
  198. static int usbhost_connect(FAR struct usbhost_class_s *usbclass,
  199. FAR const uint8_t *configdesc, int desclen);
  200. static int usbhost_disconnected(FAR struct usbhost_class_s *usbclass);
  201. /* Driver methods. We export the controller as a standard character driver */
  202. static int usbhost_open(FAR struct file *filep);
  203. static int usbhost_close(FAR struct file *filep);
  204. static ssize_t usbhost_read(FAR struct file *filep,
  205. FAR char *buffer, size_t len);
  206. static ssize_t usbhost_write(FAR struct file *filep,
  207. FAR const char *buffer, size_t len);
  208. static int usbhost_ioctl(FAR struct file* filep, int cmd, unsigned long arg);
  209. #ifndef CONFIG_DISABLE_POLL
  210. static int usbhost_poll(FAR struct file *filep, FAR struct pollfd *fds,
  211. bool setup);
  212. #endif
  213. /****************************************************************************
  214. * Private Data
  215. ****************************************************************************/
  216. /* This structure provides the registry entry ID information that will be
  217. * used to associate the USB class driver to a connected USB device.
  218. */
  219. static const const struct usbhost_id_s g_xboxcontroller_id[] =
  220. {
  221. /* XBox One classic controller */
  222. {
  223. USB_CLASS_VENDOR_SPEC, /* base -- Must be one of the USB_CLASS_* definitions in usb.h */
  224. 0x0047, /* subclass -- depends on the device */
  225. 0x00d0, /* proto -- depends on the device */
  226. 0x045E, /* vid */
  227. 0x02DD /* pid */
  228. },
  229. /* XBox One S controller */
  230. {
  231. USB_CLASS_VENDOR_SPEC, /* base -- Must be one of the USB_CLASS_* definitions in usb.h */
  232. 0x0047, /* subclass -- depends on the device */
  233. 0x00d0, /* proto -- depends on the device */
  234. 0x045E, /* vid */
  235. 0x02EA /* pid */
  236. }
  237. };
  238. /* This is the USB host storage class's registry entry */
  239. static struct usbhost_registry_s g_xboxcontroller =
  240. {
  241. NULL, /* flink */
  242. usbhost_create, /* create */
  243. 2, /* nids */
  244. g_xboxcontroller_id /* id[] */
  245. };
  246. /* The configuration information for the block file device. */
  247. static const struct file_operations g_xboxcontroller_fops =
  248. {
  249. usbhost_open, /* open */
  250. usbhost_close, /* close */
  251. usbhost_read, /* read */
  252. usbhost_write, /* write */
  253. 0, /* seek */
  254. usbhost_ioctl /* ioctl */
  255. #ifndef CONFIG_DISABLE_POLL
  256. , usbhost_poll /* poll */
  257. #endif
  258. };
  259. /* This is a bitmap that is used to allocate device names /dev/xboxa-z. */
  260. static uint32_t g_devinuse;
  261. /* The following are used to managed the class creation operation */
  262. static sem_t g_exclsem; /* For mutually exclusive thread creation */
  263. static sem_t g_syncsem; /* Thread data passing interlock */
  264. static struct usbhost_state_s *g_priv; /* Data passed to thread */
  265. /****************************************************************************
  266. * Private Functions
  267. ****************************************************************************/
  268. /****************************************************************************
  269. * Name: usbhost_takesem
  270. *
  271. * Description:
  272. * This is just a wrapper to handle the annoying behavior of semaphore
  273. * waits that return due to the receipt of a signal.
  274. *
  275. ****************************************************************************/
  276. static void usbhost_takesem(sem_t *sem)
  277. {
  278. /* Take the semaphore (perhaps waiting) */
  279. while (sem_wait(sem) != 0)
  280. {
  281. /* The only case that an error should occur here is if the wait was
  282. * awakened by a signal.
  283. */
  284. DEBUGASSERT(errno == EINTR);
  285. }
  286. }
  287. /****************************************************************************
  288. * Name: usbhost_allocclass
  289. *
  290. * Description:
  291. * This is really part of the logic that implements the create() method
  292. * of struct usbhost_registry_s. This function allocates memory for one
  293. * new class instance.
  294. *
  295. * Input Parameters:
  296. * None
  297. *
  298. * Returned Values:
  299. * On success, this function will return a non-NULL instance of struct
  300. * usbhost_class_s. NULL is returned on failure; this function will
  301. * will fail only if there are insufficient resources to create another
  302. * USB host class instance.
  303. *
  304. ****************************************************************************/
  305. static inline FAR struct usbhost_state_s *usbhost_allocclass(void)
  306. {
  307. FAR struct usbhost_state_s *priv;
  308. DEBUGASSERT(!up_interrupt_context());
  309. priv = (FAR struct usbhost_state_s *)kmm_malloc(sizeof(struct usbhost_state_s));
  310. uinfo("Allocated: %p\n", priv);
  311. return priv;
  312. }
  313. /****************************************************************************
  314. * Name: usbhost_freeclass
  315. *
  316. * Description:
  317. * Free a class instance previously allocated by usbhost_allocclass().
  318. *
  319. * Input Parameters:
  320. * usbclass - A reference to the class instance to be freed.
  321. *
  322. * Returned Values:
  323. * None
  324. *
  325. ****************************************************************************/
  326. static inline void usbhost_freeclass(FAR struct usbhost_state_s *usbclass)
  327. {
  328. DEBUGASSERT(usbclass != NULL);
  329. /* Free the class instance (perhaps calling sched_kmm_free() in case we are
  330. * executing from an interrupt handler.
  331. */
  332. uinfo("Freeing: %p\n", usbclass);
  333. kmm_free(usbclass);
  334. }
  335. /****************************************************************************
  336. * Name: Device name management
  337. *
  338. * Description:
  339. * Some tiny functions to coordinate management of device names.
  340. *
  341. ****************************************************************************/
  342. static int usbhost_allocdevno(FAR struct usbhost_state_s *priv)
  343. {
  344. irqstate_t flags;
  345. int devno;
  346. flags = enter_critical_section();
  347. for (devno = 0; devno < 26; devno++)
  348. {
  349. uint32_t bitno = 1 << devno;
  350. if ((g_devinuse & bitno) == 0)
  351. {
  352. g_devinuse |= bitno;
  353. priv->devchar = 'a' + devno;
  354. leave_critical_section(flags);
  355. return OK;
  356. }
  357. }
  358. leave_critical_section(flags);
  359. return -EMFILE;
  360. }
  361. static void usbhost_freedevno(FAR struct usbhost_state_s *priv)
  362. {
  363. int devno = 'a' - priv->devchar;
  364. if (devno >= 0 && devno < 26)
  365. {
  366. irqstate_t flags = enter_critical_section();
  367. g_devinuse &= ~(1 << devno);
  368. leave_critical_section(flags);
  369. }
  370. }
  371. static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv,
  372. FAR char *devname)
  373. {
  374. (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, priv->devchar);
  375. }
  376. /****************************************************************************
  377. * Name: usbhost_destroy
  378. *
  379. * Description:
  380. * The USB device has been disconnected and the reference count on the USB
  381. * host class instance has gone to 1.. Time to destroy the USB host class
  382. * instance.
  383. *
  384. * Input Parameters:
  385. * arg - A reference to the class instance to be destroyed.
  386. *
  387. * Returned Values:
  388. * None
  389. *
  390. ****************************************************************************/
  391. static void usbhost_destroy(FAR void *arg)
  392. {
  393. FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)arg;
  394. FAR struct usbhost_hubport_s *hport;
  395. char devname[DEV_NAMELEN];
  396. DEBUGASSERT(priv != NULL && priv->usbclass.hport != NULL);
  397. uinfo("crefs: %d\n", priv->crefs);
  398. hport = priv->usbclass.hport;
  399. DEBUGASSERT(hport->drvr);
  400. uinfo("crefs: %d\n", priv->crefs);
  401. /* Unregister the driver */
  402. uinfo("Unregister driver\n");
  403. usbhost_mkdevname(priv, devname);
  404. (void)unregister_driver(devname);
  405. /* Release the device name used by this connection */
  406. usbhost_freedevno(priv);
  407. /* Free the interrupt endpoints */
  408. if (priv->epin)
  409. {
  410. DRVR_EPFREE(hport->drvr, priv->epin);
  411. }
  412. /* Free any transfer buffers */
  413. usbhost_tfree(priv);
  414. /* Destroy the semaphores */
  415. sem_destroy(&priv->exclsem);
  416. sem_destroy(&priv->waitsem);
  417. /* Disconnect the USB host device */
  418. DRVR_DISCONNECT(hport->drvr, hport);
  419. /* Free the function address assigned to this device */
  420. usbhost_devaddr_destroy(hport, hport->funcaddr);
  421. hport->funcaddr = 0;
  422. /* And free the class instance. */
  423. usbhost_freeclass(priv);
  424. }
  425. /****************************************************************************
  426. * Name: usbhost_notify
  427. *
  428. * Description:
  429. * Wake any threads waiting for controller data
  430. *
  431. * Input Paramters:
  432. * priv - A reference to the controller state structure.
  433. *
  434. * Returned Value:
  435. * None
  436. *
  437. ****************************************************************************/
  438. static void usbhost_notify(FAR struct usbhost_state_s *priv)
  439. {
  440. #ifndef CONFIG_DISABLE_POLL
  441. int i;
  442. #endif
  443. /* If there are threads waiting for read data, then signal one of them
  444. * that the read data is available.
  445. */
  446. if (priv->nwaiters > 0)
  447. {
  448. sem_post(&priv->waitsem);
  449. }
  450. /* If there are threads waiting on poll() for controller data to become available,
  451. * then wake them up now. NOTE: we wake up all waiting threads because we
  452. * do not know that they are going to do. If they all try to read the data,
  453. * then some make end up blocking after all.
  454. */
  455. #ifndef CONFIG_DISABLE_POLL
  456. for (i = 0; i < CONFIG_XBOXCONTROLLER_NPOLLWAITERS; i++)
  457. {
  458. FAR struct pollfd *fds = priv->fds[i];
  459. if (fds)
  460. {
  461. fds->revents |= POLLIN;
  462. iinfo("Report events: %02x\n", fds->revents);
  463. sem_post(fds->sem);
  464. }
  465. }
  466. #endif
  467. }
  468. /****************************************************************************
  469. * Name: usbhost_xboxcontroller_poll
  470. *
  471. * Description:
  472. * Periodically check for new controller data.
  473. *
  474. * Input Parameters:
  475. * arg - A reference to the class instance to be destroyed.
  476. *
  477. * Returned Values:
  478. * None
  479. *
  480. ****************************************************************************/
  481. static int usbhost_xboxcontroller_poll(int argc, char *argv[])
  482. {
  483. FAR struct usbhost_state_s *priv;
  484. FAR struct usbhost_hubport_s *hport;
  485. irqstate_t flags;
  486. #if defined(CONFIG_DEBUG_USB) && defined(CONFIG_DEBUG_INFO)
  487. unsigned int npolls = 0;
  488. #endif
  489. unsigned int nerrors = 0;
  490. ssize_t nbytes;
  491. int ret = OK;
  492. /* Synchronize with the start-up logic. Get the private instance, re-start
  493. * the start-up logic, and wait a bit to make sure that all of the class
  494. * creation logic has a chance to run to completion.
  495. *
  496. * NOTE: that the reference count is *not* incremented here. When the driver
  497. * structure was created, it was created with a reference count of one. This
  498. * thread is responsible for that count. The count will be decrement when
  499. * this thread exits.
  500. */
  501. priv = g_priv;
  502. DEBUGASSERT(priv != NULL && priv->usbclass.hport != NULL);
  503. hport = priv->usbclass.hport;
  504. priv->polling = true;
  505. usbhost_givesem(&g_syncsem);
  506. sleep(1);
  507. /* Loop here until the device is disconnected */
  508. uinfo("Entering poll loop\n");
  509. while (!priv->disconnected)
  510. {
  511. /* Read the next ccontroller report. We will stall here until the
  512. * controller sends data.
  513. */
  514. nbytes = DRVR_TRANSFER(hport->drvr, priv->epin,
  515. priv->tbuffer, priv->tbuflen);
  516. /* Check for errors -- Bail if an excessive number of consecutive
  517. * errors are encountered.
  518. */
  519. if (nbytes < 0)
  520. {
  521. /* If DRVR_TRANSFER() returns EAGAIN, that simply means that
  522. * the devices was not ready and has NAK'ed the transfer. That
  523. * should not be treated as an error (unless it persists for a
  524. * long time).
  525. */
  526. if (nbytes != -EAGAIN)
  527. {
  528. uerr("ERROR: DRVR_TRANSFER returned: %d/%u\n",
  529. (int)nbytes, nerrors);
  530. if (++nerrors > 200)
  531. {
  532. uerr(" Too many errors... aborting: %d\n", nerrors);
  533. ret = (int)nbytes;
  534. break;
  535. }
  536. }
  537. }
  538. /* The report was received correctly. */
  539. else
  540. {
  541. /* Success, reset the error counter */
  542. nerrors = 0;
  543. /* The type of message is in the first byte */
  544. switch (priv->tbuffer[0])
  545. {
  546. case USBHOST_WAITING_CONNECTION:
  547. /* Send the initialization message when we received the
  548. * the first waiting connection message.
  549. */
  550. if (!priv->initialized)
  551. {
  552. /* Get exclusive access to the controller state data */
  553. usbhost_takesem(&priv->exclsem);
  554. priv->tbuffer[0] = 0x05;
  555. priv->tbuffer[1] = 0x20;
  556. priv->tbuffer[2] = priv->out_seq_num++;
  557. priv->tbuffer[3] = 0x01;
  558. priv->tbuffer[4] = 0x00;
  559. nbytes = DRVR_TRANSFER(hport->drvr, priv->epout,
  560. priv->tbuffer, 5);
  561. priv->initialized = true;
  562. /* Release our lock on the state structure */
  563. usbhost_givesem(&priv->exclsem);
  564. }
  565. break;
  566. case USBHOST_GUIDE_BUTTON_STATUS:
  567. /* Get exclusive access to the controller state data */
  568. usbhost_takesem(&priv->exclsem);
  569. /* Read the data out of the controller report. */
  570. priv->rpt.guide = (priv->tbuffer[XBOX_BUTTON_GUIDE_INDEX] != 0) ? true : false;
  571. priv->valid = true;
  572. /* The One X controller requires an ACK of the guide button status
  573. * message.
  574. */
  575. if (priv->tbuffer[1] == 0x30)
  576. {
  577. static const uint8_t guide_button_report_ack[] =
  578. {
  579. 0x01, 0x20, 0x00, 0x09, 0x00, 0x07, 0x20, 0x02,
  580. 0x00, 0x00, 0x00, 0x00, 0x00
  581. };
  582. /* Remember the input packet sequence number. */
  583. uint8_t seq_num = priv->tbuffer[2];
  584. /* Copy the ACK packet into the transfer buffer. */
  585. memcpy(priv->tbuffer, guide_button_report_ack,
  586. sizeof(guide_button_report_ack));
  587. /* Ensure the sequence number is the same as the input packet. */
  588. priv->tbuffer[2] = seq_num;
  589. /* Perform the transfer. */
  590. nbytes = DRVR_TRANSFER(hport->drvr, priv->epout, priv->tbuffer,
  591. sizeof(guide_button_report_ack));
  592. }
  593. /* Notify any waiters that new controller data is available */
  594. usbhost_notify(priv);
  595. /* Release our lock on the state structure */
  596. usbhost_givesem(&priv->exclsem);
  597. break;
  598. case USBHOST_BUTTON_DATA:
  599. /* Ignore the controller data if no task has opened the driver. */
  600. if (priv->open)
  601. {
  602. /* Get exclusive access to the controller state data */
  603. usbhost_takesem(&priv->exclsem);
  604. /* Read the data out of the controller report. */
  605. priv->rpt.sync =
  606. XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_SYNC_INDEX,
  607. XBOX_BUTTON_SYNC_MASK);
  608. priv->rpt.start =
  609. XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_START_INDEX,
  610. XBOX_BUTTON_START_MASK);
  611. priv->rpt.back =
  612. XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_BACK_INDEX,
  613. XBOX_BUTTON_BACK_MASK);
  614. priv->rpt.a =
  615. XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_A_INDEX,
  616. XBOX_BUTTON_A_MASK);
  617. priv->rpt.b =
  618. XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_B_INDEX,
  619. XBOX_BUTTON_B_MASK);
  620. priv->rpt.x =
  621. XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_X_INDEX,
  622. XBOX_BUTTON_X_MASK);
  623. priv->rpt.y =
  624. XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_Y_INDEX,
  625. XBOX_BUTTON_Y_MASK);
  626. priv->rpt.dpad_up =
  627. XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_DPAD_UP_INDEX,
  628. XBOX_BUTTON_DPAD_UP_MASK);
  629. priv->rpt.dpad_down =
  630. XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_DPAD_DOWN_INDEX,
  631. XBOX_BUTTON_DPAD_DOWN_MASK);
  632. priv->rpt.dpad_left =
  633. XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_DPAD_LEFT_INDEX,
  634. XBOX_BUTTON_DPAD_LEFT_MASK);
  635. priv->rpt.dpad_right =
  636. XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_DPAD_RIGHT_INDEX,
  637. XBOX_BUTTON_DPAD_RIGHT_MASK);
  638. priv->rpt.bumper_left =
  639. XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_BUMPER_LEFT_INDEX,
  640. XBOX_BUTTON_BUMPER_LEFT_MASK);
  641. priv->rpt.bumper_right =
  642. XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_BUMPER_RIGHT_INDEX, XBOX_BUTTON_BUMPER_RIGHT_MASK);
  643. priv->rpt.stick_click_left =
  644. XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_STICK_LEFT_INDEX,
  645. XBOX_BUTTON_STICK_LEFT_MASK);
  646. priv->rpt.stick_click_right =
  647. XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_STICK_RIGHT_INDEX,
  648. XBOX_BUTTON_STICK_RIGHT_MASK);
  649. priv->rpt.trigger_left =
  650. ((int16_t*)(priv->tbuffer))[XBOX_BUTTON_TRIGGER_LEFT];
  651. priv->rpt.trigger_right =
  652. ((int16_t*)(priv->tbuffer))[XBOX_BUTTON_TRIGGER_RIGHT];
  653. priv->rpt.stick_left_x =
  654. ((int16_t*)(priv->tbuffer))[XBOX_BUTTON_STICK_LEFT_X];
  655. priv->rpt.stick_left_y =
  656. ((int16_t*)(priv->tbuffer))[XBOX_BUTTON_STICK_LEFT_Y];
  657. priv->rpt.stick_right_x =
  658. ((int16_t*)(priv->tbuffer))[XBOX_BUTTON_STICK_RIGHT_X];
  659. priv->rpt.stick_right_y =
  660. ((int16_t*)(priv->tbuffer))[XBOX_BUTTON_STICK_RIGHT_Y];
  661. priv->valid = true;
  662. /* Notify any waiters that new controller data is available */
  663. usbhost_notify(priv);
  664. /* Release our lock on the state structure */
  665. usbhost_givesem(&priv->exclsem);
  666. }
  667. break;
  668. default:
  669. uinfo("Received messge type: %x\n", priv->tbuffer[0]);
  670. }
  671. }
  672. /* If USB debug is on, then provide some periodic indication that
  673. * polling is still happening.
  674. */
  675. #if defined(CONFIG_DEBUG_USB) && defined(CONFIG_DEBUG_INFO)
  676. npolls++;
  677. if ((npolls & 31) == 0)
  678. {
  679. uinfo("Still polling: %d\n", npolls);
  680. }
  681. #endif
  682. }
  683. /* We get here when the driver is removed.. or when too many errors have
  684. * been encountered.
  685. *
  686. * Make sure that we have exclusive access to the private data structure.
  687. * There may now be other tasks with the character driver open and actively
  688. * trying to interact with the class driver.
  689. */
  690. usbhost_takesem(&priv->exclsem);
  691. /* Indicate that we are no longer running and decrement the reference
  692. * count held by this thread. If there are no other users of the class,
  693. * we can destroy it now. Otherwise, we have to wait until the all
  694. * of the file descriptors are closed.
  695. */
  696. uinfo("Controller removed, polling halted\n");
  697. flags = enter_critical_section();
  698. priv->polling = false;
  699. /* Decrement the reference count held by this thread. */
  700. DEBUGASSERT(priv->crefs > 0);
  701. priv->crefs--;
  702. /* There are two possibilities:
  703. * 1) The reference count is greater than zero. This means that there
  704. * are still open references to the controller driver. In this case
  705. * we need to wait until usbhost_close() is called and all of the
  706. * open driver references are decremented. Then usbhost_destroy() can
  707. * be called from usbhost_close().
  708. * 2) The reference count is now zero. This means that there are no
  709. * further open references and we can call usbhost_destroy() now.
  710. */
  711. if (priv->crefs < 1)
  712. {
  713. /* Unregister the driver and destroy the instance (while we hold
  714. * the semaphore!)
  715. */
  716. usbhost_destroy(priv);
  717. }
  718. else
  719. {
  720. /* No, we will destroy the driver instance when it is final open
  721. * reference is closed
  722. */
  723. usbhost_givesem(&priv->exclsem);
  724. }
  725. leave_critical_section(flags);
  726. return ret;
  727. }
  728. /****************************************************************************
  729. * Name: usbhost_sample
  730. *
  731. * Description:
  732. * Check if new controller data is available
  733. *
  734. * Input Parameters:
  735. * priv - controller state instance
  736. * sample - The location to return the sample data
  737. *
  738. ****************************************************************************/
  739. static int usbhost_sample(FAR struct usbhost_state_s *priv,
  740. FAR struct xbox_controller_buttonstate_s *sample)
  741. {
  742. irqstate_t flags;
  743. int ret = -EAGAIN;
  744. /* Interrupts me be disabled when this is called to (1) prevent posting
  745. * of semaphores from interrupt handlers, and (2) to prevent sampled data
  746. * from changing until it has been reported.
  747. */
  748. flags = enter_critical_section();
  749. /* Is there new mouse data available? */
  750. if (priv->valid)
  751. {
  752. /* Return a copy of the sampled data. */
  753. memcpy(sample, &priv->rpt, sizeof(struct xbox_controller_buttonstate_s));
  754. /* The sample has been reported and is no longer valid */
  755. priv->valid = false;
  756. ret = OK;
  757. }
  758. leave_critical_section(flags);
  759. return ret;
  760. }
  761. /****************************************************************************
  762. * Name: usbhost_waitsample
  763. *
  764. * Description:
  765. * Wait for the next valid controller sample
  766. *
  767. * Input Parameters:
  768. * priv - controller state instance
  769. * sample - The location to return the sample data
  770. *
  771. ****************************************************************************/
  772. static int usbhost_waitsample(FAR struct usbhost_state_s *priv,
  773. FAR struct xbox_controller_buttonstate_s *sample)
  774. {
  775. irqstate_t flags;
  776. int ret;
  777. /* Interrupts me be disabled when this is called to (1) prevent posting
  778. * of semaphores from interrupt handlers, and (2) to prevent sampled data
  779. * from changing until it has been reported.
  780. *
  781. * In addition, we will also disable pre-emption to prevent other threads
  782. * from getting control while we muck with the semaphores.
  783. */
  784. sched_lock();
  785. flags = enter_critical_section();
  786. /* Now release the semaphore that manages mutually exclusive access to
  787. * the device structure. This may cause other tasks to become ready to
  788. * run, but they cannot run yet because pre-emption is disabled.
  789. */
  790. sem_post(&priv->exclsem);
  791. /* Try to get the a sample... if we cannot, then wait on the semaphore
  792. * that is posted when new sample data is available.
  793. */
  794. while (usbhost_sample(priv, sample) < 0)
  795. {
  796. /* Wait for a change in the HIDMOUSE state */
  797. iinfo("Waiting..\n");
  798. priv->nwaiters++;
  799. ret = sem_wait(&priv->waitsem);
  800. priv->nwaiters--;
  801. if (ret < 0)
  802. {
  803. /* If we are awakened by a signal, then we need to return
  804. * the failure now.
  805. */
  806. ierr("ERROR: sem_wait: %d\n", errno);
  807. DEBUGASSERT(errno == EINTR);
  808. ret = -EINTR;
  809. goto errout;
  810. }
  811. /* Did the controller become disconnected while we were waiting */
  812. if (priv->disconnected)
  813. {
  814. ret = -ENODEV;
  815. goto errout;
  816. }
  817. }
  818. iinfo("Sampled\n");
  819. /* Re-acquire the semaphore that manages mutually exclusive access to
  820. * the device structure. We may have to wait here. But we have our sample.
  821. * Interrupts and pre-emption will be re-enabled while we wait.
  822. */
  823. ret = sem_wait(&priv->exclsem);
  824. errout:
  825. /* Then re-enable interrupts. We might get interrupt here and there
  826. * could be a new sample. But no new threads will run because we still
  827. * have pre-emption disabled.
  828. */
  829. leave_critical_section(flags);
  830. /* Restore pre-emption. We might get suspended here but that is okay
  831. * because we already have our sample. Note: this means that if there
  832. * were two threads reading from the HIDMOUSE for some reason, the data
  833. * might be read out of order.
  834. */
  835. sched_unlock();
  836. return ret;
  837. }
  838. /****************************************************************************
  839. * Name: usbhost_cfgdesc
  840. *
  841. * Description:
  842. * This function implements the connect() method of struct
  843. * usbhost_class_s. This method is a callback into the class
  844. * implementation. It is used to provide the device's configuration
  845. * descriptor to the class so that the class may initialize properly
  846. *
  847. * Input Parameters:
  848. * priv - The USB host class instance.
  849. * configdesc - A pointer to a uint8_t buffer container the configuration
  850. * descriptor.
  851. * desclen - The length in bytes of the configuration descriptor.
  852. *
  853. * Returned Values:
  854. * On success, zero (OK) is returned. On a failure, a negated errno value is
  855. * returned indicating the nature of the failure
  856. *
  857. * Assumptions:
  858. * This function will *not* be called from an interrupt handler.
  859. *
  860. ****************************************************************************/
  861. static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv,
  862. FAR const uint8_t *configdesc, int desclen)
  863. {
  864. FAR struct usbhost_hubport_s *hport;
  865. FAR struct usb_cfgdesc_s *cfgdesc;
  866. FAR struct usb_desc_s *desc;
  867. FAR struct usbhost_epdesc_s epindesc;
  868. FAR struct usbhost_epdesc_s epoutdesc;
  869. int remaining;
  870. uint8_t found = 0;
  871. bool done = false;
  872. int ret;
  873. DEBUGASSERT(priv != NULL && priv->usbclass.hport &&
  874. configdesc != NULL && desclen >= sizeof(struct usb_cfgdesc_s));
  875. hport = priv->usbclass.hport;
  876. /* Keep the compiler from complaining about uninitialized variables */
  877. memset(&epindesc, 0, sizeof(struct usbhost_epdesc_s));
  878. memset(&epoutdesc, 0, sizeof(struct usbhost_epdesc_s));
  879. /* Verify that we were passed a configuration descriptor */
  880. cfgdesc = (FAR struct usb_cfgdesc_s *)configdesc;
  881. if (cfgdesc->type != USB_DESC_TYPE_CONFIG)
  882. {
  883. return -EINVAL;
  884. }
  885. /* Get the total length of the configuration descriptor (little endian).
  886. * It might be a good check to get the number of interfaces here too.
  887. */
  888. remaining = (int)usbhost_getle16(cfgdesc->totallen);
  889. /* Skip to the next entry descriptor */
  890. configdesc += cfgdesc->len;
  891. remaining -= cfgdesc->len;
  892. /* Loop where there are more dscriptors to examine */
  893. while (remaining >= sizeof(struct usb_desc_s) && !done)
  894. {
  895. /* What is the next descriptor? */
  896. desc = (FAR struct usb_desc_s *)configdesc;
  897. switch (desc->type)
  898. {
  899. /* Interface descriptor. We really should get the number of endpoints
  900. * from this descriptor too.
  901. */
  902. case USB_DESC_TYPE_INTERFACE:
  903. {
  904. uinfo("Interface descriptor\n");
  905. DEBUGASSERT(remaining >= USB_SIZEOF_IFDESC);
  906. /* Did we already find what we needed from a preceding interface? */
  907. if ((found & USBHOST_ALLFOUND) == USBHOST_ALLFOUND)
  908. {
  909. /* Yes.. then break out of the loop and use the preceding
  910. * interface.
  911. */
  912. done = true;
  913. }
  914. else
  915. {
  916. /* Otherwise, discard any endpoints previously found */
  917. found = USBHOST_IFFOUND;
  918. }
  919. }
  920. break;
  921. /* Endpoint descriptor. Here, we expect two bulk endpoints, an IN
  922. * and an OUT.
  923. */
  924. case USB_DESC_TYPE_ENDPOINT:
  925. {
  926. FAR struct usb_epdesc_s *epdesc = (FAR struct usb_epdesc_s *)configdesc;
  927. uinfo("Endpoint descriptor\n");
  928. DEBUGASSERT(remaining >= USB_SIZEOF_EPDESC);
  929. /* Check for a interrupt endpoint. */
  930. if ((epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) == USB_EP_ATTR_XFER_INT)
  931. {
  932. /* Yes.. it is a interrupt endpoint. IN or OUT? */
  933. if (USB_ISEPOUT(epdesc->addr))
  934. {
  935. /* It is an OUT interrupt endpoint. There should be only one
  936. * interrupt OUT endpoint.
  937. */
  938. if ((found & USBHOST_EPOUTFOUND) != 0)
  939. {
  940. /* Oops.. more than one endpoint. We don't know
  941. * what to do with this.
  942. */
  943. return -EINVAL;
  944. }
  945. found |= USBHOST_EPOUTFOUND;
  946. /* Save the bulk OUT endpoint information */
  947. epoutdesc.hport = hport;
  948. epoutdesc.addr = epdesc->addr & USB_EP_ADDR_NUMBER_MASK;
  949. epoutdesc.in = false;
  950. epoutdesc.xfrtype = USB_EP_ATTR_XFER_INT;
  951. epoutdesc.interval = epdesc->interval;
  952. epoutdesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize);
  953. uerr("Interrupt OUT EP addr:%d mxpacketsize:%d\n",
  954. epoutdesc.addr, epoutdesc.mxpacketsize);
  955. }
  956. else
  957. {
  958. /* It is an IN interrupt endpoint. There should be only one
  959. * interrupt IN endpoint.
  960. */
  961. if ((found & USBHOST_EPINFOUND) != 0)
  962. {
  963. /* Oops.. more than one endpoint. We don't know
  964. * what to do with this.
  965. */
  966. return -EINVAL;
  967. }
  968. found |= USBHOST_EPINFOUND;
  969. /* Save the bulk IN endpoint information */
  970. epindesc.hport = hport;
  971. epindesc.addr = epdesc->addr & USB_EP_ADDR_NUMBER_MASK;
  972. epindesc.in = true;
  973. epindesc.xfrtype = USB_EP_ATTR_XFER_INT;
  974. epindesc.interval = epdesc->interval;
  975. epindesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize);
  976. uerr("Interrupt IN EP addr:%d mxpacketsize:%d\n",
  977. epindesc.addr, epindesc.mxpacketsize);
  978. }
  979. }
  980. }
  981. break;
  982. /* Other descriptors are just ignored for now */
  983. default:
  984. break;
  985. }
  986. /* If we found everything we need with this interface, then break out
  987. * of the loop early.
  988. */
  989. if (found == USBHOST_ALLFOUND)
  990. {
  991. done = true;
  992. }
  993. /* Increment the address of the next descriptor */
  994. configdesc += desc->len;
  995. remaining -= desc->len;
  996. }
  997. /* Sanity checking... did we find all of things that we need? */
  998. if (found != USBHOST_ALLFOUND)
  999. {
  1000. uerr("ERROR: Found IF:%s BIN:%s EPOUT:%s\n",
  1001. (found & USBHOST_IFFOUND) != 0 ? "YES" : "NO",
  1002. (found & USBHOST_EPINFOUND) != 0 ? "YES" : "NO",
  1003. (found & USBHOST_EPOUTFOUND) != 0 ? "YES" : "NO");
  1004. return -EINVAL;
  1005. }
  1006. /* We are good... Allocate the endpoints */
  1007. ret = DRVR_EPALLOC(hport->drvr, &epoutdesc, &priv->epout);
  1008. if (ret < 0)
  1009. {
  1010. uerr("ERROR: Failed to allocate Interrupt OUT endpoint\n");
  1011. return ret;
  1012. }
  1013. ret = DRVR_EPALLOC(hport->drvr, &epindesc, &priv->epin);
  1014. if (ret < 0)
  1015. {
  1016. uerr("ERROR: Failed to allocate Interrupt IN endpoint\n");
  1017. (void)DRVR_EPFREE(hport->drvr, priv->epout);
  1018. return ret;
  1019. }
  1020. uinfo("Endpoints allocated\n");
  1021. return OK;
  1022. }
  1023. /****************************************************************************
  1024. * Name: usbhost_devinit
  1025. *
  1026. * Description:
  1027. * The USB device has been successfully connected. This completes the
  1028. * initialization operations. It is first called after the
  1029. * configuration descriptor has been received.
  1030. *
  1031. * This function is called from the connect() method. This function always
  1032. * executes on the thread of the caller of connect().
  1033. *
  1034. * Input Parameters:
  1035. * priv - A reference to the class instance.
  1036. *
  1037. * Returned Values:
  1038. * None
  1039. *
  1040. ****************************************************************************/
  1041. static inline int usbhost_devinit(FAR struct usbhost_state_s *priv)
  1042. {
  1043. char devname[DEV_NAMELEN];
  1044. int ret = OK;
  1045. /* Set aside a transfer buffer for exclusive use by the class driver */
  1046. ret = usbhost_talloc(priv);
  1047. if (ret < 0)
  1048. {
  1049. uerr("ERROR: Failed to allocate transfer buffer\n");
  1050. return ret;
  1051. }
  1052. /* Increment the reference count. This will prevent usbhost_destroy() from
  1053. * being called asynchronously if the device is removed.
  1054. */
  1055. priv->crefs++;
  1056. DEBUGASSERT(priv->crefs == 2);
  1057. /* Start a worker task to poll the USB device. It would be nice to used the
  1058. * the NuttX worker thread to do this, but this task needs to wait for events
  1059. * and activities on the worker thread should not involve significant waiting.
  1060. * Having a dedicated thread is more efficient in this sense, but requires more
  1061. * memory resources, primarily for the dedicated stack (CONFIG_XBOXCONTROLLER_STACKSIZE).
  1062. */
  1063. /* The inputs to a task started by kernel_thread() are very awkward for this
  1064. * purpose. They are really designed for command line tasks (argc/argv). So
  1065. * the following is kludge pass binary data when the controller poll task
  1066. * is started.
  1067. *
  1068. * First, make sure we have exclusive access to g_priv (what is the likelihood
  1069. * of this being used? About zero, but we protect it anyway).
  1070. */
  1071. usbhost_takesem(&g_exclsem);
  1072. g_priv = priv;
  1073. uinfo("Starting thread\n");
  1074. priv->pollpid = kernel_thread("xbox", CONFIG_XBOXCONTROLLER_DEFPRIO,
  1075. CONFIG_XBOXCONTROLLER_STACKSIZE,
  1076. (main_t)usbhost_xboxcontroller_poll, (FAR char * const *)NULL);
  1077. if (priv->pollpid == ERROR)
  1078. {
  1079. /* Failed to started the poll thread... probably due to memory resources */
  1080. usbhost_givesem(&g_exclsem);
  1081. ret = -ENOMEM;
  1082. goto errout;
  1083. }
  1084. /* Now wait for the poll task to get properly initialized */
  1085. usbhost_takesem(&g_syncsem);
  1086. usbhost_givesem(&g_exclsem);
  1087. /* Configure the device */
  1088. /* Register the driver */
  1089. uinfo("Register block driver\n");
  1090. usbhost_mkdevname(priv, devname);
  1091. ret = register_driver(devname, &g_xboxcontroller_fops, 0666, priv);
  1092. /* Check if we successfully initialized. We now have to be concerned
  1093. * about asynchronous modification of crefs because the block
  1094. * driver has been registerd.
  1095. */
  1096. errout:
  1097. usbhost_takesem(&priv->exclsem);
  1098. priv->crefs--;
  1099. usbhost_givesem(&priv->exclsem);
  1100. return ret;
  1101. }
  1102. /****************************************************************************
  1103. * Name: usbhost_getle16
  1104. *
  1105. * Description:
  1106. * Get a (possibly unaligned) 16-bit little endian value.
  1107. *
  1108. * Input Parameters:
  1109. * val - A pointer to the first byte of the little endian value.
  1110. *
  1111. * Returned Values:
  1112. * A uint16_t representing the whole 16-bit integer value
  1113. *
  1114. ****************************************************************************/
  1115. static inline uint16_t usbhost_getle16(const uint8_t *val)
  1116. {
  1117. return (uint16_t)val[1] << 8 | (uint16_t)val[0];
  1118. }
  1119. /****************************************************************************
  1120. * Name: usbhost_putle16
  1121. *
  1122. * Description:
  1123. * Put a (possibly unaligned) 16-bit little endian value.
  1124. *
  1125. * Input Parameters:
  1126. * dest - A pointer to the first byte to save the little endian value.
  1127. * val - The 16-bit value to be saved.
  1128. *
  1129. * Returned Values:
  1130. * None
  1131. *
  1132. ****************************************************************************/
  1133. static void usbhost_putle16(uint8_t *dest, uint16_t val)
  1134. {
  1135. dest[0] = val & 0xff; /* Little endian means LS byte first in byte stream */
  1136. dest[1] = val >> 8;
  1137. }
  1138. /****************************************************************************
  1139. * Name: usbhost_getle32
  1140. *
  1141. * Description:
  1142. * Get a (possibly unaligned) 32-bit little endian value.
  1143. *
  1144. * Input Parameters:
  1145. * dest - A pointer to the first byte to save the big endian value.
  1146. * val - The 32-bit value to be saved.
  1147. *
  1148. * Returned Values:
  1149. * None
  1150. *
  1151. ****************************************************************************/
  1152. static inline uint32_t usbhost_getle32(const uint8_t *val)
  1153. {
  1154. /* Little endian means LS halfword first in byte stream */
  1155. return (uint32_t)usbhost_getle16(&val[2]) << 16 | (uint32_t)usbhost_getle16(val);
  1156. }
  1157. /****************************************************************************
  1158. * Name: usbhost_putle32
  1159. *
  1160. * Description:
  1161. * Put a (possibly unaligned) 32-bit little endian value.
  1162. *
  1163. * Input Parameters:
  1164. * dest - A pointer to the first byte to save the little endian value.
  1165. * val - The 32-bit value to be saved.
  1166. *
  1167. * Returned Values:
  1168. * None
  1169. *
  1170. ****************************************************************************/
  1171. #if 0 /* Not used */
  1172. static void usbhost_putle32(uint8_t *dest, uint32_t val)
  1173. {
  1174. /* Little endian means LS halfword first in byte stream */
  1175. usbhost_putle16(dest, (uint16_t)(val & 0xffff));
  1176. usbhost_putle16(dest+2, (uint16_t)(val >> 16));
  1177. }
  1178. #endif
  1179. /****************************************************************************
  1180. * Name: usbhost_talloc
  1181. *
  1182. * Description:
  1183. * Allocate transfer buffer memory.
  1184. *
  1185. * Input Parameters:
  1186. * priv - A reference to the class instance.
  1187. *
  1188. * Returned Values:
  1189. * On sucess, zero (OK) is returned. On failure, an negated errno value
  1190. * is returned to indicate the nature of the failure.
  1191. *
  1192. ****************************************************************************/
  1193. static inline int usbhost_talloc(FAR struct usbhost_state_s *priv)
  1194. {
  1195. FAR struct usbhost_hubport_s *hport;
  1196. DEBUGASSERT(priv != NULL && priv->usbclass.hport != NULL &&
  1197. priv->tbuffer == NULL);
  1198. hport = priv->usbclass.hport;
  1199. return DRVR_ALLOC(hport->drvr, &priv->tbuffer, &priv->tbuflen);
  1200. }
  1201. /****************************************************************************
  1202. * Name: usbhost_tfree
  1203. *
  1204. * Description:
  1205. * Free transfer buffer memory.
  1206. *
  1207. * Input Parameters:
  1208. * priv - A reference to the class instance.
  1209. *
  1210. * Returned Values:
  1211. * On sucess, zero (OK) is returned. On failure, an negated errno value
  1212. * is returned to indicate the nature of the failure.
  1213. *
  1214. ****************************************************************************/
  1215. static inline int usbhost_tfree(FAR struct usbhost_state_s *priv)
  1216. {
  1217. FAR struct usbhost_hubport_s *hport;
  1218. int result = OK;
  1219. DEBUGASSERT(priv != NULL && priv->usbclass.hport != NULL);
  1220. if (priv->tbuffer)
  1221. {
  1222. hport = priv->usbclass.hport;
  1223. result = DRVR_FREE(hport->drvr, priv->tbuffer);
  1224. priv->tbuffer = NULL;
  1225. priv->tbuflen = 0;
  1226. }
  1227. return result;
  1228. }
  1229. /****************************************************************************
  1230. * struct usbhost_registry_s methods
  1231. ****************************************************************************/
  1232. /****************************************************************************
  1233. * Name: usbhost_create
  1234. *
  1235. * Description:
  1236. * This function implements the create() method of struct usbhost_registry_s.
  1237. * The create() method is a callback into the class implementation. It is
  1238. * used to (1) create a new instance of the USB host class state and to (2)
  1239. * bind a USB host driver "session" to the class instance. Use of this
  1240. * create() method will support environments where there may be multiple
  1241. * USB ports and multiple USB devices simultaneously connected.
  1242. *
  1243. * Input Parameters:
  1244. * hport - The hub hat manages the new class instance.
  1245. * id - In the case where the device supports multiple base classes,
  1246. * subclasses, or protocols, this specifies which to configure for.
  1247. *
  1248. * Returned Values:
  1249. * On success, this function will return a non-NULL instance of struct
  1250. * usbhost_class_s that can be used by the USB host driver to communicate
  1251. * with the USB host class. NULL is returned on failure; this function
  1252. * will fail only if the hport input parameter is NULL or if there are
  1253. * insufficient resources to create another USB host class instance.
  1254. *
  1255. ****************************************************************************/
  1256. static FAR struct usbhost_class_s *usbhost_create(FAR struct usbhost_hubport_s *hport,
  1257. FAR const struct usbhost_id_s *id)
  1258. {
  1259. FAR struct usbhost_state_s *priv;
  1260. /* Allocate a USB host class instance */
  1261. priv = usbhost_allocclass();
  1262. if (priv)
  1263. {
  1264. /* Initialize the allocated storage class instance */
  1265. memset(priv, 0, sizeof(struct usbhost_state_s));
  1266. /* Assign a device number to this class instance */
  1267. if (usbhost_allocdevno(priv) == OK)
  1268. {
  1269. /* Initialize class method function pointers */
  1270. priv->usbclass.hport = hport;
  1271. priv->usbclass.connect = usbhost_connect;
  1272. priv->usbclass.disconnected = usbhost_disconnected;
  1273. /* The initial reference count is 1... One reference is held by the driver */
  1274. priv->crefs = 1;
  1275. /* Initialize semaphores (this works okay in the interrupt context) */
  1276. sem_init(&priv->exclsem, 0, 1);
  1277. sem_init(&priv->waitsem, 0, 0);
  1278. /* The waitsem semaphore is used for signaling and, hence, should
  1279. * not have priority inheritance enabled.
  1280. */
  1281. sem_setprotocol(&priv->waitsem, SEM_PRIO_NONE);
  1282. /* Return the instance of the USB class driver */
  1283. return &priv->usbclass;
  1284. }
  1285. }
  1286. /* An error occurred. Free the allocation and return NULL on all failures */
  1287. if (priv)
  1288. {
  1289. usbhost_freeclass(priv);
  1290. }
  1291. return NULL;
  1292. }
  1293. /****************************************************************************
  1294. * struct usbhost_class_s methods
  1295. ****************************************************************************/
  1296. /****************************************************************************
  1297. * Name: usbhost_connect
  1298. *
  1299. * Description:
  1300. * This function implements the connect() method of struct
  1301. * usbhost_class_s. This method is a callback into the class
  1302. * implementation. It is used to provide the device's configuration
  1303. * descriptor to the class so that the class may initialize properly
  1304. *
  1305. * Input Parameters:
  1306. * usbclass - The USB host class entry previously obtained from a call to
  1307. * create().
  1308. * configdesc - A pointer to a uint8_t buffer container the configuration
  1309. * descriptor.
  1310. * desclen - The length in bytes of the configuration descriptor.
  1311. *
  1312. * Returned Values:
  1313. * On success, zero (OK) is returned. On a failure, a negated errno value is
  1314. * returned indicating the nature of the failure
  1315. *
  1316. * NOTE that the class instance remains valid upon return with a failure. It is
  1317. * the responsibility of the higher level enumeration logic to call
  1318. * CLASS_DISCONNECTED to free up the class driver resources.
  1319. *
  1320. * Assumptions:
  1321. * - This function will *not* be called from an interrupt handler.
  1322. * - If this function returns an error, the USB host controller driver
  1323. * must call to DISCONNECTED method to recover from the error
  1324. *
  1325. ****************************************************************************/
  1326. static int usbhost_connect(FAR struct usbhost_class_s *usbclass,
  1327. FAR const uint8_t *configdesc, int desclen)
  1328. {
  1329. FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)usbclass;
  1330. int ret;
  1331. DEBUGASSERT(priv != NULL &&
  1332. configdesc != NULL &&
  1333. desclen >= sizeof(struct usb_cfgdesc_s));
  1334. /* Parse the configuration descriptor to get the endpoints */
  1335. ret = usbhost_cfgdesc(priv, configdesc, desclen);
  1336. if (ret < 0)
  1337. {
  1338. uerr("ERROR: usbhost_cfgdesc() failed: %d\n", ret);
  1339. }
  1340. else
  1341. {
  1342. /* Now configure the device and register the NuttX driver */
  1343. ret = usbhost_devinit(priv);
  1344. if (ret < 0)
  1345. {
  1346. uerr("ERROR: usbhost_devinit() failed: %d\n", ret);
  1347. }
  1348. }
  1349. return ret;
  1350. }
  1351. /****************************************************************************
  1352. * Name: usbhost_disconnected
  1353. *
  1354. * Description:
  1355. * This function implements the disconnected() method of struct
  1356. * usbhost_class_s. This method is a callback into the class
  1357. * implementation. It is used to inform the class that the USB device has
  1358. * been disconnected.
  1359. *
  1360. * Input Parameters:
  1361. * usbclass - The USB host class entry previously obtained from a call to
  1362. * create().
  1363. *
  1364. * Returned Values:
  1365. * On success, zero (OK) is returned. On a failure, a negated errno value
  1366. * is returned indicating the nature of the failure
  1367. *
  1368. * Assumptions:
  1369. * This function may be called from an interrupt handler.
  1370. *
  1371. ****************************************************************************/
  1372. static int usbhost_disconnected(struct usbhost_class_s *usbclass)
  1373. {
  1374. FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)usbclass;
  1375. int i;
  1376. DEBUGASSERT(priv != NULL);
  1377. /* Set an indication to any users of the device that the device is no
  1378. * longer available.
  1379. */
  1380. priv->disconnected = true;
  1381. uinfo("Disconnected\n");
  1382. /* Are there a thread(s) waiting for controller data that will never come? */
  1383. for (i = 0; i < priv->nwaiters; i++)
  1384. {
  1385. /* Yes.. wake them up */
  1386. usbhost_givesem(&priv->waitsem);
  1387. }
  1388. /* Possibilities:
  1389. *
  1390. * - Failure occurred before the controller poll task was started successfully.
  1391. * In this case, the disconnection will have to be handled on the worker
  1392. * task.
  1393. * - Failure occurred after the controller poll task was started successfully. In
  1394. * this case, the disconnection can be performed on the mouse poll thread.
  1395. */
  1396. if (priv->polling)
  1397. {
  1398. /* The polling task is still alive. Signal the mouse polling task.
  1399. * When that task wakes up, it will decrement the reference count and,
  1400. * perhaps, destroy the class instance. Then it will exit.
  1401. */
  1402. (void)kill(priv->pollpid, SIGALRM);
  1403. }
  1404. else
  1405. {
  1406. /* In the case where the failure occurs before the polling task was
  1407. * started. Now what? We are probably executing from an interrupt
  1408. * handler here. We will use the worker thread. This is kind of
  1409. * wasteful and begs for a re-design.
  1410. */
  1411. DEBUGASSERT(priv->work.worker == NULL);
  1412. (void)work_queue(HPWORK, &priv->work, usbhost_destroy, priv, 0);
  1413. }
  1414. return OK;
  1415. }
  1416. /****************************************************************************
  1417. * Character driver methods
  1418. ****************************************************************************/
  1419. /****************************************************************************
  1420. * Name: usbhost_open
  1421. *
  1422. * Description:
  1423. * Standard character driver open method.
  1424. *
  1425. ****************************************************************************/
  1426. static int usbhost_open(FAR struct file *filep)
  1427. {
  1428. FAR struct inode *inode;
  1429. FAR struct usbhost_state_s *priv;
  1430. irqstate_t flags;
  1431. int ret;
  1432. uinfo("Entry\n");
  1433. DEBUGASSERT(filep && filep->f_inode);
  1434. inode = filep->f_inode;
  1435. priv = inode->i_private;
  1436. /* Make sure that we have exclusive access to the private data structure */
  1437. DEBUGASSERT(priv && priv->crefs > 0 && priv->crefs < USBHOST_MAX_CREFS);
  1438. usbhost_takesem(&priv->exclsem);
  1439. /* Check if the controller device is still connected. We need to disable
  1440. * interrupts momentarily to assure that there are no asynchronous disconnect
  1441. * events.
  1442. */
  1443. flags = enter_critical_section();
  1444. if (priv->disconnected)
  1445. {
  1446. /* No... the driver is no longer bound to the class. That means that
  1447. * the USB storage device is no longer connected. Refuse any further
  1448. * attempts to open the driver.
  1449. */
  1450. ret = -ENODEV;
  1451. }
  1452. else
  1453. {
  1454. /* Was the driver previously open? We need to perform special
  1455. * initialization on the first time that the driver is opened.
  1456. */
  1457. if (!priv->open)
  1458. {
  1459. /* Set the thresholding values so that the first button press
  1460. * will be reported.
  1461. */
  1462. #ifdef NEVER
  1463. priv->xlast = INVALID_POSITION_B16;
  1464. priv->ylast = INVALID_POSITION_B16;
  1465. #ifdef CONFIG_MOUSE_WHEEL
  1466. priv->wlast = INVALID_POSITION_B16;
  1467. #endif
  1468. /* Set the reported position to the center of the range */
  1469. priv->xaccum = (HIDMOUSE_XMAX_B16 >> 1);
  1470. priv->yaccum = (HIDMOUSE_YMAX_B16 >> 1);
  1471. #endif
  1472. }
  1473. /* Otherwise, just increment the reference count on the driver */
  1474. priv->crefs++;
  1475. priv->open = true;
  1476. ret = OK;
  1477. }
  1478. leave_critical_section(flags);
  1479. usbhost_givesem(&priv->exclsem);
  1480. return ret;
  1481. }
  1482. /****************************************************************************
  1483. * Name: usbhost_close
  1484. *
  1485. * Description:
  1486. * Standard character driver close method.
  1487. *
  1488. ****************************************************************************/
  1489. static int usbhost_close(FAR struct file *filep)
  1490. {
  1491. FAR struct inode *inode;
  1492. FAR struct usbhost_state_s *priv;
  1493. irqstate_t flags;
  1494. uinfo("Entry\n");
  1495. DEBUGASSERT(filep && filep->f_inode);
  1496. inode = filep->f_inode;
  1497. priv = inode->i_private;
  1498. /* Decrement the reference count on the driver */
  1499. DEBUGASSERT(priv->crefs >= 1);
  1500. usbhost_takesem(&priv->exclsem);
  1501. /* We need to disable interrupts momentarily to assure that there are no
  1502. * asynchronous poll or disconnect events.
  1503. */
  1504. flags = enter_critical_section();
  1505. priv->crefs--;
  1506. /* Check if the USB controller device is still connected. If the device is
  1507. * no longer connected, then unregister the driver and free the driver
  1508. * class instance.
  1509. */
  1510. if (priv->disconnected)
  1511. {
  1512. /* If the reference count is one or less then there are two
  1513. * possibilities:
  1514. *
  1515. * 1) It might be zero meaning that the polling thread has already
  1516. * exited and decremented its count.
  1517. * 2) If might be one meaning either that (a) the polling thread is still
  1518. * running and still holds a count, or (b) the polling thread has exited,
  1519. * but there is still an outstanding open reference.
  1520. */
  1521. if (priv->crefs == 0 || (priv->crefs == 1 && priv->polling))
  1522. {
  1523. /* Yes.. In either case, then the driver is no longer open */
  1524. priv->open = false;
  1525. /* Check if the USB keyboard device is still connected. */
  1526. if (priv->crefs == 0)
  1527. {
  1528. /* The polling thread is no longer running */
  1529. DEBUGASSERT(!priv->polling);
  1530. /* If the device is no longer connected, unregister the driver
  1531. * and free the driver class instance.
  1532. */
  1533. usbhost_destroy(priv);
  1534. /* Skip giving the semaphore... it is no longer valid */
  1535. leave_critical_section(flags);
  1536. return OK;
  1537. }
  1538. else /* if (priv->crefs == 1) */
  1539. {
  1540. /* The polling thread is still running. Signal it so that it
  1541. * will wake up and call usbhost_destroy(). The particular
  1542. * signal that we use does not matter in this case.
  1543. */
  1544. (void)kill(priv->pollpid, SIGALRM);
  1545. }
  1546. }
  1547. }
  1548. usbhost_givesem(&priv->exclsem);
  1549. leave_critical_section(flags);
  1550. return OK;
  1551. }
  1552. /****************************************************************************
  1553. * Name: usbhost_read
  1554. *
  1555. * Description:
  1556. * Standard character driver read method.
  1557. *
  1558. ****************************************************************************/
  1559. static ssize_t usbhost_read(FAR struct file *filep, FAR char *buffer, size_t len)
  1560. {
  1561. FAR struct inode *inode;
  1562. FAR struct usbhost_state_s *priv;
  1563. FAR struct xbox_controller_buttonstate_s sample;
  1564. int ret;
  1565. DEBUGASSERT(filep && filep->f_inode && buffer);
  1566. inode = filep->f_inode;
  1567. priv = inode->i_private;
  1568. /* Make sure that we have exclusive access to the private data structure */
  1569. DEBUGASSERT(priv && priv->crefs > 0 && priv->crefs < USBHOST_MAX_CREFS);
  1570. usbhost_takesem(&priv->exclsem);
  1571. /* Check if the controller is still connected. We need to disable interrupts
  1572. * momentarily to assure that there are no asynchronous disconnect events.
  1573. */
  1574. if (priv->disconnected)
  1575. {
  1576. /* No... the driver is no longer bound to the class. That means that
  1577. * the USB controller is no longer connected. Refuse any further attempts
  1578. * to access the driver.
  1579. */
  1580. ret = -ENODEV;
  1581. goto errout;
  1582. }
  1583. /* Try to read sample data. */
  1584. ret = usbhost_sample(priv, &sample);
  1585. if (ret < 0)
  1586. {
  1587. /* Sample data is not available now. We would ave to wait to get
  1588. * receive sample data. If the user has specified the O_NONBLOCK
  1589. * option, then just return an error.
  1590. */
  1591. if (filep->f_oflags & O_NONBLOCK)
  1592. {
  1593. /* Yes.. then return a failure */
  1594. ret = -EAGAIN;
  1595. goto errout;
  1596. }
  1597. /* Wait for sample data */
  1598. ret = usbhost_waitsample(priv, &sample);
  1599. ret = 0;
  1600. if (ret < 0)
  1601. {
  1602. /* We might have been awakened by a signal */
  1603. ierr("ERROR: usbhost_waitsample: %d\n", ret);
  1604. goto errout;
  1605. }
  1606. }
  1607. /* We now have sampled controller data that we can report to the caller. */
  1608. memcpy(buffer, &sample, sizeof(struct xbox_controller_buttonstate_s));
  1609. ret = sizeof(struct xbox_controller_buttonstate_s);
  1610. errout:
  1611. usbhost_givesem(&priv->exclsem);
  1612. iinfo("Returning: %d\n", ret);
  1613. return (ssize_t)ret;
  1614. }
  1615. /****************************************************************************
  1616. * Name: usbhost_write
  1617. *
  1618. * Description:
  1619. * Standard character driver write method.
  1620. *
  1621. ****************************************************************************/
  1622. static ssize_t usbhost_write(FAR struct file *filep, FAR const char *buffer,
  1623. size_t len)
  1624. {
  1625. /* Not implemented. */
  1626. return -ENOSYS;
  1627. }
  1628. /****************************************************************************
  1629. * Name: usbhost_ioctl
  1630. *
  1631. * Description:
  1632. * Standard character driver ioctl method.
  1633. *
  1634. ****************************************************************************/
  1635. static int usbhost_ioctl(FAR struct file* filep, int cmd, unsigned long arg)
  1636. {
  1637. FAR struct inode *inode;
  1638. FAR struct usbhost_state_s *priv;
  1639. int ret = 0;
  1640. int nbytes;
  1641. FAR struct usbhost_hubport_s *hport;
  1642. static uint8_t rumble_cmd[] =
  1643. {
  1644. 0x09, 0x00, 0x00, 0x09, 0x00, 0x0f, 0x00,
  1645. 0x00, 0x00, 0x00, 0xff, 0x00, 0xff
  1646. };
  1647. uinfo("Entered\n");
  1648. DEBUGASSERT(filep && filep->f_inode && buffer);
  1649. inode = filep->f_inode;
  1650. priv = inode->i_private;
  1651. hport = priv->usbclass.hport;
  1652. /* Check if the controller is still connected. We need to disable interrupts
  1653. * momentarily to assure that there are no asynchronous disconnect events.
  1654. */
  1655. if (priv->disconnected)
  1656. {
  1657. /* No... the driver is no longer bound to the class. That means that
  1658. * the USB controller is no longer connected. Refuse any further attempts
  1659. * to access the driver.
  1660. */
  1661. ret = -ENODEV;
  1662. goto errout;
  1663. }
  1664. /* Determine which IOCTL command to execute. */
  1665. switch (cmd)
  1666. {
  1667. case XBOX_CONTROLLER_IOCTL_RUMBLE:
  1668. /* The least significant byte is the weak actuator strength.
  1669. * The second byte is the strong actuator strength.
  1670. */
  1671. memcpy(priv->obuffer, rumble_cmd, sizeof(rumble_cmd));
  1672. priv->obuffer[2] = priv->out_seq_num++;
  1673. priv->obuffer[8] = (arg >> 1) & 0xff; // Strong (left actuator)
  1674. priv->obuffer[9] = arg & 0xff; // Weak (right actuator)
  1675. /* Perform the transfer. */
  1676. nbytes = DRVR_TRANSFER(hport->drvr, priv->epout,
  1677. priv->obuffer, sizeof(rumble_cmd));
  1678. /* Did we encounter an error? */
  1679. if (nbytes < 0)
  1680. {
  1681. ret = nbytes;
  1682. }
  1683. break;
  1684. default:
  1685. ret = -EINVAL;
  1686. goto errout;
  1687. }
  1688. errout:
  1689. iinfo("Returning: %d\n", ret);
  1690. return ret;
  1691. }
  1692. /****************************************************************************
  1693. * Name: usbhost_poll
  1694. *
  1695. * Description:
  1696. * Standard character driver poll method.
  1697. *
  1698. ****************************************************************************/
  1699. #ifndef CONFIG_DISABLE_POLL
  1700. static int usbhost_poll(FAR struct file *filep, FAR struct pollfd *fds,
  1701. bool setup)
  1702. {
  1703. FAR struct inode *inode;
  1704. FAR struct usbhost_state_s *priv;
  1705. int ret = OK;
  1706. int i;
  1707. DEBUGASSERT(filep && filep->f_inode && fds);
  1708. inode = filep->f_inode;
  1709. priv = inode->i_private;
  1710. /* Make sure that we have exclusive access to the private data structure */
  1711. DEBUGASSERT(priv);
  1712. usbhost_takesem(&priv->exclsem);
  1713. /* Check if the controller is still connected. We need to disable interrupts
  1714. * momentarily to assure that there are no asynchronous disconnect events.
  1715. */
  1716. if (priv->disconnected)
  1717. {
  1718. /* No... the driver is no longer bound to the class. That means that
  1719. * the USB controller is no longer connected. Refuse any further attempts
  1720. * to access the driver.
  1721. */
  1722. ret = -ENODEV;
  1723. }
  1724. else if (setup)
  1725. {
  1726. /* This is a request to set up the poll. Find an available slot for
  1727. * the poll structure reference
  1728. */
  1729. for (i = 0; i < CONFIG_XBOXCONTROLLER_NPOLLWAITERS; i++)
  1730. {
  1731. /* Find an available slot */
  1732. if (!priv->fds[i])
  1733. {
  1734. /* Bind the poll structure and this slot */
  1735. priv->fds[i] = fds;
  1736. fds->priv = &priv->fds[i];
  1737. break;
  1738. }
  1739. }
  1740. if (i >= CONFIG_XBOXCONTROLLER_NPOLLWAITERS)
  1741. {
  1742. fds->priv = NULL;
  1743. ret = -EBUSY;
  1744. goto errout;
  1745. }
  1746. /* Should we immediately notify on any of the requested events? Notify
  1747. * the POLLIN event if there is buffered controller data.
  1748. */
  1749. if (priv->valid)
  1750. {
  1751. usbhost_pollnotify(priv);
  1752. }
  1753. }
  1754. else
  1755. {
  1756. /* This is a request to tear down the poll. */
  1757. struct pollfd **slot = (struct pollfd **)fds->priv;
  1758. DEBUGASSERT(slot);
  1759. /* Remove all memory of the poll setup */
  1760. *slot = NULL;
  1761. fds->priv = NULL;
  1762. }
  1763. errout:
  1764. sem_post(&priv->exclsem);
  1765. return ret;
  1766. }
  1767. #endif
  1768. /****************************************************************************
  1769. * Public Functions
  1770. ****************************************************************************/
  1771. /****************************************************************************
  1772. * Name: usbhost_xboxcontroller_init
  1773. *
  1774. * Description:
  1775. * Initialize the USB class driver. This function should be called
  1776. * be platform-specific code in order to initialize and register support
  1777. * for the USB host class device.
  1778. *
  1779. * Input Parameters:
  1780. * None
  1781. *
  1782. * Returned Values:
  1783. * On success this function will return zero (OK); A negated errno value
  1784. * will be returned on failure.
  1785. *
  1786. ****************************************************************************/
  1787. int usbhost_xboxcontroller_init(void)
  1788. {
  1789. /* Perform any one-time initialization of the class implementation */
  1790. sem_init(&g_exclsem, 0, 1);
  1791. sem_init(&g_syncsem, 0, 0);
  1792. /* The g_syncsem semaphore is used for signaling and, hence, should not
  1793. * have priority inheritance enabled.
  1794. */
  1795. sem_setprotocol(&g_syncsem, SEM_PRIO_NONE);
  1796. /* Advertise our availability to support (certain) devices */
  1797. return usbhost_registerclass(&g_xboxcontroller);
  1798. }