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

📄 pdc_bus.c

📁 philips公司ISP1362 USB OTG控制芯片的驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
	}

	/* Find request target */
	switch (bmRequestType&0x03) {
		case RECIP_DEVICE:          /* DEVICE */  
			reply[0] = PDC_GETSTATUS_SELF_POWERED;
			reply[1]=0;
			break;

		case RECIP_INTERFACE:       /* INTERFACE */  

			reply[0]=0;
			reply[1]=0;
			break;
		
		case RECIP_ENDPOINT: 
			/* reply[0] needs to be 1 if the endpoint
			referred to in command[3] is stalled,
			otherwise 0 */

			/* ep->pipe handle and context conversion */
			handle = pdc_usb_to_epreg((command[4]&0x0F),(command[4]&0x80));
	
			/* Check EP status */
			ctrl_pipe_opr.handle = handle;
			ctrl_pipe_opr.context = (unsigned long) bus_dev;
			ctrl_pipe_opr.opr = PDC_GET_PIPE_STATUS;
			pdc_pipe_operation(&ctrl_pipe_opr);

			reply[0] = (ctrl_pipe_opr.pipe_status & PDC_PIPE_STALL) ? 1 : 0;
			reply[1]=0;
	
			break;
		
		default:                        /* UNDEFINED */   
			/* Stall endpoints 0 & 1 */
			reply_len = 0;

			return;
	}
	
	/* Write this packet */
	pdc_nofif_write_control_pipe(reply, reply_len);

	return;

} /* End of pdc_bus_get_status() */

void pdc_bus_usb_feature(__u8	*command)
{
	__u8	bmRequestType = command[0];
	__u8	inv_state = PDC_BUS_ADDRESSED;

	/* 
     * For USB 2.0 Suppliment OTG 1.0 Specification,
     * Set feature will be accepted in default state also 
     */

	if(command[1]==SET_FEATURE) inv_state = PDC_BUS_DEFAULT;

	if((bus_dev->state < inv_state) || (command[0]&PDC_REQTYPE_DIR_MASK)) {
		/* You are not supposed to receive this in these states */
		pdc_bus_stall_control_pipe();
		return;
	}

	switch (bmRequestType & 0x03) {

		case RECIP_DEVICE:

		if (command[2]==PDC_FEATURE_REMOTE_WAKEUP) {

			pdc_nofif_write_control_pipe(NULL, 0);
		}
#ifdef CONFIG_USB_OTG
		else if ((command[2]==PDC_FEATURE_B_HNP_ENABLE)||
				(command[2]==PDC_FEATURE_A_HNP_SUPPORT)||
				(command[2]==PDC_FEATURE_A_ALTHNP_SUPPORT))
		{
			pdc_nofif_write_control_pipe(NULL, 0);

			//inform the OTG module of this
			if( bus_dev->otg && bus_dev->otg->otg_notif) {
				bus_dev->otg->otg_notif(bus_dev->otg->priv_data, PDC_SET_HNP,command[2]);
			}
		}
#endif /* CONFIG_USB_OTG */
		else {
			/* CF_WINDEX_FIX */
			/* Stall endpoints 0 & 1 */
			pdc_bus_stall_control_pipe();
		}

		break;
					
		/* INTERFACE */  
		case RECIP_INTERFACE:
			pdc_nofif_write_control_pipe(NULL, 0);
			break;
					
		/* ENDPOINT */
		case RECIP_ENDPOINT:  
		{
			/* Find endpoint */
			pdc_pipe_handle_t handle;
			int stall=(command[1]==SET_FEATURE);

			handle = pdc_usb_to_epreg((command[4]&0x0F),(command[4]&0x80));
			detail_debug(("pdc: endpoint stall(%d)\n",handle))

			/* Set/clear endpoint stall flag */
			ctrl_pipe_opr.handle = handle;
			ctrl_pipe_opr.context = (unsigned long) bus_dev;
			if (stall) {
				ctrl_pipe_opr.opr = PDC_PIPE_STALL;
			} else if(handle > 0x01) {
				/* For Control In & Out already unstalled by
					HW */
				ctrl_pipe_opr.opr = PDC_PIPE_UNSTALL;
			}
			pdc_pipe_operation(&ctrl_pipe_opr);

			/* 0-byte ACK */
			pdc_nofif_write_control_pipe(NULL, 0);
		}
		break;
				
		/* UNDEFINED */   
		default:              
			/* Stall endpoints 0 & 1 */
			pdc_bus_stall_control_pipe();
			break;
	}

}


