This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / drivers / usb / class / cdc-acm.c
index cf7fcf8..a929a52 100644 (file)
@@ -301,9 +301,9 @@ done:
        return 0;
 
 full_bailout:
-       usb_kill_urb(acm->readurb);
+       usb_unlink_urb(acm->readurb);
 bail_out_and_unlink:
-       usb_kill_urb(acm->ctrlurb);
+       usb_unlink_urb(acm->ctrlurb);
 bail_out:
        up(&open_sem);
        return -EIO;
@@ -320,9 +320,9 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
        if (!--acm->used) {
                if (acm->dev) {
                        acm_set_control(acm, acm->ctrlout = 0);
-                       usb_kill_urb(acm->ctrlurb);
-                       usb_kill_urb(acm->writeurb);
-                       usb_kill_urb(acm->readurb);
+                       usb_unlink_urb(acm->ctrlurb);
+                       usb_unlink_urb(acm->writeurb);
+                       usb_unlink_urb(acm->readurb);
                } else {
                        tty_unregister_device(acm_tty_driver, acm->minor);
                        acm_table[acm->minor] = NULL;
@@ -335,11 +335,11 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
        up(&open_sem);
 }
 
-static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
+static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
 {
        struct acm *acm = tty->driver_data;
        int stat;
-       dbg("Entering acm_tty_write to write %d bytes,\n", count);
+       dbg("Entering acm_tty_write to write %d bytes from %s space,\n", count, from_user ? "user" : "kernel");
 
        if (!ACM_READY(acm))
                return -EINVAL;
@@ -350,15 +350,19 @@ static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int c
 
        count = (count > acm->writesize) ? acm->writesize : count;
 
-       dbg("Get %d bytes...", count);
-       memcpy(acm->write_buffer, buf, count);
+       dbg("Get %d bytes from %s space...", count, from_user ? "user" : "kernel");
+       if (from_user) {
+               if (copy_from_user(acm->write_buffer, (void __user *)buf, count))
+                       return -EFAULT;
+       } else
+               memcpy(acm->write_buffer, buf, count);
        dbg("  Successfully copied.\n");
 
        acm->writeurb->transfer_buffer_length = count;
        acm->writeurb->dev = acm->dev;
 
        acm->ready_for_write = 0;
-       stat = usb_submit_urb(acm->writeurb, GFP_ATOMIC);
+       stat = usb_submit_urb(acm->writeurb, from_user ? GFP_KERNEL : GFP_ATOMIC);
        if (stat < 0) {
                dbg("usb_submit_urb(write bulk) failed");
                acm->ready_for_write = 1;
@@ -538,17 +542,6 @@ static int acm_probe (struct usb_interface *intf,
                return -EINVAL;
        }
 
-       if (!buflen) {
-               if (intf->cur_altsetting->endpoint->extralen && intf->cur_altsetting->endpoint->extra) {
-                       dev_dbg(&intf->dev,"Seeking extra descriptors on endpoint");
-                       buflen = intf->cur_altsetting->endpoint->extralen;
-                       buffer = intf->cur_altsetting->endpoint->extra;
-               } else {
-                       err("Zero length descriptor references");
-                       return -EINVAL;
-               }
-       }
-
        while (buflen > 0) {
                if (buffer [1] != USB_DT_CS_INTERFACE) {
                        err("skipping garbage");
@@ -565,8 +558,6 @@ static int acm_probe (struct usb_interface *intf,
                                break;
                        case CDC_COUNTRY_TYPE: /* maybe somehow export */
                                break; /* for now we ignore it */
-                       case CDC_HEADER_TYPE: /* maybe check version */ 
-                               break; /* for now we ignore it */ 
                        case CDC_AC_MANAGEMENT_TYPE:
                                ac_management_function = buffer[3];
                                break;
@@ -578,7 +569,7 @@ static int acm_probe (struct usb_interface *intf,
                                break;
                                
                        default:
-                               err("Ignoring extra header, type %d, length %d", buffer[2], buffer[0]);
+                               err("Ignoring extra header");
                                break;
                        }
 next_desc:
@@ -646,7 +637,7 @@ next_desc:
        dbg("interfaces are valid");
        for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
 
-       if (minor == ACM_TTY_MINORS) {
+       if (acm_table[minor]) {
                err("no more free acm devices");
                return -ENODEV;
        }
@@ -771,9 +762,9 @@ static void acm_disconnect(struct usb_interface *intf)
        acm->dev = NULL;
        usb_set_intfdata (intf, NULL);
 
-       usb_kill_urb(acm->ctrlurb);
-       usb_kill_urb(acm->readurb);
-       usb_kill_urb(acm->writeurb);
+       usb_unlink_urb(acm->ctrlurb);
+       usb_unlink_urb(acm->readurb);
+       usb_unlink_urb(acm->writeurb);
 
        flush_scheduled_work(); /* wait for acm_softint */