Exemple #1
0
static void __serial_check_fds(SERIAL_DEVICE* serial)
{
    IRP* irp;
    IRP* prev;
    SERIAL_TTY* tty;
    uint32 result = 0;

    memset(&serial->tv, 0, sizeof(struct timeval));
    tty = serial->tty;

    /* scan every pending */
    irp = list_peek(serial->pending_irps);
    while (irp)
    {
        DEBUG_SVC("MajorFunction %u", irp->MajorFunction);

        switch (irp->MajorFunction)
        {
        case IRP_MJ_READ:
            if (FD_ISSET(tty->fd, &serial->read_fds))
            {
                irp->IoStatus = STATUS_SUCCESS;
                serial_process_irp_read(serial, irp);
            }
            break;

        case IRP_MJ_WRITE:
            if (FD_ISSET(tty->fd, &serial->write_fds))
            {
                irp->IoStatus = STATUS_SUCCESS;
                serial_process_irp_write(serial, irp);
            }
            break;

        case IRP_MJ_DEVICE_CONTROL:
            if (serial_tty_get_event(tty, &result))
            {
                DEBUG_SVC("got event result %u", result);

                irp->IoStatus = STATUS_SUCCESS;
                stream_write_uint32(irp->output, result);
                irp->Complete(irp);
            }
            break;

        default:
            DEBUG_SVC("no request found");
            break;
        }

        prev = irp;
        irp = (IRP*)list_next(serial->pending_irps, irp);
        if (prev->IoStatus == STATUS_SUCCESS)
        {
            list_remove(serial->pending_irps, prev);
            wait_obj_set(serial->in_event);
        }
    }
}
Exemple #2
0
static void serial_check_for_events(SERIAL_DEVICE* serial)
{
	IRP* irp = NULL;
	IRP* prev;
	UINT32 result = 0;
	SERIAL_TTY* tty;

	tty = serial->tty;
	if(!tty)
	{
		DEBUG_WARN("tty = %p", tty);
		return;
	}

	DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps));

	irp = (IRP*) list_peek(serial->pending_irps);

	while (irp)
	{
		prev = NULL;

		if (irp->MajorFunction == IRP_MJ_DEVICE_CONTROL)
		{
			if (serial_tty_get_event(tty, &result))
			{
				DEBUG_SVC("got event result %u", result);

				irp->IoStatus = STATUS_SUCCESS;
				Stream_Write_UINT32(irp->output, result);
				irp->Complete(irp);

				prev = irp;
				irp = (IRP*) list_next(serial->pending_irps, irp);
				list_remove(serial->pending_irps, prev);
			}
		}

		if (!prev)
			irp = (IRP*) list_next(serial->pending_irps, irp);
	}

	DEBUG_SVC("[out] pending size %d", list_size(serial->pending_irps));
}
Exemple #3
0
static void __serial_check_fds(SERIAL_DEVICE* serial)
{
	IRP* irp;
	IRP* prev;
	SERIAL_TTY* tty;
	UINT32 result = 0;
	BOOL irp_completed = FALSE;

	ZeroMemory(&serial->tv, sizeof(struct timeval));
	tty = serial->tty;
	if(!tty)
	{
		DEBUG_WARN("tty = %p", tty);
		return;
	}

	/* scan every pending */
	irp = list_peek(serial->pending_irps);

	while (irp)
	{
		DEBUG_SVC("MajorFunction %u", irp->MajorFunction);

		switch (irp->MajorFunction)
		{
			case IRP_MJ_READ:
				if (FD_ISSET(tty->fd, &serial->read_fds))
				{
					irp->IoStatus = STATUS_SUCCESS;
					serial_process_irp_read(serial, irp);
					irp_completed = TRUE;
				}
				break;

			case IRP_MJ_WRITE:
				if (FD_ISSET(tty->fd, &serial->write_fds))
				{
					irp->IoStatus = STATUS_SUCCESS;
					serial_process_irp_write(serial, irp);
					irp_completed = TRUE;
				}
				break;

			case IRP_MJ_DEVICE_CONTROL:
				if (serial_tty_get_event(tty, &result))
				{
					DEBUG_SVC("got event result %u", result);

					irp->IoStatus = STATUS_SUCCESS;
					Stream_Write_UINT32(irp->output, result);
					irp->Complete(irp);
					irp_completed = TRUE;
				}
				break;

			default:
				DEBUG_SVC("no request found");
				break;
		}

		prev = irp;
		irp = (IRP*) list_next(serial->pending_irps, irp);

		if (irp_completed || (prev->IoStatus == STATUS_SUCCESS))
			list_remove(serial->pending_irps, prev);
	}
}
Exemple #4
0
UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, wStream* output, UINT32* abort_io)
{
	int purge_mask;
	UINT32 result;
	UINT32 modemstate;
	BYTE immediate;
	UINT32 ret = STATUS_SUCCESS;
	UINT32 length = 0;
	UINT32 pos;

	DEBUG_SVC("in");

	Stream_Seek(output, sizeof(UINT32));

	switch (IoControlCode)
	{
		case IOCTL_SERIAL_SET_BAUD_RATE:
			Stream_Read_UINT32(input, tty->baud_rate);
			tty_set_termios(tty);
			DEBUG_SVC("SERIAL_SET_BAUD_RATE %d", tty->baud_rate);
			break;

		case IOCTL_SERIAL_GET_BAUD_RATE:
			length = 4;
			Stream_Write_UINT32(output, tty->baud_rate);
			DEBUG_SVC("SERIAL_GET_BAUD_RATE %d", tty->baud_rate);
			break;

		case IOCTL_SERIAL_SET_QUEUE_SIZE:
			Stream_Read_UINT32(input, tty->queue_in_size);
			Stream_Read_UINT32(input, tty->queue_out_size);
			DEBUG_SVC("SERIAL_SET_QUEUE_SIZE in %d out %d", tty->queue_in_size, tty->queue_out_size);
			break;

		case IOCTL_SERIAL_SET_LINE_CONTROL:
			Stream_Read_UINT8(input, tty->stop_bits);
			Stream_Read_UINT8(input, tty->parity);
			Stream_Read_UINT8(input, tty->word_length);
			tty_set_termios(tty);
			DEBUG_SVC("SERIAL_SET_LINE_CONTROL stop %d parity %d word %d",
				tty->stop_bits, tty->parity, tty->word_length);
			break;

		case IOCTL_SERIAL_GET_LINE_CONTROL:
			DEBUG_SVC("SERIAL_GET_LINE_CONTROL");
			length = 3;
			Stream_Write_UINT8(output, tty->stop_bits);
			Stream_Write_UINT8(output, tty->parity);
			Stream_Write_UINT8(output, tty->word_length);
			break;

		case IOCTL_SERIAL_IMMEDIATE_CHAR:
			DEBUG_SVC("SERIAL_IMMEDIATE_CHAR");
			Stream_Read_UINT8(input, immediate);
			tty_write_data(tty, &immediate, 1);
			break;

		case IOCTL_SERIAL_CONFIG_SIZE:
			DEBUG_SVC("SERIAL_CONFIG_SIZE");
			length = 4;
			Stream_Write_UINT32(output, 0);
			break;

		case IOCTL_SERIAL_GET_CHARS:
			DEBUG_SVC("SERIAL_GET_CHARS");
			length = 6;
			Stream_Write(output, tty->chars, 6);
			break;

		case IOCTL_SERIAL_SET_CHARS:
			DEBUG_SVC("SERIAL_SET_CHARS");
			Stream_Read(input, tty->chars, 6);
			tty_set_termios(tty);
			break;

		case IOCTL_SERIAL_GET_HANDFLOW:
			length = 16;
			tty_get_termios(tty);
			Stream_Write_UINT32(output, tty->control);
			Stream_Write_UINT32(output, tty->xonoff);
			Stream_Write_UINT32(output, tty->onlimit);
			Stream_Write_UINT32(output, tty->offlimit);
			DEBUG_SVC("IOCTL_SERIAL_GET_HANDFLOW %X %X %X %X",
				tty->control, tty->xonoff, tty->onlimit, tty->offlimit);
			break;

		case IOCTL_SERIAL_SET_HANDFLOW:
			Stream_Read_UINT32(input, tty->control);
			Stream_Read_UINT32(input, tty->xonoff);
			Stream_Read_UINT32(input, tty->onlimit);
			Stream_Read_UINT32(input, tty->offlimit);
			DEBUG_SVC("IOCTL_SERIAL_SET_HANDFLOW %X %X %X %X",
				tty->control, tty->xonoff, tty->onlimit, tty->offlimit);
			tty_set_termios(tty);
			break;

		case IOCTL_SERIAL_SET_TIMEOUTS:
			Stream_Read_UINT32(input, tty->read_interval_timeout);
			Stream_Read_UINT32(input, tty->read_total_timeout_multiplier);
			Stream_Read_UINT32(input, tty->read_total_timeout_constant);
			Stream_Read_UINT32(input, tty->write_total_timeout_multiplier);
			Stream_Read_UINT32(input, tty->write_total_timeout_constant);

			/* http://www.codeproject.com/KB/system/chaiyasit_t.aspx, see 'ReadIntervalTimeout' section
				http://msdn.microsoft.com/en-us/library/ms885171.aspx */
			if (tty->read_interval_timeout == SERIAL_TIMEOUT_MAX)
			{
				tty->read_interval_timeout = 0;
				tty->read_total_timeout_multiplier = 0;
			}

			DEBUG_SVC("SERIAL_SET_TIMEOUTS read timeout %d %d %d",
				tty->read_interval_timeout,
				tty->read_total_timeout_multiplier,
				tty->read_total_timeout_constant);
			break;

		case IOCTL_SERIAL_GET_TIMEOUTS:
			DEBUG_SVC("SERIAL_GET_TIMEOUTS read timeout %d %d %d",
				tty->read_interval_timeout,
				tty->read_total_timeout_multiplier,
				tty->read_total_timeout_constant);
			length = 20;
			Stream_Write_UINT32(output, tty->read_interval_timeout);
			Stream_Write_UINT32(output, tty->read_total_timeout_multiplier);
			Stream_Write_UINT32(output, tty->read_total_timeout_constant);
			Stream_Write_UINT32(output, tty->write_total_timeout_multiplier);
			Stream_Write_UINT32(output, tty->write_total_timeout_constant);
			break;

		case IOCTL_SERIAL_GET_WAIT_MASK:
			DEBUG_SVC("SERIAL_GET_WAIT_MASK %X", tty->wait_mask);
			length = 4;
			Stream_Write_UINT32(output, tty->wait_mask);
			break;

		case IOCTL_SERIAL_SET_WAIT_MASK:
			Stream_Read_UINT32(input, tty->wait_mask);
			DEBUG_SVC("SERIAL_SET_WAIT_MASK %X", tty->wait_mask);
			break;

		case IOCTL_SERIAL_SET_DTR:
			DEBUG_SVC("SERIAL_SET_DTR");
			ioctl(tty->fd, TIOCMGET, &result);
			result |= TIOCM_DTR;
			ioctl(tty->fd, TIOCMSET, &result);
			tty->dtr = 1;
			break;

		case IOCTL_SERIAL_CLR_DTR:
			DEBUG_SVC("SERIAL_CLR_DTR");
			ioctl(tty->fd, TIOCMGET, &result);
			result &= ~TIOCM_DTR;
			ioctl(tty->fd, TIOCMSET, &result);
			tty->dtr = 0;
			break;

		case IOCTL_SERIAL_SET_RTS:
			DEBUG_SVC("SERIAL_SET_RTS");
			ioctl(tty->fd, TIOCMGET, &result);
			result |= TIOCM_RTS;
			ioctl(tty->fd, TIOCMSET, &result);
			tty->rts = 1;
			break;

		case IOCTL_SERIAL_CLR_RTS:
			DEBUG_SVC("SERIAL_CLR_RTS");
			ioctl(tty->fd, TIOCMGET, &result);
			result &= ~TIOCM_RTS;
			ioctl(tty->fd, TIOCMSET, &result);
			tty->rts = 0;
			break;

		case IOCTL_SERIAL_GET_MODEMSTATUS:
			modemstate = 0;
#ifdef TIOCMGET
			ioctl(tty->fd, 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
			DEBUG_SVC("SERIAL_GET_MODEMSTATUS %X", modemstate);
			length = 4;
			Stream_Write_UINT32(output, modemstate);
			break;

		case IOCTL_SERIAL_GET_COMMSTATUS:
			length = 18;
			Stream_Write_UINT32(output, 0);	/* Errors */
			Stream_Write_UINT32(output, 0);	/* Hold reasons */

			result = 0;
#ifdef TIOCINQ
			ioctl(tty->fd, TIOCINQ, &result);
#endif
			Stream_Write_UINT32(output, result); /* Amount in in queue */
			if (result)
				DEBUG_SVC("SERIAL_GET_COMMSTATUS in queue %d", result);

			result = 0;
#ifdef TIOCOUTQ
			ioctl(tty->fd, TIOCOUTQ, &result);
#endif
			Stream_Write_UINT32(output, result);	/* Amount in out queue */
			DEBUG_SVC("SERIAL_GET_COMMSTATUS out queue %d", result);

			Stream_Write_UINT8(output, 0); /* EofReceived */
			Stream_Write_UINT8(output, 0); /* WaitForImmediate */
			break;

		case IOCTL_SERIAL_PURGE:
			Stream_Read_UINT32(input, purge_mask);
			DEBUG_SVC("SERIAL_PURGE purge_mask %X", purge_mask);

		/*	See http://msdn.microsoft.com/en-us/library/ms901431.aspx
			PURGE_TXCLEAR 	Clears the output buffer, if the driver has one.
			PURGE_RXCLEAR 	Clears the input buffer, if the driver has one.

			It clearly states to clear the *driver* buffer, not the port buffer
		*/

#ifdef DEBUG_SVC
			if (purge_mask & SERIAL_PURGE_TXCLEAR)
				DEBUG_SVC("Ignoring SERIAL_PURGE_TXCLEAR");
			if (purge_mask & SERIAL_PURGE_RXCLEAR)
				DEBUG_SVC("Ignoring SERIAL_PURGE_RXCLEAR");
#endif

			if (purge_mask & SERIAL_PURGE_TXABORT)
				*abort_io |= SERIAL_ABORT_IO_WRITE;
			if (purge_mask & SERIAL_PURGE_RXABORT)
				*abort_io |= SERIAL_ABORT_IO_READ;
			break;
		case IOCTL_SERIAL_WAIT_ON_MASK:
			DEBUG_SVC("SERIAL_WAIT_ON_MASK %X", tty->wait_mask);
			tty->event_pending = 1;
			length = 4;
			if (serial_tty_get_event(tty, &result))
			{
				DEBUG_SVC("WAIT end  event = %X", result);
				Stream_Write_UINT32(output, result);
				break;
			}
			ret = STATUS_PENDING;
			break;

		case IOCTL_SERIAL_SET_BREAK_ON:
			DEBUG_SVC("SERIAL_SET_BREAK_ON");
			tcsendbreak(tty->fd, 0);
			break;

		case IOCTL_SERIAL_RESET_DEVICE:
			DEBUG_SVC("SERIAL_RESET_DEVICE");
			break;

		case IOCTL_SERIAL_SET_BREAK_OFF:
			DEBUG_SVC("SERIAL_SET_BREAK_OFF");
			break;

		case IOCTL_SERIAL_SET_XOFF:
			DEBUG_SVC("SERIAL_SET_XOFF");
			break;

		case IOCTL_SERIAL_SET_XON:
			DEBUG_SVC("SERIAL_SET_XON");
			tcflow(tty->fd, TCION);
			break;

		default:
			DEBUG_SVC("NOT FOUND IoControlCode SERIAL IOCTL %d", IoControlCode);
			return STATUS_INVALID_PARAMETER;
	}

	/* Write OutputBufferLength */
	pos = Stream_GetPosition(output);
	Stream_SetPosition(output, 16);
	Stream_Write_UINT32(output, length);
	Stream_SetPosition(output, pos);

	return ret;
}