usbdrv.c

来自「Source code for driving RFM01 fm radio r」· C语言 代码 · 共 508 行 · 第 1/2 页

C
508
字号
/* 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 + (USBRDV_RxToken == (uchar)USBPID_SETUP), data, len);#else//    DBG1(0x10 + (USBRDV_RxToken == (uchar)USBPID_SETUP), data, 2);#endif    if(USBRDV_RxToken == (uchar)USBPID_SETUP){        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 = USBRDV_TxBuf + 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 USBRDV_CFG_IS_SELF_POWERED                    if(recipient == USBRQ_RCPT_DEVICE)                        replyData[0] =  USBRDV_CFG_IS_SELF_POWERED;#endif#if USBRDV_CFG_HAVE_INTRIN_ENDPOINT && USBRDV_CFG_IMPLEMENT_HALT                    if(USBRDV_Halted1 && 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 */                    USBRDV_NewDeviceId = rq->wValue.bytes[0];                }else if(rq->bRequest == USBRQ_GET_DESCRIPTOR){ /* 6 */                    flags = USBRDV_FLG_MSGPTR_IS_ROM | USBRDV_FLG_USE_DEFAULT_RW;                    if(rq->wValue.bytes[1] == 1){   /* descriptor type requested */                        replyLen = sizeof(USBRDV_DescrDevice);                        replyData = (uchar *)USBRDV_DescrDevice;                    }else if(rq->wValue.bytes[1] == 2){                        replyLen = sizeof(USBRDV_DescrConfig);                        replyData = (uchar *)USBRDV_DescrConfig;                    }else if(rq->wValue.bytes[1] == 3){ /* string descriptor */                        if(rq->wValue.bytes[0] == 0){   /* descriptor index */                            replyLen = sizeof(USBRDV_DescrString0);                            replyData = (uchar *)USBRDV_DescrString0;#if USBRDV_CFG_VENDOR_NAME_LEN                        }else if(rq->wValue.bytes[0] == 1){                            replyLen = sizeof(USBRDV_DescrString1);                            replyData = (uchar *)USBRDV_DescrString1;#endif#if USBRDV_CFG_DEVICE_NAME_LEN                        }else if(rq->wValue.bytes[0] == 2){                            replyLen = sizeof(USBRDV_DescrString2);                            replyData = (uchar *)USBRDV_DescrString2;#endif#if USBRDV_CFG_SERIAL_NUMBER_LENGTH                        }else if(rq->wValue.bytes[0] == 3){                            replyLen = 2 * USBRDV_CFG_SERIAL_NUMBER_LENGTH + 2;                            replyData = (uchar *)USBRDV_CfgSerialNumberStringDescriptor;#endif                        }                    }#if USBRDV_CFG_HID_REPORT_DESCRIPTOR_LENGTH                    else if(rq->wValue.bytes[1] == USBDESCR_HID){           /* 0x21 */                        replyLen = 9;                        replyData = (uchar *)USBRDV_DescrConfig + 18;                    }else if(rq->wValue.bytes[1] == USBDESCR_HID_REPORT){   /* 0x22 */                        replyLen = USBRDV_CFG_HID_REPORT_DESCRIPTOR_LENGTH;                        replyData = (uchar *)USBRDV_HidReportDescriptor;                    }#endif                }else if(rq->bRequest == USBRQ_GET_CONFIGURATION){  /* 8 */                    replyLen = 1;                    replyData = &USBRDV_Configuration;  /* send current configuration value */                }else if(rq->bRequest == USBRQ_SET_CONFIGURATION){  /* 9 */                    USBRDV_Configuration = rq->wValue.bytes[0];#if USBRDV_CFG_IMPLEMENT_HALT                    USBRDV_Halted1 = 0;#endif                }else if(rq->bRequest == USBRQ_GET_INTERFACE){      /* 10 */                    replyLen = 1;#if USBRDV_CFG_HAVE_INTRIN_ENDPOINT#if USBRDV_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 */                        USBRDV_Halted1 = rq->bRequest - 1;                        if(USBRDV_Halted1){                            USBRDV_TxBuf1[0] = USBPID_STALL;                            USBRDV_TxLen1 = 2;      /* length including sync byte */                        }                        USBRDV_TxPacketCnt1 = 0;    /* reset data toggling for interrupt endpoint */                    }#endif                }else if(rq->bRequest == USBRQ_SET_INTERFACE){      /* 11 */                    USBRDV_TxPacketCnt1 = 0;        /* reset data toggling for interrupt endpoint */#if USBRDV_CFG_IMPLEMENT_HALT                    USBRDV_Halted1 = 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 */                }                USBRDV_MsgPtr = 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 = USBRDV_FunctionSetup(data);#if USBRDV_CFG_IMPLEMENT_FN_READ || USBRDV_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 USBRDV_CFG_IMPLEMENT_FN_WRITE        if(!(USBRDV_MsgFlags & USBRDV_FLG_USE_DEFAULT_RW)){            uchar rval = USBRDV_FunctionWrite(data, len);            replyLen = -1;            if(rval == 0xff){       /* an error occurred */                /* USBRDV_MsgLen = 0xff; cancel potentially pending ACK [has been done by ASM module when OUT token arrived] */                USBRDV_TxBuf[0] = USBPID_STALL;                USBRDV_TxLen = 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    }    USBRDV_MsgFlags = flags;    USBRDV_MsgLen = replyLen;}/* ------------------------------------------------------------------------- */static void USBRDV_BuildTxBlock(void){uchar       wantLen, len, txLen, token;    wantLen = USBRDV_MsgLen;    if(wantLen > 8)        wantLen = 8;    USBRDV_MsgLen -= wantLen;    token = USBPID_DATA1;    if(USBRDV_MsgFlags & USBRDV_FLG_TX_PACKET)        token = USBPID_DATA0;    USBRDV_MsgFlags++;    len = USBRDV_Read(USBRDV_TxBuf + 1, wantLen);    if(len <= 8){           /* valid data packet */        USBRDV_Crc16Append(USBRDV_TxBuf + 1, len);        txLen = len + 4;    /* length including sync byte */        if(len < 8)         /* a partial package identifies end of message */            USBRDV_MsgLen = 0xff;    }else{        token = USBPID_STALL;        txLen = 2;          /* length including sync byte */        USBRDV_MsgLen = 0xff;    }    USBRDV_TxBuf[0] = token;    USBRDV_TxLen = txLen;#if DEBUG_LEVEL > 1    DBG2(0x20, USBRDV_TxBuf, txLen-1);#else//    DBG1(0x20, USBRDV_TxBuf + 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    USBRDV_Poll(void){uchar   len;    if((len = USBRDV_RxLen) > 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 = USBRDV_Crc16((uchar *)(unsigned)(USBRDV_AppBuf + 1), USBRDV_RxLen - 3); */        len -= 3;       /* remove PID and CRC */        if(len < 128){  /* no overflow */            converter_t appBuf;            appBuf.ptr = (uchar *)USBRDV_RxBuf;            appBuf.bytes[0] = USBRDV_AppBuf;            appBuf.bytes[0]++;            USBRDV_ProcessRx(appBuf.ptr, len);        }        USBRDV_RxLen = 0;   /* mark rx buffer as available */    }    if(USBRDV_TxLen < 0){   /* TX system is idle */        if(USBRDV_MsgLen != 0xff){            USBRDV_BuildTxBlock();        }else if(USBRDV_NewDeviceId){            USBRDV_DeviceId = USBRDV_NewDeviceId;//            DBG1(1, &USBRDV_NewDeviceId, 1);            USBRDV_NewDeviceId = 0;        }    }    if(isNotSE0()){ /* SE0 state */        USBRDV_IsReset = 0;    }else{        /* check whether SE0 lasts for more than 2.5us (3.75 bit times) */        if(!USBRDV_IsReset){            uchar i;            for(i=100;i;i--){                if(isNotSE0())                    goto notUsbReset;            }            USBRDV_IsReset = 1;            USBRDV_DeviceId = 0;            USBRDV_NewDeviceId = 0;#if USBRDV_CFG_IMPLEMENT_HALT            USBRDV_Halted1 = 0;#endif//            DBG1(0xff, 0, 0);notUsbReset:;        }    }}/* ------------------------------------------------------------------------- */void    USBRDV_init(void){    USBRDV_InputBuf = (uchar)USBRDV_RxBuf[0];    USBRDV_AppBuf = (uchar)USBRDV_RxBuf[1];#if USBRDV_INTR_CFG_SET != 0    USBRDV_INTR_CFG |= USBRDV_INTR_CFG_SET;#endif#if USBRDV_INTR_CFG_CLR != 0    USBRDV_INTR_CFG &= ~(USBRDV_INTR_CFG_CLR);#endif    USBRDV_INTR_ENABLE |= (1 << USBRDV_INTR_ENABLE_BIT);}/* ------------------------------------------------------------------------- */

⌨️ 快捷键说明

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