/* * Test: n = size of the counter, t = timeout value */ static void test_timeout(uint32_t *c, uint32_t n, uint32_t timeout) { double start, end; printf("---> test: size = %"PRIu32", timeout = %"PRIu32" s\n", n, timeout); fflush(stdout); wrapper.interrupted = false; start_timeout(timeout, handler, &wrapper); start = get_cpu_time(); loop(c, n); clear_timeout(); end = get_cpu_time(); printf(" cpu time = %.2f s\n", end - start); fflush(stdout); if (wrapper.interrupted) { printf(" interrupted at: "); show_counter(c, n); printf("\n"); fflush(stdout); } else { printf(" completed: "); show_counter(c, n); printf("\n"); fflush(stdout); } }
static void dispatch_timeout(netresolve_query_t query, netresolve_timeout_t *timeout, enum netresolve_state state) { assert(timeout && *timeout); clear_timeout(query, timeout); netresolve_query_set_state(query, state); }
static void cleanup_query(netresolve_query_t query) { struct netresolve_backend *backend = query->backend ? *query->backend : NULL; clear_timeout(query, &query->delayed); clear_timeout(query, &query->request_timeout); clear_timeout(query, &query->result_timeout); if (backend) { if (backend->cleanup) backend->cleanup(backend->data); if (backend->data) free(backend->data); backend->data = NULL; } }
void disp_win_screen_status(char *in_method, char *half_status) { dbg("disp_win_screen_status\n"); if ( // tss.c_len || ggg.gbufN || cur_file_hf && !strcmp(cur_file_hf, half_status) && cur_file_inmd && !strcmp(cur_file_inmd, in_method) #if 0 && old_x==current_in_win_x && old_y==current_in_win_y #endif ) return; old_x = current_in_win_x; old_y = current_in_win_y; clear_timeout(); free(cur_file_hf); cur_file_hf = strdup(half_status); free(cur_file_inmd); cur_file_inmd = strdup(in_method); if (!win_screen_status) { win_screen_status = create_no_focus_win(); GtkWidget *hbox = gtk_hbox_new (FALSE, 0); gtk_container_add(GTK_CONTAINER(win_screen_status), hbox); icon_inmd = gtk_image_new_from_file(in_method); gtk_box_pack_start (GTK_BOX (hbox), icon_inmd, FALSE, FALSE, 0); #if 1 icon_hf = gtk_image_new_from_file(half_status); gtk_box_pack_start (GTK_BOX (hbox), icon_hf, FALSE, FALSE, 0); #endif } else { #if 1 gtk_image_set_from_file(GTK_IMAGE(icon_hf), half_status); #endif gtk_image_set_from_file(GTK_IMAGE(icon_inmd), in_method); } gtk_widget_show_all(win_screen_status); gtk_window_present(GTK_WINDOW(win_screen_status)); timeout_handle = g_timeout_add(1000, timeout_hide, NULL); int w,h; get_win_size(win_screen_status, &w, &h); int x = current_in_win_x; int y = current_in_win_y + (win_is_visible()?win_yl:0); if (x + w > dpy_xl) x = dpy_xl - w; if (y + h > dpy_yl) y = win_y - h; gtk_window_move(GTK_WINDOW(win_screen_status), x, y); }
static int trigger_open(struct inode *inode, struct file *file) { unsigned int minor; unsigned long flags; if (!try_module_get(THIS_MODULE)) { return -EBUSY; } minor = MINOR(inode->i_rdev); printk(KERN_INFO "trigger: open called by PID %u, on minor %d\n", current->pid, minor); spin_lock_irqsave(&trigger_lock,flags); if (module_in_use) { /* return if device already open */ spin_unlock_irqrestore(&trigger_lock,flags); module_put(THIS_MODULE); return -EBUSY; } /* mark usage */ module_in_use = 1; in_use_pid = current->pid; interrupt_ready = 0; interrupt_count = 0; spin_unlock_irqrestore(&trigger_lock,flags); /* initialize control register */ unsigned char ctl; ctl = inb( PARALLEL_PORT_ADDR_CONTROL); // is control write only? printk("read ctl register before initializing 0x%04x\n",ctl); ctl = (ctl & 0xf0) | 0x4; // initialize control register outb(ctl, PARALLEL_PORT_ADDR_CONTROL); ctl = inb( PARALLEL_PORT_ADDR_CONTROL); // is control write only? printk("read ctl register after initializing 0x%04x\n",ctl); ctl = inb( PARALLEL_PORT_ADDR_CONTROL); // is control write only? printk("read ctl register before clearing bit-5 for forward/output direction 0x%04x\n",ctl); //ctl = (ctl & 0xef); // clear bit-5 register for output ctl = (ctl & 0xef) | 0x10; // set bit-5 register outb(ctl, PARALLEL_PORT_ADDR_CONTROL); ctl = inb( PARALLEL_PORT_ADDR_CONTROL); // is control write only? printk("after ctl register before clearing bit-5 for forward/output direction 0x%04x\n",ctl); if (clear_timeout() < 0) { printk("failed to clear timeout bit\n"); } return 0; }
ssize_t trigger_read(struct file *filep, char *buf, size_t count, loff_t * ppos) { ssize_t copied; while (!interrupt_ready) { if (filep->f_flags & O_NONBLOCK) return -EAGAIN; if (signal_pending(current)) return -ERESTARTSYS; // sleep until a condition gets true wait_event_interruptible(waitq,interrupt_ready); } if ( clear_timeout() < 0) { printk("failed to clear timeout bit\n"); } //trigger_info.mask = inb_p(PARALLEL_PORT_ADDR_STATUS); //printk(">>> PARALLEL PORT read: interrupt %i, status register: 0x%08x\n",interrupt_count,trigger_info.mask); //trigger_info.mask = inb_p(PARALLEL_PORT_ADDR_CONTROL); //printk(">>> PARALLEL PORT read: interrupt %i, control register: 0x%08x\n",interrupt_count,trigger_info.mask); //trigger_info.mask = inb_p(PARALLEL_PORT_ADDR_EPP_ADDR); //printk(">>> PARALLEL PORT read: interrupt %i, epp address: 0x%08x\n",interrupt_count,trigger_info.mask); //trigger_info.mask = inb(PARALLEL_PORT_ADDR_EPP_DATA); // read epp data //trigger_info.mask = inb(PARALLEL_PORT_ADDR_BASE); //read spp data //printk(">>> PARALLEL PORT read: interrupt %i, epp data: 0x%08x\n",interrupt_count,trigger_info.mask); trigger_info.irq = IRQ; trigger_info.trigger_nr = interrupt_count; if ( copy_to_user(buf, &trigger_info, sizeof(trigger_info)) != 0 ) { printk("***ERROR! Trigger was unable to copy data to user space"); copied = 0; } else copied = sizeof(trigger_info); interrupt_ready = 0; return copied; }
// The modem has closed, cleanup and send event int uart_recv_closed(uart_ctx_t* ctx) { DEBUGF("uart_recv_closed(%ld)", (long) ctx->port); clear_timeout(ctx); uart_buf_reset(&ctx->ib); close_device(ctx); if (!ctx->option.active) { uart_async_error_am(ctx, ctx->dport, ctx->caller, am_closed); } else { uart_closed_message(ctx); } return -1; }
// // We have a read error determine the action // int uart_recv_error(uart_ctx_t* ctx, int err) { if (err != EAGAIN) { clear_timeout(ctx); uart_buf_reset(&ctx->ib); close_device(ctx); if (!ctx->option.active) { uart_async_error(ctx, ctx->dport, ctx->caller, err); } else { uart_error_message(ctx, err); // first error uart_closed_message(ctx); /* then closed */ } return -1; } return 0; }
void close_win_status() { if (!clear_timeout()) return; gtk_widget_hide(win_screen_status); }
/* Show the menu and handle menu entry selection. Returns the menu entry index that should be executed or -1 if no entry should be executed (e.g., Esc pressed to exit a sub-menu or switching menu viewers). If the return value is not -1, then *AUTO_BOOT is nonzero iff the menu entry to be executed is a result of an automatic default selection because of the timeout. */ static int run_menu (grub_menu_t menu, int nested, int *auto_boot) { grub_uint64_t saved_time; int default_entry, current_entry; int timeout; default_entry = get_entry_number (menu, "default"); /* If DEFAULT_ENTRY is not within the menu entries, fall back to the first entry. */ if (default_entry < 0 || default_entry >= menu->size) default_entry = 0; /* If timeout is 0, drawing is pointless (and ugly). */ if (grub_menu_get_timeout () == 0) { *auto_boot = 1; return default_entry; } current_entry = default_entry; /* Initialize the time. */ saved_time = grub_get_time_ms (); refresh: menu_init (current_entry, menu, nested); timeout = grub_menu_get_timeout (); if (timeout > 0) menu_print_timeout (timeout); else clear_timeout (); while (1) { int c; timeout = grub_menu_get_timeout (); if (grub_normal_exit_level) return -1; if (timeout > 0) { grub_uint64_t current_time; current_time = grub_get_time_ms (); if (current_time - saved_time >= 1000) { timeout--; grub_menu_set_timeout (timeout); saved_time = current_time; menu_print_timeout (timeout); } } if (timeout == 0) { grub_env_unset ("timeout"); *auto_boot = 1; menu_fini (); return default_entry; } c = grub_getkey_noblock (); if (c != GRUB_TERM_NO_KEY) { if (timeout >= 0) { grub_env_unset ("timeout"); grub_env_unset ("fallback"); clear_timeout (); } switch (c) { case GRUB_TERM_KEY_HOME: case GRUB_TERM_CTRL | 'a': current_entry = 0; menu_set_chosen_entry (current_entry); break; case GRUB_TERM_KEY_END: case GRUB_TERM_CTRL | 'e': current_entry = menu->size - 1; menu_set_chosen_entry (current_entry); break; case GRUB_TERM_KEY_UP: case GRUB_TERM_CTRL | 'p': case '^': if (current_entry > 0) current_entry--; menu_set_chosen_entry (current_entry); break; case GRUB_TERM_CTRL | 'n': case GRUB_TERM_KEY_DOWN: case 'v': if (current_entry < menu->size - 1) current_entry++; menu_set_chosen_entry (current_entry); break; case GRUB_TERM_CTRL | 'g': case GRUB_TERM_KEY_PPAGE: if (current_entry < GRUB_MENU_PAGE_SIZE) current_entry = 0; else current_entry -= GRUB_MENU_PAGE_SIZE; menu_set_chosen_entry (current_entry); break; case GRUB_TERM_CTRL | 'c': case GRUB_TERM_KEY_NPAGE: if (current_entry + GRUB_MENU_PAGE_SIZE < menu->size) current_entry += GRUB_MENU_PAGE_SIZE; else current_entry = menu->size - 1; menu_set_chosen_entry (current_entry); break; case '\n': case '\r': case GRUB_TERM_KEY_RIGHT: case GRUB_TERM_CTRL | 'f': menu_fini (); *auto_boot = 0; return current_entry; case '\e': if (nested) { menu_fini (); return -1; } break; case 'c': menu_fini (); grub_cmdline_run (1); goto refresh; case 'e': menu_fini (); { grub_menu_entry_t e = grub_menu_get_entry (menu, current_entry); if (e) grub_menu_entry_run (e); } goto refresh; default: { grub_menu_entry_t entry; int i; for (i = 0, entry = menu->entry_list; i < menu->size; i++, entry = entry->next) if (entry->hotkey == c) { menu_fini (); *auto_boot = 0; return i; } } break; } } } /* Never reach here. */ }
/* ** Deliver packet ready ** if len == 0 then check start with a check for ready packet */ int uart_deliver(uart_ctx_t* ctx, int len) { int count = 0; int n; DEBUGF("uart_deliver(%ld): s=%ld about to deliver %d bytes...", (long)ctx->port, (long)ctx->fd, len); /* Poll for ready packet */ if (len == 0) { /* empty buffer or waiting for more input */ if ((ctx->ib.base == NULL) || (ctx->remain > 0)) return count; n = uart_buf_remain(&ctx->ib, &len, ctx->option.htype, ctx->option.psize, ctx->option.eolchar); if (n != 0) { if (n < 0) /* packet error */ return n; if (len > 0) /* more data pending */ ctx->remain = len; return count; } } if (len > 0) { int code; code = uart_reply_data(ctx, (char*) ctx->ib.ptr_start, len); clear_timeout(ctx); /* XXX The buffer gets thrown away on error (code < 0) */ /* Windows needs workaround for this in uart_uart_event... */ if (code < 0) return code; ctx->ib.ptr_start += len; if (ctx->ib.ptr_start == ctx->ib.ptr) uart_buf_reset(&ctx->ib); else ctx->remain = 0; } count++; len = 0; if (!ctx->option.active) { if (ctx->ib.base != NULL) uart_buf_restart(&ctx->ib); } else if (ctx->ib.base != NULL) { n = uart_buf_remain(&ctx->ib, &len, ctx->option.htype, ctx->option.psize, ctx->option.eolchar); if (n != 0) { if (n < 0) /* packet error */ return n; uart_buf_restart(&ctx->ib); if (len > 0) ctx->remain = len; len = 0; } } return count; }
// thread main! int uart_unix_main(void* arg) { dthread_t* self = (dthread_t*) arg; dthread_t* other = (dthread_t*) self->arg; dmessage_t* mp = NULL; dthread_poll_event_t ev, *evp; size_t nev; dterm_t term; uart_ctx_t ctx; ErlDrvTermData mp_from; ErlDrvTermData mp_ref; dthread_t* mp_source; int tmo; int r; DEBUGF("uart_unix: thread started"); uart_init(&ctx, self, other); dterm_init(&term); again_tmo: tmo = next_timeout(&ctx); again: nev = 0; evp = NULL; if (ctx.fd >= 0) { ev.event = (ErlDrvEvent) ((long)ctx.fd); ev.events = 0; if ((ctx.option.active != UART_PASSIVE) || ctx.recv) { ev.events |= ERL_DRV_READ; if (ctx.option.ptypkt && (ctx.fd != ctx.tty_fd)) ev.events |= ERL_DRV_EXCEP; } if (ctx.oq.mesg) ev.events |= ERL_DRV_WRITE; if (ev.events) { evp = &ev; nev = 1; } DEBUGF("ctx.fd=%d, ev.events=%d", ctx.fd, ev.events); } DEBUGF("uart_unix_main: nev=%d, events=%x, timeout = %d", nev, ev.events, tmo); r = dthread_poll(self, evp, &nev, tmo); if (r < 0) { DEBUGF("uart_unix_main: dthread_poll failed=%d", r); goto again_tmo; } else { DEBUGF("uart_unix_main: nev=%d, r=%d", nev, r); if (evp && (nev == 1)) { if (evp->revents & ERL_DRV_WRITE) process_output(&ctx, self); if (evp->revents & (ERL_DRV_READ|ERL_DRV_EXCEP)) { while((process_input(&ctx, self, 0) == 1) && (ctx.option.active != UART_PASSIVE)) ; } } tmo = next_timeout(&ctx); DEBUGF("uart_unix_main: timeout = %d", tmo); if (ctx.recv) { if (tmo == 0) { uart_async_error_am(&ctx, ctx.dport, ctx.caller, am_timeout); clear_timeout(&ctx); ctx.remain = 0; } } if (r == 0) goto again; // r>0 (number of messages) DEBUGF("about to receive message r=%d", r); if ((mp = dthread_recv(self, NULL)) == NULL) { DEBUGF("uart_unix_main: message was NULL"); goto again; } mp_from = mp->from; mp_ref = mp->ref; mp_source = mp->source; switch (mp->cmd) { case DTHREAD_STOP: DEBUGF("uart_unix_main: STOP"); close_device(&ctx); uart_final(&ctx); dmessage_free(mp); DEBUGF("uart_unix_main: EXIT"); dthread_exit(0); break; case DTHREAD_OUTPUT: // async send! DEBUGF("uart_unix_main: OUTPUT"); if (ctx.fd < 0) { dmessage_free(mp); goto again; } if (enq_output(&ctx, self, mp, 0) < 0) { mp = NULL; goto error; } goto again; case UART_CMD_CONNECT: { ErlDrvTermData owner; if (mp->used != 0) goto badarg; owner = driver_connected(self->port); self->owner = owner; other->owner = owner; goto ok; } case UART_CMD_CLOSE: DEBUGF("uart_unix_main: CLOSE"); close_device(&ctx); goto ok; case UART_CMD_SEND: // sync send DEBUGF("uart_unix_main: SEND"); if (ctx.fd < 0) goto ebadf; if (enq_output(&ctx, self, mp, mp_from) < 0) { mp = NULL; goto error; } goto again; case UART_CMD_SENDCHAR: // sync send DEBUGF("uart_unix_main: SENDCHAR"); if (ctx.fd < 0) goto ebadf; if (enq_output(&ctx, self, mp, mp_from) < 0) { mp = NULL; goto error; } goto again; case UART_CMD_RECV: { // <<Time:32, Length:32>> Time=0xffffffff=inf uint32_t tm; int len; DEBUGF("uart_unix_main: RECV"); if (ctx.fd < 0) goto ebadf; if (ctx.recv) goto ealready; if (mp->used != 8) goto badarg; if (ctx.option.active != UART_PASSIVE) goto badarg; tm = get_uint32((uint8_t*) mp->buffer); len = (int) get_uint32((uint8_t*) (mp->buffer+4)); if ((len < 0) || (len > UART_MAX_PACKET_SIZE)) goto badarg; ctx.ref = mp_ref; ctx.caller = mp_from; set_timeout(&ctx, tm); ctx.recv = 1; DEBUGF("recv timeout %lu", tm); process_input(&ctx, self, len); dmessage_free(mp); goto again_tmo; } case UART_CMD_UNRECV: { // argument is data to push back uart_buf_push(&ctx.ib, mp->buffer, mp->used); DEBUGF("unrecived %d bytes", ctx.ib.ptr - ctx.ib.ptr_start); if (ctx.option.active != UART_PASSIVE) { while((process_input(&ctx, self, 0) == 1) && (ctx.option.active != UART_PASSIVE)) ; } goto ok; } case UART_CMD_SETOPTS: { uart_com_state_t state = ctx.state; uart_opt_t option = ctx.option; uint32_t sflags = ctx.sflags; // parse & update options in state,option and sflag if (uart_parse_opts(mp->buffer, mp->used, &state, &option, &sflags) < 0) goto badarg; // apply the changed values if ((r=apply_opts(&ctx, &state, &option, sflags)) < 0) goto error; if (r == 1) { while((process_input(&ctx, self, 0) == 1) && (ctx.option.active != UART_PASSIVE)) ; } goto ok; } case UART_CMD_GETOPTS: { dterm_mark_t m1; dterm_mark_t m2; // {Ref, {ok,List}} || {Ref, {error,Reason}} dterm_tuple_begin(&term, &m1); { dterm_uint(&term, mp_ref); dterm_tuple_begin(&term, &m2); { dterm_atom(&term, am_ok); if (uart_get_opts(&term, &ctx,(uint8_t*)mp->buffer,mp->used) < 0) { dterm_reset(&term); goto badarg; } } dterm_tuple_end(&term, &m2); } dterm_tuple_end(&term, &m1); dthread_port_send_dterm(mp_source, self, mp_from, &term); dterm_reset(&term); dmessage_free(mp); goto again; } case UART_CMD_GET_MODEM: { dterm_mark_t m1; dterm_mark_t m2; uart_modem_state_t mstate; if (ctx.tty_fd < 0) goto ebadf; if (get_modem_state(ctx.tty_fd, &mstate) < 0) goto error; dterm_tuple_begin(&term, &m1); { dterm_uint(&term, mp_ref); dterm_tuple_begin(&term, &m2); { dterm_atom(&term, am_ok); modem_state_dterm(&term, mstate); } dterm_tuple_end(&term, &m2); } dterm_tuple_end(&term, &m1); dthread_port_send_dterm(mp_source, self, mp_from, &term); dterm_reset(&term); dmessage_free(mp); goto again; } case UART_CMD_SET_MODEM: { uart_modem_state_t mstate; if (ctx.tty_fd < 0) goto ebadf; if (mp->used != 4) goto badarg; mstate = (uart_modem_state_t) get_uint32((uint8_t*) mp->buffer); if (set_modem_state(ctx.tty_fd, mstate, 1) < 0) goto error; goto ok; } case UART_CMD_CLR_MODEM: { uart_modem_state_t mstate; if (ctx.tty_fd < 0) goto ebadf; if (mp->used != 4) goto badarg; mstate = (uart_modem_state_t) get_uint32((uint8_t*) mp->buffer); if (set_modem_state(ctx.tty_fd, mstate, 0) < 0) goto error; goto ok; } case UART_CMD_HANGUP: { struct termios tio; int r; if (ctx.tty_fd < 0) goto ebadf; if (mp->used != 0) goto badarg; if ((r = tcgetattr(ctx.tty_fd, &tio)) < 0) { INFOF("tcgetattr: error=%s\n", strerror(errno)); goto badarg; } cfsetispeed(&tio, B0); cfsetospeed(&tio, B0); if ((r = tcsetattr(ctx.tty_fd, TCSANOW, &tio)) < 0) { INFOF("tcsetattr: error=%s\n", strerror(errno)); goto badarg; } goto ok; } case UART_CMD_BREAK: { int duration; if (ctx.tty_fd < 0) goto ebadf; if (mp->used != 4) goto badarg; duration = (int) get_uint32((uint8_t*) mp->buffer); if (tcsendbreak(ctx.tty_fd, duration) < 0) goto error; goto ok; } case UART_CMD_FLOW: if (ctx.tty_fd < 0) goto ebadf; if (mp->used != 1) goto badarg; switch(mp->buffer[0]) { case 0: r = tcflow(ctx.tty_fd, TCIOFF); break; case 1: r = tcflow(ctx.tty_fd, TCION); break; case 2: r = tcflow(ctx.tty_fd, TCOOFF); break; case 3: r = tcflow(ctx.tty_fd, TCOON); break; default: goto badarg; break; } if (r < 0) goto error; goto ok; default: goto badarg; } } ok: dthread_port_send_ok(mp_source, self, mp_from, mp_ref); if (mp) dmessage_free(mp); goto again; ebadf: errno = EBADF; goto error; badarg: errno = EINVAL; goto error; ealready: errno = EALREADY; goto error; error: dthread_port_send_error(mp_source, self, mp_from, mp_ref, uart_errno(&ctx)); if (mp) dmessage_free(mp); goto again; }
// thread main! int uart_win32_main(void* arg) { dthread_t* self = (dthread_t*) arg; dthread_t* other = (dthread_t*) self->arg; dmessage_t* mp = NULL; dthread_poll_event_t ev[3]; dthread_poll_event_t* evp; size_t nev; dterm_t term; uart_ctx_t ctx; ErlDrvTermData mp_from; ErlDrvTermData mp_ref; dthread_t* mp_source; int tmo; int r; DEBUGF("uart_win32: thread started"); uart_init(&ctx, self, other); dterm_init(&term); again_tmo: tmo = next_timeout(&ctx); again: nev = 0; if (ctx.writing) { ev[nev].event = (ErlDrvEvent) ctx.out.hEvent; ev[nev].events = ERL_DRV_READ; // yepp, even for write nev++; } while(!ctx.reading && (ctx.recv || (ctx.option.active != UART_PASSIVE))) process_input(&ctx, self, 0); if (ctx.reading) { ev[nev].event = (ErlDrvEvent) ctx.in.hEvent; ev[nev].events = ERL_DRV_READ; nev++; } evp = nev ? &ev[0] : NULL; DEBUGF("uart_win32_main: ctx.fh=%d, nev=%u, timeout = %d", ctx.fh, nev, tmo); r = dthread_poll(self, evp, &nev, tmo); if (r < 0) { DEBUGF("uart_win32_main: dthread_poll failed=%d", r); goto again_tmo; } else { DWORD i; DEBUGF("uart_win32_main: nev=%u, r=%d", nev, r); for (i = 0; i < nev; i++) { if (ev[i].revents & ERL_DRV_READ) { if (ev[i].event == (ErlDrvEvent) ctx.in.hEvent) { while((process_input(&ctx, self, 0) == 1) && (ctx.option.active != UART_PASSIVE)) ; } else if (ev[i].event == (ErlDrvEvent) ctx.out.hEvent) { process_output(&ctx, self); } } } tmo = next_timeout(&ctx); DEBUGF("uart_win32_main: timeout = %d", tmo); if (ctx.recv) { if (tmo == 0) { uart_async_error_am(&ctx, ctx.dport, ctx.caller, am_timeout); clear_timeout(&ctx); ctx.remain = 0; } } if (r == 0) goto again; // r>0 (number of messages) DEBUGF("about to receive message r=%d", r); if ((mp = dthread_recv(self, NULL)) == NULL) { DEBUGF("uart_win32_main: message was NULL"); goto again; } mp_from = mp->from; mp_ref = mp->ref; mp_source = mp->source; switch (mp->cmd) { case DTHREAD_STOP: DEBUGF("uart_win32_main: STOP"); close_device(&ctx); uart_final(&ctx); dmessage_free(mp); DEBUGF("uart_win32_main: EXIT"); dthread_exit(0); break; case DTHREAD_OUTPUT: // async send! DEBUGF("uart_win32_main: OUTPUT"); if (ctx.fh == INVALID_HANDLE_VALUE) { dmessage_free(mp); goto again; } if (enq_output(&ctx, self, mp, 0) < 0) { mp = NULL; goto error; } goto again; case UART_CMD_CONNECT: { ErlDrvTermData owner; if (mp->used != 0) goto badarg; owner = driver_connected(self->port); self->owner = owner; other->owner = owner; goto ok; } case UART_CMD_CLOSE: DEBUGF("uart_win32_main: CLOSE"); close_device(&ctx); goto ok; case UART_CMD_SEND: // sync send DEBUGF("uart_win32_main: SEND"); if (ctx.fh == INVALID_HANDLE_VALUE) goto ebadf; if (enq_output(&ctx, self, mp, mp_from) < 0) { mp = NULL; goto error; } goto again; case UART_CMD_SENDCHAR: // sync send DEBUGF("uart_win32_main: SENDCHAR"); if (ctx.fh == INVALID_HANDLE_VALUE) goto ebadf; if (enq_output(&ctx, self, mp, mp_from) < 0) { mp = NULL; goto error; } goto again; case UART_CMD_RECV: { // <<Time:32, Length:32>> Time=0xffffffff=inf uint32_t tm; int len; DEBUGF("uart_win32_main: RECV"); if (ctx.fh == INVALID_HANDLE_VALUE) goto ebadf; if (ctx.recv) goto ealready; if (mp->used != 8) goto badarg; if (ctx.option.active != UART_PASSIVE) goto badarg; tm = get_uint32((uint8_t*) mp->buffer); len = (int) get_uint32((uint8_t*) (mp->buffer+4)); if ((len < 0) || (len > UART_MAX_PACKET_SIZE)) goto badarg; ctx.ref = mp_ref; ctx.caller = mp_from; set_timeout(&ctx, tm); ctx.recv = 1; DEBUGF("recv timeout %lu", tm); process_input(&ctx, self, len); dmessage_free(mp); goto again_tmo; } case UART_CMD_UNRECV: { // argument is data to push back uart_buf_push(&ctx.ib, mp->buffer, mp->used); DEBUGF("unrecived %d bytes", ctx.ib.ptr - ctx.ib.ptr_start); if (ctx.option.active != UART_PASSIVE) { while((process_input(&ctx, self, 0) == 1) && (ctx.option.active != UART_PASSIVE)) ; } goto ok; } case UART_CMD_SETOPTS: { uart_com_state_t state = ctx.state; uart_opt_t option = ctx.option; uint32_t sflags = ctx.sflags; // parse & update options in state,option and sflag if (uart_parse_opts(mp->buffer, mp->used, &state, &option, &sflags) < 0) goto badarg; // apply the changed values if ((r=apply_opts(&ctx, &state, &option, sflags)) < 0) { goto error; } goto ok; } case UART_CMD_GETOPTS: { dterm_mark_t m1; dterm_mark_t m2; // {Ref, {ok,List}} || {Ref, {error,Reason}} dterm_tuple_begin(&term, &m1); { dterm_uint(&term, mp_ref); dterm_tuple_begin(&term, &m2); { dterm_atom(&term, am_ok); if (uart_get_opts(&term, &ctx,(uint8_t*)mp->buffer,mp->used) < 0) { dterm_reset(&term); goto badarg; } } dterm_tuple_end(&term, &m2); } dterm_tuple_end(&term, &m1); dthread_port_send_dterm(mp_source, self, mp_from, &term); dterm_reset(&term); dmessage_free(mp); goto again; } case UART_CMD_GET_MODEM: { dterm_mark_t m1; dterm_mark_t m2; uart_modem_state_t mstate; if (ctx.fh == INVALID_HANDLE_VALUE) goto ebadf; if (get_modem_state(ctx.fh, &mstate) < 0) goto error; dterm_tuple_begin(&term, &m1); { dterm_uint(&term, mp_ref); dterm_tuple_begin(&term, &m2); { dterm_atom(&term, am_ok); modem_state_dterm(&term, mstate); } dterm_tuple_end(&term, &m2); } dterm_tuple_end(&term, &m1); dthread_port_send_dterm(mp_source, self, mp_from, &term); dterm_reset(&term); dmessage_free(mp); goto again; } case UART_CMD_SET_MODEM: { uart_modem_state_t mstate; if (ctx.fh == INVALID_HANDLE_VALUE) goto ebadf; if (mp->used != 4) goto badarg; mstate = (uart_modem_state_t) get_uint32((uint8_t*) mp->buffer); if (set_modem_state(ctx.fh, mstate, 1) < 0) goto error; goto ok; } case UART_CMD_CLR_MODEM: { uart_modem_state_t mstate; if (ctx.fh == INVALID_HANDLE_VALUE) goto ebadf; if (mp->used != 4) goto badarg; mstate = (uart_modem_state_t) get_uint32((uint8_t*) mp->buffer); if (set_modem_state(ctx.fh, mstate, 0) < 0) goto error; goto ok; } case UART_CMD_HANGUP: { if (ctx.fh == INVALID_HANDLE_VALUE) goto ebadf; if (mp->used != 0) goto badarg; // FIXME? goto ok; } case UART_CMD_BREAK: { int duration; if (ctx.fh == INVALID_HANDLE_VALUE) goto ebadf; if (mp->used != 4) goto badarg; duration = (int) get_uint32((uint8_t*) mp->buffer); if (!EscapeCommFunction(ctx.fh, SETBREAK)) { DEBUG_ERROR("EscapeCommFunction: error %d", GetLastError()); goto error; } Sleep(duration); if (!EscapeCommFunction(ctx.fh, CLRBREAK)) { DEBUG_ERROR("EscapeCommFunction: error %d", GetLastError()); goto error; } goto ok; } case UART_CMD_FLOW: if (ctx.fh == INVALID_HANDLE_VALUE) goto ebadf; if (mp->used != 1) goto badarg; switch(mp->buffer[0]) { case 0: if (!EscapeCommFunction(ctx.fh, SETXOFF)) { DEBUG_ERROR("EscapeCommFunction: error %d", GetLastError()); goto error; } break; case 1: if (!EscapeCommFunction(ctx.fh, SETXON)) { DEBUG_ERROR("EscapeCommFunction: error %d", GetLastError()); goto error; } break; case 2: // TransmitCommChar(ctx.fh, XOFF); break; case 3: // TransmitCommChar(ctx.fh, XON); break; default: goto badarg; } goto ok; default: goto badarg; } } ok: dthread_port_send_ok(mp_source, self, mp_from, mp_ref); if (mp) dmessage_free(mp); goto again; ebadf: errno = EBADF; goto error; badarg: errno = EINVAL; goto error; ealready: errno = EBUSY; goto error; error: dthread_port_send_error(mp_source, self, mp_from, mp_ref, uart_errno(&ctx)); if (mp) dmessage_free(mp); goto again; }
/* Show the menu and handle menu entry selection. Returns the menu entry index that should be executed or -1 if no entry should be executed (e.g., Esc pressed to exit a sub-menu or switching menu viewers). If the return value is not -1, then *AUTO_BOOT is nonzero iff the menu entry to be executed is a result of an automatic default selection because of the timeout. */ static int run_menu (grub_menu_t menu, int nested, int *auto_boot) { grub_uint64_t saved_time; int default_entry, current_entry; int timeout; default_entry = get_entry_number (menu, "default"); /* If DEFAULT_ENTRY is not within the menu entries, fall back to the first entry. */ if (default_entry < 0 || default_entry >= menu->size) default_entry = 0; /* If timeout is 0, drawing is pointless (and ugly). */ if (grub_menu_get_timeout () == 0) { *auto_boot = 1; return default_entry; } current_entry = default_entry; /* Initialize the time. */ saved_time = grub_get_time_ms (); refresh: menu_init (current_entry, menu, nested); timeout = grub_menu_get_timeout (); if (timeout > 0) menu_print_timeout (timeout); else clear_timeout (); while (1) { int c; timeout = grub_menu_get_timeout (); if (grub_normal_exit_level) return -1; if (timeout > 0) { grub_uint64_t current_time; current_time = grub_get_time_ms (); if (current_time - saved_time >= 1000) { timeout--; grub_menu_set_timeout (timeout); saved_time = current_time; menu_print_timeout (timeout); } } if (timeout == 0) { grub_env_unset ("timeout"); *auto_boot = 1; menu_fini (); return default_entry; } if (grub_checkkey () >= 0 || timeout < 0) { c = GRUB_TERM_ASCII_CHAR (grub_getkey ()); if (timeout >= 0) { grub_env_unset ("timeout"); grub_env_unset ("fallback"); clear_timeout (); } switch (c) { case GRUB_TERM_HOME: current_entry = 0; menu_set_chosen_entry (current_entry); break; case GRUB_TERM_END: current_entry = menu->size - 1; menu_set_chosen_entry (current_entry); break; case GRUB_TERM_UP: case '^': if (current_entry > 0) current_entry--; menu_set_chosen_entry (current_entry); break; case GRUB_TERM_DOWN: case 'v': if (current_entry < menu->size - 1) current_entry++; menu_set_chosen_entry (current_entry); break; case GRUB_TERM_PPAGE: if (current_entry < GRUB_MENU_PAGE_SIZE) current_entry = 0; else current_entry -= GRUB_MENU_PAGE_SIZE; menu_set_chosen_entry (current_entry); break; case GRUB_TERM_NPAGE: if (current_entry + GRUB_MENU_PAGE_SIZE < menu->size) current_entry += GRUB_MENU_PAGE_SIZE; else current_entry = menu->size - 1; menu_set_chosen_entry (current_entry); break; case '\n': case '\r': case 6: menu_fini (); *auto_boot = 0; return current_entry; case '\e': if (nested) { menu_fini (); return -1; } break; case 'c': menu_fini (); grub_cmdline_run (1); goto refresh; case 'e': menu_fini (); { grub_menu_entry_t e = grub_menu_get_entry (menu, current_entry); if (e) grub_menu_entry_run (e); } goto refresh; default: break; } } }
/**************************************************************************** * child() : hold signals, notify parent and wait for parent to send signals. * If none were caught (sighold worked), release the signals one at a time * and wait for them to be caught. Send results back to parent * for processing. ***************************************************************************/ static void child() { int rv; /* return value from sighold() and sigrelse() */ int sig; /* signal value */ int exit_val; /* exit value to send to parent */ char note[MAXMESG]; /* message buffer for pipe */ char *str; phase = 1; /* tell handler that we do not want to catch signals */ /* set note to READY and if an error occurs, overwrite it */ (void)strcpy(note, READY); /* set alarm in case something hangs */ if (set_timeout() < 0) { /* an error occured - put mesg in note and send it back to parent */ (void)strcpy(note, mesg); } else if (setup_sigs() < 0) { /* an error occured - put mesg in note and send it back to parent */ (void)strcpy(note, mesg); } else { /* all set up to catch signals, now hold them */ for (sig = 1; sig < NUMSIGS; sig++) { if (choose_sig(sig)) { if ((rv = sighold(sig)) != 0) { /* THEY say sighold ALWAYS returns 0 */ (void)sprintf(note, "sighold did not return 0. rv:%d", rv); break; } } } } /* * send note to parent (if not READY, parent will BROK) and * wait for parent to send signals. The timeout clock is set so * that we will not wait forever - if sighold() did its job, we * will not receive the signals. If sighold() blew it we will * catch a signal and the interrupt handler will exit with a * value of SIG_CAUGHT. */ if (write_pipe(pipe_fd[1], note) < 0) { /* * write_pipe() failed. Set exit value to WRITE_BROK to let * parent know what happened */ clear_timeout(); exit(WRITE_BROK); } /* * if we get to this point, all signals have been held and the * timer has expired. Now what we want to do is release each * signal and see if we catch it. If we catch all signals, * sigrelse passed, else it failed. */ phase = 2; /* let handler know we are now expecting signals */ #if DEBUG > 0 printf("child: PHASE II\n"); #endif /* assume success and overwrite exit_val if an error occurs */ exit_val = EXIT_OK; #if DEBUG > 0 printf("child: pid=%d waiting for parent's ready...\n", getpid()); #endif /* * wait for parent to tell us that sigals were all sent */ /* wait for "ready" message from parent */ if ((str = read_pipe(pipe_fd2[0])) == NULL) { /* read_pipe() failed. */ printf(" child: read_pipe failed\n"); exit(TBROK); } if (strcmp(str, READY) != 0) { /* parent/pipe problem */ printf("child: didn't proper ready message\n"); exit(TBROK); } for (sig = 1; sig < NUMSIGS; sig++) { if (choose_sig(sig)) { /* all set up, release and catch a signal */ sig_caught = FALSE; /* handler sets it to TRUE when caught */ #if DEBUG > 1 printf("child: releasing sig %d...\n", sig); #endif if ((rv = sigrelse(sig)) != 0) { /* THEY say sigrelse ALWAYS returns 0 */ (void)sprintf(note, "sigrelse did not return 0. rv:%d", rv); exit_val = TBROK; break; } /* give signal handler some time to process signal */ wait_a_while (); } } /* endfor */ /* * If we are error free so far... * check the sig_array array for one occurence of * each of the catchable signals. If this is true, * then PASS, otherwise FAIL. */ if (exit_val == EXIT_OK) { (void)memcpy(note, (char *)sig_array, sizeof(sig_array)); } /* send note to parent and exit */ if (write_pipe(pipe_fd[1], note) < 0) { /* * write_pipe() failed. Set exit value to WRITE_BROK to let * parent know what happened */ exit(WRITE_BROK); } exit(exit_val); } /* end of child */