static int tun_ctl(ErlDrvData data, unsigned int cmd, char *buf, int len, char **rbuf, int rsize) { struct tun_state *state = (struct tun_state *)data; int read_len; switch (cmd) { case REQUEST_GET_DEVICE: return ctl_reply(REPLY_OK, state->dev, strlen(state->dev), rbuf, rsize); case REQUEST_ACTIVE: state->active = (int)*buf; switch (state->active) { case ACTIVE_FALSE: set_input(state, 0); break; case ACTIVE_TRUE: set_input(state, 1); break; case ACTIVE_ONCE: /* optimization: try to read a packet immediately if it exists, to avoid going back to select() */ read_len = read(state->fd, state->buf, TUNNEL_BUF_SIZE); if (read_len > 0) { /* got a packet */ driver_output(state->port, state->buf, read_len); state->active = ACTIVE_FALSE; set_input(state, 0); } else { /* no packet available yet */ set_input(state, 1); } break; default: assert(0); } return ctl_reply(REPLY_OK, "", 0, rbuf, rsize); default: return ctl_reply(REPLY_ERROR, "", 0, rbuf, rsize); } }
static ErlDrvSSizeT uart_drv_ctl(ErlDrvData d, unsigned int cmd, char* buf, ErlDrvSizeT len, char** rbuf, ErlDrvSizeT rsize) { drv_ctx_t* ctx = (drv_ctx_t*) d; char ref_buf[sizeof(uint32_t)]; DEBUGF("uart_drv: ctl: cmd=%u(%s), len=%d", cmd, format_command(cmd), len); ctx->self.caller = driver_caller(ctx->self.port); dthread_control(ctx->other, &ctx->self, cmd, buf, len); put_uint32((unsigned char*)ref_buf, (uint32_t) ctx->self.ref); return ctl_reply(UART_OK, ref_buf, sizeof(ref_buf), rbuf, rsize); }