📄 usb_otg.c
字号:
/*******************************************************
* Philips OTG (On The Go) Driver for USB.
*
* (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: usb_otg.c
*
* History:
*
* Version Date Author Comments
* -------------------------------------------------
* 1.0 09/23/02 SYARRA Initial Creation
* 1.10 04/10/03 SYARRA OTG1.0A changes
* 1.21 08/04/03 SYARRA OPT1.2 compliance
*******************************************************/
#include <linux/config.h>
#define MODULE
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/interrupt.h> /* for in_interrupt() */
#undef DEBUG
#include <linux/usb.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/unaligned.h>
#include <asm/uaccess.h>
#include "linux/usb.h"
#include "pdc_intf.h"
#include "usb_phci.h"
#include "usb_otg.h"
/* Internal functional declerations */
int usb_otgdev_open( struct inode *inode, struct file *fp);
int usb_otgdev_close( struct inode *inode, struct file *fp);
int usb_otgdev_fasync( int fd, struct file *fp, int mode);
int usb_otgdev_ioctl(struct inode *inode, struct file *fp,
unsigned int cmd, unsigned long arg);
//void usb_otgdev_async_notif(usb_otgdev_t *otgdev);
usb_otgdev_t *usb_otgdev;
phci_otg_data_t hc_otg_data;
pdc_otg_data_t dc_otg_data;
/*-------------------------------------------------------------------------*
* USB CORE stuff (related to OTG)
* These functions execute under the context of HUB enumeration
* OTG1.0A changes: moved some stuff from usbcore to here. Added unsupported device
* support
* ------------------------------------------------------------------------*/
static int usb_otg_new_device(void *priv, struct usb_device *dev);
struct usb_device_id otg_target_peripheral[] = isp1362_targeted_peripheral;
int usb_otg_is_targeted_peripheral(struct usb_device *dev) {
int matched = 0;
if(dev->descriptor.idVendor == USB_OTG_UNSUP_VEND_ID) return matched;
#if 0
for(i = 0; i<count; i++) {
switch(otg_target_peripheral[i].match_flags) {
case USB_DEVICE_ID_MATCH_DEVICE:
if((dev->descriptor.idVendor == otg_target_peripheral[i].idVendor) &&
(dev->descriptor.idProduct == otg_target_peripheral[i].idProduct)) {
matched = 1;
}
break;
}
}
#else
matched = 1;
#endif
return matched;
}
int usb_otg_new_device(void *priv, struct usb_device *dev) {
char *buffer = dev->rawdescriptors[0];
struct usb_descriptor_header *header;
struct usb_otg_descriptor *otg_desc;
int size;
usb_otgdev_t *otg_dev = (usb_otgdev_t*)priv;
otg_tcb_t *tcb = &(otg_dev->fsm_data.tcb);
int result = 0, supported = 0;
__u8 feature;
supported = usb_otg_is_targeted_peripheral(dev);
if(!supported) {
isp1362_kernel_user_mesg("Connected device is not supported");
}
/* Set OTG enable for the root hub port OTG devices */
if((dev->parent) && (dev->parent == dev->bus->root_hub)) {
/* If OTG capable, OTG descriptor is present in all configurations
* So let us dig first configuration */
if(buffer && (tcb->id == 0)) {
/* This has already been parsed by the get_configuration fn */
size = dev->config[0].wTotalLength;
while (size >= sizeof(struct usb_descriptor_header)) {
header = (struct usb_descriptor_header *)buffer;
/* Check for OTG descriptor presence */
if (header->bDescriptorType == USB_DT_OTG) {
otg_desc = (struct usb_otg_descriptor *)buffer;
if(otg_desc->bLength == USB_DT_OTG_SIZE) {
/* Copy OTG attributes */
tcb->b_hnp_support = (otg_desc->bmAttributes & USB_OTG_HNP_SUPPORT) ? 1 : 0;
tcb->b_srp_support = (otg_desc->bmAttributes & USB_OTG_SRP_SUPPORT) ? 1 : 0;
if(tcb->b_hnp_support == 1) {
/* OTG feature is available on other port, this is normal USB port */
if(dev->parent->children[OTG_HC_PORT_NO] == dev) {
/* This port supports OTG */
feature = USB_OTG_FS_HNP_ENABLE;
result = otg_hub_set_otg_feature(dev, feature);
if(result >= 0) {
tcb->a_set_b_hnp_en = 1;
tcb->AllowStateChange = 1;
} else {
isp1362_kernel_user_mesg("Connected device is not supported");
tcb->a_set_b_hnp_en = 0;
tcb->AllowStateChange = 0;
result = -1;
}
} else {
/* OTG support is on the other port */
feature = USB_OTG_FS_ALT_HNP_SUPPORT;
otg_hub_set_otg_feature(dev, feature);
}
}
} else {
/* Problem in OTG descriptor */
/* Fail enumeration */
result = -1;
}
break;
}
buffer += header->bLength;
size -= header->bLength;
}
/* If there is no bus request on the OTG port, this must be due to an SRP, so no need to
* enumerate further. So fail the enumeration */
if((dev->parent->children[OTG_HC_PORT_NO] == dev) && (tcb->bus_req == 0)) {
if(header->bDescriptorType != USB_DT_OTG) {
/* B device is SRP capable but doesn't give any OTG descriptor ??? Inform the User */
isp1362_kernel_user_mesg("Connected device is not supported");
}
result = -1;
}
}
}
/* If not a supported device & not a root hub fail it */
if((dev->parent) && (!supported)) return -1;
return result;
}
/*-------------------------------------------------------------------------*
* OTG FSM related functions
* ------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*
* process Device Controller Notification on behalf of OTG FSM
* ------------------------------------------------------------------------*/
void otgfsm_pdc_notif(void *priv, unsigned long notif, unsigned long data) {
usb_otgdev_t *dev = (usb_otgdev_t*)priv;
otg_tcb_t *tcb = &(dev->fsm_data.tcb);
func_debug(("otgfsm_pdc_notif(priv=%p,notif=%d,data=%x)\n",priv,notif,data))
switch(notif) {
case PDC_BUSTATUS:
/*Just update the variables of suspend */
/* If you run the FSM it might cause looping
* otg->dev->otg->dev........ */
if(tcb->id == 0) {
tcb->b_bus_suspend = 1;
} else if(tcb->id == 1){
tcb->a_bus_suspend = 1;
}
return;
break;
case PDC_SUSPEND:
if(tcb->id == 0) {
tcb->b_bus_suspend = 1;
} else if(tcb->id == 1){
tcb->a_bus_suspend = 1;
}
break;
case PDC_RESET:
tcb->b_hnp_en = 0;
tcb->a_hnp_support = 0;
tcb->a_alt_hnp_support = 0;
case PDC_RESUME:
if(tcb->id == 0) {
tcb->b_bus_suspend = 0;
} else if(tcb->id == 1){
tcb->a_bus_suspend = 0;
}
break;
case PDC_SET_HNP:
if(data == USB_OTG_FS_HNP_ENABLE) {
tcb->b_hnp_en = 1;
} else if ( data == USB_OTG_FS_HNP_SUPPORT) {
tcb->a_hnp_support = 1;
} else if ( data == USB_OTG_FS_ALT_HNP_SUPPORT) {
tcb->a_alt_hnp_support = 1;
}
break;
}
otgfsm_run(&(dev->fsm_data));
}
/*-------------------------------------------------------------------------*
* process USB core Notification on behalf of OTG FSM
* ------------------------------------------------------------------------*/
void otgfsm_usb_notif(void *priv, int *result)
{
func_debug(("otgfsm_usb_notif(priv=%p)\n",priv))
usb_otgdev_t *dev = (usb_otgdev_t*)priv;
otg_tcb_t *tcb = &(dev->fsm_data.tcb);
if(tcb->bus_req == 1) {
/* There is a request for the Device to get enumerated
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -