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

📄 ohci.c

📁 usb host driver OHCI
💻 C
📖 第 1 页 / 共 4 页
字号:
	phED->TailP = 0;	
	//unlock_ohci();
	if ((trans = start_trans(pED)) != 0) {
		ohci_free_td(pTDout);
		phED->TailP   = 0x00000000;
		phED->HeadP   = 0x00000000;
		////unlock_ohci();
		return trans;
	}
#ifdef OHCI_STAT
	ohci_out_packet_count += size;
#endif
	phED->TailP   = 0x00000000;
	phED->HeadP   = 0x00000000;
	ohci_free_td(pTDout);
	////unlock_ohci();
	return 0;
}

/*
 * 
 */
int ohci_bulk_read(PS_UHP_ED pED, void *pIn, unsigned int size, unsigned int tm) {
	PS_UHP_TD pTDin;
	OHCI_PS_UHP_ED phED = pED->phED;
	int trans = 0;
	//lock_ohci();
	
	if (!phED) {
		//unlock_ohci();
		return -1;
	}
	
	// create OUT transaction
	pTDin = ohci_create_td(pED->Trigger, 0, ED_IN, 1, (unsigned int)pIn, size, 0, 0, 0);
	if (!pTDin) {
		//unlock_ohci();
		return -1;
	}
	ohci_add_td(pED, pTDin);
	// create IN transaction
	phED->TailP = 0;
	//unlock_ohci();
	
	if ((trans = start_trans(pED)) != 0) {
		ohci_free_td(pTDin);
		phED->TailP   = 0x00000000;
		phED->HeadP   = 0x00000000;
		////unlock_ohci();
		return trans;
	}
#ifdef OHCI_STAT
	ohci_in_packet_count += size;
#endif	
	phED->TailP   = 0x00000000;
	phED->HeadP   = 0x00000000;
	ohci_free_td(pTDin);
	////unlock_ohci();
	return 0;
}

/*
 * 
 */
int ohci_int_read(PS_UHP_ED pED, void *pIn, unsigned int size, unsigned int tm) {
	PS_UHP_TD pTDin;	
	OHCI_PS_UHP_ED phED = pED->phED;

	//lock_ohci();

	if (!phED) {
		//unlock_ohci();
		return -1;
	}
		
	// create IN transaction
	pTDin = ohci_create_td(pED->Trigger, 0, ED_IN, 1, (unsigned int)pIn, size, 0, 0, 0);
	if (!pTDin) {
		//unlock_ohci();
		return -1;
	}
	ohci_add_td(pED, pTDin);
	phED->TailP = 0;
	//unlock_ohci();
	
	if (start_trans(pED)) {
		ohci_free_td(pTDin);
		phED->TailP   = 0x00000000;
		phED->HeadP   = 0x00000000;
				
		return -1;
	}
	
	phED->TailP   = 0x00000000;
	phED->HeadP   = 0x00000000;
	ohci_free_td(pTDin);
	return 0;
}


/*
 * 
 */
static int start_trans(PS_UHP_ED pED) {
	OHCI_PS_UHP_ED phED;
	OHCI_PS_UHP_TD phTD;
#ifndef OHCI_POLING	
	unsigned char err;
#endif	
	S_TIMEOUT timeout;
	volatile unsigned int *tControl = NULL;
	
	phED = pED->phED;
	phTD = NULL;
	
	if (!phED) return -1;
	
	if (pED->Type == OHCI_INT_ED)		
		InitTimeout(&timeout, 1);
	
	phED->Control &= ~(1 << 14);
	ohci->HcControl |= 0x80; // USB operational
	
	if (phED->TailP > 0) {
		phTD = (OHCI_PS_UHP_TD)phED->TailP;			
	} else {
		phTD = (OHCI_PS_UHP_TD)phED->HeadP;
	}
	tControl = &phTD->Control;
	
	if (pED->Type == ED_TYPE_CONTROL) {			
		ohci->HcCommandStatus |= OHCI_CS_CLF; //CLF
	} else if (pED->Type == ED_TYPE_BULK) {		
		ohci->HcCommandStatus |= OHCI_CS_BLF; //BLF
	} else {
		
	}
	
#ifndef OHCI_POLING		
	// not interrupt or ISO transaction
	if (pED->Type != OHCI_INT_ED) {
		OSSemPend(ohci_sem, 100, &err);
			
		if (err == OS_NO_ERR) {
			
			phED->Control |= (1 << 14); // Set sKip
			
			if ((phED->HeadP & 0x01)!=0) {
				   OHCI_DBG("HALTED: 0x%02X\r\n", (phED->HeadP & 0x03));
				   //print_cc(((*tControl) >> 28) & 0x0F);
				   return -1;
			}
			if ((phED->HeadP & 0xFFFFFFF0) != phED->TailP) {
				OHCI_DBG("HALTED: 0x%02X\r\n", (phED->HeadP & 0x03));
				//print_cc(((*tControl) >> 28) & 0x0F);
				return -1;
			}
	
			if (pED->Type == ED_TYPE_BULK) {
				pED->Trigger = ((((*tControl) >> 24) & 0x00000003) | 0x00000002);
			}
			return 0;		
		} else if (err == OS_TIMEOUT) {
		   phED->Control |= (1 << 14);
		   OHCI_DBG("OHCI TIMEOUT: 0x%02X\r\n", (phED->HeadP & 0x03));
		   if ((phED->HeadP & 0x01)!=0) {
			   OHCI_DBG("HALTED TIMEOUT: 0x%02X\r\n", (phED->HeadP & 0x03));
			   //print_cc(((*tControl) >> 28) & 0x0F);
			   // Clear HALT bit
			   phED->HeadP &= ~(1 << 0);		 
		       return pED->Endpoint;
		   }
			return -1;
		}
	} else {
		// only for interrupt and ISO transactions
		do {
			
		   if (pED->stop_poling) {
			   return -1;
		   }

			// HALTED
		   if ((phED->HeadP & 0x01)!=0) {
			   phED->Control |= (1 << 14);
			   OHCI_DBG("HALTED: 0x%02X\r\n", (phED->HeadP & 0x03));
			   //print_cc(((*tControl) >> 28) & 0x0F);
			   // Clear HALT bit
			   phED->HeadP &= ~(1 << 0);		 
		       return pED->Endpoint;
		   }

		   if ((phED->HeadP & 0xFFFFFFF0) == phED->TailP) {
			   phED->Control |= (1 << 14);
			   
			   if (pED->Type == ED_TYPE_BULK) {
				   pED->Trigger = ((((*tControl) >> 24) & 0x00000003) | 0x00000002); 
			   }
		       return 0;
		   }
		}  while (1);
	}
#else	
	do {
		if (pED->Type != OHCI_INT_ED) {
			if (!TestTimeout(&timeout)) {
				OHCI_DBG("Timeout\r\n");
				print_cc(((*tControl) >> 28) & 0x0F);
				return -1;
			}
		} else {
			if (pED->stop_poling) {
				return -1;
			}
		}
		// HALTED
	   if ((phED->HeadP & 0x01)!=0) {
		   phED->Control |= (1 << 14);
		   OHCI_DBG("HALTED: 0x%02X\r\n", (phED->HeadP & 0x03));
		   print_cc(((*tControl) >> 28) & 0x0F);
		   // Clear HALT bit
		   phED->HeadP &= ~(1 << 0);		 
	       return pED->Endpoint;
	   }

	   if ((phED->HeadP & 0xFFFFFFF0) == phED->TailP) {
		   phED->Control |= (1 << 14);
		   
		   if (pED->Type == ED_TYPE_BULK) {
			   pED->Trigger = ((((*tControl) >> 24) & 0x00000003) | 0x00000002); 
		   }
	       return 0;
	   }
	}  while (1);
#endif	
	
	return -1;
}




unsigned char *pFileBuf;


/*
 * 
 */
static void *ohci_wait_event(OS_EVENT *mbox, unsigned int timeout) {
	unsigned char err;
	void *msg;
	
	if (mbox == NULL) return NULL;
	
	msg = OSMboxPend(mbox, timeout, &err);
	if (err == OS_NO_ERR) {
		return msg;
	} else 
		return NULL;
}

/*
 * 
 */
static void ohci_post_event(OS_EVENT *mbox, unsigned int msg) {
	if (mbox == NULL) return;
	
	OSMboxPost(mbox, (void *)msg);
}

/*
 * 
 */
static int ohci_create_control_ed(USBDevice_t *pD) {
	
	PS_UHP_ED pED;
	OHCI_PS_UHP_ED phED;
	
	pD->dev_eds[OHCI_CONTROL_ED].direction = ED_GEN_FORMAT; //control
	pD->dev_eds[OHCI_CONTROL_ED].type = OHCI_CONTROL_ED;
	
	pED = ohci_create_ed(64,				// Max packet
						ED_GEN_FORMAT,		// TD format
						ED_SKIP,					// Skip
						(pD->speed & 0x80)? ED_LOW_SPEED: ED_FUL_SPEED,		// Speed
						ED_GET_FROM_TD,	// Direction
						OHCI_CONTROL_ED,					// Endpoint number
						0,					// Func Address
						0,					// TDQTailPointer
						0,					// TDQHeadPointer
						0,					// ToggleCarry
						0,					// NextED
						OHCI_CONTROL_ED,
						64);				// Type (Control)
	if (!pED) return -1;
	
	phED = pED->phED;
	if (!phED) return -1;

	
	pD->dev_eds[OHCI_CONTROL_ED].pED = (void *)pED;
	pD->dev_eds[OHCI_CONTROL_ED].max_packet = 64;
	pD->dev_eds[OHCI_CONTROL_ED].present = 1;
	
	ohci_add_ed(pED);
	return 0;
}

/*
 * 
 */
static void ohci_parse_descriptor(USBDevice_t *pD, void *pDin) {
	unsigned char *p;
	unsigned char desc_len, tot_len = 9, desc_type, cur_len = 0, ep_num = 0;
	
#define DESC_DEVICE		1	
#define DESC_CONFIG		2
#define DESC_STRING		3
#define DESC_INTERF		4
#define DESC_EP			5
#define DESC_DQ			6
#define DESC_OSC		7
#define DESC_IP			8
#define DESC_OTG		9
	
	p = pDin;
	
	while (1) {
		desc_len = *p;
		desc_type = *(p + 1);
	
		if (desc_type == DESC_CONFIG) {
			tot_len = *(p + 2);
			memcpy(&pD->config_descriptor, p, desc_len);
		} else if (desc_type == DESC_INTERF) {
			memcpy(&pD->interface_descriptor, p, desc_len);
		} else if (desc_type == DESC_EP) {
			memcpy(&pD->ed_descriptor[ep_num++], p, desc_len);
		} else {
			
		}
		
		p += desc_len;
		cur_len += desc_len;
		if (cur_len >= tot_len) break;		
	}
}

/*
 * 
 */
static void ohci_set_ed_size(PS_UHP_ED pED, unsigned int size) {
	pED->phED->Control &= ~(0xFF << 16); 
	pED->phED->Control |= (size << 16);
}

/*
 * 
 */
static int ohci_get_device_info(USBDevice_t *pD) {
	
	PS_UHP_ED pED;
	unsigned char bbuf[64];
	
	if (!pD) return -1;
	
	pED = (PS_UHP_ED)(pD->dev_eds[OHCI_CONTROL_ED].pED);
	if (!pED) return -1;
	
	if (ohci_device_config_request(pED, (void *)&(pD->device_descriptor))) {
		OHCI_DBG("!!!ERROR: Get device descriptor\r\n");
		return -1;
	}	
	
	if (!pD->device_descriptor.bDescriptorType) return -1;
	
	if (pED->Max_packet != pD->device_descriptor.bMaxPacketSize0) {
		ohci_set_ed_size(pED, pD->device_descriptor.bMaxPacketSize0);		
		if (ohci_device_config_request(pED, (void *)&(pD->device_descriptor))) {
			OHCI_DBG("!!!ERROR: Get device descriptor\r\n");
			return -1;
		}	
	}
	
	//print_dev_data((void *)&(pD->device_descriptor));
	if (ohci_set_address_request(pED, (void *)bbuf, pD->dev_num + 1)) {
		OHCI_DBG("!!!ERROR: Set address[%d]\r\n", pD->dev_num + 1);
		return -1;
	}
	pD->fun_addr = pD->dev_num + 1;
	OSTimeDly(20);
	if (ohci_config_request(pED, (void *)bbuf)) {
		OHCI_DBG("!!!ERROR: Get configuration descriptor\r\n");
		return -1;
	}
	ohci_parse_descriptor(pD, (void *)bbuf);
	
	printf("\r\n");
	pD->ed_num = pD->interface_descriptor.bNumEndpoints;
	//print_dev_config((void *)&(pD->config_descriptor));

	if (ohci_set_configured_request(pED, (void *)bbuf)) {
		OHCI_DBG("!!!ERROR: Set configured\r\n");
		return -1;
	}	
	return 0;	
}

