⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pdc_bus.c

📁 linux下的usb开发
💻 C
📖 第 1 页 / 共 2 页
字号:
/************************************************************* * Philips USB device protocol and Configuration driver * * (c) 2002 Koninklijke Philips Electronics N.V., All rights reserved *  * This  source code and any compilation or derivative thereof is the * proprietary information of Koninklijke Philips Electronics N.V. * and is confidential in nature. * Under no circumstances is this software to be exposed to or placed * under an Open Source License of any type without the expressed * written permission of Koninklijke Philips Electronics N.V. * * File Name:	pdc_bus.c * * History:	 * *	Version	Date		Author		Comments * ------------------------------------------------- * 	1.0		09/23/02	SYARRA		Initial Creation * 	1.1		11/22/02	SYARRA		Clear feature on unknown wIndex is stalled *									CF_WINDEX_FIX * * Note: use tab space 4 *************************************************************/#include <linux/config.h>#define	MODULE#include <linux/types.h>#include <linux/string.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/timer.h>#include <linux/mm.h>#include <linux/ioport.h>#include <linux/interrupt.h>#include <linux/major.h>#include <linux/errno.h>#include <linux/slab.h>#include <linux/module.h>#include <linux/vmalloc.h>#include <linux/init.h>#include <linux/tqueue.h>#include <asm/byteorder.h>#include <asm/irq.h>#include <asm/segment.h>#include <asm/io.h>#include <linux/proc_fs.h>#include <linux/poll.h>#include "pdc_intf.h"#include "usb_pdc.h"#include "pdc_protocol.h"#include "pdc_bus.h"/*------------------------------------------------------------------* *                   Local variables                                * *------------------------------------------------------------------*/struct pdc_bus			pdc_bus_device;struct pdc_bus			*bus_dev = &pdc_bus_device;struct pdc_pipe_opr		ctrl_pipe_opr;LIST_HEAD(pdc_class_drv_list);/* Device descriptor */unsigned char device_desc[] = {  PDC_DEV_DESC_LEN,  /* length of this desc. */  PDC_DEV_DESC_TYPE, /* DEVICE descriptor */  0x10,0x01,         /* spec rev level (BCD) */  0x00,              /* device class */  0x00,              /* device subclass */  0x00,              /* device protocol */    PDC_CTRL_MPS,      /* max packet size */#if 0  0xCC,0x04,         /* Philips Semiconductors vendor ID */					 /* for 1362 ISA evaluation kit - 0x1A61 				  	for 1362 PCI evaluation kit - 0x1A62 */#ifdef CONFIG_1362_PCI  0x62,0x1A,         /* device product ID */#else  0x61,0x1A,         /* device product ID */#endif /* CONFIG_1362_PCI */#else  (isp1362_vendor_id & 0xFF),  (isp1362_vendor_id >> 8),  (isp1362_product_id & 0xFF),  (isp1362_product_id >> 8),#endif  0x00,0x01,         /* 1362's revision ID */    1,                 /* index of manuf. string */     2,                 /* index of prod.  string */    3,                 /* index of ser. # string */     PDC_BUS_NUM_CONFIG /* number of configs. */ };unsigned char conf_desc[] = {  PDC_CONFIG_DESC_LEN,		/* length of this desc. */   PDC_CONFIG_DESC_TYPE,    	/* CONFIGURATION descriptor */  #ifdef CONFIG_USB_HCDC_OTG   0x23,0x00,         		/* total length returned */ #else  0x20,0x00,         		/* total length returned */ #endif /* CONFIG_USB_HCDC_OTG  */  PDC_BUS_NUM_INTF, 		/* number of interfaces */   0x01,            			/* number of this config */   0x00,              		/* index of config. string */    0xC0,              		/* attr.: self powered */     0x01,              		/* we take no bus power */  	    PDC_INTF_DESC_LEN,		/* length of this desc. */    PDC_INTF_DESC_TYPE,		/* INTERFACE descriptor */    0x00,              		/* interface number */  0x00,              		/* alternate setting */    0x02,              		/* # of (non 0) endpoints */   0x08,              		/* interface class (Mass Storage)*/  0x06,              		/* interface subclass (SCSI Transparent) */    0x50,              		/* interface protocol (BOT Protocol) */    0x00,              		/* index of intf. string */ 				    /* Pipe 0 */  PDC_EP_DESC_LEN,   		/* length of this desc. */     PDC_EP_DESC_TYPE,  		/* ENDPOINT descriptor */   0x82,              		/* address (IN) */    0x02,              		/* attributes  (BULK) */      (PDC_CONFIG_PIPE_MPS&0xff),/* max packet size */  (PDC_CONFIG_PIPE_MPS>>8),  0,                 		/* interval (ms) */				    /* Pipe 1 */   PDC_EP_DESC_LEN,   		/* length of this desc. */     PDC_EP_DESC_TYPE,  		/* ENDPOINT descriptor*/   0x01,              		/* address (OUT) */    0x02,              		/* attributes  (BULK) */      (PDC_CONFIG_PIPE_MPS&0xff),/* max packet size */  (PDC_CONFIG_PIPE_MPS>>8),  0                   		/* interval (ms) */#ifdef CONFIG_USB_HCDC_OTG   ,PDC_OTG_DESC_LEN  		/* length of this desc. */  ,PDC_OTG_DESC_TYPE 		/* OTG descriptor */  ,0x03				 		/* D1: HNP Support D0:SRP Support */#endif /* CONFIG_USB_HCDC_OTG */};#define PDC_BUS_CONFIG_DESC_LEN sizeof(conf_desc[0]) /* Unicode descriptors for our device description */unsigned char unicode_string[]= { 	0x04,0x03,	0x09,0x04 		/* We offer only one language: 0409, US English */};unsigned char mfg_string[]= {	26,3, 'P',0, 'h',0, 'i',0, 'l',0, 'i',0, 'p',0, 's',0, 	'-',0, 'A',0, 'P',0, 'I',0, 'C',0};unsigned char product_string[]= #if 1	isp1362_product_string#else{	60,3, '1',0, '3',0, '6',0, '2',0, '-',0, 'O',0, 'T',0, 'G',0, ' ',0,	'M',0, 'A',0, 'S',0, 'S',0, ' ',0, 	'S',0, 't',0, 'o',0, 'r',0, 'a',0, 'g',0, 'e',0, ' ',0,#ifdef CONFIG_1362_PCI	'P',0, 'C',0, 'I',0,#else	'I',0, 'S',0, 'A',0,#endif /* CONFIG_1362_PCI */	' ',0, 'K',0, 'i',0, 't',0}#endif;unsigned char serial_string[]= {	0x0A, 0x03, '1', 0x00, '.',0x00, '0', 0x00, '0', 0x00};	/*-------------------------------------------------------------------* *                     Local Function Declerations                   * *-------------------------------------------------------------------*/static	void pdc_bus_stall_control_pipe(void);static	void pdc_bus_dev_notif(unsigned long	context, unsigned long notif);static  int pdc_bus_ctrl_pipe_notificaion(unsigned long notif_type, void *priv,unsigned char	*cmd);static	void pdc_bus_get_descriptor(__u8 *command);static	int	pdc_nofif_write_control_pipe(__u8	*buff, __u16	len);static	void pdc_bus_usb_feature(__u8	*command);static	void pdc_bus_get_status(__u8	*command);static	void pdc_bus_set_configuration(unsigned char *command);static	void pdc_bus_set_interface(unsigned char *command);/*----------------------------------------------------------------* *                   External Interface Functions                 * *----------------------------------------------------------------*//*  * Class Driver registration/Deregistration functions  */int pdc_register_class_drv( struct pdc_class_drv *drv){	func_debug(("pdc_register_class_drv(%p)\n",drv))	/* 	 * Put it in the class drivers list	 */	list_add(&drv->driver_list, &pdc_class_drv_list);	/* TODO if the device is active, call the probe function */	return 0;	/* Success */} /* End of pdc_register_class_drv() */void pdc_deregister_class_drv( struct pdc_class_drv *drv){	func_debug(("pdc_deregister_class_drv(%p)\n",drv))		list_del(&drv->driver_list);		if(drv && drv->set_config) {		drv->set_config(drv->priv_data,0);	}	return;} /* End of pdc_deregister_class_drv() *//* Initialize all the end point data structures */int	pdc_bus_init(struct pdc_dev	*pdc) {	/* Enable only control end points */	__u16	size;	struct pdc_ep_desc	*ep_desc;	int		result;	func_debug(("pdc_bus_init(void)\n"))	bus_dev->ctrl_pipe = PDC_INV_PIPE_HANDLE;	INIT_LIST_HEAD(&pdc_class_drv_list);	bus_dev->configuration = 0;	bus_dev->interface = 0;	bus_dev->state = PDC_BUS_UNKNOWN;	size = sizeof(struct pdc_config_dev) + (sizeof(struct pdc_ep_desc) * PDC_MAX_PIPES);	bus_dev->pdc_config = (struct pdc_config_dev*) kmalloc(size, GFP_KERNEL);	if(!(bus_dev->pdc_config)) {		return -1;	}		bus_dev->pdc_config->num_eps = 3;	/* Control+Bulk In + Bulk OUT */	ep_desc = bus_dev->pdc_config->ep_desc;	ep_desc->ep_num = 0;						/* Control End point*/	ep_desc->ep_dir = PDC_EP_DIR_OUT;			/* In endpoint */	ep_desc->attributes = PDC_EP_CONTROL;		/* Control type*/	ep_desc->max_pkt_size = 64;					/* Maximum packet size */	ep_desc++;	ep_desc->ep_num = 1;						/* Bulk out end point */	ep_desc->ep_dir = PDC_EP_DIR_OUT;			/* Out endpoint */	ep_desc->attributes = PDC_EP_BULK;			/* Transfer type*/	ep_desc->max_pkt_size = 64;					/* Maximum packet size */	ep_desc++;	ep_desc->ep_num = 2;						/* Bulk In end point */	ep_desc->ep_dir = PDC_EP_DIR_IN;			/* In endpoint */	ep_desc->attributes = PDC_EP_BULK;			/* Transfer type*/	ep_desc->max_pkt_size = 64;					/* Maximum packet size */	bus_dev->pdc_config->num_eps = 1;	/* Control in and out */	bus_dev->pdc_config->context = (unsigned long)bus_dev->pdc_config;	bus_dev->pdc_config->notif = pdc_bus_dev_notif;	result = pdc_configure_device(bus_dev->pdc_config);	if(result==0) {		ep_desc = bus_dev->pdc_config->ep_desc;		bus_dev->pipe_desc.ep = ep_desc->ep_num;		bus_dev->pipe_desc.ep_dir = ep_desc->ep_dir;		bus_dev->pipe_desc.context = (unsigned long)ep_desc;		bus_dev->pipe_desc.priv = (void*)bus_dev->pdc_config;		bus_dev->pipe_desc.notify = pdc_bus_ctrl_pipe_notificaion;		bus_dev->ctrl_pipe = pdc_open_pipe(&bus_dev->pipe_desc);		if(bus_dev->ctrl_pipe == PDC_INV_PIPE_HANDLE) {			result = -1;		} else {			result = 0;			bus_dev->state = PDC_BUS_INIT;			bus_dev->pdc_priv = pdc;		}	}	return result;} /* End of pdc_bus_init(void) */void pdc_bus_deinit(void){	func_debug(("pdc_bus_deinit(void)\n"))	/* Close the control pipe */	if(bus_dev->ctrl_pipe!= PDC_INV_PIPE_HANDLE){		pdc_close_pipe(bus_dev->ctrl_pipe);		bus_dev->ctrl_pipe= PDC_INV_PIPE_HANDLE;	}	/* Free the configuration data */	if(bus_dev->pdc_config) kfree(bus_dev->pdc_config);	bus_dev->pdc_config = NULL;	bus_dev->pdc_priv = NULL;	bus_dev->state = PDC_BUS_UNKNOWN;	return;} /* End of pdc_bus_deinit() */void pdc_bus_dev_notif(unsigned long	context, unsigned long notif){	struct list_head *tmp;	func_debug(("pdc_bus_dev_notif(context=%x,notif=%x)\n",context, notif))	switch(notif) {		case PDC_RESET:			if(bus_dev->configuration) {						bus_dev->configuration = 0;				tmp = pdc_class_drv_list.next;				/* Find the class driver that supports this request */				while (tmp != &pdc_class_drv_list) {					struct pdc_class_drv *cd = list_entry(tmp,struct pdc_class_drv, driver_list);					tmp = tmp->next;					if(cd->set_config)	cd->set_config(cd->priv_data,bus_dev->configuration);				}				bus_dev->pdc_config->num_eps = 1;	/* Control */				pdc_configure_device(bus_dev->pdc_config);			}			bus_dev->configuration = 0;			bus_dev->state = PDC_BUS_DEFAULT;			break;		case PDC_RESUME:			bus_dev->state = bus_dev->prev_state;			break;		case PDC_SUSPEND:			bus_dev->prev_state = bus_dev->state;			bus_dev->state = PDC_BUS_SUSPENDED;			break;	}#ifdef CONFIG_USB_HCDC_OTG	/* all kind of device notifications are passed to the OTG controller	 * (reset, suspend, resume)         */	if( bus_dev->otg && bus_dev->otg->otg_notif) {		bus_dev->otg->otg_notif(bus_dev->otg->priv_data, notif,0);	}#endif /* CONFIG_USB_HCDC_OTG */	return;} /* End of pdc_bus_dev_notif *//*--------------------------------------------------------------* *           USB Class/Vendor specific functions *--------------------------------------------------------------*//* Make a configuration active */void pdc_bus_set_configuration(unsigned char *command){	int result;	struct list_head *tmp;		func_debug(("set_configuration((command=%p)\n",command))	if((bus_dev->state < PDC_BUS_ADDRESSED) || (command[0]&PDC_REQTYPE_DIR_MASK)) {		/* You are not supposed to receive this in these states */		pdc_bus_stall_control_pipe();		return;	}	if(command[2] > 1) {		/* Invalid configuration */		/* Stall control in and out pipes */		pdc_bus_stall_control_pipe();	} else {		if((bus_dev->configuration) || (command[2] == 0)) {			/* Unconfigure the class drivers */			tmp = pdc_class_drv_list.next;			/* Find the class driver that supports this request */			while (tmp != &pdc_class_drv_list) {				struct pdc_class_drv *cd = list_entry(tmp,struct pdc_class_drv, driver_list);				tmp = tmp->next;				if(cd->set_config)	cd->set_config(cd->priv_data,0);			}			bus_dev->pdc_config->num_eps = 1;	/* Control */			result = pdc_configure_device(bus_dev->pdc_config);			bus_dev->state = PDC_BUS_ADDRESSED;		}		bus_dev->configuration = command[2];		bus_dev->interface = bus_dev->alternate = 0;		if(bus_dev->configuration) {			/* Configure the class drivers */			bus_dev->pdc_config->num_eps = 3;	/* Control + bulk */			result = pdc_configure_device(bus_dev->pdc_config);			bus_dev->state = PDC_BUS_CONFIGURED;			tmp = pdc_class_drv_list.next;			/* Find the class driver that supports this request */			while (tmp != &pdc_class_drv_list) {				struct pdc_class_drv *cd = list_entry(tmp,struct pdc_class_drv, driver_list);				tmp = tmp->next;				if(cd->set_config)	cd->set_config(cd->priv_data,bus_dev->configuration);			}		}		pdc_nofif_write_control_pipe(NULL, 0);	}	return;} /* End of pdc_bus_set_configuration() */void pdc_bus_set_interface(unsigned char *command){	struct list_head *tmp;	if((bus_dev->state > PDC_BUS_DEFAULT) && (command[2] < PDC_BUS_NUM_INTF) &&		!(command[0]&PDC_REQTYPE_DIR_MASK)) {		bus_dev->interface = command[2];		bus_dev->alternate = command[4];		tmp = pdc_class_drv_list.next;		/* Find the class driver that supports this request */		while (tmp != &pdc_class_drv_list) {			struct pdc_class_drv *cd = list_entry(tmp,struct pdc_class_drv, driver_list);			if(cd->set_intf)	cd->set_intf(cd->priv_data,bus_dev->interface, 											 bus_dev->alternate);			tmp = tmp->next;		}		pdc_nofif_write_control_pipe(NULL, 0);	} else {		pdc_bus_stall_control_pipe();

⌨️ 快捷键说明

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