Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=c4cabd28c73116716dcfd0d5f91414b48c0cf5ce
Commit:     c4cabd28c73116716dcfd0d5f91414b48c0cf5ce
Parent:     bb74782e621e988555354abba03812982236a3af
Author:     Oliver Neukum <[EMAIL PROTECTED]>
AuthorDate: Tue Feb 27 15:28:55 2007 +0100
Committer:  Greg Kroah-Hartman <[EMAIL PROTECTED]>
CommitDate: Fri Apr 27 13:28:33 2007 -0700

    USB: cdc-acm: export parsed capabilities through sysfs
    
    this patch exports the attributes cdc-acm knows about a device through 
sysfs.
    
    Signed-off-by: Oliver Neukum <[EMAIL PROTECTED]>
    Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
---
 drivers/usb/class/cdc-acm.c |   81 ++++++++++++++++++++++++++++++++++++++++---
 drivers/usb/class/cdc-acm.h |    3 ++
 2 files changed, 79 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 31ae661..14de3b1 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -212,7 +212,41 @@ static int acm_write_start(struct acm *acm)
        }
        return rc;
 }
+/*
+ * attributes exported through sysfs
+ */
+static ssize_t show_caps
+(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct usb_interface *intf = to_usb_interface(dev);
+       struct acm *acm = usb_get_intfdata(intf);
+
+       return sprintf(buf, "%d", acm->ctrl_caps);
+}
+static DEVICE_ATTR(bmCapabilities, S_IRUGO, show_caps, NULL);
+
+static ssize_t show_country_codes
+(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct usb_interface *intf = to_usb_interface(dev);
+       struct acm *acm = usb_get_intfdata(intf);
+
+       memcpy(buf, acm->country_codes, acm->country_code_size);
+       return acm->country_code_size;
+}
+
+static DEVICE_ATTR(wCountryCodes, S_IRUGO, show_country_codes, NULL);
+
+static ssize_t show_country_rel_date
+(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct usb_interface *intf = to_usb_interface(dev);
+       struct acm *acm = usb_get_intfdata(intf);
+
+       return sprintf(buf, "%d", acm->country_rel_date);
+}
 
+static DEVICE_ATTR(iCountryCodeRelDate, S_IRUGO, show_country_rel_date, NULL);
 /*
  * Interrupt handlers for various ACM device responses
  */
@@ -514,6 +548,7 @@ static void acm_tty_unregister(struct acm *acm)
        usb_free_urb(acm->writeurb);
        for (i = 0; i < nr; i++)
                usb_free_urb(acm->ru[i].urb);
+       kfree(acm->country_codes);
        kfree(acm);
 }
 
@@ -761,6 +796,7 @@ static int acm_probe (struct usb_interface *intf,
                      const struct usb_device_id *id)
 {
        struct usb_cdc_union_desc *union_header = NULL;
+       struct usb_cdc_country_functional_desc *cfd = NULL;
        char *buffer = intf->altsetting->extra;
        int buflen = intf->altsetting->extralen;
        struct usb_interface *control_interface;
@@ -824,8 +860,9 @@ static int acm_probe (struct usb_interface *intf,
                                union_header = (struct usb_cdc_union_desc *)
                                                        buffer;
                                break;
-                       case USB_CDC_COUNTRY_TYPE: /* maybe somehow export */
-                               break; /* for now we ignore it */
+                       case USB_CDC_COUNTRY_TYPE: /* export through sysfs*/
+                               cfd = (struct usb_cdc_country_functional_desc 
*)buffer;
+                               break;
                        case USB_CDC_HEADER_TYPE: /* maybe check version */ 
                                break; /* for now we ignore it */ 
                        case USB_CDC_ACM_TYPE:
@@ -983,6 +1020,34 @@ skip_normal_probe:
                goto alloc_fail7;
        }
 
+       usb_set_intfdata (intf, acm);
+
+       i = device_create_file(&intf->dev, &dev_attr_bmCapabilities);
+       if (i < 0)
+               goto alloc_fail8;
+
+       if (cfd) { /* export the country data */
+               acm->country_codes = kmalloc(cfd->bLength - 4, GFP_KERNEL);
+               if (!acm->country_codes)
+                       goto skip_countries;
+               acm->country_code_size = cfd->bLength - 4;
+               memcpy(acm->country_codes, (u8 *)&cfd->wCountyCode0, 
cfd->bLength - 4);
+               acm->country_rel_date = cfd->iCountryCodeRelDate;
+
+               i = device_create_file(&intf->dev, &dev_attr_wCountryCodes);
+               if (i < 0) {
+                       kfree(acm->country_codes);
+                       goto skip_countries;
+               }
+
+               i = device_create_file(&intf->dev, 
&dev_attr_iCountryCodeRelDate);
+               if (i < 0) {
+                       kfree(acm->country_codes);
+                       goto skip_countries;
+               }
+       }
+
+skip_countries:
        usb_fill_int_urb(acm->ctrlurb, usb_dev, usb_rcvintpipe(usb_dev, 
epctrl->bEndpointAddress),
                         acm->ctrl_buffer, ctrlsize, acm_ctrl_irq, acm, 
epctrl->bInterval);
        acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -1006,9 +1071,10 @@ skip_normal_probe:
        tty_register_device(acm_tty_driver, minor, &control_interface->dev);
 
        acm_table[minor] = acm;
-       usb_set_intfdata (intf, acm);
-       return 0;
 
+       return 0;
+alloc_fail8:
+       usb_free_urb(acm->writeurb);
 alloc_fail7:
        for (i = 0; i < num_rx_buf; i++)
                usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, 
acm->rb[i].dma);
@@ -1027,7 +1093,7 @@ alloc_fail:
 
 static void acm_disconnect(struct usb_interface *intf)
 {
-       struct acm *acm = usb_get_intfdata (intf);
+       struct acm *acm = usb_get_intfdata(intf);
        struct usb_device *usb_dev = interface_to_usbdev(intf);
        int i;
 
@@ -1041,6 +1107,11 @@ static void acm_disconnect(struct usb_interface *intf)
                mutex_unlock(&open_mutex);
                return;
        }
+       if (acm->country_codes){
+               device_remove_file(&intf->dev, &dev_attr_wCountryCodes);
+               device_remove_file(&intf->dev, &dev_attr_iCountryCodeRelDate);
+       }
+       device_remove_file(&intf->dev, &dev_attr_bmCapabilities);
        acm->dev = NULL;
        usb_set_intfdata(acm->control, NULL);
        usb_set_intfdata(acm->data, NULL);
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index 1bcaea3..09f7765 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -91,6 +91,9 @@ struct acm {
        struct urb *ctrlurb, *writeurb;                 /* urbs */
        u8 *ctrl_buffer;                                /* buffers of urbs */
        dma_addr_t ctrl_dma;                            /* dma handles of 
buffers */
+       u8 *country_codes;                              /* country codes from 
device */
+       unsigned int country_code_size;                 /* size of this buffer 
*/
+       unsigned int country_rel_date;                  /* release date of 
version */
        struct acm_wb wb[ACM_NW];
        struct acm_ru ru[ACM_NR];
        struct acm_rb rb[ACM_NR];
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to