Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: STM32F407VET6_USBHostMSD STM32F407VET6_USBHostMouse STM32F407VET6_USBHostKeyboard STM32F407VET6_USBHostMSD_1
USBHost-STM32F4/USBHostC270/USBHostCam.cpp@0:458bf947f46f, 2019-02-19 (annotated)
- Committer:
- hudakz
- Date:
- Tue Feb 19 21:32:56 2019 +0000
- Revision:
- 0:458bf947f46f
Fork of [[https://os.mbed.com/users/va009039/code/F401RE-USBHost/]]. Added support for Seeed Arch Max and STM32F407.
Who changed what in which revision?
| User | Revision | Line number | New contents of line | 
|---|---|---|---|
| hudakz | 0:458bf947f46f | 1 | // USBHostCam.cpp | 
| hudakz | 0:458bf947f46f | 2 | #include "USBHostCam.h" | 
| hudakz | 0:458bf947f46f | 3 | |
| hudakz | 0:458bf947f46f | 4 | #if 0 | 
| hudakz | 0:458bf947f46f | 5 | #define CAM_DBG(x, ...) std::printf("[%s:%d]"x"\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); | 
| hudakz | 0:458bf947f46f | 6 | #else | 
| hudakz | 0:458bf947f46f | 7 | #define CAM_DBG(...) while(0); | 
| hudakz | 0:458bf947f46f | 8 | #endif | 
| hudakz | 0:458bf947f46f | 9 | #define CAM_INFO(...) do{fprintf(stderr,__VA_ARGS__);}while(0); | 
| hudakz | 0:458bf947f46f | 10 | |
| hudakz | 0:458bf947f46f | 11 | CamInfo* getCamInfoList(); // CamInfo.cpp | 
| hudakz | 0:458bf947f46f | 12 | |
| hudakz | 0:458bf947f46f | 13 | USBHostCam::USBHostCam(uint8_t size, uint8_t option, CamInfo* user_caminfo) | 
| hudakz | 0:458bf947f46f | 14 | { | 
| hudakz | 0:458bf947f46f | 15 | CAM_DBG("size: %d, option: %d", size, option); | 
| hudakz | 0:458bf947f46f | 16 | _caminfo_size = size; | 
| hudakz | 0:458bf947f46f | 17 | _caminfo_option = option; | 
| hudakz | 0:458bf947f46f | 18 | if (user_caminfo) { | 
| hudakz | 0:458bf947f46f | 19 | CamInfoList = user_caminfo; | 
| hudakz | 0:458bf947f46f | 20 | } else { | 
| hudakz | 0:458bf947f46f | 21 | CamInfoList = getCamInfoList(); | 
| hudakz | 0:458bf947f46f | 22 | } | 
| hudakz | 0:458bf947f46f | 23 | clearOnResult(); | 
| hudakz | 0:458bf947f46f | 24 | host = USBHost::getHostInst(); | 
| hudakz | 0:458bf947f46f | 25 | init(); | 
| hudakz | 0:458bf947f46f | 26 | } | 
| hudakz | 0:458bf947f46f | 27 | |
| hudakz | 0:458bf947f46f | 28 | void USBHostCam::init() | 
| hudakz | 0:458bf947f46f | 29 | { | 
| hudakz | 0:458bf947f46f | 30 | CAM_DBG(""); | 
| hudakz | 0:458bf947f46f | 31 | dev_connected = false; | 
| hudakz | 0:458bf947f46f | 32 | dev = NULL; | 
| hudakz | 0:458bf947f46f | 33 | ep_iso_in = NULL; | 
| hudakz | 0:458bf947f46f | 34 | cam_intf = -1; | 
| hudakz | 0:458bf947f46f | 35 | device_found = false; | 
| hudakz | 0:458bf947f46f | 36 | caminfo_found = false; | 
| hudakz | 0:458bf947f46f | 37 | } | 
| hudakz | 0:458bf947f46f | 38 | |
| hudakz | 0:458bf947f46f | 39 | bool USBHostCam::connected() | 
| hudakz | 0:458bf947f46f | 40 | { | 
| hudakz | 0:458bf947f46f | 41 | return dev_connected; | 
| hudakz | 0:458bf947f46f | 42 | } | 
| hudakz | 0:458bf947f46f | 43 | |
| hudakz | 0:458bf947f46f | 44 | bool USBHostCam::connect() | 
| hudakz | 0:458bf947f46f | 45 | { | 
| hudakz | 0:458bf947f46f | 46 | if (dev_connected) { | 
| hudakz | 0:458bf947f46f | 47 | return true; | 
| hudakz | 0:458bf947f46f | 48 | } | 
| hudakz | 0:458bf947f46f | 49 | |
| hudakz | 0:458bf947f46f | 50 | for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) { | 
| hudakz | 0:458bf947f46f | 51 | if ((dev = host->getDevice(i)) != NULL) { | 
| hudakz | 0:458bf947f46f | 52 | |
| hudakz | 0:458bf947f46f | 53 | CAM_DBG("Trying to connect Cam device\r\n"); | 
| hudakz | 0:458bf947f46f | 54 | |
| hudakz | 0:458bf947f46f | 55 | if(host->enumerate(dev, this)) { | 
| hudakz | 0:458bf947f46f | 56 | break; | 
| hudakz | 0:458bf947f46f | 57 | } | 
| hudakz | 0:458bf947f46f | 58 | if (device_found) { | 
| hudakz | 0:458bf947f46f | 59 | USB_INFO("New Cam: %s device: VID:%04x PID:%04x [dev: %p - intf: %d]", caminfo->name, dev->getVid(), dev->getPid(), dev, cam_intf); | 
| hudakz | 0:458bf947f46f | 60 | ep_iso_in = new USBEndpoint(dev); | 
| hudakz | 0:458bf947f46f | 61 | ep_iso_in->init(ISOCHRONOUS_ENDPOINT, IN, caminfo->mps, caminfo->en); | 
| hudakz | 0:458bf947f46f | 62 | ep_iso_in->ohci_init(caminfo->frameCount, caminfo->queueLimit); | 
| hudakz | 0:458bf947f46f | 63 | uint8_t buf[26]; | 
| hudakz | 0:458bf947f46f | 64 | memset(buf, 0, sizeof(buf)); | 
| hudakz | 0:458bf947f46f | 65 | buf[2] = caminfo->formatIndex; | 
| hudakz | 0:458bf947f46f | 66 | buf[3] = caminfo->frameIndex; | 
| hudakz | 0:458bf947f46f | 67 | *reinterpret_cast<uint32_t*>(buf+4) = caminfo->interval; | 
| hudakz | 0:458bf947f46f | 68 | USB_TYPE res = Control(SET_CUR, VS_COMMIT_CONTROL, 1, buf, sizeof(buf)); | 
| hudakz | 0:458bf947f46f | 69 | if (res != USB_TYPE_OK) { | 
| hudakz | 0:458bf947f46f | 70 | USB_ERR("SET_CUR VS_COMMIT_CONTROL FAILED"); | 
| hudakz | 0:458bf947f46f | 71 | } | 
| hudakz | 0:458bf947f46f | 72 | res = setInterfaceAlternate(1, caminfo->if_alt); | 
| hudakz | 0:458bf947f46f | 73 | if (res != USB_TYPE_OK) { | 
| hudakz | 0:458bf947f46f | 74 | USB_ERR("SET_INTERFACE FAILED"); | 
| hudakz | 0:458bf947f46f | 75 | } | 
| hudakz | 0:458bf947f46f | 76 | dev_connected = true; | 
| hudakz | 0:458bf947f46f | 77 | return true; | 
| hudakz | 0:458bf947f46f | 78 | } | 
| hudakz | 0:458bf947f46f | 79 | } | 
| hudakz | 0:458bf947f46f | 80 | } | 
| hudakz | 0:458bf947f46f | 81 | init(); | 
| hudakz | 0:458bf947f46f | 82 | return false; | 
| hudakz | 0:458bf947f46f | 83 | } | 
| hudakz | 0:458bf947f46f | 84 | |
| hudakz | 0:458bf947f46f | 85 | /*virtual*/ void USBHostCam::setVidPid(uint16_t vid, uint16_t pid) | 
| hudakz | 0:458bf947f46f | 86 | { | 
| hudakz | 0:458bf947f46f | 87 | CAM_DBG("vid:%04x,pid:%04x", vid, pid); | 
| hudakz | 0:458bf947f46f | 88 | caminfo = CamInfoList; | 
| hudakz | 0:458bf947f46f | 89 | while(caminfo->vid != 0) { | 
| hudakz | 0:458bf947f46f | 90 | if (caminfo->vid == vid && caminfo->pid == pid && | 
| hudakz | 0:458bf947f46f | 91 | caminfo->size == _caminfo_size && caminfo->option == _caminfo_option) { | 
| hudakz | 0:458bf947f46f | 92 | caminfo_found = true; | 
| hudakz | 0:458bf947f46f | 93 | break; | 
| hudakz | 0:458bf947f46f | 94 | } | 
| hudakz | 0:458bf947f46f | 95 | caminfo++; | 
| hudakz | 0:458bf947f46f | 96 | } | 
| hudakz | 0:458bf947f46f | 97 | } | 
| hudakz | 0:458bf947f46f | 98 | |
| hudakz | 0:458bf947f46f | 99 | /*virtual*/ bool USBHostCam::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed | 
| hudakz | 0:458bf947f46f | 100 | { | 
| hudakz | 0:458bf947f46f | 101 | CAM_DBG("intf_nb=%d,intf_class=%02X,intf_subclass=%d,intf_protocol=%d", intf_nb, intf_class, intf_subclass, intf_protocol); | 
| hudakz | 0:458bf947f46f | 102 | if ((cam_intf == -1) && caminfo_found) { | 
| hudakz | 0:458bf947f46f | 103 | cam_intf = intf_nb; | 
| hudakz | 0:458bf947f46f | 104 | device_found = true; | 
| hudakz | 0:458bf947f46f | 105 | return true; | 
| hudakz | 0:458bf947f46f | 106 | } | 
| hudakz | 0:458bf947f46f | 107 | return false; | 
| hudakz | 0:458bf947f46f | 108 | } | 
| hudakz | 0:458bf947f46f | 109 | |
| hudakz | 0:458bf947f46f | 110 | /*virtual*/ bool USBHostCam::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used | 
| hudakz | 0:458bf947f46f | 111 | { | 
| hudakz | 0:458bf947f46f | 112 | CAM_DBG("intf_nb:%d,type:%d,dir:%d",intf_nb, type, dir); | 
| hudakz | 0:458bf947f46f | 113 | return false; | 
| hudakz | 0:458bf947f46f | 114 | } | 
| hudakz | 0:458bf947f46f | 115 | |
| hudakz | 0:458bf947f46f | 116 | #define SEQ_READ_IDLE 0 | 
| hudakz | 0:458bf947f46f | 117 | #define SEQ_READ_EXEC 1 | 
| hudakz | 0:458bf947f46f | 118 | #define SEQ_READ_DONE 2 | 
| hudakz | 0:458bf947f46f | 119 | |
| hudakz | 0:458bf947f46f | 120 | int USBHostCam::readJPEG(uint8_t* buf, int size, int timeout_ms) { | 
| hudakz | 0:458bf947f46f | 121 | _buf = buf; | 
| hudakz | 0:458bf947f46f | 122 | _pos = 0; | 
| hudakz | 0:458bf947f46f | 123 | _size = size; | 
| hudakz | 0:458bf947f46f | 124 | _seq = SEQ_READ_IDLE; | 
| hudakz | 0:458bf947f46f | 125 | setOnResult(this, &USBHostCam::callback_motion_jpeg); | 
| hudakz | 0:458bf947f46f | 126 | Timer timeout_t; | 
| hudakz | 0:458bf947f46f | 127 | timeout_t.reset(); | 
| hudakz | 0:458bf947f46f | 128 | timeout_t.start(); | 
| hudakz | 0:458bf947f46f | 129 | while(timeout_t.read_ms() < timeout_ms && _seq != SEQ_READ_DONE) { | 
| hudakz | 0:458bf947f46f | 130 | poll(); | 
| hudakz | 0:458bf947f46f | 131 | } | 
| hudakz | 0:458bf947f46f | 132 | return _pos; | 
| hudakz | 0:458bf947f46f | 133 | } | 
| hudakz | 0:458bf947f46f | 134 | |
| hudakz | 0:458bf947f46f | 135 | /* virtual */ void USBHostCam::outputJPEG(uint8_t c, int status) { // from decodeMJPEG | 
| hudakz | 0:458bf947f46f | 136 | if (_seq == SEQ_READ_IDLE) { | 
| hudakz | 0:458bf947f46f | 137 | if (status == JPEG_START) { | 
| hudakz | 0:458bf947f46f | 138 | _pos = 0; | 
| hudakz | 0:458bf947f46f | 139 | _seq = SEQ_READ_EXEC; | 
| hudakz | 0:458bf947f46f | 140 | } | 
| hudakz | 0:458bf947f46f | 141 | } | 
| hudakz | 0:458bf947f46f | 142 | if (_seq == SEQ_READ_EXEC) { | 
| hudakz | 0:458bf947f46f | 143 | if (_pos < _size) { | 
| hudakz | 0:458bf947f46f | 144 | _buf[_pos++] = c; | 
| hudakz | 0:458bf947f46f | 145 | } | 
| hudakz | 0:458bf947f46f | 146 | if (status == JPEG_END) { | 
| hudakz | 0:458bf947f46f | 147 | _seq = SEQ_READ_DONE; | 
| hudakz | 0:458bf947f46f | 148 | } | 
| hudakz | 0:458bf947f46f | 149 | } | 
| hudakz | 0:458bf947f46f | 150 | } | 
| hudakz | 0:458bf947f46f | 151 | |
| hudakz | 0:458bf947f46f | 152 | void USBHostCam::callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len) { | 
| hudakz | 0:458bf947f46f | 153 | inputPacket(buf, len); | 
| hudakz | 0:458bf947f46f | 154 | } |