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>
|
---|
22 | #include <lusb0_usb.h> /* this is libusb, see http://libusb.sourceforge.net/ */
|
---|
23 |
|
---|
24 | #define USBDEV_SHARED_VENDOR 0x16C0 /* VOTI */
|
---|
25 | #define USBDEV_SHARED_PRODUCT 0x05DC /* Obdev's free shared PID */
|
---|
26 | /* Use obdev's generic shared VID/PID pair and follow the rules outlined
|
---|
27 | * in firmware/usbdrv/USBID-License.txt.
|
---|
28 | */
|
---|
29 |
|
---|
30 | #define VENDORSTRING "pulkomandy.ath.cx"
|
---|
31 | #define PRODUCTSTRING "CrO2"
|
---|
32 |
|
---|
33 | #define PSCMD_CONFIG 0
|
---|
34 | #define PSCMD_GET 1
|
---|
35 | #define PSCMD_PUT 2
|
---|
36 | /* These are the vendor specific SETUP commands implemented by our USB device */
|
---|
37 |
|
---|
38 | static void usage(char *name)
|
---|
39 | {
|
---|
40 | fprintf(stderr, "usage:\n");
|
---|
41 | fprintf(stderr, " %s status\n", name);
|
---|
42 | fprintf(stderr, " %s on <port> [<duration>]\n", name);
|
---|
43 | fprintf(stderr, " %s off <port> [<duration>]\n", name);
|
---|
44 | fprintf(stderr, " %s test\n\n", name);
|
---|
45 | fprintf(stderr, "Ports are single digits in the range 0...7\n");
|
---|
46 | fprintf(stderr, "The pulse duration for switching temporarily is given in seconds.\n");
|
---|
47 | }
|
---|
48 |
|
---|
49 |
|
---|
50 | static int usbGetStringAscii(usb_dev_handle *dev, int index, int langid, char *buf, int buflen)
|
---|
51 | {
|
---|
52 | char buffer[256];
|
---|
53 | int rval, i;
|
---|
54 |
|
---|
55 | if((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + index, langid, buffer, sizeof(buffer), 1000)) < 0)
|
---|
56 | return rval;
|
---|
57 | if(buffer[1] != USB_DT_STRING)
|
---|
58 | return 0;
|
---|
59 | if((unsigned char)buffer[0] < rval)
|
---|
60 | rval = (unsigned char)buffer[0];
|
---|
61 | rval /= 2;
|
---|
62 | /* lossy conversion to ISO Latin1 */
|
---|
63 | for(i=1;i<rval;i++){
|
---|
64 | if(i > buflen) /* destination buffer overflow */
|
---|
65 | break;
|
---|
66 | buf[i-1] = buffer[2 * i];
|
---|
67 | if(buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */
|
---|
68 | buf[i-1] = '?';
|
---|
69 | }
|
---|
70 | buf[i-1] = 0;
|
---|
71 | return i-1;
|
---|
72 | }
|
---|
73 |
|
---|
74 |
|
---|
75 | /* PowerSwitch uses the free shared default VID/PID. If you want to see an
|
---|
76 | * example device lookup where an individually reserved PID is used, see our
|
---|
77 | * RemoteSensor reference implementation.
|
---|
78 | */
|
---|
79 |
|
---|
80 | #define USB_ERROR_NOTFOUND 1
|
---|
81 | #define USB_ERROR_ACCESS 2
|
---|
82 | #define USB_ERROR_IO 3
|
---|
83 |
|
---|
84 | static int usbOpenDevice(usb_dev_handle **device, int vendor, char *vendorName, int product, char *productName)
|
---|
85 | {
|
---|
86 | struct usb_bus *bus;
|
---|
87 | struct usb_device *dev;
|
---|
88 | usb_dev_handle *handle = NULL;
|
---|
89 | int errorCode = USB_ERROR_NOTFOUND;
|
---|
90 | static int didUsbInit = 0;
|
---|
91 |
|
---|
92 | if(!didUsbInit){
|
---|
93 | didUsbInit = 1;
|
---|
94 | usb_init();
|
---|
95 | }
|
---|
96 | usb_find_busses();
|
---|
97 | usb_find_devices();
|
---|
98 | for(bus=usb_get_busses(); bus; bus=bus->next){
|
---|
99 | for(dev=bus->devices; dev; dev=dev->next){
|
---|
100 | if(dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product){
|
---|
101 | char string[256];
|
---|
102 | int len;
|
---|
103 | handle = usb_open(dev); /* we need to open the device in order to query strings */
|
---|
104 | if(!handle){
|
---|
105 | errorCode = USB_ERROR_ACCESS;
|
---|
106 | fprintf(stderr, "Warning: cannot open USB device: %s\n", usb_strerror());
|
---|
107 | continue;
|
---|
108 | }
|
---|
109 | if(vendorName == NULL && productName == NULL){ /* name does not matter */
|
---|
110 | break;
|
---|
111 | }
|
---|
112 | /* now check whether the names match: */
|
---|
113 | len = usbGetStringAscii(handle, dev->descriptor.iManufacturer, 0x0409, string, sizeof(string));
|
---|
114 | if(len < 0){
|
---|
115 | errorCode = USB_ERROR_IO;
|
---|
116 | fprintf(stderr, "Warning: cannot query manufacturer for device: %s\n", usb_strerror());
|
---|
117 | }else{
|
---|
118 | errorCode = USB_ERROR_NOTFOUND;
|
---|
119 | /* fprintf(stderr, "seen device from vendor ->%s<-\n", string); */
|
---|
120 | if(strcmp(string, vendorName) == 0){
|
---|
121 | len = usbGetStringAscii(handle, dev->descriptor.iProduct, 0x0409, string, sizeof(string));
|
---|
122 | if(len < 0){
|
---|
123 | errorCode = USB_ERROR_IO;
|
---|
124 | fprintf(stderr, "Warning: cannot query product for device: %s\n", usb_strerror());
|
---|
125 | }else{
|
---|
126 | errorCode = USB_ERROR_NOTFOUND;
|
---|
127 | /* fprintf(stderr, "seen product ->%s<-\n", string); */
|
---|
128 | if(strcmp(string, productName) == 0)
|
---|
129 | break;
|
---|
130 | }
|
---|
131 | }
|
---|
132 | }
|
---|
133 | usb_close(handle);
|
---|
134 | handle = NULL;
|
---|
135 | }
|
---|
136 | }
|
---|
137 | if(handle)
|
---|
138 | break;
|
---|
139 | }
|
---|
140 | if(handle != NULL){
|
---|
141 | errorCode = 0;
|
---|
142 | *device = handle;
|
---|
143 | }
|
---|
144 | return errorCode;
|
---|
145 | }
|
---|
146 |
|
---|
147 | void hexdump(unsigned char* bytes, int len)
|
---|
148 | {
|
---|
149 | for(int i = 0; i <len; i++)
|
---|
150 | printf("%X ",bytes[i]);
|
---|
151 | puts("");
|
---|
152 | }
|
---|
153 |
|
---|
154 | int main(int argc, char **argv)
|
---|
155 | {
|
---|
156 | usb_dev_handle *handle = NULL;
|
---|
157 | unsigned char buffer[275];
|
---|
158 | int nBytes;
|
---|
159 |
|
---|
160 | if(argc < 2){
|
---|
161 | usage(argv[0]);
|
---|
162 | exit(1);
|
---|
163 | }
|
---|
164 | usb_init();
|
---|
165 | if(usbOpenDevice(&handle, USBDEV_SHARED_VENDOR, VENDORSTRING, USBDEV_SHARED_PRODUCT, PRODUCTSTRING) != 0){
|
---|
166 | fprintf(stderr, "Could not find USB device \""PRODUCTSTRING"\" with vid=0x%x pid=0x%x\n", USBDEV_SHARED_VENDOR, USBDEV_SHARED_PRODUCT);
|
---|
167 | exit(1);
|
---|
168 | }
|
---|
169 | /* We have searched all devices on all busses for our USB device above. Now
|
---|
170 | * try to open it and perform the vendor specific control operations for the
|
---|
171 | * function requested by the user.
|
---|
172 | */
|
---|
173 | if(strcmp(argv[1], "get") == 0){
|
---|
174 | memset(buffer, 0, 275);
|
---|
175 | nBytes = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, PSCMD_GET, 0,0, (char*)buffer, 200, 5000);
|
---|
176 | hexdump(buffer, sizeof(buffer));
|
---|
177 | }else if(strcmp(argv[1], "put") == 0){
|
---|
178 | hexdump(buffer, sizeof(buffer));
|
---|
179 | nBytes = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, PSCMD_PUT, 0,0, (char*)buffer, 200, 5000);
|
---|
180 | }else{
|
---|
181 | fprintf(stderr,"Unknown command: %s.\n", argv[1]);
|
---|
182 | usage(argv[0]);
|
---|
183 | nBytes = 0;
|
---|
184 | // TODO manage return code
|
---|
185 | }
|
---|
186 |
|
---|
187 | if (nBytes < 0) fprintf(stderr, "USB error %s\n", usb_strerror());
|
---|
188 |
|
---|
189 | usb_close(handle);
|
---|
190 | return 0;
|
---|
191 | }
|
---|
192 |
|
---|