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.
Dependencies: FATFileSystem
Fork of F401RE-USBHost by
Revision 13:8774c07f12a5, committed 2014-06-10
- Comitter:
- va009039
- Date:
- Tue Jun 10 13:38:41 2014 +0900
- Parent:
- 12:b91fdea8c0a7
- Child:
- 14:b167f2b97cb7
- Commit message:
- add USBHostC270
Changed in this revision
--- a/USBHost/USBHALHost2_F401RE.cpp Mon Jun 09 09:01:10 2014 +0000
+++ b/USBHost/USBHALHost2_F401RE.cpp Tue Jun 10 13:38:41 2014 +0900
@@ -199,6 +199,12 @@
USB_HC_Halt(hhcd->Instance, chnum);
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
}
+ else if(hhcd->hc[chnum].ep_type == EP_TYPE_ISOC)
+ {
+ USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
+ hhcd->hc[chnum].urb_state = URB_DONE;
+ HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
+ }
hhcd->hc[chnum].toggle_in ^= 1;
}
--- a/USBHost/USBHALHost_F401RE.cpp Mon Jun 09 09:01:10 2014 +0000
+++ b/USBHost/USBHALHost_F401RE.cpp Tue Jun 10 13:38:41 2014 +0900
@@ -409,24 +409,17 @@
}
int USBHALHost::token_iso_in(USBEndpoint* ep, uint8_t* data, int size) {
- USBDeviceConnected* dev = ep->getDevice();
- HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_ISO_IN,
- ep->getAddress(),
- dev->getAddress(),
- HCD_SPEED_FULL,
- EP_TYPE_ISOC, ep->getSize());
-
- token_done = false;
+ static bool init = false;
+ if (!init) {
+ init = true;
+ USBDeviceConnected* dev = ep->getDevice();
+ HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_ISO_IN,
+ ep->getAddress(), dev->getAddress(),
+ HCD_SPEED_FULL, EP_TYPE_ISOC, ep->getSize());
+ }
HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_ISO_IN, DIR_IN, EP_TYPE_ISOC, 1, data, size, 0);
- while(!token_done);
-
- switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_ISO_IN)) {
- case URB_DONE:
+ while(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_ISO_IN) == URB_IDLE);
return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_ISO_IN);
-
- default:
- return -1;
- }
}
#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostC270/BaseUvc.cpp Tue Jun 10 13:38:41 2014 +0900
@@ -0,0 +1,55 @@
+// BaseUvc.cpp
+#include "USBHostConf.h"
+#include "USBHost.h"
+#include "BaseUvc.h"
+
+void BaseUvc::poll()
+{
+ uint8_t buf[ep_iso_in->getSize()];
+ int result = host->isochronousReadNB(ep_iso_in, buf, sizeof(buf));
+ if (result >= 0) {
+ uint16_t frame = 0;
+ onResult(frame, buf, ep_iso_in->getLengthTransferred());
+ }
+}
+
+USB_TYPE BaseUvc::Control(int req, int cs, int index, uint8_t* buf, int size)
+{
+ if (req == SET_CUR) {
+ return host->controlWrite(dev,
+ USB_HOST_TO_DEVICE | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE,
+ req, cs<<8, index, buf, size);
+ }
+ return host->controlRead(dev,
+ USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE,
+ req, cs<<8, index, buf, size);
+}
+
+USB_TYPE BaseUvc::setInterfaceAlternate(uint8_t intf, uint8_t alt)
+{
+ return host->controlWrite(dev, USB_HOST_TO_DEVICE | USB_RECIPIENT_INTERFACE,
+ SET_INTERFACE, alt, intf, NULL, 0);
+}
+
+void BaseUvc::onResult(uint16_t frame, uint8_t* buf, int len)
+{
+ if(m_pCbItem && m_pCbMeth)
+ (m_pCbItem->*m_pCbMeth)(frame, buf, len);
+ else if(m_pCb)
+ m_pCb(frame, buf, len);
+}
+
+void BaseUvc::setOnResult( void (*pMethod)(uint16_t, uint8_t*, int) )
+{
+ m_pCb = pMethod;
+ m_pCbItem = NULL;
+ m_pCbMeth = NULL;
+}
+
+void BaseUvc::clearOnResult()
+{
+ m_pCb = NULL;
+ m_pCbItem = NULL;
+ m_pCbMeth = NULL;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostC270/BaseUvc.h Tue Jun 10 13:38:41 2014 +0900
@@ -0,0 +1,51 @@
+// BaseUvc.h
+//#include "USBIsochronous.h"
+#pragma once
+
+// --- UVC --------------------------------------------------
+#define _30FPS 333333
+#define _25FPS 400000
+#define _20FPS 500000
+#define _15FPS 666666
+#define _10FPS 1000000
+#define _5FPS 2000000
+#define _1FPS 10000000
+
+#define SET_CUR 0x01
+#define GET_CUR 0x81
+#define GET_MIN 0x82
+#define GET_MAX 0x83
+#define GET_RES 0x84
+#define GET_LEN 0x85
+#define GET_INFO 0x86
+#define GET_DEF 0x87
+
+#define VS_PROBE_CONTROL 0x01
+#define VS_COMMIT_CONTROL 0x02
+
+class BaseUvc {
+public:
+ void poll();
+ USB_TYPE Control(int req, int cs, int index, uint8_t* buf, int size);
+ USB_TYPE setInterfaceAlternate(uint8_t intf, uint8_t alt);
+ //IsochronousEp* m_isoEp;
+ // callback
+ void onResult(uint16_t frame, uint8_t* buf, int len);
+ void setOnResult( void (*pMethod)(uint16_t, uint8_t*, int) );
+ class CDummy;
+ template<class T>
+ void setOnResult( T* pItem, void (T::*pMethod)(uint16_t, uint8_t*, int) )
+ {
+ m_pCb = NULL;
+ m_pCbItem = (CDummy*) pItem;
+ m_pCbMeth = (void (CDummy::*)(uint16_t, uint8_t*, int)) pMethod;
+ }
+ void clearOnResult();
+ CDummy* m_pCbItem;
+ void (CDummy::*m_pCbMeth)(uint16_t, uint8_t*, int);
+ void (*m_pCb)(uint16_t, uint8_t*, int);
+protected:
+ USBHost * host;
+ USBDeviceConnected * dev;
+ USBEndpoint* ep_iso_in;
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostC270/CamInfo.cpp Tue Jun 10 13:38:41 2014 +0900
@@ -0,0 +1,188 @@
+// CamInfo.cpp
+#include "USBHostCam.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_192 1
+#define C270_IF_ALT(A) C270_IF_ALT_##A
+
+#define C270_INFO(SIZE) {C270_VID, C270_PID, _##SIZE, 0, \
+ "C270", \
+ C270_MJPEG, \
+ C270_##SIZE, \
+ _5FPS, \
+ C270_EN, \
+ 192, \
+ C270_IF_ALT(192), \
+ }
+
+#define C210_PID 0x819
+#define C210_INFO(SIZE) {C270_VID, C210_PID, _##SIZE, 0, \
+ "C270", \
+ C270_MJPEG, \
+ C270_##SIZE, \
+ _5FPS, \
+ C270_EN, \
+ 192, \
+ C270_IF_ALT(192), \
+ }
+
+// Logitech Qcam Orbit AF QCAM-200R
+#define Q200R_VID 0x046d
+#define Q200R_PID 0x0994
+#define Q200R_160x120 1
+#define Q200R_176x144 2
+#define Q200R_320x240 3
+#define Q200R_352x288 4
+#define Q200R_640x480 5
+#define Q200R_800x600 6
+
+#define Q200R_MJPEG 1
+#define Q200R_YUV2 2
+
+#define Q200R_EN 0x81
+#define Q200R_MPS 192
+#define Q200R_IF_ALT_192 1
+#define Q200R_IF_ALT_384 2
+#define Q200R_IF_ALT_512 3
+#define Q200R_IF_ALT_640 4
+#define Q200R_IF_ALT_800 5
+#define Q200R_IF_ALT_944 6
+#define Q200R_IF_ALT(A) Q200R_IF_ALT_##A
+#define Q200R_INFO(SIZE) {Q200R_VID, Q200R_PID, _##SIZE, 0, \
+ "Q200R", \
+ Q200R_MJPEG, \
+ Q200R_##SIZE, \
+ _5FPS, \
+ Q200R_EN, \
+ 192, \
+ Q200R_IF_ALT(192), \
+ }
+
+//LifeCam VX700 / VX500
+#define VX700_VID 0x045e
+#define VX700_PID 0x074a
+
+#define VX700_160x120 5
+#define VX700_176x144 4
+#define VX700_320x240 3
+#define VX700_352x288 2
+#define VX700_640x480 1
+
+#define VX700_MJPEG 1
+
+#define VX700_EN 0x81
+#define VX700_MPS 128
+#define VX700_IF_ALT_128 1
+#define VX700_IF_ALT(A) VX700_IF_ALT_##A
+#define VX700_INFO(SIZE) {VX700_VID, VX700_PID, _##SIZE, 0, \
+ "VX700", \
+ VX700_MJPEG, \
+ VX700_##SIZE, \
+ _5FPS, \
+ VX700_EN, \
+ 128, \
+ VX700_IF_ALT(128), \
+ }
+
+//Sonix USB 2.0 Camera
+#define SONIX_160x120 5
+#define SONIX_176x144 4
+#define SONIX_320x240 3
+#define SONIX_352x288 2
+#define SONIX_640x480 1
+
+#define SONIX_IF_ALT_128 1
+#define SONIX_IF_ALT_256 2
+#define SONIX_IF_ALT_512 3
+#define SONIX_IF_ALT_600 4
+#define SONIX_IF_ALT_800 5
+#define SONIX_IF_ALT_956 6
+#define SONIX_IF_ALT(A) SONIX_IF_ALT_##A
+#define SONIX_INFO(SIZE) {0x0c45, 0x62c0, _##SIZE, 0, \
+ "SONIX", \
+ 1, \
+ SONIX_##SIZE, \
+ _5FPS, \
+ 0x81, \
+ 128, \
+ SONIX_IF_ALT(128), \
+ }
+
+static const CamInfo CamInfoList[] = {
+// Logitech C270
+C270_INFO(160x120),
+C270_INFO(176x144),
+C270_INFO(320x176),
+C270_INFO(320x240),
+C270_INFO(352x288),
+C270_INFO(432x240),
+C270_INFO(640x480),
+C270_INFO(544x288),
+C270_INFO(640x360),
+C270_INFO(752x416),
+C270_INFO(800x448),
+C270_INFO(800x600),
+
+// Logitech C210
+C210_INFO(160x120),
+C210_INFO(176x144),
+C210_INFO(320x176),
+C210_INFO(320x240),
+C210_INFO(352x288),
+C210_INFO(432x240),
+C210_INFO(640x480),
+C210_INFO(544x288),
+C210_INFO(640x360),
+C210_INFO(752x416),
+C210_INFO(800x448),
+C210_INFO(800x600),
+
+// Logitech Qcam Orbit AF QCAM-200R
+Q200R_INFO(160x120),
+Q200R_INFO(176x144),
+Q200R_INFO(320x240),
+Q200R_INFO(352x288),
+Q200R_INFO(640x480),
+Q200R_INFO(800x600),
+
+// LifeCam VX700
+VX700_INFO(160x120),
+VX700_INFO(176x144),
+VX700_INFO(320x240),
+VX700_INFO(352x288),
+VX700_INFO(640x480),
+
+// Sonix USB 2.0 Camera
+SONIX_INFO(160x120),
+SONIX_INFO(176x144),
+SONIX_INFO(320x240),
+SONIX_INFO(352x288),
+SONIX_INFO(640x480),
+
+// Not found
+{0,0,0,0},
+};
+
+CamInfo* getCamInfoList() {
+ return const_cast<CamInfo*>(CamInfoList);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostC270/USBHostCam.cpp Tue Jun 10 13:38:41 2014 +0900
@@ -0,0 +1,191 @@
+// USBHostCam.cpp
+#include "USBHostCam.h"
+
+#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);
+
+CamInfo* getCamInfoList(); // CamInfo.cpp
+
+USBHostCam::USBHostCam(uint8_t size, uint8_t option, CamInfo* user_caminfo)
+{
+ CAM_DBG("size: %d, option: %d", size, option);
+ _caminfo_size = size;
+ _caminfo_option = option;
+ if (user_caminfo) {
+ CamInfoList = user_caminfo;
+ } else {
+ CamInfoList = getCamInfoList();
+ }
+ clearOnResult();
+ host = USBHost::getHostInst();
+ init();
+}
+
+void USBHostCam::init()
+{
+ CAM_DBG("");
+ dev_connected = false;
+ dev = NULL;
+ ep_iso_in = 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]", caminfo->name, dev->getVid(), dev->getPid(), dev, cam_intf);
+ ep_iso_in = new USBEndpoint(dev);
+ ep_iso_in->init(ISOCHRONOUS_ENDPOINT, IN, caminfo->mps, caminfo->en);
+ 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) {
+ USB_ERR("SET_CUR VS_COMMIT_CONTROL FAILED");
+ }
+ res = setInterfaceAlternate(1, caminfo->if_alt);
+ if (res != USB_TYPE_OK) {
+ USB_ERR("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->getDevice(0)->getVid() &&
+ caminfo->pid == host->getDevice(0)->getPid() &&
+ caminfo->size == _caminfo_size && caminfo->option == _caminfo_option) {
+ found = true;
+ break;
+ }
+ caminfo++;
+ }
+ if (!found) {
+ CAM_INFO("caminfo not found.");
+ exit(1);
+ }
+ CAM_INFO("Found: %s", caminfo->name);
+
+ ep_iso_in.setAddress(caminfo->en);
+ ep_iso_in.setSize(caminfo->mps);
+ 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) {
+ USB_ERR("SET_CUR VS_COMMIT_CONTROL FAILED");
+ }
+ res = setInterfaceAlternate(1, caminfo->if_alt);
+ if (res != USB_TYPE_OK) {
+ USB_ERR("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_IDLE 0
+#define SEQ_READ_EXEC 1
+#define SEQ_READ_DONE 2
+
+int USBHostCam::readJPEG(uint8_t* buf, int size, int timeout_ms) {
+ _buf = buf;
+ _pos = 0;
+ _size = size;
+ _seq = SEQ_READ_IDLE;
+ setOnResult(this, &USBHostCam::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 USBHostCam::outputJPEG(uint8_t c, int status) { // from decodeMJPEG
+ if (_seq == SEQ_READ_IDLE) {
+ 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 USBHostCam::callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len) {
+ inputPacket(buf, len);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostC270/USBHostCam.h Tue Jun 10 13:38:41 2014 +0900
@@ -0,0 +1,98 @@
+// USBHostCam.h
+#include "USBHostConf.h"
+#include "USBHost.h"
+#include "BaseUvc.h"
+#include "decodeMJPEG.h"
+#pragma once
+
+#define _160x120 2
+#define _176x144 3
+#define _320x176 4
+#define _320x240 5
+#define _352x288 6
+#define _432x240 7
+#define _640x480 1
+#define _544x288 8
+#define _640x360 9
+#define _752x416 10
+#define _800x448 11
+#define _800x600 12
+
+#define TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
+
+struct CamInfo {
+ uint16_t vid;
+ uint16_t pid;
+ uint8_t size;
+ uint8_t option;
+//
+ const char* name;
+ uint8_t formatIndex;
+ uint8_t frameIndex;
+ uint32_t interval;
+ uint8_t en;
+ uint8_t mps;
+ uint8_t if_alt;
+};
+
+/**
+ * A class to communicate a Cam
+ */
+class USBHostCam : public IUSBEnumerator, public BaseUvc, public decodeMJPEG {
+public:
+ /**
+ * Constructor
+ *
+ */
+ 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
+ * @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);
+
+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;
+ int _size;
+ CamInfo* CamInfoList;
+ CamInfo* caminfo;
+ uint8_t _caminfo_size;
+ uint8_t _caminfo_option;
+
+ virtual void outputJPEG(uint8_t c, int status); // from decodeMJPEG
+ void callback_motion_jpeg(uint16_t frame, uint8_t* buf, int len);
+ void init();
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostC270/decodeMJPEG.cpp Tue Jun 10 13:38:41 2014 +0900
@@ -0,0 +1,180 @@
+// decodeMJPEG.cpp 2012/12/8
+// decode motion-jpeg to jpeg
+#include "mbed.h"
+#include "decodeMJPEG.h"
+
+#define MARK_SOF0 0xc0
+#define MARK_DHT 0xc4
+#define MARK_RST0 0xd0
+#define MARK_RST7 0xd7
+#define MARK_SOI 0xd8
+#define MARK_EOI 0xd9
+#define MARK_SOS 0xda
+#define MARK_DQT 0xdb
+#define MARK_DRI 0xdd
+#define MARK_APP 0xe0
+
+#define SEQ_INIT 0
+#define SEQ_SOI 1
+#define SEQ_FRAME 2
+#define SEQ_MARK 3
+#define SEQ_SEG_LEN 4
+#define SEQ_SEG_LEN2 5
+#define SEQ_SEG_BODY 6
+#define SEQ_SOS 7
+#define SEQ_SOS2 8
+
+static const uint8_t dht[] = {
+0xFF,0xC4,0x01,0xA2,0x00,0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,
+0x0B,0x01,0x00,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,
+0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x10,0x00,
+0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00,0x00,0x01,0x7D,0x01,
+0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,
+0x71,0x14,0x32,0x81,0x91,0xA1,0x08,0x23,0x42,0xB1,0xC1,0x15,0x52,0xD1,0xF0,0x24,
+0x33,0x62,0x72,0x82,0x09,0x0A,0x16,0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28,0x29,
+0x2A,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,
+0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,
+0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,
+0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,
+0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,0xC4,0xC5,0xC6,
+0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xE1,0xE2,0xE3,
+0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,
+0xFA,0x11,0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01,
+0x02,0x77,0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,
+0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xA1,0xB1,0xC1,0x09,0x23,0x33,
+0x52,0xF0,0x15,0x62,0x72,0xD1,0x0A,0x16,0x24,0x34,0xE1,0x25,0xF1,0x17,0x18,0x19,
+0x1A,0x26,0x27,0x28,0x29,0x2A,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,
+0x47,0x48,0x49,0x4A,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,
+0x67,0x68,0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x82,0x83,0x84,0x85,
+0x86,0x87,0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,
+0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,
+0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,
+0xD9,0xDA,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF2,0xF3,0xF4,0xF5,0xF6,
+0xF7,0xF8,0xF9,0xFA,
+};
+
+decodeMJPEG::decodeMJPEG()
+{
+ m_seq = SEQ_INIT;
+}
+
+void decodeMJPEG::inputPacket(const uint8_t* buf, int len)
+{
+ for(int i = 12; i < len; i++) {
+ input(buf[i]);
+ }
+}
+
+void decodeMJPEG::input(uint8_t c)
+{
+ switch(m_seq) {
+ case SEQ_INIT:
+ if (c == 0xff) {
+ m_seq = SEQ_SOI;
+ }
+ break;
+ case SEQ_SOI:
+ if (c == MARK_SOI) {
+ outputJPEG(0xff, JPEG_START); // start
+ outputJPEG(c);
+ m_bDHT = false;
+ m_seq = SEQ_FRAME;
+ } else {
+ m_seq = SEQ_INIT;
+ }
+ break;
+ case SEQ_FRAME:
+ if (c == 0xff) {
+ m_seq = SEQ_MARK;
+ } else {
+ m_seq = SEQ_INIT;
+ }
+ break;
+ case SEQ_MARK:
+ if (c == MARK_SOI || c == MARK_EOI || c == 0x00) {
+ m_seq = SEQ_INIT;
+ break;
+ }
+ m_mark = c;
+ m_seq = SEQ_SEG_LEN;
+ break;
+ case SEQ_SEG_LEN:
+ m_seg_len = c;
+ m_seq = SEQ_SEG_LEN2;
+ break;
+ case SEQ_SEG_LEN2:
+ m_seg_len <<= 8;
+ m_seg_len |= c;
+ m_seg_len -= 2;
+ m_seg_pos = 0;
+ m_seq = SEQ_SEG_BODY;
+ if (m_mark == MARK_SOS) {
+ if (m_bDHT == false) {
+ for(int i = 0; i < sizeof(dht); i++) {
+ outputJPEG(dht[i]);
+ }
+ }
+ m_output_desable = false;
+ } else if (m_mark == MARK_DHT) {
+ m_bDHT = true;
+ m_output_desable = false;
+ } else {
+ m_output_desable = false;
+ }
+ if (!m_output_desable) {
+ outputJPEG(0xff);
+ outputJPEG(m_mark);
+ outputJPEG((m_seg_len+2) >> 8);
+ outputJPEG((m_seg_len+2) & 0xff);
+ }
+ break;
+ case SEQ_SEG_BODY:
+ if (!m_output_desable) {
+ outputJPEG(c);
+ }
+ if (++m_seg_pos < m_seg_len) {
+ break;
+ }
+ if (m_mark == MARK_SOS) {
+ m_seq = SEQ_SOS;
+ break;
+ }
+ m_seq = SEQ_FRAME;
+ break;
+ case SEQ_SOS:
+ if (c == 0xff) {
+ m_seq = SEQ_SOS2;
+ break;
+ }
+ outputJPEG(c);
+ break;
+ case SEQ_SOS2:
+ if (c == 0x00) {
+ outputJPEG(0xff);
+ outputJPEG(0x00);
+ m_seq = SEQ_SOS;
+ break;
+ } else if (c >= MARK_RST0 && c <= MARK_RST7) {
+ outputJPEG(0xff);
+ outputJPEG(c);
+ m_seq = SEQ_SOS;
+ break;
+ } else if (c == MARK_EOI) {
+ outputJPEG(0xff);
+ outputJPEG(c, JPEG_END);
+ m_seq = SEQ_INIT;
+ break;
+ } else if (c == MARK_SOI) {
+ outputJPEG(0xff);
+ outputJPEG(c);
+ m_seq = SEQ_INIT;
+ break;
+ }
+ m_seq = SEQ_INIT;
+ break;
+ default:
+ m_seq = SEQ_INIT;
+ break;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostC270/decodeMJPEG.h Tue Jun 10 13:38:41 2014 +0900
@@ -0,0 +1,25 @@
+// decodeMJPEG.h 2012/12/9
+#ifndef DECODE_MJPEG_H
+#define DECODE_MJPEG_H
+
+#define JPEG_NONE 0
+#define JPEG_START 1
+#define JPEG_END 2
+#define JPEG_ERROR 3
+
+class decodeMJPEG {
+public:
+ decodeMJPEG();
+ void inputPacket(const uint8_t* buf, int len);
+ virtual void outputJPEG(uint8_t c, int status = JPEG_NONE) = 0;
+protected:
+ void input(uint8_t c);
+ int m_seq;
+ uint8_t m_mark;
+ uint16_t m_seg_pos;
+ uint16_t m_seg_len;
+ bool m_bDHT;
+ bool m_output_desable;
+};
+
+#endif // DECODE_MJPEG_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostGPS/USBHostGPS.cpp Tue Jun 10 13:38:41 2014 +0900
@@ -0,0 +1,98 @@
+#include "USBHostGPS.h"
+
+USBHostGPS::USBHostGPS(int baud_)
+{
+ host = USBHost::getHostInst();
+ init();
+ baud = baud_;
+}
+
+void USBHostGPS::init() {
+ dev = NULL;
+ bulk_in = NULL;
+ onUpdateRaw = NULL;
+ dev_connected = false;
+ gps_device_found = false;
+ gps_intf = -1;
+}
+
+bool USBHostGPS::connected() {
+ return dev_connected;
+}
+
+bool USBHostGPS::connect() {
+
+ if (dev_connected) {
+ return true;
+ }
+
+ for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
+ if ((dev = host->getDevice(i)) != NULL) {
+ if(host->enumerate(dev, this)) {
+ break;
+ }
+ if (gps_device_found) {
+ bulk_in = dev->getEndpoint(gps_intf, BULK_ENDPOINT, IN);
+ USB_TEST_ASSERT(bulk_in);
+ // stop bit = 1, parity = none, 8bit
+ uint8_t data[] = {baud&0xff, baud>>8, baud>>16, baud>>24, 0x00, 0x00, 0x08};
+ USB_TYPE rc = host->controlWrite(dev, 0x21, PL2303_SET_LINE_CODING, 0, 0, data, sizeof(data));
+ USB_TEST_ASSERT(rc == USB_TYPE_OK);
+ USB_INFO("New GPS device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, gps_intf);
+ bulk_in->attach(this, &USBHostGPS::rxHandler);
+ host->bulkRead(dev, bulk_in, bulk_buf, bulk_in->getSize(), false);
+
+ dev_connected = true;
+ return true;
+ }
+ }
+ }
+ init();
+ return false;
+}
+
+void USBHostGPS::rxHandler() {
+ int len = bulk_in->getLengthTransferred();
+ if (onUpdateRaw) {
+ (*onUpdateRaw)((char*)bulk_buf, len);
+ }
+ nmea.inputNMEA((char*)bulk_buf, len);
+
+ if (dev) {
+ host->bulkRead(dev, bulk_in, bulk_buf, bulk_in->getSize(), false);
+ }
+}
+
+/*virtual*/ void USBHostGPS::setVidPid(uint16_t vid, uint16_t pid)
+{
+ USB_DBG("vid:%04x pid:%04x", vid, pid);
+ if (pid == 0x2303) {
+ gps_device_found = true;
+ }
+}
+
+/*virtual*/ bool USBHostGPS::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
+{
+ USB_DBG("intf: %d class: %02x %02x %02x", intf_nb, intf_class, intf_subclass, intf_protocol);
+ if (gps_device_found) {
+ if (gps_intf == -1) {
+ gps_intf = intf_nb;
+ return true;
+ }
+ }
+ return false;
+}
+
+/*virtual*/ bool USBHostGPS::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
+{
+ USB_DBG("intf_nb=%d type=%d dir=%d", intf_nb, type, dir);
+ if (gps_device_found) {
+ if (intf_nb == gps_intf) {
+ if (type == BULK_ENDPOINT && dir == IN) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostGPS/USBHostGPS.h Tue Jun 10 13:38:41 2014 +0900
@@ -0,0 +1,60 @@
+// Simple USBHost GPS Dongle for FRDM-KL46Z
+#include "USBHost.h"
+#include "decodeNMEA.h"
+
+#define PL2303_SET_LINE_CODING 0x20
+
+class USBHostGPS : public IUSBEnumerator {
+public:
+
+ /**
+ * Constructor
+ */
+ USBHostGPS(int baud = 38400);
+
+ /**
+ * Try to connect a USB GPS device
+ *
+ * @return true if connection was successful
+ */
+ bool connect();
+
+ /**
+ * Check if a USB GPS is connected
+ *
+ * @returns true if a mouse is connected
+ */
+ bool connected();
+
+ int readNMEA(char* data, int size, int timeout_ms) {
+ host->bulkRead(dev, bulk_in, (uint8_t*)data, size);
+ return bulk_in->getLengthTransferred();
+ }
+ void attachEventRaw(void (*ptr)(char* data, int size)) {
+ if (ptr != NULL) {
+ onUpdateRaw = ptr;
+ }
+ }
+
+ decodeNMEA nmea;
+
+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:
+ USBHost * host;
+ USBDeviceConnected* dev;
+ USBEndpoint* bulk_in;
+ bool dev_connected;
+ bool gps_device_found;
+ int gps_intf;
+
+ void rxHandler();
+ void (*onUpdateRaw)(char* data, int size);
+ uint8_t bulk_buf[64];
+ int baud;
+ void init();
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostGPS/decodeNMEA.cpp Tue Jun 10 13:38:41 2014 +0900
@@ -0,0 +1,159 @@
+// decodeNMEA.cpp 2012/12/13
+#include "mbed.h"
+#include "decodeNMEA.h"
+
+#define SEQ_INIT 0
+#define SEQ_DATA 1
+#define SEQ_SUM0 2
+#define SEQ_SUM1 3
+
+#define GPGGA 1
+#define GPGLL 2
+#define GPGSV 3
+#define GPRMC 4
+#define GPVTG 5
+#define GPZDA 6
+
+decodeNMEA::decodeNMEA():m_seq(0) {
+ gprmc_t = 0;
+ update_t = 0;
+ m_status = false;
+}
+
+void decodeNMEA::inputNMEA(char* buf, int len) {
+ for(int i = 0; i < len; i++) {
+ inputNMEA(buf[i]);
+ }
+}
+
+static int ctoh(char c) {
+ if (c >= '0' && c <= '9') {
+ return c-'0';
+ }
+ return c-'A'+10;
+}
+
+void decodeNMEA::inputNMEA(char c) {
+ switch(m_seq) {
+ case SEQ_INIT:
+ if (c == '$') {
+ m_type = 0;
+ m_row = 0;
+ m_buf_pos = 0;
+ m_sum = 0x00;
+ m_seq = SEQ_DATA;
+ }
+ break;
+ case SEQ_DATA:
+ m_sum ^= c;
+ if (c == ',' || c == '*') {
+ m_buf[m_buf_pos] = '\0';
+ parse(m_type, m_row, m_buf);
+ m_row++;
+ m_buf_pos =0;
+ if (c == '*') { // check sum ?
+ m_sum ^= c;
+ m_seq = SEQ_SUM0;
+ }
+ } else {
+ if (m_buf_pos < sizeof(m_buf)-1) {
+ m_buf[m_buf_pos++] = c;
+ }
+ }
+ break;
+ case SEQ_SUM0:
+ if (ctoh(c) == (m_sum>>4)) {
+ m_seq = SEQ_SUM1;
+ } else {
+ m_seq = SEQ_INIT;
+ }
+ break;
+ case SEQ_SUM1:
+ if (ctoh(c) == (m_sum&0x0f)) {
+ update(m_type, m_row);
+ } else {
+
+ m_seq = SEQ_INIT;
+ }
+ break;
+ default:
+ m_seq = SEQ_INIT;
+ break;
+ }
+}
+
+float DMMtoDegree(const char *s)
+{
+ char *p = strchr(const_cast<char*>(s), '.');
+ if (p == NULL) {
+ return 0.0;
+ }
+ const uint32_t k[] = {10000,1000,100,10,1};
+ uint32_t i3 = atoi(p+1) * k[strlen(p+1)];
+ uint32_t i2 = atoi(p-2);
+ uint32_t i1 = atoi(s) / 100;
+
+ uint32_t i = i1*10000*60 + (i2*10000 + i3);
+ return i / 10000.0 / 60.0;
+}
+
+void decodeNMEA::parse(int type, int row, char* buf) {
+ if (row == 0) {
+ if (strcmp(buf, "GPRMC") == 0) {
+ m_type = GPRMC;
+ m_status = false;
+ } else {
+ m_type = 0;
+ }
+ return;
+ }
+ if (type == GPRMC) {
+ switch(row) {
+ case 1:
+ tmp_timeinfo.tm_sec = atoi(buf+4);
+ buf[4] = '\0';
+ tmp_timeinfo.tm_min = atoi(buf+2);
+ buf[2] = '\0';
+ tmp_timeinfo.tm_hour = atoi(buf);
+ break;
+ case 2:
+ if (buf[0] == 'A') {
+ m_status = true;
+ }
+ break;
+ case 3:
+ tmp_lat = DMMtoDegree(buf);
+ break;
+ case 4:
+ if (buf[0] == 'S') {
+ tmp_lat *= -1;
+ }
+ break;
+ case 5:
+ tmp_lon = DMMtoDegree(buf);
+ break;
+ case 6:
+ if (buf[0] == 'W') {
+ tmp_lon *= -1;
+ }
+ break;
+ case 9:
+ tmp_timeinfo.tm_year = 2000 - 1900 + atoi(buf+4);
+ buf[4] = '\0';
+ tmp_timeinfo.tm_mon = atoi(buf+2) - 1;
+ buf[2] = '\0';
+ tmp_timeinfo.tm_mday = atoi(buf);
+ break;
+ }
+ }
+}
+
+void decodeNMEA::update(int type, int row) {
+ if (type == GPRMC && m_status) {
+ lat = tmp_lat;
+ lon = tmp_lon;
+ gprmc_t = mktime(&tmp_timeinfo);
+ update_t = gprmc_t;
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostGPS/decodeNMEA.h Tue Jun 10 13:38:41 2014 +0900
@@ -0,0 +1,28 @@
+// decodeNMEA.h 2012/12/15
+#ifndef DECODE_NMEA_H
+#define DECODE_NMEA_H
+
+class decodeNMEA {
+public:
+ decodeNMEA();
+ void inputNMEA(char* buf, int len);
+ void inputNMEA(char c);
+ float lat,lon;
+ time_t gprmc_t;
+ time_t update_t;
+
+private:
+ void parse(int type, int row, char* buf);
+ void update(int type, int row);
+ int m_seq;
+ int m_type;
+ int m_row;
+ uint8_t m_sum;
+ char m_buf[12];
+ int m_buf_pos;
+ bool m_status;
+ float tmp_lat,tmp_lon;
+ struct tm tmp_timeinfo;
+};
+
+#endif // DECODE_NMEA_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostHID/USBHostKeyboard.cpp Tue Jun 10 13:38:41 2014 +0900
@@ -0,0 +1,184 @@
+/* mbed USBHost Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "USBHostKeyboard.h"
+
+#if USBHOST_KEYBOARD
+
+static uint8_t keymap[4][0x39] = {
+ { 0, 0, 0, 0, 'a', 'b' /*0x05*/,
+ 'c', 'd', 'e', 'f', 'g' /*0x0a*/,
+ 'h', 'i', 'j', 'k', 'l'/*0x0f*/,
+ 'm', 'n', 'o', 'p', 'q'/*0x14*/,
+ 'r', 's', 't', 'u', 'v'/*0x19*/,
+ 'w', 'x', 'y', 'z', '1'/*0x1E*/,
+ '2', '3', '4', '5', '6'/*0x23*/,
+ '7', '8', '9', '0', 0x0A /*enter*/, /*0x28*/
+ 0x1B /*escape*/, 0x08 /*backspace*/, 0x09/*tab*/, 0x20/*space*/, '-', /*0x2d*/
+ '=', '[', ']', '\\', '#', /*0x32*/
+ ';', '\'', 0, ',', '.', /*0x37*/
+ '/'},
+
+ /* CTRL MODIFIER */
+ { 0, 0, 0, 0, 0, 0 /*0x05*/,
+ 0, 0, 0, 0, 0 /*0x0a*/,
+ 0, 0, 0, 0, 0/*0x0f*/,
+ 0, 0, 0, 0, 0/*0x14*/,
+ 0, 0, 0, 0, 0/*0x19*/,
+ 0, 0, 0, 0, 0/*0x1E*/,
+ 0, 0, 0, 0, 0/*0x23*/,
+ 0, 0, 0, 0, 0 /*enter*/, /*0x28*/
+ 0, 0, 0, 0, 0, /*0x2d*/
+ 0, 0, 0, 0, 0, /*0x32*/
+ 0, 0, 0, 0, 0, /*0x37*/
+ 0},
+
+ /* SHIFT MODIFIER */
+ { 0, 0, 0, 0, 'A', 'B' /*0x05*/,
+ 'C', 'D', 'E', 'F', 'G' /*0x0a*/,
+ 'H', 'I', 'J', 'K', 'L'/*0x0f*/,
+ 'M', 'N', 'O', 'P', 'Q'/*0x14*/,
+ 'R', 'S', 'T', 'U', 'V'/*0x19*/,
+ 'W', 'X', 'Y', 'Z', '!'/*0x1E*/,
+ '@', '#', '$', '%', '^'/*0x23*/,
+ '&', '*', '(', ')', 0, /*0x28*/
+ 0, 0, 0, 0, 0, /*0x2d*/
+ '+', '{', '}', '|', '~', /*0x32*/
+ ':', '"', 0, '<', '>', /*0x37*/
+ '?'},
+
+ /* ALT MODIFIER */
+ { 0, 0, 0, 0, 0, 0 /*0x05*/,
+ 0, 0, 0, 0, 0 /*0x0a*/,
+ 0, 0, 0, 0, 0/*0x0f*/,
+ 0, 0, 0, 0, 0/*0x14*/,
+ 0, 0, 0, 0, 0/*0x19*/,
+ 0, 0, 0, 0, 0/*0x1E*/,
+ 0, 0, 0, 0, 0/*0x23*/,
+ 0, 0, 0, 0, 0 /*enter*/, /*0x28*/
+ 0, 0, 0, 0, 0, /*0x2d*/
+ 0, 0, 0, 0, 0, /*0x32*/
+ 0, 0, 0, 0, 0, /*0x37*/
+ 0}
+
+};
+
+
+USBHostKeyboard::USBHostKeyboard() {
+ host = USBHost::getHostInst();
+ init();
+}
+
+
+void USBHostKeyboard::init() {
+ dev = NULL;
+ int_in = NULL;
+ report_id = 0;
+ onKey = NULL;
+ onKeyCode = NULL;
+ dev_connected = false;
+ keyboard_intf = -1;
+ keyboard_device_found = false;
+}
+
+bool USBHostKeyboard::connected() {
+ return dev_connected;
+}
+
+
+bool USBHostKeyboard::connect() {
+
+ if (dev_connected) {
+ return true;
+ }
+
+ for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
+ if ((dev = host->getDevice(i)) != NULL) {
+
+ if (host->enumerate(dev, this))
+ break;
+
+ if (keyboard_device_found) {
+ int_in = dev->getEndpoint(keyboard_intf, INTERRUPT_ENDPOINT, IN);
+
+ if (!int_in)
+ break;
+
+ USB_INFO("New Keyboard device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, keyboard_intf);
+ dev->setName("Keyboard", keyboard_intf);
+ host->registerDriver(dev, keyboard_intf, this, &USBHostKeyboard::init);
+
+ int_in->attach(this, &USBHostKeyboard::rxHandler);
+ host->interruptRead(dev, int_in, report, int_in->getSize(), false);
+
+ dev_connected = true;
+ return true;
+ }
+ }
+ }
+ init();
+ return false;
+}
+
+void USBHostKeyboard::rxHandler() {
+ int len = int_in->getLengthTransferred();
+ int index = (len == 9) ? 1 : 0;
+ int len_listen = int_in->getSize();
+ uint8_t key = 0;
+ if (len == 8 || len == 9) {
+ uint8_t modifier = (report[index] == 4) ? 3 : report[index];
+ len_listen = len;
+ key = keymap[modifier][report[index + 2]];
+ if (key && onKey) {
+ (*onKey)(key);
+ }
+ if ((report[index + 2] || modifier) && onKeyCode) {
+ (*onKeyCode)(report[index + 2], modifier);
+ }
+ }
+ if (dev && int_in)
+ host->interruptRead(dev, int_in, report, len_listen, false);
+}
+
+/*virtual*/ void USBHostKeyboard::setVidPid(uint16_t vid, uint16_t pid)
+{
+ // we don't check VID/PID for keyboard driver
+}
+
+/*virtual*/ bool USBHostKeyboard::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
+{
+ if ((keyboard_intf == -1) &&
+ (intf_class == HID_CLASS) &&
+ (intf_subclass == 0x01) &&
+ (intf_protocol == 0x01)) {
+ keyboard_intf = intf_nb;
+ return true;
+ }
+ return false;
+}
+
+/*virtual*/ bool USBHostKeyboard::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
+{
+ if (intf_nb == keyboard_intf) {
+ if (type == INTERRUPT_ENDPOINT && dir == IN) {
+ keyboard_device_found = true;
+ return true;
+ }
+ }
+ return false;
+}
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostHID/USBHostKeyboard.h Tue Jun 10 13:38:41 2014 +0900
@@ -0,0 +1,102 @@
+/* mbed USBHost Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef USBHOSTKEYBOARD_H
+#define USBHOSTKEYBOARD_H
+
+#include "USBHostConf.h"
+
+#if USBHOST_KEYBOARD
+
+#include "USBHost.h"
+
+/**
+ * A class to communicate a USB keyboard
+ */
+class USBHostKeyboard : public IUSBEnumerator {
+public:
+
+ /**
+ * Constructor
+ */
+ USBHostKeyboard();
+
+ /**
+ * Try to connect a keyboard device
+ *
+ * @return true if connection was successful
+ */
+ bool connect();
+
+ /**
+ * Check if a keyboard is connected
+ *
+ * @returns true if a keyboard is connected
+ */
+ bool connected();
+
+ /**
+ * Attach a callback called when a keyboard event is received
+ *
+ * @param ptr function pointer
+ */
+ inline void attach(void (*ptr)(uint8_t key)) {
+ if (ptr != NULL) {
+ onKey = ptr;
+ }
+ }
+
+ /**
+ * Attach a callback called when a keyboard event is received
+ *
+ * @param ptr function pointer
+ */
+ inline void attach(void (*ptr)(uint8_t keyCode, uint8_t modifier)) {
+ if (ptr != NULL) {
+ onKeyCode = ptr;
+ }
+ }
+
+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:
+ USBHost * host;
+ USBDeviceConnected * dev;
+ USBEndpoint * int_in;
+ uint8_t report[9];
+ int keyboard_intf;
+ bool keyboard_device_found;
+
+ bool dev_connected;
+
+ void rxHandler();
+
+ void (*onKey)(uint8_t key);
+ void (*onKeyCode)(uint8_t key, uint8_t modifier);
+
+ int report_id;
+
+ void init();
+
+};
+
+#endif
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostHID/USBHostMouse.cpp Tue Jun 10 13:38:41 2014 +0900
@@ -0,0 +1,144 @@
+/* mbed USBHost Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "USBHostMouse.h"
+
+#if USBHOST_MOUSE
+
+USBHostMouse::USBHostMouse() {
+ host = USBHost::getHostInst();
+ init();
+}
+
+void USBHostMouse::init() {
+ dev = NULL;
+ int_in = NULL;
+ onUpdate = NULL;
+ onButtonUpdate = NULL;
+ onXUpdate = NULL;
+ onYUpdate = NULL;
+ onZUpdate = NULL;
+ report_id = 0;
+ dev_connected = false;
+ mouse_device_found = false;
+ mouse_intf = -1;
+
+ buttons = 0;
+ x = 0;
+ y = 0;
+ z = 0;
+}
+
+bool USBHostMouse::connected() {
+ return dev_connected;
+}
+
+bool USBHostMouse::connect() {
+
+ if (dev_connected) {
+ return true;
+ }
+
+ for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
+ if ((dev = host->getDevice(i)) != NULL) {
+
+ if(host->enumerate(dev, this))
+ break;
+
+ if (mouse_device_found) {
+
+ int_in = dev->getEndpoint(mouse_intf, INTERRUPT_ENDPOINT, IN);
+ if (!int_in)
+ break;
+
+ USB_INFO("New Mouse device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, mouse_intf);
+ dev->setName("Mouse", mouse_intf);
+ host->registerDriver(dev, mouse_intf, this, &USBHostMouse::init);
+
+ int_in->attach(this, &USBHostMouse::rxHandler);
+ host->interruptRead(dev, int_in, report, int_in->getSize(), false);
+
+ dev_connected = true;
+ return true;
+ }
+ }
+ }
+ init();
+ return false;
+}
+
+void USBHostMouse::rxHandler() {
+ int len_listen = int_in->getSize();
+
+ if (onUpdate) {
+ (*onUpdate)(report[0] & 0x07, report[1], report[2], report[3]);
+ }
+
+ if (onButtonUpdate && (buttons != (report[0] & 0x07))) {
+ (*onButtonUpdate)(report[0] & 0x07);
+ }
+
+ if (onXUpdate && (x != report[1])) {
+ (*onXUpdate)(report[1]);
+ }
+
+ if (onYUpdate && (y != report[2])) {
+ (*onYUpdate)(report[2]);
+ }
+
+ if (onZUpdate && (z != report[3])) {
+ (*onZUpdate)(report[3]);
+ }
+
+ // update mouse state
+ buttons = report[0] & 0x07;
+ x = report[1];
+ y = report[2];
+ z = report[3];
+
+ if (dev)
+ host->interruptRead(dev, int_in, report, len_listen, false);
+}
+
+/*virtual*/ void USBHostMouse::setVidPid(uint16_t vid, uint16_t pid)
+{
+ // we don't check VID/PID for mouse driver
+}
+
+/*virtual*/ bool USBHostMouse::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
+{
+ if ((mouse_intf == -1) &&
+ (intf_class == HID_CLASS) &&
+ (intf_subclass == 0x01) &&
+ (intf_protocol == 0x02)) {
+ mouse_intf = intf_nb;
+ return true;
+ }
+ return false;
+}
+
+/*virtual*/ bool USBHostMouse::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
+{
+ if (intf_nb == mouse_intf) {
+ if (type == INTERRUPT_ENDPOINT && dir == IN) {
+ mouse_device_found = true;
+ return true;
+ }
+ }
+ return false;
+}
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostHID/USBHostMouse.h Tue Jun 10 13:38:41 2014 +0900
@@ -0,0 +1,139 @@
+/* mbed USBHost Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef USBHOSTMOUSE_H
+#define USBHOSTMOUSE_H
+
+#include "USBHostConf.h"
+
+#if USBHOST_MOUSE
+
+#include "USBHost.h"
+
+/**
+ * A class to communicate a USB mouse
+ */
+class USBHostMouse : public IUSBEnumerator {
+public:
+
+ /**
+ * Constructor
+ */
+ USBHostMouse();
+
+ /**
+ * Try to connect a mouse device
+ *
+ * @return true if connection was successful
+ */
+ bool connect();
+
+ /**
+ * Check if a mouse is connected
+ *
+ * @returns true if a mouse is connected
+ */
+ bool connected();
+
+ /**
+ * Attach a callback called when a mouse event is received
+ *
+ * @param ptr function pointer
+ */
+ inline void attachEvent(void (*ptr)(uint8_t buttons, int8_t x, int8_t y, int8_t z)) {
+ if (ptr != NULL) {
+ onUpdate = ptr;
+ }
+ }
+
+ /**
+ * Attach a callback called when the button state changes
+ *
+ * @param ptr function pointer
+ */
+ inline void attachButtonEvent(void (*ptr)(uint8_t buttons)) {
+ if (ptr != NULL) {
+ onButtonUpdate = ptr;
+ }
+ }
+
+ /**
+ * Attach a callback called when the X axis value changes
+ *
+ * @param ptr function pointer
+ */
+ inline void attachXEvent(void (*ptr)(int8_t x)) {
+ if (ptr != NULL) {
+ onXUpdate = ptr;
+ }
+ }
+
+ /**
+ * Attach a callback called when the Y axis value changes
+ *
+ * @param ptr function pointer
+ */
+ inline void attachYEvent(void (*ptr)(int8_t y)) {
+ if (ptr != NULL) {
+ onYUpdate = ptr;
+ }
+ }
+
+ /**
+ * Attach a callback called when the Z axis value changes (scrolling)
+ *
+ * @param ptr function pointer
+ */
+ inline void attachZEvent(void (*ptr)(int8_t z)) {
+ if (ptr != NULL) {
+ onZUpdate = ptr;
+ }
+ }
+
+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:
+ USBHost * host;
+ USBDeviceConnected * dev;
+ USBEndpoint * int_in;
+ uint8_t report[4];
+
+ bool dev_connected;
+ bool mouse_device_found;
+ int mouse_intf;
+
+ uint8_t buttons;
+ int8_t x;
+ int8_t y;
+ int8_t z;
+
+ void rxHandler();
+ void (*onUpdate)(uint8_t buttons, int8_t x, int8_t y, int8_t z);
+ void (*onButtonUpdate)(uint8_t buttons);
+ void (*onXUpdate)(int8_t x);
+ void (*onYUpdate)(int8_t y);
+ void (*onZUpdate)(int8_t z);
+ int report_id;
+ void init();
+};
+
+#endif
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostRSSI/USBHostRSSI.cpp Tue Jun 10 13:38:41 2014 +0900
@@ -0,0 +1,191 @@
+#include "USBHostRSSI.h"
+
+USBHostRSSI::USBHostRSSI()
+{
+ host = USBHost::getHostInst();
+ init();
+}
+
+void USBHostRSSI::init()
+{
+ dev = NULL;
+ int_in = NULL;
+ onUpdate = NULL;
+ dev_connected = false;
+ bluetooth_device_found = false;
+ bluetooth_intf = -1;
+ seq = 0;
+
+}
+
+bool USBHostRSSI::connected() {
+ return dev_connected;
+}
+
+bool USBHostRSSI::connect() {
+
+ if (dev_connected) {
+ return true;
+ }
+
+ for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
+ if ((dev = host->getDevice(i)) != NULL) {
+ if(host->enumerate(dev, this)) {
+ break;
+ }
+ if (bluetooth_device_found) {
+ int_in = dev->getEndpoint(bluetooth_intf, INTERRUPT_ENDPOINT, IN);
+ USB_DBG("int_in=%p", int_in);
+ if (!int_in) {
+ break;
+ }
+ USB_INFO("New Bluetooth device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, bluetooth_intf);
+ int_in->attach(this, &USBHostRSSI::rxHandler);
+ int rc = host->interruptRead(dev, int_in, int_buf, sizeof(int_buf), false);
+ USB_TEST_ASSERT(rc != USB_TYPE_ERROR);
+ rc = cmdSend(HCI_OP_RESET);
+ USB_TEST_ASSERT(rc == USB_TYPE_OK);
+ dev_connected = true;
+ return true;
+ }
+ }
+ }
+ init();
+ return false;
+}
+
+void USBHostRSSI::rxHandler() {
+ event(int_buf, int_in->getLengthTransferred());
+ if (dev) {
+ host->interruptRead(dev, int_in, int_buf, sizeof(int_buf), false);
+ }
+}
+
+/*virtual*/ void USBHostRSSI::setVidPid(uint16_t vid, uint16_t pid)
+{
+ USB_DBG("vid:%04x pid:%04x", vid, pid);
+ // we don't check VID/PID for mouse driver
+}
+
+/*virtual*/ bool USBHostRSSI::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
+{
+ USB_DBG("intf: %d class: %02x %02x %02x", intf_nb, intf_class, intf_subclass, intf_protocol);
+ if (bluetooth_intf == -1 && intf_class == 0xe0) {
+ bluetooth_intf = intf_nb;
+ return true;
+ }
+ return false;
+}
+
+/*virtual*/ bool USBHostRSSI::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
+{
+ USB_DBG("intf_nb=%d type=%d dir=%d", intf_nb, type, dir);
+
+ if (intf_nb == bluetooth_intf) {
+ if (type == INTERRUPT_ENDPOINT && dir == IN) {
+ bluetooth_device_found = true;
+ return true;
+ }
+ }
+ return false;
+}
+
+void USBHostRSSI::event(uint8_t* data, int len) {
+ CTASSERT(sizeof(BD_ADDR) == 6);
+ CTASSERT(sizeof(inquiry_with_rssi_info) == 14);
+ inquiry_with_rssi_info* info;
+ int max_period_length = 25;
+ int min_period_length = 20;
+ int inquiry_length = 15;
+ USB_TYPE rc;
+ if (len > 0) {
+ USB_DBG_HEX(data, len);
+ hci_event* event = reinterpret_cast<hci_event*>(data);
+ switch(event->evt) {
+ case HCI_EV_CMD_COMPLETE:
+ switch(event->c.op) {
+ case HCI_OP_RESET:
+ wait_ms(500);
+ rc = cmdSend(HCI_OP_WRITE_INQUIRY_MODE, "B", 0x01); // with RSSI
+ USB_TEST_ASSERT(rc == USB_TYPE_OK);
+ break;
+ case HCI_OP_WRITE_INQUIRY_MODE:
+ rc = cmdSend(HCI_OP_PERIODIC_INQUIRY, "HHBBBBB",
+ max_period_length, min_period_length, 0x33, 0x8B, 0x9E, inquiry_length, 0);
+ USB_TEST_ASSERT(rc == USB_TYPE_OK);
+ break;
+ default:
+ break;
+ }
+ break;
+ case HCI_EV_INQUIRY_RESULT_WITH_RSSI:
+ //USB_DBG_HEX(buf, r);
+ info = reinterpret_cast<inquiry_with_rssi_info*>(event->c.data);
+ if (onUpdate) {
+ (*onUpdate)(info);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+USB_TYPE USBHostRSSI::cmdSend(uint16_t op)
+{
+ return cmdSendSub(op, NULL, 0);
+}
+
+USB_TYPE USBHostRSSI::cmdSend(uint16_t op, const char* fmt, ...)
+{
+ va_list vl;
+ va_start(vl, fmt);
+ uint8_t buf[255];
+ int pos = 0;
+ char* name;
+ int name_len;
+ uint16_t h;
+ BD_ADDR* bdaddr;
+ for(int i = 0; fmt[i]; i++) {
+ switch(fmt[i]) {
+ case 's':
+ name = va_arg(vl, char*);
+ name_len = strlen(name)+1;
+ memcpy(buf+pos, name, name_len);
+ pos += name_len;
+ break;
+ case 'B':
+ buf[pos++] = va_arg(vl, int);
+ break;
+ case 'H':
+ h = va_arg(vl, int);
+ buf[pos++] = h;
+ buf[pos++] = h>>8;
+ break;
+ case 'A':
+ bdaddr = va_arg(vl, BD_ADDR*);
+ memcpy(buf+pos, bdaddr, 6);
+ pos += 6;
+ break;
+ default:
+ USB_DBG("op=%04X fmt=%s i=%d", op, fmt, i);
+ break;
+ }
+ }
+ return cmdSendSub(op, buf, pos);
+}
+
+USB_TYPE USBHostRSSI::cmdSendSub(uint16_t op, const uint8_t* data, int size)
+{
+ uint8_t* buf = new uint8_t[size+3];
+ buf[0] = op;
+ buf[1] = op>>8;
+ buf[2] = size;
+ if (data) {
+ memcpy(buf+3, data, size);
+ }
+ USB_TYPE rc = host->controlWrite(dev, USB_REQUEST_TYPE_CLASS, 0, 0, 0, buf, size+3);
+ USB_TEST_ASSERT(rc == USB_TYPE_OK);
+ delete[] buf;
+ return rc;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostRSSI/USBHostRSSI.h Tue Jun 10 13:38:41 2014 +0900
@@ -0,0 +1,145 @@
+// Simple USBHost Bluetooth RSSI for FRDM-KL46Z
+#pragma once
+#include "USBHost.h"
+#include <stdarg.h>
+
+#define HCI_OP_INQUIRY 0x0401
+#define HCI_OP_INQUIRY_CANCEL 0x0402
+#define HCI_OP_PERIODIC_INQUIRY 0x0403
+#define HCI_OP_EXIT_PERIODIC_INQUIRY 0x0404
+#define HCI_OP_REMOTE_NAME_REQ 0x0419
+#define HCI_OP_RESET 0x0c03
+#define HCI_OP_WRITE_LOCAL_NAME 0x0c13
+#define HCI_OP_WRITE_SCAN_ENABLE 0x0c1a
+#define HCI_OP_WRITE_CLASS_OF_DEV 0x0c24
+#define HCI_OP_WRITE_INQUIRY_MODE 0x0c45
+#define HCI_OP_READ_EXTENDED_INQUIRY_RESPONSE 0x0c51
+#define HCI_OP_WRITE_EXTENDED_INQUIRY_RESPONSE 0x0c52
+#define HCI_OP_READ_BD_ADDR 0x1009
+
+#define HCI_EV_INQUIRY_COMPLETE 0x01
+#define HCI_EV_INQUIRY_RESULT 0x02
+#define HCI_EV_REMOTE_NAME 0x07
+#define HCI_EV_CMD_COMPLETE 0x0e
+#define HCI_EV_CMD_STATUS 0x0f
+#define HCI_EV_INQUIRY_RESULT_WITH_RSSI 0x22
+#define HCI_EV_EXTENDED_INQUIRY_RESULT 0x2f
+
+#pragma pack(push,1)
+struct BD_ADDR {
+ uint8_t addr[6];
+ void set(char* s) {
+ char* p = s;
+ for(int i = 5; i >= 0; i--) {
+ addr[i] = strtol(p, &p, 16);
+ if (*p == ':') {
+ p++;
+ }
+ }
+ }
+ void str(char* buf, size_t size) {
+ snprintf(buf, size, "%02X:%02X:%02X:%02X:%02X:%02X", addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
+ }
+ void str_mask(char* buf, size_t size) {
+ snprintf(buf, size, "%02X:%02X:%02X:xx:xx:xx", addr[5], addr[4], addr[3]);
+ }
+ bool eq(BD_ADDR* a) {
+ return memcmp(addr, a->addr, 6) == 0;
+ }
+ bool eq_vendor(BD_ADDR* a) {
+ return memcmp(addr+3, a->addr+3, 3) == 0;
+ }
+};
+
+struct inquiry_info {
+ BD_ADDR bdaddr;
+ uint8_t page_scan_repetition_mode;
+ uint8_t reserved[2];
+ uint8_t dev_class[3];
+ uint16_t clock_offset;
+};
+
+struct inquiry_with_rssi_info { // offset
+ BD_ADDR bdaddr; // +0
+ uint8_t page_scan_repetition_mode;// +6
+ uint8_t reserved[1]; // +7
+ uint8_t class_of_device[3]; // +8
+ uint16_t clock_offset; // +11
+ int8_t rssi; // +13
+}; // +14
+
+struct extended_inquiry_info {
+ BD_ADDR bdaddr;
+ uint8_t page_scan_repetition_mode;
+ uint8_t reserved[1];
+ uint8_t class_of_device[3];
+ uint16_t clock_offset;
+ int8_t rssi;
+ uint8_t extended_inquiry_response[240];
+};
+
+struct hci_event {
+ uint8_t evt;
+ uint8_t len;
+ uint8_t status;
+ union {
+ uint16_t op;
+ uint8_t data[];
+ } c;
+};
+#pragma pack(pop)
+
+class USBHostRSSI : public IUSBEnumerator {
+public:
+
+ /**
+ * Constructor
+ */
+ USBHostRSSI();
+
+ /**
+ * Try to connect a BT device
+ *
+ * @return true if connection was successful
+ */
+ bool connect();
+
+ /**
+ * Check if a mouse is connected
+ *
+ * @returns true if a BT is connected
+ */
+ bool connected();
+
+ void attachEvent(void (*ptr)(inquiry_with_rssi_info* info)) {
+ if (ptr != NULL) {
+ onUpdate = ptr;
+ }
+ }
+ //Report* report;
+
+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:
+ USBHost * host;
+ USBDeviceConnected * dev;
+ USBEndpoint * int_in;
+ bool dev_connected;
+ bool bluetooth_device_found;
+ int bluetooth_intf;
+
+ void rxHandler();
+ void (*onUpdate)(inquiry_with_rssi_info* info);
+ uint8_t int_buf[64];
+ int seq;
+ void event(uint8_t* data, int size);
+ USB_TYPE cmdSend(uint16_t op);
+ USB_TYPE cmdSend(uint16_t op, const char* fmt, ...);
+ USB_TYPE cmdSendSub(uint16_t op, const uint8_t* data, int size);
+ void init();
+};
+
