/* * scan.c - Phase 1 inventory demo: scan UPC barcodes and display them. * * Opens the barcode serial channel (TTY:D) and its own console/keyboard * channel (CON:), then waits on both at once: a completed scan is validated * as a UPC-A and printed; pressing Esc quits. * * Asynchronous two-channel wait (PLIB pattern): each request is started with * p_ioc, which sets a status word to E_FILE_PENDING until the request * completes. p_iowait blocks until some request finishes; we then check each * status word, cancel the other outstanding request, and loop. Every started * request is matched by exactly one completion (real or cancelled) so the I/O * semaphore stays balanced. See "Asynchronous I/O" in the PLIB Reference. */ #include #include "bcode.h" #include "upc.h" #define KEY_ESC 27 /* * If a request on chan is still pending, cancel it and reap the resulting * completion, so the started p_ioc is balanced by a wait. */ LOCAL_C VOID cancelPending(VOID *chan, WORD *pStat) { if (*pStat == E_FILE_PENDING) { p_iow(chan, P_FCANCEL); p_waitstat(pStat); } } GLDEF_C INT main(VOID) { VOID *bchan; /* barcode serial channel */ VOID *kchan; /* keyboard console channel */ WORD bStat, kStat; /* async status words */ UBYTE bRaw[BCODE_MAXLEN]; /* raw bytes from one serial read */ UBYTE kRaw[1]; /* one keystroke */ TEXT line[BCODE_MAXLEN]; /* barcode assembled across reads */ INT lineLen = 0; UWORD bLen, kLen; INT err; INT quit = 0; if ((err = bcodeOpen(&bchan)) < 0) { p_printf("Cannot open barcode port TTY:D (err %d)\n", err); return 1; } if ((err = p_open(&kchan, "CON:", (UINT)-1)) < 0) { p_printf("Cannot open console (err %d)\n", err); bcodeClose(bchan); return 1; } p_printf("Inventory scan demo\n"); p_printf("Scan a UPC, or press Esc to quit.\n\n"); while (quit == 0) { /* Start one asynchronous read on each channel. */ bLen = sizeof(bRaw); p_ioc(bchan, P_FREAD, &bStat, bRaw, &bLen); kLen = sizeof(kRaw); p_ioc(kchan, P_FREAD, &kStat, kRaw, &kLen); p_iowait(); /* Keypress? Cancel the scan read and check for Esc. */ if (kStat != E_FILE_PENDING) { cancelPending(bchan, &bStat); if (kStat >= 0 && kRaw[0] == KEY_ESC) quit = 1; continue; } /* Scanner delivered bytes. Cancel the keypress read and assemble. */ if (bStat != E_FILE_PENDING) { cancelPending(kchan, &kStat); if (bStat >= 0 && bLen > 0) { if (bcodeAssemble(bRaw, (INT)bLen, line, &lineLen, BCODE_MAXLEN)) { if (upcIsValid(line)) p_printf("OK %s\n", line); else p_printf("BAD %s (not a valid UPC-A)\n", line); } } } } p_printf("\nDone.\n"); p_close(kchan); bcodeClose(bchan); return 0; }