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 + -
显示快捷键?