zoukankan      html  css  js  c++  java
  • C8051F340 USB Fn hacking

    /************************************************************************************
     *                           C8051F340 USB Fn hacking
     * 说明:
     *     简单跟踪一下这个C8051F340 USB的使用。
     *
     *                                               2017-4-1 深圳 南山平山村 曾剑锋
     ***********************************************************************************/
    
    void main(void)
    {
        System_Init (); --------------------+
        USB0_Init ();                       |
        EA = 1;                             |
                                            |
        while (1) {                         |
            Key_Scan();                     |      ------------------------------------+
            Key_Handle();                   |      ------------------------------------*-+
        }                                   |                                          | |
    }                                       |                                          | |
                                            |                                          | |
    void System_Init (void)    <------------+                                          | |
    {                                                                                  | |
        PCA0MD &= ~0x40;                    // Disable Watchdog timer                  | |
        Sysclk_Init ();      -------+       // initialize system clock                 | |
        Port_Init ();               |       // configure cross bar      -----------+   | |
        Timer_Init ();              |       // configure timer          -----------*-+ | |
    }                               |                                              | | | |
                                    |                                              | | | |
    void Sysclk_Init (void)   <-----+                                              | | | |
    {                                                                              | | | |
    #ifdef _USB_LOW_SPEED_                                                         | | | |
                                                                                   | | | |
        OSCICN |= 0x03;                     // Configure internal oscillator for   | | | |
        // its maximum frequency and enable                                        | | | |
        // missing clock detector                                                  | | | |
                                                                                   | | | |
        CLKSEL  = SYS_EXT_OSC;              // Select System clock                 | | | |
        CLKSEL |= USB_INT_OSC_DIV_2;        // Select USB clock                    | | | |
    #else                                                                          | | | |
        OSCICN |= 0x03;                     // Configure internal oscillator for   | | | |
        // its maximum frequency and enable                                        | | | |
        // missing clock detector                                                  | | | |
                                                                                   | | | |
        CLKMUL  = 0x00;                     // Select internal oscillator as       | | | |
        // input to clock multiplier                                               | | | |
                                                                                   | | | |
        CLKMUL |= 0x80;                     // Enable clock multiplier             | | | |
        CLKMUL |= 0xC0;                     // Initialize the clock multiplier     | | | |
        Delay();                            // Delay for clock multiplier to begin | | | |
                                                                                   | | | |
        while(!(CLKMUL & 0x20));            // Wait for multiplier to lock         | | | |
        CLKSEL  = SYS_INT_OSC;              // Select system clock                 | | | |
        CLKSEL |= USB_4X_CLOCK;             // Select USB clock                    | | | |
    #endif  /* _USB_LOW_SPEED_ */                                                  | | | |
    }                                                                              | | | |
                                                                                   | | | |
    void Port_Init(void)                <------------------------------------------+ | | |
    {                                                                                | | |
        P0MDOUT        = 0xFF;                                                       | | |
        P0SKIP        = 0xFF;                                                        | | |
        P2MDIN   = 0xFF;                 // Port 2 pin 5 set as analog input         | | |
        P2SKIP   = 0xFF;                    // Port 2 pin 5 skipped by crossbar      | | |
                                                                                     | | |
        XBR1        = 0x40;                    // Enable Crossbar                    | | |
                                                                                     | | |
        DebugLEDOFF;                        // ¹Ø±Õµ÷Êﵮ                            | | |
    }                                                                                | | |
                                                                                     | | |
    void Timer_Init (void)                                                           | | |
    {                                                                                | | |
        TMR2CN  = 0x00;                     // Stop Timer2; Clear TF2;               | | |
                                                                                     | | |
        CKCON  &= ~0xF0;                    // Timer2 clocked based on T2XCLK;       | | |
        TMR2L   = 0x7F;                      // Timer/Counter 2 Low                  | | |
        TMR2H   = 0xFF;                      // Timer/Counter 2 High                 | | |
        TMR2RLL = 0xEF;                         // Timer/Counter 2 Reload Low        | | |
        TMR2RLH    = 0xD8;                         // Timer/Counter 2 Reload High    | | |
                                                                                     | | |
        ET2     = 1;                        // Enable Timer2 interrupts              | | |
        TR2     = 1;                        // Start Timer2                          | | |
    }                                                                                | | |
                                                                                     | | |
    void USB0_Init (void)          <-------------------------------------------------+ | |
    {                                                                                  | |
                                                                                       | |
        //    #define POLL_WRITE_BYTE(addr, data) while(USB0ADR & 0x80);              | |
        //                                    WRITE_BYTE(addr, data);                  | |
        POLL_WRITE_BYTE (POWER, 0x08);      // Force Asynchronous USB Reset       ---+ | |
        POLL_WRITE_BYTE (IN1IE, 0x07);      // Enable Endpoint 0-1 in interrupts     | | |
        POLL_WRITE_BYTE (OUT1IE,0x07);      // Enable Endpoint 0-1 out interrupts    | | |
        POLL_WRITE_BYTE (CMIE, 0x07);       // Enable Reset, Resume, and Suspend     | | |
        // interrupts                                                                | | |
        USB0XCN = 0xE0;                     // Enable transceiver; select full speed | | |
        POLL_WRITE_BYTE (CLKREC,0x89);      // Enable clock recovery, single-step    | | |
        // mode disabled                                                             | | |
                                                                                     | | |
        EIE1 |= 0x02;                       // Enable USB0 Interrupts                | | |
                                                                                     | | |
        // Enable USB0 by clearing the USB                                           | | |
        POLL_WRITE_BYTE (POWER, 0x01);      // Inhibit Bit and enable suspend        | | |
        // detection                                                                 | | |
                                                                                     | | |
    }                                                                                | | |
                                                                                     | | |
    #define POLL_WRITE_BYTE(addr, data) while(USB0ADR & 0x80);         <------------+ | |
        WRITE_BYTE(addr, data);                                         -----+         | |
                                                                             |         | |
    #define WRITE_BYTE(addr, data) USB0ADR = (addr); USB0DAT = data     <----+         | |
                                                                             |         | |
    sfr  USB0DAT      =  0x97;             // USB0 Data Register        <----+         | |
                                                                                       | |
    void Key_Scan(void) {             <------------------------------------------------+ |
        static unsigned char AllKeyBk;                                                   |
        unsigned char AllKey = 0;                                                        |
        unsigned char i = 0;                                                             |
                                                                                         |
        if(b_ScanKey) {    // 定时器中每过10ms会对这个变量置1一次                        |
            b_ScanKey = 0;                                                               |
            AllKey = P2;                                                                 |
            AllKey >>= 2;                                                                |
            if(AllKey != 0x3F) {    // 有键按下                                          |
                if(AllKeyBk != AllKey) {                                                 |
                    LongKeyCnt = 0;    // 有新的按键按下,重新去抖                       |
                }                                                                        |
                AllKeyBk = AllKey;                                                       |
                LongKeyCnt++;                                                            |
                if(LongKeyCnt > 1) {    // 20ms 去抖                                     |
                    key_status[KEYALL] = KEY_DOWN;                                       |
                    for( i = 0; i < 6; i++) {                                            |
                        // 判断每一个按键的状态                                          |
                        if( (AllKey & 0x01) == 0 ) {                                     |
                            key_status[i] = KEY_DOWN;                                    |
                        } else {                                                         |
                            key_status[i] = KEY_UP;                                      |
                        }                                                                |
                        AllKey >>= 1;                                                    |
                    }                                                                    |
                }                                                                        |
            } else {                                                                     |
                key_status[KEYALL] = KEY_UP;                                             |
                LongKeyCnt = 0;                 // 当按键抬起来之后这里会置零            |
                for( i = 0; i < 6; i++) {                                                |
                    key_status[i] = KEY_UP;                                              |
                }                                                                        |
            }                                                                            |
        }                                                                                |
    }                                                                                    |
                                                                                         |
    void Key_Handle(void)          <-----------------------------------------------------+
    {
        static unsigned char key_status_bk[6] = {KEY_UP};
        unsigned char i;
        unsigned char cnt_i;
    
        cnt_i = 2;
        if(key_status[KEYF1] == KEY_DOWN) {
            if(key_status[KEYF1] != key_status_bk[KEYF1]) {
                IN_PACKET[cnt_i] = KB_F1;
                DebugLEDON;
                cnt_i++;
            }
        } else if(key_status[KEYF1] == KEY_UP) {
            if(key_status[KEYF1] != key_status_bk[KEYF1]) {    // 按键状态发生改变,只发送一次数据
                DebugLEDOFF;
            }
        }
        if(key_status[KEYF2] == KEY_DOWN) {
            if(key_status[KEYF2] != key_status_bk[KEYF2]) {
                IN_PACKET[cnt_i] = KB_F2;
                DebugLEDON;
                cnt_i++;
            }
        } else if(key_status[KEYF2] == KEY_UP) {
            if(key_status[KEYF2] != key_status_bk[KEYF2]) {    // 按键状态发生改变,只发送一次数据
                DebugLEDOFF;
            }
        }
        if(key_status[KEYF3] == KEY_DOWN) {
            if(key_status[KEYF3] != key_status_bk[KEYF3]) {
                IN_PACKET[cnt_i] = KB_F3;
                DebugLEDON;
                cnt_i++;
            }
        } else if(key_status[KEYF3] == KEY_UP) {
            if(key_status[KEYF3] != key_status_bk[KEYF3]) {    // 按键状态发生改变,只发送一次数据
                DebugLEDOFF;
            }
        }
        if(key_status[KEYF4] == KEY_DOWN) {
            if(key_status[KEYF4] != key_status_bk[KEYF4]) {
                IN_PACKET[cnt_i] = KB_F4;
                DebugLEDON;
                cnt_i++;
            }
        } else if(key_status[KEYF4] == KEY_UP) {
            if(key_status[KEYF4] != key_status_bk[KEYF4]) {    // 按键状态发生改变,只发送一次数据
                DebugLEDOFF;
            }
        }
        if(key_status[KEYF5] == KEY_DOWN) {
            if(key_status[KEYF5] != key_status_bk[KEYF5]) {
                IN_PACKET[cnt_i] = KB_F5;
                DebugLEDON;
                cnt_i++;
            }
        } else if(key_status[KEYF5] == KEY_UP) {
            if(key_status[KEYF5] != key_status_bk[KEYF5]) {    // 按键状态发生改变,只发送一次数据
                DebugLEDOFF;
            }
        }
        if(key_status[KEYF6] == KEY_DOWN) {
            if(key_status[KEYF6] != key_status_bk[KEYF6]) {
                IN_PACKET[cnt_i] = KB_F6;
                DebugLEDON;
                cnt_i++;
            }
        } else if(key_status[KEYF6] == KEY_UP) {
            if(key_status[KEYF6] != key_status_bk[KEYF6]) {    // 按键状态发生改变,只发送一次数据
                DebugLEDOFF;
            }
        }
        if(key_status[KEYALL] == KEY_DOWN){
            if(key_status[KEYALL] != key_status_bk[KEYALL]) {
                SendPacket (0);
            }
        } else if(key_status[KEYALL] == KEY_UP){
            for(i = 2; i < 6; i++) {
                IN_PACKET[i] = 0;                              -------+
            }                                                         |
            if(key_status[KEYALL] != key_status_bk[KEYALL]) {  -------*-+
                SendPacket (0);                                       | |
            }                                                         | |
        }                                                             | |
                                                                      | |
        for(i = 0; i < 7; i++) {                                      | |
            key_status_bk[i] = key_status[i];                         | |
        }                                                             | |
    }                                                                 | |
                                                                      | |
    unsigned char IN_PACKET[8] ={0,0,0,0,0,0,0,0};            <-------+ |
                                                                        |
    unsigned char key_status[7] = {KEY_UP};                   <---------+
    
    void Timer2_ISR (void) interrupt 5        // 10ms
    {
        static unsigned Timer2_Cnt = 0;
    
        Timer2_Cnt++;
        b_ScanKey = 1;    // for key count
    
        if( (Timer2_Cnt%50) == 0 )    {
        }
    
        if( Timer2_Cnt == 50000)
            Timer2_Cnt = 0;
    
        TF2H = 0;                           // Clear Timer2 interrupt flag
    }
    
    //-----------------------------------------------------------------------------
    // Usb_ISR
    //-----------------------------------------------------------------------------
    //
    // Called after any USB type interrupt, this handler determines which type
    // of interrupt occurred, and calls the specific routine to handle it.
    //
    //-----------------------------------------------------------------------------
    void Usb_ISR (void) interrupt 8        // USB中断入口
    {
    
        unsigned char bCommon, bIn, bOut;
        POLL_READ_BYTE (CMINT, bCommon);    // USB0公共中断寄存器    ------+
        POLL_READ_BYTE (IN1INT, bIn);        // USB0输入端点中断寄存器     |
        POLL_READ_BYTE (OUT1INT, bOut);        // USB0输出端点中断寄存器   |
        {                                                                  |
            if (bCommon & rbRSUINT) {        // 恢复-> 没有实质的动作      |
                Usb_Resume ();                                 ------------*-+
            }                                                              | |
            if (bCommon & rbRSTINT) {        // 复位                       | |
                Usb_Reset ();                                  ------------*-*-+
            }                                                              | | |
            if (bCommon & rbSUSINT)  {        // 挂起                      | | |
                Usb_Suspend ();                                ------------*-*-*---+
            }                                                              | | |   |
            if (bIn & rbEP0) {                // 端点0中断处理             | | |   |
                Handle_Control ();                             ------------*-*-*---*-----+
            }                                                              | | |   |     |
            if (bIn & rbIN1) {              // 端点1输入中断处理           | | |   |     |
                Handle_In1 ();                                 ------------*-*-*---*-+   |
            }                                                              | | |   | |   |
            if (bOut & rbOUT1) {            // 端点1输出中断处理           | | |   | |   |
                Handle_Out1 ();                                ------------*-*-*---*-*-+ |
            }                                                              | | |   | | | |
        }                                                                  | | |   | | | |
    }                                                                      | | |   | | | |
                                                                           | | |   | | | |
    #define POLL_READ_BYTE(addr, target) while(USB0ADR & 0x80);     <-----+ | |   | | | |
        READ_BYTE(addr, target);                               -------+      | |   | | | |
                                                                      |      | |   | | | |
    #define READ_BYTE(addr, target) USB0ADR = (0x80 | addr);  <------+      | |   | | | |
                             while (USB0ADR & 0x80); target = USB0DAT        | |   | | | |
                                                                             | |   | | | |
    void Usb_Resume(void)                     <------------------------------+ |   | | | |
    {                                                                          |   | | | |
        volatile int k;                                                        |   | | | |
                                                                               |   | | | |
        k++;                                                                   |   | | | |
                                                                               |   | | | |
        // Add code for resume                                                 |   | | | |
    }                                                                          |   | | | |
                                                                               |   | | | |
    void Usb_Reset (void)                     <--------------------------------+   | | | |
    {                                                                              | | | |
        USB0_STATE = DEV_DEFAULT;           // Set device state to default         | | | |
                                                                                   | | | |
        POLL_WRITE_BYTE (POWER, 0x01);      // Clear usb inhibit bit to enable USB | | | |
        // suspend detection                                                       | | | |
                                                                                   | | | |
        EP_STATUS[0] = EP_IDLE;             // Set default Endpoint Status         | | | |
        EP_STATUS[1] = EP_HALT;                                                    | | | |
        EP_STATUS[2] = EP_HALT;                                                    | | | |
    }                                                                              | | | |
                                                                                   | | | |
    void Usb_Suspend (void)         <----------------------------------------------+ | | |
    {                                                                                | | |
        volatile int k;                                                              | | |
        k++;                                                                         | | |
    }                                                                                | | |
                                                                                     | | |
    void Handle_In1 ()              <------------------------------------------------+ | |
    {                                                                                  | |
        EP_STATUS[1] = EP_IDLE;                                                        | |
    }                                                                                  | |
                                                                                       | |
    void Handle_Out1 ()             <--------------------------------------------------+ |
    {                                                                                    |
                                                                                         |
        unsigned char Count = 0;                                                         |
        unsigned char ControlReg;                                                        |
                                                                                         |
        POLL_WRITE_BYTE (INDEX, 1);         // Set index to endpoint 2 registers         |
        POLL_READ_BYTE (EOUTCSR1, ControlReg);                                           |
                                                                                         |
        if (EP_STATUS[1] == EP_HALT)        // If endpoint is halted, send a stall       |
        {                                                                                |
            POLL_WRITE_BYTE (EOUTCSR1, rbOutSDSTL);                                      |
        }                                                                                |
                                                                                         |
        else                                // Otherwise read received packet            |
            // from host                                                                 |
        {                                                                                |
            if (ControlReg & rbOutSTSTL)     // Clear sent stall bit if last             |
                // packet was a stall                                                    |
            {                                                                            |
                POLL_WRITE_BYTE (EOUTCSR1, rbOutCLRDT);                                  |
            }                                                                            |
                                                                                         |
            Setup_OUT_BUFFER ();             // configure buffer to save                 |
            // received data                                                             |
            Fifo_Read(FIFO_EP1, OUT_BUFFER.Length, OUT_BUFFER.Ptr);                      |
                                                                                         |
            // process data according to received Report ID.                             |
            // In systems with Report Descriptors that do not define report IDs,         |
            // the host will still format OUT packets with a prefix byte                 |
            // of '0x00'.                                                                |
                                                                                         |
            ReportHandler_OUT (OUT_BUFFER.Ptr[0]);                                       |
                                                                                         |
            POLL_WRITE_BYTE (EOUTCSR1, 0);   // Clear Out Packet ready bit               |
        }                                                                                |
    }                                                                                    |
                                                                                         |
    //-----------------------------------------------------------------------------      |
    // Handle_Control                                                                    |
    //-----------------------------------------------------------------------------      |
    //                                                                                   |
    // Return Value : None                                                               |
    // Parameters   : None                                                               |
    //                                                                                   |
    // - Decode Incoming SETUP requests                                                  |
    // - Load data packets on fifo while in transmit mode                                |
    //                                                                                   |
    //-----------------------------------------------------------------------------      |
                                                                                         |
    void Handle_Control (void)                    <--------------------------------------+
    {
        unsigned char ControlReg;           // Temporary storage for EP control register
    
        POLL_WRITE_BYTE (INDEX, 0);         // ¶ËµãË÷ÒýÖÁ ¶Ëµã0
        POLL_READ_BYTE (E0CSR, ControlReg); // Read control register
    
        if (EP_STATUS[0] == EP_ADDRESS)     // Handle Status Phase of Set Address
            // command
        {
            POLL_WRITE_BYTE (FADDR, SETUP.wValue.c[LSB]);
            EP_STATUS[0] = EP_IDLE;
        }
    
        if (ControlReg & rbSTSTL)           // If last packet was a sent stall,
            {                                   // reset STSTL bit and return EP0
                // to idle state
                POLL_WRITE_BYTE (E0CSR, 0);
                EP_STATUS[0] = EP_IDLE;
                return;
            }
    
        if (ControlReg & rbSUEND)           // If last SETUP transaction was
        {                                   // ended prematurely then set
            POLL_WRITE_BYTE (E0CSR, rbDATAEND);
            // Serviced SETUP End bit and return EP0
            POLL_WRITE_BYTE (E0CSR, rbSSUEND);
            EP_STATUS[0] = EP_IDLE;          // to idle state
        }
    
        if (EP_STATUS[0] == EP_IDLE)        // If Endpoint 0 is in idle mode
        {
            if (ControlReg & rbOPRDY)        // Make sure that EP 0 has an Out Packet
            {                                // ready from host although if EP0
                // is idle, this should always be the case
                /*
                                                         typedef struct
                                                         {
                // typedef union {unsigned int i; unsigned char c[2];} WORD;
    
                unsigned char bmRequestType;        // Request recipient, type, and dir.
                unsigned char bRequest;             // Specific standard request number
                WORD wValue;                        // varies according to request
                WORD wIndex;                        // varies according to request
                WORD wLength;                       // Number of bytes to transfer
                } setup_buffer;                        // End of SETUP Packet Type
                 */
                Fifo_Read (FIFO_EP0, 8, (unsigned char *)&SETUP);
                // Get SETUP Packet off of Fifo, it is currently Big-Endian
                // Compiler Specific - these next three statements swap the bytes of the
                // SETUP packet words to Big Endian so they can be compared to other 16-bit
                // values elsewhere properly
                SETUP.wValue.i = SETUP.wValue.c[MSB] + 256*SETUP.wValue.c[LSB];
                SETUP.wIndex.i = SETUP.wIndex.c[MSB] + 256*SETUP.wIndex.c[LSB];
                SETUP.wLength.i = SETUP.wLength.c[MSB] + 256*SETUP.wLength.c[LSB];
    
                // Intercept HID class-specific requests
                if( (SETUP.bmRequestType & ~0x80) == DSC_HID) {
                    switch (SETUP.bRequest) {
                        case GET_REPORT:
                            Get_Report ();                ----------------------------------+
                            break;                                                          |
                        case SET_REPORT:                                                    |
                            Set_Report ();                                                  |
                            break;                                                          |
                        case GET_IDLE:                                                      |
                            Get_Idle ();                                                    |
                            break;                                                          |
                        case SET_IDLE:                                                      |
                            Set_Idle ();                                                    |
                            break;                                                          |
                        case GET_PROTOCOL:                                                  |
                            Get_Protocol ();                                                |
                            break;                                                          |
                        case SET_PROTOCOL:                                                  |
                            Set_Protocol ();                                                |
                            break;                                                          |
                        default:                                                            |
                            Force_Stall ();      // Send stall to host if invalid           |
                            break;                 // request                               |
                    }                                                                       |
                } else                                                                      |
                                                                                            |
                    switch (SETUP.bRequest)       // Call correct subroutine to handle      |
                    {                             // each kind of standard request          |
                        case GET_STATUS:                                                    |
                            Get_Status ();                                                  |
                            break;                                                          |
                        case CLEAR_FEATURE:                                                 |
                            Clear_Feature ();                                               |
                            break;                                                          |
                        case SET_FEATURE:                                                   |
                            Set_Feature ();                                                 |
                            break;                                                          |
                        case SET_ADDRESS:                                                   |
                            Set_Address ();                                                 |
                            break;                                                          |
                        case GET_DESCRIPTOR:                                                |
                            Get_Descriptor ();                                              |
                            break;                                                          |
                        case GET_CONFIGURATION:                                             |
                            Get_Configuration ();                                           |
                            break;                                                          |
                        case SET_CONFIGURATION:                                             |
                            Set_Configuration ();                                           |
                            break;                                                          |
                        case GET_INTERFACE:                                                 |
                            Get_Interface ();                                               |
                            break;                                                          |
                        case SET_INTERFACE:                                                 |
                            Set_Interface ();                                               |
                            break;                                                          |
                        default:                                                            |
                            Force_Stall ();         // Send stall to host if invalid request|
                            break;                                                          |
                    }                                                                       |
            }                                                                               |
        }                                                                                   |
                                                                                            |
        if (EP_STATUS[0] == EP_TX)          // See if endpoint should transmit              |
        {                                                                                   |
            if (!(ControlReg & rbINPRDY) )   // Don't overwrite last packet                 |
            {                                                                               |
                // Read control register                                                    |
                POLL_READ_BYTE (E0CSR, ControlReg);                                         |
                                                                                            |
                // Check to see if SETUP End or Out Packet received, if so do not put       |
                // any new data on FIFO                                                     |
                if ((!(ControlReg & rbSUEND)) || (!(ControlReg & rbOPRDY)))                 |
                {                                                                           |
                    // Add In Packet ready flag to E0CSR bitmask                            |
                    ControlReg = rbINPRDY;                                                  |
                    if (DATASIZE >= EP0_PACKET_SIZE)                                        |
                    {                                                                       |
                        // Break Data into multiple packets if larger than Max Packet       |
                        Fifo_Write_InterruptServiceRoutine (FIFO_EP0, EP0_PACKET_SIZE,      |
                                (unsigned char*)DATAPTR);                                   |
                        // Advance data pointer                                             |
                        DATAPTR  += EP0_PACKET_SIZE;                                        |
                        // Decrement data size                                              |
                        DATASIZE -= EP0_PACKET_SIZE;                                        |
                        // Increment data sent counter                                      |
                        DATASENT += EP0_PACKET_SIZE;                                        |
                    }                                                                       |
                    else                                                                    |
                    {                                                                       |
                        // If data is less than Max Packet size or zero                     |
                        Fifo_Write_InterruptServiceRoutine (FIFO_EP0, DATASIZE,             |
                                (unsigned char*)DATAPTR);                                   |
                        ControlReg |= rbDATAEND;// Add Data End bit to bitmask              |
                        EP_STATUS[0] = EP_IDLE; // Return EP 0 to idle state                |
                    }                                                                       |
                    if (DATASENT == SETUP.wLength.i)                                        |
                    {                                                                       |
                        // This case exists when the host requests an even multiple of      |
                        // your endpoint zero max packet size, and you need to exit         |
                        // transmit mode without sending a zero length packet               |
                        ControlReg |= rbDATAEND;// Add Data End bit to mask                 |
                        EP_STATUS[0] = EP_IDLE; // Return EP 0 to idle state                |
                    }                                                                       |
                    // Write mask to E0CSR                                                  |
                    POLL_WRITE_BYTE(E0CSR, ControlReg);                                     |
                }                                                                           |
            }                                                                               |
        }                                                                                   |
                                                                                            |
        if (EP_STATUS[0] == EP_RX)          // See if endpoint should transmit              |
        {                                                                                   |
            // Read control register                                                        |
            POLL_READ_BYTE (E0CSR, ControlReg);                                             |
            if (ControlReg & rbOPRDY)        // Verify packet was received                  |
            {                                                                               |
                ControlReg = rbSOPRDY;                                                      |
                if (DATASIZE >= EP0_PACKET_SIZE)                                            |
                {                                                                           |
                    Fifo_Read(FIFO_EP0, EP0_PACKET_SIZE, (unsigned char*)DATAPTR);          |
                    // Advance data pointer                                                 |
                    DATAPTR  += EP0_PACKET_SIZE;                                            |
                    // Decrement data size                                                  |
                    DATASIZE -= EP0_PACKET_SIZE;                                            |
                    // Increment data sent counter                                          |
                    DATASENT += EP0_PACKET_SIZE;                                            |
                }                                                                           |
                else                                                                        |
                {                                                                           |
                    // read bytes from FIFO                                                 |
                    Fifo_Read (FIFO_EP0, DATASIZE, (unsigned char*) DATAPTR);               |
                                                                                            |
                    ControlReg |= rbDATAEND;   // signal end of data                        |
                    EP_STATUS[0] = EP_IDLE;    // set Endpoint to IDLE                      |
                }                                                                           |
                if (DATASENT == SETUP.wLength.i)                                            |
                {                                                                           |
                    ControlReg |= rbDATAEND;                                                |
                    EP_STATUS[0] = EP_IDLE;                                                 |
                }                                                                           |
                // if EP_RX mode was entered through a SET_REPORT request,                  |
                // call the ReportHandler_OUT function and pass the Report                  |
                // ID, which is the first by the of DATAPTR's buffer                        |
                if ( (EP_STATUS[0] == EP_IDLE) && (SETUP.bRequest == SET_REPORT) )          |
                {                                                                           |
                    ReportHandler_OUT (*DATAPTR);                                           |
                }                                                                           |
                                                                                            |
                if (EP_STATUS[0] != EP_STALL) POLL_WRITE_BYTE (E0CSR, ControlReg);          |
            }                                                                               |
        }                                                                                   |
                                                                                            |
    }                                                                                       |
                                                                                            |
    //-----------------------------------------------------------------------------         |
    //                                                                                      |
    // Return Value - None                                                                  |
    // Parameters - None                                                                    |
    //                                                                                      |
    // Description: Sends a given report type to the host.                                  |
    //                                                                                      |
    //-----------------------------------------------------------------------------         |
    void Get_Report (void)                                   <------------------------------+
    {
        // call appropriate handler to prepare buffer
        ReportHandler_IN_ISR(SETUP.wValue.c[LSB]);            --------------------+
        // set DATAPTR to buffer used inside Control Endpoint                     |
        DATAPTR = IN_BUFFER.Ptr;                                                  |
        DATASIZE = IN_BUFFER.Length;                                              |
                                                                                  |
        if (EP_STATUS[0] != EP_STALL)                                             |
        {                                                                         |
            // Set serviced SETUP Packet                                          |
            POLL_WRITE_BYTE (E0CSR, rbSOPRDY);                                    |
            EP_STATUS[0] = EP_TX;            // Endpoint 0 in transmit mode       |
            DATASENT = 0;                    // Reset DATASENT counter            |
        }                                                                         |
    }                                                                             |
                                                                                  |
    void ReportHandler_IN_ISR(unsigned char R_ID)            <--------------------+
    {
        unsigned char index;
    
        index = 0;
    
        while(index <= IN_VECTORTABLESize)
        {
            // check to see if Report ID passed into function
            // matches the Report ID for this entry in the Vector Table
            if(IN_VECTORTABLE[index].ReportID == R_ID)       ---------------------------+
            {                                                                           |
                IN_VECTORTABLE[index].hdlr();                                           |
                break;                                                                  |
            }                                                                           |
                                                                                        |
            // if Report IDs didn't match, increment the index pointer                  |
            index++;                                                                    |
        }                                                                               |
                                                                                        |
    }                                                                                   |
                                                                                        |
    // ****************************************************************************     |
    // Link all Report Handler functions to corresponding Report IDs                    |
    // ****************************************************************************     |
                                                                                        |
    const VectorTableEntry code IN_VECTORTABLE[IN_VECTORTABLESize] =        <-----------+
    {
        // FORMAT: Report ID, Report Handler
        0, IN_Report                                                       ------+
    };                                                                           |
                                                                                 |
    void IN_Report(void){                            <---------------------------+
    
        // save left mouse button stat to bit 0 of first data byte
        // IN_PACKET[2] = MOUSE_BUTTON1;
        // IN_PACKET[3] = MOUSE_BUTTON2;
        IN_BUFFER.Ptr = IN_PACKET;                   ---------+
        IN_BUFFER.Length = 8;                                 |
                                                              |
    }                                                         |
                                                              |
    unsigned char IN_PACKET[8] ={0,0,0,0,0,0,0,0};   <--------+
  • 相关阅读:
    海思HI3516A开发板顺利上线
    android WIFI信息获取
    五------Jsp九大内置对象。
    在Windows下搭建Apacheserver
    基于ContentObserver来动态取消或加入屏幕超时任务
    使用Intent的Flag设置启动參数
    IntelliJ IDEA像Eclipse一样打开多个项目
    怎样让IE支持自己定义协议
    《TCP/IP具体解释卷2:实现》笔记--协议控制块
    POJ2029:Get Many Persimmon Trees(二维树状数组)
  • 原文地址:https://www.cnblogs.com/zengjfgit/p/6654957.html
Copyright © 2011-2022 走看看