2 * Copyright © 2008 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.
23 #include "cp-usb-async.h"
24 #include "ccdbg-debug.h"
26 #define MAX_OUTSTANDING 256
27 #define CP_TIMEOUT 1000 /* ms */
29 struct cp_usb_packet {
30 struct libusb_transfer *transfer;
31 enum { packet_read, packet_write } direction;
32 unsigned char data[9];
38 libusb_device_handle *handle;
39 struct cp_usb_packet packet[MAX_OUTSTANDING];
46 cp_usb_async_open(void)
48 struct cp_usb_async *cp;
51 cp = calloc(sizeof (struct cp_usb_async), 1);
54 ret = libusb_init(&cp->ctx);
59 cp->handle = libusb_open_device_with_vid_pid(cp->ctx,
63 fprintf(stderr, "Cannot find USB device 10c4:ea60\n");
74 cp_usb_async_close(struct cp_usb_async *cp)
76 libusb_close(cp->handle);
82 cp_usb_async_transfer_callback(struct libusb_transfer *transfer)
84 struct cp_usb_async *cp = transfer->user_data;
87 for (p = 0; p < cp->p; p++)
88 if (cp->packet[p].transfer == transfer)
91 fprintf(stderr, "unknown transfer\n");
94 switch (cp->packet[p].direction) {
96 ccdbg_debug(CC_DEBUG_USB_ASYNC, "ack read %d 0x%02x\n",
97 p, cp->packet[p].data[8]);
98 *cp->packet[p].valuep = cp->packet[p].data[8];
101 ccdbg_debug(CC_DEBUG_USB_ASYNC, "ack write %d\n", p);
109 cp_usb_async_write(struct cp_usb_async *cp, uint8_t mask, uint8_t value)
116 value = (cp->value & ~mask) | (value & mask);
117 mask = value ^ cp->value;
121 gpio_set = ((uint16_t) value << 8) | mask;
122 if (cp->p == MAX_OUTSTANDING)
123 cp_usb_async_sync(cp);
125 if (!cp->packet[p].transfer)
126 cp->packet[p].transfer = libusb_alloc_transfer(0);
127 cp->packet[p].direction = packet_write;
128 libusb_fill_control_setup(cp->packet[p].data,
130 0xff, /* request type */
132 gpio_set, /* index */
135 libusb_fill_control_transfer(cp->packet[p].transfer,
138 cp_usb_async_transfer_callback,
141 ccdbg_debug(CC_DEBUG_USB_ASYNC, "Write packet %d 0x%x 0x%x\n", p, mask, value);
142 ret = libusb_submit_transfer(cp->packet[p].transfer);
144 fprintf(stderr, "libusb_submit_transfer failed %d\n", ret);
149 cp_usb_async_read(struct cp_usb_async *cp, uint8_t *valuep)
154 if (cp->p == MAX_OUTSTANDING)
155 cp_usb_async_sync(cp);
157 if (!cp->packet[p].transfer)
158 cp->packet[p].transfer = libusb_alloc_transfer(0);
159 cp->packet[p].valuep = valuep;
160 cp->packet[p].direction = packet_read;
161 libusb_fill_control_setup(cp->packet[p].data,
163 0xff, /* request type */
168 libusb_fill_control_transfer(cp->packet[p].transfer,
171 cp_usb_async_transfer_callback,
174 ccdbg_debug(CC_DEBUG_USB_ASYNC, "Read packet %d\n", p);
175 ret = libusb_submit_transfer(cp->packet[p].transfer);
177 fprintf(stderr, "libusb_submit_transfer failed %d\n", ret);
182 cp_usb_async_sync(struct cp_usb_async *cp)
184 while (cp->ack < cp->p - 1) {
185 libusb_handle_events(cp->ctx);