网站资料

http://www.google.com.hk/search?hl=zh-CN&newwindow=1&safe=strict&q=Logitech+driver+Linux&aq=f&aqi=&aql=&oq=&gs_rfai=

 

#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/kref.h>
#include <linux/smp_lock.h>
#include <linux/usb.h>
#include <asm/uaccess.h>


/* 设备ID号 */
#define USB_WEBCAM_VENDOR_ID        0x046d
#define USB_WEBCAM_PRODUCT_ID    0x09a4

#define VEDIO_CONTROL_NUM        0
#define VEDIO_STREAMING_NUM    1
#define AUDIO_STREAMING_NUM    3

#define VEDIO_WMAXPACKETSIZE_800BYTES    5
#define AUDIO_WMAXPACKETSIZE_36BYTES    1
#define HID_WMAXPACKETSIZE_16BYTES    0



static struct usb_device_id webcam_table [] = {
    { USB_DEVICE(USB_WEBCAM_VENDOR_ID, USB_WEBCAM_PRODUCT_ID) },
    { }                   
};
MODULE_DEVICE_TABLE (usb, webcam_table);


/*一个设备有三个设备文件,conn_dev_count标识设备文件的总数*/
int disconn_id;

/*次设备号*/
#define USB_WEBCAM_HID_MINOR_BASE    192
#define USB_WEBCAM_VEDIO_MINOR_BASW    200
#define USB_WEBCAM_AUDIO_MINOR_BASW    210

/*摄像头结构体*/
struct usb_webcam {
    struct usb_device *    udev;           
    struct usb_interface *    interface;       
    unsigned char *        isoc_in_buffer;       
    unsigned char *        int_buffer;
    size_t            isoc_in_size;       
    size_t            int_size;
    __u8            isoc_in_endpointAddr;   
    __u8            isoc_out_endpointAddr;   
    __u8            int_endpointAddr;
    struct kref        kref;
    struct semaphore     busy_lock;
};
#define to_webcam_dev(d) container_of(d, struct usb_webcam, kref)

static struct usb_driver webcam_driver;

static void webcam_delete(struct kref *kref)
{   
    struct usb_webcam *dev = to_webcam_dev(kref);
    usb_put_dev(dev->udev);
    kfree (dev->isoc_in_buffer);
    kfree(dev->int_buffer);
    kfree (dev);
}

static int webcam_open(struct inode *inode, struct file *file)
{
    struct usb_webcam *dev;
    struct usb_interface *interface;
    int subminor;
    int retval = 0;

    subminor = iminor(inode);

    interface = usb_find_interface(&webcam_driver, subminor);
    if (!interface) {
        err ("%s - error, can't find device for minor %d",
             __FUNCTION__, subminor);
        retval = -ENODEV;
        goto exit;
    }

    dev = usb_get_intfdata(interface);
    if (!dev) {
        retval = -ENODEV;
        goto exit;
    }
   
    kref_get(&dev->kref);

    file->private_data = dev;

exit:
    return retval;
}

static int webcam_release(struct inode *inode, struct file *file)
{
    struct usb_webcam *dev;

    dev = (struct usb_webcam *)file->private_data;
    if (dev == NULL)
        return -ENODEV;

    kref_put(&dev->kref, webcam_delete);
    return 0;
}

static ssize_t webcam_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
    struct usb_webcam *dev;
    int retval = 0;

    dev = (struct usb_webcam *)file->private_data;
   
    retval = usb_bulk_msg(dev->udev,
                  usb_rcvisocpipe(dev->udev, dev->isoc_in_endpointAddr),
                  dev->isoc_in_buffer,
                  min(dev->isoc_in_size, count),
                  &count, HZ*10);

    if (!retval) {
        if (copy_to_user(buffer, dev->isoc_in_buffer, count))
            retval = -EFAULT;
        else
            retval = count;
    }

    return retval;
}

static void webcam_write_isoc_callback(struct urb *urb)
{
    if (urb->status &&
        !(urb->status == -ENOENT ||
          urb->status == -ECONNRESET ||
          urb->status == -ESHUTDOWN)) {
        dbg("%s - nonzero write isoc status received: %d",
            __FUNCTION__, urb->status);
    }

    usb_buffer_free(urb->dev, urb->transfer_buffer_length,
            urb->transfer_buffer, urb->transfer_dma);
}

