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

📄 usbdrv.c

📁 USBasp
💻 C
📖 第 1 页 / 共 2 页
字号:
uchar       flags = USB_FLG_MSGPTR_IS_ROM;    SWITCH_START(rq->wValue.bytes[1])    SWITCH_CASE(USBDESCR_DEVICE)    /* 1 */        GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_DEVICE, usbDescriptorDevice)    SWITCH_CASE(USBDESCR_CONFIG)    /* 2 */        GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_CONFIGURATION, usbDescriptorConfiguration)    SWITCH_CASE(USBDESCR_STRING)    /* 3 */#if USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC        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)            GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_0, usbDescriptorString0)        SWITCH_CASE(1)            GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_VENDOR, usbDescriptorStringVendor)        SWITCH_CASE(2)            GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_PRODUCT, usbDescriptorStringDevice)        SWITCH_CASE(3)            GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER, usbDescriptorStringSerialNumber)        SWITCH_DEFAULT            if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){                len = usbFunctionDescriptor(rq);            }        SWITCH_END#endif  /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */#if USB_CFG_DESCR_PROPS_HID_REPORT  /* only support HID descriptors if enabled */    SWITCH_CASE(USBDESCR_HID)       /* 0x21 */        GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID, usbDescriptorConfiguration + 18)    SWITCH_CASE(USBDESCR_HID_REPORT)/* 0x22 */        GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID_REPORT, usbDescriptorHidReport)#endif    SWITCH_DEFAULT        if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){            len = usbFunctionDescriptor(rq);        }    SWITCH_END    usbMsgFlags = flags;    return len;}/* ------------------------------------------------------------------------- *//* 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 */uchar   value = rq->wValue.bytes[0];#if USB_CFG_IMPLEMENT_HALTuchar   index = rq->wIndex.bytes[0];#endif    dataPtr[0] = 0; /* default reply common to USBRQ_GET_STATUS and USBRQ_GET_INTERFACE */    SWITCH_START(rq->bRequest)    SWITCH_CASE(USBRQ_GET_STATUS)           /* 0 */        uchar recipient = rq->bmRequestType & USBRQ_RCPT_MASK;  /* assign arith ops to variables to enforce byte size */        if(USB_CFG_IS_SELF_POWERED && recipient == USBRQ_RCPT_DEVICE)            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;        len = 2;#if USB_CFG_IMPLEMENT_HALT    SWITCH_CASE2(USBRQ_CLEAR_FEATURE, USBRQ_SET_FEATURE)    /* 1, 3 */        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 */        usbNewDeviceAddr = value;        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 */        len = 1;    SWITCH_CASE(USBRQ_SET_CONFIGURATION)    /* 9 */        usbConfiguration = value;        usbResetStall();    SWITCH_CASE(USBRQ_GET_INTERFACE)        /* 10 */        len = 1;#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE    SWITCH_CASE(USBRQ_SET_INTERFACE)        /* 11 */        usbResetDataToggling();        usbResetStall();#endif    SWITCH_DEFAULT                          /* 7=SET_DESCRIPTOR, 12=SYNC_FRAME */        /* Should we add an optional hook here? */    SWITCH_END    usbMsgPtr = dataPtr;skipMsgPtrAssignment:    return len;}/* ------------------------------------------------------------------------- *//* usbProcessRx() is called for every message received by the interrupt * routine. It distinguishes between SETUP and DATA packets and processes * them accordingly. */static inline void usbProcessRx(uchar *data, uchar len){usbRequest_t    *rq = (void *)data;/* usbRxToken can be: * 0x2d 00101101 (USBPID_SETUP for setup data) * 0xe1 11100001 (USBPID_OUT: data phase of setup transfer) * 0...0x0f for OUT on endpoint X */    DBG2(0x10 + (usbRxToken & 0xf), data, len); /* 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 */        usbFunctionWriteOut(data, len);        return;    }#endif    if(usbRxToken == (uchar)USBPID_SETUP){        if(len != 8)    /* Setup size must be always 8 bytes. Ignore otherwise. */            return;        usbMsgLen_t replyLen;        usbTxBuf[0] = USBPID_DATA0;         /* initialize data toggling */        usbTxLen = USBPID_NAK;              /* abort pending transmit */        usbMsgFlags = 0;        uchar type = rq->bmRequestType & USBRQ_TYPE_MASK;        if(type != USBRQ_TYPE_STANDARD){    /* standard requests are handled by driver */            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 */            /* do some conditioning on replyLen, but on IN transfers only */            if((rq->bmRequestType & USBRQ_DIR_MASK) != USBRQ_DIR_HOST_TO_DEVICE){                if(sizeof(replyLen) < sizeof(rq->wLength.word)){ /* help compiler with optimizing */                    replyLen = rq->wLength.bytes[0];                }else{                    replyLen = rq->wLength.word;                }            }            usbMsgFlags = USB_FLG_USE_USER_RW;        }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 */                replyLen = rq->wLength.bytes[0];        }else{            if(replyLen > rq->wLength.word)     /* limit length to max */                replyLen = rq->wLength.word;        }        usbMsgLen = replyLen;    }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){            uchar rval = usbFunctionWrite(data, len);            if(rval == 0xff){   /* an error occurred */                usbTxLen = USBPID_STALL;            }else if(rval != 0){    /* This was the final package */                usbMsgLen = 0;  /* answer with a zero-sized data packet */            }        }#endif    }}/* ------------------------------------------------------------------------- *//* 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 */#if USB_CFG_IMPLEMENT_FN_READ        if(usbMsgFlags & USB_FLG_USE_USER_RW){            len = usbFunctionRead(data, len);        }else#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 */                    *data++ = c;                    r++;                }while(--i);            }else{  /* RAM data */                do{                    *data++ = *r++;                }while(--i);            }            usbMsgPtr = r;        }    }    return len;}/* ------------------------------------------------------------------------- *//* usbBuildTxBlock() is called when we have data to transmit and the * interrupt routine's transmit buffer is empty. */static inline void usbBuildTxBlock(void){usbMsgLen_t wantLen;uchar       len;    wantLen = usbMsgLen;    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 */        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 */        usbMsgLen = USB_NO_MSG;    }    usbTxLen = len;    DBG2(0x20, usbTxBuf, len-1);}/* ------------------------------------------------------------------------- */static inline void usbHandleResetHook(uchar notResetState){#ifdef USB_RESET_HOOKstatic uchar    wasReset;uchar           isReset = !notResetState;    if(wasReset != isReset){        USB_RESET_HOOK(isReset);        wasReset = isReset;    }#endif}/* ------------------------------------------------------------------------- */USB_PUBLIC void usbPoll(void){schar   len;uchar   i;    len = usbRxLen - 3;    if(len >= 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);#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 != USB_NO_MSG){    /* transmit data pending? */            usbBuildTxBlock();        }    }    for(i = 20; i > 0; i--){        uchar usbLineStatus = USBIN & USBMASK;        if(usbLineStatus != 0)  /* SE0 has ended */            goto isNotReset;    }    /* RESET condition, called multiple times during reset */    usbNewDeviceAddr = 0;    usbDeviceAddr = 0;    usbResetStall();    DBG1(0xff, 0, 0);isNotReset:    usbHandleResetHook(i);}/* ------------------------------------------------------------------------- */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);    usbResetDataToggling();#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE    usbTxLen1 = USBPID_NAK;#if USB_CFG_HAVE_INTRIN_ENDPOINT3    usbTxLen3 = USBPID_NAK;#endif#endif}/* ------------------------------------------------------------------------- */

⌨️ 快捷键说明

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