[0da6f01] | 1 | /* Name: powerSwitch.c
|
---|
| 2 | * Project: PowerSwitch based on AVR USB driver
|
---|
| 3 | * Author: Christian Starkjohann
|
---|
| 4 | * Creation Date: 2005-01-16
|
---|
| 5 | * Tabsize: 4
|
---|
| 6 | * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
|
---|
| 7 | * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
|
---|
| 8 | * This Revision: $Id: powerSwitch.c 472 2008-01-21 18:21:59Z cs $
|
---|
| 9 | */
|
---|
| 10 |
|
---|
| 11 | /*
|
---|
| 12 | General Description:
|
---|
| 13 | This program controls the PowerSwitch USB device from the command line.
|
---|
| 14 | It must be linked with libusb, a library for accessing the USB bus from
|
---|
| 15 | Linux, FreeBSD, Mac OS X and other Unix operating systems. Libusb can be
|
---|
| 16 | obtained from http://libusb.sourceforge.net/.
|
---|
| 17 | */
|
---|
| 18 |
|
---|
| 19 | #include <stdio.h>
|
---|
| 20 | #include <stdlib.h>
|
---|
| 21 | #include <string.h>
|
---|
[d46151a] | 22 | #include <stdint.h>
|
---|
[88642a4] | 23 | #include <unistd.h>
|
---|
| 24 |
|
---|
[0da6f01] | 25 | #include <lusb0_usb.h> /* this is libusb, see http://libusb.sourceforge.net/ */
|
---|
| 26 |
|
---|
| 27 | #define USBDEV_SHARED_VENDOR 0x16C0 /* VOTI */
|
---|
| 28 | #define USBDEV_SHARED_PRODUCT 0x05DC /* Obdev's free shared PID */
|
---|
| 29 | /* Use obdev's generic shared VID/PID pair and follow the rules outlined
|
---|
| 30 | * in firmware/usbdrv/USBID-License.txt.
|
---|
| 31 | */
|
---|
| 32 |
|
---|
| 33 | #define VENDORSTRING "pulkomandy.ath.cx"
|
---|
| 34 | #define PRODUCTSTRING "CrO2"
|
---|
| 35 |
|
---|
[88642a4] | 36 | /* These are the vendor specific SETUP commands implemented by our USB device */
|
---|
[0da6f01] | 37 | #define PSCMD_CONFIG 0
|
---|
| 38 | #define PSCMD_GET 1
|
---|
| 39 | #define PSCMD_PUT 2
|
---|
[88642a4] | 40 | #define PSCMD_STATUS 3
|
---|
[0da6f01] | 41 |
|
---|
| 42 | static void usage(char *name)
|
---|
| 43 | {
|
---|
| 44 | fprintf(stderr, "usage:\n");
|
---|
| 45 | fprintf(stderr, " %s status\n", name);
|
---|
| 46 | fprintf(stderr, " %s on <port> [<duration>]\n", name);
|
---|
| 47 | fprintf(stderr, " %s off <port> [<duration>]\n", name);
|
---|
| 48 | fprintf(stderr, " %s test\n\n", name);
|
---|
| 49 | fprintf(stderr, "Ports are single digits in the range 0...7\n");
|
---|
| 50 | fprintf(stderr, "The pulse duration for switching temporarily is given in seconds.\n");
|
---|
| 51 | }
|
---|
| 52 |
|
---|
| 53 |
|
---|
| 54 | static int usbGetStringAscii(usb_dev_handle *dev, int index, int langid, char *buf, int buflen)
|
---|
| 55 | {
|
---|
| 56 | char buffer[256];
|
---|
| 57 | int rval, i;
|
---|
| 58 |
|
---|
| 59 | if((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + index, langid, buffer, sizeof(buffer), 1000)) < 0)
|
---|
| 60 | return rval;
|
---|
| 61 | if(buffer[1] != USB_DT_STRING)
|
---|
| 62 | return 0;
|
---|
| 63 | if((unsigned char)buffer[0] < rval)
|
---|
| 64 | rval = (unsigned char)buffer[0];
|
---|
| 65 | rval /= 2;
|
---|
| 66 | /* lossy conversion to ISO Latin1 */
|
---|
| 67 | for(i=1;i<rval;i++){
|
---|
| 68 | if(i > buflen) /* destination buffer overflow */
|
---|
| 69 | break;
|
---|
| 70 | buf[i-1] = buffer[2 * i];
|
---|
| 71 | if(buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */
|
---|
| 72 | buf[i-1] = '?';
|
---|
| 73 | }
|
---|
| 74 | buf[i-1] = 0;
|
---|
| 75 | return i-1;
|
---|
| 76 | }
|
---|
| 77 |
|
---|
| 78 |
|
---|
| 79 | /* PowerSwitch uses the free shared default VID/PID. If you want to see an
|
---|
| 80 | * example device lookup where an individually reserved PID is used, see our
|
---|
| 81 | * RemoteSensor reference implementation.
|
---|
| 82 | */
|
---|
| 83 |
|
---|
| 84 | #define USB_ERROR_NOTFOUND 1
|
---|
| 85 | #define USB_ERROR_ACCESS 2
|
---|
| 86 | #define USB_ERROR_IO 3
|
---|
| 87 |
|
---|
| 88 | static int usbOpenDevice(usb_dev_handle **device, int vendor, char *vendorName, int product, char *productName)
|
---|
| 89 | {
|
---|
| 90 | struct usb_bus *bus;
|
---|
| 91 | struct usb_device *dev;
|
---|
| 92 | usb_dev_handle *handle = NULL;
|
---|
| 93 | int errorCode = USB_ERROR_NOTFOUND;
|
---|
| 94 | static int didUsbInit = 0;
|
---|
| 95 |
|
---|
| 96 | if(!didUsbInit){
|
---|
| 97 | didUsbInit = 1;
|
---|
| 98 | usb_init();
|
---|
| 99 | }
|
---|
| 100 | usb_find_busses();
|
---|
| 101 | usb_find_devices();
|
---|
| 102 | for(bus=usb_get_busses(); bus; bus=bus->next){
|
---|
| 103 | for(dev=bus->devices; dev; dev=dev->next){
|
---|
| 104 | if(dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product){
|
---|
| 105 | char string[256];
|
---|
| 106 | int len;
|
---|
| 107 | handle = usb_open(dev); /* we need to open the device in order to query strings */
|
---|
| 108 | if(!handle){
|
---|
| 109 | errorCode = USB_ERROR_ACCESS;
|
---|
| 110 | fprintf(stderr, "Warning: cannot open USB device: %s\n", usb_strerror());
|
---|
| 111 | continue;
|
---|
| 112 | }
|
---|
| 113 | if(vendorName == NULL && productName == NULL){ /* name does not matter */
|
---|
| 114 | break;
|
---|
| 115 | }
|
---|
| 116 | /* now check whether the names match: */
|
---|
| 117 | len = usbGetStringAscii(handle, dev->descriptor.iManufacturer, 0x0409, string, sizeof(string));
|
---|
| 118 | if(len < 0){
|
---|
| 119 | errorCode = USB_ERROR_IO;
|
---|
| 120 | fprintf(stderr, "Warning: cannot query manufacturer for device: %s\n", usb_strerror());
|
---|
| 121 | }else{
|
---|
| 122 | errorCode = USB_ERROR_NOTFOUND;
|
---|
| 123 | /* fprintf(stderr, "seen device from vendor ->%s<-\n", string); */
|
---|
| 124 | if(strcmp(string, vendorName) == 0){
|
---|
| 125 | len = usbGetStringAscii(handle, dev->descriptor.iProduct, 0x0409, string, sizeof(string));
|
---|
| 126 | if(len < 0){
|
---|
| 127 | errorCode = USB_ERROR_IO;
|
---|
| 128 | fprintf(stderr, "Warning: cannot query product for device: %s\n", usb_strerror());
|
---|
| 129 | }else{
|
---|
| 130 | errorCode = USB_ERROR_NOTFOUND;
|
---|
| 131 | /* fprintf(stderr, "seen product ->%s<-\n", string); */
|
---|
| 132 | if(strcmp(string, productName) == 0)
|
---|
| 133 | break;
|
---|
| 134 | }
|
---|
| 135 | }
|
---|
| 136 | }
|
---|
| 137 | usb_close(handle);
|
---|
| 138 | handle = NULL;
|
---|
| 139 | }
|
---|
| 140 | }
|
---|
| 141 | if(handle)
|
---|
| 142 | break;
|
---|
| 143 | }
|
---|
| 144 | if(handle != NULL){
|
---|
| 145 | errorCode = 0;
|
---|
| 146 | *device = handle;
|
---|
| 147 | }
|
---|
| 148 | return errorCode;
|
---|
| 149 | }
|
---|
| 150 |
|
---|
| 151 | void hexdump(unsigned char* bytes, int len)
|
---|
| 152 | {
|
---|
| 153 | for(int i = 0; i <len; i++)
|
---|
| 154 | printf("%X ",bytes[i]);
|
---|
| 155 | puts("");
|
---|
| 156 | }
|
---|
| 157 |
|
---|
| 158 | int main(int argc, char **argv)
|
---|
| 159 | {
|
---|
| 160 | usb_dev_handle *handle = NULL;
|
---|
| 161 | unsigned char buffer[275];
|
---|
| 162 | int nBytes;
|
---|
| 163 |
|
---|
| 164 | if(argc < 2){
|
---|
| 165 | usage(argv[0]);
|
---|
| 166 | exit(1);
|
---|
| 167 | }
|
---|
| 168 | usb_init();
|
---|
| 169 | if(usbOpenDevice(&handle, USBDEV_SHARED_VENDOR, VENDORSTRING, USBDEV_SHARED_PRODUCT, PRODUCTSTRING) != 0){
|
---|
| 170 | fprintf(stderr, "Could not find USB device \""PRODUCTSTRING"\" with vid=0x%x pid=0x%x\n", USBDEV_SHARED_VENDOR, USBDEV_SHARED_PRODUCT);
|
---|
| 171 | exit(1);
|
---|
| 172 | }
|
---|
| 173 | /* We have searched all devices on all busses for our USB device above. Now
|
---|
| 174 | * try to open it and perform the vendor specific control operations for the
|
---|
| 175 | * function requested by the user.
|
---|
| 176 | */
|
---|
| 177 | if(strcmp(argv[1], "get") == 0){
|
---|
| 178 | memset(buffer, 0, 275);
|
---|
| 179 | nBytes = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, PSCMD_GET, 0,0, (char*)buffer, 200, 5000);
|
---|
| 180 | hexdump(buffer, sizeof(buffer));
|
---|
| 181 | }else if(strcmp(argv[1], "put") == 0){
|
---|
[d46151a] | 182 |
|
---|
[88642a4] | 183 | do
|
---|
| 184 | {
|
---|
| 185 | // Wait for motor on
|
---|
| 186 | nBytes = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, PSCMD_STATUS, 0,0, (char*)buffer, 1, 5000);
|
---|
| 187 | usleep(1000000);
|
---|
| 188 | } while (buffer[0] & 8);
|
---|
| 189 |
|
---|
| 190 |
|
---|
[d46151a] | 191 | FILE* fptr = fopen(argv[2], "rb");
|
---|
| 192 | int blockid;
|
---|
| 193 | uint8_t blktype, blksize;
|
---|
| 194 | sscanf(argv[3], "%d", &blockid);
|
---|
| 195 |
|
---|
| 196 | do
|
---|
| 197 | {
|
---|
[88642a4] | 198 | do
|
---|
| 199 | {
|
---|
| 200 | fread(&blktype, 1, 1, fptr);
|
---|
| 201 | if (feof(fptr))
|
---|
| 202 | {
|
---|
| 203 | fprintf(stderr, "end of file.\n");
|
---|
| 204 | fclose(fptr);
|
---|
| 205 | usb_close(handle);
|
---|
| 206 | exit(0);
|
---|
| 207 | }
|
---|
| 208 | }
|
---|
| 209 | while(blktype != 0x5A); // skip sync header
|
---|
| 210 |
|
---|
[d46151a] | 211 | fread(&blktype, 1, 1, fptr);
|
---|
| 212 | fread(&blksize, 1, 1, fptr);
|
---|
| 213 | blksize -= 2;
|
---|
| 214 | fread(buffer, 1, blksize + 1, fptr);
|
---|
[88642a4] | 215 | if (blktype == 0)
|
---|
| 216 | {
|
---|
| 217 | // new file
|
---|
| 218 | printf("%.11s\n",buffer);
|
---|
| 219 | }
|
---|
[d46151a] | 220 | }
|
---|
| 221 | while (blockid --);
|
---|
| 222 |
|
---|
| 223 | fclose(fptr);
|
---|
| 224 |
|
---|
| 225 | hexdump(buffer, blksize);
|
---|
| 226 | int rqtype = (blksize == 0) ? USB_ENDPOINT_IN:USB_ENDPOINT_OUT;
|
---|
| 227 | nBytes = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | rqtype, PSCMD_PUT, blktype,0 /*checksum*/, (char*)buffer, blksize, 5000);
|
---|
[0da6f01] | 228 | }else{
|
---|
| 229 | fprintf(stderr,"Unknown command: %s.\n", argv[1]);
|
---|
| 230 | usage(argv[0]);
|
---|
| 231 | nBytes = 0;
|
---|
| 232 | // TODO manage return code
|
---|
| 233 | }
|
---|
| 234 |
|
---|
| 235 | if (nBytes < 0) fprintf(stderr, "USB error %s\n", usb_strerror());
|
---|
| 236 | usb_close(handle);
|
---|
| 237 | return 0;
|
---|
| 238 | }
|
---|
| 239 |
|
---|