static ssize_t webcam_write(struct file *file, const char __user *user_buffer, size_t count, loff_t *ppos)
{
    struct usb_webcam *dev;
    int retval = 0;
    struct urb *urb = NULL;
    char *buf = NULL;

    dev = (struct usb_webcam *)file->private_data;

    if (count == 0)
        goto exit;

    urb = usb_alloc_urb(0, GFP_KERNEL);
    if (!urb) {
        retval = -ENOMEM;
        goto error;
    }

    buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);
    if (!buf) {
        retval = -ENOMEM;
        goto error;
    }
    if (copy_from_user(buf, user_buffer, count)) {
        retval = -EFAULT;
        goto error;
    }

    usb_fill_bulk_urb(urb, dev->udev,
              usb_sndisocpipe(dev->udev, dev->isoc_out_endpointAddr),
              buf, count, webcam_write_isoc_callback, dev);
    urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

    retval = usb_submit_urb(urb, GFP_KERNEL);
    if (retval) {
        err("%s - failed submitting write urb, error %d", __FUNCTION__, retval);
        goto error;
    }

    usb_free_urb(urb);

exit:
    return count;

error:
    usb_buffer_free(dev->udev, count, buf, urb->transfer_dma);
    usb_free_urb(urb);
    kfree(buf);
    return retval;
}


static int send_control_msg(int set, struct usb_webcam *dev, u8 request, u16 value,
                u16 index, void *cp, u16 size)
{
        int status;

        // for reasons not yet known to me, you can't send USB control messages
        // with data in the module (if you are compiled as a module).  Whatever
        // the reason, copying it to memory allocated as kernel memory then
        // doing the usb control message fixes the problem.

        struct usb_device *udev = dev->udev;
        unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL);
        memcpy(transfer_buffer, cp, size);

        if (udev == NULL)
                return -ENODEV;
        //up(&dev->busy_lock);

        status = usb_control_msg(udev,
                        set ? usb_sndctrlpipe(udev,
                                0) :
                        usb_rcvctrlpipe(udev, 0), request,
                        (set ? USB_DIR_OUT : USB_DIR_IN) |
                        USB_TYPE_VENDOR | USB_RECIP_DEVICE, value,
                        index, transfer_buffer, size, 1000);

        kfree(transfer_buffer);

       // DBG("ctrl msg:: value: %0x, index: %0x, size: %i/n", value, index,
                        //size);
        status = min(status, 0);
        if (status < 0) {
                printk("send_msg: Failed sending control message, error %d./n",
                                status);
                printk("ctrl msg:: dir: %i, value: %0x, index: %0x, size: %i/n",
                                set, value, index, size);
        }
       //if (down_interruptible(&dev->busy_lock))
       //         return -EINTR;

        return status;
}
static struct file_operations webcam_fops = {
    .owner =    THIS_MODULE,
    .read =        webcam_read,
    .write =    webcam_write,
    .open =        webcam_open,
    .release =    webcam_release,
};

/*vedio control接口*/
static struct usb_class_driver webcam_hid_class = {
    .name = "/Logitech/camhid%d",
    .fops = &webcam_fops,
    .minor_base = USB_WEBCAM_HID_MINOR_BASE,
};

/*vedio streaming 接口*/
static struct usb_class_driver webcam_vedio_class = {
    .name = "/Logitech/camvedio%d",
    .fops = &webcam_fops,
    .minor_base = USB_WEBCAM_VEDIO_MINOR_BASW,
};

/*audio streaming 接口*/
static struct usb_class_driver webcam_audio_class={
    .name="/Logitech/camaudio%d",
    .fops=&webcam_fops,
    .minor_base =USB_WEBCAM_AUDIO_MINOR_BASW,
};

/*
 *@author:李飞翔
 *@Date:2010/08/25
*@function:实现对摄像头设备的识别和接口的注册。
*/
static int webcam_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
    struct usb_webcam *dev = NULL;
    struct usb_host_interface *iface_desc=NULL;
    struct usb_endpoint_descriptor *endpoint=NULL;
    struct usb_class_driver *cur_usb_class=NULL;
    __u8 select_setting;
    size_t buffer_size;
    int flag=0;
    int i;
    int retval = -ENOMEM;
    iface_desc=interface->cur_altsetting ;
     /*为接口分配空间*/
    dev = kmalloc(sizeof(struct usb_webcam), GFP_KERNEL);
    if (dev == NULL) {
        err("Out of memory");
        goto error;
    };
    memset(dev, 0x00, sizeof (*dev));
    kref_init(&dev->kref);

    dev->udev = usb_get_dev(interface_to_usbdev(interface));
    dev->interface = interface;printk("%d/n",iface_desc->desc.bInterfaceNumber);
    /*判断是哪种类型的接口*/
    switch(iface_desc->desc.bInterfaceNumber)
    {
        case VEDIO_CONTROL_NUM:printk("interupt/n");
                select_setting=HID_WMAXPACKETSIZE_16BYTES;
                cur_usb_class=&webcam_hid_class;
                flag=1;
                                disconn_id++;
                break;
        case VEDIO_STREAMING_NUM:printk("vedio/n");
                select_setting=VEDIO_WMAXPACKETSIZE_800BYTES;
                cur_usb_class=&webcam_vedio_class;
                disconn_id++;
                break;
        case AUDIO_STREAMING_NUM:printk("audio/n");
                select_setting=AUDIO_WMAXPACKETSIZE_36BYTES;
                cur_usb_class=&webcam_audio_class;
                disconn_id++;               
                break;
        default:
                goto error;
    }
    /* 选择接口设置*/
    for(i=0;i<interface->num_altsetting;i++){
        if(interface->altsetting[i].desc.bAlternateSetting==select_setting){
            interface->cur_altsetting=interface->altsetting+i;
            iface_desc=interface->cur_altsetting;
            endpoint=&iface_desc->endpoint->desc;
            break;
        }
    }
    /*判断是否是等时端点*/
    if (!dev->isoc_in_endpointAddr &&usb_endpoint_xfer_isoc(endpoint)) {
        buffer_size = endpoint->wMaxPacketSize;
        dev->isoc_in_size = buffer_size;
        dev->isoc_in_endpointAddr = endpoint->bEndpointAddress;
        dev->interface = interface;
        dev->isoc_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
        if (!dev->isoc_in_buffer) {
            err("Could not allocate isoc_in_buffer");
            goto error;
        }
     }
    /*判断是否是中断端点*/
    if(!dev->int_endpointAddr&&usb_endpoint_xfer_int(endpoint)){
        buffer_size = endpoint->wMaxPacketSize;
        dev->int_size = buffer_size;
        dev->int_endpointAddr = endpoint->bEndpointAddress;
        dev->interface = interface;
        dev->int_buffer = kmalloc(buffer_size, GFP_KERNEL);
        if (!dev->int_buffer) {
            err("Could not allocate isoc_in_buffer");
            goto error;
        }       
    }
    usb_set_intfdata(interface, dev);

    /* 注册接口 */
    retval = usb_register_dev(interface, cur_usb_class);
    if (retval) {
        err("Not able to get a minor for this device.");
        usb_set_intfdata(interface, NULL);
        goto error;
    }
    /*control 接口下上电操作(未实现)*/
    if(flag==1)
    {
        u16 data=0xff;
            flag=send_control_msg(1,dev,0x05,(((unsigned int)reg) << 8),
                0,(void*)(&data),1);
        if(flag<0)
        {printk("powe on failed%d/n",flag);}
        else
        printk("successfully");
    }
    info("USB webcame device now attached to USBwebcam-%d", interface->minor);
    return 0;

error:
    if (dev)
        kref_put(&dev->kref, webcam_delete);
    return retval;
}

/*
 *@author:姜国际
 *@Date:2010/08/25
 *当有usb设备拔出时,系统自动调用webcam_disconnect函数,来删除该设备相应接口的下设备文件。
 *一个设备有几个设备文件,webcam_disconnect函数就调用相应次数。
 *按照注册的先后顺序一次删除设备文件。
 *支持多设备操作,当有多个usb设备拔出时,设备文件删除无误。
 */
static void webcam_disconnect(struct usb_interface *interface)
{
    struct usb_webcam *dev;
    int minor = interface->minor;

    /*加锁,阻止webcam_open()函数引起webcam_disconnect()中断*/
    lock_kernel();

    dev = usb_get_intfdata(interface);
    usb_set_intfdata(interface, NULL);

    /*删除设备文件处理,每次插入一个设备就自动生成camhid,camvideo,camaudio三个设备文件,
         *conn_dev_count数量为3的倍数,对其求余进行判断   
         */
    /*当余数=0时。删除先注册的 camhid设备文件.设备文件数减一.*/
        if(disconn_id%3==0)
    {   
        usb_deregister_dev(interface, &webcam_hid_class);
        disconn_id--;
    }
    /*当余数=2时。删除先注册的 camvideo设备文件.设备文件数减一.*/
    else if(disconn_id%3==2)
    {
        usb_deregister_dev(interface, &webcam_vedio_class);
        disconn_id--;
    }
    /*当余数=1时。删除先注册的 camaudio设备文件.设备文件数减一.*/
    else
    {
        usb_deregister_dev(interface, &webcam_audio_class);
        disconn_id--;
    }

    unlock_kernel();
    /* 设备数量减一 */
    kref_put(&dev->kref, webcam_delete);

    info("USB webcame #%d now disconnected", minor);
}

static struct usb_driver webcam_driver = {
    .name = "Logitech",
    .id_table = webcam_table,
    .probe = webcam_probe,
    .disconnect = webcam_disconnect,
};

static int __init usb_webcam_init(void)
{
    int result;
    result = usb_register(&webcam_driver);
    if (result)
        err("usb_register failed. Error number %d", result);

    return result;
}

static void __exit usb_webcam_exit(void)
{
    usb_deregister(&webcam_driver);
}

module_init (usb_webcam_init);
module_exit (usb_webcam_exit);

MODULE_LICENSE("GPL");

 

 

 

 

 

 

 

#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/kref.h>
#include <linux/smp_lock.h>
#include <linux/usb.h>
#include <asm/uaccess.h>


/* 设备ID号 */
#define USB_WEBCAM_VENDOR_ID        0x046d
#define USB_WEBCAM_PRODUCT_ID    0x09a4

#define VEDIO_CONTROL_NUM        0
#define VEDIO_STREAMING_NUM    1
#define AUDIO_STREAMING_NUM    3

#define VEDIO_WMAXPACKETSIZE_800BYTES    5
#define AUDIO_WMAXPACKETSIZE_36BYTES    1
#define HID_WMAXPACKETSIZE_16BYTES    0



static struct usb_device_id webcam_table [] = {
    { USB_DEVICE(USB_WEBCAM_VENDOR_ID, USB_WEBCAM_PRODUCT_ID) },
    { }                   
};
MODULE_DEVICE_TABLE (usb, webcam_table);


/*一个设备有三个设备文件,conn_dev_count标识设备文件的总数*/
int disconn_id;

/*次设备号*/
#define USB_WEBCAM_HID_MINOR_BASE    192
#define USB_WEBCAM_VEDIO_MINOR_BASW    200
#define USB_WEBCAM_AUDIO_MINOR_BASW    210

/*摄像头结构体*/
struct usb_webcam {
    struct usb_device *    udev;           
    struct usb_interface *    interface;       
    unsigned char *        isoc_in_buffer;       
    unsigned char *        int_buffer;
    size_t            isoc_in_size;       
    size_t            int_size;
    __u8            isoc_in_endpointAddr;   
    __u8            isoc_out_endpointAddr;   
    __u8            int_endpointAddr;
    struct kref        kref;
    struct semaphore     busy_lock;
};
#define to_webcam_dev(d) container_of(d, struct usb_webcam, kref)

static struct usb_driver webcam_driver;

static void webcam_delete(struct kref *kref)
{   
    struct usb_webcam *dev = to_webcam_dev(kref);
    usb_put_dev(dev->udev);
    kfree (dev->isoc_in_buffer);
    kfree(dev->int_buffer);
    kfree (dev);
}

static int webcam_open(struct inode *inode, struct file *file)
{
    struct usb_webcam *dev;
    struct usb_interface *interface;
    int subminor;
    int retval = 0;

    subminor = iminor(inode);

    interface = usb_find_interface(&webcam_driver, subminor);
    if (!interface) {
        err ("%s - error, can't find device for minor %d",
             __FUNCTION__, subminor);
        retval = -ENODEV;
        goto exit;
    }

    dev = usb_get_intfdata(interface);
    if (!dev) {
        retval = -ENODEV;
        goto exit;
    }
   
    kref_get(&dev->kref);

    file->private_data = dev;

exit:
    return retval;
}

static int webcam_release(struct inode *inode, struct file *file)
{
    struct usb_webcam *dev;

    dev = (struct usb_webcam *)file->private_data;
    if (dev == NULL)
        return -ENODEV;

    kref_put(&dev->kref, webcam_delete);
    return 0;
}

static ssize_t webcam_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
    struct usb_webcam *dev;
    int retval = 0;

    dev = (struct usb_webcam *)file->private_data;
   
    retval = usb_bulk_msg(dev->udev,
                  usb_rcvisocpipe(dev->udev, dev->isoc_in_endpointAddr),
                  dev->isoc_in_buffer,
                  min(dev->isoc_in_size, count),
                  &count, HZ*10);

    if (!retval) {
        if (copy_to_user(buffer, dev->isoc_in_buffer, count))
            retval = -EFAULT;
        else
            retval = count;
    }

    return retval;
}

static void webcam_write_isoc_callback(struct urb *urb)
{
    if (urb->status &&
        !(urb->status == -ENOENT ||
          urb->status == -ECONNRESET ||
          urb->status == -ESHUTDOWN)) {
        dbg("%s - nonzero write isoc status received: %d",
            __FUNCTION__, urb->status);
    }

    usb_buffer_free(urb->dev, urb->transfer_buffer_length,
            urb->transfer_buffer, urb->transfer_dma);
}

static ssize_t webcam_write(struct file *file, const char __user *user_buffer, size_t count, loff_t *ppos)
{
    struct usb_webcam *dev;
    int retval = 0;
    struct urb *urb = NULL;
    char *buf = NULL;

    dev = (struct usb_webcam *)file->private_data;

    if (count == 0)
        goto exit;

    urb = usb_alloc_urb(0, GFP_KERNEL);
    if (!urb) {
        retval = -ENOMEM;
        goto error;
    }

    buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);
    if (!buf) {
        retval = -ENOMEM;
        goto error;
    }
    if (copy_from_user(buf, user_buffer, count)) {
        retval = -EFAULT;
        goto error;
    }

    usb_fill_bulk_urb(urb, dev->udev,
              usb_sndisocpipe(dev->udev, dev->isoc_out_endpointAddr),
              buf, count, webcam_write_isoc_callback, dev);
    urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

    retval = usb_submit_urb(urb, GFP_KERNEL);
    if (retval) {
        err("%s - failed submitting write urb, error %d", __FUNCTION__, retval);
        goto error;
    }

    usb_free_urb(urb);

exit:
    return count;

error:
    usb_buffer_free(dev->udev, count, buf, urb->transfer_dma);
    usb_free_urb(urb);
    kfree(buf);
    return retval;
}


static int send_control_msg(int set, struct usb_webcam *dev, u8 request, u16 value,
                u16 index, void *cp, u16 size)
{
        int status;

        // for reasons not yet known to me, you can't send USB control messages
        // with data in the module (if you are compiled as a module).  Whatever
        // the reason, copying it to memory allocated as kernel memory then
        // doing the usb control message fixes the problem.

        struct usb_device *udev = dev->udev;
        unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL);
        memcpy(transfer_buffer, cp, size);

        if (udev == NULL)
                return -ENODEV;
        //up(&dev->busy_lock);

        status = usb_control_msg(udev,
                        set ? usb_sndctrlpipe(udev,
                                0) :
                        usb_rcvctrlpipe(udev, 0), request,
                        (set ? USB_DIR_OUT : USB_DIR_IN) |
                        USB_TYPE_VENDOR | USB_RECIP_DEVICE, value,
                        index, transfer_buffer, size, 1000);

        kfree(transfer_buffer);

       // DBG("ctrl msg:: value: %0x, index: %0x, size: %i/n", value, index,
                        //size);
        status = min(status, 0);
        if (status < 0) {
                printk("send_msg: Failed sending control message, error %d./n",
                                status);
                printk("ctrl msg:: dir: %i, value: %0x, index: %0x, size: %i/n",
                                set, value, index, size);
        }
       //if (down_interruptible(&dev->busy_lock))
       //         return -EINTR;

        return status;
}
static struct file_operations webcam_fops = {
    .owner =    THIS_MODULE,
    .read =        webcam_read,
    .write =    webcam_write,
    .open =        webcam_open,
    .release =    webcam_release,
};

/*vedio control接口*/
static struct usb_class_driver webcam_hid_class = {
    .name = "/Logitech/camhid%d",
    .fops = &webcam_fops,
    .minor_base = USB_WEBCAM_HID_MINOR_BASE,
};

/*vedio streaming 接口*/
static struct usb_class_driver webcam_vedio_class = {
    .name = "/Logitech/camvedio%d",
    .fops = &webcam_fops,
    .minor_base = USB_WEBCAM_VEDIO_MINOR_BASW,
};

/*audio streaming 接口*/
static struct usb_class_driver webcam_audio_class={
    .name="/Logitech/camaudio%d",
    .fops=&webcam_fops,
    .minor_base =USB_WEBCAM_AUDIO_MINOR_BASW,
};

/*
 *@author:李飞翔
 *@Date:2010/08/25
*@function:实现对摄像头设备的识别和接口的注册。
*/
static int webcam_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
    struct usb_webcam *dev = NULL;
    struct usb_host_interface *iface_desc=NULL;
    struct usb_endpoint_descriptor *endpoint=NULL;
    struct usb_class_driver *cur_usb_class=NULL;
    __u8 select_setting;
    size_t buffer_size;
    int flag=0;
    int i;
    int retval = -ENOMEM;
    iface_desc=interface->cur_altsetting ;
     /*为接口分配空间*/
    dev = kmalloc(sizeof(struct usb_webcam), GFP_KERNEL);
    if (dev == NULL) {
        err("Out of memory");
        goto error;
    };
    memset(dev, 0x00, sizeof (*dev));
    kref_init(&dev->kref);

    dev->udev = usb_get_dev(interface_to_usbdev(interface));
    dev->interface = interface;printk("%d/n",iface_desc->desc.bInterfaceNumber);
    /*判断是哪种类型的接口*/
    switch(iface_desc->desc.bInterfaceNumber)
    {
        case VEDIO_CONTROL_NUM:printk("interupt/n");
                select_setting=HID_WMAXPACKETSIZE_16BYTES;
                cur_usb_class=&webcam_hid_class;
                flag=1;
                                disconn_id++;
                break;
        case VEDIO_STREAMING_NUM:printk("vedio/n");
                select_setting=VEDIO_WMAXPACKETSIZE_800BYTES;
                cur_usb_class=&webcam_vedio_class;
                disconn_id++;
                break;
        case AUDIO_STREAMING_NUM:printk("audio/n");
                select_setting=AUDIO_WMAXPACKETSIZE_36BYTES;
                cur_usb_class=&webcam_audio_class;
                disconn_id++;               
                break;
        default:
                goto error;
    }
    /* 选择接口设置*/
    for(i=0;i<interface->num_altsetting;i++){
        if(interface->altsetting[i].desc.bAlternateSetting==select_setting){
            interface->cur_altsetting=interface->altsetting+i;
            iface_desc=interface->cur_altsetting;
            endpoint=&iface_desc->endpoint->desc;
            break;
        }
    }
    /*判断是否是等时端点*/
    if (!dev->isoc_in_endpointAddr &&usb_endpoint_xfer_isoc(endpoint)) {
        buffer_size = endpoint->wMaxPacketSize;
        dev->isoc_in_size = buffer_size;
        dev->isoc_in_endpointAddr = endpoint->bEndpointAddress;
        dev->interface = interface;
        dev->isoc_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
        if (!dev->isoc_in_buffer) {
            err("Could not allocate isoc_in_buffer");
            goto error;
        }
     }
    /*判断是否是中断端点*/
    if(!dev->int_endpointAddr&&usb_endpoint_xfer_int(endpoint)){
        buffer_size = endpoint->wMaxPacketSize;
        dev->int_size = buffer_size;
        dev->int_endpointAddr = endpoint->bEndpointAddress;
        dev->interface = interface;
        dev->int_buffer = kmalloc(buffer_size, GFP_KERNEL);
        if (!dev->int_buffer) {
            err("Could not allocate isoc_in_buffer");
            goto error;
        }       
    }
    usb_set_intfdata(interface, dev);

    /* 注册接口 */
    retval = usb_register_dev(interface, cur_usb_class);
    if (retval) {
        err("Not able to get a minor for this device.");
        usb_set_intfdata(interface, NULL);
        goto error;
    }
    /*control 接口下上电操作(实现)*/
    if(flag==1)
    {
        u16 power=0x00;
       
       
            flag=usb_control_msg(dev->udev,usb_sndctrlpipe(dev->udev,
                                0),0x05,
                    USB_DIR_OUT,
                0x3200,0,(void*)(&power),0x01,1000);
        if(flag<0)
        {printk("powe on failed%d/n",flag);}
        else
        printk("Power on successfully:%d/n",flag);



        u16 led=0x00|0xFF;
        flag=usb_control_msg(dev->udev,usb_sndctrlpipe(dev->udev,
                                0),0x05,
                 USB_RECIP_DEVICE,
                0x3400,0,(void*)(&led),sizeof(u16),2000);
        if(flag<0)
        {printk("LED on failed%d/n",flag);}
        else
        printk("LED successfully:%d/n",flag);
/*****************************************************************************/
       
    }

    info("USB webcame device now attached to USBwebcam-%d", interface->minor);
    return 0;

error:
    if (dev)
        kref_put(&dev->kref, webcam_delete);
    return retval;
}

/*
 *@author:姜国际
 *@Date:2010/08/25
 *当有usb设备拔出时,系统自动调用webcam_disconnect函数,来删除该设备相应接口的下设备文件。
 *一个设备有几个设备文件,webcam_disconnect函数就调用相应次数。
 *按照注册的先后顺序一次删除设备文件。
 *支持多设备操作,当有多个usb设备拔出时,设备文件删除无误。
 */
static void webcam_disconnect(struct usb_interface *interface)
{
    struct usb_webcam *dev;
    int minor = interface->minor;

    /*加锁,阻止webcam_open()函数引起webcam_disconnect()中断*/
    lock_kernel();

    dev = usb_get_intfdata(interface);
    usb_set_intfdata(interface, NULL);

    /*删除设备文件处理,每次插入一个设备就自动生成camhid,camvideo,camaudio三个设备文件,
         *conn_dev_count数量为3的倍数,对其求余进行判断   
         */
    /*当余数=0时。删除先注册的 camhid设备文件.设备文件数减一.*/
        if(disconn_id%3==0)
    {   
        usb_deregister_dev(interface, &webcam_hid_class);
        disconn_id--;
    }
    /*当余数=2时。删除先注册的 camvideo设备文件.设备文件数减一.*/
    else if(disconn_id%3==2)
    {
        usb_deregister_dev(interface, &webcam_vedio_class);
        disconn_id--;
    }
    /*当余数=1时。删除先注册的 camaudio设备文件.设备文件数减一.*/
    else
    {
        usb_deregister_dev(interface, &webcam_audio_class);
        disconn_id--;
    }

    unlock_kernel();
    /* 设备数量减一 */
    kref_put(&dev->kref, webcam_delete);

    info("USB webcame #%d now disconnected", minor);
}

static struct usb_driver webcam_driver = {
    .name = "Logitech",
    .id_table = webcam_table,
    .probe = webcam_probe,
    .disconnect = webcam_disconnect,
};

static int __init usb_webcam_init(void)
{
    int result;
    result = usb_register(&webcam_driver);
    if (result)
        err("usb_register failed. Error number %d", result);

    return result;
}

static void __exit usb_webcam_exit(void)
{
    usb_deregister(&webcam_driver);
}

module_init (usb_webcam_init);
module_exit (usb_webcam_exit);

MODULE_LICENSE("GPL");

 

你可能感兴趣的:(网站资料)