示例#1
0
/*
 * Stall all endpoints and set a flag indicating any current transfers
 * should be aborted. IO loops will see this flag in TimerWorker().
 */
void
SetAbortState()
{
    uint8_t origEndpoint = Endpoint_GetCurrentEndpoint();

    doDeviceReset = true;
    Endpoint_SelectEndpoint(XUM_BULK_OUT_ENDPOINT);
    Endpoint_StallTransaction();
    Endpoint_SelectEndpoint(XUM_BULK_IN_ENDPOINT);
    Endpoint_StallTransaction();

    Endpoint_SelectEndpoint(origEndpoint);
}
示例#2
0
/** Function to read in a command block from the host, via the bulk data OUT endpoint. This function reads in the next command block
 *  if one has been issued, and performs validation to ensure that the block command is valid.
 *
 *  \return Boolean true if a valid command block has been read in from the endpoint, false otherwise
 */
static bool ReadInCommandBlock(void)
{
    uint16_t BytesTransferred;

    /* Select the Data Out endpoint */
    Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPADDR);

    /* Abort if no command has been sent from the host */
    if (!(Endpoint_IsOUTReceived()))
        return false;

    /* Read in command block header */
    BytesTransferred = 0;
    while (Endpoint_Read_Stream_LE(&CommandBlock, (sizeof(CommandBlock) - sizeof(CommandBlock.SCSICommandData)),
                                   &BytesTransferred) == ENDPOINT_RWSTREAM_IncompleteTransfer)
    {
        /* Check if the current command is being aborted by the host */
        if (IsMassStoreReset)
            return false;
    }

    /* Verify the command block - abort if invalid */
    if ((CommandBlock.Signature         != MS_CBW_SIGNATURE) ||
            (CommandBlock.LUN               >= TOTAL_LUNS)       ||
            (CommandBlock.Flags              & 0x1F)             ||
            (CommandBlock.SCSICommandLength == 0)                ||
            (CommandBlock.SCSICommandLength >  sizeof(CommandBlock.SCSICommandData)))
    {
        /* Stall both data pipes until reset by host */
        Endpoint_StallTransaction();
        Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPADDR);
        Endpoint_StallTransaction();

        return false;
    }

    /* Read in command block command data */
    BytesTransferred = 0;
    while (Endpoint_Read_Stream_LE(&CommandBlock.SCSICommandData, CommandBlock.SCSICommandLength,
                                   &BytesTransferred) == ENDPOINT_RWSTREAM_IncompleteTransfer)
    {
        /* Check if the current command is being aborted by the host */
        if (IsMassStoreReset)
            return false;
    }

    /* Finalize the stream transfer to send the last packet */
    Endpoint_ClearOUT();

    return true;
}
示例#3
0
static bool MS_Device_ReadInCommandBlock(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
	uint16_t BytesProcessed;

	Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber);

	BytesProcessed = 0;
	while (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock,
	                               (sizeof(MS_CommandBlockWrapper_t) - 16), &BytesProcessed) ==
	                               ENDPOINT_RWSTREAM_IncompleteTransfer)
	{
		#if !defined(INTERRUPT_CONTROL_ENDPOINT)
		USB_USBTask();
		#endif

		if (MSInterfaceInfo->State.IsMassStoreReset)
		  return false;
	}

	if ((MSInterfaceInfo->State.CommandBlock.Signature         != CPU_TO_LE32(MS_CBW_SIGNATURE))     ||
	    (MSInterfaceInfo->State.CommandBlock.LUN               >= MSInterfaceInfo->Config.TotalLUNs) ||
		(MSInterfaceInfo->State.CommandBlock.Flags              & 0x1F)                              ||
		(MSInterfaceInfo->State.CommandBlock.SCSICommandLength == 0)                                 ||
		(MSInterfaceInfo->State.CommandBlock.SCSICommandLength >  16))
	{
		Endpoint_StallTransaction();
		Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber);
		Endpoint_StallTransaction();

		return false;
	}

	BytesProcessed = 0;
	while (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock.SCSICommandData,
	                                MSInterfaceInfo->State.CommandBlock.SCSICommandLength, &BytesProcessed) ==
	                                ENDPOINT_RWSTREAM_IncompleteTransfer)
	{
		#if !defined(INTERRUPT_CONTROL_ENDPOINT)
		USB_USBTask();
		#endif

		if (MSInterfaceInfo->State.IsMassStoreReset)
		  return false;
	}

	Endpoint_ClearOUT();

	return true;
}
示例#4
0
uint8_t RNDIS_Device_ReadPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
                                void* Buffer,
                                uint16_t* const PacketLength)
{
	if ((USB_DeviceState != DEVICE_STATE_Configured) ||
	    (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))
	{
		return ENDPOINT_RWSTREAM_DeviceDisconnected;
	}

	Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpoint.Address);

	*PacketLength = 0;

	if (!(Endpoint_IsOUTReceived()))
		return ENDPOINT_RWSTREAM_NoError;

	RNDIS_Packet_Message_t RNDISPacketHeader;
	Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL);

	if (le32_to_cpu(RNDISPacketHeader.DataLength) > ETHERNET_FRAME_SIZE_MAX)
	{
		Endpoint_StallTransaction();

		return RNDIS_ERROR_LOGICAL_CMD_FAILED;
	}

	*PacketLength = (uint16_t)le32_to_cpu(RNDISPacketHeader.DataLength);

	Endpoint_Read_Stream_LE(Buffer, *PacketLength, NULL);
	Endpoint_ClearOUT();

	return ENDPOINT_RWSTREAM_NoError;
}
/** Function to manage TMC data transmission and reception to and from the host. */
void TMC_Task(void)
{
	/* Device must be connected and configured for the task to run */
	if (USB_DeviceState != DEVICE_STATE_Configured)
	  return;

	TMC_MessageHeader_t MessageHeader;
	uint8_t             MessagePayload[128];

	/* Try to read in a TMC message from the interface, process if one is available */
	if (ReadTMCHeader(&MessageHeader))
	{
		/* Indicate busy */
		LEDs_SetAllLEDs(LEDMASK_USB_BUSY);

		switch (MessageHeader.MessageID)
		{
			case TMC_MESSAGEID_DEV_DEP_MSG_OUT:
				LastTransferLength = 0;
				while (Endpoint_Read_Stream_LE(MessagePayload, MIN(MessageHeader.TransferSize, sizeof(MessagePayload)), &LastTransferLength) ==
				       ENDPOINT_RWSTREAM_IncompleteTransfer)
				{
					if (IsTMCBulkOUTReset)
					  break;
				}

				Endpoint_ClearOUT();

				ProcessSentMessage(MessagePayload, LastTransferLength);
				break;
			case TMC_MESSAGEID_DEV_DEP_MSG_IN:
				Endpoint_ClearOUT();

				MessageHeader.TransferSize = GetNextMessage(MessagePayload);
				MessageHeader.MessageIDSpecific.DeviceOUT.LastMessageTransaction = true;
				WriteTMCHeader(&MessageHeader);

				LastTransferLength = 0;
				while (Endpoint_Write_Stream_LE(MessagePayload, MessageHeader.TransferSize, &LastTransferLength) ==
				       ENDPOINT_RWSTREAM_IncompleteTransfer)
				{
					if (IsTMCBulkINReset)
					  break;
				}

				Endpoint_ClearIN();
				break;
			default:
				Endpoint_StallTransaction();
				break;
		}

		LEDs_SetAllLEDs(LEDMASK_USB_READY);
	}

	/* All pending data has been processed - reset the data abort flags */
	IsTMCBulkINReset  = false;
	IsTMCBulkOUTReset = false;
}
示例#6
0
/** Function to read in a command block from the host, via the bulk data OUT endpoint. This function reads in the next command block
 *  if one has been issued, and performs validation to ensure that the block command is valid.
 *
 *  \return Boolean true if a valid command block has been read in from the endpoint, false otherwise
 */
