VirtualBox

Changeset 59497 in vbox


Ignore:
Timestamp:
Jan 27, 2016 4:31:41 PM (9 years ago)
Author:
vboxsync
Message:

Devices/PC/DevPit-i8254.cpp: Add code (currently linux host only) for passing through PC speaker beeps from the guest to the host, again with the intention to use PC speaker. No sound card conversion so far. Documentation needs to be written.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/PC/DevPit-i8254.cpp

    r57358 r59497  
    5353
    5454#ifdef IN_RING3
     55# ifdef RT_OS_LINUX
     56#  include <fcntl.h>
     57#  include <errno.h>
     58#  include <unistd.h>
     59#  include <stdio.h>
     60#  include <linux/kd.h>
     61#  include <linux/input.h>
     62#  include <sys/ioctl.h>
     63# endif
    5564# include <iprt/alloc.h>
    5665# include <iprt/string.h>
     
    204213typedef PITCHANNEL *PPITCHANNEL;
    205214
     215/** Speaker emulation state. */
     216typedef enum PITSPEAKEREMU
     217{
     218    PIT_SPEAKER_EMU_NONE = 0,
     219    PIT_SPEAKER_EMU_CONSOLE,
     220    PIT_SPEAKER_EMU_EVDEV,
     221    PIT_SPEAKER_EMU_TTY
     222} PITSPEAKEREMU;
     223
    206224/**
    207225 * The whole PIT state.
     
    214232    int32_t                 speaker_data_on;
    215233#ifdef FAKE_REFRESH_CLOCK
    216     /** Speaker dummy. */
     234    /** Refresh dummy. */
    217235    int32_t                 dummy_refresh_clock;
    218236#else
     
    223241    /** Config: Speaker enabled. */
    224242    bool                    fSpeakerCfg;
     243    /** Config: What to do with speaker activity. */
     244    PITSPEAKEREMU           enmSpeakerEmu;
     245    /** Disconnect PIT from the interrupt controllers if requested by HPET. */
    225246    bool                    fDisabledByHpet;
    226247    bool                    afAlignment0[HC_ARCH_BITS == 32 ? 4 : 4];
     248#ifdef RT_OS_LINUX
     249    /** File handle for host speaker functionality. */
     250    int                     hHostSpeaker;
     251# if HC_ARCH_BITS == 64
     252    int                     afAlignment2;
     253# endif
     254#endif
    227255    /** PIT port interface. */
    228256    PDMIHPETLEGACYNOTIFY    IHpetLegacyNotify;
     
    842870        pit_set_gate(pThis, 2, u32 & 1);
    843871
     872        /** @todo r=klaus move this to a (system-specific) driver, which can
     873         * abstract the details, and if necessary create a thread to minimize
     874         * impact on VM execution. */
     875#ifdef RT_OS_LINUX
     876        if (pThis->enmSpeakerEmu != PIT_SPEAKER_EMU_NONE)
     877        {
     878            PPITCHANNEL pChan = &pThis->channels[2];
     879            if (pThis->speaker_data_on)
     880            {
     881                Log2Func(("starting beep freq=%d\n", PIT_FREQ / pChan->count));
     882                switch (pThis->enmSpeakerEmu)
     883                {
     884                    case PIT_SPEAKER_EMU_CONSOLE:
     885                        int res;
     886                        res = ioctl(pThis->hHostSpeaker, KIOCSOUND, pChan->count);
     887                        if (res == -1)
     888                        {
     889                            LogRel(("PIT: speaker: ioctl failed errno=%d\n", errno));
     890                            pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_NONE;
     891                        }
     892                        break;
     893                    case PIT_SPEAKER_EMU_EVDEV:
     894                        struct input_event e;
     895                        e.type = EV_SND;
     896                        e.code = SND_TONE;
     897                        e.value = PIT_FREQ / pChan->count;
     898                        write(pThis->hHostSpeaker, &e, sizeof(struct input_event));
     899                        break;
     900                    case PIT_SPEAKER_EMU_TTY:
     901                        write(pThis->hHostSpeaker, "\a", 1);
     902                        break;
     903                    case PIT_SPEAKER_EMU_NONE:
     904                        break;
     905                    default:
     906                        Log2Func(("unknown speaker emulation %d\n", pThis->enmSpeakerEmu));
     907                        pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_NONE;
     908                }
     909            }
     910            else
     911            {
     912                Log2Func(("stopping beep\n"));
     913                switch (pThis->enmSpeakerEmu)
     914                {
     915                    case PIT_SPEAKER_EMU_CONSOLE:
     916                        ioctl(pThis->hHostSpeaker, KIOCSOUND, 0);
     917                        break;
     918                    case PIT_SPEAKER_EMU_EVDEV:
     919                        struct input_event e;
     920                        e.type = EV_SND;
     921                        e.code = SND_TONE;
     922                        e.value = 0;
     923                        write(pThis->hHostSpeaker, &e, sizeof(struct input_event));
     924                        break;
     925                    case PIT_SPEAKER_EMU_TTY:
     926                        break;
     927                    case PIT_SPEAKER_EMU_NONE:
     928                        break;
     929                    default:
     930                        Log2Func(("unknown speaker emulation %d\n", pThis->enmSpeakerEmu));
     931                        pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_NONE;
     932                }
     933            }
     934        }
     935#endif
     936
    844937        DEVPIT_UNLOCK_BOTH(pThis);
    845938    }
     
    11661259     * Validate configuration.
    11671260     */
    1168     if (!CFGMR3AreValuesValid(pCfg, "Irq\0" "Base\0" "SpeakerEnabled\0" "GCEnabled\0" "R0Enabled\0"))
     1261    if (!CFGMR3AreValuesValid(pCfg, "Irq\0" "Base\0" "SpeakerEnabled\0" "PassthroughSpeaker\0" "R0Enabled\0"))
    11691262        return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
    11701263
     
    11871280                                N_("Configuration error: Querying \"SpeakerEnabled\" as a bool failed"));
    11881281
     1282    bool fPassthroughSpeaker;
     1283    rc = CFGMR3QueryBoolDef(pCfg, "PassthroughSpeaker", &fPassthroughSpeaker, false);
     1284    if (RT_FAILURE(rc))
     1285        return PDMDEV_SET_ERROR(pDevIns, rc,
     1286                                N_("Configuration error: failed to read PassthroughSpeaker as boolean"));
     1287
    11891288    rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &fGCEnabled, true);
    11901289    if (RT_FAILURE(rc))
     
    12001299    pThis->IOPortBaseCfg   = u16Base;
    12011300    pThis->fSpeakerCfg     = fSpeaker;
     1301    if (fPassthroughSpeaker)
     1302    {
     1303        /** @todo r=klaus move this to a (system-specific) driver */
     1304#ifdef RT_OS_LINUX
     1305        int fd;
     1306        fd = open("/dev/input/by-path/platform-pcspkr-event-spkr", O_WRONLY);
     1307        if (fd == -1)
     1308            fd = open("/dev/tty0", O_WRONLY);
     1309        if (fd == -1)
     1310            fd = open("/dev/vc/0", O_WRONLY);
     1311        if (fd == -1)
     1312        {
     1313            LogRel(("PIT: speaker: could not open console/speaker device\n"));
     1314            fd = open("/dev/tty", O_WRONLY);
     1315            if (fd == -1)
     1316            {
     1317                pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_NONE;
     1318                LogRel(("PIT: speaker: no emulation possible\n"));
     1319            }
     1320            else
     1321            {
     1322                pThis->hHostSpeaker = fd;
     1323                pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_TTY;
     1324                LogRel(("PIT: speaker: emulation mode tty\n"));
     1325            }
     1326        }
     1327        else
     1328        {
     1329            pThis->hHostSpeaker = fd;
     1330            if (ioctl(fd, EVIOCGSND(0)) != -1)
     1331            {
     1332                pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_EVDEV;
     1333                LogRel(("PIT: speaker: emulation mode evdev\n"));
     1334            }
     1335            else
     1336            {
     1337                pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_CONSOLE;
     1338                LogRel(("PIT: speaker: emulation mode console\n"));
     1339            }
     1340        }
     1341#else
     1342        pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_NONE;
     1343#endif
     1344    }
     1345    else
     1346        pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_NONE;
    12021347    pThis->channels[0].irq = u8Irq;
    12031348    for (i = 0; i < RT_ELEMENTS(pThis->channels); i++)
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette