]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/usb/serial/keyspan.c
Merge branch 'for-2.6.27' of git://git.infradead.org/users/dwmw2/firmware-2.6
[linux-2.6-omap-h63xx.git] / drivers / usb / serial / keyspan.c
index 857c5312555ab6d69229c19e6606acec466d433d..11e439b90eacd88a2a89e1a48ee6759e7982ccc0 100644 (file)
 #include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/firmware.h>
+#include <linux/ihex.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
@@ -445,7 +447,7 @@ static void usa26_indat_callback(struct urb *urb)
                return;
        }
 
-       port = (struct usb_serial_port *) urb->context;
+       port =  urb->context;
        tty = port->tty;
        if (tty && urb->actual_length) {
                /* 0x80 bit is error flag */
@@ -490,7 +492,7 @@ static void usa2x_outdat_callback(struct urb *urb)
        struct usb_serial_port *port;
        struct keyspan_port_private *p_priv;
 
-       port = (struct usb_serial_port *) urb->context;
+       port =  urb->context;
        p_priv = usb_get_serial_port_data(port);
        dbg ("%s - urb %d", __func__, urb == p_priv->out_urbs[1]);
 
@@ -509,7 +511,7 @@ static void usa26_outcont_callback(struct urb *urb)
        struct usb_serial_port *port;
        struct keyspan_port_private *p_priv;
 
-       port = (struct usb_serial_port *) urb->context;
+       port =  urb->context;
        p_priv = usb_get_serial_port_data(port);
 
        if (p_priv->resend_cont) {
@@ -528,7 +530,7 @@ static void usa26_instat_callback(struct urb *urb)
        int old_dcd_state, err;
        int status = urb->status;
 
-       serial = (struct usb_serial *) urb->context;
+       serial =  urb->context;
 
        if (status) {
                dbg("%s - nonzero status: %x", __func__, status);
@@ -599,7 +601,7 @@ static void usa28_indat_callback(struct urb *urb)
 
        dbg ("%s", __func__);
 
-       port = (struct usb_serial_port *) urb->context;
+       port =  urb->context;
        p_priv = usb_get_serial_port_data(port);
        data = urb->transfer_buffer;
 
@@ -613,7 +615,7 @@ static void usa28_indat_callback(struct urb *urb)
                        return;
                }
 
-               port = (struct usb_serial_port *) urb->context;
+               port =  urb->context;
                p_priv = usb_get_serial_port_data(port);
                data = urb->transfer_buffer;
 
@@ -647,7 +649,7 @@ static void usa28_outcont_callback(struct urb *urb)
        struct usb_serial_port *port;
        struct keyspan_port_private *p_priv;
 
-       port = (struct usb_serial_port *) urb->context;
+       port =  urb->context;
        p_priv = usb_get_serial_port_data(port);
 
        if (p_priv->resend_cont) {
@@ -667,7 +669,7 @@ static void usa28_instat_callback(struct urb *urb)
        int old_dcd_state;
        int status = urb->status;
 
-       serial = (struct usb_serial *) urb->context;
+       serial =  urb->context;
 
        if (status) {
                dbg("%s - nonzero status: %x", __func__, status);
@@ -733,7 +735,7 @@ static void usa49_glocont_callback(struct urb *urb)
 
        dbg ("%s", __func__);
 
-       serial = (struct usb_serial *) urb->context;
+       serial =  urb->context;
        for (i = 0; i < serial->num_ports; ++i) {
                port = serial->port[i];
                p_priv = usb_get_serial_port_data(port);
@@ -761,7 +763,7 @@ static void usa49_instat_callback(struct urb *urb)
 
        dbg ("%s", __func__);
 
-       serial = (struct usb_serial *) urb->context;
+       serial =  urb->context;
 
        if (status) {
                dbg("%s - nonzero status: %x", __func__, status);
@@ -836,7 +838,7 @@ static void usa49_indat_callback(struct urb *urb)
                return;
        }
 
-       port = (struct usb_serial_port *) urb->context;
+       port =  urb->context;
        tty = port->tty;
        if (tty && urb->actual_length) {
                /* 0x80 bit is error flag */
@@ -973,7 +975,7 @@ static void usa90_indat_callback(struct urb *urb)
                return;
        }
 
-       port = (struct usb_serial_port *) urb->context;
+       port =  urb->context;
        p_priv = usb_get_serial_port_data(port);
 
        tty = port->tty;
@@ -1037,7 +1039,7 @@ static void       usa90_instat_callback(struct urb *urb)
        int old_dcd_state, err;
        int status = urb->status;
 
-       serial = (struct usb_serial *) urb->context;
+       serial =  urb->context;
 
        if (status) {
                dbg("%s - nonzero status: %x", __func__, status);
@@ -1084,7 +1086,7 @@ static void       usa90_outcont_callback(struct urb *urb)
        struct usb_serial_port *port;
        struct keyspan_port_private *p_priv;
 
-       port = (struct usb_serial_port *) urb->context;
+       port =  urb->context;
        p_priv = usb_get_serial_port_data(port);
 
        if (p_priv->resend_cont) {
@@ -1187,6 +1189,7 @@ static int keyspan_write_room (struct usb_serial_port *port)
        p_priv = usb_get_serial_port_data(port);
        d_details = p_priv->device_details;
 
+       /* FIXME: locking */
        if (d_details->msg_format == msg_usa90)
                data_len = 64;
        else
@@ -1203,13 +1206,13 @@ static int keyspan_write_room (struct usb_serial_port *port)
                        if (this_urb->status != -EINPROGRESS)
                                return (data_len);
        }
-       return (0);
+       return 0;
 }
 
 
 static int keyspan_chars_in_buffer (struct usb_serial_port *port)
 {
-       return (0);
+       return 0;
 }
 
 
@@ -1289,7 +1292,7 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
        //mdelay(100);
        //keyspan_set_termios(port, NULL);
 
-       return (0);
+       return 0;
 }
 
 static inline void stop_urb(struct urb *urb)
@@ -1338,13 +1341,13 @@ static void keyspan_close(struct usb_serial_port *port, struct file *filp)
        port->tty = NULL;
 }
 
-
        /* 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;
+       const struct ihex_binrec        *record;
        char                            *fw_name;
+       const struct firmware           *fw;
 
        dbg("Keyspan startup version %04x product %04x",
            le16_to_cpu(serial->dev->descriptor.bcdDevice),
@@ -1358,72 +1361,60 @@ static int keyspan_fake_startup (struct usb_serial *serial)
                /* 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";
+               fw_name = "keyspan/usa28.fw";
                break;
 
        case keyspan_usa28x_pre_product_id:
-               record = &keyspan_usa28x_firmware[0];
-               fw_name = "USA28X";
+               fw_name = "keyspan/usa28x.fw";
                break;
 
        case keyspan_usa28xa_pre_product_id:
-               record = &keyspan_usa28xa_firmware[0];
-               fw_name = "USA28XA";
+               fw_name = "keyspan/usa28xa.fw";
                break;
 
        case keyspan_usa28xb_pre_product_id:
-               record = &keyspan_usa28xb_firmware[0];
-               fw_name = "USA28XB";
+               fw_name = "keyspan/usa28xb.fw";
                break;
 
        case keyspan_usa19_pre_product_id:
-               record = &keyspan_usa19_firmware[0];
-               fw_name = "USA19";
+               fw_name = "keyspan/usa19.fw";
                break;
                             
        case keyspan_usa19qi_pre_product_id:
-               record = &keyspan_usa19qi_firmware[0];
-               fw_name = "USA19QI";
+               fw_name = "keyspan/usa19qi.fw";
                break;
                             
        case keyspan_mpr_pre_product_id:
-               record = &keyspan_mpr_firmware[0];
-               fw_name = "MPR";
+               fw_name = "keyspan/mpr.fw";
                break;
 
        case keyspan_usa19qw_pre_product_id:
-               record = &keyspan_usa19qw_firmware[0];
-               fw_name = "USA19QI";
+               fw_name = "keyspan/usa19qw.fw";
                break;
                             
        case keyspan_usa18x_pre_product_id:
-               record = &keyspan_usa18x_firmware[0];
-               fw_name = "USA18X";
+               fw_name = "keyspan/usa18x.fw";
                break;
                             
        case keyspan_usa19w_pre_product_id:
-               record = &keyspan_usa19w_firmware[0];
-               fw_name = "USA19W";
+               fw_name = "keyspan/usa19w.fw";
                break;
                
        case keyspan_usa49w_pre_product_id:
-               record = &keyspan_usa49w_firmware[0];
-               fw_name = "USA49W";
+               fw_name = "keyspan/usa49w.fw";
                break;
 
        case keyspan_usa49wlc_pre_product_id:
-               record = &keyspan_usa49wlc_firmware[0];
-               fw_name = "USA49WLC";
+               fw_name = "keyspan/usa49wlc.fw";
                break;
 
        default:
-               record = NULL;
-               fw_name = "Unknown";
-               break;
+               dev_err(&serial->dev->dev, "Unknown product ID (%04x)\n",
+                       le16_to_cpu(serial->dev->descriptor.idProduct));
+               return 1;
        }
 
-       if (record == NULL) {
+       if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) {
                dev_err(&serial->dev->dev, "Required keyspan firmware image (%s) unavailable.\n", fw_name);
                return(1);
        }
@@ -1433,19 +1424,22 @@ static int keyspan_fake_startup (struct usb_serial *serial)
                /* download the firmware image */
        response = ezusb_set_reset(serial, 1);
 
-       while(record->address != 0xffff) {
-               response = ezusb_writememory(serial, record->address,
+       record = (const struct ihex_binrec *)fw->data;
+
+       while (record) {
+               response = ezusb_writememory(serial, be32_to_cpu(record->addr),
                                             (unsigned char *)record->data,
-                                            record->data_size, 0xa0);
+                                            be16_to_cpu(record->len), 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);
+                               response, be32_to_cpu(record->addr),
+                               record->data, be16_to_cpu(record->len));
                        break;
                }
-               record++;
+               record = ihex_next_binrec(record);
        }
+       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);
@@ -2006,7 +2000,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
        }
 #endif
 
