2  * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers 
   3  * Author: Christian Starkjohann 
   4  * Creation Date: 2004-12-29 
   6  * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH 
   7  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) 
  11 #include "usbportability.h" 
  17 This module implements the C-part of the USB driver. See usbdrv.h for a 
  18 documentation of the entire driver. 
  21 /* ------------------------------------------------------------------------- */ 
  23 /* raw USB registers / interface to assembler code: */ 
  24 uchar usbRxBuf
[2*USB_BUFSIZE
];  /* raw RX buffer: PID, 8 bytes data, 2 bytes CRC */ 
  25 uchar       usbInputBufOffset
;  /* offset in usbRxBuf used for low level receiving */ 
  26 uchar       usbDeviceAddr
;      /* assigned during enumeration, defaults to 0 */ 
  27 uchar       usbNewDeviceAddr
;   /* device ID which should be set after status phase */ 
  28 uchar       usbConfiguration
;   /* currently selected configuration. Administered by driver, but not used */ 
  29 volatile schar usbRxLen
;        /* = 0; number of bytes in usbRxBuf; 0 means free, -1 for flow control */ 
  30 uchar       usbCurrentTok
;      /* last token received or endpoint number for last OUT token if != 0 */ 
  31 uchar       usbRxToken
;         /* token for data we received; or endpont number for last OUT */ 
  32 volatile uchar usbTxLen 
= USBPID_NAK
;   /* number of bytes to transmit with next IN token or handshake token */ 
  33 uchar       usbTxBuf
[USB_BUFSIZE
];/* data to transmit with next IN, free if usbTxLen contains handshake token */ 
  35 volatile uchar  usbSofCount
;    /* incremented by assembler module every SOF */ 
  37 #if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE 
  38 usbTxStatus_t  usbTxStatus1
; 
  39 #   if USB_CFG_HAVE_INTRIN_ENDPOINT3 
  40 usbTxStatus_t  usbTxStatus3
; 
  43 #if USB_CFG_CHECK_DATA_TOGGLING 
  44 uchar       usbCurrentDataToken
;/* when we check data toggling to ignore duplicate packets */ 
  47 /* USB status registers / not shared with asm code */ 
  48 uchar               
*usbMsgPtr
;     /* data to transmit next -- ROM or RAM address */ 
  49 static usbMsgLen_t  usbMsgLen 
= USB_NO_MSG
; /* remaining number of bytes */ 
  50 static uchar        usbMsgFlags
;    /* flag values see below */ 
  52 #define USB_FLG_MSGPTR_IS_ROM   (1<<6) 
  53 #define USB_FLG_USE_USER_RW     (1<<7) 
  57 - do not post/pre inc/dec integer values in operations 
  58 - assign value of USB_READ_FLASH() to register variables and don't use side effects in arg 
  59 - use narrow scope for variables which should be in X/Y/Z register 
  60 - assign char sized expressions to variables to force 8 bit arithmetics 
  63 /* -------------------------- String Descriptors --------------------------- */ 
  65 #if USB_CFG_DESCR_PROPS_STRINGS == 0 
  67 #if USB_CFG_DESCR_PROPS_STRING_0 == 0 
  68 #undef USB_CFG_DESCR_PROPS_STRING_0 
  69 #define USB_CFG_DESCR_PROPS_STRING_0    sizeof(usbDescriptorString0) 
  70 PROGMEM 
