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
- Lines: 511
- Date:
Fri Nov 5 10:43:06 1999
- Orig file:
v2.3.25/linux/drivers/usb/acm.c
- Orig date:
Mon Nov 1 13:56:26 1999
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)