Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

301 lines
8.9 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. TOOLS.C
  5. Abstract:
  6. This module contains the tools for the
  7. helper lib that talks to the generic USB driver
  8. Environment:
  9. Kernel & user mode
  10. Revision History:
  11. Sept-01 : created by Kenneth Ray
  12. --*/
  13. #include <stdlib.h>
  14. #include <wtypes.h>
  15. #include <winioctl.h>
  16. #include <assert.h>
  17. #include <initguid.h>
  18. #include "genusbio.h"
  19. #include "umgusb.h"
  20. PUSB_COMMON_DESCRIPTOR __stdcall
  21. GenUSB_ParseDescriptor(
  22. IN PVOID DescriptorBuffer,
  23. IN ULONG TotalLength,
  24. IN PVOID StartPosition,
  25. IN LONG DescriptorType
  26. )
  27. /*++
  28. Routine Description:
  29. Parses a group of standard USB configuration descriptors (returned
  30. from a device) for a specific descriptor type.
  31. Arguments:
  32. DescriptorBuffer - pointer to a block of contiguous USB desscriptors
  33. TotalLength - size in bytes of the Descriptor buffer
  34. StartPosition - starting position in the buffer to begin parsing,
  35. this must point to the begining of a USB descriptor.
  36. DescriptorType - USB descritor type to locate.
  37. Return Value:
  38. pointer to a usb descriptor with a DescriptorType field matching the
  39. input parameter or NULL if not found.
  40. --*/
  41. {
  42. PUCHAR pch;
  43. PUCHAR end;
  44. PUSB_COMMON_DESCRIPTOR usbDescriptor;
  45. PUSB_COMMON_DESCRIPTOR foundUsbDescriptor;
  46. pch = (PUCHAR) StartPosition;
  47. end = ((PUCHAR) (DescriptorBuffer)) + TotalLength;
  48. foundUsbDescriptor = NULL;
  49. while (pch < end)
  50. {
  51. // see if we are pointing at the right descriptor
  52. // if not skip over the other junk
  53. usbDescriptor = (PUSB_COMMON_DESCRIPTOR) pch;
  54. if ((0 == DescriptorType) ||
  55. (usbDescriptor->bDescriptorType == DescriptorType))
  56. {
  57. foundUsbDescriptor = usbDescriptor;
  58. break;
  59. }
  60. // catch the evil case which will keep us looping forever.
  61. if (usbDescriptor->bLength == 0)
  62. {
  63. break;
  64. }
  65. pch += usbDescriptor->bLength;
  66. }
  67. return foundUsbDescriptor;
  68. }
  69. PGENUSB_CONFIGURATION_INFORMATION_ARRAY __stdcall
  70. GenUSB_ParseDescriptorsToArray(
  71. IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor
  72. )
  73. {
  74. UCHAR numberInterfaces;
  75. UCHAR numberOtherDescriptors;
  76. UCHAR numberEndpointDescriptors;
  77. ULONG size;
  78. PCHAR buffer;
  79. PCHAR bufferEnd;
  80. PVOID end;
  81. PUSB_COMMON_DESCRIPTOR current;
  82. PGENUSB_INTERFACE_DESCRIPTOR_ARRAY interfaceArray;
  83. PGENUSB_CONFIGURATION_INFORMATION_ARRAY configArray;
  84. PUSB_ENDPOINT_DESCRIPTOR * endpointArray;
  85. PUSB_COMMON_DESCRIPTOR * otherArray;
  86. //
  87. // Create a flat memory structure that will hold this array of arrays
  88. // to descriptors
  89. //
  90. numberInterfaces = 0;
  91. numberEndpointDescriptors = 0;
  92. numberOtherDescriptors = 0;
  93. //
  94. // Walk the list first to count the number of descriptors in this
  95. // Configuration descriptor.
  96. //
  97. current = (PUSB_COMMON_DESCRIPTOR) ConfigDescriptor;
  98. end = (PVOID) ((PCHAR) current + ConfigDescriptor->wTotalLength);
  99. size = 0;
  100. for ( ;(PVOID)current < end; (PUCHAR) current += current->bLength)
  101. {
  102. current = GenUSB_ParseDescriptor (ConfigDescriptor,
  103. ConfigDescriptor->wTotalLength,
  104. current,
  105. 0); // the very next one.
  106. if (NULL == current)
  107. {
  108. //
  109. // There's a problem with this config descriptor
  110. // Throw up our hands
  111. //
  112. return NULL;
  113. }
  114. if (0 == current->bLength)
  115. {
  116. //
  117. // There's a problem with this config descriptor
  118. // Throw up our hands
  119. //
  120. return NULL;
  121. }
  122. if (USB_CONFIGURATION_DESCRIPTOR_TYPE == current->bDescriptorType)
  123. { // Skip this one.
  124. ;
  125. }
  126. else if (USB_INTERFACE_DESCRIPTOR_TYPE == current->bDescriptorType)
  127. {
  128. numberInterfaces++;
  129. }
  130. else if (USB_ENDPOINT_DESCRIPTOR_TYPE == current->bDescriptorType)
  131. {
  132. numberEndpointDescriptors++;
  133. size += ROUND_TO_PTR (current->bLength);
  134. }
  135. else
  136. {
  137. numberOtherDescriptors++;
  138. size += ROUND_TO_PTR (current->bLength);
  139. }
  140. }
  141. if (0 == numberInterfaces)
  142. {
  143. //
  144. // There's a problem with this config descriptor
  145. // Throw up our hands
  146. //
  147. return NULL;
  148. }
  149. // size now has room for all of the descriptor data, no make room for headers
  150. size += sizeof (GENUSB_CONFIGURATION_INFORMATION_ARRAY) // Global structure
  151. // the interfaces structures
  152. + (sizeof (GENUSB_INTERFACE_DESCRIPTOR_ARRAY) * numberInterfaces)
  153. // array of pointers to the endpoint descriptors
  154. + (sizeof (PVOID) * numberEndpointDescriptors)
  155. // array of pointers to the other descriptors
  156. + (sizeof (PVOID) * numberOtherDescriptors);
  157. configArray = malloc (size);
  158. if (NULL == configArray)
  159. {
  160. return configArray;
  161. }
  162. ZeroMemory (configArray, size);
  163. bufferEnd = (PCHAR) configArray + size;
  164. //
  165. // Fill in the top array
  166. //
  167. configArray->NumberInterfaces = numberInterfaces;
  168. buffer = (PCHAR) configArray
  169. + sizeof (GENUSB_CONFIGURATION_INFORMATION_ARRAY)
  170. + sizeof (GENUSB_INTERFACE_DESCRIPTOR_ARRAY) * numberInterfaces;
  171. endpointArray = (PUSB_ENDPOINT_DESCRIPTOR *) buffer;
  172. buffer += sizeof (PVOID) * numberEndpointDescriptors;
  173. otherArray = (PUSB_COMMON_DESCRIPTOR *) buffer;
  174. //
  175. // Walk the array again putting the data into our arrays.
  176. //
  177. current = (PUSB_COMMON_DESCRIPTOR) ConfigDescriptor;
  178. numberInterfaces = 0;
  179. interfaceArray = NULL;
  180. for ( ;(PVOID)current < end; (PUCHAR) current += current->bLength)
  181. {
  182. current = GenUSB_ParseDescriptor (ConfigDescriptor,
  183. ConfigDescriptor->wTotalLength,
  184. current,
  185. 0); // the very next one.
  186. if (USB_CONFIGURATION_DESCRIPTOR_TYPE == current->bDescriptorType)
  187. { // should only get here once
  188. configArray->ConfigurationDescriptor
  189. = * (PUSB_CONFIGURATION_DESCRIPTOR) current;
  190. }
  191. else if (USB_INTERFACE_DESCRIPTOR_TYPE == current->bDescriptorType)
  192. {
  193. //
  194. // Allocate an interface array
  195. //
  196. interfaceArray = &configArray->Interfaces[numberInterfaces++];
  197. interfaceArray->Interface = *((PUSB_INTERFACE_DESCRIPTOR) current);
  198. interfaceArray->NumberEndpointDescriptors = 0;
  199. interfaceArray->NumberOtherDescriptors = 0;
  200. interfaceArray->EndpointDescriptors = endpointArray;
  201. interfaceArray->OtherDescriptors = otherArray;
  202. }
  203. else
  204. {
  205. //
  206. // you must first have an interface descriptor before you
  207. // can have any other type of descriptors.
  208. // So if we get here without interfaceArray set to something
  209. // Then there's a problem with your descriptor and we
  210. // should throw up our hands.
  211. //
  212. if (NULL == interfaceArray)
  213. {
  214. free (configArray);
  215. return NULL;
  216. }
  217. //
  218. // allocate this one from the end.
  219. //
  220. bufferEnd -= ROUND_TO_PTR(current->bLength);
  221. CopyMemory (bufferEnd, current, current->bLength);
  222. if (USB_ENDPOINT_DESCRIPTOR_TYPE == current->bDescriptorType)
  223. {
  224. *endpointArray = (PUSB_ENDPOINT_DESCRIPTOR) bufferEnd;
  225. endpointArray++;
  226. interfaceArray->NumberEndpointDescriptors++;
  227. }
  228. else
  229. {
  230. *otherArray = (PUSB_COMMON_DESCRIPTOR) bufferEnd;
  231. otherArray++;
  232. interfaceArray->NumberOtherDescriptors++;
  233. }
  234. }
  235. }
  236. if ((PCHAR) otherArray != bufferEnd)
  237. {
  238. // shootme.
  239. assert ((PCHAR) otherArray == bufferEnd);
  240. free (configArray);
  241. return NULL;
  242. }
  243. else if ((PCHAR)endpointArray != buffer)
  244. {
  245. // shootme.
  246. assert ((PCHAR)endpointArray != buffer);
  247. free (configArray);
  248. return NULL;
  249. }
  250. return configArray;
  251. }
  252. void __stdcall
  253. GenUSB_FreeConfigurationDescriptorArray (
  254. PGENUSB_CONFIGURATION_INFORMATION_ARRAY ConfigurationArray
  255. )
  256. {
  257. free (ConfigurationArray);
  258. }