void wl_input_wait(struct wl_input_event *ev, int sleep) { /* wl_input_wait() is called from the wikilib mainloop and we will * get here regularily when the system has no other duty. Hence, * the only thing we want to do here is go to sleep - the interrupt * sources are set up and will bring us back to life at some point */ while (1) { if (serial_get_event(ev)) { break; } if (touchscreen_get_event(ev)) { break; } if (gpio_get_event(ev)) { if (ev->key_event.value) { CTP_flush(); // flush and reset the CTP } break; } /* no power saving return */ if (!sleep) { ev->type = -1; break; } /* the timers needed for profiling don't work with suspend enabled */ #if !PROFILER_ON Temperature_control(); suspend(TIMEOUT_VALUE); #endif Temperature_control(); } }
static uint32 serial_control(IRP * irp) { int flush_mask, purge_mask; uint32 result, modemstate; uint8 immediate; int size = 0, ret = RD_STATUS_SUCCESS; SERIAL_DEVICE_INFO *info = (SERIAL_DEVICE_INFO *) irp->dev->info; char *inbuf = irp->inputBuffer; char *outbuf = NULL; /* the server commands, we obbey */ switch (irp->ioControlCode) { case IOCTL_SERIAL_SET_BAUD_RATE: info->baud_rate = GET_UINT32(inbuf, 0); set_termios(info); LLOGLN(10, ("serial_ioctl -> SERIAL_SET_BAUD_RATE %d", info->baud_rate)); break; case IOCTL_SERIAL_GET_BAUD_RATE: size = 4; outbuf = malloc(size); SET_UINT32(outbuf, 0, info->baud_rate); LLOGLN(10, ("serial_ioctl -> SERIAL_GET_BAUD_RATE %d", info->baud_rate)); break; case IOCTL_SERIAL_SET_QUEUE_SIZE: info->queue_in_size = GET_UINT32(inbuf, 0); info->queue_out_size = GET_UINT32(inbuf, 4); LLOGLN(10, ("serial_ioctl -> SERIAL_SET_QUEUE_SIZE in %d out %d", info->queue_in_size, info->queue_out_size)); break; case IOCTL_SERIAL_SET_LINE_CONTROL: info->stop_bits = GET_UINT8(inbuf, 0); info->parity = GET_UINT8(inbuf, 1); info->word_length = GET_UINT8(inbuf, 2); set_termios(info); LLOGLN(10, ("serial_ioctl -> SERIAL_SET_LINE_CONTROL stop %d parity %d word %d", info->stop_bits, info->parity, info->word_length)); break; case IOCTL_SERIAL_GET_LINE_CONTROL: LLOGLN(10, ("serial_ioctl -> SERIAL_GET_LINE_CONTROL")); size = 3; outbuf = malloc(size); SET_UINT8(outbuf, 0, info->stop_bits); SET_UINT8(outbuf, 1, info->parity); SET_UINT8(outbuf, 2, info->word_length); break; case IOCTL_SERIAL_IMMEDIATE_CHAR: LLOGLN(10, ("serial_ioctl -> SERIAL_IMMEDIATE_CHAR")); immediate = GET_UINT8(inbuf, 0); serial_write_data(irp, &immediate, 1); break; case IOCTL_SERIAL_CONFIG_SIZE: LLOGLN(10, ("serial_ioctl -> SERIAL_CONFIG_SIZE")); size = 4; outbuf = malloc(size); SET_UINT32(outbuf, 0, 0); break; case IOCTL_SERIAL_GET_CHARS: LLOGLN(10, ("serial_ioctl -> SERIAL_GET_CHARS")); size = 6; outbuf = malloc(size); memcpy(outbuf, info->chars, size); break; case IOCTL_SERIAL_SET_CHARS: LLOGLN(10, ("serial_ioctl -> SERIAL_SET_CHARS")); memcpy(info->chars, inbuf, 6); set_termios(info); break; case IOCTL_SERIAL_GET_HANDFLOW: LLOGLN(10, ("serial_ioctl -> IOCTL_SERIAL_GET_HANDFLOW")); size = 16; outbuf = malloc(size); get_termios(info); SET_UINT32(outbuf, 0, info->control); SET_UINT32(outbuf, 4, info->xonoff); SET_UINT32(outbuf, 8, info->onlimit); SET_UINT32(outbuf, 12, info->offlimit); break; case IOCTL_SERIAL_SET_HANDFLOW: info->control = GET_UINT32(inbuf, 0); info->xonoff = GET_UINT32(inbuf, 4); info->onlimit = GET_UINT32(inbuf, 8); info->offlimit = GET_UINT32(inbuf, 12); LLOGLN(10, ("serial_ioctl -> IOCTL_SERIAL_SET_HANDFLOW %x %x %x %x", info->control, info->xonoff, info->onlimit, info->onlimit)); set_termios(info); break; case IOCTL_SERIAL_SET_TIMEOUTS: info->read_interval_timeout = GET_UINT32(inbuf, 0); info->read_total_timeout_multiplier = GET_UINT32(inbuf, 4); info->read_total_timeout_constant = GET_UINT32(inbuf, 8); info->write_total_timeout_multiplier = GET_UINT32(inbuf, 12); info->write_total_timeout_constant = GET_UINT32(inbuf, 16); /* http://www.codeproject.com/KB/system/chaiyasit_t.aspx, see 'ReadIntervalTimeout' section http://msdn.microsoft.com/en-us/library/ms885171.aspx */ if (info->read_interval_timeout == SERIAL_TIMEOUT_MAX) { info->read_interval_timeout = 0; info->read_total_timeout_multiplier = 0; } LLOGLN(10, ("serial_ioctl -> SERIAL_SET_TIMEOUTS read timeout %d %d %d", info->read_interval_timeout, info->read_total_timeout_multiplier, info->read_total_timeout_constant)); break; case IOCTL_SERIAL_GET_TIMEOUTS: LLOGLN(10, ("serial_ioctl -> SERIAL_GET_TIMEOUTS read timeout %d %d %d", info->read_interval_timeout, info->read_total_timeout_multiplier, info->read_total_timeout_constant)); size = 20; outbuf = malloc(size); SET_UINT32(outbuf, 0, info->read_interval_timeout); SET_UINT32(outbuf, 4, info->read_total_timeout_multiplier); SET_UINT32(outbuf, 8, info->read_total_timeout_constant); SET_UINT32(outbuf, 12, info->write_total_timeout_multiplier); SET_UINT32(outbuf, 16, info->write_total_timeout_constant); break; case IOCTL_SERIAL_GET_WAIT_MASK: LLOGLN(10, ("serial_ioctl -> SERIAL_GET_WAIT_MASK %X", info->wait_mask)); size = 4; outbuf = malloc(size); SET_UINT32(outbuf, 0, info->wait_mask); break; case IOCTL_SERIAL_SET_WAIT_MASK: info->wait_mask = GET_UINT32(inbuf, 0); LLOGLN(10, ("serial_ioctl -> SERIAL_SET_WAIT_MASK %X", info->wait_mask)); break; case IOCTL_SERIAL_SET_DTR: LLOGLN(10, ("serial_ioctl -> SERIAL_SET_DTR")); ioctl(info->file, TIOCMGET, &result); result |= TIOCM_DTR; ioctl(info->file, TIOCMSET, &result); info->dtr = 1; break; case IOCTL_SERIAL_CLR_DTR: LLOGLN(10, ("serial_ioctl -> SERIAL_CLR_DTR")); ioctl(info->file, TIOCMGET, &result); result &= ~TIOCM_DTR; ioctl(info->file, TIOCMSET, &result); info->dtr = 0; break; case IOCTL_SERIAL_SET_RTS: LLOGLN(10, ("serial_ioctl -> SERIAL_SET_RTS")); ioctl(info->file, TIOCMGET, &result); result |= TIOCM_RTS; ioctl(info->file, TIOCMSET, &result); info->rts = 1; break; case IOCTL_SERIAL_CLR_RTS: LLOGLN(10, ("serial_ioctl -> SERIAL_CLR_RTS")); ioctl(info->file, TIOCMGET, &result); result &= ~TIOCM_RTS; ioctl(info->file, TIOCMSET, &result); info->rts = 0; break; case IOCTL_SERIAL_GET_MODEMSTATUS: modemstate = 0; #ifdef TIOCMGET ioctl(info->file, TIOCMGET, &result); if (result & TIOCM_CTS) modemstate |= SERIAL_MS_CTS; if (result & TIOCM_DSR) modemstate |= SERIAL_MS_DSR; if (result & TIOCM_RNG) modemstate |= SERIAL_MS_RNG; if (result & TIOCM_CAR) modemstate |= SERIAL_MS_CAR; if (result & TIOCM_DTR) modemstate |= SERIAL_MS_DTR; if (result & TIOCM_RTS) modemstate |= SERIAL_MS_RTS; #endif LLOGLN(10, ("serial_ioctl -> SERIAL_GET_MODEMSTATUS %X", modemstate)); size = 4; outbuf = malloc(size); SET_UINT32(outbuf, 0, modemstate); break; case IOCTL_SERIAL_GET_COMMSTATUS: size = 18; outbuf = malloc(size); SET_UINT32(outbuf, 0, 0); /* Errors */ SET_UINT32(outbuf, 4, 0); /* Hold reasons */ result = 0; #ifdef TIOCINQ ioctl(info->file, TIOCINQ, &result); #endif SET_UINT32(outbuf, 8, result); /* Amount in in queue */ if (result) LLOGLN(10, ("serial_ioctl -> SERIAL_GET_COMMSTATUS in queue %d", result)); result = 0; #ifdef TIOCOUTQ ioctl(info->file, TIOCOUTQ, &result); #endif SET_UINT32(outbuf, 12, result); /* Amount in out queue */ LLOGLN(10, ("serial_ioctl -> SERIAL_GET_COMMSTATUS out queue %d", result)); SET_UINT8(outbuf, 16, 0); /* EofReceived */ SET_UINT8(outbuf, 17, 0); /* WaitForImmediate */ break; case IOCTL_SERIAL_PURGE: purge_mask = GET_UINT32(inbuf, 0); LLOGLN(10, ("serial_ioctl -> SERIAL_PURGE purge_mask %X", purge_mask)); flush_mask = 0; if (purge_mask & SERIAL_PURGE_TXCLEAR) flush_mask |= TCOFLUSH; if (purge_mask & SERIAL_PURGE_RXCLEAR) flush_mask |= TCIFLUSH; if (flush_mask != 0) tcflush(info->file, flush_mask); if (purge_mask & SERIAL_PURGE_TXABORT) irp->abortIO |= RDPDR_ABORT_IO_WRITE; if(purge_mask & SERIAL_PURGE_RXABORT) irp->abortIO |= RDPDR_ABORT_IO_READ; break; case IOCTL_SERIAL_WAIT_ON_MASK: LLOGLN(10, ("serial_ioctl -> SERIAL_WAIT_ON_MASK %X", info->wait_mask)); info->event_pending = 1; if (serial_get_event(irp, &result)) { size = 4; outbuf = malloc(size); LLOGLN(10, ("WAIT end event = %x", result)); SET_UINT32(outbuf, 0, result); break; } irp->outputBufferLength = 4; ret = RD_STATUS_PENDING; break; case IOCTL_SERIAL_SET_BREAK_ON: LLOGLN(10, ("serial_ioctl -> SERIAL_SET_BREAK_ON")); tcsendbreak(info->file, 0); break; case IOCTL_SERIAL_RESET_DEVICE: LLOGLN(10, ("serial_ioctl -> SERIAL_RESET_DEVICE")); break; case IOCTL_SERIAL_SET_BREAK_OFF: LLOGLN(10, ("serial_ioctl -> SERIAL_SET_BREAK_OFF")); break; case IOCTL_SERIAL_SET_XOFF: LLOGLN(10, ("serial_ioctl -> SERIAL_SET_XOFF")); break; case IOCTL_SERIAL_SET_XON: LLOGLN(10, ("serial_ioctl -> SERIAL_SET_XON")); tcflow(info->file, TCION); break; default: LLOGLN(10, ("NOT FOUND IoControlCode SERIAL IOCTL %d", irp->ioControlCode)); return RD_STATUS_INVALID_PARAMETER; } irp->outputBuffer = outbuf; irp->outputBufferLength = size; return ret; }
/* Check if select() returned with one of the rdpdr file descriptors, and complete io if it did */ static void _rdpdr_check_fds(RDPCLIENT * This, fd_set * rfds, fd_set * wfds, BOOL timed_out) { NTSTATUS status; uint32 result = 0; DEVICE_FNS *fns; struct async_iorequest *iorq; struct async_iorequest *prev; uint32 req_size = 0; uint32 buffer_len; struct stream out; uint8 *buffer = NULL; if (timed_out) { /* check serial iv_timeout */ iorq = This->iorequest; prev = NULL; while (iorq != NULL) { if (iorq->fd == This->min_timeout_fd) { if ((iorq->partial_len > 0) && (This->rdpdr_device[iorq->device].device_type == DEVICE_TYPE_SERIAL)) { /* iv_timeout between 2 chars, send partial_len */ /*printf("RDPDR: IVT total %u bytes read of %u\n", iorq->partial_len, iorq->length); */ rdpdr_send_completion(This, iorq->device, iorq->id, STATUS_SUCCESS, iorq->partial_len, iorq->buffer, iorq->partial_len); iorq = rdpdr_remove_iorequest(This, prev, iorq); return; } else { break; } } else { break; } prev = iorq; if (iorq) iorq = iorq->next; } rdpdr_abort_io(This, This->min_timeout_fd, 0, STATUS_TIMEOUT); return; } iorq = This->iorequest; prev = NULL; while (iorq != NULL) { if (iorq->fd != 0) { switch (iorq->major) { case IRP_MJ_READ: if (FD_ISSET(iorq->fd, rfds)) { /* Read the data */ fns = iorq->fns; req_size = (iorq->length - iorq->partial_len) > 8192 ? 8192 : (iorq->length - iorq->partial_len); /* never read larger chunks than 8k - chances are that it will block */ status = fns->read(This, iorq->fd, iorq->buffer + iorq->partial_len, req_size, iorq->offset, &result); if ((long) result > 0) { iorq->partial_len += result; iorq->offset += result; } #if WITH_DEBUG_RDP5 DEBUG(("RDPDR: %d bytes of data read\n", result)); #endif /* only delete link if all data has been transfered */ /* or if result was 0 and status success - EOF */ if ((iorq->partial_len == iorq->length) || (result == 0)) { #if WITH_DEBUG_RDP5 DEBUG(("RDPDR: AIO total %u bytes read of %u\n", iorq->partial_len, iorq->length)); #endif rdpdr_send_completion(This, iorq->device, iorq->id, status, iorq->partial_len, iorq->buffer, iorq->partial_len); iorq = rdpdr_remove_iorequest(This, prev, iorq); } } break; case IRP_MJ_WRITE: if (FD_ISSET(iorq->fd, wfds)) { /* Write data. */ fns = iorq->fns; req_size = (iorq->length - iorq->partial_len) > 8192 ? 8192 : (iorq->length - iorq->partial_len); /* never write larger chunks than 8k - chances are that it will block */ status = fns->write(This, iorq->fd, iorq->buffer + iorq->partial_len, req_size, iorq->offset, &result); if ((long) result > 0) { iorq->partial_len += result; iorq->offset += result; } #if WITH_DEBUG_RDP5 DEBUG(("RDPDR: %d bytes of data written\n", result)); #endif /* only delete link if all data has been transfered */ /* or we couldn't write */ if ((iorq->partial_len == iorq->length) || (result == 0)) { #if WITH_DEBUG_RDP5 DEBUG(("RDPDR: AIO total %u bytes written of %u\n", iorq->partial_len, iorq->length)); #endif rdpdr_send_completion(This, iorq->device, iorq->id, status, iorq->partial_len, (uint8 *) "", 1); iorq = rdpdr_remove_iorequest(This, prev, iorq); } } break; case IRP_MJ_DEVICE_CONTROL: if (serial_get_event(This, iorq->fd, &result)) { buffer = (uint8 *) xrealloc((void *) buffer, 0x14); out.data = out.p = buffer; out.size = sizeof(buffer); out_uint32_le(&out, result); result = buffer_len = out.p - out.data; status = STATUS_SUCCESS; rdpdr_send_completion(This, iorq->device, iorq->id, status, result, buffer, buffer_len); xfree(buffer); iorq = rdpdr_remove_iorequest(This, prev, iorq); } break; } } prev = iorq; if (iorq) iorq = iorq->next; } /* Check notify */ iorq = This->iorequest; prev = NULL; while (iorq != NULL) { if (iorq->fd != 0) { switch (iorq->major) { case IRP_MJ_DIRECTORY_CONTROL: if (This->rdpdr_device[iorq->device].device_type == DEVICE_TYPE_DISK) { if (This->notify_stamp) { This->notify_stamp = False; status = disk_check_notify(This, iorq->fd); if (status != STATUS_PENDING) { rdpdr_send_completion(This, iorq->device, iorq->id, status, 0, NULL, 0); iorq = rdpdr_remove_iorequest(This, prev, iorq); } } } break; } } prev = iorq; if (iorq) iorq = iorq->next; } }