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 <iup.h>
|
---|
26 | #include <iupcontrols.h>
|
---|
27 |
|
---|
28 | #include <lusb0_usb.h> /* this is libusb, see http://libusb.sourceforge.net/ */
|
---|
29 |
|
---|
30 | #define USBDEV_SHARED_VENDOR 0x16C0 /* VOTI */
|
---|
31 | #define USBDEV_SHARED_PRODUCT 0x05DC /* Obdev's free shared PID */
|
---|
32 | /* Use obdev's generic shared VID/PID pair and follow the rules outlined
|
---|
33 | * in firmware/usbdrv/USBID-License.txt.
|
---|
34 | */
|
---|
35 |
|
---|
36 | #define VENDORSTRING (char*)"pulkomandy.ath.cx"
|
---|
37 | #define PRODUCTSTRING "CrO2"
|
---|
38 |
|
---|
39 | /* These are the vendor specific SETUP commands implemented by our USB device */
|
---|
40 | #define PSCMD_CONFIG 0
|
---|
41 | #define PSCMD_GET 1
|
---|
42 | #define PSCMD_PUT 2
|
---|
43 | #define PSCMD_STATUS 3
|
---|
44 |
|
---|
45 | static int usbGetStringAscii(usb_dev_handle *dev, int index, int langid, char *buf, int buflen)
|
---|
46 | {
|
---|
47 | char buffer[256];
|
---|
48 | int rval, i;
|
---|
49 |
|
---|
50 | if((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + index, langid, buffer, sizeof(buffer), 1000)) < 0)
|
---|
51 | return rval;
|
---|
52 | if(buffer[1] != USB_DT_STRING)
|
---|
53 | return 0;
|
---|
54 | if((unsigned char)buffer[0] < rval)
|
---|
55 | rval = (unsigned char)buffer[0];
|
---|
56 | rval /= 2;
|
---|
57 | /* lossy conversion to ISO Latin1 */
|
---|
58 | for(i=1;i<rval;i++){
|
---|
59 | if(i > buflen) /* destination buffer overflow */
|
---|
60 | break;
|
---|
61 | buf[i-1] = buffer[2 * i];
|
---|
62 | if(buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */
|
---|
63 | buf[i-1] = '?';
|
---|
64 | }
|
---|
65 | buf[i-1] = 0;
|
---|
66 | return i-1;
|
---|
67 | }
|
---|
68 |
|
---|
69 |
|
---|
70 | /* PowerSwitch uses the free shared default VID/PID. If you want to see an
|
---|
71 | * example device lookup where an individually reserved PID is used, see our
|
---|
72 | * RemoteSensor reference implementation.
|
---|
73 | */
|
---|
74 |
|
---|
75 | #define USB_ERROR_NOTFOUND 1
|
---|
76 | #define USB_ERROR_ACCESS 2
|
---|
77 | #define USB_ERROR_IO 3
|
---|
78 |
|
---|
79 | static int usbOpenDevice(usb_dev_handle **device, int vendor, char *vendorName, int product, char *productName)
|
---|
80 | {
|
---|
81 | struct usb_bus *bus;
|
---|
82 | struct usb_device *dev;
|
---|
83 | usb_dev_handle *handle = NULL;
|
---|
84 | int errorCode = USB_ERROR_NOTFOUND;
|
---|
85 | static int didUsbInit = 0;
|
---|
86 |
|
---|
87 | if(!didUsbInit){
|
---|
88 | didUsbInit = 1;
|
---|
89 | usb_init();
|
---|
90 | }
|
---|
91 | usb_find_busses();
|
---|
92 | usb_find_devices();
|
---|
93 | for(bus=usb_get_busses(); bus; bus=bus->next){
|
---|
94 | for(dev=bus->devices; dev; dev=dev->next){
|
---|
95 | if(dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product){
|
---|
96 | char string[256];
|
---|
97 | int len;
|
---|
98 | handle = usb_open(dev); /* we need to open the device in order to query strings */
|
---|
99 | if(!handle){
|
---|
100 | errorCode = USB_ERROR_ACCESS;
|
---|
101 | fprintf(stderr, "Warning: cannot open USB device: %s\n", usb_strerror());
|
---|
102 | continue;
|
---|
103 | }
|
---|
104 | if(vendorName == NULL && productName == NULL){ /* name does not matter */
|
---|
105 | break;
|
---|
106 | }
|
---|
107 | /* now check whether the names match: */
|
---|
108 | len = usbGetStringAscii(handle, dev->descriptor.iManufacturer, 0x0409, string, sizeof(string));
|
---|
109 | if(len < 0){
|
---|
110 | errorCode = USB_ERROR_IO;
|
---|
111 | fprintf(stderr, "Warning: cannot query manufacturer for device: %s\n", usb_strerror());
|
---|
112 | }else{
|
---|
113 | errorCode = USB_ERROR_NOTFOUND;
|
---|
114 | /* fprintf(stderr, "seen device from vendor ->%s<-\n", string); */
|
---|
115 | if(strcmp(string, vendorName) == 0){
|
---|
116 | len = usbGetStringAscii(handle, dev->descriptor.iProduct, 0x0409, string, sizeof(string));
|
---|
117 | if(len < 0){
|
---|
118 | errorCode = USB_ERROR_IO;
|
---|
119 | fprintf(stderr, "Warning: cannot query product for device: %s\n", usb_strerror());
|
---|
120 | }else{
|
---|
121 | errorCode = USB_ERROR_NOTFOUND;
|
---|
122 | /* fprintf(stderr, "seen product ->%s<-\n", string); */
|
---|
123 | if(strcmp(string, productName) == 0)
|
---|
124 | break;
|
---|
125 | }
|
---|
126 | }
|
---|
127 | }
|
---|
128 | usb_close(handle);
|
---|
129 | handle = NULL;
|
---|
130 | }
|
---|
131 | }
|
---|
132 | if(handle)
|
---|
133 | break;
|
---|
134 | }
|
---|
135 | if(handle != NULL){
|
---|
136 | errorCode = 0;
|
---|
137 | *device = handle;
|
---|
138 | }
|
---|
139 | return errorCode;
|
---|
140 | }
|
---|
141 |
|
---|
142 | void hexdump(unsigned char* bytes, int len)
|
---|
143 | {
|
---|
144 | for(int i = 0; i <len; i++)
|
---|
145 | printf("%X ",bytes[i]);
|
---|
146 | puts("");
|
---|
147 | }
|
---|
148 |
|
---|
149 |
|
---|
150 | int menu_open(Ihandle* that)
|
---|
151 | {
|
---|
152 | IupPopup(IupFileDlg(), IUP_CENTER, IUP_CENTER);
|
---|
153 | return IUP_DEFAULT;
|
---|
154 | }
|
---|
155 |
|
---|
156 |
|
---|
157 | void GUI_open(int* argc, char*** argv)
|
---|
158 | {
|
---|
159 | IupOpen(argc, argv);
|
---|
160 | // IupControlsOpen();
|
---|
161 |
|
---|
162 | IupSetFunction("OPEN", menu_open);
|
---|
163 |
|
---|
164 | Ihandle* menu = IupMenu(
|
---|
165 | IupSubmenu("File",
|
---|
166 | IupMenu(
|
---|
167 | IupItem("Open", "OPEN"),
|
---|
168 | IupItem("Exit", "IUP_CLOSE"),
|
---|
169 | NULL
|
---|
170 | )
|
---|
171 | ),
|
---|
172 | NULL
|
---|
173 | );
|
---|
174 |
|
---|
175 | Ihandle* platformlist = IupList(NULL);
|
---|
176 | IupSetAttribute(platformlist, "EXPAND", "HORIZONTAL");
|
---|
177 | IupSetAttribute(platformlist, "DROPDOWN", "YES");
|
---|
178 | IupSetAttribute(platformlist, "1", "MO5");
|
---|
179 | IupSetAttribute(platformlist, "VALUE", "1");
|
---|
180 |
|
---|
181 | Ihandle* blocklist = IupTree();
|
---|
182 | IupSetAttribute(blocklist, "EXPAND", "VERTICAL");
|
---|
183 |
|
---|
184 | Ihandle* tabs = IupTabs(
|
---|
185 | IupVbox(
|
---|
186 | IupLabel("Hello World"),
|
---|
187 | NULL
|
---|
188 | ),
|
---|
189 | IupVbox(
|
---|
190 | IupHbox(
|
---|
191 | IupLabel("Format:"),
|
---|
192 | platformlist,
|
---|
193 | NULL
|
---|
194 | ),
|
---|
195 | IupHbox(
|
---|
196 | blocklist,
|
---|
197 | IupVbox(
|
---|
198 | // IupMatrix(NULL),
|
---|
199 | IupLabel("Checksum:"),
|
---|
200 | NULL
|
---|
201 | ),
|
---|
202 | NULL
|
---|
203 | )
|
---|
204 | ),
|
---|
205 | NULL
|
---|
206 | );
|
---|
207 |
|
---|
208 | IupSetAttribute(tabs,"TABTITLE0", "Control");
|
---|
209 | IupSetAttribute(tabs,"TABTITLE1", "Explore");
|
---|
210 |
|
---|
211 | Ihandle* dialog = IupDialog(tabs);
|
---|
212 | IupSetAttribute(dialog, "TITLE", "CrO2 tape emulator");
|
---|
213 | IupSetAttributeHandle(dialog, "MENU", menu);
|
---|
214 | IupShow(dialog);
|
---|
215 |
|
---|
216 | IupMainLoop();
|
---|
217 |
|
---|
218 | IupClose();
|
---|
219 | }
|
---|
220 |
|
---|
221 |
|
---|
222 | int main(int argc, char **argv)
|
---|
223 | {
|
---|
224 | usb_dev_handle *handle = NULL;
|
---|
225 | unsigned char buffer[275];
|
---|
226 | int nBytes = 0;
|
---|
227 |
|
---|
228 | if(argc < 2){
|
---|
229 | GUI_open(&argc, &argv);
|
---|
230 | exit(0);
|
---|
231 | }
|
---|
232 | usb_init();
|
---|
233 | if(usbOpenDevice(&handle, USBDEV_SHARED_VENDOR, VENDORSTRING, USBDEV_SHARED_PRODUCT, (char*)PRODUCTSTRING) != 0){
|
---|
234 | fprintf(stderr, "Could not find USB device \""PRODUCTSTRING"\" with vid=0x%x pid=0x%x\n", USBDEV_SHARED_VENDOR, USBDEV_SHARED_PRODUCT);
|
---|
235 | exit(1);
|
---|
236 | }
|
---|
237 | /* We have searched all devices on all busses for our USB device above. Now
|
---|
238 | * try to open it and perform the vendor specific control operations for the
|
---|
239 | * function requested by the user.
|
---|
240 | */
|
---|
241 | if(strcmp(argv[1], "get") == 0){
|
---|
242 | memset(buffer, 0, 275);
|
---|
243 | nBytes = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, PSCMD_GET, 0,0, (char*)buffer, 200, 5000);
|
---|
244 | hexdump(buffer, sizeof(buffer));
|
---|
245 | }else if(strcmp(argv[1], "put") == 0){
|
---|
246 |
|
---|
247 | do
|
---|
248 | {
|
---|
249 | // Wait for motor on
|
---|
250 | nBytes = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, PSCMD_STATUS, 0,0, (char*)buffer, 1, 5000);
|
---|
251 | usleep(1000000);
|
---|
252 | } while (buffer[0] & 8);
|
---|
253 |
|
---|
254 |
|
---|
255 | FILE* fptr = fopen(argv[2], "rb");
|
---|
256 | int blockid;
|
---|
257 | uint8_t blktype, blksize;
|
---|
258 | sscanf(argv[3], "%d", &blockid);
|
---|
259 |
|
---|
260 | do
|
---|
261 | {
|
---|
262 | do
|
---|
263 | {
|
---|
264 | fread(&blktype, 1, 1, fptr);
|
---|
265 | if (feof(fptr))
|
---|
266 | {
|
---|
267 | fprintf(stderr, "end of file.\n");
|
---|
268 | fclose(fptr);
|
---|
269 | usb_close(handle);
|
---|
270 | exit(0);
|
---|
271 | }
|
---|
272 | }
|
---|
273 | while(blktype != 0x5A); // skip sync header
|
---|
274 |
|
---|
275 | fread(&blktype, 1, 1, fptr);
|
---|
276 | fread(&blksize, 1, 1, fptr);
|
---|
277 | blksize -= 2;
|
---|
278 | fread(buffer, 1, blksize + 1, fptr);
|
---|
279 | if (blktype == 0)
|
---|
280 | {
|
---|
281 | // new file
|
---|
282 | printf("%.11s\n",buffer);
|
---|
283 | }
|
---|
284 | }
|
---|
285 | while (blockid --);
|
---|
286 |
|
---|
287 | fclose(fptr);
|
---|
288 |
|
---|
289 | hexdump(buffer, blksize);
|
---|
290 | int rqtype = (blksize == 0) ? USB_ENDPOINT_IN:USB_ENDPOINT_OUT;
|
---|
291 | nBytes = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | rqtype, PSCMD_PUT, blktype,0 /*checksum*/, (char*)buffer, blksize, 5000);
|
---|
292 | }else{
|
---|
293 | GUI_open(&argc, &argv);
|
---|
294 | }
|
---|
295 |
|
---|
296 | if (nBytes < 0) fprintf(stderr, "USB error %s\n", usb_strerror());
|
---|
297 | usb_close(handle);
|
---|
298 | return 0;
|
---|
299 | }
|
---|
300 |
|
---|