Last active
May 26, 2016 13:46
-
-
Save avtolstoy/083b6ea8ca9188c0742e9aee2d516b9b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
****************************************************************************** | |
* Copyright (c) 2015 Particle Industries, Inc. All rights reserved. | |
* | |
* This library is free software; you can redistribute it and/or | |
* modify it under the terms of the GNU Lesser General Public | |
* License as published by the Free Software Foundation, either | |
* version 3 of the License, or (at your option) any later version. | |
* | |
* This library is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
* Lesser General Public License for more details. | |
* | |
* You should have received a copy of the GNU Lesser General Public | |
* License along with this library; if not, see <http://www.gnu.org/licenses/>. | |
****************************************************************************** | |
*/ | |
#include "application.h" | |
#include "deviceid_hal.h" | |
uint8_t handleVendorRequest(HAL_USB_SetupRequest* req); | |
STARTUP(HAL_USB_Set_Vendor_Request_Callback(&handleVendorRequest, NULL)); | |
Serial1LogHandler dbg(57600, LOG_LEVEL_ALL); | |
/* | |
* Use usbtool (https://github.com/avtolstoy/usbtool) to test requests. | |
* | |
* IN requests are Device -> Host (if wLength != 0, the data will be transmitted from device to the host) | |
* OUT requests are Host -> Device (if wLength != 0, the data will be transmitted from host to device) | |
* $ ./usbtool -v <VID> -p <PID> control <"in"|"out"> vendor device <bRequest> <wValue> <wIndex> | |
* | |
* REQUEST_GET_DEVICE_ID: | |
* $ ./usbtool -v 0x2b04 -p 0xc006 control in vendor device 0 0 0 | |
* | |
* REQUST_GET_DEVICE_ID as string (wValue = 1): | |
* $ ./usbtool -b -v 0x2b04 -p 0xc006 control in vendor device 0 1 0 | |
* | |
* REQUEST_ENTER_MODE ENTER_MODE_DFU: | |
* $ ./usbtool -v 0x2b04 -p 0xc006 control out vendor device 1 0 1 | |
* | |
* Transfer some data to the device | |
* $ ./usbtool -d 0x00,0x01,0x02,0x03,0x04,0x05,0x06 -v 0x2b04 -p 0xc006 control out vendor device 10 10 10 | |
* 0000004559 app: application.cpp:113, handleVendorRequest(): INFO: Request Host->Dev bmRequestType=0x40 bRequest=0xa wValue=0xa wIndex=0xa wLength=0x6 | |
* 0000004559 app: application.cpp:120, handleVendorRequest(): INFO: Request data=000102040506 | |
*/ | |
enum SetupRequest { | |
REQUEST_GET_DEVICE_ID = 0x00, | |
REQUEST_ENTER_MODE = 0x01, | |
#if Wiring_WiFi | |
REQUEST_GET_WIFI_PARAMETER = 0x02, | |
REQUEST_SET_WIFI_PARAMETER = 0x03, | |
#endif | |
#if Wiring_Cellular | |
REQUEST_GET_CELLULAR_PARAMETER = 0x05, | |
#endif | |
}; | |
enum EnterMode { | |
ENTER_MODE_SAFE_MODE = 0x00, | |
ENTER_MODE_DFU = 0x01, | |
ENTER_MODE_YMODEM = 0x02, | |
}; | |
#if Wiring_WiFi | |
enum WifiParameter { | |
WIFI_PARAMETER_SSID = 0x00, | |
WIFI_PARAMETER_MAC_ADDRESS = 0x01, | |
}; | |
#endif | |
#if Wiring_Cellular | |
enum CellularParameter { | |
CELLULAR_PARAMETER_IMEI = 0x00, | |
CELLULAR_PARAMETER_ICCID = 0x01, | |
}; | |
#endif | |
/* executes once at startup */ | |
void setup() { | |
Serial.begin(9600); | |
} | |
/* executes continuously after setup() runs */ | |
void loop() { | |
Serial.println("Alive"); | |
delay(1000); | |
} | |
inline void concat_nibble(String& result, uint8_t nibble) | |
{ | |
char hex_digit = nibble + 48; | |
if (57 < hex_digit) | |
hex_digit += 39; | |
result.concat(hex_digit); | |
} | |
String bytes2hex(const uint8_t* buf, unsigned len) | |
{ | |
String result; | |
for (unsigned i = 0; i < len; ++i) | |
{ | |
concat_nibble(result, (buf[i] >> 4)); | |
concat_nibble(result, (buf[i] & 0xF)); | |
} | |
return result; | |
} | |
// Will be called from USB interrupt handler | |
uint8_t handleVendorRequest(HAL_USB_SetupRequest* req) { | |
INFO("Request %s bmRequestType=0x%x bRequest=0x%x wValue=0x%x wIndex=0x%x wLength=0x%x", req->bmRequestType & 0x80 ? "Dev->Host" : "Host->Dev", | |
req->bmRequestType, req->bRequest, req->wValue, | |
req->wIndex, req->wLength); | |
// Direction = OUT (Host -> Device) | |
if (!req->bmRequestTypeDirection && req->wLength > 0) { | |
// Host->Device | |
INFO("Request data=%s", bytes2hex(req->data, req->wLength).c_str()); | |
} | |
if (req->data) { | |
memset(req->data, 0, HAL_USB_SETUP_REQUEST_MAX_DATA); | |
} | |
uint8_t ret = 0; | |
// OUT (Host -> Device) requests | |
if (!req->bmRequestTypeDirection) { | |
switch(req->bRequest) { | |
case REQUEST_ENTER_MODE: { | |
switch(req->wIndex) { | |
case ENTER_MODE_SAFE_MODE: | |
System.enterSafeMode(); | |
break; | |
case ENTER_MODE_DFU: | |
System.dfu(); | |
break; | |
case ENTER_MODE_YMODEM: | |
// ? | |
break; | |
default: | |
ret = 0; | |
break; | |
} | |
} | |
break; | |
default: | |
ret = 1; | |
break; | |
} | |
} else { | |
// IN (Device -> Host) requests | |
switch (req->bRequest) { | |
case REQUEST_GET_DEVICE_ID: | |
if (req->data) { | |
if (req->wValue == 1) { | |
String id = System.deviceID(); | |
strncpy((char*)req->data, id.c_str(), req->wLength); | |
req->wLength = id.length() + 1; | |
} else { | |
HAL_device_ID(req->data, req->wLength); | |
req->wLength = 12; | |
} | |
} | |
break; | |
#if Wiring_WiFi | |
case REQUEST_GET_WIFI_PARAMETER: { | |
switch(req->wIndex) { | |
case WIFI_PARAMETER_MAC_ADDRESS: | |
if (req->data) { | |
WiFi.macAddress(req->data); | |
req->wLength = 6; | |
} | |
break; | |
case WIFI_PARAMETER_SSID: | |
if (req->data) { | |
strncpy((char*)req->data, WiFi.SSID(), req->wLength); | |
req->wLength = strlen(WiFi.SSID()) + 1; | |
} | |
break; | |
default: | |
ret = 1; | |
break; | |
} | |
} | |
break; | |
#endif // Wiring_WiFi | |
#if Wiring_Cellular | |
case REQUEST_GET_CELLULAR_PARAMETER: { | |
CellularDevice dev; | |
cellular_device_info(&dev, NULL); | |
switch(req->wIndex) { | |
case CELLULAR_PARAMETER_IMEI: | |
if (req->data) | |
strncpy((char*)req->data, dev.imei, req->wLength); | |
req->wLength = strlen(dev.imei) + 1; | |
break; | |
case CELLULAR_PARAMETER_ICCID: | |
if (req->data) | |
strncpy((char*)req->data, dev.iccid, req->wLength); | |
req->wLength = strlen(dev.iccid) + 1; | |
break; | |
default: | |
ret = 1; | |
break; | |
} | |
} | |
break; | |
#endif // Wiring_Cellular | |
default: | |
ret = 1; | |
break; | |
} | |
} | |
return ret; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment