📄 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 * *******************************************************/ #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;/*-------------------------------------------------------------------------* * 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_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) { __u32 data; 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); phci_otg_port_control(dev->fsm_data.hcd_priv, OTG_PORT_GET_ENUM, &data); if(tcb->id == 0) { /* A device, results of HNP protocol */ tcb->a_set_b_hnp_en = (data & USB_OTG_HNP_ENABLED) ? 1 : 0; tcb->b_hnp_support = (data & USB_OTG_HNP_ENABLED) ? 1 : 0; tcb->b_srp_support = (data & USB_OTG_HNP_ENABLED) ? 1 : 0; if(tcb->a_set_b_hnp_en == 1) { /* If HNP is enabled on B device, allow it to become Host * when necessary */ tcb->AllowStateChange = 1; } } if(tcb->bus_req == 1) { /* There is a request for the Device to get enumerated * Now copy the results to the status */ if((data & USB_OTG_DEV_ENUMERATED)) { dev->status.status_code = OTG_STATUS_ENUM_SUCCESS; } else { printk("Enumeration failed\n"); dev->status.status_code = OTG_STATUS_ENUM_FAILED; } usb_otgdev_async_notif(dev); } otgfsm_run(&(dev->fsm_data));}/*-------------------------------------------------------------------------* * process Host Controller ISR on behalf of OTG FSM * ------------------------------------------------------------------------*/void usb_otg_isr(struct isp1362_dev *dev, void *isr_data) { otg_fsm_t *fsm_data = &(((usb_otgdev_t*)isr_data)->fsm_data); func_debug(("usb_otg_isr(dev=%p,isr_data=%p)\n",dev,isr_data)) fsm_data->regs.int_port.data = dev->int_reg; otgfsm_run(fsm_data);}/*-------------------------------------------------------------------------* * OTG virtual device file related functions * ------------------------------------------------------------------------*//* Device file operations */static struct file_operations usb_otgdev_fops = { owner: THIS_MODULE, read: NULL, write: NULL, poll: NULL, ioctl: usb_otgdev_ioctl, open: usb_otgdev_open, release: usb_otgdev_close, fasync: usb_otgdev_fasync,};int usb_otgdev_open( struct inode *inode, struct file *fp) { func_debug(("usb_otgdev_open(inode=%p,fp=%p)\n",inode,fp)) fp->private_data = usb_otgdev; /* set the OTG controller data in file */ MOD_INC_USE_COUNT; /* Increment the module count */ return 0;}int usb_otgdev_close( struct inode *inode, struct file *fp) { func_debug(("usb_otgdev_close(inode=%p,fp=%p)\n",inode,fp)) MOD_DEC_USE_COUNT; /* Decrement module count */ usb_otgdev_fasync(-1,fp, 0); /* cancel asynchronous notification to application */ return 0;}int usb_otgdev_fasync( int fd, struct file *fp, int mode) { usb_otgdev_t *otgdev = (usb_otgdev_t*)fp->private_data; func_debug(("usb_otgdev_fasync(fd=%d,fp=%p,mode=%d)\n",fd,fp,mode)) return fasync_helper(fd, fp, mode, &otgdev->fasync_q);}int usb_otgdev_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, unsigned long arg) { func_debug(("usb_otgdev_ioctl(inode=%p,fp=%p,cmd=%d,arg=%x)\n",inode,fp,cmd,arg)) usb_otgdev_t *otgdev = (usb_otgdev_t*)fp->private_data; int ret = 0; switch(cmd) { case OTG_IOC_GET_STATE: /* Get OTG sw FSM State */ /* Copy the status information from driver to user space */ otgdev->status.id = otgdev->fsm_data.tcb.id; otgdev->status.state = otgdev->fsm_data.tcb.app_state; if(otgdev->status.status_code == OTG_STATUS_NONE) { otgdev->status.status_code = otgdev->fsm_data.tcb.err_code; } copy_to_user((usb_otg_info_t *)arg, &otgdev->status, sizeof(usb_otg_info_t)); break; case OTG_IOC_SET_STATE: /* Set OTG sw FSM State */ copy_from_user(&otgdev->status, (usb_otg_info_t *)arg, sizeof(usb_otg_info_t)); otgdev->status.status_code = OTG_STATUS_NONE; otgfsm_set_state(&(otgdev->fsm_data), otgdev->status.state); // otgfsm_run(&(otgdev->fsm_data)); break; } return ret;}/*------------------------------------------------------------------------- * * -----------------------------------------------------------------------*/void usb_otgdev_async_notif(usb_otgdev_t *otgdev){ func_debug(("usb_otgdev_async_notif(otgdev=%p)\n",otgdev)) if(otgdev->fasync_q) { kill_fasync( &otgdev->fasync_q, SIGIO, POLL_IN); }}static int usb_otg_probe (struct isp1362_dev *dev);static void usb_otg_remove (struct isp1362_dev *dev);struct isp1362_driver usb_otg_driver = { name: "usb-otg", index: ISP1362_OTG, probe: usb_otg_probe, remove: usb_otg_remove,};/*------------------------------------------------------------------------- * OTG module init function * -----------------------------------------------------------------------*/static int usb_otg_probe (struct isp1362_dev *dev) { int result = 0; func_debug(("usb_otg_probe(dev=%p)\n",dev)) result = isp1362_check_io_region(dev); if(result < 0) { detail_debug(("%s: IO resources are busy\n",usb_otg_driver.name)) return result; } isp1362_request_io_region(dev); usb_otgdev = kmalloc(sizeof(usb_otgdev_t), GFP_KERNEL); if(usb_otgdev) { memset(usb_otgdev, 0, sizeof(usb_otgdev_t)); dev->driver_data = usb_otgdev; usb_otgdev->fsm_data.dev = dev; /* Initialize the OTG FSM state to invalid state */ otgfsm_init(&(usb_otgdev->fsm_data)); hc_otg_data.priv_data = (void*)usb_otgdev; hc_otg_data.otg_notif = otgfsm_usb_notif; dc_otg_data.priv_data = (void*)usb_otgdev; dc_otg_data.otg_notif = otgfsm_pdc_notif; result = pdc_otg_register(&dc_otg_data); result = phci_register_otg(&hc_otg_data); if(result == 0) { usb_otgdev->fsm_data.hcd_priv = hc_otg_data.hc_priv_data; usb_otgdev->fsm_data.usb_otg_data = usb_otgdev; otgfsm_status_probe(&(usb_otgdev->fsm_data)); /* Register the OTG driver to device file system so appliation * can access this driver */ result = devfs_register_chrdev(USB_OTG_MAJOR, USB_OTG_MODULE_NAME, &usb_otgdev_fops); if(result == 0) { result=isp1362_request_irq(usb_otg_isr,dev,usb_otgdev); if(result == 0) { info(DRIVER_DESC " Ver" USB_OTG_VERSION " Initialization Successful\n"); return result; } devfs_unregister_chrdev(USB_OTG_MAJOR,USB_OTG_MODULE_NAME); } pdc_otg_unregister(&dc_otg_data); dc_otg_data.priv_data = NULL; hc_otg_data.priv_data = NULL; kfree(usb_otgdev); } usb_otgdev->fsm_data.dev = NULL; } result = -ENOMEM; isp1362_release_io_region(dev); dev->driver_data = NULL; info(DRIVER_DESC " Ver" USB_OTG_VERSION " Initialization Falied\n"); return result;} /* End of usb_otg_probe *//*------------------------------------------------------------------------- * OTG module clean up function * -----------------------------------------------------------------------*/static void usb_otg_remove (struct isp1362_dev *dev) { func_debug(("usb_otg_remove(dev=%p)\n",dev)) otgfsm_deinit(&(usb_otgdev->fsm_data)); isp1362_free_irq(dev, dev->driver_data); /* De register from the device file system */ devfs_unregister_chrdev(USB_OTG_MAJOR,USB_OTG_MODULE_NAME); phci_unregister_otg(&hc_otg_data); hc_otg_data.priv_data = NULL; pdc_otg_unregister(&dc_otg_data); dc_otg_data.priv_data = NULL; kfree(dev->driver_data); dev->driver_data = NULL; isp1362_release_io_region(dev);} /* End of usb_otg_remove */static int __init usb_otg_module_init (void) { func_debug(("usb_otg_module_init(void)\n")) return isp1362_register_driver(&usb_otg_driver);}static void __exit usb_otg_module_cleanup (void) { func_debug(("usb_otg_module_cleanup(void)\n")) return isp1362_unregister_driver(&usb_otg_driver);}module_init (usb_otg_module_init);module_exit (usb_otg_module_cleanup);MODULE_AUTHOR (DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -