revert between 56095 -> 55830 in arch
[AROS.git] / rom / usb / classes / hid / hid.class.c
blobbe9519d3feb07fe13a0dcb642bb561fb2c377ede
1 /*
2 *----------------------------------------------------------------------------
3 * hid class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
6 */
8 #include "debug.h"
10 #include "numtostr.h"
11 #include "hid.class.h"
13 #include <proto/datatypes.h>
15 static LONG _rand(struct NepHidBase *nh)
17 nh->nh_Seed = nh->nh_Seed * 1103515245 + 12345;
19 return nh->nh_Seed;
22 /* /// "Lib Stuff" */
23 const STRPTR GM_UNIQUENAME(libname) = MOD_NAME_STRING;
25 //#define LowLevelBase nh->nh_LowLevelBase
27 static int GM_UNIQUENAME(libInit)(LIBBASETYPEPTR nh)
29 struct NepClassHid *nch;
30 struct NepHidBase *ret = NULL;
32 KPRINTF(10, ("libInit nh: 0x%08lx SysBase: 0x%08lx\n", nh, SysBase));
34 nh->nh_UtilityBase = OpenLibrary("utility.library", 39);
36 #define UtilityBase nh->nh_UtilityBase
38 if(UtilityBase)
40 NewList(&nh->nh_Interfaces);
41 nch = &nh->nh_DummyNCH;
42 nch->nch_ClsBase = nh;
43 nch->nch_Interface = NULL;
45 nch->nch_CDC = AllocVec(sizeof(struct ClsDevCfg), MEMF_PUBLIC|MEMF_CLEAR);
46 if(nch->nch_CDC)
48 ret = nh;
50 if(!ret)
52 CloseLibrary(UtilityBase);
54 } else {
55 KPRINTF(20, ("libInit: OpenLibrary(\"utility.library\", 39) failed!\n"));
58 KPRINTF(10, ("libInit: Ok\n"));
59 return(ret ? TRUE : FALSE);
62 static int GM_UNIQUENAME(libOpen)(LIBBASETYPEPTR nh)
64 KPRINTF(10, ("libOpen nh: 0x%08lx\n", nh));
65 GM_UNIQUENAME(nLoadClassConfig)(nh);
66 return(TRUE);
69 static int GM_UNIQUENAME(libClose)(LIBBASETYPEPTR nh)
71 if(nh->nh_Library.lib_OpenCnt == 0) // FIXME is this 0 or 1? Does AROS decrease it before calling libClose?
73 Forbid();
74 nh->nh_ReadySignal = SIGB_SINGLE;
75 nh->nh_ReadySigTask = FindTask(NULL);
76 if(nh->nh_DispatcherTask)
78 Signal(nh->nh_DispatcherTask, SIGBREAKF_CTRL_C);
80 Permit();
81 while(nh->nh_DispatcherTask)
83 Wait(1L<<nh->nh_ReadySignal);
85 //FreeSignal(nh->nh_ReadySignal);
87 KPRINTF(5, ("libClose: lib_OpenCnt = %ld\n", nh->nh_Library.lib_OpenCnt));
88 return(TRUE);
91 static int GM_UNIQUENAME(libExpunge)(LIBBASETYPEPTR nh)
93 KPRINTF(10, ("libExpunge nh: 0x%08lx\n", nh));
95 if(nh->nh_LowLevelBase)
97 APTR ourvec;
98 Disable();
99 ourvec = SetFunction(nh->nh_LowLevelBase, -5 * LIB_VECTSIZE, nh->nh_LLOldReadJoyPort);
100 if(ourvec != AROS_SLIB_ENTRY(nReadJoyPort, hid, 5))
102 SetFunction(nh->nh_LowLevelBase, -5 * LIB_VECTSIZE, ourvec);
103 Enable();
104 return(FALSE); /* we couldn't remove the patch! */
106 ourvec = SetFunction(nh->nh_LowLevelBase, -22 * LIB_VECTSIZE, nh->nh_LLOldSetJoyPortAttrsA);
107 if(ourvec != AROS_SLIB_ENTRY(nSetJoyPortAttrsA, hid, 22))
109 SetFunction(nh->nh_LowLevelBase, -22 * LIB_VECTSIZE, ourvec);
110 Enable();
111 return(FALSE); /* we couldn't remove the patch! */
113 Enable();
114 CloseLibrary(nh->nh_LowLevelBase);
115 nh->nh_LowLevelBase = NULL;
118 CloseLibrary((struct Library *) UtilityBase);
120 FreeVec(nh->nh_DummyNCH.nch_CDC);
122 KPRINTF(5, ("libExpunge: Unloading done! hid.class expunged!\n\n"));
124 return(TRUE);
127 ADD2INITLIB(GM_UNIQUENAME(libInit), 0)
128 ADD2OPENLIB(GM_UNIQUENAME(libOpen), 0)
129 ADD2CLOSELIB(GM_UNIQUENAME(libClose), 0)
130 ADD2EXPUNGELIB(GM_UNIQUENAME(libExpunge), 0)
131 /* \\\ */
134 * ***********************************************************************
135 * * Library functions *
136 * ***********************************************************************
139 /* /// "usbAttemptInterfaceBinding()" */
140 struct NepClassHid * GM_UNIQUENAME(usbAttemptInterfaceBinding)(struct NepHidBase *nh, struct PsdInterface *pif)
142 struct Library *ps;
143 IPTR ifclass;
144 //IPTR subclass;
145 //IPTR proto;
147 KPRINTF(1, ("nepHidAttemptInterfaceBinding(%08lx)\n", pif));
148 if((ps = OpenLibrary("poseidon.library", 4)))
150 psdGetAttrs(PGA_INTERFACE, pif,
151 IFA_Class, &ifclass,
152 //IFA_SubClass, &subclass,
153 //IFA_Protocol, &proto,
154 TAG_DONE);
155 CloseLibrary(ps);
157 if(ifclass == HID_CLASSCODE)
159 return(GM_UNIQUENAME(usbForceInterfaceBinding)(nh, pif));
162 return(NULL);
164 /* \\\ */
166 /* /// "usbForceInterfaceBinding()" */
167 struct NepClassHid * GM_UNIQUENAME(usbForceInterfaceBinding)(struct NepHidBase *nh, struct PsdInterface *pif)
169 struct Library *ps;
170 struct NepClassHid *nch;
171 struct PsdConfig *pc;
172 struct PsdDevice *pd;
173 STRPTR devname;
174 STRPTR ifidstr;
175 STRPTR devidstr;
176 UBYTE buf[64];
177 struct Task *tmptask;
179 KPRINTF(1, ("nepHidForceInterfaceBinding(%08lx)\n", pif));
181 nInstallLLPatch(nh);
182 if((ps = OpenLibrary("poseidon.library", 4)))
184 psdGetAttrs(PGA_INTERFACE, pif,
185 IFA_Config, &pc,
186 IFA_IDString, &ifidstr,
187 TAG_DONE);
188 psdGetAttrs(PGA_CONFIG, pc,
189 CA_Device, &pd,
190 TAG_END);
191 psdGetAttrs(PGA_DEVICE, pd,
192 DA_ProductName, &devname,
193 DA_IDString, &devidstr,
194 TAG_END);
195 if((nch = psdAllocVec(sizeof(struct NepClassHid))))
197 nch->nch_ClsBase = nh;
198 nch->nch_CDC = psdAllocVec(sizeof(struct ClsDevCfg));
199 if(!nch->nch_CDC)
201 psdFreeVec(nch);
202 CloseLibrary(ps);
203 return(NULL);
206 nch->nch_Device = pd;
207 nch->nch_Interface = pif;
208 nch->nch_DevIDString = devidstr;
209 nch->nch_IfIDString = ifidstr;
211 GM_UNIQUENAME(nLoadBindingConfig)(nch, FALSE);
213 psdSafeRawDoFmt(buf, 64, "hid.class<%08lx>", nch);
214 nch->nch_ReadySignal = SIGB_SINGLE;
215 nch->nch_ReadySigTask = FindTask(NULL);
216 SetSignal(0, SIGF_SINGLE);
218 if((tmptask = psdSpawnSubTask(buf, GM_UNIQUENAME(nHidTask), nch)))
220 psdBorrowLocksWait(tmptask, 1UL<<nch->nch_ReadySignal);
221 if(nch->nch_Task)
223 nch->nch_ReadySigTask = NULL;
224 //FreeSignal(nch->nch_ReadySignal);
225 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
226 "HID the road, '%s'!",
227 devname);
228 Forbid();
229 AddTail(&nh->nh_Interfaces, &nch->nch_Node);
230 Permit();
231 CloseLibrary(ps);
232 return(nch);
235 nch->nch_ReadySigTask = NULL;
236 //FreeSignal(nch->nch_ReadySignal);
237 psdFreeVec(nch->nch_CDC);
238 psdFreeVec(nch);
240 CloseLibrary(ps);
242 return(NULL);
244 /* \\\ */
246 /* /// "usbReleaseInterfaceBinding()" */
247 void GM_UNIQUENAME(usbReleaseInterfaceBinding)(struct NepHidBase *nh, struct NepClassHid *nch)
249 struct Library *ps;
250 struct PsdConfig *pc;
251 struct PsdDevice *pd;
252 STRPTR devname;
254 KPRINTF(1, ("nepHidReleaseInterfaceBinding(%08lx)\n", nch));
255 if((ps = OpenLibrary("poseidon.library", 4)))
257 Forbid();
258 nch->nch_ReadySignal = SIGB_SINGLE;
259 nch->nch_ReadySigTask = FindTask(NULL);
260 if(nch->nch_GUITask)
262 Signal(nch->nch_GUITask, SIGBREAKF_CTRL_C);
264 Permit();
265 while(nch->nch_GUITask)
267 Wait(1L<<nch->nch_ReadySignal);
270 Forbid();
271 if(nch->nch_HCGUITask)
273 Signal(nch->nch_HCGUITask, SIGBREAKF_CTRL_C);
275 Permit();
276 while(nch->nch_HCGUITask)
278 Wait(1L<<nch->nch_ReadySignal);
281 Forbid();
282 if(nch->nch_Task)
284 Signal(nch->nch_Task, SIGBREAKF_CTRL_C);
286 Permit();
287 while(nch->nch_Task)
289 Wait(1L<<nch->nch_ReadySignal);
291 //FreeSignal(nch->nch_ReadySignal);
292 psdGetAttrs(PGA_INTERFACE, nch->nch_Interface, IFA_Config, &pc, TAG_END);
293 psdGetAttrs(PGA_CONFIG, pc, CA_Device, &pd, TAG_END);
294 psdGetAttrs(PGA_DEVICE, pd, DA_ProductName, &devname, TAG_END);
295 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
296 "And don't you come back no more, '%s'!",
297 devname);
298 Forbid();
299 Remove(&nch->nch_Node);
300 Permit();
301 psdFreeVec(nch->nch_CDC);
302 psdFreeVec(nch);
303 CloseLibrary(ps);
306 /* \\\ */
308 /* /// "usbGetAttrsA()" */
309 AROS_LH3(LONG, usbGetAttrsA,
310 AROS_LHA(ULONG, type, D0),
311 AROS_LHA(APTR, usbstruct, A0),
312 AROS_LHA(struct TagItem *, tags, A1),
313 LIBBASETYPEPTR, nh, 5, hid)
315 AROS_LIBFUNC_INIT
317 struct TagItem *ti;
318 LONG count = 0;
320 KPRINTF(1, ("nepHidGetAttrsA(%ld, %08lx, %08lx)\n", type, usbstruct, tags));
321 switch(type)
323 case UGA_CLASS:
324 if((ti = FindTagItem(UCCA_Priority, tags)))
326 *((SIPTR *) ti->ti_Data) = 0;
327 count++;
329 if((ti = FindTagItem(UCCA_Description, tags)))
331 *((STRPTR *) ti->ti_Data) = "Generic support for human interface devices";
332 count++;
334 if((ti = FindTagItem(UCCA_HasClassCfgGUI, tags)))
336 *((IPTR *) ti->ti_Data) = TRUE;
337 count++;
339 if((ti = FindTagItem(UCCA_HasBindingCfgGUI, tags)))
341 *((IPTR *) ti->ti_Data) = TRUE;
342 count++;
344 if((ti = FindTagItem(UCCA_AfterDOSRestart, tags)))
346 *((IPTR *) ti->ti_Data) = FALSE;
347 count++;
349 if((ti = FindTagItem(UCCA_UsingDefaultCfg, tags)))
351 *((IPTR *) ti->ti_Data) = nh->nh_DummyNCH.nch_UsingDefaultCfg;
352 count++;
354 if((ti = FindTagItem(UCCA_SupportsSuspend, tags)))
356 *((IPTR *) ti->ti_Data) = TRUE;
357 count++;
359 break;
361 case UGA_BINDING:
362 if((ti = FindTagItem(UCBA_UsingDefaultCfg, tags)))
364 *((IPTR *) ti->ti_Data) = ((struct NepClassHid *) usbstruct)->nch_UsingDefaultCfg;
365 count++;
367 break;
369 return(count);
370 AROS_LIBFUNC_EXIT
372 /* \\\ */
374 /* /// "usbSetAttrsA()" */
375 AROS_LH3(LONG, usbSetAttrsA,
376 AROS_LHA(ULONG, type, D0),
377 AROS_LHA(APTR, usbstruct, A0),
378 AROS_LHA(struct TagItem *, tags, A1),
379 LIBBASETYPEPTR, nh, 6, hid)
381 AROS_LIBFUNC_INIT
382 return(0);
383 AROS_LIBFUNC_EXIT
385 /* \\\ */
387 /* /// "usbDoMethodA()" */
388 AROS_LH2(IPTR, usbDoMethodA,
389 AROS_LHA(ULONG, methodid, D0),
390 AROS_LHA(IPTR *, methoddata, A1),
391 LIBBASETYPEPTR, nh, 7, hid)
393 AROS_LIBFUNC_INIT
395 struct NepClassHid *nch;
397 KPRINTF(10, ("Do Method %ld\n", methodid));
398 switch(methodid)
400 case UCM_AttemptInterfaceBinding:
401 return((IPTR) GM_UNIQUENAME(usbAttemptInterfaceBinding)(nh, (struct PsdInterface *) methoddata[0]));
403 case UCM_ForceInterfaceBinding:
404 return((IPTR) GM_UNIQUENAME(usbForceInterfaceBinding)(nh, (struct PsdInterface *) methoddata[0]));
406 case UCM_ReleaseInterfaceBinding:
407 GM_UNIQUENAME(usbReleaseInterfaceBinding)(nh, (struct NepClassHid *) methoddata[0]);
408 return(TRUE);
410 case UCM_OpenCfgWindow:
411 return(GM_UNIQUENAME(nOpenBindingCfgWindow)(nh, &nh->nh_DummyNCH));
413 case UCM_OpenBindingCfgWindow:
414 return(GM_UNIQUENAME(nOpenBindingCfgWindow)(nh, (struct NepClassHid *) methoddata[0]));
416 case UCM_DOSAvailableEvent:
417 nInstallLLPatch(nh);
418 return(TRUE);
420 case UCM_ConfigChangedEvent:
421 GM_UNIQUENAME(nLoadClassConfig)(nh);
423 Forbid();
424 nch = (struct NepClassHid *) nh->nh_Interfaces.lh_Head;
425 while(nch->nch_Node.ln_Succ)
427 GM_UNIQUENAME(nLoadBindingConfig)(nch, TRUE);
428 nch = (struct NepClassHid *) nch->nch_Node.ln_Succ;
430 Permit();
431 return(TRUE);
433 case UCM_AttemptSuspendDevice:
434 nch = (struct NepClassHid *) methoddata[0];
435 nch->nch_Running = FALSE;
436 return(TRUE);
438 case UCM_AttemptResumeDevice:
439 nch = (struct NepClassHid *) methoddata[0];
440 nch->nch_Running = TRUE;
441 Signal(nch->nch_Task, (1L<<nch->nch_TaskMsgPort->mp_SigBit));
442 return(TRUE);
444 default:
445 break;
447 return(0);
448 AROS_LIBFUNC_EXIT
450 /* \\\ */
452 /* /// "nInstallLLPatch()" */
453 void nInstallLLPatch(struct NepHidBase *nh)
455 if(!nh->nh_LowLevelBase)
457 if((nh->nh_LowLevelBase = OpenLibrary("lowlevel.library", 40)))
459 Disable();
460 nh->nh_LLOldReadJoyPort = SetFunction(nh->nh_LowLevelBase, -5 * LIB_VECTSIZE, AROS_SLIB_ENTRY(nReadJoyPort, hid, 5));
461 nh->nh_LLOldSetJoyPortAttrsA = SetFunction(nh->nh_LowLevelBase, -22 * LIB_VECTSIZE, AROS_SLIB_ENTRY(nSetJoyPortAttrsA, hid, 22));
462 Enable();
466 /* \\\ */
468 /* /// "nLoadClassConfig()" */
469 BOOL GM_UNIQUENAME(nLoadClassConfig)(struct NepHidBase *nh)
471 struct NepClassHid *nch = &nh->nh_DummyNCH;
472 struct Library *ps;
473 struct KeymapCfg *kmc;
474 struct ClsDevCfg *cdc;
475 struct PsdIFFContext *pic;
477 KPRINTF(10, ("Loading Class Config...\n"));
478 if(nch->nch_GUITask)
480 return(FALSE);
482 if(!(ps = OpenLibrary("poseidon.library", 4)))
484 return(FALSE);
487 Forbid();
488 /* Create default config */
489 kmc = &nch->nch_KeymapCfg;
490 kmc->kmc_ChunkID = AROS_LONG2BE(MAKE_ID('K','M','A','P'));
491 kmc->kmc_Length = AROS_LONG2BE(sizeof(struct KeymapCfg)-8);
492 CopyMemQuick(usbkeymap, kmc->kmc_Keymap, AROS_LONG2BE(kmc->kmc_Length));
494 cdc = nch->nch_CDC;
495 cdc->cdc_ChunkID = AROS_LONG2BE(MAKE_ID('H','I','D','C'));
496 cdc->cdc_Length = AROS_LONG2BE(sizeof(struct ClsDevCfg)-8);
497 cdc->cdc_EnableKBReset = TRUE;
498 cdc->cdc_EnableRH = TRUE;
499 cdc->cdc_ResetDelay = 10;
500 cdc->cdc_ShellStack = AROS_STACKSIZE;
501 strcpy(cdc->cdc_ShellCon, "CON:///130/HID Rocket Bay/CLOSE/AUTO/WAIT");
502 cdc->cdc_PollingMode = FALSE;
503 cdc->cdc_LLPortMode[1] = 2;
504 cdc->cdc_HIDCtrlOpen = FALSE;
505 strcpy(cdc->cdc_HIDCtrlRexx, "HIDCTRL");
506 strcpy(cdc->cdc_HIDCtrlTitle, "HID Control");
507 cdc->cdc_LLRumblePort = 2;
508 cdc->cdc_TurboMouse = 0;
510 nch->nch_UsingDefaultCfg = TRUE;
511 /* try to load default config */
512 pic = psdGetClsCfg(GM_UNIQUENAME(libname));
513 if(pic)
515 cdc = psdGetCfgChunk(pic, AROS_LONG2BE(nch->nch_CDC->cdc_ChunkID));
516 if(cdc)
518 CopyMem(((UBYTE *) cdc) + 8, ((UBYTE *) nch->nch_CDC) + 8, min(AROS_LONG2BE(cdc->cdc_Length), AROS_LONG2BE(nch->nch_CDC->cdc_Length)));
519 psdFreeVec(cdc);
520 nch->nch_UsingDefaultCfg = FALSE;
522 kmc = psdGetCfgChunk(pic, AROS_LONG2BE(nch->nch_KeymapCfg.kmc_ChunkID));
523 if(kmc)
525 CopyMem(((UBYTE *) kmc) + 8, ((UBYTE *) &nch->nch_KeymapCfg) + 8, min(AROS_LONG2BE(kmc->kmc_Length), AROS_LONG2BE(nch->nch_KeymapCfg.kmc_Length)));
526 psdFreeVec(kmc);
527 nch->nch_UsingDefaultCfg = FALSE;
530 Permit();
531 CloseLibrary(ps);
532 return(FALSE);
534 /* \\\ */
536 /* /// "nCalcConfigCRC()" */
537 ULONG nCalcConfigCRC(struct NepClassHid *nch, struct Library *ps, struct PsdIFFContext *pic)
539 ULONG *buf = (ULONG *) psdWriteCfg(pic);
540 ULONG crc = 0;
541 if(buf)
543 UWORD *ptr = (UWORD *) buf;
544 ULONG len = (AROS_LONG2BE(buf[1]) + 8)>>1;
545 crc = len;
546 if(len)
550 crc = ((crc<<1)|(crc>>31))^(*ptr++);
551 } while(--len);
553 psdFreeVec(buf);
555 return(crc);
557 /* \\\ */
559 /* /// "nLoadBindingConfig()" */
560 BOOL GM_UNIQUENAME(nLoadBindingConfig)(struct NepClassHid *nch, BOOL gui)
562 struct NepHidBase *nh = nch->nch_ClsBase;
563 struct Library *ps;
564 struct ClsDevCfg *cdc;
565 struct KeymapCfg *kmc;
566 struct PsdIFFContext *pic;
567 ULONG crc = 0;
569 KPRINTF(10, ("Loading Binding Config...\n"));
570 if(nch->nch_GUITask)
572 return(FALSE);
574 //GM_UNIQUENAME(nLoadClassConfig)(nh);
575 *nch->nch_CDC = *nh->nh_DummyNCH.nch_CDC;
576 nch->nch_KeymapCfg = nh->nh_DummyNCH.nch_KeymapCfg;
577 nch->nch_UsingDefaultCfg = TRUE;
579 if(!(ps = OpenLibrary("poseidon.library", 4)))
581 return(FALSE);
584 Forbid();
585 /* Load config */
586 pic = psdGetUsbDevCfg(GM_UNIQUENAME(libname), nch->nch_DevIDString, nch->nch_IfIDString);
587 if(pic)
589 cdc = psdGetCfgChunk(pic, AROS_LONG2BE(nch->nch_CDC->cdc_ChunkID));
590 if(cdc)
592 CopyMem(((UBYTE *) cdc) + 8, ((UBYTE *) nch->nch_CDC) + 8, min(AROS_LONG2BE(cdc->cdc_Length), AROS_LONG2BE(nch->nch_CDC->cdc_Length)));
593 psdFreeVec(cdc);
594 nch->nch_UsingDefaultCfg = FALSE;
596 kmc = psdGetCfgChunk(pic, AROS_LONG2BE(nch->nch_KeymapCfg.kmc_ChunkID));
597 if(kmc)
599 CopyMem(((UBYTE *) kmc) + 8, ((UBYTE *) &nch->nch_KeymapCfg) + 8, min(AROS_LONG2BE(kmc->kmc_Length), AROS_LONG2BE(nch->nch_KeymapCfg.kmc_Length)));
600 psdFreeVec(kmc);
601 nch->nch_UsingDefaultCfg = FALSE;
603 crc = nCalcConfigCRC(nch, ps, pic);
605 if(crc != nch->nch_LastCfgCRC)
607 nch->nch_ReloadCfg = TRUE;
608 nch->nch_LastCfgCRC = crc;
609 if(nch->nch_Task)
611 Signal(nch->nch_Task, (1L<<nch->nch_TaskMsgPort->mp_SigBit));
614 if(gui && !nch->nch_HCGUITask)
616 psdSpawnSubTask(MOD_NAME_STRING " Control GUI", GM_UNIQUENAME(nHIDCtrlGUITask), nch);
618 Permit();
619 CloseLibrary(ps);
620 return(FALSE);
622 /* \\\ */
624 /* /// "nOpenBindingCfgWindow()" */
625 LONG GM_UNIQUENAME(nOpenBindingCfgWindow)(struct NepHidBase *nh, struct NepClassHid *nch)
627 struct Library *ps;
628 KPRINTF(10, ("Opening GUI...\n"));
629 if(!(ps = OpenLibrary("poseidon.library", 4)))
631 return(FALSE);
633 Forbid();
634 if(!nch->nch_GUITask)
636 if((nch->nch_GUITask = psdSpawnSubTask(MOD_NAME_STRING " GUI", GM_UNIQUENAME(nGUITask), nch)))
638 Permit();
639 CloseLibrary(ps);
640 return(TRUE);
643 Permit();
644 CloseLibrary(ps);
645 return(FALSE);
647 /* \\\ */
649 /**************************************************************************/
651 /* /// "Keymap Table" */
652 UBYTE usbkeymap[256] =
654 0xff, 0xff, 0xff, 0xff, 0x20, 0x35, 0x33, 0x22, /* 0x00 */
655 0x12, 0x23, 0x24, 0x25, 0x17, 0x26, 0x27, 0x28, /* 0x08 */
656 0x37, 0x36, 0x18, 0x19, 0x10, 0x13, 0x21, 0x14, /* 0x10 */
657 0x16, 0x34, 0x11, 0x32, 0x15, 0x31, 0x01, 0x02, /* 0x18 */
658 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, /* 0x20 */
659 0x44, 0x45, 0x41, 0x42, 0x40, 0x0b, 0x0c, 0x1a, /* 0x28 */
660 0x1b, 0x0d, 0x2b, 0x29, 0x2a, 0x00, 0x38, 0x39, /* 0x30 */
661 0x3a, 0x62, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, /* 0x38 */
662 0x56, 0x57, 0x58, 0x59, 0x5f, 0x67, 0xff, 0xff, /* 0x40 */
663 0x6e, 0x47, 0x70, 0x48, 0x46, 0x71, 0x49, 0x4e, /* 0x48 */
664 0x4f, 0x4d, 0x4c, 0xff, 0x5c, 0x5d, 0x4a, 0x5e, /* 0x50 */
665 0x43, 0x1d, 0x1e, 0x1f, 0x2d, 0x2e, 0x2f, 0x3d, /* 0x58 */
666 0x3e, 0x3f, 0x0f, 0x3c, 0x30, 0x67, 0xff, 0xff, /* 0x60 */
667 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x68 F13-F24 */
668 0xff, 0xff, 0xff, 0xff, 0xff, 0x5f, 0xff, 0xff, /* 0x70 */
669 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x78 */
670 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x80 */
671 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x88 */
672 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x90 */
673 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x44, 0xff, /* 0x98 */
674 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xa0 */
675 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xa8 */
676 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */
677 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb8 */
678 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xc0 */
679 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xc8 */
680 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xd0 */
681 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xd8 */
682 0x63, 0x60, 0x64, 0x66, 0x63, 0x61, 0x65, 0x67, /* 0xe0 */
683 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xe8 */
684 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xf0 */
685 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* 0xf8 */
688 /* \\\ */
690 #undef ps
691 #define ps nch->nch_Base
693 /* /// "nHidTask()" */
694 AROS_UFH0(void, GM_UNIQUENAME(nHidTask))
696 AROS_USERFUNC_INIT
698 struct NepClassHid *nch;
699 struct PsdPipe *pp;
700 ULONG sigmask;
701 ULONG sigs;
702 UBYTE *buf;
703 UBYTE *bufreal;
704 ULONG buflen;
705 LONG ioerr;
706 BOOL wacomgood;
707 LONG lastioerr = 0;
708 ULONG errcount = 0;
710 UWORD reportid;
711 UWORD count;
712 struct NepHidReport *nhr;
713 struct NepHidItem **nhiptr;
714 struct NepHidItem *nhi;
716 if((nch = GM_UNIQUENAME(nAllocHid())))
718 Forbid();
719 if(nch->nch_ReadySigTask)
721 Signal(nch->nch_ReadySigTask, 1L<<nch->nch_ReadySignal);
723 Permit();
724 sigmask = (1L<<nch->nch_TaskMsgPort->mp_SigBit)|SIGBREAKF_CTRL_C;
726 pp = nch->nch_EP0Pipe;
727 /* initial output states */
728 #if 0
729 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
730 while(nhr->nhr_Node.ln_Succ)
732 if(nhr->nhr_OutItemCount)
734 bufreal = nch->nch_EPOutBuf;
735 if(nch->nch_UsesReportID)
737 bufreal++;
738 psdPipeSetup(pp, URTF_IN|URTF_CLASS|URTF_INTERFACE,
739 UHR_GET_REPORT, (ULONG) nhr->nhr_ReportID|0x0200, nch->nch_IfNum);
740 } else {
741 psdPipeSetup(pp, URTF_IN|URTF_CLASS|URTF_INTERFACE,
742 UHR_GET_REPORT, 0x0200, nch->nch_IfNum);
744 if((ioerr = psdDoPipe(pp, nch->nch_EPOutBuf, (nhr->nhr_ReportOutSize+7)>>3)))
746 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
747 "GET_REPORT(%lx, %ld) failed: %s (%ld)!",
748 nhr->nhr_ReportID|0x0200, (nhr->nhr_ReportOutSize+7)>>3,
749 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
750 } else {
751 count = nhr->nhr_OutItemCount;
752 nhiptr = nhr->nhr_OutItemMap;
753 if(nhiptr)
757 nhi = *nhiptr++;
758 nProcessItem(nch, nhi, bufreal);
759 } while(--count);
760 } else {
761 KPRINTF(10, ("Huh? report %ld, nhiptr == NULL!\n", nhr->nhr_ReportID));
765 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
767 #endif
769 if(nch->nch_XtraInitItem)
771 struct NepHidAction *nha = (struct NepHidAction *) nch->nch_XtraInitItem->nhi_ActionList.lh_Head;
772 while(nha->nha_Node.ln_Succ)
774 KPRINTF(1, ("Executing InitItem %08lx\n", nha));
775 nDoAction(nch, nha, nch->nch_XtraInitItem, 0, 1, TRUE);
776 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
779 nFlushEvents(nch);
781 Forbid();
782 if(!nch->nch_HCGUITask)
784 psdSpawnSubTask(MOD_NAME_STRING " Control GUI", GM_UNIQUENAME(nHIDCtrlGUITask), nch);
786 Permit();
788 buf = nch->nch_EPInBuf;
789 //nch->nch_CDC->cdc_PollingMode = TRUE;
790 if(!nch->nch_HasInItems)
792 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "HID Device has no input items, input polling disabled.");
794 nch->nch_ReloadCfg = FALSE;
795 nch->nch_Running = TRUE;
796 nch->nch_IOStarted = FALSE;
799 if(nch->nch_CDC->cdc_PollingMode)
801 sigs = SetSignal(0, 0);
802 #if 0
803 UWORD rptcount;
804 sigs = SetSignal(0, 0);
805 pp = nch->nch_EP0Pipe;
806 for(rptcount = 0; rptcount <= nch->nch_MaxReportID; rptcount++)
808 if(nch->nch_ReportMap[rptcount])
810 if(nch->nch_UsesReportID)
812 psdPipeSetup(pp, URTF_IN|URTF_CLASS|URTF_INTERFACE,
813 UHR_GET_REPORT, (ULONG) rptcount|0x0100, nch->nch_IfNum);
814 } else {
815 psdPipeSetup(pp, URTF_IN|URTF_CLASS|URTF_INTERFACE,
816 UHR_GET_REPORT, 0x0100, nch->nch_IfNum);
818 ioerr = psdDoPipe(pp, buf, nch->nch_MaxInSize);
819 if((!ioerr) || (ioerr == UHIOERR_RUNTPACKET))
821 buflen = psdGetPipeActual(pp);
822 if(nch->nch_UsesReportID)
824 reportid = buf[0];
825 bufreal = &buf[1];
826 } else {
827 reportid = 0;
828 bufreal = buf;
830 if(reportid <= nch->nch_MaxReportID)
832 if((nhr = nch->nch_ReportMap[reportid]))
834 KPRINTF(40, ("Report %ld\n", reportid));
835 count = nhr->nhr_InItemCount;
836 nhiptr = nhr->nhr_InItemMap;
837 if(count && nhiptr)
841 if((nhi = *nhiptr++))
843 nProcessItem(nch, nhi, bufreal);
844 } else {
845 KPRINTF(10, ("Huh? Hole in Item Lookup Map!\n"));
847 } while(--count);
848 } else {
849 KPRINTF(10, ("Huh? report %ld, count %ld or nhiptr == NULL!\n", reportid, count));
851 } else {
852 KPRINTF(10, ("Illegal report ID %ld received!\n", reportid));
855 } else {
856 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
857 "GET_REPORT(%lx, %ld) failed: %s (%ld)!",
858 rptcount, nch->nch_MaxInSize,
859 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
860 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
861 "Reverting back to interrupt mode instead of polling!");
863 nch->nch_CDC->cdc_PollingMode = FALSE;
864 if(nch->nch_Running)
866 psdSendPipe(nch->nch_EPInPipe, buf, nch->nch_MaxInSize);
867 nch->nch_IOStarted = TRUE;
869 break;
873 psdDelayMS(nch->nch_EPInInterval);
874 #endif
875 } else {
876 if(nch->nch_Running && (!nch->nch_IOStarted) && nch->nch_HasInItems)
878 psdSendPipe(nch->nch_EPInPipe, buf, nch->nch_MaxInSize);
879 nch->nch_IOStarted = TRUE;
881 sigs = Wait(sigmask);
882 while((pp = (struct PsdPipe *) GetMsg(nch->nch_TaskMsgPort)))
884 if(pp == nch->nch_EPInPipe)
886 nch->nch_IOStarted = FALSE;
887 ioerr = psdGetPipeError(pp);
888 if((!ioerr) || (ioerr == UHIOERR_RUNTPACKET))
890 buflen = psdGetPipeActual(pp);
891 wacomgood = FALSE;
892 errcount = 0;
893 if(nch->nch_WacomMode)
895 wacomgood = nParseWacom(nch, buf, buflen);
897 if(!wacomgood)
899 // if the parser failed, use standard methods
900 if(nch->nch_UsesReportID)
902 reportid = buf[0];
903 bufreal = &buf[1];
904 } else {
905 reportid = 0;
906 bufreal = buf;
908 if(reportid <= nch->nch_MaxReportID)
910 if((nhr = nch->nch_ReportMap[reportid]))
912 KPRINTF(40, ("Report %ld\n", reportid));
913 count = nhr->nhr_InItemCount;
914 nhiptr = nhr->nhr_InItemMap;
915 if(count && nhiptr)
919 if((nhi = *nhiptr++))
921 nProcessItem(nch, nhi, bufreal);
922 } else {
923 KPRINTF(10, ("Huh? Hole in Item Lookup Map!\n"));
925 } while(--count);
926 } else {
927 KPRINTF(10, ("Huh? count or nhiptr == NULL!\n"));
930 } else {
931 KPRINTF(10, ("Illegal report ID %ld received!\n", reportid));
935 //dumpmem(buf, buflen);
936 } else {
937 KPRINTF(10, ("Int Pipe failed %ld\n", ioerr));
938 if(nch->nch_Running)
940 if(lastioerr != ioerr)
942 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
943 "Interrupt pipe failed: %s (%ld)!",
944 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
945 errcount = 0;
946 } else {
947 errcount++;
948 if(errcount > 20)
950 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
951 "That's it, that device pissed me off long enough!");
952 sigs |= SIGBREAKF_CTRL_C;
955 lastioerr = ioerr;
957 IPTR epnum;
958 psdGetAttrs(PGA_ENDPOINT, nch->nch_EPIn,
959 EA_EndpointNum, &epnum,
960 TAG_END);
961 psdPipeSetup(nch->nch_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
962 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) epnum|URTF_IN);
963 ioerr = psdDoPipe(nch->nch_EP0Pipe, NULL, 0);
965 psdDelayMS(50);
971 nFlushEvents(nch);
972 if(nch->nch_TrackEvents || nch->nch_TrackKeyEvents || (nch->nch_ReportValues && nch->nch_ItemChanged))
974 if(nch->nch_GUITask)
976 Signal(nch->nch_GUITask, (ULONG) (1<<nch->nch_TrackingSignal));
979 if(!nch->nch_HIntBase) /* attempt to open intuition */
981 nch->nch_HIntBase = OpenLibrary("intuition.library", 39);
984 /* need to update prefs? */
985 if(nch->nch_ReloadCfg)
987 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Reloading configuration...");
988 Forbid();
989 nch->nch_ReadySignal = SIGB_SINGLE;
990 nch->nch_ReadySigTask = FindTask(NULL);
991 if(nch->nch_GUITask)
993 Signal(nch->nch_GUITask, SIGBREAKF_CTRL_C);
995 Permit();
996 while(nch->nch_GUITask)
998 Wait(1L<<nch->nch_ReadySignal);
1000 Forbid();
1001 if(nch->nch_HCGUITask)
1003 Signal(nch->nch_HCGUITask, SIGBREAKF_CTRL_C);
1005 Permit();
1006 while(nch->nch_HCGUITask)
1008 Wait(1L<<nch->nch_ReadySignal);
1010 //FreeSignal(nch->nch_ReadySignal);
1011 Forbid();
1012 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
1013 while(nhr->nhr_Node.ln_Succ)
1015 nFreeReport(nch, nhr);
1016 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
1018 psdFreeVec(nch->nch_ReportMap);
1019 nch->nch_ReportMap = NULL;
1020 psdFreeVec(nch->nch_HidDesc);
1021 nch->nch_HidDesc = NULL;
1022 Permit();
1023 if(nReadReports(nch))
1025 nAddExtraReport(nch);
1026 nDetectWacom(nch);
1027 } else {
1028 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname), "Error parsing report descriptors!");
1029 sigs |= SIGBREAKF_CTRL_C;
1031 nch->nch_ReloadCfg = FALSE;
1033 } while(!(sigs & SIGBREAKF_CTRL_C));
1034 if(nch->nch_XtraQuitItem)
1036 struct NepHidAction *nha = (struct NepHidAction *) nch->nch_XtraQuitItem->nhi_ActionList.lh_Head;
1037 while(nha->nha_Node.ln_Succ)
1039 nDoAction(nch, nha, nch->nch_XtraQuitItem, 0, 1, TRUE);
1040 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
1044 KPRINTF(20, ("Going down the river!\n"));
1045 if(nch->nch_IOStarted)
1047 psdAbortPipe(nch->nch_EPInPipe);
1048 psdWaitPipe(nch->nch_EPInPipe);
1050 GM_UNIQUENAME(nFreeHid)(nch);
1053 AROS_USERFUNC_EXIT
1055 /* \\\ */
1057 /* /// "nAllocHid()" */
1058 struct NepClassHid * GM_UNIQUENAME(nAllocHid)(void)
1060 struct Task *thistask;
1061 struct NepClassHid *nch;
1062 LONG ioerr;
1063 IPTR subclass;
1064 IPTR protocol;
1066 thistask = FindTask(NULL);
1067 #undef IntuitionBase
1068 nch = thistask->tc_UserData;
1070 NewList(&nch->nch_HidReports);
1073 if(!(nch->nch_Base = OpenLibrary("poseidon.library", 4)))
1075 Alert(AG_OpenLib);
1076 break;
1078 if(!(nch->nch_HIntBase = OpenLibrary("intuition.library", 39)))
1080 /* we don't mind anymore */
1081 //Alert(AG_OpenLib|AO_Intuition);
1082 //break;
1084 #define IntuitionBase nch->nch_HIntBase
1085 psdGetAttrs(PGA_INTERFACE, nch->nch_Interface,
1086 IFA_Config, &nch->nch_Config,
1087 IFA_InterfaceNum, &nch->nch_IfNum,
1088 IFA_SubClass, &subclass,
1089 IFA_Protocol, &protocol,
1090 TAG_END);
1091 psdGetAttrs(PGA_CONFIG, nch->nch_Config,
1092 CA_Device, &nch->nch_Device,
1093 TAG_END);
1095 nch->nch_EPIn = psdFindEndpoint(nch->nch_Interface, NULL,
1096 EA_IsIn, TRUE,
1097 EA_TransferType, USEAF_INTERRUPT,
1098 TAG_END);
1099 nch->nch_EPOut = psdFindEndpoint(nch->nch_Interface, NULL,
1100 EA_IsIn, FALSE,
1101 EA_TransferType, USEAF_INTERRUPT,
1102 TAG_END);
1104 if((nch->nch_InpMsgPort = CreateMsgPort()))
1106 if((nch->nch_InpIOReq = (struct IOStdReq *) CreateIORequest(nch->nch_InpMsgPort, sizeof(struct IOStdReq))))
1108 if(!OpenDevice("input.device", 0, (struct IORequest *) nch->nch_InpIOReq, 0))
1110 nch->nch_InputBase = (struct Library *) nch->nch_InpIOReq->io_Device;
1111 #define InputBase nch->nch_InputBase
1112 nch->nch_OS4Hack = TRUE;
1113 nch->nch_ClsBase->nh_OS4Hack = TRUE;
1114 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1115 "Using AROS IND_ADDEVENT workaround to fix some mouse & keyboard problems.");
1117 if((nch->nch_TaskMsgPort = CreateMsgPort()))
1119 if((nch->nch_EP0Pipe = psdAllocPipe(nch->nch_Device, nch->nch_TaskMsgPort, NULL)))
1121 psdSetAttrs(PGA_PIPE, nch->nch_EP0Pipe,
1122 PPA_NakTimeout, TRUE,
1123 PPA_NakTimeoutTime, 5000,
1124 TAG_END);
1125 if(nch->nch_EPIn)
1127 psdGetAttrs(PGA_ENDPOINT, nch->nch_EPIn,
1128 EA_Interval, &nch->nch_EPInInterval,
1129 TAG_END);
1131 if((nch->nch_EPInPipe = psdAllocPipe(nch->nch_Device, nch->nch_TaskMsgPort, nch->nch_EPIn)))
1133 if(nch->nch_CDC->cdc_TurboMouse)
1135 psdSetAttrs(PGA_PIPE, nch->nch_EPInPipe,
1136 PPA_Interval, 1<<nch->nch_CDC->cdc_TurboMouse,
1137 PPA_AllowRuntPackets, TRUE,
1138 TAG_END);
1141 } else {
1142 nch->nch_EPInPipe = NULL;
1144 if(subclass == HID_BOOT_SUBCLASS)
1146 psdPipeSetup(nch->nch_EP0Pipe, URTF_CLASS|URTF_INTERFACE,
1147 UHR_SET_IDLE, (ULONG) ((protocol == HID_PROTO_KEYBOARD) ? 64 : 0), nch->nch_IfNum);
1148 ioerr = psdDoPipe(nch->nch_EP0Pipe, NULL, 0);
1149 if(ioerr)
1151 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1152 "SET_IDLE=0 failed: %s (%ld)!",
1153 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1156 psdPipeSetup(nch->nch_EP0Pipe, URTF_CLASS|URTF_INTERFACE,
1157 UHR_SET_PROTOCOL, HID_PROTO_REPORT, nch->nch_IfNum);
1158 ioerr = psdDoPipe(nch->nch_EP0Pipe, NULL, 0);
1159 if(ioerr)
1161 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1162 "SET_PROTOCOL=REPORT failed: %s (%ld)!",
1163 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1166 #if 0
1168 IPTR epnum;
1169 psdGetAttrs(PGA_ENDPOINT, nch->nch_EPIn,
1170 EA_EndpointNum, &epnum,
1171 TAG_END);
1172 psdPipeSetup(nch->nch_EP0Pipe, URTF_STANDARD|URTF_ENDPOINT,
1173 USR_CLEAR_FEATURE, UFS_ENDPOINT_HALT, (ULONG) epnum|URTF_IN);
1174 ioerr = psdDoPipe(nch->nch_EP0Pipe, NULL, 0);
1175 if(ioerr)
1177 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
1178 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
1179 epnum, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1182 #endif
1183 nQuirkPS3Controller(nch);
1185 if(nReadReports(nch))
1187 BOOL fail = FALSE;
1188 nAddExtraReport(nch);
1189 nDetectWacom(nch);
1190 if(!nch->nch_EPInPipe)
1192 if(nch->nch_HasInItems)
1194 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
1195 "This device does not have an interrupt IN endpoint, but it needs one for input items!");
1196 fail = TRUE;
1197 } else {
1198 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "This device does not have an interrupt IN endpoint!");
1199 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "This means it can only be used for OUTPUT, if at all. Check your HID Control window!");
1202 if(!fail)
1204 if((nch->nch_EPInBuf = psdAllocVec(nch->nch_MaxInSize)))
1206 if((nch->nch_EPOutBuf = psdAllocVec(nch->nch_MaxReportSize)))
1208 nch->nch_Task = thistask;
1209 return(nch);
1211 psdFreeVec(nch->nch_EPInBuf);
1214 } else {
1215 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname), "Error parsing report descriptors!");
1217 psdFreePipe(nch->nch_EPInPipe);
1218 psdFreePipe(nch->nch_EP0Pipe);
1220 DeleteMsgPort(nch->nch_TaskMsgPort);
1222 CloseDevice((struct IORequest *) nch->nch_InpIOReq);
1224 DeleteIORequest((struct IORequest *) nch->nch_InpIOReq);
1226 DeleteMsgPort(nch->nch_InpMsgPort);
1228 } while(FALSE);
1229 CloseLibrary(nch->nch_HIntBase);
1230 CloseLibrary(nch->nch_Base);
1231 Forbid();
1232 nch->nch_Task = NULL;
1233 if(nch->nch_ReadySigTask)
1235 Signal(nch->nch_ReadySigTask, 1L<<nch->nch_ReadySignal);
1237 return(NULL);
1239 /* \\\ */
1241 /* /// "nFreeHid()" */
1242 void GM_UNIQUENAME(nFreeHid)(struct NepClassHid *nch)
1244 struct NepHidReport *nhr;
1245 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
1246 while(nhr->nhr_Node.ln_Succ)
1248 nFreeReport(nch, nhr);
1249 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
1251 psdFreeVec(nch->nch_ReportMap);
1252 psdFreeVec(nch->nch_HidDesc);
1253 psdFreeVec(nch->nch_EPInBuf);
1254 psdFreeVec(nch->nch_EPOutBuf);
1255 psdFreePipe(nch->nch_EPInPipe);
1256 psdFreePipe(nch->nch_EP0Pipe);
1257 DeleteMsgPort(nch->nch_TaskMsgPort);
1258 CloseDevice((struct IORequest *) nch->nch_InpIOReq);
1259 DeleteIORequest((struct IORequest *) nch->nch_InpIOReq);
1260 DeleteMsgPort(nch->nch_InpMsgPort);
1261 CloseLibrary(nch->nch_HIntBase);
1262 CloseLibrary(nch->nch_Base);
1263 Forbid();
1264 nch->nch_Task = NULL;
1265 if(nch->nch_ReadySigTask)
1267 Signal(nch->nch_ReadySigTask, 1L<<nch->nch_ReadySignal);
1270 /* \\\ */
1272 /* /// "nFreeItem()" */
1273 void nFreeItem(struct NepClassHid *nch, struct NepHidItem *nhi)
1275 struct NepHidAction *nha;
1276 struct List *lst;
1277 ULONG count;
1279 Remove(&nhi->nhi_Node);
1280 psdFreeVec(nhi->nhi_UsageMap);
1281 /* Oh, this was an array */
1282 if((lst = nhi->nhi_ActionMap))
1284 /* We need to free all lists available */
1285 count = nhi->nhi_MapSize;
1288 /* And each list can have several entries */
1289 nha = (struct NepHidAction *) lst->lh_Head;
1290 while(nha->nha_Node.ln_Succ)
1292 Remove(&nha->nha_Node);
1293 psdFreeVec(nha);
1294 nha = (struct NepHidAction *) lst->lh_Head;
1296 lst++;
1297 } while(--count);
1298 psdFreeVec(nhi->nhi_ActionMap);
1300 /* Free action list */
1301 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
1302 while(nha->nha_Node.ln_Succ)
1304 Remove(&nha->nha_Node);
1305 psdFreeVec(nha);
1306 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
1308 psdFreeVec(nhi->nhi_Buffer);
1309 psdFreeVec(nhi);
1311 /* \\\ */
1313 /* /// "nCleanCollection()" */
1314 void nCleanCollection(struct NepClassHid *nch, struct NepHidCollection *nhc)
1316 struct NepHidItem *nhi;
1317 struct NepHidAction *nha;
1318 struct List *lst;
1319 ULONG count;
1321 nhi = (struct NepHidItem *) nhc->nhc_Items.lh_Head;
1322 while(nhi->nhi_Node.ln_Succ)
1324 /* Oh, this was an array */
1325 if((lst = nhi->nhi_ActionMap))
1327 /* We need to free all lists available */
1328 count = nhi->nhi_MapSize;
1331 /* And each list can have several entries */
1332 nha = (struct NepHidAction *) lst->lh_Head;
1333 while(nha->nha_Node.ln_Succ)
1335 Remove(&nha->nha_Node);
1336 psdFreeVec(nha);
1337 nha = (struct NepHidAction *) lst->lh_Head;
1339 lst++;
1340 } while(--count);
1342 /* Free action list */
1343 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
1344 while(nha->nha_Node.ln_Succ)
1346 Remove(&nha->nha_Node);
1347 psdFreeVec(nha);
1348 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
1350 nhi = (struct NepHidItem *) nhi->nhi_Node.ln_Succ;
1353 /* \\\ */
1355 /* /// "nFreeReport()" */
1356 void nFreeReport(struct NepClassHid *nch, struct NepHidReport *nhr)
1358 struct NepHidCollection *nhc;
1359 struct NepHidItem *nhi;
1361 Remove(&nhr->nhr_Node);
1362 nhc = (struct NepHidCollection *) nhr->nhr_Collections.lh_Head;
1363 while(nhc->nhc_Node.ln_Succ)
1365 Remove(&nhc->nhc_Node);
1366 nhi = (struct NepHidItem *) nhc->nhc_Items.lh_Head;
1367 while(nhi->nhi_Node.ln_Succ)
1369 nFreeItem(nch, nhi);
1370 nhi = (struct NepHidItem *) nhc->nhc_Items.lh_Head;
1372 psdFreeVec(nhc->nhc_Name);
1373 psdFreeVec(nhc);
1374 nhc = (struct NepHidCollection *) nhr->nhr_Collections.lh_Head;
1376 psdFreeVec(nhr->nhr_InItemMap);
1377 psdFreeVec(nhr->nhr_ReportBuf);
1378 psdFreeVec(nhr);
1380 /* \\\ */
1382 /* /// "nAddItemAction()" */
1383 void nAddItemAction(struct NepClassHid *nch, struct PsdIFFContext *rppic, struct NepHidItem *nhi, UWORD id)
1385 struct NepHidCollection *nhc = nhi->nhi_Collection;
1386 NewList(&nhi->nhi_ActionList);
1387 SET_WTYPE(&nhi->nhi_ActionList, id + 0xf001);
1388 AddTail(&nhc->nhc_Items, &nhi->nhi_Node);
1389 if(rppic)
1391 if(!nLoadItem(nch, rppic, &nhi->nhi_ActionList, 0xf001))
1393 nDetectDefaultAction(nch, nhi, &nhi->nhi_ActionList, nhc, nhi->nhi_Usage);
1395 } else {
1396 nDetectDefaultAction(nch, nhi, &nhi->nhi_ActionList, nhc, nhi->nhi_Usage);
1399 /* \\\ */
1401 /* /// "nAddExtraReport()" */
1402 BOOL nAddExtraReport(struct NepClassHid *nch)
1404 struct NepHidCollection *nhc;
1405 struct NepHidReport *nhr;
1406 struct NepHidItem *nhi;
1407 struct PsdIFFContext *pic;
1408 struct PsdIFFContext *rppic = NULL;
1409 UWORD item;
1410 ULONG pos;
1412 /* find rumble motors for rumble pack */
1413 if((item = nFindItemUsage(nch, 0x080045, REPORT_MAIN_OUTPUT)))
1415 nch->nch_RumbleMotors[0] = nFindItemID(nch, item, REPORT_MAIN_OUTPUT, &pos);
1417 if((item = nFindItemUsage(nch, 0x080046, REPORT_MAIN_OUTPUT)))
1419 nch->nch_RumbleMotors[1] = nFindItemID(nch, item, REPORT_MAIN_OUTPUT, &pos);
1422 pic = psdGetUsbDevCfg(GM_UNIQUENAME(libname), nch->nch_DevIDString, nch->nch_IfIDString);
1423 if(pic)
1425 rppic = psdFindCfgForm(pic, MAKE_ID('X','R','P','T'));
1427 if((nhr = psdAllocVec(sizeof(struct NepHidReport))))
1429 NewList(&nhr->nhr_Collections);
1430 AddTail(&nch->nch_HidReports, &nhr->nhr_Node);
1431 nhr->nhr_ReportID = 0xffff;
1432 nhr->nhr_ItemIDBase = 0xf001;
1433 if((nhc = psdAllocVec(sizeof(struct NepHidCollection))))
1435 NewList(&nhc->nhc_Items);
1436 AddTail(&nhr->nhr_Collections, &nhc->nhc_Node);
1437 nhc->nhc_Report = nhr;
1438 nhc->nhc_Name = psdCopyStr("[Extra]");
1439 if((nhi = psdAllocVec(sizeof(struct NepHidItem))))
1441 nhi->nhi_Collection = nhc;
1442 nhi->nhi_Type = REPORT_MAIN_INPUT;
1443 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1445 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = 0;
1446 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = 1;
1447 nhi->nhi_Usage = 0x1fff0;
1448 nAddItemAction(nch, rppic, nhi, 0xff0);
1449 nch->nch_XtraInitItem = nhi;
1451 if((nhi = psdAllocVec(sizeof(struct NepHidItem))))
1453 nhi->nhi_Collection = nhc;
1454 nhi->nhi_Type = REPORT_MAIN_INPUT;
1455 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1457 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = 0;
1458 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = 1;
1459 nhi->nhi_Usage = 0x1fff1;
1460 nAddItemAction(nch, rppic, nhi, 0xff1);
1461 nch->nch_XtraQuitItem = nhi;
1466 return(FALSE);
1468 /* \\\ */
1470 /* /// "Wacom Tables" */
1472 static struct WacomCaps WacomCapsTable[] =
1474 { 0x0000, WACOM_PENPARTNER, 5040, 3780, 8, "PenPartner" },
1475 { 0x0003, WACOM_PLX, 20480, 15360, 9, "Cintiq Partner" },
1476 { 0x0010, WACOM_GRAPHIRE, 10206, 7422, 9, "Graphire" },
1477 { 0x0011, WACOM_GRAPHIRE, 10206, 7422, 9, "Graphire 2 4x5" },
1478 { 0x0012, WACOM_GRAPHIRE, 13918, 10206, 9, "Graphire 2 5x7" },
1479 { 0x0013, WACOM_GRAPHIRE, 10208, 7424, 9, "Graphire 3" },
1480 { 0x0014, WACOM_GRAPHIRE, 16704, 12064, 9, "Graphire 3 6x8" },
1481 { 0x0015, WACOM_GRAPHIRE4, 10208, 7424, 9, "Graphire 4 4x5" },
1482 { 0x0016, WACOM_GRAPHIRE4, 16704, 12064, 9, "Graphire 4 6x8" },
1483 { 0x0020, WACOM_INTUOS, 12700, 10600, 10, "Intuos 4x5" },
1484 { 0x0021, WACOM_INTUOS, 20320, 16240, 10, "Intuos 6x8" },
1485 { 0x0022, WACOM_INTUOS, 30480, 24060, 10, "Intuos 9x12" },
1486 { 0x0023, WACOM_INTUOS, 30480, 31680, 10, "Intuos 12x12" },
1487 { 0x0024, WACOM_INTUOS, 45720, 31680, 10, "Intuos 12x18" },
1488 { 0x0030, WACOM_PL, 5408, 4056, 8, "PL-400" },
1489 { 0x0031, WACOM_PL, 6144, 4608, 8, "PL-500" },
1490 { 0x0032, WACOM_PL, 6126, 4604, 8, "PL-600" },
1491 { 0x0033, WACOM_PL, 6260, 5016, 8, "PL-600 SX" },
1492 { 0x0034, WACOM_PL2, 6144, 4608, 9, "PL-550" },
1493 { 0x0035, WACOM_PL2, 7220, 5780, 9, "PL-800" },
1494 { 0x0037, WACOM_PL2, 6758, 5406, 9, "PL-700" },
1495 { 0x0038, WACOM_PL2, 6282, 4762, 9, "PL-510" },
1496 { 0x0039, WACOM_PL2, 34080, 27660, 9, "PL-710" },
1497 { 0x003f, WACOM_CINTIQ, 87200, 65600, 10, "Cintiq 21 UX" },
1498 { 0x0041, WACOM_INTUOS, 12700, 10600, 10, "Intuos 2 4x5" },
1499 { 0x0042, WACOM_INTUOS, 20320, 16240, 10, "Intuos 2 6x8" },
1500 { 0x0043, WACOM_INTUOS, 30480, 24060, 10, "Intuos 2 9x12" },
1501 { 0x0044, WACOM_INTUOS, 30480, 31680, 10, "Intuos 2 12x12" },
1502 { 0x0045, WACOM_INTUOS, 45720, 31680, 10, "Intuos 2 12x18" },
1503 { 0x0047, WACOM_INTUOS, 20320, 16240, 10, "Intuos 2 6x8" },
1504 { 0x0060, WACOM_GRAPHIRE, 5104, 3712, 9, "Volito" },
1505 { 0x0061, WACOM_GRAPHIRE, 3250, 2320, 8, "PenStation 2" },
1506 { 0x0062, WACOM_GRAPHIRE, 5104, 3712, 9, "Volito 2 4x5" },
1507 { 0x0063, WACOM_GRAPHIRE, 3248, 2320, 9, "Volito 2 2x3" },
1508 { 0x0064, WACOM_GRAPHIRE, 3250, 2320, 8, "PenPartner 2" },
1509 { 0x00b0, WACOM_INTUOS3, 25400, 20320, 10, "Intuos 3 4x5" },
1510 { 0x00b1, WACOM_INTUOS3, 40640, 30480, 10, "Intuos 3 6x8" },
1511 { 0x00b2, WACOM_INTUOS3, 60960, 45720, 10, "Intuos 3 9x12" },
1512 { 0x00b5, WACOM_INTUOS3, 54204, 31750, 10, "Intuos 3 6x11" },
1513 { 0x00c0, WACOM_PL2, 6858, 5506, 9, "DTF-720" },
1514 { 0xffff, 0, 0, 0, 0, NULL }
1516 /* \\\ */
1518 /* /// "nParseWacom()" */
1519 BOOL nParseWacom(struct NepClassHid *nch, UBYTE *buf, ULONG len)
1521 struct WacomReport wr = { ~0, ~0, 0xffff, 0, 0, 0x80, 0x80, 0 };
1522 struct NepHidItem *nhi;
1523 BOOL take = FALSE;
1524 UWORD tmpval;
1525 KPRINTF(1, ("Wacom parsing %ld (%ld)...\n", nch->nch_WacomMode, len));
1526 switch(nch->nch_WacomMode)
1528 case WACOM_PENPARTNER:
1529 // 7 6 5 4 3 2 1 0
1530 // 80 40 20 10 08 04 02 01
1531 // 1: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1532 // 2: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1533 // 3: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
1534 // 4: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
1535 // 5: rmb outrng
1536 // 6: [signed pressure]
1537 if((buf[0] != 2) || (len < 7))
1539 break;
1541 wr.wr_PosX = buf[1] | (buf[2]<<8);
1542 wr.wr_PosY = buf[3] | (buf[4]<<8);
1543 wr.wr_Pressure = (((BYTE *) buf)[6]) + 127;
1544 wr.wr_InProximity = buf[5] & 0x20 ? 0x00 : 0xff;
1545 if(wr.wr_InProximity && (wr.wr_Pressure > 50))
1547 wr.wr_Buttons = 0x01;
1549 if(buf[5] & 0x40)
1551 wr.wr_Buttons |= 0x02;
1553 take = TRUE;
1554 break;
1556 case WACOM_GRAPHIRE:
1557 case WACOM_GRAPHIRE4:
1558 // 7 6 5 4 3 2 1 0
1559 // 80 40 20 10 08 04 02 01
1560 // 1: vld tooltype prox mmb rmb lmb
1561 // 2: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1562 // 3: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1563 // 4: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
1564 // 5: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
1565 // 6: [wheel bits ] G3 MOUSE
1566 // 6: [distance ] G4 MOUSE
1567 // 7: [distance ] G3 MOUSE
1568 // 7: wh_sgn wheel_bits G4 MOUSE
1569 // 6: [ pressure bits 0-7 ]
1570 // 7: pres8
1571 if((buf[0] != 2) || (len < 8))
1573 break;
1575 if(buf[1] & 0x10)
1577 wr.wr_InProximity = 0xff;
1578 if(buf[1] & 0x40) // is a mouse
1580 if(buf[1] & 0x20) // mouse without a scrollwheel
1582 // only two buttons, no wheel
1583 wr.wr_Buttons = buf[1] & 0x03;
1584 } else {
1585 // three buttons and wheel
1586 wr.wr_Buttons = buf[1] & 0x07;
1587 if(nch->nch_WacomMode == WACOM_GRAPHIRE4)
1589 wr.wr_Wheel = buf[7] & 0x03;
1590 if(buf[7] & 0x04)
1592 wr.wr_Wheel = -wr.wr_Wheel;
1594 } else {
1595 wr.wr_Wheel = ((BYTE *) buf)[6];
1596 KPRINTF(1, ("Wheel %ld\n", wr.wr_Wheel));
1599 } else {
1600 wr.wr_Buttons = buf[1] & 0x07;
1601 wr.wr_Pressure = buf[6] | ((buf[7] & 0x01)<<8);
1603 wr.wr_PosX = buf[2] | (buf[3]<<8);
1604 wr.wr_PosY = buf[4] | (buf[5]<<8);
1605 } else {
1606 wr.wr_InProximity = 0;
1608 take = TRUE;
1609 break;
1611 case WACOM_INTUOS:
1612 case WACOM_INTUOS3:
1613 case WACOM_CINTIQ:
1614 // 7 6 5 4 3 2 1 0
1615 // 80 40 20 10 08 04 02 01
1616 // 1: 1 1 0 0 mmb rmb tool = pen packet
1617 // 1: 1 1 1 0 0 tool = airbrush
1618 // 1: 1 1 0 1 = mouse
1619 // 1: 1 1 1 0 0 0 = lens?
1620 // 1: 1 1 0 0 0 0 = tool in
1621 // 1: 1 0 0 0 0 0 0 = tool out
1622 // 2: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1623 // 3: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1624 // 4: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
1625 // 5: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
1626 // 6: [ pressure/wheel bits 8-6 ]
1627 // 7: [press0-1] [ tiltx 6-1]
1628 // 8: tiltx0 [ tilty 6-0 ]
1629 // 9: x16 y16
1630 if(buf[0] == 12)
1632 wr.wr_PadButtons = (buf[5] & 0x0f)|(buf[6]<<4);
1633 take = TRUE;
1634 break;
1636 if((buf[0] != 2) && (buf[0] != 5) && (buf[0] != 6))
1638 break;
1640 // needs some improvement on the various tools
1641 if(buf[1] & 0x40)
1643 wr.wr_InProximity = 0xff;
1644 if(nch->nch_WacomMode == WACOM_INTUOS)
1646 wr.wr_PosX = (buf[2]<<8) | buf[3];
1647 wr.wr_PosY = (buf[4]<<8) | buf[5];
1648 if(buf[1] & 0x10)
1650 wr.wr_Buttons = (buf[8] & 0x07) | ((buf[8] & 0x30)>>1);
1652 } else {
1653 wr.wr_PosX = (buf[2]<<9) | (buf[3] << 1) | ((buf[9] & 0x02)>>1);
1654 wr.wr_PosY = (buf[4]<<9) | (buf[5] << 1) | (buf[9] & 0x01);
1656 if((buf[1] & 0xa0) == 0xa0)
1658 wr.wr_TiltX = ((buf[7] & 0x3f) << 1) | (buf[8] >> 7);
1659 wr.wr_TiltY = buf[8] & 0x7f;
1661 tmpval = (buf[6] << 2) | ((buf[7] & 0xc0)>>6);
1662 if((buf[1] & 0xb8) == 0xa0)
1664 wr.wr_Pressure = tmpval;
1665 wr.wr_Buttons = (buf[1] & 0x06) | ((wr.wr_Pressure > 16) ? 1 : 0);
1667 if((buf[1] & 0xbc) == 0xb4)
1669 wr.wr_Wheel = tmpval;
1671 } else {
1672 wr.wr_InProximity = 0;
1674 take = TRUE;
1675 break;
1677 case WACOM_PL:
1678 case WACOM_PL2:
1679 if((buf[0] != 2) || (len < 8))
1681 break;
1683 wr.wr_InProximity = buf[1] & 0x40 ? 0xff : 0;
1684 if(wr.wr_InProximity)
1686 wr.wr_Pressure = (BYTE) ((buf[7]<<1) | ((buf[4] & 0x04)>>2));
1687 if(nch->nch_WacomMode == WACOM_PL2)
1689 wr.wr_Pressure <<= 1;
1690 wr.wr_Pressure += ((buf[4] >> 6) & 1) + 256;
1691 } else {
1692 wr.wr_Pressure += 128;
1694 wr.wr_PosX = ((buf[1] & 0x03)<<14) | ((buf[2] & 0x7f)<<7) | (buf[3] & 0x7f);
1695 wr.wr_PosY = ((buf[4] & 0x03)<<14) | ((buf[5] & 0x7f)<<7) | (buf[6] & 0x7f);
1696 wr.wr_Buttons = (buf[4] & 0x38)>>3;
1698 take = TRUE;
1699 break;
1701 case WACOM_PLX:
1702 if((buf[0] != 2) || (len < 8))
1704 break;
1706 wr.wr_InProximity = 0xff;
1707 wr.wr_PosX = buf[2] | (buf[3]<<8);
1708 wr.wr_PosY = buf[4] | (buf[5]<<8);
1709 wr.wr_Pressure = buf[6] | (buf[7]<<8);
1710 if(buf[1] & 0x02)
1712 wr.wr_Buttons |= 0x01;
1714 if(buf[1] & 0x10)
1716 wr.wr_Buttons |= 0x02;
1718 take = TRUE;
1719 break;
1721 if(take)
1723 // fix endianess
1724 wr.wr_PosX = AROS_LONG2LE(wr.wr_PosX);
1725 wr.wr_PosY = AROS_LONG2LE(wr.wr_PosY);
1726 wr.wr_Pressure = AROS_WORD2LE(wr.wr_Pressure);
1728 nhi = (struct NepHidItem *) nch->nch_WacomColl->nhc_Items.lh_Head;
1729 while(nhi->nhi_Node.ln_Succ)
1731 nProcessItem(nch, nhi, (UBYTE *) &wr);
1732 nhi = (struct NepHidItem *) nhi->nhi_Node.ln_Succ;
1735 return(take);
1737 /* \\\ */
1739 /* /// "nDetectWacom()" */
1740 BOOL nDetectWacom(struct NepClassHid *nch)
1742 struct NepHidCollection *nhc;
1743 struct NepHidReport *nhr;
1744 struct NepHidItem *nhi;
1745 struct PsdIFFContext *pic;
1746 struct PsdIFFContext *rppic = NULL;
1747 struct WacomCaps *wc;
1748 IPTR vendid;
1749 IPTR prodid;
1750 ULONG caps = 0;
1751 UWORD butno;
1752 UWORD numbuts = 3;
1754 psdGetAttrs(PGA_DEVICE, nch->nch_Device,
1755 DA_VendorID, &vendid,
1756 DA_ProductID, &prodid,
1757 TAG_END);
1758 if(vendid != 0x056a)
1760 return(FALSE);
1763 for(wc = WacomCapsTable; wc->wc_ProdID != prodid; wc++)
1765 if(wc->wc_ProdID == 0xffff)
1767 return FALSE;
1770 switch(wc->wc_Type)
1772 case WACOM_PENPARTNER:
1773 case WACOM_PLX:
1774 numbuts = 2;
1775 break;
1777 case WACOM_INTUOS:
1778 case WACOM_INTUOS3:
1779 case WACOM_CINTIQ:
1780 caps |= WACOM_HASTILT;
1781 case WACOM_GRAPHIRE4:
1782 if(wc->wc_Type != WACOM_INTUOS)
1784 caps |= WACOM_HASBUTTONS;
1786 case WACOM_GRAPHIRE:
1787 caps |= WACOM_HASWHEEL;
1788 break;
1791 psdAddErrorMsg(RETURN_OK, GM_UNIQUENAME(libname), "Adding Wacom %s support.", wc->wc_Name);
1793 pic = psdGetUsbDevCfg(GM_UNIQUENAME(libname), nch->nch_DevIDString, nch->nch_IfIDString);
1794 if(pic)
1796 rppic = psdFindCfgForm(pic, MAKE_ID('W','C','O','M'));
1798 if((nhr = psdAllocVec(sizeof(struct NepHidReport))))
1800 NewList(&nhr->nhr_Collections);
1801 AddTail(&nch->nch_HidReports, &nhr->nhr_Node);
1802 nhr->nhr_ReportID = 0xfffe;
1803 nhr->nhr_ItemIDBase = 0xf001;
1804 if((nhc = psdAllocVec(sizeof(struct NepHidCollection))))
1806 NewList(&nhc->nhc_Items);
1807 AddTail(&nhr->nhr_Collections, &nhc->nhc_Node);
1808 nhc->nhc_Report = nhr;
1809 nhc->nhc_Usage = 0x0d0001;
1810 nhc->nhc_Name = psdCopyStr("[Wacom Support]");
1811 nch->nch_WacomColl = nhc;
1812 nch->nch_WacomMode = wc->wc_Type;
1813 // buttons
1814 for(butno = 0; butno < numbuts; butno++)
1816 if((nhi = psdAllocVec(sizeof(struct NepHidItem))))
1818 nhi->nhi_Collection = nhc;
1819 nhi->nhi_Type = REPORT_MAIN_INPUT;
1820 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1821 nhi->nhi_Offset = (offsetof(struct WacomReport, wr_Buttons)<<3) + butno;
1822 nhi->nhi_Size = 1;
1824 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = 0;
1825 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = 1;
1826 nhi->nhi_Usage = 0x090001+butno;
1827 nAddItemAction(nch, rppic, nhi, 0xfd0+butno);
1830 // absolute X
1831 if((nhi = psdAllocVec(sizeof(struct NepHidItem))))
1833 nhi->nhi_Collection = nhc;
1834 nhi->nhi_Type = REPORT_MAIN_INPUT;
1835 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1836 nhi->nhi_Offset = offsetof(struct WacomReport, wr_PosX)<<3;
1837 nhi->nhi_Size = sizeof(((struct WacomReport *) NULL)->wr_PosX)<<3;
1839 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = 0;
1840 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = wc->wc_ResX-1;
1841 nhi->nhi_Usage = 0x010030;
1842 nAddItemAction(nch, rppic, nhi, 0xfe1);
1844 // absolute Y
1845 if((nhi = psdAllocVec(sizeof(struct NepHidItem))))
1847 nhi->nhi_Collection = nhc;
1848 nhi->nhi_Type = REPORT_MAIN_INPUT;
1849 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1850 nhi->nhi_Offset = offsetof(struct WacomReport, wr_PosY)<<3;
1851 nhi->nhi_Size = sizeof(((struct WacomReport *) NULL)->wr_PosY)<<3;
1853 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = 0;
1854 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = wc->wc_ResY-1;
1855 nhi->nhi_Usage = 0x010031;
1856 nAddItemAction(nch, rppic, nhi, 0xfe2);
1858 // wheel
1859 if((caps & WACOM_HASWHEEL) && ((nhi = psdAllocVec(sizeof(struct NepHidItem)))))
1861 nhi->nhi_Collection = nhc;
1862 nhi->nhi_Type = REPORT_MAIN_INPUT;
1863 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1864 nhi->nhi_Offset = offsetof(struct WacomReport, wr_Wheel)<<3;
1865 nhi->nhi_Size = sizeof(((struct WacomReport *) NULL)->wr_Wheel)<<3;
1867 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = -127;
1868 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = 127;
1869 nhi->nhi_IsSigned = TRUE;
1870 nhi->nhi_Usage = 0x010038;
1871 nAddItemAction(nch, rppic, nhi, 0xfe0);
1873 // pressure
1874 if((nhi = psdAllocVec(sizeof(struct NepHidItem))))
1876 nhi->nhi_Collection = nhc;
1877 nhi->nhi_Type = REPORT_MAIN_INPUT;
1878 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1879 nhi->nhi_Offset = offsetof(struct WacomReport, wr_Pressure)<<3;
1880 nhi->nhi_Size = sizeof(((struct WacomReport *) NULL)->wr_Pressure)<<3;
1882 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = 0;
1883 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = (1UL<<wc->wc_PressBits)-1;
1884 nhi->nhi_Usage = 0x0d0030;
1885 nAddItemAction(nch, rppic, nhi, 0xfe4);
1887 // in proximity
1888 if((nhi = psdAllocVec(sizeof(struct NepHidItem))))
1890 nhi->nhi_Collection = nhc;
1891 nhi->nhi_Type = REPORT_MAIN_INPUT;
1892 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1893 nhi->nhi_Offset = offsetof(struct WacomReport, wr_InProximity)<<3;
1894 nhi->nhi_Size = 1;
1896 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = 0;
1897 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = 1;
1898 nhi->nhi_Usage = 0x0d0032;
1899 nAddItemAction(nch, rppic, nhi, 0xfe5);
1901 // x tilt
1902 if((caps & WACOM_HASTILT) && ((nhi = psdAllocVec(sizeof(struct NepHidItem)))))
1904 nhi->nhi_Collection = nhc;
1905 nhi->nhi_Type = REPORT_MAIN_INPUT;
1906 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1907 nhi->nhi_Offset = offsetof(struct WacomReport, wr_TiltX)<<3;
1908 nhi->nhi_Size = sizeof(((struct WacomReport *) NULL)->wr_TiltX)<<3;
1910 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = 0;
1911 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = 127;
1912 nhi->nhi_Usage = 0x0d003d;
1913 nAddItemAction(nch, rppic, nhi, 0xfe6);
1915 // y tilt
1916 if((caps & WACOM_HASTILT) && ((nhi = psdAllocVec(sizeof(struct NepHidItem)))))
1918 nhi->nhi_Collection = nhc;
1919 nhi->nhi_Type = REPORT_MAIN_INPUT;
1920 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1921 nhi->nhi_Offset = offsetof(struct WacomReport, wr_TiltY)<<3;
1922 nhi->nhi_Size = sizeof(((struct WacomReport *) NULL)->wr_TiltY)<<3;
1924 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = 0;
1925 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = 127;
1926 nhi->nhi_Usage = 0x0d003e;
1927 nAddItemAction(nch, rppic, nhi, 0xfe7);
1929 // pad buttons
1930 if(caps & WACOM_HASBUTTONS)
1932 for(butno = 0; butno < 8; butno++)
1934 if((nhi = psdAllocVec(sizeof(struct NepHidItem))))
1936 nhi->nhi_Collection = nhc;
1937 nhi->nhi_Type = REPORT_MAIN_INPUT;
1938 nhi->nhi_Flags = RPF_MAIN_VARIABLE;
1939 nhi->nhi_Offset = (offsetof(struct WacomReport, wr_PadButtons)<<3) + butno;
1940 nhi->nhi_Size = 1;
1942 nhi->nhi_PhysicalMin = nhi->nhi_LogicalMin = 0;
1943 nhi->nhi_PhysicalMax = nhi->nhi_LogicalMax = 1;
1944 nhi->nhi_Usage = 0x090009+butno;
1945 nAddItemAction(nch, rppic, nhi, 0xfd8+butno);
1952 return(FALSE);
1954 /* \\\ */
1956 /* /// "nQuirkPS3Controller()" */
1957 void nQuirkPS3Controller(struct NepClassHid *nch)
1959 LONG ioerr;
1960 UBYTE buf[18];
1962 IPTR vendid;
1963 IPTR prodid;
1965 psdGetAttrs(PGA_DEVICE, nch->nch_Device,
1966 DA_VendorID, &vendid,
1967 DA_ProductID, &prodid,
1968 TAG_END);
1970 if(vendid == 0x054c && prodid == 0x0268) {
1971 psdPipeSetup(nch->nch_EP0Pipe, URTF_IN|URTF_CLASS|URTF_INTERFACE, UHR_GET_REPORT, 0x03f2, nch->nch_IfNum);
1972 ioerr = psdDoPipe(nch->nch_EP0Pipe, buf, sizeof(buf));
1973 if(ioerr) {
1974 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname), "Unable to add PS3 controller support!");
1975 }else{
1976 psdAddErrorMsg(RETURN_OK, GM_UNIQUENAME(libname), "Adding PS3 controller support.");
1980 /* \\\ */
1982 /* /// "nReadReports()" */
1983 BOOL nReadReports(struct NepClassHid *nch)
1985 struct NepHidReport *nhr;
1986 struct NepHidCollection *nhc;
1987 struct NepHidItem *nhi;
1988 struct PsdDescriptor *pdd;
1990 LONG ioerr;
1991 UBYTE buf[256];
1992 ULONG num;
1993 UBYTE *bptr;
1994 BOOL res = FALSE;
1995 BOOL thisres;
1997 UWORD idnum;
1998 ULONG count;
1999 struct List *alistptr;
2000 ULONG actlen;
2002 pdd = psdFindDescriptor(nch->nch_Device, NULL,
2003 DDA_DescriptorType, UDT_HID,
2004 DDA_Interface, nch->nch_Interface,
2005 TAG_END);
2006 if(pdd)
2008 UBYTE *descdata;
2009 psdGetAttrs(PGA_DESCRIPTOR, pdd,
2010 DDA_DescriptorData, &descdata,
2011 TAG_END);
2013 actlen = descdata[0];
2014 memcpy(buf, descdata, (size_t) actlen);
2015 ioerr = 0;
2016 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
2017 "Using HID Descriptor from initial configuration run.");
2018 } else {
2019 psdPipeSetup(nch->nch_EP0Pipe, URTF_IN|URTF_STANDARD|URTF_INTERFACE,
2020 USR_GET_DESCRIPTOR, UDT_HID<<8, nch->nch_IfNum);
2021 ioerr = psdDoPipe(nch->nch_EP0Pipe, buf, 256);
2022 if(ioerr == UHIOERR_RUNTPACKET)
2024 ioerr = 0;
2026 if(ioerr)
2028 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2029 "GET_HID_DESCRIPTOR(%ld) failed: %s (%ld)!",
2030 256, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2031 psdDelayMS(100);
2032 ioerr = psdDoPipe(nch->nch_EP0Pipe, buf, 256);
2033 if(ioerr == UHIOERR_RUNTPACKET)
2035 ioerr = 0;
2037 if(ioerr)
2039 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2040 "GET_HID_DESCRIPTOR(%ld) (2nd) failed: %s (%ld)!",
2041 256, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2042 psdPipeSetup(nch->nch_EP0Pipe, URTF_IN|URTF_STANDARD|URTF_INTERFACE,
2043 USR_GET_DESCRIPTOR, UDT_HID<<8, nch->nch_IfNum);
2044 ioerr = psdDoPipe(nch->nch_EP0Pipe, buf, 1);
2045 if(ioerr)
2047 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2048 "GET_HID_DESCRIPTOR(%ld) (3rd) failed: %s (%ld)!",
2049 1, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2051 } else {
2052 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Burstroem retry successful ;)");
2055 actlen = psdGetPipeActual(nch->nch_EP0Pipe);
2057 if((!ioerr) || (ioerr == UHIOERR_OVERFLOW))
2059 if(buf[0] < 9)
2061 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2062 "bLength field (%ld) probably wrong, fixing to %ld!",
2063 buf[0], actlen);
2064 buf[0] = actlen;
2066 if(actlen < 6)
2068 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2069 "Read less than 6 bytes (%ld read) for HID Descriptor!",
2070 actlen);
2072 if((nch->nch_HidDesc = psdAllocVec((ULONG) buf[0])))
2074 /*ioerr = psdDoPipe(nch->nch_EP0Pipe, nch->nch_HidDesc, (ULONG) buf[0]);
2075 if(ioerr)
2077 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2078 "GET_HID_DESCRIPTOR(%ld) failed: %s (%ld)!",
2079 buf[0], psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2080 psdDelayMS(100);
2081 ioerr = psdDoPipe(nch->nch_EP0Pipe, nch->nch_HidDesc, (ULONG) buf[0]);
2082 if(!ioerr)
2084 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Burstroem retry successful ;)");
2087 if(!ioerr)
2089 CopyMem(buf, nch->nch_HidDesc, (ULONG) buf[0]);
2090 //dumpmem(nch->nch_HidDesc, (ULONG) buf);
2091 if(!nch->nch_HidDesc->bNumDescriptors)
2093 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2094 "Device reports that it doesn't have any descriptors!");
2095 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2096 "Debug info: %ld, %02lx, %02lx, %ld, %ld, %02lx, %ld, %ld!",
2097 nch->nch_HidDesc->bLength,
2098 nch->nch_HidDesc->bDescriptorType,
2099 nch->nch_HidDesc->bcdHID,
2100 nch->nch_HidDesc->bCountryCode,
2101 nch->nch_HidDesc->bNumDescriptors,
2102 nch->nch_HidDesc->bDescType,
2103 nch->nch_HidDesc->wDescLength,
2104 nch->nch_HidDesc->wPad0);
2106 if(6 + nch->nch_HidDesc->bNumDescriptors*3 > actlen)
2108 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2109 "Too few bytes read for HID %ld descriptor (%ld of %ld)!",
2110 nch->nch_HidDesc->bNumDescriptors,
2111 actlen,
2112 6 + nch->nch_HidDesc->bNumDescriptors*3);
2113 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2114 "Debug info: %ld, %02lx, %02lx, %ld, %ld, %02lx, %ld, %ld!",
2115 nch->nch_HidDesc->bLength,
2116 nch->nch_HidDesc->bDescriptorType,
2117 nch->nch_HidDesc->bcdHID,
2118 nch->nch_HidDesc->bCountryCode,
2119 nch->nch_HidDesc->bNumDescriptors,
2120 nch->nch_HidDesc->bDescType,
2121 nch->nch_HidDesc->wDescLength,
2122 nch->nch_HidDesc->wPad0);
2125 KPRINTF(1, ("%ld Report descriptors\n", nch->nch_HidDesc->bNumDescriptors));
2126 bptr = &nch->nch_HidDesc->bDescType;
2127 for(num = 0; num < nch->nch_HidDesc->bNumDescriptors; num++)
2129 if(*bptr == UDT_REPORT)
2131 if((nhr = psdAllocVec(sizeof(struct NepHidReport))))
2133 NewList(&nhr->nhr_Collections);
2134 AddTail(&nch->nch_HidReports, &nhr->nhr_Node);
2135 thisres = FALSE;
2136 nhr->nhr_ReportLength = bptr[1] + (bptr[2]<<8);
2137 if(!nhr->nhr_ReportLength)
2139 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2140 "Report Descriptor #%ld is said to have 0 bytes!",
2141 num);
2142 } else {
2143 if((nhr->nhr_ReportBuf = psdAllocVec(nhr->nhr_ReportLength)))
2145 psdPipeSetup(nch->nch_EP0Pipe, URTF_IN|URTF_STANDARD|URTF_INTERFACE,
2146 USR_GET_DESCRIPTOR, (UDT_REPORT<<8)|num, nch->nch_IfNum);
2147 ioerr = psdDoPipe(nch->nch_EP0Pipe, nhr->nhr_ReportBuf, nhr->nhr_ReportLength);
2148 if(!ioerr)
2150 //dumpmem(nhr->nhr_ReportBuf, nhr->nhr_ReportLength);
2151 thisres = nParseReport(nch, nhr);
2152 //nDebugReport(nch, nhr);
2153 res |= thisres;
2154 } else {
2155 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2156 "GET_REPORT_DESCRIPTOR(%ld) failed: %s (%ld)!",
2157 nhr->nhr_ReportLength, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2161 if(!thisres)
2163 nFreeReport(nch, nhr);
2167 bptr += 3;
2169 /*} else {
2170 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2171 "GET_HID_DESCRIPTOR(%ld) failed: %s (%ld)!",
2172 buf[0], psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2174 } else {
2175 KPRINTF(1, ("No Hid Descriptor memory!\n"));
2177 } else {
2178 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2179 "GET_HID_DESCRIPTOR(%ld) failed: %s (%ld)!",
2180 256, psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
2182 if(res)
2184 ULONG repsize;
2185 /* Get maximal package size */
2186 nch->nch_MaxReportID = 0;
2187 nch->nch_MaxInSize = 0;
2188 nch->nch_MaxOutSize = 0;
2189 nch->nch_MaxFeatSize = 0;
2190 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
2191 while(nhr->nhr_Node.ln_Succ)
2193 KPRINTF(5, ("Report %ld: InBits=%ld, OutBits=%ld, FeatBits=%ld\n",
2194 nhr->nhr_ReportID, nhr->nhr_ReportInSize,
2195 nhr->nhr_ReportOutSize, nhr->nhr_ReportFeatSize));
2196 if(nhr->nhr_ReportID)
2198 nch->nch_UsesReportID = TRUE;
2199 if(nch->nch_MaxReportID < nhr->nhr_ReportID)
2201 nch->nch_MaxReportID = nhr->nhr_ReportID;
2204 repsize = (nhr->nhr_ReportInSize+7)>>3;
2205 if(nch->nch_MaxInSize < repsize)
2207 nch->nch_MaxInSize = repsize;
2209 repsize = (nhr->nhr_ReportOutSize+7)>>3;
2210 if(nch->nch_MaxOutSize < repsize)
2212 nch->nch_MaxOutSize = repsize;
2214 repsize = (nhr->nhr_ReportFeatSize+7)>>3;
2215 if(nch->nch_MaxFeatSize < repsize)
2217 nch->nch_MaxFeatSize = repsize;
2219 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
2221 if(nch->nch_UsesReportID)
2223 nch->nch_MaxInSize++;
2224 nch->nch_MaxOutSize++;
2225 nch->nch_MaxFeatSize++;
2228 nch->nch_MaxReportSize = nch->nch_MaxInSize;
2229 if(nch->nch_MaxOutSize > nch->nch_MaxReportSize)
2231 nch->nch_MaxReportSize = nch->nch_MaxOutSize;
2233 if(nch->nch_MaxFeatSize > nch->nch_MaxReportSize)
2235 nch->nch_MaxReportSize = nch->nch_MaxFeatSize;
2238 KPRINTF(5, ("MaxReportID=%ld, MaxReportSize=%ld\n", nch->nch_MaxReportID, nch->nch_MaxReportSize));
2240 if((nch->nch_ReportMap = psdAllocVec((ULONG) sizeof(struct NepHidReport *) * (nch->nch_MaxReportID+1))))
2242 /* Fill in Report Map */
2243 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
2244 while(nhr->nhr_Node.ln_Succ)
2246 KPRINTF(5, ("Report Map slot %ld/%ld filled with %08lx\n", nhr->nhr_ReportID, nch->nch_MaxReportID, nhr));
2247 nch->nch_ReportMap[nhr->nhr_ReportID] = nhr;
2248 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
2250 } else {
2251 KPRINTF(10, ("Out of memory for Report Map!\n"));
2252 res = FALSE;
2256 if(res)
2258 struct NepHidItem **nhiptr;
2259 struct NepHidItem **nhiinptr;
2260 struct NepHidItem **nhioutptr;
2261 struct NepHidItem **nhifeatptr;
2263 /* Count items */
2264 idnum = 1;
2265 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
2266 while(nhr->nhr_Node.ln_Succ)
2268 KPRINTF(1, ("Report %ld:\n", nhr->nhr_ReportID));
2269 nhr->nhr_ItemIDBase = idnum;
2270 nhr->nhr_InItemCount = nhr->nhr_OutItemCount = nhr->nhr_FeatItemCount = 0;
2271 nhc = (struct NepHidCollection *) nhr->nhr_Collections.lh_Head;
2272 while(nhc->nhc_Node.ln_Succ)
2274 KPRINTF(1, (" Collection %s:\n", nhc->nhc_Name));
2275 nhi = (struct NepHidItem *) nhc->nhc_Items.lh_Head;
2276 while(nhi->nhi_Node.ln_Succ)
2278 switch(nhi->nhi_Type)
2280 case REPORT_MAIN_INPUT:
2281 KPRINTF(1, (" Input Item %lx:\n", nhi->nhi_Usage));
2282 nhr->nhr_InItemCount++;
2283 break;
2285 case REPORT_MAIN_OUTPUT:
2286 KPRINTF(1, (" Output Item %lx:\n", nhi->nhi_Usage));
2287 nhr->nhr_OutItemCount++;
2288 break;
2290 case REPORT_MAIN_FEATURE:
2291 KPRINTF(1, (" Feature Item %lx:\n", nhi->nhi_Usage));
2292 nhr->nhr_FeatItemCount++;
2293 break;
2296 // generate id numbers
2297 SET_WTYPE(&nhi->nhi_ActionList, idnum++);
2298 if(!(nhi->nhi_Flags & RPF_MAIN_VARIABLE))
2300 alistptr = nhi->nhi_ActionMap;
2301 count = nhi->nhi_MapSize;
2304 SET_WTYPE(alistptr, idnum++);
2305 alistptr++;
2306 } while(--count);
2309 nhi = (struct NepHidItem *) nhi->nhi_Node.ln_Succ;
2311 nhc = (struct NepHidCollection *) nhc->nhc_Node.ln_Succ;
2313 /*psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
2314 "R=%02lx: %ld input items, %ld output items, %ld feature items, %ld items total!",
2315 nhr->nhr_ReportID, nhr->nhr_InItemCount, nhr->nhr_OutItemCount, nhr->nhr_FeatItemCount,
2316 idnum-1);*/
2317 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
2320 /* Create quick item lookup table */
2321 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
2322 while(nhr->nhr_Node.ln_Succ)
2324 KPRINTF(1, ("Report %ld, allocating %ld/%ld/%ld items\n",
2325 nhr->nhr_ReportID,
2326 nhr->nhr_InItemCount, nhr->nhr_OutItemCount, nhr->nhr_FeatItemCount));
2327 if((nhiptr = psdAllocVec(sizeof(struct NepHidItem *) * (nhr->nhr_InItemCount +
2328 nhr->nhr_OutItemCount + nhr->nhr_FeatItemCount))))
2330 nhiinptr = nhr->nhr_InItemMap = nhiptr;
2331 nhioutptr = nhr->nhr_OutItemMap = &nhiptr[nhr->nhr_InItemCount];
2332 nhifeatptr = nhr->nhr_FeatItemMap = &nhioutptr[nhr->nhr_OutItemCount];
2333 nhc = (struct NepHidCollection *) nhr->nhr_Collections.lh_Head;
2334 while(nhc->nhc_Node.ln_Succ)
2336 nhi = (struct NepHidItem *) nhc->nhc_Items.lh_Head;
2338 while(nhi->nhi_Node.ln_Succ)
2340 /* Add quick lookup entry */
2341 switch(nhi->nhi_Type)
2343 case REPORT_MAIN_INPUT:
2344 *nhiinptr++ = nhi;
2345 nch->nch_HasInItems = TRUE;
2346 break;
2348 case REPORT_MAIN_OUTPUT:
2349 *nhioutptr++ = nhi;
2350 break;
2352 case REPORT_MAIN_FEATURE:
2353 *nhifeatptr++ = nhi;
2354 break;
2356 nhi = (struct NepHidItem *) nhi->nhi_Node.ln_Succ;
2358 nhc = (struct NepHidCollection *) nhc->nhc_Node.ln_Succ;
2360 } else {
2361 res = FALSE;
2363 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
2366 nLoadActionConfig(nch);
2368 return(res);
2370 /* \\\ */
2372 /* /// "nLoadActionConfig()" */
2373 void nLoadActionConfig(struct NepClassHid *nch)
2375 struct NepHidReport *nhr;
2376 struct NepHidCollection *nhc;
2377 struct NepHidItem *nhi;
2379 ULONG count;
2380 struct List *alistptr;
2381 ULONG *usageptr;
2382 struct PsdIFFContext *pic;
2383 struct PsdIFFContext *rppic;
2385 pic = psdGetUsbDevCfg(GM_UNIQUENAME(libname), nch->nch_DevIDString, nch->nch_IfIDString);
2386 if(pic)
2388 nch->nch_LastCfgCRC = nCalcConfigCRC(nch, nch->nch_Base, pic);
2389 } else {
2390 nch->nch_LastCfgCRC = 0;
2393 /* Create default action mapping */
2394 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
2395 while(nhr->nhr_Node.ln_Succ)
2397 KPRINTF(1, ("Report %ld:\n", nhr->nhr_ReportID));
2398 if(pic)
2400 rppic = psdFindCfgForm(pic, MAKE_ID('R','P','T','0')+nhr->nhr_ReportID);
2401 } else {
2402 rppic = NULL;
2404 nhc = (struct NepHidCollection *) nhr->nhr_Collections.lh_Head;
2405 while(nhc->nhc_Node.ln_Succ)
2407 KPRINTF(1, (" Collection %s:\n", nhc->nhc_Name));
2408 nhi = (struct NepHidItem *) nhc->nhc_Items.lh_Head;
2409 while(nhi->nhi_Node.ln_Succ)
2411 usageptr = &nhi->nhi_Usage;
2412 alistptr = &nhi->nhi_ActionList;
2413 if(rppic)
2415 if(!(nLoadItem(nch, rppic, alistptr, nhr->nhr_ItemIDBase)))
2417 nDetectDefaultAction(nch, nhi, alistptr, nhc, *usageptr);
2419 } else {
2420 nDetectDefaultAction(nch, nhi, alistptr, nhc, *usageptr);
2423 if(nhi->nhi_Flags & RPF_MAIN_VARIABLE)
2425 KPRINTF(1, (" Variable %lx: %s\n", nhi->nhi_Usage, nNumToStr(nch, NTS_USAGEID, nhi->nhi_Usage, "unknown")));
2426 } else {
2427 usageptr = nhi->nhi_UsageMap;
2428 alistptr = nhi->nhi_ActionMap;
2429 count = nhi->nhi_MapSize;
2430 KPRINTF(1, (" Array %lx: %s\n", *usageptr, nNumToStr(nch, NTS_USAGEID, *usageptr, "unknown")));
2433 if(rppic)
2435 if(!(nLoadItem(nch, rppic, alistptr, nhr->nhr_ItemIDBase)))
2437 nDetectDefaultAction(nch, nhi, alistptr, nhc, *usageptr);
2439 } else {
2440 nDetectDefaultAction(nch, nhi, alistptr, nhc, *usageptr);
2442 alistptr++;
2443 usageptr++;
2444 } while(--count);
2446 nhi = (struct NepHidItem *) nhi->nhi_Node.ln_Succ;
2448 nhc = (struct NepHidCollection *) nhc->nhc_Node.ln_Succ;
2450 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
2453 /* \\\ */
2455 /* /// "nDebugMem()" */
2456 void nDebugMem(struct NepClassHid *nch, UBYTE *rptr, ULONG rptlen)
2458 char fmtstr[108];
2459 STRPTR fmtptr;
2460 UWORD cnt;
2461 UWORD pos = 0;
2463 while(rptlen)
2465 fmtptr = fmtstr;
2466 cnt = 16;
2467 *fmtptr++ = '%';
2468 *fmtptr++ = '0';
2469 *fmtptr++ = '4';
2470 *fmtptr++ = 'l';
2471 *fmtptr++ = 'x';
2472 *fmtptr++ = ':';
2473 *fmtptr++ = ' ';
2476 *fmtptr++ = '%';
2477 *fmtptr++ = '0';
2478 *fmtptr++ = '2';
2479 *fmtptr++ = 'l';
2480 *fmtptr++ = 'x';
2481 if(--cnt)
2483 *fmtptr++ = ' ';
2485 --rptlen;
2486 } while(cnt && rptlen);
2487 *fmtptr = 0;
2488 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), fmtstr, pos,
2489 rptr[0], rptr[1], rptr[2], rptr[3], rptr[4], rptr[5], rptr[6], rptr[7],
2490 rptr[8], rptr[9], rptr[10], rptr[11], rptr[12], rptr[13], rptr[14], rptr[15]);
2491 rptr += 16;
2492 pos += 16;
2495 /* \\\ */
2497 /* /// "nDebugReport()" */
2498 void nDebugReport(struct NepClassHid *nch, struct NepHidReport *nhr)
2500 UBYTE *rptr;
2501 ULONG rptlen;
2502 if(!nhr)
2504 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname), "Can't debug HID Report: nhr=NULL!\n");
2505 return;
2507 rptr = nhr->nhr_ReportBuf;
2508 rptlen = nhr->nhr_ReportLength;
2509 if(!rptr)
2511 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname), "Can't debug HID Report: ReportBuf=NULL!\n");
2512 return;
2515 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2516 "HID Report %02lx Debug (%ld bytes):", nhr->nhr_ReportID, rptlen);
2517 nDebugMem(nch, rptr, rptlen);
2519 /* \\\ */
2521 /* /// "nParseReport()" */
2522 BOOL nParseReport(struct NepClassHid *nch, struct NepHidReport *nhr)
2524 UBYTE *rptr = nhr->nhr_ReportBuf;
2525 UBYTE *rptrend = &nhr->nhr_ReportBuf[nhr->nhr_ReportLength];
2526 struct NepHidCollection *nhc = NULL;
2527 struct Node *node;
2528 UWORD itag;
2529 UWORD isize;
2530 UWORD itype;
2531 ULONG len = 0;
2532 LONG data = 0;
2533 ULONG udata = 0;
2534 ULONG usageid, designid, stringid;
2535 ULONG usagemin, usagemax;
2536 ULONG designmin, designmax;
2537 ULONG stringmin, stringmax;
2538 ULONG reportid = 0;
2539 ULONG bitpos = 0;
2540 LONG count;
2541 UWORD delim = 0;
2542 ULONG reportpos;
2544 NewList(&nch->nch_HidStack);
2545 NewList(&nch->nch_HidUsages);
2546 NewList(&nch->nch_HidDesigns);
2547 NewList(&nch->nch_HidStrings);
2549 nch->nch_HidGlobal.nhg_UsagePage =
2550 nch->nch_HidGlobal.nhg_LogicalMin =
2551 nch->nch_HidGlobal.nhg_LogicalMax =
2552 nch->nch_HidGlobal.nhg_PhysicalMin =
2553 nch->nch_HidGlobal.nhg_PhysicalMax =
2554 nch->nch_HidGlobal.nhg_UnitExp =
2555 nch->nch_HidGlobal.nhg_Unit = HID_PARAM_UNDEF;
2557 nch->nch_HidGlobal.nhg_ReportID =
2558 nch->nch_HidGlobal.nhg_ReportSize =
2559 nch->nch_HidGlobal.nhg_ReportCount = 0;
2561 usagemin = usagemax =
2562 designmin = designmax =
2563 stringmin = stringmax = HID_PARAM_UNDEF;
2565 KPRINTF(1, ("Starting parsing...\n"));
2566 /* Parse the items */
2567 while(rptr && (rptr < rptrend))
2569 reportpos = ((IPTR) rptr) - ((IPTR) nhr->nhr_ReportBuf);
2570 itag = *rptr & REPORT_ITAG_MASK;
2571 isize = *rptr & REPORT_ISIZE_MASK;
2572 itype = *rptr & REPORT_ITYPE_MASK;
2573 if(*rptr++ == REPORT_LONGITEM) /* Is this a long item? */
2575 len = *rptr++;
2576 itag = *rptr++;
2577 rptr += len;
2578 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
2579 "HID Error at %04lx: Long items (%lx, len=%ld) are not specified in the spec!", reportpos, itag, len);
2580 } else {
2581 switch(isize)
2583 case REPORT_ISIZE_0:
2584 len = 0;
2585 udata = data = 0;
2586 break;
2588 case REPORT_ISIZE_1:
2589 len = 1;
2590 data = *((BYTE *) rptr);
2591 udata = *rptr++;
2592 break;
2594 case REPORT_ISIZE_2:
2595 len = 2;
2596 udata = data = *rptr++;
2597 data |= (*((BYTE *) rptr))<<8;
2598 udata |= (*rptr++)<<8;
2599 break;
2601 case REPORT_ISIZE_4:
2602 len = 4;
2603 data = *rptr++;
2604 data |= (*rptr++)<<8;
2605 data |= (*rptr++)<<16;
2606 data |= (*rptr++)<<24;
2607 udata = data;
2608 break;
2611 switch(itype)
2613 case REPORT_ITYPE_MAIN:
2614 //KPRINTF(1, ("Main "));
2615 if(reportid != nch->nch_HidGlobal.nhg_ReportID)
2617 struct NepHidReport *oldnhr = nhr;
2618 if(reportid)
2620 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
2621 while(nhr->nhr_Node.ln_Succ)
2623 if(nhr->nhr_ReportID == nch->nch_HidGlobal.nhg_ReportID)
2625 break;
2627 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
2629 if(!nhr->nhr_Node.ln_Succ)
2631 if((nhr = psdAllocVec(sizeof(struct NepHidReport))))
2633 KPRINTF(1, ("Generating new report ID %ld\n", nch->nch_HidGlobal.nhg_ReportID));
2634 NewList(&nhr->nhr_Collections);
2635 nhr->nhr_ReportID = nch->nch_HidGlobal.nhg_ReportID;
2636 AddTail(&nch->nch_HidReports, &nhr->nhr_Node);
2637 } else {
2638 KPRINTF(1, ("Out of memory creating new report.\n"));
2639 rptr = NULL;
2640 break;
2642 } else {
2643 KPRINTF(1, ("Switched back to report ID %ld\n", nch->nch_HidGlobal.nhg_ReportID));
2645 if(nhc)
2647 KPRINTF(1, ("Collection open, checking need for cloning.\n"));
2648 if(nhc->nhc_Items.lh_Head->ln_Succ)
2650 struct NepHidCollection *tmpnhc;
2651 struct NepHidCollection *newnhc;
2652 struct NepHidCollection *childnhc = NULL;
2654 KPRINTF(1, ("Not empty, assigning collection to current report and cloning!\n"));
2655 tmpnhc = nhc;
2656 nhc = NULL;
2659 KPRINTF(1, ("Cloning %08lx (%s)\n", tmpnhc, tmpnhc->nhc_Name));
2660 if((newnhc = psdAllocVec(sizeof(struct NepHidCollection))))
2662 if(!nhc)
2664 nhc = newnhc;
2666 NewList(&newnhc->nhc_Items);
2667 if(childnhc)
2669 childnhc->nhc_Parent = newnhc;
2671 newnhc->nhc_Usage = tmpnhc->nhc_Usage;
2672 newnhc->nhc_Name = psdCopyStr(tmpnhc->nhc_Name);
2673 } else {
2674 KPRINTF(10, ("Out of memory cloning nhc!\n"));
2675 break;
2677 AddTail(&oldnhr->nhr_Collections, &tmpnhc->nhc_Node);
2678 tmpnhc->nhc_Report = oldnhr;
2679 childnhc = newnhc;
2680 } while((tmpnhc = nhc->nhc_Parent));
2683 } else {
2684 KPRINTF(1, ("Setting first report ID %ld\n", nch->nch_HidGlobal.nhg_ReportID));
2685 nhr->nhr_ReportID = nch->nch_HidGlobal.nhg_ReportID;
2687 reportid = nch->nch_HidGlobal.nhg_ReportID;
2689 switch(itag)
2691 case REPORT_MAIN_INPUT:
2692 bitpos = nhr->nhr_ReportInSize;
2693 break;
2694 case REPORT_MAIN_OUTPUT:
2695 bitpos = nhr->nhr_ReportOutSize;
2696 break;
2697 case REPORT_MAIN_FEATURE:
2698 bitpos = nhr->nhr_ReportFeatSize;
2699 break;
2701 switch(itag)
2703 case REPORT_MAIN_INPUT:
2704 case REPORT_MAIN_OUTPUT:
2705 case REPORT_MAIN_FEATURE:
2707 struct NepHidItem *nhi;
2708 struct NepHidUsage *nhu;
2709 BOOL fakelogmin = FALSE;
2710 BOOL fakelogmax = FALSE;
2711 if(!delim)
2713 KPRINTF(1, ("%s (%lx)\n", (itag == REPORT_MAIN_INPUT) ? "Input" : ((itag == REPORT_MAIN_OUTPUT) ? "Output" : "Feature"), udata));
2714 if(!nhc)
2716 KPRINTF(10, ("No collection open!\n"));
2717 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
2718 "HID Error at %04lx: No collection open!", reportpos);
2719 nDebugReport(nch, nhr);
2720 rptr = NULL;
2721 break;
2723 if(nch->nch_HidGlobal.nhg_LogicalMin == HID_PARAM_UNDEF)
2725 nch->nch_HidGlobal.nhg_LogicalMin = 0;
2726 fakelogmin = TRUE;
2727 if(nch->nch_HidGlobal.nhg_LogicalMax == HID_PARAM_UNDEF)
2729 fakelogmax = TRUE;
2730 if(nch->nch_HidGlobal.nhg_ReportSize < 32)
2732 nch->nch_HidGlobal.nhg_LogicalMax = (1UL<<nch->nch_HidGlobal.nhg_ReportSize)-1;
2733 } else {
2734 nch->nch_HidGlobal.nhg_LogicalMin = 0x80000000;
2735 nch->nch_HidGlobal.nhg_LogicalMax = 0x7fffffff;
2737 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2738 "HID Error at %04lx: LogicalMin and Max for item missing, assuming %ld-%ld (%ld)!",
2739 reportpos,
2740 nch->nch_HidGlobal.nhg_LogicalMin,
2741 nch->nch_HidGlobal.nhg_LogicalMax);
2742 } else {
2743 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2744 "HID Error at %04lx: LogicalMin for item missing, assuming 0!", reportpos);
2747 else if(nch->nch_HidGlobal.nhg_LogicalMax == HID_PARAM_UNDEF)
2749 fakelogmax = TRUE;
2750 nch->nch_HidGlobal.nhg_LogicalMax = (1UL<<nch->nch_HidGlobal.nhg_ReportSize)-1;
2751 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2752 "HID Error at %04lx: LogicalMax for item missing, assuming %ld!", reportpos, nch->nch_HidGlobal.nhg_LogicalMax);
2755 if((nch->nch_HidGlobal.nhg_UsagePage == HID_PARAM_UNDEF) ||
2756 //(nch->nch_HidGlobal.nhg_LogicalMin == HID_PARAM_UNDEF) ||
2757 //(nch->nch_HidGlobal.nhg_LogicalMax == HID_PARAM_UNDEF) ||
2758 (!nch->nch_HidGlobal.nhg_ReportSize)// ||
2759 //(!nch->nch_HidGlobal.nhg_ReportCount) // ReportCount == 0 seems to be a valid input (sigh), just avoid error message
2762 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
2763 "HID Error at %04lx: Mandatory item missing!", reportpos);
2764 nDebugReport(nch, nhr);
2765 KPRINTF(10, ("Mandatory item missing!\n"));
2766 rptr = NULL;
2767 } else {
2768 ULONG *usageptr;
2769 struct List *alistptr;
2770 usageid = designid = stringid = HID_PARAM_UNDEF;
2771 if(udata & RPF_MAIN_VARIABLE)
2773 for(count = 0; count < nch->nch_HidGlobal.nhg_ReportCount; count++)
2775 nhu = (struct NepHidUsage *) nch->nch_HidDesigns.lh_Head;
2776 if(nhu->nhu_Node.ln_Succ)
2778 designid = nhu->nhu_Usage++;
2779 if(nhu->nhu_Usage > nhu->nhu_UsageMax)
2781 Remove(&nhu->nhu_Node);
2782 psdFreeVec(nhu);
2785 nhu = (struct NepHidUsage *) nch->nch_HidStrings.lh_Head;
2786 if(nhu->nhu_Node.ln_Succ)
2788 stringid = nhu->nhu_Usage++;
2789 if(nhu->nhu_Usage > nhu->nhu_UsageMax)
2791 Remove(&nhu->nhu_Node);
2792 psdFreeVec(nhu);
2795 nhu = (struct NepHidUsage *) nch->nch_HidUsages.lh_Head;
2796 if(nhu->nhu_Node.ln_Succ)
2798 usageid = nhu->nhu_Usage++;
2799 if(nhu->nhu_Usage > nhu->nhu_UsageMax)
2801 KPRINTF(1, ("Removing usage %08lx\n", nhu));
2802 Remove(&nhu->nhu_Node);
2803 psdFreeVec(nhu);
2806 if(usageid != HID_PARAM_UNDEF)
2808 if((nhi = psdAllocVec(sizeof(struct NepHidItem))))
2810 nhi->nhi_Collection = nhc;
2811 nhi->nhi_Type = itag;
2812 nhi->nhi_Flags = udata;
2813 nhi->nhi_Offset = bitpos;
2814 nhi->nhi_Size = nch->nch_HidGlobal.nhg_ReportSize;
2816 nhi->nhi_LogicalMin = nch->nch_HidGlobal.nhg_LogicalMin;
2817 nhi->nhi_LogicalMax = nch->nch_HidGlobal.nhg_LogicalMax;
2818 nhi->nhi_IsSigned = (nhi->nhi_LogicalMin < 0) || (nhi->nhi_LogicalMax < 0);
2819 nhi->nhi_PhysicalMin = nch->nch_HidGlobal.nhg_PhysicalMin;
2820 nhi->nhi_PhysicalMax = nch->nch_HidGlobal.nhg_PhysicalMax;
2821 nhi->nhi_UnitExp = nch->nch_HidGlobal.nhg_UnitExp;
2822 nhi->nhi_Unit = nch->nch_HidGlobal.nhg_Unit;
2823 nhi->nhi_Usage = usageid;
2824 nhi->nhi_DesignIndex = designid;
2825 nhi->nhi_StringIndex = stringid;
2826 NewList(&nhi->nhi_ActionList);
2827 AddTail(&nhc->nhc_Items, &nhi->nhi_Node);
2828 KPRINTF(1, ("New Variable Item: %ld.%ld (%ld-%ld) %lx\n",
2829 nhi->nhi_Offset>>3, nhi->nhi_Offset & 7,
2830 nhi->nhi_LogicalMin, nhi->nhi_LogicalMax,
2831 nhi->nhi_Usage));
2834 bitpos += nch->nch_HidGlobal.nhg_ReportSize;
2836 } else {
2837 nhu = (struct NepHidUsage *) nch->nch_HidUsages.lh_Head;
2838 if(nhu->nhu_Node.ln_Succ)
2840 if((nhi = psdAllocVec(sizeof(struct NepHidItem))))
2842 nhi->nhi_Collection = nhc;
2843 nhi->nhi_Type = itag;
2844 nhi->nhi_Flags = udata;
2845 nhi->nhi_Offset = bitpos;
2846 nhi->nhi_Size = nch->nch_HidGlobal.nhg_ReportSize;
2847 nhi->nhi_Count = nch->nch_HidGlobal.nhg_ReportCount;
2849 nhi->nhi_LogicalMin = nch->nch_HidGlobal.nhg_LogicalMin;
2850 nhi->nhi_LogicalMax = nch->nch_HidGlobal.nhg_LogicalMax;
2852 nhi->nhi_MapSize = (nhi->nhi_LogicalMax - nhi->nhi_LogicalMin)+1;
2853 nhi->nhi_UsageMap = psdAllocVec(sizeof(ULONG) * nhi->nhi_MapSize);
2854 nhi->nhi_ActionMap = psdAllocVec(sizeof(struct List) * nhi->nhi_MapSize);
2855 nhi->nhi_Buffer = psdAllocVec(2 * sizeof(LONG) * nhi->nhi_Count);
2856 nhi->nhi_OldBuffer = &nhi->nhi_Buffer[nhi->nhi_Count];
2857 nhi->nhi_PhysicalMin = nch->nch_HidGlobal.nhg_PhysicalMin;
2858 nhi->nhi_PhysicalMax = nch->nch_HidGlobal.nhg_PhysicalMax;
2859 nhi->nhi_UnitExp = nch->nch_HidGlobal.nhg_UnitExp;
2860 nhi->nhi_Unit = nch->nch_HidGlobal.nhg_Unit;
2862 usageptr = nhi->nhi_UsageMap;
2863 alistptr = nhi->nhi_ActionMap;
2864 if(!(usageptr && alistptr && nhi->nhi_Buffer))
2866 psdFreeVec(usageptr);
2867 psdFreeVec(alistptr);
2868 psdFreeVec(nhi->nhi_Buffer);
2869 psdFreeVec(nhi);
2870 KPRINTF(10, ("Out of memory\n"));
2871 rptr = NULL;
2872 break;
2875 nhi->nhi_Usage = nhi->nhi_DesignIndex = nhi->nhi_StringIndex = HID_PARAM_UNDEF;
2876 NewList(&nhi->nhi_ActionList);
2878 KPRINTF(1, ("New Array(%ld*%ld) Item: %ld.%ld (%ld-%ld)\n",
2879 nhi->nhi_Count, nhi->nhi_MapSize,
2880 nhi->nhi_Offset>>3, nhi->nhi_Offset & 7,
2881 nhi->nhi_LogicalMin, nhi->nhi_LogicalMax));
2883 nhi->nhi_SameUsages = TRUE;
2884 for (count = nhi->nhi_MapSize; count; count--)
2886 nhu = (struct NepHidUsage *) nch->nch_HidDesigns.lh_Head;
2887 if(nhu->nhu_Node.ln_Succ)
2889 designid = nhu->nhu_Usage++;
2890 if(nhu->nhu_Usage > nhu->nhu_UsageMax)
2892 Remove(&nhu->nhu_Node);
2893 psdFreeVec(nhu);
2896 nhu = (struct NepHidUsage *) nch->nch_HidStrings.lh_Head;
2897 if(nhu->nhu_Node.ln_Succ)
2899 stringid = nhu->nhu_Usage++;
2900 if(nhu->nhu_Usage > nhu->nhu_UsageMax)
2902 Remove(&nhu->nhu_Node);
2903 psdFreeVec(nhu);
2906 nhu = (struct NepHidUsage *) nch->nch_HidUsages.lh_Head;
2907 if(nhu->nhu_Node.ln_Succ)
2909 usageid = nhu->nhu_Usage++;
2910 if(nhu->nhu_Usage > nhu->nhu_UsageMax)
2912 KPRINTF(1, ("Removing usage %08lx\n", nhu));
2913 Remove(&nhu->nhu_Node);
2914 psdFreeVec(nhu);
2918 // check if usages are all the same
2919 if(count < nhi->nhi_MapSize)
2921 if(usageid != usageptr[-1])
2923 nhi->nhi_SameUsages = FALSE;
2927 *usageptr++ = usageid;
2928 NewList(alistptr);
2929 alistptr++;
2932 if(nhi->nhi_SameUsages)
2934 // if it's all the same, we can assign a usage id to this array
2935 nhi->nhi_Usage = nhi->nhi_UsageMap[0];
2937 if(nhi->nhi_MapSize)
2939 AddTail(&nhc->nhc_Items, &nhi->nhi_Node);
2942 } /* FIXME: Clean string/delimiter stack if no usage? */
2943 bitpos += nch->nch_HidGlobal.nhg_ReportSize * nch->nch_HidGlobal.nhg_ReportCount;
2946 if(fakelogmin)
2948 nch->nch_HidGlobal.nhg_LogicalMin = HID_PARAM_UNDEF;
2950 if(fakelogmax)
2952 nch->nch_HidGlobal.nhg_LogicalMax = HID_PARAM_UNDEF;
2955 break;
2958 case REPORT_MAIN_COLLECT:
2960 struct NepHidUsage *nhu;
2961 struct NepHidCollection *oldnhc = nhc;
2962 KPRINTF(1, ("Collection(%lx)\n", udata));
2963 if((nhc = psdAllocVec(sizeof(struct NepHidCollection))))
2965 NewList(&nhc->nhc_Items);
2966 nhc->nhc_Parent = oldnhc;
2967 nhu = (struct NepHidUsage *) nch->nch_HidUsages.lh_Head;
2968 if(nhu->nhu_Node.ln_Succ)
2970 nhc->nhc_Usage = nhu->nhu_Usage;
2971 nhc->nhc_Name = nGetUsageName(nch, nhu->nhu_Usage);
2972 } else {
2973 if(nhc->nhc_Parent)
2975 nhc->nhc_Usage = nhc->nhc_Parent->nhc_Usage;
2976 nhc->nhc_Name = psdCopyStr(nhc->nhc_Parent->nhc_Name);
2977 } else {
2978 nhc->nhc_Name = psdCopyStr("Argl!");
2982 node = nch->nch_HidUsages.lh_Head;
2983 while(node->ln_Succ)
2985 KPRINTF(1, ("Removing usage %08lx\n", node));
2986 Remove(node);
2987 psdFreeVec(node);
2988 node = nch->nch_HidUsages.lh_Head;
2990 break;
2993 case REPORT_MAIN_ENDCOLL:
2994 KPRINTF(1, ("EndCollection(%lx)\n", udata));
2995 if(nhc)
2997 /* Get rid of empty collection */
2998 //if(!nhc->nhc_Items.lh_Head->ln_Succ)
2999 if(0) /* don't do this, we might need the parent collection! */
3001 struct NepHidCollection *oldnhc = nhc;
3002 KPRINTF(1, ("Deleting empty collection %lx (%s)\n", nhc, nhc->nhc_Name));
3003 nhc = nhc->nhc_Parent;
3004 psdFreeVec(oldnhc->nhc_Name);
3005 psdFreeVec(oldnhc);
3006 } else {
3007 AddTail(&nhr->nhr_Collections, &nhc->nhc_Node);
3008 nhc->nhc_Report = nhr;
3009 nhc = nhc->nhc_Parent;
3012 break;
3014 default:
3015 KPRINTF(1, ("Reserved_%02lx(%lx)\n", itag, data));
3016 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
3017 "HID Error at %04lx: Reserved_MAIN_%02lx(%lx)", reportpos, itag, data);
3018 nDebugReport(nch, nhr);
3019 rptr = NULL;
3020 break;
3022 /* Remove remaining usages */
3023 node = nch->nch_HidUsages.lh_Head;
3024 while(node->ln_Succ)
3026 KPRINTF(1, ("MainEnd: Removing usage %08lx\n", node));
3027 Remove(node);
3028 psdFreeVec(node);
3029 node = nch->nch_HidUsages.lh_Head;
3031 /* Remove remaining designators */
3032 node = nch->nch_HidDesigns.lh_Head;
3033 while(node->ln_Succ)
3035 KPRINTF(1, ("MainEnd: Removing designator %08lx\n", node));
3036 Remove(node);
3037 psdFreeVec(node);
3038 node = nch->nch_HidDesigns.lh_Head;
3040 /* Remove remaining strings */
3041 node = nch->nch_HidStrings.lh_Head;
3042 while(node->ln_Succ)
3044 KPRINTF(1, ("MainEnd: Removing strings %08lx\n", node));
3045 Remove(node);
3046 psdFreeVec(node);
3047 node = nch->nch_HidStrings.lh_Head;
3050 switch(itag)
3052 case REPORT_MAIN_INPUT:
3053 nhr->nhr_ReportInSize = bitpos;
3054 break;
3055 case REPORT_MAIN_OUTPUT:
3056 nhr->nhr_ReportOutSize = bitpos;
3057 break;
3058 case REPORT_MAIN_FEATURE:
3059 nhr->nhr_ReportFeatSize = bitpos;
3060 break;
3063 break;
3065 case REPORT_ITYPE_GLOBAL:
3066 //KPRINTF(1, ("Global "));
3067 switch(itag)
3069 case REPORT_GLOB_USAGE:
3070 KPRINTF(1, ("Usage Page(%ld) %s\n", udata, nNumToStr(nch, NTS_USAGEPAGE, udata, "unknown")));
3071 nch->nch_HidGlobal.nhg_UsagePage = udata;
3072 break;
3074 case REPORT_GLOB_LOGMIN:
3075 KPRINTF(1, ("LogMin(%ld)\n", data));
3076 nch->nch_HidGlobal.nhg_LogicalMin = data;
3077 break;
3079 case REPORT_GLOB_LOGMAX:
3080 /* Some devices (like usb-kbd in QEMU) have wrong descriptors
3081 * Try to detect and correct this here which seems to be what other OSes do
3082 * This only works if LogMin is defined before LogMax but that's likely common
3084 nch->nch_HidGlobal.nhg_LogicalMax = (data < nch->nch_HidGlobal.nhg_LogicalMin ? udata : data);
3085 KPRINTF(1, ("LogMax(%ld)\n", nch->nch_HidGlobal.nhg_LogicalMax));
3086 break;
3088 case REPORT_GLOB_PHYMIN:
3089 KPRINTF(1, ("PhyMin(%ld)\n", data));
3090 nch->nch_HidGlobal.nhg_PhysicalMin = data;
3091 break;
3093 case REPORT_GLOB_PHYMAX:
3094 nch->nch_HidGlobal.nhg_PhysicalMax = (data < nch->nch_HidGlobal.nhg_PhysicalMin ? udata : data);
3095 KPRINTF(1, ("PhyMax(%ld)\n", nch->nch_HidGlobal.nhg_PhysicalMax));
3096 break;
3098 case REPORT_GLOB_UNITEXP:
3099 KPRINTF(1, ("UnitExp(%ld)\n", data));
3100 nch->nch_HidGlobal.nhg_UnitExp = data;
3101 break;
3103 case REPORT_GLOB_UNIT:
3104 KPRINTF(1, ("Unit(%ld)\n", data));
3105 nch->nch_HidGlobal.nhg_Unit = data;
3106 break;
3108 case REPORT_GLOB_RPSIZE:
3109 KPRINTF(1, ("ReportSize(%ld)\n", udata));
3110 nch->nch_HidGlobal.nhg_ReportSize = udata;
3111 break;
3113 case REPORT_GLOB_RPID:
3114 KPRINTF(1, ("ReportID(%ld)\n", udata));
3115 nch->nch_HidGlobal.nhg_ReportID = udata;
3116 break;
3118 case REPORT_GLOB_RPCOUNT:
3119 KPRINTF(1, ("ReportCount(%ld)\n", udata));
3120 nch->nch_HidGlobal.nhg_ReportCount = udata;
3121 break;
3123 case REPORT_GLOB_PUSH:
3125 struct NepHidGlobal *nhg = psdAllocVec(sizeof(struct NepHidGlobal));
3126 KPRINTF(1, ("Push(%ld)\n", data));
3127 if(nhg)
3129 *nhg = nch->nch_HidGlobal;
3130 AddTail(&nch->nch_HidStack, &nhg->nhg_Node);
3131 } else {
3132 KPRINTF(10, ("Out of HID stack memory!\n"));
3133 rptr = NULL;
3135 break;
3138 case REPORT_GLOB_POP:
3140 struct NepHidGlobal *nhg = (struct NepHidGlobal *) nch->nch_HidStack.lh_Tail;
3141 KPRINTF(1, ("Pop(%ld)\n", data));
3142 if(nhg->nhg_Node.ln_Pred)
3144 nch->nch_HidGlobal = *nhg;
3145 Remove(&nhg->nhg_Node);
3146 psdFreeVec(nhg);
3147 } else {
3148 KPRINTF(10, ("Pop from HID stack without push!\n"));
3149 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
3150 "HID Error at %04lx: Pop from HID stack without push!", reportpos);
3151 nDebugReport(nch, nhr);
3152 rptr = NULL;
3154 break;
3157 default:
3158 KPRINTF(1, ("Reserved_%02lx(%lx)\n", itag, data));
3159 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
3160 "HID Error at %04lx: Reserved_GLOBAL_%02lx(%lx)", reportpos, itag, data);
3161 nDebugReport(nch, nhr);
3162 rptr = NULL;
3163 break;
3165 break;
3167 case REPORT_ITYPE_LOCAL:
3168 //KPRINTF(1, ("Local "));
3169 switch(itag)
3171 case REPORT_LOCL_USAGE:
3172 if(len <= 2)
3174 udata |= nch->nch_HidGlobal.nhg_UsagePage<<16;
3176 KPRINTF(1, ("Usage (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3177 if(!nAddUsage(nch, &nch->nch_HidUsages, udata, udata))
3179 rptr = NULL;
3181 break;
3183 case REPORT_LOCL_USEMIN:
3184 if(len <= 2)
3186 udata |= nch->nch_HidGlobal.nhg_UsagePage<<16;
3188 KPRINTF(1, ("UsageMin (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3189 usagemin = udata;
3190 if(usagemax != HID_PARAM_UNDEF)
3192 if(!nAddUsage(nch, &nch->nch_HidUsages, usagemin, usagemax))
3194 rptr = NULL;
3196 usagemin = usagemax = HID_PARAM_UNDEF;
3198 break;
3200 case REPORT_LOCL_USEMAX:
3201 if(len <= 2)
3203 udata |= nch->nch_HidGlobal.nhg_UsagePage<<16;
3205 KPRINTF(1, ("UsageMax (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3206 usagemax = udata;
3207 if(usagemin != HID_PARAM_UNDEF)
3209 if(!nAddUsage(nch, &nch->nch_HidUsages, usagemin, usagemax))
3211 rptr = NULL;
3213 usagemin = usagemax = HID_PARAM_UNDEF;
3215 break;
3217 case REPORT_LOCL_DESIDX:
3218 KPRINTF(1, ("Designator index (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3219 if(!nAddUsage(nch, &nch->nch_HidDesigns, udata, udata))
3221 rptr = NULL;
3223 break;
3225 case REPORT_LOCL_DESMIN:
3226 KPRINTF(1, ("DesignMin (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3227 designmin = udata;
3228 if(designmax != HID_PARAM_UNDEF)
3230 if(!nAddUsage(nch, &nch->nch_HidDesigns, designmin, designmax))
3232 rptr = NULL;
3234 designmin = designmax = HID_PARAM_UNDEF;
3236 break;
3238 case REPORT_LOCL_DESMAX:
3239 KPRINTF(1, ("DesignMax (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3240 designmin = udata;
3241 if(designmax != HID_PARAM_UNDEF)
3243 if(!nAddUsage(nch, &nch->nch_HidDesigns, designmin, designmax))
3245 rptr = NULL;
3247 designmin = designmax = HID_PARAM_UNDEF;
3249 break;
3251 case REPORT_LOCL_STRIDX:
3252 KPRINTF(1, ("String index (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3253 if(!nAddUsage(nch, &nch->nch_HidStrings, udata, udata))
3255 rptr = NULL;
3257 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3258 "HID String Index %ld", udata);
3259 break;
3261 case REPORT_LOCL_STRMIN:
3262 KPRINTF(1, ("StringMin (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3263 stringmin = udata;
3264 if(stringmax != HID_PARAM_UNDEF)
3266 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3267 "HID String Index Range %ld - %ld", stringmin, stringmax);
3268 if(!nAddUsage(nch, &nch->nch_HidStrings, stringmin, stringmax))
3270 rptr = NULL;
3272 stringmin = stringmax = HID_PARAM_UNDEF;
3274 break;
3276 case REPORT_LOCL_STRMAX:
3277 KPRINTF(1, ("StringMax (%lx) %s\n", udata, nNumToStr(nch, NTS_USAGEID, udata, "unknown")));
3278 stringmax = udata;
3279 if(stringmin != HID_PARAM_UNDEF)
3281 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3282 "HID String Index Range %ld - %ld", stringmin, stringmax);
3283 if(!nAddUsage(nch, &nch->nch_HidStrings, stringmin, stringmax))
3285 rptr = NULL;
3287 stringmin = stringmax = HID_PARAM_UNDEF;
3289 break;
3291 case REPORT_LOCL_DELIM:
3292 KPRINTF(1, ("Delimiter (%ld)\n", udata));
3293 if(udata)
3295 delim++;
3296 } else {
3297 delim--;
3299 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "HID Report Delimiters not really supported!");
3300 break;
3302 default:
3303 KPRINTF(1, ("Reserved_%02lx(%lx)\n", itag, udata));
3304 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
3305 "HID Error at %04lx: Reserved_LOCAL_%02lx(%lx)", reportpos, itag, udata);
3306 nDebugReport(nch, nhr);
3307 rptr = NULL;
3308 break;
3310 break;
3312 default:
3313 KPRINTF(1, ("Reserved!\n"));
3314 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
3315 "HID Error at %04lx: Reserved_%02lx", reportpos, itag);
3316 nDebugReport(nch, nhr);
3317 rptr = NULL;
3318 break;
3321 KPRINTF(1, ("Parsing done, status %lx.\n", rptr));
3323 /* Remove remaining stack frame */
3324 node = nch->nch_HidStack.lh_Head;
3325 while(node->ln_Succ)
3327 KPRINTF(1, ("Removing stack frame %08lx\n", node));
3328 Remove(node);
3329 psdFreeVec(node);
3330 node = nch->nch_HidStack.lh_Head;
3332 /* Remove remaining usages */
3333 node = nch->nch_HidUsages.lh_Head;
3334 while(node->ln_Succ)
3336 KPRINTF(1, ("Removing usage %08lx\n", node));
3337 Remove(node);
3338 psdFreeVec(node);
3339 node = nch->nch_HidUsages.lh_Head;
3341 /* Remove remaining designators */
3342 node = nch->nch_HidDesigns.lh_Head;
3343 while(node->ln_Succ)
3345 KPRINTF(1, ("Removing designator %08lx\n", node));
3346 Remove(node);
3347 psdFreeVec(node);
3348 node = nch->nch_HidDesigns.lh_Head;
3350 /* Remove remaining strings */
3351 node = nch->nch_HidStrings.lh_Head;
3352 while(node->ln_Succ)
3354 KPRINTF(1, ("Removing strings %08lx\n", node));
3355 Remove(node);
3356 psdFreeVec(node);
3357 node = nch->nch_HidStrings.lh_Head;
3359 //nDebugReport(nch, nhr);
3360 return((BOOL) (rptr ? TRUE : FALSE));
3362 /* \\\ */
3364 /* /// "nFindCollID()" */
3365 BOOL nFindCollID(struct NepClassHid *nch, struct NepHidCollection *nhc, ULONG collidmin, ULONG collidmax)
3369 if((nhc->nhc_Usage >= collidmin) && (nhc->nhc_Usage <= collidmax))
3371 return(TRUE);
3373 } while((nhc = nhc->nhc_Parent));
3374 return(FALSE);
3376 /* \\\ */
3378 /* /// "nFindItemID()" */
3379 struct NepHidItem * nFindItemID(struct NepClassHid *nch, UWORD id, UWORD itype, ULONG *pos)
3381 struct NepHidReport *nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
3382 struct NepHidItem *nhi;
3383 struct NepHidItem **nhiptr;
3384 struct List *alistptr;
3385 ULONG count;
3386 ULONG icount;
3387 BOOL featmode;
3389 if(itype == REPORT_MAIN_OUTPUT)
3391 featmode = FALSE;
3393 else if(itype == REPORT_MAIN_FEATURE)
3395 featmode = TRUE;
3396 } else {
3397 return(NULL);
3399 while(nhr->nhr_Node.ln_Succ)
3401 nhiptr = NULL;
3402 if(featmode)
3404 if((icount = nhr->nhr_FeatItemCount))
3406 nhiptr = nhr->nhr_FeatItemMap;
3408 } else {
3409 if((icount = nhr->nhr_OutItemCount))
3411 nhiptr = nhr->nhr_OutItemMap;
3414 if(nhiptr)
3418 nhi = *nhiptr++;
3419 if(GET_WTYPE(&nhi->nhi_ActionList) == id)
3421 *pos = 0xffffffff;
3422 return(nhi);
3424 if(!(nhi->nhi_Flags & RPF_MAIN_VARIABLE))
3426 alistptr = nhi->nhi_ActionMap;
3427 count = nhi->nhi_MapSize;
3430 if(GET_WTYPE(alistptr) == id)
3432 *pos = nhi->nhi_MapSize - count;
3433 return(nhi);
3435 alistptr++;
3436 } while(--count);
3439 while(--icount);
3441 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
3443 return(NULL);
3445 /* \\\ */
3447 /* /// "nFindItemUsage()" */
3448 UWORD nFindItemUsage(struct NepClassHid *nch, ULONG usage, UWORD itype)
3450 struct NepHidReport *nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
3451 struct NepHidItem *nhi;
3452 struct NepHidItem **nhiptr;
3453 ULONG *usageptr;
3454 struct List *alistptr;
3455 ULONG count;
3456 ULONG icount;
3457 BOOL featmode;
3459 if(itype == REPORT_MAIN_OUTPUT)
3461 featmode = FALSE;
3463 else if(itype == REPORT_MAIN_FEATURE)
3465 featmode = TRUE;
3466 } else {
3467 return(0);
3470 while(nhr->nhr_Node.ln_Succ)
3472 nhiptr = NULL;
3473 if(featmode)
3475 if((icount = nhr->nhr_FeatItemCount))
3477 nhiptr = nhr->nhr_FeatItemMap;
3479 } else {
3480 if((icount = nhr->nhr_OutItemCount))
3482 nhiptr = nhr->nhr_OutItemMap;
3485 if(nhiptr)
3489 nhi = *nhiptr++;
3490 if(nhi->nhi_Usage == usage)
3492 return(GET_WTYPE(&nhi->nhi_ActionList));
3494 if(!(nhi->nhi_Flags & RPF_MAIN_VARIABLE))
3496 usageptr = nhi->nhi_UsageMap;
3497 alistptr = nhi->nhi_ActionMap;
3498 count = nhi->nhi_MapSize;
3501 if(*usageptr == usage)
3503 return GET_WTYPE(alistptr);
3505 usageptr++;
3506 alistptr++;
3507 } while(--count);
3510 while(--icount);
3512 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
3514 return(0);
3516 /* \\\ */
3518 /* /// "UsbToPs2 Mapping" */
3519 const struct UsbToPs2Map usbtops2map[] =
3521 { 0x010081, 0x5e }, // System Power Down
3522 { 0x010082, 0x5f }, // System Sleep
3523 { 0x010083, 0x63 }, // System Wake Up
3525 { 0x070046, 0x4c }, // Keyboard Print Screen
3526 { 0x070047, 0x64 }, // Keyboard Scroll Lock
3527 { 0x070048, 0x45 }, // Keyboard Pause
3528 { 0x070049, 0x0a }, // Keyboard Insert
3530 { 0x070066, 0x5e }, // Keyboard Power
3532 { 0x07007A, 0x08 }, // Keyboard Undo
3533 { 0x07007B, 0x17 }, // Keyboard Cut
3534 { 0x07007C, 0x18 }, // Keyboard Copy
3535 { 0x07007D, 0x0a }, // Keyboard Paste
3536 { 0x07007F, 0x20 }, // Keyboard Mute
3537 { 0x070080, 0x30 }, // Keyboard Volume Up
3538 { 0x070081, 0x2e }, // Keyboard Volume Down
3540 { 0x0C0030, 0x5e }, // Power
3541 { 0x0C0032, 0x5f }, // Sleep
3542 { 0x0C0033, 0x5f }, // Sleep After
3543 { 0x0C0034, 0x5f }, // Sleep Mode
3545 { 0x0C0094, 0x40 }, // Quit
3546 { 0x0C0095, 0x3b }, // Help
3547 { 0x0C00B0, 0x22 }, // Play
3548 { 0x0C00B1, 0x22 }, // Pause
3549 { 0x0C00B5, 0x19 }, // Scan Next Track
3550 { 0x0C00B6, 0x10 }, // Scan Previous Track
3551 { 0x0C00B7, 0x24 }, // Stop
3552 { 0x0C00CC, 0x24 }, // Stop/Eject
3553 { 0x0C00CD, 0x22 }, // Play/Pause
3554 { 0x0C00CE, 0x22 }, // Play/Skip
3556 { 0x0C00E2, 0x20 }, // Mute
3557 { 0x0C00E9, 0x30 }, // Volume Increment
3558 { 0x0C00EA, 0x2e }, // Volume Decrement
3560 { 0x0C0183, 0x6d }, // AL Consumer Control Configuration
3561 { 0x0C0184, 0x13 }, // AL Word Processor
3562 { 0x0C0185, 0x13 }, // AL Text Editor
3563 { 0x0C0186, 0x14 }, // AL Spreadsheet
3564 { 0x0C018A, 0x6c }, // AL Email Reader
3565 { 0x0C018F, 0x3d }, // AL Task/Project Manager
3566 { 0x0C0192, 0x21 }, // AL Calculator
3567 { 0x0C0194, 0x3c }, // AL Local Machine Browser
3568 { 0x0C0196, 0x3c }, // AL Internet Browser
3569 { 0x0C019B, 0x16 }, // AL Logon
3570 { 0x0C019C, 0x16 }, // AL Logoff
3571 { 0x0C019D, 0x16 }, // AL Logon/Logoff
3572 { 0x0C01A1, 0x3d }, // AL Process/Task Manager
3573 { 0x0C01A3, 0x1e }, // AL Next Task/Application
3574 { 0x0C01A4, 0x09 }, // AL Previous Task/Application
3575 { 0x0C01A6, 0x3b }, // AL Integrated Help Center
3576 { 0x0C01A7, 0x6b }, // AL Documents
3577 { 0x0C01A8, 0x23 }, // AL Thesaurus
3578 { 0x0C01A9, 0x23 }, // AL Dictionary
3579 { 0x0C01AB, 0x23 }, // AL Spell Check
3580 { 0x0C01AC, 0x23 }, // AL Grammar Check
3581 { 0x0C01B4, 0x05 }, // AL File Browser
3582 { 0x0C01BD, 0x3b }, // AL OEM Features/ Tips/Tutorial Browser
3583 { 0x0C01BE, 0x3b }, // AL OEM Help
3585 { 0x0C0201, 0x3e }, // AC New
3586 { 0x0C0202, 0x3f }, // AC Open
3587 { 0x0C0203, 0x40 }, // AC Close
3588 { 0x0C0204, 0x40 }, // AC Exit
3589 { 0x0C0207, 0x57 }, // AC Save
3590 { 0x0C0208, 0x58 }, // AC Print
3591 { 0x0C021A, 0x08 }, // AC Undo
3592 { 0x0C021B, 0x18 }, // AC Copy
3593 { 0x0C021C, 0x17 }, // AC Cut
3594 { 0x0C021D, 0x0a }, // AC Paste
3595 { 0x0C021F, 0x65 }, // AC Find
3596 { 0x0C0220, 0x65 }, // AC Find and Replace
3597 { 0x0C0221, 0x65 }, // AC Search
3598 { 0x0C0223, 0x32 }, // AC Home
3599 { 0x0C0224, 0x6a }, // AC Back
3600 { 0x0C0225, 0x69 }, // AC Forward
3601 { 0x0C0226, 0x68 }, // AC Stop
3602 { 0x0C0227, 0x67 }, // AC Refresh
3603 { 0x0C0228, 0x6a }, // AC Previous Link
3604 { 0x0C0229, 0x69 }, // AC Next Link
3605 { 0x0C022A, 0x66 }, // AC Bookmarks
3606 { 0x0C022B, 0x66 }, // AC History
3607 { 0x0C022C, 0x66 }, // AC Subscriptions
3608 { 0x0C0279, 0x07 }, // AC Redo/Repeat
3609 { 0x0C0288, 0x43 }, // AC Send To
3610 { 0x0C0289, 0x41 }, // AC Reply
3611 { 0x0C028A, 0x41 }, // AC Reply All
3612 { 0x0C028B, 0x42 }, // AC Forward Msg
3613 { 0x0C028C, 0x43 }, // AC Send
3615 { 0x000000, 0x00 }
3617 /* \\\ */
3619 /* /// "nDetectDefaultAction()" */
3620 BOOL nDetectDefaultAction(struct NepClassHid *nch, struct NepHidItem *nhi, struct List *lst, struct NepHidCollection *nhc, ULONG uid)
3622 BOOL res = FALSE;
3623 UWORD usageid = uid;
3624 struct NepHidAction *nha;
3625 struct WacomCaps *wc;
3626 const struct UsbToPs2Map *utp = usbtops2map;
3628 switch(uid>>16)
3630 case 0x01: /* generic desktop page */
3631 if(usageid == 0xfff0) /* extra init */
3633 /* AipTek USB Tablets Support */
3634 IPTR vendid = 0;
3635 IPTR prodid = 0;
3636 ULONG command;
3637 ULONG data;
3639 psdGetAttrs(PGA_DEVICE, nch->nch_Device,
3640 DA_VendorID, &vendid,
3641 DA_ProductID, &prodid,
3642 TAG_END);
3643 if((vendid == 0x08ca) &&
3644 ((prodid == 0x0001) || (prodid == 0x0010) ||
3645 ((prodid >= 0x0020) && (prodid <= 0x0024))) &&
3646 (!nhi->nhi_ActionList.lh_Head->ln_Succ))
3648 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3649 "Generating special AipTek USB Tablet init sequence.");
3650 command = nFindItemUsage(nch, 0x0D003F, REPORT_MAIN_FEATURE);
3651 data = nFindItemUsage(nch, 0x0D0040, REPORT_MAIN_FEATURE);
3652 if(command && data)
3654 /* set resolution to 500DPI */
3655 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3657 nha->nha_FeatOp = HUAT_ASSIGN;
3658 nha->nha_FeatItem = command;
3659 nha->nha_ValEnable = TRUE;
3660 nha->nha_ValVar = HUAT_CONST;
3661 nha->nha_ValConst = 0x18;
3663 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3665 nha->nha_FeatOp = HUAT_ASSIGN;
3666 nha->nha_FeatItem = data;
3667 nha->nha_ValEnable = TRUE;
3668 nha->nha_ValVar = HUAT_CONST;
3669 nha->nha_ValConst = 0x04;
3671 if((nha = nAllocAction(nch, lst, HUA_MISC|HUA_ANY)))
3673 nha->nha_MiscMode = HUAT_FLUSHEVENTS;
3676 /* set absolute tablet mode */
3677 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3679 nha->nha_FeatOp = HUAT_ASSIGN;
3680 nha->nha_FeatItem = command;
3681 nha->nha_ValEnable = TRUE;
3682 nha->nha_ValVar = HUAT_CONST;
3683 nha->nha_ValConst = 0x10;
3685 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3687 nha->nha_FeatOp = HUAT_ASSIGN;
3688 nha->nha_FeatItem = data;
3689 nha->nha_ValEnable = TRUE;
3690 nha->nha_ValVar = HUAT_CONST;
3691 nha->nha_ValConst = 0x01;
3693 if((nha = nAllocAction(nch, lst, HUA_MISC|HUA_ANY)))
3695 nha->nha_MiscMode = HUAT_FLUSHEVENTS;
3698 /* enable macro keys */
3699 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3701 nha->nha_FeatOp = HUAT_ASSIGN;
3702 nha->nha_FeatItem = command;
3703 nha->nha_ValEnable = TRUE;
3704 nha->nha_ValVar = HUAT_CONST;
3705 nha->nha_ValConst = 0x11;
3707 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3709 nha->nha_FeatOp = HUAT_ASSIGN;
3710 nha->nha_FeatItem = data;
3711 nha->nha_ValEnable = TRUE;
3712 nha->nha_ValVar = HUAT_CONST;
3713 nha->nha_ValConst = 0x02;
3715 if((nha = nAllocAction(nch, lst, HUA_MISC|HUA_ANY)))
3717 nha->nha_MiscMode = HUAT_FLUSHEVENTS;
3720 /* enable auto gain */
3721 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3723 nha->nha_FeatOp = HUAT_ASSIGN;
3724 nha->nha_FeatItem = command;
3725 nha->nha_ValEnable = TRUE;
3726 nha->nha_ValVar = HUAT_CONST;
3727 nha->nha_ValConst = 0x12;
3729 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3731 nha->nha_FeatOp = HUAT_ASSIGN;
3732 nha->nha_FeatItem = data;
3733 nha->nha_ValEnable = TRUE;
3734 nha->nha_ValVar = HUAT_CONST;
3735 nha->nha_ValConst = 0xff;
3737 /*if((nha = nAllocAction(nch, lst, HUA_MISC|HUA_ANY)))
3739 nha->nha_MiscMode = HUAT_FLUSHEVENTS;
3741 } else {
3742 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
3743 "AipTek: No command (%ld) or data (%ld) feature!", command, data);
3746 if(vendid == 0x056a)
3748 for(wc = WacomCapsTable; wc->wc_ProdID != prodid; wc++)
3750 if(wc->wc_ProdID == 0xffff)
3752 wc = NULL;
3753 break;
3756 } else {
3757 wc = NULL;
3759 if(wc)
3761 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3762 "Generating special Wacom USB Tablet init sequence.");
3763 command = nFindItemUsage(nch, 0xff000001, REPORT_MAIN_FEATURE);
3764 if(command)
3766 /* activate returning of absolute tablet data */
3767 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3769 nha->nha_FeatOp = HUAT_ASSIGN;
3770 nha->nha_FeatItem = command;
3771 nha->nha_ValEnable = TRUE;
3772 nha->nha_ValVar = HUAT_CONST;
3773 nha->nha_ValConst = 0x02;
3775 if((nha = nAllocAction(nch, lst, HUA_MISC|HUA_ANY)))
3777 nha->nha_MiscMode = HUAT_FLUSHEVENTS;
3779 if((nha = nAllocAction(nch, lst, HUA_FEATURE|HUA_ANY)))
3781 nha->nha_FeatOp = HUAT_ASSIGN;
3782 nha->nha_FeatItem = command;
3783 nha->nha_ValEnable = TRUE;
3784 nha->nha_ValVar = HUAT_CONST;
3785 nha->nha_ValConst = 0x02;
3790 if((vendid == 0x046d) &&
3791 (!nhi->nhi_ActionList.lh_Head->ln_Succ))
3793 command = nFindItemUsage(nch, 0xff000001, REPORT_MAIN_OUTPUT);
3794 if(command)
3796 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
3797 "Adding special HID2HCI Logitech Bluetooth init sequence, but deactivated!");
3798 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3799 "This init sequence would disable HID usage and enable pure Bluetooth use!");
3800 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
3801 "If you want to use this dongle for Bluetooth, switch the NOP-Startup-Actions to type Output!");
3802 // send three commands to output report 0x10
3803 if((nha = nAllocAction(nch, lst, HUA_NOP|HUA_ANY)))
3805 nha->nha_OutItem = command;
3806 strcpy(nha->nha_OutArray, "0xff, 0x80, 0x80, 0x01, 0x00, 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, 0x80, 0x00, 0x00, 0x30, 0x00");
3817 if((nha = nAllocAction(nch, lst, HUA_MISC|HUA_ANY)))
3819 nha->nha_MiscMode = HUAT_FLUSHEVENTS;
3821 if((nha = nAllocAction(nch, lst, HUA_NOP|HUA_ANY)))
3823 nha->nha_OutItem = command;
3824 strcpy(nha->nha_OutArray, "0xff, 0x81, 0x80, 0x00, 0x00, 0x00");
3830 if(nFindCollID(nch, nhc, 0x010002, 0x010002) || /* Mice */
3831 nFindCollID(nch, nhc, 0x0d0001, 0x0d000d)) /* Tablets */
3833 switch(usageid)
3835 case 0x30: /* Mouse X */
3836 if((nha = nAllocAction(nch, lst, HUA_MOUSEPOS|HUA_ALWAYS)))
3838 if(nhi->nhi_Flags & RPF_MAIN_RELATIVE)
3840 nha->nha_MouseAxis = HUAT_DELTAX;
3841 } else {
3842 nha->nha_MouseAxis = HUAT_ABSX;
3843 nha->nha_ClipEnable = TRUE;
3844 nha->nha_ClipMin = 5;
3845 nha->nha_ClipMax = 95;
3846 nha->nha_ClipStretch = TRUE;
3849 break;
3851 case 0x31: /* Mouse Y */
3852 if((nha = nAllocAction(nch, lst, HUA_MOUSEPOS|HUA_ALWAYS)))
3854 if(nhi->nhi_Flags & RPF_MAIN_RELATIVE)
3856 nha->nha_MouseAxis = HUAT_DELTAY;
3857 } else {
3858 nha->nha_MouseAxis = HUAT_ABSY;
3859 nha->nha_ClipEnable = TRUE;
3860 nha->nha_ClipMin = 5;
3861 nha->nha_ClipMax = 95;
3862 nha->nha_ClipStretch = TRUE;
3865 break;
3867 case 0x38: /* Wheel */
3868 if((nha = nAllocAction(nch, lst, HUA_WHEEL|HUA_ALWAYS)))
3870 nha->nha_WheelMode = HUAT_DELTAY;
3871 nha->nha_WheelDist = 1;
3873 break;
3877 if(nFindCollID(nch, nhc, 0x010004, 0x010005)) /* Joystick, Game Pad */
3879 switch(usageid)
3881 case 0x39: /* Hatswitch */
3882 if((nha = nAllocAction(nch, lst, HUA_DIGJOY|HUA_NAN)))
3884 nha->nha_JoypadOp = HUAT_CLEAR;
3885 nha->nha_JoypadFeat = HUAT_HATSWITCH;
3886 nha->nha_JoypadPort = 1;
3888 if((nha = nAllocAction(nch, lst, HUA_DIGJOY|HUA_ALWAYS)))
3890 nha->nha_JoypadOp = HUAT_ASSIGN;
3891 nha->nha_JoypadFeat = HUAT_HATSWITCH;
3892 nha->nha_JoypadPort = 1;
3894 break;
3896 case 0x30: /* X axis */
3897 case 0x35: /* Z rotation */
3898 case 0x31: /* Y axis */
3899 case 0x32: /* Z axis */
3901 ULONG minpos = ((nhi->nhi_LogicalMax - nhi->nhi_LogicalMin + 1)>>2) + nhi->nhi_LogicalMin;
3902 ULONG maxpos = (((nhi->nhi_LogicalMax - nhi->nhi_LogicalMin + 1)*3)>>2) + nhi->nhi_LogicalMin;
3903 UBYTE negaxis;
3904 UBYTE posaxis;
3905 UBYTE alogaxis;
3906 if((usageid == 0x30) || (usageid == 0x35))
3908 negaxis = HUAT_LEFT;
3909 posaxis = HUAT_RIGHT;
3910 alogaxis = HUAT_ABSX;
3911 } else {
3912 negaxis = HUAT_UP;
3913 posaxis = HUAT_DOWN;
3914 alogaxis = HUAT_ABSY;
3916 if((nha = nAllocAction(nch, lst, HUA_DIGJOY|HUA_ANY)))
3918 nha->nha_CCEnable = TRUE;
3919 nha->nha_CCCond = HUAT_GT;
3920 nha->nha_CCConst2 = minpos;
3921 nha->nha_JoypadOp = HUAT_CLEAR;
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_LE;
3929 nha->nha_CCConst2 = minpos;
3930 nha->nha_JoypadOp = HUAT_SET;
3931 nha->nha_JoypadFeat = negaxis;
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_LT;
3938 nha->nha_CCConst2 = maxpos;
3939 nha->nha_JoypadOp = HUAT_CLEAR;
3940 nha->nha_JoypadFeat = posaxis;
3941 nha->nha_JoypadPort = 1;
3943 if((nha = nAllocAction(nch, lst, HUA_DIGJOY|HUA_ANY)))
3945 nha->nha_CCEnable = TRUE;
3946 nha->nha_CCCond = HUAT_GE;
3947 nha->nha_CCConst2 = maxpos;
3948 nha->nha_JoypadOp = HUAT_SET;
3949 nha->nha_JoypadFeat = posaxis;
3950 nha->nha_JoypadPort = 1;
3952 if((nha = nAllocAction(nch, lst, HUA_ANALOGJOY|HUA_ANY)))
3954 nha->nha_APadFeat = alogaxis;
3955 nha->nha_JoypadPort = 1;
3957 break;
3962 if(nFindCollID(nch, nhc, 0x010008, 0x010008) && (nhi->nhi_Flags & RPF_MAIN_RELATIVE)) /* Multi-axis controller */
3964 switch(usageid)
3966 case 0x30: /* Mouse X */
3967 if((nha = nAllocAction(nch, lst, HUA_MOUSEPOS|HUA_ALWAYS)))
3969 nha->nha_MouseAxis = HUAT_DELTAX;
3970 nha->nha_ClipEnable = TRUE;
3971 nha->nha_ClipMin = 10;
3972 nha->nha_ClipMax = 45;
3973 nha->nha_ClipStretch = TRUE;
3974 nha->nha_ScaleEnable = TRUE;
3975 nha->nha_ScaleMin = -32;
3976 nha->nha_ScaleMax = 0;
3977 nha->nha_CCEnable = TRUE;
3978 nha->nha_CCVar1 = HUAT_OITEMVALUE;
3979 nha->nha_CCCond = HUAT_LT;
3980 nha->nha_CCConst2 = 0;
3982 if((nha = nAllocAction(nch, lst, HUA_MOUSEPOS|HUA_ALWAYS)))
3984 nha->nha_MouseAxis = HUAT_DELTAX;
3985 nha->nha_ClipEnable = TRUE;
3986 nha->nha_ClipMin = 55;
3987 nha->nha_ClipMax = 90;
3988 nha->nha_ClipStretch = TRUE;
3989 nha->nha_ScaleEnable = TRUE;
3990 nha->nha_ScaleMin = 0;
3991 nha->nha_ScaleMax = 32;
3992 nha->nha_CCEnable = TRUE;
3993 nha->nha_CCVar1 = HUAT_OITEMVALUE;
3994 nha->nha_CCCond = HUAT_GT;
3995 nha->nha_CCConst2 = 0;
3997 break;
3999 case 0x31: /* Mouse Y */
4000 if((nha = nAllocAction(nch, lst, HUA_MOUSEPOS|HUA_ALWAYS)))
4002 nha->nha_MouseAxis = HUAT_DELTAY;
4003 nha->nha_ClipEnable = TRUE;
4004 nha->nha_ClipMin = 10;
4005 nha->nha_ClipMax = 45;
4006 nha->nha_ClipStretch = TRUE;
4007 nha->nha_ScaleEnable = TRUE;
4008 nha->nha_ScaleMin = -32;
4009 nha->nha_ScaleMax = 0;
4010 nha->nha_CCEnable = TRUE;
4011 nha->nha_CCVar1 = HUAT_OITEMVALUE;
4012 nha->nha_CCCond = HUAT_LT;
4013 nha->nha_CCConst2 = 0;
4015 if((nha = nAllocAction(nch, lst, HUA_MOUSEPOS|HUA_ALWAYS)))
4017 nha->nha_MouseAxis = HUAT_DELTAY;
4018 nha->nha_ClipEnable = TRUE;
4019 nha->nha_ClipMin = 55;
4020 nha->nha_ClipMax = 90;
4021 nha->nha_ClipStretch = TRUE;
4022 nha->nha_ScaleEnable = TRUE;
4023 nha->nha_ScaleMin = 0;
4024 nha->nha_ScaleMax = 32;
4025 nha->nha_CCEnable = TRUE;
4026 nha->nha_CCVar1 = HUAT_OITEMVALUE;
4027 nha->nha_CCCond = HUAT_GT;
4028 nha->nha_CCConst2 = 0;
4030 break;
4032 case 0x32: /* Mouse Z */
4034 LONG minpos = (((nhi->nhi_LogicalMax - nhi->nhi_LogicalMin + 1)*3)>>3) + nhi->nhi_LogicalMin;
4035 LONG maxpos = (((nhi->nhi_LogicalMax - nhi->nhi_LogicalMin + 1)*5)>>3) + nhi->nhi_LogicalMin;
4036 UWORD led = nFindItemUsage(nch, 0x08004B, REPORT_MAIN_OUTPUT); // blue LED
4037 if(maxpos > 0)
4039 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4041 nha->nha_ButtonMode = HUAT_SET;
4042 nha->nha_ButtonNo = 1;
4043 nha->nha_CCEnable = TRUE;
4044 nha->nha_CCCond = HUAT_GT;
4045 nha->nha_CCConst2 = maxpos;
4047 if(led && ((nha = nAllocAction(nch, lst, HUA_OUTPUT|HUA_ANY))))
4049 nha->nha_OutOp = HUAT_SET;
4050 nha->nha_OutItem = led;
4051 nha->nha_CCEnable = TRUE;
4052 nha->nha_CCCond = HUAT_GT;
4053 nha->nha_CCConst2 = maxpos;
4055 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4057 nha->nha_ButtonMode = HUAT_CLEAR;
4058 nha->nha_ButtonNo = 1;
4059 nha->nha_CCEnable = TRUE;
4060 nha->nha_CCCond = HUAT_LT;
4061 nha->nha_CCConst2 = maxpos;
4063 if(led && ((nha = nAllocAction(nch, lst, HUA_OUTPUT|HUA_ANY))))
4065 nha->nha_OutOp = HUAT_CLEAR;
4066 nha->nha_OutItem = led;
4067 nha->nha_CCEnable = TRUE;
4068 nha->nha_CCCond = HUAT_LT;
4069 nha->nha_CCConst2 = maxpos;
4072 if(minpos < 0)
4074 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4076 nha->nha_ButtonMode = HUAT_SET;
4077 nha->nha_ButtonNo = 2;
4078 nha->nha_CCEnable = TRUE;
4079 nha->nha_CCCond = HUAT_LT;
4080 nha->nha_CCConst2 = minpos;
4082 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4084 nha->nha_ButtonMode = HUAT_CLEAR;
4085 nha->nha_ButtonNo = 2;
4086 nha->nha_CCEnable = TRUE;
4087 nha->nha_CCCond = HUAT_GT;
4088 nha->nha_CCConst2 = minpos;
4091 break;
4094 case 0x35: /* Z rotation */
4096 LONG minpos = (((nhi->nhi_LogicalMax - nhi->nhi_LogicalMin + 1)*2)>>3) + nhi->nhi_LogicalMin;
4097 LONG maxpos = (((nhi->nhi_LogicalMax - nhi->nhi_LogicalMin + 1)*6)>>3) + nhi->nhi_LogicalMin;
4098 if(maxpos > 0)
4100 if((nha = nAllocAction(nch, lst, HUA_WHEEL|HUA_ANY)))
4102 nha->nha_WheelMode = HUAT_DOWN;
4103 nha->nha_WheelDist = 1;
4104 nha->nha_CCEnable = TRUE;
4105 nha->nha_CCCond = HUAT_GT;
4106 nha->nha_CCConst2 = maxpos;
4109 if(minpos < 0)
4111 if((nha = nAllocAction(nch, lst, HUA_WHEEL|HUA_ANY)))
4113 nha->nha_WheelMode = HUAT_UP;
4114 nha->nha_WheelDist = 1;
4115 nha->nha_CCEnable = TRUE;
4116 nha->nha_CCCond = HUAT_LT;
4117 nha->nha_CCConst2 = minpos;
4120 break;
4124 break;
4126 case 0x09: /* Button page */
4127 if(nFindCollID(nch, nhc, 0x010002, 0x010002) || /* Mice */
4128 nFindCollID(nch, nhc, 0x0d0001, 0x0d000d) || /* Tablets */
4129 nFindCollID(nch, nhc, 0x010008, 0x010008)) /* Multi-Axis controller */
4131 if(usageid && (usageid < 6))
4133 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4135 nha->nha_ButtonMode = HUAT_ASSIGN;
4136 nha->nha_ButtonNo = usageid;
4140 if(nFindCollID(nch, nhc, 0x010004, 0x010005)) /* Joystick, Game Pad */
4142 if(usageid && (usageid < 8))
4144 if((nha = nAllocAction(nch, lst, HUA_DIGJOY|HUA_ANY)))
4146 nha->nha_JoypadOp = HUAT_ASSIGN;
4147 nha->nha_JoypadFeat = HUAT_RED + usageid - 1;
4148 nha->nha_JoypadPort = 1;
4152 break;
4154 case 0x07: /* keyboard page */
4155 switch(usageid)
4157 case 0x39: /* Caps lock */
4159 UWORD led;
4160 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_DOWNEVENT)))
4162 nha->nha_QualMode = HUAT_TOGGLE;
4163 nha->nha_Qualifier = IEQUALIFIERB_CAPSLOCK;
4165 if((led = nFindItemUsage(nch, 0x080002, REPORT_MAIN_OUTPUT)))
4167 if((nha = nAllocAction(nch, lst, HUA_OUTPUT|HUA_DOWNEVENT)))
4169 nha->nha_OutOp = HUAT_SET;
4170 nha->nha_OutItem = led;
4171 nha->nha_CCEnable = TRUE;
4172 nha->nha_CCVar1 = HUAT_QUALIFIERS;
4173 nha->nha_CCCond = HUAT_BWAND;
4174 nha->nha_CCVar2 = HUAT_CONST;
4175 nha->nha_CCConst2 = IEQUALIFIER_CAPSLOCK;
4177 if((nha = nAllocAction(nch, lst, HUA_OUTPUT|HUA_DOWNEVENT)))
4179 nha->nha_OutOp = HUAT_CLEAR;
4180 nha->nha_OutItem = led;
4181 nha->nha_CCEnable = TRUE;
4182 nha->nha_CCVar1 = HUAT_QUALIFIERS;
4183 nha->nha_CCCond = HUAT_BWNAND;
4184 nha->nha_CCVar2 = HUAT_CONST;
4185 nha->nha_CCConst2 = IEQUALIFIER_CAPSLOCK;
4188 break;
4191 case 0xe0: /* Left control */
4192 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4194 nha->nha_QualMode = HUAT_ASSIGN;
4195 nha->nha_Qualifier = IEQUALIFIERB_CONTROL;
4197 break;
4199 case 0xe1: /* Left shift */
4200 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4202 nha->nha_QualMode = HUAT_ASSIGN;
4203 nha->nha_Qualifier = IEQUALIFIERB_LSHIFT;
4205 break;
4207 case 0xe2: /* Left alt */
4208 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4210 nha->nha_QualMode = HUAT_ASSIGN;
4211 nha->nha_Qualifier = IEQUALIFIERB_LALT;
4213 break;
4215 case 0xe3: /* Left GUI */
4216 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4218 nha->nha_QualMode = HUAT_ASSIGN;
4219 nha->nha_Qualifier = IEQUALIFIERB_LCOMMAND;
4221 break;
4223 case 0xe4: /* Right control */
4224 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4226 nha->nha_QualMode = HUAT_ASSIGN;
4227 nha->nha_Qualifier = IEQUALIFIERB_CONTROL;
4229 break;
4231 case 0xe5: /* Right shift */
4232 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4234 nha->nha_QualMode = HUAT_ASSIGN;
4235 nha->nha_Qualifier = IEQUALIFIERB_RSHIFT;
4237 break;
4239 case 0xe6: /* Right alt */
4240 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4242 nha->nha_QualMode = HUAT_ASSIGN;
4243 nha->nha_Qualifier = IEQUALIFIERB_RALT;
4245 break;
4247 case 0x45: /* F12 */
4248 case 0x65: /* Application */
4249 case 0xe7: /* Right GUI */
4250 if((nha = nAllocAction(nch, lst, HUA_QUALIFIER|HUA_ANY)))
4252 nha->nha_QualMode = HUAT_ASSIGN;
4253 nha->nha_Qualifier = IEQUALIFIERB_RCOMMAND;
4255 break;
4257 nha = nAllocAction(nch, lst, HUA_KEYMAP|HUA_ANY);
4258 break;
4260 case 0x0d: /* digitizer/tablet page */
4261 switch(usageid)
4263 case 0x30: /* Tip pressure */
4264 case 0x31: /* Barrel pressure */
4265 if((nha = nAllocAction(nch, lst, HUA_TABLET|HUA_ALWAYS)))
4267 nha->nha_TabletAxis = HUAT_PRESSURE;
4269 break;
4271 case 0x32: /* In Range */
4272 case 0x37: /* Data Valid */
4273 if((nha = nAllocAction(nch, lst, HUA_TABLET|HUA_ALWAYS)))
4275 nha->nha_TabletAxis = HUAT_PROX;
4277 break;
4279 case 0x3D: /* X Tilt */
4280 if((nha = nAllocAction(nch, lst, HUA_TABLET|HUA_ALWAYS)))
4282 nha->nha_TabletAxis = HUAT_XROT;
4284 break;
4286 case 0x3E: /* Y Tilt */
4287 if((nha = nAllocAction(nch, lst, HUA_TABLET|HUA_ALWAYS)))
4289 nha->nha_TabletAxis = HUAT_YROT;
4291 break;
4293 case 0x42: /* Tip switch */
4294 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4296 nha->nha_ButtonMode = HUAT_ASSIGN;
4297 nha->nha_ButtonNo = 1;
4299 break;
4301 case 0x44: /* Barrel switch */
4302 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4304 nha->nha_ButtonMode = HUAT_ASSIGN;
4305 nha->nha_ButtonNo = 2;
4307 break;
4309 case 0x46: /* Tablet pick */
4310 if((nha = nAllocAction(nch, lst, HUA_BUTTONS|HUA_ANY)))
4312 nha->nha_ButtonMode = HUAT_ASSIGN;
4313 nha->nha_ButtonNo = 3;
4315 break;
4317 break;
4319 while(utp->utp_UsageID && (utp->utp_UsageID <= uid))
4321 if(utp->utp_UsageID == uid)
4323 if((nha = nAllocAction(nch, lst, HUA_EXTRAWKEY|HUA_DOWNEVENT)))
4325 nha->nha_RawKey = utp->utp_ExtCode;
4327 if((nha = nAllocAction(nch, lst, HUA_EXTRAWKEY|HUA_UPEVENT)))
4329 nha->nha_RawKey = utp->utp_ExtCode|IECODE_UP_PREFIX;
4332 utp++;
4334 return(res);
4336 /* \\\ */
4338 /* /// "nCheckForDefaultAction()" */
4339 BOOL nCheckForDefaultAction(struct NepClassHid *nch, struct NepHidItem *nhi, struct List *lst, struct NepHidCollection *nhc, ULONG uid)
4341 BOOL res = TRUE;
4342 struct NepHidAction *nha;
4343 struct NepHidAction *nhadef;
4344 struct List tmplist;
4346 NewList(&tmplist);
4347 nDetectDefaultAction(nch, nhi, &tmplist, nhc, nhi->nhi_Usage);
4348 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
4349 nhadef = (struct NepHidAction *) tmplist.lh_Head;
4350 while(nha->nha_Node.ln_Succ)
4352 if(nhadef->nha_Node.ln_Succ)
4354 nhadef->nha_IsDefault = nha->nha_IsDefault;
4355 if(memcmp(&nha->nha_Type, &nhadef->nha_Type, sizeof(struct NepHidAction)-offsetof(struct NepHidAction, nha_Type)))
4357 nha->nha_IsDefault = FALSE;
4358 res = FALSE;
4359 } else {
4360 nha->nha_IsDefault = TRUE;
4362 nhadef = (struct NepHidAction *) nhadef->nha_Node.ln_Succ;
4363 } else {
4364 res = FALSE;
4365 nha->nha_IsDefault = FALSE;
4367 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
4369 nhadef = (struct NepHidAction *) tmplist.lh_Head;
4370 while(nhadef->nha_Node.ln_Succ)
4372 Remove(&nhadef->nha_Node);
4373 psdFreeVec(nhadef);
4374 nhadef = (struct NepHidAction *) tmplist.lh_Head;
4376 return(res);
4378 /* \\\ */
4380 /* /// "nAllocAction()" */
4381 struct NepHidAction * nAllocAction(struct NepClassHid *nch, struct List *lst, UWORD utype)
4383 struct NepHidAction *nha = psdAllocVec(sizeof(struct NepHidAction));
4384 if(nha)
4386 KPRINTF(1, ("New action %lx\n", nha));
4387 nha->nha_Type = utype;
4388 nha->nha_ButtonNo = 1;
4389 nha->nha_SoundVolume = 64;
4390 nha->nha_ClipMax = 100;
4391 nha->nha_CCVar1 = HUAT_EITEMVALUE;
4392 nha->nha_CCVar2 = HUAT_CONST;
4393 AddTail(lst, &nha->nha_Node);
4394 return(nha);
4396 return(NULL);
4398 /* \\\ */
4400 /* /// "nAddUsage()" */
4401 BOOL nAddUsage(struct NepClassHid *nch, struct List *list, ULONG umin, ULONG umax)
4403 struct NepHidUsage *nhu;
4404 if(umin > umax)
4406 KPRINTF(10, ("UsageMin %lx > UsageMax %lx\n", umin, umax));
4407 return(FALSE);
4409 if((nhu = psdAllocVec(sizeof(struct NepHidUsage))))
4411 AddTail(list, &nhu->nhu_Node);
4412 nhu->nhu_Usage = umin;
4413 nhu->nhu_UsageMax = umax;
4414 return(TRUE);
4415 } else {
4416 KPRINTF(10, ("Out of memory during usage allocation.\n"));
4418 return(FALSE);
4420 /* \\\ */
4422 /* /// "nGetUsageName()" */
4423 STRPTR nGetUsageName(struct NepClassHid *nch, ULONG uid)
4425 STRPTR uname;
4427 uname = nNumToStr(nch, NTS_USAGEID, uid, NULL);
4428 if(uname)
4430 return(psdCopyStr(uname));
4432 uname = nNumToStr(nch, NTS_USAGEPAGE, uid>>16, "unknown");
4433 return(psdCopyStrFmt("%s (0x%lx)", uname, uid));
4435 /* \\\ */
4437 /* /// "nGenerateOutReport()" */
4438 void nGenerateOutReport(struct NepClassHid *nch, struct NepHidReport *nhr, UBYTE *buf)
4440 struct NepHidItem **nhiptr = nhr->nhr_OutItemMap;
4441 ULONG cnt;
4443 for(cnt = 0; cnt < nhr->nhr_OutItemCount; cnt++)
4445 nEncodeItemBuffer(nch, *nhiptr++, buf);
4448 /* \\\ */
4450 /* /// "nGenerateFeatReport()" */
4451 void nGenerateFeatReport(struct NepClassHid *nch, struct NepHidReport *nhr, UBYTE *buf)
4453 struct NepHidItem **nhiptr = nhr->nhr_FeatItemMap;
4454 ULONG cnt;
4456 for(cnt = 0; cnt < nhr->nhr_FeatItemCount; cnt++)
4458 nEncodeItemBuffer(nch, *nhiptr++, buf);
4461 /* \\\ */
4463 /* /// "nEncodeItemBuffer()" */
4464 void nEncodeItemBuffer(struct NepClassHid *nch, struct NepHidItem *nhi, UBYTE *buf)
4466 LONG value;
4467 LONG *valptr;
4468 ULONG ioffset;
4469 ULONG isize;
4470 UWORD count;
4471 UWORD acount;
4473 ioffset = nhi->nhi_Offset;
4474 isize = nhi->nhi_Size;
4475 if(nhi->nhi_Flags & RPF_MAIN_VARIABLE)
4477 //KPRINTF(1, ("Processing var %08lx (%ld@%ld)...\n", nhi, isize, ioffset));
4478 value = nhi->nhi_OldValue;
4479 if(value < nhi->nhi_LogicalMin)
4481 value = nhi->nhi_LogicalMin;
4483 else if(value > nhi->nhi_LogicalMax)
4485 value = nhi->nhi_LogicalMax;
4487 if(((ioffset & 7) == 0) && (isize == 8))
4489 buf[ioffset>>3] = value;
4491 else if(isize == 1)
4493 buf[ioffset>>3] &= ~(1UL<<(ioffset & 7));
4494 if(value)
4496 buf[ioffset>>3] |= (1UL<<(ioffset & 7));
4498 } else {
4499 /* I know this routine is dead slow, but hopefully, this is only a very uncommon case */
4500 count = isize;
4501 ioffset += count;
4504 ioffset--;
4505 buf[ioffset>>3] &= ~(1UL<<(ioffset & 7));
4506 if(value & 1)
4508 buf[ioffset>>3] |= (1UL<<(ioffset & 7));
4510 value >>= 1;
4511 } while(--count);
4513 } else {
4514 acount = nhi->nhi_Count;
4515 KPRINTF(1, ("Processing arr %08lx (%ld@%ld) * %ld...\n", nhi, isize, ioffset, acount));
4516 /* first generate the values */
4517 valptr = nhi->nhi_Buffer;
4518 if(((ioffset & 7) == 0) && (isize == 8))
4520 count = ioffset>>3;
4523 buf[count++] = *valptr++;
4524 } while(--acount);
4526 else if(isize == 1)
4530 buf[ioffset>>3] &= ~(1UL<<(ioffset & 7));
4531 if(*valptr++)
4533 buf[ioffset>>3] |= (1UL<<(ioffset & 7));
4535 ioffset++;
4536 } while(--acount);
4537 } else {
4538 /* I know this routine is dead slow, but hopefully, this is only a very uncommon case */
4541 count = isize;
4542 ioffset += count;
4543 value = *valptr++;
4546 ioffset--;
4547 buf[ioffset>>3] &= ~(1UL<<(ioffset & 7));
4548 if(value & 1)
4550 buf[ioffset>>3] |= (1UL<<(ioffset & 7));
4552 value >>= 1;
4553 } while(--count);
4554 ioffset += count;
4555 } while(--acount);
4559 /* \\\ */
4561 /* /// "nParseArrayString()" */
4562 void nParseArrayString(struct NepClassHid *nch, struct NepHidItem *nhi, STRPTR str)
4564 UWORD acount;
4565 LONG *valptr = nhi->nhi_Buffer;
4566 UWORD mode = 0;
4567 BOOL issigned = FALSE;
4569 if(!*str)
4571 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Empty array value string not allowed.");
4572 return;
4574 acount = nhi->nhi_Count;
4575 if(!acount)
4577 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Target array has no space!");
4580 // mode == 0 -> start
4581 // mode == 1 -> decimal value
4582 // mode == 2 -> hex value
4583 // mode == 3 -> ascii character
4584 // mode == 4 -> string
4585 // mode == 5 -> waiting for termination
4587 while(*str && acount)
4589 UBYTE ch = *str++;
4590 switch(mode)
4592 case 0: // normal
4593 if((ch == '0') && (*str == 'x'))
4595 mode = 2;
4596 *valptr = 0;
4597 str++;
4598 break;
4600 if((ch >= '0') && (ch <= '9'))
4602 mode = 1;
4603 issigned = FALSE;
4604 *valptr = ch - '0';
4605 break;
4607 else if(ch == '-')
4609 mode = 1;
4610 issigned = TRUE;
4611 *valptr = 0;
4613 else if(ch == '\'')
4615 mode = 3;
4616 break;
4618 else if(ch == '"')
4620 mode = 4;
4621 break;
4623 else if(ch == ' ')
4625 break;
4627 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Syntax error in S0!");
4628 return;
4630 case 1: // decimal value
4631 if((ch >= '0') && (ch <= '9'))
4633 *valptr *= 10;
4634 if(issigned)
4636 *valptr -= ch - '0';
4637 } else {
4638 *valptr += ch - '0';
4640 break;
4642 else if(ch == ' ')
4644 mode = 5;
4645 break;
4647 else if(ch == ',')
4649 mode = 0;
4650 valptr++;
4651 acount--;
4652 break;
4654 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Syntax error in S1!");
4655 return;
4657 case 2: // hex value
4658 if((ch >= '0') && (ch <= '9'))
4660 *valptr <<= 4;
4661 *valptr += ch - '0';
4662 break;
4664 else if((ch >= 'a') && (ch <= 'f'))
4666 *valptr <<= 4;
4667 *valptr += ch - 'a' + 10;
4668 break;
4670 else if((ch >= 'A') && (ch <= 'F'))
4672 *valptr <<= 4;
4673 *valptr += ch - 'A' + 10;
4674 break;
4676 else if(ch == ',')
4678 mode = 0;
4679 valptr++;
4680 acount--;
4681 break;
4683 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Syntax error in S2!");
4684 return;
4686 case 3: // ascii character
4687 if(*str == '\'')
4689 *valptr = ch;
4690 str++;
4691 mode = 5;
4692 break;
4694 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Syntax error in S3!");
4695 return;
4697 case 4: // string
4698 if(ch == '"')
4700 mode = 5;
4701 break;
4703 *valptr++ = ch;
4704 acount--;
4705 break;
4707 case 5: // waiting for termination
4708 if(ch == ' ')
4710 break;
4712 if(ch == ',')
4714 valptr++;
4715 acount--;
4716 mode = 0;
4717 break;
4719 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Syntax error in S5!");
4720 return;
4723 if(!(*str))
4725 if(mode == 3)
4727 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Syntax error in S3!");
4728 return;
4730 if(mode == 4)
4732 if(*str == '"')
4734 return;
4738 if(acount == 0)
4740 psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Parse error: Excessive elements ignored!");
4743 /* \\\ */
4745 /* /// "nProcessItem()" */
4746 BOOL nProcessItem(struct NepClassHid *nch, struct NepHidItem *nhi, UBYTE *buf)
4748 BOOL res = FALSE;
4749 LONG value;
4750 LONG *valptr;
4751 ULONG ioffset = nhi->nhi_Offset;
4752 ULONG isize = nhi->nhi_Size;
4753 UBYTE *bobuf = &buf[ioffset>>3];
4754 UWORD count;
4755 UWORD acount;
4756 ULONG usage;
4757 BOOL found;
4758 BOOL bytealigned = ((ioffset & 7) == 0);
4759 struct NepHidAction *nha;
4761 if(nhi->nhi_Flags & RPF_MAIN_VARIABLE)
4763 //KPRINTF(1, ("Processing var %08lx (%ld@%ld)...\n", nhi, isize, ioffset));
4764 if(bytealigned && (isize == 8))
4766 if(nhi->nhi_IsSigned)
4768 value = *((BYTE *) bobuf);
4769 } else {
4770 value = *bobuf;
4773 else if(isize == 1)
4775 value = (buf[ioffset>>3]>>(ioffset & 7)) & 1;
4777 else if(bytealigned && (isize == 16))
4779 if(nhi->nhi_IsSigned)
4781 value = (*bobuf)|((((BYTE *) bobuf)[1])<<8);
4782 } else {
4783 value = (*bobuf)|(bobuf[1]<<8);
4786 else if(bytealigned && (isize == 32))
4788 value = bobuf[0]|(bobuf[1]<<8)|(bobuf[2]<<16)|(bobuf[3]<<24);
4789 } else {
4790 /* I know this routine is dead slow, but hopefully, this is only a very uncommon case */
4791 count = isize;
4792 value = 0;
4793 ioffset += count;
4794 if(nhi->nhi_IsSigned)
4796 count--;
4797 ioffset--;
4798 if((buf[ioffset>>3]>>(ioffset & 7)) & 1)
4800 value = -1;
4805 ioffset--;
4806 value <<= 1;
4807 value |= (buf[ioffset>>3]>>(ioffset & 7)) & 1;
4808 } while(--count);
4810 if((value >= nhi->nhi_LogicalMin) && (value <= nhi->nhi_LogicalMax))
4812 ULONG currmicros = 0;
4813 ULONG currsecs = 0;
4814 if(nhi->nhi_OldValue != value)
4816 if((nhi->nhi_Usage > 0x070000) && (nhi->nhi_Usage < 0x0700E8))
4818 nch->nch_LastUSBKey = nhi->nhi_Usage;
4820 nch->nch_LastItem = nhi;
4821 nch->nch_LastItemAList = &nhi->nhi_ActionList;
4824 if(nch->nch_HIntBase)
4826 CurrentTime(&currsecs, &currmicros);
4827 if(!DoubleClick(nhi->nhi_LastSeconds, nhi->nhi_LastMicros, currsecs, currmicros))
4829 nhi->nhi_ClickCount = 0;
4831 if(nhi->nhi_OldValue < value)
4833 if(nhi->nhi_LastSeconds || nhi->nhi_LastMicros)
4835 if(DoubleClick(nhi->nhi_LastSeconds, nhi->nhi_LastMicros, currsecs, currmicros))
4837 nhi->nhi_ClickCount++;
4838 } else {
4839 nhi->nhi_ClickCount = 1;
4841 } else {
4842 nhi->nhi_ClickCount = 1;
4844 nhi->nhi_HoldSeconds = nhi->nhi_LastSeconds = currsecs;
4845 nhi->nhi_HoldMicros = nhi->nhi_LastMicros = currmicros;
4847 } else {
4848 /* no intuition library */
4849 nhi->nhi_ClickCount = 0;
4850 if(nhi->nhi_OldValue < value)
4852 nhi->nhi_ClickCount = 1;
4855 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
4856 while(nha->nha_Node.ln_Succ)
4858 if((nhi->nhi_OldValue != value) || ((nha->nha_Type & HUA_TRIGMASK) == HUA_ALWAYS))
4860 nDoAction(nch, nha, nhi, nhi->nhi_Usage, value, (nhi->nhi_OldValue < value) || ((nha->nha_Type & HUA_TRIGMASK) == HUA_ALWAYS));
4862 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
4864 if(nhi->nhi_OldValue > value)
4866 nhi->nhi_HoldSeconds = 0;
4867 nhi->nhi_HoldMicros = 0;
4869 if((nhi->nhi_OldValue != value) && nch->nch_ReportValues &&
4870 nch->nch_GUICurrentItem && (nch->nch_GUICurrentItem->nhgi_Item == nhi))
4872 nch->nch_ItemChanged = TRUE;
4874 nhi->nhi_OldValue = value;
4875 res = TRUE;
4876 } else {
4877 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
4878 while(nha->nha_Node.ln_Succ)
4880 if((nha->nha_Type & HUA_TRIGMASK) == HUA_NAN)
4882 nDoAction(nch, nha, nhi, nhi->nhi_Usage, nhi->nhi_OldValue, 0);
4884 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
4887 } else {
4888 nhi->nhi_HoldSeconds = nhi->nhi_LastSeconds = 0;
4889 nhi->nhi_HoldMicros = nhi->nhi_LastMicros = 0;
4890 acount = nhi->nhi_Count;
4891 KPRINTF(1, ("Processing arr %08lx (%ld@%ld) * %ld...\n", nhi, isize, ioffset, acount));
4892 /* first generate the values */
4893 valptr = nhi->nhi_Buffer;
4894 if(bytealigned && (isize == 8))
4896 count = ioffset>>3;
4897 if(nhi->nhi_IsSigned)
4901 *valptr++ = ((BYTE *) buf)[count++];
4902 } while(--acount);
4903 } else {
4906 *valptr++ = buf[count++];
4907 } while(--acount);
4910 else if(isize == 1)
4914 *valptr++ = (buf[ioffset>>3]>>(ioffset & 7)) & 1;
4915 ioffset++;
4916 } while(--acount);
4917 } else {
4918 /* I know this routine is dead slow, but hopefully, this is only a very uncommon case */
4921 count = isize;
4922 value = 0;
4923 ioffset += count;
4924 if(nhi->nhi_IsSigned)
4926 ioffset--;
4927 count--;
4928 if((buf[ioffset>>3]>>(ioffset & 7)) & 1)
4930 value = -1;
4935 ioffset--;
4936 value <<= 1;
4937 value |= (buf[ioffset>>3]>>(ioffset & 7)) & 1;
4938 } while(--count);
4939 ioffset += isize;
4940 *valptr++ = value;
4941 } while(--acount);
4944 /* Look for up events first */
4945 acount = 0;
4948 value = nhi->nhi_OldBuffer[acount];
4949 if((value >= nhi->nhi_LogicalMin) && (value <= nhi->nhi_LogicalMax))
4951 valptr = nhi->nhi_Buffer;
4952 count = nhi->nhi_Count;
4953 found = FALSE;
4956 if(*valptr++ == value)
4958 found = TRUE;
4959 break;
4961 } while(--count);
4962 /* Not found in the new array, so generate up event */
4963 if(!found)
4965 KPRINTF(1, ("Up event %ld\n", acount));
4966 usage = nhi->nhi_UsageMap[value - nhi->nhi_LogicalMin];
4967 if(value || nhi->nhi_LogicalMin)
4969 nch->nch_LastItem = nhi;
4970 nch->nch_LastItemAList = &nhi->nhi_ActionMap[value - nhi->nhi_LogicalMin];
4972 nha = (struct NepHidAction *) nhi->nhi_ActionMap[value - nhi->nhi_LogicalMin].lh_Head;
4973 if(!nha->nha_Node.ln_Succ) /* Use default, no override defined */
4975 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
4977 nhi->nhi_OldValue = nhi->nhi_LogicalMin - 1;
4978 while(nha->nha_Node.ln_Succ)
4980 nDoAction(nch, nha, nhi, usage, value, FALSE);
4981 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
4983 res = TRUE;
4986 } while(++acount < nhi->nhi_Count);
4988 /* Look for down events */
4989 acount = 0;
4992 value = nhi->nhi_Buffer[acount];
4993 //KPRINTF(1, ("[%ld] = %ld\n", acount, value));
4994 if((value >= nhi->nhi_LogicalMin) && (value <= nhi->nhi_LogicalMax))
4996 valptr = nhi->nhi_OldBuffer;
4997 count = nhi->nhi_Count;
4998 found = FALSE;
5001 if(*valptr++ == value)
5003 found = TRUE;
5004 break;
5006 } while(--count);
5007 /* Not found in the old array, so generate down event */
5008 if(!found)
5010 KPRINTF(1, ("Down event %ld\n", acount));
5011 usage = nhi->nhi_UsageMap[value - nhi->nhi_LogicalMin];
5012 if(value || nhi->nhi_LogicalMin)
5014 if((usage > 0x070000) && (usage < 0x0700E8))
5016 nch->nch_LastUSBKey = usage;
5018 nch->nch_LastItem = nhi;
5019 nch->nch_LastItemAList = &nhi->nhi_ActionMap[value - nhi->nhi_LogicalMin];
5022 nha = (struct NepHidAction *) nhi->nhi_ActionMap[value - nhi->nhi_LogicalMin].lh_Head;
5023 if(!nha->nha_Node.ln_Succ) /* Use default, no override defined */
5025 nha = (struct NepHidAction *) nhi->nhi_ActionList.lh_Head;
5027 nhi->nhi_OldValue = nhi->nhi_LogicalMin - 1;
5028 while(nha->nha_Node.ln_Succ)
5030 nDoAction(nch, nha, nhi, usage, value, TRUE);
5031 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
5033 res = TRUE;
5036 } while(++acount < nhi->nhi_Count);
5037 /* Copy new array */
5038 CopyMemQuick(nhi->nhi_Buffer, nhi->nhi_OldBuffer, sizeof(LONG) * nhi->nhi_Count);
5040 return(res);
5042 /* \\\ */
5044 static ULONG LLHatswitchEncoding[8] = { JPF_JOY_UP, JPF_JOY_UP|JPF_JOY_RIGHT, JPF_JOY_RIGHT, JPF_JOY_RIGHT|JPF_JOY_DOWN,
5045 JPF_JOY_DOWN, JPF_JOY_DOWN|JPF_JOY_LEFT, JPF_JOY_LEFT, JPF_JOY_LEFT|JPF_JOY_UP };
5047 /* /// "nDoAction()" */
5048 BOOL nDoAction(struct NepClassHid *nch, struct NepHidAction *nha, struct NepHidItem *nhi, ULONG uid, LONG value, BOOL downevent)
5050 UWORD atype = nha->nha_Type & HUA_ATYPEMASK;
5051 BOOL res = FALSE;
5052 ULONG qualmask;
5053 LONG clipmin, clipmax;
5054 LONG origvalue = value;
5056 if(nch->nch_DisableActions)
5058 return(FALSE);
5061 // bail out early as nothing below will affect this
5062 if(!(((nha->nha_Type & HUA_DOWNEVENT) && downevent) ||
5063 ((nha->nha_Type & HUA_UPEVENT) && !downevent) ||
5064 ((nha->nha_Type & HUA_TRIGMASK) == HUA_ALWAYS) ||
5065 ((nha->nha_Type & HUA_TRIGMASK) == HUA_NAN)))
5067 return(FALSE);
5070 if(nha->nha_AbsToRel)
5072 value = value - nhi->nhi_OldValue;
5073 nhi->nhi_RealMin = nhi->nhi_LogicalMin - nhi->nhi_LogicalMax;
5074 nhi->nhi_RealMax = nhi->nhi_LogicalMax - nhi->nhi_LogicalMin;
5075 } else {
5076 nhi->nhi_RealMin = nhi->nhi_LogicalMin;
5077 nhi->nhi_RealMax = nhi->nhi_LogicalMax;
5080 if(nha->nha_ClipEnable)
5082 if(nha->nha_ClipMin == nha->nha_ClipMax)
5084 /* shrink to a point */
5085 value = ((nha->nha_ClipMin * (nhi->nhi_RealMax - nhi->nhi_RealMin)) / 100) + nhi->nhi_RealMin;
5086 } else {
5087 if(nha->nha_ClipMin < nha->nha_ClipMax)
5089 /* normal clipping */
5090 clipmin = ((nha->nha_ClipMin * (nhi->nhi_RealMax - nhi->nhi_RealMin)) / 100) + nhi->nhi_RealMin;
5091 clipmax = ((nha->nha_ClipMax * (nhi->nhi_RealMax - nhi->nhi_RealMin)) / 100) + nhi->nhi_RealMin;
5092 } else {
5093 /* inverse clipping */
5094 value = nhi->nhi_RealMax - value;
5095 clipmin = ((nha->nha_ClipMax * (nhi->nhi_RealMax - nhi->nhi_RealMin)) / 100) + nhi->nhi_RealMin;
5096 clipmax = ((nha->nha_ClipMin * (nhi->nhi_RealMax - nhi->nhi_RealMin)) / 100) + nhi->nhi_RealMin;
5098 if(value < clipmin)
5100 value = clipmin;
5101 } else {
5102 if(value > clipmax)
5104 value = clipmax;
5107 if(nha->nha_ClipStretch && (clipmax - clipmin))
5109 value = (((value - clipmin) * (nhi->nhi_RealMax - nhi->nhi_RealMin)) /
5110 (clipmax - clipmin)) + nhi->nhi_RealMin;
5115 if(nha->nha_ScaleEnable && (nha->nha_ScaleMax != nha->nha_ScaleMin))
5117 value = (((value - nhi->nhi_RealMin) * (nha->nha_ScaleMax - nha->nha_ScaleMin)) /
5118 (nhi->nhi_RealMax - nhi->nhi_RealMin)) + nha->nha_ScaleMin;
5119 nhi->nhi_RealMin = nha->nha_ScaleMin;
5120 nhi->nhi_RealMax = nha->nha_ScaleMax;
5123 if(nha->nha_CCEnable)
5125 LONG var1 = 0;
5126 LONG var2 = 0;
5127 BOOL cond = FALSE;
5129 switch(nha->nha_CCVar1)
5131 case HUAT_EITEMVALUE:
5132 var1 = value;
5133 break;
5135 case HUAT_OITEMVALUE:
5136 var1 = origvalue;
5137 break;
5139 case HUAT_CONST:
5140 var1 = nha->nha_CCConst1;
5141 break;
5143 case HUAT_CLICKCOUNT:
5144 var1 = nhi->nhi_ClickCount;
5145 break;
5147 case HUAT_CLICKTIME:
5149 ULONG currmicros;
5150 ULONG currsecs;
5152 if(nhi->nhi_HoldSeconds || nhi->nhi_HoldMicros)
5154 CurrentTime(&currsecs, &currmicros);
5155 var1 = (currsecs - nhi->nhi_HoldSeconds) * 1000;
5156 if(nhi->nhi_HoldMicros <= currmicros)
5158 var1 += (currmicros - nhi->nhi_HoldMicros) / 1000;
5159 } else {
5160 var1 -= (nhi->nhi_HoldMicros - currmicros) / 1000;
5162 } else {
5163 var1 = 0;
5165 break;
5168 case HUAT_QUALIFIERS:
5169 var1 = nch->nch_KeyQualifiers;
5170 break;
5172 case HUAT_ALLQUAL:
5173 var1 = nch->nch_KeyQualifiers|PeekQualifier();
5174 break;
5176 case HUAT_RANDOMBIT:
5177 var1 = _rand(nch->nch_ClsBase) & 1;
5178 break;
5180 case HUAT_RANDOMVAL:
5181 var1 = _rand(nch->nch_ClsBase);
5182 break;
5184 case HUAT_TIMER:
5186 ULONG currmicros;
5187 ULONG currsecs;
5189 CurrentTime(&currsecs, &currmicros);
5190 var1 = (currsecs * 1000) + (currmicros / 1000);
5191 break;
5194 case HUAT_LOCALVAR1:
5195 case HUAT_LOCALVAR2:
5196 case HUAT_LOCALVAR3:
5197 case HUAT_LOCALVAR4:
5198 case HUAT_LOCALVAR5:
5199 case HUAT_LOCALVAR6:
5200 case HUAT_LOCALVAR7:
5201 case HUAT_LOCALVAR8:
5202 var1 = nch->nch_LocalVars[nha->nha_CCVar1 - HUAT_LOCALVAR1];
5203 break;
5205 case HUAT_GLOBVARA:
5206 case HUAT_GLOBVARB:
5207 case HUAT_GLOBVARC:
5208 case HUAT_GLOBVARD:
5209 case HUAT_GLOBVARE:
5210 case HUAT_GLOBVARF:
5211 case HUAT_GLOBVARG:
5212 case HUAT_GLOBVARH:
5213 var1 = nch->nch_ClsBase->nh_GlobalVars[nha->nha_CCVar1 - HUAT_GLOBVARA];
5214 break;
5216 switch(nha->nha_CCVar2)
5218 case HUAT_EITEMVALUE:
5219 var2 = value;
5220 break;
5222 case HUAT_OITEMVALUE:
5223 var2 = origvalue;
5224 break;
5226 case HUAT_CONST:
5227 var2 = nha->nha_CCConst2;
5228 break;
5230 case HUAT_CLICKCOUNT:
5231 var2 = nhi->nhi_ClickCount;
5232 break;
5234 case HUAT_CLICKTIME:
5236 ULONG currmicros;
5237 ULONG currsecs;
5239 if(nhi->nhi_HoldSeconds || nhi->nhi_HoldMicros)
5241 CurrentTime(&currsecs, &currmicros);
5242 var2 = (currsecs - nhi->nhi_HoldSeconds) * 1000;
5243 if(nhi->nhi_HoldMicros <= currmicros)
5245 var2 += (currmicros - nhi->nhi_HoldMicros) / 1000;
5246 } else {
5247 var2 -= (nhi->nhi_HoldMicros - currmicros) / 1000;
5249 } else {
5250 var2 = 0;
5252 break;
5255 case HUAT_QUALIFIERS:
5256 var2 = nch->nch_KeyQualifiers;
5257 break;
5259 case HUAT_ALLQUAL:
5260 var2 = nch->nch_KeyQualifiers|PeekQualifier();
5261 break;
5263 case HUAT_RANDOMBIT:
5264 var2 = _rand(nch->nch_ClsBase) & 1;
5265 break;
5267 case HUAT_RANDOMVAL:
5268 var2 = _rand(nch->nch_ClsBase);
5269 break;
5271 case HUAT_TIMER:
5273 ULONG currmicros;
5274 ULONG currsecs;
5276 CurrentTime(&currsecs, &currmicros);
5277 var2 = (currsecs * 1000) + (currmicros / 1000);
5278 break;
5281 case HUAT_LOCALVAR1:
5282 case HUAT_LOCALVAR2:
5283 case HUAT_LOCALVAR3:
5284 case HUAT_LOCALVAR4:
5285 case HUAT_LOCALVAR5:
5286 case HUAT_LOCALVAR6:
5287 case HUAT_LOCALVAR7:
5288 case HUAT_LOCALVAR8:
5289 var2 = nch->nch_LocalVars[nha->nha_CCVar2 - HUAT_LOCALVAR1];
5290 break;
5292 case HUAT_GLOBVARA:
5293 case HUAT_GLOBVARB:
5294 case HUAT_GLOBVARC:
5295 case HUAT_GLOBVARD:
5296 case HUAT_GLOBVARE:
5297 case HUAT_GLOBVARF:
5298 case HUAT_GLOBVARG:
5299 case HUAT_GLOBVARH:
5300 var2 = nch->nch_ClsBase->nh_GlobalVars[nha->nha_CCVar2 - HUAT_GLOBVARA];
5301 break;
5303 switch(nha->nha_CCCond)
5305 case HUAT_EQ:
5306 cond = (var1 == var2);
5307 break;
5309 case HUAT_NE:
5310 cond = (var1 != var2);
5311 break;
5313 case HUAT_LT:
5314 cond = (var1 < var2);
5315 break;
5317 case HUAT_LE:
5318 cond = (var1 <= var2);
5319 break;
5321 case HUAT_GT:
5322 cond = (var1 > var2);
5323 break;
5325 case HUAT_GE:
5326 cond = (var1 >= var2);
5327 break;
5329 case HUAT_AND:
5330 cond = (var1 && var2);
5331 break;
5333 case HUAT_NAND:
5334 cond = !(var1 && var2);
5335 break;
5337 case HUAT_OR:
5338 cond = (var1 || var2);
5339 break;
5341 case HUAT_XOR:
5342 cond = (var1 && (!var2)) || ((!var1) && var2);
5343 break;
5345 case HUAT_ANDNOT:
5346 cond = (var1 && (!var2));
5347 break;
5349 case HUAT_BWAND:
5350 cond = (var1 & var2) ? TRUE : FALSE;
5351 break;
5353 case HUAT_BWNAND:
5354 cond = (var1 & var2) ? FALSE : TRUE;
5355 break;
5357 case HUAT_BWOR:
5358 cond = (var1 | var2) ? TRUE : FALSE;
5359 break;
5361 case HUAT_BWXOR:
5362 cond = (var1 ^ var2) ? TRUE : FALSE;
5363 break;
5365 case HUAT_BWANDNOT:
5366 cond = (var1 & (~var2)) ? TRUE : FALSE;
5367 break;
5370 if(!cond)
5372 return(FALSE);
5376 if(nha->nha_ValEnable)
5378 switch(nha->nha_ValVar)
5380 case HUAT_EITEMVALUE:
5381 //value = value;
5382 break;
5384 case HUAT_OITEMVALUE:
5385 value = origvalue;
5386 break;
5388 case HUAT_CONST:
5389 value = nha->nha_ValConst;
5390 break;
5392 case HUAT_CLICKCOUNT:
5393 value = nhi->nhi_ClickCount;
5394 break;
5396 case HUAT_CLICKTIME:
5398 ULONG currmicros;
5399 ULONG currsecs;
5401 if(nhi->nhi_HoldSeconds || nhi->nhi_HoldMicros)
5403 CurrentTime(&currsecs, &currmicros);
5404 value = (currsecs - nhi->nhi_HoldSeconds) * 1000;
5405 if(nhi->nhi_HoldMicros <= currmicros)
5407 value += (currmicros - nhi->nhi_HoldMicros) / 1000;
5408 } else {
5409 value -= (nhi->nhi_HoldMicros - currmicros) / 1000;
5411 } else {
5412 value = 0;
5414 break;
5417 case HUAT_QUALIFIERS:
5418 value = nch->nch_KeyQualifiers;
5419 break;
5421 case HUAT_ALLQUAL:
5422 value = nch->nch_KeyQualifiers|PeekQualifier();
5423 break;
5425 case HUAT_RANDOMBIT:
5426 value = _rand(nch->nch_ClsBase) & 1;
5427 break;
5429 case HUAT_RANDOMVAL:
5430 value = _rand(nch->nch_ClsBase);
5431 break;
5433 case HUAT_TIMER:
5435 ULONG currmicros;
5436 ULONG currsecs;
5438 CurrentTime(&currsecs, &currmicros);
5439 value = (currsecs * 1000) + (currmicros / 1000);
5440 break;
5443 case HUAT_LOCALVAR1:
5444 case HUAT_LOCALVAR2:
5445 case HUAT_LOCALVAR3:
5446 case HUAT_LOCALVAR4:
5447 case HUAT_LOCALVAR5:
5448 case HUAT_LOCALVAR6:
5449 case HUAT_LOCALVAR7:
5450 case HUAT_LOCALVAR8:
5451 value = nch->nch_LocalVars[nha->nha_ValVar - HUAT_LOCALVAR1];
5452 break;
5454 case HUAT_GLOBVARA:
5455 case HUAT_GLOBVARB:
5456 case HUAT_GLOBVARC:
5457 case HUAT_GLOBVARD:
5458 case HUAT_GLOBVARE:
5459 case HUAT_GLOBVARF:
5460 case HUAT_GLOBVARG:
5461 case HUAT_GLOBVARH:
5462 value = nch->nch_ClsBase->nh_GlobalVars[nha->nha_ValVar - HUAT_GLOBVARA];
5463 break;
5466 //KPRINTF(1, ("Call for action(%04lx) %lx = %ld %s\n", atype, uid, value, downevent ? "down" : "up"));
5467 switch(atype)
5469 case HUA_SHELL:
5470 case HUA_KEYSTRING:
5471 case HUA_VANILLA:
5472 case HUA_SOUND:
5474 struct ActionMsg *am;
5475 if(!nch->nch_ClsBase->nh_DTaskMsgPort)
5477 nInstallLastActionHero(nch);
5479 if(nch->nch_ClsBase->nh_DTaskMsgPort)
5481 if((am = AllocVec(sizeof(struct ActionMsg), MEMF_PUBLIC)))
5483 am->am_Msg.mn_Length = sizeof(struct ActionMsg);
5484 am->am_Msg.mn_ReplyPort = NULL;
5485 am->am_NCH = nch;
5486 am->am_Action = nha;
5487 PutMsg(nch->nch_ClsBase->nh_DTaskMsgPort, &am->am_Msg);
5490 break;
5493 case HUA_RAWKEY:
5494 nSendRawKey(nch, nha->nha_RawKey);
5495 break;
5497 case HUA_KEYMAP:
5499 UWORD iecode;
5500 if((uid > 0x70000) && (uid < 0x700e8))
5502 iecode = nch->nch_KeymapCfg.kmc_Keymap[uid & 0xff];
5503 KPRINTF(1,("Key %ld %s\n", iecode, downevent ? "DOWN" : "UP"));
5504 nch->nch_FakeEvent.ie_Class = IECLASS_RAWKEY;
5505 nch->nch_FakeEvent.ie_SubClass = 0;
5506 nSendRawKey(nch, downevent ? iecode : iecode|IECODE_UP_PREFIX);
5508 break;
5511 case HUA_MOUSEPOS:
5512 switch(nha->nha_MouseAxis)
5514 case HUAT_DELTAX:
5515 nch->nch_NewMouseRel = TRUE;
5516 nch->nch_MouseDeltaX += value;
5517 break;
5519 case HUAT_DELTAY:
5520 nch->nch_NewMouseRel = TRUE;
5521 nch->nch_MouseDeltaY += value;
5522 break;
5524 case HUAT_ABSX:
5525 if(nch->nch_MouseRangeY)
5527 nch->nch_NewMouseAbs = TRUE;
5529 nch->nch_MouseAbsX = value - nhi->nhi_RealMin;
5530 nch->nch_MouseRangeX = (nhi->nhi_RealMax - nhi->nhi_RealMin) + 1;
5531 break;
5533 case HUAT_ABSY:
5534 if(nch->nch_MouseRangeX)
5536 nch->nch_NewMouseAbs = TRUE;
5538 nch->nch_MouseAbsY = value - nhi->nhi_RealMin;
5539 nch->nch_MouseRangeY = (nhi->nhi_RealMax - nhi->nhi_RealMin) + 1;
5540 break;
5542 break;
5544 case HUA_QUALIFIER:
5545 qualmask = 1<<nha->nha_Qualifier;
5546 switch(nha->nha_QualMode)
5548 case HUAT_SET:
5549 nch->nch_KeyQualifiers |= qualmask;
5550 break;
5552 case HUAT_CLEAR:
5553 nch->nch_KeyQualifiers &= ~qualmask;
5554 break;
5556 case HUAT_TOGGLE:
5557 nch->nch_KeyQualifiers ^= qualmask;
5558 break;
5560 case HUAT_ASSIGN:
5561 nch->nch_KeyQualifiers &= ~qualmask;
5562 if(downevent)
5564 nch->nch_KeyQualifiers |= qualmask;
5566 break;
5568 break;
5570 case HUA_BUTTONS:
5572 UWORD iecode = IECODE_NOBUTTON;
5573 ULONG iequal = 0;
5574 BOOL newmouse = FALSE;
5576 switch(nha->nha_ButtonNo)
5578 case 1:
5579 iequal = IEQUALIFIER_LEFTBUTTON;
5580 iecode = IECODE_LBUTTON;
5581 break;
5583 case 2:
5584 iequal = IEQUALIFIER_RBUTTON;
5585 iecode = IECODE_RBUTTON;
5586 break;
5588 case 3:
5589 iequal = IEQUALIFIER_MIDBUTTON;
5590 iecode = IECODE_MBUTTON;
5591 break;
5593 case 4:
5594 iecode = RAWKEY_NM_BUTTON_FOURTH;
5595 newmouse = TRUE;
5596 break;
5599 switch(nha->nha_ButtonMode)
5601 case HUAT_SET:
5602 if((!newmouse) && (nch->nch_KeyQualifiers & iequal))
5604 iequal = 0;
5605 iecode = IECODE_NOBUTTON;
5606 } else {
5607 nch->nch_KeyQualifiers |= iequal;
5608 nch->nch_MouseButtons |= 1<<(nha->nha_ButtonNo-1);
5610 break;
5612 case HUAT_CLEAR:
5613 if(newmouse || (nch->nch_KeyQualifiers & iequal))
5615 nch->nch_KeyQualifiers &= ~iequal;
5616 nch->nch_MouseButtons &= ~(1<<(nha->nha_ButtonNo-1));
5617 iequal = 0;
5618 iecode |= IECODE_UP_PREFIX;
5619 } else {
5620 iequal = 0;
5621 iecode = IECODE_NOBUTTON;
5623 break;
5625 case HUAT_TOGGLE:
5626 if(newmouse)
5628 if(nch->nch_MouseButtons & (1<<(nha->nha_ButtonNo-1)))
5630 nch->nch_MouseButtons &= ~(1<<(nha->nha_ButtonNo-1));
5631 iecode |= IECODE_UP_PREFIX;
5632 } else {
5633 nch->nch_MouseButtons |= 1<<(nha->nha_ButtonNo-1);
5635 } else {
5636 if(nch->nch_KeyQualifiers & iequal)
5638 nch->nch_KeyQualifiers &= ~iequal;
5639 nch->nch_MouseButtons &= ~(1<<(nha->nha_ButtonNo-1));
5640 iequal = 0;
5641 iecode |= IECODE_UP_PREFIX;
5642 } else {
5643 nch->nch_KeyQualifiers |= iequal;
5644 nch->nch_MouseButtons |= 1<<(nha->nha_ButtonNo-1);
5647 break;
5649 case HUAT_ASSIGN:
5650 if(value)
5652 if((!newmouse) && (nch->nch_KeyQualifiers & iequal))
5654 iequal = 0;
5655 iecode = IECODE_NOBUTTON;
5656 } else {
5657 nch->nch_KeyQualifiers |= iequal;
5658 nch->nch_MouseButtons |= 1<<(nha->nha_ButtonNo-1);
5660 } else {
5661 if(newmouse || (nch->nch_KeyQualifiers & iequal))
5663 nch->nch_KeyQualifiers &= ~iequal;
5664 nch->nch_MouseButtons &= ~(1<<(nha->nha_ButtonNo-1));
5665 iequal = 0;
5666 iecode |= IECODE_UP_PREFIX;
5667 } else {
5668 iequal = 0;
5669 iecode = IECODE_NOBUTTON;
5672 break;
5674 default:
5675 iecode = IECODE_NOBUTTON;
5676 break;
5678 if(iecode != IECODE_NOBUTTON)
5680 if(newmouse)
5682 nSendRawKey(nch, iecode);
5684 nch->nch_FakeEvent.ie_Class = IECLASS_NEWMOUSE;
5685 nch->nch_FakeEvent.ie_SubClass = 0;
5686 nch->nch_FakeEvent.ie_Code = iecode;
5687 nch->nch_FakeEvent.ie_NextEvent = NULL;
5688 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers;
5689 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
5690 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
5691 nch->nch_InpIOReq->io_Command = IND_WRITEEVENT;
5692 DoIO((struct IORequest *) nch->nch_InpIOReq);
5693 } else {
5694 nch->nch_FakeEvent.ie_X = nch->nch_MouseDeltaX;
5695 nch->nch_FakeEvent.ie_Y = nch->nch_MouseDeltaY;
5696 nch->nch_FakeEvent.ie_Class = IECLASS_RAWMOUSE;
5697 nch->nch_FakeEvent.ie_SubClass = 0;
5698 nch->nch_FakeEvent.ie_Code = iecode;
5699 nch->nch_FakeEvent.ie_NextEvent = NULL;
5700 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers|IEQUALIFIER_RELATIVEMOUSE;
5701 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
5702 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
5703 nch->nch_InpIOReq->io_Command = nch->nch_OS4Hack ? IND_ADDEVENT : IND_WRITEEVENT;
5704 DoIO((struct IORequest *) nch->nch_InpIOReq);
5705 nch->nch_NewMouseRel = FALSE;
5706 nch->nch_MouseDeltaX = 0;
5707 nch->nch_MouseDeltaY = 0;
5710 break;
5713 case HUA_TABLET:
5715 KPRINTF(1, ("Tablet!\n"));
5716 switch(nha->nha_TabletAxis)
5718 case HUAT_ABSZ:
5719 nch->nch_MouseAbsZ = value - nhi->nhi_RealMin;
5720 nch->nch_MouseRangeZ = (nhi->nhi_RealMax - nhi->nhi_RealMin) + 1;
5721 break;
5723 case HUAT_PRESSURE:
5724 if(nhi->nhi_RealMax)
5726 nch->nch_TabPressure = ((0x1fffffff / nhi->nhi_RealMax)*value)<<2;
5727 nch->nch_VldPressure = TRUE;
5729 break;
5731 case HUAT_XROT:
5732 if(nhi->nhi_RealMax)
5734 nch->nch_TabRotX = ((0x3fffffff / nhi->nhi_RealMax)*value)<<2;
5735 nch->nch_VldRotX = TRUE;
5737 break;
5739 case HUAT_YROT:
5740 if(nhi->nhi_RealMax)
5742 nch->nch_TabRotY = ((0x3fffffff / nhi->nhi_RealMax)*value)<<2;
5743 nch->nch_VldRotY = TRUE;
5745 break;
5747 case HUAT_ZROT:
5748 if(nhi->nhi_RealMax)
5750 nch->nch_TabRotZ = ((0x3fffffff / nhi->nhi_RealMax)*value)<<2;
5751 nch->nch_VldRotZ = TRUE;
5753 break;
5755 case HUAT_PROX:
5756 nch->nch_TabProx = value;
5757 nch->nch_VldProx = TRUE;
5758 break;
5760 if(nch->nch_MouseRangeX && nch->nch_MouseRangeY)
5762 nch->nch_NewMouseAbs = TRUE;
5764 break;
5767 case HUA_WHEEL:
5769 UWORD wheeldist = 0;
5770 UWORD wheeliecode = IECODE_NOBUTTON;
5771 switch(nha->nha_WheelMode)
5773 case HUAT_DELTAX:
5774 if(value > 0)
5776 wheeliecode = RAWKEY_NM_WHEEL_LEFT;
5777 wheeldist = value;
5779 else if(value < 0)
5781 wheeliecode = RAWKEY_NM_WHEEL_RIGHT;
5782 wheeldist = -value;
5784 break;
5786 case HUAT_DELTAY:
5787 if(value > 0)
5789 wheeliecode = RAWKEY_NM_WHEEL_UP;
5790 wheeldist = value;
5792 else if(value < 0)
5794 wheeliecode = RAWKEY_NM_WHEEL_DOWN;
5795 wheeldist = -value;
5797 break;
5799 case HUAT_LEFT:
5800 wheeliecode = RAWKEY_NM_WHEEL_LEFT;
5801 wheeldist = nha->nha_WheelDist;
5802 break;
5804 case HUAT_RIGHT:
5805 wheeliecode = RAWKEY_NM_WHEEL_RIGHT;
5806 wheeldist = nha->nha_WheelDist;
5807 break;
5809 case HUAT_UP:
5810 wheeliecode = RAWKEY_NM_WHEEL_UP;
5811 wheeldist = nha->nha_WheelDist;
5812 break;
5814 case HUAT_DOWN:
5815 wheeliecode = RAWKEY_NM_WHEEL_DOWN;
5816 wheeldist = nha->nha_WheelDist;
5817 break;
5819 if(wheeliecode != IECODE_NOBUTTON)
5821 if(downevent)
5823 while(wheeldist--)
5825 KPRINTF(1, ("Doing wheel %ld\n", wheeliecode));
5826 nSendRawKey(nch, wheeliecode);
5827 #if 0
5828 nch->nch_FakeEvent.ie_Class = IECLASS_NEWMOUSE;
5829 nch->nch_FakeEvent.ie_SubClass = 0;
5830 nch->nch_FakeEvent.ie_Code = wheeliecode;
5831 nch->nch_FakeEvent.ie_NextEvent = NULL;
5832 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers;
5833 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
5834 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
5835 nch->nch_InpIOReq->io_Command = IND_WRITEEVENT;
5836 DoIO((struct IORequest *) nch->nch_InpIOReq);
5837 #endif
5840 nSendRawKey(nch, wheeliecode|IECODE_UP_PREFIX);
5841 #if 0
5842 nch->nch_FakeEvent.ie_Class = IECLASS_NEWMOUSE;
5843 nch->nch_FakeEvent.ie_SubClass = 0;
5844 nch->nch_FakeEvent.ie_Code = wheeliecode|IECODE_UP_PREFIX;
5845 nch->nch_FakeEvent.ie_NextEvent = NULL;
5846 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers;
5847 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
5848 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
5849 nch->nch_InpIOReq->io_Command = IND_WRITEEVENT;
5850 DoIO((struct IORequest *) nch->nch_InpIOReq);
5851 #endif
5854 break;
5857 case HUA_DIGJOY:
5859 ULONG mask = 0;
5860 /* ULONG oldval; */
5861 ULONG *stateptr = &nch->nch_LLPortState[nha->nha_JoypadPort];
5863 switch(nha->nha_JoypadFeat)
5865 case HUAT_LEFT:
5866 mask = JPF_JOY_LEFT;
5867 break;
5869 case HUAT_RIGHT:
5870 mask = JPF_JOY_RIGHT;
5871 break;
5873 case HUAT_UP:
5874 mask = JPF_JOY_UP;
5875 break;
5877 case HUAT_DOWN:
5878 mask = JPF_JOY_DOWN;
5879 break;
5881 case HUAT_RED:
5882 mask = JPF_BUTTON_RED;
5883 break;
5885 case HUAT_BLUE:
5886 mask = JPF_BUTTON_BLUE;
5887 break;
5889 case HUAT_GREEN:
5890 mask = JPF_BUTTON_GREEN;
5891 break;
5893 case HUAT_YELLOW:
5894 mask = JPF_BUTTON_YELLOW;
5895 break;
5897 case HUAT_FORWARD:
5898 mask = JPF_BUTTON_FORWARD;
5899 break;
5901 case HUAT_REVERSE:
5902 mask = JPF_BUTTON_REVERSE;
5903 break;
5905 case HUAT_PLAY:
5906 mask = JPF_BUTTON_PLAY;
5907 break;
5909 case HUAT_HATSWITCH:
5910 mask = JP_DIRECTION_MASK;
5911 stateptr = &nch->nch_LLHatswitch[nha->nha_JoypadPort];
5912 break;
5915 /* oldval = *stateptr; */
5916 switch(nha->nha_JoypadOp)
5918 case HUAT_SET:
5919 *stateptr |= mask;
5920 break;
5922 case HUAT_CLEAR:
5923 *stateptr &= ~mask;
5924 break;
5926 case HUAT_TOGGLE:
5927 *stateptr ^= mask;
5928 break;
5930 case HUAT_ASSIGN:
5931 if(nha->nha_JoypadFeat == HUAT_HATSWITCH)
5933 value -= nhi->nhi_RealMin;
5934 if((value >= 0) && (value < 8))
5936 mask = LLHatswitchEncoding[value];
5937 } else {
5938 mask = 0;
5940 /*oldval = *stateptr;
5941 oldval &= ~JP_DIRECTION_MASK;
5942 oldval |= mask;
5943 *stateptr = oldval;*/
5944 *stateptr = mask;
5945 } else {
5946 if(value)
5948 *stateptr |= mask;
5949 } else {
5950 *stateptr &= ~mask;
5953 break;
5955 break;
5958 case HUA_ANALOGJOY:
5960 ULONG *stateptr = &nch->nch_LLAnalogue[nha->nha_JoypadPort];
5961 if((nhi->nhi_RealMin != 0) || (nhi->nhi_RealMax != 255))
5963 // scale
5964 value -= nhi->nhi_RealMin;
5965 value <<= 8;
5966 value /= (nhi->nhi_RealMax - nhi->nhi_RealMin);
5968 switch(nha->nha_APadFeat)
5970 case HUAT_ABSX:
5971 *stateptr = (*stateptr & ~JP_XAXIS_MASK) | (value & JP_XAXIS_MASK) | JP_TYPE_ANALOGUE;
5972 break;
5974 case HUAT_ABSY:
5975 *stateptr = (*stateptr & ~JP_YAXIS_MASK) | ((value<<8) & JP_YAXIS_MASK) | JP_TYPE_ANALOGUE;
5976 break;
5978 break;
5981 case HUA_OUTPUT:
5983 ULONG pos;
5984 struct NepHidItem *nhi;
5986 nhi = nFindItemID(nch, nha->nha_OutItem, REPORT_MAIN_OUTPUT, &pos);
5987 if(nhi)
5989 if(nhi->nhi_Flags & RPF_MAIN_VARIABLE)
5991 switch(nha->nha_OutOp)
5993 case HUAT_SET:
5994 nhi->nhi_OldValue = TRUE;
5995 break;
5997 case HUAT_CLEAR:
5998 nhi->nhi_OldValue = FALSE;
5999 break;
6001 case HUAT_TOGGLE:
6002 nhi->nhi_OldValue = nhi->nhi_OldValue ? FALSE : TRUE;
6003 break;
6005 case HUAT_ASSIGN:
6006 nhi->nhi_OldValue = value;
6007 break;
6009 } else {
6010 nParseArrayString(nch, nhi, nha->nha_OutArray);
6012 nhi->nhi_Collection->nhc_Report->nhr_OutTouched = TRUE;
6013 nch->nch_OutFeatTouched = TRUE;
6015 break;
6018 case HUA_FEATURE:
6020 ULONG pos;
6021 struct NepHidItem *nhi;
6023 nhi = nFindItemID(nch, nha->nha_FeatItem, REPORT_MAIN_FEATURE, &pos);
6024 if(nhi)
6026 if(nhi->nhi_Flags & RPF_MAIN_VARIABLE)
6028 switch(nha->nha_FeatOp)
6030 case HUAT_SET:
6031 nhi->nhi_OldValue = TRUE;
6032 break;
6034 case HUAT_CLEAR:
6035 nhi->nhi_OldValue = FALSE;
6036 break;
6038 case HUAT_TOGGLE:
6039 nhi->nhi_OldValue = nhi->nhi_OldValue ? FALSE : TRUE;
6040 break;
6042 case HUAT_ASSIGN:
6043 nhi->nhi_OldValue = value;
6044 break;
6046 } else {
6047 nParseArrayString(nch, nhi, nha->nha_OutArray);
6049 nhi->nhi_Collection->nhc_Report->nhr_FeatTouched = TRUE;
6050 nch->nch_OutFeatTouched = TRUE;
6052 break;
6055 case HUA_MISC:
6056 nch->nch_FakeEvent.ie_Class = IECLASS_NULL;
6057 nch->nch_FakeEvent.ie_SubClass = 0;
6058 nch->nch_FakeEvent.ie_Code = IECODE_NOBUTTON;
6059 nch->nch_FakeEvent.ie_NextEvent = NULL;
6060 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers;
6061 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
6062 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
6063 nch->nch_InpIOReq->io_Command = IND_WRITEEVENT;
6064 switch(nha->nha_MiscMode)
6066 case HUAT_DISPLAYBEEP:
6067 case HUAT_WIN2FRONT:
6068 case HUAT_WIN2BACK:
6069 case HUAT_ZIPWINDOW:
6070 case HUAT_SCREENCYCLE:
6071 case HUAT_WB2FRONT:
6072 case HUAT_ACTWINDOW:
6074 struct ActionMsg *am;
6075 if(!nch->nch_ClsBase->nh_DTaskMsgPort)
6077 nInstallLastActionHero(nch);
6079 if(nch->nch_ClsBase->nh_DTaskMsgPort)
6081 if((am = AllocVec(sizeof(struct ActionMsg), MEMF_PUBLIC)))
6083 am->am_Msg.mn_Length = sizeof(struct ActionMsg);
6084 am->am_Msg.mn_ReplyPort = NULL;
6085 am->am_NCH = nch;
6086 am->am_Action = nha;
6087 PutMsg(nch->nch_ClsBase->nh_DTaskMsgPort, &am->am_Msg);
6090 break;
6093 case HUAT_CLOSEWINDOW:
6094 nch->nch_FakeEvent.ie_Class = IECLASS_CLOSEWINDOW;
6095 DoIO((struct IORequest *) nch->nch_InpIOReq);
6096 break;
6098 case HUAT_REBOOT:
6099 nch->nch_CDC->cdc_EnableKBReset = TRUE;
6100 nch->nch_KeyQualifiers |= IEQUALIFIER_CONTROL|IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND;
6101 nCheckReset(nch);
6102 break;
6104 case HUAT_FLUSHEVENTS:
6105 nFlushEvents(nch);
6106 break;
6108 default:
6109 break;
6111 break;
6113 case HUA_VARIABLES:
6115 LONG *tarvarptr = NULL;
6117 switch(nha->nha_TarVar)
6119 case HUAT_LOCALVAR1:
6120 case HUAT_LOCALVAR2:
6121 case HUAT_LOCALVAR3:
6122 case HUAT_LOCALVAR4:
6123 case HUAT_LOCALVAR5:
6124 case HUAT_LOCALVAR6:
6125 case HUAT_LOCALVAR7:
6126 case HUAT_LOCALVAR8:
6127 tarvarptr = &nch->nch_LocalVars[nha->nha_TarVar - HUAT_LOCALVAR1];
6128 break;
6130 case HUAT_GLOBVARA:
6131 case HUAT_GLOBVARB:
6132 case HUAT_GLOBVARC:
6133 case HUAT_GLOBVARD:
6134 case HUAT_GLOBVARE:
6135 case HUAT_GLOBVARF:
6136 case HUAT_GLOBVARG:
6137 case HUAT_GLOBVARH:
6138 tarvarptr = &nch->nch_ClsBase->nh_GlobalVars[nha->nha_TarVar - HUAT_GLOBVARA];
6139 break;
6141 if(!tarvarptr)
6143 return(FALSE);
6145 switch(nha->nha_TarVarOp)
6147 case HUAT_ASSIGN:
6148 *tarvarptr = value;
6149 break;
6151 case HUAT_ADD:
6152 *tarvarptr += value;
6153 break;
6155 case HUAT_SUB:
6156 *tarvarptr -= value;
6157 break;
6159 case HUAT_MULTIPLY:
6160 *tarvarptr *= value;
6161 break;
6163 case HUAT_DIVIDE:
6164 if(value)
6166 *tarvarptr /= value;
6168 break;
6170 case HUAT_MODULO:
6171 if(value)
6173 *tarvarptr = value;
6175 break;
6177 case HUAT_AND:
6178 *tarvarptr = *tarvarptr && value;
6179 break;
6181 case HUAT_NAND:
6182 *tarvarptr = !(*tarvarptr && value);
6183 break;
6185 case HUAT_ANDNOT:
6186 *tarvarptr = *tarvarptr && (!value);
6187 break;
6189 case HUAT_OR:
6190 *tarvarptr = *tarvarptr || value;
6191 break;
6193 case HUAT_XOR:
6194 *tarvarptr = (*tarvarptr ^ value) ? TRUE : FALSE;
6195 break;
6197 case HUAT_BWAND:
6198 *tarvarptr &= value;
6199 break;
6201 case HUAT_BWNAND:
6202 *tarvarptr = ~(*tarvarptr & value);
6203 break;
6205 case HUAT_BWANDNOT:
6206 *tarvarptr &= ~value;
6207 break;
6209 case HUAT_BWOR:
6210 *tarvarptr |= value;
6211 break;
6213 case HUAT_BWXOR:
6214 *tarvarptr ^= value;
6215 break;
6217 case HUAT_ASL:
6218 *tarvarptr <<= value;
6219 break;
6221 case HUAT_ASR:
6222 *tarvarptr >>= value;
6223 break;
6225 return(TRUE);
6228 case HUA_EXTRAWKEY:
6229 #if 0 // FIXME looks like AROS does not support this (yet?)
6230 nch->nch_FakeEvent.ie_Class = IECLASS_EXTRAWKEY;
6231 nch->nch_FakeEvent.ie_SubClass = 0;
6232 nch->nch_FakeEvent.ie_Code = nha->nha_RawKey;
6233 // using ie.dead.ie_prev1DownCode instead of ie_extkey.ie_extkey1
6234 nch->nch_FakeEvent.ie_position.ie_dead.ie_prev1DownCode = 0xe0;
6235 nch->nch_FakeEvent.ie_position.ie_dead.ie_prev1DownQual = nha->nha_RawKey;
6236 nch->nch_FakeEvent.ie_NextEvent = NULL;
6237 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers;
6238 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
6239 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
6240 nch->nch_InpIOReq->io_Command = IND_WRITEEVENT;
6241 DoIO((struct IORequest *) nch->nch_InpIOReq);
6242 #endif
6243 break;
6246 return(res);
6248 /* \\\ */
6250 /* /// "nFlushEvents()" */
6251 void nFlushEvents(struct NepClassHid *nch)
6253 struct PsdPipe *pp;
6254 ULONG buflen;
6255 LONG ioerr;
6257 struct NepHidReport *nhr;
6259 /* output/feature pipes */
6260 if(nch->nch_OutFeatTouched)
6262 nch->nch_OutFeatTouched = FALSE;
6263 pp = nch->nch_EP0Pipe;
6264 nhr = (struct NepHidReport *) nch->nch_HidReports.lh_Head;
6265 while(nhr->nhr_Node.ln_Succ)
6267 if(nhr->nhr_OutTouched)
6269 KPRINTF(1, ("Out Report %ld touched...\n", nhr->nhr_ReportID));
6270 buflen = (nhr->nhr_ReportOutSize+7)>>3;
6271 if(nch->nch_UsesReportID)
6273 *nch->nch_EPOutBuf = nhr->nhr_ReportID;
6274 nGenerateOutReport(nch, nhr, nch->nch_EPOutBuf+1);
6275 buflen++;
6276 psdPipeSetup(pp, URTF_OUT|URTF_CLASS|URTF_INTERFACE,
6277 UHR_SET_REPORT, (ULONG) nhr->nhr_ReportID|0x0200, nch->nch_IfNum);
6278 } else {
6279 nGenerateOutReport(nch, nhr, nch->nch_EPOutBuf);
6280 psdPipeSetup(pp, URTF_OUT|URTF_CLASS|URTF_INTERFACE,
6281 UHR_SET_REPORT, 0x0200, nch->nch_IfNum);
6283 KPRINTF(1, ("Len: %ld [%02lx %02lx]", buflen, nch->nch_EPOutBuf[0], nch->nch_EPOutBuf[1]));
6284 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
6285 "HID OUT Report %02lx Debug (%ld bytes):", nhr->nhr_ReportID, buflen);
6286 nDebugMem(nch, nch->nch_EPOutBuf, buflen);*/
6288 if((ioerr = psdDoPipe(pp, nch->nch_EPOutBuf, buflen)))
6290 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
6291 "SET_REPORT(%lx, %ld) failed: %s (%ld)!",
6292 nhr->nhr_ReportID|0x0200, buflen,
6293 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
6295 nhr->nhr_OutTouched = FALSE;
6297 if(nhr->nhr_FeatTouched)
6299 KPRINTF(1, ("Feat Report %ld touched...\n", nhr->nhr_ReportID));
6300 buflen = (nhr->nhr_ReportFeatSize+7)>>3;
6301 if(nch->nch_UsesReportID)
6303 *nch->nch_EPOutBuf = nhr->nhr_ReportID;
6304 nGenerateFeatReport(nch, nhr, nch->nch_EPOutBuf+1);
6305 buflen++;
6306 psdPipeSetup(pp, URTF_OUT|URTF_CLASS|URTF_INTERFACE,
6307 UHR_SET_REPORT, (ULONG) nhr->nhr_ReportID|0x0300, nch->nch_IfNum);
6308 } else {
6309 nGenerateFeatReport(nch, nhr, nch->nch_EPOutBuf);
6310 psdPipeSetup(pp, URTF_OUT|URTF_CLASS|URTF_INTERFACE,
6311 UHR_SET_REPORT, 0x0300, nch->nch_IfNum);
6313 KPRINTF(1, ("Len: %ld [%02lx %02lx]", buflen, nch->nch_EPOutBuf[0], nch->nch_EPOutBuf[1]));
6314 if((ioerr = psdDoPipe(pp, nch->nch_EPOutBuf, buflen)))
6316 psdAddErrorMsg(RETURN_ERROR, (STRPTR) GM_UNIQUENAME(libname),
6317 "SET_REPORT(%lx, %ld) failed: %s (%ld)!",
6318 nhr->nhr_ReportID|0x0300, buflen,
6319 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
6320 }/* else {
6321 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
6322 "SET_REPORT(%lx, %ld)=%02lx%02lx okay!",
6323 nhr->nhr_ReportID|0x0300, buflen,
6324 nch->nch_EPOutBuf[1], nch->nch_EPOutBuf[2]);
6326 nhr->nhr_FeatTouched = FALSE;
6328 nhr = (struct NepHidReport *) nhr->nhr_Node.ln_Succ;
6331 if(nch->nch_NewMouseRel && (nch->nch_MouseDeltaX || nch->nch_MouseDeltaY))
6333 KPRINTF(1, ("Mouse rel movement...\n"));
6334 nch->nch_FakeEvent.ie_X = nch->nch_MouseDeltaX;
6335 nch->nch_FakeEvent.ie_Y = nch->nch_MouseDeltaY;
6336 nch->nch_FakeEvent.ie_Class = IECLASS_RAWMOUSE;
6337 nch->nch_FakeEvent.ie_SubClass = 0;
6338 nch->nch_FakeEvent.ie_Code = IECODE_NOBUTTON;
6339 nch->nch_FakeEvent.ie_NextEvent = NULL;
6340 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers|IEQUALIFIER_RELATIVEMOUSE;
6341 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
6342 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
6343 nch->nch_InpIOReq->io_Command = nch->nch_OS4Hack ? IND_ADDEVENT : IND_WRITEEVENT;
6344 DoIO((struct IORequest *) nch->nch_InpIOReq);
6345 nch->nch_NewMouseRel = FALSE;
6346 nch->nch_MouseDeltaX = 0;
6347 nch->nch_MouseDeltaY = 0;
6349 if(nch->nch_NewMouseAbs)
6351 ULONG *tagptr = nch->nch_TabTags;
6352 KPRINTF(1, ("Mouse abs movement...\n"));
6353 nch->nch_FakeEvent.ie_EventAddress = &nch->nch_TabletEvent;
6354 nch->nch_TabletEvent.ient_RangeX = nch->nch_MouseRangeX;
6355 nch->nch_TabletEvent.ient_RangeY = nch->nch_MouseRangeY;
6356 nch->nch_TabletEvent.ient_TabletX = nch->nch_MouseAbsX;
6357 nch->nch_TabletEvent.ient_TabletY = nch->nch_MouseAbsY;
6358 nch->nch_TabletEvent.ient_TagList = (struct TagItem *) tagptr;
6359 if(nch->nch_MouseRangeZ)
6361 KPRINTF(1, ("AbsZ %ld\n", nch->nch_MouseAbsZ));
6362 *tagptr++ = TABLETA_TabletZ;
6363 *tagptr++ = nch->nch_MouseAbsZ;
6364 *tagptr++ = TABLETA_RangeZ;
6365 *tagptr++ = nch->nch_MouseRangeZ;
6367 if(nch->nch_VldRotX)
6369 KPRINTF(1, ("AngleX %ld\n", nch->nch_TabRotX));
6370 *tagptr++ = TABLETA_AngleX;
6371 *tagptr++ = nch->nch_TabRotX;
6373 if(nch->nch_VldRotY)
6375 KPRINTF(1, ("AngleY %ld\n", nch->nch_TabRotY));
6376 *tagptr++ = TABLETA_AngleY;
6377 *tagptr++ = nch->nch_TabRotY;
6379 if(nch->nch_VldRotZ)
6381 KPRINTF(1, ("AngleZ %ld\n", nch->nch_TabRotZ));
6382 *tagptr++ = TABLETA_AngleZ;
6383 *tagptr++ = nch->nch_TabRotZ;
6385 if(nch->nch_VldPressure)
6387 KPRINTF(1, ("Pressure %ld\n", nch->nch_TabPressure));
6388 *tagptr++ = TABLETA_Pressure;
6389 *tagptr++ = nch->nch_TabPressure;
6391 *tagptr++ = TABLETA_ButtonBits;
6392 *tagptr++ = nch->nch_MouseButtons;
6393 if(nch->nch_VldProx)
6395 KPRINTF(1, ("InProx %ld\n", nch->nch_TabProx));
6396 *tagptr++ = TABLETA_InProximity;
6397 *tagptr++ = nch->nch_TabProx;
6399 *tagptr = TAG_END;
6400 nch->nch_FakeEvent.ie_Class = IECLASS_NEWPOINTERPOS;
6401 nch->nch_FakeEvent.ie_SubClass = IESUBCLASS_NEWTABLET;
6402 nch->nch_FakeEvent.ie_Code = IECODE_NOBUTTON;
6403 nch->nch_FakeEvent.ie_NextEvent = NULL;
6404 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers;
6405 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
6406 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
6407 nch->nch_InpIOReq->io_Command = IND_WRITEEVENT;
6408 DoIO((struct IORequest *) nch->nch_InpIOReq);
6409 nch->nch_NewMouseAbs = FALSE;
6411 nCheckReset(nch);
6413 /* \\\ */
6415 /* /// "nSendRawKey()" */
6416 void nSendRawKey(struct NepClassHid *nch, UWORD key)
6418 nch->nch_FakeEvent.ie_Class = IECLASS_RAWKEY;
6419 nch->nch_FakeEvent.ie_SubClass = 0;
6420 nch->nch_FakeEvent.ie_Code = key;
6421 nch->nch_FakeEvent.ie_NextEvent = NULL;
6422 nch->nch_FakeEvent.ie_Qualifier = nch->nch_KeyQualifiers;
6423 nch->nch_InpIOReq->io_Data = &nch->nch_FakeEvent;
6424 nch->nch_InpIOReq->io_Length = sizeof(struct InputEvent);
6425 nch->nch_InpIOReq->io_Command = nch->nch_OS4Hack ? IND_ADDEVENT : IND_WRITEEVENT;
6426 DoIO((struct IORequest *) nch->nch_InpIOReq);
6428 /* \\\ */
6430 /* /// "nCheckReset()" */
6431 void nCheckReset(struct NepClassHid *nch)
6433 if(nch->nch_CDC->cdc_EnableKBReset &&
6434 (nch->nch_KeyQualifiers & (IEQUALIFIER_CONTROL|IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND)) ==
6435 (IEQUALIFIER_CONTROL|IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND))
6437 struct MsgPort *mp;
6438 struct IOStdReq *ioreq;
6439 struct Interrupt tempint;
6440 struct Node *node;
6441 struct List *listhead = NULL;
6442 BOOL haskbh = FALSE;
6443 KPRINTF(20, ("Reboot!\n"));
6445 if(nch->nch_CDC->cdc_EnableRH)
6447 if((mp = CreateMsgPort()))
6449 if((ioreq = (struct IOStdReq *) CreateIORequest(mp, sizeof(struct IOStdReq))))
6451 if(!OpenDevice("keyboard.device", 0, (struct IORequest *) ioreq, 0))
6453 /* Find list header of reset handlers */
6454 tempint.is_Node.ln_Pred = NULL;
6455 tempint.is_Node.ln_Succ = NULL;
6456 tempint.is_Node.ln_Type = NT_INTERRUPT;
6457 tempint.is_Node.ln_Pri = 32;
6458 tempint.is_Node.ln_Name = "";
6459 tempint.is_Code = NULL;
6460 ioreq->io_Command = KBD_ADDRESETHANDLER;
6461 ioreq->io_Data = &tempint;
6462 Forbid();
6463 DoIO((struct IORequest *) ioreq);
6464 if((node = tempint.is_Node.ln_Pred))
6466 while(node->ln_Pred)
6468 node = node->ln_Pred;
6470 listhead = (struct List *) node;
6472 ioreq->io_Command = KBD_REMRESETHANDLER;
6473 DoIO((struct IORequest *) ioreq);
6474 Permit();
6475 if(listhead)
6477 node = listhead->lh_Head;
6478 while(node->ln_Succ)
6480 KPRINTF(20, ("Kicking %s\n", node->ln_Name));
6481 Cause((struct Interrupt *) node);
6482 haskbh = TRUE;
6483 node = node->ln_Succ;
6485 KPRINTF(20, ("Done... awaiting doom\n"));
6486 if(haskbh)
6488 psdDelayMS(nch->nch_CDC->cdc_ResetDelay*1000);
6490 } else {
6491 KPRINTF(20, ("Reset handler list not found!\n"));
6493 CloseDevice((struct IORequest *) ioreq);
6495 DeleteIORequest((struct IORequest *) ioreq);
6497 DeleteMsgPort(mp);
6500 ColdReboot();
6502 else if(nch->nch_CDC->cdc_EnableKBReset &&
6503 (nch->nch_KeyQualifiers & IEQUALIFIER_CONTROL) &&
6504 (nch->nch_KeyQualifiers & (IEQUALIFIER_LALT|IEQUALIFIER_RALT)) &&
6505 nch->nch_FakeEvent.ie_Code == RAWKEY_DELETE)
6507 KPRINTF(20, ("Reboot!\n"));
6508 ShutdownA(SD_ACTION_COLDREBOOT);
6511 /* \\\ */
6513 /* /// "nLoadItem()" */
6514 BOOL nLoadItem(struct NepClassHid *nch, struct PsdIFFContext *rppic, struct List *lst, UWORD idbase)
6516 struct PsdIFFContext *itpic;
6517 struct PsdIFFContext *actpic;
6518 struct NepHidAction *nha;
6519 ULONG newform[3];
6520 ULONG buf[2];
6521 struct NepHidActionChunk *nhac;
6522 STRPTR tmpstr;
6524 psdSafeRawDoFmt((STRPTR) buf, 8, "I%03lx", GET_WTYPE(lst) - idbase + 1);
6525 newform[0] = AROS_LONG2BE(ID_FORM);
6526 newform[1] = AROS_LONG2BE(4);
6527 newform[2] = *buf;
6528 itpic = psdFindCfgForm(rppic, AROS_LONG2BE(newform[2]));
6529 if(!itpic)
6531 return(FALSE);
6533 actpic = psdFindCfgForm(itpic, MAKE_ID('A','C','T','N'));
6534 while(actpic)
6536 if((nhac = psdGetCfgChunk(actpic, MAKE_ID('A','C','D','F'))))
6538 if((nha = nAllocAction(nch, lst, 0)))
6540 CopyMem(&nhac->nhac_Type, &nha->nha_Type, min(AROS_LONG2BE(nhac->nhac_Length), sizeof(struct NepHidActionChunk) - 8));
6541 if((tmpstr = psdGetStringChunk(actpic, MAKE_ID('S','N','D','F'))))
6543 strncpy(nha->nha_SoundFile, tmpstr, 255);
6544 psdFreeVec(tmpstr);
6546 if((tmpstr = psdGetStringChunk(actpic, MAKE_ID('V','A','N','S'))))
6548 strncpy(nha->nha_VanillaString, tmpstr, 79);
6549 psdFreeVec(tmpstr);
6551 if((tmpstr = psdGetStringChunk(actpic, MAKE_ID('K','E','Y','S'))))
6553 strncpy(nha->nha_KeyString, tmpstr, 79);
6554 psdFreeVec(tmpstr);
6556 if((tmpstr = psdGetStringChunk(actpic, MAKE_ID('E','X','E','S'))))
6558 strncpy(nha->nha_ExeString, tmpstr, 79);
6559 psdFreeVec(tmpstr);
6561 if((tmpstr = psdGetStringChunk(actpic, MAKE_ID('O','A','R','R'))))
6563 strncpy(nha->nha_OutArray, tmpstr, 255);
6564 psdFreeVec(tmpstr);
6567 psdFreeVec(nhac);
6569 actpic = psdNextCfgForm(actpic);
6571 return(TRUE);
6573 /* \\\ */
6575 /* /// "nSaveItem()" */
6576 struct PsdIFFContext * nSaveItem(struct NepClassHid *nch, struct PsdIFFContext *rppic, struct List *lst, UWORD idbase)
6578 struct PsdIFFContext *itpic;
6579 struct PsdIFFContext *actpic;
6580 struct NepHidAction *nha;
6581 ULONG newform[3];
6582 ULONG buf[2];
6583 struct NepHidActionChunk nhac;
6584 BOOL isdefault = TRUE;
6586 if(!lst->lh_Head->ln_Succ)
6588 return(NULL);
6590 nha = (struct NepHidAction *) lst->lh_Head;
6591 while(nha->nha_Node.ln_Succ)
6593 if(!nha->nha_IsDefault)
6595 isdefault = FALSE;
6597 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
6599 if(isdefault)
6601 return(NULL);
6603 psdSafeRawDoFmt((STRPTR) buf, 8, "I%03lx", GET_WTYPE(lst) - idbase + 1);
6604 newform[0] = AROS_LONG2BE(ID_FORM);
6605 newform[1] = AROS_LONG2BE(4);
6606 newform[2] = *buf;
6607 itpic = psdFindCfgForm(rppic, AROS_LONG2BE(newform[2]));
6608 if(!itpic)
6610 itpic = psdAddCfgEntry(rppic, newform);
6611 if(!itpic)
6613 return(NULL);
6616 nhac.nhac_ID = AROS_LONG2BE(MAKE_ID('A','C','D','F'));
6617 nhac.nhac_Length = AROS_LONG2BE(sizeof(struct NepHidActionChunk)-8);
6618 nha = (struct NepHidAction *) lst->lh_Head;
6619 while(nha->nha_Node.ln_Succ)
6621 if(!nha->nha_IsDefault)
6623 isdefault = FALSE;
6625 newform[2] = AROS_LONG2BE(MAKE_ID('A','C','T','N'));
6626 actpic = psdAddCfgEntry(itpic, newform);
6627 if(!actpic)
6629 break;
6631 CopyMem(&nha->nha_Type, &nhac.nhac_Type, sizeof(struct NepHidActionChunk)-8);
6632 psdAddCfgEntry(actpic, &nhac);
6633 if(*nha->nha_SoundFile)
6635 psdAddStringChunk(actpic, MAKE_ID('S','N','D','F'), nha->nha_SoundFile);
6637 if(*nha->nha_VanillaString)
6639 psdAddStringChunk(actpic, MAKE_ID('V','A','N','S'), nha->nha_VanillaString);
6641 if(*nha->nha_KeyString)
6643 psdAddStringChunk(actpic, MAKE_ID('K','E','Y','S'), nha->nha_KeyString);
6645 if(*nha->nha_ExeString)
6647 psdAddStringChunk(actpic, MAKE_ID('E','X','E','S'), nha->nha_ExeString);
6649 if(*nha->nha_OutArray)
6651 psdAddStringChunk(actpic, MAKE_ID('O','A','R','R'), nha->nha_OutArray);
6653 nha = (struct NepHidAction *) nha->nha_Node.ln_Succ;
6655 return(itpic);
6657 /* \\\ */
6659 /* /// "nReadJoyPort()" */
6660 AROS_LH1(ULONG, nReadJoyPort,
6661 AROS_LHA(ULONG, port, D0),
6662 struct Library *, LowLevelBase, 5, hid)
6664 AROS_LIBFUNC_INIT
6666 struct NepHidBase *nh;
6667 struct NepClassHid *nch;
6668 ULONG result = JP_TYPE_NOTAVAIL;
6669 ULONG mode;
6671 if(!(nh = (struct NepHidBase *) FindName(&SysBase->LibList, GM_UNIQUENAME(libname))))
6673 return(result);
6676 result = AROS_CALL1(ULONG, nh->nh_LLOldReadJoyPort,
6677 AROS_LCA(ULONG, port, D0),
6678 struct Library *, nh->nh_LowLevelBase);
6680 KPRINTF(40, ("Before %08lx\n", result));
6681 if(port < 4)
6683 Forbid();
6684 nch = (struct NepClassHid *) nh->nh_Interfaces.lh_Head;
6685 while(nch->nch_Node.ln_Succ)
6687 mode = nch->nch_CDC->cdc_LLPortMode[port];
6688 if(nh->nh_LLAnalogueOverride[port] && nch->nch_LLAnalogue[port])
6690 mode = 4;
6693 switch(mode)
6695 // case 0: /* don't touch */
6696 // break;
6698 case 1: /* overwrite with USB */
6699 result = nch->nch_LLPortState[port] | nch->nch_LLHatswitch[port] | JP_TYPE_GAMECTLR;
6700 break;
6702 case 2: /* merge with USB */
6703 if(((result & JP_TYPE_MASK) == JP_TYPE_GAMECTLR) ||
6704 ((result & JP_TYPE_MASK) == JP_TYPE_JOYSTK) ||
6705 ((result & JP_TYPE_MASK) == JP_TYPE_UNKNOWN) ||
6706 (!result))
6708 result = (result & (JP_BUTTON_MASK|JP_DIRECTION_MASK)) | nch->nch_LLPortState[port] | nch->nch_LLHatswitch[port] | JP_TYPE_GAMECTLR;
6710 break;
6712 case 3: /* disable */
6713 result = JP_TYPE_NOTAVAIL;
6714 break;
6716 case 4: /* overwrite with analogue USB */
6717 if(nch->nch_LLAnalogue[port])
6719 result = (nch->nch_LLPortState[port] & ~JP_DIRECTION_MASK) | (nch->nch_LLAnalogue[port] & JP_XYAXIS_MASK) | nch->nch_LLHatswitch[port] | JP_TYPE_ANALOGUE;
6721 break;
6723 nch = (struct NepClassHid *) nch->nch_Node.ln_Succ;
6725 Permit();
6727 if((port >= JP_ANALOGUE_PORT_MAGIC) && (port < (JP_ANALOGUE_PORT_MAGIC|4)))
6729 port &= 3;
6730 Forbid();
6731 nch = (struct NepClassHid *) nh->nh_Interfaces.lh_Head;
6732 while(nch->nch_Node.ln_Succ)
6734 if(nch->nch_LLAnalogue[port])
6736 result = (nch->nch_LLPortState[port] & ~JP_DIRECTION_MASK) | (nch->nch_LLAnalogue[port] & JP_XYAXIS_MASK) | nch->nch_LLHatswitch[port] | JP_TYPE_ANALOGUE;
6738 nch = (struct NepClassHid *) nch->nch_Node.ln_Succ;
6740 Permit();
6742 KPRINTF(40, ("And after %08lx\n", result));
6744 return(result);
6745 AROS_LIBFUNC_EXIT
6747 /* \\\ */
6749 /* /// "nSetJoyPortAttrsA()" */
6750 AROS_LH2(ULONG, nSetJoyPortAttrsA,
6751 AROS_LHA(ULONG, port, D0),
6752 AROS_LHA(struct TagItem *, tags, A1),
6753 struct Library *, LowLevelBase, 22, hid)
6755 AROS_LIBFUNC_INIT
6757 struct NepHidBase *nh;
6758 struct TagItem *typetag;
6759 struct TagItem *motortags[2];
6760 struct TagItem *motorofftag;
6761 ULONG result = FALSE;
6763 if(!(nh = (struct NepHidBase *) FindName(&SysBase->LibList, GM_UNIQUENAME(libname))))
6765 return(result);
6768 result = AROS_CALL2(ULONG, nh->nh_LLOldSetJoyPortAttrsA,
6769 AROS_LCA(ULONG, port, D0),
6770 AROS_LCA(struct TagItem *, tags, A1),
6771 struct Library *, nh->nh_LowLevelBase);
6773 KPRINTF(40, ("Before %08lx\n", result));
6774 if(port < 4)
6776 typetag = FindTagItem(SJA_Type, tags);
6777 if(typetag)
6779 if(typetag->ti_Data == SJA_TYPE_ANALOGUE)
6781 nh->nh_LLAnalogueOverride[port] = TRUE;
6782 } else {
6783 nh->nh_LLAnalogueOverride[port] = FALSE;
6785 result = TRUE;
6787 typetag = FindTagItem(SJA_Reinitialize, tags);
6788 if(typetag)
6790 if(typetag->ti_Data)
6792 nh->nh_LLAnalogueOverride[port] = FALSE;
6795 motortags[0] = FindTagItem(SJA_RumbleSetSlowMotor, tags);
6796 motortags[1] = FindTagItem(SJA_RumbleSetFastMotor, tags);
6797 motorofftag = FindTagItem(SJA_RumbleOff, tags);
6798 if(motortags[0] || motortags[1] || motorofftag)
6800 struct NepHidItem *nhi;
6801 struct NepClassHid *nch;
6802 struct TagItem nulltag = { 0, 0 };
6803 ULONG cnt;
6804 BOOL sigit = FALSE;
6805 if(motorofftag)
6807 if(motorofftag->ti_Data)
6809 motortags[0] = &nulltag;
6810 motortags[1] = &nulltag;
6813 Forbid();
6814 nch = (struct NepClassHid *) nh->nh_Interfaces.lh_Head;
6815 while(nch->nch_Node.ln_Succ)
6817 if(nch->nch_CDC->cdc_LLRumblePort == port+1)
6819 for(cnt = 0; cnt < 2; cnt++)
6821 if(motortags[cnt] && ((nhi = nch->nch_RumbleMotors[cnt])))
6823 if(nhi->nhi_OldValue != motortags[cnt]->ti_Data)
6825 nhi->nhi_OldValue = motortags[cnt]->ti_Data;
6826 nhi->nhi_Collection->nhc_Report->nhr_OutTouched = TRUE;
6827 nch->nch_OutFeatTouched = TRUE;
6828 sigit = TRUE;
6832 if(sigit)
6834 Signal(nch->nch_Task, (1L<<nch->nch_TaskMsgPort->mp_SigBit));
6838 nch = (struct NepClassHid *) nch->nch_Node.ln_Succ;
6840 Permit();
6841 result = TRUE;
6844 KPRINTF(40, ("And after %08lx\n", result));
6846 return(result);
6848 AROS_LIBFUNC_EXIT
6850 /* \\\ */
6852 /* /// "nInstallLastActionHero()" */
6853 void nInstallLastActionHero(struct NepClassHid *nch)
6855 struct NepHidBase *nh = nch->nch_ClsBase;
6857 if(!nh->nh_DispatcherTask)
6859 nh->nh_ReadySignal = SIGB_SINGLE;
6860 nh->nh_ReadySigTask = FindTask(NULL);
6861 SetSignal(0, SIGF_SINGLE);
6862 if(psdSpawnSubTask("Last Action Hero", GM_UNIQUENAME(nDispatcherTask), nh))
6864 Wait(1L<<nh->nh_ReadySignal);
6865 if(!nh->nh_DispatcherTask)
6867 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
6868 "It's your fault! I'm sure! Couldn't create subtask for launching!");
6869 } else {
6870 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
6871 "Last Action Hero successfully launched!");
6873 } else {
6874 psdAddErrorMsg(RETURN_FAIL, (STRPTR) GM_UNIQUENAME(libname),
6875 "It's your fault! I'm sure! Couldn't create subtask for launching!");
6877 nh->nh_ReadySigTask = NULL;
6878 //FreeSignal(nh->nh_ReadySignal);
6881 /* \\\ */
6883 /************************************************************************/
6885 #undef ps
6887 /* /// "nDispatcherTask()" */
6888 AROS_UFH0(void, GM_UNIQUENAME(nDispatcherTask))
6890 AROS_USERFUNC_INIT
6892 struct NepHidBase *nh;
6893 struct Task *thistask;
6894 struct ActionMsg *am;
6895 struct NepHidSound *nhs;
6897 thistask = FindTask(NULL);
6899 #undef CxBase
6900 #undef IntuitionBase
6901 #undef DOSBase
6902 #undef DataTypesBase
6903 nh = thistask->tc_UserData;
6904 NewList(&nh->nh_Sounds);
6905 if((nh->nh_InpMsgPort = CreateMsgPort()))
6907 if((nh->nh_InpIOReq = (struct IOStdReq *) CreateIORequest(nh->nh_InpMsgPort, sizeof(struct IOStdReq))))
6909 if(!OpenDevice("input.device", 0, (struct IORequest *) nh->nh_InpIOReq, 0))
6911 if((nh->nh_DOSBase = OpenLibrary("dos.library", 39)))
6913 if((nh->nh_IntBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 39)))
6915 #define IntuitionBase nh->nh_IntBase
6916 if((nh->nh_DTBase = OpenLibrary("datatypes.library", 39)))
6918 if((nh->nh_CxBase = OpenLibrary("commodities.library", 39)))
6920 if((nh->nh_LayersBase = OpenLibrary("layers.library", 39)))
6922 #define CxBase nh->nh_CxBase
6923 #define DOSBase nh->nh_DOSBase
6924 #define DataTypesBase nh->nh_DTBase
6925 #define LayersBase nh->nh_LayersBase
6926 if((nh->nh_DTaskMsgPort = CreateMsgPort()))
6928 nh->nh_DispatcherTask = thistask;
6929 Forbid();
6930 if(nh->nh_ReadySigTask)
6932 Signal(nh->nh_ReadySigTask, 1L<<nh->nh_ReadySignal);
6934 Permit();
6936 nLastActionHero(nh);
6938 Forbid();
6939 while((am = (struct ActionMsg *) GetMsg(nh->nh_DTaskMsgPort)))
6941 FreeVec(am);
6943 nhs = (struct NepHidSound *) nh->nh_Sounds.lh_Head;
6944 while(nhs->nhs_Node.ln_Succ)
6946 nFreeSound(nh, nhs);
6947 nhs = (struct NepHidSound *) nh->nh_Sounds.lh_Head;
6949 DeleteMsgPort(nh->nh_DTaskMsgPort);
6950 nh->nh_DTaskMsgPort = NULL;
6951 Permit();
6953 CloseLibrary(nh->nh_LayersBase);
6954 nh->nh_LayersBase = NULL;
6956 CloseLibrary(nh->nh_CxBase);
6957 nh->nh_CxBase = NULL;
6959 CloseLibrary(nh->nh_DTBase);
6960 nh->nh_DTBase = NULL;
6962 CloseLibrary((struct Library *) nh->nh_IntBase);
6963 nh->nh_IntBase = NULL;
6965 CloseLibrary((struct Library *) nh->nh_DOSBase);
6966 nh->nh_DOSBase = NULL;
6968 CloseDevice((struct IORequest *) nh->nh_InpIOReq);
6970 DeleteIORequest((struct IORequest *) nh->nh_InpIOReq);
6971 nh->nh_InpIOReq = NULL;
6973 DeleteMsgPort(nh->nh_InpMsgPort);
6974 nh->nh_InpMsgPort = NULL;
6976 Forbid();
6977 if(nh->nh_ReadySigTask)
6979 Signal(nh->nh_ReadySigTask, 1L<<nh->nh_ReadySignal);
6981 nh->nh_DispatcherTask = NULL;
6983 AROS_USERFUNC_EXIT
6985 /* \\\ */
6987 /* /// "nLastActionHero()" */
6988 void nLastActionHero(struct NepHidBase *nh)
6990 ULONG sigmask;
6991 ULONG sigs;
6992 struct ActionMsg *am;
6993 struct NepHidAction *nha;
6994 struct NepClassHid *nch;
6995 struct Window *actwindow;
6996 struct Screen *actscreen;
6997 char buf[128];
6998 ULONG intlock;
6999 sigmask = (1L<<nh->nh_DTaskMsgPort->mp_SigBit)|SIGBREAKF_CTRL_C;
7002 while((am = (struct ActionMsg *) GetMsg(nh->nh_DTaskMsgPort)))
7004 nch = am->am_NCH;
7005 nha = am->am_Action;
7006 switch(nha->nha_Type & HUA_ATYPEMASK)
7008 case HUA_VANILLA:
7009 buf[0] = '<';
7010 strcpy(&buf[1], nha->nha_VanillaString);
7011 strcat(buf, ">");
7012 if(!nSendKeyString(nh, buf))
7014 nEasyRequest(nh, "'%s' is no good. Really.", "Argl!", nha->nha_VanillaString);
7016 break;
7018 case HUA_KEYSTRING:
7019 if(!nSendKeyString(nh, nha->nha_KeyString))
7021 nEasyRequest(nh, "Don't you ever say\n'%s'\nto me again!", "Terribly sorry!", nha->nha_KeyString);
7023 break;
7025 case HUA_SOUND:
7026 nPlaySound(nh, nha);
7027 break;
7029 case HUA_SHELL:
7031 BPTR fhandle;
7032 LONG ioerr;
7033 if((fhandle = Open(nch->nch_CDC->cdc_ShellCon, MODE_READWRITE)))
7035 ioerr = SystemTags(nha->nha_ExeString,
7036 SYS_Input, fhandle,
7037 SYS_Output, NULL,
7038 SYS_Asynch, nha->nha_ShellAsync,
7039 NP_StackSize, nch->nch_CDC->cdc_ShellStack,
7040 TAG_END);
7041 if(ioerr)
7043 nEasyRequest(nh, "Offender survived execution of\n'%s'\nwith error code %ld.", "Get me a shotgun then!", nha->nha_ExeString, ioerr);
7045 if((!nha->nha_ShellAsync) || ioerr)
7047 Close(fhandle);
7049 } else {
7050 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);
7052 break;
7055 case HUA_MISC:
7056 switch(nha->nha_MiscMode)
7058 case HUAT_ACTWINDOW:
7060 struct Layer *toplayer;
7061 intlock = LockIBase(0);
7062 actscreen = nh->nh_IntBase->ActiveScreen;
7063 actwindow = nh->nh_IntBase->ActiveWindow;
7064 UnlockIBase(intlock);
7065 if(actscreen)
7067 LockLayerInfo(&actscreen->LayerInfo);
7068 toplayer = WhichLayer(&actscreen->LayerInfo, (LONG) actscreen->MouseX, (LONG) actscreen->MouseY);
7069 UnlockLayerInfo(&actscreen->LayerInfo);
7071 if(toplayer)
7073 if(toplayer->Window && (actwindow != toplayer->Window))
7075 ActivateWindow(toplayer->Window);
7079 break;
7082 case HUAT_DISPLAYBEEP:
7083 DisplayBeep(NULL);
7084 break;
7086 case HUAT_WB2FRONT:
7087 WBenchToFront();
7088 break;
7090 case HUAT_SCREENCYCLE:
7091 intlock = LockIBase(0);
7092 actscreen = nh->nh_IntBase->FirstScreen;
7093 UnlockIBase(intlock);
7094 if(actscreen)
7096 ScreenToBack(actscreen);
7098 break;
7100 case HUAT_WIN2FRONT:
7101 intlock = LockIBase(0);
7102 actwindow = nh->nh_IntBase->ActiveWindow;
7103 UnlockIBase(intlock);
7104 if(actwindow)
7106 WindowToFront(actwindow);
7108 break;
7110 case HUAT_WIN2BACK:
7111 intlock = LockIBase(0);
7112 actwindow = nh->nh_IntBase->ActiveWindow;
7113 UnlockIBase(intlock);
7114 if(actwindow)
7116 WindowToBack(actwindow);
7118 break;
7120 case HUAT_ZIPWINDOW:
7121 intlock = LockIBase(0);
7122 actwindow = nh->nh_IntBase->ActiveWindow;
7123 UnlockIBase(intlock);
7124 if(actwindow)
7126 ZipWindow(actwindow);
7128 break;
7131 break;
7134 FreeVec(am);
7136 sigs = Wait(sigmask);
7137 } while(!(sigs & SIGBREAKF_CTRL_C));
7139 /* \\\ */
7141 /* /// "nLoadSound()" */
7142 struct NepHidSound * nLoadSound(struct NepHidBase *nh, STRPTR name)
7144 struct NepHidSound *nhs;
7145 if((nhs = AllocVec(sizeof(struct NepHidSound), MEMF_PUBLIC|MEMF_CLEAR)))
7147 if((nhs->nhs_Node.ln_Name = AllocVec((ULONG) strlen(name)+1, MEMF_PUBLIC)))
7149 strcpy(nhs->nhs_Node.ln_Name, name);
7150 AddTail(&nh->nh_Sounds, &nhs->nhs_Node);
7151 nhs->nhs_DTHandle = NewDTObject(name,
7152 DTA_SourceType, DTST_FILE,
7153 DTA_GroupID, GID_SOUND,
7154 SDTA_Cycles, 1L,
7155 TAG_END);
7156 if(!nhs->nhs_DTHandle)
7158 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);
7160 return(nhs);
7162 FreeVec(nhs);
7164 return(NULL);
7166 /* \\\ */
7168 /* /// "nPlaySound()" */
7169 BOOL nPlaySound(struct NepHidBase *nh, struct NepHidAction *nha)
7171 struct NepHidSound *nhs;
7172 struct dtTrigger playmsg;
7173 nhs = (struct NepHidSound *) FindName(&nh->nh_Sounds, nha->nha_SoundFile);
7174 if(!nhs)
7176 nhs = nLoadSound(nh, nha->nha_SoundFile);
7178 if(!nhs)
7180 return(FALSE);
7182 if(!nhs->nhs_DTHandle)
7184 return(FALSE);
7187 SetAttrs(nhs->nhs_DTHandle,
7188 SDTA_Volume, nha->nha_SoundVolume,
7189 TAG_END);
7190 playmsg.MethodID = DTM_TRIGGER;
7191 playmsg.dtt_GInfo = NULL;
7192 playmsg.dtt_Function = STM_PLAY;
7193 playmsg.dtt_Data = NULL;
7194 DoMethodA(nhs->nhs_DTHandle, (Msg) &playmsg);
7195 return(TRUE);
7197 /* \\\ */
7199 /* /// "nFreeSound()" */
7200 void nFreeSound(struct NepHidBase *nh, struct NepHidSound *nhs)
7202 Remove(&nhs->nhs_Node);
7203 if(nhs->nhs_DTHandle)
7205 DisposeDTObject(nhs->nhs_DTHandle);
7207 FreeVec(nhs->nhs_Node.ln_Name);
7208 FreeVec(nhs);
7210 /* \\\ */
7212 /* /// "nInvertString()" */
7213 struct InputEvent *nInvertString(struct NepHidBase *nh, STRPTR str, struct KeyMap *km)
7215 struct InputEvent *prior = NULL;
7216 struct InputEvent *ne;
7217 struct InputXpression tmpIX;
7219 BOOL freeevents = FALSE;
7220 char cc;
7221 char *oldsptr;
7223 if(!str) return(NULL);
7224 if(!(*str)) return(NULL);
7227 if((ne = AllocMem(sizeof(struct InputEvent), MEMF_CLEAR)))
7229 ne->ie_NextEvent = prior;
7230 prior = ne;
7231 cc = *str++;
7232 switch(cc)
7234 case '<': /* do angles */
7235 oldsptr = str;
7236 freeevents = TRUE;
7237 while((cc = *str))
7239 if(cc == '>')
7241 *str = '\0';
7242 if(!ParseIX(oldsptr, &tmpIX))
7244 freeevents = FALSE;
7245 prior->ie_Class = tmpIX.ix_Class;
7246 prior->ie_Code = tmpIX.ix_Code;
7247 prior->ie_Qualifier = tmpIX.ix_Qualifier;
7249 *str++ = cc;
7250 break;
7252 str++;
7254 break;
7256 case '\\': /* do escape sequences */
7257 cc = *str++;
7258 switch(cc)
7260 case '"':
7261 case '\'':
7262 case '<':
7263 case '\\':
7264 break;
7265 case 'n':
7266 case 'r':
7267 cc = '\r';
7268 break;
7269 case 't':
7270 cc = '\t';
7271 break;
7272 case '0':
7273 cc = '\0';
7274 break;
7275 default:
7276 freeevents = TRUE;
7277 break;
7279 if(freeevents) break;
7280 /* note that this break is missing on purpose */
7281 default: /* normal key translation */
7282 InvertKeyMap((ULONG) cc, prior, km);
7283 break;
7285 } else {
7286 freeevents = TRUE;
7288 } while(*str && (!freeevents));
7289 if(freeevents)
7291 nFreeIEvents(nh, prior);
7292 return(NULL);
7294 return(prior);
7296 /* \\\ */
7298 /* /// "nFreeIEvents()" */
7299 void nFreeIEvents(struct NepHidBase *nh, struct InputEvent *event)
7301 struct InputEvent *next;
7302 while(event)
7304 next = event->ie_NextEvent;
7305 FreeMem(event, sizeof(struct InputEvent));
7306 event = next;
7309 /* \\\ */
7311 /* /// "nSendKeyString()" */
7312 BOOL nSendKeyString(struct NepHidBase *nh, STRPTR str)
7314 struct InputEvent *events = nInvertString(nh, str, NULL);
7315 struct InputEvent *eptr = events;
7316 struct InputEvent lastevent;
7317 int count = 0;
7318 int lstpos;
7319 if(!events)
7321 return(FALSE);
7323 while(eptr)
7325 count++;
7326 eptr = eptr->ie_NextEvent;
7328 while(count)
7330 eptr = events;
7331 for(lstpos = --count; lstpos; lstpos--)
7332 eptr = eptr->ie_NextEvent;
7334 nh->nh_FakeEvent = *eptr;
7335 nh->nh_FakeEvent.ie_NextEvent = NULL;
7336 nh->nh_InpIOReq->io_Data = &nh->nh_FakeEvent;
7337 nh->nh_InpIOReq->io_Length = sizeof(struct InputEvent);
7338 nh->nh_InpIOReq->io_Command = nh->nh_OS4Hack ? IND_ADDEVENT : IND_WRITEEVENT;
7339 DoIO((struct IORequest *) nh->nh_InpIOReq);
7341 nh->nh_FakeEvent.ie_Code |= IECODE_UP_PREFIX;
7342 nh->nh_InpIOReq->io_Data = &nh->nh_FakeEvent;
7343 nh->nh_InpIOReq->io_Length = sizeof(struct InputEvent);
7344 nh->nh_InpIOReq->io_Command = nh->nh_OS4Hack ? IND_ADDEVENT : IND_WRITEEVENT;
7345 DoIO((struct IORequest *) nh->nh_InpIOReq);
7347 lastevent.ie_Class = IECLASS_RAWKEY;
7348 lastevent.ie_SubClass = 0;
7349 lastevent.ie_Code = 0xFF;
7350 lastevent.ie_NextEvent = NULL;
7351 lastevent.ie_Qualifier = 0;
7352 nh->nh_InpIOReq->io_Data = &lastevent;
7353 nh->nh_InpIOReq->io_Length = sizeof(struct InputEvent);
7354 nh->nh_InpIOReq->io_Command = nh->nh_OS4Hack ? IND_ADDEVENT : IND_WRITEEVENT;
7355 DoIO((struct IORequest *) nh->nh_InpIOReq);
7356 nFreeIEvents(nh, events);
7357 return(TRUE);
7359 /* \\\ */
7361 /* /// "nEasyRequest()" */
7362 LONG nEasyRequest(struct NepHidBase *nh, STRPTR body, STRPTR gadgets, ...)
7364 LONG ret;
7366 AROS_SLOWSTACKFORMAT_PRE(gadgets);
7367 ret = nEasyRequestA(nh, body, gadgets, AROS_SLOWSTACKFORMAT_ARG(gadgets));
7368 AROS_SLOWSTACKFORMAT_POST(gadgets);
7370 return ret;
7372 /* \\\ */
7374 /* /// "nEasyRequestA()" */
7375 LONG nEasyRequestA(struct NepHidBase *nh, STRPTR body, STRPTR gadgets, RAWARG params)
7377 struct EasyStruct es;
7378 es.es_StructSize = sizeof(struct EasyStruct);
7379 es.es_Flags = 0;
7380 es.es_Title = GM_UNIQUENAME(libname);
7381 es.es_TextFormat = body;
7382 es.es_GadgetFormat = gadgets;
7383 return(EasyRequestArgs(NULL, &es, NULL, params));
7385 /* \\\ */