2 *----------------------------------------------------------------------------
3 * hid class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
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;
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
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
);
52 CloseLibrary(UtilityBase
);
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
);
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?
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
);
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
));
91 static int GM_UNIQUENAME(libExpunge
)(LIBBASETYPEPTR nh
)
93 KPRINTF(10, ("libExpunge nh: 0x%08lx\n", nh
));
95 if(nh
->nh_LowLevelBase
)
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
);
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
);
111 return(FALSE
); /* we couldn't remove the patch! */
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"));
127 ADD2INITLIB(GM_UNIQUENAME(libInit
), 0)
128 ADD2OPENLIB(GM_UNIQUENAME(libOpen
), 0)
129 ADD2CLOSELIB(GM_UNIQUENAME(libClose
), 0)
130 ADD2EXPUNGELIB(GM_UNIQUENAME(libExpunge
), 0)
134 * ***********************************************************************
135 * * Library functions *
136 * ***********************************************************************
139 /* /// "usbAttemptInterfaceBinding()" */
140 struct NepClassHid
* GM_UNIQUENAME(usbAttemptInterfaceBinding
)(struct NepHidBase
*nh
, struct PsdInterface
*pif
)
147 KPRINTF(1, ("nepHidAttemptInterfaceBinding(%08lx)\n", pif
));
148 if((ps
= OpenLibrary("poseidon.library", 4)))
150 psdGetAttrs(PGA_INTERFACE
, pif
,
152 //IFA_SubClass, &subclass,
153 //IFA_Protocol, &proto,
157 if(ifclass
== HID_CLASSCODE
)
159 return(GM_UNIQUENAME(usbForceInterfaceBinding
)(nh
, pif
));
166 /* /// "usbForceInterfaceBinding()" */
167 struct NepClassHid
* GM_UNIQUENAME(usbForceInterfaceBinding
)(struct NepHidBase
*nh
, struct PsdInterface
*pif
)
170 struct NepClassHid
*nch
;
171 struct PsdConfig
*pc
;
172 struct PsdDevice
*pd
;
177 struct Task
*tmptask
;
179 KPRINTF(1, ("nepHidForceInterfaceBinding(%08lx)\n", pif
));
182 if((ps
= OpenLibrary("poseidon.library", 4)))
184 psdGetAttrs(PGA_INTERFACE
, pif
,
186 IFA_IDString
, &ifidstr
,
188 psdGetAttrs(PGA_CONFIG
, pc
,
191 psdGetAttrs(PGA_DEVICE
, pd
,
192 DA_ProductName
, &devname
,
193 DA_IDString
, &devidstr
,
195 if((nch
= psdAllocVec(sizeof(struct NepClassHid
))))
197 nch
->nch_ClsBase
= nh
;
198 nch
->nch_CDC
= psdAllocVec(sizeof(struct ClsDevCfg
));
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
);
223 nch
->nch_ReadySigTask
= NULL
;
224 //FreeSignal(nch->nch_ReadySignal);
225 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
226 "HID the road, '%s'!",
229 AddTail(&nh
->nh_Interfaces
, &nch
->nch_Node
);
235 nch
->nch_ReadySigTask
= NULL
;
236 //FreeSignal(nch->nch_ReadySignal);
237 psdFreeVec(nch
->nch_CDC
);
246 /* /// "usbReleaseInterfaceBinding()" */
247 void GM_UNIQUENAME(usbReleaseInterfaceBinding
)(struct NepHidBase
*nh
, struct NepClassHid
*nch
)
250 struct PsdConfig
*pc
;
251 struct PsdDevice
*pd
;
254 KPRINTF(1, ("nepHidReleaseInterfaceBinding(%08lx)\n", nch
));
255 if((ps
= OpenLibrary("poseidon.library", 4)))
258 nch
->nch_ReadySignal
= SIGB_SINGLE
;
259 nch
->nch_ReadySigTask
= FindTask(NULL
);
262 Signal(nch
->nch_GUITask
, SIGBREAKF_CTRL_C
);
265 while(nch
->nch_GUITask
)
267 Wait(1L<<nch
->nch_ReadySignal
);
271 if(nch
->nch_HCGUITask
)
273 Signal(nch
->nch_HCGUITask
, SIGBREAKF_CTRL_C
);
276 while(nch
->nch_HCGUITask
)
278 Wait(1L<<nch
->nch_ReadySignal
);
284 Signal(nch
->nch_Task
, SIGBREAKF_CTRL_C
);
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'!",
299 Remove(&nch
->nch_Node
);
301 psdFreeVec(nch
->nch_CDC
);
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
)
320 KPRINTF(1, ("nepHidGetAttrsA(%ld, %08lx, %08lx)\n", type
, usbstruct
, tags
));
324 if((ti
= FindTagItem(UCCA_Priority
, tags
)))
326 *((SIPTR
*) ti
->ti_Data
) = 0;
329 if((ti
= FindTagItem(UCCA_Description
, tags
)))
331 *((STRPTR
*) ti
->ti_Data
) = "Generic support for human interface devices";
334 if((ti
= FindTagItem(UCCA_HasClassCfgGUI
, tags
)))
336 *((IPTR
*) ti
->ti_Data
) = TRUE
;
339 if((ti
= FindTagItem(UCCA_HasBindingCfgGUI
, tags
)))
341 *((IPTR
*) ti
->ti_Data
) = TRUE
;
344 if((ti
= FindTagItem(UCCA_AfterDOSRestart
, tags
)))
346 *((IPTR
*) ti
->ti_Data
) = FALSE
;
349 if((ti
= FindTagItem(UCCA_UsingDefaultCfg
, tags
)))
351 *((IPTR
*) ti
->ti_Data
) = nh
->nh_DummyNCH
.nch_UsingDefaultCfg
;
354 if((ti
= FindTagItem(UCCA_SupportsSuspend
, tags
)))
356 *((IPTR
*) ti
->ti_Data
) = TRUE
;
362 if((ti
= FindTagItem(UCBA_UsingDefaultCfg
, tags
)))
364 *((IPTR
*) ti
->ti_Data
) = ((struct NepClassHid
*) usbstruct
)->nch_UsingDefaultCfg
;
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
)
387 /* /// "usbDoMethodA()" */
388 AROS_LH2(IPTR
, usbDoMethodA
,
389 AROS_LHA(ULONG
, methodid
, D0
),
390 AROS_LHA(IPTR
*, methoddata
, A1
),
391 LIBBASETYPEPTR
, nh
, 7, hid
)
395 struct NepClassHid
*nch
;
397 KPRINTF(10, ("Do Method %ld\n", 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]);
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
:
420 case UCM_ConfigChangedEvent
:
421 GM_UNIQUENAME(nLoadClassConfig
)(nh
);
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
;
433 case UCM_AttemptSuspendDevice
:
434 nch
= (struct NepClassHid
*) methoddata
[0];
435 nch
->nch_Running
= FALSE
;
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
));
452 /* /// "nInstallLLPatch()" */
453 void nInstallLLPatch(struct NepHidBase
*nh
)
455 if(!nh
->nh_LowLevelBase
)
457 if((nh
->nh_LowLevelBase
= OpenLibrary("lowlevel.library", 40)))
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));
468 /* /// "nLoadClassConfig()" */
469 BOOL
GM_UNIQUENAME(nLoadClassConfig
)(struct NepHidBase
*nh
)
471 struct NepClassHid
*nch
= &nh
->nh_DummyNCH
;
473 struct KeymapCfg
*kmc
;
474 struct ClsDevCfg
*cdc
;
475 struct PsdIFFContext
*pic
;
477 KPRINTF(10, ("Loading Class Config...\n"));
482 if(!(ps
= OpenLibrary("poseidon.library", 4)))
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
));
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
));
515 cdc
= psdGetCfgChunk(pic
, AROS_LONG2BE(nch
->nch_CDC
->cdc_ChunkID
));
518 CopyMem(((UBYTE
*) cdc
) + 8, ((UBYTE
*) nch
->nch_CDC
) + 8, min(AROS_LONG2BE(cdc
->cdc_Length
), AROS_LONG2BE(nch
->nch_CDC
->cdc_Length
)));
520 nch
->nch_UsingDefaultCfg
= FALSE
;
522 kmc
= psdGetCfgChunk(pic
, AROS_LONG2BE(nch
->nch_KeymapCfg
.kmc_ChunkID
));
525 CopyMem(((UBYTE
*) kmc
) + 8, ((UBYTE
*) &nch
->nch_KeymapCfg
) + 8, min(AROS_LONG2BE(kmc
->kmc_Length
), AROS_LONG2BE(nch
->nch_KeymapCfg
.kmc_Length
)));
527 nch
->nch_UsingDefaultCfg
= FALSE
;
536 /* /// "nCalcConfigCRC()" */
537 ULONG
nCalcConfigCRC(struct NepClassHid
*nch
, struct Library
*ps
, struct PsdIFFContext
*pic
)
539 ULONG
*buf
= (ULONG
*) psdWriteCfg(pic
);
543 UWORD
*ptr
= (UWORD
*) buf
;
544 ULONG len
= (AROS_LONG2BE(buf
[1]) + 8)>>1;
550 crc
= ((crc
<<1)|(crc
>>31))^(*ptr
++);
559 /* /// "nLoadBindingConfig()" */
560 BOOL
GM_UNIQUENAME(nLoadBindingConfig
)(struct NepClassHid
*nch
, BOOL gui
)
562 struct NepHidBase
*nh
= nch
->nch_ClsBase
;
564 struct ClsDevCfg
*cdc
;
565 struct KeymapCfg
*kmc
;
566 struct PsdIFFContext
*pic
;
569 KPRINTF(10, ("Loading Binding Config...\n"));
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)))
586 pic
= psdGetUsbDevCfg(GM_UNIQUENAME(libname
), nch
->nch_DevIDString
, nch
->nch_IfIDString
);
589 cdc
= psdGetCfgChunk(pic
, AROS_LONG2BE(nch
->nch_CDC
->cdc_ChunkID
));
592 CopyMem(((UBYTE
*) cdc
) + 8, ((UBYTE
*) nch
->nch_CDC
) + 8, min(AROS_LONG2BE(cdc
->cdc_Length
), AROS_LONG2BE(nch
->nch_CDC
->cdc_Length
)));
594 nch
->nch_UsingDefaultCfg
= FALSE
;
596 kmc
= psdGetCfgChunk(pic
, AROS_LONG2BE(nch
->nch_KeymapCfg
.kmc_ChunkID
));
599 CopyMem(((UBYTE
*) kmc
) + 8, ((UBYTE
*) &nch
->nch_KeymapCfg
) + 8, min(AROS_LONG2BE(kmc
->kmc_Length
), AROS_LONG2BE(nch
->nch_KeymapCfg
.kmc_Length
)));
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
;
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
);
624 /* /// "nOpenBindingCfgWindow()" */
625 LONG
GM_UNIQUENAME(nOpenBindingCfgWindow
)(struct NepHidBase
*nh
, struct NepClassHid
*nch
)
628 KPRINTF(10, ("Opening GUI...\n"));
629 if(!(ps
= OpenLibrary("poseidon.library", 4)))
634 if(!nch
->nch_GUITask
)
636 if((nch
->nch_GUITask
= psdSpawnSubTask(MOD_NAME_STRING
" GUI", GM_UNIQUENAME(nGUITask
), nch
)))
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 */
691 #define ps nch->nch_Base
693 /* /// "nHidTask()" */
694 AROS_UFH0(void, GM_UNIQUENAME(nHidTask
))
698 struct NepClassHid
*nch
;
712 struct NepHidReport
*nhr
;
713 struct NepHidItem
**nhiptr
;
714 struct NepHidItem
*nhi
;
716 if((nch
= GM_UNIQUENAME(nAllocHid())))
719 if(nch
->nch_ReadySigTask
)
721 Signal(nch
->nch_ReadySigTask
, 1L<<nch
->nch_ReadySignal
);
724 sigmask
= (1L<<nch
->nch_TaskMsgPort
->mp_SigBit
)|SIGBREAKF_CTRL_C
;
726 pp
= nch
->nch_EP0Pipe
;
727 /* initial output states */
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
)
738 psdPipeSetup(pp
, URTF_IN
|URTF_CLASS
|URTF_INTERFACE
,
739 UHR_GET_REPORT
, (ULONG
) nhr
->nhr_ReportID
|0x0200, nch
->nch_IfNum
);
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
);
751 count
= nhr
->nhr_OutItemCount
;
752 nhiptr
= nhr
->nhr_OutItemMap
;
758 nProcessItem(nch
, nhi
, bufreal
);
761 KPRINTF(10, ("Huh? report %ld, nhiptr == NULL!\n", nhr
->nhr_ReportID
));
765 nhr
= (struct NepHidReport
*) nhr
->nhr_Node
.ln_Succ
;
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
;
782 if(!nch
->nch_HCGUITask
)
784 psdSpawnSubTask(MOD_NAME_STRING
" Control GUI", GM_UNIQUENAME(nHIDCtrlGUITask
), nch
);
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);
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
);
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
)
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
;
841 if((nhi
= *nhiptr
++))
843 nProcessItem(nch
, nhi
, bufreal
);
845 KPRINTF(10, ("Huh? Hole in Item Lookup Map!\n"));
849 KPRINTF(10, ("Huh? report %ld, count %ld or nhiptr == NULL!\n", reportid
, count
));
852 KPRINTF(10, ("Illegal report ID %ld received!\n", reportid
));
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
;
866 psdSendPipe(nch
->nch_EPInPipe
, buf
, nch
->nch_MaxInSize
);
867 nch
->nch_IOStarted
= TRUE
;
873 psdDelayMS(nch
->nch_EPInInterval
);
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
);
893 if(nch
->nch_WacomMode
)
895 wacomgood
= nParseWacom(nch
, buf
, buflen
);
899 // if the parser failed, use standard methods
900 if(nch
->nch_UsesReportID
)
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
;
919 if((nhi
= *nhiptr
++))
921 nProcessItem(nch
, nhi
, bufreal
);
923 KPRINTF(10, ("Huh? Hole in Item Lookup Map!\n"));
927 KPRINTF(10, ("Huh? count or nhiptr == NULL!\n"));
931 KPRINTF(10, ("Illegal report ID %ld received!\n", reportid
));
935 //dumpmem(buf, buflen);
937 KPRINTF(10, ("Int Pipe failed %ld\n", ioerr
));
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
);
950 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
),
951 "That's it, that device pissed me off long enough!");
952 sigs
|= SIGBREAKF_CTRL_C
;
958 psdGetAttrs(PGA_ENDPOINT
, nch
->nch_EPIn
,
959 EA_EndpointNum
, &epnum
,
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);
972 if(nch
->nch_TrackEvents
|| nch
->nch_TrackKeyEvents
|| (nch
->nch_ReportValues
&& nch
->nch_ItemChanged
))
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...");
989 nch
->nch_ReadySignal
= SIGB_SINGLE
;
990 nch
->nch_ReadySigTask
= FindTask(NULL
);
993 Signal(nch
->nch_GUITask
, SIGBREAKF_CTRL_C
);
996 while(nch
->nch_GUITask
)
998 Wait(1L<<nch
->nch_ReadySignal
);
1001 if(nch
->nch_HCGUITask
)
1003 Signal(nch
->nch_HCGUITask
, SIGBREAKF_CTRL_C
);
1006 while(nch
->nch_HCGUITask
)
1008 Wait(1L<<nch
->nch_ReadySignal
);
1010 //FreeSignal(nch->nch_ReadySignal);
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
;
1023 if(nReadReports(nch
))
1025 nAddExtraReport(nch
);
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
);
1057 /* /// "nAllocHid()" */
1058 struct NepClassHid
* GM_UNIQUENAME(nAllocHid
)(void)
1060 struct Task
*thistask
;
1061 struct NepClassHid
*nch
;
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)))
1078 if(!(nch
->nch_HIntBase
= OpenLibrary("intuition.library", 39)))
1080 /* we don't mind anymore */
1081 //Alert(AG_OpenLib|AO_Intuition);
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
,
1091 psdGetAttrs(PGA_CONFIG
, nch
->nch_Config
,
1092 CA_Device
, &nch
->nch_Device
,
1095 nch
->nch_EPIn
= psdFindEndpoint(nch
->nch_Interface
, NULL
,
1097 EA_TransferType
, USEAF_INTERRUPT
,
1099 nch
->nch_EPOut
= psdFindEndpoint(nch
->nch_Interface
, NULL
,
1101 EA_TransferType
, USEAF_INTERRUPT
,
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,
1127 psdGetAttrs(PGA_ENDPOINT
, nch
->nch_EPIn
,
1128 EA_Interval
, &nch
->nch_EPInInterval
,
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
,
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);
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);
1161 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1162 "SET_PROTOCOL=REPORT failed: %s (%ld)!",
1163 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
1169 psdGetAttrs(PGA_ENDPOINT
, nch
->nch_EPIn
,
1170 EA_EndpointNum
, &epnum
,
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);
1177 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
1178 "CLEAR_ENDPOINT_HALT %ld failed: %s (%ld)",
1179 epnum
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
1183 nQuirkPS3Controller(nch
);
1185 if(nReadReports(nch
))
1188 nAddExtraReport(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!");
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!");
1204 if((nch
->nch_EPInBuf
= psdAllocVec(nch
->nch_MaxInSize
)))
1206 if((nch
->nch_EPOutBuf
= psdAllocVec(nch
->nch_MaxReportSize
)))
1208 nch
->nch_Task
= thistask
;
1211 psdFreeVec(nch
->nch_EPInBuf
);
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
);
1229 CloseLibrary(nch
->nch_HIntBase
);
1230 CloseLibrary(nch
->nch_Base
);
1232 nch
->nch_Task
= NULL
;
1233 if(nch
->nch_ReadySigTask
)
1235 Signal(nch
->nch_ReadySigTask
, 1L<<nch
->nch_ReadySignal
);
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
);
1264 nch
->nch_Task
= NULL
;
1265 if(nch
->nch_ReadySigTask
)
1267 Signal(nch
->nch_ReadySigTask
, 1L<<nch
->nch_ReadySignal
);
1272 /* /// "nFreeItem()" */
1273 void nFreeItem(struct NepClassHid
*nch
, struct NepHidItem
*nhi
)
1275 struct NepHidAction
*nha
;
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
);
1294 nha
= (struct NepHidAction
*) lst
->lh_Head
;
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
);
1306 nha
= (struct NepHidAction
*) nhi
->nhi_ActionList
.lh_Head
;
1308 psdFreeVec(nhi
->nhi_Buffer
);
1313 /* /// "nCleanCollection()" */
1314 void nCleanCollection(struct NepClassHid
*nch
, struct NepHidCollection
*nhc
)
1316 struct NepHidItem
*nhi
;
1317 struct NepHidAction
*nha
;
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
);
1337 nha
= (struct NepHidAction
*) lst
->lh_Head
;
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
);
1348 nha
= (struct NepHidAction
*) nhi
->nhi_ActionList
.lh_Head
;
1350 nhi
= (struct NepHidItem
*) nhi
->nhi_Node
.ln_Succ
;
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
);
1374 nhc
= (struct NepHidCollection
*) nhr
->nhr_Collections
.lh_Head
;
1376 psdFreeVec(nhr
->nhr_InItemMap
);
1377 psdFreeVec(nhr
->nhr_ReportBuf
);
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
);
1391 if(!nLoadItem(nch
, rppic
, &nhi
->nhi_ActionList
, 0xf001))
1393 nDetectDefaultAction(nch
, nhi
, &nhi
->nhi_ActionList
, nhc
, nhi
->nhi_Usage
);
1396 nDetectDefaultAction(nch
, nhi
, &nhi
->nhi_ActionList
, nhc
, nhi
->nhi_Usage
);
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
;
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
);
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
;
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
}
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
;
1525 KPRINTF(1, ("Wacom parsing %ld (%ld)...\n", nch
->nch_WacomMode
, len
));
1526 switch(nch
->nch_WacomMode
)
1528 case WACOM_PENPARTNER
:
1530 // 80 40 20 10 08 04 02 01
1531 // 1: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1532 // 2: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1533 // 3: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
1534 // 4: yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
1536 // 6: [signed pressure]
1537 if((buf
[0] != 2) || (len
< 7))
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;
1551 wr
.wr_Buttons
|= 0x02;
1556 case WACOM_GRAPHIRE
:
1557 case WACOM_GRAPHIRE4
:
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 ]
1571 if((buf
[0] != 2) || (len
< 8))
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;
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;
1592 wr
.wr_Wheel
= -wr
.wr_Wheel
;
1595 wr
.wr_Wheel
= ((BYTE
*) buf
)[6];
1596 KPRINTF(1, ("Wheel %ld\n", wr
.wr_Wheel
));
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);
1606 wr
.wr_InProximity
= 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 ]
1632 wr
.wr_PadButtons
= (buf
[5] & 0x0f)|(buf
[6]<<4);
1636 if((buf
[0] != 2) && (buf
[0] != 5) && (buf
[0] != 6))
1640 // needs some improvement on the various tools
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];
1650 wr
.wr_Buttons
= (buf
[8] & 0x07) | ((buf
[8] & 0x30)>>1);
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
;
1672 wr
.wr_InProximity
= 0;
1679 if((buf
[0] != 2) || (len
< 8))
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;
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;
1702 if((buf
[0] != 2) || (len
< 8))
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);
1712 wr
.wr_Buttons
|= 0x01;
1716 wr
.wr_Buttons
|= 0x02;
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
;
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
;
1754 psdGetAttrs(PGA_DEVICE
, nch
->nch_Device
,
1755 DA_VendorID
, &vendid
,
1756 DA_ProductID
, &prodid
,
1758 if(vendid
!= 0x056a)
1763 for(wc
= WacomCapsTable
; wc
->wc_ProdID
!= prodid
; wc
++)
1765 if(wc
->wc_ProdID
== 0xffff)
1772 case WACOM_PENPARTNER
:
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
;
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
);
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
;
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
;
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
);
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);
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);
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);
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);
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;
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);
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);
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);
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
;
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
);
1956 /* /// "nQuirkPS3Controller()" */
1957 void nQuirkPS3Controller(struct NepClassHid
*nch
)
1965 psdGetAttrs(PGA_DEVICE
, nch
->nch_Device
,
1966 DA_VendorID
, &vendid
,
1967 DA_ProductID
, &prodid
,
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
));
1974 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Unable to add PS3 controller support!");
1976 psdAddErrorMsg(RETURN_OK
, GM_UNIQUENAME(libname
), "Adding PS3 controller support.");
1982 /* /// "nReadReports()" */
1983 BOOL
nReadReports(struct NepClassHid
*nch
)
1985 struct NepHidReport
*nhr
;
1986 struct NepHidCollection
*nhc
;
1987 struct NepHidItem
*nhi
;
1988 struct PsdDescriptor
*pdd
;
1999 struct List
*alistptr
;
2002 pdd
= psdFindDescriptor(nch
->nch_Device
, NULL
,
2003 DDA_DescriptorType
, UDT_HID
,
2004 DDA_Interface
, nch
->nch_Interface
,
2009 psdGetAttrs(PGA_DESCRIPTOR
, pdd
,
2010 DDA_DescriptorData
, &descdata
,
2013 actlen
= descdata
[0];
2014 memcpy(buf
, descdata
, (size_t) actlen
);
2016 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
2017 "Using HID Descriptor from initial configuration run.");
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
)
2028 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2029 "GET_HID_DESCRIPTOR(%ld) failed: %s (%ld)!",
2030 256, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2032 ioerr
= psdDoPipe(nch
->nch_EP0Pipe
, buf
, 256);
2033 if(ioerr
== UHIOERR_RUNTPACKET
)
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);
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
);
2052 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Burstroem retry successful ;)");
2055 actlen
= psdGetPipeActual(nch
->nch_EP0Pipe
);
2057 if((!ioerr
) || (ioerr
== UHIOERR_OVERFLOW
))
2061 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2062 "bLength field (%ld) probably wrong, fixing to %ld!",
2068 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2069 "Read less than 6 bytes (%ld read) for HID Descriptor!",
2072 if((nch
->nch_HidDesc
= psdAllocVec((ULONG
) buf
[0])))
2074 /*ioerr = psdDoPipe(nch->nch_EP0Pipe, nch->nch_HidDesc, (ULONG) buf[0]);
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);
2081 ioerr = psdDoPipe(nch->nch_EP0Pipe, nch->nch_HidDesc, (ULONG) buf[0]);
2084 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname), "Burstroem retry successful ;)");
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
,
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
);
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!",
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
);
2150 //dumpmem(nhr->nhr_ReportBuf, nhr->nhr_ReportLength);
2151 thisres
= nParseReport(nch
, nhr
);
2152 //nDebugReport(nch, nhr);
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
);
2163 nFreeReport(nch
, nhr
);
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);
2175 KPRINTF(1, ("No Hid Descriptor memory!\n"));
2178 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
2179 "GET_HID_DESCRIPTOR(%ld) failed: %s (%ld)!",
2180 256, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
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
;
2251 KPRINTF(10, ("Out of memory for Report Map!\n"));
2258 struct NepHidItem
**nhiptr
;
2259 struct NepHidItem
**nhiinptr
;
2260 struct NepHidItem
**nhioutptr
;
2261 struct NepHidItem
**nhifeatptr
;
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
++;
2285 case REPORT_MAIN_OUTPUT
:
2286 KPRINTF(1, (" Output Item %lx:\n", nhi
->nhi_Usage
));
2287 nhr
->nhr_OutItemCount
++;
2290 case REPORT_MAIN_FEATURE
:
2291 KPRINTF(1, (" Feature Item %lx:\n", nhi
->nhi_Usage
));
2292 nhr
->nhr_FeatItemCount
++;
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
++);
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,
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",
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
:
2345 nch
->nch_HasInItems
= TRUE
;
2348 case REPORT_MAIN_OUTPUT
:
2352 case REPORT_MAIN_FEATURE
:
2353 *nhifeatptr
++ = nhi
;
2356 nhi
= (struct NepHidItem
*) nhi
->nhi_Node
.ln_Succ
;
2358 nhc
= (struct NepHidCollection
*) nhc
->nhc_Node
.ln_Succ
;
2363 nhr
= (struct NepHidReport
*) nhr
->nhr_Node
.ln_Succ
;
2366 nLoadActionConfig(nch
);
2372 /* /// "nLoadActionConfig()" */
2373 void nLoadActionConfig(struct NepClassHid
*nch
)
2375 struct NepHidReport
*nhr
;
2376 struct NepHidCollection
*nhc
;
2377 struct NepHidItem
*nhi
;
2380 struct List
*alistptr
;
2382 struct PsdIFFContext
*pic
;
2383 struct PsdIFFContext
*rppic
;
2385 pic
= psdGetUsbDevCfg(GM_UNIQUENAME(libname
), nch
->nch_DevIDString
, nch
->nch_IfIDString
);
2388 nch
->nch_LastCfgCRC
= nCalcConfigCRC(nch
, nch
->nch_Base
, pic
);
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
));
2400 rppic
= psdFindCfgForm(pic
, MAKE_ID('R','P','T','0')+nhr
->nhr_ReportID
);
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
;
2415 if(!(nLoadItem(nch
, rppic
, alistptr
, nhr
->nhr_ItemIDBase
)))
2417 nDetectDefaultAction(nch
, nhi
, alistptr
, nhc
, *usageptr
);
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")));
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")));
2435 if(!(nLoadItem(nch
, rppic
, alistptr
, nhr
->nhr_ItemIDBase
)))
2437 nDetectDefaultAction(nch
, nhi
, alistptr
, nhc
, *usageptr
);
2440 nDetectDefaultAction(nch
, nhi
, alistptr
, nhc
, *usageptr
);
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
;
2455 /* /// "nDebugMem()" */
2456 void nDebugMem(struct NepClassHid
*nch
, UBYTE
*rptr
, ULONG rptlen
)
2486 } while(cnt
&& rptlen
);
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]);
2497 /* /// "nDebugReport()" */
2498 void nDebugReport(struct NepClassHid
*nch
, struct NepHidReport
*nhr
)
2504 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Can't debug HID Report: nhr=NULL!\n");
2507 rptr
= nhr
->nhr_ReportBuf
;
2508 rptlen
= nhr
->nhr_ReportLength
;
2511 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Can't debug HID Report: ReportBuf=NULL!\n");
2515 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
2516 "HID Report %02lx Debug (%ld bytes):", nhr
->nhr_ReportID
, rptlen
);
2517 nDebugMem(nch
, rptr
, rptlen
);
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
;
2534 ULONG usageid
, designid
, stringid
;
2535 ULONG usagemin
, usagemax
;
2536 ULONG designmin
, designmax
;
2537 ULONG stringmin
, stringmax
;
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? */
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
);
2583 case REPORT_ISIZE_0
:
2588 case REPORT_ISIZE_1
:
2590 data
= *((BYTE
*) rptr
);
2594 case REPORT_ISIZE_2
:
2596 udata
= data
= *rptr
++;
2597 data
|= (*((BYTE
*) rptr
))<<8;
2598 udata
|= (*rptr
++)<<8;
2601 case REPORT_ISIZE_4
:
2604 data
|= (*rptr
++)<<8;
2605 data
|= (*rptr
++)<<16;
2606 data
|= (*rptr
++)<<24;
2613 case REPORT_ITYPE_MAIN
:
2614 //KPRINTF(1, ("Main "));
2615 if(reportid
!= nch
->nch_HidGlobal
.nhg_ReportID
)
2617 struct NepHidReport
*oldnhr
= nhr
;
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
)
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
);
2638 KPRINTF(1, ("Out of memory creating new report.\n"));
2643 KPRINTF(1, ("Switched back to report ID %ld\n", nch
->nch_HidGlobal
.nhg_ReportID
));
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"));
2659 KPRINTF(1, ("Cloning %08lx (%s)\n", tmpnhc
, tmpnhc
->nhc_Name
));
2660 if((newnhc
= psdAllocVec(sizeof(struct NepHidCollection
))))
2666 NewList(&newnhc
->nhc_Items
);
2669 childnhc
->nhc_Parent
= newnhc
;
2671 newnhc
->nhc_Usage
= tmpnhc
->nhc_Usage
;
2672 newnhc
->nhc_Name
= psdCopyStr(tmpnhc
->nhc_Name
);
2674 KPRINTF(10, ("Out of memory cloning nhc!\n"));
2677 AddTail(&oldnhr
->nhr_Collections
, &tmpnhc
->nhc_Node
);
2678 tmpnhc
->nhc_Report
= oldnhr
;
2680 } while((tmpnhc
= nhc
->nhc_Parent
));
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
;
2691 case REPORT_MAIN_INPUT
:
2692 bitpos
= nhr
->nhr_ReportInSize
;
2694 case REPORT_MAIN_OUTPUT
:
2695 bitpos
= nhr
->nhr_ReportOutSize
;
2697 case REPORT_MAIN_FEATURE
:
2698 bitpos
= nhr
->nhr_ReportFeatSize
;
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
;
2713 KPRINTF(1, ("%s (%lx)\n", (itag
== REPORT_MAIN_INPUT
) ? "Input" : ((itag
== REPORT_MAIN_OUTPUT
) ? "Output" : "Feature"), udata
));
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
);
2723 if(nch
->nch_HidGlobal
.nhg_LogicalMin
== HID_PARAM_UNDEF
)
2725 nch
->nch_HidGlobal
.nhg_LogicalMin
= 0;
2727 if(nch
->nch_HidGlobal
.nhg_LogicalMax
== HID_PARAM_UNDEF
)
2730 if(nch
->nch_HidGlobal
.nhg_ReportSize
< 32)
2732 nch
->nch_HidGlobal
.nhg_LogicalMax
= (1UL<<nch
->nch_HidGlobal
.nhg_ReportSize
)-1;
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)!",
2740 nch
->nch_HidGlobal
.nhg_LogicalMin
,
2741 nch
->nch_HidGlobal
.nhg_LogicalMax
);
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
)
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"));
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
);
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
);
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
);
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
,
2834 bitpos
+= nch
->nch_HidGlobal
.nhg_ReportSize
;
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
);
2870 KPRINTF(10, ("Out of memory\n"));
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
);
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
);
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
);
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
;
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
;
2948 nch
->nch_HidGlobal
.nhg_LogicalMin
= HID_PARAM_UNDEF
;
2952 nch
->nch_HidGlobal
.nhg_LogicalMax
= HID_PARAM_UNDEF
;
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
);
2975 nhc
->nhc_Usage
= nhc
->nhc_Parent
->nhc_Usage
;
2976 nhc
->nhc_Name
= psdCopyStr(nhc
->nhc_Parent
->nhc_Name
);
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
));
2988 node
= nch
->nch_HidUsages
.lh_Head
;
2993 case REPORT_MAIN_ENDCOLL
:
2994 KPRINTF(1, ("EndCollection(%lx)\n", udata
));
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
);
3007 AddTail(&nhr
->nhr_Collections
, &nhc
->nhc_Node
);
3008 nhc
->nhc_Report
= nhr
;
3009 nhc
= nhc
->nhc_Parent
;
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
);
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
));
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
));
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
));
3047 node
= nch
->nch_HidStrings
.lh_Head
;
3052 case REPORT_MAIN_INPUT
:
3053 nhr
->nhr_ReportInSize
= bitpos
;
3055 case REPORT_MAIN_OUTPUT
:
3056 nhr
->nhr_ReportOutSize
= bitpos
;
3058 case REPORT_MAIN_FEATURE
:
3059 nhr
->nhr_ReportFeatSize
= bitpos
;
3065 case REPORT_ITYPE_GLOBAL
:
3066 //KPRINTF(1, ("Global "));
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
;
3074 case REPORT_GLOB_LOGMIN
:
3075 KPRINTF(1, ("LogMin(%ld)\n", data
));
3076 nch
->nch_HidGlobal
.nhg_LogicalMin
= data
;
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
));
3088 case REPORT_GLOB_PHYMIN
:
3089 KPRINTF(1, ("PhyMin(%ld)\n", data
));
3090 nch
->nch_HidGlobal
.nhg_PhysicalMin
= data
;
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
));
3098 case REPORT_GLOB_UNITEXP
:
3099 KPRINTF(1, ("UnitExp(%ld)\n", data
));
3100 nch
->nch_HidGlobal
.nhg_UnitExp
= data
;
3103 case REPORT_GLOB_UNIT
:
3104 KPRINTF(1, ("Unit(%ld)\n", data
));
3105 nch
->nch_HidGlobal
.nhg_Unit
= data
;
3108 case REPORT_GLOB_RPSIZE
:
3109 KPRINTF(1, ("ReportSize(%ld)\n", udata
));
3110 nch
->nch_HidGlobal
.nhg_ReportSize
= udata
;
3113 case REPORT_GLOB_RPID
:
3114 KPRINTF(1, ("ReportID(%ld)\n", udata
));
3115 nch
->nch_HidGlobal
.nhg_ReportID
= udata
;
3118 case REPORT_GLOB_RPCOUNT
:
3119 KPRINTF(1, ("ReportCount(%ld)\n", udata
));
3120 nch
->nch_HidGlobal
.nhg_ReportCount
= udata
;
3123 case REPORT_GLOB_PUSH
:
3125 struct NepHidGlobal
*nhg
= psdAllocVec(sizeof(struct NepHidGlobal
));
3126 KPRINTF(1, ("Push(%ld)\n", data
));
3129 *nhg
= nch
->nch_HidGlobal
;
3130 AddTail(&nch
->nch_HidStack
, &nhg
->nhg_Node
);
3132 KPRINTF(10, ("Out of HID stack memory!\n"));
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
);
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
);
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
);
3167 case REPORT_ITYPE_LOCAL
:
3168 //KPRINTF(1, ("Local "));
3171 case REPORT_LOCL_USAGE
:
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
))
3183 case REPORT_LOCL_USEMIN
:
3186 udata
|= nch
->nch_HidGlobal
.nhg_UsagePage
<<16;
3188 KPRINTF(1, ("UsageMin (%lx) %s\n", udata
, nNumToStr(nch
, NTS_USAGEID
, udata
, "unknown")));
3190 if(usagemax
!= HID_PARAM_UNDEF
)
3192 if(!nAddUsage(nch
, &nch
->nch_HidUsages
, usagemin
, usagemax
))
3196 usagemin
= usagemax
= HID_PARAM_UNDEF
;
3200 case REPORT_LOCL_USEMAX
:
3203 udata
|= nch
->nch_HidGlobal
.nhg_UsagePage
<<16;
3205 KPRINTF(1, ("UsageMax (%lx) %s\n", udata
, nNumToStr(nch
, NTS_USAGEID
, udata
, "unknown")));
3207 if(usagemin
!= HID_PARAM_UNDEF
)
3209 if(!nAddUsage(nch
, &nch
->nch_HidUsages
, usagemin
, usagemax
))
3213 usagemin
= usagemax
= HID_PARAM_UNDEF
;
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
))
3225 case REPORT_LOCL_DESMIN
:
3226 KPRINTF(1, ("DesignMin (%lx) %s\n", udata
, nNumToStr(nch
, NTS_USAGEID
, udata
, "unknown")));
3228 if(designmax
!= HID_PARAM_UNDEF
)
3230 if(!nAddUsage(nch
, &nch
->nch_HidDesigns
, designmin
, designmax
))
3234 designmin
= designmax
= HID_PARAM_UNDEF
;
3238 case REPORT_LOCL_DESMAX
:
3239 KPRINTF(1, ("DesignMax (%lx) %s\n", udata
, nNumToStr(nch
, NTS_USAGEID
, udata
, "unknown")));
3241 if(designmax
!= HID_PARAM_UNDEF
)
3243 if(!nAddUsage(nch
, &nch
->nch_HidDesigns
, designmin
, designmax
))
3247 designmin
= designmax
= HID_PARAM_UNDEF
;
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
))
3257 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3258 "HID String Index %ld", udata
);
3261 case REPORT_LOCL_STRMIN
:
3262 KPRINTF(1, ("StringMin (%lx) %s\n", udata
, nNumToStr(nch
, NTS_USAGEID
, udata
, "unknown")));
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
))
3272 stringmin
= stringmax
= HID_PARAM_UNDEF
;
3276 case REPORT_LOCL_STRMAX
:
3277 KPRINTF(1, ("StringMax (%lx) %s\n", udata
, nNumToStr(nch
, NTS_USAGEID
, udata
, "unknown")));
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
))
3287 stringmin
= stringmax
= HID_PARAM_UNDEF
;
3291 case REPORT_LOCL_DELIM
:
3292 KPRINTF(1, ("Delimiter (%ld)\n", udata
));
3299 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "HID Report Delimiters not really supported!");
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
);
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
);
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
));
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
));
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
));
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
));
3357 node
= nch
->nch_HidStrings
.lh_Head
;
3359 //nDebugReport(nch, nhr);
3360 return((BOOL
) (rptr
? TRUE
: FALSE
));
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
))
3373 } while((nhc
= nhc
->nhc_Parent
));
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
;
3389 if(itype
== REPORT_MAIN_OUTPUT
)
3393 else if(itype
== REPORT_MAIN_FEATURE
)
3399 while(nhr
->nhr_Node
.ln_Succ
)
3404 if((icount
= nhr
->nhr_FeatItemCount
))
3406 nhiptr
= nhr
->nhr_FeatItemMap
;
3409 if((icount
= nhr
->nhr_OutItemCount
))
3411 nhiptr
= nhr
->nhr_OutItemMap
;
3419 if(GET_WTYPE(&nhi
->nhi_ActionList
) == id
)
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
;
3441 nhr
= (struct NepHidReport
*) nhr
->nhr_Node
.ln_Succ
;
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
;
3454 struct List
*alistptr
;
3459 if(itype
== REPORT_MAIN_OUTPUT
)
3463 else if(itype
== REPORT_MAIN_FEATURE
)
3470 while(nhr
->nhr_Node
.ln_Succ
)
3475 if((icount
= nhr
->nhr_FeatItemCount
))
3477 nhiptr
= nhr
->nhr_FeatItemMap
;
3480 if((icount
= nhr
->nhr_OutItemCount
))
3482 nhiptr
= nhr
->nhr_OutItemMap
;
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
);
3512 nhr
= (struct NepHidReport
*) nhr
->nhr_Node
.ln_Succ
;
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
3619 /* /// "nDetectDefaultAction()" */
3620 BOOL
nDetectDefaultAction(struct NepClassHid
*nch
, struct NepHidItem
*nhi
, struct List
*lst
, struct NepHidCollection
*nhc
, ULONG uid
)
3623 UWORD usageid
= uid
;
3624 struct NepHidAction
*nha
;
3625 struct WacomCaps
*wc
;
3626 const struct UsbToPs2Map
*utp
= usbtops2map
;
3630 case 0x01: /* generic desktop page */
3631 if(usageid
== 0xfff0) /* extra init */
3633 /* AipTek USB Tablets Support */
3639 psdGetAttrs(PGA_DEVICE
, nch
->nch_Device
,
3640 DA_VendorID
, &vendid
,
3641 DA_ProductID
, &prodid
,
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
);
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;
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)
3761 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3762 "Generating special Wacom USB Tablet init sequence.");
3763 command
= nFindItemUsage(nch
, 0xff000001, REPORT_MAIN_FEATURE
);
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
);
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 */
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
;
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
;
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
;
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
;
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;
3877 if(nFindCollID(nch
, nhc
, 0x010004, 0x010005)) /* Joystick, Game Pad */
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;
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
;
3906 if((usageid
== 0x30) || (usageid
== 0x35))
3908 negaxis
= HUAT_LEFT
;
3909 posaxis
= HUAT_RIGHT
;
3910 alogaxis
= HUAT_ABSX
;
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;
3962 if(nFindCollID(nch
, nhc
, 0x010008, 0x010008) && (nhi
->nhi_Flags
& RPF_MAIN_RELATIVE
)) /* Multi-axis controller */
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;
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;
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
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
;
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
;
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
;
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
;
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
;
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;
4154 case 0x07: /* keyboard page */
4157 case 0x39: /* Caps lock */
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
4257 nha
= nAllocAction(nch
, lst
, HUA_KEYMAP
|HUA_ANY
);
4260 case 0x0d: /* digitizer/tablet page */
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
;
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
;
4279 case 0x3D: /* X Tilt */
4280 if((nha
= nAllocAction(nch
, lst
, HUA_TABLET
|HUA_ALWAYS
)))
4282 nha
->nha_TabletAxis
= HUAT_XROT
;
4286 case 0x3E: /* Y Tilt */
4287 if((nha
= nAllocAction(nch
, lst
, HUA_TABLET
|HUA_ALWAYS
)))
4289 nha
->nha_TabletAxis
= HUAT_YROT
;
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;
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;
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;
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
;
4338 /* /// "nCheckForDefaultAction()" */
4339 BOOL
nCheckForDefaultAction(struct NepClassHid
*nch
, struct NepHidItem
*nhi
, struct List
*lst
, struct NepHidCollection
*nhc
, ULONG uid
)
4342 struct NepHidAction
*nha
;
4343 struct NepHidAction
*nhadef
;
4344 struct List 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
;
4360 nha
->nha_IsDefault
= TRUE
;
4362 nhadef
= (struct NepHidAction
*) nhadef
->nha_Node
.ln_Succ
;
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
);
4374 nhadef
= (struct NepHidAction
*) tmplist
.lh_Head
;
4380 /* /// "nAllocAction()" */
4381 struct NepHidAction
* nAllocAction(struct NepClassHid
*nch
, struct List
*lst
, UWORD utype
)
4383 struct NepHidAction
*nha
= psdAllocVec(sizeof(struct NepHidAction
));
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
);
4400 /* /// "nAddUsage()" */
4401 BOOL
nAddUsage(struct NepClassHid
*nch
, struct List
*list
, ULONG umin
, ULONG umax
)
4403 struct NepHidUsage
*nhu
;
4406 KPRINTF(10, ("UsageMin %lx > UsageMax %lx\n", umin
, umax
));
4409 if((nhu
= psdAllocVec(sizeof(struct NepHidUsage
))))
4411 AddTail(list
, &nhu
->nhu_Node
);
4412 nhu
->nhu_Usage
= umin
;
4413 nhu
->nhu_UsageMax
= umax
;
4416 KPRINTF(10, ("Out of memory during usage allocation.\n"));
4422 /* /// "nGetUsageName()" */
4423 STRPTR
nGetUsageName(struct NepClassHid
*nch
, ULONG uid
)
4427 uname
= nNumToStr(nch
, NTS_USAGEID
, uid
, NULL
);
4430 return(psdCopyStr(uname
));
4432 uname
= nNumToStr(nch
, NTS_USAGEPAGE
, uid
>>16, "unknown");
4433 return(psdCopyStrFmt("%s (0x%lx)", uname
, uid
));
4437 /* /// "nGenerateOutReport()" */
4438 void nGenerateOutReport(struct NepClassHid
*nch
, struct NepHidReport
*nhr
, UBYTE
*buf
)
4440 struct NepHidItem
**nhiptr
= nhr
->nhr_OutItemMap
;
4443 for(cnt
= 0; cnt
< nhr
->nhr_OutItemCount
; cnt
++)
4445 nEncodeItemBuffer(nch
, *nhiptr
++, buf
);
4450 /* /// "nGenerateFeatReport()" */
4451 void nGenerateFeatReport(struct NepClassHid
*nch
, struct NepHidReport
*nhr
, UBYTE
*buf
)
4453 struct NepHidItem
**nhiptr
= nhr
->nhr_FeatItemMap
;
4456 for(cnt
= 0; cnt
< nhr
->nhr_FeatItemCount
; cnt
++)
4458 nEncodeItemBuffer(nch
, *nhiptr
++, buf
);
4463 /* /// "nEncodeItemBuffer()" */
4464 void nEncodeItemBuffer(struct NepClassHid
*nch
, struct NepHidItem
*nhi
, UBYTE
*buf
)
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
;
4493 buf
[ioffset
>>3] &= ~(1UL<<(ioffset
& 7));
4496 buf
[ioffset
>>3] |= (1UL<<(ioffset
& 7));
4499 /* I know this routine is dead slow, but hopefully, this is only a very uncommon case */
4505 buf
[ioffset
>>3] &= ~(1UL<<(ioffset
& 7));
4508 buf
[ioffset
>>3] |= (1UL<<(ioffset
& 7));
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))
4523 buf
[count
++] = *valptr
++;
4530 buf
[ioffset
>>3] &= ~(1UL<<(ioffset
& 7));
4533 buf
[ioffset
>>3] |= (1UL<<(ioffset
& 7));
4538 /* I know this routine is dead slow, but hopefully, this is only a very uncommon case */
4547 buf
[ioffset
>>3] &= ~(1UL<<(ioffset
& 7));
4550 buf
[ioffset
>>3] |= (1UL<<(ioffset
& 7));
4561 /* /// "nParseArrayString()" */
4562 void nParseArrayString(struct NepClassHid
*nch
, struct NepHidItem
*nhi
, STRPTR str
)
4565 LONG
*valptr
= nhi
->nhi_Buffer
;
4567 BOOL issigned
= FALSE
;
4571 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Parse error: Empty array value string not allowed.");
4574 acount
= nhi
->nhi_Count
;
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
)
4593 if((ch
== '0') && (*str
== 'x'))
4600 if((ch
>= '0') && (ch
<= '9'))
4627 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Parse error: Syntax error in S0!");
4630 case 1: // decimal value
4631 if((ch
>= '0') && (ch
<= '9'))
4636 *valptr
-= ch
- '0';
4638 *valptr
+= ch
- '0';
4654 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Parse error: Syntax error in S1!");
4657 case 2: // hex value
4658 if((ch
>= '0') && (ch
<= '9'))
4661 *valptr
+= ch
- '0';
4664 else if((ch
>= 'a') && (ch
<= 'f'))
4667 *valptr
+= ch
- 'a' + 10;
4670 else if((ch
>= 'A') && (ch
<= 'F'))
4673 *valptr
+= ch
- 'A' + 10;
4683 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Parse error: Syntax error in S2!");
4686 case 3: // ascii character
4694 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Parse error: Syntax error in S3!");
4707 case 5: // waiting for termination
4719 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Parse error: Syntax error in S5!");
4727 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Parse error: Syntax error in S3!");
4740 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Parse error: Excessive elements ignored!");
4745 /* /// "nProcessItem()" */
4746 BOOL
nProcessItem(struct NepClassHid
*nch
, struct NepHidItem
*nhi
, UBYTE
*buf
)
4751 ULONG ioffset
= nhi
->nhi_Offset
;
4752 ULONG isize
= nhi
->nhi_Size
;
4753 UBYTE
*bobuf
= &buf
[ioffset
>>3];
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
);
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);
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);
4790 /* I know this routine is dead slow, but hopefully, this is only a very uncommon case */
4794 if(nhi
->nhi_IsSigned
)
4798 if((buf
[ioffset
>>3]>>(ioffset
& 7)) & 1)
4807 value
|= (buf
[ioffset
>>3]>>(ioffset
& 7)) & 1;
4810 if((value
>= nhi
->nhi_LogicalMin
) && (value
<= nhi
->nhi_LogicalMax
))
4812 ULONG currmicros
= 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
++;
4839 nhi
->nhi_ClickCount
= 1;
4842 nhi
->nhi_ClickCount
= 1;
4844 nhi
->nhi_HoldSeconds
= nhi
->nhi_LastSeconds
= currsecs
;
4845 nhi
->nhi_HoldMicros
= nhi
->nhi_LastMicros
= currmicros
;
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
;
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
;
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))
4897 if(nhi
->nhi_IsSigned
)
4901 *valptr
++ = ((BYTE
*) buf
)[count
++];
4906 *valptr
++ = buf
[count
++];
4914 *valptr
++ = (buf
[ioffset
>>3]>>(ioffset
& 7)) & 1;
4918 /* I know this routine is dead slow, but hopefully, this is only a very uncommon case */
4924 if(nhi
->nhi_IsSigned
)
4928 if((buf
[ioffset
>>3]>>(ioffset
& 7)) & 1)
4937 value
|= (buf
[ioffset
>>3]>>(ioffset
& 7)) & 1;
4944 /* Look for up events first */
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
;
4956 if(*valptr
++ == value
)
4962 /* Not found in the new array, so generate up event */
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
;
4986 } while(++acount
< nhi
->nhi_Count
);
4988 /* Look for down events */
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
;
5001 if(*valptr
++ == value
)
5007 /* Not found in the old array, so generate down event */
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
;
5036 } while(++acount
< nhi
->nhi_Count
);
5037 /* Copy new array */
5038 CopyMemQuick(nhi
->nhi_Buffer
, nhi
->nhi_OldBuffer
, sizeof(LONG
) * nhi
->nhi_Count
);
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
;
5053 LONG clipmin
, clipmax
;
5054 LONG origvalue
= value
;
5056 if(nch
->nch_DisableActions
)
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
)))
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
;
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
;
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
;
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
;
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
)
5129 switch(nha
->nha_CCVar1
)
5131 case HUAT_EITEMVALUE
:
5135 case HUAT_OITEMVALUE
:
5140 var1
= nha
->nha_CCConst1
;
5143 case HUAT_CLICKCOUNT
:
5144 var1
= nhi
->nhi_ClickCount
;
5147 case HUAT_CLICKTIME
:
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;
5160 var1
-= (nhi
->nhi_HoldMicros
- currmicros
) / 1000;
5168 case HUAT_QUALIFIERS
:
5169 var1
= nch
->nch_KeyQualifiers
;
5173 var1
= nch
->nch_KeyQualifiers
|PeekQualifier();
5176 case HUAT_RANDOMBIT
:
5177 var1
= _rand(nch
->nch_ClsBase
) & 1;
5180 case HUAT_RANDOMVAL
:
5181 var1
= _rand(nch
->nch_ClsBase
);
5189 CurrentTime(&currsecs
, &currmicros
);
5190 var1
= (currsecs
* 1000) + (currmicros
/ 1000);
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
];
5213 var1
= nch
->nch_ClsBase
->nh_GlobalVars
[nha
->nha_CCVar1
- HUAT_GLOBVARA
];
5216 switch(nha
->nha_CCVar2
)
5218 case HUAT_EITEMVALUE
:
5222 case HUAT_OITEMVALUE
:
5227 var2
= nha
->nha_CCConst2
;
5230 case HUAT_CLICKCOUNT
:
5231 var2
= nhi
->nhi_ClickCount
;
5234 case HUAT_CLICKTIME
:
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;
5247 var2
-= (nhi
->nhi_HoldMicros
- currmicros
) / 1000;
5255 case HUAT_QUALIFIERS
:
5256 var2
= nch
->nch_KeyQualifiers
;
5260 var2
= nch
->nch_KeyQualifiers
|PeekQualifier();
5263 case HUAT_RANDOMBIT
:
5264 var2
= _rand(nch
->nch_ClsBase
) & 1;
5267 case HUAT_RANDOMVAL
:
5268 var2
= _rand(nch
->nch_ClsBase
);
5276 CurrentTime(&currsecs
, &currmicros
);
5277 var2
= (currsecs
* 1000) + (currmicros
/ 1000);
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
];
5300 var2
= nch
->nch_ClsBase
->nh_GlobalVars
[nha
->nha_CCVar2
- HUAT_GLOBVARA
];
5303 switch(nha
->nha_CCCond
)
5306 cond
= (var1
== var2
);
5310 cond
= (var1
!= var2
);
5314 cond
= (var1
< var2
);
5318 cond
= (var1
<= var2
);
5322 cond
= (var1
> var2
);
5326 cond
= (var1
>= var2
);
5330 cond
= (var1
&& var2
);
5334 cond
= !(var1
&& var2
);
5338 cond
= (var1
|| var2
);
5342 cond
= (var1
&& (!var2
)) || ((!var1
) && var2
);
5346 cond
= (var1
&& (!var2
));
5350 cond
= (var1
& var2
) ? TRUE
: FALSE
;
5354 cond
= (var1
& var2
) ? FALSE
: TRUE
;
5358 cond
= (var1
| var2
) ? TRUE
: FALSE
;
5362 cond
= (var1
^ var2
) ? TRUE
: FALSE
;
5366 cond
= (var1
& (~var2
)) ? TRUE
: FALSE
;
5376 if(nha
->nha_ValEnable
)
5378 switch(nha
->nha_ValVar
)
5380 case HUAT_EITEMVALUE
:
5384 case HUAT_OITEMVALUE
:
5389 value
= nha
->nha_ValConst
;
5392 case HUAT_CLICKCOUNT
:
5393 value
= nhi
->nhi_ClickCount
;
5396 case HUAT_CLICKTIME
:
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;
5409 value
-= (nhi
->nhi_HoldMicros
- currmicros
) / 1000;
5417 case HUAT_QUALIFIERS
:
5418 value
= nch
->nch_KeyQualifiers
;
5422 value
= nch
->nch_KeyQualifiers
|PeekQualifier();
5425 case HUAT_RANDOMBIT
:
5426 value
= _rand(nch
->nch_ClsBase
) & 1;
5429 case HUAT_RANDOMVAL
:
5430 value
= _rand(nch
->nch_ClsBase
);
5438 CurrentTime(&currsecs
, &currmicros
);
5439 value
= (currsecs
* 1000) + (currmicros
/ 1000);
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
];
5462 value
= nch
->nch_ClsBase
->nh_GlobalVars
[nha
->nha_ValVar
- HUAT_GLOBVARA
];
5466 //KPRINTF(1, ("Call for action(%04lx) %lx = %ld %s\n", atype, uid, value, downevent ? "down" : "up"));
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
;
5486 am
->am_Action
= nha
;
5487 PutMsg(nch
->nch_ClsBase
->nh_DTaskMsgPort
, &am
->am_Msg
);
5494 nSendRawKey(nch
, nha
->nha_RawKey
);
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
);
5512 switch(nha
->nha_MouseAxis
)
5515 nch
->nch_NewMouseRel
= TRUE
;
5516 nch
->nch_MouseDeltaX
+= value
;
5520 nch
->nch_NewMouseRel
= TRUE
;
5521 nch
->nch_MouseDeltaY
+= value
;
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;
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;
5545 qualmask
= 1<<nha
->nha_Qualifier
;
5546 switch(nha
->nha_QualMode
)
5549 nch
->nch_KeyQualifiers
|= qualmask
;
5553 nch
->nch_KeyQualifiers
&= ~qualmask
;
5557 nch
->nch_KeyQualifiers
^= qualmask
;
5561 nch
->nch_KeyQualifiers
&= ~qualmask
;
5564 nch
->nch_KeyQualifiers
|= qualmask
;
5572 UWORD iecode
= IECODE_NOBUTTON
;
5574 BOOL newmouse
= FALSE
;
5576 switch(nha
->nha_ButtonNo
)
5579 iequal
= IEQUALIFIER_LEFTBUTTON
;
5580 iecode
= IECODE_LBUTTON
;
5584 iequal
= IEQUALIFIER_RBUTTON
;
5585 iecode
= IECODE_RBUTTON
;
5589 iequal
= IEQUALIFIER_MIDBUTTON
;
5590 iecode
= IECODE_MBUTTON
;
5594 iecode
= RAWKEY_NM_BUTTON_FOURTH
;
5599 switch(nha
->nha_ButtonMode
)
5602 if((!newmouse
) && (nch
->nch_KeyQualifiers
& iequal
))
5605 iecode
= IECODE_NOBUTTON
;
5607 nch
->nch_KeyQualifiers
|= iequal
;
5608 nch
->nch_MouseButtons
|= 1<<(nha
->nha_ButtonNo
-1);
5613 if(newmouse
|| (nch
->nch_KeyQualifiers
& iequal
))
5615 nch
->nch_KeyQualifiers
&= ~iequal
;
5616 nch
->nch_MouseButtons
&= ~(1<<(nha
->nha_ButtonNo
-1));
5618 iecode
|= IECODE_UP_PREFIX
;
5621 iecode
= IECODE_NOBUTTON
;
5628 if(nch
->nch_MouseButtons
& (1<<(nha
->nha_ButtonNo
-1)))
5630 nch
->nch_MouseButtons
&= ~(1<<(nha
->nha_ButtonNo
-1));
5631 iecode
|= IECODE_UP_PREFIX
;
5633 nch
->nch_MouseButtons
|= 1<<(nha
->nha_ButtonNo
-1);
5636 if(nch
->nch_KeyQualifiers
& iequal
)
5638 nch
->nch_KeyQualifiers
&= ~iequal
;
5639 nch
->nch_MouseButtons
&= ~(1<<(nha
->nha_ButtonNo
-1));
5641 iecode
|= IECODE_UP_PREFIX
;
5643 nch
->nch_KeyQualifiers
|= iequal
;
5644 nch
->nch_MouseButtons
|= 1<<(nha
->nha_ButtonNo
-1);
5652 if((!newmouse
) && (nch
->nch_KeyQualifiers
& iequal
))
5655 iecode
= IECODE_NOBUTTON
;
5657 nch
->nch_KeyQualifiers
|= iequal
;
5658 nch
->nch_MouseButtons
|= 1<<(nha
->nha_ButtonNo
-1);
5661 if(newmouse
|| (nch
->nch_KeyQualifiers
& iequal
))
5663 nch
->nch_KeyQualifiers
&= ~iequal
;
5664 nch
->nch_MouseButtons
&= ~(1<<(nha
->nha_ButtonNo
-1));
5666 iecode
|= IECODE_UP_PREFIX
;
5669 iecode
= IECODE_NOBUTTON
;
5675 iecode
= IECODE_NOBUTTON
;
5678 if(iecode
!= IECODE_NOBUTTON
)
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
);
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;
5715 KPRINTF(1, ("Tablet!\n"));
5716 switch(nha
->nha_TabletAxis
)
5719 nch
->nch_MouseAbsZ
= value
- nhi
->nhi_RealMin
;
5720 nch
->nch_MouseRangeZ
= (nhi
->nhi_RealMax
- nhi
->nhi_RealMin
) + 1;
5724 if(nhi
->nhi_RealMax
)
5726 nch
->nch_TabPressure
= ((0x1fffffff / nhi
->nhi_RealMax
)*value
)<<2;
5727 nch
->nch_VldPressure
= TRUE
;
5732 if(nhi
->nhi_RealMax
)
5734 nch
->nch_TabRotX
= ((0x3fffffff / nhi
->nhi_RealMax
)*value
)<<2;
5735 nch
->nch_VldRotX
= TRUE
;
5740 if(nhi
->nhi_RealMax
)
5742 nch
->nch_TabRotY
= ((0x3fffffff / nhi
->nhi_RealMax
)*value
)<<2;
5743 nch
->nch_VldRotY
= TRUE
;
5748 if(nhi
->nhi_RealMax
)
5750 nch
->nch_TabRotZ
= ((0x3fffffff / nhi
->nhi_RealMax
)*value
)<<2;
5751 nch
->nch_VldRotZ
= TRUE
;
5756 nch
->nch_TabProx
= value
;
5757 nch
->nch_VldProx
= TRUE
;
5760 if(nch
->nch_MouseRangeX
&& nch
->nch_MouseRangeY
)
5762 nch
->nch_NewMouseAbs
= TRUE
;
5769 UWORD wheeldist
= 0;
5770 UWORD wheeliecode
= IECODE_NOBUTTON
;
5771 switch(nha
->nha_WheelMode
)
5776 wheeliecode
= RAWKEY_NM_WHEEL_LEFT
;
5781 wheeliecode
= RAWKEY_NM_WHEEL_RIGHT
;
5789 wheeliecode
= RAWKEY_NM_WHEEL_UP
;
5794 wheeliecode
= RAWKEY_NM_WHEEL_DOWN
;
5800 wheeliecode
= RAWKEY_NM_WHEEL_LEFT
;
5801 wheeldist
= nha
->nha_WheelDist
;
5805 wheeliecode
= RAWKEY_NM_WHEEL_RIGHT
;
5806 wheeldist
= nha
->nha_WheelDist
;
5810 wheeliecode
= RAWKEY_NM_WHEEL_UP
;
5811 wheeldist
= nha
->nha_WheelDist
;
5815 wheeliecode
= RAWKEY_NM_WHEEL_DOWN
;
5816 wheeldist
= nha
->nha_WheelDist
;
5819 if(wheeliecode
!= IECODE_NOBUTTON
)
5825 KPRINTF(1, ("Doing wheel %ld\n", wheeliecode
));
5826 nSendRawKey(nch
, wheeliecode
);
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
);
5840 nSendRawKey(nch
, wheeliecode
|IECODE_UP_PREFIX
);
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
);
5861 ULONG
*stateptr
= &nch
->nch_LLPortState
[nha
->nha_JoypadPort
];
5863 switch(nha
->nha_JoypadFeat
)
5866 mask
= JPF_JOY_LEFT
;
5870 mask
= JPF_JOY_RIGHT
;
5878 mask
= JPF_JOY_DOWN
;
5882 mask
= JPF_BUTTON_RED
;
5886 mask
= JPF_BUTTON_BLUE
;
5890 mask
= JPF_BUTTON_GREEN
;
5894 mask
= JPF_BUTTON_YELLOW
;
5898 mask
= JPF_BUTTON_FORWARD
;
5902 mask
= JPF_BUTTON_REVERSE
;
5906 mask
= JPF_BUTTON_PLAY
;
5909 case HUAT_HATSWITCH
:
5910 mask
= JP_DIRECTION_MASK
;
5911 stateptr
= &nch
->nch_LLHatswitch
[nha
->nha_JoypadPort
];
5915 /* oldval = *stateptr; */
5916 switch(nha
->nha_JoypadOp
)
5931 if(nha
->nha_JoypadFeat
== HUAT_HATSWITCH
)
5933 value
-= nhi
->nhi_RealMin
;
5934 if((value
>= 0) && (value
< 8))
5936 mask
= LLHatswitchEncoding
[value
];
5940 /*oldval = *stateptr;
5941 oldval &= ~JP_DIRECTION_MASK;
5943 *stateptr = oldval;*/
5960 ULONG
*stateptr
= &nch
->nch_LLAnalogue
[nha
->nha_JoypadPort
];
5961 if((nhi
->nhi_RealMin
!= 0) || (nhi
->nhi_RealMax
!= 255))
5964 value
-= nhi
->nhi_RealMin
;
5966 value
/= (nhi
->nhi_RealMax
- nhi
->nhi_RealMin
);
5968 switch(nha
->nha_APadFeat
)
5971 *stateptr
= (*stateptr
& ~JP_XAXIS_MASK
) | (value
& JP_XAXIS_MASK
) | JP_TYPE_ANALOGUE
;
5975 *stateptr
= (*stateptr
& ~JP_YAXIS_MASK
) | ((value
<<8) & JP_YAXIS_MASK
) | JP_TYPE_ANALOGUE
;
5984 struct NepHidItem
*nhi
;
5986 nhi
= nFindItemID(nch
, nha
->nha_OutItem
, REPORT_MAIN_OUTPUT
, &pos
);
5989 if(nhi
->nhi_Flags
& RPF_MAIN_VARIABLE
)
5991 switch(nha
->nha_OutOp
)
5994 nhi
->nhi_OldValue
= TRUE
;
5998 nhi
->nhi_OldValue
= FALSE
;
6002 nhi
->nhi_OldValue
= nhi
->nhi_OldValue
? FALSE
: TRUE
;
6006 nhi
->nhi_OldValue
= value
;
6010 nParseArrayString(nch
, nhi
, nha
->nha_OutArray
);
6012 nhi
->nhi_Collection
->nhc_Report
->nhr_OutTouched
= TRUE
;
6013 nch
->nch_OutFeatTouched
= TRUE
;
6021 struct NepHidItem
*nhi
;
6023 nhi
= nFindItemID(nch
, nha
->nha_FeatItem
, REPORT_MAIN_FEATURE
, &pos
);
6026 if(nhi
->nhi_Flags
& RPF_MAIN_VARIABLE
)
6028 switch(nha
->nha_FeatOp
)
6031 nhi
->nhi_OldValue
= TRUE
;
6035 nhi
->nhi_OldValue
= FALSE
;
6039 nhi
->nhi_OldValue
= nhi
->nhi_OldValue
? FALSE
: TRUE
;
6043 nhi
->nhi_OldValue
= value
;
6047 nParseArrayString(nch
, nhi
, nha
->nha_OutArray
);
6049 nhi
->nhi_Collection
->nhc_Report
->nhr_FeatTouched
= TRUE
;
6050 nch
->nch_OutFeatTouched
= TRUE
;
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
:
6069 case HUAT_ZIPWINDOW
:
6070 case HUAT_SCREENCYCLE
:
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
;
6086 am
->am_Action
= nha
;
6087 PutMsg(nch
->nch_ClsBase
->nh_DTaskMsgPort
, &am
->am_Msg
);
6093 case HUAT_CLOSEWINDOW
:
6094 nch
->nch_FakeEvent
.ie_Class
= IECLASS_CLOSEWINDOW
;
6095 DoIO((struct IORequest
*) nch
->nch_InpIOReq
);
6099 nch
->nch_CDC
->cdc_EnableKBReset
= TRUE
;
6100 nch
->nch_KeyQualifiers
|= IEQUALIFIER_CONTROL
|IEQUALIFIER_LCOMMAND
|IEQUALIFIER_RCOMMAND
;
6104 case HUAT_FLUSHEVENTS
:
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
];
6138 tarvarptr
= &nch
->nch_ClsBase
->nh_GlobalVars
[nha
->nha_TarVar
- HUAT_GLOBVARA
];
6145 switch(nha
->nha_TarVarOp
)
6152 *tarvarptr
+= value
;
6156 *tarvarptr
-= value
;
6160 *tarvarptr
*= value
;
6166 *tarvarptr
/= value
;
6178 *tarvarptr
= *tarvarptr
&& value
;
6182 *tarvarptr
= !(*tarvarptr
&& value
);
6186 *tarvarptr
= *tarvarptr
&& (!value
);
6190 *tarvarptr
= *tarvarptr
|| value
;
6194 *tarvarptr
= (*tarvarptr
^ value
) ? TRUE
: FALSE
;
6198 *tarvarptr
&= value
;
6202 *tarvarptr
= ~(*tarvarptr
& value
);
6206 *tarvarptr
&= ~value
;
6210 *tarvarptr
|= value
;
6214 *tarvarptr
^= value
;
6218 *tarvarptr
<<= value
;
6222 *tarvarptr
>>= value
;
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
);
6250 /* /// "nFlushEvents()" */
6251 void nFlushEvents(struct NepClassHid
*nch
)
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);
6276 psdPipeSetup(pp
, URTF_OUT
|URTF_CLASS
|URTF_INTERFACE
,
6277 UHR_SET_REPORT
, (ULONG
) nhr
->nhr_ReportID
|0x0200, nch
->nch_IfNum
);
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);
6306 psdPipeSetup(pp
, URTF_OUT
|URTF_CLASS
|URTF_INTERFACE
,
6307 UHR_SET_REPORT
, (ULONG
) nhr
->nhr_ReportID
|0x0300, nch
->nch_IfNum
);
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
);
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
;
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
;
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
);
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
))
6438 struct IOStdReq
*ioreq
;
6439 struct Interrupt tempint
;
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
;
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
);
6477 node
= listhead
->lh_Head
;
6478 while(node
->ln_Succ
)
6480 KPRINTF(20, ("Kicking %s\n", node
->ln_Name
));
6481 Cause((struct Interrupt
*) node
);
6483 node
= node
->ln_Succ
;
6485 KPRINTF(20, ("Done... awaiting doom\n"));
6488 psdDelayMS(nch
->nch_CDC
->cdc_ResetDelay
*1000);
6491 KPRINTF(20, ("Reset handler list not found!\n"));
6493 CloseDevice((struct IORequest
*) ioreq
);
6495 DeleteIORequest((struct IORequest
*) ioreq
);
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
);
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
;
6521 struct NepHidActionChunk
*nhac
;
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);
6528 itpic
= psdFindCfgForm(rppic
, AROS_LONG2BE(newform
[2]));
6533 actpic
= psdFindCfgForm(itpic
, MAKE_ID('A','C','T','N'));
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);
6546 if((tmpstr
= psdGetStringChunk(actpic
, MAKE_ID('V','A','N','S'))))
6548 strncpy(nha
->nha_VanillaString
, tmpstr
, 79);
6551 if((tmpstr
= psdGetStringChunk(actpic
, MAKE_ID('K','E','Y','S'))))
6553 strncpy(nha
->nha_KeyString
, tmpstr
, 79);
6556 if((tmpstr
= psdGetStringChunk(actpic
, MAKE_ID('E','X','E','S'))))
6558 strncpy(nha
->nha_ExeString
, tmpstr
, 79);
6561 if((tmpstr
= psdGetStringChunk(actpic
, MAKE_ID('O','A','R','R'))))
6563 strncpy(nha
->nha_OutArray
, tmpstr
, 255);
6569 actpic
= psdNextCfgForm(actpic
);
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
;
6583 struct NepHidActionChunk nhac
;
6584 BOOL isdefault
= TRUE
;
6586 if(!lst
->lh_Head
->ln_Succ
)
6590 nha
= (struct NepHidAction
*) lst
->lh_Head
;
6591 while(nha
->nha_Node
.ln_Succ
)
6593 if(!nha
->nha_IsDefault
)
6597 nha
= (struct NepHidAction
*) nha
->nha_Node
.ln_Succ
;
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);
6607 itpic
= psdFindCfgForm(rppic
, AROS_LONG2BE(newform
[2]));
6610 itpic
= psdAddCfgEntry(rppic
, newform
);
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
)
6625 newform
[2] = AROS_LONG2BE(MAKE_ID('A','C','T','N'));
6626 actpic
= psdAddCfgEntry(itpic
, newform
);
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
;
6659 /* /// "nReadJoyPort()" */
6660 AROS_LH1(ULONG
, nReadJoyPort
,
6661 AROS_LHA(ULONG
, port
, D0
),
6662 struct Library
*, LowLevelBase
, 5, hid
)
6666 struct NepHidBase
*nh
;
6667 struct NepClassHid
*nch
;
6668 ULONG result
= JP_TYPE_NOTAVAIL
;
6671 if(!(nh
= (struct NepHidBase
*) FindName(&SysBase
->LibList
, GM_UNIQUENAME(libname
))))
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
));
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
])
6695 // case 0: /* don't touch */
6698 case 1: /* overwrite with USB */
6699 result
= nch
->nch_LLPortState
[port
] | nch
->nch_LLHatswitch
[port
] | JP_TYPE_GAMECTLR
;
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
) ||
6708 result
= (result
& (JP_BUTTON_MASK
|JP_DIRECTION_MASK
)) | nch
->nch_LLPortState
[port
] | nch
->nch_LLHatswitch
[port
] | JP_TYPE_GAMECTLR
;
6712 case 3: /* disable */
6713 result
= JP_TYPE_NOTAVAIL
;
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
;
6723 nch
= (struct NepClassHid
*) nch
->nch_Node
.ln_Succ
;
6727 if((port
>= JP_ANALOGUE_PORT_MAGIC
) && (port
< (JP_ANALOGUE_PORT_MAGIC
|4)))
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
;
6742 KPRINTF(40, ("And after %08lx\n", result
));
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
)
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
))))
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
));
6776 typetag
= FindTagItem(SJA_Type
, tags
);
6779 if(typetag
->ti_Data
== SJA_TYPE_ANALOGUE
)
6781 nh
->nh_LLAnalogueOverride
[port
] = TRUE
;
6783 nh
->nh_LLAnalogueOverride
[port
] = FALSE
;
6787 typetag
= FindTagItem(SJA_Reinitialize
, tags
);
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 };
6807 if(motorofftag
->ti_Data
)
6809 motortags
[0] = &nulltag
;
6810 motortags
[1] = &nulltag
;
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
;
6834 Signal(nch
->nch_Task
, (1L<<nch
->nch_TaskMsgPort
->mp_SigBit
));
6838 nch
= (struct NepClassHid
*) nch
->nch_Node
.ln_Succ
;
6844 KPRINTF(40, ("And after %08lx\n", result
));
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!");
6870 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
6871 "Last Action Hero successfully launched!");
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);
6883 /************************************************************************/
6887 /* /// "nDispatcherTask()" */
6888 AROS_UFH0(void, GM_UNIQUENAME(nDispatcherTask
))
6892 struct NepHidBase
*nh
;
6893 struct Task
*thistask
;
6894 struct ActionMsg
*am
;
6895 struct NepHidSound
*nhs
;
6897 thistask
= FindTask(NULL
);
6900 #undef IntuitionBase
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
;
6930 if(nh
->nh_ReadySigTask
)
6932 Signal(nh
->nh_ReadySigTask
, 1L<<nh
->nh_ReadySignal
);
6936 nLastActionHero(nh
);
6939 while((am
= (struct ActionMsg
*) GetMsg(nh
->nh_DTaskMsgPort
)))
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
;
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
;
6977 if(nh
->nh_ReadySigTask
)
6979 Signal(nh
->nh_ReadySigTask
, 1L<<nh
->nh_ReadySignal
);
6981 nh
->nh_DispatcherTask
= NULL
;
6987 /* /// "nLastActionHero()" */
6988 void nLastActionHero(struct NepHidBase
*nh
)
6992 struct ActionMsg
*am
;
6993 struct NepHidAction
*nha
;
6994 struct NepClassHid
*nch
;
6995 struct Window
*actwindow
;
6996 struct Screen
*actscreen
;
6999 sigmask
= (1L<<nh
->nh_DTaskMsgPort
->mp_SigBit
)|SIGBREAKF_CTRL_C
;
7002 while((am
= (struct ActionMsg
*) GetMsg(nh
->nh_DTaskMsgPort
)))
7005 nha
= am
->am_Action
;
7006 switch(nha
->nha_Type
& HUA_ATYPEMASK
)
7010 strcpy(&buf
[1], nha
->nha_VanillaString
);
7012 if(!nSendKeyString(nh
, buf
))
7014 nEasyRequest(nh
, "'%s' is no good. Really.", "Argl!", nha
->nha_VanillaString
);
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
);
7026 nPlaySound(nh
, nha
);
7033 if((fhandle
= Open(nch
->nch_CDC
->cdc_ShellCon
, MODE_READWRITE
)))
7035 ioerr
= SystemTags(nha
->nha_ExeString
,
7038 SYS_Asynch
, nha
->nha_ShellAsync
,
7039 NP_StackSize
, nch
->nch_CDC
->cdc_ShellStack
,
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
)
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
);
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
);
7067 LockLayerInfo(&actscreen
->LayerInfo
);
7068 toplayer
= WhichLayer(&actscreen
->LayerInfo
, (LONG
) actscreen
->MouseX
, (LONG
) actscreen
->MouseY
);
7069 UnlockLayerInfo(&actscreen
->LayerInfo
);
7073 if(toplayer
->Window
&& (actwindow
!= toplayer
->Window
))
7075 ActivateWindow(toplayer
->Window
);
7082 case HUAT_DISPLAYBEEP
:
7090 case HUAT_SCREENCYCLE
:
7091 intlock
= LockIBase(0);
7092 actscreen
= nh
->nh_IntBase
->FirstScreen
;
7093 UnlockIBase(intlock
);
7096 ScreenToBack(actscreen
);
7100 case HUAT_WIN2FRONT
:
7101 intlock
= LockIBase(0);
7102 actwindow
= nh
->nh_IntBase
->ActiveWindow
;
7103 UnlockIBase(intlock
);
7106 WindowToFront(actwindow
);
7111 intlock
= LockIBase(0);
7112 actwindow
= nh
->nh_IntBase
->ActiveWindow
;
7113 UnlockIBase(intlock
);
7116 WindowToBack(actwindow
);
7120 case HUAT_ZIPWINDOW
:
7121 intlock
= LockIBase(0);
7122 actwindow
= nh
->nh_IntBase
->ActiveWindow
;
7123 UnlockIBase(intlock
);
7126 ZipWindow(actwindow
);
7136 sigs
= Wait(sigmask
);
7137 } while(!(sigs
& SIGBREAKF_CTRL_C
));
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
,
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
);
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
);
7176 nhs
= nLoadSound(nh
, nha
->nha_SoundFile
);
7182 if(!nhs
->nhs_DTHandle
)
7187 SetAttrs(nhs
->nhs_DTHandle
,
7188 SDTA_Volume
, nha
->nha_SoundVolume
,
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
);
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
);
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
;
7223 if(!str
) return(NULL
);
7224 if(!(*str
)) return(NULL
);
7227 if((ne
= AllocMem(sizeof(struct InputEvent
), MEMF_CLEAR
)))
7229 ne
->ie_NextEvent
= prior
;
7234 case '<': /* do angles */
7242 if(!ParseIX(oldsptr
, &tmpIX
))
7245 prior
->ie_Class
= tmpIX
.ix_Class
;
7246 prior
->ie_Code
= tmpIX
.ix_Code
;
7247 prior
->ie_Qualifier
= tmpIX
.ix_Qualifier
;
7256 case '\\': /* do escape sequences */
7279 if(freeevents
) break;
7280 /* note that this break is missing on purpose */
7281 default: /* normal key translation */
7282 InvertKeyMap((ULONG
) cc
, prior
, km
);
7288 } while(*str
&& (!freeevents
));
7291 nFreeIEvents(nh
, prior
);
7298 /* /// "nFreeIEvents()" */
7299 void nFreeIEvents(struct NepHidBase
*nh
, struct InputEvent
*event
)
7301 struct InputEvent
*next
;
7304 next
= event
->ie_NextEvent
;
7305 FreeMem(event
, sizeof(struct InputEvent
));
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
;
7326 eptr
= eptr
->ie_NextEvent
;
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
);
7361 /* /// "nEasyRequest()" */
7362 LONG
nEasyRequest(struct NepHidBase
*nh
, STRPTR body
, STRPTR gadgets
, ...)
7366 AROS_SLOWSTACKFORMAT_PRE(gadgets
);
7367 ret
= nEasyRequestA(nh
, body
, gadgets
, AROS_SLOWSTACKFORMAT_ARG(gadgets
));
7368 AROS_SLOWSTACKFORMAT_POST(gadgets
);
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
);
7380 es
.es_Title
= GM_UNIQUENAME(libname
);
7381 es
.es_TextFormat
= body
;
7382 es
.es_GadgetFormat
= gadgets
;
7383 return(EasyRequestArgs(NULL
, &es
, NULL
, params
));