USBMicroX.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  1. #include "USBMicroX.h"
  2. #define UNLESS(S) if(!(S))
  3. #define USBMX_ID_PRODUCT 0x01A5
  4. #define USBMX_ID_VENDOR 0x0DE7
  5. static long dict_get_long(CFDictionaryRef properties, CFStringRef key)
  6. {
  7. long number;
  8. CFTypeRef value = CFDictionaryGetValue(properties, key);
  9. if (!value) return 0;
  10. CFTypeID type = CFGetTypeID(value);
  11. if (type != CFNumberGetTypeID()) return 0 ;
  12. CFNumberGetValue((CFNumberRef)value, kCFNumberLongType, (void *)&number);
  13. return number;
  14. }
  15. static char* dict_get_string(CFDictionaryRef properties, CFStringRef key, CFStringEncoding encoding)
  16. {
  17. static char cstring[512];
  18. CFTypeRef value = CFDictionaryGetValue(properties, key);
  19. if (!value) return "";
  20. CFTypeID type = CFGetTypeID(value) ;
  21. if (type != CFStringGetTypeID()) return "";
  22. CFStringGetCString((CFStringRef)value, cstring, sizeof(cstring), encoding);
  23. return cstring; // WARNING: be sure to copy string after return
  24. }
  25. static void nsp(int L) {
  26. int i = 0;
  27. while(i++ < L) printf(" ");
  28. }
  29. static void cftype_dump(CFTypeRef o, int L);
  30. static void cftype_dump_arrayapply(const void *value, void *context) {
  31. int L = (int)context;
  32. nsp(L); printf("0x%08x\n", value);
  33. cftype_dump((CFTypeRef)value, L+1);
  34. }
  35. static void cftype_dump_dictapply (const void *key, const void *value, void *context) {
  36. int L = (int)context;
  37. nsp(L); printf("\"%s\" => 0x%08x\n",
  38. CFStringGetCStringPtr(key, CFStringGetSystemEncoding()), value);
  39. cftype_dump((CFTypeRef)value, L+1);
  40. }
  41. static void cftype_dump(CFTypeRef o, int L)
  42. {
  43. if(CFGetTypeID(o) == CFArrayGetTypeID()) {
  44. nsp(L); printf("[\n");
  45. CFArrayApplyFunction(
  46. o,
  47. CFRangeMake(0, CFArrayGetCount(o)),
  48. cftype_dump_arrayapply,
  49. (void*)(L+1));
  50. nsp(L); printf("]\n");
  51. } else if(CFGetTypeID(o) == CFDictionaryGetTypeID()) {
  52. nsp(L); printf("{\n");
  53. CFDictionaryApplyFunction(
  54. o,
  55. cftype_dump_dictapply,
  56. (void*)(L+1));
  57. nsp(L); printf("}\n");
  58. } else if(CFGetTypeID(o) == CFNumberGetTypeID()) {
  59. long number;
  60. CFNumberGetValue((CFNumberRef)o, kCFNumberLongType, (void*)&number);
  61. nsp(L); printf("number: 0x%08x\n", number);
  62. } else if(CFGetTypeID(o) == CFStringGetTypeID()) {
  63. const char *s = CFStringGetCStringPtr(o, CFStringGetSystemEncoding());
  64. nsp(L); printf("string: \"%s\"\n", s);
  65. } else if(CFGetTypeID(o) == CFBooleanGetTypeID()) {
  66. nsp(L); printf("boolean: %s\n", CFBooleanGetValue(o)?"TRUE":"FALSE");
  67. } else {
  68. nsp(L); printf("??? unknown type\n");
  69. }
  70. }
  71. int USBmX_DeviceAddedHandler(
  72. USBmX_ContextRef ctx,
  73. USBmX_DeviceAddedProc proc,
  74. void *cookie)
  75. {
  76. ctx->deviceAdded = proc;
  77. ctx->deviceAdded_cookie = cookie;
  78. return 0;
  79. }
  80. int USBmX_DeviceRemovedHandler(
  81. USBmX_ContextRef ctx,
  82. USBmX_DeviceRemovedProc proc,
  83. void *cookie)
  84. {
  85. ctx->deviceRemoved = proc;
  86. ctx->deviceRemoved_cookie = cookie;
  87. return 0;
  88. }
  89. int USBmX_DeviceInfo(USBmX_DeviceRef dev)
  90. {
  91. if(!dev) goto err;
  92. cftype_dump(dev->properties, 0);
  93. return 0;
  94. err:
  95. return -1;
  96. }
  97. static void DumpBuffer(const u_char buf[], unsigned int buf_size)
  98. {
  99. const u_char *p = buf;
  100. while(buf_size--) printf("0x%02x ", *p++);
  101. printf("\n");
  102. }
  103. void USBmX_DumpCommand(u_char buf[])
  104. {
  105. DumpBuffer(buf, 8);
  106. }
  107. void DeviceAddedHandler(void *refCon, io_iterator_t iterator)
  108. {
  109. #if USBMX_DEBUG_LOG
  110. USBMX_LOG("Device added notification");
  111. #endif
  112. io_object_t o;
  113. USBmX_ContextRef ctx;
  114. // Must iterate in order to re-arm notification
  115. while(o = IOIteratorNext(iterator)) {
  116. IOObjectRelease(o);
  117. }
  118. ctx = (USBmX_ContextRef)refCon;
  119. #if USBMX_DEBUG_LOG
  120. USBMX_LOG("ctx = %x", ctx);
  121. #endif
  122. USBmX_ScanForDevices(ctx);
  123. }
  124. void DestroyDeviceRef(USBmX_DeviceRef d)
  125. {
  126. #if USBMX_DEBUG_LOG
  127. USBMX_LOG("Destroying: %x %x %x %x", d->properties, d->serialNumber, d->interface, d);
  128. #endif
  129. CFRelease(d->properties);
  130. free((void *)d->serialNumber);
  131. free((void *)d->deviceName);
  132. free((void *)d->manufacturer);
  133. (*d->interface)->close(d->interface);
  134. free(d);
  135. }
  136. void DeviceRemovedHandler(void *target, IOReturn result, void *refcon, void *sender)
  137. {
  138. USBmX_DeviceRef d = (USBmX_DeviceRef)refcon;
  139. USBmX_ContextRef ctx = d->ctx;
  140. #if USBMX_DEBUG_LOG
  141. USBMX_LOG("Device Removed (# %s)", d->serialNumber);
  142. #endif
  143. USBmX_DeviceRef p = ctx->deviceList;
  144. USBmX_DeviceRef pl = NULL;
  145. while(p) {
  146. if(p == d)
  147. {
  148. if(pl == NULL) ctx->deviceList = d->next;
  149. else pl->next = d->next;
  150. ////////////////////////////
  151. //USBMX_LOG("NEED TO CALL DEVICE REMOVED CALLBACK");
  152. if(ctx->deviceRemoved)
  153. {
  154. (*ctx->deviceRemoved)(d, ctx->deviceRemoved_cookie);
  155. }
  156. ////////////////////////////
  157. DestroyDeviceRef(d);
  158. break;
  159. }
  160. pl = p;
  161. p = p->next;
  162. }
  163. }
  164. static void InterruptReportHandler(
  165. void *target,
  166. IOReturn result,
  167. void *refcon,
  168. void *sender,
  169. UInt32 bufferSize)
  170. {
  171. USBmX_DeviceRef d = (USBmX_DeviceRef)target;
  172. #if USBMX_DEBUG_LOG
  173. printf("Response: ");
  174. DumpBuffer(d->response_buffer, bufferSize);
  175. #endif
  176. d->response_ready = 1;
  177. }
  178. static int SetReport(USBmX_DeviceRef d, const u_char *buf, unsigned int buf_size)
  179. {
  180. #if USBMX_DEBUG_LOG
  181. printf("Report: "); DumpBuffer(buf, buf_size);
  182. #endif
  183. d->response_ready = 0;
  184. IOReturn rc = (*d->interface)->setReport(
  185. d->interface,
  186. kIOHIDReportTypeFeature,
  187. 0, //reportID
  188. (void *)buf,
  189. buf_size,
  190. 1000, //timeout
  191. NULL,
  192. NULL,
  193. NULL
  194. );
  195. while(!d->response_ready) {
  196. SInt32 r = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.001, false);
  197. #if USBMX_DEBUG_LOG
  198. printf("wait r=%x\n", r);
  199. #endif
  200. }
  201. if(rc != kIOReturnSuccess) {
  202. USBMX_LOG("SetReport: (*interface)->setReport() Error %x", rc);
  203. return -1;
  204. }
  205. return 0;
  206. }
  207. int USBmX_DeviceCount(USBmX_ContextRef ctx)
  208. {
  209. if(!ctx) return 0;
  210. USBmX_DeviceRef d = ctx->deviceList;
  211. int count = 0;
  212. while(d) {
  213. ++count;
  214. d = d->next;
  215. }
  216. return count;
  217. }
  218. USBmX_DeviceRef USBmX_DefaultDevice(USBmX_ContextRef ctx)
  219. {
  220. if(ctx) return ctx->deviceList;
  221. return NULL;
  222. }
  223. USBmX_DeviceRef USBmX_DeviceWithSerial(USBmX_ContextRef ctx, const char *serial)
  224. {
  225. if(!ctx || !serial) return NULL;
  226. USBmX_DeviceRef dev = ctx->deviceList;
  227. #if USBMX_DEBUG_LOG
  228. USBMX_LOG("Searching for device...");
  229. #endif
  230. while(dev) {
  231. if(!strcmp(serial, dev->serialNumber))
  232. {
  233. #if USBMX_DEBUG_LOG
  234. USBMX_LOG("Device found! %x (# %s)", dev, dev->serialNumber);
  235. #endif
  236. return dev;
  237. }
  238. dev = dev->next;
  239. }
  240. #if USBMX_DEBUG_LOG
  241. USBMX_LOG("Device not found");
  242. #endif
  243. return NULL;
  244. }
  245. int USBmX_RawCommand(USBmX_DeviceRef dev,
  246. const u_char command[8],
  247. u_char response[8])
  248. {
  249. if(!dev) goto err;
  250. if(SetReport(dev, command, 8) < 0) goto err;
  251. if(response) {
  252. memcpy(response, dev->response_buffer, 8);
  253. }
  254. return 0;
  255. err:
  256. return -1;
  257. }
  258. static int CreateDeviceRef(USBmX_ContextRef ctx, io_object_t dev, USBmX_DeviceRef *dev_out)
  259. {
  260. IOReturn rc;
  261. kern_return_t result;
  262. USBmX_DeviceRef dr = USBMX_ALLOC(USBmX_Device);
  263. dr->next = NULL;
  264. dr->ctx = ctx;
  265. dr->userData = NULL;
  266. // Get device properties
  267. result = IORegistryEntryCreateCFProperties(
  268. dev, &dr->properties,
  269. kCFAllocatorDefault, kNilOptions);
  270. if(result != KERN_SUCCESS || !dr->properties) {
  271. USBMX_LOG("IORegistryEntryCreateCFProperties Error %x", result);
  272. goto err;
  273. }
  274. dr->serialNumber = strdup(
  275. dict_get_string(
  276. dr->properties,
  277. CFSTR(kIOHIDSerialNumberKey),
  278. CFStringGetSystemEncoding()));
  279. dr->deviceName = strdup(
  280. dict_get_string(
  281. dr->properties,
  282. CFSTR(kIOHIDProductKey),
  283. CFStringGetSystemEncoding()));
  284. dr->manufacturer = strdup(
  285. dict_get_string(
  286. dr->properties,
  287. CFSTR(kIOHIDManufacturerKey),
  288. CFStringGetSystemEncoding()));
  289. // Add device to head of list if we don't already have it
  290. if(USBmX_DeviceWithSerial(ctx, dr->serialNumber) == NULL)
  291. {
  292. #if USBMX_DEBUG_LOG
  293. USBMX_LOG("Adding device");
  294. #endif
  295. dr->next = ctx->deviceList;
  296. ctx->deviceList = dr;
  297. } else {
  298. #if USBMX_DEBUG_LOG
  299. USBMX_LOG("Already have device");
  300. #endif
  301. return 0;
  302. }
  303. #if USBMX_DEBUG_LOG
  304. USBMX_LOG("Found Device (# %s)", dr->serialNumber);
  305. USBMX_LOG("kIOHIDManufacturerKey: \"%s\"",
  306. dict_get_string(dr->properties,
  307. CFSTR(kIOHIDManufacturerKey), CFStringGetSystemEncoding()));
  308. #endif
  309. { // Set up the device
  310. SInt32 score = 0;
  311. IOCFPlugInInterface **plugIn;
  312. if((rc = IOCreatePlugInInterfaceForService(
  313. dev,
  314. kIOHIDDeviceUserClientTypeID,
  315. kIOCFPlugInInterfaceID,
  316. &plugIn, &score)) != kIOReturnSuccess)
  317. {
  318. USBMX_LOG("IOCreatePlugInInterfaceForService Error %x", rc);
  319. goto err;
  320. }
  321. // Grab interface
  322. IOHIDDeviceInterface **interface;
  323. HRESULT prc;
  324. prc = (*plugIn)->QueryInterface(plugIn,
  325. CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID),
  326. (LPVOID)&interface);
  327. (*plugIn)->Release(plugIn);
  328. if(prc != S_OK) {
  329. USBMX_LOG("QueryInterface Error %x", prc);
  330. goto err;
  331. }
  332. dr->interface = interface;
  333. // Set up removal callback
  334. if((rc = (*interface)->setRemovalCallback(interface,
  335. DeviceRemovedHandler, NULL, (void *)dr)) != kIOReturnSuccess)
  336. {
  337. USBMX_LOG("(*interface)->setRemovalCallback() Error %x", rc);
  338. goto err1;
  339. }
  340. if((rc = (*interface)->open(interface, 0)) != kIOReturnSuccess)
  341. {
  342. USBMX_LOG("(*interface)->open() Error %x", rc);
  343. goto err1;
  344. }
  345. mach_port_t async_port;
  346. if((rc = (*interface)->createAsyncPort(interface, &async_port)) != kIOReturnSuccess)
  347. {
  348. USBMX_LOG("(*interface)->createAsyncPort() Error %x", rc);
  349. goto err1;
  350. }
  351. CFRunLoopSourceRef rl_source;
  352. if((rc = (*interface)->createAsyncEventSource(interface, &rl_source)) != kIOReturnSuccess)
  353. {
  354. USBMX_LOG("(*interface)->createAsyncEventSource() Error %x", rc);
  355. goto err1;
  356. }
  357. CFRunLoopAddSource(
  358. CFRunLoopGetCurrent(),
  359. rl_source,
  360. kCFRunLoopDefaultMode);
  361. if((rc = ((IOHIDDeviceInterface122*)*interface)->setInterruptReportHandlerCallback(
  362. interface,
  363. dr->response_buffer,
  364. USBMX_RESPONSE_BUFFER_SIZE,
  365. InterruptReportHandler,
  366. (void *)dr,
  367. NULL)) != kIOReturnSuccess)
  368. {
  369. USBMX_LOG("(*interface)->setInterruptReportHandlerCallback() Error %x", rc);
  370. goto err1;
  371. }
  372. }
  373. *dev_out = dr;
  374. ////////////////
  375. //USBMX_LOG("NEED TO CALL DEVICE ADDED CALLBACK");
  376. if(ctx->deviceAdded)
  377. {
  378. (*ctx->deviceAdded)(dr, ctx->deviceAdded_cookie);
  379. }
  380. ////////////////
  381. return 0;
  382. err1:
  383. (*dr->interface)->Release(dr->interface);
  384. err:
  385. IOObjectRelease(dev);
  386. free(dr);
  387. return -1;
  388. }
  389. int USBmX_ScanForDevices(USBmX_ContextRef ctx)
  390. {
  391. IOReturn rc;
  392. io_iterator_t iterator;
  393. io_object_t d;
  394. int n_devices = 0;
  395. CFRetain(ctx->matchingDict);
  396. // Narrow it down to devices matching vendor and product IDs
  397. if(rc = IOServiceGetMatchingServices(
  398. kIOMasterPortDefault,
  399. ctx->matchingDict,
  400. &iterator) != kIOReturnSuccess)
  401. {
  402. USBMX_LOG("IOServiceGetMatchingServices Error %x", rc);
  403. goto err;
  404. }
  405. // Iterate over each found device
  406. while(d = IOIteratorNext(iterator))
  407. {
  408. USBmX_DeviceRef dev;
  409. if(CreateDeviceRef(ctx, d, &dev) < 0) goto err1;
  410. n_devices++;
  411. }
  412. IOObjectRelease(iterator);
  413. noerr:
  414. return n_devices;
  415. err1:
  416. IOObjectRelease(iterator);
  417. err:
  418. USBMX_LOG("USBmX_FindDevices Failed!");
  419. return -1;
  420. }
  421. USBmX_ContextRef USBmX_Create(void)
  422. {
  423. USBmX_ContextRef ctx = NULL;
  424. if(ctx = USBMX_ALLOC(USBmX_Context))
  425. {
  426. ctx->deviceList = NULL;
  427. ctx->matchingDict = NULL;
  428. ctx->deviceAdded = NULL;
  429. ctx->deviceRemoved = NULL;
  430. ctx->deviceAdded_cookie = NULL;
  431. ctx->deviceRemoved_cookie = NULL;
  432. }
  433. return ctx;
  434. }
  435. int USBmX_Begin(USBmX_ContextRef ctx)
  436. {
  437. // USBmX_ContextRef ctx = USBMX_ALLOC(USBmX_Context);
  438. // ctx->deviceList = NULL;
  439. // ctx->matchingDict = NULL;
  440. if(!ctx) return -1;
  441. // Grab root IOKit HID services
  442. UNLESS(ctx->matchingDict = IOServiceMatching(kIOHIDDeviceKey))
  443. {
  444. USBMX_LOG("IOServiceMatching(kIOHIDDeviceKey) Error");
  445. goto err;
  446. }
  447. { // Add product and vendor keys to matchingDict
  448. SInt32 product = USBMX_ID_PRODUCT;
  449. SInt32 vendor = USBMX_ID_VENDOR;
  450. CFNumberRef num = NULL;
  451. #define USBMX_DNA(NAME, VALUE) \
  452. UNLESS(num = CFNumberCreate( \
  453. kCFAllocatorDefault, \
  454. kCFNumberSInt32Type, \
  455. & VALUE )) { \
  456. USBMX_LOG("CFNumber Error"); \
  457. goto err; \
  458. } \
  459. CFDictionaryAddValue(ctx->matchingDict, CFSTR(NAME), num); \
  460. CFRelease(num);
  461. USBMX_DNA(kIOHIDVendorIDKey, vendor)
  462. USBMX_DNA(kIOHIDProductIDKey, product)
  463. #undef USBMX_DNA
  464. }
  465. { // Set up onPlug handler
  466. io_iterator_t plugIterator;
  467. IONotificationPortRef plugPort;
  468. //CFRunLoopSourceRef runLoopSource;
  469. //CFMutableDictionaryRef hd = IOServiceMatching(kIOHIDDeviceKey);
  470. CFRetain(ctx->matchingDict);
  471. UNLESS(plugPort = IONotificationPortCreate(kIOMasterPortDefault))
  472. {
  473. USBMX_LOG("IONotificationPortCreate error");
  474. }
  475. CFRunLoopAddSource(
  476. CFRunLoopGetCurrent(),
  477. IONotificationPortGetRunLoopSource(plugPort),
  478. kCFRunLoopDefaultMode);
  479. if(IOServiceAddMatchingNotification(
  480. plugPort,
  481. kIOFirstMatchNotification,
  482. ctx->matchingDict,
  483. DeviceAddedHandler,
  484. (void *)ctx,
  485. &plugIterator) != KERN_SUCCESS)
  486. {
  487. USBMX_LOG("IOServiceAddMatchingNotification error");
  488. }
  489. DeviceAddedHandler((void *)ctx, plugIterator);
  490. }
  491. //if(USBmX_ScanForDevices(ctx) < 0) goto err;
  492. noerr:
  493. //return ctx;
  494. return 0;
  495. err:
  496. USBMX_LOG("USBmX_Init Failed!");
  497. free(ctx);
  498. //return NULL;
  499. return -1;
  500. }
  501. int USBmX_Destroy(USBmX_ContextRef ctx)
  502. {
  503. if(!ctx) return -1;
  504. free(ctx);
  505. return 0;
  506. }
  507. int USBmX_InitPorts(USBmX_DeviceRef dev)
  508. {
  509. int r;
  510. u_char res[8];
  511. static const u_char cmd[8] = {
  512. 0x00,
  513. 0x00,
  514. 0x00,
  515. 0x00,
  516. 0x00,
  517. 0x00,
  518. 0x00,
  519. 0x00
  520. };
  521. r = USBmX_RawCommand(dev, cmd, res);
  522. if(r < 0) return r;
  523. if(res[0] != cmd[0]) return -1;
  524. return 0;
  525. }
  526. int USBmX_WriteA(USBmX_DeviceRef dev, u_char value)
  527. {
  528. int r;
  529. u_char res[8];
  530. u_char cmd[8] = {
  531. 0x01,
  532. value,
  533. 0x00,
  534. 0x00,
  535. 0x00,
  536. 0x00,
  537. 0x00,
  538. 0x00
  539. };
  540. r = USBmX_RawCommand(dev, cmd, res);
  541. if(r < 0) return r;
  542. if(res[0] != cmd[0]) return -1;
  543. return 0;
  544. }
  545. int USBmX_WriteB(USBmX_DeviceRef dev, u_char value)
  546. {
  547. int r;
  548. u_char res[8];
  549. u_char cmd[8] = {
  550. 0x02,
  551. value,
  552. 0x00,
  553. 0x00,
  554. 0x00,
  555. 0x00,
  556. 0x00,
  557. 0x00
  558. };
  559. r = USBmX_RawCommand(dev, cmd, res);
  560. if(r < 0) return r;
  561. if(res[0] != cmd[0]) return -1;
  562. return 0;
  563. }
  564. int USBmX_WriteABit(USBmX_DeviceRef dev, u_char v_and, u_char v_or)
  565. {
  566. int r;
  567. u_char res[8];
  568. u_char cmd[8] = {
  569. 0x03,
  570. v_and,
  571. v_or,
  572. 0x00,
  573. 0x00,
  574. 0x00,
  575. 0x00,
  576. 0x00
  577. };
  578. r = USBmX_RawCommand(dev, cmd, res);
  579. if(r < 0) return r;
  580. if(res[0] != cmd[0]) return -1;
  581. return 0;
  582. }
  583. int USBmX_WriteBBit(USBmX_DeviceRef dev, u_char v_and, u_char v_or)
  584. {
  585. int r;
  586. u_char res[8];
  587. u_char cmd[8] = {
  588. 0x04,
  589. v_and,
  590. v_or,
  591. 0x00,
  592. 0x00,
  593. 0x00,
  594. 0x00,
  595. 0x00
  596. };
  597. r = USBmX_RawCommand(dev, cmd, res);
  598. if(r < 0) return r;
  599. if(res[0] != cmd[0]) return -1;
  600. return 0;
  601. }
  602. int USBmX_ReadA(USBmX_DeviceRef dev, u_char *value_out)
  603. {
  604. int r;
  605. u_char res[8];
  606. u_char cmd[8] = {
  607. 0x05,
  608. 0x00,
  609. 0x00,
  610. 0x00,
  611. 0x00,
  612. 0x00,
  613. 0x00,
  614. 0x00
  615. };
  616. r = USBmX_RawCommand(dev, cmd, res);
  617. if(value_out) *value_out = res[1];
  618. if(r < 0) return r;
  619. if(res[0] != cmd[0]) return -1;
  620. return 0;
  621. }
  622. int USBmX_ReadB(USBmX_DeviceRef dev, u_char *value_out)
  623. {
  624. int r;
  625. u_char res[8];
  626. u_char cmd[8] = {
  627. 0x06,
  628. 0x00,
  629. 0x00,
  630. 0x00,
  631. 0x00,
  632. 0x00,
  633. 0x00,
  634. 0x00
  635. };
  636. r = USBmX_RawCommand(dev, cmd, res);
  637. if(value_out) *value_out = res[1];
  638. if(r < 0) return r;
  639. if(res[0] != cmd[0]) return -1;
  640. return 0;
  641. }
  642. int USBmX_SetBit(USBmX_DeviceRef dev, u_char line)
  643. {
  644. int r;
  645. u_char res[8];
  646. u_char cmd[8] = {
  647. 0x07,
  648. line,
  649. 0x00,
  650. 0x00,
  651. 0x00,
  652. 0x00,
  653. 0x00,
  654. 0x00
  655. };
  656. r = USBmX_RawCommand(dev, cmd, res);
  657. if(r < 0) return r;
  658. if(res[0] != cmd[0]) return -1;
  659. return 0;
  660. }
  661. int USBmX_ResetBit(USBmX_DeviceRef dev, u_char line)
  662. {
  663. int r;
  664. u_char res[8];
  665. u_char cmd[8] = {
  666. 0x08,
  667. line,
  668. 0x00,
  669. 0x00,
  670. 0x00,
  671. 0x00,
  672. 0x00,
  673. 0x00
  674. };
  675. r = USBmX_RawCommand(dev, cmd, res);
  676. if(r < 0) return r;
  677. if(res[0] != cmd[0]) return -1;
  678. return 0;
  679. }
  680. int USBmX_DirectionA(USBmX_DeviceRef dev, u_char dir0, u_char dir1)
  681. {
  682. int r;
  683. u_char res[8];
  684. u_char cmd[8] = {
  685. 0x09,
  686. dir0,
  687. dir1,
  688. 0x00,
  689. 0x00,
  690. 0x00,
  691. 0x00,
  692. 0x00
  693. };
  694. r = USBmX_RawCommand(dev, cmd, res);
  695. if(r < 0) return r;
  696. if(res[0] != cmd[0]) return -1;
  697. return 0;
  698. }
  699. int USBmX_DirectionB(USBmX_DeviceRef dev, u_char dir0, u_char dir1)
  700. {
  701. int r;
  702. u_char res[8];
  703. u_char cmd[8] = {
  704. 0x0A,
  705. dir0,
  706. dir1,
  707. 0x00,
  708. 0x00,
  709. 0x00,
  710. 0x00,
  711. 0x00
  712. };
  713. r = USBmX_RawCommand(dev, cmd, res);
  714. if(r < 0) return r;
  715. if(res[0] != cmd[0]) return -1;
  716. return 0;
  717. }
  718. int USBmX_StrobeWrite(USBmX_DeviceRef dev,
  719. u_char data,
  720. u_char port_select,
  721. u_char strobe_line,
  722. u_char pulse_length)
  723. {
  724. return -1;
  725. }
  726. int USBmX_StrobeRead(USBmX_DeviceRef dev,
  727. u_char *data_out,
  728. u_char port_select,
  729. u_char strobe_line,
  730. u_char pulse_length)
  731. {
  732. return -1;
  733. }
  734. int USBmX_StrobeWrites(USBmX_DeviceRef dev,
  735. u_char n_bytes,
  736. u_char bytes[])
  737. {
  738. return -1;
  739. }
  740. int USBmX_InitLCD(USBmX_DeviceRef dev,
  741. u_char rw_select,
  742. u_char rs_select,
  743. u_char port_select,
  744. u_char e_select)
  745. {
  746. return -1;
  747. }
  748. int USBmX_LCDCmd(USBmX_DeviceRef dev, u_char cmd)
  749. {
  750. return -1;
  751. }
  752. int USBmX_LCDData(USBmX_DeviceRef dev, u_char data)
  753. {
  754. return -1;
  755. }