diff --git a/plugins/serial2002/Makefile b/plugins/serial2002/Makefile index f5a9a0a068787f033301a726a51e9bd208aed013..a6b40eab0a8e2bb817d8bf010bd029e6a1354311 100644 --- a/plugins/serial2002/Makefile +++ b/plugins/serial2002/Makefile @@ -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 diff --git a/plugins/serial2002/serial2002.c b/plugins/serial2002/serial2002.c index 379da56e3f9f59a0a0b0683ed7925ceaaa69dcdb..79de31d1fd2ab59d8ba4486479cc4ae998211abc 100644 --- a/plugins/serial2002/serial2002.c +++ b/plugins/serial2002/serial2002.c @@ -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; } diff --git a/plugins/serial2002/serial2002_lib.c b/plugins/serial2002/serial2002_lib.c index 295b43e3003cd8a46ee1b2db3026a24ff632ae34..5fb5354ef921af459cad27c7f7094779b0acdba5 100644 --- a/plugins/serial2002/serial2002_lib.c +++ b/plugins/serial2002/serial2002_lib.c @@ -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 diff --git a/plugins/serial2002/serial2002_lib.h b/plugins/serial2002/serial2002_lib.h index f53133a0a942f16325806bc4a87e55d8dd2758a8..dc56e3e203f670ec30656400441e93f8c0725ca8 100644 --- a/plugins/serial2002/serial2002_lib.h +++ b/plugins/serial2002/serial2002_lib.h @@ -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 diff --git a/test/.config/moberg.d/00-comedi_ttyUSB0_serial.conf b/test/.config/moberg.d/00-comedi_ttyUSB0_serial.conf new file mode 100644 index 0000000000000000000000000000000000000000..22ffc4a4f2ab379574cd259c6586296de6035188 --- /dev/null +++ b/test/.config/moberg.d/00-comedi_ttyUSB0_serial.conf @@ -0,0 +1,14 @@ +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] ; +} diff --git a/test/.config/moberg.d/30-comedi_ttyUSB0_serial.conf b/test/.config/moberg.d/30-comedi_ttyUSB0_serial.conf new file mode 100644 index 0000000000000000000000000000000000000000..480bc5d06c75d52eca82eab161c1abe985fce21f --- /dev/null +++ b/test/.config/moberg.d/30-comedi_ttyUSB0_serial.conf @@ -0,0 +1,17 @@ +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] ; +}