Simple USBHost WebCam test program

Dependencies:   F401RE-USBHost mbed

Fork of KL46Z-USBHostC270_example by Norimasa Okamoto

WebカメラからJPEG画像を読み取るテストプログラムです。
使い方はKL46Z-USBHostC270_exampleと同じです。
動作確認カメラ: Logitech C270, Logitech C210, Logitech Q200R(Qcam Orbit AF), LifeCam VX-500
/media/uploads/va009039/f401re-c270-1.jpg /media/uploads/va009039/k64f-c270.jpg

Files at this revision

API Documentation at this revision

Comitter:
va009039
Date:
Fri Jan 31 13:50:15 2014 +0000
Parent:
1:22304b8f8395
Child:
3:b2f688e2ddd7
Commit message:
USB hub support.

Changed in this revision

KL46Z-USBHost.lib Show annotated file Show diff for this revision Revisions of this file
KL46Z_USBHostC270/BaseUvc.cpp Show annotated file Show diff for this revision Revisions of this file
KL46Z_USBHostC270/BaseUvc.h Show annotated file Show diff for this revision Revisions of this file
KL46Z_USBHostC270/USBHostC270.cpp Show diff for this revision Revisions of this file
KL46Z_USBHostC270/USBHostC270.h Show diff for this revision Revisions of this file
KL46Z_USBHostC270/USBHostCam.cpp Show annotated file Show diff for this revision Revisions of this file
KL46Z_USBHostC270/USBHostCam.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/KL46Z-USBHost.lib	Tue Jan 28 06:54:16 2014 +0000
+++ b/KL46Z-USBHost.lib	Fri Jan 31 13:50:15 2014 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/va009039/code/KL46Z-USBHost/#9a20482c9a7a
+http://mbed.org/users/va009039/code/KL46Z-USBHost/#6463cd1964c0
--- a/KL46Z_USBHostC270/BaseUvc.cpp	Tue Jan 28 06:54:16 2014 +0000
+++ b/KL46Z_USBHostC270/BaseUvc.cpp	Fri Jan 31 13:50:15 2014 +0000
@@ -1,16 +1,15 @@
 // BaseUvc.cpp
 #include "USBHostConf.h"
 #include "USBHost.h"
-//#include "USBIsochronous.h"
 #include "BaseUvc.h"
 
 void BaseUvc::poll()
 {
-    uint8_t buf[ep_iso_in.getSize()];
-    int result = host->IsochronousRead(&ep_iso_in, buf, sizeof(buf));
+    uint8_t buf[ep_iso_in->getSize()];
+    int result = host->IsochronousRead(ep_iso_in, buf, sizeof(buf));
     if (result >= 0) {
         uint16_t frame = 0;
-        onResult(frame, buf, result);
+        onResult(frame, buf, ep_iso_in->getLengthTransferred());
     }
 }
 
--- a/KL46Z_USBHostC270/BaseUvc.h	Tue Jan 28 06:54:16 2014 +0000
+++ b/KL46Z_USBHostC270/BaseUvc.h	Fri Jan 31 13:50:15 2014 +0000
@@ -46,6 +46,6 @@
     void (*m_pCb)(uint16_t, uint8_t*, int);
 protected:
     USBHost * host;
-    USBDeviceConnected * dev; // dummy
-    USBEndpoint ep_iso_in;
+    USBDeviceConnected * dev;
+    USBEndpoint* ep_iso_in;
 };
--- a/KL46Z_USBHostC270/USBHostC270.cpp	Tue Jan 28 06:54:16 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-#include "USBHostC270.h"
-//#include "dbg.h"
-
-#define C270_DEBUG 1
-#ifdef C270_DEBUG
-#define C270_DBG(x, ...) std::printf("[%s:%d]"x"\r\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
-#else
-#define C270_DBG(...)  while(0);
-#endif
-
-USBHostC270::USBHostC270(int formatIndex, int frameIndex, uint32_t interval) {
-    _formatIndex = formatIndex;
-    _frameIndex = frameIndex;
-    _interval = interval;
-    clearOnResult();
-    host = USBHost::getHostInst();
-    report = &host->report;
-    setup();
-}
-
-void USBHostC270::setup() {
-    ep_iso_in.setAddress(C270_EN);
-    ep_iso_in.setSize(C270_MPS);
-    uint8_t buf[26];
-    memset(buf, 0, sizeof(buf));
-    buf[2] = _formatIndex;
-    buf[3] = _frameIndex;
-    *reinterpret_cast<uint32_t*>(buf+4) = _interval;
-    USB_TYPE res = Control(SET_CUR, VS_COMMIT_CONTROL, 1, buf, sizeof(buf));
-    if (res != USB_TYPE_OK) {
-         C270_DBG("SET_CUR VS_COMMIT_CONTROL FAILED");
-    }
-    res = setInterfaceAlternate(1, C270_IF_ALT); // alt=1 packet size = 192
-    if (res != USB_TYPE_OK) {
-         C270_DBG("SET_INTERFACE FAILED");
-    }
-}
-
-#define SEQ_READ_IDOL 0
-#define SEQ_READ_EXEC 1
-#define SEQ_READ_DONE 2
-
-int USBHostC270::readJPEG(uint8_t* buf, int size, int timeout_ms) {
-    _buf = buf;
-    _pos = 0;
-    _size = size;
-    _seq = SEQ_READ_IDOL;
-    setOnResult(this, &USBHostC270::callback_motion_jpeg);
-    Timer timeout_t;
-    timeout_t.reset();
-    timeout_t.start();
-    while(timeout_t.read_ms() < timeout_ms && _seq != SEQ_READ_DONE) {
-        poll();
-    } 
-    return _pos;
-}
-
-/* virtual */ void USBHostC270::outputJPEG(uint8_t c, int status) { // from decodeMJPEG
-    if (_seq == SEQ_READ_IDOL) {
-        if (status == JPEG_START) {
-            _pos = 0;
-            _seq = SEQ_READ_EXEC;
-        }
-    }
-    if (_seq == SEQ_READ_EXEC) {
-        if (_pos < _size) {
-            _buf[_pos++] = c;  
-        }  
-        if (status == JPEG_END) {
-            _seq = SEQ_READ_DONE;
-        }
-    }
-}
-
-void USBHostC270::callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len) {
-        inputPacket(buf, len);
-}
--- a/KL46Z_USBHostC270/USBHostC270.h	Tue Jan 28 06:54:16 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-// Simple USBHost Logtigech C270 for FRDM-KL46Z
-#include "USBHost.h"
-#include "BaseUvc.h"
-#include "decodeMJPEG.h"
-
-// Logitech C270
-#define C270_VID 0x046d
-#define C270_PID 0x0825
-#define C270_160x120 2
-#define C270_176x144 3
-#define C270_320x176 4
-#define C270_320x240 5
-#define C270_352x288 6
-#define C270_432x240 7
-#define C270_640x480 1
-#define C270_544x288 8
-#define C270_640x360 9
-#define C270_752x416 10
-#define C270_800x448 11
-#define C270_800x600 12
-
-#define C270_MJPEG 2
-#define C270_YUV2  1
-
-#define C270_EN  0x81
-#define C270_MPS  192
-#define C270_IF_ALT 1
-
-class USBHostC270 : public BaseUvc, public decodeMJPEG {
-public:
-    USBHostC270(int formatIndex = C270_MJPEG, int frameIndex = C270_160x120, uint32_t interval = _5FPS);
-    /**
-     * read jpeg image
-     *
-     * @param buf read buffer 
-     * @param size buffer size 
-     * @param timeout_ms timeout default 15sec
-     * @return jpeg size if read success else -1
-     */
-    int readJPEG(uint8_t* buf, int size, int timeout_ms = 15*1000);
-
-    Report* report;
-
-private:
-    int _formatIndex;
-    int _frameIndex;
-    uint32_t _interval;
-    uint8_t _seq;
-    uint8_t* _buf;
-    int _pos;
-    int _size;
-
-    void setup();
-    virtual void outputJPEG(uint8_t c, int status); // from decodeMJPEG
-    void callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len);
-};
-
--- a/KL46Z_USBHostC270/USBHostCam.cpp	Tue Jan 28 06:54:16 2014 +0000
+++ b/KL46Z_USBHostC270/USBHostCam.cpp	Fri Jan 31 13:50:15 2014 +0000
@@ -1,13 +1,13 @@
 // USBHostCam.cpp
 #include "USBHostCam.h"
 
-//#define CAM_DEBUG 1
-#ifdef CAM_DEBUG
-#define CAM_DBG(x, ...) std::printf("[%s:%d]"x"\r\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
+#if 0
+#define CAM_DBG(x, ...) std::printf("[%s:%d]"x"\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
 #else
 #define CAM_DBG(...)  while(0);
 #endif
 #define CAM_INFO(...) do{fprintf(stderr,__VA_ARGS__);}while(0);
+#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);}while(0);
 
 CamInfo* getCamInfoList(); // CamInfo.cpp
 
@@ -23,14 +23,78 @@
     }
     clearOnResult();
     host = USBHost::getHostInst();
-    setup();
+    dev = host->getDevice(0);
+    ep_iso_in = new USBEndpoint;
+    init();
 }
 
+void USBHostCam::init()
+{
+    CAM_DBG("");
+    dev_connected = false;
+    dev = NULL;
+    cam_intf = -1;
+    device_found = false;
+    caminfo_found = false;
+}
+ 
+bool USBHostCam::connected()
+{
+    return dev_connected;
+}
+ 
+bool USBHostCam::connect()
+{
+    if (dev_connected) {
+        return true;
+    }
+ 
+    for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
+        if ((dev = host->getDevice(i)) != NULL) {
+            
+            CAM_DBG("Trying to connect Cam device\r\n");
+            
+            if(host->enumerate(dev, this)) {
+                break;
+            }
+            if (device_found) {
+                USB_INFO("New Cam: %s device: VID:%04x PID:%04x [dev: %p - intf: %d]\n", caminfo->name, dev->getVid(), dev->getPid(), dev, cam_intf);
+                dev->setName(caminfo->name, cam_intf);
+                //host->registerDriver(dev, cam_intf, this, &USBHostCam::onDisconnect);
+                int addr = dev->getAddress();
+                ep_iso_in->setDevice(dev);
+                ep_iso_in->setAddress(caminfo->en);
+                ep_iso_in->setSize(caminfo->mps);
+                //ep_iso_in->init(addr, caminfo->en, caminfo->mps, caminfo->frameCount, caminfo->queueLimit);
+                uint8_t buf[26];
+                memset(buf, 0, sizeof(buf));
+                buf[2] = caminfo->formatIndex;
+                buf[3] = caminfo->frameIndex;
+                *reinterpret_cast<uint32_t*>(buf+4) = caminfo->interval;
+                USB_TYPE res = Control(SET_CUR, VS_COMMIT_CONTROL, 1, buf, sizeof(buf));
+                if (res != USB_TYPE_OK) {
+                    CAM_DBG("SET_CUR VS_COMMIT_CONTROL FAILED");
+                }
+                res = setInterfaceAlternate(1, caminfo->if_alt);
+                if (res != USB_TYPE_OK) {
+                    CAM_DBG("SET_INTERFACE FAILED");
+                }
+                dev_connected = true;
+                return true;
+            }
+        }
+    }
+    init();
+    return false;
+}
+
+#if 0
 void USBHostCam::setup() {
     caminfo = CamInfoList;
     bool found = false;
     while(caminfo->vid != 0) {
-        if (caminfo->vid == host->dev.vid && caminfo->pid == host->dev.pid && 
+        if (caminfo->vid == host->getDevice(0)->getVid() &&
+            caminfo->pid == host->getDevice(0)->getPid() && 
             caminfo->size == _caminfo_size && caminfo->option == _caminfo_option) {
             found = true;
             break;
@@ -59,6 +123,39 @@
          CAM_DBG("SET_INTERFACE FAILED");
     }
 }
+#endif
+
+
+/*virtual*/ void USBHostCam::setVidPid(uint16_t vid, uint16_t pid)
+{
+    CAM_DBG("vid:%04x,pid:%04x", vid, pid);
+    caminfo = CamInfoList;
+    while(caminfo->vid != 0) {
+        if (caminfo->vid == vid && caminfo->pid == pid && 
+            caminfo->size == _caminfo_size && caminfo->option == _caminfo_option) {
+            caminfo_found = true;
+            break;
+        }
+        caminfo++;
+    }
+}
+ 
+/*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
+{
+    CAM_DBG("intf_nb=%d,intf_class=%02X,intf_subclass=%d,intf_protocol=%d", intf_nb, intf_class, intf_subclass, intf_protocol);
+    if ((cam_intf == -1) && caminfo_found) {
+        cam_intf = intf_nb;
+        device_found = true;
+        return true;
+    }
+    return false;
+}
+ 
+/*virtual*/ bool USBHostCam::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
+{
+    CAM_DBG("intf_nb:%d,type:%d,dir:%d",intf_nb, type, dir);
+    return false;
+}
 
 #define SEQ_READ_IDOL 0
 #define SEQ_READ_EXEC 1
--- a/KL46Z_USBHostC270/USBHostCam.h	Tue Jan 28 06:54:16 2014 +0000
+++ b/KL46Z_USBHostC270/USBHostCam.h	Fri Jan 31 13:50:15 2014 +0000
@@ -38,7 +38,7 @@
 /** 
  * A class to communicate a Cam
  */
-class USBHostCam : public BaseUvc, public decodeMJPEG {
+class USBHostCam : public IUSBEnumerator, public BaseUvc, public decodeMJPEG {
 public:
     /**
     * Constructor
@@ -47,6 +47,20 @@
     USBHostCam(uint8_t size = _160x120, uint8_t option = 0, CamInfo* user_caminfo = NULL);
 
     /**
+    * Check if a Cam device is connected
+    *
+    * @return true if a Cam device is connected
+    */
+    bool connected();
+ 
+    /**
+     * Try to connect to a Cam device
+     *
+     * @return true if connection was successful
+     */
+    bool connect();
+
+    /**
      * read jpeg image
      *
      * @param buf read buffer 
@@ -56,7 +70,19 @@
      */
     int readJPEG(uint8_t* buf, int size, int timeout_ms = 15*1000);
 
+protected:
+    //From IUSBEnumerator
+    virtual void setVidPid(uint16_t vid, uint16_t pid);
+    virtual bool 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
+    virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used
+
 private:
+    bool dev_connected;
+ 
+    int cam_intf;
+    bool device_found;
+    bool caminfo_found;
+
     uint8_t _seq;
     uint8_t* _buf;
     int _pos;
@@ -66,7 +92,7 @@
     uint8_t _caminfo_size;
     uint8_t _caminfo_option;
 
-    void setup();
     virtual void outputJPEG(uint8_t c, int status); // from decodeMJPEG
     void callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len);
+    void init();
 };
--- a/main.cpp	Tue Jan 28 06:54:16 2014 +0000
+++ b/main.cpp	Fri Jan 31 13:50:15 2014 +0000
@@ -17,6 +17,9 @@
 
     // Logitech C270
     USBHostCam* cam = new USBHostCam(_320x240);
+    if (!cam->connect()) {
+        error("WebCam not found.\n");
+    }
 
     int pos = 0; 
     int size = 0;