usbd-func.c

来自「linux嵌入式课程实践中的一个关于声卡驱动程序 。」· C语言 代码 · 共 1,288 行 · 第 1/4 页

C
1,288
字号
/* * linux/drivers/usbd/usbd-func.c - USB Function support * * Copyright (c) 2000, 2001, 2002 Lineo * Copyright (c) 2001 Hewlett Packard * * By:  *      Stuart Lynne <sl@lineo.com>,  *      Tom Rushworth <tbr@lineo.com>,  *      Bruce Balden <balden@lineo.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */   #include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/list.h>#include <asm/uaccess.h>#include <linux/netdevice.h>#include <linux/skbuff.h>#include <linux/etherdevice.h>#include <net/arp.h>#include <linux/rtnetlink.h>#include <linux/smp_lock.h>#include <linux/ctype.h>#include <linux/timer.h>#include <linux/string.h>#include <linux/atmdev.h>#include <linux/pkt_sched.h>#include "usbd.h"#include "usbd-debug.h"#include "usbd-func.h"#include "usbd-bus.h"#include "usbd-inline.h"#define LANGID_ENGLISH          "\011"#define LANGID_US_ENGLISH       "\004"//#define LANGIDs  LANGID_US_ENGLISH LANGID_ENGLISH LANGID_US_ENGLISH LANGID_ENGLISH LANGID_US_ENGLISH LANGID_ENGLISH #define LANGIDs  LANGID_US_ENGLISH LANGID_ENGLISH //#define LANGIDs  LANGID_ENGLISH LANGID_US_ENGLISH LANGID_US_ENGLISHextern int maxstrings;extern struct usb_string_descriptor **usb_strings;extern int usb_devices;extern struct usb_function_driver ep0_driver;extern struct list_head function_drivers;extern struct list_head devices;        static __inline__ struct usb_function_driver *list_entry_func(const struct list_head *le){    return list_entry(le, struct usb_function_driver, drivers);}static __inline__ struct usb_device_instance *list_entry_device(const struct list_head *le){    return list_entry(le, struct usb_device_instance, devices);}void lkfree (void *p){    if (p) {        kfree(p);    }}extern int registered_functions;extern int registered_devices;#if 0int dbgflg_usbdfd_init = 0;int dbgflg_usbdfd_usbe = 0;#define dbg_init(lvl,fmt,args...) dbgPRINT(dbgflg_usbdfd_init,lvl,fmt,##args)#define dbg_usbe(lvl,fmt,args...) dbgPRINT(dbgflg_usbdfd_usbe,lvl,fmt,##args)#else#define dbg_init(lvl,fmt,args...) #define dbg_usbe(lvl,fmt,args...) #endif/* * * usbd_alloc_string_zero - allocate a string descriptor and return index number * @str: pointer to string * * Find an empty slot in index string array, create a corresponding descriptor * and return the slot number. */__init __u8 usbd_alloc_string_zero(char *str){    struct usb_string_descriptor *string;    __u8 bLength;    __u16 *wData;    dbg_init(1, "%02x %02x %02x %02x", str[0], str[1], str[2], str[3]);    if (usb_strings[0] == NULL) {        bLength = sizeof(struct usb_string_descriptor) + strlen(str);        dbg_init(1, "blength: %d strlen: %d", bLength, strlen(str));        if (!(string = ckmalloc(bLength, GFP_KERNEL))) {            return 0;        }        string->bLength = bLength;        string->bDescriptorType = USB_DT_STRING;        for (wData = string->wData;*str;) {            *wData = (__u16)((str[0] << 8 | str[1]));            dbg_init(1, "%p %04x %04x",  wData, *wData,                     (((__u16)str[0] << 8 | str[1])));            str += 2;            wData++;        }        // store in string index array        usb_strings[0] = string;    }    return 0;}/* * * usbd_alloc_string - allocate a string descriptor and return index number * @str: pointer to string * * Find an empty slot in index string array, create a corresponding descriptor * and return the slot number. */__init __u8 usbd_alloc_string(char *str){    int i;    struct usb_string_descriptor *string;    __u8 bLength;    __u16 *wData;    //return 0;    if (!str || !strlen(str)) {        return 0;    }    dbg_init(1,"%d: %s", maxstrings, str);    // find an empty string descriptor slot    for (i=1;i<maxstrings;i++) {        if (usb_strings[i] == NULL) {            bLength = sizeof(struct usb_string_descriptor) + 2*strlen(str);            dbg_init(1,"%s -> %d strlen: %d bLength: %d", str, i, strlen(str), bLength);            if (!(string = ckmalloc(bLength, GFP_KERNEL))) {                return 0;            }            string->bLength = bLength;            string->bDescriptorType = USB_DT_STRING;            for (wData = string->wData;*str;) {                *wData++ = (__u16)(*str++);            }            // store in string index array            usb_strings[i] = string;            return i;        }#if 1        else {            char *cp = str;            int j;            for (j = 0; (j < ((usb_strings[i]->bLength - 1) / 2)) &&                     ((usb_strings[i]->wData[j] & 0xff) == cp[j]); j++)            {            dbg_init(4, "checking for duplicate %d:%d: strlen: %d bLength: %d bLength-1/2: %d wData[%04x] cp[%02x]",                     i, j, strlen(str),                     usb_strings[i]->bLength,                     (usb_strings[i]->bLength - 1) / 2,                    (usb_strings[i]->wData[j]),                     cp[j]                    );            }            dbg_init(1, "finished               %d:%d: strlen: %d bLength: %d bLength-1/2: %d wData[%04x] cp[%02x]",                     i, j, strlen(str),                     usb_strings[i]->bLength,                     (usb_strings[i]->bLength - 1) / 2,                    (usb_strings[i]->wData[j]),                     cp[j]                    );                        if ((j >= ((usb_strings[i]->bLength - 1) / 2)) /*&& ((usb_strings[i]->wData[j]&0xff) == cp[j])*/) {                dbg_init(1,"%s -> %d (duplicate)", str, i);                return i;            }        }#endif    }    return 0;}/* * * usbd_dealloc_string - deallocate a string descriptor * @index: index into strings array to deallocte * * Find and remove an allocated string. */void __exit usbd_dealloc_string(__u8 index){    struct usb_string_descriptor *string;    dbg_init(1,"%d", index);    if ((index > 0) && (index < maxstrings) && (string = usb_strings[index])) {        usb_strings[index] = NULL;        dbg_init(1,"%p", string);        lkfree(string);    }}__u8 device_descriptor_sizes[] = {    0,    sizeof(struct usb_device_descriptor),    sizeof(struct usb_configuration_descriptor),    sizeof(struct usb_string_descriptor),    sizeof(struct usb_interface_descriptor),    sizeof(struct usb_endpoint_descriptor),    0,    0,    0,    sizeof(struct usb_otg_descriptor),};__u8 class_descriptor_sizes[] = {    sizeof(struct usb_class_header_function_descriptor),        // 0x0    sizeof(struct usb_class_call_management_descriptor),        // 0x1    sizeof(struct usb_class_abstract_control_descriptor),       // 0x2    sizeof(struct usb_class_direct_line_descriptor),            // 0x3    sizeof(struct usb_class_telephone_ringer_descriptor),       // 0x4    sizeof(struct usb_class_telephone_operational_descriptor),  // 0x5    sizeof(struct usb_class_union_function_descriptor),         // 0x6    sizeof(struct usb_class_country_selection_descriptor),      // 0x7    sizeof(struct usb_class_telephone_operational_descriptor),  // 0x8    sizeof(struct usb_class_usb_terminal_descriptor),           // 0x9    sizeof(struct usb_class_network_channel_descriptor),        // 0xa    sizeof(struct usb_class_protocol_unit_function_descriptor), // 0xb    sizeof(struct usb_class_extension_unit_descriptor),         // 0xc    sizeof(struct usb_class_multi_channel_descriptor),          // 0xd    sizeof(struct usb_class_capi_control_descriptor),           // 0xe    sizeof(struct usb_class_ethernet_networking_descriptor),    // 0xf    sizeof(struct usb_class_atm_networking_descriptor),         // 0x10    0,                                                          // 0x11    sizeof(struct usb_class_mdlm_descriptor),                   // 0x12    sizeof(struct usb_class_mdlmd_descriptor),                  // 0x13    0,                                                          // 0x14    0,                                                          // 0x15    0,                                                          // 0x16    0,                                                          // 0x17    0,                                                          // 0x18    0,                                                          // 0x19    0,                                                          // 0x1a    0,                                                          // 0x1b    0,                                                          // 0x1c    0,                                                          // 0x1d    0,                                                          // 0x1e    0,                                                          // 0x1f    0,                                                          // 0x20    sizeof(struct usb_class_hid_descriptor),                    // 0x21};/* * * usbd_alloc_descriptor - allocate a usb descriptor * bDescriptorType  * * Allocate and initialize a generic usb descriptor. */__init static void * usbd_alloc_descriptor(__u8 bDescriptorType, __u8 bDescriptorSubtype, __u8 elements){    struct usb_descriptor *descriptor;     int length;    dbg_init(1,"type: %d subtype: %d elements: %d", bDescriptorType, bDescriptorSubtype, elements);    switch (bDescriptorType) {    case USB_DT_DEVICE:    case USB_DT_CONFIG:

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?