]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | Copyright (c) 2010 Sven Peter <sven@fail0verflow.com> | |
3 | Copyright (c) 2010 Haxx Enterprises <bushing@gmail.com> | |
4 | All rights reserved. | |
5 | ||
6 | Redistribution and use in source and binary forms, with or | |
7 | without modification, are permitted provided that the following | |
8 | conditions are met: | |
9 | ||
10 | * Redistributions of source code must retain the above copyright notice, | |
11 | this list of conditions and the following disclaimer. | |
12 | ||
13 | * Redistributions in binary form must reproduce the above copyright notice, | |
14 | this list of conditions and the following disclaimer in the documentation | |
15 | and/or other materials provided with the distribution. | |
16 | ||
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | |
21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | |
27 | THE POSSIBILITY OF SUCH DAMAGE. | |
28 | ||
29 | */ | |
30 | #include <libusb.h> | |
31 | #include <stdio.h> | |
32 | #include "gl_usb.h" | |
33 | ||
34 | #define CTRL_IN (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_INTERFACE) | |
35 | #define CTRL_OUT (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT | LIBUSB_RECIPIENT_INTERFACE) | |
36 | const int PACKET_CTRL_LEN=2; | |
37 | ||
38 | const int PACKET_INT_LEN=2; | |
39 | const int PACKET_BULK_LEN=64; | |
40 | const int INTERFACE=0; | |
41 | const int ENDPOINT_INT_IN=0x81; /* endpoint 0x81 address for IN */ | |
42 | const int ENDPOINT_INT_OUT=0x01; /* endpoint 1 address for OUT */ | |
43 | const int ENDPOINT_BULK_IN=0x81; /* endpoint 0x81 address for IN */ | |
44 | const int ENDPOINT_BULK_OUT=0x02; /* endpoint 1 address for OUT */ | |
45 | const int TIMEOUT=5000; /* timeout in ms */ | |
46 | ||
47 | enum { | |
48 | REQ_READBULK = 0x82, | |
49 | REQ_WRITEADDR, | |
50 | REQ_READDATA, | |
51 | REQ_WRITEDATA, | |
52 | }; | |
53 | ||
54 | static struct libusb_device_handle *g_devh = NULL; | |
55 | ||
56 | int gl_write_address(libusb_device_handle *devh, unsigned int address) | |
57 | { | |
58 | unsigned char packet[8] = {address & 0xFF}; | |
59 | int retval = libusb_control_transfer(devh, CTRL_OUT, 0xc, REQ_WRITEADDR, 0, packet, 1,TIMEOUT); | |
60 | if (retval != 1) printf("%s: libusb_control_transfer returned %d\n", __FUNCTION__, retval); | |
61 | return retval; | |
62 | } | |
63 | ||
64 | int gl_write_data(libusb_device_handle *devh, unsigned int val) | |
65 | { | |
66 | unsigned char packet[8] = {val & 0xFF}; | |
67 | int retval = libusb_control_transfer(devh, CTRL_OUT, 0xc, REQ_WRITEDATA, 0, packet, 1,TIMEOUT); | |
68 | if (retval != 1) printf("%s: libusb_control_transfer returned %d\n", __FUNCTION__, retval); | |
69 | return retval; | |
70 | } | |
71 | ||
72 | int gl_read_data(libusb_device_handle *devh) | |
73 | { | |
74 | unsigned char packet[8] = {0}; | |
75 | int retval = libusb_control_transfer(devh, CTRL_IN, 0xc, REQ_READDATA, 0, packet, 1,TIMEOUT); | |
76 | if (retval != 1) printf("%s: libusb_control_transfer returned %d, val=%hhx\n", __FUNCTION__, retval, packet[0]); | |
77 | return retval == 1 ? packet[0] : retval; | |
78 | } | |
79 | ||
80 | int gl_read_bulk(libusb_device_handle *devh, void *buffer, unsigned int size) | |
81 | { | |
82 | unsigned char packet[8] = {0, 0, 0, 0, size & 0xff, (size & 0xff00) >> 8, (size & 0xff0000) >> 16, (size & 0xff000000)>>24}; | |
83 | int transferred = 0; | |
84 | ||
85 | int retval = libusb_control_transfer(devh, CTRL_OUT, 0x4, REQ_READBULK, 0, packet, 8, TIMEOUT); | |
86 | if (retval != 8) printf("%s: libusb_control_transfer returned %d\n", __FUNCTION__, retval); | |
87 | ||
88 | retval = libusb_bulk_transfer(devh, ENDPOINT_BULK_IN, buffer, size, | |
89 | &transferred, TIMEOUT); | |
90 | if (retval < 0) { | |
91 | fprintf(stderr, "Bulk read error %d\n", retval); | |
92 | } | |
93 | return transferred; | |
94 | } | |
95 | ||
96 | int gl_reg_write(libusb_device_handle *devh, unsigned int reg, unsigned int val) | |
97 | { | |
98 | int retval; | |
99 | retval = gl_write_address(devh, reg); | |
100 | if (retval < 0) | |
101 | return retval; | |
102 | retval = gl_write_data(devh, val); | |
103 | return retval; | |
104 | } | |
105 | ||
106 | int gl_reg_read(libusb_device_handle *devh, unsigned int reg) | |
107 | { | |
108 | int retval; | |
109 | retval = gl_write_address(devh, reg); | |
110 | if (retval < 0) | |
111 | return retval; | |
112 | retval = gl_read_data(devh); | |
113 | return retval; | |
114 | } | |
115 | ||
116 | int gl_open(int vid) | |
117 | { | |
118 | int r = 1; | |
119 | ||
120 | r = libusb_init(NULL); | |
121 | if (r < 0) | |
122 | return GL_ELIBUSB; | |
123 | ||
124 | libusb_set_debug(NULL, 0); | |
125 | ||
126 | struct libusb_device **devs; | |
127 | struct libusb_device *dev; | |
128 | size_t i = 0; | |
129 | ||
130 | if (libusb_get_device_list(NULL, &devs) < 0) { | |
131 | r = GL_EOPEN; | |
132 | goto gl_open_error; | |
133 | } | |
134 | ||
135 | while ((dev = devs[i++]) != NULL) { | |
136 | struct libusb_device_descriptor desc; | |
137 | if (libusb_get_device_descriptor(dev, &desc) < 0) | |
138 | break; | |
139 | ||
140 | if (desc.idVendor == vid) { | |
141 | if (libusb_open(dev, &g_devh) < 0) | |
142 | g_devh = NULL; | |
143 | break; | |
144 | } | |
145 | } | |
146 | ||
147 | libusb_free_device_list(devs, 1); | |
148 | ||
149 | if (!g_devh) { | |
150 | r = GL_EOPEN; | |
151 | goto gl_open_error; | |
152 | } | |
153 | ||
154 | r = libusb_set_configuration(g_devh, 1); | |
155 | if (r < 0) { | |
156 | r = GL_ESETCONFIG; | |
157 | goto gl_open_error; | |
158 | } | |
159 | ||
160 | r = libusb_claim_interface(g_devh, 0); | |
161 | if (r < 0) { | |
162 | r = GL_ECLAIM; | |
163 | goto gl_open_error; | |
164 | } | |
165 | ||
166 | return GL_OK; | |
167 | ||
168 | gl_open_error: | |
169 | gl_close(); | |
170 | return r; | |
171 | } | |
172 | ||
173 | int gl_close(void) | |
174 | { | |
175 | if (g_devh) { | |
176 | libusb_release_interface(g_devh, 0); | |
177 | libusb_reset_device(g_devh); | |
178 | libusb_close(g_devh); | |
179 | } | |
180 | libusb_exit(NULL); | |
181 | ||
182 | return 0; | |
183 | } |