]> git.donarmstrong.com Git - qmk_firmware.git/blob - tool/mbed/mbed-sdk/libraries/USBDevice/USBDevice/USBHAL_LPC40.cpp
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[qmk_firmware.git] / tool / mbed / mbed-sdk / libraries / USBDevice / USBDevice / USBHAL_LPC40.cpp
1 /* Copyright (c) 2010-2011 mbed.org, MIT License
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
4 * and associated documentation files (the "Software"), to deal in the Software without
5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
7 * Software is furnished to do so, subject to the following conditions:
8 *
9 * The above copyright notice and this permission notice shall be included in all copies or
10 * substantial portions of the Software.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17 */
18
19 #if defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM)
20
21 #include "USBHAL.h"
22
23
24 // Get endpoint direction
25 #define IN_EP(endpoint)     ((endpoint) & 1U ? true : false)
26 #define OUT_EP(endpoint)    ((endpoint) & 1U ? false : true)
27
28 // Convert physical endpoint number to register bit
29 #define EP(endpoint) (1UL<<endpoint)
30
31 // Power Control for Peripherals register
32 #define PCUSB      (1UL<<31)
33
34 // USB Clock Control register
35 #define DEV_CLK_EN  (1UL<<1)
36 #define PORT_CLK_EN (1UL<<3)
37 #define AHB_CLK_EN  (1UL<<4)
38
39 // USB Clock Status register
40 #define DEV_CLK_ON (1UL<<1)
41 #define AHB_CLK_ON (1UL<<4)
42
43 // USB Device Interupt registers
44 #define FRAME      (1UL<<0)
45 #define EP_FAST    (1UL<<1)
46 #define EP_SLOW    (1UL<<2)
47 #define DEV_STAT   (1UL<<3)
48 #define CCEMPTY    (1UL<<4)
49 #define CDFULL     (1UL<<5)
50 #define RxENDPKT   (1UL<<6)
51 #define TxENDPKT   (1UL<<7)
52 #define EP_RLZED   (1UL<<8)
53 #define ERR_INT    (1UL<<9)
54
55 // USB Control register
56 #define RD_EN (1<<0)
57 #define WR_EN (1<<1)
58 #define LOG_ENDPOINT(endpoint) ((endpoint>>1)<<2)
59
60 // USB Receive Packet Length register
61 #define DV      (1UL<<10)
62 #define PKT_RDY (1UL<<11)
63 #define PKT_LNGTH_MASK (0x3ff)
64
65 // Serial Interface Engine (SIE)
66 #define SIE_WRITE   (0x01)
67 #define SIE_READ    (0x02)
68 #define SIE_COMMAND (0x05)
69 #define SIE_CMD_CODE(phase, data) ((phase<<8)|(data<<16))
70
71 // SIE Command codes
72 #define SIE_CMD_SET_ADDRESS        (0xD0)
73 #define SIE_CMD_CONFIGURE_DEVICE   (0xD8)
74 #define SIE_CMD_SET_MODE           (0xF3)
75 #define SIE_CMD_READ_FRAME_NUMBER  (0xF5)
76 #define SIE_CMD_READ_TEST_REGISTER (0xFD)
77 #define SIE_CMD_SET_DEVICE_STATUS  (0xFE)
78 #define SIE_CMD_GET_DEVICE_STATUS  (0xFE)
79 #define SIE_CMD_GET_ERROR_CODE     (0xFF)
80 #define SIE_CMD_READ_ERROR_STATUS  (0xFB)
81
82 #define SIE_CMD_SELECT_ENDPOINT(endpoint)                 (0x00+endpoint)
83 #define SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint) (0x40+endpoint)
84 #define SIE_CMD_SET_ENDPOINT_STATUS(endpoint)             (0x40+endpoint)
85
86 #define SIE_CMD_CLEAR_BUFFER    (0xF2)
87 #define SIE_CMD_VALIDATE_BUFFER (0xFA)
88
89 // SIE Device Status register
90 #define SIE_DS_CON    (1<<0)
91 #define SIE_DS_CON_CH (1<<1)
92 #define SIE_DS_SUS    (1<<2)
93 #define SIE_DS_SUS_CH (1<<3)
94 #define SIE_DS_RST    (1<<4)
95
96 // SIE Device Set Address register
97 #define SIE_DSA_DEV_EN  (1<<7)
98
99 // SIE Configue Device register
100 #define SIE_CONF_DEVICE (1<<0)
101
102 // Select Endpoint register
103 #define SIE_SE_FE       (1<<0)
104 #define SIE_SE_ST       (1<<1)
105 #define SIE_SE_STP      (1<<2)
106 #define SIE_SE_PO       (1<<3)
107 #define SIE_SE_EPN      (1<<4)
108 #define SIE_SE_B_1_FULL (1<<5)
109 #define SIE_SE_B_2_FULL (1<<6)
110
111 // Set Endpoint Status command
112 #define SIE_SES_ST      (1<<0)
113 #define SIE_SES_DA      (1<<5)
114 #define SIE_SES_RF_MO   (1<<6)
115 #define SIE_SES_CND_ST  (1<<7)
116
117
118 USBHAL * USBHAL::instance;
119
120 static volatile int epComplete;
121 static uint32_t endpointStallState;
122
123 static void SIECommand(uint32_t command) {
124     // The command phase of a SIE transaction
125     LPC_USB->DevIntClr = CCEMPTY;
126     LPC_USB->CmdCode = SIE_CMD_CODE(SIE_COMMAND, command);
127     while (!(LPC_USB->DevIntSt & CCEMPTY));
128 }
129
130 static void SIEWriteData(uint8_t data) {
131     // The data write phase of a SIE transaction
132     LPC_USB->DevIntClr = CCEMPTY;
133     LPC_USB->CmdCode = SIE_CMD_CODE(SIE_WRITE, data);
134     while (!(LPC_USB->DevIntSt & CCEMPTY));
135 }
136
137 static uint8_t SIEReadData(uint32_t command) {
138     // The data read phase of a SIE transaction
139     LPC_USB->DevIntClr = CDFULL;
140     LPC_USB->CmdCode = SIE_CMD_CODE(SIE_READ, command);
141     while (!(LPC_USB->DevIntSt & CDFULL));
142     return (uint8_t)LPC_USB->CmdData;
143 }
144
145 static void SIEsetDeviceStatus(uint8_t status) {
146     // Write SIE device status register
147     SIECommand(SIE_CMD_SET_DEVICE_STATUS);
148     SIEWriteData(status);
149 }
150
151 static uint8_t SIEgetDeviceStatus(void) {
152     // Read SIE device status register
153     SIECommand(SIE_CMD_GET_DEVICE_STATUS);
154     return SIEReadData(SIE_CMD_GET_DEVICE_STATUS);
155 }
156
157 void SIEsetAddress(uint8_t address) {
158     // Write SIE device address register
159     SIECommand(SIE_CMD_SET_ADDRESS);
160     SIEWriteData((address & 0x7f) | SIE_DSA_DEV_EN);
161 }
162
163 static uint8_t SIEselectEndpoint(uint8_t endpoint) {
164     // SIE select endpoint command
165     SIECommand(SIE_CMD_SELECT_ENDPOINT(endpoint));
166     return SIEReadData(SIE_CMD_SELECT_ENDPOINT(endpoint));
167 }
168
169 static uint8_t SIEclearBuffer(void) {
170     // SIE clear buffer command
171     SIECommand(SIE_CMD_CLEAR_BUFFER);
172     return SIEReadData(SIE_CMD_CLEAR_BUFFER);
173 }
174
175 static void SIEvalidateBuffer(void) {
176     // SIE validate buffer command
177     SIECommand(SIE_CMD_VALIDATE_BUFFER);
178 }
179
180 static void SIEsetEndpointStatus(uint8_t endpoint, uint8_t status) {
181     // SIE set endpoint status command
182     SIECommand(SIE_CMD_SET_ENDPOINT_STATUS(endpoint));
183     SIEWriteData(status);
184 }
185
186 static uint16_t SIEgetFrameNumber(void) __attribute__ ((unused));
187 static uint16_t SIEgetFrameNumber(void) {
188     // Read current frame number
189     uint16_t lowByte;
190     uint16_t highByte;
191
192     SIECommand(SIE_CMD_READ_FRAME_NUMBER);
193     lowByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER);
194     highByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER);
195
196     return (highByte << 8) | lowByte;
197 }
198
199 static void SIEconfigureDevice(void) {
200     // SIE Configure device command
201     SIECommand(SIE_CMD_CONFIGURE_DEVICE);
202     SIEWriteData(SIE_CONF_DEVICE);
203 }
204
205 static void SIEunconfigureDevice(void) {
206     // SIE Configure device command
207     SIECommand(SIE_CMD_CONFIGURE_DEVICE);
208     SIEWriteData(0);
209 }
210
211 static void SIEconnect(void) {
212     // Connect USB device
213     uint8_t status = SIEgetDeviceStatus();
214     SIEsetDeviceStatus(status | SIE_DS_CON);
215 }
216
217
218 static void SIEdisconnect(void) {
219     // Disconnect USB device
220     uint8_t status = SIEgetDeviceStatus();
221     SIEsetDeviceStatus(status & ~SIE_DS_CON);
222 }
223
224
225 static uint8_t selectEndpointClearInterrupt(uint8_t endpoint) {
226     // Implemented using using EP_INT_CLR.
227     LPC_USB->EpIntClr = EP(endpoint);
228     while (!(LPC_USB->DevIntSt & CDFULL));
229     return (uint8_t)LPC_USB->CmdData;
230 }
231
232
233 static void enableEndpointEvent(uint8_t endpoint) {
234     // Enable an endpoint interrupt
235     LPC_USB->EpIntEn |= EP(endpoint);
236 }
237
238 static void disableEndpointEvent(uint8_t endpoint) __attribute__ ((unused));
239 static void disableEndpointEvent(uint8_t endpoint) {
240     // Disable an endpoint interrupt
241     LPC_USB->EpIntEn &= ~EP(endpoint);
242 }
243
244 static volatile uint32_t __attribute__((used)) dummyRead;
245 uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
246     // Read from an OUT endpoint
247     uint32_t size;
248     uint32_t i;
249     uint32_t data = 0;
250     uint8_t offset;
251
252     LPC_USB->Ctrl = LOG_ENDPOINT(endpoint) | RD_EN;
253     while (!(LPC_USB->RxPLen & PKT_RDY));
254
255     size = LPC_USB->RxPLen & PKT_LNGTH_MASK;
256
257     offset = 0;
258
259     if (size > 0) {
260         for (i=0; i<size; i++) {
261             if (offset==0) {
262                 // Fetch up to four bytes of data as a word
263                 data = LPC_USB->RxData;
264             }
265
266             // extract a byte
267             *buffer = (data>>offset) & 0xff;
268             buffer++;
269
270             // move on to the next byte
271             offset = (offset + 8) % 32;
272         }
273     } else {
274         dummyRead = LPC_USB->RxData;
275     }
276
277     LPC_USB->Ctrl = 0;
278
279     if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
280         SIEselectEndpoint(endpoint);
281         SIEclearBuffer();
282     }
283
284     return size;
285 }
286
287 static void endpointWritecore(uint8_t endpoint, uint8_t *buffer, uint32_t size) {
288     // Write to an IN endpoint
289     uint32_t temp, data;
290     uint8_t offset;
291
292     LPC_USB->Ctrl = LOG_ENDPOINT(endpoint) | WR_EN;
293
294     LPC_USB->TxPLen = size;
295     offset = 0;
296     data = 0;
297
298     if (size>0) {
299         do {
300             // Fetch next data byte into a word-sized temporary variable
301             temp = *buffer++;
302
303             // Add to current data word
304             temp = temp << offset;
305             data = data | temp;
306
307             // move on to the next byte
308             offset = (offset + 8) % 32;
309             size--;
310
311             if ((offset==0) || (size==0)) {
312                 // Write the word to the endpoint
313                 LPC_USB->TxData = data;
314                 data = 0;
315             }
316         } while (size>0);
317     } else {
318         LPC_USB->TxData = 0;
319     }
320
321     // Clear WR_EN to cover zero length packet case
322     LPC_USB->Ctrl=0;
323
324     SIEselectEndpoint(endpoint);
325     SIEvalidateBuffer();
326 }
327
328 USBHAL::USBHAL(void) {
329     // Disable IRQ
330     NVIC_DisableIRQ(USB_IRQn);
331
332     // fill in callback array
333     epCallback[0] = &USBHAL::EP1_OUT_callback;
334     epCallback[1] = &USBHAL::EP1_IN_callback;
335     epCallback[2] = &USBHAL::EP2_OUT_callback;
336     epCallback[3] = &USBHAL::EP2_IN_callback;
337     epCallback[4] = &USBHAL::EP3_OUT_callback;
338     epCallback[5] = &USBHAL::EP3_IN_callback;
339     epCallback[6] = &USBHAL::EP4_OUT_callback;
340     epCallback[7] = &USBHAL::EP4_IN_callback;
341     epCallback[8] = &USBHAL::EP5_OUT_callback;
342     epCallback[9] = &USBHAL::EP5_IN_callback;
343     epCallback[10] = &USBHAL::EP6_OUT_callback;
344     epCallback[11] = &USBHAL::EP6_IN_callback;
345     epCallback[12] = &USBHAL::EP7_OUT_callback;
346     epCallback[13] = &USBHAL::EP7_IN_callback;
347     epCallback[14] = &USBHAL::EP8_OUT_callback;
348     epCallback[15] = &USBHAL::EP8_IN_callback;
349     epCallback[16] = &USBHAL::EP9_OUT_callback;
350     epCallback[17] = &USBHAL::EP9_IN_callback;
351     epCallback[18] = &USBHAL::EP10_OUT_callback;
352     epCallback[19] = &USBHAL::EP10_IN_callback;
353     epCallback[20] = &USBHAL::EP11_OUT_callback;
354     epCallback[21] = &USBHAL::EP11_IN_callback;
355     epCallback[22] = &USBHAL::EP12_OUT_callback;
356     epCallback[23] = &USBHAL::EP12_IN_callback;
357     epCallback[24] = &USBHAL::EP13_OUT_callback;
358     epCallback[25] = &USBHAL::EP13_IN_callback;
359     epCallback[26] = &USBHAL::EP14_OUT_callback;
360     epCallback[27] = &USBHAL::EP14_IN_callback;
361     epCallback[28] = &USBHAL::EP15_OUT_callback;
362     epCallback[29] = &USBHAL::EP15_IN_callback;
363
364     // Enable power to USB device controller
365     LPC_SC->PCONP |= PCUSB;
366
367     // Enable USB clocks
368     LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN | PORT_CLK_EN;
369     while ((LPC_USB->USBClkSt & (DEV_CLK_EN | AHB_CLK_EN | PORT_CLK_EN)) != (DEV_CLK_ON | AHB_CLK_ON | PORT_CLK_EN));
370
371     // Select port USB2
372     LPC_USB->StCtrl |= 3;
373
374
375     // Configure pin P0.31 to be USB2
376     LPC_IOCON->P0_31 &= ~0x07;
377     LPC_IOCON->P0_31 |= 0x01;
378
379     // Disconnect USB device
380     SIEdisconnect();
381
382     // Configure pin P0.14 to be Connect
383     LPC_IOCON->P0_14 &= ~0x07;
384     LPC_IOCON->P0_14 |= 0x03;
385
386     // Connect must be low for at least 2.5uS
387     wait(0.3);
388
389     // Set the maximum packet size for the control endpoints
390     realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0);
391     realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0);
392
393     // Attach IRQ
394     instance = this;
395     NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr);
396
397     // Enable interrupts for device events and EP0
398     LPC_USB->DevIntEn = EP_SLOW | DEV_STAT | FRAME;
399     enableEndpointEvent(EP0IN);
400     enableEndpointEvent(EP0OUT);
401 }
402
403 USBHAL::~USBHAL(void) {
404     // Ensure device disconnected
405     SIEdisconnect();
406     // Disable USB interrupts
407     NVIC_DisableIRQ(USB_IRQn);
408 }
409
410 void USBHAL::connect(void) {
411     NVIC_EnableIRQ(USB_IRQn);
412     // Connect USB device
413     SIEconnect();
414 }
415
416 void USBHAL::disconnect(void) {
417     NVIC_DisableIRQ(USB_IRQn);
418     // Disconnect USB device
419     SIEdisconnect();
420 }
421
422 void USBHAL::configureDevice(void) {
423     SIEconfigureDevice();
424 }
425
426 void USBHAL::unconfigureDevice(void) {
427     SIEunconfigureDevice();
428 }
429
430 void USBHAL::setAddress(uint8_t address) {
431     SIEsetAddress(address);
432 }
433
434 void USBHAL::EP0setup(uint8_t *buffer) {
435     endpointReadcore(EP0OUT, buffer);
436 }
437
438 void USBHAL::EP0read(void) {
439     // Not required
440 }
441
442 void USBHAL::EP0readStage(void) {
443     // Not required
444 }
445
446 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
447     return endpointReadcore(EP0OUT, buffer);
448 }
449
450 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
451     endpointWritecore(EP0IN, buffer, size);
452 }
453
454 void USBHAL::EP0getWriteResult(void) {
455     // Not required
456 }
457
458 void USBHAL::EP0stall(void) {
459     // This will stall both control endpoints
460     stallEndpoint(EP0OUT);
461 }
462
463 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
464     return EP_PENDING;
465 }
466
467 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) {
468
469     //for isochronous endpoint, we don't wait an interrupt
470     if ((endpoint >> 1) % 3 || (endpoint >> 1) == 0) {
471         if (!(epComplete & EP(endpoint)))
472             return EP_PENDING;
473     }
474
475     *bytesRead = endpointReadcore(endpoint, buffer);
476     epComplete &= ~EP(endpoint);
477     return EP_COMPLETED;
478 }
479
480 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
481     if (getEndpointStallState(endpoint)) {
482         return EP_STALLED;
483     }
484
485     epComplete &= ~EP(endpoint);
486
487     endpointWritecore(endpoint, data, size);
488     return EP_PENDING;
489 }
490
491 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
492     if (epComplete & EP(endpoint)) {
493         epComplete &= ~EP(endpoint);
494         return EP_COMPLETED;
495     }
496
497     return EP_PENDING;
498 }
499
500 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) {
501     // Realise an endpoint
502     LPC_USB->DevIntClr = EP_RLZED;
503     LPC_USB->ReEp |= EP(endpoint);
504     LPC_USB->EpInd = endpoint;
505     LPC_USB->MaxPSize = maxPacket;
506
507     while (!(LPC_USB->DevIntSt & EP_RLZED));
508     LPC_USB->DevIntClr = EP_RLZED;
509
510     // Clear stall state
511     endpointStallState &= ~EP(endpoint);
512
513     enableEndpointEvent(endpoint);
514     return true;
515 }
516
517 void USBHAL::stallEndpoint(uint8_t endpoint) {
518     // Stall an endpoint
519     if ( (endpoint==EP0IN) || (endpoint==EP0OUT) ) {
520         // Conditionally stall both control endpoints
521         SIEsetEndpointStatus(EP0OUT, SIE_SES_CND_ST);
522     } else {
523         SIEsetEndpointStatus(endpoint, SIE_SES_ST);
524
525         // Update stall state
526         endpointStallState |= EP(endpoint);
527     }
528 }
529
530 void USBHAL::unstallEndpoint(uint8_t endpoint) {
531     // Unstall an endpoint. The endpoint will also be reinitialised
532     SIEsetEndpointStatus(endpoint, 0);
533
534     // Update stall state
535     endpointStallState &= ~EP(endpoint);
536 }
537
538 bool USBHAL::getEndpointStallState(uint8_t endpoint) {
539     // Returns true if endpoint stalled
540     return endpointStallState & EP(endpoint);
541 }
542
543 void USBHAL::remoteWakeup(void) {
544     // Remote wakeup
545     uint8_t status;
546
547     // Enable USB clocks
548     LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
549     while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON));
550
551     status = SIEgetDeviceStatus();
552     SIEsetDeviceStatus(status & ~SIE_DS_SUS);
553 }
554
555 void USBHAL::_usbisr(void) {
556     instance->usbisr();
557 }
558
559
560 void USBHAL::usbisr(void) {
561     uint8_t devStat;
562
563     if (LPC_USB->DevIntSt & FRAME) {
564         // Start of frame event
565         SOF(SIEgetFrameNumber());
566         // Clear interrupt status flag
567         LPC_USB->DevIntClr = FRAME;
568     }
569
570     if (LPC_USB->DevIntSt & DEV_STAT) {
571         // Device Status interrupt
572         // Must clear the interrupt status flag before reading the device status from the SIE
573         LPC_USB->DevIntClr = DEV_STAT;
574
575         // Read device status from SIE
576         devStat = SIEgetDeviceStatus();
577         //printf("devStat: %d\r\n", devStat);
578
579         if (devStat & SIE_DS_SUS_CH) {
580             // Suspend status changed
581             if((devStat & SIE_DS_SUS) != 0) {
582                 suspendStateChanged(0);
583             }
584         }
585
586         if (devStat & SIE_DS_RST) {
587             // Bus reset
588             if((devStat & SIE_DS_SUS) == 0) {
589                 suspendStateChanged(1);
590             }
591             busReset();
592         }
593     }
594
595     if (LPC_USB->DevIntSt & EP_SLOW) {
596         // (Slow) Endpoint Interrupt
597
598         // Process each endpoint interrupt
599         if (LPC_USB->EpIntSt & EP(EP0OUT)) {
600             if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP) {
601                 // this is a setup packet
602                 EP0setupCallback();
603             } else {
604                 EP0out();
605             }
606             LPC_USB->DevIntClr = EP_SLOW;
607         }
608
609         if (LPC_USB->EpIntSt & EP(EP0IN)) {
610             selectEndpointClearInterrupt(EP0IN);
611             LPC_USB->DevIntClr = EP_SLOW;
612             EP0in();
613         }
614
615         for (uint8_t num = 2; num < 16*2; num++) {
616             if (LPC_USB->EpIntSt & EP(num)) {
617                 selectEndpointClearInterrupt(num);
618                 epComplete |= EP(num);
619                 LPC_USB->DevIntClr = EP_SLOW;
620                 if ((instance->*(epCallback[num - 2]))()) {
621                     epComplete &= ~EP(num);
622                 }
623             }
624         }
625     }
626 }
627
628 #endif