/* Deal with get_descriptor */
void pdc_bus_get_descriptor(__u8 *command)
{
	__u8	*desc_ptr = NULL;
	__u16	desc_len = 0, req_len;

	func_debug(("get_descriptor(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;
	}


	switch( command[3]) {

		case PDC_DEV_DESC_TYPE:
			desc_ptr = device_desc;
			desc_len = sizeof(device_desc);
			break;

		case PDC_CONFIG_DESC_TYPE:

			if(command[2] < PDC_BUS_NUM_CONFIG) {
				desc_ptr = conf_desc;
				desc_len = sizeof(conf_desc);
			}
			break;

		case PDC_STRING_DESC_TYPE:

			switch(command[2]) {

				case 0:
					desc_ptr = unicode_string;
					desc_len = sizeof(unicode_string);

					break;
				
				case 1:
					desc_ptr = mfg_string;
					desc_len = sizeof(mfg_string);

					break;

				case 2:
					desc_ptr = product_string;
					desc_len = sizeof(product_string);
					
					break;
				case 3:
					desc_ptr = serial_string;
					desc_len = sizeof(serial_string);

				default:
					break;
			}
			break;
#ifdef CONFIG_USB_OTG
		case PDC_OTG_DESC_TYPE:
			desc_ptr = &conf_desc[PDC_CONFIG_DESC_LEN+PDC_INTF_DESC_LEN+2*PDC_EP_DESC_LEN];
			desc_len = desc_ptr[0];

			break;
#endif /* CONFIG_USB_OTG */

		default:
			break;
	}
	
	if(desc_ptr) {
		/* Get max length that remote end wants */
		req_len =command[6]|(command[7]<<8);
		if (desc_len > req_len ) {
			desc_len = req_len ;    
		}
	
		pdc_nofif_write_control_pipe(desc_ptr, desc_len);
	} else {
		pdc_bus_stall_control_pipe();
	}

	return;
} /* End of pdc_bus_get_descriptor() */



int	pdc_nofif_write_control_pipe(__u8	*buff, __u16	len)
{
	struct pdc_urb	*urb  = &bus_dev->ctrl_write_urb;

	if(!buff) len = 0;

	/* Fill the URB and submit it */
	pdc_fill_non_iso_urb(urb, bus_dev->ctrl_pipe, PDC_PIPE_CONTROL, 
						PDC_OPR_WRITE, buff, len, NULL,NULL);
	return pdc_submit_urb(urb);
} /* End of pdc_nofif_write_control_pipe() */

void pdc_bus_stall_control_pipe(void)
{
	
	/* Stall Control Out Pipe */
	ctrl_pipe_opr.handle = bus_dev->ctrl_pipe;
	ctrl_pipe_opr.context = (unsigned long) bus_dev;
	ctrl_pipe_opr.opr = PDC_PIPE_STALL;
	pdc_pipe_operation(&ctrl_pipe_opr);

} /* End of pdc_bus_stall_control_pipe() */


int pdc_bus_ctrl_pipe_notificaion(unsigned long notif_type, void *priv,unsigned char	*cmd)
{
	__u8	RequestType;
	__u8	bmRequest ;
	int		result = -1;
	__u8	reply[2];
	struct list_head *tmp;
	__u8	address;



	if(notif_type == PDC_SETUP_COMMAND) {
		/* SETUP Command from the control pipe */
		RequestType = cmd[0] & 0x60;
		
		switch(RequestType) {

			case STANDARD_REQUEST:

				/* Process USB Standrad request */
   				bmRequest = cmd[1];

				switch (bmRequest) {

					case GET_DESCRIPTOR:

						pdc_bus_get_descriptor(cmd);
						break;

					case CLEAR_FEATURE:
					case SET_FEATURE:
						pdc_bus_usb_feature(cmd);
						break;

					case SET_ADDRESS:

						/* 
						 * Set the address in the device controller
						 * and send the status back to the Host
						 */
						if((bus_dev->state != PDC_BUS_DEFAULT && bus_dev->state != PDC_BUS_ADDRESSED) || (cmd[0]&PDC_REQTYPE_DIR_MASK)) {
							pdc_bus_stall_control_pipe();
						} else {

							address = (cmd[2]&0x7F);

							pdc_set_device_address((unsigned long)bus_dev->pdc_config,address);

							pdc_nofif_write_control_pipe(NULL, 0);
			
							if(address)	bus_dev->state = PDC_BUS_ADDRESSED;
							else bus_dev->state = PDC_BUS_DEFAULT;
						}

						break;

					case SET_CONFIGURATION:

						pdc_bus_set_configuration(cmd);

						break;

					case SET_INTERFACE:
	
						pdc_bus_set_interface(cmd);

						break;

					case GET_CONFIGURATION:
	
						/* 
						 * Send the current configuration, the status stage is taken care
						 * by the device controller
						 */
						if((bus_dev->state >= PDC_BUS_DEFAULT) && (cmd[0]&PDC_REQTYPE_DIR_MASK)) {
							reply[0] = bus_dev->configuration;
							pdc_nofif_write_control_pipe(reply, 1);
						} else {
							pdc_bus_stall_control_pipe();
						}

						break;

					case GET_INTERFACE:
	
						/* 
						 * Send the current configuration, the status stage is taken care
						 * by the device controller
						 */
						if((bus_dev->state >= PDC_BUS_CONFIGURED) && (cmd[0]&PDC_REQTYPE_DIR_MASK)) {
							reply[0] = bus_dev->interface;
							pdc_nofif_write_control_pipe(reply, 1);
						} else {
							/* You are not supposed to receive this in these states */
							pdc_bus_stall_control_pipe();
						}

						break;

					case GET_STATUS:
			
						pdc_bus_get_status(cmd);

						break;

					default:

						/* SET_DESCRIPTOR, SYNCH_FRAME TODO */
						/* Other requests are not known to us */
						pdc_bus_stall_control_pipe();
						break;
				}


				break;

			case CLASS_REQUEST:
			case VENDOR_REQUEST:

				/* Process Class Vendor request */

				/* Find the class driver that supports this request */
				tmp = pdc_class_drv_list.next;
				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->class_vendor) {
						/* Currently done for only one class driver */
						result = cd->class_vendor(cd->priv_data, cmd);
						break;
					}
				}

				if(result == 0){
					pdc_nofif_write_control_pipe(NULL, 0);
				}
	
				if(result < 0){
					/* Stall control in and out pipes */
					pdc_bus_stall_control_pipe();
				}

				break;


			default:

				/* All other requests need to be stalled */
				pdc_bus_stall_control_pipe();

				break;
		}
			
	}

	return 0;
} /* End of pdc_bus_ctrl_pipe_notifacaion() */


