
cdc2313.elf:     file format elf32-avr

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         000007e6  00000000  00000000  00000094  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00000002  00800060  000007e6  0000087a  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000066  00800062  00800062  0000087c  2**0
                  ALLOC
  3 .stab         000006b4  00000000  00000000  0000087c  2**2
                  CONTENTS, READONLY, DEBUGGING
  4 .stabstr      00000085  00000000  00000000  00000f30  2**0
                  CONTENTS, READONLY, DEBUGGING
  5 .debug_aranges 00000060  00000000  00000000  00000fb8  2**3
                  CONTENTS, READONLY, DEBUGGING
  6 .debug_pubnames 00000222  00000000  00000000  00001018  2**0
                  CONTENTS, READONLY, DEBUGGING
  7 .debug_info   00000f34  00000000  00000000  0000123a  2**0
                  CONTENTS, READONLY, DEBUGGING
  8 .debug_abbrev 000004bc  00000000  00000000  0000216e  2**0
                  CONTENTS, READONLY, DEBUGGING
  9 .debug_line   000009dc  00000000  00000000  0000262a  2**0
                  CONTENTS, READONLY, DEBUGGING
 10 .debug_frame  000000d0  00000000  00000000  00003008  2**2
                  CONTENTS, READONLY, DEBUGGING
 11 .debug_str    00000563  00000000  00000000  000030d8  2**0
                  CONTENTS, READONLY, DEBUGGING
 12 .debug_loc    00000820  00000000  00000000  0000363b  2**0
                  CONTENTS, READONLY, DEBUGGING
 13 .debug_pubtypes 00000113  00000000  00000000  00003e5b  2**0
                  CONTENTS, READONLY, DEBUGGING
 14 .debug_ranges 000000e8  00000000  00000000  00003f6e  2**0
                  CONTENTS, READONLY, DEBUGGING

Disassembly of section .text:

00000000 <__vectors>:
   0:	4e c0       	rjmp	.+156    	; 0x9e <__ctors_end>
   2:	a7 c2       	rjmp	.+1358   	; 0x552 <__vector_1>
   4:	65 c0       	rjmp	.+202    	; 0xd0 <__bad_interrupt>
   6:	64 c0       	rjmp	.+200    	; 0xd0 <__bad_interrupt>
   8:	63 c0       	rjmp	.+198    	; 0xd0 <__bad_interrupt>
   a:	62 c0       	rjmp	.+196    	; 0xd0 <__bad_interrupt>
   c:	61 c0       	rjmp	.+194    	; 0xd0 <__bad_interrupt>
   e:	60 c0       	rjmp	.+192    	; 0xd0 <__bad_interrupt>
  10:	5f c0       	rjmp	.+190    	; 0xd0 <__bad_interrupt>
  12:	5e c0       	rjmp	.+188    	; 0xd0 <__bad_interrupt>
  14:	5d c0       	rjmp	.+186    	; 0xd0 <__bad_interrupt>
  16:	5c c0       	rjmp	.+184    	; 0xd0 <__bad_interrupt>
  18:	5b c0       	rjmp	.+182    	; 0xd0 <__bad_interrupt>
  1a:	5a c0       	rjmp	.+180    	; 0xd0 <__bad_interrupt>
  1c:	59 c0       	rjmp	.+178    	; 0xd0 <__bad_interrupt>
  1e:	58 c0       	rjmp	.+176    	; 0xd0 <__bad_interrupt>
  20:	57 c0       	rjmp	.+174    	; 0xd0 <__bad_interrupt>
  22:	56 c0       	rjmp	.+172    	; 0xd0 <__bad_interrupt>
  24:	55 c0       	rjmp	.+170    	; 0xd0 <__bad_interrupt>

00000026 <configDescrCDC>:
  26:	09 02 43 00 02 01 00 80 32 09 04 00 00 01 02 02     ..C.....2.......
  36:	01 00 05 24 00 10 01 04 24 02 02 05 24 06 00 01     ...$....$...$...
  46:	05 24 01 03 01 07 05 83 03 08 00 ff 09 04 01 00     .$..............
  56:	02 0a 00 00 00 07 05 01 02 08 00 00 07 05 81 02     ................
  66:	08 00 00                                            ...

00000069 <usbDescriptorString0>:
  69:	04 03 09 04                                         ....

0000006d <usbDescriptorStringVendor>:
  6d:	0e 03 6e 00 6f 00 6e 00 61 00 6d 00 65 00           ..n.o.n.a.m.e.

0000007b <usbDescriptorStringDevice>:
  7b:	10 03 55 00 53 00 42 00 2d 00 32 00 33 00 32 00     ..U.S.B.-.2.3.2.

0000008b <usbDescriptorDevice>:
  8b:	12 01 10 01 02 00 00 08 c0 16 e1 05 00 01 01 02     ................
  9b:	00 01 00                                            ...

0000009e <__ctors_end>:
  9e:	11 24       	eor	r1, r1
  a0:	1f be       	out	0x3f, r1	; 63
  a2:	cf ed       	ldi	r28, 0xDF	; 223
  a4:	cd bf       	out	0x3d, r28	; 61

000000a6 <__do_copy_data>:
  a6:	10 e0       	ldi	r17, 0x00	; 0
  a8:	a0 e6       	ldi	r26, 0x60	; 96
  aa:	b0 e0       	ldi	r27, 0x00	; 0
  ac:	e6 ee       	ldi	r30, 0xE6	; 230
  ae:	f7 e0       	ldi	r31, 0x07	; 7
  b0:	02 c0       	rjmp	.+4      	; 0xb6 <__do_copy_data+0x10>
  b2:	05 90       	lpm	r0, Z+
  b4:	0d 92       	st	X+, r0
  b6:	a2 36       	cpi	r26, 0x62	; 98
  b8:	b1 07       	cpc	r27, r17
  ba:	d9 f7       	brne	.-10     	; 0xb2 <__do_copy_data+0xc>

000000bc <__do_clear_bss>:
  bc:	10 e0       	ldi	r17, 0x00	; 0
  be:	a2 e6       	ldi	r26, 0x62	; 98
  c0:	b0 e0       	ldi	r27, 0x00	; 0
  c2:	01 c0       	rjmp	.+2      	; 0xc6 <.do_clear_bss_start>

000000c4 <.do_clear_bss_loop>:
  c4:	1d 92       	st	X+, r1

000000c6 <.do_clear_bss_start>:
  c6:	a8 3c       	cpi	r26, 0xC8	; 200
  c8:	b1 07       	cpc	r27, r17
  ca:	e1 f7       	brne	.-8      	; 0xc4 <.do_clear_bss_loop>
  cc:	6a d0       	rcall	.+212    	; 0x1a2 <main>
  ce:	89 c3       	rjmp	.+1810   	; 0x7e2 <_exit>

000000d0 <__bad_interrupt>:
  d0:	97 cf       	rjmp	.-210    	; 0x0 <__vectors>

000000d2 <usbFunctionDescriptor>:


uchar usbFunctionDescriptor(usbRequest_t *rq)
{

    if(rq->wValue.bytes[1] == USBDESCR_DEVICE){
  d2:	fc 01       	movw	r30, r24
  d4:	83 81       	ldd	r24, Z+3	; 0x03
  d6:	81 30       	cpi	r24, 0x01	; 1
  d8:	49 f4       	brne	.+18     	; 0xec <__stack+0xd>
        usbMsgPtr = (uchar *)usbDescriptorDevice;
  da:	8b e8       	ldi	r24, 0x8B	; 139
  dc:	90 e0       	ldi	r25, 0x00	; 0
  de:	90 93 a1 00 	sts	0x00A1, r25
  e2:	80 93 a0 00 	sts	0x00A0, r24
        return usbDescriptorDevice[0];
  e6:	80 91 8b 00 	lds	r24, 0x008B
  ea:	08 95       	ret
    }else{  /* must be config descriptor */
        usbMsgPtr = (uchar *)configDescrCDC;
  ec:	86 e2       	ldi	r24, 0x26	; 38
  ee:	90 e0       	ldi	r25, 0x00	; 0
  f0:	90 93 a1 00 	sts	0x00A1, r25
  f4:	80 93 a0 00 	sts	0x00A0, r24
        return sizeof(configDescrCDC);
  f8:	83 e4       	ldi	r24, 0x43	; 67
    }
}
  fa:	08 95       	ret

000000fc <usbFunctionSetup>:
static uchar    sendEmptyFrame;
static uchar    modeBuffer[7];

uchar usbFunctionSetup(uchar data[8])
{
usbRequest_t    *rq = (void *)data;
  fc:	fc 01       	movw	r30, r24

    if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){    /* class request type */
  fe:	80 81       	ld	r24, Z
 100:	80 76       	andi	r24, 0x60	; 96
 102:	80 32       	cpi	r24, 0x20	; 32
 104:	21 f4       	brne	.+8      	; 0x10e <usbFunctionSetup+0x12>

        if( rq->bRequest==GET_LINE_CODING || rq->bRequest==SET_LINE_CODING ){
 106:	81 81       	ldd	r24, Z+1	; 0x01
 108:	80 52       	subi	r24, 0x20	; 32
 10a:	82 30       	cpi	r24, 0x02	; 2
 10c:	10 f0       	brcs	.+4      	; 0x112 <usbFunctionSetup+0x16>
        if(rq->bRequest==SET_CONTROL_LINE_STATE){
            UART_CTRL_PORT	= (UART_CTRL_PORT&~(1<<UART_CTRL_DTR))|((rq->wValue.word&1)<<UART_CTRL_DTR);
        }
#endif
    }
    return 0;
 10e:	80 e0       	ldi	r24, 0x00	; 0
 110:	08 95       	ret
usbRequest_t    *rq = (void *)data;

    if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){    /* class request type */

        if( rq->bRequest==GET_LINE_CODING || rq->bRequest==SET_LINE_CODING ){
            return 0xff;
 112:	8f ef       	ldi	r24, 0xFF	; 255
            UART_CTRL_PORT	= (UART_CTRL_PORT&~(1<<UART_CTRL_DTR))|((rq->wValue.word&1)<<UART_CTRL_DTR);
        }
#endif
    }
    return 0;
}
 114:	08 95       	ret

00000116 <usbFunctionRead>:
/* usbFunctionRead -  GET_LINE_CODING                                       */
/*---------------------------------------------------------------------------*/

uchar usbFunctionRead( uchar *data, uchar len )
{
    memcpy( data, modeBuffer, 7 );
 116:	28 2f       	mov	r18, r24
 118:	39 2f       	mov	r19, r25
 11a:	d9 01       	movw	r26, r18
 11c:	ee e7       	ldi	r30, 0x7E	; 126
 11e:	f0 e0       	ldi	r31, 0x00	; 0
 120:	87 e0       	ldi	r24, 0x07	; 7
 122:	01 90       	ld	r0, Z+
 124:	0d 92       	st	X+, r0
 126:	81 50       	subi	r24, 0x01	; 1
 128:	e1 f7       	brne	.-8      	; 0x122 <usbFunctionRead+0xc>
    return 7;
}
 12a:	87 e0       	ldi	r24, 0x07	; 7
 12c:	08 95       	ret

0000012e <usbFunctionWrite>:
#define	BRMAX	38400
#define	BSTEP	((F_CPU>>3)/BRMAX)
#define	BRVAL	((unsigned)BSTEP*BRMAX/BRMIN)

uchar usbFunctionWrite( uchar *data, uchar len )
{
 12e:	fc 01       	movw	r30, r24
	usbWord_t	br;
	unsigned 	baudrate;
	uchar		i;

	//	set baudrate generator
	baudrate	= *(unsigned *)data;
 130:	20 81       	ld	r18, Z
 132:	31 81       	ldd	r19, Z+1	; 0x01
	for( i=0; baudrate>=BRMIN; i++ )
 134:	80 e0       	ldi	r24, 0x00	; 0
 136:	03 c0       	rjmp	.+6      	; 0x13e <usbFunctionWrite+0x10>
		baudrate	-= BRMIN;
 138:	28 55       	subi	r18, 0x58	; 88
 13a:	32 40       	sbci	r19, 0x02	; 2
	unsigned 	baudrate;
	uchar		i;

	//	set baudrate generator
	baudrate	= *(unsigned *)data;
	for( i=0; baudrate>=BRMIN; i++ )
 13c:	8f 5f       	subi	r24, 0xFF	; 255
 13e:	92 e0       	ldi	r25, 0x02	; 2
 140:	28 35       	cpi	r18, 0x58	; 88
 142:	39 07       	cpc	r19, r25
 144:	c8 f7       	brcc	.-14     	; 0x138 <usbFunctionWrite+0xa>
 146:	20 ec       	ldi	r18, 0xC0	; 192
 148:	39 e0       	ldi	r19, 0x09	; 9
 14a:	03 c0       	rjmp	.+6      	; 0x152 <usbFunctionWrite+0x24>
		baudrate	-= BRMIN;
	for( br.word=BRVAL; i>1; i>>=1 )
		br.word	>>= 1;
 14c:	36 95       	lsr	r19
 14e:	27 95       	ror	r18

	//	set baudrate generator
	baudrate	= *(unsigned *)data;
	for( i=0; baudrate>=BRMIN; i++ )
		baudrate	-= BRMIN;
	for( br.word=BRVAL; i>1; i>>=1 )
 150:	86 95       	lsr	r24
 152:	82 30       	cpi	r24, 0x02	; 2
 154:	d8 f7       	brcc	.-10     	; 0x14c <usbFunctionWrite+0x1e>
		br.word	>>= 1;
	br.word--;
 156:	21 50       	subi	r18, 0x01	; 1
 158:	30 40       	sbci	r19, 0x00	; 0

#ifdef _AVR_IO2313_H_
    UBRRL	= br.bytes[0] << 1;
#else
    UBRRL	= br.bytes[0];
 15a:	29 b9       	out	0x09, r18	; 9
    UBRRH   = br.bytes[1];
 15c:	32 b9       	out	0x02, r19	; 2
    UCSRA   = (1<<U2X);
 15e:	82 e0       	ldi	r24, 0x02	; 2
 160:	8b b9       	out	0x0b, r24	; 11
#endif
    UCSRB	= (1<<RXEN) | (1<<TXEN);
 162:	88 e1       	ldi	r24, 0x18	; 24
 164:	8a b9       	out	0x0a, r24	; 10

    memcpy( modeBuffer, data, 7 );
 166:	ae e7       	ldi	r26, 0x7E	; 126
 168:	b0 e0       	ldi	r27, 0x00	; 0
 16a:	87 e0       	ldi	r24, 0x07	; 7
 16c:	01 90       	ld	r0, Z+
 16e:	0d 92       	st	X+, r0
 170:	81 50       	subi	r24, 0x01	; 1
 172:	e1 f7       	brne	.-8      	; 0x16c <usbFunctionWrite+0x3e>
    return 1;
}
 174:	81 e0       	ldi	r24, 0x01	; 1
 176:	08 95       	ret

00000178 <usbFunctionWriteOut>:

static uchar    iwptr, uwptr, irptr;
static uchar    rx_buf[RX_SIZE], tx_buf[TX_SIZE];

void usbFunctionWriteOut( uchar *data, uchar len )
{
 178:	fc 01       	movw	r30, r24
 17a:	80 91 62 00 	lds	r24, 0x0062

    /*  usb -> rs232c:  transmit char    */
    for( ; len; len-- ) {
 17e:	09 c0       	rjmp	.+18     	; 0x192 <usbFunctionWriteOut+0x1a>
        tx_buf[uwptr++] = *data++;
 180:	a8 2f       	mov	r26, r24
 182:	b0 e0       	ldi	r27, 0x00	; 0
 184:	ac 59       	subi	r26, 0x9C	; 156
 186:	bf 4f       	sbci	r27, 0xFF	; 255
 188:	91 91       	ld	r25, Z+
 18a:	9c 93       	st	X, r25
 18c:	8f 5f       	subi	r24, 0xFF	; 255
        uwptr	&= TX_MASK;
 18e:	8f 70       	andi	r24, 0x0F	; 15

void usbFunctionWriteOut( uchar *data, uchar len )
{

    /*  usb -> rs232c:  transmit char    */
    for( ; len; len-- ) {
 190:	61 50       	subi	r22, 0x01	; 1
 192:	66 23       	and	r22, r22
 194:	a9 f7       	brne	.-22     	; 0x180 <usbFunctionWriteOut+0x8>
 196:	80 93 62 00 	sts	0x0062, r24
        tx_buf[uwptr++] = *data++;
        uwptr	&= TX_MASK;
    }

    /*  postpone receiving next data    */
   	usbDisableAllRequests();
 19a:	8f ef       	ldi	r24, 0xFF	; 255
 19c:	80 93 a2 00 	sts	0x00A2, r24
}
 1a0:	08 95       	ret

000001a2 <main>:
{
unsigned	i;
uchar		j;

    /* activate pull-ups except on USB lines */
    USB_CFG_IOPORT   = (uchar)~((1<<USB_CFG_DMINUS_BIT)|(1<<USB_CFG_DPLUS_BIT));
 1a2:	83 ef       	ldi	r24, 0xF3	; 243
 1a4:	82 bb       	out	0x12, r24	; 18
    /* all pins input except USB (-> USB reset) */
#ifdef USB_CFG_PULLUP_IOPORT    /* use usbDeviceConnect()/usbDeviceDisconnect() if available */
    USBDDR    = 0;    /* we do RESET by deactivating pullup */
    usbDeviceDisconnect();
#else
    USBDDR    = (1<<USB_CFG_DMINUS_BIT)|(1<<USB_CFG_DPLUS_BIT);
 1a6:	8c e0       	ldi	r24, 0x0C	; 12
 1a8:	81 bb       	out	0x11, r24	; 17
 1aa:	8f e0       	ldi	r24, 0x0F	; 15
 1ac:	01 c0       	rjmp	.+2      	; 0x1b0 <main+0xe>

    j = 15;
    while(--j){          /* USB Reset by device only required on Watchdog Reset */
        i = 0;
        while(--i);
            wdt_reset();
 1ae:	a8 95       	wdr
 1b0:	81 50       	subi	r24, 0x01	; 1
#else
    USBDDR    = (1<<USB_CFG_DMINUS_BIT)|(1<<USB_CFG_DPLUS_BIT);
#endif

    j = 15;
    while(--j){          /* USB Reset by device only required on Watchdog Reset */
 1b2:	e9 f7       	brne	.-6      	; 0x1ae <main+0xc>
    }

#ifdef USB_CFG_PULLUP_IOPORT
    usbDeviceConnect();
#else
    USBDDR    = 0;      /*  remove USB reset condition */
 1b4:	11 ba       	out	0x11, r1	; 17
#endif

	PORTB	= 0xff;
 1b6:	8f ef       	ldi	r24, 0xFF	; 255
 1b8:	88 bb       	out	0x18, r24	; 24

int main(void)
{
    odDebugInit();
    hardwareInit();
    usbInit();
 1ba:	a1 d1       	rcall	.+834    	; 0x4fe <usbInit>

    sei();
 1bc:	78 94       	sei
    for(;;){    /* main event loop */
        wdt_reset();
 1be:	a8 95       	wdr
        usbPoll();
 1c0:	75 d0       	rcall	.+234    	; 0x2ac <usbPoll>

        /*    host => device    */
        if( (UCSRA&(1<<UDRE)) && uwptr!=irptr
 1c2:	5d 9b       	sbis	0x0b, 5	; 11
 1c4:	10 c0       	rjmp	.+32     	; 0x1e6 <main+0x44>
 1c6:	80 91 63 00 	lds	r24, 0x0063
 1ca:	90 91 62 00 	lds	r25, 0x0062
 1ce:	98 17       	cp	r25, r24
 1d0:	51 f0       	breq	.+20     	; 0x1e6 <main+0x44>
#ifdef USE_UART_CTRL
		&& (UART_CTRL_PIN&(1<<UART_CTRL_CTS))
#endif
		) {
            UDR		= tx_buf[irptr++];
 1d2:	e8 2f       	mov	r30, r24
 1d4:	f0 e0       	ldi	r31, 0x00	; 0
 1d6:	ec 59       	subi	r30, 0x9C	; 156
 1d8:	ff 4f       	sbci	r31, 0xFF	; 255
 1da:	90 81       	ld	r25, Z
 1dc:	9c b9       	out	0x0c, r25	; 12
 1de:	8f 5f       	subi	r24, 0xFF	; 255
            irptr   &= TX_MASK;
 1e0:	8f 70       	andi	r24, 0x0F	; 15
 1e2:	80 93 63 00 	sts	0x0063, r24
        }
        if( usbAllRequestsAreDisabled() &&
 1e6:	80 91 a2 00 	lds	r24, 0x00A2
 1ea:	87 ff       	sbrs	r24, 7
 1ec:	0e c0       	rjmp	.+28     	; 0x20a <main+0x68>
            ((uwptr-irptr)&TX_MASK)<(TX_SIZE-HW_CDC_BULK_OUT_SIZE) ) {
 1ee:	80 91 62 00 	lds	r24, 0x0062
 1f2:	90 e0       	ldi	r25, 0x00	; 0
 1f4:	20 91 63 00 	lds	r18, 0x0063
 1f8:	82 1b       	sub	r24, r18
 1fa:	91 09       	sbc	r25, r1
 1fc:	8f 70       	andi	r24, 0x0F	; 15
 1fe:	90 70       	andi	r25, 0x00	; 0
#endif
		) {
            UDR		= tx_buf[irptr++];
            irptr   &= TX_MASK;
        }
        if( usbAllRequestsAreDisabled() &&
 200:	88 30       	cpi	r24, 0x08	; 8
 202:	91 05       	cpc	r25, r1
 204:	14 f4       	brge	.+4      	; 0x20a <main+0x68>
            ((uwptr-irptr)&TX_MASK)<(TX_SIZE-HW_CDC_BULK_OUT_SIZE) ) {
            usbEnableAllRequests();
 206:	10 92 a2 00 	sts	0x00A2, r1
        }

        /*    host <= device    */
        if( UCSRA&(1<<RXC) && iwptr<HW_CDC_BULK_IN_SIZE ) {
 20a:	5f 9b       	sbis	0x0b, 7	; 11
 20c:	0d c0       	rjmp	.+26     	; 0x228 <main+0x86>
 20e:	80 91 74 00 	lds	r24, 0x0074
 212:	88 30       	cpi	r24, 0x08	; 8
 214:	48 f4       	brcc	.+18     	; 0x228 <main+0x86>
            rx_buf[iwptr++]	= UDR;
 216:	9c b1       	in	r25, 0x0c	; 12
 218:	e8 2f       	mov	r30, r24
 21a:	f0 e0       	ldi	r31, 0x00	; 0
 21c:	eb 58       	subi	r30, 0x8B	; 139
 21e:	ff 4f       	sbci	r31, 0xFF	; 255
 220:	90 83       	st	Z, r25
 222:	8f 5f       	subi	r24, 0xFF	; 255
 224:	80 93 74 00 	sts	0x0074, r24
#ifdef USE_UART_CTRL
			if( iwptr==HW_CDC_BULK_IN_SIZE )
				UART_CTRL_PORT &= ~(1<<UART_CTRL_RTS);
#endif
        }
        if( usbInterruptIsReady() && (iwptr||sendEmptyFrame) ) {
 228:	80 91 91 00 	lds	r24, 0x0091
 22c:	84 ff       	sbrs	r24, 4
 22e:	c7 cf       	rjmp	.-114    	; 0x1be <main+0x1c>
 230:	60 91 74 00 	lds	r22, 0x0074
 234:	66 23       	and	r22, r22
 236:	29 f4       	brne	.+10     	; 0x242 <main+0xa0>
 238:	80 91 7d 00 	lds	r24, 0x007D
 23c:	88 23       	and	r24, r24
 23e:	09 f4       	brne	.+2      	; 0x242 <main+0xa0>
 240:	be cf       	rjmp	.-132    	; 0x1be <main+0x1c>
            usbSetInterrupt(rx_buf, iwptr);
 242:	85 e7       	ldi	r24, 0x75	; 117
 244:	90 e0       	ldi	r25, 0x00	; 0
 246:	2a d0       	rcall	.+84     	; 0x29c <usbSetInterrupt>
            sendEmptyFrame	= iwptr & HW_CDC_BULK_IN_SIZE;
 248:	80 91 74 00 	lds	r24, 0x0074
 24c:	88 70       	andi	r24, 0x08	; 8
 24e:	80 93 7d 00 	sts	0x007D, r24
            iwptr    = 0;
 252:	10 92 74 00 	sts	0x0074, r1
 256:	b3 cf       	rjmp	.-154    	; 0x1be <main+0x1c>

00000258 <usbGenericSetInterrupt>:
/* ------------------------------------------------------------------------- */

#if !USB_CFG_SUPPRESS_INTR_CODE
#if USB_CFG_HAVE_INTRIN_ENDPOINT
static void usbGenericSetInterrupt(uchar *data, uchar len, usbTxStatus_t *txStatus)
{
 258:	1f 93       	push	r17
 25a:	cf 93       	push	r28
 25c:	df 93       	push	r29
 25e:	9c 01       	movw	r18, r24
 260:	16 2f       	mov	r17, r22
 262:	ea 01       	movw	r28, r20

#if USB_CFG_IMPLEMENT_HALT
    if(usbTxLen1 == USBPID_STALL)
        return;
#endif
    if(txStatus->len & 0x10){   /* packet buffer was empty */
 264:	88 81       	ld	r24, Y
 266:	84 ff       	sbrs	r24, 4
 268:	05 c0       	rjmp	.+10     	; 0x274 <usbGenericSetInterrupt+0x1c>
        txStatus->buffer[0] ^= USBPID_DATA0 ^ USBPID_DATA1; /* toggle token */
 26a:	89 81       	ldd	r24, Y+1	; 0x01
 26c:	98 e8       	ldi	r25, 0x88	; 136
 26e:	89 27       	eor	r24, r25
 270:	89 83       	std	Y+1, r24	; 0x01
 272:	02 c0       	rjmp	.+4      	; 0x278 <usbGenericSetInterrupt+0x20>
    }else{
        txStatus->len = USBPID_NAK; /* avoid sending outdated (overwritten) interrupt data */
 274:	8a e5       	ldi	r24, 0x5A	; 90
 276:	88 83       	st	Y, r24
    }
    p = txStatus->buffer + 1;
 278:	ce 01       	movw	r24, r28
 27a:	02 96       	adiw	r24, 0x02	; 2
    i = len;
 27c:	41 2f       	mov	r20, r17
 27e:	d9 01       	movw	r26, r18
    if(txStatus->len & 0x10){   /* packet buffer was empty */
        txStatus->buffer[0] ^= USBPID_DATA0 ^ USBPID_DATA1; /* toggle token */
    }else{
        txStatus->len = USBPID_NAK; /* avoid sending outdated (overwritten) interrupt data */
    }
    p = txStatus->buffer + 1;
 280:	fc 01       	movw	r30, r24
    i = len;
    do{                         /* if len == 0, we still copy 1 byte, but that's no problem */
        *p++ = *data++;
 282:	2d 91       	ld	r18, X+
 284:	21 93       	st	Z+, r18
    }while(--i > 0);            /* loop control at the end is 2 bytes shorter than at beginning */
 286:	41 50       	subi	r20, 0x01	; 1
 288:	14 16       	cp	r1, r20
 28a:	dc f3       	brlt	.-10     	; 0x282 <usbGenericSetInterrupt+0x2a>
    usbCrc16Append(&txStatus->buffer[1], len);
 28c:	61 2f       	mov	r22, r17
 28e:	5d d1       	rcall	.+698    	; 0x54a <usbCrc16Append>
    txStatus->len = len + 4;    /* len must be given including sync byte */
 290:	1c 5f       	subi	r17, 0xFC	; 252
 292:	18 83       	st	Y, r17
    DBG2(0x21 + (((int)txStatus >> 3) & 3), txStatus->buffer, len + 3);
}
 294:	df 91       	pop	r29
 296:	cf 91       	pop	r28
 298:	1f 91       	pop	r17
 29a:	08 95       	ret

0000029c <usbSetInterrupt>:

USB_PUBLIC void usbSetInterrupt(uchar *data, uchar len)
{
    usbGenericSetInterrupt(data, len, &usbTxStatus1);
 29c:	41 e9       	ldi	r20, 0x91	; 145
 29e:	50 e0       	ldi	r21, 0x00	; 0
 2a0:	db df       	rcall	.-74     	; 0x258 <usbGenericSetInterrupt>
}
 2a2:	08 95       	ret

000002a4 <usbSetInterrupt3>:
#endif

#if USB_CFG_HAVE_INTRIN_ENDPOINT3
USB_PUBLIC void usbSetInterrupt3(uchar *data, uchar len)
{
    usbGenericSetInterrupt(data, len, &usbTxStatus3);
 2a4:	4c eb       	ldi	r20, 0xBC	; 188
 2a6:	50 e0       	ldi	r21, 0x00	; 0
 2a8:	d7 df       	rcall	.-82     	; 0x258 <usbGenericSetInterrupt>
}
 2aa:	08 95       	ret

000002ac <usbPoll>:
}

/* ------------------------------------------------------------------------- */

USB_PUBLIC void usbPoll(void)
{
 2ac:	1f 93       	push	r17
 2ae:	cf 93       	push	r28
 2b0:	df 93       	push	r29
schar   len;
uchar   i;

    len = usbRxLen - 3;
 2b2:	60 91 a2 00 	lds	r22, 0x00A2
 2b6:	63 50       	subi	r22, 0x03	; 3
    if(len >= 0){
 2b8:	67 fd       	sbrc	r22, 7
 2ba:	b4 c0       	rjmp	.+360    	; 0x424 <usbPoll+0x178>
 * need data integrity checks with this driver, check the CRC in your app
 * code and report errors back to the host. Since the ACK was already sent,
 * retries must be handled on application level.
 * unsigned crc = usbCrc16(buffer + 1, usbRxLen - 3);
 */
        usbProcessRx(usbRxBuf + USB_BUFSIZE + 1 - usbInputBufOffset, len);
 2bc:	80 91 9f 00 	lds	r24, 0x009F
 2c0:	cc e0       	ldi	r28, 0x0C	; 12
 2c2:	d0 e0       	ldi	r29, 0x00	; 0
 2c4:	c8 1b       	sub	r28, r24
 2c6:	d1 09       	sbc	r29, r1
 2c8:	ca 55       	subi	r28, 0x5A	; 90
 2ca:	df 4f       	sbci	r29, 0xFF	; 255
 * 0...0x0f for OUT on endpoint X
 */
    DBG2(0x10 + (usbRxToken & 0xf), data, len + 2); /* SETUP=1d, SETUP-DATA=11, OUTx=1x */
    USB_RX_USER_HOOK(data, len)
#if USB_CFG_IMPLEMENT_FN_WRITEOUT
    if(usbRxToken < 0x10){  /* OUT to endpoint != 0: endpoint number in usbRxToken */
 2cc:	80 91 9e 00 	lds	r24, 0x009E
 2d0:	80 31       	cpi	r24, 0x10	; 16
 2d2:	18 f4       	brcc	.+6      	; 0x2da <usbPoll+0x2e>
        usbFunctionWriteOut(data, len);
 2d4:	ce 01       	movw	r24, r28
 2d6:	50 df       	rcall	.-352    	; 0x178 <usbFunctionWriteOut>
 2d8:	9f c0       	rjmp	.+318    	; 0x418 <usbPoll+0x16c>
        return;
    }
#endif
    if(usbRxToken == (uchar)USBPID_SETUP){
 2da:	8d 32       	cpi	r24, 0x2D	; 45
 2dc:	09 f0       	breq	.+2      	; 0x2e0 <usbPoll+0x34>
 2de:	8c c0       	rjmp	.+280    	; 0x3f8 <usbPoll+0x14c>
        if(len != 8)    /* Setup size must be always 8 bytes. Ignore otherwise. */
 2e0:	68 30       	cpi	r22, 0x08	; 8
 2e2:	09 f0       	breq	.+2      	; 0x2e6 <usbPoll+0x3a>
 2e4:	99 c0       	rjmp	.+306    	; 0x418 <usbPoll+0x16c>
            return;
        usbMsgLen_t replyLen;
        usbTxBuf[0] = USBPID_DATA0;         /* initialize data toggling */
 2e6:	83 ec       	ldi	r24, 0xC3	; 195
 2e8:	80 93 86 00 	sts	0x0086, r24
        usbTxLen = USBPID_NAK;              /* abort pending transmit */
 2ec:	8a e5       	ldi	r24, 0x5A	; 90
 2ee:	80 93 60 00 	sts	0x0060, r24
        usbMsgFlags = 0;
 2f2:	10 92 85 00 	sts	0x0085, r1
        uchar type = rq->bmRequestType & USBRQ_TYPE_MASK;
 2f6:	88 81       	ld	r24, Y
 2f8:	80 76       	andi	r24, 0x60	; 96
        if(type != USBRQ_TYPE_STANDARD){    /* standard requests are handled by driver */
 2fa:	19 f0       	breq	.+6      	; 0x302 <usbPoll+0x56>
            replyLen = usbFunctionSetup(data);
 2fc:	ce 01       	movw	r24, r28
 2fe:	fe de       	rcall	.-516    	; 0xfc <usbFunctionSetup>
 300:	68 c0       	rjmp	.+208    	; 0x3d2 <usbPoll+0x126>
 * standard requests instead of class and custom requests.
 */
static inline usbMsgLen_t usbDriverSetup(usbRequest_t *rq)
{
uchar   len  = 0, *dataPtr = usbTxBuf + 9;  /* there are 2 bytes free space at the end of the buffer */
uchar   value = rq->wValue.bytes[0];
 302:	9a 81       	ldd	r25, Y+2	; 0x02
#if USB_CFG_IMPLEMENT_HALT
uchar   index = rq->wIndex.bytes[0];
#endif

    dataPtr[0] = 0; /* default reply common to USBRQ_GET_STATUS and USBRQ_GET_INTERFACE */
 304:	10 92 8f 00 	sts	0x008F, r1
    SWITCH_START(rq->bRequest)
 308:	89 81       	ldd	r24, Y+1	; 0x01
    SWITCH_CASE(USBRQ_GET_STATUS)           /* 0 */
 30a:	88 23       	and	r24, r24
 30c:	31 f4       	brne	.+12     	; 0x31a <usbPoll+0x6e>
            dataPtr[0] =  USB_CFG_IS_SELF_POWERED;
#if USB_CFG_IMPLEMENT_HALT
        if(recipient == USBRQ_RCPT_ENDPOINT && index == 0x81)   /* request status for endpoint 1 */
            dataPtr[0] = usbTxLen1 == USBPID_STALL;
#endif
        dataPtr[1] = 0;
 30e:	10 92 90 00 	sts	0x0090, r1
/* usbDriverSetup() is similar to usbFunctionSetup(), but it's used for
 * standard requests instead of class and custom requests.
 */
static inline usbMsgLen_t usbDriverSetup(usbRequest_t *rq)
{
uchar   len  = 0, *dataPtr = usbTxBuf + 9;  /* there are 2 bytes free space at the end of the buffer */
 312:	2f e8       	ldi	r18, 0x8F	; 143
 314:	30 e0       	ldi	r19, 0x00	; 0
#if USB_CFG_IMPLEMENT_HALT
        if(recipient == USBRQ_RCPT_ENDPOINT && index == 0x81)   /* request status for endpoint 1 */
            dataPtr[0] = usbTxLen1 == USBPID_STALL;
#endif
        dataPtr[1] = 0;
        len = 2;
 316:	82 e0       	ldi	r24, 0x02	; 2
 318:	57 c0       	rjmp	.+174    	; 0x3c8 <usbPoll+0x11c>
        if(value == 0 && index == 0x81){    /* feature 0 == HALT for endpoint == 1 */
            usbTxLen1 = rq->bRequest == USBRQ_CLEAR_FEATURE ? USBPID_NAK : USBPID_STALL;
            usbResetDataToggling();
        }
#endif
    SWITCH_CASE(USBRQ_SET_ADDRESS)          /* 5 */
 31a:	85 30       	cpi	r24, 0x05	; 5
 31c:	19 f4       	brne	.+6      	; 0x324 <usbPoll+0x78>
        usbNewDeviceAddr = value;
 31e:	90 93 a3 00 	sts	0x00A3, r25
 322:	4f c0       	rjmp	.+158    	; 0x3c2 <usbPoll+0x116>
        USB_SET_ADDRESS_HOOK();
    SWITCH_CASE(USBRQ_GET_DESCRIPTOR)       /* 6 */
 324:	86 30       	cpi	r24, 0x06	; 6
 326:	a9 f5       	brne	.+106    	; 0x392 <usbPoll+0xe6>
static inline usbMsgLen_t usbDriverDescriptor(usbRequest_t *rq)
{
usbMsgLen_t len = 0;
uchar       flags = USB_FLG_MSGPTR_IS_ROM;

    SWITCH_START(rq->wValue.bytes[1])
 328:	8b 81       	ldd	r24, Y+3	; 0x03
    SWITCH_CASE(USBDESCR_DEVICE)    /* 1 */
 32a:	81 30       	cpi	r24, 0x01	; 1
 32c:	41 f4       	brne	.+16     	; 0x33e <usbPoll+0x92>
        GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_DEVICE, usbDescriptorDevice)
 32e:	8b e8       	ldi	r24, 0x8B	; 139
 330:	90 e0       	ldi	r25, 0x00	; 0
 332:	90 93 a1 00 	sts	0x00A1, r25
 336:	80 93 a0 00 	sts	0x00A0, r24
 33a:	82 e1       	ldi	r24, 0x12	; 18
 33c:	26 c0       	rjmp	.+76     	; 0x38a <usbPoll+0xde>
    SWITCH_CASE(USBDESCR_CONFIG)    /* 2 */
 33e:	82 30       	cpi	r24, 0x02	; 2
 340:	19 f4       	brne	.+6      	; 0x348 <usbPoll+0x9c>
        GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_CONFIGURATION, usbDescriptorConfiguration)
 342:	ce 01       	movw	r24, r28
 344:	c6 de       	rcall	.-628    	; 0xd2 <usbFunctionDescriptor>
 346:	21 c0       	rjmp	.+66     	; 0x38a <usbPoll+0xde>
    SWITCH_CASE(USBDESCR_STRING)    /* 3 */
 348:	83 30       	cpi	r24, 0x03	; 3
 34a:	f1 f4       	brne	.+60     	; 0x388 <usbPoll+0xdc>
        if(USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_RAM)
            flags = 0;
        len = usbFunctionDescriptor(rq);
#else   /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */
        SWITCH_START(rq->wValue.bytes[0])
        SWITCH_CASE(0)
 34c:	99 23       	and	r25, r25
 34e:	41 f4       	brne	.+16     	; 0x360 <usbPoll+0xb4>
            GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_0, usbDescriptorString0)
 350:	89 e6       	ldi	r24, 0x69	; 105
 352:	90 e0       	ldi	r25, 0x00	; 0
 354:	90 93 a1 00 	sts	0x00A1, r25
 358:	80 93 a0 00 	sts	0x00A0, r24
 35c:	84 e0       	ldi	r24, 0x04	; 4
 35e:	15 c0       	rjmp	.+42     	; 0x38a <usbPoll+0xde>
        SWITCH_CASE(1)
 360:	91 30       	cpi	r25, 0x01	; 1
 362:	41 f4       	brne	.+16     	; 0x374 <usbPoll+0xc8>
            GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_VENDOR, usbDescriptorStringVendor)
 364:	8d e6       	ldi	r24, 0x6D	; 109
 366:	90 e0       	ldi	r25, 0x00	; 0
 368:	90 93 a1 00 	sts	0x00A1, r25
 36c:	80 93 a0 00 	sts	0x00A0, r24
 370:	8e e0       	ldi	r24, 0x0E	; 14
 372:	0b c0       	rjmp	.+22     	; 0x38a <usbPoll+0xde>
        SWITCH_CASE(2)
 374:	92 30       	cpi	r25, 0x02	; 2
 376:	41 f4       	brne	.+16     	; 0x388 <usbPoll+0xdc>
            GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_PRODUCT, usbDescriptorStringDevice)
 378:	8b e7       	ldi	r24, 0x7B	; 123
 37a:	90 e0       	ldi	r25, 0x00	; 0
 37c:	90 93 a1 00 	sts	0x00A1, r25
 380:	80 93 a0 00 	sts	0x00A0, r24
 384:	80 e1       	ldi	r24, 0x10	; 16
 386:	01 c0       	rjmp	.+2      	; 0x38a <usbPoll+0xde>
/* usbDriverDescriptor() is similar to usbFunctionDescriptor(), but used
 * internally for all types of descriptors.
 */
static inline usbMsgLen_t usbDriverDescriptor(usbRequest_t *rq)
{
usbMsgLen_t len = 0;
 388:	80 e0       	ldi	r24, 0x00	; 0
    SWITCH_DEFAULT
        if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){
            len = usbFunctionDescriptor(rq);
        }
    SWITCH_END
    usbMsgFlags = flags;
 38a:	90 e4       	ldi	r25, 0x40	; 64
 38c:	90 93 85 00 	sts	0x0085, r25
 390:	20 c0       	rjmp	.+64     	; 0x3d2 <usbPoll+0x126>
        usbNewDeviceAddr = value;
        USB_SET_ADDRESS_HOOK();
    SWITCH_CASE(USBRQ_GET_DESCRIPTOR)       /* 6 */
        len = usbDriverDescriptor(rq);
        goto skipMsgPtrAssignment;
    SWITCH_CASE(USBRQ_GET_CONFIGURATION)    /* 8 */
 392:	88 30       	cpi	r24, 0x08	; 8
 394:	79 f0       	breq	.+30     	; 0x3b4 <usbPoll+0x108>
        dataPtr = &usbConfiguration;  /* send current configuration value */
        len = 1;
    SWITCH_CASE(USBRQ_SET_CONFIGURATION)    /* 9 */
 396:	89 30       	cpi	r24, 0x09	; 9
 398:	19 f4       	brne	.+6      	; 0x3a0 <usbPoll+0xf4>
        usbConfiguration = value;
 39a:	90 93 a5 00 	sts	0x00A5, r25
 39e:	11 c0       	rjmp	.+34     	; 0x3c2 <usbPoll+0x116>
        usbResetStall();
    SWITCH_CASE(USBRQ_GET_INTERFACE)        /* 10 */
 3a0:	8a 30       	cpi	r24, 0x0A	; 10
 3a2:	59 f0       	breq	.+22     	; 0x3ba <usbPoll+0x10e>
        len = 1;
#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
    SWITCH_CASE(USBRQ_SET_INTERFACE)        /* 11 */
 3a4:	8b 30       	cpi	r24, 0x0B	; 11
 3a6:	69 f4       	brne	.+26     	; 0x3c2 <usbPoll+0x116>
/* ------------------------------------------------------------------------- */

static inline void  usbResetDataToggling(void)
{
#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
    USB_SET_DATATOKEN1(USB_INITIAL_DATATOKEN);  /* reset data toggling for interrupt endpoint */
 3a8:	8b e4       	ldi	r24, 0x4B	; 75
 3aa:	80 93 92 00 	sts	0x0092, r24
#   if USB_CFG_HAVE_INTRIN_ENDPOINT3
    USB_SET_DATATOKEN3(USB_INITIAL_DATATOKEN);  /* reset data toggling for interrupt endpoint */
 3ae:	80 93 bd 00 	sts	0x00BD, r24
 3b2:	07 c0       	rjmp	.+14     	; 0x3c2 <usbPoll+0x116>
        USB_SET_ADDRESS_HOOK();
    SWITCH_CASE(USBRQ_GET_DESCRIPTOR)       /* 6 */
        len = usbDriverDescriptor(rq);
        goto skipMsgPtrAssignment;
    SWITCH_CASE(USBRQ_GET_CONFIGURATION)    /* 8 */
        dataPtr = &usbConfiguration;  /* send current configuration value */
 3b4:	25 ea       	ldi	r18, 0xA5	; 165
 3b6:	30 e0       	ldi	r19, 0x00	; 0
 3b8:	02 c0       	rjmp	.+4      	; 0x3be <usbPoll+0x112>
/* usbDriverSetup() is similar to usbFunctionSetup(), but it's used for
 * standard requests instead of class and custom requests.
 */
static inline usbMsgLen_t usbDriverSetup(usbRequest_t *rq)
{
uchar   len  = 0, *dataPtr = usbTxBuf + 9;  /* there are 2 bytes free space at the end of the buffer */
 3ba:	2f e8       	ldi	r18, 0x8F	; 143
 3bc:	30 e0       	ldi	r19, 0x00	; 0
        len = 1;
    SWITCH_CASE(USBRQ_SET_CONFIGURATION)    /* 9 */
        usbConfiguration = value;
        usbResetStall();
    SWITCH_CASE(USBRQ_GET_INTERFACE)        /* 10 */
        len = 1;
 3be:	81 e0       	ldi	r24, 0x01	; 1
 3c0:	03 c0       	rjmp	.+6      	; 0x3c8 <usbPoll+0x11c>
/* usbDriverSetup() is similar to usbFunctionSetup(), but it's used for
 * standard requests instead of class and custom requests.
 */
static inline usbMsgLen_t usbDriverSetup(usbRequest_t *rq)
{
uchar   len  = 0, *dataPtr = usbTxBuf + 9;  /* there are 2 bytes free space at the end of the buffer */
 3c2:	2f e8       	ldi	r18, 0x8F	; 143
 3c4:	30 e0       	ldi	r19, 0x00	; 0
 3c6:	80 e0       	ldi	r24, 0x00	; 0
        usbResetStall();
#endif
    SWITCH_DEFAULT                          /* 7=SET_DESCRIPTOR, 12=SYNC_FRAME */
        /* Should we add an optional hook here? */
    SWITCH_END
    usbMsgPtr = dataPtr;
 3c8:	30 93 a1 00 	sts	0x00A1, r19
 3cc:	20 93 a0 00 	sts	0x00A0, r18
 3d0:	09 c0       	rjmp	.+18     	; 0x3e4 <usbPoll+0x138>
            replyLen = usbFunctionSetup(data);
        }else{
            replyLen = usbDriverSetup(rq);
        }
#if USB_CFG_IMPLEMENT_FN_READ || USB_CFG_IMPLEMENT_FN_WRITE
        if(replyLen == USB_NO_MSG){         /* use user-supplied read/write function */
 3d2:	8f 3f       	cpi	r24, 0xFF	; 255
 3d4:	39 f4       	brne	.+14     	; 0x3e4 <usbPoll+0x138>
            /* do some conditioning on replyLen, but on IN transfers only */
            if((rq->bmRequestType & USBRQ_DIR_MASK) != USBRQ_DIR_HOST_TO_DEVICE){
 3d6:	98 81       	ld	r25, Y
 3d8:	97 fd       	sbrc	r25, 7
                if(sizeof(replyLen) < sizeof(rq->wLength.word)){ /* help compiler with optimizing */
                    replyLen = rq->wLength.bytes[0];
 3da:	8e 81       	ldd	r24, Y+6	; 0x06
                }else{
                    replyLen = rq->wLength.word;
                }
            }
            usbMsgFlags = USB_FLG_USE_USER_RW;
 3dc:	90 e8       	ldi	r25, 0x80	; 128
 3de:	90 93 85 00 	sts	0x0085, r25
 3e2:	07 c0       	rjmp	.+14     	; 0x3f2 <usbPoll+0x146>
        }else   /* The 'else' prevents that we limit a replyLen of USB_NO_MSG to the maximum transfer len. */
#endif
        if(sizeof(replyLen) < sizeof(rq->wLength.word)){ /* help compiler with optimizing */
            if(!rq->wLength.bytes[1] && replyLen > rq->wLength.bytes[0])    /* limit length to max */
 3e4:	9f 81       	ldd	r25, Y+7	; 0x07
 3e6:	99 23       	and	r25, r25
 3e8:	21 f4       	brne	.+8      	; 0x3f2 <usbPoll+0x146>
 3ea:	9e 81       	ldd	r25, Y+6	; 0x06
 3ec:	98 17       	cp	r25, r24
 3ee:	08 f4       	brcc	.+2      	; 0x3f2 <usbPoll+0x146>
 3f0:	89 2f       	mov	r24, r25
                replyLen = rq->wLength.bytes[0];
        }else{
            if(replyLen > rq->wLength.word)     /* limit length to max */
                replyLen = rq->wLength.word;
        }
        usbMsgLen = replyLen;
 3f2:	80 93 61 00 	sts	0x0061, r24
 3f6:	10 c0       	rjmp	.+32     	; 0x418 <usbPoll+0x16c>
    }else{  /* usbRxToken must be USBPID_OUT, which means data phase of setup (control-out) */
#if USB_CFG_IMPLEMENT_FN_WRITE
        if(usbMsgFlags & USB_FLG_USE_USER_RW){
 3f8:	80 91 85 00 	lds	r24, 0x0085
 3fc:	87 ff       	sbrs	r24, 7
 3fe:	0c c0       	rjmp	.+24     	; 0x418 <usbPoll+0x16c>
            uchar rval = usbFunctionWrite(data, len);
 400:	ce 01       	movw	r24, r28
 402:	95 de       	rcall	.-726    	; 0x12e <usbFunctionWrite>
            if(rval == 0xff){   /* an error occurred */
 404:	8f 3f       	cpi	r24, 0xFF	; 255
 406:	21 f4       	brne	.+8      	; 0x410 <usbPoll+0x164>
                usbTxLen = USBPID_STALL;
 408:	8e e1       	ldi	r24, 0x1E	; 30
 40a:	80 93 60 00 	sts	0x0060, r24
 40e:	04 c0       	rjmp	.+8      	; 0x418 <usbPoll+0x16c>
            }else if(rval != 0){    /* This was the final package */
 410:	88 23       	and	r24, r24
 412:	11 f0       	breq	.+4      	; 0x418 <usbPoll+0x16c>
                usbMsgLen = 0;  /* answer with a zero-sized data packet */
 414:	10 92 61 00 	sts	0x0061, r1
 * retries must be handled on application level.
 * unsigned crc = usbCrc16(buffer + 1, usbRxLen - 3);
 */
        usbProcessRx(usbRxBuf + USB_BUFSIZE + 1 - usbInputBufOffset, len);
#if USB_CFG_HAVE_FLOWCONTROL
        if(usbRxLen > 0)    /* only mark as available if not inactivated */
 418:	80 91 a2 00 	lds	r24, 0x00A2
 41c:	18 16       	cp	r1, r24
 41e:	14 f4       	brge	.+4      	; 0x424 <usbPoll+0x178>
            usbRxLen = 0;
 420:	10 92 a2 00 	sts	0x00A2, r1
#else
        usbRxLen = 0;       /* mark rx buffer as available */
#endif
    }
    if(usbTxLen & 0x10){    /* transmit system idle */
 424:	80 91 60 00 	lds	r24, 0x0060
 428:	84 ff       	sbrs	r24, 4
 42a:	5b c0       	rjmp	.+182    	; 0x4e2 <usbPoll+0x236>
        if(usbMsgLen != USB_NO_MSG){    /* transmit data pending? */
 42c:	80 91 61 00 	lds	r24, 0x0061
 430:	8f 3f       	cpi	r24, 0xFF	; 255
 432:	09 f4       	brne	.+2      	; 0x436 <usbPoll+0x18a>
 434:	56 c0       	rjmp	.+172    	; 0x4e2 <usbPoll+0x236>
 436:	18 2f       	mov	r17, r24
 438:	89 30       	cpi	r24, 0x09	; 9
 43a:	08 f0       	brcs	.+2      	; 0x43e <usbPoll+0x192>
 43c:	18 e0       	ldi	r17, 0x08	; 8
uchar       len;

    wantLen = usbMsgLen;
    if(wantLen > 8)
        wantLen = 8;
    usbMsgLen -= wantLen;
 43e:	81 1b       	sub	r24, r17
 440:	80 93 61 00 	sts	0x0061, r24
    usbTxBuf[0] ^= USBPID_DATA0 ^ USBPID_DATA1; /* DATA toggling */
 444:	80 91 86 00 	lds	r24, 0x0086
 448:	98 e8       	ldi	r25, 0x88	; 136
 44a:	89 27       	eor	r24, r25
 44c:	80 93 86 00 	sts	0x0086, r24
/* This function is similar to usbFunctionRead(), but it's also called for
 * data handled automatically by the driver (e.g. descriptor reads).
 */
static uchar usbDeviceRead(uchar *data, uchar len)
{
    if(len > 0){    /* don't bother app with 0 sized reads */
 450:	11 23       	and	r17, r17
 452:	b1 f1       	breq	.+108    	; 0x4c0 <usbPoll+0x214>
#if USB_CFG_IMPLEMENT_FN_READ
        if(usbMsgFlags & USB_FLG_USE_USER_RW){
 454:	80 91 85 00 	lds	r24, 0x0085
 458:	87 ff       	sbrs	r24, 7
 45a:	08 c0       	rjmp	.+16     	; 0x46c <usbPoll+0x1c0>
            len = usbFunctionRead(data, len);
 45c:	87 e8       	ldi	r24, 0x87	; 135
 45e:	90 e0       	ldi	r25, 0x00	; 0
 460:	61 2f       	mov	r22, r17
 462:	59 de       	rcall	.-846    	; 0x116 <usbFunctionRead>
 464:	18 2f       	mov	r17, r24
    if(wantLen > 8)
        wantLen = 8;
    usbMsgLen -= wantLen;
    usbTxBuf[0] ^= USBPID_DATA0 ^ USBPID_DATA1; /* DATA toggling */
    len = usbDeviceRead(usbTxBuf + 1, wantLen);
    if(len <= 8){           /* valid data packet */
 466:	89 30       	cpi	r24, 0x09	; 9
 468:	b0 f5       	brcc	.+108    	; 0x4d6 <usbPoll+0x22a>
 46a:	2a c0       	rjmp	.+84     	; 0x4c0 <usbPoll+0x214>
        if(usbMsgFlags & USB_FLG_USE_USER_RW){
            len = usbFunctionRead(data, len);
        }else
#endif
        {
            uchar i = len, *r = usbMsgPtr;
 46c:	20 91 a0 00 	lds	r18, 0x00A0
 470:	30 91 a1 00 	lds	r19, 0x00A1
 474:	41 2f       	mov	r20, r17
 476:	41 50       	subi	r20, 0x01	; 1
            if(usbMsgFlags & USB_FLG_MSGPTR_IS_ROM){    /* ROM data */
 478:	86 ff       	sbrs	r24, 6
 47a:	0e c0       	rjmp	.+28     	; 0x498 <usbPoll+0x1ec>
#endif
}

/* ------------------------------------------------------------------------- */

USB_PUBLIC void usbPoll(void)
 47c:	50 e0       	ldi	r21, 0x00	; 0
 47e:	ea 01       	movw	r28, r20
 480:	c8 57       	subi	r28, 0x78	; 120
 482:	df 4f       	sbci	r29, 0xFF	; 255
 484:	f9 01       	movw	r30, r18
 486:	a7 e8       	ldi	r26, 0x87	; 135
 488:	b0 e0       	ldi	r27, 0x00	; 0
#endif
        {
            uchar i = len, *r = usbMsgPtr;
            if(usbMsgFlags & USB_FLG_MSGPTR_IS_ROM){    /* ROM data */
                do{
                    uchar c = USB_READ_FLASH(r);    /* assign to char size variable to enforce byte ops */
 48a:	84 91       	lpm	r24, Z+
                    *data++ = c;
 48c:	8d 93       	st	X+, r24
                    r++;
 48e:	31 96       	adiw	r30, 0x01	; 1
                }while(--i);
 490:	ac 17       	cp	r26, r28
 492:	bd 07       	cpc	r27, r29
 494:	d1 f7       	brne	.-12     	; 0x48a <usbPoll+0x1de>
 496:	0c c0       	rjmp	.+24     	; 0x4b0 <usbPoll+0x204>
 498:	d9 01       	movw	r26, r18
#endif
}

/* ------------------------------------------------------------------------- */

USB_PUBLIC void usbPoll(void)
 49a:	50 e0       	ldi	r21, 0x00	; 0
 49c:	ca 01       	movw	r24, r20
 49e:	88 57       	subi	r24, 0x78	; 120
 4a0:	9f 4f       	sbci	r25, 0xFF	; 255
 4a2:	e7 e8       	ldi	r30, 0x87	; 135
 4a4:	f0 e0       	ldi	r31, 0x00	; 0
                    *data++ = c;
                    r++;
                }while(--i);
            }else{  /* RAM data */
                do{
                    *data++ = *r++;
 4a6:	6d 91       	ld	r22, X+
 4a8:	61 93       	st	Z+, r22
                }while(--i);
 4aa:	e8 17       	cp	r30, r24
 4ac:	f9 07       	cpc	r31, r25
 4ae:	d9 f7       	brne	.-10     	; 0x4a6 <usbPoll+0x1fa>
#endif
}

/* ------------------------------------------------------------------------- */

USB_PUBLIC void usbPoll(void)
 4b0:	4f 5f       	subi	r20, 0xFF	; 255
 4b2:	5f 4f       	sbci	r21, 0xFF	; 255
                    r++;
                }while(--i);
            }else{  /* RAM data */
                do{
                    *data++ = *r++;
                }while(--i);
 4b4:	42 0f       	add	r20, r18
 4b6:	53 1f       	adc	r21, r19
            }
            usbMsgPtr = r;
 4b8:	50 93 a1 00 	sts	0x00A1, r21
 4bc:	40 93 a0 00 	sts	0x00A0, r20
        wantLen = 8;
    usbMsgLen -= wantLen;
    usbTxBuf[0] ^= USBPID_DATA0 ^ USBPID_DATA1; /* DATA toggling */
    len = usbDeviceRead(usbTxBuf + 1, wantLen);
    if(len <= 8){           /* valid data packet */
        usbCrc16Append(&usbTxBuf[1], len);
 4c0:	87 e8       	ldi	r24, 0x87	; 135
 4c2:	90 e0       	ldi	r25, 0x00	; 0
 4c4:	61 2f       	mov	r22, r17
 4c6:	41 d0       	rcall	.+130    	; 0x54a <usbCrc16Append>
        len += 4;           /* length including sync byte */
 4c8:	1c 5f       	subi	r17, 0xFC	; 252
        if(len < 12)        /* a partial package identifies end of message */
 4ca:	1c 30       	cpi	r17, 0x0C	; 12
 4cc:	41 f0       	breq	.+16     	; 0x4de <usbPoll+0x232>
            usbMsgLen = USB_NO_MSG;
 4ce:	8f ef       	ldi	r24, 0xFF	; 255
 4d0:	80 93 61 00 	sts	0x0061, r24
 4d4:	04 c0       	rjmp	.+8      	; 0x4de <usbPoll+0x232>
    }else{
        len = USBPID_STALL;   /* stall the endpoint */
        usbMsgLen = USB_NO_MSG;
 4d6:	8f ef       	ldi	r24, 0xFF	; 255
 4d8:	80 93 61 00 	sts	0x0061, r24
        usbCrc16Append(&usbTxBuf[1], len);
        len += 4;           /* length including sync byte */
        if(len < 12)        /* a partial package identifies end of message */
            usbMsgLen = USB_NO_MSG;
    }else{
        len = USBPID_STALL;   /* stall the endpoint */
 4dc:	1e e1       	ldi	r17, 0x1E	; 30
        usbMsgLen = USB_NO_MSG;
    }
    usbTxLen = len;
 4de:	10 93 60 00 	sts	0x0060, r17
    if(usbTxLen & 0x10){    /* transmit system idle */
        if(usbMsgLen != USB_NO_MSG){    /* transmit data pending? */
            usbBuildTxBlock();
        }
    }
    for(i = 20; i > 0; i--){
 4e2:	84 e1       	ldi	r24, 0x14	; 20
        uchar usbLineStatus = USBIN & USBMASK;
 4e4:	90 b3       	in	r25, 0x10	; 16
 4e6:	9c 70       	andi	r25, 0x0C	; 12
        if(usbLineStatus != 0)  /* SE0 has ended */
 4e8:	31 f4       	brne	.+12     	; 0x4f6 <usbPoll+0x24a>
    if(usbTxLen & 0x10){    /* transmit system idle */
        if(usbMsgLen != USB_NO_MSG){    /* transmit data pending? */
            usbBuildTxBlock();
        }
    }
    for(i = 20; i > 0; i--){
 4ea:	81 50       	subi	r24, 0x01	; 1
 4ec:	d9 f7       	brne	.-10     	; 0x4e4 <usbPoll+0x238>
        uchar usbLineStatus = USBIN & USBMASK;
        if(usbLineStatus != 0)  /* SE0 has ended */
            goto isNotReset;
    }
    /* RESET condition, called multiple times during reset */
    usbNewDeviceAddr = 0;
 4ee:	10 92 a3 00 	sts	0x00A3, r1
    usbDeviceAddr = 0;
 4f2:	10 92 9d 00 	sts	0x009D, r1
    usbResetStall();
    DBG1(0xff, 0, 0);
isNotReset:
    usbHandleResetHook(i);
}
 4f6:	df 91       	pop	r29
 4f8:	cf 91       	pop	r28
 4fa:	1f 91       	pop	r17
 4fc:	08 95       	ret

000004fe <usbInit>:
/* ------------------------------------------------------------------------- */

USB_PUBLIC void usbInit(void)
{
#if USB_INTR_CFG_SET != 0
    USB_INTR_CFG |= USB_INTR_CFG_SET;
 4fe:	85 b7       	in	r24, 0x35	; 53
 500:	82 60       	ori	r24, 0x02	; 2
 502:	85 bf       	out	0x35, r24	; 53
#endif
#if USB_INTR_CFG_CLR != 0
    USB_INTR_CFG &= ~(USB_INTR_CFG_CLR);
#endif
    USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT);
 504:	8b b7       	in	r24, 0x3b	; 59
 506:	80 64       	ori	r24, 0x40	; 64
 508:	8b bf       	out	0x3b, r24	; 59
/* ------------------------------------------------------------------------- */

static inline void  usbResetDataToggling(void)
{
#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
    USB_SET_DATATOKEN1(USB_INITIAL_DATATOKEN);  /* reset data toggling for interrupt endpoint */
 50a:	8b e4       	ldi	r24, 0x4B	; 75
 50c:	80 93 92 00 	sts	0x0092, r24
#   if USB_CFG_HAVE_INTRIN_ENDPOINT3
    USB_SET_DATATOKEN3(USB_INITIAL_DATATOKEN);  /* reset data toggling for interrupt endpoint */
 510:	80 93 bd 00 	sts	0x00BD, r24
    USB_INTR_CFG &= ~(USB_INTR_CFG_CLR);
#endif
    USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT);
    usbResetDataToggling();
#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
    usbTxLen1 = USBPID_NAK;
 514:	8a e5       	ldi	r24, 0x5A	; 90
 516:	80 93 91 00 	sts	0x0091, r24
#if USB_CFG_HAVE_INTRIN_ENDPOINT3
    usbTxLen3 = USBPID_NAK;
 51a:	80 93 bc 00 	sts	0x00BC, r24
#endif
#endif
}
 51e:	08 95       	ret

00000520 <usbCrc16>:
;   poly    r20+r21
;   scratch r23
;   resCrc  r24+r25 / r16+r17
;   ptr     X / Z
usbCrc16:
    mov     ptrL, argPtrL
 520:	a8 2f       	mov	r26, r24
    mov     ptrH, argPtrH
 522:	b9 2f       	mov	r27, r25
    ldi     resCrcL, 0
 524:	80 e0       	ldi	r24, 0x00	; 0
    ldi     resCrcH, 0
 526:	90 e0       	ldi	r25, 0x00	; 0
    ldi     polyL, lo8(0xa001)
 528:	41 e0       	ldi	r20, 0x01	; 1
    ldi     polyH, hi8(0xa001)
 52a:	50 ea       	ldi	r21, 0xA0	; 160
    com     argLen      ; argLen = -argLen - 1: modified loop to ensure that carry is set
 52c:	60 95       	com	r22
    ldi     bitCnt, 0   ; loop counter with starnd condition = end condition
 52e:	30 e0       	ldi	r19, 0x00	; 0
    rjmp    usbCrcLoopEntry
 530:	09 c0       	rjmp	.+18     	; 0x544 <usbCrcLoopEntry>

00000532 <usbCrcByteLoop>:
usbCrcByteLoop:
    ld      byte, ptr+
 532:	2d 91       	ld	r18, X+
    eor     resCrcL, byte
 534:	82 27       	eor	r24, r18

00000536 <usbCrcBitLoop>:
usbCrcBitLoop:
    ror     resCrcH     ; carry is always set here (see brcs jumps to here)
 536:	97 95       	ror	r25
    ror     resCrcL
 538:	87 95       	ror	r24
    brcs    usbCrcNoXor
 53a:	10 f0       	brcs	.+4      	; 0x540 <usbCrcNoXor>
    eor     resCrcL, polyL
 53c:	84 27       	eor	r24, r20
    eor     resCrcH, polyH
 53e:	95 27       	eor	r25, r21

00000540 <usbCrcNoXor>:
usbCrcNoXor:
    subi    bitCnt, 224 ; (8 * 224) % 256 = 0; this loop iterates 8 times
 540:	30 5e       	subi	r19, 0xE0	; 224
    brcs    usbCrcBitLoop
 542:	c8 f3       	brcs	.-14     	; 0x536 <usbCrcBitLoop>

00000544 <usbCrcLoopEntry>:
usbCrcLoopEntry:
    subi    argLen, -1
 544:	6f 5f       	subi	r22, 0xFF	; 255
    brcs    usbCrcByteLoop
 546:	a8 f3       	brcs	.-22     	; 0x532 <usbCrcByteLoop>

00000548 <usbCrcReady>:
usbCrcReady:
    ret
 548:	08 95       	ret

0000054a <usbCrc16Append>:

#endif /* USB_USE_FAST_CRC */

; extern unsigned usbCrc16Append(unsigned char *data, unsigned char len);
usbCrc16Append:
    rcall   usbCrc16
 54a:	ea df       	rcall	.-44     	; 0x520 <usbCrc16>
    st      ptr+, resCrcL
 54c:	8d 93       	st	X+, r24
    st      ptr+, resCrcH
 54e:	9d 93       	st	X+, r25
    ret
 550:	08 95       	ret

00000552 <__vector_1>:
;max allowable interrupt latency: 34 cycles -> max 25 cycles interrupt disable
;max stack usage: [ret(2), YL, SREG, YH, shift, x1, x2, x3, cnt, x4] = 11 bytes
;Numbers in brackets are maximum cycles since SOF.
USB_INTR_VECTOR:
;order of registers pushed: YL, SREG [sofError], YH, shift, x1, x2, x3, cnt
    push    YL              ;2 [35] push only what is necessary to sync with edge ASAP
 552:	cf 93       	push	r28
    in      YL, SREG        ;1 [37]
 554:	cf b7       	in	r28, 0x3f	; 63
    push    YL              ;2 [39]
 556:	cf 93       	push	r28

00000558 <waitForJ>:
;sync up with J to K edge during sync pattern -- use fastest possible loops
;The first part waits at most 1 bit long since we must be in sync pattern.
;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
;waitForJ, ensure that this prerequisite is met.
waitForJ:
    inc     YL
 558:	c3 95       	inc	r28
    sbis    USBIN, USBMINUS
 55a:	83 9b       	sbis	0x10, 3	; 16
    brne    waitForJ        ; just make sure we have ANY timeout
 55c:	e9 f7       	brne	.-6      	; 0x558 <waitForJ>

0000055e <waitForK>:
waitForK:
;The following code results in a sampling window of 1/4 bit which meets the spec.
    sbis    USBIN, USBMINUS
 55e:	83 9b       	sbis	0x10, 3	; 16
    rjmp    foundK
 560:	09 c0       	rjmp	.+18     	; 0x574 <foundK>
    sbis    USBIN, USBMINUS
 562:	83 9b       	sbis	0x10, 3	; 16
    rjmp    foundK
 564:	07 c0       	rjmp	.+14     	; 0x574 <foundK>
    sbis    USBIN, USBMINUS
 566:	83 9b       	sbis	0x10, 3	; 16
    rjmp    foundK
 568:	05 c0       	rjmp	.+10     	; 0x574 <foundK>
    sbis    USBIN, USBMINUS
 56a:	83 9b       	sbis	0x10, 3	; 16
    rjmp    foundK
 56c:	03 c0       	rjmp	.+6      	; 0x574 <foundK>
    sbis    USBIN, USBMINUS
 56e:	83 9b       	sbis	0x10, 3	; 16
    rjmp    foundK
 570:	01 c0       	rjmp	.+2      	; 0x574 <foundK>
    sts     usbSofCount, YL
#endif  /* USB_COUNT_SOF */
#ifdef USB_SOF_HOOK
    USB_SOF_HOOK
#endif
    rjmp    sofError
 572:	a6 c0       	rjmp	.+332    	; 0x6c0 <sofError>

00000574 <foundK>:
foundK:
;{3, 5} after falling D- edge, average delay: 4 cycles [we want 4 for center sampling]
;we have 1 bit time for setup purposes, then sample again. Numbers in brackets
;are cycles from center of first sync (double K) bit after the instruction
    push    YH                  ;2 [2]
 574:	df 93       	push	r29
    lds     YL, usbInputBufOffset;2 [4]
 576:	c0 91 9f 00 	lds	r28, 0x009F
    clr     YH                  ;1 [5]
 57a:	dd 27       	eor	r29, r29
    subi    YL, lo8(-(usbRxBuf));1 [6]
 57c:	ca 55       	subi	r28, 0x5A	; 90
    sbci    YH, hi8(-(usbRxBuf));1 [7]
 57e:	df 4f       	sbci	r29, 0xFF	; 255

    sbis    USBIN, USBMINUS ;1 [8] we want two bits K [sample 1 cycle too early]
 580:	83 9b       	sbis	0x10, 3	; 16
    rjmp    haveTwoBitsK    ;2 [10]
 582:	02 c0       	rjmp	.+4      	; 0x588 <haveTwoBitsK>
    pop     YH              ;2 [11] undo the push from before
 584:	df 91       	pop	r29
    rjmp    waitForK        ;2 [13] this was not the end of sync, retry
 586:	eb cf       	rjmp	.-42     	; 0x55e <waitForK>

00000588 <haveTwoBitsK>:
haveTwoBitsK:
;----------------------------------------------------------------------------
; push more registers and initialize values while we sample the first bits:
;----------------------------------------------------------------------------
    push    shift           ;2 [16]
 588:	2f 93       	push	r18
    push    x1              ;2 [12]
 58a:	0f 93       	push	r16
    push    x2              ;2 [14]
 58c:	1f 93       	push	r17

    in      x1, USBIN       ;1 [17] <-- sample bit 0
 58e:	00 b3       	in	r16, 0x10	; 16
    ldi     shift, 0xff     ;1 [18]
 590:	2f ef       	ldi	r18, 0xFF	; 255
    bst     x1, USBMINUS    ;1 [19]
 592:	03 fb       	bst	r16, 3
    bld     shift, 0        ;1 [20]
 594:	20 f9       	bld	r18, 0
    push    x3              ;2 [22]
 596:	4f 93       	push	r20
    push    cnt             ;2 [24]
 598:	3f 93       	push	r19
    
    in      x2, USBIN       ;1 [25] <-- sample bit 1
 59a:	10 b3       	in	r17, 0x10	; 16
    ser     x3              ;1 [26] [inserted init instruction]
 59c:	4f ef       	ldi	r20, 0xFF	; 255
    eor     x1, x2          ;1 [27]
 59e:	01 27       	eor	r16, r17
    bst     x1, USBMINUS    ;1 [28]
 5a0:	03 fb       	bst	r16, 3
    bld     shift, 1        ;1 [29]
 5a2:	21 f9       	bld	r18, 1
    ldi     cnt, USB_BUFSIZE;1 [30] [inserted init instruction]
 5a4:	3b e0       	ldi	r19, 0x0B	; 11
    rjmp    rxbit2          ;2 [32]
 5a6:	31 c0       	rjmp	.+98     	; 0x60a <rxbit2>

000005a8 <unstuff0>:
;----------------------------------------------------------------------------
; Receiver loop (numbers in brackets are cycles within byte after instr)
;----------------------------------------------------------------------------

unstuff0:               ;1 (branch taken)
    andi    x3, ~0x01   ;1 [15]
 5a8:	4e 7f       	andi	r20, 0xFE	; 254
    mov     x1, x2      ;1 [16] x2 contains last sampled (stuffed) bit
 5aa:	01 2f       	mov	r16, r17
    in      x2, USBIN   ;1 [17] <-- sample bit 1 again
 5ac:	10 b3       	in	r17, 0x10	; 16
    ori     shift, 0x01 ;1 [18]
 5ae:	21 60       	ori	r18, 0x01	; 1
    rjmp    didUnstuff0 ;2 [20]
 5b0:	28 c0       	rjmp	.+80     	; 0x602 <didUnstuff0>

000005b2 <unstuff1>:

unstuff1:               ;1 (branch taken)
    mov     x2, x1      ;1 [21] x1 contains last sampled (stuffed) bit
 5b2:	10 2f       	mov	r17, r16
    andi    x3, ~0x02   ;1 [22]
 5b4:	4d 7f       	andi	r20, 0xFD	; 253
    ori     shift, 0x02 ;1 [23]
 5b6:	22 60       	ori	r18, 0x02	; 2
    nop                 ;1 [24]
 5b8:	00 00       	nop
    in      x1, USBIN   ;1 [25] <-- sample bit 2 again
 5ba:	00 b3       	in	r16, 0x10	; 16
    rjmp    didUnstuff1 ;2 [27]
 5bc:	29 c0       	rjmp	.+82     	; 0x610 <didUnstuff1>

000005be <unstuff2>:

unstuff2:               ;1 (branch taken)
    andi    x3, ~0x04   ;1 [29]
 5be:	4b 7f       	andi	r20, 0xFB	; 251
    ori     shift, 0x04 ;1 [30]
 5c0:	24 60       	ori	r18, 0x04	; 4
    mov     x1, x2      ;1 [31] x2 contains last sampled (stuffed) bit
 5c2:	01 2f       	mov	r16, r17
    nop                 ;1 [32]
 5c4:	00 00       	nop
    in      x2, USBIN   ;1 [33] <-- sample bit 3
 5c6:	10 b3       	in	r17, 0x10	; 16
    rjmp    didUnstuff2 ;2 [35]
 5c8:	2b c0       	rjmp	.+86     	; 0x620 <didUnstuff2>

000005ca <unstuff3>:

unstuff3:               ;1 (branch taken)
    in      x2, USBIN   ;1 [34] <-- sample stuffed bit 3 [one cycle too late]
 5ca:	10 b3       	in	r17, 0x10	; 16
    andi    x3, ~0x08   ;1 [35]
 5cc:	47 7f       	andi	r20, 0xF7	; 247
    ori     shift, 0x08 ;1 [36]
 5ce:	28 60       	ori	r18, 0x08	; 8
    rjmp    didUnstuff3 ;2 [38]
 5d0:	2a c0       	rjmp	.+84     	; 0x626 <didUnstuff3>

000005d2 <unstuff4>:

unstuff4:               ;1 (branch taken)
    andi    x3, ~0x10   ;1 [40]
 5d2:	4f 7e       	andi	r20, 0xEF	; 239
    in      x1, USBIN   ;1 [41] <-- sample stuffed bit 4
 5d4:	00 b3       	in	r16, 0x10	; 16
    ori     shift, 0x10 ;1 [42]
 5d6:	20 61       	ori	r18, 0x10	; 16
    rjmp    didUnstuff4 ;2 [44]
 5d8:	2c c0       	rjmp	.+88     	; 0x632 <didUnstuff4>

000005da <unstuff5>:

unstuff5:               ;1 (branch taken)
    andi    x3, ~0x20   ;1 [48]
 5da:	4f 7d       	andi	r20, 0xDF	; 223
    in      x2, USBIN   ;1 [49] <-- sample stuffed bit 5
 5dc:	10 b3       	in	r17, 0x10	; 16
    ori     shift, 0x20 ;1 [50]
 5de:	20 62       	ori	r18, 0x20	; 32
    rjmp    didUnstuff5 ;2 [52]
 5e0:	2f c0       	rjmp	.+94     	; 0x640 <didUnstuff5>

000005e2 <unstuff6>:

unstuff6:               ;1 (branch taken)
    andi    x3, ~0x40   ;1 [56]
 5e2:	4f 7b       	andi	r20, 0xBF	; 191
    in      x1, USBIN   ;1 [57] <-- sample stuffed bit 6
 5e4:	00 b3       	in	r16, 0x10	; 16
    ori     shift, 0x40 ;1 [58]
 5e6:	20 64       	ori	r18, 0x40	; 64
    rjmp    didUnstuff6 ;2 [60]
 5e8:	32 c0       	rjmp	.+100    	; 0x64e <didUnstuff6>

000005ea <rxLoop>:
; bit 4:    none
; bit 5:    none
; bit 6:    none
; bit 7:    jump, eor
rxLoop:
    eor     x3, shift   ;1 [0] reconstruct: x3 is 0 at bit locations we changed, 1 at others
 5ea:	42 27       	eor	r20, r18
    in      x1, USBIN   ;1 [1] <-- sample bit 0
 5ec:	00 b3       	in	r16, 0x10	; 16
    st      y+, x3      ;2 [3] store data
 5ee:	49 93       	st	Y+, r20
    ser     x3          ;1 [4]
 5f0:	4f ef       	ldi	r20, 0xFF	; 255
    nop                 ;1 [5]
 5f2:	00 00       	nop
    eor     x2, x1      ;1 [6]
 5f4:	10 27       	eor	r17, r16
    bst     x2, USBMINUS;1 [7]
 5f6:	13 fb       	bst	r17, 3
    bld     shift, 0    ;1 [8]
 5f8:	20 f9       	bld	r18, 0
    in      x2, USBIN   ;1 [9] <-- sample bit 1 (or possibly bit 0 stuffed)
 5fa:	10 b3       	in	r17, 0x10	; 16
    andi    x2, USBMASK ;1 [10]
 5fc:	1c 70       	andi	r17, 0x0C	; 12
    breq    se0         ;1 [11] SE0 check for bit 1
 5fe:	c9 f1       	breq	.+114    	; 0x672 <se0>
    andi    shift, 0xf9 ;1 [12]
 600:	29 7f       	andi	r18, 0xF9	; 249

00000602 <didUnstuff0>:
didUnstuff0:
    breq    unstuff0    ;1 [13]
 602:	91 f2       	breq	.-92     	; 0x5a8 <unstuff0>
    eor     x1, x2      ;1 [14]
 604:	01 27       	eor	r16, r17
    bst     x1, USBMINUS;1 [15]
 606:	03 fb       	bst	r16, 3
    bld     shift, 1    ;1 [16]
 608:	21 f9       	bld	r18, 1

0000060a <rxbit2>:
rxbit2:
    in      x1, USBIN   ;1 [17] <-- sample bit 2 (or possibly bit 1 stuffed)
 60a:	00 b3       	in	r16, 0x10	; 16
    andi    shift, 0xf3 ;1 [18]
 60c:	23 7f       	andi	r18, 0xF3	; 243
    breq    unstuff1    ;1 [19] do remaining work for bit 1
 60e:	89 f2       	breq	.-94     	; 0x5b2 <unstuff1>

00000610 <didUnstuff1>:
didUnstuff1:
    subi    cnt, 1      ;1 [20]
 610:	31 50       	subi	r19, 0x01	; 1
    brcs    overflow    ;1 [21] loop control
 612:	58 f1       	brcs	.+86     	; 0x66a <overflow>
    eor     x2, x1      ;1 [22]
 614:	10 27       	eor	r17, r16
    bst     x2, USBMINUS;1 [23]
 616:	13 fb       	bst	r17, 3
    bld     shift, 2    ;1 [24]
 618:	22 f9       	bld	r18, 2
    in      x2, USBIN   ;1 [25] <-- sample bit 3 (or possibly bit 2 stuffed)
 61a:	10 b3       	in	r17, 0x10	; 16
    andi    shift, 0xe7 ;1 [26]
 61c:	27 7e       	andi	r18, 0xE7	; 231
    breq    unstuff2    ;1 [27]
 61e:	79 f2       	breq	.-98     	; 0x5be <unstuff2>

00000620 <didUnstuff2>:
didUnstuff2:
    eor     x1, x2      ;1 [28]
 620:	01 27       	eor	r16, r17
    bst     x1, USBMINUS;1 [29]
 622:	03 fb       	bst	r16, 3
    bld     shift, 3    ;1 [30]
 624:	23 f9       	bld	r18, 3

00000626 <didUnstuff3>:
didUnstuff3:
    andi    shift, 0xcf ;1 [31]
 626:	2f 7c       	andi	r18, 0xCF	; 207
    breq    unstuff3    ;1 [32]
 628:	81 f2       	breq	.-96     	; 0x5ca <unstuff3>
    in      x1, USBIN   ;1 [33] <-- sample bit 4
 62a:	00 b3       	in	r16, 0x10	; 16
    eor     x2, x1      ;1 [34]
 62c:	10 27       	eor	r17, r16
    bst     x2, USBMINUS;1 [35]
 62e:	13 fb       	bst	r17, 3
    bld     shift, 4    ;1 [36]
 630:	24 f9       	bld	r18, 4

00000632 <didUnstuff4>:
didUnstuff4:
    andi    shift, 0x9f ;1 [37]
 632:	2f 79       	andi	r18, 0x9F	; 159
    breq    unstuff4    ;1 [38]
 634:	71 f2       	breq	.-100    	; 0x5d2 <unstuff4>
    nop2                ;2 [40]
 636:	00 c0       	rjmp	.+0      	; 0x638 <didUnstuff4+0x6>
    in      x2, USBIN   ;1 [41] <-- sample bit 5
 638:	10 b3       	in	r17, 0x10	; 16
    eor     x1, x2      ;1 [42]
 63a:	01 27       	eor	r16, r17
    bst     x1, USBMINUS;1 [43]
 63c:	03 fb       	bst	r16, 3
    bld     shift, 5    ;1 [44]
 63e:	25 f9       	bld	r18, 5

00000640 <didUnstuff5>:
didUnstuff5:
    andi    shift, 0x3f ;1 [45]
 640:	2f 73       	andi	r18, 0x3F	; 63
    breq    unstuff5    ;1 [46]
 642:	59 f2       	breq	.-106    	; 0x5da <unstuff5>
    nop2                ;2 [48]
 644:	00 c0       	rjmp	.+0      	; 0x646 <didUnstuff5+0x6>
    in      x1, USBIN   ;1 [49] <-- sample bit 6
 646:	00 b3       	in	r16, 0x10	; 16
    eor     x2, x1      ;1 [50]
 648:	10 27       	eor	r17, r16
    bst     x2, USBMINUS;1 [51]
 64a:	13 fb       	bst	r17, 3
    bld     shift, 6    ;1 [52]
 64c:	26 f9       	bld	r18, 6

0000064e <didUnstuff6>:
didUnstuff6:
    cpi     shift, 0x02 ;1 [53]
 64e:	22 30       	cpi	r18, 0x02	; 2
    brlo    unstuff6    ;1 [54]
 650:	40 f2       	brcs	.-112    	; 0x5e2 <unstuff6>
    nop2                ;2 [56]
 652:	00 c0       	rjmp	.+0      	; 0x654 <didUnstuff6+0x6>
    in      x2, USBIN   ;1 [57] <-- sample bit 7
 654:	10 b3       	in	r17, 0x10	; 16
    eor     x1, x2      ;1 [58]
 656:	01 27       	eor	r16, r17
    bst     x1, USBMINUS;1 [59]
 658:	03 fb       	bst	r16, 3
    bld     shift, 7    ;1 [60]
 65a:	27 f9       	bld	r18, 7

0000065c <didUnstuff7>:
didUnstuff7:
    cpi     shift, 0x04 ;1 [61]
 65c:	24 30       	cpi	r18, 0x04	; 4
    brsh    rxLoop      ;2 [63] loop control
 65e:	28 f6       	brcc	.-118    	; 0x5ea <rxLoop>

00000660 <unstuff7>:
unstuff7:
    andi    x3, ~0x80   ;1 [63]
 660:	4f 77       	andi	r20, 0x7F	; 127
    ori     shift, 0x80 ;1 [64]
 662:	20 68       	ori	r18, 0x80	; 128
    in      x2, USBIN   ;1 [65] <-- sample stuffed bit 7
 664:	10 b3       	in	r17, 0x10	; 16
    nop                 ;1 [66]
 666:	00 00       	nop
    rjmp    didUnstuff7 ;2 [68]
 668:	f9 cf       	rjmp	.-14     	; 0x65c <didUnstuff7>

0000066a <overflow>:
*/

#define token   x1

overflow:
    ldi     x2, 1<<USB_INTR_PENDING_BIT
 66a:	10 e4       	ldi	r17, 0x40	; 64
    USB_STORE_PENDING(x2)       ; clear any pending interrupts
 66c:	1a bf       	out	0x3a, r17	; 58

0000066e <ignorePacket>:
ignorePacket:
    clr     token
 66e:	00 27       	eor	r16, r16
    rjmp    storeTokenAndReturn
 670:	1c c0       	rjmp	.+56     	; 0x6aa <storeTokenAndReturn>

00000672 <se0>:
; Processing of received packet (numbers in brackets are cycles after center of SE0)
;----------------------------------------------------------------------------
;This is the only non-error exit point for the software receiver loop
;we don't check any CRCs here because there is no time left.
se0:
    subi    cnt, USB_BUFSIZE    ;[5]
 672:	3b 50       	subi	r19, 0x0B	; 11
    neg     cnt                 ;[6]
 674:	31 95       	neg	r19
    sub     YL, cnt             ;[7]
 676:	c3 1b       	sub	r28, r19
    sbci    YH, 0               ;[8]
 678:	d0 40       	sbci	r29, 0x00	; 0
    ldi     x2, 1<<USB_INTR_PENDING_BIT ;[9]
 67a:	10 e4       	ldi	r17, 0x40	; 64
    USB_STORE_PENDING(x2)       ;[10] clear pending intr and check flag later. SE0 should be over.
 67c:	1a bf       	out	0x3a, r17	; 58
    ld      token, y            ;[11]
 67e:	08 81       	ld	r16, Y
    cpi     token, USBPID_DATA0 ;[13]
 680:	03 3c       	cpi	r16, 0xC3	; 195
    breq    handleData          ;[14]
 682:	11 f1       	breq	.+68     	; 0x6c8 <handleData>
    cpi     token, USBPID_DATA1 ;[15]
 684:	0b 34       	cpi	r16, 0x4B	; 75
    breq    handleData          ;[16]
 686:	01 f1       	breq	.+64     	; 0x6c8 <handleData>
    lds     shift, usbDeviceAddr;[17]
 688:	20 91 9d 00 	lds	r18, 0x009D
    ldd     x2, y+1             ;[19] ADDR and 1 bit endpoint number
 68c:	19 81       	ldd	r17, Y+1	; 0x01
    lsl     x2                  ;[21] shift out 1 bit endpoint number
 68e:	11 0f       	add	r17, r17
    cpse    x2, shift           ;[22]
 690:	12 13       	cpse	r17, r18
    rjmp    ignorePacket        ;[23]
 692:	ed cf       	rjmp	.-38     	; 0x66e <ignorePacket>
/* only compute endpoint number in x3 if required later */
#if USB_CFG_HAVE_INTRIN_ENDPOINT || USB_CFG_IMPLEMENT_FN_WRITEOUT
    ldd     x3, y+2             ;[24] endpoint number + crc
 694:	4a 81       	ldd	r20, Y+2	; 0x02
    rol     x3                  ;[26] shift in LSB of endpoint
 696:	44 1f       	adc	r20, r20
#endif
    cpi     token, USBPID_IN    ;[27]
 698:	09 36       	cpi	r16, 0x69	; 105
    breq    handleIn            ;[28]
 69a:	59 f1       	breq	.+86     	; 0x6f2 <handleIn>
    cpi     token, USBPID_SETUP ;[29]
 69c:	0d 32       	cpi	r16, 0x2D	; 45
    breq    handleSetupOrOut    ;[30]
 69e:	11 f0       	breq	.+4      	; 0x6a4 <handleSetupOrOut>
    cpi     token, USBPID_OUT   ;[31]
 6a0:	01 3e       	cpi	r16, 0xE1	; 225
    brne    ignorePacket        ;[32] must be ack, nak or whatever
 6a2:	29 f7       	brne	.-54     	; 0x66e <ignorePacket>

000006a4 <handleSetupOrOut>:
;Setup and Out are followed by a data packet two bit times (16 cycles) after
;the end of SE0. The sync code allows up to 40 cycles delay from the start of
;the sync pattern until the first bit is sampled. That's a total of 56 cycles.
handleSetupOrOut:               ;[32]
#if USB_CFG_IMPLEMENT_FN_WRITEOUT   /* if we have data for endpoint != 0, set usbCurrentTok to address */
    andi    x3, 0xf             ;[32]
 6a4:	4f 70       	andi	r20, 0x0F	; 15
    breq    storeTokenAndReturn ;[33]
 6a6:	09 f0       	breq	.+2      	; 0x6aa <storeTokenAndReturn>
    mov     token, x3           ;[34] indicate that this is endpoint x OUT
 6a8:	04 2f       	mov	r16, r20

000006aa <storeTokenAndReturn>:
#endif
storeTokenAndReturn:
    sts     usbCurrentTok, token;[35]
 6aa:	00 93 a4 00 	sts	0x00A4, r16

000006ae <doReturn>:
doReturn:
    POP_STANDARD                ;[37] 12...16 cycles
 6ae:	3f 91       	pop	r19
 6b0:	4f 91       	pop	r20
 6b2:	1f 91       	pop	r17
 6b4:	0f 91       	pop	r16
 6b6:	2f 91       	pop	r18
 6b8:	df 91       	pop	r29
    USB_LOAD_PENDING(YL)        ;[49]
 6ba:	ca b7       	in	r28, 0x3a	; 58
    sbrc    YL, USB_INTR_PENDING_BIT;[50] check whether data is already arriving
 6bc:	c6 fd       	sbrc	r28, 6
    rjmp    waitForJ            ;[51] save the pops and pushes -- a new interrupt is already pending
 6be:	4c cf       	rjmp	.-360    	; 0x558 <waitForJ>

000006c0 <sofError>:
sofError:
    POP_RETI                    ;macro call
 6c0:	cf 91       	pop	r28
 6c2:	cf bf       	out	0x3f, r28	; 63
 6c4:	cf 91       	pop	r28
    reti
 6c6:	18 95       	reti

000006c8 <handleData>:

handleData:
#if USB_CFG_CHECK_CRC
    CRC_CLEANUP_AND_CHECK       ; jumps to ignorePacket if CRC error
#endif
    lds     shift, usbCurrentTok;[18]
 6c8:	20 91 a4 00 	lds	r18, 0x00A4
    tst     shift               ;[20]
 6cc:	22 23       	and	r18, r18
    breq    doReturn            ;[21]
 6ce:	79 f3       	breq	.-34     	; 0x6ae <doReturn>
    lds     x2, usbRxLen        ;[22]
 6d0:	10 91 a2 00 	lds	r17, 0x00A2
    tst     x2                  ;[24]
 6d4:	11 23       	and	r17, r17
    brne    sendNakAndReti      ;[25]
 6d6:	c1 f5       	brne	.+112    	; 0x748 <sendNakAndReti>
; 2006-03-11: The following two lines fix a problem where the device was not
; recognized if usbPoll() was called less frequently than once every 4 ms.
    cpi     cnt, 4              ;[26] zero sized data packets are status phase only -- ignore and ack
 6d8:	34 30       	cpi	r19, 0x04	; 4
    brmi    sendAckAndReti      ;[27] keep rx buffer clean -- we must not NAK next SETUP
 6da:	c2 f1       	brmi	.+112    	; 0x74c <sendAckAndReti>
#if USB_CFG_CHECK_DATA_TOGGLING
    sts     usbCurrentDataToken, token  ; store for checking by C code
#endif
    sts     usbRxLen, cnt       ;[28] store received data, swap buffers
 6dc:	30 93 a2 00 	sts	0x00A2, r19
    sts     usbRxToken, shift   ;[30]
 6e0:	20 93 9e 00 	sts	0x009E, r18
    lds     x2, usbInputBufOffset;[32] swap buffers
 6e4:	10 91 9f 00 	lds	r17, 0x009F
    ldi     cnt, USB_BUFSIZE    ;[34]
 6e8:	3b e0       	ldi	r19, 0x0B	; 11
    sub     cnt, x2             ;[35]
 6ea:	31 1b       	sub	r19, r17
    sts     usbInputBufOffset, cnt;[36] buffers now swapped
 6ec:	30 93 9f 00 	sts	0x009F, r19
    rjmp    sendAckAndReti      ;[38] 40 + 17 = 57 until SOP
 6f0:	2d c0       	rjmp	.+90     	; 0x74c <sendAckAndReti>

000006f2 <handleIn>:

handleIn:
;We don't send any data as long as the C code has not processed the current
;input data and potentially updated the output data. That's more efficient
;in terms of code size than clearing the tx buffers when a packet is received.
    lds     x1, usbRxLen        ;[30]
 6f2:	00 91 a2 00 	lds	r16, 0x00A2
    cpi     x1, 1               ;[32] negative values are flow control, 0 means "buffer free"
 6f6:	01 30       	cpi	r16, 0x01	; 1
    brge    sendNakAndReti      ;[33] unprocessed input packet?
 6f8:	3c f5       	brge	.+78     	; 0x748 <sendNakAndReti>
    ldi     x1, USBPID_NAK      ;[34] prepare value for usbTxLen
 6fa:	0a e5       	ldi	r16, 0x5A	; 90
#if USB_CFG_HAVE_INTRIN_ENDPOINT
    andi    x3, 0xf             ;[35] x3 contains endpoint
 6fc:	4f 70       	andi	r20, 0x0F	; 15
#if USB_CFG_SUPPRESS_INTR_CODE
    brne    sendNakAndReti      ;[36]
#else
    brne    handleIn1           ;[36]
 6fe:	49 f4       	brne	.+18     	; 0x712 <handleIn1>
#endif
#endif
    lds     cnt, usbTxLen       ;[37]
 700:	30 91 60 00 	lds	r19, 0x0060
    sbrc    cnt, 4              ;[39] all handshake tokens have bit 4 set
 704:	34 fd       	sbrc	r19, 4
    rjmp    sendCntAndReti      ;[40] 42 + 16 = 58 until SOP
 706:	24 c0       	rjmp	.+72     	; 0x750 <sendCntAndReti>
    sts     usbTxLen, x1        ;[41] x1 == USBPID_NAK from above
 708:	00 93 60 00 	sts	0x0060, r16
    ldi     YL, lo8(usbTxBuf)   ;[43]
 70c:	c6 e8       	ldi	r28, 0x86	; 134
    ldi     YH, hi8(usbTxBuf)   ;[44]
 70e:	d0 e0       	ldi	r29, 0x00	; 0
    rjmp    usbSendAndReti      ;[45] 57 + 12 = 59 until SOP
 710:	23 c0       	rjmp	.+70     	; 0x758 <usbSendAndReti>

00000712 <handleIn1>:

#if !USB_CFG_SUPPRESS_INTR_CODE && USB_CFG_HAVE_INTRIN_ENDPOINT /* placed here due to relative jump range */
handleIn1:                      ;[38]
#if USB_CFG_HAVE_INTRIN_ENDPOINT3
; 2006-06-10 as suggested by O.Tamura: support second INTR IN / BULK IN endpoint
    cpi     x3, USB_CFG_EP3_NUMBER;[38]
 712:	43 30       	cpi	r20, 0x03	; 3
    breq    handleIn3           ;[39]
 714:	49 f0       	breq	.+18     	; 0x728 <handleIn3>
#endif
    lds     cnt, usbTxLen1      ;[40]
 716:	30 91 91 00 	lds	r19, 0x0091
    sbrc    cnt, 4              ;[42] all handshake tokens have bit 4 set
 71a:	34 fd       	sbrc	r19, 4
    rjmp    sendCntAndReti      ;[43] 47 + 16 = 63 until SOP
 71c:	19 c0       	rjmp	.+50     	; 0x750 <sendCntAndReti>
    sts     usbTxLen1, x1       ;[44] x1 == USBPID_NAK from above
 71e:	00 93 91 00 	sts	0x0091, r16
    ldi     YL, lo8(usbTxBuf1)  ;[46]
 722:	c2 e9       	ldi	r28, 0x92	; 146
    ldi     YH, hi8(usbTxBuf1)  ;[47]
 724:	d0 e0       	ldi	r29, 0x00	; 0
    rjmp    usbSendAndReti      ;[48] 50 + 12 = 62 until SOP
 726:	18 c0       	rjmp	.+48     	; 0x758 <usbSendAndReti>

00000728 <handleIn3>:

#if USB_CFG_HAVE_INTRIN_ENDPOINT3
handleIn3:
    lds     cnt, usbTxLen3      ;[41]
 728:	30 91 bc 00 	lds	r19, 0x00BC
    sbrc    cnt, 4              ;[43]
 72c:	34 fd       	sbrc	r19, 4
    rjmp    sendCntAndReti      ;[44] 49 + 16 = 65 until SOP
 72e:	10 c0       	rjmp	.+32     	; 0x750 <sendCntAndReti>
    sts     usbTxLen3, x1       ;[45] x1 == USBPID_NAK from above
 730:	00 93 bc 00 	sts	0x00BC, r16
    ldi     YL, lo8(usbTxBuf3)  ;[47]
 734:	cd eb       	ldi	r28, 0xBD	; 189
    ldi     YH, hi8(usbTxBuf3)  ;[48]
 736:	d0 e0       	ldi	r29, 0x00	; 0
    rjmp    usbSendAndReti      ;[49] 51 + 12 = 63 until SOP
 738:	0f c0       	rjmp	.+30     	; 0x758 <usbSendAndReti>

0000073a <stuffN1Delay>:
;----------------------------------------------------------------------------

txByteLoop:
txBitloop:
stuffN1Delay:                   ;     [03]
    ror     shift               ;[-5] [11] [59]
 73a:	27 95       	ror	r18
    brcc    doExorN1            ;[-4]      [60]
 73c:	a8 f4       	brcc	.+42     	; 0x768 <doExorN1>
    subi    x4, 1               ;[-3]
 73e:	51 50       	subi	r21, 0x01	; 1
    brne    commonN1            ;[-2]
 740:	a9 f4       	brne	.+42     	; 0x76c <commonN1>
    lsl     shift               ;[-1] compensate ror after rjmp stuffDelay
 742:	22 0f       	add	r18, r18
    nop                         ;[00] stuffing consists of just waiting 8 cycles
 744:	00 00       	nop
    rjmp    stuffN1Delay        ;[01] after ror, C bit is reliably clear
 746:	f9 cf       	rjmp	.-14     	; 0x73a <stuffN1Delay>

00000748 <sendNakAndReti>:

sendNakAndReti:                 ;0 [-19] 19 cycles until SOP
    ldi     x3, USBPID_NAK      ;1 [-18]
 748:	4a e5       	ldi	r20, 0x5A	; 90
    rjmp    usbSendX3           ;2 [-16]
 74a:	03 c0       	rjmp	.+6      	; 0x752 <usbSendX3>

0000074c <sendAckAndReti>:
sendAckAndReti:                 ;0 [-19] 19 cycles until SOP
    ldi     x3, USBPID_ACK      ;1 [-18]
 74c:	42 ed       	ldi	r20, 0xD2	; 210
    rjmp    usbSendX3           ;2 [-16]
 74e:	01 c0       	rjmp	.+2      	; 0x752 <usbSendX3>

00000750 <sendCntAndReti>:
sendCntAndReti:                 ;0 [-17] 17 cycles until SOP
    mov     x3, cnt             ;1 [-16]
 750:	43 2f       	mov	r20, r19

00000752 <usbSendX3>:
usbSendX3:                      ;0 [-16]
    ldi     YL, 20              ;1 [-15] 'x3' is R20
 752:	c4 e1       	ldi	r28, 0x14	; 20
    ldi     YH, 0               ;1 [-14]
 754:	d0 e0       	ldi	r29, 0x00	; 0
    ldi     cnt, 2              ;1 [-13]
 756:	32 e0       	ldi	r19, 0x02	; 2

00000758 <usbSendAndReti>:
;pointer to data in 'Y'
;number of bytes in 'cnt' -- including sync byte
;uses: x1...x2, x4, shift, cnt, Y [x1 = mirror USBOUT, x2 = USBMASK, x4 = bitstuff cnt]
;Numbers in brackets are time since first bit of sync pattern is sent (start of instruction)
usbSendAndReti:
    in      x2, USBDDR          ;[-12] 12 cycles until SOP
 758:	11 b3       	in	r17, 0x11	; 17
    ori     x2, USBMASK         ;[-11]
 75a:	1c 60       	ori	r17, 0x0C	; 12
    sbi     USBOUT, USBMINUS    ;[-10] prepare idle state; D+ and D- must have been 0 (no pullups)
 75c:	93 9a       	sbi	0x12, 3	; 18
    out     USBDDR, x2          ;[-8] <--- acquire bus
 75e:	11 bb       	out	0x11, r17	; 17
    in      x1, USBOUT          ;[-7] port mirror for tx loop
 760:	02 b3       	in	r16, 0x12	; 18
    ldi     shift, 0x40         ;[-6] sync byte is first byte sent (we enter loop after ror)
 762:	20 e4       	ldi	r18, 0x40	; 64
    ldi     x2, USBMASK         ;[-5]
 764:	1c e0       	ldi	r17, 0x0C	; 12
    push    x4                  ;[-4]
 766:	5f 93       	push	r21

00000768 <doExorN1>:
doExorN1:
    eor     x1, x2              ;[-2] [06] [62]
 768:	01 27       	eor	r16, r17
    ldi     x4, 6               ;[-1] [07] [63]
 76a:	56 e0       	ldi	r21, 0x06	; 6

0000076c <commonN1>:
commonN1:
stuffN2Delay:
    out     USBOUT, x1          ;[00] [08] [64] <--- set bit
 76c:	02 bb       	out	0x12, r16	; 18
    ror     shift               ;[01]
 76e:	27 95       	ror	r18
    brcc    doExorN2            ;[02]
 770:	20 f4       	brcc	.+8      	; 0x77a <doExorN2>
    subi    x4, 1               ;[03]
 772:	51 50       	subi	r21, 0x01	; 1
    brne    commonN2            ;[04]
 774:	21 f4       	brne	.+8      	; 0x77e <commonN2>
    lsl     shift               ;[05] compensate ror after rjmp stuffDelay
 776:	22 0f       	add	r18, r18
    rjmp    stuffN2Delay        ;[06] after ror, C bit is reliably clear
 778:	f9 cf       	rjmp	.-14     	; 0x76c <commonN1>

0000077a <doExorN2>:
doExorN2:
    eor     x1, x2              ;[04] [12]
 77a:	01 27       	eor	r16, r17
    ldi     x4, 6               ;[05] [13]
 77c:	56 e0       	ldi	r21, 0x06	; 6

0000077e <commonN2>:
commonN2:
    nop                         ;[06] [14]
 77e:	00 00       	nop
    subi    cnt, 171            ;[07] [15] trick: (3 * 171) & 0xff = 1
 780:	3b 5a       	subi	r19, 0xAB	; 171
    out     USBOUT, x1          ;[08] [16] <--- set bit
 782:	02 bb       	out	0x12, r16	; 18
    brcs    txBitloop           ;[09]      [25] [41]
 784:	d0 f2       	brcs	.-76     	; 0x73a <stuffN1Delay>

00000786 <stuff6Delay>:

stuff6Delay:
    ror     shift               ;[42] [50]
 786:	27 95       	ror	r18
    brcc    doExor6             ;[43]
 788:	28 f4       	brcc	.+10     	; 0x794 <doExor6>
    subi    x4, 1               ;[44]
 78a:	51 50       	subi	r21, 0x01	; 1
    brne    common6             ;[45]
 78c:	29 f4       	brne	.+10     	; 0x798 <common6>
    lsl     shift               ;[46] compensate ror after rjmp stuffDelay
 78e:	22 0f       	add	r18, r18
    nop                         ;[47] stuffing consists of just waiting 8 cycles
 790:	00 00       	nop
    rjmp    stuff6Delay         ;[48] after ror, C bit is reliably clear
 792:	f9 cf       	rjmp	.-14     	; 0x786 <stuff6Delay>

00000794 <doExor6>:
doExor6:
    eor     x1, x2              ;[45] [53]
 794:	01 27       	eor	r16, r17
    ldi     x4, 6               ;[46]
 796:	56 e0       	ldi	r21, 0x06	; 6

00000798 <common6>:
common6:
stuff7Delay:
    ror     shift               ;[47] [55]
 798:	27 95       	ror	r18
    out     USBOUT, x1          ;[48] <--- set bit
 79a:	02 bb       	out	0x12, r16	; 18
    brcc    doExor7             ;[49]
 79c:	20 f4       	brcc	.+8      	; 0x7a6 <doExor7>
    subi    x4, 1               ;[50]
 79e:	51 50       	subi	r21, 0x01	; 1
    brne    common7             ;[51]
 7a0:	21 f4       	brne	.+8      	; 0x7aa <common7>
    lsl     shift               ;[52] compensate ror after rjmp stuffDelay
 7a2:	22 0f       	add	r18, r18
    rjmp    stuff7Delay         ;[53] after ror, C bit is reliably clear
 7a4:	f9 cf       	rjmp	.-14     	; 0x798 <common6>

000007a6 <doExor7>:
doExor7:
    eor     x1, x2              ;[51] [59]
 7a6:	01 27       	eor	r16, r17
    ldi     x4, 6               ;[52]
 7a8:	56 e0       	ldi	r21, 0x06	; 6

000007aa <common7>:
common7:
    ld      shift, y+           ;[53]
 7aa:	29 91       	ld	r18, Y+
    tst     cnt                 ;[55]
 7ac:	33 23       	and	r19, r19
    out     USBOUT, x1          ;[56] <--- set bit
 7ae:	02 bb       	out	0x12, r16	; 18
    brne    txByteLoop          ;[57]
 7b0:	21 f6       	brne	.-120    	; 0x73a <stuffN1Delay>

;make SE0:
    cbr     x1, USBMASK         ;[58] prepare SE0 [spec says EOP may be 15 to 18 cycles]
 7b2:	03 7f       	andi	r16, 0xF3	; 243
    lds     x2, usbNewDeviceAddr;[59]
 7b4:	10 91 a3 00 	lds	r17, 0x00A3
    lsl     x2                  ;[61] we compare with left shifted address
 7b8:	11 0f       	add	r17, r17
    subi    YL, 2 + 20          ;[62] Only assign address on data packets, not ACK/NAK in x3
 7ba:	c6 51       	subi	r28, 0x16	; 22
    sbci    YH, 0               ;[63]
 7bc:	d0 40       	sbci	r29, 0x00	; 0
    out     USBOUT, x1          ;[00] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle
 7be:	02 bb       	out	0x12, r16	; 18
;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
;set address only after data packet was sent, not after handshake
    breq    skipAddrAssign      ;[01]
 7c0:	11 f0       	breq	.+4      	; 0x7c6 <skipAddrAssign>
    sts     usbDeviceAddr, x2   ; if not skipped: SE0 is one cycle longer
 7c2:	10 93 9d 00 	sts	0x009D, r17

000007c6 <skipAddrAssign>:
skipAddrAssign:
;end of usbDeviceAddress transfer
    ldi     x2, 1<<USB_INTR_PENDING_BIT;[03] int0 occurred during TX -- clear pending flag
 7c6:	10 e4       	ldi	r17, 0x40	; 64
    USB_STORE_PENDING(x2)       ;[04]
 7c8:	1a bf       	out	0x3a, r17	; 58
    ori     x1, USBIDLE         ;[05]
 7ca:	08 60       	ori	r16, 0x08	; 8
    in      x2, USBDDR          ;[06]
 7cc:	11 b3       	in	r17, 0x11	; 17
    cbr     x2, USBMASK         ;[07] set both pins to input
 7ce:	13 7f       	andi	r17, 0xF3	; 243
    mov     x3, x1              ;[08]
 7d0:	40 2f       	mov	r20, r16
    cbr     x3, USBMASK         ;[09] configure no pullup on both pins
 7d2:	43 7f       	andi	r20, 0xF3	; 243
    pop     x4                  ;[10]
 7d4:	5f 91       	pop	r21
    nop2                        ;[12]
 7d6:	00 c0       	rjmp	.+0      	; 0x7d8 <skipAddrAssign+0x12>
    nop2                        ;[14]
 7d8:	00 c0       	rjmp	.+0      	; 0x7da <skipAddrAssign+0x14>
    out     USBOUT, x1          ;[16] <-- out J (idle) -- end of SE0 (EOP signal)
 7da:	02 bb       	out	0x12, r16	; 18
    out     USBDDR, x2          ;[17] <-- release bus now
 7dc:	11 bb       	out	0x11, r17	; 17
    out     USBOUT, x3          ;[18] <-- ensure no pull-up resistors are active
 7de:	42 bb       	out	0x12, r20	; 18
    rjmp    doReturn
 7e0:	66 cf       	rjmp	.-308    	; 0x6ae <doReturn>

000007e2 <_exit>:
 7e2:	f8 94       	cli

000007e4 <__stop_program>:
 7e4:	ff cf       	rjmp	.-2      	; 0x7e4 <__stop_program>
