diff options
| -rw-r--r-- | serial/manager.c | 153 | ||||
| -rw-r--r-- | serial/serial-api.txt | 11 | 
2 files changed, 160 insertions, 4 deletions
| diff --git a/serial/manager.c b/serial/manager.c index 9f3fe8d9..9043cc0c 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -1226,6 +1226,10 @@ static gboolean connect_event(GIOChannel *chan,  		return TRUE;  	} +	if (tcsetattr(tty_sk, TCSANOW, &prx->proxy_ti) < 0) +		error("Can't change serial settings: %s(%d)", +				strerror(errno), errno); +  	node_io = g_io_channel_unix_new(nsk);  	g_io_channel_set_close_on_unref(node_io, TRUE);  	tty_io = g_io_channel_unix_new(tty_sk); @@ -1374,10 +1378,153 @@ static DBusHandlerResult proxy_get_info(DBusConnection *conn,  	return send_message_and_unref(conn, reply);  } +static struct { +	const char	*str; +	speed_t		speed; +} supported_speed[]  = { +	{"50",		B50	}, +	{"300",		B300	}, +	{"600",		B600	}, +	{"1200",	B1200	}, +	{"1800",	B1800	}, +	{"2400",	B2400	}, +	{"4800",	B4800	}, +	{"9600",	B9600	}, +	{"19200",	B19200	}, +	{"38400",	B38400	}, +	{"57600",	B57600	}, +	{"115200",	B115200	}, +	{ NULL,		B0	} +}; + +static speed_t str2speed(const char *str, speed_t *speed) +{ +	int i; + +	for (i = 0; supported_speed[i].str; i++) { +		if (strcmp(supported_speed[i].str, str) != 0) +			continue; + +		if (speed) +			*speed = supported_speed[i].speed; + +		return supported_speed[i].speed; +	} + +	return B0; +} + +static int set_parity(const char *str, tcflag_t *ctrl) +{ +	if (strcasecmp("even", str) == 0) { +		*ctrl |= PARENB; +		*ctrl &= ~PARODD; +	} else if (strcasecmp("odd", str) == 0) { +		*ctrl |= PARENB; +		*ctrl |= PARODD; +	} else if (strcasecmp("mark", str) == 0) +		*ctrl |= PARENB; +	else if ((strcasecmp("none", str) == 0) || +			(strcasecmp("space", str) == 0)) +		*ctrl &= ~PARENB; +	else +		return -1; + +	return 0; +} + +static int set_databits(uint8_t databits, tcflag_t *ctrl) +{ +	if (databits < 5 || databits > 8) +		return -EINVAL; + +	*ctrl &= ~CSIZE; +	switch (databits) { +	case 5: +		*ctrl |= CS5; +		break; +	case 6: +		*ctrl |= CS6; +		break; +	case 7: +		*ctrl |= CS7; +		break; +	case 8: +		*ctrl |= CS8; +		break; +	} + +	return 0; +} + +static int set_stopbits(uint8_t stopbits, tcflag_t *ctrl) +{ +	/* 1.5 will not be allowed */ +	switch (stopbits) { +	case 1: +		*ctrl &= ~CSTOPB; +		return 0; +	case 2: +		*ctrl |= CSTOPB; +		return 0; +	} + +	return -EINVAL; +} + +static DBusHandlerResult proxy_set_serial_params(DBusConnection *conn, +						DBusMessage *msg, void *data) +{ +	DBusError derr; +	struct proxy *prx = data; +	const char *ratestr, *paritystr; +	uint8_t databits, stopbits; +	tcflag_t ctrl; 		/* Control mode flags */ +	speed_t speed = B0;	/* In/Out speed */ + +	/* Don't allow change TTY settings if it is open */ +	if (prx->tty_watch) +		return err_failed(conn, msg, "Not allowed"); + +	dbus_error_init(&derr); +	if (!dbus_message_get_args(msg, &derr, +				DBUS_TYPE_STRING, &ratestr, +				DBUS_TYPE_BYTE, &databits, +				DBUS_TYPE_BYTE, &stopbits, +				DBUS_TYPE_STRING, &paritystr, +				DBUS_TYPE_INVALID)) { +		err_invalid_args(conn, msg, derr.message); +		dbus_error_free(&derr); +		return DBUS_HANDLER_RESULT_HANDLED; +	} + +	if (str2speed(ratestr, &speed)  == B0) +		return err_invalid_args(conn, msg, "Invalid baud rate"); + +	ctrl = prx->proxy_ti.c_cflag; +	if (set_databits(databits, &ctrl) < 0) +		return err_invalid_args(conn, msg, "Invalid data bits"); + +	if (set_stopbits(stopbits, &ctrl) < 0) +		return err_invalid_args(conn, msg, "Invalid stop bits"); + +	if (set_parity(paritystr, &ctrl) < 0) +		return err_invalid_args(conn, msg, "Invalid parity"); + +	prx->proxy_ti.c_cflag = ctrl; +	prx->proxy_ti.c_cflag |= (CLOCAL | CREAD); +	cfsetispeed(&prx->proxy_ti, speed); +	cfsetospeed(&prx->proxy_ti, speed); + +	return send_message_and_unref(conn, +			dbus_message_new_method_return(msg)); +} +  static DBusMethodVTable proxy_methods[] = { -	{ "Enable",			proxy_enable,		"",	""	}, -	{ "Disable",			proxy_disable,		"",	""	}, -	{ "GetInfo",			proxy_get_info,		"",	"{sv}"	}, +	{ "Enable",			proxy_enable,			"",	""	}, +	{ "Disable",			proxy_disable,			"",	""	}, +	{ "GetInfo",			proxy_get_info,			"",	"{sv}"	}, +	{ "SetSerialParams",		proxy_set_serial_params, 	"syys",	""	},  	{ NULL, NULL, NULL, NULL },  }; diff --git a/serial/serial-api.txt b/serial/serial-api.txt index b02786e7..70e8983f 100644 --- a/serial/serial-api.txt +++ b/serial/serial-api.txt @@ -118,5 +118,14 @@ Methods:	string Enable() [experimental]  			Unregister the service record and stop listenning. -		String GetInfo() [experimental] +		string GetInfo() [experimental]  			Returns the proxy properties + +		void SetSerialParams(string rate, byte databits, +				byte stopbits, string parity) [experimental] + +			Change the TTY settings. Available rates: "50", "300", +			"600", "1200", "1800", "2400", "4800", "9600", "19200", +			"38400", "57600" and "115200". Available data bits: 5, +			6, 7 and 8. Available stop bits: 1 and 2. Available +			parity: "even", "odd", "mark", "space" and "none". | 
