[PATCH 05/14] staging: comedi: serial2002: split up serial_2002_open()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Split out the code that sets up the comedi subdevices that are
attached to the serial port.

There are actually two steps:

1) Read the configuration of the attached subdevices.
2) Use the configuration data to setup the comedi subdevices.

Step 1 is split out as serial2002_setup_subdevs().
Step 2 is split out as serial2002_setup_subdevice().

Cleanup the split out code to remove all the extra '{ }' and indents.

Signed-off-by: H Hartley Sweeten <hsweeten@xxxxxxxxxxxxxxxxxxx>
Cc: Ian Abbott <abbotti@xxxxxxxxx>
Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxx>
---
 drivers/staging/comedi/drivers/serial2002.c | 516 +++++++++++++---------------
 1 file changed, 234 insertions(+), 282 deletions(-)

diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
index 74a0bc3..b5c464e 100644
--- a/drivers/staging/comedi/drivers/serial2002.c
+++ b/drivers/staging/comedi/drivers/serial2002.c
@@ -328,311 +328,263 @@ static void serial_write(struct file *f, struct serial_data data)
 	}
 }
 
-static int serial_2002_open(struct comedi_device *dev)
+struct config_t {
+	short int kind;
+	short int bits;
+	int min;
+	int max;
+};
+
+static int serial2002_setup_subdevice(struct comedi_subdevice *s,
+				      struct config_t *cfg,
+				      struct serial2002_range_table_t *range,
+				      unsigned char *mapping,
+				      int kind)
+{
+	const struct comedi_lrange **range_table_list = NULL;
+	unsigned int *maxdata_list;
+	int j, chan;
+
+	for (chan = 0, j = 0; j < 32; j++) {
+		if (cfg[j].kind == kind)
+			chan++;
+	}
+	s->n_chan = chan;
+	s->maxdata = 0;
+	kfree(s->maxdata_list);
+	maxdata_list = kmalloc(sizeof(unsigned int) * s->n_chan, GFP_KERNEL);
+	if (!maxdata_list)
+		return -ENOMEM;
+	s->maxdata_list = maxdata_list;
+	kfree(s->range_table_list);
+	s->range_table = NULL;
+	s->range_table_list = NULL;
+	if (kind == 1 || kind == 2) {
+		s->range_table = &range_digital;
+	} else if (range) {
+		range_table_list =
+			kmalloc(sizeof(struct serial2002_range_table_t) *
+				s->n_chan, GFP_KERNEL);
+		if (!range_table_list)
+			return -ENOMEM;
+		s->range_table_list = range_table_list;
+	}
+	for (chan = 0, j = 0; j < 32; j++) {
+		if (cfg[j].kind == kind) {
+			if (mapping)
+				mapping[chan] = j;
+			if (range) {
+				range[j].length = 1;
+				range[j].range.min = cfg[j].min;
+				range[j].range.max = cfg[j].max;
+				range_table_list[chan] =
+				    (const struct comedi_lrange *)&range[j];
+			}
+			maxdata_list[chan] = ((long long)1 << cfg[j].bits) - 1;
+			chan++;
+		}
+	}
+	return 0;
+}
+
+static int serial2002_setup_subdevs(struct comedi_device *dev)
 {
 	struct serial2002_private *devpriv = dev->private;
+	struct config_t *di_cfg;
+	struct config_t *do_cfg;
+	struct config_t *ai_cfg;
+	struct config_t *ao_cfg;
+	struct config_t *cfg;
+	struct comedi_subdevice *s;
 	int result;
-	char port[20];
+	int i;
 
-	sprintf(port, "/dev/ttyS%d", devpriv->port);
-	devpriv->tty = filp_open(port, O_RDWR, 0);
-	if (IS_ERR(devpriv->tty)) {
-		result = (int)PTR_ERR(devpriv->tty);
-		dev_err(dev->class_dev, "file open error = %d\n", result);
-	} else {
-		struct config_t {
-
-			short int kind;
-			short int bits;
-			int min;
-			int max;
-		};
-
-		struct config_t *dig_in_config;
-		struct config_t *dig_out_config;
-		struct config_t *chan_in_config;
-		struct config_t *chan_out_config;
-		int i;
-
-		result = 0;
-		dig_in_config = kcalloc(32, sizeof(struct config_t),
-				GFP_KERNEL);
-		dig_out_config = kcalloc(32, sizeof(struct config_t),
-				GFP_KERNEL);
-		chan_in_config = kcalloc(32, sizeof(struct config_t),
-				GFP_KERNEL);
-		chan_out_config = kcalloc(32, sizeof(struct config_t),
-				GFP_KERNEL);
-		if (!dig_in_config || !dig_out_config
-		    || !chan_in_config || !chan_out_config) {
-			result = -ENOMEM;
-			goto err_alloc_configs;
-		}
+	result = 0;
+	di_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL);
+	do_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL);
+	ai_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL);
+	ao_cfg = kcalloc(32, sizeof(*cfg), GFP_KERNEL);
+	if (!di_cfg || !do_cfg || !ai_cfg || !ao_cfg) {
+		result = -ENOMEM;
+		goto err_alloc_configs;
+	}
 
-		tty_setspeed(devpriv->tty, devpriv->speed);
-		poll_channel(devpriv->tty, 31);	/*  Start reading configuration */
-		while (1) {
-			struct serial_data data;
+	tty_setspeed(devpriv->tty, devpriv->speed);
+	poll_channel(devpriv->tty, 31);	/*  Start reading configuration */
+	while (1) {
+		struct serial_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;
-				struct config_t *cur_config = NULL;
-
-				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;
-				}
+		data = serial_read(devpriv->tty, 1000);
+		if (data.kind != is_channel || data.index != 31 ||
+		    !(data.value & 0xe0)) {
+			break;
+		} else {
+			int channel = data.value & 0x1f;
+			int kind = (data.value >> 5) & 0x7;
+			int command = (data.value >> 8) & 0x3;
 
-				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 */
-			struct config_t *c;
-			unsigned char *mapping = NULL;
-			struct serial2002_range_table_t *range = NULL;
-			int kind = 0;
-
-			switch (i) {
-			case 0:{
-					c = dig_in_config;
-					mapping = devpriv->digital_in_mapping;
-					kind = 1;
-				}
+			switch (kind) {
+			case 1:
+				cfg = di_cfg;
 				break;
-			case 1:{
-					c = dig_out_config;
-					mapping = devpriv->digital_out_mapping;
-					kind = 2;
-				}
+			case 2:
+				cfg = do_cfg;
 				break;
-			case 2:{
-					c = chan_in_config;
-					mapping = devpriv->analog_in_mapping;
-					range = devpriv->in_range;
-					kind = 3;
-				}
+			case 3:
+				cfg = ai_cfg;
 				break;
-			case 3:{
-					c = chan_out_config;
-					mapping = devpriv->analog_out_mapping;
-					range = devpriv->out_range;
-					kind = 4;
-				}
+			case 4:
+				cfg = ao_cfg;
 				break;
-			case 4:{
-					c = chan_in_config;
-					mapping = devpriv->encoder_in_mapping;
-					range = devpriv->in_range;
-					kind = 5;
-				}
+			case 5:
+				cfg = ai_cfg;
 				break;
-			default:{
-					c = NULL;
-				}
+			default:
+				cfg = NULL;
 				break;
 			}
-			if (c) {
-				struct comedi_subdevice *s;
-				const struct 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(unsigned int) * s->n_chan,
-					    GFP_KERNEL);
-				if (!s->maxdata_list)
-					break;	/* error handled below */
-				kfree(s->range_table_list);
-				s->range_table = NULL;
-				s->range_table_list = NULL;
-				if (kind == 1 || kind == 2) {
-					s->range_table = &range_digital;
-				} else if (range) {
-					s->range_table_list = range_table_list =
-					    kmalloc(sizeof
-						    (struct
-						     serial2002_range_table_t) *
-						    s->n_chan, GFP_KERNEL);
-					if (!s->range_table_list)
-						break;	/* err 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 struct
-							     comedi_lrange *)
-							    &range[j];
-						}
-						maxdata_list[chan] =
-						    ((long long)1 << c[j].bits)
-						    - 1;
-						chan++;
+
+			if (cfg) {
+				short int bits = (data.value >> 10) & 0x3f;
+				int unit = (data.value >> 10) & 0x7;
+				int sign = (data.value >> 13) & 0x1;
+				int min = (data.value >> 14) & 0xfffff;
+				int max = min;
+
+				cfg[channel].kind = kind;
+				switch (command) {
+				case 0:
+					cfg[channel].bits = bits;
+					break;
+				case 1:
+					switch (unit) {
+					case 0:
+						min *= 1000000;
+						break;
+					case 1:
+						min *= 1000;
+						break;
+					case 2:
+						min *= 1;
+						break;
 					}
+					if (sign)
+						min = -min;
+					cfg[channel].min = min;
+					break;
+				case 2:
+					switch (unit) {
+					case 0:
+						max *= 1000000;
+						break;
+					case 1:
+						max *= 1000;
+						break;
+					case 2:
+						max *= 1;
+						break;
+					}
+					if (sign)
+						max = -max;
+					cfg[channel].max = max;
+					break;
 				}
 			}
 		}
-		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++) {
-				struct comedi_subdevice *s;
-
-				s = &dev->subdevices[i];
-				kfree(s->maxdata_list);
-				s->maxdata_list = NULL;
-				kfree(s->range_table_list);
-				s->range_table_list = NULL;
-			}
+	}
+
+	/* Fill in subdevice data */
+	for (i = 0; i <= 4; i++) {
+		unsigned char *mapping = NULL;
+		struct serial2002_range_table_t *range = NULL;
+		int kind = 0;
+
+		switch (i) {
+		case 0:
+			cfg = di_cfg;
+			mapping = devpriv->digital_in_mapping;
+			kind = 1;
+			break;
+		case 1:
+			cfg = do_cfg;
+			mapping = devpriv->digital_out_mapping;
+			kind = 2;
+			break;
+		case 2:
+			cfg = ai_cfg;
+			mapping = devpriv->analog_in_mapping;
+			range = devpriv->in_range;
+			kind = 3;
+			break;
+		case 3:
+			cfg = ao_cfg;
+			mapping = devpriv->analog_out_mapping;
+			range = devpriv->out_range;
+			kind = 4;
+			break;
+		case 4:
+			cfg = ai_cfg;
+			mapping = devpriv->encoder_in_mapping;
+			range = devpriv->in_range;
+			kind = 5;
+			break;
+		default:
+			cfg = NULL;
+			break;
 		}
 
+		if (cfg) {
+			s = &dev->subdevices[i];
+			if (serial2002_setup_subdevice(s, cfg, range, mapping,
+						       kind))
+				break;	/* err handled below */
+		}
+	}
+	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++) {
+			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, NULL);
-				devpriv->tty = NULL;
-			}
+	kfree(di_cfg);
+	kfree(do_cfg);
+	kfree(ai_cfg);
+	kfree(ao_cfg);
+
+	if (result) {
+		if (devpriv->tty) {
+			filp_close(devpriv->tty, NULL);
+			devpriv->tty = NULL;
 		}
 	}
+
+	return result;
+}
+
+static int serial_2002_open(struct comedi_device *dev)
+{
+	struct serial2002_private *devpriv = dev->private;
+	int result;
+	char port[20];
+
+	sprintf(port, "/dev/ttyS%d", devpriv->port);
+	devpriv->tty = filp_open(port, O_RDWR, 0);
+	if (IS_ERR(devpriv->tty)) {
+		result = (int)PTR_ERR(devpriv->tty);
+		dev_err(dev->class_dev, "file open error = %d\n", result);
+	} else {
+		result = serial2002_setup_subdevs(dev);
+	}
 	return result;
 }
 
-- 
1.8.1.4

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel




[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux