grub2: bring back build of aros-side grub2 tools
[AROS.git] / rom / usb / classes / hid / hid.class.c
blob5e39fd4fff6927205e01004b7fb8f8a6e107c8ef
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 = 8192;
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 count = nhi->nhi_MapSize = (nhi->nhi_LogicalMax - nhi->nhi_LogicalMin)+1;
2853 usageptr = nhi->nhi_UsageMap = psdAllocVec(sizeof(ULONG) * count);
2854 alistptr = nhi->nhi_ActionMap = psdAllocVec(sizeof(struct List) * count);
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 if(!(usageptr && alistptr && nhi->nhi_Buffer))
2864 psdFreeVec(usageptr);
2865 psdFreeVec(alistptr);
2866 psdFreeVec(nhi->nhi_Buffer);
2867 psdFreeVec(nhi);
2868 KPRINTF(10, ("Out of memory\n"));
2869 rptr = NULL;
2870 break;
2873 nhi->nhi_Usage = nhi->nhi_DesignIndex = nhi->nhi_StringIndex = HID_PARAM_UNDEF;
2874 NewList(&nhi->nhi_ActionList);
2876 KPRINTF(1, ("New Array(%ld*%ld) Item: %ld.%ld (%ld-%ld)\n",
2877 nhi->nhi_Count, nhi->nhi_MapSize,
2878 nhi->nhi_Offset>>3, nhi->nhi_Offset & 7,
2879 nhi->nhi_LogicalMin, nhi->nhi_LogicalMax));
2881 nhi->nhi_SameUsages = TRUE;
2884 nhu = (struct NepHidUsage *) nch->nch_HidDesigns.lh_Head;
2885 if(nhu->nhu_Node.ln_Succ)
2887 designid = nhu->nhu_Usage++;
2888 if(nhu->nhu_Usage > nhu->nhu_UsageMax)
2890 Remove(&nhu->nhu_Node);
2891 psdFreeVec(nhu);
2894 nhu = (struct NepHidUsage *) nch->nch_HidStrings.lh_Head;
2895 if(nhu->nhu_Node.ln_Succ)
2897 stringid = nhu->nhu_Usage++;
2898 if(nhu->nhu_Usage > nhu->nhu_UsageMax)
2900 Remove(&nhu->nhu_Node);
2901 psdFreeVec(nhu);
2904 nhu = (struct NepHidUsage *) nch->nch_HidUsages.lh_Head;
2905 if(nhu->nhu_Node.ln_Succ)
2907 usageid = nhu->nhu_Usage++;
2908 if(nhu->nhu_Usage > nhu->nhu_UsageMax)
2910 KPRINTF(1, ("Removing usage %08lx\n", nhu));
2911 Remove(&nhu->nhu_Node);
2912 psdFreeVec(nhu);
2916 // check if usages are all the same
2917 if(count < nhi->nhi_MapSize)
2919 if(usageid != usageptr[-1])
2921 nhi->nhi_SameUsages = FALSE;
2925 *usageptr++ = usageid;
2926 NewList(alistptr);
2927 alistptr++;
2928 } while(--count);
2930 if(nhi->nhi_SameUsages)
2932 // if it's all the same, we can assign a usage id to this array
2933 nhi->nhi_Usage = nhi->nhi_UsageMap[0];
2935 AddTail(&nhc->nhc_Items, &nhi->nhi_Node);
2937 } /* FIXME: Clean string/delimiter stack if no usage? */
2938 bitpos += nch->nch_HidGlobal.nhg_ReportSize * nch->nch_HidGlobal.nhg_ReportCount;
2941 if(fakelogmin)
2943 nch->nch_HidGlobal.nhg_LogicalMin = HID_PARAM_UNDEF;
2945 if(fakelogmax)
2947 nch->nch_HidGlobal.nhg_LogicalMax = HID_PARAM_UNDEF;
2949 break;
2952 case REPORT_MAIN_COLLECT:
2954 struct NepHidUsage *nhu;
2955 struct NepHidCollection *oldnhc = nhc;
2956 KPRINTF(1, ("Collection(%lx)\n", udata));
2957 if((nhc = psdAllocVec(sizeof(struct NepHidCollection))))
2959 NewList(&nhc->nhc_Items);
2960 nhc->nhc_Parent = oldnhc;
2961 nhu = (struct NepHidUsage *) nch->nch_HidUsages.lh_Head;
2962 if(nhu->nhu_Node.ln_Succ)
2964 nhc->nhc_Usage = nhu->nhu_Usage;
2965 nhc->nhc_Name = nGetUsageName(nch, nhu->nhu_Usage);
2966 } else {
2967 if(nhc->nhc_Parent)
2969 nhc->nhc_Usage = nhc->nhc_Parent->nhc_Usage;
2970 nhc->nhc_Name = psdCopyStr(nhc->nhc_Parent->nhc_Name);
2971 } else {
2972 nhc->nhc_Name = psdCopyStr("Argl!");
2976 node = nch->nch_HidUsages.lh_Head;
2977 while(node->ln_Succ)
2979 KPRINTF(1, ("Removing usage %08lx\n", node));
2980 Remove(node);
2981 psdFreeVec(node);
2982 node = nch->nch_HidUsages.lh_Head;
2985 break;
2988 case REPORT_MAIN_ENDCOLL:
2989 KPRINTF(1, ("EndCollection(%lx)\n", udata));
2990 if(nhc)
2992 /* Get rid of empty collection */
2993 //if(!nhc->nhc_Items.lh_Head->ln_Succ)
2994 if(0) /* don't do this, we might need the parent collection! */
2996 struct NepHidCollection *oldnhc = nhc;
2997 KPRINTF(1, ("Deleting empty collection %lx (%s)\n", nhc, nhc->nhc_Name));
2998 nhc = nhc->nhc_Parent;
2999 psdFreeVec(oldnhc->nhc_Name);
3000 psdFreeVec(oldnhc);
3001 } else {
3002 AddTail(&nhr->nhr_Collections, &nhc->nhc_Node);
3003 nhc->nhc_Report = nhr;
3004 nhc = nhc->nhc_Parent;
3007 break;
3009 default:
3010 KPRINTF(1, ("Reserved_%02lx(%lx)\n", itag, data));
3011 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
3012 "HID Error at %04lx: Reserved_MAIN_%02lx(%lx)", reportpos, itag, data);
3013 nDebugReport(nch, nhr);
3014 rptr = NULL;
3015 break;
3017 /* Remove remaining usages */
3018 node = nch->nch_HidUsages.lh_Head;
3019 while(node->ln_Succ)
3021 KPRINTF(1, ("MainEnd: Removing usage %08lx\n", node));
3022 Remove(node);
3023 psdFreeVec(node);
3024 node = nch->nch_HidUsages.lh_Head;
3026 /* Remove remaining designators */
3027 node = nch->nch_HidDesigns.lh_Head;
3028 while(node->ln_Succ)
3030 KPRINTF(1, ("MainEnd: Removing designator %08lx\n", node));
3031 Remove(node);
3032 psdFreeVec(node);
3033 node = nch->nch_HidDesigns.lh_Head;
3035 /* Remove remaining strings */
3036 node = nch->nch_HidStrings.lh_Head;
3037 while(node->ln_Succ)
3039 KPRINTF(1, ("MainEnd: Removing strings %08lx\n", node));
3040 Remove(node);
3041 psdFreeVec(node);
3042 node = nch->nch_HidStrings.lh_Head;
3045 switch(itag)
3047 case REPORT_MAIN_INPUT:
3048 nhr->nhr_ReportInSize = bitpos;
3049 break;
3050 case REPORT_MAIN_OUTPUT:
3051 nhr->nhr_ReportOutSize = bitpos;
3052 break;
3053 case REPORT_MAIN_FEATURE:
3054 nhr->nhr_ReportFeatSize = bitpos;
3055 break;
3058 break;
3060 case REPORT_ITYPE_GLOBAL:
3061 //KPRINTF(1, ("Global "));
3062 switch(itag)
3064 case REPORT_GLOB_USAGE:
3065 KPRINTF(1, ("Usage Page(%ld) %s\n", udata, nNumToStr(nch, NTS_USAGEPAGE, udata, "unknown")));
3066 nch->nch_HidGlobal.nhg_UsagePage = udata;
3067 break;
3069 case REPORT_GLOB_LOGMIN:
3070 KPRINTF(1, ("LogMin(%ld)\n", data));
3071 nch->nch_HidGlobal.nhg_LogicalMin = data;
3072 break;
3074 case REPORT_GLOB_LOGMAX:
3075 KPRINTF(1, ("LogMax(%ld)\n", data));
3076 nch->nch_HidGlobal.nhg_LogicalMax = data;
3077 break;
3079 case REPORT_GLOB_PHYMIN:
3080 KPRINTF(1, ("PhyMin(%ld)\n", data));
3081 nch->nch_HidGlobal.nhg_PhysicalMin = data;
3082 break;
3084 case REPORT_GLOB_PHYMAX:
3085 KPRINTF(1, ("PhyMax(%ld)\n", data));
3086 nch->nch_HidGlobal.nhg_PhysicalMax = data;
3087 break;
3089 case REPORT_GLOB_UNITEXP:
3090 KPRINTF(1, ("UnitExp(%ld)\n", data));
3091 nch->nch_HidGlobal.nhg_UnitExp = data;
3092 break;
3094 case REPORT_GLOB_UNIT:
3095 KPRINTF(1, ("Unit(%ld)\n", data));
3096 nch->nch_HidGlobal.nhg_Unit = data;
3097 break;
3099 case REPORT_GLOB_RPSIZE:
3100 KPRINTF(1, ("ReportSize(%ld)\n", udata));
3101 nch->nch_HidGlobal.nhg_ReportSize = udata;
3102 break;
3104 case REPORT_GLOB_RPID:
3105 KPRINTF(1, ("ReportID(%ld)\n", udata));
3106 nch->nch_HidGlobal.nhg_ReportID = udata;
3107 break;
3109 case REPORT_GLOB_RPCOUNT:
3110 KPRINTF(1, ("ReportCount(%ld)\n", udata));
3111 nch->nch_HidGlobal.nhg_ReportCount = udata;
3112 break;
3114 case REPORT_GLOB_PUSH:
3116 struct NepHidGlobal *nhg = psdAllocVec(sizeof(struct NepHidGlobal));
3117 KPRINTF(1, ("Push(%ld)\n", data));
3118 if(nhg)
3120 *nhg = nch->nch_HidGlobal;
3121 AddTail(&nch->nch_HidStack, &nhg->nhg_Node);
3122 } else {
3123 KPRINTF(10, ("Out of HID stack memory!\n"));
3124 rptr = NULL;
3126 break;
3129 case REPORT_GLOB_POP:
3131 struct NepHidGlobal *nhg = (struct NepHidGlobal *) nch->nch_HidStack.lh_Tail;
3132 KPRINTF(1, ("Pop(%ld)\n", data));
3133 if(nhg->nhg_Node.ln_Pred)
3135 nch->nch_HidGlobal = *nhg;
3136 Remove(&nhg->nhg_Node);
3137 psdFreeVec(nhg);
3138 } else {
3139 KPRINTF(10, ("Pop from HID stack without push!\n"));
3140 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
3141 "HID Error at %04lx: Pop from HID stack without push!", reportpos);
3142 nDebugReport(nch, nhr);
3143 rptr = NULL;
3145 break;
3148 default:
3149 KPRINTF(1, ("Reserved_%02lx(%lx)\n", itag, data));
3150 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
3151 "HID Error at %04lx: Reserved_GLOBAL_%02lx(%lx)", reportpos, itag, data);
3152 nDebugReport(nch, nhr);
3153 rptr = NULL;
3154 break;
3156 break;
3158 case REPORT_ITYPE_LOCAL:
3159 //KPRINTF(1, ("Local "));
3160 switch(itag)
3162 case REPORT_LOCL_USAGE:
3163 if(len <= 2)
3165 udata |= nch->nch_HidGlobal.nhg_UsagePage<<16;
3167 KPRINTF(1, ("Usage (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3168 if(!nAddUsage(nch, &nch->nch_HidUsages, udata, udata))
3170 rptr = NULL;
3172 break;
3174 case REPORT_LOCL_USEMIN:
3175 if(len <= 2)
3177 udata |= nch->nch_HidGlobal.nhg_UsagePage<<16;
3179 KPRINTF(1, ("UsageMin (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3180 usagemin = udata;
3181 if(usagemax != HID_PARAM_UNDEF)
3183 if(!nAddUsage(nch, &nch->nch_HidUsages, usagemin, usagemax))
3185 rptr = NULL;
3187 usagemin = usagemax = HID_PARAM_UNDEF;
3189 break;
3191 case REPORT_LOCL_USEMAX:
3192 if(len <= 2)
3194 udata |= nch->nch_HidGlobal.nhg_UsagePage<<16;
3196 KPRINTF(1, ("UsageMax (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3197 usagemax = udata;
3198 if(usagemin != HID_PARAM_UNDEF)
3200 if(!nAddUsage(nch, &nch->nch_HidUsages, usagemin, usagemax))
3202 rptr = NULL;
3204 usagemin = usagemax = HID_PARAM_UNDEF;
3206 break;
3208 case REPORT_LOCL_DESIDX:
3209 KPRINTF(1, ("Designator index (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3210 if(!nAddUsage(nch, &nch->nch_HidDesigns, udata, udata))
3212 rptr = NULL;
3214 break;
3216 case REPORT_LOCL_DESMIN:
3217 KPRINTF(1, ("DesignMin (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3218 designmin = udata;
3219 if(designmax != HID_PARAM_UNDEF)
3221 if(!nAddUsage(nch, &nch->nch_HidDesigns, designmin, designmax))
3223 rptr = NULL;
3225 designmin = designmax = HID_PARAM_UNDEF;
3227 break;
3229 case REPORT_LOCL_DESMAX:
3230 KPRINTF(1, ("DesignMax (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3231 designmin = udata;
3232 if(designmax != HID_PARAM_UNDEF)
3234 if(!nAddUsage(nch, &nch->nch_HidDesigns, designmin, designmax))
3236 rptr = NULL;
3238 designmin = designmax = HID_PARAM_UNDEF;
3240 break;
3242 case REPORT_LOCL_STRIDX:
3243 KPRINTF(1, ("String index (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3244 if(!nAddUsage(nch, &nch->nch_HidStrings, udata, udata))
3246 rptr = NULL;
3248 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3249 "HID String Index %ld", udata);
3250 break;
3252 case REPORT_LOCL_STRMIN:
3253 KPRINTF(1, ("StringMin (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3254 stringmin = udata;
3255 if(stringmax != HID_PARAM_UNDEF)
3257 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3258 "HID String Index Range %ld - %ld", stringmin, stringmax);
3259 if(!nAddUsage(nch, &nch->nch_HidStrings, stringmin, stringmax))
3261 rptr = NULL;
3263 stringmin = stringmax = HID_PARAM_UNDEF;
3265 break;
3267 case REPORT_LOCL_STRMAX:
3268 KPRINTF(1, ("StringMax (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3269 stringmax = udata;
3270 if(stringmin != HID_PARAM_UNDEF)
3272 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3273 "HID String Index Range %ld - %ld", stringmin, stringmax);
3274 if(!nAddUsage(nch, &nch->nch_HidStrings, stringmin, stringmax))
3276 rptr = NULL;
3278 stringmin = stringmax = HID_PARAM_UNDEF;
3280 break;
3282 case REPORT_LOCL_DELIM:
3283 KPRINTF(1, ("Delimiter (%ld)\n", udata));
3284 if(udata)
3286 delim++;
3287 } else {
3288 delim--;
3290 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "HID Report Delimiters not really supported!");
3291 break;
3293 default:
3294 KPRINTF(1, ("Reserved_%02lx(%lx)\n", itag, udata));
3295 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
3296 "HID Error at %04lx: Reserved_LOCAL_%02lx(%lx)", reportpos, itag, udata);
3297 nDebugReport(nch, nhr);
3298 rptr = NULL;
3299 break;
3301 break;
3303 default:
3304 KPRINTF(1, ("Reserved!\n"));
3305 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
3306 "HID Error at %04lx: Reserved_%02lx", reportpos, itag);
3307 nDebugReport(nch, nhr);
3308 rptr = NULL;
3309 break;
3312 KPRINTF(1, ("Parsing done, status %lx.\n", rptr));
3314 /* Remove remaining stack frame */
3315 node = nch->nch_HidStack.lh_Head;
3316 while(node->ln_Succ)
3318 KPRINTF(1, ("Removing stack frame %08lx\n", node));
3319 Remove(node);
3320 psdFreeVec(node);
3321 node = nch->nch_HidStack.lh_Head;
3323 /* Remove remaining usages */
3324 node = nch->nch_HidUsages.lh_Head;
3325 while(node->ln_Succ)
3327 KPRINTF(1, ("Removing usage %08lx\n", node));
3328 Remove(node);
3329 psdFreeVec(node);
3330 node = nch->nch_HidUsages.lh_Head;
3332 /* Remove remaining designators */
3333 node = nch->nch_HidDesigns.lh_Head;
3334 while(node->ln_Succ)
3336 KPRINTF(1, ("Removing designator %08lx\n", node));
3337 Remove(node);
3338 psdFreeVec(node);
3339 node = nch->nch_HidDesigns.lh_Head;
3341 /* Remove remaining strings */
3342 node = nch->nch_HidStrings.lh_Head;
3343 while(node->ln_Succ)
3345 KPRINTF(1, ("Removing strings %08lx\n", node));
3346 Remove(node);
3347 psdFreeVec(node);
3348 node = nch->nch_HidStrings.lh_Head;
3350 //nDebugReport(nch, nhr);
3351 return((BOOL) (rptr ? TRUE : FALSE));
3353 /* \\\ */
3355 /* /// "nFindCollID()" */
3356 BOOL nFindCollID(struct NepClassHid *nch, struct NepHidCollection *nhc, ULONG collidmin, ULONG collidmax)
3360 if((nhc->nhc_Usage >= collidmin) && (nhc->nhc_Usage <= collidmax))
3362 return(TRUE);
3364 } while((nhc = nhc->nhc_Parent));
3365 return(FALSE);
3367 /* \\\ */
3369 /* /// "nFindItemID()" */
3370 struct NepHidItem * nFindItemID(struct NepClassHid *nch, UWORD id, UWORD itype, ULONG *pos)
3372 struct NepHidReport *nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
3373 struct NepHidItem *nhi;
3374 struct NepHidItem **nhiptr;
3375 struct List *alistptr;
3376 ULONG count;
3377 ULONG icount;
3378 BOOL featmode;
3380 if(itype == REPORT_MAIN_OUTPUT)
3382 featmode = FALSE;
3384 else if(itype == REPORT_MAIN_FEATURE)
3386 featmode = TRUE;
3387 } else {
3388 return(NULL);
3390 while(nhr->nhr_Node.ln_Succ)
3392 nhiptr = NULL;
3393 if(featmode)
3395 if((icount = nhr->nhr_FeatItemCount))
3397 nhiptr = nhr->nhr_FeatItemMap;
3399 } else {
3400 if((icount = nhr->nhr_OutItemCount))
3402 nhiptr = nhr->nhr_OutItemMap;
3405 if(nhiptr)
3409 nhi = *nhiptr++;
3410 if(GET_WTYPE(&nhi->nhi_ActionList) == id)
3412 *pos = 0xffffffff;
3413 return(nhi);
3415 if(!(nhi->nhi_Flags & RPF_MAIN_VARIABLE))
3417 alistptr = nhi->nhi_ActionMap;
3418 count = nhi->nhi_MapSize;
3421 if(GET_WTYPE(alistptr) == id)
3423 *pos = nhi->nhi_MapSize - count;
3424 return(nhi);
3426 alistptr++;
3427 } while(--count);
3430 while(--icount);
3432 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
3434 return(NULL);
3436 /* \\\ */
3438 /* /// "nFindItemUsage()" */
3439 UWORD nFindItemUsage(struct NepClassHid *nch, ULONG usage, UWORD itype)
3441 struct NepHidReport *nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
3442 struct NepHidItem *nhi;
3443 struct NepHidItem **nhiptr;
3444 ULONG *usageptr;
3445 struct List *alistptr;
3446 ULONG count;
3447 ULONG icount;
3448 BOOL featmode;
3450 if(itype == REPORT_MAIN_OUTPUT)
3452 featmode = FALSE;
3454 else if(itype == REPORT_MAIN_FEATURE)
3456 featmode = TRUE;
3457 } else {
3458 return(0);
3461 while(nhr->nhr_Node.ln_Succ)
3463 nhiptr = NULL;
3464 if(featmode)
3466 if((icount = nhr->nhr_FeatItemCount))
3468 nhiptr = nhr->nhr_FeatItemMap;
3470 } else {
3471 if((icount = nhr->nhr_OutItemCount))
3473 nhiptr = nhr->nhr_OutItemMap;
3476 if(nhiptr)
3480 nhi = *nhiptr++;
3481 if(nhi->nhi_Usage == usage)
3483 return(GET_WTYPE(&nhi->nhi_ActionList));
3485 if(!(nhi->nhi_Flags & RPF_MAIN_VARIABLE))
3487 usageptr = nhi->nhi_UsageMap;
3488 alistptr = nhi->nhi_ActionMap;
3489 count = nhi->nhi_MapSize;
3492 if(*usageptr == usage)
3494 return GET_WTYPE(alistptr);
3496 usageptr++;
3497 alistptr++;
3498 } while(--count);
3501 while(--icount);
3503 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
3505 return(0);
3507 /* \\\ */
3509 /* /// "UsbToPs2 Mapping" */
3510 const struct UsbToPs2Map usbtops2map[] =
3512 { 0x010081, 0x5e }, // System Power Down
3513 { 0x010082, 0x5f }, // System Sleep
3514 { 0x010083, 0x63 }, // System Wake Up
3516 { 0x070046, 0x4c }, // Keyboard Print Screen
3517 { 0x070047, 0x64 }, // Keyboard Scroll Lock
3518 { 0x070048, 0x45 }, // Keyboard Pause
3519 { 0x070049, 0x0a }, // Keyboard Insert
3521 { 0x070066, 0x5e }, // Keyboard Power
3523 { 0x07007A, 0x08 }, // Keyboard Undo
3524 { 0x07007B, 0x17 }, // Keyboard Cut
3525 { 0x07007C, 0x18 }, // Keyboard Copy
3526 { 0x07007D, 0x0a }, // Keyboard Paste
3527 { 0x07007F, 0x20 }, // Keyboard Mute
3528 { 0x070080, 0x30 }, // Keyboard Volume Up
3529 { 0x070081, 0x2e }, // Keyboard Volume Down
3531 { 0x0C0030, 0x5e }, // Power
3532 { 0x0C0032, 0x5f }, // Sleep
3533 { 0x0C0033, 0x5f }, // Sleep After
3534 { 0x0C0034, 0x5f }, // Sleep Mode
3536 { 0x0C0094, 0x40 }, // Quit
3537 { 0x0C0095, 0x3b }, // Help
3538 { 0x0C00B0, 0x22 }, // Play
3539 { 0x0C00B1, 0x22 }, // Pause
3540 { 0x0C00B5, 0x19 }, // Scan Next Track
3541 { 0x0C00B6, 0x10 }, // Scan Previous Track
3542 { 0x0C00B7, 0x24 }, // Stop
3543 { 0x0C00CC, 0x24 }, // Stop/Eject
3544 { 0x0C00CD, 0x22 }, // Play/Pause
3545 { 0x0C00CE, 0x22 }, // Play/Skip
3547 { 0x0C00E2, 0x20 }, // Mute
3548 { 0x0C00E9, 0x30 }, // Volume Increment
3549 { 0x0C00EA, 0x2e }, // Volume Decrement
3551 { 0x0C0183, 0x6d }, // AL Consumer Control Configuration
3552 { 0x0C0184, 0x13 }, // AL Word Processor
3553 { 0x0C0185, 0x13 }, // AL Text Editor
3554 { 0x0C0186, 0x14 }, // AL Spreadsheet
3555 { 0x0C018A, 0x6c }, // AL Email Reader
3556 { 0x0C018F, 0x3d }, // AL Task/Project Manager
3557 { 0x0C0192, 0x21 }, // AL Calculator
3558 { 0x0C0194, 0x3c }, // AL Local Machine Browser
3559 { 0x0C0196, 0x3c }, // AL Internet Browser
3560 { 0x0C019B, 0x16 }, // AL Logon
3561 { 0x0C019C, 0x16 }, // AL Logoff
3562 { 0x0C019D, 0x16 }, // AL Logon/Logoff
3563 { 0x0C01A1, 0x3d }, // AL Process/Task Manager
3564 { 0x0C01A3, 0x1e }, // AL Next Task/Application
3565 { 0x0C01A4, 0x09 }, // AL Previous Task/Application
3566 { 0x0C01A6, 0x3b }, // AL Integrated Help Center
3567 { 0x0C01A7, 0x6b }, // AL Documents
3568 { 0x0C01A8, 0x23 }, // AL Thesaurus
3569 { 0x0C01A9, 0x23 }, // AL Dictionary
3570 { 0x0C01AB, 0x23 }, // AL Spell Check
3571 { 0x0C01AC, 0x23 }, // AL Grammar Check
3572 { 0x0C01B4, 0x05 }, // AL File Browser
3573 { 0x0C01BD, 0x3b }, // AL OEM Features/ Tips/Tutorial Browser
3574 { 0x0C01BE, 0x3b }, // AL OEM Help
3576 { 0x0C0201, 0x3e }, // AC New
3577 { 0x0C0202, 0x3f }, // AC Open
3578 { 0x0C0203, 0x40 }, // AC Close
3579 { 0x0C0204, 0x40 }, // AC Exit
3580 { 0x0C0207, 0x57 }, // AC Save
3581 { 0x0C0208, 0x58 }, // AC Print
3582 { 0x0C021A, 0x08 }, // AC Undo
3583 { 0x0C021B, 0x18 }, // AC Copy
3584 { 0x0C021C, 0x17 }, // AC Cut
3585 { 0x0C021D, 0x0a }, // AC Paste
3586 { 0x0C021F, 0x65 }, // AC Find
3587 { 0x0C0220, 0x65 }, // AC Find and Replace
3588 { 0x0C0221, 0x65 }, // AC Search
3589 { 0x0C0223, 0x32 }, // AC Home
3590 { 0x0C0224, 0x6a }, // AC Back
3591 { 0x0C0225, 0x69 }, // AC Forward
3592 { 0x0C0226, 0x68 }, // AC Stop
3593 { 0x0C0227, 0x67 }, // AC Refresh
3594 { 0x0C0228, 0x6a }, // AC Previous Link
3595 { 0x0C0229, 0x69 }, // AC Next Link
3596 { 0x0C022A, 0x66 }, // AC Bookmarks
3597 { 0x0C022B, 0x66 }, // AC History
3598 { 0x0C022C, 0x66 }, // AC Subscriptions
3599 { 0x0C0279, 0x07 }, // AC Redo/Repeat
3600 { 0x0C0288, 0x43 }, // AC Send To
3601 { 0x0C0289, 0x41 }, // AC Reply
3602 { 0x0C028A, 0x41 }, // AC Reply All
3603 { 0x0C028B, 0x42 }, // AC Forward Msg
3604 { 0x0C028C, 0x43 }, // AC Send
3606 { 0x000000, 0x00 }
3608 /* \\\ */
3610 /* /// "nDetectDefaultAction()" */
3611 BOOL nDetectDefaultAction(struct NepClassHid *nch, struct NepHidItem *nhi, struct List *lst, struct NepHidCollection *nhc, ULONG uid)
3613 BOOL res = FALSE;
3614 UWORD usageid = uid;
3615 struct NepHidAction *nha;
3616 struct WacomCaps *wc;
3617 const struct UsbToPs2Map *utp = usbtops2map;
3619 switch(uid>>16)
3621 case 0x01: /* generic desktop page */
3622 if(usageid == 0xfff0) /* extra init */
3624 /* AipTek USB Tablets Support */
3625 IPTR vendid = 0;
3626 IPTR prodid = 0;
3627 ULONG command;
3628 ULONG data;
3630 psdGetAttrs(PGA_DEVICE, nch->nch_Device,
3631 DA_VendorID, &vendid,
3632 DA_ProductID, &prodid,
3633 TAG_END);
3634 if((vendid == 0x08ca) &&
3635 ((prodid == 0x0001) || (prodid == 0x0010) ||
3636 ((prodid >= 0x0020) && (prodid <= 0x0024))) &&
3637 (!nhi->nhi_ActionList.lh_Head->ln_Succ))
3639 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3640 "Generating special AipTek USB Tablet init sequence.");
3641 command = nFindItemUsage(nch, 0x0D003F, REPORT_MAIN_FEATURE);
3642 data = nFindItemUsage(nch, 0x0D0040, REPORT_MAIN_FEATURE);
3643 if(command && data)
3645 /* set resolution to 500DPI */
3646 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3648 nha->nha_FeatOp = HUAT_ASSIGN;
3649 nha->nha_FeatItem = command;
3650 nha->nha_ValEnable = TRUE;
3651 nha->nha_ValVar = HUAT_CONST;
3652 nha->nha_ValConst = 0x18;
3654 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3656 nha->nha_FeatOp = HUAT_ASSIGN;
3657 nha->nha_FeatItem = data;
3658 nha->nha_ValEnable = TRUE;
3659 nha->nha_ValVar = HUAT_CONST;
3660 nha->nha_ValConst = 0x04;
3662 if((nha = nAllocAction(nch, lst, HUA_MISC|HUA_ANY)))
3664 nha->nha_MiscMode = HUAT_FLUSHEVENTS;
3667 /* set absolute tablet mode */
3668 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3670 nha->nha_FeatOp = HUAT_ASSIGN;
3671 nha->nha_FeatItem = command;
3672 nha->nha_ValEnable = TRUE;
3673 nha->nha_ValVar = HUAT_CONST;
3674 nha->nha_ValConst = 0x10;
3676 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3678 nha->nha_FeatOp = HUAT_ASSIGN;
3679 nha->nha_FeatItem = data;
3680 nha->nha_ValEnable = TRUE;
3681 nha->nha_ValVar = HUAT_CONST;
3682 nha->nha_ValConst = 0x01;
3684 if((nha = nAllocAction(nch, lst, HUA_MISC|HUA_ANY)))
3686 nha->nha_MiscMode = HUAT_FLUSHEVENTS;
3689 /* enable macro keys */
3690 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3692 nha->nha_FeatOp = HUAT_ASSIGN;
3693 nha->nha_FeatItem = command;
3694 nha->nha_ValEnable = TRUE;
3695 nha->nha_ValVar = HUAT_CONST;
3696 nha->nha_ValConst = 0x11;
3698 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3700 nha->nha_FeatOp = HUAT_ASSIGN;
3701 nha->nha_FeatItem = data;
3702 nha->nha_ValEnable = TRUE;
3703 nha->nha_ValVar = HUAT_CONST;
3704 nha->nha_ValConst = 0x02;
3706 if((nha = nAllocAction(nch, lst, HUA_MISC|HUA_ANY)))
3708 nha->nha_MiscMode = HUAT_FLUSHEVENTS;
3711 /* enable auto gain */
3712 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3714 nha->nha_FeatOp = HUAT_ASSIGN;
3715 nha->nha_FeatItem = command;
3716 nha->nha_ValEnable = TRUE;
3717 nha->nha_ValVar = HUAT_CONST;
3718 nha->nha_ValConst = 0x12;
3720 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3722 nha->nha_FeatOp = HUAT_ASSIGN;
3723 nha->nha_FeatItem = data;
3724 nha->nha_ValEnable = TRUE;
3725 nha->nha_ValVar = HUAT_CONST;
3726 nha->nha_ValConst = 0xff;
3728 /*if((nha = nAllocAction(nch, lst, HUA_MISC|HUA_ANY)))
3730 nha->nha_MiscMode = HUAT_FLUSHEVENTS;
3732 } else {
3733 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
3734 "AipTek: No command (%ld) or data (%ld) feature!", command, data);
3737 if(vendid == 0x056a)
3739 for(wc = WacomCapsTable; wc->wc_ProdID != prodid; wc++)
3741 if(wc->wc_ProdID == 0xffff)
3743 wc = NULL;
3744 break;
3747 } else {
3748 wc = NULL;
3750 if(wc)
3752 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3753 "Generating special Wacom USB Tablet init sequence.");
3754 command = nFindItemUsage(nch, 0xff000001, REPORT_MAIN_FEATURE);
3755 if(command)
3757 /* activate returning of absolute tablet data */
3758 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3760 nha->nha_FeatOp = HUAT_ASSIGN;
3761 nha->nha_FeatItem = command;
3762 nha->nha_ValEnable = TRUE;
3763 nha->nha_ValVar = HUAT_CONST;
3764 nha->nha_ValConst = 0x02;
3766 if((nha = nAllocAction(nch, lst, HUA_MISC|HUA_ANY)))
3768 nha->nha_MiscMode = HUAT_FLUSHEVENTS;
3770 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3772 nha->nha_FeatOp = HUAT_ASSIGN;
3773 nha->nha_FeatItem = command;
3774 nha->nha_ValEnable = TRUE;
3775 nha->nha_ValVar = HUAT_CONST;
3776 nha->nha_ValConst = 0x02;
3781 if((vendid == 0x046d) &&
3782 (!nhi->nhi_ActionList.lh_Head->ln_Succ))
3784 command = nFindItemUsage(nch, 0xff000001, REPORT_MAIN_OUTPUT);
3785 if(command)
3787 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3788 "Adding special HID2HCI Logitech Bluetooth init sequence, but deactivated!");
3789 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3790 "This init sequence would disable HID usage and enable pure Bluetooth use!");
3791 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3792 "If you want to use this dongle for Bluetooth, switch the NOP-Startup-Actions to type Output!");
3793 // send three commands to output report 0x10
3794 if((nha = nAllocAction(nch, lst, HUA_NOP|HUA_ANY)))
3796 nha->nha_OutItem = command;
3797 strcpy(nha->nha_OutArray, "0xff, 0x80, 0x80, 0x01, 0x00, 0x00");
3799 if((nha = nAllocAction(nch, lst, HUA_MISC|HUA_ANY)))
3801 nha->nha_MiscMode = HUAT_FLUSHEVENTS;
3803 if((nha = nAllocAction(nch, lst, HUA_NOP|HUA_ANY)))
3805 nha->nha_OutItem = command;
3806 strcpy(nha->nha_OutArray, "0xff, 0x80, 0x00, 0x00, 0x30, 0x00");
3808 if((nha = nAllocAction(nch, lst, HUA_MISC|HUA_ANY)))
3810 nha->nha_MiscMode = HUAT_FLUSHEVENTS;
3812 if((nha = nAllocAction(nch, lst, HUA_NOP|HUA_ANY)))
3814 nha->nha_OutItem = command;
3815 strcpy(nha->nha_OutArray, "0xff, 0x81, 0x80, 0x00, 0x00, 0x00");
3821 if(nFindCollID(nch, nhc, 0x010002, 0x010002) || /* Mice */
3822 nFindCollID(nch, nhc, 0x0d0001, 0x0d000d)) /* Tablets */
3824 switch(usageid)
3826 case 0x30: /* Mouse X */
3827 if((nha = nAllocAction(nch, lst, HUA_MOUSEPOS|HUA_ALWAYS)))
3829 if(nhi->nhi_Flags & RPF_MAIN_RELATIVE)
3831 nha->nha_MouseAxis = HUAT_DELTAX;
3832 } else {
3833 nha->nha_MouseAxis = HUAT_ABSX;
3834 nha->nha_ClipEnable = TRUE;
3835 nha->nha_ClipMin = 5;
3836 nha->nha_ClipMax = 95;
3837 nha->nha_ClipStretch = TRUE;
3840 break;
3842 case 0x31: /* Mouse Y */
3843 if((nha = nAllocAction(nch, lst, HUA_MOUSEPOS|HUA_ALWAYS)))
3845 if(nhi->nhi_Flags & RPF_MAIN_RELATIVE)
3847 nha->nha_MouseAxis = HUAT_DELTAY;
3848 } else {
3849 nha->nha_MouseAxis = HUAT_ABSY;
3850 nha->nha_ClipEnable = TRUE;
3851 nha->nha_ClipMin = 5;
3852 nha->nha_ClipMax = 95;
3853 nha->nha_ClipStretch = TRUE;
3856 break;
3858 case 0x38: /* Wheel */
3859 if((nha = nAllocAction(nch, lst, HUA_WHEEL|HUA_ALWAYS)))
3861 nha->nha_WheelMode = HUAT_DELTAY;
3862 nha->nha_WheelDist = 1;
3864 break;
3868 if(nFindCollID(nch, nhc, 0x010004, 0x010005)) /* Joystick, Game Pad */
3870 switch(usageid)
3872 case 0x39: /* Hatswitch */
3873 if((nha = nAllocAction(nch, lst, HUA_DIGJOY|HUA_NAN)))
3875 nha->nha_JoypadOp = HUAT_CLEAR;
3876 nha->nha_JoypadFeat = HUAT_HATSWITCH;
3877 nha->nha_JoypadPort = 1;
3879 if((nha = nAllocAction(nch, lst, HUA_DIGJOY|HUA_ALWAYS)))
3881 nha->nha_JoypadOp = HUAT_ASSIGN;
3882 nha->nha_JoypadFeat = HUAT_HATSWITCH;
3883 nha->nha_JoypadPort = 1;
3885 break;
3887 case 0x30: /* X axis */
3888 case 0x35: /* Z rotation */
3889 case 0x31: /* Y axis */
3890 case 0x32: /* Z axis */
3892 ULONG minpos = ((nhi->nhi_LogicalMax - nhi->nhi_LogicalMin + 1)>>2) + nhi->nhi_LogicalMin;
3893 ULONG maxpos = (((nhi->nhi_LogicalMax - nhi->nhi_LogicalMin + 1)*3)>>2) + nhi->nhi_LogicalMin;
3894 UBYTE negaxis;
3895 UBYTE posaxis;
3896 UBYTE alogaxis;
3897 if((usageid == 0x30) || (usageid == 0x35))
3899 negaxis = HUAT_LEFT;
3900 posaxis = HUAT_RIGHT;
3901 alogaxis = HUAT_ABSX;
3902 } else {
3903 negaxis = HUAT_UP;
3904 posaxis = HUAT_DOWN;
3905 alogaxis = HUAT_ABSY;
3907 if((nha = nAllocAction(nch, lst, HUA_DIGJOY|HUA_ANY)))
3909 nha->nha_CCEnable = TRUE;
3910 nha->nha_CCCond = HUAT_GT;
3911 nha->nha_CCConst2 = minpos;
3912 nha->nha_JoypadOp = HUAT_CLEAR;
3913 nha->nha_JoypadFeat = negaxis;
3914 nha->nha_JoypadPort = 1;
3916 if((nha = nAllocAction(nch, lst, HUA_DIGJOY|HUA_ANY)))
3918 nha->nha_CCEnable = TRUE;
3919 nha->nha_CCCond = HUAT_LE;
3920 nha->nha_CCConst2 = minpos;
3921 nha->nha_JoypadOp = HUAT_SET;
3922 nha->nha_JoypadFeat = negaxis;
3923 nha->nha_JoypadPort = 1;
3925 if((nha = nAllocAction(nch, lst, HUA_DIGJOY|HUA_ANY)))
3927 nha->nha_CCEnable = TRUE;
3928 nha->nha_CCCond = HUAT_LT;
3929 nha->nha_CCConst2 = maxpos;
3930 nha->nha_JoypadOp = HUAT_CLEAR;
3931 nha->nha_JoypadFeat = posaxis;
3932 nha->nha_JoypadPort = 1;
3934 if((nha = nAllocAction(nch, lst, HUA_DIGJOY|HUA_ANY)))
3936 nha->nha_CCEnable = TRUE;
3937 nha->nha_CCCond = HUAT_GE;
3938 nha->nha_CCConst2 = maxpos;
3939 nha->nha_JoypadOp = HUAT_SET;
3940 nha->nha_JoypadFeat = posaxis;
3941 nha->nha_JoypadPort = 1;
3943 if((nha = nAllocAction(nch, lst, HUA_ANALOGJOY|HUA_ANY)))
3945 nha->nha_APadFeat = alogaxis;
3946 nha->nha_JoypadPort = 1;
3948 break;
3953 if(nFindCollID(nch, nhc, 0x010008, 0x010008) && (nhi->nhi_Flags & RPF_MAIN_RELATIVE)) /* Multi-axis controller */
3955 switch(usageid)
3957 case 0x30: /* Mouse X */
3958 if((nha = nAllocAction(nch, lst, HUA_MOUSEPOS|HUA_ALWAYS)))
3960 nha->nha_MouseAxis = HUAT_DELTAX;
3961 nha->nha_ClipEnable = TRUE;
3962 nha->nha_ClipMin = 10;
3963 nha->nha_ClipMax = 45;
3964 nha->nha_ClipStretch = TRUE;
3965 nha->nha_ScaleEnable = TRUE;
3966 nha->nha_ScaleMin = -32;
3967 nha->nha_ScaleMax = 0;
3968 nha->nha_CCEnable = TRUE;
3969 nha->nha_CCVar1 = HUAT_OITEMVALUE;
3970 nha->nha_CCCond = HUAT_LT;
3971 nha->nha_CCConst2 = 0;
3973 if((nha = nAllocAction(nch, lst, HUA_MOUSEPOS|HUA_ALWAYS)))
3975 nha->nha_MouseAxis = HUAT_DELTAX;
3976 nha->nha_ClipEnable = TRUE;
3977 nha->nha_ClipMin = 55;
3978 nha->nha_ClipMax = 90;
3979 nha->nha_ClipStretch = TRUE;
3980 nha->nha_ScaleEnable = TRUE;
3981 nha->nha_ScaleMin = 0;
3982 nha->nha_ScaleMax = 32;
3983 nha->nha_CCEnable = TRUE;
3984 nha->nha_CCVar1 = HUAT_OITEMVALUE;
3985 nha->nha_CCCond = HUAT_GT;
3986 nha->nha_CCConst2 = 0;
3988 break;
3990 case 0x31: /* Mouse Y */
3991 if((nha = nAllocAction(nch, lst, HUA_MOUSEPOS|HUA_ALWAYS)))
3993 nha->nha_MouseAxis = HUAT_DELTAY;
3994 nha->nha_ClipEnable = TRUE;
3995 nha->nha_ClipMin = 10;
3996 nha->nha_ClipMax = 45;
3997 nha->nha_ClipStretch = TRUE;
3998 nha->nha_ScaleEnable = TRUE;
3999 nha->nha_ScaleMin = -32;
4000 nha->nha_ScaleMax = 0;
4001 nha->nha_CCEnable = TRUE;
4002 nha->nha_CCVar1 = HUAT_OITEMVALUE;
4003 nha->nha_CCCond = HUAT_LT;
4004 nha->nha_CCConst2 = 0;
4006 if((nha = nAllocAction(nch, lst, HUA_MOUSEPOS|HUA_ALWAYS)))
4008 nha->nha_MouseAxis = HUAT_DELTAY;
4009 nha->nha_ClipEnable = TRUE;
4010 nha->nha_ClipMin = 55;
4011 nha->nha_ClipMax = 90;
4012 nha->nha_ClipStretch = TRUE;
4013 nha->nha_ScaleEnable = TRUE;
4014 nha->nha_ScaleMin = 0;
4015 nha->nha_ScaleMax = 32;
4016 nha->nha_CCEnable = TRUE;
4017 nha->nha_CCVar1 = HUAT_OITEMVALUE;
4018 nha->nha_CCCond = HUAT_GT;
4019 nha->nha_CCConst2 = 0;
4021 break;
4023 case 0x32: /* Mouse Z */
4025 LONG minpos = (((nhi->nhi_LogicalMax - nhi->nhi_LogicalMin + 1)*3)>>3) + nhi->nhi_LogicalMin;
4026 LONG maxpos = (((nhi->nhi_LogicalMax - nhi->nhi_LogicalMin + 1)*5)>>3) + nhi->nhi_LogicalMin;
4027 UWORD led = nFindItemUsage(nch, 0x08004B, REPORT_MAIN_OUTPUT); // blue LED
4028 if(maxpos > 0)
4030 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4032 nha->nha_ButtonMode = HUAT_SET;
4033 nha->nha_ButtonNo = 1;
4034 nha->nha_CCEnable = TRUE;
4035 nha->nha_CCCond = HUAT_GT;
4036 nha->nha_CCConst2 = maxpos;
4038 if(led && ((nha = nAllocAction(nch, lst, HUA_OUTPUT|HUA_ANY))))
4040 nha->nha_OutOp = HUAT_SET;
4041 nha->nha_OutItem = led;
4042 nha->nha_CCEnable = TRUE;
4043 nha->nha_CCCond = HUAT_GT;
4044 nha->nha_CCConst2 = maxpos;
4046 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4048 nha->nha_ButtonMode = HUAT_CLEAR;
4049 nha->nha_ButtonNo = 1;
4050 nha->nha_CCEnable = TRUE;
4051 nha->nha_CCCond = HUAT_LT;
4052 nha->nha_CCConst2 = maxpos;
4054 if(led && ((nha = nAllocAction(nch, lst, HUA_OUTPUT|HUA_ANY))))
4056 nha->nha_OutOp = HUAT_CLEAR;
4057 nha->nha_OutItem = led;
4058 nha->nha_CCEnable = TRUE;
4059 nha->nha_CCCond = HUAT_LT;
4060 nha->nha_CCConst2 = maxpos;
4063 if(minpos < 0)
4065 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4067 nha->nha_ButtonMode = HUAT_SET;
4068 nha->nha_ButtonNo = 2;
4069 nha->nha_CCEnable = TRUE;
4070 nha->nha_CCCond = HUAT_LT;
4071 nha->nha_CCConst2 = minpos;
4073 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4075 nha->nha_ButtonMode = HUAT_CLEAR;
4076 nha->nha_ButtonNo = 2;
4077 nha->nha_CCEnable = TRUE;
4078 nha->nha_CCCond = HUAT_GT;
4079 nha->nha_CCConst2 = minpos;
4082 break;
4085 case 0x35: /* Z rotation */
4087 LONG minpos = (((nhi->nhi_LogicalMax - nhi->nhi_LogicalMin + 1)*2)>>3) + nhi->nhi_LogicalMin;
4088 LONG maxpos = (((nhi->nhi_LogicalMax - nhi->nhi_LogicalMin + 1)*6)>>3) + nhi->nhi_LogicalMin;
4089 if(maxpos > 0)
4091 if((nha = nAllocAction(nch, lst, HUA_WHEEL|HUA_ANY)))
4093 nha->nha_WheelMode = HUAT_DOWN;
4094 nha->nha_WheelDist = 1;
4095 nha->nha_CCEnable = TRUE;
4096 nha->nha_CCCond = HUAT_GT;
4097 nha->nha_CCConst2 = maxpos;
4100 if(minpos < 0)
4102 if((nha = nAllocAction(nch, lst, HUA_WHEEL|HUA_ANY)))
4104 nha->nha_WheelMode = HUAT_UP;
4105 nha->nha_WheelDist = 1;
4106 nha->nha_CCEnable = TRUE;
4107 nha->nha_CCCond = HUAT_LT;
4108 nha->nha_CCConst2 = minpos;
4111 break;
4115 break;
4117 case 0x09: /* Button page */
4118 if(nFindCollID(nch, nhc, 0x010002, 0x010002) || /* Mice */
4119 nFindCollID(nch, nhc, 0x0d0001, 0x0d000d) || /* Tablets */
4120 nFindCollID(nch, nhc, 0x010008, 0x010008)) /* Multi-Axis controller */
4122 if(usageid && (usageid < 6))
4124 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4126 nha->nha_ButtonMode = HUAT_ASSIGN;
4127 nha->nha_ButtonNo = usageid;
4131 if(nFindCollID(nch, nhc, 0x010004, 0x010005)) /* Joystick, Game Pad */
4133 if(usageid && (usageid < 8))
4135 if((nha = nAllocAction(nch, lst, HUA_DIGJOY|HUA_ANY)))
4137 nha->nha_JoypadOp = HUAT_ASSIGN;
4138 nha->nha_JoypadFeat = HUAT_RED + usageid - 1;
4139 nha->nha_JoypadPort = 1;
4143 break;
4145 case 0x07: /* keyboard page */
4146 switch(usageid)
4148 case 0x39: /* Caps lock */
4150 UWORD led;
4151 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_DOWNEVENT)))
4153 nha->nha_QualMode = HUAT_TOGGLE;
4154 nha->nha_Qualifier = IEQUALIFIERB_CAPSLOCK;
4156 if((led = nFindItemUsage(nch, 0x080002, REPORT_MAIN_OUTPUT)))
4158 if((nha = nAllocAction(nch, lst, HUA_OUTPUT|HUA_DOWNEVENT)))
4160 nha->nha_OutOp = HUAT_SET;
4161 nha->nha_OutItem = led;
4162 nha->nha_CCEnable = TRUE;
4163 nha->nha_CCVar1 = HUAT_QUALIFIERS;
4164 nha->nha_CCCond = HUAT_BWAND;
4165 nha->nha_CCVar2 = HUAT_CONST;
4166 nha->nha_CCConst2 = IEQUALIFIER_CAPSLOCK;
4168 if((nha = nAllocAction(nch, lst, HUA_OUTPUT|HUA_DOWNEVENT)))
4170 nha->nha_OutOp = HUAT_CLEAR;
4171 nha->nha_OutItem = led;
4172 nha->nha_CCEnable = TRUE;
4173 nha->nha_CCVar1 = HUAT_QUALIFIERS;
4174 nha->nha_CCCond = HUAT_BWNAND;
4175 nha->nha_CCVar2 = HUAT_CONST;
4176 nha->nha_CCConst2 = IEQUALIFIER_CAPSLOCK;
4179 break;
4182 case 0xe0: /* Left control */
4183 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4185 nha->nha_QualMode = HUAT_ASSIGN;
4186 nha->nha_Qualifier = IEQUALIFIERB_CONTROL;
4188 break;
4190 case 0xe1: /* Left shift */
4191 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4193 nha->nha_QualMode = HUAT_ASSIGN;
4194 nha->nha_Qualifier = IEQUALIFIERB_LSHIFT;
4196 break;
4198 case 0xe2: /* Left alt */
4199 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4201 nha->nha_QualMode = HUAT_ASSIGN;
4202 nha->nha_Qualifier = IEQUALIFIERB_LALT;
4204 break;
4206 case 0xe3: /* Left GUI */
4207 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4209 nha->nha_QualMode = HUAT_ASSIGN;
4210 nha->nha_Qualifier = IEQUALIFIERB_LCOMMAND;
4212 break;
4214 case 0xe4: /* Right control */
4215 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4217 nha->nha_QualMode = HUAT_ASSIGN;
4218 nha->nha_Qualifier = IEQUALIFIERB_CONTROL;
4220 break;
4222 case 0xe5: /* Right shift */
4223 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4225 nha->nha_QualMode = HUAT_ASSIGN;
4226 nha->nha_Qualifier = IEQUALIFIERB_RSHIFT;
4228 break;
4230 case 0xe6: /* Right alt */
4231 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4233 nha->nha_QualMode = HUAT_ASSIGN;
4234 nha->nha_Qualifier = IEQUALIFIERB_RALT;
4236 break;
4238 case 0x45: /* F12 */
4239 case 0x65: /* Application */
4240 case 0xe7: /* Right GUI */
4241 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4243 nha->nha_QualMode = HUAT_ASSIGN;
4244 nha->nha_Qualifier = IEQUALIFIERB_RCOMMAND;
4246 break;
4248 nha = nAllocAction(nch, lst, HUA_KEYMAP|HUA_ANY);
4249 break;
4251 case 0x0d: /* digitizer/tablet page */
4252 switch(usageid)
4254 case 0x30: /* Tip pressure */
4255 case 0x31: /* Barrel pressure */
4256 if((nha = nAllocAction(nch, lst, HUA_TABLET|HUA_ALWAYS)))
4258 nha->nha_TabletAxis = HUAT_PRESSURE;
4260 break;
4262 case 0x32: /* In Range */
4263 case 0x37: /* Data Valid */
4264 if((nha = nAllocAction(nch, lst, HUA_TABLET|HUA_ALWAYS)))
4266 nha->nha_TabletAxis = HUAT_PROX;
4268 break;
4270 case 0x3D: /* X Tilt */
4271 if((nha = nAllocAction(nch, lst, HUA_TABLET|HUA_ALWAYS)))
4273 nha->nha_TabletAxis = HUAT_XROT;
4275 break;
4277 case 0x3E: /* Y Tilt */
4278 if((nha = nAllocAction(nch, lst, HUA_TABLET|HUA_ALWAYS)))
4280 nha->nha_TabletAxis = HUAT_YROT;
4282 break;
4284 case 0x42: /* Tip switch */
4285 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4287 nha->nha_ButtonMode = HUAT_ASSIGN;
4288 nha->nha_ButtonNo = 1;
4290 break;
4292 case 0x44: /* Barrel switch */
4293 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4295 nha->nha_ButtonMode = HUAT_ASSIGN;
4296 nha->nha_ButtonNo = 2;
4298 break;
4300 case 0x46: /* Tablet pick */
4301 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4303 nha->nha_ButtonMode = HUAT_ASSIGN;
4304 nha->nha_ButtonNo = 3;
4306 break;
4308 break;
4310 while(utp->utp_UsageID && (utp->utp_UsageID <= uid))
4312 if(utp->utp_UsageID == uid)
4314 if((nha = nAllocAction(nch, lst, HUA_EXTRAWKEY|HUA_DOWNEVENT)))
4316 nha->nha_RawKey = utp->utp_ExtCode;
4318 if((nha = nAllocAction(nch, lst, HUA_EXTRAWKEY|HUA_UPEVENT)))
4320 nha->nha_RawKey = utp->utp_ExtCode|IECODE_UP_PREFIX;
4323 utp++;
4325 return(res);
4327 /* \\\ */
4329 /* /// "nCheckForDefaultAction()" */
4330 BOOL nCheckForDefaultAction(struct NepClassHid *nch, struct NepHidItem *nhi, struct List *lst, struct NepHidCollection *nhc, ULONG uid)
4332 BOOL res = TRUE;
4333 struct NepHidAction *nha;
4334 struct NepHidAction *nhadef;
4335 struct List tmplist;
4337 NewList(&tmplist);
4338 nDetectDefaultAction(nch, nhi, &tmplist, nhc, nhi->nhi_Usage);
4339 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
4340 nhadef = (struct NepHidAction *) tmplist.lh_Head;
4341 while(nha->nha_Node.ln_Succ)
4343 if(nhadef->nha_Node.ln_Succ)
4345 nhadef->nha_IsDefault = nha->nha_IsDefault;
4346 if(memcmp(&nha->nha_Type, &nhadef->nha_Type, sizeof(struct NepHidAction)-offsetof(struct NepHidAction, nha_Type)))
4348 nha->nha_IsDefault = FALSE;
4349 res = FALSE;
4350 } else {
4351 nha->nha_IsDefault = TRUE;
4353 nhadef = (struct NepHidAction *) nhadef->nha_Node.ln_Succ;
4354 } else {
4355 res = FALSE;
4356 nha->nha_IsDefault = FALSE;
4358 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
4360 nhadef = (struct NepHidAction *) tmplist.lh_Head;
4361 while(nhadef->nha_Node.ln_Succ)
4363 Remove(&nhadef->nha_Node);
4364 psdFreeVec(nhadef);
4365 nhadef = (struct NepHidAction *) tmplist.lh_Head;
4367 return(res);
4369 /* \\\ */
4371 /* /// "nAllocAction()" */
4372 struct NepHidAction * nAllocAction(struct NepClassHid *nch, struct List *lst, UWORD utype)
4374 struct NepHidAction *nha = psdAllocVec(sizeof(struct NepHidAction));
4375 if(nha)
4377 KPRINTF(1, ("New action %lx\n", nha));
4378 nha->nha_Type = utype;
4379 nha->nha_ButtonNo = 1;
4380 nha->nha_SoundVolume = 64;
4381 nha->nha_ClipMax = 100;
4382 nha->nha_CCVar1 = HUAT_EITEMVALUE;
4383 nha->nha_CCVar2 = HUAT_CONST;
4384 AddTail(lst, &nha->nha_Node);
4385 return(nha);
4387 return(NULL);
4389 /* \\\ */
4391 /* /// "nAddUsage()" */
4392 BOOL nAddUsage(struct NepClassHid *nch, struct List *list, ULONG umin, ULONG umax)
4394 struct NepHidUsage *nhu;
4395 if(umin > umax)
4397 KPRINTF(10, ("UsageMin %lx > UsageMax %lx\n", umin, umax));
4398 return(FALSE);
4400 if((nhu = psdAllocVec(sizeof(struct NepHidUsage))))
4402 AddTail(list, &nhu->nhu_Node);
4403 nhu->nhu_Usage = umin;
4404 nhu->nhu_UsageMax = umax;
4405 return(TRUE);
4406 } else {
4407 KPRINTF(10, ("Out of memory during usage allocation.\n"));
4409 return(FALSE);
4411 /* \\\ */
4413 /* /// "nGetUsageName()" */
4414 STRPTR nGetUsageName(struct NepClassHid *nch, ULONG uid)
4416 STRPTR uname;
4418 uname = nNumToStr(nch, NTS_USAGEID, uid, NULL);
4419 if(uname)
4421 return(psdCopyStr(uname));
4423 uname = nNumToStr(nch, NTS_USAGEPAGE, uid>>16, "unknown");
4424 return(psdCopyStrFmt("%s (0x%lx)", uname, uid));
4426 /* \\\ */
4428 /* /// "nGenerateOutReport()" */
4429 void nGenerateOutReport(struct NepClassHid *nch, struct NepHidReport *nhr, UBYTE *buf)
4431 struct NepHidItem **nhiptr = nhr->nhr_OutItemMap;
4432 ULONG cnt;
4434 for(cnt = 0; cnt < nhr->nhr_OutItemCount; cnt++)
4436 nEncodeItemBuffer(nch, *nhiptr++, buf);
4439 /* \\\ */
4441 /* /// "nGenerateFeatReport()" */
4442 void nGenerateFeatReport(struct NepClassHid *nch, struct NepHidReport *nhr, UBYTE *buf)
4444 struct NepHidItem **nhiptr = nhr->nhr_FeatItemMap;
4445 ULONG cnt;
4447 for(cnt = 0; cnt < nhr->nhr_FeatItemCount; cnt++)
4449 nEncodeItemBuffer(nch, *nhiptr++, buf);
4452 /* \\\ */
4454 /* /// "nEncodeItemBuffer()" */
4455 void nEncodeItemBuffer(struct NepClassHid *nch, struct NepHidItem *nhi, UBYTE *buf)
4457 LONG value;
4458 LONG *valptr;
4459 ULONG ioffset;
4460 ULONG isize;
4461 UWORD count;
4462 UWORD acount;
4464 ioffset = nhi->nhi_Offset;
4465 isize = nhi->nhi_Size;
4466 if(nhi->nhi_Flags & RPF_MAIN_VARIABLE)
4468 //KPRINTF(1, ("Processing var %08lx (%ld@%ld)...\n", nhi, isize, ioffset));
4469 value = nhi->nhi_OldValue;
4470 if(value < nhi->nhi_LogicalMin)
4472 value = nhi->nhi_LogicalMin;
4474 else if(value > nhi->nhi_LogicalMax)
4476 value = nhi->nhi_LogicalMax;
4478 if(((ioffset & 7) == 0) && (isize == 8))
4480 buf[ioffset>>3] = value;
4482 else if(isize == 1)
4484 buf[ioffset>>3] &= ~(1UL<<(ioffset & 7));
4485 if(value)
4487 buf[ioffset>>3] |= (1UL<<(ioffset & 7));
4489 } else {
4490 /* I know this routine is dead slow, but hopefully, this is only a very uncommon case */
4491 count = isize;
4492 ioffset += count;
4495 ioffset--;
4496 buf[ioffset>>3] &= ~(1UL<<(ioffset & 7));
4497 if(value & 1)
4499 buf[ioffset>>3] |= (1UL<<(ioffset & 7));
4501 value >>= 1;
4502 } while(--count);
4504 } else {
4505 acount = nhi->nhi_Count;
4506 KPRINTF(1, ("Processing arr %08lx (%ld@%ld) * %ld...\n", nhi, isize, ioffset, acount));
4507 /* first generate the values */
4508 valptr = nhi->nhi_Buffer;
4509 if(((ioffset & 7) == 0) && (isize == 8))
4511 count = ioffset>>3;
4514 buf[count++] = *valptr++;
4515 } while(--acount);
4517 else if(isize == 1)
4521 buf[ioffset>>3] &= ~(1UL<<(ioffset & 7));
4522 if(*valptr++)
4524 buf[ioffset>>3] |= (1UL<<(ioffset & 7));
4526 ioffset++;
4527 } while(--acount);
4528 } else {
4529 /* I know this routine is dead slow, but hopefully, this is only a very uncommon case */
4532 count = isize;
4533 ioffset += count;
4534 value = *valptr++;
4537 ioffset--;
4538 buf[ioffset>>3] &= ~(1UL<<(ioffset & 7));
4539 if(value & 1)
4541 buf[ioffset>>3] |= (1UL<<(ioffset & 7));
4543 value >>= 1;
4544 } while(--count);
4545 ioffset += count;
4546 } while(--acount);
4550 /* \\\ */
4552 /* /// "nParseArrayString()" */
4553 void nParseArrayString(struct NepClassHid *nch, struct NepHidItem *nhi, STRPTR str)
4555 UWORD acount;
4556 LONG *valptr = nhi->nhi_Buffer;
4557 UWORD mode = 0;
4558 BOOL issigned = FALSE;
4560 if(!*str)
4562 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Empty array value string not allowed.");
4563 return;
4565 acount = nhi->nhi_Count;
4566 if(!acount)
4568 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Target array has no space!");
4571 // mode == 0 -> start
4572 // mode == 1 -> decimal value
4573 // mode == 2 -> hex value
4574 // mode == 3 -> ascii character
4575 // mode == 4 -> string
4576 // mode == 5 -> waiting for termination
4578 while(*str && acount)
4580 UBYTE ch = *str++;
4581 switch(mode)
4583 case 0: // normal
4584 if((ch == '0') && (*str == 'x'))
4586 mode = 2;
4587 *valptr = 0;
4588 str++;
4589 break;
4591 if((ch >= '0') && (ch <= '9'))
4593 mode = 1;
4594 issigned = FALSE;
4595 *valptr = ch - '0';
4596 break;
4598 else if(ch == '-')
4600 mode = 1;
4601 issigned = TRUE;
4602 *valptr = 0;
4604 else if(ch == '\'')
4606 mode = 3;
4607 break;
4609 else if(ch == '"')
4611 mode = 4;
4612 break;
4614 else if(ch == ' ')
4616 break;
4618 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Syntax error in S0!");
4619 return;
4621 case 1: // decimal value
4622 if((ch >= '0') && (ch <= '9'))
4624 *valptr *= 10;
4625 if(issigned)
4627 *valptr -= ch - '0';
4628 } else {
4629 *valptr += ch - '0';
4631 break;
4633 else if(ch == ' ')
4635 mode = 5;
4636 break;
4638 else if(ch == ',')
4640 mode = 0;
4641 valptr++;
4642 acount--;
4643 break;
4645 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Syntax error in S1!");
4646 return;
4648 case 2: // hex value
4649 if((ch >= '0') && (ch <= '9'))
4651 *valptr <<= 4;
4652 *valptr += ch - '0';
4653 break;
4655 else if((ch >= 'a') && (ch <= 'f'))
4657 *valptr <<= 4;
4658 *valptr += ch - 'a' + 10;
4659 break;
4661 else if((ch >= 'A') && (ch <= 'F'))
4663 *valptr <<= 4;
4664 *valptr += ch - 'A' + 10;
4665 break;
4667 else if(ch == ',')
4669 mode = 0;
4670 valptr++;
4671 acount--;
4672 break;
4674 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Syntax error in S2!");
4675 return;
4677 case 3: // ascii character
4678 if(*str == '\'')
4680 *valptr = ch;
4681 str++;
4682 mode = 5;
4683 break;
4685 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Syntax error in S3!");
4686 return;
4688 case 4: // string
4689 if(ch == '"')
4691 mode = 5;
4692 break;
4694 *valptr++ = ch;
4695 acount--;
4696 break;
4698 case 5: // waiting for termination
4699 if(ch == ' ')
4701 break;
4703 if(ch == ',')
4705 valptr++;
4706 acount--;
4707 mode = 0;
4708 break;
4710 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Syntax error in S5!");
4711 return;
4714 if(!(*str))
4716 if(mode == 3)
4718 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Syntax error in S3!");
4719 return;
4721 if(mode == 4)
4723 if(*str == '"')
4725 return;
4729 if(acount == 0)
4731 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Excessive elements ignored!");
4734 /* \\\ */
4736 /* /// "nProcessItem()" */
4737 BOOL nProcessItem(struct NepClassHid *nch, struct NepHidItem *nhi, UBYTE *buf)
4739 BOOL res = FALSE;
4740 LONG value;
4741 LONG *valptr;
4742 ULONG ioffset = nhi->nhi_Offset;
4743 ULONG isize = nhi->nhi_Size;
4744 UBYTE *bobuf = &buf[ioffset>>3];
4745 UWORD count;
4746 UWORD acount;
4747 ULONG usage;
4748 BOOL found;
4749 BOOL bytealigned = ((ioffset & 7) == 0);
4750 struct NepHidAction *nha;
4752 if(nhi->nhi_Flags & RPF_MAIN_VARIABLE)
4754 //KPRINTF(1, ("Processing var %08lx (%ld@%ld)...\n", nhi, isize, ioffset));
4755 if(bytealigned && (isize == 8))
4757 if(nhi->nhi_IsSigned)
4759 value = *((BYTE *) bobuf);
4760 } else {
4761 value = *bobuf;
4764 else if(isize == 1)
4766 value = (buf[ioffset>>3]>>(ioffset & 7)) & 1;
4768 else if(bytealigned && (isize == 16))
4770 if(nhi->nhi_IsSigned)
4772 value = (*bobuf)|((((BYTE *) bobuf)[1])<<8);
4773 } else {
4774 value = (*bobuf)|(bobuf[1]<<8);
4777 else if(bytealigned && (isize == 32))
4779 value = bobuf[0]|(bobuf[1]<<8)|(bobuf[2]<<16)|(bobuf[3]<<24);
4780 } else {
4781 /* I know this routine is dead slow, but hopefully, this is only a very uncommon case */
4782 count = isize;
4783 value = 0;
4784 ioffset += count;
4785 if(nhi->nhi_IsSigned)
4787 count--;
4788 ioffset--;
4789 if((buf[ioffset>>3]>>(ioffset & 7)) & 1)
4791 value = -1;
4796 ioffset--;
4797 value <<= 1;
4798 value |= (buf[ioffset>>3]>>(ioffset & 7)) & 1;
4799 } while(--count);
4801 if((value >= nhi->nhi_LogicalMin) && (value <= nhi->nhi_LogicalMax))
4803 ULONG currmicros = 0;
4804 ULONG currsecs = 0;
4805 if(nhi->nhi_OldValue != value)
4807 if((nhi->nhi_Usage > 0x070000) && (nhi->nhi_Usage < 0x0700E8))
4809 nch->nch_LastUSBKey = nhi->nhi_Usage;
4811 nch->nch_LastItem = nhi;
4812 nch->nch_LastItemAList = &nhi->nhi_ActionList;
4815 if(nch->nch_HIntBase)
4817 CurrentTime(&currsecs, &currmicros);
4818 if(!DoubleClick(nhi->nhi_LastSeconds, nhi->nhi_LastMicros, currsecs, currmicros))
4820 nhi->nhi_ClickCount = 0;
4822 if(nhi->nhi_OldValue < value)
4824 if(nhi->nhi_LastSeconds || nhi->nhi_LastMicros)
4826 if(DoubleClick(nhi->nhi_LastSeconds, nhi->nhi_LastMicros, currsecs, currmicros))
4828 nhi->nhi_ClickCount++;
4829 } else {
4830 nhi->nhi_ClickCount = 1;
4832 } else {
4833 nhi->nhi_ClickCount = 1;
4835 nhi->nhi_HoldSeconds = nhi->nhi_LastSeconds = currsecs;
4836 nhi->nhi_HoldMicros = nhi->nhi_LastMicros = currmicros;
4838 } else {
4839 /* no intuition library */
4840 nhi->nhi_ClickCount = 0;
4841 if(nhi->nhi_OldValue < value)
4843 nhi->nhi_ClickCount = 1;
4846 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
4847 while(nha->nha_Node.ln_Succ)
4849 if((nhi->nhi_OldValue != value) || ((nha->nha_Type & HUA_TRIGMASK) == HUA_ALWAYS))
4851 nDoAction(nch, nha, nhi, nhi->nhi_Usage, value, (nhi->nhi_OldValue < value) || ((nha->nha_Type & HUA_TRIGMASK) == HUA_ALWAYS));
4853 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
4855 if(nhi->nhi_OldValue > value)
4857 nhi->nhi_HoldSeconds = 0;
4858 nhi->nhi_HoldMicros = 0;
4860 if((nhi->nhi_OldValue != value) && nch->nch_ReportValues &&
4861 nch->nch_GUICurrentItem && (nch->nch_GUICurrentItem->nhgi_Item == nhi))
4863 nch->nch_ItemChanged = TRUE;
4865 nhi->nhi_OldValue = value;
4866 res = TRUE;
4867 } else {
4868 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
4869 while(nha->nha_Node.ln_Succ)
4871 if((nha->nha_Type & HUA_TRIGMASK) == HUA_NAN)
4873 nDoAction(nch, nha, nhi, nhi->nhi_Usage, nhi->nhi_OldValue, 0);
4875 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
4878 } else {
4879 nhi->nhi_HoldSeconds = nhi->nhi_LastSeconds = 0;
4880 nhi->nhi_HoldMicros = nhi->nhi_LastMicros = 0;
4881 acount = nhi->nhi_Count;
4882 KPRINTF(1, ("Processing arr %08lx (%ld@%ld) * %ld...\n", nhi, isize, ioffset, acount));
4883 /* first generate the values */
4884 valptr = nhi->nhi_Buffer;
4885 if(bytealigned && (isize == 8))
4887 count = ioffset>>3;
4888 if(nhi->nhi_IsSigned)
4892 *valptr++ = ((BYTE *) buf)[count++];
4893 } while(--acount);
4894 } else {
4897 *valptr++ = buf[count++];
4898 } while(--acount);
4901 else if(isize == 1)
4905 *valptr++ = (buf[ioffset>>3]>>(ioffset & 7)) & 1;
4906 ioffset++;
4907 } while(--acount);
4908 } else {
4909 /* I know this routine is dead slow, but hopefully, this is only a very uncommon case */
4912 count = isize;
4913 value = 0;
4914 ioffset += count;
4915 if(nhi->nhi_IsSigned)
4917 ioffset--;
4918 count--;
4919 if((buf[ioffset>>3]>>(ioffset & 7)) & 1)
4921 value = -1;
4926 ioffset--;
4927 value <<= 1;
4928 value |= (buf[ioffset>>3]>>(ioffset & 7)) & 1;
4929 } while(--count);
4930 ioffset += isize;
4931 *valptr++ = value;
4932 } while(--acount);
4935 /* Look for up events first */
4936 acount = 0;
4939 value = nhi->nhi_OldBuffer[acount];
4940 if((value >= nhi->nhi_LogicalMin) && (value <= nhi->nhi_LogicalMax))
4942 valptr = nhi->nhi_Buffer;
4943 count = nhi->nhi_Count;
4944 found = FALSE;
4947 if(*valptr++ == value)
4949 found = TRUE;
4950 break;
4952 } while(--count);
4953 /* Not found in the new array, so generate up event */
4954 if(!found)
4956 KPRINTF(1, ("Up event %ld\n", acount));
4957 usage = nhi->nhi_UsageMap[value - nhi->nhi_LogicalMin];
4958 if(value || nhi->nhi_LogicalMin)
4960 nch->nch_LastItem = nhi;
4961 nch->nch_LastItemAList = &nhi->nhi_ActionMap[value - nhi->nhi_LogicalMin];
4963 nha = (struct NepHidAction *) nhi->nhi_ActionMap[value - nhi->nhi_LogicalMin].lh_Head;
4964 if(!nha->nha_Node.ln_Succ) /* Use default, no override defined */
4966 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
4968 nhi->nhi_OldValue = nhi->nhi_LogicalMin - 1;
4969 while(nha->nha_Node.ln_Succ)
4971 nDoAction(nch, nha, nhi, usage, value, FALSE);
4972 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
4974 res = TRUE;
4977 } while(++acount < nhi->nhi_Count);
4979 /* Look for down events */
4980 acount = 0;
4983 value = nhi->nhi_Buffer[acount];
4984 //KPRINTF(1, ("[%ld] = %ld\n", acount, value));
4985 if((value >= nhi->nhi_LogicalMin) && (value <= nhi->nhi_LogicalMax))
4987 valptr = nhi->nhi_OldBuffer;
4988 count = nhi->nhi_Count;
4989 found = FALSE;
4992 if(*valptr++ == value)
4994 found = TRUE;
4995 break;
4997 } while(--count);
4998 /* Not found in the old array, so generate down event */
4999 if(!found)
5001 KPRINTF(1, ("Down event %ld\n", acount));
5002 usage = nhi->nhi_UsageMap[value - nhi->nhi_LogicalMin];
5003 if(value || nhi->nhi_LogicalMin)
5005 if((usage > 0x070000) && (usage < 0x0700E8))
5007 nch->nch_LastUSBKey = usage;
5009 nch->nch_LastItem = nhi;
5010 nch->nch_LastItemAList = &nhi->nhi_ActionMap[value - nhi->nhi_LogicalMin];
5013 nha = (struct NepHidAction *) nhi->nhi_ActionMap[value - nhi->nhi_LogicalMin].lh_Head;
5014 if(!nha->nha_Node.ln_Succ) /* Use default, no override defined */
5016 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
5018 nhi->nhi_OldValue = nhi->nhi_LogicalMin - 1;
5019 while(nha->nha_Node.ln_Succ)
5021 nDoAction(nch, nha, nhi, usage, value, TRUE);
5022 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
5024 res = TRUE;
5027 } while(++acount < nhi->nhi_Count);
5028 /* Copy new array */
5029 CopyMemQuick(nhi->nhi_Buffer, nhi->nhi_OldBuffer, sizeof(LONG) * nhi->nhi_Count);
5031 return(res);
5033 /* \\\ */
5035 static ULONG LLHatswitchEncoding[8] = { JPF_JOY_UP, JPF_JOY_UP|JPF_JOY_RIGHT, JPF_JOY_RIGHT, JPF_JOY_RIGHT|JPF_JOY_DOWN,
5036 JPF_JOY_DOWN, JPF_JOY_DOWN|JPF_JOY_LEFT, JPF_JOY_LEFT, JPF_JOY_LEFT|JPF_JOY_UP };
5038 /* /// "nDoAction()" */
5039 BOOL nDoAction(struct NepClassHid *nch, struct NepHidAction *nha, struct NepHidItem *nhi, ULONG uid, LONG value, BOOL downevent)
5041 UWORD atype = nha->nha_Type & HUA_ATYPEMASK;
5042 BOOL res = FALSE;
5043 ULONG qualmask;
5044 LONG clipmin, clipmax;
5045 LONG origvalue = value;
5047 if(nch->nch_DisableActions)
5049 return(FALSE);
5052 // bail out early as nothing below will affect this
5053 if(!(((nha->nha_Type & HUA_DOWNEVENT) && downevent) ||
5054 ((nha->nha_Type & HUA_UPEVENT) && !downevent) ||
5055 ((nha->nha_Type & HUA_TRIGMASK) == HUA_ALWAYS) ||
5056 ((nha->nha_Type & HUA_TRIGMASK) == HUA_NAN)))
5058 return(FALSE);
5061 if(nha->nha_AbsToRel)
5063 value = value - nhi->nhi_OldValue;
5064 nhi->nhi_RealMin = nhi->nhi_LogicalMin - nhi->nhi_LogicalMax;
5065 nhi->nhi_RealMax = nhi->nhi_LogicalMax - nhi->nhi_LogicalMin;
5066 } else {
5067 nhi->nhi_RealMin = nhi->nhi_LogicalMin;
5068 nhi->nhi_RealMax = nhi->nhi_LogicalMax;
5071 if(nha->nha_ClipEnable)
5073 if(nha->nha_ClipMin == nha->nha_ClipMax)
5075 /* shrink to a point */
5076 value = ((nha->nha_ClipMin * (nhi->nhi_RealMax - nhi->nhi_RealMin)) / 100) + nhi->nhi_RealMin;
5077 } else {
5078 if(nha->nha_ClipMin < nha->nha_ClipMax)
5080 /* normal clipping */
5081 clipmin = ((nha->nha_ClipMin * (nhi->nhi_RealMax - nhi->nhi_RealMin)) / 100) + nhi->nhi_RealMin;
5082 clipmax = ((nha->nha_ClipMax * (nhi->nhi_RealMax - nhi->nhi_RealMin)) / 100) + nhi->nhi_RealMin;
5083 } else {
5084 /* inverse clipping */
5085 value = nhi->nhi_RealMax - value;
5086 clipmin = ((nha->nha_ClipMax * (nhi->nhi_RealMax - nhi->nhi_RealMin)) / 100) + nhi->nhi_RealMin;
5087 clipmax = ((nha->nha_ClipMin * (nhi->nhi_RealMax - nhi->nhi_RealMin)) / 100) + nhi->nhi_RealMin;
5089 if(value < clipmin)
5091 value = clipmin;
5092 } else {
5093 if(value > clipmax)
5095 value = clipmax;
5098 if(nha->nha_ClipStretch && (clipmax - clipmin))
5100 value = (((value - clipmin) * (nhi->nhi_RealMax - nhi->nhi_RealMin)) /
5101 (clipmax - clipmin)) + nhi->nhi_RealMin;
5106 if(nha->nha_ScaleEnable && (nha->nha_ScaleMax != nha->nha_ScaleMin))
5108 value = (((value - nhi->nhi_RealMin) * (nha->nha_ScaleMax - nha->nha_ScaleMin)) /
5109 (nhi->nhi_RealMax - nhi->nhi_RealMin)) + nha->nha_ScaleMin;
5110 nhi->nhi_RealMin = nha->nha_ScaleMin;
5111 nhi->nhi_RealMax = nha->nha_ScaleMax;
5114 if(nha->nha_CCEnable)
5116 LONG var1 = 0;
5117 LONG var2 = 0;
5118 BOOL cond = FALSE;
5120 switch(nha->nha_CCVar1)
5122 case HUAT_EITEMVALUE:
5123 var1 = value;
5124 break;
5126 case HUAT_OITEMVALUE:
5127 var1 = origvalue;
5128 break;
5130 case HUAT_CONST:
5131 var1 = nha->nha_CCConst1;
5132 break;
5134 case HUAT_CLICKCOUNT:
5135 var1 = nhi->nhi_ClickCount;
5136 break;
5138 case HUAT_CLICKTIME:
5140 ULONG currmicros;
5141 ULONG currsecs;
5143 if(nhi->nhi_HoldSeconds || nhi->nhi_HoldMicros)
5145 CurrentTime(&currsecs, &currmicros);
5146 var1 = (currsecs - nhi->nhi_HoldSeconds) * 1000;
5147 if(nhi->nhi_HoldMicros <= currmicros)
5149 var1 += (currmicros - nhi->nhi_HoldMicros) / 1000;
5150 } else {
5151 var1 -= (nhi->nhi_HoldMicros - currmicros) / 1000;
5153 } else {
5154 var1 = 0;
5156 break;
5159 case HUAT_QUALIFIERS:
5160 var1 = nch->nch_KeyQualifiers;
5161 break;
5163 case HUAT_ALLQUAL:
5164 var1 = nch->nch_KeyQualifiers|PeekQualifier();
5165 break;
5167 case HUAT_RANDOMBIT:
5168 var1 = _rand(nch->nch_ClsBase) & 1;
5169 break;
5171 case HUAT_RANDOMVAL:
5172 var1 = _rand(nch->nch_ClsBase);
5173 break;
5175 case HUAT_TIMER:
5177 ULONG currmicros;
5178 ULONG currsecs;
5180 CurrentTime(&currsecs, &currmicros);
5181 var1 = (currsecs * 1000) + (currmicros / 1000);
5182 break;
5185 case HUAT_LOCALVAR1:
5186 case HUAT_LOCALVAR2:
5187 case HUAT_LOCALVAR3:
5188 case HUAT_LOCALVAR4:
5189 case HUAT_LOCALVAR5:
5190 case HUAT_LOCALVAR6:
5191 case HUAT_LOCALVAR7:
5192 case HUAT_LOCALVAR8:
5193 var1 = nch->nch_LocalVars[nha->nha_CCVar1 - HUAT_LOCALVAR1];
5194 break;
5196 case HUAT_GLOBVARA:
5197 case HUAT_GLOBVARB:
5198 case HUAT_GLOBVARC:
5199 case HUAT_GLOBVARD:
5200 case HUAT_GLOBVARE:
5201 case HUAT_GLOBVARF:
5202 case HUAT_GLOBVARG:
5203 case HUAT_GLOBVARH:
5204 var1 = nch->nch_ClsBase->nh_GlobalVars[nha->nha_CCVar1 - HUAT_GLOBVARA];
5205 break;
5207 switch(nha->nha_CCVar2)
5209 case HUAT_EITEMVALUE:
5210 var2 = value;
5211 break;
5213 case HUAT_OITEMVALUE:
5214 var2 = origvalue;
5215 break;
5217 case HUAT_CONST:
5218 var2 = nha->nha_CCConst2;
5219 break;
5221 case HUAT_CLICKCOUNT:
5222 var2 = nhi->nhi_ClickCount;
5223 break;
5225 case HUAT_CLICKTIME:
5227 ULONG currmicros;
5228 ULONG currsecs;
5230 if(nhi->nhi_HoldSeconds || nhi->nhi_HoldMicros)
5232 CurrentTime(&currsecs, &currmicros);
5233 var2 = (currsecs - nhi->nhi_HoldSeconds) * 1000;
5234 if(nhi->nhi_HoldMicros <= currmicros)
5236 var2 += (currmicros - nhi->nhi_HoldMicros) / 1000;
5237 } else {
5238 var2 -= (nhi->nhi_HoldMicros - currmicros) / 1000;
5240 } else {
5241 var2 = 0;
5243 break;
5246 case HUAT_QUALIFIERS:
5247 var2 = nch->nch_KeyQualifiers;
5248 break;
5250 case HUAT_ALLQUAL:
5251 var2 = nch->nch_KeyQualifiers|PeekQualifier();
5252 break;
5254 case HUAT_RANDOMBIT:
5255 var2 = _rand(nch->nch_ClsBase) & 1;
5256 break;
5258 case HUAT_RANDOMVAL:
5259 var2 = _rand(nch->nch_ClsBase);
5260 break;
5262 case HUAT_TIMER:
5264 ULONG currmicros;
5265 ULONG currsecs;
5267 CurrentTime(&currsecs, &currmicros);
5268 var2 = (currsecs * 1000) + (currmicros / 1000);
5269 break;
5272 case HUAT_LOCALVAR1:
5273 case HUAT_LOCALVAR2:
5274 case HUAT_LOCALVAR3:
5275 case HUAT_LOCALVAR4:
5276 case HUAT_LOCALVAR5:
5277 case HUAT_LOCALVAR6:
5278 case HUAT_LOCALVAR7:
5279 case HUAT_LOCALVAR8:
5280 var2 = nch->nch_LocalVars[nha->nha_CCVar2 - HUAT_LOCALVAR1];
5281 break;
5283 case HUAT_GLOBVARA:
5284 case HUAT_GLOBVARB:
5285 case HUAT_GLOBVARC:
5286 case HUAT_GLOBVARD:
5287 case HUAT_GLOBVARE:
5288 case HUAT_GLOBVARF:
5289 case HUAT_GLOBVARG:
5290 case HUAT_GLOBVARH:
5291 var2 = nch->nch_ClsBase->nh_GlobalVars[nha->nha_CCVar2 - HUAT_GLOBVARA];
5292 break;
5294 switch(nha->nha_CCCond)
5296 case HUAT_EQ:
5297 cond = (var1 == var2);
5298 break;
5300 case HUAT_NE:
5301 cond = (var1 != var2);
5302 break;
5304 case HUAT_LT:
5305 cond = (var1 < var2);
5306 break;
5308 case HUAT_LE:
5309 cond = (var1 <= var2);
5310 break;
5312 case HUAT_GT:
5313 cond = (var1 > var2);
5314 break;
5316 case HUAT_GE:
5317 cond = (var1 >= var2);
5318 break;
5320 case HUAT_AND:
5321 cond = (var1 && var2);
5322 break;
5324 case HUAT_NAND:
5325 cond = !(var1 && var2);
5326 break;
5328 case HUAT_OR:
5329 cond = (var1 || var2);
5330 break;
5332 case HUAT_XOR:
5333 cond = (var1 && (!var2)) || ((!var1) && var2);
5334 break;
5336 case HUAT_ANDNOT:
5337 cond = (var1 && (!var2));
5338 break;
5340 case HUAT_BWAND:
5341 cond = (var1 & var2) ? TRUE : FALSE;
5342 break;
5344 case HUAT_BWNAND:
5345 cond = (var1 & var2) ? FALSE : TRUE;
5346 break;
5348 case HUAT_BWOR:
5349 cond = (var1 | var2) ? TRUE : FALSE;
5350 break;
5352 case HUAT_BWXOR:
5353 cond = (var1 ^ var2) ? TRUE : FALSE;
5354 break;
5356 case HUAT_BWANDNOT:
5357 cond = (var1 & (~var2)) ? TRUE : FALSE;
5358 break;
5361 if(!cond)
5363 return(FALSE);
5367 if(nha->nha_ValEnable)
5369 switch(nha->nha_ValVar)
5371 case HUAT_EITEMVALUE:
5372 //value = value;
5373 break;
5375 case HUAT_OITEMVALUE:
5376 value = origvalue;
5377 break;
5379 case HUAT_CONST:
5380 value = nha->nha_ValConst;
5381 break;
5383 case HUAT_CLICKCOUNT:
5384 value = nhi->nhi_ClickCount;
5385 break;
5387 case HUAT_CLICKTIME:
5389 ULONG currmicros;
5390 ULONG currsecs;
5392 if(nhi->nhi_HoldSeconds || nhi->nhi_HoldMicros)
5394 CurrentTime(&currsecs, &currmicros);
5395 value = (currsecs - nhi->nhi_HoldSeconds) * 1000;
5396 if(nhi->nhi_HoldMicros <= currmicros)
5398 value += (currmicros - nhi->nhi_HoldMicros) / 1000;
5399 } else {
5400 value -= (nhi->nhi_HoldMicros - currmicros) / 1000;
5402 } else {
5403 value = 0;
5405 break;
5408 case HUAT_QUALIFIERS:
5409 value = nch->nch_KeyQualifiers;
5410 break;
5412 case HUAT_ALLQUAL:
5413 value = nch->nch_KeyQualifiers|PeekQualifier();
5414 break;
5416 case HUAT_RANDOMBIT:
5417 value = _rand(nch->nch_ClsBase) & 1;
5418 break;
5420 case HUAT_RANDOMVAL:
5421 value = _rand(nch->nch_ClsBase);
5422 break;
5424 case HUAT_TIMER:
5426 ULONG currmicros;
5427 ULONG currsecs;
5429 CurrentTime(&currsecs, &currmicros);
5430 value = (currsecs * 1000) + (currmicros / 1000);
5431 break;
5434 case HUAT_LOCALVAR1:
5435 case HUAT_LOCALVAR2:
5436 case HUAT_LOCALVAR3:
5437 case HUAT_LOCALVAR4:
5438 case HUAT_LOCALVAR5:
5439 case HUAT_LOCALVAR6:
5440 case HUAT_LOCALVAR7:
5441 case HUAT_LOCALVAR8:
5442 value = nch->nch_LocalVars[nha->nha_ValVar - HUAT_LOCALVAR1];
5443 break;
5445 case HUAT_GLOBVARA:
5446 case HUAT_GLOBVARB:
5447 case HUAT_GLOBVARC:
5448 case HUAT_GLOBVARD:
5449 case HUAT_GLOBVARE:
5450 case HUAT_GLOBVARF:
5451 case HUAT_GLOBVARG:
5452 case HUAT_GLOBVARH:
5453 value = nch->nch_ClsBase->nh_GlobalVars[nha->nha_ValVar - HUAT_GLOBVARA];
5454 break;
5457 //KPRINTF(1, ("Call for action(%04lx) %lx = %ld %s\n", atype, uid, value, downevent ? "down" : "up"));
5458 switch(atype)
5460 case HUA_SHELL:
5461 case HUA_KEYSTRING:
5462 case HUA_VANILLA:
5463 case HUA_SOUND:
5465 struct ActionMsg *am;
5466 if(!nch->nch_ClsBase->nh_DTaskMsgPort)
5468 nInstallLastActionHero(nch);
5470 if(nch->nch_ClsBase->nh_DTaskMsgPort)
5472 if((am = AllocVec(sizeof(struct ActionMsg), MEMF_PUBLIC)))
5474 am->am_Msg.mn_Length = sizeof(struct ActionMsg);
5475 am->am_Msg.mn_ReplyPort = NULL;
5476 am->am_NCH = nch;
5477 am->am_Action = nha;
5478 PutMsg(nch->nch_ClsBase->nh_DTaskMsgPort, &am->am_Msg);
5481 break;
5484 case HUA_RAWKEY:
5485 nSendRawKey(nch, nha->nha_RawKey);
5486 break;
5488 case HUA_KEYMAP:
5490 UWORD iecode;
5491 if((uid > 0x70000) && (uid < 0x700e8))
5493 iecode = nch->nch_KeymapCfg.kmc_Keymap[uid & 0xff];
5494 KPRINTF(1,("Key %ld %s\n", iecode, downevent ? "DOWN" : "UP"));
5495 nch->nch_FakeEvent.ie_Class = IECLASS_RAWKEY;
5496 nch->nch_FakeEvent.ie_SubClass = 0;
5497 nSendRawKey(nch, downevent ? iecode : iecode|IECODE_UP_PREFIX);
5499 break;
5502 case HUA_MOUSEPOS:
5503 switch(nha->nha_MouseAxis)
5505 case HUAT_DELTAX:
5506 nch->nch_NewMouseRel = TRUE;
5507 nch->nch_MouseDeltaX += value;
5508 break;
5510 case HUAT_DELTAY:
5511 nch->nch_NewMouseRel = TRUE;
5512 nch->nch_MouseDeltaY += value;
5513 break;
5515 case HUAT_ABSX:
5516 if(nch->nch_MouseRangeY)
5518 nch->nch_NewMouseAbs = TRUE;
5520 nch->nch_MouseAbsX = value - nhi->nhi_RealMin;
5521 nch->nch_MouseRangeX = (nhi->nhi_RealMax - nhi->nhi_RealMin) + 1;
5522 break;
5524 case HUAT_ABSY:
5525 if(nch->nch_MouseRangeX)
5527 nch->nch_NewMouseAbs = TRUE;
5529 nch->nch_MouseAbsY = value - nhi->nhi_RealMin;
5530 nch->nch_MouseRangeY = (nhi->nhi_RealMax - nhi->nhi_RealMin) + 1;
5531 break;
5533 break;
5535 case HUA_QUALIFIER:
5536 qualmask = 1<<nha->nha_Qualifier;
5537 switch(nha->nha_QualMode)
5539 case HUAT_SET:
5540 nch->nch_KeyQualifiers |= qualmask;
5541 break;
5543 case HUAT_CLEAR:
5544 nch->nch_KeyQualifiers &= ~qualmask;
5545 break;
5547 case HUAT_TOGGLE:
5548 nch->nch_KeyQualifiers ^= qualmask;
5549 break;
5551 case HUAT_ASSIGN:
5552 nch->nch_KeyQualifiers &= ~qualmask;
5553 if(downevent)
5555 nch->nch_KeyQualifiers |= qualmask;
5557 break;
5559 break;
5561 case HUA_BUTTONS:
5563 UWORD iecode = IECODE_NOBUTTON;
5564 ULONG iequal = 0;
5565 BOOL newmouse = FALSE;
5567 switch(nha->nha_ButtonNo)
5569 case 1:
5570 iequal = IEQUALIFIER_LEFTBUTTON;
5571 iecode = IECODE_LBUTTON;
5572 break;
5574 case 2:
5575 iequal = IEQUALIFIER_RBUTTON;
5576 iecode = IECODE_RBUTTON;
5577 break;
5579 case 3:
5580 iequal = IEQUALIFIER_MIDBUTTON;
5581 iecode = IECODE_MBUTTON;
5582 break;
5584 case 4:
5585 iecode = RAWKEY_NM_BUTTON_FOURTH;
5586 newmouse = TRUE;
5587 break;
5590 switch(nha->nha_ButtonMode)
5592 case HUAT_SET:
5593 if((!newmouse) && (nch->nch_KeyQualifiers & iequal))
5595 iequal = 0;
5596 iecode = IECODE_NOBUTTON;
5597 } else {
5598 nch->nch_KeyQualifiers |= iequal;
5599 nch->nch_MouseButtons |= 1<<(nha->nha_ButtonNo-1);
5601 break;
5603 case HUAT_CLEAR:
5604 if(newmouse || (nch->nch_KeyQualifiers & iequal))
5606 nch->nch_KeyQualifiers &= ~iequal;
5607 nch->nch_MouseButtons &= ~(1<<(nha->nha_ButtonNo-1));
5608 iequal = 0;
5609 iecode |= IECODE_UP_PREFIX;
5610 } else {
5611 iequal = 0;
5612 iecode = IECODE_NOBUTTON;
5614 break;
5616 case HUAT_TOGGLE:
5617 if(newmouse)
5619 if(nch->nch_MouseButtons & (1<<(nha->nha_ButtonNo-1)))
5621 nch->nch_MouseButtons &= ~(1<<(nha->nha_ButtonNo-1));
5622 iecode |= IECODE_UP_PREFIX;
5623 } else {
5624 nch->nch_MouseButtons |= 1<<(nha->nha_ButtonNo-1);
5626 } else {
5627 if(nch->nch_KeyQualifiers & iequal)
5629 nch->nch_KeyQualifiers &= ~iequal;
5630 nch->nch_MouseButtons &= ~(1<<(nha->nha_ButtonNo-1));
5631 iequal = 0;
5632 iecode |= IECODE_UP_PREFIX;
5633 } else {
5634 nch->nch_KeyQualifiers |= iequal;
5635 nch->nch_MouseButtons |= 1<<(nha->nha_ButtonNo-1);
5638 break;
5640 case HUAT_ASSIGN:
5641 if(value)
5643 if((!newmouse) && (nch->nch_KeyQualifiers & iequal))
5645 iequal = 0;
5646 iecode = IECODE_NOBUTTON;
5647 } else {
5648 nch->nch_KeyQualifiers |= iequal;
5649 nch->nch_MouseButtons |= 1<<(nha->nha_ButtonNo-1);
5651 } else {
5652 if(newmouse || (nch->nch_KeyQualifiers & iequal))
5654 nch->nch_KeyQualifiers &= ~iequal;
5655 nch->nch_MouseButtons &= ~(1<<(nha->nha_ButtonNo-1));
5656 iequal = 0;
5657 iecode |= IECODE_UP_PREFIX;
5658 } else {
5659 iequal = 0;
5660 iecode = IECODE_NOBUTTON;
5663 break;
5665 default:
5666 iecode = IECODE_NOBUTTON;
5667 break;
5669 if(iecode != IECODE_NOBUTTON)
5671 if(newmouse)
5673 nSendRawKey(nch, iecode);
5675 nch->nch_FakeEvent.ie_Class = IECLASS_NEWMOUSE;
5676 nch->nch_FakeEvent.ie_SubClass = 0;
5677 nch->nch_FakeEvent.ie_Code = iecode;
5678 nch->nch_FakeEvent.ie_NextEvent = NULL;
5679 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers;
5680 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
5681 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
5682 nch->nch_InpIOReq->io_Command = IND_WRITEEVENT;
5683 DoIO((struct IORequest *) nch->nch_InpIOReq);
5684 } else {
5685 nch->nch_FakeEvent.ie_X = nch->nch_MouseDeltaX;
5686 nch->nch_FakeEvent.ie_Y = nch->nch_MouseDeltaY;
5687 nch->nch_FakeEvent.ie_Class = IECLASS_RAWMOUSE;
5688 nch->nch_FakeEvent.ie_SubClass = 0;
5689 nch->nch_FakeEvent.ie_Code = iecode;
5690 nch->nch_FakeEvent.ie_NextEvent = NULL;
5691 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers|IEQUALIFIER_RELATIVEMOUSE;
5692 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
5693 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
5694 nch->nch_InpIOReq->io_Command = nch->nch_OS4Hack ? IND_ADDEVENT : IND_WRITEEVENT;
5695 DoIO((struct IORequest *) nch->nch_InpIOReq);
5696 nch->nch_NewMouseRel = FALSE;
5697 nch->nch_MouseDeltaX = 0;
5698 nch->nch_MouseDeltaY = 0;
5701 break;
5704 case HUA_TABLET:
5706 KPRINTF(1, ("Tablet!\n"));
5707 switch(nha->nha_TabletAxis)
5709 case HUAT_ABSZ:
5710 nch->nch_MouseAbsZ = value - nhi->nhi_RealMin;
5711 nch->nch_MouseRangeZ = (nhi->nhi_RealMax - nhi->nhi_RealMin) + 1;
5712 break;
5714 case HUAT_PRESSURE:
5715 if(nhi->nhi_RealMax)
5717 nch->nch_TabPressure = ((0x1fffffff / nhi->nhi_RealMax)*value)<<2;
5718 nch->nch_VldPressure = TRUE;
5720 break;
5722 case HUAT_XROT:
5723 if(nhi->nhi_RealMax)
5725 nch->nch_TabRotX = ((0x3fffffff / nhi->nhi_RealMax)*value)<<2;
5726 nch->nch_VldRotX = TRUE;
5728 break;
5730 case HUAT_YROT:
5731 if(nhi->nhi_RealMax)
5733 nch->nch_TabRotY = ((0x3fffffff / nhi->nhi_RealMax)*value)<<2;
5734 nch->nch_VldRotY = TRUE;
5736 break;
5738 case HUAT_ZROT:
5739 if(nhi->nhi_RealMax)
5741 nch->nch_TabRotZ = ((0x3fffffff / nhi->nhi_RealMax)*value)<<2;
5742 nch->nch_VldRotZ = TRUE;
5744 break;
5746 case HUAT_PROX:
5747 nch->nch_TabProx = value;
5748 nch->nch_VldProx = TRUE;
5749 break;
5751 if(nch->nch_MouseRangeX && nch->nch_MouseRangeY)
5753 nch->nch_NewMouseAbs = TRUE;
5755 break;
5758 case HUA_WHEEL:
5760 UWORD wheeldist = 0;
5761 UWORD wheeliecode = IECODE_NOBUTTON;
5762 switch(nha->nha_WheelMode)
5764 case HUAT_DELTAX:
5765 if(value > 0)
5767 wheeliecode = RAWKEY_NM_WHEEL_LEFT;
5768 wheeldist = value;
5770 else if(value < 0)
5772 wheeliecode = RAWKEY_NM_WHEEL_RIGHT;
5773 wheeldist = -value;
5775 break;
5777 case HUAT_DELTAY:
5778 if(value > 0)
5780 wheeliecode = RAWKEY_NM_WHEEL_UP;
5781 wheeldist = value;
5783 else if(value < 0)
5785 wheeliecode = RAWKEY_NM_WHEEL_DOWN;
5786 wheeldist = -value;
5788 break;
5790 case HUAT_LEFT:
5791 wheeliecode = RAWKEY_NM_WHEEL_LEFT;
5792 wheeldist = nha->nha_WheelDist;
5793 break;
5795 case HUAT_RIGHT:
5796 wheeliecode = RAWKEY_NM_WHEEL_RIGHT;
5797 wheeldist = nha->nha_WheelDist;
5798 break;
5800 case HUAT_UP:
5801 wheeliecode = RAWKEY_NM_WHEEL_UP;
5802 wheeldist = nha->nha_WheelDist;
5803 break;
5805 case HUAT_DOWN:
5806 wheeliecode = RAWKEY_NM_WHEEL_DOWN;
5807 wheeldist = nha->nha_WheelDist;
5808 break;
5810 if(wheeliecode != IECODE_NOBUTTON)
5812 if(downevent)
5814 while(wheeldist--)
5816 KPRINTF(1, ("Doing wheel %ld\n", wheeliecode));
5817 nSendRawKey(nch, wheeliecode);
5818 #if 0
5819 nch->nch_FakeEvent.ie_Class = IECLASS_NEWMOUSE;
5820 nch->nch_FakeEvent.ie_SubClass = 0;
5821 nch->nch_FakeEvent.ie_Code = wheeliecode;
5822 nch->nch_FakeEvent.ie_NextEvent = NULL;
5823 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers;
5824 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
5825 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
5826 nch->nch_InpIOReq->io_Command = IND_WRITEEVENT;
5827 DoIO((struct IORequest *) nch->nch_InpIOReq);
5828 #endif
5831 nSendRawKey(nch, wheeliecode|IECODE_UP_PREFIX);
5832 #if 0
5833 nch->nch_FakeEvent.ie_Class = IECLASS_NEWMOUSE;
5834 nch->nch_FakeEvent.ie_SubClass = 0;
5835 nch->nch_FakeEvent.ie_Code = wheeliecode|IECODE_UP_PREFIX;
5836 nch->nch_FakeEvent.ie_NextEvent = NULL;
5837 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers;
5838 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
5839 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
5840 nch->nch_InpIOReq->io_Command = IND_WRITEEVENT;
5841 DoIO((struct IORequest *) nch->nch_InpIOReq);
5842 #endif
5845 break;
5848 case HUA_DIGJOY:
5850 ULONG mask = 0;
5851 /* ULONG oldval; */
5852 ULONG *stateptr = &nch->nch_LLPortState[nha->nha_JoypadPort];
5854 switch(nha->nha_JoypadFeat)
5856 case HUAT_LEFT:
5857 mask = JPF_JOY_LEFT;
5858 break;
5860 case HUAT_RIGHT:
5861 mask = JPF_JOY_RIGHT;
5862 break;
5864 case HUAT_UP:
5865 mask = JPF_JOY_UP;
5866 break;
5868 case HUAT_DOWN:
5869 mask = JPF_JOY_DOWN;
5870 break;
5872 case HUAT_RED:
5873 mask = JPF_BUTTON_RED;
5874 break;
5876 case HUAT_BLUE:
5877 mask = JPF_BUTTON_BLUE;
5878 break;
5880 case HUAT_GREEN:
5881 mask = JPF_BUTTON_GREEN;
5882 break;
5884 case HUAT_YELLOW:
5885 mask = JPF_BUTTON_YELLOW;
5886 break;
5888 case HUAT_FORWARD:
5889 mask = JPF_BUTTON_FORWARD;
5890 break;
5892 case HUAT_REVERSE:
5893 mask = JPF_BUTTON_REVERSE;
5894 break;
5896 case HUAT_PLAY:
5897 mask = JPF_BUTTON_PLAY;
5898 break;
5900 case HUAT_HATSWITCH:
5901 mask = JP_DIRECTION_MASK;
5902 stateptr = &nch->nch_LLHatswitch[nha->nha_JoypadPort];
5903 break;
5906 /* oldval = *stateptr; */
5907 switch(nha->nha_JoypadOp)
5909 case HUAT_SET:
5910 *stateptr |= mask;
5911 break;
5913 case HUAT_CLEAR:
5914 *stateptr &= ~mask;
5915 break;
5917 case HUAT_TOGGLE:
5918 *stateptr ^= mask;
5919 break;
5921 case HUAT_ASSIGN:
5922 if(nha->nha_JoypadFeat == HUAT_HATSWITCH)
5924 value -= nhi->nhi_RealMin;
5925 if((value >= 0) && (value < 8))
5927 mask = LLHatswitchEncoding[value];
5928 } else {
5929 mask = 0;
5931 /*oldval = *stateptr;
5932 oldval &= ~JP_DIRECTION_MASK;
5933 oldval |= mask;
5934 *stateptr = oldval;*/
5935 *stateptr = mask;
5936 } else {
5937 if(value)
5939 *stateptr |= mask;
5940 } else {
5941 *stateptr &= ~mask;
5944 break;
5946 break;
5949 case HUA_ANALOGJOY:
5951 ULONG *stateptr = &nch->nch_LLAnalogue[nha->nha_JoypadPort];
5952 if((nhi->nhi_RealMin != 0) || (nhi->nhi_RealMax != 255))
5954 // scale
5955 value -= nhi->nhi_RealMin;
5956 value <<= 8;
5957 value /= (nhi->nhi_RealMax - nhi->nhi_RealMin);
5959 switch(nha->nha_APadFeat)
5961 case HUAT_ABSX:
5962 *stateptr = (*stateptr & ~JP_XAXIS_MASK) | (value & JP_XAXIS_MASK) | JP_TYPE_ANALOGUE;
5963 break;
5965 case HUAT_ABSY:
5966 *stateptr = (*stateptr & ~JP_YAXIS_MASK) | ((value<<8) & JP_YAXIS_MASK) | JP_TYPE_ANALOGUE;
5967 break;
5969 break;
5972 case HUA_OUTPUT:
5974 ULONG pos;
5975 struct NepHidItem *nhi;
5977 nhi = nFindItemID(nch, nha->nha_OutItem, REPORT_MAIN_OUTPUT, &pos);
5978 if(nhi)
5980 if(nhi->nhi_Flags & RPF_MAIN_VARIABLE)
5982 switch(nha->nha_OutOp)
5984 case HUAT_SET:
5985 nhi->nhi_OldValue = TRUE;
5986 break;
5988 case HUAT_CLEAR:
5989 nhi->nhi_OldValue = FALSE;
5990 break;
5992 case HUAT_TOGGLE:
5993 nhi->nhi_OldValue = nhi->nhi_OldValue ? FALSE : TRUE;
5994 break;
5996 case HUAT_ASSIGN:
5997 nhi->nhi_OldValue = value;
5998 break;
6000 } else {
6001 nParseArrayString(nch, nhi, nha->nha_OutArray);
6003 nhi->nhi_Collection->nhc_Report->nhr_OutTouched = TRUE;
6004 nch->nch_OutFeatTouched = TRUE;
6006 break;
6009 case HUA_FEATURE:
6011 ULONG pos;
6012 struct NepHidItem *nhi;
6014 nhi = nFindItemID(nch, nha->nha_FeatItem, REPORT_MAIN_FEATURE, &pos);
6015 if(nhi)
6017 if(nhi->nhi_Flags & RPF_MAIN_VARIABLE)
6019 switch(nha->nha_FeatOp)
6021 case HUAT_SET:
6022 nhi->nhi_OldValue = TRUE;
6023 break;
6025 case HUAT_CLEAR:
6026 nhi->nhi_OldValue = FALSE;
6027 break;
6029 case HUAT_TOGGLE:
6030 nhi->nhi_OldValue = nhi->nhi_OldValue ? FALSE : TRUE;
6031 break;
6033 case HUAT_ASSIGN:
6034 nhi->nhi_OldValue = value;
6035 break;
6037 } else {
6038 nParseArrayString(nch, nhi, nha->nha_OutArray);
6040 nhi->nhi_Collection->nhc_Report->nhr_FeatTouched = TRUE;
6041 nch->nch_OutFeatTouched = TRUE;
6043 break;
6046 case HUA_MISC:
6047 nch->nch_FakeEvent.ie_Class = IECLASS_NULL;
6048 nch->nch_FakeEvent.ie_SubClass = 0;
6049 nch->nch_FakeEvent.ie_Code = IECODE_NOBUTTON;
6050 nch->nch_FakeEvent.ie_NextEvent = NULL;
6051 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers;
6052 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
6053 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
6054 nch->nch_InpIOReq->io_Command = IND_WRITEEVENT;
6055 switch(nha->nha_MiscMode)
6057 case HUAT_DISPLAYBEEP:
6058 case HUAT_WIN2FRONT:
6059 case HUAT_WIN2BACK:
6060 case HUAT_ZIPWINDOW:
6061 case HUAT_SCREENCYCLE:
6062 case HUAT_WB2FRONT:
6063 case HUAT_ACTWINDOW:
6065 struct ActionMsg *am;
6066 if(!nch->nch_ClsBase->nh_DTaskMsgPort)
6068 nInstallLastActionHero(nch);
6070 if(nch->nch_ClsBase->nh_DTaskMsgPort)
6072 if((am = AllocVec(sizeof(struct ActionMsg), MEMF_PUBLIC)))
6074 am->am_Msg.mn_Length = sizeof(struct ActionMsg);
6075 am->am_Msg.mn_ReplyPort = NULL;
6076 am->am_NCH = nch;
6077 am->am_Action = nha;
6078 PutMsg(nch->nch_ClsBase->nh_DTaskMsgPort, &am->am_Msg);
6081 break;
6084 case HUAT_CLOSEWINDOW:
6085 nch->nch_FakeEvent.ie_Class = IECLASS_CLOSEWINDOW;
6086 DoIO((struct IORequest *) nch->nch_InpIOReq);
6087 break;
6089 case HUAT_REBOOT:
6090 nch->nch_CDC->cdc_EnableKBReset = TRUE;
6091 nch->nch_KeyQualifiers |= IEQUALIFIER_CONTROL|IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND;
6092 nCheckReset(nch);
6093 break;
6095 case HUAT_FLUSHEVENTS:
6096 nFlushEvents(nch);
6097 break;
6099 default:
6100 break;
6102 break;
6104 case HUA_VARIABLES:
6106 LONG *tarvarptr = NULL;
6108 switch(nha->nha_TarVar)
6110 case HUAT_LOCALVAR1:
6111 case HUAT_LOCALVAR2:
6112 case HUAT_LOCALVAR3:
6113 case HUAT_LOCALVAR4:
6114 case HUAT_LOCALVAR5:
6115 case HUAT_LOCALVAR6:
6116 case HUAT_LOCALVAR7:
6117 case HUAT_LOCALVAR8:
6118 tarvarptr = &nch->nch_LocalVars[nha->nha_TarVar - HUAT_LOCALVAR1];
6119 break;
6121 case HUAT_GLOBVARA:
6122 case HUAT_GLOBVARB:
6123 case HUAT_GLOBVARC:
6124 case HUAT_GLOBVARD:
6125 case HUAT_GLOBVARE:
6126 case HUAT_GLOBVARF:
6127 case HUAT_GLOBVARG:
6128 case HUAT_GLOBVARH:
6129 tarvarptr = &nch->nch_ClsBase->nh_GlobalVars[nha->nha_TarVar - HUAT_GLOBVARA];
6130 break;
6132 if(!tarvarptr)
6134 return(FALSE);
6136 switch(nha->nha_TarVarOp)
6138 case HUAT_ASSIGN:
6139 *tarvarptr = value;
6140 break;
6142 case HUAT_ADD:
6143 *tarvarptr += value;
6144 break;
6146 case HUAT_SUB:
6147 *tarvarptr -= value;
6148 break;
6150 case HUAT_MULTIPLY:
6151 *tarvarptr *= value;
6152 break;
6154 case HUAT_DIVIDE:
6155 if(value)
6157 *tarvarptr /= value;
6159 break;
6161 case HUAT_MODULO:
6162 if(value)
6164 *tarvarptr = value;
6166 break;
6168 case HUAT_AND:
6169 *tarvarptr = *tarvarptr && value;
6170 break;
6172 case HUAT_NAND:
6173 *tarvarptr = !(*tarvarptr && value);
6174 break;
6176 case HUAT_ANDNOT:
6177 *tarvarptr = *tarvarptr && (!value);
6178 break;
6180 case HUAT_OR:
6181 *tarvarptr = *tarvarptr || value;
6182 break;
6184 case HUAT_XOR:
6185 *tarvarptr = (*tarvarptr ^ value) ? TRUE : FALSE;
6186 break;
6188 case HUAT_BWAND:
6189 *tarvarptr &= value;
6190 break;
6192 case HUAT_BWNAND:
6193 *tarvarptr = ~(*tarvarptr & value);
6194 break;
6196 case HUAT_BWANDNOT:
6197 *tarvarptr &= ~value;
6198 break;
6200 case HUAT_BWOR:
6201 *tarvarptr |= value;
6202 break;
6204 case HUAT_BWXOR:
6205 *tarvarptr ^= value;
6206 break;
6208 case HUAT_ASL:
6209 *tarvarptr <<= value;
6210 break;
6212 case HUAT_ASR:
6213 *tarvarptr >>= value;
6214 break;
6216 return(TRUE);
6219 case HUA_EXTRAWKEY:
6220 #if 0 // FIXME looks like AROS does not support this (yet?)
6221 nch->nch_FakeEvent.ie_Class = IECLASS_EXTRAWKEY;
6222 nch->nch_FakeEvent.ie_SubClass = 0;
6223 nch->nch_FakeEvent.ie_Code = nha->nha_RawKey;
6224 // using ie.dead.ie_prev1DownCode instead of ie_extkey.ie_extkey1
6225 nch->nch_FakeEvent.ie_position.ie_dead.ie_prev1DownCode = 0xe0;
6226 nch->nch_FakeEvent.ie_position.ie_dead.ie_prev1DownQual = nha->nha_RawKey;
6227 nch->nch_FakeEvent.ie_NextEvent = NULL;
6228 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers;
6229 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
6230 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
6231 nch->nch_InpIOReq->io_Command = IND_WRITEEVENT;
6232 DoIO((struct IORequest *) nch->nch_InpIOReq);
6233 #endif
6234 break;
6237 return(res);
6239 /* \\\ */
6241 /* /// "nFlushEvents()" */
6242 void nFlushEvents(struct NepClassHid *nch)
6244 struct PsdPipe *pp;
6245 ULONG buflen;
6246 LONG ioerr;
6248 struct NepHidReport *nhr;
6250 /* output/feature pipes */
6251 if(nch->nch_OutFeatTouched)
6253 nch->nch_OutFeatTouched = FALSE;
6254 pp = nch->nch_EP0Pipe;
6255 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
6256 while(nhr->nhr_Node.ln_Succ)
6258 if(nhr->nhr_OutTouched)
6260 KPRINTF(1, ("Out Report %ld touched...\n", nhr->nhr_ReportID));
6261 buflen = (nhr->nhr_ReportOutSize+7)>>3;
6262 if(nch->nch_UsesReportID)
6264 *nch->nch_EPOutBuf = nhr->nhr_ReportID;
6265 nGenerateOutReport(nch, nhr, nch->nch_EPOutBuf+1);
6266 buflen++;
6267 psdPipeSetup(pp, URTF_OUT|URTF_CLASS|URTF_INTERFACE,
6268 UHR_SET_REPORT, (ULONG) nhr->nhr_ReportID|0x0200, nch->nch_IfNum);
6269 } else {
6270 nGenerateOutReport(nch, nhr, nch->nch_EPOutBuf);
6271 psdPipeSetup(pp, URTF_OUT|URTF_CLASS|URTF_INTERFACE,
6272 UHR_SET_REPORT, 0x0200, nch->nch_IfNum);
6274 KPRINTF(1, ("Len: %ld [%02lx %02lx]", buflen, nch->nch_EPOutBuf[0], nch->nch_EPOutBuf[1]));
6275 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
6276 "HID OUT Report %02lx Debug (%ld bytes):", nhr->nhr_ReportID, buflen);
6277 nDebugMem(nch, nch->nch_EPOutBuf, buflen);*/
6279 if((ioerr = psdDoPipe(pp, nch->nch_EPOutBuf, buflen)))
6281 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
6282 "SET_REPORT(%lx, %ld) failed: %s (%ld)!",
6283 nhr->nhr_ReportID|0x0200, buflen,
6284 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
6286 nhr->nhr_OutTouched = FALSE;
6288 if(nhr->nhr_FeatTouched)
6290 KPRINTF(1, ("Feat Report %ld touched...\n", nhr->nhr_ReportID));
6291 buflen = (nhr->nhr_ReportFeatSize+7)>>3;
6292 if(nch->nch_UsesReportID)
6294 *nch->nch_EPOutBuf = nhr->nhr_ReportID;
6295 nGenerateFeatReport(nch, nhr, nch->nch_EPOutBuf+1);
6296 buflen++;
6297 psdPipeSetup(pp, URTF_OUT|URTF_CLASS|URTF_INTERFACE,
6298 UHR_SET_REPORT, (ULONG) nhr->nhr_ReportID|0x0300, nch->nch_IfNum);
6299 } else {
6300 nGenerateFeatReport(nch, nhr, nch->nch_EPOutBuf);
6301 psdPipeSetup(pp, URTF_OUT|URTF_CLASS|URTF_INTERFACE,
6302 UHR_SET_REPORT, 0x0300, nch->nch_IfNum);
6304 KPRINTF(1, ("Len: %ld [%02lx %02lx]", buflen, nch->nch_EPOutBuf[0], nch->nch_EPOutBuf[1]));
6305 if((ioerr = psdDoPipe(pp, nch->nch_EPOutBuf, buflen)))
6307 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
6308 "SET_REPORT(%lx, %ld) failed: %s (%ld)!",
6309 nhr->nhr_ReportID|0x0300, buflen,
6310 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
6311 }/* else {
6312 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
6313 "SET_REPORT(%lx, %ld)=%02lx%02lx okay!",
6314 nhr->nhr_ReportID|0x0300, buflen,
6315 nch->nch_EPOutBuf[1], nch->nch_EPOutBuf[2]);
6317 nhr->nhr_FeatTouched = FALSE;
6319 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
6322 if(nch->nch_NewMouseRel && (nch->nch_MouseDeltaX || nch->nch_MouseDeltaY))
6324 KPRINTF(1, ("Mouse rel movement...\n"));
6325 nch->nch_FakeEvent.ie_X = nch->nch_MouseDeltaX;
6326 nch->nch_FakeEvent.ie_Y = nch->nch_MouseDeltaY;
6327 nch->nch_FakeEvent.ie_Class = IECLASS_RAWMOUSE;
6328 nch->nch_FakeEvent.ie_SubClass = 0;
6329 nch->nch_FakeEvent.ie_Code = IECODE_NOBUTTON;
6330 nch->nch_FakeEvent.ie_NextEvent = NULL;
6331 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers|IEQUALIFIER_RELATIVEMOUSE;
6332 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
6333 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
6334 nch->nch_InpIOReq->io_Command = nch->nch_OS4Hack ? IND_ADDEVENT : IND_WRITEEVENT;
6335 DoIO((struct IORequest *) nch->nch_InpIOReq);
6336 nch->nch_NewMouseRel = FALSE;
6337 nch->nch_MouseDeltaX = 0;
6338 nch->nch_MouseDeltaY = 0;
6340 if(nch->nch_NewMouseAbs)
6342 ULONG *tagptr = nch->nch_TabTags;
6343 KPRINTF(1, ("Mouse abs movement...\n"));
6344 nch->nch_FakeEvent.ie_EventAddress = &nch->nch_TabletEvent;
6345 nch->nch_TabletEvent.ient_RangeX = nch->nch_MouseRangeX;
6346 nch->nch_TabletEvent.ient_RangeY = nch->nch_MouseRangeY;
6347 nch->nch_TabletEvent.ient_TabletX = nch->nch_MouseAbsX;
6348 nch->nch_TabletEvent.ient_TabletY = nch->nch_MouseAbsY;
6349 nch->nch_TabletEvent.ient_TagList = (struct TagItem *) tagptr;
6350 if(nch->nch_MouseRangeZ)
6352 KPRINTF(1, ("AbsZ %ld\n", nch->nch_MouseAbsZ));
6353 *tagptr++ = TABLETA_TabletZ;
6354 *tagptr++ = nch->nch_MouseAbsZ;
6355 *tagptr++ = TABLETA_RangeZ;
6356 *tagptr++ = nch->nch_MouseRangeZ;
6358 if(nch->nch_VldRotX)
6360 KPRINTF(1, ("AngleX %ld\n", nch->nch_TabRotX));
6361 *tagptr++ = TABLETA_AngleX;
6362 *tagptr++ = nch->nch_TabRotX;
6364 if(nch->nch_VldRotY)
6366 KPRINTF(1, ("AngleY %ld\n", nch->nch_TabRotY));
6367 *tagptr++ = TABLETA_AngleY;
6368 *tagptr++ = nch->nch_TabRotY;
6370 if(nch->nch_VldRotZ)
6372 KPRINTF(1, ("AngleZ %ld\n", nch->nch_TabRotZ));
6373 *tagptr++ = TABLETA_AngleZ;
6374 *tagptr++ = nch->nch_TabRotZ;
6376 if(nch->nch_VldPressure)
6378 KPRINTF(1, ("Pressure %ld\n", nch->nch_TabPressure));
6379 *tagptr++ = TABLETA_Pressure;
6380 *tagptr++ = nch->nch_TabPressure;
6382 *tagptr++ = TABLETA_ButtonBits;
6383 *tagptr++ = nch->nch_MouseButtons;
6384 if(nch->nch_VldProx)
6386 KPRINTF(1, ("InProx %ld\n", nch->nch_TabProx));
6387 *tagptr++ = TABLETA_InProximity;
6388 *tagptr++ = nch->nch_TabProx;
6390 *tagptr = TAG_END;
6391 nch->nch_FakeEvent.ie_Class = IECLASS_NEWPOINTERPOS;
6392 nch->nch_FakeEvent.ie_SubClass = IESUBCLASS_NEWTABLET;
6393 nch->nch_FakeEvent.ie_Code = IECODE_NOBUTTON;
6394 nch->nch_FakeEvent.ie_NextEvent = NULL;
6395 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers;
6396 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
6397 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
6398 nch->nch_InpIOReq->io_Command = IND_WRITEEVENT;
6399 DoIO((struct IORequest *) nch->nch_InpIOReq);
6400 nch->nch_NewMouseAbs = FALSE;
6402 nCheckReset(nch);
6404 /* \\\ */
6406 /* /// "nSendRawKey()" */
6407 void nSendRawKey(struct NepClassHid *nch, UWORD key)
6409 nch->nch_FakeEvent.ie_Class = IECLASS_RAWKEY;
6410 nch->nch_FakeEvent.ie_SubClass = 0;
6411 nch->nch_FakeEvent.ie_Code = key;
6412 nch->nch_FakeEvent.ie_NextEvent = NULL;
6413 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers;
6414 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
6415 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
6416 nch->nch_InpIOReq->io_Command = nch->nch_OS4Hack ? IND_ADDEVENT : IND_WRITEEVENT;
6417 DoIO((struct IORequest *) nch->nch_InpIOReq);
6419 /* \\\ */
6421 /* /// "nCheckReset()" */
6422 void nCheckReset(struct NepClassHid *nch)
6424 if(nch->nch_CDC->cdc_EnableKBReset &&
6425 (nch->nch_KeyQualifiers & (IEQUALIFIER_CONTROL|IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND)) ==
6426 (IEQUALIFIER_CONTROL|IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND))
6428 struct MsgPort *mp;
6429 struct IOStdReq *ioreq;
6430 struct Interrupt tempint;
6431 struct Node *node;
6432 struct List *listhead = NULL;
6433 BOOL haskbh = FALSE;
6434 KPRINTF(20, ("Reboot!\n"));
6436 if(nch->nch_CDC->cdc_EnableRH)
6438 if((mp = CreateMsgPort()))
6440 if((ioreq = (struct IOStdReq *) CreateIORequest(mp, sizeof(struct IOStdReq))))
6442 if(!OpenDevice("keyboard.device", 0, (struct IORequest *) ioreq, 0))
6444 /* Find list header of reset handlers */
6445 tempint.is_Node.ln_Pred = NULL;
6446 tempint.is_Node.ln_Succ = NULL;
6447 tempint.is_Node.ln_Type = NT_INTERRUPT;
6448 tempint.is_Node.ln_Pri = 32;
6449 tempint.is_Node.ln_Name = "";
6450 tempint.is_Code = NULL;
6451 ioreq->io_Command = KBD_ADDRESETHANDLER;
6452 ioreq->io_Data = &tempint;
6453 Forbid();
6454 DoIO((struct IORequest *) ioreq);
6455 if((node = tempint.is_Node.ln_Pred))
6457 while(node->ln_Pred)
6459 node = node->ln_Pred;
6461 listhead = (struct List *) node;
6463 ioreq->io_Command = KBD_REMRESETHANDLER;
6464 DoIO((struct IORequest *) ioreq);
6465 Permit();
6466 if(listhead)
6468 node = listhead->lh_Head;
6469 while(node->ln_Succ)
6471 KPRINTF(20, ("Kicking %s\n", node->ln_Name));
6472 Cause((struct Interrupt *) node);
6473 haskbh = TRUE;
6474 node = node->ln_Succ;
6476 KPRINTF(20, ("Done... awaiting doom\n"));
6477 if(haskbh)
6479 psdDelayMS(nch->nch_CDC->cdc_ResetDelay*1000);
6481 } else {
6482 KPRINTF(20, ("Reset handler list not found!\n"));
6484 CloseDevice((struct IORequest *) ioreq);
6486 DeleteIORequest((struct IORequest *) ioreq);
6488 DeleteMsgPort(mp);
6491 ColdReboot();
6493 else if(nch->nch_CDC->cdc_EnableKBReset &&
6494 (nch->nch_KeyQualifiers & IEQUALIFIER_CONTROL) &&
6495 (nch->nch_KeyQualifiers & (IEQUALIFIER_LALT|IEQUALIFIER_RALT)) &&
6496 nch->nch_FakeEvent.ie_Code == RAWKEY_DELETE)
6498 KPRINTF(20, ("Reboot!\n"));
6499 ShutdownA(SD_ACTION_COLDREBOOT);
6502 /* \\\ */
6504 /* /// "nLoadItem()" */
6505 BOOL nLoadItem(struct NepClassHid *nch, struct PsdIFFContext *rppic, struct List *lst, UWORD idbase)
6507 struct PsdIFFContext *itpic;
6508 struct PsdIFFContext *actpic;
6509 struct NepHidAction *nha;
6510 ULONG newform[3];
6511 ULONG buf[2];
6512 struct NepHidActionChunk *nhac;
6513 STRPTR tmpstr;
6515 psdSafeRawDoFmt((STRPTR) buf, 8, "I%03lx", GET_WTYPE(lst) - idbase + 1);
6516 newform[0] = AROS_LONG2BE(ID_FORM);
6517 newform[1] = AROS_LONG2BE(4);
6518 newform[2] = *buf;
6519 itpic = psdFindCfgForm(rppic, AROS_LONG2BE(newform[2]));
6520 if(!itpic)
6522 return(FALSE);
6524 actpic = psdFindCfgForm(itpic, MAKE_ID('A','C','T','N'));
6525 while(actpic)
6527 if((nhac = psdGetCfgChunk(actpic, MAKE_ID('A','C','D','F'))))
6529 if((nha = nAllocAction(nch, lst, 0)))
6531 CopyMem(&nhac->nhac_Type, &nha->nha_Type, min(AROS_LONG2BE(nhac->nhac_Length), sizeof(struct NepHidActionChunk) - 8));
6532 if((tmpstr = psdGetStringChunk(actpic, MAKE_ID('S','N','D','F'))))
6534 strncpy(nha->nha_SoundFile, tmpstr, 255);
6535 psdFreeVec(tmpstr);
6537 if((tmpstr = psdGetStringChunk(actpic, MAKE_ID('V','A','N','S'))))
6539 strncpy(nha->nha_VanillaString, tmpstr, 79);
6540 psdFreeVec(tmpstr);
6542 if((tmpstr = psdGetStringChunk(actpic, MAKE_ID('K','E','Y','S'))))
6544 strncpy(nha->nha_KeyString, tmpstr, 79);
6545 psdFreeVec(tmpstr);
6547 if((tmpstr = psdGetStringChunk(actpic, MAKE_ID('E','X','E','S'))))
6549 strncpy(nha->nha_ExeString, tmpstr, 79);
6550 psdFreeVec(tmpstr);
6552 if((tmpstr = psdGetStringChunk(actpic, MAKE_ID('O','A','R','R'))))
6554 strncpy(nha->nha_OutArray, tmpstr, 255);
6555 psdFreeVec(tmpstr);
6558 psdFreeVec(nhac);
6560 actpic = psdNextCfgForm(actpic);
6562 return(TRUE);
6564 /* \\\ */
6566 /* /// "nSaveItem()" */
6567 struct PsdIFFContext * nSaveItem(struct NepClassHid *nch, struct PsdIFFContext *rppic, struct List *lst, UWORD idbase)
6569 struct PsdIFFContext *itpic;
6570 struct PsdIFFContext *actpic;
6571 struct NepHidAction *nha;
6572 ULONG newform[3];
6573 ULONG buf[2];
6574 struct NepHidActionChunk nhac;
6575 BOOL isdefault = TRUE;
6577 if(!lst->lh_Head->ln_Succ)
6579 return(NULL);
6581 nha = (struct NepHidAction *) lst->lh_Head;
6582 while(nha->nha_Node.ln_Succ)
6584 if(!nha->nha_IsDefault)
6586 isdefault = FALSE;
6588 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
6590 if(isdefault)
6592 return(NULL);
6594 psdSafeRawDoFmt((STRPTR) buf, 8, "I%03lx", GET_WTYPE(lst) - idbase + 1);
6595 newform[0] = AROS_LONG2BE(ID_FORM);
6596 newform[1] = AROS_LONG2BE(4);
6597 newform[2] = *buf;
6598 itpic = psdFindCfgForm(rppic, AROS_LONG2BE(newform[2]));
6599 if(!itpic)
6601 itpic = psdAddCfgEntry(rppic, newform);
6602 if(!itpic)
6604 return(NULL);
6607 nhac.nhac_ID = AROS_LONG2BE(MAKE_ID('A','C','D','F'));
6608 nhac.nhac_Length = AROS_LONG2BE(sizeof(struct NepHidActionChunk)-8);
6609 nha = (struct NepHidAction *) lst->lh_Head;
6610 while(nha->nha_Node.ln_Succ)
6612 if(!nha->nha_IsDefault)
6614 isdefault = FALSE;
6616 newform[2] = AROS_LONG2BE(MAKE_ID('A','C','T','N'));
6617 actpic = psdAddCfgEntry(itpic, newform);
6618 if(!actpic)
6620 break;
6622 CopyMem(&nha->nha_Type, &nhac.nhac_Type, sizeof(struct NepHidActionChunk)-8);
6623 psdAddCfgEntry(actpic, &nhac);
6624 if(*nha->nha_SoundFile)
6626 psdAddStringChunk(actpic, MAKE_ID('S','N','D','F'), nha->nha_SoundFile);
6628 if(*nha->nha_VanillaString)
6630 psdAddStringChunk(actpic, MAKE_ID('V','A','N','S'), nha->nha_VanillaString);
6632 if(*nha->nha_KeyString)
6634 psdAddStringChunk(actpic, MAKE_ID('K','E','Y','S'), nha->nha_KeyString);
6636 if(*nha->nha_ExeString)
6638 psdAddStringChunk(actpic, MAKE_ID('E','X','E','S'), nha->nha_ExeString);
6640 if(*nha->nha_OutArray)
6642 psdAddStringChunk(actpic, MAKE_ID('O','A','R','R'), nha->nha_OutArray);
6644 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
6646 return(itpic);
6648 /* \\\ */
6650 /* /// "nReadJoyPort()" */
6651 AROS_LH1(ULONG, nReadJoyPort,
6652 AROS_LHA(ULONG, port, D0),
6653 struct Library *, LowLevelBase, 5, hid)
6655 AROS_LIBFUNC_INIT
6657 struct NepHidBase *nh;
6658 struct NepClassHid *nch;
6659 ULONG result = JP_TYPE_NOTAVAIL;
6660 ULONG mode;
6662 if(!(nh = (struct NepHidBase *) FindName(&SysBase->LibList, GM_UNIQUENAME(libname))))
6664 return(result);
6667 result = AROS_CALL1(ULONG, nh->nh_LLOldReadJoyPort,
6668 AROS_LCA(ULONG, port, D0),
6669 struct Library *, nh->nh_LowLevelBase);
6671 KPRINTF(40, ("Before %08lx\n", result));
6672 if(port < 4)
6674 Forbid();
6675 nch = (struct NepClassHid *) nh->nh_Interfaces.lh_Head;
6676 while(nch->nch_Node.ln_Succ)
6678 mode = nch->nch_CDC->cdc_LLPortMode[port];
6679 if(nh->nh_LLAnalogueOverride[port] && nch->nch_LLAnalogue[port])
6681 mode = 4;
6684 switch(mode)
6686 // case 0: /* don't touch */
6687 // break;
6689 case 1: /* overwrite with USB */
6690 result = nch->nch_LLPortState[port] | nch->nch_LLHatswitch[port] | JP_TYPE_GAMECTLR;
6691 break;
6693 case 2: /* merge with USB */
6694 if(((result & JP_TYPE_MASK) == JP_TYPE_GAMECTLR) ||
6695 ((result & JP_TYPE_MASK) == JP_TYPE_JOYSTK) ||
6696 ((result & JP_TYPE_MASK) == JP_TYPE_UNKNOWN) ||
6697 (!result))
6699 result = (result & (JP_BUTTON_MASK|JP_DIRECTION_MASK)) | nch->nch_LLPortState[port] | nch->nch_LLHatswitch[port] | JP_TYPE_GAMECTLR;
6701 break;
6703 case 3: /* disable */
6704 result = JP_TYPE_NOTAVAIL;
6705 break;
6707 case 4: /* overwrite with analogue USB */
6708 if(nch->nch_LLAnalogue[port])
6710 result = (nch->nch_LLPortState[port] & ~JP_DIRECTION_MASK) | (nch->nch_LLAnalogue[port] & JP_XYAXIS_MASK) | nch->nch_LLHatswitch[port] | JP_TYPE_ANALOGUE;
6712 break;
6714 nch = (struct NepClassHid *) nch->nch_Node.ln_Succ;
6716 Permit();
6718 if((port >= JP_ANALOGUE_PORT_MAGIC) && (port < (JP_ANALOGUE_PORT_MAGIC|4)))
6720 port &= 3;
6721 Forbid();
6722 nch = (struct NepClassHid *) nh->nh_Interfaces.lh_Head;
6723 while(nch->nch_Node.ln_Succ)
6725 if(nch->nch_LLAnalogue[port])
6727 result = (nch->nch_LLPortState[port] & ~JP_DIRECTION_MASK) | (nch->nch_LLAnalogue[port] & JP_XYAXIS_MASK) | nch->nch_LLHatswitch[port] | JP_TYPE_ANALOGUE;
6729 nch = (struct NepClassHid *) nch->nch_Node.ln_Succ;
6731 Permit();
6733 KPRINTF(40, ("And after %08lx\n", result));
6735 return(result);
6736 AROS_LIBFUNC_EXIT
6738 /* \\\ */
6740 /* /// "nSetJoyPortAttrsA()" */
6741 AROS_LH2(ULONG, nSetJoyPortAttrsA,
6742 AROS_LHA(ULONG, port, D0),
6743 AROS_LHA(struct TagItem *, tags, A1),
6744 struct Library *, LowLevelBase, 22, hid)
6746 AROS_LIBFUNC_INIT
6748 struct NepHidBase *nh;
6749 struct TagItem *typetag;
6750 struct TagItem *motortags[2];
6751 struct TagItem *motorofftag;
6752 ULONG result = FALSE;
6754 if(!(nh = (struct NepHidBase *) FindName(&SysBase->LibList, GM_UNIQUENAME(libname))))
6756 return(result);
6759 result = AROS_CALL2(ULONG, nh->nh_LLOldSetJoyPortAttrsA,
6760 AROS_LCA(ULONG, port, D0),
6761 AROS_LCA(struct TagItem *, tags, A1),
6762 struct Library *, nh->nh_LowLevelBase);
6764 KPRINTF(40, ("Before %08lx\n", result));
6765 if(port < 4)
6767 typetag = FindTagItem(SJA_Type, tags);
6768 if(typetag)
6770 if(typetag->ti_Data == SJA_TYPE_ANALOGUE)
6772 nh->nh_LLAnalogueOverride[port] = TRUE;
6773 } else {
6774 nh->nh_LLAnalogueOverride[port] = FALSE;
6776 result = TRUE;
6778 typetag = FindTagItem(SJA_Reinitialize, tags);
6779 if(typetag)
6781 if(typetag->ti_Data)
6783 nh->nh_LLAnalogueOverride[port] = FALSE;
6786 motortags[0] = FindTagItem(SJA_RumbleSetSlowMotor, tags);
6787 motortags[1] = FindTagItem(SJA_RumbleSetFastMotor, tags);
6788 motorofftag = FindTagItem(SJA_RumbleOff, tags);
6789 if(motortags[0] || motortags[1] || motorofftag)
6791 struct NepHidItem *nhi;
6792 struct NepClassHid *nch;
6793 struct TagItem nulltag = { 0, 0 };
6794 ULONG cnt;
6795 BOOL sigit = FALSE;
6796 if(motorofftag)
6798 if(motorofftag->ti_Data)
6800 motortags[0] = &nulltag;
6801 motortags[1] = &nulltag;
6804 Forbid();
6805 nch = (struct NepClassHid *) nh->nh_Interfaces.lh_Head;
6806 while(nch->nch_Node.ln_Succ)
6808 if(nch->nch_CDC->cdc_LLRumblePort == port+1)
6810 for(cnt = 0; cnt < 2; cnt++)
6812 if(motortags[cnt] && ((nhi = nch->nch_RumbleMotors[cnt])))
6814 if(nhi->nhi_OldValue != motortags[cnt]->ti_Data)
6816 nhi->nhi_OldValue = motortags[cnt]->ti_Data;
6817 nhi->nhi_Collection->nhc_Report->nhr_OutTouched = TRUE;
6818 nch->nch_OutFeatTouched = TRUE;
6819 sigit = TRUE;
6823 if(sigit)
6825 Signal(nch->nch_Task, (1L<<nch->nch_TaskMsgPort->mp_SigBit));
6829 nch = (struct NepClassHid *) nch->nch_Node.ln_Succ;
6831 Permit();
6832 result = TRUE;
6835 KPRINTF(40, ("And after %08lx\n", result));
6837 return(result);
6839 AROS_LIBFUNC_EXIT
6841 /* \\\ */
6843 /* /// "nInstallLastActionHero()" */
6844 void nInstallLastActionHero(struct NepClassHid *nch)
6846 struct NepHidBase *nh = nch->nch_ClsBase;
6848 if(!nh->nh_DispatcherTask)
6850 nh->nh_ReadySignal = SIGB_SINGLE;
6851 nh->nh_ReadySigTask = FindTask(NULL);
6852 SetSignal(0, SIGF_SINGLE);
6853 if(psdSpawnSubTask("Last Action Hero", GM_UNIQUENAME(nDispatcherTask), nh))
6855 Wait(1L<<nh->nh_ReadySignal);
6856 if(!nh->nh_DispatcherTask)
6858 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
6859 "It's your fault! I'm sure! Couldn't create subtask for launching!");
6860 } else {
6861 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
6862 "Last Action Hero successfully launched!");
6864 } else {
6865 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
6866 "It's your fault! I'm sure! Couldn't create subtask for launching!");
6868 nh->nh_ReadySigTask = NULL;
6869 //FreeSignal(nh->nh_ReadySignal);
6872 /* \\\ */
6874 /************************************************************************/
6876 #undef ps
6878 /* /// "nDispatcherTask()" */
6879 AROS_UFH0(void, GM_UNIQUENAME(nDispatcherTask))
6881 AROS_USERFUNC_INIT
6883 struct NepHidBase *nh;
6884 struct Task *thistask;
6885 struct ActionMsg *am;
6886 struct NepHidSound *nhs;
6888 thistask = FindTask(NULL);
6890 #undef CxBase
6891 #undef IntuitionBase
6892 #undef DOSBase
6893 #undef DataTypesBase
6894 nh = thistask->tc_UserData;
6895 NewList(&nh->nh_Sounds);
6896 if((nh->nh_InpMsgPort = CreateMsgPort()))
6898 if((nh->nh_InpIOReq = (struct IOStdReq *) CreateIORequest(nh->nh_InpMsgPort, sizeof(struct IOStdReq))))
6900 if(!OpenDevice("input.device", 0, (struct IORequest *) nh->nh_InpIOReq, 0))
6902 if((nh->nh_DOSBase = OpenLibrary("dos.library", 39)))
6904 if((nh->nh_IntBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 39)))
6906 #define IntuitionBase nh->nh_IntBase
6907 if((nh->nh_DTBase = OpenLibrary("datatypes.library", 39)))
6909 if((nh->nh_CxBase = OpenLibrary("commodities.library", 39)))
6911 if((nh->nh_LayersBase = OpenLibrary("layers.library", 39)))
6913 #define CxBase nh->nh_CxBase
6914 #define DOSBase nh->nh_DOSBase
6915 #define DataTypesBase nh->nh_DTBase
6916 #define LayersBase nh->nh_LayersBase
6917 if((nh->nh_DTaskMsgPort = CreateMsgPort()))
6919 nh->nh_DispatcherTask = thistask;
6920 Forbid();
6921 if(nh->nh_ReadySigTask)
6923 Signal(nh->nh_ReadySigTask, 1L<<nh->nh_ReadySignal);
6925 Permit();
6927 nLastActionHero(nh);
6929 Forbid();
6930 while((am = (struct ActionMsg *) GetMsg(nh->nh_DTaskMsgPort)))
6932 FreeVec(am);
6934 nhs = (struct NepHidSound *) nh->nh_Sounds.lh_Head;
6935 while(nhs->nhs_Node.ln_Succ)
6937 nFreeSound(nh, nhs);
6938 nhs = (struct NepHidSound *) nh->nh_Sounds.lh_Head;
6940 DeleteMsgPort(nh->nh_DTaskMsgPort);
6941 nh->nh_DTaskMsgPort = NULL;
6942 Permit();
6944 CloseLibrary(nh->nh_LayersBase);
6945 nh->nh_LayersBase = NULL;
6947 CloseLibrary(nh->nh_CxBase);
6948 nh->nh_CxBase = NULL;
6950 CloseLibrary(nh->nh_DTBase);
6951 nh->nh_DTBase = NULL;
6953 CloseLibrary((struct Library *) nh->nh_IntBase);
6954 nh->nh_IntBase = NULL;
6956 CloseLibrary((struct Library *) nh->nh_DOSBase);
6957 nh->nh_DOSBase = NULL;
6959 CloseDevice((struct IORequest *) nh->nh_InpIOReq);
6961 DeleteIORequest((struct IORequest *) nh->nh_InpIOReq);
6962 nh->nh_InpIOReq = NULL;
6964 DeleteMsgPort(nh->nh_InpMsgPort);
6965 nh->nh_InpMsgPort = NULL;
6967 Forbid();
6968 if(nh->nh_ReadySigTask)
6970 Signal(nh->nh_ReadySigTask, 1L<<nh->nh_ReadySignal);
6972 nh->nh_DispatcherTask = NULL;
6974 AROS_USERFUNC_EXIT
6976 /* \\\ */
6978 /* /// "nLastActionHero()" */
6979 void nLastActionHero(struct NepHidBase *nh)
6981 ULONG sigmask;
6982 ULONG sigs;
6983 struct ActionMsg *am;
6984 struct NepHidAction *nha;
6985 struct NepClassHid *nch;
6986 struct Window *actwindow;
6987 struct Screen *actscreen;
6988 char buf[128];
6989 ULONG intlock;
6990 sigmask = (1L<<nh->nh_DTaskMsgPort->mp_SigBit)|SIGBREAKF_CTRL_C;
6993 while((am = (struct ActionMsg *) GetMsg(nh->nh_DTaskMsgPort)))
6995 nch = am->am_NCH;
6996 nha = am->am_Action;
6997 switch(nha->nha_Type & HUA_ATYPEMASK)
6999 case HUA_VANILLA:
7000 buf[0] = '<';
7001 strcpy(&buf[1], nha->nha_VanillaString);
7002 strcat(buf, ">");
7003 if(!nSendKeyString(nh, buf))
7005 nEasyRequest(nh, "'%s' is no good. Really.", "Argl!", nha->nha_VanillaString);
7007 break;
7009 case HUA_KEYSTRING:
7010 if(!nSendKeyString(nh, nha->nha_KeyString))
7012 nEasyRequest(nh, "Don't you ever say\n'%s'\nto me again!", "Terribly sorry!", nha->nha_KeyString);
7014 break;
7016 case HUA_SOUND:
7017 nPlaySound(nh, nha);
7018 break;
7020 case HUA_SHELL:
7022 BPTR fhandle;
7023 LONG ioerr;
7024 if((fhandle = Open(nch->nch_CDC->cdc_ShellCon, MODE_READWRITE)))
7026 ioerr = SystemTags(nha->nha_ExeString,
7027 SYS_Input, fhandle,
7028 SYS_Output, NULL,
7029 SYS_Asynch, nha->nha_ShellAsync,
7030 NP_StackSize, nch->nch_CDC->cdc_ShellStack,
7031 TAG_END);
7032 if(ioerr)
7034 nEasyRequest(nh, "Offender survived execution of\n'%s'\nwith error code %ld.", "Get me a shotgun then!", nha->nha_ExeString, ioerr);
7036 if((!nha->nha_ShellAsync) || ioerr)
7038 Close(fhandle);
7040 } else {
7041 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);
7043 break;
7046 case HUA_MISC:
7047 switch(nha->nha_MiscMode)
7049 case HUAT_ACTWINDOW:
7051 struct Layer *toplayer;
7052 intlock = LockIBase(0);
7053 actscreen = nh->nh_IntBase->ActiveScreen;
7054 actwindow = nh->nh_IntBase->ActiveWindow;
7055 UnlockIBase(intlock);
7056 if(actscreen)
7058 LockLayerInfo(&actscreen->LayerInfo);
7059 toplayer = WhichLayer(&actscreen->LayerInfo, (LONG) actscreen->MouseX, (LONG) actscreen->MouseY);
7060 UnlockLayerInfo(&actscreen->LayerInfo);
7062 if(toplayer)
7064 if(toplayer->Window && (actwindow != toplayer->Window))
7066 ActivateWindow(toplayer->Window);
7070 break;
7073 case HUAT_DISPLAYBEEP:
7074 DisplayBeep(NULL);
7075 break;
7077 case HUAT_WB2FRONT:
7078 WBenchToFront();
7079 break;
7081 case HUAT_SCREENCYCLE:
7082 intlock = LockIBase(0);
7083 actscreen = nh->nh_IntBase->FirstScreen;
7084 UnlockIBase(intlock);
7085 if(actscreen)
7087 ScreenToBack(actscreen);
7089 break;
7091 case HUAT_WIN2FRONT:
7092 intlock = LockIBase(0);
7093 actwindow = nh->nh_IntBase->ActiveWindow;
7094 UnlockIBase(intlock);
7095 if(actwindow)
7097 WindowToFront(actwindow);
7099 break;
7101 case HUAT_WIN2BACK:
7102 intlock = LockIBase(0);
7103 actwindow = nh->nh_IntBase->ActiveWindow;
7104 UnlockIBase(intlock);
7105 if(actwindow)
7107 WindowToBack(actwindow);
7109 break;
7111 case HUAT_ZIPWINDOW:
7112 intlock = LockIBase(0);
7113 actwindow = nh->nh_IntBase->ActiveWindow;
7114 UnlockIBase(intlock);
7115 if(actwindow)
7117 ZipWindow(actwindow);
7119 break;
7122 break;
7125 FreeVec(am);
7127 sigs = Wait(sigmask);
7128 } while(!(sigs & SIGBREAKF_CTRL_C));
7130 /* \\\ */
7132 /* /// "nLoadSound()" */
7133 struct NepHidSound * nLoadSound(struct NepHidBase *nh, STRPTR name)
7135 struct NepHidSound *nhs;
7136 if((nhs = AllocVec(sizeof(struct NepHidSound), MEMF_PUBLIC|MEMF_CLEAR)))
7138 if((nhs->nhs_Node.ln_Name = AllocVec((ULONG) strlen(name)+1, MEMF_PUBLIC)))
7140 strcpy(nhs->nhs_Node.ln_Name, name);
7141 AddTail(&nh->nh_Sounds, &nhs->nhs_Node);
7142 nhs->nhs_DTHandle = NewDTObject(name,
7143 DTA_SourceType, DTST_FILE,
7144 DTA_GroupID, GID_SOUND,
7145 SDTA_Cycles, 1L,
7146 TAG_END);
7147 if(!nhs->nhs_DTHandle)
7149 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);
7151 return(nhs);
7153 FreeVec(nhs);
7155 return(NULL);
7157 /* \\\ */
7159 /* /// "nPlaySound()" */
7160 BOOL nPlaySound(struct NepHidBase *nh, struct NepHidAction *nha)
7162 struct NepHidSound *nhs;
7163 struct dtTrigger playmsg;
7164 nhs = (struct NepHidSound *) FindName(&nh->nh_Sounds, nha->nha_SoundFile);
7165 if(!nhs)
7167 nhs = nLoadSound(nh, nha->nha_SoundFile);
7169 if(!nhs)
7171 return(FALSE);
7173 if(!nhs->nhs_DTHandle)
7175 return(FALSE);
7178 SetAttrs(nhs->nhs_DTHandle,
7179 SDTA_Volume, nha->nha_SoundVolume,
7180 TAG_END);
7181 playmsg.MethodID = DTM_TRIGGER;
7182 playmsg.dtt_GInfo = NULL;
7183 playmsg.dtt_Function = STM_PLAY;
7184 playmsg.dtt_Data = NULL;
7185 DoMethodA(nhs->nhs_DTHandle, (Msg) &playmsg);
7186 return(TRUE);
7188 /* \\\ */
7190 /* /// "nFreeSound()" */
7191 void nFreeSound(struct NepHidBase *nh, struct NepHidSound *nhs)
7193 Remove(&nhs->nhs_Node);
7194 if(nhs->nhs_DTHandle)
7196 DisposeDTObject(nhs->nhs_DTHandle);
7198 FreeVec(nhs->nhs_Node.ln_Name);
7199 FreeVec(nhs);
7201 /* \\\ */
7203 /* /// "nInvertString()" */
7204 struct InputEvent *nInvertString(struct NepHidBase *nh, STRPTR str, struct KeyMap *km)
7206 struct InputEvent *prior = NULL;
7207 struct InputEvent *ne;
7208 struct InputXpression tmpIX;
7210 BOOL freeevents = FALSE;
7211 char cc;
7212 char *oldsptr;
7214 if(!str) return(NULL);
7215 if(!(*str)) return(NULL);
7218 if((ne = AllocMem(sizeof(struct InputEvent), MEMF_CLEAR)))
7220 ne->ie_NextEvent = prior;
7221 prior = ne;
7222 cc = *str++;
7223 switch(cc)
7225 case '<': /* do angles */
7226 oldsptr = str;
7227 freeevents = TRUE;
7228 while((cc = *str))
7230 if(cc == '>')
7232 *str = '\0';
7233 if(!ParseIX(oldsptr, &tmpIX))
7235 freeevents = FALSE;
7236 prior->ie_Class = tmpIX.ix_Class;
7237 prior->ie_Code = tmpIX.ix_Code;
7238 prior->ie_Qualifier = tmpIX.ix_Qualifier;
7240 *str++ = cc;
7241 break;
7243 str++;
7245 break;
7247 case '\\': /* do escape sequences */
7248 cc = *str++;
7249 switch(cc)
7251 case '"':
7252 case '\'':
7253 case '<':
7254 case '\\':
7255 break;
7256 case 'n':
7257 case 'r':
7258 cc = '\r';
7259 break;
7260 case 't':
7261 cc = '\t';
7262 break;
7263 case '0':
7264 cc = '\0';
7265 break;
7266 default:
7267 freeevents = TRUE;
7268 break;
7270 if(freeevents) break;
7271 /* note that this break is missing on purpose */
7272 default: /* normal key translation */
7273 InvertKeyMap((ULONG) cc, prior, km);
7274 break;
7276 } else {
7277 freeevents = TRUE;
7279 } while(*str && (!freeevents));
7280 if(freeevents)
7282 nFreeIEvents(nh, prior);
7283 return(NULL);
7285 return(prior);
7287 /* \\\ */
7289 /* /// "nFreeIEvents()" */
7290 void nFreeIEvents(struct NepHidBase *nh, struct InputEvent *event)
7292 struct InputEvent *next;
7293 while(event)
7295 next = event->ie_NextEvent;
7296 FreeMem(event, sizeof(struct InputEvent));
7297 event = next;
7300 /* \\\ */
7302 /* /// "nSendKeyString()" */
7303 BOOL nSendKeyString(struct NepHidBase *nh, STRPTR str)
7305 struct InputEvent *events = nInvertString(nh, str, NULL);
7306 struct InputEvent *eptr = events;
7307 struct InputEvent lastevent;
7308 int count = 0;
7309 int lstpos;
7310 if(!events)
7312 return(FALSE);
7314 while(eptr)
7316 count++;
7317 eptr = eptr->ie_NextEvent;
7319 while(count)
7321 eptr = events;
7322 for(lstpos = --count; lstpos; lstpos--)
7323 eptr = eptr->ie_NextEvent;
7325 nh->nh_FakeEvent = *eptr;
7326 nh->nh_FakeEvent.ie_NextEvent = NULL;
7327 nh->nh_InpIOReq->io_Data = &nh->nh_FakeEvent;
7328 nh->nh_InpIOReq->io_Length = sizeof(struct InputEvent);
7329 nh->nh_InpIOReq->io_Command = nh->nh_OS4Hack ? IND_ADDEVENT : IND_WRITEEVENT;
7330 DoIO((struct IORequest *) nh->nh_InpIOReq);
7332 nh->nh_FakeEvent.ie_Code |= IECODE_UP_PREFIX;
7333 nh->nh_InpIOReq->io_Data = &nh->nh_FakeEvent;
7334 nh->nh_InpIOReq->io_Length = sizeof(struct InputEvent);
7335 nh->nh_InpIOReq->io_Command = nh->nh_OS4Hack ? IND_ADDEVENT : IND_WRITEEVENT;
7336 DoIO((struct IORequest *) nh->nh_InpIOReq);
7338 lastevent.ie_Class = IECLASS_RAWKEY;
7339 lastevent.ie_SubClass = 0;
7340 lastevent.ie_Code = 0xFF;
7341 lastevent.ie_NextEvent = NULL;
7342 lastevent.ie_Qualifier = 0;
7343 nh->nh_InpIOReq->io_Data = &lastevent;
7344 nh->nh_InpIOReq->io_Length = sizeof(struct InputEvent);
7345 nh->nh_InpIOReq->io_Command = nh->nh_OS4Hack ? IND_ADDEVENT : IND_WRITEEVENT;
7346 DoIO((struct IORequest *) nh->nh_InpIOReq);
7347 nFreeIEvents(nh, events);
7348 return(TRUE);
7350 /* \\\ */
7352 /* /// "nEasyRequest()" */
7353 LONG nEasyRequest(struct NepHidBase *nh, STRPTR body, STRPTR gadgets, ...)
7355 LONG ret;
7357 AROS_SLOWSTACKFORMAT_PRE(gadgets);
7358 ret = nEasyRequestA(nh, body, gadgets, AROS_SLOWSTACKFORMAT_ARG(gadgets));
7359 AROS_SLOWSTACKFORMAT_POST(gadgets);
7361 return ret;
7363 /* \\\ */
7365 /* /// "nEasyRequestA()" */
7366 LONG nEasyRequestA(struct NepHidBase *nh, STRPTR body, STRPTR gadgets, RAWARG params)
7368 struct EasyStruct es;
7369 es.es_StructSize = sizeof(struct EasyStruct);
7370 es.es_Flags = 0;
7371 es.es_Title = GM_UNIQUENAME(libname);
7372 es.es_TextFormat = body;
7373 es.es_GadgetFormat = gadgets;
7374 return(EasyRequestArgs(NULL, &es, NULL, params));
7376 /* \\\ */