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

📄 usbdrv.c

📁 采用atmel公司的mega8芯片设计的USB cdc类
💻 C
📖 第 1 页 / 共 2 页
字号:
        return len;
#if USB_CFG_IMPLEMENT_FN_READ
    }else{
        if(len != 0)    /* don't bother app with 0 sized reads */
            return usbFunctionRead(data, len);
        return 0;
    }
#endif
}

/* 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.
 */
#if DEBUG_LEVEL > 1
    DBG2(0x10 + ((usbRxToken >> 6) & 3), data, len);
#else
    DBG1(0x10 + ((usbRxToken >> 6) & 3), data, 2);
#endif
#if USB_CFG_IMPLEMENT_FN_WRITEOUT
    if(usbRxToken & 0x80){
        usbFunctionWriteOut(data, len);
        return;
    }
    if(usbRxToken == (uchar)(USBPID_SETUP & 0x7f)){ /* MSb contains endpoint (== 0) */
#else
    if(usbRxToken == (uchar)USBPID_SETUP){
#endif
        if(len == 8){   /* Setup size must be always 8 bytes. Ignore otherwise. */
            uchar type = rq->bmRequestType & USBRQ_TYPE_MASK;
            if(type == USBRQ_TYPE_STANDARD){
                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(usbHalted1 && recipient == USBRQ_RCPT_ENDPOINT && rq->wIndex.bytes[0] == 0x81)   /* request status for endpoint 1 */
                        replyData[0] = 1;
#endif
                    replyData[1] = 0;
                    replyLen = 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] == 1){   /* descriptor type requested */
                        replyLen = sizeof(usbDescrDevice);
                        replyData = (uchar *)usbDescrDevice;
                    }else if(rq->wValue.bytes[1] == 2){
                        replyLen = USB_CFG_EXTERNAL_CONFIG_DESCRIPTOR_LENGH;
                        replyData = (uchar *)usbDescrConfig;
                    }else if(rq->wValue.bytes[1] == 3){ /* string descriptor */
                        if(rq->wValue.bytes[0] == 0){   /* descriptor index */
                            replyLen = sizeof(usbDescrString0);
                            replyData = (uchar *)usbDescrString0;
#if USB_CFG_VENDOR_NAME_LEN
                        }else if(rq->wValue.bytes[0] == 1){
                            replyLen = sizeof(usbDescrString1);
                            replyData = (uchar *)usbDescrString1;
#endif
#if USB_CFG_DEVICE_NAME_LEN
                        }else if(rq->wValue.bytes[0] == 2){
                            replyLen = sizeof(usbDescrString2);
                            replyData = (uchar *)usbDescrString2;
#endif
#if USB_CFG_SERIAL_NUMBER_LENGTH
                        }else if(rq->wValue.bytes[0] == 3){
                            replyLen = 2 * USB_CFG_SERIAL_NUMBER_LENGTH + 2;
                            replyData = (uchar *)usbCfgSerialNumberStringDescriptor;
#endif
                        }
                    }
#if USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH
                    else if(rq->wValue.bytes[1] == USBDESCR_HID){           /* 0x21 */
                        replyLen = 9;
                        replyData = (uchar *)usbDescrConfig + 18;
                    }else if(rq->wValue.bytes[1] == USBDESCR_HID_REPORT){   /* 0x22 */
                        replyLen = USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH;
                        replyData = (uchar *)usbHidReportDescriptor;
                    }
#endif
                }else if(rq->bRequest == USBRQ_GET_CONFIGURATION){  /* 8 */
                    replyLen = 1;
                    replyData = &usbConfiguration;  /* send current configuration value */
                }else if(rq->bRequest == USBRQ_SET_CONFIGURATION){  /* 9 */
                    usbConfiguration = rq->wValue.bytes[0];
#if USB_CFG_IMPLEMENT_HALT
                    usbHalted1 = 0;
#endif
                }else if(rq->bRequest == USBRQ_GET_INTERFACE){      /* 10 */
                    replyLen = 1;
#if USB_CFG_HAVE_INTRIN_ENDPOINT
#if USB_CFG_IMPLEMENT_HALT
                }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 */
                        usbHalted1 = rq->bRequest - 1;
                        if(usbHalted1){
                            usbTxBuf1[0] = USBPID_STALL;
                            usbTxLen1 = 2;      /* length including sync byte */
                        }
                        usbTxPacketCnt1 = 0;    /* reset data toggling for interrupt endpoint */
                    }
#endif
                }else if(rq->bRequest == USBRQ_SET_INTERFACE){      /* 11 */
                    usbTxPacketCnt1 = 0;        /* reset data toggling for interrupt endpoint */
#if USB_CFG_IMPLEMENT_HALT
                    usbHalted1 = 0;
#endif
#endif
                }else{
                    /* the following requests can be ignored, send default reply */
                    /* 1: CLEAR_FEATURE, 3: SET_FEATURE, 7: SET_DESCRIPTOR */
                    /* 12: SYNCH_FRAME */
                }
                usbMsgPtr = replyData;
                if(!rq->wLength.bytes[1] && replyLen > rq->wLength.bytes[0])  /* max length is in */
                    replyLen = rq->wLength.bytes[0];
            }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 = 0;  /* we have no valid msg, use user supplied read/write functions */
                }
#endif
            }
        }
        /* 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 ACK [has been done by ASM module when OUT token arrived] */
                usbTxBuf[0] = USBPID_STALL;
                usbTxLen = 2;       /* length including sync byte */
            }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 */
        }
#else
        replyLen = 0;      /* send zero-sized block as ACK */
#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{
        token = USBPID_STALL;
        txLen = 2;          /* length including sync byte */
        usbMsgLen = 0xff;
    }
    usbTxBuf[0] = token;
    usbTxLen = txLen;
#if DEBUG_LEVEL > 1
    DBG2(0x20, usbTxBuf, txLen-1);
#else
    DBG1(0x20, usbTxBuf + 1, 2);
#endif
}

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;
}

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

void    usbPoll(void)
{
uchar   len;

    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((uchar *)(unsigned)(usbAppBuf + 1), usbRxLen - 3);
 */
        len -= 3;       /* remove PID and CRC */
        if(len < 128){  /* no overflow */
            converter_t appBuf;
            appBuf.ptr = (uchar *)usbRxBuf;
            appBuf.bytes[0] = usbAppBuf;
            appBuf.bytes[0]++;
            usbProcessRx(appBuf.ptr, 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(usbMsgLen != 0xff){  /* transmit data pending? */
        if(usbTxLen < 0)    /* transmit system idle */
            usbBuildTxBlock();
    }
    if(isNotSE0()){ /* SE0 state */
        usbIsReset = 0;
    }else{
        /* check whether SE0 lasts for more than 2.5us (3.75 bit times) */
        if(!usbIsReset){
            uchar i;
            for(i=100;i;i--){
                if(isNotSE0())
                    goto notUsbReset;
            }
            usbIsReset = 1;
            usbNewDeviceAddr = 0;
            usbDeviceAddr = 0;
#if USB_CFG_IMPLEMENT_HALT
            usbHalted1 = 0;
#endif
            DBG1(0xff, 0, 0);
notUsbReset:;
        }
    }
}

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

void    usbInit(void)
{
    usbInputBuf = (uchar)usbRxBuf[0];
    usbAppBuf = (uchar)usbRxBuf[1];
#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);
}

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

⌨️ 快捷键说明

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