2 * Copyright © 2016 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
30 #define CHAOS_VENDOR 0x1d50
31 #define CHAOS_PRODUCT 0x60c6
35 libusb_device_handle *handle;
39 libusb_device_handle *
40 chaoskey_match(libusb_device *dev, char *match_serial)
42 struct libusb_device_descriptor desc;
45 char *device_serial = NULL;
46 libusb_device_handle *handle = NULL;
48 ret = libusb_get_device_descriptor(dev, &desc);
50 fprintf(stderr, "failed to get device descriptor: %s\n", libusb_strerror(ret));
54 if (desc.idVendor != CHAOS_VENDOR)
56 if (desc.idProduct != CHAOS_PRODUCT)
59 ret = libusb_open(dev, &handle);
61 if (match_serial == NULL)
65 fprintf(stderr, "failed to open device: %s\n", libusb_strerror(ret));
69 match_len = strlen(match_serial);
70 device_serial = malloc(match_len + 2);
73 fprintf(stderr, "malloc failed\n");
77 ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, (unsigned char *) device_serial, match_len + 1);
80 fprintf(stderr, "failed to get serial number: %s\n", libusb_strerror(ret));
84 device_serial[ret] = '\0';
86 ret = strcmp(device_serial, match_serial);
100 chaoskey_open(char *serial)
105 libusb_device **list;
108 ck = calloc(sizeof (struct chaoskey), 1);
111 ret = libusb_init(&ck->ctx);
113 fprintf(stderr, "libusb_init failed: %s\n", libusb_strerror(ret));
117 num = libusb_get_device_list(ck->ctx, &list);
119 fprintf(stderr, "libusb_get_device_list failed: %s\n", libusb_strerror(num));
123 for (d = 0; d < num; d++) {
124 libusb_device_handle *handle;
126 handle = chaoskey_match(list[d], serial);
133 libusb_free_device_list(list, 1);
137 fprintf (stderr, "No chaoskey matching %s\n", serial);
139 fprintf (stderr, "No chaoskey\n");
143 ck->kernel_active = libusb_kernel_driver_active(ck->handle, 0);
144 if (ck->kernel_active) {
145 ret = libusb_detach_kernel_driver(ck->handle, 0);
150 ret = libusb_claim_interface(ck->handle, 0);
156 if (ck->kernel_active)
157 libusb_attach_kernel_driver(ck->handle, 0);
159 libusb_exit(ck->ctx);
165 chaoskey_close(struct chaoskey *ck)
167 libusb_release_interface(ck->handle, 0);
168 if (ck->kernel_active)
169 libusb_attach_kernel_driver(ck->handle, 0);
170 libusb_close(ck->handle);
171 libusb_exit(ck->ctx);
175 #define COOKED_ENDPOINT 0x85
176 #define RAW_ENDPOINT 0x86
177 #define FLASH_ENDPOINT 0x87
180 chaoskey_read(struct chaoskey *ck, int endpoint, void *buffer, int len)
182 uint8_t *buf = buffer;
189 ret = libusb_bulk_transfer(ck->handle, endpoint, buf, len, &transferred, 10000);
200 total += transferred;
205 static const struct option options[] = {
206 { .name = "serial", .has_arg = 1, .val = 's' },
207 { .name = "length", .has_arg = 1, .val = 'l' },
208 { .name = "infinite", .has_arg = 0, .val = 'i' },
209 { .name = "bytes", .has_arg = 0, .val = 'b' },
210 { .name = "cooked", .has_arg = 0, .val = 'c' },
211 { .name = "raw", .has_arg = 0, .val = 'r' },
212 { .name = "flash", .has_arg = 0, .val = 'f' },
216 static void usage(char *program)
218 fprintf(stderr, "usage: %s [--serial=<serial>] [--length=<length>[kMG]] [--infinite] [--bytes] [--cooked] [--raw] [--flash]\n", program);
223 main (int argc, char **argv)
232 unsigned long length = sizeof(buf);
236 int endpoint = RAW_ENDPOINT;
238 while ((c = getopt_long(argc, argv, "s:l:ibcrf", options, NULL)) != -1) {
244 length_string = optarg;
245 length = strtoul(length_string, &length_end, 10);
246 if (!strcasecmp(length_end, "k"))
248 else if (!strcasecmp(length_end, "m"))
249 length *= 1024 * 1024;
250 else if (!strcasecmp(length_end, "g"))
251 length *= 1024 * 1024 * 1024;
252 else if (strlen(length_end))
262 endpoint = COOKED_ENDPOINT;
265 endpoint = RAW_ENDPOINT;
268 endpoint = FLASH_ENDPOINT;
276 ck = chaoskey_open(serial);
283 while (length || infinite) {
284 this_time = sizeof(buf);
285 if (!infinite && length < sizeof(buf))
286 this_time = (int) length;
287 got = chaoskey_read(ck, endpoint, buf, this_time);
294 for (i = 0; i < got / 2; i++)
295 putchar((buf[i] >> 1 & 0xff));
299 for (i = 0; i < got; i += ret) {
300 ret = write(1, ((char *) buf) + i, got - i);