Fixed warning about variable used unititalised
[AROS.git] / rom / usb / classes / hid / hid.class.c
blob7e1da6e208ad1795d03c496786320596e69a5cab
1 /*
2 *----------------------------------------------------------------------------
3 * hid class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
6 */
8 #include "debug.h"
10 #include "numtostr.h"
11 #include "hid.class.h"
13 #include <proto/datatypes.h>
15 static LONG _rand(struct NepHidBase *nh)
17 nh->nh_Seed = nh->nh_Seed * 1103515245 + 12345;
19 return nh->nh_Seed;
22 /* /// "Lib Stuff" */
23 const STRPTR GM_UNIQUENAME(libname) = MOD_NAME_STRING;
25 //#define LowLevelBase nh->nh_LowLevelBase
27 static int GM_UNIQUENAME(libInit)(LIBBASETYPEPTR nh)
29 struct NepClassHid *nch;
30 struct NepHidBase *ret = NULL;
32 KPRINTF(10, ("libInit nh: 0x%08lx SysBase: 0x%08lx\n", nh, SysBase));
34 nh->nh_UtilityBase = OpenLibrary("utility.library", 39);
36 #define UtilityBase nh->nh_UtilityBase
38 if(UtilityBase)
40 NewList(&nh->nh_Interfaces);
41 nch = &nh->nh_DummyNCH;
42 nch->nch_ClsBase = nh;
43 nch->nch_Interface = NULL;
45 nch->nch_CDC = AllocVec(sizeof(struct ClsDevCfg), MEMF_PUBLIC|MEMF_CLEAR);
46 if(nch->nch_CDC)
48 ret = nh;
50 if(!ret)
52 CloseLibrary(UtilityBase);
54 } else {
55 KPRINTF(20, ("libInit: OpenLibrary(\"utility.library\", 39) failed!\n"));
58 KPRINTF(10, ("libInit: Ok\n"));
59 return(ret ? TRUE : FALSE);
62 static int GM_UNIQUENAME(libOpen)(LIBBASETYPEPTR nh)
64 KPRINTF(10, ("libOpen nh: 0x%08lx\n", nh));
65 GM_UNIQUENAME(nLoadClassConfig)(nh);
66 return(TRUE);
69 static int GM_UNIQUENAME(libClose)(LIBBASETYPEPTR nh)
71 if(nh->nh_Library.lib_OpenCnt == 0) // FIXME is this 0 or 1? Does AROS decrease it before calling libClose?
73 Forbid();
74 nh->nh_ReadySignal = SIGB_SINGLE;
75 nh->nh_ReadySigTask = FindTask(NULL);
76 if(nh->nh_DispatcherTask)
78 Signal(nh->nh_DispatcherTask, SIGBREAKF_CTRL_C);
80 Permit();
81 while(nh->nh_DispatcherTask)
83 Wait(1L<<nh->nh_ReadySignal);
85 //FreeSignal(nh->nh_ReadySignal);
87 KPRINTF(5, ("libClose: lib_OpenCnt = %ld\n", nh->nh_Library.lib_OpenCnt));
88 return(TRUE);
91 static int GM_UNIQUENAME(libExpunge)(LIBBASETYPEPTR nh)
93 KPRINTF(10, ("libExpunge nh: 0x%08lx\n", nh));
95 if(nh->nh_LowLevelBase)
97 APTR ourvec;
98 Disable();
99 ourvec = SetFunction(nh->nh_LowLevelBase, -5 * LIB_VECTSIZE, nh->nh_LLOldReadJoyPort);
100 if(ourvec != AROS_SLIB_ENTRY(nReadJoyPort, hid, 5))
102 SetFunction(nh->nh_LowLevelBase, -5 * LIB_VECTSIZE, ourvec);
103 Enable();
104 return(FALSE); /* we couldn't remove the patch! */
106 ourvec = SetFunction(nh->nh_LowLevelBase, -22 * LIB_VECTSIZE, nh->nh_LLOldSetJoyPortAttrsA);
107 if(ourvec != AROS_SLIB_ENTRY(nSetJoyPortAttrsA, hid, 22))
109 SetFunction(nh->nh_LowLevelBase, -22 * LIB_VECTSIZE, ourvec);
110 Enable();
111 return(FALSE); /* we couldn't remove the patch! */
113 Enable();
114 CloseLibrary(nh->nh_LowLevelBase);
115 nh->nh_LowLevelBase = NULL;
118 CloseLibrary((struct Library *) UtilityBase);
120 FreeVec(nh->nh_DummyNCH.nch_CDC);
122 KPRINTF(5, ("libExpunge: Unloading done! hid.class expunged!\n\n"));
124 return(TRUE);
127 ADD2INITLIB(GM_UNIQUENAME(libInit), 0)
128 ADD2OPENLIB(GM_UNIQUENAME(libOpen), 0)
129 ADD2CLOSELIB(GM_UNIQUENAME(libClose), 0)
130 ADD2EXPUNGELIB(GM_UNIQUENAME(libExpunge), 0)
131 /* \\\ */
134 * ***********************************************************************
135 * * Library functions *
136 * ***********************************************************************
139 /* /// "usbAttemptInterfaceBinding()" */
140 struct NepClassHid * GM_UNIQUENAME(usbAttemptInterfaceBinding)(struct NepHidBase *nh, struct PsdInterface *pif)
142 struct Library *ps;
143 IPTR ifclass;
144 //IPTR subclass;
145 //IPTR proto;
147 KPRINTF(1, ("nepHidAttemptInterfaceBinding(%08lx)\n", pif));
148 if((ps = OpenLibrary("poseidon.library", 4)))
150 psdGetAttrs(PGA_INTERFACE, pif,
151 IFA_Class, &ifclass,
152 //IFA_SubClass, &subclass,
153 //IFA_Protocol, &proto,
154 TAG_DONE);
155 CloseLibrary(ps);
157 if(ifclass == HID_CLASSCODE)
159 return(GM_UNIQUENAME(usbForceInterfaceBinding)(nh, pif));
162 return(NULL);
164 /* \\\ */
166 /* /// "usbForceInterfaceBinding()" */
167 struct NepClassHid * GM_UNIQUENAME(usbForceInterfaceBinding)(struct NepHidBase *nh, struct PsdInterface *pif)
169 struct Library *ps;
170 struct NepClassHid *nch;
171 struct PsdConfig *pc;
172 struct PsdDevice *pd;
173 STRPTR devname;
174 STRPTR ifidstr;
175 STRPTR devidstr;
176 UBYTE buf[64];
177 struct Task *tmptask;
179 KPRINTF(1, ("nepHidForceInterfaceBinding(%08lx)\n", pif));
181 nInstallLLPatch(nh);
182 if((ps = OpenLibrary("poseidon.library", 4)))
184 psdGetAttrs(PGA_INTERFACE, pif,
185 IFA_Config, &pc,
186 IFA_IDString, &ifidstr,
187 TAG_DONE);
188 psdGetAttrs(PGA_CONFIG, pc,
189 CA_Device, &pd,
190 TAG_END);
191 psdGetAttrs(PGA_DEVICE, pd,
192 DA_ProductName, &devname,
193 DA_IDString, &devidstr,
194 TAG_END);
195 if((nch = psdAllocVec(sizeof(struct NepClassHid))))
197 nch->nch_ClsBase = nh;
198 nch->nch_CDC = psdAllocVec(sizeof(struct ClsDevCfg));
199 if(!nch->nch_CDC)
201 psdFreeVec(nch);
202 CloseLibrary(ps);
203 return(NULL);
206 nch->nch_Device = pd;
207 nch->nch_Interface = pif;
208 nch->nch_DevIDString = devidstr;
209 nch->nch_IfIDString = ifidstr;
211 GM_UNIQUENAME(nLoadBindingConfig)(nch, FALSE);
213 psdSafeRawDoFmt(buf, 64, "hid.class<%08lx>", nch);
214 nch->nch_ReadySignal = SIGB_SINGLE;
215 nch->nch_ReadySigTask = FindTask(NULL);
216 SetSignal(0, SIGF_SINGLE);
218 if((tmptask = psdSpawnSubTask(buf, GM_UNIQUENAME(nHidTask), nch)))
220 psdBorrowLocksWait(tmptask, 1UL<<nch->nch_ReadySignal);
221 if(nch->nch_Task)
223 nch->nch_ReadySigTask = NULL;
224 //FreeSignal(nch->nch_ReadySignal);
225 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
226 "HID the road, '%s'!",
227 devname);
228 Forbid();
229 AddTail(&nh->nh_Interfaces, &nch->nch_Node);
230 Permit();
231 CloseLibrary(ps);
232 return(nch);
235 nch->nch_ReadySigTask = NULL;
236 //FreeSignal(nch->nch_ReadySignal);
237 psdFreeVec(nch->nch_CDC);
238 psdFreeVec(nch);
240 CloseLibrary(ps);
242 return(NULL);
244 /* \\\ */
246 /* /// "usbReleaseInterfaceBinding()" */
247 void GM_UNIQUENAME(usbReleaseInterfaceBinding)(struct NepHidBase *nh, struct NepClassHid *nch)
249 struct Library *ps;
250 struct PsdConfig *pc;
251 struct PsdDevice *pd;
252 STRPTR devname;
254 KPRINTF(1, ("nepHidReleaseInterfaceBinding(%08lx)\n", nch));
255 if((ps = OpenLibrary("poseidon.library", 4)))
257 Forbid();
258 nch->nch_ReadySignal = SIGB_SINGLE;
259 nch->nch_ReadySigTask = FindTask(NULL);
260 if(nch->nch_GUITask)
262 Signal(nch->nch_GUITask, SIGBREAKF_CTRL_C);
264 Permit();
265 while(nch->nch_GUITask)
267 Wait(1L<<nch->nch_ReadySignal);
270 Forbid();
271 if(nch->nch_HCGUITask)
273 Signal(nch->nch_HCGUITask, SIGBREAKF_CTRL_C);
275 Permit();
276 while(nch->nch_HCGUITask)
278 Wait(1L<<nch->nch_ReadySignal);
281 Forbid();
282 if(nch->nch_Task)
284 Signal(nch->nch_Task, SIGBREAKF_CTRL_C);
286 Permit();
287 while(nch->nch_Task)
289 Wait(1L<<nch->nch_ReadySignal);
291 //FreeSignal(nch->nch_ReadySignal);
292 psdGetAttrs(PGA_INTERFACE, nch->nch_Interface, IFA_Config, &pc, TAG_END);
293 psdGetAttrs(PGA_CONFIG, pc, CA_Device, &pd, TAG_END);
294 psdGetAttrs(PGA_DEVICE, pd, DA_ProductName, &devname, TAG_END);
295 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
296 "And don't you come back no more, '%s'!",
297 devname);
298 Forbid();
299 Remove(&nch->nch_Node);
300 Permit();
301 psdFreeVec(nch->nch_CDC);
302 psdFreeVec(nch);
303 CloseLibrary(ps);
306 /* \\\ */
308 /* /// "usbGetAttrsA()" */
309 AROS_LH3(LONG, usbGetAttrsA,
310 AROS_LHA(ULONG, type, D0),
311 AROS_LHA(APTR, usbstruct, A0),
312 AROS_LHA(struct TagItem *, tags, A1),
313 LIBBASETYPEPTR, nh, 5, hid)
315 AROS_LIBFUNC_INIT
317 struct TagItem *ti;
318 LONG count = 0;
320 KPRINTF(1, ("nepHidGetAttrsA(%ld, %08lx, %08lx)\n", type, usbstruct, tags));
321 switch(type)
323 case UGA_CLASS:
324 if((ti = FindTagItem(UCCA_Priority, tags)))
326 *((SIPTR *) ti->ti_Data) = 0;
327 count++;
329 if((ti = FindTagItem(UCCA_Description, tags)))
331 *((STRPTR *) ti->ti_Data) = "Generic support for human interface devices";
332 count++;
334 if((ti = FindTagItem(UCCA_HasClassCfgGUI, tags)))
336 *((IPTR *) ti->ti_Data) = TRUE;
337 count++;
339 if((ti = FindTagItem(UCCA_HasBindingCfgGUI, tags)))
341 *((IPTR *) ti->ti_Data) = TRUE;
342 count++;
344 if((ti = FindTagItem(UCCA_AfterDOSRestart, tags)))
346 *((IPTR *) ti->ti_Data) = FALSE;
347 count++;
349 if((ti = FindTagItem(UCCA_UsingDefaultCfg, tags)))
351 *((IPTR *) ti->ti_Data) = nh->nh_DummyNCH.nch_UsingDefaultCfg;
352 count++;
354 if((ti = FindTagItem(UCCA_SupportsSuspend, tags)))
356 *((IPTR *) ti->ti_Data) = TRUE;
357 count++;
359 break;
361 case UGA_BINDING:
362 if((ti = FindTagItem(UCBA_UsingDefaultCfg, tags)))
364 *((IPTR *) ti->ti_Data) = ((struct NepClassHid *) usbstruct)->nch_UsingDefaultCfg;
365 count++;
367 break;
369 return(count);
370 AROS_LIBFUNC_EXIT
372 /* \\\ */
374 /* /// "usbSetAttrsA()" */
375 AROS_LH3(LONG, usbSetAttrsA,
376 AROS_LHA(ULONG, type, D0),
377 AROS_LHA(APTR, usbstruct, A0),
378 AROS_LHA(struct TagItem *, tags, A1),
379 LIBBASETYPEPTR, nh, 6, hid)
381 AROS_LIBFUNC_INIT
382 return(0);
383 AROS_LIBFUNC_EXIT
385 /* \\\ */
387 /* /// "usbDoMethodA()" */
388 AROS_LH2(IPTR, usbDoMethodA,
389 AROS_LHA(ULONG, methodid, D0),
390 AROS_LHA(IPTR *, methoddata, A1),
391 LIBBASETYPEPTR, nh, 7, hid)
393 AROS_LIBFUNC_INIT
395 struct NepClassHid *nch;
397 KPRINTF(10, ("Do Method %ld\n", methodid));
398 switch(methodid)
400 case UCM_AttemptInterfaceBinding:
401 return((IPTR) GM_UNIQUENAME(usbAttemptInterfaceBinding)(nh, (struct PsdInterface *) methoddata[0]));
403 case UCM_ForceInterfaceBinding:
404 return((IPTR) GM_UNIQUENAME(usbForceInterfaceBinding)(nh, (struct PsdInterface *) methoddata[0]));
406 case UCM_ReleaseInterfaceBinding:
407 GM_UNIQUENAME(usbReleaseInterfaceBinding)(nh, (struct NepClassHid *) methoddata[0]);
408 return(TRUE);
410 case UCM_OpenCfgWindow:
411 return(GM_UNIQUENAME(nOpenBindingCfgWindow)(nh, &nh->nh_DummyNCH));
413 case UCM_OpenBindingCfgWindow:
414 return(GM_UNIQUENAME(nOpenBindingCfgWindow)(nh, (struct NepClassHid *) methoddata[0]));
416 case UCM_DOSAvailableEvent:
417 nInstallLLPatch(nh);
418 return(TRUE);
420 case UCM_ConfigChangedEvent:
421 GM_UNIQUENAME(nLoadClassConfig)(nh);
423 Forbid();
424 nch = (struct NepClassHid *) nh->nh_Interfaces.lh_Head;
425 while(nch->nch_Node.ln_Succ)
427 GM_UNIQUENAME(nLoadBindingConfig)(nch, TRUE);
428 nch = (struct NepClassHid *) nch->nch_Node.ln_Succ;
430 Permit();
431 return(TRUE);
433 case UCM_AttemptSuspendDevice:
434 nch = (struct NepClassHid *) methoddata[0];
435 nch->nch_Running = FALSE;
436 return(TRUE);
438 case UCM_AttemptResumeDevice:
439 nch = (struct NepClassHid *) methoddata[0];
440 nch->nch_Running = TRUE;
441 Signal(nch->nch_Task, (1L<<nch->nch_TaskMsgPort->mp_SigBit));
442 return(TRUE);
444 default:
445 break;
447 return(0);
448 AROS_LIBFUNC_EXIT
450 /* \\\ */
452 /* /// "nInstallLLPatch()" */
453 void nInstallLLPatch(struct NepHidBase *nh)
455 if(!nh->nh_LowLevelBase)
457 if((nh->nh_LowLevelBase = OpenLibrary("lowlevel.library", 40)))
459 Disable();
460 nh->nh_LLOldReadJoyPort = SetFunction(nh->nh_LowLevelBase, -5 * LIB_VECTSIZE, AROS_SLIB_ENTRY(nReadJoyPort, hid, 5));
461 nh->nh_LLOldSetJoyPortAttrsA = SetFunction(nh->nh_LowLevelBase, -22 * LIB_VECTSIZE, AROS_SLIB_ENTRY(nSetJoyPortAttrsA, hid, 22));
462 Enable();
466 /* \\\ */
468 /* /// "nLoadClassConfig()" */
469 BOOL GM_UNIQUENAME(nLoadClassConfig)(struct NepHidBase *nh)
471 struct NepClassHid *nch = &nh->nh_DummyNCH;
472 struct Library *ps;
473 struct KeymapCfg *kmc;
474 struct ClsDevCfg *cdc;
475 struct PsdIFFContext *pic;
477 KPRINTF(10, ("Loading Class Config...\n"));
478 if(nch->nch_GUITask)
480 return(FALSE);
482 if(!(ps = OpenLibrary("poseidon.library", 4)))
484 return(FALSE);
487 Forbid();
488 /* Create default config */
489 kmc = &nch->nch_KeymapCfg;
490 kmc->kmc_ChunkID = AROS_LONG2BE(MAKE_ID('K','M','A','P'));
491 kmc->kmc_Length = AROS_LONG2BE(sizeof(struct KeymapCfg)-8);
492 CopyMemQuick(usbkeymap, kmc->kmc_Keymap, AROS_LONG2BE(kmc->kmc_Length));
494 cdc = nch->nch_CDC;
495 cdc->cdc_ChunkID = AROS_LONG2BE(MAKE_ID('H','I','D','C'));
496 cdc->cdc_Length = AROS_LONG2BE(sizeof(struct ClsDevCfg)-8);
497 cdc->cdc_EnableKBReset = TRUE;
498 cdc->cdc_EnableRH = TRUE;
499 cdc->cdc_ResetDelay = 10;
500 cdc->cdc_ShellStack = AROS_STACKSIZE;
501 strcpy(cdc->cdc_ShellCon, "CON:///130/HID Rocket Bay/CLOSE/AUTO/WAIT");
502 cdc->cdc_PollingMode = FALSE;
503 cdc->cdc_LLPortMode[1] = 2;
504 cdc->cdc_HIDCtrlOpen = FALSE;
505 strcpy(cdc->cdc_HIDCtrlRexx, "HIDCTRL");
506 strcpy(cdc->cdc_HIDCtrlTitle, "HID Control");
507 cdc->cdc_LLRumblePort = 2;
508 cdc->cdc_TurboMouse = 0;
510 nch->nch_UsingDefaultCfg = TRUE;
511 /* try to load default config */
512 pic = psdGetClsCfg(GM_UNIQUENAME(libname));
513 if(pic)
515 cdc = psdGetCfgChunk(pic, AROS_LONG2BE(nch->nch_CDC->cdc_ChunkID));
516 if(cdc)
518 CopyMem(((UBYTE *) cdc) + 8, ((UBYTE *) nch->nch_CDC) + 8, min(AROS_LONG2BE(cdc->cdc_Length), AROS_LONG2BE(nch->nch_CDC->cdc_Length)));
519 psdFreeVec(cdc);
520 nch->nch_UsingDefaultCfg = FALSE;
522 kmc = psdGetCfgChunk(pic, AROS_LONG2BE(nch->nch_KeymapCfg.kmc_ChunkID));
523 if(kmc)
525 CopyMem(((UBYTE *) kmc) + 8, ((UBYTE *) &nch->nch_KeymapCfg) + 8, min(AROS_LONG2BE(kmc->kmc_Length), AROS_LONG2BE(nch->nch_KeymapCfg.kmc_Length)));
526 psdFreeVec(kmc);
527 nch->nch_UsingDefaultCfg = FALSE;
530 Permit();
531 CloseLibrary(ps);
532 return(FALSE);
534 /* \\\ */
536 /* /// "nCalcConfigCRC()" */
537 ULONG nCalcConfigCRC(struct NepClassHid *nch, struct Library *ps, struct PsdIFFContext *pic)
539 ULONG *buf = (ULONG *) psdWriteCfg(pic);
540 ULONG crc = 0;
541 if(buf)
543 UWORD *ptr = (UWORD *) buf;
544 ULONG len = (AROS_LONG2BE(buf[1]) + 8)>>1;
545 crc = len;
546 if(len)
550 crc = ((crc<<1)|(crc>>31))^(*ptr++);
551 } while(--len);
553 psdFreeVec(buf);
555 return(crc);
557 /* \\\ */
559 /* /// "nLoadBindingConfig()" */
560 BOOL GM_UNIQUENAME(nLoadBindingConfig)(struct NepClassHid *nch, BOOL gui)
562 struct NepHidBase *nh = nch->nch_ClsBase;
563 struct Library *ps;
564 struct ClsDevCfg *cdc;
565 struct KeymapCfg *kmc;
566 struct PsdIFFContext *pic;
567 ULONG crc = 0;
569 KPRINTF(10, ("Loading Binding Config...\n"));
570 if(nch->nch_GUITask)
572 return(FALSE);
574 //GM_UNIQUENAME(nLoadClassConfig)(nh);
575 *nch->nch_CDC = *nh->nh_DummyNCH.nch_CDC;
576 nch->nch_KeymapCfg = nh->nh_DummyNCH.nch_KeymapCfg;
577 nch->nch_UsingDefaultCfg = TRUE;
579 if(!(ps = OpenLibrary("poseidon.library", 4)))
581 return(FALSE);
584 Forbid();
585 /* Load config */
586 pic = psdGetUsbDevCfg(GM_UNIQUENAME(libname), nch->nch_DevIDString, nch->nch_IfIDString);
587 if(pic)
589 cdc = psdGetCfgChunk(pic, AROS_LONG2BE(nch->nch_CDC->cdc_ChunkID));
590 if(cdc)
592 CopyMem(((UBYTE *) cdc) + 8, ((UBYTE *) nch->nch_CDC) + 8, min(AROS_LONG2BE(cdc->cdc_Length), AROS_LONG2BE(nch->nch_CDC->cdc_Length)));
593 psdFreeVec(cdc);
594 nch->nch_UsingDefaultCfg = FALSE;
596 kmc = psdGetCfgChunk(pic, AROS_LONG2BE(nch->nch_KeymapCfg.kmc_ChunkID));
597 if(kmc)
599 CopyMem(((UBYTE *) kmc) + 8, ((UBYTE *) &nch->nch_KeymapCfg) + 8, min(AROS_LONG2BE(kmc->kmc_Length), AROS_LONG2BE(nch->nch_KeymapCfg.kmc_Length)));
600 psdFreeVec(kmc);
601 nch->nch_UsingDefaultCfg = FALSE;
603 crc = nCalcConfigCRC(nch, ps, pic);
605 if(crc != nch->nch_LastCfgCRC)
607 nch->nch_ReloadCfg = TRUE;
608 nch->nch_LastCfgCRC = crc;
609 if(nch->nch_Task)
611 Signal(nch->nch_Task, (1L<<nch->nch_TaskMsgPort->mp_SigBit));
614 if(gui && !nch->nch_HCGUITask)
616 psdSpawnSubTask(MOD_NAME_STRING " Control GUI", GM_UNIQUENAME(nHIDCtrlGUITask), nch);
618 Permit();
619 CloseLibrary(ps);
620 return(FALSE);
622 /* \\\ */
624 /* /// "nOpenBindingCfgWindow()" */
625 LONG GM_UNIQUENAME(nOpenBindingCfgWindow)(struct NepHidBase *nh, struct NepClassHid *nch)
627 struct Library *ps;
628 KPRINTF(10, ("Opening GUI...\n"));
629 if(!(ps = OpenLibrary("poseidon.library", 4)))
631 return(FALSE);
633 Forbid();
634 if(!nch->nch_GUITask)
636 if((nch->nch_GUITask = psdSpawnSubTask(MOD_NAME_STRING " GUI", GM_UNIQUENAME(nGUITask), nch)))
638 Permit();
639 CloseLibrary(ps);
640 return(TRUE);
643 Permit();
644 CloseLibrary(ps);
645 return(FALSE);
647 /* \\\ */
649 /**************************************************************************/
651 /* /// "Keymap Table" */
652 UBYTE usbkeymap[256] =
654 0xff, 0xff, 0xff, 0xff, 0x20, 0x35, 0x33, 0x22, /* 0x00 */
655 0x12, 0x23, 0x24, 0x25, 0x17, 0x26, 0x27, 0x28, /* 0x08 */
656 0x37, 0x36, 0x18, 0x19, 0x10, 0x13, 0x21, 0x14, /* 0x10 */
657 0x16, 0x34, 0x11, 0x32, 0x15, 0x31, 0x01, 0x02, /* 0x18 */
658 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, /* 0x20 */
659 0x44, 0x45, 0x41, 0x42, 0x40, 0x0b, 0x0c, 0x1a, /* 0x28 */
660 0x1b, 0x0d, 0x2b, 0x29, 0x2a, 0x00, 0x38, 0x39, /* 0x30 */
661 0x3a, 0x62, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, /* 0x38 */
662 0x56, 0x57, 0x58, 0x59, 0x5f, 0x67, 0xff, 0xff, /* 0x40 */
663 0x6e, 0x47, 0x70, 0x48, 0x46, 0x71, 0x49, 0x4e, /* 0x48 */
664 0x4f, 0x4d, 0x4c, 0xff, 0x5c, 0x5d, 0x4a, 0x5e, /* 0x50 */
665 0x43, 0x1d, 0x1e, 0x1f, 0x2d, 0x2e, 0x2f, 0x3d, /* 0x58 */
666 0x3e, 0x3f, 0x0f, 0x3c, 0x30, 0x67, 0xff, 0xff, /* 0x60 */
667 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x68 F13-F24 */
668 0xff, 0xff, 0xff, 0xff, 0xff, 0x5f, 0xff, 0xff, /* 0x70 */
669 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x78 */
670 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x80 */
671 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x88 */
672 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x90 */
673 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x44, 0xff, /* 0x98 */
674 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xa0 */
675 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xa8 */
676 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */
677 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb8 */
678 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xc0 */
679 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xc8 */
680 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xd0 */
681 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xd8 */
682 0x63, 0x60, 0x64, 0x66, 0x63, 0x61, 0x65, 0x67, /* 0xe0 */
683 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xe8 */
684 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xf0 */
685 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* 0xf8 */
688 /* \\\ */
690 #undef ps
691 #define ps nch->nch_Base
693 /* /// "nHidTask()" */
694 AROS_UFH0(void, GM_UNIQUENAME(nHidTask))
696 AROS_USERFUNC_INIT
698 struct NepClassHid *nch;
699 struct PsdPipe *pp;
700 ULONG sigmask;
701 ULONG sigs;
702 UBYTE *buf;
703 UBYTE *bufreal;
704 ULONG buflen;
705 LONG ioerr;
706 BOOL wacomgood;
707 LONG lastioerr = 0;
708 ULONG errcount = 0;
710 UWORD reportid;
711 UWORD count;
712 struct NepHidReport *nhr;
713 struct NepHidItem **nhiptr;
714 struct NepHidItem *nhi;
716 if((nch = GM_UNIQUENAME(nAllocHid())))
718 Forbid();
719 if(nch->nch_ReadySigTask)
721 Signal(nch->nch_ReadySigTask, 1L<<nch->nch_ReadySignal);
723 Permit();
724 sigmask = (1L<<nch->nch_TaskMsgPort->mp_SigBit)|SIGBREAKF_CTRL_C;
726 pp = nch->nch_EP0Pipe;
727 /* initial output states */
728 #if 0
729 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
730 while(nhr->nhr_Node.ln_Succ)
732 if(nhr->nhr_OutItemCount)
734 bufreal = nch->nch_EPOutBuf;
735 if(nch->nch_UsesReportID)
737 bufreal++;
738 psdPipeSetup(pp, URTF_IN|URTF_CLASS|URTF_INTERFACE,
739 UHR_GET_REPORT, (ULONG) nhr->nhr_ReportID|0x0200, nch->nch_IfNum);
740 } else {
741 psdPipeSetup(pp, URTF_IN|URTF_CLASS|URTF_INTERFACE,
742 UHR_GET_REPORT, 0x0200, nch->nch_IfNum);
744 if((ioerr = psdDoPipe(pp, nch->nch_EPOutBuf, (nhr->nhr_ReportOutSize+7)>>3)))
746 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
747 "GET_REPORT(%lx, %ld) failed: %s (%ld)!",
748 nhr->nhr_ReportID|0x0200, (nhr->nhr_ReportOutSize+7)>>3,
749 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
750 } else {
751 count = nhr->nhr_OutItemCount;
752 nhiptr = nhr->nhr_OutItemMap;
753 if(nhiptr)
757 nhi = *nhiptr++;
758 nProcessItem(nch, nhi, bufreal);
759 } while(--count);
760 } else {
761 KPRINTF(10, ("Huh? report %ld, nhiptr == NULL!\n", nhr->nhr_ReportID));
765 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
767 #endif
769 if(nch->nch_XtraInitItem)
771 struct NepHidAction *nha = (struct NepHidAction *) nch->nch_XtraInitItem->nhi_ActionList.lh_Head;
772 while(nha->nha_Node.ln_Succ)
774 KPRINTF(1, ("Executing InitItem %08lx\n", nha));
775 nDoAction(nch, nha, nch->nch_XtraInitItem, 0, 1, TRUE);
776 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
779 nFlushEvents(nch);
781 Forbid();
782 if(!nch->nch_HCGUITask)
784 psdSpawnSubTask(MOD_NAME_STRING " Control GUI", GM_UNIQUENAME(nHIDCtrlGUITask), nch);
786 Permit();
788 buf = nch->nch_EPInBuf;
789 //nch->nch_CDC->cdc_PollingMode = TRUE;
790 if(!nch->nch_HasInItems)
792 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "HID Device has no input items, input polling disabled.");
794 nch->nch_ReloadCfg = FALSE;
795 nch->nch_Running = TRUE;
796 nch->nch_IOStarted = FALSE;
799 if(nch->nch_CDC->cdc_PollingMode)
801 sigs = SetSignal(0, 0);
802 #if 0
803 UWORD rptcount;
804 sigs = SetSignal(0, 0);
805 pp = nch->nch_EP0Pipe;
806 for(rptcount = 0; rptcount <= nch->nch_MaxReportID; rptcount++)
808 if(nch->nch_ReportMap[rptcount])
810 if(nch->nch_UsesReportID)
812 psdPipeSetup(pp, URTF_IN|URTF_CLASS|URTF_INTERFACE,
813 UHR_GET_REPORT, (ULONG) rptcount|0x0100, nch->nch_IfNum);
814 } else {
815 psdPipeSetup(pp, URTF_IN|URTF_CLASS|URTF_INTERFACE,
816 UHR_GET_REPORT, 0x0100, nch->nch_IfNum);
818 ioerr = psdDoPipe(pp, buf, nch->nch_MaxInSize);
819 if((!ioerr) || (ioerr == UHIOERR_RUNTPACKET))
821 buflen = psdGetPipeActual(pp);
822 if(nch->nch_UsesReportID)
824 reportid = buf[0];
825 bufreal = &buf[1];
826 } else {
827 reportid = 0;
828 bufreal = buf;
830 if(reportid <= nch->nch_MaxReportID)
832 if((nhr = nch->nch_ReportMap[reportid]))
834 KPRINTF(40, ("Report %ld\n", reportid));
835 count = nhr->nhr_InItemCount;
836 nhiptr = nhr->nhr_InItemMap;
837 if(count && nhiptr)
841 if((nhi = *nhiptr++))
843 nProcessItem(nch, nhi, bufreal);
844 } else {
845 KPRINTF(10, ("Huh? Hole in Item Lookup Map!\n"));
847 } while(--count);
848 } else {
849 KPRINTF(10, ("Huh? report %ld, count %ld or nhiptr == NULL!\n", reportid, count));
851 } else {
852 KPRINTF(10, ("Illegal report ID %ld received!\n", reportid));
855 } else {
856 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
857 "GET_REPORT(%lx, %ld) failed: %s (%ld)!",
858 rptcount, nch->nch_MaxInSize,
859 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
860 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
861 "Reverting back to interrupt mode instead of polling!");
863 nch->nch_CDC->cdc_PollingMode = FALSE;
864 if(nch->nch_Running)
866 psdSendPipe(nch->nch_EPInPipe, buf, nch->nch_MaxInSize);
867 nch->nch_IOStarted = TRUE;
869 break;
873 psdDelayMS(nch->nch_EPInInterval);
874 #endif
875 } else {
876 if(nch->nch_Running && (!nch->nch_IOStarted) && nch->nch_HasInItems)
878 psdSendPipe(nch->nch_EPInPipe, buf, nch->nch_MaxInSize);
879 nch->nch_IOStarted = TRUE;
881 sigs = Wait(sigmask);
882 while((pp = (struct PsdPipe *) GetMsg(nch->nch_TaskMsgPort)))
884 if(pp == nch->nch_EPInPipe)
886 nch->nch_IOStarted = FALSE;
887 ioerr = psdGetPipeError(pp);
888 if((!ioerr) || (ioerr == UHIOERR_RUNTPACKET))
890 buflen = psdGetPipeActual(pp);
891 wacomgood = FALSE;
892 errcount = 0;
893 if(nch->nch_WacomMode)
895 wacomgood = nParseWacom(nch, buf, buflen);
897 if(!wacomgood)
899 // if the parser failed, use standard methods
900 if(nch->nch_UsesReportID)
902 reportid = buf[0];
903 bufreal = &buf[1];
904 } else {
905 reportid = 0;
906 bufreal = buf;
908 if(reportid <= nch->nch_MaxReportID)
910 if((nhr = nch->nch_ReportMap[reportid]))
912 KPRINTF(40, ("Report %ld\n", reportid));
913 count = nhr->nhr_InItemCount;
914 nhiptr = nhr->nhr_InItemMap;
915 if(count && nhiptr)
919 if((nhi = *nhiptr++))
921 nProcessItem(nch, nhi, bufreal);
922 } else {
923 KPRINTF(10, ("Huh? Hole in Item Lookup Map!\n"));
925 } while(--count);
926 } else {
927 KPRINTF(10, ("Huh? count or nhiptr == NULL!\n"));
930 } else {
931 KPRINTF(10, ("Illegal report ID %ld received!\n", reportid));
935 //dumpmem(buf, buflen);
936 } else {
937 KPRINTF(10, ("Int Pipe failed %ld\n", ioerr));
938 if(nch->nch_Running)
940 if(lastioerr != ioerr)
942 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
943 "Interrupt pipe failed: %s (%ld)!",
944 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
945 errcount = 0;
946 } else {
947 errcount++;
948 if(errcount > 20)
950 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
951 "That's it, that device pissed me off long enough!");
952 sigs |= SIGBREAKF_CTRL_C;
955 lastioerr = ioerr;
957 IPTR epnum;
958 psdGetAttrs(PGA_ENDPOINT, nch->nch_EPIn,
959 EA_EndpointNum, &epnum,
960 TAG_END);
961 psdPipeSetup(nch->nch_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
962 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) epnum|URTF_IN);
963 ioerr = psdDoPipe(nch->nch_EP0Pipe, NULL, 0);
965 psdDelayMS(50);
971 nFlushEvents(nch);
972 if(nch->nch_TrackEvents || nch->nch_TrackKeyEvents || (nch->nch_ReportValues && nch->nch_ItemChanged))
974 if(nch->nch_GUITask)
976 Signal(nch->nch_GUITask, (ULONG) (1<<nch->nch_TrackingSignal));
979 if(!nch->nch_HIntBase) /* attempt to open intuition */
981 nch->nch_HIntBase = OpenLibrary("intuition.library", 39);
984 /* need to update prefs? */
985 if(nch->nch_ReloadCfg)
987 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Reloading configuration...");
988 Forbid();
989 nch->nch_ReadySignal = SIGB_SINGLE;
990 nch->nch_ReadySigTask = FindTask(NULL);
991 if(nch->nch_GUITask)
993 Signal(nch->nch_GUITask, SIGBREAKF_CTRL_C);
995 Permit();
996 while(nch->nch_GUITask)
998 Wait(1L<<nch->nch_ReadySignal);
1000 Forbid();
1001 if(nch->nch_HCGUITask)
1003 Signal(nch->nch_HCGUITask, SIGBREAKF_CTRL_C);
1005 Permit();
1006 while(nch->nch_HCGUITask)
1008 Wait(1L<<nch->nch_ReadySignal);
1010 //FreeSignal(nch->nch_ReadySignal);
1011 Forbid();
1012 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
1013 while(nhr->nhr_Node.ln_Succ)
1015 nFreeReport(nch, nhr);
1016 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
1018 psdFreeVec(nch->nch_ReportMap);
1019 nch->nch_ReportMap = NULL;
1020 psdFreeVec(nch->nch_HidDesc);
1021 nch->nch_HidDesc = NULL;
1022 Permit();
1023 if(nReadReports(nch))
1025 nAddExtraReport(nch);
1026 nDetectWacom(nch);
1027 } else {
1028 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname), "Error parsing report descriptors!");
1029 sigs |= SIGBREAKF_CTRL_C;
1031 nch->nch_ReloadCfg = FALSE;
1033 } while(!(sigs & SIGBREAKF_CTRL_C));
1034 if(nch->nch_XtraQuitItem)
1036 struct NepHidAction *nha = (struct NepHidAction *) nch->nch_XtraQuitItem->nhi_ActionList.lh_Head;
1037 while(nha->nha_Node.ln_Succ)
1039 nDoAction(nch, nha, nch->nch_XtraQuitItem, 0, 1, TRUE);
1040 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
1044 KPRINTF(20, ("Going down the river!\n"));
1045 if(nch->nch_IOStarted)
1047 psdAbortPipe(nch->nch_EPInPipe);
1048 psdWaitPipe(nch->nch_EPInPipe);
1050 GM_UNIQUENAME(nFreeHid)(nch);
1053 AROS_USERFUNC_EXIT
1055 /* \\\ */
1057 /* /// "nAllocHid()" */
1058 struct NepClassHid * GM_UNIQUENAME(nAllocHid)(void)
1060 struct Task *thistask;
1061 struct NepClassHid *nch;
1062 LONG ioerr;
1063 IPTR subclass;
1064 IPTR protocol;
1066 thistask = FindTask(NULL);
1067 #undef IntuitionBase
1068 nch = thistask->tc_UserData;
1070 NewList(&nch->nch_HidReports);
1073 if(!(nch->nch_Base = OpenLibrary("poseidon.library", 4)))
1075 Alert(AG_OpenLib);
1076 break;
1078 if(!(nch->nch_HIntBase = OpenLibrary("intuition.library", 39)))
1080 /* we don't mind anymore */
1081 //Alert(AG_OpenLib|AO_Intuition);
1082 //break;
1084 #define IntuitionBase nch->nch_HIntBase
1085 psdGetAttrs(PGA_INTERFACE, nch->nch_Interface,
1086 IFA_Config, &nch->nch_Config,
1087 IFA_InterfaceNum, &nch->nch_IfNum,
1088 IFA_SubClass, &subclass,
1089 IFA_Protocol, &protocol,
1090 TAG_END);
1091 psdGetAttrs(PGA_CONFIG, nch->nch_Config,
1092 CA_Device, &nch->nch_Device,
1093 TAG_END);
1095 nch->nch_EPIn = psdFindEndpoint(nch->nch_Interface, NULL,
1096 EA_IsIn, TRUE,
1097 EA_TransferType, USEAF_INTERRUPT,
1098 TAG_END);
1099 nch->nch_EPOut = psdFindEndpoint(nch->nch_Interface, NULL,
1100 EA_IsIn, FALSE,
1101 EA_TransferType, USEAF_INTERRUPT,
1102 TAG_END);
1104 if((nch->nch_InpMsgPort = CreateMsgPort()))
1106 if((nch->nch_InpIOReq = (struct IOStdReq *) CreateIORequest(nch->nch_InpMsgPort, sizeof(struct IOStdReq))))
1108 if(!OpenDevice("input.device", 0, (struct IORequest *) nch->nch_InpIOReq, 0))
1110 nch->nch_InputBase = (struct Library *) nch->nch_InpIOReq->io_Device;
1111 #define InputBase nch->nch_InputBase
1112 nch->nch_OS4Hack = TRUE;
1113 nch->nch_ClsBase->nh_OS4Hack = TRUE;
1114 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1115 "Using AROS IND_ADDEVENT workaround to fix some mouse & keyboard problems.");
1117 if((nch->nch_TaskMsgPort = CreateMsgPort()))
1119 if((nch->nch_EP0Pipe = psdAllocPipe(nch->nch_Device, nch->nch_TaskMsgPort, NULL)))
1121 psdSetAttrs(PGA_PIPE, nch->nch_EP0Pipe,
1122 PPA_NakTimeout, TRUE,
1123 PPA_NakTimeoutTime, 5000,
1124 TAG_END);
1125 if(nch->nch_EPIn)
1127 psdGetAttrs(PGA_ENDPOINT, nch->nch_EPIn,
1128 EA_Interval, &nch->nch_EPInInterval,
1129 TAG_END);
1131 if((nch->nch_EPInPipe = psdAllocPipe(nch->nch_Device, nch->nch_TaskMsgPort, nch->nch_EPIn)))
1133 if(nch->nch_CDC->cdc_TurboMouse)
1135 psdSetAttrs(PGA_PIPE, nch->nch_EPInPipe,
1136 PPA_Interval, 1<<nch->nch_CDC->cdc_TurboMouse,
1137 PPA_AllowRuntPackets, TRUE,
1138 TAG_END);
1141 } else {
1142 nch->nch_EPInPipe = NULL;
1144 if(subclass == HID_BOOT_SUBCLASS)
1146 psdPipeSetup(nch->nch_EP0Pipe, URTF_CLASS|URTF_INTERFACE,
1147 UHR_SET_IDLE, (ULONG) ((protocol == HID_PROTO_KEYBOARD) ? 64 : 0), nch->nch_IfNum);
1148 ioerr = psdDoPipe(nch->nch_EP0Pipe, NULL, 0);
1149 if(ioerr)
1151 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1152 "SET_IDLE=0 failed: %s (%ld)!",
1153 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1156 psdPipeSetup(nch->nch_EP0Pipe, URTF_CLASS|URTF_INTERFACE,
1157 UHR_SET_PROTOCOL, HID_PROTO_REPORT, nch->nch_IfNum);
1158 ioerr = psdDoPipe(nch->nch_EP0Pipe, NULL, 0);
1159 if(ioerr)
1161 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1162 "SET_PROTOCOL=REPORT failed: %s (%ld)!",
1163 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1166 #if 0
1168 IPTR epnum;
1169 psdGetAttrs(PGA_ENDPOINT, nch->nch_EPIn,
1170 EA_EndpointNum, &epnum,
1171 TAG_END);
1172 psdPipeSetup(nch->nch_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
1173 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) epnum|URTF_IN);
1174 ioerr = psdDoPipe(nch->nch_EP0Pipe, NULL, 0);
1175 if(ioerr)
1177 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1178 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
1179 epnum, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1182 #endif
1183 nQuirkPS3Controller(nch);
1185 if(nReadReports(nch))
1187 BOOL fail = FALSE;
1188 nAddExtraReport(nch);
1189 nDetectWacom(nch);
1190 if(!nch->nch_EPInPipe)
1192 if(nch->nch_HasInItems)
1194 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
1195 "This device does not have an interrupt IN endpoint, but it needs one for input items!");
1196 fail = TRUE;
1197 } else {
1198 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "This device does not have an interrupt IN endpoint!");
1199 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "This means it can only be used for OUTPUT, if at all. Check your HID Control window!");
1202 if(!fail)
1204 if((nch->nch_EPInBuf = psdAllocVec(nch->nch_MaxInSize)))
1206 if((nch->nch_EPOutBuf = psdAllocVec(nch->nch_MaxReportSize)))
1208 nch->nch_Task = thistask;
1209 return(nch);
1211 psdFreeVec(nch->nch_EPInBuf);
1214 } else {
1215 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname), "Error parsing report descriptors!");
1217 psdFreePipe(nch->nch_EPInPipe);
1218 psdFreePipe(nch->nch_EP0Pipe);
1220 DeleteMsgPort(nch->nch_TaskMsgPort);
1222 CloseDevice((struct IORequest *) nch->nch_InpIOReq);
1224 DeleteIORequest((struct IORequest *) nch->nch_InpIOReq);
1226 DeleteMsgPort(nch->nch_InpMsgPort);
1228 } while(FALSE);
1229 CloseLibrary(nch->nch_HIntBase);
1230 CloseLibrary(nch->nch_Base);
1231 Forbid();
1232 nch->nch_Task = NULL;
1233 if(nch->nch_ReadySigTask)
1235 Signal(nch->nch_ReadySigTask, 1L<<nch->nch_ReadySignal);
1237 return(NULL);
1239 /* \\\ */
1241 /* /// "nFreeHid()" */
1242 void GM_UNIQUENAME(nFreeHid)(struct NepClassHid *nch)
1244 struct NepHidReport *nhr;
1245 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
1246 while(nhr->nhr_Node.ln_Succ)
1248 nFreeReport(nch, nhr);
1249 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
1251 psdFreeVec(nch->nch_ReportMap);
1252 psdFreeVec(nch->nch_HidDesc);
1253 psdFreeVec(nch->nch_EPInBuf);
1254 psdFreeVec(nch->nch_EPOutBuf);
1255 psdFreePipe(nch->nch_EPInPipe);
1256 psdFreePipe(nch->nch_EP0Pipe);
1257 DeleteMsgPort(nch->nch_TaskMsgPort);
1258 CloseDevice((struct IORequest *) nch->nch_InpIOReq);
1259 DeleteIORequest((struct IORequest *) nch->nch_InpIOReq);
1260 DeleteMsgPort(nch->nch_InpMsgPort);
1261 CloseLibrary(nch->nch_HIntBase);
1262 CloseLibrary(nch->nch_Base);
1263 Forbid();
1264 nch->nch_Task = NULL;
1265 if(nch->nch_ReadySigTask)
1267 Signal(nch->nch_ReadySigTask, 1L<<nch->nch_ReadySignal);
1270 /* \\\ */
1272 /* /// "nFreeItem()" */
1273 void nFreeItem(struct NepClassHid *nch, struct NepHidItem *nhi)
1275 struct NepHidAction *nha;
1276 struct List *lst;
1277 ULONG count;
1279 Remove(&nhi->nhi_Node);
1280 psdFreeVec(nhi->nhi_UsageMap);
1281 /* Oh, this was an array */
1282 if((lst = nhi->nhi_ActionMap))
1284 /* We need to free all lists available */
1285 count = nhi->nhi_MapSize;
1288 /* And each list can have several entries */
1289 nha = (struct NepHidAction *) lst->lh_Head;
1290 while(nha->nha_Node.ln_Succ)
1292 Remove(&nha->nha_Node);
1293 psdFreeVec(nha);
1294 nha = (struct NepHidAction *) lst->lh_Head;
1296 lst++;
1297 } while(--count);
1298 psdFreeVec(nhi->nhi_ActionMap);
1300 /* Free action list */
1301 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
1302 while(nha->nha_Node.ln_Succ)
1304 Remove(&nha->nha_Node);
1305 psdFreeVec(nha);
1306 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
1308 psdFreeVec(nhi->nhi_Buffer);
1309 psdFreeVec(nhi);
1311 /* \\\ */
1313 /* /// "nCleanCollection()" */
1314 void nCleanCollection(struct NepClassHid *nch, struct NepHidCollection *nhc)
1316 struct NepHidItem *nhi;
1317 struct NepHidAction *nha;
1318 struct List *lst;
1319 ULONG count;
1321 nhi = (struct NepHidItem *) nhc->nhc_Items.lh_Head;
1322 while(nhi->nhi_Node.ln_Succ)
1324 /* Oh, this was an array */
1325 if((lst = nhi->nhi_ActionMap))
1327 /* We need to free all lists available */
1328 count = nhi->nhi_MapSize;
1331 /* And each list can have several entries */
1332 nha = (struct NepHidAction *) lst->lh_Head;
1333 while(nha->nha_Node.ln_Succ)
1335 Remove(&nha->nha_Node);
1336 psdFreeVec(nha);
1337 nha = (struct NepHidAction *) lst->lh_Head;
1339 lst++;
1340 } while(--count);
1342 /* Free action list */
1343 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
1344 while(nha->nha_Node.ln_Succ)
1346 Remove(&nha->nha_Node);
1347 psdFreeVec(nha);
1348 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
1350 nhi = (struct NepHidItem *) nhi->nhi_Node.ln_Succ;
1353 /* \\\ */
1355 /* /// "nFreeReport()" */
1356 void nFreeReport(struct NepClassHid *nch, struct NepHidReport *nhr)
1358 struct NepHidCollection *nhc;
1359 struct NepHidItem *nhi;
1361 Remove(&nhr->nhr_Node);
1362 nhc = (struct NepHidCollection *) nhr->nhr_Collections.lh_Head;
1363 while(nhc->nhc_Node.ln_Succ)
1365 Remove(&nhc->nhc_Node);
1366 nhi = (struct NepHidItem *) nhc->nhc_Items.lh_Head;
1367 while(nhi->nhi_Node.ln_Succ)
1369 nFreeItem(nch, nhi);
1370 nhi = (struct NepHidItem *) nhc->nhc_Items.lh_Head;
1372 psdFreeVec(nhc->nhc_Name);
1373 psdFreeVec(nhc);
1374 nhc = (struct NepHidCollection *) nhr->nhr_Collections.lh_Head;
1376 psdFreeVec(nhr->nhr_InItemMap);
1377 psdFreeVec(nhr->nhr_ReportBuf);
1378 psdFreeVec(nhr);
1380 /* \\\ */
1382 /* /// "nAddItemAction()" */
1383 void nAddItemAction(struct NepClassHid *nch, struct PsdIFFContext *rppic, struct NepHidItem *nhi, UWORD id)
1385 struct NepHidCollection *nhc = nhi->nhi_Collection;
1386 NewList(&nhi->nhi_ActionList);
1387 SET_WTYPE(&nhi->nhi_ActionList, id + 0xf001);
1388 AddTail(&nhc->nhc_Items, &nhi->nhi_Node);
1389 if(rppic)
1391 if(!nLoadItem(nch, rppic, &nhi->nhi_ActionList, 0xf001))
1393 nDetectDefaultAction(nch, nhi, &nhi->nhi_ActionList, nhc, nhi->nhi_Usage);
1395 } else {
1396 nDetectDefaultAction(nch, nhi, &nhi->nhi_ActionList, nhc, nhi->nhi_Usage);
1399 /* \\\ */
1401 /* /// "nAddExtraReport()" */
1402 BOOL nAddExtraReport(struct NepClassHid *nch)
1404 struct NepHidCollection *nhc;
1405 struct NepHidReport *nhr;
1406 struct NepHidItem *nhi;
1407 struct PsdIFFContext *pic;
1408 struct PsdIFFContext *rppic = NULL;
1409 UWORD item;
1410 ULONG pos;
1412 /* find rumble motors for rumble pack */
1413 if((item = nFindItemUsage(nch, 0x080045, REPORT_MAIN_OUTPUT)))
1415 nch->nch_RumbleMotors[0] = nFindItemID(nch, item, REPORT_MAIN_OUTPUT, &pos);
1417 if((item = nFindItemUsage(nch, 0x080046, REPORT_MAIN_OUTPUT)))
1419 nch->nch_RumbleMotors[1] = nFindItemID(nch, item, REPORT_MAIN_OUTPUT, &pos);
1422 pic = psdGetUsbDevCfg(GM_UNIQUENAME(libname), nch->nch_DevIDString, nch->nch_IfIDString);
1423 if(pic)
1425 rppic = psdFindCfgForm(pic, MAKE_ID('X','R','P','T'));
1427 if((nhr = psdAllocVec(sizeof(struct NepHidReport))))
1429 NewList(&nhr->nhr_Collections);
1430 AddTail(&nch->nch_HidReports, &nhr->nhr_Node);
1431 nhr->nhr_ReportID = 0xffff;
1432 nhr->nhr_ItemIDBase = 0xf001;
1433 if((nhc = psdAllocVec(sizeof(struct NepHidCollection))))
1435 NewList(&nhc->nhc_Items);
1436 AddTail(&nhr->nhr_Collections, &nhc->nhc_Node);
1437 nhc->nhc_Report = nhr;
1438 nhc->nhc_Name = psdCopyStr("[Extra]");
1439 if((nhi = psdAllocVec(sizeof(struct NepHidItem))))
1441 nhi->nhi_Collection = nhc;
1442 nhi->nhi_Type = REPORT_MAIN_INPUT;
1443 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1445 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = 0;
1446 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = 1;
1447 nhi->nhi_Usage = 0x1fff0;
1448 nAddItemAction(nch, rppic, nhi, 0xff0);
1449 nch->nch_XtraInitItem = nhi;
1451 if((nhi = psdAllocVec(sizeof(struct NepHidItem))))
1453 nhi->nhi_Collection = nhc;
1454 nhi->nhi_Type = REPORT_MAIN_INPUT;
1455 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1457 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = 0;
1458 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = 1;
1459 nhi->nhi_Usage = 0x1fff1;
1460 nAddItemAction(nch, rppic, nhi, 0xff1);
1461 nch->nch_XtraQuitItem = nhi;
1466 return(FALSE);
1468 /* \\\ */
1470 /* /// "Wacom Tables" */
1472 static struct WacomCaps WacomCapsTable[] =
1474 { 0x0000, WACOM_PENPARTNER, 5040, 3780, 8, "PenPartner" },
1475 { 0x0003, WACOM_PLX, 20480, 15360, 9, "Cintiq Partner" },
1476 { 0x0010, WACOM_GRAPHIRE, 10206, 7422, 9, "Graphire" },
1477 { 0x0011, WACOM_GRAPHIRE, 10206, 7422, 9, "Graphire 2 4x5" },
1478 { 0x0012, WACOM_GRAPHIRE, 13918, 10206, 9, "Graphire 2 5x7" },
1479 { 0x0013, WACOM_GRAPHIRE, 10208, 7424, 9, "Graphire 3" },
1480 { 0x0014, WACOM_GRAPHIRE, 16704, 12064, 9, "Graphire 3 6x8" },
1481 { 0x0015, WACOM_GRAPHIRE4, 10208, 7424, 9, "Graphire 4 4x5" },
1482 { 0x0016, WACOM_GRAPHIRE4, 16704, 12064, 9, "Graphire 4 6x8" },
1483 { 0x0020, WACOM_INTUOS, 12700, 10600, 10, "Intuos 4x5" },
1484 { 0x0021, WACOM_INTUOS, 20320, 16240, 10, "Intuos 6x8" },
1485 { 0x0022, WACOM_INTUOS, 30480, 24060, 10, "Intuos 9x12" },
1486 { 0x0023, WACOM_INTUOS, 30480, 31680, 10, "Intuos 12x12" },
1487 { 0x0024, WACOM_INTUOS, 45720, 31680, 10, "Intuos 12x18" },
1488 { 0x0030, WACOM_PL, 5408, 4056, 8, "PL-400" },
1489 { 0x0031, WACOM_PL, 6144, 4608, 8, "PL-500" },
1490 { 0x0032, WACOM_PL, 6126, 4604, 8, "PL-600" },
1491 { 0x0033, WACOM_PL, 6260, 5016, 8, "PL-600 SX" },
1492 { 0x0034, WACOM_PL2, 6144, 4608, 9, "PL-550" },
1493 { 0x0035, WACOM_PL2, 7220, 5780, 9, "PL-800" },
1494 { 0x0037, WACOM_PL2, 6758, 5406, 9, "PL-700" },
1495 { 0x0038, WACOM_PL2, 6282, 4762, 9, "PL-510" },
1496 { 0x0039, WACOM_PL2, 34080, 27660, 9, "PL-710" },
1497 { 0x003f, WACOM_CINTIQ, 87200, 65600, 10, "Cintiq 21 UX" },
1498 { 0x0041, WACOM_INTUOS, 12700, 10600, 10, "Intuos 2 4x5" },
1499 { 0x0042, WACOM_INTUOS, 20320, 16240, 10, "Intuos 2 6x8" },
1500 { 0x0043, WACOM_INTUOS, 30480, 24060, 10, "Intuos 2 9x12" },
1501 { 0x0044, WACOM_INTUOS, 30480, 31680, 10, "Intuos 2 12x12" },
1502 { 0x0045, WACOM_INTUOS, 45720, 31680, 10, "Intuos 2 12x18" },
1503 { 0x0047, WACOM_INTUOS, 20320, 16240, 10, "Intuos 2 6x8" },
1504 { 0x0060, WACOM_GRAPHIRE, 5104, 3712, 9, "Volito" },
1505 { 0x0061, WACOM_GRAPHIRE, 3250, 2320, 8, "PenStation 2" },
1506 { 0x0062, WACOM_GRAPHIRE, 5104, 3712, 9, "Volito 2 4x5" },
1507 { 0x0063, WACOM_GRAPHIRE, 3248, 2320, 9, "Volito 2 2x3" },
1508 { 0x0064, WACOM_GRAPHIRE, 3250, 2320, 8, "PenPartner 2" },
1509 { 0x00b0, WACOM_INTUOS3, 25400, 20320, 10, "Intuos 3 4x5" },
1510 { 0x00b1, WACOM_INTUOS3, 40640, 30480, 10, "Intuos 3 6x8" },
1511 { 0x00b2, WACOM_INTUOS3, 60960, 45720, 10, "Intuos 3 9x12" },
1512 { 0x00b5, WACOM_INTUOS3, 54204, 31750, 10, "Intuos 3 6x11" },
1513 { 0x00c0, WACOM_PL2, 6858, 5506, 9, "DTF-720" },
1514 { 0xffff, 0, 0, 0, 0, NULL }
1516 /* \\\ */
1518 /* /// "nParseWacom()" */
1519 BOOL nParseWacom(struct NepClassHid *nch, UBYTE *buf, ULONG len)
1521 struct WacomReport wr = { ~0, ~0, 0xffff, 0, 0, 0x80, 0x80, 0 };
1522 struct NepHidItem *nhi;
1523 BOOL take = FALSE;
1524 UWORD tmpval;
1525 KPRINTF(1, ("Wacom parsing %ld (%ld)...\n", nch->nch_WacomMode, len));
1526 switch(nch->nch_WacomMode)
1528 case WACOM_PENPARTNER:
1529 // 7 6 5 4 3 2 1 0
1530 // 80 40 20 10 08 04 02 01
1531 // 1: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1532 // 2: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1533 // 3: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
1534 // 4: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
1535 // 5: rmb outrng
1536 // 6: [signed pressure]
1537 if((buf[0] != 2) || (len < 7))
1539 break;
1541 wr.wr_PosX = buf[1] | (buf[2]<<8);
1542 wr.wr_PosY = buf[3] | (buf[4]<<8);
1543 wr.wr_Pressure = (((BYTE *) buf)[6]) + 127;
1544 wr.wr_InProximity = buf[5] & 0x20 ? 0x00 : 0xff;
1545 if(wr.wr_InProximity && (wr.wr_Pressure > 50))
1547 wr.wr_Buttons = 0x01;
1549 if(buf[5] & 0x40)
1551 wr.wr_Buttons |= 0x02;
1553 take = TRUE;
1554 break;
1556 case WACOM_GRAPHIRE:
1557 case WACOM_GRAPHIRE4:
1558 // 7 6 5 4 3 2 1 0
1559 // 80 40 20 10 08 04 02 01
1560 // 1: vld tooltype prox mmb rmb lmb
1561 // 2: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1562 // 3: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1563 // 4: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
1564 // 5: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
1565 // 6: [wheel bits ] G3 MOUSE
1566 // 6: [distance ] G4 MOUSE
1567 // 7: [distance ] G3 MOUSE
1568 // 7: wh_sgn wheel_bits G4 MOUSE
1569 // 6: [ pressure bits 0-7 ]
1570 // 7: pres8
1571 if((buf[0] != 2) || (len < 8))
1573 break;
1575 if(buf[1] & 0x10)
1577 wr.wr_InProximity = 0xff;
1578 if(buf[1] & 0x40) // is a mouse
1580 if(buf[1] & 0x20) // mouse without a scrollwheel
1582 // only two buttons, no wheel
1583 wr.wr_Buttons = buf[1] & 0x03;
1584 } else {
1585 // three buttons and wheel
1586 wr.wr_Buttons = buf[1] & 0x07;
1587 if(nch->nch_WacomMode == WACOM_GRAPHIRE4)
1589 wr.wr_Wheel = buf[7] & 0x03;
1590 if(buf[7] & 0x04)
1592 wr.wr_Wheel = -wr.wr_Wheel;
1594 } else {
1595 wr.wr_Wheel = ((BYTE *) buf)[6];
1596 KPRINTF(1, ("Wheel %ld\n", wr.wr_Wheel));
1599 } else {
1600 wr.wr_Buttons = buf[1] & 0x07;
1601 wr.wr_Pressure = buf[6] | ((buf[7] & 0x01)<<8);
1603 wr.wr_PosX = buf[2] | (buf[3]<<8);
1604 wr.wr_PosY = buf[4] | (buf[5]<<8);
1605 } else {
1606 wr.wr_InProximity = 0;
1608 take = TRUE;
1609 break;
1611 case WACOM_INTUOS:
1612 case WACOM_INTUOS3:
1613 case WACOM_CINTIQ:
1614 // 7 6 5 4 3 2 1 0
1615 // 80 40 20 10 08 04 02 01
1616 // 1: 1 1 0 0 mmb rmb tool = pen packet
1617 // 1: 1 1 1 0 0 tool = airbrush
1618 // 1: 1 1 0 1 = mouse
1619 // 1: 1 1 1 0 0 0 = lens?
1620 // 1: 1 1 0 0 0 0 = tool in
1621 // 1: 1 0 0 0 0 0 0 = tool out
1622 // 2: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1623 // 3: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1624 // 4: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
1625 // 5: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
1626 // 6: [ pressure/wheel bits 8-6 ]
1627 // 7: [press0-1] [ tiltx 6-1]
1628 // 8: tiltx0 [ tilty 6-0 ]
1629 // 9: x16 y16
1630 if(buf[0] == 12)
1632 wr.wr_PadButtons = (buf[5] & 0x0f)|(buf[6]<<4);
1633 take = TRUE;
1634 break;
1636 if((buf[0] != 2) && (buf[0] != 5) && (buf[0] != 6))
1638 break;
1640 // needs some improvement on the various tools
1641 if(buf[1] & 0x40)
1643 wr.wr_InProximity = 0xff;
1644 if(nch->nch_WacomMode == WACOM_INTUOS)
1646 wr.wr_PosX = (buf[2]<<8) | buf[3];
1647 wr.wr_PosY = (buf[4]<<8) | buf[5];
1648 if(buf[1] & 0x10)
1650 wr.wr_Buttons = (buf[8] & 0x07) | ((buf[8] & 0x30)>>1);
1652 } else {
1653 wr.wr_PosX = (buf[2]<<9) | (buf[3] << 1) | ((buf[9] & 0x02)>>1);
1654 wr.wr_PosY = (buf[4]<<9) | (buf[5] << 1) | (buf[9] & 0x01);
1656 if((buf[1] & 0xa0) == 0xa0)
1658 wr.wr_TiltX = ((buf[7] & 0x3f) << 1) | (buf[8] >> 7);
1659 wr.wr_TiltY = buf[8] & 0x7f;
1661 tmpval = (buf[6] << 2) | ((buf[7] & 0xc0)>>6);
1662 if((buf[1] & 0xb8) == 0xa0)
1664 wr.wr_Pressure = tmpval;
1665 wr.wr_Buttons = (buf[1] & 0x06) | ((wr.wr_Pressure > 16) ? 1 : 0);
1667 if((buf[1] & 0xbc) == 0xb4)
1669 wr.wr_Wheel = tmpval;
1671 } else {
1672 wr.wr_InProximity = 0;
1674 take = TRUE;
1675 break;
1677 case WACOM_PL:
1678 case WACOM_PL2:
1679 if((buf[0] != 2) || (len < 8))
1681 break;
1683 wr.wr_InProximity = buf[1] & 0x40 ? 0xff : 0;
1684 if(wr.wr_InProximity)
1686 wr.wr_Pressure = (BYTE) ((buf[7]<<1) | ((buf[4] & 0x04)>>2));
1687 if(nch->nch_WacomMode == WACOM_PL2)
1689 wr.wr_Pressure <<= 1;
1690 wr.wr_Pressure += ((buf[4] >> 6) & 1) + 256;
1691 } else {
1692 wr.wr_Pressure += 128;
1694 wr.wr_PosX = ((buf[1] & 0x03)<<14) | ((buf[2] & 0x7f)<<7) | (buf[3] & 0x7f);
1695 wr.wr_PosY = ((buf[4] & 0x03)<<14) | ((buf[5] & 0x7f)<<7) | (buf[6] & 0x7f);
1696 wr.wr_Buttons = (buf[4] & 0x38)>>3;
1698 take = TRUE;
1699 break;
1701 case WACOM_PLX:
1702 if((buf[0] != 2) || (len < 8))
1704 break;
1706 wr.wr_InProximity = 0xff;
1707 wr.wr_PosX = buf[2] | (buf[3]<<8);
1708 wr.wr_PosY = buf[4] | (buf[5]<<8);
1709 wr.wr_Pressure = buf[6] | (buf[7]<<8);
1710 if(buf[1] & 0x02)
1712 wr.wr_Buttons |= 0x01;
1714 if(buf[1] & 0x10)
1716 wr.wr_Buttons |= 0x02;
1718 take = TRUE;
1719 break;
1721 if(take)
1723 // fix endianess
1724 wr.wr_PosX = AROS_LONG2LE(wr.wr_PosX);
1725 wr.wr_PosY = AROS_LONG2LE(wr.wr_PosY);
1726 wr.wr_Pressure = AROS_WORD2LE(wr.wr_Pressure);
1728 nhi = (struct NepHidItem *) nch->nch_WacomColl->nhc_Items.lh_Head;
1729 while(nhi->nhi_Node.ln_Succ)
1731 nProcessItem(nch, nhi, (UBYTE *) &wr);
1732 nhi = (struct NepHidItem *) nhi->nhi_Node.ln_Succ;
1735 return(take);
1737 /* \\\ */
1739 /* /// "nDetectWacom()" */
1740 BOOL nDetectWacom(struct NepClassHid *nch)
1742 struct NepHidCollection *nhc;
1743 struct NepHidReport *nhr;
1744 struct NepHidItem *nhi;
1745 struct PsdIFFContext *pic;
1746 struct PsdIFFContext *rppic = NULL;
1747 struct WacomCaps *wc;
1748 IPTR vendid;
1749 IPTR prodid;
1750 ULONG caps = 0;
1751 UWORD butno;
1752 UWORD numbuts = 3;
1754 psdGetAttrs(PGA_DEVICE, nch->nch_Device,
1755 DA_VendorID, &vendid,
1756 DA_ProductID, &prodid,
1757 TAG_END);
1758 if(vendid != 0x056a)
1760 return(FALSE);
1763 for(wc = WacomCapsTable; wc->wc_ProdID != prodid; wc++)
1765 if(wc->wc_ProdID == 0xffff)
1767 return FALSE;
1770 switch(wc->wc_Type)
1772 case WACOM_PENPARTNER:
1773 case WACOM_PLX:
1774 numbuts = 2;
1775 break;
1777 case WACOM_INTUOS:
1778 case WACOM_INTUOS3:
1779 case WACOM_CINTIQ:
1780 caps |= WACOM_HASTILT;
1781 case WACOM_GRAPHIRE4:
1782 if(wc->wc_Type != WACOM_INTUOS)
1784 caps |= WACOM_HASBUTTONS;
1786 case WACOM_GRAPHIRE:
1787 caps |= WACOM_HASWHEEL;
1788 break;
1791 psdAddErrorMsg(RETURN_OK, GM_UNIQUENAME(libname), "Adding Wacom %s support.", wc->wc_Name);
1793 pic = psdGetUsbDevCfg(GM_UNIQUENAME(libname), nch->nch_DevIDString, nch->nch_IfIDString);
1794 if(pic)
1796 rppic = psdFindCfgForm(pic, MAKE_ID('W','C','O','M'));
1798 if((nhr = psdAllocVec(sizeof(struct NepHidReport))))
1800 NewList(&nhr->nhr_Collections);
1801 AddTail(&nch->nch_HidReports, &nhr->nhr_Node);
1802 nhr->nhr_ReportID = 0xfffe;
1803 nhr->nhr_ItemIDBase = 0xf001;
1804 if((nhc = psdAllocVec(sizeof(struct NepHidCollection))))
1806 NewList(&nhc->nhc_Items);
1807 AddTail(&nhr->nhr_Collections, &nhc->nhc_Node);
1808 nhc->nhc_Report = nhr;
1809 nhc->nhc_Usage = 0x0d0001;
1810 nhc->nhc_Name = psdCopyStr("[Wacom Support]");
1811 nch->nch_WacomColl = nhc;
1812 nch->nch_WacomMode = wc->wc_Type;
1813 // buttons
1814 for(butno = 0; butno < numbuts; butno++)
1816 if((nhi = psdAllocVec(sizeof(struct NepHidItem))))
1818 nhi->nhi_Collection = nhc;
1819 nhi->nhi_Type = REPORT_MAIN_INPUT;
1820 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1821 nhi->nhi_Offset = (offsetof(struct WacomReport, wr_Buttons)<<3) + butno;
1822 nhi->nhi_Size = 1;
1824 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = 0;
1825 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = 1;
1826 nhi->nhi_Usage = 0x090001+butno;
1827 nAddItemAction(nch, rppic, nhi, 0xfd0+butno);
1830 // absolute X
1831 if((nhi = psdAllocVec(sizeof(struct NepHidItem))))
1833 nhi->nhi_Collection = nhc;
1834 nhi->nhi_Type = REPORT_MAIN_INPUT;
1835 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1836 nhi->nhi_Offset = offsetof(struct WacomReport, wr_PosX)<<3;
1837 nhi->nhi_Size = sizeof(((struct WacomReport *) NULL)->wr_PosX)<<3;
1839 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = 0;
1840 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = wc->wc_ResX-1;
1841 nhi->nhi_Usage = 0x010030;
1842 nAddItemAction(nch, rppic, nhi, 0xfe1);
1844 // absolute Y
1845 if((nhi = psdAllocVec(sizeof(struct NepHidItem))))
1847 nhi->nhi_Collection = nhc;
1848 nhi->nhi_Type = REPORT_MAIN_INPUT;
1849 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1850 nhi->nhi_Offset = offsetof(struct WacomReport, wr_PosY)<<3;
1851 nhi->nhi_Size = sizeof(((struct WacomReport *) NULL)->wr_PosY)<<3;
1853 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = 0;
1854 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = wc->wc_ResY-1;
1855 nhi->nhi_Usage = 0x010031;
1856 nAddItemAction(nch, rppic, nhi, 0xfe2);
1858 // wheel
1859 if((caps & WACOM_HASWHEEL) && ((nhi = psdAllocVec(sizeof(struct NepHidItem)))))
1861 nhi->nhi_Collection = nhc;
1862 nhi->nhi_Type = REPORT_MAIN_INPUT;
1863 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1864 nhi->nhi_Offset = offsetof(struct WacomReport, wr_Wheel)<<3;
1865 nhi->nhi_Size = sizeof(((struct WacomReport *) NULL)->wr_Wheel)<<3;
1867 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = -127;
1868 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = 127;
1869 nhi->nhi_IsSigned = TRUE;
1870 nhi->nhi_Usage = 0x010038;
1871 nAddItemAction(nch, rppic, nhi, 0xfe0);
1873 // pressure
1874 if((nhi = psdAllocVec(sizeof(struct NepHidItem))))
1876 nhi->nhi_Collection = nhc;
1877 nhi->nhi_Type = REPORT_MAIN_INPUT;
1878 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1879 nhi->nhi_Offset = offsetof(struct WacomReport, wr_Pressure)<<3;
1880 nhi->nhi_Size = sizeof(((struct WacomReport *) NULL)->wr_Pressure)<<3;
1882 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = 0;
1883 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = (1UL<<wc->wc_PressBits)-1;
1884 nhi->nhi_Usage = 0x0d0030;
1885 nAddItemAction(nch, rppic, nhi, 0xfe4);
1887 // in proximity
1888 if((nhi = psdAllocVec(sizeof(struct NepHidItem))))
1890 nhi->nhi_Collection = nhc;
1891 nhi->nhi_Type = REPORT_MAIN_INPUT;
1892 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1893 nhi->nhi_Offset = offsetof(struct WacomReport, wr_InProximity)<<3;
1894 nhi->nhi_Size = 1;
1896 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = 0;
1897 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = 1;
1898 nhi->nhi_Usage = 0x0d0032;
1899 nAddItemAction(nch, rppic, nhi, 0xfe5);
1901 // x tilt
1902 if((caps & WACOM_HASTILT) && ((nhi = psdAllocVec(sizeof(struct NepHidItem)))))
1904 nhi->nhi_Collection = nhc;
1905 nhi->nhi_Type = REPORT_MAIN_INPUT;
1906 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1907 nhi->nhi_Offset = offsetof(struct WacomReport, wr_TiltX)<<3;
1908 nhi->nhi_Size = sizeof(((struct WacomReport *) NULL)->wr_TiltX)<<3;
1910 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = 0;
1911 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = 127;
1912 nhi->nhi_Usage = 0x0d003d;
1913 nAddItemAction(nch, rppic, nhi, 0xfe6);
1915 // y tilt
1916 if((caps & WACOM_HASTILT) && ((nhi = psdAllocVec(sizeof(struct NepHidItem)))))
1918 nhi->nhi_Collection = nhc;
1919 nhi->nhi_Type = REPORT_MAIN_INPUT;
1920 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1921 nhi->nhi_Offset = offsetof(struct WacomReport, wr_TiltY)<<3;
1922 nhi->nhi_Size = sizeof(((struct WacomReport *) NULL)->wr_TiltY)<<3;
1924 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = 0;
1925 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = 127;
1926 nhi->nhi_Usage = 0x0d003e;
1927 nAddItemAction(nch, rppic, nhi, 0xfe7);
1929 // pad buttons
1930 if(caps & WACOM_HASBUTTONS)
1932 for(butno = 0; butno < 8; butno++)
1934 if((nhi = psdAllocVec(sizeof(struct NepHidItem))))
1936 nhi->nhi_Collection = nhc;
1937 nhi->nhi_Type = REPORT_MAIN_INPUT;
1938 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1939 nhi->nhi_Offset = (offsetof(struct WacomReport, wr_PadButtons)<<3) + butno;
1940 nhi->nhi_Size = 1;
1942 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = 0;
1943 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = 1;
1944 nhi->nhi_Usage = 0x090009+butno;
1945 nAddItemAction(nch, rppic, nhi, 0xfd8+butno);
1952 return(FALSE);
1954 /* \\\ */
1956 /* /// "nQuirkPS3Controller()" */
1957 void nQuirkPS3Controller(struct NepClassHid *nch)
1959 LONG ioerr;
1960 UBYTE buf[18];
1962 IPTR vendid;
1963 IPTR prodid;
1965 psdGetAttrs(PGA_DEVICE, nch->nch_Device,
1966 DA_VendorID, &vendid,
1967 DA_ProductID, &prodid,
1968 TAG_END);
1970 if(vendid == 0x054c && prodid == 0x0268) {
1971 psdPipeSetup(nch->nch_EP0Pipe, URTF_IN|URTF_CLASS|URTF_INTERFACE, UHR_GET_REPORT, 0x03f2, nch->nch_IfNum);
1972 ioerr = psdDoPipe(nch->nch_EP0Pipe, buf, sizeof(buf));
1973 if(ioerr) {
1974 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname), "Unable to add PS3 controller support!");
1975 }else{
1976 psdAddErrorMsg(RETURN_OK, GM_UNIQUENAME(libname), "Adding PS3 controller support.");
1980 /* \\\ */
1982 /* /// "nReadReports()" */
1983 BOOL nReadReports(struct NepClassHid *nch)
1985 struct NepHidReport *nhr;
1986 struct NepHidCollection *nhc;
1987 struct NepHidItem *nhi;
1988 struct PsdDescriptor *pdd;
1990 LONG ioerr;
1991 UBYTE buf[256];
1992 ULONG num;
1993 UBYTE *bptr;
1994 BOOL res = FALSE;
1995 BOOL thisres;
1997 UWORD idnum;
1998 ULONG count;
1999 struct List *alistptr;
2000 ULONG actlen;
2002 pdd = psdFindDescriptor(nch->nch_Device, NULL,
2003 DDA_DescriptorType, UDT_HID,
2004 DDA_Interface, nch->nch_Interface,
2005 TAG_END);
2006 if(pdd)
2008 UBYTE *descdata;
2009 psdGetAttrs(PGA_DESCRIPTOR, pdd,
2010 DDA_DescriptorData, &descdata,
2011 TAG_END);
2013 actlen = descdata[0];
2014 memcpy(buf, descdata, (size_t) actlen);
2015 ioerr = 0;
2016 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
2017 "Using HID Descriptor from initial configuration run.");
2018 } else {
2019 psdPipeSetup(nch->nch_EP0Pipe, URTF_IN|URTF_STANDARD|URTF_INTERFACE,
2020 USR_GET_DESCRIPTOR, UDT_HID<<8, nch->nch_IfNum);
2021 ioerr = psdDoPipe(nch->nch_EP0Pipe, buf, 256);
2022 if(ioerr == UHIOERR_RUNTPACKET)
2024 ioerr = 0;
2026 if(ioerr)
2028 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2029 "GET_HID_DESCRIPTOR(%ld) failed: %s (%ld)!",
2030 256, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2031 psdDelayMS(100);
2032 ioerr = psdDoPipe(nch->nch_EP0Pipe, buf, 256);
2033 if(ioerr == UHIOERR_RUNTPACKET)
2035 ioerr = 0;
2037 if(ioerr)
2039 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2040 "GET_HID_DESCRIPTOR(%ld) (2nd) failed: %s (%ld)!",
2041 256, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2042 psdPipeSetup(nch->nch_EP0Pipe, URTF_IN|URTF_STANDARD|URTF_INTERFACE,
2043 USR_GET_DESCRIPTOR, UDT_HID<<8, nch->nch_IfNum);
2044 ioerr = psdDoPipe(nch->nch_EP0Pipe, buf, 1);
2045 if(ioerr)
2047 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2048 "GET_HID_DESCRIPTOR(%ld) (3rd) failed: %s (%ld)!",
2049 1, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2051 } else {
2052 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Burstroem retry successful ;)");
2055 actlen = psdGetPipeActual(nch->nch_EP0Pipe);
2057 if((!ioerr) || (ioerr == UHIOERR_OVERFLOW))
2059 if(buf[0] < 9)
2061 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2062 "bLength field (%ld) probably wrong, fixing to %ld!",
2063 buf[0], actlen);
2064 buf[0] = actlen;
2066 if(actlen < 6)
2068 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2069 "Read less than 6 bytes (%ld read) for HID Descriptor!",
2070 actlen);
2072 if((nch->nch_HidDesc = psdAllocVec((ULONG) buf[0])))
2074 /*ioerr = psdDoPipe(nch->nch_EP0Pipe, nch->nch_HidDesc, (ULONG) buf[0]);
2075 if(ioerr)
2077 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2078 "GET_HID_DESCRIPTOR(%ld) failed: %s (%ld)!",
2079 buf[0], psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2080 psdDelayMS(100);
2081 ioerr = psdDoPipe(nch->nch_EP0Pipe, nch->nch_HidDesc, (ULONG) buf[0]);
2082 if(!ioerr)
2084 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Burstroem retry successful ;)");
2087 if(!ioerr)
2089 CopyMem(buf, nch->nch_HidDesc, (ULONG) buf[0]);
2090 //dumpmem(nch->nch_HidDesc, (ULONG) buf);
2091 if(!nch->nch_HidDesc->bNumDescriptors)
2093 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2094 "Device reports that it doesn't have any descriptors!");
2095 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2096 "Debug info: %ld, %02lx, %02lx, %ld, %ld, %02lx, %ld, %ld!",
2097 nch->nch_HidDesc->bLength,
2098 nch->nch_HidDesc->bDescriptorType,
2099 nch->nch_HidDesc->bcdHID,
2100 nch->nch_HidDesc->bCountryCode,
2101 nch->nch_HidDesc->bNumDescriptors,
2102 nch->nch_HidDesc->bDescType,
2103 nch->nch_HidDesc->wDescLength,
2104 nch->nch_HidDesc->wPad0);
2106 if(6 + nch->nch_HidDesc->bNumDescriptors*3 > actlen)
2108 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2109 "Too few bytes read for HID %ld descriptor (%ld of %ld)!",
2110 nch->nch_HidDesc->bNumDescriptors,
2111 actlen,
2112 6 + nch->nch_HidDesc->bNumDescriptors*3);
2113 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2114 "Debug info: %ld, %02lx, %02lx, %ld, %ld, %02lx, %ld, %ld!",
2115 nch->nch_HidDesc->bLength,
2116 nch->nch_HidDesc->bDescriptorType,
2117 nch->nch_HidDesc->bcdHID,
2118 nch->nch_HidDesc->bCountryCode,
2119 nch->nch_HidDesc->bNumDescriptors,
2120 nch->nch_HidDesc->bDescType,
2121 nch->nch_HidDesc->wDescLength,
2122 nch->nch_HidDesc->wPad0);
2125 KPRINTF(1, ("%ld Report descriptors\n", nch->nch_HidDesc->bNumDescriptors));
2126 bptr = &nch->nch_HidDesc->bDescType;
2127 for(num = 0; num < nch->nch_HidDesc->bNumDescriptors; num++)
2129 if(*bptr == UDT_REPORT)
2131 if((nhr = psdAllocVec(sizeof(struct NepHidReport))))
2133 NewList(&nhr->nhr_Collections);
2134 AddTail(&nch->nch_HidReports, &nhr->nhr_Node);
2135 thisres = FALSE;
2136 nhr->nhr_ReportLength = bptr[1] + (bptr[2]<<8);
2137 if(!nhr->nhr_ReportLength)
2139 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2140 "Report Descriptor #%ld is said to have 0 bytes!",
2141 num);
2142 } else {
2143 if((nhr->nhr_ReportBuf = psdAllocVec(nhr->nhr_ReportLength)))
2145 psdPipeSetup(nch->nch_EP0Pipe, URTF_IN|URTF_STANDARD|URTF_INTERFACE,
2146 USR_GET_DESCRIPTOR, (UDT_REPORT<<8)|num, nch->nch_IfNum);
2147 ioerr = psdDoPipe(nch->nch_EP0Pipe, nhr->nhr_ReportBuf, nhr->nhr_ReportLength);
2148 if(!ioerr)
2150 //dumpmem(nhr->nhr_ReportBuf, nhr->nhr_ReportLength);
2151 thisres = nParseReport(nch, nhr);
2152 //nDebugReport(nch, nhr);
2153 res |= thisres;
2154 } else {
2155 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2156 "GET_REPORT_DESCRIPTOR(%ld) failed: %s (%ld)!",
2157 nhr->nhr_ReportLength, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2161 if(!thisres)
2163 nFreeReport(nch, nhr);
2167 bptr += 3;
2169 /*} else {
2170 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2171 "GET_HID_DESCRIPTOR(%ld) failed: %s (%ld)!",
2172 buf[0], psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2174 } else {
2175 KPRINTF(1, ("No Hid Descriptor memory!\n"));
2177 } else {
2178 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2179 "GET_HID_DESCRIPTOR(%ld) failed: %s (%ld)!",
2180 256, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2182 if(res)
2184 ULONG repsize;
2185 /* Get maximal package size */
2186 nch->nch_MaxReportID = 0;
2187 nch->nch_MaxInSize = 0;
2188 nch->nch_MaxOutSize = 0;
2189 nch->nch_MaxFeatSize = 0;
2190 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
2191 while(nhr->nhr_Node.ln_Succ)
2193 KPRINTF(5, ("Report %ld: InBits=%ld, OutBits=%ld, FeatBits=%ld\n",
2194 nhr->nhr_ReportID, nhr->nhr_ReportInSize,
2195 nhr->nhr_ReportOutSize, nhr->nhr_ReportFeatSize));
2196 if(nhr->nhr_ReportID)
2198 nch->nch_UsesReportID = TRUE;
2199 if(nch->nch_MaxReportID < nhr->nhr_ReportID)
2201 nch->nch_MaxReportID = nhr->nhr_ReportID;
2204 repsize = (nhr->nhr_ReportInSize+7)>>3;
2205 if(nch->nch_MaxInSize < repsize)
2207 nch->nch_MaxInSize = repsize;
2209 repsize = (nhr->nhr_ReportOutSize+7)>>3;
2210 if(nch->nch_MaxOutSize < repsize)
2212 nch->nch_MaxOutSize = repsize;
2214 repsize = (nhr->nhr_ReportFeatSize+7)>>3;
2215 if(nch->nch_MaxFeatSize < repsize)
2217 nch->nch_MaxFeatSize = repsize;
2219 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
2221 if(nch->nch_UsesReportID)
2223 nch->nch_MaxInSize++;
2224 nch->nch_MaxOutSize++;
2225 nch->nch_MaxFeatSize++;
2228 nch->nch_MaxReportSize = nch->nch_MaxInSize;
2229 if(nch->nch_MaxOutSize > nch->nch_MaxReportSize)
2231 nch->nch_MaxReportSize = nch->nch_MaxOutSize;
2233 if(nch->nch_MaxFeatSize > nch->nch_MaxReportSize)
2235 nch->nch_MaxReportSize = nch->nch_MaxFeatSize;
2238 KPRINTF(5, ("MaxReportID=%ld, MaxReportSize=%ld\n", nch->nch_MaxReportID, nch->nch_MaxReportSize));
2240 if((nch->nch_ReportMap = psdAllocVec((ULONG) sizeof(struct NepHidReport *) * (nch->nch_MaxReportID+1))))
2242 /* Fill in Report Map */
2243 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
2244 while(nhr->nhr_Node.ln_Succ)
2246 KPRINTF(5, ("Report Map slot %ld/%ld filled with %08lx\n", nhr->nhr_ReportID, nch->nch_MaxReportID, nhr));
2247 nch->nch_ReportMap[nhr->nhr_ReportID] = nhr;
2248 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
2250 } else {
2251 KPRINTF(10, ("Out of memory for Report Map!\n"));
2252 res = FALSE;
2256 if(res)
2258 struct NepHidItem **nhiptr;
2259 struct NepHidItem **nhiinptr;
2260 struct NepHidItem **nhioutptr;
2261 struct NepHidItem **nhifeatptr;
2263 /* Count items */
2264 idnum = 1;
2265 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
2266 while(nhr->nhr_Node.ln_Succ)
2268 KPRINTF(1, ("Report %ld:\n", nhr->nhr_ReportID));
2269 nhr->nhr_ItemIDBase = idnum;
2270 nhr->nhr_InItemCount = nhr->nhr_OutItemCount = nhr->nhr_FeatItemCount = 0;
2271 nhc = (struct NepHidCollection *) nhr->nhr_Collections.lh_Head;
2272 while(nhc->nhc_Node.ln_Succ)
2274 KPRINTF(1, (" Collection %s:\n", nhc->nhc_Name));
2275 nhi = (struct NepHidItem *) nhc->nhc_Items.lh_Head;
2276 while(nhi->nhi_Node.ln_Succ)
2278 switch(nhi->nhi_Type)
2280 case REPORT_MAIN_INPUT:
2281 KPRINTF(1, (" Input Item %lx:\n", nhi->nhi_Usage));
2282 nhr->nhr_InItemCount++;
2283 break;
2285 case REPORT_MAIN_OUTPUT:
2286 KPRINTF(1, (" Output Item %lx:\n", nhi->nhi_Usage));
2287 nhr->nhr_OutItemCount++;
2288 break;
2290 case REPORT_MAIN_FEATURE:
2291 KPRINTF(1, (" Feature Item %lx:\n", nhi->nhi_Usage));
2292 nhr->nhr_FeatItemCount++;
2293 break;
2296 // generate id numbers
2297 SET_WTYPE(&nhi->nhi_ActionList, idnum++);
2298 if(!(nhi->nhi_Flags & RPF_MAIN_VARIABLE))
2300 alistptr = nhi->nhi_ActionMap;
2301 count = nhi->nhi_MapSize;
2304 SET_WTYPE(alistptr, idnum++);
2305 alistptr++;
2306 } while(--count);
2309 nhi = (struct NepHidItem *) nhi->nhi_Node.ln_Succ;
2311 nhc = (struct NepHidCollection *) nhc->nhc_Node.ln_Succ;
2313 /*psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
2314 "R=%02lx: %ld input items, %ld output items, %ld feature items, %ld items total!",
2315 nhr->nhr_ReportID, nhr->nhr_InItemCount, nhr->nhr_OutItemCount, nhr->nhr_FeatItemCount,
2316 idnum-1);*/
2317 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
2320 /* Create quick item lookup table */
2321 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
2322 while(nhr->nhr_Node.ln_Succ)
2324 KPRINTF(1, ("Report %ld, allocating %ld/%ld/%ld items\n",
2325 nhr->nhr_ReportID,
2326 nhr->nhr_InItemCount, nhr->nhr_OutItemCount, nhr->nhr_FeatItemCount));
2327 if((nhiptr = psdAllocVec(sizeof(struct NepHidItem *) * (nhr->nhr_InItemCount +
2328 nhr->nhr_OutItemCount + nhr->nhr_FeatItemCount))))
2330 nhiinptr = nhr->nhr_InItemMap = nhiptr;
2331 nhioutptr = nhr->nhr_OutItemMap = &nhiptr[nhr->nhr_InItemCount];
2332 nhifeatptr = nhr->nhr_FeatItemMap = &nhioutptr[nhr->nhr_OutItemCount];
2333 nhc = (struct NepHidCollection *) nhr->nhr_Collections.lh_Head;
2334 while(nhc->nhc_Node.ln_Succ)
2336 nhi = (struct NepHidItem *) nhc->nhc_Items.lh_Head;
2338 while(nhi->nhi_Node.ln_Succ)
2340 /* Add quick lookup entry */
2341 switch(nhi->nhi_Type)
2343 case REPORT_MAIN_INPUT:
2344 *nhiinptr++ = nhi;
2345 nch->nch_HasInItems = TRUE;
2346 break;
2348 case REPORT_MAIN_OUTPUT:
2349 *nhioutptr++ = nhi;
2350 break;
2352 case REPORT_MAIN_FEATURE:
2353 *nhifeatptr++ = nhi;
2354 break;
2356 nhi = (struct NepHidItem *) nhi->nhi_Node.ln_Succ;
2358 nhc = (struct NepHidCollection *) nhc->nhc_Node.ln_Succ;
2360 } else {
2361 res = FALSE;
2363 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
2366 nLoadActionConfig(nch);
2368 return(res);
2370 /* \\\ */
2372 /* /// "nLoadActionConfig()" */
2373 void nLoadActionConfig(struct NepClassHid *nch)
2375 struct NepHidReport *nhr;
2376 struct NepHidCollection *nhc;
2377 struct NepHidItem *nhi;
2379 ULONG count;
2380 struct List *alistptr;
2381 ULONG *usageptr;
2382 struct PsdIFFContext *pic;
2383 struct PsdIFFContext *rppic;
2385 pic = psdGetUsbDevCfg(GM_UNIQUENAME(libname), nch->nch_DevIDString, nch->nch_IfIDString);
2386 if(pic)
2388 nch->nch_LastCfgCRC = nCalcConfigCRC(nch, nch->nch_Base, pic);
2389 } else {
2390 nch->nch_LastCfgCRC = 0;
2393 /* Create default action mapping */
2394 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
2395 while(nhr->nhr_Node.ln_Succ)
2397 KPRINTF(1, ("Report %ld:\n", nhr->nhr_ReportID));
2398 if(pic)
2400 rppic = psdFindCfgForm(pic, MAKE_ID('R','P','T','0')+nhr->nhr_ReportID);
2401 } else {
2402 rppic = NULL;
2404 nhc = (struct NepHidCollection *) nhr->nhr_Collections.lh_Head;
2405 while(nhc->nhc_Node.ln_Succ)
2407 KPRINTF(1, (" Collection %s:\n", nhc->nhc_Name));
2408 nhi = (struct NepHidItem *) nhc->nhc_Items.lh_Head;
2409 while(nhi->nhi_Node.ln_Succ)
2411 usageptr = &nhi->nhi_Usage;
2412 alistptr = &nhi->nhi_ActionList;
2413 if(rppic)
2415 if(!(nLoadItem(nch, rppic, alistptr, nhr->nhr_ItemIDBase)))
2417 nDetectDefaultAction(nch, nhi, alistptr, nhc, *usageptr);
2419 } else {
2420 nDetectDefaultAction(nch, nhi, alistptr, nhc, *usageptr);
2423 if(nhi->nhi_Flags & RPF_MAIN_VARIABLE)
2425 KPRINTF(1, (" Variable %lx: %s\n", nhi->nhi_Usage, nNumToStr(nch, NTS_USAGEID, nhi->nhi_Usage, "unknown")));
2426 } else {
2427 usageptr = nhi->nhi_UsageMap;
2428 alistptr = nhi->nhi_ActionMap;
2429 count = nhi->nhi_MapSize;
2430 KPRINTF(1, (" Array %lx: %s\n", *usageptr, nNumToStr(nch, NTS_USAGEID, *usageptr, "unknown")));
2433 if(rppic)
2435 if(!(nLoadItem(nch, rppic, alistptr, nhr->nhr_ItemIDBase)))
2437 nDetectDefaultAction(nch, nhi, alistptr, nhc, *usageptr);
2439 } else {
2440 nDetectDefaultAction(nch, nhi, alistptr, nhc, *usageptr);
2442 alistptr++;
2443 usageptr++;
2444 } while(--count);
2446 nhi = (struct NepHidItem *) nhi->nhi_Node.ln_Succ;
2448 nhc = (struct NepHidCollection *) nhc->nhc_Node.ln_Succ;
2450 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
2453 /* \\\ */
2455 /* /// "nDebugMem()" */
2456 void nDebugMem(struct NepClassHid *nch, UBYTE *rptr, ULONG rptlen)
2458 char fmtstr[108];
2459 STRPTR fmtptr;
2460 UWORD cnt;
2461 UWORD pos = 0;
2463 while(rptlen)
2465 fmtptr = fmtstr;
2466 cnt = 16;
2467 *fmtptr++ = '%';
2468 *fmtptr++ = '0';
2469 *fmtptr++ = '4';
2470 *fmtptr++ = 'l';
2471 *fmtptr++ = 'x';
2472 *fmtptr++ = ':';
2473 *fmtptr++ = ' ';
2476 *fmtptr++ = '%';
2477 *fmtptr++ = '0';
2478 *fmtptr++ = '2';
2479 *fmtptr++ = 'l';
2480 *fmtptr++ = 'x';
2481 if(--cnt)
2483 *fmtptr++ = ' ';
2485 --rptlen;
2486 } while(cnt && rptlen);
2487 *fmtptr = 0;
2488 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), fmtstr, pos,
2489 rptr[0], rptr[1], rptr[2], rptr[3], rptr[4], rptr[5], rptr[6], rptr[7],
2490 rptr[8], rptr[9], rptr[10], rptr[11], rptr[12], rptr[13], rptr[14], rptr[15]);
2491 rptr += 16;
2492 pos += 16;
2495 /* \\\ */
2497 /* /// "nDebugReport()" */
2498 void nDebugReport(struct NepClassHid *nch, struct NepHidReport *nhr)
2500 UBYTE *rptr;
2501 ULONG rptlen;
2502 if(!nhr)
2504 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname), "Can't debug HID Report: nhr=NULL!\n");
2505 return;
2507 rptr = nhr->nhr_ReportBuf;
2508 rptlen = nhr->nhr_ReportLength;
2509 if(!rptr)
2511 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname), "Can't debug HID Report: ReportBuf=NULL!\n");
2512 return;
2515 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2516 "HID Report %02lx Debug (%ld bytes):", nhr->nhr_ReportID, rptlen);
2517 nDebugMem(nch, rptr, rptlen);
2519 /* \\\ */
2521 /* /// "nParseReport()" */
2522 BOOL nParseReport(struct NepClassHid *nch, struct NepHidReport *nhr)
2524 UBYTE *rptr = nhr->nhr_ReportBuf;
2525 UBYTE *rptrend = &nhr->nhr_ReportBuf[nhr->nhr_ReportLength];
2526 struct NepHidCollection *nhc = NULL;
2527 struct Node *node;
2528 UWORD itag;
2529 UWORD isize;
2530 UWORD itype;
2531 ULONG len = 0;
2532 LONG data = 0;
2533 ULONG udata = 0;
2534 ULONG usageid, designid, stringid;
2535 ULONG usagemin, usagemax;
2536 ULONG designmin, designmax;
2537 ULONG stringmin, stringmax;
2538 ULONG reportid = 0;
2539 ULONG bitpos = 0;
2540 LONG count;
2541 UWORD delim = 0;
2542 ULONG reportpos;
2544 NewList(&nch->nch_HidStack);
2545 NewList(&nch->nch_HidUsages);
2546 NewList(&nch->nch_HidDesigns);
2547 NewList(&nch->nch_HidStrings);
2549 nch->nch_HidGlobal.nhg_UsagePage =
2550 nch->nch_HidGlobal.nhg_LogicalMin =
2551 nch->nch_HidGlobal.nhg_LogicalMax =
2552 nch->nch_HidGlobal.nhg_PhysicalMin =
2553 nch->nch_HidGlobal.nhg_PhysicalMax =
2554 nch->nch_HidGlobal.nhg_UnitExp =
2555 nch->nch_HidGlobal.nhg_Unit = HID_PARAM_UNDEF;
2557 nch->nch_HidGlobal.nhg_ReportID =
2558 nch->nch_HidGlobal.nhg_ReportSize =
2559 nch->nch_HidGlobal.nhg_ReportCount = 0;
2561 usagemin = usagemax =
2562 designmin = designmax =
2563 stringmin = stringmax = HID_PARAM_UNDEF;
2565 KPRINTF(1, ("Starting parsing...\n"));
2566 /* Parse the items */
2567 while(rptr && (rptr < rptrend))
2569 reportpos = ((IPTR) rptr) - ((IPTR) nhr->nhr_ReportBuf);
2570 itag = *rptr & REPORT_ITAG_MASK;
2571 isize = *rptr & REPORT_ISIZE_MASK;
2572 itype = *rptr & REPORT_ITYPE_MASK;
2573 if(*rptr++ == REPORT_LONGITEM) /* Is this a long item? */
2575 len = *rptr++;
2576 itag = *rptr++;
2577 rptr += len;
2578 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2579 "HID Error at %04lx: Long items (%lx, len=%ld) are not specified in the spec!", reportpos, itag, len);
2580 } else {
2581 switch(isize)
2583 case REPORT_ISIZE_0:
2584 len = 0;
2585 udata = data = 0;
2586 break;
2588 case REPORT_ISIZE_1:
2589 len = 1;
2590 data = *((BYTE *) rptr);
2591 udata = *rptr++;
2592 break;
2594 case REPORT_ISIZE_2:
2595 len = 2;
2596 udata = data = *rptr++;
2597 data |= (*((BYTE *) rptr))<<8;
2598 udata |= (*rptr++)<<8;
2599 break;
2601 case REPORT_ISIZE_4:
2602 len = 4;
2603 data = *rptr++;
2604 data |= (*rptr++)<<8;
2605 data |= (*rptr++)<<16;
2606 data |= (*rptr++)<<24;
2607 udata = data;
2608 break;
2611 switch(itype)
2613 case REPORT_ITYPE_MAIN:
2614 //KPRINTF(1, ("Main "));
2615 if(reportid != nch->nch_HidGlobal.nhg_ReportID)
2617 struct NepHidReport *oldnhr = nhr;
2618 if(reportid)
2620 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
2621 while(nhr->nhr_Node.ln_Succ)
2623 if(nhr->nhr_ReportID == nch->nch_HidGlobal.nhg_ReportID)
2625 break;
2627 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
2629 if(!nhr->nhr_Node.ln_Succ)
2631 if((nhr = psdAllocVec(sizeof(struct NepHidReport))))
2633 KPRINTF(1, ("Generating new report ID %ld\n", nch->nch_HidGlobal.nhg_ReportID));
2634 NewList(&nhr->nhr_Collections);
2635 nhr->nhr_ReportID = nch->nch_HidGlobal.nhg_ReportID;
2636 AddTail(&nch->nch_HidReports, &nhr->nhr_Node);
2637 } else {
2638 KPRINTF(1, ("Out of memory creating new report.\n"));
2639 rptr = NULL;
2640 break;
2642 } else {
2643 KPRINTF(1, ("Switched back to report ID %ld\n", nch->nch_HidGlobal.nhg_ReportID));
2645 if(nhc)
2647 KPRINTF(1, ("Collection open, checking need for cloning.\n"));
2648 if(nhc->nhc_Items.lh_Head->ln_Succ)
2650 struct NepHidCollection *tmpnhc;
2651 struct NepHidCollection *newnhc;
2652 struct NepHidCollection *childnhc = NULL;
2654 KPRINTF(1, ("Not empty, assigning collection to current report and cloning!\n"));
2655 tmpnhc = nhc;
2656 nhc = NULL;
2659 KPRINTF(1, ("Cloning %08lx (%s)\n", tmpnhc, tmpnhc->nhc_Name));
2660 if((newnhc = psdAllocVec(sizeof(struct NepHidCollection))))
2662 if(!nhc)
2664 nhc = newnhc;
2666 NewList(&newnhc->nhc_Items);
2667 if(childnhc)
2669 childnhc->nhc_Parent = newnhc;
2671 newnhc->nhc_Usage = tmpnhc->nhc_Usage;
2672 newnhc->nhc_Name = psdCopyStr(tmpnhc->nhc_Name);
2673 } else {
2674 KPRINTF(10, ("Out of memory cloning nhc!\n"));
2675 break;
2677 AddTail(&oldnhr->nhr_Collections, &tmpnhc->nhc_Node);
2678 tmpnhc->nhc_Report = oldnhr;
2679 childnhc = newnhc;
2680 } while((tmpnhc = nhc->nhc_Parent));
2683 } else {
2684 KPRINTF(1, ("Setting first report ID %ld\n", nch->nch_HidGlobal.nhg_ReportID));
2685 nhr->nhr_ReportID = nch->nch_HidGlobal.nhg_ReportID;
2687 reportid = nch->nch_HidGlobal.nhg_ReportID;
2689 switch(itag)
2691 case REPORT_MAIN_INPUT:
2692 bitpos = nhr->nhr_ReportInSize;
2693 break;
2694 case REPORT_MAIN_OUTPUT:
2695 bitpos = nhr->nhr_ReportOutSize;
2696 break;
2697 case REPORT_MAIN_FEATURE:
2698 bitpos = nhr->nhr_ReportFeatSize;
2699 break;
2701 switch(itag)
2703 case REPORT_MAIN_INPUT:
2704 case REPORT_MAIN_OUTPUT:
2705 case REPORT_MAIN_FEATURE:
2707 struct NepHidItem *nhi;
2708 struct NepHidUsage *nhu;
2709 BOOL fakelogmin = FALSE;
2710 BOOL fakelogmax = FALSE;
2711 if(!delim)
2713 KPRINTF(1, ("%s (%lx)\n", (itag == REPORT_MAIN_INPUT) ? "Input" : ((itag == REPORT_MAIN_OUTPUT) ? "Output" : "Feature"), udata));
2714 if(!nhc)
2716 KPRINTF(10, ("No collection open!\n"));
2717 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
2718 "HID Error at %04lx: No collection open!", reportpos);
2719 nDebugReport(nch, nhr);
2720 rptr = NULL;
2721 break;
2723 if(nch->nch_HidGlobal.nhg_LogicalMin == HID_PARAM_UNDEF)
2725 nch->nch_HidGlobal.nhg_LogicalMin = 0;
2726 fakelogmin = TRUE;
2727 if(nch->nch_HidGlobal.nhg_LogicalMax == HID_PARAM_UNDEF)
2729 fakelogmax = TRUE;
2730 if(nch->nch_HidGlobal.nhg_ReportSize < 32)
2732 nch->nch_HidGlobal.nhg_LogicalMax = (1UL<<nch->nch_HidGlobal.nhg_ReportSize)-1;
2733 } else {
2734 nch->nch_HidGlobal.nhg_LogicalMin = 0x80000000;
2735 nch->nch_HidGlobal.nhg_LogicalMax = 0x7fffffff;
2737 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2738 "HID Error at %04lx: LogicalMin and Max for item missing, assuming %ld-%ld (%ld)!",
2739 reportpos,
2740 nch->nch_HidGlobal.nhg_LogicalMin,
2741 nch->nch_HidGlobal.nhg_LogicalMax);
2742 } else {
2743 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2744 "HID Error at %04lx: LogicalMin for item missing, assuming 0!", reportpos);
2747 else if(nch->nch_HidGlobal.nhg_LogicalMax == HID_PARAM_UNDEF)
2749 fakelogmax = TRUE;
2750 nch->nch_HidGlobal.nhg_LogicalMax = (1UL<<nch->nch_HidGlobal.nhg_ReportSize)-1;
2751 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2752 "HID Error at %04lx: LogicalMax for item missing, assuming %ld!", reportpos, nch->nch_HidGlobal.nhg_LogicalMax);
2755 if((nch->nch_HidGlobal.nhg_UsagePage == HID_PARAM_UNDEF) ||
2756 //(nch->nch_HidGlobal.nhg_LogicalMin == HID_PARAM_UNDEF) ||
2757 //(nch->nch_HidGlobal.nhg_LogicalMax == HID_PARAM_UNDEF) ||
2758 (!nch->nch_HidGlobal.nhg_ReportSize)// ||
2759 //(!nch->nch_HidGlobal.nhg_ReportCount) // ReportCount == 0 seems to be a valid input (sigh), just avoid error message
2762 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2763 "HID Error at %04lx: Mandatory item missing!", reportpos);
2764 nDebugReport(nch, nhr);
2765 KPRINTF(10, ("Mandatory item missing!\n"));
2766 rptr = NULL;
2767 } else {
2768 ULONG *usageptr;
2769 struct List *alistptr;
2770 usageid = designid = stringid = HID_PARAM_UNDEF;
2771 if(udata & RPF_MAIN_VARIABLE)
2773 for(count = 0; count < nch->nch_HidGlobal.nhg_ReportCount; count++)
2775 nhu = (struct NepHidUsage *) nch->nch_HidDesigns.lh_Head;
2776 if(nhu->nhu_Node.ln_Succ)
2778 designid = nhu->nhu_Usage++;
2779 if(nhu->nhu_Usage > nhu->nhu_UsageMax)
2781 Remove(&nhu->nhu_Node);
2782 psdFreeVec(nhu);
2785 nhu = (struct NepHidUsage *) nch->nch_HidStrings.lh_Head;
2786 if(nhu->nhu_Node.ln_Succ)
2788 stringid = nhu->nhu_Usage++;
2789 if(nhu->nhu_Usage > nhu->nhu_UsageMax)
2791 Remove(&nhu->nhu_Node);
2792 psdFreeVec(nhu);
2795 nhu = (struct NepHidUsage *) nch->nch_HidUsages.lh_Head;
2796 if(nhu->nhu_Node.ln_Succ)
2798 usageid = nhu->nhu_Usage++;
2799 if(nhu->nhu_Usage > nhu->nhu_UsageMax)
2801 KPRINTF(1, ("Removing usage %08lx\n", nhu));
2802 Remove(&nhu->nhu_Node);
2803 psdFreeVec(nhu);
2806 if(usageid != HID_PARAM_UNDEF)
2808 if((nhi = psdAllocVec(sizeof(struct NepHidItem))))
2810 nhi->nhi_Collection = nhc;
2811 nhi->nhi_Type = itag;
2812 nhi->nhi_Flags = udata;
2813 nhi->nhi_Offset = bitpos;
2814 nhi->nhi_Size = nch->nch_HidGlobal.nhg_ReportSize;
2816 nhi->nhi_LogicalMin = nch->nch_HidGlobal.nhg_LogicalMin;
2817 nhi->nhi_LogicalMax = nch->nch_HidGlobal.nhg_LogicalMax;
2818 nhi->nhi_IsSigned = (nhi->nhi_LogicalMin < 0) || (nhi->nhi_LogicalMax < 0);
2819 nhi->nhi_PhysicalMin = nch->nch_HidGlobal.nhg_PhysicalMin;
2820 nhi->nhi_PhysicalMax = nch->nch_HidGlobal.nhg_PhysicalMax;
2821 nhi->nhi_UnitExp = nch->nch_HidGlobal.nhg_UnitExp;
2822 nhi->nhi_Unit = nch->nch_HidGlobal.nhg_Unit;
2823 nhi->nhi_Usage = usageid;
2824 nhi->nhi_DesignIndex = designid;
2825 nhi->nhi_StringIndex = stringid;
2826 NewList(&nhi->nhi_ActionList);
2827 AddTail(&nhc->nhc_Items, &nhi->nhi_Node);
2828 KPRINTF(1, ("New Variable Item: %ld.%ld (%ld-%ld) %lx\n",
2829 nhi->nhi_Offset>>3, nhi->nhi_Offset & 7,
2830 nhi->nhi_LogicalMin, nhi->nhi_LogicalMax,
2831 nhi->nhi_Usage));
2834 bitpos += nch->nch_HidGlobal.nhg_ReportSize;
2836 } else {
2837 nhu = (struct NepHidUsage *) nch->nch_HidUsages.lh_Head;
2838 if(nhu->nhu_Node.ln_Succ)
2840 if((nhi = psdAllocVec(sizeof(struct NepHidItem))))
2842 nhi->nhi_Collection = nhc;
2843 nhi->nhi_Type = itag;
2844 nhi->nhi_Flags = udata;
2845 nhi->nhi_Offset = bitpos;
2846 nhi->nhi_Size = nch->nch_HidGlobal.nhg_ReportSize;
2847 nhi->nhi_Count = nch->nch_HidGlobal.nhg_ReportCount;
2849 nhi->nhi_LogicalMin = nch->nch_HidGlobal.nhg_LogicalMin;
2850 nhi->nhi_LogicalMax = nch->nch_HidGlobal.nhg_LogicalMax;
2852 nhi->nhi_MapSize = (nhi->nhi_LogicalMax - nhi->nhi_LogicalMin)+1;
2853 nhi->nhi_UsageMap = psdAllocVec(sizeof(ULONG) * nhi->nhi_MapSize);
2854 nhi->nhi_ActionMap = psdAllocVec(sizeof(struct List) * nhi->nhi_MapSize);
2855 nhi->nhi_Buffer = psdAllocVec(2 * sizeof(LONG) * nhi->nhi_Count);
2856 nhi->nhi_OldBuffer = &nhi->nhi_Buffer[nhi->nhi_Count];
2857 nhi->nhi_PhysicalMin = nch->nch_HidGlobal.nhg_PhysicalMin;
2858 nhi->nhi_PhysicalMax = nch->nch_HidGlobal.nhg_PhysicalMax;
2859 nhi->nhi_UnitExp = nch->nch_HidGlobal.nhg_UnitExp;
2860 nhi->nhi_Unit = nch->nch_HidGlobal.nhg_Unit;
2862 usageptr = nhi->nhi_UsageMap;
2863 alistptr = nhi->nhi_ActionMap;
2864 if(!(usageptr && alistptr && nhi->nhi_Buffer))
2866 psdFreeVec(usageptr);
2867 psdFreeVec(alistptr);
2868 psdFreeVec(nhi->nhi_Buffer);
2869 psdFreeVec(nhi);
2870 KPRINTF(10, ("Out of memory\n"));
2871 rptr = NULL;
2872 break;
2875 nhi->nhi_Usage = nhi->nhi_DesignIndex = nhi->nhi_StringIndex = HID_PARAM_UNDEF;
2876 NewList(&nhi->nhi_ActionList);
2878 KPRINTF(1, ("New Array(%ld*%ld) Item: %ld.%ld (%ld-%ld)\n",
2879 nhi->nhi_Count, nhi->nhi_MapSize,
2880 nhi->nhi_Offset>>3, nhi->nhi_Offset & 7,
2881 nhi->nhi_LogicalMin, nhi->nhi_LogicalMax));
2883 nhi->nhi_SameUsages = TRUE;
2884 for (count = nhi->nhi_MapSize; count; count--)
2886 nhu = (struct NepHidUsage *) nch->nch_HidDesigns.lh_Head;
2887 if(nhu->nhu_Node.ln_Succ)
2889 designid = nhu->nhu_Usage++;
2890 if(nhu->nhu_Usage > nhu->nhu_UsageMax)
2892 Remove(&nhu->nhu_Node);
2893 psdFreeVec(nhu);
2896 nhu = (struct NepHidUsage *) nch->nch_HidStrings.lh_Head;
2897 if(nhu->nhu_Node.ln_Succ)
2899 stringid = nhu->nhu_Usage++;
2900 if(nhu->nhu_Usage > nhu->nhu_UsageMax)
2902 Remove(&nhu->nhu_Node);
2903 psdFreeVec(nhu);
2906 nhu = (struct NepHidUsage *) nch->nch_HidUsages.lh_Head;
2907 if(nhu->nhu_Node.ln_Succ)
2909 usageid = nhu->nhu_Usage++;
2910 if(nhu->nhu_Usage > nhu->nhu_UsageMax)
2912 KPRINTF(1, ("Removing usage %08lx\n", nhu));
2913 Remove(&nhu->nhu_Node);
2914 psdFreeVec(nhu);
2918 // check if usages are all the same
2919 if(count < nhi->nhi_MapSize)
2921 if(usageid != usageptr[-1])
2923 nhi->nhi_SameUsages = FALSE;
2927 *usageptr++ = usageid;
2928 NewList(alistptr);
2929 alistptr++;
2932 if(nhi->nhi_SameUsages)
2934 // if it's all the same, we can assign a usage id to this array
2935 nhi->nhi_Usage = nhi->nhi_UsageMap[0];
2937 if(nhi->nhi_MapSize)
2939 AddTail(&nhc->nhc_Items, &nhi->nhi_Node);
2942 } /* FIXME: Clean string/delimiter stack if no usage? */
2943 bitpos += nch->nch_HidGlobal.nhg_ReportSize * nch->nch_HidGlobal.nhg_ReportCount;
2946 if(fakelogmin)
2948 nch->nch_HidGlobal.nhg_LogicalMin = HID_PARAM_UNDEF;
2950 if(fakelogmax)
2952 nch->nch_HidGlobal.nhg_LogicalMax = HID_PARAM_UNDEF;
2954 break;
2957 case REPORT_MAIN_COLLECT:
2959 struct NepHidUsage *nhu;
2960 struct NepHidCollection *oldnhc = nhc;
2961 KPRINTF(1, ("Collection(%lx)\n", udata));
2962 if((nhc = psdAllocVec(sizeof(struct NepHidCollection))))
2964 NewList(&nhc->nhc_Items);
2965 nhc->nhc_Parent = oldnhc;
2966 nhu = (struct NepHidUsage *) nch->nch_HidUsages.lh_Head;
2967 if(nhu->nhu_Node.ln_Succ)
2969 nhc->nhc_Usage = nhu->nhu_Usage;
2970 nhc->nhc_Name = nGetUsageName(nch, nhu->nhu_Usage);
2971 } else {
2972 if(nhc->nhc_Parent)
2974 nhc->nhc_Usage = nhc->nhc_Parent->nhc_Usage;
2975 nhc->nhc_Name = psdCopyStr(nhc->nhc_Parent->nhc_Name);
2976 } else {
2977 nhc->nhc_Name = psdCopyStr("Argl!");
2981 node = nch->nch_HidUsages.lh_Head;
2982 while(node->ln_Succ)
2984 KPRINTF(1, ("Removing usage %08lx\n", node));
2985 Remove(node);
2986 psdFreeVec(node);
2987 node = nch->nch_HidUsages.lh_Head;
2990 break;
2993 case REPORT_MAIN_ENDCOLL:
2994 KPRINTF(1, ("EndCollection(%lx)\n", udata));
2995 if(nhc)
2997 /* Get rid of empty collection */
2998 //if(!nhc->nhc_Items.lh_Head->ln_Succ)
2999 if(0) /* don't do this, we might need the parent collection! */
3001 struct NepHidCollection *oldnhc = nhc;
3002 KPRINTF(1, ("Deleting empty collection %lx (%s)\n", nhc, nhc->nhc_Name));
3003 nhc = nhc->nhc_Parent;
3004 psdFreeVec(oldnhc->nhc_Name);
3005 psdFreeVec(oldnhc);
3006 } else {
3007 AddTail(&nhr->nhr_Collections, &nhc->nhc_Node);
3008 nhc->nhc_Report = nhr;
3009 nhc = nhc->nhc_Parent;
3012 break;
3014 default:
3015 KPRINTF(1, ("Reserved_%02lx(%lx)\n", itag, data));
3016 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
3017 "HID Error at %04lx: Reserved_MAIN_%02lx(%lx)", reportpos, itag, data);
3018 nDebugReport(nch, nhr);
3019 rptr = NULL;
3020 break;
3022 /* Remove remaining usages */
3023 node = nch->nch_HidUsages.lh_Head;
3024 while(node->ln_Succ)
3026 KPRINTF(1, ("MainEnd: Removing usage %08lx\n", node));
3027 Remove(node);
3028 psdFreeVec(node);
3029 node = nch->nch_HidUsages.lh_Head;
3031 /* Remove remaining designators */
3032 node = nch->nch_HidDesigns.lh_Head;
3033 while(node->ln_Succ)
3035 KPRINTF(1, ("MainEnd: Removing designator %08lx\n", node));
3036 Remove(node);
3037 psdFreeVec(node);
3038 node = nch->nch_HidDesigns.lh_Head;
3040 /* Remove remaining strings */
3041 node = nch->nch_HidStrings.lh_Head;
3042 while(node->ln_Succ)
3044 KPRINTF(1, ("MainEnd: Removing strings %08lx\n", node));
3045 Remove(node);
3046 psdFreeVec(node);
3047 node = nch->nch_HidStrings.lh_Head;
3050 switch(itag)
3052 case REPORT_MAIN_INPUT:
3053 nhr->nhr_ReportInSize = bitpos;
3054 break;
3055 case REPORT_MAIN_OUTPUT:
3056 nhr->nhr_ReportOutSize = bitpos;
3057 break;
3058 case REPORT_MAIN_FEATURE:
3059 nhr->nhr_ReportFeatSize = bitpos;
3060 break;
3063 break;
3065 case REPORT_ITYPE_GLOBAL:
3066 //KPRINTF(1, ("Global "));
3067 switch(itag)
3069 case REPORT_GLOB_USAGE:
3070 KPRINTF(1, ("Usage Page(%ld) %s\n", udata, nNumToStr(nch, NTS_USAGEPAGE, udata, "unknown")));
3071 nch->nch_HidGlobal.nhg_UsagePage = udata;
3072 break;
3074 case REPORT_GLOB_LOGMIN:
3075 KPRINTF(1, ("LogMin(%ld)\n", data));
3076 nch->nch_HidGlobal.nhg_LogicalMin = data;
3077 break;
3079 case REPORT_GLOB_LOGMAX:
3080 KPRINTF(1, ("LogMax(%ld)\n", data));
3081 nch->nch_HidGlobal.nhg_LogicalMax = data;
3082 break;
3084 case REPORT_GLOB_PHYMIN:
3085 KPRINTF(1, ("PhyMin(%ld)\n", data));
3086 nch->nch_HidGlobal.nhg_PhysicalMin = data;
3087 break;
3089 case REPORT_GLOB_PHYMAX:
3090 KPRINTF(1, ("PhyMax(%ld)\n", data));
3091 nch->nch_HidGlobal.nhg_PhysicalMax = data;
3092 break;
3094 case REPORT_GLOB_UNITEXP:
3095 KPRINTF(1, ("UnitExp(%ld)\n", data));
3096 nch->nch_HidGlobal.nhg_UnitExp = data;
3097 break;
3099 case REPORT_GLOB_UNIT:
3100 KPRINTF(1, ("Unit(%ld)\n", data));
3101 nch->nch_HidGlobal.nhg_Unit = data;
3102 break;
3104 case REPORT_GLOB_RPSIZE:
3105 KPRINTF(1, ("ReportSize(%ld)\n", udata));
3106 nch->nch_HidGlobal.nhg_ReportSize = udata;
3107 break;
3109 case REPORT_GLOB_RPID:
3110 KPRINTF(1, ("ReportID(%ld)\n", udata));
3111 nch->nch_HidGlobal.nhg_ReportID = udata;
3112 break;
3114 case REPORT_GLOB_RPCOUNT:
3115 KPRINTF(1, ("ReportCount(%ld)\n", udata));
3116 nch->nch_HidGlobal.nhg_ReportCount = udata;
3117 break;
3119 case REPORT_GLOB_PUSH:
3121 struct NepHidGlobal *nhg = psdAllocVec(sizeof(struct NepHidGlobal));
3122 KPRINTF(1, ("Push(%ld)\n", data));
3123 if(nhg)
3125 *nhg = nch->nch_HidGlobal;
3126 AddTail(&nch->nch_HidStack, &nhg->nhg_Node);
3127 } else {
3128 KPRINTF(10, ("Out of HID stack memory!\n"));
3129 rptr = NULL;
3131 break;
3134 case REPORT_GLOB_POP:
3136 struct NepHidGlobal *nhg = (struct NepHidGlobal *) nch->nch_HidStack.lh_Tail;
3137 KPRINTF(1, ("Pop(%ld)\n", data));
3138 if(nhg->nhg_Node.ln_Pred)
3140 nch->nch_HidGlobal = *nhg;
3141 Remove(&nhg->nhg_Node);
3142 psdFreeVec(nhg);
3143 } else {
3144 KPRINTF(10, ("Pop from HID stack without push!\n"));
3145 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
3146 "HID Error at %04lx: Pop from HID stack without push!", reportpos);
3147 nDebugReport(nch, nhr);
3148 rptr = NULL;
3150 break;
3153 default:
3154 KPRINTF(1, ("Reserved_%02lx(%lx)\n", itag, data));
3155 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
3156 "HID Error at %04lx: Reserved_GLOBAL_%02lx(%lx)", reportpos, itag, data);
3157 nDebugReport(nch, nhr);
3158 rptr = NULL;
3159 break;
3161 break;
3163 case REPORT_ITYPE_LOCAL:
3164 //KPRINTF(1, ("Local "));
3165 switch(itag)
3167 case REPORT_LOCL_USAGE:
3168 if(len <= 2)
3170 udata |= nch->nch_HidGlobal.nhg_UsagePage<<16;
3172 KPRINTF(1, ("Usage (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3173 if(!nAddUsage(nch, &nch->nch_HidUsages, udata, udata))
3175 rptr = NULL;
3177 break;
3179 case REPORT_LOCL_USEMIN:
3180 if(len <= 2)
3182 udata |= nch->nch_HidGlobal.nhg_UsagePage<<16;
3184 KPRINTF(1, ("UsageMin (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3185 usagemin = udata;
3186 if(usagemax != HID_PARAM_UNDEF)
3188 if(!nAddUsage(nch, &nch->nch_HidUsages, usagemin, usagemax))
3190 rptr = NULL;
3192 usagemin = usagemax = HID_PARAM_UNDEF;
3194 break;
3196 case REPORT_LOCL_USEMAX:
3197 if(len <= 2)
3199 udata |= nch->nch_HidGlobal.nhg_UsagePage<<16;
3201 KPRINTF(1, ("UsageMax (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3202 usagemax = udata;
3203 if(usagemin != HID_PARAM_UNDEF)
3205 if(!nAddUsage(nch, &nch->nch_HidUsages, usagemin, usagemax))
3207 rptr = NULL;
3209 usagemin = usagemax = HID_PARAM_UNDEF;
3211 break;
3213 case REPORT_LOCL_DESIDX:
3214 KPRINTF(1, ("Designator index (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3215 if(!nAddUsage(nch, &nch->nch_HidDesigns, udata, udata))
3217 rptr = NULL;
3219 break;
3221 case REPORT_LOCL_DESMIN:
3222 KPRINTF(1, ("DesignMin (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3223 designmin = udata;
3224 if(designmax != HID_PARAM_UNDEF)
3226 if(!nAddUsage(nch, &nch->nch_HidDesigns, designmin, designmax))
3228 rptr = NULL;
3230 designmin = designmax = HID_PARAM_UNDEF;
3232 break;
3234 case REPORT_LOCL_DESMAX:
3235 KPRINTF(1, ("DesignMax (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3236 designmin = udata;
3237 if(designmax != HID_PARAM_UNDEF)
3239 if(!nAddUsage(nch, &nch->nch_HidDesigns, designmin, designmax))
3241 rptr = NULL;
3243 designmin = designmax = HID_PARAM_UNDEF;
3245 break;
3247 case REPORT_LOCL_STRIDX:
3248 KPRINTF(1, ("String index (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3249 if(!nAddUsage(nch, &nch->nch_HidStrings, udata, udata))
3251 rptr = NULL;
3253 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3254 "HID String Index %ld", udata);
3255 break;
3257 case REPORT_LOCL_STRMIN:
3258 KPRINTF(1, ("StringMin (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3259 stringmin = udata;
3260 if(stringmax != HID_PARAM_UNDEF)
3262 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3263 "HID String Index Range %ld - %ld", stringmin, stringmax);
3264 if(!nAddUsage(nch, &nch->nch_HidStrings, stringmin, stringmax))
3266 rptr = NULL;
3268 stringmin = stringmax = HID_PARAM_UNDEF;
3270 break;
3272 case REPORT_LOCL_STRMAX:
3273 KPRINTF(1, ("StringMax (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3274 stringmax = udata;
3275 if(stringmin != HID_PARAM_UNDEF)
3277 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3278 "HID String Index Range %ld - %ld", stringmin, stringmax);
3279 if(!nAddUsage(nch, &nch->nch_HidStrings, stringmin, stringmax))
3281 rptr = NULL;
3283 stringmin = stringmax = HID_PARAM_UNDEF;
3285 break;
3287 case REPORT_LOCL_DELIM:
3288 KPRINTF(1, ("Delimiter (%ld)\n", udata));
3289 if(udata)
3291 delim++;
3292 } else {
3293 delim--;
3295 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "HID Report Delimiters not really supported!");
3296 break;
3298 default:
3299 KPRINTF(1, ("Reserved_%02lx(%lx)\n", itag, udata));
3300 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
3301 "HID Error at %04lx: Reserved_LOCAL_%02lx(%lx)", reportpos, itag, udata);
3302 nDebugReport(nch, nhr);
3303 rptr = NULL;
3304 break;
3306 break;
3308 default:
3309 KPRINTF(1, ("Reserved!\n"));
3310 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
3311 "HID Error at %04lx: Reserved_%02lx", reportpos, itag);
3312 nDebugReport(nch, nhr);
3313 rptr = NULL;
3314 break;
3317 KPRINTF(1, ("Parsing done, status %lx.\n", rptr));
3319 /* Remove remaining stack frame */
3320 node = nch->nch_HidStack.lh_Head;
3321 while(node->ln_Succ)
3323 KPRINTF(1, ("Removing stack frame %08lx\n", node));
3324 Remove(node);
3325 psdFreeVec(node);
3326 node = nch->nch_HidStack.lh_Head;
3328 /* Remove remaining usages */
3329 node = nch->nch_HidUsages.lh_Head;
3330 while(node->ln_Succ)
3332 KPRINTF(1, ("Removing usage %08lx\n", node));
3333 Remove(node);
3334 psdFreeVec(node);
3335 node = nch->nch_HidUsages.lh_Head;
3337 /* Remove remaining designators */
3338 node = nch->nch_HidDesigns.lh_Head;
3339 while(node->ln_Succ)
3341 KPRINTF(1, ("Removing designator %08lx\n", node));
3342 Remove(node);
3343 psdFreeVec(node);
3344 node = nch->nch_HidDesigns.lh_Head;
3346 /* Remove remaining strings */
3347 node = nch->nch_HidStrings.lh_Head;
3348 while(node->ln_Succ)
3350 KPRINTF(1, ("Removing strings %08lx\n", node));
3351 Remove(node);
3352 psdFreeVec(node);
3353 node = nch->nch_HidStrings.lh_Head;
3355 //nDebugReport(nch, nhr);
3356 return((BOOL) (rptr ? TRUE : FALSE));
3358 /* \\\ */
3360 /* /// "nFindCollID()" */
3361 BOOL nFindCollID(struct NepClassHid *nch, struct NepHidCollection *nhc, ULONG collidmin, ULONG collidmax)
3365 if((nhc->nhc_Usage >= collidmin) && (nhc->nhc_Usage <= collidmax))
3367 return(TRUE);
3369 } while((nhc = nhc->nhc_Parent));
3370 return(FALSE);
3372 /* \\\ */
3374 /* /// "nFindItemID()" */
3375 struct NepHidItem * nFindItemID(struct NepClassHid *nch, UWORD id, UWORD itype, ULONG *pos)
3377 struct NepHidReport *nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
3378 struct NepHidItem *nhi;
3379 struct NepHidItem **nhiptr;
3380 struct List *alistptr;
3381 ULONG count;
3382 ULONG icount;
3383 BOOL featmode;
3385 if(itype == REPORT_MAIN_OUTPUT)
3387 featmode = FALSE;
3389 else if(itype == REPORT_MAIN_FEATURE)
3391 featmode = TRUE;
3392 } else {
3393 return(NULL);
3395 while(nhr->nhr_Node.ln_Succ)
3397 nhiptr = NULL;
3398 if(featmode)
3400 if((icount = nhr->nhr_FeatItemCount))
3402 nhiptr = nhr->nhr_FeatItemMap;
3404 } else {
3405 if((icount = nhr->nhr_OutItemCount))
3407 nhiptr = nhr->nhr_OutItemMap;
3410 if(nhiptr)
3414 nhi = *nhiptr++;
3415 if(GET_WTYPE(&nhi->nhi_ActionList) == id)
3417 *pos = 0xffffffff;
3418 return(nhi);
3420 if(!(nhi->nhi_Flags & RPF_MAIN_VARIABLE))
3422 alistptr = nhi->nhi_ActionMap;
3423 count = nhi->nhi_MapSize;
3426 if(GET_WTYPE(alistptr) == id)
3428 *pos = nhi->nhi_MapSize - count;
3429 return(nhi);
3431 alistptr++;
3432 } while(--count);
3435 while(--icount);
3437 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
3439 return(NULL);
3441 /* \\\ */
3443 /* /// "nFindItemUsage()" */
3444 UWORD nFindItemUsage(struct NepClassHid *nch, ULONG usage, UWORD itype)
3446 struct NepHidReport *nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
3447 struct NepHidItem *nhi;
3448 struct NepHidItem **nhiptr;
3449 ULONG *usageptr;
3450 struct List *alistptr;
3451 ULONG count;
3452 ULONG icount;
3453 BOOL featmode;
3455 if(itype == REPORT_MAIN_OUTPUT)
3457 featmode = FALSE;
3459 else if(itype == REPORT_MAIN_FEATURE)
3461 featmode = TRUE;
3462 } else {
3463 return(0);
3466 while(nhr->nhr_Node.ln_Succ)
3468 nhiptr = NULL;
3469 if(featmode)
3471 if((icount = nhr->nhr_FeatItemCount))
3473 nhiptr = nhr->nhr_FeatItemMap;
3475 } else {
3476 if((icount = nhr->nhr_OutItemCount))
3478 nhiptr = nhr->nhr_OutItemMap;
3481 if(nhiptr)
3485 nhi = *nhiptr++;
3486 if(nhi->nhi_Usage == usage)
3488 return(GET_WTYPE(&nhi->nhi_ActionList));
3490 if(!(nhi->nhi_Flags & RPF_MAIN_VARIABLE))
3492 usageptr = nhi->nhi_UsageMap;
3493 alistptr = nhi->nhi_ActionMap;
3494 count = nhi->nhi_MapSize;
3497 if(*usageptr == usage)
3499 return GET_WTYPE(alistptr);
3501 usageptr++;
3502 alistptr++;
3503 } while(--count);
3506 while(--icount);
3508 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
3510 return(0);
3512 /* \\\ */
3514 /* /// "UsbToPs2 Mapping" */
3515 const struct UsbToPs2Map usbtops2map[] =
3517 { 0x010081, 0x5e }, // System Power Down
3518 { 0x010082, 0x5f }, // System Sleep
3519 { 0x010083, 0x63 }, // System Wake Up
3521 { 0x070046, 0x4c }, // Keyboard Print Screen
3522 { 0x070047, 0x64 }, // Keyboard Scroll Lock
3523 { 0x070048, 0x45 }, // Keyboard Pause
3524 { 0x070049, 0x0a }, // Keyboard Insert
3526 { 0x070066, 0x5e }, // Keyboard Power
3528 { 0x07007A, 0x08 }, // Keyboard Undo
3529 { 0x07007B, 0x17 }, // Keyboard Cut
3530 { 0x07007C, 0x18 }, // Keyboard Copy
3531 { 0x07007D, 0x0a }, // Keyboard Paste
3532 { 0x07007F, 0x20 }, // Keyboard Mute
3533 { 0x070080, 0x30 }, // Keyboard Volume Up
3534 { 0x070081, 0x2e }, // Keyboard Volume Down
3536 { 0x0C0030, 0x5e }, // Power
3537 { 0x0C0032, 0x5f }, // Sleep
3538 { 0x0C0033, 0x5f }, // Sleep After
3539 { 0x0C0034, 0x5f }, // Sleep Mode
3541 { 0x0C0094, 0x40 }, // Quit
3542 { 0x0C0095, 0x3b }, // Help
3543 { 0x0C00B0, 0x22 }, // Play
3544 { 0x0C00B1, 0x22 }, // Pause
3545 { 0x0C00B5, 0x19 }, // Scan Next Track
3546 { 0x0C00B6, 0x10 }, // Scan Previous Track
3547 { 0x0C00B7, 0x24 }, // Stop
3548 { 0x0C00CC, 0x24 }, // Stop/Eject
3549 { 0x0C00CD, 0x22 }, // Play/Pause
3550 { 0x0C00CE, 0x22 }, // Play/Skip
3552 { 0x0C00E2, 0x20 }, // Mute
3553 { 0x0C00E9, 0x30 }, // Volume Increment
3554 { 0x0C00EA, 0x2e }, // Volume Decrement
3556 { 0x0C0183, 0x6d }, // AL Consumer Control Configuration
3557 { 0x0C0184, 0x13 }, // AL Word Processor
3558 { 0x0C0185, 0x13 }, // AL Text Editor
3559 { 0x0C0186, 0x14 }, // AL Spreadsheet
3560 { 0x0C018A, 0x6c }, // AL Email Reader
3561 { 0x0C018F, 0x3d }, // AL Task/Project Manager
3562 { 0x0C0192, 0x21 }, // AL Calculator
3563 { 0x0C0194, 0x3c }, // AL Local Machine Browser
3564 { 0x0C0196, 0x3c }, // AL Internet Browser
3565 { 0x0C019B, 0x16 }, // AL Logon
3566 { 0x0C019C, 0x16 }, // AL Logoff
3567 { 0x0C019D, 0x16 }, // AL Logon/Logoff
3568 { 0x0C01A1, 0x3d }, // AL Process/Task Manager
3569 { 0x0C01A3, 0x1e }, // AL Next Task/Application
3570 { 0x0C01A4, 0x09 }, // AL Previous Task/Application
3571 { 0x0C01A6, 0x3b }, // AL Integrated Help Center
3572 { 0x0C01A7, 0x6b }, // AL Documents
3573 { 0x0C01A8, 0x23 }, // AL Thesaurus
3574 { 0x0C01A9, 0x23 }, // AL Dictionary
3575 { 0x0C01AB, 0x23 }, // AL Spell Check
3576 { 0x0C01AC, 0x23 }, // AL Grammar Check
3577 { 0x0C01B4, 0x05 }, // AL File Browser
3578 { 0x0C01BD, 0x3b }, // AL OEM Features/ Tips/Tutorial Browser
3579 { 0x0C01BE, 0x3b }, // AL OEM Help
3581 { 0x0C0201, 0x3e }, // AC New
3582 { 0x0C0202, 0x3f }, // AC Open
3583 { 0x0C0203, 0x40 }, // AC Close
3584 { 0x0C0204, 0x40 }, // AC Exit
3585 { 0x0C0207, 0x57 }, // AC Save
3586 { 0x0C0208, 0x58 }, // AC Print
3587 { 0x0C021A, 0x08 }, // AC Undo
3588 { 0x0C021B, 0x18 }, // AC Copy
3589 { 0x0C021C, 0x17 }, // AC Cut
3590 { 0x0C021D, 0x0a }, // AC Paste
3591 { 0x0C021F, 0x65 }, // AC Find
3592 { 0x0C0220, 0x65 }, // AC Find and Replace
3593 { 0x0C0221, 0x65 }, // AC Search
3594 { 0x0C0223, 0x32 }, // AC Home
3595 { 0x0C0224, 0x6a }, // AC Back
3596 { 0x0C0225, 0x69 }, // AC Forward
3597 { 0x0C0226, 0x68 }, // AC Stop
3598 { 0x0C0227, 0x67 }, // AC Refresh
3599 { 0x0C0228, 0x6a }, // AC Previous Link
3600 { 0x0C0229, 0x69 }, // AC Next Link
3601 { 0x0C022A, 0x66 }, // AC Bookmarks
3602 { 0x0C022B, 0x66 }, // AC History
3603 { 0x0C022C, 0x66 }, // AC Subscriptions
3604 { 0x0C0279, 0x07 }, // AC Redo/Repeat
3605 { 0x0C0288, 0x43 }, // AC Send To
3606 { 0x0C0289, 0x41 }, // AC Reply
3607 { 0x0C028A, 0x41 }, // AC Reply All
3608 { 0x0C028B, 0x42 }, // AC Forward Msg
3609 { 0x0C028C, 0x43 }, // AC Send
3611 { 0x000000, 0x00 }
3613 /* \\\ */
3615 /* /// "nDetectDefaultAction()" */
3616 BOOL nDetectDefaultAction(struct NepClassHid *nch, struct NepHidItem *nhi, struct List *lst, struct NepHidCollection *nhc, ULONG uid)
3618 BOOL res = FALSE;
3619 UWORD usageid = uid;
3620 struct NepHidAction *nha;
3621 struct WacomCaps *wc;
3622 const struct UsbToPs2Map *utp = usbtops2map;
3624 switch(uid>>16)
3626 case 0x01: /* generic desktop page */
3627 if(usageid == 0xfff0) /* extra init */
3629 /* AipTek USB Tablets Support */
3630 IPTR vendid = 0;
3631 IPTR prodid = 0;
3632 ULONG command;
3633 ULONG data;
3635 psdGetAttrs(PGA_DEVICE, nch->nch_Device,
3636 DA_VendorID, &vendid,
3637 DA_ProductID, &prodid,
3638 TAG_END);
3639 if((vendid == 0x08ca) &&
3640 ((prodid == 0x0001) || (prodid == 0x0010) ||
3641 ((prodid >= 0x0020) && (prodid <= 0x0024))) &&
3642 (!nhi->nhi_ActionList.lh_Head->ln_Succ))
3644 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3645 "Generating special AipTek USB Tablet init sequence.");
3646 command = nFindItemUsage(nch, 0x0D003F, REPORT_MAIN_FEATURE);
3647 data = nFindItemUsage(nch, 0x0D0040, REPORT_MAIN_FEATURE);
3648 if(command && data)
3650 /* set resolution to 500DPI */
3651 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3653 nha->nha_FeatOp = HUAT_ASSIGN;
3654 nha->nha_FeatItem = command;
3655 nha->nha_ValEnable = TRUE;
3656 nha->nha_ValVar = HUAT_CONST;
3657 nha->nha_ValConst = 0x18;
3659 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3661 nha->nha_FeatOp = HUAT_ASSIGN;
3662 nha->nha_FeatItem = data;
3663 nha->nha_ValEnable = TRUE;
3664 nha->nha_ValVar = HUAT_CONST;
3665 nha->nha_ValConst = 0x04;
3667 if((nha = nAllocAction(nch, lst, HUA_MISC|HUA_ANY)))
3669 nha->nha_MiscMode = HUAT_FLUSHEVENTS;
3672 /* set absolute tablet mode */
3673 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3675 nha->nha_FeatOp = HUAT_ASSIGN;
3676 nha->nha_FeatItem = command;
3677 nha->nha_ValEnable = TRUE;
3678 nha->nha_ValVar = HUAT_CONST;
3679 nha->nha_ValConst = 0x10;
3681 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3683 nha->nha_FeatOp = HUAT_ASSIGN;
3684 nha->nha_FeatItem = data;
3685 nha->nha_ValEnable = TRUE;
3686 nha->nha_ValVar = HUAT_CONST;
3687 nha->nha_ValConst = 0x01;
3689 if((nha = nAllocAction(nch, lst, HUA_MISC|HUA_ANY)))
3691 nha->nha_MiscMode = HUAT_FLUSHEVENTS;
3694 /* enable macro keys */
3695 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3697 nha->nha_FeatOp = HUAT_ASSIGN;
3698 nha->nha_FeatItem = command;
3699 nha->nha_ValEnable = TRUE;
3700 nha->nha_ValVar = HUAT_CONST;
3701 nha->nha_ValConst = 0x11;
3703 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3705 nha->nha_FeatOp = HUAT_ASSIGN;
3706 nha->nha_FeatItem = data;
3707 nha->nha_ValEnable = TRUE;
3708 nha->nha_ValVar = HUAT_CONST;
3709 nha->nha_ValConst = 0x02;
3711 if((nha = nAllocAction(nch, lst, HUA_MISC|HUA_ANY)))
3713 nha->nha_MiscMode = HUAT_FLUSHEVENTS;
3716 /* enable auto gain */
3717 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3719 nha->nha_FeatOp = HUAT_ASSIGN;
3720 nha->nha_FeatItem = command;
3721 nha->nha_ValEnable = TRUE;
3722 nha->nha_ValVar = HUAT_CONST;
3723 nha->nha_ValConst = 0x12;
3725 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3727 nha->nha_FeatOp = HUAT_ASSIGN;
3728 nha->nha_FeatItem = data;
3729 nha->nha_ValEnable = TRUE;
3730 nha->nha_ValVar = HUAT_CONST;
3731 nha->nha_ValConst = 0xff;
3733 /*if((nha = nAllocAction(nch, lst, HUA_MISC|HUA_ANY)))
3735 nha->nha_MiscMode = HUAT_FLUSHEVENTS;
3737 } else {
3738 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
3739 "AipTek: No command (%ld) or data (%ld) feature!", command, data);
3742 if(vendid == 0x056a)
3744 for(wc = WacomCapsTable; wc->wc_ProdID != prodid; wc++)
3746 if(wc->wc_ProdID == 0xffff)
3748 wc = NULL;
3749 break;
3752 } else {
3753 wc = NULL;
3755 if(wc)
3757 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3758 "Generating special Wacom USB Tablet init sequence.");
3759 command = nFindItemUsage(nch, 0xff000001, REPORT_MAIN_FEATURE);
3760 if(command)
3762 /* activate returning of absolute tablet data */
3763 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3765 nha->nha_FeatOp = HUAT_ASSIGN;
3766 nha->nha_FeatItem = command;
3767 nha->nha_ValEnable = TRUE;
3768 nha->nha_ValVar = HUAT_CONST;
3769 nha->nha_ValConst = 0x02;
3771 if((nha = nAllocAction(nch, lst, HUA_MISC|HUA_ANY)))
3773 nha->nha_MiscMode = HUAT_FLUSHEVENTS;
3775 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3777 nha->nha_FeatOp = HUAT_ASSIGN;
3778 nha->nha_FeatItem = command;
3779 nha->nha_ValEnable = TRUE;
3780 nha->nha_ValVar = HUAT_CONST;
3781 nha->nha_ValConst = 0x02;
3786 if((vendid == 0x046d) &&
3787 (!nhi->nhi_ActionList.lh_Head->ln_Succ))
3789 command = nFindItemUsage(nch, 0xff000001, REPORT_MAIN_OUTPUT);
3790 if(command)
3792 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3793 "Adding special HID2HCI Logitech Bluetooth init sequence, but deactivated!");
3794 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3795 "This init sequence would disable HID usage and enable pure Bluetooth use!");
3796 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3797 "If you want to use this dongle for Bluetooth, switch the NOP-Startup-Actions to type Output!");
3798 // send three commands to output report 0x10
3799 if((nha = nAllocAction(nch, lst, HUA_NOP|HUA_ANY)))
3801 nha->nha_OutItem = command;
3802 strcpy(nha->nha_OutArray, "0xff, 0x80, 0x80, 0x01, 0x00, 0x00");
3804 if((nha = nAllocAction(nch, lst, HUA_MISC|HUA_ANY)))
3806 nha->nha_MiscMode = HUAT_FLUSHEVENTS;
3808 if((nha = nAllocAction(nch, lst, HUA_NOP|HUA_ANY)))
3810 nha->nha_OutItem = command;
3811 strcpy(nha->nha_OutArray, "0xff, 0x80, 0x00, 0x00, 0x30, 0x00");
3813 if((nha = nAllocAction(nch, lst, HUA_MISC|HUA_ANY)))
3815 nha->nha_MiscMode = HUAT_FLUSHEVENTS;
3817 if((nha = nAllocAction(nch, lst, HUA_NOP|HUA_ANY)))
3819 nha->nha_OutItem = command;
3820 strcpy(nha->nha_OutArray, "0xff, 0x81, 0x80, 0x00, 0x00, 0x00");
3826 if(nFindCollID(nch, nhc, 0x010002, 0x010002) || /* Mice */
3827 nFindCollID(nch, nhc, 0x0d0001, 0x0d000d)) /* Tablets */
3829 switch(usageid)
3831 case 0x30: /* Mouse X */
3832 if((nha = nAllocAction(nch, lst, HUA_MOUSEPOS|HUA_ALWAYS)))
3834 if(nhi->nhi_Flags & RPF_MAIN_RELATIVE)
3836 nha->nha_MouseAxis = HUAT_DELTAX;
3837 } else {
3838 nha->nha_MouseAxis = HUAT_ABSX;
3839 nha->nha_ClipEnable = TRUE;
3840 nha->nha_ClipMin = 5;
3841 nha->nha_ClipMax = 95;
3842 nha->nha_ClipStretch = TRUE;
3845 break;
3847 case 0x31: /* Mouse Y */
3848 if((nha = nAllocAction(nch, lst, HUA_MOUSEPOS|HUA_ALWAYS)))
3850 if(nhi->nhi_Flags & RPF_MAIN_RELATIVE)
3852 nha->nha_MouseAxis = HUAT_DELTAY;
3853 } else {
3854 nha->nha_MouseAxis = HUAT_ABSY;
3855 nha->nha_ClipEnable = TRUE;
3856 nha->nha_ClipMin = 5;
3857 nha->nha_ClipMax = 95;
3858 nha->nha_ClipStretch = TRUE;
3861 break;
3863 case 0x38: /* Wheel */
3864 if((nha = nAllocAction(nch, lst, HUA_WHEEL|HUA_ALWAYS)))
3866 nha->nha_WheelMode = HUAT_DELTAY;
3867 nha->nha_WheelDist = 1;
3869 break;
3873 if(nFindCollID(nch, nhc, 0x010004, 0x010005)) /* Joystick, Game Pad */
3875 switch(usageid)
3877 case 0x39: /* Hatswitch */
3878 if((nha = nAllocAction(nch, lst, HUA_DIGJOY|HUA_NAN)))
3880 nha->nha_JoypadOp = HUAT_CLEAR;
3881 nha->nha_JoypadFeat = HUAT_HATSWITCH;
3882 nha->nha_JoypadPort = 1;
3884 if((nha = nAllocAction(nch, lst, HUA_DIGJOY|HUA_ALWAYS)))
3886 nha->nha_JoypadOp = HUAT_ASSIGN;
3887 nha->nha_JoypadFeat = HUAT_HATSWITCH;
3888 nha->nha_JoypadPort = 1;
3890 break;
3892 case 0x30: /* X axis */
3893 case 0x35: /* Z rotation */
3894 case 0x31: /* Y axis */
3895 case 0x32: /* Z axis */
3897 ULONG minpos = ((nhi->nhi_LogicalMax - nhi->nhi_LogicalMin + 1)>>2) + nhi->nhi_LogicalMin;
3898 ULONG maxpos = (((nhi->nhi_LogicalMax - nhi->nhi_LogicalMin + 1)*3)>>2) + nhi->nhi_LogicalMin;
3899 UBYTE negaxis;
3900 UBYTE posaxis;
3901 UBYTE alogaxis;
3902 if((usageid == 0x30) || (usageid == 0x35))
3904 negaxis = HUAT_LEFT;
3905 posaxis = HUAT_RIGHT;
3906 alogaxis = HUAT_ABSX;
3907 } else {
3908 negaxis = HUAT_UP;
3909 posaxis = HUAT_DOWN;
3910 alogaxis = HUAT_ABSY;
3912 if((nha = nAllocAction(nch, lst, HUA_DIGJOY|HUA_ANY)))
3914 nha->nha_CCEnable = TRUE;
3915 nha->nha_CCCond = HUAT_GT;
3916 nha->nha_CCConst2 = minpos;
3917 nha->nha_JoypadOp = HUAT_CLEAR;
3918 nha->nha_JoypadFeat = negaxis;
3919 nha->nha_JoypadPort = 1;
3921 if((nha = nAllocAction(nch, lst, HUA_DIGJOY|HUA_ANY)))
3923 nha->nha_CCEnable = TRUE;
3924 nha->nha_CCCond = HUAT_LE;
3925 nha->nha_CCConst2 = minpos;
3926 nha->nha_JoypadOp = HUAT_SET;
3927 nha->nha_JoypadFeat = negaxis;
3928 nha->nha_JoypadPort = 1;
3930 if((nha = nAllocAction(nch, lst, HUA_DIGJOY|HUA_ANY)))
3932 nha->nha_CCEnable = TRUE;
3933 nha->nha_CCCond = HUAT_LT;
3934 nha->nha_CCConst2 = maxpos;
3935 nha->nha_JoypadOp = HUAT_CLEAR;
3936 nha->nha_JoypadFeat = posaxis;
3937 nha->nha_JoypadPort = 1;
3939 if((nha = nAllocAction(nch, lst, HUA_DIGJOY|HUA_ANY)))
3941 nha->nha_CCEnable = TRUE;
3942 nha->nha_CCCond = HUAT_GE;
3943 nha->nha_CCConst2 = maxpos;
3944 nha->nha_JoypadOp = HUAT_SET;
3945 nha->nha_JoypadFeat = posaxis;
3946 nha->nha_JoypadPort = 1;
3948 if((nha = nAllocAction(nch, lst, HUA_ANALOGJOY|HUA_ANY)))
3950 nha->nha_APadFeat = alogaxis;
3951 nha->nha_JoypadPort = 1;
3953 break;
3958 if(nFindCollID(nch, nhc, 0x010008, 0x010008) && (nhi->nhi_Flags & RPF_MAIN_RELATIVE)) /* Multi-axis controller */
3960 switch(usageid)
3962 case 0x30: /* Mouse X */
3963 if((nha = nAllocAction(nch, lst, HUA_MOUSEPOS|HUA_ALWAYS)))
3965 nha->nha_MouseAxis = HUAT_DELTAX;
3966 nha->nha_ClipEnable = TRUE;
3967 nha->nha_ClipMin = 10;
3968 nha->nha_ClipMax = 45;
3969 nha->nha_ClipStretch = TRUE;
3970 nha->nha_ScaleEnable = TRUE;
3971 nha->nha_ScaleMin = -32;
3972 nha->nha_ScaleMax = 0;
3973 nha->nha_CCEnable = TRUE;
3974 nha->nha_CCVar1 = HUAT_OITEMVALUE;
3975 nha->nha_CCCond = HUAT_LT;
3976 nha->nha_CCConst2 = 0;
3978 if((nha = nAllocAction(nch, lst, HUA_MOUSEPOS|HUA_ALWAYS)))
3980 nha->nha_MouseAxis = HUAT_DELTAX;
3981 nha->nha_ClipEnable = TRUE;
3982 nha->nha_ClipMin = 55;
3983 nha->nha_ClipMax = 90;
3984 nha->nha_ClipStretch = TRUE;
3985 nha->nha_ScaleEnable = TRUE;
3986 nha->nha_ScaleMin = 0;
3987 nha->nha_ScaleMax = 32;
3988 nha->nha_CCEnable = TRUE;
3989 nha->nha_CCVar1 = HUAT_OITEMVALUE;
3990 nha->nha_CCCond = HUAT_GT;
3991 nha->nha_CCConst2 = 0;
3993 break;
3995 case 0x31: /* Mouse Y */
3996 if((nha = nAllocAction(nch, lst, HUA_MOUSEPOS|HUA_ALWAYS)))
3998 nha->nha_MouseAxis = HUAT_DELTAY;
3999 nha->nha_ClipEnable = TRUE;
4000 nha->nha_ClipMin = 10;
4001 nha->nha_ClipMax = 45;
4002 nha->nha_ClipStretch = TRUE;
4003 nha->nha_ScaleEnable = TRUE;
4004 nha->nha_ScaleMin = -32;
4005 nha->nha_ScaleMax = 0;
4006 nha->nha_CCEnable = TRUE;
4007 nha->nha_CCVar1 = HUAT_OITEMVALUE;
4008 nha->nha_CCCond = HUAT_LT;
4009 nha->nha_CCConst2 = 0;
4011 if((nha = nAllocAction(nch, lst, HUA_MOUSEPOS|HUA_ALWAYS)))
4013 nha->nha_MouseAxis = HUAT_DELTAY;
4014 nha->nha_ClipEnable = TRUE;
4015 nha->nha_ClipMin = 55;
4016 nha->nha_ClipMax = 90;
4017 nha->nha_ClipStretch = TRUE;
4018 nha->nha_ScaleEnable = TRUE;
4019 nha->nha_ScaleMin = 0;
4020 nha->nha_ScaleMax = 32;
4021 nha->nha_CCEnable = TRUE;
4022 nha->nha_CCVar1 = HUAT_OITEMVALUE;
4023 nha->nha_CCCond = HUAT_GT;
4024 nha->nha_CCConst2 = 0;
4026 break;
4028 case 0x32: /* Mouse Z */
4030 LONG minpos = (((nhi->nhi_LogicalMax - nhi->nhi_LogicalMin + 1)*3)>>3) + nhi->nhi_LogicalMin;
4031 LONG maxpos = (((nhi->nhi_LogicalMax - nhi->nhi_LogicalMin + 1)*5)>>3) + nhi->nhi_LogicalMin;
4032 UWORD led = nFindItemUsage(nch, 0x08004B, REPORT_MAIN_OUTPUT); // blue LED
4033 if(maxpos > 0)
4035 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4037 nha->nha_ButtonMode = HUAT_SET;
4038 nha->nha_ButtonNo = 1;
4039 nha->nha_CCEnable = TRUE;
4040 nha->nha_CCCond = HUAT_GT;
4041 nha->nha_CCConst2 = maxpos;
4043 if(led && ((nha = nAllocAction(nch, lst, HUA_OUTPUT|HUA_ANY))))
4045 nha->nha_OutOp = HUAT_SET;
4046 nha->nha_OutItem = led;
4047 nha->nha_CCEnable = TRUE;
4048 nha->nha_CCCond = HUAT_GT;
4049 nha->nha_CCConst2 = maxpos;
4051 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4053 nha->nha_ButtonMode = HUAT_CLEAR;
4054 nha->nha_ButtonNo = 1;
4055 nha->nha_CCEnable = TRUE;
4056 nha->nha_CCCond = HUAT_LT;
4057 nha->nha_CCConst2 = maxpos;
4059 if(led && ((nha = nAllocAction(nch, lst, HUA_OUTPUT|HUA_ANY))))
4061 nha->nha_OutOp = HUAT_CLEAR;
4062 nha->nha_OutItem = led;
4063 nha->nha_CCEnable = TRUE;
4064 nha->nha_CCCond = HUAT_LT;
4065 nha->nha_CCConst2 = maxpos;
4068 if(minpos < 0)
4070 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4072 nha->nha_ButtonMode = HUAT_SET;
4073 nha->nha_ButtonNo = 2;
4074 nha->nha_CCEnable = TRUE;
4075 nha->nha_CCCond = HUAT_LT;
4076 nha->nha_CCConst2 = minpos;
4078 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4080 nha->nha_ButtonMode = HUAT_CLEAR;
4081 nha->nha_ButtonNo = 2;
4082 nha->nha_CCEnable = TRUE;
4083 nha->nha_CCCond = HUAT_GT;
4084 nha->nha_CCConst2 = minpos;
4087 break;
4090 case 0x35: /* Z rotation */
4092 LONG minpos = (((nhi->nhi_LogicalMax - nhi->nhi_LogicalMin + 1)*2)>>3) + nhi->nhi_LogicalMin;
4093 LONG maxpos = (((nhi->nhi_LogicalMax - nhi->nhi_LogicalMin + 1)*6)>>3) + nhi->nhi_LogicalMin;
4094 if(maxpos > 0)
4096 if((nha = nAllocAction(nch, lst, HUA_WHEEL|HUA_ANY)))
4098 nha->nha_WheelMode = HUAT_DOWN;
4099 nha->nha_WheelDist = 1;
4100 nha->nha_CCEnable = TRUE;
4101 nha->nha_CCCond = HUAT_GT;
4102 nha->nha_CCConst2 = maxpos;
4105 if(minpos < 0)
4107 if((nha = nAllocAction(nch, lst, HUA_WHEEL|HUA_ANY)))
4109 nha->nha_WheelMode = HUAT_UP;
4110 nha->nha_WheelDist = 1;
4111 nha->nha_CCEnable = TRUE;
4112 nha->nha_CCCond = HUAT_LT;
4113 nha->nha_CCConst2 = minpos;
4116 break;
4120 break;
4122 case 0x09: /* Button page */
4123 if(nFindCollID(nch, nhc, 0x010002, 0x010002) || /* Mice */
4124 nFindCollID(nch, nhc, 0x0d0001, 0x0d000d) || /* Tablets */
4125 nFindCollID(nch, nhc, 0x010008, 0x010008)) /* Multi-Axis controller */
4127 if(usageid && (usageid < 6))
4129 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4131 nha->nha_ButtonMode = HUAT_ASSIGN;
4132 nha->nha_ButtonNo = usageid;
4136 if(nFindCollID(nch, nhc, 0x010004, 0x010005)) /* Joystick, Game Pad */
4138 if(usageid && (usageid < 8))
4140 if((nha = nAllocAction(nch, lst, HUA_DIGJOY|HUA_ANY)))
4142 nha->nha_JoypadOp = HUAT_ASSIGN;
4143 nha->nha_JoypadFeat = HUAT_RED + usageid - 1;
4144 nha->nha_JoypadPort = 1;
4148 break;
4150 case 0x07: /* keyboard page */
4151 switch(usageid)
4153 case 0x39: /* Caps lock */
4155 UWORD led;
4156 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_DOWNEVENT)))
4158 nha->nha_QualMode = HUAT_TOGGLE;
4159 nha->nha_Qualifier = IEQUALIFIERB_CAPSLOCK;
4161 if((led = nFindItemUsage(nch, 0x080002, REPORT_MAIN_OUTPUT)))
4163 if((nha = nAllocAction(nch, lst, HUA_OUTPUT|HUA_DOWNEVENT)))
4165 nha->nha_OutOp = HUAT_SET;
4166 nha->nha_OutItem = led;
4167 nha->nha_CCEnable = TRUE;
4168 nha->nha_CCVar1 = HUAT_QUALIFIERS;
4169 nha->nha_CCCond = HUAT_BWAND;
4170 nha->nha_CCVar2 = HUAT_CONST;
4171 nha->nha_CCConst2 = IEQUALIFIER_CAPSLOCK;
4173 if((nha = nAllocAction(nch, lst, HUA_OUTPUT|HUA_DOWNEVENT)))
4175 nha->nha_OutOp = HUAT_CLEAR;
4176 nha->nha_OutItem = led;
4177 nha->nha_CCEnable = TRUE;
4178 nha->nha_CCVar1 = HUAT_QUALIFIERS;
4179 nha->nha_CCCond = HUAT_BWNAND;
4180 nha->nha_CCVar2 = HUAT_CONST;
4181 nha->nha_CCConst2 = IEQUALIFIER_CAPSLOCK;
4184 break;
4187 case 0xe0: /* Left control */
4188 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4190 nha->nha_QualMode = HUAT_ASSIGN;
4191 nha->nha_Qualifier = IEQUALIFIERB_CONTROL;
4193 break;
4195 case 0xe1: /* Left shift */
4196 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4198 nha->nha_QualMode = HUAT_ASSIGN;
4199 nha->nha_Qualifier = IEQUALIFIERB_LSHIFT;
4201 break;
4203 case 0xe2: /* Left alt */
4204 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4206 nha->nha_QualMode = HUAT_ASSIGN;
4207 nha->nha_Qualifier = IEQUALIFIERB_LALT;
4209 break;
4211 case 0xe3: /* Left GUI */
4212 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4214 nha->nha_QualMode = HUAT_ASSIGN;
4215 nha->nha_Qualifier = IEQUALIFIERB_LCOMMAND;
4217 break;
4219 case 0xe4: /* Right control */
4220 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4222 nha->nha_QualMode = HUAT_ASSIGN;
4223 nha->nha_Qualifier = IEQUALIFIERB_CONTROL;
4225 break;
4227 case 0xe5: /* Right shift */
4228 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4230 nha->nha_QualMode = HUAT_ASSIGN;
4231 nha->nha_Qualifier = IEQUALIFIERB_RSHIFT;
4233 break;
4235 case 0xe6: /* Right alt */
4236 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4238 nha->nha_QualMode = HUAT_ASSIGN;
4239 nha->nha_Qualifier = IEQUALIFIERB_RALT;
4241 break;
4243 case 0x45: /* F12 */
4244 case 0x65: /* Application */
4245 case 0xe7: /* Right GUI */
4246 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4248 nha->nha_QualMode = HUAT_ASSIGN;
4249 nha->nha_Qualifier = IEQUALIFIERB_RCOMMAND;
4251 break;
4253 nha = nAllocAction(nch, lst, HUA_KEYMAP|HUA_ANY);
4254 break;
4256 case 0x0d: /* digitizer/tablet page */
4257 switch(usageid)
4259 case 0x30: /* Tip pressure */
4260 case 0x31: /* Barrel pressure */
4261 if((nha = nAllocAction(nch, lst, HUA_TABLET|HUA_ALWAYS)))
4263 nha->nha_TabletAxis = HUAT_PRESSURE;
4265 break;
4267 case 0x32: /* In Range */
4268 case 0x37: /* Data Valid */
4269 if((nha = nAllocAction(nch, lst, HUA_TABLET|HUA_ALWAYS)))
4271 nha->nha_TabletAxis = HUAT_PROX;
4273 break;
4275 case 0x3D: /* X Tilt */
4276 if((nha = nAllocAction(nch, lst, HUA_TABLET|HUA_ALWAYS)))
4278 nha->nha_TabletAxis = HUAT_XROT;
4280 break;
4282 case 0x3E: /* Y Tilt */
4283 if((nha = nAllocAction(nch, lst, HUA_TABLET|HUA_ALWAYS)))
4285 nha->nha_TabletAxis = HUAT_YROT;
4287 break;
4289 case 0x42: /* Tip switch */
4290 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4292 nha->nha_ButtonMode = HUAT_ASSIGN;
4293 nha->nha_ButtonNo = 1;
4295 break;
4297 case 0x44: /* Barrel switch */
4298 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4300 nha->nha_ButtonMode = HUAT_ASSIGN;
4301 nha->nha_ButtonNo = 2;
4303 break;
4305 case 0x46: /* Tablet pick */
4306 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4308 nha->nha_ButtonMode = HUAT_ASSIGN;
4309 nha->nha_ButtonNo = 3;
4311 break;
4313 break;
4315 while(utp->utp_UsageID && (utp->utp_UsageID <= uid))
4317 if(utp->utp_UsageID == uid)
4319 if((nha = nAllocAction(nch, lst, HUA_EXTRAWKEY|HUA_DOWNEVENT)))
4321 nha->nha_RawKey = utp->utp_ExtCode;
4323 if((nha = nAllocAction(nch, lst, HUA_EXTRAWKEY|HUA_UPEVENT)))
4325 nha->nha_RawKey = utp->utp_ExtCode|IECODE_UP_PREFIX;
4328 utp++;
4330 return(res);
4332 /* \\\ */
4334 /* /// "nCheckForDefaultAction()" */
4335 BOOL nCheckForDefaultAction(struct NepClassHid *nch, struct NepHidItem *nhi, struct List *lst, struct NepHidCollection *nhc, ULONG uid)
4337 BOOL res = TRUE;
4338 struct NepHidAction *nha;
4339 struct NepHidAction *nhadef;
4340 struct List tmplist;
4342 NewList(&tmplist);
4343 nDetectDefaultAction(nch, nhi, &tmplist, nhc, nhi->nhi_Usage);
4344 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
4345 nhadef = (struct NepHidAction *) tmplist.lh_Head;
4346 while(nha->nha_Node.ln_Succ)
4348 if(nhadef->nha_Node.ln_Succ)
4350 nhadef->nha_IsDefault = nha->nha_IsDefault;
4351 if(memcmp(&nha->nha_Type, &nhadef->nha_Type, sizeof(struct NepHidAction)-offsetof(struct NepHidAction, nha_Type)))
4353 nha->nha_IsDefault = FALSE;
4354 res = FALSE;
4355 } else {
4356 nha->nha_IsDefault = TRUE;
4358 nhadef = (struct NepHidAction *) nhadef->nha_Node.ln_Succ;
4359 } else {
4360 res = FALSE;
4361 nha->nha_IsDefault = FALSE;
4363 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
4365 nhadef = (struct NepHidAction *) tmplist.lh_Head;
4366 while(nhadef->nha_Node.ln_Succ)
4368 Remove(&nhadef->nha_Node);
4369 psdFreeVec(nhadef);
4370 nhadef = (struct NepHidAction *) tmplist.lh_Head;
4372 return(res);
4374 /* \\\ */
4376 /* /// "nAllocAction()" */
4377 struct NepHidAction * nAllocAction(struct NepClassHid *nch, struct List *lst, UWORD utype)
4379 struct NepHidAction *nha = psdAllocVec(sizeof(struct NepHidAction));
4380 if(nha)
4382 KPRINTF(1, ("New action %lx\n", nha));
4383 nha->nha_Type = utype;
4384 nha->nha_ButtonNo = 1;
4385 nha->nha_SoundVolume = 64;
4386 nha->nha_ClipMax = 100;
4387 nha->nha_CCVar1 = HUAT_EITEMVALUE;
4388 nha->nha_CCVar2 = HUAT_CONST;
4389 AddTail(lst, &nha->nha_Node);
4390 return(nha);
4392 return(NULL);
4394 /* \\\ */
4396 /* /// "nAddUsage()" */
4397 BOOL nAddUsage(struct NepClassHid *nch, struct List *list, ULONG umin, ULONG umax)
4399 struct NepHidUsage *nhu;
4400 if(umin > umax)
4402 KPRINTF(10, ("UsageMin %lx > UsageMax %lx\n", umin, umax));
4403 return(FALSE);
4405 if((nhu = psdAllocVec(sizeof(struct NepHidUsage))))
4407 AddTail(list, &nhu->nhu_Node);
4408 nhu->nhu_Usage = umin;
4409 nhu->nhu_UsageMax = umax;
4410 return(TRUE);
4411 } else {
4412 KPRINTF(10, ("Out of memory during usage allocation.\n"));
4414 return(FALSE);
4416 /* \\\ */
4418 /* /// "nGetUsageName()" */
4419 STRPTR nGetUsageName(struct NepClassHid *nch, ULONG uid)
4421 STRPTR uname;
4423 uname = nNumToStr(nch, NTS_USAGEID, uid, NULL);
4424 if(uname)
4426 return(psdCopyStr(uname));
4428 uname = nNumToStr(nch, NTS_USAGEPAGE, uid>>16, "unknown");
4429 return(psdCopyStrFmt("%s (0x%lx)", uname, uid));
4431 /* \\\ */
4433 /* /// "nGenerateOutReport()" */
4434 void nGenerateOutReport(struct NepClassHid *nch, struct NepHidReport *nhr, UBYTE *buf)
4436 struct NepHidItem **nhiptr = nhr->nhr_OutItemMap;
4437 ULONG cnt;
4439 for(cnt = 0; cnt < nhr->nhr_OutItemCount; cnt++)
4441 nEncodeItemBuffer(nch, *nhiptr++, buf);
4444 /* \\\ */
4446 /* /// "nGenerateFeatReport()" */
4447 void nGenerateFeatReport(struct NepClassHid *nch, struct NepHidReport *nhr, UBYTE *buf)
4449 struct NepHidItem **nhiptr = nhr->nhr_FeatItemMap;
4450 ULONG cnt;
4452 for(cnt = 0; cnt < nhr->nhr_FeatItemCount; cnt++)
4454 nEncodeItemBuffer(nch, *nhiptr++, buf);
4457 /* \\\ */
4459 /* /// "nEncodeItemBuffer()" */
4460 void nEncodeItemBuffer(struct NepClassHid *nch, struct NepHidItem *nhi, UBYTE *buf)
4462 LONG value;
4463 LONG *valptr;
4464 ULONG ioffset;
4465 ULONG isize;
4466 UWORD count;
4467 UWORD acount;
4469 ioffset = nhi->nhi_Offset;
4470 isize = nhi->nhi_Size;
4471 if(nhi->nhi_Flags & RPF_MAIN_VARIABLE)
4473 //KPRINTF(1, ("Processing var %08lx (%ld@%ld)...\n", nhi, isize, ioffset));
4474 value = nhi->nhi_OldValue;
4475 if(value < nhi->nhi_LogicalMin)
4477 value = nhi->nhi_LogicalMin;
4479 else if(value > nhi->nhi_LogicalMax)
4481 value = nhi->nhi_LogicalMax;
4483 if(((ioffset & 7) == 0) && (isize == 8))
4485 buf[ioffset>>3] = value;
4487 else if(isize == 1)
4489 buf[ioffset>>3] &= ~(1UL<<(ioffset & 7));
4490 if(value)
4492 buf[ioffset>>3] |= (1UL<<(ioffset & 7));
4494 } else {
4495 /* I know this routine is dead slow, but hopefully, this is only a very uncommon case */
4496 count = isize;
4497 ioffset += count;
4500 ioffset--;
4501 buf[ioffset>>3] &= ~(1UL<<(ioffset & 7));
4502 if(value & 1)
4504 buf[ioffset>>3] |= (1UL<<(ioffset & 7));
4506 value >>= 1;
4507 } while(--count);
4509 } else {
4510 acount = nhi->nhi_Count;
4511 KPRINTF(1, ("Processing arr %08lx (%ld@%ld) * %ld...\n", nhi, isize, ioffset, acount));
4512 /* first generate the values */
4513 valptr = nhi->nhi_Buffer;
4514 if(((ioffset & 7) == 0) && (isize == 8))
4516 count = ioffset>>3;
4519 buf[count++] = *valptr++;
4520 } while(--acount);
4522 else if(isize == 1)
4526 buf[ioffset>>3] &= ~(1UL<<(ioffset & 7));
4527 if(*valptr++)
4529 buf[ioffset>>3] |= (1UL<<(ioffset & 7));
4531 ioffset++;
4532 } while(--acount);
4533 } else {
4534 /* I know this routine is dead slow, but hopefully, this is only a very uncommon case */
4537 count = isize;
4538 ioffset += count;
4539 value = *valptr++;
4542 ioffset--;
4543 buf[ioffset>>3] &= ~(1UL<<(ioffset & 7));
4544 if(value & 1)
4546 buf[ioffset>>3] |= (1UL<<(ioffset & 7));
4548 value >>= 1;
4549 } while(--count);
4550 ioffset += count;
4551 } while(--acount);
4555 /* \\\ */
4557 /* /// "nParseArrayString()" */
4558 void nParseArrayString(struct NepClassHid *nch, struct NepHidItem *nhi, STRPTR str)
4560 UWORD acount;
4561 LONG *valptr = nhi->nhi_Buffer;
4562 UWORD mode = 0;
4563 BOOL issigned = FALSE;
4565 if(!*str)
4567 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Empty array value string not allowed.");
4568 return;
4570 acount = nhi->nhi_Count;
4571 if(!acount)
4573 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Target array has no space!");
4576 // mode == 0 -> start
4577 // mode == 1 -> decimal value
4578 // mode == 2 -> hex value
4579 // mode == 3 -> ascii character
4580 // mode == 4 -> string
4581 // mode == 5 -> waiting for termination
4583 while(*str && acount)
4585 UBYTE ch = *str++;
4586 switch(mode)
4588 case 0: // normal
4589 if((ch == '0') && (*str == 'x'))
4591 mode = 2;
4592 *valptr = 0;
4593 str++;
4594 break;
4596 if((ch >= '0') && (ch <= '9'))
4598 mode = 1;
4599 issigned = FALSE;
4600 *valptr = ch - '0';
4601 break;
4603 else if(ch == '-')
4605 mode = 1;
4606 issigned = TRUE;
4607 *valptr = 0;
4609 else if(ch == '\'')
4611 mode = 3;
4612 break;
4614 else if(ch == '"')
4616 mode = 4;
4617 break;
4619 else if(ch == ' ')
4621 break;
4623 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Syntax error in S0!");
4624 return;
4626 case 1: // decimal value
4627 if((ch >= '0') && (ch <= '9'))
4629 *valptr *= 10;
4630 if(issigned)
4632 *valptr -= ch - '0';
4633 } else {
4634 *valptr += ch - '0';
4636 break;
4638 else if(ch == ' ')
4640 mode = 5;
4641 break;
4643 else if(ch == ',')
4645 mode = 0;
4646 valptr++;
4647 acount--;
4648 break;
4650 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Syntax error in S1!");
4651 return;
4653 case 2: // hex value
4654 if((ch >= '0') && (ch <= '9'))
4656 *valptr <<= 4;
4657 *valptr += ch - '0';
4658 break;
4660 else if((ch >= 'a') && (ch <= 'f'))
4662 *valptr <<= 4;
4663 *valptr += ch - 'a' + 10;
4664 break;
4666 else if((ch >= 'A') && (ch <= 'F'))
4668 *valptr <<= 4;
4669 *valptr += ch - 'A' + 10;
4670 break;
4672 else if(ch == ',')
4674 mode = 0;
4675 valptr++;
4676 acount--;
4677 break;
4679 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Syntax error in S2!");
4680 return;
4682 case 3: // ascii character
4683 if(*str == '\'')
4685 *valptr = ch;
4686 str++;
4687 mode = 5;
4688 break;
4690 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Syntax error in S3!");
4691 return;
4693 case 4: // string
4694 if(ch == '"')
4696 mode = 5;
4697 break;
4699 *valptr++ = ch;
4700 acount--;
4701 break;
4703 case 5: // waiting for termination
4704 if(ch == ' ')
4706 break;
4708 if(ch == ',')
4710 valptr++;
4711 acount--;
4712 mode = 0;
4713 break;
4715 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Syntax error in S5!");
4716 return;
4719 if(!(*str))
4721 if(mode == 3)
4723 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Syntax error in S3!");
4724 return;
4726 if(mode == 4)
4728 if(*str == '"')
4730 return;
4734 if(acount == 0)
4736 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Excessive elements ignored!");
4739 /* \\\ */
4741 /* /// "nProcessItem()" */
4742 BOOL nProcessItem(struct NepClassHid *nch, struct NepHidItem *nhi, UBYTE *buf)
4744 BOOL res = FALSE;
4745 LONG value;
4746 LONG *valptr;
4747 ULONG ioffset = nhi->nhi_Offset;
4748 ULONG isize = nhi->nhi_Size;
4749 UBYTE *bobuf = &buf[ioffset>>3];
4750 UWORD count;
4751 UWORD acount;
4752 ULONG usage;
4753 BOOL found;
4754 BOOL bytealigned = ((ioffset & 7) == 0);
4755 struct NepHidAction *nha;
4757 if(nhi->nhi_Flags & RPF_MAIN_VARIABLE)
4759 //KPRINTF(1, ("Processing var %08lx (%ld@%ld)...\n", nhi, isize, ioffset));
4760 if(bytealigned && (isize == 8))
4762 if(nhi->nhi_IsSigned)
4764 value = *((BYTE *) bobuf);
4765 } else {
4766 value = *bobuf;
4769 else if(isize == 1)
4771 value = (buf[ioffset>>3]>>(ioffset & 7)) & 1;
4773 else if(bytealigned && (isize == 16))
4775 if(nhi->nhi_IsSigned)
4777 value = (*bobuf)|((((BYTE *) bobuf)[1])<<8);
4778 } else {
4779 value = (*bobuf)|(bobuf[1]<<8);
4782 else if(bytealigned && (isize == 32))
4784 value = bobuf[0]|(bobuf[1]<<8)|(bobuf[2]<<16)|(bobuf[3]<<24);
4785 } else {
4786 /* I know this routine is dead slow, but hopefully, this is only a very uncommon case */
4787 count = isize;
4788 value = 0;
4789 ioffset += count;
4790 if(nhi->nhi_IsSigned)
4792 count--;
4793 ioffset--;
4794 if((buf[ioffset>>3]>>(ioffset & 7)) & 1)
4796 value = -1;
4801 ioffset--;
4802 value <<= 1;
4803 value |= (buf[ioffset>>3]>>(ioffset & 7)) & 1;
4804 } while(--count);
4806 if((value >= nhi->nhi_LogicalMin) && (value <= nhi->nhi_LogicalMax))
4808 ULONG currmicros = 0;
4809 ULONG currsecs = 0;
4810 if(nhi->nhi_OldValue != value)
4812 if((nhi->nhi_Usage > 0x070000) && (nhi->nhi_Usage < 0x0700E8))
4814 nch->nch_LastUSBKey = nhi->nhi_Usage;
4816 nch->nch_LastItem = nhi;
4817 nch->nch_LastItemAList = &nhi->nhi_ActionList;
4820 if(nch->nch_HIntBase)
4822 CurrentTime(&currsecs, &currmicros);
4823 if(!DoubleClick(nhi->nhi_LastSeconds, nhi->nhi_LastMicros, currsecs, currmicros))
4825 nhi->nhi_ClickCount = 0;
4827 if(nhi->nhi_OldValue < value)
4829 if(nhi->nhi_LastSeconds || nhi->nhi_LastMicros)
4831 if(DoubleClick(nhi->nhi_LastSeconds, nhi->nhi_LastMicros, currsecs, currmicros))
4833 nhi->nhi_ClickCount++;
4834 } else {
4835 nhi->nhi_ClickCount = 1;
4837 } else {
4838 nhi->nhi_ClickCount = 1;
4840 nhi->nhi_HoldSeconds = nhi->nhi_LastSeconds = currsecs;
4841 nhi->nhi_HoldMicros = nhi->nhi_LastMicros = currmicros;
4843 } else {
4844 /* no intuition library */
4845 nhi->nhi_ClickCount = 0;
4846 if(nhi->nhi_OldValue < value)
4848 nhi->nhi_ClickCount = 1;
4851 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
4852 while(nha->nha_Node.ln_Succ)
4854 if((nhi->nhi_OldValue != value) || ((nha->nha_Type & HUA_TRIGMASK) == HUA_ALWAYS))
4856 nDoAction(nch, nha, nhi, nhi->nhi_Usage, value, (nhi->nhi_OldValue < value) || ((nha->nha_Type & HUA_TRIGMASK) == HUA_ALWAYS));
4858 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
4860 if(nhi->nhi_OldValue > value)
4862 nhi->nhi_HoldSeconds = 0;
4863 nhi->nhi_HoldMicros = 0;
4865 if((nhi->nhi_OldValue != value) && nch->nch_ReportValues &&
4866 nch->nch_GUICurrentItem && (nch->nch_GUICurrentItem->nhgi_Item == nhi))
4868 nch->nch_ItemChanged = TRUE;
4870 nhi->nhi_OldValue = value;
4871 res = TRUE;
4872 } else {
4873 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
4874 while(nha->nha_Node.ln_Succ)
4876 if((nha->nha_Type & HUA_TRIGMASK) == HUA_NAN)
4878 nDoAction(nch, nha, nhi, nhi->nhi_Usage, nhi->nhi_OldValue, 0);
4880 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
4883 } else {
4884 nhi->nhi_HoldSeconds = nhi->nhi_LastSeconds = 0;
4885 nhi->nhi_HoldMicros = nhi->nhi_LastMicros = 0;
4886 acount = nhi->nhi_Count;
4887 KPRINTF(1, ("Processing arr %08lx (%ld@%ld) * %ld...\n", nhi, isize, ioffset, acount));
4888 /* first generate the values */
4889 valptr = nhi->nhi_Buffer;
4890 if(bytealigned && (isize == 8))
4892 count = ioffset>>3;
4893 if(nhi->nhi_IsSigned)
4897 *valptr++ = ((BYTE *) buf)[count++];
4898 } while(--acount);
4899 } else {
4902 *valptr++ = buf[count++];
4903 } while(--acount);
4906 else if(isize == 1)
4910 *valptr++ = (buf[ioffset>>3]>>(ioffset & 7)) & 1;
4911 ioffset++;
4912 } while(--acount);
4913 } else {
4914 /* I know this routine is dead slow, but hopefully, this is only a very uncommon case */
4917 count = isize;
4918 value = 0;
4919 ioffset += count;
4920 if(nhi->nhi_IsSigned)
4922 ioffset--;
4923 count--;
4924 if((buf[ioffset>>3]>>(ioffset & 7)) & 1)
4926 value = -1;
4931 ioffset--;
4932 value <<= 1;
4933 value |= (buf[ioffset>>3]>>(ioffset & 7)) & 1;
4934 } while(--count);
4935 ioffset += isize;
4936 *valptr++ = value;
4937 } while(--acount);
4940 /* Look for up events first */
4941 acount = 0;
4944 value = nhi->nhi_OldBuffer[acount];
4945 if((value >= nhi->nhi_LogicalMin) && (value <= nhi->nhi_LogicalMax))
4947 valptr = nhi->nhi_Buffer;
4948 count = nhi->nhi_Count;
4949 found = FALSE;
4952 if(*valptr++ == value)
4954 found = TRUE;
4955 break;
4957 } while(--count);
4958 /* Not found in the new array, so generate up event */
4959 if(!found)
4961 KPRINTF(1, ("Up event %ld\n", acount));
4962 usage = nhi->nhi_UsageMap[value - nhi->nhi_LogicalMin];
4963 if(value || nhi->nhi_LogicalMin)
4965 nch->nch_LastItem = nhi;
4966 nch->nch_LastItemAList = &nhi->nhi_ActionMap[value - nhi->nhi_LogicalMin];
4968 nha = (struct NepHidAction *) nhi->nhi_ActionMap[value - nhi->nhi_LogicalMin].lh_Head;
4969 if(!nha->nha_Node.ln_Succ) /* Use default, no override defined */
4971 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
4973 nhi->nhi_OldValue = nhi->nhi_LogicalMin - 1;
4974 while(nha->nha_Node.ln_Succ)
4976 nDoAction(nch, nha, nhi, usage, value, FALSE);
4977 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
4979 res = TRUE;
4982 } while(++acount < nhi->nhi_Count);
4984 /* Look for down events */
4985 acount = 0;
4988 value = nhi->nhi_Buffer[acount];
4989 //KPRINTF(1, ("[%ld] = %ld\n", acount, value));
4990 if((value >= nhi->nhi_LogicalMin) && (value <= nhi->nhi_LogicalMax))
4992 valptr = nhi->nhi_OldBuffer;
4993 count = nhi->nhi_Count;
4994 found = FALSE;
4997 if(*valptr++ == value)
4999 found = TRUE;
5000 break;
5002 } while(--count);
5003 /* Not found in the old array, so generate down event */
5004 if(!found)
5006 KPRINTF(1, ("Down event %ld\n", acount));
5007 usage = nhi->nhi_UsageMap[value - nhi->nhi_LogicalMin];
5008 if(value || nhi->nhi_LogicalMin)
5010 if((usage > 0x070000) && (usage < 0x0700E8))
5012 nch->nch_LastUSBKey = usage;
5014 nch->nch_LastItem = nhi;
5015 nch->nch_LastItemAList = &nhi->nhi_ActionMap[value - nhi->nhi_LogicalMin];
5018 nha = (struct NepHidAction *) nhi->nhi_ActionMap[value - nhi->nhi_LogicalMin].lh_Head;
5019 if(!nha->nha_Node.ln_Succ) /* Use default, no override defined */
5021 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
5023 nhi->nhi_OldValue = nhi->nhi_LogicalMin - 1;
5024 while(nha->nha_Node.ln_Succ)
5026 nDoAction(nch, nha, nhi, usage, value, TRUE);
5027 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
5029 res = TRUE;
5032 } while(++acount < nhi->nhi_Count);
5033 /* Copy new array */
5034 CopyMemQuick(nhi->nhi_Buffer, nhi->nhi_OldBuffer, sizeof(LONG) * nhi->nhi_Count);
5036 return(res);
5038 /* \\\ */
5040 static ULONG LLHatswitchEncoding[8] = { JPF_JOY_UP, JPF_JOY_UP|JPF_JOY_RIGHT, JPF_JOY_RIGHT, JPF_JOY_RIGHT|JPF_JOY_DOWN,
5041 JPF_JOY_DOWN, JPF_JOY_DOWN|JPF_JOY_LEFT, JPF_JOY_LEFT, JPF_JOY_LEFT|JPF_JOY_UP };
5043 /* /// "nDoAction()" */
5044 BOOL nDoAction(struct NepClassHid *nch, struct NepHidAction *nha, struct NepHidItem *nhi, ULONG uid, LONG value, BOOL downevent)
5046 UWORD atype = nha->nha_Type & HUA_ATYPEMASK;
5047 BOOL res = FALSE;
5048 ULONG qualmask;
5049 LONG clipmin, clipmax;
5050 LONG origvalue = value;
5052 if(nch->nch_DisableActions)
5054 return(FALSE);
5057 // bail out early as nothing below will affect this
5058 if(!(((nha->nha_Type & HUA_DOWNEVENT) && downevent) ||
5059 ((nha->nha_Type & HUA_UPEVENT) && !downevent) ||
5060 ((nha->nha_Type & HUA_TRIGMASK) == HUA_ALWAYS) ||
5061 ((nha->nha_Type & HUA_TRIGMASK) == HUA_NAN)))
5063 return(FALSE);
5066 if(nha->nha_AbsToRel)
5068 value = value - nhi->nhi_OldValue;
5069 nhi->nhi_RealMin = nhi->nhi_LogicalMin - nhi->nhi_LogicalMax;
5070 nhi->nhi_RealMax = nhi->nhi_LogicalMax - nhi->nhi_LogicalMin;
5071 } else {
5072 nhi->nhi_RealMin = nhi->nhi_LogicalMin;
5073 nhi->nhi_RealMax = nhi->nhi_LogicalMax;
5076 if(nha->nha_ClipEnable)
5078 if(nha->nha_ClipMin == nha->nha_ClipMax)
5080 /* shrink to a point */
5081 value = ((nha->nha_ClipMin * (nhi->nhi_RealMax - nhi->nhi_RealMin)) / 100) + nhi->nhi_RealMin;
5082 } else {
5083 if(nha->nha_ClipMin < nha->nha_ClipMax)
5085 /* normal clipping */
5086 clipmin = ((nha->nha_ClipMin * (nhi->nhi_RealMax - nhi->nhi_RealMin)) / 100) + nhi->nhi_RealMin;
5087 clipmax = ((nha->nha_ClipMax * (nhi->nhi_RealMax - nhi->nhi_RealMin)) / 100) + nhi->nhi_RealMin;
5088 } else {
5089 /* inverse clipping */
5090 value = nhi->nhi_RealMax - value;
5091 clipmin = ((nha->nha_ClipMax * (nhi->nhi_RealMax - nhi->nhi_RealMin)) / 100) + nhi->nhi_RealMin;
5092 clipmax = ((nha->nha_ClipMin * (nhi->nhi_RealMax - nhi->nhi_RealMin)) / 100) + nhi->nhi_RealMin;
5094 if(value < clipmin)
5096 value = clipmin;
5097 } else {
5098 if(value > clipmax)
5100 value = clipmax;
5103 if(nha->nha_ClipStretch && (clipmax - clipmin))
5105 value = (((value - clipmin) * (nhi->nhi_RealMax - nhi->nhi_RealMin)) /
5106 (clipmax - clipmin)) + nhi->nhi_RealMin;
5111 if(nha->nha_ScaleEnable && (nha->nha_ScaleMax != nha->nha_ScaleMin))
5113 value = (((value - nhi->nhi_RealMin) * (nha->nha_ScaleMax - nha->nha_ScaleMin)) /
5114 (nhi->nhi_RealMax - nhi->nhi_RealMin)) + nha->nha_ScaleMin;
5115 nhi->nhi_RealMin = nha->nha_ScaleMin;
5116 nhi->nhi_RealMax = nha->nha_ScaleMax;
5119 if(nha->nha_CCEnable)
5121 LONG var1 = 0;
5122 LONG var2 = 0;
5123 BOOL cond = FALSE;
5125 switch(nha->nha_CCVar1)
5127 case HUAT_EITEMVALUE:
5128 var1 = value;
5129 break;
5131 case HUAT_OITEMVALUE:
5132 var1 = origvalue;
5133 break;
5135 case HUAT_CONST:
5136 var1 = nha->nha_CCConst1;
5137 break;
5139 case HUAT_CLICKCOUNT:
5140 var1 = nhi->nhi_ClickCount;
5141 break;
5143 case HUAT_CLICKTIME:
5145 ULONG currmicros;
5146 ULONG currsecs;
5148 if(nhi->nhi_HoldSeconds || nhi->nhi_HoldMicros)
5150 CurrentTime(&currsecs, &currmicros);
5151 var1 = (currsecs - nhi->nhi_HoldSeconds) * 1000;
5152 if(nhi->nhi_HoldMicros <= currmicros)
5154 var1 += (currmicros - nhi->nhi_HoldMicros) / 1000;
5155 } else {
5156 var1 -= (nhi->nhi_HoldMicros - currmicros) / 1000;
5158 } else {
5159 var1 = 0;
5161 break;
5164 case HUAT_QUALIFIERS:
5165 var1 = nch->nch_KeyQualifiers;
5166 break;
5168 case HUAT_ALLQUAL:
5169 var1 = nch->nch_KeyQualifiers|PeekQualifier();
5170 break;
5172 case HUAT_RANDOMBIT:
5173 var1 = _rand(nch->nch_ClsBase) & 1;
5174 break;
5176 case HUAT_RANDOMVAL:
5177 var1 = _rand(nch->nch_ClsBase);
5178 break;
5180 case HUAT_TIMER:
5182 ULONG currmicros;
5183 ULONG currsecs;
5185 CurrentTime(&currsecs, &currmicros);
5186 var1 = (currsecs * 1000) + (currmicros / 1000);
5187 break;
5190 case HUAT_LOCALVAR1:
5191 case HUAT_LOCALVAR2:
5192 case HUAT_LOCALVAR3:
5193 case HUAT_LOCALVAR4:
5194 case HUAT_LOCALVAR5:
5195 case HUAT_LOCALVAR6:
5196 case HUAT_LOCALVAR7:
5197 case HUAT_LOCALVAR8:
5198 var1 = nch->nch_LocalVars[nha->nha_CCVar1 - HUAT_LOCALVAR1];
5199 break;
5201 case HUAT_GLOBVARA:
5202 case HUAT_GLOBVARB:
5203 case HUAT_GLOBVARC:
5204 case HUAT_GLOBVARD:
5205 case HUAT_GLOBVARE:
5206 case HUAT_GLOBVARF:
5207 case HUAT_GLOBVARG:
5208 case HUAT_GLOBVARH:
5209 var1 = nch->nch_ClsBase->nh_GlobalVars[nha->nha_CCVar1 - HUAT_GLOBVARA];
5210 break;
5212 switch(nha->nha_CCVar2)
5214 case HUAT_EITEMVALUE:
5215 var2 = value;
5216 break;
5218 case HUAT_OITEMVALUE:
5219 var2 = origvalue;
5220 break;
5222 case HUAT_CONST:
5223 var2 = nha->nha_CCConst2;
5224 break;
5226 case HUAT_CLICKCOUNT:
5227 var2 = nhi->nhi_ClickCount;
5228 break;
5230 case HUAT_CLICKTIME:
5232 ULONG currmicros;
5233 ULONG currsecs;
5235 if(nhi->nhi_HoldSeconds || nhi->nhi_HoldMicros)
5237 CurrentTime(&currsecs, &currmicros);
5238 var2 = (currsecs - nhi->nhi_HoldSeconds) * 1000;
5239 if(nhi->nhi_HoldMicros <= currmicros)
5241 var2 += (currmicros - nhi->nhi_HoldMicros) / 1000;
5242 } else {
5243 var2 -= (nhi->nhi_HoldMicros - currmicros) / 1000;
5245 } else {
5246 var2 = 0;
5248 break;
5251 case HUAT_QUALIFIERS:
5252 var2 = nch->nch_KeyQualifiers;
5253 break;
5255 case HUAT_ALLQUAL:
5256 var2 = nch->nch_KeyQualifiers|PeekQualifier();
5257 break;
5259 case HUAT_RANDOMBIT:
5260 var2 = _rand(nch->nch_ClsBase) & 1;
5261 break;
5263 case HUAT_RANDOMVAL:
5264 var2 = _rand(nch->nch_ClsBase);
5265 break;
5267 case HUAT_TIMER:
5269 ULONG currmicros;
5270 ULONG currsecs;
5272 CurrentTime(&currsecs, &currmicros);
5273 var2 = (currsecs * 1000) + (currmicros / 1000);
5274 break;
5277 case HUAT_LOCALVAR1:
5278 case HUAT_LOCALVAR2:
5279 case HUAT_LOCALVAR3:
5280 case HUAT_LOCALVAR4:
5281 case HUAT_LOCALVAR5:
5282 case HUAT_LOCALVAR6:
5283 case HUAT_LOCALVAR7:
5284 case HUAT_LOCALVAR8:
5285 var2 = nch->nch_LocalVars[nha->nha_CCVar2 - HUAT_LOCALVAR1];
5286 break;
5288 case HUAT_GLOBVARA:
5289 case HUAT_GLOBVARB:
5290 case HUAT_GLOBVARC:
5291 case HUAT_GLOBVARD:
5292 case HUAT_GLOBVARE:
5293 case HUAT_GLOBVARF:
5294 case HUAT_GLOBVARG:
5295 case HUAT_GLOBVARH:
5296 var2 = nch->nch_ClsBase->nh_GlobalVars[nha->nha_CCVar2 - HUAT_GLOBVARA];
5297 break;
5299 switch(nha->nha_CCCond)
5301 case HUAT_EQ:
5302 cond = (var1 == var2);
5303 break;
5305 case HUAT_NE:
5306 cond = (var1 != var2);
5307 break;
5309 case HUAT_LT:
5310 cond = (var1 < var2);
5311 break;
5313 case HUAT_LE:
5314 cond = (var1 <= var2);
5315 break;
5317 case HUAT_GT:
5318 cond = (var1 > var2);
5319 break;
5321 case HUAT_GE:
5322 cond = (var1 >= var2);
5323 break;
5325 case HUAT_AND:
5326 cond = (var1 && var2);
5327 break;
5329 case HUAT_NAND:
5330 cond = !(var1 && var2);
5331 break;
5333 case HUAT_OR:
5334 cond = (var1 || var2);
5335 break;
5337 case HUAT_XOR:
5338 cond = (var1 && (!var2)) || ((!var1) && var2);
5339 break;
5341 case HUAT_ANDNOT:
5342 cond = (var1 && (!var2));
5343 break;
5345 case HUAT_BWAND:
5346 cond = (var1 & var2) ? TRUE : FALSE;
5347 break;
5349 case HUAT_BWNAND:
5350 cond = (var1 & var2) ? FALSE : TRUE;
5351 break;
5353 case HUAT_BWOR:
5354 cond = (var1 | var2) ? TRUE : FALSE;
5355 break;
5357 case HUAT_BWXOR:
5358 cond = (var1 ^ var2) ? TRUE : FALSE;
5359 break;
5361 case HUAT_BWANDNOT:
5362 cond = (var1 & (~var2)) ? TRUE : FALSE;
5363 break;
5366 if(!cond)
5368 return(FALSE);
5372 if(nha->nha_ValEnable)
5374 switch(nha->nha_ValVar)
5376 case HUAT_EITEMVALUE:
5377 //value = value;
5378 break;
5380 case HUAT_OITEMVALUE:
5381 value = origvalue;
5382 break;
5384 case HUAT_CONST:
5385 value = nha->nha_ValConst;
5386 break;
5388 case HUAT_CLICKCOUNT:
5389 value = nhi->nhi_ClickCount;
5390 break;
5392 case HUAT_CLICKTIME:
5394 ULONG currmicros;
5395 ULONG currsecs;
5397 if(nhi->nhi_HoldSeconds || nhi->nhi_HoldMicros)
5399 CurrentTime(&currsecs, &currmicros);
5400 value = (currsecs - nhi->nhi_HoldSeconds) * 1000;
5401 if(nhi->nhi_HoldMicros <= currmicros)
5403 value += (currmicros - nhi->nhi_HoldMicros) / 1000;
5404 } else {
5405 value -= (nhi->nhi_HoldMicros - currmicros) / 1000;
5407 } else {
5408 value = 0;
5410 break;
5413 case HUAT_QUALIFIERS:
5414 value = nch->nch_KeyQualifiers;
5415 break;
5417 case HUAT_ALLQUAL:
5418 value = nch->nch_KeyQualifiers|PeekQualifier();
5419 break;
5421 case HUAT_RANDOMBIT:
5422 value = _rand(nch->nch_ClsBase) & 1;
5423 break;
5425 case HUAT_RANDOMVAL:
5426 value = _rand(nch->nch_ClsBase);
5427 break;
5429 case HUAT_TIMER:
5431 ULONG currmicros;
5432 ULONG currsecs;
5434 CurrentTime(&currsecs, &currmicros);
5435 value = (currsecs * 1000) + (currmicros / 1000);
5436 break;
5439 case HUAT_LOCALVAR1:
5440 case HUAT_LOCALVAR2:
5441 case HUAT_LOCALVAR3:
5442 case HUAT_LOCALVAR4:
5443 case HUAT_LOCALVAR5:
5444 case HUAT_LOCALVAR6:
5445 case HUAT_LOCALVAR7:
5446 case HUAT_LOCALVAR8:
5447 value = nch->nch_LocalVars[nha->nha_ValVar - HUAT_LOCALVAR1];
5448 break;
5450 case HUAT_GLOBVARA:
5451 case HUAT_GLOBVARB:
5452 case HUAT_GLOBVARC:
5453 case HUAT_GLOBVARD:
5454 case HUAT_GLOBVARE:
5455 case HUAT_GLOBVARF:
5456 case HUAT_GLOBVARG:
5457 case HUAT_GLOBVARH:
5458 value = nch->nch_ClsBase->nh_GlobalVars[nha->nha_ValVar - HUAT_GLOBVARA];
5459 break;
5462 //KPRINTF(1, ("Call for action(%04lx) %lx = %ld %s\n", atype, uid, value, downevent ? "down" : "up"));
5463 switch(atype)
5465 case HUA_SHELL:
5466 case HUA_KEYSTRING:
5467 case HUA_VANILLA:
5468 case HUA_SOUND:
5470 struct ActionMsg *am;
5471 if(!nch->nch_ClsBase->nh_DTaskMsgPort)
5473 nInstallLastActionHero(nch);
5475 if(nch->nch_ClsBase->nh_DTaskMsgPort)
5477 if((am = AllocVec(sizeof(struct ActionMsg), MEMF_PUBLIC)))
5479 am->am_Msg.mn_Length = sizeof(struct ActionMsg);
5480 am->am_Msg.mn_ReplyPort = NULL;
5481 am->am_NCH = nch;
5482 am->am_Action = nha;
5483 PutMsg(nch->nch_ClsBase->nh_DTaskMsgPort, &am->am_Msg);
5486 break;
5489 case HUA_RAWKEY:
5490 nSendRawKey(nch, nha->nha_RawKey);
5491 break;
5493 case HUA_KEYMAP:
5495 UWORD iecode;
5496 if((uid > 0x70000) && (uid < 0x700e8))
5498 iecode = nch->nch_KeymapCfg.kmc_Keymap[uid & 0xff];
5499 KPRINTF(1,("Key %ld %s\n", iecode, downevent ? "DOWN" : "UP"));
5500 nch->nch_FakeEvent.ie_Class = IECLASS_RAWKEY;
5501 nch->nch_FakeEvent.ie_SubClass = 0;
5502 nSendRawKey(nch, downevent ? iecode : iecode|IECODE_UP_PREFIX);
5504 break;
5507 case HUA_MOUSEPOS:
5508 switch(nha->nha_MouseAxis)
5510 case HUAT_DELTAX:
5511 nch->nch_NewMouseRel = TRUE;
5512 nch->nch_MouseDeltaX += value;
5513 break;
5515 case HUAT_DELTAY:
5516 nch->nch_NewMouseRel = TRUE;
5517 nch->nch_MouseDeltaY += value;
5518 break;
5520 case HUAT_ABSX:
5521 if(nch->nch_MouseRangeY)
5523 nch->nch_NewMouseAbs = TRUE;
5525 nch->nch_MouseAbsX = value - nhi->nhi_RealMin;
5526 nch->nch_MouseRangeX = (nhi->nhi_RealMax - nhi->nhi_RealMin) + 1;
5527 break;
5529 case HUAT_ABSY:
5530 if(nch->nch_MouseRangeX)
5532 nch->nch_NewMouseAbs = TRUE;
5534 nch->nch_MouseAbsY = value - nhi->nhi_RealMin;
5535 nch->nch_MouseRangeY = (nhi->nhi_RealMax - nhi->nhi_RealMin) + 1;
5536 break;
5538 break;
5540 case HUA_QUALIFIER:
5541 qualmask = 1<<nha->nha_Qualifier;
5542 switch(nha->nha_QualMode)
5544 case HUAT_SET:
5545 nch->nch_KeyQualifiers |= qualmask;
5546 break;
5548 case HUAT_CLEAR:
5549 nch->nch_KeyQualifiers &= ~qualmask;
5550 break;
5552 case HUAT_TOGGLE:
5553 nch->nch_KeyQualifiers ^= qualmask;
5554 break;
5556 case HUAT_ASSIGN:
5557 nch->nch_KeyQualifiers &= ~qualmask;
5558 if(downevent)
5560 nch->nch_KeyQualifiers |= qualmask;
5562 break;
5564 break;
5566 case HUA_BUTTONS:
5568 UWORD iecode = IECODE_NOBUTTON;
5569 ULONG iequal = 0;
5570 BOOL newmouse = FALSE;
5572 switch(nha->nha_ButtonNo)
5574 case 1:
5575 iequal = IEQUALIFIER_LEFTBUTTON;
5576 iecode = IECODE_LBUTTON;
5577 break;
5579 case 2:
5580 iequal = IEQUALIFIER_RBUTTON;
5581 iecode = IECODE_RBUTTON;
5582 break;
5584 case 3:
5585 iequal = IEQUALIFIER_MIDBUTTON;
5586 iecode = IECODE_MBUTTON;
5587 break;
5589 case 4:
5590 iecode = RAWKEY_NM_BUTTON_FOURTH;
5591 newmouse = TRUE;
5592 break;
5595 switch(nha->nha_ButtonMode)
5597 case HUAT_SET:
5598 if((!newmouse) && (nch->nch_KeyQualifiers & iequal))
5600 iequal = 0;
5601 iecode = IECODE_NOBUTTON;
5602 } else {
5603 nch->nch_KeyQualifiers |= iequal;
5604 nch->nch_MouseButtons |= 1<<(nha->nha_ButtonNo-1);
5606 break;
5608 case HUAT_CLEAR:
5609 if(newmouse || (nch->nch_KeyQualifiers & iequal))
5611 nch->nch_KeyQualifiers &= ~iequal;
5612 nch->nch_MouseButtons &= ~(1<<(nha->nha_ButtonNo-1));
5613 iequal = 0;
5614 iecode |= IECODE_UP_PREFIX;
5615 } else {
5616 iequal = 0;
5617 iecode = IECODE_NOBUTTON;
5619 break;
5621 case HUAT_TOGGLE:
5622 if(newmouse)
5624 if(nch->nch_MouseButtons & (1<<(nha->nha_ButtonNo-1)))
5626 nch->nch_MouseButtons &= ~(1<<(nha->nha_ButtonNo-1));
5627 iecode |= IECODE_UP_PREFIX;
5628 } else {
5629 nch->nch_MouseButtons |= 1<<(nha->nha_ButtonNo-1);
5631 } else {
5632 if(nch->nch_KeyQualifiers & iequal)
5634 nch->nch_KeyQualifiers &= ~iequal;
5635 nch->nch_MouseButtons &= ~(1<<(nha->nha_ButtonNo-1));
5636 iequal = 0;
5637 iecode |= IECODE_UP_PREFIX;
5638 } else {
5639 nch->nch_KeyQualifiers |= iequal;
5640 nch->nch_MouseButtons |= 1<<(nha->nha_ButtonNo-1);
5643 break;
5645 case HUAT_ASSIGN:
5646 if(value)
5648 if((!newmouse) && (nch->nch_KeyQualifiers & iequal))
5650 iequal = 0;
5651 iecode = IECODE_NOBUTTON;
5652 } else {
5653 nch->nch_KeyQualifiers |= iequal;
5654 nch->nch_MouseButtons |= 1<<(nha->nha_ButtonNo-1);
5656 } else {
5657 if(newmouse || (nch->nch_KeyQualifiers & iequal))
5659 nch->nch_KeyQualifiers &= ~iequal;
5660 nch->nch_MouseButtons &= ~(1<<(nha->nha_ButtonNo-1));
5661 iequal = 0;
5662 iecode |= IECODE_UP_PREFIX;
5663 } else {
5664 iequal = 0;
5665 iecode = IECODE_NOBUTTON;
5668 break;
5670 default:
5671 iecode = IECODE_NOBUTTON;
5672 break;
5674 if(iecode != IECODE_NOBUTTON)
5676 if(newmouse)
5678 nSendRawKey(nch, iecode);
5680 nch->nch_FakeEvent.ie_Class = IECLASS_NEWMOUSE;
5681 nch->nch_FakeEvent.ie_SubClass = 0;
5682 nch->nch_FakeEvent.ie_Code = iecode;
5683 nch->nch_FakeEvent.ie_NextEvent = NULL;
5684 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers;
5685 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
5686 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
5687 nch->nch_InpIOReq->io_Command = IND_WRITEEVENT;
5688 DoIO((struct IORequest *) nch->nch_InpIOReq);
5689 } else {
5690 nch->nch_FakeEvent.ie_X = nch->nch_MouseDeltaX;
5691 nch->nch_FakeEvent.ie_Y = nch->nch_MouseDeltaY;
5692 nch->nch_FakeEvent.ie_Class = IECLASS_RAWMOUSE;
5693 nch->nch_FakeEvent.ie_SubClass = 0;
5694 nch->nch_FakeEvent.ie_Code = iecode;
5695 nch->nch_FakeEvent.ie_NextEvent = NULL;
5696 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers|IEQUALIFIER_RELATIVEMOUSE;
5697 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
5698 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
5699 nch->nch_InpIOReq->io_Command = nch->nch_OS4Hack ? IND_ADDEVENT : IND_WRITEEVENT;
5700 DoIO((struct IORequest *) nch->nch_InpIOReq);
5701 nch->nch_NewMouseRel = FALSE;
5702 nch->nch_MouseDeltaX = 0;
5703 nch->nch_MouseDeltaY = 0;
5706 break;
5709 case HUA_TABLET:
5711 KPRINTF(1, ("Tablet!\n"));
5712 switch(nha->nha_TabletAxis)
5714 case HUAT_ABSZ:
5715 nch->nch_MouseAbsZ = value - nhi->nhi_RealMin;
5716 nch->nch_MouseRangeZ = (nhi->nhi_RealMax - nhi->nhi_RealMin) + 1;
5717 break;
5719 case HUAT_PRESSURE:
5720 if(nhi->nhi_RealMax)
5722 nch->nch_TabPressure = ((0x1fffffff / nhi->nhi_RealMax)*value)<<2;
5723 nch->nch_VldPressure = TRUE;
5725 break;
5727 case HUAT_XROT:
5728 if(nhi->nhi_RealMax)
5730 nch->nch_TabRotX = ((0x3fffffff / nhi->nhi_RealMax)*value)<<2;
5731 nch->nch_VldRotX = TRUE;
5733 break;
5735 case HUAT_YROT:
5736 if(nhi->nhi_RealMax)
5738 nch->nch_TabRotY = ((0x3fffffff / nhi->nhi_RealMax)*value)<<2;
5739 nch->nch_VldRotY = TRUE;
5741 break;
5743 case HUAT_ZROT:
5744 if(nhi->nhi_RealMax)
5746 nch->nch_TabRotZ = ((0x3fffffff / nhi->nhi_RealMax)*value)<<2;
5747 nch->nch_VldRotZ = TRUE;
5749 break;
5751 case HUAT_PROX:
5752 nch->nch_TabProx = value;
5753 nch->nch_VldProx = TRUE;
5754 break;
5756 if(nch->nch_MouseRangeX && nch->nch_MouseRangeY)
5758 nch->nch_NewMouseAbs = TRUE;
5760 break;
5763 case HUA_WHEEL:
5765 UWORD wheeldist = 0;
5766 UWORD wheeliecode = IECODE_NOBUTTON;
5767 switch(nha->nha_WheelMode)
5769 case HUAT_DELTAX:
5770 if(value > 0)
5772 wheeliecode = RAWKEY_NM_WHEEL_LEFT;
5773 wheeldist = value;
5775 else if(value < 0)
5777 wheeliecode = RAWKEY_NM_WHEEL_RIGHT;
5778 wheeldist = -value;
5780 break;
5782 case HUAT_DELTAY:
5783 if(value > 0)
5785 wheeliecode = RAWKEY_NM_WHEEL_UP;
5786 wheeldist = value;
5788 else if(value < 0)
5790 wheeliecode = RAWKEY_NM_WHEEL_DOWN;
5791 wheeldist = -value;
5793 break;
5795 case HUAT_LEFT:
5796 wheeliecode = RAWKEY_NM_WHEEL_LEFT;
5797 wheeldist = nha->nha_WheelDist;
5798 break;
5800 case HUAT_RIGHT:
5801 wheeliecode = RAWKEY_NM_WHEEL_RIGHT;
5802 wheeldist = nha->nha_WheelDist;
5803 break;
5805 case HUAT_UP:
5806 wheeliecode = RAWKEY_NM_WHEEL_UP;
5807 wheeldist = nha->nha_WheelDist;
5808 break;
5810 case HUAT_DOWN:
5811 wheeliecode = RAWKEY_NM_WHEEL_DOWN;
5812 wheeldist = nha->nha_WheelDist;
5813 break;
5815 if(wheeliecode != IECODE_NOBUTTON)
5817 if(downevent)
5819 while(wheeldist--)
5821 KPRINTF(1, ("Doing wheel %ld\n", wheeliecode));
5822 nSendRawKey(nch, wheeliecode);
5823 #if 0
5824 nch->nch_FakeEvent.ie_Class = IECLASS_NEWMOUSE;
5825 nch->nch_FakeEvent.ie_SubClass = 0;
5826 nch->nch_FakeEvent.ie_Code = wheeliecode;
5827 nch->nch_FakeEvent.ie_NextEvent = NULL;
5828 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers;
5829 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
5830 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
5831 nch->nch_InpIOReq->io_Command = IND_WRITEEVENT;
5832 DoIO((struct IORequest *) nch->nch_InpIOReq);
5833 #endif
5836 nSendRawKey(nch, wheeliecode|IECODE_UP_PREFIX);
5837 #if 0
5838 nch->nch_FakeEvent.ie_Class = IECLASS_NEWMOUSE;
5839 nch->nch_FakeEvent.ie_SubClass = 0;
5840 nch->nch_FakeEvent.ie_Code = wheeliecode|IECODE_UP_PREFIX;
5841 nch->nch_FakeEvent.ie_NextEvent = NULL;
5842 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers;
5843 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
5844 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
5845 nch->nch_InpIOReq->io_Command = IND_WRITEEVENT;
5846 DoIO((struct IORequest *) nch->nch_InpIOReq);
5847 #endif
5850 break;
5853 case HUA_DIGJOY:
5855 ULONG mask = 0;
5856 /* ULONG oldval; */
5857 ULONG *stateptr = &nch->nch_LLPortState[nha->nha_JoypadPort];
5859 switch(nha->nha_JoypadFeat)
5861 case HUAT_LEFT:
5862 mask = JPF_JOY_LEFT;
5863 break;
5865 case HUAT_RIGHT:
5866 mask = JPF_JOY_RIGHT;
5867 break;
5869 case HUAT_UP:
5870 mask = JPF_JOY_UP;
5871 break;
5873 case HUAT_DOWN:
5874 mask = JPF_JOY_DOWN;
5875 break;
5877 case HUAT_RED:
5878 mask = JPF_BUTTON_RED;
5879 break;
5881 case HUAT_BLUE:
5882 mask = JPF_BUTTON_BLUE;
5883 break;
5885 case HUAT_GREEN:
5886 mask = JPF_BUTTON_GREEN;
5887 break;
5889 case HUAT_YELLOW:
5890 mask = JPF_BUTTON_YELLOW;
5891 break;
5893 case HUAT_FORWARD:
5894 mask = JPF_BUTTON_FORWARD;
5895 break;
5897 case HUAT_REVERSE:
5898 mask = JPF_BUTTON_REVERSE;
5899 break;
5901 case HUAT_PLAY:
5902 mask = JPF_BUTTON_PLAY;
5903 break;
5905 case HUAT_HATSWITCH:
5906 mask = JP_DIRECTION_MASK;
5907 stateptr = &nch->nch_LLHatswitch[nha->nha_JoypadPort];
5908 break;
5911 /* oldval = *stateptr; */
5912 switch(nha->nha_JoypadOp)
5914 case HUAT_SET:
5915 *stateptr |= mask;
5916 break;
5918 case HUAT_CLEAR:
5919 *stateptr &= ~mask;
5920 break;
5922 case HUAT_TOGGLE:
5923 *stateptr ^= mask;
5924 break;
5926 case HUAT_ASSIGN:
5927 if(nha->nha_JoypadFeat == HUAT_HATSWITCH)
5929 value -= nhi->nhi_RealMin;
5930 if((value >= 0) && (value < 8))
5932 mask = LLHatswitchEncoding[value];
5933 } else {
5934 mask = 0;
5936 /*oldval = *stateptr;
5937 oldval &= ~JP_DIRECTION_MASK;
5938 oldval |= mask;
5939 *stateptr = oldval;*/
5940 *stateptr = mask;
5941 } else {
5942 if(value)
5944 *stateptr |= mask;
5945 } else {
5946 *stateptr &= ~mask;
5949 break;
5951 break;
5954 case HUA_ANALOGJOY:
5956 ULONG *stateptr = &nch->nch_LLAnalogue[nha->nha_JoypadPort];
5957 if((nhi->nhi_RealMin != 0) || (nhi->nhi_RealMax != 255))
5959 // scale
5960 value -= nhi->nhi_RealMin;
5961 value <<= 8;
5962 value /= (nhi->nhi_RealMax - nhi->nhi_RealMin);
5964 switch(nha->nha_APadFeat)
5966 case HUAT_ABSX:
5967 *stateptr = (*stateptr & ~JP_XAXIS_MASK) | (value & JP_XAXIS_MASK) | JP_TYPE_ANALOGUE;
5968 break;
5970 case HUAT_ABSY:
5971 *stateptr = (*stateptr & ~JP_YAXIS_MASK) | ((value<<8) & JP_YAXIS_MASK) | JP_TYPE_ANALOGUE;
5972 break;
5974 break;
5977 case HUA_OUTPUT:
5979 ULONG pos;
5980 struct NepHidItem *nhi;
5982 nhi = nFindItemID(nch, nha->nha_OutItem, REPORT_MAIN_OUTPUT, &pos);
5983 if(nhi)
5985 if(nhi->nhi_Flags & RPF_MAIN_VARIABLE)
5987 switch(nha->nha_OutOp)
5989 case HUAT_SET:
5990 nhi->nhi_OldValue = TRUE;
5991 break;
5993 case HUAT_CLEAR:
5994 nhi->nhi_OldValue = FALSE;
5995 break;
5997 case HUAT_TOGGLE:
5998 nhi->nhi_OldValue = nhi->nhi_OldValue ? FALSE : TRUE;
5999 break;
6001 case HUAT_ASSIGN:
6002 nhi->nhi_OldValue = value;
6003 break;
6005 } else {
6006 nParseArrayString(nch, nhi, nha->nha_OutArray);
6008 nhi->nhi_Collection->nhc_Report->nhr_OutTouched = TRUE;
6009 nch->nch_OutFeatTouched = TRUE;
6011 break;
6014 case HUA_FEATURE:
6016 ULONG pos;
6017 struct NepHidItem *nhi;
6019 nhi = nFindItemID(nch, nha->nha_FeatItem, REPORT_MAIN_FEATURE, &pos);
6020 if(nhi)
6022 if(nhi->nhi_Flags & RPF_MAIN_VARIABLE)
6024 switch(nha->nha_FeatOp)
6026 case HUAT_SET:
6027 nhi->nhi_OldValue = TRUE;
6028 break;
6030 case HUAT_CLEAR:
6031 nhi->nhi_OldValue = FALSE;
6032 break;
6034 case HUAT_TOGGLE:
6035 nhi->nhi_OldValue = nhi->nhi_OldValue ? FALSE : TRUE;
6036 break;
6038 case HUAT_ASSIGN:
6039 nhi->nhi_OldValue = value;
6040 break;
6042 } else {
6043 nParseArrayString(nch, nhi, nha->nha_OutArray);
6045 nhi->nhi_Collection->nhc_Report->nhr_FeatTouched = TRUE;
6046 nch->nch_OutFeatTouched = TRUE;
6048 break;
6051 case HUA_MISC:
6052 nch->nch_FakeEvent.ie_Class = IECLASS_NULL;
6053 nch->nch_FakeEvent.ie_SubClass = 0;
6054 nch->nch_FakeEvent.ie_Code = IECODE_NOBUTTON;
6055 nch->nch_FakeEvent.ie_NextEvent = NULL;
6056 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers;
6057 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
6058 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
6059 nch->nch_InpIOReq->io_Command = IND_WRITEEVENT;
6060 switch(nha->nha_MiscMode)
6062 case HUAT_DISPLAYBEEP:
6063 case HUAT_WIN2FRONT:
6064 case HUAT_WIN2BACK:
6065 case HUAT_ZIPWINDOW:
6066 case HUAT_SCREENCYCLE:
6067 case HUAT_WB2FRONT:
6068 case HUAT_ACTWINDOW:
6070 struct ActionMsg *am;
6071 if(!nch->nch_ClsBase->nh_DTaskMsgPort)
6073 nInstallLastActionHero(nch);
6075 if(nch->nch_ClsBase->nh_DTaskMsgPort)
6077 if((am = AllocVec(sizeof(struct ActionMsg), MEMF_PUBLIC)))
6079 am->am_Msg.mn_Length = sizeof(struct ActionMsg);
6080 am->am_Msg.mn_ReplyPort = NULL;
6081 am->am_NCH = nch;
6082 am->am_Action = nha;
6083 PutMsg(nch->nch_ClsBase->nh_DTaskMsgPort, &am->am_Msg);
6086 break;
6089 case HUAT_CLOSEWINDOW:
6090 nch->nch_FakeEvent.ie_Class = IECLASS_CLOSEWINDOW;
6091 DoIO((struct IORequest *) nch->nch_InpIOReq);
6092 break;
6094 case HUAT_REBOOT:
6095 nch->nch_CDC->cdc_EnableKBReset = TRUE;
6096 nch->nch_KeyQualifiers |= IEQUALIFIER_CONTROL|IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND;
6097 nCheckReset(nch);
6098 break;
6100 case HUAT_FLUSHEVENTS:
6101 nFlushEvents(nch);
6102 break;
6104 default:
6105 break;
6107 break;
6109 case HUA_VARIABLES:
6111 LONG *tarvarptr = NULL;
6113 switch(nha->nha_TarVar)
6115 case HUAT_LOCALVAR1:
6116 case HUAT_LOCALVAR2:
6117 case HUAT_LOCALVAR3:
6118 case HUAT_LOCALVAR4:
6119 case HUAT_LOCALVAR5:
6120 case HUAT_LOCALVAR6:
6121 case HUAT_LOCALVAR7:
6122 case HUAT_LOCALVAR8:
6123 tarvarptr = &nch->nch_LocalVars[nha->nha_TarVar - HUAT_LOCALVAR1];
6124 break;
6126 case HUAT_GLOBVARA:
6127 case HUAT_GLOBVARB:
6128 case HUAT_GLOBVARC:
6129 case HUAT_GLOBVARD:
6130 case HUAT_GLOBVARE:
6131 case HUAT_GLOBVARF:
6132 case HUAT_GLOBVARG:
6133 case HUAT_GLOBVARH:
6134 tarvarptr = &nch->nch_ClsBase->nh_GlobalVars[nha->nha_TarVar - HUAT_GLOBVARA];
6135 break;
6137 if(!tarvarptr)
6139 return(FALSE);
6141 switch(nha->nha_TarVarOp)
6143 case HUAT_ASSIGN:
6144 *tarvarptr = value;
6145 break;
6147 case HUAT_ADD:
6148 *tarvarptr += value;
6149 break;
6151 case HUAT_SUB:
6152 *tarvarptr -= value;
6153 break;
6155 case HUAT_MULTIPLY:
6156 *tarvarptr *= value;
6157 break;
6159 case HUAT_DIVIDE:
6160 if(value)
6162 *tarvarptr /= value;
6164 break;
6166 case HUAT_MODULO:
6167 if(value)
6169 *tarvarptr = value;
6171 break;
6173 case HUAT_AND:
6174 *tarvarptr = *tarvarptr && value;
6175 break;
6177 case HUAT_NAND:
6178 *tarvarptr = !(*tarvarptr && value);
6179 break;
6181 case HUAT_ANDNOT:
6182 *tarvarptr = *tarvarptr && (!value);
6183 break;
6185 case HUAT_OR:
6186 *tarvarptr = *tarvarptr || value;
6187 break;
6189 case HUAT_XOR:
6190 *tarvarptr = (*tarvarptr ^ value) ? TRUE : FALSE;
6191 break;
6193 case HUAT_BWAND:
6194 *tarvarptr &= value;
6195 break;
6197 case HUAT_BWNAND:
6198 *tarvarptr = ~(*tarvarptr & value);
6199 break;
6201 case HUAT_BWANDNOT:
6202 *tarvarptr &= ~value;
6203 break;
6205 case HUAT_BWOR:
6206 *tarvarptr |= value;
6207 break;
6209 case HUAT_BWXOR:
6210 *tarvarptr ^= value;
6211 break;
6213 case HUAT_ASL:
6214 *tarvarptr <<= value;
6215 break;
6217 case HUAT_ASR:
6218 *tarvarptr >>= value;
6219 break;
6221 return(TRUE);
6224 case HUA_EXTRAWKEY:
6225 #if 0 // FIXME looks like AROS does not support this (yet?)
6226 nch->nch_FakeEvent.ie_Class = IECLASS_EXTRAWKEY;
6227 nch->nch_FakeEvent.ie_SubClass = 0;
6228 nch->nch_FakeEvent.ie_Code = nha->nha_RawKey;
6229 // using ie.dead.ie_prev1DownCode instead of ie_extkey.ie_extkey1
6230 nch->nch_FakeEvent.ie_position.ie_dead.ie_prev1DownCode = 0xe0;
6231 nch->nch_FakeEvent.ie_position.ie_dead.ie_prev1DownQual = nha->nha_RawKey;
6232 nch->nch_FakeEvent.ie_NextEvent = NULL;
6233 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers;
6234 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
6235 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
6236 nch->nch_InpIOReq->io_Command = IND_WRITEEVENT;
6237 DoIO((struct IORequest *) nch->nch_InpIOReq);
6238 #endif
6239 break;
6242 return(res);
6244 /* \\\ */
6246 /* /// "nFlushEvents()" */
6247 void nFlushEvents(struct NepClassHid *nch)
6249 struct PsdPipe *pp;
6250 ULONG buflen;
6251 LONG ioerr;
6253 struct NepHidReport *nhr;
6255 /* output/feature pipes */
6256 if(nch->nch_OutFeatTouched)
6258 nch->nch_OutFeatTouched = FALSE;
6259 pp = nch->nch_EP0Pipe;
6260 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
6261 while(nhr->nhr_Node.ln_Succ)
6263 if(nhr->nhr_OutTouched)
6265 KPRINTF(1, ("Out Report %ld touched...\n", nhr->nhr_ReportID));
6266 buflen = (nhr->nhr_ReportOutSize+7)>>3;
6267 if(nch->nch_UsesReportID)
6269 *nch->nch_EPOutBuf = nhr->nhr_ReportID;
6270 nGenerateOutReport(nch, nhr, nch->nch_EPOutBuf+1);
6271 buflen++;
6272 psdPipeSetup(pp, URTF_OUT|URTF_CLASS|URTF_INTERFACE,
6273 UHR_SET_REPORT, (ULONG) nhr->nhr_ReportID|0x0200, nch->nch_IfNum);
6274 } else {
6275 nGenerateOutReport(nch, nhr, nch->nch_EPOutBuf);
6276 psdPipeSetup(pp, URTF_OUT|URTF_CLASS|URTF_INTERFACE,
6277 UHR_SET_REPORT, 0x0200, nch->nch_IfNum);
6279 KPRINTF(1, ("Len: %ld [%02lx %02lx]", buflen, nch->nch_EPOutBuf[0], nch->nch_EPOutBuf[1]));
6280 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
6281 "HID OUT Report %02lx Debug (%ld bytes):", nhr->nhr_ReportID, buflen);
6282 nDebugMem(nch, nch->nch_EPOutBuf, buflen);*/
6284 if((ioerr = psdDoPipe(pp, nch->nch_EPOutBuf, buflen)))
6286 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
6287 "SET_REPORT(%lx, %ld) failed: %s (%ld)!",
6288 nhr->nhr_ReportID|0x0200, buflen,
6289 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
6291 nhr->nhr_OutTouched = FALSE;
6293 if(nhr->nhr_FeatTouched)
6295 KPRINTF(1, ("Feat Report %ld touched...\n", nhr->nhr_ReportID));
6296 buflen = (nhr->nhr_ReportFeatSize+7)>>3;
6297 if(nch->nch_UsesReportID)
6299 *nch->nch_EPOutBuf = nhr->nhr_ReportID;
6300 nGenerateFeatReport(nch, nhr, nch->nch_EPOutBuf+1);
6301 buflen++;
6302 psdPipeSetup(pp, URTF_OUT|URTF_CLASS|URTF_INTERFACE,
6303 UHR_SET_REPORT, (ULONG) nhr->nhr_ReportID|0x0300, nch->nch_IfNum);
6304 } else {
6305 nGenerateFeatReport(nch, nhr, nch->nch_EPOutBuf);
6306 psdPipeSetup(pp, URTF_OUT|URTF_CLASS|URTF_INTERFACE,
6307 UHR_SET_REPORT, 0x0300, nch->nch_IfNum);
6309 KPRINTF(1, ("Len: %ld [%02lx %02lx]", buflen, nch->nch_EPOutBuf[0], nch->nch_EPOutBuf[1]));
6310 if((ioerr = psdDoPipe(pp, nch->nch_EPOutBuf, buflen)))
6312 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
6313 "SET_REPORT(%lx, %ld) failed: %s (%ld)!",
6314 nhr->nhr_ReportID|0x0300, buflen,
6315 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
6316 }/* else {
6317 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
6318 "SET_REPORT(%lx, %ld)=%02lx%02lx okay!",
6319 nhr->nhr_ReportID|0x0300, buflen,
6320 nch->nch_EPOutBuf[1], nch->nch_EPOutBuf[2]);
6322 nhr->nhr_FeatTouched = FALSE;
6324 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
6327 if(nch->nch_NewMouseRel && (nch->nch_MouseDeltaX || nch->nch_MouseDeltaY))
6329 KPRINTF(1, ("Mouse rel movement...\n"));
6330 nch->nch_FakeEvent.ie_X = nch->nch_MouseDeltaX;
6331 nch->nch_FakeEvent.ie_Y = nch->nch_MouseDeltaY;
6332 nch->nch_FakeEvent.ie_Class = IECLASS_RAWMOUSE;
6333 nch->nch_FakeEvent.ie_SubClass = 0;
6334 nch->nch_FakeEvent.ie_Code = IECODE_NOBUTTON;
6335 nch->nch_FakeEvent.ie_NextEvent = NULL;
6336 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers|IEQUALIFIER_RELATIVEMOUSE;
6337 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
6338 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
6339 nch->nch_InpIOReq->io_Command = nch->nch_OS4Hack ? IND_ADDEVENT : IND_WRITEEVENT;
6340 DoIO((struct IORequest *) nch->nch_InpIOReq);
6341 nch->nch_NewMouseRel = FALSE;
6342 nch->nch_MouseDeltaX = 0;
6343 nch->nch_MouseDeltaY = 0;
6345 if(nch->nch_NewMouseAbs)
6347 ULONG *tagptr = nch->nch_TabTags;
6348 KPRINTF(1, ("Mouse abs movement...\n"));
6349 nch->nch_FakeEvent.ie_EventAddress = &nch->nch_TabletEvent;
6350 nch->nch_TabletEvent.ient_RangeX = nch->nch_MouseRangeX;
6351 nch->nch_TabletEvent.ient_RangeY = nch->nch_MouseRangeY;
6352 nch->nch_TabletEvent.ient_TabletX = nch->nch_MouseAbsX;
6353 nch->nch_TabletEvent.ient_TabletY = nch->nch_MouseAbsY;
6354 nch->nch_TabletEvent.ient_TagList = (struct TagItem *) tagptr;
6355 if(nch->nch_MouseRangeZ)
6357 KPRINTF(1, ("AbsZ %ld\n", nch->nch_MouseAbsZ));
6358 *tagptr++ = TABLETA_TabletZ;
6359 *tagptr++ = nch->nch_MouseAbsZ;
6360 *tagptr++ = TABLETA_RangeZ;
6361 *tagptr++ = nch->nch_MouseRangeZ;
6363 if(nch->nch_VldRotX)
6365 KPRINTF(1, ("AngleX %ld\n", nch->nch_TabRotX));
6366 *tagptr++ = TABLETA_AngleX;
6367 *tagptr++ = nch->nch_TabRotX;
6369 if(nch->nch_VldRotY)
6371 KPRINTF(1, ("AngleY %ld\n", nch->nch_TabRotY));
6372 *tagptr++ = TABLETA_AngleY;
6373 *tagptr++ = nch->nch_TabRotY;
6375 if(nch->nch_VldRotZ)
6377 KPRINTF(1, ("AngleZ %ld\n", nch->nch_TabRotZ));
6378 *tagptr++ = TABLETA_AngleZ;
6379 *tagptr++ = nch->nch_TabRotZ;
6381 if(nch->nch_VldPressure)
6383 KPRINTF(1, ("Pressure %ld\n", nch->nch_TabPressure));
6384 *tagptr++ = TABLETA_Pressure;
6385 *tagptr++ = nch->nch_TabPressure;
6387 *tagptr++ = TABLETA_ButtonBits;
6388 *tagptr++ = nch->nch_MouseButtons;
6389 if(nch->nch_VldProx)
6391 KPRINTF(1, ("InProx %ld\n", nch->nch_TabProx));
6392 *tagptr++ = TABLETA_InProximity;
6393 *tagptr++ = nch->nch_TabProx;
6395 *tagptr = TAG_END;
6396 nch->nch_FakeEvent.ie_Class = IECLASS_NEWPOINTERPOS;
6397 nch->nch_FakeEvent.ie_SubClass = IESUBCLASS_NEWTABLET;
6398 nch->nch_FakeEvent.ie_Code = IECODE_NOBUTTON;
6399 nch->nch_FakeEvent.ie_NextEvent = NULL;
6400 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers;
6401 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
6402 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
6403 nch->nch_InpIOReq->io_Command = IND_WRITEEVENT;
6404 DoIO((struct IORequest *) nch->nch_InpIOReq);
6405 nch->nch_NewMouseAbs = FALSE;
6407 nCheckReset(nch);
6409 /* \\\ */
6411 /* /// "nSendRawKey()" */
6412 void nSendRawKey(struct NepClassHid *nch, UWORD key)
6414 nch->nch_FakeEvent.ie_Class = IECLASS_RAWKEY;
6415 nch->nch_FakeEvent.ie_SubClass = 0;
6416 nch->nch_FakeEvent.ie_Code = key;
6417 nch->nch_FakeEvent.ie_NextEvent = NULL;
6418 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers;
6419 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
6420 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
6421 nch->nch_InpIOReq->io_Command = nch->nch_OS4Hack ? IND_ADDEVENT : IND_WRITEEVENT;
6422 DoIO((struct IORequest *) nch->nch_InpIOReq);
6424 /* \\\ */
6426 /* /// "nCheckReset()" */
6427 void nCheckReset(struct NepClassHid *nch)
6429 if(nch->nch_CDC->cdc_EnableKBReset &&
6430 (nch->nch_KeyQualifiers & (IEQUALIFIER_CONTROL|IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND)) ==
6431 (IEQUALIFIER_CONTROL|IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND))
6433 struct MsgPort *mp;
6434 struct IOStdReq *ioreq;
6435 struct Interrupt tempint;
6436 struct Node *node;
6437 struct List *listhead = NULL;
6438 BOOL haskbh = FALSE;
6439 KPRINTF(20, ("Reboot!\n"));
6441 if(nch->nch_CDC->cdc_EnableRH)
6443 if((mp = CreateMsgPort()))
6445 if((ioreq = (struct IOStdReq *) CreateIORequest(mp, sizeof(struct IOStdReq))))
6447 if(!OpenDevice("keyboard.device", 0, (struct IORequest *) ioreq, 0))
6449 /* Find list header of reset handlers */
6450 tempint.is_Node.ln_Pred = NULL;
6451 tempint.is_Node.ln_Succ = NULL;
6452 tempint.is_Node.ln_Type = NT_INTERRUPT;
6453 tempint.is_Node.ln_Pri = 32;
6454 tempint.is_Node.ln_Name = "";
6455 tempint.is_Code = NULL;
6456 ioreq->io_Command = KBD_ADDRESETHANDLER;
6457 ioreq->io_Data = &tempint;
6458 Forbid();
6459 DoIO((struct IORequest *) ioreq);
6460 if((node = tempint.is_Node.ln_Pred))
6462 while(node->ln_Pred)
6464 node = node->ln_Pred;
6466 listhead = (struct List *) node;
6468 ioreq->io_Command = KBD_REMRESETHANDLER;
6469 DoIO((struct IORequest *) ioreq);
6470 Permit();
6471 if(listhead)
6473 node = listhead->lh_Head;
6474 while(node->ln_Succ)
6476 KPRINTF(20, ("Kicking %s\n", node->ln_Name));
6477 Cause((struct Interrupt *) node);
6478 haskbh = TRUE;
6479 node = node->ln_Succ;
6481 KPRINTF(20, ("Done... awaiting doom\n"));
6482 if(haskbh)
6484 psdDelayMS(nch->nch_CDC->cdc_ResetDelay*1000);
6486 } else {
6487 KPRINTF(20, ("Reset handler list not found!\n"));
6489 CloseDevice((struct IORequest *) ioreq);
6491 DeleteIORequest((struct IORequest *) ioreq);
6493 DeleteMsgPort(mp);
6496 ColdReboot();
6498 else if(nch->nch_CDC->cdc_EnableKBReset &&
6499 (nch->nch_KeyQualifiers & IEQUALIFIER_CONTROL) &&
6500 (nch->nch_KeyQualifiers & (IEQUALIFIER_LALT|IEQUALIFIER_RALT)) &&
6501 nch->nch_FakeEvent.ie_Code == RAWKEY_DELETE)
6503 KPRINTF(20, ("Reboot!\n"));
6504 ShutdownA(SD_ACTION_COLDREBOOT);
6507 /* \\\ */
6509 /* /// "nLoadItem()" */
6510 BOOL nLoadItem(struct NepClassHid *nch, struct PsdIFFContext *rppic, struct List *lst, UWORD idbase)
6512 struct PsdIFFContext *itpic;
6513 struct PsdIFFContext *actpic;
6514 struct NepHidAction *nha;
6515 ULONG newform[3];
6516 ULONG buf[2];
6517 struct NepHidActionChunk *nhac;
6518 STRPTR tmpstr;
6520 psdSafeRawDoFmt((STRPTR) buf, 8, "I%03lx", GET_WTYPE(lst) - idbase + 1);
6521 newform[0] = AROS_LONG2BE(ID_FORM);
6522 newform[1] = AROS_LONG2BE(4);
6523 newform[2] = *buf;
6524 itpic = psdFindCfgForm(rppic, AROS_LONG2BE(newform[2]));
6525 if(!itpic)
6527 return(FALSE);
6529 actpic = psdFindCfgForm(itpic, MAKE_ID('A','C','T','N'));
6530 while(actpic)
6532 if((nhac = psdGetCfgChunk(actpic, MAKE_ID('A','C','D','F'))))
6534 if((nha = nAllocAction(nch, lst, 0)))
6536 CopyMem(&nhac->nhac_Type, &nha->nha_Type, min(AROS_LONG2BE(nhac->nhac_Length), sizeof(struct NepHidActionChunk) - 8));
6537 if((tmpstr = psdGetStringChunk(actpic, MAKE_ID('S','N','D','F'))))
6539 strncpy(nha->nha_SoundFile, tmpstr, 255);
6540 psdFreeVec(tmpstr);
6542 if((tmpstr = psdGetStringChunk(actpic, MAKE_ID('V','A','N','S'))))
6544 strncpy(nha->nha_VanillaString, tmpstr, 79);
6545 psdFreeVec(tmpstr);
6547 if((tmpstr = psdGetStringChunk(actpic, MAKE_ID('K','E','Y','S'))))
6549 strncpy(nha->nha_KeyString, tmpstr, 79);
6550 psdFreeVec(tmpstr);
6552 if((tmpstr = psdGetStringChunk(actpic, MAKE_ID('E','X','E','S'))))
6554 strncpy(nha->nha_ExeString, tmpstr, 79);
6555 psdFreeVec(tmpstr);
6557 if((tmpstr = psdGetStringChunk(actpic, MAKE_ID('O','A','R','R'))))
6559 strncpy(nha->nha_OutArray, tmpstr, 255);
6560 psdFreeVec(tmpstr);
6563 psdFreeVec(nhac);
6565 actpic = psdNextCfgForm(actpic);
6567 return(TRUE);
6569 /* \\\ */
6571 /* /// "nSaveItem()" */
6572 struct PsdIFFContext * nSaveItem(struct NepClassHid *nch, struct PsdIFFContext *rppic, struct List *lst, UWORD idbase)
6574 struct PsdIFFContext *itpic;
6575 struct PsdIFFContext *actpic;
6576 struct NepHidAction *nha;
6577 ULONG newform[3];
6578 ULONG buf[2];
6579 struct NepHidActionChunk nhac;
6580 BOOL isdefault = TRUE;
6582 if(!lst->lh_Head->ln_Succ)
6584 return(NULL);
6586 nha = (struct NepHidAction *) lst->lh_Head;
6587 while(nha->nha_Node.ln_Succ)
6589 if(!nha->nha_IsDefault)
6591 isdefault = FALSE;
6593 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
6595 if(isdefault)
6597 return(NULL);
6599 psdSafeRawDoFmt((STRPTR) buf, 8, "I%03lx", GET_WTYPE(lst) - idbase + 1);
6600 newform[0] = AROS_LONG2BE(ID_FORM);
6601 newform[1] = AROS_LONG2BE(4);
6602 newform[2] = *buf;
6603 itpic = psdFindCfgForm(rppic, AROS_LONG2BE(newform[2]));
6604 if(!itpic)
6606 itpic = psdAddCfgEntry(rppic, newform);
6607 if(!itpic)
6609 return(NULL);
6612 nhac.nhac_ID = AROS_LONG2BE(MAKE_ID('A','C','D','F'));
6613 nhac.nhac_Length = AROS_LONG2BE(sizeof(struct NepHidActionChunk)-8);
6614 nha = (struct NepHidAction *) lst->lh_Head;
6615 while(nha->nha_Node.ln_Succ)
6617 if(!nha->nha_IsDefault)
6619 isdefault = FALSE;
6621 newform[2] = AROS_LONG2BE(MAKE_ID('A','C','T','N'));
6622 actpic = psdAddCfgEntry(itpic, newform);
6623 if(!actpic)
6625 break;
6627 CopyMem(&nha->nha_Type, &nhac.nhac_Type, sizeof(struct NepHidActionChunk)-8);
6628 psdAddCfgEntry(actpic, &nhac);
6629 if(*nha->nha_SoundFile)
6631 psdAddStringChunk(actpic, MAKE_ID('S','N','D','F'), nha->nha_SoundFile);
6633 if(*nha->nha_VanillaString)
6635 psdAddStringChunk(actpic, MAKE_ID('V','A','N','S'), nha->nha_VanillaString);
6637 if(*nha->nha_KeyString)
6639 psdAddStringChunk(actpic, MAKE_ID('K','E','Y','S'), nha->nha_KeyString);
6641 if(*nha->nha_ExeString)
6643 psdAddStringChunk(actpic, MAKE_ID('E','X','E','S'), nha->nha_ExeString);
6645 if(*nha->nha_OutArray)
6647 psdAddStringChunk(actpic, MAKE_ID('O','A','R','R'), nha->nha_OutArray);
6649 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
6651 return(itpic);
6653 /* \\\ */
6655 /* /// "nReadJoyPort()" */
6656 AROS_LH1(ULONG, nReadJoyPort,
6657 AROS_LHA(ULONG, port, D0),
6658 struct Library *, LowLevelBase, 5, hid)
6660 AROS_LIBFUNC_INIT
6662 struct NepHidBase *nh;
6663 struct NepClassHid *nch;
6664 ULONG result = JP_TYPE_NOTAVAIL;
6665 ULONG mode;
6667 if(!(nh = (struct NepHidBase *) FindName(&SysBase->LibList, GM_UNIQUENAME(libname))))
6669 return(result);
6672 result = AROS_CALL1(ULONG, nh->nh_LLOldReadJoyPort,
6673 AROS_LCA(ULONG, port, D0),
6674 struct Library *, nh->nh_LowLevelBase);
6676 KPRINTF(40, ("Before %08lx\n", result));
6677 if(port < 4)
6679 Forbid();
6680 nch = (struct NepClassHid *) nh->nh_Interfaces.lh_Head;
6681 while(nch->nch_Node.ln_Succ)
6683 mode = nch->nch_CDC->cdc_LLPortMode[port];
6684 if(nh->nh_LLAnalogueOverride[port] && nch->nch_LLAnalogue[port])
6686 mode = 4;
6689 switch(mode)
6691 // case 0: /* don't touch */
6692 // break;
6694 case 1: /* overwrite with USB */
6695 result = nch->nch_LLPortState[port] | nch->nch_LLHatswitch[port] | JP_TYPE_GAMECTLR;
6696 break;
6698 case 2: /* merge with USB */
6699 if(((result & JP_TYPE_MASK) == JP_TYPE_GAMECTLR) ||
6700 ((result & JP_TYPE_MASK) == JP_TYPE_JOYSTK) ||
6701 ((result & JP_TYPE_MASK) == JP_TYPE_UNKNOWN) ||
6702 (!result))
6704 result = (result & (JP_BUTTON_MASK|JP_DIRECTION_MASK)) | nch->nch_LLPortState[port] | nch->nch_LLHatswitch[port] | JP_TYPE_GAMECTLR;
6706 break;
6708 case 3: /* disable */
6709 result = JP_TYPE_NOTAVAIL;
6710 break;
6712 case 4: /* overwrite with analogue USB */
6713 if(nch->nch_LLAnalogue[port])
6715 result = (nch->nch_LLPortState[port] & ~JP_DIRECTION_MASK) | (nch->nch_LLAnalogue[port] & JP_XYAXIS_MASK) | nch->nch_LLHatswitch[port] | JP_TYPE_ANALOGUE;
6717 break;
6719 nch = (struct NepClassHid *) nch->nch_Node.ln_Succ;
6721 Permit();
6723 if((port >= JP_ANALOGUE_PORT_MAGIC) && (port < (JP_ANALOGUE_PORT_MAGIC|4)))
6725 port &= 3;
6726 Forbid();
6727 nch = (struct NepClassHid *) nh->nh_Interfaces.lh_Head;
6728 while(nch->nch_Node.ln_Succ)
6730 if(nch->nch_LLAnalogue[port])
6732 result = (nch->nch_LLPortState[port] & ~JP_DIRECTION_MASK) | (nch->nch_LLAnalogue[port] & JP_XYAXIS_MASK) | nch->nch_LLHatswitch[port] | JP_TYPE_ANALOGUE;
6734 nch = (struct NepClassHid *) nch->nch_Node.ln_Succ;
6736 Permit();
6738 KPRINTF(40, ("And after %08lx\n", result));
6740 return(result);
6741 AROS_LIBFUNC_EXIT
6743 /* \\\ */
6745 /* /// "nSetJoyPortAttrsA()" */
6746 AROS_LH2(ULONG, nSetJoyPortAttrsA,
6747 AROS_LHA(ULONG, port, D0),
6748 AROS_LHA(struct TagItem *, tags, A1),
6749 struct Library *, LowLevelBase, 22, hid)
6751 AROS_LIBFUNC_INIT
6753 struct NepHidBase *nh;
6754 struct TagItem *typetag;
6755 struct TagItem *motortags[2];
6756 struct TagItem *motorofftag;
6757 ULONG result = FALSE;
6759 if(!(nh = (struct NepHidBase *) FindName(&SysBase->LibList, GM_UNIQUENAME(libname))))
6761 return(result);
6764 result = AROS_CALL2(ULONG, nh->nh_LLOldSetJoyPortAttrsA,
6765 AROS_LCA(ULONG, port, D0),
6766 AROS_LCA(struct TagItem *, tags, A1),
6767 struct Library *, nh->nh_LowLevelBase);
6769 KPRINTF(40, ("Before %08lx\n", result));
6770 if(port < 4)
6772 typetag = FindTagItem(SJA_Type, tags);
6773 if(typetag)
6775 if(typetag->ti_Data == SJA_TYPE_ANALOGUE)
6777 nh->nh_LLAnalogueOverride[port] = TRUE;
6778 } else {
6779 nh->nh_LLAnalogueOverride[port] = FALSE;
6781 result = TRUE;
6783 typetag = FindTagItem(SJA_Reinitialize, tags);
6784 if(typetag)
6786 if(typetag->ti_Data)
6788 nh->nh_LLAnalogueOverride[port] = FALSE;
6791 motortags[0] = FindTagItem(SJA_RumbleSetSlowMotor, tags);
6792 motortags[1] = FindTagItem(SJA_RumbleSetFastMotor, tags);
6793 motorofftag = FindTagItem(SJA_RumbleOff, tags);
6794 if(motortags[0] || motortags[1] || motorofftag)
6796 struct NepHidItem *nhi;
6797 struct NepClassHid *nch;
6798 struct TagItem nulltag = { 0, 0 };
6799 ULONG cnt;
6800 BOOL sigit = FALSE;
6801 if(motorofftag)
6803 if(motorofftag->ti_Data)
6805 motortags[0] = &nulltag;
6806 motortags[1] = &nulltag;
6809 Forbid();
6810 nch = (struct NepClassHid *) nh->nh_Interfaces.lh_Head;
6811 while(nch->nch_Node.ln_Succ)
6813 if(nch->nch_CDC->cdc_LLRumblePort == port+1)
6815 for(cnt = 0; cnt < 2; cnt++)
6817 if(motortags[cnt] && ((nhi = nch->nch_RumbleMotors[cnt])))
6819 if(nhi->nhi_OldValue != motortags[cnt]->ti_Data)
6821 nhi->nhi_OldValue = motortags[cnt]->ti_Data;
6822 nhi->nhi_Collection->nhc_Report->nhr_OutTouched = TRUE;
6823 nch->nch_OutFeatTouched = TRUE;
6824 sigit = TRUE;
6828 if(sigit)
6830 Signal(nch->nch_Task, (1L<<nch->nch_TaskMsgPort->mp_SigBit));
6834 nch = (struct NepClassHid *) nch->nch_Node.ln_Succ;
6836 Permit();
6837 result = TRUE;
6840 KPRINTF(40, ("And after %08lx\n", result));
6842 return(result);
6844 AROS_LIBFUNC_EXIT
6846 /* \\\ */
6848 /* /// "nInstallLastActionHero()" */
6849 void nInstallLastActionHero(struct NepClassHid *nch)
6851 struct NepHidBase *nh = nch->nch_ClsBase;
6853 if(!nh->nh_DispatcherTask)
6855 nh->nh_ReadySignal = SIGB_SINGLE;
6856 nh->nh_ReadySigTask = FindTask(NULL);
6857 SetSignal(0, SIGF_SINGLE);
6858 if(psdSpawnSubTask("Last Action Hero", GM_UNIQUENAME(nDispatcherTask), nh))
6860 Wait(1L<<nh->nh_ReadySignal);
6861 if(!nh->nh_DispatcherTask)
6863 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
6864 "It's your fault! I'm sure! Couldn't create subtask for launching!");
6865 } else {
6866 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
6867 "Last Action Hero successfully launched!");
6869 } else {
6870 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
6871 "It's your fault! I'm sure! Couldn't create subtask for launching!");
6873 nh->nh_ReadySigTask = NULL;
6874 //FreeSignal(nh->nh_ReadySignal);
6877 /* \\\ */
6879 /************************************************************************/
6881 #undef ps
6883 /* /// "nDispatcherTask()" */
6884 AROS_UFH0(void, GM_UNIQUENAME(nDispatcherTask))
6886 AROS_USERFUNC_INIT
6888 struct NepHidBase *nh;
6889 struct Task *thistask;
6890 struct ActionMsg *am;
6891 struct NepHidSound *nhs;
6893 thistask = FindTask(NULL);
6895 #undef CxBase
6896 #undef IntuitionBase
6897 #undef DOSBase
6898 #undef DataTypesBase
6899 nh = thistask->tc_UserData;
6900 NewList(&nh->nh_Sounds);
6901 if((nh->nh_InpMsgPort = CreateMsgPort()))
6903 if((nh->nh_InpIOReq = (struct IOStdReq *) CreateIORequest(nh->nh_InpMsgPort, sizeof(struct IOStdReq))))
6905 if(!OpenDevice("input.device", 0, (struct IORequest *) nh->nh_InpIOReq, 0))
6907 if((nh->nh_DOSBase = OpenLibrary("dos.library", 39)))
6909 if((nh->nh_IntBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 39)))
6911 #define IntuitionBase nh->nh_IntBase
6912 if((nh->nh_DTBase = OpenLibrary("datatypes.library", 39)))
6914 if((nh->nh_CxBase = OpenLibrary("commodities.library", 39)))
6916 if((nh->nh_LayersBase = OpenLibrary("layers.library", 39)))
6918 #define CxBase nh->nh_CxBase
6919 #define DOSBase nh->nh_DOSBase
6920 #define DataTypesBase nh->nh_DTBase
6921 #define LayersBase nh->nh_LayersBase
6922 if((nh->nh_DTaskMsgPort = CreateMsgPort()))
6924 nh->nh_DispatcherTask = thistask;
6925 Forbid();
6926 if(nh->nh_ReadySigTask)
6928 Signal(nh->nh_ReadySigTask, 1L<<nh->nh_ReadySignal);
6930 Permit();
6932 nLastActionHero(nh);
6934 Forbid();
6935 while((am = (struct ActionMsg *) GetMsg(nh->nh_DTaskMsgPort)))
6937 FreeVec(am);
6939 nhs = (struct NepHidSound *) nh->nh_Sounds.lh_Head;
6940 while(nhs->nhs_Node.ln_Succ)
6942 nFreeSound(nh, nhs);
6943 nhs = (struct NepHidSound *) nh->nh_Sounds.lh_Head;
6945 DeleteMsgPort(nh->nh_DTaskMsgPort);
6946 nh->nh_DTaskMsgPort = NULL;
6947 Permit();
6949 CloseLibrary(nh->nh_LayersBase);
6950 nh->nh_LayersBase = NULL;
6952 CloseLibrary(nh->nh_CxBase);
6953 nh->nh_CxBase = NULL;
6955 CloseLibrary(nh->nh_DTBase);
6956 nh->nh_DTBase = NULL;
6958 CloseLibrary((struct Library *) nh->nh_IntBase);
6959 nh->nh_IntBase = NULL;
6961 CloseLibrary((struct Library *) nh->nh_DOSBase);
6962 nh->nh_DOSBase = NULL;
6964 CloseDevice((struct IORequest *) nh->nh_InpIOReq);
6966 DeleteIORequest((struct IORequest *) nh->nh_InpIOReq);
6967 nh->nh_InpIOReq = NULL;
6969 DeleteMsgPort(nh->nh_InpMsgPort);
6970 nh->nh_InpMsgPort = NULL;
6972 Forbid();
6973 if(nh->nh_ReadySigTask)
6975 Signal(nh->nh_ReadySigTask, 1L<<nh->nh_ReadySignal);
6977 nh->nh_DispatcherTask = NULL;
6979 AROS_USERFUNC_EXIT
6981 /* \\\ */
6983 /* /// "nLastActionHero()" */
6984 void nLastActionHero(struct NepHidBase *nh)
6986 ULONG sigmask;
6987 ULONG sigs;
6988 struct ActionMsg *am;
6989 struct NepHidAction *nha;
6990 struct NepClassHid *nch;
6991 struct Window *actwindow;
6992 struct Screen *actscreen;
6993 char buf[128];
6994 ULONG intlock;
6995 sigmask = (1L<<nh->nh_DTaskMsgPort->mp_SigBit)|SIGBREAKF_CTRL_C;
6998 while((am = (struct ActionMsg *) GetMsg(nh->nh_DTaskMsgPort)))
7000 nch = am->am_NCH;
7001 nha = am->am_Action;
7002 switch(nha->nha_Type & HUA_ATYPEMASK)
7004 case HUA_VANILLA:
7005 buf[0] = '<';
7006 strcpy(&buf[1], nha->nha_VanillaString);
7007 strcat(buf, ">");
7008 if(!nSendKeyString(nh, buf))
7010 nEasyRequest(nh, "'%s' is no good. Really.", "Argl!", nha->nha_VanillaString);
7012 break;
7014 case HUA_KEYSTRING:
7015 if(!nSendKeyString(nh, nha->nha_KeyString))
7017 nEasyRequest(nh, "Don't you ever say\n'%s'\nto me again!", "Terribly sorry!", nha->nha_KeyString);
7019 break;
7021 case HUA_SOUND:
7022 nPlaySound(nh, nha);
7023 break;
7025 case HUA_SHELL:
7027 BPTR fhandle;
7028 LONG ioerr;
7029 if((fhandle = Open(nch->nch_CDC->cdc_ShellCon, MODE_READWRITE)))
7031 ioerr = SystemTags(nha->nha_ExeString,
7032 SYS_Input, fhandle,
7033 SYS_Output, NULL,
7034 SYS_Asynch, nha->nha_ShellAsync,
7035 NP_StackSize, nch->nch_CDC->cdc_ShellStack,
7036 TAG_END);
7037 if(ioerr)
7039 nEasyRequest(nh, "Offender survived execution of\n'%s'\nwith error code %ld.", "Get me a shotgun then!", nha->nha_ExeString, ioerr);
7041 if((!nha->nha_ShellAsync) || ioerr)
7043 Close(fhandle);
7045 } else {
7046 nEasyRequest(nh, "Do you really think\n'%s'\nis a nice and witty\nconsole window? Well, it's not!", "I'll use that string to hang myself!", nch->nch_CDC->cdc_ShellCon);
7048 break;
7051 case HUA_MISC:
7052 switch(nha->nha_MiscMode)
7054 case HUAT_ACTWINDOW:
7056 struct Layer *toplayer;
7057 intlock = LockIBase(0);
7058 actscreen = nh->nh_IntBase->ActiveScreen;
7059 actwindow = nh->nh_IntBase->ActiveWindow;
7060 UnlockIBase(intlock);
7061 if(actscreen)
7063 LockLayerInfo(&actscreen->LayerInfo);
7064 toplayer = WhichLayer(&actscreen->LayerInfo, (LONG) actscreen->MouseX, (LONG) actscreen->MouseY);
7065 UnlockLayerInfo(&actscreen->LayerInfo);
7067 if(toplayer)
7069 if(toplayer->Window && (actwindow != toplayer->Window))
7071 ActivateWindow(toplayer->Window);
7075 break;
7078 case HUAT_DISPLAYBEEP:
7079 DisplayBeep(NULL);
7080 break;
7082 case HUAT_WB2FRONT:
7083 WBenchToFront();
7084 break;
7086 case HUAT_SCREENCYCLE:
7087 intlock = LockIBase(0);
7088 actscreen = nh->nh_IntBase->FirstScreen;
7089 UnlockIBase(intlock);
7090 if(actscreen)
7092 ScreenToBack(actscreen);
7094 break;
7096 case HUAT_WIN2FRONT:
7097 intlock = LockIBase(0);
7098 actwindow = nh->nh_IntBase->ActiveWindow;
7099 UnlockIBase(intlock);
7100 if(actwindow)
7102 WindowToFront(actwindow);
7104 break;
7106 case HUAT_WIN2BACK:
7107 intlock = LockIBase(0);
7108 actwindow = nh->nh_IntBase->ActiveWindow;
7109 UnlockIBase(intlock);
7110 if(actwindow)
7112 WindowToBack(actwindow);
7114 break;
7116 case HUAT_ZIPWINDOW:
7117 intlock = LockIBase(0);
7118 actwindow = nh->nh_IntBase->ActiveWindow;
7119 UnlockIBase(intlock);
7120 if(actwindow)
7122 ZipWindow(actwindow);
7124 break;
7127 break;
7130 FreeVec(am);
7132 sigs = Wait(sigmask);
7133 } while(!(sigs & SIGBREAKF_CTRL_C));
7135 /* \\\ */
7137 /* /// "nLoadSound()" */
7138 struct NepHidSound * nLoadSound(struct NepHidBase *nh, STRPTR name)
7140 struct NepHidSound *nhs;
7141 if((nhs = AllocVec(sizeof(struct NepHidSound), MEMF_PUBLIC|MEMF_CLEAR)))
7143 if((nhs->nhs_Node.ln_Name = AllocVec((ULONG) strlen(name)+1, MEMF_PUBLIC)))
7145 strcpy(nhs->nhs_Node.ln_Name, name);
7146 AddTail(&nh->nh_Sounds, &nhs->nhs_Node);
7147 nhs->nhs_DTHandle = NewDTObject(name,
7148 DTA_SourceType, DTST_FILE,
7149 DTA_GroupID, GID_SOUND,
7150 SDTA_Cycles, 1L,
7151 TAG_END);
7152 if(!nhs->nhs_DTHandle)
7154 nEasyRequest(nh, "Does '%s' make a sound\nin the woods, when it was chopped\nbut nobody was looking at it?", "No! Couldn't load it!", name);
7156 return(nhs);
7158 FreeVec(nhs);
7160 return(NULL);
7162 /* \\\ */
7164 /* /// "nPlaySound()" */
7165 BOOL nPlaySound(struct NepHidBase *nh, struct NepHidAction *nha)
7167 struct NepHidSound *nhs;
7168 struct dtTrigger playmsg;
7169 nhs = (struct NepHidSound *) FindName(&nh->nh_Sounds, nha->nha_SoundFile);
7170 if(!nhs)
7172 nhs = nLoadSound(nh, nha->nha_SoundFile);
7174 if(!nhs)
7176 return(FALSE);
7178 if(!nhs->nhs_DTHandle)
7180 return(FALSE);
7183 SetAttrs(nhs->nhs_DTHandle,
7184 SDTA_Volume, nha->nha_SoundVolume,
7185 TAG_END);
7186 playmsg.MethodID = DTM_TRIGGER;
7187 playmsg.dtt_GInfo = NULL;
7188 playmsg.dtt_Function = STM_PLAY;
7189 playmsg.dtt_Data = NULL;
7190 DoMethodA(nhs->nhs_DTHandle, (Msg) &playmsg);
7191 return(TRUE);
7193 /* \\\ */
7195 /* /// "nFreeSound()" */
7196 void nFreeSound(struct NepHidBase *nh, struct NepHidSound *nhs)
7198 Remove(&nhs->nhs_Node);
7199 if(nhs->nhs_DTHandle)
7201 DisposeDTObject(nhs->nhs_DTHandle);
7203 FreeVec(nhs->nhs_Node.ln_Name);
7204 FreeVec(nhs);
7206 /* \\\ */
7208 /* /// "nInvertString()" */
7209 struct InputEvent *nInvertString(struct NepHidBase *nh, STRPTR str, struct KeyMap *km)
7211 struct InputEvent *prior = NULL;
7212 struct InputEvent *ne;
7213 struct InputXpression tmpIX;
7215 BOOL freeevents = FALSE;
7216 char cc;
7217 char *oldsptr;
7219 if(!str) return(NULL);
7220 if(!(*str)) return(NULL);
7223 if((ne = AllocMem(sizeof(struct InputEvent), MEMF_CLEAR)))
7225 ne->ie_NextEvent = prior;
7226 prior = ne;
7227 cc = *str++;
7228 switch(cc)
7230 case '<': /* do angles */
7231 oldsptr = str;
7232 freeevents = TRUE;
7233 while((cc = *str))
7235 if(cc == '>')
7237 *str = '\0';
7238 if(!ParseIX(oldsptr, &tmpIX))
7240 freeevents = FALSE;
7241 prior->ie_Class = tmpIX.ix_Class;
7242 prior->ie_Code = tmpIX.ix_Code;
7243 prior->ie_Qualifier = tmpIX.ix_Qualifier;
7245 *str++ = cc;
7246 break;
7248 str++;
7250 break;
7252 case '\\': /* do escape sequences */
7253 cc = *str++;
7254 switch(cc)
7256 case '"':
7257 case '\'':
7258 case '<':
7259 case '\\':
7260 break;
7261 case 'n':
7262 case 'r':
7263 cc = '\r';
7264 break;
7265 case 't':
7266 cc = '\t';
7267 break;
7268 case '0':
7269 cc = '\0';
7270 break;
7271 default:
7272 freeevents = TRUE;
7273 break;
7275 if(freeevents) break;
7276 /* note that this break is missing on purpose */
7277 default: /* normal key translation */
7278 InvertKeyMap((ULONG) cc, prior, km);
7279 break;
7281 } else {
7282 freeevents = TRUE;
7284 } while(*str && (!freeevents));
7285 if(freeevents)
7287 nFreeIEvents(nh, prior);
7288 return(NULL);
7290 return(prior);
7292 /* \\\ */
7294 /* /// "nFreeIEvents()" */
7295 void nFreeIEvents(struct NepHidBase *nh, struct InputEvent *event)
7297 struct InputEvent *next;
7298 while(event)
7300 next = event->ie_NextEvent;
7301 FreeMem(event, sizeof(struct InputEvent));
7302 event = next;
7305 /* \\\ */
7307 /* /// "nSendKeyString()" */
7308 BOOL nSendKeyString(struct NepHidBase *nh, STRPTR str)
7310 struct InputEvent *events = nInvertString(nh, str, NULL);
7311 struct InputEvent *eptr = events;
7312 struct InputEvent lastevent;
7313 int count = 0;
7314 int lstpos;
7315 if(!events)
7317 return(FALSE);
7319 while(eptr)
7321 count++;
7322 eptr = eptr->ie_NextEvent;
7324 while(count)
7326 eptr = events;
7327 for(lstpos = --count; lstpos; lstpos--)
7328 eptr = eptr->ie_NextEvent;
7330 nh->nh_FakeEvent = *eptr;
7331 nh->nh_FakeEvent.ie_NextEvent = NULL;
7332 nh->nh_InpIOReq->io_Data = &nh->nh_FakeEvent;
7333 nh->nh_InpIOReq->io_Length = sizeof(struct InputEvent);
7334 nh->nh_InpIOReq->io_Command = nh->nh_OS4Hack ? IND_ADDEVENT : IND_WRITEEVENT;
7335 DoIO((struct IORequest *) nh->nh_InpIOReq);
7337 nh->nh_FakeEvent.ie_Code |= IECODE_UP_PREFIX;
7338 nh->nh_InpIOReq->io_Data = &nh->nh_FakeEvent;
7339 nh->nh_InpIOReq->io_Length = sizeof(struct InputEvent);
7340 nh->nh_InpIOReq->io_Command = nh->nh_OS4Hack ? IND_ADDEVENT : IND_WRITEEVENT;
7341 DoIO((struct IORequest *) nh->nh_InpIOReq);
7343 lastevent.ie_Class = IECLASS_RAWKEY;
7344 lastevent.ie_SubClass = 0;
7345 lastevent.ie_Code = 0xFF;
7346 lastevent.ie_NextEvent = NULL;
7347 lastevent.ie_Qualifier = 0;
7348 nh->nh_InpIOReq->io_Data = &lastevent;
7349 nh->nh_InpIOReq->io_Length = sizeof(struct InputEvent);
7350 nh->nh_InpIOReq->io_Command = nh->nh_OS4Hack ? IND_ADDEVENT : IND_WRITEEVENT;
7351 DoIO((struct IORequest *) nh->nh_InpIOReq);
7352 nFreeIEvents(nh, events);
7353 return(TRUE);
7355 /* \\\ */
7357 /* /// "nEasyRequest()" */
7358 LONG nEasyRequest(struct NepHidBase *nh, STRPTR body, STRPTR gadgets, ...)
7360 LONG ret;
7362 AROS_SLOWSTACKFORMAT_PRE(gadgets);
7363 ret = nEasyRequestA(nh, body, gadgets, AROS_SLOWSTACKFORMAT_ARG(gadgets));
7364 AROS_SLOWSTACKFORMAT_POST(gadgets);
7366 return ret;
7368 /* \\\ */
7370 /* /// "nEasyRequestA()" */
7371 LONG nEasyRequestA(struct NepHidBase *nh, STRPTR body, STRPTR gadgets, RAWARG params)
7373 struct EasyStruct es;
7374 es.es_StructSize = sizeof(struct EasyStruct);
7375 es.es_Flags = 0;
7376 es.es_Title = GM_UNIQUENAME(libname);
7377 es.es_TextFormat = body;
7378 es.es_GadgetFormat = gadgets;
7379 return(EasyRequestArgs(NULL, &es, NULL, params));
7381 /* \\\ */