⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbdrv.c

📁 制作AVR下在线
💻 C
📖 第 1 页 / 共 2 页
字号:
    }  
#endif   
}  
  
  
#define GET_DESCRIPTOR(cfgProp, staticName)         \   
    if(cfgProp){                                    \  
        if((cfgProp) & USB_PROP_IS_RAM)             \  
            flags &= ~USB_FLG_MSGPTR_IS_ROM;        \  
        if((cfgProp) & USB_PROP_IS_DYNAMIC){        \  
            replyLen = usbFunctionDescriptor(rq);   \  
        }else{                                      \  
            replyData = (uchar *)(staticName);      \  
            SET_REPLY_LEN((cfgProp) & 0xff);        \  
        }                                           \  
    }  
/* We use if() instead of #if in the macro above because #if can't be used 
 * in macros and the compiler optimizes constant conditions anyway. 
 */  
  
  
/* Don't make this function static to avoid inlining. 
 * The entire function would become too large and exceed the range of 
 * relative jumps. 
 * 2006-02-25: Either gcc 3.4.3 is better than the gcc used when the comment 
 * above was written, or other parts of the code have changed. We now get 
 * better results with an inlined function. Test condition: PowerSwitch code. 
 */  
static void usbProcessRx(uchar *data, uchar len)  
{  
usbRequest_t    *rq = (void *)data;  
uchar           replyLen = 0, flags = USB_FLG_USE_DEFAULT_RW;  
/* We use if() cascades because the compare is done byte-wise while switch() 
 * is int-based. The if() cascades are therefore more efficient. 
 */  
/* usbRxToken can be: 
 * 0x2d 00101101 (USBPID_SETUP for endpoint 0) 
 * 0xe1 11100001 (USBPID_OUT for endpoint 0) 
 * 0xff 11111111 (USBPID_OUT for endpoint 1) 
 */  
    DBG2(0x10 + ((usbRxToken >> 1) & 3), data, len);    /* SETUP0=12; OUT0=10; OUT1=13 */  
#if USB_CFG_IMPLEMENT_FN_WRITEOUT   
    if(usbRxToken == 0xff){  
        usbFunctionWriteOut(data, len);  
        return; /* no reply expected, hence no usbMsgPtr, usbMsgFlags, usbMsgLen set */  
    }  
#endif   
    if(usbRxToken == (uchar)USBPID_SETUP){  
        usbTxLen = USBPID_NAK;  /* abort pending transmit */  
        if(len == 8){   /* Setup size must be always 8 bytes. Ignore otherwise. */  
            uchar type = rq->bmRequestType & USBRQ_TYPE_MASK;  
            if(type == USBRQ_TYPE_STANDARD){  
                #define SET_REPLY_LEN(len)  replyLen = (len); usbMsgPtr = replyData   
                /* This macro ensures that replyLen and usbMsgPtr are always set in the same way. 
                 * That allows optimization of common code in if() branches */  
                uchar *replyData = usbTxBuf + 9; /* there is 3 bytes free space at the end of the buffer */  
                replyData[0] = 0;   /* common to USBRQ_GET_STATUS and USBRQ_GET_INTERFACE */  
                if(rq->bRequest == USBRQ_GET_STATUS){           /* 0 */  
                    uchar __attribute__((__unused__)) recipient = rq->bmRequestType & USBRQ_RCPT_MASK;  /* assign arith ops to variables to enforce byte size */  
#if USB_CFG_IS_SELF_POWERED   
                    if(recipient == USBRQ_RCPT_DEVICE)  
                        replyData[0] =  USB_CFG_IS_SELF_POWERED;  
#endif   
#if USB_CFG_HAVE_INTRIN_ENDPOINT && USB_CFG_IMPLEMENT_HALT   
                    if(recipient == USBRQ_RCPT_ENDPOINT && rq->wIndex.bytes[0] == 0x81)   /* request status for endpoint 1 */  
                        replyData[0] = usbTxLen1 == USBPID_STALL;  
#endif   
                    replyData[1] = 0;  
                    SET_REPLY_LEN(2);  
                }else if(rq->bRequest == USBRQ_SET_ADDRESS){    /* 5 */  
                    usbNewDeviceAddr = rq->wValue.bytes[0];  
                }else if(rq->bRequest == USBRQ_GET_DESCRIPTOR){ /* 6 */  
                    flags = USB_FLG_MSGPTR_IS_ROM | USB_FLG_USE_DEFAULT_RW;  
                    if(rq->wValue.bytes[1] == USBDESCR_DEVICE){ /* 1 */  
                        GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_DEVICE, usbDescriptorDevice)  
                    }else if(rq->wValue.bytes[1] == USBDESCR_CONFIG){   /* 2 */  
                        GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_CONFIGURATION, usbDescriptorConfiguration)  
                    }else if(rq->wValue.bytes[1] == USBDESCR_STRING){   /* 3 */  
#if USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC   
                        if(USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_RAM)  
                            flags &= ~USB_FLG_MSGPTR_IS_ROM;  
                        replyLen = usbFunctionDescriptor(rq);  
#else   /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */   
                        if(rq->wValue.bytes[0] == 0){   /* descriptor index */  
                            GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_0, usbDescriptorString0)  
                        }else if(rq->wValue.bytes[0] == 1){  
                            GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_VENDOR, usbDescriptorStringVendor)  
                        }else if(rq->wValue.bytes[0] == 2){  
                            GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_PRODUCT, usbDescriptorStringDevice)  
                        }else if(rq->wValue.bytes[0] == 3){  
                            GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER, usbDescriptorStringSerialNumber)  
                        }else if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){  
                            replyLen = usbFunctionDescriptor(rq);  
                        }  
#endif  /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */   
                    }else if(rq->wValue.bytes[1] == USBDESCR_HID){          /* 0x21 */  
                        GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID, usbDescriptorConfiguration + 18)  
                    }else if(rq->wValue.bytes[1] == USBDESCR_HID_REPORT){   /* 0x22 */  
                        GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID_REPORT, usbDescriptorHidReport)  
                    }else if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){  
                        replyLen = usbFunctionDescriptor(rq);  
                    }  
                }else if(rq->bRequest == USBRQ_GET_CONFIGURATION){  /* 8 */  
                    replyData = &usbConfiguration;  /* send current configuration value */  
                    SET_REPLY_LEN(1);  
                }else if(rq->bRequest == USBRQ_SET_CONFIGURATION){  /* 9 */  
                    usbConfiguration = rq->wValue.bytes[0];  
#if USB_CFG_IMPLEMENT_HALT   
                    usbTxLen1 = USBPID_NAK;  
#endif   
                }else if(rq->bRequest == USBRQ_GET_INTERFACE){      /* 10 */  
                    SET_REPLY_LEN(1);  
#if USB_CFG_HAVE_INTRIN_ENDPOINT   
                }else if(rq->bRequest == USBRQ_SET_INTERFACE){      /* 11 */  
                    USB_SET_DATATOKEN1(USBPID_DATA0);   /* reset data toggling for interrupt endpoint */  
#   if USB_CFG_HAVE_INTRIN_ENDPOINT3   
                    USB_SET_DATATOKEN3(USBPID_DATA0);   /* reset data toggling for interrupt endpoint */  
#   endif   
#   if USB_CFG_IMPLEMENT_HALT   
                    usbTxLen1 = USBPID_NAK;  
                }else if(rq->bRequest == USBRQ_CLEAR_FEATURE || rq->bRequest == USBRQ_SET_FEATURE){   /* 1|3 */  
                    if(rq->wValue.bytes[0] == 0 && rq->wIndex.bytes[0] == 0x81){   /* feature 0 == HALT for endpoint == 1 */  
                        usbTxLen1 = rq->bRequest == USBRQ_CLEAR_FEATURE ? USBPID_NAK : USBPID_STALL;  
                        USB_SET_DATATOKEN1(USBPID_DATA0);   /* reset data toggling for interrupt endpoint */  
#       if USB_CFG_HAVE_INTRIN_ENDPOINT3   
                        USB_SET_DATATOKEN3(USBPID_DATA0);   /* reset data toggling for interrupt endpoint */  
#       endif   
                    }  
#   endif   
#endif   
                }else{  
                    /* the following requests can be ignored, send default reply */  
                    /* 1: CLEAR_FEATURE, 3: SET_FEATURE, 7: SET_DESCRIPTOR */  
                    /* 12: SYNCH_FRAME */  
                }  
                #undef SET_REPLY_LEN   
            }else{  /* not a standard request -- must be vendor or class request */  
                replyLen = usbFunctionSetup(data);  
            }  
#if USB_CFG_IMPLEMENT_FN_READ || USB_CFG_IMPLEMENT_FN_WRITE   
            if(replyLen == 0xff){   /* use user-supplied read/write function */  
                if((rq->bmRequestType & USBRQ_DIR_MASK) == USBRQ_DIR_DEVICE_TO_HOST){  
                    replyLen = rq->wLength.bytes[0];    /* IN transfers only */  
                }  
                flags &= ~USB_FLG_USE_DEFAULT_RW;  /* we have no valid msg, use user supplied read/write functions */  
            }else   /* The 'else' prevents that we limit a replyLen of 0xff to the maximum transfer len. */  