static bool ReadInCommandBlock(void)
{
	/* Select the Data Out endpoint */
	Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);

	/* Abort if no command has been sent from the host */
	if (!(Endpoint_IsOUTReceived()))
	  return false;

	/* Read in command block header */
	Endpoint_Read_Stream_LE(&CommandBlock, (sizeof(CommandBlock) - sizeof(CommandBlock.SCSICommandData)),
	                        StreamCallback_AbortOnMassStoreReset);

	/* Check if the current command is being aborted by the host */
	if (IsMassStoreReset)
	  return false;

	/* Verify the command block - abort if invalid */
	if ((CommandBlock.Signature         != CBW_SIGNATURE) ||
	    (CommandBlock.LUN               >= TOTAL_LUNS)    ||
		(CommandBlock.Flags              & 0x1F)          ||
		(CommandBlock.SCSICommandLength == 0)             ||
		(CommandBlock.SCSICommandLength >  MAX_SCSI_COMMAND_LENGTH))
	{
		/* Stall both data pipes until reset by host */
		Endpoint_StallTransaction();
		Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);
		Endpoint_StallTransaction();

		return false;
	}

	/* Read in command block command data */
	Endpoint_Read_Stream_LE(&CommandBlock.SCSICommandData,
	                        CommandBlock.SCSICommandLength,
	                        StreamCallback_AbortOnMassStoreReset);

	/* Check if the current command is being aborted by the host */
	if (IsMassStoreReset)
	  return false;

	/* Finalize the stream transfer to send the last packet */
	Endpoint_ClearOUT();

	return true;
}
示例#7
0
void EVENT_USB_Device_ControlRequest(void){
    void* buffer = NULL;
    uint16_t length =  0;
    if(change != NULL) {
        usb_set_device(change, 1);
        Endpoint_ClearSETUP();
        Endpoint_ClearIN();
        Endpoint_ClearOUT();
    } else { 
        Endpoint_ClearSETUP();
    }
    uart_print("Type: %x, req: %x, val: %x, idx: %x, len: %d\n",
                USB_ControlRequest.bmRequestType,
                USB_ControlRequest.bRequest,
                USB_ControlRequest.wValue,
                USB_ControlRequest.wIndex,
                USB_ControlRequest.wLength);

    device->handle_configuration(   device,
                                    USB_ControlRequest.bmRequestType,
                                    USB_ControlRequest.bRequest,
                                    USB_ControlRequest.wValue,
                                    USB_ControlRequest.wIndex,
                                    USB_ControlRequest.wLength,
                                    &buffer,
                                    &length);

    if(buffer) {
        if(length == 0xFFFF) {
            return;
        }

        if(length) {
            if(length & CONST_PTR) {
                Endpoint_Write_Control_PStream_LE(buffer, length & ~CONST_PTR);
            } else {
                Endpoint_Write_Control_Stream_LE(buffer, length);
            }
        }

        Endpoint_ClearStatusStage();

        if(deferred_addr >= 0) {
            _usb_set_addr(deferred_addr);
            uart_print("Setting addr to %d\n", deferred_addr);
            deferred_addr = -1;
        }

    } else {
        Endpoint_StallTransaction();
        uart_print("STALLED!\n");
    }

}
示例#8
0
/** Task to manage the Mass Storage interface, reading in Command Block Wrappers from the host, processing the SCSI commands they
 *  contain, and returning Command Status Wrappers back to the host to indicate the success or failure of the last issued command.
 */
