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 <stdint.h>
|
---|
23 | #include <unistd.h>
|
---|
24 |
|
---|
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 |
|
---|
36 | /* These are the vendor specific SETUP commands implemented by our USB device */
|
---|
37 | #define PSCMD_CONFIG 0
|
---|
38 | #define PSCMD_GET 1
|
---|
39 | #define PSCMD_PUT 2
|
---|
40 | #define PSCMD_STATUS 3
|
---|
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){
|
---|
182 |
|
---|
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 |
|
---|
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 | {
|
---|
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 |
|
---|
211 | fread(&blktype, 1, 1, fptr);
|
---|
212 | fread(&blksize, 1, 1, fptr);
|
---|
213 | blksize -= 2;
|
---|
214 | fread(buffer, 1, blksize + 1, fptr);
|
---|
215 | if (blktype == 0)
|
---|
216 | {
|
---|
217 | // new file
|
---|
218 | printf("%.11s\n",buffer);
|
---|
219 | }
|
---|
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);
|
---|
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 |
|
---|