API
 
Loading...
Searching...
No Matches
ArcusPerformaxDriver.c
Go to the documentation of this file.
2
3#ifdef DEBUGARCUS
4#include <stdio.h>
5#endif // DEBUGARCUS
6
7//
8// I'm not thrilled with the use of these globals, but it seems required to support
9// the existing fnPerformax function prototypes...
10//
11
12struct libusb_context * usb_context = 0;
15
16#define AR_FALSE 0
17#define AR_TRUE 1
18
19// Internal function to allow us to keep a single list of
20// vendor/product codes that are compatible with this driver
21int _is_performax_device_by_vendor_product(int vendor, int product) {
22 if ((vendor == 0x1589) && (product == 0xa101) ) {
23 return AR_TRUE;
24 }
25 return AR_FALSE;
26}
27
28// Internal function to figure out if the libusb_device_descriptor is a performax device
29int _is_performax_device(struct libusb_device_descriptor *descriptor) {
30 return _is_performax_device_by_vendor_product(descriptor->idVendor, descriptor->idProduct);
31}
32
33// Iterate through the list of usb devices present and count the number of
34// devices that we could use (based on returning true to _is_performax_device)
35
37 ssize_t device_count, i;
38 libusb_device **list;
39 struct libusb_device_descriptor descriptor;
40
42 return AR_FALSE;
43 }
44
45 *numDevices = 0;
46
47 device_count = libusb_get_device_list(usb_context, &list);
48
49
50 for (i = 0; i < device_count; i++) {
51
52 if (0 == libusb_get_device_descriptor(list[i], &descriptor)) {
53 if ( _is_performax_device(&descriptor) ) {
54 (*numDevices) ++ ;
55 }
56 }
57 }
58
59 libusb_free_device_list(list, 1); // Unreference and remove items from the list
60 return AR_TRUE;
61}
62
63// Internal function
64// Return a libusb_device_descriptor for the device given by the dwNumDevice offset.
65// On success, the offset number in the libusb_device list is returned.
66// On error, -1 is returned.
67int _get_libusb_device_offset_from_arcos_offset(libusb_device **list, ssize_t list_count,
68 struct libusb_device_descriptor *descriptor, AR_DWORD dwNumDevice) {
69int i;
70
71 for (i = 0; i < list_count; i++) {
72 // iterate through each device and find a perfmax device:
73 if (0 == libusb_get_device_descriptor(list[i], descriptor)) {
74 if ( _is_performax_device(descriptor) ) {
75 if (dwNumDevice) {
76 // skip to the perfmax device offset in dwNumDevice
77 dwNumDevice--;
78 } else { // This is the one we're interested in...
79 return i;
80 }
81 }
82 }
83 }
84
85 return -1; // Couldn't find the offset requested...
86}
87
88AR_BOOL fnPerformaxComGetProductString(AR_DWORD dwNumDevice, AR_VOID *lpDeviceString, AR_DWORD dwOptions) {
89 ssize_t device_count, i;
90 libusb_device **list;
91 struct libusb_device_descriptor descriptor;
92 AR_BOOL result;
93 libusb_device_handle *device_handle;
94
96 return AR_FALSE;
97 }
98
99 result = AR_TRUE; // no error yet...
100
101 // Get the list of all devices:
102 device_count = libusb_get_device_list(usb_context, &list);
103
104 i = _get_libusb_device_offset_from_arcos_offset(list, device_count, &descriptor, dwNumDevice);
105 if (i<0) {
106 result = AR_FALSE; // invlaid dwNumDevice id; we should have found the offset above...
107 } else {
108 if (libusb_open(list[i], &device_handle) != 0 ) {
109 result = AR_FALSE; // libusb_open error
110 } else {
111 if (dwOptions == PERFORMAX_RETURN_SERIAL_NUMBER) {
112 if (0 > libusb_get_string_descriptor_ascii(
113 device_handle, descriptor.iSerialNumber, lpDeviceString, PERFORMAX_MAX_DEVICE_STRLEN)) {
114 result = AR_FALSE; // invalid descriptor
115 }
116 } else if (dwOptions == PERFORMAX_RETURN_DESCRIPTION) {
117 if (0 > libusb_get_string_descriptor_ascii(
118 device_handle, descriptor.iProduct, lpDeviceString, PERFORMAX_MAX_DEVICE_STRLEN)) {
119 result = AR_FALSE; // invalid descriptor
120 }
121 } else {
122 result = AR_FALSE; // invlaid dwOption
123 }
124 libusb_close(device_handle);
125 }
126 }
127
128 libusb_free_device_list(list, 1); // Unreference and remove items from the list
129 return result;
130}
131
132int _send_urb_control(AR_HANDLE device_handle, int id) {
133
134 return libusb_control_transfer(device_handle,
135 0x40, // bmRequestType
136 0x02, // bRequest,
137 id, // wValue,
138 0x00, // wIndex,
139 NULL, // data,
140 0, // wLength,
142}
143
144AR_BOOL fnPerformaxComOpen(AR_DWORD dwDeviceNum, AR_HANDLE *device_handle) {
145 ssize_t device_count, i;
146 libusb_device **list;
147 struct libusb_device_descriptor descriptor;
148 AR_BOOL result;
149
151 return AR_FALSE;
152 }
153
154 result = AR_TRUE; // no error yet...
155
156 // Get the list of all devices:
157 device_count = libusb_get_device_list(usb_context, &list);
158
159 i = _get_libusb_device_offset_from_arcos_offset(list, device_count, &descriptor, dwDeviceNum);
160 if (i<0) {
161 result = AR_FALSE; // invlaid dwNumDevice id; we should have found the offset above...
162 } else {
163 if (0 != libusb_open(list[i], device_handle) ) {
164 result = AR_FALSE; // libusb_open error
165 }
166 if (0 != libusb_claim_interface(*device_handle, 0) ) {
167 result = AR_FALSE; // libusb_open error
168 }
169 }
170
171 libusb_free_device_list(list, 1); // Unreference and remove items from the list
172
173 _send_urb_control(*device_handle, 0x02); // Should document this better; it's some open command
174 return result;
175}
176
178 AR_BOOL result;
179
181 return AR_FALSE;
182 }
183
184 _send_urb_control(device_handle, 0x04); // Should document this better; it's some close command
185
186 result = AR_TRUE; // no error yet...
187
188 if (0 != libusb_release_interface(device_handle, 0) ) {
189 result = AR_FALSE; // libusb_open error
190 }
191 libusb_close(device_handle);
192 return result;
193}
194
195AR_BOOL fnPerformaxComSetTimeouts(AR_DWORD dwReadTimeout, AR_DWORD dwWriteTimeout) {
197 return AR_FALSE;
198 }
199
200 libusb_ReadTimeout = dwReadTimeout;
201 libusb_WriteTimeout = dwWriteTimeout;
202
203 return AR_TRUE; // TODO: errors for wacky times?
204}
205
206AR_BOOL fnPerformaxComSendRecv(AR_HANDLE device_handle, AR_VOID *wBuffer, AR_DWORD dwNumBytesToWrite, AR_DWORD dwNumBytesToRead, AR_VOID *rBuffer) {
208 return AR_FALSE;
209 }
210
211int transferred;
212int result;
213char buffer[4096];
214
215 // clear any outstanding reads:
216 result = libusb_bulk_transfer(device_handle, 0x82, buffer, sizeof(buffer), &transferred, libusb_ReadTimeout);
217 // if the above fails, it's probably ok. We probably don't care.
218
219 result = libusb_bulk_transfer(device_handle, 0x02, wBuffer, dwNumBytesToWrite, &transferred, libusb_WriteTimeout);
220
221#ifdef DEBUGARCUS
222 printf("sent: %d (%d) result %d '%s'\n", transferred, (int)dwNumBytesToWrite, result, (char *)wBuffer);
223#endif // DEBUGARCUS
224
225 if (0 != result) {
226 return AR_FALSE;
227 }
228
229 result = libusb_bulk_transfer(device_handle, 0x82, rBuffer, dwNumBytesToRead, &transferred, libusb_ReadTimeout);
230
231#ifdef DEBUGARCUS
232 printf("received: %d (%d) result %d - %s\n", transferred, (int)dwNumBytesToRead, result, (char *)rBuffer);
233#endif // DEBUGARCUS
234 if (0 != result) {
235 return AR_FALSE;
236 }
237
238 return AR_TRUE;
239}
240
243 return AR_FALSE;
244 }
245
246 if (_send_urb_control(device_handle, 0x01) == 0) { // Should document this better; it's some flush command
247 return AR_TRUE;
248 }
249 return AR_FALSE;
250}
251
252//the following does _not_ need to be called before using the other functions. It is safe to ignore its existence
253
254// Since the original interface contained the above line, all functions call the initialization function
255// below. Since we have no context being passed inthe fnPerformax functions, we don't get the opportunity
256// anywhere to properly close the libusb library with libusb_exit...
257
259 if (usb_context) {
260 return AR_TRUE;
261 }
262
263 if (!libusb_init(&usb_context)) {
264 return AR_TRUE;
265 }
266
267 return AR_FALSE;
268}
269
AR_DWORD libusb_WriteTimeout
AR_BOOL fnPerformaxComClose(AR_HANDLE device_handle)
AR_BOOL fnPerformaxComFlush(AR_HANDLE device_handle)
int _is_performax_device(struct libusb_device_descriptor *descriptor)
AR_BOOL InitializePerformaxLibrary(AR_VOID)
AR_BOOL fnPerformaxComGetNumDevices(AR_DWORD *numDevices)
AR_BOOL fnPerformaxComGetProductString(AR_DWORD dwNumDevice, AR_VOID *lpDeviceString, AR_DWORD dwOptions)
AR_BOOL fnPerformaxComSetTimeouts(AR_DWORD dwReadTimeout, AR_DWORD dwWriteTimeout)
int _send_urb_control(AR_HANDLE device_handle, int id)
int _is_performax_device_by_vendor_product(int vendor, int product)
int _get_libusb_device_offset_from_arcos_offset(libusb_device **list, ssize_t list_count, struct libusb_device_descriptor *descriptor, AR_DWORD dwNumDevice)
AR_BOOL fnPerformaxComSendRecv(AR_HANDLE device_handle, AR_VOID *wBuffer, AR_DWORD dwNumBytesToWrite, AR_DWORD dwNumBytesToRead, AR_VOID *rBuffer)
AR_DWORD libusb_ReadTimeout
AR_BOOL fnPerformaxComOpen(AR_DWORD dwDeviceNum, AR_HANDLE *device_handle)
#define AR_TRUE
#define AR_FALSE
struct libusb_context * usb_context
void AR_VOID
int AR_BOOL
#define PERFORMAX_RETURN_SERIAL_NUMBER
#define PERFORMAX_MAX_DEVICE_STRLEN
libusb_device_handle * AR_HANDLE
long AR_DWORD
#define PERFORMAX_RETURN_DESCRIPTION