void MassStorage_Task(void)
{
	/* Device must be connected and configured for the task to run */
	if (USB_DeviceState != DEVICE_STATE_Configured)
	  return;

	/* Process sent command block from the host if one has been sent */
	if (ReadInCommandBlock())
	{
		/* Indicate busy */
		LEDs_SetAllLEDs(LEDMASK_USB_BUSY);

		/* Check direction of command, select Data IN endpoint if data is from the device */
		if (CommandBlock.Flags & COMMAND_DIRECTION_DATA_IN)
		  Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);

		/* Decode the received SCSI command, set returned status code */
		CommandStatus.Status = SCSI_DecodeSCSICommand() ? Command_Pass : Command_Fail;

		/* Load in the CBW tag into the CSW to link them together */
		CommandStatus.Tag = CommandBlock.Tag;

		/* Load in the data residue counter into the CSW */
		CommandStatus.DataTransferResidue = CommandBlock.DataTransferLength;

		/* Stall the selected data pipe if command failed (if data is still to be transferred) */
		if ((CommandStatus.Status == Command_Fail) && (CommandStatus.DataTransferResidue))
		  Endpoint_StallTransaction();

		/* Return command status block to the host */
		ReturnCommandStatus();

		/* Indicate ready */
		LEDs_SetAllLEDs(LEDMASK_USB_READY);
	}

	/* Check if a Mass Storage Reset occurred */
	if (IsMassStoreReset)
	{
		/* Reset the data endpoint banks */
		Endpoint_ResetFIFO(MASS_STORAGE_OUT_EPNUM);
		Endpoint_ResetFIFO(MASS_STORAGE_IN_EPNUM);

		Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);
		Endpoint_ClearStall();
		Endpoint_ResetDataToggle();
		Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);
		Endpoint_ClearStall();
		Endpoint_ResetDataToggle();

		/* Clear the abort transfer flag */
		IsMassStoreReset = false;
	}
}
static void USB_Device_ClearSetFeature(void)
{
	switch (USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT)
	{
		#if !defined(NO_DEVICE_REMOTE_WAKEUP)
		case REQREC_DEVICE:
			if ((uint8_t)USB_ControlRequest.wValue == FEATURE_SEL_DeviceRemoteWakeup)
			  USB_Device_RemoteWakeupEnabled = (USB_ControlRequest.bRequest == REQ_SetFeature);
			else
			  return;

			break;
		#endif
		#if !defined(CONTROL_ONLY_DEVICE)
		case REQREC_ENDPOINT:
			if ((uint8_t)USB_ControlRequest.wValue == FEATURE_SEL_EndpointHalt)
			{
				uint8_t EndpointIndex = ((uint8_t)USB_ControlRequest.wIndex & ENDPOINT_EPNUM_MASK);

				if (EndpointIndex == ENDPOINT_CONTROLEP)
				  return;

				Endpoint_SelectEndpoint(EndpointIndex);

				if (Endpoint_IsEnabled())
				{
					if (USB_ControlRequest.bRequest == REQ_SetFeature)
					{
						Endpoint_StallTransaction();
					}
					else
					{
						Endpoint_ClearStall();
						Endpoint_ResetEndpoint(EndpointIndex);
						Endpoint_ResetDataToggle();
					}
				}
			}

			break;
		#endif
		default:
			return;
	}

	Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);

	Endpoint_ClearSETUP();

	Endpoint_ClearStatusStage();
}
示例#10
0
static bool MS_Device_ReadInCommandBlock(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
	Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber);

	CallbackIsResetSource = &MSInterfaceInfo->State.IsMassStoreReset;
	if (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock,
	                            (sizeof(MS_CommandBlockWrapper_t) - 16),
	                            StreamCallback_MS_Device_AbortOnMassStoreReset))
	{
		return false;
	}
	
	if ((MSInterfaceInfo->State.CommandBlock.Signature         != MS_CBW_SIGNATURE)                  ||
	    (MSInterfaceInfo->State.CommandBlock.LUN               >= MSInterfaceInfo->Config.TotalLUNs) ||
		(MSInterfaceInfo->State.CommandBlock.Flags              & 0x1F)                              ||
		(MSInterfaceInfo->State.CommandBlock.SCSICommandLength == 0)                                 ||
		(MSInterfaceInfo->State.CommandBlock.SCSICommandLength >  16))
	{
		Endpoint_StallTransaction();
		Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber);
		Endpoint_StallTransaction();
		
		return false;
	}

	CallbackIsResetSource = &MSInterfaceInfo->State.IsMassStoreReset;
	if (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock.SCSICommandData,
	                            MSInterfaceInfo->State.CommandBlock.SCSICommandLength,
	                            StreamCallback_MS_Device_AbortOnMassStoreReset))
	{
		return false;
	}

	Endpoint_ClearOUT();
	
	return true;
}
void MS_Device_USBTask(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
	if (USB_DeviceState[MSInterfaceInfo->Config.PortNumber] != DEVICE_STATE_Configured)
	  return;

	Endpoint_SelectEndpoint(MSInterfaceInfo->Config.PortNumber, MSInterfaceInfo->Config.DataOUTEndpointNumber);

	if (Endpoint_IsReadWriteAllowed(MSInterfaceInfo->Config.PortNumber))
	{
		if (MS_Device_ReadInCommandBlock(MSInterfaceInfo))
		{
			if (MSInterfaceInfo->State.CommandBlock.Flags & MS_COMMAND_DIR_DATA_IN)
			  Endpoint_SelectEndpoint(MSInterfaceInfo->Config.PortNumber, MSInterfaceInfo->Config.DataINEndpointNumber);

			bool SCSICommandResult = CALLBACK_MS_Device_SCSICommandReceived(MSInterfaceInfo);

			Endpoint_SelectEndpoint(MSInterfaceInfo->Config.PortNumber, MSInterfaceInfo->Config.DataOUTEndpointNumber);// for streaming
			Endpoint_ClearOUT(MSInterfaceInfo->Config.PortNumber);
			if (MSInterfaceInfo->State.CommandBlock.Flags & MS_COMMAND_DIR_DATA_IN)
				Endpoint_SelectEndpoint(MSInterfaceInfo->Config.PortNumber, MSInterfaceInfo->Config.DataINEndpointNumber);
			MSInterfaceInfo->State.CommandStatus.Status              = (SCSICommandResult) ? MS_SCSI_COMMAND_Pass : MS_SCSI_COMMAND_Fail;
			MSInterfaceInfo->State.CommandStatus.Signature           = CPU_TO_LE32(MS_CSW_SIGNATURE);
			MSInterfaceInfo->State.CommandStatus.Tag                 = MSInterfaceInfo->State.CommandBlock.Tag;
			MSInterfaceInfo->State.CommandStatus.DataTransferResidue = MSInterfaceInfo->State.CommandBlock.DataTransferLength;

			if (!(SCSICommandResult) && (le32_to_cpu(MSInterfaceInfo->State.CommandStatus.DataTransferResidue)))
			  Endpoint_StallTransaction(MSInterfaceInfo->Config.PortNumber);

			MS_Device_ReturnCommandStatus(MSInterfaceInfo);
		}
	}

	if (MSInterfaceInfo->State.IsMassStoreReset)
	{
		Endpoint_ResetEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber);
		Endpoint_ResetEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber);

		Endpoint_SelectEndpoint(MSInterfaceInfo->Config.PortNumber, MSInterfaceInfo->Config.DataOUTEndpointNumber);
		Endpoint_ClearStall(MSInterfaceInfo->Config.PortNumber);
		Endpoint_ResetDataToggle(MSInterfaceInfo->Config.PortNumber);
		Endpoint_SelectEndpoint(MSInterfaceInfo->Config.PortNumber, MSInterfaceInfo->Config.DataINEndpointNumber);
		Endpoint_ClearStall(MSInterfaceInfo->Config.PortNumber);
		Endpoint_ResetDataToggle(MSInterfaceInfo->Config.PortNumber);

		MSInterfaceInfo->State.IsMassStoreReset = false;
	}
}
示例#12
0
void MS_Device_USBTask(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
	if (USB_DeviceState != DEVICE_STATE_Configured)
	  return;

	Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber);

	if (Endpoint_IsReadWriteAllowed())
	{
		if (MS_Device_ReadInCommandBlock(MSInterfaceInfo))
		{
			if (MSInterfaceInfo->State.CommandBlock.Flags & MS_COMMAND_DIR_DATA_IN)
			  Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber);

			MSInterfaceInfo->State.CommandStatus.Status = CALLBACK_MS_Device_SCSICommandReceived(MSInterfaceInfo) ?
			                                               MS_SCSI_COMMAND_Pass : MS_SCSI_COMMAND_Fail;
			MSInterfaceInfo->State.CommandStatus.Signature           = MS_CSW_SIGNATURE;
			MSInterfaceInfo->State.CommandStatus.Tag                 = MSInterfaceInfo->State.CommandBlock.Tag;
			MSInterfaceInfo->State.CommandStatus.DataTransferResidue = MSInterfaceInfo->State.CommandBlock.DataTransferLength;

			if ((MSInterfaceInfo->State.CommandStatus.Status == MS_SCSI_COMMAND_Fail) &&
			    (MSInterfaceInfo->State.CommandStatus.DataTransferResidue))
			{
				Endpoint_StallTransaction();
			}

			MS_Device_ReturnCommandStatus(MSInterfaceInfo);
		}
	}

	if (MSInterfaceInfo->State.IsMassStoreReset)
	{
		Endpoint_ResetFIFO(MSInterfaceInfo->Config.DataOUTEndpointNumber);
		Endpoint_ResetFIFO(MSInterfaceInfo->Config.DataINEndpointNumber);

		Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpointNumber);
		Endpoint_ClearStall();
		Endpoint_ResetDataToggle();
		Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpointNumber);
		Endpoint_ClearStall();
		Endpoint_ResetDataToggle();

		MSInterfaceInfo->State.IsMassStoreReset = false;
	}
}
示例#13
0
/** Function to manage TMC data transmission and reception to and from the host. */
void TMC_Task(void)
{
    /* Device must be connected and configured for the task to run */
    if (USB_DeviceState != DEVICE_STATE_Configured)
        return;

    TMC_MessageHeader_t MessageHeader;

    /* Try to read in a TMC message from the interface, process if one is available */
    if (ReadTMCHeader(&MessageHeader))
    {
        /* Indicate busy */
        LEDs_SetAllLEDs(LEDMASK_USB_BUSY);

        switch (MessageHeader.MessageID)
        {
        case TMC_MESSAGEID_DEV_DEP_MSG_OUT:
            Endpoint_Discard_Stream(MessageHeader.TransferSize, StreamCallback_AbortOUTOnRequest);
            Endpoint_ClearOUT();
            break;
        case TMC_MESSAGEID_DEV_DEP_MSG_IN:
            Endpoint_ClearOUT();

            MessageHeader.TransferSize = 3;
            WriteTMCHeader(&MessageHeader);

            Endpoint_Write_Stream_LE("TMC", 3, StreamCallback_AbortINOnRequest);
            Endpoint_ClearIN();
            break;
        default:
            Endpoint_StallTransaction();
            break;
        }

        LEDs_SetAllLEDs(LEDMASK_USB_READY);
    }

    /* All pending data has been processed - reset the data abort flags */
    IsTMCBulkINReset  = false;
    IsTMCBulkOUTReset = false;
}
示例#14
0
void USB_Device_ProcessControlRequest(void)
{
	uint8_t* RequestHeader  = (uint8_t*)&USB_ControlRequest;

	for (uint8_t RequestHeaderByte = 0; RequestHeaderByte < sizeof(USB_Request_Header_t); RequestHeaderByte++)
	  *(RequestHeader++) = Endpoint_Read_Byte();

	EVENT_USB_Device_ControlRequest();

	if (Endpoint_IsSETUPReceived())
	{
		uint8_t bmRequestType = USB_ControlRequest.bmRequestType;

		switch (USB_ControlRequest.bRequest)
		{
			case REQ_GetStatus:
				if ((bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) ||
					(bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_ENDPOINT)))
				{
					USB_Device_GetStatus();
				}

				break;
			case REQ_ClearFeature:
			case REQ_SetFeature:
				if ((bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE)) ||
					(bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_ENDPOINT)))
				{
					USB_Device_ClearSetFeature();
				}

				break;
			case REQ_SetAddress:
				if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE))
				  USB_Device_SetAddress();

				break;
			case REQ_GetDescriptor:
				if ((bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) ||
					(bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE)))
				{
					USB_Device_GetDescriptor();
				}

				break;
			case REQ_GetConfiguration:
				if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE))
				  USB_Device_GetConfiguration();

				break;
			case REQ_SetConfiguration:
				if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE))
				  USB_Device_SetConfiguration();

				break;
		}
	}

	if (Endpoint_IsSETUPReceived())
	{
		Endpoint_StallTransaction();
		Endpoint_ClearSETUP();
	}
}
示例#15
0
static bool
USB_BulkWorker()
{
    uint8_t cmdBuf[XUM_CMDBUF_SIZE], statusBuf[XUM_STATUSBUF_SIZE];
    int8_t status;

    /*
     * If we are not connected to the host or a command has not yet
     * been sent, no more processing is required.
     */
    if (USB_DeviceState != DEVICE_STATE_Configured)
        return false;
    Endpoint_SelectEndpoint(XUM_BULK_OUT_ENDPOINT);
    if (!Endpoint_IsReadWriteAllowed())
        return false;

#ifdef DEBUG
    // Dump the status of both endpoints before getting the command
    Endpoint_SelectEndpoint(XUM_BULK_IN_ENDPOINT);
    DEBUGF(DBG_INFO, "bsti %x %x %x %x %x %x %x %x\n",
        Endpoint_GetCurrentEndpoint(),
        Endpoint_BytesInEndpoint(), Endpoint_IsEnabled(),
        Endpoint_IsReadWriteAllowed(), Endpoint_IsConfigured(),
        Endpoint_IsINReady(), Endpoint_IsOUTReceived(), Endpoint_IsStalled());
    Endpoint_SelectEndpoint(XUM_BULK_OUT_ENDPOINT);
    DEBUGF(DBG_INFO, "bsto %x %x %x %x %x %x %x %x\n",
        Endpoint_GetCurrentEndpoint(),
        Endpoint_BytesInEndpoint(), Endpoint_IsEnabled(),
        Endpoint_IsReadWriteAllowed(), Endpoint_IsConfigured(),
        Endpoint_IsINReady(), Endpoint_IsOUTReceived(), Endpoint_IsStalled());
#endif

    // Read in the command from the host now that one is ready.
    if (!USB_ReadBlock(cmdBuf, sizeof(cmdBuf))) {
        board_set_status(STATUS_ERROR);
        return false;
    }

    // Allow commands to leave the extended status untouched
    memset(statusBuf, 0, sizeof(statusBuf));

    /*
     * Decode and process the command.
     * usbHandleBulk() stores its extended result in the output buffer,
     * up to XUM_STATUSBUF_SIZE.
     *
     * Return values:
     *   >0: completed ok, send the return value and extended status
     *    0: completed ok, don't send any status
     *   -1: error, no status
     */
    status = usbHandleBulk(cmdBuf, statusBuf);
    if (status > 0) {
        statusBuf[0] = status;
        USB_WriteBlock(statusBuf, sizeof(statusBuf));
    } else if (status < 0) {
        DEBUGF(DBG_ERROR, "usbblk err\n");
        board_set_status(STATUS_ERROR);
        Endpoint_StallTransaction();
        return false;
    }

    return true;
}
void USB_Device_ProcessControlRequest(void)
{
//	USB_ControlRequest.bmRequestType = Endpoint_Read_8();
//	USB_ControlRequest.bRequest      = Endpoint_Read_8();
//	USB_ControlRequest.wValue        = Endpoint_Read_16_LE();
//	USB_ControlRequest.wIndex        = Endpoint_Read_16_LE();
//	USB_ControlRequest.wLength       = Endpoint_Read_16_LE();

	Endpoint_GetSetupPackage( (uint8_t*) &USB_ControlRequest);

	EVENT_USB_Device_ControlRequest();

	if (Endpoint_IsSETUPReceived())
	{
		uint8_t bmRequestType = USB_ControlRequest.bmRequestType;

		switch (USB_ControlRequest.bRequest)
		{
			case REQ_GetStatus:
				if ((bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) ||
					(bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_ENDPOINT)))
				{
					USB_Device_GetStatus();
				}

				break;
			case REQ_ClearFeature:
			case REQ_SetFeature:
				if ((bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE)) ||
					(bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_ENDPOINT)))
				{
					USB_Device_ClearSetFeature();
				}

				break;
			case REQ_SetAddress:
				if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE))
				  USB_Device_SetAddress();

				break;
			case REQ_GetDescriptor:
				if ((bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) ||
					(bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE)))
				{
					USB_Device_GetDescriptor();
				}

				break;
			case REQ_GetConfiguration:
				if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE))
				  USB_Device_GetConfiguration();

				break;
			case REQ_SetConfiguration:
				if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE))
				  USB_Device_SetConfiguration();

				break;
		}
	}

	if (Endpoint_IsSETUPReceived())
	{
		Endpoint_ClearSETUP();
		Endpoint_StallTransaction();
	}
}
示例#17
0
文件: RNDIS.c 项目: geemoo/oopslogger
void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
{
	if (USB_DeviceState != DEVICE_STATE_Configured)
	  return;

	RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISInterfaceInfo->State.RNDISMessageBuffer;

	Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.NotificationEndpointNumber);

	if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.ResponseReady)
	{
		USB_Request_Header_t Notification = (USB_Request_Header_t)
			{
				.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
				.bRequest      = NOTIF_ResponseAvailable,
				.wValue        = 0,
				.wIndex        = 0,
				.wLength       = 0,
			};
		
		Endpoint_Write_Stream_LE(&Notification, sizeof(Notification), NO_STREAM_CALLBACK);

		Endpoint_ClearIN();

		RNDISInterfaceInfo->State.ResponseReady = false;
	}
	
	if ((RNDISInterfaceInfo->State.CurrRNDISState == RNDIS_Data_Initialized) && !(MessageHeader->MessageLength))
	{
		RNDIS_Packet_Message_t RNDISPacketHeader;

		Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpointNumber);

		if (Endpoint_IsOUTReceived() && !(RNDISInterfaceInfo->State.FrameIN.FrameInBuffer))
		{
			Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NO_STREAM_CALLBACK);

			if (RNDISPacketHeader.DataLength > ETHERNET_FRAME_SIZE_MAX)
			{
				Endpoint_StallTransaction();
				return;
			}
			
			Endpoint_Read_Stream_LE(RNDISInterfaceInfo->State.FrameIN.FrameData, RNDISPacketHeader.DataLength, NO_STREAM_CALLBACK);

			Endpoint_ClearOUT();
			
			RNDISInterfaceInfo->State.FrameIN.FrameLength = RNDISPacketHeader.DataLength;

			RNDISInterfaceInfo->State.FrameIN.FrameInBuffer = true;
		}
		
		Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataINEndpointNumber);
		
		if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.FrameOUT.FrameInBuffer)
		{
			memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t));

			RNDISPacketHeader.MessageType   = REMOTE_NDIS_PACKET_MSG;
			RNDISPacketHeader.MessageLength = (sizeof(RNDIS_Packet_Message_t) + RNDISInterfaceInfo->State.FrameOUT.FrameLength);
			RNDISPacketHeader.DataOffset    = (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
			RNDISPacketHeader.DataLength    = RNDISInterfaceInfo->State.FrameOUT.FrameLength;

			Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NO_STREAM_CALLBACK);
			Endpoint_Write_Stream_LE(RNDISInterfaceInfo->State.FrameOUT.FrameData, RNDISPacketHeader.DataLength, NO_STREAM_CALLBACK);
			Endpoint_ClearIN();
			
			RNDISInterfaceInfo->State.FrameOUT.FrameInBuffer = false;
		}
	}
}							
示例#18
0
/** Task to manage the sending and receiving of encapsulated RNDIS data and notifications. This removes the RNDIS
 *  wrapper from received Ethernet frames and places them in the FrameIN global buffer, or adds the RNDIS wrapper
 *  to a frame in the FrameOUT global before sending the buffer contents to the host.
 */
void RNDIS_Task(void)
{
	/* Select the notification endpoint */
	Endpoint_SelectEndpoint(CDC_NOTIFICATION_EPADDR);

	/* Check if a message response is ready for the host */
	if (Endpoint_IsINReady() && ResponseReady)
	{
		USB_Request_Header_t Notification = (USB_Request_Header_t)
			{
				.bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
				.bRequest      = RNDIS_NOTIF_ResponseAvailable,
				.wValue        = 0,
				.wIndex        = 0,
				.wLength       = 0,
			};

		/* Indicate that a message response is ready for the host */
		Endpoint_Write_Stream_LE(&Notification, sizeof(Notification), NULL);

		/* Finalize the stream transfer to send the last packet */
		Endpoint_ClearIN();

		/* Indicate a response is no longer ready */
		ResponseReady = false;
	}

	/* Don't process the data endpoints until the system is in the data initialized state, and the buffer is free */
	if ((CurrRNDISState == RNDIS_Data_Initialized) && !(MessageHeader->MessageLength))
	{
		/* Create a new packet header for reading/writing */
		RNDIS_Packet_Message_t RNDISPacketHeader;

		/* Select the data OUT endpoint */
		Endpoint_SelectEndpoint(CDC_RX_EPADDR);

		/* Check if the data OUT endpoint contains data, and that the IN buffer is empty */
		if (Endpoint_IsOUTReceived() && !(FrameIN.FrameLength))
		{
			/* Read in the packet message header */
			Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL);

			/* Stall the request if the data is too large */
			if (RNDISPacketHeader.DataLength > ETHERNET_FRAME_SIZE_MAX)
			{
				Endpoint_StallTransaction();
				return;
			}

			/* Read in the Ethernet frame into the buffer */
			Endpoint_Read_Stream_LE(FrameIN.FrameData, RNDISPacketHeader.DataLength, NULL);

			/* Finalize the stream transfer to send the last packet */
			Endpoint_ClearOUT();

			/* Store the size of the Ethernet frame */
			FrameIN.FrameLength = RNDISPacketHeader.DataLength;
		}

		/* Select the data IN endpoint */
		Endpoint_SelectEndpoint(CDC_TX_EPADDR);

		/* Check if the data IN endpoint is ready for more data, and that the IN buffer is full */
		if (Endpoint_IsINReady() && FrameOUT.FrameLength)
		{
			/* Clear the packet header with all 0s so that the relevant fields can be filled */
			memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t));

			/* Construct the required packet header fields in the buffer */
			RNDISPacketHeader.MessageType   = REMOTE_NDIS_PACKET_MSG;
			RNDISPacketHeader.MessageLength = (sizeof(RNDIS_Packet_Message_t) + FrameOUT.FrameLength);
			RNDISPacketHeader.DataOffset    = (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
			RNDISPacketHeader.DataLength    = FrameOUT.FrameLength;

			/* Send the packet header to the host */
			Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL);

			/* Send the Ethernet frame data to the host */
			Endpoint_Write_Stream_LE(FrameOUT.FrameData, RNDISPacketHeader.DataLength, NULL);

			/* Finalize the stream transfer to send the last packet */
			Endpoint_ClearIN();

			/* Indicate Ethernet OUT buffer no longer full */
			FrameOUT.FrameLength = 0;
		}
	}
}