#endif   
            if(!rq->wLength.bytes[1] && replyLen > rq->wLength.bytes[0])  /* limit length to max */  
                replyLen = rq->wLength.bytes[0];  
        }  
        /* make sure that data packets which are sent as ACK to an OUT transfer are always zero sized */  
    }else{  /* DATA packet from out request */  
#if USB_CFG_IMPLEMENT_FN_WRITE   
        if(!(usbMsgFlags & USB_FLG_USE_DEFAULT_RW)){  
            uchar rval = usbFunctionWrite(data, len);  
            replyLen = 0xff;  
            if(rval == 0xff){       /* an error occurred */  
                usbMsgLen = 0xff;   /* cancel potentially pending data packet for ACK */  
                usbTxLen = USBPID_STALL;  
            }else if(rval != 0){    /* This was the final package */  
                replyLen = 0;       /* answer with a zero-sized data packet */  
            }  
            flags = 0;    /* start with a DATA1 package, stay with user supplied write() function */  
        }  
#endif   
    }  
    usbMsgFlags = flags;  
    usbMsgLen = replyLen;  
}  
  
/* ------------------------------------------------------------------------- */  
  
static void usbBuildTxBlock(void)  
{  
uchar   wantLen, len, txLen, token;  
  
    wantLen = usbMsgLen;  
    if(wantLen > 8)  
        wantLen = 8;  
    usbMsgLen -= wantLen;  
    token = USBPID_DATA1;  
    if(usbMsgFlags & USB_FLG_TX_PACKET)  
        token = USBPID_DATA0;  
    usbMsgFlags++;  
    len = usbRead(usbTxBuf + 1, wantLen);  
    if(len <= 8){           /* valid data packet */  
        usbCrc16Append(&usbTxBuf[1], len);  
        txLen = len + 4;    /* length including sync byte */  
        if(len < 8)         /* a partial package identifies end of message */  
            usbMsgLen = 0xff;  
    }else{  
        txLen = USBPID_STALL;   /* stall the endpoint */  
        usbMsgLen = 0xff;  
    }  
    usbTxBuf[0] = token;  
    usbTxLen = txLen;  
    DBG2(0x20, usbTxBuf, txLen-1);  
}  
  
static inline uchar isNotSE0(void)  
{  
uchar   rval;  
/* We want to do 
 *     return (USBIN & USBMASK); 
 * here, but the compiler does int-expansion acrobatics. 
 * We can avoid this by assigning to a char-sized variable. 
 */  
    rval = USBIN & USBMASK;  
    return rval;  
}  
  
/* ------------------------------------------------------------------------- */  
  
USB_PUBLIC void usbPoll(void)  
{  
schar   len;  
uchar   i;  
  
    if((len = usbRxLen) > 0){  
/* We could check CRC16 here -- but ACK has already been sent anyway. If you 
 * 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 - 3);  
#if USB_CFG_HAVE_FLOWCONTROL   
        if(usbRxLen > 0)    /* only mark as available if not inactivated */  
            usbRxLen = 0;  
#else   
        usbRxLen = 0;       /* mark rx buffer as available */  
#endif   
    }  
    if(usbTxLen & 0x10){ /* transmit system idle */  
        if(usbMsgLen != 0xff){  /* transmit data pending? */  
            usbBuildTxBlock();  
        }  
    }  
    for(i = 10; i > 0; i--){  
        if(isNotSE0())  
            break;  
    }  
    if(i == 0){ /* RESET condition, called multiple times during reset */  
        usbNewDeviceAddr = 0;  
        usbDeviceAddr = 0;  
#if USB_CFG_IMPLEMENT_HALT   
        usbTxLen1 = USBPID_NAK;  
#if USB_CFG_HAVE_INTRIN_ENDPOINT3   
        usbTxLen3 = USBPID_NAK;  
#endif   
#endif   
        DBG1(0xff, 0, 0);  
    }  
}  
  
/* ------------------------------------------------------------------------- */  
  
USB_PUBLIC void usbInit(void)  
{  
#if USB_INTR_CFG_SET != 0   
    USB_INTR_CFG |= USB_INTR_CFG_SET;  
#endif   
#if USB_INTR_CFG_CLR != 0   
    USB_INTR_CFG &= ~(USB_INTR_CFG_CLR);  
#endif   
    USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT);  
#if USB_CFG_HAVE_INTRIN_ENDPOINT   
    USB_SET_DATATOKEN1(USBPID_DATA0);   /* reset data toggling for interrupt endpoint */  
#   if USB_CFG_HAVE_INTRIN_ENDPOINT3   
    USB_SET_DATATOKEN3(USBPID_DATA0);   /* reset data toggling for interrupt endpoint */  
#   endif   
#endif   
}  
  
/* ------------------------------------------------------------------------- */  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -