1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165#define U14LIB_MAJOR 4
166#define U14LIB_MINOR 0
167#define U14LIB_REVISION 0
168#define U14LIB_VERSION ((U14LIB_MAJOR<<24) | (U14LIB_MINOR<<16) | U14LIB_REVISION)
169
170#include <stdlib.h>
171#include <string.h>
172#include <stdio.h>
173
174#include "USE1401.H"
175
176#ifdef _IS_WINDOWS_
177#include <io.h>
178#include <windows.h>
179#pragma warning(disable: 4100)
180#include <assert.h>
181#include "process.h"
182
183
184#define sprintf wsprintf
185#define PATHSEP '\\'
186#define PATHSEPSTR "\\"
187#define DEFCMDPATH "\\1401\\"
188#define MINDRIVERMAJREV 1
189#define __packed
190
191#include "use14_ioc.h"
192#endif
193
194#ifdef LINUX
195#include <fcntl.h>
196#include <unistd.h>
197#include <sys/ioctl.h>
198#include <errno.h>
199#include <sys/time.h>
200#include <sched.h>
201#include <libgen.h>
202#define PATHSEP '/'
203#define PATHSEPSTR "/"
204#define DEFCMDPATH "/var/1401/"
205#define MINDRIVERMAJREV 2
206
207#include "ced_ioctl.h"
208#endif
209
210#define MAX1401 8
211
212
213
214
215
216
217#define DRIVRET_STD 4
218#define DRIVRET_U1401 5
219#define DRIVRET_PLUS 6
220#define DRIVRET_POWER 7
221#define DRIVRET_MAX 26
222
223
224
225
226
227static char szLastName[20];
228
229
230
231
232
233
234
235
236static short asDriverType[MAX1401] = {0};
237static int lLastDriverVersion = U14ERR_NO1401DRIV;
238static int lLastDriverType = U14TYPEUNKNOWN;
239static int alDriverVersion[MAX1401];
240static int alTimeOutPeriod[MAX1401];
241static short asLastRetCode[MAX1401];
242static short asType1401[MAX1401] = {0};
243static BOOL abGrabbed[MAX1401] = {0};
244static int iAttached = 0;
245
246#ifdef _IS_WINDOWS_
247
248
249
250static HANDLE aHand1401[MAX1401] = {0};
251static HANDLE aXferEvent[MAX1401] = {0};
252static LPVOID apAreas[MAX1401][MAX_TRANSAREAS];
253static DWORD auAreas[MAX1401][MAX_TRANSAREAS];
254static BOOL bWindows9x = FALSE;
255#ifdef _WIN64
256#define USE_NT_DIOC(ind) TRUE
257#else
258static BOOL abUseNTDIOC[MAX1401];
259#define USE_NT_DIOC(ind) abUseNTDIOC[ind]
260#endif
261
262#endif
263
264#ifdef LINUX
265static int aHand1401[MAX1401] = {0};
266#define INVALID_HANDLE_VALUE 0
267#endif
268
269
270
271
272
273
274
275#pragma pack(1)
276typedef struct CmdHead
277{
278 char acBasic[5];
279 WORD wBasicSz;
280 WORD wCmdSize;
281} __packed CMDHEAD;
282#pragma pack()
283
284
285
286
287
288
289
290
291
292typedef CMDHEAD *LPCMDHEAD;
293
294#define MAXSTRLEN 255
295#define TOHOST FALSE
296#define TO1401 TRUE
297
298static short CheckHandle(short h)
299{
300 if ((h < 0) || (h >= MAX1401))
301 return U14ERR_BADHAND;
302 if (aHand1401[h] <= 0)
303 return U14ERR_BADHAND;
304 return U14ERR_NOERROR;
305}
306
307#ifdef _IS_WINDOWS_
308
309
310
311
312static short U14Status1401(short sHand, LONG lCode, TCSBLOCK* pBlk)
313{
314 DWORD dwBytes = 0;
315
316 if ((sHand < 0) || (sHand >= MAX1401))
317 return U14ERR_BADHAND;
318#ifndef _WIN64
319 if (!USE_NT_DIOC(sHand))
320 {
321 if (DeviceIoControl(aHand1401[sHand], lCode, NULL, 0, pBlk,sizeof(TCSBLOCK),&dwBytes,NULL))
322 return (short)((dwBytes>=sizeof(TCSBLOCK)) ? U14ERR_NOERROR : U14ERR_DRIVCOMMS);
323 else
324 return (short)GetLastError();
325 }
326 else
327#endif
328 {
329 PARAMBLK rWork;
330 rWork.sState = U14ERR_DRIVCOMMS;
331 if (DeviceIoControl(aHand1401[sHand], lCode, NULL, 0, &rWork,sizeof(PARAMBLK),&dwBytes,NULL) &&
332 (dwBytes >= sizeof(PARAMBLK)))
333 {
334 *pBlk = rWork.csBlock;
335 return rWork.sState;
336 }
337 }
338
339 return U14ERR_DRIVCOMMS;
340}
341
342
343
344
345
346static short U14Control1401(short sHand, LONG lCode, TCSBLOCK* pBlk)
347{
348 DWORD dwBytes = 0;
349
350 if ((sHand < 0) || (sHand >= MAX1401))
351 return U14ERR_BADHAND;
352
353#ifndef _WIN64
354 if (!USE_NT_DIOC(sHand))
355 {
356 if (DeviceIoControl(aHand1401[sHand], lCode, NULL, 0, pBlk, sizeof(TCSBLOCK), &dwBytes, NULL))
357 return (short)(dwBytes >= sizeof(TCSBLOCK) ? U14ERR_NOERROR : U14ERR_DRIVCOMMS);
358 else
359 return (short)GetLastError();
360 }
361 else
362#endif
363 {
364 PARAMBLK rWork;
365 rWork.sState = U14ERR_DRIVCOMMS;
366 if (DeviceIoControl(aHand1401[sHand], lCode, pBlk, sizeof(TCSBLOCK), &rWork, sizeof(PARAMBLK), &dwBytes, NULL) &&
367 (dwBytes >= sizeof(PARAMBLK)))
368 return rWork.sState;
369 }
370
371 return U14ERR_DRIVCOMMS;
372}
373#endif
374
375
376
377
378
379static long SafeTickCount()
380{
381#ifdef _IS_WINDOWS_
382 return GetTickCount();
383#endif
384#ifdef LINUX
385 struct timeval tv;
386 gettimeofday(&tv, NULL);
387 return (tv.tv_sec*1000 + tv.tv_usec/1000);
388#endif
389}
390
391
392
393
394
395static int ExtForType(short sType, char* szExt)
396{
397 szExt[0] = 0;
398 switch (sType)
399 {
400 case U14TYPE1401: strcpy(szExt, ".CMD"); break;
401 case U14TYPEPLUS: strcpy(szExt, ".GXC"); break;
402 default:
403 strcpy(szExt, ".ARM");
404 szExt[3] = (char)('M' + sType - U14TYPEU1401);
405 if (szExt[3] > 'Z')
406 szExt[3] = (char)(szExt[3] - 26);
407 }
408 return 0;
409}
410
411
412
413
414
415
416U14API(int) U14WhenToTimeOut(short hand)
417{
418 int iNow = SafeTickCount();
419 if ((hand >= 0) && (hand < MAX1401))
420 iNow += alTimeOutPeriod[hand];
421 return iNow;
422}
423
424
425
426
427
428U14API(short) U14PassedTime(int lCheckTime)
429{
430 return (short)((SafeTickCount()-lCheckTime) > 0);
431}
432
433
434
435
436
437
438static void TranslateString(char* pStr)
439{
440 int i = 0;
441 while (pStr[i])
442 {
443 if (pStr[i] == ',')
444 pStr[i] = ' ';
445 ++i;
446 }
447
448 if ((i > 0) && (pStr[i-1] == '\n'))
449 pStr[i-1] = (char)0;
450}
451
452
453
454
455
456U14API(short) U14StrToLongs(const char* pszBuff, U14LONG *palNums, short sMaxLongs)
457{
458 WORD wChInd = 0;
459 short sLgInd = 0;
460
461 while (pszBuff[wChInd] &&
462 (sLgInd < sMaxLongs))
463 {
464
465 switch (pszBuff[wChInd])
466 {
467 case '-':
468 case '0': case '1': case '2': case '3': case '4':
469 case '5': case '6': case '7': case '8': case '9':
470 {
471 BOOL bDone = FALSE;
472 int iSign = 1;
473 long lValue = 0;
474
475 while ((!bDone) && pszBuff[wChInd])
476 {
477 switch (pszBuff[wChInd])
478 {
479 case '-':
480 iSign = -1;
481 break;
482
483 case '0': case '1': case '2': case '3': case '4':
484 case '5': case '6': case '7': case '8': case '9':
485 lValue *= 10;
486 lValue += ((int)pszBuff[wChInd]-(int)'0');
487 break;
488
489 default:
490 bDone = TRUE;
491 break;
492 }
493 wChInd++;
494 }
495 palNums[sLgInd] = lValue * iSign;
496 sLgInd++;
497 }
498 break;
499
500 default:
501 wChInd++;
502 break;
503 }
504 }
505 return (sLgInd);
506}
507
508
509
510
511
512
513
514U14API(short) U14LongsFrom1401(short hand, U14LONG *palBuff, short sMaxLongs)
515{
516 char szWork[MAXSTRLEN];
517 short sResult = U14GetString(hand, szWork, MAXSTRLEN);
518 if (sResult == U14ERR_NOERROR)
519 sResult = U14StrToLongs(szWork, palBuff, sMaxLongs);
520 return sResult;
521}
522
523
524
525
526
527
528U14API(short) U14CheckErr(short hand)
529{
530 short sResult = U14SendString(hand, ";ERR;");
531 if (sResult == U14ERR_NOERROR)
532 {
533 U14LONG er[3];
534 sResult = U14LongsFrom1401(hand, er, 3);
535 if (sResult > 0)
536 {
537 sResult = (short)er[0];
538#ifdef _DEBUG
539 if (er[0] != 0)
540 {
541 char szMsg[50];
542 sprintf(szMsg, "U14CheckErr returned %d,%d\n", er[0], er[1]);
543 OutputDebugString(szMsg);
544 }
545#endif
546 }
547 else
548 {
549 if (sResult == 0)
550 sResult = U14ERR_TIMEOUT;
551 }
552 }
553
554 return sResult;
555}
556
557
558
559
560
561
562U14API(short) U14LastErrCode(short hand)
563{
564 if ((hand < 0) || (hand >= MAX1401))
565 return U14ERR_BADHAND;
566 return asLastRetCode[hand];
567}
568
569
570
571
572
573U14API(void) U14SetTimeout(short hand, int lTimeOut)
574{
575 if ((hand < 0) || (hand >= MAX1401))
576 return;
577 alTimeOutPeriod[hand] = lTimeOut;
578}
579
580
581
582
583
584U14API(int) U14GetTimeout(short hand)
585{
586 if ((hand < 0) || (hand >= MAX1401))
587 return U14ERR_BADHAND;
588 return alTimeOutPeriod[hand];
589}
590
591
592
593
594
595U14API(short) U14OutBufSpace(short hand)
596{
597#ifdef _IS_WINDOWS_
598 TCSBLOCK csBlock;
599 short sErr = U14Status1401(hand, U14_GETOUTBUFSPACE,&csBlock);
600 if (sErr == U14ERR_NOERROR)
601 sErr = csBlock.ints[0];
602 return sErr;
603#endif
604#ifdef LINUX
605 short sErr = CheckHandle(hand);
606 return (sErr == U14ERR_NOERROR) ? CED_GetOutBufSpace(aHand1401[hand]) : sErr;
607#endif
608}
609
610
611
612
613
614
615U14API(int) U14BaseAddr1401(short hand)
616{
617#ifdef _IS_WINDOWS_
618 TCSBLOCK csBlock;
619 int iError = U14Status1401(hand, U14_GETBASEADDRESS,&csBlock);
620 if (iError == U14ERR_NOERROR)
621 iError = csBlock.longs[0];
622 return iError;
623#endif
624#ifdef LINUX
625 short sErr = CheckHandle(hand);
626 return (sErr == U14ERR_NOERROR) ? CED_GetBaseAddress(aHand1401[hand]) : sErr;
627#endif
628}
629
630
631
632
633
634U14API(short) U14StateOf1401(short hand)
635{
636#ifdef _IS_WINDOWS_
637 TCSBLOCK csBlock;
638 short sErr = U14Status1401(hand, U14_STATEOF1401, &csBlock);
639 if (sErr == U14ERR_NOERROR)
640 {
641 sErr = csBlock.ints[0];
642 if ((sErr >= DRIVRET_STD) && (sErr <= DRIVRET_MAX))
643 sErr = U14ERR_NOERROR;
644 }
645#endif
646#ifdef LINUX
647 short sErr = CheckHandle(hand);
648 if (sErr == U14ERR_NOERROR)
649 {
650 sErr = (short)CED_StateOf1401(aHand1401[hand]);
651 if ((sErr >= DRIVRET_STD) && (sErr <= DRIVRET_MAX))
652 sErr = U14ERR_NOERROR;
653 }
654#endif
655 return sErr;
656}
657
658
659
660
661
662
663
664U14API(int) U14DriverVersion(short hand)
665{
666 return CheckHandle(hand) != U14ERR_NOERROR ? lLastDriverVersion : alDriverVersion[hand];
667}
668
669
670
671
672
673
674
675U14API(int) U14DriverType(short hand)
676{
677 return CheckHandle(hand) != U14ERR_NOERROR ? lLastDriverType : asDriverType[hand];
678}
679
680
681
682
683
684U14API(short) U14DriverName(short hand, char* pBuf, WORD wMax)
685{
686 char* pName;
687 *pBuf = 0;
688 switch (U14DriverType(hand))
689 {
690 case 0: pName = "ISA"; break;
691 case 1: pName = "PCI"; break;
692 case 2: pName = "USB"; break;
693 case 3: pName = "HSS"; break;
694 default: pName = "???"; break;
695 }
696 strncpy(pBuf, pName, wMax);
697
698 return U14ERR_NOERROR;
699}
700
701
702
703
704
705U14API(short) U14BlkTransState(short hand)
706{
707#ifdef _IS_WINDOWS_
708 TCSBLOCK csBlock;
709 short sErr = U14Status1401(hand, U14_BLKTRANSSTATE, &csBlock);
710 if (sErr == U14ERR_NOERROR)
711 sErr = csBlock.ints[0];
712 return sErr;
713#endif
714#ifdef LINUX
715 short sErr = CheckHandle(hand);
716 return (sErr == U14ERR_NOERROR) ? CED_BlkTransState(aHand1401[hand]) : sErr;
717#endif
718}
719
720
721
722
723
724U14API(short) U14Grab1401(short hand)
725{
726 short sErr = CheckHandle(hand);
727 if (sErr == U14ERR_NOERROR)
728 {
729#ifdef _IS_WINDOWS_
730 if (abGrabbed[hand])
731 sErr = U14ERR_ALREADYSET;
732 else
733 {
734 TCSBLOCK csBlock;
735 sErr = U14Control1401(hand, U14_GRAB1401, &csBlock);
736 }
737#endif
738#ifdef LINUX
739
740 sErr = abGrabbed[hand] ? U14ERR_ALREADYSET : CED_Grab1401(aHand1401[hand]);
741#endif
742 if (sErr == U14ERR_NOERROR)
743 abGrabbed[hand] = TRUE;
744 }
745 return sErr;
746}
747
748
749
750
751U14API(short) U14Free1401(short hand)
752{
753 short sErr = CheckHandle(hand);
754 if (sErr == U14ERR_NOERROR)
755 {
756#ifdef _IS_WINDOWS_
757 if (abGrabbed[hand])
758 {
759 TCSBLOCK csBlock;
760 sErr = U14Control1401(hand, U14_FREE1401, &csBlock);
761 }
762 else
763 sErr = U14ERR_NOTSET;
764#endif
765#ifdef LINUX
766
767 sErr = abGrabbed[hand] ? CED_Free1401(aHand1401[hand]) : U14ERR_NOTSET;
768#endif
769 if (sErr == U14ERR_NOERROR)
770 abGrabbed[hand] = FALSE;
771 }
772 return sErr;
773}
774
775
776
777
778
779
780
781
782U14API(short) U14Peek1401(short hand, DWORD dwAddr, int nSize, int nRepeats)
783{
784 short sErr = CheckHandle(hand);
785 if (sErr == U14ERR_NOERROR)
786 {
787 if (abGrabbed[hand])
788 {
789#ifdef _IS_WINDOWS_
790 TCSBLOCK csBlock;
791 csBlock.longs[0] = (long)dwAddr;
792 csBlock.longs[1] = nSize;
793 csBlock.longs[2] = nRepeats;
794 sErr = U14Control1401(hand, U14_DBGPEEK, &csBlock);
795#endif
796#ifdef LINUX
797 TDBGBLOCK dbb;
798 dbb.iAddr = (int)dwAddr;
799 dbb.iWidth = nSize;
800 dbb.iRepeats = nRepeats;
801 sErr = CED_DbgPeek(aHand1401[hand], &dbb);
802#endif
803 }
804 else
805 sErr = U14ERR_NOTSET;
806 }
807 return sErr;
808}
809
810
811
812
813
814
815
816U14API(short) U14Poke1401(short hand, DWORD dwAddr, DWORD dwValue,
817 int nSize, int nRepeats)
818{
819 short sErr = CheckHandle(hand);
820 if (sErr == U14ERR_NOERROR)
821 {
822 if (abGrabbed[hand])
823 {
824#ifdef _IS_WINDOWS_
825 TCSBLOCK csBlock;
826 csBlock.longs[0] = (long)dwAddr;
827 csBlock.longs[1] = nSize;
828 csBlock.longs[2] = nRepeats;
829 csBlock.longs[3] = (long)dwValue;
830 sErr = U14Control1401(hand, U14_DBGPOKE, &csBlock);
831#endif
832#ifdef LINUX
833 TDBGBLOCK dbb;
834 dbb.iAddr = (int)dwAddr;
835 dbb.iWidth = nSize;
836 dbb.iRepeats= nRepeats;
837 dbb.iData = (int)dwValue;
838 sErr = CED_DbgPoke(aHand1401[hand], &dbb);
839#endif
840 }
841 else
842 sErr = U14ERR_NOTSET;
843 }
844 return sErr;
845}
846
847
848
849
850
851
852U14API(short) U14Ramp1401(short hand, DWORD dwAddr, DWORD dwDef, DWORD dwEnable,
853 int nSize, int nRepeats)
854{
855 short sErr = CheckHandle(hand);
856 if (sErr == U14ERR_NOERROR)
857 {
858 if (abGrabbed[hand])
859 {
860#ifdef _IS_WINDOWS_
861 TCSBLOCK csBlock;
862 csBlock.longs[0] = (long)dwAddr;
863 csBlock.longs[1] = (long)dwDef;
864 csBlock.longs[2] = (long)dwEnable;
865 csBlock.longs[3] = nSize;
866 csBlock.longs[4] = nRepeats;
867 sErr = U14Control1401(hand, U14_DBGRAMPDATA, &csBlock);
868#endif
869#ifdef LINUX
870 TDBGBLOCK dbb;
871 dbb.iAddr = (int)dwAddr;
872 dbb.iDefault = (int)dwDef;
873 dbb.iMask = (int)dwEnable;
874 dbb.iWidth = nSize;
875 dbb.iRepeats = nRepeats;
876 sErr = CED_DbgRampAddr(aHand1401[hand], &dbb);
877#endif
878 }
879 else
880 sErr = U14ERR_NOTSET;
881 }
882 return sErr;
883}
884
885
886
887
888
889
890U14API(short) U14RampAddr(short hand, DWORD dwDef, DWORD dwEnable,
891 int nSize, int nRepeats)
892{
893 short sErr = CheckHandle(hand);
894 if (sErr == U14ERR_NOERROR)
895 {
896 if (abGrabbed[hand])
897 {
898#ifdef _IS_WINDOWS_
899 TCSBLOCK csBlock;
900 csBlock.longs[0] = (long)dwDef;
901 csBlock.longs[1] = (long)dwEnable;
902 csBlock.longs[2] = nSize;
903 csBlock.longs[3] = nRepeats;
904 sErr = U14Control1401(hand, U14_DBGRAMPADDR, &csBlock);
905#endif
906#ifdef LINUX
907 TDBGBLOCK dbb;
908 dbb.iDefault = (int)dwDef;
909 dbb.iMask = (int)dwEnable;
910 dbb.iWidth = nSize;
911 dbb.iRepeats = nRepeats;
912 sErr = CED_DbgRampAddr(aHand1401[hand], &dbb);
913#endif
914 }
915 else
916 sErr = U14ERR_NOTSET;
917 }
918 return sErr;
919}
920
921
922
923
924
925
926U14API(short) U14StopDebugLoop(short hand)
927{
928 short sErr = CheckHandle(hand);
929 if (sErr == U14ERR_NOERROR)
930#ifdef _IS_WINDOWS_
931 {
932 if (abGrabbed[hand])
933 {
934 TCSBLOCK csBlock;
935 sErr = U14Control1401(hand, U14_DBGSTOPLOOP, &csBlock);
936 }
937 else
938 sErr = U14ERR_NOTSET;
939 }
940#endif
941#ifdef LINUX
942 sErr = abGrabbed[hand] ? CED_DbgStopLoop(aHand1401[hand]) : U14ERR_NOTSET;
943#endif
944 return sErr;
945}
946
947
948
949
950
951U14API(short) U14GetDebugData(short hand, U14LONG* plValue)
952{
953 short sErr = CheckHandle(hand);
954 if (sErr == U14ERR_NOERROR)
955 {
956 if (abGrabbed[hand])
957 {
958#ifdef _IS_WINDOWS_
959 TCSBLOCK csBlock;
960 sErr = U14Status1401(hand, U14_DBGGETDATA, &csBlock);
961 if (sErr == U14ERR_NOERROR)
962 *plValue = csBlock.longs[0];
963#endif
964#ifdef LINUX
965 TDBGBLOCK dbb;
966 sErr = CED_DbgGetData(aHand1401[hand], &dbb);
967 if (sErr == U14ERR_NOERROR)
968 *plValue = dbb.iData;
969#endif
970 }
971 else
972 sErr = U14ERR_NOTSET;
973 }
974 return sErr;
975}
976
977
978
979
980U14API(short) U14StartSelfTest(short hand)
981{
982#ifdef _IS_WINDOWS_
983 TCSBLOCK csBlock;
984 return U14Control1401(hand, U14_STARTSELFTEST, &csBlock);
985#endif
986#ifdef LINUX
987 short sErr = CheckHandle(hand);
988 return (sErr == U14ERR_NOERROR) ? CED_StartSelfTest(aHand1401[hand]) : sErr;
989#endif
990}
991
992
993
994
995U14API(short) U14CheckSelfTest(short hand, U14LONG *pData)
996{
997#ifdef _IS_WINDOWS_
998 TCSBLOCK csBlock;
999 short sErr = U14Status1401(hand, U14_CHECKSELFTEST, &csBlock);
1000 if (sErr == U14ERR_NOERROR)
1001 {
1002 pData[0] = csBlock.longs[0];
1003 pData[1] = csBlock.longs[1];
1004 pData[2] = csBlock.longs[2];
1005 }
1006#endif
1007#ifdef LINUX
1008 short sErr = CheckHandle(hand);
1009 if (sErr == U14ERR_NOERROR)
1010 {
1011 TGET_SELFTEST gst;
1012 sErr = CED_CheckSelfTest(aHand1401[hand], &gst);
1013 if (sErr == U14ERR_NOERROR)
1014 {
1015 pData[0] = gst.code;
1016 pData[1] = gst.x;
1017 pData[2] = gst.y;
1018 }
1019 }
1020#endif
1021 return sErr;
1022}
1023
1024
1025
1026
1027U14API(short) U14GetUserMemorySize(short hand, DWORD *pMemorySize)
1028{
1029
1030 short sErr = U14SendString(hand, (asType1401[hand] == U14TYPE1401) ? "MEMTOP;" : "MEMTOP,?;");
1031 *pMemorySize = 0;
1032 if (sErr == U14ERR_NOERROR)
1033 {
1034 U14LONG alLimits[4];
1035 sErr = U14LongsFrom1401(hand, alLimits, 4);
1036 if (sErr > 0)
1037 {
1038 sErr = U14ERR_NOERROR;
1039 if (asType1401[hand] == U14TYPE1401)
1040 *pMemorySize = alLimits[0] - alLimits[1];
1041 else
1042 *pMemorySize = alLimits[0];
1043 }
1044 }
1045 return sErr;
1046}
1047
1048
1049
1050
1051
1052U14API(short) U14TypeOf1401(short hand)
1053{
1054 if ((hand < 0) || (hand >= MAX1401))
1055 return U14ERR_BADHAND;
1056 else
1057 return asType1401[hand];
1058}
1059
1060
1061
1062
1063
1064U14API(short) U14NameOf1401(short hand, char* pBuf, WORD wMax)
1065{
1066 short sErr = CheckHandle(hand);
1067 if (sErr == U14ERR_NOERROR)
1068 {
1069 char* pName;
1070 switch (asType1401[hand])
1071 {
1072 case U14TYPE1401: pName = "Std 1401"; break;
1073 case U14TYPEPLUS: pName = "1401plus"; break;
1074 case U14TYPEU1401: pName = "micro1401"; break;
1075 case U14TYPEPOWER: pName = "Power1401"; break;
1076 case U14TYPEU14012:pName = "Micro1401 mk II"; break;
1077 case U14TYPEPOWER2:pName = "Power1401 mk II"; break;
1078 case U14TYPEU14013:pName = "Micro1401-3"; break;
1079 case U14TYPEPOWER3:pName = "Power1401-3"; break;
1080 default: pName = "Unknown";
1081 }
1082 strncpy(pBuf, pName, wMax);
1083 }
1084 return sErr;
1085}
1086
1087
1088
1089
1090
1091
1092U14API(short) U14TransferFlags(short hand)
1093{
1094#ifdef _IS_WINDOWS_
1095 TCSBLOCK csBlock;
1096 short sErr = U14Status1401(hand, U14_TRANSFERFLAGS, &csBlock);
1097 return (sErr == U14ERR_NOERROR) ? (short)csBlock.ints[0] : sErr;
1098#endif
1099#ifdef LINUX
1100 short sErr = CheckHandle(hand);
1101 return (sErr == U14ERR_NOERROR) ? CED_TransferFlags(aHand1401[hand]) : sErr;
1102#endif
1103}
1104
1105
1106
1107
1108
1109
1110
1111static int GetDriverVersion(short hand)
1112{
1113#ifdef _IS_WINDOWS_
1114 TCSBLOCK csBlock;
1115 int iErr = U14Status1401(hand, U14_GETDRIVERREVISION, &csBlock);
1116 if (iErr == U14ERR_NOERROR)
1117 iErr = csBlock.longs[0];
1118 return iErr;
1119#endif
1120#ifdef LINUX
1121 return CED_GetDriverRevision(aHand1401[hand]);
1122#endif
1123}
1124
1125
1126
1127
1128
1129
1130
1131U14API(int) U14MonitorRev(short hand)
1132{
1133 int iRev = 0;
1134 int iErr = CheckHandle(hand);
1135 if (iErr != U14ERR_NOERROR)
1136 return iErr;
1137
1138 if (asType1401[hand] >= U14TYPEPOWER2)
1139 {
1140 iErr = U14SendString(hand, "INFO,S,28;");
1141 if (iErr == U14ERR_NOERROR)
1142 {
1143 U14LONG lVals[2];
1144 iErr = U14LongsFrom1401(hand, lVals, 1);
1145 if (iErr > 0)
1146 {
1147 iErr = U14ERR_NOERROR;
1148 iRev = lVals[0];
1149 iRev += asType1401[hand] * 10000;
1150 }
1151 }
1152 }
1153 else
1154 {
1155 iErr = U14SendString(hand, ";CLIST;");
1156 if (iErr == U14ERR_NOERROR)
1157 {
1158 while (iErr == U14ERR_NOERROR)
1159 {
1160 char wstr[50];
1161 iErr = U14GetString(hand, wstr, 45);
1162 if (iErr == U14ERR_NOERROR)
1163 {
1164 char *pstr = strstr(wstr,"RESET");
1165 if ((pstr == wstr) && (wstr[5] == ' '))
1166 {
1167 char *pstr2;
1168 size_t l;
1169 pstr += 6;
1170 l = strlen(pstr);
1171 while (((pstr[l-1] == ' ') || (pstr[l-1] == 13)) && (l > 0))
1172 {
1173 pstr[l-1] = 0;
1174 l--;
1175 }
1176 pstr2 = strchr(pstr, '.');
1177 if (pstr2 != NULL)
1178 {
1179 *pstr2 = 0;
1180 pstr2++;
1181 iRev = atoi(pstr2);
1182 }
1183 iRev += (atoi(pstr) * 1000);
1184 }
1185 if ((strlen(wstr) < 3) && (wstr[0] == ' '))
1186 break;
1187 }
1188 }
1189 }
1190 }
1191 if (iErr == U14ERR_NOERROR)
1192 iErr = iRev;
1193
1194 return iErr;
1195}
1196
1197
1198
1199
1200
1201
1202
1203#ifdef _IS_WINDOWS_
1204#define U14NAMEOLD "\\\\.\\CED_140%d"
1205#define U14NAMENEW "\\\\.\\CED%d"
1206static short U14TryToOpen(int n1401, long* plRetVal, short* psHandle)
1207{
1208 short sErr = U14ERR_NOERROR;
1209 HANDLE hDevice = INVALID_HANDLE_VALUE;
1210 DWORD dwErr = 0;
1211 int nFirst, nLast, nDev = 0;
1212 BOOL bOldName = FALSE;
1213
1214 if (n1401 == 0)
1215 {
1216 nFirst = 1;
1217 nLast = MAX1401;
1218 }
1219 else
1220 nFirst = nLast = n1401;
1221
1222 while (hDevice == INVALID_HANDLE_VALUE)
1223 {
1224 for (nDev = nFirst; nDev <= nLast; nDev++)
1225 {
1226 char szDevName[40];
1227 sprintf(szDevName, bOldName ? U14NAMEOLD : U14NAMENEW, nDev);
1228 hDevice = CreateFile(szDevName, GENERIC_WRITE | GENERIC_READ,
1229 0, 0,
1230 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1231
1232 if (hDevice != INVALID_HANDLE_VALUE)
1233 {
1234 TCSBLOCK csBlock;
1235 assert(aHand1401[nDev-1] == INVALID_HANDLE_VALUE);
1236 aHand1401[nDev-1] = hDevice;
1237
1238#ifndef _WIN64
1239
1240 abUseNTDIOC[nDev-1] = (BOOL)(!bWindows9x || !bOldName);
1241#endif
1242 sErr = U14Status1401((short)(nDev-1), U14_TYPEOF1401, &csBlock);
1243 if (sErr == U14ERR_NOERROR)
1244 {
1245 *plRetVal = csBlock.ints[0];
1246 if (csBlock.ints[0] == U14ERR_INUSE)
1247 {
1248 CloseHandle(hDevice);
1249 hDevice = INVALID_HANDLE_VALUE;
1250 aHand1401[nDev-1] = INVALID_HANDLE_VALUE;
1251 sErr = U14ERR_INUSE;
1252 }
1253 else
1254 break;
1255 }
1256 else
1257 {
1258 CloseHandle(hDevice);
1259 hDevice = INVALID_HANDLE_VALUE;
1260 aHand1401[nDev-1] = INVALID_HANDLE_VALUE;
1261 }
1262 }
1263 else
1264 {
1265 DWORD dwe = GetLastError();
1266 if ((dwe != ERROR_FILE_NOT_FOUND) || (dwErr == 0))
1267 dwErr = dwe;
1268 }
1269 }
1270
1271 if ((hDevice == INVALID_HANDLE_VALUE) &&
1272 (bWindows9x) &&
1273 (bOldName == FALSE))
1274 bOldName = TRUE;
1275 else
1276 break;
1277 }
1278
1279 if (hDevice != INVALID_HANDLE_VALUE)
1280 *psHandle = (short)(nDev-1);
1281 else
1282 {
1283 if (dwErr == ERROR_FILE_NOT_FOUND)
1284 sErr = U14ERR_NO1401DRIV;
1285 else if (dwErr == ERROR_NOT_SUPPORTED)
1286 sErr = U14ERR_DRIVTOOOLD;
1287 else if (dwErr == ERROR_ACCESS_DENIED)
1288 sErr = U14ERR_INUSE;
1289 else
1290 sErr = U14ERR_DRIVCOMMS;
1291 }
1292 return sErr;
1293}
1294#endif
1295#ifdef LINUX
1296static short U14TryToOpen(int n1401, long* plRetVal, short* psHandle)
1297{
1298 short sErr = U14ERR_NOERROR;
1299 int fh = 0;
1300 int iErr = 0;
1301 int nFirst, nLast, nDev = 0;
1302
1303 if (n1401 == 0)
1304 {
1305 nFirst = 1;
1306 nLast = MAX1401;
1307 }
1308 else
1309 nFirst = nLast = n1401;
1310
1311 for (nDev = nFirst; nDev <= nLast; nDev++)
1312 {
1313 char szDevName[40];
1314 sprintf(szDevName,"/dev/cedusb/%d", nDev-1);
1315 fh = open(szDevName, O_RDWR);
1316 if (fh > 0)
1317 {
1318 int iType1401 = CED_TypeOf1401(fh);
1319 aHand1401[nDev-1] = fh;
1320 if (iType1401 >= 0)
1321 {
1322 *plRetVal = iType1401;
1323 break;
1324 }
1325 else
1326 {
1327 close(fh);
1328 fh = 0;
1329 aHand1401[nDev-1] = 0;
1330 }
1331 }
1332 else
1333 {
1334 if (((errno != ENODEV) && (errno != ENOENT)) || (iErr == 0))
1335 iErr = errno;
1336 }
1337 }
1338
1339
1340 if (fh)
1341 *psHandle = (short)(nDev-1);
1342 else
1343 {
1344 if ((iErr == ENODEV) || (iErr == ENOENT))
1345 sErr = U14ERR_NO1401DRIV;
1346 else if (iErr == EBUSY)
1347 sErr = U14ERR_INUSE;
1348 else
1349 sErr = U14ERR_DRIVCOMMS;
1350 }
1351
1352 return sErr;
1353}
1354#endif
1355
1356
1357
1358
1359U14API(short) U14Open1401(short n1401)
1360{
1361 long lRetVal = -1;
1362 short sErr;
1363 short hand = 0;
1364
1365 if ((n1401 < 0) || (n1401 > MAX1401))
1366 return U14ERR_BAD1401NUM;
1367
1368 szLastName[0] = 0;
1369
1370 sErr = U14TryToOpen(n1401, &lRetVal, &hand);
1371 if (sErr == U14ERR_NOERROR)
1372 {
1373 long lDriverVersion = GetDriverVersion(hand);
1374 long lDriverRev = -1;
1375 if (lDriverVersion >= 0)
1376 {
1377 lLastDriverType = (lDriverVersion >> 24) & 0x000000FF;
1378 asDriverType[hand] = (short)lLastDriverType;
1379 lLastDriverVersion = lDriverVersion & 0x00FFFFFF;
1380 alDriverVersion[hand] = lLastDriverVersion;
1381 lDriverRev = ((lDriverVersion>>16) & 0x00FF);
1382 }
1383 else
1384 {
1385 U14Close1401(hand);
1386 return (short)lDriverVersion;
1387 }
1388
1389 if (lDriverRev < MINDRIVERMAJREV)
1390 {
1391 U14Close1401(hand);
1392 return U14ERR_DRIVTOOOLD;
1393 }
1394
1395 asLastRetCode[hand] = U14ERR_NOERROR;
1396 abGrabbed[hand] = FALSE;
1397 U14SetTimeout(hand, 3000);
1398
1399 switch (lRetVal)
1400 {
1401 case DRIVRET_STD: asType1401[hand] = U14TYPE1401; break;
1402 case DRIVRET_U1401:asType1401[hand] = U14TYPEU1401; break;
1403 case DRIVRET_PLUS: asType1401[hand] = U14TYPEPLUS; break;
1404 default:
1405 if ((lRetVal >= DRIVRET_POWER) && (lRetVal <= DRIVRET_MAX))
1406 asType1401[hand] = (short)(lRetVal - (DRIVRET_POWER - U14TYPEPOWER));
1407 else
1408 asType1401[hand] = U14TYPEUNKNOWN;
1409 break;
1410 }
1411 U14KillIO1401(hand);
1412
1413 if (asType1401[hand] != U14TYPEUNKNOWN)
1414 {
1415 sErr = U14CheckErr(hand);
1416 if (sErr != 0)
1417 U14Reset1401(hand);
1418 }
1419
1420 sErr = U14StateOf1401(hand);
1421 if (sErr == U14ERR_NOERROR)
1422 sErr = hand;
1423 else
1424 U14Close1401(hand);
1425 }
1426
1427 return sErr;
1428}
1429
1430
1431
1432
1433
1434
1435U14API(short) U14Close1401(short hand)
1436{
1437 int j;
1438 int iAreaMask = 0;
1439 short sErr = CheckHandle(hand);
1440 if (sErr != U14ERR_NOERROR)
1441 return sErr;
1442
1443 for (j = 0; j<MAX_TRANSAREAS; ++j)
1444 {
1445 TGET_TX_BLOCK gtb;
1446 int iReturn = U14GetTransfer(hand, >b);
1447 if (iReturn == U14ERR_NOERROR)
1448 if (gtb.used)
1449 iAreaMask |= (1 << j);
1450 }
1451
1452 if (iAreaMask)
1453 {
1454 U14Reset1401(hand);
1455 for (j = 0; j < MAX_TRANSAREAS; ++j)
1456 if (iAreaMask & (1 << j))
1457 U14UnSetTransfer(hand, (WORD)j);
1458 }
1459
1460#ifdef _IS_WINDOWS_
1461 if (aXferEvent[hand])
1462 {
1463 CloseHandle(aXferEvent[hand]);
1464 aXferEvent[hand] = NULL;
1465 }
1466
1467 if (CloseHandle(aHand1401[hand]))
1468#endif
1469#ifdef LINUX
1470 if (close(aHand1401[hand]) == 0)
1471#endif
1472 {
1473 aHand1401[hand] = INVALID_HANDLE_VALUE;
1474 asType1401[hand] = U14TYPEUNKNOWN;
1475 return U14ERR_NOERROR;
1476 }
1477 else
1478 return U14ERR_BADHAND;
1479}
1480
1481
1482
1483
1484
1485U14API(void) U14CloseAll(void)
1486{
1487 int i;
1488 for (i = 0; i < MAX1401; i++)
1489 if (aHand1401[i] != INVALID_HANDLE_VALUE)
1490 U14Close1401((short)i);
1491}
1492
1493
1494
1495
1496
1497U14API(short) U14Reset1401(short hand)
1498{
1499#ifdef _IS_WINDOWS_
1500 TCSBLOCK csBlock;
1501 return U14Control1401(hand, U14_RESET1401, &csBlock);
1502#endif
1503#ifdef LINUX
1504 short sErr = CheckHandle(hand);
1505 return (sErr == U14ERR_NOERROR) ? CED_Reset1401(aHand1401[hand]) : sErr;
1506#endif
1507}
1508
1509
1510
1511
1512
1513
1514U14API(short) U14ForceReset(short hand)
1515{
1516#ifdef _IS_WINDOWS_
1517 TCSBLOCK csBlock;
1518 return U14Control1401(hand, U14_FULLRESET, &csBlock);
1519#endif
1520#ifdef LINUX
1521 short sErr = CheckHandle(hand);
1522 return (sErr == U14ERR_NOERROR) ? CED_FullReset(aHand1401[hand]) : sErr;
1523#endif
1524}
1525
1526
1527
1528
1529
1530U14API(short) U14KillIO1401(short hand)
1531{
1532#ifdef _IS_WINDOWS_
1533 TCSBLOCK csBlock;
1534 return U14Control1401(hand, U14_KILLIO1401, &csBlock);
1535#endif
1536#ifdef LINUX
1537 short sErr = CheckHandle(hand);
1538 return (sErr == U14ERR_NOERROR) ? CED_KillIO1401(aHand1401[hand]) : sErr;
1539#endif
1540}
1541
1542
1543
1544
1545
1546
1547U14API(short) U14SendString(short hand, const char* pString)
1548{
1549 int nChars;
1550 long lTimeOutTicks;
1551 BOOL bSpaceToSend;
1552 short sErr = CheckHandle(hand);
1553 if (sErr != U14ERR_NOERROR)
1554 return sErr;
1555
1556 nChars = (int)strlen(pString);
1557 if (nChars > MAXSTRLEN)
1558 return U14ERR_STRLEN;
1559
1560#ifdef _IS_WINDOWS_
1561
1562 lTimeOutTicks = U14WhenToTimeOut(hand);
1563 do
1564 {
1565 bSpaceToSend = (BOOL)((long)U14OutBufSpace(hand) >= nChars);
1566 }
1567 while (!bSpaceToSend && !U14PassedTime(lTimeOutTicks));
1568
1569 if (!bSpaceToSend)
1570 {
1571 int i;
1572 for (i = 0; (i < 4) && (!bSpaceToSend); ++i)
1573 {
1574 Sleep(25);
1575 bSpaceToSend = (BOOL)((long)U14OutBufSpace(hand) >= nChars);
1576 }
1577 }
1578
1579 if (asLastRetCode[hand] == U14ERR_NOERROR)
1580 {
1581 if (bSpaceToSend)
1582 {
1583 PARAMBLK rData;
1584 DWORD dwBytes;
1585 char tstr[MAXSTRLEN+5];
1586
1587 if ((hand < 0) || (hand >= MAX1401))
1588 sErr = U14ERR_BADHAND;
1589 else
1590 {
1591 strcpy(tstr, pString);
1592#ifndef _WIN64
1593 if (!USE_NT_DIOC(hand))
1594 {
1595 int iOK = DeviceIoControl(aHand1401[hand], (DWORD)U14_SENDSTRING,
1596 NULL, 0, tstr, nChars,
1597 &dwBytes, NULL);
1598 if (iOK)
1599 sErr = (dwBytes >= (DWORD)nChars) ? U14ERR_NOERROR : U14ERR_DRIVCOMMS;
1600 else
1601 sErr = (short)GetLastError();
1602 }
1603 else
1604#endif
1605 {
1606 int iOK = DeviceIoControl(aHand1401[hand],(DWORD)U14_SENDSTRING,
1607 tstr, nChars,
1608 &rData,sizeof(PARAMBLK),&dwBytes,NULL);
1609 if (iOK && (dwBytes >= sizeof(PARAMBLK)))
1610 sErr = rData.sState;
1611 else
1612 sErr = U14ERR_DRIVCOMMS;
1613 }
1614
1615 if (sErr != U14ERR_NOERROR)
1616 U14ForceReset(hand);
1617 }
1618
1619 return sErr;
1620
1621 }
1622 else
1623 {
1624 U14ForceReset(hand);
1625 return U14ERR_TIMEOUT;
1626 }
1627 }
1628 else
1629 return asLastRetCode[hand];
1630#endif
1631#ifdef LINUX
1632
1633 sErr = CED_SendString(aHand1401[hand], pString, nChars);
1634 if (sErr != U14ERR_NOOUT)
1635 {
1636 if (sErr != U14ERR_NOERROR)
1637 U14ForceReset(hand);
1638 return sErr;
1639 }
1640
1641
1642 lTimeOutTicks = U14WhenToTimeOut(hand);
1643 do
1644 {
1645 bSpaceToSend = (BOOL)((long)U14OutBufSpace(hand) >= nChars);
1646 if (!bSpaceToSend)
1647 sched_yield();
1648 }
1649 while (!bSpaceToSend && !U14PassedTime(lTimeOutTicks));
1650
1651 if (asLastRetCode[hand] == U14ERR_NOERROR)
1652 {
1653 if (bSpaceToSend)
1654 {
1655 sErr = CED_SendString(aHand1401[hand], pString, nChars);
1656 if (sErr != U14ERR_NOERROR)
1657 U14ForceReset(hand);
1658 return sErr;
1659 }
1660 else
1661 {
1662 U14ForceReset(hand);
1663 return U14ERR_TIMEOUT;
1664 }
1665 }
1666 else
1667 return asLastRetCode[hand];
1668#endif
1669}
1670
1671
1672
1673
1674
1675U14API(short) U14SendChar(short hand, char cChar)
1676{
1677#ifdef _IS_WINDOWS_
1678 char sz[2]=" ";
1679 sz[0] = cChar;
1680 sz[1] = 0;
1681 return(U14SendString(hand, sz));
1682#endif
1683#ifdef LINUX
1684 short sErr = CheckHandle(hand);
1685 return (sErr == U14ERR_NOERROR) ? CED_SendChar(aHand1401[hand], cChar) : sErr;
1686#endif
1687}
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700U14API(short) U14GetString(short hand, char* pBuffer, WORD wMaxLen)
1701{
1702 short sErr = CheckHandle(hand);
1703 if (sErr != U14ERR_NOERROR)
1704 return sErr;
1705
1706#ifdef _IS_WINDOWS_
1707 if (wMaxLen>1)
1708 {
1709 BOOL bLineToGet;
1710 long lTimeOutTicks = U14WhenToTimeOut(hand);
1711 do
1712 bLineToGet = (BOOL)(U14LineCount(hand) != 0);
1713 while (!bLineToGet && !U14PassedTime(lTimeOutTicks));
1714
1715 if (!bLineToGet)
1716 {
1717 int i;
1718 for (i = 0; (i < 4) && (!bLineToGet); ++i)
1719 {
1720 Sleep(25);
1721 bLineToGet = (BOOL)(U14LineCount(hand) != 0);
1722 }
1723 }
1724
1725 if (bLineToGet)
1726 {
1727 if (asLastRetCode[hand] == U14ERR_NOERROR)
1728 {
1729 DWORD dwBytes = 0;
1730 *((WORD *)pBuffer) = wMaxLen;
1731#ifndef _WIN64
1732 if (!USE_NT_DIOC(hand))
1733 {
1734 char tstr[MAXSTRLEN+5];
1735 int iOK;
1736
1737 if (wMaxLen > MAXSTRLEN)
1738 wMaxLen = MAXSTRLEN;
1739
1740 *((WORD *)tstr) = wMaxLen;
1741
1742 iOK = DeviceIoControl(aHand1401[hand],(DWORD)U14_GETSTRING,
1743 NULL, 0, tstr, wMaxLen+sizeof(short),
1744 &dwBytes, NULL);
1745 if (iOK)
1746 {
1747 if (dwBytes >= 0)
1748 {
1749 strcpy(pBuffer, tstr);
1750 sErr = U14ERR_NOERROR;
1751 }
1752 else
1753 sErr = U14ERR_DRIVCOMMS;
1754 }
1755 else
1756 {
1757 sErr = (short)GetLastError();
1758 if (sErr > 0)
1759 sErr = (short)-sErr;
1760 }
1761 }
1762 else
1763#endif
1764 {
1765 HANDLE hMem = GlobalAlloc(GMEM_MOVEABLE,wMaxLen+sizeof(short));
1766 if (hMem)
1767 {
1768 char* pMem = (char*)GlobalLock(hMem);
1769 if (pMem)
1770 {
1771 int iOK = DeviceIoControl(aHand1401[hand],(DWORD)U14_GETSTRING,
1772 NULL, 0, pMem, wMaxLen+sizeof(short),
1773 &dwBytes, NULL);
1774 if (iOK)
1775 {
1776 if (dwBytes >= wMaxLen)
1777 {
1778 strcpy(pBuffer, pMem+sizeof(short));
1779 sErr = *((SHORT*)pMem);
1780 }
1781 else
1782 sErr = U14ERR_DRIVCOMMS;
1783 }
1784 else
1785 sErr = U14ERR_DRIVCOMMS;
1786
1787 GlobalUnlock(hMem);
1788 }
1789 else
1790 sErr = U14ERR_OUTOFMEMORY;
1791
1792 GlobalFree(hMem);
1793 }
1794 else
1795 sErr = U14ERR_OUTOFMEMORY;
1796 }
1797
1798 if (sErr == U14ERR_NOERROR)
1799 TranslateString(pBuffer);
1800 else
1801 U14ForceReset(hand);
1802
1803 }
1804 else
1805 sErr = asLastRetCode[hand];
1806 }
1807 else
1808 {
1809 sErr = U14ERR_TIMEOUT;
1810 U14ForceReset(hand);
1811 }
1812 }
1813 else
1814 sErr = U14ERR_BUFF_SMALL;
1815 return sErr;
1816#endif
1817#ifdef LINUX
1818 if (wMaxLen>1)
1819 {
1820 BOOL bLineToGet;
1821 long lTimeOutTicks = U14WhenToTimeOut(hand);
1822 do
1823 {
1824 bLineToGet = (BOOL)(U14LineCount(hand) != 0);
1825 if (!bLineToGet)
1826 sched_yield();
1827
1828 }
1829 while (!bLineToGet && !U14PassedTime(lTimeOutTicks));
1830
1831 if (bLineToGet)
1832 {
1833 sErr = CED_GetString(aHand1401[hand], pBuffer, wMaxLen-1);
1834 if (sErr >=0)
1835 {
1836 if (sErr >= wMaxLen)
1837 sErr = U14ERR_DRIVCOMMS;
1838 else
1839 {
1840 pBuffer[sErr] = 0;
1841 TranslateString(pBuffer);
1842 }
1843 }
1844
1845 if (sErr < U14ERR_NOERROR)
1846 U14ForceReset(hand);
1847 }
1848 else
1849 {
1850 sErr = U14ERR_TIMEOUT;
1851 U14ForceReset(hand);
1852 }
1853 }
1854 else
1855 sErr = U14ERR_BUFF_SMALL;
1856
1857 return sErr >= U14ERR_NOERROR ? U14ERR_NOERROR : sErr;
1858#endif
1859}
1860
1861
1862
1863
1864
1865U14API(short) U14GetChar(short hand, char* pcChar)
1866{
1867#ifdef _IS_WINDOWS_
1868 char sz[2];
1869 short sErr = U14GetString(hand, sz, 2);
1870 *pcChar = sz[0];
1871 if (sErr == U14ERR_NOERROR)
1872 {
1873 if (*pcChar == '\0')
1874 *pcChar = '\n';
1875 }
1876 return sErr;
1877#endif
1878#ifdef LINUX
1879 short sErr = CheckHandle(hand);
1880 if (sErr != U14ERR_NOERROR)
1881 return sErr;
1882 sErr = CED_GetChar(aHand1401[hand]);
1883 if (sErr >= 0)
1884 {
1885 *pcChar = (char)sErr;
1886 return U14ERR_NOERROR;
1887 }
1888 else
1889 return sErr;
1890#endif
1891}
1892
1893
1894
1895
1896
1897U14API(short) U14Stat1401(short hand)
1898{
1899 return ((short)(U14LineCount(hand) > 0));
1900}
1901
1902
1903
1904
1905
1906U14API(short) U14CharCount(short hand)
1907{
1908#ifdef _IS_WINDOWS_
1909 TCSBLOCK csBlock;
1910 short sErr = U14Status1401(hand, U14_STAT1401, &csBlock);
1911 if (sErr == U14ERR_NOERROR)
1912 sErr = csBlock.ints[0];
1913 return sErr;
1914#endif
1915#ifdef LINUX
1916 short sErr = CheckHandle(hand);
1917 return (sErr == U14ERR_NOERROR) ? CED_Stat1401(aHand1401[hand]) : sErr;
1918#endif
1919}
1920
1921
1922
1923
1924
1925U14API(short) U14LineCount(short hand)
1926{
1927#ifdef _IS_WINDOWS_
1928 TCSBLOCK csBlock;
1929 short sErr = U14Status1401(hand, U14_LINECOUNT, &csBlock);
1930 if (sErr == U14ERR_NOERROR)
1931 sErr = csBlock.ints[0];
1932 return sErr;
1933#endif
1934#ifdef LINUX
1935 short sErr = CheckHandle(hand);
1936 return (sErr == U14ERR_NOERROR) ? CED_LineCount(aHand1401[hand]) : sErr;
1937#endif
1938}
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949U14API(void) U14GetErrorString(short nErr, char* pStr, WORD wMax)
1950{
1951 char wstr[150];
1952
1953 switch (nErr)
1954 {
1955 case U14ERR_OFF:
1956 sprintf(wstr, "The 1401 is apparently switched off (code %d)", nErr);
1957 break;
1958
1959 case U14ERR_NC:
1960 sprintf(wstr, "The 1401 is not connected to the interface card (code %d)", nErr);
1961 break;
1962
1963 case U14ERR_ILL:
1964 sprintf(wstr, "The 1401 is not working correctly (code %d)", nErr);
1965 break;
1966
1967 case U14ERR_NOIF:
1968 sprintf(wstr, "The 1401 interface card was not detected (code %d)", nErr);
1969 break;
1970
1971 case U14ERR_TIME:
1972 sprintf(wstr, "The 1401 fails to become ready for use (code %d)", nErr);
1973 break;
1974
1975 case U14ERR_BADSW:
1976 sprintf(wstr, "The 1401 interface card jumpers are incorrect (code %d)", nErr);
1977 break;
1978
1979 case U14ERR_NOINT:
1980 sprintf(wstr, "The 1401 interrupt is not available for use (code %d)", nErr);
1981 break;
1982
1983 case U14ERR_INUSE:
1984 sprintf(wstr, "The 1401 is already in use by another program (code %d)", nErr);
1985 break;
1986
1987 case U14ERR_NODMA:
1988 sprintf(wstr, "The 1401 DMA channel is not available for use (code %d)", nErr);
1989 break;
1990
1991 case U14ERR_BADHAND:
1992 sprintf(wstr, "The application supplied an incorrect 1401 handle (code %d)", nErr);
1993 break;
1994
1995 case U14ERR_BAD1401NUM:
1996 sprintf(wstr, "The application used an incorrect 1401 number (code %d)", nErr);
1997 break;
1998
1999 case U14ERR_NO_SUCH_FN:
2000 sprintf(wstr, "The code passed to the 1401 driver is invalid (code %d)", nErr);
2001 break;
2002
2003 case U14ERR_NO_SUCH_SUBFN:
2004 sprintf(wstr, "The sub-code passed to the 1401 driver is invalid (code %d)", nErr);
2005 break;
2006
2007 case U14ERR_NOOUT:
2008 sprintf(wstr, "No room in buffer for characters for the 1401 (code %d)", nErr);
2009 break;
2010
2011 case U14ERR_NOIN:
2012 sprintf(wstr, "No characters from the 1401 are available (code %d)", nErr);
2013 break;
2014
2015 case U14ERR_STRLEN:
2016 sprintf(wstr, "A string sent to or read from the 1401 was too long (code %d)", nErr);
2017 break;
2018
2019 case U14ERR_LOCKFAIL:
2020 sprintf(wstr, "Failed to lock host memory for data transfer (code %d)", nErr);
2021 break;
2022
2023 case U14ERR_UNLOCKFAIL:
2024 sprintf(wstr, "Failed to unlock host memory after data transfer (code %d)", nErr);
2025 break;
2026
2027 case U14ERR_ALREADYSET:
2028 sprintf(wstr, "The transfer area used is already set up (code %d)", nErr);
2029 break;
2030
2031 case U14ERR_NOTSET:
2032 sprintf(wstr, "The transfer area used has not been set up (code %d)", nErr);
2033 break;
2034
2035 case U14ERR_BADAREA:
2036 sprintf(wstr, "The transfer area number is incorrect (code %d)", nErr);
2037 break;
2038
2039 case U14ERR_NOFILE:
2040 sprintf(wstr, "The command file %s could not be opened (code %d)", szLastName, nErr);
2041 break;
2042
2043 case U14ERR_READERR:
2044 sprintf(wstr, "The command file %s could not be read (code %d)", szLastName, nErr);
2045 break;
2046
2047 case U14ERR_UNKNOWN:
2048 sprintf(wstr, "The %s command resource could not be found (code %d)", szLastName, nErr);
2049 break;
2050
2051 case U14ERR_HOSTSPACE:
2052 sprintf(wstr, "Unable to allocate memory for loading command %s (code %d)", szLastName, nErr);
2053 break;
2054
2055 case U14ERR_LOCKERR:
2056 sprintf(wstr, "Unable to lock memory for loading command %s (code %d)", szLastName, nErr);
2057 break;
2058
2059 case U14ERR_CLOADERR:
2060 sprintf(wstr, "Error in loading command %s, bad command format (code %d)", szLastName, nErr);
2061 break;
2062
2063 case U14ERR_TOXXXERR:
2064 sprintf(wstr, "Error detected after data transfer to or from the 1401 (code %d)", nErr);
2065 break;
2066
2067 case U14ERR_NO386ENH:
2068 sprintf(wstr, "Windows 3.1 is not running in 386 enhanced mode (code %d)", nErr);
2069 break;
2070
2071 case U14ERR_NO1401DRIV:
2072 sprintf(wstr, "The 1401 device driver cannot be found (code %d)\nUSB: check plugged in and powered\nOther: not installed?", nErr);
2073 break;
2074
2075 case U14ERR_DRIVTOOOLD:
2076 sprintf(wstr, "The 1401 device driver is too old for use (code %d)", nErr);
2077 break;
2078
2079 case U14ERR_TIMEOUT:
2080 sprintf(wstr, "Character transmissions to the 1401 timed-out (code %d)", nErr);
2081 break;
2082
2083 case U14ERR_BUFF_SMALL:
2084 sprintf(wstr, "Buffer for text from the 1401 was too small (code %d)", nErr);
2085 break;
2086
2087 case U14ERR_CBALREADY:
2088 sprintf(wstr, "1401 monitor callback already set up (code %d)", nErr);
2089 break;
2090
2091 case U14ERR_BADDEREG:
2092 sprintf(wstr, "1401 monitor callback deregister invalid (code %d)", nErr);
2093 break;
2094
2095 case U14ERR_DRIVCOMMS:
2096 sprintf(wstr, "1401 device driver communications failed (code %d)", nErr);
2097 break;
2098
2099 case U14ERR_OUTOFMEMORY:
2100 sprintf(wstr, "Failed to allocate or lock memory for text from the 1401 (code %d)", nErr);
2101 break;
2102
2103 default:
2104 sprintf(wstr, "1401 error code %d returned; this code is unknown", nErr);
2105 break;
2106
2107 }
2108 if ((WORD)strlen(wstr) >= wMax-1)
2109 wstr[wMax-1] = 0;
2110 strcpy(pStr, wstr);
2111}
2112
2113
2114
2115
2116
2117U14API(short) U14GetTransfer(short hand, TGET_TX_BLOCK *pTransBlock)
2118{
2119 short sErr = CheckHandle(hand);
2120#ifdef _IS_WINDOWS_
2121 if (sErr == U14ERR_NOERROR)
2122 {
2123 DWORD dwBytes = 0;
2124 BOOL bOK = DeviceIoControl(aHand1401[hand], (DWORD)U14_GETTRANSFER, NULL, 0, pTransBlock,
2125 sizeof(TGET_TX_BLOCK), &dwBytes, NULL);
2126
2127 if (bOK && (dwBytes >= sizeof(TGET_TX_BLOCK)))
2128 sErr = U14ERR_NOERROR;
2129 else
2130 sErr = U14ERR_DRIVCOMMS;
2131 }
2132 return sErr;
2133#endif
2134#ifdef LINUX
2135 return (sErr == U14ERR_NOERROR) ? CED_GetTransfer(aHand1401[hand], pTransBlock) : sErr;
2136#endif
2137}
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148U14API(short) U14WorkingSet(DWORD dwMinKb, DWORD dwMaxKb)
2149{
2150#ifdef _IS_WINDOWS_
2151 short sRetVal = 0;
2152 HANDLE hProcess;
2153 DWORD dwVer = GetVersion();
2154 if (dwVer & 0x80000000)
2155 return 0;
2156
2157
2158 hProcess = OpenProcess(STANDARD_RIGHTS_REQUIRED |
2159 PROCESS_QUERY_INFORMATION |
2160 PROCESS_SET_QUOTA,
2161 FALSE, _getpid());
2162 if (hProcess)
2163 {
2164 SIZE_T dwMinSize,dwMaxSize;
2165 if (GetProcessWorkingSetSize(hProcess, &dwMinSize, &dwMaxSize))
2166 {
2167 DWORD dwMin = dwMinKb << 10;
2168 DWORD dwMax = dwMaxKb << 10;
2169
2170
2171 if (dwMin > dwMinSize)
2172 dwMinSize = dwMin;
2173
2174 if (dwMax > dwMaxSize)
2175 dwMaxSize = dwMax;
2176
2177 if (!SetProcessWorkingSetSize(hProcess, dwMinSize, dwMaxSize))
2178 sRetVal = 3;
2179 }
2180 else
2181 sRetVal = 2;
2182
2183 CloseHandle(hProcess);
2184 }
2185 else
2186 sRetVal = 1;
2187
2188 return sRetVal;
2189#endif
2190#ifdef LINUX
2191 if (dwMinKb | dwMaxKb)
2192 {
2193
2194 }
2195 return U14ERR_NOERROR;
2196#endif
2197}
2198
2199
2200
2201
2202
2203U14API(short) U14UnSetTransfer(short hand, WORD wArea)
2204{
2205 short sErr = CheckHandle(hand);
2206#ifdef _IS_WINDOWS_
2207 if (sErr == U14ERR_NOERROR)
2208 {
2209 TCSBLOCK csBlock;
2210 csBlock.ints[0] = (short)wArea;
2211 sErr = U14Control1401(hand, U14_UNSETTRANSFER, &csBlock);
2212
2213 VirtualUnlock(apAreas[hand][wArea], auAreas[hand][wArea]);
2214 apAreas[hand][wArea] = NULL;
2215 auAreas[hand][wArea] = 0;
2216 }
2217 return sErr;
2218#endif
2219#ifdef LINUX
2220 return (sErr == U14ERR_NOERROR) ? CED_UnsetTransfer(aHand1401[hand], wArea) : sErr;
2221#endif
2222}
2223
2224
2225
2226
2227
2228
2229
2230
2231U14API(short) U14SetTransArea(short hand, WORD wArea, void *pvBuff,
2232 DWORD dwLength, short eSz)
2233{
2234 TRANSFERDESC td;
2235 short sErr = CheckHandle(hand);
2236 if (sErr != U14ERR_NOERROR)
2237 return sErr;
2238 if (wArea >= MAX_TRANSAREAS)
2239 return U14ERR_BADAREA;
2240
2241#ifdef _IS_WINDOWS_
2242 assert(apAreas[hand][wArea] == NULL);
2243 assert(auAreas[hand][wArea] == 0);
2244
2245 apAreas[hand][wArea] = pvBuff;
2246 auAreas[hand][wArea] = dwLength;
2247
2248 if (!VirtualLock(pvBuff, dwLength))
2249 {
2250 apAreas[hand][wArea] = NULL;
2251 auAreas[hand][wArea] = 0;
2252 return U14ERR_LOCKERR;
2253 }
2254#ifndef _WIN64
2255 if (!USE_NT_DIOC(hand))
2256 {
2257 DWORD dwBytes;
2258 VXTRANSFERDESC vxDesc;
2259 vxDesc.wArea = wArea;
2260 vxDesc.dwLength = dwLength;
2261
2262
2263 if ((wArea != 0) && (U14DriverVersion(hand) < 0x00010002L))
2264 sErr = U14ERR_DRIVTOOOLD;
2265 else
2266 {
2267 vxDesc.dwAddrOfs = (DWORD)pvBuff;
2268 vxDesc.wAddrSel = 0;
2269
2270 if (DeviceIoControl(aHand1401[hand], (DWORD)U14_SETTRANSFER,
2271 pvBuff,dwLength,
2272 &vxDesc,sizeof(VXTRANSFERDESC),
2273 &dwBytes,NULL))
2274 {
2275 if (dwBytes >= sizeof(VXTRANSFERDESC))
2276 sErr = U14ERR_NOERROR;
2277 else
2278 sErr = U14ERR_DRIVCOMMS;
2279 }
2280 else
2281 sErr = (short)GetLastError();
2282 }
2283 }
2284 else
2285#endif
2286 {
2287 PARAMBLK rWork;
2288 DWORD dwBytes;
2289 td.wArea = wArea;
2290 td.lpvBuff = pvBuff;
2291 td.dwLength = dwLength;
2292 td.eSize = 0;
2293
2294 if (DeviceIoControl(aHand1401[hand],(DWORD)U14_SETTRANSFER,
2295 &td,sizeof(TRANSFERDESC),
2296 &rWork,sizeof(PARAMBLK),&dwBytes,NULL))
2297 {
2298 if (dwBytes >= sizeof(PARAMBLK))
2299 sErr = rWork.sState;
2300 else
2301 sErr = U14ERR_DRIVCOMMS;
2302 }
2303 else
2304 sErr = U14ERR_DRIVCOMMS;
2305 }
2306
2307 if (sErr != U14ERR_NOERROR)
2308 {
2309 if (sErr != U14ERR_LOCKERR)
2310 VirtualUnlock(pvBuff, dwLength);
2311 apAreas[hand][wArea] = NULL;
2312 auAreas[hand][wArea] = 0;
2313 }
2314
2315 return sErr;
2316#endif
2317#ifdef LINUX
2318
2319
2320 td.lpvBuff = (long long)((unsigned long)pvBuff);
2321 td.wAreaNum = wArea;
2322 td.dwLength = dwLength;
2323 td.eSize = eSz;
2324 return CED_SetTransfer(aHand1401[hand], &td);
2325#endif
2326}
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347U14API(short) U14SetTransferEvent(short hand, WORD wArea, BOOL bEvent,
2348 BOOL bToHost, DWORD dwStart, DWORD dwLength)
2349{
2350#ifdef _IS_WINDOWS_
2351 TCSBLOCK csBlock;
2352 short sErr = U14TransferFlags(hand);
2353 if (sErr >= U14ERR_NOERROR)
2354 {
2355 bEvent = bEvent && ((sErr & U14TF_NOTIFY) != 0);
2356 if (wArea >= MAX_TRANSAREAS)
2357 return U14ERR_BADAREA;
2358
2359
2360
2361 if ((bEvent != 0) != (aXferEvent[hand] != 0))
2362 {
2363 if (bEvent)
2364 aXferEvent[hand] = CreateEvent(NULL, FALSE, FALSE, NULL);
2365 else
2366 {
2367 CloseHandle(aXferEvent[hand]);
2368 aXferEvent[hand] = NULL;
2369 }
2370 }
2371
2372
2373
2374
2375#ifdef _WIN64
2376 csBlock.longs[0] = wArea;
2377 if (bToHost != 0)
2378 csBlock.longs[0] |= 0x10000;
2379 *((HANDLE*)&csBlock.longs[1]) = aXferEvent[hand];
2380 csBlock.longs[3] = dwStart;
2381 csBlock.longs[4] = dwLength;
2382#else
2383 csBlock.longs[0] = wArea;
2384 csBlock.longs[1] = (long)aXferEvent[hand];
2385 csBlock.longs[2] = bToHost;
2386 csBlock.longs[3] = dwStart;
2387 csBlock.longs[4] = dwLength;
2388#endif
2389 sErr = U14Control1401(hand, U14_SETTRANSEVENT, &csBlock);
2390 if (sErr == U14ERR_NOERROR)
2391 sErr = (short)(aXferEvent[hand] != NULL);
2392 }
2393
2394 return sErr;
2395#endif
2396#ifdef LINUX
2397 TRANSFEREVENT te;
2398 short sErr = CheckHandle(hand);
2399 if (sErr != U14ERR_NOERROR)
2400 return sErr;
2401
2402 if (wArea >= MAX_TRANSAREAS)
2403 return U14ERR_BADAREA;
2404
2405 te.wAreaNum = wArea;
2406 te.wFlags = bToHost ? 1 : 0;
2407 te.dwStart = dwStart;
2408 te.dwLength = dwLength;
2409 te.iSetEvent = bEvent;
2410 return CED_SetEvent(aHand1401[hand], &te);
2411#endif
2412}
2413
2414
2415
2416
2417
2418
2419U14API(int) U14TestTransferEvent(short hand, WORD wArea)
2420{
2421#ifdef _IS_WINDOWS_
2422 int iErr = CheckHandle(hand);
2423 if (iErr == U14ERR_NOERROR)
2424 {
2425 if (aXferEvent[hand])
2426 iErr = WaitForSingleObject(aXferEvent[hand], 0) == WAIT_OBJECT_0;
2427 }
2428 return iErr;
2429#endif
2430#ifdef LINUX
2431 short sErr = CheckHandle(hand);
2432 return (sErr == U14ERR_NOERROR) ? CED_TestEvent(aHand1401[hand], wArea) : sErr;
2433#endif
2434}
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444U14API(int) U14WaitTransferEvent(short hand, WORD wArea, int msTimeOut)
2445{
2446#ifdef _IS_WINDOWS_
2447 int iErr = CheckHandle(hand);
2448 if (iErr == U14ERR_NOERROR)
2449 {
2450 if (aXferEvent[hand])
2451 {
2452 if (msTimeOut == 0)
2453 msTimeOut = INFINITE;
2454 iErr = WaitForSingleObject(aXferEvent[hand], msTimeOut) != WAIT_OBJECT_0;
2455 }
2456 else
2457 iErr = TRUE;
2458 }
2459 return iErr;
2460#endif
2461#ifdef LINUX
2462 short sErr = CheckHandle(hand);
2463 return (sErr == U14ERR_NOERROR) ? CED_WaitEvent(aHand1401[hand], wArea, msTimeOut) : sErr;
2464#endif
2465}
2466
2467
2468
2469
2470
2471
2472
2473
2474U14API(short) U14SetCircular(short hand, WORD wArea, BOOL bToHost,
2475 void *pvBuff, DWORD dwLength)
2476{
2477 short sErr = CheckHandle(hand);
2478 if (sErr != U14ERR_NOERROR)
2479 return sErr;
2480
2481 if (wArea >= MAX_TRANSAREAS)
2482 return U14ERR_BADAREA;
2483
2484 if (!bToHost)
2485 return U14ERR_BADAREA;
2486#ifdef _IS_WINDOWS_
2487 assert(apAreas[hand][wArea] == NULL);
2488 assert(auAreas[hand][wArea] == 0);
2489
2490 apAreas[hand][wArea] = pvBuff;
2491 auAreas[hand][wArea] = dwLength;
2492
2493 if (!VirtualLock(pvBuff, dwLength))
2494 sErr = U14ERR_LOCKERR;
2495 else
2496 {
2497 PARAMBLK rWork;
2498 DWORD dwBytes;
2499 TRANSFERDESC txDesc;
2500 txDesc.wArea = wArea;
2501 txDesc.lpvBuff = pvBuff;
2502 txDesc.dwLength = dwLength;
2503 txDesc.eSize = (short)bToHost;
2504
2505 if (DeviceIoControl(aHand1401[hand],(DWORD)U14_SETCIRCULAR,
2506 &txDesc, sizeof(TRANSFERDESC),
2507 &rWork, sizeof(PARAMBLK),&dwBytes,NULL))
2508 {
2509 if (dwBytes >= sizeof(PARAMBLK))
2510 sErr = rWork.sState;
2511 else
2512 sErr = U14ERR_DRIVCOMMS;
2513 }
2514 else
2515 sErr = U14ERR_DRIVCOMMS;
2516 }
2517
2518 if (sErr != U14ERR_NOERROR)
2519 {
2520 if (sErr != U14ERR_LOCKERR)
2521 VirtualUnlock(pvBuff, dwLength);
2522 apAreas[hand][wArea] = NULL;
2523 auAreas[hand][wArea] = 0;
2524 }
2525
2526 return sErr;
2527#endif
2528#ifdef LINUX
2529 else
2530 {
2531 TRANSFERDESC td;
2532 td.lpvBuff = (long long)((unsigned long)pvBuff);
2533 td.wAreaNum = wArea;
2534 td.dwLength = dwLength;
2535 td.eSize = (short)bToHost;
2536 return CED_SetCircular(aHand1401[hand], &td);
2537 }
2538#endif
2539}
2540
2541
2542
2543
2544
2545U14API(int) U14GetCircBlk(short hand, WORD wArea, DWORD *pdwOffs)
2546{
2547 int lErr = CheckHandle(hand);
2548 if (lErr != U14ERR_NOERROR)
2549 return lErr;
2550
2551 if (wArea >= MAX_TRANSAREAS)
2552 return U14ERR_BADAREA;
2553 else
2554 {
2555#ifdef _IS_WINDOWS_
2556 PARAMBLK rWork;
2557 TCSBLOCK csBlock;
2558 DWORD dwBytes;
2559 csBlock.longs[0] = wArea;
2560 rWork.sState = U14ERR_DRIVCOMMS;
2561 if (DeviceIoControl(aHand1401[hand], (DWORD)U14_GETCIRCBLK, &csBlock, sizeof(TCSBLOCK), &rWork, sizeof(PARAMBLK), &dwBytes, NULL) &&
2562 (dwBytes >= sizeof(PARAMBLK)))
2563 lErr = rWork.sState;
2564 else
2565 lErr = U14ERR_DRIVCOMMS;
2566
2567 if (lErr == U14ERR_NOERROR)
2568 {
2569 lErr = rWork.csBlock.longs[1];
2570 *pdwOffs = rWork.csBlock.longs[0];
2571 }
2572#endif
2573#ifdef LINUX
2574 TCIRCBLOCK cb;
2575 cb.nArea = wArea;
2576 cb.dwOffset = 0;
2577 cb.dwSize = 0;
2578 lErr = CED_GetCircBlock(aHand1401[hand], &cb);
2579 if (lErr == U14ERR_NOERROR)
2580 {
2581 lErr = cb.dwSize;
2582 *pdwOffs = cb.dwOffset;
2583 }
2584#endif
2585 }
2586 return lErr;
2587}
2588
2589
2590
2591
2592
2593
2594U14API(int) U14FreeCircBlk(short hand, WORD wArea, DWORD dwOffs, DWORD dwSize,
2595 DWORD *pdwOffs)
2596{
2597 int lErr = CheckHandle(hand);
2598 if (lErr != U14ERR_NOERROR)
2599 return lErr;
2600
2601 if (wArea < MAX_TRANSAREAS)
2602 {
2603#ifdef _IS_WINDOWS_
2604 PARAMBLK rWork;
2605 TCSBLOCK csBlock;
2606 DWORD dwBytes;
2607 csBlock.longs[0] = wArea;
2608 csBlock.longs[1] = dwOffs;
2609 csBlock.longs[2] = dwSize;
2610 rWork.sState = U14ERR_DRIVCOMMS;
2611 if (DeviceIoControl(aHand1401[hand], (DWORD)U14_FREECIRCBLK, &csBlock, sizeof(TCSBLOCK),
2612 &rWork, sizeof(PARAMBLK), &dwBytes, NULL) &&
2613 (dwBytes >= sizeof(PARAMBLK)))
2614 lErr = rWork.sState;
2615 else
2616 lErr = U14ERR_DRIVCOMMS;
2617 if (lErr == U14ERR_NOERROR)
2618 {
2619 lErr = rWork.csBlock.longs[1];
2620 *pdwOffs = rWork.csBlock.longs[0];
2621 }
2622#endif
2623#ifdef LINUX
2624 TCIRCBLOCK cb;
2625 cb.nArea = wArea;
2626 cb.dwOffset = dwOffs;
2627 cb.dwSize = dwSize;
2628
2629 lErr = CED_FreeCircBlock(aHand1401[hand], &cb);
2630 if (lErr == U14ERR_NOERROR)
2631 {
2632 lErr = cb.dwSize;
2633 *pdwOffs = cb.dwOffset;
2634 }
2635#endif
2636 }
2637 else
2638 lErr = U14ERR_BADAREA;
2639
2640 return lErr;
2641}
2642
2643
2644
2645
2646
2647
2648
2649static short Transfer(short hand, BOOL bTo1401, char* pData,
2650 DWORD dwSize, DWORD dw1401, short eSz)
2651{
2652 char strcopy[MAXSTRLEN+1];
2653 short sResult = U14SetTransArea(hand, 0, (void *)pData, dwSize, eSz);
2654 if (sResult == U14ERR_NOERROR)
2655 {
2656 sprintf(strcopy,
2657 "TO%s,$%X,$%X,0;", bTo1401 ? "1401" : "HOST", dw1401, dwSize);
2658
2659 U14SendString(hand, strcopy);
2660
2661 sResult = U14CheckErr(hand);
2662 if (sResult > 0)
2663 sResult = U14ERR_TOXXXERR;
2664
2665 U14UnSetTransfer(hand, 0);
2666 }
2667 return sResult;
2668}
2669
2670
2671
2672
2673U14API(short) U14ToHost(short hand, char* pAddrHost, DWORD dwSize,
2674 DWORD dw1401, short eSz)
2675{
2676 short sErr = CheckHandle(hand);
2677 if ((sErr == U14ERR_NOERROR) && dwSize)
2678 sErr = Transfer(hand, TOHOST, pAddrHost, dwSize, dw1401, eSz);
2679 return sErr;
2680}
2681
2682
2683
2684
2685U14API(short) U14To1401(short hand, const char* pAddrHost,DWORD dwSize,
2686 DWORD dw1401, short eSz)
2687{
2688 short sErr = CheckHandle(hand);
2689 if ((sErr == U14ERR_NOERROR) && dwSize)
2690 sErr = Transfer(hand, TO1401, (char*)pAddrHost, dwSize, dw1401, eSz);
2691 return sErr;
2692}
2693
2694
2695
2696
2697#ifdef _IS_WINDOWS_
2698#define file_exist(name) (_access(name, 0) != -1)
2699#define file_open(name) _lopen(name, OF_READ)
2700#define file_close(h) _lclose(h)
2701#define file_seek(h, pos) _llseek(h, pos, FILE_BEGIN)
2702#define file_read(h, buffer, size) (_lread(h, buffer, size) == size)
2703#endif
2704#ifdef LINUX
2705#define file_exist(name) (access(name, F_OK) != -1)
2706#define file_open(name) open(name, O_RDONLY)
2707#define file_close(h) close(h)
2708#define file_seek(h, pos) lseek(h, pos, SEEK_SET)
2709#define file_read(h, buffer, size) (read(h, buffer, size) == (ssize_t)size)
2710static DWORD GetModuleFileName(void* dummy, char* buffer, int max)
2711{
2712
2713 char szProcPath[32];
2714 sprintf(szProcPath, "/proc/%d/exe", getpid());
2715 if (readlink(szProcPath, buffer, max) != -1)
2716 {
2717 dirname (buffer);
2718 strcat (buffer, "/");
2719 return strlen(buffer);
2720 }
2721 return 0;
2722}
2723#endif
2724
2725U14API(short) U14LdCmd(short hand, const char* command)
2726{
2727 char strcopy[MAXSTRLEN+1];
2728 BOOL bGotIt = FALSE;
2729 int iFHandle;
2730#define FNSZ 260
2731 char filnam[FNSZ];
2732 char szCmd[25];
2733
2734 short sErr = CheckHandle(hand);
2735 if (sErr != U14ERR_NOERROR)
2736 return sErr;
2737
2738 if (strchr(command, '.') != NULL)
2739 {
2740 if (file_exist(command))
2741 {
2742 strcpy(filnam, command);
2743 bGotIt = TRUE;
2744 }
2745 else
2746 {
2747 char* pStr = strrchr(command, PATHSEP);
2748 if (pStr != NULL)
2749 {
2750 pStr++;
2751 strcpy(szCmd, pStr);
2752 }
2753 else
2754 strcpy(szCmd, command);
2755 }
2756 }
2757 else
2758 {
2759 char szExt[8];
2760 strcpy(szCmd, command);
2761 ExtForType(asType1401[hand], szExt);
2762 strcat(szCmd, szExt);
2763 }
2764
2765
2766
2767 if (!bGotIt)
2768 {
2769 DWORD dwLen = GetModuleFileName(NULL, filnam, FNSZ);
2770 if (dwLen > 0)
2771 {
2772 char* pStr = strrchr(filnam, PATHSEP);
2773 if (pStr != NULL)
2774 {
2775 *(++pStr) = 0;
2776 if (strlen(filnam) < FNSZ-6)
2777 {
2778 strcat(filnam, "1401" PATHSEPSTR);
2779 strcat(filnam,szCmd);
2780 bGotIt = (BOOL)file_exist(filnam);
2781 }
2782 }
2783 }
2784 }
2785
2786
2787
2788 if (!bGotIt)
2789 {
2790 char* pStr = getenv("1401DIR");
2791 if (pStr != NULL)
2792 {
2793 strcpy(filnam, pStr);
2794 if (filnam[strlen(filnam)-1] != PATHSEP)
2795 strcat(filnam, PATHSEPSTR);
2796 strcat(filnam, szCmd);
2797 bGotIt = (BOOL)file_exist(filnam);
2798 }
2799 }
2800
2801
2802 if (!bGotIt)
2803 {
2804 strcpy(filnam, DEFCMDPATH);
2805 strcat(filnam, szCmd);
2806 bGotIt = file_exist(filnam);
2807 }
2808
2809 iFHandle = file_open(filnam);
2810 if (iFHandle == -1)
2811 sErr = U14ERR_NOFILE;
2812 else
2813 {
2814 CMDHEAD rCmdHead;
2815 if (file_read(iFHandle, &rCmdHead, sizeof(CMDHEAD)))
2816 {
2817 size_t nComSize = rCmdHead.wCmdSize;
2818 char* pMem = malloc(nComSize);
2819 if (pMem != NULL)
2820 {
2821 file_seek(iFHandle, sizeof(CMDHEAD));
2822 if (file_read(iFHandle, pMem, (UINT)nComSize))
2823 {
2824 sErr = U14SetTransArea(hand, 0, (void *)pMem, (DWORD)nComSize, ESZBYTES);
2825 if (sErr == U14ERR_NOERROR)
2826 {
2827 sprintf(strcopy, "CLOAD,0,$%X;", (int)nComSize);
2828 sErr = U14SendString(hand, strcopy);
2829 if (sErr == U14ERR_NOERROR)
2830 {
2831 sErr = U14CheckErr(hand);
2832 if (sErr > 0)
2833 sErr = U14ERR_CLOADERR;
2834 }
2835 U14UnSetTransfer(hand, 0);
2836 }
2837 }
2838 else
2839 sErr = U14ERR_READERR;
2840 free(pMem);
2841 }
2842 else
2843 sErr = U14ERR_HOSTSPACE;
2844 }
2845 else
2846 sErr = U14ERR_READERR;
2847
2848 file_close(iFHandle);
2849 }
2850
2851 return sErr;
2852}
2853
2854
2855
2856
2857
2858
2859
2860
2861U14API(DWORD) U14Ld(short hand, const char* vl, const char* str)
2862{
2863 DWORD dwIndex = 0;
2864 long lErr = U14ERR_NOERROR;
2865 char strcopy[MAXSTRLEN+1];
2866 char szFExt[8];
2867 short sErr = CheckHandle(hand);
2868 if (sErr != U14ERR_NOERROR)
2869 return sErr;
2870
2871 ExtForType(asType1401[hand], szFExt);
2872 strcpy(strcopy, str);
2873
2874
2875 if (*str)
2876 {
2877 BOOL bDone = FALSE;
2878 int iLoop1 = 0;
2879 int iLoop2 = 0;
2880 do
2881 {
2882 char filnam[MAXSTRLEN+1];
2883 char szFName[MAXSTRLEN+1];
2884
2885 if (!strcopy[iLoop1])
2886 bDone = TRUE;
2887
2888 if (bDone || (strcopy[iLoop1] == ','))
2889 {
2890 U14LONG er[5];
2891 ++dwIndex;
2892 szFName[iLoop2]=(char)0;
2893
2894 strncpy(szLastName, szFName, sizeof(szLastName));
2895 szLastName[sizeof(szLastName)-1] = 0;
2896 strncat(szLastName, szFExt, sizeof(szLastName));
2897 szLastName[sizeof(szLastName)-1] = 0;
2898
2899 U14SendString(hand, szFName);
2900 U14SendString(hand, ";ERR;");
2901
2902 lErr = U14LongsFrom1401(hand, er, 5);
2903 if (lErr > 0)
2904 {
2905 lErr = U14ERR_NOERROR;
2906 if (er[0] == 255)
2907 {
2908 if (vl && *vl)
2909 {
2910 strcpy(filnam, vl);
2911 if (strchr("\\/:", filnam[strlen(filnam)-1]) == NULL)
2912 strcat(filnam, PATHSEPSTR);
2913 strcat(filnam, szFName);
2914 strcat(filnam, szFExt);
2915 }
2916 else
2917 strcpy(filnam, szFName);
2918
2919 lErr = U14LdCmd(hand, filnam);
2920 if (lErr != U14ERR_NOERROR)
2921 bDone = TRUE;
2922 }
2923 }
2924 else
2925 bDone = TRUE;
2926
2927 iLoop2 = 0;
2928 ++iLoop1;
2929 }
2930 else
2931 szFName[iLoop2++] = strcopy[iLoop1++];
2932 }
2933 while (!bDone);
2934 }
2935
2936 if (lErr == U14ERR_NOERROR)
2937 {
2938 szLastName[0] = 0;
2939 return lErr;
2940 }
2941 else
2942 return ((dwIndex<<16) | ((DWORD)lErr & 0x0000FFFF));
2943}
2944
2945
2946U14API(int) U14InitLib(void)
2947{
2948 int iRetVal = U14LIB_VERSION;
2949 if (iAttached == 0)
2950 {
2951 int i;
2952#ifdef _IS_WINDOWS_
2953 int j;
2954 DWORD dwVersion = GetVersion();
2955 bWindows9x = FALSE;
2956
2957 if (dwVersion & 0x80000000)
2958 {
2959 if ((LOBYTE(LOWORD(dwVersion)) < 4) &&
2960 (HIBYTE(LOWORD(dwVersion)) < 95))
2961 iRetVal = 0;
2962 else
2963 bWindows9x = TRUE;
2964 }
2965#endif
2966
2967 for (i = 0; i < MAX1401; i++)
2968 {
2969 aHand1401[i] = INVALID_HANDLE_VALUE;
2970 asType1401[i] = U14TYPEUNKNOWN;
2971 alTimeOutPeriod[i] = 3000;
2972#ifdef _IS_WINDOWS_
2973#ifndef _WIN64
2974 abUseNTDIOC[i] = (BOOL)!bWindows9x;
2975#endif
2976 aXferEvent[i] = NULL;
2977 for (j = 0; j < MAX_TRANSAREAS; j++)
2978 {
2979 apAreas[i][j] = NULL;
2980 auAreas[i][j] = 0;
2981 }
2982#endif
2983 }
2984 }
2985 return iRetVal;
2986}
2987
2988
2989
2990
2991
2992
2993#ifdef _IS_WINDOWS_
2994#ifndef U14_NOT_DLL
2995
2996
2997
2998
2999
3000
3001INT APIENTRY DllMain(HANDLE hInst, DWORD ul_reason_being_called, LPVOID lpReserved)
3002{
3003 int iRetVal = 1;
3004
3005 switch (ul_reason_being_called)
3006 {
3007 case DLL_PROCESS_ATTACH:
3008 iRetVal = U14InitLib() > 0;
3009 ++iAttached;
3010 break;
3011
3012 case DLL_PROCESS_DETACH:
3013 if (--iAttached == 0)
3014 U14CloseAll();
3015 break;
3016 }
3017 return iRetVal;
3018
3019 UNREFERENCED_PARAMETER(lpReserved);
3020}
3021#endif
3022#endif
3023#ifdef LINUX
3024void __attribute__((constructor)) use1401_load(void)
3025{
3026 U14InitLib();
3027 ++iAttached;
3028}
3029
3030void __attribute__((destructor)) use1401_unload(void)
3031{
3032 if (--iAttached == 0)
3033 U14CloseAll();
3034}
3035#endif
3036