Exemplo n.º 1
0
// See serial_packet.h for documentation on this function.
status_t serial_packet_read(const peripheral_descriptor_t * self, uint8_t ** packet, uint32_t * packetLength, packet_type_t packetType)
{
    if (!packet || !packetLength)
    {
        debug_printf("Error: invalid packet\r\n");
        return kStatus_InvalidArgument;
    }
    *packetLength = 0;
    status_t status;

    g_serialContext.isBackToBackWrite = false;

    // Send ACK if needed.
    status = send_deferred_ack();
    if (status != kStatus_Success)
    {
        return status;
    }

    framing_data_packet_t framingPacket;

    bool isPacketOk;
    do {
        // Clear the packet data area so unsent parameters default to zero.
        memset(g_serialContext.data, 0, sizeof(g_serialContext.data));

        // Receive the framing data packet.
        isPacketOk = true;
        status_t status = read_data_packet(&framingPacket, g_serialContext.data, packetType);
        if (status != kStatus_Success)
        {
            // No packet available.
            *packetLength = 0;
            return status;
        }

        // Verify crc.
        uint16_t calculated_crc = calculate_framing_crc16(&framingPacket, g_serialContext.data);
        if (framingPacket.crc16 != calculated_crc)
        {
            debug_printf("Error: invalid crc 0x%x, expected 0x%x\r\n", framingPacket.crc16, calculated_crc);
            isPacketOk = false;
        }

        // Send Nak if necessary.
        if (!isPacketOk)
        {
            serial_packet_send_sync(kFramingPacketType_Nak);
        }
    } while (!isPacketOk);

    // Indicate an ACK must be sent.
    g_serialContext.isAckNeeded = true;

    // Set caller's data buffer and length
    *packet = g_serialContext.data;
    *packetLength = framingPacket.length;

    return kStatus_Success;
}
Exemplo n.º 2
0
// See serial_packet.h for documentation on this function.
status_t serial_packet_write(const peripheral_descriptor_t *self,
                             const uint8_t *packet,
                             uint32_t byteCount,
                             packet_type_t packetType)
{
    if (!packet || (byteCount > kOutgoingPacketBufferSize))
    {
        debug_printf("Error: invalid packet or packet size %d\r\n", byteCount);
        return kStatus_InvalidArgument;
    }

    // Send ACK if needed.
    status_t status = send_deferred_ack();
    if (status != kStatus_Success)
    {
        return status;
    }

    // Back-to-back writes require delay for receiver to enter peripheral read routine.
    if (g_serialContext.isBackToBackWrite)
    {
        g_serialContext.isBackToBackWrite = false;

#if defined(BOOTLOADER_HOST)
        host_delay(100);
#endif
    }

    // Initialize the framing data packet.
    serial_framing_packet_t *framingPacket = &g_serialContext.framingPacket;
    framingPacket->dataPacket.header.startByte = kFramingPacketStartByte;
    framingPacket->dataPacket.header.packetType = kFramingPacketType_Command;
    if (packetType != kPacketType_Command)
    {
        framingPacket->dataPacket.header.packetType = kFramingPacketType_Data;
    }
    framingPacket->dataPacket.length = (uint16_t)byteCount;

    // Copy the caller's data buffer into the framing packet.
    if (byteCount)
    {
        memcpy(framingPacket->data, packet, byteCount);
    }

    // Calculate and set the framing packet crc.
    framingPacket->dataPacket.crc16 =
        calculate_framing_crc16(&framingPacket->dataPacket, (uint8_t *)framingPacket->data);
#if defined(TEST_NAK)
    ++framingPacket->dataPacket.crc16;
#endif // TEST_NAK

    // Send the framing data packet.
    status = write_data((uint8_t *)framingPacket, sizeof(framing_data_packet_t) + byteCount);
    if (status != kStatus_Success)
    {
        return status;
    }

    return wait_for_ack_packet();
}
Exemplo n.º 3
0
//! @brief Handle a command transaction.
static status_t handle_command_internal(uint8_t *packet, uint32_t packetLength)
{
    serial_framing_packet_t framingPacket;
    status_t status = kStatus_Success;

    uint8_t *rxBuf = (uint8_t *)g_targetRxBuffer;
    uint8_t rxSize = 0;

    framing_sync_packet_t sync;

    // Convert to framing packet
    framingPacket.dataPacket.header.startByte = kFramingPacketStartByte;
    framingPacket.dataPacket.header.packetType = kFramingPacketType_Command;
    // Only read, write memory, receive SB file and flash read resource will have data command type
    // Will add later
    framingPacket.dataPacket.length = packetLength;

    // Copy the caller's data buffer into the framing packet.
    if (packetLength)
    {
        memcpy(framingPacket.data, packet, packetLength);
    }

    framingPacket.dataPacket.crc16 = calculate_framing_crc16(&framingPacket.dataPacket, (uint8_t *)framingPacket.data);

    // send framing packet to target peripheral
    if (peripheral_write((uint8_t *)&framingPacket, sizeof(framing_data_packet_t) + framingPacket.dataPacket.length) !=
        kStatus_Success)
    {
        status = kStatus_Fail;
    }
    else // recering ACK from target peripheral
    {
        uint8_t count = 32;
        do
        {
            if (peripheral_read((uint8_t *)&sync.header.startByte, 1) != kStatus_Success)
            {
                status = kStatus_Fail;
                break;
            }
            else
            {
                if (sync.header.startByte == kFramingPacketStartByte)
                {
                    if (peripheral_read((uint8_t *)&sync.header.packetType, 1) != kStatus_Success)
                    {
                        status = kStatus_Fail;
                    }
                    else if (sync.header.packetType != kFramingPacketType_Ack)
                    {
                        status = kStatus_Fail;
                    }
                    else
                    {
                        // receiving framing paket header
                        if (peripheral_read(rxBuf, sizeof(framing_data_packet_t)) != kStatus_Success)
                        {
                            status = kStatus_Fail;
                        }
                        else
                        {
                            rxSize = ((framing_data_packet_t *)rxBuf)->length;
                            if (peripheral_read(rxBuf + sizeof(framing_data_packet_t), rxSize) != kStatus_Success)
                            {
                                status = kStatus_Fail;
                                sync.header.packetType = kFramingPacketType_Nak;
                            }
                            else
                            {
                                sync.header.packetType = kFramingPacketType_Ack;
                            }

                            // send Ack/Nak back to peripheral
                            peripheral_write((uint8_t *)&sync, sizeof(framing_sync_packet_t));
                        }
                    }
                    break;
                }
            }
        } while (count-- != 0); // really good??
    }

    if (status == kStatus_Success)
    {
        status =
            usb_hid_packet_write(&g_peripherals[0], rxBuf + sizeof(framing_data_packet_t), rxSize, kPacketType_Command);
    }

    return status;
}
Exemplo n.º 4
0
static status_t handle_data_write(bool *hasMoreData)
{
    serial_framing_packet_t framingPacket;

    if (g_commandData.dataPhase.count == 0)
    {
        // No data phase.
        *hasMoreData = false;
        finalize_data_phase(kStatus_Success);
        return kStatus_Success;
    }

    *hasMoreData = true;
    uint32_t remaining = g_commandData.dataPhase.count;
    uint32_t dataAddress = g_commandData.dataPhase.address;
    uint8_t *packet;
    uint32_t packetLength = 0;
    status_t status;

    framing_sync_packet_t sync;

    // read data packet
    status = usb_hid_packet_read(&g_peripherals[0], &packet, &packetLength, kPacketType_Data);
    if (status != kStatus_Success)
    {
        // Abort data phase due to error.
        debug_printf("consumer abort data phase due to status 0x%x\r\n", status);
        //        g_packetInterface->abortDataPhase(0);
        finalize_data_phase(status);
        *hasMoreData = false;
        return kStatus_Success;
    }

    if (packetLength == 0)
    {
        // Sender requested data phase abort.
        debug_printf("Data phase aborted by sender\r\n");
        //        finalize_data_phase(kStatus_AbortDataPhase);
        finalize_data_phase(kStatus_Success);
        *hasMoreData = false;
        return kStatus_Success;
    }

    packetLength = MIN(packetLength, remaining);

    // Convert to framing packet
    framingPacket.dataPacket.header.startByte = kFramingPacketStartByte;
    framingPacket.dataPacket.header.packetType = kFramingPacketType_Data;

    framingPacket.dataPacket.length = packetLength;

    // Copy the caller's data buffer into the framing packet.
    if (packetLength)
    {
        memcpy(framingPacket.data, packet, packetLength);
    }

    framingPacket.dataPacket.crc16 = calculate_framing_crc16(&framingPacket.dataPacket, (uint8_t *)framingPacket.data);

    // send framing packet to target peripheral
    if (peripheral_write((uint8_t *)&framingPacket, sizeof(framing_data_packet_t) + framingPacket.dataPacket.length) !=
        kStatus_Success)
    {
        status = kStatus_Fail;
    }
    // recering ACK from target peripheral
    else
    {
        uint8_t count = 32;
        do
        {
            if (peripheral_read((uint8_t *)&sync.header, 2) != kStatus_Success)
            {
                status = kStatus_Fail;
            }
            else
            {
                if ((sync.header.startByte != kFramingPacketStartByte) &&
                    (sync.header.packetType != kFramingPacketType_Ack))
                {
                    status = kStatus_Fail;
                }
                break;
            }
        } while ((sync.header.startByte != kFramingPacketStartByte) && (count-- != 0)); //
    }

    dataAddress += packetLength;
    remaining -= packetLength;

    if (remaining == 0)
    {
        finalize_data_phase(status);
        *hasMoreData = false;
    }
    else if (status != kStatus_Success)
    {
        debug_printf("writePacket aborted due to status 0x%x\r\n", status);
        finalize_data_phase(status);
        *hasMoreData = false;
    }
    else
    {
        g_commandData.dataPhase.count = remaining;
        g_commandData.dataPhase.address = dataAddress;
    }

    return kStatus_Success;
}