[PATCH 2/70] USB: add EPIC support to the io_edgeport driver

Greg KH <[email protected]>
Newsgroups gmane.linux.usb.devel
Message-ID <[email protected]>
From: Greg Kroah-Hartman <[email protected]>

This patch adds EPiC support to the io_edgeport driver which adds
support for a number of NCR printers:
	- NCR (Axiohm) 7401-K580 printer
	- NCR (TEC) 7401-K590 printer, 7402-K592
	- NCR (TEC) 7167, 7168 printers
	- NCR (TEC) 7197, 7198, F306, F307, F309 printers
	- NCR (Axiohm) 7194 printer
	- NCR (Axiohm) 7158 printer
and a few more.

It is based on the 2.6.19 kernel.

Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
 drivers/usb/serial/io_edgeport.c |  409 ++++++++++++++++++++++++++++++--------
 drivers/usb/serial/io_edgeport.h |    6 +-
 drivers/usb/serial/io_tables.h   |   50 +++++
 drivers/usb/serial/io_usbvend.h  |    5 +
 4 files changed, 386 insertions(+), 84 deletions(-)

diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index f623d58..cca1607 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 */
@@ -397,6 +399,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 +437,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 +526,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 +1078,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 +1763,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 +2366,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 +2374,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 +2461,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 +2469,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 +2518,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 +2599,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 +2624,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 +2843,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 +2872,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 boot descriptor */
-	get_boot_desc (edge_serial);
+		/* get the manufacturing descriptor for this device */
+		get_manufacturing_desc (edge_serial);
 
-	get_product_info(edge_serial);
+		/* get the boot descriptor */
+		get_boot_desc (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 [email protected] 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 "
+			 "[email protected] 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 +2938,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 +3042,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 +3052,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 +3085,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 +3095,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 +3117,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 123fa8a..29a913a 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 fad561c..3cbb8c1 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,6 +82,14 @@ 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 */
 };
 
@@ -165,5 +185,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_usbvend.h b/drivers/usb/serial/io_usbvend.h
index f1804fd..e57fa11 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)
-- 
1.4.4.4


-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier.
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.