diff options
| -rw-r--r-- | tmk_core/common.mk | 1 | ||||
| -rw-r--r-- | tmk_core/common/arm_atsam/printf.c | 66 | ||||
| -rw-r--r-- | tmk_core/common/arm_atsam/printf.h | 7 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/main_arm_atsam.c | 12 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/usb/conf_usb.h | 5 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/usb/main_usb.c | 14 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/usb/udi_cdc.c | 4 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/usb/udi_cdc.h | 1 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/usb/udi_device_conf.h | 88 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.c | 146 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.h | 11 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/usb/udi_hid_kbd_desc.c | 6 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/usb/usb_main.h | 6 | 
13 files changed, 347 insertions, 20 deletions
| diff --git a/tmk_core/common.mk b/tmk_core/common.mk index 319d196aec..4a0f7dcf9a 100644 --- a/tmk_core/common.mk +++ b/tmk_core/common.mk @@ -43,6 +43,7 @@ endif  endif  ifeq ($(PLATFORM),ARM_ATSAM) +	TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/printf.c  	TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/eeprom.c  endif diff --git a/tmk_core/common/arm_atsam/printf.c b/tmk_core/common/arm_atsam/printf.c new file mode 100644 index 0000000000..d49d234de2 --- /dev/null +++ b/tmk_core/common/arm_atsam/printf.c @@ -0,0 +1,66 @@ +/* +Copyright 2018 Massdrop Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program.  If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifdef CONSOLE_PRINT + +#include "samd51j18a.h" +#include "arm_atsam_protocol.h" +#include "printf.h" +#include <string.h> +#include <stdarg.h> + +void console_printf(char *fmt, ...) { +    while (udi_hid_con_b_report_trans_ongoing) {}           //Wait for any previous transfers to complete + +    static char console_printbuf[CONSOLE_PRINTBUF_SIZE];    //Print and send buffer +    va_list va; +    int result; + +    va_start(va, fmt); +    result = vsnprintf(console_printbuf, CONSOLE_PRINTBUF_SIZE, fmt, va); +    va_end(va); + +    uint32_t irqflags; +    char *pconbuf = console_printbuf;                       //Pointer to start send from +    int send_out = CONSOLE_EPSIZE;                          //Bytes to send per transfer + +    while (result > 0) {                                    //While not error and bytes remain +        while (udi_hid_con_b_report_trans_ongoing) {}       //Wait for any previous transfers to complete + +        irqflags = __get_PRIMASK(); +        __disable_irq(); +        __DMB(); + +        if (result < CONSOLE_EPSIZE) {                      //If remaining bytes are less than console epsize +            memset(udi_hid_con_report, 0, CONSOLE_EPSIZE);  //Clear the buffer +            send_out = result;                              //Send remaining size +        } + +        memcpy(udi_hid_con_report, pconbuf, send_out);      //Copy data into the send buffer + +        udi_hid_con_b_report_valid = 1;                     //Set report valid +        udi_hid_con_send_report();                          //Send report + +        __DMB(); +        __set_PRIMASK(irqflags); + +        result -= send_out;                                 //Decrement result by bytes sent +        pconbuf += send_out;                                //Increment buffer point by bytes sent +    } +} + +#endif //CONSOLE_PRINT diff --git a/tmk_core/common/arm_atsam/printf.h b/tmk_core/common/arm_atsam/printf.h index 3206b40bdb..1f1c2280b5 100644 --- a/tmk_core/common/arm_atsam/printf.h +++ b/tmk_core/common/arm_atsam/printf.h @@ -1,8 +1,11 @@  #ifndef _PRINTF_H_  #define _PRINTF_H_ -int dpf(const char *_Format, ...); -#define __xprintf dpf +#define CONSOLE_PRINTBUF_SIZE 512 + +void console_printf(char *fmt, ...); + +#define __xprintf console_printf  #endif //_PRINTF_H_ diff --git a/tmk_core/protocol/arm_atsam/main_arm_atsam.c b/tmk_core/protocol/arm_atsam/main_arm_atsam.c index 676dac4ea3..54d056a14e 100644 --- a/tmk_core/protocol/arm_atsam/main_arm_atsam.c +++ b/tmk_core/protocol/arm_atsam/main_arm_atsam.c @@ -276,9 +276,9 @@ int main(void)      host_set_driver(&arm_atsam_driver); -#ifdef VIRTSER_ENABLE +#ifdef CONSOLE_ENABLE      uint64_t next_print = 0; -#endif //VIRTSER_ENABLE +#endif //CONSOLE_ENABLE      v_5v_avg = adc_get(ADC_5V); @@ -290,15 +290,17 @@ int main(void)          main_subtasks(); //Note these tasks will also be run while waiting for USB keyboard polling intervals -#ifdef VIRTSER_ENABLE +#ifdef CONSOLE_ENABLE          if (CLK_get_ms() > next_print)          {              next_print = CLK_get_ms() + 250; -            dprintf("5v=%u 5vu=%u dlow=%u dhi=%u gca=%u gcd=%u\r\n",v_5v,v_5v_avg,v_5v_avg-V5_LOW,v_5v_avg-V5_HIGH,gcr_actual,gcr_desired); +            //Add any debug information here that you want to see very often +            //dprintf("5v=%u 5vu=%u dlow=%u dhi=%u gca=%u gcd=%u\r\n", v_5v, v_5v_avg, v_5v_avg - V5_LOW, v_5v_avg - V5_HIGH, gcr_actual, gcr_desired);          } -#endif //VIRTSER_ENABLE +#endif //CONSOLE_ENABLE      } +      return 1;  } diff --git a/tmk_core/protocol/arm_atsam/usb/conf_usb.h b/tmk_core/protocol/arm_atsam/usb/conf_usb.h index 8f0f472687..c91caffe02 100644 --- a/tmk_core/protocol/arm_atsam/usb/conf_usb.h +++ b/tmk_core/protocol/arm_atsam/usb/conf_usb.h @@ -134,6 +134,11 @@  #define  UDI_HID_EXK_DISABLE_EXT()      main_exk_disable()  #endif +#ifdef CON +#define  UDI_HID_CON_ENABLE_EXT()       main_con_enable() +#define  UDI_HID_CON_DISABLE_EXT()      main_con_disable() +#endif +  #ifdef MOU  #define  UDI_HID_MOU_ENABLE_EXT()       main_mou_enable()  #define  UDI_HID_MOU_DISABLE_EXT()      main_mou_disable() diff --git a/tmk_core/protocol/arm_atsam/usb/main_usb.c b/tmk_core/protocol/arm_atsam/usb/main_usb.c index e943cbcdcd..0f676ab639 100644 --- a/tmk_core/protocol/arm_atsam/usb/main_usb.c +++ b/tmk_core/protocol/arm_atsam/usb/main_usb.c @@ -88,6 +88,20 @@ void main_exk_disable(void)  }  #endif +#ifdef CON +volatile bool main_b_con_enable = false; +bool main_con_enable(void) +{ +    main_b_con_enable = true; +    return true; +} + +void main_con_disable(void) +{ +    main_b_con_enable = false; +} +#endif +  #ifdef MOU  volatile bool main_b_mou_enable = false;  bool main_mou_enable(void) diff --git a/tmk_core/protocol/arm_atsam/usb/udi_cdc.c b/tmk_core/protocol/arm_atsam/usb/udi_cdc.c index 15f0f760cc..5f3c289e81 100644 --- a/tmk_core/protocol/arm_atsam/usb/udi_cdc.c +++ b/tmk_core/protocol/arm_atsam/usb/udi_cdc.c @@ -1260,7 +1260,7 @@ uint32_t CDC_print(char *printbuf)  char printbuf[CDC_PRINTBUF_SIZE]; -int dpf(const char *_Format, ...) +int CDC_printf(const char *_Format, ...)  {      va_list va; //Variable argument list variable      int result; @@ -1356,7 +1356,7 @@ uint32_t CDC_print(char *printbuf)      return 0;  } -int dpf(const char *_Format, ...) +int CDC_printf(const char *_Format, ...)  {      return 0;  } diff --git a/tmk_core/protocol/arm_atsam/usb/udi_cdc.h b/tmk_core/protocol/arm_atsam/usb/udi_cdc.h index e134cf2360..86077ce53b 100644 --- a/tmk_core/protocol/arm_atsam/usb/udi_cdc.h +++ b/tmk_core/protocol/arm_atsam/usb/udi_cdc.h @@ -365,6 +365,7 @@ extern inbuf_t inbuf;  #endif //CDC  uint32_t CDC_print(char *printbuf); +int CDC_printf(const char *_Format, ...);  uint32_t CDC_input(void);  void CDC_init(void); diff --git a/tmk_core/protocol/arm_atsam/usb/udi_device_conf.h b/tmk_core/protocol/arm_atsam/usb/udi_device_conf.h index c787262340..1e82b9eccb 100644 --- a/tmk_core/protocol/arm_atsam/usb/udi_device_conf.h +++ b/tmk_core/protocol/arm_atsam/usb/udi_device_conf.h @@ -44,10 +44,10 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #define RAW  #endif -//#define CONSOLE_ENABLE //deferred implementation -//#ifdef CONSOLE_ENABLE -//#define CON -//#endif +//#define CONSOLE_ENABLE //rules.mk +#ifdef CONSOLE_ENABLE +#define CON +#endif  //#define NKRO_ENABLE //rules.mk  #ifdef NKRO_ENABLE @@ -110,8 +110,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #endif  #ifdef CON -#define CONSOLE_INTERFACE           NEXT_INTERFACE_4 -#define NEXT_INTERFACE_5            (CONSOLE_INTERFACE + 1) +#define CON_INTERFACE               NEXT_INTERFACE_4 +#define NEXT_INTERFACE_5            (CON_INTERFACE + 1) +#define UDI_HID_CON_IFACE_NUMBER    CON_INTERFACE  #else  #define NEXT_INTERFACE_5            NEXT_INTERFACE_4  #endif @@ -211,11 +212,16 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #endif  #ifdef CON -#define CONSOLE_IN_EPNUM            NEXT_IN_EPNUM_4 -#define NEXT_IN_EPNUM_5             (CONSOLE_IN_EPNUM + 1) -#define CONSOLE_OUT_EPNUM           NEXT_OUT_EPNUM_1 -#define NEXT_OUT_EPNUM_2            (CONSOLE_OUT_EPNUM + 1) -#define CONSOLE_POLLING_INTERVAL    1 +#define CON_IN_EPNUM                NEXT_IN_EPNUM_4 +#define UDI_HID_CON_EP_IN           CON_IN_EPNUM +#define NEXT_IN_EPNUM_5             (CON_IN_EPNUM + 1) +#define CON_OUT_EPNUM               NEXT_OUT_EPNUM_1 +#define UDI_HID_CON_EP_OUT          CON_OUT_EPNUM +#define NEXT_OUT_EPNUM_2            (CON_OUT_EPNUM + 1) +#define CON_POLLING_INTERVAL        1 +#ifndef UDI_HID_CON_STRING_ID +#define UDI_HID_CON_STRING_ID       0 +#endif  #else  #define NEXT_IN_EPNUM_5             NEXT_IN_EPNUM_4  #define NEXT_OUT_EPNUM_2            NEXT_OUT_EPNUM_1 @@ -559,6 +565,66 @@ COMPILER_PACK_RESET()  #endif //RAW  // ********************************************************************** +// CON Descriptor structure and content +// ********************************************************************** +#ifdef CON + +COMPILER_PACK_SET(1) + +typedef struct { +    usb_iface_desc_t iface; +    usb_hid_descriptor_t hid; +    usb_ep_desc_t ep_out; +    usb_ep_desc_t ep_in; +} udi_hid_con_desc_t; + +typedef struct { +    uint8_t array[34]; +} udi_hid_con_report_desc_t; + +#define UDI_HID_CON_DESC {\ +    .iface.bLength             = sizeof(usb_iface_desc_t),\ +    .iface.bDescriptorType     = USB_DT_INTERFACE,\ +    .iface.bInterfaceNumber    = UDI_HID_CON_IFACE_NUMBER,\ +    .iface.bAlternateSetting   = 0,\ +    .iface.bNumEndpoints       = 2,\ +    .iface.bInterfaceClass     = HID_CLASS,\ +    .iface.bInterfaceSubClass  = HID_SUB_CLASS_NOBOOT,\ +    .iface.bInterfaceProtocol  = HID_SUB_CLASS_NOBOOT,\ +    .iface.iInterface          = UDI_HID_CON_STRING_ID,\ +    .hid.bLength               = sizeof(usb_hid_descriptor_t),\ +    .hid.bDescriptorType       = USB_DT_HID,\ +    .hid.bcdHID                = LE16(USB_HID_BDC_V1_11),\ +    .hid.bCountryCode          = USB_HID_NO_COUNTRY_CODE,\ +    .hid.bNumDescriptors       = USB_HID_NUM_DESC,\ +    .hid.bRDescriptorType      = USB_DT_HID_REPORT,\ +    .hid.wDescriptorLength     = LE16(sizeof(udi_hid_con_report_desc_t)),\ +    .ep_out.bLength            = sizeof(usb_ep_desc_t),\ +    .ep_out.bDescriptorType    = USB_DT_ENDPOINT,\ +    .ep_out.bEndpointAddress   = UDI_HID_CON_EP_OUT | USB_EP_DIR_OUT,\ +    .ep_out.bmAttributes       = USB_EP_TYPE_INTERRUPT,\ +    .ep_out.wMaxPacketSize     = LE16(CONSOLE_EPSIZE),\ +    .ep_out.bInterval          = CON_POLLING_INTERVAL,\ +    .ep_in.bLength             = sizeof(usb_ep_desc_t),\ +    .ep_in.bDescriptorType     = USB_DT_ENDPOINT,\ +    .ep_in.bEndpointAddress    = UDI_HID_CON_EP_IN | USB_EP_DIR_IN,\ +    .ep_in.bmAttributes        = USB_EP_TYPE_INTERRUPT,\ +    .ep_in.wMaxPacketSize      = LE16(CONSOLE_EPSIZE),\ +    .ep_in.bInterval           = CON_POLLING_INTERVAL,\ +} + +#define UDI_HID_CON_REPORT_SIZE CONSOLE_EPSIZE + +extern uint8_t udi_hid_con_report_set[UDI_HID_CON_REPORT_SIZE]; + +//report buffer +extern uint8_t udi_hid_con_report[UDI_HID_CON_REPORT_SIZE]; + +COMPILER_PACK_RESET() + +#endif //CON + +// **********************************************************************  // CDC Descriptor structure and content  // **********************************************************************  #ifdef CDC diff --git a/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.c b/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.c index 1a6f7905e6..18f9784ae6 100644 --- a/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.c +++ b/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.c @@ -843,3 +843,149 @@ static void udi_hid_raw_setreport_valid(void)  }  #endif //RAW + +//******************************************************************************************** +// CON +//******************************************************************************************** +#ifdef CON + +bool udi_hid_con_enable(void); +void udi_hid_con_disable(void); +bool udi_hid_con_setup(void); +uint8_t udi_hid_con_getsetting(void); + +UDC_DESC_STORAGE udi_api_t udi_api_hid_con = { +    .enable = (bool(*)(void))udi_hid_con_enable, +    .disable = (void (*)(void))udi_hid_con_disable, +    .setup = (bool(*)(void))udi_hid_con_setup, +    .getsetting = (uint8_t(*)(void))udi_hid_con_getsetting, +    .sof_notify = NULL, +}; + +COMPILER_WORD_ALIGNED +static uint8_t udi_hid_con_rate; + +COMPILER_WORD_ALIGNED +static uint8_t udi_hid_con_protocol; + +COMPILER_WORD_ALIGNED +uint8_t udi_hid_con_report_set[UDI_HID_CON_REPORT_SIZE]; + +bool udi_hid_con_b_report_valid; + +COMPILER_WORD_ALIGNED +uint8_t udi_hid_con_report[UDI_HID_CON_REPORT_SIZE]; + +volatile bool udi_hid_con_b_report_trans_ongoing; + +COMPILER_WORD_ALIGNED +static uint8_t udi_hid_con_report_trans[UDI_HID_CON_REPORT_SIZE]; + +COMPILER_WORD_ALIGNED +UDC_DESC_STORAGE udi_hid_con_report_desc_t udi_hid_con_report_desc = { +    { +        0x06, 0x31, 0xFF,           // Vendor Page (PJRC Teensy compatible) +        0x09, 0x74,                 // Vendor Usage (PJRC Teensy compatible) +        0xA1, 0x01,                 // Collection (Application) +            0x09, 0x75,             //   Usage (Vendor) +            0x15, 0x00,             //   Logical Minimum (0x00) +            0x26, 0xFF, 0x00,       //   Logical Maximum (0x00FF) +            0x95, CONSOLE_EPSIZE,   //   Report Count +            0x75, 0x08,             //   Report Size (8) +            0x81, 0x02,             //   Input (Data) +            0x09, 0x76,             //   Usage (Vendor) +            0x15, 0x00,             //   Logical Minimum (0x00) +            0x26, 0xFF, 0x00,       //   Logical Maximum (0x00FF) +            0x95, CONSOLE_EPSIZE,   //   Report Count +            0x75, 0x08,             //   Report Size (8) +            0x91, 0x02,             //   Output (Data) +        0xC0,                       // End Collection +    } +}; + +static bool udi_hid_con_setreport(void); +static void udi_hid_con_setreport_valid(void); + +static void udi_hid_con_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep); + +bool udi_hid_con_enable(void) +{ +    // Initialize internal values +    udi_hid_con_rate = 0; +    udi_hid_con_protocol = 0; +    udi_hid_con_b_report_trans_ongoing = false; +    memset(udi_hid_con_report, 0, UDI_HID_CON_REPORT_SIZE); +    udi_hid_con_b_report_valid = false; +    return UDI_HID_CON_ENABLE_EXT(); +} + +void udi_hid_con_disable(void) +{ +    UDI_HID_CON_DISABLE_EXT(); +} + +bool udi_hid_con_setup(void) +{ +    return udi_hid_setup(&udi_hid_con_rate, +                            &udi_hid_con_protocol, +                            (uint8_t *) &udi_hid_con_report_desc, +                            udi_hid_con_setreport); +} + +uint8_t udi_hid_con_getsetting(void) +{ +    return 0; +} + +static bool udi_hid_con_setreport(void) +{ +    if ((USB_HID_REPORT_TYPE_OUTPUT == (udd_g_ctrlreq.req.wValue >> 8)) +            && (0 == (0xFF & udd_g_ctrlreq.req.wValue)) +            && (UDI_HID_CON_REPORT_SIZE == udd_g_ctrlreq.req.wLength)) { +        udd_g_ctrlreq.payload = udi_hid_con_report_set; +        udd_g_ctrlreq.callback = udi_hid_con_setreport_valid; +        udd_g_ctrlreq.payload_size = UDI_HID_CON_REPORT_SIZE; +        return true; +    } +    return false; +} + +bool udi_hid_con_send_report(void) +{ +    if (!main_b_con_enable) { +        return false; +    } + +    if (udi_hid_con_b_report_trans_ongoing) { +        return false; +    } + +    memcpy(udi_hid_con_report_trans, udi_hid_con_report,UDI_HID_CON_REPORT_SIZE); +    udi_hid_con_b_report_valid = false; +    udi_hid_con_b_report_trans_ongoing = +            udd_ep_run(UDI_HID_CON_EP_IN | USB_EP_DIR_IN, +                        false, +                        udi_hid_con_report_trans, +                        UDI_HID_CON_REPORT_SIZE, +                        udi_hid_con_report_sent); + +    return udi_hid_con_b_report_trans_ongoing; +} + +static void udi_hid_con_report_sent(udd_ep_status_t status, iram_size_t nb_sent, udd_ep_id_t ep) +{ +    UNUSED(status); +    UNUSED(nb_sent); +    UNUSED(ep); +    udi_hid_con_b_report_trans_ongoing = false; +    if (udi_hid_con_b_report_valid) { +        udi_hid_con_send_report(); +    } +} + +static void udi_hid_con_setreport_valid(void) +{ + +} + +#endif //CON diff --git a/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.h b/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.h index babfdb7a78..e442919a9b 100644 --- a/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.h +++ b/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.h @@ -86,6 +86,17 @@ bool udi_hid_exk_send_report(void);  #endif //EXK  //******************************************************************************************** +// CON Console +//******************************************************************************************** +#ifdef CON +extern UDC_DESC_STORAGE udi_api_t udi_api_hid_con; +extern bool udi_hid_con_b_report_valid; +extern uint8_t udi_hid_con_report_set[UDI_HID_CON_REPORT_SIZE]; +extern volatile bool udi_hid_con_b_report_trans_ongoing; +bool udi_hid_con_send_report(void); +#endif //CON + +//********************************************************************************************  // MOU Mouse  //********************************************************************************************  #ifdef MOU diff --git a/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd_desc.c b/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd_desc.c index 16bd4e514c..2d6e35e254 100644 --- a/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd_desc.c +++ b/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd_desc.c @@ -134,6 +134,9 @@ UDC_DESC_STORAGE udc_desc_t udc_desc = {  #ifdef EXK    .hid_exk                   = UDI_HID_EXK_DESC,  #endif +#ifdef CON +  .hid_con                   = UDI_HID_CON_DESC, +#endif  #ifdef NKRO    .hid_nkro                  = UDI_HID_NKRO_DESC,  #endif @@ -155,6 +158,9 @@ UDC_DESC_STORAGE udi_api_t *udi_apis[USB_DEVICE_NB_INTERFACE] = {    #ifdef EXK      &udi_api_hid_exk,    #endif +  #ifdef CON +    &udi_api_hid_con, +  #endif    #ifdef NKRO      &udi_api_hid_nkro,    #endif diff --git a/tmk_core/protocol/arm_atsam/usb/usb_main.h b/tmk_core/protocol/arm_atsam/usb/usb_main.h index b7adaa1a72..76ced474dc 100644 --- a/tmk_core/protocol/arm_atsam/usb/usb_main.h +++ b/tmk_core/protocol/arm_atsam/usb/usb_main.h @@ -82,6 +82,12 @@ bool main_exk_enable(void);  void main_exk_disable(void);  #endif //EXK +#ifdef CON +extern volatile bool main_b_con_enable; +bool main_con_enable(void); +void main_con_disable(void); +#endif //CON +  #ifdef MOU  extern volatile bool main_b_mou_enable;  bool main_mou_enable(void); | 
