+/*----------------------------------------------------------------------*/
+/*
+** copies src to dest string up to count characters or until a character is found
+** which matches the delim string set. As the return value will be returned the next
+** address of src, which can be used for the next stnarr of NULL if the found string
+** was longer than count.
+*/
+const char *strnarr(char *dst, const char *src, const char *dlim, size_t count)
+{
+ int i;
+ for(i=0; i<count; i++) {
+ if (*src == '\0') {
+ *dst='\0';
+ return src;
+ }
+ if (strchr(dlim, *src)!=NULL) {
+ *dst='\0';
+ return ++src;
+ }
+ *dst++=*src++;
+ }
+ *--dst='\0'; /* add missing line end */
+ return NULL;
+}
+
+
+#if 0
+void parse_irqs(int nports, const char *irqstr, int irqval[])
+{
+ unsigned int i;
+ for (i=0; i<nports && irgstr; i++){
+ if (!strncmp(irqstr, "auto", 4))
+ irqval[i] = AUTO;
+ else if (!strncmp(irqstr, "none", 4))
+ irqval[i] = NONE;
+ else {
+ char *ep;
+ unsigned long r = simple_strtoul(irqstr, &ep, 0);
+ if (ep != irqstr)
+ irqval[i] = r;
+ else {
+ printk("... bad irq specifier '%s'\n", irqstr);
+ return;
+ }
+ }
+ irqstr = strchr(irqstr, ',');
+ if (irqstr) irqstr++;
+ }
+}
+#endif
+
+
+/*
+** spi parport registers SPI devices, defined by the given module load parameters.
+*/
+static int spi_parport_register_spi_devices(struct spi_parport *pp)
+{
+ const char *modalias_param=spi_modalias;
+ int i=0;
+
+ /* loop over all SPI device informations found in module parameter settings */
+ while ((modalias_param[0]!='\0') && (i<SPI_DEV_MAX)) {
+ struct spi_board_info chip; /* parport SPI board description placeholder*/
+ struct spi_device *proxy; /* just need to check spi device result and add additional settings */
+ modalias_param=strnarr(chip.modalias, modalias_param, " ,", sizeof(chip.modalias));
+ if (modalias_param==NULL) {
+ pr_err("%s: %d given modalias name is too long! See only that '%s'!\n", DRVNAME, i, chip.modalias);
+ return -EINVAL;
+ }
+
+ /*
+ * The modalias name MUST match the device_driver name
+ * for the bus glue code to match and subsequently bind them.
+ */
+ chip.max_speed_hz = SPI_PARPORT_MAX_SPEED;
+ chip.chip_select = i;
+ chip.mode = spi_mode[i];
+ chip.irq = pp->irq;
+ chip.controller_data = pp; /* enable access to primary controller data */
+ chip.platform_data = NULL; /* data area of SPI protocol driver */
+ /* chip.bus_num = master->bus_num; // not needed for spi_new_device */
+ i++; /* found new SPI protocol driver */
+
+ if (spi_mode_cnt < i) {
+ pr_warning("%s: No spi mode parameter given for device %d with driver '%s'. "
+ "Will use default setting: %d\n",
+ DRVNAME, i, chip.modalias, chip.mode);
+ }
+ pr_info("%s: Will load protocol driver: '%s' on CS%d with mode 0x%02x!\n",
+ DRVNAME, chip.modalias, chip.chip_select, chip.mode);
+
+ /*
+ * Register spi device from board info settings.
+ * Note that this will also call the probe inside the SPI protocall driver
+ */
+ proxy = spi_new_device(pp->bitbang.master, &chip);
+ if (!proxy) {
+ pr_err("%s: spi_new_device failed!\n", DRVNAME);
+ return -ENODEV;
+ }
+ if (spi_bits_cnt < i) {
+ pr_warning("%s: No spi bits per word parameter given for device %d with driver '%s'. "
+ "Will use default setting: %d\n",
+ DRVNAME, i, chip.modalias, spi_bits[i-1]);
+ }
+ proxy->bits_per_word=spi_bits[i-1];
+ pr_info("%s: SPI device successfully registered at bus %s as device %s with %d bits/word\n", DRVNAME,
+ proxy->dev.bus_id, chip.modalias, proxy->bits_per_word);
+ }
+ if (modalias_param[0]!='\0'){
+ pr_warning("%s: Found more modalias parameters of SPI devices than allowed (max: %d)!\n",
+ DRVNAME, SPI_DEV_MAX);
+ }
+ return i;
+}