Esempio n. 1
0
/*
 * 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);
  }
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
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;
	}
}
Esempio n. 4
0
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);
}
Esempio n. 5
0
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;
}
Esempio n. 6
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;

}
Esempio n. 7
0
// 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;
}
Esempio n. 8
0
//
// 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;
}
Esempio n. 9
0
void close_win_status()
{
  if (!clear_timeout())
    return;
  gtk_widget_hide(win_screen_status);
}
Esempio n. 10
0
/* 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.  */
}
Esempio n. 11
0
/*
** 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;
}
Esempio n. 12
0
// 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;
}
Esempio n. 13
0
// 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;
}
Esempio n. 14
0
/* 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;
	    }
	}
    }
Esempio n. 15
0
/****************************************************************************
 * 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 */