cy7c67200_300_pcd.c
来自「linux嵌入式课程实践中的一个关于声卡驱动程序 。」· C语言 代码 · 共 2,215 行 · 第 1/5 页
C
2,215 行
{ pcd_dbg("srp successful, R0:0x%04x", value); } else { pcd_dbg("srp ERROR, R0:0x%04x", value); } otg->b_srp_done = TRUE; update_otg_state(otg);}#endifint pcd_signal_srp(size_t vbus_pulse_time, cy_priv_t *cy_priv){#if 0 lcd_int_data_t int_data; pcd_dbg("Entering pcd_signal_srp"); int_data.int_num = 84; int_data.reg[0] = 20; // 20ms pulse on VBUS int_data.reg[1] = 0; // 0=full_speed, ~0=low_speed lcd_exec_interrupt(&int_data, signal_srp_done, 0, cy_priv); return SUCCESS;#else unsigned short reg_val; /* Check SE0 state for 2ms */ lcd_read_reg(USB1_CTL_REG, ®_val, cy_priv); if( reg_val & (A_DP_STAT | A_DM_STAT) ) { cy_err("Not SE0 state"); /* Not SE0 state */ return ERROR; } mdelay(2); lcd_read_reg(USB1_CTL_REG, ®_val, cy_priv); if( reg_val & (A_DP_STAT | A_DM_STAT) ) { cy_err("Not SE0 state"); /* Not SE0 state */ return ERROR; } /* check session ended */ lcd_read_reg(OTG_CTL_REG, ®_val, cy_priv); if( reg_val & VBUS_VALID_FLG ) { cy_err("VBUS high 1"); /* A-Device still driving VBUS.*/ return ERROR; } else { /* Pulse VBUS discharge resistor */ lcd_read_reg(OTG_CTL_REG, ®_val, cy_priv); lcd_write_reg(OTG_CTL_REG, reg_val | VBUS_DISCH_EN, cy_priv); mdelay(30); lcd_read_reg(OTG_CTL_REG, ®_val, cy_priv); lcd_write_reg(OTG_CTL_REG, reg_val & ~VBUS_DISCH_EN, cy_priv); lcd_read_reg(OTG_CTL_REG, ®_val, cy_priv); if( reg_val & OTG_DATA_STAT ) { cy_err("VBUS high 2"); /* Error: The USB host may be driving the VBUS */ return ERROR; } /* Pulse D+ data line */ //pcd_dbg("START D+ PULLUP"); lcd_read_reg(OTG_CTL_REG, ®_val, cy_priv); reg_val |= DPLUS_PULLUP_EN; lcd_write_reg(OTG_CTL_REG, reg_val, cy_priv); mdelay(8); lcd_read_reg(OTG_CTL_REG, ®_val, cy_priv); reg_val &= ~DPLUS_PULLUP_EN; lcd_write_reg(OTG_CTL_REG, reg_val, cy_priv); //pcd_dbg("END D+ PULLUP"); lcd_read_reg(OTG_CTL_REG, ®_val, cy_priv); if( reg_val & VBUS_VALID_FLG ) { pcd_dbg("VBUS high 3"); /* A-Device has raised VBUS */ return SUCCESS; } /* Pulse VBUS */ //pcd_dbg("START VBUS PULLUP"); lcd_read_reg(OTG_CTL_REG, ®_val, cy_priv); lcd_write_reg(OTG_CTL_REG, reg_val | 0x2000, cy_priv); mdelay(vbus_pulse_time); lcd_read_reg(OTG_CTL_REG, ®_val, cy_priv); lcd_write_reg(OTG_CTL_REG, reg_val & ~0x2000, cy_priv); //pcd_dbg("END VBUS PULLUP"); /* Discharge VBUS again to prevent false transitions to b_peripheral */ lcd_read_reg(OTG_CTL_REG, ®_val, cy_priv); lcd_write_reg(OTG_CTL_REG, reg_val | VBUS_DISCH_EN, cy_priv); mdelay(30); lcd_read_reg(OTG_CTL_REG, ®_val, cy_priv); lcd_write_reg(OTG_CTL_REG, reg_val & ~VBUS_DISCH_EN, cy_priv); } /* if( cy_priv->otg != NULL ) { ((otg_t *)cy_priv->otg)->b_srp_done = TRUE; } */ return SUCCESS;#endif}/****************************************************************************** PARAMETERS: sie_num -> which SIE on Lyberty the configuration belongs. cy_priv -> private data DESCRIPTION: This function will obtain descriptors from the function drivers attached above it, and will then load them to the Lyberty hardware. Currently, the BIOS does not allow us to load an alternative configuration. Therefore, if the host cannot support the initial configuration that we load to Lyberty, then we do not have a way of loading an alternative configuration. A device will contain a single device descriptor. A device may have multiple configurations. Device, configuration, interface, and endpoint descriptors are written to Lyberty RAM during initialization. The BIOS then will handle any standard requests made by a host to the control endpoint. Initially, we will write the base configuration to Lyberty. There is still a question as to how we would handle multiple configurations. Currently, we write the location of the device and configuration descriptor to a SW interrupt. If a host then attempts to enumerate the device and then cancels due to not having bandwidth or power available, the host normally would attempt another configuration if available. It would be necessary then to be able to detect that we failed to enumerate, and to write a different configuration descriptor address to the SW interrupt. RETURNS: SUCCESS or ERROR */int load_configuration_data(cy_priv_t * cy_priv){ int port = 0; int bNumConfigurations; int bNumInterfaces; int bLength = 0; unsigned short wTotalLength = 0; unsigned short length_remaining = 0; char * descriptor_buffer; char * buffer_position; size_t index = 0; struct usb_string_descriptor *string; unsigned short string_loc; struct usb_device_instance * dev; int class; int bNumEndpoint; struct usb_device_descriptor * device_descriptor; struct usb_configuration_descriptor * configuration_descriptor; struct usb_interface_descriptor * interface_descriptor; struct usb_alternate_instance * alternate_instance; struct usb_otg_descriptor * otg_descriptor; pcd_dbg("load_configuration_data enter"); HWTrace(0x7b7b); dev = sie->bus->device; /* load the descriptors to the ASIC to handle enumeration. load the device descriptor */ if(!(device_descriptor = usbd_device_device_descriptor(dev, port))) { cy_err("usbd_device_device_descriptor() failed, dev:%p, port:%d", dev, port); return(ERROR); } if(lcd_write_memory(sie->sie_dev_desc_location, sizeof(*device_descriptor), (char *)device_descriptor, cy_priv) == ERROR) { cy_err("lcd_write_memory() failed"); return(ERROR); } /* write the vector address to the software interrupt. */ if(lcd_write_reg(sie->susb_dev_desc_vec, sie->sie_dev_desc_location, cy_priv) == ERROR) { cy_err("lcd_write_reg() failed"); return(ERROR); } /* create a buffer and write all descriptor information to the buffer. */ descriptor_buffer = (char *)kmalloc(DESCRIPTOR_BUFFER_SIZE, GFP_ATOMIC); /* determine the number of configurations. */ for(bNumConfigurations = 0; bNumConfigurations < device_descriptor->bNumConfigurations; bNumConfigurations++) { configuration_descriptor = usbd_device_configuration_descriptor( dev, port, bNumConfigurations); /* get config descriptor length */ bLength = configuration_descriptor->bLength; /* get the total length of all descriptors for this configuration */ wTotalLength = configuration_descriptor->wTotalLength; length_remaining = wTotalLength - bLength; memcpy(descriptor_buffer, configuration_descriptor, bLength); buffer_position = descriptor_buffer + bLength; /* iterate across interfaces for specified configuration */ for(bNumInterfaces = 0; bNumInterfaces < configuration_descriptor->bNumInterfaces ; bNumInterfaces++) { int bAlternateSetting; struct usb_interface_instance * interface_instance; if(!(interface_instance = usbd_device_interface_instance(dev, port, 0, bNumInterfaces))) { cy_err("usbd_device_interface_instance() failed"); return(ERROR); } /* iterate across interface alternates */ for(bAlternateSetting = 0; bAlternateSetting < interface_instance->alternates; bAlternateSetting++) { if (!(alternate_instance = usbd_device_alternate_instance( dev, port, 0, bNumInterfaces, bAlternateSetting))) { cy_err("usbd_device_alternate_instance() failed"); return(ERROR); } length_remaining = length_remaining - alternate_instance->interface_descriptor->bLength; /* copy interface descriptor to buffer */ memcpy(buffer_position, alternate_instance->interface_descriptor, alternate_instance->interface_descriptor->bLength); buffer_position = buffer_position + alternate_instance-> interface_descriptor-> bLength; /* iterate across classes for this alternate interface */ for (class = 0; class < alternate_instance->classes ; class++) { struct usb_class_descriptor * class_descriptor; if (!(class_descriptor = usbd_device_class_descriptor_index(dev, port, 0, bNumInterfaces, bAlternateSetting, class))) { cy_err("usbd_device_class_descriptor_index() failed"); return(ERROR); } length_remaining = length_remaining - class_descriptor->descriptor.generic.bFunctionLength; /* copy descriptor for this class */ memcpy(buffer_position, class_descriptor, class_descriptor->descriptor.generic.bFunctionLength); buffer_position = buffer_position + class_descriptor->descriptor.generic.bFunctionLength; } /* iterate across endpoints for this alternate interface */ interface_descriptor = alternate_instance->interface_descriptor; for (bNumEndpoint = 0; bNumEndpoint < alternate_instance->endpoints; bNumEndpoint++) { struct usb_endpoint_descriptor * endpoint_descriptor; if (!(endpoint_descriptor = usbd_device_endpoint_descriptor_index(dev, port, 0, bNumInterfaces, bAlternateSetting, bNumEndpoint))) { cy_err("usbd_device_endpoint_descriptor_index()" " failed"); return(ERROR); } length_remaining = length_remaining - endpoint_descriptor->bLength; /* copy descriptor for this endpoint */ memcpy(buffer_position, endpoint_descriptor, endpoint_descriptor->bLength); buffer_position = buffer_position + endpoint_descriptor->bLength; } /* get the otg descriptor if it is available, the * length_remaining if the otg_descriptor is present should * be three, otherwise the otg_descriptor will not be present * for this function */ if(alternate_instance->otg_descriptor != NULL) { otg_descriptor = usbd_device_otg_descriptor(dev, port, bNumConfigurations, bNumInterfaces, bAlternateSetting); memcpy(buffer_position, otg_descriptor, otg_descriptor->bLength); buffer_position = buffer_position + otg_descriptor->bLength; } } } } /* write the config descriptor to Lyberty */ if (lcd_write_memory(sie->sie_config_desc_location, wTotalLength, descriptor_buffer, cy_priv) == ERROR) { kfree(descriptor_buffer); cy_err("lcd_write_memory() failed for config descriptors"); return(ERROR); } /* write the config descriptor address to the software interrupt. */ if (lcd_write_reg(sie->susb_config_desc_vec, sie->sie_config_desc_location, cy_priv) == ERROR) { kfree(descriptor_buffer); cy_err("lcd_write_reg() failed"); return(ERROR); } /* Enable HNP FIXME */ if (lcd_write_reg(0xb0, 3, cy_priv) == ERROR) { kfree(descriptor_buffer); cy_err("lcd_write_reg() failed"); return(ERROR); } /* write string descriptors to Lyberty */ string_loc = sie->sie_string_desc_location; while( (string = usbd_get_string(index++)) != NULL ) { if (lcd_write_memory(string_loc, string->bLength, (char*)string, cy_priv) == ERROR) { kfree(descriptor_buffer); cy_err("lcd_write_memory() failed for string descriptors"); return(ERROR); } string_loc += string->bLength; } pcd_dbg("Device descriptor address: 0x%04x", sie->sie_dev_desc_location); pcd_dbg("Config descriptor address: 0x%04x", sie->sie_config_desc_location); pcd_dbg("String descriptor address: 0x%04x", sie->sie_string_desc_location); /* write the string descriptor address to the software interrupt. */ if (lcd_write_reg(sie->susb_string_desc_vec, sie->sie_string_desc_location, cy_priv) == ERROR) { kfree(descriptor_buffer); cy_err("lcd_write_reg() failed for string descriptors"); return(ERROR); } kfree(descriptor_buffer); return(SUCCESS);}/***************************************************************** * * Function Name: Various * * This is a collection of handlers called at interrupt context * from the main interrupt handler defined in lcd. * * Input: cy_priv - Private data structure maintaining certain * state for hcd, pcd, lcd, otg. * * Return: none * *****************************************************************/#if 0int is_host_mode(cy_priv_t * cy_priv, int sie_num){ if (cy_priv->system_mode[sie_num] == HOST_ROLE) return (TRUE); else return (FALSE);}#endif/*****************************************************************/void pcd_irq_sofeop1(cy_priv_t *cy_priv){#if 0 sie_info *sie_var = (sie_info *)cy_priv->pcdi; unsigned short reg_value; otg_t * otg = cy_priv->otg;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?