usbd-func.c
来自「Linux2.4.20针对三星公司的s3c2440内核基础上的一些设备驱动代码」· C语言 代码 · 共 1,206 行 · 第 1/3 页
C
1,206 行
/* * 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> * * Changes copyright (c) 2003 MontaVista Software, Inc. * * 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); }}int dbgflg_usbdfd_init;EXPORT_SYMBOL(dbgflg_usbdfd_init);extern int registered_functions;extern int registered_devices;#define dbg_init(lvl,fmt,args...) dbgPRINT(dbgflg_usbdfd_init,lvl,fmt,##args)/* * * 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. */__devinit __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 = cpu_to_le16((__u16)((str[0] << 8 | str[1]))); dbg_init (1, "%p %04x %04x", wData, *wData, cpu_to_le16((__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. */__devinit __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++ = cpu_to_le16((__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 __devexit 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)};__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};/* * * usbd_alloc_descriptor - allocate a usb descriptor * bDescriptorType * * Allocate and initialize a generic usb descriptor. */__devinit 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: case USB_DT_INTERFACE: case USB_DT_ENDPOINT: length = device_descriptor_sizes[bDescriptorType]; break; case CS_INTERFACE: switch (bDescriptorSubtype) { case USB_ST_HEADER: case USB_ST_CMF: case USB_ST_ACMF: case USB_ST_DLMF: case USB_ST_TRF: case USB_ST_TCLF: case USB_ST_NCT: case USB_ST_MCMF: case USB_ST_CCMF: case USB_ST_ENF: case USB_ST_ATMNF: case USB_ST_MDLM: length = class_descriptor_sizes[bDescriptorSubtype]; break; case USB_ST_UF: case USB_ST_CSF: case USB_ST_TOMF: case USB_ST_USBTF: case USB_ST_PUF: case USB_ST_EUF: case USB_ST_MDLMD: length = class_descriptor_sizes[bDescriptorSubtype] + elements; // XXX check me break; default: return NULL; } break; case USB_DT_HID: length = sizeof(struct usb_class_hid_descriptor) + elements; break; case USB_DT_REPORT: length = sizeof(struct usb_class_report_descriptor) + elements; break; case USB_DT_STRING: default: return NULL; } if (!(descriptor = ckmalloc (length, GFP_KERNEL))) { return NULL; } switch (bDescriptorType) { case CS_INTERFACE: descriptor->descriptor.generic.bDescriptorSubtype = bDescriptorSubtype; case USB_DT_DEVICE: case USB_DT_CONFIG: case USB_DT_INTERFACE: case USB_DT_ENDPOINT: case USB_DT_HID: case USB_DT_REPORT: descriptor->descriptor.generic.bLength = length; descriptor->descriptor.generic.bDescriptorType = bDescriptorType; break; case USB_DT_STRING: break; } dbg_init (1, "descriptor: %p length: %d", descriptor, length); return descriptor;}/* * * usbd_dealloc_descriptor - deallocate a usb descriptor * @descriptor: pointer to usb descriptor to deallocate * * Deallocate a descriptor, first deallocate the index string descriptors. */static __devexit void usbd_dealloc_descriptor (struct usb_descriptor *descriptor){ dbg_init (2, "descriptor: %p type: %d", descriptor, descriptor->descriptor.generic.bDescriptorType); if (descriptor) { switch (descriptor->descriptor.generic.bDescriptorType) { case USB_DT_DEVICE: dbg_init (2, "USB_DT_DEVICE"); usbd_dealloc_string (descriptor->descriptor.device.iManufacturer); usbd_dealloc_string (descriptor->descriptor.device.iProduct); usbd_dealloc_string (descriptor->descriptor.device.iManufacturer); break; case USB_DT_CONFIG: dbg_init (2, "USB_DT_CONFIG"); usbd_dealloc_string (descriptor->descriptor.configuration.iConfiguration); break; case USB_DT_INTERFACE: dbg_init (2, "USB_DT_INTERFACE"); usbd_dealloc_string (descriptor->descriptor.interface.iInterface); break; case CS_INTERFACE: dbg_init (2, "class descriptor: %p type: %d subtype: %d", descriptor, descriptor->descriptor.generic.bDescriptorType, descriptor->descriptor.generic.bDescriptorSubtype); dbg_init (2, "USB_CS_INTERFACE"); { struct usb_class_descriptor *class_descriptor = (struct usb_class_descriptor *) descriptor; switch (descriptor->descriptor.generic.bDescriptorSubtype) { case USB_ST_HEADER: case USB_ST_CMF: case USB_ST_ACMF: case USB_ST_DLMF: case USB_ST_TRF: case USB_ST_TCLF:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?