USB host library, support isochronous,bulk,interrupt and control.

Dependents:   BaseUsbHost_example BaseJpegDecode_example SimpleJpegDecode_example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BaseUsbHostCtlEp.cpp Source File

BaseUsbHostCtlEp.cpp

00001 // BaseUsbHostCtlEp.cpp 2013/2/11
00002 #include "mbed.h"
00003 #include "rtos.h"
00004 #include "BaseUsbHost.h"
00005 //#define DEBUG
00006 #include "BaseUsbHostDebug.h"
00007 #define TEST
00008 #include "BaseUsbHostTest.h"
00009 
00010 #pragma pack(push,1)
00011 struct SETUP {
00012     uint8_t bmRequestType;// +0
00013     uint8_t bRequest;     // +1
00014     uint16_t wValue;      // +2
00015     uint16_t wIndex;      // +4
00016     uint16_t wLength;     // +6
00017                           // +8
00018     SETUP(uint8_t RequestType, uint8_t Request, uint16_t Value, uint16_t Index, uint16_t Length) {
00019         CTASSERT(sizeof(SETUP) == 8);
00020         TEST_ASSERT(sizeof(SETUP) == 8);
00021         bmRequestType = RequestType;
00022         bRequest = Request;
00023         wValue = Value;
00024         wIndex = Index;
00025         wLength = Length;
00026     };
00027 };
00028 #pragma pack(pop)
00029 
00030 static uint8_t device_addr = 1;
00031 ControlEp::ControlEp(int lowSpeed):BaseEp(0, 0, 8, lowSpeed)
00032 {
00033     CTASSERT(HCTD_QUEUE_SIZE >= 3);
00034     TEST_ASSERT(HCTD_QUEUE_SIZE >= 3);
00035     HCTD* td = new HCTD(this);
00036     TEST_ASSERT(td);
00037     m_pED->TailTd = td;
00038     m_pED->HeadTd = td; 
00039     
00040     m_pED->Next = reinterpret_cast<HCED*>(LPC_USB->HcControlHeadED);
00041     LPC_USB->HcControlHeadED = reinterpret_cast<uint32_t>(m_pED);
00042 
00043     DBG_OHCI(LPC_USB->HcControlHeadED);
00044     DBG_ED(m_pED);
00045 
00046     int r = open(device_addr);
00047     if (r == USB_OK) {
00048         device_addr++;
00049     }
00050 }
00051 
00052 int ControlEp::SetAddress(int addr)
00053 {
00054     return controlSend(0x00, 5, addr);
00055 }
00056 
00057 int ControlEp::GetDescriptor(int descType, int descIndex, uint8_t* data, int length)
00058 {
00059     return controlReceive(0x80, 6, (descType<<8)|descIndex, 0, data, length);
00060 }
00061 
00062 int ControlEp::SetConfiguration(int config)
00063 {
00064     return controlSend(0x00, 9, config);
00065 }
00066 
00067 int ControlEp::GetConfiguration(int *config)
00068 {
00069     uint8_t buf[1];
00070     int rc = controlReceive(0x80, 8, 0, 0, buf, 1);
00071     *config = buf[0];
00072     return rc;
00073 }
00074 
00075 int ControlEp::SetInterfaceAlternate(int interface, int alternate)
00076 {
00077     int rc = controlSend(USB_HOST_TO_DEVICE | USB_RECIPIENT_INTERFACE, 
00078                      SET_INTERFACE, alternate, interface, NULL, 0);
00079     return rc;
00080 }
00081 
00082 int ControlEp::GetInterface(int interface, int *alternate)
00083 {
00084     uint8_t buf[1];
00085     int rc = controlReceive(0x81, 10, 0, interface, buf, 1);
00086     *alternate = buf[0];
00087     return rc;
00088 }
00089 
00090 string ControlEp::GetStringDescriptor(int index)
00091 {
00092     string s = "";
00093     uint8_t buf[128];
00094     int r = GetDescriptor(USB_DESCRIPTOR_TYPE_STRING, index, buf, sizeof(buf));
00095     if (r != USB_OK) {
00096         return s;
00097     }
00098     DBG_HEX(buf, sizeof(buf));
00099     StandardStringDescriptor* desc = reinterpret_cast<StandardStringDescriptor*>(buf);
00100     if (desc->bLength <= 2 || desc->bDescriptorType != 3) {
00101         return s;
00102     }
00103     for(int i = 0; i < desc->bLength-2; i += 2) {
00104         s += desc->bString[i];
00105     }
00106     return s;
00107 }
00108 
00109 int ControlEp::open(int addr)
00110 {
00111     TEST_ASSERT(addr >= 1 && addr <= 127);
00112     uint8_t buf[8];
00113     int r = GetDescriptor(1, 0, buf, 8);
00114     if (r != USB_OK) {
00115         return r;
00116     }
00117     TEST_ASSERT(buf[0] == 0x12);
00118     TEST_ASSERT(buf[1] == 0x01);
00119     TEST_ASSERT(buf[7] >= 8);
00120     update_MaxPacketSize(buf[7]);
00121     r = SetAddress(addr);    
00122     TEST_ASSERT(r == USB_OK);
00123     if (r != USB_OK) {
00124         return r;
00125     }
00126     wait_ms(2);
00127     update_FunctionAddress(addr);
00128     return USB_OK;
00129 }
00130 
00131 int ControlEp::controlReceive(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
00132                      uint8_t* data, int length) {
00133     DBG("Type: %02X Request: %02X Value: %04X Index: %04X %p %d\n", bmRequestType, bRequest, wValue, wIndex, data, length);
00134     HCTD* setup_td = m_pED->TailTd;
00135     SETUP setup(bmRequestType, bRequest, wValue, wIndex, length);
00136     setup_td->transfer(reinterpret_cast<uint8_t*>(&setup), sizeof(SETUP));
00137     setup_td->Control |= TD_TOGGLE_0|TD_SETUP|TD_DI; 
00138 
00139     HCTD* data_td = new HCTD(this);
00140     TEST_ASSERT(data_td);
00141     data_td->transfer(data, length);
00142     data_td->Control |= TD_TOGGLE_1|TD_IN|TD_DI; 
00143     setup_td->Next = data_td;
00144 
00145     HCTD* status_td = new HCTD(this);
00146     TEST_ASSERT(status_td);
00147     status_td->Control |= TD_TOGGLE_1|TD_OUT; // OUT(DATA1)
00148     data_td->Next = status_td;
00149 
00150     HCTD* blank_td = new HCTD(this);
00151     TEST_ASSERT(blank_td);
00152     status_td->Next = blank_td;
00153     m_pED->TailTd = blank_td;
00154 
00155     LPC_USB->HcCommandStatus |= OR_CMD_STATUS_CLF;
00156     LPC_USB->HcControl |= OR_CONTROL_CLE;
00157 
00158     int r = wait_queue_HCTD(setup_td, 100); // wait setup stage
00159     if (r != USB_OK) {
00160         return r;
00161     }
00162     HCTD* td = get_queue_HCTD(100);
00163     if (td == data_td) {
00164         delete td;
00165     } else {
00166         DBG_TD(td);
00167         TEST_ASSERT(td == data_td);
00168         return USB_ERROR;
00169     }
00170     r = wait_queue_HCTD(status_td, 100); // wait status stage
00171     return r;
00172 }
00173 
00174 int ControlEp::controlSend(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
00175                      const uint8_t* data, int length) {
00176     DBG("Type: %02X Request: %02X Value: %04X Index: %04X %p %d\n", bmRequestType, bRequest, wValue, wIndex, data, length);
00177     HCTD* setup_td = m_pED->TailTd;
00178 
00179     HCTD* status_td = new HCTD(this);
00180     TEST_ASSERT(status_td);
00181     HCTD* blank_td = new HCTD(this);
00182     TEST_ASSERT(blank_td);
00183     
00184     SETUP setup(bmRequestType, bRequest, wValue, wIndex, length);
00185     setup_td->transfer(reinterpret_cast<uint8_t*>(&setup), sizeof(SETUP));
00186     setup_td->Control |= TD_TOGGLE_0|TD_SETUP|TD_DI; 
00187     status_td->Control |= TD_TOGGLE_1|TD_IN; // IN(DATA1)
00188     setup_td->Next = status_td;
00189     status_td->Next = blank_td;
00190 
00191     if (length != 0) {
00192         HCTD* data_td = new HCTD(this);
00193         TEST_ASSERT(data_td);
00194         data_td->Control |= TD_TOGGLE_1|TD_OUT|TD_DI; 
00195         data_td->transfer(const_cast<uint8_t*>(data), length);
00196         setup_td->Next = data_td;
00197         data_td->Next = status_td;
00198     }
00199     m_pED->TailTd = blank_td;
00200     DBG_ED(m_pED);
00201 
00202     LPC_USB->HcCommandStatus |= OR_CMD_STATUS_CLF;
00203     LPC_USB->HcControl |= OR_CONTROL_CLE;
00204     
00205     int r = wait_queue_HCTD(status_td, 200); // wait status stage
00206     return r;
00207 }
00208 
00209 HCTD::HCTD(BaseEp* obj) {
00210     CTASSERT(sizeof(HCTD) == 36);
00211     TEST_ASSERT(sizeof(HCTD) == 36);
00212     TEST_ASSERT(obj);
00213     Control = TD_CC|TD_ROUNDING;
00214     CurrBufPtr = NULL;
00215     Next = NULL;
00216     BufEnd = NULL;
00217     buf_top = NULL;
00218     buf_size = 0;
00219     ep = obj;
00220 }