Changeset 59497 in vbox
- Timestamp:
- Jan 27, 2016 4:31:41 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/DevPit-i8254.cpp
r57358 r59497 53 53 54 54 #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 55 64 # include <iprt/alloc.h> 56 65 # include <iprt/string.h> … … 204 213 typedef PITCHANNEL *PPITCHANNEL; 205 214 215 /** Speaker emulation state. */ 216 typedef 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 206 224 /** 207 225 * The whole PIT state. … … 214 232 int32_t speaker_data_on; 215 233 #ifdef FAKE_REFRESH_CLOCK 216 /** Speakerdummy. */234 /** Refresh dummy. */ 217 235 int32_t dummy_refresh_clock; 218 236 #else … … 223 241 /** Config: Speaker enabled. */ 224 242 bool fSpeakerCfg; 243 /** Config: What to do with speaker activity. */ 244 PITSPEAKEREMU enmSpeakerEmu; 245 /** Disconnect PIT from the interrupt controllers if requested by HPET. */ 225 246 bool fDisabledByHpet; 226 247 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 227 255 /** PIT port interface. */ 228 256 PDMIHPETLEGACYNOTIFY IHpetLegacyNotify; … … 842 870 pit_set_gate(pThis, 2, u32 & 1); 843 871 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 844 937 DEVPIT_UNLOCK_BOTH(pThis); 845 938 } … … 1166 1259 * Validate configuration. 1167 1260 */ 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")) 1169 1262 return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES; 1170 1263 … … 1187 1280 N_("Configuration error: Querying \"SpeakerEnabled\" as a bool failed")); 1188 1281 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 1189 1288 rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &fGCEnabled, true); 1190 1289 if (RT_FAILURE(rc)) … … 1200 1299 pThis->IOPortBaseCfg = u16Base; 1201 1300 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; 1202 1347 pThis->channels[0].irq = u8Irq; 1203 1348 for (i = 0; i < RT_ELEMENTS(pThis->channels); i++)
Note:
See TracChangeset
for help on using the changeset viewer.