Пример #1
0
void mp_hal_set_interrupt_char(int c) {
    if (c != -1) {
        #if MICROPY_KBD_EXCEPTION
        mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
        #else
        mp_obj_exception_clear_traceback(MP_STATE_PORT(mp_kbd_exception));
        #endif
    }
    mp_interrupt_char = c;
}
Пример #2
0
void mp_hal_set_interrupt_char(int c) {
    if (c != -1) {
        mp_obj_exception_clear_traceback(MP_STATE_PORT(mp_kbd_exception));
    }
    extern int interrupt_char;
    interrupt_char = c;
}
Пример #3
0
void usb_vcp_set_interrupt_char(int c) {
    if (dev_is_enabled) {
        if (c != VCP_CHAR_NONE) {
            mp_obj_exception_clear_traceback(mp_const_vcp_interrupt);
        }
        USBD_CDC_SetInterrupt(c, mp_const_vcp_interrupt);
    }
}
Пример #4
0
void usb_vcp_set_interrupt_char(int c) {
    if (pyb_usb_flags & PYB_USB_FLAG_DEV_ENABLED) {
        if (c != -1) {
            mp_obj_exception_clear_traceback(MP_STATE_PORT(mp_const_vcp_interrupt));
        }
        USBD_CDC_SetInterrupt(c, MP_STATE_PORT(mp_const_vcp_interrupt));
    }
}
Пример #5
0
STATIC void sighandler(int signum) {
    if (signum == SIGINT) {
        if (MP_STATE_VM(mp_pending_exception) == MP_STATE_VM(keyboard_interrupt_obj)) {
            // this is the second time we are called, so die straight away
            exit(1);
        }
        mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj));
        MP_STATE_VM(mp_pending_exception) = MP_STATE_VM(keyboard_interrupt_obj);
    }
}
Пример #6
0
STATIC void sighandler(int signum) {
    if (signum == SIGINT) {
        #if MICROPY_ASYNC_KBD_INTR
        mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj));
        sigset_t mask;
        sigemptyset(&mask);
        // On entry to handler, its signal is blocked, and unblocked on
        // normal exit. As we instead perform longjmp, unblock it manually.
        sigprocmask(SIG_SETMASK, &mask, NULL);
        nlr_raise(MP_STATE_VM(keyboard_interrupt_obj));
        #else
        if (MP_STATE_VM(mp_pending_exception) == MP_STATE_VM(keyboard_interrupt_obj)) {
            // this is the second time we are called, so die straight away
            exit(1);
        }
        mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj));
        MP_STATE_VM(mp_pending_exception) = MP_STATE_VM(keyboard_interrupt_obj);
        #endif
    }
}
Пример #7
0
STATIC void sighandler(int signum) {
    if (signum == SIGINT) {
        mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj));
        MP_STATE_VM(mp_pending_exception) = MP_STATE_VM(keyboard_interrupt_obj);
        // disable our handler so next we really die
        struct sigaction sa;
        sa.sa_handler = SIG_DFL;
        sigemptyset(&sa.sa_mask);
        sigaction(SIGINT, &sa, NULL);
    }
}
Пример #8
0
// Handler to be installed by SetConsoleCtrlHandler, currently used only to handle Ctrl-C.
// This handler has to be installed just once (this has to be done elswhere in init code).
// Previous versions of the mp_hal code would install a handler whenever Ctrl-C input is
// allowed and remove the handler again when it is not. That is not necessary though (1),
// and it might introduce problems (2) because console notifications are delivered to the
// application in a seperate thread. 
// (1) mp_hal_set_interrupt_char effectively enables/disables processing of Ctrl-C via the
// ENABLE_PROCESSED_INPUT flag so in raw mode console_sighandler won't be called.
// (2) if mp_hal_set_interrupt_char would remove the handler while Ctrl-C was issued earlier,
// the thread created for handling it might not be running yet so we'd miss the notification.
BOOL WINAPI console_sighandler(DWORD evt) {
    if (evt == CTRL_C_EVENT) {
        if (MP_STATE_VM(mp_pending_exception) == MP_STATE_VM(keyboard_interrupt_obj)) {
            // this is the second time we are called, so die straight away
            exit(1);
        }
        mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj));
        MP_STATE_VM(mp_pending_exception) = MP_STATE_VM(keyboard_interrupt_obj);
        return TRUE;
    }
    return FALSE;
}
Пример #9
0
void mp_hal_set_interrupt_char(int c) {
    if (c != -1) {
        mp_obj_exception_clear_traceback(MP_STATE_PORT(keyboard_interrupt_obj));
    }
    interrupt_char = c;
}
Пример #10
0
void mp_hal_set_interrupt_char(int c) {
  if (c != -1) {
    mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
  }
  mp_interrupt_char = c;
}
Пример #11
0
void usbdbg_control(void *buffer, uint8_t request, uint32_t length)
{
    cmd = (enum usbdbg_cmd) request;
    switch (cmd) {
        case USBDBG_FW_VERSION:
            xfer_bytes = 0;
            xfer_length = length;
            break;

        case USBDBG_FRAME_SIZE:
            xfer_bytes = 0;
            xfer_length = length;
            break;

        case USBDBG_FRAME_DUMP:
            xfer_bytes = 0;
            xfer_length = length;
            break;

        case USBDBG_ARCH_STR:
            xfer_bytes = 0;
            xfer_length = length;
            break;

        case USBDBG_SCRIPT_EXEC:
            xfer_bytes = 0;
            xfer_length = length;
            vstr_reset(&script_buf);
            break;

        case USBDBG_SCRIPT_STOP:
            if (script_running) {
                // Set script running flag
                script_running = false;

                // Disable IDE IRQ (re-enabled by pyexec or main).
                usbdbg_set_irq_enabled(false);

                // interrupt running code by raising an exception
                mp_obj_exception_clear_traceback(mp_const_ide_interrupt);
                pendsv_nlr_jump(mp_const_ide_interrupt);
            }
            cmd = USBDBG_NONE;
            break;

        case USBDBG_SCRIPT_SAVE:
            /* save running script */
            // TODO
            break;

        case USBDBG_SCRIPT_RUNNING:
            xfer_bytes = 0;
            xfer_length =length;
            break;

        case USBDBG_TEMPLATE_SAVE:
        case USBDBG_DESCRIPTOR_SAVE:
            /* save template */
            xfer_bytes = 0;
            xfer_length =length;
            break;

        case USBDBG_ATTR_WRITE: {
            /* write sensor attribute */
            int16_t attr= *((int16_t*)buffer);
            int16_t val = *((int16_t*)buffer+1);
            switch (attr) {
                case ATTR_CONTRAST:
                    sensor_set_contrast(val);
                    break;
                case ATTR_BRIGHTNESS:
                    sensor_set_brightness(val);
                    break;
                case ATTR_SATURATION:
                    sensor_set_saturation(val);
                    break;
                case ATTR_GAINCEILING:
                    sensor_set_gainceiling(val);
                    break;
                default:
                    break;
            }
            cmd = USBDBG_NONE;
            break;
        }

        case USBDBG_SYS_RESET:
            NVIC_SystemReset();
            break;

        case USBDBG_FB_ENABLE: {
            int16_t enable = *((int16_t*)buffer);
            JPEG_FB()->enabled = enable;
            if (enable == 0) {
                // When disabling framebuffer, the IDE might still be holding FB lock.
                // If the IDE is not the current lock owner, this operation is ignored.
                mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_IDE);
            }
            cmd = USBDBG_NONE;
            break;
        }

        case USBDBG_TX_BUF:
        case USBDBG_TX_BUF_LEN:
            xfer_bytes = 0;
            xfer_length = length;
            break;

        default: /* error */
            cmd = USBDBG_NONE;
            break;
    }
}
Пример #12
0
void usbdbg_data_out(void *buffer, int length)
{
    switch (cmd) {
        case USBDBG_SCRIPT_EXEC:
            // check if GC is locked before allocating memory for vstr. If GC was locked
            // at least once before the script is fully uploaded xfer_bytes will be less
            // than the total length (xfer_length) and the script will Not be executed.
            if (!script_running && !gc_is_locked()) {
                vstr_add_strn(&script_buf, buffer, length);
                xfer_bytes += length;
                if (xfer_bytes == xfer_length) {
                    // Set script ready flag
                    script_ready = true;

                    // Set script running flag
                    script_running = true;

                    // Disable IDE IRQ (re-enabled by pyexec or main).
                    usbdbg_set_irq_enabled(false);

                    // Clear interrupt traceback
                    mp_obj_exception_clear_traceback(mp_const_ide_interrupt);
                    // Interrupt running REPL
                    // Note: setting pendsv explicitly here because the VM is probably
                    // waiting in REPL and the soft interrupt flag will not be checked.
                    pendsv_nlr_jump_hard(mp_const_ide_interrupt);
                }
            }
            break;

        case USBDBG_TEMPLATE_SAVE: {
            image_t image ={
                .w = MAIN_FB()->w,
                .h = MAIN_FB()->h,
                .bpp = MAIN_FB()->bpp,
                .pixels = MAIN_FB()->pixels
            };

            // null terminate the path
            length = (length == 64) ? 63:length;
            ((char*)buffer)[length] = 0;

            rectangle_t *roi = (rectangle_t*)buffer;
            char *path = (char*)buffer+sizeof(rectangle_t);

            imlib_save_image(&image, path, roi, 50);
            // raise a flash IRQ to flush image
            //NVIC->STIR = FLASH_IRQn;
            break;
        }

        case USBDBG_DESCRIPTOR_SAVE: {
            image_t image ={
                .w = MAIN_FB()->w,
                .h = MAIN_FB()->h,
                .bpp = MAIN_FB()->bpp,
                .pixels = MAIN_FB()->pixels
            };

            // null terminate the path
            length = (length == 64) ? 63:length;
            ((char*)buffer)[length] = 0;

            rectangle_t *roi = (rectangle_t*)buffer;
            char *path = (char*)buffer+sizeof(rectangle_t);

            py_image_descriptor_from_roi(&image, path, roi);
            break;
        }
        default: /* error */
            break;
    }
}
Пример #13
0
void usbdbg_data_out(void *buffer, int length)
{
    switch (cmd) {
        case USBDBG_SCRIPT_EXEC:
            // check if GC is locked before allocating memory for vstr. If GC was locked
            // at least once before the script is fully uploaded xfer_bytes will be less
            // than the total length (xfer_length) and the script will Not be executed.
            if (usbdbg_get_irq_enabled() && !gc_is_locked()) {
                vstr_add_strn(&script_buf, buffer, length);
                xfer_bytes += length;
                if (xfer_bytes == xfer_length) {
                    // Set script ready flag
                    script_ready = 1;
                    // Disable IDE IRQ (re-enabled by pyexec or main).
                    usbdbg_set_irq_enabled(false);
                    // interrupt running script/REPL
                    mp_obj_exception_clear_traceback(mp_const_ide_interrupt);
                    pendsv_nlr_jump_hard(mp_const_ide_interrupt);
                }
            }
            break;

        case USBDBG_TEMPLATE_SAVE: {
            image_t image ={
                .w = fb->w,
                .h = fb->h,
                .bpp = fb->bpp,
                .pixels = fb->pixels
            };

            // null terminate the path
            length = (length == 64) ? 63:length; 
            ((char*)buffer)[length] = 0;

            rectangle_t *roi = (rectangle_t*)buffer;
            char *path = (char*)buffer+sizeof(rectangle_t);

            int res=imlib_save_image(&image, path, roi);
            if (res != FR_OK) {
                nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, ffs_strerror(res)));
            }
            // raise a flash IRQ to flush image
            //NVIC->STIR = FLASH_IRQn;
            break;
        }

        case USBDBG_DESCRIPTOR_SAVE: {
            image_t image ={
                .w = fb->w,
                .h = fb->h,
                .bpp = fb->bpp,
                .pixels = fb->pixels
            };

            // null terminate the path
            length = (length == 64) ? 63:length; 
            ((char*)buffer)[length] = 0;

            rectangle_t *roi = (rectangle_t*)buffer;
            char *path = (char*)buffer+sizeof(rectangle_t);

            py_image_descriptor_from_roi(&image, path, roi);
            break;
        }
        default: /* error */
            break;
    }
}

void usbdbg_control(void *buffer, uint8_t request, uint32_t length)
{
    cmd = (enum usbdbg_cmd) request;
    switch (cmd) {
        case USBDBG_FW_VERSION:
            xfer_bytes = 0;
            xfer_length = length;
            break;

        case USBDBG_FRAME_SIZE:
            xfer_bytes = 0;
            xfer_length = length;
            break;

        case USBDBG_FRAME_DUMP:
            xfer_bytes = 0;
            xfer_length = length;
            break;

        case USBDBG_FRAME_LOCK:
            xfer_bytes = 0;
            xfer_length = length;
            break;

        case USBDBG_FRAME_UPDATE:
            sensor_snapshot(NULL);
            cmd = USBDBG_NONE;
            break;

        case USBDBG_SCRIPT_EXEC:
            xfer_bytes = 0;
            xfer_length =length;
            vstr_reset(&script_buf);
            break;

        case USBDBG_SCRIPT_STOP:
            if (usbdbg_get_irq_enabled()) {
                // Disable IDE IRQ (re-enabled by pyexec or main).
                usbdbg_set_irq_enabled(false);
                // interrupt running code by raising an exception
                mp_obj_exception_clear_traceback(mp_const_ide_interrupt);
                pendsv_nlr_jump_hard(mp_const_ide_interrupt);
            }
            cmd = USBDBG_NONE;
            break;

        case USBDBG_SCRIPT_SAVE:
            /* save running script */
            break;

        case USBDBG_TEMPLATE_SAVE:
        case USBDBG_DESCRIPTOR_SAVE:
            /* save template */
            xfer_bytes = 0;
            xfer_length =length;
            break;

        case USBDBG_ATTR_WRITE: {
            /* write sensor attribute */
            int16_t attr= *((int16_t*)buffer);
            int16_t val = *((int16_t*)buffer+1);
            switch (attr) {
                case ATTR_CONTRAST:
                    sensor_set_contrast(val);
                    break;
                case ATTR_BRIGHTNESS:
                    sensor_set_brightness(val);
                    break;
                case ATTR_SATURATION:
                    sensor_set_saturation(val);
                    break;
                case ATTR_GAINCEILING:
                    sensor_set_gainceiling(val);
                    break;
                default:
                    break;
            }
            cmd = USBDBG_NONE;
            break;
        }

        case USBDBG_SYS_RESET:
            NVIC_SystemReset();
            break;

        case USBDBG_BOOT:
            *((uint32_t *)0x20002000) = 0xDEADBEEF;
            NVIC_SystemReset();
            break;

        case USBDBG_TX_BUF:
        case USBDBG_TX_BUF_LEN:
            xfer_bytes = 0;
            xfer_length = length;
            break;

        default: /* error */
            cmd = USBDBG_NONE;
            break;
    }
}
Пример #14
0
ide_dbg_status_t ide_dbg_dispatch_cmd(machine_uart_obj_t* uart, uint8_t* data)
{
    uint32_t length;

    if(ide_dbg_cmd_len_count==0)
    {
        if( is_busy_sending ) // throw out data //TODO: maybe need queue data?
            return IDE_DBG_DISPATCH_STATUS_BUSY;
        length = xfer_length - xfer_bytes;
        if(length)//receive data from IDE
        {
            ide_dbg_receive_data(uart, data);
            ++xfer_bytes;
            return IDE_DBG_STATUS_OK;
        }
        if(*data == IDE_DBG_CMD_START_FLAG)
            ide_dbg_cmd_len_count = 1;
    }
    else
    {
        ide_dbg_cmd_buf[ide_dbg_cmd_len_count++] = *data;
        if(ide_dbg_cmd_len_count < 6)
            return IDE_DBG_DISPATCH_STATUS_WAIT;
        length = *( (uint32_t*)(ide_dbg_cmd_buf+2) );
        cmd = ide_dbg_cmd_buf[1];
        switch (cmd) {
            case USBDBG_FW_VERSION:
                xfer_bytes = 0;
                xfer_length = length;
                break;

            case USBDBG_FRAME_SIZE:
                xfer_bytes = 0;
                xfer_length = length;
                break;

            case USBDBG_FRAME_DUMP:
                xfer_bytes = 0;
                xfer_length = length;
                if(length)
                    is_sending_jpeg = true;
                break;

            case USBDBG_ARCH_STR:
                xfer_bytes = 0;
                xfer_length = length;
                break;

            case USBDBG_SCRIPT_EXEC:
                xfer_bytes = 0;
                xfer_length = length;
                vstr_reset(&script_buf);
                break;

            case USBDBG_SCRIPT_STOP:
                if (script_running) {
                    // Set script running flag
                    script_running = false;
                    // // Disable IDE IRQ (re-enabled by pyexec or main).
                    // usbdbg_set_irq_enabled(false);

                    // interrupt running code by raising an exception
                    mp_obj_exception_clear_traceback(mp_const_ide_interrupt);
                    // pendsv_nlr_jump_hard(mp_const_ide_interrupt);
                    MP_STATE_VM(mp_pending_exception) = mp_const_ide_interrupt; //MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception));
                    #if MICROPY_ENABLE_SCHEDULER
                    if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {
                        MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
                    }
                    #endif
                }
                cmd = USBDBG_NONE;
                break;

            case USBDBG_FILE_SAVE:
                xfer_bytes = 0;
                xfer_length = length;
                ide_file_save_status = 0;
                if(length)
                {
                    ide_file_save_status = 1;
                    ide_file_length = length;
                    if( p_data_temp )
                    {
                        free(p_data_temp);
                    }
                    p_data_temp = malloc( (length%4)? (length+4-(length%4)): length );
                    if(!p_data_temp)
                    {
                        xfer_length = 0;
                        ide_file_length = 0;
                        ide_file_save_status = 2;
                    }
                }
                break;
            case USBDBG_FILE_SAVE_STATUS:
                xfer_bytes = 0;
                xfer_length = length;
                break;
            case USBDBG_SCRIPT_RUNNING:
                xfer_bytes = 0;
                xfer_length =length;
                break;

            case USBDBG_TEMPLATE_SAVE:
            case USBDBG_DESCRIPTOR_SAVE:
                /* save template */
                xfer_bytes = 0;
                xfer_length =length;
                break;

            case USBDBG_ATTR_WRITE: {
                if(ide_dbg_cmd_len_count < 10)
                    return IDE_DBG_DISPATCH_STATUS_WAIT;
                /* write sensor attribute */
                int16_t attr = *( (int16_t*)(ide_dbg_cmd_buf+6) );
                int16_t val = *( (int16_t*)(ide_dbg_cmd_buf+8) );
                switch (attr) {
                    case ATTR_CONTRAST:
                        sensor_set_contrast(val);
                        break;
                    case ATTR_BRIGHTNESS:
                        sensor_set_brightness(val);
                        break;
                    case ATTR_SATURATION:
                        sensor_set_saturation(val);
                        break;
                    case ATTR_GAINCEILING:
                        sensor_set_gainceiling(val);
                        break;
                    default:
                        break;
                }
                cmd = USBDBG_NONE;
                break;
            }

            case USBDBG_SYS_RESET:
                sipeed_sys_reset();
                break;

            case USBDBG_FB_ENABLE: 
            {
                if(ide_dbg_cmd_len_count < 8)
                    return IDE_DBG_DISPATCH_STATUS_WAIT;
                int16_t enable = *( (int16_t*)(ide_dbg_cmd_buf+6) );
                JPEG_FB()->enabled = enable;
                if (enable == 0) {
                    // When disabling framebuffer, the IDE might still be holding FB lock.
                    // If the IDE is not the current lock owner, this operation is ignored.
                    mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_IDE);
                }
                xfer_bytes = 0;
                xfer_length = length;
                cmd = USBDBG_NONE;
                break;
            }

            case USBDBG_TX_BUF:
            case USBDBG_TX_BUF_LEN:
                xfer_bytes = 0;
                xfer_length = length;
                break;
            default: /* error */
                cmd = USBDBG_NONE;
                break;
        }
        ide_dbg_cmd_len_count = 0; // all cmd data received ok
        if(length && (cmd&0x80) ) // need send data to IDE
        {
            is_busy_sending = true;
            ide_dbg_ack_data(uart);    // ack data
        }
    }
}
Пример #15
0
ide_dbg_status_t ide_dbg_receive_data(machine_uart_obj_t* uart, uint8_t* data)
{
    switch (cmd) {
        case USBDBG_SCRIPT_EXEC:
            // check if GC is locked before allocating memory for vstr. If GC was locked
            // at least once before the script is fully uploaded xfer_bytes will be less
            // than the total length (xfer_length) and the script will Not be executed.
            if (!script_running && !gc_is_locked()) {
                vstr_add_strn_00(&script_buf, data, 1);
                if (xfer_bytes+1 == xfer_length) {
                    // Set script ready flag
                    script_ready = true;

                    // Set script running flag
                    script_running = true;

                    // Disable IDE IRQ (re-enabled by pyexec or main).
                    // usbdbg_set_irq_enabled(false);
                    // Clear interrupt traceback
                    mp_obj_exception_clear_traceback(mp_const_ide_interrupt);
                    // Interrupt running REPL
                    // Note: setting pendsv explicitly here because the VM is probably
                    // waiting in REPL and the soft interrupt flag will not be checked.
                    // nlr_jump(mp_const_ide_interrupt);
                    MP_STATE_VM(mp_pending_exception) = mp_const_ide_interrupt;//MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception));
                    #if MICROPY_ENABLE_SCHEDULER
                    if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {
                        MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
                    }
                    #endif
                }
            }
            break;

        case USBDBG_FILE_SAVE:
        {
            p_data_temp[xfer_bytes] = *data;
            if (xfer_bytes+1 == xfer_length) {
                //save to FS
                ide_file_save_status = 5;
                mp_obj_exception_clear_traceback(mp_const_ide_interrupt);
                MP_STATE_VM(mp_pending_exception) = mp_const_ide_interrupt;//MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception));
                #if MICROPY_ENABLE_SCHEDULER
                if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {
                    MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
                }
                #endif
            }
            break;
        }
        case USBDBG_TEMPLATE_SAVE: {
            //TODO: save image support
            // image_t image ={
            //     .w = MAIN_FB()->w,
            //     .h = MAIN_FB()->h,
            //     .bpp = MAIN_FB()->bpp,
            //     .pixels = MAIN_FB()->pixels
            // };

            // // null terminate the path
            // length = (length == 64) ? 63:length;
            // ((char*)buffer)[length] = 0;

            // rectangle_t *roi = (rectangle_t*)buffer;
            // char *path = (char*)buffer+sizeof(rectangle_t);

            // imlib_save_image(&image, path, roi, 50);
            // raise a flash IRQ to flush image
            //NVIC->STIR = FLASH_IRQn;
            break;
        }

        case USBDBG_DESCRIPTOR_SAVE: {
            //TODO: save descriptor support
            // image_t image ={
            //     .w = MAIN_FB()->w,
            //     .h = MAIN_FB()->h,
            //     .bpp = MAIN_FB()->bpp,
            //     .pixels = MAIN_FB()->pixels
            // };

            // // null terminate the path
            // length = (length == 64) ? 63:length;
            // ((char*)buffer)[length] = 0;

            // rectangle_t *roi = (rectangle_t*)buffer;
            // char *path = (char*)buffer+sizeof(rectangle_t);

            // py_image_descriptor_from_roi(&image, path, roi);
            break;
        }
        default: /* error */
            break;
    }
}