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

📄 pdc_bus.c

📁 philips公司ISP1362 USB OTG控制芯片的驱动
💻 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 */
  (isp1362_vendor_id & 0xFF),
  (isp1362_vendor_id >> 8),
  (isp1362_product_id & 0xFF),
  (isp1362_product_id >> 8),
  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_OTG 
  0x23,0x00,         		/* total length returned */ 
#else
  0x20,0x00,         		/* total length returned */ 
#endif /* CONFIG_USB_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_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_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[]=  isp1362_mfg_string;

unsigned char product_string[]= isp1362_product_string;

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);

	isp1362_printk(KERN_INFO __FILE__ ": Registered Driver %s\n",drv->name);

	/* 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);
	}

	isp1362_printk(KERN_INFO __FILE__ ": De-registered Driver %s\n",drv->name);


	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_BUSTATUS:
			break;
		case PDC_SUSPEND:
			bus_dev->prev_state = bus_dev->state;
			bus_dev->state = PDC_BUS_SUSPENDED;
			break;

	}

#ifdef CONFIG_USB_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_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();
	}

} /* End of pdc_bus_set_interface() */

void pdc_bus_get_status(__u8 *command)
{
	unsigned char reply[4];
	__u8	bmRequestType = command[0];
	pdc_pipe_handle_t		handle;
	__u8	reply_len = 2;

	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;

⌨️ 快捷键说明

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