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,
73 cp_usb_async_close(struct cp_usb_async *cp)
75 libusb_close(cp->handle);
81 cp_usb_async_transfer_callback(struct libusb_transfer *transfer)
83 struct cp_usb_async *cp = transfer->user_data;
86 for (p = 0; p < cp->p; p++)
87 if (cp->packet[p].transfer == transfer)
90 fprintf(stderr, "unknown transfer\n");
93 switch (cp->packet[p].direction) {
95 ccdbg_debug(CC_DEBUG_USB_ASYNC, "ack read %d 0x%02x\n",
96 p, cp->packet[p].data[8]);
97 *cp->packet[p].valuep = cp->packet[p].data[8];
100 ccdbg_debug(CC_DEBUG_USB_ASYNC, "ack write %d\n", p);
108 cp_usb_async_write(struct cp_usb_async *cp, uint8_t mask, uint8_t value)
115 value = (cp->value & ~mask) | (value & mask);
116 mask = value ^ cp->value;
120 gpio_set = ((uint16_t) value << 8) | mask;
121 if (cp->p == MAX_OUTSTANDING)
122 cp_usb_async_sync(cp);
124 if (!cp->packet[p].transfer)
125 cp->packet[p].transfer = libusb_alloc_transfer(0);
126 cp->packet[p].direction = packet_write;
127 libusb_fill_control_setup(cp->packet[p].data,
129 0xff, /* request type */
131 gpio_set, /* index */
134 libusb_fill_control_transfer(cp->packet[p].transfer,
137 cp_usb_async_transfer_callback,
140 ccdbg_debug(CC_DEBUG_USB_ASYNC, "Write packet %d 0x%x 0x%x\n", p, mask, value);
141 ret = libusb_submit_transfer(cp->packet[p].transfer);
143 fprintf(stderr, "libusb_submit_transfer failed %d\n", ret);
148 cp_usb_async_read(struct cp_usb_async *cp, uint8_t *valuep)
153 if (cp->p == MAX_OUTSTANDING)
154 cp_usb_async_sync(cp);
156 if (!cp->packet[p].transfer)
157 cp->packet[p].transfer = libusb_alloc_transfer(0);
158 cp->packet[p].valuep = valuep;
159 cp->packet[p].direction = packet_read;
160 libusb_fill_control_setup(cp->packet[p].data,
162 0xff, /* request type */
167 libusb_fill_control_transfer(cp->packet[p].transfer,
170 cp_usb_async_transfer_callback,
173 ccdbg_debug(CC_DEBUG_USB_ASYNC, "Read packet %d\n", p);
174 ret = libusb_submit_transfer(cp->packet[p].transfer);
176 fprintf(stderr, "libusb_submit_transfer failed %d\n", ret);
181 cp_usb_async_sync(struct cp_usb_async *cp)
183 while (cp->ack < cp->p - 1) {
184 libusb_handle_events(cp->ctx);