📄 ohci.c
字号:
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 + -