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

📄 hc_sl811_rh.c

📁 Cy3662在Linux下的驱程开发
💻 C
📖 第 1 页 / 共 2 页
字号:

/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*
 * SL811HS virtual root hub
 *  
 * based on usb-ohci.c by R. Weissgaerber et al.
 *-------------------------------------------------------------------------*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 *-------------------------------------------------------------------------*/

#ifdef DEBUG
#undef DEBUG
#endif
static __u32 getPortStatusAndChange(hci_t *hci);
static void setPortStatus(hci_t *hci, __u16 bitPos);
static void setPortChange(hci_t *hci, __u16 bitPos);
static void clrPortStatus(hci_t *hci, __u16 bitPos);
static void clrPortChange(hci_t *hci, __u16 bitPos);
static int USBReset(hci_t *hci);
static int cc_to_error (int cc);

/*-------------------------------------------------------------------------*
 * Virtual Root Hub 
 *-------------------------------------------------------------------------*/
 
/* Device descriptor */
static __u8 root_hub_dev_des[] =
{
	0x12,       /*  __u8  bLength; */
	0x01,       /*  __u8  bDescriptorType; Device */
	0x10,	    /*  __u16 bcdUSB; v1.1 */
	0x01,
	0x09,	    /*  __u8  bDeviceClass; HUB_CLASSCODE */
	0x00,	    /*  __u8  bDeviceSubClass; */
	0x00,       /*  __u8  bDeviceProtocol; */
	0x08,       /*  __u8  bMaxPacketSize0; 8 Bytes */
	0x00,       /*  __u16 idVendor; */
	0x00,
	0x00,       /*  __u16 idProduct; */
 	0x00,
	0x00,       /*  __u16 bcdDevice; */
 	0x00,
	0x00,       /*  __u8  iManufacturer; */
	0x02,       /*  __u8  iProduct; */
	0x01,       /*  __u8  iSerialNumber; */
	0x01        /*  __u8  bNumConfigurations; */
};


/* Configuration descriptor */
static __u8 root_hub_config_des[] =
{
	0x09,       /*  __u8  bLength; */
	0x02,       /*  __u8  bDescriptorType; Configuration */
	0x19,       /*  __u16 wTotalLength; */
	0x00,
	0x01,       /*  __u8  bNumInterfaces; */
	0x01,       /*  __u8  bConfigurationValue; */
	0x00,       /*  __u8  iConfiguration; */
	0x40,       /*  __u8  bmAttributes; 
                    Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 
                    4..0: resvd */
	0x00,       /*  __u8  MaxPower; */
      
	/* interface */	  
	0x09,       /*  __u8  if_bLength; */
	0x04,       /*  __u8  if_bDescriptorType; Interface */
	0x00,       /*  __u8  if_bInterfaceNumber; */
	0x00,       /*  __u8  if_bAlternateSetting; */
	0x01,       /*  __u8  if_bNumEndpoints; */
	0x09,       /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
	0x00,       /*  __u8  if_bInterfaceSubClass; */
	0x00,       /*  __u8  if_bInterfaceProtocol; */
	0x00,       /*  __u8  if_iInterface; */
     
	/* endpoint */
	0x07,       /*  __u8  ep_bLength; */
	0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
	0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
 	0x03,       /*  __u8  ep_bmAttributes; Interrupt */
 	0x02,       /*  __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
 	0x00,
	0xff        /*  __u8  ep_bInterval; 255 ms */
};

/* Hub class-specific descriptor is constructed dynamically */


/***************************************************************************
 * Function Name : rh_send_irq
 * 
 * This function examine the port change in the virtual root hub.
 * 
 * Note: This function assumes only one port exist in the root hub.
 *
 * Input:  hci = data structure for the host controller
 *         rh_data = The pointer to port change data
 *         rh_len = length of the data in bytes
 *
 * Return: length of data  
 **************************************************************************/

static int rh_send_irq (hci_t * hci, void * rh_data, int rh_len)
{
    int num_ports;
    int i;
    int ret;
    int len;
    __u8 data[8];
		
    DBGFUNC ("enter rh_send_irq: \n");

    /* Assuming the root hub has one port.  This value need to change if
     * there are more than one port for the root hub
     */

    num_ports = 1; 
	
    /* The root hub status is not implemented, it basically has two fields:
     *     -- Local Power Status
     *     -- Over Current Indicator
     *     -- Local Power Change
     *     -- Over Current Indicator
     *
     * Right now, It is assume the power is good and no changes 
     */


    *(__u8 *) data = 0;
	   
    ret = *(__u8 *) data;

    /* Has the port status change within the root hub: It checks for
     *      -- Port Connect Status change
     *      -- Port Enable Change
     */
  
    for ( i = 0; i < num_ports; i++) 
    {
        *(__u8 *) (data + (i + 1) / 8) |= (((getPortStatusAndChange (hci) >> 16)
		    & (PORT_CONNECT_STAT | PORT_ENABLE_STAT)) ? 1: 0) << 
                    ((i + 1) % 8);
	ret += *(__u8 *) (data + (i + 1) / 8);
		
	/* After the port change is read, it should be reset so the next time 
	 * is it doesn't trigger a change again */
		
    }
    len = i/8 + 1;
  
	
    if (ret > 0) 
    { 
	memcpy (rh_data, data, min (len, min (rh_len, sizeof(data))));
	return len;
    }	
    return 0;
}

/***************************************************************************
 * Function Name : rh_int_timer_do
 * 
 * This function is called when the timer expires.  It gets the the port 
 * change data and pass along to the upper protocol.
 * 
 * Note:  The virtual root hub interrupt pipe are polled by the timer
 *        every "interval" ms
 *
 * Input:  ptr = ptr to the urb
 *
 * Return: none  
 **************************************************************************/

static void rh_int_timer_do (unsigned long ptr)
{
    int len; 
    urb_t * urb = (urb_t *) ptr;
    hci_t * hci = urb->dev->bus->hcpriv;

    DBGFUNC ("enter rh_int_timer_do\n");

    if(hci->rh.send) 
    { 
        len = rh_send_irq (hci, urb->transfer_buffer, 
                           urb->transfer_buffer_length);
	if (len > 0)  
        {
	    urb->actual_length = len;
	    if (urb_debug == 2)
	        urb_print (urb, "RET-t(rh)", usb_pipeout (urb->pipe));

	    if (urb->complete)
            {
		urb->complete (urb);
            }
	}
    }

    /* re-activate the timer */
    rh_init_int_timer (urb);
}

/***************************************************************************
 * Function Name : rh_init_int_timer
 * 
 * This function creates a timer that act as interrupt pipe in the
 * virtual hub.   
 * 
 * Note:  The virtual root hub's interrupt pipe are polled by the timer
 *        every "interval" ms
 *
 * Input: urb = USB request block 
 *
 * Return: 0  
 **************************************************************************/

static int rh_init_int_timer (urb_t * urb) 
{
    hci_t * hci = urb->dev->bus->hcpriv;
    hci->rh.interval = urb->interval;

    init_timer (&hci->rh.rh_int_timer);
    hci->rh.rh_int_timer.function = rh_int_timer_do;
    hci->rh.rh_int_timer.data = (unsigned long) urb;
    hci->rh.rh_int_timer.expires = jiffies + 
               (HZ * (urb->interval < 30? 30: urb->interval)) / 1000;
    add_timer (&hci->rh.rh_int_timer);
	
    return 0;
}

/*-------------------------------------------------------------------------*/

/* helper macro */
#define OK(x) 			len = (x); break

/***************************************************************************
 * Function Name : rh_submit_urb
 * 
 * This function handles all USB request to the the virtual root hub
 * 
 * Input: urb = USB request block 
 *
 * Return: 0  
 **************************************************************************/

static int rh_submit_urb (urb_t * urb)
{
    struct usb_device * usb_dev = urb->dev;
    hci_t * hci = usb_dev->bus->hcpriv;
    unsigned int pipe = urb->pipe;
    devrequest * cmd = (devrequest *) urb->setup_packet;
    void * data = urb->transfer_buffer;
    int leni = urb->transfer_buffer_length;
    int len = 0;
    int status = TD_CC_NOERROR;
    __u32 datab[4];
    __u8  * data_buf = (__u8 *) datab;
	
    __u16 bmRType_bReq;
    __u16 wValue; 
    __u16 wIndex;
    __u16 wLength;

    DBGFUNC ("enter rh_submit_urb\n");

⌨️ 快捷键说明

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