/*-----------------------------------------------------------------*
 *                     External OTG interface functions            *
 *-----------------------------------------------------------------*/

#ifdef CONFIG_USB_OTG
int		pdc_otg_register(pdc_otg_data_t	*otg_data)
{
	
	if( bus_dev && otg_data ) {
		otg_data->dc_priv_data = (void*)bus_dev;
		bus_dev->otg = otg_data;
		isp1362_printk(KERN_INFO __FILE__ ": Registered Driver usb-otg\n");
		return 0;
	}
	return -1;
}

void	pdc_otg_unregister(pdc_otg_data_t	*otg_data) 
{

	if(bus_dev && otg_data) {
		otg_data->dc_priv_data = NULL;
		bus_dev->otg = NULL;
		isp1362_printk(KERN_INFO __FILE__ ": De-registered Driver usb-otg\n");
	}
}

void    pdc_otg_control(void *priv, unsigned long opr)
{
	struct list_head *tmp;

	pdc_dev_control(opr);

	switch(opr) {
		case PDC_ENABLE:
		bus_dev->state = PDC_BUS_ATTACHED;
		break;

		case PDC_DISABLE:
			bus_dev->state = PDC_BUS_INIT;

			if(bus_dev->configuration) {
				bus_dev->configuration = 0;
				/* Find the class driver that supports this request */
				tmp = pdc_class_drv_list.next;
				while (tmp != &pdc_class_drv_list) {
					struct pdc_class_drv *cd = list_entry(tmp,struct pdc_class_drv, driver_list);

					/* Currently done for only one class driver */
					if(cd->set_config)	cd->set_config(cd->priv_data,bus_dev->configuration);
					tmp = tmp->next;
				}
			}
			break;
	}

}

#endif /* CONFIG_USB_OTG */

⌨️ 快捷键说明

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