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

📄 tftp.c

📁 Intrisyc 公司的PXA255-bootloader,源码易懂
💻 C
📖 第 1 页 / 共 2 页
字号:
                }                case TFTP_EV_PACKET_ERROR:                {                    print_tftp_error(data);                    state->state = TFTP_ST_FINISHED;                    break;                }                default:                {                    // Illegal event in this state                    ev_err(state->state, event);                    break;                }            }            break;        }////////////////////////////////////////////////////////////////////////////////// Receive blocks state////////////////////////////////////////////////////////////////////////////////        case TFTP_ST_RECEIVE:        {            switch (event)            {                case TFTP_EV_PACKET_DATA:                {                    int const block = ntohs(*(u16 *)(data->ev_packet_x.data +                                            TFTP_BLOCK_OFFSET));                    // Make sure this is the packet we are expecting                    if (NEXT_BLOCK(state->block) == block)                    {                        //and add it to the total received                        received_block(state, data);                        /*                         * Here we check to see what the "actual" data size is.                         * If we don't in fact have 512 bytes we transition to                         * the finished state.                         */	                               if (data->ev_packet_x.length <                                TFTP_DATA_SIZE + TFTP_HEADER_SIZE)                        {                            state->state = TFTP_ST_FINISHED;                        }                    }                    //if it's a repeat, re-acknowledge it                    else if (state->block == block)                    {                        BLOCK_ERROR("+");                        // tftp server resent packet (probably didn't get                        // previous ack) so we ack it again                        if (retry(state))                        {                            tftpack(state->block, state->conn);                            // Stay in receive state                        }                        else                        {                            // Too many retries                            BLOCK_ERROR("!");                            state->state = TFTP_ST_FINISHED;                        }                        break;                    }                    else                    {                        // out of sync packet (this should never happen)                        BLOCK_ERROR("X");                        if (retry(state))                        {                            // Don't send ACK here                            // Stay in receive state                        }                        else                        {                            // Too many retries                            BLOCK_ERROR("!");                            state->state = TFTP_ST_FINISHED;                        }                        break;                    }                    break;                }                case TFTP_EV_TIMEOUT:                {                    BLOCK_ERROR(".");                    if (retry(state))                    {                        // Didn't receive our last block ACK or TFTP_ACK_WRQ                        tftpack(state->block, state->conn);                        // stay in receive state                    }                    else                    {                        // Too many retries                        BLOCK_ERROR("!");                        state->state = TFTP_ST_FINISHED;                    }                    break;                }                case TFTP_EV_PACKET_ERROR:                {                    print_tftp_error(data);                    state->state = TFTP_ST_FINISHED;                    break;                }                case TFTP_EV_PACKET_WRQ:                {                    // Hopefully, we are in server mode                    if (state->block == 0)                    {                        // Must have missed our last ACK                        BLOCK_ERROR("W");                        tftpack(TFTP_ACK_WRQ, state->conn);                    }                    else                    {                        itc_printf("ERROR: Unexpected WRQ\r\n");                        state->state = TFTP_ST_FINISHED;                    }                    break;                }                default:                {                    // Illegal event in this state                    ev_err(state->state, event);                    break;                }            }            break;        }////////////////////////////////////////////////////////////////////////////////// Server request state////////////////////////////////////////////////////////////////////////////////        case TFTP_ST_SERVER:        {            switch (event)            {                case TFTP_EV_PACKET_WRQ:                {                    state->start_time = get_time_timer();                    BLOCK_INDICATOR("W");                    tftpack(TFTP_ACK_WRQ, state->conn);                    state->state = TFTP_ST_RECEIVE;                    break;                }                case TFTP_EV_PACKET_ERROR:                {                    print_tftp_error(data);                    state->state = TFTP_ST_FINISHED;                    break;                }                case TFTP_EV_TIMEOUT:                {                    BLOCK_ERROR(".");                    break;                }                default:                {                    // Illegal event in this state                    ev_err(state->state, event);                    break;                }            }            break;        }////////////////////////////////////////////////////////////////////////////////// Finished state////////////////////////////////////////////////////////////////////////////////        case TFTP_ST_FINISHED:        {            // Nothing to do!            itc_printf("%s: We're finished!\r\n", __FUNCTION__);            break;        }////////////////////////////////////////////////////////////////////////////////// Unknown state////////////////////////////////////////////////////////////////////////////////        default:        {            // Unknown state            ev_err(state->state, event);            break;        }                }        return state->state == TFTP_ST_FINISHED;}////////////////////////////////////////////////////////////////////////////////// tftp_type_to_event// PURPOSE: Convert a TFTP packet type into the appropriate state machine event// PARAMS:  (IN) u16 - TFTP packet type// RETURNS  tftp_events - event code////////////////////////////////////////////////////////////////////////////////static inline tftp_eventstftp_type_to_event(u16 tftp_type){    switch (tftp_type)    {        case TFTP_OP_RRQ:       return TFTP_EV_PACKET_RRQ;        case TFTP_OP_WRQ:       return TFTP_EV_PACKET_WRQ;        case TFTP_OP_DATA:      return TFTP_EV_PACKET_DATA;        case TFTP_OP_ACK:       return TFTP_EV_PACKET_ACK;        case TFTP_OP_ERROR:     return TFTP_EV_PACKET_ERROR;        default:                return TFTP_EV_PACKET_UNKNOWN;    }}////////////////////////////////////////////////////////////////////////////////// tftp_sm_loop// PURPOSE: Send packet and timeout events into state machine// PARAMS:  (IN/OUT) state - state data//          (IN) event - initial event to send to the state machine//                       (with NULL data pointer)// RETURNS: file length or -1 for error////////////////////////////////////////////////////////////////////////////////static inttftp_sm_loop(tftp_state_data *state, tftp_events event){    u8 buf[MAX_PACKET_SIZE];    //we want the packet to be u16 aligned after the headers (42 bytes)    u8 * const packet = (u8 *)(buf + sizeof(u16) -                               (((u32)buf + UDPIP_HEADER_SIZE) % sizeof(u16)));    u8 * const udp_data = packet + UDPIP_HEADER_SIZE;    int tftp_timeout;    int done = 0;    u32 elapsed;    tftp_ev_data data;    /*     * Flush the Ethernet chip of data; any data that is there now is invalid     */    flush_ethernet();    // Send the initial event to the state machine    done = tftp_sm(state, event, NULL);    // Loop until the state machine reaches the finished state    tftp_timeout = get_time_timer () + TFTP_TIMEOUT_PERIOD;    while (!done)    {        int size;        if ((size = udp_recvfrom(&state->conn, packet,                TFTP_DATA_SIZE + TFTP_HEADER_SIZE + UDPIP_HEADER_SIZE,                &state->conn)) < 0)        {            // Problem receiving block; may be timeout            if (tftp_timeout < get_time_timer())	    {                done = tftp_sm(state, TFTP_EV_TIMEOUT, NULL);                // Reset the timeout                tftp_timeout = get_time_timer() + TFTP_TIMEOUT_PERIOD;            }        }        else        {            data.ev_packet_x.data = udp_data;            data.ev_packet_x.length = (u16) size;            done = tftp_sm(state,                           tftp_type_to_event(                                ntohs(*(u16 *)(udp_data + TFTP_TYPE_OFFSET))),                           &data);            // Reset the timeout            tftp_timeout = get_time_timer() + TFTP_TIMEOUT_PERIOD;        }    }    /*     * We are done, so we should clean up after ourselves.     */    rx_ethernet_off();    flush_ethernet();    show_received(state, 1);    elapsed = MAX(1, get_time_timer() - state->start_time);    itc_printf("\r\nDownloaded %i bytes at %i kB/s\r\n",           state->file_length, (state->file_length / 1024) / elapsed);    // Calling retry here actually changes the retry count, which means that    // in the pathological case of the transfer succeeding after exactly    // TFTP_RETRIES-1 tries, we will erroneously return failure.    return retry(state) ? state->file_length : -1;}////////////////////////////////////////////////////////////////////////////////// tftplisten// PURPOSE: Listens for a TFTP connection to receive an MS bin file// PARAMS:  (IN) u8 *dest - memory location to put downloaded bin file in// RETURNS: Size of upload in bytes.////////////////////////////////////////////////////////////////////////////////inttftplisten(u8 *dest){    tftp_state_data state;    itc_printf("Awaiting file send: ");    // Initialize state variable    memset8((u8 *)&state, 0, sizeof(state));    //state.state = TFTP_ST_INIT;    state.dest = dest;    // Start the state machine    return tftp_sm_loop(&state, TFTP_EV_BEGIN_TX);}////////////////////////////////////////////////////////////////////////////////// tftpget// PURPOSE: downloads a file via tftp. Server to download determined externally.// PARAMS:  (IN) char * file - file to request.//          (IN) u8 * dest   - buffer to store file.// RETURNS  int - size of download in bytes.////////////////////////////////////////////////////////////////////////////////inttftpget(char const *file,        u8 *dest){    tftp_state_data state;    itc_printf("Downloading %s: ", file);    // Initialize state variables    memset8((u8 *)&state, 0, sizeof(state));    //state.state = TFTP_ST_INIT;    state.dest = dest;    state.file_name = file;    // Start the state machine    return tftp_sm_loop(&state, TFTP_EV_BEGIN_RX);}

⌨️ 快捷键说明

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