static BOOL serial_check_fds(SERIAL_DEVICE* serial) { if (list_size(serial->pending_irps) == 0) return 1; serial_set_fds(serial); DEBUG_SVC("waiting %lu %lu", serial->tv.tv_sec, serial->tv.tv_usec); switch (select(serial->nfds + 1, &serial->read_fds, &serial->write_fds, NULL, &serial->tv)) { case -1: DEBUG_SVC("select has returned -1 with error: %s", strerror(errno)); return 0; case 0: if (serial->select_timeout) { __serial_check_fds(serial); serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_NONE, STATUS_TIMEOUT); serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_READ, STATUS_TIMEOUT); serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_WRITE, STATUS_TIMEOUT); } DEBUG_SVC("select has timed out"); return 0; default: break; } __serial_check_fds(serial); return 1; }
static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp) { char* path = NULL; int status; SERIAL_TTY* tty; UINT32 PathLength; UINT32 FileId; Stream_Seek(irp->input, 28); /* DesiredAccess(4) AllocationSize(8), FileAttributes(4) */ /* SharedAccess(4) CreateDisposition(4), CreateOptions(4) */ Stream_Read_UINT32(irp->input, PathLength); status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(irp->input), PathLength / 2, &path, 0, NULL, NULL); if (status < 1) path = (char*) calloc(1, 1); FileId = irp->devman->id_sequence++; tty = serial_tty_new(serial->path, FileId); if (tty == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; FileId = 0; DEBUG_WARN("failed to create %s", path); } else { serial->tty = tty; serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_NONE, STATUS_CANCELLED); serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_READ, STATUS_CANCELLED); serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_WRITE, STATUS_CANCELLED); serial->mthread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) serial_thread_mfunc, (void*) serial, 0, NULL); DEBUG_SVC("%s(%d) created.", serial->path, FileId); } Stream_Write_UINT32(irp->output, FileId); Stream_Write_UINT8(irp->output, 0); free(path); irp->Complete(irp); }
static void serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp) { SERIAL_TTY* tty; UINT32 IoControlCode; UINT32 InputBufferLength; UINT32 OutputBufferLength; UINT32 abort_io = SERIAL_ABORT_IO_NONE; DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps)); Stream_Read_UINT32(irp->input, InputBufferLength); Stream_Read_UINT32(irp->input, OutputBufferLength); Stream_Read_UINT32(irp->input, IoControlCode); Stream_Seek(irp->input, 20); /* Padding */ tty = serial->tty; if (!tty) { irp->IoStatus = STATUS_UNSUCCESSFUL; OutputBufferLength = 0; DEBUG_WARN("tty not valid."); } else { irp->IoStatus = serial_tty_control(tty, IoControlCode, irp->input, irp->output, &abort_io); } if (abort_io & SERIAL_ABORT_IO_WRITE) serial_abort_single_io(serial, tty->id, SERIAL_ABORT_IO_WRITE, STATUS_CANCELLED); if (abort_io & SERIAL_ABORT_IO_READ) serial_abort_single_io(serial, tty->id, SERIAL_ABORT_IO_READ, STATUS_CANCELLED); if (irp->IoStatus == STATUS_PENDING) list_enqueue(serial->pending_irps, irp); else irp->Complete(irp); }