Usb.Mod 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758
  1. MODULE Usb; (** AUTHOR "staubesv"; PURPOSE "USB 2.0 Bus Driver"; *)
  2. (**
  3. * Bluebottle USB 2.0 Bus Driver based on Usb.Mod from "cplattner".
  4. *
  5. * Note that the hub driver (UsbHubDriver.Mod) is closely coupled with the USB driver. The USB driver maintains bus topology using
  6. * UsbDevice object. Usb.rootHubArray is the root of the tiered-star topology. These are the root hubs of the USB host controllers, which
  7. * are represented as EmulatedHubDevice. All other USB devices are represented using UsbDevice objects. If the hubFlag of such an object
  8. * is set, it represents a USB hub. Then the hubPortDevices array is valid.
  9. *
  10. * References:
  11. *
  12. * Universal Serial Bus Specification, Revision 2.0
  13. * USB Interface Association Descriptor and Device Class Code and Use Model
  14. * USB Engineering Change Notice: Interface Association Descriptors (Applies to USB Specification 2.0)
  15. *
  16. * All references can be found at http://www.usb.org
  17. *
  18. * History:
  19. *
  20. * 01.12.2005 First release (staubesv)
  21. * 07.12.2005 Support for automatic device driver loading using UsbDriverLoader (staubesv)
  22. * 12.12.2005 Exception handling for Usbdi.Driver.Connect added (staubesv)
  23. * 13.12.2005 Fixed UsbDevice.InternalParseConfiguration (always ask for 8 bytes, some devices didn't like less) (staubesv)
  24. * 03.12.2005 Fixed bug in DriverManager.Remove that prevented automatic USB pipe de-allocation when removing the device driver,
  25. * added exception handling for Usbdi.Driver.Disconnect (staubesv)
  26. * 25.01.2006 Don't import UTF8String anymore, copied the procedure needed to this file to save space for the boot file (staubesv)
  27. * 10.02.2006 Moved TrimWS & Length into this module (staubesv)
  28. * 09.06.2006 DriverManager is notified when the driver lookup service is enabled (staubesv)
  29. * 28.06.2006 Removed some unnecessary exports, procedure GetRootHubs now copies rootHubs array, moved utility procedures
  30. * to module UsbStrings.Mod (staubesv)
  31. * 26.07.2006 Replaced DriverManager.Notify mechanism by nbrOfDriverEvents variable, clients can poll this value to be
  32. * informed about driver adds/removals (staubesv)
  33. * 02.08.2006 ParseEndpointDescriptor enhanced for EndpointDescriptor.type field, adapted to Usbdi changes (staubesv)
  34. * 05.01.2007 Check descriptor type in UsbDevice.GetDescriptor (staubesv)
  35. * 22.03.2007 Renamed UsbDevice fields hubPortDevices, hubPortPermanentlyDisabled & HubPortErrors to deviceAtPort,
  36. * portPermanentlyDisabled & portErrors
  37. *
  38. * TODOs
  39. * - more general GetStringDescriptor
  40. * - put driver manager in own module, driver manager should only return reference to appropriate driver, not call its connect/disconnect procedures
  41. *)
  42. IMPORT SYSTEM, Modules, Machine, Plugins, KernelLog, UsbDriverLoader, Usbdi, UsbHcdi, Debug := UsbDebug, Lib := UsbUtilities;
  43. CONST
  44. (** USB device states *)
  45. StateDisconnected* = -1;
  46. StateAttached* = 0;
  47. StatePowered* = 1;
  48. StateDefault* = 2;
  49. StateAddress* = 3;
  50. StateConfigured* = 4;
  51. StateSuspended* = 5;
  52. (* Descriptor types for GetDescriptor & SetDesciptor USB standard requests *)
  53. DescriptorDevice = 1;
  54. DescriptorConfiguration = 2;
  55. DescriptorString = 3;
  56. DescriptorInterface = 4;
  57. DescriptorEndpoint = 5;
  58. DescriptorDeviceQualifier = 6;
  59. DescriptorOtherSpeedConfig = 7;
  60. DescriptorInterfacePower = 8;
  61. DescriptorOtg = 9;
  62. DescriptorDebug = 10;
  63. DescriptorIad = 11; (* Interface Associtation Descriptor *)
  64. (* Standard Request Codes (USB2.0, p. 251) *)
  65. SrGetStatus = 0;
  66. SrClearFeature = 1;
  67. SrSetFeature = 3;
  68. SrSetAddress = 5;
  69. SrGetDescriptor = 6;
  70. SrSetDescriptor = 7;
  71. SrGetConfiguration = 8;
  72. SrSetConfiguration = 9;
  73. SrGetInterface = 10;
  74. SrSetInterface = 11;
  75. SrSynchFrame = 12;
  76. (** Standard feature selectors for GetFeature & SetFeature USB standard requests *)
  77. FsDeviceRemoteWakeup* = 1;
  78. FsEndpointHalt* = 0;
  79. FsTestMode* = 2;
  80. (** GetStatus bits (recipient = Device) *)
  81. SelfPowered* = {0}; (* Current power source *)
  82. RemoteWakeup* = {1}; (* Remote Wakeup enabled? *)
  83. (** GetStatus bits (recipient = Endpoint) *)
  84. Halted* = {0}; (* Endpoint halted? *)
  85. LowSpeed* = 0;
  86. FullSpeed* = 1;
  87. HighSpeed* = 2;
  88. (* LANGID codes used by string descriptors, see HID page on www.usb.org *)
  89. IdUserDefault = 0400H;
  90. IdSystemDefault = 0800H;
  91. IdEnglishUS = 0409H;
  92. IdEnglishUK = 0809H;
  93. (* Timeouts *)
  94. DefaultTimeout* = 5000;
  95. (* Driver manager constants *)
  96. DmMaxPriorities = 12;
  97. TYPE
  98. Name* = Usbdi.Name;
  99. Description* = Usbdi.Description;
  100. TYPE
  101. DeviceDescriptor* = POINTER TO RECORD (Usbdi.DeviceDescriptor)
  102. bMaxPacketSize0- : LONGINT;
  103. iManufacturer- : LONGINT;
  104. iProduct- : LONGINT;
  105. iSerialNumber- : LONGINT;
  106. sManufacturer- : Lib.AsciiString;
  107. sProduct- : Lib.AsciiString;
  108. sSerialNumber- : Lib.AsciiString;
  109. uManufacturer- : Lib.UnicodeString;
  110. uProduct- : Lib.UnicodeString;
  111. uSerialNumber- : Lib.UnicodeString;
  112. END;
  113. (** As specified in the Universal Serial Bus Specification 1.1/2.0 **)
  114. ConfigurationDescriptor* = POINTER TO RECORD (Usbdi.ConfigurationDescriptor)
  115. bLength- : LONGINT;
  116. wTotalLength- : LONGINT;
  117. iConfiguration- : LONGINT;
  118. bmAttributes- : SET;
  119. bMaxPower- : LONGINT;
  120. sConfiguration- : Lib.AsciiString;
  121. uConfiguration- : Lib.UnicodeString;
  122. (* Decoded bmAttributes *)
  123. selfPowered- : BOOLEAN;
  124. remoteWakeup- : BOOLEAN;
  125. END;
  126. (** UsbDeviceInterface: As specified in the Universal Serial Bus Specification 1.1/2.0
  127. Oberon Usb addition: "Driver" points to the device driver for this interface, NIL means no driver (yet) attached
  128. to this interface **)
  129. InterfaceDescriptor* = POINTER TO RECORD (Usbdi.InterfaceDescriptor)
  130. bLength- : LONGINT;
  131. iInterface- : LONGINT;
  132. sInterface- : Lib.AsciiString;
  133. uInterface- : Lib.UnicodeString;
  134. driver- : Usbdi.Driver;
  135. END;
  136. (** EndpointDescriptor: As specified in the Universal Serial Bus Specification 1.1/2.0 **)
  137. EndpointDescriptor* = POINTER TO RECORD (Usbdi.EndpointDescriptor)
  138. bLength- : LONGINT;
  139. bInterval- : LONGINT; (* Raw value; interpretation dependend on transfer speed and transfer type *)
  140. mult- : LONGINT; (* Only for high-speed isochronous & interrupt transfers: How many transactions per microframe (1,2 or 3) *)
  141. END;
  142. InterfaceAssociationDescriptor* = POINTER TO RECORD (Usbdi.InterfaceAssociationDescriptor);
  143. bLength- : LONGINT;
  144. iFunction- : LONGINT;
  145. sFunction- : Lib.AsciiString;
  146. uFunction- : Lib.UnicodeString;
  147. END;
  148. TYPE
  149. UsbDevice* = OBJECT(Usbdi.UsbDevice)
  150. VAR
  151. (* Default control pipe (endpoint zero) *)
  152. defaultpipe* : UsbHcdi.Pipe;
  153. (* Device Qualifier; NIL if not available *)
  154. qualifier- : DeviceDescriptor;
  155. (* Other speed configurations *)
  156. otherconfigurations- : Usbdi.Configurations;
  157. address* : LONGINT;
  158. speed* : LONGINT; (* Usb.LowSpeed, Usb.FullSpeed, Usb.HighSpeed *)
  159. (* This device is connected to the port <port> of the UsbDevice <parent> *)
  160. parent* : UsbDevice;
  161. port* : LONGINT;
  162. (* If this is a low- or fullspeed device that is connected to a high-speed bus, the device is connected to
  163. the high-speed hub with the device address <ttAddress> at port <ttPort> *)
  164. ttAddress*, ttPort* : LONGINT;
  165. hubFlag* : BOOLEAN;
  166. (* USB hub specific fields *)
  167. nbrOfPorts* : LONGINT;
  168. deviceAtPort* : POINTER TO ARRAY OF UsbDevice;
  169. portPermanentDisabled* : POINTER TO ARRAY OF BOOLEAN;
  170. portErrors* : POINTER TO ARRAY OF LONGINT;
  171. (* Private, exported readonly to grant access to bytesTransfered field of the controller *)
  172. controller* : UsbHcdi.Hcd;
  173. PROCEDURE SetState*(state : LONGINT);
  174. BEGIN {EXCLUSIVE}
  175. IF Debug.Trace & Debug.traceDeviceStates THEN ShowStateTransition(SELF, state); END;
  176. SELF.state := state;
  177. END SetState;
  178. (*
  179. * Build a pipe object for the specified endpoint.
  180. * @param interface: USB device interface to be searched
  181. * @param endpointAddr: Address of endpoint to be searched
  182. * @return: Pipe for specified endpoint; NIL if endpoint not found
  183. *)
  184. PROCEDURE GetPipeByInterface(interface : InterfaceDescriptor; endpointAddr : LONGINT) : UsbHcdi.Pipe;
  185. VAR pipe : UsbHcdi.Pipe; endpoint : EndpointDescriptor; endp : LONGINT;
  186. BEGIN
  187. WHILE (endp < interface.bNumEndpoints) DO (* Search all endpoints of the interface *)
  188. IF interface.endpoints[endp].bEndpointAddress = endpointAddr THEN (* Found ! *)
  189. endpoint := interface.endpoints[endp](EndpointDescriptor);
  190. NEW(pipe, address, endpointAddr, controller);
  191. IF (SYSTEM.VAL(SET, endpointAddr) * {7}) = {7} THEN (* device-to-host *)
  192. pipe.direction := UsbHcdi.In;
  193. ELSE (* host-to-device *)
  194. pipe.direction := UsbHcdi.Out;
  195. END;
  196. pipe.status := Usbdi.InProgress;
  197. pipe.mult := endpoint.mult;
  198. pipe.device := SELF;
  199. pipe.ttPort := ttPort;
  200. pipe.ttAddress := ttAddress;
  201. pipe.type := SYSTEM.VAL(INTEGER,endpoint.bmAttributes * {0,1});
  202. IF pipe.type = UsbHcdi.PipeControl THEN
  203. pipe.direction := UsbHcdi.In;
  204. ELSE
  205. pipe.mode := Usbdi.MinCpu;
  206. pipe.ioc := TRUE;
  207. controller.AddCompletionHandler(pipe);
  208. END;
  209. pipe.maxPacketSize := endpoint.wMaxPacketSize;
  210. pipe.maxRetries := 3;
  211. pipe.irqInterval := endpoint.bInterval;
  212. pipe.speed := speed;
  213. pipe.timeout := DefaultTimeout;
  214. pipe.completion.device := SELF;
  215. RETURN pipe;
  216. END;
  217. INC(endp);
  218. END;
  219. RETURN pipe;
  220. END GetPipeByInterface;
  221. (** Allocate a pipe for the specified endpoint *)
  222. PROCEDURE GetPipe*(endpoint : LONGINT) : Usbdi.Pipe;
  223. VAR pipe : UsbHcdi.Pipe; intfc, altIntfc : LONGINT; interface : InterfaceDescriptor;
  224. BEGIN
  225. IF SYSTEM.VAL(SET, endpoint) * {0..3} = {} THEN (* Special case: Default control pipe is always allocated *)
  226. ASSERT(defaultpipe#NIL);
  227. RETURN defaultpipe;
  228. ELSE
  229. LOOP (* Search all interfaces of the active configuration *)
  230. IF (pipe # NIL) OR (intfc >= actConfiguration.bNumInterfaces) THEN EXIT; END;
  231. interface := actConfiguration.interfaces[intfc] (InterfaceDescriptor);
  232. pipe := GetPipeByInterface(interface, endpoint);
  233. IF pipe # NIL THEN EXIT; END;
  234. LOOP (* Search all alternate interfaces *)
  235. IF altIntfc >= interface.numAlternateInterfaces THEN EXIT; END;
  236. pipe := GetPipeByInterface(interface.alternateInterfaces[altIntfc] (InterfaceDescriptor), endpoint);
  237. IF pipe # NIL THEN EXIT; END;
  238. INC(altIntfc);
  239. END; (* LOOP altIntfc *)
  240. INC(intfc);
  241. END; (* LOOP intfc *)
  242. controller.GetPipe(address, endpoint, pipe);
  243. RETURN pipe; (* can be NIL *)
  244. END;
  245. RETURN NIL;
  246. END GetPipe;
  247. (** De-allocate the specified pipe *)
  248. PROCEDURE FreePipe*(pipe : Usbdi.Pipe);
  249. BEGIN
  250. controller.FreePipe(pipe (UsbHcdi.Pipe));
  251. END FreePipe;
  252. (* Register this USB device at the USB hub <hub> *)
  253. PROCEDURE Register*(hub: UsbDevice; portNbr: LONGINT);
  254. BEGIN {EXCLUSIVE}
  255. ASSERT(hub.hubFlag);
  256. parent := hub; port := portNbr;
  257. hub.deviceAtPort[portNbr] := SELF;
  258. Machine.AtomicInc(nbrOfTopologyEvents);
  259. END Register;
  260. (* this device from the hub it is connected to and remove its driver if installed *)
  261. PROCEDURE Remove*;
  262. VAR n : LONGINT;device: UsbDevice;
  263. BEGIN {EXCLUSIVE}
  264. IF hubFlag THEN
  265. FOR n := 0 TO nbrOfPorts - 1 DO
  266. IF deviceAtPort[n] # NIL THEN
  267. device := deviceAtPort[n];
  268. deviceAtPort[n] := NIL; (* avoid recursion *)
  269. device.SetState(StateDisconnected);
  270. device.Remove;
  271. IF parent = SELF THEN (* Root hub: only disable ports on root hubs *) controller.DisablePort(n); END;
  272. END;
  273. END;
  274. IF actConfiguration.interfaces[0](InterfaceDescriptor).driver # NIL THEN
  275. drivers.RemoveInstance(actConfiguration.interfaces[0](InterfaceDescriptor).driver.name, SELF);
  276. END;
  277. ELSE
  278. FOR n := 0 TO actConfiguration.bNumInterfaces - 1 DO
  279. IF actConfiguration.interfaces[n](InterfaceDescriptor).driver # NIL THEN (* Remove device driver instance *)
  280. drivers.RemoveInstance(actConfiguration.interfaces[n](InterfaceDescriptor).driver.name, SELF);
  281. actConfiguration.interfaces[n](InterfaceDescriptor).driver := NIL;
  282. END;
  283. END;
  284. END;
  285. (* If it's not a root hub, then unregister all pipes of this device *)
  286. IF ~(hubFlag & (parent = SELF)) THEN
  287. controller.FreeAll(address);
  288. controller.FreeAddress(address);
  289. END;
  290. Machine.AtomicInc(nbrOfTopologyEvents);
  291. END Remove;
  292. (** Implementation of the USB standard device requests, see USB Specification Rev 1.1, p. 185 *)
  293. (** The ClearFeature standard request is used to clear or disable a specific feature. *)
  294. PROCEDURE ClearFeature*(recipient : SET; feature, recipientNumber : LONGINT) : BOOLEAN;
  295. BEGIN
  296. ASSERT((recipient = Usbdi.Device) OR (recipient =Usbdi.Interface) OR (recipient = Usbdi.Endpoint));
  297. RETURN Request(recipient, SrClearFeature, feature, recipientNumber, 0, Usbdi.NoData) = Usbdi.Ok;
  298. END ClearFeature;
  299. (** This request is used to set or enable a specific feature *)
  300. PROCEDURE SetFeature*(recipient : SET; feature, recipientNumber : LONGINT) : BOOLEAN;
  301. BEGIN
  302. ASSERT((recipient = Usbdi.Device) OR (recipient = Usbdi.Interface) OR (recipient = Usbdi.Endpoint));
  303. RETURN Request(recipient, SrSetFeature, feature, recipientNumber, 0, Usbdi.NoData) = Usbdi.Ok;
  304. END SetFeature;
  305. (** Sets the address of the USB device dev to adr (should only be used by the USB driver) *)
  306. PROCEDURE SetAddress*(adr : LONGINT) : BOOLEAN;
  307. BEGIN
  308. IF Request(Usbdi.ToDevice, SrSetAddress, adr, 0, 0, Usbdi.NoData) = Usbdi.Ok THEN
  309. address := adr; RETURN TRUE;
  310. END;
  311. RETURN FALSE;
  312. END SetAddress;
  313. (** This requests returns the current device configuration value. If the returned value is zero, the device is not configured. *)
  314. PROCEDURE GetConfiguration*(VAR conf : LONGINT) : BOOLEAN;
  315. VAR buffer : Usbdi.BufferPtr;
  316. BEGIN
  317. NEW(buffer, 1);
  318. IF Request(Usbdi.ToHost, SrGetConfiguration, 0, 0, 1, buffer^) = Usbdi.Ok THEN
  319. conf := ORD(buffer[0]); RETURN TRUE;
  320. ELSE
  321. conf := -1; RETURN FALSE;
  322. END;
  323. END GetConfiguration;
  324. (** This requests sets the device configuration *)
  325. PROCEDURE SetConfiguration*(conf : LONGINT) : BOOLEAN;
  326. BEGIN
  327. ASSERT(configurations[conf].bConfigurationValue <= 255);
  328. IF Request(Usbdi.ToDevice + Usbdi.Standard, SrSetConfiguration, configurations[conf].bConfigurationValue, 0, 0, Usbdi.NoData) = Usbdi.Ok THEN
  329. actConfiguration := configurations[conf];
  330. RETURN TRUE;
  331. (* need to update info for pipes *)
  332. END;
  333. RETURN FALSE;
  334. END SetConfiguration;
  335. (** This request returns the specified descriptor if the descriptor exists *)
  336. PROCEDURE GetDescriptor*(descriptor, index, wIndex, len : LONGINT; VAR buffer : Usbdi.Buffer) : BOOLEAN;
  337. VAR status : Usbdi.Status;
  338. BEGIN
  339. ASSERT(len >= 2);
  340. status := Request(Usbdi.ToHost + Usbdi.Standard + Usbdi.Device, SrGetDescriptor, index + descriptor*100H, wIndex, len, buffer);
  341. RETURN (status = Usbdi.Ok) & (ORD(buffer[1]) = descriptor);
  342. END GetDescriptor;
  343. (** This request may be used to update existing descriptors or new descriptors may be added *)
  344. PROCEDURE SetDescriptor*(type : SET; index, wIndex, len : LONGINT; VAR buffer : Usbdi.Buffer) : BOOLEAN;
  345. BEGIN
  346. RETURN Request(Usbdi.ToDevice, SrSetDescriptor, index + 100H*SYSTEM.VAL(LONGINT, type), wIndex, len, buffer) = Usbdi.Ok;
  347. END SetDescriptor;
  348. (** This request returns the selected alternate settings for the specified interface *)
  349. PROCEDURE GetInterface*(interfaceNumber : LONGINT; VAR setting : LONGINT): BOOLEAN;
  350. VAR buffer : Usbdi.BufferPtr;
  351. BEGIN
  352. NEW(buffer, 1);
  353. IF Request(Usbdi.ToHost + Usbdi.Interface, SrGetInterface, 0, interfaceNumber, 1, buffer^) = Usbdi.Ok THEN
  354. setting := ORD(buffer[0]);
  355. RETURN TRUE;
  356. END;
  357. RETURN FALSE;
  358. END GetInterface;
  359. (** This requests allows the host to select an alternate setting for the specified interface *)
  360. PROCEDURE SetInterface*(interfaceNumber, setting : LONGINT): BOOLEAN;
  361. BEGIN
  362. RETURN Request(Usbdi.ToDevice + Usbdi.Standard + Usbdi.Interface, SrSetInterface, setting, interfaceNumber, 0, Usbdi.NoData) = Usbdi.Ok;
  363. END SetInterface;
  364. (** This request returns status for the specified recipient *)
  365. PROCEDURE GetStatus*(recipient: SET; recipientNumber: LONGINT; VAR status : SET): BOOLEAN;
  366. VAR buffer : Usbdi.BufferPtr;
  367. BEGIN
  368. ASSERT((recipient = Usbdi.Device) OR (recipient = Usbdi.Interface) OR (recipient = Usbdi.Endpoint));
  369. NEW(buffer, 2);
  370. IF Request(Usbdi.ToHost + Usbdi.Standard + recipient, SrGetStatus , 0, recipientNumber, 2, buffer^) = Usbdi.Ok THEN
  371. status := SYSTEM.VAL(SET, ORD(buffer[0]) + 100H*SYSTEM.VAL(LONGINT, ORD(buffer[1])));
  372. RETURN TRUE;
  373. END;
  374. RETURN FALSE;
  375. END GetStatus;
  376. (** This request is used to set and then report an endpoint's synchronization frame *)
  377. PROCEDURE SynchFrame*(endpoint: LONGINT; VAR frameNumber : LONGINT): BOOLEAN; (* UNTESTED *)
  378. VAR buffer : Usbdi.BufferPtr;
  379. BEGIN
  380. NEW(buffer, 2);
  381. IF Request(Usbdi.ToDevice + Usbdi.Standard + Usbdi.Endpoint, SrSynchFrame, 0, endpoint, 2, buffer^) = Usbdi.Ok THEN
  382. frameNumber := ORD(buffer[0]) + 100H*SYSTEM.VAL(LONGINT, ORD(buffer[1]));
  383. RETURN TRUE;
  384. END;
  385. RETURN FALSE;
  386. END SynchFrame;
  387. (** USB device request *)
  388. PROCEDURE Request*(bmRequestType : SET; bRequest, wValue, wIndex, wLength : LONGINT; VAR buffer : Usbdi.Buffer) : Usbdi.Status;
  389. BEGIN
  390. RETURN defaultpipe.Request(bmRequestType, bRequest, wValue, wIndex, wLength, buffer);
  391. END Request;
  392. (*
  393. * Get a device's configuration descriptor.
  394. * @param nbr Configuration number
  395. * @param type Configuration descriptor or Other-Speed configuration descriptor
  396. * @return Buffer containing the configuration, NIL if operation fails
  397. *)
  398. PROCEDURE InternalGetConfigurations(type : LONGINT; configurations : Usbdi.Configurations) : BOOLEAN;
  399. VAR buffer : Usbdi.BufferPtr; c, length : LONGINT;
  400. BEGIN
  401. ASSERT(((type = DescriptorConfiguration) & (descriptor # NIL)) OR ((type = DescriptorOtherSpeedConfig) & (qualifier # NIL)));
  402. FOR c := 0 TO LEN(configurations)-1 DO
  403. (* Get the total size of this configuration *)
  404. NEW(buffer, 8);
  405. IF GetDescriptor(type, c, 0, 8, buffer^) THEN
  406. length := ORD(buffer[2])+ 256*SYSTEM.VAL(LONGINT, ORD(buffer[3]));
  407. NEW(buffer, length);
  408. IF GetDescriptor(type, c, 0, length, buffer^) THEN (* Load and parse configuration *)
  409. configurations[c] := ParseConfigurationDescriptor(buffer^);
  410. IF configurations[c] = NIL THEN RETURN FALSE; END;
  411. IF (descriptor # NIL) &
  412. (descriptor.bDeviceClass = 0EFH) & (descriptor.bDeviceSubClass = 02H) & (descriptor.bDeviceProtocol = 01H) THEN
  413. (* Multi-interface function has Interface Association descriptors *)
  414. configurations[c].iads := ParseInterfaceAssociation(buffer^);
  415. END;
  416. (* Parse non-standard descriptors *)
  417. configurations[c].unknown := ParseUnknownDescriptors(configurations[c], buffer^);
  418. ELSE
  419. IF Debug.Level >= Debug.Errors THEN KernelLog.String("Usb: Get configuration failed."); KernelLog.Ln; END;
  420. RETURN FALSE;
  421. END;
  422. ELSE
  423. IF Debug.Level >= Debug.Errors THEN KernelLog.String("Usb: Read first 8 bytes of configuration failed"); KernelLog.Ln; END;
  424. RETURN FALSE;
  425. END;
  426. END;
  427. RETURN TRUE;
  428. END InternalGetConfigurations;
  429. PROCEDURE GetConfigurations*() : BOOLEAN;
  430. BEGIN
  431. ASSERT(descriptor # NIL);
  432. NEW(configurations, descriptor.bNumConfigurations);
  433. IF InternalGetConfigurations(DescriptorConfiguration, configurations) THEN
  434. RETURN TRUE;
  435. ELSE
  436. configurations := NIL;
  437. RETURN FALSE;
  438. END;
  439. END GetConfigurations;
  440. PROCEDURE GetOtherSpeedConfigurations*() : BOOLEAN;
  441. BEGIN
  442. ASSERT(qualifier # NIL);
  443. NEW(otherconfigurations, qualifier.bNumConfigurations);
  444. IF InternalGetConfigurations(DescriptorOtherSpeedConfig, otherconfigurations) THEN
  445. RETURN TRUE;
  446. ELSE
  447. otherconfigurations := NIL;
  448. RETURN FALSE;
  449. END;
  450. END GetOtherSpeedConfigurations;
  451. (**
  452. * Loads and parses the USB device qualifier. This descriptor is only available on USB 2.0 devices
  453. * which can operate as Low-/Fullspeed and Highspeed USB device.
  454. * It essentially contains the same information as the device descriptor, but the values are for
  455. * the case that the device would operate at its other operating speed.
  456. * @return TRUE, if operation succeeded, FALSE otherwise
  457. *)
  458. PROCEDURE GetDeviceQualifier*() : BOOLEAN;
  459. VAR buffer : Usbdi.BufferPtr;
  460. BEGIN
  461. ASSERT(descriptor # NIL);
  462. NEW(buffer, 10);
  463. IF GetDescriptor(DescriptorDeviceQualifier, 0, 0, 10, buffer^) THEN
  464. qualifier := ParseDeviceQualifier(buffer^);
  465. (* Duplicate fields from device descriptor *)
  466. qualifier.idVendor := descriptor.idVendor;
  467. qualifier.idProduct := descriptor.idProduct;
  468. qualifier.bcdDevice := descriptor.bcdDevice;
  469. qualifier.iManufacturer := descriptor(DeviceDescriptor).iManufacturer;
  470. qualifier.iProduct := descriptor(DeviceDescriptor).iProduct;
  471. qualifier.iSerialNumber := descriptor(DeviceDescriptor).iSerialNumber;
  472. qualifier.sManufacturer := descriptor(DeviceDescriptor).sManufacturer;
  473. qualifier.sProduct := descriptor(DeviceDescriptor).sProduct;
  474. qualifier.sSerialNumber := descriptor(DeviceDescriptor).sSerialNumber;
  475. qualifier.uManufacturer := descriptor(DeviceDescriptor).uManufacturer;
  476. qualifier.uProduct := descriptor(DeviceDescriptor).uProduct;
  477. qualifier.uSerialNumber := descriptor(DeviceDescriptor).uSerialNumber;
  478. RETURN TRUE;
  479. ELSIF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: Couldn't retrieve device qualifier."); KernelLog.Ln;
  480. END;
  481. RETURN FALSE;
  482. END GetDeviceQualifier;
  483. (**
  484. * Loads and parses the USB device descriptor. If parsing succeeds, the SELF.descriptor record
  485. * will be set, otherwise it's set to NIL.
  486. * @return TRUE, if opertation succeeded, FALSE otherwise
  487. *)
  488. PROCEDURE GetDeviceDescriptor*() : BOOLEAN;
  489. VAR buffer : Usbdi.BufferPtr;
  490. BEGIN
  491. NEW(buffer, 18);
  492. IF GetDescriptor(DescriptorDevice, 0, 0, 18, buffer^) THEN
  493. descriptor := ParseDeviceDescriptor(buffer^);
  494. RETURN TRUE;
  495. ELSIF Debug.Level >= Debug.Errors THEN KernelLog.String("Usb: Couldn't get the device descriptor."); KernelLog.Ln;
  496. END;
  497. RETURN FALSE;
  498. END GetDeviceDescriptor;
  499. PROCEDURE ShowName*;
  500. BEGIN
  501. IF (descriptor # NIL) & (descriptor(DeviceDescriptor).sManufacturer # NIL) OR (descriptor(DeviceDescriptor).sProduct # NIL) THEN
  502. IF descriptor(DeviceDescriptor).sManufacturer # NIL THEN KernelLog.String(descriptor(DeviceDescriptor).sManufacturer^); KernelLog.Char(" "); END;
  503. IF descriptor(DeviceDescriptor).sProduct # NIL THEN KernelLog.String(descriptor(DeviceDescriptor).sProduct^); END;
  504. ELSE
  505. KernelLog.String("unknown device");
  506. END;
  507. END ShowName;
  508. END UsbDevice;
  509. TYPE
  510. RootHubArray* = POINTER TO ARRAY OF UsbDevice;
  511. TYPE
  512. (* Root hub emulation. Emulate USB standard device requests for root hubs. Since all standard requests implemented in the
  513. * UsbDevice object use Request for the actual transfer, we simply overwrite it and emulated the results of the control transfers. *)
  514. EmulatedHubDevice* = OBJECT(UsbDevice);
  515. PROCEDURE GetPipe*(endpoint : LONGINT) : Usbdi.Pipe;
  516. BEGIN
  517. HALT(99); RETURN NIL; (* Root hubs don't provide pipes *)
  518. END GetPipe;
  519. PROCEDURE FreePipe*(pipe : Usbdi.Pipe);
  520. BEGIN
  521. HALT(99); (* Root hubs don't provide pipes *)
  522. END FreePipe;
  523. PROCEDURE Register*(hub: UsbDevice; portNbr: LONGINT);
  524. BEGIN
  525. HALT(99);
  526. END Register;
  527. (** Emulated USB device request *)
  528. PROCEDURE Request*(bmRequestType : SET; bRequest, wValue, wIndex, wLength : LONGINT; VAR buffer : Usbdi.Buffer) : Usbdi.Status;
  529. VAR res : Usbdi.Status;
  530. BEGIN
  531. res := Usbdi.Stalled;
  532. CASE bRequest OF
  533. SrGetStatus:
  534. BEGIN
  535. ASSERT(wLength = 2);
  536. IF (bmRequestType * Usbdi.ToHost # {}) & (bmRequestType - Usbdi.ToHost = {}) THEN
  537. (* Get Device status: Indicate Selfpowered, Remote Wakeup disabled *)
  538. buffer[0] := CHR(SYSTEM.VAL(LONGINT, {0})); buffer[1] := 0X; res := Usbdi.Ok;
  539. ELSIF (bmRequestType * Usbdi.ToHost # {}) & (bmRequestType - Usbdi.ToHost = Usbdi.Interface) THEN
  540. (* Get Interface status: Reserved *)
  541. buffer[0] := 0X; buffer[1] := 0X; res := Usbdi.Ok;
  542. ELSIF (bmRequestType * Usbdi.ToHost # {}) & (bmRequestType - Usbdi.ToHost = Usbdi.Endpoint) THEN
  543. (* Get endpoint status: Indicate endpoint not halted. *)
  544. buffer[0] := 0X; buffer[1] := 0X; res := Usbdi.Ok;
  545. END;
  546. END;
  547. (* All following requests will fail *)
  548. |SrClearFeature:
  549. |SrSetFeature:
  550. |SrGetDescriptor:
  551. |SrSetDescriptor:
  552. |SrGetConfiguration:
  553. |SrSetConfiguration:
  554. (* Requests unsupported by hubs / root hubs *)
  555. |SrGetInterface: HALT(99);
  556. |SrSetInterface: HALT(99);
  557. |SrSynchFrame: HALT(99);
  558. (* Requests unsupported by root hubs *)
  559. |SrSetAddress: HALT(99);
  560. ELSE
  561. HALT(99);
  562. END;
  563. RETURN res;
  564. END Request;
  565. (* Emulate device, configuration, interface and endpoint descriptors of root hub *)
  566. PROCEDURE EmulateDescriptors;
  567. VAR
  568. descriptor : DeviceDescriptor; configuration : ConfigurationDescriptor;
  569. interface : InterfaceDescriptor; endpoint : EndpointDescriptor;
  570. name : Lib.AsciiString;
  571. i, j : LONGINT;
  572. BEGIN
  573. (* Emulate device descriptor *)
  574. NEW(descriptor); SELF.descriptor := descriptor;
  575. descriptor.bNumConfigurations := 1;
  576. NEW(name, LEN(controller.name) + LEN(controller.desc) + 2);
  577. WHILE(i < LEN(controller.name)) & (controller.name[i] # 0X) DO name[i] := controller.name[i]; INC(i); END;
  578. name[i] := " "; name[i+1] := "(";
  579. WHILE(j < LEN(controller.desc)) & (controller.desc[j] # 0X) DO name[j + i + 2] := controller.desc[j]; INC(j); END;
  580. name[j + i + 2] := ")"; name[j + i + 3] := 0X;
  581. descriptor.sProduct := name;
  582. (* Emulate device configuration *)
  583. NEW(configurations, 1); NEW(configuration); configurations[0] := configuration;
  584. configuration.bNumInterfaces := 1;
  585. configuration.bmAttributes := {6,7}; (* Indicate self-powered device *)
  586. configuration.bMaxPower := 0; (* Root hub don't draw current from the BUS *)
  587. configuration.selfPowered := TRUE;
  588. configuration.remoteWakeup := FALSE;
  589. NEW(configurations[0].interfaces, 1); NEW(interface);
  590. configurations[0].interfaces[0] := interface;
  591. configurations[0].interfaces[0].bInterfaceClass := 9; (* Hub device class *)
  592. configurations[0].interfaces[0].bInterfaceSubClass := 0;
  593. configurations[0].interfaces[0].bNumEndpoints := 1;
  594. configurations[0].interfaces[0].bInterfaceProtocol := 0;
  595. NEW(configurations[0].interfaces[0].endpoints, 1);
  596. NEW(endpoint); endpoint.type := Usbdi.InterruptIn;
  597. configurations[0].interfaces[0].endpoints[0] := endpoint;
  598. actConfiguration := configuration;
  599. END EmulateDescriptors;
  600. PROCEDURE &New*(controller : UsbHcdi.Hcd);
  601. BEGIN
  602. ASSERT(controller # NIL);
  603. SELF.controller := controller;
  604. parent := SELF;
  605. hubFlag := TRUE;
  606. nbrOfPorts := controller.portCount;
  607. NEW(deviceAtPort, nbrOfPorts);
  608. NEW(portPermanentDisabled, nbrOfPorts);
  609. NEW(portErrors, nbrOfPorts);
  610. EmulateDescriptors;
  611. END New;
  612. END EmulatedHubDevice;
  613. TYPE
  614. RegisteredDriver* = POINTER TO RECORD
  615. probe : Usbdi.ProbeProc;
  616. name- : Usbdi.Name;
  617. desc- : Usbdi.Description;
  618. usedSuffix- : ARRAY 100 OF BOOLEAN; (* Which numbers are used for the unique names of instances *)
  619. next- : RegisteredDriver;
  620. END;
  621. TYPE
  622. (*
  623. * This object manages USB device drivers. It will be notified by the USB hub driver when devices
  624. * are attached/detached from the bus. If a device is attached, the driver manager calls the probe procedures
  625. * of all USB device drivers which are registered at the driver manager. When a device is detached from the
  626. * bus, the associated driver (if any) will be removed from the UsbDevice object.
  627. *)
  628. DriverManager* = OBJECT(Usbdi.DriverManager)
  629. VAR
  630. (* Driver manager internal USB device driver registy (exported for WMUsbInfo only). *)
  631. drivers- : ARRAY DmMaxPriorities OF RegisteredDriver;
  632. (* Incremented each time a driver is added or removed *)
  633. nbrOfDriverEvents- : LONGINT;
  634. (* local copy of rootHubs, since it could be modified while operating on it *)
  635. rootHubs : RootHubArray;
  636. alive, dead, probeDrivers : BOOLEAN;
  637. (* For each interface of the USB device <dev> try to install a registered driver; called when a new USB device is found *)
  638. PROCEDURE ProbeDevice*(dev : UsbDevice);
  639. VAR n : LONGINT;
  640. BEGIN
  641. FOR n := 0 TO dev.actConfiguration.bNumInterfaces - 1 DO
  642. IF dev.actConfiguration.interfaces[n](InterfaceDescriptor).driver = NIL THEN
  643. (* probe all device drivers and install a driver instance if a driver for the device is registered *)
  644. Install(dev, n);
  645. END;
  646. END;
  647. END ProbeDevice;
  648. (* Load driver using driver database services *)
  649. PROCEDURE ConsultDriverDatabase(dev : UsbDevice) : BOOLEAN;
  650. VAR loaded : BOOLEAN; d : DeviceDescriptor; i : InterfaceDescriptor; intf : LONGINT;
  651. BEGIN
  652. IF (dev # NIL) & (dev.descriptor # NIL) THEN
  653. d := dev.descriptor (DeviceDescriptor);
  654. (* First look for a device-specific driver *)
  655. loaded := UsbDriverLoader.LoadDeviceDriver(d.idVendor, d.idProduct, d.bcdDevice);
  656. (* Look for class-specific driver *)
  657. IF ~((d.bDeviceClass = 0EFH) & (d.bDeviceSubClass = 02H) & (d.bDeviceProtocol = 01H)) & (* IAD -> Search interfaces *)
  658. ((d.bDeviceClass # 0) OR (d.bDeviceSubClass # 0) OR (d.bDeviceProtocol # 0)) THEN (* Class description at device level *)
  659. IF UsbDriverLoader.LoadClassDriver(d.bDeviceClass, d.bDeviceSubClass, d.bDeviceProtocol, d.bcdDevice) THEN
  660. loaded := TRUE;
  661. END;
  662. ELSE (* Class description at interface level *)
  663. IF (dev.actConfiguration # NIL) & (dev.actConfiguration.interfaces # NIL) THEN
  664. intf := 0;
  665. LOOP
  666. i := dev.actConfiguration.interfaces[intf] (InterfaceDescriptor);
  667. (* TODO: Actually, some classes specifiy class-specfic descriptors that may contain the class revision the device supports. Use this instead of bcdDevice *)
  668. IF (i # NIL) & UsbDriverLoader.LoadClassDriver(i.bInterfaceClass, i.bInterfaceSubClass, i.bInterfaceProtocol, d.bcdDevice) THEN
  669. loaded := TRUE;
  670. END;
  671. INC(intf);
  672. IF intf >= LEN(dev.actConfiguration.interfaces) THEN EXIT END;
  673. END;
  674. END;
  675. END;
  676. END;
  677. RETURN loaded;
  678. END ConsultDriverDatabase;
  679. PROCEDURE LookupDriver(dev : UsbDevice; interface : InterfaceDescriptor; VAR temp : RegisteredDriver) : Usbdi.Driver;
  680. VAR drv : Usbdi.Driver; i : LONGINT;
  681. BEGIN
  682. LOOP (* Search all priority lists *)
  683. temp := drivers[i].next;
  684. LOOP (* Search all drivers in priority list i *)
  685. IF temp = NIL THEN (* No more drivers available *) EXIT; END;
  686. drv := temp.probe(dev, interface);
  687. IF drv # NIL THEN (* Driver found *) EXIT; END;
  688. temp := temp.next;
  689. END;
  690. IF drv # NIL THEN (* Driver found *) EXIT; END;
  691. INC(i); IF (i >= DmMaxPriorities) THEN (* No driver available *) EXIT; END;
  692. END;
  693. RETURN drv;
  694. END LookupDriver;
  695. (* Returns FALSE if connect failed or trapped *)
  696. PROCEDURE SafelyConnect(drv : Usbdi.Driver) : BOOLEAN;
  697. VAR connected, trap : BOOLEAN;
  698. BEGIN
  699. connected := drv.Connect();
  700. FINALLY
  701. IF trap & (Debug.Level >= Debug.Warnings) THEN KernelLog.String("Usb: Catched TRAP when calling Driver.Connect."); KernelLog.Ln; END;
  702. RETURN (~trap & connected);
  703. END SafelyConnect;
  704. PROCEDURE SafelyDisconnect(drv : Usbdi.Driver);
  705. VAR trap : BOOLEAN;
  706. BEGIN
  707. drv.Disconnect;
  708. FINALLY
  709. IF trap & (Debug.Level >= Debug.Warnings) THEN KernelLog.String("Usb: Catched TRAP when calling Driver.Disconnect."); KernelLog.Ln; END;
  710. END SafelyDisconnect;
  711. (* Checks whether an appropriate driver for the USB device <dev> is registred in registredDrivers.
  712. * If yes, a unique Plugins.Name is generated and the driver is added to the usbDrivers registry *)
  713. PROCEDURE Install(dev : UsbDevice; interfaceIdx : LONGINT);
  714. VAR
  715. temp : RegisteredDriver;
  716. drv : Usbdi.Driver;
  717. interface : InterfaceDescriptor;
  718. i : LONGINT; res : WORD;
  719. name : Usbdi.Name;
  720. suffix : LONGINT; (* 0-99; suffix is used to generate unique names for AosPlugin.Name *)
  721. BEGIN
  722. interface := dev.actConfiguration.interfaces[interfaceIdx] (InterfaceDescriptor);
  723. (* Search an USB device driver for this device (See USB Common Class Specification, 3.10 Locating USB Drivers) *)
  724. (* we have to consult the database first always because of priorities. If a driver has already been loaded previously, this will return FALSE anyway *)
  725. IF ConsultDriverDatabase(dev) THEN
  726. RETURN; (* Appropriate device driver has been loaded from driver database. Loading will force bus enumeration, so don't continue here. *)
  727. ELSE
  728. drv := LookupDriver(dev, interface, temp);
  729. END;
  730. BEGIN {EXCLUSIVE}
  731. (* Since it's possible that two threads (active body, hub driver via ProbeDevice) try to install a driver for the same device and interface,
  732. we need to check here *)
  733. IF (drv # NIL) & (interface.driver = NIL) THEN
  734. (* Driver found; generate a unique name for the instance of this driver to be created *)
  735. drv.device := dev; drv.interface := interface;
  736. (* Get first unused suffix *)
  737. i := 0; WHILE (temp.usedSuffix[i] = TRUE) & (i <= 99) DO INC(i); END;
  738. IF (i = 99) & (temp.usedSuffix[99] = TRUE) THEN
  739. KernelLog.String("Usb: No more than 99 instances of a driver supported"); KernelLog.Ln;
  740. RETURN;
  741. ELSE
  742. temp.usedSuffix[i] := TRUE; suffix := i;
  743. END;
  744. name := AddSuffix(temp.name, suffix);
  745. drv.SetName(name); drv.desc := temp.desc;
  746. (* Add this driver to the usbDrivers registry *)
  747. usbDrivers.Add(drv, res);
  748. IF res # Plugins.Ok THEN
  749. KernelLog.String("Usb: Couldn't register USB device driver (res: "); KernelLog.Int(res, 0); KernelLog.String(")"); KernelLog.Ln;
  750. temp.usedSuffix[suffix] := FALSE;
  751. RETURN;
  752. ELSE (* USB device driver successfully registered *)
  753. interface.driver := drv;
  754. IF ~SafelyConnect(drv) THEN
  755. KernelLog.String("Usb: Connect of driver "); KernelLog.String(drv.name); KernelLog.String("("); KernelLog.String(drv.desc); KernelLog.String(") failed."); KernelLog.Ln;
  756. ASSERT(drv.device(UsbDevice).parent.hubFlag);
  757. ASSERT(drv.device(UsbDevice).parent.portPermanentDisabled # NIL);
  758. (* Don't try to re-install a driver until ConnectStatusChange at this port *)
  759. drv.device(UsbDevice).parent.portPermanentDisabled[drv.device(UsbDevice).port] := TRUE;
  760. drv.device(UsbDevice).Remove;
  761. RETURN;
  762. END;
  763. IF Debug.Trace & Debug.traceDm THEN KernelLog.String("Usb: Registered USB device driver: "); KernelLog.String(name); KernelLog.Ln; END;
  764. END;
  765. END;
  766. END;
  767. END Install;
  768. (* For all USB devices which are attached to any USB root hub in the system the procedure ProbeDeviceChain() is called *)
  769. PROCEDURE ProbeDriversInternal;
  770. VAR i : LONGINT;
  771. BEGIN (* Works with local copy of rootHubs array *)
  772. GetRootHubs(rootHubs);
  773. IF rootHubs # NIL THEN
  774. FOR i := 0 TO LEN(rootHubs)-1 DO
  775. ProbeDeviceChain(rootHubs[i]);
  776. rootHubs[i] := NIL; (* we don't need the reference anymore *)
  777. END;
  778. END;
  779. END ProbeDriversInternal;
  780. (* Called by ProbeDrivers; calls Install() for all devices which don't already have a driver instance installed *)
  781. PROCEDURE ProbeDeviceChain(dev : UsbDevice);
  782. VAR n : LONGINT;
  783. BEGIN
  784. FOR n := 0 TO dev.actConfiguration.bNumInterfaces - 1 DO
  785. IF dev.actConfiguration.interfaces[n](InterfaceDescriptor).driver = NIL THEN
  786. (* Probe all device drivers and install a driver instance if a driver for the device is registered *)
  787. Install(dev, n);
  788. END;
  789. END;
  790. IF dev.hubFlag THEN
  791. FOR n := 0 TO dev.nbrOfPorts - 1 DO
  792. IF dev.deviceAtPort[n] # NIL THEN ProbeDeviceChain(dev.deviceAtPort[n]); END;
  793. END;
  794. END;
  795. END ProbeDeviceChain;
  796. (** Add a USB device driver to the internal registry. Driver names have to be unique and no longer than 30 characters (incl. Null-String) *)
  797. PROCEDURE Add*(probe : Usbdi.ProbeProc; CONST name: Usbdi.Name; CONST desc: Usbdi.Description; priority : LONGINT);
  798. VAR temp, new : RegisteredDriver; i : LONGINT;
  799. BEGIN
  800. (* The specified name mustn't be longer than 30 characters (including 0X) *)
  801. WHILE (name[i] # 0X) & (i < 32) DO INC(i); END;
  802. IF (i > 29) OR (name = "") THEN
  803. KernelLog.String("Usb: Couldn't add driver (name NULL or longer than 30 characters or not NULL-terminated)"); KernelLog.Ln;
  804. RETURN;
  805. END;
  806. (* Specified priority must be in the interval [0,DmMaxPriorities-1] *)
  807. IF (priority > DmMaxPriorities-1) OR (priority < 0) THEN
  808. KernelLog.String("Usb: Couldn't add driver (Priority invalid)"); KernelLog.Ln;
  809. RETURN;
  810. END;
  811. BEGIN {EXCLUSIVE}
  812. (* Check whether there is no driver with the name <name> registered *)
  813. FOR i := 0 TO DmMaxPriorities-1 DO
  814. temp := drivers[i].next;
  815. WHILE temp # NIL DO
  816. IF temp.name = name THEN
  817. KernelLog.String("Usb: Couldn't add driver (driver name already registered)"); KernelLog.Ln;
  818. RETURN;
  819. END;
  820. temp := temp.next;
  821. END;
  822. END;
  823. (* Okay, arguments are valid, create RegisteredDriver object and add it to internal registry *)
  824. NEW(new);
  825. new.probe := probe;
  826. new.name := name;
  827. new.desc := desc;
  828. new.next := drivers[priority].next;
  829. FOR i := 0 TO 99 DO new.usedSuffix[i] := FALSE; END;
  830. drivers[priority].next := new;
  831. END;
  832. IF Debug.Verbose THEN
  833. KernelLog.String("Usb: Driver "); KernelLog.String(name); KernelLog.String(" ("); KernelLog.String(desc); KernelLog.String(")");
  834. KernelLog.String(" has been added."); KernelLog.Ln;
  835. END;
  836. (* Maybe a USB device is already attached, just waiting for this driver: check! *)
  837. ProbeDrivers;
  838. BEGIN {EXCLUSIVE} INC(nbrOfDriverEvents); END;
  839. END Add;
  840. (* Removes a device driver instance from usbDriver registry; only used by the USB driver itself*)
  841. PROCEDURE RemoveInstance(CONST name : Usbdi.Name; dev : UsbDevice);
  842. VAR
  843. plugin : Plugins.Plugin;
  844. driver : Usbdi.Driver;
  845. regname : Plugins.Name;
  846. temp : RegisteredDriver;
  847. i, suffix : LONGINT;
  848. BEGIN
  849. plugin := usbDrivers.Get(name);
  850. IF plugin # NIL THEN (* Uninstall this instance *)
  851. driver := plugin (Usbdi.Driver);
  852. usbDrivers.Remove(plugin);
  853. SafelyDisconnect(driver);
  854. (* Remove allocated pipes *)
  855. driver.device(UsbDevice).controller.FreeAll(driver.device(UsbDevice).address);
  856. (* Get the name of the registered device driver which generates this instances *)
  857. WHILE name[i] # 0X DO regname[i] := name[i]; INC(i); END;
  858. regname[i-1] := 0X; regname[i-2] := 0X;
  859. suffix := GetSuffix(name);
  860. (* Need to update usedSuffix at the registered driver *)
  861. i := 0;
  862. LOOP
  863. temp := drivers[i].next;
  864. WHILE (temp # NIL) & (temp.name # regname) DO temp := temp.next; END;
  865. IF temp # NIL THEN (* Registered device driver found *)
  866. temp.usedSuffix[suffix] := FALSE;
  867. EXIT;
  868. END;
  869. INC(i); IF (i >= DmMaxPriorities) THEN (* No driver found *) EXIT; END;
  870. END;
  871. IF (i = DmMaxPriorities) & (temp = NIL) THEN (* Registered driver for this instance was not found *)
  872. IF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: Couldn't find registered driver of the removed driver instance"); KernelLog.Ln; END;
  873. END;
  874. ELSE (* No such instance found *)
  875. IF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: Warning: Couldn't remove driver instance (no instance found)"); KernelLog.Ln; END;
  876. END;
  877. END RemoveInstance;
  878. (**
  879. * Calls Disconnect of all instances of the driver. All instances are removed from the usbDrivers registry
  880. * and the device driver is removed from the internal registry. *)
  881. PROCEDURE Remove*(CONST name : Plugins.Name);
  882. VAR
  883. prev, temp : RegisteredDriver;
  884. regname : Plugins.Name;
  885. plugin : Plugins.Plugin;
  886. dev : UsbDevice;
  887. i, j : LONGINT;
  888. BEGIN {EXCLUSIVE}
  889. IF Debug.Trace & Debug.traceDm THEN KernelLog.String("Usb: Removing driver: "); KernelLog.String(name); KernelLog.Ln; END;
  890. (* Remove device driver from internal registry *)
  891. LOOP
  892. prev := drivers[i];
  893. temp := drivers[i].next;
  894. WHILE (temp # NIL) & (temp.name # name) DO temp := temp.next; prev := prev.next; END;
  895. IF temp # NIL THEN (* Driver found *) EXIT; END;
  896. INC(i); IF (i >= DmMaxPriorities) THEN (* No driver available *) EXIT; END;
  897. END;
  898. (* Remove driver from internal registry and remove all its instances *)
  899. IF temp # NIL THEN
  900. (* Remove driver from internal registry *)
  901. prev.next := temp.next;
  902. (* Remove all instances of the driver *)
  903. FOR i := 0 TO 99 DO
  904. IF temp.usedSuffix[i] = TRUE THEN (* Driver instance found *)
  905. (* Get plugin name *)
  906. regname := AddSuffix(temp.name, i);
  907. plugin := usbDrivers.Get(regname);
  908. IF plugin = NIL THEN
  909. IF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: Error while trying to remove driver from usbDrivers registry"); KernelLog.Ln; END;
  910. ELSE
  911. SafelyDisconnect(plugin(Usbdi.Driver));
  912. dev := plugin(Usbdi.Driver).device (UsbDevice);
  913. IF dev # NIL THEN (* Remove link to driver instance from USB device *)
  914. IF ~(dev.hubFlag & (dev.parent = dev)) THEN
  915. dev.controller.FreeAll(dev.address);
  916. END;
  917. FOR j := 0 TO dev.actConfiguration.bNumInterfaces-1 DO
  918. IF dev.actConfiguration.interfaces[j](InterfaceDescriptor).driver = plugin(Usbdi.Driver) THEN
  919. dev.actConfiguration.interfaces[j](InterfaceDescriptor).driver := NIL;
  920. END;
  921. END;
  922. END;
  923. usbDrivers.Remove(plugin);
  924. temp.usedSuffix[i]:=FALSE;
  925. END;
  926. END;
  927. END;
  928. INC(nbrOfDriverEvents);
  929. ELSIF Debug.Level >= Debug.Warnings THEN
  930. KernelLog.String("Usb: Warning: Couldn't remove driver "); KernelLog.String(name); KernelLog.Ln;
  931. END;
  932. END Remove;
  933. (* Appends the suffix to name; the suffix is a number between 0-99 which is added as 2 ASCII characters (each 1 bytes)
  934. * note: name mustn't be longer than 30 characters (incl. Null-Termination) *)
  935. PROCEDURE AddSuffix*(CONST name: Plugins.Name; suffix : LONGINT) : Plugins.Name;
  936. VAR i : LONGINT; newName : Plugins.Name;
  937. BEGIN
  938. WHILE name[i]#0X DO newName[i]:=name[i]; INC(i); END;
  939. (* Append suffix to name *)
  940. IF suffix < 10 THEN
  941. newName[i]:="0";
  942. newName[i+1]:=CHR(suffix+48);
  943. newName[i+2]:=0X;
  944. ELSE
  945. newName[i]:=CHR((suffix DIV 10)+48);
  946. newName[i+1]:=CHR((suffix MOD 10)+48);
  947. newName[i+2]:=0X;
  948. END;
  949. RETURN newName;
  950. END AddSuffix;
  951. (* Returns the suffix of the Plugins.Name name *)
  952. PROCEDURE GetSuffix(CONST name : Plugins.Name) : LONGINT;
  953. VAR i, suffix : LONGINT;
  954. BEGIN
  955. WHILE (name[i] # 0X) & (i < 32) DO INC(i); END;
  956. suffix:= (ORD(name[i-2]) - 48) * 10 + ORD(name[i-1])-48;
  957. ASSERT((suffix >= 0) & (suffix <= 99));
  958. RETURN suffix;
  959. END GetSuffix;
  960. (* Displays a list of registered drivers *)
  961. PROCEDURE Show*;
  962. VAR temp : RegisteredDriver; i : LONGINT;
  963. BEGIN
  964. KernelLog.Ln; KernelLog.String("Usb: Registered USB device drivers: "); KernelLog.Ln;
  965. FOR i := 0 TO DmMaxPriorities - 1 DO
  966. temp := drivers[i].next;
  967. WHILE temp # NIL DO
  968. KernelLog.String(" ");
  969. KernelLog.String(temp.name); KernelLog.String(" ("); KernelLog.String(temp.desc); KernelLog.String(")");
  970. KernelLog.String(" Priority: "); KernelLog.Int(i, 0); KernelLog.Ln;
  971. temp := temp.next;
  972. END;
  973. END;
  974. END Show;
  975. PROCEDURE ProbeDrivers;
  976. BEGIN {EXCLUSIVE}
  977. probeDrivers := TRUE;
  978. END ProbeDrivers;
  979. PROCEDURE Terminate;
  980. BEGIN
  981. BEGIN {EXCLUSIVE} alive := FALSE; END;
  982. (* Release object lock to prevent deadlock *)
  983. BEGIN {EXCLUSIVE} AWAIT(dead); END;
  984. END Terminate;
  985. PROCEDURE &Init*;
  986. VAR i : LONGINT; temp : RegisteredDriver;
  987. BEGIN
  988. alive := TRUE; dead := FALSE;
  989. FOR i := 0 TO 11 DO NEW(temp); drivers[i] := temp; END; (* Allocate list heads *)
  990. END Init;
  991. BEGIN {ACTIVE}
  992. (* This thread decouples the process of checking all connected USB devices for matching device drivers from the caller. *)
  993. (* It will be active in the following two situations: *)
  994. (* - A device driver is successfully registered at the driver manager (Add procedure) *)
  995. (* - The driver lookup service has been enabled *)
  996. (* *)
  997. (* Note: *)
  998. (* When a device is connected to a bus, the thread of the corresponding hub driver will call ProbeDevice, so different *)
  999. (* hubs/busses can install device drivers concurrently. To prevent two threads (this one and the hub driver's one) to con-*)
  1000. (* currently install the same device driver to the same function, another check is made in proedure install. *)
  1001. WHILE alive DO
  1002. BEGIN {EXCLUSIVE}
  1003. AWAIT(probeDrivers OR ~alive);
  1004. probeDrivers := FALSE;
  1005. END;
  1006. IF alive THEN (* Check availability of device drivers for all connected devices *)
  1007. IF Debug.Trace & Debug.traceDm THEN
  1008. KernelLog.Enter; KernelLog.String("Usb: Check connected devices for available device drivers"); KernelLog.Exit;
  1009. END;
  1010. ProbeDriversInternal;
  1011. END;
  1012. END;
  1013. IF Debug.Trace & Debug.traceDm THEN KernelLog.Enter; KernelLog.String("Usb: Driver Manager object terminated."); KernelLog.Exit; END;
  1014. BEGIN {EXCLUSIVE} dead := TRUE; END;
  1015. END DriverManager;
  1016. TYPE
  1017. Registry= OBJECT(Plugins.Registry) END Registry;
  1018. VAR
  1019. usbDrivers- : (*Plugins.*)Registry; (* Instanciated USB device drivers (linked to a attached USB device) *)
  1020. drivers- : DriverManager; (* Usb internal registry for installable USB device drivers *)
  1021. rootHubs : RootHubArray;
  1022. nbrOfTopologyEvents- : LONGINT; (* Incremented each time a device is connected/disconnected *)
  1023. PROCEDURE ParseDeviceDescriptor(buffer : Usbdi.Buffer) : DeviceDescriptor;
  1024. VAR descriptor : DeviceDescriptor;
  1025. BEGIN
  1026. IF LEN(buffer) >= 18 THEN
  1027. NEW(descriptor);
  1028. descriptor.bcdUSB := ORD(buffer[2]) + 256*SYSTEM.VAL(LONGINT, ORD(buffer[3]));
  1029. descriptor.bDeviceClass := ORD(buffer[4]);
  1030. descriptor.bDeviceSubClass := ORD(buffer[5]);
  1031. descriptor.bDeviceProtocol := ORD(buffer[6]);
  1032. descriptor.bMaxPacketSize0 := ORD(buffer[7]);
  1033. descriptor.idVendor := ORD(buffer[8]) + 256*SYSTEM.VAL(LONGINT, ORD(buffer[9]));
  1034. descriptor.idProduct := ORD(buffer[10]) + 256*SYSTEM.VAL(LONGINT, ORD(buffer[11]));
  1035. descriptor.bcdDevice := ORD(buffer[12]) + 256*SYSTEM.VAL(LONGINT, ORD(buffer[13]));
  1036. descriptor.iManufacturer := ORD(buffer[14]);
  1037. descriptor.iProduct := ORD(buffer[15]);
  1038. descriptor.iSerialNumber := ORD(buffer[16]);
  1039. descriptor.bNumConfigurations := ORD(buffer[17]);
  1040. ELSIF Debug.Level >= Debug.Errors THEN KernelLog.String("Usb: Could not parse device descriptor."); KernelLog.Ln;
  1041. END;
  1042. RETURN descriptor;
  1043. END ParseDeviceDescriptor;
  1044. (**
  1045. * Parses the USB device qualifier. This descriptor is only available on USB 2.0 devices which can operate as
  1046. * Low-/Fullspeed and Highspeed USB device. It essentially contains the same information as the device descriptor,
  1047. * but the values are for the case that the device would operate at its other operating speed.
  1048. *)
  1049. PROCEDURE ParseDeviceQualifier(buffer : Usbdi.Buffer) : DeviceDescriptor;
  1050. VAR qualifier : DeviceDescriptor;
  1051. BEGIN
  1052. IF LEN(buffer) >= 10 THEN
  1053. NEW(qualifier);
  1054. qualifier.bcdUSB := ORD(buffer[2]) + 256*SYSTEM.VAL(LONGINT, ORD(buffer[3]));
  1055. qualifier.bDeviceClass := ORD(buffer[4]);
  1056. qualifier.bDeviceSubClass := ORD(buffer[5]);
  1057. qualifier.bDeviceProtocol := ORD(buffer[6]);
  1058. qualifier.bMaxPacketSize0 := ORD(buffer[7]);
  1059. qualifier.bNumConfigurations := ORD(buffer[8]);
  1060. ELSIF Debug.Level >= Debug.Errors THEN KernelLog.String("Usb: Could not parse device qualifier."); KernelLog.Ln;
  1061. END;
  1062. RETURN qualifier;
  1063. END ParseDeviceQualifier;
  1064. (** Parse all Interface Association Descriptors in the given configuration. All other descriptor types are skipped. *)
  1065. PROCEDURE ParseInterfaceAssociation(buffer : Usbdi.Buffer) : Usbdi.Iads;
  1066. VAR iads : Usbdi.Iads; iad : InterfaceAssociationDescriptor; idx, num, i : LONGINT;
  1067. BEGIN
  1068. IF Debug.Trace & Debug.traceParsing THEN KernelLog.String("Usb: Parsing interface association descriptors:"); KernelLog.Ln; END;
  1069. (* Determine number of available IADs *)
  1070. WHILE(idx+1 < LEN(buffer)) DO
  1071. IF (ORD(buffer[idx+1]) = DescriptorIad) THEN INC(num); END;
  1072. idx := idx + ORD(buffer[idx+0]);
  1073. END;
  1074. idx := 0;
  1075. IF num > 0 THEN (* Parse the IADs *)
  1076. NEW(iads, num);
  1077. LOOP
  1078. IF idx+8 >= LEN(buffer) THEN EXIT; END;
  1079. IF i >= LEN(iads) THEN EXIT; END;
  1080. IF ORD(buffer[idx+1]) = DescriptorIad THEN
  1081. IF Debug.Trace & Debug.traceParsing THEN ShowParse("interface association", idx, ORD(buffer[idx+1]), ORD(buffer[idx+0])); END;
  1082. NEW(iad);
  1083. iad.bFirstInterface := ORD(buffer[idx+2]);
  1084. iad.bInterfaceCount := ORD(buffer[idx+3]);
  1085. iad.bFunctionClass := ORD(buffer[idx+4]);
  1086. iad.bFunctionSubClass := ORD(buffer[idx+5]);
  1087. iad.bFunctionProtocol := ORD(buffer[idx+6]);
  1088. iad.iFunction := ORD(buffer[idx+7]) + 256*SYSTEM.VAL(LONGINT, ORD(buffer[idx+8]));
  1089. iads[i] := iad;
  1090. INC(i);
  1091. END;
  1092. idx := idx + ORD(buffer[idx+0]);
  1093. END;
  1094. ELSIF Debug.Trace & Debug.traceParsing THEN KernelLog.String("No interface association descriptors found."); KernelLog.Ln;
  1095. END;
  1096. IF i # num THEN (* We didn't find all IADs... we can live without them, but warn the user *)
  1097. IF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: Warning: Error when parsing IADs."); KernelLog.Ln; END;
  1098. RETURN NIL;
  1099. END;
  1100. RETURN iads;
  1101. END ParseInterfaceAssociation;
  1102. (* Parse all non-standard descriptors found in the configuration *)
  1103. PROCEDURE ParseUnknownDescriptors(configuration : Usbdi.ConfigurationDescriptor; buffer : Usbdi.Buffer) : Usbdi.UnknownDescriptor;
  1104. VAR idx, i, type, curIntf, curAltIntf, curEp : LONGINT; list, unknown : Usbdi.UnknownDescriptor;
  1105. PROCEDURE AppendToList(head, unknown : Usbdi.UnknownDescriptor);
  1106. VAR u : Usbdi.UnknownDescriptor;
  1107. BEGIN
  1108. u := head; WHILE(u.next # NIL) DO u := u.next; END;
  1109. u.next := unknown;
  1110. END AppendToList;
  1111. PROCEDURE AppendNonStandard(unknown : Usbdi.UnknownDescriptor) : BOOLEAN;
  1112. VAR i : LONGINT; intf, altIntf : Usbdi.InterfaceDescriptor; endp : Usbdi.EndpointDescriptor;
  1113. BEGIN
  1114. IF (curIntf = -1) THEN (* Append to configuration *)
  1115. IF configuration.unknown = NIL THEN configuration.unknown := unknown;
  1116. ELSE
  1117. AppendToList(configuration.unknown, unknown);
  1118. END;
  1119. ELSE (* Append to interface, alternate interface or endpoint *)
  1120. (* Search Interface *)
  1121. LOOP
  1122. IF (configuration.interfaces=NIL) OR (i >= LEN(configuration.interfaces)) THEN EXIT; END;
  1123. intf := configuration.interfaces[i];
  1124. IF intf.bInterfaceNumber = curIntf THEN EXIT; END;
  1125. INC(i);
  1126. END;
  1127. IF (intf = NIL) OR (intf.bInterfaceNumber # curIntf) THEN RETURN FALSE; END;
  1128. IF curAltIntf # 0 THEN
  1129. (* Search alternate interface *)
  1130. i := 0;
  1131. LOOP
  1132. IF (intf.alternateInterfaces=NIL) OR (i >= LEN(intf.alternateInterfaces)) THEN EXIT; END;
  1133. altIntf := intf.alternateInterfaces[i];
  1134. IF altIntf.bAlternateSetting = curAltIntf THEN EXIT; END;
  1135. INC(i);
  1136. END;
  1137. IF (altIntf = NIL) OR (altIntf.bAlternateSetting # curAltIntf) THEN RETURN FALSE; END;
  1138. intf := altIntf;
  1139. END;
  1140. IF curEp = -1 THEN (* Append to interface *)
  1141. IF intf.unknown = NIL THEN intf.unknown := unknown;
  1142. ELSE
  1143. AppendToList(intf.unknown, unknown);
  1144. END;
  1145. ELSE (* Append to endpoint *)
  1146. (* Search endpoint descriptor *)
  1147. i := 0;
  1148. LOOP
  1149. IF (intf.endpoints = NIL) OR (i >= LEN(intf.endpoints)) THEN EXIT; END;
  1150. endp := intf.endpoints[i];
  1151. IF endp.bEndpointAddress = curEp THEN EXIT; END;
  1152. INC(i);
  1153. END;
  1154. IF (endp = NIL) OR (endp.bEndpointAddress # curEp) THEN RETURN FALSE; END;
  1155. IF endp.unknown = NIL THEN endp.unknown := unknown;
  1156. ELSE
  1157. AppendToList(endp.unknown, unknown);
  1158. END;
  1159. END;
  1160. END;
  1161. RETURN TRUE;
  1162. END AppendNonStandard;
  1163. BEGIN
  1164. ASSERT(configuration # NIL);
  1165. IF Debug.Trace & Debug.traceParsing THEN KernelLog.String("Usb: Parsing non-standard descriptors:"); KernelLog.Ln; END;
  1166. curIntf := -1; curAltIntf := -1; curEp := -1;
  1167. LOOP
  1168. IF idx + 1 >= LEN(buffer) THEN EXIT; END;
  1169. type := ORD(buffer[idx+1]);
  1170. IF type = DescriptorConfiguration THEN
  1171. (* skip *)
  1172. ELSIF type = DescriptorIad THEN
  1173. curIntf := -1; curAltIntf := -1; curEp := -1;
  1174. ELSIF type = DescriptorInterface THEN
  1175. IF idx+3 >= LEN(buffer) THEN EXIT; END;
  1176. curIntf := ORD(buffer[idx+2]);
  1177. curAltIntf := ORD(buffer[idx+3]);
  1178. curEp := -1;
  1179. ELSIF type = DescriptorEndpoint THEN
  1180. IF idx+2 >= LEN(buffer) THEN EXIT; END;
  1181. curEp := ORD(buffer[idx+2]);
  1182. ELSE (* Non-Standard descriptor *)
  1183. NEW(unknown);
  1184. unknown.bLength := ORD(buffer[idx+0]);
  1185. unknown.bDescriptorType := ORD(buffer[idx+1]);
  1186. IF Debug.Trace & Debug.traceParsing THEN ShowParse("unknown descriptor", idx, unknown.bDescriptorType, unknown.bLength); END;
  1187. IF idx + unknown.bLength > LEN(buffer) THEN EXIT; END;
  1188. NEW(unknown.descriptor, unknown.bLength);
  1189. FOR i := 0 TO unknown.bLength-1 DO unknown.descriptor[i] := buffer[idx+i] END;
  1190. IF ~AppendNonStandard(unknown) THEN
  1191. IF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: ParseUnknownDescriptors: Warning: Could not assign non-standard descriptor."); KernelLog.Ln; END;
  1192. RETURN NIL;
  1193. END;
  1194. END;
  1195. idx := idx + ORD(buffer[idx + 0]);
  1196. END;
  1197. IF idx # LEN(buffer) THEN
  1198. IF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: ParseUnknownDescriptors: Warning: Parse Error"); KernelLog.Ln; END;
  1199. list := NIL;
  1200. END;
  1201. RETURN list;
  1202. END ParseUnknownDescriptors;
  1203. (* Parse the first endpoint descriptor found in the configuration beginning at index idx *)
  1204. PROCEDURE ParseEndpointDescriptor(buffer : Usbdi.Buffer; VAR idx : LONGINT) : EndpointDescriptor;
  1205. VAR endpoint : EndpointDescriptor; dword : SET;
  1206. PROCEDURE GetEndpointType(address, attributes : SET) : LONGINT;
  1207. VAR type : LONGINT;
  1208. BEGIN
  1209. IF attributes * {0..1} = {} THEN
  1210. type := Usbdi.Control;
  1211. ELSE
  1212. IF address * {7} = {} THEN (* direction = OUT *)
  1213. IF attributes * {0..1} = {0} THEN type := Usbdi.IsochronousOut;
  1214. ELSIF attributes * {0..1} = {1} THEN type := Usbdi.BulkOut;
  1215. ELSE type := Usbdi.InterruptOut;
  1216. END;
  1217. ELSE (* direction = IN *)
  1218. IF attributes * {0..1} = {0} THEN type := Usbdi.IsochronousIn;
  1219. ELSIF attributes * {0..1} = {1} THEN type := Usbdi.BulkIn;
  1220. ELSE type := Usbdi.InterruptIn;
  1221. END;
  1222. END;
  1223. END;
  1224. RETURN type;
  1225. END GetEndpointType;
  1226. BEGIN
  1227. IF (Debug.Trace & Debug.traceParsing) & (idx+1 < LEN(buffer)) THEN ShowParse("endpoint",idx, ORD(buffer[idx+1]), ORD(buffer[idx+0])); END;
  1228. (* Skip non-USB-standard descriptors (e.g. HID descriptors) *)
  1229. SkipOthers(DescriptorEndpoint, buffer, idx);
  1230. IF idx + 6 >= LEN(buffer) THEN
  1231. IF Debug.Level >= Debug.Errors THEN KernelLog.String("Usb: ParseEndpoint: Buffer too short."); KernelLog.Ln; END;
  1232. RETURN NIL;
  1233. END;
  1234. ASSERT(ORD(buffer[idx+1])=DescriptorEndpoint);
  1235. NEW(endpoint);
  1236. endpoint.bLength := ORD(buffer[idx + 0]);
  1237. endpoint.bEndpointAddress := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, ORD(buffer[idx + 2])) * {0..3, 7});
  1238. endpoint.bmAttributes := SYSTEM.VAL(SET, ORD(buffer[idx + 3]));
  1239. endpoint.type := GetEndpointType(SYSTEM.VAL(SET, endpoint.bEndpointAddress), endpoint.bmAttributes);
  1240. dword := SYSTEM.VAL(SET, ORD(buffer[idx + 4]) + 256*SYSTEM.VAL(LONGINT, ORD(buffer[idx + 5])));
  1241. endpoint.wMaxPacketSize := SYSTEM.VAL(LONGINT, dword * {0..10});
  1242. endpoint.mult := LSH(SYSTEM.VAL(LONGINT, dword * {11..12}), -11) + 1;
  1243. endpoint.bInterval := ORD(buffer[idx + 6]);
  1244. idx := idx + ORD(buffer[idx + 0]);
  1245. RETURN endpoint;
  1246. END ParseEndpointDescriptor;
  1247. (* Parse the first interface descriptor beginning at index idx including its endpoints *)
  1248. PROCEDURE ParseInterfaceDescriptor(buffer :Usbdi.Buffer; VAR idx : LONGINT) : InterfaceDescriptor;
  1249. VAR interface : InterfaceDescriptor; e : LONGINT;
  1250. BEGIN
  1251. IF (Debug.Trace & Debug.traceParsing) & (idx+1 < LEN(buffer)) THEN ShowParse("interface",idx, ORD(buffer[idx+1]), ORD(buffer[idx+0])); END;
  1252. (* Skip non-USB-standard descriptors (e.g. HID descriptors) *)
  1253. SkipOthers(DescriptorInterface, buffer, idx);
  1254. IF idx + 8 >= LEN(buffer) THEN
  1255. IF Debug.Level >= Debug.Errors THEN KernelLog.String("Usb: ParseInterface: Buffer too short."); KernelLog.Ln; END;
  1256. RETURN NIL;
  1257. END;
  1258. ASSERT(ORD(buffer[idx + 1])=DescriptorInterface);
  1259. NEW(interface);
  1260. interface.bLength := ORD(buffer[idx + 0]);
  1261. interface.bInterfaceNumber := ORD(buffer[idx + 2]);
  1262. interface.bAlternateSetting := ORD(buffer[idx + 3]);
  1263. interface.bNumEndpoints := ORD(buffer[idx + 4]);
  1264. interface.bInterfaceClass := ORD(buffer[idx + 5]);
  1265. interface.bInterfaceSubClass := ORD(buffer[idx + 6]);
  1266. interface.bInterfaceProtocol := ORD(buffer[idx + 7]);
  1267. interface.iInterface := ORD(buffer[idx + 8]);
  1268. idx := idx + ORD(buffer[idx + 0]);
  1269. (* Interface can have zero endpoints (only containing endpoint 0) *)
  1270. IF (interface.bNumEndpoints > 0) THEN
  1271. NEW(interface.endpoints, interface.bNumEndpoints);
  1272. FOR e := 0 TO interface.bNumEndpoints-1 DO
  1273. interface.endpoints[e] := ParseEndpointDescriptor(buffer, idx);
  1274. IF interface.endpoints[e] = NIL THEN RETURN NIL; END;
  1275. END;
  1276. END;
  1277. RETURN interface;
  1278. END ParseInterfaceDescriptor;
  1279. (* Parse the configuration descriptor including all standard interfaces, alternate interfaces and endpoints. *)
  1280. PROCEDURE ParseConfigurationDescriptor(buffer : Usbdi.Buffer) : ConfigurationDescriptor;
  1281. VAR configuration : ConfigurationDescriptor; i, j, idx, num, intfNbr : LONGINT;
  1282. (* Return the number of alternate interfaces of interface <intf> starting at idx *)
  1283. PROCEDURE NumAltInterfaces(intf, idx : LONGINT) : LONGINT;
  1284. VAR res := 0: LONGINT;
  1285. BEGIN
  1286. WHILE(idx + 3 < LEN(buffer)) DO
  1287. IF (ORD(buffer[idx+1]) = DescriptorInterface) & (ORD(buffer[idx+2]) = intf) & (ORD(buffer[idx+3]) # 0) THEN
  1288. INC(res);
  1289. END;
  1290. idx := idx + ORD(buffer[idx+0]);
  1291. END;
  1292. RETURN res;
  1293. END NumAltInterfaces;
  1294. BEGIN
  1295. IF Debug.Trace & Debug.traceParsing THEN
  1296. ShowParse("configuration",idx, ORD(buffer[idx+1]), ORD(buffer[idx+0]));
  1297. KernelLog.String("Usb: Total Length of configuration: "); KernelLog.Int(LEN(buffer), 0); KernelLog.Ln;
  1298. END;
  1299. NEW(configuration);
  1300. configuration.bLength := ORD(buffer[0]);
  1301. configuration.wTotalLength := ORD(buffer[2])+ 256*SYSTEM.VAL(LONGINT, ORD(buffer[3]));
  1302. configuration.bNumInterfaces := ORD(buffer[4]);
  1303. configuration.bConfigurationValue := ORD(buffer[5]);
  1304. configuration.iConfiguration := ORD(buffer[6]);
  1305. configuration.bmAttributes := SYSTEM.VAL(SET, ORD(buffer[7]));
  1306. configuration.bMaxPower := 2*ORD(buffer[8]);
  1307. IF SYSTEM.VAL(SET, ORD(buffer[7])) * {5} # {} THEN configuration.remoteWakeup := TRUE; END;
  1308. IF SYSTEM.VAL(SET, ORD(buffer[7])) * {6} # {} THEN configuration.selfPowered := TRUE; END;
  1309. idx := configuration.bLength; (* idx points to first interface or IAD*)
  1310. NEW(configuration.interfaces, configuration.bNumInterfaces); (* Always > 0 *)
  1311. FOR i := 0 TO configuration.bNumInterfaces-1 DO
  1312. IF idx + 1 >= LEN(buffer) THEN
  1313. IF Debug.Level >= Debug.Errors THEN KernelLog.String("Usb: ParseConfiguration: Buffer too short."); KernelLog.Ln; END;
  1314. RETURN NIL;
  1315. END;
  1316. SkipOthers(DescriptorInterface, buffer, idx);
  1317. IF ORD(buffer[idx+1]) = DescriptorInterface THEN
  1318. intfNbr := ORD(buffer[idx+2]);
  1319. configuration.interfaces[i] := ParseInterfaceDescriptor(buffer, idx);
  1320. IF configuration.interfaces[i] = NIL THEN RETURN NIL; END;
  1321. num := NumAltInterfaces(intfNbr, idx);
  1322. IF Debug.Trace & Debug.traceParsing THEN
  1323. KernelLog.String("Usb: Parsing: "); KernelLog.Int(num, 0); KernelLog.String(" alternate interfaces found."); KernelLog.Ln;
  1324. END;
  1325. IF num # 0 THEN
  1326. configuration.interfaces[i].numAlternateInterfaces := num;
  1327. NEW(configuration.interfaces[i].alternateInterfaces, num);
  1328. FOR j := 0 TO num-1 DO
  1329. configuration.interfaces[i].alternateInterfaces[j] := ParseInterfaceDescriptor(buffer, idx);
  1330. IF configuration.interfaces[i].alternateInterfaces[j] = NIL THEN RETURN NIL; END;
  1331. END;
  1332. END;
  1333. END;
  1334. END;
  1335. RETURN configuration;
  1336. END ParseConfigurationDescriptor;
  1337. (* Skip all descriptors except those with the specified type *)
  1338. PROCEDURE SkipOthers(type : LONGINT; buffer : Usbdi.Buffer; VAR idx : LONGINT);
  1339. BEGIN
  1340. (* Skip non-USB-standard descriptors (e.g. HID descriptors) *)
  1341. WHILE(idx+1 < LEN(buffer)) & (ORD(buffer[idx+1]) # type) (* & (ORD(buffer[idx+1]) # DescriptorIad) *) DO
  1342. IF Debug.Trace & Debug.traceParsing THEN ShowParse("Skip descriptor", idx, ORD(buffer[idx+1]), ORD(buffer[idx+0])); END;
  1343. idx := idx + ORD(buffer[idx+0]);
  1344. END;
  1345. END SkipOthers;
  1346. PROCEDURE ShowParse(CONST string : ARRAY OF CHAR; index, type, length : LONGINT);
  1347. BEGIN
  1348. IF Debug.Trace THEN
  1349. KernelLog.String("Usb: Parsing "); KernelLog.String(string); KernelLog.String(" at index "); KernelLog.Int(index, 0);
  1350. KernelLog.String(" (Type: "); KernelLog.Int(type, 0); KernelLog.String(", Length: "); KernelLog.Int(length, 0); KernelLog.String(")"); KernelLog.Ln;
  1351. END;
  1352. END ShowParse;
  1353. (* Reads StringDescriptors from USBdevice dev if any available *)
  1354. PROCEDURE GetStrings*(dev : UsbDevice);
  1355. VAR
  1356. buffer : Usbdi.BufferPtr;
  1357. langid : LONGINT;
  1358. i, j, k, len : LONGINT;
  1359. configuration : ConfigurationDescriptor;
  1360. interface, altInterface : InterfaceDescriptor;
  1361. PROCEDURE GetString(descriptorIndex, langID : LONGINT) : Lib.UnicodeString;
  1362. VAR unicode : Lib.UnicodeString; size, i, len : LONGINT; res : BOOLEAN;
  1363. BEGIN
  1364. (*First, get the length of the string descriptor to be loaded... *)
  1365. NEW(buffer, 2);
  1366. res := dev.GetDescriptor(DescriptorString, descriptorIndex, langID, 2, buffer^);
  1367. IF (res = TRUE) & (ORD(buffer[1]) = DescriptorString) & (ORD(buffer[0]) > 3) & (ORD(buffer[0]) MOD 2 = 0) THEN
  1368. (* ... and then load the string descriptor *)
  1369. len := ORD(buffer[0]); NEW(buffer, len);
  1370. IF dev.GetDescriptor(DescriptorString, descriptorIndex, langID, len, buffer^) THEN
  1371. (* ORD(buffer[0]) (length in bytes) - 2 (descriptortype and length field) DIV 2 : device delivers 16byte per character *)
  1372. size := ((ORD(buffer[0])-2) DIV 2);
  1373. NEW(unicode, size);
  1374. (* Convert ARRAY OF CHAR to ARRAY OF LONGINT *)
  1375. FOR i:=0 TO size-1 DO
  1376. unicode[i] := ORD(buffer[(2*i)+2])+SYSTEM.VAL(LONGINT, ORD(buffer[(2*i)+3]))*100H;
  1377. END;
  1378. ELSIF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: Couldn't load string descriptor"); KernelLog.Ln;
  1379. END;
  1380. ELSIF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: Couldn't get the first 2 bytes of the string descriptor"); KernelLog.Ln;
  1381. END;
  1382. RETURN unicode;
  1383. END GetString;
  1384. BEGIN
  1385. IF Debug.Trace & Debug.traceParsing THEN KernelLog.String("Usb: Read string descriptors... "); KernelLog.Ln; END;
  1386. IF (dev.descriptor(DeviceDescriptor).iManufacturer=0) & (dev.descriptor(DeviceDescriptor).iProduct=0) & (dev.descriptor(DeviceDescriptor).iSerialNumber=0) THEN (* no string describtors supported *)
  1387. IF Debug.Trace & Debug.traceParsing THEN KernelLog.String("Usb: No String Descriptors provided by this device."); KernelLog.Ln; END;
  1388. ELSE
  1389. (* first get the length of the LANGID code array *)
  1390. NEW(buffer, 2);
  1391. IF ~dev.GetDescriptor(DescriptorString, 0, 0, 2, buffer^) OR (ORD(buffer[1]) # DescriptorString) THEN
  1392. IF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: Couldn't load the first 2 bytes of StringDescriptor"); KernelLog.Ln; END;
  1393. RETURN;
  1394. END;
  1395. (* Get the LANDID code array *)
  1396. len := ORD(buffer[0]); NEW(buffer, len);
  1397. IF ~dev.GetDescriptor(DescriptorString, 0, 0, len, buffer^) OR (ORD(buffer[1]) # DescriptorString) THEN
  1398. IF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: Couldn't load String Descriptor"); KernelLog.Ln; END;
  1399. RETURN;
  1400. END;
  1401. (* Get a preferred LANGID code *)
  1402. IF LangIdSupported(buffer^, IdEnglishUS) THEN langid := IdEnglishUS;
  1403. ELSIF LangIdSupported(buffer^, IdEnglishUK) THEN langid := IdEnglishUK;
  1404. ELSIF LangIdSupported(buffer^, IdSystemDefault) THEN langid := IdSystemDefault;
  1405. ELSIF LangIdSupported(buffer^, IdUserDefault) THEN langid := IdUserDefault;
  1406. ELSIF ORD(buffer[0])-2 > 0 THEN (* at least one other language is supported... use it *)
  1407. langid := ORD(buffer[3]) + 100H*SYSTEM.VAL(LONGINT, ORD(buffer[4]));
  1408. IF Debug.Trace & Debug.traceParsing THEN KernelLog.String("Usb: Used LANGID code for GetString():"); KernelLog.Int(langid, 0); KernelLog.Ln; END;
  1409. ELSE
  1410. IF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: Couldn't load string descriptor (No supported language found)"); KernelLog.Ln; END;
  1411. RETURN;
  1412. END;
  1413. (* Get manufacturer string *)
  1414. IF dev.descriptor(DeviceDescriptor).iManufacturer # 0 THEN
  1415. dev.descriptor(DeviceDescriptor).uManufacturer := GetString(dev.descriptor(DeviceDescriptor).iManufacturer, langid);
  1416. dev.descriptor(DeviceDescriptor).sManufacturer := Lib.Unicode2Ascii(dev.descriptor(DeviceDescriptor).uManufacturer);
  1417. END;
  1418. (* Get product string *)
  1419. IF dev.descriptor(DeviceDescriptor).iProduct # 0 THEN
  1420. dev.descriptor(DeviceDescriptor).uProduct := GetString(dev.descriptor(DeviceDescriptor).iProduct, langid);
  1421. dev.descriptor(DeviceDescriptor).sProduct := Lib.Unicode2Ascii(dev.descriptor(DeviceDescriptor).uProduct);
  1422. END;
  1423. (* Get serial number *)
  1424. IF dev.descriptor(DeviceDescriptor).iSerialNumber # 0 THEN
  1425. dev.descriptor(DeviceDescriptor).uSerialNumber := GetString(dev.descriptor(DeviceDescriptor).iSerialNumber, 0000H); (* 0000H: Language neutral *)
  1426. dev.descriptor(DeviceDescriptor).sSerialNumber := Lib.Unicode2Ascii(dev.descriptor(DeviceDescriptor).uSerialNumber);
  1427. END;
  1428. (* Get string descriptors of the configurations and interfaces if available *)
  1429. FOR i := 0 TO dev.descriptor.bNumConfigurations-1 DO
  1430. configuration := dev.configurations[i] (ConfigurationDescriptor);
  1431. IF configuration.iConfiguration#0 THEN (* device provide configuration description(s) *)
  1432. dev.configurations[i](ConfigurationDescriptor).uConfiguration := GetString(configuration.iConfiguration, langid);
  1433. dev.configurations[i](ConfigurationDescriptor).sConfiguration := Lib.Unicode2Ascii(dev.configurations[i](ConfigurationDescriptor).uConfiguration);
  1434. END;
  1435. FOR j := 0 TO configuration.bNumInterfaces -1 DO
  1436. interface := configuration.interfaces[j] (InterfaceDescriptor);
  1437. IF interface.iInterface#0 THEN (* Device provides interface descriptor(s) *)
  1438. interface.uInterface := GetString(interface.iInterface, langid);
  1439. interface.sInterface := Lib.Unicode2Ascii(interface.uInterface);
  1440. END;
  1441. FOR k := 0 TO interface.numAlternateInterfaces -1 DO
  1442. altInterface := interface.alternateInterfaces[k] (InterfaceDescriptor);
  1443. IF altInterface.iInterface#0 THEN (* Device provides interface descriptor(s) *)
  1444. altInterface.uInterface := GetString(altInterface.iInterface, langid);
  1445. altInterface.sInterface := Lib.Unicode2Ascii(altInterface.uInterface);
  1446. END;
  1447. END;
  1448. END;
  1449. END;
  1450. END;
  1451. END GetStrings;
  1452. (** Returns TRUE if the <langid> is supported, FALSE otherwise *)
  1453. PROCEDURE LangIdSupported(buffer : Usbdi.Buffer; langid : LONGINT): BOOLEAN;
  1454. VAR supported : BOOLEAN; i : LONGINT;
  1455. BEGIN
  1456. (* LANDID code array: buf[0]=length of code array, buf[1]=DecriptorString, buf[2*i]+buf[2*i+1] : LangID codes *)
  1457. IF (ORD(buffer[0]) MOD 2 # 0) OR (ORD(buffer[0]) < 4) THEN RETURN FALSE; END;
  1458. (* Check whether langID is a element of the LANGID code array *)
  1459. FOR i := 2 TO ORD(buffer[0])-2 BY 2 DO
  1460. IF (ORD(buffer[i])+SYSTEM.VAL(LONGINT, ORD(buffer[i+1]))*100H) = langid THEN supported := TRUE; END;
  1461. END;
  1462. RETURN supported;
  1463. END LangIdSupported;
  1464. PROCEDURE ShowState(state : LONGINT);
  1465. BEGIN
  1466. IF Debug.Trace THEN
  1467. CASE state OF
  1468. |StateDisconnected: KernelLog.String("Disconnected");
  1469. |StateAttached: KernelLog.String("Attached");
  1470. |StatePowered: KernelLog.String("Powered");
  1471. |StateDefault: KernelLog.String("Default");
  1472. |StateAddress: KernelLog.String("Address");
  1473. |StateConfigured: KernelLog.String("Configured");
  1474. |StateSuspended: KernelLog.String("Suspended");
  1475. ELSE
  1476. KernelLog.String("Unknown ("); KernelLog.Int(state, 0); KernelLog.String(")");
  1477. END;
  1478. END;
  1479. END ShowState;
  1480. PROCEDURE ShowStateTransition(dev : UsbDevice; newState : LONGINT);
  1481. BEGIN
  1482. IF Debug.Trace THEN
  1483. KernelLog.String("Usb: Device "); dev.ShowName; KernelLog.String(": State transition from ");
  1484. ShowState(dev.state); KernelLog.String(" to "); ShowState(newState); KernelLog.Ln;
  1485. END;
  1486. END ShowStateTransition;
  1487. PROCEDURE GetRootHubs*(VAR rootHubsCopy : RootHubArray);
  1488. VAR i : LONGINT;
  1489. BEGIN {EXCLUSIVE}
  1490. IF rootHubs = NIL THEN rootHubsCopy := NIL; RETURN; END;
  1491. IF (rootHubsCopy = NIL) OR (LEN(rootHubs) # LEN(rootHubsCopy)) THEN
  1492. NEW(rootHubsCopy, LEN(rootHubs));
  1493. END;
  1494. FOR i := 0 TO LEN(rootHubs)-1 DO
  1495. rootHubsCopy[i] := rootHubs[i];
  1496. END;
  1497. END GetRootHubs;
  1498. PROCEDURE RootHubEvent(event : WORD; plugin : Plugins.Plugin);
  1499. VAR hcd : UsbHcdi.Hcd;
  1500. BEGIN
  1501. hcd := plugin(UsbHcdi.Hcd);
  1502. IF event = Plugins.EventAdd THEN
  1503. AddRootHub(hcd);
  1504. ELSIF event = Plugins.EventRemove THEN
  1505. RemoveRootHub(hcd);
  1506. ELSE
  1507. HALT(90);
  1508. END;
  1509. Machine.AtomicInc(nbrOfTopologyEvents);
  1510. END RootHubEvent;
  1511. PROCEDURE AddRootHub(hcd : UsbHcdi.Hcd);
  1512. VAR roothub : EmulatedHubDevice; temp : RootHubArray; i : LONGINT;
  1513. BEGIN {EXCLUSIVE}
  1514. NEW(roothub, hcd);
  1515. IF rootHubs = NIL THEN
  1516. NEW(rootHubs, 1);
  1517. rootHubs[0] := roothub;
  1518. ELSE
  1519. NEW(temp, LEN(rootHubs)+1);
  1520. FOR i := 0 TO LEN(rootHubs)-1 DO
  1521. temp[i] := rootHubs[i];
  1522. END;
  1523. temp[LEN(rootHubs)] := roothub;
  1524. rootHubs := temp;
  1525. END;
  1526. drivers.ProbeDevice(roothub);
  1527. END AddRootHub;
  1528. PROCEDURE RemoveRootHub(hcd : UsbHcdi.Hcd);
  1529. VAR i, j : LONGINT; temp : RootHubArray; roothub : EmulatedHubDevice;
  1530. BEGIN {EXCLUSIVE}
  1531. IF rootHubs # NIL THEN
  1532. IF LEN(rootHubs) > 1 THEN
  1533. NEW(temp, LEN(rootHubs)-1);
  1534. j := 0;
  1535. FOR i := 0 TO LEN(rootHubs)-1 DO
  1536. IF rootHubs[i].controller = hcd THEN
  1537. roothub := rootHubs[i] (EmulatedHubDevice);
  1538. ELSE
  1539. IF j < LEN(temp) THEN temp[j] := rootHubs[i]; END; INC(j);
  1540. END;
  1541. END;
  1542. ELSE
  1543. IF rootHubs[0].controller = hcd THEN
  1544. roothub := rootHubs[0] (EmulatedHubDevice);
  1545. END;
  1546. END;
  1547. IF roothub # NIL THEN (* Found device to be removed *)
  1548. rootHubs := temp;
  1549. roothub.Remove;
  1550. END;
  1551. END;
  1552. END RemoveRootHub;
  1553. PROCEDURE InstallRootHubs;
  1554. VAR table : Plugins.Table; i : LONGINT; res: WORD;
  1555. BEGIN
  1556. UsbHcdi.controllers.AddEventHandler(RootHubEvent, res); (* ignore res *)
  1557. UsbHcdi.controllers.GetAll(table);
  1558. IF table # NIL THEN
  1559. FOR i := 0 TO LEN(table)-1 DO AddRootHub(table[i](UsbHcdi.Hcd)); END;
  1560. END;
  1561. END InstallRootHubs;
  1562. PROCEDURE Cleanup;
  1563. BEGIN {EXCLUSIVE}
  1564. UsbDriverLoader.SetListener(NIL);
  1565. drivers.Terminate;
  1566. Plugins.main.Remove(usbDrivers);
  1567. IF Debug.Verbose THEN KernelLog.Enter; KernelLog.String("Usb: USB driver unloaded."); KernelLog.Exit; END;
  1568. END Cleanup;
  1569. BEGIN
  1570. (* System wide registry for USB device drivers *)
  1571. NEW(usbDrivers, "Usb","USB Device Drivers");
  1572. (* Create internal driver registry *)
  1573. NEW(drivers); Usbdi.drivers := drivers;
  1574. ASSERT(UsbHcdi.StateDisconnected = StateDisconnected);
  1575. Modules.InstallTermHandler(Cleanup);
  1576. InstallRootHubs;
  1577. (* Install a notifier that will be called when the driver lookup service is enabled. *)
  1578. UsbDriverLoader.SetListener(drivers.ProbeDrivers);
  1579. IF Debug.Verbose THEN KernelLog.Enter; KernelLog.String("Usb: USB driver loaded."); KernelLog.Exit; END;
  1580. END Usb.