Commit 6e8cf775 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman Committed by Greg Kroah-Hartman

USB: add EPIC support to the io_edgeport driver

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: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent 20b2e28f
...@@ -146,6 +146,8 @@ struct edgeport_serial { ...@@ -146,6 +146,8 @@ struct edgeport_serial {
struct edge_manuf_descriptor manuf_descriptor; /* the manufacturer descriptor */ struct edge_manuf_descriptor manuf_descriptor; /* the manufacturer descriptor */
struct edge_boot_descriptor boot_descriptor; /* the boot firmware descriptor */ struct edge_boot_descriptor boot_descriptor; /* the boot firmware descriptor */
struct edgeport_product_info product_info; /* Product Info */ 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 */ __u8 interrupt_in_endpoint; /* the interrupt endpoint handle */
unsigned char * interrupt_in_buffer; /* the buffer we use for the interrupt endpoint */ 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) ...@@ -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); unicode_to_ascii(string, buflen, pStringDesc->wData, pStringDesc->bLength/2);
kfree(pStringDesc); kfree(pStringDesc);
dbg("%s - USB String %s", __FUNCTION__, string);
return strlen(string); return strlen(string);
} }
...@@ -434,6 +437,34 @@ static int get_string_desc (struct usb_device *dev, int Id, struct usb_string_de ...@@ -434,6 +437,34 @@ static int get_string_desc (struct usb_device *dev, int Id, struct usb_string_de
} }
#endif #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) static void get_product_info(struct edgeport_serial *edge_serial)
{ {
struct edgeport_product_info *product_info = &edge_serial->product_info; struct edgeport_product_info *product_info = &edge_serial->product_info;
...@@ -495,30 +526,60 @@ static void get_product_info(struct edgeport_serial *edge_serial) ...@@ -495,30 +526,60 @@ static void get_product_info(struct edgeport_serial *edge_serial)
break; break;
} }
// Dump Product Info structure dump_product_info(product_info);
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);
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) ...@@ -1017,21 +1078,29 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
edge_port->closePending = TRUE; edge_port->closePending = TRUE;
/* flush and chase */ if ((!edge_serial->is_epic) ||
edge_port->chaseResponsePending = TRUE; ((edge_serial->is_epic) &&
(edge_serial->epic_descriptor.Supports.IOSPChase))) {
dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__); /* flush and chase */
status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0); edge_port->chaseResponsePending = TRUE;
if (status == 0) {
// block until chase finished dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__);
block_until_chase_response(edge_port); status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
} else { if (status == 0) {
edge_port->chaseResponsePending = FALSE; // block until chase finished
block_until_chase_response(edge_port);
} else {
edge_port->chaseResponsePending = FALSE;
}
} }
/* close the port */ if ((!edge_serial->is_epic) ||
dbg("%s - Sending IOSP_CMD_CLOSE_PORT", __FUNCTION__); ((edge_serial->is_epic) &&
send_iosp_ext_cmd (edge_port, IOSP_CMD_CLOSE_PORT, 0); (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; //port->close = TRUE;
edge_port->closePending = FALSE; edge_port->closePending = FALSE;
...@@ -1694,29 +1763,38 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned ...@@ -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) 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_port *edge_port = usb_get_serial_port_data(port);
struct edgeport_serial *edge_serial = usb_get_serial_data(port->serial);
int status; int status;
/* flush and chase */ if ((!edge_serial->is_epic) ||
edge_port->chaseResponsePending = TRUE; ((edge_serial->is_epic) &&
(edge_serial->epic_descriptor.Supports.IOSPChase))) {
dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__); /* flush and chase */
status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0); edge_port->chaseResponsePending = TRUE;
if (status == 0) {
// block until chase finished dbg("%s - Sending IOSP_CMD_CHASE_PORT", __FUNCTION__);
block_until_chase_response(edge_port); status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CHASE_PORT, 0);
} else { if (status == 0) {
edge_port->chaseResponsePending = FALSE; // block until chase finished
block_until_chase_response(edge_port);
} else {
edge_port->chaseResponsePending = FALSE;
}
} }
if (break_state == -1) { if ((!edge_serial->is_epic) ||
dbg("%s - Sending IOSP_CMD_SET_BREAK", __FUNCTION__); ((edge_serial->is_epic) &&
status = send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_BREAK, 0); (edge_serial->epic_descriptor.Supports.IOSPSetClrBreak))) {
} else { if (break_state == -1) {
dbg("%s - Sending IOSP_CMD_CLEAR_BREAK", __FUNCTION__); dbg("%s - Sending IOSP_CMD_SET_BREAK", __FUNCTION__);
status = send_iosp_ext_cmd (edge_port, IOSP_CMD_CLEAR_BREAK, 0); status = send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_BREAK, 0);
} } else {
if (status) { dbg("%s - Sending IOSP_CMD_CLEAR_BREAK", __FUNCTION__);
dbg("%s - error sending break set/clear command.", __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; return;
...@@ -2288,6 +2366,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer ...@@ -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) 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 *cmdBuffer;
unsigned char *currCmd; unsigned char *currCmd;
int cmdLen = 0; int cmdLen = 0;
...@@ -2295,6 +2374,14 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa ...@@ -2295,6 +2374,14 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa
int status; int status;
unsigned char number = edge_port->port->number - edge_port->port->serial->minor; 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); dbg("%s - port = %d, baud = %d", __FUNCTION__, edge_port->port->number, baudRate);
status = calc_baud_rate_divisor (baudRate, &divisor); status = calc_baud_rate_divisor (baudRate, &divisor);
...@@ -2374,6 +2461,7 @@ static int calc_baud_rate_divisor (int baudrate, int *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) 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 *cmdBuffer;
unsigned char *currCmd; unsigned char *currCmd;
unsigned long cmdLen = 0; unsigned long cmdLen = 0;
...@@ -2381,6 +2469,22 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r ...@@ -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); 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. // Alloc memory for the string of commands.
cmdBuffer = kmalloc (0x10, GFP_ATOMIC); cmdBuffer = kmalloc (0x10, GFP_ATOMIC);
if (cmdBuffer == NULL ) { if (cmdBuffer == NULL ) {
...@@ -2414,6 +2518,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r ...@@ -2414,6 +2518,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
#endif #endif
static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios) 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; struct tty_struct *tty;
int baud; int baud;
unsigned cflag; unsigned cflag;
...@@ -2494,8 +2599,12 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi ...@@ -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 stop_char = STOP_CHAR(tty);
unsigned char start_char = START_CHAR(tty); unsigned char start_char = START_CHAR(tty);
send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XON_CHAR, start_char); if ((!edge_serial->is_epic) ||
send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_XOFF_CHAR, stop_char); ((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 we are implementing INBOUND XON/XOFF */
if (I_IXOFF(tty)) { if (I_IXOFF(tty)) {
...@@ -2515,8 +2624,14 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi ...@@ -2515,8 +2624,14 @@ static void change_port_settings (struct edgeport_port *edge_port, struct ktermi
} }
/* Set flow control to the configured value */ /* Set flow control to the configured value */
send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_RX_FLOW, rxFlow); if ((!edge_serial->is_epic) ||
send_iosp_ext_cmd (edge_port, IOSP_CMD_SET_TX_FLOW, txFlow); ((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); edge_port->shadowLCR &= ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK);
...@@ -2728,6 +2843,13 @@ static int edge_startup (struct usb_serial *serial) ...@@ -2728,6 +2843,13 @@ static int edge_startup (struct usb_serial *serial)
struct edgeport_port *edge_port; struct edgeport_port *edge_port;
struct usb_device *dev; struct usb_device *dev;
int i, j; 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; dev = serial->dev;
...@@ -2750,38 +2872,50 @@ static int edge_startup (struct usb_serial *serial) ...@@ -2750,38 +2872,50 @@ static int edge_startup (struct usb_serial *serial)
dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name); dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name);
/* get the manufacturing descriptor for this device */ /* Read the epic descriptor */
get_manufacturing_desc (edge_serial); 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 the manufacturing descriptor for this device */
get_boot_desc (edge_serial); 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 */ /* set the number of ports from the manufacturing description */
/* serial->num_ports = serial->product_info.NumPorts; */ /* serial->num_ports = serial->product_info.NumPorts; */
if (edge_serial->product_info.NumPorts != serial->num_ports) { if ((!edge_serial->is_epic) &&
warn("%s - Device Reported %d serial ports vs core " (edge_serial->product_info.NumPorts != serial->num_ports)) {
"thinking we have %d ports, email greg@kroah.com this info.", dev_warn(&serial->dev->dev, "Device Reported %d serial ports "
__FUNCTION__, edge_serial->product_info.NumPorts, "vs. core thinking we have %d ports, email "
serial->num_ports); "greg@kroah.com this information.",
edge_serial->product_info.NumPorts,
serial->num_ports);
} }
dbg("%s - time 1 %ld", __FUNCTION__, jiffies); dbg("%s - time 1 %ld", __FUNCTION__, jiffies);
/* now load the application firmware into this device */ /* If not an EPiC device */
load_application_firmware (edge_serial); 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 */ /* Check current Edgeport EEPROM and update if necessary */
update_edgeport_E2PROM (edge_serial); update_edgeport_E2PROM (edge_serial);
dbg("%s - time 3 %ld", __FUNCTION__, jiffies);
/* set the configuration to use #1 */ dbg("%s - time 3 %ld", __FUNCTION__, jiffies);
// dbg("set_configuration 1");
// usb_set_configuration (dev, 1); /* 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, /* we set up the pointers to the endpoints in the edge_open function,
* as the structures aren't created yet. */ * as the structures aren't created yet. */
...@@ -2804,8 +2938,101 @@ static int edge_startup (struct usb_serial *serial) ...@@ -2804,8 +2938,101 @@ static int edge_startup (struct usb_serial *serial)
edge_port->port = serial->port[i]; edge_port->port = serial->port[i];
usb_set_serial_port_data(serial->port[i], edge_port); 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) ...@@ -2815,6 +3042,7 @@ static int edge_startup (struct usb_serial *serial)
****************************************************************************/ ****************************************************************************/
static void edge_shutdown (struct usb_serial *serial) static void edge_shutdown (struct usb_serial *serial)
{ {
struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
int i; int i;
dbg("%s", __FUNCTION__); dbg("%s", __FUNCTION__);
...@@ -2824,7 +3052,18 @@ static void edge_shutdown (struct usb_serial *serial) ...@@ -2824,7 +3052,18 @@ static void edge_shutdown (struct usb_serial *serial)
kfree (usb_get_serial_port_data(serial->port[i])); kfree (usb_get_serial_port_data(serial->port[i]));
usb_set_serial_port_data(serial->port[i], NULL); 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); usb_set_serial_data(serial, NULL);
} }
...@@ -2846,6 +3085,9 @@ static int __init edgeport_init(void) ...@@ -2846,6 +3085,9 @@ static int __init edgeport_init(void)
retval = usb_serial_register(&edgeport_8port_device); retval = usb_serial_register(&edgeport_8port_device);
if (retval) if (retval)
goto failed_8port_device_register; goto failed_8port_device_register;
retval = usb_serial_register(&epic_device);
if (retval)
goto failed_epic_device_register;
retval = usb_register(&io_driver); retval = usb_register(&io_driver);
if (retval) if (retval)
goto failed_usb_register; goto failed_usb_register;
...@@ -2853,6 +3095,8 @@ static int __init edgeport_init(void) ...@@ -2853,6 +3095,8 @@ static int __init edgeport_init(void)
return 0; return 0;
failed_usb_register: failed_usb_register:
usb_serial_deregister(&epic_device);
failed_epic_device_register:
usb_serial_deregister(&edgeport_8port_device); usb_serial_deregister(&edgeport_8port_device);
failed_8port_device_register: failed_8port_device_register:
usb_serial_deregister(&edgeport_4port_device); usb_serial_deregister(&edgeport_4port_device);
...@@ -2873,6 +3117,7 @@ static void __exit edgeport_exit (void) ...@@ -2873,6 +3117,7 @@ static void __exit edgeport_exit (void)
usb_serial_deregister (&edgeport_2port_device); usb_serial_deregister (&edgeport_2port_device);
usb_serial_deregister (&edgeport_4port_device); usb_serial_deregister (&edgeport_4port_device);
usb_serial_deregister (&edgeport_8port_device); usb_serial_deregister (&edgeport_8port_device);
usb_serial_deregister (&epic_device);
} }
module_init(edgeport_init); module_init(edgeport_init);
......
...@@ -111,10 +111,12 @@ struct edgeport_product_info { ...@@ -111,10 +111,12 @@ struct edgeport_product_info {
__le16 FirmwareBuildNumber; /* zzzz (LE format) */ __le16 FirmwareBuildNumber; /* zzzz (LE format) */
__u8 ManufactureDescDate[3]; /* MM/DD/YY when descriptor template was compiled */ __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 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;
}; };
/* /*
......
...@@ -47,6 +47,18 @@ static struct usb_device_id edgeport_8port_id_table [] = { ...@@ -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 */ /* Devices that this driver supports */
static struct usb_device_id id_table_combined [] = { static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4) }, { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4) },
...@@ -70,6 +82,14 @@ static struct usb_device_id id_table_combined [] = { ...@@ -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_8R) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8RR) }, { 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_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 */ { } /* Terminating entry */
}; };
...@@ -165,5 +185,35 @@ static struct usb_serial_driver edgeport_8port_device = { ...@@ -165,5 +185,35 @@ static struct usb_serial_driver edgeport_8port_device = {
.write_bulk_callback = edge_bulk_out_data_callback, .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 #endif
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#define USB_VENDOR_ID_ION 0x1608 // Our VID #define USB_VENDOR_ID_ION 0x1608 // Our VID
#define USB_VENDOR_ID_TI 0x0451 // TI VID #define USB_VENDOR_ID_TI 0x0451 // TI VID
#define USB_VENDOR_ID_AXIOHM 0x05D9 /* Axiohm VID */
// //
// Definitions of USB product IDs (PID) // Definitions of USB product IDs (PID)
...@@ -334,6 +335,10 @@ struct edge_compatibility_bits ...@@ -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 struct edge_compatibility_descriptor
{ {
__u8 Length; // Descriptor Length (per USB spec) __u8 Length; // Descriptor Length (per USB spec)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment