\r
EFI_GUID mFormSetGuid = FORMSET_GUID;\r
EFI_GUID mInventoryGuid = INVENTORY_GUID;\r
+EFI_GUID MyEventGroupGuid = EFI_IFR_REFRESH_ID_OP_GUID;\r
\r
CHAR16 VariableName[] = L"MyIfrNVData";\r
EFI_HANDLE DriverHandle[2] = {NULL, NULL};\r
DRIVER_SAMPLE_PRIVATE_DATA *PrivateData = NULL;\r
+EFI_EVENT mEvent;\r
\r
HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath0 = {\r
{\r
}\r
};\r
\r
+/**\r
+ Add empty function for event process function.\r
+\r
+ @param Event The Event need to be process\r
+ @param Context The context of the event.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DriverSampleInternalEmptyFunction (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+}\r
+\r
+/**\r
+ Notification function for keystrokes.\r
+\r
+ @param[in] KeyData The key that was pressed.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NotificationFunction(\r
+ IN EFI_KEY_DATA *KeyData\r
+ )\r
+{\r
+ gBS->SignalEvent (mEvent);\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Function to start monitoring for CTRL-C using SimpleTextInputEx. \r
+\r
+ @retval EFI_SUCCESS The feature is enabled.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough mnemory available.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InternalStartMonitor(\r
+ VOID\r
+ )\r
+{\r
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;\r
+ EFI_KEY_DATA KeyData;\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE *Handles;\r
+ UINTN HandleCount;\r
+ UINTN HandleIndex;\r
+ EFI_HANDLE NotifyHandle;\r
+\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &Handles\r
+ );\r
+ for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {\r
+ Status = gBS->HandleProtocol (Handles[HandleIndex], &gEfiSimpleTextInputExProtocolGuid, (VOID **) &SimpleEx);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ KeyData.KeyState.KeyToggleState = 0;\r
+ KeyData.Key.ScanCode = 0;\r
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;\r
+ KeyData.Key.UnicodeChar = L'c';\r
+\r
+ Status = SimpleEx->RegisterKeyNotify(\r
+ SimpleEx,\r
+ &KeyData,\r
+ NotificationFunction,\r
+ &NotifyHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ \r
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;\r
+ Status = SimpleEx->RegisterKeyNotify(\r
+ SimpleEx,\r
+ &KeyData,\r
+ NotificationFunction,\r
+ &NotifyHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Function to stop monitoring for CTRL-C using SimpleTextInputEx. \r
+\r
+ @retval EFI_SUCCESS The feature is enabled.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough mnemory available.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InternalStopMonitor(\r
+ VOID\r
+ )\r
+{\r
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE *Handles;\r
+ EFI_KEY_DATA KeyData; \r
+ UINTN HandleCount;\r
+ UINTN HandleIndex;\r
+ EFI_HANDLE NotifyHandle;\r
+\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &Handles\r
+ );\r
+ for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {\r
+ Status = gBS->HandleProtocol (Handles[HandleIndex], &gEfiSimpleTextInputExProtocolGuid, (VOID **) &SimpleEx);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ KeyData.KeyState.KeyToggleState = 0;\r
+ KeyData.Key.ScanCode = 0;\r
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;\r
+ KeyData.Key.UnicodeChar = L'c';\r
+\r
+ Status = SimpleEx->RegisterKeyNotify(\r
+ SimpleEx,\r
+ &KeyData,\r
+ NotificationFunction,\r
+ &NotifyHandle);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = SimpleEx->UnregisterKeyNotify (SimpleEx, NotifyHandle);\r
+ }\r
+\r
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;\r
+ Status = SimpleEx->RegisterKeyNotify(\r
+ SimpleEx,\r
+ &KeyData,\r
+ NotificationFunction,\r
+ &NotifyHandle);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = SimpleEx->UnregisterKeyNotify (SimpleEx, NotifyHandle);\r
+ }\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
/**\r
Encode the password using a simple algorithm.\r
\r
EFI_INPUT_KEY Key;\r
DRIVER_SAMPLE_CONFIGURATION *Configuration;\r
UINTN MyVarSize;\r
+ EFI_FORM_ID FormId;\r
\r
if (((Value == NULL) && (Action != EFI_BROWSER_ACTION_FORM_OPEN) && (Action != EFI_BROWSER_ACTION_FORM_CLOSE))||\r
(ActionRequest == NULL)) {\r
}\r
\r
\r
+ FormId = 0;\r
Status = EFI_SUCCESS;\r
PrivateData = DRIVER_SAMPLE_PRIVATE_FROM_THIS (This);\r
\r
\r
HiiFreeOpCodeHandle (StartOpCodeHandle);\r
}\r
+\r
+ if (QuestionId == 0x1247) {\r
+ Status = InternalStartMonitor ();\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
}\r
break;\r
\r
);\r
} while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
}\r
+\r
+ if (QuestionId == 0x1247) {\r
+ Status = InternalStopMonitor ();\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
}\r
break;\r
\r
break;\r
\r
case 0x5678:\r
+ case 0x1247:\r
//\r
// We will reach here once the Question is refreshed\r
//\r
//\r
StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
- StartLabel->Number = LABEL_UPDATE2;\r
+ if (QuestionId == 0x5678) {\r
+ StartLabel->Number = LABEL_UPDATE2;\r
+ FormId = 0x03;\r
+ PrivateData->Configuration.DynamicRefresh++;\r
+ } else if (QuestionId == 0x1247 ) {\r
+ StartLabel->Number = LABEL_UPDATE3;\r
+ FormId = 0x05;\r
+ PrivateData->Configuration.RefreshGuidCount++;\r
+ }\r
\r
HiiCreateActionOpCode (\r
StartOpCodeHandle, // Container for dynamic created opcodes\r
HiiUpdateForm (\r
PrivateData->HiiHandle[0], // HII handle\r
&mFormSetGuid, // Formset GUID\r
- 0x3, // Form ID\r
+ FormId, // Form ID\r
StartOpCodeHandle, // Label for where to insert opcodes\r
NULL // Insert data\r
);\r
//\r
// Refresh the Question value\r
//\r
- PrivateData->Configuration.DynamicRefresh++;\r
Status = gRT->SetVariable(\r
VariableName,\r
&mFormSetGuid,\r
&PrivateData->Configuration\r
);\r
\r
- //\r
- // Change an EFI Variable storage (MyEfiVar) asynchronous, this will cause\r
- // the first statement in Form 3 be suppressed\r
- //\r
- MyVarSize = 1;\r
- MyVar = 111;\r
- Status = gRT->SetVariable(\r
- L"MyVar",\r
- &mFormSetGuid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
- MyVarSize,\r
- &MyVar\r
- );\r
+ if (QuestionId == 0x5678) {\r
+ //\r
+ // Change an EFI Variable storage (MyEfiVar) asynchronous, this will cause\r
+ // the first statement in Form 3 be suppressed\r
+ //\r
+ MyVarSize = 1;\r
+ MyVar = 111;\r
+ Status = gRT->SetVariable(\r
+ L"MyVar",\r
+ &mFormSetGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+ MyVarSize,\r
+ &MyVar\r
+ );\r
+ }\r
break;\r
\r
case 0x1237:\r
\r
FreePool (ConfigRequestHdr);\r
\r
-\r
+ Status = gBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL, \r
+ TPL_NOTIFY,\r
+ DriverSampleInternalEmptyFunction,\r
+ NULL,\r
+ &MyEventGroupGuid,\r
+ &mEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
//\r
// In default, this driver is built into Flash device image,\r
// the following code doesn't run.\r
FreePool (PrivateData);\r
PrivateData = NULL;\r
\r
+ gBS->CloseEvent (mEvent);\r
+\r
return EFI_SUCCESS;\r
}\r
gEfiHiiConfigAccessProtocolGuid ## PRODUCES\r
gEfiFormBrowser2ProtocolGuid ## CONSUMES\r
gEfiHiiDatabaseProtocolGuid ## CONSUMES\r
+ gEfiSimpleTextInputExProtocolGuid ## CONSUMES\r
\r
\r
[Depex]\r
#define EFI_USER_INFO_ACCESS_SETUP_ADMIN_GUID \\r
{ 0x85b75607, 0xf7ce, 0x471e, { 0xb7, 0xe4, 0x2a, 0xea, 0x5f, 0x72, 0x32, 0xee } }\r
\r
+#define EFI_IFR_REFRESH_ID_OP_GUID \\r
+ { \\r
+ 0xF5E655D9, 0x02A6, 0x46f2, {0x9E, 0x76, 0xB8, 0xBE, 0x8E, 0x60, 0xAB, 0x22} \\r
+ }\r
+\r
#define CONFIGURATION_VARSTORE_ID 0x1234\r
\r
#pragma pack(1)\r
UINT8 GetDefaultValueFromCallBack;\r
UINT8 GetDefaultValueFromAccess;\r
EFI_HII_TIME Time;\r
+ UINT8 RefreshGuidCount;\r
} DRIVER_SAMPLE_CONFIGURATION;\r
\r
//\r
//\r
#define LABEL_UPDATE1 0x1234\r
#define LABEL_UPDATE2 0x2234\r
+#define LABEL_UPDATE3 0x3234\r
#define LABEL_END 0x2223\r
\r
#pragma pack()\r
CurrentStatement->RefreshInterval = ((EFI_IFR_REFRESH *) OpCodeData)->RefreshInterval;\r
break;\r
\r
+ //\r
+ // Refresh guid.\r
+ //\r
+ case EFI_IFR_REFRESH_ID_OP:\r
+ ASSERT (CurrentStatement != NULL);\r
+ CopyMem (&CurrentStatement->RefreshGuid, &((EFI_IFR_REFRESH_ID *) OpCodeData)->RefreshEventGroupId, sizeof (EFI_GUID));\r
+ break;\r
+\r
//\r
// Modal tag\r
//\r
EFI_QUESTION_ID RefQuestionId; // for EFI_IFR_REF2\r
EFI_GUID RefFormSetId; // for EFI_IFR_REF3\r
EFI_STRING_ID RefDevicePath; // for EFI_IFR_REF4\r
+ EFI_GUID RefreshGuid; // for EFI_IFR_REFRESH_ID\r
\r
//\r
// Get from IFR parsing\r
\r
LIST_ENTRY gMenuOption;\r
LIST_ENTRY gMenuList = INITIALIZE_LIST_HEAD_VARIABLE (gMenuList);\r
-MENU_REFRESH_ENTRY *gMenuRefreshHead;\r
+MENU_REFRESH_ENTRY *gMenuRefreshHead; // Menu list used for refresh timer opcode.\r
+MENU_REFRESH_ENTRY *gMenuEventGuidRefreshHead; // Menu list used for refresh event guid opcode.\r
\r
//\r
// Search table for UiDisplayMenu()\r
gMenuRefreshHead = OldMenuRefreshEntry;\r
}\r
\r
- gMenuRefreshHead = NULL;\r
+ while (gMenuEventGuidRefreshHead != NULL) {\r
+ OldMenuRefreshEntry = gMenuEventGuidRefreshHead->Next;\r
+ if (gMenuEventGuidRefreshHead != NULL) {\r
+ gBS->CloseEvent(gMenuEventGuidRefreshHead->Event);\r
+ }\r
+ FreePool (gMenuEventGuidRefreshHead);\r
+ gMenuEventGuidRefreshHead = OldMenuRefreshEntry;\r
+ }\r
}\r
\r
\r
\r
/**\r
- Refresh screen.\r
+ Refresh question.\r
\r
+ @param MenuRefreshEntry Menu refresh structure which has info about the refresh question.\r
**/\r
-EFI_STATUS\r
-RefreshForm (\r
- VOID\r
+EFI_STATUS \r
+RefreshQuestion (\r
+ IN MENU_REFRESH_ENTRY *MenuRefreshEntry\r
)\r
{\r
CHAR16 *OptionString;\r
- MENU_REFRESH_ENTRY *MenuRefreshEntry;\r
UINTN Index;\r
EFI_STATUS Status;\r
UI_MENU_SELECTION *Selection;\r
FORM_BROWSER_STATEMENT *Question;\r
\r
- if (gMenuRefreshHead != NULL) {\r
+ Selection = MenuRefreshEntry->Selection;\r
+ Question = MenuRefreshEntry->MenuOption->ThisTag;\r
\r
- MenuRefreshEntry = gMenuRefreshHead;\r
+ Status = GetQuestionValue (Selection->FormSet, Selection->Form, Question, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ OptionString = NULL;\r
+ ProcessOptions (Selection, MenuRefreshEntry->MenuOption, FALSE, &OptionString);\r
\r
+ if (OptionString != NULL) {\r
//\r
- // Reset FormPackage update flag\r
+ // If leading spaces on OptionString - remove the spaces\r
//\r
- mHiiPackageListUpdated = FALSE;\r
+ for (Index = 0; OptionString[Index] == L' '; Index++)\r
+ ;\r
\r
- do {\r
- Selection = MenuRefreshEntry->Selection;\r
- Question = MenuRefreshEntry->MenuOption->ThisTag;\r
+ //\r
+ // If old Text is longer than new string, need to clean the old string before paint the newer.\r
+ // This option is no need for time/date opcode, because time/data opcode has fixed string length.\r
+ //\r
+ if ((MenuRefreshEntry->MenuOption->ThisTag->Operand != EFI_IFR_DATE_OP) &&\r
+ (MenuRefreshEntry->MenuOption->ThisTag->Operand != EFI_IFR_TIME_OP)) {\r
+ ClearLines (\r
+ MenuRefreshEntry->CurrentColumn, \r
+ MenuRefreshEntry->CurrentColumn + gOptionBlockWidth - 1,\r
+ MenuRefreshEntry->CurrentRow,\r
+ MenuRefreshEntry->CurrentRow,\r
+ PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND\r
+ );\r
+ }\r
\r
- Status = GetQuestionValue (Selection->FormSet, Selection->Form, Question, FALSE);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ gST->ConOut->SetAttribute (gST->ConOut, MenuRefreshEntry->CurrentAttribute);\r
+ PrintStringAt (MenuRefreshEntry->CurrentColumn, MenuRefreshEntry->CurrentRow, &OptionString[Index]);\r
+ FreePool (OptionString);\r
+ }\r
\r
- OptionString = NULL;\r
- ProcessOptions (Selection, MenuRefreshEntry->MenuOption, FALSE, &OptionString);\r
+ //\r
+ // Question value may be changed, need invoke its Callback()\r
+ //\r
+ Status = ProcessCallBackFunction (Selection, Question, EFI_BROWSER_ACTION_CHANGING, FALSE);\r
\r
- if (OptionString != NULL) {\r
- //\r
- // If leading spaces on OptionString - remove the spaces\r
- //\r
- for (Index = 0; OptionString[Index] == L' '; Index++)\r
- ;\r
+ return Status;\r
+}\r
\r
- //\r
- // If old Text is longer than new string, need to clean the old string before paint the newer.\r
- // This option is no need for time/date opcode, because time/data opcode has fixed string length.\r
- //\r
- if ((MenuRefreshEntry->MenuOption->ThisTag->Operand != EFI_IFR_DATE_OP) &&\r
- (MenuRefreshEntry->MenuOption->ThisTag->Operand != EFI_IFR_TIME_OP)) {\r
- ClearLines (\r
- MenuRefreshEntry->CurrentColumn, \r
- MenuRefreshEntry->CurrentColumn + gOptionBlockWidth - 1,\r
- MenuRefreshEntry->CurrentRow,\r
- MenuRefreshEntry->CurrentRow,\r
- PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND\r
- );\r
- }\r
+/**\r
+ Refresh the question which has refresh guid event attribute.\r
+ \r
+ @param Event The event which has this function related. \r
+ @param Context The input context info related to this event or the status code return to the caller.\r
+**/\r
+VOID\r
+RefreshQuestionNotify(\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ MENU_REFRESH_ENTRY *MenuRefreshEntry;\r
+ UI_MENU_SELECTION *Selection;\r
\r
- gST->ConOut->SetAttribute (gST->ConOut, MenuRefreshEntry->CurrentAttribute);\r
- PrintStringAt (MenuRefreshEntry->CurrentColumn, MenuRefreshEntry->CurrentRow, &OptionString[Index]);\r
- FreePool (OptionString);\r
- }\r
+ //\r
+ // Reset FormPackage update flag\r
+ //\r
+ mHiiPackageListUpdated = FALSE;\r
\r
- //\r
- // Question value may be changed, need invoke its Callback()\r
- //\r
- Status = ProcessCallBackFunction(Selection, Question, EFI_BROWSER_ACTION_CHANGING, FALSE);\r
+ MenuRefreshEntry = (MENU_REFRESH_ENTRY *)Context;\r
+ ASSERT (MenuRefreshEntry != NULL);\r
+ Selection = MenuRefreshEntry->Selection;\r
+\r
+ RefreshQuestion (MenuRefreshEntry);\r
+ \r
+ if (mHiiPackageListUpdated) {\r
+ //\r
+ // Package list is updated, force to reparse IFR binary of target Formset\r
+ //\r
+ mHiiPackageListUpdated = FALSE;\r
+ Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+ } \r
+}\r
+\r
+\r
+/**\r
+ Refresh screen.\r
+\r
+**/\r
+EFI_STATUS\r
+RefreshForm (\r
+ VOID\r
+ )\r
+{\r
+ MENU_REFRESH_ENTRY *MenuRefreshEntry;\r
+ EFI_STATUS Status;\r
+ UI_MENU_SELECTION *Selection;\r
+\r
+ if (gMenuRefreshHead != NULL) {\r
+ //\r
+ // call from refresh interval process.\r
+ //\r
+ MenuRefreshEntry = gMenuRefreshHead;\r
+ Selection = MenuRefreshEntry->Selection;\r
+ //\r
+ // Reset FormPackage update flag\r
+ //\r
+ mHiiPackageListUpdated = FALSE;\r
+\r
+ do {\r
+ Status = RefreshQuestion (MenuRefreshEntry);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
UI_CONTROL_FLAG ControlFlag;\r
EFI_SCREEN_DESCRIPTOR LocalScreen;\r
MENU_REFRESH_ENTRY *MenuRefreshEntry;\r
+ MENU_REFRESH_ENTRY *MenuUpdateEntry; \r
UI_SCREEN_OPERATION ScreenOperation;\r
UINT8 MinRefreshInterval;\r
UINTN BufferSize;\r
OptionString[Count] = CHAR_NULL;\r
}\r
\r
+ //\r
+ // If Question has refresh guid, register the op-code.\r
+ //\r
+ if (!CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) {\r
+ if (gMenuEventGuidRefreshHead == NULL) {\r
+ MenuUpdateEntry = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));\r
+ gMenuEventGuidRefreshHead = MenuUpdateEntry;\r
+ } else {\r
+ MenuUpdateEntry = gMenuEventGuidRefreshHead;\r
+ while (MenuUpdateEntry->Next != NULL) {\r
+ MenuUpdateEntry = MenuUpdateEntry->Next; \r
+ }\r
+ MenuUpdateEntry->Next = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));\r
+ }\r
+ ASSERT (MenuUpdateEntry != NULL);\r
+ Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY, RefreshQuestionNotify, MenuUpdateEntry, &Statement->RefreshGuid, &MenuUpdateEntry->Event);\r
+ ASSERT (!EFI_ERROR (Status));\r
+ MenuUpdateEntry->MenuOption = MenuOption;\r
+ MenuUpdateEntry->Selection = Selection;\r
+ MenuUpdateEntry->CurrentColumn = MenuOption->OptCol;\r
+ MenuUpdateEntry->CurrentRow = MenuOption->Row;\r
+ if (MenuOption->GrayOut) {\r
+ MenuUpdateEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND;\r
+ } else {\r
+ MenuUpdateEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND;\r
+ }\r
+ }\r
+\r
//\r
// If Question request refresh, register the op-code\r
//\r
UINTN CurrentColumn;\r
UINTN CurrentRow;\r
UINTN CurrentAttribute;\r
+ EFI_EVENT Event;\r
};\r
\r
typedef struct {\r