Commit 6ca5f79f authored by Anders Blomdell's avatar Anders Blomdell
Browse files

add timeout parameter to serial_2002 driver

parent d64b6368
......@@ -17,5 +17,6 @@ build:
build/serial2002.o: ../../moberg_module.h
build/serial2002.o: serial2002_lib.h
build/serial2002_lib.o: serial2002_lib.h
build/libmoberg_serial2002.so: build/serial2002.o
build/libmoberg_serial2002.so: build/serial2002_lib.o
......@@ -47,6 +47,7 @@ struct moberg_device_context {
int count;
char *name;
int baud;
long timeout;
int fd;
} port;
struct remap_analog {
......@@ -108,14 +109,14 @@ static struct moberg_status analog_in_read(
struct moberg_channel_context *channel = &analog_in->channel_context;
struct moberg_device_context *device = channel->device;
struct serial2002_data data = { 0, 0 };
struct serial2002_data data;
struct analog_map map = device->analog_in.map[channel->index];
struct moberg_status result = serial2002_poll_channel(
device->port.fd, map.index);
if (! OK(result)) {
goto return_result;
}
result = serial2002_read(device->port.fd, 1000, &data);
result = serial2002_read(device->port.fd, device->port.timeout, &data);
if (OK(result)) {
*value = (data.value * map.delta + map.min);
}
......@@ -157,7 +158,7 @@ static struct moberg_status digital_in_read(
if (! OK(result)) {
goto return_result;
}
result = serial2002_read(device->port.fd, 1000, &data);
result = serial2002_read(device->port.fd, device->port.timeout, &data);
if (OK(result)) {
*value = data.value != 0;
}
......@@ -188,14 +189,14 @@ static struct moberg_status encoder_in_read(
struct moberg_channel_context *channel = &encoder_in->channel_context;
struct moberg_device_context *device = channel->device;
struct serial2002_data data = { 0, 0 };
struct serial2002_data data;
struct digital_map map = device->encoder_in.map[channel->index];
struct moberg_status result = serial2002_poll_channel(
device->port.fd, map.index);
if (! OK(result)) {
goto return_result;
}
result = serial2002_read(device->port.fd, 1000, &data);
result = serial2002_read(device->port.fd, device->port.timeout, &data);
if (OK(result)) {
*value = (data.value);
}
......@@ -307,7 +308,7 @@ static struct moberg_status device_open(struct moberg_device_context *device)
ioctl(fd, TIOCSSERIAL, &settings);
}
struct serial2002_config config;
result = serial2002_read_config(fd, &config);
result = serial2002_read_config(fd, device->port.timeout, &config);
if (! OK(result)) { goto err_result; }
remap_analog(&device->analog_in, SERIAL2002_ANALOG_IN,
config.channel_in, 31);
......@@ -426,6 +427,20 @@ static struct moberg_status parse_config(
if (! acceptsym(c, tok_INTEGER, &baud)) { goto syntax_err; }
if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto syntax_err; }
device->port.baud = baud.u.integer.value;
} else if (acceptkeyword(c, "timeout")) {
token_t timeout;
int multiplier = 0;
if (! acceptsym(c, tok_EQUAL, NULL)) { goto syntax_err; }
if (! acceptsym(c, tok_INTEGER, &timeout)) { goto syntax_err; }
if (acceptkeyword(c, "s")) {
multiplier = 1000000;
} else if (acceptkeyword(c, "ms")) {
multiplier = 1000;
} else if (acceptkeyword(c, "us")) {
multiplier = 1;
}
if (! acceptsym(c, tok_SEMICOLON, NULL)) { goto syntax_err; }
device->port.timeout = timeout.u.integer.value * multiplier;
} else {
goto syntax_err;
}
......
......@@ -43,7 +43,7 @@ static struct moberg_status tty_write(int fd, unsigned char *buf, int count)
return MOBERG_OK;
}
static struct moberg_status tty_read(int fd, int timeout, unsigned char *value)
static struct moberg_status tty_read(int fd, long timeout, unsigned char *value)
{
struct pollfd pollfd;
......@@ -83,8 +83,8 @@ struct moberg_status serial2002_poll_channel(int fd, int channel)
return tty_write(fd, &cmd, 1);
}
struct moberg_status serial2002_read(int f, int timeout,
struct serial2002_data *value)
struct moberg_status serial2002_read(int f, long timeout,
struct serial2002_data *value)
{
int length;
......@@ -211,6 +211,7 @@ static struct moberg_status update_channel(struct serial2002_channel *channel,
static struct moberg_status do_read_config(
int fd,
long timeout,
struct serial2002_config *config)
{
struct serial2002_data data = { 0, 0 };
......@@ -218,7 +219,7 @@ static struct moberg_status do_read_config(
memset(config, 0, sizeof(*config));
serial2002_poll_channel(fd, 31);
while (1) {
struct moberg_status result = serial2002_read(fd, 1000, &data);
struct moberg_status result = serial2002_read(fd, timeout, &data);
if (! OK(result)) { return result; }
unsigned int channel = (data.value & 0x0001f);
unsigned int kind = (data.value & 0x00e0) >> 5;
......@@ -285,9 +286,10 @@ static struct moberg_status check_config(struct serial2002_config *c)
struct moberg_status serial2002_read_config(
int fd,
long timeout,
struct serial2002_config *config)
{
struct moberg_status result = do_read_config(fd, config);
struct moberg_status result = do_read_config(fd, timeout, config);
if (OK(result)) {
result = check_config(config);
}
......@@ -295,399 +297,3 @@ struct moberg_status serial2002_read_config(
}
#if 0
static void x() {
typedef struct {
short int kind;
short int bits;
int min;
int max;
} config_t;
config_t *dig_in_config;
config_t *dig_out_config;
config_t *chan_in_config;
config_t *chan_out_config;
int i;
result = 0;
dig_in_config = kcalloc(32, sizeof(config_t), GFP_KERNEL);
dig_out_config = kcalloc(32, sizeof(config_t), GFP_KERNEL);
chan_in_config = kcalloc(32, sizeof(config_t), GFP_KERNEL);
chan_out_config = kcalloc(32, sizeof(config_t), GFP_KERNEL);
if (!dig_in_config || !dig_out_config
|| !chan_in_config || !chan_out_config) {
result = -ENOMEM;
goto err_alloc_configs;
}
tty_setspeed(devpriv->tty, devpriv->speed);
poll_channel(devpriv->tty, 31); // Start reading configuration
while (1) {
struct serial2002_data data;
data = serial_read(devpriv->tty, 1000);
if (data.kind != is_channel || data.index != 31
|| !(data.value & 0xe0)) {
break;
} else {
int command, channel, kind;
config_t *cur_config = 0;
channel = data.value & 0x1f;
kind = (data.value >> 5) & 0x7;
command = (data.value >> 8) & 0x3;
switch (kind) {
case 1:{
cur_config = dig_in_config;
}
break;
case 2:{
cur_config = dig_out_config;
}
break;
case 3:{
cur_config = chan_in_config;
}
break;
case 4:{
cur_config = chan_out_config;
}
break;
case 5:{
cur_config = chan_in_config;
}
break;
}
if (cur_config) {
cur_config[channel].kind = kind;
switch (command) {
case 0:{
cur_config[channel].
bits =
(data.
value >> 10) &
0x3f;
}
break;
case 1:{
int unit, sign, min;
unit = (data.
value >> 10) &
0x7;
sign = (data.
value >> 13) &
0x1;
min = (data.
value >> 14) &
0xfffff;
switch (unit) {
case 0:{
min = min * 1000000;
}
break;
case 1:{
min = min * 1000;
}
break;
case 2:{
min = min * 1;
}
break;
}
if (sign) {
min = -min;
}
cur_config[channel].
min = min;
}
break;
case 2:{
int unit, sign, max;
unit = (data.
value >> 10) &
0x7;
sign = (data.
value >> 13) &
0x1;
max = (data.
value >> 14) &
0xfffff;
switch (unit) {
case 0:{
max = max * 1000000;
}
break;
case 1:{
max = max * 1000;
}
break;
case 2:{
max = max * 1;
}
break;
}
if (sign) {
max = -max;
}
cur_config[channel].
max = max;
}
break;
}
}
}
}
for (i = 0; i <= 4; i++) {
// Fill in subdev data
config_t *c;
unsigned char *mapping = 0;
serial2002_range_table_t *range = 0;
int kind = 0;
switch (i) {
case 0:{
c = dig_in_config;
mapping = devpriv->digital_in_mapping;
kind = 1;
}
break;
case 1:{
c = dig_out_config;
mapping = devpriv->digital_out_mapping;
kind = 2;
}
break;
case 2:{
c = chan_in_config;
mapping = devpriv->analog_in_mapping;
range = devpriv->in_range;
kind = 3;
}
break;
case 3:{
c = chan_out_config;
mapping = devpriv->analog_out_mapping;
range = devpriv->out_range;
kind = 4;
}
break;
case 4:{
c = chan_in_config;
mapping = devpriv->encoder_in_mapping;
range = devpriv->in_range;
kind = 5;
}
break;
default:{
c = 0;
}
break;
}
if (c) {
comedi_subdevice *s;
const comedi_lrange **range_table_list = NULL;
unsigned int *maxdata_list;
int j, chan;
for (chan = 0, j = 0; j < 32; j++) {
if (c[j].kind == kind) {
chan++;
}
}
s = &dev->subdevices[i];
s->n_chan = chan;
s->maxdata = 0;
kfree(s->maxdata_list);
s->maxdata_list = maxdata_list =
kmalloc(sizeof(lsampl_t) * s->n_chan,
GFP_KERNEL);
if (!s->maxdata_list) {
break; /* error handled below */
}
kfree(s->range_table_list);
s->range_table = 0;
s->range_table_list = 0;
if (kind == 1 || kind == 2) {
s->range_table = &range_digital;
} else if (range) {
s->range_table_list = range_table_list =
kmalloc(sizeof
(serial2002_range_table_t) *
s->n_chan, GFP_KERNEL);
if (!s->range_table_list) {
break; /* error handled below */
}
}
for (chan = 0, j = 0; j < 32; j++) {
if (c[j].kind == kind) {
if (mapping) {
mapping[chan] = j;
}
if (range) {
range[j].length = 1;
range[j].range.min =
c[j].min;
range[j].range.max =
c[j].max;
range_table_list[chan] =
(const
comedi_lrange *)
&range[j];
}
maxdata_list[chan] =
((long long)1 << c[j].
bits) - 1;
chan++;
}
}
}
}
if (i <= 4) {
/* Failed to allocate maxdata_list or range_table_list
* for a subdevice that needed it. */
result = -ENOMEM;
for (i = 0; i <= 4; i++) {
comedi_subdevice *s = &dev->subdevices[i];
kfree(s->maxdata_list);
s->maxdata_list = NULL;
kfree(s->range_table_list);
s->range_table_list = NULL;
}
}
err_alloc_configs:
kfree(dig_in_config);
kfree(dig_out_config);
kfree(chan_in_config);
kfree(chan_out_config);
if (result) {
if (devpriv->tty) {
filp_close(devpriv->tty, 0);
devpriv->tty = NULL;
}
}
}
return result;
}
static int serial2002_di_rinsn(comedi_device * dev, comedi_subdevice * s,
comedi_insn * insn, lsampl_t * data)
{
int n;
int chan;
chan = devpriv->digital_in_mapping[CR_CHAN(insn->chanspec)];
for (n = 0; n < insn->n; n++) {
struct serial2002_data read;
poll_digital(devpriv->tty, chan);
while (1) {
read = serial_read(devpriv->tty, 1000);
if (read.kind != is_digital || read.index == chan) {
break;
}
}
data[n] = read.value;
}
return n;
}
static int serial2002_do_winsn(comedi_device * dev, comedi_subdevice * s,
comedi_insn * insn, lsampl_t * data)
{
int n;
int chan;
chan = devpriv->digital_out_mapping[CR_CHAN(insn->chanspec)];
for (n = 0; n < insn->n; n++) {
struct serial2002_data write;
write.kind = is_digital;
write.index = chan;
write.value = data[n];
serial_write(devpriv->tty, write);
}
return n;
}
static int serial2002_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
comedi_insn * insn, lsampl_t * data)
{
int n;
int chan;
chan = devpriv->analog_in_mapping[CR_CHAN(insn->chanspec)];
for (n = 0; n < insn->n; n++) {
struct serial2002_data read;
poll_channel(devpriv->tty, chan);
while (1) {
read = serial_read(devpriv->tty, 1000);
if (read.kind != is_channel || read.index == chan) {
break;
}
}
data[n] = read.value;
}
return n;
}
static int serial2002_ao_winsn(comedi_device * dev, comedi_subdevice * s,
comedi_insn * insn, lsampl_t * data)
{
int n;
int chan;
chan = devpriv->analog_out_mapping[CR_CHAN(insn->chanspec)];
for (n = 0; n < insn->n; n++) {
struct serial2002_data write;
write.kind = is_channel;
write.index = chan;
write.value = data[n];
serial_write(devpriv->tty, write);
devpriv->ao_readback[chan] = data[n];
}
return n;
}
static int serial2002_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
comedi_insn * insn, lsampl_t * data)
{
int n;
int chan = CR_CHAN(insn->chanspec);
for (n = 0; n < insn->n; n++) {
data[n] = devpriv->ao_readback[chan];
}
return n;
}
static int serial2002_ei_rinsn(comedi_device * dev, comedi_subdevice * s,
comedi_insn * insn, lsampl_t * data)
{
int n;
int chan;
chan = devpriv->encoder_in_mapping[CR_CHAN(insn->chanspec)];
for (n = 0; n < insn->n; n++) {
struct serial2002_data read;
poll_channel(devpriv->tty, chan);
while (1) {
read = serial_read(devpriv->tty, 1000);
if (read.kind != is_channel || read.index == chan) {
break;
}
}
data[n] = read.value;
}
return n;
}
#endif
......@@ -53,12 +53,13 @@ struct moberg_status serial2002_poll_digital(int fd, int channel);
struct moberg_status serial2002_poll_channel(int fd, int channel);
struct moberg_status serial2002_read(int fd, int timeout,
struct moberg_status serial2002_read(int fd, long timeout,
struct serial2002_data *data);
struct moberg_status serial2002_write(int fd, struct serial2002_data data);
struct moberg_status serial2002_read_config(int fd,
long timeout,
struct serial2002_config *config);
#endif
driver(serial2002) {
config {
/* Parsed by parse_config in libmoberg_serial2002.so */
device = "/dev/ttyUSB0" ;
baud = 115200 ;
}
/* Moberg mapping[indices] = {driver specific}[indices]
{driver specific} is parsed by parse_map in libmoberg_serial2002.so */
map analog_in[0:7] = analog_in[0:7] ;
map analog_out[0:7] = analog_out[0:7] ;
map digital_in[0:7] = digital_in[0:7] ;
map digital_out[0:7] = digital_out[0:7] ;
map encoder_in[0:7] = encoder_in[0:7] ;
}
driver(serial2002) {
config {
/* Parsed by parse_config in libmoberg_serial2002.so */
device = "/dev/ttyUSB0" ;
baud = 115200 ;
timeout = 1 s ;
timeout = 100 ms ;
timeout = 10000 us ;
}
/* Moberg mapping[indices] = {driver specific}[indices]
{driver specific} is parsed by parse_map in libmoberg_serial2002.so */
map analog_in[30:37] = analog_in[0:7] ;
map analog_out[30:37] = analog_out[0:7] ;
map digital_in[30:37] = digital_in[0:7] ;
map digital_out[30:37] = digital_out[0:7] ;
map encoder_in[30:37] = encoder_in[0:7] ;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment