usbhost_hidkbd.c 76 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353
  1. /****************************************************************************
  2. * drivers/usbhost/usbhost_hidkbd.c
  3. *
  4. * Copyright (C) 2011-2012 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. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Included Files
  37. ****************************************************************************/
  38. #include <nuttx/config.h>
  39. #include <sys/types.h>
  40. #include <stdbool.h>
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <unistd.h>
  44. #include <string.h>
  45. #include <poll.h>
  46. #include <semaphore.h>
  47. #include <time.h>
  48. #include <fcntl.h>
  49. #include <assert.h>
  50. #include <errno.h>
  51. #include <debug.h>
  52. #include <nuttx/kmalloc.h>
  53. #include <nuttx/fs/fs.h>
  54. #include <nuttx/arch.h>
  55. #include <nuttx/wqueue.h>
  56. #include <nuttx/usb/usb.h>
  57. #include <nuttx/usb/usbhost.h>
  58. #include <nuttx/usb/hid.h>
  59. #ifdef CONFIG_HIDKBD_ENCODED
  60. # include <nuttx/streams.h>
  61. # include <nuttx/input/kbd_codec.h>
  62. #endif
  63. /* Don't compile if prerequisites are not met */
  64. #if defined(CONFIG_USBHOST) && !defined(CONFIG_USBHOST_INT_DISABLE) && CONFIG_NFILE_DESCRIPTORS > 0
  65. /****************************************************************************
  66. * Pre-processor Definitions
  67. ****************************************************************************/
  68. /* Configuration ************************************************************/
  69. /* This determines how often the USB keyboard will be polled in units of
  70. * of microseconds. The default is 100MS.
  71. */
  72. #ifndef CONFIG_HIDKBD_POLLUSEC
  73. # define CONFIG_HIDKBD_POLLUSEC (100*1000)
  74. #endif
  75. /* Worker thread is needed, unfortunately, to handle some cornercase failure
  76. * conditions. This is kind of wasteful and begs for a re-design.
  77. */
  78. #ifndef CONFIG_SCHED_WORKQUEUE
  79. # warning "Worker thread support is required (CONFIG_SCHED_WORKQUEUE)"
  80. #endif
  81. /* Signals must not be disabled as they are needed by usleep. Need to have
  82. * CONFIG_DISABLE_SIGNALS=n
  83. */
  84. #ifdef CONFIG_DISABLE_SIGNALS
  85. # warning "Signal support is required (CONFIG_DISABLE_SIGNALS)"
  86. #endif
  87. /* Provide some default values for other configuration settings */
  88. #ifndef CONFIG_HIDKBD_DEFPRIO
  89. # define CONFIG_HIDKBD_DEFPRIO 50
  90. #endif
  91. #ifndef CONFIG_HIDKBD_STACKSIZE
  92. # define CONFIG_HIDKBD_STACKSIZE 1024
  93. #endif
  94. #ifndef CONFIG_HIDKBD_BUFSIZE
  95. # define CONFIG_HIDKBD_BUFSIZE 64
  96. #endif
  97. #ifndef CONFIG_HIDKBD_NPOLLWAITERS
  98. # define CONFIG_HIDKBD_NPOLLWAITERS 2
  99. #endif
  100. /* The default is to support scancode mapping for the standard 104 key
  101. * keyboard. Setting CONFIG_HIDKBD_RAWSCANCODES will disable all scancode
  102. * mapping; Setting CONFIG_HIDKBD_ALLSCANCODES will enable mapping of all
  103. * scancodes;
  104. */
  105. #ifndef CONFIG_HIDKBD_RAWSCANCODES
  106. # ifdef CONFIG_HIDKBD_ALLSCANCODES
  107. # define USBHID_NUMSCANCODES (USBHID_KBDUSE_MAX+1)
  108. # else
  109. # define USBHID_NUMSCANCODES 104
  110. # endif
  111. #endif
  112. /* We cant support encoding of special characters of unless the Keyboard
  113. * CODEC is enabled.
  114. */
  115. #ifndef CONFIG_LIB_KBDCODEC
  116. # undef CONFIG_HIDKBD_ENCODED
  117. #endif
  118. /* If we are using raw scancodes, then we cannot support encoding of
  119. * special characters either.
  120. */
  121. #ifdef CONFIG_HIDKBD_RAWSCANCODES
  122. # undef CONFIG_HIDKBD_ENCODED
  123. #endif
  124. /* Driver support ***********************************************************/
  125. /* This format is used to construct the /dev/kbd[n] device driver path. It
  126. * defined here so that it will be used consistently in all places.
  127. */
  128. #define DEV_FORMAT "/dev/kbd%c"
  129. #define DEV_NAMELEN 11
  130. /* Used in usbhost_cfgdesc() */
  131. #define USBHOST_IFFOUND 0x01 /* Required I/F descriptor found */
  132. #define USBHOST_EPINFOUND 0x02 /* Required interrupt IN EP descriptor found */
  133. #define USBHOST_EPOUTFOUND 0x04 /* Optional interrupt OUT EP descriptor found */
  134. #define USBHOST_RQDFOUND (USBHOST_IFFOUND|USBHOST_EPINFOUND)
  135. #define USBHOST_ALLFOUND (USBHOST_RQDFOUND|USBHOST_EPOUTFOUND)
  136. #define USBHOST_MAX_CREFS 0x7fff
  137. /* Debug ********************************************************************/
  138. /* Both CONFIG_DEBUG_INPUT and CONFIG_DEBUG_USB could apply to this file.
  139. * We assume here that CONFIG_DEBUG_INPUT might be enabled separately, but
  140. * CONFIG_DEBUG_USB implies both.
  141. */
  142. #ifndef CONFIG_DEBUG_INPUT
  143. # undef idbg
  144. # define idbg udbg
  145. # undef illdbg
  146. # define illdbg ulldbg
  147. # undef ivdbg
  148. # define ivdbg uvdbg
  149. # undef illvdbg
  150. # define illvdbg ullvdbg
  151. #endif
  152. /****************************************************************************
  153. * Private Types
  154. ****************************************************************************/
  155. /* This structure contains the internal, private state of the USB host
  156. * keyboard storage class.
  157. */
  158. struct usbhost_state_s
  159. {
  160. /* This is the externally visible portion of the state */
  161. struct usbhost_class_s class;
  162. /* This is an instance of the USB host driver bound to this class instance */
  163. struct usbhost_driver_s *drvr;
  164. /* The remainder of the fields are provide o the keyboard class driver */
  165. char devchar; /* Character identifying the /dev/kbd[n] device */
  166. volatile bool disconnected; /* TRUE: Device has been disconnected */
  167. volatile bool polling; /* TRUE: Poll thread is running */
  168. volatile bool open; /* TRUE: The keyboard device is open */
  169. volatile bool waiting; /* TRUE: waiting for keyboard data */
  170. uint8_t ifno; /* Interface number */
  171. int16_t crefs; /* Reference count on the driver instance */
  172. sem_t exclsem; /* Used to maintain mutual exclusive access */
  173. sem_t waitsem; /* Used to wait for keyboard data */
  174. FAR uint8_t *tbuffer; /* The allocated transfer buffer */
  175. size_t tbuflen; /* Size of the allocated transfer buffer */
  176. pid_t pollpid; /* PID of the poll task */
  177. struct work_s work; /* For cornercase error handling by the worker thread */
  178. /* Endpoints:
  179. * EP0 (Control):
  180. * - Receiving and responding to requests for USB control and class data.
  181. * - IN data when polled by the HID class driver (Get_Report)
  182. * - OUT data from the host.
  183. * EP Interrupt IN:
  184. * - Receiving asynchronous (unrequested) IN data from the device.
  185. * EP Interrrupt OUT (optional):
  186. * - Transmitting low latency OUT data to the device.
  187. * - If not present, EP0 used.
  188. */
  189. usbhost_ep_t epin; /* Interrupt IN endpoint */
  190. usbhost_ep_t epout; /* Optional interrupt OUT endpoint */
  191. /* The following is a list if poll structures of threads waiting for
  192. * driver events. The 'struct pollfd' reference for each open is also
  193. * retained in the f_priv field of the 'struct file'.
  194. */
  195. #ifndef CONFIG_DISABLE_POLL
  196. struct pollfd *fds[CONFIG_HIDKBD_NPOLLWAITERS];
  197. #endif
  198. /* Buffer used to collect and buffer incoming keyboard characters */
  199. volatile uint16_t headndx; /* Buffer head index */
  200. volatile uint16_t tailndx; /* Buffer tail index */
  201. uint8_t kbdbuffer[CONFIG_HIDKBD_BUFSIZE];
  202. };
  203. /* This type is used for encoding special characters */
  204. #ifdef CONFIG_HIDKBD_ENCODED
  205. struct usbhost_outstream_s
  206. {
  207. struct lib_outstream_s stream;
  208. FAR struct usbhost_state_s *priv;
  209. };
  210. #endif
  211. /****************************************************************************
  212. * Private Function Prototypes
  213. ****************************************************************************/
  214. /* Semaphores */
  215. static void usbhost_takesem(sem_t *sem);
  216. #define usbhost_givesem(s) sem_post(s);
  217. /* Polling support */
  218. #ifndef CONFIG_DISABLE_POLL
  219. static void usbhost_pollnotify(FAR struct usbhost_state_s *dev);
  220. #else
  221. # define usbhost_pollnotify(dev)
  222. #endif
  223. /* Memory allocation services */
  224. static inline FAR struct usbhost_state_s *usbhost_allocclass(void);
  225. static inline void usbhost_freeclass(FAR struct usbhost_state_s *class);
  226. /* Device name management */
  227. static int usbhost_allocdevno(FAR struct usbhost_state_s *priv);
  228. static void usbhost_freedevno(FAR struct usbhost_state_s *priv);
  229. static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv, char *devname);
  230. /* Keyboard polling thread */
  231. static void usbhost_destroy(FAR void *arg);
  232. static void usbhost_putbuffer(FAR struct usbhost_state_s *priv, uint8_t keycode);
  233. #ifdef CONFIG_HIDKBD_ENCODED
  234. static void usbhost_putstream(FAR struct lib_outstream_s *this, int ch);
  235. #endif
  236. static inline uint8_t usbhost_mapscancode(uint8_t scancode, uint8_t modifier);
  237. #ifdef CONFIG_HIDKBD_ENCODED
  238. static inline void usbhost_encodescancode(FAR struct usbhost_state_s *priv,
  239. uint8_t scancode, uint8_t modifier);
  240. #endif
  241. static int usbhost_kbdpoll(int argc, char *argv[]);
  242. /* Helpers for usbhost_connect() */
  243. static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv,
  244. FAR const uint8_t *configdesc, int desclen,
  245. uint8_t funcaddr);
  246. static inline int usbhost_devinit(FAR struct usbhost_state_s *priv);
  247. /* (Little Endian) Data helpers */
  248. static inline uint16_t usbhost_getle16(const uint8_t *val);
  249. static inline void usbhost_putle16(uint8_t *dest, uint16_t val);
  250. static inline uint32_t usbhost_getle32(const uint8_t *val);
  251. #if 0 /* Not used */
  252. static void usbhost_putle32(uint8_t *dest, uint32_t val);
  253. #endif
  254. /* Transfer descriptor memory management */
  255. static inline int usbhost_tdalloc(FAR struct usbhost_state_s *priv);
  256. static inline int usbhost_tdfree(FAR struct usbhost_state_s *priv);
  257. /* struct usbhost_registry_s methods */
  258. static struct usbhost_class_s *usbhost_create(FAR struct usbhost_driver_s *drvr,
  259. FAR const struct usbhost_id_s *id);
  260. /* struct usbhost_class_s methods */
  261. static int usbhost_connect(FAR struct usbhost_class_s *class,
  262. FAR const uint8_t *configdesc, int desclen,
  263. uint8_t funcaddr);
  264. static int usbhost_disconnected(FAR struct usbhost_class_s *class);
  265. /* Driver methods. We export the keyboard as a standard character driver */
  266. static int usbhost_open(FAR struct file *filep);
  267. static int usbhost_close(FAR struct file *filep);
  268. static ssize_t usbhost_read(FAR struct file *filep,
  269. FAR char *buffer, size_t len);
  270. static ssize_t usbhost_write(FAR struct file *filep,
  271. FAR const char *buffer, size_t len);
  272. #ifndef CONFIG_DISABLE_POLL
  273. static int usbhost_poll(FAR struct file *filep, FAR struct pollfd *fds,
  274. bool setup);
  275. #endif
  276. /****************************************************************************
  277. * Private Data
  278. ****************************************************************************/
  279. /* This structure provides the registry entry ID informatino that will be
  280. * used to associate the USB host keyboard class driver to a connected USB
  281. * device.
  282. */
  283. static const const struct usbhost_id_s g_id =
  284. {
  285. USB_CLASS_HID, /* base */
  286. USBHID_SUBCLASS_BOOTIF, /* subclass */
  287. USBHID_PROTOCOL_KEYBOARD, /* proto */
  288. 0, /* vid */
  289. 0 /* pid */
  290. };
  291. /* This is the USB host storage class's registry entry */
  292. static struct usbhost_registry_s g_skeleton =
  293. {
  294. NULL, /* flink */
  295. usbhost_create, /* create */
  296. 1, /* nids */
  297. &g_id /* id[] */
  298. };
  299. static const struct file_operations usbhost_fops =
  300. {
  301. usbhost_open, /* open */
  302. usbhost_close, /* close */
  303. usbhost_read, /* read */
  304. usbhost_write, /* write */
  305. 0, /* seek */
  306. 0 /* ioctl */
  307. #ifndef CONFIG_DISABLE_POLL
  308. , usbhost_poll /* poll */
  309. #endif
  310. };
  311. /* This is a bitmap that is used to allocate device names /dev/kbda-z. */
  312. static uint32_t g_devinuse;
  313. /* The following are used to managed the class creation operation */
  314. static sem_t g_exclsem; /* For mutually exclusive thread creation */
  315. static sem_t g_syncsem; /* Thread data passing interlock */
  316. static struct usbhost_state_s *g_priv; /* Data passed to thread */
  317. /* The following tables map keyboard scan codes to printable ASIC
  318. * characters. There is no support here for function keys or cursor
  319. * controls.
  320. */
  321. #ifndef CONFIG_HIDKBD_RAWSCANCODES
  322. #ifdef CONFIG_HIDKBD_ENCODED
  323. /* The first and last scancode values with encode-able values */
  324. #define FIRST_ENCODING USBHID_KBDUSE_ENTER /* 0x28 Keyboard Return (ENTER) */
  325. #ifndef CONFIG_HIDKBD_ALLSCANCODES
  326. # define LAST_ENCODING USBHID_KBDUSE_POWER /* 0x66 Keyboard Power */
  327. #else
  328. # define LAST_ENCODING USBHID_KBDUSE_KPDHEXADECIMAL /* 0xdd Keypad Hexadecimal */
  329. #endif
  330. #define USBHID_NUMENCODINGS (LAST_ENCODING - FIRST_ENCODING + 1)
  331. static const uint8_t encoding[USBHID_NUMENCODINGS] =
  332. {
  333. /* 0x28-0x2f: Enter,escape,del,back-tab,space,_,+,{ */
  334. KEYCODE_ENTER, 0, KEYCODE_FWDDEL, KEYCODE_BACKDEL, 0, 0, 0, 0,
  335. /* 0x30-0x37: },|,Non-US tilde,:,",grave tilde,<,> */
  336. 0, 0, 0, 0, 0, 0, 0, 0,
  337. /* 0x38-0x3f: /,CapsLock,F1,F2,F3,F4,F5,F6 */
  338. 0, KEYCODE_CAPSLOCK, KEYCODE_F1, KEYCODE_F2, KEYCODE_F3, KEYCODE_F4, KEYCODE_F5, KEYCODE_F6,
  339. /* 0x40-0x47: F7,F8,F9,F10,F11,F12,PrtScn,ScrollLock */
  340. KEYCODE_F7, KEYCODE_F8, KEYCODE_F9, KEYCODE_F10, KEYCODE_F11, KEYCODE_F12, KEYCODE_PRTSCRN, KEYCODE_SCROLLLOCK,
  341. /* 0x48-0x4f: Pause,Insert,Home,PageUp,DeleteForward,End,PageDown,RightArrow */
  342. KEYCODE_PAUSE, KEYCODE_INSERT, KEYCODE_HOME, KEYCODE_PAGEUP, KEYCODE_FWDDEL, KEYCODE_END, KEYCODE_PAGEDOWN, KEYCODE_RIGHT,
  343. /* 0x50-0x57: LeftArrow,DownArrow,UpArrow,Num Lock,/,*,-,+ */
  344. KEYCODE_LEFT, KEYCODE_DOWN, KEYCODE_UP, KEYCODE_NUMLOCK, 0, 0, 0, 0,
  345. /* 0x58-0x5f: Enter,1-7 */
  346. KEYCODE_ENTER, 0, 0, 0, 0, 0, 0, 0,
  347. /* 0x60-0x66: 8-9,0,.,Non-US \,Application,Power */
  348. 0, 0, 0, 0, 0, 0, KEYCODE_POWER,
  349. #ifdef CONFIG_HIDKBD_ALLSCANCODES
  350. 0, /* 0x67 = */
  351. /* 0x68-0x6f: F13,F14,F15,F16,F17,F18,F19,F20 */
  352. KEYCODE_F13, KEYCODE_F14, KEYCODE_F15, KEYCODE_F16, KEYCODE_F17, KEYCODE_F18, KEYCODE_F19, KEYCODE_F20,
  353. /* 0x70-0x77: F21,F22,F23,F24,Execute,Help,Menu,Select */
  354. KEYCODE_F21, KEYCODE_F22, KEYCODE_F23, KEYCODE_F24, KEYCODE_EXECUTE, KEYCODE_HELP, KEYCODE_MENU, KEYCODE_SELECT,
  355. /* 0x78-0x7f: Stop,Again,Undo,Cut,Copy,Paste,Find,Mute */
  356. KEYCODE_STOP, KEYCODE_AGAIN, KEYCODE_UNDO, KEYCODE_CUT, KEYCODE_COPY, KEYCODE_PASTE, KEYCODE_FIND, KEYCODE_MUTE,
  357. /* 0x80-0x87: VolUp,VolDown,LCapsLock,lNumLock,LScrollLock,,,=,International1 */
  358. KEYCODE_VOLUP, KEYCODE_VOLDOWN, KEYCODE_LCAPSLOCK, KEYCODE_LNUMLOCK, KEYCODE_LSCROLLLOCK, 0, 0, 0,
  359. /* 0x88-0x8f: International 2-9 */
  360. 0, 0, 0, 0, 0, 0, 0, 0,
  361. /* 0x90-0x97: LAN 1-8 */
  362. KEYCODE_LANG1, KEYCODE_LANG2, KEYCODE_LANG3, KEYCODE_LANG4, KEYCODE_LANG5, KEYCODE_LANG6, KEYCODE_LANG7, KEYCODE_LANG8,
  363. /* 0x98-0x9f: LAN 9,Erase,SysReq,Cancel,Clear,Prior,Return,Separator */
  364. 0, 0, KEYCODE_SYSREQ, KEYCODE_CANCEL, KEYCODE_CLEAR, 0, KEYCODE_ENTER, 0,
  365. /* 0xa0-0xa7: Out,Oper,Clear,CrSel,Excel,(reserved) */
  366. 0, 0, 0, 0, 0, 0, 0, 0,
  367. /* 0xa8-0xaf: (reserved) */
  368. 0, 0, 0, 0, 0, 0, 0, 0,
  369. /* 0xb0-0xb7: 00,000,ThouSeparator,DecSeparator,CurrencyUnit,SubUnit,(,) */
  370. 0, 0, 0, 0, 0, 0, 0, 0,
  371. /* 0xb8-0xbf: {,},tab,backspace,A-D */
  372. 0, 0, 0, KEYCODE_BACKDEL, 0, 0, 0, 0,
  373. /* 0xc0-0xc7: E-F,XOR,^,%,<,>,& */
  374. 0, 0, 0, 0, 0, 0, 0, 0,
  375. /* 0xc8-0xcf: &&,|,||,:,#, ,@,! */
  376. 0, 0, 0, 0, 0, 0, 0, 0,
  377. /* 0xd0-0xd7: Memory Store,Recall,Clear,Add,Subtract,Muliply,Divide,+/- */
  378. KEYCODE_MEMSTORE, KEYCODE_MEMRECALL, KEYCODE_MEMCLEAR, KEYCODE_MEMADD, KEYCODE_MEMSUB, KEYCODE_MEMMUL, KEYCODE_MEMDIV, KEYCODE_NEGATE,
  379. /* 0xd8-0xdd: Clear,ClearEntry,Binary,Octal,Decimal,Hexadecimal */
  380. KEYCODE_CLEAR, KEYCODE_CLEARENTRY, KEYCODE_BINARY, KEYCODE_OCTAL, KEYCODE_DECIMAL, KEYCODE_HEXADECIMAL
  381. #endif
  382. };
  383. #endif
  384. static const uint8_t ucmap[USBHID_NUMSCANCODES] =
  385. {
  386. 0, 0, 0, 0, 'A', 'B', 'C', 'D', /* 0x00-0x07: Reserved, errors, A-D */
  387. 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', /* 0x08-0x0f: E-L */
  388. 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', /* 0x10-0x17: M-T */
  389. 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', /* 0x18-0x1f: U-Z,!,@ */
  390. '#', '$', '%', '^', '&', '*', '(', ')', /* 0x20-0x27: #,$,%,^,&,*,(,) */
  391. '\n', '\033', '\177', 0, ' ', '_', '+', '{', /* 0x28-0x2f: Enter,escape,del,back-tab,space,_,+,{ */
  392. '}', '|', 0, ':', '"', '~', '<', '>', /* 0x30-0x37: },|,Non-US tilde,:,",grave tilde,<,> */
  393. '?', 0, 0, 0, 0, 0, 0, 0, /* 0x38-0x3f: /,CapsLock,F1,F2,F3,F4,F5,F6 */
  394. 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40-0x47: F7,F8,F9,F10,F11,F12,PrtScn,ScrollLock */
  395. 0, 0, 0, 0, 0, 0, 0, 0, /* 0x48-0x4f: Pause,Insert,Home,PageUp,DeleteForward,End,PageDown,RightArrow */
  396. 0, 0, 0, 0, '/', '*', '-', '+', /* 0x50-0x57: LeftArrow,DownArrow,UpArrow,Num Lock,/,*,-,+ */
  397. '\n', '1', '2', '3', '4', '5', '6', '7', /* 0x58-0x5f: Enter,1-7 */
  398. '8', '9', '0', '.', 0, 0, 0, '=', /* 0x60-0x67: 8-9,0,.,Non-US \,Application,Power,= */
  399. #ifdef CONFIG_HIDKBD_ALLSCANCODES
  400. 0, 0, 0, 0, 0, 0, 0, 0, /* 0x68-0x6f: F13,F14,F15,F16,F17,F18,F19,F20 */
  401. 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77: F21,F22,F23,F24,Execute,Help,Menu,Select */
  402. 0, 0, 0, 0, 0, 0, 0, 0, /* 0x78-0x7f: Stop,Again,Undo,Cut,Copy,Paste,Find,Mute */
  403. 0, 0, 0, 0, 0, ',', 0, 0, /* 0x80-0x87: VolUp,VolDown,LCapsLock,lNumLock,LScrollLock,,,=,International1 */
  404. 0, 0, 0, 0, 0, 0, 0, 0, /* 0x88-0x8f: International 2-9 */
  405. 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x97: LAN 1-8 */
  406. 0, 0, 0, 0, 0, 0, '\n', 0, /* 0x98-0x9f: LAN 9,Erase,SysReq,Cancel,Clear,Prior,Return,Separator */
  407. 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0-0xa7: Out,Oper,Clear,CrSel,Excel,(reserved) */
  408. 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa8-0xaf: (reserved) */
  409. 0, 0, 0, 0, 0, 0, '(', ')', /* 0xb0-0xb7: 00,000,ThouSeparator,DecSeparator,CurrencyUnit,SubUnit,(,) */
  410. '{', '}', '\t', \177, 'A', 'B', 'C', 'D', /* 0xb8-0xbf: {,},tab,backspace,A-D */
  411. 'F', 'F', 0, '^', '%', '<', '>', '&', /* 0xc0-0xc7: E-F,XOR,^,%,<,>,& */
  412. 0, '|', 0, ':', '%', ' ', '@', '!', /* 0xc8-0xcf: &&,|,||,:,#, ,@,! */
  413. 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0-0xd7: Memory Store,Recall,Clear,Add,Subtract,Muliply,Divide,+/- */
  414. 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd8-0xdf: Clear,ClearEntry,Binary,Octal,Decimal,Hexadecimal */
  415. 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0-0xe7: Left Ctrl,Shift,Alt,GUI, Right Ctrl,Shift,Alt,GUI */
  416. #endif
  417. };
  418. static const uint8_t lcmap[USBHID_NUMSCANCODES] =
  419. {
  420. 0, 0, 0, 0, 'a', 'b', 'c', 'd', /* 0x00-0x07: Reserved, errors, a-d */
  421. 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', /* 0x08-0x0f: e-l */
  422. 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', /* 0x10-0x17: m-t */
  423. 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', /* 0x18-0x1f: u-z,1-2 */
  424. '3', '4', '5', '6', '7', '8', '9', '0', /* 0x20-0x27: 3-9,0 */
  425. '\n', '\033', '\177', '\t', ' ', '-', '=', '[', /* 0x28-0x2f: Enter,escape,del,tab,space,-,=,[ */
  426. ']', '\\', '\234', ';', '\'', '`', ',', '.', /* 0x30-0x37: ],\,Non-US pound,;,',grave accent,,,. */
  427. '/', 0, 0, 0, 0, 0, 0, 0, /* 0x38-0x3f: /,CapsLock,F1,F2,F3,F4,F5,F6 */
  428. 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40-0x47: F7,F8,F9,F10,F11,F12,PrtScn,ScrollLock */
  429. 0, 0, 0, 0, 0, 0, 0, 0, /* 0x48-0x4f: Pause,Insert,Home,PageUp,DeleteForward,End,PageDown,RightArrow */
  430. 0, 0, 0, 0, '/', '*', '-', '+', /* 0x50-0x57: LeftArrow,DownArrow,UpArrow,Num Lock,/,*,-,+ */
  431. '\n', '1', '2', '3', '4', '5', '6', '7', /* 0x58-0x5f: Enter,1-7 */
  432. '8', '9', '0', '.', 0, 0, 0, '=', /* 0x60-0x67: 8-9,0,.,Non-US \,Application,Power,= */
  433. #ifdef CONFIG_HIDKBD_ALLSCANCODES
  434. 0, 0, 0, 0, 0, 0, 0, 0, /* 0x68-0x6f: F13,F14,F15,F16,F17,F18,F19,F20 */
  435. 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77: F21,F22,F23,F24,Execute,Help,Menu,Select */
  436. 0, 0, 0, 0, 0, 0, 0, 0, /* 0x78-0x7f: Stop,Again,Undo,Cut,Copy,Paste,Find,Mute */
  437. 0, 0, 0, 0, 0, ',', 0, 0, /* 0x80-0x87: VolUp,VolDown,LCapsLock,lNumLock,LScrollLock,,,=,International1 */
  438. 0, 0, 0, 0, 0, 0, 0, 0, /* 0x88-0x8f: International 2-9 */
  439. 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x97: LAN 1-8 */
  440. 0, 0, 0, 0, 0, 0, '\n', 0, /* 0x98-0x9f: LAN 9,Erase,SysReq,Cancel,Clear,Prior,Return,Separator */
  441. 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0-0xa7: Out,Oper,Clear,CrSel,Excel,(reserved) */
  442. 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa8-0xaf: (reserved) */
  443. 0, 0, 0, 0, 0, 0, '(', ')', /* 0xb0-0xb7: 00,000,ThouSeparator,DecSeparator,CurrencyUnit,SubUnit,(,) */
  444. '{', '}', '\t', '\177', 'A', 'B', 'C', 'D', /* 0xb8-0xbf: {,},tab,backspace,A-D */
  445. 'F', 'F', 0, '^', '%', '<', '>', '&', /* 0xc0-0xc7: E-F,XOR,^,%,<,>,& */
  446. 0, '|', 0, ':', '%', ' ', '@', '!', /* 0xc8-0xcf: &&,|,||,:,#, ,@,! */
  447. 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0-0xd7: Memory Store,Recall,Clear,Add,Subtract,Muliply,Divide,+/- */
  448. 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd8-0xdf: Clear,ClearEntry,Binary,Octal,Decimal,Hexadecimal */
  449. 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0-0xe7: Left Ctrl,Shift,Alt,GUI, Right Ctrl,Shift,Alt,GUI */
  450. #endif
  451. };
  452. #endif /* CONFIG_HIDKBD_RAWSCANCODES */
  453. /****************************************************************************
  454. * Private Functions
  455. ****************************************************************************/
  456. /****************************************************************************
  457. * Name: usbhost_takesem
  458. *
  459. * Description:
  460. * This is just a wrapper to handle the annoying behavior of semaphore
  461. * waits that return due to the receipt of a signal.
  462. *
  463. ****************************************************************************/
  464. static void usbhost_takesem(sem_t *sem)
  465. {
  466. /* Take the semaphore (perhaps waiting) */
  467. while (sem_wait(sem) != 0)
  468. {
  469. /* The only case that an error should occr here is if the wait was
  470. * awakened by a signal.
  471. */
  472. ASSERT(errno == EINTR);
  473. }
  474. }
  475. /****************************************************************************
  476. * Name: usbhost_pollnotify
  477. ****************************************************************************/
  478. #ifndef CONFIG_DISABLE_POLL
  479. static void usbhost_pollnotify(FAR struct usbhost_state_s *priv)
  480. {
  481. int i;
  482. for (i = 0; i < CONFIG_HIDKBD_NPOLLWAITERS; i++)
  483. {
  484. struct pollfd *fds = priv->fds[i];
  485. if (fds)
  486. {
  487. fds->revents |= (fds->events & POLLIN);
  488. if (fds->revents != 0)
  489. {
  490. uvdbg("Report events: %02x\n", fds->revents);
  491. sem_post(fds->sem);
  492. }
  493. }
  494. }
  495. }
  496. #endif
  497. /****************************************************************************
  498. * Name: usbhost_allocclass
  499. *
  500. * Description:
  501. * This is really part of the logic that implements the create() method
  502. * of struct usbhost_registry_s. This function allocates memory for one
  503. * new class instance.
  504. *
  505. * Input Parameters:
  506. * None
  507. *
  508. * Returned Values:
  509. * On success, this function will return a non-NULL instance of struct
  510. * usbhost_class_s. NULL is returned on failure; this function will
  511. * will fail only if there are insufficient resources to create another
  512. * USB host class instance.
  513. *
  514. ****************************************************************************/
  515. static inline FAR struct usbhost_state_s *usbhost_allocclass(void)
  516. {
  517. FAR struct usbhost_state_s *priv;
  518. DEBUGASSERT(!up_interrupt_context());
  519. priv = (FAR struct usbhost_state_s *)kmalloc(sizeof(struct usbhost_state_s));
  520. uvdbg("Allocated: %p\n", priv);;
  521. return priv;
  522. }
  523. /****************************************************************************
  524. * Name: usbhost_freeclass
  525. *
  526. * Description:
  527. * Free a class instance previously allocated by usbhost_allocclass().
  528. *
  529. * Input Parameters:
  530. * class - A reference to the class instance to be freed.
  531. *
  532. * Returned Values:
  533. * None
  534. *
  535. ****************************************************************************/
  536. static inline void usbhost_freeclass(FAR struct usbhost_state_s *class)
  537. {
  538. DEBUGASSERT(class != NULL);
  539. /* Free the class instance. */
  540. uvdbg("Freeing: %p\n", class);;
  541. kfree(class);
  542. }
  543. /****************************************************************************
  544. * Name: Device name management
  545. *
  546. * Description:
  547. * Some tiny functions to coordinate management of device names.
  548. *
  549. ****************************************************************************/
  550. static int usbhost_allocdevno(FAR struct usbhost_state_s *priv)
  551. {
  552. irqstate_t flags;
  553. int devno;
  554. flags = irqsave();
  555. for (devno = 0; devno < 26; devno++)
  556. {
  557. uint32_t bitno = 1 << devno;
  558. if ((g_devinuse & bitno) == 0)
  559. {
  560. g_devinuse |= bitno;
  561. priv->devchar = 'a' + devno;
  562. irqrestore(flags);
  563. return OK;
  564. }
  565. }
  566. irqrestore(flags);
  567. return -EMFILE;
  568. }
  569. static void usbhost_freedevno(FAR struct usbhost_state_s *priv)
  570. {
  571. int devno = 'a' - priv->devchar;
  572. if (devno >= 0 && devno < 26)
  573. {
  574. irqstate_t flags = irqsave();
  575. g_devinuse &= ~(1 << devno);
  576. irqrestore(flags);
  577. }
  578. }
  579. static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv, char *devname)
  580. {
  581. (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, priv->devchar);
  582. }
  583. /****************************************************************************
  584. * Name: usbhost_destroy
  585. *
  586. * Description:
  587. * The USB device has been disconnected and the refernce count on the USB
  588. * host class instance has gone to 1.. Time to destroy the USB host class
  589. * instance.
  590. *
  591. * Input Parameters:
  592. * arg - A reference to the class instance to be destroyed.
  593. *
  594. * Returned Values:
  595. * None
  596. *
  597. ****************************************************************************/
  598. static void usbhost_destroy(FAR void *arg)
  599. {
  600. FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)arg;
  601. char devname[DEV_NAMELEN];
  602. DEBUGASSERT(priv != NULL);
  603. uvdbg("crefs: %d\n", priv->crefs);
  604. /* Unregister the driver */
  605. uvdbg("Unregister driver\n");
  606. usbhost_mkdevname(priv, devname);
  607. (void)unregister_driver(devname);
  608. /* Release the device name used by this connection */
  609. usbhost_freedevno(priv);
  610. /* Free the interrupt endpoints */
  611. if (priv->epin)
  612. {
  613. DRVR_EPFREE(priv->drvr, priv->epin);
  614. }
  615. if (priv->epout)
  616. {
  617. DRVR_EPFREE(priv->drvr, priv->epout);
  618. }
  619. /* Free any transfer buffers */
  620. usbhost_tdfree(priv);
  621. /* Destroy the semaphores */
  622. sem_destroy(&priv->exclsem);
  623. sem_destroy(&priv->waitsem);
  624. /* Disconnect the USB host device */
  625. DRVR_DISCONNECT(priv->drvr);
  626. /* And free the class instance. Hmmm.. this may execute on the worker
  627. * thread and the work structure is part of what is getting freed. That
  628. * should be okay because once the work contained is removed from the
  629. * queue, it should not longer be accessed by the worker thread.
  630. */
  631. usbhost_freeclass(priv);
  632. }
  633. /****************************************************************************
  634. * Name: usbhost_putbuffer
  635. *
  636. * Description:
  637. * Add one character to the user buffer.
  638. *
  639. * Input Parameters:
  640. * priv - Driver internal state
  641. * keycode - The value to add to the user buffer
  642. *
  643. * Returned Values:
  644. * None
  645. *
  646. ****************************************************************************/
  647. static void usbhost_putbuffer(FAR struct usbhost_state_s *priv,
  648. uint8_t keycode)
  649. {
  650. register unsigned int head;
  651. register unsigned int tail;
  652. /* Copy the next keyboard character into the user buffer. */
  653. head = priv->headndx;
  654. priv->kbdbuffer[head] = keycode;
  655. /* Increment the head index */
  656. if (++head >= CONFIG_HIDKBD_BUFSIZE)
  657. {
  658. head = 0;
  659. }
  660. /* If the buffer is full, then increment the tail index to make space. Is
  661. * it better to lose old keystrokes or new?
  662. */
  663. tail = priv->tailndx;
  664. if (tail == head)
  665. {
  666. if (++tail >= CONFIG_HIDKBD_BUFSIZE)
  667. {
  668. tail = 0;
  669. }
  670. /* Save the updated tail index */
  671. priv->tailndx = tail;
  672. }
  673. /* Save the updated head index */
  674. priv->headndx = head;
  675. }
  676. /****************************************************************************
  677. * Name: usbhost_putstream
  678. *
  679. * Description:
  680. * A wrapper for usbhost_putc that is compatibile with the lib_outstream_s
  681. * putc methos.
  682. *
  683. * Input Parameters:
  684. * stream - The struct lib_outstream_s reference
  685. * ch - The character to add to the user buffer
  686. *
  687. * Returned Values:
  688. * None
  689. *
  690. ****************************************************************************/
  691. #ifdef CONFIG_HIDKBD_ENCODED
  692. static void usbhost_putstream(FAR struct lib_outstream_s *stream, int ch)
  693. {
  694. FAR struct usbhost_outstream_s *privstream = (FAR struct usbhost_outstream_s *)stream;
  695. DEBUGASSERT(privstream && privstream->priv);
  696. usbhost_putbuffer(privstream->priv, (uint8_t)ch);
  697. stream->nput++;
  698. }
  699. #endif
  700. /****************************************************************************
  701. * Name: usbhost_mapscancode
  702. *
  703. * Description:
  704. * Map a keyboard scancode to a printable ASCII character. There is no
  705. * support here for function keys or cursor controls in this version of
  706. * the driver.
  707. *
  708. * Input Parameters:
  709. * scancode - Scan code to be mapped.
  710. * modifier - Ctrl,Alt,Shift,GUI modifier bits
  711. *
  712. * Returned Values:
  713. * None
  714. *
  715. ****************************************************************************/
  716. static inline uint8_t usbhost_mapscancode(uint8_t scancode, uint8_t modifier)
  717. {
  718. #ifndef CONFIG_HIDKBD_RAWSCANCODES
  719. /* Range check */
  720. if (scancode >= USBHID_NUMSCANCODES)
  721. {
  722. return 0;
  723. }
  724. /* Is either shift key pressed? */
  725. if ((modifier & (USBHID_MODIFER_LSHIFT|USBHID_MODIFER_RSHIFT)) != 0)
  726. {
  727. return ucmap[scancode];
  728. }
  729. else
  730. {
  731. return lcmap[scancode];
  732. }
  733. #else
  734. return scancode;
  735. #endif
  736. }
  737. /****************************************************************************
  738. * Name: usbhost_encodescancode
  739. *
  740. * Description:
  741. * Check if the key has a special function encoding and, if it does, add
  742. * the encoded value to the user buffer.
  743. *
  744. * Input Parameters:
  745. * priv - Driver internal state
  746. * scancode - Scan code to be mapped.
  747. * modifier - Ctrl,Alt,Shift,GUI modifier bits
  748. *
  749. * Returned Values:
  750. * None
  751. *
  752. ****************************************************************************/
  753. #ifdef CONFIG_HIDKBD_ENCODED
  754. static inline void usbhost_encodescancode(FAR struct usbhost_state_s *priv,
  755. uint8_t scancode, uint8_t modifier)
  756. {
  757. uint8_t encoded;
  758. /* Check if the raw scancode is in a valid range */
  759. if (scancode >= FIRST_ENCODING && scancode <= LAST_ENCODING)
  760. {
  761. /* Yes the value is within range */
  762. encoded = encoding[scancode - FIRST_ENCODING];
  763. ivdbg(" scancode: %02x modifier: %02x encoded: %d\n",
  764. scancode, modifier, encoded);
  765. if (encoded)
  766. {
  767. struct usbhost_outstream_s usbstream;
  768. /* And it does correspond to a special function key */
  769. usbstream.stream.put = usbhost_putstream;
  770. usbstream.stream.nput = 0;
  771. usbstream.priv = priv;
  772. /* Add the special function value to the user buffer */
  773. kbd_specpress((enum kbd_keycode_e)encoded,
  774. (FAR struct lib_outstream_s *)&usbstream);
  775. }
  776. }
  777. }
  778. #endif
  779. /****************************************************************************
  780. * Name: usbhost_kbdpoll
  781. *
  782. * Description:
  783. * Periodically check for new keyboard data.
  784. *
  785. * Input Parameters:
  786. * arg - A reference to the class instance to be destroyed.
  787. *
  788. * Returned Values:
  789. * None
  790. *
  791. ****************************************************************************/
  792. static int usbhost_kbdpoll(int argc, char *argv[])
  793. {
  794. FAR struct usbhost_state_s *priv;
  795. FAR struct usb_ctrlreq_s *ctrlreq;
  796. #ifndef CONFIG_HIDKBD_NODEBOUNCE
  797. uint8_t lastkey[6] = {0, 0, 0, 0, 0, 0};
  798. #endif
  799. #if defined(CONFIG_DEBUG_USB) && defined(CONFIG_DEBUG_VERBOSE)
  800. unsigned int npolls = 0;
  801. #endif
  802. unsigned int nerrors = 0;
  803. bool empty = true;
  804. bool newstate;
  805. int ret;
  806. uvdbg("Started\n");
  807. /* Synchronize with the start-up logic. Get the private instance, re-start
  808. * the start-up logic, and wait a bit to make sure that all of the class
  809. * creation logic has a chance to run to completion.
  810. *
  811. * NOTE: that the reference count is incremented here. Therefore, we know
  812. * that the driver data structure will remain stable while this thread is
  813. * running.
  814. */
  815. priv = g_priv;
  816. DEBUGASSERT(priv != NULL);
  817. priv->polling = true;
  818. priv->crefs++;
  819. usbhost_givesem(&g_syncsem);
  820. sleep(1);
  821. /* Loop here until the device is disconnected */
  822. uvdbg("Entering poll loop\n");
  823. while (!priv->disconnected)
  824. {
  825. /* Make sure that we have exclusive access to the private data
  826. * structure. There may now be other tasks with the character driver
  827. * open and actively trying to interact with the class driver.
  828. */
  829. usbhost_takesem(&priv->exclsem);
  830. /* Format the HID report request:
  831. *
  832. * bmRequestType 10100001
  833. * bRequest GET_REPORT (0x01)
  834. * wValue Report Type and Report Index
  835. * wIndex Interface Number
  836. * wLength Descriptor Length
  837. * Data Descriptor Data
  838. */
  839. ctrlreq = (struct usb_ctrlreq_s *)priv->tbuffer;
  840. ctrlreq->type = USB_REQ_DIR_IN|USB_REQ_TYPE_CLASS|USB_REQ_RECIPIENT_INTERFACE;
  841. ctrlreq->req = USBHID_REQUEST_GETREPORT;
  842. usbhost_putle16(ctrlreq->value, (USBHID_REPORTTYPE_INPUT << 8));
  843. usbhost_putle16(ctrlreq->index, priv->ifno);
  844. usbhost_putle16(ctrlreq->len, sizeof(struct usbhid_kbdreport_s));
  845. /* Send HID report request */
  846. ret = DRVR_CTRLIN(priv->drvr, ctrlreq, priv->tbuffer);
  847. usbhost_givesem(&priv->exclsem);
  848. /* Check for errors -- Bail if an excessive number of errors
  849. * are encountered.
  850. */
  851. if (ret != OK)
  852. {
  853. nerrors++;
  854. udbg("ERROR: GETREPORT/INPUT, DRVR_CTRLIN returned: %d/%d\n",
  855. ret, nerrors);
  856. if (nerrors > 200)
  857. {
  858. udbg("Too many errors... aborting: %d\n", nerrors);
  859. break;
  860. }
  861. }
  862. /* The report was received correctly. But ignore the keystrokes if no
  863. * task has opened the driver.
  864. */
  865. else if (priv->open)
  866. {
  867. struct usbhid_kbdreport_s *rpt = (struct usbhid_kbdreport_s *)priv->tbuffer;
  868. uint8_t keycode;
  869. int i;
  870. /* Add the newly received keystrokes to our internal buffer */
  871. usbhost_takesem(&priv->exclsem);
  872. for (i = 0; i < 6; i++)
  873. {
  874. /* Is this key pressed? But not pressed last time?
  875. * HID spec: "The order of keycodes in array fields has no
  876. * significance. Order determination is done by the host
  877. * software comparing the contents of the previous report to
  878. * the current report. If two or more keys are reported in
  879. * one report, their order is indeterminate. Keyboards may
  880. * buffer events that would have otherwise resulted in
  881. * multiple event in a single report.
  882. *
  883. * "'Repeat Rate' and 'Delay Before First Repeat' are
  884. * implemented by the host and not in the keyboard (this
  885. * means the BIOS in legacy mode). The host may use the
  886. * device report rate and the number of reports to determine
  887. * how long a key is being held down. Alternatively, the host
  888. * may use its own clock or the idle request for the timing
  889. * of these features."
  890. */
  891. if (rpt->key[i] != USBHID_KBDUSE_NONE
  892. #ifndef CONFIG_HIDKBD_NODEBOUNCE
  893. && rpt->key[i] != lastkey[i]
  894. #endif
  895. )
  896. {
  897. /* Yes.. Add it to the buffer. */
  898. /* Map the keyboard scancode to a printable ASCII
  899. * character. There is no support here for function keys
  900. * or cursor controls in this version of the driver.
  901. */
  902. keycode = usbhost_mapscancode(rpt->key[i], rpt->modifier);
  903. ivdbg("Key %d: %02x keycode:%c modifier: %02x\n",
  904. i, rpt->key[i], keycode ? keycode : ' ', rpt->modifier);
  905. /* Zero at this point means that the key does not map to a
  906. * printable character.
  907. */
  908. if (keycode != 0)
  909. {
  910. /* Handle control characters. Zero after this means
  911. * a valid, NUL character.
  912. */
  913. if ((rpt->modifier & (USBHID_MODIFER_LCTRL|USBHID_MODIFER_RCTRL)) != 0)
  914. {
  915. keycode &= 0x1f;
  916. }
  917. /* Copy the next keyboard character into the user
  918. * buffer.
  919. */
  920. usbhost_putbuffer(priv, keycode);
  921. }
  922. /* The zero might, however, map to a special keyboard action (such as a
  923. * cursor movement or function key). Attempt to encode the special key.
  924. */
  925. #ifdef CONFIG_HIDKBD_ENCODED
  926. else
  927. {
  928. usbhost_encodescancode(priv, rpt->key[i], rpt->modifier);
  929. }
  930. #endif
  931. }
  932. /* Save the scancode (or lack thereof) for key debouncing on
  933. * next keyboard report.
  934. */
  935. #ifndef CONFIG_HIDKBD_NODEBOUNCE
  936. lastkey[i] = rpt->key[i];
  937. #endif
  938. }
  939. /* Is there data available? */
  940. newstate = (priv->headndx == priv->tailndx);
  941. if (!newstate)
  942. {
  943. /* Yes.. Is there a thread waiting for keyboard data now? */
  944. if (priv->waiting)
  945. {
  946. /* Yes.. wake it up */
  947. usbhost_givesem(&priv->waitsem);
  948. priv->waiting = false;
  949. }
  950. /* Did we just transition from no data available to data
  951. * available? If so, wake up any threads waiting for the
  952. * POLLIN event.
  953. */
  954. if (empty)
  955. {
  956. usbhost_pollnotify(priv);
  957. }
  958. }
  959. empty = newstate;
  960. usbhost_givesem(&priv->exclsem);
  961. }
  962. /* If USB debug is on, then provide some periodic indication that
  963. * polling is still happening.
  964. */
  965. #if defined(CONFIG_DEBUG_USB) && defined(CONFIG_DEBUG_VERBOSE)
  966. npolls++;
  967. if ((npolls & 31) == 0)
  968. {
  969. udbg("Still polling: %d\n", npolls);
  970. }
  971. #endif
  972. /* Wait for the required amount (or until a signal is received). We
  973. * will wake up when either the delay elapses or we are signalled that
  974. * the device has been disconnected.
  975. */
  976. usleep(CONFIG_HIDKBD_POLLUSEC);
  977. }
  978. /* We get here when the driver is removed.. or when too many errors have
  979. * been encountered.
  980. *
  981. * Make sure that we have exclusive access to the private data structure.
  982. * There may now be other tasks with the character driver open and actively
  983. * trying to interact with the class driver.
  984. */
  985. usbhost_takesem(&priv->exclsem);
  986. /* Indicate that we are no longer running and decrement the reference
  987. * count help by this thread. If there are no other users of the class,
  988. * we can destroy it now. Otherwise, we have to wait until the all
  989. * of the file descriptors are closed.
  990. */
  991. udbg("Keyboard removed, polling halted\n");
  992. priv->polling = false;
  993. if (--priv->crefs < 2)
  994. {
  995. /* Destroy the instance (while we hold the semaphore!) */
  996. usbhost_destroy(priv);
  997. }
  998. else
  999. {
  1000. /* No, we will destroy the driver instance when it is finally closed */
  1001. usbhost_givesem(&priv->exclsem);
  1002. }
  1003. return 0;
  1004. }
  1005. /****************************************************************************
  1006. * Name: usbhost_cfgdesc
  1007. *
  1008. * Description:
  1009. * This function implements the connect() method of struct
  1010. * usbhost_class_s. This method is a callback into the class
  1011. * implementation. It is used to provide the device's configuration
  1012. * descriptor to the class so that the class may initialize properly
  1013. *
  1014. * Input Parameters:
  1015. * priv - The USB host class instance.
  1016. * configdesc - A pointer to a uint8_t buffer container the configuration descripor.
  1017. * desclen - The length in bytes of the configuration descriptor.
  1018. * funcaddr - The USB address of the function containing the endpoint that EP0
  1019. * controls
  1020. *
  1021. * Returned Values:
  1022. * On success, zero (OK) is returned. On a failure, a negated errno value is
  1023. * returned indicating the nature of the failure
  1024. *
  1025. * Assumptions:
  1026. * This function will *not* be called from an interrupt handler.
  1027. *
  1028. ****************************************************************************/
  1029. static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv,
  1030. FAR const uint8_t *configdesc, int desclen,
  1031. uint8_t funcaddr)
  1032. {
  1033. FAR struct usb_cfgdesc_s *cfgdesc;
  1034. FAR struct usb_desc_s *desc;
  1035. FAR struct usbhost_epdesc_s epindesc;
  1036. FAR struct usbhost_epdesc_s epoutdesc;
  1037. int remaining;
  1038. uint8_t found = 0;
  1039. bool done = false;
  1040. int ret;
  1041. DEBUGASSERT(priv != NULL &&
  1042. configdesc != NULL &&
  1043. desclen >= sizeof(struct usb_cfgdesc_s));
  1044. /* Verify that we were passed a configuration descriptor */
  1045. cfgdesc = (FAR struct usb_cfgdesc_s *)configdesc;
  1046. if (cfgdesc->type != USB_DESC_TYPE_CONFIG)
  1047. {
  1048. return -EINVAL;
  1049. }
  1050. /* Get the total length of the configuration descriptor (little endian).
  1051. * It might be a good check to get the number of interfaces here too.
  1052. */
  1053. remaining = (int)usbhost_getle16(cfgdesc->totallen);
  1054. /* Skip to the next entry descriptor */
  1055. configdesc += cfgdesc->len;
  1056. remaining -= cfgdesc->len;
  1057. /* Loop where there are more dscriptors to examine */
  1058. while (remaining >= sizeof(struct usb_desc_s) && !done)
  1059. {
  1060. /* What is the next descriptor? */
  1061. desc = (FAR struct usb_desc_s *)configdesc;
  1062. switch (desc->type)
  1063. {
  1064. /* Interface descriptor. We really should get the number of endpoints
  1065. * from this descriptor too.
  1066. */
  1067. case USB_DESC_TYPE_INTERFACE:
  1068. {
  1069. FAR struct usb_ifdesc_s *ifdesc = (FAR struct usb_ifdesc_s *)configdesc;
  1070. uvdbg("Interface descriptor\n");
  1071. DEBUGASSERT(remaining >= USB_SIZEOF_IFDESC);
  1072. /* Did we already find what we needed from a preceding interface? */
  1073. if ((found & USBHOST_RQDFOUND) == USBHOST_RQDFOUND)
  1074. {
  1075. /* Yes.. then break out of the loop and use the preceding
  1076. * interface.
  1077. */
  1078. done = true;
  1079. }
  1080. else
  1081. {
  1082. /* Otherwise, save the interface number and discard any
  1083. * endpoints previously found
  1084. */
  1085. priv->ifno = ifdesc->ifno;
  1086. found = USBHOST_IFFOUND;
  1087. }
  1088. }
  1089. break;
  1090. /* HID descriptor */
  1091. case USBHID_DESCTYPE_HID:
  1092. uvdbg("HID descriptor\n");
  1093. break;
  1094. /* Endpoint descriptor. We expect one or two interrupt endpoints,
  1095. * a required IN endpoint and an optional OUT endpoint.
  1096. */
  1097. case USB_DESC_TYPE_ENDPOINT:
  1098. {
  1099. FAR struct usb_epdesc_s *epdesc = (FAR struct usb_epdesc_s *)configdesc;
  1100. uvdbg("Endpoint descriptor\n");
  1101. DEBUGASSERT(remaining >= USB_SIZEOF_EPDESC);
  1102. /* Check for an interrupt endpoint. */
  1103. if ((epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) == USB_EP_ATTR_XFER_INT)
  1104. {
  1105. /* Yes.. it is a interrupt endpoint. IN or OUT? */
  1106. if (USB_ISEPOUT(epdesc->addr))
  1107. {
  1108. /* It is an interrupt OUT endpoint. There not be more than one
  1109. * interrupt OUT endpoint.
  1110. */
  1111. if ((found & USBHOST_EPOUTFOUND) != 0)
  1112. {
  1113. /* Oops.. more than one endpoint. We don't know what to do with this. */
  1114. return -EINVAL;
  1115. }
  1116. found |= USBHOST_EPOUTFOUND;
  1117. /* Save the interrupt OUT endpoint information */
  1118. epoutdesc.addr = epdesc->addr & USB_EP_ADDR_NUMBER_MASK;
  1119. epoutdesc.in = false;
  1120. epoutdesc.funcaddr = funcaddr;
  1121. epoutdesc.xfrtype = USB_EP_ATTR_XFER_INT;
  1122. epoutdesc.interval = epdesc->interval;
  1123. epoutdesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize);
  1124. uvdbg("Interrupt OUT EP addr:%d mxpacketsize:%d\n",
  1125. epoutdesc.addr, epoutdesc.mxpacketsize);
  1126. }
  1127. else
  1128. {
  1129. /* It is an interrupt IN endpoint. There should be only
  1130. * one interrupt IN endpoint.
  1131. */
  1132. if ((found & USBHOST_EPINFOUND) != 0)
  1133. {
  1134. /* Oops.. more than one endpint. We don't know what
  1135. * to do with this.
  1136. */
  1137. return -EINVAL;
  1138. }
  1139. found |= USBHOST_EPINFOUND;
  1140. /* Save the interrupt IN endpoint information */
  1141. epindesc.addr = epdesc->addr & USB_EP_ADDR_NUMBER_MASK;
  1142. epindesc.in = 1;
  1143. epindesc.funcaddr = funcaddr;
  1144. epindesc.xfrtype = USB_EP_ATTR_XFER_INT;
  1145. epindesc.interval = epdesc->interval;
  1146. epindesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize);
  1147. uvdbg("Interrupt IN EP addr:%d mxpacketsize:%d\n",
  1148. epindesc.addr, epindesc.mxpacketsize);
  1149. }
  1150. }
  1151. }
  1152. break;
  1153. /* Other descriptors are just ignored for now */
  1154. default:
  1155. uvdbg("Other descriptor: %d\n", desc->type);
  1156. break;
  1157. }
  1158. /* What we found everything that we are going to find? */
  1159. if (found == USBHOST_ALLFOUND)
  1160. {
  1161. /* Yes.. then break out of the loop and use the preceding interface */
  1162. done = true;
  1163. }
  1164. /* Increment the address of the next descriptor */
  1165. configdesc += desc->len;
  1166. remaining -= desc->len;
  1167. }
  1168. /* Sanity checking... did we find all of things that we need? */
  1169. if ((found & USBHOST_RQDFOUND) != USBHOST_RQDFOUND)
  1170. {
  1171. ulldbg("ERROR: Found IF:%s EPIN:%s\n",
  1172. (found & USBHOST_IFFOUND) != 0 ? "YES" : "NO",
  1173. (found & USBHOST_EPINFOUND) != 0 ? "YES" : "NO");
  1174. return -EINVAL;
  1175. }
  1176. /* We are good... Allocate the endpoints. First, the required interrupt
  1177. * IN endpoint.
  1178. */
  1179. ret = DRVR_EPALLOC(priv->drvr, &epindesc, &priv->epin);
  1180. if (ret != OK)
  1181. {
  1182. udbg("ERROR: Failed to allocate interrupt IN endpoint\n");
  1183. return ret;
  1184. }
  1185. /* Then the optional interrupt OUT endpoint */
  1186. ullvdbg("Found EPOOUT:%s\n",
  1187. (found & USBHOST_EPOUTFOUND) != 0 ? "YES" : "NO");
  1188. if ((found & USBHOST_EPOUTFOUND) != 0)
  1189. {
  1190. ret = DRVR_EPALLOC(priv->drvr, &epoutdesc, &priv->epout);
  1191. if (ret != OK)
  1192. {
  1193. udbg("ERROR: Failed to allocate interrupt OUT endpoint\n");
  1194. (void)DRVR_EPFREE(priv->drvr, priv->epin);
  1195. return ret;
  1196. }
  1197. }
  1198. ullvdbg("Endpoints allocated\n");
  1199. return OK;
  1200. }
  1201. /****************************************************************************
  1202. * Name: usbhost_devinit
  1203. *
  1204. * Description:
  1205. * The USB device has been successfully connected. This completes the
  1206. * initialization operations. It is first called after the
  1207. * configuration descriptor has been received.
  1208. *
  1209. * This function is called from the connect() method. This function always
  1210. * executes on the thread of the caller of connect().
  1211. *
  1212. * Input Parameters:
  1213. * priv - A reference to the class instance.
  1214. *
  1215. * Returned Values:
  1216. * None
  1217. *
  1218. ****************************************************************************/
  1219. static inline int usbhost_devinit(FAR struct usbhost_state_s *priv)
  1220. {
  1221. char devname[DEV_NAMELEN];
  1222. int ret;
  1223. /* Set aside a transfer buffer for exclusive use by the keyboard class driver */
  1224. ret = usbhost_tdalloc(priv);
  1225. if (ret != OK)
  1226. {
  1227. udbg("ERROR: Failed to allocate transfer buffer\n");
  1228. return ret;
  1229. }
  1230. /* Increment the reference count. This will prevent usbhost_destroy() from
  1231. * being called asynchronously if the device is removed.
  1232. */
  1233. priv->crefs++;
  1234. DEBUGASSERT(priv->crefs == 2);
  1235. /* Start a worker task to poll the USB device. It would be nice to used the
  1236. * the NuttX worker thread to do this, but this task needs to wait for events
  1237. * and activities on the worker thread should not involve significant waiting.
  1238. * Having a dedicated thread is more efficient in this sense, but requires more
  1239. * memory resources, primarily for the dedicated stack (CONFIG_HIDKBD_STACKSIZE).
  1240. */
  1241. uvdbg("user_start: Start poll task\n");
  1242. /* The inputs to a task started by task_create() are very awkard for this
  1243. * purpose. They are really designed for command line tasks (argc/argv). So
  1244. * the following is kludge pass binary data when the keyboard poll task
  1245. * is started.
  1246. *
  1247. * First, make sure we have exclusive access to g_priv (what is the likelihood
  1248. * of this being used? About zero, but we protect it anyway).
  1249. */
  1250. usbhost_takesem(&g_exclsem);
  1251. g_priv = priv;
  1252. #ifndef CONFIG_CUSTOM_STACK
  1253. priv->pollpid = task_create("usbhost", CONFIG_HIDKBD_DEFPRIO,
  1254. CONFIG_HIDKBD_STACKSIZE,
  1255. (main_t)usbhost_kbdpoll, (FAR char * const *)NULL);
  1256. #else
  1257. priv->pollpid = task_create("usbhost", CONFIG_HIDKBD_DEFPRIO,
  1258. (main_t)usbhost_kbdpoll, (FAR char * const *)NULL);
  1259. #endif
  1260. if (priv->pollpid == ERROR)
  1261. {
  1262. /* Failed to started the poll thread... probably due to memory resources */
  1263. usbhost_givesem(&g_exclsem);
  1264. ret = -ENOMEM;
  1265. goto errout;
  1266. }
  1267. /* Now wait for the poll task to get properly initialized */
  1268. usbhost_takesem(&g_syncsem);
  1269. usbhost_givesem(&g_exclsem);
  1270. /* Register the driver */
  1271. uvdbg("Register driver\n");
  1272. usbhost_mkdevname(priv, devname);
  1273. ret = register_driver(devname, &usbhost_fops, 0666, priv);
  1274. /* We now have to be concerned about asynchronous modification of crefs
  1275. * because the driver has been registerd.
  1276. */
  1277. errout:
  1278. usbhost_takesem(&priv->exclsem);
  1279. priv->crefs--;
  1280. usbhost_givesem(&priv->exclsem);
  1281. return ret;
  1282. }
  1283. /****************************************************************************
  1284. * Name: usbhost_getle16
  1285. *
  1286. * Description:
  1287. * Get a (possibly unaligned) 16-bit little endian value.
  1288. *
  1289. * Input Parameters:
  1290. * val - A pointer to the first byte of the little endian value.
  1291. *
  1292. * Returned Values:
  1293. * A uint16_t representing the whole 16-bit integer value
  1294. *
  1295. ****************************************************************************/
  1296. static inline uint16_t usbhost_getle16(const uint8_t *val)
  1297. {
  1298. return (uint16_t)val[1] << 8 | (uint16_t)val[0];
  1299. }
  1300. /****************************************************************************
  1301. * Name: usbhost_putle16
  1302. *
  1303. * Description:
  1304. * Put a (possibly unaligned) 16-bit little endian value.
  1305. *
  1306. * Input Parameters:
  1307. * dest - A pointer to the first byte to save the little endian value.
  1308. * val - The 16-bit value to be saved.
  1309. *
  1310. * Returned Values:
  1311. * None
  1312. *
  1313. ****************************************************************************/
  1314. static void usbhost_putle16(uint8_t *dest, uint16_t val)
  1315. {
  1316. dest[0] = val & 0xff; /* Little endian means LS byte first in byte stream */
  1317. dest[1] = val >> 8;
  1318. }
  1319. /****************************************************************************
  1320. * Name: usbhost_getle32
  1321. *
  1322. * Description:
  1323. * Get a (possibly unaligned) 32-bit little endian value.
  1324. *
  1325. * Input Parameters:
  1326. * dest - A pointer to the first byte to save the big endian value.
  1327. * val - The 32-bit value to be saved.
  1328. *
  1329. * Returned Values:
  1330. * None
  1331. *
  1332. ****************************************************************************/
  1333. static inline uint32_t usbhost_getle32(const uint8_t *val)
  1334. {
  1335. /* Little endian means LS halfword first in byte stream */
  1336. return (uint32_t)usbhost_getle16(&val[2]) << 16 | (uint32_t)usbhost_getle16(val);
  1337. }
  1338. /****************************************************************************
  1339. * Name: usbhost_putle32
  1340. *
  1341. * Description:
  1342. * Put a (possibly unaligned) 32-bit little endian value.
  1343. *
  1344. * Input Parameters:
  1345. * dest - A pointer to the first byte to save the little endian value.
  1346. * val - The 32-bit value to be saved.
  1347. *
  1348. * Returned Values:
  1349. * None
  1350. *
  1351. ****************************************************************************/
  1352. #if 0 /* Not used */
  1353. static void usbhost_putle32(uint8_t *dest, uint32_t val)
  1354. {
  1355. /* Little endian means LS halfword first in byte stream */
  1356. usbhost_putle16(dest, (uint16_t)(val & 0xffff));
  1357. usbhost_putle16(dest+2, (uint16_t)(val >> 16));
  1358. }
  1359. #endif
  1360. /****************************************************************************
  1361. * Name: usbhost_tdalloc
  1362. *
  1363. * Description:
  1364. * Allocate transfer buffer memory.
  1365. *
  1366. * Input Parameters:
  1367. * priv - A reference to the class instance.
  1368. *
  1369. * Returned Values:
  1370. * On sucess, zero (OK) is returned. On failure, an negated errno value
  1371. * is returned to indicate the nature of the failure.
  1372. *
  1373. ****************************************************************************/
  1374. static inline int usbhost_tdalloc(FAR struct usbhost_state_s *priv)
  1375. {
  1376. DEBUGASSERT(priv && priv->tbuffer == NULL);
  1377. return DRVR_ALLOC(priv->drvr, &priv->tbuffer, &priv->tbuflen);
  1378. }
  1379. /****************************************************************************
  1380. * Name: usbhost_tdfree
  1381. *
  1382. * Description:
  1383. * Free transfer buffer memory.
  1384. *
  1385. * Input Parameters:
  1386. * priv - A reference to the class instance.
  1387. *
  1388. * Returned Values:
  1389. * On sucess, zero (OK) is returned. On failure, an negated errno value
  1390. * is returned to indicate the nature of the failure.
  1391. *
  1392. ****************************************************************************/
  1393. static inline int usbhost_tdfree(FAR struct usbhost_state_s *priv)
  1394. {
  1395. int result = OK;
  1396. DEBUGASSERT(priv);
  1397. if (priv->tbuffer)
  1398. {
  1399. DEBUGASSERT(priv->drvr);
  1400. result = DRVR_FREE(priv->drvr, priv->tbuffer);
  1401. priv->tbuffer = NULL;
  1402. priv->tbuflen = 0;
  1403. }
  1404. return result;
  1405. }
  1406. /****************************************************************************
  1407. * struct usbhost_registry_s methods
  1408. ****************************************************************************/
  1409. /****************************************************************************
  1410. * Name: usbhost_create
  1411. *
  1412. * Description:
  1413. * This function implements the create() method of struct usbhost_registry_s.
  1414. * The create() method is a callback into the class implementation. It is
  1415. * used to (1) create a new instance of the USB host class state and to (2)
  1416. * bind a USB host driver "session" to the class instance. Use of this
  1417. * create() method will support environments where there may be multiple
  1418. * USB ports and multiple USB devices simultaneously connected.
  1419. *
  1420. * Input Parameters:
  1421. * drvr - An instance of struct usbhost_driver_s that the class
  1422. * implementation will "bind" to its state structure and will
  1423. * subsequently use to communicate with the USB host driver.
  1424. * id - In the case where the device supports multiple base classes,
  1425. * subclasses, or protocols, this specifies which to configure for.
  1426. *
  1427. * Returned Values:
  1428. * On success, this function will return a non-NULL instance of struct
  1429. * usbhost_class_s that can be used by the USB host driver to communicate
  1430. * with the USB host class. NULL is returned on failure; this function
  1431. * will fail only if the drvr input parameter is NULL or if there are
  1432. * insufficient resources to create another USB host class instance.
  1433. *
  1434. ****************************************************************************/
  1435. static FAR struct usbhost_class_s *usbhost_create(FAR struct usbhost_driver_s *drvr,
  1436. FAR const struct usbhost_id_s *id)
  1437. {
  1438. FAR struct usbhost_state_s *priv;
  1439. /* Allocate a USB host class instance */
  1440. priv = usbhost_allocclass();
  1441. if (priv)
  1442. {
  1443. /* Initialize the allocated storage class instance */
  1444. memset(priv, 0, sizeof(struct usbhost_state_s));
  1445. /* Assign a device number to this class instance */
  1446. if (usbhost_allocdevno(priv) == OK)
  1447. {
  1448. /* Initialize class method function pointers */
  1449. priv->class.connect = usbhost_connect;
  1450. priv->class.disconnected = usbhost_disconnected;
  1451. /* The initial reference count is 1... One reference is held by the driver */
  1452. priv->crefs = 1;
  1453. /* Initialize semaphores */
  1454. sem_init(&priv->exclsem, 0, 1);
  1455. sem_init(&priv->waitsem, 0, 0);
  1456. /* Bind the driver to the storage class instance */
  1457. priv->drvr = drvr;
  1458. /* Return the instance of the USB keyboard class driver */
  1459. return &priv->class;
  1460. }
  1461. }
  1462. /* An error occurred. Free the allocation and return NULL on all failures */
  1463. if (priv)
  1464. {
  1465. usbhost_freeclass(priv);
  1466. }
  1467. return NULL;
  1468. }
  1469. /****************************************************************************
  1470. * struct usbhost_class_s methods
  1471. ****************************************************************************/
  1472. /****************************************************************************
  1473. * Name: usbhost_connect
  1474. *
  1475. * Description:
  1476. * This function implements the connect() method of struct
  1477. * usbhost_class_s. This method is a callback into the class
  1478. * implementation. It is used to provide the device's configuration
  1479. * descriptor to the class so that the class may initialize properly
  1480. *
  1481. * Input Parameters:
  1482. * class - The USB host class entry previously obtained from a call to create().
  1483. * configdesc - A pointer to a uint8_t buffer container the configuration descripor.
  1484. * desclen - The length in bytes of the configuration descriptor.
  1485. * funcaddr - The USB address of the function containing the endpoint that EP0
  1486. * controls
  1487. *
  1488. * Returned Values:
  1489. * On success, zero (OK) is returned. On a failure, a negated errno value is
  1490. * returned indicating the nature of the failure
  1491. *
  1492. * NOTE that the class instance remains valid upon return with a failure. It is
  1493. * the responsibility of the higher level enumeration logic to call
  1494. * CLASS_DISCONNECTED to free up the class driver resources.
  1495. *
  1496. * Assumptions:
  1497. * - This function will *not* be called from an interrupt handler.
  1498. * - If this function returns an error, the USB host controller driver
  1499. * must call to DISCONNECTED method to recover from the error
  1500. *
  1501. ****************************************************************************/
  1502. static int usbhost_connect(FAR struct usbhost_class_s *class,
  1503. FAR const uint8_t *configdesc, int desclen,
  1504. uint8_t funcaddr)
  1505. {
  1506. FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)class;
  1507. int ret;
  1508. DEBUGASSERT(priv != NULL &&
  1509. configdesc != NULL &&
  1510. desclen >= sizeof(struct usb_cfgdesc_s));
  1511. /* Parse the configuration descriptor to get the endpoints */
  1512. ret = usbhost_cfgdesc(priv, configdesc, desclen, funcaddr);
  1513. if (ret != OK)
  1514. {
  1515. udbg("usbhost_cfgdesc() failed: %d\n", ret);
  1516. }
  1517. else
  1518. {
  1519. /* Now configure the device and register the NuttX driver */
  1520. ret = usbhost_devinit(priv);
  1521. if (ret != OK)
  1522. {
  1523. udbg("usbhost_devinit() failed: %d\n", ret);
  1524. }
  1525. }
  1526. /* ERROR handling: Do nothing. If we return and error during connection,
  1527. * the driver is required to call the DISCONNECT method. Possibilities:
  1528. *
  1529. * - Failure occurred before the kbdpoll task was started successfully.
  1530. * In this case, the disconnection will have to be handled on the worker
  1531. * task.
  1532. * - Failure occured after the kbdpoll task was started succesffuly. In
  1533. * this case, the disconnetion can be performed on the kbdpoll thread.
  1534. */
  1535. return ret;
  1536. }
  1537. /****************************************************************************
  1538. * Name: usbhost_disconnected
  1539. *
  1540. * Description:
  1541. * This function implements the disconnected() method of struct
  1542. * usbhost_class_s. This method is a callback into the class
  1543. * implementation. It is used to inform the class that the USB device has
  1544. * been disconnected.
  1545. *
  1546. * Input Parameters:
  1547. * class - The USB host class entry previously obtained from a call to
  1548. * create().
  1549. *
  1550. * Returned Values:
  1551. * On success, zero (OK) is returned. On a failure, a negated errno value
  1552. * is returned indicating the nature of the failure
  1553. *
  1554. * Assumptions:
  1555. * This function may be called from an interrupt handler.
  1556. *
  1557. ****************************************************************************/
  1558. static int usbhost_disconnected(struct usbhost_class_s *class)
  1559. {
  1560. FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)class;
  1561. DEBUGASSERT(priv != NULL);
  1562. /* Set an indication to any users of the keyboard device that the device
  1563. * is no longer available.
  1564. */
  1565. priv->disconnected = true;
  1566. ullvdbg("Disconnected\n");
  1567. /* Is there a thread waiting for keyboard data that will never come? */
  1568. if (priv->waiting)
  1569. {
  1570. /* Yes.. wake it up */
  1571. usbhost_givesem(&priv->waitsem);
  1572. priv->waiting = false;
  1573. }
  1574. /* Possibilities:
  1575. *
  1576. * - Failure occurred before the kbdpoll task was started successfully.
  1577. * In this case, the disconnection will have to be handled on the worker
  1578. * task.
  1579. * - Failure occured after the kbdpoll task was started succesffuly. In
  1580. * this case, the disconnetion can be performed on the kbdpoll thread.
  1581. */
  1582. if (priv->polling)
  1583. {
  1584. /* The polling task is still alive. Signal the keyboard polling task.
  1585. * When that task wakes up, it will decrement the reference count and,
  1586. * perhaps, destroy the class instance. Then it will exit.
  1587. */
  1588. (void)kill(priv->pollpid, SIGALRM);
  1589. }
  1590. else
  1591. {
  1592. /* In the case where the failure occurs before the polling task was
  1593. * started. Now what? We are probably executing from an interrupt
  1594. * handler here. We will use the worker thread. This is kind of
  1595. * wasteful and begs for a re-design.
  1596. */
  1597. DEBUGASSERT(priv->work.worker == NULL);
  1598. (void)work_queue(HPWORK, &priv->work, usbhost_destroy, priv, 0);
  1599. }
  1600. return OK;
  1601. }
  1602. /****************************************************************************
  1603. * Character driver methods
  1604. ****************************************************************************/
  1605. /****************************************************************************
  1606. * Name: usbhost_open
  1607. *
  1608. * Description:
  1609. * Standard character driver open method.
  1610. *
  1611. ****************************************************************************/
  1612. static int usbhost_open(FAR struct file *filep)
  1613. {
  1614. FAR struct inode *inode;
  1615. FAR struct usbhost_state_s *priv;
  1616. irqstate_t flags;
  1617. int ret;
  1618. uvdbg("Entry\n");
  1619. DEBUGASSERT(filep && filep->f_inode);
  1620. inode = filep->f_inode;
  1621. priv = inode->i_private;
  1622. /* Make sure that we have exclusive access to the private data structure */
  1623. DEBUGASSERT(priv && priv->crefs > 0 && priv->crefs < USBHOST_MAX_CREFS);
  1624. usbhost_takesem(&priv->exclsem);
  1625. /* Check if the keyboard device is still connected. We need to disable
  1626. * interrupts momentarily to assure that there are no asynchronous disconnect
  1627. * events.
  1628. */
  1629. flags = irqsave();
  1630. if (priv->disconnected)
  1631. {
  1632. /* No... the driver is no longer bound to the class. That means that
  1633. * the USB storage device is no longer connected. Refuse any further
  1634. * attempts to open the driver.
  1635. */
  1636. ret = -ENODEV;
  1637. }
  1638. else
  1639. {
  1640. /* Otherwise, just increment the reference count on the driver */
  1641. priv->crefs++;
  1642. priv->open = true;
  1643. ret = OK;
  1644. }
  1645. irqrestore(flags);
  1646. usbhost_givesem(&priv->exclsem);
  1647. return ret;
  1648. }
  1649. /****************************************************************************
  1650. * Name: usbhost_close
  1651. *
  1652. * Description:
  1653. * Standard character driver close method.
  1654. *
  1655. ****************************************************************************/
  1656. static int usbhost_close(FAR struct file *filep)
  1657. {
  1658. FAR struct inode *inode;
  1659. FAR struct usbhost_state_s *priv;
  1660. uvdbg("Entry\n");
  1661. DEBUGASSERT(filep && filep->f_inode);
  1662. inode = filep->f_inode;
  1663. priv = inode->i_private;
  1664. /* Decrement the reference count on the driver */
  1665. DEBUGASSERT(priv->crefs > 1);
  1666. usbhost_takesem(&priv->exclsem);
  1667. priv->crefs--;
  1668. /* Is this the last reference (other than the one held by the USB host
  1669. * controller driver)
  1670. */
  1671. if (priv->crefs <= 1)
  1672. {
  1673. irqstate_t flags;
  1674. /* Yes.. then the driver is no longer open */
  1675. priv->open = false;
  1676. priv->headndx = 0;
  1677. priv->tailndx = 0;
  1678. /* We need to disable interrupts momentarily to assure that there are
  1679. * no asynchronous disconnect events.
  1680. */
  1681. flags = irqsave();
  1682. /* Check if the USB keyboard device is still connected. If the device is
  1683. * no longer connected, then unregister the driver and free the driver
  1684. * class instance.
  1685. */
  1686. if (priv->disconnected)
  1687. {
  1688. /* Destroy the class instance (we can't use priv after this; we can't
  1689. * 'give' the semapore)
  1690. */
  1691. usbhost_destroy(priv);
  1692. irqrestore(flags);
  1693. return OK;
  1694. }
  1695. irqrestore(flags);
  1696. }
  1697. usbhost_givesem(&priv->exclsem);
  1698. return OK;
  1699. }
  1700. /****************************************************************************
  1701. * Name: usbhost_read
  1702. *
  1703. * Description:
  1704. * Standard character driver read method.
  1705. *
  1706. ****************************************************************************/
  1707. static ssize_t usbhost_read(FAR struct file *filep, FAR char *buffer, size_t len)
  1708. {
  1709. FAR struct inode *inode;
  1710. FAR struct usbhost_state_s *priv;
  1711. size_t nbytes;
  1712. unsigned int tail;
  1713. int ret;
  1714. uvdbg("Entry\n");
  1715. DEBUGASSERT(filep && filep->f_inode && buffer);
  1716. inode = filep->f_inode;
  1717. priv = inode->i_private;
  1718. /* Make sure that we have exclusive access to the private data structure */
  1719. DEBUGASSERT(priv && priv->crefs > 0 && priv->crefs < USBHOST_MAX_CREFS);
  1720. usbhost_takesem(&priv->exclsem);
  1721. /* Check if the keyboard is still connected. We need to disable interrupts
  1722. * momentarily to assure that there are no asynchronous disconnect events.
  1723. */
  1724. if (priv->disconnected)
  1725. {
  1726. /* No... the driver is no longer bound to the class. That means that
  1727. * the USB keybaord is no longer connected. Refuse any further attempts
  1728. * to access the driver.
  1729. */
  1730. ret = -ENODEV;
  1731. }
  1732. else
  1733. {
  1734. /* Is there keyboard data now? */
  1735. while (priv->tailndx == priv->headndx)
  1736. {
  1737. /* No.. were we open non-blocking? */
  1738. if (filep->f_oflags & O_NONBLOCK)
  1739. {
  1740. /* Yes.. then return a failure */
  1741. ret = -EAGAIN;
  1742. goto errout;
  1743. }
  1744. /* Wait for data to be available */
  1745. uvdbg("Waiting...\n");
  1746. priv->waiting = true;
  1747. usbhost_givesem(&priv->exclsem);
  1748. usbhost_takesem(&priv->waitsem);
  1749. usbhost_takesem(&priv->exclsem);
  1750. /* Did the keyboard become disconnected while we were waiting */
  1751. if (priv->disconnected)
  1752. {
  1753. ret = -ENODEV;
  1754. goto errout;
  1755. }
  1756. }
  1757. /* Read data from our internal buffer of received characters */
  1758. for (tail = priv->tailndx, nbytes = 0;
  1759. tail != priv->headndx && nbytes < len;
  1760. nbytes++)
  1761. {
  1762. /* Copy the next keyboard character into the user buffer */
  1763. *buffer++ = priv->kbdbuffer[tail];
  1764. /* Handle wrap-around of the tail index */
  1765. if (++tail >= CONFIG_HIDKBD_BUFSIZE)
  1766. {
  1767. tail = 0;
  1768. }
  1769. }
  1770. ret = nbytes;
  1771. /* Update the tail index (pehaps marking the buffer empty) */
  1772. priv->tailndx = tail;
  1773. }
  1774. errout:
  1775. usbhost_givesem(&priv->exclsem);
  1776. return (ssize_t)ret;
  1777. }
  1778. /****************************************************************************
  1779. * Name: usbhost_write
  1780. *
  1781. * Description:
  1782. * Standard character driver write method.
  1783. *
  1784. ****************************************************************************/
  1785. static ssize_t usbhost_write(FAR struct file *filep, FAR const char *buffer, size_t len)
  1786. {
  1787. /* We won't try to write to the keyboard */
  1788. return -ENOSYS;
  1789. }
  1790. /****************************************************************************
  1791. * Name: usbhost_poll
  1792. *
  1793. * Description:
  1794. * Standard character driver poll method.
  1795. *
  1796. ****************************************************************************/
  1797. #ifndef CONFIG_DISABLE_POLL
  1798. static int usbhost_poll(FAR struct file *filep, FAR struct pollfd *fds,
  1799. bool setup)
  1800. {
  1801. FAR struct inode *inode;
  1802. FAR struct usbhost_state_s *priv;
  1803. int ret = OK;
  1804. int i;
  1805. uvdbg("Entry\n");
  1806. DEBUGASSERT(filep && filep->f_inode && fds);
  1807. inode = filep->f_inode;
  1808. priv = inode->i_private;
  1809. /* Make sure that we have exclusive access to the private data structure */
  1810. DEBUGASSERT(priv);
  1811. usbhost_takesem(&priv->exclsem);
  1812. /* Check if the keyboard is still connected. We need to disable interrupts
  1813. * momentarily to assure that there are no asynchronous disconnect events.
  1814. */
  1815. if (priv->disconnected)
  1816. {
  1817. /* No... the driver is no longer bound to the class. That means that
  1818. * the USB keybaord is no longer connected. Refuse any further attempts
  1819. * to access the driver.
  1820. */
  1821. ret = -ENODEV;
  1822. }
  1823. else if (setup)
  1824. {
  1825. /* This is a request to set up the poll. Find an availableslot for
  1826. * the poll structure reference
  1827. */
  1828. for (i = 0; i < CONFIG_HIDKBD_NPOLLWAITERS; i++)
  1829. {
  1830. /* Find an available slot */
  1831. if (!priv->fds[i])
  1832. {
  1833. /* Bind the poll structure and this slot */
  1834. priv->fds[i] = fds;
  1835. fds->priv = &priv->fds[i];
  1836. break;
  1837. }
  1838. }
  1839. if (i >= CONFIG_HIDKBD_NPOLLWAITERS)
  1840. {
  1841. fds->priv = NULL;
  1842. ret = -EBUSY;
  1843. goto errout;
  1844. }
  1845. /* Should we immediately notify on any of the requested events? Notify
  1846. * the POLLIN event if there is buffered keyboard data.
  1847. */
  1848. if (priv->headndx != priv->tailndx)
  1849. {
  1850. usbhost_pollnotify(priv);
  1851. }
  1852. }
  1853. else
  1854. {
  1855. /* This is a request to tear down the poll. */
  1856. struct pollfd **slot = (struct pollfd **)fds->priv;
  1857. DEBUGASSERT(slot);
  1858. /* Remove all memory of the poll setup */
  1859. *slot = NULL;
  1860. fds->priv = NULL;
  1861. }
  1862. errout:
  1863. sem_post(&priv->exclsem);
  1864. return ret;
  1865. }
  1866. #endif
  1867. /****************************************************************************
  1868. * Public Functions
  1869. ****************************************************************************/
  1870. /****************************************************************************
  1871. * Name: usbhost_kbdinit
  1872. *
  1873. * Description:
  1874. * Initialize the USB storage HID keyboard class driver. This function
  1875. * should be called be platform-specific code in order to initialize and
  1876. * register support for the USB host HID keyboard class device.
  1877. *
  1878. * Input Parameters:
  1879. * None
  1880. *
  1881. * Returned Values:
  1882. * On success this function will return zero (OK); A negated errno value
  1883. * will be returned on failure.
  1884. *
  1885. ****************************************************************************/
  1886. int usbhost_kbdinit(void)
  1887. {
  1888. /* Perform any one-time initialization of the class implementation */
  1889. sem_init(&g_exclsem, 0, 1);
  1890. sem_init(&g_syncsem, 0, 0);
  1891. /* Advertise our availability to support (certain) devices */
  1892. return usbhost_registerclass(&g_skeleton);
  1893. }
  1894. #endif /* CONFIG_USBHOST)&& !CONFIG_USBHOST_INT_DISABLE && CONFIG_NFILE_DESCRIPTORS */