o cleanup
This commit is contained in:
26
tools/avrusb/libs-host/Readme.txt
Normal file
26
tools/avrusb/libs-host/Readme.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
This is the Readme file for the libs-host directory. This directory contains
|
||||
code snippets which may be useful for host side USB software.
|
||||
|
||||
|
||||
WHAT IS INCLUDED IN THIS DIRECTORY?
|
||||
===================================
|
||||
|
||||
opendevice.c and opendevice.h
|
||||
This module contains a function to find and open a device given its
|
||||
numeric IDs (VID, PID), names (vendor name and product name) and serial
|
||||
number. It is based on libusb/libusb-win32 and returns a libusb device
|
||||
handle. See opendevice.h for an API documentation.
|
||||
|
||||
hiddata.c and hiddata.h
|
||||
This module contains functions for data transfer over HID feature reports.
|
||||
It is based on libusb on Unix and native Windows functions on Windows. No
|
||||
driver DLL is needed on Windows. See hiddata.h for an API documentation.
|
||||
|
||||
hidsdi.h
|
||||
This DDK header file is missing in the free MinGW version of the Windows
|
||||
DDK. Use this version if you get an "include file not found" error.
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
(c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH.
|
||||
http://www.obdev.at/
|
||||
317
tools/avrusb/libs-host/hiddata.c
Normal file
317
tools/avrusb/libs-host/hiddata.c
Normal file
@@ -0,0 +1,317 @@
|
||||
/* Name: hiddata.c
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2008-04-11
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: hiddata.c 692 2008-11-07 15:07:40Z cs $
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "hiddata.h"
|
||||
|
||||
/* ######################################################################## */
|
||||
#if defined(WIN32) /* ##################################################### */
|
||||
/* ######################################################################## */
|
||||
|
||||
#include <windows.h>
|
||||
#include <setupapi.h>
|
||||
#include "hidsdi.h"
|
||||
#include <ddk/hidpi.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DEBUG_PRINT(arg) printf arg
|
||||
#else
|
||||
#define DEBUG_PRINT(arg)
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static void convertUniToAscii(char *buffer)
|
||||
{
|
||||
unsigned short *uni = (void *)buffer;
|
||||
char *ascii = buffer;
|
||||
|
||||
while(*uni != 0){
|
||||
if(*uni >= 256){
|
||||
*ascii++ = '?';
|
||||
}else{
|
||||
*ascii++ = *uni++;
|
||||
}
|
||||
}
|
||||
*ascii++ = 0;
|
||||
}
|
||||
|
||||
int usbhidOpenDevice(usbDevice_t **device, int vendor, char *vendorName, int product, char *productName, int usesReportIDs)
|
||||
{
|
||||
GUID hidGuid; /* GUID for HID driver */
|
||||
HDEVINFO deviceInfoList;
|
||||
SP_DEVICE_INTERFACE_DATA deviceInfo;
|
||||
SP_DEVICE_INTERFACE_DETAIL_DATA *deviceDetails = NULL;
|
||||
DWORD size;
|
||||
int i, openFlag = 0; /* may be FILE_FLAG_OVERLAPPED */
|
||||
int errorCode = USBOPEN_ERR_NOTFOUND;
|
||||
HANDLE handle = INVALID_HANDLE_VALUE;
|
||||
HIDD_ATTRIBUTES deviceAttributes;
|
||||
|
||||
HidD_GetHidGuid(&hidGuid);
|
||||
deviceInfoList = SetupDiGetClassDevs(&hidGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
|
||||
deviceInfo.cbSize = sizeof(deviceInfo);
|
||||
for(i=0;;i++){
|
||||
if(handle != INVALID_HANDLE_VALUE){
|
||||
CloseHandle(handle);
|
||||
handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
if(!SetupDiEnumDeviceInterfaces(deviceInfoList, 0, &hidGuid, i, &deviceInfo))
|
||||
break; /* no more entries */
|
||||
/* first do a dummy call just to determine the actual size required */
|
||||
SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInfo, NULL, 0, &size, NULL);
|
||||
if(deviceDetails != NULL)
|
||||
free(deviceDetails);
|
||||
deviceDetails = malloc(size);
|
||||
deviceDetails->cbSize = sizeof(*deviceDetails);
|
||||
/* this call is for real: */
|
||||
SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInfo, deviceDetails, size, &size, NULL);
|
||||
DEBUG_PRINT(("checking HID path \"%s\"\n", deviceDetails->DevicePath));
|
||||
/* attempt opening for R/W -- we don't care about devices which can't be accessed */
|
||||
handle = CreateFile(deviceDetails->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, openFlag, NULL);
|
||||
if(handle == INVALID_HANDLE_VALUE){
|
||||
DEBUG_PRINT(("opening failed: %d\n", (int)GetLastError()));
|
||||
/* errorCode = USBOPEN_ERR_ACCESS; opening will always fail for mouse -- ignore */
|
||||
continue;
|
||||
}
|
||||
deviceAttributes.Size = sizeof(deviceAttributes);
|
||||
HidD_GetAttributes(handle, &deviceAttributes);
|
||||
DEBUG_PRINT(("device attributes: vid=%d pid=%d\n", deviceAttributes.VendorID, deviceAttributes.ProductID));
|
||||
if(deviceAttributes.VendorID != vendor || deviceAttributes.ProductID != product)
|
||||
continue; /* ignore this device */
|
||||
errorCode = USBOPEN_ERR_NOTFOUND;
|
||||
if(vendorName != NULL && productName != NULL){
|
||||
char buffer[512];
|
||||
if(!HidD_GetManufacturerString(handle, buffer, sizeof(buffer))){
|
||||
DEBUG_PRINT(("error obtaining vendor name\n"));
|
||||
errorCode = USBOPEN_ERR_IO;
|
||||
continue;
|
||||
}
|
||||
convertUniToAscii(buffer);
|
||||
DEBUG_PRINT(("vendorName = \"%s\"\n", buffer));
|
||||
if(strcmp(vendorName, buffer) != 0)
|
||||
continue;
|
||||
if(!HidD_GetProductString(handle, buffer, sizeof(buffer))){
|
||||
DEBUG_PRINT(("error obtaining product name\n"));
|
||||
errorCode = USBOPEN_ERR_IO;
|
||||
continue;
|
||||
}
|
||||
convertUniToAscii(buffer);
|
||||
DEBUG_PRINT(("productName = \"%s\"\n", buffer));
|
||||
if(strcmp(productName, buffer) != 0)
|
||||
continue;
|
||||
}
|
||||
break; /* we have found the device we are looking for! */
|
||||
}
|
||||
SetupDiDestroyDeviceInfoList(deviceInfoList);
|
||||
if(deviceDetails != NULL)
|
||||
free(deviceDetails);
|
||||
if(handle != INVALID_HANDLE_VALUE){
|
||||
*device = (usbDevice_t *)handle;
|
||||
errorCode = 0;
|
||||
}
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
void usbhidCloseDevice(usbDevice_t *device)
|
||||
{
|
||||
CloseHandle((HANDLE)device);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
int usbhidSetReport(usbDevice_t *device, char *buffer, int len)
|
||||
{
|
||||
BOOLEAN rval;
|
||||
|
||||
rval = HidD_SetFeature((HANDLE)device, buffer, len);
|
||||
return rval == 0 ? USBOPEN_ERR_IO : 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
int usbhidGetReport(usbDevice_t *device, int reportNumber, char *buffer, int *len)
|
||||
{
|
||||
BOOLEAN rval = 0;
|
||||
|
||||
buffer[0] = reportNumber;
|
||||
rval = HidD_GetFeature((HANDLE)device, buffer, *len);
|
||||
return rval == 0 ? USBOPEN_ERR_IO : 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* ######################################################################## */
|
||||
#else /* defined WIN32 #################################################### */
|
||||
/* ######################################################################## */
|
||||
|
||||
#include <string.h>
|
||||
#include <usb.h>
|
||||
|
||||
#define usbDevice usb_dev_handle /* use libusb's device structure */
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#define USBRQ_HID_GET_REPORT 0x01
|
||||
#define USBRQ_HID_SET_REPORT 0x09
|
||||
|
||||
#define USB_HID_REPORT_TYPE_FEATURE 3
|
||||
|
||||
|
||||
static int usesReportIDs;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static int usbhidGetStringAscii(usb_dev_handle *dev, int index, char *buf, int buflen)
|
||||
{
|
||||
char buffer[256];
|
||||
int rval, i;
|
||||
|
||||
if((rval = usb_get_string_simple(dev, index, buf, buflen)) >= 0) /* use libusb version if it works */
|
||||
return rval;
|
||||
if((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + index, 0x0409, buffer, sizeof(buffer), 5000)) < 0)
|
||||
return rval;
|
||||
if(buffer[1] != USB_DT_STRING){
|
||||
*buf = 0;
|
||||
return 0;
|
||||
}
|
||||
if((unsigned char)buffer[0] < rval)
|
||||
rval = (unsigned char)buffer[0];
|
||||
rval /= 2;
|
||||
/* lossy conversion to ISO Latin1: */
|
||||
for(i=1;i<rval;i++){
|
||||
if(i > buflen) /* destination buffer overflow */
|
||||
break;
|
||||
buf[i-1] = buffer[2 * i];
|
||||
if(buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */
|
||||
buf[i-1] = '?';
|
||||
}
|
||||
buf[i-1] = 0;
|
||||
return i-1;
|
||||
}
|
||||
|
||||
int usbhidOpenDevice(usbDevice_t **device, int vendor, char *vendorName, int product, char *productName, int _usesReportIDs)
|
||||
{
|
||||
struct usb_bus *bus;
|
||||
struct usb_device *dev;
|
||||
usb_dev_handle *handle = NULL;
|
||||
int errorCode = USBOPEN_ERR_NOTFOUND;
|
||||
static int didUsbInit = 0;
|
||||
|
||||
if(!didUsbInit){
|
||||
usb_init();
|
||||
didUsbInit = 1;
|
||||
}
|
||||
usb_find_busses();
|
||||
usb_find_devices();
|
||||
for(bus=usb_get_busses(); bus; bus=bus->next){
|
||||
for(dev=bus->devices; dev; dev=dev->next){
|
||||
if(dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product){
|
||||
char string[256];
|
||||
int len;
|
||||
handle = usb_open(dev); /* we need to open the device in order to query strings */
|
||||
if(!handle){
|
||||
errorCode = USBOPEN_ERR_ACCESS;
|
||||
fprintf(stderr, "Warning: cannot open USB device: %s\n", usb_strerror());
|
||||
continue;
|
||||
}
|
||||
if(vendorName == NULL && productName == NULL){ /* name does not matter */
|
||||
break;
|
||||
}
|
||||
/* now check whether the names match: */
|
||||
len = usbhidGetStringAscii(handle, dev->descriptor.iManufacturer, string, sizeof(string));
|
||||
if(len < 0){
|
||||
errorCode = USBOPEN_ERR_IO;
|
||||
fprintf(stderr, "Warning: cannot query manufacturer for device: %s\n", usb_strerror());
|
||||
}else{
|
||||
errorCode = USBOPEN_ERR_NOTFOUND;
|
||||
/* fprintf(stderr, "seen device from vendor ->%s<-\n", string); */
|
||||
if(strcmp(string, vendorName) == 0){
|
||||
len = usbhidGetStringAscii(handle, dev->descriptor.iProduct, string, sizeof(string));
|
||||
if(len < 0){
|
||||
errorCode = USBOPEN_ERR_IO;
|
||||
fprintf(stderr, "Warning: cannot query product for device: %s\n", usb_strerror());
|
||||
}else{
|
||||
errorCode = USBOPEN_ERR_NOTFOUND;
|
||||
/* fprintf(stderr, "seen product ->%s<-\n", string); */
|
||||
if(strcmp(string, productName) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
usb_close(handle);
|
||||
handle = NULL;
|
||||
}
|
||||
}
|
||||
if(handle)
|
||||
break;
|
||||
}
|
||||
if(handle != NULL){
|
||||
errorCode = 0;
|
||||
*device = (void *)handle;
|
||||
usesReportIDs = _usesReportIDs;
|
||||
}
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
void usbhidCloseDevice(usbDevice_t *device)
|
||||
{
|
||||
if(device != NULL)
|
||||
usb_close((void *)device);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
int usbhidSetReport(usbDevice_t *device, char *buffer, int len)
|
||||
{
|
||||
int bytesSent;
|
||||
|
||||
if(!usesReportIDs){
|
||||
buffer++; /* skip dummy report ID */
|
||||
len--;
|
||||
}
|
||||
bytesSent = usb_control_msg((void *)device, USB_TYPE_CLASS | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, USBRQ_HID_SET_REPORT, USB_HID_REPORT_TYPE_FEATURE << 8 | (buffer[0] & 0xff), 0, buffer, len, 5000);
|
||||
if(bytesSent != len){
|
||||
if(bytesSent < 0)
|
||||
fprintf(stderr, "Error sending message: %s\n", usb_strerror());
|
||||
return USBOPEN_ERR_IO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
int usbhidGetReport(usbDevice_t *device, int reportNumber, char *buffer, int *len)
|
||||
{
|
||||
int bytesReceived, maxLen = *len;
|
||||
|
||||
if(!usesReportIDs){
|
||||
buffer++; /* make room for dummy report ID */
|
||||
maxLen--;
|
||||
}
|
||||
bytesReceived = usb_control_msg((void *)device, USB_TYPE_CLASS | USB_RECIP_DEVICE | USB_ENDPOINT_IN, USBRQ_HID_GET_REPORT, USB_HID_REPORT_TYPE_FEATURE << 8 | reportNumber, 0, buffer, maxLen, 5000);
|
||||
if(bytesReceived < 0){
|
||||
fprintf(stderr, "Error sending message: %s\n", usb_strerror());
|
||||
return USBOPEN_ERR_IO;
|
||||
}
|
||||
*len = bytesReceived;
|
||||
if(!usesReportIDs){
|
||||
buffer[-1] = reportNumber; /* add dummy report ID */
|
||||
(*len)++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ######################################################################## */
|
||||
#endif /* defined WIN32 ################################################### */
|
||||
/* ######################################################################## */
|
||||
71
tools/avrusb/libs-host/hiddata.h
Normal file
71
tools/avrusb/libs-host/hiddata.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/* Name: hiddata.h
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2008-04-11
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: hiddata.h 692 2008-11-07 15:07:40Z cs $
|
||||
*/
|
||||
|
||||
#ifndef __HIDDATA_H_INCLUDED__
|
||||
#define __HIDDATA_H_INCLUDED__
|
||||
|
||||
/*
|
||||
General Description:
|
||||
This module implements an abstraction layer for data transfer over HID feature
|
||||
requests. The implementation uses native Windows functions on Windows so that
|
||||
no driver installation is required and libusb on Unix. You must link the
|
||||
appropriate libraries in either case: "-lhid -lusb -lsetupapi" on Windows and
|
||||
`libusb-config --libs` on Unix.
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#define USBOPEN_SUCCESS 0 /* no error */
|
||||
#define USBOPEN_ERR_ACCESS 1 /* not enough permissions to open device */
|
||||
#define USBOPEN_ERR_IO 2 /* I/O error */
|
||||
#define USBOPEN_ERR_NOTFOUND 3 /* device not found */
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
typedef struct usbDevice usbDevice_t;
|
||||
/* Opaque data type representing the USB device. This can be a Windows handle
|
||||
* or a libusb handle, depending on the backend implementation.
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
int usbhidOpenDevice(usbDevice_t **device, int vendorID, char *vendorName, int productID, char *productName, int usesReportIDs);
|
||||
/* This function opens a USB device. 'vendorID' and 'productID' are the numeric
|
||||
* Vendor-ID and Product-ID of the device we want to open. If 'vendorName' and
|
||||
* 'productName' are both not NULL, only devices with matching manufacturer-
|
||||
* and product name strings are accepted. If the device uses report IDs,
|
||||
* 'usesReportIDs' must be set to a non-zero value.
|
||||
* Returns: If a matching device has been found, USBOPEN_SUCCESS is returned
|
||||
* and '*device' is set to an opaque pointer representing the device. The
|
||||
* device must be closed with usbhidCloseDevice(). If the device has not been
|
||||
* found or opening failed, an error code is returned.
|
||||
*/
|
||||
void usbhidCloseDevice(usbDevice_t *device);
|
||||
/* Every device opened with usbhidOpenDevice() must be closed with this function.
|
||||
*/
|
||||
int usbhidSetReport(usbDevice_t *device, char *buffer, int len);
|
||||
/* This function sends a feature report to the device. The report ID must be
|
||||
* in the first byte of buffer and the length 'len' of the report is specified
|
||||
* including this report ID. If no report IDs are used, buffer[0] must be set
|
||||
* to 0 (dummy report ID).
|
||||
* Returns: 0 on success, an error code otherwise.
|
||||
*/
|
||||
int usbhidGetReport(usbDevice_t *device, int reportID, char *buffer, int *len);
|
||||
/* This function obtains a feature report from the device. The requested
|
||||
* report-ID is passed in 'reportID'. The caller must pass a buffer of the size
|
||||
* of the expected report in 'buffer' and initialize the variable pointed to by
|
||||
* 'len' to the total size of this buffer. Upon successful return, the report
|
||||
* (prefixed with the report-ID) is in 'buffer' and the actual length of the
|
||||
* report is returned in '*len'.
|
||||
* Returns: 0 on success, an error code otherwise.
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#endif /* __HIDDATA_H_INCLUDED__ */
|
||||
49
tools/avrusb/libs-host/hidsdi.h
Normal file
49
tools/avrusb/libs-host/hidsdi.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* Name: hidsdi.h
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2006-02-02
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2006-2008 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: hidsdi.h 692 2008-11-07 15:07:40Z cs $
|
||||
*/
|
||||
|
||||
/*
|
||||
General Description
|
||||
This file is a replacement for hidsdi.h from the Windows DDK. It defines some
|
||||
of the types and function prototypes of this header for our project. If you
|
||||
have the Windows DDK version of this file or a version shipped with MinGW, use
|
||||
that instead.
|
||||
*/
|
||||
|
||||
#ifndef _HIDSDI_H
|
||||
#define _HIDSDI_H
|
||||
|
||||
#include <pshpack4.h>
|
||||
|
||||
#include <ddk/hidusage.h>
|
||||
#include <ddk/hidpi.h>
|
||||
|
||||
typedef struct{
|
||||
ULONG Size;
|
||||
USHORT VendorID;
|
||||
USHORT ProductID;
|
||||
USHORT VersionNumber;
|
||||
}HIDD_ATTRIBUTES;
|
||||
|
||||
void __stdcall HidD_GetHidGuid(OUT LPGUID hidGuid);
|
||||
|
||||
BOOLEAN __stdcall HidD_GetAttributes(IN HANDLE device, OUT HIDD_ATTRIBUTES *attributes);
|
||||
|
||||
BOOLEAN __stdcall HidD_GetManufacturerString(IN HANDLE device, OUT void *buffer, IN ULONG bufferLen);
|
||||
BOOLEAN __stdcall HidD_GetProductString(IN HANDLE device, OUT void *buffer, IN ULONG bufferLen);
|
||||
BOOLEAN __stdcall HidD_GetSerialNumberString(IN HANDLE device, OUT void *buffer, IN ULONG bufferLen);
|
||||
|
||||
BOOLEAN __stdcall HidD_GetFeature(IN HANDLE device, OUT void *reportBuffer, IN ULONG bufferLen);
|
||||
BOOLEAN __stdcall HidD_SetFeature(IN HANDLE device, IN void *reportBuffer, IN ULONG bufferLen);
|
||||
|
||||
BOOLEAN __stdcall HidD_GetNumInputBuffers(IN HANDLE device, OUT ULONG *numBuffers);
|
||||
BOOLEAN __stdcall HidD_SetNumInputBuffers(IN HANDLE device, OUT ULONG numBuffers);
|
||||
|
||||
#include <poppack.h>
|
||||
|
||||
#endif
|
||||
203
tools/avrusb/libs-host/opendevice.c
Normal file
203
tools/avrusb/libs-host/opendevice.c
Normal file
@@ -0,0 +1,203 @@
|
||||
/* Name: opendevice.c
|
||||
* Project: AVR-USB host-side library
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2008-04-10
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: opendevice.c 692 2008-11-07 15:07:40Z cs $
|
||||
*/
|
||||
|
||||
/*
|
||||
General Description:
|
||||
The functions in this module can be used to find and open a device based on
|
||||
libusb or libusb-win32.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "opendevice.h"
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#define MATCH_SUCCESS 1
|
||||
#define MATCH_FAILED 0
|
||||
#define MATCH_ABORT -1
|
||||
|
||||
/* private interface: match text and p, return MATCH_SUCCESS, MATCH_FAILED, or MATCH_ABORT. */
|
||||
static int _shellStyleMatch(char *text, char *p)
|
||||
{
|
||||
int last, matched, reverse;
|
||||
|
||||
for(; *p; text++, p++){
|
||||
if(*text == 0 && *p != '*')
|
||||
return MATCH_ABORT;
|
||||
switch(*p){
|
||||
case '\\':
|
||||
/* Literal match with following character. */
|
||||
p++;
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
if(*text != *p)
|
||||
return MATCH_FAILED;
|
||||
continue;
|
||||
case '?':
|
||||
/* Match anything. */
|
||||
continue;
|
||||
case '*':
|
||||
while(*++p == '*')
|
||||
/* Consecutive stars act just like one. */
|
||||
continue;
|
||||
if(*p == 0)
|
||||
/* Trailing star matches everything. */
|
||||
return MATCH_SUCCESS;
|
||||
while(*text)
|
||||
if((matched = _shellStyleMatch(text++, p)) != MATCH_FAILED)
|
||||
return matched;
|
||||
return MATCH_ABORT;
|
||||
case '[':
|
||||
reverse = p[1] == '^';
|
||||
if(reverse) /* Inverted character class. */
|
||||
p++;
|
||||
matched = MATCH_FAILED;
|
||||
if(p[1] == ']' || p[1] == '-')
|
||||
if(*++p == *text)
|
||||
matched = MATCH_SUCCESS;
|
||||
for(last = *p; *++p && *p != ']'; last = *p)
|
||||
if (*p == '-' && p[1] != ']' ? *text <= *++p && *text >= last : *text == *p)
|
||||
matched = MATCH_SUCCESS;
|
||||
if(matched == reverse)
|
||||
return MATCH_FAILED;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return *text == 0;
|
||||
}
|
||||
|
||||
/* public interface for shell style matching: returns 0 if fails, 1 if matches */
|
||||
static int shellStyleMatch(char *text, char *pattern)
|
||||
{
|
||||
if(pattern == NULL) /* NULL pattern is synonymous to "*" */
|
||||
return 1;
|
||||
return _shellStyleMatch(text, pattern) == MATCH_SUCCESS;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
int usbGetStringAscii(usb_dev_handle *dev, int index, char *buf, int buflen)
|
||||
{
|
||||
char buffer[256];
|
||||
int rval, i;
|
||||
|
||||
if((rval = usb_get_string_simple(dev, index, buf, buflen)) >= 0) /* use libusb version if it works */
|
||||
return rval;
|
||||
if((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + index, 0x0409, buffer, sizeof(buffer), 5000)) < 0)
|
||||
return rval;
|
||||
if(buffer[1] != USB_DT_STRING){
|
||||
*buf = 0;
|
||||
return 0;
|
||||
}
|
||||
if((unsigned char)buffer[0] < rval)
|
||||
rval = (unsigned char)buffer[0];
|
||||
rval /= 2;
|
||||
/* lossy conversion to ISO Latin1: */
|
||||
for(i=1;i<rval;i++){
|
||||
if(i > buflen) /* destination buffer overflow */
|
||||
break;
|
||||
buf[i-1] = buffer[2 * i];
|
||||
if(buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */
|
||||
buf[i-1] = '?';
|
||||
}
|
||||
buf[i-1] = 0;
|
||||
return i-1;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
int usbOpenDevice(usb_dev_handle **device, int vendorID, char *vendorNamePattern, int productID, char *productNamePattern, char *serialNamePattern, FILE *printMatchingDevicesFp, FILE *warningsFp)
|
||||
{
|
||||
struct usb_bus *bus;
|
||||
struct usb_device *dev;
|
||||
usb_dev_handle *handle = NULL;
|
||||
int errorCode = USBOPEN_ERR_NOTFOUND;
|
||||
|
||||
usb_find_busses();
|
||||
usb_find_devices();
|
||||
for(bus = usb_get_busses(); bus; bus = bus->next){
|
||||
for(dev = bus->devices; dev; dev = dev->next){ /* iterate over all devices on all busses */
|
||||
if((vendorID == 0 || dev->descriptor.idVendor == vendorID)
|
||||
&& (productID == 0 || dev->descriptor.idProduct == productID)){
|
||||
char vendor[256], product[256], serial[256];
|
||||
int len;
|
||||
handle = usb_open(dev); /* we need to open the device in order to query strings */
|
||||
if(!handle){
|
||||
errorCode = USBOPEN_ERR_ACCESS;
|
||||
if(warningsFp != NULL)
|
||||
fprintf(warningsFp, "Warning: cannot open VID=0x%04x PID=0x%04x: %s\n", dev->descriptor.idVendor, dev->descriptor.idProduct, usb_strerror());
|
||||
continue;
|
||||
}
|
||||
/* now check whether the names match: */
|
||||
len = vendor[0] = 0;
|
||||
if(dev->descriptor.iManufacturer > 0){
|
||||
len = usbGetStringAscii(handle, dev->descriptor.iManufacturer, vendor, sizeof(vendor));
|
||||
}
|
||||
if(len < 0){
|
||||
errorCode = USBOPEN_ERR_ACCESS;
|
||||
if(warningsFp != NULL)
|
||||
fprintf(warningsFp, "Warning: cannot query manufacturer for VID=0x%04x PID=0x%04x: %s\n", dev->descriptor.idVendor, dev->descriptor.idProduct, usb_strerror());
|
||||
}else{
|
||||
errorCode = USBOPEN_ERR_NOTFOUND;
|
||||
/* printf("seen device from vendor ->%s<-\n", vendor); */
|
||||
if(shellStyleMatch(vendor, vendorNamePattern)){
|
||||
len = product[0] = 0;
|
||||
if(dev->descriptor.iProduct > 0){
|
||||
len = usbGetStringAscii(handle, dev->descriptor.iProduct, product, sizeof(product));
|
||||
}
|
||||
if(len < 0){
|
||||
errorCode = USBOPEN_ERR_ACCESS;
|
||||
if(warningsFp != NULL)
|
||||
fprintf(warningsFp, "Warning: cannot query product for VID=0x%04x PID=0x%04x: %s\n", dev->descriptor.idVendor, dev->descriptor.idProduct, usb_strerror());
|
||||
}else{
|
||||
errorCode = USBOPEN_ERR_NOTFOUND;
|
||||
/* printf("seen product ->%s<-\n", product); */
|
||||
if(shellStyleMatch(product, productNamePattern)){
|
||||
len = serial[0] = 0;
|
||||
if(dev->descriptor.iSerialNumber > 0){
|
||||
len = usbGetStringAscii(handle, dev->descriptor.iSerialNumber, serial, sizeof(serial));
|
||||
}
|
||||
if(len < 0){
|
||||
errorCode = USBOPEN_ERR_ACCESS;
|
||||
if(warningsFp != NULL)
|
||||
fprintf(warningsFp, "Warning: cannot query serial for VID=0x%04x PID=0x%04x: %s\n", dev->descriptor.idVendor, dev->descriptor.idProduct, usb_strerror());
|
||||
}
|
||||
if(shellStyleMatch(serial, serialNamePattern)){
|
||||
if(printMatchingDevicesFp != NULL){
|
||||
if(serial[0] == 0){
|
||||
fprintf(printMatchingDevicesFp, "VID=0x%04x PID=0x%04x vendor=\"%s\" product=\"%s\"\n", dev->descriptor.idVendor, dev->descriptor.idProduct, vendor, product);
|
||||
}else{
|
||||
fprintf(printMatchingDevicesFp, "VID=0x%04x PID=0x%04x vendor=\"%s\" product=\"%s\" serial=\"%s\"\n", dev->descriptor.idVendor, dev->descriptor.idProduct, vendor, product, serial);
|
||||
}
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
usb_close(handle);
|
||||
handle = NULL;
|
||||
}
|
||||
}
|
||||
if(handle) /* we have found a deice */
|
||||
break;
|
||||
}
|
||||
if(handle != NULL){
|
||||
errorCode = 0;
|
||||
*device = handle;
|
||||
}
|
||||
if(printMatchingDevicesFp != NULL) /* never return an error for listing only */
|
||||
errorCode = 0;
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
77
tools/avrusb/libs-host/opendevice.h
Normal file
77
tools/avrusb/libs-host/opendevice.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/* Name: opendevice.h
|
||||
* Project: AVR-USB host-side library
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2008-04-10
|
||||
* Tabsize: 4
|
||||
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||
* This Revision: $Id: opendevice.h 692 2008-11-07 15:07:40Z cs $
|
||||
*/
|
||||
|
||||
/*
|
||||
General Description:
|
||||
This module offers additional functionality for host side drivers based on
|
||||
libusb or libusb-win32. It includes a function to find and open a device
|
||||
based on numeric IDs and textual description. It also includes a function to
|
||||
obtain textual descriptions from a device.
|
||||
|
||||
To use this functionality, simply copy opendevice.c and opendevice.h into your
|
||||
project and add them to your Makefile. You may modify and redistribute these
|
||||
files according to the GNU General Public License (GPL) version 2 or 3.
|
||||
*/
|
||||
|
||||
#ifndef __OPENDEVICE_H_INCLUDED__
|
||||
#define __OPENDEVICE_H_INCLUDED__
|
||||
|
||||
#include <usb.h> /* this is libusb, see http://libusb.sourceforge.net/ */
|
||||
#include <stdio.h>
|
||||
|
||||
int usbGetStringAscii(usb_dev_handle *dev, int index, char *buf, int buflen);
|
||||
/* This function gets a string descriptor from the device. 'index' is the
|
||||
* string descriptor index. The string is returned in ISO Latin 1 encoding in
|
||||
* 'buf' and it is terminated with a 0-character. The buffer size must be
|
||||
* passed in 'buflen' to prevent buffer overflows. A libusb device handle
|
||||
* must be given in 'dev'.
|
||||
* Returns: The length of the string (excluding the terminating 0) or
|
||||
* a negative number in case of an error. If there was an error, use
|
||||
* usb_strerror() to obtain the error message.
|
||||
*/
|
||||
|
||||
int usbOpenDevice(usb_dev_handle **device, int vendorID, char *vendorNamePattern, int productID, char *productNamePattern, char *serialNamePattern, FILE *printMatchingDevicesFp, FILE *warningsFp);
|
||||
/* This function iterates over all devices on all USB busses and searches for
|
||||
* a device. Matching is done first by means of Vendor- and Product-ID (passed
|
||||
* in 'vendorID' and 'productID'. An ID of 0 matches any numeric ID (wildcard).
|
||||
* When a device matches by its IDs, matching by names is performed. Name
|
||||
* matching can be done on textual vendor name ('vendorNamePattern'), product
|
||||
* name ('productNamePattern') and serial number ('serialNamePattern'). A
|
||||
* device matches only if all non-null pattern match. If you don't care about
|
||||
* a string, pass NULL for the pattern. Patterns are Unix shell style pattern:
|
||||
* '*' stands for 0 or more characters, '?' for one single character, a list
|
||||
* of characters in square brackets for a single character from the list
|
||||
* (dashes are allowed to specify a range) and if the lis of characters begins
|
||||
* with a caret ('^'), it matches one character which is NOT in the list.
|
||||
* Other parameters to the function: If 'warningsFp' is not NULL, warning
|
||||
* messages are printed to this file descriptor with fprintf(). If
|
||||
* 'printMatchingDevicesFp' is not NULL, no device is opened but matching
|
||||
* devices are printed to the given file descriptor with fprintf().
|
||||
* If a device is opened, the resulting USB handle is stored in '*device'. A
|
||||
* pointer to a "usb_dev_handle *" type variable must be passed here.
|
||||
* Returns: 0 on success, an error code (see defines below) on failure.
|
||||
*/
|
||||
|
||||
/* usbOpenDevice() error codes: */
|
||||
#define USBOPEN_SUCCESS 0 /* no error */
|
||||
#define USBOPEN_ERR_ACCESS 1 /* not enough permissions to open device */
|
||||
#define USBOPEN_ERR_IO 2 /* I/O error */
|
||||
#define USBOPEN_ERR_NOTFOUND 3 /* device not found */
|
||||
|
||||
|
||||
/* Obdev's free USB IDs, see USBID-License.txt for details */
|
||||
|
||||
#define USB_VID_OBDEV_SHARED 5824 /* obdev's shared vendor ID */
|
||||
#define USB_PID_OBDEV_SHARED_CUSTOM 1500 /* shared PID for custom class devices */
|
||||
#define USB_PID_OBDEV_SHARED_HID 1503 /* shared PID for HIDs except mice & keyboards */
|
||||
#define USB_PID_OBDEV_SHARED_CDCACM 1505 /* shared PID for CDC Modem devices */
|
||||
#define USB_PID_OBDEV_SHARED_MIDI 1508 /* shared PID for MIDI class devices */
|
||||
|
||||
#endif /* __OPENDEVICE_H_INCLUDED__ */
|
||||
Reference in New Issue
Block a user