public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [patch 0/5] Hotplug firmware loader for Keyspan usb-serial driver
@ 2005-04-05 19:38 Jan Harkes
  2005-04-05 19:39 ` [patch 1/5] " Jan Harkes
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Jan Harkes @ 2005-04-05 19:38 UTC (permalink / raw)
  To: Greg KH, Sam Ravnborg
  Cc: jaharkes, Dmitry Torokhov, Marcel Holtmann, linux-kernel


Here is another stab at making the keyspan firmware easily loadable with
hotplug. Differences from the previous version,

- keep the IHEX parser into a separate module.
- added a fw-y and fw-m install targets to kbuild which will install a
  driver's firmware files in /lib/modules/`uname -r`/firmware.

01 - Add lib/ihex_parser.ko.
02 - Adapt drivers/usb/serial/keyspan.ko to use request_firmware/load_ihex.
03 - Program used to dump the firmware headers to IHEX formatted files.
04 - Result of converting the firmware.
05 - Add "make install_firmware" and the related fw-$(CONFIG_FOO) stuff.

Jan



^ permalink raw reply	[flat|nested] 8+ messages in thread

* [patch 1/5] Hotplug firmware loader for Keyspan usb-serial driver
  2005-04-05 19:38 [patch 0/5] Hotplug firmware loader for Keyspan usb-serial driver Jan Harkes
@ 2005-04-05 19:39 ` Jan Harkes
  2005-04-05 20:41   ` Brian Gerst
  2005-04-05 19:39 ` [patch 2/5] " Jan Harkes
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Jan Harkes @ 2005-04-05 19:39 UTC (permalink / raw)
  To: Greg KH, Sam Ravnborg
  Cc: jaharkes, Dmitry Torokhov, Marcel Holtmann, linux-kernel

