Merge pull request #23 from yamori813/master
Add Mac OS X native HID transport support.
This commit is contained in:
commit
9114125216
9
Makefile
9
Makefile
|
@ -38,6 +38,8 @@ else
|
||||||
CONSOLE_INPUT_OBJ = ui/input_readline.o
|
CONSOLE_INPUT_OBJ = ui/input_readline.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
BSLHID_OBJ ?= transport/bslhid.o
|
||||||
|
|
||||||
ifeq ($(OS),Windows_NT)
|
ifeq ($(OS),Windows_NT)
|
||||||
MSPDEBUG_CC = $(CC)
|
MSPDEBUG_CC = $(CC)
|
||||||
BINARY = mspdebug.exe
|
BINARY = mspdebug.exe
|
||||||
|
@ -68,8 +70,9 @@ else
|
||||||
PORTS_LDFLAGS := $(shell pkg-config --libs libusb) -ltermcap -pthread
|
PORTS_LDFLAGS := $(shell pkg-config --libs libusb) -ltermcap -pthread
|
||||||
else
|
else
|
||||||
PORTS_CFLAGS := -I/opt/local/include
|
PORTS_CFLAGS := -I/opt/local/include
|
||||||
PORTS_LDFLAGS := -L/opt/local/lib
|
PORTS_LDFLAGS := -L/opt/local/lib -framework IOKit -framework CoreFoundation
|
||||||
endif
|
endif
|
||||||
|
BSLHID_OBJ = transport/bslosx.o
|
||||||
else ifneq ($(filter $(UNAME_S),OpenBSD NetBSD DragonFly),)
|
else ifneq ($(filter $(UNAME_S),OpenBSD NetBSD DragonFly),)
|
||||||
PORTS_CFLAGS := $(shell pkg-config --cflags libusb)
|
PORTS_CFLAGS := $(shell pkg-config --cflags libusb)
|
||||||
PORTS_LDFLAGS := $(shell pkg-config --libs libusb) -ltermcap -pthread
|
PORTS_LDFLAGS := $(shell pkg-config --libs libusb) -ltermcap -pthread
|
||||||
|
@ -84,7 +87,7 @@ GCC_CFLAGS = -O1 -Wall -Wno-char-subscripts -ggdb
|
||||||
CONFIG_CFLAGS = -DLIB_DIR=\"$(LIBDIR)\"
|
CONFIG_CFLAGS = -DLIB_DIR=\"$(LIBDIR)\"
|
||||||
|
|
||||||
MSPDEBUG_LDFLAGS = $(LDFLAGS) $(PORTS_LDFLAGS)
|
MSPDEBUG_LDFLAGS = $(LDFLAGS) $(PORTS_LDFLAGS)
|
||||||
MSPDEBUG_LIBS = -lusb $(READLINE_LIBS) $(OS_LIBS)
|
MSPDEBUG_LIBS = -L. -lusb $(READLINE_LIBS) $(OS_LIBS)
|
||||||
MSPDEBUG_CFLAGS = $(CFLAGS) $(READLINE_CFLAGS) $(PORTS_CFLAGS)\
|
MSPDEBUG_CFLAGS = $(CFLAGS) $(READLINE_CFLAGS) $(PORTS_CFLAGS)\
|
||||||
$(GCC_CFLAGS) $(INCLUDES) $(CONFIG_CFLAGS) $(OS_CFLAGS)
|
$(GCC_CFLAGS) $(INCLUDES) $(CONFIG_CFLAGS) $(OS_CFLAGS)
|
||||||
|
|
||||||
|
@ -150,7 +153,7 @@ OBJ=\
|
||||||
transport/rf2500.o \
|
transport/rf2500.o \
|
||||||
transport/ti3410.o \
|
transport/ti3410.o \
|
||||||
transport/comport.o \
|
transport/comport.o \
|
||||||
transport/bslhid.o \
|
$(BSLHID_OBJ) \
|
||||||
drivers/device.o \
|
drivers/device.o \
|
||||||
drivers/bsl.o \
|
drivers/bsl.o \
|
||||||
drivers/fet.o \
|
drivers/fet.o \
|
||||||
|
|
|
@ -432,7 +432,11 @@ static device_t loadbsl_open(const struct device_args *args)
|
||||||
dev->base.type = &device_loadbsl;
|
dev->base.type = &device_loadbsl;
|
||||||
dev->base.max_breakpoints = 0;
|
dev->base.max_breakpoints = 0;
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
dev->trans = bslosx_open(args->path, args->requested_serial);
|
||||||
|
#else
|
||||||
dev->trans = bslhid_open(args->path, args->requested_serial);
|
dev->trans = bslhid_open(args->path, args->requested_serial);
|
||||||
|
#endif
|
||||||
if (!dev->trans) {
|
if (!dev->trans) {
|
||||||
free(dev);
|
free(dev);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -25,6 +25,10 @@
|
||||||
* protocol. The interface is described in SLAU319C: "MSP430 Programming
|
* protocol. The interface is described in SLAU319C: "MSP430 Programming
|
||||||
* via the Bootstrap Loader".
|
* via the Bootstrap Loader".
|
||||||
*/
|
*/
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
transport_t bslosx_open(const char *dev_path, const char *requested_serial);
|
||||||
|
#else
|
||||||
transport_t bslhid_open(const char *dev_path, const char *requested_serial);
|
transport_t bslhid_open(const char *dev_path, const char *requested_serial);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,284 @@
|
||||||
|
/* MSPDebug - debugging tool for MSP430 MCUs
|
||||||
|
* Copyright (C) 2009-2013 Daniel Beer
|
||||||
|
* Copyright (C) 2016 Hiroki Mori
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <usb.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <IOKit/hid/IOHIDManager.h>
|
||||||
|
#include <IOKit/hid/IOHIDKeys.h>
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
#include "usbutil.h"
|
||||||
|
#include "output.h"
|
||||||
|
#include "output_util.h"
|
||||||
|
#include "bslhid.h"
|
||||||
|
|
||||||
|
#define BSLHID_VID 0x2047
|
||||||
|
#define BSLHID_PID 0x0200
|
||||||
|
|
||||||
|
#define BSLHID_CLASS USB_CLASS_HID
|
||||||
|
|
||||||
|
#define BSLHID_XFER_SIZE 64
|
||||||
|
#define BSLHID_MTU (BSLHID_XFER_SIZE - 2)
|
||||||
|
#define BSLHID_HEADER 0x3F
|
||||||
|
#define BSLHID_TIMEOUT 5000
|
||||||
|
|
||||||
|
struct bslosx_transport {
|
||||||
|
struct transport base;
|
||||||
|
|
||||||
|
int cfg_number;
|
||||||
|
int int_number;
|
||||||
|
|
||||||
|
IOHIDDeviceRef refDevice;
|
||||||
|
|
||||||
|
char bus_name[PATH_MAX + 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
static void bslosx_destroy(transport_t base)
|
||||||
|
{
|
||||||
|
struct bslosx_transport *tr = (struct bslosx_transport *)base;
|
||||||
|
|
||||||
|
if (tr->refDevice) {
|
||||||
|
IOHIDDeviceClose(tr->refDevice, kIOHIDOptionsTypeNone);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(tr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bslosx_flush(transport_t base)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bslosx_send(transport_t base, const uint8_t *data, int len)
|
||||||
|
{
|
||||||
|
struct bslosx_transport *tr = (struct bslosx_transport *)base;
|
||||||
|
uint8_t outbuf[BSLHID_XFER_SIZE];
|
||||||
|
|
||||||
|
if (!tr->refDevice) {
|
||||||
|
printc_err("bslosx: send on suspended device\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(outbuf, 0xac, sizeof(outbuf));
|
||||||
|
|
||||||
|
if (len > BSLHID_MTU) {
|
||||||
|
printc_err("bslosx: send in excess of MTU: %d\n", len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
outbuf[0] = BSLHID_HEADER;
|
||||||
|
outbuf[1] = len;
|
||||||
|
memcpy(outbuf + 2, data, len);
|
||||||
|
|
||||||
|
#ifdef DEBUG_BSLHID
|
||||||
|
debug_hexdump("bslosx_send", outbuf, sizeof(outbuf));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
IOReturn ret = IOHIDDeviceSetReport(tr->refDevice, kIOHIDReportTypeOutput, 0, outbuf, BSLHID_XFER_SIZE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int g_readBytes;
|
||||||
|
|
||||||
|
static void reportCallback(void *inContext, IOReturn inResult, void *inSender,
|
||||||
|
IOHIDReportType inType, uint32_t inReportID,
|
||||||
|
uint8_t *inReport, CFIndex InReportLength)
|
||||||
|
{
|
||||||
|
g_readBytes = InReportLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bslosx_recv(transport_t base, uint8_t *data, int max_len)
|
||||||
|
{
|
||||||
|
struct bslosx_transport *tr = (struct bslosx_transport *)base;
|
||||||
|
uint8_t inbuf[BSLHID_XFER_SIZE];
|
||||||
|
int r;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (!tr->refDevice) {
|
||||||
|
printc_err("bslosx: recv on suspended device\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOHIDDeviceRegisterInputReportCallback(tr->refDevice,
|
||||||
|
&inbuf,
|
||||||
|
BSLHID_XFER_SIZE,
|
||||||
|
reportCallback,
|
||||||
|
NULL);
|
||||||
|
g_readBytes = -1;
|
||||||
|
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, false);
|
||||||
|
|
||||||
|
r = g_readBytes;
|
||||||
|
if (r <= 0) {
|
||||||
|
printc_err("bslosx_recv: usb_bulk_read no data\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_BSLHID
|
||||||
|
debug_hexdump("bslosx_recv", inbuf, r);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (r < 2) {
|
||||||
|
printc_err("bslosx_recv: short transfer\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inbuf[0] != BSLHID_HEADER) {
|
||||||
|
printc_err("bslosx_recv: missing transfer header\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = inbuf[1];
|
||||||
|
if ((len > max_len) || (len + 2 > r)) {
|
||||||
|
printc_err("bslosx_recv: bad length: %d (%d byte transfer)\n",
|
||||||
|
len, r);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(data, inbuf + 2, len);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bslosx_set_modem(transport_t base, transport_modem_t state)
|
||||||
|
{
|
||||||
|
printc_err("bslosx: unsupported operation: set_modem\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bslosx_suspend(transport_t base)
|
||||||
|
{
|
||||||
|
struct bslosx_transport *tr = (struct bslosx_transport *)base;
|
||||||
|
|
||||||
|
if (tr->refDevice) {
|
||||||
|
IOHIDDeviceClose(tr->refDevice, kIOHIDOptionsTypeNone);
|
||||||
|
tr->refDevice = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct usb_bus *find_by_name(const char *name)
|
||||||
|
{
|
||||||
|
struct usb_bus *b;
|
||||||
|
|
||||||
|
for (b = usb_get_busses(); b; b = b->next)
|
||||||
|
if (!strcmp(name, b->dirname))
|
||||||
|
return b;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct usb_device *find_first_bsl(struct usb_bus *bus)
|
||||||
|
{
|
||||||
|
struct usb_device *d;
|
||||||
|
|
||||||
|
for (d = bus->devices; d; d = d->next)
|
||||||
|
if ((d->descriptor.idVendor == BSLHID_VID) &&
|
||||||
|
(d->descriptor.idProduct == BSLHID_PID))
|
||||||
|
return d;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bslosx_resume(transport_t base)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct transport_class bslosx_transport_class = {
|
||||||
|
.destroy = bslosx_destroy,
|
||||||
|
.send = bslosx_send,
|
||||||
|
.recv = bslosx_recv,
|
||||||
|
.flush = bslosx_flush,
|
||||||
|
.set_modem = bslosx_set_modem,
|
||||||
|
.suspend = bslosx_suspend,
|
||||||
|
.resume = bslosx_resume
|
||||||
|
};
|
||||||
|
|
||||||
|
int getIntProperty(IOHIDDeviceRef inIOHIDDeviceRef, CFStringRef inKey) {
|
||||||
|
int val;
|
||||||
|
if (inIOHIDDeviceRef) {
|
||||||
|
CFTypeRef tCFTypeRef = IOHIDDeviceGetProperty(inIOHIDDeviceRef, inKey);
|
||||||
|
if (tCFTypeRef) {
|
||||||
|
if (CFNumberGetTypeID() == CFGetTypeID(tCFTypeRef)) {
|
||||||
|
if (!CFNumberGetValue( (CFNumberRef) tCFTypeRef, kCFNumberSInt32Type, &val)) {
|
||||||
|
val = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
transport_t bslosx_open(const char *dev_path, const char *requested_serial)
|
||||||
|
{
|
||||||
|
struct bslosx_transport *tr = malloc(sizeof(*tr));
|
||||||
|
|
||||||
|
if (!tr) {
|
||||||
|
pr_error("bslosx: can't allocate memory");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(tr, 0, sizeof(*tr));
|
||||||
|
|
||||||
|
IOHIDDeviceRef refDevice;
|
||||||
|
IOHIDManagerRef refHidMgr = NULL;
|
||||||
|
CFSetRef refDevSet = NULL;
|
||||||
|
IOHIDDeviceRef *prefDevs = NULL;
|
||||||
|
int i;
|
||||||
|
int vid, pid;
|
||||||
|
CFIndex numDevices;
|
||||||
|
IOReturn ret;
|
||||||
|
|
||||||
|
refHidMgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
|
||||||
|
IOHIDManagerSetDeviceMatching(refHidMgr, NULL);
|
||||||
|
IOHIDManagerScheduleWithRunLoop(refHidMgr, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
||||||
|
IOHIDManagerOpen(refHidMgr, kIOHIDOptionsTypeNone);
|
||||||
|
refDevSet = IOHIDManagerCopyDevices(refHidMgr);
|
||||||
|
numDevices = CFSetGetCount(refDevSet);
|
||||||
|
prefDevs = malloc(numDevices * sizeof(IOHIDDeviceRef));
|
||||||
|
CFSetGetValues(refDevSet, (const void **)prefDevs);
|
||||||
|
for (i = 0; i < numDevices; i++) {
|
||||||
|
refDevice = prefDevs[i];
|
||||||
|
vid = getIntProperty(refDevice, CFSTR(kIOHIDVendorIDKey));
|
||||||
|
pid = getIntProperty(refDevice, CFSTR(kIOHIDProductIDKey));
|
||||||
|
if (vid == BSLHID_VID && pid == BSLHID_PID) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!refDevice) {
|
||||||
|
free(tr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = IOHIDDeviceOpen(refDevice, kIOHIDOptionsTypeNone);
|
||||||
|
if (ret != kIOReturnSuccess) {
|
||||||
|
printc_err("bslosx: failed to open BSL HID device\n");
|
||||||
|
free(tr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
tr->base.ops = &bslosx_transport_class;
|
||||||
|
tr->refDevice = refDevice;
|
||||||
|
strcpy(tr->bus_name, "macosxhid");
|
||||||
|
|
||||||
|
bslosx_flush(&tr->base);
|
||||||
|
return &tr->base;
|
||||||
|
}
|
Loading…
Reference in New Issue