patch-2.3.26 linux/drivers/usb/acm.c

Next file: linux/drivers/usb/audio.c
Previous file: linux/drivers/usb/README.dc2xx
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.25/linux/drivers/usb/acm.c linux/drivers/usb/acm.c
@@ -1,7 +1,9 @@
 /*
- * USB Abstract Control Model based on Brad Keryan's USB busmouse driver 
+ * USB Abstract Control Model based on Brad Keryan's USB busmouse driver
  *
- * Armin Fuerst 5/8/1999 <armin.please@put.your.email.here.!!!!>
+ * (C) Copyright 1999 Armin Fuerst <armin.please@put.your.email.here.!!!!>
+ * (C) Copyright 1999 Pavel Machek <pavel@suse.cz>
+ * (C) Copyright 1999 Johannes Erdfelt <jerdfelt@valinux.com>
  *
  * version 0.8: Fixed endianity bug, some cleanups. I really hate to have
  * half of driver in form if (...) { info("x"); return y; }
@@ -11,7 +13,7 @@
  * wrote this code? ...Oops that was me). Fixed module cleanup. Did some
  * testing at 3Com => zmodem uload+download works, pppd had trouble but
  * seems to work now. Changed Menuconfig texts "Communications Device
- * Class (ACM)" might be a bit more intuitive. Ported to 2.3.13-1 prepatch. 
+ * Class (ACM)" might be a bit more intuitive. Ported to 2.3.13-1 prepatch.
  * (2/8/99)
  *
  * version 0.6: Modularized driver, added disconnect code, improved
@@ -23,8 +25,8 @@
  * in uhci_td_allocate. Commenetd out getstringtable which causes crash.
  * (13/7/99)
  *
- * version 0.4: Small fixes in the FIFO, cleanup. Updated Bulk transfer in 
- * uhci.c. Should have the correct interface now. 
+ * version 0.4: Small fixes in the FIFO, cleanup. Updated Bulk transfer in
+ * uhci.c. Should have the correct interface now.
  * (6/6/99)
  *
  * version 0.3: Major changes. Changed Bulk transfer to interrupt based
@@ -60,15 +62,14 @@
 #include <linux/tty_flip.h>
 #include <linux/tty.h>
 #include <linux/module.h>
-#include <linux/spinlock.h>
 
 #include "usb.h"
 
 #define NR_PORTS 3
 #define ACM_MAJOR 166	/* Wow, major is now officially allocated */
 
-//#define info(message...); printk(message);
-#define info(message...);
+//#define info(message...) printk(KERN_DEBUG message)
+#define info(message...)
 
 #define CTRL_STAT_DTR	1
 #define CTRL_STAT_RTS	2
@@ -88,7 +89,7 @@
 	int cfgnum;					//configuration number on this device
 	struct tty_struct *tty;				//the coresponding tty
 	char present;					//a device for this struct was detected => this tty is used
-	char active;					//someone has this acm's device open 
+	char active;					//someone has this acm's device open
 	unsigned int ctrlstate;				//Status of the serial control lines  (handshake,...)
 	unsigned int linecoding;			//Status of the line coding (Bits, Stop, Parity)
 	int writesize, readsize;			//size of the usb buffers
@@ -105,56 +106,56 @@
 
 //functions for various ACM requests
 
-void Set_Control_Line_Status (unsigned int status,struct acm_state *acm)
+void Set_Control_Line_Status(unsigned int status, struct acm_state *acm)
 {
-	devrequest dr;
+	struct usb_device *dev = acm->dev;
+	int ret;
 
 	info("Set_control_Line_Status\n");
 
-	dr.requesttype = 0x22;
-	dr.request = 0x22;
-	dr.value = status;
-	dr.index = 0;
-	dr.length = 0;
-	acm->dev->bus->op->control_msg(acm->dev, usb_sndctrlpipe(acm->dev,0), &dr, NULL, 0, HZ);
+	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x22, 0x22,
+		status, 0, NULL, 0, HZ);
+	if (ret < 0)
+		printk(KERN_ERR "acm: Set_Control_Line_Status failed\n");
 
-	acm->ctrlstate=status;
+	acm->ctrlstate = status;
 }
 
-void Set_Line_Coding (unsigned int coding,struct acm_state *acm)
+void Set_Line_Coding(unsigned int coding, struct acm_state *acm)
 {
-	devrequest dr;
+	struct usb_device *dev = acm->dev;
+	int ret;
 
 	info("Set_Line_Coding\n");
 
-	dr.requesttype = 0x22;
-	dr.request = 0x30;
-	dr.value = coding;
-	dr.index = 0;
-	dr.length = 0;
-	acm->dev->bus->op->control_msg(acm->dev, usb_sndctrlpipe(acm->dev,0), &dr, NULL, 0, HZ);
-	
-	acm->linecoding=coding;
+	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x30, 0x22,
+		coding, 0, NULL, 0, HZ);
+
+	acm->linecoding = coding;
 }
 
 //Interrupt handler for various usb events
 static int acm_irq(int state, void *__buffer, int count, void *dev_id)
 {
-
 	unsigned char *data;
-	struct acm_state *acm = (struct acm_state *) dev_id; 
+	struct acm_state *acm = (struct acm_state *)dev_id;
         devrequest *dr;
-		
+
 	info("ACM_USB_IRQ\n");
 
+	if (state) {
+		printk(KERN_DEBUG "acm_irq: strange state received: %x\n", state);
+		return 0;
+	}
+
 	if (!acm->present)
 		return 0;
 	if (!acm->active)
 		return 1;
-       
-        dr=__buffer;
-	data=__buffer;
-	data+=sizeof(dr);
+
+        dr = __buffer;
+	data = __buffer;
+	data += sizeof(dr);
  
 #if 0
         printk("reqtype: %02X\n",dr->requesttype);
@@ -163,23 +164,23 @@
 	printk("wIndex: %02X\n",dr->index);
 	printk("wLength: %02X\n",dr->length);
 #endif
-	
+
 	switch(dr->request) {
 	case 0x00: /* Network connection */
-		printk("Network connection: ");
-		if (dr->request==0) printk("disconnected\n");
-		if (dr->request==1) printk("connected\n");
+		printk(KERN_DEBUG "Network connection: ");
+		if (dr->request==0) printk(KERN_DEBUG "disconnected\n");
+		if (dr->request==1) printk(KERN_DEBUG "connected\n");
 		break;
-	    
+
 	case 0x01: /* Response available */
-		printk("Response available\n");
+		printk(KERN_DEBUG "Response available\n");
 		break;
-	
+
 	case 0x20: /* Set serial line state */
-		printk("acm.c: Set serial control line state\n");
-		if ((dr->index==1)&&(dr->length==2)) {
+		printk(KERN_DEBUG "acm.c: Set serial control line state\n");
+		if ((dr->index==1) && (dr->length==2)) {
 			acm->ctrlstate= data[0] || (data[1] << 16);
-			printk("Serstate: %02X\n",acm->ctrlstate);
+			printk(KERN_DEBUG "Serstate: %02X\n",acm->ctrlstate);
 		}
 		break;
 	}
@@ -197,7 +198,7 @@
 	info("ACM_READ_IRQ: state %d, %d bytes\n", state, count);
 	if (state) {
 		printk( "acm_read_irq: strange state received: %x\n", state );
-		return 0;
+		return 1;
 	}
 	
 	if (!ACM_READY)
@@ -207,13 +208,13 @@
 		tty_insert_flip_char(tty,data[i],0);
   	tty_flip_buffer_push(tty);
 
-	return 0; /* Never return 1 from this routine. It makes uhci do bad things. */
+	return 1;
 }
 
 static int acm_write_irq(int state, void *__buffer, int count, void *dev_id)
 {
-	struct acm_state *acm = (struct acm_state *) dev_id; 
-       	struct tty_struct *tty = acm->tty; 
+	struct acm_state *acm = (struct acm_state *) dev_id;
+       	struct tty_struct *tty = acm->tty;
 
 	info("ACM_WRITE_IRQ\n");
 
@@ -221,24 +222,25 @@
 		return 0; /* stop transfer */
 
 	usb_terminate_bulk(acm->dev, acm->writetransfer);
-	acm->writing=0;
+	acm->writing = 0;
 	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
 		(tty->ldisc.write_wakeup)(tty);
 	wake_up_interruptible(&tty->write_wait);
-	
+
 	return 0; /* stop tranfer */
 }
 
 /*TTY STUFF*/
-static int rs_open(struct tty_struct *tty, struct file * filp) 
+static int rs_open(struct tty_struct *tty, struct file *filp)
 {
 	struct acm_state *acm;
 	int ret;
-	
+
 	info("USB_FILE_OPEN\n");
 
-	tty->driver_data=acm=&acm_state_table[MINOR(tty->device)-tty->driver.minor_start];
-	acm->tty=tty;
+	tty->driver_data = acm =
+		&acm_state_table[MINOR(tty->device) - tty->driver.minor_start];
+	acm->tty = tty;
 	 
 	if (!acm->present)
 		return -EINVAL;
@@ -246,139 +248,147 @@
 	if (acm->active++)
 		return 0;
  
+	MOD_INC_USE_COUNT;
+
 	/* Start reading from the device */
-	ret = usb_request_irq(acm->dev,acm->ctrlpipe, acm_irq, acm->ctrlinterval, acm, &acm->ctrltransfer);
+	ret = usb_request_irq(acm->dev, acm->ctrlpipe, acm_irq,
+		acm->ctrlinterval, acm, &acm->ctrltransfer);
 	if (ret)
-		printk (KERN_WARNING "usb-acm: usb_request_irq failed (0x%x)\n", ret);
-	acm->reading=1;
-	acm->readtransfer=usb_request_bulk(acm->dev,acm->readpipe, acm_read_irq, acm->readbuffer, acm->readsize, acm);
-	
-	Set_Control_Line_Status (CTRL_STAT_DTR | CTRL_STAT_RTS, acm);
-				                  
+		printk(KERN_ERR "usb-acm: usb_request_irq failed (0x%x)\n", ret);
+	acm->reading = 1;
+	acm->readtransfer = usb_request_bulk(acm->dev, acm->readpipe,
+		acm_read_irq, acm->readbuffer, acm->readsize, acm);
+
+	Set_Control_Line_Status(CTRL_STAT_DTR | CTRL_STAT_RTS, acm);
+
 	return 0;
 }
 
-static void rs_close(struct tty_struct *tty, struct file * filp)
+static void rs_close(struct tty_struct *tty, struct file *filp)
 {
-	struct acm_state *acm = (struct acm_state *) tty->driver_data; 
+	struct acm_state *acm = (struct acm_state *) tty->driver_data;
+
 	info("rs_close\n");
-	
+
 	if (!acm->present)
 		return;
 
 	if (--acm->active)
 		return;
 
-	Set_Control_Line_Status (0, acm);
-	
-	if (acm->writing){
+	Set_Control_Line_Status(0, acm);
+
+	if (acm->writing) {
 		usb_terminate_bulk(acm->dev, acm->writetransfer);
-		acm->writing=0;
+		acm->writing = 0;
 	}
-	if (acm->reading){
+	if (acm->reading) {
 		usb_terminate_bulk(acm->dev, acm->readtransfer);
-		acm->reading=0;
+		acm->reading = 0;
 	}
-//	usb_release_irq(acm->dev,acm->ctrltransfer, acm->ctrlpipe);
+//	usb_release_irq(acm->dev, acm->ctrltransfer, acm->ctrlpipe);
+
+	MOD_DEC_USE_COUNT;
 }
 
-static int rs_write(struct tty_struct * tty, int from_user,
+static int rs_write(struct tty_struct *tty, int from_user,
 		    const unsigned char *buf, int count)
 {
-	struct acm_state *acm = (struct acm_state *) tty->driver_data; 
+	struct acm_state *acm = (struct acm_state *)tty->driver_data;
 	int written;
-	
+
 	info("rs_write\n");
 
 	if (!ACM_READY)
 		return -EINVAL;
-	
+
 	if (acm->writing) {
-		info ("already writing\n");
+		info("already writing\n");
 		return 0;
 	}
 
-	written=(count>acm->writesize) ? acm->writesize : count;
-	  
-	if (from_user) copy_from_user(acm->writebuffer,buf,written);
-	else	       memcpy(acm->writebuffer,buf,written);
+	written = (count>acm->writesize) ? acm->writesize : count;
+
+	if (from_user)
+		copy_from_user(acm->writebuffer, buf, written);
+	else
+		memcpy(acm->writebuffer, buf, written);
 
 	//start the transfer
-	acm->writing=1;
-	acm->writetransfer=usb_request_bulk(acm->dev,acm->writepipe, acm_write_irq, acm->writebuffer, written, acm);
+	acm->writing = 1;
+	acm->writetransfer = usb_request_bulk(acm->dev, acm->writepipe,
+		acm_write_irq, acm->writebuffer, written, acm);
 
 	return written;
 } 
 
 static void rs_put_char(struct tty_struct *tty, unsigned char ch)
 {
-	struct acm_state *acm = (struct acm_state *) tty->driver_data; 
-	
-	printk( "acm: rs_put_char: Who called this unsupported routine?\n" );
+	printk(KERN_DEBUG "acm: rs_put_char: Who called this unsupported routine?\n");
 	BUG();
-}                   
+}
 
-static int rs_write_room(struct tty_struct *tty) 
+static int rs_write_room(struct tty_struct *tty)
 {
-	struct acm_state *acm = (struct acm_state *) tty->driver_data; 
+	struct acm_state *acm = (struct acm_state *) tty->driver_data;
 
 	info("rs_write_room\n");
-	
+
 	if (!ACM_READY)
 		return -EINVAL;
-	
+
 	return acm->writing ? 0 : acm->writesize;
 }
 
-static int rs_chars_in_buffer(struct tty_struct *tty) 
+static int rs_chars_in_buffer(struct tty_struct *tty)
 {
-	struct acm_state *acm = (struct acm_state *) tty->driver_data; 
+	struct acm_state *acm = (struct acm_state *) tty->driver_data;
 
 //	info("rs_chars_in_buffer\n");
-	
+
 	if (!ACM_READY)
 		return -EINVAL;
-	
-	return acm->writing ? acm->writesize :  0;
+
+	return acm->writing ? acm->writesize : 0;
 }
 
-static void rs_throttle(struct tty_struct * tty)
+static void rs_throttle(struct tty_struct *tty)
 {
-	struct acm_state *acm = (struct acm_state *) tty->driver_data; 
-	
+	struct acm_state *acm = (struct acm_state *) tty->driver_data;
+
 	info("rs_throttle\n");
-	
+
 	if (!ACM_READY)
 		return;
-/*	
+/*
 	if (I_IXOFF(tty))
 		rs_send_xchar(tty, STOP_CHAR(tty));
-*/    
+*/
 	if (tty->termios->c_cflag & CRTSCTS)
-		Set_Control_Line_Status (acm->ctrlstate & ~CTRL_STAT_RTS, acm);
+		Set_Control_Line_Status(acm->ctrlstate & ~CTRL_STAT_RTS, acm);
 }
 
-static void rs_unthrottle(struct tty_struct * tty)
+static void rs_unthrottle(struct tty_struct *tty)
 {
-	struct acm_state *acm = (struct acm_state *) tty->driver_data; 
-	
+	struct acm_state *acm = (struct acm_state *) tty->driver_data;
+
 	info("rs_unthrottle\n");
-	
+
 	if (!ACM_READY)
 		return;
-/*	
+/*
 	if (I_IXOFF(tty))
 		rs_send_xchar(tty, STOP_CHAR(tty));
-*/    
+*/
 	if (tty->termios->c_cflag & CRTSCTS)
-		Set_Control_Line_Status (acm->ctrlstate | CTRL_STAT_RTS, acm);
+		Set_Control_Line_Status(acm->ctrlstate | CTRL_STAT_RTS, acm);
 }
 
 static int get_free_acm(void)
 {
 	int i;
  
-	for (i=0;i<NR_PORTS;i++) {
+	for (i = 0; i < NR_PORTS; i++) {
 		if (!acm_state_table[i].present)
 			return i;
 	}
@@ -413,14 +423,14 @@
 	 * selecting or should the usbcore?  [different configurations
 	 * can have different bandwidth requirements] -greg */
 
-	/* Now scan all configs for a ACM configuration*/
+	/* Now scan all configs for a ACM configuration */
 	for (cfgnum=0;cfgnum<dev->descriptor.bNumConfigurations;cfgnum++) {
 		/* The first one should be Communications interface? */
 		interface = &dev->config[cfgnum].interface[0].altsetting[0];
 		if (IFCLASS(interface) != 0x02020101)
 			continue;
 
-		/*Which uses an interrupt input */
+		/* Which uses an interrupt input */
 		endpoint = &interface->endpoint[0];
 		if ((endpoint->bEndpointAddress & 0x80) != 0x80 ||
 		    (endpoint->bmAttributes & 3) != 3)
@@ -540,13 +550,12 @@
 int usb_acm_init(void)
 {
 	int cnt;
-	
+
 	info("usb_acm_init\n");
-		
+
 	//INITIALIZE GLOBAL DATA STRUCTURES
-	for (cnt=0;cnt<NR_PORTS;cnt++) {
+	for (cnt = 0; cnt < NR_PORTS; cnt++)
 		memset(&acm_state_table[cnt], 0, sizeof(struct acm_state));
-	}
 
 	//REGISTER TTY DRIVER
 	memset(&acm_tty_driver, 0, sizeof(struct tty_driver));
@@ -565,16 +574,16 @@
 	acm_tty_driver.table = acm_tty;
 	acm_tty_driver.termios = acm_termios;
 	acm_tty_driver.termios_locked = acm_termios_locked;
-	
+
 	acm_tty_driver.open = rs_open;
 	acm_tty_driver.close = rs_close;
 	acm_tty_driver.write = rs_write;
 	acm_tty_driver.put_char = rs_put_char;
 	acm_tty_driver.flush_chars = NULL; //rs_flush_chars;
 	acm_tty_driver.write_room = rs_write_room;
-	acm_tty_driver.ioctl = NULL; //rs_ioctl;
+	acm_tty_driver.ioctl = NULL; //rs_ioctl
 	acm_tty_driver.set_termios = NULL; //rs_set_termios;
-	acm_tty_driver.set_ldisc = NULL; 
+	acm_tty_driver.set_ldisc = NULL;
 	acm_tty_driver.throttle = rs_throttle;
 	acm_tty_driver.unthrottle = rs_unthrottle;
 	acm_tty_driver.stop = NULL; //rs_stop;
@@ -587,12 +596,14 @@
 	acm_tty_driver.chars_in_buffer = rs_chars_in_buffer;
 	acm_tty_driver.flush_buffer = NULL; //rs_flush_buffer;
 	if (tty_register_driver(&acm_tty_driver)) {
-		printk( "acm: failed to register tty driver\n" );
+		printk(KERN_ERR "acm: failed to register tty driver\n");
 		return -EPERM;
 	}
-	
-	//REGISTER USB DRIVER
-	usb_register(&acm_driver);
+
+	if (usb_register(&acm_driver) < 0) {
+		tty_unregister_driver(&acm_tty_driver);
+		return -1;
+	}
 
 	printk(KERN_INFO "USB ACM registered.\n");
 	return 0;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)