📄 usbio.c
字号:
/* bit2=0: 儂僗僩偐傜僨僶僀僗傊偺揮憲 */ /* bit1=0: USB 揮憲 Disable */ /* bit0=1: 揮憲壜擻 */ /* HUB required approx. 24.1ms */ DELAYMS (25); if (speed == SPEED_UNKNOWN) printf ("枹専弌: InterruptStatusRegister = 0x%02x, 0x%02x\n", stat1, stat2); else { const char* sp_mes[] = { "(邅瓦)", "Full Speed", "Low Speed", "Low Speed (via HUB)", }; printf ("専弌: %s, InterruptStatusRegister = 0x%02x, 0x%02x\n", sp_mes[speed], stat1, stat2); } return speed;}/* USB 偵愙懕偝傟偰偄傞婡婍傪儕僙僢僩偡傞 */voidUsbReset (void){ unsigned char tmp = SL811Read (SL811_ControlRegister1); /* Setup USB Reset */ SL811Write (SL811_ControlRegister1, tmp | b0000_1000); /* bit3=1: USB Engine Reset */ DELAYMS (24); /* enable USB */ SL811Write (SL811_ControlRegister1, tmp); DELAYMS (10); return;}/* ---------------------------------------------------------------------- *//* 僙僢僩傾僢僾僩儔儞僓僋僔儑儞(僐儞僩儘乕儖揮憲)傪幚峴偡傞 *//* 曉抣: 僨乕僞僷働僢僩偱幚嵺偵揮憲偟偨僶僀僩悢(-1 側傜僄儔乕) */intsetup_transfer (int devadr, SetupData* pSetup, unsigned char* pData, int payload, DevSpeed speed){ int ep = 0; int rc, pid, len, transfered_len = 0; /* 傑偢 Setup 僷働僢僩傪憲怣偡傞 */ pid = PID_SETUP; len = sizeof_SetupData; rc = UsbTransfer (devadr, ep, pid, (unsigned char*) pSetup, len, payload, speed); if (rc < 0) return rc; /* 僨乕僞僗僥乕僕偺曽岦 */ if ((pSetup->bmRequestType & DATA_TRANSFER_DIRECTION) == DIR_DEVICE2HOST) pid = PID_IN; else pid = PID_OUT; /* 師偵 in 僷働僢僩傪庴怣傑偨偼 out 僷働僢僩傪憲怣偡傞(徣棯偝傟傞応崌傕偁傞) */ len = read_w (pSetup->wLength); if (len) { rc = UsbTransfer (devadr, ep, pid, pData, len, payload, speed); if (rc < 0) return rc; transfered_len = rc; } /* 嵟屻偵(ACK 偺戙傢傝偵)嬻偺 out 僷働僢僩傪憲怣傑偨偼 in 僷働僢僩傪庴怣偡傞 */ /* 僗僥乕僞僗僗僥乕僕偼僨乕僞僗僥乕僕偺斀懳曽岦 */ pid ^= (PID_IN ^ PID_OUT); len = 0; rc = UsbTransfer (devadr, ep, pid, NULL, len, payload, speed); if (rc < 0) return rc; /* 揮憲僶僀僩悢傪曉偡 */ return transfered_len;}/* 僷働僢僩憲庴怣傪峴偆 *//* 曉抣: 幚嵺偵揮憲偟偨僶僀僩悢(-1 側傜僄儔乕) */intUsbTransfer (int devadr, int ep, int pid, unsigned char* pData, int req_len, int payload, DevSpeed speed){ int transfered_len = 0; int stat; int cmd, buf, toggle_buf; unsigned char* p; /* 僷働僢僩偺庬椶偲(偁傟偽)偦偺撪梕傪昞帵 */ switch (pid) { case PID_OUT: printf ("憲怣: PID_OUT, %d byte", req_len); if (req_len) { printf (", *pData = "); hexdump (pData, req_len); } printf ("\n"); break; case PID_IN: printf ("庴怣: PID_IN, 嵟戝 %d byte\n", req_len); break; case PID_SOF: printf ("憲怣: PID_SOF\n"); break; case PID_SETUP: printf ("憲怣: PID_SETUP, %d byte", req_len); if (req_len) { printf (", *pSetup = "); hexdump (pData, req_len); } printf ("\n"); break; case PID_DATA0: printf ("????: PID_DATA0, %d byte\n", req_len); break; case PID_DATA1: printf ("????: PID_DATA1, %d byte\n", req_len); break; case PID_ACK: printf ("憲怣: PID_ACK\n"); break; case PID_NAK: printf ("憲怣: PID_NAK\n"); break; case PID_STALL: printf ("憲怣: PID_STALL\n"); break; case PID_PRE: printf ("憲怣: PID_PRE\n"); break; default: printf ("PID=0x%02x: 枹抦偺 PID 偱偡.\n", pid); break; } /* 弶夞偺揮憲奐巒僐儅儞僪傪媮傔傞 */ switch (pid) { case PID_OUT: cmd = (ep == 0) ? SL811_WRITE_DATA1 : SL811_WRITE_DATA0; break; case PID_IN: cmd = (ep == 0) ? SL811_READ_DATA1 : SL811_READ_DATA0; break; case PID_SETUP: cmd = SL811_WRITE_DATA0; break; default: cmd = 0; break; } if (speed == FULL_SPEED) cmd |= SL811_SOF; /* SL811 忋偺憲庴怣僶僢僼傽偺傾僪儗僗傪媮傔傞 */ buf = SL811_BUF; toggle_buf = 0;/* * 憲庴怣僶僢僼傽傪擇偮梡堄偟偰偺岎屳棙梡 * * 崱偺偲偙傠 * 僐儅儞僪(0)愝掕 -> 庴怣(0)姰椆懸偪 -> 僶僢僼傽(0)撉傒弌偟 * -> 僐儅儞僪(1)愝掕 -> 庴怣(1)姰椆懸偪 -> 僶僢僼傽(1)撉傒弌偟 乧 * 偲側偭偰偄傞偺偱堄枴側偟. * * 僐儅儞僪愝掕偐傜庴怣姰椆傑偱偼懡彮帪娫偑梋偭偰偄傞偺偱丄 * 僐儅儞僪(0)愝掕 -> 庴怣(0)姰椆懸偪 * -> 僐儅儞僪(1)愝掕 -> 僶僢僼傽(0)撉傒弌偟 -> 庴怣(1)姰椆懸偪 * -> 僐儅儞僪(0)愝掕 -> 僶僢僼傽(1)撉傒弌偟 -> 庴怣(0)姰椆懸偪 乧 * 偺傛偆偵曄峏偡傟偽懡彮揮憲懍搙偑忋傞偐傕抦傟側偄. */ if (SL811_BUF_SIZE / 2 >= payload) toggle_buf = buf ^ (SL811_BUF + SL811_BUF_SIZE / 2); /* 偦偺懠偺僷儔儊乕僞傪寁嶼 */ p = pData; /* SL811 偺儗僕僗僞偵 PID:EndPoint 傪愝掕 */ SL811Write (SL811_A_HostPID_DeviceEndpoint, ((pid & 0x0f) << 4) + ep); /* SL811 偺儗僕僗僞偵 DeviceAddress 傪愝掕 */ SL811Write (SL811_A_HostDeviceAddress, devadr); /* 妱傝崬傒嬛巭 */ SL811Write (SL811_InterruptEnableRegister, 0x00); if (verbose_level) printf (" 僐儅儞僪偺愝掕偲廔椆懸偪傪峴偄傑偡.\n");/* * 0 僶僀僩偺僷働僢僩傪憲庴怣偡傞応崌偑偁傞偺偱 * while (transfered_len < req_len) * 偱偼偄偗側偄. */ do { int last_stat; /* 崱夞憲庴怣偡傞僷働僢僩僒僀僘 */ int packet_size = min (req_len - transfered_len, payload); /* SL811 偺儗僕僗僞偵僶僢僼傽傾僪儗僗偺傾僪儗僗傪愝掕 */ SL811Write (SL811_A_HostBaseAddress, buf); /* SL811 偺儗僕僗僞偵僷働僢僩僒僀僘(憲庴怣僒僀僘)傪愝掕 */ SL811Write (SL811_A_HostBaseLength, packet_size); /* 憲怣偺応崌 */ if (pid == PID_OUT || pid == PID_SETUP) { /* SL811 偺僶僢僼傽偵憲怣僨乕僞傪彂偒崬傓 */ SL811BufWrite (buf, p, packet_size); p += packet_size; } last_stat = -1; do { /* 僗僥乕僞僗僋儕傾 */ SL811Write (SL811_InterruptStatusRegister, 0xff); /* SL811 偺儗僕僗僞偵揮憲奐巒僐儅儞僪傪愝掕 */ SL811Write (SL811_A_HostControlRegister, cmd); /* 僐儅儞僪廔椆懸偪 */ if (wait_command_done (SL811_INT_A) < 0) return -1; /* 僗僥乕僞僗庢摼 */ stat = SL811Read (SL811_A_USBStatus); /* 擇夞栚埲崀偼曄壔偑偁偭偨帪偩偗昞帵 */ if (stat != last_stat) print_usb_status (stat);#if 0/* 偙偙傪桳岠偵偡傞偲壗屘偐 wait_command_done() 偱偄偮傑偱偨偭偰傕廔傢傜側偄 */ last_stat = stat;#endif } while (stat & SL811_ST_NAK); /* 僨僶僀僗偑 NAK 偺応崌偼傕偆堦搙憲傝捈偡 */ if ((stat & SL811_ST_ACK) == 0) return -1; /* 僷働僢僩挿 - 枹揮憲僶僀僩悢 = 幚嵺偵揮憲偝傟偨僶僀僩悢 */ stat = SL811Read (SL811_A_HostTransferCountRegister); if (packet_size > stat) packet_size -= stat; /* 椵寁揮憲僶僀僩悢 */ transfered_len += packet_size; /* 庴怣偺応崌 */ if (pid == PID_IN) { /* SL811 偺僶僢僼傽偐傜庴怣僨乕僞傪撉傒崬傓 */ SL811BufRead (buf, p, packet_size); p += packet_size; } /* short packet 側傜揮憲傪懪偪愗傞 */ if (stat != 0) break; /* 師夞偺揮憲僐儅儞僪(Data0/Data1 僩僌儖) */ cmd ^= SL811_SEQ; /* 師夞偺揮憲僶僢僼傽(0/1)僩僌儖 */ buf ^= toggle_buf; } while (transfered_len < req_len); if (req_len) { if (pid == PID_SETUP || pid == PID_OUT) { printf (" %d 僶僀僩憲怣偟傑偟偨%s.\n", transfered_len, req_len == transfered_len ? "" : "(short packet)"); } else if (pid == PID_IN) { printf (" %d 僶僀僩庴怣偟傑偟偨%s.\n", transfered_len, req_len == transfered_len ? "" : "(short packet)"); /* 庴怣撪梕傪昞帵 */ printf (" *pData = "); hexdump (pData, transfered_len); printf ("\n"); } } return transfered_len;}/* USB-A/B 僗僥乕僞僗昞帵 */static voidprint_usb_status (int stat){ /* verbose=0 偐偮 ACK 側傜昞帵偟側偄 */ if (verbose_level == 0 && (stat & ~SL811_ST_SEQ) == SL811_ST_ACK) return; printf (" USBStatus: 0x%02x", stat); printf (" (STALL=%d", (stat & SL811_ST_STALL) ? 1 : 0); printf (", NAK=%d", (stat & SL811_ST_NAK) ? 1 : 0); printf (", OverFlow=%d", (stat & SL811_ST_OVFL) ? 1 : 0); printf (", Su-Packet=%d", (stat & SL811_ST_SUP) ? 1 : 0); printf (", Seq=Data%d", (stat & SL811_ST_SEQ) ? 1 : 0); printf (", Time-Out=%d", (stat & SL811_ST_TO) ? 1 : 0); printf (", ERR=%d", (stat & SL811_ST_ERR) ? 1 : 0); printf (", ACK=%d)\n", (stat & SL811_ST_ACK) ? 1 : 0); return;}/* 僐儅儞僪廔椆懸偪丗昞帵桳傝 */static intwait_command_done_verbose (int check_bit){ int prev = -1, stat; printf (" InterruptStatus:"); do { stat = SL811Read (SL811_InterruptStatusRegister); if (prev != stat) { printf (" %02x", stat); fflush (stdout); } prev = stat; if (_iocs_b_sftsns () & 1) { printf (" abort."); stat = -1; break; } } while ((stat & check_bit) == 0); printf ("\n"); return stat;}/* 僐儅儞僪廔椆懸偪丗昞帵側偟 */static intwait_command_done_quiet (int check_bit){ int stat; do { stat = SL811Read (SL811_InterruptStatusRegister); if (_iocs_b_sftsns () & 1) { stat = -1; break; } } while ((stat & check_bit) == 0); return stat;}/* 僐儅儞僪廔椆懸偪 */static intwait_command_done (int check_bit){ if (verbose_level) return wait_command_done_verbose (check_bit); else return wait_command_done_quiet (check_bit);}/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -