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];
44 cp_usb_async_open(void)
46 struct cp_usb_async *cp;
49 cp = calloc(sizeof (struct cp_usb_async), 1);
52 ret = libusb_init(&cp->ctx);
57 cp->handle = libusb_open_device_with_vid_pid(cp->ctx,
68 cp_usb_async_close(struct cp_usb_async *cp)
70 libusb_close(cp->handle);
76 cp_usb_async_transfer_callback(struct libusb_transfer *transfer)
78 struct cp_usb_async *cp = transfer->user_data;
81 for (p = 0; p < cp->p; p++)
82 if (cp->packet[p].transfer == transfer)
85 fprintf(stderr, "unknown transfer\n");
88 switch (cp->packet[p].direction) {
90 ccdbg_debug(CC_DEBUG_USB_ASYNC, "ack read %d 0x%02x\n",
91 p, cp->packet[p].data[8]);
92 *cp->packet[p].valuep = cp->packet[p].data[8];
95 ccdbg_debug(CC_DEBUG_USB_ASYNC, "ack write %d\n", p);
103 cp_usb_async_write(struct cp_usb_async *cp, uint8_t mask, uint8_t value)
106 uint16_t gpio_set = ((uint16_t) value << 8) | mask;
109 if (cp->p == MAX_OUTSTANDING)
110 cp_usb_async_sync(cp);
112 if (!cp->packet[p].transfer)
113 cp->packet[p].transfer = libusb_alloc_transfer(0);
114 cp->packet[p].direction = packet_write;
115 libusb_fill_control_setup(cp->packet[p].data,
117 0xff, /* request type */
119 gpio_set, /* index */
122 libusb_fill_control_transfer(cp->packet[p].transfer,
125 cp_usb_async_transfer_callback,
128 ccdbg_debug(CC_DEBUG_USB_ASYNC, "Write packet %d 0x%x 0x%x\n", p, mask, value);
129 ret = libusb_submit_transfer(cp->packet[p].transfer);
131 fprintf(stderr, "libusb_submit_transfer failed %d\n", ret);
136 cp_usb_async_read(struct cp_usb_async *cp, uint8_t *valuep)
141 if (cp->p == MAX_OUTSTANDING)
142 cp_usb_async_sync(cp);
144 if (!cp->packet[p].transfer)
145 cp->packet[p].transfer = libusb_alloc_transfer(0);
146 cp->packet[p].valuep = valuep;
147 cp->packet[p].direction = packet_read;
148 libusb_fill_control_setup(cp->packet[p].data,
150 0xff, /* request type */
155 libusb_fill_control_transfer(cp->packet[p].transfer,
158 cp_usb_async_transfer_callback,
161 ccdbg_debug(CC_DEBUG_USB_ASYNC, "Read packet %d\n", p);
162 ret = libusb_submit_transfer(cp->packet[p].transfer);
164 fprintf(stderr, "libusb_submit_transfer failed %d\n", ret);
169 cp_usb_async_sync(struct cp_usb_async *cp)
171 while (cp->ack < cp->p - 1) {
172 libusb_handle_events(cp->ctx);