ALSA: 6fire - Improve firmware loader
authorTorsten Schenk <torsten.schenk@zoho.com>
Mon, 4 Apr 2011 09:49:57 +0000 (11:49 +0200)
committerTakashi Iwai <tiwai@suse.de>
Mon, 4 Apr 2011 10:25:50 +0000 (12:25 +0200)
Firmware loader: magical device bytes check updated (accepts all device
versions now and accepts possibly loaded firmware, if it is knowing to
be working)

Signed-off-by: Torsten Schenk <torsten.schenk@zoho.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/usb/6fire/firmware.c

index 9081a54a9c6cecdeb39e05603fc3c775bfe171c7..e720035fbd1eaf42af04272141e33e129258241f 100644 (file)
@@ -3,12 +3,6 @@
  *
  * Firmware loader
  *
- * Currently not working for all devices. To be able to use the device
- * in linux, it is also possible to let the windows driver upload the firmware.
- * For that, start the computer in windows and reboot.
- * As long as the device is connected to the power supply, no firmware reload
- * needs to be performed.
- *
  * Author:     Torsten Schenk <torsten.schenk@zoho.com>
  * Created:    Jan 01, 2011
  * Version:    0.3.0
@@ -72,6 +66,10 @@ static const u8 ep_w_max_packet_size[] = {
        0x94, 0x01, 0x5c, 0x02  /* alt 3: 404 EP2 and 604 EP6 (25 fpp) */
 };
 
+static const u8 known_fw_versions[][4] = {
+       { 0x03, 0x01, 0x0b, 0x00 }
+};
+
 struct ihex_record {
        u16 address;
        u8 len;
@@ -363,6 +361,25 @@ static int usb6fire_fw_fpga_upload(
        return 0;
 }
 
+/* check, if the firmware version the devices has currently loaded
+ * is known by this driver. 'version' needs to have 4 bytes version
+ * info data. */
+static int usb6fire_fw_check(u8 *version)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(known_fw_versions); i++)
+               if (!memcmp(version, known_fw_versions + i, 4))
+                       return 0;
+
+       snd_printk(KERN_ERR PREFIX "invalid fimware version in device: "
+                       "%02x %02x %02x %02x. "
+                       "please reconnect to power. if this failure "
+                       "still happens, check your firmware installation.",
+                       version[0], version[1], version[2], version[3]);
+       return -EINVAL;
+}
+
 int usb6fire_fw_init(struct usb_interface *intf)
 {
        int i;
@@ -378,9 +395,7 @@ int usb6fire_fw_init(struct usb_interface *intf)
                                "firmware state.\n");
                return ret;
        }
-       if (buffer[0] != 0xeb || buffer[1] != 0xaa || buffer[2] != 0x55
-                       || buffer[4] != 0x03 || buffer[5] != 0x01 || buffer[7]
-                       != 0x00) {
+       if (buffer[0] != 0xeb || buffer[1] != 0xaa || buffer[2] != 0x55) {
                snd_printk(KERN_ERR PREFIX "unknown device firmware state "
                                "received from device: ");
                for (i = 0; i < 8; i++)
@@ -389,7 +404,7 @@ int usb6fire_fw_init(struct usb_interface *intf)
                return -EIO;
        }
        /* do we need fpga loader ezusb firmware? */
-       if (buffer[3] == 0x01 && buffer[6] == 0x19) {
+       if (buffer[3] == 0x01) {
                ret = usb6fire_fw_ezusb_upload(intf,
                                "6fire/dmx6firel2.ihx", 0, NULL, 0);
                if (ret < 0)
@@ -397,7 +412,10 @@ int usb6fire_fw_init(struct usb_interface *intf)
                return FW_NOT_READY;
        }
        /* do we need fpga firmware and application ezusb firmware? */
-       else if (buffer[3] == 0x02 && buffer[6] == 0x0b) {
+       else if (buffer[3] == 0x02) {
+               ret = usb6fire_fw_check(buffer + 4);
+               if (ret < 0)
+                       return ret;
                ret = usb6fire_fw_fpga_upload(intf, "6fire/dmx6firecf.bin");
                if (ret < 0)
                        return ret;
@@ -410,8 +428,8 @@ int usb6fire_fw_init(struct usb_interface *intf)
                return FW_NOT_READY;
        }
        /* all fw loaded? */
-       else if (buffer[3] == 0x03 && buffer[6] == 0x0b)
-               return 0;
+       else if (buffer[3] == 0x03)
+               return usb6fire_fw_check(buffer + 4);
        /* unknown data? */
        else {
                snd_printk(KERN_ERR PREFIX "unknown device firmware state "