Usb.Mod 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764
  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. IF controller.isHighSpeed THEN
  605. speed := HighSpeed
  606. ELSE
  607. (* TODO: a way to differentiate full/low speed controllers? *)
  608. speed := FullSpeed
  609. END;
  610. parent := SELF;
  611. hubFlag := TRUE;
  612. nbrOfPorts := controller.portCount;
  613. NEW(deviceAtPort, nbrOfPorts);
  614. NEW(portPermanentDisabled, nbrOfPorts);
  615. NEW(portErrors, nbrOfPorts);
  616. EmulateDescriptors;
  617. END New;
  618. END EmulatedHubDevice;
  619. TYPE
  620. RegisteredDriver* = POINTER TO RECORD
  621. probe : Usbdi.ProbeProc;
  622. name- : Usbdi.Name;
  623. desc- : Usbdi.Description;
  624. usedSuffix- : ARRAY 100 OF BOOLEAN; (* Which numbers are used for the unique names of instances *)
  625. next- : RegisteredDriver;
  626. END;
  627. TYPE
  628. (*
  629. * This object manages USB device drivers. It will be notified by the USB hub driver when devices
  630. * are attached/detached from the bus. If a device is attached, the driver manager calls the probe procedures
  631. * of all USB device drivers which are registered at the driver manager. When a device is detached from the
  632. * bus, the associated driver (if any) will be removed from the UsbDevice object.
  633. *)
  634. DriverManager* = OBJECT(Usbdi.DriverManager)
  635. VAR
  636. (* Driver manager internal USB device driver registy (exported for WMUsbInfo only). *)
  637. drivers- : ARRAY DmMaxPriorities OF RegisteredDriver;
  638. (* Incremented each time a driver is added or removed *)
  639. nbrOfDriverEvents- : LONGINT;
  640. (* local copy of rootHubs, since it could be modified while operating on it *)
  641. rootHubs : RootHubArray;
  642. alive, dead, probeDrivers : BOOLEAN;
  643. (* For each interface of the USB device <dev> try to install a registered driver; called when a new USB device is found *)
  644. PROCEDURE ProbeDevice*(dev : UsbDevice);
  645. VAR n : LONGINT;
  646. BEGIN
  647. FOR n := 0 TO dev.actConfiguration.bNumInterfaces - 1 DO
  648. IF dev.actConfiguration.interfaces[n](InterfaceDescriptor).driver = NIL THEN
  649. (* probe all device drivers and install a driver instance if a driver for the device is registered *)
  650. Install(dev, n);
  651. END;
  652. END;
  653. END ProbeDevice;
  654. (* Load driver using driver database services *)
  655. PROCEDURE ConsultDriverDatabase(dev : UsbDevice) : BOOLEAN;
  656. VAR loaded : BOOLEAN; d : DeviceDescriptor; i : InterfaceDescriptor; intf : LONGINT;
  657. BEGIN
  658. IF (dev # NIL) & (dev.descriptor # NIL) THEN
  659. d := dev.descriptor (DeviceDescriptor);
  660. (* First look for a device-specific driver *)
  661. loaded := UsbDriverLoader.LoadDeviceDriver(d.idVendor, d.idProduct, d.bcdDevice);
  662. (* Look for class-specific driver *)
  663. IF ~((d.bDeviceClass = 0EFH) & (d.bDeviceSubClass = 02H) & (d.bDeviceProtocol = 01H)) & (* IAD -> Search interfaces *)
  664. ((d.bDeviceClass # 0) OR (d.bDeviceSubClass # 0) OR (d.bDeviceProtocol # 0)) THEN (* Class description at device level *)
  665. IF UsbDriverLoader.LoadClassDriver(d.bDeviceClass, d.bDeviceSubClass, d.bDeviceProtocol, d.bcdDevice) THEN
  666. loaded := TRUE;
  667. END;
  668. ELSE (* Class description at interface level *)
  669. IF (dev.actConfiguration # NIL) & (dev.actConfiguration.interfaces # NIL) THEN
  670. intf := 0;
  671. LOOP
  672. i := dev.actConfiguration.interfaces[intf] (InterfaceDescriptor);
  673. (* TODO: Actually, some classes specifiy class-specfic descriptors that may contain the class revision the device supports. Use this instead of bcdDevice *)
  674. IF (i # NIL) & UsbDriverLoader.LoadClassDriver(i.bInterfaceClass, i.bInterfaceSubClass, i.bInterfaceProtocol, d.bcdDevice) THEN
  675. loaded := TRUE;
  676. END;
  677. INC(intf);
  678. IF intf >= LEN(dev.actConfiguration.interfaces) THEN EXIT END;
  679. END;
  680. END;
  681. END;
  682. END;
  683. RETURN loaded;
  684. END ConsultDriverDatabase;
  685. PROCEDURE LookupDriver(dev : UsbDevice; interface : InterfaceDescriptor; VAR temp : RegisteredDriver) : Usbdi.Driver;
  686. VAR drv : Usbdi.Driver; i : LONGINT;
  687. BEGIN
  688. LOOP (* Search all priority lists *)
  689. temp := drivers[i].next;
  690. LOOP (* Search all drivers in priority list i *)
  691. IF temp = NIL THEN (* No more drivers available *) EXIT; END;
  692. drv := temp.probe(dev, interface);
  693. IF drv # NIL THEN (* Driver found *) EXIT; END;
  694. temp := temp.next;
  695. END;
  696. IF drv # NIL THEN (* Driver found *) EXIT; END;
  697. INC(i); IF (i >= DmMaxPriorities) THEN (* No driver available *) EXIT; END;
  698. END;
  699. RETURN drv;
  700. END LookupDriver;
  701. (* Returns FALSE if connect failed or trapped *)
  702. PROCEDURE SafelyConnect(drv : Usbdi.Driver) : BOOLEAN;
  703. VAR connected, trap : BOOLEAN;
  704. BEGIN
  705. connected := drv.Connect();
  706. FINALLY
  707. IF trap & (Debug.Level >= Debug.Warnings) THEN KernelLog.String("Usb: Catched TRAP when calling Driver.Connect."); KernelLog.Ln; END;
  708. RETURN (~trap & connected);
  709. END SafelyConnect;
  710. PROCEDURE SafelyDisconnect(drv : Usbdi.Driver);
  711. VAR trap : BOOLEAN;
  712. BEGIN
  713. drv.Disconnect;
  714. FINALLY
  715. IF trap & (Debug.Level >= Debug.Warnings) THEN KernelLog.String("Usb: Catched TRAP when calling Driver.Disconnect."); KernelLog.Ln; END;
  716. END SafelyDisconnect;
  717. (* Checks whether an appropriate driver for the USB device <dev> is registred in registredDrivers.
  718. * If yes, a unique Plugins.Name is generated and the driver is added to the usbDrivers registry *)
  719. PROCEDURE Install(dev : UsbDevice; interfaceIdx : LONGINT);
  720. VAR
  721. temp : RegisteredDriver;
  722. drv : Usbdi.Driver;
  723. interface : InterfaceDescriptor;
  724. i, res : LONGINT;
  725. name : Usbdi.Name;
  726. suffix : LONGINT; (* 0-99; suffix is used to generate unique names for AosPlugin.Name *)
  727. BEGIN
  728. interface := dev.actConfiguration.interfaces[interfaceIdx] (InterfaceDescriptor);
  729. (* Search an USB device driver for this device (See USB Common Class Specification, 3.10 Locating USB Drivers) *)
  730. (* we have to consult the database first always because of priorities. If a driver has already been loaded previously, this will return FALSE anyway *)
  731. IF ConsultDriverDatabase(dev) THEN
  732. RETURN; (* Appropriate device driver has been loaded from driver database. Loading will force bus enumeration, so don't continue here. *)
  733. ELSE
  734. drv := LookupDriver(dev, interface, temp);
  735. END;
  736. BEGIN {EXCLUSIVE}
  737. (* Since it's possible that two threads (active body, hub driver via ProbeDevice) try to install a driver for the same device and interface,
  738. we need to check here *)
  739. IF (drv # NIL) & (interface.driver = NIL) THEN
  740. (* Driver found; generate a unique name for the instance of this driver to be created *)
  741. drv.device := dev; drv.interface := interface;
  742. (* Get first unused suffix *)
  743. i := 0; WHILE (temp.usedSuffix[i] = TRUE) & (i <= 99) DO INC(i); END;
  744. IF (i = 99) & (temp.usedSuffix[99] = TRUE) THEN
  745. KernelLog.String("Usb: No more than 99 instances of a driver supported"); KernelLog.Ln;
  746. RETURN;
  747. ELSE
  748. temp.usedSuffix[i] := TRUE; suffix := i;
  749. END;
  750. name := AddSuffix(temp.name, suffix);
  751. drv.SetName(name); drv.desc := temp.desc;
  752. (* Add this driver to the usbDrivers registry *)
  753. usbDrivers.Add(drv, res);
  754. IF res # Plugins.Ok THEN
  755. KernelLog.String("Usb: Couldn't register USB device driver (res: "); KernelLog.Int(res, 0); KernelLog.String(")"); KernelLog.Ln;
  756. temp.usedSuffix[suffix] := FALSE;
  757. RETURN;
  758. ELSE (* USB device driver successfully registered *)
  759. interface.driver := drv;
  760. IF ~SafelyConnect(drv) THEN
  761. KernelLog.String("Usb: Connect of driver "); KernelLog.String(drv.name); KernelLog.String("("); KernelLog.String(drv.desc); KernelLog.String(") failed."); KernelLog.Ln;
  762. ASSERT(drv.device(UsbDevice).parent.hubFlag);
  763. ASSERT(drv.device(UsbDevice).parent.portPermanentDisabled # NIL);
  764. (* Don't try to re-install a driver until ConnectStatusChange at this port *)
  765. drv.device(UsbDevice).parent.portPermanentDisabled[drv.device(UsbDevice).port] := TRUE;
  766. drv.device(UsbDevice).Remove;
  767. RETURN;
  768. END;
  769. IF Debug.Trace & Debug.traceDm THEN KernelLog.String("Usb: Registered USB device driver: "); KernelLog.String(name); KernelLog.Ln; END;
  770. END;
  771. END;
  772. END;
  773. END Install;
  774. (* For all USB devices which are attached to any USB root hub in the system the procedure ProbeDeviceChain() is called *)
  775. PROCEDURE ProbeDriversInternal;
  776. VAR i : LONGINT;
  777. BEGIN (* Works with local copy of rootHubs array *)
  778. GetRootHubs(rootHubs);
  779. IF rootHubs # NIL THEN
  780. FOR i := 0 TO LEN(rootHubs)-1 DO
  781. ProbeDeviceChain(rootHubs[i]);
  782. rootHubs[i] := NIL; (* we don't need the reference anymore *)
  783. END;
  784. END;
  785. END ProbeDriversInternal;
  786. (* Called by ProbeDrivers; calls Install() for all devices which don't already have a driver instance installed *)
  787. PROCEDURE ProbeDeviceChain(dev : UsbDevice);
  788. VAR n : LONGINT;
  789. BEGIN
  790. FOR n := 0 TO dev.actConfiguration.bNumInterfaces - 1 DO
  791. IF dev.actConfiguration.interfaces[n](InterfaceDescriptor).driver = NIL THEN
  792. (* Probe all device drivers and install a driver instance if a driver for the device is registered *)
  793. Install(dev, n);
  794. END;
  795. END;
  796. IF dev.hubFlag THEN
  797. FOR n := 0 TO dev.nbrOfPorts - 1 DO
  798. IF dev.deviceAtPort[n] # NIL THEN ProbeDeviceChain(dev.deviceAtPort[n]); END;
  799. END;
  800. END;
  801. END ProbeDeviceChain;
  802. (** Add a USB device driver to the internal registry. Driver names have to be unique and no longer than 30 characters (incl. Null-String) *)
  803. PROCEDURE Add*(probe : Usbdi.ProbeProc; CONST name: Usbdi.Name; CONST desc: Usbdi.Description; priority : LONGINT);
  804. VAR temp, new : RegisteredDriver; i : LONGINT;
  805. BEGIN
  806. (* The specified name mustn't be longer than 30 characters (including 0X) *)
  807. WHILE (name[i] # 0X) & (i < 32) DO INC(i); END;
  808. IF (i > 29) OR (name = "") THEN
  809. KernelLog.String("Usb: Couldn't add driver (name NULL or longer than 30 characters or not NULL-terminated)"); KernelLog.Ln;
  810. RETURN;
  811. END;
  812. (* Specified priority must be in the interval [0,DmMaxPriorities-1] *)
  813. IF (priority > DmMaxPriorities-1) OR (priority < 0) THEN
  814. KernelLog.String("Usb: Couldn't add driver (Priority invalid)"); KernelLog.Ln;
  815. RETURN;
  816. END;
  817. BEGIN {EXCLUSIVE}
  818. (* Check whether there is no driver with the name <name> registered *)
  819. FOR i := 0 TO DmMaxPriorities-1 DO
  820. temp := drivers[i].next;
  821. WHILE temp # NIL DO
  822. IF temp.name = name THEN
  823. KernelLog.String("Usb: Couldn't add driver (driver name already registered)"); KernelLog.Ln;
  824. RETURN;
  825. END;
  826. temp := temp.next;
  827. END;
  828. END;
  829. (* Okay, arguments are valid, create RegisteredDriver object and add it to internal registry *)
  830. NEW(new);
  831. new.probe := probe;
  832. new.name := name;
  833. new.desc := desc;
  834. new.next := drivers[priority].next;
  835. FOR i := 0 TO 99 DO new.usedSuffix[i] := FALSE; END;
  836. drivers[priority].next := new;
  837. END;
  838. IF Debug.Verbose THEN
  839. KernelLog.String("Usb: Driver "); KernelLog.String(name); KernelLog.String(" ("); KernelLog.String(desc); KernelLog.String(")");
  840. KernelLog.String(" has been added."); KernelLog.Ln;
  841. END;
  842. (* Maybe a USB device is already attached, just waiting for this driver: check! *)
  843. ProbeDrivers;
  844. BEGIN {EXCLUSIVE} INC(nbrOfDriverEvents); END;
  845. END Add;
  846. (* Removes a device driver instance from usbDriver registry; only used by the USB driver itself*)
  847. PROCEDURE RemoveInstance(CONST name : Usbdi.Name; dev : UsbDevice);
  848. VAR
  849. plugin : Plugins.Plugin;
  850. driver : Usbdi.Driver;
  851. regname : Plugins.Name;
  852. temp : RegisteredDriver;
  853. i, suffix : LONGINT;
  854. BEGIN
  855. plugin := usbDrivers.Get(name);
  856. IF plugin # NIL THEN (* Uninstall this instance *)
  857. driver := plugin (Usbdi.Driver);
  858. usbDrivers.Remove(plugin);
  859. SafelyDisconnect(driver);
  860. (* Remove allocated pipes *)
  861. driver.device(UsbDevice).controller.FreeAll(driver.device(UsbDevice).address);
  862. (* Get the name of the registered device driver which generates this instances *)
  863. WHILE name[i] # 0X DO regname[i] := name[i]; INC(i); END;
  864. regname[i-1] := 0X; regname[i-2] := 0X;
  865. suffix := GetSuffix(name);
  866. (* Need to update usedSuffix at the registered driver *)
  867. i := 0;
  868. LOOP
  869. temp := drivers[i].next;
  870. WHILE (temp # NIL) & (temp.name # regname) DO temp := temp.next; END;
  871. IF temp # NIL THEN (* Registered device driver found *)
  872. temp.usedSuffix[suffix] := FALSE;
  873. EXIT;
  874. END;
  875. INC(i); IF (i >= DmMaxPriorities) THEN (* No driver found *) EXIT; END;
  876. END;
  877. IF (i = DmMaxPriorities) & (temp = NIL) THEN (* Registered driver for this instance was not found *)
  878. IF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: Couldn't find registered driver of the removed driver instance"); KernelLog.Ln; END;
  879. END;
  880. ELSE (* No such instance found *)
  881. IF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: Warning: Couldn't remove driver instance (no instance found)"); KernelLog.Ln; END;
  882. END;
  883. END RemoveInstance;
  884. (**
  885. * Calls Disconnect of all instances of the driver. All instances are removed from the usbDrivers registry
  886. * and the device driver is removed from the internal registry. *)
  887. PROCEDURE Remove*(CONST name : Plugins.Name);
  888. VAR
  889. prev, temp : RegisteredDriver;
  890. regname : Plugins.Name;
  891. plugin : Plugins.Plugin;
  892. dev : UsbDevice;
  893. i, j : LONGINT;
  894. BEGIN {EXCLUSIVE}
  895. IF Debug.Trace & Debug.traceDm THEN KernelLog.String("Usb: Removing driver: "); KernelLog.String(name); KernelLog.Ln; END;
  896. (* Remove device driver from internal registry *)
  897. LOOP
  898. prev := drivers[i];
  899. temp := drivers[i].next;
  900. WHILE (temp # NIL) & (temp.name # name) DO temp := temp.next; prev := prev.next; END;
  901. IF temp # NIL THEN (* Driver found *) EXIT; END;
  902. INC(i); IF (i >= DmMaxPriorities) THEN (* No driver available *) EXIT; END;
  903. END;
  904. (* Remove driver from internal registry and remove all its instances *)
  905. IF temp # NIL THEN
  906. (* Remove driver from internal registry *)
  907. prev.next := temp.next;
  908. (* Remove all instances of the driver *)
  909. FOR i := 0 TO 99 DO
  910. IF temp.usedSuffix[i] = TRUE THEN (* Driver instance found *)
  911. (* Get plugin name *)
  912. regname := AddSuffix(temp.name, i);
  913. plugin := usbDrivers.Get(regname);
  914. IF plugin = NIL THEN
  915. IF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: Error while trying to remove driver from usbDrivers registry"); KernelLog.Ln; END;
  916. ELSE
  917. SafelyDisconnect(plugin(Usbdi.Driver));
  918. dev := plugin(Usbdi.Driver).device (UsbDevice);
  919. IF dev # NIL THEN (* Remove link to driver instance from USB device *)
  920. IF ~(dev.hubFlag & (dev.parent = dev)) THEN
  921. dev.controller.FreeAll(dev.address);
  922. END;
  923. FOR j := 0 TO dev.actConfiguration.bNumInterfaces-1 DO
  924. IF dev.actConfiguration.interfaces[j](InterfaceDescriptor).driver = plugin(Usbdi.Driver) THEN
  925. dev.actConfiguration.interfaces[j](InterfaceDescriptor).driver := NIL;
  926. END;
  927. END;
  928. END;
  929. usbDrivers.Remove(plugin);
  930. temp.usedSuffix[i]:=FALSE;
  931. END;
  932. END;
  933. END;
  934. INC(nbrOfDriverEvents);
  935. ELSIF Debug.Level >= Debug.Warnings THEN
  936. KernelLog.String("Usb: Warning: Couldn't remove driver "); KernelLog.String(name); KernelLog.Ln;
  937. END;
  938. END Remove;
  939. (* Appends the suffix to name; the suffix is a number between 0-99 which is added as 2 ASCII characters (each 1 bytes)
  940. * note: name mustn't be longer than 30 characters (incl. Null-Termination) *)
  941. PROCEDURE AddSuffix*(CONST name: Plugins.Name; suffix : LONGINT) : Plugins.Name;
  942. VAR i : LONGINT; newName : Plugins.Name;
  943. BEGIN
  944. WHILE name[i]#0X DO newName[i]:=name[i]; INC(i); END;
  945. (* Append suffix to name *)
  946. IF suffix < 10 THEN
  947. newName[i]:="0";
  948. newName[i+1]:=CHR(suffix+48);
  949. newName[i+2]:=0X;
  950. ELSE
  951. newName[i]:=CHR((suffix DIV 10)+48);
  952. newName[i+1]:=CHR((suffix MOD 10)+48);
  953. newName[i+2]:=0X;
  954. END;
  955. RETURN newName;
  956. END AddSuffix;
  957. (* Returns the suffix of the Plugins.Name name *)
  958. PROCEDURE GetSuffix(CONST name : Plugins.Name) : LONGINT;
  959. VAR i, suffix : LONGINT;
  960. BEGIN
  961. WHILE (name[i] # 0X) & (i < 32) DO INC(i); END;
  962. suffix:= (ORD(name[i-2]) - 48) * 10 + ORD(name[i-1])-48;
  963. ASSERT((suffix >= 0) & (suffix <= 99));
  964. RETURN suffix;
  965. END GetSuffix;
  966. (* Displays a list of registered drivers *)
  967. PROCEDURE Show*;
  968. VAR temp : RegisteredDriver; i : LONGINT;
  969. BEGIN
  970. KernelLog.Ln; KernelLog.String("Usb: Registered USB device drivers: "); KernelLog.Ln;
  971. FOR i := 0 TO DmMaxPriorities - 1 DO
  972. temp := drivers[i].next;
  973. WHILE temp # NIL DO
  974. KernelLog.String(" ");
  975. KernelLog.String(temp.name); KernelLog.String(" ("); KernelLog.String(temp.desc); KernelLog.String(")");
  976. KernelLog.String(" Priority: "); KernelLog.Int(i, 0); KernelLog.Ln;
  977. temp := temp.next;
  978. END;
  979. END;
  980. END Show;
  981. PROCEDURE ProbeDrivers;
  982. BEGIN {EXCLUSIVE}
  983. probeDrivers := TRUE;
  984. END ProbeDrivers;
  985. PROCEDURE Terminate;
  986. BEGIN
  987. BEGIN {EXCLUSIVE} alive := FALSE; END;
  988. (* Release object lock to prevent deadlock *)
  989. BEGIN {EXCLUSIVE} AWAIT(dead); END;
  990. END Terminate;
  991. PROCEDURE &Init*;
  992. VAR i : LONGINT; temp : RegisteredDriver;
  993. BEGIN
  994. alive := TRUE; dead := FALSE;
  995. FOR i := 0 TO 11 DO NEW(temp); drivers[i] := temp; END; (* Allocate list heads *)
  996. END Init;
  997. BEGIN {ACTIVE}
  998. (* This thread decouples the process of checking all connected USB devices for matching device drivers from the caller. *)
  999. (* It will be active in the following two situations: *)
  1000. (* - A device driver is successfully registered at the driver manager (Add procedure) *)
  1001. (* - The driver lookup service has been enabled *)
  1002. (* *)
  1003. (* Note: *)
  1004. (* When a device is connected to a bus, the thread of the corresponding hub driver will call ProbeDevice, so different *)
  1005. (* hubs/busses can install device drivers concurrently. To prevent two threads (this one and the hub driver's one) to con-*)
  1006. (* currently install the same device driver to the same function, another check is made in proedure install. *)
  1007. WHILE alive DO
  1008. BEGIN {EXCLUSIVE}
  1009. AWAIT(probeDrivers OR ~alive);
  1010. probeDrivers := FALSE;
  1011. END;
  1012. IF alive THEN (* Check availability of device drivers for all connected devices *)
  1013. IF Debug.Trace & Debug.traceDm THEN
  1014. KernelLog.Enter; KernelLog.String("Usb: Check connected devices for available device drivers"); KernelLog.Exit;
  1015. END;
  1016. ProbeDriversInternal;
  1017. END;
  1018. END;
  1019. IF Debug.Trace & Debug.traceDm THEN KernelLog.Enter; KernelLog.String("Usb: Driver Manager object terminated."); KernelLog.Exit; END;
  1020. BEGIN {EXCLUSIVE} dead := TRUE; END;
  1021. END DriverManager;
  1022. TYPE
  1023. Registry= OBJECT(Plugins.Registry) END Registry;
  1024. VAR
  1025. usbDrivers- : (*Plugins.*)Registry; (* Instanciated USB device drivers (linked to a attached USB device) *)
  1026. drivers- : DriverManager; (* Usb internal registry for installable USB device drivers *)
  1027. rootHubs : RootHubArray;
  1028. nbrOfTopologyEvents- : LONGINT; (* Incremented each time a device is connected/disconnected *)
  1029. PROCEDURE ParseDeviceDescriptor(buffer : Usbdi.Buffer) : DeviceDescriptor;
  1030. VAR descriptor : DeviceDescriptor;
  1031. BEGIN
  1032. IF LEN(buffer) >= 18 THEN
  1033. NEW(descriptor);
  1034. descriptor.bcdUSB := ORD(buffer[2]) + 256*SYSTEM.VAL(LONGINT, ORD(buffer[3]));
  1035. descriptor.bDeviceClass := ORD(buffer[4]);
  1036. descriptor.bDeviceSubClass := ORD(buffer[5]);
  1037. descriptor.bDeviceProtocol := ORD(buffer[6]);
  1038. descriptor.bMaxPacketSize0 := ORD(buffer[7]);
  1039. descriptor.idVendor := ORD(buffer[8]) + 256*SYSTEM.VAL(LONGINT, ORD(buffer[9]));
  1040. descriptor.idProduct := ORD(buffer[10]) + 256*SYSTEM.VAL(LONGINT, ORD(buffer[11]));
  1041. descriptor.bcdDevice := ORD(buffer[12]) + 256*SYSTEM.VAL(LONGINT, ORD(buffer[13]));
  1042. descriptor.iManufacturer := ORD(buffer[14]);
  1043. descriptor.iProduct := ORD(buffer[15]);
  1044. descriptor.iSerialNumber := ORD(buffer[16]);
  1045. descriptor.bNumConfigurations := ORD(buffer[17]);
  1046. ELSIF Debug.Level >= Debug.Errors THEN KernelLog.String("Usb: Could not parse device descriptor."); KernelLog.Ln;
  1047. END;
  1048. RETURN descriptor;
  1049. END ParseDeviceDescriptor;
  1050. (**
  1051. * Parses the USB device qualifier. This descriptor is only available on USB 2.0 devices which can operate as
  1052. * Low-/Fullspeed and Highspeed USB device. It essentially contains the same information as the device descriptor,
  1053. * but the values are for the case that the device would operate at its other operating speed.
  1054. *)
  1055. PROCEDURE ParseDeviceQualifier(buffer : Usbdi.Buffer) : DeviceDescriptor;
  1056. VAR qualifier : DeviceDescriptor;
  1057. BEGIN
  1058. IF LEN(buffer) >= 10 THEN
  1059. NEW(qualifier);
  1060. qualifier.bcdUSB := ORD(buffer[2]) + 256*SYSTEM.VAL(LONGINT, ORD(buffer[3]));
  1061. qualifier.bDeviceClass := ORD(buffer[4]);
  1062. qualifier.bDeviceSubClass := ORD(buffer[5]);
  1063. qualifier.bDeviceProtocol := ORD(buffer[6]);
  1064. qualifier.bMaxPacketSize0 := ORD(buffer[7]);
  1065. qualifier.bNumConfigurations := ORD(buffer[8]);
  1066. ELSIF Debug.Level >= Debug.Errors THEN KernelLog.String("Usb: Could not parse device qualifier."); KernelLog.Ln;
  1067. END;
  1068. RETURN qualifier;
  1069. END ParseDeviceQualifier;
  1070. (** Parse all Interface Association Descriptors in the given configuration. All other descriptor types are skipped. *)
  1071. PROCEDURE ParseInterfaceAssociation(buffer : Usbdi.Buffer) : Usbdi.Iads;
  1072. VAR iads : Usbdi.Iads; iad : InterfaceAssociationDescriptor; idx, num, i : LONGINT;
  1073. BEGIN
  1074. IF Debug.Trace & Debug.traceParsing THEN KernelLog.String("Usb: Parsing interface association descriptors:"); KernelLog.Ln; END;
  1075. (* Determine number of available IADs *)
  1076. WHILE(idx+1 < LEN(buffer)) DO
  1077. IF (ORD(buffer[idx+1]) = DescriptorIad) THEN INC(num); END;
  1078. idx := idx + ORD(buffer[idx+0]);
  1079. END;
  1080. idx := 0;
  1081. IF num > 0 THEN (* Parse the IADs *)
  1082. NEW(iads, num);
  1083. LOOP
  1084. IF idx+8 >= LEN(buffer) THEN EXIT; END;
  1085. IF i >= LEN(iads) THEN EXIT; END;
  1086. IF ORD(buffer[idx+1]) = DescriptorIad THEN
  1087. IF Debug.Trace & Debug.traceParsing THEN ShowParse("interface association", idx, ORD(buffer[idx+1]), ORD(buffer[idx+0])); END;
  1088. NEW(iad);
  1089. iad.bFirstInterface := ORD(buffer[idx+2]);
  1090. iad.bInterfaceCount := ORD(buffer[idx+3]);
  1091. iad.bFunctionClass := ORD(buffer[idx+4]);
  1092. iad.bFunctionSubClass := ORD(buffer[idx+5]);
  1093. iad.bFunctionProtocol := ORD(buffer[idx+6]);
  1094. iad.iFunction := ORD(buffer[idx+7]) + 256*SYSTEM.VAL(LONGINT, ORD(buffer[idx+8]));
  1095. iads[i] := iad;
  1096. INC(i);
  1097. END;
  1098. idx := idx + ORD(buffer[idx+0]);
  1099. END;
  1100. ELSIF Debug.Trace & Debug.traceParsing THEN KernelLog.String("No interface association descriptors found."); KernelLog.Ln;
  1101. END;
  1102. IF i # num THEN (* We didn't find all IADs... we can live without them, but warn the user *)
  1103. IF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: Warning: Error when parsing IADs."); KernelLog.Ln; END;
  1104. RETURN NIL;
  1105. END;
  1106. RETURN iads;
  1107. END ParseInterfaceAssociation;
  1108. (* Parse all non-standard descriptors found in the configuration *)
  1109. PROCEDURE ParseUnknownDescriptors(configuration : Usbdi.ConfigurationDescriptor; buffer : Usbdi.Buffer) : Usbdi.UnknownDescriptor;
  1110. VAR idx, i, type, curIntf, curAltIntf, curEp : LONGINT; list, unknown : Usbdi.UnknownDescriptor;
  1111. PROCEDURE AppendToList(head, unknown : Usbdi.UnknownDescriptor);
  1112. VAR u : Usbdi.UnknownDescriptor;
  1113. BEGIN
  1114. u := head; WHILE(u.next # NIL) DO u := u.next; END;
  1115. u.next := unknown;
  1116. END AppendToList;
  1117. PROCEDURE AppendNonStandard(unknown : Usbdi.UnknownDescriptor) : BOOLEAN;
  1118. VAR i : LONGINT; intf, altIntf : Usbdi.InterfaceDescriptor; endp : Usbdi.EndpointDescriptor;
  1119. BEGIN
  1120. IF (curIntf = -1) THEN (* Append to configuration *)
  1121. IF configuration.unknown = NIL THEN configuration.unknown := unknown;
  1122. ELSE
  1123. AppendToList(configuration.unknown, unknown);
  1124. END;
  1125. ELSE (* Append to interface, alternate interface or endpoint *)
  1126. (* Search Interface *)
  1127. LOOP
  1128. IF (configuration.interfaces=NIL) OR (i >= LEN(configuration.interfaces)) THEN EXIT; END;
  1129. intf := configuration.interfaces[i];
  1130. IF intf.bInterfaceNumber = curIntf THEN EXIT; END;
  1131. INC(i);
  1132. END;
  1133. IF (intf = NIL) OR (intf.bInterfaceNumber # curIntf) THEN RETURN FALSE; END;
  1134. IF curAltIntf # 0 THEN
  1135. (* Search alternate interface *)
  1136. i := 0;
  1137. LOOP
  1138. IF (intf.alternateInterfaces=NIL) OR (i >= LEN(intf.alternateInterfaces)) THEN EXIT; END;
  1139. altIntf := intf.alternateInterfaces[i];
  1140. IF altIntf.bAlternateSetting = curAltIntf THEN EXIT; END;
  1141. INC(i);
  1142. END;
  1143. IF (altIntf = NIL) OR (altIntf.bAlternateSetting # curAltIntf) THEN RETURN FALSE; END;
  1144. intf := altIntf;
  1145. END;
  1146. IF curEp = -1 THEN (* Append to interface *)
  1147. IF intf.unknown = NIL THEN intf.unknown := unknown;
  1148. ELSE
  1149. AppendToList(intf.unknown, unknown);
  1150. END;
  1151. ELSE (* Append to endpoint *)
  1152. (* Search endpoint descriptor *)
  1153. i := 0;
  1154. LOOP
  1155. IF (intf.endpoints = NIL) OR (i >= LEN(intf.endpoints)) THEN EXIT; END;
  1156. endp := intf.endpoints[i];
  1157. IF endp.bEndpointAddress = curEp THEN EXIT; END;
  1158. INC(i);
  1159. END;
  1160. IF (endp = NIL) OR (endp.bEndpointAddress # curEp) THEN RETURN FALSE; END;
  1161. IF endp.unknown = NIL THEN endp.unknown := unknown;
  1162. ELSE
  1163. AppendToList(endp.unknown, unknown);
  1164. END;
  1165. END;
  1166. END;
  1167. RETURN TRUE;
  1168. END AppendNonStandard;
  1169. BEGIN
  1170. ASSERT(configuration # NIL);
  1171. IF Debug.Trace & Debug.traceParsing THEN KernelLog.String("Usb: Parsing non-standard descriptors:"); KernelLog.Ln; END;
  1172. curIntf := -1; curAltIntf := -1; curEp := -1;
  1173. LOOP
  1174. IF idx + 1 >= LEN(buffer) THEN EXIT; END;
  1175. type := ORD(buffer[idx+1]);
  1176. IF type = DescriptorConfiguration THEN
  1177. (* skip *)
  1178. ELSIF type = DescriptorIad THEN
  1179. curIntf := -1; curAltIntf := -1; curEp := -1;
  1180. ELSIF type = DescriptorInterface THEN
  1181. IF idx+3 >= LEN(buffer) THEN EXIT; END;
  1182. curIntf := ORD(buffer[idx+2]);
  1183. curAltIntf := ORD(buffer[idx+3]);
  1184. curEp := -1;
  1185. ELSIF type = DescriptorEndpoint THEN
  1186. IF idx+2 >= LEN(buffer) THEN EXIT; END;
  1187. curEp := ORD(buffer[idx+2]);
  1188. ELSE (* Non-Standard descriptor *)
  1189. NEW(unknown);
  1190. unknown.bLength := ORD(buffer[idx+0]);
  1191. unknown.bDescriptorType := ORD(buffer[idx+1]);
  1192. IF Debug.Trace & Debug.traceParsing THEN ShowParse("unknown descriptor", idx, unknown.bDescriptorType, unknown.bLength); END;
  1193. IF idx + unknown.bLength > LEN(buffer) THEN EXIT; END;
  1194. NEW(unknown.descriptor, unknown.bLength);
  1195. FOR i := 0 TO unknown.bLength-1 DO unknown.descriptor[i] := buffer[idx+i] END;
  1196. IF ~AppendNonStandard(unknown) THEN
  1197. IF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: ParseUnknownDescriptors: Warning: Could not assign non-standard descriptor."); KernelLog.Ln; END;
  1198. RETURN NIL;
  1199. END;
  1200. END;
  1201. idx := idx + ORD(buffer[idx + 0]);
  1202. END;
  1203. IF idx # LEN(buffer) THEN
  1204. IF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: ParseUnknownDescriptors: Warning: Parse Error"); KernelLog.Ln; END;
  1205. list := NIL;
  1206. END;
  1207. RETURN list;
  1208. END ParseUnknownDescriptors;
  1209. (* Parse the first endpoint descriptor found in the configuration beginning at index idx *)
  1210. PROCEDURE ParseEndpointDescriptor(buffer : Usbdi.Buffer; VAR idx : LONGINT) : EndpointDescriptor;
  1211. VAR endpoint : EndpointDescriptor; dword : SET;
  1212. PROCEDURE GetEndpointType(address, attributes : SET) : LONGINT;
  1213. VAR type : LONGINT;
  1214. BEGIN
  1215. IF attributes * {0..1} = {} THEN
  1216. type := Usbdi.Control;
  1217. ELSE
  1218. IF address * {7} = {} THEN (* direction = OUT *)
  1219. IF attributes * {0..1} = {0} THEN type := Usbdi.IsochronousOut;
  1220. ELSIF attributes * {0..1} = {1} THEN type := Usbdi.BulkOut;
  1221. ELSE type := Usbdi.InterruptOut;
  1222. END;
  1223. ELSE (* direction = IN *)
  1224. IF attributes * {0..1} = {0} THEN type := Usbdi.IsochronousIn;
  1225. ELSIF attributes * {0..1} = {1} THEN type := Usbdi.BulkIn;
  1226. ELSE type := Usbdi.InterruptIn;
  1227. END;
  1228. END;
  1229. END;
  1230. RETURN type;
  1231. END GetEndpointType;
  1232. BEGIN
  1233. IF (Debug.Trace & Debug.traceParsing) & (idx+1 < LEN(buffer)) THEN ShowParse("endpoint",idx, ORD(buffer[idx+1]), ORD(buffer[idx+0])); END;
  1234. (* Skip non-USB-standard descriptors (e.g. HID descriptors) *)
  1235. SkipOthers(DescriptorEndpoint, buffer, idx);
  1236. IF idx + 6 >= LEN(buffer) THEN
  1237. IF Debug.Level >= Debug.Errors THEN KernelLog.String("Usb: ParseEndpoint: Buffer too short."); KernelLog.Ln; END;
  1238. RETURN NIL;
  1239. END;
  1240. ASSERT(ORD(buffer[idx+1])=DescriptorEndpoint);
  1241. NEW(endpoint);
  1242. endpoint.bLength := ORD(buffer[idx + 0]);
  1243. endpoint.bEndpointAddress := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, ORD(buffer[idx + 2])) * {0..3, 7});
  1244. endpoint.bmAttributes := SYSTEM.VAL(SET, ORD(buffer[idx + 3]));
  1245. endpoint.type := GetEndpointType(SYSTEM.VAL(SET, endpoint.bEndpointAddress), endpoint.bmAttributes);
  1246. dword := SYSTEM.VAL(SET, ORD(buffer[idx + 4]) + 256*SYSTEM.VAL(LONGINT, ORD(buffer[idx + 5])));
  1247. endpoint.wMaxPacketSize := SYSTEM.VAL(LONGINT, dword * {0..10});
  1248. endpoint.mult := LSH(SYSTEM.VAL(LONGINT, dword * {11..12}), -11) + 1;
  1249. endpoint.bInterval := ORD(buffer[idx + 6]);
  1250. idx := idx + ORD(buffer[idx + 0]);
  1251. RETURN endpoint;
  1252. END ParseEndpointDescriptor;
  1253. (* Parse the first interface descriptor beginning at index idx including its endpoints *)
  1254. PROCEDURE ParseInterfaceDescriptor(buffer :Usbdi.Buffer; VAR idx : LONGINT) : InterfaceDescriptor;
  1255. VAR interface : InterfaceDescriptor; e : LONGINT;
  1256. BEGIN
  1257. IF (Debug.Trace & Debug.traceParsing) & (idx+1 < LEN(buffer)) THEN ShowParse("interface",idx, ORD(buffer[idx+1]), ORD(buffer[idx+0])); END;
  1258. (* Skip non-USB-standard descriptors (e.g. HID descriptors) *)
  1259. SkipOthers(DescriptorInterface, buffer, idx);
  1260. IF idx + 8 >= LEN(buffer) THEN
  1261. IF Debug.Level >= Debug.Errors THEN KernelLog.String("Usb: ParseInterface: Buffer too short."); KernelLog.Ln; END;
  1262. RETURN NIL;
  1263. END;
  1264. ASSERT(ORD(buffer[idx + 1])=DescriptorInterface);
  1265. NEW(interface);
  1266. interface.bLength := ORD(buffer[idx + 0]);
  1267. interface.bInterfaceNumber := ORD(buffer[idx + 2]);
  1268. interface.bAlternateSetting := ORD(buffer[idx + 3]);
  1269. interface.bNumEndpoints := ORD(buffer[idx + 4]);
  1270. interface.bInterfaceClass := ORD(buffer[idx + 5]);
  1271. interface.bInterfaceSubClass := ORD(buffer[idx + 6]);
  1272. interface.bInterfaceProtocol := ORD(buffer[idx + 7]);
  1273. interface.iInterface := ORD(buffer[idx + 8]);
  1274. idx := idx + ORD(buffer[idx + 0]);
  1275. (* Interface can have zero endpoints (only containing endpoint 0) *)
  1276. IF (interface.bNumEndpoints > 0) THEN
  1277. NEW(interface.endpoints, interface.bNumEndpoints);
  1278. FOR e := 0 TO interface.bNumEndpoints-1 DO
  1279. interface.endpoints[e] := ParseEndpointDescriptor(buffer, idx);
  1280. IF interface.endpoints[e] = NIL THEN RETURN NIL; END;
  1281. END;
  1282. END;
  1283. RETURN interface;
  1284. END ParseInterfaceDescriptor;
  1285. (* Parse the configuration descriptor including all standard interfaces, alternate interfaces and endpoints. *)
  1286. PROCEDURE ParseConfigurationDescriptor(buffer : Usbdi.Buffer) : ConfigurationDescriptor;
  1287. VAR configuration : ConfigurationDescriptor; i, j, idx, num, intfNbr : LONGINT;
  1288. (* Return the number of alternate interfaces of interface <intf> starting at idx *)
  1289. PROCEDURE NumAltInterfaces(intf, idx : LONGINT) : LONGINT;
  1290. VAR res : LONGINT;
  1291. BEGIN
  1292. WHILE(idx + 3 < LEN(buffer)) DO
  1293. IF (ORD(buffer[idx+1]) = DescriptorInterface) & (ORD(buffer[idx+2]) = intf) & (ORD(buffer[idx+3]) # 0) THEN
  1294. INC(res);
  1295. END;
  1296. idx := idx + ORD(buffer[idx+0]);
  1297. END;
  1298. RETURN res;
  1299. END NumAltInterfaces;
  1300. BEGIN
  1301. IF Debug.Trace & Debug.traceParsing THEN
  1302. ShowParse("configuration",idx, ORD(buffer[idx+1]), ORD(buffer[idx+0]));
  1303. KernelLog.String("Usb: Total Length of configuration: "); KernelLog.Int(LEN(buffer), 0); KernelLog.Ln;
  1304. END;
  1305. NEW(configuration);
  1306. configuration.bLength := ORD(buffer[0]);
  1307. configuration.wTotalLength := ORD(buffer[2])+ 256*SYSTEM.VAL(LONGINT, ORD(buffer[3]));
  1308. configuration.bNumInterfaces := ORD(buffer[4]);
  1309. configuration.bConfigurationValue := ORD(buffer[5]);
  1310. configuration.iConfiguration := ORD(buffer[6]);
  1311. configuration.bmAttributes := SYSTEM.VAL(SET, ORD(buffer[7]));
  1312. configuration.bMaxPower := 2*ORD(buffer[8]);
  1313. IF SYSTEM.VAL(SET, ORD(buffer[7])) * {5} # {} THEN configuration.remoteWakeup := TRUE; END;
  1314. IF SYSTEM.VAL(SET, ORD(buffer[7])) * {6} # {} THEN configuration.selfPowered := TRUE; END;
  1315. idx := configuration.bLength; (* idx points to first interface or IAD*)
  1316. NEW(configuration.interfaces, configuration.bNumInterfaces); (* Always > 0 *)
  1317. FOR i := 0 TO configuration.bNumInterfaces-1 DO
  1318. IF idx + 1 >= LEN(buffer) THEN
  1319. IF Debug.Level >= Debug.Errors THEN KernelLog.String("Usb: ParseConfiguration: Buffer too short."); KernelLog.Ln; END;
  1320. RETURN NIL;
  1321. END;
  1322. SkipOthers(DescriptorInterface, buffer, idx);
  1323. IF ORD(buffer[idx+1]) = DescriptorInterface THEN
  1324. intfNbr := ORD(buffer[idx+2]);
  1325. configuration.interfaces[i] := ParseInterfaceDescriptor(buffer, idx);
  1326. IF configuration.interfaces[i] = NIL THEN RETURN NIL; END;
  1327. num := NumAltInterfaces(intfNbr, idx);
  1328. IF Debug.Trace & Debug.traceParsing THEN
  1329. KernelLog.String("Usb: Parsing: "); KernelLog.Int(num, 0); KernelLog.String(" alternate interfaces found."); KernelLog.Ln;
  1330. END;
  1331. IF num # 0 THEN
  1332. configuration.interfaces[i].numAlternateInterfaces := num;
  1333. NEW(configuration.interfaces[i].alternateInterfaces, num);
  1334. FOR j := 0 TO num-1 DO
  1335. configuration.interfaces[i].alternateInterfaces[j] := ParseInterfaceDescriptor(buffer, idx);
  1336. IF configuration.interfaces[i].alternateInterfaces[j] = NIL THEN RETURN NIL; END;
  1337. END;
  1338. END;
  1339. END;
  1340. END;
  1341. RETURN configuration;
  1342. END ParseConfigurationDescriptor;
  1343. (* Skip all descriptors except those with the specified type *)
  1344. PROCEDURE SkipOthers(type : LONGINT; buffer : Usbdi.Buffer; VAR idx : LONGINT);
  1345. BEGIN
  1346. (* Skip non-USB-standard descriptors (e.g. HID descriptors) *)
  1347. WHILE(idx+1 < LEN(buffer)) & (ORD(buffer[idx+1]) # type) (* & (ORD(buffer[idx+1]) # DescriptorIad) *) DO
  1348. IF Debug.Trace & Debug.traceParsing THEN ShowParse("Skip descriptor", idx, ORD(buffer[idx+1]), ORD(buffer[idx+0])); END;
  1349. idx := idx + ORD(buffer[idx+0]);
  1350. END;
  1351. END SkipOthers;
  1352. PROCEDURE ShowParse(CONST string : ARRAY OF CHAR; index, type, length : LONGINT);
  1353. BEGIN
  1354. IF Debug.Trace THEN
  1355. KernelLog.String("Usb: Parsing "); KernelLog.String(string); KernelLog.String(" at index "); KernelLog.Int(index, 0);
  1356. KernelLog.String(" (Type: "); KernelLog.Int(type, 0); KernelLog.String(", Length: "); KernelLog.Int(length, 0); KernelLog.String(")"); KernelLog.Ln;
  1357. END;
  1358. END ShowParse;
  1359. (* Reads StringDescriptors from USBdevice dev if any available *)
  1360. PROCEDURE GetStrings*(dev : UsbDevice);
  1361. VAR
  1362. buffer : Usbdi.BufferPtr;
  1363. langid : LONGINT;
  1364. i, j, k, len : LONGINT;
  1365. configuration : ConfigurationDescriptor;
  1366. interface, altInterface : InterfaceDescriptor;
  1367. PROCEDURE GetString(descriptorIndex, langID : LONGINT) : Lib.UnicodeString;
  1368. VAR unicode : Lib.UnicodeString; size, i, len : LONGINT; res : BOOLEAN;
  1369. BEGIN
  1370. (*First, get the length of the string descriptor to be loaded... *)
  1371. NEW(buffer, 2);
  1372. res := dev.GetDescriptor(DescriptorString, descriptorIndex, langID, 2, buffer);
  1373. IF (res = TRUE) & (ORD(buffer[1]) = DescriptorString) & (ORD(buffer[0]) > 3) & (ORD(buffer[0]) MOD 2 = 0) THEN
  1374. (* ... and then load the string descriptor *)
  1375. len := ORD(buffer[0]); NEW(buffer, len);
  1376. IF dev.GetDescriptor(DescriptorString, descriptorIndex, langID, len, buffer) THEN
  1377. (* ORD(buffer[0]) (length in bytes) - 2 (descriptortype and length field) DIV 2 : device delivers 16byte per character *)
  1378. size := ((ORD(buffer[0])-2) DIV 2);
  1379. NEW(unicode, size);
  1380. (* Convert ARRAY OF CHAR to ARRAY OF LONGINT *)
  1381. FOR i:=0 TO size-1 DO
  1382. unicode[i] := ORD(buffer[(2*i)+2])+SYSTEM.VAL(LONGINT, ORD(buffer[(2*i)+3]))*100H;
  1383. END;
  1384. ELSIF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: Couldn't load string descriptor"); KernelLog.Ln;
  1385. END;
  1386. ELSIF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: Couldn't get the first 2 bytes of the string descriptor"); KernelLog.Ln;
  1387. END;
  1388. RETURN unicode;
  1389. END GetString;
  1390. BEGIN
  1391. IF Debug.Trace & Debug.traceParsing THEN KernelLog.String("Usb: Read string descriptors... "); KernelLog.Ln; END;
  1392. IF (dev.descriptor(DeviceDescriptor).iManufacturer=0) & (dev.descriptor(DeviceDescriptor).iProduct=0) & (dev.descriptor(DeviceDescriptor).iSerialNumber=0) THEN (* no string describtors supported *)
  1393. IF Debug.Trace & Debug.traceParsing THEN KernelLog.String("Usb: No String Descriptors provided by this device."); KernelLog.Ln; END;
  1394. ELSE
  1395. (* first get the length of the LANGID code array *)
  1396. NEW(buffer, 2);
  1397. IF ~dev.GetDescriptor(DescriptorString, 0, 0, 2, buffer) OR (ORD(buffer[1]) # DescriptorString) THEN
  1398. IF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: Couldn't load the first 2 bytes of StringDescriptor"); KernelLog.Ln; END;
  1399. RETURN;
  1400. END;
  1401. (* Get the LANDID code array *)
  1402. len := ORD(buffer[0]); NEW(buffer, len);
  1403. IF ~dev.GetDescriptor(DescriptorString, 0, 0, len, buffer) OR (ORD(buffer[1]) # DescriptorString) THEN
  1404. IF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: Couldn't load String Descriptor"); KernelLog.Ln; END;
  1405. RETURN;
  1406. END;
  1407. (* Get a preferred LANGID code *)
  1408. IF LangIdSupported(buffer, IdEnglishUS) THEN langid := IdEnglishUS;
  1409. ELSIF LangIdSupported(buffer, IdEnglishUK) THEN langid := IdEnglishUK;
  1410. ELSIF LangIdSupported(buffer, IdSystemDefault) THEN langid := IdSystemDefault;
  1411. ELSIF LangIdSupported(buffer, IdUserDefault) THEN langid := IdUserDefault;
  1412. ELSIF ORD(buffer[0])-2 > 0 THEN (* at least one other language is supported... use it *)
  1413. langid := ORD(buffer[3]) + 100H*SYSTEM.VAL(LONGINT, ORD(buffer[4]));
  1414. IF Debug.Trace & Debug.traceParsing THEN KernelLog.String("Usb: Used LANGID code for GetString():"); KernelLog.Int(langid, 0); KernelLog.Ln; END;
  1415. ELSE
  1416. IF Debug.Level >= Debug.Warnings THEN KernelLog.String("Usb: Couldn't load string descriptor (No supported language found)"); KernelLog.Ln; END;
  1417. RETURN;
  1418. END;
  1419. (* Get manufacturer string *)
  1420. IF dev.descriptor(DeviceDescriptor).iManufacturer # 0 THEN
  1421. dev.descriptor(DeviceDescriptor).uManufacturer := GetString(dev.descriptor(DeviceDescriptor).iManufacturer, langid);
  1422. dev.descriptor(DeviceDescriptor).sManufacturer := Lib.Unicode2Ascii(dev.descriptor(DeviceDescriptor).uManufacturer);
  1423. END;
  1424. (* Get product string *)
  1425. IF dev.descriptor(DeviceDescriptor).iProduct # 0 THEN
  1426. dev.descriptor(DeviceDescriptor).uProduct := GetString(dev.descriptor(DeviceDescriptor).iProduct, langid);
  1427. dev.descriptor(DeviceDescriptor).sProduct := Lib.Unicode2Ascii(dev.descriptor(DeviceDescriptor).uProduct);
  1428. END;
  1429. (* Get serial number *)
  1430. IF dev.descriptor(DeviceDescriptor).iSerialNumber # 0 THEN
  1431. dev.descriptor(DeviceDescriptor).uSerialNumber := GetString(dev.descriptor(DeviceDescriptor).iSerialNumber, 0000H); (* 0000H: Language neutral *)
  1432. dev.descriptor(DeviceDescriptor).sSerialNumber := Lib.Unicode2Ascii(dev.descriptor(DeviceDescriptor).uSerialNumber);
  1433. END;
  1434. (* Get string descriptors of the configurations and interfaces if available *)
  1435. FOR i := 0 TO dev.descriptor.bNumConfigurations-1 DO
  1436. configuration := dev.configurations[i] (ConfigurationDescriptor);
  1437. IF configuration.iConfiguration#0 THEN (* device provide configuration description(s) *)
  1438. dev.configurations[i](ConfigurationDescriptor).uConfiguration := GetString(configuration.iConfiguration, langid);
  1439. dev.configurations[i](ConfigurationDescriptor).sConfiguration := Lib.Unicode2Ascii(dev.configurations[i](ConfigurationDescriptor).uConfiguration);
  1440. END;
  1441. FOR j := 0 TO configuration.bNumInterfaces -1 DO
  1442. interface := configuration.interfaces[j] (InterfaceDescriptor);
  1443. IF interface.iInterface#0 THEN (* Device provides interface descriptor(s) *)
  1444. interface.uInterface := GetString(interface.iInterface, langid);
  1445. interface.sInterface := Lib.Unicode2Ascii(interface.uInterface);
  1446. END;
  1447. FOR k := 0 TO interface.numAlternateInterfaces -1 DO
  1448. altInterface := interface.alternateInterfaces[k] (InterfaceDescriptor);
  1449. IF altInterface.iInterface#0 THEN (* Device provides interface descriptor(s) *)
  1450. altInterface.uInterface := GetString(altInterface.iInterface, langid);
  1451. altInterface.sInterface := Lib.Unicode2Ascii(altInterface.uInterface);
  1452. END;
  1453. END;
  1454. END;
  1455. END;
  1456. END;
  1457. END GetStrings;
  1458. (** Returns TRUE if the <langid> is supported, FALSE otherwise *)
  1459. PROCEDURE LangIdSupported(buffer : Usbdi.Buffer; langid : LONGINT): BOOLEAN;
  1460. VAR supported : BOOLEAN; i : LONGINT;
  1461. BEGIN
  1462. (* LANDID code array: buf[0]=length of code array, buf[1]=DecriptorString, buf[2*i]+buf[2*i+1] : LangID codes *)
  1463. IF (ORD(buffer[0]) MOD 2 # 0) OR (ORD(buffer[0]) < 4) THEN RETURN FALSE; END;
  1464. (* Check whether langID is a element of the LANGID code array *)
  1465. FOR i := 2 TO ORD(buffer[0])-2 BY 2 DO
  1466. IF (ORD(buffer[i])+SYSTEM.VAL(LONGINT, ORD(buffer[i+1]))*100H) = langid THEN supported := TRUE; END;
  1467. END;
  1468. RETURN supported;
  1469. END LangIdSupported;
  1470. PROCEDURE ShowState(state : LONGINT);
  1471. BEGIN
  1472. IF Debug.Trace THEN
  1473. CASE state OF
  1474. |StateDisconnected: KernelLog.String("Disconnected");
  1475. |StateAttached: KernelLog.String("Attached");
  1476. |StatePowered: KernelLog.String("Powered");
  1477. |StateDefault: KernelLog.String("Default");
  1478. |StateAddress: KernelLog.String("Address");
  1479. |StateConfigured: KernelLog.String("Configured");
  1480. |StateSuspended: KernelLog.String("Suspended");
  1481. ELSE
  1482. KernelLog.String("Unknown ("); KernelLog.Int(state, 0); KernelLog.String(")");
  1483. END;
  1484. END;
  1485. END ShowState;
  1486. PROCEDURE ShowStateTransition(dev : UsbDevice; newState : LONGINT);
  1487. BEGIN
  1488. IF Debug.Trace THEN
  1489. KernelLog.String("Usb: Device "); dev.ShowName; KernelLog.String(": State transition from ");
  1490. ShowState(dev.state); KernelLog.String(" to "); ShowState(newState); KernelLog.Ln;
  1491. END;
  1492. END ShowStateTransition;
  1493. PROCEDURE GetRootHubs*(VAR rootHubsCopy : RootHubArray);
  1494. VAR i : LONGINT;
  1495. BEGIN {EXCLUSIVE}
  1496. IF rootHubs = NIL THEN rootHubsCopy := NIL; RETURN; END;
  1497. IF (rootHubsCopy = NIL) OR (LEN(rootHubs) # LEN(rootHubsCopy)) THEN
  1498. NEW(rootHubsCopy, LEN(rootHubs));
  1499. END;
  1500. FOR i := 0 TO LEN(rootHubs)-1 DO
  1501. rootHubsCopy[i] := rootHubs[i];
  1502. END;
  1503. END GetRootHubs;
  1504. PROCEDURE RootHubEvent(event : LONGINT; plugin : Plugins.Plugin);
  1505. VAR hcd : UsbHcdi.Hcd;
  1506. BEGIN
  1507. hcd := plugin(UsbHcdi.Hcd);
  1508. IF event = Plugins.EventAdd THEN
  1509. AddRootHub(hcd);
  1510. ELSIF event = Plugins.EventRemove THEN
  1511. RemoveRootHub(hcd);
  1512. ELSE
  1513. HALT(90);
  1514. END;
  1515. Machine.AtomicInc(nbrOfTopologyEvents);
  1516. END RootHubEvent;
  1517. PROCEDURE AddRootHub(hcd : UsbHcdi.Hcd);
  1518. VAR roothub : EmulatedHubDevice; temp : RootHubArray; i : LONGINT;
  1519. BEGIN {EXCLUSIVE}
  1520. NEW(roothub, hcd);
  1521. IF rootHubs = NIL THEN
  1522. NEW(rootHubs, 1);
  1523. rootHubs[0] := roothub;
  1524. ELSE
  1525. NEW(temp, LEN(rootHubs)+1);
  1526. FOR i := 0 TO LEN(rootHubs)-1 DO
  1527. temp[i] := rootHubs[i];
  1528. END;
  1529. temp[LEN(rootHubs)] := roothub;
  1530. rootHubs := temp;
  1531. END;
  1532. drivers.ProbeDevice(roothub);
  1533. END AddRootHub;
  1534. PROCEDURE RemoveRootHub(hcd : UsbHcdi.Hcd);
  1535. VAR i, j : LONGINT; temp : RootHubArray; roothub : EmulatedHubDevice;
  1536. BEGIN {EXCLUSIVE}
  1537. IF rootHubs # NIL THEN
  1538. IF LEN(rootHubs) > 1 THEN
  1539. NEW(temp, LEN(rootHubs)-1);
  1540. j := 0;
  1541. FOR i := 0 TO LEN(rootHubs)-1 DO
  1542. IF rootHubs[i].controller = hcd THEN
  1543. roothub := rootHubs[i] (EmulatedHubDevice);
  1544. ELSE
  1545. IF j < LEN(temp) THEN temp[j] := rootHubs[i]; END; INC(j);
  1546. END;
  1547. END;
  1548. ELSE
  1549. IF rootHubs[0].controller = hcd THEN
  1550. roothub := rootHubs[0] (EmulatedHubDevice);
  1551. END;
  1552. END;
  1553. IF roothub # NIL THEN (* Found device to be removed *)
  1554. rootHubs := temp;
  1555. roothub.Remove;
  1556. END;
  1557. END;
  1558. END RemoveRootHub;
  1559. PROCEDURE InstallRootHubs;
  1560. VAR table : Plugins.Table; i : LONGINT;
  1561. BEGIN
  1562. UsbHcdi.controllers.AddEventHandler(RootHubEvent, i); (* ignore res *)
  1563. UsbHcdi.controllers.GetAll(table);
  1564. IF table # NIL THEN
  1565. FOR i := 0 TO LEN(table)-1 DO AddRootHub(table[i](UsbHcdi.Hcd)); END;
  1566. END;
  1567. END InstallRootHubs;
  1568. PROCEDURE Cleanup;
  1569. BEGIN {EXCLUSIVE}
  1570. UsbDriverLoader.SetListener(NIL);
  1571. drivers.Terminate;
  1572. Plugins.main.Remove(usbDrivers);
  1573. IF Debug.Verbose THEN KernelLog.Enter; KernelLog.String("Usb: USB driver unloaded."); KernelLog.Exit; END;
  1574. END Cleanup;
  1575. BEGIN
  1576. (* System wide registry for USB device drivers *)
  1577. NEW(usbDrivers, "Usb","USB Device Drivers");
  1578. (* Create internal driver registry *)
  1579. NEW(drivers); Usbdi.drivers := drivers;
  1580. ASSERT(UsbHcdi.StateDisconnected = StateDisconnected);
  1581. Modules.InstallTermHandler(Cleanup);
  1582. InstallRootHubs;
  1583. (* Install a notifier that will be called when the driver lookup service is enabled. *)
  1584. UsbDriverLoader.SetListener(drivers.ProbeDrivers);
  1585. IF Debug.Verbose THEN KernelLog.Enter; KernelLog.String("Usb: USB driver loaded."); KernelLog.Exit; END;
  1586. END Usb.