First version
This commit is contained in:
26
commandline/Makefile
Normal file
26
commandline/Makefile
Normal file
@ -0,0 +1,26 @@
|
||||
# $Id: Makefile,v 1.1 2006/10/28 12:40:42 rschaten Exp $
|
||||
|
||||
CC = gcc
|
||||
LIBUSB_CONFIG = libusb-config
|
||||
# Make sure that libusb-config is in the search path or specify a full path. On
|
||||
# Windows, there is no libusb-config and you must configure the options below
|
||||
# manually. See examples.
|
||||
|
||||
CFLAGS = `$(LIBUSB_CONFIG) --cflags` -O -Wall -I../common
|
||||
|
||||
USBLIBS = `$(LIBUSB_CONFIG) --libs`
|
||||
XSPLIBS = -lX11 -lm
|
||||
|
||||
all: usb-servo xservopointer
|
||||
|
||||
usb-servo: usb-servo.o usbdrv.o
|
||||
$(CC) $(CFLAGS) -o usb-servo usb-servo.o usbdrv.o $(USBLIBS)
|
||||
|
||||
xservopointer: xservopointer.o usbdrv.o
|
||||
$(CC) $(CFLAGS) -o xservopointer xservopointer.o usbdrv.o $(USBLIBS) $(XSPLIBS)
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $*.c -o $*.o
|
||||
|
||||
clean:
|
||||
rm -f usb-servo xservopointer *.o
|
75
commandline/usb-servo.c
Normal file
75
commandline/usb-servo.c
Normal file
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* \file usb-servo.c
|
||||
* \brief Commandline-tool for the USB-Servo.
|
||||
* \author Ronald Schaten
|
||||
* \version $Id: usb-servo.c,v 1.1 2006/10/28 12:40:42 rschaten Exp $
|
||||
*
|
||||
* License: See documentation.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <usb.h> /* this is libusb, see
|
||||
http://libusb.sourceforge.net/ */
|
||||
|
||||
#include "usbdrv.h"
|
||||
|
||||
/**
|
||||
* Displays usage-information. This function is called if the parameters cannot
|
||||
* be parsed.
|
||||
* \param name The name of this application.
|
||||
*/
|
||||
void usage(char *name) {
|
||||
fprintf(stderr, "usage:\n");
|
||||
fprintf(stderr, " %s status\n", name);
|
||||
fprintf(stderr, " %s set <angle>\n", name);
|
||||
fprintf(stderr, " %s test\n\n", name);
|
||||
fprintf(stderr, "parameters:\n");
|
||||
fprintf(stderr, " angle: Required angle for the servo.\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function. Initializes the USB-device, parses commandline-parameters and
|
||||
* calls the functions that communicate with the device.
|
||||
* \param argc Number of arguments.
|
||||
* \param argv Arguments.
|
||||
* \return Error code.
|
||||
*/
|
||||
int main(int argc, char **argv) {
|
||||
usb_dev_handle *handle = NULL;
|
||||
|
||||
if (argc < 2) {
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
usb_init();
|
||||
if (usbOpenDevice(&handle, USBDEV_SHARED_VENDOR, "www.schatenseite.de",
|
||||
USBDEV_SHARED_PRODUCT, "USB-Servo") != 0) {
|
||||
fprintf(stderr,
|
||||
"Could not find USB device \"USB-Servo\" with vid=0x%x pid=0x%x\n",
|
||||
USBDEV_SHARED_VENDOR, USBDEV_SHARED_PRODUCT);
|
||||
exit(1);
|
||||
}
|
||||
/* We have searched all devices on all busses for our USB device
|
||||
above. Now try to open it and perform the vendor specific control
|
||||
operations for the function requested by the user. */
|
||||
if (strcmp(argv[1], "test") == 0) {
|
||||
if (dev_test(handle, argc, argv) != 0) {
|
||||
usage(argv[1]);
|
||||
}
|
||||
} else if (strcmp(argv[1], "set") == 0) {
|
||||
if (dev_set(handle, argc, argv) != 0) {
|
||||
usage(argv[1]);
|
||||
}
|
||||
} else if (strcmp(argv[1], "status") == 0) {
|
||||
if (dev_status(handle, argc, argv) != 0) {
|
||||
usage(argv[1]);
|
||||
}
|
||||
} else {
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
usb_close(handle);
|
||||
return 0;
|
||||
}
|
207
commandline/usbdrv.c
Normal file
207
commandline/usbdrv.c
Normal file
@ -0,0 +1,207 @@
|
||||
/**
|
||||
* \file usbdrv.c
|
||||
* \brief USB-driver-parts for implementing a client.
|
||||
* \author Ronald Schaten
|
||||
* \version $Id: usbdrv.c,v 1.1 2006/10/28 12:40:42 rschaten Exp $
|
||||
*
|
||||
* License: See documentation.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <usb.h> /* this is libusb, see
|
||||
http://libusb.sourceforge.net/ */
|
||||
|
||||
#include "usbdrv.h"
|
||||
#include "usbservo.h"
|
||||
|
||||
int usbGetStringAscii(usb_dev_handle * dev, int index, int langid,
|
||||
char *buf, int buflen) {
|
||||
char buffer[256];
|
||||
int rval, i;
|
||||
|
||||
if ((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
|
||||
(USB_DT_STRING << 8) + index, langid, buffer,
|
||||
sizeof(buffer), 1000)) < 0) {
|
||||
return rval;
|
||||
}
|
||||
if (buffer[1] != USB_DT_STRING) {
|
||||
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 vendor, char *vendorName,
|
||||
int product, char *productName) {
|
||||
struct usb_bus *bus;
|
||||
struct usb_device *dev;
|
||||
usb_dev_handle *handle = NULL;
|
||||
int errorCode = USB_ERROR_NOTFOUND;
|
||||
static int didUsbInit = 0;
|
||||
|
||||
if (!didUsbInit) {
|
||||
didUsbInit = 1;
|
||||
usb_init();
|
||||
}
|
||||
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 = USB_ERROR_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 = usbGetStringAscii(handle,
|
||||
dev->descriptor.iManufacturer,
|
||||
0x0409, string, sizeof(string));
|
||||
if (len < 0) {
|
||||
errorCode = USB_ERROR_IO;
|
||||
fprintf(stderr,
|
||||
"Warning: cannot query manufacturer for device: %s\n",
|
||||
usb_strerror());
|
||||
} else {
|
||||
errorCode = USB_ERROR_NOTFOUND;
|
||||
if (strcmp(string, vendorName) == 0) {
|
||||
len = usbGetStringAscii(handle,
|
||||
dev->descriptor.iProduct,
|
||||
0x0409, string,
|
||||
sizeof(string));
|
||||
if (len < 0) {
|
||||
errorCode = USB_ERROR_IO;
|
||||
fprintf(stderr,
|
||||
"Warning: cannot query product for device: %s\n",
|
||||
usb_strerror());
|
||||
} else {
|
||||
errorCode = USB_ERROR_NOTFOUND;
|
||||
if (strcmp(string, productName) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
usb_close(handle);
|
||||
handle = NULL;
|
||||
}
|
||||
}
|
||||
if (handle) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (handle != NULL) {
|
||||
errorCode = 0;
|
||||
*device = handle;
|
||||
}
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
int dev_test(usb_dev_handle * handle, int argc, char **argv) {
|
||||
unsigned char buffer[8];
|
||||
int nBytes;
|
||||
int i, v, r;
|
||||
if (argc != 2) {
|
||||
return 1;
|
||||
}
|
||||
for (i = 0; i < 1000; i++) {
|
||||
v = rand() & 0xffff;
|
||||
nBytes = usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_IN, CMD_ECHO, v, 0,
|
||||
(char *)buffer, sizeof(buffer), 5000);
|
||||
if (nBytes < 2) {
|
||||
if (nBytes < 0) {
|
||||
fprintf(stderr, "USB error: %s\n", usb_strerror());
|
||||
}
|
||||
fprintf(stderr, "only %d bytes received in iteration %d\n",
|
||||
nBytes, i);
|
||||
exit(1);
|
||||
}
|
||||
r = buffer[0] | (buffer[1] << 8);
|
||||
if (r != v) {
|
||||
fprintf(stderr,
|
||||
"data error: received 0x%x instead of 0x%x in iteration %d\n",
|
||||
r, v, i);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
printf("test succeeded\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dev_set(usb_dev_handle * handle, int argc, char **argv) {
|
||||
unsigned char buffer[8];
|
||||
int nBytes;
|
||||
if (argc != 3) {
|
||||
return 1;
|
||||
}
|
||||
int angle = atoi(argv[2]);
|
||||
if ((angle < 0) || (angle > 255)) {
|
||||
fprintf(stderr, "invalid angle: %d\n", angle);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
nBytes = usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_OUT, CMD_SET, angle, 0,
|
||||
(char *)buffer, sizeof(buffer), 5000);
|
||||
|
||||
if (nBytes < 0) {
|
||||
fprintf(stderr, "USB error: %s\n", usb_strerror());
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dev_status(usb_dev_handle * handle, int argc, char **argv) {
|
||||
int nBytes;
|
||||
unsigned char buffer[8];
|
||||
if (argc != 2) {
|
||||
return 1;
|
||||
}
|
||||
nBytes = usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE |
|
||||
USB_ENDPOINT_IN, CMD_GET, 0, 0, (char *)buffer,
|
||||
sizeof(buffer), 5000);
|
||||
if (nBytes < 0) {
|
||||
fprintf(stderr, "USB error: %s\n", usb_strerror());
|
||||
exit(1);
|
||||
}
|
||||
if (nBytes < 1) {
|
||||
fprintf(stderr, "only %d bytes status received\n", nBytes);
|
||||
exit(1);
|
||||
}
|
||||
printf("Current servo angle: %d\n", buffer[0]);
|
||||
return 0;
|
||||
}
|
||||
|
74
commandline/usbdrv.h
Normal file
74
commandline/usbdrv.h
Normal file
@ -0,0 +1,74 @@
|
||||
/**
|
||||
* \file usbdrv.h
|
||||
* \brief USB-driver-parts for implementing a client.
|
||||
* \author Ronald Schaten
|
||||
* \version $Id: usbdrv.h,v 1.1 2006/10/28 12:40:42 rschaten Exp $
|
||||
*
|
||||
* License: See documentation.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <usb.h> /* this is libusb, see http://libusb.sourceforge.net/ */
|
||||
|
||||
#include "usbservo.h"
|
||||
|
||||
#define USBDEV_SHARED_VENDOR 0x16C0 /**< VOTI */
|
||||
#define USBDEV_SHARED_PRODUCT 0x05DC /**< Obdev's free shared PID. Use obdev's generic shared VID/PID pair and follow the rules outlined in firmware/usbdrv/USBID-License.txt. */
|
||||
|
||||
/* These are error codes for the communication via USB. */
|
||||
#define USB_ERROR_NOTFOUND 1 /**< Error code if the device isn't found. */
|
||||
#define USB_ERROR_ACCESS 2 /**< Error code if the device isn't accessible. */
|
||||
#define USB_ERROR_IO 3 /**< Error code if errors in the communication with the device occur. */
|
||||
|
||||
/**
|
||||
* Reads and converts a string from USB. The conversion to ASCII is 'lossy' (unknown characters become '?').
|
||||
* \param dev Handle of the USB-Device.
|
||||
* \param index Index of the required data.
|
||||
* \param langid Index of the expected language.
|
||||
* \param buf Buffer to contain the return-string.
|
||||
* \param buflen Length of buf.
|
||||
* \return Length of the string.
|
||||
*/
|
||||
int usbGetStringAscii(usb_dev_handle * dev, int index, int langid, char *buf, int buflen);
|
||||
|
||||
/**
|
||||
* Connect to the USB-device. Loops through all connected USB-Devices and
|
||||
* searches our counterpart.
|
||||
* \param device Handle to address the device.
|
||||
* \param vendor USBDEV_SHARED_VENDOR as defined.
|
||||
* \param vendorName In our case "www.schatenseite.de".
|
||||
* \param product USBDEV_SHARED_PRODUCT as defined.
|
||||
* \param productName In our case "USB-Servo".
|
||||
* \return Error code.
|
||||
*/
|
||||
int usbOpenDevice(usb_dev_handle ** device, int vendor, char *vendorName, int product, char *productName);
|
||||
|
||||
/**
|
||||
* Test connection to the device. The test consists of writing 1000 random
|
||||
* numbers to the device and checking the echo. This should discover systematic
|
||||
* bit errors (e.g. in bit stuffing).
|
||||
* \param handle Handle to talk to the device.
|
||||
* \param argc Number of arguments.
|
||||
* \param argv Arguments.
|
||||
*/
|
||||
int dev_test(usb_dev_handle * handle, int argc, char **argv);
|
||||
|
||||
/**
|
||||
* Set the angle of the Servo.
|
||||
* \param handle Handle to talk to the device.
|
||||
* \param argc Number of arguments.
|
||||
* \param argv Arguments.
|
||||
*/
|
||||
int dev_set(usb_dev_handle * handle, int argc, char **argv);
|
||||
|
||||
/**
|
||||
* Get the status of the device. Status information is printed in detail (we
|
||||
* dont't have too many details with only one servo).
|
||||
* \param handle Handle to talk to the device.
|
||||
* \param argc Number of arguments.
|
||||
* \param argv Arguments.
|
||||
*/
|
||||
int dev_status(usb_dev_handle * handle, int argc, char **argv);
|
||||
|
107
commandline/xservopointer.c
Normal file
107
commandline/xservopointer.c
Normal file
@ -0,0 +1,107 @@
|
||||
/**
|
||||
* \file xservopointer.c
|
||||
* \brief Tool that uses a servo to point to the mouse cursor under X.
|
||||
* \author Ronald Schaten
|
||||
* \version $Id: xservopointer.c,v 1.1 2006/10/28 12:40:42 rschaten Exp $
|
||||
*
|
||||
* License: See documentation.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include <usb.h> /* this is libusb, see http://libusb.sourceforge.net/ */
|
||||
|
||||
#include "usbdrv.h"
|
||||
|
||||
Display *dpy; /** The display to use */
|
||||
Window root; /** The root-window of the display */
|
||||
|
||||
int rootwidth, rootheight; /** Measurements of the desktop */
|
||||
int servoposx, servoposy; /** Position of the mouse cursor */
|
||||
|
||||
usb_dev_handle *handle = NULL; /** Handle to the device */
|
||||
|
||||
/**
|
||||
* Determines the current cursor position and sets the servo angle.
|
||||
*/
|
||||
void update() {
|
||||
Window wroot, wchild;
|
||||
int absx, absy, relx, rely, angle;
|
||||
static int oldabsx = -1000;
|
||||
static int oldabsy = -1000;
|
||||
unsigned int modmask;
|
||||
unsigned char buffer[8];
|
||||
|
||||
// get cursor position
|
||||
XQueryPointer(dpy, root, &wroot, &wchild, &absx, &absy, &relx, &rely, &modmask);
|
||||
|
||||
if (oldabsx == absx && oldabsy == absy) {
|
||||
// position unchanged
|
||||
} else {
|
||||
// calculate new angle
|
||||
angle = (int)(atan((float)(absx - servoposx) / (absy - servoposy)) * (255 / M_PI));
|
||||
angle = 128 - angle;
|
||||
printf("absx/absy %d/%d -> angle %d\n", absx, absy, angle);
|
||||
int nBytes = usb_control_msg(handle,
|
||||
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CMD_SET, angle, 0,
|
||||
(char *)buffer, sizeof(buffer), 5000);
|
||||
|
||||
if (nBytes < 0) {
|
||||
fprintf(stderr, "USB error: %s\n", usb_strerror());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
oldabsx = absx;
|
||||
oldabsy = absy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function. Initializes the X-settings and the USB-device, starts the
|
||||
* timer and calls the update-function.
|
||||
* \param argc Number of arguments.
|
||||
* \param argv Arguments.
|
||||
* \return Error code.
|
||||
*/
|
||||
int main(int argc, char *argv[]) {
|
||||
// values for timer
|
||||
struct timespec ts;
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 100 * 1000 * 1000; // every 100ms
|
||||
|
||||
// open display
|
||||
dpy = XOpenDisplay(NULL);
|
||||
if (dpy == NULL) {
|
||||
fprintf(stderr, "xservopointer: Unable to open display\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
root = DefaultRootWindow(dpy);
|
||||
|
||||
// determine screen width and height
|
||||
XWindowAttributes Attributes;
|
||||
XGetWindowAttributes(dpy, root, &Attributes);
|
||||
rootwidth = Attributes.width;
|
||||
rootheight = Attributes.height;
|
||||
|
||||
// set servo position
|
||||
servoposx = rootwidth / 2; // middle of the screen
|
||||
servoposy = -150; // above the screen
|
||||
|
||||
// initialize USB-device
|
||||
usb_init();
|
||||
if (usbOpenDevice(&handle, USBDEV_SHARED_VENDOR, "www.schatenseite.de", USBDEV_SHARED_PRODUCT, "USB-Servo") != 0) {
|
||||
fprintf(stderr, "Could not find USB device \"USB-Servo\" with vid=0x%x pid=0x%x\n", USBDEV_SHARED_VENDOR, USBDEV_SHARED_PRODUCT);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// main loop
|
||||
while (1) {
|
||||
update();
|
||||
nanosleep(&ts, NULL);
|
||||
}
|
||||
usb_close(handle);
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user