patch-2.3.25 linux/drivers/usb/acm.c
Next file: linux/drivers/usb/audio.c
Previous file: linux/drivers/sound/soundcard.c
Back to the patch index
Back to the overall index
- Lines: 159
- Date:
Thu Oct 28 12:54:35 1999
- Orig file:
v2.3.24/linux/drivers/usb/acm.c
- Orig date:
Wed Oct 27 16:34:12 1999
diff -u --recursive --new-file v2.3.24/linux/drivers/usb/acm.c linux/drivers/usb/acm.c
@@ -73,6 +73,8 @@
#define CTRL_STAT_DTR 1
#define CTRL_STAT_RTS 2
+static struct usb_driver acm_driver;
+
static int acm_refcount;
static struct tty_driver acm_tty_driver;
@@ -83,6 +85,7 @@
struct acm_state {
struct usb_device *dev; //the coresponding usb device
+ 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
@@ -194,7 +197,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 1;
+ return 0;
}
if (!ACM_READY)
@@ -204,7 +207,7 @@
tty_insert_flip_char(tty,data[i],0);
tty_flip_buffer_push(tty);
- return 1; /* continue transfer */
+ return 0; /* Never return 1 from this routine. It makes uhci do bad things. */
}
static int acm_write_irq(int state, void *__buffer, int count, void *dev_id)
@@ -382,7 +385,7 @@
return -1;
}
-static int acm_probe(struct usb_device *dev)
+static void * acm_probe(struct usb_device *dev, unsigned int ifnum)
{
struct acm_state *acm;
struct usb_interface_descriptor *interface;
@@ -394,7 +397,7 @@
if (0>(acmno=get_free_acm())) {
info("Too many acm devices connected\n");
- return -1;
+ return NULL;
}
acm = &acm_state_table[acmno];
@@ -402,10 +405,14 @@
if (dev->descriptor.bDeviceClass != 2 ||
dev->descriptor.bDeviceSubClass != 0 ||
dev->descriptor.bDeviceProtocol != 0)
- return -1;
+ return NULL;
#define IFCLASS(if) ((if->bInterfaceClass << 24) | (if->bInterfaceSubClass << 16) | (if->bInterfaceProtocol << 8) | (if->bNumEndpoints))
+ /* FIXME: should the driver really be doing the configuration
+ * selecting or should the usbcore? [different configurations
+ * can have different bandwidth requirements] -greg */
+
/* Now scan all configs for a ACM configuration*/
for (cfgnum=0;cfgnum<dev->descriptor.bNumConfigurations;cfgnum++) {
/* The first one should be Communications interface? */
@@ -425,7 +432,14 @@
interface->bNumEndpoints != 2)
continue;
- /* if ((endpoint->bEndpointAddress & 0x80) == 0x80) */
+ /* make sure both interfaces are available for our use */
+ if (usb_interface_claimed(&dev->config[cfgnum].interface[0]) ||
+ usb_interface_claimed(&dev->config[cfgnum].interface[1])) {
+ printk("usb-acm: required interface already has a driver\n");
+ continue;
+ }
+
+ endpoint = &interface->endpoint[0];
if ((endpoint->bEndpointAddress & 0x80) != 0x80)
swapped = 1;
@@ -445,7 +459,6 @@
usb_set_configuration(dev, dev->config[cfgnum].bConfigurationValue);
acm->dev=dev;
- dev->private=acm;
acm->readendp=dev->config[cfgnum].interface[1].altsetting[0].endpoint[0^swapped].bEndpointAddress;
acm->readpipe=usb_rcvbulkpipe(dev,acm->readendp);
@@ -453,7 +466,7 @@
acm->reading=0;
if (!acm->readbuffer) {
printk("ACM: Couldn't allocate readbuffer\n");
- return -1;
+ return NULL;
}
acm->writeendp=dev->config[cfgnum].interface[1].altsetting[0].endpoint[1^swapped].bEndpointAddress;
@@ -463,23 +476,29 @@
if (!acm->writebuffer) {
printk("ACM: Couldn't allocate writebuffer\n");
kfree(acm->readbuffer);
- return -1;
+ return NULL;
}
acm->ctrlendp=dev->config[cfgnum].interface[0].altsetting[0].endpoint[0].bEndpointAddress;
acm->ctrlpipe=usb_rcvctrlpipe(acm->dev,acm->ctrlendp);
acm->ctrlinterval=dev->config[cfgnum].interface[0].altsetting[0].endpoint[0].bInterval;
+ acm->cfgnum = cfgnum;
acm->present=1;
MOD_INC_USE_COUNT;
- return 0;
+
+ usb_driver_claim_interface(&acm_driver,
+ &dev->config[cfgnum].interface[0], acm);
+ usb_driver_claim_interface(&acm_driver,
+ &dev->config[cfgnum].interface[1], acm);
+ return acm;
}
- return -1;
+ return NULL;
}
-static void acm_disconnect(struct usb_device *dev)
+static void acm_disconnect(struct usb_device *dev, void *ptr)
{
- struct acm_state *acm = (struct acm_state *) dev->private;
+ struct acm_state *acm = ptr;
info("acm_disconnect\n");
@@ -501,6 +520,12 @@
kfree(acm->writebuffer);
kfree(acm->readbuffer);
+ /* release the interfaces so that other drivers can have at them */
+ usb_driver_release_interface(&acm_driver,
+ &dev->config[acm->cfgnum].interface[0]);
+ usb_driver_release_interface(&acm_driver,
+ &dev->config[acm->cfgnum].interface[1]);
+
MOD_DEC_USE_COUNT;
}
@@ -584,7 +609,7 @@
acm=&acm_state_table[i];
if (acm->present) {
printk("disconnecting %d\n",i);
- acm_disconnect(acm->dev);
+ acm_disconnect(acm->dev, acm);
}
}
tty_unregister_driver(&acm_tty_driver);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)