API
ArcusPerformaxDriver.c
Go to the documentation of this file.
1 #include "ArcusPerformaxDriver.h"
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 
12 struct 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
21 int _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
29 int _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.
67 int _get_libusb_device_offset_from_arcos_offset(libusb_device **list, ssize_t list_count,
68  struct libusb_device_descriptor *descriptor, AR_DWORD dwNumDevice) {
69 int 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 
88 AR_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 
132 int _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 
144 AR_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 
195 AR_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 
206 AR_BOOL fnPerformaxComSendRecv(AR_HANDLE device_handle, AR_VOID *wBuffer, AR_DWORD dwNumBytesToWrite, AR_DWORD dwNumBytesToRead, AR_VOID *rBuffer) {
208  return AR_FALSE;
209  }
210 
211 int transferred;
212 int result;
213 char 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