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.

769 lines
19 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. usb2lib.c
  5. Abstract:
  6. interface to usb2lib, usb2 low/full speed scheduling algorithms
  7. Environment:
  8. kernel or user mode only
  9. Notes:
  10. Revision History:
  11. 10-31-00 : created
  12. --*/
  13. #include "common.h"
  14. USB2LIB_DATA LibData;
  15. VOID
  16. USB2LIB_InitializeLib(
  17. PULONG HcContextSize,
  18. PULONG EndpointContextSize,
  19. PULONG TtContextSize,
  20. PUSB2LIB_DBGPRINT Usb2LibDbgPrint,
  21. PUSB2LIB_DBGBREAK Usb2LibDbgBreak
  22. )
  23. /*++
  24. Routine Description:
  25. Arguments:
  26. Return Value:
  27. --*/
  28. {
  29. *HcContextSize = sizeof(USB2LIB_HC_CONTEXT);
  30. *TtContextSize = sizeof(USB2LIB_TT_CONTEXT);
  31. *EndpointContextSize = sizeof(USB2LIB_ENDPOINT_CONTEXT);
  32. LibData.DbgPrint = Usb2LibDbgPrint;
  33. LibData.DbgBreak = Usb2LibDbgBreak;
  34. }
  35. VOID
  36. USB2LIB_InitController(
  37. PUSB2LIB_HC_CONTEXT HcContext
  38. )
  39. /*++
  40. Routine Description:
  41. Called at init time for an instance of the USB 2
  42. controller
  43. Arguments:
  44. Return Value:
  45. --*/
  46. {
  47. DBGPRINT(("USB2LIB_InitController %x\n", HcContext));
  48. HcContext->Sig = SIG_LIB_HC;
  49. init_hc(&HcContext->Hc);
  50. init_tt(&HcContext->Hc, &HcContext->DummyTt); // set up dummy TT for use by HS endpoints
  51. }
  52. VOID
  53. USB2LIB_InitTt(
  54. PUSB2LIB_HC_CONTEXT HcContext,
  55. PUSB2LIB_TT_CONTEXT TtContext
  56. )
  57. /*++
  58. Routine Description:
  59. Arguments:
  60. Return Value:
  61. --*/
  62. {
  63. DBGPRINT(("USB2LIB_InitTt %x %x\n", HcContext, TtContext));
  64. TtContext->Sig = SIG_LIB_TT;
  65. init_tt(&HcContext->Hc, &TtContext->Tt);
  66. }
  67. #if 1
  68. void Shift_to_list_end(
  69. int move_ep,
  70. PEndpoint RebalanceList[]
  71. )
  72. {
  73. // int i;
  74. PEndpoint ep = RebalanceList[move_ep];
  75. move_ep++;
  76. while (RebalanceList[move_ep])
  77. {
  78. RebalanceList[move_ep-1] = RebalanceList[move_ep];
  79. move_ep++;
  80. }
  81. RebalanceList[move_ep-1] = ep;
  82. }
  83. #endif
  84. BOOLEAN
  85. Promote_endpoint_periods(
  86. PEndpoint ep,
  87. PEndpoint RebalanceList[],
  88. PULONG RebalanceListEntries
  89. )
  90. {
  91. int unwind = 0, check_ep;
  92. unsigned result;
  93. if ((ep->actual_period != 1) && (ep->ep_type == interrupt) && (ep->start_microframe > 2))
  94. {
  95. DBGPRINT((">Period Promotion of allocated endpoint\n"));
  96. // To promote an endpoint period:
  97. // 0) unwind = false
  98. // 1) deallocate original endpoint
  99. // 2) change new ep period to 1
  100. // 3) (re)allocate new endpoint (with new period 1)
  101. // 4) if successful
  102. // 5) check endpoints in change list for need of period promotion
  103. // 6) deallocate endpoint, move to end of change list, change period to 1, reallocate
  104. // 7) if unsuccessful
  105. // 8) unwind = true; break
  106. // 9) next ep
  107. //10) if unwind
  108. //11) deallocate orginal ep
  109. //12) check change list for promotion endpoint(s)
  110. //13) if promoted ep
  111. //14) deallocate ep, change back to original period, allocate
  112. //15) next ep
  113. //16) return false
  114. //17) else return true
  115. //18) else return false
  116. /*
  117. // On return, change list will have promoted endpoints in order of reallocation, but it is possible
  118. // to have other endpoints interspersed with the promoted endpoints. The corresponding schedule of endpoints
  119. // must be adjusted to match the order of the promoted endpoints (since they are reinserted into the budget).
  120. // The promoted endpoints (except the original endpoint) are moved to the end of the change list as the
  121. // promotion reallocations are done to ensure that they are in the change list in the order of insertion
  122. // into the budget. This allows the scheduler to derive the new schedule/budget order from the order the
  123. // promoted endpoints appear in the change list.
  124. //
  125. // This algorithm (critically) depends on the Allocate/Deallocate "appending"/reusing an existing change list
  126. // as the "final" change list is composed during the period promotion processing is performed.
  127. */
  128. Deallocate_time_for_endpoint(ep,
  129. RebalanceList,
  130. RebalanceListEntries);
  131. ep->saved_period = ep->period;
  132. ep->period = 1;
  133. // 3) (re)allocate new endpoint (with new period 1)
  134. result = Allocate_time_for_endpoint(ep,
  135. RebalanceList,
  136. RebalanceListEntries);
  137. if (!result) {
  138. ep->period = ep->saved_period;
  139. ep->saved_period = 0;
  140. ep->promoted_this_time = 0;
  141. return 0; // failed period promotion of original endpoint
  142. }
  143. }
  144. check_ep = 0;
  145. while (RebalanceList[check_ep])
  146. {
  147. RebalanceList[check_ep]->promoted_this_time = 0;
  148. check_ep++;
  149. }
  150. check_ep = 0;
  151. while (RebalanceList[check_ep])
  152. {
  153. if ((RebalanceList[check_ep]->actual_period != 1) &&
  154. (RebalanceList[check_ep]->ep_type == interrupt) &&
  155. (RebalanceList[check_ep]->start_microframe > 2))
  156. {
  157. // 6) deallocate endpoint, move to end of change list, change period to 1, reallocate
  158. DBGPRINT((">Period Promoting endpoint\n"));
  159. Deallocate_time_for_endpoint(
  160. RebalanceList[check_ep],
  161. RebalanceList,
  162. RebalanceListEntries);
  163. // Shift_to_list_end(check_ep, RebalanceList);
  164. RebalanceList[check_ep]->promoted_this_time = 1;
  165. RebalanceList[check_ep]->saved_period = RebalanceList[check_ep]->period;
  166. RebalanceList[check_ep]->period = 1;
  167. result = Allocate_time_for_endpoint(
  168. RebalanceList[check_ep],
  169. RebalanceList,
  170. RebalanceListEntries);
  171. if (!result)
  172. {
  173. unwind = 1;
  174. break;
  175. }
  176. }
  177. check_ep++;
  178. }
  179. if (unwind)
  180. {
  181. DBGPRINT((">Unwinding Promoted endpoints\n"));
  182. //11) deallocate orginal ep
  183. Deallocate_time_for_endpoint(
  184. ep,
  185. RebalanceList,
  186. RebalanceListEntries);
  187. ep->period = ep->saved_period;
  188. ep->saved_period = 0;
  189. //12) check change list for promotion endpoint(s)
  190. check_ep = 0;
  191. while (RebalanceList[check_ep])
  192. {
  193. //13) if promoted ep
  194. if (RebalanceList[check_ep]->promoted_this_time)
  195. {
  196. //14) deallocate ep, change back to original period, allocate
  197. DBGPRINT((">Reallocating Unpromoted endpoint\n"));
  198. if(RebalanceList[check_ep]->calc_bus_time != 0)
  199. Deallocate_time_for_endpoint(
  200. RebalanceList[check_ep],
  201. RebalanceList,
  202. RebalanceListEntries);
  203. RebalanceList[check_ep]->period = RebalanceList[check_ep]->saved_period;
  204. RebalanceList[check_ep]->saved_period = 0;
  205. // Leave the promoted flag set since order could have changed.
  206. // schedule must be reconciled accordingly by the HC code.
  207. //RebalanceList[check_ep]->promoted_this_time = 0;
  208. result = Allocate_time_for_endpoint(
  209. RebalanceList[check_ep],
  210. RebalanceList,
  211. RebalanceListEntries);
  212. }
  213. check_ep++;
  214. }
  215. return 0;
  216. } else {
  217. return 1;
  218. }
  219. }
  220. BOOLEAN
  221. USB2LIB_AllocUsb2BusTime(
  222. PUSB2LIB_HC_CONTEXT HcContext,
  223. PUSB2LIB_TT_CONTEXT TtContext,
  224. PUSB2LIB_ENDPOINT_CONTEXT EndpointContext,
  225. PUSB2LIB_BUDGET_PARAMETERS Budget,
  226. PVOID RebalanceContext,
  227. PVOID RebalanceList,
  228. PULONG RebalanceListEntries
  229. )
  230. /*++
  231. Routine Description:
  232. Arguments:
  233. Return Value:
  234. --*/
  235. {
  236. eptype endpointType;
  237. unsigned direction, speed;
  238. //PEndpoint changed_ep_list[];
  239. unsigned result;
  240. //unsigned changed_eps;
  241. PEndpoint ep;
  242. BOOLEAN alloced;
  243. ULONG ilop;
  244. PREBALANCE_LIST rbl;
  245. PTT tt;
  246. ep = &EndpointContext->Ep;
  247. EndpointContext->Sig = SIG_LIB_EP;
  248. EndpointContext->RebalanceContext = RebalanceContext;
  249. //changed_ep_list = RebalanceList;
  250. switch (Budget->TransferType) {
  251. case Budget_Iso:
  252. DBGPRINT((">Iso \n"));
  253. endpointType = isoch;
  254. break;
  255. case Budget_Interrupt:
  256. DBGPRINT((">Interrupt \n"));
  257. endpointType = interrupt;
  258. break;
  259. default:
  260. TEST_TRAP();
  261. }
  262. if (Budget->Direction == Budget_In) {
  263. DBGPRINT((">In \n"));
  264. direction = INDIR;
  265. } else {
  266. DBGPRINT((">Out \n"));
  267. direction = OUTDIR;
  268. }
  269. switch (Budget->Speed) {
  270. case Budget_FullSpeed:
  271. DBGPRINT((">FullSpeed \n"));
  272. speed = FSSPEED;
  273. tt = &TtContext->Tt;
  274. break;
  275. case Budget_HighSpeed:
  276. DBGPRINT((">HighSpeed \n"));
  277. speed = HSSPEED;
  278. tt = &HcContext->DummyTt; // set endpoint to dummy TT so HC can be reached
  279. break;
  280. case Budget_LowSpeed:
  281. DBGPRINT((">LowSpeed \n"));
  282. speed = LSSPEED;
  283. tt = &TtContext->Tt;
  284. break;
  285. default:
  286. DBGPRINT(("BAD SPEED\n"));
  287. }
  288. DBGPRINT((">Period %d\n", Budget->Period));
  289. if(Budget->Speed == Budget_HighSpeed) {
  290. // This value should be a power of 2, so we don't have to check
  291. // but limit its value to MAXFRAMES * 8
  292. if(Budget->Period > MAXMICROFRAMES) {
  293. Budget->Period = MAXMICROFRAMES;
  294. }
  295. } else {
  296. // We are full / low speed endpoint
  297. //
  298. // Round down the period to the nearest power of two (if it isn't already)
  299. //
  300. for(ilop = MAXFRAMES; ilop >= 1; ilop = ilop >> 1) {
  301. if(Budget->Period >= ilop) {
  302. break;
  303. }
  304. }
  305. Budget->Period = ilop;
  306. }
  307. DBGPRINT((">MaxPacket %d\n", Budget->MaxPacket));
  308. DBGPRINT((">Converted Period %d\n", Budget->Period));
  309. DBGPRINT((">RebalanceListEntries %d\n", *RebalanceListEntries));
  310. Set_endpoint(
  311. ep,
  312. endpointType,
  313. direction,
  314. speed,
  315. Budget->Period,
  316. Budget->MaxPacket,
  317. tt);
  318. // ask John Garney to do the math
  319. DBGPRINT((">alloc (ep) %x \n", ep));
  320. result = Allocate_time_for_endpoint(ep,
  321. RebalanceList,
  322. RebalanceListEntries);
  323. // check if successful, period != 1, interrupt, and "late" in frame,
  324. // then need to promote period to 1
  325. // DBGPRINT((">Executing Promote_endpoint_periods (ep) %x \n", ep));
  326. if (result)
  327. {
  328. result = Promote_endpoint_periods(ep,
  329. RebalanceList,
  330. RebalanceListEntries);
  331. }
  332. // nonzero indicates success
  333. if (result) {
  334. // set return parameters
  335. DBGPRINT((">Results\n"));
  336. DBGPRINT((">num_starts %d \n", ep->num_starts));
  337. DBGPRINT((">num_completes %d \n", ep->num_completes));
  338. DBGPRINT((">start_microframe %d \n", ep->start_microframe));
  339. // this is the schedule offset
  340. DBGPRINT((">start_frame %d \n", ep->start_frame));
  341. // period awarded, may be less than requested
  342. DBGPRINT((">actual_period %d \n", ep->actual_period));
  343. DBGPRINT((">start_time %d \n", ep->start_time));
  344. DBGPRINT((">calc_bus_time %d \n", ep->calc_bus_time));
  345. DBGPRINT((">promoted_this_time %d \n", ep->promoted_this_time));
  346. alloced = TRUE;
  347. } else {
  348. alloced = FALSE;
  349. }
  350. // fix up rebalance list
  351. rbl = RebalanceList;
  352. ilop = 0;
  353. while (rbl->RebalanceContext[ilop]) {
  354. PUSB2LIB_ENDPOINT_CONTEXT endpointContext;
  355. PEndpoint rep;
  356. DBGPRINT((">rb[%d] %x\n", ilop, rbl->RebalanceContext[ilop]));
  357. endpointContext = CONTAINING_RECORD(rbl->RebalanceContext[ilop],
  358. struct _USB2LIB_ENDPOINT_CONTEXT,
  359. Ep);
  360. rep = &endpointContext->Ep;
  361. DBGPRINT((">rb Results\n"));
  362. DBGPRINT((">rb num_starts %d \n", rep->num_starts));
  363. DBGPRINT((">rb num_completes %d \n", rep->num_completes));
  364. DBGPRINT((">rb start_microframe %d \n", rep->start_microframe));
  365. // this is the schedule offset
  366. DBGPRINT((">rb start_frame %d \n", rep->start_frame));
  367. // period awarded, may be less than requested
  368. DBGPRINT((">rb actual_period %d \n", rep->actual_period));
  369. DBGPRINT((">rb start_time %d \n", rep->start_time));
  370. DBGPRINT((">rb calc_bus_time %d \n", rep->calc_bus_time));
  371. DBGPRINT((">rb promoted_this_time %d \n", rep->promoted_this_time));
  372. rbl->RebalanceContext[ilop] = endpointContext->RebalanceContext;
  373. ilop++;
  374. }
  375. DBGPRINT((">Change List Size = %d RBE = %d\n", ilop, *RebalanceListEntries));
  376. *RebalanceListEntries = ilop;
  377. return alloced;
  378. }
  379. VOID
  380. USB2LIB_FreeUsb2BusTime(
  381. PUSB2LIB_HC_CONTEXT HcContext,
  382. PUSB2LIB_TT_CONTEXT TtContext,
  383. PUSB2LIB_ENDPOINT_CONTEXT EndpointContext,
  384. PVOID RebalanceList,
  385. PULONG RebalanceListEntries
  386. )
  387. /*++
  388. Routine Description:
  389. Arguments:
  390. Return Value:
  391. --*/
  392. {
  393. unsigned result;
  394. PEndpoint ep;
  395. PREBALANCE_LIST rbl;
  396. ULONG i;
  397. // ASSERT(EndpointContext->Sig == SIG_LIB_EP);
  398. ep = &EndpointContext->Ep;
  399. DBGPRINT((">dealloc ep Context = 0x%x (ep) %x \n", EndpointContext, ep));
  400. DBGPRINT((">RebalanceListEntries %d \n", *RebalanceListEntries));
  401. Deallocate_time_for_endpoint(ep,
  402. RebalanceList,
  403. RebalanceListEntries);
  404. // fix up rebalance list
  405. rbl = RebalanceList;
  406. i = 0;
  407. while (rbl->RebalanceContext[i]) {
  408. PUSB2LIB_ENDPOINT_CONTEXT endpointContext;
  409. DBGPRINT((">rb[%d] %x\n", i, rbl->RebalanceContext[i]));
  410. endpointContext = CONTAINING_RECORD(rbl->RebalanceContext[i],
  411. struct _USB2LIB_ENDPOINT_CONTEXT,
  412. Ep);
  413. rbl->RebalanceContext[i] = endpointContext->RebalanceContext;
  414. i++;
  415. }
  416. DBGPRINT((">Change List Size = %d RBE = %d\n", i, *RebalanceListEntries));
  417. *RebalanceListEntries = i;
  418. }
  419. VOID
  420. ConvertBtoHFrame(UCHAR BFrame, UCHAR BUFrame, PUCHAR HFrame, PUCHAR HUFrame)
  421. {
  422. // The budgeter returns funky values that we have to convert to something
  423. // that the host controller understands.
  424. // If bus micro frame is -1, that means that the start split is scheduled
  425. // in the last microframe of the previous bus frame.
  426. // to convert to hframes, you simply change the microframe to 0 and
  427. // keep the bus frame (see one of the tables in the host controller spec
  428. // eg 4-17.
  429. if(BUFrame == 0xFF) {
  430. *HUFrame = 0;
  431. *HFrame = BFrame;
  432. }
  433. // if the budgeter returns a value in the range from 0-6
  434. // we simply add one to the bus micro frame to get the host
  435. // microframe
  436. if(BUFrame >= 0 && BUFrame <= 6) {
  437. *HUFrame = BUFrame + 1;
  438. *HFrame = BFrame;
  439. }
  440. // if the budgeter returns a value of 7 for the bframe
  441. // then the HUframe = 0 and the HUframe = buframe +1
  442. if(BUFrame == 7) {
  443. *HUFrame = 0;
  444. *HFrame = BFrame + 1;
  445. }
  446. }
  447. UCHAR
  448. USB2LIB_GetSMASK(PUSB2LIB_ENDPOINT_CONTEXT EndpointContext)
  449. {
  450. PEndpoint Ep;
  451. UCHAR tmp = 0;
  452. Ep = &EndpointContext->Ep;
  453. // ASSERT(EndpointContext->Sig == SIG_LIB_EP);
  454. if(Ep->speed == HSSPEED) {
  455. //DBGPRINT(("in GetSMASK StartUFrame on High Speed Endpoint = 0x%x\n", Ep->start_microframe));
  456. tmp |= 1 << Ep->start_microframe;
  457. } else {
  458. ULONG ilop;
  459. UCHAR HFrame; // H (Host) frame for endpoint
  460. UCHAR HUFrame; // H (Host) micro frame for endpoint
  461. // For Full and Low Speed Endpoints
  462. // the budgeter returns a bframe. Convert to HUFrame to get SMASK
  463. ConvertBtoHFrame((UCHAR)Ep->start_frame, (UCHAR)Ep->start_microframe, &HFrame, &HUFrame);
  464. for(ilop = 0; ilop < Ep->num_starts; ilop++) {
  465. tmp |= 1 << HUFrame++;
  466. }
  467. }
  468. return tmp;
  469. }
  470. //
  471. // I'm too brain dead to calculate this so just do table lookup
  472. //
  473. // Calculated by 1 << Start H Frame + 2. If Start H Frame + 2 > 7 wrap the bits
  474. // to the lower part of the word
  475. // eg. hframe 0 +2 means cmask in frames 2,3,4 ==> cmask 0x1c
  476. // eg. hframe 5 + 2 means cmasks in frames 7, 8, 9 which means cmask 0x83
  477. #define SIZE_OF_CMASK 8
  478. static UCHAR CMASKS [SIZE_OF_CMASK] =
  479. { 0x1c, // Start HUFRAME 0
  480. 0x38, // Start HUFRAME 1
  481. 0x70, // Start HUFRAME 2
  482. 0xE0, // Start HUFRAME 3
  483. 0xC1, // Start HUFRAME 4
  484. 0x83, // Start HUFRAME 5
  485. 0x07, // Start HUFRAME 6
  486. 0x0E, // Start HUFRAME 7
  487. };
  488. UCHAR
  489. USB2LIB_GetCMASK(PUSB2LIB_ENDPOINT_CONTEXT EndpointContext)
  490. {
  491. PEndpoint Ep;
  492. Ep = &EndpointContext->Ep;
  493. // ASSERT(EndpointContext->Sig == SIG_LIB_EP);
  494. if(Ep->speed == HSSPEED) {
  495. return 0;
  496. } else if(Ep->ep_type == interrupt) {
  497. UCHAR HFrame; // H (Host) frame for endpoint
  498. UCHAR HUFrame; // H (Host) micro frame for endpoint
  499. ConvertBtoHFrame((UCHAR)Ep->start_frame, (UCHAR)Ep->start_microframe,
  500. &HFrame, &HUFrame);
  501. return CMASKS[HUFrame];
  502. } else {
  503. // Split ISO!
  504. UCHAR HFrame; // H (Host) frame for endpoint
  505. UCHAR HUFrame; // H (Host) micro frame for endpoint
  506. UCHAR tmp = 0;
  507. ULONG NumCompletes;
  508. if(Ep->direction == OUTDIR) {
  509. // Split iso out -- NO complete splits
  510. return 0;
  511. }
  512. ConvertBtoHFrame((UCHAR)Ep->start_frame, (UCHAR)Ep->start_microframe,
  513. &HFrame, &HUFrame);
  514. HUFrame += 2;
  515. NumCompletes = Ep->num_completes;
  516. // ASSERT(NumCompletes > 0);
  517. //
  518. // Set all CMASKS bits to be set at the end of the frame
  519. //
  520. for(; HUFrame < 8; HUFrame++) {
  521. tmp |= 1 << HUFrame;
  522. NumCompletes--;
  523. if(!NumCompletes){
  524. break;
  525. }
  526. }
  527. //
  528. // Now set all CMASKS bits to be set at the end of the
  529. // frame I.E. for the next frame wrap condition
  530. //
  531. while(NumCompletes) {
  532. tmp |= 1 << (HUFrame - 8);
  533. NumCompletes--;
  534. }
  535. //DBGPRINT(("in GetCMASK HFRAME = 0x%x HUFRAME 0x%x\n", HFrame, HUFrame));
  536. return tmp;
  537. }
  538. }
  539. UCHAR
  540. USB2LIB_GetStartMicroFrame(PUSB2LIB_ENDPOINT_CONTEXT EndpointContext)
  541. {
  542. PEndpoint Ep;
  543. UCHAR HFrame; // H (Host) frame for endpoint
  544. UCHAR HUFrame; // H (Host) micro frame for endpoint
  545. Ep = &EndpointContext->Ep;
  546. // ASSERT(EndpointContext->Sig == SIG_LIB_EP);
  547. ConvertBtoHFrame((UCHAR)Ep->start_frame, (UCHAR)Ep->start_microframe,
  548. &HFrame, &HUFrame);
  549. return HUFrame;
  550. }
  551. UCHAR
  552. USB2LIB_GetPromotedThisTime(PUSB2LIB_ENDPOINT_CONTEXT EndpointContext)
  553. {
  554. PEndpoint Ep;
  555. UCHAR Promoted = 0;
  556. Ep = &EndpointContext->Ep;
  557. // ASSERT(EndpointContext->Sig == SIG_LIB_EP);
  558. Promoted = (UCHAR) Ep->promoted_this_time;
  559. Ep->promoted_this_time = 0;
  560. return Promoted;
  561. }
  562. UCHAR
  563. USB2LIB_GetNewPeriod(PUSB2LIB_ENDPOINT_CONTEXT EndpointContext)
  564. {
  565. PEndpoint Ep;
  566. Ep = &EndpointContext->Ep;
  567. // ASSERT(EndpointContext->Sig == SIG_LIB_EP);
  568. return (UCHAR) Ep->actual_period;
  569. }
  570. ULONG
  571. USB2LIB_GetScheduleOffset(PUSB2LIB_ENDPOINT_CONTEXT EndpointContext)
  572. {
  573. PEndpoint Ep;
  574. Ep = &EndpointContext->Ep;
  575. // assert(EndpointContext->Sig == SIG_LIB_EP);
  576. return Ep->start_frame;
  577. }
  578. PVOID
  579. USB2LIB_GetEndpoint(PUSB2LIB_ENDPOINT_CONTEXT EndpointContext)
  580. {
  581. return &(EndpointContext->Ep);
  582. }
  583. ULONG
  584. USB2LIB_GetAllocedBusTime(PUSB2LIB_ENDPOINT_CONTEXT EndpointContext)
  585. {
  586. PEndpoint Ep;
  587. Ep = &EndpointContext->Ep;
  588. // assert(EndpointContext->Sig == SIG_LIB_EP);
  589. return Ep->calc_bus_time;
  590. }
  591. PVOID
  592. USB2LIB_GetNextEndpoint(PUSB2LIB_ENDPOINT_CONTEXT EndpointContext)
  593. {
  594. PEndpoint Ep, nextEp;
  595. PUSB2LIB_ENDPOINT_CONTEXT nextContext;
  596. Ep = &EndpointContext->Ep;
  597. nextEp = Ep->next_ep;
  598. if (nextEp) {
  599. nextContext = CONTAINING_RECORD(nextEp,
  600. struct _USB2LIB_ENDPOINT_CONTEXT,
  601. Ep);
  602. // assert(EndpointContext->Sig == SIG_LIB_EP);
  603. return nextContext->RebalanceContext;
  604. } else {
  605. return NULL;
  606. }
  607. }