/*
 * 
 */
static int ohci_set_device_configuration(USBDevice_t *pD) {
	unsigned int i;
	PS_UHP_ED pED;
	OHCI_PS_UHP_ED phED;
	unsigned int dir;
	unsigned int addr;
	unsigned int type = 0;
	unsigned int amount;
		
	for (i = 0;i < pD->ed_num;i++) {
		dir = (pD->ed_descriptor[i].bEndpointAddress & 0x80)? ED_IN: ED_OUT;
		addr = pD->ed_descriptor[i].bEndpointAddress & 0x0F;
		
		if ((pD->ed_descriptor[i].bmAttributes & 0x03) == 2)
			type = OHCI_BULK_ED;
		else if ((pD->ed_descriptor[i].bmAttributes & 0x03) == 3)
			type = OHCI_INT_ED;

		amount = pD->ed_descriptor[i].wMaxPacketSize;

		pED = ohci_create_ed(pD->ed_descriptor[i].wMaxPacketSize,				// Max packet
				 			ED_GEN_FORMAT,		// TD format
				 			ED_SKIP,			// Skip
				 			(pD->speed & 0x80)? ED_LOW_SPEED: ED_FUL_SPEED,		// Speed
				 			dir,				// Direction
				 			addr,				// Endpoint number
				 			pD->fun_addr,		// Func Address
				 			0,					// TDQTailPointer
				 			0,					// TDQHeadPointer
				 			0,					// ToggleCarry
				 			0,					// NextED
				 			type,				// Type (Bulk, Int, Iso)
				 			amount);			// EP max packet size	
		if (!pED) return -1;
			
		phED = pED->phED;
		if (!phED) return -1;
		
		pD->dev_eds[i + 1].pED = (void *)pED;
		pD->dev_eds[i + 1].max_packet = pD->ed_descriptor[i].wMaxPacketSize;
		pD->dev_eds[i + 1].direction = dir; 
		pD->dev_eds[i + 1].present = 1;
		
		ohci_add_ed(pED);
	}
	return 0;
}

/*
 * 
 */
int ohci_init_ed_list() {
	PS_UHP_ED pControl, pBulk, pInt;
	OHCI_PS_UHP_HCCA pHcca = &HCCA;
	// Create empty EDs to start ed list
	
	// Create Control ED
	pControl = ohci_create_ed(64,				// Max packet
							ED_GEN_FORMAT,		// TD format
							ED_SKIP,					// Skip
							ED_FUL_SPEED,		// Speed
							ED_GET_FROM_TD,	// Direction
							0,					// Endpoint number
							0,					// Func Address
							0,					// TDQTailPointer
							0,					// TDQHeadPointer
							0,					// ToggleCarry
							0,					// NextED
							OHCI_CONTROL_ED,
							64);				// Type (Control)
	if (!pControl) 
		return -1;
	
	ohci->HcControlHeadED = (unsigned int) pControl->phED;
	ohci->HcControlCurrentED = (unsigned int) pControl->phED;
	// Create Bulk ED	
	pBulk = ohci_create_ed(64,				// Max packet
 							ED_GEN_FORMAT,		// TD format
 							ED_SKIP,			// Skip
 							ED_FUL_SPEED,		// Speed
 							ED_GET_FROM_TD,		// Direction
 							0,					// Endpoint number
 							0,					// Func Address
 							0,					// TDQTailPointer
 							0,					// TDQHeadPointer
 							0,					// ToggleCarry
 							0,					// NextED
 							OHCI_BULK_ED,
 							64);	
	if (!pBulk)
		return -1;
	
	ohci->HcBulkHeadED = (unsigned int) pBulk->phED;
	ohci->HcBulkCurrentED = (unsigned int) pBulk->phED;
	// Create Interrupt ED
	pInt = ohci_create_ed(64,				// Max packet
 							ED_GEN_FORMAT,		// TD format

⌨️ 快捷键说明

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