-       return (0);
+       return 0;
 }
 
 static int keyspan_usa28_send_setup(struct usb_serial *serial,
@@ -2131,7 +2125,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
        }
 #endif
 
-       return (0);
+       return 0;
 }
 
 static int keyspan_usa49_send_setup(struct usb_serial *serial,
@@ -2317,7 +2311,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
        }
 #endif
 
-       return (0);
+       return 0;
 }
 
 static int keyspan_usa90_send_setup(struct usb_serial *serial,
@@ -2455,7 +2449,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
        if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
                dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
        }
-       return (0);
+       return 0;
 }
 
 static int keyspan_usa67_send_setup(struct usb_serial *serial,
@@ -2603,7 +2597,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial,
        if (err != 0)
                dbg("%s - usb_submit_urb(setup) failed (%d)", __func__,
                                err);
-       return (0);
+       return 0;
 }
 
 static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
@@ -2696,7 +2690,7 @@ static int keyspan_startup (struct usb_serial *serial)
                                err);
        }
                        
-       return (0);
+       return 0;
 }
 
 static void keyspan_shutdown (struct usb_serial *serial)
@@ -2755,6 +2749,19 @@ MODULE_AUTHOR( DRIVER_AUTHOR );
 MODULE_DESCRIPTION( DRIVER_DESC );
 MODULE_LICENSE("GPL");
 
+MODULE_FIRMWARE("keyspan/usa28.fw");
+MODULE_FIRMWARE("keyspan/usa28x.fw");
+MODULE_FIRMWARE("keyspan/usa28xa.fw");
+MODULE_FIRMWARE("keyspan/usa28xb.fw");
+MODULE_FIRMWARE("keyspan/usa19.fw");
+MODULE_FIRMWARE("keyspan/usa19qi.fw");
+MODULE_FIRMWARE("keyspan/mpr.fw");
+MODULE_FIRMWARE("keyspan/usa19qw.fw");
+MODULE_FIRMWARE("keyspan/usa18x.fw");
+MODULE_FIRMWARE("keyspan/usa19w.fw");
+MODULE_FIRMWARE("keyspan/usa49w.fw");
+MODULE_FIRMWARE("keyspan/usa49wlc.fw");
+
 module_param(debug, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug enabled or not");