const char usbDescriptorString0
[] = { /* language descriptor */ 
  71     4,          /* sizeof(usbDescriptorString0): length of descriptor in bytes */ 
  72     3,          /* descriptor type */ 
  73     0x09, 0x04, /* language index (0x0409 = US-English) */ 
  77 #if USB_CFG_DESCR_PROPS_STRING_VENDOR == 0 && USB_CFG_VENDOR_NAME_LEN 
  78 #undef USB_CFG_DESCR_PROPS_STRING_VENDOR 
  79 #define USB_CFG_DESCR_PROPS_STRING_VENDOR   sizeof(usbDescriptorStringVendor) 
  80 PROGMEM 
const int  usbDescriptorStringVendor
[] = { 
  81     USB_STRING_DESCRIPTOR_HEADER(USB_CFG_VENDOR_NAME_LEN
), 
  86 #if USB_CFG_DESCR_PROPS_STRING_PRODUCT == 0 && USB_CFG_DEVICE_NAME_LEN 
  87 #undef USB_CFG_DESCR_PROPS_STRING_PRODUCT 
  88 #define USB_CFG_DESCR_PROPS_STRING_PRODUCT   sizeof(usbDescriptorStringDevice) 
  89 PROGMEM 
const int  usbDescriptorStringDevice
[] = { 
  90     USB_STRING_DESCRIPTOR_HEADER(USB_CFG_DEVICE_NAME_LEN
), 
  95 #if USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER == 0 && USB_CFG_SERIAL_NUMBER_LEN 
  96 #undef USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 
  97 #define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER    sizeof(usbDescriptorStringSerialNumber) 
  98 PROGMEM 
const int usbDescriptorStringSerialNumber
[] = { 
  99     USB_STRING_DESCRIPTOR_HEADER(USB_CFG_SERIAL_NUMBER_LEN
), 
 100     USB_CFG_SERIAL_NUMBER
 
 104 #endif  /* USB_CFG_DESCR_PROPS_STRINGS == 0 */ 
 106 /* --------------------------- Device Descriptor --------------------------- */ 
 108 #if USB_CFG_DESCR_PROPS_DEVICE == 0 
 109 #undef USB_CFG_DESCR_PROPS_DEVICE 
 110 #define USB_CFG_DESCR_PROPS_DEVICE  sizeof(usbDescriptorDevice) 
 111 PROGMEM 
const char usbDescriptorDevice
[] = {    /* USB device descriptor */ 
 112     18,         /* sizeof(usbDescriptorDevice): length of descriptor in bytes */ 
 113     USBDESCR_DEVICE
,        /* descriptor type */ 
 114     0x10, 0x01,             /* USB version supported */ 
 115     USB_CFG_DEVICE_CLASS
, 
 116     USB_CFG_DEVICE_SUBCLASS
, 
 118     8,                      /* max packet size */ 
 119     /* the following two casts affect the first byte of the constant only, but 
 120      * that's sufficient to avoid a warning with the default values. 
 122     (char)USB_CFG_VENDOR_ID
,/* 2 bytes */ 
 123     (char)USB_CFG_DEVICE_ID
,/* 2 bytes */ 
 124     USB_CFG_DEVICE_VERSION
, /* 2 bytes */ 
 125     USB_CFG_DESCR_PROPS_STRING_VENDOR 
!= 0 ? 
1 : 0,         /* manufacturer string index */ 
 126     USB_CFG_DESCR_PROPS_STRING_PRODUCT 
!= 0 ? 
2 : 0,        /* product string index */ 
 127     USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 
!= 0 ? 
3 : 0,  /* serial number string index */ 
 128     1,          /* number of configurations */ 
 132 /* ----------------------- Configuration Descriptor ------------------------ */ 
 134 #if USB_CFG_DESCR_PROPS_HID_REPORT != 0 && USB_CFG_DESCR_PROPS_HID == 0 
 135 #undef USB_CFG_DESCR_PROPS_HID 
 136 #define USB_CFG_DESCR_PROPS_HID     9   /* length of HID descriptor in config descriptor below */ 
 139 #if USB_CFG_DESCR_PROPS_CONFIGURATION == 0 
 140 #undef USB_CFG_DESCR_PROPS_CONFIGURATION 
 141 #define USB_CFG_DESCR_PROPS_CONFIGURATION   sizeof(usbDescriptorConfiguration) 
 142 PROGMEM 
const char usbDescriptorConfiguration
[] = {    /* USB configuration descriptor */ 
 143     9,          /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */ 
 144     USBDESCR_CONFIG
,    /* descriptor type */ 
 145     18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT 
+ 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 
+ 
 146                 (USB_CFG_DESCR_PROPS_HID 
& 0xff), 0, 
 147                 /* total length of data returned (including inlined descriptors) */ 
 148     1,          /* number of interfaces in this configuration */ 
 149     1,          /* index of this configuration */ 
 150     0,          /* configuration name string index */ 
 151 #if USB_CFG_IS_SELF_POWERED 
 152     (1 << 7) | USBATTR_SELFPOWER
,       /* attributes */ 
 154     (1 << 7),                           /* attributes */ 
 156     USB_CFG_MAX_BUS_POWER
/2,            /* max USB current in 2mA units */ 
 157 /* interface descriptor follows inline: */ 
 158     9,          /* sizeof(usbDescrInterface): length of descriptor in bytes */ 
 159     USBDESCR_INTERFACE
, /* descriptor type */ 
 160     0,          /* index of this interface */ 
 161     0,          /* alternate setting for this interface */ 
 162     USB_CFG_HAVE_INTRIN_ENDPOINT 
+ USB_CFG_HAVE_INTRIN_ENDPOINT3
, /* endpoints excl 0: number of endpoint descriptors to follow */ 
 163     USB_CFG_INTERFACE_CLASS
, 
 164     USB_CFG_INTERFACE_SUBCLASS
, 
 165     USB_CFG_INTERFACE_PROTOCOL
, 
 166     0,          /* string index for interface */ 
 167 #if (USB_CFG_DESCR_PROPS_HID & 0xff)    /* HID descriptor */ 
 168     9,          /* sizeof(usbDescrHID): length of descriptor in bytes */ 
 169     USBDESCR_HID
,   /* descriptor type: HID */ 
 170     0x01, 0x01, /* BCD representation of HID version */ 
 171     0x00,       /* target country code */ 
 172     0x01,       /* number of HID Report (or other HID class) Descriptor infos to follow */ 
 173     0x22,       /* descriptor type: report */ 
 174     USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH
, 0,  /* total length of report descriptor */ 
 176 #if USB_CFG_HAVE_INTRIN_ENDPOINT    /* endpoint descriptor for endpoint 1 */ 
 177     7,          /* sizeof(usbDescrEndpoint) */ 
 178     USBDESCR_ENDPOINT
,  /* descriptor type = endpoint */ 
 179     (char)0x81, /* IN endpoint number 1 */ 
 180     0x03,       /* attrib: Interrupt endpoint */ 
 181     8, 0,       /* maximum packet size */ 
 182     USB_CFG_INTR_POLL_INTERVAL
, /* in ms */ 
 184 #if USB_CFG_HAVE_INTRIN_ENDPOINT3   /* endpoint descriptor for endpoint 3 */ 
 185     7,          /* sizeof(usbDescrEndpoint) */ 
 186     USBDESCR_ENDPOINT
,  /* descriptor type = endpoint */ 
 187     (char)(0x80 | USB_CFG_EP3_NUMBER
), /* IN endpoint number 3 */ 
 188     0x03,       /* attrib: Interrupt endpoint */ 
 189     8, 0,       /* maximum packet size */ 
 190     USB_CFG_INTR_POLL_INTERVAL
, /* in ms */ 
 195 /* ------------------------------------------------------------------------- */ 
 197 static inline void  usbResetDataToggling(void) 
 199 #if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE 
 200     USB_SET_DATATOKEN1(USB_INITIAL_DATATOKEN
);  /* reset data toggling for interrupt endpoint */ 
 201 #   if USB_CFG_HAVE_INTRIN_ENDPOINT3 
 202     USB_SET_DATATOKEN3(USB_INITIAL_DATATOKEN
);  /* reset data toggling for interrupt endpoint */ 
 207 static inline void  usbResetStall(void) 
 209 #if USB_CFG_IMPLEMENT_HALT && USB_CFG_HAVE_INTRIN_ENDPOINT 
 210         usbTxLen1 
= USBPID_NAK
; 
 211 #if USB_CFG_HAVE_INTRIN_ENDPOINT3 
 212         usbTxLen3 
= USBPID_NAK
; 
 217 /* ------------------------------------------------------------------------- */ 
 219 #if !USB_CFG_SUPPRESS_INTR_CODE 
 220 #if USB_CFG_HAVE_INTRIN_ENDPOINT 
 221 static void usbGenericSetInterrupt(uchar 
*data
, uchar len
, usbTxStatus_t 
*txStatus
) 
 226 #if USB_CFG_IMPLEMENT_HALT 
 227     if(usbTxLen1 
== USBPID_STALL
) 
 230     if(txStatus
->len 
& 0x10){   /* packet buffer was empty */ 
 231         txStatus
->buffer
[0] ^= USBPID_DATA0 
^ USBPID_DATA1
; /* toggle token */ 
 233         txStatus
->len 
= USBPID_NAK
; /* avoid sending outdated (overwritten) interrupt data */ 
 235     p 
= txStatus
->buffer 
+ 1; 
 237     do{                         /* if len == 0, we still copy 1 byte, but that's no problem */ 
 239     }while(--i 
> 0);            /* loop control at the end is 2 bytes shorter than at beginning */ 
 240     usbCrc16Append(&txStatus
->buffer
[1], len
); 
 241     txStatus
->len 
= len 
+ 4;    /* len must be given including sync byte */ 
 242     DBG2(0x21 + (((int)txStatus 
>> 3) & 3), txStatus
->buffer
, len 
+ 3); 
 245 USB_PUBLIC 
void usbSetInterrupt(uchar 
*data
, uchar len
) 
 247     usbGenericSetInterrupt(data
, len
, &usbTxStatus1
); 
 251 #if USB_CFG_HAVE_INTRIN_ENDPOINT3 
 252 USB_PUBLIC 
void usbSetInterrupt3(uchar 
*data
, uchar len
) 
 254     usbGenericSetInterrupt(data
, len
, &usbTxStatus3
); 
 257 #endif /* USB_CFG_SUPPRESS_INTR_CODE */ 
 259 /* ------------------ utilities for code following below ------------------- */ 
 261 /* Use defines for the switch statement so that we can choose between an 
 262  * if()else if() and a switch/case based implementation. switch() is more 
 263  * efficient for a LARGE set of sequential choices, if() is better in all other 
 266 #if USB_CFG_USE_SWITCH_STATEMENT 
 267 #   define SWITCH_START(cmd)       switch(cmd){{ 
 268 #   define SWITCH_CASE(value)      }break; case (value):{ 
 269 #   define SWITCH_CASE2(v1,v2)     }break; case (v1): case(v2):{ 
 270 #   define SWITCH_CASE3(v1,v2,v3)  }break; case (v1): case(v2): case(v3):{ 
 271 #   define SWITCH_DEFAULT          }break; default:{ 
 272 #   define SWITCH_END              }} 
 274 #   define SWITCH_START(cmd)       {uchar _cmd = cmd; if(0){ 
 275 #   define SWITCH_CASE(value)      }else if(_cmd == (value)){ 
 276 #   define SWITCH_CASE2(v1,v2)     }else if(_cmd == (v1) || _cmd == (v2)){ 
 277 #   define SWITCH_CASE3(v1,v2,v3)  }else if(_cmd == (v1) || _cmd == (v2) || (_cmd == v3)){ 
 278 #   define SWITCH_DEFAULT          }else{ 
 279 #   define SWITCH_END              }} 
 282 #ifndef USB_RX_USER_HOOK 
 283 #define USB_RX_USER_HOOK(data, len) 
 285 #ifndef USB_SET_ADDRESS_HOOK 
 286 #define USB_SET_ADDRESS_HOOK() 
 289 /* ------------------------------------------------------------------------- */ 
 291 /* We use if() instead of #if in the macro below because #if can't be used 
 292  * in macros and the compiler optimizes constant conditions anyway. 
 293  * This may cause problems with undefined symbols if compiled without 
 296 #define GET_DESCRIPTOR(cfgProp, staticName)         \ 
 298         if((cfgProp) & USB_PROP_IS_RAM)             \ 
 300         if((cfgProp) & USB_PROP_IS_DYNAMIC){        \ 
 301             len = usbFunctionDescriptor(rq);        \ 
 303             len = USB_PROP_LENGTH(cfgProp);         \ 
 304             usbMsgPtr = (uchar *)(staticName);      \ 
 308 /* usbDriverDescriptor() is similar to usbFunctionDescriptor(), but used 
 309  * internally for all types of descriptors. 
 311 static inline usbMsgLen_t 
usbDriverDescriptor(usbRequest_t 
*rq
) 
 314 uchar       flags 
= USB_FLG_MSGPTR_IS_ROM
; 
 316     SWITCH_START(rq
->wValue
.bytes
[1]) 
 317     SWITCH_CASE(USBDESCR_DEVICE
)    /* 1 */ 
 318         GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_DEVICE
, usbDescriptorDevice
) 
 319     SWITCH_CASE(USBDESCR_CONFIG
)    /* 2 */ 
 320         GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_CONFIGURATION
, usbDescriptorConfiguration
) 
 321     SWITCH_CASE(USBDESCR_STRING
)    /* 3 */ 
 322 #if USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC 
 323         if(USB_CFG_DESCR_PROPS_STRINGS 
& USB_PROP_IS_RAM
) 
 325         len 
= usbFunctionDescriptor(rq
); 
 326 #else   /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */ 
 327         SWITCH_START(rq
->wValue
.bytes
[0]) 
 329             GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_0
, usbDescriptorString0
) 
 331             GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_VENDOR
, usbDescriptorStringVendor
) 
 333             GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_PRODUCT
, usbDescriptorStringDevice
) 
 335             GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER
, usbDescriptorStringSerialNumber
) 
 337             if(USB_CFG_DESCR_PROPS_UNKNOWN 
& USB_PROP_IS_DYNAMIC
){ 
 338                 len 
= usbFunctionDescriptor(rq
); 
 341 #endif  /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */ 
 342 #if USB_CFG_DESCR_PROPS_HID_REPORT  /* only support HID descriptors if enabled */ 
 343     SWITCH_CASE(USBDESCR_HID
)       /* 0x21 */ 
 344         GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID
, usbDescriptorConfiguration 
+ 18) 
 345     SWITCH_CASE(USBDESCR_HID_REPORT
)/* 0x22 */ 
 346         GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID_REPORT
, usbDescriptorHidReport
) 
 349         if(USB_CFG_DESCR_PROPS_UNKNOWN 
& USB_PROP_IS_DYNAMIC
){ 
 350             len 
= usbFunctionDescriptor(rq
); 
 357 /* ------------------------------------------------------------------------- */ 
 359 /* usbDriverSetup() is similar to usbFunctionSetup(), but it's used for 
 360  * standard requests instead of class and custom requests. 
 362 static inline usbMsgLen_t 
usbDriverSetup(usbRequest_t 
*rq
) 
 365 uchar   
*dataPtr 
= usbTxBuf 
+ 9;    /* there are 2 bytes free space at the end of the buffer */ 
 366 uchar   value 
= rq
->wValue
.bytes
[0]; 
 367 #if USB_CFG_IMPLEMENT_HALT 
 368 uchar   index 
= rq
->wIndex
.bytes
[0]; 
 371     dataPtr
[0] = 0; /* default reply common to USBRQ_GET_STATUS and USBRQ_GET_INTERFACE */ 
 372     SWITCH_START(rq
->bRequest
) 
 373     SWITCH_CASE(USBRQ_GET_STATUS
)           /* 0 */ 
 374         uchar recipient 
= rq
->bmRequestType 
& USBRQ_RCPT_MASK
;  /* assign arith ops to variables to enforce byte size */ 
 375         if(USB_CFG_IS_SELF_POWERED 
&& recipient 
== USBRQ_RCPT_DEVICE
) 
 376             dataPtr
[0] =  USB_CFG_IS_SELF_POWERED
; 
 377 #if USB_CFG_IMPLEMENT_HALT 
 378         if(recipient 
== USBRQ_RCPT_ENDPOINT 
&& index 
== 0x81)   /* request status for endpoint 1 */ 
 379             dataPtr
[0] = usbTxLen1 
== USBPID_STALL
; 
 383 #if USB_CFG_IMPLEMENT_HALT 
 384     SWITCH_CASE2(USBRQ_CLEAR_FEATURE
, USBRQ_SET_FEATURE
)    /* 1, 3 */ 
 385         if(value 
== 0 && index 
== 0x81){    /* feature 0 == HALT for endpoint == 1 */ 
 386             usbTxLen1 
= rq
->bRequest 
== USBRQ_CLEAR_FEATURE ? USBPID_NAK 
: USBPID_STALL
; 
 387             usbResetDataToggling(); 
 390     SWITCH_CASE(USBRQ_SET_ADDRESS
)          /* 5 */ 
 391         usbNewDeviceAddr 
= value
; 
 392         USB_SET_ADDRESS_HOOK(); 
 393     SWITCH_CASE(USBRQ_GET_DESCRIPTOR
)       /* 6 */ 
 394         len 
= usbDriverDescriptor(rq
); 
 395         goto skipMsgPtrAssignment
; 
 396     SWITCH_CASE(USBRQ_GET_CONFIGURATION
)    /* 8 */ 
 397         dataPtr 
= &usbConfiguration
;  /* send current configuration value */ 
 399     SWITCH_CASE(USBRQ_SET_CONFIGURATION
)    /* 9 */ 
 400         usbConfiguration 
= value
; 
 402     SWITCH_CASE(USBRQ_GET_INTERFACE
)        /* 10 */ 
 404 #if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE 
 405     SWITCH_CASE(USBRQ_SET_INTERFACE
)        /* 11 */ 
 406         usbResetDataToggling(); 
 409     SWITCH_DEFAULT                          
/* 7=SET_DESCRIPTOR, 12=SYNC_FRAME */ 
 410         /* Should we add an optional hook here? */ 
 413 skipMsgPtrAssignment
: 
 417 /* ------------------------------------------------------------------------- */ 
 419 /* usbProcessRx() is called for every message received by the interrupt 
 420  * routine. It distinguishes between SETUP and DATA packets and processes 
 423 static inline void usbProcessRx(uchar 
*data
, uchar len
) 
 425 usbRequest_t    
*rq 
= (void *)data
; 
 427 /* usbRxToken can be: 
 428  * 0x2d 00101101 (USBPID_SETUP for setup data) 
 429  * 0xe1 11100001 (USBPID_OUT: data phase of setup transfer) 
 430  * 0...0x0f for OUT on endpoint X 
 432     DBG2(0x10 + (usbRxToken 
& 0xf), data
, len 
+ 2); /* SETUP=1d, SETUP-DATA=11, OUTx=1x */ 
 433     USB_RX_USER_HOOK(data
, len
) 
 434 #if USB_CFG_IMPLEMENT_FN_WRITEOUT 
 435     if(usbRxToken 
< 0x10){  /* OUT to endpoint != 0: endpoint number in usbRxToken */ 
 436         usbFunctionWriteOut(data
, len
); 
 440     if(usbRxToken 
== (uchar
)USBPID_SETUP
){ 
 441         if(len 
!= 8)    /* Setup size must be always 8 bytes. Ignore otherwise. */ 
 443         usbMsgLen_t replyLen
; 
 444         usbTxBuf
[0] = USBPID_DATA0
;         /* initialize data toggling */ 
 445         usbTxLen 
= USBPID_NAK
;              /* abort pending transmit */ 
 447         uchar type 
= rq
->bmRequestType 
& USBRQ_TYPE_MASK
; 
 448         if(type 
!= USBRQ_TYPE_STANDARD
){    /* standard requests are handled by driver */ 
 449             replyLen 
= usbFunctionSetup(data
); 
 451             replyLen 
= usbDriverSetup(rq
); 
 453 #if USB_CFG_IMPLEMENT_FN_READ || USB_CFG_IMPLEMENT_FN_WRITE 
 454         if(replyLen 
== USB_NO_MSG
){         /* use user-supplied read/write function */ 
 455             /* do some conditioning on replyLen, but on IN transfers only */ 
 456             if((rq
->bmRequestType 
& USBRQ_DIR_MASK
) != USBRQ_DIR_HOST_TO_DEVICE
){ 
 457                 if(sizeof(replyLen
) < sizeof(rq
->wLength
.word
)){ /* help compiler with optimizing */ 
 458                     replyLen 
= rq
->wLength
.bytes
[0]; 
 460                     replyLen 
= rq
->wLength
.word
; 
 463             usbMsgFlags 
= USB_FLG_USE_USER_RW
; 
 464         }else   /* The 'else' prevents that we limit a replyLen of USB_NO_MSG to the maximum transfer len. */ 
 466         if(sizeof(replyLen
) < sizeof(rq
->wLength
.word
)){ /* help compiler with optimizing */ 
 467             if(!rq
->wLength
.bytes
[1] && replyLen 
> rq
->wLength
.bytes
[0])    /* limit length to max */ 
 468                 replyLen 
= rq
->wLength
.bytes
[0]; 
 470             if(replyLen 
> rq
->wLength
.word
)     /* limit length to max */ 
 471                 replyLen 
= rq
->wLength
.word
; 
 473         usbMsgLen 
= replyLen
; 
 474     }else{  /* usbRxToken must be USBPID_OUT, which means data phase of setup (control-out) */ 
 475 #if USB_CFG_IMPLEMENT_FN_WRITE 
 476         if(usbMsgFlags 
& USB_FLG_USE_USER_RW
){ 
 477             uchar rval 
= usbFunctionWrite(data
, len
); 
 478             if(rval 
== 0xff){   /* an error occurred */ 
 479                 usbTxLen 
= USBPID_STALL
; 
 480             }else if(rval 
!= 0){    /* This was the final package */ 
 481                 usbMsgLen 
= 0;  /* answer with a zero-sized data packet */ 
 488 /* ------------------------------------------------------------------------- */ 
 490 /* This function is similar to usbFunctionRead(), but it's also called for 
 491  * data handled automatically by the driver (e.g. descriptor reads). 
 493 static uchar 
usbDeviceRead(uchar 
*data
, uchar len
) 
 495     if(len 
> 0){    /* don't bother app with 0 sized reads */ 
 496 #if USB_CFG_IMPLEMENT_FN_READ 
 497         if(usbMsgFlags 
& USB_FLG_USE_USER_RW
){ 
 498             len 
= usbFunctionRead(data
, len
); 
 502             uchar i 
= len
, *r 
= usbMsgPtr
; 
 503             if(usbMsgFlags 
& USB_FLG_MSGPTR_IS_ROM
){    /* ROM data */ 
 505                     uchar c 
= USB_READ_FLASH(r
);    /* assign to char size variable to enforce byte ops */ 
 509             }else{  /* RAM data */ 
 520 /* ------------------------------------------------------------------------- */ 
 522 /* usbBuildTxBlock() is called when we have data to transmit and the 
 523  * interrupt routine's transmit buffer is empty. 
 525 static inline void usbBuildTxBlock(void) 
 533     usbMsgLen 
-= wantLen
; 
 534     usbTxBuf
[0] ^= USBPID_DATA0 
^ USBPID_DATA1
; /* DATA toggling */ 
 535     len 
= usbDeviceRead(usbTxBuf 
+ 1, wantLen
); 
 536     if(len 
<= 8){           /* valid data packet */ 
 537         usbCrc16Append(&usbTxBuf
[1], len
); 
 538         len 
+= 4;           /* length including sync byte */ 
 539         if(len 
< 12)        /* a partial package identifies end of message */ 
 540             usbMsgLen 
= USB_NO_MSG
; 
 542         len 
= USBPID_STALL
;   /* stall the endpoint */ 
 543         usbMsgLen 
= USB_NO_MSG
; 
 546     DBG2(0x20, usbTxBuf
, len
-1); 
 549 /* ------------------------------------------------------------------------- */ 
 551 static inline void usbHandleResetHook(uchar notResetState
) 
 553 #ifdef USB_RESET_HOOK 
 554 static uchar    wasReset
; 
 555 uchar           isReset 
= !notResetState
; 
 557     if(wasReset 
!= isReset
){ 
 558         USB_RESET_HOOK(isReset
); 
 562     notResetState 
= notResetState
;  // avoid compiler warning 
 566 /* ------------------------------------------------------------------------- */ 
 568 USB_PUBLIC 
void usbPoll(void) 
 575 /* We could check CRC16 here -- but ACK has already been sent anyway. If you 
 576  * need data integrity checks with this driver, check the CRC in your app 
 577  * code and report errors back to the host. Since the ACK was already sent, 
 578  * retries must be handled on application level. 
 579  * unsigned crc = usbCrc16(buffer + 1, usbRxLen - 3); 
 581         usbProcessRx(usbRxBuf 
+ USB_BUFSIZE 
+ 1 - usbInputBufOffset
, len
); 
 582 #if USB_CFG_HAVE_FLOWCONTROL 
 583         if(usbRxLen 
> 0)    /* only mark as available if not inactivated */ 
 586         usbRxLen 
= 0;       /* mark rx buffer as available */ 
 589     if(usbTxLen 
& 0x10){    /* transmit system idle */ 
 590         if(usbMsgLen 
!= USB_NO_MSG
){    /* transmit data pending? */ 
 594     for(i 
= 20; i 
> 0; i
--){ 
 595         uchar usbLineStatus 
= USBIN 
& USBMASK
; 
 596         if(usbLineStatus 
!= 0)  /* SE0 has ended */ 
 599     /* RESET condition, called multiple times during reset */ 
 600     usbNewDeviceAddr 
= 0; 
 605     usbHandleResetHook(i
); 
 608 /* ------------------------------------------------------------------------- */ 
 610 USB_PUBLIC 
void usbInit(void) 
 612 #if USB_INTR_CFG_SET != 0 
 613     USB_INTR_CFG 
|= USB_INTR_CFG_SET
; 
 615 #if USB_INTR_CFG_CLR != 0 
 616     USB_INTR_CFG 
&= ~(USB_INTR_CFG_CLR
); 
 618     USB_INTR_ENABLE 
|= (1 << USB_INTR_ENABLE_BIT
); 
 619     usbResetDataToggling(); 
 620 #if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE 
 621     usbTxLen1 
= USBPID_NAK
; 
 622 #if USB_CFG_HAVE_INTRIN_ENDPOINT3 
 623     usbTxLen3 
= USBPID_NAK
; 
 628 /* ------------------------------------------------------------------------- */