]>
Commit | Line | Data |
---|---|---|
1 | #include <string.h> | |
2 | #include <stdio.h> | |
3 | #include <stdint.h> | |
4 | #include <unistd.h> | |
5 | #include <stdlib.h> | |
6 | #include <libusb-1.0/libusb.h> | |
7 | ||
8 | #define USB_TIMEOUT 10000 | |
9 | ||
10 | #define ID_VENDOR 0x18ef | |
11 | #define ID_PRODUCT 0xe015 | |
12 | ||
13 | /* Not in all libusb-1.0 versions, so we have to roll our own :-( */ | |
14 | static char * usb_strerror(int e) | |
15 | { | |
16 | static char unknerr[256]; | |
17 | ||
18 | switch (e) { | |
19 | case LIBUSB_SUCCESS: | |
20 | return "Success"; | |
21 | case LIBUSB_ERROR_IO: | |
22 | return "Input/output error"; | |
23 | case LIBUSB_ERROR_INVALID_PARAM: | |
24 | return "Invalid parameter"; | |
25 | case LIBUSB_ERROR_ACCESS: | |
26 | return "Access denied (insufficient permissions)"; | |
27 | case LIBUSB_ERROR_NO_DEVICE: | |
28 | return "No such device (it may have been disconnected)"; | |
29 | case LIBUSB_ERROR_NOT_FOUND: | |
30 | return "Entity not found"; | |
31 | case LIBUSB_ERROR_BUSY: | |
32 | return "Resource busy"; | |
33 | case LIBUSB_ERROR_TIMEOUT: | |
34 | return "Operation timed out"; | |
35 | case LIBUSB_ERROR_OVERFLOW: | |
36 | return "Overflow"; | |
37 | case LIBUSB_ERROR_PIPE: | |
38 | return "Pipe error"; | |
39 | case LIBUSB_ERROR_INTERRUPTED: | |
40 | return "System call interrupted (perhaps due to signal)"; | |
41 | case LIBUSB_ERROR_NO_MEM: | |
42 | return "Insufficient memory"; | |
43 | case LIBUSB_ERROR_NOT_SUPPORTED: | |
44 | return "Operation not supported or unimplemented on this platform"; | |
45 | case LIBUSB_ERROR_OTHER: | |
46 | return "Other error"; | |
47 | }; | |
48 | snprintf(unknerr, sizeof(unknerr), "Unknown error code %d / 0x%02x", e, e); | |
49 | return unknerr; | |
50 | } | |
51 | ||
52 | libusb_device_handle *fs20pcs_find() { | |
53 | libusb_device_handle *devh = NULL; | |
54 | libusb_device **list; | |
55 | ssize_t cnt; | |
56 | ssize_t i; | |
57 | int err; | |
58 | ||
59 | cnt = libusb_get_device_list(NULL, &list); | |
60 | if (cnt < 0) { | |
61 | fprintf(stderr, "Can't get USB device list: %d\n", (int)cnt); | |
62 | return NULL; | |
63 | } | |
64 | ||
65 | for (i = 0; i < cnt; i++){ | |
66 | struct libusb_device_descriptor desc; | |
67 | ||
68 | err = libusb_get_device_descriptor(list[i], &desc); | |
69 | if (err) | |
70 | continue; | |
71 | ||
72 | if ((desc.idVendor == ID_VENDOR) && (desc.idProduct == ID_PRODUCT)) { | |
73 | libusb_device *dev = list[i]; | |
74 | ||
75 | err = libusb_open(dev, &devh); | |
76 | if (err) { | |
77 | fprintf(stderr, "Can't open device: %s\n", usb_strerror(err)); | |
78 | return NULL; | |
79 | } | |
80 | ||
81 | err = libusb_detach_kernel_driver(devh, 0); | |
82 | if ((err != 0) && (err != LIBUSB_ERROR_NOT_FOUND)) { | |
83 | fprintf(stderr, "Can't detach kernel driver: %s\n", usb_strerror(err)); | |
84 | return NULL; | |
85 | } | |
86 | ||
87 | err = libusb_claim_interface(devh, 0); | |
88 | if ((err != 0)) { | |
89 | fprintf(stderr, "Can't claim interface: %s\n", usb_strerror(err)); | |
90 | return NULL; | |
91 | } | |
92 | ||
93 | return devh; | |
94 | } | |
95 | ||
96 | } | |
97 | ||
98 | return NULL; | |
99 | } | |
100 | ||
101 | int fs20pcs_send(libusb_device_handle *devh, unsigned char* send_data) | |
102 | { | |
103 | unsigned char recv_data[5] = {0x00, 0x00, 0x00, 0x00, 0x00}; | |
104 | int err; | |
105 | int cnt; | |
106 | int i; | |
107 | int ret; | |
108 | ||
109 | err = libusb_interrupt_transfer(devh, 0x01, send_data, 11, &cnt, 5000); | |
110 | if (err) { | |
111 | fprintf(stderr, "Can't send data: %s\n", usb_strerror(err)); | |
112 | return 0; | |
113 | } | |
114 | ||
115 | err = libusb_interrupt_transfer(devh, 0x81, recv_data, sizeof(recv_data), &cnt, 5000); | |
116 | if (err) { | |
117 | fprintf(stderr, "Can't receive data: %s\n", usb_strerror(err)); | |
118 | return 0; | |
119 | } | |
120 | ||
121 | if ((recv_data[0] != 0x02) || | |
122 | (recv_data[1] != 0x03) || | |
123 | (recv_data[2] != 0xa0)) { | |
124 | fprintf(stderr, "Unexpected response: "); | |
125 | for (i = 0; i < cnt; i++) { | |
126 | fprintf(stderr, "0x%02x ", recv_data[i]); | |
127 | } | |
128 | fprintf(stderr, "\n"); | |
129 | ||
130 | return 0; | |
131 | } | |
132 | ||
133 | ret = 1; | |
134 | ||
135 | switch(recv_data[3]) { | |
136 | case 0x00: | |
137 | printf("Success"); | |
138 | break; | |
139 | case 0x01: | |
140 | printf("Firmware V%d.%d", ((recv_data[4] & 0xf0) >> 4) & 0x0f, recv_data[4] & 0x0f); | |
141 | break; | |
142 | case 0x02: | |
143 | printf("Unknown command"); | |
144 | ret = 0; | |
145 | break; | |
146 | case 0x03: | |
147 | printf("Wrong length"); | |
148 | ret = 0; | |
149 | break; | |
150 | case 0x04: | |
151 | printf("Aborted sending long press"); | |
152 | break; | |
153 | case 0x05: | |
154 | printf("Nothing to stop"); | |
155 | break; | |
156 | default: | |
157 | printf("Unknown response: 0x%02x 0x%02x", recv_data[3], recv_data[4]); | |
158 | ret = 0; | |
159 | break; | |
160 | } | |
161 | ||
162 | printf("\n"); | |
163 | ||
164 | return ret; | |
165 | } | |
166 | ||
167 | int main(int argc, char **argv) | |
168 | { | |
169 | unsigned char send_data[11]; | |
170 | libusb_device_handle *devh = NULL; | |
171 | int err; | |
172 | int i; | |
173 | ||
174 | if ((argc < 2) || (argc > 12)) { | |
175 | fprintf(stderr, "Invalid number of parameters!\n"); | |
176 | return EXIT_FAILURE; | |
177 | } | |
178 | ||
179 | memset(send_data, 0, sizeof(send_data)); | |
180 | for (i = 0; i < argc - 1; i++) { | |
181 | send_data[i] = strtoul(argv[i+1], NULL, 16); | |
182 | } | |
183 | ||
184 | err = libusb_init(NULL); | |
185 | if (err != 0) { | |
186 | fprintf(stderr, "Can't initialize libusb: %s\n", usb_strerror(err)); | |
187 | return EXIT_FAILURE; | |
188 | } | |
189 | ||
190 | devh = fs20pcs_find(); | |
191 | if (!devh) { | |
192 | fprintf(stderr, "Can't find/open fs20pcs!\n"); | |
193 | return EXIT_FAILURE; | |
194 | } | |
195 | ||
196 | if (fs20pcs_send(devh, send_data) == 0) { | |
197 | fprintf(stderr, "Can't communicate with fs20pcs!\n"); | |
198 | return EXIT_FAILURE; | |
199 | } | |
200 | ||
201 | libusb_close(NULL); | |
202 | ||
203 | return EXIT_SUCCESS; | |
204 | } |