239 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			239 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/**
 | 
						|
 * PROJECT:         ExectOS
 | 
						|
 * COPYRIGHT:       See COPYING.md in the top level directory
 | 
						|
 * FILE:            xtldr/modules/beep/beep.cc
 | 
						|
 * DESCRIPTION:     XTLDR Beep Module
 | 
						|
 * DEVELOPERS:      Rafal Kupiec <belliash@codingworkshop.eu.org>
 | 
						|
 */
 | 
						|
 | 
						|
#include <beep.hh>
 | 
						|
 | 
						|
 | 
						|
/* Beep module information */
 | 
						|
MODULE_AUTHOR(L"Rafal Kupiec <belliash@codingworkshop.eu.org>");
 | 
						|
MODULE_DESCRIPTION(L"Plays a GRUB compatible tune via PC speaker");
 | 
						|
MODULE_LICENSE(L"GPLv3");
 | 
						|
MODULE_VERSION(L"0.1");
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Disables the PC speaker.
 | 
						|
 *
 | 
						|
 * @return This routine does not return any value.
 | 
						|
 *
 | 
						|
 * @since XT 1.0
 | 
						|
 */
 | 
						|
XTCDECL
 | 
						|
VOID
 | 
						|
Beep::DisableToneBeep()
 | 
						|
{
 | 
						|
    UCHAR Status;
 | 
						|
 | 
						|
    /* Stop the PC speaker */
 | 
						|
    Status = XtLdrProtocol->IoPort.Read8(0x61);
 | 
						|
    XtLdrProtocol->IoPort.Write8(0x61, Status & 0xFC);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Enables the PC speaker and plays a sound.
 | 
						|
 *
 | 
						|
 * @param Pitch
 | 
						|
 *        Specifies a pitch (in Hz) of the sound.
 | 
						|
 *
 | 
						|
 * @return This routine does not return any value.
 | 
						|
 *
 | 
						|
 * @since XT 1.0
 | 
						|
 */
 | 
						|
XTCDECL
 | 
						|
VOID
 | 
						|
Beep::EnableToneBeep(IN UINT Pitch)
 | 
						|
{
 | 
						|
    UINT Counter;
 | 
						|
    UCHAR Status;
 | 
						|
 | 
						|
    /* Pitch only in range of 20..20000 */
 | 
						|
    if(Pitch < 20)
 | 
						|
    {
 | 
						|
        Pitch = 20;
 | 
						|
    }
 | 
						|
    else if(Pitch > 20000)
 | 
						|
    {
 | 
						|
        Pitch = 20000;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Set the desired frequency of the PIT clock */
 | 
						|
    Counter = 0x1234DD / Pitch;
 | 
						|
    XtLdrProtocol->IoPort.Write8(0x43, 0xB6);
 | 
						|
    XtLdrProtocol->IoPort.Write8(0x43, 0xB6);
 | 
						|
    XtLdrProtocol->IoPort.Write8(0x42, (UCHAR) Counter & 0xFF);
 | 
						|
    XtLdrProtocol->IoPort.Write8(0x42, (UCHAR) (Counter >> 8) & 0xFF);
 | 
						|
 | 
						|
    /* Start the PC speaker */
 | 
						|
    Status = XtLdrProtocol->IoPort.Read8(0x61);
 | 
						|
    XtLdrProtocol->IoPort.Write8(0x61, Status | 0x03);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Initializes BEEP module by opening XTLDR protocol and playing the tune.
 | 
						|
 *
 | 
						|
 * @param ImageHandle
 | 
						|
 *        Firmware-allocated handle that identifies the image.
 | 
						|
 *
 | 
						|
 * @param SystemTable
 | 
						|
 *        Provides the EFI system table.
 | 
						|
 *
 | 
						|
 * @return This routine returns status code.
 | 
						|
 *
 | 
						|
 * @since XT 1.0
 | 
						|
 */
 | 
						|
XTCDECL
 | 
						|
EFI_STATUS
 | 
						|
Beep::InitializeModule(IN EFI_HANDLE ImageHandle,
 | 
						|
                       IN PEFI_SYSTEM_TABLE SystemTable)
 | 
						|
{
 | 
						|
    EFI_STATUS Status;
 | 
						|
    PWCHAR Tune;
 | 
						|
 | 
						|
    /* Open the XTLDR protocol */
 | 
						|
    Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol);
 | 
						|
    if(Status != STATUS_EFI_SUCCESS)
 | 
						|
    {
 | 
						|
        /* Failed to open the protocol, return error */
 | 
						|
        return STATUS_EFI_PROTOCOL_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Play the tune set in the configuration */
 | 
						|
    XtLdrProtocol->Config.GetValue(L"TUNE", &Tune);
 | 
						|
    PlayTune(Tune);
 | 
						|
 | 
						|
    /* Return success */
 | 
						|
    return STATUS_EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * This routine plays a tune.
 | 
						|
 *
 | 
						|
 * @param Arguments
 | 
						|
 *        Optional list of parameters provided with the command.
 | 
						|
 *
 | 
						|
 * @return This routine does not return any value.
 | 
						|
 *
 | 
						|
 * @since XT 1.0
 | 
						|
 */
 | 
						|
XTCDECL
 | 
						|
VOID
 | 
						|
Beep::PlayTune(IN PWCHAR Arguments)
 | 
						|
{
 | 
						|
    LONG Pitch, Duration, Tempo;
 | 
						|
    PWCHAR Argument, LastArgument;
 | 
						|
 | 
						|
    /* Reset pitch and duration */
 | 
						|
    Duration = -1;
 | 
						|
    Pitch = -1;
 | 
						|
    Tempo = -1;
 | 
						|
 | 
						|
    /* Tokenize provided list of arguments */
 | 
						|
    Argument = XtLdrProtocol->WideString.Tokenize(Arguments, L" ", &LastArgument);
 | 
						|
 | 
						|
    /* Iterate over all arguments */
 | 
						|
    while(Argument != NULLPTR)
 | 
						|
    {
 | 
						|
        /* Check if tempo, pitch and duration are set */
 | 
						|
        if(Tempo < 0)
 | 
						|
        {
 | 
						|
            /* Set the tempo */
 | 
						|
            Tempo = WideStringToNumber(Argument);
 | 
						|
        }
 | 
						|
        else if(Pitch < 0)
 | 
						|
        {
 | 
						|
            /* Set the pitch */
 | 
						|
            Pitch = WideStringToNumber(Argument);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            /* Set the duration */
 | 
						|
            Duration = WideStringToNumber(Argument);
 | 
						|
 | 
						|
            /* Check pitch value */
 | 
						|
            if(Pitch > 0)
 | 
						|
            {
 | 
						|
                /* Emit the beep tone */
 | 
						|
                EnableToneBeep(Pitch);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                /* Stop emitting beep tone */
 | 
						|
                DisableToneBeep();
 | 
						|
            }
 | 
						|
 | 
						|
            /* Wait for duration time */
 | 
						|
            XtLdrProtocol->Utils.SleepExecution(60000 * Duration / Tempo);
 | 
						|
 | 
						|
            /* Reset pitch and duration */
 | 
						|
            Pitch = -1;
 | 
						|
            Duration = -1;
 | 
						|
        }
 | 
						|
 | 
						|
        /* Get next argument */
 | 
						|
        Argument = XtLdrProtocol->WideString.Tokenize(NULLPTR, L" ", &LastArgument);
 | 
						|
    }
 | 
						|
 | 
						|
    /* Stop emitting beep tone */
 | 
						|
    DisableToneBeep();
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Converts a wide string into a number.
 | 
						|
 *
 | 
						|
 * @param String
 | 
						|
 *        Supplies an input wide string.
 | 
						|
 *
 | 
						|
 * @return This routine returns the number that was converted from the wide string.
 | 
						|
 *
 | 
						|
 * @since XT 1.0
 | 
						|
 */
 | 
						|
XTCDECL
 | 
						|
UINT
 | 
						|
Beep::WideStringToNumber(IN PWCHAR String)
 | 
						|
{
 | 
						|
    ULONG Number = 0;
 | 
						|
 | 
						|
    /* Iterate over all characters until '\0' found */
 | 
						|
    do
 | 
						|
    {
 | 
						|
        /* Check if this is a digit */
 | 
						|
        if(*String - '0' < 10)
 | 
						|
        {
 | 
						|
            /* Add another digit to the number */
 | 
						|
            Number *= 10;
 | 
						|
            Number += *String - '0';
 | 
						|
        }
 | 
						|
    }
 | 
						|
    while(*++String != L'\0');
 | 
						|
 | 
						|
    /* Return number */
 | 
						|
    return Number;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * This routine is the entry point of the XT EFI boot loader module.
 | 
						|
 *
 | 
						|
 * @param ImageHandle
 | 
						|
 *        Firmware-allocated handle that identifies the image.
 | 
						|
 *
 | 
						|
 * @param SystemTable
 | 
						|
 *        Provides the EFI system table.
 | 
						|
 *
 | 
						|
 * @return This routine returns status code.
 | 
						|
 *
 | 
						|
 * @since XT 1.0
 | 
						|
 */
 | 
						|
XTCDECL
 | 
						|
EFI_STATUS
 | 
						|
XtLdrModuleMain(IN EFI_HANDLE ImageHandle,
 | 
						|
                IN PEFI_SYSTEM_TABLE SystemTable)
 | 
						|
{
 | 
						|
    /* Initialize BEEP module */
 | 
						|
    return Beep::InitializeModule(ImageHandle, SystemTable);
 | 
						|
}
 |