📄 pdc_bus.c
字号:
/************************************************************* * 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 + -