summaryrefslogtreecommitdiff
path: root/drivers/usb/serial
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r--drivers/usb/serial/aircable.c21
-rw-r--r--drivers/usb/serial/airprime.c1
-rw-r--r--drivers/usb/serial/ark3116.c2
-rw-r--r--drivers/usb/serial/belkin_sa.c1
-rw-r--r--drivers/usb/serial/bus.c45
-rw-r--r--drivers/usb/serial/cp2101.c1
-rw-r--r--drivers/usb/serial/cyberjack.c3
-rw-r--r--drivers/usb/serial/cypress_m8.c3
-rw-r--r--drivers/usb/serial/digi_acceleport.c2
-rw-r--r--drivers/usb/serial/empeg.c1
-rw-r--r--drivers/usb/serial/ftdi_sio.c2
-rw-r--r--drivers/usb/serial/ftdi_sio.h1
-rw-r--r--drivers/usb/serial/funsoft.c1
-rw-r--r--drivers/usb/serial/garmin_gps.c1
-rw-r--r--drivers/usb/serial/generic.c35
-rw-r--r--drivers/usb/serial/hp4x.c1
-rw-r--r--drivers/usb/serial/io_edgeport.c417
-rw-r--r--drivers/usb/serial/io_edgeport.h6
-rw-r--r--drivers/usb/serial/io_tables.h61
-rw-r--r--drivers/usb/serial/io_ti.c2
-rw-r--r--drivers/usb/serial/io_usbvend.h5
-rw-r--r--drivers/usb/serial/ipaq.c1
-rw-r--r--drivers/usb/serial/ipw.c1
-rw-r--r--drivers/usb/serial/ir-usb.c1
-rw-r--r--drivers/usb/serial/keyspan.c49
-rw-r--r--drivers/usb/serial/keyspan.h7
-rw-r--r--drivers/usb/serial/keyspan_pda.c3
-rw-r--r--drivers/usb/serial/kl5kusb105.c1
-rw-r--r--drivers/usb/serial/kobil_sct.c1
-rw-r--r--drivers/usb/serial/mct_u232.c1
-rw-r--r--drivers/usb/serial/mos7720.c16
-rw-r--r--drivers/usb/serial/mos7840.c16
-rw-r--r--drivers/usb/serial/navman.c1
-rw-r--r--drivers/usb/serial/omninet.c1
-rw-r--r--drivers/usb/serial/option.c1
-rw-r--r--drivers/usb/serial/pl2303.c1
-rw-r--r--drivers/usb/serial/safe_serial.c1
-rw-r--r--drivers/usb/serial/sierra.c29
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c2
-rw-r--r--drivers/usb/serial/usb-serial.c102
-rw-r--r--drivers/usb/serial/visor.c6
-rw-r--r--drivers/usb/serial/visor.h1
-rw-r--r--drivers/usb/serial/whiteheat.c2
43 files changed, 683 insertions, 173 deletions
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index 86bcf63b6ba5..11dad42c3c60 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -572,8 +572,20 @@ static void aircable_unthrottle(struct usb_serial_port *port)
schedule_work(&priv->rx_work);
}
+static struct usb_driver aircable_driver = {
+ .name = "aircable",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = id_table,
+ .no_dynamic_id = 1,
+};
+
static struct usb_serial_driver aircable_device = {
- .description = "aircable",
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "aircable",
+ },
+ .usb_driver = &aircable_driver,
.id_table = id_table,
.num_ports = 1,
.attach = aircable_attach,
@@ -587,13 +599,6 @@ static struct usb_serial_driver aircable_device = {
.unthrottle = aircable_unthrottle,
};
-static struct usb_driver aircable_driver = {
- .name = "aircable",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table,
-};
-
static int __init aircable_init (void)
{
int retval;
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index f2ca76a9cbac..0af42e32fa0a 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -277,6 +277,7 @@ static struct usb_serial_driver airprime_device = {
.owner = THIS_MODULE,
.name = "airprime",
},
+ .usb_driver = &airprime_driver,
.id_table = id_table,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index 5261cd22ee6b..edd685791a6b 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -444,6 +444,7 @@ static struct usb_driver ark3116_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
+ .no_dynamic_id = 1,
};
static struct usb_serial_driver ark3116_device = {
@@ -452,6 +453,7 @@ static struct usb_serial_driver ark3116_device = {
.name = "ark3116",
},
.id_table = id_table,
+ .usb_driver = &ark3116_driver,
.num_interrupt_in = 1,
.num_bulk_in = 1,
.num_bulk_out = 1,
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 38b4dae319ee..3b800d277c4b 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -126,6 +126,7 @@ static struct usb_serial_driver belkin_device = {
.name = "belkin",
},
.description = "Belkin / Peracom / GoHubs USB Serial Adapter",
+ .usb_driver = &belkin_driver,
.id_table = id_table_combined,
.num_interrupt_in = 1,
.num_bulk_in = 1,
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index 6542f220468f..c08a38402b93 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -103,11 +103,52 @@ exit:
return retval;
}
+#ifdef CONFIG_HOTPLUG
+static ssize_t store_new_id(struct device_driver *driver,
+ const char *buf, size_t count)
+{
+ struct usb_serial_driver *usb_drv = to_usb_serial_driver(driver);
+ ssize_t retval = usb_store_new_id(&usb_drv->dynids, driver, buf, count);
+
+ if (retval >= 0 && usb_drv->usb_driver != NULL)
+ retval = usb_store_new_id(&usb_drv->usb_driver->dynids,
+ &usb_drv->usb_driver->drvwrap.driver,
+ buf, count);
+ return retval;
+}
+
+static struct driver_attribute drv_attrs[] = {
+ __ATTR(new_id, S_IWUSR, NULL, store_new_id),
+ __ATTR_NULL,
+};
+
+static void free_dynids(struct usb_serial_driver *drv)
+{
+ struct usb_dynid *dynid, *n;
+
+ spin_lock(&drv->dynids.lock);
+ list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
+ list_del(&dynid->node);
+ kfree(dynid);
+ }
+ spin_unlock(&drv->dynids.lock);
+}
+
+#else
+static struct driver_attribute drv_attrs[] = {
+ __ATTR_NULL,
+};
+static inline void free_dynids(struct usb_driver *drv)
+{
+}
+#endif
+
struct bus_type usb_serial_bus_type = {
.name = "usb-serial",
.match = usb_serial_device_match,
.probe = usb_serial_device_probe,
.remove = usb_serial_device_remove,
+ .drv_attrs = drv_attrs,
};
int usb_serial_bus_register(struct usb_serial_driver *driver)
@@ -115,6 +156,9 @@ int usb_serial_bus_register(struct usb_serial_driver *driver)
int retval;
driver->driver.bus = &usb_serial_bus_type;
+ spin_lock_init(&driver->dynids.lock);
+ INIT_LIST_HEAD(&driver->dynids.list);
+
retval = driver_register(&driver->driver);
return retval;
@@ -122,6 +166,7 @@ int usb_serial_bus_register(struct usb_serial_driver *driver)
void usb_serial_bus_deregister(struct usb_serial_driver *driver)
{
+ free_dynids(driver);
driver_unregister(&driver->driver);
}
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index 7ebaffd6ed86..06b4fffc189c 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -89,6 +89,7 @@ static struct usb_serial_driver cp2101_device = {
.owner = THIS_MODULE,
.name = "cp2101",
},
+ .usb_driver = &cp2101_driver,
.id_table = id_table,
.num_interrupt_in = 0,
.num_bulk_in = 0,
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index a63c3286caa0..4167753ed31f 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -88,6 +88,7 @@ static struct usb_serial_driver cyberjack_device = {
.name = "cyberjack",
},
.description = "Reiner SCT Cyberjack USB card reader",
+ .usb_driver = &cyberjack_driver,
.id_table = id_table,
.num_interrupt_in = 1,
.num_bulk_in = 1,
@@ -98,7 +99,7 @@ static struct usb_serial_driver cyberjack_device = {
.open = cyberjack_open,
.close = cyberjack_close,
.write = cyberjack_write,
- .write_room = cyberjack_write_room,
+ .write_room = cyberjack_write_room,
.read_int_callback = cyberjack_read_int_callback,
.read_bulk_callback = cyberjack_read_bulk_callback,
.write_bulk_callback = cyberjack_write_bulk_callback,
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 6bc1f404e186..57b8e27285fc 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -193,6 +193,7 @@ static struct usb_serial_driver cypress_earthmate_device = {
.name = "earthmate",
},
.description = "DeLorme Earthmate USB",
+ .usb_driver = &cypress_driver,
.id_table = id_table_earthmate,
.num_interrupt_in = 1,
.num_interrupt_out = 1,
@@ -222,6 +223,7 @@ static struct usb_serial_driver cypress_hidcom_device = {
.name = "cyphidcom",
},
.description = "HID->COM RS232 Adapter",
+ .usb_driver = &cypress_driver,
.id_table = id_table_cyphidcomrs232,
.num_interrupt_in = 1,
.num_interrupt_out = 1,
@@ -251,6 +253,7 @@ static struct usb_serial_driver cypress_ca42v2_device = {
.name = "nokiaca42v2",
},
.description = "Nokia CA-42 V2 Adapter",
+ .usb_driver = &cypress_driver,
.id_table = id_table_nokiaca42v2,
.num_interrupt_in = 1,
.num_interrupt_out = 1,
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index efd9ce3f931f..0b0fb51bad3e 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -509,6 +509,7 @@ static struct usb_serial_driver digi_acceleport_2_device = {
.name = "digi_2",
},
.description = "Digi 2 port USB adapter",
+ .usb_driver = &digi_driver,
.id_table = id_table_2,
.num_interrupt_in = 0,
.num_bulk_in = 4,
@@ -538,6 +539,7 @@ static struct usb_serial_driver digi_acceleport_4_device = {
.name = "digi_4",
},
.description = "Digi 4 port USB adapter",
+ .usb_driver = &digi_driver,
.id_table = id_table_4,
.num_interrupt_in = 0,
.num_bulk_in = 5,
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 92beeb19795f..4703c8f85383 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -117,6 +117,7 @@ static struct usb_serial_driver empeg_device = {
.name = "empeg",
},
.id_table = id_table,
+ .usb_driver = &empeg_driver,
.num_interrupt_in = 0,
.num_bulk_in = 1,
.num_bulk_out = 1,
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 6986e756f7c0..4695952b6470 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -464,7 +464,6 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },
{ USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) },
{ USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) },
- { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_0_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) },
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_0_PID) },
@@ -615,6 +614,7 @@ static struct usb_serial_driver ftdi_sio_device = {
.name = "ftdi_sio",
},
.description = "FTDI USB Serial Device",
+ .usb_driver = &ftdi_driver ,
.id_table = id_table_combined,
.num_interrupt_in = 0,
.num_bulk_in = 1,
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 40dd394de58d..7eff1c03ba80 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -364,7 +364,6 @@
* USB-TTY activ, USB-TTY passiv. Some PIDs are used by several devices
* and I'm not entirely sure which are used by which.
*/
-#define FTDI_4N_GALAXY_DE_0_PID 0x8372
#define FTDI_4N_GALAXY_DE_1_PID 0xF3C0
#define FTDI_4N_GALAXY_DE_2_PID 0xF3C1
diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c
index 2bebd63d5ed1..4092f6dc9efd 100644
--- a/drivers/usb/serial/funsoft.c
+++ b/drivers/usb/serial/funsoft.c
@@ -58,6 +58,7 @@ static struct usb_serial_driver funsoft_device = {
.name = "funsoft",
},
.id_table = id_table,
+ .usb_driver = &funsoft_driver,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
.num_bulk_out = NUM_DONT_CARE,
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 6530d391ebed..74660a3aa670 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -1566,6 +1566,7 @@ static struct usb_serial_driver garmin_device = {
.name = "garmin_gps",
},
.description = "Garmin GPS usb/tty",
+ .usb_driver = &garmin_driver,
.id_table = id_table,
.num_interrupt_in = 1,
.num_bulk_in = 1,
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 36042937e77f..601e0648dec6 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -20,6 +20,10 @@
#include <linux/usb/serial.h>
#include <asm/uaccess.h>
+static int generic_probe(struct usb_interface *interface,
+ const struct usb_device_id *id);
+
+
static int debug;
#ifdef CONFIG_USB_SERIAL_GENERIC
@@ -34,6 +38,21 @@ MODULE_PARM_DESC(product, "User specified USB idProduct");
static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */
+/* we want to look at all devices, as the vendor/product id can change
+ * depending on the command line argument */
+static struct usb_device_id generic_serial_ids[] = {
+ {.driver_info = 42},
+ {}
+};
+
+static struct usb_driver generic_driver = {
+ .name = "usbserial_generic",
+ .probe = generic_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = generic_serial_ids,
+ .no_dynamic_id = 1,
+};
+
/* All of the device info needed for the Generic Serial Converter */
struct usb_serial_driver usb_serial_generic_device = {
.driver = {
@@ -41,6 +60,7 @@ struct usb_serial_driver usb_serial_generic_device = {
.name = "generic",
},
.id_table = generic_device_ids,
+ .usb_driver = &generic_driver,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
.num_bulk_out = NUM_DONT_CARE,
@@ -48,13 +68,6 @@ struct usb_serial_driver usb_serial_generic_device = {
.shutdown = usb_serial_generic_shutdown,
};
-/* we want to look at all devices, as the vendor/product id can change
- * depending on the command line argument */
-static struct usb_device_id generic_serial_ids[] = {
- {.driver_info = 42},
- {}
-};
-
static int generic_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
@@ -65,14 +78,6 @@ static int generic_probe(struct usb_interface *interface,
return usb_serial_probe(interface, id);
return -ENODEV;
}
-
-static struct usb_driver generic_driver = {
- .name = "usbserial_generic",
- .probe = generic_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = generic_serial_ids,
- .no_dynamic_id = 1,
-};
#endif
int usb_serial_generic_register (int _debug)
diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
index ebcac701b069..6c6ebae741c9 100644
--- a/drivers/usb/serial/hp4x.c
+++ b/drivers/usb/serial/hp4x.c
@@ -49,6 +49,7 @@ static struct usb_serial_driver hp49gp_device = {
.name = "hp4X",
},
.id_table = id_table,
+ .usb_driver = &hp49gp_driver,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
.num_bulk_out = NUM_DONT_CARE,
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index f623d58370a4..6a26a2e683a6 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -146,6 +146,8 @@ struct edgeport_serial {
struct edge_manuf_descriptor manuf_descriptor; /* the manufacturer descriptor */
struct edge_boot_descriptor boot_descriptor; /* the boot firmware descriptor */
struct edgeport_product_info product_info; /* Product Info */
+ struct edge_compatibility_descriptor epic_descriptor; /* Edgeport compatible descriptor */
+ int is_epic; /* flag if EPiC device or not */
__u8 interrupt_in_endpoint; /* the interrupt endpoint handle */
unsigned char * interrupt_in_buffer; /* the buffer we use for the interrupt endpoint */
@@ -240,14 +242,6 @@ static void edge_shutdown (struct usb_serial *serial);
#include "io_tables.h" /* all of the devices that this driver supports */
-static struct usb_driver io_driver = {
- .name = "io_edgeport",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = id_table_combined,
- .no_dynamic_id = 1,
-};
-
/* function prototypes for all of our local functions */
static void process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char *buffer, __u16 bufferLength);
static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2, __u8 byte3);
@@ -397,6 +391,7 @@ static int get_string (struct usb_device *dev, int Id, char *string, int buflen)
unicode_to_ascii(string, buflen, pStringDesc->wData, pStringDesc->bLength/2);
kfree(pStringDesc);
+ dbg("%s - USB String %s", __FUNCTION__, string);
return strlen(string);
}
@@ -434,6 +429,34 @@ static int get_string_desc (struct usb_device *dev, int Id, struct usb_string_de
}
#endif
+static void dump_product_info(struct edgeport_product_info *product_info)
+{
+ // Dump Product Info structure
+ dbg("**Product Information:");
+ dbg(" ProductId %x", product_info->ProductId );
+ dbg(" NumPorts %d", product_info->NumPorts );
+ dbg(" ProdInfoVer %d", product_info->ProdInfoVer );
+ dbg(" IsServer %d", product_info->IsServer);
+ dbg(" IsRS232 %d", product_info->IsRS232 );
+ dbg(" IsRS422 %d", product_info->IsRS422 );
+ dbg(" IsRS485 %d", product_info->IsRS485 );
+ dbg(" RomSize %d", product_info->RomSize );
+ dbg(" RamSize %d", product_info->RamSize );
+ dbg(" CpuRev %x", product_info->CpuRev );
+ dbg(" BoardRev %x", product_info->BoardRev);
+ dbg(" BootMajorVersion %d.%d.%d", product_info->BootMajorVersion,
+ product_info->BootMinorVersion,
+ le16_to_cpu(product_info->BootBuildNumber));
+ dbg(" FirmwareMajorVersion %d.%d.%d", product_info->FirmwareMajorVersion,
+ product_info->FirmwareMinorVersion,
+ le16_to_cpu(product_info->FirmwareBuildNumber));
+ dbg(" ManufactureDescDate %d/%d/%d", product_info->ManufactureDescDate[0],
+ product_info->ManufactureDescDate[1],
+ product_info->ManufactureDescDate[2]+1900);
+ dbg(" iDownloadFile 0x%x", product_info->iDownloadFile);
+ dbg(" EpicVer %d", product_info->EpicVer);
+}
+
static void get_product_info(struct edgeport_serial *edge_serial)
{
struct edgeport_product_info *product_info = &edge_serial->product_info;
@@ -495,30 +518,60 @@ static void get_product_info(struct edgeport_serial *edge_serial)
break;
}
- // Dump Product Info structure
- dbg("**Product Information:");
- dbg(" ProductId %x", product_info->ProductId );
- dbg(" NumPorts %d", product_info->NumPorts );
- dbg(" ProdInfoVer %d", product_info->ProdInfoVer );
- dbg(" IsServer %d", product_info->IsServer);
- dbg(" IsRS232 %d", product_info->IsRS232 );
- dbg(" IsRS422 %d", product_info->IsRS422 );
- dbg(" IsRS485 %d", product_info->IsRS485 );
- dbg(" RomSize %d", product_info->RomSize );
- dbg(" RamSize %d", product_info->RamSize );
- dbg(" CpuRev %x", product_info->CpuRev );
- dbg(" BoardRev %x", product_info->BoardRev);
- dbg(" BootMajorVersion %d.%d.%d", product_info->BootMajorVersion,
- product_info->BootMinorVersion,
- le16_to_cpu(product_info->BootBuildNumber));
- dbg(" FirmwareMajorVersion %d.%d.%d", product_info->FirmwareMajorVersion,
- product_info->FirmwareMinorVersion,
- le16_to_cpu(product_info->FirmwareBuildNumber));
- dbg(" ManufactureDescDate %d/%d/%d", product_info->ManufactureDescDate[0],
- product_info->ManufactureDescDate[1],
- product_info->ManufactureDescDate[2]+1900);
- dbg(" iDownloadFile 0x%x", product_info->iDownloadFile);
+ dump_product_info(product_info);
+}
+static int get_epic_descriptor(struct edgeport_serial *ep)
+{
+ int result;
+ struct usb_serial *serial = ep->serial;
+ struct edgeport_product_info *product_info = &ep->product_info;
+ struct edge_compatibility_descriptor *epic = &ep->epic_descriptor;
+ struct edge_compatibility_bits *bits;
+
+ ep->is_epic = 0;
+ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ USB_REQUEST_ION_GET_EPIC_DESC,
+ 0xC0, 0x00, 0x00,
+ &ep->epic_descriptor,
+ sizeof(struct edge_compatibility_descriptor),
+ 300);
+
+ dbg("%s result = %d", __FUNCTION__, result);
+
+ if (result > 0) {
+ ep->is_epic = 1;
+ memset(product_info, 0, sizeof(struct edgeport_product_info));
+
+ product_info->NumPorts = epic->NumPorts;
+ product_info->ProdInfoVer = 0;
+ product_info->FirmwareMajorVersion = epic->MajorVersion;
+ product_info->FirmwareMinorVersion = epic->MinorVersion;
+ product_info->FirmwareBuildNumber = epic->BuildNumber;
+ product_info->iDownloadFile = epic->iDownloadFile;
+ product_info->EpicVer = epic->EpicVer;
+ product_info->Epic = epic->Supports;
+ product_info->ProductId = ION_DEVICE_ID_EDGEPORT_COMPATIBLE;
+ dump_product_info(product_info);
+
+ bits = &ep->epic_descriptor.Supports;
+ dbg("**EPIC descriptor:");
+ dbg(" VendEnableSuspend: %s", bits->VendEnableSuspend ? "TRUE": "FALSE");
+ dbg(" IOSPOpen : %s", bits->IOSPOpen ? "TRUE": "FALSE" );
+ dbg(" IOSPClose : %s", bits->IOSPClose ? "TRUE": "FALSE" );
+ dbg(" IOSPChase : %s", bits->IOSPChase ? "TRUE": "FALSE" );
+ dbg(" IOSPSetRxFlow : %s", bits->IOSPSetRxFlow ? "TRUE": "FALSE" );
+ dbg(" IOSPSetTxFlow : %s", bits->IOSPSetTxFlow ? "TRUE": "FALSE" );
+ dbg(" IOSPSetXChar : %s", bits->IOSPSetXChar ? "TRUE": "FALSE" );
+ dbg(" IOSPRxCheck : %s", bits->IOSPRxCheck ? "TRUE": "FALSE" );
+ dbg(" IOSPSetClrBreak : %s", bits->IOSPSetClrBreak ? "TRUE": "FALSE" );
+ dbg(" IOSPWriteMCR : %s", bits->IOSPWriteMCR ? "TRUE": "FALSE" );
+ dbg(" IOSPWriteLCR : %s", bits->IOSPWriteLCR ? "TRUE": "FALSE" );
+ dbg(" IOSPSetBaudRate : %s", bits->IOSPSetBaudRate ? "TRUE": "FALSE" );
+ dbg(" TrueEdgeport : %s", bits->TrueEdgeport ? "TRUE": "FALSE" );
+ }
+
+ return result;
}
@@ -1017,21 +1070,29 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
edge_port->closePending = TRUE;
- /* flush and chase */
- edge_port->chaseResponsePending = TRUE;
-
- dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__);
- status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
- if (status == 0) {
- // block until chase finished
- block_until_chase_response(edge_port);
- } else {
- edge_port->chaseResponsePending = FALSE;
+ if ((!edge_serial->is_epic) ||
+ ((edge_serial->is_epic) &&
+ (edge_serial->epic_descriptor.Supports.IOSPChase))) {
+ /* flush and chase */
+ edge_port->chaseResponsePending = TRUE;
+
+ dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__);
+ status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
+ if (status == 0) {
+ // block until chase finished
+ block_until_chase_response(edge_port);
+ } else {
+ edge_port->chaseResponsePending = FALSE;
+ }
}
- /* close the port */
- dbg("%s - Sending IOSP_CMD_CLOSE_PORT", __FUNCTION__);
- send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0);
+ if ((!edge_serial->is_epic) ||
+ ((edge_serial->is_epic) &&
+ (edge_serial->epic_descriptor.Supports.IOSPClose))) {
+ /* close the port */
+ dbg("%s - Sending IOSP_CMD_CLOSE_PORT", __FUNCTION__);
+ send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0);
+ }
//port->close = TRUE;
edge_port->closePending = FALSE;
@@ -1694,29 +1755,38 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
static void edge_break (struct usb_serial_port *port, int break_state)
{
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+ struct edgeport_serial *edge_serial = usb_get_serial_data(port->serial);
int status;
- /* flush and chase */
- edge_port->chaseResponsePending = TRUE;
-
- dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__);
- status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
- if (status == 0) {
- // block until chase finished
- block_until_chase_response(edge_port);
- } else {
- edge_port->chaseResponsePending = FALSE;
+ if ((!edge_serial->is_epic) ||
+ ((edge_serial->is_epic) &&
+ (edge_serial->epic_descriptor.Supports.IOSPChase))) {
+ /* flush and chase */
+ edge_port->chaseResponsePending = TRUE;
+
+ dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__);
+ status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
+ if (status == 0) {
+ // block until chase finished
+ block_until_chase_response(edge_port);
+ } else {
+ edge_port->chaseResponsePending = FALSE;
+ }
}
- if (break_state == -1) {
- dbg("%s - Sending IOSP_CMD_SET_BREAK", __FUNCTION__);
- status = send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_BREAK, 0);
- } else {
- dbg("%s - Sending IOSP_CMD_CLEAR_BREAK", __FUNCTION__);
- status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CLEAR_BREAK, 0);
- }
- if (status) {
- dbg("%s - error sending break set/clear command.", __FUNCTION__);
+ if ((!edge_serial->is_epic) ||
+ ((edge_serial->is_epic) &&
+ (edge_serial->epic_descriptor.Supports.IOSPSetClrBreak))) {
+ if (break_state == -1) {
+ dbg("%s - Sending IOSP_CMD_SET_BREAK", __FUNCTION__);
+ status = send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_BREAK, 0);
+ } else {
+ dbg("%s - Sending IOSP_CMD_CLEAR_BREAK", __FUNCTION__);
+ status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CLEAR_BREAK, 0);
+ }
+ if (status) {
+ dbg("%s - error sending break set/clear command.", __FUNCTION__);
+ }
}
return;
@@ -2288,6 +2358,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
*****************************************************************************/
static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRate)
{
+ struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial);
unsigned char *cmdBuffer;
unsigned char *currCmd;
int cmdLen = 0;
@@ -2295,6 +2366,14 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa
int status;
unsigned char number = edge_port->port->number - edge_port->port->serial->minor;
+ if ((!edge_serial->is_epic) ||
+ ((edge_serial->is_epic) &&
+ (!edge_serial->epic_descriptor.Supports.IOSPSetBaudRate))) {
+ dbg("SendCmdWriteBaudRate - NOT Setting baud rate for port = %d, baud = %d",
+ edge_port->port->number, baudRate);
+ return 0;
+ }
+
dbg("%s - port = %d, baud = %d", __FUNCTION__, edge_port->port->number, baudRate);
status = calc_baud_rate_divisor (baudRate, &divisor);
@@ -2374,6 +2453,7 @@ static int calc_baud_rate_divisor (int baudrate, int *divisor)
*****************************************************************************/
static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 regNum, __u8 regValue)
{
+ struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial);
unsigned char *cmdBuffer;
unsigned char *currCmd;
unsigned long cmdLen = 0;
@@ -2381,6 +2461,22 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
dbg("%s - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", __FUNCTION__, regValue);
+ if ((!edge_serial->is_epic) ||
+ ((edge_serial->is_epic) &&
+ (!edge_serial->epic_descriptor.Supports.IOSPWriteMCR) &&
+ (regNum == MCR))) {
+ dbg("SendCmdWriteUartReg - Not writting to MCR Register");
+ return 0;
+ }
+
+ if ((!edge_serial->is_epic) ||
+ ((edge_serial->is_epic) &&
+ (!edge_serial->epic_descriptor.Supports.IOSPWriteLCR) &&
+ (regNum == LCR))) {
+ dbg ("SendCmdWriteUartReg - Not writting to LCR Register");
+ return 0;
+ }
+
// Alloc memory for the string of commands.
cmdBuffer = kmalloc (0x10, GFP_ATOMIC);
if (cmdBuffer == NULL ) {
@@ -2414,6 +2510,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
#endif
static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios)
{
+ struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial);
struct tty_struct *tty;
int baud;
unsigned cflag;
@@ -2494,8 +2591,12 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
unsigned char stop_char = STOP_CHAR(tty);
unsigned char start_char = START_CHAR(tty);
- send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XON_CHAR, start_char);
- send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XOFF_CHAR, stop_char);
+ if ((!edge_serial->is_epic) ||
+ ((edge_serial->is_epic) &&
+ (edge_serial->epic_descriptor.Supports.IOSPSetXChar))) {
+ send_iosp_ext_cmd(edge_port, IOSP_CMD_SET_XON_CHAR, start_char);
+ send_iosp_ext_cmd(edge_port, IOSP_CMD_SET_XOFF_CHAR, stop_char);
+ }
/* if we are implementing INBOUND XON/XOFF */
if (I_IXOFF(tty)) {
@@ -2515,8 +2616,14 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
}
/* Set flow control to the configured value */
- send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_RX_FLOW, rxFlow);
- send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_TX_FLOW, txFlow);
+ if ((!edge_serial->is_epic) ||
+ ((edge_serial->is_epic) &&
+ (edge_serial->epic_descriptor.Supports.IOSPSetRxFlow)))
+ send_iosp_ext_cmd(edge_port, IOSP_CMD_SET_RX_FLOW, rxFlow);
+ if ((!edge_serial->is_epic) ||
+ ((edge_serial->is_epic) &&
+ (edge_serial->epic_descriptor.Supports.IOSPSetTxFlow)))
+ send_iosp_ext_cmd(edge_port, IOSP_CMD_SET_TX_FLOW, txFlow);
edge_port->shadowLCR &= ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK);
@@ -2728,6 +2835,13 @@ static int edge_startup (struct usb_serial *serial)
struct edgeport_port *edge_port;
struct usb_device *dev;
int i, j;
+ int response;
+ int interrupt_in_found;
+ int bulk_in_found;
+ int bulk_out_found;
+ static __u32 descriptor[3] = { EDGE_COMPATIBILITY_MASK0,
+ EDGE_COMPATIBILITY_MASK1,
+ EDGE_COMPATIBILITY_MASK2 };
dev = serial->dev;
@@ -2750,38 +2864,50 @@ static int edge_startup (struct usb_serial *serial)
dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name);
- /* get the manufacturing descriptor for this device */
- get_manufacturing_desc (edge_serial);
+ /* Read the epic descriptor */
+ if (get_epic_descriptor(edge_serial) <= 0) {
+ /* memcpy descriptor to Supports structures */
+ memcpy(&edge_serial->epic_descriptor.Supports, descriptor,
+ sizeof(struct edge_compatibility_bits));
+
+ /* get the manufacturing descriptor for this device */
+ get_manufacturing_desc (edge_serial);
- /* get the boot descriptor */
- get_boot_desc (edge_serial);
+ /* get the boot descriptor */
+ get_boot_desc (edge_serial);
- get_product_info(edge_serial);
+ get_product_info(edge_serial);
+ }
/* set the number of ports from the manufacturing description */
/* serial->num_ports = serial->product_info.NumPorts; */
- if (edge_serial->product_info.NumPorts != serial->num_ports) {
- warn("%s - Device Reported %d serial ports vs core "
- "thinking we have %d ports, email greg@kroah.com this info.",
- __FUNCTION__, edge_serial->product_info.NumPorts,
- serial->num_ports);
+ if ((!edge_serial->is_epic) &&
+ (edge_serial->product_info.NumPorts != serial->num_ports)) {
+ dev_warn(&serial->dev->dev, "Device Reported %d serial ports "
+ "vs. core thinking we have %d ports, email "
+ "greg@kroah.com this information.",
+ edge_serial->product_info.NumPorts,
+ serial->num_ports);
}
dbg("%s - time 1 %ld", __FUNCTION__, jiffies);
- /* now load the application firmware into this device */
- load_application_firmware (edge_serial);
+ /* If not an EPiC device */
+ if (!edge_serial->is_epic) {
+ /* now load the application firmware into this device */
+ load_application_firmware (edge_serial);
- dbg("%s - time 2 %ld", __FUNCTION__, jiffies);
+ dbg("%s - time 2 %ld", __FUNCTION__, jiffies);
- /* Check current Edgeport EEPROM and update if necessary */
- update_edgeport_E2PROM (edge_serial);
-
- dbg("%s - time 3 %ld", __FUNCTION__, jiffies);
+ /* Check current Edgeport EEPROM and update if necessary */
+ update_edgeport_E2PROM (edge_serial);
- /* set the configuration to use #1 */
-// dbg("set_configuration 1");
-// usb_set_configuration (dev, 1);
+ dbg("%s - time 3 %ld", __FUNCTION__, jiffies);
+
+ /* set the configuration to use #1 */
+// dbg("set_configuration 1");
+// usb_set_configuration (dev, 1);
+ }
/* we set up the pointers to the endpoints in the edge_open function,
* as the structures aren't created yet. */
@@ -2804,8 +2930,101 @@ static int edge_startup (struct usb_serial *serial)
edge_port->port = serial->port[i];
usb_set_serial_port_data(serial->port[i], edge_port);
}
-
- return 0;
+
+ response = 0;
+
+ if (edge_serial->is_epic) {
+ /* EPIC thing, set up our interrupt polling now and our read urb, so
+ * that the device knows it really is connected. */
+ interrupt_in_found = bulk_in_found = bulk_out_found = FALSE;
+ for (i = 0; i < serial->interface->altsetting[0].desc.bNumEndpoints; ++i) {
+ struct usb_endpoint_descriptor *endpoint;
+ int buffer_size;
+
+ endpoint = &serial->interface->altsetting[0].endpoint[i].desc;
+ buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+ if ((!interrupt_in_found) &&
+ (usb_endpoint_is_int_in(endpoint))) {
+ /* we found a interrupt in endpoint */
+ dbg("found interrupt in");
+
+ /* not set up yet, so do it now */
+ edge_serial->interrupt_read_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!edge_serial->interrupt_read_urb) {
+ err("out of memory");
+ return -ENOMEM;
+ }
+ edge_serial->interrupt_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+ if (!edge_serial->interrupt_in_buffer) {
+ err("out of memory");
+ usb_free_urb(edge_serial->interrupt_read_urb);
+ return -ENOMEM;
+ }
+ edge_serial->interrupt_in_endpoint = endpoint->bEndpointAddress;
+
+ /* set up our interrupt urb */
+ usb_fill_int_urb(edge_serial->interrupt_read_urb,
+ dev,
+ usb_rcvintpipe(dev, endpoint->bEndpointAddress),
+ edge_serial->interrupt_in_buffer,
+ buffer_size,
+ edge_interrupt_callback,
+ edge_serial,
+ endpoint->bInterval);
+
+ interrupt_in_found = TRUE;
+ }
+
+ if ((!bulk_in_found) &&
+ (usb_endpoint_is_bulk_in(endpoint))) {
+ /* we found a bulk in endpoint */
+ dbg("found bulk in");
+
+ /* not set up yet, so do it now */
+ edge_serial->read_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!edge_serial->read_urb) {
+ err("out of memory");
+ return -ENOMEM;
+ }
+ edge_serial->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+ if (!edge_serial->bulk_in_buffer) {
+ err ("out of memory");
+ usb_free_urb(edge_serial->read_urb);
+ return -ENOMEM;
+ }
+ edge_serial->bulk_in_endpoint = endpoint->bEndpointAddress;
+
+ /* set up our bulk in urb */
+ usb_fill_bulk_urb(edge_serial->read_urb, dev,
+ usb_rcvbulkpipe(dev, endpoint->bEndpointAddress),
+ edge_serial->bulk_in_buffer,
+ endpoint->wMaxPacketSize,
+ edge_bulk_in_callback,
+ edge_serial);
+ bulk_in_found = TRUE;
+ }
+
+ if ((!bulk_out_found) &&
+ (usb_endpoint_is_bulk_out(endpoint))) {
+ /* we found a bulk out endpoint */
+ dbg("found bulk out");
+ edge_serial->bulk_out_endpoint = endpoint->bEndpointAddress;
+ bulk_out_found = TRUE;
+ }
+ }
+
+ if ((!interrupt_in_found) || (!bulk_in_found) || (!bulk_out_found)) {
+ err ("Error - the proper endpoints were not found!");
+ return -ENODEV;
+ }
+
+ /* start interrupt read for this edgeport this interrupt will
+ * continue as long as the edgeport is connected */
+ response = usb_submit_urb(edge_serial->interrupt_read_urb, GFP_KERNEL);
+ if (response)
+ err("%s - Error %d submitting control urb", __FUNCTION__, response);
+ }
+ return response;
}
@@ -2815,6 +3034,7 @@ static int edge_startup (struct usb_serial *serial)
****************************************************************************/
static void edge_shutdown (struct usb_serial *serial)
{
+ struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
int i;
dbg("%s", __FUNCTION__);
@@ -2824,7 +3044,18 @@ static void edge_shutdown (struct usb_serial *serial)
kfree (usb_get_serial_port_data(serial->port[i]));
usb_set_serial_port_data(serial->port[i], NULL);
}
- kfree (usb_get_serial_data(serial));
+ /* free up our endpoint stuff */
+ if (edge_serial->is_epic) {
+ usb_unlink_urb(edge_serial->interrupt_read_urb);
+ usb_free_urb(edge_serial->interrupt_read_urb);
+ kfree(edge_serial->interrupt_in_buffer);
+
+ usb_unlink_urb(edge_serial->read_urb);
+ usb_free_urb(edge_serial->read_urb);
+ kfree(edge_serial->bulk_in_buffer);
+ }
+
+ kfree(edge_serial);
usb_set_serial_data(serial, NULL);
}
@@ -2846,6 +3077,9 @@ static int __init edgeport_init(void)
retval = usb_serial_register(&edgeport_8port_device);
if (retval)
goto failed_8port_device_register;
+ retval = usb_serial_register(&epic_device);
+ if (retval)
+ goto failed_epic_device_register;
retval = usb_register(&io_driver);
if (retval)
goto failed_usb_register;
@@ -2853,6 +3087,8 @@ static int __init edgeport_init(void)
return 0;
failed_usb_register:
+ usb_serial_deregister(&epic_device);
+failed_epic_device_register:
usb_serial_deregister(&edgeport_8port_device);
failed_8port_device_register:
usb_serial_deregister(&edgeport_4port_device);
@@ -2873,6 +3109,7 @@ static void __exit edgeport_exit (void)
usb_serial_deregister (&edgeport_2port_device);
usb_serial_deregister (&edgeport_4port_device);
usb_serial_deregister (&edgeport_8port_device);
+ usb_serial_deregister (&epic_device);
}
module_init(edgeport_init);
diff --git a/drivers/usb/serial/io_edgeport.h b/drivers/usb/serial/io_edgeport.h
index 123fa8a904e6..29a913a6daca 100644
--- a/drivers/usb/serial/io_edgeport.h
+++ b/drivers/usb/serial/io_edgeport.h
@@ -111,10 +111,12 @@ struct edgeport_product_info {
__le16 FirmwareBuildNumber; /* zzzz (LE format) */
__u8 ManufactureDescDate[3]; /* MM/DD/YY when descriptor template was compiled */
- __u8 Unused1[1]; /* Available */
+ __u8 HardwareType;
__u8 iDownloadFile; /* What to download to EPiC device */
- __u8 Unused2[2]; /* Available */
+ __u8 EpicVer; /* What version of EPiC spec this device supports */
+
+ struct edge_compatibility_bits Epic;
};
/*
diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
index fad561c04c76..6d3008772540 100644
--- a/drivers/usb/serial/io_tables.h
+++ b/drivers/usb/serial/io_tables.h
@@ -47,6 +47,18 @@ static struct usb_device_id edgeport_8port_id_table [] = {
{ }
};
+static struct usb_device_id Epic_port_id_table [] = {
+ { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0202) },
+ { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0203) },
+ { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0310) },
+ { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0311) },
+ { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0312) },
+ { USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A758) },
+ { USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A794) },
+ { USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A225) },
+ { }
+};
+
/* Devices that this driver supports */
static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4) },
@@ -70,17 +82,34 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8R) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8RR) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_412_8) },
+ { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0202) },
+ { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0203) },
+ { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0310) },
+ { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0311) },
+ { USB_DEVICE(USB_VENDOR_ID_NCR, NCR_DEVICE_ID_EPIC_0312) },
+ { USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A758) },
+ { USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A794) },
+ { USB_DEVICE(USB_VENDOR_ID_AXIOHM, AXIOHM_DEVICE_ID_EPIC_A225) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, id_table_combined);
+static struct usb_driver io_driver = {
+ .name = "io_edgeport",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = id_table_combined,
+ .no_dynamic_id = 1,
+};
+
static struct usb_serial_driver edgeport_2port_device = {
.driver = {
.owner = THIS_MODULE,
.name = "edgeport_2",
},
.description = "Edgeport 2 port adapter",
+ .usb_driver = &io_driver,
.id_table = edgeport_2port_id_table,
.num_interrupt_in = 1,
.num_bulk_in = 1,
@@ -111,6 +140,7 @@ static struct usb_serial_driver edgeport_4port_device = {
.name = "edgeport_4",
},
.description = "Edgeport 4 port adapter",
+ .usb_driver = &io_driver,
.id_table = edgeport_4port_id_table,
.num_interrupt_in = 1,
.num_bulk_in = 1,
@@ -141,6 +171,7 @@ static struct usb_serial_driver edgeport_8port_device = {
.name = "edgeport_8",
},
.description = "Edgeport 8 port adapter",
+ .usb_driver = &io_driver,
.id_table = edgeport_8port_id_table,
.num_interrupt_in = 1,
.num_bulk_in = 1,
@@ -165,5 +196,35 @@ static struct usb_serial_driver edgeport_8port_device = {
.write_bulk_callback = edge_bulk_out_data_callback,
};
+static struct usb_serial_driver epic_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "epic",
+ },
+ .description = "EPiC device",
+ .id_table = Epic_port_id_table,
+ .num_interrupt_in = 1,
+ .num_bulk_in = 1,
+ .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = edge_open,
+ .close = edge_close,
+ .throttle = edge_throttle,
+ .unthrottle = edge_unthrottle,
+ .attach = edge_startup,
+ .shutdown = edge_shutdown,
+ .ioctl = edge_ioctl,
+ .set_termios = edge_set_termios,
+ .tiocmget = edge_tiocmget,
+ .tiocmset = edge_tiocmset,
+ .write = edge_write,
+ .write_room = edge_write_room,
+ .chars_in_buffer = edge_chars_in_buffer,
+ .break_ctl = edge_break,
+ .read_int_callback = edge_interrupt_callback,
+ .read_bulk_callback = edge_bulk_in_callback,
+ .write_bulk_callback = edge_bulk_out_data_callback,
+};
+
#endif
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 980285c0233a..544098d2b775 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -2979,6 +2979,7 @@ static struct usb_serial_driver edgeport_1port_device = {
.name = "edgeport_ti_1",
},
.description = "Edgeport TI 1 port adapter",
+ .usb_driver = &io_driver,
.id_table = edgeport_1port_id_table,
.num_interrupt_in = 1,
.num_bulk_in = 1,
@@ -3009,6 +3010,7 @@ static struct usb_serial_driver edgeport_2port_device = {
.name = "edgeport_ti_2",
},
.description = "Edgeport TI 2 port adapter",
+ .usb_driver = &io_driver,
.id_table = edgeport_2port_id_table,
.num_interrupt_in = 1,
.num_bulk_in = 2,
diff --git a/drivers/usb/serial/io_usbvend.h b/drivers/usb/serial/io_usbvend.h
index f1804fd5a3dd..e57fa117e486 100644
--- a/drivers/usb/serial/io_usbvend.h
+++ b/drivers/usb/serial/io_usbvend.h
@@ -30,6 +30,7 @@
#define USB_VENDOR_ID_ION 0x1608 // Our VID
#define USB_VENDOR_ID_TI 0x0451 // TI VID
+#define USB_VENDOR_ID_AXIOHM 0x05D9 /* Axiohm VID */
//
// Definitions of USB product IDs (PID)
@@ -334,6 +335,10 @@ struct edge_compatibility_bits
};
+#define EDGE_COMPATIBILITY_MASK0 0x0001
+#define EDGE_COMPATIBILITY_MASK1 0x3FFF
+#define EDGE_COMPATIBILITY_MASK2 0x0001
+
struct edge_compatibility_descriptor
{
__u8 Length; // Descriptor Length (per USB spec)
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 42f757a5b876..a408184334ea 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -563,6 +563,7 @@ static struct usb_serial_driver ipaq_device = {
.name = "ipaq",
},
.description = "PocketPC PDA",
+ .usb_driver = &ipaq_driver,
.id_table = ipaq_id_table,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = 1,
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index d3b9a351cef8..1bc586064c77 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -442,6 +442,7 @@ static struct usb_serial_driver ipw_device = {
.name = "ipw",
},
.description = "IPWireless converter",
+ .usb_driver = &usb_ipw_driver,
.id_table = usb_ipw_ids,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = 1,
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 8fdf486e3465..9d847f69291c 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -138,6 +138,7 @@ static struct usb_serial_driver ir_device = {
.name = "ir-usb",
},
.description = "IR Dongle",
+ .usb_driver = &ir_driver,
.id_table = id_table,
.num_interrupt_in = 1,
.num_bulk_in = 1,
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 9d2fdfd6865f..e6966f12ed5a 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -1275,11 +1275,31 @@ static int keyspan_fake_startup (struct usb_serial *serial)
}
/* Helper functions used by keyspan_setup_urbs */
+static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *serial,
+ int endpoint)
+{
+ struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *ep;
+ int i;
+
+ iface_desc = serial->interface->cur_altsetting;
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+ ep = &iface_desc->endpoint[i].desc;
+ if (ep->bEndpointAddress == endpoint)
+ return ep;
+ }
+ dev_warn(&serial->interface->dev, "found no endpoint descriptor for "
+ "endpoint %x\n", endpoint);
+ return NULL;
+}
+
static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint,
int dir, void *ctx, char *buf, int len,
void (*callback)(struct urb *))
{
struct urb *urb;
+ struct usb_endpoint_descriptor const *ep_desc;
+ char const *ep_type_name;
if (endpoint == -1)
return NULL; /* endpoint not needed */
@@ -1291,11 +1311,32 @@ static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint,
return NULL;
}
- /* Fill URB using supplied data. */
- usb_fill_bulk_urb(urb, serial->dev,
- usb_sndbulkpipe(serial->dev, endpoint) | dir,
- buf, len, callback, ctx);
+ ep_desc = find_ep(serial, endpoint);
+ if (!ep_desc) {
+ /* leak the urb, something's wrong and the callers don't care */
+ return urb;
+ }
+ if (usb_endpoint_xfer_int(ep_desc)) {
+ ep_type_name = "INT";
+ usb_fill_int_urb(urb, serial->dev,
+ usb_sndintpipe(serial->dev, endpoint) | dir,
+ buf, len, callback, ctx,
+ ep_desc->bInterval);
+ } else if (usb_endpoint_xfer_bulk(ep_desc)) {
+ ep_type_name = "BULK";
+ usb_fill_bulk_urb(urb, serial->dev,
+ usb_sndbulkpipe(serial->dev, endpoint) | dir,
+ buf, len, callback, ctx);
+ } else {
+ dev_warn(&serial->interface->dev,
+ "unsupported endpoint type %x\n",
+ ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
+ usb_free_urb(urb);
+ return NULL;
+ }
+ dbg("%s - using urb %p for %s endpoint %x",
+ __func__, urb, ep_type_name, endpoint);
return urb;
}
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index 6413d73c139c..c6830cbdc6df 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -229,7 +229,6 @@ struct ezusb_hex_record {
#define keyspan_usa28_product_id 0x010f
#define keyspan_usa28x_product_id 0x0110
#define keyspan_usa28xa_product_id 0x0115
-#define keyspan_usa28xb_product_id 0x0110
#define keyspan_usa49w_product_id 0x010a
#define keyspan_usa49wlc_product_id 0x012a
@@ -511,7 +510,6 @@ static struct usb_device_id keyspan_ids_combined[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
- { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id)},
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
{ } /* Terminating entry */
@@ -559,7 +557,6 @@ static struct usb_device_id keyspan_2port_ids[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
- { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) },
{ } /* Terminating entry */
};
@@ -576,6 +573,7 @@ static struct usb_serial_driver keyspan_pre_device = {
.name = "keyspan_no_firm",
},
.description = "Keyspan - (without firmware)",
+ .usb_driver = &keyspan_driver,
.id_table = keyspan_pre_ids,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
@@ -590,6 +588,7 @@ static struct usb_serial_driver keyspan_1port_device = {
.name = "keyspan_1",
},
.description = "Keyspan 1 port adapter",
+ .usb_driver = &keyspan_driver,
.id_table = keyspan_1port_ids,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
@@ -617,6 +616,7 @@ static struct usb_serial_driver keyspan_2port_device = {
.name = "keyspan_2",
},
.description = "Keyspan 2 port adapter",
+ .usb_driver = &keyspan_driver,
.id_table = keyspan_2port_ids,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
@@ -644,6 +644,7 @@ static struct usb_serial_driver keyspan_4port_device = {
.name = "keyspan_4",
},
.description = "Keyspan 4 port adapter",
+ .usb_driver = &keyspan_driver,
.id_table = keyspan_4port_ids,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = 5,
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 126b9703bbaf..da514cb785b3 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -793,6 +793,7 @@ static struct usb_serial_driver keyspan_pda_fake_device = {
.name = "keyspan_pda_pre",
},
.description = "Keyspan PDA - (prerenumeration)",
+ .usb_driver = &keyspan_pda_driver,
.id_table = id_table_fake,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
@@ -809,6 +810,7 @@ static struct usb_serial_driver xircom_pgs_fake_device = {
.name = "xircom_no_firm",
},
.description = "Xircom / Entregra PGS - (prerenumeration)",
+ .usb_driver = &keyspan_pda_driver,
.id_table = id_table_fake_xircom,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
@@ -824,6 +826,7 @@ static struct usb_serial_driver keyspan_pda_device = {
.name = "keyspan_pda",
},
.description = "Keyspan PDA",
+ .usb_driver = &keyspan_pda_driver,
.id_table = id_table_std,
.num_interrupt_in = 1,
.num_bulk_in = 0,
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 5c4b06a99ac0..b2097c45a235 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -124,6 +124,7 @@ static struct usb_serial_driver kl5kusb105d_device = {
.name = "kl5kusb105d",
},
.description = "KL5KUSB105D / PalmConnect",
+ .usb_driver = &kl5kusb105d_driver,
.id_table = id_table,
.num_interrupt_in = 1,
.num_bulk_in = 1,
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 62bea0c923bd..0683b51f0932 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -110,6 +110,7 @@ static struct usb_serial_driver kobil_device = {
.name = "kobil",
},
.description = "KOBIL USB smart card terminal",
+ .usb_driver = &kobil_driver,
.id_table = id_table,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = 0,
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 38b1d17e06ef..4cd839b1407f 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -137,6 +137,7 @@ static struct usb_serial_driver mct_u232_device = {
.name = "mct_u232",
},
.description = "MCT U232",
+ .usb_driver = &mct_u232_driver,
.id_table = id_table_combined,
.num_interrupt_in = 2,
.num_bulk_in = 0,
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index e55f4ed81d7b..6109c6704a73 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -1605,12 +1605,21 @@ static void mos7720_shutdown(struct usb_serial *serial)
usb_set_serial_data(serial, NULL);
}
+static struct usb_driver usb_driver = {
+ .name = "moschip7720",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = moschip_port_id_table,
+ .no_dynamic_id = 1,
+};
+
static struct usb_serial_driver moschip7720_2port_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "moschip7720",
},
.description = "Moschip 2 port adapter",
+ .usb_driver = &usb_driver,
.id_table = moschip_port_id_table,
.num_interrupt_in = 1,
.num_bulk_in = 2,
@@ -1631,13 +1640,6 @@ static struct usb_serial_driver moschip7720_2port_driver = {
.read_bulk_callback = mos7720_bulk_in_callback,
};
-static struct usb_driver usb_driver = {
- .name = "moschip7720",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = moschip_port_id_table,
-};
-
static int __init moschip7720_init(void)
{
int retval;
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 83f661403ba1..b2264a87617b 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -2834,12 +2834,21 @@ static void mos7840_shutdown(struct usb_serial *serial)
}
+static struct usb_driver io_driver = {
+ .name = "mos7840",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = moschip_id_table_combined,
+ .no_dynamic_id = 1,
+};
+
static struct usb_serial_driver moschip7840_4port_device = {
.driver = {
.owner = THIS_MODULE,
.name = "mos7840",
},
.description = DRIVER_DESC,
+ .usb_driver = &io_driver,
.id_table = moschip_port_id_table,
.num_interrupt_in = 1, //NUM_DONT_CARE,//1,
#ifdef check
@@ -2869,13 +2878,6 @@ static struct usb_serial_driver moschip7840_4port_device = {
.read_int_callback = mos7840_interrupt_callback,
};
-static struct usb_driver io_driver = {
- .name = "mos7840",
- .probe = usb_serial_probe,
- .disconnect = usb_serial_disconnect,
- .id_table = moschip_id_table_combined,
-};
-
/****************************************************************************
* moschip7840_init
* This is called by the module subsystem, or on startup to initialize us
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
index 054abee81652..90701111d746 100644
--- a/drivers/usb/serial/navman.c
+++ b/drivers/usb/serial/navman.c
@@ -119,6 +119,7 @@ static struct usb_serial_driver navman_device = {
.name = "navman",
},
.id_table = id_table,
+ .usb_driver = &navman_driver,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
.num_bulk_out = NUM_DONT_CARE,
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index bc91d3b726fc..0216ac12a27d 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -93,6 +93,7 @@ static struct usb_serial_driver zyxel_omninet_device = {
.name = "omninet",
},
.description = "ZyXEL - omni.net lcd plus usb",
+ .usb_driver = &omninet_driver,
.id_table = id_table,
.num_interrupt_in = 1,
.num_bulk_in = 1,
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 0fed43a96871..ced9f32b29d9 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -135,6 +135,7 @@ static struct usb_serial_driver option_1port_device = {
.name = "option1",
},
.description = "GSM modem (1-port)",
+ .usb_driver = &option_driver,
.id_table = option_ids1,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 5dc2ac9afa90..6c083d4e2c9b 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -1118,6 +1118,7 @@ static struct usb_serial_driver pl2303_device = {
.name = "pl2303",
},
.id_table = id_table,
+ .usb_driver = &pl2303_driver,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = 1,
.num_bulk_out = 1,
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index 30b7ebc8d45d..5a03a3fc9386 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -402,6 +402,7 @@ static struct usb_serial_driver safe_device = {
.name = "safe_serial",
},
.id_table = id_table,
+ .usb_driver = &safe_driver,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
.num_bulk_out = NUM_DONT_CARE,
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 6d8e91e00ecf..ecedd833818d 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -13,10 +13,9 @@
Portions based on the option driver by Matthias Urlichs <smurf@smurf.noris.de>
Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org>
- History:
*/
-#define DRIVER_VERSION "v.1.0.5"
+#define DRIVER_VERSION "v.1.0.6"
#define DRIVER_AUTHOR "Kevin Lloyd <linux@sierrawireless.com>"
#define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
@@ -31,14 +30,15 @@
static struct usb_device_id id_table [] = {
+ { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
{ USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */
+ { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */
{ USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */
- { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
{ USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */
- { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */
+ { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */
{ USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
+ { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */
{ USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */
- { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 for Europe */
{ USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */
{ USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */
@@ -55,14 +55,15 @@ static struct usb_device_id id_table_1port [] = {
};
static struct usb_device_id id_table_3port [] = {
+ { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
{ USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */
+ { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */
{ USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */
- { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
{ USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */
- { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */
+ { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */
{ USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
+ { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */
{ USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */
- { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 for Europe */
{ USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */
{ USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */
{ }
@@ -81,7 +82,7 @@ static int debug;
/* per port private data */
#define N_IN_URB 4
-#define N_OUT_URB 1
+#define N_OUT_URB 4
#define IN_BUFLEN 4096
#define OUT_BUFLEN 128
@@ -396,6 +397,8 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
struct usb_serial *serial = port->serial;
int i, err;
struct urb *urb;
+ int result;
+ __u16 set_mode_dzero = 0x0000;
portdata = usb_get_serial_port_data(port);
@@ -442,6 +445,12 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
port->tty->low_latency = 1;
+ /* set mode to D0 */
+ result = usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ 0x00, 0x40, set_mode_dzero, 0, NULL,
+ 0, USB_CTRL_SET_TIMEOUT);
+
sierra_send_setup(port);
return (0);
@@ -614,6 +623,7 @@ static struct usb_serial_driver sierra_1port_device = {
},
.description = "Sierra USB modem (1 port)",
.id_table = id_table_1port,
+ .usb_driver = &sierra_driver,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = 1,
.num_bulk_out = 1,
@@ -642,6 +652,7 @@ static struct usb_serial_driver sierra_3port_device = {
},
.description = "Sierra USB modem (3 port)",
.id_table = id_table_3port,
+ .usb_driver = &sierra_driver,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = 3,
.num_bulk_out = 3,
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 83189005c6fb..4203e2b1a761 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -262,6 +262,7 @@ static struct usb_serial_driver ti_1port_device = {
.name = "ti_usb_3410_5052_1",
},
.description = "TI USB 3410 1 port adapter",
+ .usb_driver = &ti_usb_driver,
.id_table = ti_id_table_3410,
.num_interrupt_in = 1,
.num_bulk_in = 1,
@@ -292,6 +293,7 @@ static struct usb_serial_driver ti_2port_device = {
.name = "ti_usb_3410_5052_2",
},
.description = "TI USB 5052 2 port adapter",
+ .usb_driver = &ti_usb_driver,
.id_table = ti_id_table_5052,
.num_interrupt_in = 1,
.num_bulk_in = 2,
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 716f6806cc89..6bf22a28adb8 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -59,14 +59,19 @@ static struct usb_driver usb_serial_driver = {
static int debug;
static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */
+static spinlock_t table_lock;
static LIST_HEAD(usb_serial_driver_list);
struct usb_serial *usb_serial_get_by_index(unsigned index)
{
- struct usb_serial *serial = serial_table[index];
+ struct usb_serial *serial;
+
+ spin_lock(&table_lock);
+ serial = serial_table[index];
if (serial)
kref_get(&serial->kref);
+ spin_unlock(&table_lock);
return serial;
}
@@ -78,6 +83,7 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po
dbg("%s %d", __FUNCTION__, num_ports);
*minor = 0;
+ spin_lock(&table_lock);
for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
if (serial_table[i])
continue;
@@ -96,8 +102,10 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po
dbg("%s - minor base = %d", __FUNCTION__, *minor);
for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i)
serial_table[i] = serial;
+ spin_unlock(&table_lock);
return serial;
}
+ spin_unlock(&table_lock);
return NULL;
}
@@ -110,9 +118,11 @@ static void return_serial(struct usb_serial *serial)
if (serial == NULL)
return;
+ spin_lock(&table_lock);
for (i = 0; i < serial->num_ports; ++i) {
serial_table[serial->minor + i] = NULL;
}
+ spin_unlock(&table_lock);
}
static void destroy_serial(struct kref *kref)
@@ -271,7 +281,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count)
{
struct usb_serial_port *port = tty->driver_data;
- int retval = -EINVAL;
+ int retval = -ENODEV;
if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED)
goto exit;
@@ -279,6 +289,7 @@ static int serial_write (struct tty_struct * tty, const unsigned char *buf, int
dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
if (!port->open_count) {
+ retval = -EINVAL;
dbg("%s - port not opened", __FUNCTION__);
goto exit;
}
@@ -559,15 +570,20 @@ static void port_release(struct device *dev)
port_free(port);
}
-static void port_free(struct usb_serial_port *port)
+static void kill_traffic(struct usb_serial_port *port)
{
usb_kill_urb(port->read_urb);
- usb_free_urb(port->read_urb);
usb_kill_urb(port->write_urb);
- usb_free_urb(port->write_urb);
usb_kill_urb(port->interrupt_in_urb);
- usb_free_urb(port->interrupt_in_urb);
usb_kill_urb(port->interrupt_out_urb);
+}
+
+static void port_free(struct usb_serial_port *port)
+{
+ kill_traffic(port);
+ usb_free_urb(port->read_urb);
+ usb_free_urb(port->write_urb);
+ usb_free_urb(port->interrupt_in_urb);
usb_free_urb(port->interrupt_out_urb);
kfree(port->bulk_in_buffer);
kfree(port->bulk_out_buffer);
@@ -596,6 +612,39 @@ static struct usb_serial * create_serial (struct usb_device *dev,
return serial;
}
+static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
+ struct usb_serial_driver *drv)
+{
+ struct usb_dynid *dynid;
+
+ spin_lock(&drv->dynids.lock);
+ list_for_each_entry(dynid, &drv->dynids.list, node) {
+ if (usb_match_one_id(intf, &dynid->id)) {
+ spin_unlock(&drv->dynids.lock);
+ return &dynid->id;
+ }
+ }
+ spin_unlock(&drv->dynids.lock);
+ return NULL;
+}
+
+static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv,
+ struct usb_interface *intf)
+{
+ const struct usb_device_id *id;
+
+ id = usb_match_id(intf, drv->id_table);
+ if (id) {
+ dbg("static descriptor matches");
+ goto exit;
+ }
+ id = match_dynamic_id(intf, drv);
+ if (id)
+ dbg("dynamic descriptor matches");
+exit:
+ return id;
+}
+
static struct usb_serial_driver *search_serial_device(struct usb_interface *iface)
{
struct list_head *p;
@@ -605,11 +654,9 @@ static struct usb_serial_driver *search_serial_device(struct usb_interface *ifac
/* Check if the usb id matches a known device */
list_for_each(p, &usb_serial_driver_list) {
t = list_entry(p, struct usb_serial_driver, driver_list);
- id = usb_match_id(iface, t->id_table);
- if (id != NULL) {
- dbg("descriptor matches");
+ id = get_iface_id(t, iface);
+ if (id)
return t;
- }
}
return NULL;
@@ -639,14 +686,17 @@ int usb_serial_probe(struct usb_interface *interface,
int num_ports = 0;
int max_endpoints;
+ lock_kernel(); /* guard against unloading a serial driver module */
type = search_serial_device(interface);
if (!type) {
+ unlock_kernel();
dbg("none matched");
return -ENODEV;
}
serial = create_serial (dev, interface, type);
if (!serial) {
+ unlock_kernel();
dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__);
return -ENOMEM;
}
@@ -656,16 +706,18 @@ int usb_serial_probe(struct usb_interface *interface,
const struct usb_device_id *id;
if (!try_module_get(type->driver.owner)) {
+ unlock_kernel();
dev_err(&interface->dev, "module get failed, exiting\n");
kfree (serial);
return -EIO;
}
- id = usb_match_id(interface, type->id_table);
+ id = get_iface_id(type, interface);
retval = type->probe(serial, id);
module_put(type->driver.owner);
if (retval) {
+ unlock_kernel();
dbg ("sub driver rejected device");
kfree (serial);
return retval;
@@ -735,6 +787,7 @@ int usb_serial_probe(struct usb_interface *interface,
* properly during a later invocation of usb_serial_probe
*/
if (num_bulk_in == 0 || num_bulk_out == 0) {
+ unlock_kernel();
dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
kfree (serial);
return -ENODEV;
@@ -750,6 +803,7 @@ int usb_serial_probe(struct usb_interface *interface,
if (type == &usb_serial_generic_device) {
num_ports = num_bulk_out;
if (num_ports == 0) {
+ unlock_kernel();
dev_err(&interface->dev, "Generic device with no bulk out, not allowed.\n");
kfree (serial);
return -EIO;
@@ -760,6 +814,7 @@ int usb_serial_probe(struct usb_interface *interface,
/* if this device type has a calc_num_ports function, call it */
if (type->calc_num_ports) {
if (!try_module_get(type->driver.owner)) {
+ unlock_kernel();
dev_err(&interface->dev, "module get failed, exiting\n");
kfree (serial);
return -EIO;
@@ -771,12 +826,6 @@ int usb_serial_probe(struct usb_interface *interface,
num_ports = type->num_ports;
}
- if (get_free_serial (serial, num_ports, &minor) == NULL) {
- dev_err(&interface->dev, "No more free serial devices\n");
- kfree (serial);
- return -ENOMEM;
- }
-
serial->minor = minor;
serial->num_ports = num_ports;
serial->num_bulk_in = num_bulk_in;
@@ -791,6 +840,8 @@ int usb_serial_probe(struct usb_interface *interface,
max_endpoints = max(max_endpoints, num_interrupt_out);
max_endpoints = max(max_endpoints, (int)serial->num_ports);
serial->num_port_pointers = max_endpoints;
+ unlock_kernel();
+
dbg("%s - setting up %d port structures for this device", __FUNCTION__, max_endpoints);
for (i = 0; i < max_endpoints; ++i) {
port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
@@ -925,6 +976,11 @@ int usb_serial_probe(struct usb_interface *interface,
}
}
+ if (get_free_serial (serial, num_ports, &minor) == NULL) {
+ dev_err(&interface->dev, "No more free serial devices\n");
+ goto probe_error;
+ }
+
/* register all of the individual ports with the driver core */
for (i = 0; i < num_ports; ++i) {
port = serial->port[i];
@@ -1002,8 +1058,11 @@ void usb_serial_disconnect(struct usb_interface *interface)
if (serial) {
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
- if (port && port->tty)
- tty_hangup(port->tty);
+ if (port) {
+ if (port->tty)
+ tty_hangup(port->tty);
+ kill_traffic(port);
+ }
}
/* let the last holder of this object
* cause it to be cleaned up */
@@ -1040,6 +1099,7 @@ static int __init usb_serial_init(void)
return -ENOMEM;
/* Initialize our global data */
+ spin_lock_init(&table_lock);
for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
serial_table[i] = NULL;
}
@@ -1138,7 +1198,7 @@ static void fixup_generic(struct usb_serial_driver *device)
set_to_generic_if_null(device, shutdown);
}
-int usb_serial_register(struct usb_serial_driver *driver)
+int usb_serial_register(struct usb_serial_driver *driver) /* must be called with BKL held */
{
int retval;
@@ -1162,7 +1222,7 @@ int usb_serial_register(struct usb_serial_driver *driver)
}
-void usb_serial_deregister(struct usb_serial_driver *device)
+void usb_serial_deregister(struct usb_serial_driver *device) /* must be called with BKL held */
{
info("USB Serial deregistering driver %s", device->description);
list_del(&device->driver_list);
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index b09f06096056..2f59ff226e2c 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -90,8 +90,6 @@ static struct usb_device_id id_table [] = {
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
- { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE31_ID),
- .driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID),
@@ -151,7 +149,6 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_TREO_650) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID) },
- { USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE31_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
@@ -189,6 +186,7 @@ static struct usb_serial_driver handspring_device = {
.name = "visor",
},
.description = "Handspring Visor / Palm OS",
+ .usb_driver = &visor_driver,
.id_table = id_table,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = 2,
@@ -219,6 +217,7 @@ static struct usb_serial_driver clie_5_device = {
.name = "clie_5",
},
.description = "Sony Clie 5.0",
+ .usb_driver = &visor_driver,
.id_table = clie_id_5_table,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = 2,
@@ -249,6 +248,7 @@ static struct usb_serial_driver clie_3_5_device = {
.name = "clie_3.5",
},
.description = "Sony Clie 3.5",
+ .usb_driver = &visor_driver,
.id_table = clie_id_3_5_table,
.num_interrupt_in = 0,
.num_bulk_in = 1,
diff --git a/drivers/usb/serial/visor.h b/drivers/usb/serial/visor.h
index 765118d83fb6..4ce6f62a6f39 100644
--- a/drivers/usb/serial/visor.h
+++ b/drivers/usb/serial/visor.h
@@ -32,7 +32,6 @@
#define PALM_TUNGSTEN_T_ID 0x0060
#define PALM_TREO_650 0x0061
#define PALM_TUNGSTEN_Z_ID 0x0031
-#define PALM_ZIRE31_ID 0x0061
#define PALM_ZIRE_ID 0x0070
#define PALM_M100_ID 0x0080
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 5483d8564c1b..bf16e9e1d84e 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -161,6 +161,7 @@ static struct usb_serial_driver whiteheat_fake_device = {
.name = "whiteheatnofirm",
},
.description = "Connect Tech - WhiteHEAT - (prerenumeration)",
+ .usb_driver = &whiteheat_driver,
.id_table = id_table_prerenumeration,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
@@ -176,6 +177,7 @@ static struct usb_serial_driver whiteheat_device = {
.name = "whiteheat",
},
.description = "Connect Tech - WhiteHEAT",
+ .usb_driver = &whiteheat_driver,
.id_table = id_table_std,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,