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