00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #define USB_SERIAL_PRIVATE_INCLUDE
00045 #include "usb_serial.h"
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 #define STR_MANUFACTURER L"Your Name"
00057 #define STR_PRODUCT L"USB Serial"
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 #define STR_SERIAL_NUMBER L"12345"
00075
00076
00077
00078
00079
00080 #define VENDOR_ID 0x16C0
00081 #define PRODUCT_ID 0x047A
00082
00083
00084
00085
00086
00087
00088
00089
00090 #define TRANSMIT_FLUSH_TIMEOUT 5
00091
00092
00093
00094
00095
00096
00097
00098 #define TRANSMIT_TIMEOUT 25
00099
00100
00101
00102
00103
00104
00105 #define SUPPORT_ENDPOINT_HALT
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 #define ENDPOINT0_SIZE 16
00121 #define CDC_ACM_ENDPOINT 2
00122 #define CDC_RX_ENDPOINT 3
00123 #define CDC_TX_ENDPOINT 4
00124 #if defined(__AVR_AT90USB162__)
00125 #define CDC_ACM_SIZE 16
00126 #define CDC_ACM_BUFFER EP_SINGLE_BUFFER
00127 #define CDC_RX_SIZE 32
00128 #define CDC_RX_BUFFER EP_DOUBLE_BUFFER
00129 #define CDC_TX_SIZE 32
00130 #define CDC_TX_BUFFER EP_DOUBLE_BUFFER
00131 #else
00132 #define CDC_ACM_SIZE 16
00133 #define CDC_ACM_BUFFER EP_SINGLE_BUFFER
00134 #define CDC_RX_SIZE 64
00135 #define CDC_RX_BUFFER EP_DOUBLE_BUFFER
00136 #define CDC_TX_SIZE 64
00137 #define CDC_TX_BUFFER EP_DOUBLE_BUFFER
00138 #endif
00139
00140 static const uint8_t PROGMEM endpoint_config_table[] = {
00141 0,
00142 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(CDC_ACM_SIZE) | CDC_ACM_BUFFER,
00143 1, EP_TYPE_BULK_OUT, EP_SIZE(CDC_RX_SIZE) | CDC_RX_BUFFER,
00144 1, EP_TYPE_BULK_IN, EP_SIZE(CDC_TX_SIZE) | CDC_TX_BUFFER
00145 };
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 static uint8_t PROGMEM device_descriptor[] = {
00161 18,
00162 1,
00163 0x00, 0x02,
00164 2,
00165 0,
00166 0,
00167 ENDPOINT0_SIZE,
00168 LSB(VENDOR_ID), MSB(VENDOR_ID),
00169 LSB(PRODUCT_ID), MSB(PRODUCT_ID),
00170 0x00, 0x01,
00171 1,
00172 2,
00173 3,
00174 1
00175 };
00176
00177 #define CONFIG1_DESC_SIZE (9+9+5+5+4+5+7+9+7+7)
00178 static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
00179
00180 9,
00181 2,
00182 LSB(CONFIG1_DESC_SIZE),
00183 MSB(CONFIG1_DESC_SIZE),
00184 2,
00185 1,
00186 0,
00187 0xC0,
00188 50,
00189
00190 9,
00191 4,
00192 0,
00193 0,
00194 1,
00195 0x02,
00196 0x02,
00197 0x01,
00198 0,
00199
00200 5,
00201 0x24,
00202 0x00,
00203 0x10, 0x01,
00204
00205 5,
00206 0x24,
00207 0x01,
00208 0x01,
00209 1,
00210
00211 4,
00212 0x24,
00213 0x02,
00214 0x06,
00215
00216 5,
00217 0x24,
00218 0x06,
00219 0,
00220 1,
00221
00222 7,
00223 5,
00224 CDC_ACM_ENDPOINT | 0x80,
00225 0x03,
00226 CDC_ACM_SIZE, 0,
00227 64,
00228
00229 9,
00230 4,
00231 1,
00232 0,
00233 2,
00234 0x0A,
00235 0x00,
00236 0x00,
00237 0,
00238
00239 7,
00240 5,
00241 CDC_RX_ENDPOINT,
00242 0x02,
00243 CDC_RX_SIZE, 0,
00244 0,
00245
00246 7,
00247 5,
00248 CDC_TX_ENDPOINT | 0x80,
00249 0x02,
00250 CDC_TX_SIZE, 0,
00251 0
00252 };
00253
00254
00255
00256
00257 struct usb_string_descriptor_struct {
00258 uint8_t bLength;
00259 uint8_t bDescriptorType;
00260 int16_t wString[];
00261 };
00262 static struct usb_string_descriptor_struct PROGMEM string0 = {
00263 4,
00264 3,
00265 {0x0409}
00266 };
00267 static struct usb_string_descriptor_struct PROGMEM string1 = {
00268 sizeof(STR_MANUFACTURER),
00269 3,
00270 STR_MANUFACTURER
00271 };
00272 static struct usb_string_descriptor_struct PROGMEM string2 = {
00273 sizeof(STR_PRODUCT),
00274 3,
00275 STR_PRODUCT
00276 };
00277 static struct usb_string_descriptor_struct PROGMEM string3 = {
00278 sizeof(STR_SERIAL_NUMBER),
00279 3,
00280 STR_SERIAL_NUMBER
00281 };
00282
00283
00284
00285 static struct descriptor_list_struct {
00286 uint16_t wValue;
00287 uint16_t wIndex;
00288 const uint8_t *addr;
00289 uint8_t length;
00290 } PROGMEM descriptor_list[] = {
00291 {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
00292 {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
00293 {0x0300, 0x0000, (const uint8_t *)&string0, 4},
00294 {0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)},
00295 {0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)},
00296 {0x0303, 0x0409, (const uint8_t *)&string3, sizeof(STR_SERIAL_NUMBER)}
00297 };
00298 #define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 static volatile uint8_t usb_configuration=0;
00309
00310
00311
00312 static volatile uint8_t transmit_flush_timer=0;
00313 static uint8_t transmit_previous_timeout=0;
00314
00315
00316
00317 static uint8_t cdc_line_coding[7]={0x00, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x08};
00318 static uint8_t cdc_line_rtsdtr=0;
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328 void usb_init(void)
00329 {
00330 HW_CONFIG();
00331 USB_FREEZE();
00332 PLL_CONFIG();
00333 while (!(PLLCSR & (1<<PLOCK))) ;
00334 USB_CONFIG();
00335 UDCON = 0;
00336 usb_configuration = 0;
00337 cdc_line_rtsdtr = 0;
00338 UDIEN = (1<<EORSTE)|(1<<SOFE);
00339 sei();
00340 }
00341
00342
00343
00344 uint8_t usb_configured(void)
00345 {
00346 return usb_configuration;
00347 }
00348
00349
00350 int16_t usb_serial_getchar(void)
00351 {
00352 uint8_t c, intr_state;
00353
00354
00355
00356
00357 intr_state = SREG;
00358 cli();
00359 if (!usb_configuration) {
00360 SREG = intr_state;
00361 return -1;
00362 }
00363 UENUM = CDC_RX_ENDPOINT;
00364 if (!(UEINTX & (1<<RWAL))) {
00365
00366 SREG = intr_state;
00367 return -1;
00368 }
00369
00370 c = UEDATX;
00371
00372 if (!(UEINTX & (1<<RWAL))) UEINTX = 0x6B;
00373 SREG = intr_state;
00374 return c;
00375 }
00376
00377
00378 uint8_t usb_serial_available(void)
00379 {
00380 uint8_t n=0, intr_state;
00381
00382 intr_state = SREG;
00383 cli();
00384 if (usb_configuration) {
00385 UENUM = CDC_RX_ENDPOINT;
00386 n = UEBCLX;
00387 }
00388 SREG = intr_state;
00389 return n;
00390 }
00391
00392
00393 void usb_serial_flush_input(void)
00394 {
00395 uint8_t intr_state;
00396
00397 if (usb_configuration) {
00398 intr_state = SREG;
00399 cli();
00400 UENUM = CDC_RX_ENDPOINT;
00401 while ((UEINTX & (1<<RWAL))) {
00402 UEINTX = 0x6B;
00403 }
00404 SREG = intr_state;
00405 }
00406 }
00407
00408
00409 int8_t usb_serial_putchar(uint8_t c)
00410 {
00411 uint8_t timeout, intr_state;
00412
00413
00414 if (!usb_configuration) return -1;
00415
00416
00417
00418 intr_state = SREG;
00419 cli();
00420 UENUM = CDC_TX_ENDPOINT;
00421
00422 if (transmit_previous_timeout) {
00423 if (!(UEINTX & (1<<RWAL))) {
00424 SREG = intr_state;
00425 return -1;
00426 }
00427 transmit_previous_timeout = 0;
00428 }
00429
00430 timeout = UDFNUML + TRANSMIT_TIMEOUT;
00431 while (1) {
00432
00433 if (UEINTX & (1<<RWAL)) break;
00434 SREG = intr_state;
00435
00436
00437 if (UDFNUML == timeout) {
00438 transmit_previous_timeout = 1;
00439 return -1;
00440 }
00441
00442 if (!usb_configuration) return -1;
00443
00444 intr_state = SREG;
00445 cli();
00446 UENUM = CDC_TX_ENDPOINT;
00447 }
00448
00449 UEDATX = c;
00450
00451 if (!(UEINTX & (1<<RWAL))) UEINTX = 0x3A;
00452 transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
00453 SREG = intr_state;
00454 return 0;
00455 }
00456
00457
00458
00459
00460 int8_t usb_serial_putchar_nowait(uint8_t c)
00461 {
00462 uint8_t intr_state;
00463
00464 if (!usb_configuration) return -1;
00465 intr_state = SREG;
00466 cli();
00467 UENUM = CDC_TX_ENDPOINT;
00468 if (!(UEINTX & (1<<RWAL))) {
00469
00470 SREG = intr_state;
00471 return -1;
00472 }
00473
00474 UEDATX = c;
00475
00476 if (!(UEINTX & (1<<RWAL))) UEINTX = 0x3A;
00477 transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
00478 SREG = intr_state;
00479 return 0;
00480 }
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494 int8_t usb_serial_write(const uint8_t *buffer, uint16_t size)
00495 {
00496 uint8_t timeout, intr_state, write_size;
00497
00498
00499 if (!usb_configuration) return -1;
00500
00501
00502
00503 intr_state = SREG;
00504 cli();
00505 UENUM = CDC_TX_ENDPOINT;
00506
00507 if (transmit_previous_timeout) {
00508 if (!(UEINTX & (1<<RWAL))) {
00509 SREG = intr_state;
00510 return -1;
00511 }
00512 transmit_previous_timeout = 0;
00513 }
00514
00515 while (size) {
00516
00517 timeout = UDFNUML + TRANSMIT_TIMEOUT;
00518 while (1) {
00519
00520 if (UEINTX & (1<<RWAL)) break;
00521 SREG = intr_state;
00522
00523
00524 if (UDFNUML == timeout) {
00525 transmit_previous_timeout = 1;
00526 return -1;
00527 }
00528
00529 if (!usb_configuration) return -1;
00530
00531 intr_state = SREG;
00532 cli();
00533 UENUM = CDC_TX_ENDPOINT;
00534 }
00535
00536
00537 write_size = CDC_TX_SIZE - UEBCLX;
00538 if (write_size > size) write_size = size;
00539 size -= write_size;
00540
00541
00542 switch (write_size) {
00543 #if (CDC_TX_SIZE == 64)
00544 case 64: UEDATX = *buffer++;
00545 case 63: UEDATX = *buffer++;
00546 case 62: UEDATX = *buffer++;
00547 case 61: UEDATX = *buffer++;
00548 case 60: UEDATX = *buffer++;
00549 case 59: UEDATX = *buffer++;
00550 case 58: UEDATX = *buffer++;
00551 case 57: UEDATX = *buffer++;
00552 case 56: UEDATX = *buffer++;
00553 case 55: UEDATX = *buffer++;
00554 case 54: UEDATX = *buffer++;
00555 case 53: UEDATX = *buffer++;
00556 case 52: UEDATX = *buffer++;
00557 case 51: UEDATX = *buffer++;
00558 case 50: UEDATX = *buffer++;
00559 case 49: UEDATX = *buffer++;
00560 case 48: UEDATX = *buffer++;
00561 case 47: UEDATX = *buffer++;
00562 case 46: UEDATX = *buffer++;
00563 case 45: UEDATX = *buffer++;
00564 case 44: UEDATX = *buffer++;
00565 case 43: UEDATX = *buffer++;
00566 case 42: UEDATX = *buffer++;
00567 case 41: UEDATX = *buffer++;
00568 case 40: UEDATX = *buffer++;
00569 case 39: UEDATX = *buffer++;
00570 case 38: UEDATX = *buffer++;
00571 case 37: UEDATX = *buffer++;
00572 case 36: UEDATX = *buffer++;
00573 case 35: UEDATX = *buffer++;
00574 case 34: UEDATX = *buffer++;
00575 case 33: UEDATX = *buffer++;
00576 #endif
00577 #if (CDC_TX_SIZE >= 32)
00578 case 32: UEDATX = *buffer++;
00579 case 31: UEDATX = *buffer++;
00580 case 30: UEDATX = *buffer++;
00581 case 29: UEDATX = *buffer++;
00582 case 28: UEDATX = *buffer++;
00583 case 27: UEDATX = *buffer++;
00584 case 26: UEDATX = *buffer++;
00585 case 25: UEDATX = *buffer++;
00586 case 24: UEDATX = *buffer++;
00587 case 23: UEDATX = *buffer++;
00588 case 22: UEDATX = *buffer++;
00589 case 21: UEDATX = *buffer++;
00590 case 20: UEDATX = *buffer++;
00591 case 19: UEDATX = *buffer++;
00592 case 18: UEDATX = *buffer++;
00593 case 17: UEDATX = *buffer++;
00594 #endif
00595 #if (CDC_TX_SIZE >= 16)
00596 case 16: UEDATX = *buffer++;
00597 case 15: UEDATX = *buffer++;
00598 case 14: UEDATX = *buffer++;
00599 case 13: UEDATX = *buffer++;
00600 case 12: UEDATX = *buffer++;
00601 case 11: UEDATX = *buffer++;
00602 case 10: UEDATX = *buffer++;
00603 case 9: UEDATX = *buffer++;
00604 #endif
00605 case 8: UEDATX = *buffer++;
00606 case 7: UEDATX = *buffer++;
00607 case 6: UEDATX = *buffer++;
00608 case 5: UEDATX = *buffer++;
00609 case 4: UEDATX = *buffer++;
00610 case 3: UEDATX = *buffer++;
00611 case 2: UEDATX = *buffer++;
00612 default:
00613 case 1: UEDATX = *buffer++;
00614 case 0: break;
00615 }
00616
00617 if (!(UEINTX & (1<<RWAL))) UEINTX = 0x3A;
00618 transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
00619 }
00620 SREG = intr_state;
00621 return 0;
00622 }
00623
00624
00625
00626
00627
00628
00629 void usb_serial_flush_output(void)
00630 {
00631 uint8_t intr_state;
00632
00633 intr_state = SREG;
00634 cli();
00635 if (transmit_flush_timer) {
00636 UENUM = CDC_TX_ENDPOINT;
00637 UEINTX = 0x3A;
00638 transmit_flush_timer = 0;
00639 }
00640 SREG = intr_state;
00641 }
00642
00643
00644
00645
00646
00647
00648 uint32_t usb_serial_get_baud(void)
00649 {
00650 return *(uint32_t *)cdc_line_coding;
00651 }
00652 uint8_t usb_serial_get_stopbits(void)
00653 {
00654 return cdc_line_coding[4];
00655 }
00656 uint8_t usb_serial_get_paritytype(void)
00657 {
00658 return cdc_line_coding[5];
00659 }
00660 uint8_t usb_serial_get_numbits(void)
00661 {
00662 return cdc_line_coding[6];
00663 }
00664 uint8_t usb_serial_get_control(void)
00665 {
00666 return cdc_line_rtsdtr;
00667 }
00668
00669
00670
00671
00672
00673
00674
00675
00676 int8_t usb_serial_set_control(uint8_t signals)
00677 {
00678 uint8_t intr_state;
00679
00680 intr_state = SREG;
00681 cli();
00682 if (!usb_configuration) {
00683
00684 SREG = intr_state;
00685 return -1;
00686 }
00687
00688 UENUM = CDC_ACM_ENDPOINT;
00689 if (!(UEINTX & (1<<RWAL))) {
00690
00691
00692
00693 SREG = intr_state;
00694 return -1;
00695 }
00696 UEDATX = 0xA1;
00697 UEDATX = 0x20;
00698 UEDATX = 0;
00699 UEDATX = 0;
00700 UEDATX = 0;
00701 UEDATX = 0;
00702 UEDATX = 2;
00703 UEDATX = 0;
00704 UEDATX = signals;
00705 UEDATX = 0;
00706 UEINTX = 0x3A;
00707 SREG = intr_state;
00708 return 0;
00709 }
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723 ISR(USB_GEN_vect)
00724 {
00725 uint8_t intbits, t;
00726
00727 intbits = UDINT;
00728 UDINT = 0;
00729 if (intbits & (1<<EORSTI)) {
00730 UENUM = 0;
00731 UECONX = 1;
00732 UECFG0X = EP_TYPE_CONTROL;
00733 UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
00734 UEIENX = (1<<RXSTPE);
00735 usb_configuration = 0;
00736 cdc_line_rtsdtr = 0;
00737 }
00738 if (intbits & (1<<SOFI)) {
00739 if (usb_configuration) {
00740 t = transmit_flush_timer;
00741 if (t) {
00742 transmit_flush_timer = --t;
00743 if (!t) {
00744 UENUM = CDC_TX_ENDPOINT;
00745 UEINTX = 0x3A;
00746 }
00747 }
00748 }
00749 }
00750 }
00751
00752
00753
00754 static inline void usb_wait_in_ready(void)
00755 {
00756 while (!(UEINTX & (1<<TXINI))) ;
00757 }
00758 static inline void usb_send_in(void)
00759 {
00760 UEINTX = ~(1<<TXINI);
00761 }
00762 static inline void usb_wait_receive_out(void)
00763 {
00764 while (!(UEINTX & (1<<RXOUTI))) ;
00765 }
00766 static inline void usb_ack_out(void)
00767 {
00768 UEINTX = ~(1<<RXOUTI);
00769 }
00770
00771
00772
00773
00774
00775
00776
00777 ISR(USB_COM_vect)
00778 {
00779 uint8_t intbits;
00780 const uint8_t *list;
00781 const uint8_t *cfg;
00782 uint8_t i, n, len, en;
00783 uint8_t *p;
00784 uint8_t bmRequestType;
00785 uint8_t bRequest;
00786 uint16_t wValue;
00787 uint16_t wIndex;
00788 uint16_t wLength;
00789 uint16_t desc_val;
00790 const uint8_t *desc_addr;
00791 uint8_t desc_length;
00792
00793 UENUM = 0;
00794 intbits = UEINTX;
00795 if (intbits & (1<<RXSTPI)) {
00796 bmRequestType = UEDATX;
00797 bRequest = UEDATX;
00798 wValue = UEDATX;
00799 wValue |= (UEDATX << 8);
00800 wIndex = UEDATX;
00801 wIndex |= (UEDATX << 8);
00802 wLength = UEDATX;
00803 wLength |= (UEDATX << 8);
00804 UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
00805 if (bRequest == GET_DESCRIPTOR) {
00806 list = (const uint8_t *)descriptor_list;
00807 for (i=0; ; i++) {
00808 if (i >= NUM_DESC_LIST) {
00809 UECONX = (1<<STALLRQ)|(1<<EPEN);
00810 return;
00811 }
00812 desc_val = pgm_read_word(list);
00813 if (desc_val != wValue) {
00814 list += sizeof(struct descriptor_list_struct);
00815 continue;
00816 }
00817 list += 2;
00818 desc_val = pgm_read_word(list);
00819 if (desc_val != wIndex) {
00820 list += sizeof(struct descriptor_list_struct)-2;
00821 continue;
00822 }
00823 list += 2;
00824 desc_addr = (const uint8_t *)pgm_read_word(list);
00825 list += 2;
00826 desc_length = pgm_read_byte(list);
00827 break;
00828 }
00829 len = (wLength < 256) ? wLength : 255;
00830 if (len > desc_length) len = desc_length;
00831 do {
00832
00833 do {
00834 i = UEINTX;
00835 } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
00836 if (i & (1<<RXOUTI)) return;
00837
00838 n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
00839 for (i = n; i; i--) {
00840 UEDATX = pgm_read_byte(desc_addr++);
00841 }
00842 len -= n;
00843 usb_send_in();
00844 } while (len || n == ENDPOINT0_SIZE);
00845 return;
00846 }
00847 if (bRequest == SET_ADDRESS) {
00848 usb_send_in();
00849 usb_wait_in_ready();
00850 UDADDR = wValue | (1<<ADDEN);
00851 return;
00852 }
00853 if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
00854 usb_configuration = wValue;
00855 cdc_line_rtsdtr = 0;
00856 transmit_flush_timer = 0;
00857 usb_send_in();
00858 cfg = endpoint_config_table;
00859 for (i=1; i<5; i++) {
00860 UENUM = i;
00861 en = pgm_read_byte(cfg++);
00862 UECONX = en;
00863 if (en) {
00864 UECFG0X = pgm_read_byte(cfg++);
00865 UECFG1X = pgm_read_byte(cfg++);
00866 }
00867 }
00868 UERST = 0x1E;
00869 UERST = 0;
00870 return;
00871 }
00872 if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
00873 usb_wait_in_ready();
00874 UEDATX = usb_configuration;
00875 usb_send_in();
00876 return;
00877 }
00878 if (bRequest == CDC_GET_LINE_CODING && bmRequestType == 0xA1) {
00879 usb_wait_in_ready();
00880 p = cdc_line_coding;
00881 for (i=0; i<7; i++) {
00882 UEDATX = *p++;
00883 }
00884 usb_send_in();
00885 return;
00886 }
00887 if (bRequest == CDC_SET_LINE_CODING && bmRequestType == 0x21) {
00888 usb_wait_receive_out();
00889 p = cdc_line_coding;
00890 for (i=0; i<7; i++) {
00891 *p++ = UEDATX;
00892 }
00893 usb_ack_out();
00894 usb_send_in();
00895 return;
00896 }
00897 if (bRequest == CDC_SET_CONTROL_LINE_STATE && bmRequestType == 0x21) {
00898 cdc_line_rtsdtr = wValue;
00899 usb_wait_in_ready();
00900 usb_send_in();
00901 return;
00902 }
00903 if (bRequest == GET_STATUS) {
00904 usb_wait_in_ready();
00905 i = 0;
00906 #ifdef SUPPORT_ENDPOINT_HALT
00907 if (bmRequestType == 0x82) {
00908 UENUM = wIndex;
00909 if (UECONX & (1<<STALLRQ)) i = 1;
00910 UENUM = 0;
00911 }
00912 #endif
00913 UEDATX = i;
00914 UEDATX = 0;
00915 usb_send_in();
00916 return;
00917 }
00918 #ifdef SUPPORT_ENDPOINT_HALT
00919 if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
00920 && bmRequestType == 0x02 && wValue == 0) {
00921 i = wIndex & 0x7F;
00922 if (i >= 1 && i <= MAX_ENDPOINT) {
00923 usb_send_in();
00924 UENUM = i;
00925 if (bRequest == SET_FEATURE) {
00926 UECONX = (1<<STALLRQ)|(1<<EPEN);
00927 } else {
00928 UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
00929 UERST = (1 << i);
00930 UERST = 0;
00931 }
00932 return;
00933 }
00934 }
00935 #endif
00936 }
00937 UECONX = (1<<STALLRQ) | (1<<EPEN);
00938 }
00939
00940