[-- Attachment #1: keyspan-ihex_parser --]
[-- Type: text/plain, Size: 6980 bytes --]


A simple Intel HEX format parser/loader.

Signed-off-by: Jan Harkes <jaharkes@cs.cmu.edu>


 include/linux/ihex_parser.h |   23 +++++
 lib/Kconfig                 |    8 +
 lib/Makefile                |    2 
 lib/ihex_parser.c           |  181 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 214 insertions(+)

Index: linux/lib/Makefile
===================================================================
--- linux.orig/lib/Makefile	2005-04-05 15:21:30.000000000 -0400
+++ linux/lib/Makefile	2005-04-05 15:21:45.000000000 -0400
@@ -34,6 +34,8 @@ obj-$(CONFIG_ZLIB_INFLATE) += zlib_infla
 obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
 obj-$(CONFIG_REED_SOLOMON) += reed_solomon/
 
+obj-$(CONFIG_IHEX_PARSER) += ihex_parser.o
+
 hostprogs-y	:= gen_crc32table
 clean-files	:= crc32table.h
 
Index: linux/lib/ihex_parser.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/lib/ihex_parser.c	2005-04-05 15:29:55.000000000 -0400
@@ -0,0 +1,181 @@
+/*
+ * Parser/loader for IHEX formatted data.
+ *
+ * Copyright (C) 2005 Jan Harkes <jaharkes@cs.cmu.edu>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License version
+ *     2 as published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/ihex_parser.h>
+
+MODULE_AUTHOR("Jan Harkes <jaharkes@cs.cmu.edu>");
+MODULE_DESCRIPTION("IHEX formatted data parser");
+MODULE_LICENSE("GPL");
+
+#ifndef QUIET
+#define dbg(msg, ...) printk(KERN_WARNING "%s: line %d: " msg, __FUNCTION__, line, ## __VA_ARGS__)
+#else
+#define dbg(msg, ...) do {} while(0)
+#endif
+
+/**
+ * nibble/hex are little helpers to parse hexadecimal numbers to a byte value
+ **/
+static __u8 nibble(const __u8 n)
+{
+       if      (n >= '0' && n <= '9') return n - '0';
+       else if (n >= 'A' && n <= 'F') return n - ('A' - 10);
+       else if (n >= 'a' && n <= 'f') return n - ('a' - 10);
+       return 0;
+}
+static __u8 hex(const __u8 *data, __u8 *crc)
+{
+       __u8 val = (nibble(data[0]) << 4) | nibble(data[1]);
+       *crc += val;
+       return val;
+}
+
+/**
+ * load_ihex:
+ *
+ * Description:
+ *     @data  is expected to point at a block of Intel HEX formatted data.
+ *     @size  is the size of the data block.
+ *
+ *     @load will be called for each record that is found in the IHEX data.
+ *
+ *     @context will be passed on to @load.
+ *
+ **/
+int load_ihex(const u8 *data, const size_t size, void *context,
+	      int (*load)(struct ihex_record *record, void *context))
+{
+	struct ihex_record *record;
+	__u32 offset = 0;
+	__u8 type, crc = 0;
+	int i, j, err = 0;
+	int line = 1;
+
+	record = kmalloc(sizeof(*record), GFP_KERNEL);
+	if (!record) {
+		dbg("Allocation failed\n");
+		return -ENOMEM;
+	}
+
+	i = 0;
+next_record:
+	/* search for the start of record character */
+	while (i < size) {
+		if (data[i] == '\n') line++;
+		if (data[i++] == ':') break;
+	}
+
+	/* Minimum record length would be about 10 characters */
+	if (i + 10 > size) {
+		dbg("Can't find valid record\n");
+		err = -EINVAL;
+		goto done;
+	}
+
+	record->len = hex(data + i, &crc);
+	i += 2;
+
+	/* now check if we have enough data to read everything */
+	if (i + 8 + (record->len * 2) > size) {
+		dbg("Not enough data to read complete record\n");
+		err = -EINVAL;
+		goto done;
+	}
+
+	record->address  = hex(data + i, &crc) << 8; i += 2;
+	record->address |= hex(data + i, &crc); i += 2;
+	record->address += offset;
+	type = hex(data + i, &crc); i += 2;
+
+	for (j = 0; j < record->len; j++, i += 2)
+		record->data[j] = hex(data + i, &crc);
+
+	/* check CRC */
+	(void)hex(data + i, &crc); i += 2;
+	if (crc != 0) {
+		dbg("CRC failure\n");
+		err = -EINVAL;
+		goto done;
+	}
+
+	/* Done reading the record */
+	switch (type) {
+	case 0:
+		/* old style EOF record? */
+		if (!record->len)
+			break;
+
+		err = load(record, context);
+		if (err < 0) {
+			dbg("Firmware load failed (err %d)\n", err);
+			break;
+		} else
+		    err = 0;
+		goto next_record;
+
+	case 1: /* End-Of-File Record */
+		if (record->address || record->len) {
+			dbg("Bad EOF record (type 01) format\n");
+			err = -EINVAL;
+		}
+		break;
+
+	case 2: /* Extended Segment Address Record (HEX86) */
+	case 4: /* Extended Linear Address Record (HEX386) */
+		if (record->address || record->len != 2) {
+			dbg("Bad HEX86/HEX386 record (type %02X)\n", type);
+			err = -EINVAL;
+			break;
+		}
+
+		/* We shouldn't really be using the offset for HEX86 because
+		 * the wraparound case is specified quite differently. */
+		offset = record->data[0] << 8 | record->data[1];
+		offset <<= (type == 2 ? 4 : 16);
+		goto next_record;
+
+	case 3: /* Start Segment Address Record */
+	case 5: /* Start Linear Address Record */
+		if (record->address || record->len != 4) {
+			dbg("Bad Start Address record (type %02X)\n", type);
+			err = -EINVAL;
+			break;
+		}
+
+		/* These records contain the CS/IP or EIP where execution
+		 * starts. Don't really know what to do with them. */
+		goto next_record;
+
+	default:
+		dbg("Unknown record (type %02X)\n", type);
+		err = -EINVAL;
+		break; /* unknown record type */
+	}
+done:
+	kfree(record);
+	return err;
+}
+
+static int __init no_init(void)
+{
+	return 0;
+}
+
+static void __exit no_exit(void)
+{
+}
+
+module_init(no_init);
+module_exit(no_exit);
+
+EXPORT_SYMBOL(load_ihex);
+
Index: linux/include/linux/ihex_parser.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/include/linux/ihex_parser.h	2005-04-05 15:21:45.000000000 -0400
@@ -0,0 +1,23 @@
+/*
+ * Definitions for parser/loader for IHEX formatted data.
+ *
+ * Copyright (C) 2005 Jan Harkes <jaharkes@cs.cmu.edu>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License version
+ *     2 as published by the Free Software Foundation.
+ */
+
+#ifndef _LINUX_IHEX_PARSER_H
+#define _LINUX_IHEX_PARSER_H
+
+struct ihex_record {
+       __u32 address;
+       __u8  len;
+       __u8  data[255];
+};
+
+int load_ihex(const u8 *data, const size_t size, void *context,
+	      int (*load)(struct ihex_record *record, void *context));
+
+#endif
Index: linux/lib/Kconfig
===================================================================
--- linux.orig/lib/Kconfig	2005-04-05 15:08:37.000000000 -0400
+++ linux/lib/Kconfig	2005-04-05 15:21:45.000000000 -0400
@@ -57,5 +57,13 @@ config REED_SOLOMON_ENC16
 config REED_SOLOMON_DEC16
 	boolean
 
+config IHEX_PARSER
+	tristate "Intel HEX formatted data parser"
+	help
+	  This option is provided for the case where no in-kernel-tree
+	  modules require IHEX parsing, but a module built outside the
+	  kernel tree does. Such modules that need to parse Intel HEX
+	  formatted data require M here.
+
 endmenu
 

--


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [patch 2/5] Hotplug firmware loader for Keyspan usb-serial driver
  2005-04-05 19:38 [patch 0/5] Hotplug firmware loader for Keyspan usb-serial driver Jan Harkes
  2005-04-05 19:39 ` [patch 1/5] " Jan Harkes
@ 2005-04-05 19:39 ` Jan Harkes
  2005-04-05 19:39 ` [patch 3/5] " Jan Harkes
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Jan Harkes @ 2005-04-05 19:39 UTC (permalink / raw)
  To: Greg KH, Sam Ravnborg
  Cc: jaharkes, Dmitry Torokhov, Marcel Holtmann, linux-kernel

[-- Attachment #1: keyspan-request_firmware --]
[-- Type: text/plain, Size: 12984 bytes --]


Convert the keyspan USB serial driver to use request_firmware and
firmware_load_ihex.

Signed-off-by: Jan Harkes <jaharkes@cs.cmu.edu>


 Kconfig   |   90 ++++--------------------------------------
 keyspan.c |  132 +++++++++++++++++++++++---------------------------------------
 keyspan.h |   84 ---------------------------------------
 3 files changed, 59 insertions(+), 247 deletions(-)

Index: linux/drivers/usb/serial/keyspan.c
===================================================================
--- linux.orig/drivers/usb/serial/keyspan.c	2005-04-05 15:08:37.000000000 -0400
+++ linux/drivers/usb/serial/keyspan.c	2005-04-05 15:23:47.000000000 -0400
@@ -28,6 +28,9 @@
 
   Change History
 
+    2005mar10	Jan Harkes
+      Use generic request_firmware/load_ihex functions.
+
     2003sep04	LPM (Keyspan) add support for new single port product USA19HS.
 				Improve setup message handling for all devices.
 
@@ -106,6 +109,8 @@
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/firmware.h>
+#include <linux/ihex_parser.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
 #include "usb-serial.h"
@@ -1165,13 +1170,28 @@ static void keyspan_close(struct usb_ser
 	port->tty = NULL;
 }
 
+static int keyspan_fw_load(struct ihex_record *record, void *arg)
+{
+	struct usb_serial *serial = (struct usb_serial *)arg;
+	int ret;
+
+	ret = ezusb_writememory(serial, record->address, record->data,
+				record->len, 0xa0);
+	if (ret < 0) {
+		dev_err(&serial->dev->dev,
+			"ezusb_writememory failed for Keyspan"
+			"firmware (%d %08X %p %d)\n",
+			ret, record->address, record->data, record->len);
+	}
+	return ret;
+}
 
 	/* download the firmware to a pre-renumeration device */
 static int keyspan_fake_startup (struct usb_serial *serial)
 {
 	int 				response;
-	const struct ezusb_hex_record 	*record;
-	char				*fw_name;
+	char				*model, fw_name[20];
+	const struct firmware		*fw;
 
 	dbg("Keyspan startup version %04x product %04x",
 	    le16_to_cpu(serial->dev->descriptor.bcdDevice),
@@ -1182,97 +1202,43 @@ static int keyspan_fake_startup (struct 
 		return(1);
 	}
 
-		/* Select firmware image on the basis of idProduct */
 	switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
-	case keyspan_usa28_pre_product_id:
-		record = &keyspan_usa28_firmware[0];
-		fw_name = "USA28";
-		break;
-
-	case keyspan_usa28x_pre_product_id:
-		record = &keyspan_usa28x_firmware[0];
-		fw_name = "USA28X";
-		break;
-
-	case keyspan_usa28xa_pre_product_id:
-		record = &keyspan_usa28xa_firmware[0];
-		fw_name = "USA28XA";
-		break;
-
-	case keyspan_usa28xb_pre_product_id:
-		record = &keyspan_usa28xb_firmware[0];
-		fw_name = "USA28XB";
-		break;
-
-	case keyspan_usa19_pre_product_id:
-		record = &keyspan_usa19_firmware[0];
-		fw_name = "USA19";
-		break;
-			     
-	case keyspan_usa19qi_pre_product_id:
-		record = &keyspan_usa19qi_firmware[0];
-		fw_name = "USA19QI";
-		break;
-			     
-	case keyspan_mpr_pre_product_id:
-		record = &keyspan_mpr_firmware[0];
-		fw_name = "MPR";
-		break;
-
-	case keyspan_usa19qw_pre_product_id:
-		record = &keyspan_usa19qw_firmware[0];
-		fw_name = "USA19QI";
-		break;
-			     
-	case keyspan_usa18x_pre_product_id:
-		record = &keyspan_usa18x_firmware[0];
-		fw_name = "USA18X";
-		break;
-			     
-	case keyspan_usa19w_pre_product_id:
-		record = &keyspan_usa19w_firmware[0];
-		fw_name = "USA19W";
-		break;
-		
-	case keyspan_usa49w_pre_product_id:
-		record = &keyspan_usa49w_firmware[0];
-		fw_name = "USA49W";
-		break;
-
-	case keyspan_usa49wlc_pre_product_id:
-		record = &keyspan_usa49wlc_firmware[0];
-		fw_name = "USA49WLC";
-		break;
-
+	case keyspan_usa18x_pre_product_id:   model = "usa18x";   break;
+	case keyspan_usa19_pre_product_id:    model = "usa19";    break;
+	case keyspan_usa19qi_pre_product_id:  model = "usa19qi";  break;
+	case keyspan_mpr_pre_product_id:      model = "mpr";      break;
+	case keyspan_usa19qw_pre_product_id:  model = "usa19qw";  break;
+	case keyspan_usa19w_pre_product_id:   model = "usa19w";   break;
+	case keyspan_usa28_pre_product_id:    model = "usa28";    break;
+	case keyspan_usa28x_pre_product_id:   model = "usa28x";   break;
+	case keyspan_usa28xa_pre_product_id:  model = "usa28xa";  break;
+	case keyspan_usa28xb_pre_product_id:  model = "usa28xb";  break;
+	case keyspan_usa49w_pre_product_id:   model = "usa49w";   break;
+	case keyspan_usa49wlc_pre_product_id: model = "usa49wlc"; break;
 	default:
-		record = NULL;
-		fw_name = "Unknown";
-		break;
+		dev_err(&serial->dev->dev, "Unknown keyspan device (%04x).\n",
+			le16_to_cpu(serial->dev->descriptor.idProduct));
+		return(1);
 	}
 
-	if (record == NULL) {
-		dev_err(&serial->dev->dev, "Required keyspan firmware image (%s) unavailable.\n", fw_name);
+	sprintf(fw_name, "keyspan-%s.fw", model);
+
+	if (request_firmware(&fw, fw_name, &serial->dev->dev) != 0) {
+		dev_err(&serial->dev->dev, "Required firmware image (%s) unavailable.\n", fw_name);
 		return(1);
 	}
 
-	dbg("Uploading Keyspan %s firmware.", fw_name);
+	dbg("Uploading Keyspan %s firmware.", model);
 
 		/* download the firmware image */
 	response = ezusb_set_reset(serial, 1);
 
-	while(record->address != 0xffff) {
-		response = ezusb_writememory(serial, record->address,
-					     (unsigned char *)record->data,
-					     record->data_size, 0xa0);
-		if (response < 0) {
-			dev_err(&serial->dev->dev, "ezusb_writememory failed for Keyspan"
-				"firmware (%d %04X %p %d)\n",
-				response, 
-				record->address, record->data, record->data_size);
-			break;
-		}
-		record++;
-	}
+	if (load_ihex(fw->data, fw->size, serial, keyspan_fw_load))
+		dev_err(&serial->dev->dev, "Firmware %s upload failed\n",
+			fw_name);
+
+	release_firmware(fw);
+
 		/* bring device out of reset. Renumeration will occur in a
 		   moment and the new device will bind to the real driver */
 	response = ezusb_set_reset(serial, 0);
@@ -1418,7 +1384,7 @@ static void keyspan_setup_urbs(struct us
 			(serial, d_details->outcont_endpoints[i], USB_DIR_OUT,
 			 port, p_priv->outcont_buffer, 64,
 			 cback->outcont_callback);
-	}	
+	}
 
 }
 
Index: linux/drivers/usb/serial/keyspan.h
===================================================================
--- linux.orig/drivers/usb/serial/keyspan.h	2005-04-05 15:08:37.000000000 -0400
+++ linux/drivers/usb/serial/keyspan.h	2005-04-05 15:21:45.000000000 -0400
@@ -99,90 +99,6 @@ static int  keyspan_usa90_send_setup	(st
 					 struct usb_serial_port *port,
 					 int reset_port);
 
-/* Struct used for firmware - increased size of data section
-   to allow Keyspan's 'C' firmware struct to be used unmodified */
-struct ezusb_hex_record {
-	__u16 address;
-	__u8 data_size;
-	__u8 data[64];
-};
-
-/* Conditionally include firmware images, if they aren't
-   included create a null pointer instead.  Current 
-   firmware images aren't optimised to remove duplicate
-   addresses in the image itself. */
-#ifdef CONFIG_USB_SERIAL_KEYSPAN_USA28
-	#include "keyspan_usa28_fw.h"
-#else
-	static const struct ezusb_hex_record *keyspan_usa28_firmware = NULL;
-#endif
-
-#ifdef CONFIG_USB_SERIAL_KEYSPAN_USA28X
-	#include "keyspan_usa28x_fw.h"
-#else
-	static const struct ezusb_hex_record *keyspan_usa28x_firmware = NULL;
-#endif
-
-#ifdef CONFIG_USB_SERIAL_KEYSPAN_USA28XA
-	#include "keyspan_usa28xa_fw.h"
-#else
-	static const struct ezusb_hex_record *keyspan_usa28xa_firmware = NULL;
-#endif
-
-#ifdef CONFIG_USB_SERIAL_KEYSPAN_USA28XB
-	#include "keyspan_usa28xb_fw.h"
-#else
-	static const struct ezusb_hex_record *keyspan_usa28xb_firmware = NULL;
-#endif
-
-#ifdef CONFIG_USB_SERIAL_KEYSPAN_USA19
-	#include "keyspan_usa19_fw.h"
-#else
-	static const struct ezusb_hex_record *keyspan_usa19_firmware = NULL;
-#endif
-
-#ifdef CONFIG_USB_SERIAL_KEYSPAN_USA19QI
-	#include "keyspan_usa19qi_fw.h"
-#else
-	static const struct ezusb_hex_record *keyspan_usa19qi_firmware = NULL;
-#endif
-
-#ifdef CONFIG_USB_SERIAL_KEYSPAN_MPR
-        #include "keyspan_mpr_fw.h"
-#else
-	static const struct ezusb_hex_record *keyspan_mpr_firmware = NULL;
-#endif
-
-#ifdef CONFIG_USB_SERIAL_KEYSPAN_USA19QW
-	#include "keyspan_usa19qw_fw.h"
-#else
-	static const struct ezusb_hex_record *keyspan_usa19qw_firmware = NULL;
-#endif
-
-#ifdef CONFIG_USB_SERIAL_KEYSPAN_USA18X
-	#include "keyspan_usa18x_fw.h"
-#else
-	static const struct ezusb_hex_record *keyspan_usa18x_firmware = NULL;
-#endif
-
-#ifdef CONFIG_USB_SERIAL_KEYSPAN_USA19W
-	#include "keyspan_usa19w_fw.h"
-#else
-	static const struct ezusb_hex_record *keyspan_usa19w_firmware = NULL;
-#endif
-
-#ifdef CONFIG_USB_SERIAL_KEYSPAN_USA49W
-	#include "keyspan_usa49w_fw.h"
-#else
-	static const struct ezusb_hex_record *keyspan_usa49w_firmware = NULL;
-#endif
-
-#ifdef CONFIG_USB_SERIAL_KEYSPAN_USA49WLC
-        #include "keyspan_usa49wlc_fw.h"
-#else
-	static const struct ezusb_hex_record *keyspan_usa49wlc_firmware = NULL;
-#endif
-
 /* Values used for baud rate calculation - device specific */
 #define	KEYSPAN_INVALID_BAUD_RATE		(-1)
 #define	KEYSPAN_BAUD_RATE_OK			(0)
Index: linux/drivers/usb/serial/Kconfig
===================================================================
--- linux.orig/drivers/usb/serial/Kconfig	2005-04-05 15:08:37.000000000 -0400
+++ linux/drivers/usb/serial/Kconfig	2005-04-05 15:21:45.000000000 -0400
@@ -239,95 +239,25 @@ config USB_SERIAL_KEYSPAN_PDA
 config USB_SERIAL_KEYSPAN
 	tristate "USB Keyspan USA-xxx Serial Driver"
 	depends on USB_SERIAL
+	select IHEX_PARSER
 	---help---
 	  Say Y here if you want to use Keyspan USB to serial converter
 	  devices.  This driver makes use of Keyspan's official firmware
-	  and was developed with their support.  You must also include
-	  firmware to support your particular device(s).
+	  and was developed with their support.  It uses hotplug to load
+	  the required firmware from /usr/lib/hotplug/firmware or
+	  /lib/firmware.
+	  
+	  However there really isn't a good way to get this firmware
+	  since the license only allows it to be distributed as part of
+	  a Linux or other Open Source operating system kernel.  So you
+	  will have to copy the firmware files from the kernel source
+	  tree (drivers/usb/serial/*.fw) to /lib/firmware yourself.
 
 	  See <http://misc.nu/hugh/keyspan.html> for more information.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called keyspan.
 
-config USB_SERIAL_KEYSPAN_MPR
-	bool "USB Keyspan MPR Firmware"
-	depends on USB_SERIAL_KEYSPAN
-	help
-	  Say Y here to include firmware for the Keyspan MPR converter.
-
-config USB_SERIAL_KEYSPAN_USA28
-	bool "USB Keyspan USA-28 Firmware"
-	depends on USB_SERIAL_KEYSPAN
-	help
-	  Say Y here to include firmware for the USA-28 converter.
-
-config USB_SERIAL_KEYSPAN_USA28X
-	bool "USB Keyspan USA-28X Firmware"
-	depends on USB_SERIAL_KEYSPAN
-	help
-	  Say Y here to include firmware for the USA-28X converter.
-	  Be sure you have a USA-28X, there are also 28XA and 28XB
-	  models, the label underneath has the actual part number.
-
-config USB_SERIAL_KEYSPAN_USA28XA
-	bool "USB Keyspan USA-28XA Firmware"
-	depends on USB_SERIAL_KEYSPAN
-	help
-	  Say Y here to include firmware for the USA-28XA converter.
-	  Be sure you have a USA-28XA, there are also 28X and 28XB
-	  models, the label underneath has the actual part number.
-
-config USB_SERIAL_KEYSPAN_USA28XB
-	bool "USB Keyspan USA-28XB Firmware"
-	depends on USB_SERIAL_KEYSPAN
-	help
-	  Say Y here to include firmware for the USA-28XB converter.
-	  Be sure you have a USA-28XB, there are also 28X and 28XA
-	  models, the label underneath has the actual part number.
-
-config USB_SERIAL_KEYSPAN_USA19
-	bool "USB Keyspan USA-19 Firmware"
-	depends on USB_SERIAL_KEYSPAN
-	help
-	  Say Y here to include firmware for the USA-19 converter.
-
-config USB_SERIAL_KEYSPAN_USA18X
-	bool "USB Keyspan USA-18X Firmware"
-	depends on USB_SERIAL_KEYSPAN
-	help
-	  Say Y here to include firmware for the USA-18X converter.
-
-config USB_SERIAL_KEYSPAN_USA19W
-	bool "USB Keyspan USA-19W Firmware"
-	depends on USB_SERIAL_KEYSPAN
-	help
-	  Say Y here to include firmware for the USA-19W converter.
-
-config USB_SERIAL_KEYSPAN_USA19QW
-	bool "USB Keyspan USA-19QW Firmware"
-	depends on USB_SERIAL_KEYSPAN
-	help
-	  Say Y here to include firmware for the USA-19QW converter.
-
-config USB_SERIAL_KEYSPAN_USA19QI
-	bool "USB Keyspan USA-19QI Firmware"
-	depends on USB_SERIAL_KEYSPAN
-	help
-	  Say Y here to include firmware for the USA-19QI converter.
-
-config USB_SERIAL_KEYSPAN_USA49W
-	bool "USB Keyspan USA-49W Firmware"
-	depends on USB_SERIAL_KEYSPAN
-	help
-	  Say Y here to include firmware for the USA-49W converter.
-
-config USB_SERIAL_KEYSPAN_USA49WLC
-	bool "USB Keyspan USA-49WLC Firmware"
-	depends on USB_SERIAL_KEYSPAN
-	help
-	  Say Y here to include firmware for the USA-49WLC converter.
-
 config USB_SERIAL_KLSI
 	tristate "USB KL5KUSB105 (Palmconnect) Driver (EXPERIMENTAL)"
 	depends on USB_SERIAL && EXPERIMENTAL

--


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [patch 3/5] Hotplug firmware loader for Keyspan usb-serial driver
  2005-04-05 19:38 [patch 0/5] Hotplug firmware loader for Keyspan usb-serial driver Jan Harkes
  2005-04-05 19:39 ` [patch 1/5] " Jan Harkes
  2005-04-05 19:39 ` [patch 2/5] " Jan Harkes
@ 2005-04-05 19:39 ` Jan Harkes
  2005-04-05 19:39 ` [patch 5/5] " Jan Harkes
  2005-04-05 20:45 ` [patch 0/5] " Kay Sievers
  4 siblings, 0 replies; 8+ messages in thread
From: Jan Harkes @ 2005-04-05 19:39 UTC (permalink / raw)
  To: Greg KH, Sam Ravnborg
  Cc: jaharkes, Dmitry Torokhov, Marcel Holtmann, linux-kernel

[-- Attachment #1: keyspan-dumpfw --]
[-- Type: text/plain, Size: 3587 bytes --]


Simple program to convert the keyspan firmware header files to IHEX
formatted files that can be loaded with hotplug.

This is really only needed once to convert the existing keyspan firmware
headers, which is what the next patch does.


Index: linux/drivers/usb/serial/dumpfw.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/drivers/usb/serial/dumpfw.c	2005-03-10 23:16:37.240765747 -0500
@@ -0,0 +1,98 @@
+/*
+ * Convert keyspan firmware header files to Intel HEX format
+ * cc -I/usr/src/linux/drivers/usb/serial -o dumpfw dumpfw.c
+ */
+#include <stdint.h>
+#include <stdio.h>
+
+//#include "keyspan.h" /* ezusb_hex_record */
+
+struct ezusb_hex_record {
+    uint16_t address;
+    uint8_t  size;
+    uint8_t  data[64];
+};
+
+#include "keyspan_usa28_fw.h"
+#include "keyspan_usa28x_fw.h"
+#include "keyspan_usa28xa_fw.h"
+#include "keyspan_usa28xb_fw.h"
+#include "keyspan_usa19_fw.h"
+#include "keyspan_usa19qi_fw.h"
+#include "keyspan_mpr_fw.h"
+#include "keyspan_usa19qw_fw.h"
+#include "keyspan_usa18x_fw.h"
+#include "keyspan_usa19w_fw.h"
+#include "keyspan_usa49w_fw.h"
+#include "keyspan_usa49wlc_fw.h"
+
+char *boilerplate = "\
+# This firmware for the Keyspan %s USB-to-Serial adapter is\n\
+#\n\
+#    Copyright (C) 1999-2003\n\
+#    Keyspan, A division of InnoSys Incorporated (\"Keyspan\")\n\
+#\n\
+# as an unpublished work. This notice does not imply unrestricted or\n\
+# public access to the source code from which this firmware image is\n\
+# derived.  Except as noted below this firmware image may not be\n\
+# reproduced, used, sold or transferred to any third party without\n\
+# Keyspan's prior written consent.  All Rights Reserved.\n\
+#\n\
+# Permission is hereby granted for the distribution of this firmware\n\
+# image as part of a Linux or other Open Source operating system kernel\n\
+# in text or binary form as required.\n\
+#\n\
+# This firmware may not be modified and may only be used with\n\
+# Keyspan hardware.  Distribution of this firmware, in whole or in\n\
+# part, requires the inclusion of this statement.\n\
+#\n";
+
+void dumpfw(char *name, const struct ezusb_hex_record *record)
+{
+    char fw_name[20];
+    char NAME[10];
+    uint16_t address, i;
+    uint8_t crc;
+    FILE *f;
+
+    for (i = 0; name[i] != '\0'; i++)
+	NAME[i] = toupper(name[i]);
+    NAME[i] = '\0';
+
+    sprintf(fw_name, "keyspan-%s.fw", name);
+    printf("writing %s\n", fw_name);
+
+    f = fopen(fw_name, "w");
+    fprintf(f, boilerplate, NAME);
+
+    while (record->address != 0xffff) {
+	crc = record->size + (record->address >> 8) + record->address;
+	fprintf(f, ":%02X%04X00", record->size, record->address);
+	for (i = 0; i < record->size; i++) {
+	    fprintf(f, "%02X", record->data[i]);
+	    crc += record->data[i];
+	}
+	fprintf(f, "%02X\n", (uint8_t)-crc);
+	record++;
+    }
+    fprintf(f, ":00000001FF\n");
+
+    fclose(f);
+}
+
+int main(int argc, char **argv)
+{
+    dumpfw("mpr",	keyspan_mpr_firmware);
+    dumpfw("usa18x",	keyspan_usa18x_firmware);
+    dumpfw("usa19",	keyspan_usa19_firmware);
+    dumpfw("usa19qi",	keyspan_usa19qi_firmware);
+    dumpfw("usa19qw",	keyspan_usa19qw_firmware);
+    dumpfw("usa19w",	keyspan_usa19w_firmware);
+    dumpfw("usa28",	keyspan_usa28_firmware);
+    dumpfw("usa28x",	keyspan_usa28x_firmware);
+    dumpfw("usa28xa",	keyspan_usa28xa_firmware);
+    dumpfw("usa28xb",	keyspan_usa28xb_firmware);
+    dumpfw("usa49w",	keyspan_usa49w_firmware);
+    dumpfw("usa49wlc",	keyspan_usa49wlc_firmware);
+}
+

--


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [patch 5/5] Hotplug firmware loader for Keyspan usb-serial driver
  2005-04-05 19:38 [patch 0/5] Hotplug firmware loader for Keyspan usb-serial driver Jan Harkes
                   ` (2 preceding siblings ...)
  2005-04-05 19:39 ` [patch 3/5] " Jan Harkes
@ 2005-04-05 19:39 ` Jan Harkes
  2005-04-05 20:45 ` [patch 0/5] " Kay Sievers
  4 siblings, 0 replies; 8+ messages in thread
From: Jan Harkes @ 2005-04-05 19:39 UTC (permalink / raw)
  To: Greg KH, Sam Ravnborg
  Cc: jaharkes, Dmitry Torokhov, Marcel Holtmann, linux-kernel

[-- Attachment #1: keyspan-install_fw --]
[-- Type: text/plain, Size: 5086 bytes --]


Add "make install_firmware" to the kbuild environment.

Signed-off-by: Jan Harkes <jaharkes@cs.cmu.edu>


 Makefile                    |   33 +++++++++++++++++++++++++++++++++
 drivers/usb/serial/Makefile |    5 +++++
 scripts/Makefile.fwinst     |   34 ++++++++++++++++++++++++++++++++++
 3 files changed, 72 insertions(+)

Index: linux/scripts/Makefile.fwinst
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux/scripts/Makefile.fwinst	2005-04-05 14:36:56.000000000 -0400
@@ -0,0 +1,34 @@
+# ==========================================================================
+# Installing firmware
+# ==========================================================================
+
+src := $(obj)
+
+.PHONY: __fwinst
+__fwinst:
+
+-include .config
+include $(if $(wildcard $(obj)/Kbuild), $(obj)/Kbuild, $(obj)/Makefile)
+include scripts/Makefile.lib
+
+firmware	:= $(fw-y) $(fw-m)
+firmware	:= $(addprefix $(src)/, $(firmware))
+
+# =====================================================================
+
+.PHONY: $(firmware)
+__fwinst: $(firmware) $(subdir-ym)
+	@:
+
+quiet_cmd_firmware_install = INSTALL $@
+      cmd_firmware_install = mkdir -p $(2); cp $@ $(2)
+
+$(firmware):
+	$(call cmd,firmware_install,$(MODLIB)/firmware)
+
+# =====================================================================
+
+.PHONY: $(subdir-ym)
+$(subdir-ym):
+	$(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.fwinst obj=$@
+
Index: linux/Makefile
===================================================================
--- linux.orig/Makefile	2005-03-29 16:19:14.000000000 -0500
+++ linux/Makefile	2005-04-05 14:42:42.000000000 -0400
@@ -927,6 +927,21 @@ modules modules_install: FORCE
 
 endif # CONFIG_MODULES
 
+# ---------------------------------------------------------------------------
+# Firmware
+
+fwinst-dirs      := $(addprefix _fwinst_,$(vmlinux-dirs))
+
+.PHONY: $(fwinst-dirs) _fwinst_ firmware_install
+$(fwinst-dirs):
+	$(Q)$(MAKE) $(fwinst)=$(patsubst _fwinst_%,%,$@)
+
+_fwinst_:
+	@rm -rf $(MODLIB)/firmware
+	@mkdir -p $(MODLIB)/firmware
+
+firmware_install: _fwinst_ $(fwinst-dirs)
+
 # Generate asm-offsets.h 
 # ---------------------------------------------------------------------------
 
@@ -1042,6 +1057,7 @@ help:
 	@echo  '* vmlinux	  - Build the bare kernel'
 	@echo  '* modules	  - Build all modules'
 	@echo  '  modules_install - Install all modules'
+	@echo  '  firmware_install- Install all firmware'
 	@echo  '  dir/            - Build all files in dir and below'
 	@echo  '  dir/file.[ois]  - Build specified target only'
 	@echo  '  rpm		  - Build a kernel as an RPM package'
@@ -1101,6 +1117,10 @@ else # KBUILD_EXTMOD
 # make M=dir modules_install
 #                      Install the modules build in the module directory
 #                      Assumes install directory is already created
+# make M=dir firmware_install
+#                      Install the firmware in the firmware directory
+#                      Assumes install directory is already created
+
 
 # We are always building modules
 KBUILD_MODULES := 1
@@ -1129,6 +1149,13 @@ modules: $(module-dirs)
 modules_install:
 	$(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modinst
 
+fwinst-dirs := $(addprefix _fwinst_,$(KBUILD_EXTMOD))
+.PHONY: $(fwinst-dirs) firmware_install
+$(fwinst-dirs):
+	$(Q)$(MAKE) $(fwinst)=$(patsubst _fwinst_%,%,$@)
+
+firmware_install: $(fwinst-dirs)
+
 clean-dirs := $(addprefix _clean_,$(KBUILD_EXTMOD))
 
 .PHONY: $(clean-dirs) clean
@@ -1149,6 +1176,7 @@ help:
 	@echo  ''
 	@echo  '  modules         - default target, build the module(s)'
 	@echo  '  modules_install - install the module'
+	@echo  '  firmware_install- install firmware'
 	@echo  '  clean           - remove generated files in module directory only'
 	@echo  ''
 endif # KBUILD_EXTMOD
@@ -1346,6 +1374,11 @@ build := -f $(if $(KBUILD_SRC),$(srctree
 # $(Q)$(MAKE) $(clean)=dir
 clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj
 
+# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.fwinst obj=dir
+# Usage:
+# $(Q)$(MAKE) $(fwinst)=dir
+fwinst := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.fwinst obj
+
 #	$(call descend,<dir>,<target>)
 #	Recursively call a sub-make in <dir> with target <target>
 # Usage is deprecated, because make does not see this as an invocation of make.
Index: linux/drivers/usb/serial/Makefile
===================================================================
--- linux.orig/drivers/usb/serial/Makefile	2005-03-10 16:01:14.000000000 -0500
+++ linux/drivers/usb/serial/Makefile	2005-04-05 13:01:54.000000000 -0400
@@ -36,3 +36,8 @@ obj-$(CONFIG_USB_SERIAL_VISOR)			+= viso
 obj-$(CONFIG_USB_SERIAL_WHITEHEAT)		+= whiteheat.o
 obj-$(CONFIG_USB_SERIAL_XIRCOM)			+= keyspan_pda.o
 
+fw-$(CONFIG_USB_SERIAL_KEYSPAN)			+= \
+	keyspan-mpr.fw     keyspan-usa18x.fw  keyspan-usa19.fw \
+	keyspan-usa19qi.fw keyspan-usa19qw.fw keyspan-usa19w.fw \
+	keyspan-usa28.fw   keyspan-usa28x.fw  keyspan-usa28xa.fw \
+	keyspan-usa28xb.fw keyspan-usa49w.fw  keyspan-usa49wlc.fw

--


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch 1/5] Hotplug firmware loader for Keyspan usb-serial driver
  2005-04-05 19:39 ` [patch 1/5] " Jan Harkes
@ 2005-04-05 20:41   ` Brian Gerst
  0 siblings, 0 replies; 8+ messages in thread
From: Brian Gerst @ 2005-04-05 20:41 UTC (permalink / raw)
  To: Jan Harkes
  Cc: Greg KH, Sam Ravnborg, Dmitry Torokhov, Marcel Holtmann,
	linux-kernel

Jan Harkes wrote:
> A simple Intel HEX format parser/loader.

...

> +static int __init no_init(void)
> +{
> +	return 0;
> +}
> +
> +static void __exit no_exit(void)
> +{
> +}
> +
> +module_init(no_init);
> +module_exit(no_exit);

module_init/exit are not needed if both are simply stubs.

--
				Brian Gerst

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch 0/5] Hotplug firmware loader for Keyspan usb-serial driver
  2005-04-05 19:38 [patch 0/5] Hotplug firmware loader for Keyspan usb-serial driver Jan Harkes
                   ` (3 preceding siblings ...)
  2005-04-05 19:39 ` [patch 5/5] " Jan Harkes
@ 2005-04-05 20:45 ` Kay Sievers
  2005-04-05 21:12   ` Jan Harkes
  4 siblings, 1 reply; 8+ messages in thread
From: Kay Sievers @ 2005-04-05 20:45 UTC (permalink / raw)
  To: Jan Harkes
  Cc: Greg KH, Sam Ravnborg, Dmitry Torokhov, Marcel Holtmann,
	linux-kernel

On Tue, 2005-04-05 at 15:38 -0400, Jan Harkes wrote:
> Here is another stab at making the keyspan firmware easily loadable with
> hotplug. Differences from the previous version,
> 
> - keep the IHEX parser into a separate module.
> - added a fw-y and fw-m install targets to kbuild which will install a
>   driver's firmware files in /lib/modules/`uname -r`/firmware.
> 
> 01 - Add lib/ihex_parser.ko.

Oh, I just see now that it's a EZ-USB device. Did you try adapting the
driver to use fxload(8)? to load the firmware. I have a USB-Modem that
works perfect with loading ez-firmware that way.

Kay


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch 0/5] Hotplug firmware loader for Keyspan usb-serial driver
  2005-04-05 20:45 ` [patch 0/5] " Kay Sievers
@ 2005-04-05 21:12   ` Jan Harkes
  0 siblings, 0 replies; 8+ messages in thread
From: Jan Harkes @ 2005-04-05 21:12 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Jan Harkes, Greg KH, Sam Ravnborg, Dmitry Torokhov,
	Marcel Holtmann, linux-kernel

On Tue, Apr 05, 2005 at 10:45:30PM +0200, Kay Sievers wrote:
> On Tue, 2005-04-05 at 15:38 -0400, Jan Harkes wrote:
> > Here is another stab at making the keyspan firmware easily loadable with
> > hotplug. Differences from the previous version,
> > 
> > - keep the IHEX parser into a separate module.
> > - added a fw-y and fw-m install targets to kbuild which will install a
> >   driver's firmware files in /lib/modules/`uname -r`/firmware.
> > 
> > 01 - Add lib/ihex_parser.ko.
> 
> Oh, I just see now that it's a EZ-USB device. Did you try adapting the
> driver to use fxload(8)? to load the firmware. I have a USB-Modem that
> works perfect with loading ez-firmware that way.

Never heard of fxload before. I just tried it by moving the firmware
directory out of the way so that hotplug wouldn't try to initialize the
device behind my back.

    # fxload -v -t fx -D /proc/bus/usb/002/011 -I keyspan-usa19qi.fw 
    microcontroller type: fx
    single stage:  load on-chip memory
    open RAM hexfile image keyspan-usa19qi.fw
    stop CPU
    write on-chip, addr 0x0033 len    3 (0x0003)
    write on-chip, addr 0x001a len    4 (0x0004)
    write on-chip, addr 0x0003 len   23 (0x0017)
    write on-chip, addr 0x0023 len    3 (0x0003)
    write on-chip, addr 0x0046 len  192 (0x00c0)
    write on-chip, addr 0x0043 len    3 (0x0003)
    write on-chip, addr 0x0000 len    3 (0x0003)
    write on-chip, addr 0x0026 len   12 (0x000c)
    write on-chip, addr 0x0106 len  960 (0x03c0)
    write on-chip, addr 0x04c6 len  960 (0x03c0)
    write on-chip, addr 0x0886 len  960 (0x03c0)
    write on-chip, addr 0x0c46 len  905 (0x0389)
    ... WROTE: 4028 bytes, 12 segments, avg 335
    reset CPU

    # dmesg | tail
    keyspan 2-1:1.0: device disconnected
    usb 2-1: new full speed USB device using uhci_hcd and address 11
    keyspan 2-1:1.0: Keyspan - (without firmware) converter detected
    usb 2-1: Required firmware image (keyspan-usa19qi.fw) unavailable.
>>> fxload was used at this point
    usb 2-1: USB disconnect, address 11
    keyspan 2-1:1.0: device disconnected
    usb 2-1: new full speed USB device using uhci_hcd and address 12
    usb 2-1: configuration #1 chosen from 2 choices
    keyspan 2-1:1.0: Keyspan 1 port adapter converter detected
    usb 2-1: Keyspan 1 port adapter converter now attached to ttyUSB0

Looks like it works, so I guess the pre-numeration stuff in the driver
is really not necessary. We just need a bunch of hotplug rules to load
the correct firmware whenever an uninitialized device is plugged in and
some way to distribute the firmware images.

Jan


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2005-04-05 21:29 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-04-05 19:38 [patch 0/5] Hotplug firmware loader for Keyspan usb-serial driver Jan Harkes
2005-04-05 19:39 ` [patch 1/5] " Jan Harkes
2005-04-05 20:41   ` Brian Gerst
2005-04-05 19:39 ` [patch 2/5] " Jan Harkes
2005-04-05 19:39 ` [patch 3/5] " Jan Harkes
2005-04-05 19:39 ` [patch 5/5] " Jan Harkes
2005-04-05 20:45 ` [patch 0/5] " Kay Sievers
2005-04-05 21:12   ` Jan Harkes

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox